What sort of design patterns and ideas might one use to build a somewhat general purpose card game framework?

This stems from I made an attempt to build a clone of the popular Steve Jackson game "Munchkin". Because of the nature of that game I ended having to hard code so many card functionalities that the development became chaotic and over-bearing. I had wanted to build something general but ended up with just to many classes with to many overridden functions and switch statements to determine behavior.

I was curious what someone with more experience in design would handle such a task of building a general purpose card game framework, or at least something that could be extended. Or is it best that if I want to make a simulation of a card game like Munchkin, i'm stuck making a specific framework.

I would like to use C#.


I would like to clarify somewhat of what i'd eventually like to achieve. I'd like a framework where I can basically implement phases with custom functionality (phase 1: draw cards, phase 2: apply upkeep rules, phase 3: play cards, phase 4: resolve, etc).

I think then defining a ruleset would be wise which would be coupled with both the cards and the phases.

Then, the cards would be defined and I suppose tied to the rules so for instance a rule might be "During upkeep phase, lose 1 token". However, a card that the player has might provide "Don't lose any tokens during the upkeep phase". So it would be nice to be able to tie this together but within the guts of the framework.

I suppose this might be way out of my league as well.

  • 1
    \$\begingroup\$ Please clarify something for me: are you looking for something that will just let you develop Munchkin painlessly, or do you have the ambition to create a generic card game framework that people can also use on other card games? (Aside, if you're considering the latter, I would advise just focusing on the former at this point) \$\endgroup\$ – doppelgreener May 19 '11 at 22:35
  • \$\begingroup\$ I'm not really interested in Munchkin anymore, but I actually have another card game in mind (something of my own creation) that i'd like to put in computer form, painlessly. Does that help? \$\endgroup\$ – Robb May 19 '11 at 23:58
  • \$\begingroup\$ As long as you're writing a game, not just an engine. \$\endgroup\$ – doppelgreener May 20 '11 at 6:14

I would have used some kind of script language as LUA or Python to define each special behaviors or card.

This way you can define a "generic" engine, and keep the cards particularities away from the main code, into some small and easily editable scripts.

The main advantage of script languages over XML or some other "static" data is that script languages can "create" their own behaviors using the public methods offered by the engine.

Example: suppose your engine offer the methods "setDommage(target,dmg)" and "setVisualEffect(nameOfFxLuaScript)" etc. You can have a cards doing something like this peuso-code

------Card1 -- A simple fireball-----
// Fire ball
setDommage(target, 37);

------Card2 -- A multitype ball (outch it hurts!)-----
// Fire ball
setDommage(target, 37);

// Ice ball
if( player.protectionAgainstIce == false )
    setDommage(target, 102);

// thunderbolt
while( player.Alive )
    setDommage(target, 1005);

The both cards use the same engine methods, but they don't do the same things. The behaviors can also use data gathered from the engine (like the player list to loop over them) and for, if etc. statements.

The second but not the least advantage, is that it doesn't need to be compiled. You can modify you LUA script and reload it directly without recompiling your game. It's very nice for testing and iterating until you find the good settings.

The third advantage is that, anyone that can learn script language can create new cards/behaviors as long as you provide a list of the public methods shared by the engine (and as long as you don't encode the LUAs). And as anyone knows, the community is incredible when you give them nice tools ;)

Here is a LUA wrapper for C#: http://luaforge.net/projects/luainterface/

|improve this answer|||||
  • \$\begingroup\$ You wouldn't happen to have a link to a project that might be similar to what you describe? I have never used script languages before. I was hoping to just define the cards in XML, read them in and basically the game would just apply what the card does. \$\endgroup\$ – Robb May 19 '11 at 19:46
  • \$\begingroup\$ XML is not a bad idea, but you will be very limited trough. Script offer the ability to create custom behaviors using the public methods offered by the engine. This way the engine can remain as "generic" as possible. I don't know an example applying to cards, but there is tons of games using LUA like WoW (addons) or Aquaria (behaviors of entities). \$\endgroup\$ – Valkea May 19 '11 at 20:23
  • \$\begingroup\$ Hmm I'm seeing a real advantage to using a script language. So in the example, you have damage. For a card game, with multiple things would it be better to try to figure out all the actions possible or try to build a generic 'setActionEffect'. In Munchkin you can say apply a modifier to your level to inrease it. You can also make the monster disappear. You can even adjust a die roll. That piece of the puzzle is what I'm challenged with, how to model something complex like that. \$\endgroup\$ – Robb May 19 '11 at 20:39
  • \$\begingroup\$ I'm not really sure how scripting is going to help his "engine" from devolving into a whole host of properties such as "ProtectionAgainstX" and "CanDoY", etc. In fact it seems like scripting would force you to break encapsulation down, which I believe would make it harder and harder to add new cards and change fundamental game rules. \$\endgroup\$ – Alex Schearer May 19 '11 at 20:50
  • \$\begingroup\$ @Alex: The goal is to make it the more "generic" possible, so it can be used with a completely different universe without having to change the game code/core. The "protectionAgainstIce" used in the pseudo-code was a bad example used to demonstrate the "if" statement, but it should be something like isProtectedAgainst("ice") which is more generic an reusable with different stuffs ("fire", "balls", "laser", etc.). This way there is an "infinity" of possibilities as long as the types (fire etc) are defined outside the game core too. \$\endgroup\$ – Valkea May 19 '11 at 21:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.