dsh-eval-guard 0.2.3 → 0.3.1

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 (221) hide show
  1. package/README.md +91 -13
  2. package/assets/commit0/instance.json +30 -0
  3. package/assets/commit0/workspace.zip +0 -0
  4. package/assets/featurebench/hidden/test_regression.py +690 -0
  5. package/assets/featurebench/instance.json +16 -0
  6. package/assets/featurebench/workspace.zip +0 -0
  7. package/assets/swe-bench-pro/hidden/test.patch +36 -0
  8. package/assets/swe-bench-pro/instance.json +10 -0
  9. package/assets/swe-bench-pro/workspace.zip +0 -0
  10. package/eval/README.md +18 -0
  11. package/eval/arena/arena/README.md +21 -0
  12. package/eval/arena/arena/bt.py +104 -0
  13. package/eval/arena/arena/clock.py +15 -0
  14. package/eval/arena/arena/core.py +265 -0
  15. package/eval/arena/arena/run.cmd +24 -0
  16. package/eval/arena/arena/run.sh +11 -0
  17. package/eval/arena/arena/schedule.py +79 -0
  18. package/eval/arena/arena/tournament.py +183 -0
  19. package/eval/arena/bomberman/bots/README.md +16 -0
  20. package/eval/arena/bomberman/bots/deepseek-v4.1-flash.cpp +447 -0
  21. package/eval/arena/bomberman/bots/doubao-seed-2.1.cpp +542 -0
  22. package/eval/arena/bomberman/bots/glm-5.3.cpp +406 -0
  23. package/eval/arena/bomberman/bots/gpt-6-astra.cpp +768 -0
  24. package/eval/arena/bomberman/bots/gpt-6-sol.cpp +444 -0
  25. package/eval/arena/bomberman/bots/kimi-k3.cpp +432 -0
  26. package/eval/arena/bomberman/bots/mimo-v2.6-pro.cpp +529 -0
  27. package/eval/arena/bomberman/bots/opus-5.5.cpp +548 -0
  28. package/eval/arena/bomberman/bots/qwen-3.8-max.cpp +836 -0
  29. package/eval/arena/bomberman/tournament/README.md +11 -0
  30. package/eval/arena/bomberman/tournament/bt.py +56 -0
  31. package/eval/arena/bomberman/tournament/evaluate.py +199 -0
  32. package/eval/arena/bomberman/tournament/run.py +79 -0
  33. package/eval/arena/bomberman/tournament/schedule-2to10.json.gz +0 -0
  34. package/eval/arena/bomberman/workspace/MANIFEST.json +13 -0
  35. package/eval/arena/bomberman/workspace/README.md +29 -0
  36. package/eval/arena/bomberman/workspace/RULES.md +100 -0
  37. package/eval/arena/bomberman/workspace/baseline.cpp +240 -0
  38. package/eval/arena/bomberman/workspace/clock.py +25 -0
  39. package/eval/arena/bomberman/workspace/engine/arena.py +198 -0
  40. package/eval/arena/bomberman/workspace/engine/build.py +35 -0
  41. package/eval/arena/bomberman/workspace/engine/engine.py +256 -0
  42. package/eval/arena/bomberman/workspace/engine/verify_replay.py +24 -0
  43. package/eval/arena/bomberman/workspace/run.cmd +28 -0
  44. package/eval/arena/bomberman/workspace/run.sh +16 -0
  45. package/eval/arena/bomberman/workspace/viewer/index.html +42 -0
  46. package/eval/arena/ctf/bots/README.md +18 -0
  47. package/eval/arena/ctf/bots/deepseek-v4.1-flash.cpp +601 -0
  48. package/eval/arena/ctf/bots/doubao-seed-2.1-turbo.cpp +320 -0
  49. package/eval/arena/ctf/bots/fable-5.1.cpp +634 -0
  50. package/eval/arena/ctf/bots/glm-5.3.cpp +689 -0
  51. package/eval/arena/ctf/bots/gpt-6-astra.cpp +657 -0
  52. package/eval/arena/ctf/bots/gpt-6.1-sol.cpp +725 -0
  53. package/eval/arena/ctf/bots/kimi-k3.cpp +667 -0
  54. package/eval/arena/ctf/bots/mimo-v2.6-pro.cpp +533 -0
  55. package/eval/arena/ctf/bots/opus-5.5.cpp +645 -0
  56. package/eval/arena/ctf/bots/qwen-3.8-max.cpp +726 -0
  57. package/eval/arena/ctf/bots/sonnet-5.5.cpp +569 -0
  58. package/eval/arena/ctf/tournament/README.md +15 -0
  59. package/eval/arena/ctf/tournament/formal-2to8.json +31 -0
  60. package/eval/arena/ctf/tournament/formal-9to15.json +31 -0
  61. package/eval/arena/ctf/workspace/README.md +41 -0
  62. package/eval/arena/ctf/workspace/RULES.md +119 -0
  63. package/eval/arena/ctf/workspace/arena.py +186 -0
  64. package/eval/arena/ctf/workspace/baseline.cpp +257 -0
  65. package/eval/arena/ctf/workspace/clock.py +15 -0
  66. package/eval/arena/ctf/workspace/core.py +265 -0
  67. package/eval/arena/ctf/workspace/engine.py +389 -0
  68. package/eval/arena/ctf/workspace/run.cmd +24 -0
  69. package/eval/arena/ctf/workspace/run.sh +11 -0
  70. package/eval/arena/ctf/workspace/viewer.html +71 -0
  71. package/eval/arena/land/bots/README.md +17 -0
  72. package/eval/arena/land/bots/deepseek-4.1f@workbuddy#1/bot.cpp +608 -0
  73. package/eval/arena/land/bots/glm-5.3@workbuddy#1/bot.cpp +521 -0
  74. package/eval/arena/land/bots/gpt-6-astra@codex#1/bot.cpp +373 -0
  75. package/eval/arena/land/bots/gpt-6-sol@codex#1/bot.cpp +341 -0
  76. package/eval/arena/land/bots/kimi-k3@workbuddy#1/bot.cpp +492 -0
  77. package/eval/arena/land/bots/mimo-2.6-pro@zcode#1/bot.cpp +652 -0
  78. package/eval/arena/land/bots/mystery-model@zcode#1/bot.cpp +466 -0
  79. package/eval/arena/land/bots/opus-5.5@claude-code#1/bot.cpp +630 -0
  80. package/eval/arena/land/bots/sonnet-5@claude-code#1/bot.cpp +619 -0
  81. package/eval/arena/land/tournament/make_replay_page.py +17 -0
  82. package/eval/arena/land/tournament/rate.py +290 -0
  83. package/eval/arena/land/tournament/round_robin.py +172 -0
  84. package/eval/arena/land/tournament/sparring.cpp +356 -0
  85. package/eval/arena/land/workspace/RULES.md +114 -0
  86. package/eval/arena/land/workspace/TASK.md +46 -0
  87. package/eval/arena/land/workspace/anchors/.build/greedy_f2e6d2dea5ca +0 -0
  88. package/eval/arena/land/workspace/anchors/greedy.cpp +194 -0
  89. package/eval/arena/land/workspace/anchors/random.cpp +80 -0
  90. package/eval/arena/land/workspace/clock.py +64 -0
  91. package/eval/arena/land/workspace/engine/build.py +33 -0
  92. package/eval/arena/land/workspace/engine/game.py +273 -0
  93. package/eval/arena/land/workspace/engine/referee.py +308 -0
  94. package/eval/arena/land/workspace/starter/.build/bot_be32b45b4699 +0 -0
  95. package/eval/arena/land/workspace/starter/bot.cpp +82 -0
  96. package/eval/arena/land/workspace/viewer/viewer.html +210 -0
  97. package/eval/arena/tank/bots/README.md +24 -0
  98. package/eval/arena/tank/bots/half1/deepseek-v4.1-flash.cpp +367 -0
  99. package/eval/arena/tank/bots/half1/doubao-seed-evolving.cpp +402 -0
  100. package/eval/arena/tank/bots/half1/gemini-4-argon.cpp +1132 -0
  101. package/eval/arena/tank/bots/half1/glm-5.3.cpp +551 -0
  102. package/eval/arena/tank/bots/half1/gpt-6-astra.cpp +233 -0
  103. package/eval/arena/tank/bots/half1/gpt-6.1-sol-ultrafast.cpp +350 -0
  104. package/eval/arena/tank/bots/half1/gpt-6.1-sol.cpp +78 -0
  105. package/eval/arena/tank/bots/half1/grok-4.7.cpp +1099 -0
  106. package/eval/arena/tank/bots/half1/haiku-5.5.cpp +210 -0
  107. package/eval/arena/tank/bots/half1/kimi-k3.cpp +353 -0
  108. package/eval/arena/tank/bots/half1/mimo-v2.6-pro.cpp +336 -0
  109. package/eval/arena/tank/bots/half1/muse-wonder-full.cpp +560 -0
  110. package/eval/arena/tank/bots/half1/opus-5.5.cpp +435 -0
  111. package/eval/arena/tank/bots/half1/qwen-3.8-max.cpp +537 -0
  112. package/eval/arena/tank/bots/half2/deepseek-v4.1-flash.cpp +425 -0
  113. package/eval/arena/tank/bots/half2/doubao-seed-evolving.cpp +308 -0
  114. package/eval/arena/tank/bots/half2/gemini-4-argon.cpp +1390 -0
  115. package/eval/arena/tank/bots/half2/glm-5.3.cpp +651 -0
  116. package/eval/arena/tank/bots/half2/gpt-6-astra.cpp +241 -0
  117. package/eval/arena/tank/bots/half2/gpt-6.1-sol-ultrafast.cpp +356 -0
  118. package/eval/arena/tank/bots/half2/gpt-6.1-sol.cpp +87 -0
  119. package/eval/arena/tank/bots/half2/grok-4.7.cpp +1205 -0
  120. package/eval/arena/tank/bots/half2/haiku-5.5.cpp +210 -0
  121. package/eval/arena/tank/bots/half2/kimi-k3.cpp +487 -0
  122. package/eval/arena/tank/bots/half2/mimo-v2.6-pro.cpp +336 -0
  123. package/eval/arena/tank/bots/half2/muse-wonder-full.cpp +560 -0
  124. package/eval/arena/tank/bots/half2/opus-5.5.cpp +476 -0
  125. package/eval/arena/tank/bots/half2/qwen-3.8-max.cpp +392 -0
  126. package/eval/arena/tank/tournament/README.md +24 -0
  127. package/eval/arena/tank/tournament/bt.py +218 -0
  128. package/eval/arena/tank/tournament/final.json +202 -0
  129. package/eval/arena/tank/tournament/halftime.json +146 -0
  130. package/eval/arena/tank/tournament/progress.json +911 -0
  131. package/eval/arena/tank/tournament/schedule.py +100 -0
  132. package/eval/arena/tank/tournament/sparring.cpp +928 -0
  133. package/eval/arena/tank/tournament/tournament.py +1426 -0
  134. package/eval/arena/tank/workspace/README.md +169 -0
  135. package/eval/arena/tank/workspace/RULES.md +443 -0
  136. package/eval/arena/tank/workspace/arena.py +862 -0
  137. package/eval/arena/tank/workspace/baseline.cpp +259 -0
  138. package/eval/arena/tank/workspace/clock.py +103 -0
  139. package/eval/arena/tank/workspace/core.py +712 -0
  140. package/eval/arena/tank/workspace/engine.py +573 -0
  141. package/eval/arena/tank/workspace/history/.lock +0 -0
  142. package/eval/arena/tank/workspace/history/20261017-193610-08715287f91f-bot.cpp +109 -0
  143. package/eval/arena/tank/workspace/history/20261017-193619-f00b2d5635fa-gpt-6-astra.cpp +241 -0
  144. package/eval/arena/tank/workspace/history/20261017-193643-63319e0a2b1a-gpt-6_1-sol-ultrafast.cpp +356 -0
  145. package/eval/arena/tank/workspace/history/20261017-193647-41c1341d0a8a-gemini-4-argon.cpp +1390 -0
  146. package/eval/arena/tank/workspace/history/20261017-193652-e34c0f45539a-gpt-6_1-sol.cpp +87 -0
  147. package/eval/arena/tank/workspace/history/20261017-193654-c026348ce96e-opus-5_5.cpp +476 -0
  148. package/eval/arena/tank/workspace/history/20261017-193655-4a21366e94d1-muse-wonder-full.cpp +560 -0
  149. package/eval/arena/tank/workspace/history/20261017-193657-dbc4e9969c52-mimo-v2_6-pro.cpp +336 -0
  150. package/eval/arena/tank/workspace/history/20261017-193703-723cd036eb31-grok-4_7.cpp +1205 -0
  151. package/eval/arena/tank/workspace/history/20261017-193707-1ebbb227be68-deepseek-v4_1-flash.cpp +425 -0
  152. package/eval/arena/tank/workspace/history/20261017-193709-aeb0e7202ad5-doubao-seed-evolving.cpp +308 -0
  153. package/eval/arena/tank/workspace/history/20261017-193710-b21ebeb9bc76-kimi-k3.cpp +487 -0
  154. package/eval/arena/tank/workspace/history/20261017-193712-54cd86531905-haiku-5_5.cpp +210 -0
  155. package/eval/arena/tank/workspace/history/20261017-193714-efdb8e35c0bf-qwen-3_8-max.cpp +392 -0
  156. package/eval/arena/tank/workspace/history/20261017-193715-681423c23fdb-glm-5_3.cpp +651 -0
  157. package/eval/arena/tank/workspace/history/20261017-193717-1a8b3c75181d-sparring.cpp +928 -0
  158. package/eval/arena/tank/workspace/history/20261017-193720-1e0803a541e8-baseline.cpp +259 -0
  159. package/eval/arena/tank/workspace/history/log.jsonl +103 -0
  160. package/eval/arena/tank/workspace/judge/cycles.hpp +53 -0
  161. package/eval/arena/tank/workspace/judge/fast.cpp +337 -0
  162. package/eval/arena/tank/workspace/judge/referee.cpp +125 -0
  163. package/eval/arena/tank/workspace/judge/speed.cpp +99 -0
  164. package/eval/arena/tank/workspace/run.cmd +31 -0
  165. package/eval/arena/tank/workspace/run.sh +23 -0
  166. package/eval/arena/tank/workspace/tank.hpp +1762 -0
  167. package/eval/arena/tank/workspace/tank_main.cpp +215 -0
  168. package/eval/arena/tank/workspace/viewer.html +1150 -0
  169. package/eval/arena/warehouse/workspace/SPEC.md +130 -0
  170. package/eval/arena/warehouse/workspace/TASK.md +71 -0
  171. package/eval/arena/warehouse/workspace/baseline/common.h +88 -0
  172. package/eval/arena/warehouse/workspace/baseline/main.cpp +27 -0
  173. package/eval/arena/warehouse/workspace/baseline/old_stuff.cpp +87 -0
  174. package/eval/arena/warehouse/workspace/baseline/sim.cpp +427 -0
  175. package/eval/arena/warehouse/workspace/baseline/util.cpp +220 -0
  176. package/eval/arena/warehouse/workspace/clock.py +42 -0
  177. package/eval/arena/warehouse/workspace/src/common.h +88 -0
  178. package/eval/arena/warehouse/workspace/src/main.cpp +27 -0
  179. package/eval/arena/warehouse/workspace/src/old_stuff.cpp +87 -0
  180. package/eval/arena/warehouse/workspace/src/sim.cpp +427 -0
  181. package/eval/arena/warehouse/workspace/src/util.cpp +220 -0
  182. package/eval/arena/warehouse/workspace/tools/bench.py +119 -0
  183. package/eval/arena/warehouse/workspace/tools/check_input.py +161 -0
  184. package/eval/arena/warehouse/workspace/tools/gen.py +132 -0
  185. package/eval/arena/warehouse/workspace/tools/measure.py +107 -0
  186. package/eval/arena/warehouse/workspace/workloads/public/pub_crowded.in +1420 -0
  187. package/eval/arena/warehouse/workspace/workloads/public/pub_crowded.out +9162 -0
  188. package/eval/arena/warehouse/workspace/workloads/public/pub_dynamic.in +1465 -0
  189. package/eval/arena/warehouse/workspace/workloads/public/pub_dynamic.out +3439 -0
  190. package/eval/arena/warehouse/workspace/workloads/public/pub_flood.in +2757 -0
  191. package/eval/arena/warehouse/workspace/workloads/public/pub_flood.out +3126 -0
  192. package/eval/arena/warehouse/workspace/workloads/public/pub_small.in +731 -0
  193. package/eval/arena/warehouse/workspace/workloads/public/pub_small.out +2578 -0
  194. package/eval/arena/warehouse/workspace/workloads/public/pub_wide.in +528 -0
  195. package/eval/arena/warehouse/workspace/workloads/public/pub_wide.out +2026 -0
  196. package/eval/bomberman.py +20 -0
  197. package/eval/commit0.py +21 -0
  198. package/eval/common.py +61 -0
  199. package/eval/ctf.py +20 -0
  200. package/eval/featurebench.py +25 -0
  201. package/eval/land.py +20 -0
  202. package/eval/legacy/bomberman-prices.json +4 -0
  203. package/eval/legacy/bomberman.py +161 -0
  204. package/eval/legacy/commit0.py +91 -0
  205. package/eval/legacy/ctf-prices.json +4 -0
  206. package/eval/legacy/ctf.py +178 -0
  207. package/eval/legacy/featurebench.py +103 -0
  208. package/eval/legacy/land-prices.json +4 -0
  209. package/eval/legacy/land.py +177 -0
  210. package/eval/legacy/swe_bench_pro.py +116 -0
  211. package/eval/legacy/tank-prices.json +3 -0
  212. package/eval/legacy/tank.py +408 -0
  213. package/eval/legacy/warehouse-prices.json +4 -0
  214. package/eval/legacy/warehouse.py +365 -0
  215. package/eval/swe-bench-pro.py +25 -0
  216. package/eval/tank.py +20 -0
  217. package/eval/warehouse.py +20 -0
  218. package/lib/client/index.js +376 -63
  219. package/lib/client/index.js.map +1 -1
  220. package/lib/index.js +684 -27
  221. package/package.json +2 -1
