refactoring of player anticipation function

This commit is contained in:
Alexandre 2024-11-20 21:17:29 +01:00
parent b6727d2eb9
commit 3532eeb40e
8 changed files with 126 additions and 170 deletions

BIN
again

Binary file not shown.

BIN
again.cmi

Binary file not shown.

BIN
again.cmx

Binary file not shown.

252
again.ml
View File

@ -31,7 +31,7 @@ type player = {
id : int ;
xy : pt ;
nspeed : int ;
nbomb_atonce : int ;
bomb_to_place : int ;
bomb_radius : int ;
ndash : int ;
ntraps : int ;
@ -57,7 +57,7 @@ and default_player = {
id = -1 ;
xy = default_point ;
nspeed = 0 ;
nbomb_atonce = 0 ;
bomb_to_place = 0 ;
bomb_radius = 0 ;
ndash = 0 ;
ntraps = 0 ;
@ -168,7 +168,7 @@ let print_game_data (gd : game_data) =
done;
Printf.fprintf stderr "Players (%d) : \n" gd.nplayers ;
for b = 0 to gd.nplayers -1 do
Printf.fprintf stderr " [Player %d] (at %d %d) (holding %d %d %d %d %d)\n" gd.players.(b).id gd.players.(b).xy.x gd.players.(b).xy.y gd.players.(b).nspeed gd.players.(b).nbomb_atonce gd.players.(b).bomb_radius gd.players.(b).ndash gd.players.(b).ntraps ;
Printf.fprintf stderr " [Player %d] (at %d %d) (holding %d %d %d %d %d)\n" gd.players.(b).id gd.players.(b).xy.x gd.players.(b).xy.y gd.players.(b).nspeed gd.players.(b).bomb_to_place gd.players.(b).bomb_radius gd.players.(b).ndash gd.players.(b).ntraps ;
done;
Printf.fprintf stderr "Boosts (%d) : \n" gd.nboosts ;
for b = 0 to gd.nboosts -1 do
@ -200,6 +200,10 @@ let rec ln_b b = function
| k when k < b -> 0
| k -> 1 + ln_b b (k/b) ;;
let int_of_bool = function
| false -> 0
| true -> 1 ;;
let get_meta_info (pid : int) =
let ptr = open_in ("main_"^(string_of_int pid)^".sav") in
let fct0 () = match (int_of_string (input_line ptr)) with
@ -303,7 +307,7 @@ let parse_input (str : string) =
res.players <- Array.make 4 default_player ;
for p = 0 to res.nplayers -1 do
let dat = int_n_of_string (input_line ptr) 8 useless in
res.players.(dat.(2)) <- {id = dat.(2) ; xy = {x = dat.(0) ; y = dat.(1) ;} ; nspeed = dat.(3) ; nbomb_atonce = dat.(4) ; bomb_radius = dat.(5) ; ndash = dat.(6) ; ntraps = dat.(7) ;}
res.players.(dat.(2)) <- {id = dat.(2) ; xy = {x = dat.(0) ; y = dat.(1) ;} ; nspeed = dat.(3) ; bomb_to_place = dat.(4) ; bomb_radius = dat.(5) ; ndash = dat.(6) ; ntraps = dat.(7) ;}
done;
(* boosts *)
@ -505,7 +509,7 @@ let tile_distance (gd : game_data) (x0 : int) (y0 : int) (end_x : int) (end_y :
if (x = end_x && y = end_y) then begin
raise (ReturnInt depth)
end;
if not (x0 == x && y0 == y) then begin
if true then begin
for dir = 0 to 3 do
Queue.add (x + (fst order.(dir)), y + (snd order.(dir)), depth+1) q ;
done;
@ -547,82 +551,50 @@ let amt_free_adj_spaces (gd : game_data) (x : int) (y : int) =
0
order ;;
let max_depth = 12345 ;;
let is_player_nearby (gd : game_data) (x0 : int) (y0 : int) (detect_dist : int) =
let mind = min_dist_from_player gd x0 y0 in
(mind <= detect_dist) ;;
let generate_dead_end_map (gd : game_data) =
(* links every cell that has at least 3 neighbors *)
let is_dead_end (gd : game_data) (xstart : int) (ystart : int) (xban : int) (yban : int) =
if not (is_player_nearby gd gd.players.(gd.player_id).xy.x gd.players.(gd.player_id).xy.y 3) then
false (* if no one is nearby, it's safe to go there (hopefully) *)
else begin
let lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) in
let visited = Hashtbl.create 50 in
Hashtbl.add visited (xban, yban) 1 ;
let rec aux x y =
if Hashtbl.find_opt visited (x, y) = None then begin
Hashtbl.add visited (x, y) 1;
if (is_valid x y lines cols && gd.laby.(x).(y) <> 1 && gd.laby.(x).(y) <> 2 && not (Array.fold_left (fun acc (b : bomb) -> acc || (b.xy.x = x && b.xy.y = y)) false gd.bombs)) then begin
match (amt_free_adj_spaces gd x y) with
| 0 -> failwith "wtf john"
| 1 | 2 -> for dir = 0 to 3 do
aux (x + fst order.(dir)) (y + snd order.(dir))
done
| _ -> raise (ReturnBool false)
end
end
in
try
aux xstart ystart;
true ;
with
| ReturnBool b -> b
end ;;
let has_multiple_escapes (gd : game_data) (xstart : int) (ystart : int) (xban : int) (yban : int) =
let lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) in
if not (is_player_nearby gd gd.players.(gd.player_id).xy.x gd.players.(gd.player_id).xy.y max_depth) then
false (* if no one is nearby, it's safe to go there (hopefully) *)
else begin
let visited = Hashtbl.create 100 in
let q = Queue.create () in
let res = Array.make_matrix lines cols false in
(* false = dead end (or wall), true = not a dead end *)
Queue.add (xstart, ystart, 0, false) q;
let pid = gd.player_id in
let visited = Hashtbl.create (lines * cols) in
let rec dfs x y prev last_dir =
if
(is_valid x y lines cols) &&
(Hashtbl.find_opt visited (x, y) = None) &&
(gd.laby.(x).(y) <> 1 && gd.laby.(x).(y) <> 2) &&
(not (Array.fold_left (fun acc (b : bomb) -> acc || (b.xy.x = x && b.xy.y = y)) false gd.bombs)) &&
(not (Array.fold_left (fun acc (p : player) -> acc || (p.xy.x = x && p.xy.y = y && p.id <> pid)) false gd.players))
then begin
Hashtbl.add visited (x, y) 1 ;
if (amt_free_adj_spaces gd x y) >= 3 then begin
if prev <> [] then
Hashtbl.remove visited (x, y) ;
List.iter (fun (cx, cy) -> res.(cx).(cy) <- true) ((x, y)::prev) ;
for dir = 0 to 3 do
if (dir + 2) mod 4 <> last_dir then (* dont backtrack *)
dfs (x + fst (order.(dir))) (y + snd (order.(dir))) [] dir
done
end
else begin
for dir = 0 to 3 do
if (dir + 2) mod 4 <> last_dir then
dfs (x + fst (order.(dir))) (y + snd (order.(dir))) ((x, y)::prev) dir
done
end
end
in
dfs gd.players.(pid).xy.x gd.players.(pid).xy.y [] 4 ;
res ;;
try
while not (Queue.is_empty q) do
let (x, y, depth, hasSafe) = Queue.pop q in
if is_valid x y lines cols && gd.laby.(x).(y) <> 1 && gd.laby.(x).(y) <> 2 && not (Array.fold_left (fun acc (b : bomb) -> acc || (b.xy.x = x && b.xy.y = y)) false gd.bombs) then begin
if Hashtbl.find_opt visited (x, y) = None then begin (* has not been visited yet *)
Hashtbl.add visited (x, y) 1 ;
if
(amt_free_adj_spaces gd x y >= 3) &&
(min_dist_from_player gd x y >= depth - d_len || hasSafe)
then begin
raise (ReturnBool true)
end
else if (amt_free_adj_spaces gd x y >= 3) then begin
for dir = 0 to 3 do
Queue.add (x + (fst order.(dir)), y + (snd order.(dir)), depth+1, true) q ;
done;
end
else if (amt_free_adj_spaces gd x y = 2) then begin
for dir = 0 to 3 do
Queue.add (x + (fst order.(dir)), y + (snd order.(dir)), depth+1, hasSafe) q ;
done;
end
end
end
done;
false ;
with
| ReturnBool k -> k
end ;;
let advanced_pathfind (gd : game_data) (dgs : danger_map) (xstart : int) (ystart : int) (xban : int) (yban : int) =
(not (is_player_nearby gd gd.players.(gd.player_id).xy.x gd.players.(gd.player_id).xy.y max_depth)) || ((*is_dead_end gd xstart ystart xban yban) && *)(has_multiple_escapes gd xstart ystart xban yban)) ;;
let is_player_nearby (gd : game_data) (x0 : int) (y0 : int) (detect_dist : int) =
let mind = min_dist_from_player gd x0 y0 in
if x0 = gd.players.(gd.player_id).xy.x && y0 = gd.players.(gd.player_id).xy.y then Printf.fprintf stderr "[player %d] %d\n" gd.player_id mind ;
(mind <= detect_dist) ;;
let reverse_simulate_bomb (dgs : danger_map) (save : (int * int, float) Hashtbl.t) =
Hashtbl.iter
@ -662,7 +634,7 @@ let is_dead_all (dgs : danger_map) (x : int) (y : int) (t : float) (dt : float)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let goto_tile (gd : game_data) (dgs : danger_map) (x0 : int) (y0 : int) (end_x : int) (end_y : int) (stime : float) =
(*let goto_tile (gd : game_data) (dgs : danger_map) (x0 : int) (y0 : int) (end_x : int) (end_y : int) (stime : float) =
let lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) in
@ -710,7 +682,7 @@ let goto_tile (gd : game_data) (dgs : danger_map) (x0 : int) (y0 : int) (end_x :
done;
4 ;
with
| ReturnInt k -> k ;;
| ReturnInt k -> k ;;*)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
@ -784,6 +756,19 @@ let bfs_for_crate (gd : game_data) (dgs : danger_map) (x0 : int) (y0 : int) (sti
let interval = Float.pow (0.9) (float_of_int gd.players.(gd.player_id).nspeed) in
let pid = gd.player_id in
let needs_gtfo = not (is_empty_lst dgs.explosionTimes.(x0).(y0)) in
let undead_end_tiles = generate_dead_end_map gd in
(*if gd.player_id = 0 then begin
for l = 0 to Array.length undead_end_tiles -1 do
for c = 0 to Array.length undead_end_tiles.(l) -1 do
Printf.fprintf stderr "%d " (int_of_bool undead_end_tiles.(l).(c));
done;
Printf.fprintf stderr "\n";
done
end ;*)
Queue.add (x0, y0, stime +. interval, 4, 1) q ;
Queue.add (x0+1, y0, stime +. interval, 2, 1) q ;
@ -805,15 +790,13 @@ let bfs_for_crate (gd : game_data) (dgs : danger_map) (x0 : int) (y0 : int) (sti
if
(ct >= stime +. (float_of_int minDist) *. interval) && (* not too deep *)
(is_empty_lst dgs.explosionTimes.(x).(y)) && (* safe *)
(not (is_player_nearby gd x y 3 && amt_free_adj_spaces gd (gd.players.(pid).xy.x + fst order.(direction)) (gd.players.(pid).xy.y + snd order.(direction)) = 1)) && (* is not a dead-end (==> ez kill) *)
((advanced_pathfind gd dgs (gd.players.(pid).xy.x + fst order.(direction)) (gd.players.(pid).xy.y + snd order.(direction)) gd.players.(pid).xy.x gd.players.(pid).xy.y)) &&
(not (is_player_nearby gd x y 4 && not undead_end_tiles.(x).(y))) && (* is not going to be an ez kill *)
(not searchCrate || (sees_a_crate gd dgs x y && not dgs.explodedCrates.(x).(y))) && (* sees a crate *)
(not searchBonus || dgs.bonusMap.(x).(y)) (* is a bonus *)
then begin
raise (ReturnInt direction)
end;
(*Queue.add (x, y, ct +. interval, direction, polar+1) q ;*)
if not (x0 == x && y0 == y) && (not (is_player_nearby gd x y 3 && amt_free_adj_spaces gd (gd.players.(pid).xy.x + fst order.(direction)) (gd.players.(pid).xy.y + snd order.(direction)) = 1)) then begin
if not (x0 == x && y0 == y) && (needs_gtfo || not (is_player_nearby gd x y 5 && not undead_end_tiles.(x).(y))) then begin
for dir = 0 to 3 do
Queue.add (x + (fst order.(dir)), y + (snd order.(dir)), ct +. interval, direction, polar) q ;
done;
@ -831,15 +814,38 @@ let move_crate (gd : game_data) (dgs : danger_map) =
let cxi = gd.players.(pid).xy.x
and cyi = gd.players.(pid).xy.y in
try
let bonusres = bfs_for_crate gd dgs cxi cyi gd.dt false true false 0 false 7 in
if bonusres <> 4 then begin
if logg then Printf.fprintf stderr "bonus spotted\n" ;
raise (ReturnInt bonusres) ;
(* send away a player standing right on top *)
if Array.exists (fun (p : player) -> p.id <> pid && p.xy.x = cxi && p.xy.y = cyi) gd.players then begin
if gd.players.(pid).bomb_to_place > 0 then begin
if logg then Printf.fprintf stderr "oh no you dont\n" ;
let saved_p = simulate_bomb_deconstruct dgs cxi cyi gd.players.(pid).bomb_radius (gd.dt +. 5.5) in
let bonusres_2p = bfs_for_crate gd dgs cxi cyi gd.dt false true false 0 false 7 in
if bonusres_2p <> 4 then begin
if logg then Printf.fprintf stderr "mine\n" ;
raise (ReturnInt bonusres_2p) ;
end;
let resultp = bfs_for_crate gd dgs cxi cyi gd.dt false false true 1 false 80 in
if resultp <> 4 then begin
if logg then Printf.fprintf stderr "go away\n" ;
action := 1 ;
raise (ReturnInt resultp) ;
end;
reverse_simulate_bomb dgs saved_p ;
end
end;
if (is_a_crate_nearby gd dgs) && (is_empty_lst dgs.explosionTimes.(cxi).(cyi)) then begin
if gd.players.(pid).nbomb_atonce > 0 then begin
if gd.players.(pid).bomb_to_place > 0 then begin
if logg then Printf.fprintf stderr "trying...\n" ;
let saved = simulate_bomb_deconstruct dgs cxi cyi gd.players.(pid).bomb_radius (gd.dt +. 5.5) in
let bonusres_2 = bfs_for_crate gd dgs cxi cyi gd.dt false true false 0 false 7 in
if bonusres_2 <> 4 then begin
if logg then Printf.fprintf stderr "Bonus Spotted\n" ;
raise (ReturnInt bonusres_2) ;
end;
let result = bfs_for_crate gd dgs cxi cyi gd.dt false false true 1 false 80 in
if result <> 4 then begin
action := 1 ;
@ -851,6 +857,11 @@ let move_crate (gd : game_data) (dgs : danger_map) =
raise (ReturnInt 4)
end;
end;
let bonusres = bfs_for_crate gd dgs cxi cyi gd.dt false true false 0 false 7 in
if bonusres <> 4 then begin
if logg then Printf.fprintf stderr "bonus spotted\n" ;
raise (ReturnInt bonusres) ;
end;
if logg then Printf.fprintf stderr "searching...\n" ;
let rescr = bfs_for_crate gd dgs cxi cyi gd.dt true false false 0 false 80 in
if rescr <> 4 then
@ -868,61 +879,7 @@ let move_crate (gd : game_data) (dgs : danger_map) =
(* let goto_tile (gd : game_data) (dgs : danger_map) (x0 : int) (y0 : int) (end_x : int) (end_y : int) (stime : float) = *)
let move_land (gd : game_data) (dgs : danger_map) (gns : int array array) =
let pid = gd.player_id in
let cxi = gd.players.(pid).xy.x
and cyi = gd.players.(pid).xy.y in
let max_map = Array.mapi
(fun i line -> Array.mapi
(fun j elt ->
if (gd.laby.(i).(j) <> 1 && gd.laby.(i).(j) <> 2 && not (Array.fold_left (fun acc (b : bomb) -> acc || (b.xy.x = i && b.xy.y = j)) false gd.bombs)) then
(elt, i, j)
else
(-1, i, j)
)
line
)
gns
in
let (_, xmax, ymax) = Array.fold_left
(fun (vm, xm, ym) line ->
let (otm, xtm, ytm) = Array.fold_left
(fun (vm2, xm2, ym2) (i, j, v) ->
if vm2 > v then
(vm2, xm2, ym2)
else
(i, j, v)
) (-1, -1, -1) line
in
if vm > otm then
(vm, xm, ym)
else
(otm, xtm, ytm)
) (-1, -1, -1) max_map
in
Printf.fprintf stderr "(%d %d) -> (%d %d)\n" cxi cyi xmax ymax ;
try
if cxi = xmax && cyi = ymax && (is_empty_lst dgs.explosionTimes.(cxi).(cyi)) then begin (* standing on right tile *)
if gd.players.(pid).nbomb_atonce > 0 then begin
if logg then Printf.fprintf stderr "trying...\n" ;
let saved = simulate_bomb_deconstruct dgs cxi cyi gd.players.(pid).bomb_radius (gd.dt +. 5.5) in
let result = goto_tile gd dgs cxi cyi xmax ymax gd.dt in
if result <> 4 then begin
action := 1 ;
raise (ReturnInt result) ;
end;
reverse_simulate_bomb dgs saved ;
raise (ReturnInt 4)
end
else
raise (ReturnInt 4)
end
else
raise (ReturnInt (goto_tile gd dgs cxi cyi xmax ymax gd.dt))
with
| ReturnInt k -> k ;;
let draw_random (gd : game_data) (infx : int) (infy : int) (lines : int) (cols : int) (dmin : int) =
(*let draw_random (gd : game_data) (infx : int) (infy : int) (lines : int) (cols : int) (dmin : int) =
(* get a random, valid tile *)
let xres = ref (-1)
and yres = ref (-1) in
@ -947,7 +904,7 @@ let move_land_2 (gd : game_data) (dgs : danger_map) (gns : int array array) =
let result_0 = goto_tile gd dgs cxi cyi x y gd.dt in
if result_0 <> 4 then begin
if
gd.players.(pid).nbomb_atonce > 0 &&
gd.players.(pid).bomb_to_place > 0 &&
not (Array.fold_left (fun acc (b : bomb) -> acc || (b.xy.x = cxi && b.xy.y = cyi)) false gd.bombs) &&
(is_empty_lst dgs.explosionTimes.(cxi).(cyi))
then begin
@ -964,7 +921,7 @@ let move_land_2 (gd : game_data) (dgs : danger_map) (gns : int array array) =
done;
4
with
| ReturnInt k -> k ;;
| ReturnInt k -> k ;;*)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
@ -992,16 +949,15 @@ print_dangers danger_data ;;*)
let direction = ref 4 ;;
if exists_crate game_map then begin
Printf.fprintf stderr "Crates\n" ;
if logg then Printf.fprintf stderr "Crates\n" ;
direction := move_crate game_map danger_data
end
else begin
Printf.fprintf stderr "No crates\n" ;
if logg then Printf.fprintf stderr "No crates\n" ;
(*direction := move_land game_map danger_data gain_map *)
direction := move_land_2 game_map danger_data gain_map
(*direction := move_land_2 game_map danger_data gain_map *)
end ;;
Printf.printf "%d %d" !direction !action ;
if true || logg then Printf.fprintf stderr "[player %d] %d %d (at time %f)\n" game_map.player_id !direction !action game_map.dt;

BIN
again.o

Binary file not shown.

View File

@ -1,26 +1,25 @@
183.6000000000002
227.200000000001
0
13 21
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 3 3 3 3 3 3 3 0 0 0 4 4 4 4 5 5 5 5 5 1
1 3 1 3 1 3 1 3 1 0 1 0 1 4 1 4 1 5 1 5 1
1 3 6 3 6 3 3 3 3 3 3 3 4 4 4 4 4 5 5 5 1
1 3 1 0 1 3 1 3 1 3 1 0 1 4 1 4 1 4 1 5 1
1 6 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 5 4 5 1
1 3 1 3 1 6 1 3 1 5 1 5 1 5 1 5 1 4 1 4 1
1 3 3 6 6 5 5 3 5 5 5 5 5 5 5 5 5 4 4 4 1
1 3 1 3 1 6 1 5 1 5 1 5 1 5 1 5 1 4 1 4 1
1 3 6 3 6 6 6 5 6 6 5 5 5 5 5 5 4 4 4 4 1
1 6 1 6 1 3 1 4 1 5 1 5 1 5 1 4 1 4 1 4 1
1 6 6 6 4 4 4 4 4 4 4 6 5 5 5 5 4 4 4 4 1
1 3 3 3 3 3 0 0 0 3 3 3 3 3 3 4 4 4 4 5 1
1 3 1 3 1 3 1 3 1 0 1 3 1 5 1 5 1 4 1 5 1
1 3 3 3 3 3 2 3 0 3 5 3 5 5 5 4 5 4 5 5 1
1 3 1 3 1 3 1 3 1 3 1 3 1 5 1 4 1 4 1 5 1
1 3 3 3 3 3 3 3 3 3 3 3 3 5 5 5 5 4 5 4 1
1 3 1 3 1 3 1 3 1 3 1 5 1 5 1 4 1 4 1 4 1
1 3 3 3 3 3 3 3 3 3 4 4 4 5 4 4 4 4 4 4 1
1 3 1 3 1 6 1 3 1 3 1 3 1 5 1 4 1 4 1 4 1
1 6 3 3 6 6 6 6 6 6 6 6 4 4 4 4 4 4 4 4 1
1 6 1 6 1 6 1 6 1 6 1 6 1 4 1 4 1 4 1 4 1
1 6 6 6 6 6 6 6 6 6 6 6 0 4 0 4 4 4 4 4 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
3
8 9 3 186.5850000000011
2 7 2 187.30000000000018
9 10 3 188.04300000000111
4
1 8 0 1 1 2 1 4
9 8 1 3 1 3 1 1
9 8 2 1 4 2 2 0
9 11 3 1 4 2 0 2
0
4
1 9 0 1 7 3 4 2
3 15 1 1 2 4 2 6
1 13 2 1 1 3 2 5
3 9 3 2 3 2 3 0
2
1 7 3
1 8 4

View File

@ -427,6 +427,7 @@ def execute_evenement(evenements, evenement, plateau, plateauCouleur, bombes, jo
indiceJoueur = trouve_objet(i,j,joueurs)
while indiceJoueur != None:
joueurs[indiceJoueur] = None
print("DEATH :", indiceJoueur)
indiceJoueur = trouve_objet(i,j,joueurs)
# On fait exploser la bombe s'il y en a une
@ -541,5 +542,6 @@ def simulation(strategies):
fenetre.mainloop()
return
#simulation(["./again"])
#simulation(["./again", "./again"])
simulation(["./again", "./again", "./again", "./again"])

View File

@ -1 +0,0 @@
1 1