added exploration function
This commit is contained in:
parent
1ed4d9b75b
commit
a7da366a02
120
main.ml
120
main.ml
|
@ -94,6 +94,8 @@ exception ReturnInt of int ;;
|
|||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||
|
||||
let current_status = ref BlowUpCrates ;;
|
||||
|
||||
let equal_pt (p1 : pt) (p2 : pt) =
|
||||
p1.x = p2.x && p1.y = p2.y ;;
|
||||
|
||||
|
@ -269,6 +271,35 @@ let evaluate_dangers (gd : game_data) =
|
|||
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 *)
|
||||
for b = 0 to gd.nbombs -1 do
|
||||
let m = ref gd.bombs.(b).det_time
|
||||
|
@ -323,6 +354,7 @@ let is_safe = function
|
|||
|
||||
let move_safe (gd : game_data) (dgs : danger array array) =
|
||||
(* 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) *)
|
||||
let pid = gd.player_id in
|
||||
|
||||
let lines = Array.length gd.laby
|
||||
|
@ -330,12 +362,16 @@ let move_safe (gd : game_data) (dgs : danger array array) =
|
|||
|
||||
(* BFS to find the nearest safe spot (if it exists) *)
|
||||
try
|
||||
(* 0. if you're standing on a safe tile, stay there *)
|
||||
let (cx, cy) = (gd.players.(pid).xy.x, gd.players.(pid).xy.y) in
|
||||
if dgs.(cx).(cy) = Safe then
|
||||
raise (ReturnInt 4) ;
|
||||
|
||||
let q = Queue.create () in
|
||||
let visited = Hashtbl.create 100 in
|
||||
|
||||
(* 1. try not to walk on fatal tiles *)
|
||||
if debug then Printf.printf "Attempt 1/3...\n";
|
||||
let (cx, cy) = (gd.players.(pid).xy.x, gd.players.(pid).xy.y) in
|
||||
if debug then Printf.printf "[escape] Attempt 1/3...\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 ;
|
||||
|
@ -356,7 +392,7 @@ let move_safe (gd : game_data) (dgs : danger array array) =
|
|||
done;
|
||||
|
||||
(* 2. find the path that get you off fatal tiles ASAP *)
|
||||
if debug then Printf.printf "Attempt 2/3...\n";
|
||||
if debug then Printf.printf "[escape] Attempt 2/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 ;
|
||||
|
@ -377,7 +413,7 @@ let move_safe (gd : game_data) (dgs : danger array array) =
|
|||
done;
|
||||
|
||||
(* 3. no safe tile within reach (very rare), look out for warning *)
|
||||
if debug then Printf.printf "Attempt 3/3...\n";
|
||||
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 ;
|
||||
|
@ -398,11 +434,85 @@ let move_safe (gd : game_data) (dgs : danger array array) =
|
|||
done;
|
||||
|
||||
(* you're probably dead if the code reaches here *)
|
||||
if debug then Printf.printf "Attempt F...\n";
|
||||
if debug then Printf.printf "[escape] Attempt F...\n";
|
||||
4
|
||||
with
|
||||
| ReturnInt k -> k ;;
|
||||
|
||||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||
|
||||
let move_explore (gd: game_data) (dgs : danger array array) =
|
||||
(* destroy crates *)
|
||||
let pid = gd.player_id in
|
||||
|
||||
let lines = Array.length gd.laby
|
||||
and cols = Array.length gd.laby.(0) in
|
||||
|
||||
(* find nearest crate and blow it up *)
|
||||
try
|
||||
let q = Queue.create () 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 ;
|
||||
|
||||
while not (Queue.is_empty q) do
|
||||
let (cx, cy, dir) = Queue.pop q in
|
||||
Hashtbl.add visited (cx, cy, 1) 1 ;
|
||||
if gd.laby.(cx).(cy) = 2 then
|
||||
raise (ReturnInt dir)
|
||||
else begin
|
||||
(* 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 ;
|
||||
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 ;
|
||||
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 ;
|
||||
end
|
||||
done;
|
||||
|
||||
(* 2. search one anyway *)
|
||||
if debug then Printf.printf "[explore] Attempt 2/2...\n";
|
||||
let (cx, cy) = (gd.players.(pid).xy.x, gd.players.(pid).xy.y) in
|
||||
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 ;
|
||||
|
||||
while not (Queue.is_empty q) do
|
||||
let (cx, cy, dir) = Queue.pop q in
|
||||
Hashtbl.add visited (cx, cy, 2) 1 ;
|
||||
if gd.laby.(cx).(cy) = 2 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).(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 *)
|
||||
if debug then Printf.printf "[explore] Attempt F...\n";
|
||||
4
|
||||
with
|
||||
| ReturnInt k -> k ;;
|
||||
|
||||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
|
||||
|
||||
let game_d = parse_input "input_test.txt" ;;
|
||||
let dangers = evaluate_dangers game_d ;;
|
||||
print_game_data game_d ;;
|
||||
|
|
Loading…
Reference in New Issue