package snakes;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class Game {
private List<ISquare> squares;
private int size;
private Queue<Player> players;
private Player winner;
private boolean invariant() {
return squares.size() > 3
&& size == squares.size()
&& players.size() > 1;
}
public Game(int size, Player[] initPlayers) {
this.size = size;
this.addSquares(size);
this.addPlayers(initPlayers);
assert invariant();
}
public boolean isValidPosition(int position) {
return position>=1 && position<=size;
}
public static void main(String args[]) {
(new SimpleGameTest()).newGame().play(new Die());
}
public void play(Die die) {
System.out.println("Initial state: " + this);
while (this.notOver()) {
int roll = die.roll();
System.out.println(this.currentPlayer() + " rolls " + roll + ": " + this);
this.movePlayer(roll);
}
System.out.println("Final state: " + this);
System.out.println(this.winner() + " wins!");
}
public boolean notOver() {
return winner == null;
}
public boolean isOver() {
return !this.notOver();
}
public Player currentPlayer() {
return players.peek();
}
public void movePlayer(int roll) {
assert roll>=1 && roll<=6;
Player currentPlayer = players.remove(); // from front of queue
currentPlayer.moveForward(roll);
players.add(currentPlayer); // to back of the queue
if (currentPlayer.wins()) {
winner = currentPlayer;
}
assert invariant();
}
public void setSquare(int position, ISquare square) {
// Do not change the type of the first or last square!
assert !this.getSquare(position).isLastSquare()
&& !this.getSquare(position).isFirstSquare();
this.initSquare(position, square);
assert invariant();
}
public Player winner() {
return winner;
}
public ISquare firstSquare() {
return squares.get(0);
}
public ISquare getSquare(int position) {
assert this.isValidPosition(position);
return squares.get(position - 1);
}
public String toString() {
StringBuffer buffer = new StringBuffer();
for (ISquare square : squares) {
buffer.append(square.toString());
}
return buffer.toString();
}
private void addSquares(int size) {
squares = new ArrayList<ISquare>();
for(int i=0; i<size; i++) {
Square square = new Square(this, i+1);
squares.add(square);
}
this.initSquare(1, new FirstSquare(this, 1));
this.initSquare(size, new LastSquare(this, size));
}
private void addPlayers(Player[] initPlayers) {
players = new LinkedList<Player>();
for (Player player : initPlayers) {
player.joinGame(this);
players.add(player);
}
}
private void initSquare(int position, ISquare square) {
assert this.isValidPosition(position) && square != null;
squares.set(position-1, square);
}
public void setSquareToLadder(int position, int transport) {
this.setSquare(position, new Ladder(transport, this, position));
}
public void setSquareToSnake(int position, int transport) {
this.setSquare(position, new Snake(transport, this, position));
}
public ISquare findSquare(int position, int moves) {
assert position + moves <= 2*size - 1; // can't go more than size-1 moves backwards past end
int target = position + moves;
if (target > size) { // reverse direction if we go past the end
target = size - (target - size);
}
return this.getSquare(target);
}
}