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,725 @@
1
+ // Coordinated capture, escort and interception with simultaneous combat search.
2
+ #include <algorithm>
3
+ #include <array>
4
+ #include <cmath>
5
+ #include <chrono>
6
+ #include <cstdint>
7
+ #include <functional>
8
+ #include <iostream>
9
+ #include <limits>
10
+ #include <numeric>
11
+ #include <queue>
12
+ #include <sstream>
13
+ #include <string>
14
+ #include <utility>
15
+ #include <vector>
16
+ using namespace std;
17
+ #ifndef C_MULTI
18
+ #define C_MULTI 1.0
19
+ #endif
20
+ #ifndef C_DUEL
21
+ #define C_DUEL 1.0
22
+ #endif
23
+ #ifndef F_MULTI
24
+ #define F_MULTI 0.0
25
+ #endif
26
+ #ifndef F_DUEL
27
+ #define F_DUEL 1.0
28
+ #endif
29
+ #ifndef PICK_BONUS
30
+ #define PICK_BONUS 8.5
31
+ #endif
32
+ #ifndef SHOT_MIX
33
+ #define SHOT_MIX 0.0
34
+ #endif
35
+ #ifndef COLLISION_WEIGHT
36
+ #define COLLISION_WEIGHT .7
37
+ #endif
38
+
39
+ struct Unit { int id, team, x, y, hp, flag, respawn_at; }; // 阵亡时 x = y = -1
40
+ struct Flag { int id; string status; int x, y, holder, return_at; };
41
+ struct Event { string type; vector<int> args; }; // 各类事件的字段见 RULES.md
42
+
43
+ struct Game {
44
+ // 开局信息(INIT 块)
45
+ int teams = 0, me = 0, size = 0, turns = 0, hp = 0, damage = 0, respawn = 0, flag_return = 0, flag_cooldown = 0;
46
+ vector<string> map; // map[y][x]:'#' 墙,'.' 空地
47
+ vector<pair<int, int>> bases; // 各阵营基地中心,基地是以它为中心的 3×3
48
+ vector<pair<int, int>> spots; // 全部旗点
49
+ // 每回合更新(TURN 块)
50
+ int turn = 0;
51
+ vector<int> score;
52
+ vector<Unit> units;
53
+ vector<Flag> flags;
54
+ vector<Event> events; // 上一回合发生的事件
55
+ };
56
+
57
+ // 读一个块。读到 INIT 时继续读到 TURN 块结束。返回 false 表示输入结束。
58
+ bool read_turn(Game& g) {
59
+ string w;
60
+ while (cin >> w) {
61
+ if (w == "INIT") {
62
+ cin >> g.teams >> g.me >> g.size >> g.turns >> g.hp >> g.damage >> g.respawn >> g.flag_return >> g.flag_cooldown;
63
+ } else if (w == "MAP") {
64
+ g.map.assign(g.size, "");
65
+ for (auto& row : g.map) cin >> row;
66
+ } else if (w == "BASES") {
67
+ int k; cin >> k; g.bases.resize(k);
68
+ for (auto& b : g.bases) cin >> b.first >> b.second;
69
+ } else if (w == "SPOTS") {
70
+ int k; cin >> k; g.spots.resize(k);
71
+ for (auto& s : g.spots) cin >> s.first >> s.second;
72
+ } else if (w == "TURN") {
73
+ cin >> g.turn;
74
+ } else if (w == "SCORE") {
75
+ g.score.resize(g.teams);
76
+ for (auto& s : g.score) cin >> s;
77
+ } else if (w == "UNITS") {
78
+ int k; cin >> k; g.units.resize(k);
79
+ for (auto& u : g.units) { string tag; cin >> tag >> u.id >> u.team >> u.x >> u.y >> u.hp >> u.flag >> u.respawn_at; }
80
+ } else if (w == "FLAGS") {
81
+ int k; cin >> k; g.flags.resize(k);
82
+ for (auto& f : g.flags) { string tag; cin >> tag >> f.id >> f.status >> f.x >> f.y >> f.holder >> f.return_at; }
83
+ } else if (w == "EVENTS") {
84
+ int k; cin >> k; g.events.assign(k, {});
85
+ string line; getline(cin, line);
86
+ for (auto& e : g.events) {
87
+ getline(cin, line);
88
+ istringstream in(line);
89
+ string tag; in >> tag >> e.type;
90
+ for (int v; in >> v;) e.args.push_back(v);
91
+ }
92
+ } else if (w == "END") {
93
+ return true;
94
+ }
95
+ }
96
+ return false;
97
+ }
98
+
99
+ // 为自己的 3 个角色(id 为 3*me、3*me+1、3*me+2)各给出一个移动和一个动作。
100
+ // 移动:U 上 D 下 L 左 R 右 S 不动。动作:- 无,P 拾旗,X 丢旗,数字 = 攻击该 id 的角色。
101
+ struct Mission {
102
+ int type, key, p, unit = -1;
103
+ double danger = 0;
104
+ };
105
+ struct Prediction {
106
+ int id;
107
+ array<int,5> p;
108
+ array<double,5> pr;
109
+ array<double,5> other;
110
+ };
111
+ struct Choice { int target; double v; };
112
+
113
+ class Player {
114
+ int n=0, cells=0, me=0;
115
+ vector<array<int,5>> nb;
116
+ vector<vector<uint16_t>> dist;
117
+ vector<vector<int>> bd;
118
+ vector<int> oldp, lasttarget, oldhp, occupied;
119
+ array<int,3> lastmission{{-100,-100,-100}};
120
+ vector<Unit> u;
121
+ vector<int> pos;
122
+ vector<bool> immune;
123
+ vector<Prediction> pred;
124
+ vector<double> otherFocus;
125
+ vector<Mission> missions;
126
+ vector<array<int,3>> goal;
127
+ array<int,3> assigned, own;
128
+ array<double,3> rolew;
129
+ array<vector<double>,3> route;
130
+ array<array<double,5>,3> block;
131
+ // Probability of being able to shoot a particular enemy from each move.
132
+ array<array<vector<array<double,5>>,5>,3> hit;
133
+ const array<char,5> mc{{'S','U','D','L','R'}};
134
+ int D(int a,int b) const { return a<0||b<0 ? 999 : dist[a][b]; }
135
+ int man(int a,int b) const { return abs(a%n-b%n)+abs(a/n-b/n); }
136
+ bool shot(int a,int b) const {
137
+ if(a<0||b<0) return false;
138
+ int dx=b%n-a%n,dy=b/n-a/n;
139
+ if(abs(dx)+abs(dy)>2) return false;
140
+ if(abs(dx)==2) return nb[a][dx>0?4:3]>=0;
141
+ if(abs(dy)==2) return nb[a][dy>0?2:1]>=0;
142
+ if(abs(dx)==1 && abs(dy)==1) return nb[a][dx>0?4:3]>=0 || nb[a][dy>0?2:1]>=0;
143
+ return true;
144
+ }
145
+ int cell(int x,int y) const { return x<0 ? -1 : y*n+x; }
146
+ double tw(int id) const {
147
+ return (u[id].flag>=0?5.0:1.0)*(u[id].hp<=34?3.1:u[id].hp<=68?1.65:1.0);
148
+ }
149
+ void init(const Game& g) {
150
+ n=g.size;cells=n*n;me=g.me;
151
+ nb.resize(cells);dist.resize(cells);
152
+ for(int p=0;p<cells;p++) {
153
+ nb[p].fill(-1);
154
+ if(g.map[p/n][p%n]=='#') continue;
155
+ nb[p][0]=p;
156
+ const int dx[5]={0,0,0,-1,1},dy[5]={0,-1,1,0,0};
157
+ for(int m=1;m<5;m++) {
158
+ int x=p%n+dx[m],y=p/n+dy[m];
159
+ if(x>=0&&y>=0&&x<n&&y<n&&g.map[y][x]!='#') nb[p][m]=y*n+x;
160
+ }
161
+ }
162
+ vector<int> q(cells);
163
+ for(int p=0;p<cells;p++) {
164
+ dist[p].assign(cells,999);
165
+ if(nb[p][0]<0) continue;
166
+ int head=0,tail=0;q[tail++]=p;dist[p][p]=0;
167
+ while(head<tail) {
168
+ int a=q[head++];
169
+ for(int m=1;m<5;m++) { int b=nb[a][m];
170
+ if(b>=0&&dist[p][b]==999) {dist[p][b]=dist[p][a]+1;q[tail++]=b;}
171
+ }
172
+ }
173
+ }
174
+ bd.assign(g.teams,vector<int>(cells,999));
175
+ for(int t=0;t<g.teams;t++) for(int p=0;p<cells;p++)
176
+ for(int dy=-1;dy<=1;dy++) for(int dx=-1;dx<=1;dx++)
177
+ bd[t][p]=min(bd[t][p],D(p,cell(g.bases[t].first+dx,g.bases[t].second+dy)));
178
+ oldp.assign(g.units.size(),-1);lasttarget.assign(g.units.size(),-1);oldhp.assign(g.units.size(),100);
179
+ }
180
+ void update(const Game& g) {
181
+ u=g.units;pos.assign(u.size(),-1);immune.assign(u.size(),false);
182
+ occupied.assign(cells,-1);
183
+ for(auto& a:u) {pos[a.id]=cell(a.x,a.y);if(a.x>=0)occupied[pos[a.id]]=a.id;}
184
+ for(auto& a:u) if(pos[a.id]<0&&a.respawn_at<=g.turn&&a.respawn_at>=0) {
185
+ vector<int> spawn;
186
+ for(int dy=-1;dy<=1;dy++) for(int dx=-1;dx<=1;dx++) spawn.push_back(cell(g.bases[a.team].first+dx,g.bases[a.team].second+dy));
187
+ int c=cell(n/2,n/2),bc=cell(g.bases[a.team].first,g.bases[a.team].second);
188
+ stable_sort(spawn.begin(),spawn.end(),[&](int x,int y){
189
+ return make_pair(man(x,c),abs(x%n-bc%n)+2*abs(x/n-bc/n))<make_pair(man(y,c),abs(y%n-bc%n)+2*abs(y/n-bc/n));
190
+ });
191
+ for(int p:spawn) if(occupied[p]<0){pos[a.id]=p;occupied[p]=a.id;a.hp=100;a.flag=-1;immune[a.id]=true;break;}
192
+ }
193
+ for(auto& e:g.events) if(e.type=="attack"&&e.args.size()>=2) lasttarget[e.args[0]]=e.args[1];
194
+ for(int k=0;k<3;k++)own[k]=3*me+k;
195
+ }
196
+ vector<double> safeRoute(int uid,const Game& g) {
197
+ vector<double> d(cells,1e9),cost(cells,1);
198
+ for(int p=0;p<cells;p++) if(nb[p][0]>=0) {
199
+ double risk=0;
200
+ for(auto& e:u) if(e.team!=me&&pos[e.id]>=0&&e.flag<0&&!immune[e.id]) {
201
+ int r=D(p,pos[e.id]);
202
+ if(r>7)continue;
203
+ double escort=0;
204
+ for(int id:own) if(id!=uid&&pos[id]>=0&&u[id].flag<0) {
205
+ int dd=D(pos[id],pos[e.id]);
206
+ if(dd<=4)escort+= (u[id].hp>34?0.6:0.3);
207
+ }
208
+ double v=r<=2?3.5:r==3?2.8:r==4?1.5:r==5?.6:.15;
209
+ risk+=v*(.5+.5*e.hp/100.0)/(1+escort*1.6);
210
+ }
211
+ cost[p]=1+min(6.0,risk)*(u[uid].hp<=34?.85:u[uid].hp<=68?.6:.45);
212
+ }
213
+ priority_queue<pair<double,int>,vector<pair<double,int>>,greater<pair<double,int>>> q;
214
+ for(int p=0;p<cells;p++) if(bd[me][p]==0){d[p]=0;q.push({0,p});}
215
+ while(!q.empty()) {
216
+ auto [v,p]=q.top();q.pop();if(v!=d[p])continue;
217
+ for(int m=1;m<5;m++){int b=nb[p][m];if(b>=0&&d[b]>v+(cost[b]+cost[p])*.5){d[b]=v+(cost[b]+cost[p])*.5;q.push({d[b],b});}}
218
+ }
219
+ return d;
220
+ }
221
+ int intercept(int uid,int enemy) const {
222
+ int a=pos[uid],b=pos[enemy],t=u[enemy].team;
223
+ if(a<0||b<0)return b;
224
+ int p=b;vector<int> path{p};
225
+ while(bd[t][p]>0&&path.size()<80) {
226
+ int best=-1;
227
+ for(int m=1;m<5;m++)if(nb[p][m]>=0&&bd[t][nb[p][m]]<bd[t][p]){
228
+ int z=nb[p][m];if(best<0||D(a,z)<D(a,best))best=z;
229
+ }
230
+ if(best<0)break;p=best;path.push_back(p);
231
+ }
232
+ int best=b;double val=1e9;
233
+ for(int j=0;j<(int)path.size();j++) {
234
+ double v=max(0,D(a,path[j])-2-j)*3.0+j*.35+D(a,path[j])*.1;
235
+ if(v<val){val=v;best=path[j];}
236
+ }
237
+ return best;
238
+ }
239
+ void plan(const Game& g) {
240
+ missions.clear();goal.clear();
241
+ auto add=[&](Mission m){missions.push_back(m);array<int,3> a; a.fill(m.p);goal.push_back(a);};
242
+ for(auto& f:g.flags) if((f.status=="home"||f.status=="dropped")&&f.x>=0&&(f.return_at<0||f.return_at>g.turn))
243
+ add({0,f.id,cell(f.x,f.y)});
244
+ for(auto& e:u) if(e.team!=me&&pos[e.id]>=0&&e.flag>=0&&bd[e.team][pos[e.id]]>0) {
245
+ bool can=false;for(int id:own)if(pos[id]>=0&&u[id].flag<0&&D(pos[id],pos[e.id])<=bd[e.team][pos[e.id]]+3)can=true;
246
+ if(can) {add({1,100+e.id,pos[e.id],e.id});for(int k=0;k<3;k++)goal.back()[k]=intercept(own[k],e.id);}
247
+ }
248
+ for(int id:own)if(pos[id]>=0&&u[id].flag>=0) {
249
+ double threat=0;int bad=-1;double bv=0;
250
+ for(auto& e:u)if(e.team!=me&&pos[e.id]>=0&&e.flag<0&&!immune[e.id]) {
251
+ int d=D(pos[e.id],pos[id]);double v=d<=3?2.0:d<=5?1.2:d<=7?.5:0;
252
+ threat+=v;if(v>bv){bv=v;bad=e.id;}
253
+ }
254
+ if(threat>.1&&bd[me][pos[id]]>1){add({2,200+id,pos[id],id,min(4.0,threat)});
255
+ if(bad>=0)goal.back().fill(pos[bad]);
256
+ }
257
+ }
258
+ vector<pair<int,int>> ss;
259
+ for(int j=0;j<(int)g.spots.size();j++)ss.push_back({bd[me][cell(g.spots[j].first,g.spots[j].second)],j});
260
+ sort(ss.begin(),ss.end());
261
+ for(int j=0;j<min(3,(int)ss.size());j++){int s=ss[j].second;add({3,300+s,cell(g.spots[s].first,g.spots[s].second)});}
262
+ if(missions.empty())add({3,300,cell(n/2,n/2)});
263
+ int M=missions.size();
264
+ array<vector<int>,3> options;
265
+ for(int k=0;k<3;k++) {
266
+ int id=own[k];assigned[k]=-1;rolew[k]=.85;route[k].clear();
267
+ if(pos[id]<0||u[id].flag>=0){options[k]={-1};if(pos[id]>=0)route[k]=safeRoute(id,g);continue;}
268
+ vector<pair<double,int>> order;
269
+ for(int j=0;j<M;j++) {
270
+ auto& m=missions[j];int d=D(pos[id],goal[j][k]);double val=0;
271
+ if(m.type==0)val=240.0/(8+d+bd[me][m.p]);
272
+ if(m.type==1)val=100.0/(6+d+bd[u[m.unit].team][pos[m.unit]]);
273
+ if(m.type==2)val=12*m.danger/(3+d);
274
+ if(m.type==3)val=2.8/(1+.15*d);
275
+ if(lastmission[k]==m.key)val+=.3;
276
+ order.push_back({val,j});
277
+ }
278
+ sort(order.rbegin(),order.rend());
279
+ for(int j=0;j<min(7,M);j++)options[k].push_back(order[j].second);
280
+ }
281
+ double best=-1e30;
282
+ for(int a:options[0])for(int b:options[1])for(int c:options[2]) {
283
+ array<int,3> as{{a,b,c}};double v=0;
284
+ for(int j=0;j<M;j++) {
285
+ int cnt=0,mind=999;double extra=0,health=0;
286
+ for(int k=0;k<3;k++)if(as[k]==j){cnt++;int d=D(pos[own[k]],goal[j][k]);mind=min(mind,d);extra+=d;health+=(u[own[k]].hp<=34?.65:u[own[k]].hp<=68?.85:1.0);}
287
+ if(!cnt)continue;
288
+ auto& m=missions[j];
289
+ if(m.type==0) {
290
+ vector<int> nearest(g.teams,999),force(g.teams,0);int eMin=999;
291
+ for(auto& e:u)if(e.team!=me&&pos[e.id]>=0&&e.flag<0){nearest[e.team]=min(nearest[e.team],D(pos[e.id],m.p));eMin=min(eMin,D(pos[e.id],m.p));}
292
+ for(auto& e:u)if(e.team!=me&&pos[e.id]>=0&&e.flag<0&&D(pos[e.id],m.p)<=nearest[e.team]+3&&nearest[e.team]<=mind+3)force[e.team]++;
293
+ double ef=0,others=0;for(int t=0;t<g.teams;t++)if(t!=me&&force[t]){others+=force[t];ef=max(ef,(double)force[t]);}
294
+ ef+=.15*(others-ef);
295
+ double pr=.97;
296
+ if(eMin<=mind+3) {double lead=exp(max(-1.0,min(1.5,.22*(mind-eMin))));pr=.08+.90*health*health/(health*health+ef*ef*lead);}
297
+ double vv=240.0/(8+mind+bd[me][m.p])*pr;
298
+ if(mind+bd[me][m.p]+g.turn>g.turns)vv*=.08;
299
+ if(cnt>1&&eMin<=mind+3)vv+=.7*(cnt-1);
300
+ v+=vv-.045*(extra-cnt*mind);
301
+ } else if(m.type==1) {
302
+ int e=m.unit;double pr=.25+.75*health*health/(health*health+2.0);
303
+ double leader=1+min(.6,.12*max(0,g.score[u[e].team]-g.score[me]));
304
+ v+=100*pr*leader/(6+mind+bd[u[e].team][pos[e]])-.06*(extra-cnt*mind);
305
+ } else if(m.type==2) {
306
+ int d=D(pos[m.unit],m.p);
307
+ double escortWeight=g.teams>=6?1.8:1.0;
308
+ v+=escortWeight*min(14.0,6*m.danger)*(1-exp(-.8*cnt))/(1+.13*mind)-.03*extra;
309
+ } else v+=2.5/(1+.13*mind)+.12*(cnt-1)-.04*(extra-cnt*mind);
310
+ }
311
+ for(int k=0;k<3;k++)if(as[k]>=0&&missions[as[k]].key==lastmission[k])v+=.12;
312
+ if(v>best){best=v;assigned=as;}
313
+ }
314
+ for(int k=0;k<3;k++)if(assigned[k]>=0) {
315
+ auto& m=missions[assigned[k]];lastmission[k]=m.key;
316
+ if(m.type==0) {
317
+ int runner=k;
318
+ for(int h=0;h<3;h++)if(assigned[h]==assigned[k]&&D(pos[own[h]],m.p)+(100-u[own[h]].hp)*.025<D(pos[own[runner]],m.p)+(100-u[own[runner]].hp)*.025)runner=h;
319
+ rolew[k]=runner==k?1.0:.72;
320
+ } else if(m.type==1)rolew[k]=.85;
321
+ else if(m.type==2)rolew[k]=.65;
322
+ else rolew[k]=.6;
323
+ }
324
+ }
325
+ void predict(const Game& g) {
326
+ pred.clear();
327
+ for(auto& e:u)if(e.team!=me&&pos[e.id]>=0) {
328
+ Prediction pr;pr.id=e.id;pr.p=nb[pos[e.id]];pr.pr.fill(0);pr.other.fill(0);
329
+ int target=-1,dd=999;
330
+ if(e.flag<0) {
331
+ for(auto& f:g.flags)if(f.x>=0&&(f.status=="home"||f.status=="dropped")&&(f.return_at<0||f.return_at>g.turn)){
332
+ int p=cell(f.x,f.y),d=D(pos[e.id],p);if(d<dd){dd=d;target=p;}
333
+ }
334
+ int victim=-1;double bv=-1e9;
335
+ for(auto& z:u)if(z.team!=e.team&&pos[z.id]>=0&&!immune[z.id]) {
336
+ int d=D(pos[e.id],pos[z.id]);double v=(z.flag>=0?8.0:0)+(100-z.hp)*.035-d*1.5;
337
+ if(d<=5&&v>bv){bv=v;victim=z.id;}
338
+ }
339
+ if(victim>=0&&(u[victim].flag>=0||dd>3)) { target=pos[victim];dd=D(pos[e.id],target); }
340
+ if(target<0) {
341
+ int d0=999;for(auto s:g.spots){int p=cell(s.first,s.second),d=D(pos[e.id],p)+bd[e.team][p]/3;if(d<d0){d0=d;target=p;}}
342
+ }
343
+ }
344
+ double sum=0;
345
+ for(int m=0;m<5;m++)if(pr.p[m]>=0) {
346
+ int p=pr.p[m];double v=0;
347
+ if(e.flag>=0) {
348
+ v=-2.4*(bd[e.team][p]-bd[e.team][pos[e.id]]);
349
+ for(int id:own)if(pos[id]>=0&&u[id].flag<0&&!immune[id]&&D(pos[id],p)<=3)v-=.3*(4-D(pos[id],p));
350
+ } else {
351
+ if(target>=0)v=-1.8*(D(p,target)-D(pos[e.id],target));
352
+ if(target>=0&&D(p,target)<=2&&dd<=5)v+=.4;
353
+ }
354
+ if(oldp[e.id]>=0&&pos[e.id]!=oldp[e.id]&&p-pos[e.id]==pos[e.id]-oldp[e.id])v+=.35;
355
+ if(m==0)v-=.15;
356
+ if(occupied[p]>=0&&occupied[p]!=e.id) v-=.65;
357
+ pr.pr[m]=exp(max(-5.0,min(5.0,v)));sum+=pr.pr[m];
358
+ }
359
+ int cnt=0;for(int p:pr.p)if(p>=0)cnt++;
360
+ for(int m=0;m<5;m++)if(pr.p[m]>=0)pr.pr[m]=.90*pr.pr[m]/sum+.10/cnt;
361
+ pred.push_back(pr);
362
+ }
363
+ for(auto& e:pred)for(int m=0;m<5;m++)if(e.p[m]>=0) {
364
+ for(auto& z:pred)if(u[z.id].team!=u[e.id].team&&!immune[z.id]) {
365
+ double p=0;for(int j=0;j<5;j++)if(z.p[j]>=0&&shot(e.p[m],z.p[j]))p+=z.pr[j];
366
+ e.other[m]+=tw(z.id)*p;
367
+ }
368
+ }
369
+ otherFocus.assign(g.teams,0);
370
+ for(int t=0;t<g.teams;t++)if(t!=me) for(auto& victim:pred)if(u[victim.id].team!=t&&!immune[victim.id]) {
371
+ double val=0;int need=(u[victim.id].hp+33)/34;
372
+ for(int m=0;m<5;m++)if(victim.p[m]>=0) {
373
+ array<double,4> dp{{1,0,0,0}};
374
+ for(auto& a:pred)if(u[a.id].team==t&&u[a.id].flag<0&&!immune[a.id]) {
375
+ double p=0;for(int h=0;h<5;h++)if(a.p[h]>=0&&shot(a.p[h],victim.p[m]))p+=a.pr[h];
376
+ array<double,4> z{};for(int h=0;h<4;h++){z[h]+=dp[h]*(1-p);z[min(3,h+1)]+=dp[h]*p;}dp=z;
377
+ }
378
+ double hits=0,kill=0;for(int h=0;h<4;h++){hits+=dp[h]*min(h,need);if(h>=need)kill+=dp[h];}
379
+ val+=victim.pr[m]*(hits*1.75+kill*(u[victim.id].flag>=0?19.0:7.0));
380
+ }
381
+ otherFocus[t]+=val*val*val;
382
+ }
383
+ for(int k=0;k<3;k++)for(int m=0;m<5;m++) {
384
+ hit[k][m].assign(pred.size(),{});block[k][m]=0;
385
+ int a=pos[own[k]];if(a<0||nb[a][m]<0)continue;int p=nb[a][m];
386
+ double unblocked=1;
387
+ for(int j=0;j<(int)pred.size();j++) {
388
+ auto& e=pred[j];double bp=0;int b=pos[e.id];
389
+ for(int h=0;h<5;h++)if(e.p[h]>=0) {
390
+ int q=e.p[h],ap=p,bp0=q;
391
+ if(p==q||(p==b&&q==a)||(p==b&&q==b)) {ap=a;bp0=b;bp+=e.pr[h];}
392
+ if(q==a&&p==a)bp0=b;
393
+ hit[k][m][j][h]=shot(ap,bp0)?1.0:0.0;
394
+ }
395
+ unblocked*=1-bp;
396
+ }
397
+ block[k][m]=1-unblocked;
398
+ }
399
+ }
400
+ double incoming(const array<int,3>& move,array<double,3>& death,array<double,3>& expected) const {
401
+ array<array<double,4>,3> dp{};array<double,3> eh{};
402
+ for(int k=0;k<3;k++)dp[k][0]=1;
403
+ for(int j=0;j<(int)pred.size();j++) {
404
+ auto& e=pred[j];if(u[e.id].flag>=0||immune[e.id])continue;
405
+ array<double,3> prob{};
406
+ for(int h=0;h<5;h++)if(e.p[h]>=0) {
407
+ array<double,3> w{};double sum=e.other[h];
408
+ for(int k=0;k<3;k++)if(pos[own[k]]>=0&&!immune[own[k]]) {
409
+ double s=hit[k][move[k]][j][h];
410
+ if(s>0) {w[k]=tw(own[k]);if(lasttarget[e.id]==own[k])w[k]*=1.25;sum+=w[k];}
411
+ }
412
+ if(sum>0)for(int k=0;k<3;k++)prob[k]+=e.pr[h]*w[k]/sum;
413
+ }
414
+ for(int k=0;k<3;k++) {
415
+ eh[k]+=prob[k];
416
+ array<double,4> z{};
417
+ for(int a=0;a<4;a++){z[a]+=dp[k][a]*(1-prob[k]);z[min(3,a+1)]+=dp[k][a]*prob[k];}dp[k]=z;
418
+ }
419
+ }
420
+ double v=0;
421
+ for(int k=0;k<3;k++)if(pos[own[k]]>=0) {
422
+ int id=own[k],need=(u[id].hp+33)/34;death[k]=0;
423
+ for(int a=need;a<4;a++)death[k]+=dp[k][a];
424
+ double dmg=0;for(int a=0;a<4;a++)dmg+=dp[k][a]*min(a,need);
425
+ double life= u[id].flag>=0 ? 24.0+max(0,12-bd[me][pos[id]])*.5 : 8.0;
426
+ if(bd[me][pos[id]]<4&&u[id].flag<0)life=6;
427
+ v-=dmg*(u[id].flag>=0?2.1:1.1)+life*death[k];
428
+ if(u[id].flag>=0&&u[id].hp<=68)v-=eh[k]*1.2;
429
+ }
430
+ double focusloss=0;
431
+ array<double,3> focusdeath{};
432
+ for(int t=0;t<(int)otherFocus.size();t++)if(t!=me) {
433
+ array<double,3> value{},loss{},dk{};double sum=otherFocus[t];
434
+ for(int k=0;k<3;k++)if(pos[own[k]]>=0&&!immune[own[k]]) {
435
+ int id=own[k],need=(u[id].hp+33)/34;array<double,4> z{{1,0,0,0}};
436
+ for(int j=0;j<(int)pred.size();j++)if(u[pred[j].id].team==t&&u[pred[j].id].flag<0&&!immune[pred[j].id]) {
437
+ double p=0;for(int h=0;h<5;h++)p+=pred[j].pr[h]*hit[k][move[k]][j][h];
438
+ array<double,4> zz{};for(int h=0;h<4;h++){zz[h]+=z[h]*(1-p);zz[min(3,h+1)]+=z[h]*p;}z=zz;
439
+ }
440
+ double hits=0,kills=0;for(int h=0;h<4;h++){hits+=z[h]*min(h,need);if(h>=need)kills+=z[h];}
441
+ double desirability=hits*1.75+kills*(u[id].flag>=0?22.0:7.0);
442
+ value[k]=desirability*desirability*desirability;
443
+ if(u[id].flag>=0)value[k]*=1.8;
444
+ sum+=value[k];dk[k]=kills;
445
+ double life=u[id].flag>=0?24.0+max(0,12-bd[me][pos[id]])*.5:8.0;
446
+ loss[k]=hits*(u[id].flag>=0?2.1:1.1)+life*kills;
447
+ }
448
+ if(sum>0)for(int k=0;k<3;k++){focusloss+=value[k]*loss[k]/sum;focusdeath[k]+=value[k]*dk[k]/sum;}
449
+ }
450
+ for(int k=0;k<3;k++){death[k]=max(death[k],min(1.0,focusdeath[k])*.65);expected[k]=eh[k];}
451
+ return .55*v-.45*max(-v,focusloss);
452
+ }
453
+ using FutureTable=array<vector<array<array<double,4>,5>>,3>;
454
+ FutureTable futureTable(const array<int,3>& mv,const array<int,3>& pp,const Game& g) const {
455
+ FutureTable ft;
456
+ for(int k=0;k<3;k++) {
457
+ ft[k].resize(pred.size());int id=own[k],p=pp[k];if(p<0)continue;
458
+ bool carry=u[id].flag>=0;
459
+ for(auto& f:g.flags)if(f.x>=0&&cell(f.x,f.y)==p&&(f.return_at<0||f.return_at>g.turn))carry=true;
460
+ if(!carry||bd[me][p]==0)continue;
461
+ vector<int> path{p};
462
+ while(bd[me][path.back()]>0&&path.size()<9) {
463
+ int a=path.back(),best=-1;double bv=1e9;
464
+ for(int m=1;m<5;m++)if(nb[a][m]>=0&&bd[me][nb[a][m]]<bd[me][a]) {
465
+ int z=nb[a][m];double v=0;
466
+ for(auto& e:pred)if(u[e.id].flag<0&&D(z,pos[e.id])<=6)v+=1.0/(.4+D(z,pos[e.id]));
467
+ if(v<bv){bv=v;best=z;}
468
+ }
469
+ if(best<0)break;path.push_back(best);
470
+ }
471
+ for(int j=0;j<(int)pred.size();j++) {
472
+ int enemy=pred[j].id;
473
+ if(u[enemy].flag>=0||D(p,pos[enemy])>7)continue;
474
+ int need=(u[enemy].hp+33)/34;
475
+ for(int h=0;h<5;h++)if(pred[j].p[h]>=0) {
476
+ int q=pred[j].p[h],first=99;
477
+ for(int step=1;step<(int)path.size();step++)if(D(q,path[step])<=step+2){first=step;break;}
478
+ if(first==99)continue;
479
+ double support=0;
480
+ for(int s=0;s<3;s++)if(s!=k&&pp[s]>=0&&u[own[s]].flag<0) {
481
+ int d=D(pp[s],q);
482
+ support+=d<=2?1:d==3?.95:d==4?.60:d==5?.25:0;
483
+ }
484
+ for(int shots=0;shots<4;shots++) {
485
+ if(shots>=need)continue;
486
+ int kill=support>.15?(int)ceil((need-shots)/support):99;
487
+ int exposed=max(0,min({bd[me][p],kill,7})-first+1);
488
+ double w=u[id].hp<=34?15:u[id].hp<=68?8:5;
489
+ ft[k][j][h][shots]=exposed*.85*w/(w+pred[j].other[h]);
490
+ }
491
+ }
492
+ }
493
+ }
494
+ return ft;
495
+ }
496
+ double futureRisk(const array<int,3>& mv,const array<int,3>& targets,const FutureTable& ft,const array<double,3>& now,const array<int,3>& pp) const {
497
+ array<double,3> future{};
498
+ for(int j=0;j<(int)pred.size();j++)for(int h=0;h<5;h++)if(pred[j].p[h]>=0) {
499
+ int cnt=0;
500
+ for(int k=0;k<3;k++)if(targets[k]==j&&hit[k][mv[k]][j][h]>.5)cnt++;
501
+ for(int k=0;k<3;k++)if(u[own[k]].flag>=0||targets[k]<0)future[k]+=pred[j].pr[h]*ft[k][j][h][cnt];
502
+ }
503
+ double value=0;
504
+ for(int k=0;k<3;k++)if(pp[k]>=0&&future[k]>0&&(u[own[k]].flag>=0||targets[k]<0)) {
505
+ if(n>23&&u[own[k]].flag<0)continue;
506
+ double need=(u[own[k]].hp+33)/34;
507
+ double danger=max(0.0,min(1.0,(now[k]+future[k]-need+.45)/1.3));
508
+ value-=danger*(u[own[k]].flag>=0?15:18);
509
+ value-=future[k]*.3;
510
+ }
511
+ return value;
512
+ }
513
+ double firing(const array<int,3>& move,const array<int,3>& targets) const {
514
+ double v=0;
515
+ for(int j=0;j<(int)pred.size();j++) {
516
+ int id=pred[j].id;if(immune[id])continue;
517
+ bool any=false;for(int k=0;k<3;k++)if(targets[k]==j)any=true;if(!any)continue;
518
+ int need=(u[id].hp+33)/34;
519
+ double kill=0,hits=0;
520
+ int legal=0;for(int h=0;h<5;h++)if(pred[j].p[h]>=0)legal++;
521
+ for(int h=0;h<5;h++)if(pred[j].p[h]>=0) {
522
+ int cnt=0;for(int k=0;k<3;k++)if(targets[k]==j&&hit[k][move[k]][j][h]>.5)cnt++;
523
+ double mix=u[id].flag>=0?.06:SHOT_MIX;
524
+ double probability=(1-mix)*pred[j].pr[h]+mix/legal;
525
+ hits+=probability*min(need,cnt);if(cnt>=need)kill+=probability;
526
+ }
527
+ double value=7;
528
+ if(u[id].flag>=0)value+=14.0/(1+.05*bd[me][pos[id]]);
529
+ for(int k=0;k<3;k++)if(pos[own[k]]>=0&&u[own[k]].flag>=0&&D(pos[id],pos[own[k]])<=5)value+=5;
530
+ v+=hits*1.75+kill*value;
531
+ }
532
+ return v;
533
+ }
534
+ struct Candidate {array<int,3> mv,ac;double value,future;};
535
+ vector<int> settle(const array<int,3>& mv,const vector<int>& em) const {
536
+ int count=u.size();vector<int> want(count,-1),owner(cells,-1),frequency(cells,0);vector<bool> blocked(count,false);
537
+ for(int id=0;id<count;id++)if(pos[id]>=0) {owner[pos[id]]=id;want[id]=pos[id];}
538
+ for(int j=0;j<(int)pred.size();j++)want[pred[j].id]=pred[j].p[em[j]];
539
+ for(int k=0;k<3;k++)if(pos[own[k]]>=0)want[own[k]]=nb[pos[own[k]]][mv[k]];
540
+ for(int p:want)if(p>=0)frequency[p]++;
541
+ for(int id=0;id<count;id++)if(want[id]>=0) {
542
+ if(frequency[want[id]]>1)blocked[id]=true;
543
+ int other=owner[want[id]];
544
+ if(other>=0&&other!=id&&u[other].team!=u[id].team&&want[other]==pos[id])blocked[id]=blocked[other]=true;
545
+ }
546
+ for(bool change=true;change;) {
547
+ change=false;
548
+ for(int id=0;id<count;id++)if(want[id]>=0&&!blocked[id]&&want[id]!=pos[id]) {
549
+ int other=owner[want[id]];
550
+ if(other>=0&&(blocked[other]||want[other]==pos[other])){blocked[id]=true;change=true;}
551
+ }
552
+ }
553
+ for(int id=0;id<count;id++)if(blocked[id])want[id]=pos[id];
554
+ return want;
555
+ }
556
+ double actualIncoming(const vector<int>& p,array<double,3>& death) const {
557
+ array<array<double,4>,3> dp{};for(int k=0;k<3;k++)dp[k][0]=1;
558
+ for(auto& e:pred)if(u[e.id].flag<0&&!immune[e.id]) {
559
+ double total=0;array<double,3> w{};
560
+ for(auto& z:u)if(z.team!=u[e.id].team&&p[z.id]>=0&&!immune[z.id]&&shot(p[e.id],p[z.id])) {
561
+ double v=tw(z.id);if(z.team==me&&lasttarget[e.id]==z.id)v*=1.25;
562
+ total+=v;if(z.team==me)w[z.id-3*me]=v;
563
+ }
564
+ if(total>0)for(int k=0;k<3;k++) {
565
+ double pr=w[k]/total;array<double,4> z{};
566
+ for(int h=0;h<4;h++){z[h]+=dp[k][h]*(1-pr);z[min(3,h+1)]+=dp[k][h]*pr;}dp[k]=z;
567
+ }
568
+ }
569
+ double loss=0,focus=0;
570
+ for(int k=0;k<3;k++)if(p[own[k]]>=0) {
571
+ int id=own[k],need=(u[id].hp+33)/34;double hits=0,kills=0;
572
+ for(int h=0;h<4;h++){hits+=dp[k][h]*min(need,h);if(h>=need)kills+=dp[k][h];}
573
+ death[k]=kills;
574
+ double life=u[id].flag>=0?24.0+max(0,12-bd[me][pos[id]])*.5:(bd[me][pos[id]]<4?6:8);
575
+ loss+=hits*(u[id].flag>=0?2.1:1.1)+life*kills;
576
+ if(u[id].flag>=0&&u[id].hp<=68)loss+=hits*1.2;
577
+ }
578
+ for(int t=0;t<(int)otherFocus.size();t++)if(t!=me) {
579
+ double denominator=0;array<double,3> weight{},ls{},dk{};
580
+ for(auto& victim:u)if(victim.team!=t&&p[victim.id]>=0&&!immune[victim.id]) {
581
+ int cnt=0;for(int j=t*3;j<t*3+3;j++)if(p[j]>=0&&!immune[j]&&u[j].flag<0&&shot(p[j],p[victim.id]))cnt++;
582
+ int need=(victim.hp+33)/34;double kills=cnt>=need?1:0,hits=min(need,cnt);
583
+ double desire=hits*1.75+kills*(victim.flag>=0?(victim.team==me?22:19):7);
584
+ double w=desire*desire*desire;if(victim.team==me&&victim.flag>=0)w*=1.8;
585
+ denominator+=w;
586
+ if(victim.team==me) {
587
+ int k=victim.id-3*me;weight[k]=w;dk[k]=kills;
588
+ double life=victim.flag>=0?24+max(0,12-bd[me][pos[victim.id]])*.5:8;
589
+ ls[k]=hits*(victim.flag>=0?2.1:1.1)+life*kills;
590
+ }
591
+ }
592
+ if(denominator>0)for(int k=0;k<3;k++){focus+=weight[k]*ls[k]/denominator;death[k]=max(death[k],weight[k]*dk[k]/denominator*.65);}
593
+ }
594
+ return -.55*loss-.45*max(loss,focus);
595
+ }
596
+ double actualFire(const vector<int>& p,const array<int,3>& ac) const {
597
+ vector<int> hits(u.size(),0);
598
+ for(int k=0;k<3;k++)if(ac[k]>=0&&p[own[k]]>=0&&!immune[own[k]]&&u[own[k]].flag<0) {
599
+ int id=pred[ac[k]].id;if(!immune[id]&&shot(p[own[k]],p[id]))hits[id]++;
600
+ }
601
+ double value=0;
602
+ for(auto& e:pred)if(hits[e.id]) {
603
+ int need=(u[e.id].hp+33)/34;double kv=7;
604
+ if(u[e.id].flag>=0)kv+=14/(1+.05*bd[me][pos[e.id]]);
605
+ for(int k=0;k<3;k++)if(pos[own[k]]>=0&&u[own[k]].flag>=0&&D(pos[e.id],pos[own[k]])<=5)kv+=5;
606
+ value+=1.75*min(hits[e.id],need)+(hits[e.id]>=need?kv:0);
607
+ }
608
+ return value;
609
+ }
610
+ public:
611
+ string decide(const Game& g) {
612
+ if(!n)init(g);update(g);plan(g);predict(g);
613
+ array<vector<int>,3> moves;
614
+ array<array<double,5>,3> positional{};
615
+ array<array<vector<int>,5>,3> actions;
616
+ array<array<double,5>,3> pickup{};
617
+ for(int k=0;k<3;k++) {
618
+ int id=own[k],a=pos[id];
619
+ if(a<0){moves[k]={0};actions[k][0]={-1};continue;}
620
+ for(int m=0;m<5;m++)if(nb[a][m]>=0) {
621
+ int p=nb[a][m];moves[k].push_back(m);
622
+ double v=0;
623
+ if(u[id].flag>=0) {
624
+ double rd=route[k][p];v=-1.5*(.7*rd+.3*bd[me][p]);
625
+ if(bd[me][p]==0)v+=30;
626
+ v-=.15*(m==0);
627
+ } else if(assigned[k]>=0) {
628
+ auto& ms=missions[assigned[k]];int gp=goal[assigned[k]][k];int d=D(p,gp);
629
+ if(ms.type==0&&rolew[k]<.9&&d==0)d=1;
630
+ if(ms.type==1)d=max(0,d-1);
631
+ if(ms.type==2)d=max(0,d-2);
632
+ v=-rolew[k]*d;
633
+ if(ms.type==0)for(int h=0;h<3;h++)if(h!=k&&assigned[h]==assigned[k]&&pos[own[h]]>=0)v-=.1*max(0,D(p,pos[own[h]])-3);
634
+ }
635
+ v-=block[k][m]*1.7;
636
+ if(m!=0)v+=(g.turn*7919+id*193+m*769)%103*.00015;
637
+ positional[k][m]=v;
638
+ vector<pair<double,int>> opts;
639
+ if(u[id].flag<0&&!immune[id])for(int j=0;j<(int)pred.size();j++)if(!immune[pred[j].id]) {
640
+ double h=0;for(int z=0;z<5;z++)h+=pred[j].pr[z]*hit[k][m][j][z];
641
+ if(h>.025){int e=pred[j].id;double val=h*(1.75+(u[e].hp<=34?7:u[e].hp<=68?3:1)+(u[e].flag>=0?7:0));opts.push_back({val,j});}
642
+ }
643
+ sort(opts.rbegin(),opts.rend());
644
+ for(int z=0;z<min(4,(int)opts.size());z++)actions[k][m].push_back(opts[z].second);
645
+ bool flaghere=false;
646
+ for(auto& f:g.flags)if(f.x>=0&&cell(f.x,f.y)==p&&(f.return_at<0||f.return_at>g.turn))flaghere=true;
647
+ if(u[id].flag<0&&flaghere){pickup[k][m]=PICK_BONUS*(1-block[k][m]);actions[k][m].push_back(-1);}
648
+ if(actions[k][m].empty())actions[k][m].push_back(-1);
649
+ if(u[id].flag>=0){actions[k][m]={-1};pickup[k][m]=0;}
650
+ }
651
+ }
652
+ double best=-1e50;array<int,3> bm{{0,0,0}},ba{{-1,-1,-1}};
653
+ vector<Candidate> candidates;
654
+ for(int a:moves[0])for(int b:moves[1])for(int c:moves[2]) {
655
+ array<int,3> mv{{a,b,c}},pp{{-1,-1,-1}};bool good=true;
656
+ for(int k=0;k<3;k++)if(pos[own[k]]>=0)pp[k]=nb[pos[own[k]]][mv[k]];
657
+ for(int k=0;k<3;k++)for(int h=k+1;h<3;h++)if(pp[k]>=0&&pp[k]==pp[h])good=false;
658
+ if(!good)continue;
659
+ double combat=g.teams==2?C_DUEL:C_MULTI,futurescale=g.teams==2?F_DUEL:F_MULTI;
660
+ array<double,3> death{},expected{};double value=combat*incoming(mv,death,expected);
661
+ for(int k=0;k<3;k++)value+=positional[k][mv[k]];
662
+ auto ft=futureTable(mv,pp,g);
663
+ Candidate candidate{mv,{{-1,-1,-1}},-1e50,0};
664
+ for(int x:actions[0][a])for(int y:actions[1][b])for(int z:actions[2][c]) {
665
+ array<int,3> ac{{x,y,z}};double fr=futurescale*futureRisk(mv,ac,ft,expected,pp);
666
+ double v=value+combat*firing(mv,ac)+fr;
667
+ for(int k=0;k<3;k++)if(ac[k]<0)v+=pickup[k][mv[k]]*(1-death[k]);
668
+ if(v>best){best=v;bm=mv;ba=ac;}
669
+ if(v>candidate.value)candidate={mv,ac,v,fr};
670
+ }
671
+ candidates.push_back(candidate);
672
+ }
673
+ if(COLLISION_WEIGHT>0&&g.teams>=4&&!pred.empty()) {
674
+ auto refinementStart=chrono::steady_clock::now();
675
+ sort(candidates.begin(),candidates.end(),[](const Candidate& a,const Candidate& b){return a.value>b.value;});
676
+ if(candidates.size()>16)candidates.resize(16);
677
+ constexpr int samples=24;vector<vector<int>> enemyMoves(samples,vector<int>(pred.size()));
678
+ for(int s=0;s<samples;s++)for(int j=0;j<(int)pred.size();j++) {
679
+ uint32_t h=(uint32_t)(g.turn*101+pred[j].id*7919+187);
680
+ h^=h>>16;h*=0x7feb352dU;h^=h>>15;h*=0x846ca68bU;h^=h>>16;
681
+ double r=fmod((s+.5)/samples+(h%65536)/65536.0,1.0),acc=0;
682
+ int chosen=0;for(int m=0;m<5;m++)if(pred[j].p[m]>=0){chosen=m;acc+=pred[j].pr[m];if(r<=acc)break;}
683
+ enemyMoves[s][j]=chosen;
684
+ }
685
+ double refinedBest=-1e50;
686
+ for(auto& ca:candidates) {
687
+ if(chrono::duration<double,milli>(chrono::steady_clock::now()-refinementStart).count()>12)break;
688
+ double actual=0;
689
+ for(int s=0;s<samples;s++) {
690
+ auto p=settle(ca.mv,enemyMoves[s]);array<double,3> death{};
691
+ double v=(g.teams==2?C_DUEL:C_MULTI)*(actualIncoming(p,death)+actualFire(p,ca.ac))+ca.future;
692
+ for(int k=0;k<3;k++)if(p[own[k]]>=0) {
693
+ int id=own[k],want=nb[pos[id]][ca.mv[k]],a=p[id];
694
+ v+=positional[k][ca.mv[k]]+block[k][ca.mv[k]]*1.7;
695
+ if(u[id].flag>=0) {
696
+ v-=1.5*(.7*(route[k][a]-route[k][want])+.3*(bd[me][a]-bd[me][want]));
697
+ if(bd[me][want]==0&&bd[me][a]>0)v-=30;
698
+ } else if(assigned[k]>=0) {
699
+ auto& ms=missions[assigned[k]];int gp=goal[assigned[k]][k],offset=ms.type==1?1:ms.type==2?2:0;
700
+ auto gd=[&](int at){int d=D(at,gp);if(ms.type==0&&rolew[k]<.9&&d==0)d=1;return max(0,d-offset);};
701
+ v-=rolew[k]*(gd(a)-gd(want));
702
+ }
703
+ if(ca.ac[k]<0&&u[id].flag<0)for(auto& f:g.flags)if(f.x>=0&&cell(f.x,f.y)==a&&(f.return_at<0||f.return_at>g.turn)) {v+=PICK_BONUS*(1-death[k]);break;}
704
+ }
705
+ actual+=v/samples;
706
+ }
707
+ double value=(1-COLLISION_WEIGHT)*ca.value+COLLISION_WEIGHT*actual;
708
+ if(value>refinedBest){refinedBest=value;bm=ca.mv;ba=ca.ac;}
709
+ }
710
+ }
711
+ string out=to_string(g.turn);
712
+ for(int k=0;k<3;k++) {out+=' ';out+=mc[bm[k]];out+=' ';out+=ba[k]>=0?to_string(pred[ba[k]].id):"P";}
713
+ for(int id=0;id<(int)u.size();id++){oldp[id]=pos[id];oldhp[id]=u[id].hp;}
714
+ return out;
715
+ }
716
+ };
717
+ string decide(const Game& g) {static Player p;return p.decide(g);}
718
+
719
+ int main() {
720
+ ios::sync_with_stdio(false);
721
+ Game g;
722
+ while (read_turn(g)) {
723
+ cout << decide(g) << endl; // endl 会立即刷新输出
724
+ }
725
+ }