package model;
import GameIO.*;
import java.awt.Point;
import java.util.*;
import model.board.*;
import model.nextMove.*;
/**
* A concrete model of a game. For descriptions of the methods, see the IModel
* and IModelAdmin interface documentation. Except for the setPlayers(),
* getPlayers() and addPlayer() methods, whose descriptions are below.
*/
public final class GameModel implements IModel {
/**
* An abstract factory to create APlayers. Used privately by GameModel.
*/
private static interface IMakePlayer {
/**
* Instantiates an APlayer object given the player's "player number".
* Player number 0 plays first, player number 1 plays second.
* @param playerNo The player number for the player to be instantiated.
* @return APlayer object
*/
public APlayer create(int playerNo);
}
/**
* The maximum amount of time a player is alloted to take its turn.
*/
private int maxTurnTime = 15; // default time in seconds
/**
* For player management. Initalized to a null TurnControl object.
*/
private TurnControl turnControl = TurnControl.NullObject;
/**
* Adapter to talk to the view to display/clear a game piece ("token") or
* a String message.
*/
private ICommand iCommand;
/**
* Adapter to talk to the view to announce winner, draw, or reset.
*/
private IViewAdmin viewAdmin;
/**
* Adapter to talk to the view to tell that the human player needs to try a
* move.
*/
private ITurnAdmin turnAdmin;
/**
* The invariant, encapsulated rules and behaviors of a game.
*/
private IBoardModel boardModel;
/**
* Initializes this GameModel to a given IBoradModel and a max turn time.
* @param boardModel for example Othello or TicTacToe.
* @param maxTurnTime maximum allowable time to make the next move.
*/
public GameModel(IBoardModel boardModel, int maxTurnTime) {
this.boardModel = boardModel;
this.maxTurnTime = maxTurnTime;
}
// FOR STUDENTS TO COMPLETE IN THE LAB
private IRequestor requestor =
new IRequestor() {
public void setTokenAt(final int row, final int col, final int player,
final IRejectCommand rejectCommand) {
boardModel.makeMove(row, col, player,
new ICheckMoveVisitor() {
public void invalidMoveCase() {
// TO DO
}
public void validMoveCase() {
// TO DO
}
},
new IBoardStatusVisitor() {
public Object player0WonCase(IBoardModel host, Object param) {
// TO DO
return null;
}
public Object player1WonCase(IBoardModel host, Object param) {
// TO DO
return null;
}
public Object drawCase(IBoardModel host, Object param) {
// TO DO
return null;
}
public Object noWinnerCase(IBoardModel host, Object param) {
// TO DO
return null;
}
});
}
};
/**
* Initializes the adapter to talk to the view.
* @param command Adapter to talk to the view to display/clear a game piece
* ("token") or a String message.
*/
public void setCommand(ICommand command) {
iCommand = command;
}
public void reset() {
System.out.println("Resetting");
boardModel.reset();
boardModel.redrawAll(iCommand);
turnControl.setHalt();
}
/**
* Adds players created by the supplied factories to the TurnControl.
* Assumes that the players are IMakePlayer factory objects.
* Any existing players are lost. Player 0 starts the game.
* @param player0 Factory for the starting player.
* @param player1 Factory for the second player.
*/
public void setPlayers(Object player0, Object player1) {
// Last in/first play
turnControl = new TurnControl(((IMakePlayer) player1).create(1));
turnControl.addPlayer(((IMakePlayer) player0).create(0));
turnControl.setAdapters(viewAdmin, iCommand);
turnControl.run(maxTurnTime);
}
public void setViewAdmin(IViewAdmin viewAdmin, ITurnAdmin turnAdmin) {
this.viewAdmin = viewAdmin;
this.turnAdmin = turnAdmin;
}
public IBoardModel getBoardModel() {
return boardModel;
}
/**
* Returns a Vector filled with IMakePlayer factory objects.
* @return
*/
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";
}
});
v.addElement(new IMakePlayer() {
public APlayer create(int playerNo) {
return new ComputerPlayer(requestor, playerNo, GameModel.this,
new RandomMoveStrategy());
}
public String toString() {
return "Computer RandomMove";
}
});
v.addElement(new IMakePlayer() {
public APlayer create(int playerNo) {
return new ComputerPlayer(requestor, playerNo, GameModel.this,
new RandomValidMove());
}
public String toString() {
return "Computer RandomValidMove";
}
});
/*
// CODE TO ADD PLAYERS WITH OTHER KINDS OF NEXT MOVE STRATEGIES THAT
// STUDENTS ARE REQUIRED TO IMPLEMENT:
v.addElement(new IMakePlayer() {
public APlayer create(int playerNo) {
return new ComputerPlayer(requestor, playerNo, GameModel.this,
new MinMax(new MinMaxFac()));
}
public String toString() {
return "Computer w. MinMax";
}
});
v.addElement(new IMakePlayer() {
public APlayer create(int playerNo) {
return new ComputerPlayer(requestor, playerNo, GameModel.this,
new MinMax(new AlphaBetaFac()));
}
public String toString() {
return "Computer w. AlphaBeta";
}
});
v.addElement(new IMakePlayer() {
public APlayer create(int playerNo) {
return new ComputerPlayer(requestor, playerNo, GameModel.this,
new MinMax(new DepthFac(new AlphaBetaFac(),2)));
}
public String toString() {
return "Computer w. Depth 2";
}
});
v.addElement(new IMakePlayer() {
public APlayer create(int playerNo) {
return new ComputerPlayer(requestor, playerNo, GameModel.this,
new MinMax(new DepthFac(new AlphaBetaFac(),3)));
}
public String toString() {
return "Computer w. Depth 3";
}
});
*/
return v;
}
public void exit() {
reset();
}
/**
* Add a ComputerPlayer based using the INextMoveStrategy specified by the
* fully qualified (i.e. included package name) String classname.
* The strategy is assumed to have either a no-parameter constructor or a
* constructor that takes an IModel as an input parameter.
* An IMakePlayer factory is returned.
* @param className Fully qualified class name for an INextMoveStrategy subclass.
* @return IMakePlayer object that can construct a new Computer player with the supplied strategy.
*/
public Object addPlayer(final String className) {
final INextMoveStrategy strategy;
try {
java.lang.reflect.Constructor c = Class.forName(className).getConstructors()[0];
Object [][] args = new Object[][]{new Object[]{}, new Object[]{this}};
strategy = (INextMoveStrategy) c.newInstance(args[c.getParameterTypes().length]);
}
catch(Exception ex) {
iCommand.setMessage(ex.toString());