piclets / battle_system_design.md
Fraser's picture
closer
946e7bf

Pictuary Battle System Design Document

Overview

This document defines a new programmatic battle system for Pictuary that replaces the current description-based approach with executable building blocks. The design is inspired by Pokemon Emerald's sophisticated battle mechanics while being simplified for our use case.

Core Philosophy

The battle system is built on composable building blocks that can be combined to create unique and dynamic effects. Each action and ability is defined using simple, atomic operations that can be chained together to create complex behaviors.

JSON Schema for generateStats

Monster Definition

{
  "name": "Zephyr Sprite",
  "description": "A mysterious floating creature that manipulates wind currents",
  "tier": "medium",
  "primaryType": "space",
  "secondaryType": null,
  "baseStats": {
    "hp": 65,
    "attack": 85,
    "defense": 40,
    "speed": 90
  },
  "nature": "hasty",
  "specialAbility": {
    "name": "Wind Currents",
    "description": "Gains +25% speed when opponent uses a contact move",
    "trigger": "onOpponentContactMove",
    "effects": [
      {
        "type": "modifyStats",
        "target": "self",
        "stats": { "speed": "increase" }
      }
    ]
  },
  "movepool": [
    {
      "name": "Gust Strike",
      "type": "space",
      "power": 65,
      "accuracy": 95,
      "pp": 20,
      "priority": 0,
      "flags": ["contact"],
      "effects": [
        {
          "type": "damage",
          "target": "opponent",
          "amount": "normal"
        }
      ]
    },
    {
      "name": "Piercing Gale",
      "type": "space", 
      "power": 80,
      "accuracy": 85,
      "pp": 15,
      "priority": 0,
      "flags": [],
      "effects": [
        {
          "type": "damage",
          "target": "opponent",
          "amount": "normal"
        },
        {
          "type": "modifyStats",
          "target": "self",
          "stats": { "accuracy": "decrease" },
          "condition": "afterUse"
        }
      ]
    },
    {
      "name": "Tailwind Boost",
      "type": "space",
      "power": 0,
      "accuracy": 100,
      "pp": 10,
      "priority": 1,
      "flags": [],
      "effects": [
        {
          "type": "modifyStats",
          "target": "self",
          "stats": { "speed": "greatly_increase" }
        }
      ]
    },
    {
      "name": "Reckless Dive",
      "type": "space", 
      "power": 120,
      "accuracy": 80,
      "pp": 5,
      "priority": 0,
      "flags": ["contact", "reckless"],
      "effects": [
        {
          "type": "damage",
          "target": "opponent",
          "amount": "normal"
        },
        {
          "type": "damage",
          "target": "self",
          "formula": "recoil",
          "value": 0.25
        }
      ]
    }
  ]
}

Building Blocks System

Effect Types

All battle effects are built from these atomic operations:

1. damage

{
  "type": "damage",
  "target": "opponent" | "self" | "all" | "allies",
  "amount": "weak" | "normal" | "strong" | "extreme"
}

2. modifyStats

{
  "type": "modifyStats",
  "target": "self" | "opponent" | "all",
  "stats": {
    "attack": "increase",      // "increase" | "decrease" | "greatly_increase" | "greatly_decrease"
    "defense": "decrease",
    "speed": "greatly_increase",
    "accuracy": "decrease"
  },
  "condition": "always" | "onHit" | "afterUse" | "ifCritical"
}

Standard Stat Modification Levels:

  • increase: +25% (1.25x multiplier)
  • decrease: -25% (0.75x multiplier)
  • greatly_increase: +50% (1.5x multiplier)
  • greatly_decrease: -50% (0.5x multiplier)

3. applyStatus

{
  "type": "applyStatus",
  "target": "opponent" | "self",
  "status": "burn" | "freeze" | "paralyze" | "poison" | "sleep" | "confuse"
}

4. heal

{
  "type": "heal",
  "target": "self" | "ally",
  "amount": "small" | "medium" | "large" | "full"
}

5. manipulatePP

{
  "type": "manipulatePP",
  "target": "opponent",
  "action": "drain" | "restore" | "disable",
  "amount": "small" | "medium" | "large"
}

6. fieldEffect

{
  "type": "fieldEffect",
  "effect": "reflect" | "lightScreen" | "spikes" | "healingMist" | "toxicSpikes",
  "target": "playerSide" | "opponentSide" | "field",
  "stackable": false
}

7. counter

{
  "type": "counter",
  "counterType": "physical" | "special" | "any",
  "strength": "weak" | "normal" | "strong"
}

8. priority

{
  "type": "priority",
  "target": "self",
  "value": 1,           // Priority bracket (-5 to +5)
  "condition": "ifLowHp" | "always"
}

9. removeStatus

{
  "type": "removeStatus",
  "target": "self" | "opponent" | "allies",
  "status": "burn" | "freeze" | "paralyze" | "poison" | "sleep" | "confuse"
}

Move Flags

Moves can have flags that affect how they interact with abilities and other mechanics:

Combat Flags

  • contact: Move makes physical contact (triggers contact abilities like Rough Skin)
  • bite: Biting move (affected by Strong Jaw ability, blocked by certain defenses)
  • punch: Punching move (affected by Iron Fist ability)
  • sound: Sound-based move (bypasses Substitute, blocked by Soundproof)
  • explosive: Explosive move (affected by Damp ability)
  • draining: Move that drains HP (affected by Liquid Ooze ability)
  • ground: Ground-based attack (blocked by Sky Dancer, Levitate abilities)

Priority Flags

  • priority: Move has natural priority (+1 to +5)
  • lowPriority: Move has negative priority (-1 to -5)

Special Mechanics

  • charging: Move requires charging turn (Sky Attack, Solar Beam)
  • recharge: User must recharge next turn (Hyper Beam)
  • multiHit: Hits multiple times (2-5 hits)
  • twoTurn: Takes two turns to execute
  • sacrifice: Move involves self-sacrifice or major cost
  • gambling: Move has random outcomes
  • reckless: Move gains power but has drawbacks (affected by Reckless ability)

Interaction Flags

  • reflectable: Can be reflected by Magic Coat
  • snatchable: Can be stolen by Snatch
  • copyable: Can be copied by Mirror Move
  • protectable: Blocked by Protect/Detect
  • bypassProtect: Ignores Protect/Detect

