Impl UCI bench and perft

This commit is contained in:
Quinten Kock 2020-06-20 03:26:33 +02:00
parent fd1158c0c8
commit 21e956519e
3 changed files with 194 additions and 162 deletions

View File

@ -10,168 +10,6 @@
#include "Types.h"
#include "Uci.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() {
print();
make({0x06, 0x25, P_EMPTY}); print();
make({0x76, 0x55, P_EMPTY}); print();
make({0x16, 0x26, P_EMPTY}); print();
make({0x63, 0x43, P_EMPTY}); print();
make({0x05, 0x16, P_EMPTY}); print();
make({0x62, 0x42, P_EMPTY}); print();
make({0x04, 0x06, P_EMPTY}); print();
unmake(); print();
unmake(); print();
unmake(); print();
unmake(); print();
unmake(); print();
unmake(); print();
unmake(); print();
}
void debug_ep() {
print();
make({0x14, 0x34, P_EMPTY});
print();
make({0x64, 0x54, P_EMPTY});
print();
make({0x34, 0x44, P_EMPTY});
print();
make({0x63, 0x43, P_EMPTY});
print();
make({0x44, 0x53, P_EMPTY});
print();
unmake();
print();
unmake();
print();
unmake();
print();
unmake();
print();
unmake();
print();
}
void bench() {
unsigned long startTime = micros();
make({0x14, 0x34, P_EMPTY});
make({0x64, 0x54, P_EMPTY});
make({0x34, 0x44, P_EMPTY});
make({0x63, 0x43, P_EMPTY});
make({0x44, 0x53, P_EMPTY});
unmake();
unmake();
unmake();
unmake();
unmake();
make({0x06, 0x25, P_EMPTY});
make({0x76, 0x55, P_EMPTY});
make({0x16, 0x26, P_EMPTY});
make({0x63, 0x43, P_EMPTY});
make({0x05, 0x16, P_EMPTY});
make({0x62, 0x42, P_EMPTY});
make({0x04, 0x06, P_EMPTY});
unmake();
unmake();
unmake();
unmake();
unmake();
unmake();
unmake();
unsigned long elapsed = micros() - startTime;
Serial.print(elapsed);
Serial.println(F(" microseconds for make/unmake"));
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)"));
}
void setup() {
// put your setup code here, to run once:
board_init();

167
Tasks.h Normal file
View File

@ -0,0 +1,167 @@
#ifndef __TASKS_H_INC
#define __TASKS_H_INC
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) {
Board::make(m);
move_count += pseudo_perft(depth-1);
Board::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() {
Board::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");
Board::make(m);
Board::print();
DEBUG("unmake");
Board::unmake();
DEBUG("unmake done");
}
} while (m.sq_from != 255);
}
void debug_castle() {
Board::print();
Board::make({0x06, 0x25, P_EMPTY}); Board::print();
Board::make({0x76, 0x55, P_EMPTY}); Board::print();
Board::make({0x16, 0x26, P_EMPTY}); Board::print();
Board::make({0x63, 0x43, P_EMPTY}); Board::print();
Board::make({0x05, 0x16, P_EMPTY}); Board::print();
Board::make({0x62, 0x42, P_EMPTY}); Board::print();
Board::make({0x04, 0x06, P_EMPTY}); Board::print();
Board::unmake(); Board::print();
Board::unmake(); Board::print();
Board::unmake(); Board::print();
Board::unmake(); Board::print();
Board::unmake(); Board::print();
Board::unmake(); Board::print();
Board::unmake(); Board::print();
}
void debug_ep() {
Board::print();
Board::make({0x14, 0x34, P_EMPTY});
Board::print();
Board::make({0x64, 0x54, P_EMPTY});
Board::print();
Board::make({0x34, 0x44, P_EMPTY});
Board::print();
Board::make({0x63, 0x43, P_EMPTY});
Board::print();
Board::make({0x44, 0x53, P_EMPTY});
Board::print();
Board::unmake();
Board::print();
Board::unmake();
Board::print();
Board::unmake();
Board::print();
Board::unmake();
Board::print();
Board::unmake();
Board::print();
}
void bench() {
// TODO reduce code size of this (by moving repeated constants from here to PROGMEM and loops?)
unsigned long startTime = micros();
Board::make({0x14, 0x34, P_EMPTY});
Board::make({0x64, 0x54, P_EMPTY});
Board::make({0x34, 0x44, P_EMPTY});
Board::make({0x63, 0x43, P_EMPTY});
Board::make({0x44, 0x53, P_EMPTY});
Board::unmake();
Board::unmake();
Board::unmake();
Board::unmake();
Board::unmake();
Board::make({0x06, 0x25, P_EMPTY});
Board::make({0x76, 0x55, P_EMPTY});
Board::make({0x16, 0x26, P_EMPTY});
Board::make({0x63, 0x43, P_EMPTY});
Board::make({0x05, 0x16, P_EMPTY});
Board::make({0x62, 0x42, P_EMPTY});
Board::make({0x04, 0x06, P_EMPTY});
Board::unmake();
Board::unmake();
Board::unmake();
Board::unmake();
Board::unmake();
Board::unmake();
Board::unmake();
unsigned long elapsed = micros() - startTime;
Serial.print(elapsed);
Serial.println(F(" microseconds for make/unmake"));
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++) {
Board::make(move[i]);
Board::unmake();
}
elapsed = micros() - startTime;
Serial.print(elapsed);
Serial.println(F(" microseconds for make/unmake(init_pos)"));
}
#endif

