added claim function + tweaked some numbers

This commit is contained in:
Alexandre 2024-11-11 21:40:29 +01:00
parent 77f6ec5c5e
commit 1f47adad37
6 changed files with 202 additions and 71 deletions

View File

@ -1,24 +1,26 @@
182.62000000000037
2
205.50000000000065
3
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 3 3 2 0 0 5 5 5 5 5 5 5 1
1 3 1 3 1 3 1 0 1 0 1 2 1 0 1 5 1 5 1 5 1
1 3 3 3 3 3 3 3 2 3 2 2 2 2 5 5 5 5 5 5 1
1 3 1 3 1 3 1 3 1 3 1 2 1 2 1 5 1 5 1 5 1
1 3 0 3 3 3 3 3 3 3 3 3 0 2 0 5 5 5 5 5 1
1 0 1 0 1 3 1 3 1 3 1 4 1 0 1 5 1 5 1 2 1
1 0 0 6 6 3 3 3 3 3 0 4 0 5 5 5 5 5 4 4 1
1 0 1 6 1 6 1 3 1 3 1 4 1 4 1 5 1 4 1 4 1
1 6 6 6 6 6 6 4 4 3 4 4 4 4 4 4 4 4 5 4 1
1 6 1 6 1 6 1 6 1 3 1 4 1 4 1 5 1 4 1 4 1
1 6 6 6 6 6 6 6 0 3 4 4 4 4 4 4 4 4 4 4 1
1 6 3 3 3 4 4 4 4 6 6 6 6 6 6 4 6 5 6 6 1
1 6 1 3 1 6 1 6 1 4 1 6 1 6 1 4 1 5 1 5 1
1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 4 6 5 1
1 6 1 3 1 6 1 6 1 4 1 6 1 6 1 4 1 4 1 5 1
1 6 6 6 6 6 6 6 6 4 6 6 4 6 4 4 4 4 4 4 1
1 6 1 6 1 6 1 6 1 3 1 6 1 6 1 4 1 4 1 4 1
1 6 6 6 6 6 6 4 4 4 4 6 4 4 4 4 4 4 4 4 1
1 6 1 6 1 6 1 6 1 3 1 6 1 6 1 4 1 4 1 4 1
1 6 6 6 6 3 3 3 4 3 3 6 3 3 3 4 4 4 4 4 1
1 6 1 6 1 6 1 6 1 3 1 6 1 3 1 3 1 4 1 4 1
1 6 6 6 3 6 3 3 3 3 3 3 3 3 3 3 3 4 3 4 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
2
6 11 2 185.56136399999963
9 13 4 186.85000000000056
2
8 13 1 2 3 4 1 3
7 15 2 2 3 2 1 1
1
2 9 1
4
5 9 5 206.50000000000063
5 18 2 207.00000000000085
7 10 5 209.20000000000064
11 15 4 209.69300000000123
3
11 17 1 3 2 4 1 3
3 19 2 1 2 2 1 3
8 9 3 1 4 5 4 3
0

BIN
main

Binary file not shown.

BIN
main.cmi

Binary file not shown.

BIN
main.cmo

Binary file not shown.

227
main.ml
View File