Triggers and Conditions

Effects can be triggered by various battle events:

  • always: Effect always applies when move is used
  • onHit: Effect applies only if the move hits
  • afterUse: Effect applies after move execution regardless of hit/miss
  • onCritical: Effect applies only on critical hits
  • ifLowHp: Effect applies if user's HP < 25%
  • ifHighHp: Effect applies if user's HP > 75%
  • onOpponentContactMove: Trigger when opponent uses a contact move
  • endOfTurn: Effect applies at the end of each turn
  • onSwitchIn: Effect applies when Piclet enters battle
  • afterKO: Effect applies after knocking out an opponent

Target Specification

  • self: The move user
  • opponent: The target opponent
  • all: All Piclets in battle
  • allies: All allied Piclets (in team battles)
  • playerSide: Player's side of the field
  • opponentSide: Opponent's side of the field
  • field: Entire battlefield

Special Abilities

Special abilities are passive traits that can fundamentally alter battle mechanics. They can use standard effect building blocks OR modify core game mechanics directly.

Mechanic Modifications

Special abilities can override or alter fundamental battle mechanics:

9. mechanicOverride

{
  "type": "mechanicOverride",
  "mechanic": "criticalHits" | "statusImmunity" | "damageReflection" | "healingInversion" | "priorityOverride" | "accuracyBypass" | "typeImmunity" | "contactDamage" | "drainInversion" | "weatherImmunity",
  "condition": "always" | "ifLowHp" | "whenStatusAfflicted" | "vsPhysical" | "vsSpecial",
  "value": true | false | "invert" | "double" | "absorb" | "reflect"
}

Mechanic Types:

  • criticalHits: false = cannot be crit, true = always crit, "double" = 2x crit rate
  • statusImmunity: Array of status types to be immune to
  • damageReflection: Reflects % of damage back to attacker
  • healingInversion: Healing effects cause damage instead
  • priorityOverride: Always goes first/last regardless of speed
  • accuracyBypass: Moves cannot miss this Piclet
  • typeImmunity: Immune to specific damage types
  • contactDamage: Attackers take damage when using contact moves
  • drainInversion: HP draining moves heal the target instead
  • weatherImmunity: Unaffected by weather damage/effects
  • flagImmunity: Immune to moves with specific flags
  • flagWeakness: Takes extra damage from moves with specific flags
  • flagResistance: Takes reduced damage from moves with specific flags

Advanced Ability Examples

1. Shell Armor - Cannot be critically hit

{
  "name": "Shell Armor",
  "description": "Hard shell prevents critical hits",
  "effects": [
    {
      "type": "mechanicOverride",
      "mechanic": "criticalHits",
      "condition": "always",
      "value": false
    }
  ]
}

2. Rough Skin - Contact moves damage attacker

{
  "name": "Rough Skin",
  "description": "Rough skin damages attackers on contact",
  "triggers": [
    {
      "event": "onContactDamage",
      "effects": [
        {
          "type": "damage",
          "target": "attacker",
          "formula": "fixed",
          "value": 12
        }
      ]
    }
  ]
}

3. Photosynthesis - Healed by flora-type moves

{
  "name": "Photosynthesis",
  "description": "Absorbs flora-type moves to restore HP",
  "triggers": [
    {
      "event": "onDamageTaken",
      "condition": "ifMoveType:flora",
      "effects": [
        {
          "type": "mechanicOverride",
          "mechanic": "damageAbsorption",
          "value": "absorb"
        },
        {
          "type": "heal",
          "target": "self",
          "amount": "percentage",
          "value": 25
        }
      ]
    }
  ]
}

4. Poison Heal - Healed by poison instead of damaged

{
  "name": "Poison Heal",
  "description": "Poison heals instead of damages",
  "effects": [
    {
      "type": "mechanicOverride",
      "mechanic": "statusEffect:poison",
      "value": "invert"
    }
  ]
}

5. Wonder Guard - Only super-effective moves can hit

{
  "name": "Wonder Guard",
  "description": "Only super-effective moves deal damage",
  "effects": [
    {
      "type": "mechanicOverride", 
      "mechanic": "damageCalculation",
      "condition": "ifNotSuperEffective",
      "value": false
    }
  ]
}

6. Levitate - Immune to ground-type moves

{
  "name": "Levitate",
  "description": "Floating ability makes ground moves miss",
  "effects": [
    {
      "type": "mechanicOverride",
      "mechanic": "typeImmunity",
      "value": ["ground"]
    }
  ]
}

7. Vampiric - Drain moves damage the drainer

{
  "name": "Vampiric",
  "description": "Cursed blood damages those who try to drain it",
  "triggers": [
    {
      "event": "onHPDrained",
      "effects": [
        {
          "type": "mechanicOverride",
          "mechanic": "drainInversion",
          "value": true
        },
        {
          "type": "damage",
          "target": "attacker",
          "formula": "fixed",
          "value": 20
        }
      ]
    }
  ]
}

8. Insomnia - Cannot be put to sleep

{
  "name": "Insomnia",
  "description": "Prevents sleep status",
  "effects": [
    {
      "type": "mechanicOverride",
      "mechanic": "statusImmunity",
      "value": ["sleep"]
    }
  ]
}

9. Prankster - Status moves have +1 priority

{
  "name": "Prankster",
  "description": "Status moves gain priority",
  "effects": [
    {
      "type": "mechanicOverride",
      "mechanic": "priorityOverride",
      "condition": "ifStatusMove",
      "value": 1
    }
  ]
}

10. Magic Bounce - Reflects status moves

{
  "name": "Magic Bounce",
  "description": "Reflects status moves back at the user",
  "triggers": [
    {
      "event": "onStatusMoveTargeted",
      "effects": [
        {
          "type": "mechanicOverride",
          "mechanic": "targetRedirection",
          "value": "reflect"
        }
      ]
    }
  ]
}

Complex Multi-Mechanic Abilities

Protean - Changes type to match moves used

{
  "name": "Protean",
  "description": "Changes type to match the move being used",
  "triggers": [
    {
      "event": "beforeMoveUse",
      "effects": [
        {
          "type": "mechanicOverride",
          "mechanic": "typeChange",
          "value": "matchMoveType"
        }
      ]
    }
  ]
}

Contrary - Stat changes are reversed

{
  "name": "Contrary",
  "description": "Stat changes have the opposite effect",
  "effects": [
    {
      "type": "mechanicOverride",
      "mechanic": "statModification",
      "value": "invert"
    }
  ]
}

Status-Specific Abilities

Frost Walker - Alternative effect when frozen

{
  "name": "Frost Walker",
  "description": "Instead of being frozen, gains +50% attack",
  "effects": [
    {
      "type": "mechanicOverride",
      "mechanic": "statusReplacement:freeze",
      "value": {
        "type": "modifyStats",
        "target": "self",
        "stats": { "attack": "greatly_increase" }
      }
    }
  ]
}

Glacial Birth - Starts battle frozen

{
  "name": "Glacial Birth",
  "description": "Enters battle in a frozen state but gains defensive bonuses",
  "triggers": [
    {
      "event": "onSwitchIn",
      "effects": [
        {
          "type": "applyStatus",
          "target": "self",
          "status": "freeze",
          "chance": 100
        },
        {
          "type": "modifyStats",
          "target": "self",
          "stats": { "defense": "greatly_increase" },
          "condition": "whileFrozen"
        }
      ]
    }
  ]
}

Cryogenic Touch - Freezes enemy on contact

{
  "name": "Cryogenic Touch",
  "description": "Contact moves have a chance to freeze the attacker",
  "triggers": [
    {
      "event": "onContactDamage",
      "effects": [
        {
          "type": "applyStatus",
          "target": "attacker",
          "status": "freeze",
          "chance": 30
        }
      ]
    }
  ]
}

Slumber Heal - Heal when asleep

{
  "name": "Slumber Heal",
  "description": "Restores HP while sleeping instead of being unable to act",
  "triggers": [
    {
      "event": "endOfTurn",
      "condition": "ifStatus:sleep",
      "effects": [
        {
          "type": "heal",
          "target": "self",
          "amount": "percentage",
          "value": 15
        }
      ]
    }
  ]
}

Toxic Skin - Poisons on contact

{
  "name": "Toxic Skin",
  "description": "Physical contact poisons the attacker",
  "triggers": [
    {
      "event": "onContactDamage",
      "effects": [
        {
          "type": "applyStatus",
          "target": "attacker",
          "status": "poison",
          "chance": 50
        }
      ]
    }
  ]
}

Paralytic Aura - Starts battle with paralyzed enemy

{
  "name": "Paralytic Aura",
  "description": "Intimidating presence paralyzes the opponent upon entry",
  "triggers": [
    {
      "event": "onSwitchIn",
      "effects": [
        {
          "type": "applyStatus",
          "target": "opponent",
          "status": "paralyze",
          "chance": 75
        }
      ]
    }
  ]
}

Burn Boost - Powered up when burned

{
  "name": "Burn Boost",
  "description": "Fire damage energizes this Piclet, increasing attack power",
  "triggers": [
    {
      "event": "onStatusInflicted",
      "condition": "ifStatus:burn",
      "effects": [
        {
          "type": "modifyStats",
          "target": "self",
          "stats": { "attack": "greatly_increase" }
        }
      ]
    }
  ]
}

Confusion Clarity - Cannot be confused, clears team confusion

{
  "name": "Confusion Clarity",
  "description": "Clear mind prevents confusion and helps allies focus",
  "effects": [
    {
      "type": "mechanicOverride",
      "mechanic": "statusImmunity",
      "value": ["confuse"]
    }
  ],
  "triggers": [
    {
      "event": "onSwitchIn",
      "effects": [
        {
          "type": "removeStatus",
          "target": "allies",
          "status": "confuse"
        }
      ]
    }
  ]
}

Flag-Based Immunities and Weaknesses

Sky Dancer - Immune to ground-flagged attacks

{
  "name": "Sky Dancer",
  "description": "Floating in air, immune to ground-based attacks",
  "effects": [
    {
      "type": "mechanicOverride", 
      "mechanic": "flagImmunity",
      "value": ["ground"]
    }
  ]
}

Sound Barrier - Immune to sound attacks

{
  "name": "Sound Barrier",
  "description": "Natural sound dampening prevents sound-based moves",
  "effects": [
    {
      "type": "mechanicOverride",
      "mechanic": "flagImmunity", 
      "value": ["sound"]
    }
  ]
}

Soft Body - Weak to punch moves, immune to explosive

{
  "name": "Soft Body",
  "description": "Gelatinous form absorbs explosions but vulnerable to direct hits",
  "effects": [
    {
      "type": "mechanicOverride",
      "mechanic": "flagImmunity",
      "value": ["explosive"]
    },
    {
      "type": "mechanicOverride", 
      "mechanic": "flagWeakness",
      "value": ["punch"]
    }
  ]
}

Ethereal Form - Immune to contact moves

{
  "name": "Ethereal Form",
  "description": "Ghostly body cannot be touched by physical contact",
  "effects": [
    {
      "type": "mechanicOverride",
      "mechanic": "flagImmunity",
      "value": ["contact"]
    }
  ]
}

Fragile Shell - Takes double damage from explosive moves

{
  "name": "Fragile Shell", 
  "description": "Hard shell provides defense but shatters from explosions",
  "effects": [
    {
      "type": "modifyStats",
      "target": "self", 
      "stats": { "defense": "increase" }
    },
    {
      "type": "mechanicOverride",
      "mechanic": "flagWeakness",
      "value": ["explosive"]
    }
  ]
}

Liquid Body - Immune to punch/bite, weak to sound

{
  "name": "Liquid Body",
  "description": "Fluid form flows around physical attacks but resonates with sound",
  "effects": [
    {
      "type": "mechanicOverride",
      "mechanic": "flagImmunity",
      "value": ["punch", "bite"]
    },
    {
      "type": "mechanicOverride",
      "mechanic": "flagWeakness", 
      "value": ["sound"]
    }
  ]
}

Thick Hide - Reduced damage from contact moves

{
  "name": "Thick Hide",
  "description": "Tough skin reduces impact from physical contact",
  "effects": [
    {
      "type": "mechanicOverride",
      "mechanic": "flagResistance",
      "value": ["contact"]
    }
  ]
}

Event Triggers for Abilities

Extended list of trigger events:

  • onDamageTaken: When this Piclet takes damage
  • onDamageDealt: When this Piclet deals damage
  • onContactDamage: When hit by a contact move
  • onStatusInflicted: When a status is applied to this Piclet
  • onStatusMove: When targeted by a status move
  • onCriticalHit: When this Piclet lands/receives a critical hit
  • onHPDrained: When HP is drained from this Piclet
  • onKO: When this Piclet knocks out an opponent
  • onSwitchIn: When this Piclet enters battle
  • onSwitchOut: When this Piclet leaves battle
  • onWeatherChange: When battlefield weather changes
  • beforeMoveUse: Just before this Piclet uses a move
  • afterMoveUse: Just after this Piclet uses a move
  • onLowHP: When HP drops below 25%
  • onFullHP: When HP is at 100%

Move Categories and Interactions

Physical vs Special Attacks

  • Physical: Direct combat using attack vs defense stats, affected by contact abilities
  • Special: Ranged/magical attacks using attack vs defense stats, no contact interactions
  • Status: No damage, focus on effects and stat manipulation

Move Flags

Moves can have flags that affect interactions:

  • contact: Triggers contact-based abilities (like Rough Skin)
  • sound: Affects sound-based interactions
  • bite: Triggers bite-specific abilities
  • punch: Triggers punch-specific abilities
  • reckless: Increased power but with drawbacks
  • priority: Natural priority moves
  • multiHit: Hits multiple times
  • charging: Requires charging turn

Dynamic Combinations

Power vs Risk Tradeoffs

  1. High Power, Self-Debuff
{
  "name": "Berserker Strike",
  "power": 130,
  "effects": [
    {
      "type": "damage",
      "target": "opponent", 
      "formula": "standard"
    },
    {
      "type": "modifyStats",
      "target": "self",
      "stats": { "defense": "greatly_decrease" },
      "condition": "afterUse"
    }
  ]
}
  1. Accuracy Trade for Power
{
  "name": "Wild Swing",
  "power": 100,
  "accuracy": 70,
  "effects": [
    {
      "type": "damage",
      "target": "opponent",
      "formula": "standard"
    },
    {
      "type": "modifyStats", 
      "target": "self",
      "stats": { "accuracy": "decrease" },
      "condition": "afterUse"
    }
  ]
}
  1. Conditional Power Scaling
{
  "name": "Revenge Strike",
  "power": 60,
  "effects": [
    {
      "type": "damage",
      "target": "opponent",
      "amount": "normal"
    },
    {
      "type": "damage", 
      "target": "opponent",
      "amount": "strong",
      "condition": "ifDamagedThisTurn"
    }
  ]
}

Extreme Risk-Reward Moves

Powerful moves with dramatic sacrifices create high-stakes decision making:

Self Destruct - Ultimate sacrifice for massive damage

{
  "name": "Self Destruct",
  "power": 200,
  "accuracy": 100,
  "pp": 1,
  "priority": 0,
  "flags": ["explosive", "contact"],
  "effects": [
    {
      "type": "damage",
      "target": "all",
      "formula": "standard",
      "multiplier": 1.5
    },
    {
      "type": "damage",
      "target": "self",
      "formula": "fixed",
      "value": 9999,
      "condition": "afterUse"
    }
  ]
}

Life Drain Overload - Heal massively but lose stats permanently

{
  "name": "Life Drain Overload",
  "power": 0,
  "accuracy": 100,
  "pp": 3,
  "priority": 0,
  "flags": ["draining"],
  "effects": [
    {
      "type": "heal",
      "target": "self",
      "amount": "percentage",
      "value": 75
    },
    {
      "type": "modifyStats",
      "target": "self",
      "stats": { "attack": "greatly_decrease" },
      "condition": "afterUse"
    }
  ]
}

Berserker's End - More damage as HP gets lower, but can't heal

{
  "name": "Berserker's End", 
  "power": 80,
  "accuracy": 95,
  "pp": 10,
  "priority": 0,
  "flags": ["contact", "reckless"],
  "effects": [
    {
      "type": "damage",
      "target": "opponent",
      "amount": "normal"
    },
    {
      "type": "damage",
      "target": "opponent", 
      "amount": "strong",
      "condition": "ifLowHp"
    },
    {
      "type": "mechanicOverride",
      "target": "self",
      "mechanic": "healingBlocked",
      "value": true
    }
  ]
}

Mirror Shatter - Reflect all damage taken this turn back doubled

{
  "name": "Mirror Shatter",
  "power": 0,
  "accuracy": 100,
  "pp": 5,
  "priority": 4,
  "flags": ["priority"],
  "effects": [
    {
      "type": "mechanicOverride",
      "target": "self",
      "mechanic": "damageReflection",
      "value": "double",
      "condition": "thisTurn"
    },
    {
      "type": "modifyStats",
      "target": "self",
      "stats": { "defense": "greatly_decrease", "fieldDefense": "greatly_decrease" },
      "condition": "afterUse"
    }
  ]
}

Temporal Overload - Act twice next turn, skip following turn

{
  "name": "Temporal Overload",
  "power": 0,
  "accuracy": 100,
  "pp": 2,
  "priority": 0,
  "flags": ["temporal"],
  "effects": [
    {
      "type": "mechanicOverride",
      "target": "self",
      "mechanic": "extraTurn",
      "value": true,
      "condition": "nextTurn"
    },
    {
      "type": "applyStatus",
      "target": "self",
      "status": "paralyzed",
      "chance": 100,
      "condition": "turnAfterNext"
    }
  ]
}

Blood Pact - Sacrifice HP to double all damage dealt

{
  "name": "Blood Pact",
  "power": 0,
  "accuracy": 100,
  "pp": 3,
  "priority": 0,
  "flags": ["sacrifice"],
  "effects": [
    {
      "type": "damage",
      "target": "self",
      "formula": "percentage",
      "value": 50
    },
    {
      "type": "mechanicOverride",
      "target": "self",
      "mechanic": "damageMultiplier",
      "value": 2.0,
      "condition": "restOfBattle"
    }
  ]
}

