Why use an event system
General Discussion of the Intricacies
	Moderator: CCGHQ Admins
			7 posts
			 • Page 1 of 1
		
	
Why use an event system
 by Incantus » 23 Jan 2009, 19:04
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
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
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
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
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
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
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 4 guests
 
 