Changes

Jump to: navigation, search

CPW-Engine move(0x88)

6,636 bytes added, 16:24, 18 December 2018
Created page with "'''Home * Engines * CPW-Engine * Move(0x88)''' Both move_make and move_unmake call the functions fillSq(color, piece, square) and clearSq(square). They..."
'''[[Main Page|Home]] * [[Engines]] * [[CPW-Engine]] * Move(0x88)'''

Both move_make and move_unmake call the functions fillSq(color, piece, square) and clearSq(square). They are meant to encapsulate all the incremental updates(material and pcsq calues, hash keys etc.) and can be viewed in [[CPW-Engine_board(0x88)]].Ideally this will make both make and unmake functions independent from the board representation. Beside that, incremental update code will be rather long, if not necessarily ugly.

= Code =
<pre>
#include "stdafx.h"
#include "transposition.h"

int move_makeNull() {
b.stm = !b.stm;
b.hash ^= zobrist.color;
b.ply++;
if (b.ep != -1) {
b.hash ^= zobrist.ep[b.ep];
b.ep = -1;
}
return 0;
}

int move_unmakeNull(char ep) {
b.stm = !b.stm;
b.hash ^= zobrist.color;
b.ply--;
if (ep != -1) {
b.hash ^= zobrist.ep[ep];
b.ep = ep;
}
return 0;
}

int move_make(smove move) {

/* switch the side to move */
b.stm = !b.stm;
b.hash ^= zobrist.color;

/* a capture or a pawn move clears b.ply */
b.ply++;
if ((move.piece_from == PAWN) || move_iscapt(move))
b.ply = 0;

/* a piece vacates its initial square */
clearSq(move.from);

/* in case of a capture, the "to" square must be cleared,
else incrementally updated stuff gets blown up
*/
if (b.pieces[move.to] != PIECE_EMPTY)
clearSq(move.to);

/* a piece arrives to its destination square */
fillSq(!b.stm, move.piece_to, move.to);

/* castle flags
if either a king or a rook leaves its initial square, the side looses its castling-right.
The same happens if another piece moves to this square (eg.: captures a rook on its initial square)
*/
switch (move.from) {
case H1: b.castle &= ~CASTLE_WK; break;
case E1: b.castle &= ~(CASTLE_WK | CASTLE_WQ); break;
case A1: b.castle &= ~CASTLE_WQ; break;
case H8: b.castle &= ~CASTLE_BK; break;
case E8: b.castle &= ~(CASTLE_BK | CASTLE_BQ); break;
case A8: b.castle &= ~CASTLE_BQ; break;
}
switch (move.to) {
case H1: b.castle &= ~CASTLE_WK; break;
case E1: b.castle &= ~(CASTLE_WK | CASTLE_WQ); break;
case A1: b.castle &= ~CASTLE_WQ; break;
case H8: b.castle &= ~CASTLE_BK; break;
case E8: b.castle &= ~(CASTLE_BK | CASTLE_BQ); break;
case A8: b.castle &= ~CASTLE_BQ; break;
}
b.hash ^= zobrist.castling[move.castle];
b.hash ^= zobrist.castling[b.castle];

/* castle-move
in communication with the gui a castling move is represented through
the king move. (eg.: e1g1 = White castles short) This king move already
got executed in the code above with the fillSq() and clearSq() command.
Whats missing now is the relating rook-move.
*/
if (move.flags & MFLAG_CASTLE) {
if (move.to == G1) {
clearSq(H1);
fillSq(WHITE, ROOK, F1);
}
else if (move.to == C1) {
clearSq(A1);
fillSq(WHITE, ROOK, D1);
}
else if (move.to == G8) {
clearSq(H8);
fillSq(BLACK, ROOK, F8);
}
else if (move.to == C8) {
clearSq(A8);
fillSq(BLACK, ROOK, D8);
}
}

/* en-passant flag
First erase the current state of the ep-flag, then set it again
in case there has been a two square pawn move that allows such
capture. For example, 1.e4 in the initial position will not set
the en passant flag, because there are no black pawns on d4 and f4.
This soluion helps with opening book and increases the number of
transposition table hits.
*/
if (b.ep != -1) {
b.hash ^= zobrist.ep[b.ep];
b.ep = -1;
}
if ((move.piece_from == PAWN) && (abs(move.from - move.to) == 32) &&
(pawnRecapture(!b.stm, (move.from + move.to) / 2))
) {
b.ep = (move.from + move.to) / 2;
b.hash ^= zobrist.ep[b.ep];
}

/* en-passant capture
if the move is an en-passant capture, the captured pawn has to be removed manually
*/
if (move.flags & MFLAG_EPCAPTURE) {
if (!b.stm == WHITE) {
clearSq(move.to - 16);
}
else {
clearSq(move.to + 16);
}
}

++b.rep_index;
b.rep_stack[b.rep_index] = b.hash;

return 0;
}

