Skip to content

Team Validation

Before a battle starts, Frontier checks every team against the ladder’s format rules. Species bans, move restrictions, custom MoLang logic — it all runs through the clause system. Illegal teams can’t queue.

Clauses are enforced at three different points, depending on their type:

  1. Queue joinTEAM_VALIDATION clauses run against the player’s team. Fail any clause and you can’t join the queue. The failure message tells you exactly what’s wrong.
  2. Battle startSHOWDOWN_NATIVE clauses are passed to the Showdown engine as rule strings. Format-level bans (species, moves, abilities, items) are also applied here.
  3. During battleIN_BATTLE clauses fire when players attempt to use banned mechanics (Mega Evolution, Terastallization, etc.).
TypeWhen it runsHow it works
TEAM_VALIDATIONQueue join + battle startCustom MoLang expressions evaluated against the team.
SHOWDOWN_NATIVEBattle startRule string passed directly to the Showdown battle engine.
IN_BATTLEDuring battleFrontier intercepts banned battle mechanics (gimmick bans).

Clauses live in config/frontier/clauses.conf. Here’s an example:

clauses {
species_clause {
displayName = "Species Clause"
description = "A player cannot have two of the same species on their team."
type = "TEAM_VALIDATION"
showdownRule = "Species Clause"
perPokemon = false
molangExpression = ["!query.has_duplicate_species"]
failureMessage = "Species Clause: Your team has duplicate species"
}
}
FieldTypeDefaultDescription
displayNameString""Human-readable name shown in GUIs.
descriptionString""What the clause does, shown in format info.
typeClauseType"SHOWDOWN_NATIVE"When and how the clause runs.
showdownRuleString?nullShowdown rule string (only for SHOWDOWN_NATIVE clauses).
molangExpressionListnullMoLang expressions for validation. Each entry is a separate expression.
perPokemonBooleantrueIf true, expression runs once per Pokemon. If false, once for the whole team.
failureMessageString?nullMessage shown when validation fails. Supports {pokemon} (per-Pokemon only) and {clause} placeholders.

Beyond clauses, formats can ban specific species, moves, abilities, and items directly. These are configured in config/frontier/formats.conf:

formats {
ou {
displayName = "OU"
clauses = ["species_clause", "sleep_clause", "evasion_clause", "ohko_clause"]
bannedSpecies = ["mewtwo", "arceus", "zacian"]
bannedMoves = ["swagger", "baton_pass"]
bannedAbilities = ["moody", "shadow_tag"]
bannedItems = ["kings_rock"]
validateLegality = true
}
}
FieldTypeDefaultDescription
bannedSpeciesList[]Species to ban (Showdown IDs, e.g. "mewtwo", "arceus").
bannedMovesList[]Moves to ban (e.g. "swagger", "baton_pass").
bannedAbilitiesList[]Abilities to ban (e.g. "moody", "shadow_tag").
bannedItemsList[]Items to ban (e.g. "kings_rock").
validateLegalityBooleanfalseCheck each Pokemon’s moves and abilities against its species/form for legality.

Formats also support inheritance with the includes field — ban lists and clauses merge from all included formats:

formats {
base_ou {
clauses = ["species_clause", "sleep_clause", "evasion_clause", "ohko_clause"]
bannedSpecies = ["mewtwo", "arceus", "zacian"]
validateLegality = true
}
ou_no_tera {
displayName = "OU (No Tera)"
includes = ["base_ou"]
clauses = ["ban_tera"]
}
}
IDNamePer-PokemonDescription
species_clauseSpecies ClauseNoNo duplicate species on a team.
item_clauseItem ClauseNoNo duplicate held items on a team.
evasion_clauseEvasion ClauseYesBans Double Team and Minimize.
ohko_clauseOHKO ClauseYesBans Fissure, Sheer Cold, Horn Drill, Guillotine.
monotypeMonotypeNoAll team members must share a type.
level_capLevel CapYesPokemon must be at or below the format’s target level.
no_legendariesNo LegendariesYesLegendary Pokemon are banned.
nfe_onlyNFE OnlyYesOnly unevolved Pokemon (Little Cup).
IDNameShowdown RuleDescription
sleep_clauseSleep Clause"Sleep Clause Mod"Only one opposing Pokemon can be asleep at a time.
IDNameWhat it bans
gimmick_banGimmick BanMega Evolution, Ultra Burst, Z-Moves, Dynamax, Terastallization
ban_megaMega Evolution BanMega Evolution, Ultra Burst
ban_teraTerastallization BanTerastallization
ban_dynamaxDynamax BanDynamax
ban_zmovesZ-Moves BanZ-Moves

Frontier exposes MoLang queries for writing custom clause expressions.

Available when perPokemon = true. Access through query.pokemon.

QueryReturnsDescription
query.pokemon.levelDoublePokemon’s current level.
query.pokemon.can_evolve1.0/0.0Whether the Pokemon can still evolve.
query.pokemon.has_move('name')1.0/0.0Whether the Pokemon knows a specific move (Showdown ID).
query.pokemon.has_any_move('m1,m2,...')1.0/0.0Whether the Pokemon knows any of the listed moves (comma-separated).
query.pokemon.species.has_label('label')1.0/0.0Whether the species has a label (e.g., legendary).
query.pokemon.ability.nameStringThe Pokemon’s ability (Showdown ID).

Available in both per-Pokemon and team mode.

QueryReturnsDescription
query.team_sizeDoubleNumber of Pokemon on the team.
query.has_duplicate_species1.0/0.0Whether the team has duplicate species.
query.has_duplicate_items1.0/0.0Whether the team has duplicate held items.
query.team_shares_type1.0/0.0Whether all team members share at least one type.
query.format_target_levelDoubleFormat’s target level (0 if none set).
query.format_team_sizeDoubleFormat’s max team size.
clauses {
no_uber_abilities {
displayName = "No Uber Abilities"
description = "Bans Shadow Tag and Arena Trap."
type = "TEAM_VALIDATION"
perPokemon = true
molangExpression = [
"query.pokemon.ability.name != 'shadowtag' && query.pokemon.ability.name != 'arenatrap'"
]
failureMessage = "{pokemon} has a banned ability"
}
}
clauses {
max_level_50 {
displayName = "Level 50 Cap"
description = "All Pokemon must be level 50 or below."
type = "TEAM_VALIDATION"
perPokemon = true
molangExpression = ["query.pokemon.level <= 50"]
failureMessage = "{pokemon} exceeds the level 50 cap"
}
}