Why use an event system
General Discussion of the Intricacies
Moderator: CCGHQ Admins
Why use an event system
by Incantus » 23 Jan 2009, 19:04
Here's the best justification for using an event system:
When an event happens in magic, other things might care about the event, but the cause of the event doesn't care who responded to that event. Which suggests that you should completely decouple the objects generating the events from the objects listening for them. A general publish/subscribe event system gives you this decoupling. This will make your design much simpler.
For example, in Incantus all important objects derive from a common MtGObject, who's sole behavior is to send and listen to events. Almost everything derives from this, including Player, Cards, the Abilities hierarchy, since they all have to send events (arguably this is a stupid design, since I'm already using a global event dispatching system, so anybody object could access it anyway, but it was the first design decision I made so I'm stuck with it).
For example, these are the events currently sent in Incantus:
When an event happens in magic, other things might care about the event, but the cause of the event doesn't care who responded to that event. Which suggests that you should completely decouple the objects generating the events from the objects listening for them. A general publish/subscribe event system gives you this decoupling. This will make your design much simpler.
For example, in Incantus all important objects derive from a common MtGObject, who's sole behavior is to send and listen to events. Almost everything derives from this, including Player, Cards, the Abilities hierarchy, since they all have to send events (arguably this is a stupid design, since I'm already using a global event dispatching system, so anybody object could access it anyway, but it was the first design decision I made so I'm stuck with it).
For example, these are the events currently sent in Incantus:
- Code: Select all
class GameStartEvent(Event): pass
class GameOverEvent(Event): pass
class HasPriorityEvent(Event): pass
class TimestepEvent(Event): pass
class GameFocusEvent(Event): pass
class LogEvent(Event): pass
class LifeGainedEvent(Event): pass
class LifeLostEvent(Event): pass
class DrawCardEvent(Event): pass
class DiscardCardEvent(Event): pass
class ShuffleEvent(Event): pass
class CardEnteringZoneFrom(Event): pass
class CardEnteredZone(Event): pass
class CardLeftZone(Event): pass
class CardCeasesToExist(Event): pass
class ControllerChanged(Event): pass
class TokenLeavingPlay(Event): pass
class CounterAddedEvent(Event): pass
class CounterRemovedEvent(Event): pass
class MorphEvent(Event): pass
class ClashEvent(Event): pass
class CardCycledEvent(Event): pass
class NameModifiedEvent(Event): pass
class CostModifiedEvent(Event): pass
class TextModifiedEvent(Event): pass
class TypesModifiedEvent(Event): pass
class ColorModifiedEvent(Event): pass
class SubtypesModifiedEvent(Event): pass
class SupertypesModifiedEvent(Event): pass
class AbilitiesModifiedEvent(Event): pass
class PowerToughnessModifiedEvent(Event): pass
class LoyaltyModifiedEvent(Event): pass
class ManaAdded(Event): pass
class ManaSpent(Event): pass
class ManaCleared(Event): pass
class CardTapped(Event): pass
class CardUntapped(Event): pass
class LandPlayedEvent(Event): pass
class AbilityAnnounced(Event): pass
class AbilityCanceled(Event): pass
class AbilityPlacedOnStack(Event): pass
class AbilityRemovedFromStack(Event): pass
class AbilityResolved(Event): pass
class AbilityCountered(Event): pass
class AbilityPlayedEvent(Event): pass
class SpellPlayedEvent(Event): pass
class DeclareAttackersEvent(Event): pass
class DeclareBlockersEvent(Event): pass
class AttackerSelectedEvent(Event): pass
class AttackersResetEvent(Event): pass
class BlockerSelectedEvent(Event): pass
class BlockersResetEvent(Event): pass
class AttackerDeclaredEvent(Event): pass
class BlockerDeclaredEvent(Event): pass
class AttackerBlockedEvent(Event): pass
class AttackerClearedEvent(Event): pass
class BlockerClearedEvent(Event): pass
class CreatureInCombatEvent(Event): pass
class CreatureCombatClearedEvent(Event): pass
class RegenerateEvent(Event): pass
class DamagePreventedEvent(Event): pass
class DealsDamageEvent(Event): pass
class DealsDamageToEvent(Event): pass
class ReceivesDamageEvent(Event): pass
class PermanentSacrificedEvent(Event): pass
class PermanentDestroyedEvent(Event): pass
class AttachedEvent(Event): pass
class UnAttachedEvent(Event): pass
class CardSelectedEvent(Event): pass
class AllDeselectedEvent(Event): pass
class TargetedByEvent(Event): pass
class InvalidTargetEvent(Event): pass
class NewTurnEvent(Event): pass
class TurnFinishedEvent(Event): pass
class GameStepEvent(Event): pass
class UntapStepEvent(GameStepEvent): pass
class UpkeepStepEvent(GameStepEvent): pass
class DrawStepEvent(GameStepEvent): pass
class MainPhase1Event(GameStepEvent): pass
class MainPhase2Event(GameStepEvent): pass
class EndMainPhaseEvent(GameStepEvent): pass
class BeginCombatEvent(GameStepEvent): pass
class AttackStepEvent(GameStepEvent): pass
class BlockStepEvent(GameStepEvent): pass
class AssignDamageEvent(GameStepEvent): pass
class EndCombatEvent(GameStepEvent): pass
class EndTurnStepEvent(GameStepEvent): pass
class CleanupPhase(GameStepEvent): pass
class CleanupEvent(GameStepEvent): pass
Re: Why use an event system
by frwololo » 23 Jan 2009, 22:48
Isn't there a risk of infinite loop with this design ?
Re: Why use an event system
by Incantus » 24 Jan 2009, 00:13
There is, but that risk is also considered in the comprehensive rules. If you have an infinite loop, then the game becomes a draw. It's just a matter of tracing execution paths.
Re: Why use an event system
by MageKing17 » 25 Jan 2009, 02:30
The thing about infinite loops is that the cards themselves are usually designed in such a way as to prevent this from happening. For example, consider a card with the text "When ~ comes into play, remove all permanents from the game" and "When ~ leaves play, return the removed permanents to play under their owners' control". No card is ever printed with both of these abilities, and for a very good reason... playing this card leads to an infinite loop (in real Magic, this will cause the game to be a draw). Nonetheless, if your implementation of the game doesn't allow such an occurrence, your implementation is incomplete... you won't have to worry about such a card wrecking the game because Wizards wouldn't print it, but you shouldn't take it upon yourself to prevent it from ever happening (by not adopting an event system that can let it happen), because the rules say it can.
So, in short, yes, it allows infinite loops. But that's intended behavior.
So, in short, yes, it allows infinite loops. But that's intended behavior.
-
MageKing17 - Programmer
- Posts: 473
- Joined: 12 Jun 2008, 20:40
- Has thanked: 5 times
- Been thanked: 9 times
Re: Why use an event system
by mtgrares » 27 Jan 2009, 20:34
That is alot of events, lol. My favorite is NameModifiedEvent, I'm sure that a card can have it's name changed, but I can't cite an example off of the top of my head.
- mtgrares
- DEVELOPER
- Posts: 1352
- Joined: 08 Sep 2008, 22:10
- Has thanked: 3 times
- Been thanked: 12 times
Re: Why use an event system
by MageKing17 » 28 Jan 2009, 02:47
Copy effects copy names.mtgrares wrote:That is alot of events, lol. My favorite is NameModifiedEvent, I'm sure that a card can have it's name changed, but I can't cite an example off of the top of my head.
-
MageKing17 - Programmer
- Posts: 473
- Joined: 12 Jun 2008, 20:40
- Has thanked: 5 times
- Been thanked: 9 times
Re: Why use an event system
by mtgrares » 28 Jan 2009, 19:51
I tend to make events that are "too large". Like a zoneEvent will includes both adding and removing cards, while I should probably split them into zoneAddEvent and zoneRemoveEvent. I think I need to make the events "more fine grained."
Instead of
Instead of
- Code: Select all
zone.addEvent(Event)
- Code: Select all
zone.addEvent_Add(Event)
zone.addEvent_Remove(Event)
- mtgrares
- DEVELOPER
- Posts: 1352
- Joined: 08 Sep 2008, 22:10
- Has thanked: 3 times
- Been thanked: 12 times
7 posts
• Page 1 of 1
Return to Magic Rules Engine Programming
Who is online
Users browsing this forum: No registered users and 10 guests