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.

Think of a game as a sequence of states, separated by moves. Every time a player makes a move, a new state is generated.

(It's like this XKCD comic!)

How

Create a class Move, which represents one move made by one player. (In Reversi, a sufficient description is one set of board coordinates where a piece is to be placed. In Chess, an origin and destination coordinate are sufficient.)

Create a class GameState, which represents the state of the game at any one time. (In Reversi, a sufficient description would be the board's contents and which player's turn it is. In Chess, you'd additionally need to store whether it is still possible for each player to castle kingside or queenside.)

Now, you can probably imagine the GameState having an isMoveLegal(Move) method. After all, it contains all the information it needs to make that decision.

Why

This design cleanly isolates the rule logic, reducing inter-component dependencies.

It also makes AI easy! You can trivially generate all possible moves from a GameState, check if they're legal, generate more GameStates from those and basically build a tree that you can use for minimax, perhaps with alpha-beta pruning.