diff --git a/again b/again index 4bf00b2..7feb98f 100755 Binary files a/again and b/again differ diff --git a/again.cmi b/again.cmi index 1a0daca..f69c408 100644 Binary files a/again.cmi and b/again.cmi differ diff --git a/again.cmx b/again.cmx index cb6bbd4..126a2d9 100644 Binary files a/again.cmx and b/again.cmx differ diff --git a/again.ml b/again.ml index 75d41ab..a67e925 100644 --- a/again.ml +++ b/again.ml @@ -7,6 +7,7 @@ TODO : *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) +Random.self_init () ;; let debug_all = false ;; let logg = true ;; @@ -68,6 +69,9 @@ and default_boost = { and useless = ref 0 ;; +let fodder_x = ref 0 +and fodder_y = ref 0 ;; + type game_data = { mutable dt : float ; mutable player_id : int ; @@ -482,6 +486,32 @@ 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) = + (* 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 + try + aux start_x start_y 0; + (-1) ; + with + | ReturnInt b -> b ;; + +(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) +(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) + let amt_free_adj_spaces (gd : game_data) (x : int) (y : int) = let lines = Array.length gd.laby and cols = Array.length gd.laby.(0) in @@ -492,9 +522,9 @@ let amt_free_adj_spaces (gd : game_data) (x : int) (y : int) = 0 order ;; -let max_depth = 4 ;; +let max_depth = 3 ;; let max_spacing = 3 ;; -let is_player_nearby (gd : game_data) = +let is_player_nearby (gd : game_data) (res_x : int ref) (res_y : int ref) = let pid = gd.player_id in let lines = Array.length gd.laby and cols = Array.length gd.laby.(0) in @@ -504,8 +534,11 @@ let is_player_nearby (gd : game_data) = 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 Hashtbl.add visited (x, y) 1; - if Array.exists (fun (p : player) -> p.xy.x = x && p.xy.y = y) gd.players then + if Array.exists (fun (p : player) -> p.xy.x = x && p.xy.y = y) gd.players then begin + res_x := x ; + res_y := y ; raise (ReturnBool true) + end else begin for dir = 0 to 3 do dfs (x + fst order.(dir)) (y + snd order.(dir)) (depth+1) @@ -526,7 +559,7 @@ let is_player_nearby (gd : game_data) = | ReturnBool b -> b ;; let is_dead_end (gd : game_data) (xstart : int) (ystart : int) (xban : int) (yban : int) = - if not (is_player_nearby gd) then + if not (is_player_nearby gd fodder_x fodder_y) then false (* if no one is nearby, it's safe to go there (hopefully) *) else begin let lines = Array.length gd.laby @@ -554,10 +587,11 @@ 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) = - if not (is_player_nearby gd) then + let pl_x = ref 0 + and pl_y = ref 0 in + if not (is_player_nearby gd pl_x pl_y) then false (* if no one is nearby, it's safe to go there (hopefully) *) else begin - let n_34 = ref 0 in let lines = Array.length gd.laby and cols = Array.length gd.laby.(0) in let visited = Hashtbl.create 50 in @@ -571,7 +605,9 @@ let has_multiple_escapes (gd : game_data) (xstart : int) (ystart : int) (xban : | 1 | 2 -> for dir = 0 to 3 do aux (x + fst order.(dir)) (y + snd order.(dir)) done - | _ -> if !n_34 >= 1 then raise (ReturnBool false) else incr n_34 + | _ -> + if tile_distance gd x y !pl_x !pl_y >= max_spacing then + raise (ReturnBool false) ; end end in @@ -622,6 +658,59 @@ let is_dead_all (dgs : danger_map) (x : int) (y : int) (t : float) (dt : float) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) + +let goto_tile (gd : game_data) (dgs : danger_map) (x0 : int) (y0 : int) (end_x : int) (end_y : int) (stime : float) = + let lines = Array.length gd.laby + and cols = Array.length gd.laby.(0) in + + let pid = gd.player_id in + + let visited = Hashtbl.create 100 in + let q = Queue.create () in + let interval = Float.pow (0.9) (float_of_int gd.players.(gd.player_id).nspeed) in + + (*Queue.add (x0, y0, stime +. interval, 4, 1) q ;*) + + Queue.add (x0+1, y0, stime +. interval, 2) q ; + Queue.add (x0-1, y0, stime +. interval, 0) q ; + Queue.add (x0, y0+1, stime +. interval, 1) q ; + Queue.add (x0, y0-1, stime +. interval, 3) q ; + + try + while not (Queue.is_empty q) do + let (x, y, ct, direction) = Queue.pop q in + if is_valid x y lines cols && gd.laby.(x).(y) <> 1 && gd.laby.(x).(y) <> 2 then begin (* within the map *) + if Hashtbl.find_opt visited (x, y) = None then begin (* has not been visited yet *) + Hashtbl.add visited (x, y) 1 ; + if + not (is_dead_all dgs x y ct interval false) && + ct < stime +. 70. *. interval && + not (Array.fold_left (fun acc (b : bomb) -> acc || (b.xy.x = x && b.xy.y = y)) false gd.bombs) + 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)) && + (x = end_x && y = end_y) + then begin + raise (ReturnInt direction) + end; + (*Queue.add (x, y, ct +. interval, direction) q ;*) + if not (x0 == x && y0 == y) then begin + for dir = 0 to 3 do + Queue.add (x + (fst order.(dir)), y + (snd order.(dir)), ct +. interval, direction) q ; + done; + end + end + end + end + done; + 4 ; + with + | ReturnInt k -> k ;; + +(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) +(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) let contains_crate (gd : game_data) = Array.fold_left @@ -713,7 +802,7 @@ 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 && amt_free_adj_spaces gd x y = 1)) && (* is not a dead-end (==> ez kill) *) + (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 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 *) @@ -774,7 +863,109 @@ let move_crate (gd : game_data) (dgs : danger_map) = (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) +(* let goto_tile (gd : game_data) (dgs : danger_map) (x0 : int) (y0 : int) (end_x : int) (end_y : int) (stime : float) = *) +let move_land (gd : game_data) (dgs : danger_map) (gns : int array array) = + let pid = gd.player_id in + let cxi = gd.players.(pid).xy.x + and cyi = gd.players.(pid).xy.y in + let max_map = Array.mapi + (fun i line -> Array.mapi + (fun j elt -> + if (gd.laby.(i).(j) <> 1 && gd.laby.(i).(j) <> 2 && not (Array.fold_left (fun acc (b : bomb) -> acc || (b.xy.x = i && b.xy.y = j)) false gd.bombs)) then + (elt, i, j) + else + (-1, i, j) + ) + line + ) + gns + in + let (_, xmax, ymax) = Array.fold_left + (fun (vm, xm, ym) line -> + let (otm, xtm, ytm) = Array.fold_left + (fun (vm2, xm2, ym2) (i, j, v) -> + if vm2 > v then + (vm2, xm2, ym2) + else + (i, j, v) + ) (-1, -1, -1) line + in + if vm > otm then + (vm, xm, ym) + else + (otm, xtm, ytm) + ) (-1, -1, -1) max_map + in + Printf.fprintf stderr "(%d %d) -> (%d %d)\n" cxi cyi xmax ymax ; + try + if cxi = xmax && cyi = ymax && (is_empty_lst dgs.explosionTimes.(cxi).(cyi)) then begin (* standing on right tile *) + if gd.players.(pid).nbomb_atonce > 0 then begin + if logg then Printf.fprintf stderr "trying...\n" ; + let saved = simulate_bomb_deconstruct dgs cxi cyi gd.players.(pid).bomb_radius (gd.dt +. 5.5) in + let result = goto_tile gd dgs cxi cyi xmax ymax gd.dt in + if result <> 4 then begin + action := 1 ; + raise (ReturnInt result) ; + end; + reverse_simulate_bomb dgs saved ; + raise (ReturnInt 4) + end + else + raise (ReturnInt 4) + end + else + raise (ReturnInt (goto_tile gd dgs cxi cyi xmax ymax gd.dt)) + with + | ReturnInt k -> k ;; + +let draw_random (gd : game_data) (infx : int) (infy : int) (lines : int) (cols : int) (dmin : int) = + (* get a random, valid tile *) + let xres = ref (-1) + and yres = ref (-1) in + while not (is_valid !xres !yres lines cols && gd.laby.(!xres).(!yres) <> 1 && gd.laby.(!xres).(!yres) <> 2 && not (Array.fold_left (fun acc (b : bomb) -> acc || (b.xy.x = !xres && b.xy.y = !yres)) false gd.bombs)) do + xres := infx + Random.int (lines - infx) ; + yres := infy + Random.int (cols - infy) ; + done; + (!xres, !yres) ;; + +let nloops = 40 ;; +let move_land_2 (gd : game_data) (dgs : danger_map) (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 + + try + for azertyiop = 0 to nloops -1 do + let (x, y) = draw_random gd 0 0 lines cols 4 in + let result_0 = goto_tile gd dgs cxi cyi x y gd.dt in + if result_0 <> 4 then begin + if gd.players.(pid).nbomb_atonce > 0 && not (Array.fold_left (fun acc (b : bomb) -> acc || (b.xy.x = cxi && b.xy.y = cyi)) false gd.bombs) then begin + if logg then Printf.fprintf stderr "trying...\n" ; + let _ = simulate_bomb_deconstruct dgs cxi cyi gd.players.(pid).bomb_radius (gd.dt +. 5.5) in + let result = goto_tile gd dgs cxi cyi x y gd.dt in + if result <> 4 then begin + action := 1 ; + raise (ReturnInt result) + end + end; + raise (ReturnInt result_0) + end + done; + 4 + with + | ReturnInt k -> k ;; + +(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) +(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) + +let exists_crate (gd : game_data) = + Array.exists + (fun line -> Array.exists (fun tile -> tile = 2) line) + gd.laby ;; (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) @@ -791,11 +982,21 @@ print_dangers danger_data ;;*) get_meta_info game_map.player_id ;; (*Printf.fprintf stderr "\n" ;; print_dangers danger_data ;;*) +let direction = ref 4 ;; -let direction = move_crate game_map danger_data ;; +if exists_crate game_map then begin + Printf.fprintf stderr "Crates\n" ; + direction := move_crate game_map danger_data +end +else begin + Printf.fprintf stderr "No crates\n" ; + (*direction := move_land game_map danger_data gain_map *) + direction := move_land_2 game_map danger_data gain_map +end ;; -Printf.printf "%d %d" direction !action ; -if true || logg then Printf.fprintf stderr "[player %d] %d %d (at time %f)\n" game_map.player_id direction !action game_map.dt; + +Printf.printf "%d %d" !direction !action ; +if true || logg then Printf.fprintf stderr "[player %d] %d %d (at time %f)\n" game_map.player_id !direction !action game_map.dt; set_meta_info game_map.player_id ;; let __end = Unix.gettimeofday() ;; diff --git a/again.o b/again.o index 6472d13..115750f 100644 Binary files a/again.o and b/again.o differ diff --git a/entrees.txt b/entrees.txt index 879e27d..a9523fb 100644 --- a/entrees.txt +++ b/entrees.txt @@ -1,26 +1,29 @@ -150.01600000000056 -3 +225.80000000000052 +0 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 6 6 6 6 6 0 0 5 5 5 5 5 5 5 5 5 1 -1 3 1 3 1 3 1 6 1 0 1 5 1 5 1 5 1 5 1 5 1 -1 3 3 3 3 3 3 6 6 4 6 6 5 5 5 5 5 5 5 5 1 -1 3 1 3 1 3 1 3 1 4 1 5 1 2 1 0 1 5 1 0 1 -1 3 3 3 3 3 6 6 6 4 2 0 2 2 2 2 2 0 2 2 1 -1 0 1 3 1 3 1 3 1 4 1 0 1 2 1 0 1 2 1 2 1 -1 2 6 3 3 3 3 3 3 4 0 0 2 0 0 4 0 0 0 2 1 -1 0 1 6 1 3 1 3 1 4 1 4 1 4 1 4 1 4 1 2 1 -1 6 0 6 6 6 6 4 4 4 4 4 4 4 4 4 4 4 0 0 1 -1 6 1 0 1 3 1 6 1 0 1 0 1 4 1 4 1 4 1 4 1 -1 6 6 6 3 3 0 0 2 2 0 4 4 4 4 4 4 4 4 4 1 +1 3 6 6 5 5 5 4 5 5 5 5 5 5 5 3 3 3 3 5 1 +1 3 1 6 1 0 1 4 1 5 1 5 1 5 1 3 1 3 1 5 1 +1 3 3 3 4 4 4 4 4 4 5 5 5 5 5 3 5 3 5 5 1 +1 3 1 3 1 3 1 4 1 4 1 5 1 5 1 3 1 3 1 5 1 +1 3 3 3 4 4 4 4 4 4 4 5 3 3 3 3 3 3 3 3 1 +1 3 1 3 1 3 1 4 1 4 1 5 1 5 1 3 1 3 1 5 1 +1 3 3 3 3 3 3 5 5 5 5 5 5 5 5 3 3 3 3 3 1 +1 0 1 3 1 3 1 4 1 4 1 5 1 3 1 3 1 3 1 4 1 +1 3 3 3 3 3 3 3 3 3 3 5 3 3 3 3 3 3 3 4 1 +1 6 1 3 1 3 1 4 1 5 1 5 1 3 1 3 1 3 1 4 1 +1 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 5 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -2 -4 17 2 150.60000000000025 -9 13 3 151.16750000000042 -4 -7 17 0 1 6 1 2 1 -8 15 1 4 5 3 1 2 -3 19 2 2 0 2 1 3 -4 9 3 3 1 3 1 2 -1 -11 10 3 +7 +3 13 5 225.9000000000005 +8 9 2 225.91200000000183 +9 9 2 226.64100000000184 +4 13 5 226.8000000000005 +5 13 5 227.7000000000005 +6 13 5 228.6000000000005 +11 11 3 230.7100000000007 +3 +7 15 0 1 0 5 1 2 +9 12 1 3 0 2 3 3 +10 11 2 2 1 3 3 0 +0 diff --git a/iachallenge2024_bomberman_tkinter.py b/iachallenge2024_bomberman_tkinter.py index 9319f02..c048f8a 100644 --- a/iachallenge2024_bomberman_tkinter.py +++ b/iachallenge2024_bomberman_tkinter.py @@ -226,13 +226,13 @@ def ln_b(n, b): def affiche_empires(canvas, joueurs, plateauCouleur): scores = compte_couleur(plateauCouleur, len(joueurs)) canvas.create_polygon( - 0, 0, - 0 + X_LARGEUR_EMPIRES, 0, - 0 + X_LARGEUR_EMPIRES, 0 + Y_LARGEUR_EMPIRES, - 0, 0 + Y_LARGEUR_EMPIRES, + X0_EMPIRES, Y0_EMPIRES - Y_STEP_CLAIMS, + X0_EMPIRES + X_LARGEUR_EMPIRES, Y0_EMPIRES - Y_STEP_CLAIMS, + X0_EMPIRES + X_LARGEUR_EMPIRES, Y0_EMPIRES + Y_LARGEUR_EMPIRES, + X0_EMPIRES, Y0_EMPIRES + Y_LARGEUR_EMPIRES, fill="black") for k in range(len(scores)): - canvas.create_text(X_LARGEUR_EMPIRES/2, Y0_EMPIRES + k*Y_STEP_CLAIMS, text=str(scores[k]), fill=COULEURS_JOUEURS[k]) + canvas.create_text(X0_EMPIRES + X_LARGEUR_EMPIRES/2, Y0_EMPIRES + k*Y_STEP_CLAIMS, text=str(scores[k]), fill=COULEURS_JOUEURS[k]) def affiche_infos(canvas, joueurs, plateauCouleur): canvas.delete(ALL) @@ -452,10 +452,11 @@ TAILLE_OVERLAY = 15 NOMBRE_SPARKS = 10 SIZE_SPARKS = 12 +X0_EMPIRES = 600 Y0_EMPIRES = 20 Y_STEP_CLAIMS = 40 -X_LARGEUR_EMPIRES = 400 +X_LARGEUR_EMPIRES = 60 Y_LARGEUR_EMPIRES = 180 def decision(programme, indiceJoueur, plateau, plateauCouleur, bombes, joueurs, powerups, instant): @@ -499,8 +500,8 @@ def simulation(strategies): return execute_evenement(evenements, evenement, plateau, plateauCouleur, bombes, joueurs, powerups, pieges) affiche_plateau(canvas, plateau, plateauCouleur, bombes, joueurs, powerups) - affiche_empires(canvasInfosLand, joueurs, plateauCouleur) # very laggy for some reason affiche_infos(canvasInfosJoueurs, joueurs, plateauCouleur) + affiche_empires(canvasInfosJoueurs, joueurs, plateauCouleur) # very laggy for some reason temps = int((evenements[0][0]-evenement[0])/3*200) if temps != 0: fenetre.after(temps, pas_de_jeu) @@ -535,9 +536,6 @@ def simulation(strategies): canvasInfosJoueurs = Canvas(width = LARGEUR_INFOS, height=len(joueurs)*HAUTEUR_JOUEUR) canvasInfosJoueurs.pack() - canvasInfosLand = Canvas(width = X_LARGEUR_EMPIRES, height=Y_LARGEUR_EMPIRES) - canvasInfosLand.pack() - pas_de_jeu() fenetre.mainloop() diff --git a/sortie.txt b/sortie.txt index 389086a..69035af 100644 --- a/sortie.txt +++ b/sortie.txt @@ -1 +1 @@ -2 0 \ No newline at end of file +3 0 \ No newline at end of file