reworked dead-end algorithm to allow travel over dead ends when no one is near

This commit is contained in:
Alexandre 2024-11-22 22:10:32 +01:00
parent 3532eeb40e
commit f620572de5
7 changed files with 74 additions and 34 deletions

BIN
again

Binary file not shown.

BIN
again.cmi

Binary file not shown.

BIN
again.cmx

Binary file not shown.

View File

@ -11,7 +11,7 @@ TODO :
Random.self_init () ;;
let debug_all = false ;;
let logg = true ;;
let logg = false ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
@ -556,25 +556,26 @@ let generate_dead_end_map (gd : game_data) =
let lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) in
let res = Array.make_matrix lines cols false in
(* false = dead end (or wall), true = not a dead end *)
let res = Array.make_matrix lines cols 72727 in
(* distances for each tile to exit to a safe place (ie not a dead end) *)
let pid = gd.player_id in
let visited = Hashtbl.create (lines * cols) in
(* places 0s to connectable tiles *)
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))
((x = gd.players.(pid).xy.x && y = gd.players.(pid).xy.y) || 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 (amt_free_adj_spaces gd x y) >= 3 || (x = gd.players.(pid).xy.x && y = gd.players.(pid).xy.y) then begin
if prev <> [] then
Hashtbl.remove visited (x, y) ;
List.iter (fun (cx, cy) -> res.(cx).(cy) <- true) ((x, y)::prev) ;
List.iter (fun (cx, cy) -> res.(cx).(cy) <- 0) ((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
@ -589,6 +590,41 @@ let generate_dead_end_map (gd : game_data) =
end
in
dfs gd.players.(pid).xy.x gd.players.(pid).xy.y [] 4 ;
(* fills remaining spaces with BFS *)
let bfs (x0 : int) (y0 : int) =
let q = Queue.create () in
let visit_mem = Hashtbl.create 100 in
Queue.add (x0, y0, 0) q ;
try
while not (Queue.is_empty q) do
let (x, y, d) = Queue.pop q in
if
(is_valid x y lines cols) &&
(Hashtbl.find_opt visit_mem (x, y) = None) &&
(gd.laby.(x).(y) <> 1 && gd.laby.(x).(y) <> 2) &&
((x = gd.players.(pid).xy.x && y = gd.players.(pid).xy.y) || 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 visit_mem (x, y) 1;
if res.(x).(y) = 0 && not (x = gd.players.(pid).xy.x && y = gd.players.(pid).xy.y) then
raise (ReturnInt d) ;
for dir = 0 to 3 do
Queue.add (x + fst (order.(dir)), y + snd (order.(dir)), d+1) q
done
end
done;
()
with
| ReturnInt k -> res.(x0).(y0) <- k
in
for l = 0 to lines -1 do
for c = 0 to cols -1 do
if res.(l).(c) <> 0 then
bfs l c
done
done;
res ;;
let is_player_nearby (gd : game_data) (x0 : int) (y0 : int) (detect_dist : int) =
@ -757,17 +793,21 @@ let bfs_for_crate (gd : game_data) (dgs : danger_map) (x0 : int) (y0 : int) (sti
let pid = gd.player_id in
let needs_gtfo = not (is_empty_lst dgs.explosionTimes.(x0).(y0)) in
let nearest_player = min_dist_from_player gd gd.players.(pid).xy.x gd.players.(pid).xy.y in
let undead_end_tiles = generate_dead_end_map gd in
(*if gd.player_id = 0 then begin
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));
if undead_end_tiles.(l).(c) >= 727 then
Printf.fprintf stderr "- "
else
Printf.fprintf stderr "%d " undead_end_tiles.(l).(c);
done;
Printf.fprintf stderr "\n";
done
end ;*)
end ;
Queue.add (x0, y0, stime +. interval, 4, 1) q ;
@ -790,13 +830,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 4 && not undead_end_tiles.(x).(y))) && (* is not going to be an ez kill *)
(undead_end_tiles.(x).(y) * 2 <= nearest_player) && (* 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;
if not (x0 == x && y0 == y) && (needs_gtfo || not (is_player_nearby gd x y 5 && not undead_end_tiles.(x).(y))) then begin
if not (x0 == x && y0 == y) && (needs_gtfo || undead_end_tiles.(x).(y) * 2 <= nearest_player) then begin
for dir = 0 to 3 do
Queue.add (x + (fst order.(dir)), y + (snd order.(dir)), ct +. interval, direction, polar) q ;
done;
@ -954,14 +994,15 @@ if exists_crate game_map then begin
end
else begin
if logg then Printf.fprintf stderr "No crates\n" ;
Printf.fprintf stderr "WIN\n" ;
(*direction := move_land 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;
if logg then Printf.fprintf stderr "[player %d] %d %d (at time %f)\n" game_map.player_id !direction !action game_map.dt;
set_meta_info game_map.player_id ;;
let __end = Unix.gettimeofday() ;;
Printf.fprintf stderr "Time : %f\n" (__end -. __start) ;;
if logg then Printf.fprintf stderr "Time : %f\n" (__end -. __start) ;;

BIN
again.o

Binary file not shown.

View File

@ -1,25 +1,23 @@
227.200000000001
0
229.1200000000008
2
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 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 3 3 3 6 3 6 3 3 3 3 3 5 5 5 5 5 5 5 5 1
1 3 1 3 1 3 1 6 1 3 1 3 1 4 1 5 1 5 1 5 1
1 3 3 6 6 3 6 6 6 3 0 3 5 5 5 5 5 5 4 4 1
1 0 1 6 1 3 1 3 1 6 1 3 1 4 1 5 1 5 1 5 1
1 3 3 3 3 3 3 3 3 6 3 4 3 4 4 4 4 4 4 4 1
1 0 1 6 1 3 1 3 1 6 1 4 1 4 1 3 1 4 1 5 1
1 3 3 3 3 3 6 6 6 6 6 4 5 4 5 3 5 5 5 4 1
1 6 1 6 1 3 1 6 1 6 1 4 1 4 1 3 1 4 1 4 1
1 3 3 6 3 6 6 6 6 6 4 4 4 4 4 4 4 4 4 4 1
1 6 1 6 1 3 1 6 1 0 1 4 1 4 1 5 1 4 1 4 1
1 6 6 6 0 3 0 4 4 4 4 4 4 4 4 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
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
10 7 0 1 2 4 3 3
10 11 1 2 1 6 0 1
10 13 2 2 1 3 2 3
9 6 3 5 2 2 4 1
0

View File

@ -0,0 +1 @@
4 0