// BoardConstants.java package net.sf.gogui.go; /** Some values that are constant for a given board size. Instances of this class are immutable. */ public final class BoardConstants { /** Get board constants for a given board size. The instance is created if it did not exist before, otherwise a reference to the existing one is returned. The creation is done in a thread-safe way. @param boardSize The new board size (number of points per row / column) in the range from one to GoPoint.MAX_SIZE @return The board constants. */ public static BoardConstants get(int boardSize) { synchronized (s_boardConstants) { if (s_boardConstants[boardSize] == null) s_boardConstants[boardSize] = new BoardConstants(boardSize); } return s_boardConstants[boardSize]; } public ConstPointList getAdjacent(GoPoint p) { return m_adjacent[p.getIndex()]; } /** Get location of handicap stones. The handicap stone locations are defined as in the GTP version 2 specification (section 4.1.1 Fixed Handicap Placement). Even board sizes and sizes smaller than 9 support up to 4 handicap stones; other sizes up to 9 handicap stones. @param n The number of handicap stones. @return List of points (go.Point) corresponding to the handicap stone locations; null if handicap locations are not defined for this combination of number of handicap stones and board size; empty list for zero handicap stones. */ public ConstPointList getHandicapStones(int n) { PointList result = new PointList(9); if (n == 0) return result; int line1 = m_handicapLine1; int line2 = m_handicapLine2; int line3 = m_handicapLine3; if (line1 < 0) return null; if (n == 1 || n > 9 || (n > 4 && line2 < 0)) return null; if (n >= 1) result.add(GoPoint.get(line1, line1)); if (n >= 2) result.add(GoPoint.get(line3, line3)); if (n >= 3) result.add(GoPoint.get(line1, line3)); if (n >= 4) result.add(GoPoint.get(line3, line1)); if (n >= 5 && n % 2 != 0) { result.add(GoPoint.get(line2, line2)); --n; } if (n >= 5) result.add(GoPoint.get(line1, line2)); if (n >= 6) result.add(GoPoint.get(line3, line2)); if (n >= 7) result.add(GoPoint.get(line2, line1)); if (n >= 8) result.add(GoPoint.get(line2, line3)); return result; } /** Get list containing all points on the board. */ public ConstPointList getPoints() { return m_allPoints; } /** Get board size. */ public int getSize() { return m_size; } /** Check if line is on the edge of the board. @param i The value of the constant coordinate shared by all points on the line. @return <code>true</code>, if the constant coordinate has the smallest or largest possible value (<code>0</code> or <code>getSize() - 1</code>). */ public boolean isEdgeLine(int i) { return (i == 0 || i == m_size - 1); } /** Check if line is a line containing handicap points. @param i The value of the constant coordinate shared by all points on the line. @return <code>true</code>, if the line contains handicap points. @see #getHandicapStones */ public boolean isHandicapLine(int i) { return (i == m_handicapLine1 || i == m_handicapLine2 || i == m_handicapLine3); } /** Check if point is a potential location of a handicap stone. @param p The point to check. @return true, if point is a potential location of a handicap stone. @see #getHandicapStones */ public boolean isHandicap(GoPoint p) { int x = p.getX(); int y = p.getY(); return (isHandicapLine(x) && isHandicapLine(y)); } private static BoardConstants[] s_boardConstants = new BoardConstants[GoPoint.MAX_SIZE + 1]; private final int m_size; private final int m_handicapLine1; private final int m_handicapLine2; private final int m_handicapLine3; private final PointList m_allPoints; private final ConstPointList[] m_adjacent; private BoardConstants(int size) { m_size = size; if (size >= 13) { m_handicapLine1 = 3; m_handicapLine3 = size - 4; } else if (size >= 7) { m_handicapLine1 = 2; m_handicapLine3 = size - 3; } else { m_handicapLine1 = -1; m_handicapLine3 = -1; } if (size >= 9 && size % 2 != 0) m_handicapLine2 = size / 2; else m_handicapLine2 = -1; m_allPoints = new PointList(); m_adjacent = new ConstPointList[GoPoint.NUMBER_INDEXES]; for (int x = 0; x < m_size; ++x) for (int y = 0; y < m_size; ++y) { GoPoint p = GoPoint.get(x, y); m_allPoints.add(p); PointList adjacent = new PointList(); if (x > 0) adjacent.add(GoPoint.get(x - 1, y)); if (x < m_size - 1) adjacent.add(GoPoint.get(x + 1, y)); if (y > 0) adjacent.add(GoPoint.get(x, y - 1)); if (y < m_size - 1) adjacent.add(GoPoint.get(x, y + 1)); m_adjacent[p.getIndex()] = adjacent; } } }