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,241 @@
|
|
|
1
|
+
// Final entry: coordinated opening supply routes, marginal terrain-clearing
|
|
2
|
+
// value, selective projectile pressure, and joint attack/defense allocation.
|
|
3
|
+
// Exact simultaneous-action matrices with three-turn tactical rollouts;
|
|
4
|
+
// CPU-budget guard retains a legal one-turn fallback.
|
|
5
|
+
#include "tank.hpp"
|
|
6
|
+
#include <algorithm>
|
|
7
|
+
#include <array>
|
|
8
|
+
#include <cmath>
|
|
9
|
+
#include <queue>
|
|
10
|
+
#include <vector>
|
|
11
|
+
#include <cstdio>
|
|
12
|
+
using namespace tank;
|
|
13
|
+
namespace ai {
|
|
14
|
+
constexpr float INF=10000;
|
|
15
|
+
struct Context { float field[6][CELLS]; float grad[6]; float attack[2][2][CELLS]; float sd[2][MAX_SUPPLY][CELLS]; float ed[6][CELLS]; int occ[CELLS]; float wallval[CELLS]; int walls[CELLS],nw; uint64_t wh; int me; } ctx;
|
|
16
|
+
int hist[6][CELLS];int opening[6];
|
|
17
|
+
unsigned rng=7123671;
|
|
18
|
+
unsigned rnd(){rng^=rng<<13;rng^=rng>>17;rng^=rng<<5;return rng;}
|
|
19
|
+
int md(int a,int b){return std::abs(cell_x(a)-cell_x(b))+std::abs(cell_y(a)-cell_y(b));}
|
|
20
|
+
void dijkstra(const State&s,float* d,bool steel,float speed){
|
|
21
|
+
using P=std::pair<float,int>;std::priority_queue<P,std::vector<P>,std::greater<P>>q;
|
|
22
|
+
for(int y=0;y<s.P.size;y++)for(int x=0;x<s.P.size;x++){int c=cell_of(x,y);if(d[c]<INF)q.push({d[c],c});}
|
|
23
|
+
while(!q.empty()){auto [v,c]=q.top();q.pop();if(v>d[c]+.001)continue;
|
|
24
|
+
int gc=s.grid[c];float cost=1/speed+(gc==BRICK?1.8f:gc==STEEL?2.0f:0);
|
|
25
|
+
for(int k=0;k<4;k++){int n=c+DIR_DELTA[k],g=s.grid[n];if(g!=EMPTY&&g!=BRICK&&!(g==STEEL&&steel))continue;
|
|
26
|
+
float nv=v+cost;if(nv<d[n]){d[n]=nv;q.push({nv,n});}}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
void setup(const State&s,int me){
|
|
30
|
+
ctx.me=me;ctx.nw=0;ctx.wh=s.wall_hash;std::fill(ctx.occ,ctx.occ+CELLS,-1);for(int i=0;i<6;i++)if(s.tank[i].alive)ctx.occ[s.tank[i].pos]=i;
|
|
31
|
+
for(int seat=0;seat<2;seat++)for(int st=0;st<2;st++){
|
|
32
|
+
float* d=ctx.attack[seat][st];std::fill(d,d+CELLS,INF);
|
|
33
|
+
int base=s.base_pos[1-seat];
|
|
34
|
+
for(int dir=0;dir<4;dir++){float cost=0;int len=0;for(int c=base+DIR_DELTA[dir];s.grid[c]!=OUTSIDE;c+=DIR_DELTA[dir]){
|
|
35
|
+
int g=s.grid[c];if(g==BASE0||g==BASE1||(g==STEEL&&!st))break;len++;cost+=(g==BRICK||g==STEEL)?1.9f:0;
|
|
36
|
+
if(g!=WATER)d[c]=cost+len*.75f;
|
|
37
|
+
int blocker=ctx.occ[c];if(blocker>=0)cost+=(blocker/3==seat?2.0f:6.0f);}}
|
|
38
|
+
dijkstra(s,d,st,1);
|
|
39
|
+
}
|
|
40
|
+
for(int st=0;st<2;st++)for(int k=0;k<s.n_supply;k++){float*d=ctx.sd[st][k];std::fill(d,d+CELLS,INF);d[s.supply[k]]=0;dijkstra(s,d,st,1);}
|
|
41
|
+
|
|
42
|
+
if(s.turn==0){for(int seat=0;seat<2;seat++){
|
|
43
|
+
float best=1e9;for(int a=0;a<3;a++)for(int b=0;b<3;b++)for(int c=0;c<3;c++)if(a!=b&&a!=c&&b!=c){
|
|
44
|
+
int z[3]={a,b,c};float sum=0,mx=0;
|
|
45
|
+
for(int t=0;t<3;t++){float d=ctx.sd[0][z[t]][s.spawn[seat*3+t]]/(t==0?1.65f:1.f);sum+=d;mx=std::max(mx,d);}
|
|
46
|
+
if(sum+.5f*mx<best){best=sum+.5f*mx;for(int t=0;t<3;t++)opening[seat*3+t]=z[t]+1;}
|
|
47
|
+
}
|
|
48
|
+
}}
|
|
49
|
+
for(int j=0;j<6;j++){
|
|
50
|
+
float*d=ctx.ed[j];std::fill(d,d+CELLS,INF);if(!s.tank[j].alive)continue;
|
|
51
|
+
int p=s.tank[j].pos;d[p]=1;
|
|
52
|
+
for(int k=0;k<4;k++)for(int n=1,c=p+DIR_DELTA[k];n<=5;n++,c+=DIR_DELTA[k]){
|
|
53
|
+
if(s.grid[c]!=EMPTY&&s.grid[c]!=WATER)break;
|
|
54
|
+
if(s.grid[c]==EMPTY)d[c]=n*.65f;
|
|
55
|
+
}
|
|
56
|
+
dijkstra(s,d,false,1);
|
|
57
|
+
}
|
|
58
|
+
for(int seat=0;seat<2;seat++){
|
|
59
|
+
float util[3][8];
|
|
60
|
+
for(int t=0;t<3;t++){int i=3*seat+t;const Tank&a=s.tank[i];int p=a.alive?a.pos:s.spawn[i];float speed=t==0?1.65f:1;
|
|
61
|
+
util[t][0]=34-1.6f*ctx.attack[seat][a.level>=2][p]/speed;
|
|
62
|
+
for(int k=0;k<s.n_supply;k++){
|
|
63
|
+
float dis=ctx.sd[a.level>=2][k][p]/speed;
|
|
64
|
+
int wait=(s.star_mask>>k&1)?0:(s.turn<10?11-s.turn:21-(s.turn-10)%20);
|
|
65
|
+
float val=33-2.25f*dis-3.6f*std::max(0.0f,wait-dis);
|
|
66
|
+
if(a.level>=2)val=-1000;
|
|
67
|
+
if(a.level==0)val+=7;else val-=12;
|
|
68
|
+
if(t==0)val+=3;
|
|
69
|
+
util[t][k+1]=val;
|
|
70
|
+
}
|
|
71
|
+
for(int e=0;e<3;e++){
|
|
72
|
+
int j=(1-seat)*3+e;float bd=ctx.attack[1-seat][s.tank[j].level>=2][s.tank[j].pos];
|
|
73
|
+
int home=md(s.tank[j].pos,s.base_pos[seat]);float threat=std::max(0,8-home)*4.5f;
|
|
74
|
+
float dis=ctx.ed[j][p]/speed;
|
|
75
|
+
util[t][s.n_supply+1+e]=s.tank[j].alive&&home<=7?40+threat-2.5f*dis:-1000;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
int goals[3]={};float best=-1e9;
|
|
79
|
+
for(int a=0;a<=s.n_supply+3;a++)for(int b=0;b<=s.n_supply+3;b++)for(int c=0;c<=s.n_supply+3;c++){
|
|
80
|
+
if((a&&a==b)||(a&&a==c)||(b&&b==c))continue;
|
|
81
|
+
int nd=(a>s.n_supply)+(b>s.n_supply)+(c>s.n_supply);
|
|
82
|
+
float v=util[0][a]+util[1][b]+util[2][c]-std::max(0,nd-1)*24;if(v>best){best=v;goals[0]=a;goals[1]=b;goals[2]=c;}}
|
|
83
|
+
for(int t=0;t<3;t++){int i=seat*3+t;const Tank&a=s.tank[i];float speed=t==0?1.65f:1;int goal=goals[t];if(s.turn<11||(s.turn<17&&a.level==0&&(s.star_mask>>(opening[i]-1)&1)))goal=opening[i];ctx.grad[i]=(goal==0?1.6f:goal<=s.n_supply?2.25f:2.5f)/speed;
|
|
84
|
+
for(int c=0;c<CELLS;c++){
|
|
85
|
+
float atk=34-1.6f*std::min(40.f,ctx.attack[seat][a.level>=2][c]/speed);
|
|
86
|
+
float v=atk;
|
|
87
|
+
if(goal&&goal<=s.n_supply){int k=goal-1;float dis=ctx.sd[a.level>=2][k][c]/speed;v=47-2.25f*std::min(40.f,dis);}
|
|
88
|
+
if(goal>s.n_supply){int j=(1-seat)*3+goal-s.n_supply-1;v=50-2.5f*std::min(40.f,ctx.ed[j][c]/speed);}
|
|
89
|
+
ctx.field[i][c]=v;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Credit terrain changes immediately, including bullets consumed this turn.
|
|
94
|
+
for(int c=0;c<CELLS;c++)if(s.grid[c]==BRICK||s.grid[c]==STEEL){
|
|
95
|
+
ctx.walls[ctx.nw++]=c;float vv[2]={};
|
|
96
|
+
for(int i=0;i<6;i++)if(s.tank[i].alive){int p=s.tank[i].pos;int d=md(p,c);float gain=ctx.field[i][c]-ctx.field[i][p];
|
|
97
|
+
if(d<=6&&gain>0)vv[i/3]=std::max(vv[i/3],std::max(0.f,(gain-ctx.grad[i]*d)*1.2f+.3f));
|
|
98
|
+
}
|
|
99
|
+
if(md(c,s.base_pos[0])<=2)vv[1]+=7;
|
|
100
|
+
if(md(c,s.base_pos[1])<=2)vv[0]+=7;
|
|
101
|
+
ctx.wallval[c]=vv[0]-vv[1];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
float bulletval(const State&s,const Bullet&b){
|
|
105
|
+
int seat=seat_of(b.owner),pos=b.pos;
|
|
106
|
+
float val=0;
|
|
107
|
+
for(int n=1;n<=s.P.size+1;n++){
|
|
108
|
+
pos+=DIR_DELTA[b.dir];int g=s.grid[pos];if(g==OUTSIDE)break;
|
|
109
|
+
if(g==BRICK||(g==STEEL&&b.steel)){
|
|
110
|
+
float gain=ctx.wallval[pos]*(seat==0?1:-1);
|
|
111
|
+
val=gain;break;
|
|
112
|
+
}
|
|
113
|
+
if(g==STEEL)break;
|
|
114
|
+
if(g==BASE0||g==BASE1){int side=g-BASE0;val=(side!=seat?1.f:-1.f)*135.f/(1+.035f*n);break;}
|
|
115
|
+
int hit=tank_at(s,pos);
|
|
116
|
+
if(hit>=0){
|
|
117
|
+
int free=0;for(int k=0;k<4;k++)if((k/2)!=(b.dir/2)&&s.grid[pos+DIR_DELTA[k]]==EMPTY&&tank_at(s,pos+DIR_DELTA[k])<0)free++;
|
|
118
|
+
float p=(n<=2?.22f:.025f);if(free==0)p=(n<=2?.7f:.12f);
|
|
119
|
+
if(can_fire(s,hit))p*=.55f;
|
|
120
|
+
float damage=16+(s.tank[hit].hp==1?45.f:0);
|
|
121
|
+
val=damage*p*(seat_of(hit)==seat?-1.f:1.f);break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return seat==0?val:-val;
|
|
125
|
+
}
|
|
126
|
+
float eval(const State&s){
|
|
127
|
+
if(s.done)return s.winner==0?1e6f:s.winner==1?-1e6f:0;
|
|
128
|
+
float z=(s.base_hp[0]-s.base_hp[1])*180.f+(s.kills[0]-s.kills[1])*28.f+(s.stars_eaten[0]-s.stars_eaten[1])*2;
|
|
129
|
+
for(int i=0;i<6;i++){
|
|
130
|
+
const Tank&t=s.tank[i];float v;
|
|
131
|
+
if(!t.alive)v=-3*respawn_in(s,i);
|
|
132
|
+
else {
|
|
133
|
+
v=40+t.hp*15+t.level*8+ctx.field[i][t.pos];
|
|
134
|
+
if(can_fire(s,i))v+=1.4f;
|
|
135
|
+
int base=s.base_pos[1-i/3];int dir=-1;
|
|
136
|
+
if(cell_x(base)==cell_x(t.pos))dir=base>t.pos?DOWN:UP;
|
|
137
|
+
if(cell_y(base)==cell_y(t.pos))dir=base>t.pos?RIGHT:LEFT;
|
|
138
|
+
if(dir>=0){
|
|
139
|
+
bool clear=true;int dis=md(base,t.pos);
|
|
140
|
+
for(int c=t.pos+DIR_DELTA[dir];c!=base;c+=DIR_DELTA[dir])if(s.grid[c]==BRICK||s.grid[c]==STEEL||tank_at(s,c)>=0){clear=false;break;}
|
|
141
|
+
if(clear)v+=100.f/(1+dis*.35f)*(t.level==0&&i%3!=FIRE?.8f:1.f);
|
|
142
|
+
}
|
|
143
|
+
for(int j=0;j<6;j++)if(seat_of(j)!=seat_of(i)&&!s.tank[j].alive&&s.spawn[j]==t.pos)v-=respawn_in(s,j)<=1?100:15;
|
|
144
|
+
// Only a modest exploration penalty; do not abandon productive siege squares.
|
|
145
|
+
v-=std::min(8,hist[i][t.pos])*.11f;
|
|
146
|
+
}
|
|
147
|
+
z+=(i<3?v:-v);
|
|
148
|
+
}
|
|
149
|
+
if(s.wall_hash!=ctx.wh)for(int k=0;k<ctx.nw;k++){int c=ctx.walls[k];if(s.grid[c]==EMPTY)z+=ctx.wallval[c];}
|
|
150
|
+
for(int k=0;k<s.n_bullets;k++)z+=bulletval(s,s.bullet[k]);
|
|
151
|
+
return z;
|
|
152
|
+
}
|
|
153
|
+
float value(const State&s,int seat,const Orders&a,const Orders&b){State n=s;step_as(n,seat,a,b);float v=eval(n);return seat==0?v:-v;}
|
|
154
|
+
struct Choice {Cmd c;float v;};
|
|
155
|
+
struct Pool{std::vector<Orders> a;void add(Orders x){for(auto y:a)if(x==y)return;a.push_back(x);}};
|
|
156
|
+
Orders improve(const State&s,int seat,Orders own,const Orders&enemy, std::array<std::vector<Choice>,3>*rank=nullptr){
|
|
157
|
+
for(int t=0;t<3;t++){
|
|
158
|
+
Cmd cmds[N_CMDS];int n=legal_commands(s,seat*3+t,cmds);float best=-1e20;Cmd bc=0;std::vector<Choice>ls;
|
|
159
|
+
for(int k=0;k<n;k++){Orders a=own;a.cmd[t]=cmds[k];float v=value(s,seat,a,enemy);ls.push_back({cmds[k],v});if(v>best+1e-4){best=v;bc=cmds[k];}}
|
|
160
|
+
own.cmd[t]=bc;
|
|
161
|
+
if(rank){std::sort(ls.begin(),ls.end(),[](Choice a,Choice b){return a.v>b.v;});(*rank)[t]=ls;}
|
|
162
|
+
}
|
|
163
|
+
return own;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
void init(const State&s,int me){using namespace ai;for(auto &row:hist)std::fill(row,row+CELLS,0);rng=7123671+me;}
|
|
167
|
+
Orders decide(const State&s,int me){
|
|
168
|
+
using namespace ai;setup(s,me);
|
|
169
|
+
for(int i=0;i<6;i++)if(s.tank[i].alive)hist[i][s.tank[i].pos]++;
|
|
170
|
+
Orders a,b;
|
|
171
|
+
a=improve(s,me,a,b);b=improve(s,1-me,b,a);
|
|
172
|
+
Pool pa,pb;pa.add(a);pb.add(b);pb.add(Orders{});
|
|
173
|
+
std::array<std::vector<Choice>,3> ra,rb;
|
|
174
|
+
for(int it=0;it<3;it++){
|
|
175
|
+
a=improve(s,me,a,b,&ra);pa.add(a);
|
|
176
|
+
b=improve(s,1-me,b,a,&rb);pb.add(b);
|
|
177
|
+
}
|
|
178
|
+
for(int t=0;t<3;t++){
|
|
179
|
+
for(int k=0;k<std::min(4,(int)ra[t].size());k++){Orders x=a;x.cmd[t]=ra[t][k].c;pa.add(x);}
|
|
180
|
+
for(int k=0;k<std::min(4,(int)rb[t].size());k++){Orders x=b;x.cmd[t]=rb[t][k].c;pb.add(x);}
|
|
181
|
+
}
|
|
182
|
+
// Include coordinated variants; a single best reply cannot express simultaneous dodges.
|
|
183
|
+
for(int k=0;k<9;k++){
|
|
184
|
+
Orders x=a,y=b;for(int t=0;t<3;t++){int r=(k/(t==0?1:t==1?3:1)+t)%3;if(r<(int)ra[t].size())x.cmd[t]=ra[t][r].c;if(r<(int)rb[t].size())y.cmd[t]=rb[t][r].c;}pa.add(x);pb.add(y);
|
|
185
|
+
}
|
|
186
|
+
int na=pa.a.size(),nb=pb.a.size();float mat[32][32];
|
|
187
|
+
for(int i=0;i<na;i++)for(int j=0;j<nb;j++)mat[i][j]=value(s,me,pa.a[i],pb.a[j]);
|
|
188
|
+
// Fictitious play gives a robust mixed policy for the simultaneous-action game.
|
|
189
|
+
float sa[32]={},sb[32]={};int ca[32]={},cb[32]={};int bi=0,bj=0;
|
|
190
|
+
for(int it=0;it<160;it++){
|
|
191
|
+
ca[bi]++;cb[bj]++;
|
|
192
|
+
for(int i=0;i<na;i++)sa[i]+=mat[i][bj];
|
|
193
|
+
for(int j=0;j<nb;j++)sb[j]+=mat[bi][j];
|
|
194
|
+
bi=0;bj=0;for(int i=1;i<na;i++)if(sa[i]>sa[bi])bi=i;for(int j=1;j<nb;j++)if(sb[j]<sb[bj])bj=j;
|
|
195
|
+
}
|
|
196
|
+
int sel=0;float bv=-1e20;
|
|
197
|
+
for(int i=0;i<na;i++){
|
|
198
|
+
float v=0,w=1e20;for(int j=0;j<nb;j++){v+=mat[i][j]*cb[j]/160.f;w=std::min(w,mat[i][j]);}
|
|
199
|
+
v=.85f*v+.15f*w;
|
|
200
|
+
if(v>bv){bv=v;sel=i;}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Extend the most relevant simultaneous choices through three full turns.
|
|
204
|
+
std::vector<int> ia,ib;
|
|
205
|
+
for(int i=0;i<na;i++)ia.push_back(i);
|
|
206
|
+
for(int j=0;j<nb;j++)ib.push_back(j);
|
|
207
|
+
float ar[64]={},br[64]={};
|
|
208
|
+
for(int i=0;i<na;i++){float w=1e20;for(int j=0;j<nb;j++){ar[i]+=mat[i][j]*cb[j]/160.f;w=std::min(w,mat[i][j]);}ar[i]=ar[i]*.85f+.15f*w;}
|
|
209
|
+
for(int j=0;j<nb;j++){float w=-1e20;for(int i=0;i<na;i++){br[j]+=mat[i][j]*ca[i]/160.f;w=std::max(w,mat[i][j]);}br[j]=br[j]*.85f+.15f*w;}
|
|
210
|
+
std::sort(ia.begin(),ia.end(),[&](int x,int y){return ar[x]>ar[y];});
|
|
211
|
+
std::sort(ib.begin(),ib.end(),[&](int x,int y){return br[x]<br[y];});
|
|
212
|
+
ia.erase(std::remove(ia.begin(),ia.end(),sel),ia.end());ia.insert(ia.begin(),sel);
|
|
213
|
+
ia.resize(std::min(12,(int)ia.size()));ib.resize(std::min(10,(int)ib.size()));
|
|
214
|
+
float deep[12][12];int nr=ia.size(),nc=ib.size();
|
|
215
|
+
for(int x=0;x<nr;x++)for(int y=0;y<nc;y++){
|
|
216
|
+
if(budget_left()<6)return pa.a[sel];
|
|
217
|
+
State n=s;step_as(n,me,pa.a[ia[x]],pb.a[ib[y]]);
|
|
218
|
+
float v=eval(n)*(me==0?1:-1)*.25f;
|
|
219
|
+
for(int depth=0;depth<2&&!n.done;depth++){
|
|
220
|
+
Orders aa,bb;
|
|
221
|
+
aa=improve(n,me,aa,bb);bb=improve(n,1-me,bb,aa);
|
|
222
|
+
Orders aa2=improve(n,me,aa,bb);
|
|
223
|
+
step_as(n,me,aa2,bb);
|
|
224
|
+
v+=eval(n)*(me==0?1:-1)*(depth==0?.30f:.45f);
|
|
225
|
+
}
|
|
226
|
+
deep[x][y]=n.done?eval(n)*(me==0?1:-1):v;
|
|
227
|
+
}
|
|
228
|
+
std::fill(sa,sa+32,0);std::fill(sb,sb+32,0);std::fill(ca,ca+32,0);std::fill(cb,cb+32,0);bi=bj=0;
|
|
229
|
+
for(int it=0;it<200;it++){
|
|
230
|
+
ca[bi]++;cb[bj]++;
|
|
231
|
+
for(int i=0;i<nr;i++)sa[i]+=deep[i][bj];
|
|
232
|
+
for(int j=0;j<nc;j++)sb[j]+=deep[bi][j];
|
|
233
|
+
bi=bj=0;for(int i=1;i<nr;i++)if(sa[i]>sa[bi])bi=i;for(int j=1;j<nc;j++)if(sb[j]<sb[bj])bj=j;
|
|
234
|
+
}
|
|
235
|
+
bv=-1e20;
|
|
236
|
+
for(int i=0;i<nr;i++){
|
|
237
|
+
float v=0,w=1e20;for(int j=0;j<nc;j++){v+=deep[i][j]*cb[j]/200.f;w=std::min(w,deep[i][j]);}
|
|
238
|
+
v=.85f*v+.15f*w;if(v>bv){bv=v;sel=ia[i];}
|
|
239
|
+
}
|
|
240
|
+
return pa.a[sel];
|
|
241
|
+
}
|
package/eval/arena/tank/workspace/history/20261017-193643-63319e0a2b1a-gpt-6_1-sol-ultrafast.cpp
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
// Coordinated tank bot: supply control, a committed fast flanker, and adaptive support.
|
|
2
|
+
// Supply assignments account for opposing arrival times and chassis-specific contest risk.
|
|
3
|
+
// Fire tanks discount incidental chases while retaining critical defensive interceptions.
|
|
4
|
+
// Exact joint-action simulation combines strategic rollouts with nested simultaneous games.
|
|
5
|
+
// Shared action rankings avoid repeated work; every search retains a legal budget fallback.
|
|
6
|
+
#include "tank.hpp"
|
|
7
|
+
#include <algorithm>
|
|
8
|
+
#include <array>
|
|
9
|
+
#include <cmath>
|
|
10
|
+
#include <queue>
|
|
11
|
+
#include <utility>
|
|
12
|
+
#include <vector>
|
|
13
|
+
#include <cstdio>
|
|
14
|
+
#include <unordered_map>
|
|
15
|
+
using namespace tank;
|
|
16
|
+
namespace bot {
|
|
17
|
+
constexpr float INF=10000;
|
|
18
|
+
float bd[6][CELLS], sd[6][MAX_SUPPLY][CELLS], hd[6][3][CELLS], field[6][CELLS];
|
|
19
|
+
int goal[6], previous[6];float anchor[6];
|
|
20
|
+
uint64_t rng=123456789;
|
|
21
|
+
uint64_t random64(){rng^=rng<<13;rng^=rng>>7;rng^=rng<<17;return rng;}
|
|
22
|
+
float rand01(){return (random64()>>40)*(1.0f/16777216);}
|
|
23
|
+
int md(int a,int b){return std::abs(cell_x(a)-cell_x(b))+std::abs(cell_y(a)-cell_y(b));}
|
|
24
|
+
int direction(int a,int b){if(a==b)return -1;if(cell_x(a)==cell_x(b))return a>b?0:1;if(cell_y(a)==cell_y(b))return a>b?2:3;return -1;}
|
|
25
|
+
bool clear(const State&s,int a,int b){int d=direction(a,b);if(d<0)return false;for(int p=a+DIR_DELTA[d];p!=b;p+=DIR_DELTA[d])if(s.grid[p]!=EMPTY&&s.grid[p]!=WATER)return false;return true;}
|
|
26
|
+
void dijkstra(const State&s,int i,float *dist,const std::vector<std::pair<int,float>>& seeds){
|
|
27
|
+
for(int p=0;p<CELLS;p++)dist[p]=INF;
|
|
28
|
+
using Node=std::pair<float,int>;
|
|
29
|
+
std::priority_queue<Node,std::vector<Node>,std::greater<Node>>q;
|
|
30
|
+
for(auto [p,v]:seeds)if(v<dist[p]){dist[p]=v;q.emplace(v,p);}
|
|
31
|
+
float walk=type_of(i)==FAST?.58f:1.f;
|
|
32
|
+
while(!q.empty()){
|
|
33
|
+
auto [v,p]=q.top();q.pop();if(v>dist[p]+.001f)continue;
|
|
34
|
+
int g=s.grid[p];float extra=g==BRICK?2.f:g==STEEL?3.f:0.f;
|
|
35
|
+
for(int d=0;d<4;d++){
|
|
36
|
+
int n=p+DIR_DELTA[d];if(n<0||n>=CELLS)continue;
|
|
37
|
+
int ng=s.grid[n];if(ng==OUTSIDE||ng==WATER||ng==BASE0||ng==BASE1||(ng==STEEL&&s.tank[i].level<2))continue;
|
|
38
|
+
float nv=v+walk+extra;
|
|
39
|
+
if(nv<dist[n]){dist[n]=nv;q.emplace(nv,n);}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
void prepare(const State&s){
|
|
44
|
+
for(int i=0;i<6;i++){
|
|
45
|
+
int side=seat_of(i),base=s.base_pos[1-side];std::vector<std::pair<int,float>> seeds;
|
|
46
|
+
for(int d=0;d<4;d++){
|
|
47
|
+
int walls=0,range=0;
|
|
48
|
+
for(int p=base+DIR_DELTA[d];p>=0&&p<CELLS;p+=DIR_DELTA[d]){
|
|
49
|
+
int g=s.grid[p];if(g==OUTSIDE||g==BASE0||g==BASE1||(g==STEEL&&s.tank[i].level<2))break;
|
|
50
|
+
range++;if(g==BRICK||g==STEEL)walls++;
|
|
51
|
+
if(g!=WATER)seeds.emplace_back(p,range*(type_of(i)==FAST?1.45f:.85f)+walls*2.0f+((type_of(i)==FAST&&d<2)?5.f:0.f));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
dijkstra(s,i,bd[i],seeds);
|
|
55
|
+
for(int k=0;k<s.n_supply;k++)dijkstra(s,i,sd[i][k],{{s.supply[k],0}});
|
|
56
|
+
}
|
|
57
|
+
for(int i=0;i<6;i++)for(int t=0;t<3;t++){
|
|
58
|
+
int j=(1-seat_of(i))*3+t,p=s.tank[j].pos;
|
|
59
|
+
std::vector<std::pair<int,float>> seeds;
|
|
60
|
+
if(s.tank[j].alive)for(int d=0;d<4;d++)for(int range=1;range<=5;range++){
|
|
61
|
+
int q=p+DIR_DELTA[d]*range;if(q<0||q>=CELLS||s.grid[q]==OUTSIDE)break;
|
|
62
|
+
int g=s.grid[q];if(g==BASE0||g==BASE1)break;if(g==STEEL&&s.tank[i].level<2)break;
|
|
63
|
+
if(g==EMPTY||g==BRICK||g==STEEL)seeds.emplace_back(q,1.0f*range+(g==EMPTY?0.f:2.f));
|
|
64
|
+
if(g==BRICK||g==STEEL)break;
|
|
65
|
+
}
|
|
66
|
+
dijkstra(s,i,hd[i][t],seeds);
|
|
67
|
+
}
|
|
68
|
+
for(int side=0;side<2;side++){
|
|
69
|
+
float options[3][7];int next=s.turn<10?10-s.turn:20-(s.turn-10)%20;
|
|
70
|
+
for(int t=0;t<3;t++){
|
|
71
|
+
int i=side*3+t;int p=s.tank[i].alive?s.tank[i].pos:s.spawn[i];
|
|
72
|
+
options[t][0]=-bd[i][p]*.65f;
|
|
73
|
+
for(int k=0;k<s.n_supply;k++){
|
|
74
|
+
float wait=(s.star_mask&(1<<k))?0.f:float(next+1);
|
|
75
|
+
float eta=sd[i][k][p],enemy=INF;
|
|
76
|
+
for(int j=(1-side)*3;j<(1-side)*3+3;j++)if(s.tank[j].alive&&s.tank[j].level<2)enemy=std::min(enemy,sd[j][k][s.tank[j].pos]);
|
|
77
|
+
float value=(s.tank[i].level==0?17.f:0.f)-1.5f*std::max(eta,wait);
|
|
78
|
+
if(enemy+.5f<eta)value-=std::min(18.f,(eta-enemy)*(t==0?4.f:t==2?1.f:2.f));
|
|
79
|
+
if(!s.tank[i].alive)value=-INF;
|
|
80
|
+
if(s.tank[i].level>=2)value=-INF;
|
|
81
|
+
options[t][k+1]=value;
|
|
82
|
+
}
|
|
83
|
+
for(int e=0;e<3;e++){
|
|
84
|
+
int j=(1-side)*3+e;
|
|
85
|
+
float threat=-INF;
|
|
86
|
+
if(s.tank[j].alive){
|
|
87
|
+
int dist=md(s.tank[j].pos,s.base_pos[side]);
|
|
88
|
+
if(dist<=7){threat=27.f-2.f*dist+3.f*s.tank[j].level;
|
|
89
|
+
if(clear(s,s.tank[j].pos,s.base_pos[side]))threat+=18.f;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
options[t][4+e]=threat-1.5f*hd[i][e][p]-(t==1?8.f:0.f);
|
|
93
|
+
if(t==0||!s.tank[i].alive)options[t][4+e]=-INF;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
float best=-INF*10;int choice[3]={};
|
|
97
|
+
for(int a=0;a<7;a++)for(int b=0;b<7;b++)for(int c=0;c<7;c++){
|
|
98
|
+
if((a&&a==b)||(a&&a==c)||(b&&b==c))continue;
|
|
99
|
+
float v=options[0][a]+options[1][b]+options[2][c];
|
|
100
|
+
if(v>best){best=v;choice[0]=a;choice[1]=b;choice[2]=c;}
|
|
101
|
+
}
|
|
102
|
+
for(int t=0;t<3;t++){
|
|
103
|
+
int i=side*3+t;goal[i]=choice[t]-1;
|
|
104
|
+
for(int p=0;p<CELLS;p++)field[i][p]=goal[i]<0?-bd[i][p]:goal[i]<3?-sd[i][goal[i]][p]:-hd[i][goal[i]-3][p];
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
float projectile(const State&s,const Bullet&b){
|
|
109
|
+
int side=seat_of(b.owner),p=b.pos,steps=0;
|
|
110
|
+
for(;;){
|
|
111
|
+
if(p<0||p>=CELLS)return 0;
|
|
112
|
+
int g=s.grid[p];
|
|
113
|
+
if(g==OUTSIDE||g==BRICK||g==STEEL)return 0;
|
|
114
|
+
if(g==BASE0||g==BASE1){
|
|
115
|
+
float value=60.f/(1.f+.08f*steps);
|
|
116
|
+
for(int j=0;j<6;j++)if(seat_of(j)!=side&&s.tank[j].alive){int dd=md(s.tank[j].pos,p);if(dd<steps/2+2)value*=.72f;}
|
|
117
|
+
return (g-BASE0==side?-1.f:1.f)*value;
|
|
118
|
+
}
|
|
119
|
+
for(int j=0;j<6;j++)if(s.tank[j].alive&&s.tank[j].pos==p){
|
|
120
|
+
int escapes=0;for(int d=0;d<4;d++){int n=p+DIR_DELTA[d];if(s.grid[n]==EMPTY&&tank_at(s,n)<0)escapes++;}
|
|
121
|
+
float value=(s.tank[j].hp==1?19.f:9.f)/(1.f+.35f*steps);
|
|
122
|
+
if(steps>0)value*=escapes? .3f:.9f;
|
|
123
|
+
if(steps>0&&can_fire(s,j)&&direction(p,b.pos)>=0)value*=.6f;
|
|
124
|
+
return (seat_of(j)==side?-1.f:1.f)*value;
|
|
125
|
+
}
|
|
126
|
+
p+=DIR_DELTA[b.dir];steps++;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
float evaluate(const State&s,int side){
|
|
130
|
+
if(s.done)return s.winner<0?0.f:(s.winner==side?100000.f:-100000.f);
|
|
131
|
+
float v=140.f*(s.base_hp[side]-s.base_hp[1-side])+30.f*(s.kills[side]-s.kills[1-side])+4.f*(s.stars_eaten[side]-s.stars_eaten[1-side]);
|
|
132
|
+
for(int i=0;i<6;i++){
|
|
133
|
+
auto&t=s.tank[i];float val;
|
|
134
|
+
if(t.alive){
|
|
135
|
+
val=34.f+11.f*t.hp+14.f*t.level;
|
|
136
|
+
val+=5.f*(std::max(-45.f,field[i][t.pos])-anchor[i]);
|
|
137
|
+
if(clear(s,t.pos,s.base_pos[1-seat_of(i)]))val+=25.f/(1.f+.18f*md(t.pos,s.base_pos[1-seat_of(i)]));
|
|
138
|
+
}else val=-4.f*respawn_in(s,i)-20.f;
|
|
139
|
+
v+=(seat_of(i)==side?1.f:-1.f)*val;
|
|
140
|
+
}
|
|
141
|
+
for(int k=0;k<s.n_bullets;k++)v+=(seat_of(s.bullet[k].owner)==side?1.f:-1.f)*projectile(s,s.bullet[k]);
|
|
142
|
+
return v;
|
|
143
|
+
}
|
|
144
|
+
void path(const State&s,int i,Cmd c,int&p1,int&p2){
|
|
145
|
+
p1=p2=s.tank[i].pos;
|
|
146
|
+
int d1=-1,d2=-1;if(is_move(c))d1=c-1;else if(is_move2(c)){d1=(c-9)/4;d2=(c-9)%4;}
|
|
147
|
+
if(d1>=0){int n=p1+DIR_DELTA[d1];if(s.grid[n]==EMPTY&&tank_at(s,n)<0)p1=n;}
|
|
148
|
+
p2=p1;if(d2>=0){int n=p2+DIR_DELTA[d2];if(s.grid[n]==EMPTY&&tank_at(s,n)<0)p2=n;}
|
|
149
|
+
}
|
|
150
|
+
float shot_value(const State&s,int i,int d){
|
|
151
|
+
int p=s.tank[i].pos,side=seat_of(i),steps=0;
|
|
152
|
+
for(int n=p+DIR_DELTA[d];;n+=DIR_DELTA[d]){
|
|
153
|
+
steps++;int g=s.grid[n];if(g==OUTSIDE)return 0;
|
|
154
|
+
if(g==BASE0||g==BASE1)return g-BASE0==side?-200.f:70.f/(1.f+.08f*steps);
|
|
155
|
+
int j=tank_at(s,n);
|
|
156
|
+
if(j>=0){
|
|
157
|
+
if(seat_of(j)==side)return -25.f/(1.f+.1f*steps);
|
|
158
|
+
int exits=0;for(int k=0;k<4;k++)if(s.grid[n+DIR_DELTA[k]]==EMPTY&&tank_at(s,n+DIR_DELTA[k])<0)exits++;
|
|
159
|
+
float value=(s.tank[j].hp==1?20.f:13.f)/(1+.35f*steps);
|
|
160
|
+
if(exits>1)value*=.65f;
|
|
161
|
+
if(can_fire(s,j))value*=.65f;
|
|
162
|
+
return value;
|
|
163
|
+
}
|
|
164
|
+
if(g==BRICK||g==STEEL){
|
|
165
|
+
if(g==STEEL&&s.tank[i].level<2)return 0;
|
|
166
|
+
float gain=field[i][n]-field[i][p];
|
|
167
|
+
float value=std::max(0.f,2.0f*gain-1.f)/(1.f+.2f*steps);
|
|
168
|
+
int base=s.base_pos[1-side];
|
|
169
|
+
if(direction(p,base)==d){
|
|
170
|
+
bool line=true;for(int q=n+DIR_DELTA[d];q!=base;q+=DIR_DELTA[d]){if(s.grid[q]==OUTSIDE||(s.grid[q]==STEEL&&s.tank[i].level<2)){line=false;break;}}
|
|
171
|
+
if(line)value+=12.f/(1.f+.1f*md(p,base));
|
|
172
|
+
}
|
|
173
|
+
int own=s.base_pos[side];if(md(n,own)<=2&&md(p,own)<6)value-=8.f;
|
|
174
|
+
return value;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
float primitive(const State&s,int i,Cmd c){
|
|
179
|
+
if(!s.tank[i].alive)return 0;
|
|
180
|
+
int p=s.tank[i].pos,p1,p2;path(s,i,c,p1,p2);
|
|
181
|
+
float val=3.2f*(field[i][p2]-field[i][p]);
|
|
182
|
+
bool fire=is_fire(c)&&can_fire(s,i);int fd=fire?c-5:-1;
|
|
183
|
+
if(fire)val+=shot_value(s,i,fd);
|
|
184
|
+
if(c==STAY)val-=.12f;
|
|
185
|
+
if(p2==p&&is_move(c))val-=.4f;
|
|
186
|
+
int damage=0;
|
|
187
|
+
for(int k=0;k<s.n_bullets;k++){
|
|
188
|
+
const auto&b=s.bullet[k];int n=b.pos+DIR_DELTA[b.dir],nn=n+DIR_DELTA[b.dir];
|
|
189
|
+
bool cancel=false;
|
|
190
|
+
if(fire){int f1=p+DIR_DELTA[fd],f2=f1+DIR_DELTA[fd];cancel=(f1==n)||(f1==b.pos&&n==p)||(f2==nn)||(f2==n&&nn==f1);}
|
|
191
|
+
if(cancel)continue;
|
|
192
|
+
bool hit=n==p1||(n==p&&b.pos==p1);
|
|
193
|
+
if(!hit&&s.grid[n]!=BRICK&&s.grid[n]!=STEEL&&s.grid[n]!=OUTSIDE&&tank_at(s,n)<0)hit=nn==p2||(nn==p1&&n==p2);
|
|
194
|
+
if(hit)damage++;
|
|
195
|
+
}
|
|
196
|
+
if(damage)val-=damage*17.f+(damage>=s.tank[i].hp?65.f+15*s.tank[i].level:0.f);
|
|
197
|
+
for(int j=0;j<6;j++)if(seat_of(i)!=seat_of(j)&&s.tank[j].alive&&can_fire(s,j)){
|
|
198
|
+
int e=s.tank[j].pos;
|
|
199
|
+
for(int d=0;d<4;d++){
|
|
200
|
+
int n=e+DIR_DELTA[d],nn=n+DIR_DELTA[d];
|
|
201
|
+
bool hit=(n==p1)||(nn==p2&&s.grid[n]!=BRICK&&s.grid[n]!=STEEL&&tank_at(s,n)<0)||(p1==e&&n==p);
|
|
202
|
+
if(hit){if(fire&&fd==(d^1)&&direction(p,e)==fd)continue;val-=(s.tank[i].hp==1?17.f:7.f);}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
for(int j=0;j<6;j++)if(seat_of(j)!=seat_of(i)&&!s.tank[j].alive&&s.spawn[j]==p2&&respawn_in(s,j)<=1)val-=200;
|
|
206
|
+
if(goal[i]>=0&&goal[i]<3&&p2==s.supply[goal[i]]&&s.tank[i].level<2&&(s.star_mask&(1<<goal[i])))val+=28;
|
|
207
|
+
if(p2==previous[i]&&p2!=p)val-=.18f;
|
|
208
|
+
return val;
|
|
209
|
+
}
|
|
210
|
+
struct Rated {Cmd c;float v;};
|
|
211
|
+
struct Plan {Orders o;float v;};
|
|
212
|
+
std::vector<Rated> ranked(const State&s,int i){
|
|
213
|
+
Cmd a[N_CMDS];int n=legal_commands(s,i,a);std::vector<Rated>r;
|
|
214
|
+
for(int k=0;k<n;k++)r.push_back({a[k],primitive(s,i,a[k])});
|
|
215
|
+
std::stable_sort(r.begin(),r.end(),[](auto&a,auto&b){return a.v>b.v;});return r;
|
|
216
|
+
}
|
|
217
|
+
Orders policy_from_r(const State&s,int side,const std::vector<Rated>* rs){
|
|
218
|
+
Orders o;int p1[3],p2[3];
|
|
219
|
+
for(int t=0;t<3;t++){
|
|
220
|
+
int i=side*3+t;const auto&r=rs[t];float best=-INF;
|
|
221
|
+
for(auto x:r){int a,b;path(s,i,x.c,a,b);float v=x.v;
|
|
222
|
+
for(int j=0;j<t;j++)if(s.tank[side*3+j].alive&&s.tank[i].alive){if(a==p1[j])v-=20;if(b==p2[j])v-=20;}
|
|
223
|
+
if(v>best){best=v;o.cmd[t]=x.c;p1[t]=a;p2[t]=b;}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return o;
|
|
227
|
+
}
|
|
228
|
+
Orders policy(const State&s,int side){
|
|
229
|
+
std::vector<Rated> rs[3];for(int t=0;t<3;t++)rs[t]=ranked(s,side*3+t);
|
|
230
|
+
return policy_from_r(s,side,rs);
|
|
231
|
+
}
|
|
232
|
+
std::vector<Orders> plans(const State&s,int side){
|
|
233
|
+
std::vector<Rated> r[3];for(int t=0;t<3;t++)r[t]=ranked(s,side*3+t);
|
|
234
|
+
std::vector<Plan> all;
|
|
235
|
+
for(int a=0;a<std::min(4,(int)r[0].size());a++)for(int b=0;b<std::min(4,(int)r[1].size());b++)for(int c=0;c<std::min(4,(int)r[2].size());c++){
|
|
236
|
+
Orders o;o.cmd[0]=r[0][a].c;o.cmd[1]=r[1][b].c;o.cmd[2]=r[2][c].c;
|
|
237
|
+
int p1[3],p2[3];float v=r[0][a].v+r[1][b].v+r[2][c].v;
|
|
238
|
+
for(int t=0;t<3;t++)path(s,side*3+t,o.cmd[t],p1[t],p2[t]);
|
|
239
|
+
for(int t=0;t<3;t++)for(int j=t+1;j<3;j++)if(s.tank[side*3+t].alive&&s.tank[side*3+j].alive){if(p1[t]==p1[j])v-=20;if(p2[t]==p2[j])v-=20;}
|
|
240
|
+
all.push_back({o,v});
|
|
241
|
+
}
|
|
242
|
+
std::stable_sort(all.begin(),all.end(),[](auto&a,auto&b){return a.v>b.v;});
|
|
243
|
+
std::vector<Orders>out;
|
|
244
|
+
auto add=[&](Orders o){for(auto q:out)if(q==o)return;out.push_back(o);};
|
|
245
|
+
add(policy_from_r(s,side,r));for(int k=0;k<std::min(14,(int)all.size());k++)add(all[k].o);
|
|
246
|
+
Orders best=out[0];
|
|
247
|
+
for(int t=0;t<3;t++)for(int a=0;a<std::min(7,(int)r[t].size());a++){Orders o=best;o.cmd[t]=r[t][a].c;add(o);}
|
|
248
|
+
add(Orders{});return out;
|
|
249
|
+
}
|
|
250
|
+
std::vector<Orders> smallplans(const State&s,int side){
|
|
251
|
+
std::vector<Rated> rs[3];for(int t=0;t<3;t++)rs[t]=ranked(s,side*3+t);
|
|
252
|
+
Orders base=policy_from_r(s,side,rs);std::vector<Orders> a{base};
|
|
253
|
+
for(int t=0;t<3;t++){
|
|
254
|
+
const auto&r=rs[t];int got=0;
|
|
255
|
+
for(auto x:r)if(x.c!=base.cmd[t]){Orders q=base;q.cmd[t]=x.c;if(std::find(a.begin(),a.end(),q)==a.end())a.push_back(q);if(++got>=2)break;}
|
|
256
|
+
}
|
|
257
|
+
return a;
|
|
258
|
+
}
|
|
259
|
+
float subgame(const State&s,int side){
|
|
260
|
+
if(s.done)return evaluate(s,side);
|
|
261
|
+
auto a=smallplans(s,side),b=smallplans(s,1-side);int n=a.size(),m=b.size();
|
|
262
|
+
float M[8][8];for(int i=0;i<n;i++)for(int j=0;j<m;j++){State z=s;step_as(z,side,a[i],b[j]);M[i][j]=evaluate(z,side);}
|
|
263
|
+
double u[8]={},v[8]={},ca[8]={},cb[8]={};int x=0,y=0;
|
|
264
|
+
for(int it=0;it<160;it++){
|
|
265
|
+
if(it>=40){ca[x]++;cb[y]++;}
|
|
266
|
+
for(int i=0;i<n;i++)u[i]+=M[i][y];
|
|
267
|
+
for(int j=0;j<m;j++)v[j]+=M[x][j];
|
|
268
|
+
x=std::max_element(u,u+n)-u;y=std::min_element(v,v+m)-v;
|
|
269
|
+
}
|
|
270
|
+
double ans=0;for(int i=0;i<n;i++)for(int j=0;j<m;j++)ans+=ca[i]*cb[j]*M[i][j];return ans/14400;
|
|
271
|
+
}
|
|
272
|
+
struct GameMix {std::vector<double> a,b;};
|
|
273
|
+
GameMix solvegame(const std::vector<std::vector<float>>&M){
|
|
274
|
+
int n=M.size(),m=M[0].size();
|
|
275
|
+
std::vector<double>u(n,0),v(m,0),ca(n,0),cb(m,0);int x=0,y=0;
|
|
276
|
+
for(int it=0;it<1200;it++){
|
|
277
|
+
if(it>=300){ca[x]++;cb[y]++;}
|
|
278
|
+
for(int j=0;j<n;j++)u[j]+=M[j][y];
|
|
279
|
+
for(int j=0;j<m;j++)v[j]+=M[x][j];
|
|
280
|
+
x=std::max_element(u.begin(),u.end())-u.begin();y=std::min_element(v.begin(),v.end())-v.begin();
|
|
281
|
+
}
|
|
282
|
+
for(double &x:ca)x/=900;
|
|
283
|
+
for(double &x:cb)x/=900;
|
|
284
|
+
return {ca,cb};
|
|
285
|
+
}
|
|
286
|
+
uint64_t code(Orders o){return o.cmd[0]|(uint64_t(o.cmd[1])<<8)|(uint64_t(o.cmd[2])<<16);}
|
|
287
|
+
Orders choose_oracle(const State&s,int side){
|
|
288
|
+
prepare(s);for(int i=0;i<6;i++)anchor[i]=std::max(-45.f,field[i][s.tank[i].alive?s.tank[i].pos:s.spawn[i]]);auto a=plans(s,side),b=plans(s,1-side);
|
|
289
|
+
std::unordered_map<uint64_t,float>cache;cache.reserve(4000);
|
|
290
|
+
auto ev=[&](Orders a,Orders b){
|
|
291
|
+
uint64_t key=code(a)|(code(b)<<24);auto it=cache.find(key);if(it!=cache.end())return it->second;
|
|
292
|
+
State z=s;step_as(z,side,a,b);float first=evaluate(z,side);
|
|
293
|
+
for(int h=0;h<2&&!z.done;h++){Orders u=policy(z,side),v=policy(z,1-side);step_as(z,side,u,v);}
|
|
294
|
+
float ans=.3f*first+.7f*evaluate(z,side);cache.emplace(key,ans);return ans;
|
|
295
|
+
};
|
|
296
|
+
GameMix mix;
|
|
297
|
+
for(int round=0;round<3;round++){
|
|
298
|
+
std::vector<std::vector<float>>M(a.size(),std::vector<float>(b.size()));
|
|
299
|
+
for(int x=0;x<(int)a.size();x++)for(int y=0;y<(int)b.size();y++)M[x][y]=ev(a[x],b[y]);
|
|
300
|
+
mix=solvegame(M);if(round==2||budget_left()<18)break;
|
|
301
|
+
std::vector<std::pair<double,Orders>>sa,sb;
|
|
302
|
+
for(int x=0;x<(int)a.size();x++)if(mix.a[x]>.001)sa.emplace_back(mix.a[x],a[x]);
|
|
303
|
+
for(int y=0;y<(int)b.size();y++)if(mix.b[y]>.001)sb.emplace_back(mix.b[y],b[y]);
|
|
304
|
+
auto prep=[](auto&v){std::sort(v.begin(),v.end(),[](auto&a,auto&b){return a.first>b.first;});if(v.size()>6)v.resize(6);double sum=0;for(auto &x:v)sum+=x.first;for(auto &x:v)x.first/=sum;};prep(sa);prep(sb);
|
|
305
|
+
auto response=[&](int who,Orders best,const std::vector<std::pair<double,Orders>>&support){
|
|
306
|
+
auto val=[&](Orders o){double v=0;for(auto &[p,e]:support)v+=p*(who==side?ev(o,e):-ev(e,o));return v;};
|
|
307
|
+
double current=val(best);
|
|
308
|
+
for(int pass=0;pass<2;pass++)for(int t=0;t<3;t++){
|
|
309
|
+
if(budget_left()<7)return best;
|
|
310
|
+
Cmd list[N_CMDS];int n=legal_commands(s,who*3+t,list);Orders old=best;
|
|
311
|
+
for(int c=0;c<n;c++){Orders trial=old;trial.cmd[t]=list[c];double v=val(trial);if(v>current+.001){current=v;best=trial;}}
|
|
312
|
+
}
|
|
313
|
+
return best;
|
|
314
|
+
};
|
|
315
|
+
int ai=std::max_element(mix.a.begin(),mix.a.end())-mix.a.begin(),bi=std::max_element(mix.b.begin(),mix.b.end())-mix.b.begin();
|
|
316
|
+
Orders ar=response(side,a[ai],sb),br=response(1-side,b[bi],sa);
|
|
317
|
+
if(std::find(a.begin(),a.end(),ar)==a.end())a.push_back(ar);
|
|
318
|
+
if(std::find(b.begin(),b.end(),br)==b.end())b.push_back(br);
|
|
319
|
+
}
|
|
320
|
+
double target=rand01(),sum=0;for(int x=0;x<(int)a.size();x++){sum+=mix.a[x];if(sum>=target)return a[x];}
|
|
321
|
+
return a.back();
|
|
322
|
+
}
|
|
323
|
+
Orders choose_nested(const State&s,int side){
|
|
324
|
+
prepare(s);for(int i=0;i<6;i++)anchor[i]=std::max(-45.f,field[i][s.tank[i].alive?s.tank[i].pos:s.spawn[i]]);
|
|
325
|
+
auto a=plans(s,side),b=plans(s,1-side);
|
|
326
|
+
int n=a.size(),m=b.size();std::vector<float>matrix(n*m);
|
|
327
|
+
for(int x=0;x<n;x++)for(int y=0;y<m;y++){
|
|
328
|
+
if((y&3)==0&&budget_left()<5)return policy(s,side);
|
|
329
|
+
State z=s;step_as(z,side,a[x],b[y]);float first=evaluate(z,side);
|
|
330
|
+
matrix[x*m+y]=.15f*first+.85f*subgame(z,side);
|
|
331
|
+
}
|
|
332
|
+
std::vector<double>u(n,0),v(m,0),counts(n,0),opp(m,0);int x=0,y=0;
|
|
333
|
+
for(int it=0;it<220;it++){
|
|
334
|
+
counts[x]++;opp[y]++;
|
|
335
|
+
for(int j=0;j<n;j++)u[j]+=matrix[j*m+y];
|
|
336
|
+
for(int j=0;j<m;j++)v[j]+=matrix[x*m+j];
|
|
337
|
+
x=std::max_element(u.begin(),u.end())-u.begin();y=std::min_element(v.begin(),v.end())-v.begin();
|
|
338
|
+
}
|
|
339
|
+
double target=rand01()*220,acc=0;int chosen=n-1;
|
|
340
|
+
for(int j=0;j<n;j++){acc+=counts[j];if(acc>target){chosen=j;break;}}
|
|
341
|
+
return a[chosen];
|
|
342
|
+
}
|
|
343
|
+
Orders choose(const State&s,int side){
|
|
344
|
+
bool combat=false;
|
|
345
|
+
for(int i=side*3;i<side*3+3;i++)if(s.tank[i].alive){
|
|
346
|
+
for(int j=(1-side)*3;j<(1-side)*3+3;j++)if(s.tank[j].alive){
|
|
347
|
+
int d=md(s.tank[i].pos,s.tank[j].pos);
|
|
348
|
+
if(d<=3||(d<=6&&clear(s,s.tank[i].pos,s.tank[j].pos)))combat=true;
|
|
349
|
+
}
|
|
350
|
+
for(int k=0;k<s.n_bullets;k++)if(md(s.bullet[k].pos,s.tank[i].pos)<=4)combat=true;
|
|
351
|
+
}
|
|
352
|
+
return combat?choose_nested(s,side):choose_oracle(s,side);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
void init(const State&s,int me){bot::rng=0x7d2543a71b9ULL^s.wall_hash^(me*987654321ULL);for(int i=0;i<6;i++)bot::previous[i]=-1;}
|
|
356
|
+
Orders decide(const State&s,int me){Orders o=bot::choose(s,me);for(int i=0;i<6;i++)bot::previous[i]=s.tank[i].alive?s.tank[i].pos:-1;return o;}
|