@ -329,6 +329,21 @@ let evaluate_dangers (gd : game_data) =
done
done ;
(* add players *)
for p = 0 to gd.nplayers -1 do
if p <> gd.player_id then begin
let player_dgr = (Danger (gd.dt +. 5.5)) in
for d = 0 to 3 do
for o = 0 to gd.players.(p).bomb_radius do
let nx = gd.players.(p).xy.x + o*(fst order.(d))
and ny = gd.players.(p).xy.y + o*(snd order.(d)) in
if is_valid nx ny lines cols then
res.(nx).(ny) <- danger_priority res.(nx).(ny) player_dgr ;
done
done
end
done;
(* add bonuses *)
for b = 0 to gd.nboosts -1 do
res.(gd.boosts.(b).xy.x).(gd.boosts.(b).xy.y) <- danger_priority (res.(gd.boosts.(b).xy.x).(gd.boosts.(b).xy.y)) Bonus
@ -401,8 +416,10 @@ let cell_values (gd : game_data) =
let cx = ln + w*(fst order.(dir))
and cy = cl + w*(snd order.(dir)) in
if not !halt && is_valid (cx) (cy) lines cols then begin
if gd.laby.(cx).(cy) <> 1 && gd.laby.(cx).(cy) <> 2 then (* non-wall *)
if gd.laby.(cx).(cy) = 0 then (* unclaimed tile *)
res.(cx).(cy) <- res.(cx).(cy) + 1
else if gd.laby.(cx).(cy) >= 3 then (* opponent tile *)
res.(cx).(cy) <- res.(cx).(cy) + 2
else
halt := true ;
end
@ -486,7 +503,6 @@ let has_a_safe_path_origin_2 (cx0 : int) (cy0 : int) (lines : int) (cols : int)
Hashtbl.add visited (cx0, cy0) 1 ;
Queue.add (cx0+1, cy0, simt +. interval, 2) q ;
Queue.add (cx0-1, cy0, simt +. interval, 0) q ;
Queue.add (cx0, cy0+1, simt +. interval, 1) q ;
@ -498,6 +514,7 @@ let has_a_safe_path_origin_2 (cx0 : int) (cy0 : int) (lines : int) (cols : int)
let (cx, cy, cur_t, direct) = Queue.pop q in
if (Hashtbl.find_opt visited (cx, cy) = None && is_valid cx cy lines cols && level_of_danger dgs.(cx).(cy) >= cur_t) then begin
(* cell is unvisited, wont kill the player and is within range *)
Hashtbl.add visited (cx, cy) 1 ;
if cur_t > simt +. (float_of_int maxdepth) *. interval then (* too deep *)
raise (ReturnInt 4)
@ -526,48 +543,9 @@ let has_a_safe_path_origin_2 (cx0 : int) (cy0 : int) (lines : int) (cols : int)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let is_safe = function
| Safe | Danger _ | Bonus -> true
| Fatal _ | Blocked -> false ;;
let move_safe (gd : game_data) (dgs : danger array array) =
(* use this whenever you are standing on a non-safe tile *)
(* Strat : find the shortest, safest path *)
let pid = gd.player_id in
let interval = Float.pow 0.9 (float_of_int gd.players.(pid).nspeed) in
if debug_all then Printf.fprintf stderr "I = %f\n" interval ;
let lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) in
(* 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 begin
current_status := BlowUpCrates ;
raise (ReturnInt 4) ;
end;
(*let result = has_a_safe_path (cx) (cy) gd.dt in*)
let result = has_a_safe_path_origin_2 cx cy lines cols gd.dt interval gd dgs [|Bonus|] [||] [|Blocked|] [||] 20 in
if result <> 4 then result else begin
let result2 = has_a_safe_path_origin_2 cx cy lines cols gd.dt interval gd dgs [|Safe|] [||] [|Blocked|] [||] 80 in
if result2 <> 4 then result2
else begin
(* you're probably dead if the code reaches here... *)
if debug_all then Printf.fprintf stderr "[escape] Attempt F...\n";
Printf.fprintf stderr "well shit\n" ;
4
end
end
with
| ReturnInt k -> k ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let contains_crate (gd : game_data) =
Array.fold_left
(fun b1 lst -> b1 || (Array.fold_left (fun b2 tile -> b2 || (tile = 2)) false lst)) false gd.laby ;;
let is_a_crate_nearby (gd : game_data) (dgs : danger array array) =
let pid = gd.player_id
@ -622,7 +600,7 @@ let move_explore (gd: game_data) (dgs : danger array array) =
res2
end
else begin
if false && exit then (* TODO *)
if exit then (* TODONE *)
current_status := ClaimLand ;
Printf.fprintf stderr "Exited.\n" ;
4
@ -672,9 +650,157 @@ let move_explore (gd: game_data) (dgs : danger array array) =
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let cell_profit (d_from_p : int) (gain : int) =
(100000 * gain * (1 + ln_b 7 gain)) / d_from_p ;;
let move_claim (gd : game_data) (dgs : danger array array) (gns : int array array) =
let lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) in
let pid = gd.player_id in
let cxi = gd.players.(pid).xy.x
and cyi = gd.players.(pid).xy.y in
let interval = Float.pow 0.9 (float_of_int gd.players.(pid).nspeed) in
let distances = Array.make_matrix lines cols (-1) in
(* 1st BFS to calculate the distances *)
let visited = Hashtbl.create 100 in
let q = Queue.create () in
Hashtbl.add visited (cxi, cyi) 1 ;
distances.(cxi).(cyi) <- 1 ;
Queue.add (cxi+1, cyi, gd.dt +. interval, 2) q ;
Queue.add (cxi-1, cyi, gd.dt +. interval, 2) q ;
Queue.add (cxi, cyi+1, gd.dt +. interval, 2) q ;
Queue.add (cxi, cyi-1, gd.dt +. interval, 2) q ;
while not (Queue.is_empty q) do
let (cx, cy, cur_t, dist) = Queue.pop q in
if (Hashtbl.find_opt visited (cx, cy) = None && is_valid cx cy lines cols && dgs.(cx).(cy) <> Blocked && level_of_danger dgs.(cx).(cy) >= cur_t) then begin
(* cell is unvisited, is not a wall, wont kill the player and is within range *)
Hashtbl.add visited (cx, cy) 1 ;
distances.(cx).(cy) <- dist ;
for dir = 0 to 3 do
let newx = cx + fst order.(dir)
and newy = cy + snd order.(dir) in
Queue.add (newx, newy, cur_t +. interval, dist+1) q
done
end
done;
(* compute the best value *)
let maxi_gain = ref 0 in
let maxi_i = ref (-1)
and maxi_j = ref (-1) in
Array.iteri
(fun i lst -> Array.iteri
(
fun j elt ->
if (distances.(i).(j) <> -1) then begin maxi_gain := max (!maxi_gain) (cell_profit distances.(i).(j) gns.(i).(j)); maxi_i := i ; maxi_j := j end
)
lst
)
gd.laby ;
(* 2nd BFS to find the direction, if you're not standing on the tile *)
try
if cell_profit distances.(cxi).(cyi) gns.(cxi).(cyi) = !maxi_gain then begin
if gd.players.(pid).nbomb_atonce > 0 then begin
(* simulate the placement of a bomb to ensure a safe escape route*)
let bsize = gd.players.(pid).bomb_radius in
let bomb_hash = Hashtbl.create (4 * (bsize +1)) in
let saved_dgs = Hashtbl.create (4 * (bsize +1)) in
for dir = 0 to 3 do
for w = 0 to bsize do
Hashtbl.add bomb_hash (cxi + w*(fst order.(dir)), cyi + w*(snd order.(dir))) (Danger (gd.dt +. 5.5)) ;
done
done;
Hashtbl.iter
(fun (kx, ky) v ->
if is_valid kx ky lines cols then begin
Hashtbl.add saved_dgs (kx, ky) dgs.(kx).(ky) ;
dgs.(kx).(ky) <- danger_priority dgs.(kx).(ky) v
end
)
bomb_hash ;
let result0 = has_a_safe_path_origin_2 cxi cyi lines cols gd.dt interval gd dgs [|Safe; Bonus|] [||] [|Blocked|] [||] 80 in
Hashtbl.iter (fun (k1, k2) v -> dgs.(k1).(k2) <- v) saved_dgs ;
if result0 <> 4 then begin
action := 1 ;
current_status := EscapeDeath ;
raise (ReturnInt result0)
end
end;
raise (ReturnInt 4)
end
else if !maxi_i = (-1) then begin
current_status := EscapeDeath ;
raise (ReturnInt (has_a_safe_path_origin_2 cxi cyi lines cols gd.dt interval gd dgs [|Bonus; Safe|] [||] [|Blocked|] [||] 80))
end
else begin
let memo = gd.laby.(!maxi_i).(!maxi_j) in
gd.laby.(!maxi_i).(!maxi_j) <- (-2) ;
let result = has_a_safe_path_origin_2 cxi cyi lines cols gd.dt interval gd dgs [||] [|-2|] [|Blocked|] [||] 80 in
gd.laby.(!maxi_i).(!maxi_j) <- memo ;
result
end
with
| ReturnInt k -> k ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let move_safe (gd : game_data) (dgs : danger array array) (gns : int array array)=
(* use this whenever you are standing on a non-safe tile *)
(* Strat : find the shortest, safest path *)
let pid = gd.player_id in
let interval = Float.pow 0.9 (float_of_int gd.players.(pid).nspeed) in
if debug_all then Printf.fprintf stderr "I = %f\n" interval ;
let lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) in
(* BFS to find the nearest safe spot (if it exists) *)
try
(* 0. if you're standing on a safe tile, switch mode *)
let (cx, cy) = (gd.players.(pid).xy.x, gd.players.(pid).xy.y) in
if dgs.(cx).(cy) = Safe then begin
if contains_crate gd then begin
current_status := BlowUpCrates ;
raise (ReturnInt (move_explore gd dgs)) ;
end else begin
current_status := ClaimLand ;
raise (ReturnInt (move_claim gd dgs gns)) ;
end
end;
(*let result = has_a_safe_path (cx) (cy) gd.dt in*)
let result = has_a_safe_path_origin_2 cx cy lines cols gd.dt interval gd dgs [|Bonus|] [||] [|Blocked|] [||] 20 in
if result <> 4 then result else begin
let result2 = has_a_safe_path_origin_2 cx cy lines cols gd.dt interval gd dgs [|Safe|] [||] [|Blocked|] [||] 80 in
if result2 <> 4 then result2
else begin
(* you're probably dead if the code reaches here... *)
Printf.fprintf stderr "well shit\n" ;
4
end
end
with
| ReturnInt k -> k ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let update_strat (gd : game_data) (dgs : danger array array) = match dgs.(gd.players.(gd.player_id).xy.x).(gd.players.(gd.player_id).xy.y) with
| Safe -> ()
| Danger k -> current_status := EscapeDeath
| Danger k when k < 3.0 -> current_status := EscapeDeath
| Danger k -> ()
| Bonus -> ()
| Fatal k -> (* should not happen *) current_status := EscapeDeath
| Blocked -> failwith "did you just suffocate the player ?" ;;
@ -691,6 +817,8 @@ let debug_game_data (gd : game_data) =
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
Printf.fprintf stderr "XXXXXXXX\n" ;;
let game_d = parse_input "entrees.txt" ;;
let dangers = evaluate_dangers game_d ;;
let gains = cell_values game_d ;;
@ -711,7 +839,7 @@ let chosen = ref 0 ;;
let main_actions () = match !current_status with
| EscapeDeath ->
chosen := move_safe game_d dangers ;
chosen := move_safe game_d dangers gains ;
Printf.printf "%d " !chosen
| BlowUpCrates ->
if dangers.(game_d.players.(game_d.player_id).xy.x).(game_d.players.(game_d.player_id).xy.y) = Safe then begin
@ -720,11 +848,12 @@ let main_actions () = match !current_status with
end
else begin
current_status := EscapeDeath ;
chosen := move_safe game_d dangers ;
chosen := move_safe game_d dangers gains ;
Printf.printf "%d " !chosen
end
| ClaimLand ->
()
chosen := move_claim game_d dangers gains ;
Printf.printf "%d " !chosen
| KillPlayers ->
() ;;

View File

@ -1 +1 @@
1
2