forge icon indicating copy to clipboard operation
forge copied to clipboard

Volatile Stormdrake bug - opponent doesn't pay energy counters but doesn't sacrifice creature.

Open Alkaraba opened this issue 1 year ago • 6 comments

Volatile Stormdrake enters, targets 5 MV creature (Marneus Calgar), player gets 4 energy counters, player doesn't pay any, creature isn't sacrificed. No object on board visible that would prevent the sacrifice effect.

Log image

Boardstate image

Forge updated latest version.

Alkaraba avatar Oct 23 '24 19:10 Alkaraba

Hmm, a pretty strange issue, I might need some help on this one... So far, I debugged it as far as SacrificeAllAi decision goes, that routes through the chkAIDrawback path and always returns "true", so the AI confirms the fact that it will agree to play that part. However, the SacrificeAllEffect#resolve method never fires for some reason... I'm not sure if it's the issue with the "unless cost" code path in the AI somewhere, or with something else, and sadly, can't quite figure out how to debug this properly :(

Agetian avatar Oct 24 '24 17:10 Agetian

Alright, so this might be a deeper issue in the code that parses Unless cost parts. This has to do with the fact that the Unless cost which is formatted as PayEnergy < N > or PayEnergy < X > or something else like that, where N and X usually resolve to Count$ChosenNumber, but sometimes to something else (e.g. Volatile Stormdrake uses TargetedManaCost), never get parsed by the AI to a specific value. I tried hooking up some basic code to do the parsing via AbilityUtils.calculate into AiCostDecision where it decides to pay Energy, but that doesn't seem to work, e.g. for Volatile Stormdrake it doesn't work because the ability doesn't have set targets while inside this method (not sure why, I tried looking for targets in the parent ability but there is none). The "cheating" part is actually due to the fact that the AI proceeds with "PayEnergy: 0" when it can't figure out how much it needs to pay, so the cost is considered "paid" by the AI (when it pays 0), from hence the effect that the card isn't sacrificed. It's easy enough to make it correctly "not pay" the cost at all, but I'm not sure how to make it choose to pay the cost when it can. This is also relevant for cards such as Aether Spike (which the AI has no idea how to play at all) and most likely other cards with PayEnergy that has PayEnergy < N > or PayEnergy < X > and resolves to something complex enough. This will probably need custom AI logic on a case-by-case basis. I'll most likely patch the "cheaty" part for now, not sure what to do about the other cards tbh. Maybe marking them as AI-unplayable would be a good idea until we can come up with a good enough idea for how to make the AI work for them?

Agetian avatar Oct 25 '24 06:10 Agetian

The AI will do the same kind of cheating with Galvanic Discharge, for instance. It'll target the card and pay 0 energy (the same way as above), killing the targeted card (since it marks the cost as paid despite paying 0).

Agetian avatar Oct 25 '24 06:10 Agetian

Any suggestions, @Hanmac @tool4ever ?

Agetian avatar Oct 25 '24 06:10 Agetian

@Agetian I will try to look at it over the weekend

I need to refactor #1119 anyway

Hanmac avatar Oct 25 '24 07:10 Hanmac

Alrighty, thanks a lot for help!

Agetian avatar Oct 25 '24 08:10 Agetian

This issue has not been updated in a while and has now been marked as stale. Stale messages will be auto closed.

github-actions[bot] avatar Nov 24 '24 09:11 github-actions[bot]