 is possibly my last attempt to write an engine that learns during real time. The Thread struct is set up to meet that goal with every thread having it's own game record for playing quick games. Another goal is for it to be somewhat fast so to play as many games as possible in the allotted time. The chess board is not a very good environment for CPU conditional branch instructions. And every time a branch prediction is wrong it cost performance. Some conditional branches are okay like loops that do not change drastically. Mostly I just wanted to get rid of as many "if" statements as possible. It's not that all eliminations are faster. Some might even be slower. It is just about following a philosophy so to speak. There are no "if" statements in GenAllMoves(), [GenQuiMoves()], AttackedByWhite(), AttackedByBlack(), MakeMove(), TakeBack() and FillMoveFields().
 is possibly my last attempt to write an engine that learns during real time. The Thread struct is set up to meet that goal with every thread having it's own game record for playing quick games. Another goal is for it to be somewhat fast so to play as many games as possible in the allotted time. The chess board is not a very good environment for CPU conditional branch instructions. And every time a branch prediction is wrong it cost performance. Some conditional branches are okay like loops that do not change drastically. Mostly I just wanted to get rid of as many "if" statements as possible. It's not that all eliminations are faster. Some might even be slower. It is just about following a philosophy so to speak. There are no "if" statements in GenAllMoves(), [GenQuiMoves()], AttackedByWhite(), AttackedByBlack(), MakeMove(), TakeBack() and FillMoveFields(). The first mile marker has been reached. The above mentioned functions have been debugged and seem to be working properly, no guarantees. I have entered every series of moves I can think of to test every possibility and had GenAllMoves() do the verification. Enter e2e4 to make a move, e7e8n to promote and e1g1 to castle, etc.
The code has been written as simple to understand as I can. But, if one is new to writing branchless code then it might not be easily understood. Some examples are.
In MakeMove() the following line of code is executed for every move.
Code: Select all
piece[BLACK] ^= (u64)(mtt != ES) << mts;(u64)0 << mts; (m->s.ts) does nothing.
(u64)1 << mts; removes the captured piece from that sides piece list. One might object that performing that operation when not necessary waste time. However, most moves are capture moves from Qsearch(). Something like 90% or more of the moves are captures!
Code: Select all
m.s.ft += ((ts == g1) * (WCS - WKC) + (ts == c1) * (WCL - WKC));! uses pseudo piece types. WKC, WRC, BKC, BRC appear on the board. The other pseudo pieces exist only in switch statements. But some of them could also appear on the board. For example a pawn that moves to the 5th rank can change from a WP to a WPE. It would be a little faster because the second switch(fs >> 3) for the pawns would not be needed. I might optimize that later. In the code above WCS and WCL are pseudo pieces for castling that cannot be on the board. The from type starts off as a WKC (white king that can castle). That is (pseudo) piece 7. WCS and WCL is further along in the piece type list.
Code: Select all
enum {
  ES,
  WP, WN, WB, WRC, WR, WQ, WKC, WK,
  BP, BN, BB, BRC, BR, BQ, BKC, BK,
  WCS, WCL, WPD, WPE, WPQ, WPN, WPR, WPB,
  BCS, BCL, BPD, BPE, BPQ, BPN, BPR, BPB
};Here is the complete MSVS 2022 standard 2020 code so far.
Code: Select all
// !
// !.cpp
#include <cstring>
#include <bit>
#include <cctype>
#include <iostream>
#include "Defines.cpp"
#include "Equates.cpp"
#include "Globals.cpp"
#include "Utilities.cpp"
#include "Move.cpp"
#include "GenMoves.cpp"
#include "Search.cpp"
#include "GetCommand.cpp"
#include "Initialize.cpp"
#include "Main.cpp"Code: Select all
// !
// Main.cpp
s32 main() {
  Initialize();
  while (mode) {
	if (mode == GETCMD) GetCommand(thread[0]);
	if (mode == SEARCH) StartSearch(thread[0]);
  }
  return 0;
}Code: Select all
// !
// Initialize.cpp
void InitThreads() {
  numThreads = 4;
  thread = new Thread * [numThreads];
  for (s32 i = 0; i < numThreads; i++) {
	thread[i] = new Thread;
  }
}
u64 mask_shift(u64 bb, s32 ranks) {
  if (ranks > 0) return bb >> (ranks << 3);
  else return bb << -(ranks << 3);
}
void InitRays() {
  // Classic style sliding piece bitboards.
  // Bob-Mike-Dan
  // Bob = Robert Hyatt - originator of basic approach
  // Mike = Michael Sherwin - Originally stop bits but later worked to modernize
  // Dan = Daniel Infuehr - Final optimizations and code example 
  for (s32 sq = a1; sq <= h8; sq++) {
	ray[sq].NW = dir_D2(sq) & GetUpper(sq);
	ray[sq].NN = dir_VE(sq) & GetUpper(sq);
	ray[sq].NE = dir_D1(sq) & GetUpper(sq);
	ray[sq].EE = dir_HO(sq) & GetUpper(sq);
	ray[sq].SE = dir_D1(sq) & GetLower(sq);
	ray[sq].SS = dir_VE(sq) & GetLower(sq);
	ray[sq].SW = dir_D2(sq) & GetLower(sq);
	ray[sq].WW = dir_HO(sq) & GetLower(sq);
  }
  ray[64] = ray[63];
  for (s32 sq = a1; sq <= h8; sq++) rev[sq] = ray[63 - sq];
  rev[64] = ray[0];
}
void InitBoardBB() {
  s32 file, rank;
  for (s32 sq = a1; sq <= h8; sq++) {
	file = sq & 7;
	rank = sq >> 3;
	wPawnCapts[sq] = 0;
	bPawnCapts[sq] = 0;
	knightMoves[sq] = 0;
	bishopMoves[sq] = 0;
	rookMoves[sq] = 0;
	queenMoves[sq] = 0;
	kingMoves[sq] = 0;
	// pawns
	if (sq >= a2 && sq <= h7) {
	  if (file != FILEa) {
		wPawnCapts[sq] |= 1ull << (sq + 7);
		bPawnCapts[sq] |= 1ull << (sq - 9);
	  }
	  if (file != FILEh) {
		wPawnCapts[sq] |= 1ull << (sq + 9);
		bPawnCapts[sq] |= 1ull << (sq - 7);
	  }
	}
	// knights
	if (rank <= RANK6 && file <= FILEg) knightMoves[sq] |= 1ull << (sq + 17);
	if (rank <= RANK7 && file <= FILEf) knightMoves[sq] |= 1ull << (sq + 10);
	if (rank >= RANK2 && file <= FILEf) knightMoves[sq] |= 1ull << (sq - +6);
	if (rank >= RANK3 && file <= FILEg) knightMoves[sq] |= 1ull << (sq - 15);
	if (rank >= RANK3 && file >= FILEb) knightMoves[sq] |= 1ull << (sq - 17);
	if (rank >= RANK2 && file >= FILEc) knightMoves[sq] |= 1ull << (sq - 10);
	if (rank <= RANK7 && file >= FILEc) knightMoves[sq] |= 1ull << (sq + +6);
	if (rank <= RANK6 && file >= FILEb) knightMoves[sq] |= 1ull << (sq + 15);
	// bishops
	bishopMoves[sq] = ray[sq].NW | ray[sq].NE | ray[sq].SE | ray[sq].SW;
	//rooks
	rookMoves[sq] = ray[sq].NN | ray[sq].EE | ray[sq].SS | ray[sq].WW;
	// queen
	queenMoves[sq] = bishopMoves[sq] | rookMoves[sq];
	// king
	if (rank <= RANK7) kingMoves[sq] |= 1ull << (sq + 8);
	if (rank >= RANK2) kingMoves[sq] |= 1ull << (sq - 8);
	if (file <= FILEg) kingMoves[sq] |= 1ull << (sq + 1);
	if (file >= FILEb) kingMoves[sq] |= 1ull << (sq - 1);
	if (rank <= RANK7 && file <= FILEg) kingMoves[sq] |= 1ull << (sq + 9);
	if (rank >= RANK2 && file <= FILEg) kingMoves[sq] |= 1ull << (sq - 7);
	if (rank >= RANK2 && file >= FILEb) kingMoves[sq] |= 1ull << (sq - 9);
	if (rank <= RANK7 && file >= FILEb) kingMoves[sq] |= 1ull << (sq + 7);
  }
}
void InitGame(Thread* t) {
  s32 ok;
  mode = GETCMD;
  computer = BLACK;
  ply = 0;
  gly = 0;
  ok = LoadFen(t, startFen);
  if (!ok) {
	std::cout << "Apparently a bad fen" << std::endl;
  }
}
void InitStruct(Thread* t) {
  piece[BLACK] = 0;
  piece[WHITE] = 0;
  king[BLACK] = 0;
  king[WHITE] = 0;
  for (s32 i = 0; i <= BK; i++) pctypbb[i] = 0;
  for (s32 sq = a1; sq <= h8; sq++) {
	s32 pce = board[sq];
	switch (pce) {
	case ES:
	  // no action
	  break;
	case WP:
	  piece[WHITE] |= 1ull << sq;
	  pctypbb[WP] |= 1ull << sq;
	  break;
	case WN:
	  piece[WHITE] |= 1ull << sq;
	  pctypbb[WN] |= 1ull << sq;
	  break;
	case WB:
	  piece[WHITE] |= 1ull << sq;
	  pctypbb[WB] |= 1ull << sq;
	  break;
	case WRC:
	case WR:
	  piece[WHITE] |= 1ull << sq;
	  pctypbb[WR] |= 1ull << sq;
	  break;
	case WQ:
	  piece[WHITE] |= 1ull << sq;
	  pctypbb[WQ] |= 1ull << sq;
	  break;
	case WKC:
	case WK:
	  piece[WHITE] |= 1ull << sq;
	  king[WHITE] |= 1ull << sq;
	  break;
	case BP:
	  piece[BLACK] |= 1ull << sq;
	  pctypbb[BP] |= 1ull << sq;
	  break;
	case BN:
	  piece[BLACK] |= 1ull << sq;
	  pctypbb[BN] |= 1ull << sq;
	  break;
	case BB:
	  piece[BLACK] |= 1ull << sq;
	  pctypbb[BB] |= 1ull << sq;
	  break;
	case BRC:
	case BR:
	  piece[BLACK] |= 1ull << sq;
	  pctypbb[BR] |= 1ull << sq;
	  break;
	case BQ:
	  piece[BLACK] |= 1ull << sq;
	  pctypbb[BQ] |= 1ull << sq;
	  break;
	case BKC:
	case BK:
	  piece[BLACK] |= 1ull << sq;
	  king[BLACK] |= 1ull << sq;
	  break;
	}
  }
  for (s32 i = 0; i < 100; i++) epbit[i] = 0;
}
void Initialize() {
  InitThreads();
  InitRays();
  InitBoardBB();
  InitGame(thread[0]);
  InitStruct(thread[0]);
}Code: Select all
// !
// GetCommand.cpp
void GetCommand(Thread* t) {
  s08 line[256], cmd[256], a_move, fs, ts, fs2;
  uMove m;
  u64 pieces;
  s32 ok, not_ok;
  if (!fgets(line, 256, stdin)) return;
  ok = sscanf(line, "%s", cmd);
  cmd[255] = '\0';
  a_move = true;
  if (line[0] < 'a' || line[0] > 'h') a_move = false;
  if (line[1] < '1' || line[1] > '8') a_move = false;
  if (line[2] < 'a' || line[2] > 'h') a_move = false;
  if (line[3] < '1' || line[3] > '8') a_move = false;
  if (a_move) {
	ok = GenAllMoves(t);
	if (!ok) {
	  printf("Illegal Move/n");
	  return;
	}
	fs = (line[1] - '1') * 8 + (line[0] - 'a');
	ts = (line[3] - '1') * 8 + (line[2] - 'a');
	a_move = false;
	pieces = piece[stm];
	while (pieces) {
	  fs2 = std::countr_zero(pieces);
	  pieces ^= 1ull << fs2;
	  if (fs == fs2) {
		if (gbb[ply][fs] & (1ull << ts)) {
		  a_move = true;
		  break;
		}
	  }
	}
	if (a_move) {
	  m = FillMoveFields(t, fs, ts);
	  if (m.s.ft == WPQ) {
		if (line[4] == 'n') m.s.ft = WPN; else;
		if (line[4] == 'b') m.s.ft = WPB; else;
		if (line[4] == 'r') m.s.ft = WPR;
	  }
	  else;
	  if (m.s.ft == BPQ) {
		if (line[4] == 'n') m.s.ft = BPN; else;
		if (line[4] == 'b') m.s.ft = BPB; else;
		if (line[4] == 'r') m.s.ft = BPR;
	  }
	  MakeMove(t, &m);
	  g[gly] = m;
	  gly++;
	  not_ok = InCheckBy[stm](t, king[1 - stm]); 
	  if (not_ok) {
		gly--;
		m = g[gly];
		TakeBack(t, &m);
		return;
	  }
	}
	PrintBoard(t);
	return;
  }
  if (!strcmp(cmd, "undo") && gly > 0) {
	gly--;
	m = g[gly];
	TakeBack(t, &m);
	PrintBoard(t);
	return;
  }
}
 Code: Select all