27
Uci.h
View File

@ -1,6 +1,8 @@
#ifndef __UCI_H_INC
#define __UCI_H_INC
#include "Tasks.h"
#define PS2(s) ([]{ static const char c[] PROGMEM = (s); return &c[0]; }())
typedef void uci_return;
@ -11,6 +13,15 @@ struct uci_cmd {
uci_handler handler;
};
void clear_line() {
int peek = Serial.peek();
if(peek == -1) return;
do {
peek = Serial.read();
} while(peek != '\n');
}
uci_return uci_hello() {
Serial.println(F("id name ArduChess\nid author Quinten Kock\nuciok"));
}
@ -23,6 +34,15 @@ uci_return uci_unknown() {
Serial.println(F("Not an UCI command"));
}
uci_return uci_perft() {
int depth = Serial.parseInt();
unsigned long result = pseudo_perft(depth);
Serial.print(F("perft("));
Serial.print(depth);
Serial.print(F(") result: "));
Serial.println(result);
}
const char UCI_COMMAND_uci[] PROGMEM = "uci";
const char UCI_COMMAND_debug[] PROGMEM = "debug";
const char UCI_COMMAND_isready[] PROGMEM = "isready";
@ -33,6 +53,9 @@ const char UCI_COMMAND_go[] PROGMEM = "go";
const char UCI_COMMAND_stop[] PROGMEM = "stop";
const char UCI_COMMAND_ponderhit[] PROGMEM = "ponderhit";
const char UCI_COMMAND_quit[] PROGMEM = "quit";
const char UCI_COMMAND_bench[] PROGMEM = "bench";
const char UCI_COMMAND_perft[] PROGMEM = "perft";
const uci_cmd UCI_COMMANDS[] PROGMEM = {
{UCI_COMMAND_uci, &uci_hello},
@ -45,6 +68,8 @@ const uci_cmd UCI_COMMANDS[] PROGMEM = {
{UCI_COMMAND_stop, &uci_unimpl},
{UCI_COMMAND_ponderhit, &uci_unimpl},
{UCI_COMMAND_quit, &uci_unimpl},
{UCI_COMMAND_bench, &bench},
{UCI_COMMAND_perft, &uci_perft},
};
const uci_cmd UCI_INVALID = {PS2(""), &uci_unknown};
@ -87,7 +112,9 @@ uci_return handle_uci() {
String command = read_word();
uci_cmd handler = get_uci_command(command.c_str());
handler.handler();
clear_line();
}
}
#endif