int move_unmake(smove move) {

b.stm = !b.stm;
b.hash ^= zobrist.color;

b.ply = move.ply;

/* set en passant square */
if (b.ep != -1)
b.hash ^= zobrist.ep[b.ep];
if (move.ep != -1)
b.hash ^= zobrist.ep[move.ep];
b.ep = move.ep;

clearSq(move.to);

fillSq(b.stm, move.piece_from, move.from);

/* un-capture
in case of a capture, put the captured piece back
*/
if (move_iscapt(move))
fillSq(!b.stm, move.piece_cap, move.to);

/* un-castle
the king has already been moved, now move the rook
*/
if (move.flags & MFLAG_CASTLE) {
if (move.to == G1) {
clearSq(F1);
fillSq(WHITE, ROOK, H1);
}
else if (move.to == C1) {
clearSq(D1);
fillSq(WHITE, ROOK, A1);
}
else if (move.to == G8) {
clearSq(F8);
fillSq(BLACK, ROOK, H8);
}
else if (move.to == C8) {
clearSq(D8);
fillSq(BLACK, ROOK, A8);
}
}

/* adjust castling flags */
b.hash ^= zobrist.castling[move.castle];
b.hash ^= zobrist.castling[b.castle];
b.castle = move.castle;

/* en-passant-uncapture
put the captured pawn back to its initial square
*/
if (move.flags & MFLAG_EPCAPTURE) {
if (b.stm == WHITE) {
fillSq(BLACK, PAWN, move.to - 16);
}
else {
fillSq(WHITE, PAWN, move.to + 16);
}
}

--b.rep_index;

return 0;
}

int move_iscapt(smove m) {
return (m.piece_cap != PIECE_EMPTY);
}

int move_isprom(smove m) {
return (m.piece_from != m.piece_to);
}

int move_canSimplify(smove m) {
if (m.piece_cap == PAWN ||
b.PieceMaterial[!b.stm] - e.PIECE_VALUE[m.piece_cap] > e.ENDGAME_MAT)
return 0;
else
return 1;
}

// this function returns number of legal moves in the current position

int move_countLegal() {
smove mlist[256];
int mcount = movegen(mlist, 0xFF);
int result = 0;

for (int i = 0; i < mcount; i++) {

// try a move...
move_make(mlist[i]);

// ...then increase the counter if it did not leave us in check
if (!isAttacked(b.stm, b.KingLoc[!b.stm])) ++result;

move_unmake(mlist[i]);
}

return result;
}

int move_isLegal(smove m) {
smove movelist[256];
int movecount = movegen(movelist, 0xFF);

for (int i = 0; i < movecount; i++) {
if (movelist[i].from == m.from &&
movelist[i].to == m.to) {

int result = 1;

// test if the move in question leaves us in check

move_make(movelist[i]);
if (isAttacked(b.stm, b.KingLoc[!b.stm])) result = 0;
move_unmake(movelist[i]);

return result;
}
}

return 0;
}
</pre>
'''[[CPW-Engine|Up one Level]]'''

Navigation menu