13
13
Jan 2013

Scourge, Part III – the ROPES

Solid foundations

Scourge is a complex game, and programming its model involves accomplishing several tasks. Starting out, I wanted to separate the game concepts that are specific to Scourge from the concepts that form the underlying structure of a strategy board game.

So! What makes a good model for a strategy board game? By “good” I mean, “offers a representation of the system it’s modeling that best facilitates reasoning about that system”. I want views, net protocols and computer opponents to be relatively easy to map to this thing. So here’s the list of criteria that I came up with:

  1. Each player decision must be explicitly represented : rather than leaving it up to players to discover what options are available to them, the model should create options from the state that players may then evaluate, compare and choose from. This limits the role of an AI to purely strategizing, and reduces the amount of code that a player relies on to reason about a particular rule. (I could technically write a functioning AI that performs no rule-specific reasoning about its decisions, relying solely upon a coarse estimate of the board’s value. I think it makes for a good starting point!)
  2. A traversable decision tree : we can couple the aforementioned player decision generation with a rewindable history object, so that players can climb up and down the decision tree like a rock climber on a climbing wall, moving from handhold to handhold, trying to reach a goal position.
  3. Dynamic rules : there are games with many, many rules, with each one applying to a particular context. If the game is being played in a context where a rule never applies, then the game model should not represent that rule computationally– after all, it will never contribute to the available options to a player.

That last condition relates to entity system frameworks, which allow the game devs who work with them to maintain complex changing systems. But the games I’m interested in generally don’t change much after they begin; the third condition only really applies to the generation of games, and is rigid afterwards.

My system needs to be built flexibly, but to run rigidly and deterministically, and thirdly, to limit the players to a set of decisions. I call this the Rule-Option Paradigm Entity System, or the ROPES, and it’s the most distinctive model I’ve ever written. Feast your eyes, visitor!

The ROPES UML class diagram.

There’s a little bit more to it than this, but really, this is all most programmers will ever see of it. Let’s break it down.

ROPES games are comprised of Rules, which are just Option generators; to perform a player action, the game simply passes the player’s choice of Option to the Rule that generated it. That Rule, in turn, updates the State, and the game updates all the Rules, and so they generate new Options, and so on. There’s our explicit player decision representation.

On the bottom right there’s a History object, which is just a buffer of data that can record and undo changes we make to it. The StateHistorian maps the State of the game to that History. This gives us the ability to make changes and then rewind them.

The third major feature of the ROPES, and possibly the most prominent in the codebase, is mostly left out of this diagram– the ability to configure games quickly. Scourge’s prototype was built in a way that makes it harder and harder to add new features, and to configure existing ones, because the game’s complexity was related to the number of Rules in it. In contrast, the ROPES makes no assumptions about the way a game is played; each Rule is a separate, independent logical component. When you line up a bunch of Rules, each one specifies what Aspects it needs on the different entities within the State. The ROPES then builds the State and the Rules get pointers to the Aspects they need. In this way, the complexity of a ROPES game is related to the number of Rules you play by, not the number of Rules you have available.

Here’s an example of a Scourge Rule built in the ROPES. Note that it has only one option. That’s because not all Rules of a game are used to offer choice to a player– some are active right after a player makes a choice. The ROPES offers a convenient way to chain Rules like this together, so that a player action triggers a sequence of Rule activity.

So! We have a model with initial configurability; it has a history, so that we can choose options and then undo them, which helps us reason about the future; and apart from its State, it exposes Options to the player, so that the decision tree is directly traversable. Job done.

I think this is a big enough blob of text for now. I’ll be producing a couple ROPES examples soon– one for Tic-Tac-Toe and one for Checkers– that will hopefully demonstrate by example what I may have failed to communicate here. The ROPES has helped Scourge grow quickly, and I think it’s a useful stepping stone for similar games.


You can leave a response, or trackback from your own site.

Leave a Reply