This commit is contained in:
Alexandre 2024-11-13 22:33:31 +01:00
parent 6b980deeef
commit 0a7a37b79b
13 changed files with 752 additions and 56 deletions

BIN
again Executable file

Binary file not shown.

BIN
again.cmi Normal file

Binary file not shown.

BIN
again.cmo Normal file

Binary file not shown.

670
again.ml Normal file
View File

@ -0,0 +1,670 @@
(*
TODO :
- deal with double bombing (DONE)
- well shit ==> dash (DONE (needs dash to be fixed tho))
- deeper analysis on pathfinfing
*)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let debug_all = false ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
type pt = {
x : int ;
y : int ;
}
type bomb = {
xy : pt ;
size : int ;
det_time : float ;
}
type player = {
id : int ;
xy : pt ;
nspeed : int ;
nbomb_atonce : int ;
bomb_radius : int ;
ndash : int ;
ntraps : int ;
}
type boost = {
xy : pt ;
spec : int ;
}
let default_point = {
x = 0 ;
y = 0 ;
}
let default_bomb = {
xy = default_point ;
size = 0 ;
det_time = 0. ;
}
and default_player = {
id = 0 ;
xy = default_point ;
nspeed = 0 ;
nbomb_atonce = 0 ;
bomb_radius = 0 ;
ndash = 0 ;
ntraps = 0 ;
}
and default_boost = {
xy = default_point ;
spec = 0 ;
}
and useless = ref 0 ;;
type game_data = {
mutable dt : float ;
mutable player_id : int ;
mutable laby : int array array ;
mutable nbombs : int ;
mutable bombs : bomb array ;
mutable nplayers : int ;
mutable players : player array ;
mutable nboosts : int ;
mutable boosts : boost array ;
}
type danger_map = {
explosionTimes : (float list) array array ;
bonusMap : bool array array ;
playersMap : (int * int * int) array ;
explodedCrates : bool array array ;
}
type moveType = EscapeDeath | BlowUpCrates | KillPlayers | ClaimLand ;;
exception ReturnInt of int ;;
exception ReturnBool of bool ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let order = [|(1, 0); (-1, 0); (0, 1); (0, -1)|] ;;
let current_status = ref BlowUpCrates ;;
let action = ref 0 ;;
let dash_left = ref 0 ;;
let equal_pt (p1 : pt) (p2 : pt) =
p1.x = p2.x && p1.y = p2.y ;;
let swap arr i j =
let temp = arr.(i) in
arr.(i) <- arr.(j) ;
arr.(j) <- temp ;;
let is_valid i j len hei =
i >= 0 && j >= 0 && i < len && j < hei ;;
let print_direction = function
| 0 -> Printf.fprintf stderr "NORTH "
| 1 -> Printf.fprintf stderr "EAST "
| 2 -> Printf.fprintf stderr "SOUTH "
| 3 -> Printf.fprintf stderr "WEST "
| 4 -> Printf.fprintf stderr "STILL "
| _-> failwith "ERROR : invalid direction" ;;
let delta i j =
if i = j then 1 else 0 ;;
let overwrite_file (filename : string) =
let ptr = open_out filename in
close_out ptr ;;
let rec pop_list elt = function
| [] -> []
| h::t when h = elt -> t
| h::t -> h::(pop_list elt t) ;;
let is_empty_lst = function
| [] -> true
| _ -> false ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let print_game_data (gd : game_data) =
Printf.fprintf stderr "--------------------------------| Board data |--------------------------------\n" ;
Printf.fprintf stderr "Time : %f\n" gd.dt ;
Printf.fprintf stderr "ID : %d\n" gd.player_id ;
Printf.fprintf stderr "Laby [of size %d %d]:\n" (Array.length gd.laby) (Array.length gd.laby.(0));
for l = 0 to Array.length gd.laby -1 do
Printf.fprintf stderr " " ;
for c = 0 to Array.length gd.laby.(l) -1 do
Printf.fprintf stderr "%d " gd.laby.(l).(c) ;
done;
Printf.fprintf stderr "\n"
done ;
Printf.fprintf stderr "Bombs (%d) : \n" gd.nbombs ;
for b = 0 to gd.nbombs -1 do
Printf.fprintf stderr " [Bomb] (at %d %d) (of size %d) (blowing up at %f)\n" gd.bombs.(b).xy.x gd.bombs.(b).xy.y gd.bombs.(b).size gd.bombs.(b).det_time ;
done;
Printf.fprintf stderr "Players (%d) : \n" gd.nplayers ;
for b = 0 to gd.nplayers -1 do
Printf.fprintf stderr " [Player %d] (at %d %d) (holding %d %d %d %d %d)\n" gd.players.(b).id gd.players.(b).xy.x gd.players.(b).xy.y gd.players.(b).nspeed gd.players.(b).nbomb_atonce gd.players.(b).bomb_radius gd.players.(b).ndash gd.players.(b).ntraps ;
done;
Printf.fprintf stderr "Boosts (%d) : \n" gd.nboosts ;
for b = 0 to gd.nboosts -1 do
Printf.fprintf stderr " [Boost] (at %d %d) (of type %d)\n" gd.boosts.(b).xy.x gd.boosts.(b).xy.y gd.boosts.(b).spec ;
done;;
let print_dangers (dgs : danger_map) =
for w = 0 to Array.length dgs.explosionTimes -1 do
for h = 0 to Array.length dgs.explosionTimes.(0) -1 do
Printf.fprintf stderr "%d " (List.length dgs.explosionTimes.(w).(h)) ;
done ;
Printf.fprintf stderr "\n" ;
done ;;
let print_gain_map (map : int array array) =
Printf.fprintf stderr "--------------------------------| Gain levels |--------------------------------\n" ;
for l = 0 to (Array.length map -1) do
for c = 0 to (Array.length map.(l) -1) do
Printf.fprintf stderr "%d " map.(l).(c) ;
done;
Printf.fprintf stderr "\n"
done ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let rec ln_b b = function
| k when k < 0 -> failwith "are you sure about that ?"
| k when k < b -> 0
| k -> 1 + ln_b b (k/b) ;;
let get_meta_info (pid : int) =
let ptr = open_in ("main_"^(string_of_int pid)^".sav") in
let fct0 () = match (int_of_string (input_line ptr)) with
| 0 -> current_status := EscapeDeath
| 1 -> current_status := BlowUpCrates
| 2 -> current_status := ClaimLand
| 3 -> current_status := KillPlayers
| _ -> current_status := EscapeDeath
in
fct0 () ;
try
let resu = int_of_string (input_line ptr) in
dash_left := resu -1;
close_in ptr
with
| End_of_file -> close_in ptr ;;
let set_meta_info (pid : int) =
let ptr = open_out ("main_"^(string_of_int pid)^".sav") in
let fct0 () = match !current_status with
| EscapeDeath -> Printf.fprintf ptr "0"
| BlowUpCrates -> Printf.fprintf ptr "1"
| ClaimLand -> Printf.fprintf ptr "2"
| KillPlayers -> Printf.fprintf ptr "3"
in
fct0 () ;
if !dash_left > 0 then
Printf.fprintf ptr "\n%d" !dash_left ;
close_out ptr ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let int_of_string (str : string) =
String.fold_right (fun ch acc -> let cd = Char.code ch in if cd >= 48 || cd <= 57 then 10*acc + cd - 48 else failwith "not an integer\n") str 0 ;;
let string_of_int (k0 : int) =
String.make (1) (Char.chr (k0 + 48)) ;;
let int_n_of_string (str : string) (n : int) (nlast : int ref) =
let res = Array.make n 0 in
let rec aux idres idstr = match idstr with
| k when k = String.length str || idres >= n ->
nlast := k
| k ->
if str.[k] = ' ' then
aux (idres+1) (k+1)
else begin
let cd = Char.code str.[k] in
if cd >= 48 && cd <= 57 then begin
res.(idres) <- 10 * res.(idres) + cd - 48 ;
aux (idres) (k+1)
end
else
failwith "not an integer (n/n)\n"
end
in
aux 0 0 ;
res ;;
let parse_input (str : string) =
let ptr = open_in str in
let (res : game_data) = {dt = 0. ; player_id = 0 ; laby = [||] ; nbombs = 0 ; bombs = [||] ; nplayers = 0 ; players = [||] ; nboosts = 0 ; boosts = [||] ;} in
try
(* time *)
if debug_all then Printf.fprintf stderr "Time\n" ;
res.dt <- Float.of_string (input_line ptr) ;
(* player_id *)
if debug_all then Printf.fprintf stderr "PID\n" ;
res.player_id <- int_of_string (input_line ptr) ;
(* maze *)
if debug_all then Printf.fprintf stderr "Maze\n" ;
let msize = int_n_of_string (input_line ptr) 2 useless in
res.laby <- Array.make msize.(0) [||] ;
for lane = 0 to msize.(0) -1 do
let psd = input_line ptr in
res.laby.(lane) <- int_n_of_string psd msize.(1) useless ;
done;
(* bombs *)
if debug_all then Printf.fprintf stderr "Boom\n" ;
res.nbombs <- int_of_string (input_line ptr) ;
res.bombs <- Array.make res.nbombs default_bomb ;
for b = 0 to res.nbombs -1 do
let psd = input_line ptr
and last = ref 0 in
let dat = int_n_of_string psd 3 last in
let dtime = Float.of_string (String.init (String.length psd - !last) (fun i -> psd.[i + !last])) in
res.bombs.(b) <- {xy = {x = dat.(0) ; y = dat.(1) ;} ; size = dat.(2) ; det_time = dtime ;
}
done;
(* players *)
if debug_all then Printf.fprintf stderr "Players\n" ;
res.nplayers <- int_of_string (input_line ptr) ;
res.players <- Array.make res.nplayers default_player ;
for p = 0 to res.nplayers -1 do
let dat = int_n_of_string (input_line ptr) 8 useless in
res.players.(p) <- {id = dat.(2) ; xy = {x = dat.(0) ; y = dat.(1) ;} ; nspeed = dat.(3) ; nbomb_atonce = dat.(4) ; bomb_radius = dat.(5) ; ndash = dat.(6) ; ntraps = dat.(7) ;}
done;
(* boosts *)
if debug_all then Printf.fprintf stderr "Boosts\n" ;
res.nboosts <- int_of_string (input_line ptr) ;
res.boosts <- Array.make res.nboosts default_boost ;
for p = 0 to res.nboosts -1 do
let dat = int_n_of_string (input_line ptr) 3 useless in
res.boosts.(p) <- {xy = {x = dat.(0) ; y = dat.(1) ;} ; spec = dat.(2)}
done;
if debug_all then Printf.fprintf stderr "Done!\n" ;
close_in ptr ;
res
with
| End_of_file ->
close_in ptr ;
failwith "cannot happen unless something is wrong" ;;
let build_danger_map (gd : game_data) =
let lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) in
let (res : danger_map) = {
explosionTimes = Array.make lines [||] ;
bonusMap = Array.make lines [||] ;
playersMap = Array.make (gd.nplayers) (0, 0, 0) ;
explodedCrates = Array.make lines [||] ;
} in
for l = 0 to lines -1 do
res.explosionTimes.(l) <- Array.make cols [] ;
res.explodedCrates.(l) <- Array.make cols false ;
res.bonusMap.(l) <- Array.make cols false ;
done;
Array.sort
(
fun b1 b2 -> int_of_float (100. *. (b1.det_time -. b2.det_time))
)
gd.bombs ;
(* add bombs *)
let halt = ref false in
for b = 0 to gd.nbombs -1 do
let bx = gd.bombs.(b).xy.x
and by = gd.bombs.(b).xy.y in
let bsize = gd.bombs.(b).size
and dtime = min (gd.bombs.(b).det_time) (List.fold_left min (gd.dt +. 1000.) res.explosionTimes.(bx).(by)) in
for dir = 0 to 3 do
for w = 0 to bsize do
if (not !halt) && (w > 0 || dir = 0) then begin
let nx = bx + w * (fst order.(dir))
and ny = by + w * (snd order.(dir)) in
if is_valid nx ny lines cols then begin
if (gd.laby.(nx).(ny) = 0 || gd.laby.(nx).(ny) >= 3) || (gd.laby.(nx).(ny) = 2 && res.explodedCrates.(nx).(ny)) then
res.explosionTimes.(nx).(ny) <- (dtime)::(res.explosionTimes.(nx).(ny))
else if gd.laby.(nx).(ny) = 1 then
halt := true
else if gd.laby.(nx).(ny) = 2 then begin
halt := true ;
res.explodedCrates.(nx).(ny) <- true ;
end
end
end
done;
halt := false ;
done
done;
(* add players *)
for p = 0 to gd.nplayers -1 do
if p <> gd.player_id then begin
let bx = gd.players.(p).xy.x
and by = gd.players.(p).xy.y in
let bsize = gd.players.(p).bomb_radius
(*and dtime = min (gd.dt +. 5.5) (List.fold_left min (gd.dt +. 1000.) res.explosionTimes.(bx).(by)) in*)
and dtime = (gd.dt +. 5.5) in
for dir = 0 to 3 do
for w = 0 to bsize do
if (not !halt) && (w > 0 || dir = 0) then begin
let nx = bx + w * (fst order.(dir))
and ny = by + w * (snd order.(dir)) in
if is_valid nx ny lines cols then begin
if (gd.laby.(nx).(ny) = 0 || gd.laby.(nx).(ny) >= 3) || (gd.laby.(nx).(ny) = 2 && res.explodedCrates.(nx).(ny)) then
res.explosionTimes.(nx).(ny) <- (dtime)::(res.explosionTimes.(nx).(ny))
else if gd.laby.(nx).(ny) = 1 then
halt := true
else if gd.laby.(nx).(ny) = 2 then begin
halt := true ;
res.explodedCrates.(nx).(ny) <- true ;
end
end
end
done;
halt := false ;
done
(*res.playersMap.(p) <- (gd.players.(p).xy.x, gd.players.(p).xy.y, gd.players.(p).bomb_radius) ;*)
end
done;
(* add bonuses *)
for b = 0 to gd.nboosts -1 do
res.bonusMap.(gd.boosts.(b).xy.x).(gd.boosts.(b).xy.y) <- true ;
done;
res ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let simulate_bomb (dgs : danger_map) (b : bomb) =
let saved_data = Hashtbl.create 30 in
let bx = b.xy.x
and by = b.xy.y in
let bsize = b.size
and dtime = min (b.det_time) (List.fold_left min (32760.) dgs.explosionTimes.(bx).(by)) in
let lines = Array.length dgs.explosionTimes
and cols = Array.length dgs.explosionTimes.(0) in
for dir = 0 to 3 do
for w = 0 to bsize do
if (w > 0 || dir = 0) then begin
let nx = bx + w * (fst order.(dir))
and ny = by + w * (snd order.(dir)) in
if is_valid nx ny lines cols then begin
Hashtbl.add saved_data (nx, ny) dtime ;
dgs.explosionTimes.(nx).(ny) <- (dtime)::(dgs.explosionTimes.(nx).(ny))
end
end
done;
done;
saved_data ;;
let simulate_bomb_deconstruct (dgs : danger_map) (bx : int) (by : int) (bsize : int) (dtime0 : float) =
let saved_data = Hashtbl.create 30 in
let dtime = min dtime0 (List.fold_left min (32760.) dgs.explosionTimes.(bx).(by)) in
let lines = Array.length dgs.explosionTimes
and cols = Array.length dgs.explosionTimes.(0) in
for dir = 0 to 3 do
for w = 0 to bsize do
if (w > 0 || dir = 0) then begin
let nx = bx + w * (fst order.(dir))
and ny = by + w * (snd order.(dir)) in
if is_valid nx ny lines cols then begin
Hashtbl.add saved_data (nx, ny) dtime ;
dgs.explosionTimes.(nx).(ny) <- (dtime)::(dgs.explosionTimes.(nx).(ny))
end
end
done;
done;
saved_data ;;
let reverse_simulate_bomb (dgs : danger_map) (save : (int * int, float) Hashtbl.t) =
Hashtbl.iter
(fun (x, y) dt ->
dgs.explosionTimes.(x).(y) <- pop_list dt (dgs.explosionTimes.(x).(y))
)
save ;;
let is_dead (dgs : danger_map) (x : int) (y : int) (t : float) (dt : float) =
List.fold_left
(fun acc curtime ->
acc || (t > curtime && t < curtime +. dt)
)
false
dgs.explosionTimes.(x).(y) ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
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_map) =
let pid = gd.player_id
and lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) in
try
let halt = ref false in
let res = ref false in
for dir = 0 to 3 do
for o = 1 to gd.players.(pid).bomb_radius do
if not !halt then begin
let nx = gd.players.(pid).xy.x + o * (fst order.(dir))
and ny = gd.players.(pid).xy.y + o * (snd order.(dir)) in
if is_valid nx ny lines cols then begin
if gd.laby.(nx).(ny) = 2 then
res := true
else if gd.laby.(nx).(ny) = 1 then
halt := true
else if dgs.bonusMap.(nx).(ny) then
raise (ReturnBool false)
end
end
done;
halt := false ;
done;
!res
with
| ReturnBool b -> b ;;
let sees_a_crate (gd : game_data) (dgs : danger_map) (x : int) (y : int) =
let pid = gd.player_id
and lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) in
try
let halt = ref false in
let res = ref false in
for dir = 0 to 3 do
for o = 1 to gd.players.(pid).bomb_radius do
if not !halt then begin
let nx = x + o * (fst order.(dir))
and ny = y + o * (snd order.(dir)) in
if is_valid nx ny lines cols then begin
if gd.laby.(nx).(ny) = 2 then
res := true
else if gd.laby.(nx).(ny) = 1 then
halt := true
else if dgs.bonusMap.(nx).(ny) then
raise (ReturnBool false)
end
end
done;
halt := false ;
done;
!res
with
| ReturnBool b -> b ;;
let bfs_for_crate (gd : game_data) (dgs : danger_map) (x0 : int) (y0 : int) (stime : float) =
let lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) 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
Hashtbl.add visited (x0, y0) 1 ;
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 dgs x y ct interval) then begin (* is not lethal *)
if (is_empty_lst dgs.explosionTimes.(x).(y)) && (sees_a_crate gd dgs x y && not dgs.explodedCrates.(x).(y)) then begin (* is a safe and valid tile *)
raise (ReturnInt direction)
end;
(*Printf.fprintf stderr "+4 (%b %b)\n" (is_empty_lst dgs.explosionTimes.(x).(y)) (sees_a_crate gd dgs x y) ;*)
for dir = 0 to 3 do
Queue.add (x + (fst order.(dir)), y + (snd order.(dir)), ct +. interval, direction) q ;
done
end
end
end
done;
4 ;
with
| ReturnInt k -> k ;;
let bfs_gtfo (gd : game_data) (dgs : danger_map) (x0 : int) (y0 : int) (stime : float) =
let lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) 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
Hashtbl.add visited (x0, y0) 1 ;
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 dgs x y ct interval) then begin (* is not lethal *)
if (is_empty_lst dgs.explosionTimes.(x).(y)) then begin (* is a safe and valid tile *)
raise (ReturnInt direction)
end;
for dir = 0 to 3 do
Queue.add (x + (fst order.(dir)), y + (snd order.(dir)), ct +. interval, direction) q ;
done
end
end
end
done;
4 ;
with
| ReturnInt k -> k ;;
let bfs_bonus (gd : game_data) (dgs : danger_map) (x0 : int) (y0 : int) (stime : float) =
let lines = Array.length gd.laby
and cols = Array.length gd.laby.(0) 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
Hashtbl.add visited (x0, y0) 1 ;
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 dgs x y ct interval) && ct < stime +. 7. *. interval then begin (* is not lethal *)
if dgs.bonusMap.(x).(y) then begin (* is a safe and valid tile *)
raise (ReturnInt direction)
end;
for dir = 0 to 3 do
Queue.add (x + (fst order.(dir)), y + (snd order.(dir)), ct +. interval, direction) q ;
done
end
end
end
done;
4 ;
with
| ReturnInt k -> k ;;
let move_crate (gd : game_data) (dgs : danger_map) =
let pid = gd.player_id in
let cxi = gd.players.(pid).xy.x
and cyi = gd.players.(pid).xy.y in
try
let bonusres = bfs_bonus gd dgs cxi cyi gd.dt in
if bonusres <> 4 then raise (ReturnInt bonusres) ;
if (is_a_crate_nearby gd dgs) && (is_empty_lst dgs.explosionTimes.(cxi).(cyi)) then begin
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 = bfs_gtfo gd dgs cxi cyi gd.dt in
if result <> 4 && gd.players.(pid).nbomb_atonce > 0 then begin
action := 1 ;
raise (ReturnInt result) ;
end
else
raise (ReturnInt 4)
end;
bfs_for_crate gd dgs cxi cyi gd.dt
with
| ReturnInt k -> k ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let game_map = parse_input "entrees.txt" ;;
if debug_all then print_game_data game_map ;;
let danger_data = build_danger_map game_map ;;
get_meta_info game_map.player_id ;;
(*Printf.fprintf stderr "\n" ;;
print_dangers danger_data ;;*)
let direction = move_crate game_map danger_data ;;
Printf.printf "%d %d" direction !action ;
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 ;;

