diff --git a/Board.h b/Board.h index ab4fca2..900a9d5 100644 --- a/Board.h +++ b/Board.h @@ -51,7 +51,9 @@ namespace Board { *zob = 0xDEADBEEF; } - + void swap_side() { + field[PTR_SIDE_AND_CASTLERIGHT] ^= 0x01; + } struct Unmove { byte sq_from; // 0b(1kingside_castle?)(3rank)(1queenside_castle?)(3file) @@ -151,17 +153,21 @@ namespace Board { // TODO test the castling code more extensively // Handle castling - if(piece_type == W_KING && sq_diff_abs == 2) { - // We are castling! After all, a king cannot move - // more than one position except when castling. - // Since we don't care about legality; just do it - byte castle_source = (color ? 0x70 : 0x0); - if(sq_diff == 2) { - castle_source += 0x7; + if(piece_type == W_KING) { + // Update the king position + field[PTR_W_KING | Board::black_moving()] = m.sq_to; + if(sq_diff_abs == 2) { + // We are castling! After all, a king cannot move + // more than one position except when castling. + // Since we don't care about legality; just do it + byte castle_source = (color ? 0x70 : 0x0); + if(sq_diff == 2) { + castle_source += 0x7; + } + byte castle_target = m.sq_from + (sq_diff/2); + field[castle_target] = field[castle_source]; + field[castle_source] = P_EMPTY; } - byte castle_target = m.sq_from + (sq_diff/2); - field[castle_target] = field[castle_source]; - field[castle_source] = P_EMPTY; } // Handle castling rights @@ -267,27 +273,32 @@ namespace Board { field[PTR_SIDE_AND_CASTLERIGHT] |= 0b01 << castleright_offset; } + field[PTR_SIDE_AND_CASTLERIGHT] ^= 0x01; + int sq_diff = (int)sq_to - (int)sq_from; int sq_diff_abs = abs(sq_diff); - if((field[sq_from] & 0x7) == W_KING && sq_diff_abs == 2) { - // we castled - byte castle_source = 0x70*!black_moving(); - if(sq_diff == 2) { - castle_source += 0x7; + if((field[sq_from] & 0x7) == W_KING) { + field[PTR_W_KING | Board::black_moving()] = sq_from; + if(sq_diff_abs == 2) { + // we castled + byte castle_source = 0x70*black_moving(); + if(sq_diff == 2) { + castle_source += 0x7; + } + byte castle_target = sq_from + (sq_diff/2); + // move rook back to original position + field[castle_source] = field[castle_target]; + // and clear where it was put + field[castle_target] = P_EMPTY; } - byte castle_target = sq_from + (sq_diff/2); - // move rook back to original position - field[castle_source] = field[castle_target]; - // and clear where it was put - field[castle_target] = P_EMPTY; } field[sq_to] = u.captured & 0b1111; - field[PTR_SIDE_AND_CASTLERIGHT] ^= 0x01; field[PTR_ENPASSANT] = u.captured >> 4; } + } diff --git a/Config.h b/Config.h index e570758..0ed5df9 100644 --- a/Config.h +++ b/Config.h @@ -8,4 +8,7 @@ #define _ACF_DEBUG_PRINT -#define _ACF_ACTIVITY_BLINK \ No newline at end of file +#define _ACF_ACTIVITY_BLINK + +//#define _ACF_BENCH_BIG + diff --git a/Movegen.h b/Movegen.h index e6290f2..69026b9 100644 --- a/Movegen.h +++ b/Movegen.h @@ -2,6 +2,7 @@ #define __MOVEGEN_H_INC #include "Types.h" +#include "Board.h" const static byte SLIDE_OFFSETS[] = {255, 1, 240, 16, 15, 17, 241, 239}; const static byte KNIGHT_OFFSETS[] = {225, 31, 223, 33, 238, 18, 242, 14}; diff --git a/Tasks.h b/Tasks.h index 4ba660e..7e1ac07 100644 --- a/Tasks.h +++ b/Tasks.h @@ -3,6 +3,7 @@ #include "Types.h" #include "Movegen.h" +#include "Threat.h" unsigned long pseudo_perft(byte depth) { // only checks pseudolegality @@ -17,7 +18,37 @@ unsigned long pseudo_perft(byte depth) { m = gen.next_move(); if(m.sq_to != 255) { Board::make(m); - move_count += pseudo_perft(depth-1); + if(!Threat::illegal()) { + move_count += pseudo_perft(depth-1); + } else { + //Board::print(); + } + Board::unmake(); + } else { + break; + } + } + return move_count; +} + +unsigned long divide(byte depth) { + // only checks pseudolegality + // but, it should work overall + if(depth == 0) return 1; + if(depth == 3) blink(); + unsigned long move_count = 0; + Movegen gen; + Move m; + + while (true) { + m = gen.next_move(); + print_move(m); + Serial.print(F(" ")); + if(m.sq_to != 255) { + Board::make(m); + int count = pseudo_perft(depth-1); + Serial.println(count); + move_count += count; Board::unmake(); } else { break; @@ -77,6 +108,15 @@ void debug_castle() { Board::unmake(); Board::print(); } +void debug_check() { + Board::make({0x14, 0x34, P_EMPTY}); + Board::make({0x63, 0x43, P_EMPTY}); + Board::make({0x05, 0x41, P_EMPTY}); + Board::print(); + + Serial.println(Threat::is_check()); +} + void debug_ep() { Board::print(); Board::make({0x14, 0x34, P_EMPTY}); @@ -104,7 +144,11 @@ void debug_ep() { void bench() { // TODO reduce code size of this (by moving repeated constants from here to PROGMEM and loops?) - unsigned long startTime = micros(); + unsigned long startTime; + unsigned long elapsed; + + #ifdef _ACF_BENCH_BIG + startTime = micros(); Board::make({0x14, 0x34, P_EMPTY}); Board::make({0x64, 0x54, P_EMPTY}); @@ -133,9 +177,10 @@ void bench() { Board::unmake(); - unsigned long elapsed = micros() - startTime; + elapsed = micros() - startTime; Serial.print(elapsed); Serial.println(F(" microseconds for make/unmake")); + #endif for(int i = 1; i <= 4; i++) { startTime = millis(); @@ -167,4 +212,4 @@ void bench() { Serial.println(F(" microseconds for make/unmake(init_pos)")); } -#endif \ No newline at end of file +#endif diff --git a/Types.h b/Types.h index ed4848c..ee7acb6 100644 --- a/Types.h +++ b/Types.h @@ -50,4 +50,19 @@ struct Move { //Move move_from_str(char* s) { //} +void print_sq(byte sq) { + Serial.print((char)((sq & 0x07) + 'a')); + Serial.print((char)(((sq & 0x70) >> 4) + '1')); +} +void print_move(Move m) { + if(m.sq_from == 0xFF) { + Serial.print(F("INVALID_MOVE")); + return; + } + print_sq(m.sq_from); + print_sq(m.sq_to); + byte pc = m.pc_prom & 0x7; + if(pc != 0) Serial.print(piece_to_char(pc)); +} + #endif diff --git a/Uci.h b/Uci.h index 01deb5c..932a86a 100644 --- a/Uci.h +++ b/Uci.h @@ -39,7 +39,7 @@ namespace Uci { int depth = Serial.parseInt(); unsigned long startTime = millis(); - unsigned long result = pseudo_perft(depth); + unsigned long result = divide(depth); unsigned long elapsed = millis() - startTime; Serial.print(F("perft("));