Design Patterns for Games Stephen Wong Dung Nguyen

  • Slides: 25
Download presentation
Design Patterns for Games Stephen Wong Dung Nguyen Rice University

Design Patterns for Games Stephen Wong Dung Nguyen Rice University

Let’s Play a Game v v Sun’s Tic-Tac-Toe What can we learn from this?

Let’s Play a Game v v Sun’s Tic-Tac-Toe What can we learn from this? – Arrays – For-loops – Nested Conditionals v What aren’t we learning? – Delineation of concepts from implementation – Abstraction – Design

Something Different… v It’s not really about Tic. Tac. Toe… – It’s a vehicle

Something Different… v It’s not really about Tic. Tac. Toe… – It’s a vehicle to teach something BIGGER. Abstraction v Design Process v Fundamental Principles v

What’s in a Game? Model X Rules Strategies Players adapter View adapter Buttons, etc.

What’s in a Game? Model X Rules Strategies Players adapter View adapter Buttons, etc. Display outputs O Controller O Install adapters X

Game Model v Rules of the Game – Board configurations – Legal moves v

Game Model v Rules of the Game – Board configurations – Legal moves v Next Move Strategies Abstract these components! – Random – Min-Max – Etc. v Player Management Decouple these components! – Turn taking – Win/lose/draw notification – Fault handling

Game Model Classes Game. Model {Game Management} • Game initialization • Win/lose/draw notification IBoard.

Game Model Classes Game. Model {Game Management} • Game initialization • Win/lose/draw notification IBoard. Model {Rules of the Game} • Board configurations • Legal moves Abstracted & Decoupled! Turn. Control {Player Management} INext. Move. Strategy APlayer {Turn Taker} {Next Move Computation} • Random • Min-max/Alpha-beta • Limited depth • Custom

State Diagram Invalid Move State Valid Move State Non-Terminal State (no winner yet) Terminal

State Diagram Invalid Move State Valid Move State Non-Terminal State (no winner yet) Terminal States Player #0 Wins Player #1 Wins Draw Game

State Design Pattern IBoard. Model execute(IBoard. Status. Visitor v, …) Tic. Tac. Toe. Board

State Design Pattern IBoard. Model execute(IBoard. Status. Visitor v, …) Tic. Tac. Toe. Board state. execute(v, …) state ABoard. State v. no. Winner. Case(…) ATerminal. State Player 0 Won v. player 0 Won. Case(…) Player 1 Won Non. Terminal. State Draw. Game v. player 1 Won. Case(…) v. draw. Case(…)

The Rules of the Game IBoard. Model IUndo. Move make. Move(player, row, col), chk.

The Rules of the Game IBoard. Model IUndo. Move make. Move(player, row, col), chk. Move. Cmd), bd. Status. Vstr) Object execute(bd. Status. Vstr, param) // other methods commands host/visitor ICheck. Move. Cmd valid. Move. Case() invalid. Move. Case() IUndo. Move apply(…) IBoard. Status. Visitor player 0 Won. Case(…) player 1 Won. Case(…) draw. Case(…) no. Winner. Case(…)

Playing the Game Computer. Player INext. Move. Strategy take. Turn(…) Point get. Next. Move(…)

Playing the Game Computer. Player INext. Move. Strategy take. Turn(…) Point get. Next. Move(…) Random Min. Max Alpha. Beta The next move process is decoupled from the rules of the game!

Facade APlayer take. Turn(…) IRequestor IBoard. Model make. Move(…) Turn. Control IView

Facade APlayer take. Turn(…) IRequestor IBoard. Model make. Move(…) Turn. Control IView