1
compilZ.sh Normal file
View File

@ -0,0 +1 @@
ocamlc again.ml -o again

View File

@ -1,29 +1,27 @@
107.60000000000014 135.09900000000007
3 3
13 21 13 21
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 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 0 2 0 2 2 2 2 2 2 5 5 5 5 1 1 3 3 3 3 0 2 2 2 2 2 2 2 0 5 5 5 5 5 5 1
1 3 1 3 1 3 1 2 1 2 1 0 1 2 1 2 1 5 1 5 1 1 3 1 3 1 0 1 2 1 0 1 2 1 2 1 5 1 5 1 5 1
1 3 3 3 3 3 3 3 0 2 2 2 2 2 0 5 5 5 5 5 1 1 3 3 3 3 3 3 0 2 0 2 2 0 0 5 5 5 5 5 5 1
1 3 1 3 1 3 1 2 1 2 1 2 1 0 1 5 1 5 1 5 1 1 3 1 3 1 0 1 2 1 2 1 2 1 0 1 5 1 5 1 5 1
1 3 3 3 3 3 0 2 2 2 2 2 2 0 5 5 5 5 5 5 1 1 0 0 3 0 0 2 2 2 2 2 2 0 4 4 5 5 5 5 5 1
1 0 1 3 1 3 1 2 1 2 1 0 1 2 1 5 1 4 1 5 1 1 0 1 3 1 3 1 6 1 0 1 2 1 4 1 4 1 5 1 0 1
1 6 6 6 6 6 0 2 2 2 2 2 2 0 2 0 0 4 4 4 1 1 3 6 3 3 3 3 6 2 6 2 0 0 4 4 4 4 5 4 4 1
1 6 1 3 1 6 1 0 1 2 1 2 1 2 1 0 1 4 1 5 1 1 6 1 3 1 3 1 6 1 6 1 2 1 5 1 4 1 4 1 4 1
1 6 6 3 6 6 0 2 2 2 2 2 0 0 0 4 4 4 4 4 1 1 6 6 6 6 6 3 6 3 3 0 2 0 5 5 5 4 4 4 4 1
1 6 1 6 1 6 1 0 1 2 1 2 1 2 1 4 1 4 1 4 1 1 6 1 6 1 0 1 6 1 6 1 2 1 5 1 5 1 4 1 4 1
1 6 6 6 6 6 6 0 2 2 2 2 2 2 0 4 4 4 4 4 1 1 6 6 6 6 6 6 6 6 6 6 0 2 5 5 5 5 5 4 4 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
5
7 17 3 108.35799999999998
11 15 2 109.5
11 6 2 109.50000000000011
3 6 3 109.64919999999982
10 7 2 112.20000000000013
4 4
1 7 0 4 3 3 0 0 9 5 5 137.68300000000002
8 15 1 0 2 2 3 1 5 12 2 138.5
9 17 2 3 3 3 0 2 3 12 1 139.70000000000022
10 7 3 1 2 2 3 0 4 13 2 140.5
3
3 13 1 1 2 1 2 2
3 13 2 0 4 2 0 2
7 3 3 3 3 5 0 2
1 1
5 13 1 11 11 0

