diff --git a/again b/again index 0068d05..0529b2c 100755 Binary files a/again and b/again differ diff --git a/again.cmi b/again.cmi index f499970..7970f1a 100644 Binary files a/again.cmi and b/again.cmi differ diff --git a/again.cmo b/again.cmo index f453c97..5f20e1a 100644 Binary files a/again.cmo and b/again.cmo differ diff --git a/again.cmx b/again.cmx index fb40e82..6eb26fa 100644 Binary files a/again.cmx and b/again.cmx differ diff --git a/again.ml b/again.ml index 2e4659b..46281d6 100644 --- a/again.ml +++ b/again.ml @@ -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 diff --git a/again.o b/again.o index 7a3cfed..02ffa59 100644 Binary files a/again.o and b/again.o differ diff --git a/compilZ.sh b/compilZ.sh index 1913351..b7beaf8 100644 --- a/compilZ.sh +++ b/compilZ.sh @@ -1 +1 @@ -ocamlc again.ml -o again \ No newline at end of file +ocamlfind ocamlopt -linkpkg -package unix again.ml -o again \ No newline at end of file diff --git a/entrees.txt b/entrees.txt index b639384..1f5cdc3 100644 --- a/entrees.txt +++ b/entrees.txt @@ -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 diff --git a/sortie.txt b/sortie.txt index 92880af..4a3b60a 100644 --- a/sortie.txt +++ b/sortie.txt @@ -1 +1 @@ -1 1 \ No newline at end of file +0 0 \ No newline at end of file