/* * Copyright (C) 2012 JPII and contributors * * 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 3 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, see <http://www.gnu.org/licenses/>. */ package com.jpii.navalbattle.pavo.grid; import java.io.Serializable; import com.jpii.navalbattle.pavo.PavoHelper; import com.jpii.navalbattle.pavo.World; import maximusvladimir.dagen.Rand; public class Location implements Serializable { private static final long serialVersionUID = 1L; private int row; private int col; private boolean isunknown = false; public static Location Unknown = new Location(5,5,5,5); private Location(int c, int d, int a, int b) { row = -1; col = -1; isunknown = true; } public static Location random(World w,Rand provider) { return new Location( provider.nextInt(PavoHelper.getGameWidth(w.getWorldSize())), provider.nextInt(PavoHelper.getGameHeight(w.getWorldSize()))); } public boolean isUnknown() { return isunknown; } /** * The turn angle for turning 90 degrees to the left. */ public static final int LEFT = -90; /** * The turn angle for turning 90 degrees to the right. */ public static final int RIGHT = 90; /** * The turn angle for turning 45 degrees to the left. */ public static final int HALF_LEFT = -45; /** * The turn angle for turning 45 degrees to the right. */ public static final int HALF_RIGHT = 45; /** * The turn angle for turning a full circle. */ public static final int FULL_CIRCLE = 360; /** * The turn angle for turning a half circle. */ public static final int HALF_CIRCLE = 180; /** * The turn angle for making no turn. */ public static final int AHEAD = 0; /** * The compass direction for north. */ public static final int NORTH = 0; /** * The compass direction for northeast. */ public static final int NORTHEAST = 45; /** * The compass direction for east. */ public static final int EAST = 90; /** * The compass direction for south-east. */ public static final int SOUTHEAST = 135; /** * The compass direction for south. */ public static final int SOUTH = 180; /** * The compass direction for south-west. */ public static final int SOUTHWEST = 225; /** * The compass direction for west. */ public static final int WEST = 270; /** * The compass direction for northwest. */ public static final int NORTHWEST = 315; /** * Constructs a location with given row and column coordinates. * @param r the row * @param c the column */ public Location(int r, int c) { row = r; col = c; } /** * Gets the row coordinate. * @return the row of this location */ public int getRow() { return row; } /** * Gets the column coordinate. * @return the column of this location */ public int getCol() { return col; } /** * Gets the adjacent location in any one of the eight compass directions. * @param direction the direction in which to find a neighbor location * @return the adjacent location in the direction that is closest to * <tt>direction</tt> */ public Location getAdjacentLocation(int direction) { int adjustedDirection = (direction + HALF_RIGHT / 2) % FULL_CIRCLE; if (adjustedDirection < 0) adjustedDirection += FULL_CIRCLE; adjustedDirection = (adjustedDirection / HALF_RIGHT) * HALF_RIGHT; int dc = 0; int dr = 0; if (adjustedDirection == EAST) dc = 1; else if (adjustedDirection == SOUTHEAST) { dc = 1; dr = 1; } else if (adjustedDirection == SOUTH) dr = 1; else if (adjustedDirection == SOUTHWEST) { dc = -1; dr = 1; } else if (adjustedDirection == WEST) dc = -1; else if (adjustedDirection == NORTHWEST) { dc = -1; dr = -1; } else if (adjustedDirection == NORTH) dr = -1; else if (adjustedDirection == NORTHEAST) { dc = 1; dr = -1; } return new Location(getRow() + dr, getCol() + dc); } public double getDistanceFrom(Location target){ if(target.equals(Location.Unknown)) return 10000000.0; int dx = target.getCol() - getCol(); int dy = target.getRow() - getRow(); return Math.sqrt((Math.pow(dx, 2)+Math.pow(dy, 2))); } /** * Returns the direction from this location toward another location. The * direction is rounded to the nearest compass direction. * @param target a location that is different from this location * @return the closest compass direction from this location toward * <code>target</code> */ public int getDirectionToward(Location target) { int dx = target.getCol() - getCol(); int dy = target.getRow() - getRow(); int angle = (int) Math.toDegrees(Math.atan2(-dy, dx)); int compassAngle = RIGHT - angle; compassAngle += HALF_RIGHT / 2; if (compassAngle < 0) compassAngle += FULL_CIRCLE; return (compassAngle / HALF_RIGHT) * HALF_RIGHT; } /** * Indicates whether some other <code>Location</code> object is "equal to" * this one. * @param other the other location to test * @return <code>true</code> if <code>other</code> is a * <code>Location</code> with the same row and column as this location; * <code>false</code> otherwise */ public boolean equals(Object other) { if (!(other instanceof Location)) return false; Location otherLoc = (Location) other; return getRow() == otherLoc.getRow() && getCol() == otherLoc.getCol(); } /** * Generates a hash code. * @return a hash code for this location */ public int hashCode() { return getRow() * 3737 + getCol(); } /** * Compares this location to <code>other</code> for ordering. Returns a * negative integer, zero, or a positive integer as this location is less * than, equal to, or greater than <code>other</code>. Locations are * ordered in row-major order. <br /> * (Precondition: <code>other</code> is a <code>Location</code> object.) * @param other the other location to test * @return a negative integer if this location is less than * <code>other</code>, zero if the two locations are equal, or a positive * integer if this location is greater than <code>other</code> */ public int compareTo(Object other) { Location otherLoc = (Location) other; if (getRow() < otherLoc.getRow()) return -1; if (getRow() > otherLoc.getRow()) return 1; if (getCol() < otherLoc.getCol()) return -1; if (getCol() > otherLoc.getCol()) return 1; return 0; } /** * Creates a string that describes this location. * @return a string with the row and column of this location, in the format * (row, col) */ public String toString() { if (isUnknown()) return "Imaginary space @"+super.toString(); else return "(" + getRow() + ", " + getCol() + ") @"+super.hashCode(); } public static boolean isValid(Location l,EntityManager em) { if (l.getCol() < 0 || l.getRow() < 0) return false; if (l.getCol() >= PavoHelper.getGameWidth(em.getWorld().getWorldSize())*2 || l.getRow() >= PavoHelper.getGameHeight(em.getWorld().getWorldSize())*2) return false; return true; } }