Advertisement
regzarr

C Chess v0.12

Mar 25th, 2019
265
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 12.83 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdint.h>
  3. #include <string.h>
  4. #include <time.h>
  5. #include <stdlib.h>
  6.  
  7. /*  ~~~ BITBOARD REPRESENTATION LAYOUT ~~~
  8.  *  56  57  58  59  60  61  62  63
  9.     48  49  50  51  52  53  54  55
  10.     40  41  42  43  44  45  46  47
  11.     32  33  34  35  36  37  38  39
  12.     24  25  26  27  28  29  30  31
  13.     16  17  18  19  20  21  22  23
  14.     08  09  10  11  12  13  14  15
  15.     00  01  02  03  04  05  06  07
  16.  */
  17.  
  18. #define BOARD_STRING_SIZE 2004 + 1
  19.  
  20. // Evaluation values.
  21. #define VALUE_KING 200
  22. #define VALUE_QUEEN 9
  23. #define VALUE_ROOK 5
  24. #define VALUE_BISHOP 3
  25. #define VALUE_KNIGHT 3
  26. #define VALUE_PAWN 1
  27.  
  28. /* Positional bitwise operations
  29.  * NOTE: @amount ALWAYS needs to be positive
  30.  * --- SHIFTING BY NEGATIVE VALUES IS UNDEFINED BEHAVIOUR IN C. ---
  31.  * Also, it should be checked before calling whether or not @amount is within
  32.  * "legal" bounds (not exceeding the board size), e.g.:
  33.  *      - if @x represents the H8 square (upper right corner) the maximum value
  34.  *      @amount can take for NORTH_EAST is 0, for SOUTH_WEST 7 and for the other
  35.  *      two it is also 0;
  36.  *      - if @x represents the B7 square the maximum value @amount can take for
  37.  *      SOUTH_EAST is 6 and for the other three it is 1.
  38.  */
  39. #define NORTH(x, amount) (x) << (8 * (amount))
  40. #define SOUTH(x, amount) (x) >> (8 * (amount))
  41. #define WEST(x, amount) (x) >> (amount)
  42. #define EAST(x, amount) (x) << (amount)
  43. #define NORTH_EAST(x, amount) (x) << (9 * (amount))
  44. #define NORTH_WEST(x, amount) (x) << (7 * (amount))
  45. #define SOUTH_EAST(x, amount) (x) >> (7 * (amount))
  46. #define SOUTH_WEST(x, amount) (x) >> (9 * (amount))
  47.  
  48. // Positions on board.
  49. #define WHITE_SQUARES 0x55aa55aa55aa55aa
  50. #define BLACK_SQUARES 0xaa55aa55aa55aa55
  51. #define A_FILE 0x101010101010101
  52. #define B_FILE 0x202020202020202
  53. #define C_FILE 0x404040404040404
  54. #define D_FILE 0x808080808080808
  55. #define E_FILE 0x1010101010101010
  56. #define F_FILE 0x2020202020202020
  57. #define G_FILE 0x4040404040404040
  58. #define H_FILE 0x8080808080808080
  59. #define RANK_1 0xff
  60. #define RANK_2 0xff00
  61. #define RANK_3 0xff0000
  62. #define RANK_4 0xff000000
  63. #define RANK_5 0xff00000000
  64. #define RANK_6 0xff0000000000
  65. #define RANK_7 0xff000000000000
  66. #define RANK_8 0xff00000000000000
  67.  
  68. // Positions (char array index) on board string.
  69. // There is an horizontal increment of 7 between pieces and a vertical
  70. // increment of 236. For example: the char representing the piece on A8
  71. // will be at @_board[123], the one on B8 at @_board[130] and the one on
  72. // A7 at @_board[123 + 236]
  73. #define S_HORIZONTAL_INC 7
  74. #define S_VERTICAL_INC 236
  75. #define S_A8 123      // upper left corner
  76. #define S_A7 (S_A8 + S_VERTICAL_INC)
  77. #define S_A6 (S_A8 + 2 * S_VERTICAL_INC)
  78. #define S_A3 (S_A8 + 5 * S_VERTICAL_INC)
  79. #define S_A2 (S_A8 + 6 * S_VERTICAL_INC)
  80. #define S_A1 (S_A8 + 7 * S_VERTICAL_INC)
  81. #define S_H1 1824     // lower right corner
  82.  
  83. // States
  84. #define ST_PLAYING 0xf
  85. #define ST_DRAW 0
  86. #define ST_WHITE_WIN 1
  87. #define ST_WHITE_IN_CHECK 2
  88. #define ST_BLACK_WIN -1
  89. #define ST_BLACK_IN_CHECK -2
  90.  
  91. #define PLAYER_WHITE 1
  92. #define PLAYER_BLACK -1
  93. uint64_t _wKing;
  94. uint64_t _wQueen;
  95. uint64_t _wRooks;
  96. uint64_t _wBishops;
  97. uint64_t _wKnights;
  98. uint64_t _wPawns;
  99. uint64_t _wPieces;
  100. uint64_t _bKing;
  101. uint64_t _bQueen;
  102. uint64_t _bRooks;
  103. uint64_t _bBishops;
  104. uint64_t _bKnights;
  105. uint64_t _bPawns;
  106. uint64_t _bPieces;
  107.  
  108. // 16 eligible squares for en passant: the 7th rank and the 2nd rank
  109. uint64_t _enPassant; // could've made it 8bit but it gets promoted anyway
  110.  
  111. // least significant 2 bits for white, the next two for black
  112. // first king-side, then queen-side (e.g.: for 1101 white can only castle
  113. // kingside but black can castle both ways).
  114. uint8_t _canCastle;
  115.  
  116. int8_t _player; // 1 = white, -1 = black
  117.  
  118. // 0xF = playing, 0 = draw/stalemate, -1 black win, 1 = white win
  119. // 2 = white in check, -2 = black in check
  120. int8_t _playingState;
  121.  
  122. /* The fifty-move rule in chess states that a player can claim a draw if no
  123.  * capture has been made and no pawn has been moved in the last fifty moves
  124.  */
  125. uint8_t _50MoveRuleCount;
  126.  
  127.  
  128. char _board[BOARD_STRING_SIZE] =
  129.     "  ########################################################\n"
  130.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  131.     "8 #  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  #\n"
  132.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  133.     "  ########################################################\n"
  134.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  135.     "7 #  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  #\n"
  136.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  137.     "  ########################################################\n"
  138.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  139.     "6 #  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  #\n"
  140.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  141.     "  ########################################################\n"
  142.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  143.     "5 #  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  #\n"
  144.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  145.     "  ########################################################\n"
  146.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  147.     "4 #  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  #\n"
  148.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  149.     "  ########################################################\n"
  150.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  151.     "3 #  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  #\n"
  152.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  153.     "  ########################################################\n"
  154.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  155.     "2 #  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  #\n"
  156.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  157.     "  ########################################################\n"
  158.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  159.     "1 #  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  ##  O  #\n"
  160.     "  #     ##     ##     ##     ##     ##     ##     ##     #\n"
  161.     "  ########################################################\n"
  162.     "     A      B      C      D      E      F      G      H\n\n";
  163.  
  164. void clearBitPos(uint64_t *var, uint64_t x) {
  165.     *var &= (~1u << x);
  166. }
  167.  
  168. void setBitPos(uint64_t *var, uint64_t x) {
  169.     *var |= (1 << x);
  170. }
  171.  
  172. // Returns either 0 or a value greater than 0.
  173. uint64_t getBitPos(const uint64_t *var, uint64_t x) {
  174.     return *var & (1 << x);
  175. }
  176.  
  177. /* For versatility's sake, the board will always look the same but the way
  178.  * pieces and empty squares are represented can be changed. This function works
  179.  * for the random variant too.
  180.  */
  181. void init_board_string() {
  182. #define A8 (1ull << (8 * 7))
  183. #define A2 (1ull << 8)
  184. #define S_OPEN_SQUARE ' ' // must be a single char
  185.  
  186.     uint64_t *ptrBlackPieces[6] = {
  187.         &_bPawns, &_bRooks, &_bKnights, &_bBishops, &_bQueen, &_bKing
  188.     };
  189.     uint64_t *ptrWhitePieces[6] = {
  190.         &_wPawns, &_wRooks, &_wKnights, &_wBishops, &_wQueen, &_wKing
  191.     };
  192.  
  193.     enum Piece {
  194.         Pawn = 0, Rook, Knight, Bishop, Queen, King
  195.     };
  196.  
  197.     char c;
  198.     unsigned i, j, k;
  199.     uint64_t square = A8;
  200.     // black pieces
  201.     for (i = S_A8; i <= S_A7; i = i + S_VERTICAL_INC) {
  202.         for (j = i; j <= i + S_HORIZONTAL_INC * 7; j = j + S_HORIZONTAL_INC) {
  203.             c = S_OPEN_SQUARE;
  204.             // determine what black piece resides here
  205.             for (k = 0; k < 6; ++k) {
  206.                 if (*ptrBlackPieces[k] & square) {
  207.                     switch (k) {
  208.                         case Pawn :
  209.                             c = 'p';
  210.                             break;
  211.                         case Rook :
  212.                             c = 'r';
  213.                             break;
  214.                         case Knight:
  215.                             c = 'n';
  216.                             break;
  217.                         case Bishop :
  218.                             c = 'b';
  219.                             break;
  220.                         case Queen :
  221.                             c = 'q';
  222.                             break;
  223.                         case King :
  224.                             c = 'k';
  225.                             break;
  226.                         default:
  227.                             c = '?';
  228.                     }
  229.                 }
  230.             }
  231.             _board[j] = c;
  232.             square = EAST(square, 1);
  233.         }
  234.         square = SOUTH(A8, 1); // A7
  235.     }
  236.  
  237.     // open squares
  238.     for (i = S_A6; i <= S_A3; i = i + S_VERTICAL_INC) {
  239.         for (j = i; j <= i + S_HORIZONTAL_INC * 7; j = j + S_HORIZONTAL_INC) {
  240.             _board[j] = S_OPEN_SQUARE;
  241.         }
  242.     }
  243.  
  244.     // white pieces
  245.     square = A2;
  246.     for (i = S_A2; i <= S_A1; i = i + S_VERTICAL_INC) {
  247.         for (j = i; j <= i + S_HORIZONTAL_INC * 7; j = j + S_HORIZONTAL_INC) {
  248.             c = S_OPEN_SQUARE;
  249.             for (k = 0; k < 6; ++k) {
  250.                 if (*ptrWhitePieces[k] & square) {
  251.                     switch (k) {
  252.                         case Pawn :
  253.                             c = 'P';
  254.                             break;
  255.                         case Rook :
  256.                             c = 'R';
  257.                             break;
  258.                         case Knight:
  259.                             c = 'N';
  260.                             break;
  261.                         case Bishop :
  262.                             c = 'B';
  263.                             break;
  264.                         case Queen :
  265.                             c = 'Q';
  266.                             break;
  267.                         case King :
  268.                             c = 'K';
  269.                             break;
  270.                         default:
  271.                             c = '?';
  272.                     }
  273.                 }
  274.             }
  275.             _board[j] = c;
  276.             square = EAST(square, 1);
  277.         }
  278.         square = SOUTH(A2, 1); // A1
  279.     }
  280. }
  281.  
  282. void init_board() {
  283.     _wKing = RANK_1 & E_FILE;
  284.     _wQueen = RANK_1 & D_FILE;
  285.     _wRooks = (RANK_1 & A_FILE) | (RANK_1 & H_FILE);
  286.     _wBishops = (RANK_1 & C_FILE) | (RANK_1 & F_FILE);
  287.     _wKnights = (RANK_1 & B_FILE) | (RANK_1 & G_FILE);
  288.     _wPawns = RANK_2;
  289.  
  290.     _bKing = RANK_8 & E_FILE;
  291.     _bQueen = RANK_8 & D_FILE;
  292.     _bRooks = (RANK_8 & A_FILE) | (RANK_8 & H_FILE);
  293.     _bBishops = (RANK_8 & C_FILE) | (RANK_8 & F_FILE);
  294.     _bKnights = (RANK_8 & B_FILE) | (RANK_8 & G_FILE);
  295.     _bPawns = RANK_7;
  296.  
  297.     _wPieces = _wKing | _wQueen | _wRooks | _wBishops | _wKnights | _wPawns;
  298.     _bPieces = _bKing | _bQueen | _bRooks | _bBishops | _bKnights | _bPawns;
  299. }
  300.  
  301. // Generate source squares of pawns able to push
  302. // TODO (latest): Optimize (check 1 square advance and then the second one (if starting on r2))
  303. void gen_PawnMoves(uint64_t *board) {
  304.     *board = 0;
  305.     if (_player == PLAYER_WHITE) {
  306.         if (RANK_2 & _wPawns) {
  307.             // those pawns can move two squares
  308.             // TODO: check for white pieces in the way
  309.             *board = *board |
  310.                 (NORTH((RANK_2 & _wPawns), 2) &
  311.                 ~((RANK_4 & _bPieces) | (NORTH((RANK_3 & _bPieces), 1)) |
  312.                 (RANK_4 & _wPieces) | (NORTH((RANK_3 & _wPieces), 1))));
  313.         }
  314.         // 1 square advance for every pawn
  315.     }
  316. }
  317.  
  318. // generates the entire bitboard for available moves every time it's called
  319. // will optimize later; TODO: optimize gen_move()
  320. void gen_move(uint64_t *moveBoard, unsigned piece) {
  321.     *moveBoard = 0;
  322.     enum Pieces {
  323.         Pawn = 0, Knight, Bishop, Rook, Queen, King
  324.     };
  325.     switch (piece) {
  326.         case Pawn:
  327.  
  328.             break;
  329.         case Knight:
  330.  
  331.             break;
  332.         case Bishop:
  333.  
  334.             break;
  335.         case Rook:
  336.  
  337.             break;
  338.         case Queen:
  339.  
  340.             break;
  341.         case King:
  342.  
  343.             break;
  344.         default:
  345.             *moveBoard = 0; // redundant?
  346.             break;
  347.     }
  348. }
  349.  
  350. // TODO: rename @_playingState to @_state
  351. void play() {
  352.     _playingState = ST_PLAYING; // new game
  353.  
  354.     enum Pieces {
  355.         Pawn = 0, Knight, Bishop, Rook, Queen, King
  356.     };
  357.     uint64_t wMoveBoards[6];
  358.     uint64_t bMoveBoards[6];
  359.  
  360.     while (_playingState == ST_PLAYING) {
  361.         // generate moves for side, see source piece, pick one move randomly
  362.         if (_player == PLAYER_WHITE) {
  363.             // white moves
  364.  
  365.         }
  366.         if (_player == PLAYER_BLACK) {
  367.             // black moves
  368.         }
  369.         // check for a change of state (win or check or whatever)
  370.     }
  371. }
  372.  
  373. void print_board() {
  374.     printf("%s", _board);
  375. }
  376.  
  377. int main() {
  378.     srand((unsigned int) time(NULL));
  379.     init_board();
  380.     init_board_string();
  381.     print_board();
  382.  
  383.     return 0;
  384. }
  385.  
  386. /* TODO: Add states (castling rights, en passant, 50-move rule)
  387.  * TODO: Add play(), random variant for init_board()
  388.  */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement