Impl UCI bench and perft
This commit is contained in:
parent
fd1158c0c8
commit
21e956519e
162
ArduChess.ino
162
ArduChess.ino
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
27
Uci.h
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue