Design Patterns for Games

23
Design Patterns for Games Stephen Wong Dung Nguyen Rice University

description

Design Patterns for Games. Stephen Wong Dung Nguyen Rice University. Let’s Play a Game. Sun’s Tic-Tac-Toe What can we learn from this? Arrays For-loops Nested Conditionals What aren’t we learning? Delineation of concepts from implementation Abstraction Design. Something Different…. - PowerPoint PPT Presentation

Transcript of Design Patterns for Games

Page 1: Design Patterns for Games

Design Patterns for Games

Stephen Wong

Dung NguyenRice University

Page 2: Design Patterns for Games

Let’s Play a Game

Sun’s Tic-Tac-Toe What can we learn from this?

– Arrays– For-loops– Nested Conditionals

What aren’t we learning?– Delineation of concepts from implementation– Abstraction– Design

Page 3: Design Patterns for Games

Something Different…

It’s not really about TicTacToe…– It’s a vehicle to teach something BIGGER.

Abstraction Design Process Fundamental Principles

Page 4: Design Patterns for Games

What’s in a Game?

X X

O

OController

ModelRules

PlayersStrategies

View

Buttons, etc.

Display outputsadapter

adapter

Install adapters

Page 5: Design Patterns for Games

Game Model Rules of the Game

– Board configurations– Legal moves

Next Move Strategies– Random– Min-Max– Etc.

Player Management– Turn taking– Win/lose/draw notification– Fault handling

Decouple these components!

Abstractthese components!

Page 6: Design Patterns for Games

The Rules of the Game

IBoardModel

IBoardStatusVisitor

makeMove(player, row, col), chkMoveCmd)IUndoMove , bdStatusVstr)

ICheckMoveCmdvalidMoveCase()invalidMoveCase()

player1WonCase(…)player0WonCase(…)

noWinnerCase(…)drawCase(…)IUndoMove

apply(…)

commandshost/visitor

Object execute(bdStatusVstr, param)

// other methods

Page 7: Design Patterns for Games

State Diagram

Invalid Move State

Valid Move State

Non-Terminal State(no winner yet)

Terminal States

Player #0 Wins

Draw Game

Player #1 Wins

Page 8: Design Patterns for Games

ABoardStatestate

State Design Pattern

TicTacToeBoard

Player1WonPlayer0Won DrawGame

ATerminalState NonTerminalState

IBoardModel

execute(IBoardStatusVisitor v, …)

v.player0WonCase(…)

state.execute(v, …)

v.player1WonCase(…) v.drawCase(…)

v.noWinnerCase(…)

Page 9: Design Patterns for Games

Playing the GameComputerPlayer

takeTurn(…)

INextMoveStrategyPoint getNextMove(…)

Random AlphaBetaMinMax

The next move process is decoupledfrom the rules of the game!

Page 10: Design Patterns for Games

FacadeAPlayer

takeTurn(…)

IBoardModel

makeMove(…)

TurnControl IView

IRequestor

Page 11: Design Patterns for Games

What the player sees:

public interface IRequestor {

public abstract void setTokenAt(int row, int col, int player, IRejectCommand rejectCommand);

}

public interface IRejectCommand { public abstract void execute();}

Page 12: Design Patterns for Games

Player FactoriesIView

GameModel

Set of APlayerfactories

Selected APlayerfactories

Only displays the toString()of the factories. The factories are treated as Objects!

private interface IMakePlayer {public APlayer create(int playerNo);

}

Page 13: Design Patterns for Games

The Set of APlayer Factories

public Vector getPlayers() { Vector v = new Vector();

v.addElement(new IMakePlayer() {

public APlayer create(int playerNo) { return new HumanPlayer(requestor, playerNo, turnAdmin); } public String toString() { return "Human player"; } });

return v;}

Anonymous APlayer factory

IView only cares about this!

Factory method

Page 14: Design Patterns for Games

Min-Max PrincipleV(s) =

For terminal state +1, if s is a winning state for that player 0, if s is a draw state -1, if s is a losing state for that player

For non-terminal state 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.

Application of a process over a set!

Page 15: Design Patterns for Games

Mapping and Lambda

Math/FP: Map(, S) = {(x) | x S}

Express our algorithm in terms of mapping, not iteration:

– min(…) map(, min-accum)

– max(…) map(, max-accum)

Both accumulators are abstractly equivalent!

Backtracking is automatically handled by mapping.

Page 16: Design Patterns for Games

IBoardLambda

Mapping Abstraction

IBoardModel makeMove(player, row, col), chkMoveCmd)IUndoMove , bdStatusVstr)

command

Object execute(bdStatusVstr, param)

void map(player, lambda, param)

boolean apply(board, param, row, col, cell-val)

void noApply(board, param)

Controls continuation of mappingCalled when there are no valid moves.

Called on all valid moves.

Page 17: Design Patterns for Games

Min-Max AbstractionINextMoveStrategy

MinMax accFac:IAccFactory

AAccum makeAcc(player)

minMaxEval:IBoardLambda

boolean apply(…)

void noApply(…)

Point getNextMove(model, player)

AAccum acc = accFac.makeAcc(player);model.getBoardModel().map(minMaxEval, acc);return acc.getMove();

Page 18: Design Patterns for Games

private IBoardLambda minMaxEval = new IBoardLambda() {

public boolean apply(board, acc, row, col, cell-value) {

IUndoMove undo = host.makeMove(row, col, acc.getPlayer(), validMvVstr,new IBoardStatusVisitor() {

player0WonCase(...) {…}

player1WonCase(…) {…}

drawCase(…) {…}

noWinnerCase(…) {

undo.apply(validUndo); return acc.isNotDone();

}

UpdateaccumulatorUpdateaccumulator

Updateaccumulator

AAccumulator nextAcc = acc.makeOpposite(); host.map(nextAcc.getPlayer(), minMaxEval, nextAcc); acc.updateBest(row, col, nextAcc.getVal()); return null; } });

Try a test move.

Undo the move.

Declarative style programming!

to be mapped over the available states.

Called by map on each valid (row, col)

What to do in each situation

Stop mapping?

Page 19: Design Patterns for Games

Alpha-Beta Pruningpublic class AlphaAcc extends MaxAcc { public AAccumulator makeOpposite() {

return new BetaAcc() {

{ this.modelPlayer = AlphaAcc.this.modelPlayer; }

public boolean isNotDone() { return AlphaAcc.this.getVal() < this.getVal(); } }; }}

Just a new accumulator!

Override the creation of the next level’s accumulator

Accumulator for the opposite player as an anonymous inner class.

Stop mapping if pruning condition is met.

Abstraction isolates the essence and provides extensibility

Inner class gives the scoping we need!

Page 20: Design Patterns for Games

Player Management

Event-loop for turn-taking

Call-back techniques for asynchronous processing

Abstract players

Page 21: Design Patterns for Games

Design Patterns In Action

MVC separates model from view Commands and Visitors isolate rules

from behaviors State pattern models game behavior Calculating the next move is a Strategy

Design patterns express abstractions

Page 22: Design Patterns for Games

Concepts in Action

Abstract functions – lambda’s Higher order functions – Mapping Declarative programming Invariant: Min-Max Principle Variant:

– Full depth-first search– Alpha-beta pruning

Page 23: Design Patterns for Games

More Information…

Design Pattern for Games:

http://www.exciton.cs.rice.edu/research/SIGCSE02

Patterns for Decoupling Data Structures and Algorithms:

http://www.exciton.cs.rice.edu/research/SIGCSE02