Skip to content

Commit 168db24

Browse files
authored
Remove misleading KO chance outputs (#536)
This removes a good amount of the text duplication in getKOChance() , but really the point is to resolve #448: where previously 100% chance to be KOed would be returned will instead yield 99.9%, and 0% will instead show 0.1%. I also added a test for the specific case mentioned. I can't think of an example for 0%, but I have seen it before.
1 parent f840e76 commit 168db24

File tree

2 files changed

+49
-47
lines changed

2 files changed

+49
-47
lines changed

calc/src/desc.ts

+27-47
Original file line numberDiff line numberDiff line change
@@ -287,20 +287,28 @@ export function getKOChance(
287287
? ' after ' + serializeText(hazards.texts.concat(eot.texts))
288288
: '';
289289

290+
function KOChance(
291+
chance: number | undefined,
292+
n: number,
293+
multipleTurns = false,
294+
) {
295+
if (chance === 0) return {chance: undefined, n, text: qualifier + 'not a KO'};
296+
let text = chance === undefined ? qualifier + 'possible '
297+
: chance === 1 ? qualifier || 'guaranteed '
298+
// prevent displaying misleading 100% or 0% chances
299+
: `${qualifier}${Math.max(Math.min(Math.round(chance * 1000), 999), 1) / 10}% chance to `;
300+
// using the number of hits we can determine the type of KO we are checking for
301+
text += n === 1 ? 'OHKO' + hazardsText
302+
: (multipleTurns ? `KO in ${n} turns` : `${n}HKO`) + afterText;
303+
return {chance, n, text};
304+
}
305+
290306
if ((move.timesUsed === 1 && move.timesUsedWithMetronome === 1) || move.isZ) {
291307
const chance = computeKOChance(
292308
damage, defender.curHP() - hazards.damage, 0, 1, 1, defender.maxHP(), toxicCounter
293309
);
294-
if (chance === 1) {
295-
return {chance, n: 1, text: `guaranteed OHKO${hazardsText}`}; // eot wasn't considered
296-
} else if (chance > 0) {
297-
// note: still not accounting for EOT due to poor eot damage handling
298-
return {
299-
chance,
300-
n: 1,
301-
text: qualifier + Math.round(chance * 1000) / 10 + `% chance to OHKO${hazardsText}`,
302-
};
303-
}
310+
// note: still not accounting for EOT due to poor eot damage handling
311+
if (chance > 0) return KOChance(chance, 1);
304312

305313
// Parental Bond's combined first + second hit only is accurate for chance to OHKO, for
306314
// multihit KOs its only approximated. We should be doing squashMultihit here instead of
@@ -315,28 +323,21 @@ export function getKOChance(
315323
const chance = computeKOChance(
316324
damage, defender.curHP() - hazards.damage, eot.damage, i, 1, defender.maxHP(), toxicCounter
317325
);
318-
if (chance === 1) {
319-
return {chance, n: i, text: `${qualifier || 'guaranteed '}${i}HKO${afterText}`};
320-
} else if (chance > 0) {
321-
return {
322-
chance,
323-
n: i,
324-
text: qualifier + Math.round(chance * 1000) / 10 + `% chance to ${i}HKO${afterText}`,
325-
};
326-
}
326+
if (chance > 0) return KOChance(chance, i);
327327
}
328328

329329
for (let i = 5; i <= 9; i++) {
330330
if (
331331
predictTotal(damage[0], eot.damage, i, 1, toxicCounter, defender.maxHP()) >=
332332
defender.curHP() - hazards.damage
333333
) {
334-
return {chance: 1, n: i, text: `${qualifier || 'guaranteed '}${i}HKO${afterText}`};
334+
return KOChance(1, i);
335335
} else if (
336336
predictTotal(damage[damage.length - 1], eot.damage, i, 1, toxicCounter, defender.maxHP()) >=
337337
defender.curHP() - hazards.damage
338338
) {
339-
return {n: i, text: qualifier + `possible ${i}HKO${afterText}`};
339+
// possible but no concrete chance
340+
return KOChance(undefined, i);
340341
}
341342
}
342343
} else {
@@ -348,22 +349,7 @@ export function getKOChance(
348349
defender.maxHP(),
349350
toxicCounter
350351
);
351-
if (chance === 1) {
352-
return {
353-
chance,
354-
n: move.timesUsed,
355-
text: `${qualifier || 'guaranteed '}KO in ${move.timesUsed} turns${afterText}`,
356-
};
357-
} else if (chance > 0) {
358-
return {
359-
chance,
360-
n: move.timesUsed,
361-
text:
362-
qualifier +
363-
Math.round(chance * 1000) / 10 +
364-
`% chance to ${move.timesUsed}HKO${afterText}`,
365-
};
366-
}
352+
if (chance > 0) return KOChance(chance, move.timesUsed, chance === 1);
367353

368354
if (predictTotal(
369355
damage[0],
@@ -375,11 +361,7 @@ export function getKOChance(
375361
) >=
376362
defender.curHP() - hazards.damage
377363
) {
378-
return {
379-
chance: 1,
380-
n: move.timesUsed,
381-
text: `${qualifier || 'guaranteed '}KO in ${move.timesUsed} turns${afterText}`,
382-
};
364+
return KOChance(1, move.timesUsed, true);
383365
} else if (
384366
predictTotal(
385367
damage[damage.length - 1],
@@ -391,12 +373,10 @@ export function getKOChance(
391373
) >=
392374
defender.curHP() - hazards.damage
393375
) {
394-
return {
395-
n: move.timesUsed,
396-
text: qualifier + `possible KO in ${move.timesUsed} turns${afterText}`,
397-
};
376+
// possible but no real idea
377+
return KOChance(undefined, move.timesUsed, true);
398378
}
399-
return {n: move.timesUsed, text: qualifier + 'not a KO'};
379+
return KOChance(0, move.timesUsed);
400380
}
401381

402382
return {chance: 0, n: 0, text: ''};

calc/src/test/calc.test.ts

+22
Original file line numberDiff line numberDiff line change
@@ -1210,5 +1210,27 @@ describe('calc', () => {
12101210
);
12111211
});
12121212
});
1213+
describe('Descriptions', () => {
1214+
inGen(9, ({gen, calculate, Pokemon, Move}) => {
1215+
test('displayed chances should not round to 100%', () => {
1216+
const result = calculate(
1217+
Pokemon('Xerneas', {item: 'Choice Band', nature: 'Adamant', evs: {atk: 252}}),
1218+
Pokemon('Necrozma-Dusk-Mane', {nature: 'Impish', evs: {hp: 252, def: 252}}),
1219+
Move('Close Combat')
1220+
);
1221+
expect(result.kochance().chance).toBeGreaterThanOrEqual(0.9995);
1222+
expect(result.kochance().text).toBe('99.9% chance to 3HKO');
1223+
});
1224+
test('displayed chances should not round to 0%', () => {
1225+
const result = calculate(
1226+
Pokemon('Deoxys-Attack', {evs: {spa: 44}}),
1227+
Pokemon('Blissey', {nature: 'Calm', evs: {hp: 252, spd: 252}}),
1228+
Move('Psycho Boost')
1229+
);
1230+
expect(result.kochance().chance).toBeLessThan(0.005); // it would round down.
1231+
expect(result.kochance().text).toBe('0.1% chance to 4HKO');
1232+
});
1233+
});
1234+
});
12131235
});
12141236
});

0 commit comments

Comments
 (0)