Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rule / validation design pattern

What design patterns can be used to create a rule / validation system for a game like chess (this is just a simple example, the actual game needs more difficult sets of rules)

I've read several questions on this site and haven't found a conclusive answer nor an answer pointing me in the right direction.

This system would require the following:

  • Every object that has rules applied to it should implement a specific interface with a method that is the starting point for the validation
  • The rule should be applied in 2 steps: first, it needs to be validated (can pawn A move to square D4), if true then execute method A if false then execute method B
  • Every object can have multiple rules that need to be applied in a specific sequence. When rule 1 is finished, rule 2 should then start to validate etc
  • Every separate rule (for example: can only move 1 square, can only move diagonally etc) must be in its own class and must be reusable and applicable on the objects that need rules.
  • Note this is going to be used in a multiplayer game on the backend
  • Note that every rule need multiple objects to test its validity, for example, normally a pawn can move 1 square, now the next sqaure on the gameboard is filled by a pawn of your opponent. Result: your pawn cannot move. The pawn should include the other pawns positions, or the gameboard in its validation.

Another word for these rules would be behavioral limits.

I've also posted the question on gamedev.stackexchange but since this is not nescesarily a game related question and no-one seems to have an answer I'm posting it here too.

like image 712
Thomas Avatar asked Dec 15 '22 15:12

Thomas


1 Answers

The more I look at the problem, the more I'm reminded of a state/flow chart.

enter image description here

  • Every object that has rules applied to it should implement a specific interface with a method that is the starting point for the validation

  • The rule should be applied in 2 steps: first, it needs to be validated (can pawn A move to square D4), if true then execute method A if false then execute method B

The state object can contain multiple transitions.

A Transition consists of:

  1. Condition(s)
  2. Action(s)
  • Every object can have multiple rules that need to be applied in a specific sequence. When rule 1 is finished, rule 2 should then start to validate etc

By using a state diagram, you get multiple rules and specific action sequences via states and state transitions

  • Every separate rule (for example: can only move 1 square, can only move diagonally etc) must be in its own class and must be reusable and applicable on the objects that need rules.

This can be achieved by encapsulating the condition-checking behaviour as a class

public class Condition 
{
    public string Name {get; set;}
    public Func<Move,bool> IsMet {get;set;} 
}

// Captures the behaviour of moving diagonally by 1-step
// This can now be referenced/composed by other classes to build
// a more complex condition
var moveDiagonalCondition = new Condition 
{ 
    Name="Move diagonal", 
    IsMet = move => 
                    {
                        var delta = (move.ToPosition - move.FromPosition);
                        // 1 step to the left or right
                        return Math.Abs(delta.X) == 1 
                        // 1 step upwards (if player),
                        // or 1 step downwards (if opponent)
                        && delta.Y == move.IsPlayer1Move ? -1 : 1
                    }
}
  • Note this is going to be used in a multiplayer game on the backend

  • Note that every rule need multiple objects to test its validity, for example, normally a pawn can move 1 square, now the next sqaure on the gameboard is filled by a pawn of your opponent. Result: your pawn cannot move. The pawn should include the other pawns positions, or the gameboard in its validation.

In the chess scenario, I propose passing around the move parameter:

public class Move
{
    public Point FromPosition {get;set;}
    public Point ToPosition {get;set;}
    public Piece Piece {get;set;}
}

At the same time, the states should have access to the entire GameBoard. This allows the state to do things like

// Check for empty cell
GameBoard.GetPieceAt(move.ToPosition) == null;

// Check for opponent's piece
GameBoard.GetPieceAt(move.ToPosition).IsPlayer2;

To further extend this to your MMORPG scenario, I would pass any "sources" and/or "targets" via parameter

  • i.e. Collision source/target, or any objects that are directly affected

Conclusion

Being so similar to a state problem, I think it's a good idea to look at state-based solutions.

E.g., State Pattern, Finite State Machines, State Transition Tables, automata, etc.

Or you can try looking up decision tables and decision trees (haven't really used these myself, so I'm unable to say much about them).

Unfortunately, I don't think I can recommend an exact solution.

But hopefully the few examples/keywords above will help you get started.

like image 59
jayars Avatar answered Dec 21 '22 22:12

jayars