--- a/hedgewars/CMakeLists.txt Wed Nov 20 21:37:47 2024 +0100
+++ b/hedgewars/CMakeLists.txt Fri Nov 22 17:30:45 2024 +0100
@@ -82,6 +82,7 @@
uLandGraphics.pas
uLandPainted.pas
uLandUtils.pas
+ uAI2.pas
#this is where dependency tracking becomes hard
uStore.pas
--- a/hedgewars/uAI.pas Wed Nov 20 21:37:47 2024 +0100
+++ b/hedgewars/uAI.pas Fri Nov 22 17:30:45 2024 +0100
@@ -32,7 +32,7 @@
uses uConsts, SDLh, uAIMisc, uAIAmmoTests, uAIActions,
uAmmos, uTypes,
uVariables, uCommands, uUtils, uDebug, uAILandMarks,
- uGearsUtils;
+ uGearsUtils, uAI2;
var BestActions: TActions;
CanUseAmmo: array [TAmmoType] of boolean;
@@ -635,7 +635,7 @@
var scoreShown: boolean = false;
{$ENDIF}
-procedure ProcessBot;
+procedure ProcessBot_old;
const cStopThinkTime = 40;
begin
with CurrentHedgehog^ do
@@ -677,6 +677,12 @@
StopThinking:= true
end;
+
+procedure ProcessBot;
+begin
+ if false then ProcessBot_old else uAI2.ProcessBot
+end;
+
procedure initModule;
begin
StartTicks:= 0;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hedgewars/uAI2.pas Fri Nov 22 17:30:45 2024 +0100
@@ -0,0 +1,50 @@
+unit uAI2;
+
+interface
+
+procedure ProcessBot;
+procedure initModule;
+
+implementation
+uses uLandUtils, uFloat, uVariables, uTypes;
+
+{$linklib hwengine_future}
+
+function create_ai(game_field: pointer): pointer; cdecl; external;
+procedure ai_clear_team(ai: pointer); cdecl; external;
+procedure ai_add_team_hedgehog(ai: pointer; x, y: real); cdecl; external;
+procedure ai_think(ai: pointer); cdecl; external;
+function ai_have_plan(): boolean; cdecl; external;
+procedure dispose_ai(ai: pointer); cdecl; external;
+
+var ai: pointer;
+
+procedure ProcessBot;
+var currHedgehogIndex, itHedgehog: Longword;
+begin
+ if ai = nil then
+ begin
+ ai:= create_ai(gameField)
+ end;
+
+ ai_clear_team(ai);
+
+ currHedgehogIndex:= CurrentTeam^.CurrHedgehog;
+ itHedgehog:= currHedgehogIndex;
+ repeat
+ with CurrentTeam^.Hedgehogs[itHedgehog] do
+ if (Gear <> nil) and (Effects[heFrozen] = 0) then
+ begin
+ ai_add_team_hedgehog(ai, hwFloat2float(Gear^.X), hwFloat2float(Gear^.Y))
+ end;
+ itHedgehog:= Succ(itHedgehog) mod CurrentTeam^.HedgehogsNumber;
+ until (itHedgehog = currHedgehogIndex);
+end;
+
+procedure initModule;
+begin
+ ai:= nil
+end;
+
+end.
+
--- a/hedgewars/uAIActions.pas Wed Nov 20 21:37:47 2024 +0100
+++ b/hedgewars/uAIActions.pas Fri Nov 22 17:30:45 2024 +0100
@@ -120,7 +120,17 @@
{$ENDIF}
procedure AddAction(var Actions: TActions; Action: Longword; Param: LongInt; TimeDelta: Longword; X, Y: LongInt);
+var t: Longword;
begin
+if ((Action = aia_LookLeft) or (Action = aia_LookRight)) and (Actions.Count > 0) then
+ begin
+ t:= Actions.actions[Actions.Count - 1].Action;
+ if ((t = aia_LookLeft) or (t = aia_LookRight)) then
+ begin
+ dec(Actions.Count)
+ end;
+ end;
+
if Actions.Count < MAXACTIONS then
with Actions do
begin
@@ -136,16 +146,23 @@
end
end;
-procedure CheckHang(Me: PGear);
+procedure CheckHang(Me: PGear; fromLeft: boolean);
+var newX: LongInt;
begin
-if hwRound(Me^.X) <> PrevX then
+newX:= hwRound(Me^.X);
+if newX <> PrevX then
begin
- PrevX:= hwRound(Me^.X);
+ if (newX < PrevX) = fromLeft then
+ begin
+ FreeActionsList
+ end;
+
+ PrevX:= newX;
timedelta:= 0
end else
begin
inc(timedelta);
- if timedelta > 1700 then
+ if timedelta > 900 then
begin
timedelta:= 0;
FreeActionsList
@@ -186,7 +203,7 @@
end
else
begin
- CheckHang(Me);
+ CheckHang(Me, false);
exit
end;
@@ -205,7 +222,7 @@
end
else
begin
- CheckHang(Me);
+ CheckHang(Me, true);
exit
end;
aia_LookLeft: begin
--- a/hedgewars/uAIMisc.pas Wed Nov 20 21:37:47 2024 +0100
+++ b/hedgewars/uAIMisc.pas Fri Nov 22 17:30:45 2024 +0100
@@ -915,12 +915,12 @@
begin
if (WorldEdge <> weWrap) or (not (hwAbs(meX - int2hwFloat(pX)) > int2hwFloat(cSeductionDist))) then
- dX:= _50 * aiGravity * (meX - int2hwFloat(pX)) / _25
+ dX:= aiGravity * (meX - int2hwFloat(pX)) / 2
else if (not (hwAbs(meX + int2hwFloat((RightX-LeftX) - pX)) > int2hwFloat(cSeductionDist))) then
- dX:= _50 * aiGravity * (meX + (int2hwFloat((RightX-LeftX) - pX))) / _25
+ dX:= aiGravity * (meX + (int2hwFloat((RightX-LeftX) - pX))) / 2
else
- dX:= _50 * aiGravity * (meX - (int2hwFloat((RightX-LeftX) - pX))) / _25;
- dY:= -_450 * cMaxWindSpeed * 2;
+ dX:= aiGravity * (meX - (int2hwFloat((RightX-LeftX) - pX))) / 2;
+ dY:= -_900 * cMaxWindSpeed;
pXr:= pX;
@@ -1064,7 +1064,7 @@
begin
if TestCollisionYwithGear(Gear, -1) <> 0 then
if TestCollisionXwithXYShift(Gear, _0, -2, hwSign(Gear^.dX)) = 0 then
- Gear^.Y:= Gear^.Y - int2hwFloat(2)
+ Gear^.Y:= Gear^.Y - _2
else
if TestCollisionXwithXYShift(Gear, _0, -1, hwSign(Gear^.dX)) = 0 then
Gear^.Y:= Gear^.Y - _1;
@@ -1081,12 +1081,6 @@
end;
repeat
- {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then
- begin
- LandPixelGet(hwRound(Gear^.Y), hwRound(Gear^.X)):= Gear^.Hedgehog^.Team^.Clan^.Color;
- UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true);
- end;}
-
if CheckCoordInWater(hwRound(Gear^.X), hwRound(Gear^.Y) + cHHRadius) then
exit(false);
if (Gear^.State and gstMoving) <> 0 then
@@ -1147,12 +1141,6 @@
GoInfo.JumpType:= jmpNone;
tY:= hwRound(Gear^.Y);
repeat
- {if ((hwRound(Gear^.Y) and LAND_HEIGHT_MASK) = 0) and ((hwRound(Gear^.X) and LAND_WIDTH_MASK) = 0) then
- begin
- LandPixelGet(hwRound(Gear^.Y), hwRound(Gear^.X)):= random($FFFFFFFF);//Gear^.Hedgehog^.Team^.Clan^.Color;
- UpdateLandTexture(hwRound(Gear^.X), 1, hwRound(Gear^.Y), 1, true);
- end;}
-
pX:= hwRound(Gear^.X);
pY:= hwRound(Gear^.Y);
if CheckCoordInWater(pX, pY + cHHRadius) then
--- a/hedgewars/uFloat.pas Wed Nov 20 21:37:47 2024 +0100
+++ b/hedgewars/uFloat.pas Fri Nov 22 17:30:45 2024 +0100
@@ -181,6 +181,7 @@
_300: hwFloat = (isNegative: false; QWordValue: 4294967296 * 300);
_360: hwFloat = (isNegative: false; QWordValue: 4294967296 * 360);
_450: hwFloat = (isNegative: false; QWordValue: 4294967296 * 450);
+ _900: hwFloat = (isNegative: false; QWordValue: 4294967296 * 900);
_1000: hwFloat = (isNegative: false; QWordValue: 4294967296 * 1000);
_1024: hwFloat = (isNegative: false; QWordValue: 4294967296 * 1024);
_2048: hwFloat = (isNegative: false; QWordValue: 4294967296 * 2048);
--- a/hedgewars/uLandUtils.pas Wed Nov 20 21:37:47 2024 +0100
+++ b/hedgewars/uLandUtils.pas Fri Nov 22 17:30:45 2024 +0100
@@ -19,6 +19,8 @@
procedure LandPixelSet(y, x: LongInt; value: Longword);
function LandPixelRow(row: LongInt): PLongwordArray;
+var gameField: pointer;
+
implementation
uses uUtils, uConsts, uVariables, uTypes;
@@ -42,8 +44,6 @@
function generate_maze_game_field(feature_size: Longword; seed, template_type, data_path: PChar): pointer; cdecl; external;
procedure apply_theme(game_field: pointer; data_path, theme_name: PChar); cdecl; external;
-var gameField: pointer;
-
function LandGet(y, x: LongInt): Word;
begin
LandGet:= land_get(gameField, x, y)
--- a/rust/integral-geometry/src/lib.rs Wed Nov 20 21:37:47 2024 +0100
+++ b/rust/integral-geometry/src/lib.rs Fri Nov 22 17:30:45 2024 +0100
@@ -4,7 +4,7 @@
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, RangeInclusive, Sub, SubAssign},
};
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
pub struct Point {
pub x: i32,
pub y: i32,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/lib-hwengine-future/src/ai/action.rs Fri Nov 22 17:30:45 2024 +0100
@@ -0,0 +1,31 @@
+#[derive(Clone)]
+pub enum Direction {
+ Left,
+ Right
+}
+#[derive(Clone)]
+pub enum Action {
+ Walk(Direction),
+ LongJump,
+ HighJump(usize)
+}
+
+pub struct Actions {
+ actions: Vec<Action>
+}
+
+impl Actions {
+ pub fn new() -> Self {
+ Self {
+ actions: vec![],
+ }
+ }
+
+ pub fn push(&mut self, action: Action) {
+ self.actions.push(action)
+ }
+
+ pub fn pop(&mut self) -> Option<Action> {
+ self.actions.pop()
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rust/lib-hwengine-future/src/ai/mod.rs Fri Nov 22 17:30:45 2024 +0100
@@ -0,0 +1,86 @@
+mod action;
+
+use std::collections::HashMap;
+use integral_geometry::Point;
+use crate::GameField;
+use action::*;
+
+pub struct Target {
+ point: Point,
+ health: i32,
+ radius: u32,
+ density: f32,
+
+}
+
+pub struct Hedgehog {
+ pub(crate) x: f32,
+ pub(crate) y: f32,
+}
+
+pub struct AI<'a> {
+ game_field: &'a GameField,
+ targets: Vec<Target>,
+ team: Vec<Hedgehog>,
+ planned_actions: Option<Actions>,
+}
+
+#[derive(Clone)]
+struct Waypoint {
+ x: f32,
+ y: f32,
+ ticks: usize,
+ damage: usize,
+ previous_point: Option<(usize, Action)>,
+}
+
+#[derive(Default)]
+pub struct Waypoints {
+ key_points: Vec<Waypoint>,
+ points: HashMap<Point, Waypoint>,
+}
+
+impl Waypoints {
+ fn add_keypoint(&mut self, waypoint: Waypoint) {
+ let [x, y] = [waypoint.x, waypoint.y].map(|i| i as i32);
+ let point = Point::new(x, y);
+ self.key_points.push(waypoint.clone());
+ self.points.insert(point, waypoint);
+ }
+}
+
+impl<'a> AI<'a> {
+ pub fn new(game_field: &'a GameField) -> AI<'a> {
+ Self {
+ game_field,
+ targets: vec![],
+ team: vec![],
+ planned_actions: None,
+ }
+ }
+
+ pub fn get_team_mut(&mut self) -> &mut Vec<Hedgehog> {
+ &mut self.team
+ }
+
+ pub fn walk(hedgehog: &Hedgehog) {
+ let mut stack = Vec::<usize>::new();
+ let mut waypoints = Waypoints::default();
+
+ waypoints.add_keypoint(Waypoint{
+ x: hedgehog.x,
+ y: hedgehog.y,
+ ticks: 0,
+ damage: 0,
+ previous_point: None,
+ });
+
+ while let Some(wp) = stack.pop() {
+
+ }
+ }
+
+ pub fn have_plan(&self) -> bool {
+ self.planned_actions.is_some()
+ }
+}
--- a/rust/lib-hwengine-future/src/lib.rs Wed Nov 20 21:37:47 2024 +0100
+++ b/rust/lib-hwengine-future/src/lib.rs Fri Nov 22 17:30:45 2024 +0100
@@ -1,3 +1,5 @@
+mod ai;
+
use integral_geometry::{Point, Size};
use landgen::{
@@ -10,6 +12,7 @@
use mapgen::{theme::Theme, MapGenerator};
use std::fs;
use std::{ffi::CStr, path::Path};
+use ai::*;
#[repr(C)]
pub struct GameField {
@@ -43,7 +46,7 @@
landgen_parameters: None,
});
- Box::leak(game_field)
+ Box::into_raw(game_field)
}
#[no_mangle]
@@ -83,7 +86,7 @@
landgen_parameters: Some(params),
});
- Box::leak(game_field)
+ Box::into_raw(game_field)
}
#[no_mangle]
@@ -123,7 +126,7 @@
landgen_parameters: Some(params),
});
- Box::leak(game_field)
+ Box::into_raw(game_field)
}
#[no_mangle]
@@ -166,7 +169,7 @@
landgen_parameters: Some(params),
});
- Box::leak(game_field)
+ Box::into_raw(game_field)
}
#[no_mangle]
@@ -244,3 +247,38 @@
pub extern "C" fn dispose_game_field(game_field: *mut GameField) {
unsafe { drop(Box::from_raw(game_field)) };
}
+
+#[no_mangle]
+pub extern "C" fn create_ai(game_field: &GameField) -> *mut AI {
+ Box::into_raw(Box::new(AI::new(game_field)))
+}
+
+#[no_mangle]
+pub extern "C" fn ai_clear_team(ai: &mut AI) {
+ *ai.get_team_mut() = vec![];
+}
+
+#[no_mangle]
+pub extern "C" fn ai_add_team_hedgehog(ai: &mut AI, x: f32, y: f32) {
+ ai.get_team_mut().push(Hedgehog{x, y});
+}
+
+#[no_mangle]
+pub extern "C" fn ai_think(ai: &AI) {
+
+}
+
+#[no_mangle]
+pub extern "C" fn ai_have_plan(ai: &AI) -> bool {
+ ai.have_plan()
+}
+
+#[no_mangle]
+pub extern "C" fn ai_get(ai: &AI) -> bool {
+ ai.have_plan()
+}
+
+#[no_mangle]
+pub extern "C" fn dispose_ai(ai: *mut AI) {
+ unsafe { drop(Box::from_raw(ai)) };
+}