In my opinion it's a good idea for your Hand and card implementations to know as little as possible (preferably nothing, if you can manage it) about the rules of the game. Hand should know only about how to receive and remove a card, fetch a card, maybe search for a particular type of card, and maybe some way to sort the cards (some players prefer to keep their cards sorted). Even sorting is a little tricky because different games may have different ways to sort cards. This can probably be accomplished by implementing some sort of "sorter" interface. You could create classes "MyGameHandSorter" or a "PokerHandSorter" or "BridgeHandSorter," for example. At that point you could either "MyGameHandSorter().sort(myHand)". You can even go through the trouble of formally declaring your interfaces, "class IHandSorter(object): ...class PokerHandSorter(IHandSorter)" but it's probably not necessary. Remember, python does duck typing.
As far as implementing every game rule as an object: It depends. Some rules are better left implemented directly into your Game class. Things like phases of a player turn, what can be done during the different phases, etc. might be better left in Game.
That being said, if you're making a game in the same genre as MtG, each card could have its own set of special rules associated with it. You should spend some time trying to classify these rules down into as many "rule types" as you can. From there, find a way to represent the data that is associated with these rule types. That data will be held in your Card implementation for the game, either directly in the card or attached to the card through some sort of CardProperties member on Card or something. I'd probably just stick them in Card. With MtG there are always exceptions, and these will have to be handled in your Game.playCard implementation. I wouldn't put them on Card, personally. Cards should just be data. This way you don't risk having to rewrite individual card implementations if you decide to create some specialized version of your game.
In fact, you probably won't be implementing a "playCard" method on game. You'll more likely be implementing what we call the command pattern. The player will build commands indicating what she would like to do, then dispatch those to the implementation of Game. The reason you have to do this is because in games like MtG, the opposing player has an opportunity to interrupt your action. You cannot immediately resolve a healing spell, for example, because the opposing player might cast an interrupt to prevent the spell. Another player might interrupt that spell somehow, or perform some other action (maybe even eliminate the player with an instant damage spell!) that affects the outcome. All these commands will need to be collected from all the players, then resolved by Game in the proper order and the outcome will need to change the state of the game, cards, and players. And finally those outcomes will need to be presented to the players.
I bet you thought you were picking an easy game coding project, didn't you?
Show differencesHistory of post edits
#1smr
Posted 27 November 2012 - 01:19 PM
In my opinion it's a good idea for your Hand and card implementations to know as little as possible (preferably nothing, if you can manage it) about the rules of the game. Hand should know only about how to receive and remove a card, fetch a card, maybe search for a particular type of card, and maybe some way to sort the cards (some players prefer to keep their cards sorted). Even sorting is a little tricky because different games may have different ways to sort cards. This can probably be accomplished by implementing some sort of "sorter" interface. You could create classes "MyGameHandSorter" or a "PokerHandSorter" or "BridgeHandSorter," for example. At that point you could either "MyGameHandSorter().sort(myHand)". You can even go through the trouble of formally declaring your interfaces, "class IHandSorter(object): ...class PokerHandSorter(IHandSorter)" but it's probably not necessary. Remember, python does duck typing.
As far as implementing every game rule as an object: It depends. Some rules are better left implemented directly into your Game class. Things like phases of a player turn, what can be done during the different phases, etc. might be better left in Game.
That being said, if you're making a game in the same genre as MtG, each card could have its own set of special rules associated with it. You should spend some time trying to classify these rules down into as many "rule types" as you can. From there, find a way to represent the data that is associated with these rule types. That data will be held in your Card implementation for the game, either directly in the card or attached to the card through some sort of CardProperties member on Card or something. I'd probably just stick them in Card. With MtG there are always exceptions, and these will have to be handled in your Game.playCard implementation. I wouldn't put them on Card, personally. Cards should just be data. This way you don't risk having to rewrite individual card implementations if you decide to create some specialized version of your game.
In fact, you probably won't be implementing a "playCard" method on game. You'll more likely be implementing what we call the command pattern. The player will build commands indicating what she would like to do, then dispatch those to the implementation of Game. The reason you have to do this is because in games like MtG, the opposing player has an opportunity to interrupt your action. You cannot immediately resolve a healing spell, for example, because the opposing player might cast an interrupt to prevent the spell. Another player might interrupt that spell somehow, or perform some other action (maybe even eliminate the player with an instant damage spell!) that affects the outcome. All these commands will need to be collected from all the players, then resolved by Game in the proper order and the outcome will need to change the state of the game, cards, and players. And finally those outcomes will need to be issued to the players.
I bet you thought you were picking an easy game coding project, didn't you?
As far as implementing every game rule as an object: It depends. Some rules are better left implemented directly into your Game class. Things like phases of a player turn, what can be done during the different phases, etc. might be better left in Game.
That being said, if you're making a game in the same genre as MtG, each card could have its own set of special rules associated with it. You should spend some time trying to classify these rules down into as many "rule types" as you can. From there, find a way to represent the data that is associated with these rule types. That data will be held in your Card implementation for the game, either directly in the card or attached to the card through some sort of CardProperties member on Card or something. I'd probably just stick them in Card. With MtG there are always exceptions, and these will have to be handled in your Game.playCard implementation. I wouldn't put them on Card, personally. Cards should just be data. This way you don't risk having to rewrite individual card implementations if you decide to create some specialized version of your game.
In fact, you probably won't be implementing a "playCard" method on game. You'll more likely be implementing what we call the command pattern. The player will build commands indicating what she would like to do, then dispatch those to the implementation of Game. The reason you have to do this is because in games like MtG, the opposing player has an opportunity to interrupt your action. You cannot immediately resolve a healing spell, for example, because the opposing player might cast an interrupt to prevent the spell. Another player might interrupt that spell somehow, or perform some other action (maybe even eliminate the player with an instant damage spell!) that affects the outcome. All these commands will need to be collected from all the players, then resolved by Game in the proper order and the outcome will need to change the state of the game, cards, and players. And finally those outcomes will need to be issued to the players.
I bet you thought you were picking an easy game coding project, didn't you?