Soul Burn - Massive special attack that burns user's PP

{
  "name": "Soul Burn",
  "power": 150,
  "accuracy": 90,
  "pp": 5,
  "priority": 0,
  "flags": ["burning"],
  "effects": [
    {
      "type": "damage",
      "target": "opponent",
      "formula": "standard"
    },
    {
      "type": "manipulatePP",
      "target": "self",
      "action": "drain",
      "amount": 3,
      "targetMove": "random",
      "condition": "afterUse"
    }
  ]
}

Cursed Gambit - Random effect: heal fully OR faint instantly

{
  "name": "Cursed Gambit",
  "power": 0,
  "accuracy": 100,
  "pp": 1,
  "priority": 0,
  "flags": ["gambling", "cursed"],
  "effects": [
    {
      "type": "heal",
      "target": "self",
      "amount": "percentage", 
      "value": 100,
      "condition": "ifLucky50"
    },
    {
      "type": "damage",
      "target": "self",
      "formula": "fixed",
      "value": 9999,
      "condition": "ifUnlucky50"
    }
  ]
}

Apocalypse Strike - Massive damage to all, but user becomes vulnerable

{
  "name": "Apocalypse Strike",
  "power": 120,
  "accuracy": 85,
  "pp": 1,
  "priority": 0,
  "flags": ["apocalyptic"],
  "effects": [
    {
      "type": "damage",
      "target": "all",
      "formula": "standard",
      "multiplier": 1.3
    },
    {
      "type": "mechanicOverride",
      "target": "self",
      "mechanic": "criticalHits",
      "value": "alwaysReceive",
      "condition": "restOfBattle"
    },
    {
      "type": "modifyStats",
      "target": "self",
      "stats": { "defense": "greatly_decrease", "fieldDefense": "greatly_decrease" }
    }
  ]
}

Multi-Stage Effects

Complex moves can have multiple phases:

{
  "name": "Charging Blast",
  "power": 120,
  "accuracy": 90,
  "pp": 5,
  "flags": ["charging"],
  "effects": [
    {
      "type": "modifyStats",
      "target": "self",
      "stats": { "defense": "increase" },
      "condition": "onCharging"
    },
    {
      "type": "damage",
      "target": "opponent", 
      "formula": "standard",
      "condition": "afterCharging"
    },
    {
      "type": "applyStatus",
      "target": "self",
      "status": "vulnerable",
      "condition": "afterCharging"
    }
  ]
}

Implementation Benefits

1. Programmatic Execution

  • All effects are defined as data structures
  • Battle engine can execute any combination of effects
  • No hardcoded move implementations needed

2. Infinite Variety

  • Mix and match building blocks for unique moves
  • Same building blocks create vastly different strategies
  • Easy to balance by adjusting values

3. Clear Tradeoffs

  • Every powerful effect has a drawback
  • Players must weigh risk vs reward
  • Multiple viable strategies emerge

4. Emergent Complexity

  • Simple rules create complex interactions
  • Abilities interact with moves in unexpected ways
  • Meta-game develops naturally

5. Easy Extension

  • New effect types can be added seamlessly
  • New conditions and triggers expand possibilities
  • Backward compatible with existing definitions

Battle Flow Integration

The battle system processes effects in this order:

  1. Pre-Move Phase: Priority calculation, ability triggers
  2. Move Execution: Damage calculation, hit/miss determination
  3. Effect Application: Apply all move effects based on conditions
  4. Post-Move Phase: End-of-turn abilities, status effects
  5. Turn Cleanup: Duration decrements, expired effect removal

This ensures predictable interaction resolution while allowing for complex chains of effects.

Balancing Philosophy

The system encourages diverse strategies through:

  • No "strictly better" moves: Every powerful move has meaningful drawbacks
  • Type diversity matters: Different types offer different utility patterns
  • Timing is crucial: When to use high-risk moves becomes strategic
  • Adaptation required: Static strategies are punishable by counter-play

This creates a dynamic battle system where player skill and strategic thinking matter more than raw stat advantages.

Complete System Reference

Available Conditions

  • always: Effect always applies when triggered
  • onHit: Effect applies only if the move hits successfully
  • afterUse: Effect applies after move execution regardless of hit/miss
  • onCritical: Effect applies only on critical hits
  • ifLowHp: Effect applies if user's HP < 25%
  • ifHighHp: Effect applies if user's HP > 75%
  • thisTurn: Effect lasts only for the current turn
  • nextTurn: Effect applies on the next turn
  • turnAfterNext: Effect applies two turns from now
  • restOfBattle: Effect persists for the remainder of the battle
  • onCharging: Effect applies during charging phase of two-turn moves
  • afterCharging: Effect applies after charging phase completes
  • ifDamagedThisTurn: Effect applies if user took damage this turn
  • ifNotSuperEffective: Effect applies if move would not be super effective
  • ifMoveType:[type]: Effect applies if move is of specified type
  • ifStatus:[status]: Effect applies if user has specified status
  • whileFrozen: Effect applies while user is frozen
  • ifWeather:[weather]: Effect applies if weather condition is active
  • ifStatusMove: Effect applies if move is a status move
  • ifLucky50: Effect applies on 50% random chance (good outcome)
  • ifUnlucky50: Effect applies on 50% random chance (bad outcome)

Available Mechanic Overrides

  • criticalHits: Modify critical hit behavior
  • statusImmunity: Immunity to specific status effects
  • statusReplacement:[status]: Replace status effect with different effect
  • damageReflection: Reflect damage back to attacker
  • damageAbsorption: Absorb damage of specific types
  • damageCalculation: Modify damage calculation rules
  • damageMultiplier: Multiply all damage dealt
  • healingInversion: Healing effects cause damage instead
  • healingBlocked: Prevent all healing
  • priorityOverride: Override move priority
  • accuracyBypass: Moves cannot miss
  • typeImmunity: Immunity to specific damage types
  • typeChange: Change Piclet's type
  • contactDamage: Deal damage to contact move users
  • drainInversion: HP drain heals target instead
  • weatherImmunity: Immunity to weather effects
  • flagImmunity: Immunity to moves with specific flags
  • flagWeakness: Extra damage from moves with specific flags
  • flagResistance: Reduced damage from moves with specific flags
  • statModification: Modify how stat changes work
  • targetRedirection: Change move targets
  • extraTurn: Grant additional turns

