Skip to content

feat(parser): implement Tekuthal, Inquiry Dominus — fix split_cost_parts for multi-type from-among costs#3699

Open
wlaursen wants to merge 1 commit into
phase-rs:mainfrom
wlaursen:card/tekuthal-inquiry-dominus
Open

feat(parser): implement Tekuthal, Inquiry Dominus — fix split_cost_parts for multi-type from-among costs#3699
wlaursen wants to merge 1 commit into
phase-rs:mainfrom
wlaursen:card/tekuthal-inquiry-dominus

Conversation

@wlaursen

Copy link
Copy Markdown
Contributor

Summary

Tekuthal, Inquiry Dominus has two parseable abilities:

  1. Proliferate replacement — "If you would proliferate, proliferate twice instead."
    Already implemented and tested (parse_proliferate_count_replacement, test tekuthal_proliferate_replacement_parses).

  2. Activated ability{1}{U/P}{U/P}, Remove three counters from among other artifacts, creatures, and planeswalkers you control: Proliferate.
    The cost had a coverage gap: split_cost_parts was splitting on commas in the type list, producing [{1}{U/P}{U/P}], [Remove...artifacts], [creatures], [planeswalkers] — four parts instead of two. The last two parsed as Unimplemented, blocking cost evaluation.

Fix: When the accumulated cost segment already contains "from among", skip comma and " and " splits — they are type-list separators, not cost separators. The intact phrase reaches parse_remove_counter_targetparse_targetparse_type_phrase, which already handles comma-separated type lists and builds Or[Typed{Artifact,Another,You}, Typed{Creature,Another,You}, Typed{Planeswalker,Another,You}].

All five Dominus cards from Phyrexia: All Will Be One share this cost pattern and benefit from the same fix.


Model: claude-sonnet-4-6
Tier: Standard

Gate A

$ bash ./scripts/check-parser-combinators.sh
(no output — exit 0)

Anchored on

  1. crates/engine/src/parser/oracle_cost.rs:76split_cost_parts already uses brace-depth tracking to avoid splitting inside {...} mana symbols. My change extends this with a look-back condition for "from among" phrases using the same per-character loop.

  2. crates/engine/src/parser/oracle_cost.rs:130fixup_bare_noun_continuations was the prior mechanism for handling false cost fragments produced by over-eager splitting (for Sacrifice/Exile/TapCreatures). My fix addresses the same problem at the split level rather than post-hoc, keeping RemoveCounter's multi-type target unified.

  3. crates/engine/src/parser/oracle_target.rs:1911–1968 — comma-separated type list → OR filter is already implemented in parse_type_phrase_with_ctx, confirmed by test at line 9238 ("creatures, artifacts, and enchantments you control"Or[Creature{You}, Artifact{You}, Enchantment{You}]). My fix enables this path to receive the full type-list string.

  4. crates/engine/src/parser/oracle_cost.rs:2185 — existing test cost_remove_x_counters_from_among_creatures_you_control establishes the AmongObjects selection path for single-type "from among" costs; my new test cost_tekuthal_remove_three_counters_from_among_or_types extends the pattern to the multi-type OR case.

Test plan

  • cost_tekuthal_remove_three_counters_from_among_or_types — new discriminating test; verifies the full composite cost parses as Composite[Mana, RemoveCounter{count=3, AmongObjects, Or[Artifact|Creature|Planeswalker, each Another+You]}]
  • Reverts to 4-part Composite with Unimplemented fragments if the split_cost_parts guard is removed
  • Existing cost_remove_x_counters_from_among_creatures_you_control (single-type) and all other split_cost_parts tests unchanged

🤖 Generated with Claude Code

…s one cost

Tekuthal, Inquiry Dominus has activation cost:
  {1}{U/P}{U/P}, Remove three counters from among other artifacts, creatures, and planeswalkers you control

split_cost_parts was splitting on the commas in the type list, producing
four fragments ([mana], [Remove...artifacts], [creatures], [planeswalkers])
instead of two ([mana], [Remove...planeswalkers you control]).

The "creatures" and "planeswalkers" fragments parsed as Unimplemented, so
the ability showed a coverage gap and was treated as always-payable.

Fix: when the accumulated cost segment already contains "from among", skip
comma and " and " splits — they are type-list separators, not cost separators.
The full target phrase then reaches parse_remove_counter_target intact, which
calls parse_target → parse_type_phrase on "other artifacts, creatures, and
planeswalkers you control" and correctly builds
Or[Typed{Artifact,Another,You}, Typed{Creature,Another,You}, Typed{Planeswalker,Another,You}].

All five Dominus cards (Phyrexia: All Will Be One) share this cost pattern
and benefit from the same fix.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@wlaursen wlaursen requested a review from matthewevans as a code owner June 18, 2026 02:33
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

VERDICT: request-changes

[MED] The from among guard suppresses every later separator until the end of the cost string. Evidence: crates/engine/src/parser/oracle_cost.rs:94 and crates/engine/src/parser/oracle_cost.rs:104 check whether the whole accumulated segment contains from among, but never re-anchor start after the target phrase ends. Why it matters: this fixes Tekuthal because its from-among cost is the final cost part, but the shared splitter will merge any later top-level cost (for example a future Remove ... from among ..., Sacrifice ... shape) into the remove-counter target text and silently drop/misparse that later cost. Suggested fix: make the exception bounded to the comma/and separators inside the parsed from among <type-list> target phrase, or split normally first and repair only the known RemoveCounter continuation fragments with a helper that stops once the target phrase is complete.

[LOW] The new CR citation points at the wrong rule. Evidence: crates/engine/src/parser/oracle_cost.rs:90 cites CR 118.12b, but docs/MagicCompRules.txt defines 118.12b as an “If [a player] does” search-choice rule, not remove-counter activation costs or counter objects. Why it matters: incorrect CR annotations are worse than absent ones in this repo because they make future reviewers trust the wrong rules basis. Suggested fix: cite the actual rule(s) being implemented here, such as the activation-cost payment rule plus the counter rule, or remove the CR number from this splitter comment if it is only documenting parser structure.

@matthewevans matthewevans added the enhancement New feature or request label Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants