Implement eg threat detection

This commit is contained in:
Quinten Kock 2020-07-04 16:58:30 +02:00
parent 5507db23dd
commit 49aa6ec54b
6 changed files with 103 additions and 28 deletions

55
Board.h
View File

@ -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;
}
}

View File

@ -8,4 +8,7 @@
#define _ACF_DEBUG_PRINT
#define _ACF_ACTIVITY_BLINK
#define _ACF_ACTIVITY_BLINK
//#define _ACF_BENCH_BIG

View File

@ -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};

53
Tasks.h
View File

@ -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
#endif

15
Types.h
View File

@ -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

2
Uci.h
View File

@ -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("));