dsh-eval-guard 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/README.md +91 -13
  2. package/assets/bomberman/workspace.zip +0 -0
  3. package/assets/commit0/instance.json +30 -0
  4. package/assets/commit0/workspace.zip +0 -0
  5. package/assets/ctf/workspace.zip +0 -0
  6. package/assets/featurebench/hidden/test_regression.py +690 -0
  7. package/assets/featurebench/instance.json +16 -0
  8. package/assets/featurebench/workspace.zip +0 -0
  9. package/assets/swe-bench-pro/hidden/test.patch +36 -0
  10. package/assets/swe-bench-pro/instance.json +10 -0
  11. package/assets/swe-bench-pro/workspace.zip +0 -0
  12. package/assets/tank/workspace.zip +0 -0
  13. package/eval/README.md +18 -0
  14. package/eval/arena/arena/README.md +21 -0
  15. package/eval/arena/arena/bt.py +104 -0
  16. package/eval/arena/arena/clock.py +15 -0
  17. package/eval/arena/arena/core.py +265 -0
  18. package/eval/arena/arena/run.cmd +24 -0
  19. package/eval/arena/arena/run.sh +11 -0
  20. package/eval/arena/arena/schedule.py +79 -0
  21. package/eval/arena/arena/tournament.py +183 -0
  22. package/eval/arena/bomberman/bots/README.md +16 -0
  23. package/eval/arena/bomberman/bots/deepseek-v4.1-flash.cpp +447 -0
  24. package/eval/arena/bomberman/bots/doubao-seed-2.1.cpp +542 -0
  25. package/eval/arena/bomberman/bots/glm-5.3.cpp +406 -0
  26. package/eval/arena/bomberman/bots/gpt-6-astra.cpp +768 -0
  27. package/eval/arena/bomberman/bots/gpt-6-sol.cpp +444 -0
  28. package/eval/arena/bomberman/bots/kimi-k3.cpp +432 -0
  29. package/eval/arena/bomberman/bots/mimo-v2.6-pro.cpp +529 -0
  30. package/eval/arena/bomberman/bots/opus-5.5.cpp +548 -0
  31. package/eval/arena/bomberman/bots/qwen-3.8-max.cpp +836 -0
  32. package/eval/arena/bomberman/tournament/README.md +11 -0
  33. package/eval/arena/bomberman/tournament/bt.py +56 -0
  34. package/eval/arena/bomberman/tournament/evaluate.py +199 -0
  35. package/eval/arena/bomberman/tournament/run.py +79 -0
  36. package/eval/arena/bomberman/tournament/schedule-2to10.json.gz +0 -0
  37. package/eval/arena/bomberman/workspace/MANIFEST.json +13 -0
  38. package/eval/arena/bomberman/workspace/README.md +29 -0
  39. package/eval/arena/bomberman/workspace/RULES.md +100 -0
  40. package/eval/arena/bomberman/workspace/baseline.cpp +240 -0
  41. package/eval/arena/bomberman/workspace/clock.py +25 -0
  42. package/eval/arena/bomberman/workspace/engine/arena.py +198 -0
  43. package/eval/arena/bomberman/workspace/engine/build.py +35 -0
  44. package/eval/arena/bomberman/workspace/engine/engine.py +256 -0
  45. package/eval/arena/bomberman/workspace/engine/verify_replay.py +24 -0
  46. package/eval/arena/bomberman/workspace/run.cmd +28 -0
  47. package/eval/arena/bomberman/workspace/run.sh +16 -0
  48. package/eval/arena/bomberman/workspace/viewer/index.html +42 -0
  49. package/eval/arena/ctf/bots/README.md +18 -0
  50. package/eval/arena/ctf/bots/deepseek-v4.1-flash.cpp +601 -0
  51. package/eval/arena/ctf/bots/doubao-seed-2.1-turbo.cpp +320 -0
  52. package/eval/arena/ctf/bots/fable-5.1.cpp +634 -0
  53. package/eval/arena/ctf/bots/glm-5.3.cpp +689 -0
  54. package/eval/arena/ctf/bots/gpt-6-astra.cpp +657 -0
  55. package/eval/arena/ctf/bots/gpt-6.1-sol.cpp +725 -0
  56. package/eval/arena/ctf/bots/kimi-k3.cpp +667 -0
  57. package/eval/arena/ctf/bots/mimo-v2.6-pro.cpp +533 -0
  58. package/eval/arena/ctf/bots/opus-5.5.cpp +645 -0
  59. package/eval/arena/ctf/bots/qwen-3.8-max.cpp +726 -0
  60. package/eval/arena/ctf/bots/sonnet-5.5.cpp +569 -0
  61. package/eval/arena/ctf/tournament/README.md +15 -0
  62. package/eval/arena/ctf/tournament/formal-2to8.json +31 -0
  63. package/eval/arena/ctf/tournament/formal-9to15.json +31 -0
  64. package/eval/arena/ctf/workspace/README.md +41 -0
  65. package/eval/arena/ctf/workspace/RULES.md +119 -0
  66. package/eval/arena/ctf/workspace/arena.py +186 -0
  67. package/eval/arena/ctf/workspace/baseline.cpp +257 -0
  68. package/eval/arena/ctf/workspace/clock.py +15 -0
  69. package/eval/arena/ctf/workspace/core.py +265 -0
  70. package/eval/arena/ctf/workspace/engine.py +389 -0
  71. package/eval/arena/ctf/workspace/run.cmd +24 -0
  72. package/eval/arena/ctf/workspace/run.sh +11 -0
  73. package/eval/arena/ctf/workspace/viewer.html +71 -0
  74. package/eval/arena/land/bots/README.md +17 -0
  75. package/eval/arena/land/bots/deepseek-4.1f@workbuddy#1/bot.cpp +608 -0
  76. package/eval/arena/land/bots/glm-5.3@workbuddy#1/bot.cpp +521 -0
  77. package/eval/arena/land/bots/gpt-6-astra@codex#1/bot.cpp +373 -0
  78. package/eval/arena/land/bots/gpt-6-sol@codex#1/bot.cpp +341 -0
  79. package/eval/arena/land/bots/kimi-k3@workbuddy#1/bot.cpp +492 -0
  80. package/eval/arena/land/bots/mimo-2.6-pro@zcode#1/bot.cpp +652 -0
  81. package/eval/arena/land/bots/mystery-model@zcode#1/bot.cpp +466 -0
  82. package/eval/arena/land/bots/opus-5.5@claude-code#1/bot.cpp +630 -0
  83. package/eval/arena/land/bots/sonnet-5@claude-code#1/bot.cpp +619 -0
  84. package/eval/arena/land/tournament/make_replay_page.py +17 -0
  85. package/eval/arena/land/tournament/rate.py +290 -0
  86. package/eval/arena/land/tournament/round_robin.py +172 -0
  87. package/eval/arena/land/tournament/sparring.cpp +356 -0
  88. package/eval/arena/land/workspace/RULES.md +114 -0
  89. package/eval/arena/land/workspace/TASK.md +46 -0
  90. package/eval/arena/land/workspace/anchors/.build/greedy_f2e6d2dea5ca +0 -0
  91. package/eval/arena/land/workspace/anchors/greedy.cpp +194 -0
  92. package/eval/arena/land/workspace/anchors/random.cpp +80 -0
  93. package/eval/arena/land/workspace/clock.py +64 -0
  94. package/eval/arena/land/workspace/engine/build.py +33 -0
  95. package/eval/arena/land/workspace/engine/game.py +273 -0
  96. package/eval/arena/land/workspace/engine/referee.py +308 -0
  97. package/eval/arena/land/workspace/starter/.build/bot_be32b45b4699 +0 -0
  98. package/eval/arena/land/workspace/starter/bot.cpp +82 -0
  99. package/eval/arena/land/workspace/viewer/viewer.html +210 -0
  100. package/eval/arena/tank/bots/README.md +24 -0
  101. package/eval/arena/tank/bots/half1/deepseek-v4.1-flash.cpp +367 -0
  102. package/eval/arena/tank/bots/half1/doubao-seed-evolving.cpp +402 -0
  103. package/eval/arena/tank/bots/half1/gemini-4-argon.cpp +1132 -0
  104. package/eval/arena/tank/bots/half1/glm-5.3.cpp +551 -0
  105. package/eval/arena/tank/bots/half1/gpt-6-astra.cpp +233 -0
  106. package/eval/arena/tank/bots/half1/gpt-6.1-sol-ultrafast.cpp +350 -0
  107. package/eval/arena/tank/bots/half1/gpt-6.1-sol.cpp +78 -0
  108. package/eval/arena/tank/bots/half1/grok-4.7.cpp +1099 -0
  109. package/eval/arena/tank/bots/half1/haiku-5.5.cpp +210 -0
  110. package/eval/arena/tank/bots/half1/kimi-k3.cpp +353 -0
  111. package/eval/arena/tank/bots/half1/mimo-v2.6-pro.cpp +336 -0
  112. package/eval/arena/tank/bots/half1/muse-wonder-full.cpp +560 -0
  113. package/eval/arena/tank/bots/half1/opus-5.5.cpp +435 -0
  114. package/eval/arena/tank/bots/half1/qwen-3.8-max.cpp +537 -0
  115. package/eval/arena/tank/bots/half2/deepseek-v4.1-flash.cpp +425 -0
  116. package/eval/arena/tank/bots/half2/doubao-seed-evolving.cpp +308 -0
  117. package/eval/arena/tank/bots/half2/gemini-4-argon.cpp +1390 -0
  118. package/eval/arena/tank/bots/half2/glm-5.3.cpp +651 -0
  119. package/eval/arena/tank/bots/half2/gpt-6-astra.cpp +241 -0
  120. package/eval/arena/tank/bots/half2/gpt-6.1-sol-ultrafast.cpp +356 -0
  121. package/eval/arena/tank/bots/half2/gpt-6.1-sol.cpp +87 -0
  122. package/eval/arena/tank/bots/half2/grok-4.7.cpp +1205 -0
  123. package/eval/arena/tank/bots/half2/haiku-5.5.cpp +210 -0
  124. package/eval/arena/tank/bots/half2/kimi-k3.cpp +487 -0
  125. package/eval/arena/tank/bots/half2/mimo-v2.6-pro.cpp +336 -0
  126. package/eval/arena/tank/bots/half2/muse-wonder-full.cpp +560 -0
  127. package/eval/arena/tank/bots/half2/opus-5.5.cpp +476 -0
  128. package/eval/arena/tank/bots/half2/qwen-3.8-max.cpp +392 -0
  129. package/eval/arena/tank/tournament/README.md +24 -0
  130. package/eval/arena/tank/tournament/bt.py +218 -0
  131. package/eval/arena/tank/tournament/final.json +202 -0
  132. package/eval/arena/tank/tournament/halftime.json +146 -0
  133. package/eval/arena/tank/tournament/progress.json +911 -0
  134. package/eval/arena/tank/tournament/schedule.py +100 -0
  135. package/eval/arena/tank/tournament/sparring.cpp +928 -0
  136. package/eval/arena/tank/tournament/tournament.py +1426 -0
  137. package/eval/arena/tank/workspace/README.md +169 -0
  138. package/eval/arena/tank/workspace/RULES.md +443 -0
  139. package/eval/arena/tank/workspace/arena.py +862 -0
  140. package/eval/arena/tank/workspace/baseline.cpp +259 -0
  141. package/eval/arena/tank/workspace/clock.py +103 -0
  142. package/eval/arena/tank/workspace/core.py +712 -0
  143. package/eval/arena/tank/workspace/engine.py +573 -0
  144. package/eval/arena/tank/workspace/history/.lock +0 -0
  145. package/eval/arena/tank/workspace/history/20261017-193610-08715287f91f-bot.cpp +109 -0
  146. package/eval/arena/tank/workspace/history/20261017-193619-f00b2d5635fa-gpt-6-astra.cpp +241 -0
  147. package/eval/arena/tank/workspace/history/20261017-193643-63319e0a2b1a-gpt-6_1-sol-ultrafast.cpp +356 -0
  148. package/eval/arena/tank/workspace/history/20261017-193647-41c1341d0a8a-gemini-4-argon.cpp +1390 -0
  149. package/eval/arena/tank/workspace/history/20261017-193652-e34c0f45539a-gpt-6_1-sol.cpp +87 -0
  150. package/eval/arena/tank/workspace/history/20261017-193654-c026348ce96e-opus-5_5.cpp +476 -0
  151. package/eval/arena/tank/workspace/history/20261017-193655-4a21366e94d1-muse-wonder-full.cpp +560 -0
  152. package/eval/arena/tank/workspace/history/20261017-193657-dbc4e9969c52-mimo-v2_6-pro.cpp +336 -0
  153. package/eval/arena/tank/workspace/history/20261017-193703-723cd036eb31-grok-4_7.cpp +1205 -0
  154. package/eval/arena/tank/workspace/history/20261017-193707-1ebbb227be68-deepseek-v4_1-flash.cpp +425 -0
  155. package/eval/arena/tank/workspace/history/20261017-193709-aeb0e7202ad5-doubao-seed-evolving.cpp +308 -0
  156. package/eval/arena/tank/workspace/history/20261017-193710-b21ebeb9bc76-kimi-k3.cpp +487 -0
  157. package/eval/arena/tank/workspace/history/20261017-193712-54cd86531905-haiku-5_5.cpp +210 -0
  158. package/eval/arena/tank/workspace/history/20261017-193714-efdb8e35c0bf-qwen-3_8-max.cpp +392 -0
  159. package/eval/arena/tank/workspace/history/20261017-193715-681423c23fdb-glm-5_3.cpp +651 -0
  160. package/eval/arena/tank/workspace/history/20261017-193717-1a8b3c75181d-sparring.cpp +928 -0
  161. package/eval/arena/tank/workspace/history/20261017-193720-1e0803a541e8-baseline.cpp +259 -0
  162. package/eval/arena/tank/workspace/history/log.jsonl +103 -0
  163. package/eval/arena/tank/workspace/judge/cycles.hpp +53 -0
  164. package/eval/arena/tank/workspace/judge/fast.cpp +337 -0
  165. package/eval/arena/tank/workspace/judge/referee.cpp +125 -0
  166. package/eval/arena/tank/workspace/judge/speed.cpp +99 -0
  167. package/eval/arena/tank/workspace/run.cmd +31 -0
  168. package/eval/arena/tank/workspace/run.sh +23 -0
  169. package/eval/arena/tank/workspace/tank.hpp +1762 -0
  170. package/eval/arena/tank/workspace/tank_main.cpp +215 -0
  171. package/eval/arena/tank/workspace/viewer.html +1150 -0
  172. package/eval/arena/warehouse/workspace/SPEC.md +130 -0
  173. package/eval/arena/warehouse/workspace/TASK.md +71 -0
  174. package/eval/arena/warehouse/workspace/baseline/common.h +88 -0
  175. package/eval/arena/warehouse/workspace/baseline/main.cpp +27 -0
  176. package/eval/arena/warehouse/workspace/baseline/old_stuff.cpp +87 -0
  177. package/eval/arena/warehouse/workspace/baseline/sim.cpp +427 -0
  178. package/eval/arena/warehouse/workspace/baseline/util.cpp +220 -0
  179. package/eval/arena/warehouse/workspace/clock.py +42 -0
  180. package/eval/arena/warehouse/workspace/src/common.h +88 -0
  181. package/eval/arena/warehouse/workspace/src/main.cpp +27 -0
  182. package/eval/arena/warehouse/workspace/src/old_stuff.cpp +87 -0
  183. package/eval/arena/warehouse/workspace/src/sim.cpp +427 -0
  184. package/eval/arena/warehouse/workspace/src/util.cpp +220 -0
  185. package/eval/arena/warehouse/workspace/tools/bench.py +119 -0
  186. package/eval/arena/warehouse/workspace/tools/check_input.py +161 -0
  187. package/eval/arena/warehouse/workspace/tools/gen.py +132 -0
  188. package/eval/arena/warehouse/workspace/tools/measure.py +107 -0
  189. package/eval/arena/warehouse/workspace/workloads/public/pub_crowded.in +1420 -0
  190. package/eval/arena/warehouse/workspace/workloads/public/pub_crowded.out +9162 -0
  191. package/eval/arena/warehouse/workspace/workloads/public/pub_dynamic.in +1465 -0
  192. package/eval/arena/warehouse/workspace/workloads/public/pub_dynamic.out +3439 -0
  193. package/eval/arena/warehouse/workspace/workloads/public/pub_flood.in +2757 -0
  194. package/eval/arena/warehouse/workspace/workloads/public/pub_flood.out +3126 -0
  195. package/eval/arena/warehouse/workspace/workloads/public/pub_small.in +731 -0
  196. package/eval/arena/warehouse/workspace/workloads/public/pub_small.out +2578 -0
  197. package/eval/arena/warehouse/workspace/workloads/public/pub_wide.in +528 -0
  198. package/eval/arena/warehouse/workspace/workloads/public/pub_wide.out +2026 -0
  199. package/eval/bomberman.py +20 -0
  200. package/eval/commit0.py +21 -0
  201. package/eval/common.py +61 -0
  202. package/eval/ctf.py +20 -0
  203. package/eval/featurebench.py +25 -0
  204. package/eval/land.py +20 -0
  205. package/eval/legacy/bomberman-prices.json +4 -0
  206. package/eval/legacy/bomberman.py +161 -0
  207. package/eval/legacy/commit0.py +91 -0
  208. package/eval/legacy/ctf-prices.json +4 -0
  209. package/eval/legacy/ctf.py +178 -0
  210. package/eval/legacy/featurebench.py +103 -0
  211. package/eval/legacy/land-prices.json +4 -0
  212. package/eval/legacy/land.py +177 -0
  213. package/eval/legacy/swe_bench_pro.py +116 -0
  214. package/eval/legacy/tank-prices.json +3 -0
  215. package/eval/legacy/tank.py +408 -0
  216. package/eval/legacy/warehouse-prices.json +4 -0
  217. package/eval/legacy/warehouse.py +365 -0
  218. package/eval/swe-bench-pro.py +25 -0
  219. package/eval/tank.py +20 -0
  220. package/eval/warehouse.py +20 -0
  221. package/lib/client/index.js +376 -63
  222. package/lib/client/index.js.map +1 -1
  223. package/lib/index.js +684 -27
  224. package/package.json +2 -1