2
execZ.sh Normal file
View File

@ -0,0 +1,2 @@
ocamlc again.ml -o again
./again

View File

@ -60,7 +60,7 @@ PU_NATURE = 2
from random import randrange from random import randrange
from copy import deepcopy from copy import deepcopy
from tkinter import * from tkinter import *
from os import system import os
def attente(vitesse): def attente(vitesse):
return TEMPS_BASE * 0.9**vitesse return TEMPS_BASE * 0.9**vitesse
@ -209,10 +209,10 @@ def execute_evenement(evenements, evenement, plateau, plateauCouleur, bombes, jo
bombes.append([i,j,joueur[J_LONGUEURFLAMMES],indiceJoueur,evenement[0]+TEMPS_EXPLOSION]) bombes.append([i,j,joueur[J_LONGUEURFLAMMES],indiceJoueur,evenement[0]+TEMPS_EXPLOSION])
ajoute_evenement(evenements, [evenement[0]+TEMPS_EXPLOSION, EVENEMENT_EXPLOSION_BOMBE, len(bombes)-1]) ajoute_evenement(evenements, [evenement[0]+TEMPS_EXPLOSION, EVENEMENT_EXPLOSION_BOMBE, len(bombes)-1])
elif joueurs[indiceJoueur][J_DASHSRESTANTS]>0 and action == A_DASH: elif joueurs[indiceJoueur][J_DASHSRESTANTS]>0 and action == A_DASH:
joueurs[J_DASHSRESTANTS]-=1 joueur[J_DASHSRESTANTS]-=1
joueurs[J_TOURSDASH]+=3 joueur[J_TOURSDASH]+=3
elif joueurs[indiceJoueur][J_PIEGESRESTANTS]>0 and action == A_PIEGE: elif joueurs[indiceJoueur][J_PIEGESRESTANTS]>0 and action == A_PIEGE:
joueurs[J_PIEGESRESTANTS]-=1 joueur[J_PIEGESRESTANTS]-=1
pieges.append([i,j,indiceJoueur]) pieges.append([i,j,indiceJoueur])
ip,jp = prochain(i,j,direction) ip,jp = prochain(i,j,direction)
if plateau[ip][jp]==PLATEAU_VIDE and trouve_objet(ip, jp, bombes)==None: if plateau[ip][jp]==PLATEAU_VIDE and trouve_objet(ip, jp, bombes)==None:
@ -289,7 +289,7 @@ def execute_evenement(evenements, evenement, plateau, plateauCouleur, bombes, jo
longueurFlammes = 0 longueurFlammes = 0
# Si on est pas au bout de la flamme, on propage # Si on est pas au bout de la flamme, on propage
if longueurFlammes>0: elif longueurFlammes>0:
ip, jp = prochain(i,j,direction) ip, jp = prochain(i,j,direction)
ajoute_evenement(evenements, [evenement[0]+TEMPS_PROPAGATION, EVENEMENT_PROPAGATION, ip, jp, direction, longueurFlammes-1, indJoueur]) ajoute_evenement(evenements, [evenement[0]+TEMPS_PROPAGATION, EVENEMENT_PROPAGATION, ip, jp, direction, longueurFlammes-1, indJoueur])
@ -322,9 +322,10 @@ def decision(programme, indiceJoueur, plateau, plateauCouleur, bombes, joueurs,
print(len(powerups), file=entrees) print(len(powerups), file=entrees)
for pu in powerups: for pu in powerups:
print(pu[PU_LIGNE], pu[PU_COLONNE], pu[PU_NATURE], file=entrees) print(pu[PU_LIGNE], pu[PU_COLONNE], pu[PU_NATURE], file=entrees)
if os.name == "posix":
system("cat entrees.txt | "+programme+" > sortie.txt") os.system("cat entrees.txt | "+programme+" > sortie.txt")
elif os.name =="nt":
os.system('type entrees.txt | python '+programme[2:]+ ' >sortie.txt')
with open("sortie.txt", "r") as sortie: with open("sortie.txt", "r") as sortie:
direction, b = sortie.readline().split() direction, b = sortie.readline().split()
action = int(b) action = int(b)
@ -332,7 +333,7 @@ def decision(programme, indiceJoueur, plateau, plateauCouleur, bombes, joueurs,
def simulation(strategies): def simulation(strategies):
def pas_de_jeu(): def pas_de_jeu():
if len(joueurs) - joueurs.count(None) > 1: if len(joueurs) - joueurs.count(None) > 0:
evenement = evenements.pop(0) evenement = evenements.pop(0)
if evenement[0]>TEMPS_PARTIE: if evenement[0]>TEMPS_PARTIE:
return return
@ -366,7 +367,7 @@ def simulation(strategies):
joueurs = [] joueurs = []
for i in range(len(strategies)): for i in range(len(strategies)):
joueur = [positionsInitiales[i][0], positionsInitiales[i][1], strategies[i], 0, 1, 1, 1, 0, 0, 0] joueur = [positionsInitiales[i][0], positionsInitiales[i][1], strategies[i], 0, 1, 1, 1, 0, 0, 0, 0]
joueurs.append(joueur) joueurs.append(joueur)
ajoute_evenement(evenements, [0., EVENEMENT_TOUR_JOUEUR, i]) ajoute_evenement(evenements, [0., EVENEMENT_TOUR_JOUEUR, i])
@ -378,5 +379,4 @@ def simulation(strategies):
fenetre.mainloop() fenetre.mainloop()
return return
from importlib import import_module simulation(["./again", "./again", "./again", "./again"])
simulation(["./main", "./main", "./main", "./main"])

BIN
main

Binary file not shown.

BIN
main.cmi

Binary file not shown.

BIN
main.cmo

Binary file not shown.

66
main.ml
View File

@ -12,6 +12,7 @@ let debug_all = false ;;
let debug_data = false ;; let debug_data = false ;;
let fatal_time = 1.0 ;; let fatal_time = 1.0 ;;
let explosion_time = 1.0 ;; let explosion_time = 1.0 ;;
let logg = true ;;
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
@ -327,6 +328,8 @@ let parse_input (str : string) =
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let exploded = Hashtbl.create 21 ;;
let warn_level (b : bomb) (ct : float) = match (b.det_time -. ct) with let warn_level (b : bomb) (ct : float) = match (b.det_time -. ct) with
| k when k < fatal_time -> Fatal b.det_time ; | k when k < fatal_time -> Fatal b.det_time ;
| _ -> Danger b.det_time ;; | _ -> Danger b.det_time ;;
@ -367,7 +370,6 @@ let evaluate_dangers (gd : game_data) =
done; done;
(* add bomb tiles *) (* add bomb tiles *)
let exploded = Hashtbl.create 12 in
for b = 0 to gd.nbombs -1 do for b = 0 to gd.nbombs -1 do
let bx = gd.bombs.(b).xy.x let bx = gd.bombs.(b).xy.x
and by = gd.bombs.(b).xy.y in and by = gd.bombs.(b).xy.y in
@ -606,20 +608,33 @@ let move_explore (gd: game_data) (dgs : danger array array) =
try try
let (cxi, cyi) = (gd.players.(pid).xy.x, gd.players.(pid).xy.y) in let (cxi, cyi) = (gd.players.(pid).xy.x, gd.players.(pid).xy.y) in
let move_with_caution (exit : bool) = let move_with_caution () =
let res = has_a_safe_path_origin_2 cxi cyi lines cols gd.dt interval gd dgs [|Bonus|] [||] [|Blocked|] [||] 7 in let res = has_a_safe_path_origin_2 cxi cyi lines cols gd.dt interval gd dgs [|Bonus|] [||] [|Blocked|] [||] 7 in
if res <> 4 then begin if res <> 4 then begin
if debug_all then Printf.fprintf stderr "[crates] success 1/2!\n" ; if debug_all then Printf.fprintf stderr "[crates] success 1/2!\n" ;
res res
end end
else begin else begin
let res2 = has_a_safe_path_origin_2 cxi cyi lines cols gd.dt interval gd dgs [||] [|2|] [|Blocked|] [||] 80 in for w = 0 to lines -1 do
for h = 0 to cols -1 do
if gd.laby.(w).(h) = 2 then begin
for dir = 0 to 3 do
let nx = w + fst order.(dir)
and ny = h + snd order.(dir) in
if is_valid nx ny lines cols && dgs.(nx).(ny) <> Blocked then
gd.laby.(nx).(ny) <- (-5) ;
done
end
done
done;
(* you dont want to stop INSIDE a crate, but rather right next to it *)
let res2 = has_a_safe_path_origin_2 cxi cyi lines cols gd.dt interval gd dgs [||] [|-5|] [|Blocked|] [||] 80 in
if res2 <> 4 then begin if res2 <> 4 then begin
if debug_all then Printf.fprintf stderr "[crates] success 2/2!\n" ; if debug_all then Printf.fprintf stderr "[crates] success 2/2!\n" ;
res2 res2
end end
else begin else begin
if exit then (* TODONE *) if not (contains_crate gd) then (* TODONE *)
current_status := ClaimLand ; current_status := ClaimLand ;
Printf.fprintf stderr "Exited.\n" ; Printf.fprintf stderr "Exited.\n" ;
4 4
@ -645,25 +660,26 @@ let move_explore (gd: game_data) (dgs : danger array array) =
end end
) )
bomb_hash ; bomb_hash ;
let result = move_with_caution false in let result = has_a_safe_path_origin_2 cxi cyi lines cols gd.dt interval gd dgs [|Bonus; Safe|] [||] [|Blocked|] [||] 10 in
Hashtbl.iter (fun (k1, k2) v -> dgs.(k1).(k2) <- v) saved_dgs ; Hashtbl.iter (fun (k1, k2) v -> dgs.(k1).(k2) <- v) saved_dgs ;
result result
in in
(* check if there's a crate next to the player, and if upon placing a bomb it won't softlock the player, and if you can place a bomb *) (* check if there's a crate next to the player, and if upon placing a bomb it won't softlock the player, and if you can place a bomb *)
if is_a_crate_nearby gd dgs && (safe_path_with_bomb cxi cyi gd.players.(pid).bomb_radius <> 4) then begin (* Crate at South *) let spwb = safe_path_with_bomb cxi cyi gd.players.(pid).bomb_radius in
if is_a_crate_nearby gd dgs && (spwb <> 4) then begin (* Crate at South *)
if dgs.(cxi).(cyi) = Safe && gd.players.(pid).nbomb_atonce > 0 then begin if dgs.(cxi).(cyi) = Safe && gd.players.(pid).nbomb_atonce > 0 then begin
current_status := EscapeDeath ; (*current_status := EscapeDeath ;*)
action := 1; action := 1;
if debug_all then Printf.fprintf stderr "Fire in the hole!\n" ; if debug_all then Printf.fprintf stderr "Fire in the hole!\n" ;
raise (ReturnInt 4) ; raise (ReturnInt spwb) ;
end; end;
end; end;
if debug_all then Printf.fprintf stderr "[crates] Cannot bomb now, searching for a crate...\n"; if debug_all then Printf.fprintf stderr "[crates] Cannot bomb now, searching for a crate...\n";
(* go to one without stepping into a dangerous tile *) (* go to one without stepping into a dangerous tile *)
raise (ReturnInt (move_with_caution true)) ; raise (ReturnInt (move_with_caution ())) ;
with with
| ReturnInt k -> k ;; | ReturnInt k -> k ;;
@ -671,7 +687,7 @@ let move_explore (gd: game_data) (dgs : danger array array) =
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
let cell_profit (d_from_p : int) (gain : int) = let cell_profit (d_from_p : int) (gain : int) =
(100000 * gain * (1 + ln_b 7 gain)) / d_from_p ;; (100 * gain * (1 + ln_b 7 gain)) (*/ d_from_p *);;
let move_claim (gd : game_data) (dgs : danger array array) (gns : int array array) = let move_claim (gd : game_data) (dgs : danger array array) (gns : int array array) =
let lines = Array.length gd.laby let lines = Array.length gd.laby
@ -718,7 +734,14 @@ let move_claim (gd : game_data) (dgs : danger array array) (gns : int array arra
(fun i lst -> Array.iteri (fun i lst -> Array.iteri
( (
fun j elt -> 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 if (distances.(i).(j) <> -1) then begin
let cpft = cell_profit distances.(i).(j) gns.(i).(j) in
if !maxi_gain < cpft then begin
maxi_gain := cpft ;
maxi_i := i ;
maxi_j := j ;
end
end
) )
lst lst
) )
@ -752,14 +775,14 @@ let move_claim (gd : game_data) (dgs : danger array array) (gns : int array arra
if result0 <> 4 then begin if result0 <> 4 then begin
action := 1 ; action := 1 ;
current_status := EscapeDeath ; (*current_status := EscapeDeath ;*)
raise (ReturnInt result0) raise (ReturnInt result0)
end end
end; end;
raise (ReturnInt 4) raise (ReturnInt 4)
end end
else if !maxi_i = (-1) then begin else if !maxi_i = (-1) then begin
current_status := EscapeDeath ; (*current_status := EscapeDeath ;*)
raise (ReturnInt (has_a_safe_path_origin_2 cxi cyi lines cols gd.dt interval gd dgs [|Bonus; Safe|] [||] [|Blocked|] [||] 80)) raise (ReturnInt (has_a_safe_path_origin_2 cxi cyi lines cols gd.dt interval gd dgs [|Bonus; Safe|] [||] [|Blocked|] [||] 80))
end end
else begin else begin
@ -811,7 +834,7 @@ let move_safe (gd : game_data) (dgs : danger array array) (gns : int array array
result2 result2
else begin else begin
(* you're probably dead if the code reaches here, unless... *) (* you're probably dead if the code reaches here, unless... *)
if (!dash_left > 0) || gd.players.(pid).ndash > 0 then begin if false && ((!dash_left > 0) || gd.players.(pid).ndash > 0) then begin
Printf.fprintf stderr "*teleports*\n" ; Printf.fprintf stderr "*teleports*\n" ;
if (!dash_left = 0) then if (!dash_left = 0) then
action := 2 ; action := 2 ;
@ -831,6 +854,8 @@ let move_safe (gd : game_data) (dgs : danger array array) (gns : int array array
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
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 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
| _ when !current_status = BlowUpCrates -> ()
| _ when !current_status = ClaimLand -> ()
| Safe -> () | Safe -> ()
| Danger k when k < 3.0 -> current_status := EscapeDeath | Danger k when k < 3.0 -> current_status := EscapeDeath
| Danger k -> () | Danger k -> ()
@ -850,7 +875,7 @@ let debug_game_data (gd : game_data) =
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *)
Printf.fprintf stderr "XXXXXXXX\n" ;; if logg then Printf.fprintf stderr "XXXXXXXX\n" ;;
let game_d = parse_input "entrees.txt" ;; let game_d = parse_input "entrees.txt" ;;
let dangers = evaluate_dangers game_d ;; let dangers = evaluate_dangers game_d ;;
@ -858,7 +883,7 @@ let gains = cell_values game_d ;;
get_meta_info game_d.player_id ;; get_meta_info game_d.player_id ;;
Printf.fprintf stderr "[player %d started its turn]\n" game_d.player_id ;; if logg then Printf.fprintf stderr "[player %d started its turn]\n" game_d.player_id ;;
if debug_data then begin if debug_data then begin
print_game_data game_d ; print_game_data game_d ;
@ -894,9 +919,10 @@ main_actions () ;
Printf.printf "%d" !action ; Printf.printf "%d" !action ;
(*debug_game_data game_d ;;*) (*debug_game_data game_d ;;*)
if logg then begin
Printf.fprintf stderr "[player %d went at direction " game_d.player_id ;; Printf.fprintf stderr "[player %d went at direction " game_d.player_id ;
print_direction !chosen ;; print_direction !chosen ;
Printf.fprintf stderr "with action %d] time at end : %f\n" !action game_d.dt ;; Printf.fprintf stderr "with action %d] time at end : %f\n" !action game_d.dt ;
end ;;
set_meta_info game_d.player_id ;; set_meta_info game_d.player_id ;;

View File

@ -1 +0,0 @@
2 2