Board.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. #include "Board.h"
  2. #include <string>
  3. #include <map>
  4. #include <ctype.h>
  5. #include <stdexcept>
  6. #include <sstream>
  7. #include "MoveGeneration.h"
  8. using namespace chessy;
  9. using namespace std;
  10. void Board::resetBoard(void)
  11. {
  12. whites[PieceType::PAWN] = 0x000000000000FF00;
  13. whites[PieceType::ROOK] = 0x0000000000000081;
  14. whites[PieceType::KNIGHT] = 0x0000000000000042;
  15. whites[PieceType::BISHOP] = 0x0000000000000024;
  16. whites[PieceType::QUEEN] = 0x0000000000000008;
  17. whites[PieceType::KING] = 0x0000000000000010;
  18. blacks[PieceType::PAWN] = 0x00FF000000000000;
  19. blacks[PieceType::ROOK] = 0x8100000000000000;
  20. blacks[PieceType::KNIGHT] = 0x4200000000000000;
  21. blacks[PieceType::BISHOP] = 0x2400000000000000;
  22. blacks[PieceType::QUEEN] = 0x0800000000000000;
  23. blacks[PieceType::KING] = 0x1000000000000000;
  24. }
  25. void Board::setEmpty(void)
  26. {
  27. whites[PieceType::PAWN] = 0;
  28. whites[PieceType::KNIGHT] = 0;
  29. whites[PieceType::BISHOP] = 0;
  30. whites[PieceType::ROOK] = 0;
  31. whites[PieceType::QUEEN] = 0;
  32. whites[PieceType::KING] = 0;
  33. blacks[PieceType::PAWN] = 0;
  34. blacks[PieceType::KNIGHT] = 0;
  35. blacks[PieceType::BISHOP] = 0;
  36. blacks[PieceType::ROOK] = 0;
  37. blacks[PieceType::QUEEN] = 0;
  38. blacks[PieceType::KING] = 0;
  39. }
  40. bool Board::tryToMove(Bitboard start, Bitboard end, Bitboard& b)
  41. {
  42. if (start & b)
  43. b = b ^ start ^ end;
  44. return false;
  45. }
  46. void Board::setBoard(const std::string& fenPosition)
  47. {
  48. int row = 7, column = 0;
  49. map<char, Bitboard*> boards {
  50. { 'p', &blacks[PieceType::PAWN] },
  51. { 'n', &blacks[PieceType::KNIGHT] },
  52. { 'b', &blacks[PieceType::BISHOP] },
  53. { 'r', &blacks[PieceType::ROOK] },
  54. { 'q', &blacks[PieceType::QUEEN] },
  55. { 'k', &blacks[PieceType::KING] },
  56. { 'P', &whites[PieceType::PAWN] },
  57. { 'N', &whites[PieceType::KNIGHT] },
  58. { 'B', &whites[PieceType::BISHOP] },
  59. { 'R', &whites[PieceType::ROOK] },
  60. { 'Q', &whites[PieceType::QUEEN] },
  61. { 'K', &whites[PieceType::KING] }
  62. };
  63. setEmpty();
  64. for (auto character : fenPosition) {
  65. if (character >= '0' && character <= '9') {
  66. column += character - '0';
  67. }
  68. else if (character == '/') {
  69. -- row;
  70. column = 0;
  71. }
  72. else {
  73. auto board = boards.find(character);
  74. if (board != boards.end()) {
  75. *(board->second) |= Bitboard::fromIndex({row, column});
  76. }
  77. else {
  78. throw runtime_error("invalid piece type "s + character);
  79. }
  80. ++ column;
  81. }
  82. if (row < -1 || column > 8)
  83. throw runtime_error("invalid board string "s + fenPosition);
  84. }
  85. }
  86. // a bit hacky, sry
  87. std::string Board::getFenBoard(void) const
  88. {
  89. using namespace std;
  90. stringstream str;
  91. for (int row = 7; row >= 0; row--) {
  92. int counter = 0;
  93. for (int column = 0; column < 8; column++) {
  94. PieceType black = getBlackAtPosition({ row, column });
  95. PieceType white = getWhiteAtPosition({ row, column });
  96. //str << " " << Bitboard::fromIndex({row, column}) << " " << " ";;
  97. //str << "row,column,index: " << row << "," << column << "," <<
  98. // int(Index(row, column).index) << " ";
  99. if (black == PieceType::EMPTY && white == PieceType::EMPTY)
  100. ++ counter;
  101. else if (counter > 0) {
  102. str << counter;
  103. counter = 0;
  104. }
  105. switch (black) {
  106. case PieceType::PAWN: str << 'p'; break;
  107. case PieceType::KNIGHT: str << 'n'; break;
  108. case PieceType::BISHOP: str << 'b'; break;
  109. case PieceType::ROOK: str << 'r'; break;
  110. case PieceType::QUEEN: str << 'q'; break;
  111. case PieceType::KING: str << 'k'; break;
  112. default:
  113. switch (white) {
  114. case PieceType::PAWN: str << 'P'; break;
  115. case PieceType::KNIGHT: str << 'N'; break;
  116. case PieceType::BISHOP: str << 'B'; break;
  117. case PieceType::ROOK: str << 'R'; break;
  118. case PieceType::QUEEN: str << 'Q'; break;
  119. case PieceType::KING: str << 'K'; break;
  120. default:;
  121. }
  122. }
  123. }
  124. if (counter > 0)
  125. str << counter;
  126. if (row != 0)
  127. str << "/";
  128. }
  129. return str.str();
  130. }
  131. PieceType Board::getWhiteAtPosition(Index i) const
  132. {
  133. Bitboard mask = Bitboard::fromIndex(i);
  134. for (int i = 0; i < 6; i++)
  135. if (whites[i] & mask)
  136. return (PieceType) i;
  137. return PieceType::EMPTY;
  138. }
  139. PieceType Board::getBlackAtPosition(Index i) const
  140. {
  141. Bitboard mask = Bitboard::fromIndex(i);
  142. for (int i = 0; i < 6; i++)
  143. if (blacks[i] & mask)
  144. return (PieceType) i;
  145. return PieceType::EMPTY;
  146. }
  147. PieceType Board::getAtPosition(Index i) const
  148. {
  149. PieceType b = getWhiteAtPosition(i);
  150. if (b != PieceType::EMPTY)
  151. return b;
  152. return getBlackAtPosition(i);;
  153. }
  154. void Board::move(const Move& move)
  155. {
  156. Bitboard start = Bitboard::fromIndex(move.origin);
  157. Bitboard end = Bitboard::fromIndex(move.destination);
  158. for (Bitboard& b : whites)
  159. if (b & end) {
  160. b ^= end;
  161. goto move;
  162. }
  163. for (Bitboard& b : blacks)
  164. if (b & end) {
  165. b ^= end;
  166. goto move;
  167. }
  168. move:
  169. for (Bitboard& b : whites) {
  170. if (b & end)
  171. b ^= end;
  172. if (b & start) {
  173. b &= ~start;
  174. b |= end;
  175. return;
  176. }
  177. }
  178. for (Bitboard& b : blacks) {
  179. if (b & start) {
  180. b &= ~start;
  181. b |= end;
  182. return;
  183. }
  184. }
  185. }
  186. void Board::removeAt(Index i)
  187. {
  188. Bitboard mask = ~Bitboard::fromIndex(i);
  189. for (Bitboard& b : whites)
  190. b &= mask;
  191. for (Bitboard& b : blacks)
  192. b &= mask;
  193. }
  194. Bitboard Board::getWhites(void) const
  195. {
  196. return whites[0] | whites[1] | whites[2] | whites[3] | whites[4] | whites[5];
  197. }
  198. Bitboard Board::getBlacks(void) const
  199. {
  200. return blacks[0] | blacks[1] | blacks[2] | blacks[3] | blacks[4] | blacks[5];
  201. }
  202. Bitboard Board::getOccupied(void) const
  203. {
  204. return getBlacks() | getWhites();
  205. }
  206. Bitboard Board::getFree(void) const
  207. {
  208. return ~getOccupied();
  209. }
  210. #include <iostream>
  211. template<Side side>
  212. bool Board::isCheck(void) const
  213. {
  214. constexpr Side enemy = otherSide(side);
  215. Index kingIndex = getKing<side>().getLeastSignificantBit();
  216. KnightMoveGenerator nmg{ kingIndex, 0 };
  217. if (nmg.getBitboard() & getKnights<enemy>())
  218. return true;
  219. PrimitiveBishopMoveGenerator pbmg{ kingIndex, get<enemy>(), get<side>() };
  220. if (pbmg.getBitboard() & (getBishops<enemy>() | getQueens<enemy>()))
  221. return true;
  222. PrimitiveRookMoveGenerator prmg{ kingIndex, get<enemy>(), get<side>() };
  223. if (prmg.getBitboard() & (getRooks<enemy>() | getQueens<enemy>()))
  224. return true;
  225. if (side == WHITE_SIDE) {
  226. if (kingIndex.getRow() < 6) {
  227. if (kingIndex.getColumn() > 0)
  228. if (getKing<side>().neOne() & getPawns<enemy>())
  229. return true;
  230. if (kingIndex.getColumn() < 7)
  231. if (getKing<side>().nwOne() & getPawns<enemy>())
  232. return true;
  233. }
  234. }
  235. else {
  236. if (kingIndex.getRow() > 1) {
  237. if (kingIndex.getColumn() > 0)
  238. if (getKing<side>().seOne() & getPawns<enemy>())
  239. return true;
  240. if (kingIndex.getColumn() < 7)
  241. if (getKing<side>().swOne() & getPawns<enemy>())
  242. return true;
  243. }
  244. }
  245. KingMoveGenerator kmg{ getKing<side>(), 0 };
  246. if (kmg.getBitboard() & getKing<enemy>())
  247. return true;
  248. return false;
  249. }
  250. template bool Board::isCheck<WHITE_SIDE>(void) const;
  251. template bool Board::isCheck<BLACK_SIDE>(void) const;