Mert Us Matthew Hannay Logan Starr
Dependencies: mbed 4DGL-uLCD-SE
Diff: main.cpp
- Revision:
- 16:b66a720631dd
- Parent:
- 14:f390d08e5f92
- Child:
- 17:4d74a661d6a0
--- a/main.cpp Sun Dec 04 09:32:07 2022 +0000 +++ b/main.cpp Mon Dec 05 12:10:50 2022 +0000 @@ -1,33 +1,34 @@ #include "mbed.h" #include "uLCD_4DGL.h" #include <vector> - + uLCD_4DGL uLCD(p28,p27,p30); // serial tx, serial rx, reset pin; - -DigitalOut myLed(LED1); Serial Blue(p13, p14); - +DigitalOut bad_move(p18); +DigitalIn reset_button(p19); +DigitalIn game_mode_switch(p20); + 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 Nav_Switch { public: @@ -42,12 +43,13 @@ //automatic read on RHS operator int (); //index to any switch array style - bool operator[](int index) { + bool operator[](int index) + { return _pins[index]; }; private: BusIn _pins; - + }; Nav_Switch::Nav_Switch (PinName up,PinName down,PinName left,PinName right,PinName fire): _pins(up, down, left, right, fire) @@ -84,63 +86,72 @@ return _pins.read(); } +const int BOARD_DARK_COLOR = 0x769656; +const int BOARD_LIGHT_COLOR = 0xbaca44; + const float KING_POSITION_VALUES[] = {2.0, 3.0, 1.0, 0.0, 0.0, 1.0, 3.0, 2,0, - 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 2.0, - -1.0, -2.0, -2.0, -2.0, -2.0, -2.0, -2.0, -1.0, - -2.0, -3.0, -3.0, -4.0, -4.0, -3.0, -3.0, -2,0, - -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0, - -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0, - -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0, - -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0}; - + 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 2.0, + -1.0, -2.0, -2.0, -2.0, -2.0, -2.0, -2.0, -1.0, + -2.0, -3.0, -3.0, -4.0, -4.0, -3.0, -3.0, -2,0, + -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0, + -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0, + -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0, + -3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0 + }; + const float QUEEN_POSITION_VALUES[] = {-2.0, -1.0, -1.0, -0.5, -0.5, -1.0, -1.0, -2.0, - -1.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, -1.0, - -1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.0, -1.0, - 0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, -0.5, - -0.5, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, -0.5, - -1.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, -1.0, - -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, - -2.0, -1.0, -1.0, -0.5, -0.5, -1.0, -1.0, -2.0}; - + -1.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, -1.0, + -1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.0, -1.0, + 0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, -0.5, + -0.5, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, -0.5, + -1.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, -1.0, + -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, + -2.0, -1.0, -1.0, -0.5, -0.5, -1.0, -1.0, -2.0 + }; + const float ROOK_POSITION_VALUES[] = {0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, - -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5, - -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5, - -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5, - -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5, - -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5, - 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; - + -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5, + -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5, + -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5, + -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5, + -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5, + 0.5, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.5, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }; + const float BISHOP_POSITION_VALUES[] = {-2.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -2.0, - -1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.5, -1.0, - -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, - -1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, -1.0, - -1.0, 0.5, 0.5, 1.0, 1.0, 0.5, 0.5, -1.0, - -1.0, 0.0, 0.5, 1.0, 1.0, 0.5, 0.0, -1.0, - -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, - -2.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -2.0}; + -1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.5, -1.0, + -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, + -1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, -1.0, + -1.0, 0.5, 0.5, 1.0, 1.0, 0.5, 0.5, -1.0, + -1.0, 0.0, 0.5, 1.0, 1.0, 0.5, 0.0, -1.0, + -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, + -2.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -2.0 + }; const float KNIGHT_POSITION_VALUES[] = {-5.0, -4.0, -3.0, -3.0, -3.0, -3.0, -4.0, -5.0, - -4.0, -2.0, 0.0, 0.5, 0.5, 0.0, -2.0, -4.0, - -3.0, 0.5, 1.0, 1.5, 1.5, 1.0, 0.5, -3.0, - -3.0, 0.0, 1.5, 2.0, 2.0, 1.5, 0.0, -3.0, - -3.0, 0.5, 1.5, 2.0, 2.0, 1.5, 0.5, -3.0, - -3.0, 0.0, 1.0, 1.5, 1.5, 1.0, 0.0, -3.0, - -4.0, -2.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0, - -5.0, -4.0, -3.0, -3.0, -3.0, -3.0, -4.0, -5.0}; + -4.0, -2.0, 0.0, 0.5, 0.5, 0.0, -2.0, -4.0, + -3.0, 0.5, 1.0, 1.5, 1.5, 1.0, 0.5, -3.0, + -3.0, 0.0, 1.5, 2.0, 2.0, 1.5, 0.0, -3.0, + -3.0, 0.5, 1.5, 2.0, 2.0, 1.5, 0.5, -3.0, + -3.0, 0.0, 1.0, 1.5, 1.5, 1.0, 0.0, -3.0, + -4.0, -2.0, 0.0, 0.0, 0.0, 0.0, -2.0, -4.0, + -5.0, -4.0, -3.0, -3.0, -3.0, -3.0, -4.0, -5.0 + }; const float PAWN_POSITION_VALUES[] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, - 0.5, 1.0, 1.0, -2.0, -2.0, 1.0, 1.0, 0.5, - 0.5, -0.5, -1.0, 0.0, 0.0, -1.0, -0.5, 0.5, - 0.0, 0.0, 0.0, 2.0, 2.0, 0.0, 0.0, 0.0, - 0.5, 0.5, 1.0, 2.5, 2.5, 1.0, 0.5, 0.5, - 1.0, 1.0, 2.0, 3.0, 3.0, 2.0, 1.0, 1.0, - 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; - + 0.5, 1.0, 1.0, -2.0, -2.0, 1.0, 1.0, 0.5, + 0.5, -0.5, -1.0, 0.0, 0.0, -1.0, -0.5, 0.5, + 0.0, 0.0, 0.0, 2.0, 2.0, 0.0, 0.0, 0.0, + 0.5, 0.5, 1.0, 2.5, 2.5, 1.0, 0.5, 0.5, + 1.0, 1.0, 2.0, 3.0, 3.0, 2.0, 1.0, 1.0, + 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, 5.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 + }; + class BoardState { private: Piece array[64]; - // These values are for white pieces, need to be inverted + // These values are for white pieces, need to be inverted // when making calculations for black pieces. static const float PAWN_VALUE = 10.0; static const float KNIGHT_VALUE = 30.0; @@ -150,7 +161,7 @@ static const float KING_VALUE = 900.0; public: BoardState() {} - + // calculates the advantage difference for the board state float calculateBoardState() { @@ -198,23 +209,30 @@ break; default: break; - } + } } return sum; } - + // 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; + // pawn promotion handling + if (piece == w && row == 7) { + array[column + 8 * row] = wQ; + } else if (piece == b && row == 0) { + array[column + 8 * row] = bQ; + } else { + array[column + 8 * row] = piece; + } } - + /* removes a piece from the set position of the board returns the bit representation of the piece */ @@ -224,7 +242,7 @@ array[column + 8 * row] = e; return removedPiece; } - + /* moves a piece from one position to another returns the captured piece */ @@ -235,7 +253,7 @@ placePiece(movingPiece, endRow, endColumn); return capturedPiece; } - + // generates a list of possible moves for a piece // returns moves std::vector<boardPos> getMoves(boardPos pos) @@ -255,204 +273,44 @@ case bK: isWhite = movingPiece == wK; if (validMove(isWhite, row + 1, column)) { - boardPos tPos = (boardPos) { + moves.push_back((boardPos) { row + 1, column - }; - bool possibleKingMove = true; - for (int i = 0; i < 64; i++) { - Piece possibleThreat = getPiece(i/8, i%8); - if (isWhite && (possibleThreat == bK || possibleThreat == bQ || possibleThreat == bR || possibleThreat == bN || possibleThreat == bB || possibleThreat == b)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } else if (!isWhite && (possibleThreat == wK || possibleThreat == wQ || possibleThreat == wR || possibleThreat == wN || possibleThreat == wB || possibleThreat == w)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } - } - if (possibleKingMove) { - moves.push_back(tPos); - } + }); } if (validMove(isWhite, row, column + 1)) { - boardPos tPos = (boardPos) { + moves.push_back((boardPos) { row, column + 1 - }; - bool possibleKingMove = true; - for (int i = 0; i < 64; i++) { - Piece possibleThreat = getPiece(i/8, i%8); - if (isWhite && (possibleThreat == bK || possibleThreat == bQ || possibleThreat == bR || possibleThreat == bN || possibleThreat == bB || possibleThreat == b)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } else if (!isWhite && (possibleThreat == wK || possibleThreat == wQ || possibleThreat == wR || possibleThreat == wN || possibleThreat == wB || possibleThreat == w)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } - } - if (possibleKingMove) { - moves.push_back(tPos); - } + }); } if (validMove(isWhite, row - 1, column)) { - boardPos tPos = (boardPos) { + moves.push_back((boardPos) { row - 1, column - }; - bool possibleKingMove = true; - for (int i = 0; i < 64; i++) { - Piece possibleThreat = getPiece(i/8, i%8); - if (isWhite && (possibleThreat == bK || possibleThreat == bQ || possibleThreat == bR || possibleThreat == bN || possibleThreat == bB || possibleThreat == b)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } else if (!isWhite && (possibleThreat == wK || possibleThreat == wQ || possibleThreat == wR || possibleThreat == wN || possibleThreat == wB || possibleThreat == w)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } - } - if (possibleKingMove) { - moves.push_back(tPos); - } + }); } if (validMove(isWhite, row, column - 1)) { - boardPos tPos = (boardPos) { + moves.push_back((boardPos) { row, column - 1 - }; - bool possibleKingMove = true; - for (int i = 0; i < 64; i++) { - Piece possibleThreat = getPiece(i/8, i%8); - if (isWhite && (possibleThreat == bK || possibleThreat == bQ || possibleThreat == bR || possibleThreat == bN || possibleThreat == bB || possibleThreat == b)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } else if (!isWhite && (possibleThreat == wK || possibleThreat == wQ || possibleThreat == wR || possibleThreat == wN || possibleThreat == wB || possibleThreat == w)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } - } - if (possibleKingMove) { - moves.push_back(tPos); - } + }); } if (validMove(isWhite, row + 1, column + 1)) { - boardPos tPos = (boardPos) { + moves.push_back((boardPos) { row + 1, column + 1 - }; - bool possibleKingMove = true; - for (int i = 0; i < 64; i++) { - Piece possibleThreat = getPiece(i/8, i%8); - if (isWhite && (possibleThreat == bK || possibleThreat == bQ || possibleThreat == bR || possibleThreat == bN || possibleThreat == bB || possibleThreat == b)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } else if (!isWhite && (possibleThreat == wK || possibleThreat == wQ || possibleThreat == wR || possibleThreat == wN || possibleThreat == wB || possibleThreat == w)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } - } - if (possibleKingMove) { - moves.push_back(tPos); - } + }); } if (validMove(isWhite, row - 1, column + 1)) { - boardPos tPos = (boardPos) { + moves.push_back((boardPos) { row - 1, column + 1 - }; - bool possibleKingMove = true; - for (int i = 0; i < 64; i++) { - Piece possibleThreat = getPiece(i/8, i%8); - if (isWhite && (possibleThreat == bK || possibleThreat == bQ || possibleThreat == bR || possibleThreat == bN || possibleThreat == bB || possibleThreat == b)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } else if (!isWhite && (possibleThreat == wK || possibleThreat == wQ || possibleThreat == wR || possibleThreat == wN || possibleThreat == wB || possibleThreat == w)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } - } - if (possibleKingMove) { - moves.push_back(tPos); - } + }); } if (validMove(isWhite, row - 1, column - 1)) { - boardPos tPos = (boardPos) { + moves.push_back((boardPos) { row - 1, column - 1 - }; - bool possibleKingMove = true; - for (int i = 0; i < 64; i++) { - Piece possibleThreat = getPiece(i/8, i%8); - if (isWhite && (possibleThreat == bK || possibleThreat == bQ || possibleThreat == bR || possibleThreat == bN || possibleThreat == bB || possibleThreat == b)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } else if (!isWhite && (possibleThreat == wK || possibleThreat == wQ || possibleThreat == wR || possibleThreat == wN || possibleThreat == wB || possibleThreat == w)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } - } - if (possibleKingMove) { - moves.push_back(tPos); - } + }); } if (validMove(isWhite, row + 1, column - 1)) { - boardPos tPos = (boardPos) { + moves.push_back((boardPos) { row + 1, column - 1 - }; - bool possibleKingMove = true; - for (int i = 0; i < 64; i++) { - Piece possibleThreat = getPiece(i/8, i%8); - if (isWhite && (possibleThreat == bK || possibleThreat == bQ || possibleThreat == bR || possibleThreat == bN || possibleThreat == bB || possibleThreat == b)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } else if (!isWhite && (possibleThreat == wK || possibleThreat == wQ || possibleThreat == wR || possibleThreat == wN || possibleThreat == wB || possibleThreat == w)) { - std::vector<boardPos> possibleThreatMoves = getMoves(i/8, i%8); - if (std::find(possibleThreatMoves.begin(), possibleThreatMoves.end(), tPos) != possibleThreatMoves.end()) { - possibleKingMove = false; - break; - } - } - } - if (possibleKingMove) { - moves.push_back(tPos); - } + }); } break; case wQ: @@ -726,7 +584,7 @@ } 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) { @@ -748,7 +606,7 @@ } return moves; } - + // returns if a piece can move to a given location bool validMove(bool isMovingPieceWhite, int row, int column) { @@ -777,163 +635,153 @@ 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); } - - // 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); + + 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() { @@ -972,9 +820,22 @@ placePieceAndDraw(b, 6, i); } } - + + // 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 MOVEMENT AND GRAPHICS FUNCTIONS - + // returns the piece at a given location Piece getPiece(boardPos pos) { @@ -984,7 +845,7 @@ { 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 */ @@ -996,34 +857,41 @@ { 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; + 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: + if (piece == w && row == 7) { + drawQueen(row, column, true, (row+column)%2); + } else if (piece == b && row == 0) { + drawQueen(row, column, false, (row+column)%2); + } else { + 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 */ @@ -1044,7 +912,7 @@ 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 */ @@ -1059,9 +927,9 @@ placePieceAndDraw(movingPiece, endRow, endColumn); return capturedPiece; } - + // SQUARE BORDER GRAPHICS FUNCTIONS - + // removes selection border around square void unselectSquare(boardPos pos) { @@ -1081,7 +949,7 @@ } uLCD.rectangle(tl.x, tl.y, tl.x + 15, tl.y + 15, color); } - + // draws the hover border around square void hoverSquare(boardPos pos) { @@ -1092,7 +960,7 @@ 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) { @@ -1106,7 +974,7 @@ 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) { @@ -1118,7 +986,7 @@ uLCD.rectangle(tl.x, tl.y, tl.x + 15, tl.y + 15, MOVE_COLOR); } }; - + // game variables GameBoard gameBoard; GameState state = whiteSelecting; @@ -1130,21 +998,27 @@ 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; + int newColumn = cursorPos.column + columnChange; + if (newRow > 7 || newRow < 0 || newColumn > 7 || newColumn < 0) { + bad_move = 1; + wait(0.2); + bad_move = 0; + wait(0.02); + } 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); @@ -1153,32 +1027,91 @@ } else { gameBoard.unselectSquare(cursorPos); } - + // draw hover rectangle over new square cursorPos = newPos; gameBoard.hoverSquare(cursorPos); } +void reset_game(void) { + BoardState newBS; + for (int i = 0; i < 64; i++) { + newBS.placePiece(e, i/8, i%8); + } + gameBoard.setBoardState(newBS); + // 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 = gameBoard.getTopLeftOfSquare(row, column); + uLCD.filled_rectangle(tl.x, tl.y, tl.x + 15, tl.y + 15, color); + } + } + // draw pieces + gameBoard.placePieceAndDraw(wR, 0, 0); + gameBoard.placePieceAndDraw(wN, 0, 1); + gameBoard.placePieceAndDraw(wB, 0, 2); + gameBoard.placePieceAndDraw(wQ, 0, 3); + gameBoard.placePieceAndDraw(wK, 0, 4); + gameBoard.placePieceAndDraw(wB, 0, 5); + gameBoard.placePieceAndDraw(wN, 0, 6); + gameBoard.placePieceAndDraw(wR, 0, 7); + gameBoard.placePieceAndDraw(bR, 7, 0); + gameBoard.placePieceAndDraw(bN, 7, 1); + gameBoard.placePieceAndDraw(bB, 7, 2); + gameBoard.placePieceAndDraw(bQ, 7, 3); + gameBoard.placePieceAndDraw(bK, 7, 4); + gameBoard.placePieceAndDraw(bB, 7, 5); + gameBoard.placePieceAndDraw(bN, 7, 6); + gameBoard.placePieceAndDraw(bR, 7, 7); + for (int i = 0; i < 8; i++) { + gameBoard.placePieceAndDraw(w, 1, i); + gameBoard.placePieceAndDraw(b, 6, i); + } + + state = whiteSelecting; + cursorPos = (boardPos) + { + 3, 4 + }; + if (game_mode_switch) { + OnePlayer = true; + } else { + OnePlayer = false; + } + selectedPos = (boardPos) + { + 10, 10 + }; + possibleMoves.clear(); + moveCursor(0, 0); +} + void joyStickUp() { moveCursor(1, 0); } - + void joyStickDown() { moveCursor(-1, 0); } - + void joyStickLeft() { moveCursor(0, -1); } - + void joyStickRight() { moveCursor(0, 1); } - + void joyStickPressed() { switch(state) { @@ -1204,10 +1137,13 @@ state = state == whiteSelecting ? whitePickedUp : blackPickedUp; } } else { - selectedPos = (boardPos) - { + selectedPos = (boardPos) { 10, 10 }; + bad_move = 1; + wait(0.1); + bad_move = 0; + wait(0.02); } break; } @@ -1218,8 +1154,38 @@ // move the piece Piece capturedPiece = gameBoard.movePieceAndDraw(selectedPos, cursorPos); // check for king capture - if (state == whitePickedUp && capturedPiece == bK || state == blackPickedUp && capturedPiece == wK) { - // game end + if (state == whitePickedUp && capturedPiece == bK) { + uLCD.cls(); + uLCD.text_height(2); + uLCD.text_width(2); + uLCD.color(WHITE); + uLCD.locate(2,2); + uLCD.printf("WHITE"); + uLCD.locate(2,4); + uLCD.printf("WINS"); + while(1) { + if (!reset_button) { + reset_game(); + break; + } + } + break; + } else if (state == blackPickedUp && capturedPiece == wK) { + uLCD.cls(); + uLCD.text_height(2); + uLCD.text_width(2); + uLCD.color(WHITE); + uLCD.locate(2,2); + uLCD.printf("BLACK"); + uLCD.locate(2,4); + uLCD.printf("WINS"); + while(1) { + if (!reset_button) { + reset_game(); + break; + } + } + break; } // transition state if (OnePlayer) { @@ -1239,8 +1205,7 @@ gameBoard.unselectSquare(selectedPos); gameBoard.hoverSquare(cursorPos); possibleMoves.clear(); - selectedPos = (boardPos) - { + selectedPos = (boardPos) { 10, 10 }; break; @@ -1309,7 +1274,7 @@ } } } - + if (bestMoveValueDepth1 < bestMoveValueDepth0) { bestMoveSourceDepth0 = currSourceDepth0; bestMoveDestDepth0 = *it; @@ -1319,8 +1284,22 @@ } } Piece capturedPiece = gameBoard.movePieceAndDraw(bestMoveSourceDepth0, bestMoveDestDepth0); - if (capturedPiece == bK) { - // game end + if (capturedPiece == wK) { + uLCD.cls(); + uLCD.text_height(2); + uLCD.text_width(2); + uLCD.color(WHITE); + uLCD.locate(2,2); + uLCD.printf("BLACK"); + uLCD.locate(2,4); + uLCD.printf("WINS"); + while(1) { + if (!reset_button) { + reset_game(); + break; + } + } + break; } state = whiteSelecting; break; @@ -1330,7 +1309,7 @@ } } } - + // bluetooth volatile bool button_ready = 0; volatile int bnum = 0; @@ -1366,12 +1345,14 @@ bluetooth_state = start; } } - + Nav_Switch myNav(p9, p6, p7, p5, p8); //pin order on Sparkfun breakout - + int main() { - //gameBoard = GameBoard(); + reset_button.mode(PullUp); + game_mode_switch.mode(PullUp); + wait(0.01); whitePieces.push_back(wK); whitePieces.push_back(wQ); whitePieces.push_back(wB); @@ -1384,13 +1365,22 @@ blackPieces.push_back(bN); blackPieces.push_back(bR); blackPieces.push_back(b); + + if (game_mode_switch) { + OnePlayer = true; + } else { + OnePlayer = false; + } + moveCursor(0, 0); Blue.attach(&parse_message,Serial::RxIrq); + while (1) { - if (state == blackAI) { + if (!reset_button) { + reset_game(); + } else if (state == blackAI) { joyStickPressed(); - } - if (myNav.up()) { + } else if (myNav.up()) { joyStickUp(); } else if (myNav.down()) { joyStickDown();