Compare commits

..

2 commits

Author SHA1 Message Date
A.M. Rowsell
21fae88bdb
fmt: reformatted code, changed some function signatures, fairly minor 2025-08-29 04:17:16 -04:00
A.M. Rowsell
76c0c3ce8b
FEN: more work on FEN decoding, handling field 2 and 3 2025-08-29 04:16:20 -04:00
6 changed files with 271 additions and 61 deletions

View file

@ -89,22 +89,17 @@ void Board::setupInitialPosition() {
return;
}
int setupFromFEN(std::string strFEN) {
int Board::setupFromFEN(std::string strFEN) {
std::vector<std::string> splitFEN = split(strFEN, ' ');
if(splitFEN.size() != 6) // a valid FEN *must* contain 6 fields
return -1;
// ====== START OF FIELD 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
@ -173,17 +168,62 @@ int setupFromFEN(std::string strFEN) {
case '5':
case '6':
case '7':
case '8':
case '9':
skip = atoi(sym);
case '8': {
std::string skipStr(1, sym);
skip = atoi(skipStr.c_str());
skip--; // fix off by 1 error
do {
boardGrid[rank][file] = nullptr; // remove reference
file = (file < 8) ? file + 1 : 0;
} while(--skip);
break;
}
default:
// invalid character?
return -1;
break;
}
file++;
if(file > 7) {
file = 0;
break;
}
}
rank++;
if(rank > 7)
break;
}
// ======= END OF FIELD 1 ======
// ======= START OF FIELD 2 ======
std::string w = "w";
std::string b = "b";
if(splitFEN[1] == w)
playerTurn = PL_WHITE;
else if(splitFEN[1] == b)
playerTurn = PL_BLACK;
else {
// invalid FEN
return -1;
}
// ====== END OF FIELD 2 ======
// ====== START OF FIELD 3 ======
std::string k = "k", K = "K", q = "q", Q = "Q";
if(splitFEN[2] == "-") {
// nobody can castle, either side
// locate Kings and set appropriate variables
// canCastleKS, canCastleQS
}
if(splitFEN[2].find(k) != std::string::npos) {
// black king can castle kingside
}
if(splitFEN[2].find(K) != std::string::npos) {
// white king can castle kingside
}
if(splitFEN[2].find(q) != std::string::npos) {
// black king can castle queenside
}
if(splitFEN[2].find(Q) != std::string::npos) {
// white king can castle queenside
}
return 0;
}
@ -199,3 +239,7 @@ void Board::deserializeBoard(uint64_t incomingBoard) {
// how do we then figure out what has moved?
return;
}
std::unique_ptr<Piece> &Board::getPieceAt(Square square) {
return boardGrid[square.rank][square.file];
}

View file

