Replacement Effects
Post MTG Forge Related Programming Questions Here
Moderators: timmermac, Agetian, friarsol, Blacksmith, KrazyTheFox, CCGHQ Admins
21 posts
• Page 1 of 2 • 1, 2
Replacement Effects
by Hellfish » 28 Dec 2011, 21:57
Heyo! Hope y'all had a merry christmas.I myself was blessed with a glut of work after spending all of winter unemployed, incidentally the reason I kind of disappeared for a while.
Now, getting back to the *important* business of Forge
, I will check up on the cloner problem soon, but first I wanted to submit something I've been tinkering with for scrutiny: Scriptable Replacement Effects. I'm mostly looking for feedback on rules accuracy for the time being but the issue of AI is also very important, seeing as there not being any AI is the current issue.I'm not even sure how the AI would evaluate the effects.
The structure is very similar to Triggers (So there's currently a little code duplication), there is a Handler class, a base class for Replacement effects and subclasses for each event that can be replaced. Before each replacable event elsewhere in Forge, we fill in a runParams HashMap, just as for triggers, and pass that to ReplacementHandler.run so it can determine which replacement effects, if any, apply and let the correct player(s) choose between multiples. If ReplacementHandler.run returns true, the event that was about to happen is aborted, as it has been replaced.
I've got it working for card draws currently, though other events are possible to add with a bit of copy pasting. Current future plans include more replacable events, of course, non-static replacement effects(Until EOT, if you would X, do Y instead.) and an equivalent to Triggered-variables for use in things like altered amounts (Akki Lavarunner,Boon Reflection) or maybe even redirection effects (Using AF_DealDamage's Source parameter,maybe?)
Examples: (Note, the Handler currently assumes that the replacement effect only functions on the battlefield)
Now, getting back to the *important* business of Forge
The structure is very similar to Triggers (So there's currently a little code duplication), there is a Handler class, a base class for Replacement effects and subclasses for each event that can be replaced. Before each replacable event elsewhere in Forge, we fill in a runParams HashMap, just as for triggers, and pass that to ReplacementHandler.run so it can determine which replacement effects, if any, apply and let the correct player(s) choose between multiples. If ReplacementHandler.run returns true, the event that was about to happen is aborted, as it has been replaced.
I've got it working for card draws currently, though other events are possible to add with a bit of copy pasting. Current future plans include more replacable events, of course, non-static replacement effects(Until EOT, if you would X, do Y instead.) and an equivalent to Triggered-variables for use in things like altered amounts (Akki Lavarunner,Boon Reflection) or maybe even redirection effects (Using AF_DealDamage's Source parameter,maybe?)
Examples: (Note, the Handler currently assumes that the replacement effect only functions on the battlefield)
- Code: Select all
Name:Laboratory Maniac
ManaCost:2 U
Types:Creature Human Wizard
Text:no text
PT:2/2
R:Event$ Draw | ValidPlayer$ You | IsPresent$ Card.YouOwn | PresentZone$ Library | PresentCompare$ EQ0 | ReplaceWith$ Win | Description$ If you would draw a card while your library has no cards in it, you win the game instead.
SVar:Win:AB$WinsGame | Cost$ 0 | Defined$ You
End
Name:Obstinate Familiar
ManaCost:R
Types:Creature Human Wizard
Text:no text
PT:1/1
R:Event$ Draw | ValidPlayer$ You | Optional$ True | Prevent$ True | Description$ If you would draw a card, you may skip that draw instead.
End
Name:Thought Reflection
ManaCost:4 U U U
Types:Enchantment
Text:no text
R:Event$ Draw | ValidPlayer$ You | ReplaceWith$ DrawTwo | Description$ If you would draw a card, draw two cards instead.
SVar:DrawTwo:AB$Draw | Cost$ 0 | Defined$ You | NumCards$ 2
End
- Attachments
-
RepEff 1.txt- (31.18 KiB) Downloaded 223 times
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-

Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Replacement Effects
by friarsol » 29 Dec 2011, 03:09
Oooooh Scriptable Replacement effects? Count me in.
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: Replacement Effects
by Sloth » 29 Dec 2011, 17:43
The biggest rules problems with replacement effects are created when the effects could create loops. We have to make sure all replacement effects can be applied only once. For example Thought Reflection does not replace its own draws, but a second Thought Reflection should (So two Thought Reflections would let you draw four cards per normal draw).
Effects that could be replaced have to "remember" what replacements they already went through.
Effects that could be replaced have to "remember" what replacements they already went through.
-

