poke-crucible 0.1.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/LICENSE +21 -0
- package/README.md +192 -0
- package/dist/battle/pairing.d.ts +25 -0
- package/dist/battle/pairing.js +59 -0
- package/dist/battle/pairing.js.map +1 -0
- package/dist/battle/pool.d.ts +25 -0
- package/dist/battle/pool.js +97 -0
- package/dist/battle/pool.js.map +1 -0
- package/dist/battle/run-battle.d.ts +13 -0
- package/dist/battle/run-battle.js +49 -0
- package/dist/battle/run-battle.js.map +1 -0
- package/dist/battle/worker.d.ts +1 -0
- package/dist/battle/worker.js +21 -0
- package/dist/battle/worker.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +326 -0
- package/dist/cli.js.map +1 -0
- package/dist/critic/agent-sdk-model.d.ts +27 -0
- package/dist/critic/agent-sdk-model.js +21 -0
- package/dist/critic/agent-sdk-model.js.map +1 -0
- package/dist/critic/critique.d.ts +21 -0
- package/dist/critic/critique.js +51 -0
- package/dist/critic/critique.js.map +1 -0
- package/dist/critic/evidence.d.ts +24 -0
- package/dist/critic/evidence.js +17 -0
- package/dist/critic/evidence.js.map +1 -0
- package/dist/critic/llm.d.ts +34 -0
- package/dist/critic/llm.js +23 -0
- package/dist/critic/llm.js.map +1 -0
- package/dist/critic/parse.d.ts +5 -0
- package/dist/critic/parse.js +84 -0
- package/dist/critic/parse.js.map +1 -0
- package/dist/critic/prompt.d.ts +14 -0
- package/dist/critic/prompt.js +56 -0
- package/dist/critic/prompt.js.map +1 -0
- package/dist/critic/types.d.ts +52 -0
- package/dist/critic/types.js +2 -0
- package/dist/critic/types.js.map +1 -0
- package/dist/designer/agent-sdk-model.d.ts +30 -0
- package/dist/designer/agent-sdk-model.js +62 -0
- package/dist/designer/agent-sdk-model.js.map +1 -0
- package/dist/designer/design.d.ts +12 -0
- package/dist/designer/design.js +218 -0
- package/dist/designer/design.js.map +1 -0
- package/dist/designer/fitness.d.ts +25 -0
- package/dist/designer/fitness.js +24 -0
- package/dist/designer/fitness.js.map +1 -0
- package/dist/designer/model.d.ts +14 -0
- package/dist/designer/model.js +27 -0
- package/dist/designer/model.js.map +1 -0
- package/dist/designer/mutate.d.ts +31 -0
- package/dist/designer/mutate.js +209 -0
- package/dist/designer/mutate.js.map +1 -0
- package/dist/designer/rng.d.ts +17 -0
- package/dist/designer/rng.js +40 -0
- package/dist/designer/rng.js.map +1 -0
- package/dist/designer/types.d.ts +103 -0
- package/dist/designer/types.js +2 -0
- package/dist/designer/types.js.map +1 -0
- package/dist/evaluate.d.ts +11 -0
- package/dist/evaluate.js +99 -0
- package/dist/evaluate.js.map +1 -0
- package/dist/gauntlet/gauntlet.d.ts +18 -0
- package/dist/gauntlet/gauntlet.js +41 -0
- package/dist/gauntlet/gauntlet.js.map +1 -0
- package/dist/gauntlet/teams-g1.d.ts +23 -0
- package/dist/gauntlet/teams-g1.js +476 -0
- package/dist/gauntlet/teams-g1.js.map +1 -0
- package/dist/gauntlet/teams-g2.d.ts +14 -0
- package/dist/gauntlet/teams-g2.js +725 -0
- package/dist/gauntlet/teams-g2.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/agent-query.d.ts +21 -0
- package/dist/llm/agent-query.js +70 -0
- package/dist/llm/agent-query.js.map +1 -0
- package/dist/pilot/damage.d.ts +34 -0
- package/dist/pilot/damage.js +75 -0
- package/dist/pilot/damage.js.map +1 -0
- package/dist/pilot/eval-pilot.d.ts +39 -0
- package/dist/pilot/eval-pilot.js +161 -0
- package/dist/pilot/eval-pilot.js.map +1 -0
- package/dist/pilot/pilot.d.ts +71 -0
- package/dist/pilot/pilot.js +290 -0
- package/dist/pilot/pilot.js.map +1 -0
- package/dist/ranking.d.ts +25 -0
- package/dist/ranking.js +40 -0
- package/dist/ranking.js.map +1 -0
- package/dist/seed.d.ts +13 -0
- package/dist/seed.js +42 -0
- package/dist/seed.js.map +1 -0
- package/dist/team.d.ts +29 -0
- package/dist/team.js +100 -0
- package/dist/team.js.map +1 -0
- package/dist/types.d.ts +77 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Pilot — one competent Gen 3 heuristic policy, identical on both sides
|
|
3
|
+
* (ADR 0002). Given the omniscient battle state and the current request, it
|
|
4
|
+
* returns a Showdown choice string.
|
|
5
|
+
*
|
|
6
|
+
* Competence is layered as an ordered decision tree; each layer only fires when
|
|
7
|
+
* the earlier, higher-priority ones decline:
|
|
8
|
+
* 1. secure a KO we can safely land (max-damage core)
|
|
9
|
+
* 2. pivot out of a losing matchup (matchup switching)
|
|
10
|
+
* 3. heal when worn down and safe (recovery / stall)
|
|
11
|
+
* 4. lay Spikes / spin them away (hazards)
|
|
12
|
+
* 5. spread status on a fresh target (Toxic / paralysis / burn)
|
|
13
|
+
* 6. set up when the foe can't pressure us (Dragon Dance, Calm Mind, ...)
|
|
14
|
+
* 7. otherwise hit as hard as possible (max-damage fallback)
|
|
15
|
+
*
|
|
16
|
+
* Per ADR 0002 / the PRD, the Pilot is never asserted move-by-move: its
|
|
17
|
+
* competence is judged only through outcome thresholds at the `evaluate` seam.
|
|
18
|
+
*/
|
|
19
|
+
import { BattleStreams } from '@pkmn/sim';
|
|
20
|
+
import { bestDamageFraction, estimateDamageFraction, resolveMove, } from './damage.js';
|
|
21
|
+
// --- Move classifications -------------------------------------------------
|
|
22
|
+
const RECOVERY = new Set([
|
|
23
|
+
'recover', 'softboiled', 'milkdrink', 'slackoff', 'moonlight', 'morningsun',
|
|
24
|
+
'synthesis', 'rest', 'wish',
|
|
25
|
+
]);
|
|
26
|
+
const SPIKES = 'spikes';
|
|
27
|
+
const RAPID_SPIN = 'rapidspin';
|
|
28
|
+
const TOXIC = 'toxic';
|
|
29
|
+
const PARALYZE = new Set(['thunderwave', 'stunspore', 'glare']);
|
|
30
|
+
const BURN = new Set(['willowisp']);
|
|
31
|
+
const PHAZE = new Set(['roar', 'whirlwind']);
|
|
32
|
+
/** Setup moves → the offensive stat they raise and the boost level to stop at. */
|
|
33
|
+
const SETUP = {
|
|
34
|
+
swordsdance: { stat: 'atk', cap: 2 },
|
|
35
|
+
dragondance: { stat: 'atk', cap: 2 },
|
|
36
|
+
bulkup: { stat: 'atk', cap: 2 },
|
|
37
|
+
curse: { stat: 'atk', cap: 2 },
|
|
38
|
+
calmmind: { stat: 'spa', cap: 3 },
|
|
39
|
+
agility: { stat: 'spe', cap: 2 },
|
|
40
|
+
};
|
|
41
|
+
// --- Small state helpers --------------------------------------------------
|
|
42
|
+
function hpFraction(p) {
|
|
43
|
+
return p.maxhp > 0 ? p.hp / p.maxhp : 0;
|
|
44
|
+
}
|
|
45
|
+
function effectiveSpeed(p) {
|
|
46
|
+
let spe = p.getStat('spe');
|
|
47
|
+
if (p.status === 'par')
|
|
48
|
+
spe = Math.floor(spe * 0.25);
|
|
49
|
+
return spe;
|
|
50
|
+
}
|
|
51
|
+
function spikesLayers(side) {
|
|
52
|
+
const cond = side.sideConditions?.['spikes'];
|
|
53
|
+
if (!cond)
|
|
54
|
+
return 0;
|
|
55
|
+
return typeof cond.layers === 'number' ? cond.layers : 1;
|
|
56
|
+
}
|
|
57
|
+
/** Find the live battle Pokemon matching a request slot (Species Clause ⇒ unique). */
|
|
58
|
+
function battleMon(team, rp) {
|
|
59
|
+
const species = (rp.details.split(',')[0] ?? '').trim();
|
|
60
|
+
return team.find((m) => m && m.species && m.species.name === species) ?? null;
|
|
61
|
+
}
|
|
62
|
+
function isFainted(rp) {
|
|
63
|
+
return rp.condition.includes('fnt');
|
|
64
|
+
}
|
|
65
|
+
/** Moves that are actually choosable this turn (present, not disabled, PP left). */
|
|
66
|
+
function usableMoves(battle, me, active) {
|
|
67
|
+
const out = [];
|
|
68
|
+
active.moves.forEach((rm, i) => {
|
|
69
|
+
if (rm.disabled)
|
|
70
|
+
return;
|
|
71
|
+
if (typeof rm.pp === 'number' && rm.pp <= 0)
|
|
72
|
+
return;
|
|
73
|
+
const name = me.set?.moves?.[i] ?? rm.move ?? rm.id;
|
|
74
|
+
out.push({ index: i, move: resolveMove(battle, name) });
|
|
75
|
+
});
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
// --- Status legality (heuristic, Gen 3) -----------------------------------
|
|
79
|
+
function canToxic(foe) {
|
|
80
|
+
return (!foe.types.includes('Steel') &&
|
|
81
|
+
!foe.types.includes('Poison') &&
|
|
82
|
+
foe.ability !== 'immunity');
|
|
83
|
+
}
|
|
84
|
+
function canParalyze(battle, moveId, foe) {
|
|
85
|
+
if (foe.ability === 'limber')
|
|
86
|
+
return false;
|
|
87
|
+
// Thunder Wave respects Electric-type immunity (Ground is immune); powders don't hit Grass? (Grass isn't immune in gen 3).
|
|
88
|
+
if (moveId === 'thunderwave' && !battle.dex.getImmunity('Electric', foe.types))
|
|
89
|
+
return false;
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
function canBurn(foe) {
|
|
93
|
+
return !foe.types.includes('Fire') && foe.ability !== 'waterveil';
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Best Pokemon to bring in against `foe`: the one that takes the least from the
|
|
97
|
+
* foe's hardest hit, lightly favouring candidates that threaten back.
|
|
98
|
+
* `requireOffense` filters to candidates that can actually dent the foe.
|
|
99
|
+
*/
|
|
100
|
+
function bestSwitch(battle, sideID, request, foe, requireOffense = false) {
|
|
101
|
+
const myIdx = sideID === 'p1' ? 0 : 1;
|
|
102
|
+
const team = battle.sides[myIdx]?.pokemon ?? [];
|
|
103
|
+
let best = null;
|
|
104
|
+
let bestValue = -Infinity;
|
|
105
|
+
request.side.pokemon.forEach((rp, i) => {
|
|
106
|
+
if (rp.active || isFainted(rp))
|
|
107
|
+
return;
|
|
108
|
+
const c = battleMon(team, rp);
|
|
109
|
+
if (!c)
|
|
110
|
+
return;
|
|
111
|
+
const foeDamage = bestDamageFraction(battle, foe, c);
|
|
112
|
+
const myDamage = bestDamageFraction(battle, c, foe);
|
|
113
|
+
if (requireOffense && myDamage < 0.12)
|
|
114
|
+
return;
|
|
115
|
+
// Favour candidates that take the least from the foe's hardest hit, with a
|
|
116
|
+
// small bonus for those that threaten back.
|
|
117
|
+
const value = -foeDamage + 0.3 * Math.min(myDamage, 1);
|
|
118
|
+
if (value > bestValue) {
|
|
119
|
+
bestValue = value;
|
|
120
|
+
best = { choiceIndex: i + 1, foeDamage };
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
return best;
|
|
124
|
+
}
|
|
125
|
+
// --- The decision ---------------------------------------------------------
|
|
126
|
+
function defaultMove(active) {
|
|
127
|
+
const i = active.moves.findIndex((m) => !m.disabled && (m.pp === undefined || m.pp > 0));
|
|
128
|
+
return i >= 0 ? `move ${i + 1}` : 'move 1';
|
|
129
|
+
}
|
|
130
|
+
/** The first alive benched Pokemon, as a `switch N` choice (or `pass`). */
|
|
131
|
+
function firstAliveSwitch(request) {
|
|
132
|
+
const i = request.side.pokemon.findIndex((p) => !p.active && !isFainted(p));
|
|
133
|
+
return i >= 0 ? `switch ${i + 1}` : 'pass';
|
|
134
|
+
}
|
|
135
|
+
export function chooseAction(battle, sideID, request) {
|
|
136
|
+
const myIdx = sideID === 'p1' ? 0 : 1;
|
|
137
|
+
const mySide = battle.sides[myIdx];
|
|
138
|
+
const foeSide = battle.sides[1 - myIdx];
|
|
139
|
+
const me = mySide?.active?.[0];
|
|
140
|
+
const foe = foeSide?.active?.[0];
|
|
141
|
+
// Forced to send in a new Pokemon (ours fainted / was dragged out).
|
|
142
|
+
if (request.forceSwitch?.[0]) {
|
|
143
|
+
if (foe) {
|
|
144
|
+
const sw = bestSwitch(battle, sideID, request, foe);
|
|
145
|
+
if (sw)
|
|
146
|
+
return `switch ${sw.choiceIndex}`;
|
|
147
|
+
}
|
|
148
|
+
return firstAliveSwitch(request);
|
|
149
|
+
}
|
|
150
|
+
const active = request.active?.[0];
|
|
151
|
+
if (!active)
|
|
152
|
+
return 'default'; // team preview (none in gen 3) or nothing to do
|
|
153
|
+
if (!me || !foe || !mySide || !foeSide)
|
|
154
|
+
return defaultMove(active);
|
|
155
|
+
const usable = usableMoves(battle, me, active);
|
|
156
|
+
const damaging = usable
|
|
157
|
+
.map((u) => ({ ...u, frac: estimateDamageFraction(battle, me, foe, u.move) }))
|
|
158
|
+
.filter((u) => u.frac > 0)
|
|
159
|
+
.sort((a, b) => b.frac * b.move.accuracy - a.frac * a.move.accuracy);
|
|
160
|
+
const best = damaging[0];
|
|
161
|
+
const myHp = hpFraction(me);
|
|
162
|
+
const foeHp = hpFraction(foe);
|
|
163
|
+
const foeThreat = bestDamageFraction(battle, foe, me);
|
|
164
|
+
const iAmFaster = effectiveSpeed(me) > effectiveSpeed(foe);
|
|
165
|
+
const myKO = best ? best.frac >= foeHp : false;
|
|
166
|
+
const foeKO = foeThreat >= myHp;
|
|
167
|
+
const safe = !foeKO || (iAmFaster && myKO);
|
|
168
|
+
const trapped = active.trapped || active.maybeTrapped;
|
|
169
|
+
const canSwitch = !trapped && request.side.pokemon.some((p) => !p.active && !isFainted(p));
|
|
170
|
+
// 1) Secure a KO we can safely land.
|
|
171
|
+
if (best && myKO && (iAmFaster || !foeKO))
|
|
172
|
+
return `move ${best.index + 1}`;
|
|
173
|
+
// 2) Losing matchup: the foe threatens to KO us and we can't KO first — pivot
|
|
174
|
+
// to a teammate that walls it better.
|
|
175
|
+
if (canSwitch && foeKO && !(myKO && iAmFaster)) {
|
|
176
|
+
const sw = bestSwitch(battle, sideID, request, foe);
|
|
177
|
+
if (sw && sw.foeDamage < foeThreat * 0.85 && sw.foeDamage < 0.6) {
|
|
178
|
+
return `switch ${sw.choiceIndex}`;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const foeBoosted = foe.boosts.atk > 0 || foe.boosts.spa > 0 || foe.boosts.spe > 0;
|
|
182
|
+
const foeHasSub = !!foe.volatiles && 'substitute' in foe.volatiles;
|
|
183
|
+
const strongHit = !!best && best.frac >= 0.45;
|
|
184
|
+
// 3) Phaze a Pokemon setting up on us — undo its boosts and rack Spikes chip.
|
|
185
|
+
if (foeBoosted && (iAmFaster || !foeKO)) {
|
|
186
|
+
const phaze = usable.find((u) => PHAZE.has(u.move.id));
|
|
187
|
+
if (phaze)
|
|
188
|
+
return `move ${phaze.index + 1}`;
|
|
189
|
+
}
|
|
190
|
+
// 4) Defensive utility — the heart of competent stall. A wall stays in on a
|
|
191
|
+
// foe it can't hurt (as long as it's safe) and does something useful:
|
|
192
|
+
// heal, lay Spikes, cripple with burn/Toxic/paralysis, spin hazards away.
|
|
193
|
+
if (safe) {
|
|
194
|
+
if (myHp < 0.55) {
|
|
195
|
+
const rec = usable.find((u) => RECOVERY.has(u.move.id));
|
|
196
|
+
if (rec)
|
|
197
|
+
return `move ${rec.index + 1}`;
|
|
198
|
+
}
|
|
199
|
+
const spikes = usable.find((u) => u.move.id === SPIKES);
|
|
200
|
+
if (spikes && spikesLayers(foeSide) < 3)
|
|
201
|
+
return `move ${spikes.index + 1}`;
|
|
202
|
+
// Status is worth a turn only when we can't just beat the foe down.
|
|
203
|
+
if (!strongHit && foe.status === '' && !foeHasSub) {
|
|
204
|
+
const foePhysical = foe.getStat('atk') >= foe.getStat('spa');
|
|
205
|
+
if (foePhysical) {
|
|
206
|
+
const wisp = usable.find((u) => BURN.has(u.move.id) && canBurn(foe));
|
|
207
|
+
if (wisp)
|
|
208
|
+
return `move ${wisp.index + 1}`;
|
|
209
|
+
}
|
|
210
|
+
if (foeHp > 0.5) {
|
|
211
|
+
const toxic = usable.find((u) => u.move.id === TOXIC);
|
|
212
|
+
if (toxic && canToxic(foe))
|
|
213
|
+
return `move ${toxic.index + 1}`;
|
|
214
|
+
}
|
|
215
|
+
if (!iAmFaster) {
|
|
216
|
+
const para = usable.find((u) => PARALYZE.has(u.move.id) && canParalyze(battle, u.move.id, foe));
|
|
217
|
+
if (para)
|
|
218
|
+
return `move ${para.index + 1}`;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const spin = usable.find((u) => u.move.id === RAPID_SPIN);
|
|
222
|
+
if (spin && spikesLayers(mySide) > 0)
|
|
223
|
+
return `move ${spin.index + 1}`;
|
|
224
|
+
// 5) Set up while the foe can't pressure us.
|
|
225
|
+
if (foeThreat < 0.35 && foeHp > 0.6) {
|
|
226
|
+
const setup = usable.find((u) => {
|
|
227
|
+
const s = SETUP[u.move.id];
|
|
228
|
+
return s && me.boosts[s.stat] < s.cap;
|
|
229
|
+
});
|
|
230
|
+
if (setup)
|
|
231
|
+
return `move ${setup.index + 1}`;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// 6) Otherwise, hit as hard as possible.
|
|
235
|
+
if (best && best.frac >= 0.06)
|
|
236
|
+
return `move ${best.index + 1}`;
|
|
237
|
+
// 7) We can't meaningfully damage the foe. If safe with nothing useful left,
|
|
238
|
+
// pivot to a teammate that threatens it; else make the best move we have.
|
|
239
|
+
if (canSwitch) {
|
|
240
|
+
const sw = bestSwitch(battle, sideID, request, foe, /*requireOffense*/ true);
|
|
241
|
+
if (sw && sw.foeDamage < 0.85)
|
|
242
|
+
return `switch ${sw.choiceIndex}`;
|
|
243
|
+
}
|
|
244
|
+
if (best)
|
|
245
|
+
return `move ${best.index + 1}`;
|
|
246
|
+
if (usable[0])
|
|
247
|
+
return `move ${usable[0].index + 1}`;
|
|
248
|
+
return defaultMove(active);
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* A player that drives one side of a BattleStream with the heuristic Pilot.
|
|
252
|
+
* It reads the shared omniscient {@link Battle} through `getBattle` (both sides
|
|
253
|
+
* see the same information, so the contest stays fair).
|
|
254
|
+
*/
|
|
255
|
+
export class PilotPlayer extends BattleStreams.BattlePlayer {
|
|
256
|
+
getBattle;
|
|
257
|
+
sideID;
|
|
258
|
+
/** Guards against re-entrant recovery within a single stuck decision. */
|
|
259
|
+
recovering = false;
|
|
260
|
+
constructor(playerStream, getBattle, sideID) {
|
|
261
|
+
super(playerStream);
|
|
262
|
+
this.getBattle = getBattle;
|
|
263
|
+
this.sideID = sideID;
|
|
264
|
+
}
|
|
265
|
+
receiveRequest(request) {
|
|
266
|
+
this.recovering = false; // a fresh request clears any prior recovery
|
|
267
|
+
if (request?.wait)
|
|
268
|
+
return; // opponent must act; nothing for us to choose
|
|
269
|
+
const battle = this.getBattle();
|
|
270
|
+
if (!battle) {
|
|
271
|
+
this.choose('default');
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
this.choose(chooseAction(battle, this.sideID, request));
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Safety net: if the heuristic ever produces an illegal choice (e.g. an
|
|
278
|
+
* uncertain trap it mis-read), fall back to the safest legal action instead
|
|
279
|
+
* of aborting the whole evaluation. Any other error still propagates.
|
|
280
|
+
*/
|
|
281
|
+
receiveError(error) {
|
|
282
|
+
if (!this.recovering && /\[(Invalid|Unavailable) choice\]/.test(error.message)) {
|
|
283
|
+
this.recovering = true;
|
|
284
|
+
this.choose('default');
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
throw error;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=pilot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pilot.js","sourceRoot":"","sources":["../../src/pilot/pilot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ranking / aggregation. Strength is a win-rate under the Pilot; each row also
|
|
3
|
+
* carries a 95% Wilson confidence interval so callers don't over-read a
|
|
4
|
+
* difference that's within noise. Elo/Glicko is deferred (out of scope).
|
|
5
|
+
*/
|
|
6
|
+
import type { MatchupResult, StrengthRow } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Wilson score interval for a binomial proportion. `successes` may be
|
|
9
|
+
* fractional (ties count as half a win); `n` is the battle count.
|
|
10
|
+
*/
|
|
11
|
+
export declare function wilsonInterval(successes: number, n: number, z?: number): [number, number];
|
|
12
|
+
/** Fractional successes for a matchup: full for wins, half for ties. */
|
|
13
|
+
export declare function successes(m: {
|
|
14
|
+
wins: number;
|
|
15
|
+
battles: number;
|
|
16
|
+
winRate: number;
|
|
17
|
+
}): number;
|
|
18
|
+
/**
|
|
19
|
+
* Build a Strength row for one Team from its per-opponent matchups. Overall
|
|
20
|
+
* Strength is total successes over total battles (a raw win-rate), which for
|
|
21
|
+
* equal battle counts per matchup equals the mean of the per-matchup win-rates.
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildStrengthRow(team: string, matchups: MatchupResult[]): StrengthRow;
|
|
24
|
+
/** Sort strongest first; ties broken by name so the order is deterministic. */
|
|
25
|
+
export declare function rankRows(rows: StrengthRow[]): StrengthRow[];
|
package/dist/ranking.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wilson score interval for a binomial proportion. `successes` may be
|
|
3
|
+
* fractional (ties count as half a win); `n` is the battle count.
|
|
4
|
+
*/
|
|
5
|
+
export function wilsonInterval(successes, n, z = 1.96) {
|
|
6
|
+
if (n <= 0)
|
|
7
|
+
return [0, 0];
|
|
8
|
+
const p = successes / n;
|
|
9
|
+
const z2 = z * z;
|
|
10
|
+
const denom = 1 + z2 / n;
|
|
11
|
+
const center = (p + z2 / (2 * n)) / denom;
|
|
12
|
+
const margin = (z * Math.sqrt((p * (1 - p) + z2 / (4 * n)) / n)) / denom;
|
|
13
|
+
return [Math.max(0, center - margin), Math.min(1, center + margin)];
|
|
14
|
+
}
|
|
15
|
+
/** Fractional successes for a matchup: full for wins, half for ties. */
|
|
16
|
+
export function successes(m) {
|
|
17
|
+
return m.winRate * m.battles;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Build a Strength row for one Team from its per-opponent matchups. Overall
|
|
21
|
+
* Strength is total successes over total battles (a raw win-rate), which for
|
|
22
|
+
* equal battle counts per matchup equals the mean of the per-matchup win-rates.
|
|
23
|
+
*/
|
|
24
|
+
export function buildStrengthRow(team, matchups) {
|
|
25
|
+
const battles = matchups.reduce((s, m) => s + m.battles, 0);
|
|
26
|
+
const succ = matchups.reduce((s, m) => s + successes(m), 0);
|
|
27
|
+
const strength = battles > 0 ? succ / battles : 0;
|
|
28
|
+
return {
|
|
29
|
+
team,
|
|
30
|
+
strength,
|
|
31
|
+
battles,
|
|
32
|
+
ci95: wilsonInterval(succ, battles),
|
|
33
|
+
matchups,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Sort strongest first; ties broken by name so the order is deterministic. */
|
|
37
|
+
export function rankRows(rows) {
|
|
38
|
+
return [...rows].sort((a, b) => b.strength - a.strength || a.team.localeCompare(b.team));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=ranking.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ranking.js","sourceRoot":"","sources":["../src/ranking.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,CAAS,EAAE,CAAC,GAAG,IAAI;IACnE,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1B,MAAM,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC;IACxB,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;IACjB,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACzB,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IAC1C,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC;IACzE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;AACtE,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,SAAS,CAAC,CAAqD;IAC7E,OAAO,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY,EAAE,QAAyB;IACtE,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,OAAO;QACL,IAAI;QACJ,QAAQ;QACR,OAAO;QACP,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC;QACnC,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,QAAQ,CAAC,IAAmB;IAC1C,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3F,CAAC"}
|
package/dist/seed.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic seed derivation. A single master seed (a string) threads through
|
|
3
|
+
* the whole run; every Battle gets a sub-seed derived from the master plus the
|
|
4
|
+
* pairing and battle indices, so a fixed master reproduces identical results
|
|
5
|
+
* regardless of iteration order.
|
|
6
|
+
*/
|
|
7
|
+
/** `@pkmn/sim`'s PRNG seed: four 16-bit words. */
|
|
8
|
+
export type PRNGSeed = [number, number, number, number];
|
|
9
|
+
/**
|
|
10
|
+
* Derive a reproducible 4-word PRNG seed from the master seed and any number of
|
|
11
|
+
* integer indices (e.g. team index, opponent index, battle index).
|
|
12
|
+
*/
|
|
13
|
+
export declare function deriveSeed(master: string, ...ints: number[]): PRNGSeed;
|
package/dist/seed.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic seed derivation. A single master seed (a string) threads through
|
|
3
|
+
* the whole run; every Battle gets a sub-seed derived from the master plus the
|
|
4
|
+
* pairing and battle indices, so a fixed master reproduces identical results
|
|
5
|
+
* regardless of iteration order.
|
|
6
|
+
*/
|
|
7
|
+
function fnv1a(master, ints) {
|
|
8
|
+
let h = 2166136261 >>> 0;
|
|
9
|
+
const mix = (x) => {
|
|
10
|
+
h ^= x & 0xff;
|
|
11
|
+
h = Math.imul(h, 16777619) >>> 0;
|
|
12
|
+
h ^= (x >>> 8) & 0xff;
|
|
13
|
+
h = Math.imul(h, 16777619) >>> 0;
|
|
14
|
+
h ^= (x >>> 16) & 0xff;
|
|
15
|
+
h = Math.imul(h, 16777619) >>> 0;
|
|
16
|
+
h ^= (x >>> 24) & 0xff;
|
|
17
|
+
h = Math.imul(h, 16777619) >>> 0;
|
|
18
|
+
};
|
|
19
|
+
for (let i = 0; i < master.length; i++)
|
|
20
|
+
mix(master.charCodeAt(i));
|
|
21
|
+
mix(0x9e3779b1);
|
|
22
|
+
for (const n of ints)
|
|
23
|
+
mix(n >>> 0);
|
|
24
|
+
return h >>> 0;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Derive a reproducible 4-word PRNG seed from the master seed and any number of
|
|
28
|
+
* integer indices (e.g. team index, opponent index, battle index).
|
|
29
|
+
*/
|
|
30
|
+
export function deriveSeed(master, ...ints) {
|
|
31
|
+
let s = fnv1a(master, ints);
|
|
32
|
+
// mulberry32 stepped four times → four independent 16-bit words.
|
|
33
|
+
const next = () => {
|
|
34
|
+
s = (s + 0x6d2b79f5) >>> 0;
|
|
35
|
+
let t = s;
|
|
36
|
+
t = Math.imul(t ^ (t >>> 15), t | 1);
|
|
37
|
+
t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
|
|
38
|
+
return (t ^ (t >>> 14)) >>> 0;
|
|
39
|
+
};
|
|
40
|
+
return [next() % 65536, next() % 65536, next() % 65536, next() % 65536];
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=seed.js.map
|
package/dist/seed.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed.js","sourceRoot":"","sources":["../src/seed.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,SAAS,KAAK,CAAC,MAAc,EAAE,IAAc;IAC3C,IAAI,CAAC,GAAG,UAAU,KAAK,CAAC,CAAC;IACzB,MAAM,GAAG,GAAG,CAAC,CAAS,EAAE,EAAE;QACxB,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACd,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC;QACtB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;QACvB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC;QACvB,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,CAAC;IACF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAClE,GAAG,CAAC,UAAU,CAAC,CAAC;IAChB,KAAK,MAAM,CAAC,IAAI,IAAI;QAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;IACnC,OAAO,CAAC,KAAK,CAAC,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc,EAAE,GAAG,IAAc;IAC1D,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC5B,iEAAiE;IACjE,MAAM,IAAI,GAAG,GAAW,EAAE;QACxB,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACrC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;QAC1C,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC,CAAC;IACF,OAAO,CAAC,IAAI,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,CAAC;AAC1E,CAAC"}
|
package/dist/team.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { PokemonSet } from '@pkmn/sim';
|
|
2
|
+
import { type Submission, type ValidationError } from './types.js';
|
|
3
|
+
export type Team = PokemonSet[];
|
|
4
|
+
/** A submission that parsed and passed Gen 3 OU legality. */
|
|
5
|
+
export interface LegalTeam {
|
|
6
|
+
name: string;
|
|
7
|
+
team: Team;
|
|
8
|
+
/** The packed form fed to the sim's `>player` command. */
|
|
9
|
+
packed: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Split a raw paste that may hold several Teams (Showdown's multi-team export
|
|
13
|
+
* uses `=== [format] name ===` header lines) into one {@link Submission} each.
|
|
14
|
+
* A paste with no header markers is treated as a single unnamed Team.
|
|
15
|
+
*/
|
|
16
|
+
export declare function splitSubmissions(raw: string): Submission[];
|
|
17
|
+
/** Normalize the flexible `teams` input of {@link EvaluateInput} into Submissions. */
|
|
18
|
+
export declare function toSubmissions(input: string | Array<string | Submission>): Submission[];
|
|
19
|
+
export interface ParseOutcome {
|
|
20
|
+
legal: LegalTeam[];
|
|
21
|
+
errors: ValidationError[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Parse and legality-check a batch of submissions. Never throws for team
|
|
25
|
+
* content problems: unparseable or illegal Teams become {@link ValidationError}s.
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseAndValidate(submissions: Submission[]): ParseOutcome;
|
|
28
|
+
/** Round-trip a single paste through parse + serialize (used by tests/tools). */
|
|
29
|
+
export declare function reserialize(paste: string): string;
|
package/dist/team.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Team I/O — parse and serialize Showdown paste text and validate legality as
|
|
3
|
+
* Gen 3 OU. Illegal Teams surface as {@link ValidationError} values rather than
|
|
4
|
+
* throwing, so the `evaluate` seam can report them instead of crashing.
|
|
5
|
+
*/
|
|
6
|
+
import { Teams, TeamValidator } from '@pkmn/sim';
|
|
7
|
+
import { FORMAT } from './types.js';
|
|
8
|
+
// One shared validator; constructing it parses the whole gen-3 ruleset.
|
|
9
|
+
const validator = new TeamValidator(FORMAT);
|
|
10
|
+
/**
|
|
11
|
+
* Split a raw paste that may hold several Teams (Showdown's multi-team export
|
|
12
|
+
* uses `=== [format] name ===` header lines) into one {@link Submission} each.
|
|
13
|
+
* A paste with no header markers is treated as a single unnamed Team.
|
|
14
|
+
*/
|
|
15
|
+
export function splitSubmissions(raw) {
|
|
16
|
+
const headerRe = /^===\s*(?:\[[^\]]*\]\s*)?(.*?)\s*===\s*$/;
|
|
17
|
+
const lines = raw.replace(/\r\n/g, '\n').split('\n');
|
|
18
|
+
const hasHeaders = lines.some((l) => headerRe.test(l.trim()));
|
|
19
|
+
if (!hasHeaders) {
|
|
20
|
+
const paste = raw.trim();
|
|
21
|
+
return paste ? [{ name: '', paste }] : [];
|
|
22
|
+
}
|
|
23
|
+
const out = [];
|
|
24
|
+
let name = '';
|
|
25
|
+
let buf = [];
|
|
26
|
+
const flush = () => {
|
|
27
|
+
const paste = buf.join('\n').trim();
|
|
28
|
+
if (paste)
|
|
29
|
+
out.push({ name, paste });
|
|
30
|
+
buf = [];
|
|
31
|
+
};
|
|
32
|
+
for (const line of lines) {
|
|
33
|
+
const m = headerRe.exec(line.trim());
|
|
34
|
+
if (m) {
|
|
35
|
+
flush();
|
|
36
|
+
name = (m[1] ?? '').trim();
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
buf.push(line);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
flush();
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
/** Normalize the flexible `teams` input of {@link EvaluateInput} into Submissions. */
|
|
46
|
+
export function toSubmissions(input) {
|
|
47
|
+
if (typeof input === 'string')
|
|
48
|
+
return splitSubmissions(input);
|
|
49
|
+
const out = [];
|
|
50
|
+
for (const entry of input) {
|
|
51
|
+
if (typeof entry === 'string')
|
|
52
|
+
out.push(...splitSubmissions(entry));
|
|
53
|
+
else
|
|
54
|
+
out.push(entry);
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
/** A fallback display name derived from a parsed Team's lead species. */
|
|
59
|
+
function defaultName(team, index) {
|
|
60
|
+
const lead = team[0];
|
|
61
|
+
const species = lead?.species || lead?.name;
|
|
62
|
+
return species ? `${species} team` : `Team ${index + 1}`;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Parse and legality-check a batch of submissions. Never throws for team
|
|
66
|
+
* content problems: unparseable or illegal Teams become {@link ValidationError}s.
|
|
67
|
+
*/
|
|
68
|
+
export function parseAndValidate(submissions) {
|
|
69
|
+
const legal = [];
|
|
70
|
+
const errors = [];
|
|
71
|
+
submissions.forEach((sub, i) => {
|
|
72
|
+
let team;
|
|
73
|
+
try {
|
|
74
|
+
team = Teams.import(sub.paste);
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
team = null;
|
|
78
|
+
}
|
|
79
|
+
const name = sub.name || (team ? defaultName(team, i) : `Team ${i + 1}`);
|
|
80
|
+
if (!team || team.length === 0) {
|
|
81
|
+
errors.push({ team: name, problems: ['Could not parse any Pokémon from the paste.'] });
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const problems = validator.validateTeam(team);
|
|
85
|
+
if (problems && problems.length > 0) {
|
|
86
|
+
errors.push({ team: name, problems });
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
legal.push({ name, team, packed: Teams.pack(team) });
|
|
90
|
+
});
|
|
91
|
+
return { legal, errors };
|
|
92
|
+
}
|
|
93
|
+
/** Round-trip a single paste through parse + serialize (used by tests/tools). */
|
|
94
|
+
export function reserialize(paste) {
|
|
95
|
+
const team = Teams.import(paste);
|
|
96
|
+
if (!team)
|
|
97
|
+
throw new Error('unparseable team');
|
|
98
|
+
return Teams.export(team);
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=team.js.map
|
package/dist/team.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team.js","sourceRoot":"","sources":["../src/team.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public result contract for the evaluation harness.
|
|
3
|
+
*
|
|
4
|
+
* This is the structure the Slice-2 Critic will read, so it is the stable
|
|
5
|
+
* shape callers depend on. See the PRD "Results contract".
|
|
6
|
+
*/
|
|
7
|
+
export declare const FORMAT: "gen3ou";
|
|
8
|
+
export type Mode = 'gauntlet' | 'round-robin';
|
|
9
|
+
/** A team the user submitted for evaluation, as Showdown paste text. */
|
|
10
|
+
export interface Submission {
|
|
11
|
+
/** Display name for reports (defaults to the lead species when omitted). */
|
|
12
|
+
name: string;
|
|
13
|
+
/** Standard Showdown export/paste text for one Team. */
|
|
14
|
+
paste: string;
|
|
15
|
+
}
|
|
16
|
+
/** Opposition configuration: what the submitted Teams are measured against. */
|
|
17
|
+
export type Opposition = {
|
|
18
|
+
mode: 'gauntlet';
|
|
19
|
+
gauntletVersion?: string;
|
|
20
|
+
} | {
|
|
21
|
+
mode: 'round-robin';
|
|
22
|
+
};
|
|
23
|
+
export interface EvaluateInput {
|
|
24
|
+
/**
|
|
25
|
+
* Submitted Teams. Either an array of pastes / {name,paste} entries, or a
|
|
26
|
+
* single string containing one or more Teams (multi-team `=== name ===`
|
|
27
|
+
* markers are split apart).
|
|
28
|
+
*/
|
|
29
|
+
teams: string | Array<string | Submission>;
|
|
30
|
+
opposition: Opposition;
|
|
31
|
+
/** Battles run per Team-vs-opponent pairing (sides swapped 50/50). */
|
|
32
|
+
battlesPerPairing?: number;
|
|
33
|
+
/** Master seed; identical seed + teams + config reproduces identical results. */
|
|
34
|
+
seed?: string;
|
|
35
|
+
}
|
|
36
|
+
/** A submitted Team that failed Gen 3 OU legality, named so the user can fix it. */
|
|
37
|
+
export interface ValidationError {
|
|
38
|
+
team: string;
|
|
39
|
+
problems: string[];
|
|
40
|
+
}
|
|
41
|
+
/** Win-rate of a submitted Team against one specific opponent. */
|
|
42
|
+
export interface MatchupResult {
|
|
43
|
+
/** Opponent name — a Gauntlet member or a peer Team. */
|
|
44
|
+
opponent: string;
|
|
45
|
+
/** Archetype label of the opponent (Gauntlet members only). */
|
|
46
|
+
archetype?: string;
|
|
47
|
+
/** Battles won outright. */
|
|
48
|
+
wins: number;
|
|
49
|
+
/** Battles that ended in a tie (counted as half a win in `winRate`). */
|
|
50
|
+
ties: number;
|
|
51
|
+
battles: number;
|
|
52
|
+
/** (wins + ties/2) / battles, in [0, 1]. */
|
|
53
|
+
winRate: number;
|
|
54
|
+
}
|
|
55
|
+
/** One row of the Strength ranking. */
|
|
56
|
+
export interface StrengthRow {
|
|
57
|
+
team: string;
|
|
58
|
+
/** Overall Strength: win-rate under the Pilot, in [0, 1]. */
|
|
59
|
+
strength: number;
|
|
60
|
+
battles: number;
|
|
61
|
+
/** 95% Wilson confidence interval on the overall win-rate. */
|
|
62
|
+
ci95: [number, number];
|
|
63
|
+
/** Per-opponent breakdown. */
|
|
64
|
+
matchups: MatchupResult[];
|
|
65
|
+
}
|
|
66
|
+
/** The full structured result returned from the single `evaluate` seam. */
|
|
67
|
+
export interface EvaluationResult {
|
|
68
|
+
mode: Mode;
|
|
69
|
+
seed: string;
|
|
70
|
+
/** Present in gauntlet mode; records which Gauntlet version produced the result. */
|
|
71
|
+
gauntletVersion?: string;
|
|
72
|
+
battlesPerPairing: number;
|
|
73
|
+
/** Strength rows, sorted strongest first. */
|
|
74
|
+
ranking: StrengthRow[];
|
|
75
|
+
/** Submitted Teams that were illegal and therefore not run. */
|
|
76
|
+
errors: ValidationError[];
|
|
77
|
+
}
|