diff --git a/entrees.txt b/entrees.txt index 5145141..75b2d07 100644 --- a/entrees.txt +++ b/entrees.txt @@ -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 diff --git a/main b/main index ef1fc65..ae859d2 100755 Binary files a/main and b/main differ diff --git a/main.cmi b/main.cmi index bd5ae92..3bc2c54 100644 Binary files a/main.cmi and b/main.cmi differ diff --git a/main.cmo b/main.cmo index 5b66a00..d713901 100644 Binary files a/main.cmo and b/main.cmo differ diff --git a/main.ml b/main.ml index c39c49b..b9c1383 100755 --- a/main.ml +++ b/main.ml @@ -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 -> () ;; diff --git a/main_2.sav b/main_2.sav index 56a6051..d8263ee 100644 --- a/main_2.sav +++ b/main_2.sav @@ -1 +1 @@ -1 \ No newline at end of file +2 \ No newline at end of file