Releases: phase-rs/phase
v0.1.59
Downloads
| Platform | File |
|---|---|
| Windows | Phase_*_x64-setup.exe |
| macOS (Apple Silicon) | Phase_*_aarch64.dmg |
| Linux | Phase_*_amd64.AppImage or .deb |
macOS note: If you see "this app is damaged", open Terminal and run:
xattr -cr /Applications/Phase.app
Changes
- fix(parser): bind "for each 1 life you gained/lost" to the event amount (#3588)
- test(engine): add Ugin's Labyrinth imprint mana integration guard (#3586)
- fix(parser): split bare-"and" "… and each opponent/player " conjunct (#3584)
- feat(parser): add 'N mana of different colors' production (#3581)
- chore: refresh metagame feeds (#3583)
- fix(parser): bind "that has a … counter on it" target-filter (#3579)
- fix(parser): parse "a creature is attacking you" presence condition (#3580)
- fix(parser): recognize Glimmer and Mammoth creature subtypes (#3575)
- fix(parser): UNSUPPORTED cluster: Villainous choice — each-opponent / each-target-controller two-mod (#3489)
- feat(parser): support Me, the Immortal + The Master, Mesmerist (#3509)
- fix(engine): resolve Kain combat-damage GiveControl and if-they-do riders (#3563)
- fix(engine): synthesize equip ability on created Equipment tokens (#942) (#3568)
- fix(ci): diagnostic ratchet skips cards not supported in baseline (#3571)
- fix(parser): bind target-anaphoric "if it [didn't] attack this turn" condition (#3567)
- fix(parser): recognize Universe Beyond creature subtypes (Gamma, Symbiote, Kree, Inhuman, Skrull, Autobot, Brainiac) (#3570)
- fix(parser): bind where-X to ChangeZone target's Cmc filter (#3564)
- fix(engine): make stacked proliferate doublers compound (Tekuthal x2) (#3562)
- fix(parser): bind "that attacking player" for attack-trigger token creation (#3560)
- fix(parser): recognize Hero, Spy, Scientist, Cyborg, Sorcerer creature subtypes (#3561)
- fix(parser): bind "target creature attacks if able" to the chosen creature (#3558)
- fix(parser): Temporary replacement effect ('creatures that would enter from exile are shuffled into (#3419)
- fix(parser): Cybership combat-damage trigger — top-two to battlefield as 2/2 Cybermen under controller (#3461)
- docs(skill): add cheap value/direction pre-gate before deep PR review (#3556)
- fix: wire proliferate through the CR 614 replacement pipeline for Tekuthal (#3555)
- fix(parser): recognize the Villain creature subtype (#3554)
- fix(parser): bind discard that many to previous draw count (issue #3296) (#3541)
- docs(skills): dual-mode pr-review-loop with tiered review + contributor-quality tracking (#3552)
- fix(engine): sum granted Toxic with printed Toxic instances (#955) (#3551)
- fix(parser): route "deals N to each opponent and …" player damage (Dagger Caster) (#3548)
- feat(ai): add enchantments-matter deck-feature axis + EnchantmentsPayoffPolicy (#3492)
- fix(effects): bind LastCreated GenericEffect grants to created tokens (issue #3297) (#3539)
- feat(engine): exchange life totals between two players (#3513)
- fix: Killian, Decisive Mentor trigger (#3483)
- fix(parser): parse opponent and battle they protect damage (issue #3293) (#3542)
- fix(parser): keep Syr Konrad disjunctive trigger unified (issue #3299) (#3532)
- fix(ui): shrink mobile lands tile + floor creature overview at one card row (#3544)
- fix(ui): surface chosen {X} value as a prominent stack badge (#3543)
- test(engine): production-path Springheart Nantuko regression + refresh stale fixture (#3540)
- fix(parser): parse 'gained or lost life this turn' disjunctive condition (#3538)
- fix(parser): split a second "target gets/…" conjunct (Skulduggery) (#3537)
- fix(casting): hide illegal modal spell modes by target legality (issue #3301) (#3529)
- fix(parser): Adeline tokens enter tapped and attacking (issue #3303) (#3528)
- fix(parser): one-shot damage-replacement shield carries inherent this-turn lifetime (#3534)
- fix(parser): preserve "one-sided fight" damage recipient + bind source (Ambuscade) (#3530)
- feat(ai): add artifacts-matter deck-feature axis + ArtifactSynergyPolicy (#3355)
- docs(engine): annotate CR 903.9c coverage via SBA path + discriminating tests (#3511)
- feat(parser): opponent-scoped draw replacements with except-first-draw gate (#3525)
- feat(parser): played-by-opponents enter tapped replacement (#3520)
- fix(ai+ui): activation patience (Mother of Runes, fetch lands) + stack-label mana symbols (#3527)
- fix(engine): Halving Season opponent scope on permanent counters (#3519)
- test(engine): Rise + ETB graveyard-return regression (#3309) (#3526)
- test(engine): Bloodletter skip doubling on opponent turns (#3522)
- fix(engine): synthesize keyword triggers in copiable values for copies (#3506)
- Fix Astral Dragon token copies missing 3/3 Dragon creature overrides (#3505)
- test(parser): artifact inverted counter prohibition regression (#3503)
- feat(parser): explore replacement scry prelude and double explore (#3499)
- fix(parser): count distinct power/mana value "among" populations (Golden Ratio) (#3515)
- test(engine): Bloodletter lose-life doubler runtime regression (#3521)
- feat(parser): parse subject-prefixed 'flips a coin' (#3349)
- fix: Breach the Multiverse per-player reanimation (#3484)
- Add Nix (#3488)
- fix: Phyrexian Mana autotap prioritization (#3446)
- fix: Springheart Nantuko attachment condition (#3439)
- fix(parser): Path of Ancestry (Commander-staple land) is UNSUPPORTED — implement full support, not a (#3487)
- fix(parser): UNSUPPORTED cluster: Granted 'next spell has cascade' + you-may-planeswalk rider, and g (#3508)
- refactor(PreferencesModal): replace SelectField with MenuSelect and enhance board background and audio theme selection (#3411)
- fix(engine): Fractal Harness ETB attaches to created Fractal token (#1007) (#3242)
- Fix Sevinne's Reclamation self-copy on flashback spell copies. (#3504)
- feat(parser): Halving Season opponent token halving replacement (#3495)
- test(parser): planeswalker inverted counter prohibition regression (#3501)
- fix(engine): no-op top-of-library put when search finds nothing (#3317) (#3443)
- test(engine): Halving Season halves opponent token batches (#3497)
- feat(parser): parse 'pay any amount of life' and 'pay half your life' (#3433)
- feat(engine): set-check CLI — per-set/deck coverage + AST-hash regression diff (#3481)
- Partial: fix(parser): counter target accepts all listed spell types and triggered abilities (#3360)
v0.1.58
Downloads
| Platform | File |
|---|---|
| Windows | Phase_*_x64-setup.exe |
| macOS (Apple Silicon) | Phase_*_aarch64.dmg |
| Linux | Phase_*_amd64.AppImage or .deb |
macOS note: If you see "this app is damaged", open Terminal and run:
xattr -cr /Applications/Phase.app
Changes
- test(engine): full-pipeline regression tests for Daretti emblem (#3075) and Afflict N (#2268) (#3410)
- fix(ai): reject SeparateIntoPiles spells when opponents have no creatures (#3468)
- chore: refresh metagame feeds (#3490)
- fix(parser): "you have protection from " grants the player protection, not their permanents (#3444)
- fix(parser): route bare "you don't own" ownership suffix (Agent of Treachery) (#3435)
- fix(parser): Elided-subject 'is a(n) {type} in addition to its other types' clause inside a become-c (#3426)
- fix(parser): recognize "for each card you've discarded this turn" dynamic count (#3482)
- fix: Agent of Treachery draw condition (#3447)
- fix(parser): capture "if it was cast using web-slinging" ETB intervening-if (#3448)
- fix(engine): pay untap-symbol activation costs for equipment grants (#3467)
- fix(parser): DamageDone trigger leaves valid_target=null, so match_damage_done skips the target/owne (#3469)
- fix: silently parses an unconditional counter (#3480)
- test(engine): pin Unearth activation-zone gate via Scrapwork Mutt (issue #3295) (#3465)
- feat(parser): opponent-scoped direct library search prohibition (#3428)
- feat(parser): Halving Season opponent counter halving (#3397)
- fix(engine): Seasoned Pyromancer creates correct token count for each nonland card discarded (#3437)
- refactor(parser): centralize optional, repeat-for, and player-scope peeling in clause_shell (#3464)
- feat(engine): legend rule integration guardrail test (#3432)
- feat(engine): SBA coverage for bare tokens legend-rule exemption (#3429)
- feat(parser): legend-rule exemption for base types, tokens, commanders (#3427)
- feat(parser): complete distribute/divide parser gaps (#3462)
- test(engine): pin Dark Depths + Thespian's Stage Marit Lage combo (issue #1514) (#3463)
- feat(parser): Ghostfire colorless CDA via oracle text pipeline (#3460)
- feat(parser): creatures counter prohibition inverse wording (#3451)
- feat(engine): first kicked spell per-turn cost reduction static (#3431)
- fix(engine): turn face-down cards face up when leaving stack/battlefield (#3285) (#3382)
- feat: Add parser support for global double-all-damage replacement sta… (#3445)
- fix: Explore additional land drop not working (#3442)
- fix(parser): route name-hate search clauses to MultiZoneSameNameExile (#3438)
- fix(engine): exclude transform back faces from Momir random-token pool (#3440)
- feat(engine): Momir's Madness format — fixed-deck flow, emblem, token-copy ETB (#3434)
- fix(engine): finish manifest dread when a land choice pauses on entry (#3311) (#3405)
- fix(parser): conditional "if it's a creature, it can't be regenerated" rider (#3376)
- fix(parser): count distinct card types among discarded cards (Occult Epiphany) (#3420)
- refactor(AiOpponentConfig): replace SelectField with MenuSelect for improved UI consistency (#3413)
- feat(parser): enchanted land destroy sacrifice indestructible replacement (#3399)
- feat(notification): integrate AppToast for import success notifications (#3417)
- feat(ai): add lifegain-matters deck-feature axis + LifegainPayoffPolicy (#3415)
- fix(engine): crew/saddle legal-action enumerator must use crew-adjusted power (#3412)
- feat(engine): max-untap restriction (can't untap more than one ) (#3366)
- refactor(CardSearch): replace SelectField with MenuSelect for improved dropdown functionality (#3409)
- fix(parser): Compound continuous-modification static '+N/+N and can't be blocked unless ...' drops t (#3406)
- feat(parser): generic additional token replacement (Tippy-Toe class) (#3385)
- feat(parser): lose-life doubler with opponent scope (#3393)
- feat(deck-builder): implement mobile filter sheet with portal support (#3408)
- feat(parser): basic land triple mana tap multiplier (#3395)
- fix(client): improve Settings modal layout, sidebar navigation, and scroll behavior (#3407)
- feat(parser): energy get additional {E} replacement (#3401)
- fix(engine): defer manifest dread graveyard on manifest entry pause (#3245) (#3383)
- fix(engine): Magus Lucea Kane Psychic Stimulus copies next X spell (#1010) (#3326)
- fix(parser): Fight/attacks-trigger target drops the 'creature defending player controls' scope, so t (#3404)
- feat(parser): parse 'remove all of them and transform' counter clause (#3346)
- fix(parser): bind 'equal to the result' die-roll quantity ref (#3380)
v0.1.57
Downloads
| Platform | File |
|---|---|
| Windows | Phase_*_x64-setup.exe |
| macOS (Apple Silicon) | Phase_*_aarch64.dmg |
| Linux | Phase_*_amd64.AppImage or .deb |
macOS note: If you see "this app is damaged", open Terminal and run:
xattr -cr /Applications/Phase.app
Changes
- fix(parser): parse "{N} plus an additional {M} for each X" unless-payment (#3381)
- fix(parser): Intervening-if 'if it was attacking or blocking alone' on a dies-trigger is dropped (tr (#3379)
- fix(engine): Vexing Puzzlebox tap ability rolls d20 on the stack (#1011) (#3244)
- fix(parser): Relative clause 'that didn't attack or enter this turn' is dropped from the PutCounterA (#3377)
- feat(parser): migrate sacrificed-this-turn quantity to nom combinators (#3374)
- chore: refresh metagame feeds (#3375)
- feat(parser): parse {TK} ticket-counter symbols (N tickets) (#3335)
- fix(parser): route sorcery cycling lines to keyword extraction (#3373)
- feat(parser): recognize registry named tokens (Vibranium, Mutavault, …) (#3336)
- feat(parser): grant the chosen keyword (choose ... gain that ability) (#3347)
- fix(engine): block auto-pass when sacrifice-for-mana is available (#3372)
- feat(parser): parse 'one or more target creatures become ' (#3358)
- test(engine): add layered regression coverage for Good King Mog XII chapter IV (#3371)
- fix(parser): BecomeCopy duration ForAsLongAs binds the tapped-state condition to ability.source_id v (#3362)
- fix(parser): parse_keyword_from_oracle numeric-param normalizer splits on the first space, so a keyw (#3369)
- Fix Peregrine Drake untap prompt labeled as sacrifice (#3320) (#3365)
- fix(parser): route "its owner" life-change subject to owner not controller (#3368)
- Add Nexus of Fate extra-turn regression tests (#3323) (#3361)
- feat(engine): prevent damage + remove that many +1/+1 counters (#3344)
- fix(parser): Saga/GoadAll target drops FilterProp::HasChosenName after the 'choose a creature card n (#3367)
- Fix airbend cast permission granted to wrong player (#3322) (#3363)
- Add regression test for Volcanic Spite optional prompt (#3364)
- Fix Haunted One buffing ineligible creatures (#3324) (#3359)
- feat(engine): static permission to block shadow creatures (#3350)
- fix(parser): attack-trigger targets honor "defending player controls" controller scope (#3356)
- fix(parser): parse_escape_keyword parses only a single leading 'Exile N' clause and reads exile_coun (#3353)
- fix(client): preview card hover on touch-primary devices with a mouse (#3352)
- feat(parser): parse 'they gain ' multi-keyword grant (#3340)
- feat(parser): parse ' may have you draw a card' (#3348)
- feat(engine): convert Momir to Momir's Madness (snow basics, 20 life) (#3345)
- feat(parser): parse per-kind counter add-or-remove (#3341)
- chore(tauri): regenerate ACL schemas (#3342)
- Fix Song of the Dryads ability loss per CR 305.7 (#3337)
- fix(parser): route 'dealt damage this way can't be regenerated' riders (#3339)
- feat(engine): add Momir Basic format (#3338)
- fix(engine): bind damage-trigger companion player slot to the damaged player (#3331)
- fix(parser): Suffer the Past exiles from target player's graveyard (#1005) (#3329)
- Add regression tests for Korvold sacrifice triggers (#1008). (#3241)
- fix(parser): Per-opponent 'they' anaphor in 'each opponent ... the life they lost this turn' emits L (#3334)
- fix(ai): don't pay for self-protection on your own turn vs a standing board (#3332)
- feat(engine): “any player may” group-bargain / punisher pattern (#3243)
- fix(parser): RevealUntil filter collapses to Any (dropping 'a Time Lord creature card') when parsed (#3330)
- fix(parser): do not misread "into your graveyard" destination as origin (#3238)
- ci: gate MTGJSON download on file existence, not cache-hit (#3240)
- fix(parser): Effect-chain ' and ' split inside a villainous-choice branch collapses 'Destroy all X a (#3226)
- fix(engine): set source_controller in ReplacementDefinition literals (main hotfix) (#3239)
- feat(engine): add CoreType::Conspiracy + command-zone conspiracy runtime (CR 905 / 702.106) (#3231)
- fix(parser): Escape to the Wilds play-permission + extra land (#3232)
- fix(engine): Taii Wakeen #3203 coverage regression + global damage-replacement controller anchor (#3237)
- feat(engine): hexproof if it hasn’t dealt damage yet (#3228)
- fix(parser): Compound player+object damage parser (try_parse_compound_player_object_damage) fails on (#3229)
- fix(engine): type StaticMode::LinkedCollectionCounterPlayPermission (Evelyn coverage) (#3227)
- feat(engine): Archenemy schemes runtime — Scheme type, scheme deck, set-in-motion, abandon (CR 904/314/701.32/701.33) (#3222)
- Fix #1022: Savai Triome cycling draws from the battlefield (#3204)
- fix(parser): keep conditional “costs {N} less to activate” on activated abilities (#3224)
- feat: trigger on "a spell or ability an opponent controls causes you to discard this card" (#3116)
- fix(engine): Level Up doubles +1/+1 counters on attack (#1020) (#3214)
- fix(engine): fire Ring tempts you triggers after bearer choice (#1017) (#3218)
- fix(parser): Equipped-creature-attacking static resolves the wrong subject and condition: emits affe (#3220)
- fix(parser): Peregrin Took additional Food replacement (#1016) (#3219)
- fix(parser): 'first/each [type] spell you cast each turn has [keyword]' static (parse_spells_have_ke (#3212)
- fix(parser): route "enters under the control of an opponent" to the replacement parser (#3217)
- Fix Heraldic Banner chosen-color pump regression (#1019). (#3215)
v0.1.56
Downloads
| Platform | File |
|---|---|
| Windows | Phase_*_x64-setup.exe |
| macOS (Apple Silicon) | Phase_*_aarch64.dmg |
| Linux | Phase_*_amd64.AppImage or .deb |
macOS note: If you see "this app is damaged", open Terminal and run:
xattr -cr /Applications/Phase.app
Changes
- Add manifest dread choice integration coverage (#1018). (#3216)
- Fix/541 endurance graveyard bottom of library (#3211)
- Fix #1021: Recurring Nightmare returns itself to hand when activating (#3205)
- chore: refresh metagame feeds (#3210)
- fix(engine): constrained library search must allow fail-to-find (#2722) (#3198)
- test(client): gate handled WaitingFor variants on a real UI dispatch site (#3209)
- fix(engine): clear dangling pending-trigger cursor on concede (#3175) (#3207)
- fix(engine): freeze reflexive event count so up-to-that-many targets resolve (#3208)
- feat(client): flex-layout edit-mode polish — reorder, snap-to-home, alignment, mobile (#3206)
- Fix #1023: gate Oversold Cemetery on four creature cards in graveyard (#3202)
- Fix #1024: allow nine Nazgûl copies in Commander decks (#3201)
- Fix #2354: implement Mayhem and Green Goblin graveyard grant (#3178)
- Fix #1025: cast Expertise free spells during resolution (#3200)
- Fix/821 expropriate money vote (#3140)
- Fix #1200: implement Gonti, Night Minister triggered abilities (#3189)
- feat(client): flex layout edit mode — drag widgets, resize zones, scale, presets (#3199)
- fix(engine): declined optional trigger must not fire its reflexive (#3179) (#3197)
- fix(ui): render the Learn modal (CR 701.48a) (#3195)
- feat(ui): wire Assist overlays + WaitingFor UI-handler parity gate (#3196)
- fix(client): PairChoice is modal-resolved, drop its board-glow seed (#3194)
- fix(parser): bind "untaps it" anaphor to trigger subject, not ParentTarget (#3193)
- fix(ai): stop animating man-lands into useless tapped creatures (#3191)
- fix(parser): Villainous-choice / scoped-player ChooseOneOf construction in try_parse_choose_one_of_i (#3183)
- feat(ui): surface player conditions, ring benefits, mana availability & creature overflow (#3190)
- Fix Shelob spider-damage death trigger (fixes #1206) (#3184)
- Add regression tests for prepared spell cast timing and mana payment. (#3187)
- fix(engine): consume one-shot in-place cast grants when the spell leaves the stack (#3188)
- perf(ai-duel): parallelize suite across cores + isolated-target wrappers (#3186)
- feat(ai): only cast creature removal that can actually kill the target (#3185)
- Deck contribute workflow (#2511)
- fix(engine): equipment DamageDone triggers on combat damage (#2348) (#3176)
- feat(frontend): surface multi-card top-of-library reveals to all players (#2366, #2005) (#3182)
- test(engine): reveal-dig exposes looked-at cards to opponents during DigChoice (#2005) (#3181)
- test(engine): Fear of Missing Out delirium untap (#2355) (#3174)
- test(engine): Planar Birth mass basic-land graveyard return — tapped, owners' control (#1126) (#3180)
- test(engine): regression for Ulamog ETB counters from exiled MV (#3177)
- fix(parser): Sarkhan +1 legendary Dragon animation (#2362) (#3172)
- test(engine): Norin exiles on creature attack (#2357) (#3173)
- fix(parser): distribute trailing search-filter predicate across disjunctive type list (#2892) (#3171)
- fix(engine): resolve city's blessing race and Siege self-cast from exile (#2873, #2876) (#3170)
- fix(parser): Taigam exiles the cast spell (not itself) with time counters (#749) (#3169)
- fix(engine): play-from-exile permission is consultable from the graveyard for milled cards (#751) (#3168)
- fix(engine): replay deferred entry events on as-enters-choice resolution so ETB observers fire (#830) (#3167)
- feat(engine): is_mana_ability flag + #3162 Gemini follow-ups (#3164)
- fix(parser): Trailing 'for each ...' multiplier clause is not converted into a QuantityExpr on an ef (#3163)
- fix(parser): lower 'gains no life instead' to Prevent replacement (#743) (#3166)
- fix(engine): sacrifice triggers look back via LKI for ceased-to-exist tokens (#754) (#3165)
- refactor(client): frontend cleanup & optimization pass (#3162)
- fix(parser): Gonti-class look-and-exile-face-down exiles the dug card, not the source (#1146) (#3161)
- fix(parser): 3000-the tokens are goaded (#3158)
- fix(parser): mass return-to-battlefield preserves enter-with-counters as ChangeZoneAll (#656) (#3160)
- fix(parser): Dig 'reveal ... on top of your library, rest on bottom' kept-to-top destination (#2349) (#3155)
- fix(parser): Gideon Blackblade turn-conditional 'is a creature ... still a planeswalker' animation (#1155) (#3159)
- test(engine): regression for Station counter-gated static teardown (#1134) (#3157)
- fix(engine): scope 'If you do' tracked-set reset to producer riders so consumer anaphors stay chain-local (#2350) (#3156)
- fix(parser): scope 'creatures that died under your control' count to controller (#1129) (#3154)
- fix(engine): Bring to Light free-cast is resolution-only, not a lingering permission (#2880) (#3153)
- fix(parser): Lulu Stern Guardian stun targets attackers only (#3149)
- fix(parser): token Flying keyword before equal-to count (#3151)
- test(engine): add Obuun land animation regression (#3152)
- fix(engine): parse Wall of Mourning ETB as ExileTop (#3148)
- Fix Teferi loyalty loss when counter map is missing (#2862) (#3137)
- Add Baldin toughness damage static (#3147)
- fix(engine): Sevinne's Reclamation flashback self-copy (#2860) (#3145)
- fix(engine): pay sacrifice cost on modal activated abilities (#3146)
- Add Telepathy hand reveal static (#3144)
- Fix Professor Onyx magecraft on spell copy (#2866) (#3132)
- feat(engine): Planechase runtime — planes/phenomena, planar deck, planeswalk, chaos, planar die (#3126)
v0.1.55
Downloads
| Platform | File |
|---|---|
| Windows | Phase_*_x64-setup.exe |
| macOS (Apple Silicon) | Phase_*_aarch64.dmg |
| Linux | Phase_*_amd64.AppImage or .deb |
macOS note: If you see "this app is damaged", open Terminal and run:
xattr -cr /Applications/Phase.app
Changes
- fix(engine): Mechtitan token keeps haste + becomes all colors (#2343) (#3143)
- fix(parser): parse all-player static step skips (#3141)
- chore: refresh metagame feeds (#3142)
- fix(engine): keep sacrificed creatures out of exiled-this-way set (#2932) (#3124)
- fix(parser): resolve 'draw cards equal to the difference' in triggers (#3139)
- Fix aura attachment cleanup on commander zone changes (#2863) (#3136)
- fix(parser): rewrite 'copy of it' to TrackedSet after exile clause (#377) (#3131)
- Add regression test for Kaldra Compleat haste equipment grant. (#3133)
- feat(parser): consume "draft matters" draft-time text (#3129)
- fix(parser): count "cards your opponents have drawn this turn" as a scoped quantity (#3130)
- test(engine): regression test for #1558 — Myriad on copy creature (#3123)
- fix(engine): Bronzehide Lion no-target ReturnAsAura hang (#1332) (#3087)
- fix(engine): cast opponent-graveyard free-cast during resolution (#2884) (#3122)
- Fix Currency Converter creating tokens with no exiled card (issue #2871) (#3120)
- Allow enchantment adventure cards to cast their spell face (issue #2870) (#3121)
- Fix Dragon's Rage Channeler cast trigger timing on flashback (issue #2872) (#3119)
- fix(engine): resolve impossible Choose as no-op instead of wedging (#3040) (#3117)
- fix(engine): gate Caesar's reflexive choose-two on the optional sacrifice (#3118)
- fix(engine): exile from controller library on combat-damage ExileFrom TopUntil (#3106)
- feat: fire "when you spend this mana to cast [filter] spell" triggers (Orb of Dragonkind) (#3110)
- test(engine): Marchesa +1/+1 dies return regression (#1334) (#3094)
- fix(engine): gate Suppressor Skyguard’s prevent trigger on an unattacked opponent (#3112)
- fix(engine): apply Najeela untap + keyword grant with extra combat (#2898) (#3111)
- fix(parser): fix tracked-set scan shadowed by intermediate clause and add end-of-combat prefix (closes #2850, closes #3010) (#3113)
- fix(engine): return dying creatures as face-down Forest lands (#2923) (#3099)
- fix: implement Zack Fair activated ability (#1327) (#3082)
- fix(engine): track additional cost instances (#3114)
- Fix Agitator Ant end-step counters and scoped goad (fixes #2903) (#3085)
- Fix Master of Cruelties can only attack alone parsing (fixes #2910) (#3086)
- test(engine): Brain in a Jar charge-then-cast regression (#1333) (#3091)
- Fix Teferi's Protection mass phase-out targeting (fixes #2907) (#3092)
- fix(engine): model enlist as attack cost (#3108)
- feat: parse "spend mana only to cast X spell or activate an ability" (#3100)
- fix(engine): impose additional life cost on spells targeting Terror of the Peaks (#3105)
- Fix Blast-Furnace Hellkite Artifact offering and attacking-opponents static (fixes #2909) (#3095)
- feat: grant "all activated abilities of cards exiled with it" (Myr Welder, Territory Forge) (#3107)
- fix(engine): resolve Reality Shift chained manifest via parent-target referent (#3103)
- fix(engine): snapshot TriggeringSource object in delayed triggers at creation time (#3104)
- fix(engine): bind "for as long as it has a counter" to the recipient (#3084)
- Improve mobile battlefield zone overflow (#3102)
- fix(engine): bind 'deal damage to that player' to triggering drawer (#2893) (#3097)
- fix(engine): scope DamageReceived triggers by valid_card recipient filter (#3077)
- fix(parser): bind a token creator's "it gains/gets X" grant to the created token (#3098)
- fix(client): surface Impending alternative-cast option (#2859) (#3049)
- feat: support [−X] variable-loyalty planeswalker abilities (#3088)
- fix(ci): refresh tauri lock during nightly release (#3089)
- ship/Standardize AI measurement and policy gates (#3093)
- fix: Inti reflexive counter after interactive discard (#1328) (#3083)
v0.1.54
Downloads
| Platform | File |
|---|---|
| Windows | Phase_*_x64-setup.exe |
| macOS (Apple Silicon) | Phase_*_aarch64.dmg |
| Linux | Phase_*_amd64.AppImage or .deb |
macOS note: If you see "this app is damaged", open Terminal and run:
xattr -cr /Applications/Phase.app
Changes
- fix(engine): Tabernacle granted upkeep destroys on decline (#1326) (#3080)
- fix(engine): Winding Way reveal-and-partition routing (issue #2931) (#3061)
- fix(engine): apply +X/+X-where-X-is-power boost on trigger (#3044)
- fix(engine): stamp source_incarnation on warp delayed trigger (#539) (#3068)
- fix(client): handle all alternative-cast keywords in modal (#2939) (#3051)
- fix(engine): resolve mass put-all Dig deterministically (Muxus) (#3066)
- fix(engine): cap divided-damage targets by divisible pool (issue #2856) (#3054)
- fix: nexus of Fate shuffle-back replacement on stack resolution (#3048)
- fix(parser): parse untyped "for each counter on this [type]" as dynamic quantity (closes #2865) (#3072)
- fix(parser): parse damage-source-type intervening-if (#2867) (#3063)
- fix(engine): resolve venture and initiative dungeon triggers (#3069)
- fix(engine): pay as-enters MayCost discard cost for real (#2853) (#3067)
- fix(parser): graveyard zone + origin if for Prized Amalgam (issue #2861) (#3062)
- fix(engine): fire unblocked opponent-attack triggers after blockers (#3074)
- chore: refresh metagame feeds (#3071)
- fix(ci): refresh tauri lockfile
- fix(ci): lock Tauri app dependency resolution (#3081)
- fix(ci): pin tauri time dependency
- Fix trigger index routing for 'from anywhere to graveyard' triggers (#3050)
- fix(engine): resume mass return-to-battlefield after an Aura host choice (#3064)
- fix(parser): parse "no creatures attacked this turn" intervening-if (#3047)
- fix(engine): type-filter + single-use bound on cast-from-exile grant (#3056)
- fix(parser): handle zone-qualified card keyword grants (Six #536) (#3057)
- fix(parser): bind "where X is …" into a continuous grant’s dynamic P/T (#3058)
- fix(parser): scope self-recipient "~ would be dealt damage" prevention to self (Unbreathing Horde) (#3059)
- fix(engine): charge each repeated modal unless-pay instance (#2925) (#3060)
- fix(parser): bind "deals N damage to them" to a player-actor trigger subject (#3052)
- fix(parser): preserve "may" optionality for each-player discard (Mog, Moogle Warrior) (#3055)
- fix(parser): route subject-led mana to ScopedPlayer for Blinkmoth Urn (#3053)
- feat(engine): implement Meld keyword action runtime (CR 701.42 / CR 712.4) (#3023)
- feat(engine): mass "gain control of all" via GainControlAll (closes #2906) (#3020)
- fix(parser): gate first-{X}-spell cost reduction (#3011)
- fix(parser): hoist "if it's not a token" intervening-if and goad token anaphors (#3041)
- fix(engine): apply "each player's life total becomes N" to all players (Worldfire) (#3045)
- fix(parser): bind "deals N damage to them" to the upkeep player (#3046)
- fix(engine): gate Amareth reveal on shared card type (#3028)
- fix(engine): StaticCondition::WasCast for cast-gated continuous statics (closes #2919) (#3029)
- fix(engine): Future Sight library top reveal at runtime (closes #2918) (#3030)
- Fix Torment of Hailfire repeat resolution order (#2916) (#3033)
- feat(engine): implement the Cloak keyword action (CR 701.58a) (#3038)
- feat(engine): dynamic P/T for "unspent mana you have" (Omnath, closes #2887) (#3036)
- fix(parser): split compound statics with foreign keyword-grant subject; fix trailing-comma keyword drop (#3039)
- fix(engine): Torrential Gearhulk exile-on-resolve rider (closes #2937) (#3035)
- feat(engine): turn the exiled card face up (Imprint flip cards) (#3034)
- fix(engine): Alexios can't attack owner + upkeep GiveControl (closes #2915) (#3031)
- Fix Flurry target gate for Shiko and Narset, Unified (#2914) (#3032)
- fix(engine): synthesize runtime-granted keyword triggers from LKI on … (#2965)
- fix(engine): bind connive count to creatures-died-this-turn quantity (#3008)
- fix(engine): enforce any-other-target distinctness for Arc Trail (closes #2929) (#3027)
- fix(parser): existential opponent control activation restrictions (#3002)
- fix(engine): correct reveal-until CR annotations (#3025)
- fix(parser): attach multi-target spec for Trystan's Command return mode (closes #3004) (#3005)
- Fix Phyrexian Dreadnought ETB unless-sacrifice (#864) (#2843)
- fix(parser): parse Library of Leng discard-to-top replacement (#2998)
- Migrate reveal-until zone moves to pipeline (#3024)
- fix(parser): parse Astarion's modal "life they lost this turn" amount (closes #2927) (#3001)
- fix(parser): evaluate combat-damage-by-type intervening-if (issue #1347) (#3006)
- fix(parser): split dual-subject anthem statics (issue #1489) (#3007)
- fix(engine): seed saga lore counter on transformed DFC entry (#691) (#3013)
- fix(parser): accept "if you do, it becomes plotted" Plot grant (CR 702.168) (#2990)
- test(engine): regression tests for Resonating Lute hand-size gate (#689) (#3016)
- fix(engine): bestow-cast Detective's Phoenix from graveyard (#3014)
- fix(engine): apply no-target sibling grant to triggering object (#2378) (#3019)
- fix(engine): draw only when no copy was made (issue #1370) (#3018)
- fix(engine): add CanOnlyAttackAlone static mode and enforcement (closes #2910) (#2985)
- fix(engine): flush layers before sub-ability reads P/T (issue #2384) (#3015)
- test(engine): regression test for Mind into Matter artifact put (#688) (#3017)
- feat(ai): avoid casting spells into a Chalice of the Void (#3003)
- fix(engine): up-to-N target bounce honors 0-target opt-out (#3012)
- test(engine): re-freeze anaphoric allowlist at 166 (crumble/sly spy/solitude reclassified) (#3009)
- fix(parser): parse Deflecting Swat "choose new targets" as ChangeTargets (#2957)
- Fix targeting and controller assignment bugs (#2803)
- fix(parser): keep Krark win-flip copy+retarget in one clause (#2956)
- fix: ParentTarget GenericEffect binding for targeted pump/debuff abilities (#2999)
- fix(parser): parse exile X cards from graveyard additional cost (Harvest Pyre) (#2995)
- feat(engine): zone pipeline tranche 4 — route draws through move_object (CR 121.1) (#2996)
- fix(parser): split scoped "can't attack you" from compound static lines (closes #2874) (#2986)
- fix(parser): parse "for each player who has lost the game" quantity (Rampant Frogantua) (#2992)
- ship/zone t3 (#2989)
- chore: refresh metagame feeds (#2993)
- fix(parser): passive "spells with the chosen name can't be cast" (CR 101.2) (#2984)
- fix(parser): honor positive 'that's a/an X [or a/an Y]' subtype relative clause (CR 205.3) (#2987)
- fix(lobby): improve mobile format filter and server chip layout (#2972)
- fix(parser): parse conditional flat activated cost reductions (#2983)
- fix(parser): parse unconditional life-floor damage replacements (Ali from Cairo) (#2978)
- feat(engine): conditional activation cost reduction — "costs {N} less to activate if [condition]" (CR 601.2f) (#2980)
- fix(engine): read a left-battlefield target's power/toughness from last-known info (CR 608.2g) (#2979)
- Fix ParentTargetSlot resolution to use accumulated targets from chain (#2973)
- fix(parser): parse leading "N/M" as a power/toughness filter, not a subtype (CR 208.1) (#2975)
- fix(parser): recognize unconditional life-floor replacement (CR 614.1a) (#2974)
- fix(parser): parse opponent-control and cards-drawn CDA quantities (#2971)
- fix(parser+runtime): handle 'N fewer [type] counter' pattern in enter_with_counters (#2968)
- ship/zone phase e t2 (#2967)
- ship/cost payment phase5 (#2966)
- fix(parser): Breena attack trigger intervening-if (#2839)
- fix(engine): Mystic Remora cumulative upkeep after card rehydration (Fixes #581) (#2792)
- fix(engine): Gate lands offer fixed color and chosen color when tapped (#2964)
- fix(engine): keep keyword suffixes on final Or disjunct for comma-OR targets (#2961)
- fix(engine): derive merged Mutate permanent token-ness from the topmost component (CR 730.2d) (#2963)
- fix(engine): preserve cost-payment pause semantics (#2959)
- ship/zone phase e t1 (#2958)
- ship/cost payment phase4 delete paymentcost (#2960)
- feat(engine): promote Effect::Animate power/toughness to Option (CR 613.4b) (#2841)
- fix(engine): Rod of Absorption exile-tracking and free-cast (#2845)
- fix(frontend): auto-open graveyard viewer above prompts during zone casts (#2681)
- Add regression tests for issue #861 (Tree of Perdition, First Sliver) (#2844)
- fix(engine): flickering a merged Mutate permanent returns all components, not just the survivor (CR 730.3c) (#2848)
- Cost-payment unification Phase 3: route handle_unless_payment through the authority (#2955)
- fix(parser): parse "equal to the number of … destroyed this way" quantities (#2954)
- fix(engine): publish RevealTop cards for ChooseFromZone picks (#2953)
- fix(parser): recognize "that turn’s end step" delayed loss (Final Fortune family, CR 603.7a) (#2952)
- feat(deck-builder): enhance DeckBuilderToolbar with MenuSelect for format selection (#2950)
- fix(parser): share one target across compound "target opponent does A, B, and C" (CR 601.2c) (#2832)
- fix(engine): Pest token attack life gain from catalog (#2840)
- Cost-payment unification Phase 2: PaymentScope + route effects/pay.rs through the authority (#2951)
- feat(engine): enter under an opponent’s control on ETB (CR 110.2a) (#2945)
- fix(parser): keep all keywords when an animation has a 'still a land' rider (CR 613.1d) (#2948)
- feat(menu): integrate MenuSelect for format filtering in MyDecks (#2947)
- feat(parser): extend conjure-duplicate anaphors to that creature/spell/permanent (CR 707.2) (#2828)
- Zone pipeline: OQ#3 cast-link preservation + bucket-A closure + cost-payment authority extraction (#2946)
- fix(engine): Nadier's Nightblade triggers on creature tokens leaving (#2838)
- fix(deck-builder): replace Load deck select with MenuSelect (#2842)
- ...
v0.1.53
Downloads
| Platform | File |
|---|---|
| Windows | Phase_*_x64-setup.exe |
| macOS (Apple Silicon) | Phase_*_aarch64.dmg |
| Linux | Phase_*_amd64.AppImage or .deb |
macOS note: If you see "this app is damaged", open Terminal and run:
xattr -cr /Applications/Phase.app
Changes
- chore: refresh metagame feeds (#2810)
- ci: make coverage ratchet informational on push-to-main (#2806)
- ship/architecture opinionation (#2802)
- fix(engine): add 'becomes the target of a backup ability' trigger primitive (CR 702.165a) (#2796)
- style(client): enhance deck builder and modal components with thin scrollbar and layout adjustments (#2786)
- ci: guard scheduled/deploy workflows against fork execution (#2793)
- fix(engine): Aven Interrupter ETB exiles chosen stack spell, not itself (#2764)
- fix(parser): split Gathering Stone ETB/upkeep trigger and chosen-type gate (#1525) (#2769)
- fix(engine): decompose Case 'To solve' conditions via the single condition authority (CR 719.3a) (#2784)
- feat(server): self-host reachability — ngrok tunnel + shareable join link (#2783)
- fix(engine): scope 'is renowned' condition to event subject vs source (CR 702.112) (#2782)
- Fix Serpent's Soul-Jar exile and cast-from-exile (fixes #1524) (#2772)
- Fix Arabella attack trigger dealing 0 damage (fixes #1499) (#2771)
- style(client): add thin scrollbar styling for improved UI experience (#2779)
- refactor(ui): introduce shared SelectField component for consistent dropdown styling (#2776)
- fix(engine): parse clone-of-you-control replacements without zone phrase (#2775)
- Stop AI wasting Alchemist's Refuge flash activations (fixes #1528) (#2773)
- fix(parser): route 'that/the 's controller gains life' to ParentTargetController (#2741)
- docs(pr-handler): add cooperative PR assignment lock (#2781)
- fix(engine): add object incarnation epoch so blinked self-referential triggers don't hit the new object (CR 400.7) (#2780)
- Fix White Sun's Twilight: token-grant routing + "destroy all other creatures" spares self-created tokens (#2739)
- fix(client): resolve mobile overflow in online lobby join controls (#2766)
- fix(engine): scope exploit triggers by subject filter + LKI self-exploit look-back (#2762)
- fix(parser): bind Emperor of Bones delayed sacrifice to returned creature (#1515) (#2770)
- fix(engine): scan command zone for CastFromHandFree emblem sources (#2768)
- fix(parser): bind Harvest Season X to tapped creature count (#1526) (#2767)
- fix(engine): apply self-spell cost reductions from graveyard (#2765)
- fix(parser): extend pronoun becomes-type static to gendered pronouns and fixed P/T (#2363) (#2759)
- fix(engine): enforce can-block-only-flying BlockRestriction (#2364) (#2756)
- docs(pr-handler): cut GitHub core rate-limit use; harden comment-resolution gate (#2763)
- Fix Obsessive Pursuit sacrificed-this-turn trigger (#879) (#2745)
- fix(engine): Delver transform gate and no-op second transform (#2754)
- fix(engine): grant nested-quoted abilities from emblems (Koth of the Hammer) (#2761)
- feat(engine): parse Prototype's alternative power/toughness from Oracle text (#2760)
- fix(parser): parse Slime Against Humanity Ooze/named card count for X (#2752)
- fix(engine): scan tracked-set member zone in ChangeZoneAll (#2753)
- feat(engine): thread non-mana activation costs through Embalm/Eternalize (#2758)
- fix(client): restore opponent HUD visibility in 1v1 games (#2757)
- fix(engine): re-apply aura layers after phasing in (#2751)
- feat(engine): reconfigure Equipment stops being a creature while attached (#2755)
- fix(engine): seed back-face loyalty counters when permanent enters transformed (CR 306.5b + CR 712.14a) (#2740)
- feat(engine): model the saddled designation as gated state (OTJ Mounts) (#2750)
- Fix trigger parser compound and afflict (#2747)
- Fix Final Parting hand/graveyard search split (#1302) (#2731)
- fix(mana): auto-tap colorless multi-mana sources (Sol Ring) for generic costs (#2749)
- Fix Luminarch Aspirant begin-combat trigger with multiple copies (#860) (#2744)
- fix: map until end of next turn duration correctly (#2743)
- fix(parser): typed QuantityRef::VoteCount for vote tallies (#1446) (#2738)
- docs: add large-refactor PR value gate (#2748)
- fix: impulse play-from-exile routing lands through cast path (#2732)
- feat(engine): gate enters-this-way riders on cast-variant-paid (#2746)
- Fix Thalisse token count for tokens created this turn (#1305) (#2730)
- Keyword backlog: sacrifice-replacement, toxic/infect poison routing, craft material links (#2735)
- fix(parser): bind "that player" damage to the chosen permanent's controller (#1670) (#2729)
- Fix Pest token battlefield grouping (#1968) (#2694)
- fix: Paradigm copies dropping sibling spell abilities (#2728)
v0.1.52
Downloads
| Platform | File |
|---|---|
| Windows | Phase_*_x64-setup.exe |
| macOS (Apple Silicon) | Phase_*_aarch64.dmg |
| Linux | Phase_*_amd64.AppImage or .deb |
macOS note: If you see "this app is damaged", open Terminal and run:
xattr -cr /Applications/Phase.app
Changes
- chore: refresh metagame feeds (#2742)
- fix(engine): awaken keyword filter, Training trigger install, fabricate source-gone tests (#2737)
- feat(engine): wire granted-keyword seams for fabricate/blitz/riot/encore (#2736)
- feat(emblem): display-only source provenance for emblems (CR 114) (#2734)
- feat(client): two-column board layout with command-zone dock (#2733)
- refactor(engine): replace raw bool fields with typed enums in engine … (#2713)
- ship/planeswalker loyalty and gy art (#2726)
- Keyword backlog: X-cost cap perf, escape floor, split-search, each-of-N parse (#2727)
- Add regression test for prepared spell SpellCast triggers (#2725)
- Regression: Joel, Resolute Survivor token dies trigger (#1961) (#2696)
- Regression: combat damage under pass-to-end (#1969) (#2697)
- Fix Unstoppable Plan end-step untap when phase entry is deferred (#2724)
- Regression: Lotleth Troll creature discard filter (#1963) (#2695)
- Fix Thespian's Stage losing copy ability after copying land (#2723)
- Fix Banner of Kinship fellowship counters and +1/+1s (#2719)
- Fix TriggeringPlayer for combat damage to player events (#2718)
- fix(engine): conditionally apply Not of This World's {7} cost reduction (CR 115.9b) (#2715)
- fix: lifecraft Engine causing Vehicles to crew each other. (#2711)
- refactor(engine): extract shared condition-evaluation helpers into ga… (#2706)
- Fix/parser optional as though permission grants 2274 (#2703)
- fix(engine): flush layers before combat damage to use evaluated power (CR 510.1a) (#2702)
- fix(engine): expose runtime-granted typecycling (#2701)
- feat(engine): implement Alchemy intensity state and Intensify mutation (#2699)
- Fix Eladamri hand reveal RevealChoice (#1970) (#2692)
- fix(engine): support top-library exile cumulative upkeep (#2691)
- Fix Marath variable X counter removal, verify Homeward Path ownership… (#2683)
- Fix Nita, Forum Conciliator spell you don't own trigger filter (#2720)
- Fix Electrodominance hand cast selection (Fixes #1313) (#2721)
- Fix/parser swallow clauses (#2687)
- fix(engine): leaves-battlefield counter look-back uses LKI (#2685)
- fix(client): single-source commander-column visibility; keep emblems on-screen (#2717)
- fix(client): hide empty commander column; emblem compact-height polish (#2716)
- fix(client): emblem art-crop tiles, non-wrapping support planeswalkers, unclipped commander damage (#2714)
- feat(engine): Alchemy spellbook draft runtime (#2680)
- fix(engine): carry token art routing through copy-of-token (CR 111.1 / 707.2) (#2708)
- fix(client): stop leaking opponent library cards in the reveal-aware viewer (#2707)
- fix: manual +1/+1 counter addition in debug menu (#2678)
- feat(client): reveal-aware library viewer with hover preview and play-from-top (#2704)
v0.1.51
Downloads
| Platform | File |
|---|---|
| Windows | Phase_*_x64-setup.exe |
| macOS (Apple Silicon) | Phase_*_aarch64.dmg |
| Linux | Phase_*_amd64.AppImage or .deb |
macOS note: If you see "this app is damaged", open Terminal and run:
xattr -cr /Applications/Phase.app
Changes
- feat(parser): parse excess noncombat damage triggers and compound base P/T continuations (#2677)
- feat(engine): interactive free-cast window for Invoke Calamity (#2676)
- fix Omnath conditional triggers and Obuun animation (#2675)
- Fix/parser enchant exile dig bugs (#2671)
- chore: refresh metagame feeds (#2693)
- feat(engine): implement Epic keyword runtime — rest-of-game cast lock and recurring upkeep spell-copy (CR 702.50) (#2670)
- Add Enduring Tenacity dies-to-enchantment regression (#1971) (#2669)
- Fix Rise of the Dark Realms mass graveyard reanimation (#1973) (#2668)
- fix(ai): emit legal mixed-target attacks under goad/must-attack (CR 508.1d) (#2673)
- feat(client): replays, content i18n, spectator dashboard, 2HG UI (#2247)
- fix(engine): scope Dromoka's Command prevention to chosen spell; stop modal-sibling fusion (#2684)
- fix(parser): add artifact token subtypes to enchant target leg parser (CR 702.5a) (#2667)
- test(engine): regression for modal DFC commander cast from command zone (#1985). (#2665)
- fix(engine): Bucknard's Everfull Purse treasure + control transfer (#1987) (#2664)
- Implement bands with other combat runtime (#2663)
- fix(parser): split "and can't attack or block" into CantAttackOrBlock static (CR 508.1a / 509.1b) (#2660)
- feat(parser): alternative keyword costs — cycling/crew/collect-eviden… (#2659)
- docs(pipeline): add author-side gates from contribution retrospective (#2672)
- Fix Planar Genesis dig and Broken Bond land drop (#2405) (#2657)
- Draft Mana Curve Fix (#2556)
- Fix Sin Spira exile-to-copy tracked set (#2403) (#2654)
- Fix Chaos Warp owner library reveal (#2406) (#2656)
- Fix Doubling Chant per-creature search loop (#2400) (#2658)
- Fix Hazel copy-of-token resolution (#2402) (#2653)
- Fix Mobilize sacrifice at next end step (#2404) (#2652)
- Fix Anti-Venom prevention scoping (#2401) (#2651)
- Fix Daretti loyalty reset on rehydration (#2407) (#2650)
- feat(engine): implement Ripple keyword runtime (CR 702.60) (#2646)
- fix(engine): exclude phased-out lands from domain count (CR 702.26b) (#2649)
- feat(parser): bind self-spell dynamic cost reduction 'where X is ' (CR 107.3) (#2647)
- Fix Scroll Rack exile/draw/reorder chain (#2411) (#2642)
- fix(keyword): Devour respects simultaneous co-entry exclusion (CR 702.82 / 614.13a) (#2661)
- Fix Kenessos multi-subtype library reveal (#2409) (#2641)
- feat(engine): implement Ripple keyword runtime (CR 702.60) (#2640)
- Fix Desynchronization nonhistoric filter (#2410) (#2637)
- feat(engine): implement Devoid keyword runtime — colorless in all zones (CR 702.114) (#2634)
- Fix Mishra's Bauble opponent library peek display (#2416) (#2631)
- Fix Hada Spy Patrol Shroud at level 0 (#2412) (#2636)
- feat(keyword): implement Transfigure (CR 702.71) (#2638)
- Fix Semblance Anvil imprint type cost reduction (#2414) (#2630)
- Fix Timber Paladin max-level static without Auras (#2418) (#2629)
- feat(engine): implement Delve keyword runtime (CR 702.66) (#2627)
- fix(keyword): cumulative upkeep with non-mana Discard cost (CR 702.24) (#2635)
- Fix Vesuva copy identity persisting in graveyard (#2413) (#2628)
- feat(engine): implement Spectacle keyword runtime (CR 702.137) (#2625)
- feat(engine): implement Assist keyword runtime (CR 702.132) (#2624)
- Fix legend rule clobbering targeted ETB trigger construction (#2420). (#2623)
- Fix Mox Amber color filter among controlled legendaries (#2421) (#2621)
- feat(p2p): raise online multiplayer cap from 4 to 6 players (#2632)
- fix(engine): apply cost increases before reductions so the {0} floor is aggregate (CR 601.2f) (#2610)
- fix(engine): enforce CR 111.8 — a token that left the battlefield can't return (#2620)
- Add Solemnity (#2618)
- fix(engine): day/night transition keys on the active player's spells (CR 502.2) (#2616)
- feat(engine): implement Fuse keyword runtime — cast both halves of sp… (#2611)
- feat(engine): Splice onto Arcane runtime (CR 702.47) (#2613)
- fix(engine): label optional replacement branches by outcome, not rules text (CR 702.136a) (#2581)
- Fix Demanding Dragon ETB unless-sacrifice prompt (#2422) (#2603)
- feat(keyword): implement Frenzy (CR 702.68) (#2614)
- Exclude phased-out permanents from control conditions (CR 702.26b) (#2609)
- fix(engine): keyword counters can't grant a denied keyword (CR 113.11) (#2606)
v0.1.50
Downloads
| Platform | File |
|---|---|
| Windows | Phase_*_x64-setup.exe |
| macOS (Apple Silicon) | Phase_*_aarch64.dmg |
| Linux | Phase_*_amd64.AppImage or .deb |
macOS note: If you see "this app is damaged", open Terminal and run:
xattr -cr /Applications/Phase.app
Changes
- fix(keyword): support granted Conspire (CR 702.78) (#2607)
- Fix #2423: Deadly Brew return rider after planeswalker sacrifice; AI mandatory sacrifice (#2602)
- Fix Goryo's Vengeance: returned creature gains haste and is exiled at next end step (#2424) (#2600)
- fix(casting): cast Overload spells with no legal printed target (CR 702.96) (#2601)
- Fix Fable chapter III returning as Saga with lore counter instead of transforming (#2425) (#2598)
- chore: refresh metagame feeds (#2599)
- fix(keyword): implement Echo non-mana costs (CR 702.30) (#2597)
- fix(engine): compute excess damage to planeswalkers and battles (CR 120.10) (#2587)
- Exclude phased-out permanents from control conditions (CR 702.26b) (#2596)
- fix(engine): route counter-doubling through the replacement pipeline (CR 614.1) (#2594)
- fix(synthesis): strip level-gated keywords from base keyword list (CR 711) (#2592)
- fix(engine): exclude phased-out permanents from devotion (CR 702.26b) (#2590)
- Implement Time Travel keyword action (CR 701.56) (#2588)
- Implement Surge keyword (CR 702.117) (#2582)
- fix(engine): fire bare "becomes blocked" triggers once per combat (CR 509.3c) (#2576)
- fix(parser): preserve sibling clauses under leading 'for as long as' host-lifetime duration (Opportunistic Dragon, CR 611.2b) (#2585)
- fix(engine): Aura Graft attaches only to hosts the moved aura can enchant (CR 702.5a) (#2583)
- fix(ai): maximize block_is_futile absorption over all chump counts (#2571)
- fix(parser): parse Offering keyword line ' offering' (CR 702.48a) (#2580)
- fix(PR-2573): await trailing cloud sync (#2579)
- fix(PR-2572): preserve named search disjunction members (#2577)
- fix(parser): Affinity for card types and type combinations (CR 205.2) (#2574)
- fix(cloud-sync): address Gemini review on egress PR (#2573)
- fix(parser): front-gate comma-series search disjunctions (CR 701.23a) (#2572)
- Implement Read Ahead keyword (CR 702.155) (#2567)
- feat(engine): Fortify keyword runtime — synthesize attach-to-land activated ability (CR 702.67a) (#2568)
- fix(ai): reserve largest-toughness blockers for trample in block_is_futile (CR 510.1c) (#2564)
- Implement Forecast keyword (CR 702.57) (#2563)
- feat(parser): grant scavenge/encore to graveyard cards (CR 702.97 / 702.141) (#2560)
- perf(cloud-sync): cut Supabase egress with revision-check pull + realtime projection table (#2565)
- Implement Forage keyword action (CR 701.61) (#2559)
- fix(parser): parse controller same-name multi-zone extraction (CR 701.23/701.24) (#2554)
- Implement Amplify keyword (CR 702.38) (#2551)
- fix(engine): break Speed max-speed static-condition infinite recursion (#2553)
- fix(parser): treat 'a X, a Y, or a Z card' search as single-card disjunction (#2552)
- feat(parser): filtered "during any turn you attacked with " condition (CR 508.1a) (#2548)
- Implement Dredge keyword (CR 702.52) (#2547)
- fix(parser): CastCopyOfCard recognized as internally optional in swal… (#2543)
- fix(parser): parse "Any player may activate this ability but only " (CR 602.2/602.5) (#2542)
- Implement Compleated keyword (CR 702.150) (#2540)
- fix(parser): parse variable (X) count in "create X tokens that are copies of …" (CR 707.2) (#2537)
- Implement Enlist keyword (CR 702.154) (#2535)
- feat(parser): recognize Teferi, Time Raveler's flash-grant as represented (fix false Optional_YouMay swallow) (#2538)
- feat(engine): Haunt keyword runtime — exile-haunting + payoff from exile (#2533)
- feat(engine): crew/saddle/station power-contribution modifiers (CR 702.122c) (#2531)
- Implement Undaunted keyword (CR 702.125) (#2528)
- feat(engine): Hideaway keyword runtime — ETB look-and-exile-face-down (#2526)
- Implement Prowl keyword (CR 702.76a) (#2524)
- fix(parser): split static "… and can’t be the target of …" so the targeting restriction isn’t dropped (CR 702.18a/702.11a) (#2522)
- feat(engine): Mayhem keyword (#2354) + self-referential damage-prevention scoping (Anti-Venom #2401) (#2520)
- Fix passive reveal-until parsing (#2519)