Implement passing of available ammo to rust AI transitional_engine
authorunC0Rr
Tue, 17 Dec 2024 15:44:21 +0100
branchtransitional_engine
changeset 16049 db18f1a30b0c
parent 16048 67469603872a
child 16050 624b74443b53
Implement passing of available ammo to rust AI
hedgewars/uAI2.pas
rust/lib-hwengine-future/src/ai/action.rs
rust/lib-hwengine-future/src/ai/ammo.rs
rust/lib-hwengine-future/src/ai/mod.rs
rust/lib-hwengine-future/src/lib.rs
--- a/hedgewars/uAI2.pas	Sat Dec 14 18:07:29 2024 +0100
+++ b/hedgewars/uAI2.pas	Tue Dec 17 15:44:21 2024 +0100
@@ -10,9 +10,12 @@
 
 {$linklib hwengine_future}
 
+type TAmmoCounts = array[TAmmoType] of Longword;
+     PAmmoCounts = ^TAmmoCounts;
+
 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_add_team_hedgehog(ai: pointer; x, y: real; ammo_counts: PAmmoCounts); cdecl; external;
 procedure ai_think(ai: pointer); cdecl; external;
 function ai_have_plan(): boolean; cdecl; external;
 procedure dispose_ai(ai: pointer); cdecl; external;
@@ -21,6 +24,8 @@
 
 procedure ProcessBot;
 var currHedgehogIndex, itHedgehog: Longword;
+    itAmmo: TAmmoType;
+    ammoCounts: TAmmoCounts;
 begin
     if ai = nil then
     begin
@@ -35,10 +40,15 @@
         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))
+                for itAmmo:= Low(TAmmoType) to High(TAmmoType) do
+                    ammoCounts[itAmmo]:= HHHasAmmo(CurrentTeam^.Hedgehogs[itHedgehog], itAmmo);
+
+                ai_add_team_hedgehog(ai, hwFloat2float(Gear^.X), hwFloat2float(Gear^.Y), ammoCounts)
             end;
         itHedgehog:= Succ(itHedgehog) mod CurrentTeam^.HedgehogsNumber;
     until (itHedgehog = currHedgehogIndex);
+    
+    ai_think(ai);
 end;
 
 procedure initModule;
