Compare commits

..

No commits in common. "c54e2b9e1ab6bf31d6072d4f5a92695e8d586b4d" and "65015c9a6ca6c76b14946cfd266a899e7118e2e4" have entirely different histories.

6 changed files with 34 additions and 151 deletions

View File

@ -9,61 +9,6 @@
#include "Movegen.h" #include "Movegen.h"
#include "Types.h" #include "Types.h"
unsigned long pseudo_perft(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();
if(m.sq_to != 255) {
make(m);
move_count += pseudo_perft(depth-1);
unmake();
} else {
break;
}
}
return move_count;
}
void perft_test() {
for(byte i = 0; i < 5; i++) {
Serial.print(F("Perft "));
Serial.print(i);
Serial.print(F(": "));
Serial.println(pseudo_perft(i));
}
}
void debug_movegen() {
make({0x14, 0x34, P_EMPTY});
Movegen gen = Movegen();
Move m;
do {
DEBUG("start movegen");
m = gen.next_move();
Serial.print(F("FROM "));
Serial.print(m.sq_from, HEX);
Serial.print(F(" TO "));
Serial.print(m.sq_to, HEX);
Serial.print(F(" PROMOTE "));
Serial.println(m.pc_prom);
if(m.sq_from != 255) {
DEBUG("make");
make(m);
print();
DEBUG("unmake");
unmake();
DEBUG("unmake done");
}
} while (m.sq_from != 255);
}
void debug_castle() { void debug_castle() {
print(); print();
make({0x06, 0x25, P_EMPTY}); print(); make({0x06, 0x25, P_EMPTY}); print();
@ -107,7 +52,7 @@ void debug_ep() {
} }
void bench() { void bench() {
unsigned long startTime = micros(); int startTime = micros();
make({0x14, 0x34, P_EMPTY}); make({0x14, 0x34, P_EMPTY});
make({0x64, 0x54, P_EMPTY}); make({0x64, 0x54, P_EMPTY});
@ -136,38 +81,9 @@ void bench() {
unmake(); unmake();
unsigned long elapsed = micros() - startTime; int elapsed = micros() - startTime;
Serial.print(elapsed); Serial.print(elapsed);
Serial.println(F(" microseconds for make/unmake")); Serial.println(F(" microseconds"));
for(int i = 1; i <= 4; i++) {
startTime = millis();
pseudo_perft(i);
elapsed = millis() - startTime;
Serial.print(elapsed);
Serial.print(F(" milliseconds for pseudo_perft("));
Serial.print(i);
Serial.println(')');
}
Movegen gen;
Move move[20];
startTime = micros();
for(int i = 0; i < 20; i++) {
move[i] = gen.next_move();
}
elapsed = micros() - startTime;
Serial.print(elapsed);
Serial.println(F(" microseconds for movegen(init_pos)"));
startTime = micros();
for(int i = 0; i < 20; i++) {
make(move[i]);
unmake();
}
elapsed = micros() - startTime;
Serial.print(elapsed);
Serial.println(F(" microseconds for make/unmake(init_pos)"));
} }
@ -175,8 +91,6 @@ void setup() {
// put your setup code here, to run once: // put your setup code here, to run once:
board_init(); board_init();
Serial.begin(115200); Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
perft_test();
bench(); bench();
} }

View File

@ -34,7 +34,7 @@
#define PTR_UNMOVE_LAST 0x7F #define PTR_UNMOVE_LAST 0x7F
byte field[128]; byte field[128];
byte PTR_UNMOVE; byte PTR_UNMOVE = PTR_UNMOVE_START;
const byte field_default_value[] PROGMEM = BOARD_DEFAULT_VALUE; const byte field_default_value[] PROGMEM = BOARD_DEFAULT_VALUE;
@ -42,7 +42,6 @@ void board_init() {
for(int i = 0; i < 128; i++) { for(int i = 0; i < 128; i++) {
field[i] = pgm_read_byte_near(field_default_value + i); field[i] = pgm_read_byte_near(field_default_value + i);
} }
PTR_UNMOVE = PTR_UNMOVE_START;
field[PTR_SIDE_AND_CASTLERIGHT] = 0b11110; // all castle rights allowed, white to move field[PTR_SIDE_AND_CASTLERIGHT] = 0b11110; // all castle rights allowed, white to move
field[PTR_W_KING] = 0x04; // e1 field[PTR_W_KING] = 0x04; // e1
field[PTR_B_KING] = 0x74; // e8 field[PTR_B_KING] = 0x74; // e8
@ -268,7 +267,7 @@ void unmake() {
field[PTR_SIDE_AND_CASTLERIGHT] |= 0b01 << castleright_offset; field[PTR_SIDE_AND_CASTLERIGHT] |= 0b01 << castleright_offset;
} }
int sq_diff = (int)sq_to - (int)sq_from; int sq_diff = (int)sq_to - (int)u.sq_from;
int sq_diff_abs = abs(sq_diff); int sq_diff_abs = abs(sq_diff);
if((field[sq_from] & 0x7) == W_KING && sq_diff_abs == 2) { if((field[sq_from] & 0x7) == W_KING && sq_diff_abs == 2) {
// we castled // we castled

View File

@ -5,7 +5,3 @@
// PANIC_BLINK makes the Arduino blink an error code when it panics. // PANIC_BLINK makes the Arduino blink an error code when it panics.
// Costs a lot of flash though (around 700 bytes) // Costs a lot of flash though (around 700 bytes)
//#define _ACF_PANIC_BLINK //#define _ACF_PANIC_BLINK
#define _ACF_DEBUG_PRINT
#define _ACF_ACTIVITY_BLINK

View File

@ -25,7 +25,7 @@ class Movegen {
}; };
Move Movegen::next_move() { Move Movegen::next_move() {
while(square <= 0x77) { while(square <= 0x7F) {
if(square & 0x88) square += 8; if(square & 0x88) square += 8;
byte piece_type = field[square] & 0x7; byte piece_type = field[square] & 0x7;
@ -37,11 +37,14 @@ Move Movegen::next_move() {
// there is an own piece to investigate // there is an own piece to investigate
Move m; Move m;
if(piece_type == W_PAWN) { if(piece_type == W_PAWN) {
Serial.println("GENERATE PAWN");
m = generate_pawn(); m = generate_pawn();
} else if(piece_type & 0b0100) { } else if(piece_type & 0b0100) {
Serial.println("GENERATE SLIDING");
// bishop, rook and queen are 01xx. // bishop, rook and queen are 01xx.
m = generate_sliding(piece_type); m = generate_sliding(piece_type);
} else { } else {
Serial.println("GENERATE NONSLIDING");
m = generate_non_sliding(piece_type); m = generate_non_sliding(piece_type);
} }
if(m.sq_to != 255) { if(m.sq_to != 255) {
@ -50,7 +53,6 @@ Move Movegen::next_move() {
} }
square++; square++;
direction = 0; direction = 0;
target_square = square;
} }
return INVALID_MOVE; return INVALID_MOVE;
} }
@ -123,8 +125,6 @@ Move Movegen::generate_non_sliding(byte piece_type) {
} }
Move Movegen::generate_pawn() { Move Movegen::generate_pawn() {
// TODO: implement capture promotion
byte color = black_moving(); byte color = black_moving();
byte offset; byte offset;
byte target; byte target;
@ -166,21 +166,19 @@ Move Movegen::generate_pawn() {
offset = color ? -0x11 : 0xF; offset = color ? -0x11 : 0xF;
target_square = square + offset; target_square = square + offset;
target = field[target_square]; target = field[target_square];
if(!(target_square & 0x88)) { if(target && (target & 0x8) != (field[square] & 0x8)) {
if(target && (target & 0x8) != (field[square] & 0x8)) { // normal capture allowded
// normal capture allowded return Move{square, target_square, P_EMPTY};
} else if(field[PTR_ENPASSANT]) {
// note that EP being legal only happens
// when the target field is empty. so this saves some effort.
byte ep_col = field[PTR_ENPASSANT] & 0x7;
if(
ep_col == (target_square & 0x7) &&
(square & 0x70) == (color ? 0x30 : 0x40)
) {
// EP-capture possible
return Move{square, target_square, P_EMPTY}; return Move{square, target_square, P_EMPTY};
} else if(field[PTR_ENPASSANT]) {
// note that EP being legal only happens
// when the target field is empty. so this saves some effort.
byte ep_col = field[PTR_ENPASSANT] & 0x7;
if(
ep_col == (target_square & 0x7) &&
(square & 0x70) == (color ? 0x30 : 0x40)
) {
// EP-capture possible
return Move{square, target_square, P_EMPTY};
}
} }
} }
// fall through // fall through
@ -190,21 +188,19 @@ Move Movegen::generate_pawn() {
offset = color ? -0xF : 0x11; offset = color ? -0xF : 0x11;
target_square = square + offset; target_square = square + offset;
target = field[target_square]; target = field[target_square];
if(!(target_square & 0x88)) { if(target && (target & 0x8) != (field[square] & 0x8)) {
if(target && (target & 0x8) != (field[square] & 0x8)) { // normal capture allowded
// normal capture allowded return Move{square, target_square, P_EMPTY};
} else if(field[PTR_ENPASSANT]) {
// note that EP being legal only happens
// when the target field is empty. so this saves some effort.
byte ep_col = field[PTR_ENPASSANT] & 0x7;
if(
ep_col == (target_square & 0x7) &&
(square & 0x70) == (color ? 0x30 : 0x40)
) {
// EP-capture possible
return Move{square, target_square, P_EMPTY}; return Move{square, target_square, P_EMPTY};
} else if(field[PTR_ENPASSANT]) {
// note that EP being legal only happens
// when the target field is empty. so this saves some effort.
byte ep_col = field[PTR_ENPASSANT] & 0x7;
if(
ep_col == (target_square & 0x7) &&
(square & 0x70) == (color ? 0x30 : 0x40)
) {
// EP-capture possible
return Move{square, target_square, P_EMPTY};
}
} }
} }
// fall through // fall through

16
Panic.h
View File

@ -4,23 +4,9 @@
#pragma GCC push_options #pragma GCC push_options
#pragma GCC optimize("-Os") #pragma GCC optimize("-Os")
#ifdef _ACF_ACTIVITY_BLINK
bool ledhi;
void blink() {
ledhi = !ledhi;
if(ledhi) {
digitalWrite(LED_BUILTIN, HIGH);
} else {
digitalWrite(LED_BUILTIN, LOW);
}
}
#else
void blink() {}
#endif
#ifdef _ACF_PANIC_BLINK #ifdef _ACF_PANIC_BLINK
void sos() { void sos() {
pinMode(LED_BUILTIN, OUTPUT);
while(true) { while(true) {
digitalWrite(LED_BUILTIN, HIGH); digitalWrite(LED_BUILTIN, HIGH);
delay(500); delay(500);

View File

@ -1,14 +1,6 @@
#ifndef __TYPES_H_INC #ifndef __TYPES_H_INC
#define __TYPES_H_INC #define __TYPES_H_INC
#include "Config.h""
#ifdef _ACF_DEBUG_PRINT
#define DEBUG(x) Serial.println(F(x)); Serial.flush()
#else
#define DEBUG(x)
#endif
enum Piece: byte { enum Piece: byte {
P_EMPTY = 0b0000, P_EMPTY = 0b0000,
P_ANY = 0b1000, P_ANY = 0b1000,