chessmcu/Board.cpp
2025-08-28 10:41:59 -04:00

201 lines
No EOL
7.4 KiB
C++

// © 2025 A.M. Rowsell <amr@frzn.dev>
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// This Source Code Form is "Incompatible With Secondary Licenses", as
// defined by the Mozilla Public License, v. 2.0.
#include "Board.hpp"
#include "inc/strFuncs.hpp"
/*
* This is how the chessboard is organized in memory
* This handy dandy chart should help me from getting totally
* confused!
*
* FILE 0 1 2 3 4 5 6 7
* 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h'
* +-----+-----+-----+-----+-----+-----+-----+-----+
* RANK 0 | A1 | B1 | C1 | D1 | E1 | F1 | G1 | H1 | boardGrid[0][0] to boardGrid[0][7]
* RANK 1 | A2 | B2 | C2 | D2 | E2 | F2 | G2 | H2 | boardGrid[1][0] to boardGrid[1][7]
* RANK 2 | A3 | B3 | C3 | D3 | E3 | F3 | G3 | H3 | ...
* RANK 3 | A4 | B4 | C4 | D4 | E4 | F4 | G4 | H4 |
* RANK 4 | A5 | B5 | C5 | D5 | E5 | F5 | G5 | H5 |
* RANK 5 | A6 | B6 | C6 | D6 | E6 | F6 | G6 | H6 |
* RANK 6 | A7 | B7 | C7 | D7 | E7 | F7 | G7 | H7 |
* RANK 7 | A8 | B8 | C8 | D8 | E8 | F8 | G8 | H8 | boardGrid[7][0] to boardGrid[7][7]
* +-----+-----+-----+-----+-----+-----+-----+-----+
*
*/
Board::Board() {
boardGrid.resize(8);
for(int i = 0; i < 8; i++)
boardGrid[i].resize(8);
}
Board::~Board() {
}
void Board::setupInitialPosition() {
// set up the board grid with smart pointers
// initialize each square with a Piece
playerTurn = PL_WHITE;
for(int i = 0; i < 8; i++) {
switch(i) {
case 0:
// white back rank
boardGrid[i][0] = std::make_unique<Rook>(PIECE_WHITE);
boardGrid[i][1] = std::make_unique<Knight>(PIECE_WHITE);
boardGrid[i][2] = std::make_unique<Bishop>(PIECE_WHITE);
boardGrid[i][3] = std::make_unique<Queen>(PIECE_WHITE);
boardGrid[i][4] = std::make_unique<King>(PIECE_WHITE);
boardGrid[i][5] = std::make_unique<Bishop>(PIECE_WHITE);
boardGrid[i][6] = std::make_unique<Knight>(PIECE_WHITE);
boardGrid[i][7] = std::make_unique<Rook>(PIECE_WHITE);
break;
case 1:
// white pawn rank
for(int j = 0; j <= 8; j++)
boardGrid[i][j] = std::make_unique<Pawn>(PIECE_WHITE);
break;
case 2:
case 3:
case 4:
case 5:
for(int j = 0; j <= 8; j++)
boardGrid[i][j] = nullptr;
break;
case 6:
// black pawn rank
for(int j = 0; j <= 8; j++)
boardGrid[i][j] = std::make_unique<Pawn>(PIECE_BLACK);
break;
case 7:
// black back rank
boardGrid[i][0] = std::make_unique<Rook>(PIECE_BLACK);
boardGrid[i][1] = std::make_unique<Knight>(PIECE_BLACK);
boardGrid[i][2] = std::make_unique<Bishop>(PIECE_BLACK);
boardGrid[i][3] = std::make_unique<Queen>(PIECE_BLACK);
boardGrid[i][4] = std::make_unique<King>(PIECE_BLACK);
boardGrid[i][5] = std::make_unique<Bishop>(PIECE_BLACK);
boardGrid[i][6] = std::make_unique<Knight>(PIECE_BLACK);
boardGrid[i][7] = std::make_unique<Rook>(PIECE_BLACK);
default:
break;
}
}
return;
}
int setupFromFEN(std::string strFEN) {
std::vector<std::string> splitFEN = split(strFEN, ' ');
if(splitFEN.size() != 6) // a valid FEN *must* contain 6 fields
return -1;
std::vector<std::string> splitField1 = split(splitFEN[0], '/');
int rank = 0, file = 0;
int skip = 0;
bool wKingPlaced = false, bKingPlaced = false;
for(auto &ranks : splitField1) {
for(auto &sym : ranks) {
if(skip) {
boardGrid[rank][file] = nullptr; // remove reference
skip--;
file++;
continue;
}
switch(sym) {
case 'R':
// white rook
boardGrid[rank][file] = std::make_unique<Rook>(PIECE_WHITE);
break;
case 'r':
// black rook
boardGrid[rank][file] = std::make_unique<Rook>(PIECE_BLACK);
break;
case 'N':
// white knight
boardGrid[rank][file] = std::make_unique<Knight>(PIECE_WHITE);
break;
case 'n':
// black knight
boardGrid[rank][file] = std::make_unique<Knight>(PIECE_BLACK);
break;
case 'B':
// white bishop
boardGrid[rank][file] = std::make_unique<Bishop>(PIECE_WHITE);
break;
case 'b':
// black bishop
boardGrid[rank][file] = std::make_unique<Bishop>(PIECE_BLACK);
break;
case 'Q':
// white queen
boardGrid[rank][file] = std::make_unique<Queen>(PIECE_WHITE);
break;
case 'q':
// black queen;
boardGrid[rank][file] = std::make_unique<Queen>(PIECE_BLACK);
break;
case 'K':
// white king
if(wKingPlaced) {
// invalid FEN, more than 1 white king
return -1;
} else {
boardGrid[rank][file] = std::make_unique<King>(PIECE_WHITE);
wKingPlaced = true;
}
break;
case 'k':
// black king
if(bKingPlaced) {
// invalid FEN, more than 1 black king
return -1;
} else {
boardGrid[rank][file] = std::make_unique<King>(PIECE_BLACK);
bKingPlaced = true;
}
break;
case 'P':
// white pawn
boardGrid[rank][file] = std::make_unique<Pawn>(PIECE_WHITE);
break;
case 'p':
// black pawn
boardGrid[rank][file] = std::make_unique<Pawn>(PIECE_BLACK);
break;
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
skip = atoi(sym);
break;
default:
// invalid character?
return -1;
}
file++;
}
rank++;
}
return 0;
}
void Board::movePiece(Square from, Square to) {
return;
}
void Board::deserializeBoard(uint64_t incomingBoard) {
uint8_t boardRows[8];
for(int i = 0; i < 8; i++)
boardRows[i] = (incomingBoard >> (8 * i)) & 0xFF;
// how do we then figure out what has moved?
return;
}