@@ -0,0 +1,373 @@
1
+ // Territory contest bot. Standard C++20, one process and one thread.
2
+ // Uses exact flood-fill scoring, directed opponent reachability, a diverse
3
+ // family of closed excursions, and receding-horizon return-path searches.
4
+ // Interceptions account for actual enemy return times and multiplayer rank value.
5
+ // Search has a soft 4 ms wall-clock budget, leaving room for protocol overhead.
6
+ #include <algorithm>
7
+ #include <array>
8
+ #include <chrono>
9
+ #include <cmath>
10
+ #include <cstdint>
11
+ #include <deque>
12
+ #include <iostream>
13
+ #include <limits>
14
+ #include <memory>
15
+ #include <queue>
16
+ #include <string>
17
+ #include <utility>
18
+ #include <vector>
19
+ using namespace std;
20
+ namespace territory {
21
+ constexpr int V=2304, INF=10000;
22
+ const int dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};
23
+ const char dc[5]="UDLR";
24
+ struct Player { int x=0,y=0,dir=0,len=0,area=0,deaths=0; };
25
+ struct State {int turn=0; array<Player,4> p; array<int,V> own{},tr{};};
26
+ struct Candidate {double score; int anchor,d,s,a,b,c=-1;};
27
+ struct Eval { double value=0; int gain=0,len=0,margin=INF,approach=0; bool valid=false; vector<int> path; };
28
+ struct Bot {
29
+ int W,H,N,me,T,S,spawn[4],initdir[4],nb[V][4],protect[V];
30
+ int enemy[4][V],danger[V],home[V],prev[V],pd[V],reach[V],estate[V];
31
+ int nxtOwn[V][4],rayMin[V][4][49];
32
+ double weight[V],psum[49][49];
33
+ vector<int> plan; int expected=-1,lastDeaths=0,lastLen=0,planAge=0; int optimism=8; int baseOptimism=-1; deque<int> recentDeaths; bool safetyGate=false, preplan=true, adaptive=true, bridges=true; double attackScale=1.0, efficiency=-1.0, baseEfficiency=-2.0; bool rankAware=true, smartHunt=true, altReturns=false, navigation=false, cautiousHunt=true; double compactness=0.0, edgeValue=0.0; int entry=-1; double importance[4], threatValue[4], huntScore=0; int enemyRet[4];
34
+ State st; uint64_t randomState=73192871;
35
+ chrono::steady_clock::time_point began; int evaluated=0;
36
+ Bot(int w,int h,int n,int m,int turns,const vector<int>& sp):W(w),H(h),N(n),me(m),T(turns),S(w*h){
37
+ cautiousHunt=true;if(N==4)attackScale=0.9;
38
+ for(int p=0;p<N;p++)spawn[p]=sp[p],initdir[p]=0;
39
+ for(int k=0;k<S;k++) { int x=k%W,y=k/W; protect[k]=-1;for(int d=0;d<4;d++){int xx=x+dx[d],yy=y+dy[d];nb[k][d]=(xx<0||yy<0||xx>=W||yy>=H)?-1:yy*W+xx;}for(int p=0;p<N;p++)if(abs(x-spawn[p]%W)<=1&&abs(y-spawn[p]/W)<=1)protect[k]=p; }
40
+ }
41
+ int pos(int p)const{return st.p[p].y*W+st.p[p].x;}
42
+ int man(int a,int b)const{return abs(a%W-b%W)+abs(a/W-b/W);}
43
+ uint32_t rnd(){randomState^=randomState<<13;randomState^=randomState>>7;randomState^=randomState<<17;return uint32_t(randomState);}
44
+ bool expired(){return chrono::duration<double,milli>(chrono::steady_clock::now()-began).count()>4.0;}
45
+ // Shortest opponent arrival times. Its old trail is impassable until it returns home.
46
+ void enemyFields(){
47
+ fill(danger,danger+S,INF);
48
+ for(int p=0;p<N;p++)if(p!=me){
49
+ int dis[2*V],q[2*V],a=0,b=0;fill(dis,dis+2*S,INF);
50
+ int start=pos(p),mode=st.p[p].len==0;dis[start+mode*S]=0;
51
+ for(int d=0;d<4;d++)if(d!=(st.p[p].dir^1)){
52
+ int v=nb[start][d];if(v<0||(!mode&&st.tr[v]==p))continue;
53
+ int u=v+(mode||st.own[v]==p)*S;
54
+ if(dis[u]>1)dis[u]=1,q[b++]=u;
55
+ }
56
+ while(a<b){int u=q[a++],k=u%S,clear=u>=S;
57
+ for(int d=0;d<4;d++){int v=nb[k][d];if(v<0||(!clear&&st.tr[v]==p))continue;int v2=v+(clear||st.own[v]==p)*S;if(dis[v2]>dis[u]+1){dis[v2]=dis[u]+1;q[b++]=v2;}}
58
+ }
59
+ for(int k=0;k<S;k++){
60
+ enemy[p][k]=min(dis[k],dis[k+S]);
61
+ // A player can deliberately reset; do not assume an undefended spawn stays empty.
62
+ int reset=man(start,spawn[p])>8?8:INF;
63
+ enemy[p][k]=min(enemy[p][k],reset+man(spawn[p],k));
64
+ danger[k]=min(danger[k],enemy[p][k]);
65
+ }
66
+ }
67
+ }
68
+ void homeField(){
69
+ int q[V],a=0,b=0;fill(home,home+S,INF);
70
+ for(int k=0;k<S;k++)if(st.own[k]==me&&st.tr[k]!=me)home[k]=0,q[b++]=k;
71
+ while(a<b){int k=q[a++];for(int d=0;d<4;d++){int v=nb[k][d];if(v>=0&&st.tr[v]!=me&&home[v]>home[k]+1){home[v]=home[k]+1;q[b++]=v;}}}
72
+ }
73
+ bool moveSafe(int k,int d,int heading)const {return d!=(heading^1)&&nb[k][d]>=0&&st.tr[nb[k][d]]!=me;}
74
+ bool collision(int k,int d)const{
75
+ int v=nb[k][d];if(v<0)return true;
76
+ for(int p=0;p<N;p++)if(p!=me){int e=pos(p);for(int z=0;z<4;z++)if(z!=(st.p[p].dir^1)&&nb[e][z]>=0&&st.tr[nb[e][z]]!=p){int t=nb[e][z];if(t==v||(v==e&&t==k))return true;}}
77
+ return false;
78
+ }
79
+ vector<int> returnPath(const vector<int>& prefix={}){
80
+ int blocked[V]={0},k=pos(me),heading=st.p[me].dir;
81
+ for(int v=0;v<S;v++)blocked[v]=st.tr[v]==me;
82
+ bool outside=st.p[me].len>0;
83
+ for(int d:prefix){if(d==(heading^1)||nb[k][d]<0||blocked[nb[k][d]])return {};k=nb[k][d];heading=d;if(st.own[k]==me&&outside)return prefix;if(st.own[k]!=me)blocked[k]=1,outside=true;}
84
+ int dis[V],par[V],pdir[V],q[V],a=0,b=0;fill(dis,dis+S,INF);dis[k]=0;
85
+ for(int d=0;d<4;d++)if(d!=(heading^1)){int v=nb[k][d];if(v<0||blocked[v]||(prefix.empty()&&collision(k,d)))continue;dis[v]=1;par[v]=k;pdir[v]=d;q[b++]=v;}
86
+ int end=-1;
87
+ while(a<b){int u=q[a++];if(st.own[u]==me){end=u;break;}
88
+ // Prefer the side farther away from the enemy among equally short returns.
89
+ int dirs[4]={0,1,2,3};sort(dirs,dirs+4,[&](int d,int e){int v=nb[u][d],w=nb[u][e];return (v<0?-INF:danger[v])>(w<0?-INF:danger[w]);});
90
+ for(int d:dirs){int v=nb[u][d];if(v<0||blocked[v]||dis[v]!=INF)continue;dis[v]=dis[u]+1;par[v]=u;pdir[v]=d;q[b++]=v;}
91
+ }
92
+ if(end<0)return {};vector<int> tail;for(int v=end;v!=k;v=par[v])tail.push_back(pdir[v]);reverse(tail.begin(),tail.end());vector<int> out=prefix;out.insert(out.end(),tail.begin(),tail.end());return out;
93
+ }
94
+ vector<vector<int>> contourReturns(){
95
+ vector<vector<int>> results;int dis[V],q[V],a=0,b=0;fill(dis,dis+S,INF);
96
+ for(int k=0;k<S;k++)if(st.own[k]==me&&st.tr[k]!=me)dis[k]=0,q[b++]=k;
97
+ while(a<b){int u=q[a++];for(int d=0;d<4;d++){int v=nb[u][d];if(v>=0&&st.tr[v]!=me&&dis[v]==INF)dis[v]=dis[u]+1,q[b++]=v;}}
98
+ int anchor=entry>=0?entry:spawn[me];auto cross=[&](int u,int v){return (u%W)*(v/W)-(v%W)*(u/W);};
99
+ int start=pos(me),minimum=INF;for(int d=0;d<4;d++)if(moveSafe(start,d,st.p[me].dir)&&!collision(start,d))minimum=min(minimum,dis[nb[start][d]]+1);
100
+ if(minimum>=INF)return results;
101
+ for(int sign:{-1,1}){
102
+ int val[V],follow[V];fill(val,val+S,-100000000);
103
+ for(int i=0;i<b;i++){int u=q[i];if(dis[u]==0){val[u]=sign*cross(u,anchor);continue;}
104
+ for(int d=0;d<4;d++){int v=nb[u][d];if(v>=0&&dis[v]+1==dis[u]){int z=val[v]+sign*cross(u,v);if(z>val[u])val[u]=z,follow[u]=d;}}
105
+ }
106
+ int first=-1,best=-100000000;
107
+ for(int d=0;d<4;d++)if(moveSafe(start,d,st.p[me].dir)&&!collision(start,d)){int v=nb[start][d];if(dis[v]+1==minimum){int z=val[v]+sign*cross(start,v);if(z>best)best=z,first=d;}}
108
+ if(first<0)continue;vector<int> path{first};int u=nb[start][first];while(dis[u]>0){int d=follow[u];path.push_back(d);u=nb[u][d];}results.push_back(path);
109
+ }
110
+ return results;
111
+ }
112
+ Eval evaluate(const vector<int>& moves,bool flood=true){
113
+ Eval e;if(moves.empty())return e;
114
+ int mark[V]={0},k=pos(me),heading=st.p[me].dir;bool out=st.p[me].len>0;int risk=INF;
115
+ for(int u=0;u<S;u++)if(st.tr[u]==me){mark[u]=1;risk=min(risk,danger[u]);}
116
+ int n=0;for(int d:moves){if(d==(heading^1)||nb[k][d]<0)return e;k=nb[k][d];heading=d;if(mark[k])return e;n++;e.path.push_back(d);
117
+ if(n==1&&collision(pos(me),d))risk=min(risk,0);
118
+ if(st.own[k]==me){if(out)break;}else {if(!out)e.approach=n-1;out=true;mark[k]=1;risk=min(risk,danger[k]);}
119
+ }
120
+ if(!out||st.own[k]!=me||n>T-st.turn)return e;
121
+ e.valid=true;e.len=n;e.margin=risk-n;
122
+ if(!flood)return e;
123
+ int seen[V]={0},q[V],a=0,b=0;
124
+ auto add=[&](int u){if(!seen[u]&&!mark[u]&&st.own[u]!=me){seen[u]=1;q[b++]=u;}};
125
+ for(int x=0;x<W;x++)add(x),add((H-1)*W+x);
126
+ for(int y=0;y<H;y++)add(y*W),add(y*W+W-1);
127
+ while(a<b){int u=q[a++];for(int d=0;d<4;d++){int v=nb[u][d];if(v>=0)add(v);}}
128
+ for(int u=0;u<S;u++)if((mark[u]||!seen[u])&&st.own[u]!=me&&(protect[u]<0||protect[u]==me)){e.gain++;e.value+=weight[u];}
129
+ if(compactness>0){
130
+ int delta=0;auto after=[&](int u){return st.own[u]==me||((mark[u]||!seen[u])&&(protect[u]<0||protect[u]==me));};
131
+ for(int u=0;u<S;u++)for(int d:{1,3}){int v=nb[u][d];if(v>=0)delta+=(after(u)!=after(v))-((st.own[u]==me)!=(st.own[v]==me));}
132
+ e.value-=compactness*delta;
133
+ }
134
+ return e;
135
+ }
136
+ double utility(const Eval&e)const{
137
+ if(!e.valid||e.gain==0)return -1e9;
138
+ int slack=e.margin+optimism+(navigation?int(e.approach*0.8):0); double risk=slack>=2?1.0:slack>=0?0.86:slack>=-2?0.48:slack>=-4?0.17:0.025;
139
+ return e.value* risk/pow(e.len+4.0,efficiency);
140
+ }
141
+ vector<int> approach(int anchor){vector<int> path;for(int k=anchor;k!=pos(me);k=prev[k])path.push_back(pd[k]);reverse(path.begin(),path.end());return path;}
142
+ void prepPlan(){
143
+ int q[V],a=0,b=0,k=pos(me);fill(reach,reach+S,INF);reach[k]=0;estate[k]=st.p[me].dir;q[b++]=k;
144
+ while(a<b){int u=q[a++];for(int d=0;d<4;d++){if(d==(estate[u]^1))continue;int v=nb[u][d];if(v<0||st.own[v]!=me||st.tr[v]==me||reach[v]!=INF)continue;if(u==k&&collision(k,d))continue;reach[v]=reach[u]+1;prev[v]=u;pd[v]=d;estate[v]=d;q[b++]=v;}}
145
+ for(int u=0;u<S;u++)for(int d=0;d<4;d++){
146
+ nxtOwn[u][d]=INF;rayMin[u][d][0]=INF;int v=u,mn=INF;
147
+ for(int len=1;len<=48;len++){v=v<0?-1:nb[v][d];if(v<0){rayMin[u][d][len]=-INF;continue;}if(st.own[v]==me&&nxtOwn[u][d]==INF)nxtOwn[u][d]=len;if(st.own[v]!=me)mn=min(mn,danger[v]);rayMin[u][d][len]=mn;}
148
+ }
149
+ for(int y=0;y<=H;y++)for(int x=0;x<=W;x++)psum[y][x]=0;
150
+ for(int y=0;y<H;y++)for(int x=0;x<W;x++)psum[y+1][x+1]=weight[y*W+x]+psum[y][x+1]+psum[y+1][x]-psum[y][x];
151
+ }
152
+ double rect(int x1,int y1,int x2,int y2){if(x1>x2)swap(x1,x2);if(y1>y2)swap(y1,y2);return psum[y2+1][x2+1]-psum[y1][x2+1]-psum[y2+1][x1]+psum[y1][x1];}
153
+ vector<int> expand(){
154
+ prepPlan();vector<pair<double,pair<int,int>>> anchors;
155
+ for(int k=0;k<S;k++)if(reach[k]<INF)for(int d=0;d<4;d++){int v=nb[k][d];if(v<0||st.own[v]==me||d==(estate[k]^1))continue;
156
+ double potential=0;for(int a=1;a<=8;a++)for(int b=-5;b<=5;b++){int x=k%W+dx[d]*a+(d<2?b:0),y=k/W+dy[d]*a+(d>=2?b:0);if(x>=0&&y>=0&&x<W&&y<H)potential+=weight[y*W+x];}
157
+ double score=potential/(reach[k]+8.0)*min(1.0,max(0.1,(danger[v]-(navigation?0.2:1.0)*reach[k])/18.0));anchors.push_back({score,{k,d}});
158
+ }
159
+ sort(anchors.begin(),anchors.end(),[](auto&a,auto&b){return a.first>b.first;});
160
+ vector<pair<int,int>> chosen;int used[12][12][4]={0};
161
+ for(auto item:anchors){int k=item.second.first,d=item.second.second;if(used[k/W/4][k%W/4][d]++>0)continue;chosen.push_back({k,d});if(chosen.size()>=52)break;}
162
+ int slot[V][4];for(int k=0;k<S;k++)for(int d=0;d<4;d++)slot[k][d]=-1;vector<array<Candidate,3>> diverse(chosen.size());for(int i=0;i<(int)chosen.size();i++){slot[chosen[i].first][chosen[i].second]=i;for(auto& c:diverse[i])c.score=-1;}
163
+ vector<Candidate> best;best.reserve(180);
164
+ auto keep=[&](Candidate c){int id=slot[c.anchor][c.d];if(id>=0){auto& bucket=diverse[id];if(c.score>bucket[2].score){bucket[2]=c;sort(bucket.begin(),bucket.end(),[](auto&a,auto&b){return a.score>b.score;});}}if(best.size()<60){best.push_back(c);push_heap(best.begin(),best.end(),[](auto&a,auto&b){return a.score>b.score;});}else if(c.score>best.front().score){pop_heap(best.begin(),best.end(),[](auto&a,auto&b){return a.score>b.score;});best.back()=c;push_heap(best.begin(),best.end(),[](auto&a,auto&b){return a.score>b.score;});}};
165
+ for(auto [k,d]:chosen){if(expired())break;int x=k%W,y=k/W;
166
+ for(int a=1;a<=min(26,nxtOwn[k][d]-1);a++){
167
+ int xx=x+dx[d]*a,yy=y+dy[d]*a;if(xx<0||yy<0||xx>=W||yy>=H)break;int corner=yy*W+xx;
168
+ for(int s=0;s<4;s++)if((s<2)!=(d<2))for(int b=1;b<=28;b++){
169
+ int x2=xx+dx[s]*b,y2=yy+dy[s]*b;if(x2<0||y2<0||x2>=W||y2>=H)break;int corner2=y2*W+x2;
170
+ // Do not march through home and accidentally start a second excursion.
171
+ if(nxtOwn[corner][s]<b)break;
172
+ int c=min(a,nxtOwn[corner2][d^1]);int end=corner2+(dx[d^1]+W*dy[d^1])*c;
173
+ int back=st.own[end]==me?0:min(b,nxtOwn[end][s^1]);
174
+ int len=reach[k]+a+b+c+back;if(nxtOwn[corner][s]==b)len=reach[k]+a+b,c=back=0;
175
+ if(len>T-st.turn)continue;
176
+ int risk=min(rayMin[k][d][a],rayMin[corner][s][b]);if(c)risk=min(risk,rayMin[corner2][d^1][c]);if(back)risk=min(risk,rayMin[end][s^1][back]);int margin=risk-len+optimism+(navigation?int(reach[k]*0.8):0);
177
+ if(margin < -2)continue;
178
+ double val=rect(x,y,x2,y2);double factor=margin>=2?1.0:margin>=0?0.86:0.48;
179
+ double score=val*factor/pow(len+4.0,efficiency);if(score>0)keep({score,k,d,s,a,b});
180
+ int full=nxtOwn[corner2][d^1];
181
+ if(full>a&&full<=32&&nxtOwn[corner][s]>b){
182
+ int finish=corner2+(dx[d^1]+W*dy[d^1])*full;
183
+ int ll=reach[k]+a+b+full,rr=min(min(rayMin[k][d][a],rayMin[corner][s][b]),rayMin[corner2][d^1][full]);int mm=rr-ll+optimism;
184
+ if(ll<=T-st.turn&&mm>=-2){int fx=finish%W,fy=finish/W;double vv=rect(min({x,x2,fx}),min({y,y2,fy}),max({x,x2,fx}),max({y,y2,fy}));double ff=mm>=2?1.0:mm>=0?0.86:0.48;keep({vv*ff/pow(ll+4.0,efficiency),k,d,s,a,b,full});}
185
+ }
186
+ }
187
+ }
188
+ }
189
+ vector<Candidate> bridge;
190
+ if(bridges)for(auto [k,d]:chosen){
191
+ if(expired())break;
192
+ int dis[V],q[V],head=0,tail=0;fill(dis,dis+S,INF);dis[k]=0;q[tail++]=k;
193
+ while(head<tail){int u=q[head++];for(int z=0;z<4;z++){int v=nb[u][z];if(v>=0&&st.own[v]==me&&dis[v]==INF)dis[v]=dis[u]+1,q[tail++]=v;}}
194
+ auto addBridge=[&](int a,int b,int side,int endpoint,int risk){
195
+ int len=reach[k]+a+b,margin=risk-len+optimism+(navigation?int(reach[k]*0.8):0);if(len>T-st.turn||margin < -2||dis[endpoint]>=INF)return;
196
+ int detour=dis[endpoint]-a-b;if(detour<2&&b!=0)return;
197
+ double val=max(1.0,detour*(a+b-1)*0.45)+(a+b-1);
198
+ double factor=margin>=2?1.0:margin>=0?0.86:0.48;
199
+ bridge.push_back({val*factor/pow(len+4.0,efficiency),k,d,side,a,b});
200
+ };
201
+ int straight=nxtOwn[k][d];if(straight<=30){int end=k+(dx[d]+W*dy[d])*straight;addBridge(straight,0,d<2?2:0,end,rayMin[k][d][straight]);}
202
+ int u=k;for(int a=1;a<=min(20,straight-1);a++){
203
+ u=nb[u][d];if(u<0)break;
204
+ for(int side=0;side<4;side++)if((side<2)!=(d<2)){
205
+ int b=nxtOwn[u][side];if(b>24)continue;int end=u+(dx[side]+W*dy[side])*b;
206
+ addBridge(a,b,side,end,min(rayMin[k][d][a],rayMin[u][side][b]));
207
+ }
208
+ }
209
+ }
210
+ sort(bridge.begin(),bridge.end(),[](auto&a,auto&b){return a.score>b.score;});if(bridge.size()>24)bridge.resize(24);
211
+ sort(best.begin(),best.end(),[](auto&a,auto&b){return a.score>b.score;});best.insert(best.end(),bridge.begin(),bridge.end());for(auto bucket:diverse)for(auto c:bucket)if(c.score>0)best.push_back(c);
212
+ vector<int> result;double highest=-1;vector<uint64_t> fingerprints;
213
+ for(auto c:best){if(evaluated>=8&&expired())break;uint64_t key=((((uint64_t(c.anchor)*4+c.d)*4+c.s)*64+c.a)*64+c.b)*64+(c.c+1);if(find(fingerprints.begin(),fingerprints.end(),key)!=fingerprints.end())continue;fingerprints.push_back(key);vector<int> path=approach(c.anchor);for(int i=0;i<c.a;i++)path.push_back(c.d);for(int i=0;i<c.b;i++)path.push_back(c.s);for(int i=0;i<(c.c<0?c.a:c.c);i++)path.push_back(c.d^1);if(c.c<0)for(int i=0;i<c.b;i++)path.push_back(c.s^1);
214
+ Eval e=evaluate(path);evaluated++;double score=utility(e);if(score>highest){highest=score;result=e.path;}
215
+ }
216
+ if(result.empty()){for(auto [anchor,d]:chosen)if(reach[anchor]>0){result=approach(anchor);break;}}
217
+ return result;
218
+ }
219
+ void opponentValues(){
220
+ double sum=0;for(int p=0;p<N;p++)if(p!=me){double scale=max(45.0,(T-st.turn)*0.18);double x=min(20.0,abs(st.p[me].area-st.p[p].area)/scale);double e=exp(-x);importance[p]=rankAware?e/(1+e)/(1+e):1.0;sum+=importance[p];}
221
+ for(int p=0;p<N;p++)if(p!=me)importance[p]/=sum;
222
+ for(int p=0;p<N;p++)if(p!=me){enemyRet[p]=0;threatValue[p]=0;if(!st.p[p].len)continue;
223
+ int q[V],dis[V],par[V],a=0,b=0;fill(dis,dis+S,INF);int start=pos(p);dis[start]=0;
224
+ for(int d=0;d<4;d++)if(d!=(st.p[p].dir^1)){int v=nb[start][d];if(v<0||st.tr[v]==p)continue;dis[v]=1;par[v]=start;q[b++]=v;}
225
+ int end=-1;
226
+ while(a<b){int u=q[a++];if(st.own[u]==p){end=u;break;}for(int d=0;d<4;d++){int v=nb[u][d];if(v<0||st.tr[v]==p||dis[v]!=INF)continue;dis[v]=dis[u]+1;par[v]=u;q[b++]=v;}}
227
+ if(end<0){enemyRet[p]=INF;continue;}enemyRet[p]=dis[end];
228
+ int mark[V]={0},seen[V]={0};for(int u=0;u<S;u++)mark[u]=st.tr[u]==p||st.own[u]==p;
229
+ for(int u=end;u!=start;u=par[u])mark[u]=1;
230
+ a=b=0;auto add=[&](int u){if(!mark[u]&&!seen[u])seen[u]=1,q[b++]=u;};
231
+ for(int x=0;x<W;x++)add(x),add((H-1)*W+x);for(int y=0;y<H;y++)add(y*W),add(y*W+W-1);
232
+ while(a<b){int u=q[a++];for(int d=0;d<4;d++){int v=nb[u][d];if(v>=0)add(v);}}
233
+ double gain=0,otherBenefit=0;int intrusion=0;
234
+ for(int u=0;u<S;u++){if(st.tr[u]==p&&st.own[u]==me)intrusion++;if(st.own[u]!=p&&(mark[u]||!seen[u])&&(protect[u]<0||protect[u]==p)){gain+=importance[p];if(st.own[u]==me)gain+=1.0;else if(st.own[u]>=0){gain-=importance[st.own[u]];otherBenefit+=importance[st.own[u]];}}}
235
+ double length=st.p[p].len+enemyRet[p];
236
+ threatValue[p]=N==4?max(0.0,gain+importance[p]*(length*0.25+3.0)+intrusion*0.5):max(0.0,max(gain,importance[p]*length*length/20.0-otherBenefit)+importance[p]*(length*0.6+6.0)+intrusion*0.5);
237
+ }
238
+ }
239
+ vector<int> hunt(){
240
+ int k=pos(me),dis[V],par[V],pdir[V],q[V],risk[V],a=0,b=0;fill(dis,dis+S,INF);fill(risk,risk+S,-INF);dis[k]=0;int initialRisk=INF;for(int u=0;u<S;u++)if(st.tr[u]==me)initialRisk=min(initialRisk,danger[u]);risk[k]=initialRisk;
241
+ for(int d=0;d<4;d++)if(moveSafe(k,d,st.p[me].dir)){int v=nb[k][d];dis[v]=1;par[v]=k;pdir[v]=d;risk[v]=min(initialRisk,st.own[v]==me?INF:danger[v]);q[b++]=v;}
242
+ while(a<b){int u=q[a++];if(dis[u]>=30)continue;for(int d=0;d<4;d++){int v=nb[u][d];if(v<0||st.tr[v]==me)continue;int r=min(risk[u],st.own[v]==me?INF:danger[v]);if(dis[v]==INF){dis[v]=dis[u]+1;par[v]=u;pdir[v]=d;risk[v]=r;q[b++]=v;}else if(dis[v]==dis[u]+1&&r>risk[v]){par[v]=u;pdir[v]=d;risk[v]=r;}}}
243
+ double best=0;int target=-1;huntScore=0;
244
+ for(int p=0;p<N;p++)if(p!=me&&st.p[p].len){
245
+ int ret=enemyRet[p];if(ret>T-st.turn)continue;
246
+ int nearest=INF,end=-1;for(int u=0;u<S;u++)if(st.tr[u]==p&&dis[u]<nearest&&(!cautiousHunt||dis[u]<=1||risk[u]>=dis[u]))nearest=dis[u],end=u;
247
+ if(end<0||nearest>ret+10||nearest>(nearest<=ret||(smartHunt&&threatValue[p]>90)?26:16)||nearest>T-st.turn)continue;
248
+ double value=(st.p[p].len+ret)*0.8+8;
249
+ if(st.p[p].area>=st.p[me].area-30)value*=1.3;
250
+ int intrusion=0;for(int u=0;u<S;u++)if(st.tr[u]==p&&st.own[u]==me)intrusion++;
251
+ value+=intrusion*2;
252
+ double prob=nearest<=ret?1.0:max(0.15,1.0-(nearest-ret)*0.12);
253
+ double score=smartHunt?threatValue[p]*prob/pow(nearest+4.0,efficiency):value/(nearest+3.0);if(nearest==1)score+=smartHunt?2.0:10.0;
254
+ if(score>best){best=score;target=end;}
255
+ }
256
+ huntScore=best;if(target<0)return {};vector<int> result;for(int v=target;v!=k;v=par[v])result.push_back(pdir[v]);reverse(result.begin(),result.end());return result;
257
+ }
258
+ int fallback(){
259
+ int k=pos(me),best=st.p[me].dir;double val=-1e9;
260
+ for(int d=0;d<4;d++)if(moveSafe(k,d,st.p[me].dir)){int v=nb[k][d];double z=0;z+=(st.own[v]==me?10:0);z-=home[v]*2;z+=min(20,danger[v])*0.15;if(collision(k,d))z-=100;int exits=0;for(int s=0;s<4;s++)if(moveSafe(v,s,d))exits++;z+=exits;z+=(d==st.p[me].dir?0.05:0);if(z>val)val=z,best=d;}return best;
261
+ }
262
+ int decide(const State& state){
263
+ began=chrono::steady_clock::now();evaluated=0;st=state;int k=pos(me);
264
+ if(baseEfficiency < -1.0)baseEfficiency=efficiency; if(baseEfficiency<0){int filled=0;for(int u=0;u<S;u++)filled+=st.own[u]>=0;efficiency=0.82+0.22*filled/S;}else efficiency=baseEfficiency;
265
+ if(st.turn==0)for(int p=0;p<N;p++)initdir[p]=st.p[p].dir;
266
+ if(baseOptimism<0)baseOptimism=optimism;if(st.p[me].deaths>lastDeaths)recentDeaths.push_back(st.turn);while(!recentDeaths.empty()&&recentDeaths.front()<st.turn-80)recentDeaths.pop_front();optimism=max(0,baseOptimism-max(0,int(recentDeaths.size())-1)*2);
267
+ if(expected!=k||lastDeaths!=st.p[me].deaths||(lastLen>0&&st.p[me].len==0))plan.clear();
268
+ if(st.p[me].len==0)entry=k;
269
+ lastDeaths=st.p[me].deaths;lastLen=st.p[me].len;enemyFields();homeField();opponentValues();
270
+ for(int u=0;u<S;u++){weight[u]=0;if(st.own[u]!=me&&(protect[u]<0||protect[u]==me)){weight[u]=st.own[u]<0?1.0:(rankAware?1.0+importance[st.own[u]]:(N==2?1.9:1.55));int edge=min(min(u%W,W-1-u%W),min(u/W,H-1-u/W));weight[u]*=1.0+edgeValue*(edge==0?1.0:edge==1?0.3:edge==2?0.1:0.0);}}
271
+ auto finish=[&](int d){expected=nb[k][d];return d;};
272
+ if(preplan && st.p[me].len==0 && plan.empty()){plan=expand();planAge=0;}
273
+ vector<int> attack=hunt();
274
+ if(!attack.empty()){
275
+ // A guaranteed cut can justify abandoning a modest unfinished excursion.
276
+ Eval current=evaluate(plan);double expansion=current.valid?utility(current):0;
277
+ int target=k;for(int d:attack)target=nb[target][d];int p=st.tr[target];
278
+ double av=smartHunt?huntScore:(p>=0?(st.p[p].len*2.0+st.p[p].len*st.p[p].len/14.0+12.0)/(attack.size()+3.0):0);
279
+ Eval immediate=evaluate(returnPath());bool bank=immediate.valid&&immediate.len==1&&immediate.margin>=1&&immediate.value>av*3.5;
280
+ if(!bank&&(attack.size()==1||(av*attackScale>expansion*1.15+0.5))){
281
+ plan.clear();return finish(attack.front());
282
+ }
283
+ }
284
+ if(st.p[me].len==0){
285
+ if(plan.empty()||planAge>=4){vector<int> fresh=expand();Eval old=evaluate(plan);Eval next=evaluate(fresh);if(utility(next)>utility(old)*1.05||!old.valid)plan=next.valid?next.path:fresh;planAge=0;}
286
+ else {Eval old=evaluate(plan,false);if(!old.valid||old.margin < -optimism){plan=expand();planAge=0;}}
287
+ }else{
288
+ Eval current=evaluate(plan);vector<int> bestPath=current.path;double best=utility(current);
289
+ vector<int> ret=returnPath();Eval fast=evaluate(ret); if(altReturns)for(auto path:contourReturns()){Eval e=evaluate(path);if(utility(e)>utility(fast))fast=e;}double score=utility(fast);
290
+ // Keep productive loops, but shorten immediately if an opponent can cut them.
291
+ if(score>best*1.07||!current.valid||(fast.valid&&fast.margin<=2&&fast.margin>current.margin+1)){bestPath=fast.path;best=score;}
292
+ if(current.valid&&current.margin<3){
293
+ vector<int> prefix;for(int i=0;i<min(10,(int)current.path.size()-1);i++){
294
+ prefix.push_back(current.path[i]);if(i%2)continue;Eval e=evaluate(returnPath(prefix));double u=utility(e);if(u>best*1.05){best=u;bestPath=e.path;}
295
+ }
296
+ }
297
+ if(adaptive && (st.turn%2==0 || !current.valid) && !expired()){
298
+ int start=pos(me),heading=st.p[me].dir,trailRisk=INF;for(int u=0;u<S;u++)if(st.tr[u]==me)trailRisk=min(trailRisk,danger[u]);
299
+ vector<int> directions;if(!bestPath.empty())directions.push_back(bestPath.front());directions.push_back(heading);for(int d=0;d<4;d++)directions.push_back(d);bool tried[4]={false,false,false,false};
300
+ for(int d:directions)if(d!=(heading^1)&&!tried[d]){tried[d]=true;
301
+ vector<int> prefix;int u=start,prefixRisk=trailRisk;
302
+ for(int a=1;a<=10;a++){
303
+ u=nb[u][d];if(u<0||st.tr[u]==me||st.own[u]==me)break;prefix.push_back(d);prefixRisk=min(prefixRisk,danger[u]);
304
+ if(a+home[u]>prefixRisk+optimism+2)continue;
305
+ if(a>4 && a%2)continue;
306
+ Eval direct=evaluate(returnPath(prefix));double val=utility(direct);if(val>best*1.08){best=val;bestPath=direct.path;}
307
+ for(int side=0;side<4;side++)if((side<2)!=(d<2)){
308
+ vector<int> pp=prefix;int v=u,sideRisk=prefixRisk;
309
+ for(int b=1;b<=8;b++){ if(expired())break;
310
+ v=nb[v][side];if(v<0||st.tr[v]==me)break;pp.push_back(side);if(st.own[v]!=me)sideRisk=min(sideRisk,danger[v]);
311
+ if(a+b+home[v]>sideRisk+optimism+2){if(st.own[v]==me)break;continue;}
312
+ if(b>3&&b%2)continue;
313
+ Eval e=evaluate(returnPath(pp));double z=utility(e);if(z>best*1.08){best=z;bestPath=e.path;}
314
+ if(st.own[v]==me)break;
315
+ }
316
+ }
317
+ if(expired())break;
318
+ }
319
+ if(expired())break;
320
+ }
321
+ }
322
+ if(safetyGate && !bestPath.empty()){Eval escape=evaluate(returnPath(vector<int>{bestPath.front()})); if(!escape.valid||escape.margin<1){ if(fast.valid)bestPath=fast.path; }}
323
+ plan=bestPath;
324
+ }
325
+ planAge++;
326
+ if(!plan.empty()&&moveSafe(k,plan.front(),st.p[me].dir)&&!collision(k,plan.front())){int d=plan.front();plan.erase(plan.begin());return finish(d);}
327
+ plan.clear();return finish(fallback());
328
+ }
329
+ };
330
+ }
331
+ #ifndef BOT_LIBRARY
332
+ int main() {
333
+ ios::sync_with_stdio(false);
334
+ cin.tie(nullptr);
335
+ string token;
336
+ int W, H, turns, players, me, moveMs, initMs;
337
+ if (!(cin >> token >> W >> H >> turns >> players >> me >> moveMs >> initMs)) return 0;
338
+ vector<int> spawns(players);
339
+ for (int i = 0; i < players; ++i) {
340
+ int p, x, y;
341
+ cin >> token >> p >> x >> y;
342
+ spawns[p] = y * W + x;
343
+ }
344
+ // The search tables live on the heap, including on systems with small stacks.
345
+ auto bot = make_unique<territory::Bot>(W, H, players, me, turns, spawns);
346
+ territory::State state;
347
+ while (cin >> token >> state.turn) {
348
+ for (int i = 0; i < players; ++i) {
349
+ int p;
350
+ char direction;
351
+ territory::Player player;
352
+ cin >> token >> p >> player.x >> player.y >> direction
353
+ >> player.len >> player.area >> player.deaths;
354
+ player.dir = int(string("UDLR").find(direction));
355
+ state.p[p] = player;
356
+ }
357
+ cin >> token;
358
+ for (int y = 0; y < H; ++y) {
359
+ cin >> token;
360
+ for (int x = 0; x < W; ++x) state.own[y * W + x] = token[x] == '.' ? -1 : token[x] - '0';
361
+ }
362
+ cin >> token;
363
+ for (int y = 0; y < H; ++y) {
364
+ cin >> token;
365
+ for (int x = 0; x < W; ++x) state.tr[y * W + x] = token[x] == '.' ? -1 : token[x] - '0';
366
+ }
367
+ cin >> token;
368
+ if (!cin) break;
369
+ cout << state.turn << ' ' << territory::dc[bot->decide(state)] << endl;
370
+ }
371
+ return 0;
372
+ }
373
+ #endif