From 3486ed84c1e5dd3fbd17632ae6bdb96484af33e1 Mon Sep 17 00:00:00 2001 From: Alexandre Date: Fri, 8 Nov 2024 22:16:27 +0100 Subject: [PATCH] major reworks to BFS functions --- bin/main | Bin 222793 -> 227925 bytes input_test.txt | 16 +-- main.cmi | Bin 6332 -> 6827 bytes main.cmo | Bin 21036 -> 28084 bytes main.ml | 265 ++++++++++++++++++++++++++++++++++++------------- 5 files changed, 202 insertions(+), 79 deletions(-) diff --git a/bin/main b/bin/main index bef0f9a1bff570295e0c6fe539ed9be11a2f2142..ca9926e553b6f1b64c97d85eaaefeb49e448bce5 100755 GIT binary patch delta 7472 zcmcgw3virO70$i4+a#OUrcJVmX}X()nm}knfDmZ4SuM4eAhDG6L1|)0w+}*-+Jxc* zT(A{qoY5jXaCB6f86B80C@AWpjtznik3K-KAXuriiZp3c9wiN(;`)96?oE?z(xkNb z&wg|7fA6{Hp7Y&v&%OUXvomAQ(TqE`s9)*+H}w)v_^tFjnf;JTPc2MJN@@f$jp>IZaT zC;;&rfEFMdpu6e7?LY%i0kFRs=*Ik+C=-3W5^bE8CQSjTqYcOc5@ks#b;M;$hJ*uX z zE|3d#jw7G5M;V9aq;i0Ix#o0;hFiWLC&e60rRxAr;)$2^IsoutJH54r*=1)yQI5*V z9OcM*q8_`DY^O1PfI5~icrHPO3WiTSe1KbOwefzAVMjZug9LECM!>|&Z73PV9|Q7% z)7cPHxzMV#YQ|FC4|U4`s;7)MUgvlQ)I-uV&3LPCLe;7uTf^0k=GN!+8aC* zBC*g>PBW6ov3a!e=a9#dDzEs^JW8ZrmtFy1oRFL-cbxqUxEmfzb}OHbyV2y&lDn~0 zo&|SuB+i}Px!e__#a-g;XULsh?1^%hD1Q#P8(rmDaChrlaqe2d+3Dhr+zp@oBzMXy zOW)R|8OtHj16&9ELfQ}F(7oU;H7(qDWlBZ>ZG1RGrt}=tWkugbbrrxgNdy2sF_E-h zT`Ko|pmXFkWm44SaH!8KjlDWux#i(rU6#EDqRiM_YYvH#tCA(!t9{wmqJ^g%CD@xH zm3`W$Ql!357pgRA?bD@2!xJ^r5|28bEF3Udy8Cqf3@$aBShAa!1{%xg;*hz3ley;Q zJ_2@lK1~Ifidnj(^^h*iy$W5lm;7Cik_=@@{ZY8M|A5Xfpr{6@eKSBg8t0X%kU1YU z=k%fo9b)$7iMJY{t*kEu*2um)bs=v$De~GOU9Ns9$%l1~+9I`wb!)06Iz61V*OyIi zEU3gS^^>$$jvr7tMHP6b$N3*bqqK=~sqr#Rb{y8e^O@-=#_}5{qEUAH081Druu-uCzFX^V!YgWPbp>EG}zFrGJD!g0Nse@?s+-w9nYw)Mlg zr5C4L3oFYt8Q1!cWG#L@&RWV(ucoIL49F1bD<4(Cn-qs`?_W&xnkEmU@bsZj{{Uy46FleBnD9DL(V8S{M*Kdcgl^} zmfYVn?C$cTm%EV;RL1K=`&)Xn@y+MP;iNQ*yo_~ws-`hH`HaLvVd-?;r_BEhcfym!VTqQ zwl>qwiXLj=>}O3+$Q`GL(J~%Aob@C<4dc;c8MQQ>jvgzE8^ebU9jk(2bWXTAk{0KN zyJjqI?5qr-GvvlDqD|F_7j(O=I0a?Tk{hZR$;~MrgLHDVoqEc)f*iLPcQ`)=|KNNK z&TK{XbUe|5kvvr;9?;v7shEsx{$u{&ZF4)oyVN5iZ=14druN7a2laWWcca(Iz|yCT zPx5-T$3r+J$@R43K z>%in1Ou`I2$~Ch(@tR3Ff)8orA}3Pc!}It>=dY_P(Vgks!qnQZZ@({N7aDlU=6x$G zT>JgP+~34ouwG6&rQ2@a=e$)6gWCW`2w5OA1hulS4WI!w7}K0#8TMZHZFIH7{^9yM zs&-nAU`j6mxFOpCPD;((LF~8xe62#Ab?AB{z}(NHk+K^Aj^|if#4{m5_9n+< z4zj|WjKXxwo-=jfeh|+;_z!m8^p%4W0rXTURn6Gxp9FM8V zeL8MAtu+9NyEz8J~Jywz2q&^ssnA_GOtB>P3#OQ-5`mp4{)jN9!JW&;x;& zq-l!5=Y@tbG1^h z$-6md+sC$t)juVgYwE(^dL@4*W1gYI0N`TLXx91M39ye@j!wKTO?jqL?U${2W{x@_ zKCdZM|B4m=jumgjivO_iMy~am$5b)ZlC3wfge(un%ieg|Clv+en?;B48bJ3TuohSe zYymjrusl~_Ld%c-H};)afhIn;oFq0LR) zyqtl|Mvq0KX(&0fEh)!-sy65!?&LcI__mjA+q5^7hi(olj+f`fOZzW49dI9weZScJ zVM}g7j%B`PX`Qz^%Hr*o44QD&J25Zcfmaw4a}`!LR#%=Y8e zd8fbZXOz7Qp~SPAS?<7?Jzd=w4-M+LrKKg<(NXLUjMA3AYbPGF z^H8n)yun;2k2IKTL#dYx4W8HB*4EzXzp;J&jsCXwTQBr?1e-UutXY-ak*cIU__*|VwSXD>YY`kvx9>s7USrgxEiA!r`dm6uBDYBODzte5jw8~^_RWxq?g delta 3906 zcmb_fd2EzL6yKS*?QZEp7ij4TyW3J)D7Fx6%aPbNHY%~UD5OTpnRX>mu|*p2AQTc3 zV^Byyc|@WRFyRjj7^_(n1Wb@aC?IkK(IOy+h5*u9j$qgK+kRi&mThZ=FZpGT_h#O2 z-n^MN-^r%l2M_mNvP^xUuV2l!IV_f;7K>$=fCS}&(Skh!CGZG(3Hk(~fTRA@vAoqv z_Q&kfZx!SSw#WdCT_q*PCJSB?)C(pF_V76?xmItqMi1;KO|jgD0;%I0Bh$c%{x*&`X z*(fCp)o{)_BP(3dtVgI%d3UqURp0ULW?d-^{cE)=!er#+Jgatb&R*r5n;`>1X-A9S z4^O%TpaY7aXKsMG60@uonduJbx&>B2sQ^m@Z7j{y!?-@!f|S%asbY0-3YQe)XPqJl`D`af=@lbjJmHJ?2t(GnmWBP+Wr72@dVJa31N{2)Lui zrt@wEn-1v)m^PR7fN7BhZ;7e_>DPl7Oa5PL5NF5*C<=};qM?8qmX#%L2fDArpf7&YmO~-h55F#s?qJhqx$=dm_Hm`|5**)ZUmG3SHewI0Yf1-_m*+ zgftd7#JpP`3+gm-elN8QsITxzH7z6J+b z?dnUu7)=@c;e8#=b7Cl(b7IKNr;O%kwcWQVhVqp9iYpT+*Ow4WixfBeMSF1qrTdP@ z(OSiG6h-@_Jw!XfQAKP_){|CAW0!P-GyyW%q};SftxhXvhz6WeO$o zbq~4KL5@lm zPPG=N0|l2Rlaq_n$)V1mBi6Sfowh3vjuBS)ldKTsS)=^fD1YHu!{}|*z&D1;l;=1y zgKEdT_jl{t5JwqbLWg!_hxV!aem`z02bUetX)}|gilH{a(tE8rXn@ftW-XJY&%Dsg z68AO6kRV6o;QFh<@w`!9Fv^QuHC(*8;C=0khnr^HX-~IA+77PWtzt(G6fvfD8zpF< zjVGx|G5NONZ$6J4oV!L|%KJ`e=TyA!p^MB0UA&gZHMLUvO{hSI``9DE>hX$3JyHM} zo;zscLmM{G#;#rp#2@#`Bzp{goFIoQO!?(Dc~kroM!yt+9|P!&5nSPMS>#ezePvm+ zW>7!3xPruOQ6I@hth8HfpZKVl>f^?4*fO%L{I!`i-uYAA1vNF^xz#o9z4`h1TZUvk zo|&21D}T%b;?#B z=HL^vsnNHjlIB^}9lljX6C>UE>2s?Vc-=E=+&rOLeDJ%kx|+PodF5FCs`QC971O=1 z&#qD8noIL&q0PDJ%6jXZujjlw>HNv{qbd{n^DA%A=H!8k3X3M-*FL!VBY{ UlbribVZo#ViJ5rLev{n)06mX?RsaA1 diff --git a/input_test.txt b/input_test.txt index 36eba2e..20bb71f 100644 --- a/input_test.txt +++ b/input_test.txt @@ -1,19 +1,19 @@ 3.7 0 7 11 -0 0 2 2 2 2 2 2 2 0 0 -0 1 2 1 2 1 2 1 2 1 0 -2 2 2 2 2 2 2 0 2 2 2 -2 1 0 1 2 1 2 1 2 1 0 -2 2 2 2 2 2 2 2 2 2 2 -0 1 2 1 2 1 2 1 0 1 0 -0 0 2 2 2 2 2 2 2 0 0 +2 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 2 +0 0 0 0 0 0 0 0 0 0 0 +3 3 3 0 0 0 0 0 4 4 0 +0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 3 3 0 0 3 3 2 4 4.1 4 4 2 4.3 8 6 3 5.5 5 -0 1 0 3 2 4 5 3 +3 0 0 0 2 4 5 3 2 0 1 4 3 2 2 2 10 5 2 0 2 3 2 3 5 5 3 5 1 10 2 3 diff --git a/main.cmi b/main.cmi index 5e6b5e87e31952b32476f2e12871fa05d34c9ad9..15e807a7b64d00413b96d0a536a461a620a3b4eb 100644 GIT binary patch literal 6827 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 literal 6332 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%0A+TYXVv-cO6s8&BRYP%y2hNaEqtR23P{UXF~7U zm=a%^>V?HTWdW{qEM=;`hXC!2!&HG@LiHD}F#_NMWcPt=+>7W)vyjO(R3Q6!XX~>K z$6FT^p#iJ~_4BHX7jm}+{8hl;xQPbv6=Z9W?Lw0hvw$aB98e)3`|Wo9T{hsmY?6WB zYxvz4(O+hVZ8aCy(P{P5o*8xi#JZlPt?!ORy6Epc9FBtGsj5G0^Y;BAv^`Mu(2gF5 z4&EOB>%>T;t9eI0-$lZB9<~i}_JO&_9c526 zyfEaA*wT9}CL=;xNDJFa*R}6HA$mHY{oAjV9^Em1w#6imoj*##w#L4-L#`Jrt1Dc4 zdB=jMK3NutbTdr`;cLKPkvnX=QLQdc`1Shs*0XOH9^3Lt1B=lB_G&$B>tB2FmNz4# z@^v_|Wa+|-rIAQyQzeU6SN%HeVtvK#s=U2bqqAltp0Xs#43(5<*dnicSJs!l`E%T+ z=2a&fjXpEY;*!DMq=apSZ3`|}583?ov5k#3#2?t*ClWEGFhig06)=WF&JoJIlmxN*; NO88aSH-Zm1{|D1hll%Yx diff --git a/main.cmo b/main.cmo index a66906e98fe2caf6098e7f2d8138e11095f56d20..6e4f181980e00a4f2c8b0692642c7039b174de35 100644 GIT binary patch literal 28084 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 WvBZA68uFF{X91Tc0)avEi2Xm%OgDD` diff --git a/main.ml b/main.ml index cbf17ab..a633b7d 100644 --- a/main.ml +++ b/main.ml @@ -1,9 +1,9 @@ (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) -let debug = false ;; +let debug_all = true ;; let fatal_time = 1.0 ;; -let explosion_time = 1.5 ;; +let explosion_time = 0.5 ;; (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) @@ -122,6 +122,9 @@ let level_of_danger = function | Danger k | Fatal k -> k | _ -> 32768. ;; +let delta i j = + if i = j then 1 else 0 ;; + (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) @@ -163,6 +166,15 @@ let print_danger_levels (map : danger array array) = Printf.printf "\n" done ;; +let print_gain_map (map : int array array) = + Printf.printf "--------------------------------| Gain levels |--------------------------------\n" ; + for l = 0 to (Array.length map -1) do + for c = 0 to (Array.length map.(l) -1) do + Printf.printf "%d " map.(l).(c) ; + done; + Printf.printf "\n" + done ;; + (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) @@ -195,15 +207,15 @@ let parse_input (str : string) = let (res : game_data) = {dt = 0. ; player_id = 0 ; laby = [||] ; nbombs = 0 ; bombs = [||] ; nplayers = 0 ; players = [||] ; nboosts = 0 ; boosts = [||] ;} in try (* time *) - if debug then Printf.printf "Time\n" ; + if debug_all then Printf.printf "Time\n" ; res.dt <- Float.of_string (input_line ptr) ; (* player_id *) - if debug then Printf.printf "PID\n" ; + if debug_all then Printf.printf "PID\n" ; res.player_id <- int_of_string (input_line ptr) ; (* maze *) - if debug then Printf.printf "Maze\n" ; + if debug_all then Printf.printf "Maze\n" ; let msize = int_n_of_string (input_line ptr) 2 useless in res.laby <- Array.make msize.(0) [||] ; @@ -213,7 +225,7 @@ let parse_input (str : string) = done; (* bombs *) - if debug then Printf.printf "Boom\n" ; + if debug_all then Printf.printf "Boom\n" ; res.nbombs <- int_of_string (input_line ptr) ; res.bombs <- Array.make res.nbombs default_bomb ; @@ -227,7 +239,7 @@ let parse_input (str : string) = done; (* players *) - if debug then Printf.printf "Players\n" ; + if debug_all then Printf.printf "Players\n" ; res.nplayers <- int_of_string (input_line ptr) ; res.players <- Array.make res.nplayers default_player ; @@ -237,7 +249,7 @@ let parse_input (str : string) = done; (* boosts *) - if debug then Printf.printf "Boosts\n" ; + if debug_all then Printf.printf "Boosts\n" ; res.nboosts <- int_of_string (input_line ptr) ; res.boosts <- Array.make res.nboosts default_boost ; @@ -246,7 +258,7 @@ let parse_input (str : string) = res.boosts.(p) <- {xy = {x = dat.(0) ; y = dat.(1) ;} ; spec = dat.(2)} done; - if debug then Printf.printf "Done!\n" ; + if debug_all then Printf.printf "Done!\n" ; close_in ptr ; res with @@ -326,6 +338,41 @@ let evaluate_dangers (gd : game_data) = (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) (* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) +let cell_values (gd : game_data) = + (* computes the net gain upon blowing up each cell *) + let lines = Array.length gd.laby + and cols = Array.length gd.laby.(0) in + let res = Array.make_matrix lines cols 0 in + + let psize = gd.players.(gd.player_id).bomb_radius in + + for ln = 0 to lines -1 do + for cl = 0 to cols -1 do + if gd.laby.(ln).(cl) >= 3 && gd.laby.(ln).(cl) <> 3 + gd.player_id then begin + (* use a similar method than danger for bombs *) + let halt = ref false in + + for dir = 0 to 3 do + for w = 1 - delta dir 0 to psize do + 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 *) + res.(cx).(cy) <- res.(cx).(cy) + 1 + else + halt := true ; + end + done; + halt := false ; + done + end + done + done ; + res ;; + +(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) +(* ---------------------------------------------------------------------------------------------------------------------------------------------------- *) + let is_safe = function | Safe | Danger _ -> true | Fatal _ | Blocked -> false ;; @@ -336,6 +383,8 @@ let move_safe (gd : game_data) (dgs : danger array array) = 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.printf "I = %f\n" interval ; + let lines = Array.length gd.laby and cols = Array.length gd.laby.(0) in @@ -343,22 +392,44 @@ let move_safe (gd : game_data) (dgs : danger array array) = 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 + if dgs.(cx).(cy) = Safe then begin + current_status := BlowUpCrates ; raise (ReturnInt 4) ; + end; let visited = Hashtbl.create 100 in - let has_a_safe_path (cx0 : int) (cy0 : int) (simt : float) (vid : int) = + let has_a_safe_path (cx0 : int) (cy0 : int) (simt : float) = let q = Queue.create () in - Queue.add (cx0, cy0, simt) q ; (* everything added to q has valid coords *) - if debug then Printf.printf "[escape] Attempt %d/4...\n" vid ; + + Hashtbl.add visited (cx0, cy0) 1 ; + + if is_valid (cx0+1) (cy0) lines cols && not ((simt +. interval) > (level_of_danger dgs.(cx0+1).(cy0)) && (simt +. interval) < (level_of_danger dgs.(cx0+1).(cy0)) +. explosion_time) then begin (* South *) + if debug_all then Printf.printf "[escape] +South\n" ; + Queue.add (cx0+1, cy0, simt +. interval, 2) q ; + end; + if is_valid (cx0-1) (cy0) lines cols && not ((simt +. interval) > (level_of_danger dgs.(cx0-1).(cy0)) && (simt +. interval) < (level_of_danger dgs.(cx0-1).(cy0)) +. explosion_time) then begin (* North *) + if debug_all then Printf.printf "[escape] +North\n" ; + Queue.add (cx0-1, cy0, simt +. interval, 0) q ; + end; + if is_valid (cx0) (cy0+1) lines cols && not ((simt +. interval) > (level_of_danger dgs.(cx0).(cy0+1)) && (simt +. interval) < (level_of_danger dgs.(cx0).(cy0+1)) +. explosion_time) then begin (* East *) + if debug_all then Printf.printf "[escape] +East\n" ; + Queue.add (cx0, cy0+1, simt +. interval, 1) q ; + end; + if is_valid (cx0) (cy0-1) lines cols && not ((simt +. interval) > (level_of_danger dgs.(cx0).(cy0-1)) && (simt +. interval) < (level_of_danger dgs.(cx0).(cy0-1)) +. explosion_time) then begin (* West *) + if debug_all then Printf.printf "[escape] +West\n" ; + Queue.add (cx0, cy0-1, simt +. interval, 3) q ; + end; + + if debug_all then Printf.printf "[escape] Attempt 1/1...\n" ; try while not (Queue.is_empty q) do - let (cx, cy, cur_t) = Queue.pop q in - if Hashtbl.find_opt visited (cx, cy, vid) <> None then () else begin - Hashtbl.add visited (cx, cy, vid) 1 ; + let (cx, cy, cur_t, direct) = Queue.pop q in + if Hashtbl.find_opt visited (cx, cy) <> None then () else begin + Hashtbl.add visited (cx, cy) 1 ; + (*if debug_all then Printf.printf "dealing at (%d, %d) with dir %d\n" cx cy direct ;*) if dgs.(cx).(cy) = Safe then - raise (ReturnBool true) + raise (ReturnInt direct) else if dgs.(cx).(cy) = Blocked then () else begin (* either danger or fatal *) @@ -368,24 +439,23 @@ let move_safe (gd : game_data) (dgs : danger array array) = and newy = cy + snd order.(dir) and newt = cur_t +. interval in if (is_valid newx newy lines cols) && not (newt > dang_time && newt < dang_time +. explosion_time) then - Queue.add (newx, newy, newt) q + Queue.add (newx, newy, newt, direct) q done end end done; - false + 4 with - | ReturnBool b -> b + | ReturnInt b -> b in - if is_valid (cx+1) (cy) lines cols && has_a_safe_path (cx+1) (cy) gd.dt 0 then raise (ReturnInt 2) ; (* South *) - if is_valid (cx-1) (cy) lines cols && has_a_safe_path (cx-1) (cy) gd.dt 1 then raise (ReturnInt 0) ; (* North *) - if is_valid (cx) (cy+1) lines cols && has_a_safe_path (cx) (cy+1) gd.dt 2 then raise (ReturnInt 1) ; (* East *) - if is_valid (cx) (cy-1) lines cols && has_a_safe_path (cx) (cy-1) gd.dt 3 then raise (ReturnInt 3) ; (* West *) + let result = has_a_safe_path (cx) (cy) gd.dt in - (* you're probably dead if the code reaches here... *) - if debug then Printf.printf "[escape] Attempt F...\n"; - 4 + if result <> 4 then result else begin + (* you're probably dead if the code reaches here... *) + if debug_all then Printf.printf "[escape] Attempt F...\n"; + 4 + end with | ReturnInt k -> k ;; @@ -402,23 +472,40 @@ let move_explore (gd: game_data) (dgs : danger array array) = (* find nearest crate and blow it up *) try - let (cx, cy) = (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 visited = Hashtbl.create 100 in - let has_a_safe_path (cx0 : int) (cy0 : int) (simt : float) (vid : int) = + let has_a_safe_path (cx0 : int) (cy0 : int) (simt : float) = let q = Queue.create () in - Queue.add (cx0, cy0, simt) q ; (* everything added to q has valid coords *) - if debug then Printf.printf "[crates] Attempt %d/4...\n" vid ; + Hashtbl.add visited (cx0, cy0) 1 ; + + if is_valid (cx0+1) (cy0) lines cols && not ((simt +. interval) > (level_of_danger dgs.(cx0+1).(cy0)) && (simt +. interval) < (level_of_danger dgs.(cx0+1).(cy0)) +. explosion_time) then begin (* South *) + if debug_all then Printf.printf "[escape] +South\n" ; + Queue.add (cx0+1, cy0, simt +. interval, 2) q ; + end; + if is_valid (cx0-1) (cy0) lines cols && not ((simt +. interval) > (level_of_danger dgs.(cx0-1).(cy0)) && (simt +. interval) < (level_of_danger dgs.(cx0-1).(cy0)) +. explosion_time) then begin (* North *) + if debug_all then Printf.printf "[escape] +North\n" ; + Queue.add (cx0-1, cy0, simt +. interval, 0) q ; + end; + if is_valid (cx0) (cy0+1) lines cols && not ((simt +. interval) > (level_of_danger dgs.(cx0).(cy0+1)) && (simt +. interval) < (level_of_danger dgs.(cx0).(cy0+1)) +. explosion_time) then begin (* East *) + if debug_all then Printf.printf "[escape] +East\n" ; + Queue.add (cx0, cy0+1, simt +. interval, 1) q ; + end; + if is_valid (cx0) (cy0-1) lines cols && not ((simt +. interval) > (level_of_danger dgs.(cx0).(cy0-1)) && (simt +. interval) < (level_of_danger dgs.(cx0).(cy0-1)) +. explosion_time) then begin (* West *) + if debug_all then Printf.printf "[escape] +West\n" ; + Queue.add (cx0, cy0-1, simt +. interval, 3) q ; + end; + + if debug_all then Printf.printf "[crates] Attempt 1/1...\n" ; try while not (Queue.is_empty q) do - let (cx, cy, cur_t) = Queue.pop q in - if Hashtbl.find_opt visited (cx, cy, vid) <> None then () else begin - Hashtbl.add visited (cx, cy, vid) 1 ; - if dgs.(cx).(cy) = Safe then - raise (ReturnBool true) - else if gd.laby.(cx).(cy) = 2 then (* crate *) - raise (ReturnBool true) + let (cx, cy, cur_t, direct) = Queue.pop q in + if Hashtbl.find_opt visited (cx, cy) <> None then () else begin + Hashtbl.add visited (cx, cy) 1 ; + (*if debug_all then Printf.printf "[crates] exploring (%d, %d) at time %f for dir %d\n" cx cy cur_t direct ;*) + if gd.laby.(cx).(cy) = 2 then (* crate *) + raise (ReturnInt direct) else if dgs.(cx).(cy) = Blocked then () else begin (* either danger or fatal *) @@ -428,51 +515,84 @@ let move_explore (gd: game_data) (dgs : danger array array) = and newy = cy + snd order.(dir) and newt = cur_t +. interval in if (is_valid newx newy lines cols) && not (newt > dang_time && newt < dang_time +. explosion_time) then - Queue.add (newx, newy, newt) q + Queue.add (newx, newy, newt, direct) q done end end done; - false + (-1) with - | ReturnBool b -> b + | ReturnInt k -> k in - (* check if there's a crate next to the player *) - if is_valid (cx+1) (cy) lines cols && gd.laby.(cx+1).(cy) = 2 then begin (* Crate at South *) + let move_with_caution (exit : bool) = + let res = has_a_safe_path cxi cyi gd.dt in + if res <> -1 then begin + if debug_all then Printf.printf "[crates] success!\n" ; + res + end + else begin + if exit then + current_status := ClaimLand ; + 4 + end + in + + let safe_path_with_bomb (bx : int) (by : int) (bsize : int) = + (* simulate the placement of a bomb, and test if that stills allows safe escape *) + 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 (bx + w*(fst order.(dir)), by + w*(snd order.(dir))) (Danger 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 result = move_with_caution false in + Hashtbl.iter (fun (k1, k2) v -> dgs.(k1).(k2) <- v) saved_dgs ; + result + in + + (* check if there's a crate next to the player, and if upon placing a bomb it won't block the player *) + if is_valid (cxi+1) (cyi) lines cols && gd.laby.(cxi+1).(cyi) = 2 && (safe_path_with_bomb cxi cyi gd.players.(pid).bomb_radius <> 4) then begin (* Crate at South *) current_status := EscapeDeath ; action := 1; - if debug then Printf.printf "Fire in the hole!\n" ; - raise (ReturnInt 4) ; - end; - if is_valid (cx-1) (cy) lines cols && gd.laby.(cx-1).(cy) = 2 then begin (* Crate at North *) - current_status := EscapeDeath ; - action := 1; - if debug then Printf.printf "Fire in the hole!\n" ; - raise (ReturnInt 4) ; - end; - if is_valid (cx) (cy+1) lines cols && gd.laby.(cx).(cy+1) = 2 then begin (* Crate at East *) - current_status := EscapeDeath ; - action := 1; - if debug then Printf.printf "Fire in the hole!\n" ; - raise (ReturnInt 4) ; - end; - if is_valid (cx) (cy-1) lines cols && gd.laby.(cx).(cy-1) = 2 then begin (* Crate at West *) - current_status := EscapeDeath ; - action := 1; - if debug then Printf.printf "Fire in the hole!\n" ; + if debug_all then Printf.printf "Fire in the hole!\n" ; raise (ReturnInt 4) ; end; + if is_valid (cxi-1) (cyi) lines cols && gd.laby.(cxi-1).(cyi) = 2 && (safe_path_with_bomb cxi cyi gd.players.(pid).bomb_radius <> 4) then begin (* Crate at North *) + current_status := EscapeDeath ; + action := 1; + if debug_all then Printf.printf "Fire in the hole!\n" ; + raise (ReturnInt 4) ; + end; + + if is_valid (cxi) (cyi+1) lines cols && gd.laby.(cxi).(cyi+1) = 2 && (safe_path_with_bomb cxi cyi gd.players.(pid).bomb_radius <> 4) then begin (* Crate at East *) + current_status := EscapeDeath ; + action := 1; + if debug_all then Printf.printf "Fire in the hole!\n" ; + raise (ReturnInt 4) ; + end; + + if is_valid (cxi) (cyi-1) lines cols && gd.laby.(cxi).(cyi-1) = 2 && (safe_path_with_bomb cxi cyi gd.players.(pid).bomb_radius <> 4) then begin (* Crate at West *) + current_status := EscapeDeath ; + action := 1; + if debug_all then Printf.printf "Fire in the hole!\n" ; + raise (ReturnInt 4) ; + end; + + if debug_all then Printf.printf "[crates] Cannot bomb now, searching for a crate...\n"; + (* go to one without stepping into a dangerous tile *) - if is_valid (cx+1) (cy) lines cols && has_a_safe_path (cx+1) (cy) gd.dt 0 then raise (ReturnInt 2) ; (* South *) - if is_valid (cx-1) (cy) lines cols && has_a_safe_path (cx-1) (cy) gd.dt 1 then raise (ReturnInt 0) ; (* North *) - if is_valid (cx) (cy+1) lines cols && has_a_safe_path (cx) (cy+1) gd.dt 2 then raise (ReturnInt 1) ; (* East *) - if is_valid (cx) (cy-1) lines cols && has_a_safe_path (cx) (cy-1) gd.dt 3 then raise (ReturnInt 3) ; (* West *) - - (* no crates ? Go for kills *) - if debug then Printf.printf "[crates] Attempt F...\n"; - 4 + raise (ReturnInt (move_with_caution true)) ; with | ReturnInt k -> k ;; @@ -481,9 +601,12 @@ let move_explore (gd: game_data) (dgs : danger array array) = let game_d = parse_input "input_test.txt" ;; let dangers = evaluate_dangers game_d ;; +let gains = cell_values game_d ;; + print_game_data game_d ;; print_danger_levels dangers ;; +print_gain_map gains ;; -Printf.printf "move at ";; +Printf.printf "move at\n";; print_direction (move_explore game_d dangers) ;; Printf.printf "\n" ;; \ No newline at end of file