--- a/rust/lib-hwengine-future/src/ai/action.rs	Sat Dec 14 18:07:29 2024 +0100
+++ b/rust/lib-hwengine-future/src/ai/action.rs	Tue Dec 17 15:44:21 2024 +0100
@@ -1,24 +1,22 @@
 #[derive(Clone)]
 pub enum Direction {
     Left,
-    Right
+    Right,
 }
 #[derive(Clone)]
 pub enum Action {
     Walk(Direction),
     LongJump,
-    HighJump(usize)
+    HighJump(usize),
 }
 
 pub struct Actions {
-    actions: Vec<Action>
+    actions: Vec<Action>,
 }
 
 impl Actions {
     pub fn new() -> Self {
-        Self {
-            actions: vec![],
-        }
+        Self { actions: vec![] }
     }
 
     pub fn push(&mut self, action: Action) {
@@ -28,4 +26,4 @@
     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/ammo.rs	Tue Dec 17 15:44:21 2024 +0100
@@ -0,0 +1,65 @@
+#[repr(usize)]
+pub enum AmmoType {
+    Nothing,
+    Grenade,
+    ClusterBomb,
+    Bazooka,
+    Bee,
+    Shotgun,
+    PickHammer, // 6
+    Skip,
+    Rope,
+    Mine,
+    DEagle,
+    Dynamite,
+    FirePunch,
+    Whip, // 13
+    BaseballBat,
+    Parachute,
+    AirAttack,
+    MineStrike,
+    BlowTorch, // 18
+    Girder,
+    Teleport,
+    Switch,
+    Mortar,
+    Kamikaze,
+    Cake, // 24
+    Seduction,
+    Watermelon,
+    HellishBomb,
+    Napalm,
+    Drill,
+    Ballgun, // 30
+    RCPlane,
+    LowGravity,
+    ExtraDamage,
+    Invulnerable,
+    ExtraTime, // 35
+    LaserSight,
+    Vampiric,
+    SniperRifle,
+    Jetpack,
+    Molotov,
+    Birdy,
+    PortalGun, // 42
+    Piano,
+    GasBomb,
+    SineGun,
+    Flamethrower,
+    SMine,
+    Hammer, // 48
+    Resurrector,
+    DrillStrike,
+    Snowball,
+    Tardis,
+    LandGun, // 53
+    IceGun,
+    Knife,
+    Rubber,
+    AirMine,
+    Creeper,
+    Minigun,
+    Sentry, // 60
+    Count,
+}
--- a/rust/lib-hwengine-future/src/ai/mod.rs	Sat Dec 14 18:07:29 2024 +0100
+++ b/rust/lib-hwengine-future/src/ai/mod.rs	Tue Dec 17 15:44:21 2024 +0100
@@ -1,25 +1,28 @@
 mod action;
+pub mod ammo;
 
-use std::collections::HashMap;
-use integral_geometry::Point;
 use crate::GameField;
 use action::*;
+use integral_geometry::Point;
+use std::collections::HashMap;
 
 pub struct Target {
     point: Point,
     health: i32,
     radius: u32,
     density: f32,
-
 }
 
 pub struct Hedgehog {
     pub(crate) x: f32,
     pub(crate) y: f32,
+    pub(crate) ammo: [u32; ammo::AmmoType::Count as usize],
+
 }
 
 pub struct AI<'a> {
     game_field: &'a GameField,
+    ammo: [u32; ammo::AmmoType::Count as usize],
     targets: Vec<Target>,
     team: Vec<Hedgehog>,
     planned_actions: Option<Actions>,
@@ -53,12 +56,17 @@
     pub fn new(game_field: &'a GameField) -> AI<'a> {
         Self {
             game_field,
+            ammo: [0; ammo::AmmoType::Count as usize],
             targets: vec![],
             team: vec![],
             planned_actions: None,
         }
     }
 
+    pub fn set_available_ammo(&mut self, ammo: [u32; ammo::AmmoType::Count as usize]) {
+        self.ammo = ammo;
+    }
+
     pub fn get_team_mut(&mut self) -> &mut Vec<Hedgehog> {
         &mut self.team
     }
@@ -67,7 +75,7 @@
         let mut stack = Vec::<usize>::new();
         let mut waypoints = Waypoints::default();
 
-        waypoints.add_keypoint(Waypoint{
+        waypoints.add_keypoint(Waypoint {
             x: hedgehog.x,
             y: hedgehog.y,
             ticks: 0,
@@ -75,9 +83,7 @@
             previous_point: None,
         });
 
-        while let Some(wp) = stack.pop() {
-
-        }
+        while let Some(wp) = stack.pop() {}
     }
 
     pub fn have_plan(&self) -> bool {
--- a/rust/lib-hwengine-future/src/lib.rs	Sat Dec 14 18:07:29 2024 +0100
+++ b/rust/lib-hwengine-future/src/lib.rs	Tue Dec 17 15:44:21 2024 +0100
@@ -2,9 +2,9 @@
 
 use integral_geometry::{Point, Size};
 
+use ai::*;
 use landgen::{
-    outline_template_based::outline_template::OutlineTemplate,
-    maze::MazeTemplate,
+    maze::MazeTemplate, outline_template_based::outline_template::OutlineTemplate,
     wavefront_collapse::generator::TemplateDescription as WfcTemplate, LandGenerationParameters,
     LandGenerator,
 };
@@ -12,7 +12,7 @@
 use mapgen::{theme::Theme, MapGenerator};
 use std::fs;
 use std::{ffi::CStr, path::Path};
-use ai::*;
+use std::ptr::slice_from_raw_parts;
 
 #[repr(C)]
 pub struct GameField {
@@ -24,18 +24,16 @@
 #[no_mangle]
 pub extern "C" fn get_game_field_parameters(
     game_field: &GameField,
-    width: *mut i32,
-    height: *mut i32,
-    play_width: *mut i32,
-    play_height: *mut i32,
+    width: &mut i32,
+    height: &mut i32,
+    play_width: &mut i32,
+    play_height: &mut i32,
 ) {
-    unsafe {
-        *width = game_field.collision.width() as i32;
-        *height = game_field.collision.height() as i32;
+    *width = game_field.collision.width() as i32;
+    *height = game_field.collision.height() as i32;
 
-        *play_width = game_field.collision.play_width() as i32;
-        *play_height = game_field.collision.play_height() as i32;
-    }
+    *play_width = game_field.collision.play_width() as i32;
+    *play_height = game_field.collision.play_height() as i32;
 }
 
 #[no_mangle]
@@ -50,17 +48,17 @@
 }
 
 #[no_mangle]
-pub extern "C" fn generate_outline_templated_game_field(
+pub unsafe extern "C" fn generate_outline_templated_game_field(
     feature_size: u32,
     seed: *const i8,
     template_type: *const i8,
     data_path: *const i8,
 ) -> *mut GameField {
-    let data_path: &str = unsafe { CStr::from_ptr(data_path) }.to_str().unwrap();
+    let data_path: &str = CStr::from_ptr(data_path).to_str().unwrap();
     let data_path = Path::new(&data_path);
 
-    let seed: &str = unsafe { CStr::from_ptr(seed) }.to_str().unwrap();
-    let template_type: &str = unsafe { CStr::from_ptr(template_type) }.to_str().unwrap();
+    let seed: &str = CStr::from_ptr(seed).to_str().unwrap();
+    let template_type: &str = CStr::from_ptr(template_type).to_str().unwrap();
 
     let mut random_numbers_gen = LaggedFibonacciPRNG::new(seed.as_bytes());
 
@@ -90,17 +88,17 @@
 }
 
 #[no_mangle]
-pub extern "C" fn generate_wfc_templated_game_field(
+pub unsafe extern "C" fn generate_wfc_templated_game_field(
     feature_size: u32,
     seed: *const i8,
     template_type: *const i8,
     data_path: *const i8,
 ) -> *mut GameField {
-    let data_path: &str = unsafe { CStr::from_ptr(data_path) }.to_str().unwrap();
+    let data_path: &str = CStr::from_ptr(data_path).to_str().unwrap();
     let data_path = Path::new(&data_path);
 
-    let seed: &str = unsafe { CStr::from_ptr(seed) }.to_str().unwrap();
-    let template_type: &str = unsafe { CStr::from_ptr(template_type) }.to_str().unwrap();
+    let seed: &str = CStr::from_ptr(seed).to_str().unwrap();
+    let template_type: &str = CStr::from_ptr(template_type).to_str().unwrap();
 
     let mut random_numbers_gen = LaggedFibonacciPRNG::new(seed.as_bytes());
 
@@ -130,17 +128,17 @@
 }
 
 #[no_mangle]
-pub extern "C" fn generate_maze_game_field(
+pub unsafe extern "C" fn generate_maze_game_field(
     feature_size: u32,
     seed: *const i8,
     template_type: *const i8,
     data_path: *const i8,
 ) -> *mut GameField {
-    let data_path: &str = unsafe { CStr::from_ptr(data_path) }.to_str().unwrap();
+    let data_path: &str = CStr::from_ptr(data_path).to_str().unwrap();
     let data_path = Path::new(&data_path);
 
-    let seed: &str = unsafe { CStr::from_ptr(seed) }.to_str().unwrap();
-    let template_type: &str = unsafe { CStr::from_ptr(template_type) }.to_str().unwrap();
+    let seed: &str = CStr::from_ptr(seed).to_str().unwrap();
+    let template_type: &str = CStr::from_ptr(template_type).to_str().unwrap();
 
     let mut random_numbers_gen = LaggedFibonacciPRNG::new(seed.as_bytes());
 
@@ -173,15 +171,15 @@
 }
 
 #[no_mangle]
-pub extern "C" fn apply_theme(
+pub unsafe extern "C" fn apply_theme(
     game_field: &mut GameField,
     data_path: *const i8,
     theme_name: *const i8,
 ) {
-    let data_path: &str = unsafe { CStr::from_ptr(data_path) }.to_str().unwrap();
+    let data_path: &str = CStr::from_ptr(data_path).to_str().unwrap();
     let data_path = Path::new(&data_path);
 
-    let theme_name: &str = unsafe { CStr::from_ptr(theme_name) }.to_str().unwrap();
+    let theme_name: &str = CStr::from_ptr(theme_name).to_str().unwrap();
     let map_gen = MapGenerator::<()>::new(data_path);
 
     let theme = Theme::load(
@@ -244,8 +242,8 @@
 }
 
 #[no_mangle]
-pub extern "C" fn dispose_game_field(game_field: *mut GameField) {
-    unsafe { drop(Box::from_raw(game_field)) };
+pub unsafe extern "C" fn dispose_game_field(game_field: *mut GameField) {
+    drop(Box::from_raw(game_field));
 }
 
 #[no_mangle]
@@ -259,14 +257,15 @@
 }
 
 #[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});
+pub unsafe extern "C" fn ai_add_team_hedgehog(ai: &mut AI, x: f32, y: f32, ammo_counts: *const u32) {
+    let ammo_counts = &*slice_from_raw_parts(ammo_counts, crate::ai::ammo::AmmoType::Count as usize);
+    let ammo_counts = std::array::from_fn(|i| ammo_counts[i].clone());
+
+    ai.get_team_mut().push(Hedgehog { x, y, ammo: ammo_counts });
 }
 
 #[no_mangle]
-pub extern "C" fn ai_think(ai: &AI) {
-
-}
+pub extern "C" fn ai_think(ai: &AI) {}
 
 #[no_mangle]
 pub extern "C" fn ai_have_plan(ai: &AI) -> bool {
@@ -279,6 +278,6 @@
 }
 
 #[no_mangle]
-pub extern "C" fn dispose_ai(ai: *mut AI) {
-    unsafe { drop(Box::from_raw(ai)) };
+pub unsafe extern "C" fn dispose_ai(ai: *mut AI) {
+    drop(Box::from_raw(ai));
 }