Sloth - Programmer
- Posts: 3498
- Joined: 23 Jun 2009, 19:40
- Has thanked: 125 times
- Been thanked: 507 times
Re: Replacement Effects
by Hellfish » 29 Dec 2011, 23:43
I was gonna say that I did take that into account, but there appears to be a glitch in that regard..
What it's doing is marking the ReplacementEffects as "Has Run" when they are selected to replace an event and only clear those marks at the appropriate, later, time. I currently clear the marks in checkStateEffects and I think that's part of the problem..
What it's doing is marking the ReplacementEffects as "Has Run" when they are selected to replace an event and only clear those marks at the appropriate, later, time. I currently clear the marks in checkStateEffects and I think that's part of the problem..
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-

Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Replacement Effects
by Hellfish » 31 Dec 2011, 12:08
I'm implementing an improved system for interactions like double Tought Reflection that Sloth mentioned. It's still not right (Seems the second Thought Reflection only replaces the first draw of the first Thought Reflection) but I expect this is down to human error somewhere, because AFAICT it's theoretically sound.
- Spoilered because jesus flippin' christ | Open
- Terminology:
TR = Thought Reflection
RE object = The card's instance of the ReplacementEffect class.- The ordinary draw reaches Player.doDraw(), where ReplacementHandler.run() is called.
- run() let's the player choose which TR replacement to apply first, and pushes that RE object onto a stack, then runs the TR's replacement draw.
- The first draw of the first TR reaches Player.doDraw(), see point 1.
- run() see's that the first TR's RE object is on the stack and does not allow it to run. Instead it automatically pushes the second TR's RE object on the stack and runs it.
- The first draw of the second TR reaches player.doDraw(), see point 1.
- run() sees the second TR's RE object on the stack and does no replacement.The draw resolves as normal. Same thing with the second TR's second draw.
- Now,after having completed the second TR's replacement draw, the code returns to run() to finish the method for the second TR.Here, the second TR's RE object is popped off the stack.
- Now run() returns to the doDraw() of the first draw of the first TR, which will abort because it was replaced. The calling method will loop around and call doDraw() again (because it was a Draw 2-ability). Now we go back to point 3, except for the second draw of the first TR. Once that's done, continue to the next point.
- Now we are at the doDraw() for the original card draw, which aborts because ReplacementHandler.run() returned true.
- The ordinary draw reaches Player.doDraw(), where ReplacementHandler.run() is called.
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-

Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Replacement Effects
by Hellfish » 02 Jan 2012, 11:40
Welp, in one fell swoop, the problem was fixed and the extra stack mentioned in the spoiler was eliminated. Cool beans. Next up: replacing other events than draws and "Replaced-variables".
EDIT: New patch is for r12917.
EDIT: New patch is for r12917.
- Attachments
-
RepEff 2.txt- (32.23 KiB) Downloaded 214 times
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-

Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Replacement Effects
by moomarc » 02 Jan 2012, 20:43
I saw in the 1.2.1 thread that you3e done with damage replacement effects. Does that include redirecting damage as well, or is that a whole different ballgame? I can't wait to add Kor creatures from Stronghold! Would finally be able to build the first deck I built with paper magic (although it definitely won't be as effective since I've learnt the proper rules)
-Marc
-

