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,373 @@
|
|
|
1
|
+
// Territory contest bot. Standard C++20, one process and one thread.
|
|
2
|
+
// Uses exact flood-fill scoring, directed opponent reachability, a diverse
|
|
3
|
+
// family of closed excursions, and receding-horizon return-path searches.
|
|
4
|
+
// Interceptions account for actual enemy return times and multiplayer rank value.
|
|
5
|
+
// Search has a soft 4 ms wall-clock budget, leaving room for protocol overhead.
|
|
6
|
+
#include <algorithm>
|
|
7
|
+
#include <array>
|
|
8
|
+
#include <chrono>
|
|
9
|
+
#include <cmath>
|
|
10
|
+
#include <cstdint>
|
|
11
|
+
#include <deque>
|
|
12
|
+
#include <iostream>
|
|
13
|
+
#include <limits>
|
|
14
|
+
#include <memory>
|
|
15
|
+
#include <queue>
|
|
16
|
+
#include <string>
|
|
17
|
+
#include <utility>
|
|
18
|
+
#include <vector>
|
|
19
|
+
using namespace std;
|
|
20
|
+
namespace territory {
|
|
21
|
+
constexpr int V=2304, INF=10000;
|
|
22
|
+
const int dx[4]={0,0,-1,1},dy[4]={-1,1,0,0};
|
|
23
|
+
const char dc[5]="UDLR";
|
|
24
|
+
struct Player { int x=0,y=0,dir=0,len=0,area=0,deaths=0; };
|
|
25
|
+
struct State {int turn=0; array<Player,4> p; array<int,V> own{},tr{};};
|
|
26
|
+
struct Candidate {double score; int anchor,d,s,a,b,c=-1;};
|
|
27
|
+
struct Eval { double value=0; int gain=0,len=0,margin=INF,approach=0; bool valid=false; vector<int> path; };
|
|
28
|
+
struct Bot {
|
|
29
|
+
int W,H,N,me,T,S,spawn[4],initdir[4],nb[V][4],protect[V];
|
|
30
|
+
int enemy[4][V],danger[V],home[V],prev[V],pd[V],reach[V],estate[V];
|
|
31
|
+
int nxtOwn[V][4],rayMin[V][4][49];
|
|
32
|
+
double weight[V],psum[49][49];
|
|
33
|
+
vector<int> plan; int expected=-1,lastDeaths=0,lastLen=0,planAge=0; int optimism=8; int baseOptimism=-1; deque<int> recentDeaths; bool safetyGate=false, preplan=true, adaptive=true, bridges=true; double attackScale=1.0, efficiency=-1.0, baseEfficiency=-2.0; bool rankAware=true, smartHunt=true, altReturns=false, navigation=false, cautiousHunt=true; double compactness=0.0, edgeValue=0.0; int entry=-1; double importance[4], threatValue[4], huntScore=0; int enemyRet[4];
|
|
34
|
+
State st; uint64_t randomState=73192871;
|
|
35
|
+
chrono::steady_clock::time_point began; int evaluated=0;
|
|
36
|
+
Bot(int w,int h,int n,int m,int turns,const vector<int>& sp):W(w),H(h),N(n),me(m),T(turns),S(w*h){
|
|
37
|
+
cautiousHunt=true;if(N==4)attackScale=0.9;
|
|
38
|
+
for(int p=0;p<N;p++)spawn[p]=sp[p],initdir[p]=0;
|
|
39
|
+
for(int k=0;k<S;k++) { int x=k%W,y=k/W; protect[k]=-1;for(int d=0;d<4;d++){int xx=x+dx[d],yy=y+dy[d];nb[k][d]=(xx<0||yy<0||xx>=W||yy>=H)?-1:yy*W+xx;}for(int p=0;p<N;p++)if(abs(x-spawn[p]%W)<=1&&abs(y-spawn[p]/W)<=1)protect[k]=p; }
|
|
40
|
+
}
|
|
41
|
+
int pos(int p)const{return st.p[p].y*W+st.p[p].x;}
|
|
42
|
+
int man(int a,int b)const{return abs(a%W-b%W)+abs(a/W-b/W);}
|
|
43
|
+
uint32_t rnd(){randomState^=randomState<<13;randomState^=randomState>>7;randomState^=randomState<<17;return uint32_t(randomState);}
|
|
44
|
+
bool expired(){return chrono::duration<double,milli>(chrono::steady_clock::now()-began).count()>4.0;}
|
|
45
|
+
// Shortest opponent arrival times. Its old trail is impassable until it returns home.
|
|
46
|
+
void enemyFields(){
|
|
47
|
+
fill(danger,danger+S,INF);
|
|
48
|
+
for(int p=0;p<N;p++)if(p!=me){
|
|
49
|
+
int dis[2*V],q[2*V],a=0,b=0;fill(dis,dis+2*S,INF);
|
|
50
|
+
int start=pos(p),mode=st.p[p].len==0;dis[start+mode*S]=0;
|
|
51
|
+
for(int d=0;d<4;d++)if(d!=(st.p[p].dir^1)){
|
|
52
|
+
int v=nb[start][d];if(v<0||(!mode&&st.tr[v]==p))continue;
|
|
53
|
+
int u=v+(mode||st.own[v]==p)*S;
|
|
54
|
+
if(dis[u]>1)dis[u]=1,q[b++]=u;
|
|
55
|
+
}
|
|
56
|
+
while(a<b){int u=q[a++],k=u%S,clear=u>=S;
|
|
57
|
+
for(int d=0;d<4;d++){int v=nb[k][d];if(v<0||(!clear&&st.tr[v]==p))continue;int v2=v+(clear||st.own[v]==p)*S;if(dis[v2]>dis[u]+1){dis[v2]=dis[u]+1;q[b++]=v2;}}
|
|
58
|
+
}
|
|
59
|
+
for(int k=0;k<S;k++){
|
|
60
|
+
enemy[p][k]=min(dis[k],dis[k+S]);
|
|
61
|
+
// A player can deliberately reset; do not assume an undefended spawn stays empty.
|
|
62
|
+
int reset=man(start,spawn[p])>8?8:INF;
|
|
63
|
+
enemy[p][k]=min(enemy[p][k],reset+man(spawn[p],k));
|
|
64
|
+
danger[k]=min(danger[k],enemy[p][k]);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
void homeField(){
|
|
69
|
+
int q[V],a=0,b=0;fill(home,home+S,INF);
|
|
70
|
+
for(int k=0;k<S;k++)if(st.own[k]==me&&st.tr[k]!=me)home[k]=0,q[b++]=k;
|
|
71
|
+
while(a<b){int k=q[a++];for(int d=0;d<4;d++){int v=nb[k][d];if(v>=0&&st.tr[v]!=me&&home[v]>home[k]+1){home[v]=home[k]+1;q[b++]=v;}}}
|
|
72
|
+
}
|
|
73
|
+
bool moveSafe(int k,int d,int heading)const {return d!=(heading^1)&&nb[k][d]>=0&&st.tr[nb[k][d]]!=me;}
|
|
74
|
+
bool collision(int k,int d)const{
|
|
75
|
+
int v=nb[k][d];if(v<0)return true;
|
|
76
|
+
for(int p=0;p<N;p++)if(p!=me){int e=pos(p);for(int z=0;z<4;z++)if(z!=(st.p[p].dir^1)&&nb[e][z]>=0&&st.tr[nb[e][z]]!=p){int t=nb[e][z];if(t==v||(v==e&&t==k))return true;}}
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
vector<int> returnPath(const vector<int>& prefix={}){
|
|
80
|
+
int blocked[V]={0},k=pos(me),heading=st.p[me].dir;
|
|
81
|
+
for(int v=0;v<S;v++)blocked[v]=st.tr[v]==me;
|
|
82
|
+
bool outside=st.p[me].len>0;
|
|
83
|
+
for(int d:prefix){if(d==(heading^1)||nb[k][d]<0||blocked[nb[k][d]])return {};k=nb[k][d];heading=d;if(st.own[k]==me&&outside)return prefix;if(st.own[k]!=me)blocked[k]=1,outside=true;}
|
|
84
|
+
int dis[V],par[V],pdir[V],q[V],a=0,b=0;fill(dis,dis+S,INF);dis[k]=0;
|
|
85
|
+
for(int d=0;d<4;d++)if(d!=(heading^1)){int v=nb[k][d];if(v<0||blocked[v]||(prefix.empty()&&collision(k,d)))continue;dis[v]=1;par[v]=k;pdir[v]=d;q[b++]=v;}
|
|
86
|
+
int end=-1;
|
|
87
|
+
while(a<b){int u=q[a++];if(st.own[u]==me){end=u;break;}
|
|
88
|
+
// Prefer the side farther away from the enemy among equally short returns.
|
|
89
|
+
int dirs[4]={0,1,2,3};sort(dirs,dirs+4,[&](int d,int e){int v=nb[u][d],w=nb[u][e];return (v<0?-INF:danger[v])>(w<0?-INF:danger[w]);});
|
|
90
|
+
for(int d:dirs){int v=nb[u][d];if(v<0||blocked[v]||dis[v]!=INF)continue;dis[v]=dis[u]+1;par[v]=u;pdir[v]=d;q[b++]=v;}
|
|
91
|
+
}
|
|
92
|
+
if(end<0)return {};vector<int> tail;for(int v=end;v!=k;v=par[v])tail.push_back(pdir[v]);reverse(tail.begin(),tail.end());vector<int> out=prefix;out.insert(out.end(),tail.begin(),tail.end());return out;
|
|
93
|
+
}
|
|
94
|
+
vector<vector<int>> contourReturns(){
|
|
95
|
+
vector<vector<int>> results;int dis[V],q[V],a=0,b=0;fill(dis,dis+S,INF);
|
|
96
|
+
for(int k=0;k<S;k++)if(st.own[k]==me&&st.tr[k]!=me)dis[k]=0,q[b++]=k;
|
|
97
|
+
while(a<b){int u=q[a++];for(int d=0;d<4;d++){int v=nb[u][d];if(v>=0&&st.tr[v]!=me&&dis[v]==INF)dis[v]=dis[u]+1,q[b++]=v;}}
|
|
98
|
+
int anchor=entry>=0?entry:spawn[me];auto cross=[&](int u,int v){return (u%W)*(v/W)-(v%W)*(u/W);};
|
|
99
|
+
int start=pos(me),minimum=INF;for(int d=0;d<4;d++)if(moveSafe(start,d,st.p[me].dir)&&!collision(start,d))minimum=min(minimum,dis[nb[start][d]]+1);
|
|
100
|
+
if(minimum>=INF)return results;
|
|
101
|
+
for(int sign:{-1,1}){
|
|
102
|
+
int val[V],follow[V];fill(val,val+S,-100000000);
|
|
103
|
+
for(int i=0;i<b;i++){int u=q[i];if(dis[u]==0){val[u]=sign*cross(u,anchor);continue;}
|
|
104
|
+
for(int d=0;d<4;d++){int v=nb[u][d];if(v>=0&&dis[v]+1==dis[u]){int z=val[v]+sign*cross(u,v);if(z>val[u])val[u]=z,follow[u]=d;}}
|
|
105
|
+
}
|
|
106
|
+
int first=-1,best=-100000000;
|
|
107
|
+
for(int d=0;d<4;d++)if(moveSafe(start,d,st.p[me].dir)&&!collision(start,d)){int v=nb[start][d];if(dis[v]+1==minimum){int z=val[v]+sign*cross(start,v);if(z>best)best=z,first=d;}}
|
|
108
|
+
if(first<0)continue;vector<int> path{first};int u=nb[start][first];while(dis[u]>0){int d=follow[u];path.push_back(d);u=nb[u][d];}results.push_back(path);
|
|
109
|
+
}
|
|
110
|
+
return results;
|
|
111
|
+
}
|
|
112
|
+
Eval evaluate(const vector<int>& moves,bool flood=true){
|
|
113
|
+
Eval e;if(moves.empty())return e;
|
|
114
|
+
int mark[V]={0},k=pos(me),heading=st.p[me].dir;bool out=st.p[me].len>0;int risk=INF;
|
|
115
|
+
for(int u=0;u<S;u++)if(st.tr[u]==me){mark[u]=1;risk=min(risk,danger[u]);}
|
|
116
|
+
int n=0;for(int d:moves){if(d==(heading^1)||nb[k][d]<0)return e;k=nb[k][d];heading=d;if(mark[k])return e;n++;e.path.push_back(d);
|
|
117
|
+
if(n==1&&collision(pos(me),d))risk=min(risk,0);
|
|
118
|
+
if(st.own[k]==me){if(out)break;}else {if(!out)e.approach=n-1;out=true;mark[k]=1;risk=min(risk,danger[k]);}
|
|
119
|
+
}
|
|
120
|
+
if(!out||st.own[k]!=me||n>T-st.turn)return e;
|
|
121
|
+
e.valid=true;e.len=n;e.margin=risk-n;
|
|
122
|
+
if(!flood)return e;
|
|
123
|
+
int seen[V]={0},q[V],a=0,b=0;
|
|
124
|
+
auto add=[&](int u){if(!seen[u]&&!mark[u]&&st.own[u]!=me){seen[u]=1;q[b++]=u;}};
|
|
125
|
+
for(int x=0;x<W;x++)add(x),add((H-1)*W+x);
|
|
126
|
+
for(int y=0;y<H;y++)add(y*W),add(y*W+W-1);
|
|
127
|
+
while(a<b){int u=q[a++];for(int d=0;d<4;d++){int v=nb[u][d];if(v>=0)add(v);}}
|
|
128
|
+
for(int u=0;u<S;u++)if((mark[u]||!seen[u])&&st.own[u]!=me&&(protect[u]<0||protect[u]==me)){e.gain++;e.value+=weight[u];}
|
|
129
|
+
if(compactness>0){
|
|
130
|
+
int delta=0;auto after=[&](int u){return st.own[u]==me||((mark[u]||!seen[u])&&(protect[u]<0||protect[u]==me));};
|
|
131
|
+
for(int u=0;u<S;u++)for(int d:{1,3}){int v=nb[u][d];if(v>=0)delta+=(after(u)!=after(v))-((st.own[u]==me)!=(st.own[v]==me));}
|
|
132
|
+
e.value-=compactness*delta;
|
|
133
|
+
}
|
|
134
|
+
return e;
|
|
135
|
+
}
|
|
136
|
+
double utility(const Eval&e)const{
|
|
137
|
+
if(!e.valid||e.gain==0)return -1e9;
|
|
138
|
+
int slack=e.margin+optimism+(navigation?int(e.approach*0.8):0); double risk=slack>=2?1.0:slack>=0?0.86:slack>=-2?0.48:slack>=-4?0.17:0.025;
|
|
139
|
+
return e.value* risk/pow(e.len+4.0,efficiency);
|
|
140
|
+
}
|
|
141
|
+
vector<int> approach(int anchor){vector<int> path;for(int k=anchor;k!=pos(me);k=prev[k])path.push_back(pd[k]);reverse(path.begin(),path.end());return path;}
|
|
142
|
+
void prepPlan(){
|
|
143
|
+
int q[V],a=0,b=0,k=pos(me);fill(reach,reach+S,INF);reach[k]=0;estate[k]=st.p[me].dir;q[b++]=k;
|
|
144
|
+
while(a<b){int u=q[a++];for(int d=0;d<4;d++){if(d==(estate[u]^1))continue;int v=nb[u][d];if(v<0||st.own[v]!=me||st.tr[v]==me||reach[v]!=INF)continue;if(u==k&&collision(k,d))continue;reach[v]=reach[u]+1;prev[v]=u;pd[v]=d;estate[v]=d;q[b++]=v;}}
|
|
145
|
+
for(int u=0;u<S;u++)for(int d=0;d<4;d++){
|
|
146
|
+
nxtOwn[u][d]=INF;rayMin[u][d][0]=INF;int v=u,mn=INF;
|
|
147
|
+
for(int len=1;len<=48;len++){v=v<0?-1:nb[v][d];if(v<0){rayMin[u][d][len]=-INF;continue;}if(st.own[v]==me&&nxtOwn[u][d]==INF)nxtOwn[u][d]=len;if(st.own[v]!=me)mn=min(mn,danger[v]);rayMin[u][d][len]=mn;}
|
|
148
|
+
}
|
|
149
|
+
for(int y=0;y<=H;y++)for(int x=0;x<=W;x++)psum[y][x]=0;
|
|
150
|
+
for(int y=0;y<H;y++)for(int x=0;x<W;x++)psum[y+1][x+1]=weight[y*W+x]+psum[y][x+1]+psum[y+1][x]-psum[y][x];
|
|
151
|
+
}
|
|
152
|
+
double rect(int x1,int y1,int x2,int y2){if(x1>x2)swap(x1,x2);if(y1>y2)swap(y1,y2);return psum[y2+1][x2+1]-psum[y1][x2+1]-psum[y2+1][x1]+psum[y1][x1];}
|
|
153
|
+
vector<int> expand(){
|
|
154
|
+
prepPlan();vector<pair<double,pair<int,int>>> anchors;
|
|
155
|
+
for(int k=0;k<S;k++)if(reach[k]<INF)for(int d=0;d<4;d++){int v=nb[k][d];if(v<0||st.own[v]==me||d==(estate[k]^1))continue;
|
|
156
|
+
double potential=0;for(int a=1;a<=8;a++)for(int b=-5;b<=5;b++){int x=k%W+dx[d]*a+(d<2?b:0),y=k/W+dy[d]*a+(d>=2?b:0);if(x>=0&&y>=0&&x<W&&y<H)potential+=weight[y*W+x];}
|
|
157
|
+
double score=potential/(reach[k]+8.0)*min(1.0,max(0.1,(danger[v]-(navigation?0.2:1.0)*reach[k])/18.0));anchors.push_back({score,{k,d}});
|
|
158
|
+
}
|
|
159
|
+
sort(anchors.begin(),anchors.end(),[](auto&a,auto&b){return a.first>b.first;});
|
|
160
|
+
vector<pair<int,int>> chosen;int used[12][12][4]={0};
|
|
161
|
+
for(auto item:anchors){int k=item.second.first,d=item.second.second;if(used[k/W/4][k%W/4][d]++>0)continue;chosen.push_back({k,d});if(chosen.size()>=52)break;}
|
|
162
|
+
int slot[V][4];for(int k=0;k<S;k++)for(int d=0;d<4;d++)slot[k][d]=-1;vector<array<Candidate,3>> diverse(chosen.size());for(int i=0;i<(int)chosen.size();i++){slot[chosen[i].first][chosen[i].second]=i;for(auto& c:diverse[i])c.score=-1;}
|
|
163
|
+
vector<Candidate> best;best.reserve(180);
|
|
164
|
+
auto keep=[&](Candidate c){int id=slot[c.anchor][c.d];if(id>=0){auto& bucket=diverse[id];if(c.score>bucket[2].score){bucket[2]=c;sort(bucket.begin(),bucket.end(),[](auto&a,auto&b){return a.score>b.score;});}}if(best.size()<60){best.push_back(c);push_heap(best.begin(),best.end(),[](auto&a,auto&b){return a.score>b.score;});}else if(c.score>best.front().score){pop_heap(best.begin(),best.end(),[](auto&a,auto&b){return a.score>b.score;});best.back()=c;push_heap(best.begin(),best.end(),[](auto&a,auto&b){return a.score>b.score;});}};
|
|
165
|
+
for(auto [k,d]:chosen){if(expired())break;int x=k%W,y=k/W;
|
|
166
|
+
for(int a=1;a<=min(26,nxtOwn[k][d]-1);a++){
|
|
167
|
+
int xx=x+dx[d]*a,yy=y+dy[d]*a;if(xx<0||yy<0||xx>=W||yy>=H)break;int corner=yy*W+xx;
|
|
168
|
+
for(int s=0;s<4;s++)if((s<2)!=(d<2))for(int b=1;b<=28;b++){
|
|
169
|
+
int x2=xx+dx[s]*b,y2=yy+dy[s]*b;if(x2<0||y2<0||x2>=W||y2>=H)break;int corner2=y2*W+x2;
|
|
170
|
+
// Do not march through home and accidentally start a second excursion.
|
|
171
|
+
if(nxtOwn[corner][s]<b)break;
|
|
172
|
+
int c=min(a,nxtOwn[corner2][d^1]);int end=corner2+(dx[d^1]+W*dy[d^1])*c;
|
|
173
|
+
int back=st.own[end]==me?0:min(b,nxtOwn[end][s^1]);
|
|
174
|
+
int len=reach[k]+a+b+c+back;if(nxtOwn[corner][s]==b)len=reach[k]+a+b,c=back=0;
|
|
175
|
+
if(len>T-st.turn)continue;
|
|
176
|
+
int risk=min(rayMin[k][d][a],rayMin[corner][s][b]);if(c)risk=min(risk,rayMin[corner2][d^1][c]);if(back)risk=min(risk,rayMin[end][s^1][back]);int margin=risk-len+optimism+(navigation?int(reach[k]*0.8):0);
|
|
177
|
+
if(margin < -2)continue;
|
|
178
|
+
double val=rect(x,y,x2,y2);double factor=margin>=2?1.0:margin>=0?0.86:0.48;
|
|
179
|
+
double score=val*factor/pow(len+4.0,efficiency);if(score>0)keep({score,k,d,s,a,b});
|
|
180
|
+
int full=nxtOwn[corner2][d^1];
|
|
181
|
+
if(full>a&&full<=32&&nxtOwn[corner][s]>b){
|
|
182
|
+
int finish=corner2+(dx[d^1]+W*dy[d^1])*full;
|
|
183
|
+
int ll=reach[k]+a+b+full,rr=min(min(rayMin[k][d][a],rayMin[corner][s][b]),rayMin[corner2][d^1][full]);int mm=rr-ll+optimism;
|
|
184
|
+
if(ll<=T-st.turn&&mm>=-2){int fx=finish%W,fy=finish/W;double vv=rect(min({x,x2,fx}),min({y,y2,fy}),max({x,x2,fx}),max({y,y2,fy}));double ff=mm>=2?1.0:mm>=0?0.86:0.48;keep({vv*ff/pow(ll+4.0,efficiency),k,d,s,a,b,full});}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
vector<Candidate> bridge;
|
|
190
|
+
if(bridges)for(auto [k,d]:chosen){
|
|
191
|
+
if(expired())break;
|
|
192
|
+
int dis[V],q[V],head=0,tail=0;fill(dis,dis+S,INF);dis[k]=0;q[tail++]=k;
|
|
193
|
+
while(head<tail){int u=q[head++];for(int z=0;z<4;z++){int v=nb[u][z];if(v>=0&&st.own[v]==me&&dis[v]==INF)dis[v]=dis[u]+1,q[tail++]=v;}}
|
|
194
|
+
auto addBridge=[&](int a,int b,int side,int endpoint,int risk){
|
|
195
|
+
int len=reach[k]+a+b,margin=risk-len+optimism+(navigation?int(reach[k]*0.8):0);if(len>T-st.turn||margin < -2||dis[endpoint]>=INF)return;
|
|
196
|
+
int detour=dis[endpoint]-a-b;if(detour<2&&b!=0)return;
|
|
197
|
+
double val=max(1.0,detour*(a+b-1)*0.45)+(a+b-1);
|
|
198
|
+
double factor=margin>=2?1.0:margin>=0?0.86:0.48;
|
|
199
|
+
bridge.push_back({val*factor/pow(len+4.0,efficiency),k,d,side,a,b});
|
|
200
|
+
};
|
|
201
|
+
int straight=nxtOwn[k][d];if(straight<=30){int end=k+(dx[d]+W*dy[d])*straight;addBridge(straight,0,d<2?2:0,end,rayMin[k][d][straight]);}
|
|
202
|
+
int u=k;for(int a=1;a<=min(20,straight-1);a++){
|
|
203
|
+
u=nb[u][d];if(u<0)break;
|
|
204
|
+
for(int side=0;side<4;side++)if((side<2)!=(d<2)){
|
|
205
|
+
int b=nxtOwn[u][side];if(b>24)continue;int end=u+(dx[side]+W*dy[side])*b;
|
|
206
|
+
addBridge(a,b,side,end,min(rayMin[k][d][a],rayMin[u][side][b]));
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
sort(bridge.begin(),bridge.end(),[](auto&a,auto&b){return a.score>b.score;});if(bridge.size()>24)bridge.resize(24);
|
|
211
|
+
sort(best.begin(),best.end(),[](auto&a,auto&b){return a.score>b.score;});best.insert(best.end(),bridge.begin(),bridge.end());for(auto bucket:diverse)for(auto c:bucket)if(c.score>0)best.push_back(c);
|
|
212
|
+
vector<int> result;double highest=-1;vector<uint64_t> fingerprints;
|
|
213
|
+
for(auto c:best){if(evaluated>=8&&expired())break;uint64_t key=((((uint64_t(c.anchor)*4+c.d)*4+c.s)*64+c.a)*64+c.b)*64+(c.c+1);if(find(fingerprints.begin(),fingerprints.end(),key)!=fingerprints.end())continue;fingerprints.push_back(key);vector<int> path=approach(c.anchor);for(int i=0;i<c.a;i++)path.push_back(c.d);for(int i=0;i<c.b;i++)path.push_back(c.s);for(int i=0;i<(c.c<0?c.a:c.c);i++)path.push_back(c.d^1);if(c.c<0)for(int i=0;i<c.b;i++)path.push_back(c.s^1);
|
|
214
|
+
Eval e=evaluate(path);evaluated++;double score=utility(e);if(score>highest){highest=score;result=e.path;}
|
|
215
|
+
}
|
|
216
|
+
if(result.empty()){for(auto [anchor,d]:chosen)if(reach[anchor]>0){result=approach(anchor);break;}}
|
|
217
|
+
return result;
|
|
218
|
+
}
|
|
219
|
+
void opponentValues(){
|
|
220
|
+
double sum=0;for(int p=0;p<N;p++)if(p!=me){double scale=max(45.0,(T-st.turn)*0.18);double x=min(20.0,abs(st.p[me].area-st.p[p].area)/scale);double e=exp(-x);importance[p]=rankAware?e/(1+e)/(1+e):1.0;sum+=importance[p];}
|
|
221
|
+
for(int p=0;p<N;p++)if(p!=me)importance[p]/=sum;
|
|
222
|
+
for(int p=0;p<N;p++)if(p!=me){enemyRet[p]=0;threatValue[p]=0;if(!st.p[p].len)continue;
|
|
223
|
+
int q[V],dis[V],par[V],a=0,b=0;fill(dis,dis+S,INF);int start=pos(p);dis[start]=0;
|
|
224
|
+
for(int d=0;d<4;d++)if(d!=(st.p[p].dir^1)){int v=nb[start][d];if(v<0||st.tr[v]==p)continue;dis[v]=1;par[v]=start;q[b++]=v;}
|
|
225
|
+
int end=-1;
|
|
226
|
+
while(a<b){int u=q[a++];if(st.own[u]==p){end=u;break;}for(int d=0;d<4;d++){int v=nb[u][d];if(v<0||st.tr[v]==p||dis[v]!=INF)continue;dis[v]=dis[u]+1;par[v]=u;q[b++]=v;}}
|
|
227
|
+
if(end<0){enemyRet[p]=INF;continue;}enemyRet[p]=dis[end];
|
|
228
|
+
int mark[V]={0},seen[V]={0};for(int u=0;u<S;u++)mark[u]=st.tr[u]==p||st.own[u]==p;
|
|
229
|
+
for(int u=end;u!=start;u=par[u])mark[u]=1;
|
|
230
|
+
a=b=0;auto add=[&](int u){if(!mark[u]&&!seen[u])seen[u]=1,q[b++]=u;};
|
|
231
|
+
for(int x=0;x<W;x++)add(x),add((H-1)*W+x);for(int y=0;y<H;y++)add(y*W),add(y*W+W-1);
|
|
232
|
+
while(a<b){int u=q[a++];for(int d=0;d<4;d++){int v=nb[u][d];if(v>=0)add(v);}}
|
|
233
|
+
double gain=0,otherBenefit=0;int intrusion=0;
|
|
234
|
+
for(int u=0;u<S;u++){if(st.tr[u]==p&&st.own[u]==me)intrusion++;if(st.own[u]!=p&&(mark[u]||!seen[u])&&(protect[u]<0||protect[u]==p)){gain+=importance[p];if(st.own[u]==me)gain+=1.0;else if(st.own[u]>=0){gain-=importance[st.own[u]];otherBenefit+=importance[st.own[u]];}}}
|
|
235
|
+
double length=st.p[p].len+enemyRet[p];
|
|
236
|
+
threatValue[p]=N==4?max(0.0,gain+importance[p]*(length*0.25+3.0)+intrusion*0.5):max(0.0,max(gain,importance[p]*length*length/20.0-otherBenefit)+importance[p]*(length*0.6+6.0)+intrusion*0.5);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
vector<int> hunt(){
|
|
240
|
+
int k=pos(me),dis[V],par[V],pdir[V],q[V],risk[V],a=0,b=0;fill(dis,dis+S,INF);fill(risk,risk+S,-INF);dis[k]=0;int initialRisk=INF;for(int u=0;u<S;u++)if(st.tr[u]==me)initialRisk=min(initialRisk,danger[u]);risk[k]=initialRisk;
|
|
241
|
+
for(int d=0;d<4;d++)if(moveSafe(k,d,st.p[me].dir)){int v=nb[k][d];dis[v]=1;par[v]=k;pdir[v]=d;risk[v]=min(initialRisk,st.own[v]==me?INF:danger[v]);q[b++]=v;}
|
|
242
|
+
while(a<b){int u=q[a++];if(dis[u]>=30)continue;for(int d=0;d<4;d++){int v=nb[u][d];if(v<0||st.tr[v]==me)continue;int r=min(risk[u],st.own[v]==me?INF:danger[v]);if(dis[v]==INF){dis[v]=dis[u]+1;par[v]=u;pdir[v]=d;risk[v]=r;q[b++]=v;}else if(dis[v]==dis[u]+1&&r>risk[v]){par[v]=u;pdir[v]=d;risk[v]=r;}}}
|
|
243
|
+
double best=0;int target=-1;huntScore=0;
|
|
244
|
+
for(int p=0;p<N;p++)if(p!=me&&st.p[p].len){
|
|
245
|
+
int ret=enemyRet[p];if(ret>T-st.turn)continue;
|
|
246
|
+
int nearest=INF,end=-1;for(int u=0;u<S;u++)if(st.tr[u]==p&&dis[u]<nearest&&(!cautiousHunt||dis[u]<=1||risk[u]>=dis[u]))nearest=dis[u],end=u;
|
|
247
|
+
if(end<0||nearest>ret+10||nearest>(nearest<=ret||(smartHunt&&threatValue[p]>90)?26:16)||nearest>T-st.turn)continue;
|
|
248
|
+
double value=(st.p[p].len+ret)*0.8+8;
|
|
249
|
+
if(st.p[p].area>=st.p[me].area-30)value*=1.3;
|
|
250
|
+
int intrusion=0;for(int u=0;u<S;u++)if(st.tr[u]==p&&st.own[u]==me)intrusion++;
|
|
251
|
+
value+=intrusion*2;
|
|
252
|
+
double prob=nearest<=ret?1.0:max(0.15,1.0-(nearest-ret)*0.12);
|
|
253
|
+
double score=smartHunt?threatValue[p]*prob/pow(nearest+4.0,efficiency):value/(nearest+3.0);if(nearest==1)score+=smartHunt?2.0:10.0;
|
|
254
|
+
if(score>best){best=score;target=end;}
|
|
255
|
+
}
|
|
256
|
+
huntScore=best;if(target<0)return {};vector<int> result;for(int v=target;v!=k;v=par[v])result.push_back(pdir[v]);reverse(result.begin(),result.end());return result;
|
|
257
|
+
}
|
|
258
|
+
int fallback(){
|
|
259
|
+
int k=pos(me),best=st.p[me].dir;double val=-1e9;
|
|
260
|
+
for(int d=0;d<4;d++)if(moveSafe(k,d,st.p[me].dir)){int v=nb[k][d];double z=0;z+=(st.own[v]==me?10:0);z-=home[v]*2;z+=min(20,danger[v])*0.15;if(collision(k,d))z-=100;int exits=0;for(int s=0;s<4;s++)if(moveSafe(v,s,d))exits++;z+=exits;z+=(d==st.p[me].dir?0.05:0);if(z>val)val=z,best=d;}return best;
|
|
261
|
+
}
|
|
262
|
+
int decide(const State& state){
|
|
263
|
+
began=chrono::steady_clock::now();evaluated=0;st=state;int k=pos(me);
|
|
264
|
+
if(baseEfficiency < -1.0)baseEfficiency=efficiency; if(baseEfficiency<0){int filled=0;for(int u=0;u<S;u++)filled+=st.own[u]>=0;efficiency=0.82+0.22*filled/S;}else efficiency=baseEfficiency;
|
|
265
|
+
if(st.turn==0)for(int p=0;p<N;p++)initdir[p]=st.p[p].dir;
|
|
266
|
+
if(baseOptimism<0)baseOptimism=optimism;if(st.p[me].deaths>lastDeaths)recentDeaths.push_back(st.turn);while(!recentDeaths.empty()&&recentDeaths.front()<st.turn-80)recentDeaths.pop_front();optimism=max(0,baseOptimism-max(0,int(recentDeaths.size())-1)*2);
|
|
267
|
+
if(expected!=k||lastDeaths!=st.p[me].deaths||(lastLen>0&&st.p[me].len==0))plan.clear();
|
|
268
|
+
if(st.p[me].len==0)entry=k;
|
|
269
|
+
lastDeaths=st.p[me].deaths;lastLen=st.p[me].len;enemyFields();homeField();opponentValues();
|
|
270
|
+
for(int u=0;u<S;u++){weight[u]=0;if(st.own[u]!=me&&(protect[u]<0||protect[u]==me)){weight[u]=st.own[u]<0?1.0:(rankAware?1.0+importance[st.own[u]]:(N==2?1.9:1.55));int edge=min(min(u%W,W-1-u%W),min(u/W,H-1-u/W));weight[u]*=1.0+edgeValue*(edge==0?1.0:edge==1?0.3:edge==2?0.1:0.0);}}
|
|
271
|
+
auto finish=[&](int d){expected=nb[k][d];return d;};
|
|
272
|
+
if(preplan && st.p[me].len==0 && plan.empty()){plan=expand();planAge=0;}
|
|
273
|
+
vector<int> attack=hunt();
|
|
274
|
+
if(!attack.empty()){
|
|
275
|
+
// A guaranteed cut can justify abandoning a modest unfinished excursion.
|
|
276
|
+
Eval current=evaluate(plan);double expansion=current.valid?utility(current):0;
|
|
277
|
+
int target=k;for(int d:attack)target=nb[target][d];int p=st.tr[target];
|
|
278
|
+
double av=smartHunt?huntScore:(p>=0?(st.p[p].len*2.0+st.p[p].len*st.p[p].len/14.0+12.0)/(attack.size()+3.0):0);
|
|
279
|
+
Eval immediate=evaluate(returnPath());bool bank=immediate.valid&&immediate.len==1&&immediate.margin>=1&&immediate.value>av*3.5;
|
|
280
|
+
if(!bank&&(attack.size()==1||(av*attackScale>expansion*1.15+0.5))){
|
|
281
|
+
plan.clear();return finish(attack.front());
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
if(st.p[me].len==0){
|
|
285
|
+
if(plan.empty()||planAge>=4){vector<int> fresh=expand();Eval old=evaluate(plan);Eval next=evaluate(fresh);if(utility(next)>utility(old)*1.05||!old.valid)plan=next.valid?next.path:fresh;planAge=0;}
|
|
286
|
+
else {Eval old=evaluate(plan,false);if(!old.valid||old.margin < -optimism){plan=expand();planAge=0;}}
|
|
287
|
+
}else{
|
|
288
|
+
Eval current=evaluate(plan);vector<int> bestPath=current.path;double best=utility(current);
|
|
289
|
+
vector<int> ret=returnPath();Eval fast=evaluate(ret); if(altReturns)for(auto path:contourReturns()){Eval e=evaluate(path);if(utility(e)>utility(fast))fast=e;}double score=utility(fast);
|
|
290
|
+
// Keep productive loops, but shorten immediately if an opponent can cut them.
|
|
291
|
+
if(score>best*1.07||!current.valid||(fast.valid&&fast.margin<=2&&fast.margin>current.margin+1)){bestPath=fast.path;best=score;}
|
|
292
|
+
if(current.valid&¤t.margin<3){
|
|
293
|
+
vector<int> prefix;for(int i=0;i<min(10,(int)current.path.size()-1);i++){
|
|
294
|
+
prefix.push_back(current.path[i]);if(i%2)continue;Eval e=evaluate(returnPath(prefix));double u=utility(e);if(u>best*1.05){best=u;bestPath=e.path;}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
if(adaptive && (st.turn%2==0 || !current.valid) && !expired()){
|
|
298
|
+
int start=pos(me),heading=st.p[me].dir,trailRisk=INF;for(int u=0;u<S;u++)if(st.tr[u]==me)trailRisk=min(trailRisk,danger[u]);
|
|
299
|
+
vector<int> directions;if(!bestPath.empty())directions.push_back(bestPath.front());directions.push_back(heading);for(int d=0;d<4;d++)directions.push_back(d);bool tried[4]={false,false,false,false};
|
|
300
|
+
for(int d:directions)if(d!=(heading^1)&&!tried[d]){tried[d]=true;
|
|
301
|
+
vector<int> prefix;int u=start,prefixRisk=trailRisk;
|
|
302
|
+
for(int a=1;a<=10;a++){
|
|
303
|
+
u=nb[u][d];if(u<0||st.tr[u]==me||st.own[u]==me)break;prefix.push_back(d);prefixRisk=min(prefixRisk,danger[u]);
|
|
304
|
+
if(a+home[u]>prefixRisk+optimism+2)continue;
|
|
305
|
+
if(a>4 && a%2)continue;
|
|
306
|
+
Eval direct=evaluate(returnPath(prefix));double val=utility(direct);if(val>best*1.08){best=val;bestPath=direct.path;}
|
|
307
|
+
for(int side=0;side<4;side++)if((side<2)!=(d<2)){
|
|
308
|
+
vector<int> pp=prefix;int v=u,sideRisk=prefixRisk;
|
|
309
|
+
for(int b=1;b<=8;b++){ if(expired())break;
|
|
310
|
+
v=nb[v][side];if(v<0||st.tr[v]==me)break;pp.push_back(side);if(st.own[v]!=me)sideRisk=min(sideRisk,danger[v]);
|
|
311
|
+
if(a+b+home[v]>sideRisk+optimism+2){if(st.own[v]==me)break;continue;}
|
|
312
|
+
if(b>3&&b%2)continue;
|
|
313
|
+
Eval e=evaluate(returnPath(pp));double z=utility(e);if(z>best*1.08){best=z;bestPath=e.path;}
|
|
314
|
+
if(st.own[v]==me)break;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if(expired())break;
|
|
318
|
+
}
|
|
319
|
+
if(expired())break;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if(safetyGate && !bestPath.empty()){Eval escape=evaluate(returnPath(vector<int>{bestPath.front()})); if(!escape.valid||escape.margin<1){ if(fast.valid)bestPath=fast.path; }}
|
|
323
|
+
plan=bestPath;
|
|
324
|
+
}
|
|
325
|
+
planAge++;
|
|
326
|
+
if(!plan.empty()&&moveSafe(k,plan.front(),st.p[me].dir)&&!collision(k,plan.front())){int d=plan.front();plan.erase(plan.begin());return finish(d);}
|
|
327
|
+
plan.clear();return finish(fallback());
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
#ifndef BOT_LIBRARY
|
|
332
|
+
int main() {
|
|
333
|
+
ios::sync_with_stdio(false);
|
|
334
|
+
cin.tie(nullptr);
|
|
335
|
+
string token;
|
|
336
|
+
int W, H, turns, players, me, moveMs, initMs;
|
|
337
|
+
if (!(cin >> token >> W >> H >> turns >> players >> me >> moveMs >> initMs)) return 0;
|
|
338
|
+
vector<int> spawns(players);
|
|
339
|
+
for (int i = 0; i < players; ++i) {
|
|
340
|
+
int p, x, y;
|
|
341
|
+
cin >> token >> p >> x >> y;
|
|
342
|
+
spawns[p] = y * W + x;
|
|
343
|
+
}
|
|
344
|
+
// The search tables live on the heap, including on systems with small stacks.
|
|
345
|
+
auto bot = make_unique<territory::Bot>(W, H, players, me, turns, spawns);
|
|
346
|
+
territory::State state;
|
|
347
|
+
while (cin >> token >> state.turn) {
|
|
348
|
+
for (int i = 0; i < players; ++i) {
|
|
349
|
+
int p;
|
|
350
|
+
char direction;
|
|
351
|
+
territory::Player player;
|
|
352
|
+
cin >> token >> p >> player.x >> player.y >> direction
|
|
353
|
+
>> player.len >> player.area >> player.deaths;
|
|
354
|
+
player.dir = int(string("UDLR").find(direction));
|
|
355
|
+
state.p[p] = player;
|
|
356
|
+
}
|
|
357
|
+
cin >> token;
|
|
358
|
+
for (int y = 0; y < H; ++y) {
|
|
359
|
+
cin >> token;
|
|
360
|
+
for (int x = 0; x < W; ++x) state.own[y * W + x] = token[x] == '.' ? -1 : token[x] - '0';
|
|
361
|
+
}
|
|
362
|
+
cin >> token;
|
|
363
|
+
for (int y = 0; y < H; ++y) {
|
|
364
|
+
cin >> token;
|
|
365
|
+
for (int x = 0; x < W; ++x) state.tr[y * W + x] = token[x] == '.' ? -1 : token[x] - '0';
|
|
366
|
+
}
|
|
367
|
+
cin >> token;
|
|
368
|
+
if (!cin) break;
|
|
369
|
+
cout << state.turn << ' ' << territory::dc[bot->decide(state)] << endl;
|
|
370
|
+
}
|
|
371
|
+
return 0;
|
|
372
|
+
}
|
|
373
|
+
#endif
|