@ -18,11 +18,11 @@ Piece::~Piece() {
// so this is just a stub that does nothing. it doesn't matter
// because only the derived class versions should be called.
std::vector<Move> Piece::getLegalMoves(const Square &from, const Board &board) const {
std::vector<Move> Piece::getLegalMoves(const Square &from, Board &board) const {
std::vector<Move> moveList;
return moveList;
}
bool King::checkForCheck() const {
bool King::checkForCheck(Board &board) const {
std::vector<std::vector<int>> kingVulnerable = {
{-1, 0}, // Up
{-1, -1}, // up-left
@ -45,7 +45,7 @@ bool King::checkForCheck() const {
return inCheck;
}
std::vector<Move> King::getLegalMoves(const Square &from, const Board &board) const {
std::vector<Move> King::getLegalMoves(const Square &from, Board &board) const {
std::vector<Move> moveList;
std::vector<std::vector<int>> directions = {
{-1, 0}, // Up
@ -156,7 +156,7 @@ std::vector<Move> King::getLegalMoves(const Square &from, const Board &board) co
return moveList;
}
std::vector<Move> Rook::getLegalMoves(const Square &from, const Board &board) const {
std::vector<Move> Rook::getLegalMoves(const Square &from, Board &board) const {
std::vector<Move> moveList;
const int directions[4][2] = {
{-1, 0}, // Up
@ -186,22 +186,22 @@ std::vector<Move> Rook::getLegalMoves(const Square &from, const Board &board) co
return moveList;
}
std::vector<Move> Queen::getLegalMoves(const Square &from, const Board &board) const {
std::vector<Move> Queen::getLegalMoves(const Square &from, Board &board) const {
std::vector<Move> moveList;
return moveList;
}
std::vector<Move> Knight::getLegalMoves(const Square &from, const Board &board) const {
std::vector<Move> Knight::getLegalMoves(const Square &from, Board &board) const {
std::vector<Move> moveList;
return moveList;
}
std::vector<Move> Bishop::getLegalMoves(const Square &from, const Board &board) const {
std::vector<Move> Bishop::getLegalMoves(const Square &from, Board &board) const {
std::vector<Move> moveList;
return moveList;
}
std::vector<Move> Pawn::getLegalMoves(const Square &from, const Board &board) const {
std::vector<Move> Pawn::getLegalMoves(const Square &from, Board &board) const {
std::vector<Move> moveList;
const int directions[2][4][2] = {
{

View file

@ -9,39 +9,37 @@
#ifndef BOARD_HPP
#define BOARD_HPP
#include <vector>
#include <memory>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "Piece.hpp"
// why do I have to forward declare all these?!
class Piece;
enum Players {
PL_WHITE, PL_BLACK
};
enum Players { PL_WHITE, PL_BLACK };
struct Square;
class Board {
private:
private:
friend class Piece;
Players playerTurn;
public:
public:
// this should be protected, but even when Piece is declared as a friend,
// accessing it in Piece.cpp threw an error
std::vector<std::vector<std::unique_ptr<Piece>>> boardGrid;
Board();
virtual ~Board();
void setupInitialPosition();
Piece *getPieceAt(Square square);
std::unique_ptr<Piece> &getPieceAt(Square square);
void movePiece(Square from, Square to);
int setupFromFEN(std::string strFEN);
bool isInBounds(Square square) const;
bool isEmpty(Square square) const;
uint64_t serialBoard = 0xFFFF00000000FFFF; // opening position
void deserializeBoard(uint64_t incomingBoard);
};
#endif // BOARD_HPP

View file

@ -68,7 +68,7 @@ class Piece {
Piece(PieceColour pColour) : colour(pColour) {
}
virtual ~Piece();
virtual std::vector<Move> getLegalMoves(const Square &from, const Board &board) const;
virtual std::vector<Move> getLegalMoves(const Square &from, Board &board) const;
PieceColour getColour() const {
return colour;
@ -101,9 +101,9 @@ class King : public Piece {
pieceSymbol = 'K';
pieceType = KING;
}
virtual std::vector<Move> getLegalMoves(const Square &from, const Board &board) const override;
virtual std::vector<Move> getLegalMoves(const Square &from, Board &board) const override;
bool checkForCheck() const;
bool checkForCheck(Board &board) const;
bool checkForCastle(enum CastleSide side) const {
if(side == KINGSIDE)
@ -130,7 +130,7 @@ class Rook : public Piece {
pieceSymbol = 'R';
pieceType = ROOK;
}
virtual std::vector<Move> getLegalMoves(const Square &from, const Board &board) const override;
virtual std::vector<Move> getLegalMoves(const Square &from, Board &board) const override;
};
class Queen : public Piece {
@ -142,7 +142,7 @@ class Queen : public Piece {
pieceSymbol = 'Q';
pieceType = QUEEN;
}
virtual std::vector<Move> getLegalMoves(const Square &from, const Board &board) const override;
virtual std::vector<Move> getLegalMoves(const Square &from, Board &board) const override;
};
class Knight : public Piece {
@ -154,7 +154,7 @@ class Knight : public Piece {
pieceSymbol = 'N';
pieceType = KNIGHT;
}
virtual std::vector<Move> getLegalMoves(const Square &from, const Board &board) const override;
virtual std::vector<Move> getLegalMoves(const Square &from, Board &board) const override;
};
class Bishop : public Piece {
@ -166,7 +166,7 @@ class Bishop : public Piece {
pieceSymbol = 'B';
pieceType = BISHOP;
}
virtual std::vector<Move> getLegalMoves(const Square &from, const Board &board) const override;
virtual std::vector<Move> getLegalMoves(const Square &from, Board &board) const override;
};
class Pawn : public Piece {
@ -178,7 +178,7 @@ class Pawn : public Piece {
pieceSymbol = 'P';
pieceType = PAWN;
}
virtual std::vector<Move> getLegalMoves(const Square &from, const Board &board) const override;
virtual std::vector<Move> getLegalMoves(const Square &from, Board &board) const override;
};
#endif // PIECE_HPP

View file

@ -179,6 +179,8 @@ extern "C" int main(void) {
initInterrupts();
Board gameBoard;
NeoPixel boardLights(64);
gameBoard.setupInitialPosition();
while(1) {
}
}

View file

@ -54,7 +54,7 @@
<targetDevice>PIC32MX270F256B</targetDevice>
<targetHeader></targetHeader>
<targetPluginBoard></targetPluginBoard>
<platformTool>noID</platformTool>
<platformTool>snap</platformTool>
<languageToolchain>XC32</languageToolchain>
<languageToolchainVersion>4.60</languageToolchainVersion>
<platform>2</platform>
@ -73,7 +73,7 @@
</archiverTool>
<loading>
<useAlternateLoadableFile>false</useAlternateLoadableFile>
<parseOnProdLoad>true</parseOnProdLoad>
<parseOnProdLoad>false</parseOnProdLoad>
<alternateLoadableFile></alternateLoadableFile>
</loading>
<subordinates>
@ -87,7 +87,7 @@
<makeCustomizationPostStep></makeCustomizationPostStep>
<makeCustomizationPutChecksumInUserID>false</makeCustomizationPutChecksumInUserID>
<makeCustomizationEnableLongLines>false</makeCustomizationEnableLongLines>
<makeCustomizationNormalizeHexFile>false</makeCustomizationNormalizeHexFile>
<makeCustomizationNormalizeHexFile>true</makeCustomizationNormalizeHexFile>
</makeCustomizationType>
<C32>
<property key="additional-warnings" value="true"/>
@ -103,12 +103,12 @@
<property key="enable-short-double" value="false"/>
<property key="enable-symbols" value="true"/>
<property key="enable-unroll-loops" value="false"/>
<property key="exclude-floating-point" value="false"/>
<property key="exclude-floating-point" value="true"/>
<property key="expand-pragma-config" value="false"/>
<property key="extra-include-directories" value=""/>
<property key="generate-16-bit-code" value="false"/>
<property key="generate-micro-compressed-code" value="false"/>
<property key="isolate-each-function" value="false"/>
<property key="isolate-each-function" value="true"/>
<property key="keep-inline" value="false"/>
<property key="make-warnings-into-errors" value="true"/>
<property key="oXC16gcc-errata" value=""/>
@ -141,7 +141,7 @@
<C32-AS>
<property key="assembler-symbols" value=""/>
<property key="enable-symbols" value="true"/>
<property key="exclude-floating-point-library" value="false"/>
<property key="exclude-floating-point-library" value="true"/>
<property key="expand-macros" value="false"/>
<property key="extra-include-directories-for-assembler" value=""/>
<property key="extra-include-directories-for-preprocessor" value=""/>
@ -171,7 +171,7 @@
<property key="allocate-dinit" value="false"/>
<property key="code-dinit" value="false"/>
<property key="ebase-addr" value=""/>
<property key="enable-check-sections" value="false"/>
<property key="enable-check-sections" value="true"/>
<property key="enable-data-init" value="true"/>
<property key="enable-default-isr" value="true"/>
<property key="exclude-floating-point-library" value="false"/>
@ -214,18 +214,18 @@
<C32CPP>
<property key="additional-warnings" value="false"/>
<property key="addresss-attribute-use" value="false"/>
<property key="check-new" value="true"/>
<property key="check-new" value="false"/>
<property key="eh-specs" value="false"/>
<property key="enable-app-io" value="false"/>
<property key="enable-omit-frame-pointer" value="false"/>
<property key="enable-symbols" value="true"/>
<property key="enable-unroll-loops" value="false"/>
<property key="exceptions" value="false"/>
<property key="exclude-floating-point" value="false"/>
<property key="exclude-floating-point" value="true"/>
<property key="extra-include-directories" value=""/>
<property key="generate-16-bit-code" value="false"/>
<property key="generate-micro-compressed-code" value="false"/>
<property key="isolate-each-function" value="false"/>
<property key="isolate-each-function" value="true"/>
<property key="make-warnings-into-errors" value="false"/>
<property key="optimization-level" value=""/>
<property key="place-data-into-section" value="true"/>
@ -261,6 +261,172 @@
<property key="stack-smashing" value=""/>
<property key="wpo-lto" value="false"/>
</C32Global>
<Tool>
<property key="ADC 1" value="true"/>
<property key="AutoSelectMemRanges" value="auto"/>
<property key="CHANGE NOTICE" value="true"/>
<property key="COMPARATOR" value="true"/>
<property key="CTMU" value="true"/>
<property key="DMA" value="true"/>
<property key="Freeze All Other Peripherals" value="true"/>
<property key="I2C1" value="true"/>
<property key="I2C2" value="true"/>
<property key="INPUT CAPTURE 1" value="true"/>
<property key="INPUT CAPTURE 2" value="true"/>
<property key="INPUT CAPTURE 3" value="true"/>
<property key="INPUT CAPTURE 4" value="true"/>
<property key="INPUT CAPTURE 5" value="true"/>
<property key="INTERRUPT CONTROL" value="true"/>
<property key="OUTPUT COMPARE 1" value="true"/>
<property key="OUTPUT COMPARE 2" value="true"/>
<property key="OUTPUT COMPARE 3" value="true"/>
<property key="OUTPUT COMPARE 4" value="true"/>
<property key="OUTPUT COMPARE 5" value="true"/>
<property key="PARALLEL MASTER/SLAVE PORT" value="true"/>
<property key="REAL TIME CLOCK" value="true"/>
<property key="SPI/I2S 1" value="true"/>
<property key="SPI/I2S 2" value="true"/>
<property key="TIMER1" value="true"/>
<property key="TIMER2" value="true"/>
<property key="TIMER3" value="true"/>
<property key="TIMER4" value="true"/>
<property key="TIMER5" value="true"/>
<property key="ToolFirmwareFilePath"
value="Press to browse for a specific firmware version"/>
<property key="ToolFirmwareOption.UpdateOptions"
value="ToolFirmwareOption.UseLatest"/>
<property key="ToolFirmwareToolPack"
value="Press to select which tool pack to use"/>
<property key="UART1" value="true"/>
<property key="UART2" value="true"/>
<property key="USB" value="true"/>
<property key="communication.interface" value=""/>
<property key="communication.interface.jtag" value="2wire"/>
<property key="communication.speed" value="${communication.speed.default}"/>
<property key="debugoptions.debug-startup" value="Use system settings"/>
<property key="debugoptions.reset-behaviour" value="Use system settings"/>
<property key="debugoptions.simultaneous.debug" value="false"/>
<property key="debugoptions.useswbreakpoints" value="false"/>
<property key="event.recorder.debugger.behavior" value="Running"/>
<property key="event.recorder.enabled" value="false"/>
<property key="event.recorder.scvd.files" value=""/>
<property key="freeze.timers" value="false"/>
<property key="lastid" value=""/>
<property key="memories.aux" value="false"/>
<property key="memories.bootflash" value="true"/>
<property key="memories.configurationmemory" value="true"/>
<property key="memories.configurationmemory2" value="true"/>
<property key="memories.dataflash" value="true"/>
<property key="memories.eeprom" value="true"/>
<property key="memories.exclude.configurationmemory" value="true"/>
<property key="memories.flashdata" value="true"/>
<property key="memories.id" value="true"/>
<property key="memories.instruction.ram.ranges"
value="${memories.instruction.ram.ranges}"/>
<property key="memories.programmemory" value="true"/>
<property key="memories.programmemory.ranges" value="1d000000-1d03ffff"/>
<property key="programoptions.donoteraseauxmem" value="false"/>
<property key="programoptions.eraseb4program" value="true"/>
<property key="programoptions.pgmentry.voltage" value="low"/>
<property key="programoptions.pgmspeed" value="Max"/>
<property key="programoptions.preservedataflash" value="false"/>
<property key="programoptions.preservedataflash.ranges"
value="${memories.dataflash.default}"/>
<property key="programoptions.preserveeeprom" value="false"/>
<property key="programoptions.preserveeeprom.ranges" value=""/>
<property key="programoptions.preserveprogram.ranges" value=""/>
<property key="programoptions.preserveprogramrange" value="false"/>
<property key="programoptions.programcalmem" value="false"/>
<property key="programoptions.programuserotp" value="false"/>
<property key="programoptions.testmodeentrymethod" value="VDDFirst"/>
<property key="toolpack.updateoptions"
value="toolpack.updateoptions.uselatestoolpack"/>
<property key="toolpack.updateoptions.packversion"
value="Press to select which tool pack to use"/>
</Tool>
<snap>
<property key="ADC 1" value="true"/>
<property key="AutoSelectMemRanges" value="auto"/>
<property key="CHANGE NOTICE" value="true"/>
<property key="COMPARATOR" value="true"/>
<property key="CTMU" value="true"/>
<property key="DMA" value="true"/>
<property key="Freeze All Other Peripherals" value="true"/>
<property key="I2C1" value="true"/>
<property key="I2C2" value="true"/>
<property key="INPUT CAPTURE 1" value="true"/>
<property key="INPUT CAPTURE 2" value="true"/>
<property key="INPUT CAPTURE 3" value="true"/>
<property key="INPUT CAPTURE 4" value="true"/>
<property key="INPUT CAPTURE 5" value="true"/>
<property key="INTERRUPT CONTROL" value="true"/>
<property key="OUTPUT COMPARE 1" value="true"/>
<property key="OUTPUT COMPARE 2" value="true"/>
<property key="OUTPUT COMPARE 3" value="true"/>
<property key="OUTPUT COMPARE 4" value="true"/>
<property key="OUTPUT COMPARE 5" value="true"/>
<property key="PARALLEL MASTER/SLAVE PORT" value="true"/>
<property key="REAL TIME CLOCK" value="true"/>
<property key="SPI/I2S 1" value="true"/>
<property key="SPI/I2S 2" value="true"/>
<property key="TIMER1" value="true"/>
<property key="TIMER2" value="true"/>
<property key="TIMER3" value="true"/>
<property key="TIMER4" value="true"/>
<property key="TIMER5" value="true"/>
<property key="ToolFirmwareFilePath"
value="Press to browse for a specific firmware version"/>
<property key="ToolFirmwareOption.UpdateOptions"
value="ToolFirmwareOption.UseLatest"/>
<property key="ToolFirmwareToolPack"
value="Press to select which tool pack to use"/>
<property key="UART1" value="true"/>
<property key="UART2" value="true"/>
<property key="USB" value="true"/>
<property key="communication.interface" value=""/>
<property key="communication.interface.jtag" value="2wire"/>
<property key="communication.speed" value="${communication.speed.default}"/>
<property key="debugoptions.debug-startup" value="Use system settings"/>
<property key="debugoptions.reset-behaviour" value="Use system settings"/>
<property key="debugoptions.simultaneous.debug" value="false"/>
<property key="debugoptions.useswbreakpoints" value="false"/>
<property key="event.recorder.debugger.behavior" value="Running"/>
<property key="event.recorder.enabled" value="false"/>
<property key="event.recorder.scvd.files" value=""/>
<property key="freeze.timers" value="false"/>
<property key="lastid" value=""/>
<property key="memories.aux" value="false"/>
<property key="memories.bootflash" value="true"/>
<property key="memories.configurationmemory" value="true"/>
<property key="memories.configurationmemory2" value="true"/>
<property key="memories.dataflash" value="true"/>
<property key="memories.eeprom" value="true"/>
<property key="memories.exclude.configurationmemory" value="true"/>
<property key="memories.flashdata" value="true"/>
<property key="memories.id" value="true"/>
<property key="memories.instruction.ram.ranges"
value="${memories.instruction.ram.ranges}"/>
<property key="memories.programmemory" value="true"/>
<property key="memories.programmemory.ranges" value="1d000000-1d03ffff"/>
<property key="programoptions.donoteraseauxmem" value="false"/>
<property key="programoptions.eraseb4program" value="true"/>
<property key="programoptions.pgmentry.voltage" value="low"/>
<property key="programoptions.pgmspeed" value="Max"/>
<property key="programoptions.preservedataflash" value="false"/>
<property key="programoptions.preservedataflash.ranges"
value="${memories.dataflash.default}"/>
<property key="programoptions.preserveeeprom" value="false"/>
<property key="programoptions.preserveeeprom.ranges" value=""/>
<property key="programoptions.preserveprogram.ranges" value=""/>
<property key="programoptions.preserveprogramrange" value="false"/>
<property key="programoptions.programcalmem" value="false"/>
<property key="programoptions.programuserotp" value="false"/>
<property key="programoptions.testmodeentrymethod" value="VDDFirst"/>
<property key="toolpack.updateoptions"
value="toolpack.updateoptions.uselatestoolpack"/>
<property key="toolpack.updateoptions.packversion"
value="Press to select which tool pack to use"/>
</snap>
</conf>
<conf name="Production" type="2">
<toolsSet>