moomarc - Pixel Commander
- Posts: 2091
- Joined: 04 Jun 2010, 15:22
- Location: Johannesburg, South Africa
- Has thanked: 371 times
- Been thanked: 372 times
Re: Replacement Effects
by Hellfish » 02 Jan 2012, 21:00
I guess that's a matter of wording. This system can handle "If damage would be dealt to CARDNAME, that damage is dealt to <whatever> instead." It *can't* handle things like "{cost}:The next # damage that would be dealt to CARDNAME this turn is dealt to target creature instead."
Fake edit: If you mean things like Lancer en-Kor; no, sorry.
Real edit: Committed, r12924.
Fake edit: If you mean things like Lancer en-Kor; no, sorry.
Real edit: Committed, r12924.
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-

Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Replacement Effects
by SoulStorm » 03 Jan 2012, 10:25
Posted this in the bugs thread, but it's probably more appropriate here Hellfish. Your Phytohydra conversion is having growing pains. My 1/1 Phytohydra attacked with Caltrops on the Battlefield and promptly died.
Must say though that I'm excited to have scriptable replacement effects in the game. Been looking forward to this for a long time. Many thanks!
Must say though that I'm excited to have scriptable replacement effects in the game. Been looking forward to this for a long time. Many thanks!
Re: Replacement Effects
by Hellfish » 03 Jan 2012, 10:36
Thank *you*SoulStorm wrote:Posted this in the bugs thread, but it's probably more appropriate here Hellfish. Your Phytohydra conversion is having growing pains. My 1/1 Phytohydra attacked with Caltrops on the Battlefield and promptly died.
Must say though that I'm excited to have scriptable replacement effects in the game. Been looking forward to this for a long time. Many thanks!
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-

Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Replacement Effects
by SoulStorm » 03 Jan 2012, 14:29
Thanks for the fix Hellfish. I just added Phytohydra's big brother Vigor. That's one more Incarnation down. It looks like Hostility may be scriptable, maybe Personal Incarnation as well, but I'm not sure. I think Guile needs some more infrastructure though.
Thanks Again Hellfish!
Thanks Again Hellfish!
Re: Replacement Effects
by friarsol » 03 Jan 2012, 15:33
Hey Hellfish,
Instead of AllzoneUtil.matchesValid() that you made in r12937 any reason not to have these things inherit from the same abstract class that has that function to consolidate? This way we don't need the call outside the objects?
Instead of AllzoneUtil.matchesValid() that you made in r12937 any reason not to have these things inherit from the same abstract class that has that function to consolidate? This way we don't need the call outside the objects?
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: Replacement Effects
by Hellfish » 03 Jan 2012, 15:37
No *good* reason, no.. 
The only reason not to do that is what would the base object be called without being confusing? TriggerReplacementBase?
The only reason not to do that is what would the base object be called without being confusing? TriggerReplacementBase?
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-

Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
Re: Replacement Effects
by friarsol » 03 Jan 2012, 15:43
Ohh my favorite part of programming, coming up with names for things!
BaseValidator?
BaseFiringEvent?
George?
BaseValidator?
BaseFiringEvent?
George?
- friarsol
- Global Moderator
- Posts: 7593
- Joined: 15 May 2010, 04:20
- Has thanked: 243 times
- Been thanked: 965 times
Re: Replacement Effects
by Hellfish » 03 Jan 2012, 16:06
Will commit after doing the laundry.
So now you're
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
Screaming for the blood of the cookie monster
Evil puppet demon of obesity
Time to change the tune of his fearful ballad
C is for "Lettuce," that's good enough for me
-

Hellfish - Programmer
- Posts: 1297
- Joined: 07 Jun 2009, 10:41
- Location: South of the Pumphouse
- Has thanked: 110 times
- Been thanked: 169 times
21 posts
• Page 1 of 2 • 1, 2
Who is online
Users browsing this forum: No registered users and 71 guests