What the player sees: public interface IRequestor { public abstract void set. Token. At(

What the player sees: public interface IRequestor { public abstract void set. Token. At( int row, int col, int player, IReject. Command reject. Command); } public interface IReject. Command { public abstract void execute(); }

Player Factories IView Only displays the to. String() of the factories. The factories are

Player Factories IView Only displays the to. String() of the factories. The factories are treated as Objects! Selected APlayer factories Set of APlayer factories Game. Model private interface IMake. Player { public APlayer create(int player. No); }

The Set of APlayer Factories public Vector get. Players() { Vector v = new

The Set of APlayer Factories public Vector get. Players() { Vector v = new Vector(); Anonymous APlayer factory Factory method v. add. Element(new IMake. Player() { public APlayer create(int player. No) { return new Human. Player(requestor, player. No, turn. Admin); } public String to. String() { return "Human player"; } }); return v; } IView only cares about this!

Min-Max Principle V(s) = ·For terminal state · +1, if s is a winning

Min-Max Principle V(s) = ·For terminal state · +1, if s is a winning state for that player · 0, if s is a draw state Application of · -1, if s is a losing state for that player a process ·For non-terminal state over a set! · max{V(c) | c is a child valid move state of s} , if that player moves next · min{V(c) | c is a child valid move state of s}, if the other player moves next. The best next move for a given player, m, is determined from max{V(c) | c S} where S is the set of available moves for that player. How max is computed is a variant.

Mapping and Lambda v Math/FP: Map( , S) = { (x) | x S}

Mapping and Lambda v Math/FP: Map( , S) = { (x) | x S} Both accumulators are abstractly equivalent! v Express our algorithm in terms of mapping, not iteration: – min(…) map( , min-accum) – max(…) map( , max-accum) v Backtracking is automatically handled by mapping.

Abstract Accumulators Intelligent component AAccum void update. Best(row, col, value) Point get. Move() AAccum

Abstract Accumulators Intelligent component AAccum void update. Best(row, col, value) Point get. Move() AAccum make. Opposite() Min. Acc Max. Acc IAcc. Factory AAccum make. Acc(player) Opposite is Min. Acc

Mapping Abstraction IBoard. Model IUndo. Move make. Move(player, row, col), chk. Move. Cmd), bd.

Mapping Abstraction IBoard. Model IUndo. Move make. Move(player, row, col), chk. Move. Cmd), bd. Status. Vstr) Object execute(bd. Status. Vstr, param) void map(player, lambda, param) Controls Called on all valid continuation of Called when there moves. mapping are no valid moves. command IBoard. Lambda boolean apply(board, param, row, col, cell-val) void no. Apply(board, param)

INext. Move. Strategy Min-Max Abstraction Min. Max acc. Fac: IAcc. Factory AAccum make. Acc(player)

INext. Move. Strategy Min-Max Abstraction Min. Max acc. Fac: IAcc. Factory AAccum make. Acc(player) Point get. Next. Move(model, player) min. Max. Eval: IBoard. Lambda boolean apply(…) void no. Apply(…) AAccum acc = acc. Fac. make. Acc(player); model. get. Board. Model(). map(min. Max. Eval, acc); return acc. get. Move();

private IBoard. Lambda eval. Lambda = new IBoard. Lambda() { sur Cl o Try

private IBoard. Lambda eval. Lambda = new IBoard. Lambda() { sur Cl o Try a test move. public boolean apply(board, acc, row, col, cell-value) { to be mapped over IUndo. Move undo = board. make. Move( the available states. row, col, acc. get. Player(), valid. Mv. Vstr, Called by map on new IBoard. Status. Visitor() { each valid (row, col) Update player 0 Won. Case(. . . ) {…} accumulator What to do in e each situation {…} player 1 Won. Case(…) draw. Case(…) {…} Declarative programming! no. Winner. Case(…) { AAccumulator next. Acc = acc. make. Opposite(); Undoboard. map(next. Acc. get. Player(), the move. eval. Lambda, next. Acc); acc. update. Best(row, col, next. Acc. get. Val()); return null; } }); undo. apply(valid. Undo); return acc. is. Not. Done(); } Stop mapping?

Just a new accumulator! Alpha-Beta Pruning Override the creation of the next level’s accumulator

Just a new accumulator! Alpha-Beta Pruning Override the creation of the next level’s accumulator Accumulator for the public class Alpha extends Max. Acc { opposite player as an inner {class. public AAccumulatoranonymous make. Opposite() Stop mapping if pruning Closure gives the condition is met. return new Beta(model. Player) { scoping we need! public boolean is. Not. Done() { return Alpha. this. get. Val() < Beta. this. get. Val(); } } Abstraction isolates the essence and provides extensibility

Player Management Abstract players Event-loop for turn-taking Call-back techniques for asynchronous processing

Player Management Abstract players Event-loop for turn-taking Call-back techniques for asynchronous processing

Design Patterns In Action MVC separates model from view v Commands and Visitors isolate

Design Patterns In Action MVC separates model from view v Commands and Visitors isolate rules from behaviors v State pattern models game behavior v Calculating the next move is a Strategy v Design patterns express abstractions

Concepts in Action Abstract functions – lambda’s v Higher order functions – Mapping v

Concepts in Action Abstract functions – lambda’s v Higher order functions – Mapping v Declarative programming v Invariant: Min-Max Principle v Variant: v – Full depth-first search – Alpha-beta pruning

More Information… v Design Pattern for Games: http: //www. exciton. cs. rice. edu/research/SIGCSE 02

More Information… v Design Pattern for Games: http: //www. exciton. cs. rice. edu/research/SIGCSE 02 v Patterns for Decoupling Data Structures and Algorithms: http: //www. exciton. cs. rice. edu/research/SIGCSE 02