refactoring of BFS functions
This commit is contained in:
parent
a7da366a02
commit
e74af821f2
|
@ -1,19 +1,19 @@
|
||||||
3.7
|
3.7
|
||||||
0
|
0
|
||||||
7 11
|
7 11
|
||||||
0 0 0 0 0 0 0 0 0 0 0
|
0 0 2 2 2 2 2 2 2 0 0
|
||||||
0 0 0 0 2 0 2 0 2 0 0
|
0 1 2 1 2 1 2 1 2 1 0
|
||||||
0 0 0 2 2 2 2 2 0 0 0
|
2 2 2 2 2 2 2 0 2 2 2
|
||||||
0 0 2 0 2 0 2 0 2 0 2
|
2 1 0 1 2 1 2 1 2 1 0
|
||||||
3 3 3 0 0 0 2 2 4 4 0
|
2 2 2 2 2 2 2 2 2 2 2
|
||||||
0 0 0 0 0 0 0 0 0 0 0
|
0 1 2 1 2 1 2 1 0 1 0
|
||||||
0 0 0 2 2 2 2 3 3 2 0
|
0 0 2 2 2 2 2 2 2 0 0
|
||||||
3
|
3
|
||||||
3 2 4 4.1
|
3 2 4 4.1
|
||||||
4 4 2 4.3
|
4 4 2 4.3
|
||||||
0 0 3 5.5
|
8 6 3 5.5
|
||||||
5
|
5
|
||||||
2 2 0 3 2 4 5 3
|
0 1 0 3 2 4 5 3
|
||||||
2 0 1 4 3 2 2 2
|
2 0 1 4 3 2 2 2
|
||||||
10 5 2 0 2 3 2 3
|
10 5 2 0 2 3 2 3
|
||||||
5 5 3 5 1 10 2 3
|
5 5 3 5 1 10 2 3
|
||||||
|
|
264
main.ml
264
main.ml
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
let debug = false ;;
|
let debug = false ;;
|
||||||
let fatal_time = 1.0 ;;
|
let fatal_time = 1.0 ;;
|
||||||
|
let explosion_time = 1.5 ;;
|
||||||
|
|
||||||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||||
|
@ -73,28 +74,30 @@ type game_data = {
|
||||||
mutable boosts : boost array ;
|
mutable boosts : boost array ;
|
||||||
}
|
}
|
||||||
|
|
||||||
type danger = Safe | Danger | Fatal | Blocked ;;
|
type danger = Safe | Danger of float | Fatal of float | Blocked ;;
|
||||||
|
|
||||||
let int_of_danger = function
|
let int_of_danger = function
|
||||||
| Safe -> 0
|
| Safe -> 0
|
||||||
| Danger -> 1
|
| Danger _ -> 1
|
||||||
| Fatal -> 2
|
| Fatal _ -> 2
|
||||||
| Blocked -> 3 ;;
|
| Blocked -> 3 ;;
|
||||||
|
|
||||||
let danger_of_int = function
|
let danger_of_int t = function
|
||||||
| 0 -> Safe
|
| 0 -> Safe
|
||||||
| 1 -> Danger
|
| 1 -> Danger t
|
||||||
| 2 -> Fatal
|
| 2 -> Fatal t
|
||||||
| _ -> Blocked ;;
|
| _ -> Blocked ;;
|
||||||
|
|
||||||
type moveType = EscapeDeath | BlowUpCrates | KillPlayers | ClaimLand ;;
|
type moveType = EscapeDeath | BlowUpCrates | KillPlayers | ClaimLand ;;
|
||||||
|
|
||||||
exception ReturnInt of int ;;
|
exception ReturnInt of int ;;
|
||||||
|
exception ReturnBool of bool ;;
|
||||||
|
|
||||||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||||
|
|
||||||
let current_status = ref BlowUpCrates ;;
|
let current_status = ref BlowUpCrates ;;
|
||||||
|
let action = ref 0 ;;
|
||||||
|
|
||||||
let equal_pt (p1 : pt) (p2 : pt) =
|
let equal_pt (p1 : pt) (p2 : pt) =
|
||||||
p1.x = p2.x && p1.y = p2.y ;;
|
p1.x = p2.x && p1.y = p2.y ;;
|
||||||
|
@ -115,6 +118,10 @@ let print_direction = function
|
||||||
| 4 -> Printf.printf "STILL "
|
| 4 -> Printf.printf "STILL "
|
||||||
| _-> failwith "ERROR : invalid direction" ;;
|
| _-> failwith "ERROR : invalid direction" ;;
|
||||||
|
|
||||||
|
let level_of_danger = function
|
||||||
|
| Danger k | Fatal k -> k
|
||||||
|
| _ -> 32768. ;;
|
||||||
|
|
||||||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||||
|
|
||||||
|
@ -150,8 +157,8 @@ let print_danger_levels (map : danger array array) =
|
||||||
match map.(l).(c) with
|
match map.(l).(c) with
|
||||||
| Blocked -> Printf.printf "@ "
|
| Blocked -> Printf.printf "@ "
|
||||||
| Safe -> Printf.printf ". "
|
| Safe -> Printf.printf ". "
|
||||||
| Danger -> Printf.printf "! "
|
| Danger _ -> Printf.printf "! "
|
||||||
| Fatal -> Printf.printf "X "
|
| Fatal _ -> Printf.printf "X "
|
||||||
done;
|
done;
|
||||||
Printf.printf "\n"
|
Printf.printf "\n"
|
||||||
done ;;
|
done ;;
|
||||||
|
@ -251,11 +258,11 @@ let parse_input (str : string) =
|
||||||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||||
|
|
||||||
let warn_level (b : bomb) (ct : float) = match (b.det_time -. ct) with
|
let warn_level (b : bomb) (ct : float) = match (b.det_time -. ct) with
|
||||||
| k when k < fatal_time -> Fatal ;
|
| k when k < fatal_time -> Fatal b.det_time ;
|
||||||
| _ -> Danger ;;
|
| _ -> Danger b.det_time ;;
|
||||||
|
|
||||||
let danger_priority (p1 : danger) (p2 : danger) =
|
let danger_priority (p1 : danger) (p2 : danger) =
|
||||||
danger_of_int (max (int_of_danger p1) (int_of_danger p2)) ;;
|
danger_of_int (min (level_of_danger p1) (level_of_danger p2)) (max (int_of_danger p1) (int_of_danger p2)) ;;
|
||||||
|
|
||||||
let order = [|(1, 0); (-1, 0); (0, 1); (0, -1)|] ;;
|
let order = [|(1, 0); (-1, 0); (0, 1); (0, -1)|] ;;
|
||||||
let evaluate_dangers (gd : game_data) =
|
let evaluate_dangers (gd : game_data) =
|
||||||
|
@ -271,35 +278,6 @@ let evaluate_dangers (gd : game_data) =
|
||||||
done
|
done
|
||||||
done ;
|
done ;
|
||||||
|
|
||||||
(* add players as warning (in case they bomb) *)
|
|
||||||
for p = 0 to gd.nplayers -1 do
|
|
||||||
if p <> gd.player_id then begin
|
|
||||||
let halt = ref false in
|
|
||||||
|
|
||||||
let bx = gd.players.(p).xy.x
|
|
||||||
and by = gd.players.(p).xy.y in
|
|
||||||
|
|
||||||
for dir = 0 to 3 do
|
|
||||||
for w = 0 to gd.players.(p).bomb_radius do
|
|
||||||
let cx = bx + w*(fst order.(dir))
|
|
||||||
and cy = by + w*(snd order.(dir)) in
|
|
||||||
if not !halt && is_valid (cx) (cy) lines cols then begin
|
|
||||||
if gd.laby.(cx).(cy) = 1 then (* bedrock *)
|
|
||||||
halt := true ;
|
|
||||||
if gd.laby.(cx).(cy) = 2 then begin (* crate *)
|
|
||||||
halt := true ;
|
|
||||||
res.(cx).(cy) <- danger_priority res.(cx).(cy) Danger ;
|
|
||||||
end
|
|
||||||
else begin
|
|
||||||
res.(cx).(cy) <- danger_priority res.(cx).(cy) Danger ;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
done;
|
|
||||||
halt := false ;
|
|
||||||
done
|
|
||||||
end
|
|
||||||
done;
|
|
||||||
|
|
||||||
(* sort bombs based on detonation time *)
|
(* sort bombs based on detonation time *)
|
||||||
for b = 0 to gd.nbombs -1 do
|
for b = 0 to gd.nbombs -1 do
|
||||||
let m = ref gd.bombs.(b).det_time
|
let m = ref gd.bombs.(b).det_time
|
||||||
|
@ -349,13 +327,14 @@ let evaluate_dangers (gd : game_data) =
|
||||||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||||
|
|
||||||
let is_safe = function
|
let is_safe = function
|
||||||
| Safe | Danger -> true
|
| Safe | Danger _ -> true
|
||||||
| Fatal | Blocked -> false ;;
|
| Fatal _ | Blocked -> false ;;
|
||||||
|
|
||||||
let move_safe (gd : game_data) (dgs : danger array array) =
|
let move_safe (gd : game_data) (dgs : danger array array) =
|
||||||
(* use this whenever you are standing on a non-safe tile *)
|
(* use this whenever you are standing on a non-safe tile *)
|
||||||
(* Strat : find the closest safe tile (or warning tile if there are no reachable safe tile) *)
|
(* Strat : find the shortest, safest path *)
|
||||||
let pid = gd.player_id in
|
let pid = gd.player_id in
|
||||||
|
let interval = Float.pow 0.9 (float_of_int gd.players.(pid).nspeed) in
|
||||||
|
|
||||||
let lines = Array.length gd.laby
|
let lines = Array.length gd.laby
|
||||||
and cols = Array.length gd.laby.(0) in
|
and cols = Array.length gd.laby.(0) in
|
||||||
|
@ -367,73 +346,44 @@ let move_safe (gd : game_data) (dgs : danger array array) =
|
||||||
if dgs.(cx).(cy) = Safe then
|
if dgs.(cx).(cy) = Safe then
|
||||||
raise (ReturnInt 4) ;
|
raise (ReturnInt 4) ;
|
||||||
|
|
||||||
let q = Queue.create () in
|
|
||||||
let visited = Hashtbl.create 100 in
|
let visited = Hashtbl.create 100 in
|
||||||
|
|
||||||
(* 1. try not to walk on fatal tiles *)
|
let has_a_safe_path (cx0 : int) (cy0 : int) (simt : float) (vid : int) =
|
||||||
if debug then Printf.printf "[escape] Attempt 1/3...\n";
|
let q = Queue.create () in
|
||||||
if cx <> 0 && is_safe dgs.(cx-1).(cy) then (* North *) Queue.add (cx-1, cy, 0) q ;
|
Queue.add (cx0, cy0, simt) q ; (* everything added to q has valid coords *)
|
||||||
if cx <> lines -1 && is_safe dgs.(cx+1).(cy) then (* South *) Queue.add (cx+1, cy, 2) q ;
|
if debug then Printf.printf "[escape] Attempt %d/4...\n" vid ;
|
||||||
if cy <> 0 && is_safe dgs.(cx).(cy-1) then (* West *) Queue.add (cx, cy-1, 3) q ;
|
try
|
||||||
if cy <> cols -1 && is_safe dgs.(cx).(cy+1) then (* East *) Queue.add (cx, cy+1, 1) q ;
|
|
||||||
|
|
||||||
while not (Queue.is_empty q) do
|
while not (Queue.is_empty q) do
|
||||||
let (cx, cy, dir) = Queue.pop q in
|
let (cx, cy, cur_t) = Queue.pop q in
|
||||||
Hashtbl.add visited (cx, cy, 1) 1 ;
|
if Hashtbl.find_opt visited (cx, cy, vid) <> None then () else begin
|
||||||
|
Hashtbl.add visited (cx, cy, vid) 1 ;
|
||||||
if dgs.(cx).(cy) = Safe then
|
if dgs.(cx).(cy) = Safe then
|
||||||
raise (ReturnInt dir)
|
raise (ReturnBool true)
|
||||||
else begin
|
else if dgs.(cx).(cy) = Blocked then
|
||||||
(* add neighbors *)
|
()
|
||||||
if cx <> 0 && Hashtbl.find_opt visited (cx-1, cy, 1) = None && is_safe dgs.(cx-1).(cy) then (* North *) Queue.add (cx-1, cy, dir) q ;
|
else begin (* either danger or fatal *)
|
||||||
if cx <> lines -1 && Hashtbl.find_opt visited (cx+1, cy, 1) = None && is_safe dgs.(cx+1).(cy) then (* South *) Queue.add (cx+1, cy, dir) q ;
|
let dang_time = level_of_danger dgs.(cx).(cy) in
|
||||||
if cy <> 0 && Hashtbl.find_opt visited (cx, cy-1, 1) = None && is_safe dgs.(cx).(cy-1) then (* West *) Queue.add (cx, cy-1, dir) q ;
|
for dir = 0 to 3 do
|
||||||
if cy <> cols -1 && Hashtbl.find_opt visited (cx, cy+1, 1) = None && is_safe dgs.(cx).(cy+1) then (* East *) Queue.add (cx, cy+1, dir) q ;
|
let newx = cx + fst order.(dir)
|
||||||
|
and newy = cy + snd order.(dir)
|
||||||
|
and newt = cur_t +. interval in
|
||||||
|
if (is_valid newx newy lines cols) && not (newt > dang_time && newt < dang_time +. explosion_time) then
|
||||||
|
Queue.add (newx, newy, newt) q
|
||||||
|
done
|
||||||
|
end
|
||||||
end
|
end
|
||||||
done;
|
done;
|
||||||
|
false
|
||||||
|
with
|
||||||
|
| ReturnBool b -> b
|
||||||
|
in
|
||||||
|
|
||||||
(* 2. find the path that get you off fatal tiles ASAP *)
|
if is_valid (cx+1) (cy) lines cols && has_a_safe_path (cx+1) (cy) gd.dt 0 then raise (ReturnInt 2) ; (* South *)
|
||||||
if debug then Printf.printf "[escape] Attempt 2/3...\n";
|
if is_valid (cx-1) (cy) lines cols && has_a_safe_path (cx-1) (cy) gd.dt 1 then raise (ReturnInt 0) ; (* North *)
|
||||||
if cx <> 0 && dgs.(cx-1).(cy) <> Blocked then (* North *) Queue.add (cx-1, cy, 0) q ;
|
if is_valid (cx) (cy+1) lines cols && has_a_safe_path (cx) (cy+1) gd.dt 2 then raise (ReturnInt 1) ; (* East *)
|
||||||
if cx <> lines -1 && dgs.(cx+1).(cy) <> Blocked then (* South *) Queue.add (cx+1, cy, 2) q ;
|
if is_valid (cx) (cy-1) lines cols && has_a_safe_path (cx) (cy-1) gd.dt 3 then raise (ReturnInt 3) ; (* West *)
|
||||||
if cy <> 0 && dgs.(cx).(cy-1) <> Blocked then (* West *) Queue.add (cx, cy-1, 3) q ;
|
|
||||||
if cy <> cols -1 && dgs.(cx).(cy+1) <> Blocked then (* East *) Queue.add (cx, cy+1, 1) q ;
|
|
||||||
|
|
||||||
while not (Queue.is_empty q) do
|
(* you're probably dead if the code reaches here... *)
|
||||||
let (cx, cy, dir) = Queue.pop q in
|
|
||||||
Hashtbl.add visited (cx, cy, 2) 1 ;
|
|
||||||
if dgs.(cx).(cy) = Safe then
|
|
||||||
raise (ReturnInt dir)
|
|
||||||
else begin
|
|
||||||
(* add neighbors *)
|
|
||||||
if cx <> 0 && Hashtbl.find_opt visited (cx-1, cy, 2) = None && dgs.(cx-1).(cy) <> Blocked then (* North *) Queue.add (cx-1, cy, dir) q ;
|
|
||||||
if cx <> lines -1 && Hashtbl.find_opt visited (cx+1, cy, 2) = None && dgs.(cx+1).(cy) <> Blocked then (* South *) Queue.add (cx+1, cy, dir) q ;
|
|
||||||
if cy <> 0 && Hashtbl.find_opt visited (cx, cy-1, 2) = None && dgs.(cx-1).(cy) <> Blocked then (* West *) Queue.add (cx, cy-1, dir) q ;
|
|
||||||
if cy <> cols -1 && Hashtbl.find_opt visited (cx, cy+1, 2) = None && dgs.(cx).(cy+1) <> Blocked then (* East *) Queue.add (cx, cy+1, dir) q ;
|
|
||||||
end
|
|
||||||
done;
|
|
||||||
|
|
||||||
(* 3. no safe tile within reach (very rare), look out for warning *)
|
|
||||||
if debug then Printf.printf "[escape] Attempt 3/3...\n";
|
|
||||||
if cx <> 0 && dgs.(cx-1).(cy) <> Blocked then (* North *) Queue.add (cx-1, cy, 0) q ;
|
|
||||||
if cx <> lines -1 && dgs.(cx+1).(cy) <> Blocked then (* South *) Queue.add (cx+1, cy, 2) q ;
|
|
||||||
if cy <> 0 && dgs.(cx).(cy-1) <> Blocked then (* West *) Queue.add (cx, cy-1, 3) q ;
|
|
||||||
if cy <> cols -1 && dgs.(cx).(cy+1) <> Blocked then (* East *) Queue.add (cx, cy+1, 1) q ;
|
|
||||||
|
|
||||||
while not (Queue.is_empty q) do
|
|
||||||
let (cx, cy, dir) = Queue.pop q in
|
|
||||||
Hashtbl.add visited (cx, cy, 3) 1 ;
|
|
||||||
if dgs.(cx).(cy) = Danger then
|
|
||||||
raise (ReturnInt dir)
|
|
||||||
else begin
|
|
||||||
(* add neighbors *)
|
|
||||||
if cx <> 0 && Hashtbl.find_opt visited (cx-1, cy, 3) = None && dgs.(cx-1).(cy) <> Blocked then (* North *) Queue.add (cx-1, cy, dir) q ;
|
|
||||||
if cx <> lines -1 && Hashtbl.find_opt visited (cx+1, cy, 3) = None && dgs.(cx+1).(cy) <> Blocked then (* South *) Queue.add (cx+1, cy, dir) q ;
|
|
||||||
if cy <> 0 && Hashtbl.find_opt visited (cx, cy-1, 3) = None && dgs.(cx-1).(cy) <> Blocked then (* West *) Queue.add (cx, cy-1, dir) q ;
|
|
||||||
if cy <> cols -1 && Hashtbl.find_opt visited (cx, cy+1, 3) = None && dgs.(cx).(cy+1) <> Blocked then (* East *) Queue.add (cx, cy+1, dir) q ;
|
|
||||||
end
|
|
||||||
done;
|
|
||||||
|
|
||||||
(* you're probably dead if the code reaches here *)
|
|
||||||
if debug then Printf.printf "[escape] Attempt F...\n";
|
if debug then Printf.printf "[escape] Attempt F...\n";
|
||||||
4
|
4
|
||||||
with
|
with
|
||||||
|
@ -445,67 +395,83 @@ let move_safe (gd : game_data) (dgs : danger array array) =
|
||||||
let move_explore (gd: game_data) (dgs : danger array array) =
|
let move_explore (gd: game_data) (dgs : danger array array) =
|
||||||
(* destroy crates *)
|
(* destroy crates *)
|
||||||
let pid = gd.player_id in
|
let pid = gd.player_id in
|
||||||
|
let interval = Float.pow 0.9 (float_of_int gd.players.(pid).nspeed) in
|
||||||
|
|
||||||
let lines = Array.length gd.laby
|
let lines = Array.length gd.laby
|
||||||
and cols = Array.length gd.laby.(0) in
|
and cols = Array.length gd.laby.(0) in
|
||||||
|
|
||||||
(* find nearest crate and blow it up *)
|
(* find nearest crate and blow it up *)
|
||||||
try
|
try
|
||||||
let q = Queue.create () in
|
let (cx, cy) = (gd.players.(pid).xy.x, gd.players.(pid).xy.y) in
|
||||||
|
|
||||||
let visited = Hashtbl.create 100 in
|
let visited = Hashtbl.create 100 in
|
||||||
let (cx, cy) = (gd.players.(pid).xy.x, gd.players.(pid).xy.y) in
|
|
||||||
|
|
||||||
(* O. if there's a crate right next to you, blow it up *)
|
|
||||||
if cx <> 0 && gd.laby.(cx-1).(cy) = 2 then (* North *) begin current_status := EscapeDeath; raise (ReturnInt 4) end ;
|
|
||||||
if cx <> lines -1 && gd.laby.(cx+1).(cy) = 2 then (* South *) begin current_status := EscapeDeath; raise (ReturnInt 4) end ;
|
|
||||||
if cy <> 0 && gd.laby.(cx).(cy-1) = 2 then (* West *) begin current_status := EscapeDeath; raise (ReturnInt 4) end ;
|
|
||||||
if cy <> cols -1 && gd.laby.(cx).(cy+1) = 2 then (* East *) begin current_status := EscapeDeath; raise (ReturnInt 4) end ;
|
|
||||||
|
|
||||||
(* 1. search without walking on dangerous tiles *)
|
|
||||||
if debug then Printf.printf "[explore] Attempt 1/2...\n";
|
|
||||||
if cx <> 0 && is_safe dgs.(cx-1).(cy) then (* North *) Queue.add (cx-1, cy, 0) q ;
|
|
||||||
if cx <> lines -1 && is_safe dgs.(cx+1).(cy) then (* South *) Queue.add (cx+1, cy, 2) q ;
|
|
||||||
if cy <> 0 && is_safe dgs.(cx).(cy-1) then (* West *) Queue.add (cx, cy-1, 3) q ;
|
|
||||||
if cy <> cols -1 && is_safe dgs.(cx).(cy+1) then (* East *) Queue.add (cx, cy+1, 1) q ;
|
|
||||||
|
|
||||||
|
let has_a_safe_path (cx0 : int) (cy0 : int) (simt : float) (vid : int) =
|
||||||
|
let q = Queue.create () in
|
||||||
|
Queue.add (cx0, cy0, simt) q ; (* everything added to q has valid coords *)
|
||||||
|
if debug then Printf.printf "[crates] Attempt %d/4...\n" vid ;
|
||||||
|
try
|
||||||
while not (Queue.is_empty q) do
|
while not (Queue.is_empty q) do
|
||||||
let (cx, cy, dir) = Queue.pop q in
|
let (cx, cy, cur_t) = Queue.pop q in
|
||||||
Hashtbl.add visited (cx, cy, 1) 1 ;
|
if Hashtbl.find_opt visited (cx, cy, vid) <> None then () else begin
|
||||||
if gd.laby.(cx).(cy) = 2 then
|
Hashtbl.add visited (cx, cy, vid) 1 ;
|
||||||
raise (ReturnInt dir)
|
if dgs.(cx).(cy) = Safe then
|
||||||
else begin
|
raise (ReturnBool true)
|
||||||
(* add neighbors *)
|
else if gd.laby.(cx).(cy) = 2 then (* crate *)
|
||||||
if cx <> 0 && Hashtbl.find_opt visited (cx-1, cy, 1) = None && is_safe dgs.(cx-1).(cy) then (* North *) Queue.add (cx-1, cy, dir) q ;
|
raise (ReturnBool true)
|
||||||
if cx <> lines -1 && Hashtbl.find_opt visited (cx+1, cy, 1) = None && is_safe dgs.(cx+1).(cy) then (* South *) Queue.add (cx+1, cy, dir) q ;
|
else if dgs.(cx).(cy) = Blocked then
|
||||||
if cy <> 0 && Hashtbl.find_opt visited (cx, cy-1, 1) = None && is_safe dgs.(cx).(cy-1) then (* West *) Queue.add (cx, cy-1, dir) q ;
|
()
|
||||||
if cy <> cols -1 && Hashtbl.find_opt visited (cx, cy+1, 1) = None && is_safe dgs.(cx).(cy+1) then (* East *) Queue.add (cx, cy+1, dir) q ;
|
else begin (* either danger or fatal *)
|
||||||
|
let dang_time = level_of_danger dgs.(cx).(cy) in
|
||||||
|
for dir = 0 to 3 do
|
||||||
|
let newx = cx + fst order.(dir)
|
||||||
|
and newy = cy + snd order.(dir)
|
||||||
|
and newt = cur_t +. interval in
|
||||||
|
if (is_valid newx newy lines cols) && not (newt > dang_time && newt < dang_time +. explosion_time) then
|
||||||
|
Queue.add (newx, newy, newt) q
|
||||||
|
done
|
||||||
|
end
|
||||||
end
|
end
|
||||||
done;
|
done;
|
||||||
|
false
|
||||||
|
with
|
||||||
|
| ReturnBool b -> b
|
||||||
|
in
|
||||||
|
|
||||||
(* 2. search one anyway *)
|
(* check if there's a crate next to the player *)
|
||||||
if debug then Printf.printf "[explore] Attempt 2/2...\n";
|
if is_valid (cx+1) (cy) lines cols && gd.laby.(cx+1).(cy) = 2 then begin (* Crate at South *)
|
||||||
let (cx, cy) = (gd.players.(pid).xy.x, gd.players.(pid).xy.y) in
|
current_status := EscapeDeath ;
|
||||||
if cx <> 0 && is_safe dgs.(cx-1).(cy) then (* North *) Queue.add (cx-1, cy, 0) q ;
|
action := 1;
|
||||||
if cx <> lines -1 && is_safe dgs.(cx+1).(cy) then (* South *) Queue.add (cx+1, cy, 2) q ;
|
if debug then Printf.printf "Fire in the hole!\n" ;
|
||||||
if cy <> 0 && is_safe dgs.(cx).(cy-1) then (* West *) Queue.add (cx, cy-1, 3) q ;
|
raise (ReturnInt 4) ;
|
||||||
if cy <> cols -1 && is_safe dgs.(cx).(cy+1) then (* East *) Queue.add (cx, cy+1, 1) q ;
|
end;
|
||||||
|
if is_valid (cx-1) (cy) lines cols && gd.laby.(cx-1).(cy) = 2 then begin (* Crate at North *)
|
||||||
|
current_status := EscapeDeath ;
|
||||||
|
action := 1;
|
||||||
|
if debug then Printf.printf "Fire in the hole!\n" ;
|
||||||
|
raise (ReturnInt 4) ;
|
||||||
|
end;
|
||||||
|
if is_valid (cx) (cy+1) lines cols && gd.laby.(cx).(cy+1) = 2 then begin (* Crate at East *)
|
||||||
|
current_status := EscapeDeath ;
|
||||||
|
action := 1;
|
||||||
|
if debug then Printf.printf "Fire in the hole!\n" ;
|
||||||
|
raise (ReturnInt 4) ;
|
||||||
|
end;
|
||||||
|
if is_valid (cx) (cy-1) lines cols && gd.laby.(cx).(cy-1) = 2 then begin (* Crate at West *)
|
||||||
|
current_status := EscapeDeath ;
|
||||||
|
action := 1;
|
||||||
|
if debug then Printf.printf "Fire in the hole!\n" ;
|
||||||
|
raise (ReturnInt 4) ;
|
||||||
|
end;
|
||||||
|
|
||||||
while not (Queue.is_empty q) do
|
(* go to one without stepping into a dangerous tile *)
|
||||||
let (cx, cy, dir) = Queue.pop q in
|
if is_valid (cx+1) (cy) lines cols && has_a_safe_path (cx+1) (cy) gd.dt 0 then raise (ReturnInt 2) ; (* South *)
|
||||||
Hashtbl.add visited (cx, cy, 2) 1 ;
|
if is_valid (cx-1) (cy) lines cols && has_a_safe_path (cx-1) (cy) gd.dt 1 then raise (ReturnInt 0) ; (* North *)
|
||||||
if gd.laby.(cx).(cy) = 2 then
|
if is_valid (cx) (cy+1) lines cols && has_a_safe_path (cx) (cy+1) gd.dt 2 then raise (ReturnInt 1) ; (* East *)
|
||||||
raise (ReturnInt dir)
|
if is_valid (cx) (cy-1) lines cols && has_a_safe_path (cx) (cy-1) gd.dt 3 then raise (ReturnInt 3) ; (* West *)
|
||||||
else begin
|
|
||||||
(* add neighbors *)
|
|
||||||
if cx <> 0 && Hashtbl.find_opt visited (cx-1, cy, 2) = None && dgs.(cx-1).(cy) <> Blocked then (* North *) Queue.add (cx-1, cy, dir) q ;
|
|
||||||
if cx <> lines -1 && Hashtbl.find_opt visited (cx+1, cy, 2) = None && dgs.(cx+1).(cy) <> Blocked then (* South *) Queue.add (cx+1, cy, dir) q ;
|
|
||||||
if cy <> 0 && Hashtbl.find_opt visited (cx, cy-1, 2) = None && dgs.(cx).(cy-1) <> Blocked then (* West *) Queue.add (cx, cy-1, dir) q ;
|
|
||||||
if cy <> cols -1 && Hashtbl.find_opt visited (cx, cy+1, 2) = None && dgs.(cx).(cy+1) <> Blocked then (* East *) Queue.add (cx, cy+1, dir) q ;
|
|
||||||
end
|
|
||||||
done;
|
|
||||||
|
|
||||||
(* no crates ? Go for kills *)
|
(* no crates ? Go for kills *)
|
||||||
if debug then Printf.printf "[explore] Attempt F...\n";
|
if debug then Printf.printf "[crates] Attempt F...\n";
|
||||||
4
|
4
|
||||||
with
|
with
|
||||||
| ReturnInt k -> k ;;
|
| ReturnInt k -> k ;;
|
||||||
|
@ -519,5 +485,5 @@ print_game_data game_d ;;
|
||||||
print_danger_levels dangers ;;
|
print_danger_levels dangers ;;
|
||||||
|
|
||||||
Printf.printf "move at ";;
|
Printf.printf "move at ";;
|
||||||
print_direction (move_safe game_d dangers) ;;
|
print_direction (move_explore game_d dangers) ;;
|
||||||
Printf.printf "\n" ;;
|
Printf.printf "\n" ;;
|
8
tp.txt
8
tp.txt
|
@ -13,3 +13,11 @@
|
||||||
3 3 3 0 0 0 2 2 4 4 0
|
3 3 3 0 0 0 2 2 4 4 0
|
||||||
0 1 0 1 0 1 0 1 0 1 0
|
0 1 0 1 0 1 0 1 0 1 0
|
||||||
0 0 0 2 2 2 2 3 3 2 0
|
0 0 0 2 2 2 2 3 3 2 0
|
||||||
|
|
||||||
|
0 0 2 2 2 2 2 2 2 0 0
|
||||||
|
0 1 2 1 2 1 2 1 2 1 0
|
||||||
|
2 2 2 2 2 2 2 0 2 2 2
|
||||||
|
2 1 0 1 2 1 2 1 2 1 0
|
||||||
|
2 2 2 2 2 2 2 2 2 2 2
|
||||||
|
0 1 2 1 2 1 2 1 0 1 0
|
||||||
|
0 0 2 2 2 2 2 2 2 0 0
|
Loading…
Reference in New Issue