MoLang Query Reference
MoLang Query Reference
Section titled “MoLang Query Reference”All conditions in the Smart Trainers AI system are written in MoLang. Queries are accessed through q.<namespace>.<property>. This page documents every available query, organized by namespace.
Active Pokemon Queries
Section titled “Active Pokemon Queries”Queries about the AI’s currently active Pokemon. Used as q.pokemon.<property>.
| Query | Returns | Description |
|---|---|---|
q.pokemon.id | string | UUID of the Pokemon |
q.pokemon.species | string | Species name (e.g., “Garchomp”) |
q.pokemon.level | double | Level (1—100) |
q.pokemon.current_hp | double | Current HP value |
q.pokemon.max_hp | double | Maximum HP value |
q.pokemon.current_hp_percent | double (0.0—1.0) | Current HP as a percentage. 0.5 = 50% HP. |
q.pokemon.types | array | List of type names (e.g., [“dragon”, “ground”]) |
q.pokemon.has_type(name) | 0/1 | Whether this Pokemon has the specified type. q.pokemon.has_type('fire') |
q.pokemon.ability | string | Ability name |
q.pokemon.has_ability(name) | 0/1 | Whether ability matches. q.pokemon.has_ability('intimidate') |
q.pokemon.speed | double | Speed base stat |
q.pokemon.attack | double | Attack base stat |
q.pokemon.defence | double | Defence base stat |
q.pokemon.special_attack | double | Special Attack base stat |
q.pokemon.special_defence | double | Special Defence base stat |
q.pokemon.status | string | Current status condition name (e.g., “burn”, “paralysis”), or "" if none |
q.pokemon.has_status | 0/1 | Whether the Pokemon has any status condition |
q.pokemon.stat_boosts | struct | Stat boost sub-struct. See Stat Boosts. |
q.pokemon.volatiles | array | List of volatile conditions (confusion, leech seed, etc.) |
q.pokemon.has_volatile(name) | 0/1 | Whether a specific volatile is active |
q.pokemon.has_substitute | 0/1 | Has a Substitute up |
q.pokemon.has_confusion | 0/1 | Is confused |
q.pokemon.has_leech_seed | 0/1 | Is Leech Seeded |
q.pokemon.has_encore | 0/1 | Is Encored |
q.pokemon.has_taunt | 0/1 | Is Taunted |
q.pokemon.has_disable | 0/1 | Has a move Disabled |
q.pokemon.has_torment | 0/1 | Is Tormented |
q.pokemon.is_first_turn | 0/1 | Whether this is the Pokemon’s first turn on the field (relevant for Fake Out) |
q.pokemon.last_move | string | The last move this Pokemon used (from memory) |
q.pokemon.item | string | Held item name (normalized) |
q.pokemon.has_item | 0/1 | Whether the Pokemon is holding an item |
q.pokemon.item_boosts_type(type) | 0/1 | Whether held item boosts the given type |
q.pokemon.item_type_boost_multiplier(type) | double | Type boost multiplier from held item |
q.pokemon.item_boosted_type | string | The type name boosted by the held item, or "" |
q.pokemon.item_has_category(cat) | 0/1 | Whether held item has a specific effect category |
q.pokemon.item_is_choice | 0/1 | Is holding a Choice item (Band/Specs/Scarf) |
q.pokemon.item_is_berry | 0/1 | Is holding a berry |
q.pokemon.item_is_consumable | 0/1 | Is holding a consumable item |
q.pokemon.item_stat_multiplier(stat) | double | Stat multiplier from held item |
q.pokemon.item_restricts_move | 0/1 | Whether held item restricts move choice |
q.pokemon.item_recoil | double | Recoil multiplier from held item (e.g., Life Orb) |
q.pokemon.is_choice_locked | 0/1 | Whether locked into one move by a Choice item |
q.pokemon.effective_speed | double | Speed after boosts, paralysis, Choice Scarf, Tailwind, weather abilities (Chlorophyll, Swift Swim, etc.), Unburden |
q.pokemon.action_speed | double | Raw base Speed stat (no modifiers applied) |
q.pokemon.has_recovery_move | 0/1 | Has any healing move (Recover, Roost, etc.) |
q.pokemon.has_priority_move | 0/1 | Has any priority move (Quick Attack, Mach Punch, etc.) |
q.pokemon.has_pivot_move | 0/1 | Has any pivot move (U-turn, Volt Switch, etc.) |
q.pokemon.has_setup_move | 0/1 | Has any setup/buff move (Swords Dance, Calm Mind, etc.) |
q.pokemon.has_hazard_move | 0/1 | Has any entry hazard move (Stealth Rock, Spikes, etc.) |
q.pokemon.has_move(name) | 0/1 | Has a specific move. q.pokemon.has_move('earthquake') |
q.pokemon.is_trapped | 0/1 | Cannot switch out (trapped by ability or move) |
q.pokemon.turns_on_field | double | How many turns this Pokemon has been active |
q.pokemon.protected_last_turn | 0/1 | Used Protect/Detect last turn |
q.pokemon.is_grounded | 0/1 | Affected by ground-based effects (terrain, Spikes, etc.) |
q.pokemon.is_win_condition | 0/1 | Heuristic: is this Pokemon a win condition? (High offensive stats + stat boosts) |
q.pokemon.is_threatening | 0/1 | Has high offensive stats (Attack or SpAtk > 100) |
q.pokemon.is_targeted | 0/1 | Opponent has super-effective STAB type against us |
q.pokemon.is_terastallized | 0/1 | Currently Terastallized |
q.pokemon.is_mega_evolved | 0/1 | Currently Mega Evolved |
q.pokemon.is_dynamaxed | 0/1 | Currently Dynamaxed |
q.pokemon.tera_type | string | Tera type, or "" |
q.pokemon.can_tera | 0/1 | Can Terastallize this turn |
q.pokemon.can_mega | 0/1 | Can Mega Evolve this turn |
q.pokemon.can_dynamax | 0/1 | Can Dynamax this turn |
q.pokemon.can_zmove | 0/1 | Can use a Z-Move this turn |
q.pokemon.tera_type_advantageous | 0/1 | Would Terastallizing give a type advantage? |
q.pokemon.tera_resists_incoming | 0/1 | Would Tera type resist the opponent’s STAB? |
q.pokemon.will_be_koed | 0/1 | Estimates whether the opponent can KO us this turn |
q.pokemon.should_protect | double (0.0—1.0) | Heuristic score for how beneficial Protect would be |
q.pokemon.under_threat | double (0.0—1.0) | How threatened this Pokemon is. Considers opponent SE types, speed, boosts, and our HP. Higher = more danger. |
q.pokemon.se_threat_count | double | Number of opponents with super-effective coverage against us |
q.pokemon.should_switch | double (0.0—1.0) | Heuristic for whether switching would be beneficial |
q.pokemon.opponents_likely_to_protect | double (0.0—1.0) | Likelihood opponent will use Protect this turn |
q.pokemon.held_item | string | Same as q.pokemon.item |
q.pokemon.used_ally_switch_recently | 0/1 | Whether this Pokemon used Ally Switch recently (currently always 0) |
Stat Boosts
Section titled “Stat Boosts”Accessed via q.pokemon.stat_boosts.<stat> or q.target.stat_boosts.<stat>.
| Query | Returns | Description |
|---|---|---|
.stat_boosts.atk | double (-6 to +6) | Attack boost stage |
.stat_boosts.def | double (-6 to +6) | Defence boost stage |
.stat_boosts.spa | double (-6 to +6) | Special Attack boost stage |
.stat_boosts.spd | double (-6 to +6) | Special Defence boost stage |
.stat_boosts.spe | double (-6 to +6) | Speed boost stage |
.stat_boosts.accuracy | double (-6 to +6) | Accuracy boost stage |
.stat_boosts.evasion | double (-6 to +6) | Evasion boost stage |
Target/Opponent Queries
Section titled “Target/Opponent Queries”Queries about the primary opponent. q.target.* and q.opponent.* are identical aliases.
| Query | Returns | Description |
|---|---|---|
q.target.id | string | UUID |
q.target.species | string | Species name |
q.target.level | double | Level |
q.target.current_hp | double | Current HP |
q.target.max_hp | double | Max HP |
q.target.current_hp_percent | double (0.0—1.0) | HP percentage |
q.target.types | array | Type names |
q.target.has_type(name) | 0/1 | Type check |
q.target.revealed_ability | string | Ability revealed during battle (from memory) |
q.target.has_revealed_ability(name) | 0/1 | Ability match against revealed ability |
q.target.revealed_item | string | Item revealed during battle (from memory) |
q.target.status | string | Status condition name, or "" |
q.target.has_status | 0/1 | Has any status condition |
q.target.stat_boosts | struct | Stat boost sub-struct |
q.target.predicted_speed | double | Estimated speed considering known boosts/items |
q.target.speed | double | Base Speed stat |
q.target.attack | double | Base Attack stat |
q.target.special_attack | double | Base Special Attack stat |
q.target.defence | double | Base Defence stat |
q.target.special_defence | double | Base Special Defence stat |
q.target.is_physical_attacker | 0/1 | Attack > Special Attack |
q.target.is_dynamaxed | 0/1 | Is Dynamaxed |
q.target.is_terastallized | 0/1 | Is Terastallized |
q.target.is_mega_evolved | 0/1 | Is Mega Evolved |
q.target.tera_type | string | Tera type (if revealed) |
q.target.item_consumed | 0/1 | Whether the target’s item has been consumed (from memory) |
q.target.is_threatening | 0/1 | High offensive stats |
q.target.is_biggest_threat | 0/1 | Highest offensive stat among all opponents |
q.target.will_attack | 0/1 | Predicts whether opponent will use an attacking move (not status) |
q.target.used_setup_move | 0/1 | Opponent used a setup move recently |
q.target.is_support | 0/1 | Appears to be a support Pokemon (high defenses, status moves) |
q.target.likely_to_protect | double (0.0—1.0) | Likelihood of using Protect this turn |
q.target.likely_to_switch | double (0.0—1.0) | Likelihood of switching out |
q.target.threat_to_active | double (0.0—1.0) | How threatening this target is to our active Pokemon |
q.target.can_ko_active | 0/1 | Estimates whether the target can KO our active Pokemon |
q.target.predicted_action | string | Best guess of what opponent will do: "attack", "protect", "switch", "setup", "support" |
q.target.priority_score | double | Combined threat/priority score for target selection |
Move Queries
Section titled “Move Queries”Queries about the specific move being evaluated. Only available during move scoring. Used as q.move.<property>.
| Query | Returns | Description |
|---|---|---|
q.move.name | string | Move name (Showdown ID, e.g., “earthquake”) |
q.move.type | string | Elemental type (e.g., “ground”) |
q.move.power | double | Base power (0 for status moves) |
q.move.accuracy | double | Accuracy (0—100, or -1 for never-miss) |
q.move.pp | double | Remaining PP |
q.move.max_pp | double | Maximum PP |
q.move.priority | double | Move priority (e.g., +1 for Quick Attack) |
q.move.damage_category | string | "physical", "special", or "status" |
q.move.is_physical | 0/1 | Is a physical move |
q.move.is_special | 0/1 | Is a special move |
q.move.is_status | 0/1 | Is a status move |
q.move.categories | array | AI categories (e.g., [“damage”, “priority”]) |
q.move.has_category(cat) | 0/1 | Has a specific AI category. q.move.has_category('heal') |
q.move.is_stab | 0/1 | Same-Type Attack Bonus — move type matches one of the user’s types |
q.move.type_effectiveness | double | Type effectiveness multiplier (0, 0.25, 0.5, 1, 2, 4) |
q.move.effectiveness | double | Same as type_effectiveness |
q.move.predicted_damage | double | Estimated raw damage amount |
q.move.predicted_damage_percent | double (0.0—1.0+) | Estimated damage as a percentage of target’s current HP |
q.move.min_damage | double | Minimum possible damage (low roll) |
q.move.max_damage | double | Maximum possible damage (high roll) |
q.move.is_ohko | 0/1 | Can this move one-hit KO the target? |
q.move.is_2hko | 0/1 | Can two uses of this move KO? |
q.move.hits_to_ko | double | Estimated number of hits needed to KO |
q.move.is_spread | 0/1 | Hits multiple targets (doubles) |
q.move.is_protect | 0/1 | Is a protection move |
q.move.hits_ally | 0/1 | Would this move hit our ally (doubles) |
q.move.likely_blocked_by_protect | 0/1 | Would this move be blocked if the opponent uses Protect? |
q.move.is_good_timing | double (0.0—1.0) | Heuristic for whether this is a good time to use this move |
q.move.better_target_exists | 0/1 | Is there a better target for this move? (doubles) |
q.move.is_good_fake_out_target | 0/1 | Is this a good target for Fake Out? |
q.move.opponent_reaction_penalty | double | Penalty for predictable moves the opponent can capitalize on |
Battle Queries
Section titled “Battle Queries”General battle state. Used as q.battle.<property>.
| Query | Returns | Description |
|---|---|---|
q.battle.turn | double | Current turn number |
q.battle.format | string | Battle format name |
q.battle.is_doubles | 0/1 | Whether this is a doubles battle |
q.battle.weather | string | Current weather (e.g., “RainDance”, “SunnyDay”), or "" |
q.battle.has_weather(name) | 0/1 | Check for specific weather |
q.battle.terrain | string | Current terrain, or "" |
q.battle.has_terrain(name) | 0/1 | Check for specific terrain |
q.battle.hazards_on_our_side | struct | Hazard data for our side. See Hazards. |
q.battle.hazards_on_enemy_side | struct | Hazard data for the enemy side |
q.battle.is_opponent_switching | 0/1 | Whether the opponent is being forced to switch (currently always 0) |
q.battle.has_trick_room | 0/1 | Whether Trick Room is active |
Hazards
Section titled “Hazards”Accessed via q.battle.hazards_on_our_side.<hazard> or q.battle.hazards_on_enemy_side.<hazard>.
| Query | Returns | Description |
|---|---|---|
.spikes | double (0—3) | Layers of Spikes |
.toxic_spikes | double (0—2) | Layers of Toxic Spikes |
.stealth_rock | 0/1 | Stealth Rock present |
.sticky_web | 0/1 | Sticky Web present |
Memory Queries
Section titled “Memory Queries”AI memory of what has been revealed during battle. Used as q.memory.<property>.
| Query | Returns | Description |
|---|---|---|
q.memory.opponent_revealed_moves | array | Moves the opponent has used (from memory) |
q.memory.opponent_revealed_item | string | Opponent’s revealed item |
q.memory.opponent_revealed_ability | string | Opponent’s revealed ability |
q.memory.times_move_used(move) | double | How many times a specific move has been used |
q.memory.total_switches | double | Total switches made during the battle |
q.memory.opponent_switch_likelihood | double (0.0—1.0) | Estimated probability the opponent will switch |
Matchup Queries
Section titled “Matchup Queries”Type matchup analysis. Used as q.matchup.<property>.
| Query | Returns | Description |
|---|---|---|
q.matchup.score | double (~-4 to +4) | Type-based matchup score. Positive = we have type advantage. Based on STAB types only (not actual moves). |
q.matchup.can_outspeed | 0/1 | Whether we outspeed the current target. Trick Room-aware — returns 1 if we move first regardless of Trick Room. |
q.matchup.speed_tier | double | Speed ratio. >1 = we move first, <1 = they move first. Trick Room-aware — under Trick Room, the ratio is inverted (theirSpeed/ourSpeed) so >1 always means “I move first.” |
Ally Queries
Section titled “Ally Queries”Queries about your doubles partner. Used as q.ally.<property>. Returns empty values in singles.
| Query | Returns | Description |
|---|---|---|
q.ally.id | string | UUID |
q.ally.species | string | Species name |
q.ally.current_hp_percent | double (0.0—1.0) | HP percentage |
q.ally.types | array | Type names |
q.ally.has_ability(name) | 0/1 | Ability check |
q.ally.benefits_from_weather(weather) | 0/1 | Would ally benefit from this weather? |
q.ally.is_setting_up | 0/1 | Used a setup move last turn |
q.ally.will_ko_target | 0/1 | Ally is likely to KO the shared target |
q.ally.is_targeting_same | 0/1 | Ally is targeting the same opponent |
q.ally.resists_predicted_move | 0/1 | Ally resists the opponent’s likely attack |
q.ally.is_protecting_or_redirecting | 0/1 | Ally is using Protect, Follow Me, etc. |
q.ally.has_spread_move | 0/1 | Ally has a spread move |
Allies Array Access
Section titled “Allies Array Access”q.allies is an indexed array of all ally Pokemon (doubles). Each element has:
| Query | Returns | Description |
|---|---|---|
q.allies[N].id | string | UUID |
q.allies[N].species | string | Species name |
q.allies[N].current_hp_percent | double (0.0—1.0) | HP percentage |
Switch Candidate Queries
Section titled “Switch Candidate Queries”Queries about a Pokemon being considered for switch-in. Only available during switch evaluation. Used as q.switch_candidate.<property>.
| Query | Returns | Description |
|---|---|---|
q.switch_candidate.id | string | UUID |
q.switch_candidate.species | string | Species name |
q.switch_candidate.level | double | Level |
q.switch_candidate.current_hp | double | Current HP |
q.switch_candidate.max_hp | double | Max HP |
q.switch_candidate.current_hp_percent | double (0.0—1.0) | HP percentage |
q.switch_candidate.types | array | Type names |
q.switch_candidate.ability | string | Ability name |
q.switch_candidate.matchup_score | double | Type matchup score vs current opponent (same formula as q.matchup.score) |
q.switch_candidate.has_move(name) | 0/1 | Has a specific move |
q.switch_candidate.sets_weather | 0/1 | Has a weather-setting ability (Drizzle, Drought, Sand Stream, Snow Warning) |
q.switch_candidate.sets_terrain | 0/1 | Has a terrain-setting ability (Grassy/Electric/Psychic/Misty Surge, Hadron Engine) |
Field Queries
Section titled “Field Queries”Field conditions (weather, terrain, screens, etc.). Used as q.field.<property>.
| Query | Returns | Description |
|---|---|---|
q.field.weather | string | Current weather name |
q.field.has_weather(name) | 0/1 | Specific weather check |
q.field.terrain | string | Current terrain name |
q.field.has_terrain(name) | 0/1 | Specific terrain check |
q.field.has_electric_terrain | 0/1 | Electric Terrain active |
q.field.has_grassy_terrain | 0/1 | Grassy Terrain active |
q.field.has_psychic_terrain | 0/1 | Psychic Terrain active |
q.field.has_misty_terrain | 0/1 | Misty Terrain active |
q.field.has_trick_room | 0/1 | Trick Room active |
q.field.has_tailwind_ally | 0/1 | Tailwind on our side |
q.field.has_tailwind_opponent | 0/1 | Tailwind on opponent’s side |
q.field.has_light_screen_ally | 0/1 | Light Screen on our side |
q.field.has_reflect_ally | 0/1 | Reflect on our side |
q.field.has_aurora_veil_ally | 0/1 | Aurora Veil on our side |
q.field.has_light_screen_opponent | 0/1 | Light Screen on opponent’s side |
q.field.has_reflect_opponent | 0/1 | Reflect on opponent’s side |
q.field.has_aurora_veil_opponent | 0/1 | Aurora Veil on opponent’s side |
q.field.has_screens_ally | 0/1 | Any screen on our side |
q.field.has_screens_opponent | 0/1 | Any screen on opponent’s side |
q.field.has_gravity | 0/1 | Gravity active |
q.field.has_mud_sport | 0/1 | Mud Sport active |
q.field.has_water_sport | 0/1 | Water Sport active |
q.field.has_preferred_weather | 0/1 | Current weather benefits our Pokemon |
q.field.has_preferred_terrain | 0/1 | Current terrain benefits our Pokemon |
Team Queries
Section titled “Team Queries”Information about the AI’s whole team. Used as q.team.<property>.
| Query | Returns | Description |
|---|---|---|
q.team.remaining_count | double | Number of living Pokemon on the team |
q.team.has_intimidate_available | 0/1 | Whether an available switch-in has Intimidate |
q.team.has_weather_abuser | 0/1 | Has a Pokemon that benefits from the current weather |
q.team.has_terrain_abuser | 0/1 | Has a Pokemon that benefits from the current terrain |
q.team.wants_weather | 0/1 | Any team member wants a specific weather |
q.team.wants_terrain | 0/1 | Any team member wants a specific terrain |
q.team.wants_trick_room | 0/1 | Any team member is slow enough to want Trick Room |
q.team.wants_max_weather | 0/1 | Team has many weather abusers |
Bag Queries
Section titled “Bag Queries”Information about the AI’s battle bag. Used as q.bag.<property>.
| Query | Returns | Description |
|---|---|---|
q.bag.enabled | 0/1 | Whether the bag is usable |
q.bag.remaining_uses | double | Total remaining item uses this battle |
q.bag.has_healing_item | 0/1 | Has a HEALING category item available |
q.bag.has_status_cure | 0/1 | Has a STATUS_CURE item available |
q.bag.has_revive | 0/1 | Has a REVIVE item available |
q.bag.has_stat_boost | 0/1 | Has a STAT_BOOST item available |
q.bag.remaining_quantity(itemId) | double | Remaining quantity of a specific item |
q.bag.can_use_item(itemId) | 0/1 | Whether a specific item can be used right now |
Item Lookup Queries
Section titled “Item Lookup Queries”Lookup held item properties from the HeldItemEffectsRegistry. Used as q.item.<property>(itemName).
| Query | Returns | Description |
|---|---|---|
q.item.boosts_type(name, type) | 0/1 | Whether item boosts the given type |
q.item.type_boost_multiplier(name, type) | double | Type boost multiplier from item |
q.item.boosted_type(name) | string | Type boosted by the item |
q.item.has_category(name, cat) | 0/1 | Whether item has a specific effect category |
q.item.categories(name) | array | All effect categories of the item |
q.item.is_choice(name) | 0/1 | Is a Choice item |
q.item.is_type_boost(name) | 0/1 | Boosts a specific type |
q.item.is_berry(name) | 0/1 | Is a berry |
q.item.is_consumable(name) | 0/1 | Is consumable |
q.item.stat_multiplier(name, stat) | double | Stat multiplier from item |
q.item.restricts_move(name) | 0/1 | Whether item restricts move choice |
q.item.recoil(name) | double | Recoil multiplier |
q.item.has_property(name, prop) | 0/1 | Whether item has a named property |
q.item.property(name, prop) | double | Numeric property value |
q.item.property_string(name, prop) | string | String property value |
Personality Queries
Section titled “Personality Queries”The AI’s current personality values. Used as q.personality.<property>.
| Query | Returns | Description |
|---|---|---|
q.personality.aggression | double (0.0—1.0) | Aggression level |
q.personality.risk_tolerance | double (0.0—1.0) | Risk tolerance |
q.personality.setup_preference | double (0.0—1.0) | Setup move preference |
q.personality.switchiness | double (0.0—1.0) | Switch frequency |
q.personality.item_conservatism | double (0.0—1.0) | Item conservatism |
Top-Level Queries
Section titled “Top-Level Queries”Aggregate queries accessed directly on q.*.
| Query | Returns | Description |
|---|---|---|
q.opponents_count | double | Number of active opponents |
q.opponent_remaining_count | double | Total remaining opponent Pokemon (including bench) |
q.opponents_faster_count | double | Number of opponents faster than us |
q.opponents_physical_count | double | Number of opponents that are physical attackers |
q.opponent_has_spread_move | 0/1 | Any opponent has a spread move |
q.opponent_has_priority | 0/1 | Any opponent has a priority move |
q.opponent_has_special_threat | 0/1 | Any opponent has Special Attack > 100 |
q.opponent_is_setting_up | 0/1 | Any opponent used a setup move last turn |
MoLang Syntax Basics
Section titled “MoLang Syntax Basics”MoLang uses a simple expression syntax for conditions and value expressions.
Comparison Operators
Section titled “Comparison Operators”q.pokemon.current_hp_percent < 0.5 // less thanq.pokemon.current_hp_percent > 0.5 // greater thanq.pokemon.current_hp_percent == 0.5 // equalq.pokemon.current_hp_percent >= 0.5 // greater or equalq.pokemon.current_hp_percent <= 0.5 // less or equalLogical Operators
Section titled “Logical Operators”q.pokemon.current_hp_percent < 0.5 && q.target.has_status == 0 // ANDq.pokemon.current_hp_percent < 0.3 || q.pokemon.has_status // OR!q.target.has_status // NOTBoolean Values
Section titled “Boolean Values”Boolean values use 0 = false and anything > 0 = true. So q.target.has_status alone works as a boolean check without needing == 1.
Math Expressions
Section titled “Math Expressions”q.move.power * q.move.type_effectivenessq.pokemon.current_hp_percent * 100q.target.current_hp_percent * 2.5Function Calls
Section titled “Function Calls”q.pokemon.has_type('fire')q.pokemon.has_move('earthquake')q.target.has_revealed_ability('levitate')Constant True Condition
Section titled “Constant True Condition”To make a rule always apply, use "1" as the condition:
{ "condition": "1"}Temp Variables
Section titled “Temp Variables”The AI uses a single MoLang runtime per battle actor that persists across turns. You can use t.xxx temporary variables in conditions to track state across turns:
{ "id": "escalating_aggression", "condition": "t.turns_without_ko = (t.turns_without_ko ?? 0) + 1; t.turns_without_ko > 3", "action_type": "move", "move_filter": { "categories": ["damage"] }, "bias_multiplier": 2.0, "score_bonus": 50.0}All q.* queries are refreshed each decision (they reflect current battle state). Only t.* and v.* variables persist across turns on the same actor.