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.
- package/README.md +91 -13
- package/assets/commit0/instance.json +30 -0
- package/assets/commit0/workspace.zip +0 -0
- package/assets/featurebench/hidden/test_regression.py +690 -0
- package/assets/featurebench/instance.json +16 -0
- package/assets/featurebench/workspace.zip +0 -0
- package/assets/swe-bench-pro/hidden/test.patch +36 -0
- package/assets/swe-bench-pro/instance.json +10 -0
- package/assets/swe-bench-pro/workspace.zip +0 -0
- package/eval/README.md +18 -0
- package/eval/arena/arena/README.md +21 -0
- package/eval/arena/arena/bt.py +104 -0
- package/eval/arena/arena/clock.py +15 -0
- package/eval/arena/arena/core.py +265 -0
- package/eval/arena/arena/run.cmd +24 -0
- package/eval/arena/arena/run.sh +11 -0
- package/eval/arena/arena/schedule.py +79 -0
- package/eval/arena/arena/tournament.py +183 -0
- package/eval/arena/bomberman/bots/README.md +16 -0
- package/eval/arena/bomberman/bots/deepseek-v4.1-flash.cpp +447 -0
- package/eval/arena/bomberman/bots/doubao-seed-2.1.cpp +542 -0
- package/eval/arena/bomberman/bots/glm-5.3.cpp +406 -0
- package/eval/arena/bomberman/bots/gpt-6-astra.cpp +768 -0
- package/eval/arena/bomberman/bots/gpt-6-sol.cpp +444 -0
- package/eval/arena/bomberman/bots/kimi-k3.cpp +432 -0
- package/eval/arena/bomberman/bots/mimo-v2.6-pro.cpp +529 -0
- package/eval/arena/bomberman/bots/opus-5.5.cpp +548 -0
- package/eval/arena/bomberman/bots/qwen-3.8-max.cpp +836 -0
- package/eval/arena/bomberman/tournament/README.md +11 -0
- package/eval/arena/bomberman/tournament/bt.py +56 -0
- package/eval/arena/bomberman/tournament/evaluate.py +199 -0
- package/eval/arena/bomberman/tournament/run.py +79 -0
- package/eval/arena/bomberman/tournament/schedule-2to10.json.gz +0 -0
- package/eval/arena/bomberman/workspace/MANIFEST.json +13 -0
- package/eval/arena/bomberman/workspace/README.md +29 -0
- package/eval/arena/bomberman/workspace/RULES.md +100 -0
- package/eval/arena/bomberman/workspace/baseline.cpp +240 -0
- package/eval/arena/bomberman/workspace/clock.py +25 -0
- package/eval/arena/bomberman/workspace/engine/arena.py +198 -0
- package/eval/arena/bomberman/workspace/engine/build.py +35 -0
- package/eval/arena/bomberman/workspace/engine/engine.py +256 -0
- package/eval/arena/bomberman/workspace/engine/verify_replay.py +24 -0
- package/eval/arena/bomberman/workspace/run.cmd +28 -0
- package/eval/arena/bomberman/workspace/run.sh +16 -0
- package/eval/arena/bomberman/workspace/viewer/index.html +42 -0
- package/eval/arena/ctf/bots/README.md +18 -0
- package/eval/arena/ctf/bots/deepseek-v4.1-flash.cpp +601 -0
- package/eval/arena/ctf/bots/doubao-seed-2.1-turbo.cpp +320 -0
- package/eval/arena/ctf/bots/fable-5.1.cpp +634 -0
- package/eval/arena/ctf/bots/glm-5.3.cpp +689 -0
- package/eval/arena/ctf/bots/gpt-6-astra.cpp +657 -0
- package/eval/arena/ctf/bots/gpt-6.1-sol.cpp +725 -0
- package/eval/arena/ctf/bots/kimi-k3.cpp +667 -0
- package/eval/arena/ctf/bots/mimo-v2.6-pro.cpp +533 -0
- package/eval/arena/ctf/bots/opus-5.5.cpp +645 -0
- package/eval/arena/ctf/bots/qwen-3.8-max.cpp +726 -0
- package/eval/arena/ctf/bots/sonnet-5.5.cpp +569 -0
- package/eval/arena/ctf/tournament/README.md +15 -0
- package/eval/arena/ctf/tournament/formal-2to8.json +31 -0
- package/eval/arena/ctf/tournament/formal-9to15.json +31 -0
- package/eval/arena/ctf/workspace/README.md +41 -0
- package/eval/arena/ctf/workspace/RULES.md +119 -0
- package/eval/arena/ctf/workspace/arena.py +186 -0
- package/eval/arena/ctf/workspace/baseline.cpp +257 -0
- package/eval/arena/ctf/workspace/clock.py +15 -0
- package/eval/arena/ctf/workspace/core.py +265 -0
- package/eval/arena/ctf/workspace/engine.py +389 -0
- package/eval/arena/ctf/workspace/run.cmd +24 -0
- package/eval/arena/ctf/workspace/run.sh +11 -0
- package/eval/arena/ctf/workspace/viewer.html +71 -0
- package/eval/arena/land/bots/README.md +17 -0
- package/eval/arena/land/bots/deepseek-4.1f@workbuddy#1/bot.cpp +608 -0
- package/eval/arena/land/bots/glm-5.3@workbuddy#1/bot.cpp +521 -0
- package/eval/arena/land/bots/gpt-6-astra@codex#1/bot.cpp +373 -0
- package/eval/arena/land/bots/gpt-6-sol@codex#1/bot.cpp +341 -0
- package/eval/arena/land/bots/kimi-k3@workbuddy#1/bot.cpp +492 -0
- package/eval/arena/land/bots/mimo-2.6-pro@zcode#1/bot.cpp +652 -0
- package/eval/arena/land/bots/mystery-model@zcode#1/bot.cpp +466 -0
- package/eval/arena/land/bots/opus-5.5@claude-code#1/bot.cpp +630 -0
- package/eval/arena/land/bots/sonnet-5@claude-code#1/bot.cpp +619 -0
- package/eval/arena/land/tournament/make_replay_page.py +17 -0
- package/eval/arena/land/tournament/rate.py +290 -0
- package/eval/arena/land/tournament/round_robin.py +172 -0
- package/eval/arena/land/tournament/sparring.cpp +356 -0
- package/eval/arena/land/workspace/RULES.md +114 -0
- package/eval/arena/land/workspace/TASK.md +46 -0
- package/eval/arena/land/workspace/anchors/.build/greedy_f2e6d2dea5ca +0 -0
- package/eval/arena/land/workspace/anchors/greedy.cpp +194 -0
- package/eval/arena/land/workspace/anchors/random.cpp +80 -0
- package/eval/arena/land/workspace/clock.py +64 -0
- package/eval/arena/land/workspace/engine/build.py +33 -0
- package/eval/arena/land/workspace/engine/game.py +273 -0
- package/eval/arena/land/workspace/engine/referee.py +308 -0
- package/eval/arena/land/workspace/starter/.build/bot_be32b45b4699 +0 -0
- package/eval/arena/land/workspace/starter/bot.cpp +82 -0
- package/eval/arena/land/workspace/viewer/viewer.html +210 -0
- package/eval/arena/tank/bots/README.md +24 -0
- package/eval/arena/tank/bots/half1/deepseek-v4.1-flash.cpp +367 -0
- package/eval/arena/tank/bots/half1/doubao-seed-evolving.cpp +402 -0
- package/eval/arena/tank/bots/half1/gemini-4-argon.cpp +1132 -0
- package/eval/arena/tank/bots/half1/glm-5.3.cpp +551 -0
- package/eval/arena/tank/bots/half1/gpt-6-astra.cpp +233 -0
- package/eval/arena/tank/bots/half1/gpt-6.1-sol-ultrafast.cpp +350 -0
- package/eval/arena/tank/bots/half1/gpt-6.1-sol.cpp +78 -0
- package/eval/arena/tank/bots/half1/grok-4.7.cpp +1099 -0
- package/eval/arena/tank/bots/half1/haiku-5.5.cpp +210 -0
- package/eval/arena/tank/bots/half1/kimi-k3.cpp +353 -0
- package/eval/arena/tank/bots/half1/mimo-v2.6-pro.cpp +336 -0
- package/eval/arena/tank/bots/half1/muse-wonder-full.cpp +560 -0
- package/eval/arena/tank/bots/half1/opus-5.5.cpp +435 -0
- package/eval/arena/tank/bots/half1/qwen-3.8-max.cpp +537 -0
- package/eval/arena/tank/bots/half2/deepseek-v4.1-flash.cpp +425 -0
- package/eval/arena/tank/bots/half2/doubao-seed-evolving.cpp +308 -0
- package/eval/arena/tank/bots/half2/gemini-4-argon.cpp +1390 -0
- package/eval/arena/tank/bots/half2/glm-5.3.cpp +651 -0
- package/eval/arena/tank/bots/half2/gpt-6-astra.cpp +241 -0
- package/eval/arena/tank/bots/half2/gpt-6.1-sol-ultrafast.cpp +356 -0
- package/eval/arena/tank/bots/half2/gpt-6.1-sol.cpp +87 -0
- package/eval/arena/tank/bots/half2/grok-4.7.cpp +1205 -0
- package/eval/arena/tank/bots/half2/haiku-5.5.cpp +210 -0
- package/eval/arena/tank/bots/half2/kimi-k3.cpp +487 -0
- package/eval/arena/tank/bots/half2/mimo-v2.6-pro.cpp +336 -0
- package/eval/arena/tank/bots/half2/muse-wonder-full.cpp +560 -0
- package/eval/arena/tank/bots/half2/opus-5.5.cpp +476 -0
- package/eval/arena/tank/bots/half2/qwen-3.8-max.cpp +392 -0
- package/eval/arena/tank/tournament/README.md +24 -0
- package/eval/arena/tank/tournament/bt.py +218 -0
- package/eval/arena/tank/tournament/final.json +202 -0
- package/eval/arena/tank/tournament/halftime.json +146 -0
- package/eval/arena/tank/tournament/progress.json +911 -0
- package/eval/arena/tank/tournament/schedule.py +100 -0
- package/eval/arena/tank/tournament/sparring.cpp +928 -0
- package/eval/arena/tank/tournament/tournament.py +1426 -0
- package/eval/arena/tank/workspace/README.md +169 -0
- package/eval/arena/tank/workspace/RULES.md +443 -0
- package/eval/arena/tank/workspace/arena.py +862 -0
- package/eval/arena/tank/workspace/baseline.cpp +259 -0
- package/eval/arena/tank/workspace/clock.py +103 -0
- package/eval/arena/tank/workspace/core.py +712 -0
- package/eval/arena/tank/workspace/engine.py +573 -0
- package/eval/arena/tank/workspace/history/.lock +0 -0
- package/eval/arena/tank/workspace/history/20261017-193610-08715287f91f-bot.cpp +109 -0
- package/eval/arena/tank/workspace/history/20261017-193619-f00b2d5635fa-gpt-6-astra.cpp +241 -0
- package/eval/arena/tank/workspace/history/20261017-193643-63319e0a2b1a-gpt-6_1-sol-ultrafast.cpp +356 -0
- package/eval/arena/tank/workspace/history/20261017-193647-41c1341d0a8a-gemini-4-argon.cpp +1390 -0
- package/eval/arena/tank/workspace/history/20261017-193652-e34c0f45539a-gpt-6_1-sol.cpp +87 -0
- package/eval/arena/tank/workspace/history/20261017-193654-c026348ce96e-opus-5_5.cpp +476 -0
- package/eval/arena/tank/workspace/history/20261017-193655-4a21366e94d1-muse-wonder-full.cpp +560 -0
- package/eval/arena/tank/workspace/history/20261017-193657-dbc4e9969c52-mimo-v2_6-pro.cpp +336 -0
- package/eval/arena/tank/workspace/history/20261017-193703-723cd036eb31-grok-4_7.cpp +1205 -0
- package/eval/arena/tank/workspace/history/20261017-193707-1ebbb227be68-deepseek-v4_1-flash.cpp +425 -0
- package/eval/arena/tank/workspace/history/20261017-193709-aeb0e7202ad5-doubao-seed-evolving.cpp +308 -0
- package/eval/arena/tank/workspace/history/20261017-193710-b21ebeb9bc76-kimi-k3.cpp +487 -0
- package/eval/arena/tank/workspace/history/20261017-193712-54cd86531905-haiku-5_5.cpp +210 -0
- package/eval/arena/tank/workspace/history/20261017-193714-efdb8e35c0bf-qwen-3_8-max.cpp +392 -0
- package/eval/arena/tank/workspace/history/20261017-193715-681423c23fdb-glm-5_3.cpp +651 -0
- package/eval/arena/tank/workspace/history/20261017-193717-1a8b3c75181d-sparring.cpp +928 -0
- package/eval/arena/tank/workspace/history/20261017-193720-1e0803a541e8-baseline.cpp +259 -0
- package/eval/arena/tank/workspace/history/log.jsonl +103 -0
- package/eval/arena/tank/workspace/judge/cycles.hpp +53 -0
- package/eval/arena/tank/workspace/judge/fast.cpp +337 -0
- package/eval/arena/tank/workspace/judge/referee.cpp +125 -0
- package/eval/arena/tank/workspace/judge/speed.cpp +99 -0
- package/eval/arena/tank/workspace/run.cmd +31 -0
- package/eval/arena/tank/workspace/run.sh +23 -0
- package/eval/arena/tank/workspace/tank.hpp +1762 -0
- package/eval/arena/tank/workspace/tank_main.cpp +215 -0
- package/eval/arena/tank/workspace/viewer.html +1150 -0
- package/eval/arena/warehouse/workspace/SPEC.md +130 -0
- package/eval/arena/warehouse/workspace/TASK.md +71 -0
- package/eval/arena/warehouse/workspace/baseline/common.h +88 -0
- package/eval/arena/warehouse/workspace/baseline/main.cpp +27 -0
- package/eval/arena/warehouse/workspace/baseline/old_stuff.cpp +87 -0
- package/eval/arena/warehouse/workspace/baseline/sim.cpp +427 -0
- package/eval/arena/warehouse/workspace/baseline/util.cpp +220 -0
- package/eval/arena/warehouse/workspace/clock.py +42 -0
- package/eval/arena/warehouse/workspace/src/common.h +88 -0
- package/eval/arena/warehouse/workspace/src/main.cpp +27 -0
- package/eval/arena/warehouse/workspace/src/old_stuff.cpp +87 -0
- package/eval/arena/warehouse/workspace/src/sim.cpp +427 -0
- package/eval/arena/warehouse/workspace/src/util.cpp +220 -0
- package/eval/arena/warehouse/workspace/tools/bench.py +119 -0
- package/eval/arena/warehouse/workspace/tools/check_input.py +161 -0
- package/eval/arena/warehouse/workspace/tools/gen.py +132 -0
- package/eval/arena/warehouse/workspace/tools/measure.py +107 -0
- package/eval/arena/warehouse/workspace/workloads/public/pub_crowded.in +1420 -0
- package/eval/arena/warehouse/workspace/workloads/public/pub_crowded.out +9162 -0
- package/eval/arena/warehouse/workspace/workloads/public/pub_dynamic.in +1465 -0
- package/eval/arena/warehouse/workspace/workloads/public/pub_dynamic.out +3439 -0
- package/eval/arena/warehouse/workspace/workloads/public/pub_flood.in +2757 -0
- package/eval/arena/warehouse/workspace/workloads/public/pub_flood.out +3126 -0
- package/eval/arena/warehouse/workspace/workloads/public/pub_small.in +731 -0
- package/eval/arena/warehouse/workspace/workloads/public/pub_small.out +2578 -0
- package/eval/arena/warehouse/workspace/workloads/public/pub_wide.in +528 -0
- package/eval/arena/warehouse/workspace/workloads/public/pub_wide.out +2026 -0
- package/eval/bomberman.py +20 -0
- package/eval/commit0.py +21 -0
- package/eval/common.py +61 -0
- package/eval/ctf.py +20 -0
- package/eval/featurebench.py +25 -0
- package/eval/land.py +20 -0
- package/eval/legacy/bomberman-prices.json +4 -0
- package/eval/legacy/bomberman.py +161 -0
- package/eval/legacy/commit0.py +91 -0
- package/eval/legacy/ctf-prices.json +4 -0
- package/eval/legacy/ctf.py +178 -0
- package/eval/legacy/featurebench.py +103 -0
- package/eval/legacy/land-prices.json +4 -0
- package/eval/legacy/land.py +177 -0
- package/eval/legacy/swe_bench_pro.py +116 -0
- package/eval/legacy/tank-prices.json +3 -0
- package/eval/legacy/tank.py +408 -0
- package/eval/legacy/warehouse-prices.json +4 -0
- package/eval/legacy/warehouse.py +365 -0
- package/eval/swe-bench-pro.py +25 -0
- package/eval/tank.py +20 -0
- package/eval/warehouse.py +20 -0
- package/lib/client/index.js +376 -63
- package/lib/client/index.js.map +1 -1
- package/lib/index.js +684 -27
- package/package.json +2 -1
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
// 圈地对战 bot
|
|
2
|
+
// 策略核心:
|
|
3
|
+
// 1) 圈地判定是「从边界泛洪、够不到的格子全归我」,所以画一个尽量大的闭合回路就能一次吞掉整块区域。
|
|
4
|
+
// 本 bot 每次都规划一个「矩形回路」:矩形必须严格包住自己的领地 bbox,
|
|
5
|
+
// 从 bbox 的某个角出发绕矩形一周再回到该角 → 回路内部(= 整个矩形)全部变成我的领地。
|
|
6
|
+
// 领地因此像滚雪球一样扩张,几步之内吃掉大半个棋盘。
|
|
7
|
+
// 2) 分数只看名次,所以优先选「收益/步数」最大且能在剩余回合内跑完的矩形。
|
|
8
|
+
// 3) 对手可能反过来用一个大圈把我包住(领地会被抢走,只剩保护区),
|
|
9
|
+
// 所以每回合检测「某个对手这回合圈地是否会吞掉我的领地」,一旦成立立刻冲过去切断它的轨迹。
|
|
10
|
+
// 4) 顺手切对手:轨迹是它这轮全部积累,踩一脚就让它白跑,所以近身有机会必切。
|
|
11
|
+
// 5) 画圈期间被切断 = 阵亡回到出生点(领地保留),损失只是时间;计划每回合校验,非法即重排。
|
|
12
|
+
#include <bits/stdc++.h>
|
|
13
|
+
using namespace std;
|
|
14
|
+
|
|
15
|
+
static int W, H, MAXT, N, ME, MOVE_MS, INIT_MS;
|
|
16
|
+
static const int DX[4] = {0, 0, -1, 1};
|
|
17
|
+
static const int DY[4] = {-1, 1, 0, 0};
|
|
18
|
+
static const char DCH[4] = {'U', 'D', 'L', 'R'};
|
|
19
|
+
static int MEc;
|
|
20
|
+
|
|
21
|
+
static vector<signed char> own, trl;
|
|
22
|
+
static int spx[8], spy[8];
|
|
23
|
+
static int pX[8], pY[8], pD[8], pTL[8], pA[8], pDe[8];
|
|
24
|
+
static int TURN;
|
|
25
|
+
|
|
26
|
+
static int bfsD[4096], bfsF[4096], qb[4096];
|
|
27
|
+
static int lastDist;
|
|
28
|
+
static bool bfsOwnOnly = false; // 只走自己的领地(画圈前的回家路径)
|
|
29
|
+
static int edist[4096]; // 到最近对手头部的纯网格距离
|
|
30
|
+
static vector<signed char> seen;
|
|
31
|
+
|
|
32
|
+
static vector<int> plan; // 剩余执行的方向序列
|
|
33
|
+
static bool planActive = false; // 计划是否已开始执行
|
|
34
|
+
static bool wasOutside = false; // 本轮计划中是否已经离开过领地
|
|
35
|
+
|
|
36
|
+
static inline bool inb(int x, int y) { return x >= 0 && x < W && y >= 0 && y < H; }
|
|
37
|
+
static inline int dOf(char c) { return c == 'U' ? 0 : c == 'D' ? 1 : c == 'L' ? 2 : 3; }
|
|
38
|
+
|
|
39
|
+
// ---------------------------------------------------------------- BFS
|
|
40
|
+
// 从头部出发,禁止踩自己的轨迹,禁止第一步掉头。
|
|
41
|
+
// mode 0: 全程;mode 1: 找最近的对手轨迹格;mode 2: 找最近的自有领地格
|
|
42
|
+
static int bfsRun(int mode, int targetPlayer) {
|
|
43
|
+
lastDist = -1;
|
|
44
|
+
int n = W * H;
|
|
45
|
+
int s = pY[ME] * W + pX[ME];
|
|
46
|
+
for (int k = 0; k < n; k++) bfsD[k] = -1;
|
|
47
|
+
bfsD[s] = 0;
|
|
48
|
+
bfsF[s] = -1;
|
|
49
|
+
int qh = 0, qt = 0;
|
|
50
|
+
qb[qt++] = s;
|
|
51
|
+
int back = pD[ME] ^ 1;
|
|
52
|
+
int found = -1;
|
|
53
|
+
while (qh < qt) {
|
|
54
|
+
int k = qb[qh++];
|
|
55
|
+
if (mode == 1 && trl[k] >= 0 && trl[k] != MEc) { found = k; break; }
|
|
56
|
+
if (mode == 2 && own[k] == MEc) { found = k; break; }
|
|
57
|
+
int x = k % W, y = k / W;
|
|
58
|
+
for (int d = 0; d < 4; d++) {
|
|
59
|
+
if (k == s && d == back) continue;
|
|
60
|
+
int nx = x + DX[d], ny = y + DY[d];
|
|
61
|
+
if (!inb(nx, ny)) continue;
|
|
62
|
+
int nk = ny * W + nx;
|
|
63
|
+
if (bfsD[nk] != -1) continue;
|
|
64
|
+
if (trl[nk] == MEc) continue; // 踩自己的轨迹 = 自杀
|
|
65
|
+
if (bfsOwnOnly && own[nk] != MEc) continue;
|
|
66
|
+
bfsD[nk] = bfsD[k] + 1;
|
|
67
|
+
bfsF[nk] = (k == s ? d : bfsF[k]);
|
|
68
|
+
qb[qt++] = nk;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (mode == 0) return 0;
|
|
72
|
+
if (found < 0) return -1;
|
|
73
|
+
lastDist = bfsD[found];
|
|
74
|
+
return bfsF[found];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// -------------------------------------------------- 对手是否要把我围死
|
|
78
|
+
// 用对手的领地+轨迹当墙,从边界泛洪;泛洪不到的我的领地格 = 它这一圈会吞掉的地方。
|
|
79
|
+
static bool enemyEnclosesMe(int j) {
|
|
80
|
+
int n = W * H;
|
|
81
|
+
int ch = j;
|
|
82
|
+
for (int k = 0; k < n; k++)
|
|
83
|
+
seen[k] = (own[k] == ch || trl[k] == ch) ? 1 : 0;
|
|
84
|
+
int qh = 0, qt = 0;
|
|
85
|
+
for (int x = 0; x < W; x++) {
|
|
86
|
+
int a = x, b = (H - 1) * W + x;
|
|
87
|
+
if (!seen[a]) { seen[a] = 1; qb[qt++] = a; }
|
|
88
|
+
if (!seen[b]) { seen[b] = 1; qb[qt++] = b; }
|
|
89
|
+
}
|
|
90
|
+
for (int y = 0; y < H; y++) {
|
|
91
|
+
int a = y * W, b = y * W + W - 1;
|
|
92
|
+
if (!seen[a]) { seen[a] = 1; qb[qt++] = a; }
|
|
93
|
+
if (!seen[b]) { seen[b] = 1; qb[qt++] = b; }
|
|
94
|
+
}
|
|
95
|
+
while (qh < qt) {
|
|
96
|
+
int k = qb[qh++];
|
|
97
|
+
int x = k % W, y = k / W;
|
|
98
|
+
for (int d = 0; d < 4; d++) {
|
|
99
|
+
int nx = x + DX[d], ny = y + DY[d];
|
|
100
|
+
if (!inb(nx, ny)) continue;
|
|
101
|
+
int nk = ny * W + nx;
|
|
102
|
+
if (seen[nk]) continue;
|
|
103
|
+
seen[nk] = 1;
|
|
104
|
+
qb[qt++] = nk;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
int hx = pX[ME], hy = pY[ME];
|
|
108
|
+
if (!seen[hy * W + hx]) return true;
|
|
109
|
+
for (int k = 0; k < n; k++)
|
|
110
|
+
if (own[k] == MEc && !seen[k]) return true;
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ---------------------------------------------------------------- 规划
|
|
115
|
+
// 一个「圈」= 从自己领地上某个角 s 出发,绕一个矩形一整圈,再踩回 s。
|
|
116
|
+
// 矩形的一条近边必须紧贴 s(否则回路接不回领地),远边任意(只要整条边都不是自己的格子)。
|
|
117
|
+
// 绕完一圈后回路内部(含自己领地)全部被围住 = 一次吃掉整块区域。
|
|
118
|
+
static int pref[64][64]; // 自己领地的前缀和,用来 O(1) 算矩形里有多少自己的格子
|
|
119
|
+
|
|
120
|
+
static void buildPlan() {
|
|
121
|
+
plan.clear();
|
|
122
|
+
planActive = false;
|
|
123
|
+
wasOutside = false;
|
|
124
|
+
|
|
125
|
+
int x0 = W, y0 = H, x1 = -1, y1 = -1;
|
|
126
|
+
for (int y = 0; y < H; y++)
|
|
127
|
+
for (int x = 0; x < W; x++)
|
|
128
|
+
if (own[y * W + x] == MEc) {
|
|
129
|
+
if (x < x0) x0 = x;
|
|
130
|
+
if (x > x1) x1 = x;
|
|
131
|
+
if (y < y0) y0 = y;
|
|
132
|
+
if (y > y1) y1 = y;
|
|
133
|
+
}
|
|
134
|
+
if (x1 < 0) return;
|
|
135
|
+
for (int y = 0; y < H; y++)
|
|
136
|
+
for (int x = 0; x < W; x++)
|
|
137
|
+
pref[y + 1][x + 1] = pref[y][x + 1] + pref[y + 1][x] - pref[y][x] + (own[y * W + x] == MEc);
|
|
138
|
+
|
|
139
|
+
int rem = MAXT - TURN;
|
|
140
|
+
if (rem < 5) return;
|
|
141
|
+
// 手上有轨迹(人在外面)时不画圈:先回家。回路要靠这条路径接回领地,
|
|
142
|
+
// 路径和回路一旦撞上就是自杀,限制成只走自己的领地就永远不会撞。
|
|
143
|
+
if (pTL[ME] > 0 || own[pY[ME] * W + pX[ME]] != MEc) return;
|
|
144
|
+
|
|
145
|
+
bfsOwnOnly = true;
|
|
146
|
+
bfsRun(0, 0);
|
|
147
|
+
bfsOwnOnly = false;
|
|
148
|
+
int head = pY[ME] * W + pX[ME];
|
|
149
|
+
|
|
150
|
+
// 候选起点:自己领地边界上的「凸角」——某一侧相邻的两个格子都空着。
|
|
151
|
+
// 先放 bbox 的四个角(向外扩收益最大),再从整条边界上均匀取样,
|
|
152
|
+
// 否则只会一路往上顶, territory 长到顶以后就没圈可画了。
|
|
153
|
+
int cand[4][12], nc[4] = {0, 0, 0, 0};
|
|
154
|
+
for (int o = 0; o < 4; o++) {
|
|
155
|
+
int ex = o & 1, ey = o >> 1;
|
|
156
|
+
int k = (o == 0 ? y0 * W + x0 : o == 1 ? y0 * W + x1 : o == 2 ? y1 * W + x0 : y1 * W + x1);
|
|
157
|
+
int x = k % W, y = k / W;
|
|
158
|
+
int ax = ex ? x + 1 : x - 1, ay = ey ? y + 1 : y - 1;
|
|
159
|
+
if (inb(ax, ay) && own[ay * W + ax] != MEc) cand[o][nc[o]++] = k;
|
|
160
|
+
}
|
|
161
|
+
for (int o = 0; o < 4; o++) {
|
|
162
|
+
int ex = o & 1, ey = o >> 1;
|
|
163
|
+
int all[400], na = 0;
|
|
164
|
+
for (int y = 0; y < H; y++)
|
|
165
|
+
for (int x = 0; x < W; x++) {
|
|
166
|
+
if (own[y * W + x] != MEc) continue;
|
|
167
|
+
int ax = ex ? x + 1 : x - 1, ay = ey ? y + 1 : y - 1;
|
|
168
|
+
if (!inb(ax, ay) || own[ay * W + ax] == MEc) continue;
|
|
169
|
+
if (na < 400) all[na++] = y * W + x;
|
|
170
|
+
}
|
|
171
|
+
int room = 12 - nc[o];
|
|
172
|
+
if (room <= 0) continue;
|
|
173
|
+
if (na <= room) {
|
|
174
|
+
for (int q = 0; q < na; q++) cand[o][nc[o]++] = all[q];
|
|
175
|
+
} else {
|
|
176
|
+
for (int q = 0; q < room; q++)
|
|
177
|
+
cand[o][nc[o]++] = all[(int)((long)na * q / room)];
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// 开局领地小,一个大圈就能吃掉半个棋盘,这时值得押上全部剩余回合;
|
|
182
|
+
// 领地大了以后再画超长圈只是白送人头,所以收紧。
|
|
183
|
+
const int CAP = (N == 2) ? 140 : 60;
|
|
184
|
+
const double ALPHA = 1.0;
|
|
185
|
+
double bestScore = -1e18;
|
|
186
|
+
int bS = -1, bEx = 0, bEy = 0, bBw = 0, bBh = 0, bStop = 0;
|
|
187
|
+
const int SAMP = 9;
|
|
188
|
+
|
|
189
|
+
for (int o = 0; o < 4; o++) {
|
|
190
|
+
int ex = o & 1, ey = o >> 1;
|
|
191
|
+
for (int ci = 0; ci < nc[o]; ci++) {
|
|
192
|
+
int sIdx = cand[o][ci], sx = sIdx % W, sy = sIdx / W;
|
|
193
|
+
if (bfsD[sIdx] < 0) continue;
|
|
194
|
+
int approach = bfsD[sIdx];
|
|
195
|
+
int xlo = ex ? sx + 1 : sx - 1, ylo = ey ? sy + 1 : sy - 1;
|
|
196
|
+
if (!inb(xlo, sy) || !inb(sx, ylo)) continue;
|
|
197
|
+
int fx0 = ex ? 0 : sx, fx1 = ex ? sx - 1 : W - 1;
|
|
198
|
+
int fy0 = ey ? 0 : sy, fy1 = ey ? sy - 1 : H - 1;
|
|
199
|
+
if (fx0 > fx1 || fy0 > fy1) continue;
|
|
200
|
+
int dIn = ex ? 3 : 2, dA1 = ey ? 0 : 1, dH2 = ex ? 2 : 3, dUp = ey ? 1 : 0, dH5 = ex ? 3 : 2;
|
|
201
|
+
for (int a = 0; a < SAMP; a++) {
|
|
202
|
+
int farX = fx0 + (int)((long)(fx1 - fx0) * a / (SAMP - 1));
|
|
203
|
+
int bw = abs(farX - sx);
|
|
204
|
+
for (int b = 0; b < SAMP; b++) {
|
|
205
|
+
int farY = fy0 + (int)((long)(fy1 - fy0) * b / (SAMP - 1));
|
|
206
|
+
int bh = abs(farY - sy);
|
|
207
|
+
int P = 2 * bw + 2 * bh + 4;
|
|
208
|
+
int rx0 = min(xlo, farX), rx1 = max(xlo, farX);
|
|
209
|
+
int ry0 = min(ylo, farY), ry1 = max(ylo, farY);
|
|
210
|
+
int mine = pref[ry1 + 1][rx1 + 1] - pref[ry0][rx1 + 1] - pref[ry1 + 1][rx0] + pref[ry0][rx0];
|
|
211
|
+
int pc = 0;
|
|
212
|
+
for (int j = 0; j < N; j++) {
|
|
213
|
+
if (j == ME) continue;
|
|
214
|
+
int ox = min(rx1, spx[j] + 1) - max(rx0, spx[j] - 1) + 1;
|
|
215
|
+
int oy = min(ry1, spy[j] + 1) - max(ry0, spy[j] - 1) + 1;
|
|
216
|
+
if (ox > 0 && oy > 0) pc += ox * oy;
|
|
217
|
+
}
|
|
218
|
+
int gain = (rx1 - rx0 + 1) * (ry1 - ry0 + 1) - mine - pc;
|
|
219
|
+
if (gain <= 0) continue;
|
|
220
|
+
// 走一遍回路。撞到自己领地 = 这一圈到此为止(踩进去就结算,顺带把这条带子圈下来),
|
|
221
|
+
// 撞到自己的轨迹/回家路径 = 同格自杀,这个候选作废。
|
|
222
|
+
int risk = 0, kill = 0, stopT = 0, t = 0, x = sx, y = sy;
|
|
223
|
+
auto stepTo = [&](int d) {
|
|
224
|
+
x += DX[d]; y += DY[d]; t++;
|
|
225
|
+
int k = y * W + x;
|
|
226
|
+
if (own[k] == MEc) { stopT = t; return; }
|
|
227
|
+
// 会被切断 = 白跑 t 回合,代价按已投入的工作量算
|
|
228
|
+
if (edist[k] < t) risk += t;
|
|
229
|
+
if (trl[k] >= 0 && pTL[trl[k]] >= 3) kill += 2 * pTL[trl[k]] + 20;
|
|
230
|
+
};
|
|
231
|
+
stepTo(dIn);
|
|
232
|
+
for (int i = 0; i < bh && !stopT; i++) stepTo(dA1);
|
|
233
|
+
for (int i = 0; i < bw + 1 && !stopT; i++) stepTo(dH2);
|
|
234
|
+
for (int i = 0; i < bh + 1 && !stopT; i++) stepTo(dUp);
|
|
235
|
+
for (int i = 0; i < bw && !stopT; i++) stepTo(dH5);
|
|
236
|
+
int planLen = stopT ? stopT : P;
|
|
237
|
+
int total = approach + planLen;
|
|
238
|
+
if (total + 2 > rem) continue;
|
|
239
|
+
if (total > CAP) continue;
|
|
240
|
+
// 半途截断的圈只能吃到已经围住的那条带子,收益按比例打折
|
|
241
|
+
int gain2 = stopT ? (int)(gain * pow((double)stopT / (P + 1), ALPHA)) : gain;
|
|
242
|
+
if (gain2 <= 0) continue;
|
|
243
|
+
const double PWR = 0.85, KLP = 0.35, QRSK = 0.02;
|
|
244
|
+
double score = (double)gain2 / pow((double)(total + 6), PWR) - QRSK * risk + KLP * kill;
|
|
245
|
+
if (score > bestScore) {
|
|
246
|
+
bestScore = score;
|
|
247
|
+
bS = sIdx; bEx = ex; bEy = ey; bBw = bw; bBh = bh; bStop = stopT;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
if (bS < 0) return;
|
|
254
|
+
|
|
255
|
+
// 拼出:回家路径 + 回路
|
|
256
|
+
{
|
|
257
|
+
vector<int> rev;
|
|
258
|
+
int k = bS;
|
|
259
|
+
while (k != head) {
|
|
260
|
+
int d = bfsD[k], x = k % W, y = k / W, pk = -1;
|
|
261
|
+
for (int dd = 0; dd < 4; dd++) {
|
|
262
|
+
int nx = x + DX[dd], ny = y + DY[dd];
|
|
263
|
+
if (inb(nx, ny) && bfsD[ny * W + nx] == d - 1) { pk = ny * W + nx; break; }
|
|
264
|
+
}
|
|
265
|
+
if (pk < 0) { plan.clear(); return; }
|
|
266
|
+
rev.push_back(pk);
|
|
267
|
+
k = pk;
|
|
268
|
+
}
|
|
269
|
+
int x = pX[ME], y = pY[ME];
|
|
270
|
+
for (int i = (int)rev.size() - 1; i >= 0; i--) {
|
|
271
|
+
int tx = rev[i] % W, ty = rev[i] / W;
|
|
272
|
+
for (int dd = 0; dd < 4; dd++)
|
|
273
|
+
if (x + DX[dd] == tx && y + DY[dd] == ty) { plan.push_back(dd); break; }
|
|
274
|
+
x = tx; y = ty;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
int dIn = bEx ? 3 : 2, dA1 = bEy ? 0 : 1, dH2 = bEx ? 2 : 3, dUp = bEy ? 1 : 0, dH5 = bEx ? 3 : 2;
|
|
278
|
+
vector<int> ring;
|
|
279
|
+
ring.push_back(dIn);
|
|
280
|
+
for (int i = 0; i < bBh; i++) ring.push_back(dA1);
|
|
281
|
+
for (int i = 0; i < bBw + 1; i++) ring.push_back(dH2);
|
|
282
|
+
for (int i = 0; i < bBh + 1; i++) ring.push_back(dUp);
|
|
283
|
+
for (int i = 0; i < bBw; i++) ring.push_back(dH5);
|
|
284
|
+
ring.push_back(dA1);
|
|
285
|
+
int nRing = bStop ? bStop : (int)ring.size();
|
|
286
|
+
for (int i = 0; i < nRing && i < (int)ring.size(); i++) plan.push_back(ring[i]);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// ---------------------------------------------------------------- 决策
|
|
290
|
+
static int decide() {
|
|
291
|
+
int hx = pX[ME], hy = pY[ME], hd = pD[ME];
|
|
292
|
+
int back = hd ^ 1;
|
|
293
|
+
|
|
294
|
+
// 合法:不能掉头、不能出界、不能踩自己的轨迹
|
|
295
|
+
auto legal = [&](int d, int& nx, int& ny) {
|
|
296
|
+
if (d == back) return false;
|
|
297
|
+
nx = hx + DX[d]; ny = hy + DY[d];
|
|
298
|
+
if (!inb(nx, ny)) return false;
|
|
299
|
+
if (trl[ny * W + nx] == MEc) return false;
|
|
300
|
+
return true;
|
|
301
|
+
};
|
|
302
|
+
// 走上去会和一个贴脸的首领换位 = 同归于尽
|
|
303
|
+
auto swapDie = [&](int nx, int ny) {
|
|
304
|
+
for (int j = 0; j < N; j++) {
|
|
305
|
+
if (j == ME) continue;
|
|
306
|
+
if (pX[j] == nx && pY[j] == ny && abs(pX[j] - hx) + abs(pY[j] - hy) == 1) return true;
|
|
307
|
+
}
|
|
308
|
+
return false;
|
|
309
|
+
};
|
|
310
|
+
auto tryStep = [&](int d) {
|
|
311
|
+
int nx, ny;
|
|
312
|
+
return legal(d, nx, ny) && !swapDie(nx, ny);
|
|
313
|
+
};
|
|
314
|
+
int nx, ny;
|
|
315
|
+
|
|
316
|
+
// 提前圈地(半路踩回自己领地):原计划作废
|
|
317
|
+
if (planActive && wasOutside && pTL[ME] == 0 && own[hy * W + hx] == MEc) {
|
|
318
|
+
plan.clear();
|
|
319
|
+
planActive = false;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// 紧急:某个对手这一圈下来会把我整块吞掉,只能去踩断它的轨迹
|
|
323
|
+
for (int j = 0; j < N; j++) {
|
|
324
|
+
if (j == ME || pTL[j] == 0) continue;
|
|
325
|
+
if (!enemyEnclosesMe(j)) continue;
|
|
326
|
+
int d = bfsRun(1, j);
|
|
327
|
+
if (d >= 0 && tryStep(d)) {
|
|
328
|
+
plan.clear();
|
|
329
|
+
planActive = false;
|
|
330
|
+
return d;
|
|
331
|
+
}
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// 切人:对手轨迹就是它这一轮全部积累,踩一脚等于让它白跑几十回合。
|
|
336
|
+
// 手上有东西(正在画圈)时只有贴脸才切;空手时可以为了一口大鱼多跑几步。
|
|
337
|
+
if (plan.size() <= 3 || pTL[ME] <= 1) {
|
|
338
|
+
bool idle = (plan.empty() || plan.size() <= 3) && pTL[ME] <= 1;
|
|
339
|
+
int maxD = idle ? 6 : 3, minTL = idle ? 4 : 6;
|
|
340
|
+
for (int j = 0; j < N; j++) {
|
|
341
|
+
if (j == ME || pTL[j] < minTL) continue;
|
|
342
|
+
int d = bfsRun(1, j);
|
|
343
|
+
if (d < 0 || lastDist > maxD) continue;
|
|
344
|
+
if (tryStep(d)) { plan.clear(); planActive = false; return d; }
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (plan.empty()) {
|
|
349
|
+
buildPlan();
|
|
350
|
+
planActive = !plan.empty();
|
|
351
|
+
wasOutside = false;
|
|
352
|
+
}
|
|
353
|
+
if (!plan.empty()) {
|
|
354
|
+
int d = plan[0];
|
|
355
|
+
if (tryStep(d)) {
|
|
356
|
+
plan.erase(plan.begin());
|
|
357
|
+
int tx = hx + DX[d], ty = hy + DY[d];
|
|
358
|
+
if (own[ty * W + tx] != MEc) wasOutside = true;
|
|
359
|
+
if (plan.empty()) planActive = false;
|
|
360
|
+
return d;
|
|
361
|
+
}
|
|
362
|
+
plan.clear(); // 计划被堵死,重排
|
|
363
|
+
planActive = false;
|
|
364
|
+
buildPlan();
|
|
365
|
+
planActive = !plan.empty();
|
|
366
|
+
wasOutside = false;
|
|
367
|
+
if (!plan.empty()) {
|
|
368
|
+
int d = plan[0];
|
|
369
|
+
if (tryStep(d)) {
|
|
370
|
+
plan.erase(plan.begin());
|
|
371
|
+
int tx = hx + DX[d], ty = hy + DY[d];
|
|
372
|
+
if (own[ty * W + tx] != MEc) wasOutside = true;
|
|
373
|
+
if (plan.empty()) planActive = false;
|
|
374
|
+
return d;
|
|
375
|
+
}
|
|
376
|
+
plan.clear();
|
|
377
|
+
planActive = false;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// 兜底:回家;在领地里就沿着领地晃(领地内移动不掉血)
|
|
382
|
+
{
|
|
383
|
+
int d = bfsRun(2, 0);
|
|
384
|
+
if (d >= 0 && tryStep(d)) return d;
|
|
385
|
+
}
|
|
386
|
+
if (own[hy * W + hx] == MEc) {
|
|
387
|
+
for (int d = 0; d < 4; d++)
|
|
388
|
+
if (tryStep(d) && own[(hy + DY[d]) * W + hx + DX[d]] == MEc) return d;
|
|
389
|
+
}
|
|
390
|
+
for (int d = 0; d < 4; d++) if (tryStep(d)) return d;
|
|
391
|
+
return hd;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
static bool readState() {
|
|
395
|
+
string tok;
|
|
396
|
+
if (!(cin >> tok)) return false;
|
|
397
|
+
if (!(cin >> TURN)) return false;
|
|
398
|
+
for (int i = 0; i < N; i++) {
|
|
399
|
+
int id, x, y, tl, ar, de; char dc;
|
|
400
|
+
cin >> tok >> id >> x >> y >> dc >> tl >> ar >> de;
|
|
401
|
+
pX[id] = x; pY[id] = y; pD[id] = dOf(dc); pTL[id] = tl; pA[id] = ar; pDe[id] = de;
|
|
402
|
+
}
|
|
403
|
+
cin >> tok; // OWNER
|
|
404
|
+
{
|
|
405
|
+
string row;
|
|
406
|
+
for (int y = 0; y < H; y++) {
|
|
407
|
+
cin >> row;
|
|
408
|
+
signed char* o = own.data() + y * W;
|
|
409
|
+
for (int x = 0; x < W; x++) o[x] = (row[x] == '.') ? -1 : (signed char)(row[x] - '0');
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
cin >> tok; // TRAIL
|
|
413
|
+
{
|
|
414
|
+
string row;
|
|
415
|
+
for (int y = 0; y < H; y++) {
|
|
416
|
+
cin >> row;
|
|
417
|
+
signed char* o = trl.data() + y * W;
|
|
418
|
+
for (int x = 0; x < W; x++) o[x] = (row[x] == '.') ? -1 : (signed char)(row[x] - '0');
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
cin >> tok; // END
|
|
422
|
+
return true;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
int main() {
|
|
426
|
+
ios::sync_with_stdio(false);
|
|
427
|
+
cin.tie(nullptr);
|
|
428
|
+
string tok;
|
|
429
|
+
if (!(cin >> tok)) return 0; // INIT
|
|
430
|
+
if (!(cin >> W >> H >> MAXT >> N >> ME >> MOVE_MS >> INIT_MS)) return 0;
|
|
431
|
+
MEc = ME;
|
|
432
|
+
for (int i = 0; i < N; i++) {
|
|
433
|
+
int id, x, y;
|
|
434
|
+
cin >> tok >> id >> x >> y;
|
|
435
|
+
spx[id] = x; spy[id] = y;
|
|
436
|
+
}
|
|
437
|
+
own.assign(W * H, -1);
|
|
438
|
+
trl.assign(W * H, -1);
|
|
439
|
+
seen.assign(W * H, 0);
|
|
440
|
+
|
|
441
|
+
while (readState()) {
|
|
442
|
+
// 到最近对手头部的距离(纯网格 BFS,取最小)
|
|
443
|
+
for (int k = 0; k < W * H; k++) edist[k] = 1 << 20;
|
|
444
|
+
for (int j = 0; j < N; j++) {
|
|
445
|
+
if (j == ME) continue;
|
|
446
|
+
int qh = 0, qt = 0;
|
|
447
|
+
int s = pY[j] * W + pX[j];
|
|
448
|
+
if (edist[s] != 0) { edist[s] = 0; qb[qt++] = s; }
|
|
449
|
+
while (qh < qt) {
|
|
450
|
+
int k = qb[qh++];
|
|
451
|
+
int x = k % W, y = k / W;
|
|
452
|
+
for (int dd = 0; dd < 4; dd++) {
|
|
453
|
+
int ax = x + DX[dd], ay = y + DY[dd];
|
|
454
|
+
if (!inb(ax, ay)) continue;
|
|
455
|
+
int nk = ay * W + ax;
|
|
456
|
+
if (edist[nk] != 0) continue;
|
|
457
|
+
edist[nk] = edist[k] + 1;
|
|
458
|
+
qb[qt++] = nk;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
int d = decide();
|
|
463
|
+
cout << TURN << ' ' << DCH[d] << endl;
|
|
464
|
+
}
|
|
465
|
+
return 0;
|
|
466
|
+
}
|