Available Event Triggers

  • onDamageTaken: When this Piclet takes damage
  • onDamageDealt: When this Piclet deals damage
  • onContactDamage: When hit by a contact move
  • onStatusInflicted: When a status is applied to this Piclet
  • onStatusMove: When targeted by a status move
  • onStatusMoveTargeted: When targeted by opponent's status move
  • onCriticalHit: When this Piclet lands/receives a critical hit
  • onHPDrained: When HP is drained from this Piclet
  • onKO: When this Piclet knocks out an opponent
  • onSwitchIn: When this Piclet enters battle
  • onSwitchOut: When this Piclet leaves battle
  • onWeatherChange: When battlefield weather changes
  • beforeMoveUse: Just before this Piclet uses a move
  • afterMoveUse: Just after this Piclet uses a move
  • onLowHP: When HP drops below 25%
  • onFullHP: When HP is at 100%
  • endOfTurn: At the end of each turn
  • onOpponentContactMove: When opponent uses contact move

Available Status Effects

  • burn: Ongoing fire damage
  • freeze: Cannot act (unless replaced by ability)
  • paralyze: Speed reduction and chance to be unable to move
  • poison: Ongoing poison damage
  • sleep: Cannot act for several turns
  • confuse: Chance to hit self instead of target

Available Move Flags

  • contact: Makes physical contact
  • bite: Biting attack
  • punch: Punching attack
  • sound: Sound-based attack
  • explosive: Explosive attack
  • draining: Drains HP from target
  • ground: Ground-based attack
  • priority: Has natural priority
  • lowPriority: Has negative priority
  • charging: Requires charging turn
  • recharge: User must recharge after
  • multiHit: Hits multiple times
  • twoTurn: Takes two turns to execute
  • sacrifice: Involves self-sacrifice
  • gambling: Has random outcomes
  • reckless: High power with drawbacks
  • reflectable: Can be reflected
  • snatchable: Can be stolen
  • copyable: Can be copied
  • protectable: Blocked by Protect
  • bypassProtect: Ignores Protect

Available Types

Types correspond to photographed objects in the real world:

  • beast 🐾: Vertebrate wildlife — mammals, birds, reptiles. Raw physicality, instincts, and region-based variants
  • bug 🐛: Arthropods great and small: butterflies, beetles, mantises. Agile swarms, precision strikes, metamorphosis
  • aquatic 🌊: Life that swims, dives, sloshes: fish, octopus, ink-creatures, sentient puddles. Masters of tides and pressure
  • flora 🌿: Plants and fungi captured in bloom or decay. Growth, spores, vines, seasonal shifts
  • mineral 🪨: Stones, crystals, metals shaped by earth's depths. High durability, reflective armor, seismic shocks
  • space ✨: Stars, moon, cosmic objects not of this world. Stellar energy, gravitational effects, void manipulation
  • machina ⚙️: Engineered devices from gadgets to heavy machinery. Gears, circuits, drones, power surges
  • structure 🏛️: Buildings, bridges, monuments, ruins as titans. Fortification, terrain shaping, zone denial
  • culture 🎨: Art, fashion, toys, written symbols. Buffs, debuffs, illusion, story-driven interactions
  • cuisine 🍣: Dishes, drinks, culinary artistry. Flavors, aromas, temperature shifts for support or offense
  • normal 👤: Attack type only (no Piclets are Normal type). Represents mundane, non-specialized attacks

Type Effectiveness Chart

ATK \ DEF 🐾 Beast 🐛 Bug 🌊 Aquatic 🌿 Flora 🪨 Mineral ✨Space ⚙️ Machina 🏛️ Structure 🎨 Culture 🍣 Cuisine
🐾 Beast 1 ×2 1 1 ×½ 0 ×½ ×½ ×2 ×2
🐛 Bug ×2 1 1 ×2 ×½ ×½ 1 0 ×½ ×½
🌊 Aquatic 1 1 1 ×½ ×2 ×2 ×2 1 ×½ ×½
🌿 Flora 1 ×2 ×2 1 ×2 ×½ 0 ×2 1 ×½
🪨 Mineral ×2 ×2 ×½ ×½ 1 ×½ ×2 1 1 0
✨ Space 0 ×2 ×½ ×2 ×2 1 ×½ ×2 ×½ ×½
⚙️ Machina ×2 ×½ ×½ ×2 ×½ ×½ 1 ×2 1 1
🏛️ Structure ×½ ×½ 1 1 1 ×½ ×2 1 ×2 ×2
🎨 Culture ×½ ×½ 1 1 0 ×2 ×2 ×2 1 ×½
🍣 Cuisine ×2 ×½ ×½ 1 0 ×2 1 ×½ ×2 1
👤 Normal 1 1 1 1 1 0 1 1 1 1

Legend:

  • ×2 = Super effective (2x damage)
  • ×½ = Not very effective (0.5x damage)
  • 0 = No effect (0x damage)
  • 1 = Normal effectiveness (1x damage)

