"Game" Engine Requirements System I am/have been building a game for a long time now. The game is a web browser based system, and data is stored using JSON stored in RavenDB.

One thing I am very constantly running into as a problem is the notion of Requirements. Anyone who has played a game, particularly an RPG, is probably familiar with this. Requirements such as Requires Level 10 to use or Requires [Race] to use.

This has been a constant struggle for me, and I have finally worked out what I feel is a solution; But I wanted to see if there were other people who have overcome this issue and could offer any advice.

The way it works is that all of the various things in the game that can have requirements have a field...

List&lt;Conditional&gt; Conditions { get; set; }


Conditional is defined like this; 

public class Conditionals {

    public Condition&lt;bool&gt; Named { get; set; }
    public Condition&lt;double&gt; Minimum { get; set; }
    public Condition&lt;double&gt; Maximum { get; set; }
    public Condition&lt;double&gt; Exactly { get; set; }
}


And then each of those is a type of Condition&lt;T&gt;, which is declared like this;

public class Condition&lt;T&gt; {

    public string Id { get; set; }
    public string Name { get; set; }
    public string Adjective { get; set; }
    public string Label { get; set; }
    public T Value { get; set; }
}


So then the JSON would, if I am right, look like this... assume an item that requires level 10.

var Conditionals = new List&lt;Conditionals&gt;{
    new Conditionals {
        Minimum = new Condition&lt;double&gt;{
            Id = "clue/level",
            Name = "Level",
            Adjective = "&gt;=",
            Label = "Level is greater than or equal to 10",
            Value = 10
        }
    }
};


These will be resolved when the character is retrieved from the database using Clues. Clues are simple key/value pairs, like a dictionary. A clue has an identity and a value only.

var character = new Character {
    Level = 11,
    Clues = new List&lt;Clue&gt; () // clues will contain key/value pairs
};
// on database save
character.Clues.Add(new Clue {
    Id = "clue/level",
    Value = character.Level
});


This means I will have to do some hard coding, but only by coding in clues that we know the game is going to expect. This allows us to be a little more specific (I feel) and still have some freedom.

foreach (var condition in Conditionals) {
    // attempt to see if the condition can be satisfied. This code would
    // execute for all four propertyes (named, minimum, maximum, equals)
    var currentClue = character.Clues.FirstOrDefault(y =&gt; y.Id == condition.Minimum.Id);

    // attempt to resolve. this is the minimum section, so we always use &gt;=
    var outcome = currentClue.Value &gt;= condition.Value;
}


I am basically trying to ask if anyone else who has more experience has ever encountered this kind of issue in their own projects, and if my solution compares to any that are known to work. This has frustrated me for a long time.
I have never written code against a RavenDB, and very seldom use Json (actually, "never" is almost accurate). The way I see it, the classes that end up Json-serialized and persisted to the database, are analoguous to Entities (Entity Framework), or POCO's.

They are part of your data model.

It might seem (/be) code duplication, but if you had a domain model (which might mirror your data model... or not) and a way to "translate" a domain entity to a data entity (and vice-versa), you could very well use an enum in your domain model, and have it serialized as a string.

Basically: the shape of the data shouldn't drive, nor define, the shape of the objects your application is going to work with.

Your business logic (well, the actual game!) should work with the domain model objects, and then you'll have a data access layer that will do its job with RavenDB and Json - the business logic shouldn't be bothered with these concerns.

The Label is a good example of why presentation concerns and data concerns need to be separated: serializing and storing it is a waste, you already have all the necessary information in the other fields.

If you had a domain model Condition, it could have a Label property, with logic to build the string out of the other values.