Compare commits

...

3 commits

Author SHA1 Message Date
A.M. Rowsell
7722a84b2e
astyle: reformatted all files 2025-08-28 10:41:59 -04:00
A.M. Rowsell
04c7a931d3
fen: Merge branch 'fen' into dev 2025-08-28 10:39:50 -04:00
A.M. Rowsell
b553823dde
FEN: implemented first field of FEN string handling 2025-08-28 10:28:11 -04:00
5 changed files with 149 additions and 39 deletions

121
Board.cpp
View file

@ -30,12 +30,19 @@
*/
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;
boardGrid.resize(8);
for(int i = 0; i < 8; i++) {
boardGrid[i].resize(8);
switch(i) {
case 0:
// white back rank
@ -57,7 +64,9 @@ Board::Board() {
case 3:
case 4:
case 5:
continue;
for(int j = 0; j <= 8; j++)
boardGrid[i][j] = nullptr;
break;
case 6:
// black pawn rank
for(int j = 0; j <= 8; j++)
@ -77,27 +86,105 @@ Board::Board() {
break;
}
}
}
Board::~Board() {
}
void Board::setupInitialPosition() {
return;
}
int setupFromFEN(std::string strFEN) {
std::string field1, field2, field3, field4, field5, field6;
std::vector<std::string> splitFEN = split(strFEN, ' ');
if(splitFEN.size() != 6) { // a valid FEN *must* contain 6 fields
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++;
}
field1 = splitFEN[0];
field2 = splitFEN[1];
field3 = splitFEN[2];
field4 = splitFEN[3];
field5 = splitFEN[4];
field6 = splitFEN[5];
return 0;
}

View file

@ -22,6 +22,28 @@ std::vector<Move> Piece::getLegalMoves(const Square &from, const Board &board) c
std::vector<Move> moveList;
return moveList;
}
bool King::checkForCheck() const {
std::vector<std::vector<int>> kingVulnerable = {
{-1, 0}, // Up
{-1, -1}, // up-left
{-1, 1}, // up-right
{1, 0}, // Down
{1, -1}, // down-left
{1, 1}, // down-right
{0, -1}, // Left
{0, 1}, // Right
{-1, -2}, // 1
{-1, 2}, // 2
{-2, -1}, // 3
{-2, 1}, // 4
{1, -2}, // 5
{1, 2}, // 6
{2, -1}, // 7
{2, 1} // 8
};
// locate our King
return inCheck;
}
std::vector<Move> King::getLegalMoves(const Square &from, const Board &board) const {
std::vector<Move> moveList;
@ -97,18 +119,20 @@ std::vector<Move> King::getLegalMoves(const Square &from, const Board &board) co
if(target && (target->getColour() != this->getColour())) { // is it occupied & an enemy?
if((target->getPieceType() == QUEEN || target->getPieceType() == BISHOP) && diagonal) {
// we are being attacked diagonally on this square, so remove it
moves.to.rank = INVALID_RANK; moves.to.file = INVALID_FILE;
}
else if(target->getPieceType() == KNIGHT && knight) {
moves.to.rank = INVALID_RANK;
moves.to.file = INVALID_FILE;
} else if(target->getPieceType() == KNIGHT && knight) {
// we are being attacked by a knight, so remove it
moves.to.rank = INVALID_RANK; moves.to.file = INVALID_FILE;
}
else if(target->getPieceType() == ROOK || target->getPieceType() == QUEEN && (!diagonal && !knight)) {
moves.to.rank = INVALID_RANK;
moves.to.file = INVALID_FILE;
} else if(target->getPieceType() == ROOK || target->getPieceType() == QUEEN && (!diagonal && !knight)) {
// again, being attacked, remove it
moves.to.rank = INVALID_RANK; moves.to.file = INVALID_FILE;
moves.to.rank = INVALID_RANK;
moves.to.file = INVALID_FILE;
}
if(target->getPieceType() == PAWN && (abs(r - startSquare.rank) == 1 && abs(f - startSquare.file) == 1)) {
moves.to.rank = INVALID_RANK; moves.to.file = INVALID_FILE;
moves.to.rank = INVALID_RANK;
moves.to.file = INVALID_FILE;
}
}
if(target && (target->getColour() == this->getColour())) {
@ -125,10 +149,10 @@ std::vector<Move> King::getLegalMoves(const Square &from, const Board &board) co
}
// will this actually work?
moveList.erase(
std::remove_if(moveList.begin(), moveList.end(),
[&](const auto &x) {
return !x.to.isValid();
}));
std::remove_if(moveList.begin(), moveList.end(),
[&](const auto & x) {
return !x.to.isValid();
}));
return moveList;
}

View file

@ -92,6 +92,7 @@ class Piece {
};
class King : public Piece {
private:
friend class Board;
public:
@ -102,18 +103,17 @@ class King : public Piece {
}
virtual std::vector<Move> getLegalMoves(const Square &from, const Board &board) const override;
bool checkForCheck() const {
return inCheck;
}
bool checkForCheck() const;
bool checkForCastle(enum CastleSide side) const {
if(side == KINGSIDE) {
if(side == KINGSIDE)
return canCastleKS;
} else if(side == QUEENSIDE) {
else if(side == QUEENSIDE)
return canCastleQS;
} else {
else
return false;
}
}
protected:
bool canCastleQS = true;

View file

@ -114,7 +114,7 @@ uint8_t initSystem(void) {
SDI1R = 0b0100; // RB8
RPA0R = 0b0001; // U1TX
SYSKEY = 0x12345678; // lock SYSKEY
ANSELBCLR = 0xFFFF; // port A all digital
ANSELBCLR = 0xFFFF; // port B all digital
SL_TRIS = 0; // RA0 as output
SL_LAT = 1; // set high
/* Set up SPI1 */

View file

@ -4,9 +4,8 @@ template <typename Out>
void split(const std::string &s, char delim, Out result) {
std::istringstream iss(s);
std::string item;
while (std::getline(iss, item, delim)) {
while(std::getline(iss, item, delim))
*result++ = item;
}
}
std::vector<std::string> split(const std::string &s, char delim) {