mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-03-21 17:25:10 -05:00
Fix validator precedence bugs
This commit is contained in:
parent
751ab2c587
commit
68edac35b5
|
|
@ -97,6 +97,11 @@ export class RuleTable extends Map<string, string> {
|
|||
return this.has(`*pokemontag:allpokemon`);
|
||||
}
|
||||
|
||||
/**
|
||||
* - non-empty string: banned, string is the reason
|
||||
* - '': whitelisted
|
||||
* - null: neither whitelisted nor banned
|
||||
*/
|
||||
check(thing: string, setHas: {[id: string]: true} | null = null) {
|
||||
if (this.has(`+${thing}`)) return '';
|
||||
if (setHas) setHas[thing] = true;
|
||||
|
|
@ -619,8 +624,6 @@ export class DexFormats {
|
|||
|
||||
getTagRules(ruleTable: RuleTable) {
|
||||
const tagRules = [];
|
||||
const specificExistenceTagRules = [];
|
||||
const existenceTagRules = [];
|
||||
for (const ruleid of ruleTable.keys()) {
|
||||
if (/^[+*-]pokemontag:/.test(ruleid)) {
|
||||
const banid = ruleid.slice(12);
|
||||
|
|
@ -629,25 +632,14 @@ export class DexFormats {
|
|||
banid === 'allabilities' || banid === 'allnatures'
|
||||
) {
|
||||
// hardcoded and not a part of the ban rule system
|
||||
} else if (!ruleid.startsWith('+') && (
|
||||
banid === 'past' || banid === 'future' || banid === 'lgpe' ||
|
||||
banid === 'unobtainable' || banid === 'cap' || banid === 'custom'
|
||||
)) {
|
||||
specificExistenceTagRules.push(ruleid);
|
||||
} else if (!ruleid.startsWith('+') && banid === 'nonexistent') {
|
||||
existenceTagRules.push(ruleid);
|
||||
} else {
|
||||
tagRules.push(ruleid);
|
||||
}
|
||||
} else if ('+*-'.includes(ruleid.charAt(0)) && ruleid.slice(1) === 'nonexistent') {
|
||||
if (!ruleid.startsWith('+')) {
|
||||
existenceTagRules.push(ruleid.charAt(0) + 'pokemontag:nonexistent');
|
||||
} else {
|
||||
tagRules.push('+pokemontag:nonexistent');
|
||||
}
|
||||
tagRules.push(ruleid.charAt(0) + 'pokemontag:nonexistent');
|
||||
}
|
||||
}
|
||||
ruleTable.tagRules = [...tagRules, ...existenceTagRules, ...specificExistenceTagRules].reverse();
|
||||
ruleTable.tagRules = tagRules.reverse();
|
||||
}
|
||||
|
||||
validateRule(rule: string, format: Format | null = null) {
|
||||
|
|
|
|||
|
|
@ -1334,15 +1334,25 @@ export class TeamValidator {
|
|||
}
|
||||
}
|
||||
|
||||
// We can't return here because the `-nonexistent` rule is a bit
|
||||
// complicated in terms of what trumps it. We don't want e.g.
|
||||
// +Mythical to unban Shaymin in Gen 1, for instance.
|
||||
const nonexistentCheck = Tags.nonexistent.genericFilter!(tierSpecies) && ruleTable.check('nonexistent');
|
||||
|
||||
const EXISTENCE_TAG = ['past', 'future', 'lgpe', 'unobtainable', 'cap', 'custom', 'nonexistent'];
|
||||
console.log(ruleTable.tagRules);
|
||||
|
||||
for (const ruleid of ruleTable.tagRules) {
|
||||
if (ruleid.startsWith('*')) continue;
|
||||
const tagid = ruleid.slice(12);
|
||||
const tag = Tags[tagid];
|
||||
if ((tag.speciesFilter || tag.genericFilter)!(tierSpecies)) {
|
||||
if (ruleid.startsWith('+')) return null;
|
||||
if (EXISTENCE_TAG.includes(tagid)) {
|
||||
const existenceTag = EXISTENCE_TAG.includes(tagid);
|
||||
if (ruleid.startsWith('+')) {
|
||||
// we want rules like +CAP to trump -Nonexistent, but most tags shouldn't
|
||||
if (!existenceTag && nonexistentCheck) continue;
|
||||
return null;
|
||||
}
|
||||
if (existenceTag) {
|
||||
if (tierSpecies.isNonstandard === 'Past' || tierSpecies.isNonstandard === 'Future') {
|
||||
return `${tierSpecies.name} does not exist in Gen ${dex.gen}.`;
|
||||
}
|
||||
|
|
@ -1363,6 +1373,11 @@ export class TeamValidator {
|
|||
}
|
||||
}
|
||||
|
||||
if (nonexistentCheck) {
|
||||
return `Despite being whitelisted by a tag, ${tierSpecies.name} does not exist in this game.`;
|
||||
}
|
||||
if (nonexistentCheck === '') return null;
|
||||
|
||||
// Special casing for Pokemon that can Gmax, but their Gmax factor cannot be legally obtained
|
||||
if (tierSpecies.gmaxUnreleased && set.gigantamax) {
|
||||
banReason = ruleTable.check('pokemontag:unobtainable');
|
||||
|
|
|
|||
|
|
@ -767,16 +767,22 @@ describe('Team Validator', function () {
|
|||
|
||||
it('should support banning/unbanning tag combinations', function () {
|
||||
let team = [
|
||||
{species: 'Blaziken-Mega', ability: 'Speed Boost', moves: ['protect'], evs: {hp: 1}},
|
||||
{species: 'Crucibelle-Mega', ability: 'Regenerator', moves: ['protect'], evs: {hp: 1}},
|
||||
];
|
||||
let illegal = TeamValidator.get('gen8customgame@@@-nonexistent,+mega').validateTeam(team);
|
||||
assert(illegal, "Nonexistent should override all tags that aren't existence-related");
|
||||
|
||||
team = [
|
||||
{species: 'Blaziken-Mega', ability: 'Speed Boost', moves: ['protect'], evs: {hp: 1}},
|
||||
{species: 'Crucibelle-Mega', ability: 'Regenerator', moves: ['protect'], evs: {hp: 1}},
|
||||
];
|
||||
illegal = TeamValidator.get('gen8customgame@@@+mega,-nonexistent').validateTeam(team);
|
||||
assert(illegal, "Nonexistent should override all tags that aren't existence-related");
|
||||
|
||||
team = [
|
||||
{species: 'Crucibelle-Mega', ability: 'Regenerator', moves: ['protect'], evs: {hp: 1}},
|
||||
];
|
||||
illegal = TeamValidator.get('gen8customgame@@@-nonexistent,+crucibellemega').validateTeam(team);
|
||||
assert.equal(illegal, null, "Nonexistent should override all tags that aren't existence-related");
|
||||
});
|
||||
|
||||
it('should allow moves to be banned', function () {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user