Mert Us Matthew Hannay Logan Starr
Dependencies: mbed 4DGL-uLCD-SE
main.cpp
- Committer:
- mhannay3
- Date:
- 24 months ago
- Revision:
- 10:8f73a917b239
- Parent:
- 9:1f33c0f299ae
- Child:
- 12:7ef20deb9d5e
File content as of revision 10:8f73a917b239:
#include "mbed.h" #include "uLCD_4DGL.h" #include <vector> uLCD_4DGL uLCD(p28,p27,p30); // serial tx, serial rx, reset pin; enum Piece {e, wK, bK, wQ, bQ, wR, bR, wB, bB, wN, bN, w, b}; std::vector<Piece> whitePieces; std::vector<Piece> blackPieces; enum GameState {whiteSelecting, whitePickedUp, whiteAI, blackSelecting, blackPickedUp, blackAI}; struct pixelCoord { uint8_t x; uint8_t y; }; struct boardPos { uint8_t row; uint8_t column; bool operator==(const boardPos &other) const { return row == other.row && column && other.column; } }; class BoardState { private: Piece array[64]; public: // calculates the advantage difference for the board state float calculateBoardState() { return 0.0; } // returns the piece at a given location Piece getPiece(int row, int column) { return array[column + 8 * row]; } // puts a piece at a given location void placePiece(Piece piece, int row, int column) { array[column + 8 * row] = piece; } /* removes a piece from the set position of the board returns the bit representation of the piece */ Piece removePiece(int row, int column) { Piece removedPiece = array[column + 8 * row]; array[column + 8 * row] = e; return removedPiece; } /* moves a piece from one position to another returns the captured piece */ Piece movePiece(int startRow, int startColumn, int endRow, int endColumn) { Piece movingPiece = removePiece(startRow, startColumn); Piece capturedPiece = removePiece(endRow, endColumn); placePiece(movingPiece, endRow, endColumn); return capturedPiece; } // generates a list of possible moves for a piece // returns moves std::vector<boardPos> getMoves(boardPos pos) { return getMoves(pos.row, pos.column); } std::vector<boardPos> getMoves(int row, int column) { std::vector<boardPos> moves; std::vector<boardPos> lineMoves; Piece movingPiece = getPiece(row, column); bool isWhite; switch(movingPiece) { case wK: case bK: isWhite = movingPiece == wK; for (int i = -1; i <= 1; i++) { for (int j = -1; j <= 1; j++) { if (validMove(isWhite, row + i, column + j)) { moves.push_back((boardPos) { row + i, column + j }); } } } break; case wQ: case bQ: isWhite = movingPiece == wQ; lineMoves = movesInLine(isWhite, row, column, 1, 0); moves.insert(moves.end(), lineMoves.begin(), moves.end()); lineMoves = movesInLine(isWhite, row, column, -1, 0); moves.insert(moves.end(), lineMoves.begin(), moves.end()); lineMoves = movesInLine(isWhite, row, column, 0, 1); moves.insert(moves.end(), lineMoves.begin(), moves.end()); lineMoves = movesInLine(isWhite, row, column, 0, -1); moves.insert(moves.end(), lineMoves.begin(), moves.end()); lineMoves = movesInLine(isWhite, row, column, 1, 1); moves.insert(moves.end(), lineMoves.begin(), moves.end()); lineMoves = movesInLine(isWhite, row, column, -1, 1); moves.insert(moves.end(), lineMoves.begin(), moves.end()); lineMoves = movesInLine(isWhite, row, column, 1, -1); moves.insert(moves.end(), lineMoves.begin(), moves.end()); lineMoves = movesInLine(isWhite, row, column, -1, -1); moves.insert(moves.end(), lineMoves.begin(), moves.end()); break; case wB: case bB: isWhite = movingPiece == wB; lineMoves = movesInLine(isWhite, row, column, 1, 1); moves.insert(moves.end(), lineMoves.begin(), moves.end()); lineMoves = movesInLine(isWhite, row, column, -1, 1); moves.insert(moves.end(), lineMoves.begin(), moves.end()); lineMoves = movesInLine(isWhite, row, column, 1, -1); moves.insert(moves.end(), lineMoves.begin(), moves.end()); lineMoves = movesInLine(isWhite, row, column, -1, -1); moves.insert(moves.end(), lineMoves.begin(), moves.end()); break; case wN: case bN: isWhite = movingPiece == wN; for (int i = -1; i <= 1; i+=2) { for (int j = -1; j <= 1; j+=2) { if (validMove(isWhite, row + 2*i, column + j)) { moves.push_back((boardPos) { row + 2*i, column + j }); } if (validMove(isWhite, row + i, column + 2*j)) { moves.push_back((boardPos) { row + i, column + 2*j }); } } } break; case wR: case bR: isWhite = movingPiece == wR; lineMoves = movesInLine(isWhite, row, column, 1, 0); moves.insert(moves.end(), lineMoves.begin(), moves.end()); lineMoves = movesInLine(isWhite, row, column, -1, 0); moves.insert(moves.end(), lineMoves.begin(), moves.end()); lineMoves = movesInLine(isWhite, row, column, 0, 1); moves.insert(moves.end(), lineMoves.begin(), moves.end()); lineMoves = movesInLine(isWhite, row, column, 0, -1); moves.insert(moves.end(), lineMoves.begin(), moves.end()); break; case w: case b: isWhite = movingPiece == w; int rowChange = isWhite ? 1 : -1; if (validMove(isWhite, row + rowChange, column)) { moves.push_back((boardPos) { row + rowChange, column }); } if (validMove(isWhite, row + rowChange, column + 1) && getPiece(row + rowChange, column + 1) != e) { moves.push_back((boardPos) { row + rowChange, column + 1 }); } if (validMove(isWhite, row + rowChange, column - 1) && getPiece(row + rowChange, column - 1) != e) { moves.push_back((boardPos) { row + rowChange, column - 1 }); } break; } return moves; } // returns a vector of board positions that a piece can move in a line std::vector<boardPos> movesInLine(bool isMovingPieceWhite, int row, int column, int rowChange, int columnChange) { std::vector<boardPos> moves; for (int i = 1; ; i++) { // check if piece can move to location if (validMove(isMovingPieceWhite, row + i * rowChange, column + i * columnChange)) { moves.push_back((boardPos) { row + i * rowChange, column + i * columnChange }); // if piece is capturable, stop moving beyond it if (getPiece(row + i * rowChange, column + i * columnChange) != e) { break; } // if unable to move, break out } else { break; } } return moves; } // returns if a piece can move to a given location bool validMove(bool isMovingPieceWhite, int row, int column) { if (row < 0 || row > 7 || column < 0 || column > 7) { return false; } Piece capturedPiece = getPiece(row, column); switch(capturedPiece) { case wK: case wQ: case wR: case wB: case wN: case w: return !isMovingPieceWhite; case bK: case bQ: case bR: case bB: case bN: case b: return isMovingPieceWhite; case e: return true; } return false; } }; class GameBoard { private: BoardState boardState; static const int BOARD_DARK_COLOR = 0x769656; static const int BOARD_LIGHT_COLOR = 0xbaca44; static const int HOVER_COLOR = 0x0000ff; static const int SELECTED_COLOR = 0xff8800; static const int MOVE_COLOR = 0xff00ff; // gets the pixel coordinates of the top left of the square static pixelCoord getTopLeftOfSquare(boardPos pos) { return getTopLeftOfSquare(pos.row, pos.column); } static pixelCoord getTopLeftOfSquare(int row, int column) { pixelCoord topLeft; topLeft.x = 16 * column; topLeft.y = 112 - 16 * row; return topLeft; } // piece sprites (12 x 12) static void drawPawn(int row, int column, bool white, bool light) { int X = white ? 0xffffff : 0x000000; int _ = light ? BOARD_LIGHT_COLOR : BOARD_DARK_COLOR; int sprite[144] = {_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, X, X, _, _, _, _, _, _, _, _, _, X, X, X, X, _, _, _, _, _, _, _, _, X, X, X, X, _, _, _, _, _, _, _, _, _, X, X, _, _, _, _, _, _, _, _, _, _, X, X, _, _, _, _, _, _, _, _, _, X, X, X, X, _, _, _, _, _, _, X, X, X, X, X, X, X, X, _, _, _, _, X, X, X, X, X, X, X, X, _, _ }; pixelCoord tl = getTopLeftOfSquare(row, column); uLCD.BLIT(tl.x + 2, tl.y + 2, 12, 12, sprite); } static void drawRook(int row, int column, bool white, bool light) { int X = white ? 0xffffff : 0x000000; int _ = light ? BOARD_LIGHT_COLOR : BOARD_DARK_COLOR; int sprite[144] = {X, X, _, X, X, _, _, X, X, _, X, X, X, X, _, X, X, _, _, X, X, _, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, _, X, X, X, _, X, X, _, X, X, X, _, _, X, X, X, _, X, X, _, X, X, X, _, _, _, X, X, _, X, X, _, X, X, _, _, _, _, X, X, _, X, X, _, X, X, _, _, _, _, X, X, _, X, X, _, X, X, _, _, _, X, X, X, X, X, X, X, X, X, X, _, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X }; pixelCoord tl = getTopLeftOfSquare(row, column); uLCD.BLIT(tl.x + 2, tl.y + 2, 12, 12, sprite); } static void drawKnight(int row, int column, bool white, bool light) { int X = white ? 0xffffff : 0x000000; int _ = light ? BOARD_LIGHT_COLOR : BOARD_DARK_COLOR; int sprite[144] = {_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, X, X, _, X, X, _, _, _, _, _, _, _, X, X, _, X, X, _, _, _, _, _, X, X, X, X, X, X, _, _, _, _, _, X, X, X, X, X, _, X, _, _, _, _, _, X, X, X, X, X, X, X, _, _, _, _, _, _, _, _, X, X, X, X, _, _, _, _, _, _, _, X, X, X, X, X, _, _, _, _, _, _, X, X, X, X, X, X, X, _, _, _, _, X, X, X, X, X, X, X, X, _, _, _, X, X, X, X, X, X, X, X, X, X, _, _, X, X, X, X, X, X, X, X, X, X, _ }; pixelCoord tl = getTopLeftOfSquare(row, column); uLCD.BLIT(tl.x + 2, tl.y + 2, 12, 12, sprite); } static void drawBishop(int row, int column, bool white, bool light) { int X = white ? 0xffffff : 0x000000; int _ = light ? BOARD_LIGHT_COLOR : BOARD_DARK_COLOR; int sprite[144] = {_, _, _, _, _, X, X, _, _, _, _, _, _, _, _, _, X, X, X, _, _, _, _, _, _, _, _, X, X, X, _, _, X, _, _, _, _, _, _, X, X, _, _, X, X, _, _, _, _, _, _, X, X, X, X, X, X, _, _, _, _, _, _, _, X, X, X, X, _, _, _, _, _, _, _, _, _, X, X, _, _, _, _, _, _, _, _, _, X, X, X, X, _, _, _, _, _, _, _, X, X, X, X, X, X, _, _, _, _, _, _, X, X, X, X, X, X, _, _, _, _, _, X, X, X, X, X, X, X, X, _, _, _, _, X, X, X, X, X, X, X, X, _, _ }; pixelCoord tl = getTopLeftOfSquare(row, column); uLCD.BLIT(tl.x + 2, tl.y + 2, 12, 12, sprite); } static void drawQueen(int row, int column, bool white, bool light) { int X = white ? 0xffffff : 0x000000; int _ = light ? BOARD_LIGHT_COLOR : BOARD_DARK_COLOR; int sprite[144] = {_, _, _, _, _, X, X, _, _, _, _, _, _, _, X, _, _, X, X, _, _, X, _, _, X, _, X, X, _, X, X, _, X, X, _, X, X, _, X, X, _, X, X, _, X, X, _, X, X, _, X, X, _, X, X, _, X, X, _, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, _, X, X, X, X, X, X, _, X, X, X, X, X, X, _, X, X, _, X, X, X, X, _, X, X, X, X, X, X, X, X, X, X, _, _, _, X, X, X, X, X, X, X, X, _, _, _, X, X, X, X, X, X, X, X, X, X, _ }; pixelCoord tl = getTopLeftOfSquare(row, column); uLCD.BLIT(tl.x + 2, tl.y + 2, 12, 12, sprite); } static void drawKing(int row, int column, bool white, bool light) { int X = white ? 0xffffff : 0x000000; int _ = light ? BOARD_LIGHT_COLOR : BOARD_DARK_COLOR; int sprite[144] = {_, _, _, _, _, X, X, _, _, _, _, _, _, _, _, _, _, X, X, _, _, _, _, _, _, _, _, X, X, X, X, X, X, _, _, _, _, _, _, X, X, X, X, X, X, _, _, _, X, X, _, _, _, X, X, _, _, _, X, X, X, X, X, X, _, X, X, _, X, X, X, X, X, _, X, X, X, X, X, X, X, X, _, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, _, X, X, X, X, _, X, X, X, _, X, X, X, X, X, X, X, X, X, X, _, _, _, X, X, X, _, _, X, X, X, _, _, _, X, X, X, X, X, X, X, X, X, X, _ }; pixelCoord tl = getTopLeftOfSquare(row, column); uLCD.BLIT(tl.x + 2, tl.y + 2, 12, 12, sprite); } public: BoardState getBoardState() { return boardState; } void setBoardState(BoardState newBoardState) { boardState = newBoardState; } // initializes the starting board state GameBoard() { // draw board for (int row = 0; row < 8; row++) { for (int column = 0; column < 8; column++) { uint64_t color; if ((row + column) % 2 == 0) { color = BOARD_DARK_COLOR; } else { color = BOARD_LIGHT_COLOR; } pixelCoord tl = getTopLeftOfSquare(row, column); uLCD.filled_rectangle(tl.x, tl.y, tl.x + 15, tl.y + 15, color); } } // draw pieces placePieceAndDraw(wR, 0, 0); placePieceAndDraw(wN, 0, 1); placePieceAndDraw(wB, 0, 2); placePieceAndDraw(wQ, 0, 3); placePieceAndDraw(wK, 0, 4); placePieceAndDraw(wB, 0, 5); placePieceAndDraw(wN, 0, 6); placePieceAndDraw(wR, 0, 7); placePieceAndDraw(bR, 7, 0); placePieceAndDraw(bN, 7, 1); placePieceAndDraw(bB, 7, 2); placePieceAndDraw(bQ, 7, 3); placePieceAndDraw(bK, 7, 4); placePieceAndDraw(bB, 7, 5); placePieceAndDraw(bN, 7, 6); placePieceAndDraw(bR, 7, 7); for (int i = 0; i < 8; i++) { placePieceAndDraw(w, 1, i); placePieceAndDraw(b, 6, i); } } // PIECE MOVEMENT AND GRAPHICS FUNCTIONS // returns the piece at a given location Piece getPiece(boardPos pos) { return getPiece(pos.row, pos.column); } Piece getPiece(int row, int column) { return boardState.getPiece(row, column); } /* puts the bit representation of a piece at the set position of the board assumes that the position of the board is emptied beforehand */ void placePieceAndDraw(Piece piece, boardPos pos) { placePieceAndDraw(piece, pos.row, pos.column); } void placePieceAndDraw(Piece piece, int row, int column) { boardState.placePiece(piece, row, column); pixelCoord tl = getTopLeftOfSquare(row, column); switch(piece) { case wK: case bK: drawKing(row, column, piece==wK, (row+column)%2); break; case wQ: case bQ: drawQueen(row, column, piece==wQ, (row+column)%2); break; case wB: case bB: drawBishop(row, column, piece==wB, (row+column)%2); break; case wN: case bN: drawKnight(row, column, piece==wN, (row+column)%2); break; case wR: case bR: drawRook(row, column, piece==wR, (row+column)%2); break; case w: case b: drawPawn(row, column, piece==w, (row+column)%2); break; } } /* removes a piece from the set position of the board returns the bit representation of the piece */ Piece removePieceAndDraw(boardPos pos) { return removePieceAndDraw(pos.row, pos.column); } Piece removePieceAndDraw(int row, int column) { Piece removedPiece = boardState.removePiece(row, column); pixelCoord tl = getTopLeftOfSquare(row, column); uint64_t color; if ((row + column) % 2 == 0) { color = BOARD_DARK_COLOR; } else { color = BOARD_LIGHT_COLOR; } uLCD.filled_rectangle(tl.x+2, tl.y+2, tl.x + 13, tl.y + 13, color); return removedPiece; } /* moves a piece from one position to another returns the captured piece */ Piece movePieceAndDraw(boardPos startPos, boardPos endPos) { return movePieceAndDraw(startPos.row, startPos.column, endPos.row, endPos.column); } Piece movePieceAndDraw(int startRow, int startColumn, int endRow, int endColumn) { Piece movingPiece = removePieceAndDraw(startRow, startColumn); Piece capturedPiece = boardState.removePiece(endRow, endColumn); placePieceAndDraw(movingPiece, endRow, endColumn); return capturedPiece; } // SQUARE BORDER GRAPHICS FUNCTIONS // removes selection border around square void unselectSquare(boardPos pos) { unselectSquare(pos.row, pos.column); } void unselectSquare(int row, int column) { pixelCoord tl = getTopLeftOfSquare(row, column); uint64_t color; if ((row + column) % 2 == 0) { color = BOARD_DARK_COLOR; } else { color = BOARD_LIGHT_COLOR; } uLCD.rectangle(tl.x, tl.y, tl.x + 15, tl.y + 15, color); } // draws the hover border around square void hoverSquare(boardPos pos) { hoverSquare(pos.row, pos.column); } void hoverSquare(int row, int column) { pixelCoord tl = getTopLeftOfSquare(row, column); uLCD.rectangle(tl.x, tl.y, tl.x + 15, tl.y + 15, HOVER_COLOR); } // draws selection border around square void selectSquare(boardPos pos) { selectSquare(pos.row, pos.column); } void selectSquare(int row, int column) { pixelCoord tl = getTopLeftOfSquare(row, column); uLCD.rectangle(tl.x, tl.y, tl.x + 15, tl.y + 15, SELECTED_COLOR); } // draws the movement border around square void movementSquare(boardPos pos) { movementSquare(pos.row, pos.column); } void movementSquare(int row, int column) { pixelCoord tl = getTopLeftOfSquare(row, column); uLCD.rectangle(tl.x, tl.y, tl.x + 15, tl.y + 15, MOVE_COLOR); } }; // game variables GameBoard gameBoard; GameState state = whiteSelecting; boardPos cursorPos = (boardPos) { 3, 4 }; boardPos selectedPos; Piece selectedPiece; std::vector<boardPos> possibleMoves; // callbacks void moveCursor(int rowChange, int columnChange) { // calculate new positoin that is within board bounds int newRow = cursorPos.row + rowChange; newRow = newRow <= 7 ? newRow : 7; newRow = newRow >= 0 ? newRow : 0; int newColumn = cursorPos.column + columnChange; newColumn = newColumn <= 7 ? newColumn : 7; newColumn = newColumn >= 0 ? newColumn : 0; boardPos newPos = (boardPos) { newRow, newColumn }; // draw border around square that should be there after moving cursor off if (cursorPos == selectedPos) { gameBoard.selectSquare(cursorPos); } else if (std::find(possibleMoves.begin(), possibleMoves.end(), cursorPos) != possibleMoves.end()) { gameBoard.movementSquare(cursorPos); } else { gameBoard.unselectSquare(cursorPos); } // draw hover rectangle over new square cursorPos = newPos; gameBoard.hoverSquare(cursorPos); } void joyStickUp() { moveCursor(1, 0); } void joyStickDown() { moveCursor(-1, 0); } void joyStickLeft() { moveCursor(0, -1); } void joyStickRight() { moveCursor(0, 1); } void joyStickPressed() { switch(state) { case whiteSelecting: case blackSelecting: { selectedPos = cursorPos; Piece tempPiece = gameBoard.getPiece(cursorPos); std::vector<Piece> pickablePieces = state == whiteSelecting ? whitePieces : blackPieces; // check that piece is white and able to be picked up if (std::find(pickablePieces.begin(), pickablePieces.end(), tempPiece) != pickablePieces.end()) { selectedPiece = tempPiece; possibleMoves = gameBoard.getBoardState().getMoves(cursorPos); // draw movement squares for (std::vector<boardPos>::iterator it = possibleMoves.begin(); it != possibleMoves.end(); ++it) { gameBoard.movementSquare(*it); } gameBoard.selectSquare(selectedPos); // transistion state state = state == whiteSelecting ? whitePickedUp : blackPickedUp; } break; } case whitePickedUp: case blackPickedUp: { // check if move is valid if (std::find(possibleMoves.begin(), possibleMoves.end(), cursorPos) != possibleMoves.end()) { // move the piece Piece capturedPiece = gameBoard.movePieceAndDraw(selectedPos, cursorPos); // check for king capture if (state == whitePickedUp && capturedPiece == bK || state == blackPickedUp && capturedPiece == wK) { // game end } // transition state state = state == whitePickedUp ? blackSelecting : whiteSelecting; // check if placing piece back down } else if (cursorPos == selectedPos) { // transition state state = state == whitePickedUp ? whiteSelecting : blackSelecting; } // unselect movement squares for (std::vector<boardPos>::iterator it = possibleMoves.begin(); it != possibleMoves.end(); ++it) { gameBoard.unselectSquare(*it); } gameBoard.unselectSquare(selectedPos); gameBoard.hoverSquare(cursorPos); break; } case whiteAI: case blackAI: { break; } } } int main() { //gameBoard = GameBoard(); whitePieces.push_back(wK); whitePieces.push_back(wQ); whitePieces.push_back(wB); whitePieces.push_back(wN); whitePieces.push_back(wR); whitePieces.push_back(w); blackPieces.push_back(bK); blackPieces.push_back(bQ); blackPieces.push_back(bB); blackPieces.push_back(bN); blackPieces.push_back(bR); blackPieces.push_back(b); return 0; }