package com.captstudios.games.tafl.core.es.model; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Pool; import com.captstudios.games.tafl.core.consts.Constants; import com.captstudios.games.tafl.core.enums.BoardType; import com.captstudios.games.tafl.core.es.model.ai.optimization.BitBoard; import com.captstudios.games.tafl.core.es.model.ai.optimization.GameBoard; import com.captstudios.games.tafl.core.es.model.ai.optimization.moves.Move; import com.captstudios.games.tafl.core.es.model.ai.optimization.transposition.ZorbistHash; import com.captstudios.games.tafl.core.es.model.rules.RulesEngine; import com.roundtriangles.games.zaria.utils.ModifiableString; public class TaflBoard extends GameBoard { public BitBoard corners; public BitBoard nearCorners; public int center; public BitBoard nearCenter; private Vector2 position; public int selectedPiece; public int capturedKing; public RulesEngine rules; public ModifiableString boardString; public BoardType boardType; public Pool<Move> movePool; public OrthographicCamera camera; public TaflBoard(int dimensions, int pieceTypes, ZorbistHash zorbistHash, RulesEngine rulesEngine, OrthographicCamera camera) { super(dimensions, pieceTypes, zorbistHash); this.rules = rulesEngine; this.boardType = BoardType.getBoardType(dimensions); this.movePool = new Pool<Move>() { @Override protected Move newObject() { return new Move(this, boardSize); } }; this.camera = camera; initialize(); } private void initialize() { boardString = new ModifiableString(boardSize); this.position = new Vector2(); this.selectedPiece = Constants.BoardConstants.ILLEGAL_CELL; this.hashCode = super.hashCode(); capturedKing = Constants.BoardConstants.ILLEGAL_CELL; center = (dimensions/2) * dimensions + (dimensions / 2); nearCenter = new BitBoard(boardSize); nearCenter.set(center + 1); nearCenter.set(center - 1); nearCenter.set(center + dimensions); nearCenter.set(center - dimensions); corners = new BitBoard(boardSize); corners.set(0); corners.set(dimensions - 1); corners.set(boardSize - dimensions); corners.set(boardSize - 1); nearCorners = new BitBoard(boardSize); nearCorners.set(1); nearCorners.set(dimensions); nearCorners.set(dimensions - 2); nearCorners.set(dimensions * 2 - 1); nearCorners.set(boardSize - dimensions + 1); nearCorners.set(boardSize - dimensions * 2); nearCorners.set(boardSize - 2); nearCorners.set(boardSize - dimensions - 1); } public boolean canWalk(int piece, int destination) { return bitBoards[Constants.BoardConstants.KING].get(piece) || (center != destination && !corners.get(destination)); } public Vector2 getCellPosition(int cellId) { position.x = cellId % dimensions * boardType.tileSize + boardType.cellXOffset; position.y = cellId / dimensions * boardType.tileSize + boardType.cellYOffset + camera.position.y / 2; return position; } public Vector2 getCellPositionCenter(int cellId) { return getCellPosition(cellId).add( boardType.halfTile, boardType.halfTile); } public int getCellId(Vector2 screenPosition) { int x = (int)((screenPosition.x - boardType.cellXOffset) / boardType.tileSize); // to make sure we are not wrapping around to the other side // when we touch the edge of the board. x = Math.min(x, dimensions - 1); int y = (int)((screenPosition.y - boardType.cellYOffset - camera.position.y / 2) / boardType.tileSize); // leave some margin around the top as well if (y == dimensions) { y = dimensions - 1; } return y * dimensions + x; } public BitBoard blackBitBoard() { return bitBoards[Constants.BoardConstants.BLACK_TEAM]; } public BitBoard whiteBitBoard() { return bitBoards[Constants.BoardConstants.WHITE_TEAM]; } public BitBoard kingBitBoard() { return bitBoards[Constants.BoardConstants.KING]; } public int getKing() { if (!getKingCaptured()) { return bitBoards[Constants.BoardConstants.KING].nextSetBit(0); } return Constants.BoardConstants.ILLEGAL_CELL; } public boolean getKingCaptured() { return bitBoards[Constants.BoardConstants.KING].isEmpty(); } @Override public void addPiece(int team, int piece) { if (piece == capturedKing) { super.addPiece(Constants.BoardConstants.KING, piece); capturedKing = Constants.BoardConstants.ILLEGAL_CELL; } else { super.addPiece(team, piece); } } @Override public void removePieces(int team, BitBoard pieces) { super.removePieces(team, pieces); if (bitBoards[Constants.BoardConstants.KING].intersects(pieces)) { capturedKing = getKing(); bitBoards[Constants.BoardConstants.KING].clear(); } } @Override protected BitBoard getCapturedPieces(Move move) { return rules.getCapturedPieces(move); } @Override public String toString() { for (int i = 0; i < boardSize; i++) { boardString.setChar(i, Constants.BoardConstants.EMPTY_CELL); } BitBoard bitBoard = bitBoards[Constants.BoardConstants.WHITE_TEAM]; for (int i = bitBoard.nextSetBit(0); i >= 0; i = bitBoard.nextSetBit(i+1)) { boardString.setChar(i, Constants.BoardConstants.WHITE_PIECE); } bitBoard = bitBoards[Constants.BoardConstants.BLACK_TEAM]; for (int i = bitBoard.nextSetBit(0); i >= 0; i = bitBoard.nextSetBit(i+1)) { boardString.setChar(i, Constants.BoardConstants.BLACK_PIECE); } if (!bitBoards[Constants.BoardConstants.KING].isEmpty()) { boardString.setChar(getKing(), Constants.BoardConstants.KING_PIECE); } return boardString.toString(); } }