JSON Schema

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "title": "Piclet Definition",
  "required": ["name", "description", "tier", "primaryType", "baseStats", "nature", "specialAbility", "movepool"],
  "properties": {
    "name": {
      "type": "string",
      "description": "The name of the Piclet"
    },
    "description": {
      "type": "string", 
      "description": "Flavor text describing the Piclet"
    },
    "tier": {
      "type": "string",
      "enum": ["low", "medium", "high", "legendary"],
      "description": "Power tier of the Piclet"
    },
    "primaryType": {
      "type": "string",
      "enum": ["beast", "bug", "aquatic", "flora", "mineral", "space", "machina", "structure", "culture", "cuisine"],
      "description": "Primary type of the Piclet"
    },
    "secondaryType": {
      "type": ["string", "null"],
      "enum": ["beast", "bug", "aquatic", "flora", "mineral", "space", "machina", "structure", "culture", "cuisine", null],
      "description": "Optional secondary type"
    },
    "baseStats": {
      "type": "object",
      "required": ["hp", "attack", "defense", "speed"],
      "properties": {
        "hp": {"type": "integer", "minimum": 1, "maximum": 255},
        "attack": {"type": "integer", "minimum": 1, "maximum": 255},
        "defense": {"type": "integer", "minimum": 1, "maximum": 255},
        "speed": {"type": "integer", "minimum": 1, "maximum": 255}
      },
      "additionalProperties": false
    },
    "nature": {
      "type": "string",
      "description": "Personality trait affecting stats or behavior"
    },
    "specialAbility": {
      "$ref": "#/definitions/SpecialAbility"
    },
    "movepool": {
      "type": "array",
      "items": {"$ref": "#/definitions/Move"},
      "minItems": 1,
      "maxItems": 8
    }
  },
  "additionalProperties": false,
  "definitions": {
    "SpecialAbility": {
      "type": "object",
      "required": ["name", "description"],
      "properties": {
        "name": {"type": "string"},
        "description": {"type": "string"},
        "effects": {
          "type": "array",
          "items": {"$ref": "#/definitions/Effect"}
        },
        "triggers": {
          "type": "array", 
          "items": {"$ref": "#/definitions/Trigger"}
        }
      },
      "additionalProperties": false
    },
    "Move": {
      "type": "object",
      "required": ["name", "type", "power", "accuracy", "pp", "priority", "flags", "effects"],
      "properties": {
        "name": {"type": "string"},
        "type": {
          "type": "string",
          "enum": ["beast", "bug", "aquatic", "flora", "mineral", "space", "machina", "structure", "culture", "cuisine", "normal"]
        },
        "power": {"type": "integer", "minimum": 0, "maximum": 250},
        "accuracy": {"type": "integer", "minimum": 0, "maximum": 100},
        "pp": {"type": "integer", "minimum": 1, "maximum": 50},
        "priority": {"type": "integer", "minimum": -5, "maximum": 5},
        "flags": {
          "type": "array",
          "items": {
            "type": "string",
            "enum": ["contact", "bite", "punch", "sound", "explosive", "draining", "ground", "priority", "lowPriority", "charging", "recharge", "multiHit", "twoTurn", "sacrifice", "gambling", "reckless", "reflectable", "snatchable", "copyable", "protectable", "bypassProtect"]
          },
          "uniqueItems": true
        },
        "effects": {
          "type": "array",
          "items": {"$ref": "#/definitions/Effect"},
          "minItems": 1
        }
      },
      "additionalProperties": false
    },
    "Effect": {
      "type": "object",
      "required": ["type"],
      "properties": {
        "type": {
          "type": "string",
          "enum": ["damage", "modifyStats", "applyStatus", "heal", "manipulatePP", "fieldEffect", "counter", "priority", "removeStatus", "mechanicOverride"]
        },
        "target": {
          "type": "string",
          "enum": ["self", "opponent", "allies", "all", "attacker", "field", "playerSide", "opponentSide"]
        },
        "condition": {
          "type": "string",
          "enum": ["always", "onHit", "afterUse", "onCritical", "ifLowHp", "ifHighHp", "thisTurn", "nextTurn", "turnAfterNext", "restOfBattle", "onCharging", "afterCharging", "ifDamagedThisTurn", "ifNotSuperEffective", "ifStatusMove", "ifLucky50", "ifUnlucky50", "whileFrozen"]
        }
      },
      "allOf": [
        {
          "if": {"properties": {"type": {"const": "damage"}}},
          "then": {
            "required": ["amount"],
            "properties": {
              "amount": {
                "type": "string",
                "enum": ["weak", "normal", "strong", "extreme"]
              }
            }
          }
        },
        {
          "if": {"properties": {"type": {"const": "modifyStats"}}},
          "then": {
            "required": ["stats"],
            "properties": {
              "stats": {
                "type": "object",
                "properties": {
                  "hp": {"type": "string", "enum": ["increase", "decrease", "greatly_increase", "greatly_decrease"]},
                  "attack": {"type": "string", "enum": ["increase", "decrease", "greatly_increase", "greatly_decrease"]},
                  "defense": {"type": "string", "enum": ["increase", "decrease", "greatly_increase", "greatly_decrease"]},
                  "speed": {"type": "string", "enum": ["increase", "decrease", "greatly_increase", "greatly_decrease"]},
                  "accuracy": {"type": "string", "enum": ["increase", "decrease", "greatly_increase", "greatly_decrease"]}
                },
                "additionalProperties": false,
                "minProperties": 1
              }
            }
          }
        },
        {
          "if": {"properties": {"type": {"const": "applyStatus"}}},
          "then": {
            "required": ["status"],
            "properties": {
              "status": {
                "type": "string",
                "enum": ["burn", "freeze", "paralyze", "poison", "sleep", "confuse"]
              }
            }
          }
        },
        {
          "if": {"properties": {"type": {"const": "heal"}}},
          "then": {
            "required": ["amount"],
            "properties": {
              "amount": {"type": "string", "enum": ["small", "medium", "large", "full"]}
            }
          }
        },
        {
          "if": {"properties": {"type": {"const": "manipulatePP"}}},
          "then": {
            "required": ["action", "amount"],
            "properties": {
              "action": {"type": "string", "enum": ["drain", "restore", "disable"]},
              "amount": {"type": "string", "enum": ["small", "medium", "large"]}
            }
          }
        },
        {
          "if": {"properties": {"type": {"const": "fieldEffect"}}},
          "then": {
            "required": ["effect"],
            "properties": {
              "effect": {"type": "string"},
              "stackable": {"type": "boolean"}
            }
          }
        },
        {
          "if": {"properties": {"type": {"const": "counter"}}},
          "then": {
            "required": ["counterType", "strength"],
            "properties": {
              "counterType": {"type": "string", "enum": ["physical", "special", "any"]},
              "strength": {"type": "string", "enum": ["weak", "normal", "strong"]}
            }
          }
        },
        {
          "if": {"properties": {"type": {"const": "priority"}}},
          "then": {
            "required": ["value"],
            "properties": {
              "value": {"type": "integer", "minimum": -5, "maximum": 5}
            }
          }
        },
        {
          "if": {"properties": {"type": {"const": "removeStatus"}}},
          "then": {
            "required": ["status"],
            "properties": {
              "status": {
                "type": "string",
                "enum": ["burn", "freeze", "paralyze", "poison", "sleep", "confuse"]
              }
            }
          }
        },
        {
          "if": {"properties": {"type": {"const": "mechanicOverride"}}},
          "then": {
            "required": ["mechanic", "value"],
            "properties": {
              "mechanic": {
                "type": "string",
                "enum": ["criticalHits", "statusImmunity", "damageReflection", "damageAbsorption", "damageCalculation", "damageMultiplier", "healingInversion", "healingBlocked", "priorityOverride", "accuracyBypass", "typeImmunity", "typeChange", "contactDamage", "drainInversion", "weatherImmunity", "flagImmunity", "flagWeakness", "flagResistance", "statModification", "targetRedirection", "extraTurn"]
              },
              "value": {}
            }
          }
        }
      ],
      "additionalProperties": false
    },
    "Trigger": {
      "type": "object",
      "required": ["event", "effects"],
      "properties": {
        "event": {
          "type": "string",
          "enum": ["onDamageTaken", "onDamageDealt", "onContactDamage", "onStatusInflicted", "onStatusMove", "onStatusMoveTargeted", "onCriticalHit", "onHPDrained", "onKO", "onSwitchIn", "onSwitchOut", "onWeatherChange", "beforeMoveUse", "afterMoveUse", "onLowHP", "onFullHP", "endOfTurn", "onOpponentContactMove"]
        },
        "condition": {
          "type": "string",
          "enum": ["always", "onHit", "afterUse", "onCritical", "ifLowHp", "ifHighHp", "thisTurn", "nextTurn", "turnAfterNext", "restOfBattle", "onCharging", "afterCharging", "ifDamagedThisTurn", "ifNotSuperEffective", "ifStatusMove", "ifLucky50", "ifUnlucky50", "whileFrozen"]
        },
        "effects": {
          "type": "array",
          "items": {"$ref": "#/definitions/Effect"},
          "minItems": 1
        }
      },
      "additionalProperties": false
    }
  }
}

