Skip to content

Commit

Permalink
Basic play demo
Browse files Browse the repository at this point in the history
  • Loading branch information
bungogood committed Oct 7, 2024
1 parent da5a89b commit 48619c5
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 92 deletions.
2 changes: 0 additions & 2 deletions include/fsm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,3 @@ typedef struct {
FSMState update_state(Chess *chess, int instruction, FSMState state,
State_Memory *state_memory, Move_List *move_list,
Move_List *current_square_moves);

void print_bitboard(unsigned long long bitboard);
18 changes: 12 additions & 6 deletions lib/chess/include/chess.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

#include <string>
#include <cstdint>
#include <string>
typedef int Square;
typedef int Player;

Expand Down Expand Up @@ -56,7 +56,11 @@ typedef struct {
std::string square_to_string(const Square square);
std::string move_to_string(const Move move);

extern Move_List chess_move_lists[3];
int to_square(int file, int rank);
int to_square(int index);
int to_index(int square);

extern Move_List chess_move_lists[4];

class Chess {
private:
Expand All @@ -79,17 +83,19 @@ class Chess {
uint64_t get_black();
int get_piece_on_square(int square);
void print_board();
Move parse_move(const char *move_string, Move_List *move_list);
Move parse_move(const char *move_string);
Move parse_move(Square source_square, Square target_square);
Move parse_move(Square source_square, Square target_square,
char promoted_piece);
int search_position(Player side, int alpha, int beta, int depth,
Search_Info *search_info, Move_List *move_lists);
Search_Info *search_info);
int quiescence_search(Player side, int alpha, int beta);
int generate_moves(Move_List *move_list, bool only_captures = false);
inline int evaluate_position(Player side);
void unmake_move(Move move, Square old_ep);
void make_move(Move move);

void get_best_move(int depth, Search_Info *search_info,
Move_List *move_lists);
void get_best_move(int depth, Search_Info *search_info);

char square_char(int square);
std::string get_fen();
Expand Down
56 changes: 42 additions & 14 deletions lib/chess/src/chess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ static const int move_offsets[] = {
static const int piece_weights[] = {0, 0, -100, 0, -300, -350, -500, -900,
0, 100, 0, 0, 300, 350, 500, 900};

Move_List chess_move_lists[4];

Chess::Chess() : side(WHITE), en_passant(128) {
// initialize board
}
Expand Down Expand Up @@ -454,9 +456,9 @@ int Chess::quiescence_search(Player side, int alpha,
}

int Chess::search_position(Player side, int alpha, int beta, int depth,
Search_Info *search_info, Move_List *move_lists) {
Search_Info *search_info) {
// Move_List move_list[1];
Move_List *move_list = &move_lists[depth - 1];
Move_List *move_list = &chess_move_lists[depth - 1];
int old_alpha = alpha;
Square old_ep = en_passant;
Move move;
Expand All @@ -478,8 +480,8 @@ int Chess::search_position(Player side, int alpha, int beta, int depth,
}

make_move(move_list->moves[i]); // make move
int score = -search_position(24 - side, -beta, -alpha, depth - 1,
search_info, move_lists);
int score =
-search_position(24 - side, -beta, -alpha, depth - 1, search_info);
unmake_move(move_list->moves[i], old_ep); // take back

search_info->best_move = move_list->moves[i]; // store best move so far
Expand All @@ -500,9 +502,8 @@ int Chess::search_position(Player side, int alpha, int beta, int depth,
return alpha;
}

void Chess::get_best_move(int depth, Search_Info *search_info,
Move_List *move_lists) {
search_position(side, -10000, 10000, depth, search_info, move_lists);
void Chess::get_best_move(int depth, Search_Info *search_info) {
search_position(side, -10000, 10000, depth, search_info);
}

/*********************************************************************************\
Expand All @@ -511,31 +512,53 @@ void Chess::get_best_move(int depth, Search_Info *search_info,
;---------------------------------------------------------------------------------;
\*********************************************************************************/

Move Chess::parse_move(const char *move_string, Move_List *move_list) {
Move Chess::parse_move(Square source_square, Square target_square,
char promoted_piece) {
Move move;
Move_List *move_list = &chess_move_lists[0];
generate_moves(move_list, false);

for (int i = 0; i < move_list->length; i++) {
move = move_list->moves[i];

if (move.source_square == (move_string[0] - 'a') +
(7 - (move_string[1] - '0' - 1)) * 16 &&
move.target_square == (move_string[2] - 'a') +
(7 - (move_string[3] - '0' - 1)) * 16) {
if (move.promoted_piece) {
if (promoted_pieces[move.promoted_piece] == move_string[4])
if (move.source_square == source_square &&
move.target_square == target_square) {
// Check promotion piece if provided
if (promoted_piece) {
if (move.promoted_piece &&
promoted_pieces[move.promoted_piece] == promoted_piece) {
return move;
}
continue;
}

// Return move if no promotion check is needed
return move;
}
}

// Return an invalid move if no match is found
move.promoted_piece = move.target_square = move.source_square = 0;
return move;
}

Move Chess::parse_move(Square source_square, Square target_square) {
return parse_move(source_square, target_square, 0);
}

Move Chess::parse_move(const char *move_string) {
Square source_square =
(move_string[0] - 'a') + (7 - (move_string[1] - '0' - 1)) * 16;
Square target_square =
(move_string[2] - 'a') + (7 - (move_string[3] - '0' - 1)) * 16;

// Check if the move string includes a promotion character
char promoted_piece = move_string[4];

// Delegate to the overloaded parse_move function
return parse_move(source_square, target_square, promoted_piece);
}

void Chess::print_board() {
for (int i = 0; i < 128; i++) {
if (!(i % 16)) printf(" %d ", 8 - (i / 16));
Expand Down Expand Up @@ -605,3 +628,8 @@ std::string move_to_string(const Move move) {
str += square_to_string(move.target_square);
return str;
}

// do the to square with the 7 - rank to get the correct square
int to_square(int file, int rank) { return ((7 - rank) << 4) + file; }
int to_square(int index) { return to_square(index & 7, index >> 3); }
int to_index(int square) { return (7 - (square >> 4)) * 8 + (square & 7); }
82 changes: 69 additions & 13 deletions src/bin/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <string>

#include "bluetooth.hpp"
#include "controller.hpp"
#include "fsm.hpp"

Expand Down Expand Up @@ -52,16 +53,21 @@ std::vector<std::string> game = {
// clang-format on

FSMState state;
Move_List move_list[4];

void replay() {
for (std::string moveStr : game) {
Move move = chess.parse_move(moveStr.c_str(), move_list);
Move move = chess.parse_move(moveStr.c_str());
controller.makeMove(move, 500);
delay(1000);
}
}

uint64_t prevBoard;

State_Memory state_memory;
Move_List cur;
Move_List other;

void setup() {
Serial.begin(9600);
delay(1000);
Expand All @@ -75,16 +81,20 @@ void setup() {
// controller.makeMove(move, 500);
// board.gotoSquare(SQB4);
// replay();
state = FSMState::EnemyPU;

prevBoard = detection.read();
// state = FSMState::EnemyPU;
state = FSMState::Idle;
ble.setFSMState(state);
ble.setReedSwitchValue(0);
ble.setReedSwitchValue(prevBoard);
}

void enemy() {
if (ble.getMoveUpdated()) {
delay(10); // FIX: delay stops ble crash
std::string moveStr = ble.readMove();
Move move = chess.parse_move(moveStr.c_str(), move_list);
Serial.println(moveStr.c_str());
Move move = chess.parse_move(moveStr.c_str());
chess.make_move(move);
state = FSMState::FriendlyPU;
ble.setFEN(chess.get_fen());
Expand All @@ -95,7 +105,7 @@ void enemy() {

void friendly() {
Search_Info search_info;
chess.get_best_move(3, &search_info, move_list);
chess.get_best_move(3, &search_info);
Move move = search_info.best_move;
chess.make_move(move);
state = FSMState::EnemyPU;
Expand All @@ -104,13 +114,59 @@ void friendly() {
ble.setFSMState(state);
}

int countOnes(uint64_t value) {
return __builtin_popcountll(value); // Works for uint64_t
}

int findLSBIndex(uint64_t value) {
if (value == 0) return -1; // No bits are set, return -1
// ffsll returns 1-based index, so subtract 1 for 0-based index
return __builtin_ffsll(value) - 1;
}

void loop() {
switch (state) {
case FSMState::EnemyPU:
enemy();
break;
case FSMState::FriendlyPU:
friendly();
break;
// switch (state) {
// case FSMState::EnemyPU:
// enemy();
// break;
// case FSMState::FriendlyPU:
// friendly();
// break;
// }
uint64_t currentBoard = detection.read();
ble.setReedSwitchValue(currentBoard);
delay(10);
uint64_t diff = currentBoard ^ prevBoard;
if (diff && countOnes(diff) == 1) {
bool pickedUp = prevBoard & diff;
// xor and find the changed bit and its index
int sq8x8 = findLSBIndex(diff);
int square = to_square(sq8x8);
if (pickedUp) {
Serial.println("Picked up: " + String(sq8x8) +
" Square: " + String(square));
} else {
Serial.println("Put down: " + String(sq8x8) +
" Square: " + String(square));
}

chess.generate_moves(&cur);
state =
update_state(&chess, square, state, &state_memory, &cur, &other);

if (state == FSMState::MoveComplete) {
ble.setFEN(chess.get_fen());
state = FSMState::Idle;
state_memory.length = 0;
}

ble.setFSMState(state);
Serial.println(String(fsm_state_string(state).c_str()) + " " +
String(state_memory.length));
} else if (state == FSMState::Error &&
currentBoard == chess.get_occupied()) {
state = FSMState::Idle;
ble.setFSMState(state);
}
prevBoard = currentBoard;
}
1 change: 1 addition & 0 deletions src/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Controller::Controller(Board* board, ReedMatrix* detection, Chess* chess,

void Controller::init() {
board->init();
detection->init();
indicator->init();
indicator->set(Color::RED);
bluetooth->begin("Gambit");
Expand Down
Loading

0 comments on commit 48619c5

Please sign in to comment.