class PatternFinder {

	public static long getHash(Board board, short p, int minStones,
			short lastMove) {
		CoordinateSystem coords = board.getCoordinateSystem();
		long result = 0L;
		int row = coords.row(p);
		int column = coords.column(p);
		int stonesSeen = 0;
		// TODO Verify (in a test) that this finds distant patterns
		for (int i = 0; i < patternSizes.length - 1; i++) {
			for (int j = patternSizes[i]; j < patternSizes[i + 1]; j++) {
				int newRow = row + offsets[j][0];
				int newColumn = column + offsets[j][1];
				if (coords.isValidOneDimensionalCoordinate(newRow)
						&& coords.isValidOneDimensionalCoordinate(newColumn)) {
					short point = coords.at(newRow, newColumn);
					Color color = board.getColorAt(point);
					if (color == board.getColorToPlay()) {
						if (board.getLiberties(point).size() == 1) {
							result ^= POINT_HASHES[FRIENDLY_IN_ATARI][j];
						} else if (board.getLiberties(point).size() == 2) {
							result ^= POINT_HASHES[FRIENDLY_2_LIBERTIES][j];
						} else {
							result ^= POINT_HASHES[FRIENDLY_3_OR_MORE_LIBERTIES][j];
						}
						stonesSeen++;
					} else if (color == board.getColorToPlay().opposite()) {
						int lastMoveIncrease = lastMove == point ? LAST_MOVE_INCREASE : 0;
						if (board.getLiberties(point).size() == 1) {
							result ^= POINT_HASHES[ENEMY_IN_ATARI + lastMoveIncrease][j];
						} else if (board.getLiberties(point).size() == 2) {
							result ^= POINT_HASHES[ENEMY_2_LIBERTIES + lastMoveIncrease][j];
						} else {
							result ^= POINT_HASHES[ENEMY_3_OR_MORE_LIBERTIES + lastMoveIncrease][j];
						}
						stonesSeen++;
					}
				} else {
					result ^= POINT_HASHES[OFF_BOARD][j];
				}
			}
			if (stonesSeen >= minStones) {
				return result;
			}
		}
		return result;
	}

}