private void getChildren(boolean setStringMoves) { dbh.getCharArray(oldPosition); int counter = 0; // looks at every spot on the board for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { // only a valid child if there is an empty space there if (board[row][col].getPiece() == ' ') { Cell place = board[row][col]; Cell[] neighbors = place.getNeighbors(); // looks at each spot around the given spot for (int index = 0; index < 8; index++) { // makes sure the spot is within bounds, then checks if // there is an opposing piece next to it Cell neighbor = neighbors[index]; if (neighbor != null && neighbor.getPiece() == pieces[opposite(turn)] && isFlippable(place.boardNum, index, false, null)) { if (setStringMoves) { stringMoves[counter] = (char) (col + 'A') + Integer.toString(row + 1); } System.arraycopy(oldPosition, 0, tempPosition, 0, boardSize); isFlippable(place.boardNum, index, true, tempPosition); int newWhitePieces = count(tempPosition); int nextTier = getTier() + 1; children[counter].tier = nextTier; children[counter].hash = offsetTable[nextTier][opposite(turn)][newWhitePieces] + dbh.setNumsAndHash(tempPosition); counter++; dbh.setNumsAndHash(oldPosition); break; } } } } } if (setStringMoves && counter == 0) { turn = opposite(turn); getChildren(false); if (numChildren > 0) { stringMoves[0] = "pass"; children[0].tier = getTier(); children[0].hash = getHash(); counter = 1; } turn = opposite(turn); } numChildren = counter; isChildrenValid = true; }
@Override public void nextHashInTier() { if (dbh.getHash() < dbh.numHashes() - 1) dbh.next(); else if (numPieces[BLACK] == 0) { numPieces[BLACK] = numPieces[WHITE]; numPieces[WHITE] = 0; dbh.setNums(boardSize - getTier(), 0, getTier()); if (turn != 0) throw new RuntimeException("Tier finished"); else turn++; } else { dbh.setNums(boardSize - getTier(), ++numPieces[WHITE], --numPieces[BLACK]); } isChildrenValid = false; }
@Override public String stateToString() { String answer = ""; answer += (this.turn == BLACK ? 'X' : 'O'); for (int boardNumber = 0; boardNumber < boardSize; boardNumber++) { answer += dbh.get(boardNumber); } return answer; }
private void unhash(int tier, long hash) { if (hash >= offsetTable[tier][BLACK][0]) { turn = BLACK; } else { turn = WHITE; } int offset = Arrays.binarySearch(offsetTable[tier][turn], hash); if (offset < 0) offset = -offset - 2; hash -= offsetTable[tier][turn][offset]; numPieces[WHITE] = offset; numPieces[BLACK] = tier - offset; dbh.setNums(boardSize - tier, numPieces[WHITE], numPieces[BLACK]); dbh.unhash(hash); char[] charBoard = new char[boardSize]; dbh.getCharArray(charBoard); for (int i = 0; i < boardSize; i++) { board[i / width][i % width].setPiece(charBoard[i]); } }
@Override public void setStartingPosition(int n) { numPieces[BLACK] = numPieces[WHITE] = 0; dbh.setNums(boardSize, 0, 0); board[height / 2 - 1][width / 2 - 1].setPiece('X'); board[height / 2][width / 2 - 1].setPiece('O'); board[height / 2 - 1][width / 2].setPiece('O'); board[height / 2][width / 2].setPiece('X'); turn = BLACK; isChildrenValid = false; }
public Reversi(Configuration conf) { super(conf); width = conf.getInteger("gamesman.game.width", 8); height = conf.getInteger("gamesman.game.height", 8); boardSize = width * height; board = new Cell[height][width]; dbh = new DartboardHasher(boardSize, ' ', 'O', 'X'); offsetTable = new long[boardSize + 1][2][]; // initialize offset table for (int tier = 0; tier <= boardSize; tier++) { long total = 0; for (int turn = 0; turn < 2; turn++) { offsetTable[tier][turn] = new long[tier + 1]; for (int offset = 0; offset <= tier; offset++) { dbh.setNums(boardSize - tier, offset, tier - offset); offsetTable[tier][turn][offset] = total; total += dbh.numHashes(); } } } for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { board[row][col] = new Cell(row, col, row * width + col); } } turn = BLACK; board[height / 2 - 1][width / 2 - 1].setPiece('X'); board[height / 2][width / 2 - 1].setPiece('O'); board[height / 2 - 1][width / 2].setPiece('O'); board[height / 2][width / 2].setPiece('X'); isChildrenValid = false; children = newStateArray(maxChildren()); stringMoves = new String[maxChildren()]; // only for testing. oldPosition = new char[boardSize]; tempPosition = new char[boardSize]; }
@Override public String displayState() { StringBuilder sb = new StringBuilder((width + 1) * 2 * (height + 1)); for (int row = height - 1; row >= 0; row--) { sb.append(row + 1); for (int col = 0; col < width; col++) { sb.append(" "); char piece = dbh.get(row * width + col); if (piece == ' ') sb.append('-'); else if (piece == 'X' || piece == 'O') sb.append(piece); else throw new Error(piece + " is not a valid piece"); } sb.append("\n"); } sb.append(" "); for (int col = 0; col < width; col++) { sb.append(" "); sb.append((char) ('A' + col)); } sb.append("\n"); return sb.toString(); }
@Override public void setFromString(String pos) { if (pos.length() != boardSize + 1) throw new Error("Bad String - wrong length: " + pos.length() + " != " + boardSize); char[] posArray = pos.toCharArray(); char turn = posArray[0]; if (turn == 'X') this.turn = BLACK; else if (turn == 'O') this.turn = WHITE; else throw new Error("Bad turn"); char[] woTurn = Arrays.copyOfRange(posArray, 1, posArray.length - 1); numPieces[BLACK] = 0; numPieces[WHITE] = 0; for (int i = 0; i < woTurn.length; i++) { if (woTurn[i] == 'X') { numPieces[BLACK]++; } else if (woTurn[i] == 'O') { numPieces[WHITE]++; } } dbh.setNumsAndHash(woTurn); isChildrenValid = false; }
@Override public boolean hasNextHashInTier() { long currentHash = dbh.getHash(); return (currentHash != numHashesForTier(getTier()) - 1); }
private long getHash() { return offsetTable[getTier()][turn][numPieces[WHITE]] + dbh.getHash(); }