# HG changeset patch # User unC0Rr # Date 1732293045 -3600 # Node ID 14b83df1832b87ed184e0580c20c957f7491417f # Parent fc5258d7ecb26a522fc2924d7b9d0d44b7a8c637# Parent d903f8d2395a4b89a8378745be4bcc6e4ccc1052 Merge tip diff -r d903f8d2395a -r 14b83df1832b hedgewars/CMakeLists.txt --- 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 diff -r d903f8d2395a -r 14b83df1832b hedgewars/uAI.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; diff -r d903f8d2395a -r 14b83df1832b hedgewars/uAI2.pas --- /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. + diff -r d903f8d2395a -r 14b83df1832b hedgewars/uAIActions.pas --- 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 diff -r d903f8d2395a -r 14b83df1832b hedgewars/uAIMisc.pas --- 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 diff -r d903f8d2395a -r 14b83df1832b hedgewars/uFloat.pas --- 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); diff -r d903f8d2395a -r 14b83df1832b hedgewars/uLandUtils.pas --- 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) diff -r d903f8d2395a -r 14b83df1832b rust/integral-geometry/src/lib.rs --- 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, diff -r d903f8d2395a -r 14b83df1832b rust/lib-hwengine-future/src/ai/action.rs --- /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 +} + +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 { + self.actions.pop() + } +} \ No newline at end of file diff -r d903f8d2395a -r 14b83df1832b rust/lib-hwengine-future/src/ai/mod.rs --- /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, + team: Vec, + planned_actions: Option, +} + +#[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, + points: HashMap, +} + +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 { + &mut self.team + } + + pub fn walk(hedgehog: &Hedgehog) { + let mut stack = Vec::::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() + } +} diff -r d903f8d2395a -r 14b83df1832b rust/lib-hwengine-future/src/lib.rs --- 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)) }; +}