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,569 @@
|
|
|
1
|
+
// 夺旗 bot v1:全图 BFS + 任务分配(送旗/截击/取旗/护送/待命)+ 3 角色联合动作评估(威胁、命中、集火、击杀)
|
|
2
|
+
#include <bits/stdc++.h>
|
|
3
|
+
using namespace std;
|
|
4
|
+
|
|
5
|
+
struct Unit { int id, team, x, y, hp, flag, respawn_at; }; // 阵亡时 x = y = -1
|
|
6
|
+
struct Flag { int id; string status; int x, y, holder, return_at; };
|
|
7
|
+
struct Event { string type; vector<int> args; };
|
|
8
|
+
|
|
9
|
+
struct Game {
|
|
10
|
+
int teams = 0, me = 0, size = 0, turns = 0, hp = 0, damage = 0, respawn = 0, flag_return = 0, flag_cooldown = 0;
|
|
11
|
+
vector<string> map;
|
|
12
|
+
vector<pair<int, int>> bases;
|
|
13
|
+
vector<pair<int, int>> spots;
|
|
14
|
+
int turn = 0;
|
|
15
|
+
vector<int> score;
|
|
16
|
+
vector<Unit> units;
|
|
17
|
+
vector<Flag> flags;
|
|
18
|
+
vector<Event> events;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
bool read_turn(Game& g) {
|
|
22
|
+
string w;
|
|
23
|
+
while (cin >> w) {
|
|
24
|
+
if (w == "INIT") {
|
|
25
|
+
cin >> g.teams >> g.me >> g.size >> g.turns >> g.hp >> g.damage >> g.respawn >> g.flag_return >> g.flag_cooldown;
|
|
26
|
+
} else if (w == "MAP") {
|
|
27
|
+
g.map.assign(g.size, "");
|
|
28
|
+
for (auto& row : g.map) cin >> row;
|
|
29
|
+
} else if (w == "BASES") {
|
|
30
|
+
int k; cin >> k; g.bases.resize(k);
|
|
31
|
+
for (auto& b : g.bases) cin >> b.first >> b.second;
|
|
32
|
+
} else if (w == "SPOTS") {
|
|
33
|
+
int k; cin >> k; g.spots.resize(k);
|
|
34
|
+
for (auto& s : g.spots) cin >> s.first >> s.second;
|
|
35
|
+
} else if (w == "TURN") {
|
|
36
|
+
cin >> g.turn;
|
|
37
|
+
} else if (w == "SCORE") {
|
|
38
|
+
g.score.resize(g.teams);
|
|
39
|
+
for (auto& s : g.score) cin >> s;
|
|
40
|
+
} else if (w == "UNITS") {
|
|
41
|
+
int k; cin >> k; g.units.resize(k);
|
|
42
|
+
for (auto& u : g.units) { string tag; cin >> tag >> u.id >> u.team >> u.x >> u.y >> u.hp >> u.flag >> u.respawn_at; }
|
|
43
|
+
} else if (w == "FLAGS") {
|
|
44
|
+
int k; cin >> k; g.flags.resize(k);
|
|
45
|
+
for (auto& f : g.flags) { string tag; cin >> tag >> f.id >> f.status >> f.x >> f.y >> f.holder >> f.return_at; }
|
|
46
|
+
} else if (w == "EVENTS") {
|
|
47
|
+
int k; cin >> k; g.events.assign(k, {});
|
|
48
|
+
string line; getline(cin, line);
|
|
49
|
+
for (auto& e : g.events) {
|
|
50
|
+
getline(cin, line);
|
|
51
|
+
istringstream in(line);
|
|
52
|
+
string tag; in >> tag >> e.type;
|
|
53
|
+
for (int v; in >> v;) e.args.push_back(v);
|
|
54
|
+
}
|
|
55
|
+
} else if (w == "END") {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// ============================ 参数 ============================
|
|
63
|
+
static double envd(const char* n, double d) {
|
|
64
|
+
#ifdef TUNE
|
|
65
|
+
const char* s = getenv(n);
|
|
66
|
+
if (s) return atof(s);
|
|
67
|
+
#endif
|
|
68
|
+
(void)n;
|
|
69
|
+
return d;
|
|
70
|
+
}
|
|
71
|
+
struct Params {
|
|
72
|
+
double VK, VKC, VD, VDC, VHD, VHT, PICK, CAPT, WG_FETCH, WG_DELIV, WG_HUNT, WG_SUP, WG_STA;
|
|
73
|
+
double P_IN, P_REACH, STAYW, SLACK, ELIG, HUNTSLACK, ENGR, ENGRATIO, WG_ENG, PF1, PF2, FETCHMAXEFF, ESCR, WG_ESC, CTRN, FELIG, FEN;
|
|
74
|
+
void load() {
|
|
75
|
+
VK = envd("VK", 11); VKC = envd("VKC", 22); VD = envd("VD", 5); VDC = envd("VDC", 28);
|
|
76
|
+
VHD = envd("VHD", 3.0); VHT = envd("VHT", 2.0); PICK = envd("PICK", 30); CAPT = envd("CAPT", 100);
|
|
77
|
+
WG_FETCH = envd("WG_FETCH", 1.6); WG_DELIV = envd("WG_DELIV", 1.5); WG_HUNT = envd("WG_HUNT", 1.2);
|
|
78
|
+
WG_SUP = envd("WG_SUP", 0.5); WG_STA = envd("WG_STA", 0.3);
|
|
79
|
+
P_IN = envd("P_IN", 0.9); P_REACH = envd("P_REACH", 0.5); STAYW = envd("STAYW", 0.35); SLACK = envd("SLACK", 5); ELIG = envd("ELIG", 3); HUNTSLACK = envd("HUNTSLACK", 2); ENGR = envd("ENGR", 6); ENGRATIO = envd("ENGRATIO", 1.0); WG_ENG = envd("WG_ENG", 0.8); PF1 = envd("PF1", 1.0); PF2 = envd("PF2", 1.0); FETCHMAXEFF = envd("FETCHMAXEFF", 99); CTRN = envd("CTRN", 4); FELIG = envd("FELIG", 99); FEN = envd("FEN", 4); ESCR = envd("ESCR", 8); WG_ESC = envd("WG_ESC", 1.2);
|
|
80
|
+
}
|
|
81
|
+
} PR;
|
|
82
|
+
|
|
83
|
+
// ============================ 地图 ============================
|
|
84
|
+
static const int MAXC = 49 * 49;
|
|
85
|
+
static const int INFD = 30000;
|
|
86
|
+
static int W, NC, NT, ME;
|
|
87
|
+
static bool WALL[MAXC];
|
|
88
|
+
static int NB[MAXC][5]; // 0 不动 1 上 2 下 3 左 4 右;-1 为墙
|
|
89
|
+
static const int DXs[5] = {0, 0, 0, -1, 1};
|
|
90
|
+
static const int DYs[5] = {0, -1, 1, 0, 0};
|
|
91
|
+
static const char MVC[5] = {'S', 'U', 'D', 'L', 'R'};
|
|
92
|
+
static vector<int16_t> DISTV;
|
|
93
|
+
static int16_t* DIST;
|
|
94
|
+
static vector<vector<int>> BASED; // BASED[team][cell]:到该队基地的最短步数
|
|
95
|
+
static vector<array<int, 9>> BASECELLS;
|
|
96
|
+
static vector<vector<char>> ISBASE;
|
|
97
|
+
static vector<vector<int>> SPAWN;
|
|
98
|
+
static vector<int> SPOTC, BASEC;
|
|
99
|
+
static int CENTER, MYSPOT;
|
|
100
|
+
static bool inited = false;
|
|
101
|
+
|
|
102
|
+
static inline int Cx(int c) { return c % W; }
|
|
103
|
+
static inline int Cy(int c) { return c / W; }
|
|
104
|
+
static inline int MD(int a, int b) { return abs(a % W - b % W) + abs(a / W - b / W); }
|
|
105
|
+
static inline int D2(int a, int b) { return DIST[a * NC + b]; }
|
|
106
|
+
|
|
107
|
+
static bool canAtk(int a, int b) {
|
|
108
|
+
int ax = a % W, ay = a / W, bx = b % W, by = b / W;
|
|
109
|
+
int dx = bx - ax, dy = by - ay;
|
|
110
|
+
if (abs(dx) + abs(dy) > 2) return false;
|
|
111
|
+
if (abs(dx) == 2 && dy == 0) return !WALL[ay * W + ax + dx / 2];
|
|
112
|
+
if (abs(dy) == 2 && dx == 0) return !WALL[(ay + dy / 2) * W + ax];
|
|
113
|
+
if (abs(dx) == 1 && abs(dy) == 1) return !WALL[ay * W + ax + dx] || !WALL[(ay + dy) * W + ax];
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
static void bfsFrom(int s, int16_t* d) {
|
|
118
|
+
static int q[MAXC];
|
|
119
|
+
for (int i = 0; i < NC; i++) d[i] = INFD;
|
|
120
|
+
int h = 0, t = 0; q[t++] = s; d[s] = 0;
|
|
121
|
+
while (h < t) {
|
|
122
|
+
int c = q[h++];
|
|
123
|
+
for (int k = 1; k < 5; k++) { int n = NB[c][k]; if (n >= 0 && d[n] == INFD) { d[n] = d[c] + 1; q[t++] = n; } }
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
static void init(const Game& g) {
|
|
128
|
+
PR.load();
|
|
129
|
+
W = g.size; NC = W * W; NT = g.teams; ME = g.me;
|
|
130
|
+
for (int y = 0; y < W; y++) for (int x = 0; x < W; x++) WALL[y * W + x] = g.map[y][x] == '#';
|
|
131
|
+
for (int c = 0; c < NC; c++) {
|
|
132
|
+
int x = c % W, y = c / W;
|
|
133
|
+
for (int k = 0; k < 5; k++) {
|
|
134
|
+
int nx = x + DXs[k], ny = y + DYs[k];
|
|
135
|
+
if (WALL[c] || nx < 0 || ny < 0 || nx >= W || ny >= W || WALL[ny * W + nx]) NB[c][k] = (k == 0 && !WALL[c]) ? c : -1;
|
|
136
|
+
else NB[c][k] = ny * W + nx;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
DISTV.assign((size_t)NC * NC, INFD);
|
|
140
|
+
DIST = DISTV.data();
|
|
141
|
+
for (int s = 0; s < NC; s++) if (!WALL[s]) bfsFrom(s, DIST + (size_t)s * NC);
|
|
142
|
+
CENTER = (W / 2) * W + W / 2;
|
|
143
|
+
BASEC.clear(); BASECELLS.assign(NT, {}); ISBASE.assign(NT, vector<char>(NC, 0)); BASED.assign(NT, vector<int>(NC, INFD)); SPAWN.assign(NT, {});
|
|
144
|
+
for (int t = 0; t < NT; t++) {
|
|
145
|
+
int bx = g.bases[t].first, by = g.bases[t].second;
|
|
146
|
+
BASEC.push_back(by * W + bx);
|
|
147
|
+
int k = 0;
|
|
148
|
+
vector<int> cells;
|
|
149
|
+
for (int dy = -1; dy <= 1; dy++) for (int dx = -1; dx <= 1; dx++) { int c = (by + dy) * W + bx + dx; BASECELLS[t][k++] = c; ISBASE[t][c] = 1; cells.push_back(c); }
|
|
150
|
+
for (int c = 0; c < NC; c++) if (!WALL[c]) { int m = INFD; for (int bc : BASECELLS[t]) m = min(m, (int)D2(bc, c)); BASED[t][c] = m; }
|
|
151
|
+
stable_sort(cells.begin(), cells.end(), [&](int a, int b) {
|
|
152
|
+
auto key = [&](int c) { return make_pair(abs(c % W - W / 2) + abs(c / W - W / 2), abs(c % W - bx) + 2 * abs(c / W - by)); };
|
|
153
|
+
return key(a) < key(b);
|
|
154
|
+
});
|
|
155
|
+
SPAWN[t] = cells;
|
|
156
|
+
}
|
|
157
|
+
SPOTC.clear();
|
|
158
|
+
for (auto& s : g.spots) SPOTC.push_back(s.second * W + s.first);
|
|
159
|
+
MYSPOT = SPOTC.empty() ? CENTER : SPOTC[0];
|
|
160
|
+
int best = INFD;
|
|
161
|
+
for (int s : SPOTC) { int d = D2(BASEC[ME], s); if (d < best) { best = d; MYSPOT = s; } }
|
|
162
|
+
inited = true;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// ============================ 决策 ============================
|
|
166
|
+
struct En { int id, team, c, hp, flag; bool canAtk; int nm; int mc[5]; };
|
|
167
|
+
struct My {
|
|
168
|
+
int k, id; bool active, spawning; int c, hp, flag;
|
|
169
|
+
int nm; int mv[5]; int mc[5];
|
|
170
|
+
int mode = 0; // 0 待命 1 取旗 2 送旗 3 截击 4 护送/支援
|
|
171
|
+
vector<int> G; double wg = 0; int fcell = -1; int tgtEn = -1;
|
|
172
|
+
string note;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
static double atLeast(const double* p, int n, int need) {
|
|
176
|
+
if (need <= 0) return 1.0;
|
|
177
|
+
if (n < need) return 0.0;
|
|
178
|
+
double dp[8] = {0}; dp[0] = 1.0;
|
|
179
|
+
for (int i = 0; i < n; i++) {
|
|
180
|
+
for (int k = need; k >= 0; k--) {
|
|
181
|
+
double up = (k > 0 ? dp[k - 1] * p[i] : 0.0);
|
|
182
|
+
if (k == need) dp[k] = dp[k] + up;
|
|
183
|
+
else dp[k] = dp[k] * (1 - p[i]) + up;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return dp[need];
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
static string decide(const Game& g) {
|
|
190
|
+
if (!inited) init(g);
|
|
191
|
+
const int t = g.turn;
|
|
192
|
+
const int remaining = g.turns - t + 1; // 含本回合
|
|
193
|
+
vector<Unit> us(NT * 3);
|
|
194
|
+
for (auto& u : g.units) if (u.id >= 0 && u.id < NT * 3) us[u.id] = u;
|
|
195
|
+
vector<int> occ(NC, -1);
|
|
196
|
+
for (auto& u : us) if (u.x >= 0) occ[u.y * W + u.x] = u.id;
|
|
197
|
+
|
|
198
|
+
// ---- 敌方 ----
|
|
199
|
+
vector<En> en;
|
|
200
|
+
for (auto& u : us) {
|
|
201
|
+
if (u.team == ME || u.x < 0) continue;
|
|
202
|
+
En e; e.id = u.id; e.team = u.team; e.c = u.y * W + u.x; e.hp = u.hp; e.flag = u.flag; e.canAtk = (u.flag < 0);
|
|
203
|
+
e.nm = 0;
|
|
204
|
+
for (int k = 0; k < 5; k++) if (NB[e.c][k] >= 0) e.mc[e.nm++] = NB[e.c][k];
|
|
205
|
+
en.push_back(e);
|
|
206
|
+
}
|
|
207
|
+
// ---- 己方 ----
|
|
208
|
+
My my[3];
|
|
209
|
+
{
|
|
210
|
+
vector<char> taken(NC, 0);
|
|
211
|
+
for (int c = 0; c < NC; c++) if (occ[c] >= 0) taken[c] = 1;
|
|
212
|
+
for (int k = 0; k < 3; k++) {
|
|
213
|
+
My& m = my[k]; Unit& u = us[3 * ME + k];
|
|
214
|
+
m.k = k; m.id = 3 * ME + k; m.hp = u.hp; m.flag = u.flag; m.active = false; m.spawning = false; m.nm = 0; m.c = -1;
|
|
215
|
+
if (u.x >= 0) { m.active = true; m.c = u.y * W + u.x; }
|
|
216
|
+
else if (u.respawn_at == t) {
|
|
217
|
+
for (int c : SPAWN[ME]) if (!taken[c]) { taken[c] = 1; m.c = c; m.active = true; m.spawning = true; m.hp = g.hp; m.flag = -1; break; }
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// ---- 旗子 ----
|
|
222
|
+
struct FI { int id, c, st, ret; };
|
|
223
|
+
vector<FI> avail; // 可拾取的旗
|
|
224
|
+
vector<int> carriedBy(g.flags.size(), -1);
|
|
225
|
+
for (auto& f : g.flags) {
|
|
226
|
+
if (f.status == "home" && f.x >= 0) avail.push_back({f.id, f.y * W + f.x, 0, 1 << 30});
|
|
227
|
+
else if (f.status == "dropped" && f.x >= 0 && f.return_at > t) avail.push_back({f.id, f.y * W + f.x, 1, f.return_at});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// ---- 候选移动 ----
|
|
231
|
+
for (int k = 0; k < 3; k++) {
|
|
232
|
+
My& m = my[k];
|
|
233
|
+
if (!m.active) continue;
|
|
234
|
+
for (int mv = 0; mv < 5; mv++) {
|
|
235
|
+
int nc = NB[m.c][mv];
|
|
236
|
+
if (nc < 0) continue;
|
|
237
|
+
if (mv != 0 && occ[nc] >= 0 && us[occ[nc]].team != ME) continue;
|
|
238
|
+
m.mv[m.nm] = mv; m.mc[m.nm] = nc; m.nm++;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ---- 任务分配 ----
|
|
243
|
+
bool assigned[3] = {false, false, false};
|
|
244
|
+
auto setGoal = [&](My& m, int mode, int cell, double wg) {
|
|
245
|
+
m.mode = mode; m.G.assign(NC, 0);
|
|
246
|
+
for (int c = 0; c < NC; c++) m.G[c] = (cell >= 0) ? D2(cell, c) : 0;
|
|
247
|
+
m.wg = wg;
|
|
248
|
+
};
|
|
249
|
+
// 危险附加代价(用于携旗者绕行)
|
|
250
|
+
vector<int> extra(NC, 0);
|
|
251
|
+
for (auto& e : en) if (e.canAtk) {
|
|
252
|
+
int ex = e.c % W, ey = e.c / W;
|
|
253
|
+
for (int dy = -3; dy <= 3; dy++) for (int dx = -3; dx <= 3; dx++) {
|
|
254
|
+
int d = abs(dx) + abs(dy); if (d > 3) continue;
|
|
255
|
+
int x = ex + dx, y = ey + dy; if (x < 0 || y < 0 || x >= W || y >= W) continue;
|
|
256
|
+
extra[y * W + x] += (d <= 2 ? 3 : 1);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
// 1) 携旗者:送旗(带危险代价的 Dijkstra)
|
|
260
|
+
bool anyCarrier = false; int carrierK = -1;
|
|
261
|
+
{
|
|
262
|
+
bool need = false;
|
|
263
|
+
for (int k = 0; k < 3; k++) if (my[k].active && my[k].flag >= 0) need = true;
|
|
264
|
+
if (need) {
|
|
265
|
+
vector<int> sd(NC, INFD);
|
|
266
|
+
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
|
|
267
|
+
for (int bc : BASECELLS[ME]) { sd[bc] = 0; pq.push({0, bc}); }
|
|
268
|
+
while (!pq.empty()) {
|
|
269
|
+
auto [d, c] = pq.top(); pq.pop();
|
|
270
|
+
if (d > sd[c]) continue;
|
|
271
|
+
for (int k = 1; k < 5; k++) { int n = NB[c][k]; if (n < 0) continue; int nd = d + 1 + extra[c]; if (nd < sd[n]) { sd[n] = nd; pq.push({nd, n}); } }
|
|
272
|
+
}
|
|
273
|
+
for (int k = 0; k < 3; k++) if (my[k].active && my[k].flag >= 0) {
|
|
274
|
+
My& m = my[k]; m.mode = 2; m.G = sd; m.wg = PR.WG_DELIV; assigned[k] = true; anyCarrier = true; carrierK = k; m.note = "deliver";
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
// 2) 截击敌方携旗者
|
|
279
|
+
vector<int> enemyCarriers;
|
|
280
|
+
for (int i = 0; i < (int)en.size(); i++) if (en[i].flag >= 0) enemyCarriers.push_back(i);
|
|
281
|
+
for (int ei : enemyCarriers) {
|
|
282
|
+
const En& e = en[ei];
|
|
283
|
+
// 敌方预测路径
|
|
284
|
+
vector<int> path; int c = e.c; path.push_back(c);
|
|
285
|
+
for (int s = 0; s < 40 && BASED[e.team][c] > 0; s++) {
|
|
286
|
+
int bestn = -1, bd = BASED[e.team][c];
|
|
287
|
+
for (int k = 1; k < 5; k++) { int n = NB[c][k]; if (n >= 0 && BASED[e.team][n] < bd) { bd = BASED[e.team][n]; bestn = n; } }
|
|
288
|
+
if (bestn < 0) break;
|
|
289
|
+
c = bestn; path.push_back(c);
|
|
290
|
+
}
|
|
291
|
+
// 找截击者:所有能赶上的空闲角色
|
|
292
|
+
for (int k = 0; k < 3; k++) {
|
|
293
|
+
if (!my[k].active || assigned[k] || my[k].flag >= 0) continue;
|
|
294
|
+
for (int s = 0; s < (int)path.size(); s++) {
|
|
295
|
+
int d = D2(my[k].c, path[s]);
|
|
296
|
+
if (d <= s + (int)PR.HUNTSLACK && s <= 14) {
|
|
297
|
+
My& m = my[k]; setGoal(m, 3, path[s], PR.WG_HUNT); m.tgtEn = ei; assigned[k] = true; m.note = "hunt";
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
// 3) 取旗
|
|
304
|
+
{
|
|
305
|
+
struct Cand { int k, fi, eta; };
|
|
306
|
+
vector<Cand> cands;
|
|
307
|
+
vector<int> rival(avail.size(), INFD);
|
|
308
|
+
for (int fi = 0; fi < (int)avail.size(); fi++) {
|
|
309
|
+
for (auto& e : en) if (e.flag < 0) rival[fi] = min(rival[fi], (int)D2(e.c, avail[fi].c));
|
|
310
|
+
for (auto& u : us) if (u.team != ME && u.x < 0 && u.respawn_at >= 0) {
|
|
311
|
+
int dd = max(0, u.respawn_at - t) + D2(BASEC[u.team], avail[fi].c);
|
|
312
|
+
rival[fi] = min(rival[fi], dd);
|
|
313
|
+
}
|
|
314
|
+
for (int k = 0; k < 3; k++) {
|
|
315
|
+
if (!my[k].active || assigned[k] || my[k].flag >= 0) continue;
|
|
316
|
+
int eta = D2(my[k].c, avail[fi].c);
|
|
317
|
+
if (avail[fi].st == 1 && eta > avail[fi].ret - t) continue;
|
|
318
|
+
if (eta + (int)BASED[ME][avail[fi].c] > remaining) continue;
|
|
319
|
+
cands.push_back({k, fi, eta});
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
sort(cands.begin(), cands.end(), [](const Cand& a, const Cand& b) { return a.eta < b.eta; });
|
|
323
|
+
vector<char> fdone(avail.size(), 0);
|
|
324
|
+
for (auto& cd : cands) {
|
|
325
|
+
if (assigned[cd.k] || fdone[cd.fi]) continue;
|
|
326
|
+
int margin = rival[cd.fi] - cd.eta;
|
|
327
|
+
if (margin < -PR.SLACK) continue;
|
|
328
|
+
if (NT >= (int)PR.FEN) {
|
|
329
|
+
int mn = INFD;
|
|
330
|
+
for (int tt = 0; tt < NT; tt++) if (tt != ME) mn = min(mn, (int)D2(BASEC[tt], avail[cd.fi].c));
|
|
331
|
+
if (D2(BASEC[ME], avail[cd.fi].c) > mn + (int)PR.FELIG) continue;
|
|
332
|
+
}
|
|
333
|
+
if (BASED[ME][avail[cd.fi].c] > 3) {
|
|
334
|
+
int chasers = 0, guards = 0;
|
|
335
|
+
for (auto& e : en) if (e.canAtk && D2(e.c, avail[cd.fi].c) <= 3) chasers++;
|
|
336
|
+
for (int j = 0; j < 3; j++) if (j != cd.k && my[j].active && !my[j].spawning && D2(my[j].c, avail[cd.fi].c) <= 4) guards++;
|
|
337
|
+
if (chasers - guards >= (int)PR.FETCHMAXEFF) continue;
|
|
338
|
+
}
|
|
339
|
+
My& m = my[cd.k]; setGoal(m, 1, avail[cd.fi].c, PR.WG_FETCH); m.fcell = avail[cd.fi].c; assigned[cd.k] = true; fdone[cd.fi] = 1; m.note = "fetch";
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
// 4) 其余:护送 / 分散待命到空旗点
|
|
343
|
+
{
|
|
344
|
+
vector<int> freeK;
|
|
345
|
+
for (int k = 0; k < 3; k++) if (my[k].active && !assigned[k]) freeK.push_back(k);
|
|
346
|
+
if (anyCarrier && carrierK >= 0 && !freeK.empty()) {
|
|
347
|
+
int cc = my[carrierK].c;
|
|
348
|
+
vector<pair<int, int>> th;
|
|
349
|
+
for (int ei = 0; ei < (int)en.size(); ei++) if (en[ei].canAtk && D2(en[ei].c, cc) <= (int)PR.ESCR) th.push_back({D2(en[ei].c, cc), ei});
|
|
350
|
+
sort(th.begin(), th.end());
|
|
351
|
+
if (!th.empty()) {
|
|
352
|
+
sort(freeK.begin(), freeK.end(), [&](int a, int b) { return D2(my[a].c, cc) < D2(my[b].c, cc); });
|
|
353
|
+
vector<int> usedCells;
|
|
354
|
+
int nesc = min((int)freeK.size(), 2);
|
|
355
|
+
for (int idx = 0; idx < nesc; idx++) {
|
|
356
|
+
int k = freeK[idx]; const En& e = en[th[min(idx, (int)th.size() - 1)].second];
|
|
357
|
+
int bestCell = -1; double bv = 1e18;
|
|
358
|
+
int cx = cc % W, cy = cc / W;
|
|
359
|
+
for (int dy = -2; dy <= 2; dy++) for (int dx = -2; dx <= 2; dx++) {
|
|
360
|
+
if (abs(dx) + abs(dy) > 2) continue;
|
|
361
|
+
int x = cx + dx, y = cy + dy; if (x < 0 || y < 0 || x >= W || y >= W) continue;
|
|
362
|
+
int c = y * W + x; if (WALL[c] || c == cc) continue;
|
|
363
|
+
if (find(usedCells.begin(), usedCells.end(), c) != usedCells.end()) continue;
|
|
364
|
+
double v = D2(c, e.c) + 0.3 * D2(c, my[k].c);
|
|
365
|
+
if (v < bv) { bv = v; bestCell = c; }
|
|
366
|
+
}
|
|
367
|
+
if (bestCell < 0) continue;
|
|
368
|
+
usedCells.push_back(bestCell);
|
|
369
|
+
setGoal(my[k], 4, bestCell, PR.WG_ESC); my[k].note = "escort"; assigned[k] = true;
|
|
370
|
+
}
|
|
371
|
+
vector<int> rest;
|
|
372
|
+
for (int k : freeK) if (!assigned[k]) rest.push_back(k);
|
|
373
|
+
freeK = rest;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
// 局部优势时主动接敌
|
|
377
|
+
for (int idx = 0; idx < (int)freeK.size();) {
|
|
378
|
+
int k = freeK[idx]; My& m = my[k];
|
|
379
|
+
int bestE = -1; double bestV = -1e9;
|
|
380
|
+
for (int ei = 0; ei < (int)en.size(); ei++) {
|
|
381
|
+
const En& e = en[ei]; int d = D2(m.c, e.c);
|
|
382
|
+
if (d > (int)PR.ENGR) continue;
|
|
383
|
+
double myP = 0, enP = 0;
|
|
384
|
+
for (int j = 0; j < 3; j++) if (my[j].active && !my[j].spawning && D2(my[j].c, e.c) <= 5) myP += my[j].hp;
|
|
385
|
+
for (auto& e2 : en) if (e2.canAtk && D2(e2.c, e.c) <= 4) enP += e2.hp;
|
|
386
|
+
if (myP < PR.ENGRATIO * enP) continue;
|
|
387
|
+
double v = -d - e.hp * 0.02 + (e.flag >= 0 ? 10 : 0);
|
|
388
|
+
if (v > bestV) { bestV = v; bestE = ei; }
|
|
389
|
+
}
|
|
390
|
+
if (bestE >= 0) { setGoal(m, 5, en[bestE].c, PR.WG_ENG); m.note = "engage"; assigned[k] = true; freeK.erase(freeK.begin() + idx); }
|
|
391
|
+
else idx++;
|
|
392
|
+
}
|
|
393
|
+
vector<int> stations;
|
|
394
|
+
for (int sp : SPOTC) {
|
|
395
|
+
bool hasFlag = false;
|
|
396
|
+
for (auto& f : g.flags) if (f.status == "home" && f.x >= 0 && f.y * W + f.x == sp) hasFlag = true;
|
|
397
|
+
if (hasFlag) continue;
|
|
398
|
+
if (sp == CENTER && NT >= (int)PR.CTRN) continue;
|
|
399
|
+
int myd = D2(BASEC[ME], sp), mn = INFD;
|
|
400
|
+
for (int tt = 0; tt < NT; tt++) if (tt != ME) mn = min(mn, (int)D2(BASEC[tt], sp));
|
|
401
|
+
if (myd <= mn + (int)PR.ELIG) stations.push_back(sp);
|
|
402
|
+
}
|
|
403
|
+
if (stations.empty()) stations.push_back(MYSPOT);
|
|
404
|
+
struct Pr { int k, si, d; };
|
|
405
|
+
vector<Pr> prs;
|
|
406
|
+
for (int k : freeK) for (int si = 0; si < (int)stations.size(); si++) prs.push_back({k, si, (int)D2(my[k].c, stations[si])});
|
|
407
|
+
sort(prs.begin(), prs.end(), [](const Pr& a, const Pr& b) { return a.d < b.d; });
|
|
408
|
+
vector<char> sused(stations.size(), 0);
|
|
409
|
+
for (auto& pr : prs) {
|
|
410
|
+
if (assigned[pr.k] || sused[pr.si]) continue;
|
|
411
|
+
setGoal(my[pr.k], 0, stations[pr.si], PR.WG_STA); my[pr.k].note = "station"; assigned[pr.k] = true; sused[pr.si] = 1;
|
|
412
|
+
}
|
|
413
|
+
for (int k : freeK) if (!assigned[k]) {
|
|
414
|
+
int bd = INFD, bs = stations[0];
|
|
415
|
+
for (int sp : stations) { int d = D2(my[k].c, sp); if (d < bd) { bd = d; bs = sp; } }
|
|
416
|
+
setGoal(my[k], 0, bs, PR.WG_STA); my[k].note = "station2"; assigned[k] = true;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// ---- 联合动作评估 ----
|
|
421
|
+
int NE = en.size();
|
|
422
|
+
// 预计算:pa[e][k][mi](敌方 e 攻击我方 k 在候选 mi 的概率),ph[e][k][mi](我方命中 e 的概率)
|
|
423
|
+
static double pa[48][3][5], ph[48][3][5];
|
|
424
|
+
for (int ei = 0; ei < NE; ei++) for (int k = 0; k < 3; k++) {
|
|
425
|
+
My& m = my[k];
|
|
426
|
+
for (int mi = 0; mi < m.nm; mi++) {
|
|
427
|
+
pa[ei][k][mi] = 0; ph[ei][k][mi] = 0;
|
|
428
|
+
if (!m.active) continue;
|
|
429
|
+
int c = m.mc[mi]; const En& e = en[ei];
|
|
430
|
+
if (e.canAtk && !m.spawning) {
|
|
431
|
+
bool now = canAtk(e.c, c), reach = false;
|
|
432
|
+
for (int q = 0; q < e.nm && !reach; q++) if (canAtk(e.mc[q], c)) reach = true;
|
|
433
|
+
pa[ei][k][mi] = now ? PR.P_IN : (reach ? PR.P_REACH : 0.0);
|
|
434
|
+
}
|
|
435
|
+
if (!m.spawning && m.flag < 0) {
|
|
436
|
+
double p = 0; int others = max(1, e.nm - 1);
|
|
437
|
+
for (int q = 0; q < e.nm; q++) {
|
|
438
|
+
double w = (e.mc[q] == e.c) ? PR.STAYW : (1 - PR.STAYW) / others;
|
|
439
|
+
if (e.nm == 1) w = 1.0;
|
|
440
|
+
if (canAtk(c, e.mc[q])) p += w;
|
|
441
|
+
}
|
|
442
|
+
ph[ei][k][mi] = min(1.0, p);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
// 单元静态得分
|
|
447
|
+
double base[3][5];
|
|
448
|
+
int pickAt[3][5]; // 该位置可拾取旗(1)
|
|
449
|
+
double pickB[3][5];
|
|
450
|
+
for (int k = 0; k < 3; k++) {
|
|
451
|
+
My& m = my[k];
|
|
452
|
+
for (int mi = 0; mi < m.nm; mi++) {
|
|
453
|
+
int c = m.mc[mi];
|
|
454
|
+
double s = 0;
|
|
455
|
+
s -= m.wg * (m.G.empty() ? 0 : m.G[c]);
|
|
456
|
+
pickAt[k][mi] = 0; pickB[k][mi] = 0;
|
|
457
|
+
if (m.flag >= 0) {
|
|
458
|
+
if (ISBASE[ME][c]) s += PR.CAPT;
|
|
459
|
+
} else {
|
|
460
|
+
for (auto& f : avail) if (f.c == c) {
|
|
461
|
+
pickAt[k][mi] = 1;
|
|
462
|
+
double coll = 0;
|
|
463
|
+
for (auto& e : en) if (e.flag < 0 && D2(e.c, c) <= 1) coll = max(coll, 0.6);
|
|
464
|
+
double pf = 1.0;
|
|
465
|
+
if (BASED[ME][c] > 3) {
|
|
466
|
+
int chasers = 0, guards = 0;
|
|
467
|
+
for (auto& e : en) if (e.canAtk && D2(e.c, c) <= 3) chasers++;
|
|
468
|
+
for (int j = 0; j < 3; j++) if (j != k && my[j].active && !my[j].spawning && D2(my[j].c, c) <= 2) guards++;
|
|
469
|
+
int eff = max(0, chasers - guards);
|
|
470
|
+
pf = eff == 0 ? 1.0 : eff == 1 ? PR.PF1 : PR.PF2;
|
|
471
|
+
}
|
|
472
|
+
pickB[k][mi] = PR.PICK * (1 - coll) * pf;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
base[k][mi] = s;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
// 枚举
|
|
479
|
+
double bestScore = -1e18; int bestSel[3] = {0, 0, 0}; int bestTgt[3] = {-1, -1, -1};
|
|
480
|
+
int sel[3];
|
|
481
|
+
int n0 = my[0].active ? my[0].nm : 1, n1 = my[1].active ? my[1].nm : 1, n2 = my[2].active ? my[2].nm : 1;
|
|
482
|
+
for (sel[0] = 0; sel[0] < n0; sel[0]++) for (sel[1] = 0; sel[1] < n1; sel[1]++) for (sel[2] = 0; sel[2] < n2; sel[2]++) {
|
|
483
|
+
int cell[3] = {-1, -1, -1}; bool ok = true;
|
|
484
|
+
for (int k = 0; k < 3; k++) if (my[k].active) cell[k] = my[k].mc[sel[k]];
|
|
485
|
+
for (int a = 0; a < 3 && ok; a++) for (int b = a + 1; b < 3; b++) if (cell[a] >= 0 && cell[a] == cell[b]) { ok = false; break; }
|
|
486
|
+
if (!ok) continue;
|
|
487
|
+
double score = 0;
|
|
488
|
+
for (int k = 0; k < 3; k++) if (my[k].active) score += base[k][sel[k]];
|
|
489
|
+
// 敌方火力分配
|
|
490
|
+
double inc[3][48]; int incn[3] = {0, 0, 0};
|
|
491
|
+
for (int ei = 0; ei < NE; ei++) {
|
|
492
|
+
if (!en[ei].canAtk) continue;
|
|
493
|
+
int bk = -1; double bp = -1;
|
|
494
|
+
for (int k = 0; k < 3; k++) if (my[k].active && pa[ei][k][sel[k]] > 0) {
|
|
495
|
+
double pr = (my[k].flag >= 0 ? 1000 : 0) + (200 - my[k].hp) + pa[ei][k][sel[k]] * 10;
|
|
496
|
+
if (pr > bp) { bp = pr; bk = k; }
|
|
497
|
+
}
|
|
498
|
+
if (bk >= 0) inc[bk][incn[bk]++] = pa[ei][bk][sel[bk]];
|
|
499
|
+
}
|
|
500
|
+
for (int k = 0; k < 3; k++) if (my[k].active && incn[k] > 0) {
|
|
501
|
+
int need = (my[k].hp + g.damage - 1) / g.damage;
|
|
502
|
+
double pd = atLeast(inc[k], incn[k], need);
|
|
503
|
+
double eh = 0; for (int i = 0; i < incn[k]; i++) eh += inc[k][i];
|
|
504
|
+
double endf = min(1.0, remaining / 12.0);
|
|
505
|
+
double vd = PR.VD * (0.35 + 0.65 * min(1.0, my[k].hp / 100.0)) * endf + (my[k].flag >= 0 ? PR.VDC : 0);
|
|
506
|
+
score -= pd * vd + min(eh, (double)(need - 1)) * PR.VHT;
|
|
507
|
+
}
|
|
508
|
+
// 我方攻击目标枚举
|
|
509
|
+
int opt[3][5]; int on[3];
|
|
510
|
+
for (int k = 0; k < 3; k++) {
|
|
511
|
+
on[k] = 0; opt[k][on[k]++] = -1;
|
|
512
|
+
if (!my[k].active || my[k].spawning || my[k].flag >= 0) continue;
|
|
513
|
+
vector<pair<double, int>> lst;
|
|
514
|
+
for (int ei = 0; ei < NE; ei++) {
|
|
515
|
+
double p = ph[ei][k][sel[k]];
|
|
516
|
+
if (p > 0.05) lst.push_back({p + (en[ei].flag >= 0 ? 2 : 0) + (200 - en[ei].hp) * 0.01, ei});
|
|
517
|
+
}
|
|
518
|
+
sort(lst.begin(), lst.end(), [](auto& a, auto& b) { return a.first > b.first; });
|
|
519
|
+
for (int i = 0; i < (int)lst.size() && on[k] < 4; i++) opt[k][on[k]++] = lst[i].second;
|
|
520
|
+
}
|
|
521
|
+
double bestAtk = -1e18; int bt[3] = {-1, -1, -1};
|
|
522
|
+
for (int a = 0; a < on[0]; a++) for (int b = 0; b < on[1]; b++) for (int c = 0; c < on[2]; c++) {
|
|
523
|
+
int tg[3] = {opt[0][a], opt[1][b], opt[2][c]};
|
|
524
|
+
double val = 0;
|
|
525
|
+
// 汇总每个目标
|
|
526
|
+
for (int ei = 0; ei < NE; ei++) {
|
|
527
|
+
double ps[3]; int n = 0;
|
|
528
|
+
for (int k = 0; k < 3; k++) if (tg[k] == ei) ps[n++] = ph[ei][k][sel[k]];
|
|
529
|
+
if (!n) continue;
|
|
530
|
+
int need = (en[ei].hp + g.damage - 1) / g.damage;
|
|
531
|
+
double pk = atLeast(ps, n, need), eh = 0;
|
|
532
|
+
for (int i = 0; i < n; i++) eh += ps[i];
|
|
533
|
+
val += pk * (PR.VK + (en[ei].flag >= 0 ? PR.VKC : 0)) + min(eh, (double)need) * PR.VHD;
|
|
534
|
+
}
|
|
535
|
+
// 拾旗替代攻击
|
|
536
|
+
for (int k = 0; k < 3; k++) if (tg[k] < 0 && my[k].active && pickAt[k][sel[k]]) val += pickB[k][sel[k]];
|
|
537
|
+
if (val > bestAtk) { bestAtk = val; bt[0] = tg[0]; bt[1] = tg[1]; bt[2] = tg[2]; }
|
|
538
|
+
}
|
|
539
|
+
score += bestAtk;
|
|
540
|
+
if (score > bestScore) { bestScore = score; for (int k = 0; k < 3; k++) { bestSel[k] = sel[k]; bestTgt[k] = bt[k]; } }
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// ---- 输出 ----
|
|
544
|
+
string out = to_string(t);
|
|
545
|
+
string notes;
|
|
546
|
+
for (int k = 0; k < 3; k++) {
|
|
547
|
+
My& m = my[k];
|
|
548
|
+
if (!m.active) { out += " S -"; notes += (k ? ";" : "") + string("dead"); continue; }
|
|
549
|
+
int mv = m.mv[bestSel[k]];
|
|
550
|
+
string act = "-";
|
|
551
|
+
if (bestTgt[k] >= 0) act = to_string(en[bestTgt[k]].id);
|
|
552
|
+
else act = "P";
|
|
553
|
+
out += string(" ") + MVC[mv] + " " + act;
|
|
554
|
+
notes += (k ? ";" : "") + m.note;
|
|
555
|
+
}
|
|
556
|
+
out += " # " + notes;
|
|
557
|
+
return out;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
int main() {
|
|
561
|
+
ios::sync_with_stdio(false);
|
|
562
|
+
Game g;
|
|
563
|
+
while (read_turn(g)) {
|
|
564
|
+
string out;
|
|
565
|
+
try { out = decide(g); }
|
|
566
|
+
catch (...) { out = to_string(g.turn) + " S - S - S -"; }
|
|
567
|
+
cout << out << endl;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# 复现正式赛
|
|
2
|
+
|
|
3
|
+
正式赛分两段:2–8 人(`formal-2to8.json`,每位选手一份)、9–15 人(`formal-9to15.json`,每位选手两份同场),合并评分。配置里写着原来的赛程种子,所以赛程(地图、座位、对阵)可以一模一样地重建。
|
|
4
|
+
|
|
5
|
+
在本目录运行(全程约 2 小时,12 并发;可以中断后用同一命令续跑):
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
python ../../arena/tournament.py plan formal-2to8.json run-2to8
|
|
9
|
+
python ../../arena/tournament.py plan formal-9to15.json run-9to15
|
|
10
|
+
python ../../arena/tournament.py run run-2to8 --workers 8
|
|
11
|
+
python ../../arena/tournament.py run run-9to15 --workers 8
|
|
12
|
+
python ../../arena/tournament.py rate run-2to8 run-9to15
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
注意:旗子每次刷新在哪个旗点用的是单独的随机数(每局现取,为了防止从地图反推),所以逐局比分不会和原赛完全相同,但总排名应当一致。每回合限时 50 毫秒,对机器负载敏感:每局程序数 × 并发局数,最好不超过 CPU 线程数的约 3/4。
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"game": "../workspace/engine.py",
|
|
3
|
+
"anchor": "基准",
|
|
4
|
+
"players": {
|
|
5
|
+
"基准": "../workspace/baseline.cpp",
|
|
6
|
+
"Fable 5.1": "../bots/fable-5.1.cpp",
|
|
7
|
+
"Opus 5.5": "../bots/opus-5.5.cpp",
|
|
8
|
+
"Sonnet 5.5": "../bots/sonnet-5.5.cpp",
|
|
9
|
+
"GPT-6 Astra": "../bots/gpt-6-astra.cpp",
|
|
10
|
+
"GPT-6.1 Sol": "../bots/gpt-6.1-sol.cpp",
|
|
11
|
+
"DeepSeek V4.1 Flash": "../bots/deepseek-v4.1-flash.cpp",
|
|
12
|
+
"Qwen 3.8 Max": "../bots/qwen-3.8-max.cpp",
|
|
13
|
+
"GLM 5.3": "../bots/glm-5.3.cpp",
|
|
14
|
+
"MiMo V2.6 Pro": "../bots/mimo-v2.6-pro.cpp",
|
|
15
|
+
"豆包 Seed 2.1 Turbo": "../bots/doubao-seed-2.1-turbo.cpp",
|
|
16
|
+
"Kimi K3": "../bots/kimi-k3.cpp"
|
|
17
|
+
},
|
|
18
|
+
"sizes": [
|
|
19
|
+
2,
|
|
20
|
+
3,
|
|
21
|
+
4,
|
|
22
|
+
5,
|
|
23
|
+
6,
|
|
24
|
+
7,
|
|
25
|
+
8
|
|
26
|
+
],
|
|
27
|
+
"maps_per_size": 110,
|
|
28
|
+
"copies": 1,
|
|
29
|
+
"seed": 27772916379806,
|
|
30
|
+
"replays": false
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"game": "../workspace/engine.py",
|
|
3
|
+
"anchor": "基准",
|
|
4
|
+
"players": {
|
|
5
|
+
"基准": "../workspace/baseline.cpp",
|
|
6
|
+
"Fable 5.1": "../bots/fable-5.1.cpp",
|
|
7
|
+
"Opus 5.5": "../bots/opus-5.5.cpp",
|
|
8
|
+
"Sonnet 5.5": "../bots/sonnet-5.5.cpp",
|
|
9
|
+
"GPT-6 Astra": "../bots/gpt-6-astra.cpp",
|
|
10
|
+
"GPT-6.1 Sol": "../bots/gpt-6.1-sol.cpp",
|
|
11
|
+
"DeepSeek V4.1 Flash": "../bots/deepseek-v4.1-flash.cpp",
|
|
12
|
+
"Qwen 3.8 Max": "../bots/qwen-3.8-max.cpp",
|
|
13
|
+
"GLM 5.3": "../bots/glm-5.3.cpp",
|
|
14
|
+
"MiMo V2.6 Pro": "../bots/mimo-v2.6-pro.cpp",
|
|
15
|
+
"豆包 Seed 2.1 Turbo": "../bots/doubao-seed-2.1-turbo.cpp",
|
|
16
|
+
"Kimi K3": "../bots/kimi-k3.cpp"
|
|
17
|
+
},
|
|
18
|
+
"sizes": [
|
|
19
|
+
9,
|
|
20
|
+
10,
|
|
21
|
+
11,
|
|
22
|
+
12,
|
|
23
|
+
13,
|
|
24
|
+
14,
|
|
25
|
+
15
|
|
26
|
+
],
|
|
27
|
+
"maps_per_size": 110,
|
|
28
|
+
"copies": 2,
|
|
29
|
+
"seed": 91187465621305,
|
|
30
|
+
"replays": false
|
|
31
|
+
}
|