// !
// Search.cpp
void StartSearch(Thread* t) {
}Code: Select all
// !
// GenMoves.cpp
bool GenAllMoves(Thread* t) {
  s08 fs, ft;
  u64 atk;
  
  u64 pieces = piece[stm];
  u64 notme = ~pieces;
  u64 occ = pieces | piece[1 - stm];
  u64 empty = ~occ;
  u64 enemy = notme ^ empty;
  abb[ply] = 0;
  do {
    fs = std::countr_zero(pieces);
    ft = board[fs];
    switch (ft) {
    case ES:
      // can't get here
      break;
    case WP:
      switch (fs >> 3) {
      case RANK1:
        // can't get here
        break;
      case RANK2:
        gbb[ply][fs] = ((0x0000000000000100ull << fs) & empty);
        gbb[ply][fs] |= ((gbb[ply][fs] << 8) & empty);
        atk = wPawnCapts[fs];
        gbb[ply][fs] |= atk & enemy;
        abb[ply] |= atk;
        break;
      case RANK3:
      case RANK4:
        gbb[ply][fs] = ((0x0000000000000100ull << fs) & empty);
        atk = wPawnCapts[fs];
        gbb[ply][fs] |= atk & enemy;
        abb[ply] |= atk;
        break;
      case RANK5:
        gbb[ply][fs] = ((0x0000000000000100ull << fs) & empty);
        atk = wPawnCapts[fs];
        gbb[ply][fs] |= (atk & (enemy | epbit[ply]));
        abb[ply] |= atk;
        break;
      case RANK6:
      case RANK7:
        gbb[ply][fs] = ((0x0000000000000100ull << fs) & empty);
        atk = wPawnCapts[fs];
        gbb[ply][fs] |= atk & enemy;
        abb[ply] |= atk;
        break;
      }
      break;
    case WN:
      gbb[ply][fs] = knightMoves[fs] & notme;
      abb[ply] |= knightMoves[fs];
      break;
    case WB:
      gbb[ply][fs]
        = (ray[std::countr_zero(ray[fs].NW & occ)].NW
         | ray[std::countr_zero(ray[fs].NE & occ)].NE
         | rev[std::countl_zero(ray[fs].SE & occ)].SE
         | rev[std::countl_zero(ray[fs].SW & occ)].SW)
         ^ bishopMoves[fs];
      abb[ply] |= gbb[ply][fs];
      gbb[ply][fs] &= notme;
      break;
    case WRC:
    case WR:
      gbb[ply][fs]
        = (ray[std::countr_zero(ray[fs].NN & occ)].NN
         | ray[std::countr_zero(ray[fs].EE & occ)].EE
         | rev[std::countl_zero(ray[fs].SS & occ)].SS
         | rev[std::countl_zero(ray[fs].WW & occ)].WW)
         ^ rookMoves[fs];
      abb[ply] |= gbb[ply][fs];
      gbb[ply][fs] &= notme;
      break;
    case WQ:
      gbb[ply][fs]
        = (ray[std::countr_zero(ray[fs].NW & occ)].NW
         | ray[std::countr_zero(ray[fs].NE & occ)].NE
         | rev[std::countl_zero(ray[fs].SE & occ)].SE
         | rev[std::countl_zero(ray[fs].SW & occ)].SW
         | ray[std::countr_zero(ray[fs].NN & occ)].NN
         | ray[std::countr_zero(ray[fs].EE & occ)].EE
         | rev[std::countl_zero(ray[fs].SS & occ)].SS
         | rev[std::countl_zero(ray[fs].WW & occ)].WW) 
         ^ queenMoves[fs];
      abb[ply] |= gbb[ply][fs];
      gbb[ply][fs] &= notme;
      break;
    case WKC:
      gbb[ply][fs] = kingMoves[fs] & notme;
      abb[ply] |= kingMoves[fs];
      gbb[ply][fs] |= (u64)((board[h1] == WRC) + ((occ & SWCS) == 0) + (AttackedByBlack(t, AWCS) == 0) == 3) << g1;
      gbb[ply][fs] |= (u64)((board[a1] == WRC) + ((occ & SWCL) == 0) + (AttackedByBlack(t, AWCL) == 0) == 3) << c1;
      break;
    case WK:
      gbb[ply][fs] = kingMoves[fs] & notme;
      abb[ply] |= kingMoves[fs];
      break;
    case BP:
      switch (fs >> 3) {
      case RANK1:
        // can't get here
        break;
      case RANK2:
      case RANK3:
        gbb[ply][fs] = (1ull << (fs - 8)) & empty;
        atk = bPawnCapts[fs];
        gbb[ply][fs] |= atk & enemy;
        abb[ply] |= atk;
        break;
      case RANK4:
        gbb[ply][fs] = (1ull << (fs - 8)) & empty;
        atk = bPawnCapts[fs];
        gbb[ply][fs] |= (atk & (enemy | epbit[ply]));
        abb[ply] |= atk;
        break;
      case RANK5:
      case RANK6:
        gbb[ply][fs] = (1ull << (fs - 8)) & empty;
        atk = bPawnCapts[fs];
        gbb[ply][fs] |= atk & enemy;
        abb[ply] |= atk;
        break;
      case RANK7:
        gbb[ply][fs] = (1ull << (fs - 8)) & empty;
        gbb[ply][fs] |= ((gbb[ply][fs] >> 8) & empty);
        atk = bPawnCapts[fs];
        gbb[ply][fs] |= atk & enemy;
        abb[ply] |= atk;
        break;
      }
      break;
    case BN:
      gbb[ply][fs] = knightMoves[fs] & notme;
      abb[ply] |= knightMoves[fs];
      break;
    case BB:
      gbb[ply][fs]
        = (ray[std::countr_zero(ray[fs].NW & occ)].NW
          | ray[std::countr_zero(ray[fs].NE & occ)].NE
          | rev[std::countl_zero(ray[fs].SE & occ)].SE
          | rev[std::countl_zero(ray[fs].SW & occ)].SW)
        ^ bishopMoves[fs];
      abb[ply] |= gbb[ply][fs];
      gbb[ply][fs] &= notme;
      break;
    case BRC:
    case BR:
      gbb[ply][fs]
        = (ray[std::countr_zero(ray[fs].NN & occ)].NN
         | ray[std::countr_zero(ray[fs].EE & occ)].EE
         | rev[std::countl_zero(ray[fs].SS & occ)].SS
         | rev[std::countl_zero(ray[fs].WW & occ)].WW)
         ^ rookMoves[fs];
      abb[ply] |= gbb[ply][fs];
      gbb[ply][fs] &= notme;
      break;
    case BQ:
      gbb[ply][fs]
        = (ray[std::countr_zero(ray[fs].NW & occ)].NW
         | ray[std::countr_zero(ray[fs].NE & occ)].NE
         | rev[std::countl_zero(ray[fs].SE & occ)].SE
         | rev[std::countl_zero(ray[fs].SW & occ)].SW
         | ray[std::countr_zero(ray[fs].NN & occ)].NN
         | ray[std::countr_zero(ray[fs].EE & occ)].EE
         | rev[std::countl_zero(ray[fs].SS & occ)].SS
         | rev[std::countl_zero(ray[fs].WW & occ)].WW)
         ^ queenMoves[fs];
      abb[ply] |= gbb[ply][fs];
      gbb[ply][fs] &= notme;
      break;
    case BKC:
      gbb[ply][fs] = kingMoves[fs] & notme;
      abb[ply] |= kingMoves[fs];
      gbb[ply][fs] |= (u64)((board[h8] == BRC) + ((occ & SBCS) == 0) + (AttackedByWhite(t, ABCS) == 0) == 3) << g8;
      gbb[ply][fs] |= (u64)((board[a8] == BRC) + ((occ & SBCL) == 0) + (AttackedByWhite(t, ABCL) == 0) == 3) << c8;
      break;
    case BK:
      gbb[ply][fs] = kingMoves[fs] & notme;
      abb[ply] |= kingMoves[fs];
      break;
    }
    pieces ^= 1ull << fs;
  } while (pieces);
  return 1 - (king[1 - stm] & abb[ply]);
}Code: Select all
// !
// Move.cpp
void MakeMove(Thread* t, uMove* m) {
  switch (m->s.ft) {
  case ES:
	// can't get here
	break;
  case WP:
	board[mfs] = ES;
	board[mts] = WP;
	piece[WHITE] ^= 1ull << mfs;
	piece[WHITE] ^= 1ull << mts;
	wpos -= pst[WP][mfs];
	wpos += pst[WP][mts];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat -= val[mtt];
	bpos -= pst[mtt][mts];
	pctypbb[WP] ^= 1ull << mfs;
	pctypbb[WP] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WN:
	board[mfs] = ES;
	board[mts] = WN;
	piece[WHITE] ^= 1ull << mfs;
	piece[WHITE] ^= 1ull << mts;
	wpos -= pst[WN][mfs];
	wpos += pst[WN][mts];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat -= val[mtt];
	bpos -= pst[mtt][mts];
	pctypbb[WN] ^= 1ull << mfs;
	pctypbb[WN] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WB:
	board[mfs] = ES;
	board[mts] = WB;
	piece[WHITE] ^= 1ull << mfs;
	piece[WHITE] ^= 1ull << mts;
	wpos -= pst[WB][mfs];
	wpos += pst[WB][mts];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat -= val[mtt];
	bpos -= pst[mtt][mts];
	pctypbb[WB] ^= 1ull << mfs;
	pctypbb[WB] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WRC:
  case WR:
	board[mfs] = ES;
	board[mts] = WR;
	piece[WHITE] ^= 1ull << mfs;
	piece[WHITE] ^= 1ull << mts;
	wpos -= pst[WR][mfs];
	wpos += pst[WR][mts];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat -= val[mtt];
	bpos -= pst[mtt][mts];
	pctypbb[WR] ^= 1ull << mfs;
	pctypbb[WR] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WQ:
	board[mfs] = ES;
	board[mts] = WQ;
	piece[WHITE] ^= 1ull << mfs;
	piece[WHITE] ^= 1ull << mts;
	wpos -= pst[WQ][mfs];
	wpos += pst[WQ][mts];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat -= val[mtt];
	bpos -= pst[mtt][mts];
	pctypbb[WQ] ^= 1ull << mfs;
	pctypbb[WQ] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WKC:
  case WK:
	board[mfs] = ES;
	board[mts] = WK;
	piece[WHITE] ^= 1ull << mfs;
	piece[WHITE] ^= 1ull << mts;
	king[WHITE] ^= 1ull << mfs;
	king[WHITE] ^= 1ull << mts;
	wpos -= pst[WK][mfs];
	wpos += pst[WK][mts];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat -= val[mtt];
	bpos -= pst[mtt][mts];
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BP:
	board[mfs] = ES;
	board[mts] = BP;
	piece[BLACK] ^= 1ull << mfs;
	piece[BLACK] ^= 1ull << mts;
	bpos -= pst[BP][mfs];
	bpos += pst[BP][mts];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat -= val[mtt];
	wpos -= pst[mtt][mts];
	pctypbb[BP] ^= 1ull << mfs;
	pctypbb[BP] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BN:
	board[mfs] = ES;
	board[mts] = BN;
	piece[BLACK] ^= 1ull << mfs;
	piece[BLACK] ^= 1ull << mts;
	bpos -= pst[BN][mfs];
	bpos += pst[BN][mts];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat -= val[mtt];
	wpos -= pst[mtt][mts];
	pctypbb[BN] ^= 1ull << mfs;
	pctypbb[BN] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BB:
	board[mfs] = ES;
	board[mts] = BB;
	piece[BLACK] ^= 1ull << mfs;
	piece[BLACK] ^= 1ull << mts;
	bpos -= pst[BB][mfs];
	bpos += pst[BB][mts];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat -= val[mtt];
	wpos -= pst[mtt][mts];
	pctypbb[BB] ^= 1ull << mfs;
	pctypbb[BB] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BRC:
  case BR:
	board[mfs] = ES;
	board[mts] = BR;
	piece[BLACK] ^= 1ull << mfs;
	piece[BLACK] ^= 1ull << mts;
	bpos -= pst[BR][mfs];
	bpos += pst[BR][mts];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat -= val[mtt];
	wpos -= pst[mtt][mts];
	pctypbb[BR] ^= 1ull << mfs;
	pctypbb[BR] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BQ:
	board[mfs] = ES;
	board[mts] = BQ;
	piece[BLACK] ^= 1ull << mfs;
	piece[BLACK] ^= 1ull << mts;
	bpos -= pst[BQ][mfs];
	bpos += pst[BQ][mts];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat -= val[mtt];
	wpos -= pst[mtt][mts];
	pctypbb[BQ] ^= 1ull << mfs;
	pctypbb[BQ] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BKC:
  case BK:
	board[mfs] = ES;
	board[mts] = BK;
	piece[BLACK] ^= 1ull << mfs;
	piece[BLACK] ^= 1ull << mts;
	king[BLACK] ^= 1ull << mfs;
	king[BLACK] ^= 1ull << mts;
	bpos -= pst[BK][mfs];
	bpos += pst[BK][mts];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat -= val[mtt];
	wpos -= pst[mtt][mts];
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WCS:
	board[e1] = ES;
	board[g1] = WK;
	piece[WHITE] ^= 1ull << e1;
	piece[WHITE] ^= 1ull << g1;
	king[WHITE] ^= 1ull << e1;
	king[WHITE] ^= 1ull << g1;
	wpos -= pst[WK][e1];
	wpos += pst[WK][g1];
	board[h1] = ES;
	board[f1] = WR;
	piece[WHITE] ^= 1ull << h1;
	piece[WHITE] ^= 1ull << f1;
	wpos += 10;
	pctypbb[WR] ^= 1ull << h1;
	pctypbb[WR] ^= 1ull << f1;
	break;
  case WCL:
	board[e1] = ES;
	board[c1] = WK;
	piece[WHITE] ^= 1ull << e1;
	piece[WHITE] ^= 1ull << c1;
	king[WHITE] ^= 1ull << e1;
	king[WHITE] ^= 1ull << c1;
	wpos -= pst[WK][e1];
	wpos += pst[WK][c1];
	board[a1] = ES;
	board[d1] = WR;
	piece[WHITE] ^= 1ull << a1;
	piece[WHITE] ^= 1ull << d1;
	wpos += 8;
	pctypbb[WR] ^= 1ull << a1;
	pctypbb[WR] ^= 1ull << d1;
	break;
  case WPD:
	board[mfs] = ES;
	board[mts] = WP;
	piece[WHITE] ^= 1ull << mfs;
	piece[WHITE] ^= 1ull << mts;
	wpos -= pst[WP][mfs];
	wpos += pst[WP][mts];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat -= val[mtt];
	bpos -= pst[mtt][mts];
	pctypbb[WP] ^= 1ull << mfs;
	pctypbb[WP] ^= 1ull << mts;
	epbit[ply + 1] = 1ull << (mts - 8);
	break;
  case WPE:
	board[mfs] = ES;
	board[mts] = WP;
	piece[WHITE] ^= 1ull << mfs;
	piece[WHITE] ^= 1ull << mts;
	wpos -= pst[WP][mfs];
	wpos += pst[WP][mts];
	board[mts - 8] = ES;
	piece[BLACK] ^= 1ull << (mts - 8);
	bmat -= val[BP];
	bpos -= pst[BP][mts - 8];
	pctypbb[WP] ^= 1ull << mfs;
	pctypbb[WP] ^= 1ull << mts;
	pctypbb[BP] ^= 1ull << (mts - 8);
	break;
  case WPQ:
	board[mfs] = ES;
	board[mts] = WQ;
	piece[WHITE] ^= 1ull << mfs;
	piece[WHITE] ^= 1ull << mts;
	wpos -= pst[WP][mfs];
	wpos += pst[WQ][mts];
	wmat += 80;
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat -= val[mtt];
	bpos -= pst[mtt][mts];
	pctypbb[WP] ^= 1ull << mfs;
	pctypbb[WQ] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WPN:
	board[mfs] = ES;
	board[mts] = WN;
	piece[WHITE] ^= 1ull << mfs;
	piece[WHITE] ^= 1ull << mts;
	wpos -= pst[WP][mfs];
	wpos += pst[WN][mts];
	wmat += 19;
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat -= val[mtt];
	bpos -= pst[mtt][mts];
	pctypbb[WP] ^= 1ull << mfs;
	pctypbb[WN] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WPR:
	board[mfs] = ES;
	board[mts] = WR;
	piece[WHITE] ^= 1ull << mfs;
	piece[WHITE] ^= 1ull << mts;
	wpos -= pst[WP][mfs];
	wpos += pst[WR][mts];
	wmat += 40;
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat -= val[mtt];
	bpos -= pst[mtt][mts];
	pctypbb[WP] ^= 1ull << mfs;
	pctypbb[WR] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WPB:
	board[mfs] = ES;
	board[mts] = WB;
	piece[WHITE] ^= 1ull << mfs;
	piece[WHITE] ^= 1ull << mts;
	wpos -= pst[WP][mfs];
	wpos += pst[WB][mts];
	wmat += 22;
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat -= val[mtt];
	bpos -= pst[mtt][mts];
	pctypbb[WP] ^= 1ull << mfs;
	pctypbb[WB] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BCS:
	board[e8] = ES;
	board[g8] = BK;
	piece[BLACK] ^= 1ull << e8;
	piece[BLACK] ^= 1ull << g8;
	king[BLACK] ^= 1ull << e8;
	king[BLACK] ^= 1ull << g8;
	bpos -= pst[BK][e8];
	bpos += pst[BK][g8];
	board[h8] = ES;
	board[f8] = BR;
	piece[BLACK] ^= 1ull << h8;
	piece[BLACK] ^= 1ull << f8;
	bpos += 10;
	pctypbb[BR] ^= 1ull << h8;
	pctypbb[BR] ^= 1ull << f8;
	break;
  case BCL:
	board[e8] = ES;
	board[c8] = BK;
	piece[BLACK] ^= 1ull << e8;
	piece[BLACK] ^= 1ull << c8;
	king[BLACK] ^= 1ull << e8;
	king[BLACK] ^= 1ull << c8;
	bpos -= pst[BK][e8];
	bpos += pst[BK][c8];
	board[a8] = ES;
	board[d8] = BR;
	piece[BLACK] ^= 1ull << a8;
	piece[BLACK] ^= 1ull << d8;
	bpos += 8;
	pctypbb[BR] ^= 1ull << a8;
	pctypbb[BR] ^= 1ull << d8;
	break;
  case BPD:
	board[mfs] = ES;
	board[mts] = BP;
	piece[BLACK] ^= 1ull << mfs;
	piece[BLACK] ^= 1ull << mts;
	bpos -= pst[BP][mfs];
	bpos += pst[BP][mts];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat -= val[mtt];
	wpos -= pst[mtt][mts];
	pctypbb[BP] ^= 1ull << mfs;
	pctypbb[BP] ^= 1ull << mts;
	epbit[ply + 1] = 1ull << (mts + 8);
	break;
  case BPE:
	board[mfs] = ES;
	board[mts] = BP;
	piece[BLACK] ^= 1ull << mfs;
	piece[BLACK] ^= 1ull << mts;
	wpos -= pst[WP][mfs];
	wpos += pst[WP][mts];
	board[mts + 8] = ES;
	piece[WHITE] ^= 1ull << (mts + 8);
	wmat -= val[WP];
	wpos -= pst[WP][mts + 8];
	pctypbb[BP] ^= 1ull << mfs;
	pctypbb[BP] ^= 1ull << mts;
	pctypbb[WP] ^= 1ull << (mts + 8);
	break;
  case BPQ:
	board[mfs] = ES;
	board[mts] = BQ;
	piece[BLACK] ^= 1ull << mfs;
	piece[BLACK] ^= 1ull << mts;
	bpos -= pst[BP][mfs];
	bpos += pst[BQ][mts];
	bmat += 80;
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat -= val[mtt];
	wpos -= pst[mtt][mts];
	pctypbb[BP] ^= 1ull << mfs;
	pctypbb[BQ] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BPN:
	board[mfs] = ES;
	board[mts] = BN;
	piece[BLACK] ^= 1ull << mfs;
	piece[BLACK] ^= 1ull << mts;
	bpos -= pst[BP][mfs];
	bpos += pst[BN][mts];
	bmat += 19;
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat -= val[mtt];
	wpos -= pst[mtt][mts];
	pctypbb[BP] ^= 1ull << mfs;
	pctypbb[BN] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BPR:
	board[mfs] = ES;
	board[mts] = BR;
	piece[BLACK] ^= 1ull << mfs;
	piece[BLACK] ^= 1ull << mts;
	bpos -= pst[BP][mfs];
	bpos += pst[BN][mts];
	bmat += 40;
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat -= val[mtt];
	wpos -= pst[mtt][mts];
	pctypbb[BP] ^= 1ull << mfs;
	pctypbb[BR] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BPB:
	board[mfs] = ES;
	board[mts] = BB;
	piece[BLACK] ^= 1ull << mfs;
	piece[BLACK] ^= 1ull << mts;
	bpos -= pst[BP][mfs];
	bpos += pst[BB][mts];
	bmat += 22;
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat -= val[mtt];
	wpos -= pst[mtt][mts];
	pctypbb[BP] ^= 1ull << mfs;
	pctypbb[BB] ^= 1ull << mts;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  }
  ply++;
  stm = 1 - stm;
}
void TakeBack(Thread* t, uMove* m) {
  s08 ft;
  ply--;
  stm = 1 - stm;
  ft = m->s.ft;
  switch (ft) {
  case ES:
	// can't get here
	break;
  case WP:
	board[mfs] = WP;
	board[mts] = mtt;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	wpos -= pst[WP][mts];
	wpos += pst[WP][mfs];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat += val[mtt];
	bpos += pst[mtt][mts];
	pctypbb[WP] ^= 1ull << mts;
	pctypbb[WP] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WN:
	board[mfs] = WN;
	board[mts] = mtt;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	wpos -= pst[WN][mts];
	wpos += pst[WN][mfs];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat += val[mtt];
	bpos += pst[mtt][mts];
	pctypbb[WN] ^= 1ull << mts;
	pctypbb[WN] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WB:
	board[mfs] = WB;
	board[mts] = mtt;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	wpos -= pst[WB][mts];
	wpos += pst[WB][mfs];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat += val[mtt];
	bpos += pst[mtt][mts];
	pctypbb[WB] ^= 1ull << mts;
	pctypbb[WB] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WRC:
	board[mfs] = WRC;
	board[mts] = mtt;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	wpos -= pst[WR][mts];
	wpos += pst[WR][mfs];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat += val[mtt];
	bpos += pst[mtt][mts];
	pctypbb[WR] ^= 1ull << mts;
	pctypbb[WR] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WR:
	board[mfs] = WR;
	board[mts] = mtt;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	wpos -= pst[WR][mts];
	wpos += pst[WR][mfs];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat += val[mtt];
	bpos += pst[mtt][mts];
	pctypbb[WR] ^= 1ull << mts;
	pctypbb[WR] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WQ:
	board[mfs] = WQ;
	board[mts] = mtt;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	wpos -= pst[WQ][mts];
	wpos += pst[WQ][mfs];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat += val[mtt];
	bpos += pst[mtt][mts];
	pctypbb[WQ] ^= 1ull << mts;
	pctypbb[WQ] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WKC:
	board[mfs] = WKC;
	board[mts] = mtt;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	king[WHITE] ^= 1ull << mts;
	king[WHITE] ^= 1ull << mfs;
	wpos -= pst[WK][mts];
	wpos += pst[WK][mfs];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat += val[mtt];
	bpos += pst[mtt][mts];
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WK:
	board[mfs] = WK;
	board[mts] = mtt;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	king[WHITE] ^= 1ull << mts;
	king[WHITE] ^= 1ull << mfs;
	wpos -= pst[WK][mts];
	wpos += pst[WK][mfs];
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat += val[mtt];
	bpos += pst[mtt][mts];
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BP:
	board[mfs] = BP;
	board[mts] = mtt;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	bpos -= pst[BP][mts];
	bpos += pst[BP][mfs];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat += val[mtt];
	wpos += pst[mtt][mts];
	pctypbb[BP] ^= 1ull << mts;
	pctypbb[BP] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BN:
	board[mfs] = BN;
	board[mts] = mtt;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	bpos -= pst[BN][mts];
	bpos += pst[BN][mfs];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat += val[mtt];
	wpos += pst[mtt][mts];
	pctypbb[BN] ^= 1ull << mts;
	pctypbb[BN] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BB:
	board[mfs] = BB;
	board[mts] = mtt;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	bpos -= pst[BB][mts];
	bpos += pst[BB][mfs];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat += val[mtt];
	wpos += pst[mtt][mts];
	pctypbb[BB] ^= 1ull << mts;
	pctypbb[BB] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BRC:
	board[mfs] = BRC;
	board[mts] = mtt;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	bpos -= pst[BR][mts];
	bpos += pst[BR][mfs];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat += val[mtt];
	wpos += pst[mtt][mts];
	pctypbb[BR] ^= 1ull << mts;
	pctypbb[BR] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BR:
	board[mfs] = BR;
	board[mts] = mtt;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	bpos -= pst[BR][mts];
	bpos += pst[BR][mfs];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat += val[mtt];
	wpos += pst[mtt][mts];
	pctypbb[BR] ^= 1ull << mts;
	pctypbb[BR] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BQ:
	board[mfs] = BQ;
	board[mts] = mtt;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	bpos -= pst[BR][mts];
	bpos += pst[BR][mfs];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat += val[mtt];
	wpos += pst[mtt][mts];
	pctypbb[BQ] ^= 1ull << mts;
	pctypbb[BQ] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BKC:
	board[mfs] = BKC;
	board[mts] = mtt;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	king[BLACK] ^= 1ull << mts;
	king[BLACK] ^= 1ull << mfs;
	bpos -= pst[BK][mts];
	bpos += pst[BK][mfs];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat += val[mtt];
	wpos += pst[mtt][mts];
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BK:
	board[mfs] = BK;
	board[mts] = mtt;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	king[BLACK] ^= 1ull << mts;
	king[BLACK] ^= 1ull << mfs;
	bpos -= pst[BK][mts];
	bpos -= pst[BK][mts];
	bpos += pst[BK][mfs];
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat += val[mtt];
	wpos += pst[mtt][mts];
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WCS:
	board[e1] = WKC;
	board[g1] = ES;
	piece[WHITE] ^= 1ull << g1;
	piece[WHITE] ^= 1ull << e1;
	king[WHITE] ^= 1ull << g1;
	king[WHITE] ^= 1ull << e1;
	bpos -= pst[BK][mts];
	wpos -= pst[WK][g1];
	wpos += pst[WK][e1];
	board[h1] = WRC;
	board[f1] = ES;
	piece[WHITE] ^= 1ull << f1;
	piece[WHITE] ^= 1ull << h1;
	wpos -= pst[WR][f1];
	wpos += pst[WR][h1];
	pctypbb[WR] ^= 1ull << f1;
	pctypbb[WR] ^= 1ull << h1;
	break;
  case WCL:
	board[e1] = WKC;
	board[c1] = ES;
	piece[WHITE] ^= 1ull << c1;
	piece[WHITE] ^= 1ull << e1;
	king[WHITE] ^= 1ull << c1;
	king[WHITE] ^= 1ull << e1;
	wpos -= pst[WK][c1];
	wpos += pst[WK][e1];
	board[a1] = WRC;
	board[d1] = ES;
	piece[WHITE] ^= 1ull << d1;
	piece[WHITE] ^= 1ull << a1;
	wpos -= pst[WR][d1];
	wpos += pst[WR][a1];
	pctypbb[WR] ^= 1ull << d1;
	pctypbb[WR] ^= 1ull << a1;
	break;
  case WPD:
	board[mfs] = WP;
	board[mts] = ES;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	wpos -= pst[WP][mts];
	wpos += pst[WP][mfs];
	epbit[ply + 1] = 0;
	pctypbb[WP] ^= 1ull << mts;
	pctypbb[WP] ^= 1ull << mfs;
	break;
  case WPE:
	board[mfs] = WP;
	board[mts] = ES;
	board[mts - 8] = BP;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	wpos -= pst[WP][mts];
	wpos += pst[WP][mfs];
	piece[BLACK] ^= 1ULL << (mts - 8);
	bmat += val[BP];
	bpos += pst[BP][mts];
	pctypbb[WP] ^= 1ull << mts;
	pctypbb[WP] ^= 1ull << mfs;
	pctypbb[BP] ^= 1ull << (mts - 8);
	break;
  case WPQ:
	board[mfs] = WP;
	board[mts] = mtt;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	wpos -= pst[WQ][mts];
	wpos += pst[WP][mfs];
	wmat -= 80;
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat += val[mtt];
	bpos += pst[mtt][mts];
	pctypbb[WQ] ^= 1ull << mts;
	pctypbb[WP] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WPN:
	board[mfs] = WP;
	board[mts] = mtt;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	wpos -= pst[WN][mts];
	wpos += pst[WP][mfs];
	wmat -= 19;
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat += val[mtt];
	bpos += pst[mtt][mts];
	pctypbb[WN] ^= 1ull << mts;
	pctypbb[WP] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WPR:
	board[mfs] = WP;
	board[mts] = mtt;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	wpos -= pst[WR][mts];
	wpos += pst[WP][mfs];
	wmat -= 40;
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat += val[mtt];
	bpos += pst[mtt][mts];
	pctypbb[WR] ^= 1ull << mts;
	pctypbb[WP] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case WPB:
	board[mfs] = WP;
	board[mts] = mtt;
	piece[WHITE] ^= 1ull << mts;
	piece[WHITE] ^= 1ull << mfs;
	wpos -= pst[WB][mts];
	wpos += pst[WP][mfs];
	wmat -= 22;
	piece[BLACK] ^= (u64)(mtt != ES) << mts;
	bmat += val[mtt];
	bpos += pst[mtt][mts];
	pctypbb[WB] ^= 1ull << mts;
	pctypbb[WP] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BCS:
	board[e8] = BKC;
	board[g8] = ES;
	piece[BLACK] ^= 1ull << g8;
	piece[BLACK] ^= 1ull << e8;
	king[BLACK] ^= 1ull << g8;
	king[BLACK] ^= 1ull << e8;
	bpos -= pst[BK][g8];
	bpos += pst[BK][e8];
	board[h8] = BRC;
	board[f8] = ES;
	piece[BLACK] ^= 1ull << f8;
	piece[BLACK] ^= 1ull << h8;
	bpos -= pst[BR][f8];
	bpos += pst[BR][h8];
	pctypbb[BR] ^= 1ull << f8;
	pctypbb[BR] ^= 1ull << h8;
	break;
  case BCL:
	board[e8] = BKC;
	board[c8] = ES;
	piece[BLACK] ^= 1ull << c8;
	piece[BLACK] ^= 1ull << e8;
	king[BLACK] ^= 1ull << c8;
	king[BLACK] ^= 1ull << e8;
	bpos -= pst[BK][c8];
	bpos += pst[BK][e8];
	board[a8] = BRC;
	board[d8] = ES;
	piece[BLACK] ^= 1ull << c8;
	piece[BLACK] ^= 1ull << a8;
	bpos -= pst[BR][d8];
	bpos += pst[BR][a8];
	pctypbb[BR] ^= 1ull << c8;
	pctypbb[BR] ^= 1ull << a8;
	break;
  case BPD:
	board[mfs] = BP;
	board[mts] = ES;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	bpos -= pst[BP][mts];
	bpos += pst[BP][mfs];
	pctypbb[BP] ^= 1ull << mts;
	pctypbb[BP] ^= 1ull << mfs;
	epbit[ply + 1] = 0;
	break;
  case BPE:
	board[mfs] = BP;
	board[mts] = ES;
	board[mts + 8] = WP;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	bpos -= pst[BP][mts];
	bpos += pst[BP][mfs];
	piece[WHITE] ^= 1ULL << (mts + 8);
	bmat += val[WP];
	bpos += pst[WP][mts];
	pctypbb[BP] ^= 1ull << mts;
	pctypbb[BP] ^= 1ull << mfs;
	pctypbb[WP] ^= 1ull << (mts + 8);
	break;
  case BPQ:
	board[mfs] = BP;
	board[mts] = mtt;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	bpos -= pst[BQ][mts];
	bpos += pst[BP][mfs];
	bmat -= 80;
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat += val[mtt];
	wpos += pst[mtt][mts];
	pctypbb[BQ] ^= 1ull << mts;
	pctypbb[BP] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BPN:
	board[mfs] = BP;
	board[mts] = mtt;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	bpos -= pst[BN][mts];
	bpos += pst[BP][mfs];
	bmat -= 19;
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat += val[mtt];
	wpos += pst[mtt][mts];
	pctypbb[BN] ^= 1ull << mts;
	pctypbb[BP] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BPR:
	board[mfs] = BP;
	board[mts] = mtt;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	bpos -= pst[BR][mts];
	bpos += pst[BP][mfs];
	bmat -= 40;
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat += val[mtt];
	wpos += pst[mtt][mts];
	pctypbb[BR] ^= 1ull << mts;
	pctypbb[BP] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  case BPB:
	board[mfs] = BP;
	board[mts] = mtt;
	piece[BLACK] ^= 1ull << mts;
	piece[BLACK] ^= 1ull << mfs;
	bpos -= pst[BB][mts];
	bpos += pst[BP][mfs];
	bmat -= 22;
	piece[WHITE] ^= (u64)(mtt != ES) << mts;
	wmat += val[mtt];
	wpos += pst[mtt][mts];
	pctypbb[BB] ^= 1ull << mts;
	pctypbb[BP] ^= 1ull << mfs;
	pctypbb[mtt] ^= 1ull << mts;
	break;
  }
}Code: Select all
// !
// Utilities.cpp
void PrintBoard(Thread* t) {
  s32 x, y, sq, pce;
  s08 fig[] = { ".PNBRRQKKpnbrrqkk" };
  for (y = 7; y >= 0; y--) {
	for (x = 0; x < 8; x++) {
	  sq = ((y << 3) + x);
	  pce = board[sq];
	  std::cout << "  " << fig[pce];
	}
	std::cout << std::endl;
  }
  std::cout << std::endl;
}
bool LoadFen(Thread* t, s08* f) {
  s32 rank, file, sq, fs, pce;
  for (sq = a1; sq <= h8; sq++) board[sq] = ES;
  
  ply = 0;
  file = FILEa;
  rank = RANK8;
  fs = 56;
  for (;; f++) {
	if (*f == ' ') break;
	switch (*f) {
	case '1':
	case '2':
	case '3':
	case '4':
	case '5':
	case '6':
	case '7':
	case '8':
	  file += *f - '0';
	  fs = (rank * 8 + file) & 63;
	  continue;
	case '/':
	  file = FILEa;
	  rank--;
	  fs = (rank * 8 + file) & 63;
	  continue;
	case 'P':
	  pce = WP;
	  break;
	case 'N':
	  pce = WN;
	  break;
	case 'B':
	  pce = WB;
	  break;
	case 'R':
	  pce = WR;
	  break;
	case 'Q':
	  pce = WQ;
	  break;
	case 'K':
	  pce = WK;
	  break;
	case 'p':
	  pce = BP;
		break;
	case 'n':
	  pce = BN;
	  break;
	case 'b':
	  pce = BB;
	  break;
	case 'r':
	  pce = BR;
	  break;
	case 'q':
	  pce = BQ;
	  break;
	case 'k':
	  pce = BK;
	  break;
	}
	board[fs] = pce;
	file++;
	fs = (rank * 8 + file) & 63;
  }
  f++;
  switch (*f++) {
  case 'w':
	stm = WHITE;
	break;
  case 'b':
	stm = BLACK;
	break;
  default:
	return false;
  }
  if (*f++ != ' ') return false;
  if (*f == '-') {
	f++;
	if (*f++ != ' ') return false;
  }
  else {
	for (;;) {
	  if (*f == ' ') {
		f++;
		break;
	  }
	  switch (*f++) {
	  case 'K':
		board[e1] = WKC;
		board[h1] = WRC;
		break;
	  case 'Q':
		board[e1] = WKC;
		board[a1] = WRC;
		break;
	  case 'k':
		board[e8] = BKC;
		board[h8] = BRC;
		break;
	  case 'q':
		board[e8] = BKC;
		board[a8] = BRC;
		break;
	  default:
		return false;
	  }
	}
  }
  epbit[0] = 0;
  if (*f == '-') f++;
  else {
	if (*f < 'a' || *f > 'h') return false;
	if (*(f + 1) < '0' || *(f + 1) > '7') return false;
	rank = *(f + 1) - '1';
	file = *f - 'a';
	f += 2;
  }
  if (*f++ != ' ') return false;
  fifty[0] = 0;
  for (;;) {
	if (!isdigit(*f)) break;
	fifty[0] = *f++ * 10;
	fifty[0] += *f++ - '0';
  }
  if (*f++ != ' ') return false;
  start = 0;
  for (;;) {
	if (!isdigit(*f)) break;
	start = *f++ * 10;
	start += *f++ - '0';
  }
  if (start < 1) return false;
  while (*f == ' ') f++;
  if (*f != '\0') return false;
  return true;
}
s32 AttackedByWhite(Thread* t, u64 bb) {
  s32 n = 0;
  u64 bbn;
  u64 occ = piece[BLACK] | piece[WHITE];
  do {
	s32 sq = std::countr_zero(bb);
	bbn = (knightMoves[sq] & pctypbb[WN])
	  | (bPawnCapts[sq] & pctypbb[WP])
	  | (kingMoves[sq] & pctypbb[WK])
	  | (((ray[std::countr_zero(ray[sq].NW & occ)].NW
		 | ray[std::countr_zero(ray[sq].NE & occ)].NE
		 | rev[std::countl_zero(ray[sq].SE & occ)].SE
		 | rev[std::countl_zero(ray[sq].SW & occ)].SW)
		 ^ bishopMoves[sq])
		 & (pctypbb[WB] | pctypbb[WQ]))
	  | (((ray[std::countr_zero(ray[sq].NN & occ)].NN
		 | ray[std::countr_zero(ray[sq].EE & occ)].EE
		 | rev[std::countl_zero(ray[sq].SS & occ)].SS
		 | rev[std::countl_zero(ray[sq].WW & occ)].WW)
		 ^ rookMoves[sq])
		 & (pctypbb[WR] | pctypbb[WQ]));
	n += std::popcount(bbn);
	bb ^= 1ull << sq;
  } while (bb);
  return n;
}
s32 AttackedByBlack(Thread* t, u64 bb) {
  s32 n = 0;
  u64 bbn;
  u64 occ = piece[BLACK] | piece[WHITE];
  do {
	s32 sq = std::countr_zero(bb);
	bbn = (knightMoves[sq] & pctypbb[BN])
	    | (wPawnCapts[sq] & pctypbb[BP])
	    | (kingMoves[sq] & pctypbb[BK])
	    | (((ray[std::countr_zero(ray[sq].NW & occ)].NW
		   | ray[std::countr_zero(ray[sq].NE & occ)].NE
		   | rev[std::countl_zero(ray[sq].SE & occ)].SE
		   | rev[std::countl_zero(ray[sq].SW & occ)].SW)
		   ^ bishopMoves[sq])
		   & (pctypbb[BB] | pctypbb[BQ]))
	    | (((ray[std::countr_zero(ray[sq].NN & occ)].NN
		   | ray[std::countr_zero(ray[sq].EE & occ)].EE
		   | rev[std::countl_zero(ray[sq].SS & occ)].SS
		   | rev[std::countl_zero(ray[sq].WW & occ)].WW)
		   ^ rookMoves[sq])
		   & (pctypbb[BR] | pctypbb[BQ]));
	n += std::popcount(bbn);
	bb ^= 1ull << sq;
  } while (bb);
  return n;
}
s32(*InCheckBy[2])(Thread*, u64) = { AttackedByBlack, AttackedByWhite };
uMove FillMoveFields(Thread* t, s08 fs, s08 ts) {
  uMove m;
  m.s.fs = fs;
  m.s.ts = ts;
  m.s.tt = board[ts];
  m.s.ft = board[fs];
  switch (m.s.ft) {
  case ES:
	// can't get here
	break;
  case WP:
	switch (fs >> 3) {
	case RANK1:
	  // can't get here
	  break;
	case RANK2:
	  m.s.ft += ((fs + 16 == ts) * (WPD - WP));
	  break;
	case RANK3:
	case RANK4:
	  // no action
	  break;
	case RANK5:
	  m.s.ft += ((ts != fs + 8 && !m.s.tt) * (WPE - WP));
	  break;
	case RANK6:
	  // no action
	  break;
	case RANK7:
	  m.s.ft = WPQ;
	  break;
	}
	break;
  case WN:
  case WB:
  case WRC:
  case WR:
  case WQ:
	// no action
	break;
  case WKC:
	m.s.ft += ((ts == g1) * (WCS - WKC) + (ts == c1) * (WCL - WKC));
	break;
  case WK:
	// no action
	break;
  case BP:
	switch (fs >> 3) {
	case RANK1:
	  // can't get here
	  break;
	case RANK2:
	  m.s.ft = BPQ;
	  break;
	case RANK3:
	  // no action
	  break;
	case RANK4:
	  m.s.ft += ((ts != fs - 8 && !m.s.tt) * (BPE - BP));
	  break;
	case RANK5:
	case RANK6:
	  // no action
	  break;
	case RANK7:
	  m.s.ft += ((fs - 16 == ts) * (BPD - BP));
	  break;
	}
	break;
  case BN:
  case BB:
  case BRC:
  case BR:
  case BQ:
	// no action
	break;
  case BKC:
	m.s.ft += ((ts == g8) * (BCS - BKC) + (ts == c8) * (BCL - BKC));
	break;
  }
  return m;
}Code: Select all
// !
// Globals.cpp
s32 mode;
s32 computer;
s32 numThreads;
Thread** thread;
Ray ray[65];
Ray rev[65];
u64 wPawnCapts[64];
u64 bPawnCapts[64];
u64 knightMoves[64];
u64 bishopMoves[64];
u64 rookMoves[64];
u64 queenMoves[64];
u64 kingMoves[64];
s32 val[] = { 0, 10, 29, 32, 50, 50, 90, 0, 0, 10, 29, 32, 50, 50, 90, 0, 0 };
s32 pst[17][64];
s08 startFen[] = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
s08 fen[100];Code: Select all
// !
// Equates.cpp
constexpr auto AWCS = 0b0000000000000000000000000000000000000000000000000000000001110000;
constexpr auto AWCL = 0b0000000000000000000000000000000000000000000000000000000000011100;
constexpr auto ABCS = 0b0111000000000000000000000000000000000000000000000000000000000000;
constexpr auto ABCL = 0b0001110000000000000000000000000000000000000000000000000000000000;
constexpr auto SWCS = 0b0000000000000000000000000000000000000000000000000000000001100000;
constexpr auto SWCL = 0b0000000000000000000000000000000000000000000000000000000000001110;
constexpr auto SBCS = 0b0110000000000000000000000000000000000000000000000000000000000000;
constexpr auto SBCL = 0b0000111000000000000000000000000000000000000000000000000000000000;
enum { EXIT, GETCMD, SEARCH };
enum { BLACK, WHITE };
enum { ILLEGAL, LEGAL };
enum {
  a1, b1, c1, d1, e1, f1, g1, h1,
  a2, b2, c2, d2, e2, f2, g2, h2,
  a3, b3, c3, d3, e3, f3, g3, h3,
  a4, b4, c4, d4, e4, f4, g4, h4,
  a5, b5, c5, d5, e5, f5, g5, h5,
  a6, b6, c6, d6, e6, f6, g6, h6,
  a7, b7, c7, d7, e7, f7, g7, h7,
  a8, b8, c8, d8, e8, f8, g8, h8
};
enum { FILEa, FILEb, FILEc, FILEd, FILEe, FILEf, FILEg, FILEh };
enum { RANK1, RANK2, RANK3, RANK4, RANK5, RANK6, RANK7, RANK8 };
enum {
  ES,
  WP, WN, WB, WRC, WR, WQ, WKC, WK,
  BP, BN, BB, BRC, BR, BQ, BKC, BK,
  WCS, WCL, WPD, WPE, WPQ, WPN, WPR, WPB,
  BCS, BCL, BPD, BPE, BPQ, BPN, BPR, BPB
};
Code: Select all
// !
// Defines.cpp
typedef char s08;
typedef int s32;
typedef unsigned long long u64;
typedef long long s64;
#define dir_HO(X) (0xFFull << (X & 56))
#define dir_VE(X) (0x0101010101010101ull << (X & 7))
#define dir_D1(X) (mask_shift(0x8040201008040201ull, (X & 7) - (X >> 3)))
#define dir_D2(X) (mask_shift(0x0102040810204080ull, 7 - (X & 7) - (X >> 3)))
#define GetLower(X) ((1ull << X) - 1)
#define GetUpper(X) (0xFFFFFFFFFFFFFFFE << (X))
struct Ray {
  u64 NW;
  u64 NN;
  u64 NE;
  u64 EE;
  u64 SE;
  u64 SS;
  u64 SW;
  u64 WW;
};
struct sMove {
  s08 fs; // from square
  s08 ts; // to square
  s08 ft; // from type
  s08 tt; // to type
  s32 sc; // score
};
union uMove {
  sMove s;
  u64 u;
};
// instead of typing m->s.fs just type mfs
#define mfs m->s.fs
#define mts m->s.ts
#define mft m->s.ft
#define mtt m->s.tt
struct Thread {
  uMove g[500];
  u64 piece[2];
  u64 king[2];
  u64 pctypbb[17];
  u64 epbit[100];
  u64 abb[100];
  u64 gbb[100][64];
  s32 board[64];
  s32 fifty[100];
  s32 ply;
  s32 gly;
  s32 stm;
  s32 wmat;
  s32 bmat;
  s32 wpos;
  s32 bpos;
  s32 start;
};
// to avoid having to type t->whatever just type whatever
#define g       t->g
#define piece   t->piece
#define king    t->king
#define pctypbb t->pctypbb
#define epbit   t->epbit
#define abb     t->abb
#define gbb     t->gbb
#define board   t->board
#define fifty   t->fifty
#define ply     t->ply
#define gly     t->gly
#define stm     t->stm
#define matsc   t->matsc
#define wmat    t->wmat
#define bmat    t->bmat
#define wpos    t->wpos
#define bpos    t->bpos
#define start   t->start
