Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevention rework (tags, and maybe some others) #7973

Merged
merged 39 commits into from
Mar 4, 2025

Conversation

NBKelly
Copy link
Collaborator

@NBKelly NBKelly commented Feb 24, 2025

Here's my draft of a reworked prevention/interrupt system, starting with just the tag cards for now and then I'll add some of the other systems later.

These all being:

  • tags
  • cards being trashed
  • damage
  • jacking out
  • the run ending
  • encounter-abilities
  • bad publicity
  • expose

I'm leaving the trace/subroutine ones out because I don't think they're work touching (they hit exactly two cards, tyr's hand and disrupter, and both of them work well enough for now. I might change my mind later).

Then we can forget that the prevent-type prompts exist in our code, and no longer need to design things around them.

There's a video in slack showing how it works, I think it's pretty slick, and it avoids having our weird fake checkpoint thing.

This should deal with the following issues (once done):

And I guess if move ever gets reworked, then we have a basis for doing replacement abilities like nanuq

Some notes:

  • You can actually pass prevention back and forth until both players pass (like a regular paid ability window) - currently we don't do that, and it's only relevant for damage (prana/tori hanzo). This will allow us to do that when I'm done.

A few extra things I hit:

  • You can expose multiple cards at a time simultaneously (satellite uplink, that TD card) - so I rewrote expose to do that. You can also pass through a card, and it says you used that card to expose the card, and I'm going to de-clutter a few of the cards that use expose using that.
  • I added a system for deferring events (basically renaming them), so you could register ':until-next-runner-turn-begins' while the runner turn is beginning, and it will last until then. I'll apply this to klevetnik later. I fixed klevetnik 🎉. Basically, it's just avoiding the case where we need special handlers for events that make events that make events.
  • Cannot-jack-out has gone from a flag to a floating ability/effect, so that's one more flag gone from the game
  • I fixed the dirty hack on Banner
  • Zamba now uses an autoresolve, and can account for multiple cards being revealed at once (should be set to :always by default if the cost change pr is merged)
  • You can specify a :maximum key for :x-credits costs now, which is the maximum amount you can spend. It isn't really compatible with stealth, but it is what it is. This is for things like recon drone, where you pay up to X to prevent exactly X damage - so we can cap credits spent at X for similar effects now
  • Net shield is actually enforced now. So is prana condenser, and tori hanzo just works too
  • Cards that let you prevent any amount of something now actually let you do so
  • Ramujan Reliant BMI was apparently implemented wrong for the last 10 years... the trashing from the stack isn't a cost 😂
  • Likewise, noble path would prevent damage before you initiated the run, and now only works during the run, just like Damon intended.
  • I made liza's ability simultaneous (kind of unrelated to everything else, just got a request while I was working on this)
  • I redid Marilyn campaign as an interrupt (same timing as trash prevent), where it just changes the trash destination, so it should work with regenisis now (I'll need to write a test for this though, and multiple marilyns only involve one shuffle, which doesn't matter for now but maybe something super cursed will make it matter later) - I added a unit test for this, and it just works 💯
  • For trash prevention, I did something neat for the prompt:
    • if there's five or less cards, the prompt will list the cards
    • If there's more, you're probably getting nuked by an all-seeing I or something, so it just says the number of cards (so it doesn't stretch off the screen)
    • If there's exactly one card on the trash list, the ability will automatically target that card
    • Otherwise you pick the card from a prompt
    • Added an optional second argument to enumerate-str, which is the terminal seperator to be used: default is and, but if you want something like 'x, y OR z', you can do (enumerate-str [x y z] "or")

@NBKelly NBKelly changed the title Prevention rework (tags) Prevention rework (tags, and maybe some others) Feb 24, 2025
@NBKelly NBKelly marked this pull request as ready for review February 27, 2025 01:21
@NBKelly
Copy link
Collaborator Author

NBKelly commented Feb 27, 2025

Holy moly, it's actually done (I think)

@NBKelly
Copy link
Collaborator Author

NBKelly commented Feb 28, 2025

I updated this a little as per discussions with Jamie.

The current plan is that all damage manipulation is being moved to interrupts on the same timing, but we're keeping specifically the cleaners and brainchips on the pre-damage interrupt so we can keep from needing the runner to anticipate negative damage values.

It's currently good to go again :)

@NoahTheDuke
Copy link
Collaborator

NoahTheDuke commented Mar 3, 2025

This is a monumental amount of work. Thank you for it.

A couple broad notes/thoughts (instead of doing them inline in the diffs):

  • The prevention system is very robust, but it sits in an odd spot where it straddles conditional abilities (:type :event) and paid abilities (:type :ability). In doing so, it's not exactly mapping to either existing api (which keys/values are expected), even in the :ability section. If this is the way we're going to go, can you document the expected keys and kinds of this new api?
  • Costs have to be hardcoded in the labels (:label "[trash]: Zaibatsu Loyalty"). I think this should be automated (build the label from the :ability cost and the card name), especially if we go forward with [RFC] Use maps instead of strings for messages #7971.
  • Likewise, the has-trash-icon? system merely checks :abilities but can/should check the prevention abilities as well. This means we don't need to put :trash-icon true on every preventative card def.
  • Expose's args can take :card which I believe is the source of the ability. Can this be moved to the eid? (Should it? I think so but I'm willing to hear your thoughts.)
  • You write :req (req (and ... (not (:unpreventable context)) (pos? (:remaining context)))) a number of times. Maybe this could be a helper.
  • Why is :damage repeated in (prevent-damage state side eid :damage 1)? Can it be removed?
  • (keep identity (map #(...))) is just (keep #(...)).

@NBKelly
Copy link
Collaborator Author

NBKelly commented Mar 3, 2025

Hmm. For the costs/labels one, I'm (mostly) only putting the costs in when the cards can do multiple different things (ie for zaibatsu loyalty, or to help with clarity for feedback filter).
The damage one is a bit awkward because there's a pre-damage step, and then a damage step, but I think I can refactor those to scry the prevent state and select the key as part of the function rather than needing to put it in every interaction.

I'll run through the rest of those after work 💯

@NBKelly
Copy link
Collaborator Author

NBKelly commented Mar 3, 2025

I future-proofed the has-trash-icon for access abilities (you'll see why in a few months 😂)

@NoahTheDuke
Copy link
Collaborator

i can't get over how good this is lol. i did many PRs that felt this big and it's very cool to be on the other side. can't wait to see what our players think

Copy link
Collaborator

@NoahTheDuke NoahTheDuke left a comment

Choose a reason for hiding this comment

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

merge when you think it's good!

@NBKelly NBKelly merged commit 8334ed4 into mtgred:master Mar 4, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment