Compare commits
No commits in common. "c54e2b9e1ab6bf31d6072d4f5a92695e8d586b4d" and "65015c9a6ca6c76b14946cfd266a899e7118e2e4" have entirely different histories.
c54e2b9e1a
...
65015c9a6c
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
5
Board.h
5
Board.h
|
|
@ -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
|
||||||
|
|
|
||||||
4
Config.h
4
Config.h
|
|
@ -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
|
|
||||||
12
Movegen.h
12
Movegen.h
|
|
@ -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,7 +166,6 @@ 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};
|
return Move{square, target_square, P_EMPTY};
|
||||||
|
|
@ -182,7 +181,6 @@ Move Movegen::generate_pawn() {
|
||||||
return Move{square, target_square, P_EMPTY};
|
return Move{square, target_square, P_EMPTY};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// fall through
|
// fall through
|
||||||
case 3:
|
case 3:
|
||||||
// capture right or EP-capture right
|
// capture right or EP-capture right
|
||||||
|
|
@ -190,7 +188,6 @@ 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};
|
return Move{square, target_square, P_EMPTY};
|
||||||
|
|
@ -206,7 +203,6 @@ Move Movegen::generate_pawn() {
|
||||||
return Move{square, target_square, P_EMPTY};
|
return Move{square, target_square, P_EMPTY};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// fall through
|
// fall through
|
||||||
case 4:
|
case 4:
|
||||||
// try promoting (queen)
|
// try promoting (queen)
|
||||||
|
|
|
||||||
16
Panic.h
16
Panic.h
|
|
@ -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);
|
||||||
|
|
|
||||||
8
Types.h
8
Types.h
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue