Design Patterns for Games Stephen Wong Dung Nguyen Rice University.

Post on 14-Dec-2015

212 views 0 download

Transcript of Design Patterns for Games Stephen Wong Dung Nguyen Rice University.

Design Patterns for Games

Stephen Wong

Dung NguyenRice 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…

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

Abstraction Design Process Fundamental Principles

What’s in a Game?

X X

O

OController

ModelRules

PlayersStrategies

View

Buttons, etc.

Display outputsadapter

adapter

Install adapters

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!

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

State Diagram

Invalid Move State

Valid Move State

Non-Terminal State(no winner yet)

Terminal States

Player #0 Wins

Draw Game

Player #1 Wins

ABoardStatestate

State Design Pattern

TicTacToeBoard

Player1WonPlayer0Won DrawGame

ATerminalState NonTerminalState

IBoardModel

execute(IBoardStatusVisitor v, …)

v.player0WonCase(…)

state.execute(v, …)

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

v.noWinnerCase(…)

Playing the GameComputerPlayer

takeTurn(…)

INextMoveStrategyPoint getNextMove(…)

Random AlphaBetaMinMax

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

FacadeAPlayer

takeTurn(…)

IBoardModel

makeMove(…)

TurnControl IView

IRequestor

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();}

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);

}

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

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!

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.

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.

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();

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?

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!

Player Management

Event-loop for turn-taking

Call-back techniques for asynchronous processing

Abstract players

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

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

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