Start on AI implementation in rust transitional_engine
authorunC0Rr
Sun, 27 Oct 2024 17:00:17 +0100
branchtransitional_engine
changeset 16039 a236360669cc
parent 16036 7b8d96fc8799
child 16040 6c5b3c576fc6
Start on AI implementation in rust
hedgewars/CMakeLists.txt
hedgewars/uAI.pas
hedgewars/uAI2.pas
hedgewars/uAIActions.pas
hedgewars/uAIMisc.pas
hedgewars/uFloat.pas
hedgewars/uLandUtils.pas
rust/integral-geometry/src/lib.rs
rust/lib-hwengine-future/src/ai/mod.rs
rust/lib-hwengine-future/src/lib.rs
--- a/hedgewars/CMakeLists.txt	Wed Sep 18 14:10:51 2024 +0200
+++ b/hedgewars/CMakeLists.txt	Sun Oct 27 17:00:17 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 Sep 18 14:10:51 2024 +0200
+++ b/hedgewars/uAI.pas	Sun Oct 27 17:00:17 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	Sun Oct 27 17:00:17 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;
+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 Sep 18 14:10:51 2024 +0200
+++ b/hedgewars/uAIActions.pas	Sun Oct 27 17:00:17 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
--- a/hedgewars/uAIMisc.pas	Wed Sep 18 14:10:51 2024 +0200
+++ b/hedgewars/uAIMisc.pas	Sun Oct 27 17:00:17 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 Sep 18 14:10:51 2024 +0200
+++ b/hedgewars/uFloat.pas	Sun Oct 27 17:00:17 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 Sep 18 14:10:51 2024 +0200
+++ b/hedgewars/uLandUtils.pas	Sun Oct 27 17:00:17 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 Sep 18 14:10:51 2024 +0200
+++ b/rust/integral-geometry/src/lib.rs	Sun Oct 27 17:00:17 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/mod.rs	Sun Oct 27 17:00:17 2024 +0100
@@ -0,0 +1,89 @@
+use std::collections::HashMap;
+use integral_geometry::Point;
+use crate::GameField;
+
+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>,
+}
+
+#[derive(Clone)]
+enum Direction {
+    Left,
+    Right
+}
+#[derive(Clone)]
+enum Action {
+    Walk(Direction),
+    LongJump,
+    HighJump(usize)
+}
+
+#[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![],
+        }
+    }
+
+    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() {
+
+        }
+    }
+}
\ No newline at end of file
--- a/rust/lib-hwengine-future/src/lib.rs	Wed Sep 18 14:10:51 2024 +0200
+++ b/rust/lib-hwengine-future/src/lib.rs	Sun Oct 27 17:00:17 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,28 @@
 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 dispose_ai(ai: *mut AI) {
+    unsafe { drop(Box::from_raw(ai)) };
+}
\ No newline at end of file