implementing-cards
A specialized skill for adding new card logic and abilities to the Pokémon TCG Pocket game engine.
Install
mkdir -p .claude/skills/implementing-cards && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/347" && unzip -o skill.zip -d .claude/skills/implementing-cards && rm skill.zipInstalls to .claude/skills/implementing-cards
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Fill out the implementation of effects of different attacks, abilities, and trainer cards in this Pokemon TCG Pocket engine codebase.Key capabilities
- →Identify missing ability implementations
- →Map attack effects to existing mechanics
- →Execute card status checks via CLI
- →Validate card logic using test-driven development
- →Generate outcomes for state transitions
How it works
Uses existing rust binaries and effect maps to locate missing logic and validates new code through automated unit tests.
Inputs & outputs
When to use implementing-cards
- →Implement new card abilities
- →Add attack mechanics
- →Write TDD tests for game cards
About this skill
Implementing Cards
To implement cards, first read the models module and the state module. Cards
are not implemented if they are a Pokemon that is missing an Ability or Attack implementation,
or a Trainer card (be it a tool or a normal one) missig implementation.
Use TDD for every new card implementation:
- Before changing the production implementation, add 1 or 2 focused tests for the new card behavior.
- Write those tests at the same abstraction level as
test_raikou_rocky_helmet_promotion_orderintests/tools/raikou_rocky_helmet_order_test.rs. - Keep the tests at the public
GameAPI level, driving behavior through calls likegame.apply_action(...),generate_possible_actions(),get_state_clone(), and observable game state changes. - Do not start implementation until those tests exist.
If the user hasn't specified what card to implement, you can use the tool:
cargo run --bin card_status
to see what cards are missing, and choose one. You can also that tool to see what is missing from the specified card.
Abilities
-
Get the details of all the cards that have the ability you want to implement by using the following script:
- For a single card or name lookup:
cargo run --bin search "Venusaur" -
Copy the ids of cards to implement (including full art versions) in the given JSON. Only choose the ones with the ability you want to implement.
-
All abilities should use the
AbilityMechanicpathway.- Find the ability effect text in the JSON and search for it in
effect_ability_mechanic_map.rs. - Re-use an existing
AbilityMechanicwhen possible. If not, add a new variant insrc/actions/abilities/mechanic.rs. - Add or uncomment all matching
map.insert(...)lines ineffect_ability_mechanic_map.rsand map them to the correctAbilityMechanicwith parameters. - Implement the mechanic logic in
forecast_ability_by_mechanicinsrc/actions/apply_abilities_action.rs.- Return an
Outcomesstruct (seesrc/actions/outcomes.rs). - For deterministic effects:
Outcomes::single_fn(|rng, state, action| { ... }) - For coin-flip effects, use the appropriate
Outcomesconstructor:Outcomes::binary_coin(heads_mutation, tails_mutation)for a single coin flipOutcomes::binomial_by_heads(n, |heads| mutation)for N flips grouped by heads countOutcomes::geometric_until_tails(max, |heads| mutation)for flip-until-tails effects
- Keep
matcharms as one-liners by moving logic into helpers.
- Return an
- Implement move generation logic in
can_use_ability_by_mechanicinsrc/move_generation/move_generation_abilities.rs.- Keep
matcharms as one-liners by moving logic into helpers.
- Keep
- Find the ability effect text in the JSON and search for it in
-
If the ability is passive or hook-driven:
- Prefer a mechanic + hook combination.
- Put the mechanic-to-hook wiring in the relevant hook file, usually under
src/hooks/. forecast_ability_by_mechanicshouldpanic!for passive mechanics, andcan_use_ability_by_mechanicshould returnfalse.
-
Add 1 or 2 logic tests before implementation at the
Gamepublic API level.- Prefer the folder-matched integration test layout under
tests/, for exampletests/pokemon/...,tests/tools/...,tests/stadiums/..., ortests/mechanics/.... - Follow
test_raikou_rocky_helmet_promotion_orderintests/tools/raikou_rocky_helmet_order_test.rsin style and abstraction level. - Drive behavior through public APIs like
game.apply_action(...)instead of internal helpers or private implementation details. - Do not assert on
.move_generation_stack; drive behavior through public actions and resulting game state.
- Prefer the folder-matched integration test layout under
Attack
-
Get the details of the card with the attack you want to implement by using the following script:
cargo run --bin search "Venusaur" --attack "Giant Bloom" -
Search for the effect text in the above JSON in the
effect_mechanic_map.rsfile. -
Decide if we should introduce a new Mechanic or re-use or generalize an existing one. Try to re-use existing ones first.
-
Identify all the cards that have the same effect text template, and just differ by parameters.
-
Uncomment all the
// map.insert("lines that pertain to the mechanic, and add the correct value (anMechanicenum variant with the corresponding parameters). -
Implement the mechanic logic in
forecast_effect_attack_by_mechanicinsrc/actions/apply_attack_action.rs.- Return an
Outcomesstruct (seesrc/actions/outcomes.rs). - For deterministic effects:
Outcomes::single_fn(|rng, state, action| { ... }) - For coin-flip effects, use the appropriate
Outcomesconstructor:Outcomes::binary_coin(heads_mutation, tails_mutation)- single coin flipOutcomes::binomial_by_heads(n, |heads| mutation)- flip N coins, group by heads countOutcomes::geometric_until_tails(max, |heads| mutation)- flip until tails
- Keep the code as a simple one-liner in the match statement by using helper functions
- Review similar attacks in
src/actions/apply_attack_action.rsto ensure consistency in implementation.
- Return an
-
Add 1 or 2 Game-level logic tests in the matching
tests/subfolder before implementation when the attack has non-trivial behavior.- Match the abstraction level of
test_raikou_rocky_helmet_promotion_orderintests/tools/raikou_rocky_helmet_order_test.rs. - Exercise the
Gamepublic API, especiallygame.apply_action(...)and the resulting public game state.
- Match the abstraction level of
Tool
-
Get the details of the tool card that you want to implement by using the following script:
cargo run --bin search "Leaf Cape" -
Copy the ids of cards to implement (including full art versions) in the given JSON.
-
In
tools.rs: -
In
src/tools.rs:- Add a
static EFFECT_NAME_EFFECT: LazyLock<String>constant usingtool_effect_text_from_card_id(CardId::...). - Add the effect to
is_tool_effect_implemented()match expression. - If the tool has attachment restrictions (e.g., only Grass pokemon), add a check in
can_attach_tool_to().
- Add a
-
Implement any immediate effects in the tool's core logic rather than a dedicated "on attach" hook.
- For HP modifiers, prefer dynamic calculation in
PlayedCard::get_effective_total_hp(). - For other immediate effects, add a focused helper in the relevant hook file and call it from the appropriate action handler.
- For HP modifiers, prefer dynamic calculation in
-
Ensure Tool is correctly handled by
forecast_trainer_action. -
For tools with ongoing effects (not just on-attach):
- Implement hooks in
hooks/core.rsor other appropriate hook files. - Use
has_tool(played_card, CardId::...)to check if a pokemon has a specific tool attached. - Examples: Rocky Helmet deals damage when the holder is attacked.
- Implement hooks in
-
Add 1 or 2 Game-level integration tests under
tests/tools/before implementation for the observable effect.- Match the abstraction level of
test_raikou_rocky_helmet_promotion_orderintests/tools/raikou_rocky_helmet_order_test.rs. - Exercise the
Gamepublic API, especiallygame.apply_action(...)and the resulting public game state.
- Match the abstraction level of
Trainer Cards
-
Get the details of the trainer card that you want to implement by using the following script:
cargo run --bin search "Rare Candy" -
Copy the ids of cards to implement (including full art versions) in the given JSON.
-
Implement the "move generation" logic.
- In
move_generation_trainer.rsimplement the switch branch. Its often the case the Trainer/Support can always be played, so just add to this case in the switch.
- In
-
Implement the "apply action" logic.
-
This is the code that actually runs when the card is played.
-
Visit
src/actions/apply_trainer_action.rs. -
Return an
Outcomesstruct (seesrc/actions/outcomes.rs):- For deterministic effects:
Outcomes::single_fn(|rng, state, action| { ... }) - For coin-flip effects, use
Outcomes::binary_coin(...)or other coin constructors
- For deterministic effects:
-
Often its just "applying an effect" in the field (like Leaf).
- If the turn is something that affects all pokemon in play for a given turn use
the
.turn_effectsfield in the state. You can use to for effects that apply to this turn, or a future one. - Some cards might be fairly unique and might need architectural changes to the engine. For cards with considerable custom logic,
try to find a generalizing pattern that can be presented as a "hook" in the
hooks.rs. The idea ofhooks.rsis to try to encapsulate most custom logic that goes outside of the normal business logic. Also consider adding new pieces of state to theStatestruct if necessary.
- If the turn is something that affects all pokemon in play for a given turn use
the
-
Try to keep the
match trainer_idcases as one-liners (using helper functions if necessary).
-
-
Add 1 or 2 Game-level integration tests in the appropriate
tests/area before implementation if the trainer has logic beyond a trivial draw/search path.- Match the abstraction level of
test_raikou_rocky_helmet_promotion_orderintests/tools/raikou_rocky_helmet_order_test.rs. - Exercise the
Gamepublic API, especiallygame.apply_action(...)and the resulting public game state.
- Match the abstraction level of
Stadium
-
Get the details of the stadium card that you want to implement by using the following script:
cargo run --bin search "Peculiar Plaza" -
Copy the ids of cards to implement (including full art versions) in the given JSON.
-
In
src/stadiums.rs:- Add a static
LazyLock<String>constant for the stadium's effect text. - Add the stadium to
is_stadium_effect_implemented(). - Add a helper function to query the stadium's effect (e.g.,
get_peculiar_plaza_retreat_reduction).
- Add a static
-
Add Stadium move generation:
- Move generation is already handled generically in
move_generation_trainer.rsviacan_play_stadium(). - No per-stadium logic needed unless the stadium has unique play conditions.
- Move generation is already handled generically in
-
Hook the stadium effect into the appropriate game mechanic:
- Retreat cost effects:
hooks/retreat.rsin `get_retre
- Retreat cost effects:
Content truncated.
When not to use it
- →Creating new game engine features unrelated to card effects
- →General engine refactoring without specific card tests
Prerequisites
Limitations
- →Requires familiarity with the Rust codebase
- →Strict adherence to existing mechanic patterns required
How it compares
Enforces a strict test-first constraint before any production code modification is accepted.
Compared to similar skills
implementing-cards side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| implementing-cards (this skill) | 7 | 2mo | Review | Advanced |
| write-rust-tests | 9 | 5mo | No flags | Intermediate |
| gen-rust | 1 | 6mo | Review | Advanced |
| rocq-simulate-author | 1 | 6mo | Review | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
write-rust-tests
RediSearch
Write Rust tests to verify correctness of Rust code.
gen-rust
MoonshotAI
Sync Rust implementation with Python changes (exclude UI/login) by reviewing recent changes, mapping modules, porting logic, and updating tests.
rocq-simulate-author
formal-land
Create or update Rocq simulate files in this repository, including imports, executable definitions, and corresponding _eq lemmas with the project’s proof/admission conventions.
testing-hashql
hashintel
HashQL testing strategies including compiletest (UI tests), unit tests, and snapshot tests. Use when writing tests for HashQL code, using //~ annotations, running --bless, debugging test failures, or choosing the right testing approach.
rust-testing
aaione
Rust 测试模式,包括单元测试、集成测试、异步测试、属性测试、mocking 和覆盖率。遵循 TDD 方法论。
evolve
yologdev
Safely modify your own source code, test changes, and manage your evolution