@@ -0,0 +1,529 @@
1
+ // Bomberman bot for 2-10 players. Survival-first with opportunistic kills.
2
+ // Time-expanded reachability guarantees we never die to bombs/flames/shrink;
3
+ // escape-denial scoring converts safe bombing into kills.
4
+ #include <algorithm>
5
+ #include <array>
6
+ #include <cmath>
7
+ #include <deque>
8
+ #include <iostream>
9
+ #include <queue>
10
+ #include <string>
11
+ #include <vector>
12
+ using namespace std;
13
+
14
+ static const int DX[5] = {0, 0, -1, 1, 0};
15
+ static const int DY[5] = {-1, 1, 0, 0, 0};
16
+ static const string DSTR = "UDLRS";
17
+
18
+ int N, P, ME, LIMIT, FUSE, RANGE, CAP, FIRE, SHRINK, EVERY;
19
+ int T;
20
+ vector<string> board;
21
+ struct Player { int x, y, alive; };
22
+ struct Bomb { int owner, x, y, at; };
23
+ struct Flame { int x, y, end; };
24
+ vector<Player> players;
25
+ vector<Bomb> bombs;
26
+ vector<Flame> flames;
27
+
28
+ inline int cell(int x, int y) { return y * N + x; }
29
+ inline int cx(int c) { return c % N; }
30
+ inline int cy(int c) { return c / N; }
31
+ inline bool inb(int x, int y) { return x >= 0 && y >= 0 && x < N && y < N; }
32
+ inline int edgeDist(int x, int y) { return min({x, y, N - 1 - x, N - 1 - y}); }
33
+ inline int shrinkLayer(int t) {
34
+ return t < SHRINK ? 0 : 1 + (t - SHRINK) / EVERY;
35
+ }
36
+
37
+ // ---------- input ----------
38
+ bool readTurn() {
39
+ string word;
40
+ if (!(cin >> word >> T)) return false;
41
+ cin >> word;
42
+ for (auto &row : board) cin >> row;
43
+ for (int i = 0, id; i < P; i++) {
44
+ cin >> word >> id;
45
+ cin >> players[id].x >> players[id].y >> players[id].alive;
46
+ }
47
+ int k;
48
+ cin >> word >> k;
49
+ bombs.resize(k);
50
+ for (auto &b : bombs) cin >> word >> b.owner >> b.x >> b.y >> b.at;
51
+ cin >> word >> k;
52
+ flames.resize(k);
53
+ for (auto &f : flames) cin >> word >> f.x >> f.y >> f.end;
54
+ while (cin >> word) {
55
+ if (word == "END") return true;
56
+ string line;
57
+ getline(cin, line);
58
+ }
59
+ return false;
60
+ }
61
+
62
+ // ---------- fire / safety prediction ----------
63
+ // safe[k][c]: cell c is walkable-safe at action turn T+k
64
+ // open[k][c]: cell c is terrain-open (no wall/crate) at T+k
65
+ // occ[k][c]: a bomb occupies c at T+k
66
+ struct Pred {
67
+ vector<vector<unsigned char>> safe, open, occ;
68
+ };
69
+
70
+ Pred predict(vector<Bomb> bs, int horizon) {
71
+ Pred out;
72
+ int H = horizon, NN = N * N;
73
+ out.safe.assign(H, vector<unsigned char>(NN, 0));
74
+ out.open.assign(H, vector<unsigned char>(NN, 0));
75
+ out.occ.assign(H, vector<unsigned char>(NN, 0));
76
+ auto grid = board;
77
+ vector<int> expires(NN, -1);
78
+ for (auto &f : flames) expires[cell(f.x, f.y)] = f.end;
79
+
80
+ for (int k = 0; k < H; k++) {
81
+ int now = T + k;
82
+ int layer = shrinkLayer(now);
83
+ if (layer > 0) {
84
+ for (int y = 0; y < N; y++)
85
+ for (int x = 0; x < N; x++)
86
+ if (edgeDist(x, y) <= layer) {
87
+ grid[y][x] = '#';
88
+ expires[cell(x, y)] = -1;
89
+ }
90
+ }
91
+ bs.erase(remove_if(bs.begin(), bs.end(),
92
+ [&](const Bomb &b) { return grid[b.y][b.x] == '#'; }),
93
+ bs.end());
94
+ vector<int> at(NN, -1);
95
+ for (int i = 0; i < (int)bs.size(); i++) {
96
+ at[cell(bs[i].x, bs[i].y)] = i;
97
+ out.occ[k][cell(bs[i].x, bs[i].y)] = 1;
98
+ }
99
+ for (int y = 0; y < N; y++)
100
+ for (int x = 0; x < N; x++)
101
+ out.open[k][cell(x, y)] = grid[y][x] == '.';
102
+
103
+ queue<int> q;
104
+ vector<bool> gone(bs.size(), false);
105
+ vector<unsigned char> hit(NN, 0);
106
+ for (int i = 0; i < (int)bs.size(); i++)
107
+ if (bs[i].at <= now || expires[cell(bs[i].x, bs[i].y)] >= now) q.push(i);
108
+ while (!q.empty()) {
109
+ int i = q.front();
110
+ q.pop();
111
+ if (gone[i]) continue;
112
+ gone[i] = true;
113
+ auto b = bs[i];
114
+ hit[cell(b.x, b.y)] = 1;
115
+ for (int d = 0; d < 4; d++)
116
+ for (int r = 1; r <= RANGE; r++) {
117
+ int x = b.x + DX[d] * r, y = b.y + DY[d] * r;
118
+ if (!inb(x, y) || grid[y][x] == '#') break;
119
+ int c = cell(x, y);
120
+ hit[c] = 1;
121
+ if (grid[y][x] == '+') break;
122
+ if (at[c] >= 0) {
123
+ q.push(at[c]);
124
+ break;
125
+ }
126
+ }
127
+ }
128
+ vector<Bomb> left;
129
+ for (int i = 0; i < (int)bs.size(); i++)
130
+ if (!gone[i]) left.push_back(bs[i]);
131
+ bs = move(left);
132
+ for (int y = 0; y < N; y++)
133
+ for (int x = 0; x < N; x++) {
134
+ int c = cell(x, y);
135
+ if (hit[c]) {
136
+ expires[c] = max(expires[c], now + FIRE - 1);
137
+ if (grid[y][x] == '+') grid[y][x] = '.';
138
+ }
139
+ out.safe[k][c] = grid[y][x] == '.' && expires[c] < now;
140
+ }
141
+ }
142
+ return out;
143
+ }
144
+
145
+ // ---------- time-expanded reachability ----------
146
+ // Tracks which first-move direction (bitmask) can reach each cell at each step.
147
+ struct Reach {
148
+ array<int, 5> life{}, count{};
149
+ array<double, 5> util{};
150
+ int unique = 0;
151
+ };
152
+
153
+ vector<double> potential;
154
+
155
+ Reach reach(const Pred &pr, int who, int forced = -1) {
156
+ int NN = N * N;
157
+ vector<unsigned char> cur(NN, 0);
158
+ cur[cell(players[who].x, players[who].y)] = 31;
159
+ Reach res;
160
+ res.util.fill(-1e6);
161
+ int H = (int)pr.safe.size();
162
+ for (int k = 0; k < H; k++) {
163
+ vector<unsigned char> nxt(NN, 0);
164
+ int now = T + k;
165
+ int layer = shrinkLayer(now);
166
+ for (int c = 0; c < NN; c++) {
167
+ if (!cur[c]) continue;
168
+ int x = cx(c), y = cy(c);
169
+ if (edgeDist(x, y) <= layer) continue;
170
+ for (int d = 0; d < 5; d++) {
171
+ int nx = x + DX[d], ny = y + DY[d], nc = c;
172
+ if (inb(nx, ny)) {
173
+ int z = cell(nx, ny);
174
+ if (pr.open[k][z] && (!pr.occ[k][z] || z == c)) nc = z;
175
+ }
176
+ if (k == 0 && forced >= 0) nc = forced;
177
+ if (pr.safe[k][nc]) nxt[nc] |= (k == 0) ? (1 << d) : cur[c];
178
+ }
179
+ }
180
+ cur = move(nxt);
181
+ for (int c = 0; c < NN; c++)
182
+ if (cur[c])
183
+ for (int d = 0; d < 5; d++)
184
+ if (cur[c] & (1 << d)) res.life[d] = k + 1;
185
+ }
186
+ for (int c = 0; c < NN; c++)
187
+ if (cur[c]) {
188
+ res.unique++;
189
+ for (int d = 0; d < 5; d++)
190
+ if (cur[c] & (1 << d)) {
191
+ res.count[d]++;
192
+ res.util[d] = max(res.util[d], potential.empty() ? 0.0 : potential[c]);
193
+ }
194
+ }
195
+ return res;
196
+ }
197
+
198
+ // ---------- strategic potential field ----------
199
+ int blastValue(int x, int y) {
200
+ int score = 0;
201
+ for (int d = 0; d < 4; d++)
202
+ for (int r = 1; r <= RANGE; r++) {
203
+ int nx = x + DX[d] * r, ny = y + DY[d] * r;
204
+ if (!inb(nx, ny) || board[ny][nx] == '#') break;
205
+ if (board[ny][nx] == '+') {
206
+ score += 3;
207
+ break;
208
+ }
209
+ for (int i = 0; i < P; i++)
210
+ if (i != ME && players[i].alive && players[i].x == nx && players[i].y == ny)
211
+ score += 5;
212
+ }
213
+ return score;
214
+ }
215
+
216
+ void makePotential() {
217
+ int NN = N * N;
218
+ potential.assign(NN, -1e6);
219
+ priority_queue<pair<double, int>> pq;
220
+ for (int y = 0; y < N; y++)
221
+ for (int x = 0; x < N; x++) {
222
+ if (board[y][x] != '.') continue;
223
+ int edge = edgeDist(x, y);
224
+ double val = blastValue(x, y) * 0.85;
225
+ int until = SHRINK + max(0, edge - 1) * EVERY - T;
226
+ if (until < 14)
227
+ val -= 40;
228
+ else
229
+ val += min(4.5, edge * 0.45);
230
+ potential[cell(x, y)] = val;
231
+ pq.push({val, cell(x, y)});
232
+ }
233
+ while (!pq.empty()) {
234
+ auto [v, c] = pq.top();
235
+ pq.pop();
236
+ if (v < potential[c] - 1e-9) continue;
237
+ int x = cx(c), y = cy(c);
238
+ for (int d = 0; d < 4; d++) {
239
+ int nx = x + DX[d], ny = y + DY[d];
240
+ if (!inb(nx, ny) || board[ny][nx] != '.') continue;
241
+ int nc = cell(nx, ny);
242
+ if (v - 0.75 > potential[nc]) {
243
+ potential[nc] = v - 0.75;
244
+ pq.push({v - 0.75, nc});
245
+ }
246
+ }
247
+ }
248
+ }
249
+
250
+ // ---------- goal-based movement (anti-oscillation) ----------
251
+ vector<int> recent;
252
+ int goal = -1, goalTurn = -100;
253
+ vector<int> goalDist;
254
+
255
+ vector<int> bfsDist(int start) {
256
+ vector<int> dist(N * N, 10000);
257
+ queue<int> q;
258
+ dist[start] = 0;
259
+ q.push(start);
260
+ while (!q.empty()) {
261
+ int c = q.front();
262
+ q.pop();
263
+ for (int d = 0; d < 4; d++) {
264
+ int x = cx(c) + DX[d], y = cy(c) + DY[d];
265
+ if (!inb(x, y) || board[y][x] != '.') continue;
266
+ int z = cell(x, y);
267
+ if (dist[z] > dist[c] + 1) {
268
+ dist[z] = dist[c] + 1;
269
+ q.push(z);
270
+ }
271
+ }
272
+ }
273
+ return dist;
274
+ }
275
+
276
+ double visits(int c) {
277
+ double s = 0;
278
+ for (int k = 0; k < (int)recent.size(); k++)
279
+ if (recent[k] == c) s += 1.0 / (1 + 0.15 * (recent.size() - 1 - k));
280
+ return s;
281
+ }
282
+
283
+ void updateGoal() {
284
+ int current = cell(players[ME].x, players[ME].y);
285
+ recent.push_back(current);
286
+ if (recent.size() > 32) recent.erase(recent.begin());
287
+ auto dist = bfsDist(current);
288
+ int layer = shrinkLayer(T);
289
+ if (goal < 0 || board[goal / N][goal % N] != '.' || dist[goal] >= 10000 ||
290
+ T - goalTurn >= 12 || edgeDist(goal % N, goal / N) <= layer + 1 || current == goal) {
291
+ goal = -1;
292
+ double best = -1e20;
293
+ for (int c = 0; c < N * N; c++) {
294
+ if (dist[c] >= 10000) continue;
295
+ int x = c % N, y = c / N;
296
+ int edge = edgeDist(x, y);
297
+ double v = 1.5 * blastValue(x, y) - 0.7 * dist[c] - 1.0 * visits(c);
298
+ int until = SHRINK + max(0, edge - 1) * EVERY - T;
299
+ if (until <= dist[c] + 12)
300
+ v -= 45;
301
+ else
302
+ v += min(3.5, edge * 0.35);
303
+ if (v > best) {
304
+ best = v;
305
+ goal = c;
306
+ }
307
+ }
308
+ goalTurn = T;
309
+ }
310
+ goalDist = bfsDist(goal < 0 ? current : goal);
311
+ }
312
+
313
+ // ---------- collision-aware destination prediction ----------
314
+ // Simultaneous moves: same-target => all stay; propagate until stable.
315
+ // Swaps allowed by rules; we conservatively assume they may fail.
316
+ vector<int> prevCells;
317
+
318
+ int predictDest(const Pred &pr, int myDir) {
319
+ vector<int> ids, origin, target;
320
+ for (int i = 0; i < P; i++) {
321
+ if (!players[i].alive) continue;
322
+ int old = cell(players[i].x, players[i].y);
323
+ if (!pr.open[0][old]) continue;
324
+ int d = 4;
325
+ if (i == ME)
326
+ d = myDir;
327
+ else if (!prevCells.empty())
328
+ for (int j = 0; j < 4; j++)
329
+ if (old == prevCells[i] + DY[j] * N + DX[j]) d = j;
330
+ int x = players[i].x + DX[d], y = players[i].y + DY[d], dest = old;
331
+ if (inb(x, y)) {
332
+ int z = cell(x, y);
333
+ if (pr.open[0][z] && (!pr.occ[0][z] || z == old)) dest = z;
334
+ }
335
+ ids.push_back(i);
336
+ origin.push_back(old);
337
+ target.push_back(dest);
338
+ }
339
+ auto result = target;
340
+ for (int i = 0; i < (int)ids.size(); i++)
341
+ if (count(target.begin(), target.end(), target[i]) > 1) result[i] = origin[i];
342
+ // swaps: if two players target each other's origin, both stay (conservative)
343
+ for (int i = 0; i < (int)ids.size(); i++)
344
+ for (int j = 0; j < i; j++)
345
+ if (result[i] == origin[j] && result[j] == origin[i]) {
346
+ result[i] = origin[i];
347
+ result[j] = origin[j];
348
+ }
349
+ bool changed = true;
350
+ while (changed) {
351
+ changed = false;
352
+ auto last = result;
353
+ for (int i = 0; i < (int)ids.size(); i++) {
354
+ if (result[i] == origin[i]) continue;
355
+ for (int j = 0; j < (int)ids.size(); j++)
356
+ if (last[j] == origin[j] && result[i] == origin[j]) {
357
+ result[i] = origin[i];
358
+ changed = true;
359
+ }
360
+ }
361
+ }
362
+ for (int i = 0; i < (int)ids.size(); i++)
363
+ if (ids[i] == ME) return result[i];
364
+ return cell(players[ME].x, players[ME].y);
365
+ }
366
+
367
+ // ---------- threat map: cells endangered if any nearby opponent bombs ----------
368
+ vector<double> threatMap(const vector<Bomb> &bs) {
369
+ vector<double> threat(N * N, 0.0);
370
+ for (int i = 0; i < P; i++) {
371
+ if (i == ME || !players[i].alive) continue;
372
+ int cnt = 0;
373
+ bool onBomb = false;
374
+ for (auto &b : bs) {
375
+ if (b.owner == i) cnt++;
376
+ if (b.x == players[i].x && b.y == players[i].y) onBomb = true;
377
+ }
378
+ if (cnt >= CAP || onBomb) continue;
379
+ int ex = players[i].x, ey = players[i].y;
380
+ int dist = abs(ex - players[ME].x) + abs(ey - players[ME].y);
381
+ if (dist > 10) continue;
382
+ double w = 1.0 + max(0.0, (10 - dist) * 0.15);
383
+ threat[cell(ex, ey)] += 2.0 * w;
384
+ for (int d = 0; d < 4; d++)
385
+ for (int r = 1; r <= RANGE; r++) {
386
+ int nx = ex + DX[d] * r, ny = ey + DY[d] * r;
387
+ if (!inb(nx, ny) || board[ny][nx] == '#') break;
388
+ threat[cell(nx, ny)] += 2.0 * w / r;
389
+ if (board[ny][nx] == '+') break;
390
+ }
391
+ }
392
+ return threat;
393
+ }
394
+
395
+ // ---------- main decision ----------
396
+ pair<int, int> decide() {
397
+ int horizon = min(12, LIMIT - T);
398
+ auto me = players[ME];
399
+ makePotential();
400
+ updateGoal();
401
+
402
+ auto basePred = predict(bombs, horizon);
403
+ auto baseReach = reach(basePred, ME);
404
+ auto threat = threatMap(bombs);
405
+
406
+ int myBombs = 0;
407
+ bool onBomb = false;
408
+ for (auto &b : bombs) {
409
+ if (b.owner == ME) myBombs++;
410
+ if (b.x == me.x && b.y == me.y) onBomb = true;
411
+ }
412
+ bool shared = false;
413
+ for (int i = 0; i < P; i++)
414
+ if (i != ME && players[i].alive && players[i].x == me.x && players[i].y == me.y)
415
+ shared = true;
416
+
417
+ pair<int, int> answer = {4, 0};
418
+ double bestScore = -1e30;
419
+
420
+ for (int place = 0; place <= 1; place++) {
421
+ if (place && (myBombs >= CAP || onBomb || shared)) continue;
422
+ auto bs = bombs;
423
+ if (place) bs.push_back({ME, me.x, me.y, T + FUSE});
424
+ auto pred = place ? predict(bs, horizon) : basePred;
425
+ auto own = place ? reach(pred, ME) : baseReach;
426
+
427
+ double denial = 0;
428
+ if (place) {
429
+ denial = blastValue(me.x, me.y) * 0.65 - 2.2;
430
+ for (int i = 0; i < P; i++) {
431
+ if (i == ME || !players[i].alive) continue;
432
+ auto ob = reach(basePred, i);
433
+ if (ob.unique == 0) continue;
434
+ auto on = reach(pred, i);
435
+ denial += on.unique == 0 ? 90.0
436
+ : 5.5 * max(0.0, 1.0 - double(on.unique) / ob.unique);
437
+ }
438
+ }
439
+
440
+ // nearest opponent threat (may place bomb next turn)
441
+ int aliveOpp = 0;
442
+ for (int i = 0; i < P; i++)
443
+ if (i != ME && players[i].alive) aliveOpp++;
444
+ int threatId = -1, tdist = 1000;
445
+ for (int i = 0; i < P; i++) {
446
+ if (i == ME || !players[i].alive) continue;
447
+ int dist = abs(players[i].x - me.x) + abs(players[i].y - me.y);
448
+ int cnt = 0;
449
+ bool blocked = false;
450
+ for (auto &b : bs) {
451
+ if (b.owner == i) cnt++;
452
+ if (b.x == players[i].x && b.y == players[i].y) blocked = true;
453
+ }
454
+ if (dist <= 7 && dist < tdist && cnt < CAP && !blocked) {
455
+ threatId = i;
456
+ tdist = dist;
457
+ }
458
+ }
459
+ Reach cautious = own;
460
+ if (threatId >= 0) {
461
+ auto other = bs;
462
+ other.push_back({threatId, players[threatId].x, players[threatId].y, T + FUSE});
463
+ cautious = reach(predict(other, horizon), ME);
464
+ }
465
+
466
+ // Multiplayer scaling: more opponents = more chaos = be safer.
467
+ double threatMult = 1.0 + max(0, aliveOpp - 2) * 0.45;
468
+ // In multiplayer, value survival even more and offense less.
469
+ double survMult = 1.0 + max(0, aliveOpp - 2) * 0.18;
470
+ double denialScale = 1.0 / (1.0 + max(0, aliveOpp - 2) * 0.12);
471
+
472
+ for (int d = 0; d < 5; d++) {
473
+ int dest = predictDest(pred, d);
474
+ Reach adj = reach(pred, ME, dest);
475
+ double score = adj.life[d] * 22000.0 * survMult;
476
+ if (adj.count[d] > 0) {
477
+ score += 0.28 * adj.util[d] + (1.15 + 0.25 * max(0, aliveOpp - 2)) * log(1.0 + adj.count[d]) + denial * denialScale;
478
+ score -= 1.35 * min(50, goalDist[dest]) + 1.9 * visits(dest);
479
+ if (dest == cell(me.x, me.y)) score -= 0.55;
480
+ if (cautious.count[d] == 0)
481
+ score -= 32 + 5 * (horizon - cautious.life[d]);
482
+ else
483
+ score += 0.75 * log(1.0 + cautious.count[d]);
484
+ score -= 2.2 * threatMult * min(3.0, threat[dest]);
485
+ }
486
+ // collision penalty: contested target may block us
487
+ bool contested = false;
488
+ int nx = me.x + DX[d], ny = me.y + DY[d];
489
+ for (int i = 0; i < P; i++) {
490
+ if (i != ME && players[i].alive &&
491
+ abs(players[i].x - nx) + abs(players[i].y - ny) <= 1)
492
+ contested = true;
493
+ if (i != ME && players[i].alive && players[i].x == nx && players[i].y == ny)
494
+ score -= 2.0;
495
+ }
496
+ if (contested && d != 4) {
497
+ auto blocked = reach(pred, ME, cell(me.x, me.y));
498
+ if (blocked.life[d] < horizon) score -= 80;
499
+ else score -= 1.2;
500
+ }
501
+ score -= 0.002 * ((d + T) % 5);
502
+ if (score > bestScore) {
503
+ bestScore = score;
504
+ answer = {d, place};
505
+ }
506
+ }
507
+ }
508
+ if (answer.second) goal = -1;
509
+ prevCells.clear();
510
+ for (auto &p : players) prevCells.push_back(cell(p.x, p.y));
511
+ return answer;
512
+ }
513
+
514
+ int main() {
515
+ ios::sync_with_stdio(false);
516
+ cin.tie(nullptr);
517
+ string word;
518
+ if (!(cin >> word >> N >> P >> ME >> LIMIT >> FUSE >> RANGE >> CAP >> FIRE >> SHRINK >>
519
+ EVERY))
520
+ return 0;
521
+ board.resize(N);
522
+ players.resize(P);
523
+ while (readTurn()) {
524
+ auto [d, b] = decide();
525
+ cout << T << ' ' << DSTR[d] << ' ' << b << '\n';
526
+ cout.flush();
527
+ }
528
+ return 0;
529
+ }