dsh-eval-guard 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -13
- package/assets/bomberman/workspace.zip +0 -0
- package/assets/commit0/instance.json +30 -0
- package/assets/commit0/workspace.zip +0 -0
- package/assets/ctf/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/assets/tank/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,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
|
+
}
|