(tried to) make advanced pathfinding more exausti(ng)ve

This commit is contained in:
Alexandre 2024-11-19 22:15:24 +01:00
parent 21f2b79a4b
commit 50a354ea94
9 changed files with 117 additions and 86 deletions

BIN
again

Binary file not shown.

BIN
again.cmi

Binary file not shown.

BIN
again.cmo

Binary file not shown.

BIN
again.cmx

Binary file not shown.

152
again.ml
View File

@ -98,7 +98,7 @@ exception ReturnBool of bool ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let order = [|(-1, 0); (0, 1); (1, 0); (0, -1)|] ;;
let order = [|(-1, 0); (0, 1); (1, 0); (0, -1); (0, 0)|] ;;
let current_status = ref BlowUpCrates ;;
let action = ref 0 ;;
@ -486,28 +486,52 @@ let simulate_bomb_deconstruct (dgs : danger_map) (bx : int) (by : int) (bsize :
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let tile_distance (gd : game_data) (start_x : int) (start_y : int) (end_x : int) (end_y : int) =
let tile_distance (gd : game_data) (x0 : int) (y0 : int) (end_x : int) (end_y : int) =
(* returns -1 if the 2 tiles cannot connect *)
let lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) in
let visited = Hashtbl.create 50 in
let rec aux x y depth =
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
if x = end_x && y = end_y then
raise (ReturnInt depth) ;
for dir = 0 to 3 do
aux (x + fst order.(dir)) (y + snd order.(dir)) (depth+1)
done
end
end
in
let visited = Hashtbl.create 100 in
let q = Queue.create () in
Queue.add (x0, y0, 0) q;
try
aux start_x start_y 0;
while not (Queue.is_empty q) do
let (x, y, depth) = 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 (x = end_x && y = end_y) then begin
raise (ReturnInt depth)
end;
if not (x0 == x && y0 == y) then begin
for dir = 0 to 3 do
Queue.add (x + (fst order.(dir)), y + (snd order.(dir)), depth+1) q ;
done;
end
end
end
done;
(-1) ;
with
| ReturnInt b -> b ;;
| ReturnInt k -> k ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let d_len = 1 ;;
let min_dist_from_player (gd : game_data) (x : int) (y : int) =
Array.fold_left min 999999 (Array.init
(Array.length gd.players)
(fun i ->
if gd.player_id = gd.players.(i).id then
999999
else begin
let d = tile_distance gd x y (gd.players.(i).xy.x) (gd.players.(i).xy.y) in
if d = -1 then 999999 else d
end
)
) ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
@ -517,26 +541,29 @@ let amt_free_adj_spaces (gd : game_data) (x : int) (y : int) =
and cols = Array.length gd.laby.(0) in
Array.fold_left
(fun acc (ox, oy) ->
if (is_valid (x+ox) (y+oy) lines cols && gd.laby.(x+ox).(y+oy) <> 1 && gd.laby.(x+ox).(y+oy) <> 2 && not (Array.fold_left (fun acc (b : bomb) -> acc || (b.xy.x = x && b.xy.y = y)) false gd.bombs)) then acc+1 else acc
if (is_valid (x+ox) (y+oy) lines cols && gd.laby.(x+ox).(y+oy) <> 1 && gd.laby.(x+ox).(y+oy) <> 2 && not (Array.fold_left (fun acc (b : bomb) -> acc || (b.xy.x = x+ox && b.xy.y = y+oy)) false gd.bombs)) then acc+1 else acc
)
0
order ;;
let max_depth = 4 ;;
let max_spacing = 4 ;;
let is_player_nearby (gd : game_data) (res_x : int ref) (res_y : int ref) =
let max_depth = 12345 ;;
let is_player_nearby (gd : game_data) (x0 : int) (y0 : int) (detect_dist : int) =
let pid = gd.player_id in
let lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) in
(* DFS to find whether or not there are nearby players *)
let visited = Hashtbl.create 40 in
Hashtbl.add visited ((gd.players.(pid).xy.x), (gd.players.(pid).xy.y)) 1 ;
Hashtbl.add visited (x0, y0) 1 ;
let rec dfs x y depth =
if Hashtbl.find_opt visited (x, y) = None && depth <= max_depth && (is_valid x y lines cols && gd.laby.(x).(y) <> 1 && gd.laby.(x).(y) <> 2) then begin
if
(Hashtbl.find_opt visited (x, y) = None) &&
(depth <= detect_dist) &&
(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
Hashtbl.add visited (x, y) 1;
if Array.exists (fun (p : player) -> p.xy.x = x && p.xy.y = y) gd.players then begin
res_x := x ;
res_y := y ;
if Array.exists (fun (p : player) -> p.xy.x = x && p.xy.y = y && p.id <> gd.player_id) gd.players then begin
raise (ReturnBool true)
end
else begin
@ -559,7 +586,7 @@ let is_player_nearby (gd : game_data) (res_x : int ref) (res_y : int ref) =
| ReturnBool b -> b ;;
let is_dead_end (gd : game_data) (xstart : int) (ystart : int) (xban : int) (yban : int) =
if not (is_player_nearby gd fodder_x fodder_y) then
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 lines = Array.length gd.laby
@ -587,39 +614,48 @@ let is_dead_end (gd : game_data) (xstart : int) (ystart : int) (xban : int) (yba
end ;;
let has_multiple_escapes (gd : game_data) (xstart : int) (ystart : int) (xban : int) (yban : int) =
let pl_x = ref 0
and pl_y = ref 0 in
if not (is_player_nearby gd pl_x pl_y) then
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 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
| _ ->
if tile_distance gd x y !pl_x !pl_y >= max_spacing then
raise (ReturnBool false) ;
end
end
in
let visited = Hashtbl.create 100 in
let q = Queue.create () in
Queue.add (xstart, ystart, 0, false) q;
try
aux xstart ystart;
true ;
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 b -> b
| ReturnBool k -> k
end ;;
let advanced_pathfind (gd : game_data) (xstart : int) (ystart : int) (xban : int) (yban : int) =
(is_dead_end gd xstart ystart xban yban) && (has_multiple_escapes gd xstart ystart xban yban) ;;
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 reverse_simulate_bomb (dgs : danger_map) (save : (int * int, float) Hashtbl.t) =
Hashtbl.iter
@ -689,8 +725,8 @@ let goto_tile (gd : game_data) (dgs : danger_map) (x0 : int) (y0 : int) (end_x :
then begin (* is not lethal *)
if
(is_empty_lst dgs.explosionTimes.(x).(y)) && (* safe *)
(not (is_player_nearby gd fodder_x fodder_y && amt_free_adj_spaces gd x y = 1)) && (* is not a dead-end (==> ez kill) *)
(direction = 4 || not (advanced_pathfind gd (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 3 && amt_free_adj_spaces gd (gd.players.(pid).xy.x + fst order.(direction)) (gd.players.(pid).xy.y + snd order.(direction)) = 1)) &&
(direction = 4 || (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)) &&
(x = end_x && y = end_y)
then begin
raise (ReturnInt direction)
@ -802,8 +838,8 @@ 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 fodder_x fodder_y && amt_free_adj_spaces gd x y = 1)) && (* is not a dead-end (==> ez kill) *)
(not placedBomb || direction = 4 || not (advanced_pathfind gd (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 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 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

BIN
again.o

Binary file not shown.

View File

@ -1 +1 @@
ocamlc again.ml -o again
ocamlfind ocamlopt -linkpkg -package unix again.ml -o again

View File

@ -1,31 +1,26 @@
457.50401999999656
3
187.24208499999915
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 0 6 3 3 3 3 3 3 3 3 3 5 5 5 5 5 6 1
1 3 1 0 1 6 1 3 1 3 1 3 1 3 1 5 1 5 1 5 1
1 5 3 6 6 6 6 3 5 5 5 5 5 3 5 5 5 5 3 3 1
1 6 1 6 1 6 1 3 1 4 1 4 1 3 1 5 1 5 1 5 1
1 6 6 6 6 6 3 3 3 3 3 3 3 3 3 5 5 5 5 5 1
1 6 1 6 1 6 1 3 1 3 1 6 1 3 1 5 1 5 1 4 1
1 6 6 6 6 6 6 6 6 6 6 6 4 4 5 5 6 5 0 4 1
1 6 1 6 1 6 1 6 1 3 1 6 1 4 1 6 1 3 1 4 1
1 6 6 6 4 6 3 6 6 6 6 6 6 4 3 3 3 3 3 3 1
1 6 1 6 1 6 1 6 1 6 1 6 1 4 1 6 1 3 1 4 1
1 6 6 5 6 6 6 6 6 6 6 6 4 4 4 4 3 3 3 3 1
1 3 3 3 3 3 3 6 3 3 3 3 0 0 0 0 5 5 5 5 1
1 3 1 3 1 3 1 6 1 0 1 3 1 5 1 0 1 5 1 5 1
1 3 3 3 3 3 3 6 3 0 0 3 5 5 5 5 5 5 5 5 1
1 3 1 3 1 3 1 6 1 6 1 3 1 5 1 5 1 0 1 0 1
1 3 3 5 3 4 3 6 3 5 0 3 0 3 3 3 3 3 3 0 1
1 3 1 5 1 4 1 6 1 5 1 3 1 4 1 4 1 4 1 0 1
1 0 0 4 4 4 4 4 6 6 6 6 6 6 4 4 3 3 3 3 1
1 0 1 5 1 4 1 6 1 5 1 0 1 4 1 4 1 4 1 3 1
1 5 5 5 5 4 5 6 6 5 6 5 6 6 4 4 4 4 4 3 1
1 5 1 6 1 5 1 6 1 6 1 5 1 0 1 4 1 4 1 3 1
1 5 6 6 6 5 6 6 6 6 6 6 5 5 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
8
7 13 2 457.7330299999967
7 10 2 459.4610799999966
2 9 1 459.5
8 9 2 460.68547999999663
1 13 2 460.9700000000011
5 11 2 461.2325499999966
7 7 2 462.4569499999966
3 7 1 462.5
3
5 1 3 189.5
7 4 6 190.30000000000013
6 3 2 192.5
4
8 7 0 5 2 2 1 0
4 7 1 0 2 1 0 1
2 11 2 2 2 2 0 0
5 14 3 5 2 2 6 6
7 1 0 0 2 3 1 1
5 3 1 0 0 2 1 3
6 3 2 6 1 2 2 2
7 5 3 1 0 6 1 1
0

View File

@ -1 +1 @@
1 1
0 0