Complete Example: Tempest Wraith

Here's a full example of a Piclet using the complete schema with advanced abilities and dramatic moves:

{
  "name": "Tempest Wraith",
  "description": "A ghostly creature born from violent storms, wielding cosmic energy and shadowy illusions",
  "tier": "high",
  "primaryType": "space",
  "secondaryType": "culture",
  "baseStats": {
    "hp": 75,
    "attack": 95,
    "defense": 45,
    "speed": 85
  },
  "nature": "timid",
  "specialAbility": {
    "name": "Storm Caller",
    "description": "When HP drops below 25%, gains immunity to status effects and +50% speed",
    "triggers": [
      {
        "event": "onLowHP",
        "effects": [
          {
            "type": "mechanicOverride",
            "mechanic": "statusImmunity",
            "value": ["burn", "freeze", "paralyze", "poison", "sleep", "confuse"]
          },
          {
            "type": "modifyStats",
            "target": "self",
            "stats": { "speed": "greatly_increase" }
          }
        ]
      },
      {
        "event": "onSwitchIn",
        "condition": "ifWeather:storm",
        "effects": [
          {
            "type": "modifyStats",
            "target": "self",
            "stats": { "attack": "increase" }
          }
        ]
      }
    ]
  },
  "movepool": [
    {
      "name": "Shadow Pulse",
      "type": "culture",
      "power": 70,
      "accuracy": 100,
      "pp": 15,
      "priority": 0,
      "flags": [],
      "effects": [
        {
          "type": "damage",
          "target": "opponent",
          "amount": "normal"
        },
        {
          "type": "applyStatus",
          "target": "opponent",
          "status": "confuse"
        }
      ]
    },
    {
      "name": "Cosmic Strike",
      "type": "space",
      "power": 85,
      "accuracy": 90,
      "pp": 10,
      "priority": 0,
      "flags": [],
      "effects": [
        {
          "type": "damage",
          "target": "opponent",
          "amount": "normal"
        },
        {
          "type": "applyStatus",
          "target": "opponent",
          "status": "paralyze"
        }
      ]
    },
    {
      "name": "Spectral Drain",
      "type": "culture",
      "power": 60,
      "accuracy": 95,
      "pp": 12,
      "priority": 0,
      "flags": ["draining"],
      "effects": [
        {
          "type": "damage",
          "target": "opponent",
          "formula": "drain",
          "value": 0.5
        },
        {
          "type": "heal",
          "target": "self",
          "amount": "medium"
        }
      ]
    },
    {
      "name": "Void Sacrifice",
      "type": "space",
      "power": 130,
      "accuracy": 85,
      "pp": 1,
      "priority": 0,
      "flags": ["sacrifice", "explosive"],
      "effects": [
        {
          "type": "damage",
          "target": "all",
          "formula": "standard",
          "multiplier": 1.2
        },
        {
          "type": "damage",
          "target": "self",
          "formula": "percentage",
          "value": 75
        },
        {
          "type": "fieldEffect",
          "effect": "voidStorm",
          "target": "field",
          "stackable": false
        }
      ]
    }
  ]
}

This example demonstrates:

Advanced Special Ability

  • Conditional Triggers: Different effects based on HP and weather
  • Multiple Mechanics: Status immunity + stat boosts + weather interactions
  • Strategic Depth: Becomes more dangerous when near defeat

Diverse Movepool

  • Standard Attack: Shadow Pulse with minor status chance
  • Type Coverage: Storm and Shadow moves for different matchups
  • Utility Move: Spectral Drain for sustainability
  • Ultimate Move: Storm's Sacrifice - massive AoE damage with severe self-harm

Meaningful Tradeoffs

  • Spectral Drain: Healing requires hitting the opponent
  • Storm's Sacrifice: Incredible power (130 base + 20% bonus to all) but costs 75% of user's HP
  • Low defenses: High speed/special attack but vulnerable to physical moves

Emergent Strategy

  • Use standard moves early while healthy
  • Spectral Drain for sustain in mid-game
  • When low on HP, ability kicks in for immunity and speed boost
  • Storm's Sacrifice as desperate finisher or when opponent is also low

This creates a Piclet that plays differently throughout the battle, rewards risk-taking, and offers multiple viable strategies depending on the situation!