Mert Us Matthew Hannay Logan Starr
Dependencies: mbed 4DGL-uLCD-SE
main.cpp
- Committer:
- mhannay3
- Date:
- 2022-11-17
- Revision:
- 8:928d5d33258f
- Parent:
- 7:9e01c9a334dc
- Child:
- 9:1f33c0f299ae
File content as of revision 8:928d5d33258f:
#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}; enum GameState {whiteSelecting, whitePickedUp, blackSelecting, blackPickedUp}; struct pixelCoord { uint8_t x; uint8_t y; }; struct boardPos { uint8_t row; uint8_t 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(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; // piece sprites (12 x 12) static void spritePawn(bool white, bool light, int* spriteArray) { 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, _, _ }; memcpy(sprite, spriteArray, sizeof(sprite)); } static void spriteRook(bool white, bool light, int* spriteArray) { 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 }; memcpy(sprite, spriteArray, sizeof(sprite)); } static void spriteKnight(bool white, bool light, int* spriteArray) { 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, _ }; memcpy(sprite, spriteArray, sizeof(sprite)); } static void spriteBishop(bool white, bool light, int* spriteArray) { 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, _, _ }; memcpy(sprite, spriteArray, sizeof(sprite)); } static void spriteQueen(bool white, bool light, int* spriteArray) { 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, _ }; memcpy(sprite, spriteArray, sizeof(sprite)); } static void spriteKing(bool white, bool light, int* spriteArray) { 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, _ }; memcpy(sprite, spriteArray, sizeof(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); } } // gets the pixel coordinates of the top left of the square pixelCoord getTopLeftOfSquare(boardPos pos) { return getTopLeftOfSquare(pos.row, pos.column); } pixelCoord getTopLeftOfSquare(int row, int column) { pixelCoord topLeft; topLeft.x = 16 * column; topLeft.y = 112 - 16 * row; return topLeft; } // 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); int sprite[144]; switch(piece) { case wK: case bK: spriteKing(piece==wK, (row+column)%2, sprite); break; case wQ: case bQ: spriteQueen(piece==wQ, (row+column)%2, sprite); break; case wB: case bB: spriteBishop(piece==wB, (row+column)%2, sprite); break; case wN: case bN: spriteKing(piece==wN, (row+column)%2, sprite); break; case wR: case bR: spriteKing(piece==wR, (row+column)%2, sprite); break; case w: case b: spriteKing(piece==w, (row+column)%2, sprite); break; } uLCD.BLIT(tl.x + 2, tl.y + 2, 12, 12, sprite); } /* 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 moveSquare(boardPos pos) { moveSquare(pos.row, pos.column); } void moveSquare(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; // callbacks void joyStickUp() { if (cursorPos.row < 7) { boardPos nextPos; nextPos.row = cursorPos.row + 1; nextPos.column = cursorPos.column; gameBoard.unselectSquare(cursorPos); gameBoard.hoverSquare(nextPos); cursorPos = nextPos; } } void joyStickDown() { if (cursorPos.row > 0) { boardPos nextPos; nextPos.row = cursorPos.row - 1; nextPos.column = cursorPos.column; gameBoard.unselectSquare(cursorPos); gameBoard.hoverSquare(nextPos); cursorPos = nextPos; } } void joyStickLeft() { if (cursorPos.column > 0) { boardPos nextPos; nextPos.row = cursorPos.row; nextPos.column = cursorPos.column - 1; gameBoard.unselectSquare(cursorPos); gameBoard.hoverSquare(nextPos); cursorPos = nextPos; } } void joyStickRight() { if (cursorPos.column < 7) { boardPos nextPos; nextPos.row = cursorPos.row; nextPos.column = cursorPos.column + 1; gameBoard.unselectSquare(cursorPos); gameBoard.hoverSquare(nextPos); cursorPos = nextPos; } } void joyStickPressed() { switch(state) { case whiteSelecting: selectedPos = cursorPos; break; case whitePickedUp: break; case blackSelecting: break; case blackPickedUp: break; } } int main() { gameBoard = GameBoard(); return 0; }