gt: 				p.setLocation(p.x, BattleshipModel.BOARD_SIZE - 1);
context: /*
   * JOGRE (Java Online Gaming Real-time Engine) - Battleship
   * Copyright (C) 2004  Bob Marks (marksie531@yahoo.com)
   * http://jogre.sourceforge.org
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   */
  package org.jogre.battleship.client;
  
  import java.awt.Point;
  
  import nanoxml.XMLElement;
  
  import org.jogre.common.JogreModel;
  import org.jogre.common.Player;
  import org.jogre.common.comm.Comm;
  import org.jogre.common.util.JogreUtils;
  
  /**
   * Battleship model
   * 
   * @author Gman, JavaRed
   * @version Alpha 0.2.3
   */
  public class BattleshipModel extends JogreModel {
  
  	// Cell constants
  	public static final int BLANK = 0;
  	public static final int MISS = 1;
  	public static final int HIT = 2;
  
  	// Ship constants
  	public static final int CARRIER = 1;
  	public static final int BATTLESHIP = 2;
  	public static final int DESTROYER = 3;
  	public static final int CRUISER = 4;
  	public static final int PTBOAT = 5;
  	public static final int GAME_STATE_PLACING_SHIPS = 0;
  	public static final int GAME_STATE_PLAYING = 1;
  	public static final Point OFFSCREEN_POINT = new Point(-1, -1);	
  	public static final int [] SHIP_NAMES = {CARRIER, BATTLESHIP, DESTROYER, CRUISER, PTBOAT};
  	public static final int [] SHIP_SIZES = {5, 4, 3, 3, 2};	
  	public static final int BOARD_SIZE = 10;	// Board size will always be 10x10 for Battleship
  
  	// XML constants
  	private static final String XML_PLAYER = "player";
  	private static final String XML_ATT_PLACED_SHIPS = "placed_ships";
  	private static final String XML_ATT_HITS_MISSES  = "hits_misses";
  	private static final String XML_ATT_SHIPS_PLACED = "ships_placed";
  	private static final String XML_ATT_SHIPS_PLACED_HOR = "ships_places_hor";
  	
  	// Game data
  	private int[][][] placedShips = new int[2][BOARD_SIZE][BOARD_SIZE];
  	private int[][][] hitsAndMisses = new int[2][BOARD_SIZE][BOARD_SIZE];
  	
  	// Current ship placement data
  	private int[] shipsPlaced = new int[2];
  	private boolean[] shipPlacedHorizontally = new boolean[2];
  	
  	// Game state and seat information
  	private int gameState = GAME_STATE_PLACING_SHIPS;
  	private int seatNum = Player.NOT_SEATED;
  	
  	// Points to keep track of
  	private Point boardPlacingPoint = null;
  	private Point boardFiringPoint = null;
  	private Point mousePressedPoint = null;
  	
  	/**
  	 * Constructor
  	 */
  	public BattleshipModel() {
  		super();
  	}
  
  	/**
  	 * Start method which calls reset method (resets the model)
  	 */
  	public void start() {
  		reset ();
  	}
  
  	/**
  	 * Reset model
  	 */
  	public void reset() {
  		
  		// Reset "placed ships" and "hits and misses"
  		for (int x = 0; x < BattleshipModel.BOARD_SIZE; x++) {
  			for (int y = 0; y < BattleshipModel.BOARD_SIZE; y++) {
  				for (int p = 0; p < 2; p++) {
  					this.placedShips[p][x][y] = BLANK;
  					this.hitsAndMisses[p][x][y] = BLANK;
  				}
  			}
  		}
  		
  		// Reset game state and placing ship index
  		this.gameState = GAME_STATE_PLACING_SHIPS;
  		this.shipPlacedHorizontally = new boolean[2];
  		this.shipsPlaced = new int[2];
  		
  		// Refresh observers after reset
  		refreshObservers();
  	}
  	
  	/**
  	 * Check if coordinates are a valid move
  	 * 
  	 * @param x
  	 * @param y
  	 * @return true if valid move, false otherwise
  	 */
  	public boolean isValidMove(int seatNum, int x, int y) {
  		if (x > -1 && x < BOARD_SIZE && y > -1 && y < BOARD_SIZE)
  			return hitsAndMisses[seatNum][x][y] == BLANK;
  		return false;
  	}
  	
  	/**
  	 * Set move in battleship
  	 * 
  	 * @param seatNum
  	 * @param x
  	 * @param y
  	 */
  	public void setMove(int seatNum, int x, int y) {
  		int opponent = JogreUtils.invert(seatNum);
  		if (this.placedShips[opponent][x][y] != BLANK) {
  			this.hitsAndMisses[seatNum][x][y] = HIT;
  		} else {
  			this.hitsAndMisses[seatNum][x][y] = MISS;
  		}
  		
  		refreshObservers();
  	}
  	
  	/**
  	 * Check if game has been won
  	 * 
  	 * @param seatNum
  	 * @return true if game has been won by seat num provided, false otherwise
  	 */
  	public boolean isGameWon(int seatNum) {
  		int opponentSeatNum = JogreUtils.invert(seatNum);
  		
  		for (int i = 0; i < BattleshipModel.SHIP_NAMES.length; i++) {
  			if (!this.sunkShip(opponentSeatNum, BattleshipModel.SHIP_NAMES[i]))
  				return false;
  		}
  		return true;
  	}
  	
  	/**
  	 * Set game state
  	 * 
  	 * @param gameState
  	 */
  	public void setGameState(int gameState) {
  		this.gameState = gameState;
  	}
  	
  	/**
  	 * Get game state
  	 * 
  	 * @return game state
  	 */
  	public int getGameState() {
  		return this.gameState;
  	}
  	
  	/**
  	 * Get board point based off of mouse x and y
  	 * 
  	 * @param mouseX
  	 * @param mouseY
  	 * @return board point
  	 */
  	public Point getBoardPoint(int mouseX, int mouseY) {
  		int x = mouseX / (BattleshipBoardComponent.CELL_SIZE + BattleshipBoardComponent.CELL_SPACING);
  		int y = mouseY / (BattleshipBoardComponent.CELL_SIZE + BattleshipBoardComponent.CELL_SPACING);
  		return new Point(x, y);
  	}
  	
  	/**
  	 * Check if placement is valid for a ship
  	 * 
  	 * @param x
  	 * @param y
  	 * @param ship
  	 * @param horizontal
  	 * @return true if ship can be placed, otherwise false
  	 */
  	public boolean validPlacementForShip(int seatNum, Point p) {
  
  		// Get ship properties
  		p = getShipIndexPoint(seatNum, p, isShipPlacedHorizontally(seatNum));
  		int x = p.x;
  		int y = p.y;
  		int size = BattleshipModel.SHIP_SIZES[this.shipsPlaced[seatNum]];
  		
  		// Check horizontally
  		if (this.shipPlacedHorizontally[seatNum]) {
  
  			// Check bounds
  			if (x < 0 || y < 0 || (x + size) > BattleshipModel.BOARD_SIZE || y >= BattleshipModel.BOARD_SIZE)
  				return false;
  			
  			// Check if a ship is already placed within the path
  			for (int xx = x; xx < x+size; xx++) {
  				if (this.placedShips[seatNum][xx][y] != BLANK)
  					return false;
  			}
  		
  		// Check vertically
  		} else {
  			
  			// Check bounds
  			if (x < 0 || y < 0 || x >= BattleshipModel.BOARD_SIZE || (y + size) > BattleshipModel.BOARD_SIZE)
  				return false;
  			
  			// Check if a ship is already placed within the path
  			for (int yy = y; yy < y+size; yy++) {
  				if (placedShips[seatNum][x][yy] != BLANK)
  					return false;
  			}
  		}
  		
  		// Ship placement is valid
  		return true;
  	}
  	
  	/**
  	 * Place ship
  	 * 
  	 * @param seatNum
  	 * @param p
  	 */
  	public void placeShip(int seatNum, Point p) {
  		int size = BattleshipModel.SHIP_SIZES[this.shipsPlaced[seatNum]];
  		int ship = BattleshipModel.SHIP_NAMES[this.shipsPlaced[seatNum]];
  		boolean horizontal = this.shipPlacedHorizontally[seatNum];
  		placeShip(seatNum, p, size, ship, horizontal);
  	}
  	
  	/**
  	 * Place ship
  	 * 
  	 * @param seatNum
  	 * @param p
  	 * @param size
  	 * @param ship
  	 * @param horizontal
  	 */
  	public void placeShip(int seatNum, Point p, int size, int ship, boolean horizontal) {
  
  		// Get ship properties
  		p = getShipIndexPoint(seatNum, p, horizontal);
  		int x = p.x;
  		int y = p.y;
  		
  		// Fill in placedShips array with ship name
  		if (horizontal) {
  			for (int xx = x; xx < x+size; xx++)
  				this.placedShips[seatNum][xx][y] = ship;
  		} else {
  			for (int yy = y; yy < y+size; yy++)
  				this.placedShips[seatNum][x][yy] = ship;
  		}
  		
  		// Increment ships placed
  		this.shipsPlaced[seatNum]++;		
  		this.refreshObservers();
  	}
  	
  	/**
  	 * Set mouse board point when placing ships
  	 * 
  	 * @param boardPlacingPoint
  	 */
  	public void setBoardPlacingPoint(Point boardPlacingPoint) {
  		int seatNum = getSeatNum();
  		if (boardPlacingPoint != null && seatNum != Player.NOT_SEATED)
  			this.boardPlacingPoint = getShipIndexPoint(seatNum, boardPlacingPoint, isShipPlacedHorizontally(seatNum));
  		else
  			this.boardPlacingPoint = null;
  	}
  	
  	/**
  	 * Set mouse board point when firing at ships
  	 * 
  	 * @param boardFiringPoint
  	 */
  	public void setBoardFiringPoint(Point p) {
  		if (p != null) {
  			if (p.x < (BattleshipModel.BOARD_SIZE + 1))
  				p.setLocation(BattleshipModel.BOARD_SIZE + 1, p.y);
  			if (p.y < 0)
  				p.setLocation(p.x, 0);
  			if (p.x > (BattleshipModel.BOARD_SIZE * 2))
  				p.setLocation((BattleshipModel.BOARD_SIZE * 2), p.y);
  			if (p.y > BattleshipModel.BOARD_SIZE)
  