Created
June 21, 2017 18:14
-
-
Save Ravenslofty/1133d0867f795d7dec77433d042b954a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * attacks.c - attack table update code. | |
| * | |
| * Copyright (C) 2016 Dan Ravensloft <[email protected]> | |
| * | |
| * This file is part of Dorpsgek. | |
| * | |
| * Dorpsgek is free software: you can redistribute it and/or modify | |
| * it under the terms of the GNU General Public License as published by | |
| * the Free Software Foundation, either version 3 of the License, or | |
| * (at your option) any later version. | |
| * | |
| * Dorpsgek is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| * GNU General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU General Public License | |
| * along with Dorpsgek. If not, see <http://www.gnu.org/licenses/>. | |
| */ | |
| #include <functional> | |
| #include <assert.h> | |
| #include <stdbool.h> | |
| #include <string.h> | |
| #include "definitions.h" | |
| #include "functions.h" | |
| auto AddBits = [](unsigned int bitlist, unsigned int bit) { return bitlist | bit; }; | |
| auto RemoveBits = [](unsigned int bitlist, unsigned int bit) { return bitlist & ~bit; }; | |
| void AddBitlist(struct Board * b, unsigned int bit, int piece, int from) | |
| { | |
| if (piece == PAWN) { | |
| int col = COL(from); | |
| if (bit & b->sidemask[WHITE]) { | |
| if (col) { | |
| b->bitlist[from + 7] |= bit; | |
| } | |
| if (col < 7) { | |
| b->bitlist[from + 9] |= bit; | |
| } | |
| } | |
| if (bit & b->sidemask[BLACK]) { | |
| if (col) { | |
| b->bitlist[from - 9] |= bit; | |
| } | |
| if (col < 7) { | |
| b->bitlist[from - 7] |= bit; | |
| } | |
| } | |
| } else { | |
| int delta; | |
| int from16x12 = TO16x12(from); | |
| for (int dir = 0; dir < 8; dir++) { | |
| delta = rays[piece][dir]; | |
| if (!delta) { | |
| break; | |
| } | |
| int to = from16x12 + delta; | |
| while (board16x12[to] != INVALID) { | |
| b->bitlist[board16x12[to]] |= bit; | |
| assert(ray_vector[VECTOR(from16x12, to)] == delta); | |
| if (!slide[piece] || b->index[board16x12[to]] != INVALID) { | |
| break; | |
| } | |
| to += delta; | |
| } | |
| } | |
| } | |
| } | |
| void RemoveBitlist(struct Board * b, unsigned int bit, int piece, int from) | |
| { | |
| if (piece == PAWN) { | |
| int col = COL(from); | |
| if (bit & b->sidemask[WHITE]) { | |
| if (col) { | |
| b->bitlist[from + 7] &= ~bit; | |
| } | |
| if (col < 7) { | |
| b->bitlist[from + 9] &= ~bit; | |
| } | |
| } | |
| if (bit & b->sidemask[BLACK]) { | |
| if (col) { | |
| b->bitlist[from - 9] &= ~bit; | |
| } | |
| if (col < 7) { | |
| b->bitlist[from - 7] &= ~bit; | |
| } | |
| } | |
| } else { | |
| int dir, delta; | |
| int from16x12 = TO16x12(from); | |
| for (dir = 0; dir < 8; dir++) { | |
| delta = rays[piece][dir]; | |
| if (!delta) { | |
| break; | |
| } | |
| int to = from16x12 + delta; | |
| while (board16x12[to] != INVALID) { | |
| b->bitlist[board16x12[to]] &= ~bit; | |
| assert(ray_vector[VECTOR(from16x12, to)] == delta); | |
| if (!slide[piece] || b->index[board16x12[to]] != INVALID) { | |
| break; | |
| } | |
| to += delta; | |
| } | |
| } | |
| } | |
| } | |
| void ExtendSliders(struct Board * b, int sq) | |
| { | |
| uint32_t bits = b->bitlist[sq] & (b->piecemask[BISHOP] | b->piecemask[ROOK] | b->piecemask[QUEEN]); | |
| int sq16x12 = TO16x12(sq); | |
| while (bits) { | |
| int bit = CountTrailingZeroes(bits); | |
| int from = b->piecelist[bit]; | |
| int from16x12 = TO16x12(from); | |
| bits &= bits - 1; | |
| int vec = VECTOR(from16x12, sq16x12); | |
| int dir = ray_vector[vec]; | |
| int to = sq16x12 + dir; | |
| while (board16x12[to] != INVALID) { | |
| b->bitlist[board16x12[to]] |= 1u << bit; | |
| if (b->index[board16x12[to]] != INVALID) { | |
| break; | |
| } | |
| to += dir; | |
| } | |
| } | |
| } | |
| void BlockSliders(struct Board * b, int sq) | |
| { | |
| uint32_t bits = b->bitlist[sq] & (b->piecemask[BISHOP] | b->piecemask[ROOK] | b->piecemask[QUEEN]); | |
| int sq16x12 = TO16x12(sq); | |
| while (bits) { | |
| int bit = CountTrailingZeroes(bits); | |
| int from = b->piecelist[bit]; | |
| int from16x12 = TO16x12(from); | |
| bits &= bits - 1; | |
| int vec = VECTOR(from16x12, sq16x12); | |
| int dir = ray_vector[vec]; | |
| int to = sq16x12 + dir; | |
| while (board16x12[to] != INVALID) { | |
| b->bitlist[board16x12[to]] &= ~(1u << bit); | |
| if (b->index[board16x12[to]] != INVALID) { | |
| break; | |
| } | |
| to += dir; | |
| } | |
| } | |
| } | |
| template<typename Func> | |
| void UpdateSliders(struct Board * b, int sq, Func update_func) | |
| { | |
| uint32_t bits = b->bitlist[sq] & (b->piecemask[BISHOP] | b->piecemask[ROOK] | b->piecemask[QUEEN]); | |
| int sq16x12 = TO16x12(sq); | |
| while (bits) { | |
| int bit = CountTrailingZeroes(bits); | |
| int from = b->piecelist[bit]; | |
| int from16x12 = TO16x12(from); | |
| bits &= bits - 1; | |
| int vec = VECTOR(from16x12, sq16x12); | |
| int dir = ray_vector[vec]; | |
| int to = sq16x12 + dir; | |
| while (board16x12[to] != INVALID) { | |
| b->bitlist[board16x12[to]] = update_func(b->bitlist[board16x12[to]], 1u << bit); | |
| if (b->index[board16x12[to]] != INVALID) { | |
| break; | |
| } | |
| to += dir; | |
| } | |
| } | |
| } | |
| void RecalculateAttacksFromScratch(struct Board * b) | |
| { | |
| int idx, sq; | |
| unsigned int i; | |
| memset(b->bitlist, 0, sizeof(b->bitlist)); | |
| for (idx = 0; idx < 32; idx++) { | |
| sq = b->piecelist[idx]; | |
| if (sq == INVALID) { | |
| continue; | |
| } | |
| i = 1u << idx; | |
| AddBitlist(b, i, GetPieceByBit(b, i), sq); | |
| } | |
| } | |
| void RecalculateAttacksForQuiets(struct Board * c, struct Move m) | |
| { | |
| int from = m.from; | |
| int dest = m.dest; | |
| unsigned int bit = 1u << c->index[dest]; | |
| int piece = GetPieceByBit(c, bit); | |
| RemoveBitlist(c, bit, piece, from); | |
| AddBitlist(c, bit, piece, dest); | |
| UpdateSliders(c, from, AddBits); | |
| UpdateSliders(c, from, RemoveBits); | |
| } | |
| void RecalculateAttacksForCaptures(struct Board * c, struct Move m) | |
| { | |
| int from = m.from; | |
| int dest = m.dest; | |
| unsigned int bit = 1u << c->index[dest]; | |
| int att = GetPieceByBit(c, bit); | |
| RemoveBitlist(c, bit, att, from); | |
| AddBitlist(c, bit, att, dest); | |
| // It turns out that because we remove the captured piece bit in the masks, | |
| // we can actually ignore resetting the captured piece bits without affecting | |
| // correctness. | |
| //RemoveBitlist(c, def_bit, def, dest); | |
| ExtendSliders(c, from); | |
| } | |
| void RecalculateAttacksForPromotions(struct Board * c, struct Move m) | |
| { | |
| int from = m.from; | |
| int dest = m.dest; | |
| int bit = 1 << c->index[dest]; | |
| RemoveBitlist(c, bit, PAWN, from); | |
| switch (m.type) { | |
| case MoveTypePromotionKnight: | |
| AddBitlist(c, bit, KNIGHT, dest); | |
| break; | |
| case MoveTypePromotionBishop: | |
| AddBitlist(c, bit, BISHOP, dest); | |
| break; | |
| case MoveTypePromotionRook: | |
| AddBitlist(c, bit, ROOK, dest); | |
| break; | |
| case MoveTypePromotionQueen: | |
| AddBitlist(c, bit, QUEEN, dest); | |
| break; | |
| } | |
| ExtendSliders(c, from); | |
| BlockSliders(c, dest); | |
| } | |
| void RecalculateAttacksForCapturePromotions(struct Board * c, struct Move m) | |
| { | |
| int from = m.from; | |
| int dest = m.dest; | |
| int att_bit = 1 << c->index[dest]; | |
| int att = GetPieceByBit(c, att_bit); | |
| RemoveBitlist(c, att_bit, PAWN, from); | |
| switch (m.type) { | |
| case MoveTypeCapturePromotionKnight: | |
| AddBitlist(c, att_bit, KNIGHT, dest); | |
| break; | |
| case MoveTypeCapturePromotionBishop: | |
| AddBitlist(c, att_bit, BISHOP, dest); | |
| break; | |
| case MoveTypeCapturePromotionRook: | |
| AddBitlist(c, att_bit, ROOK, dest); | |
| break; | |
| case MoveTypeCapturePromotionQueen: | |
| AddBitlist(c, att_bit, QUEEN, dest); | |
| break; | |
| } | |
| // It turns out that because we remove the captured piece bit in the masks, | |
| // we can actually ignore resetting the captured piece bits without affecting | |
| // correctness. | |
| //RemoveBitlist(c, def_bit, def, dest); | |
| ExtendSliders(c, from); | |
| } | |
| void RecalculateAttacks(struct Board * c, struct Move move) | |
| { | |
| if (move.type == MoveTypeNormal || move.type == MoveTypeDoublePush) { | |
| RecalculateAttacksForQuiets(c, move); | |
| } else if (move.type == MoveTypeCapture) { | |
| RecalculateAttacksForCaptures(c, move); | |
| } else if (move.type >= MoveTypePromotionQueen && move.type <= MoveTypePromotionKnight) { | |
| RecalculateAttacksForPromotions(c, move); | |
| } else if (move.type >= MoveTypeCapturePromotionQueen && move.type <= MoveTypeCapturePromotionKnight) { | |
| RecalculateAttacksForCapturePromotions(c, move); | |
| } else { | |
| RecalculateAttacksFromScratch(c); | |
| } | |
| //RecalculateAttacksFromScratch_Bad(c); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment