Subversion Repositories Games.Chess Giants

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2. This Software is distributed with the following X11 License,
  3. sometimes also known as MIT license.
  4.  
  5. Copyright (c) 2010 Miguel A. Ballicora
  6.  
  7.  Permission is hereby granted, free of charge, to any person
  8.  obtaining a copy of this software and associated documentation
  9.  files (the "Software"), to deal in the Software without
  10.  restriction, including without limitation the rights to use,
  11.  copy, modify, merge, publish, distribute, sublicense, and/or sell
  12.  copies of the Software, and to permit persons to whom the
  13.  Software is furnished to do so, subject to the following
  14.  conditions:
  15.  
  16.  The above copyright notice and this permission notice shall be
  17.  included in all copies or substantial portions of the Software.
  18.  
  19.  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  20.  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  21.  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  22.  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  23.  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  24.  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  25.  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  26.  OTHER DEALINGS IN THE SOFTWARE.
  27. */
  28.  
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include "gtb-att.h"
  32.  
  33. #if 0
  34.  
  35. #include "mtypes.h"
  36. #include "bool_t.h"
  37. #include "maindef.h"
  38.  
  39. #else
  40.  
  41. /* mtypes.h */
  42.  
  43. typedef unsigned int SQUARE;
  44. typedef unsigned char SQ_CONTENT;
  45.  
  46. /* bool_t.h */
  47.  
  48. #if !defined(bool_t)
  49. typedef int                                             bool_t;
  50. #endif
  51.  
  52. #if !defined(TRUE)
  53. #define TRUE ((bool_t)1)
  54. #endif
  55.  
  56. #if !defined(FALSE)
  57. #define FALSE ((bool_t)0)
  58. #endif
  59.  
  60. /* maindef.h */
  61.  
  62. #define NOPIECE 0u
  63. #define PAWN    1u
  64. #define KNIGHT  2u
  65. #define BISHOP  3u
  66. #define ROOK    4u
  67. #define QUEEN   5u
  68. #define KING    6u
  69. #define PIECE_MASK (KING|PAWN|KNIGHT|BISHOP|ROOK|QUEEN)
  70.  
  71. /*Whites*/
  72. #define wK (KING   | WHITES)
  73. #define wP (PAWN   | WHITES)
  74. #define wN (KNIGHT | WHITES)
  75. #define wB (BISHOP | WHITES)
  76. #define wR (ROOK   | WHITES)
  77. #define wQ (QUEEN  | WHITES)
  78.  
  79. /*Blacks*/
  80. #define bK (KING   | BLACKS)
  81. #define bP (PAWN   | BLACKS)
  82. #define bN (KNIGHT | BLACKS)
  83. #define bB (BISHOP | BLACKS)
  84. #define bR (ROOK   | BLACKS)
  85. #define bQ (QUEEN  | BLACKS)
  86.  
  87. /*Bits that define color */
  88.  
  89. #define WHITES (1u<<6)
  90. #define BLACKS (1u<<7)
  91.  
  92. /*squares*/
  93. enum SQUARES {
  94.         A1,B1,C1,D1,E1,F1,G1,H1,
  95.         A2,B2,C2,D2,E2,F2,G2,H2,
  96.         A3,B3,C3,D3,E3,F3,G3,H3,
  97.         A4,B4,C4,D4,E4,F4,G4,H4,
  98.         A5,B5,C5,D5,E5,F5,G5,H5,
  99.         A6,B6,C6,D6,E6,F6,G6,H6,
  100.         A7,B7,C7,D7,E7,F7,G7,H7,
  101.         A8,B8,C8,D8,E8,F8,G8,H8,
  102.         NOSQUARE,
  103.         ERRSQUARE = 128
  104. };
  105. #endif
  106.  
  107. /*----------------------------------------------------------------------*/
  108.  
  109. #ifndef NDEBUG
  110. #define NDEBUG
  111. #endif
  112. #ifdef DEBUG
  113. #undef NDEBUG
  114. #endif
  115. #include "assert.h"
  116.  
  117. /*----------------------------------------------------------------------*/
  118.  
  119. /* global variables */
  120. uint64_t Reach [7] [64];
  121.  
  122. /* static variables */
  123. static unsigned char    attmap [64] [64];
  124. static unsigned int             attmsk [256];
  125.  
  126. /* static functions */
  127. static unsigned int mapx88 (unsigned int x);
  128.  
  129. /* macros */
  130. #define BB_ISBITON(bb,bit)   (0 != (((bb)>>(bit)) & U64(1)))
  131.  
  132. #define map88(x)    (   (x) + ((x)&070)        )
  133. #define unmap88(x)  ( ( (x) + ((x)& 07) ) >> 1 )
  134.  
  135. /*----------------------------------------------------------------------*/
  136.  
  137. static unsigned int
  138. mapx88 (unsigned int x)
  139. {
  140.         return ((x & 070) << 1) | (x & 07);
  141. }
  142.  
  143.  
  144. void
  145. attack_maps_init(void)
  146. {
  147.         int i;
  148.         unsigned int m, from, to;
  149.         unsigned int to88, fr88;
  150.         int diff;      
  151.  
  152.         uint64_t rook, bishop, queen, knight, king;
  153.  
  154.         if (!reach_was_initialized()) {
  155.                 printf ("Wrong initialization order of data\n");
  156.                 exit(EXIT_FAILURE);
  157.         }
  158.  
  159.         for (i = 0; i < 256; ++i) {
  160.                 attmsk [i] = 0;
  161.         }
  162.         attmsk[wP]              = 1 << 0;
  163.         attmsk[bP]              = 1 << 1;
  164.  
  165.         attmsk[KNIGHT]  = 1 << 2;
  166.         attmsk[wN]              = 1 << 2;
  167.         attmsk[bN]              = 1 << 2;
  168.  
  169.         attmsk[BISHOP]  = 1 << 3;
  170.         attmsk[wB]              = 1 << 3;
  171.         attmsk[bB]              = 1 << 3;
  172.  
  173.         attmsk[ROOK  ]  = 1 << 4;
  174.         attmsk[wR]              = 1 << 4;
  175.         attmsk[bR]              = 1 << 4;
  176.  
  177.         attmsk[QUEEN ]  = 1 << 5;
  178.         attmsk[wQ]              = 1 << 5;
  179.         attmsk[bQ]              = 1 << 5;
  180.  
  181.         attmsk[KING  ]  = 1 << 6;
  182.         attmsk[wK]              = 1 << 6;
  183.         attmsk[bK]              = 1 << 6;
  184.  
  185.         for (to = 0; to < 64; ++to) {
  186.                 for (from = 0; from < 64; ++from) {
  187.                         m = 0;
  188.                         rook   = Reach [ROOK]   [from];
  189.                         bishop = Reach [BISHOP] [from];
  190.                         queen  = Reach [QUEEN]  [from];
  191.                         knight = Reach [KNIGHT] [from];
  192.                         king   = Reach [KING]   [from];
  193.  
  194.                         if (BB_ISBITON (knight, to)) {
  195.                                 m |= attmsk[wN];
  196.                         }
  197.                         if (BB_ISBITON (king, to)) {
  198.                                 m |= attmsk[wK];
  199.                         }
  200.                         if (BB_ISBITON (rook, to)) {
  201.                                 m |= attmsk[wR];
  202.                         }
  203.                         if (BB_ISBITON (bishop, to)) {
  204.                                 m |= attmsk[wB];
  205.                         }                      
  206.                         if (BB_ISBITON (queen, to)) {
  207.                                 m |= attmsk[wQ];
  208.                         }
  209.                        
  210.                         to88 = mapx88(to);
  211.                         fr88 = mapx88(from);
  212.                         diff = (int)to88 - (int)fr88;
  213.  
  214.                         if (diff ==  17 || diff ==  15) {
  215.                                 m |= attmsk[wP];
  216.                         }
  217.                         if (diff == -17 || diff == -15) {
  218.                                 m |= attmsk[bP];
  219.                         }
  220.  
  221.                         attmap [to] [from] = (unsigned char) m;
  222.                 }              
  223.         }
  224.  
  225. }
  226.  
  227. bool_t
  228. possible_attack(unsigned int from, unsigned int to, unsigned int piece)
  229. {
  230.  
  231.         assert (piece < 256);
  232.         assert (from < 64 && to < 64);
  233.         assert (reach_was_initialized());
  234.         assert (attmsk [piece] != 0 || 0==fprintf(stderr, "PIECE=%d\n",piece) ); /* means piece has been considered */
  235.  
  236.         return 0 != (attmap [to] [from] & attmsk [piece]);
  237. }
  238.  
  239. /*
  240. |
  241. |       REACH ROUTINES
  242. |
  243. \*----------------------------------------------*/
  244.  
  245.  
  246. enum Key {REACH_INITIALIZED_KEY = 0x1313};
  247. static int reach_initialized_key = 0;
  248.  
  249. bool_t
  250. reach_was_initialized (void)
  251. {
  252.         return  reach_initialized_key == REACH_INITIALIZED_KEY;
  253. }
  254.  
  255. void
  256. reach_init (void)
  257. {      
  258.         SQUARE buflist[64+1], *list;
  259.         SQ_CONTENT pc;
  260.         int stp_a [] = {15, -15 };
  261.         int stp_b [] = {17, -17 };
  262.         int STEP_A, STEP_B;
  263.         unsigned int side;
  264.         unsigned int index;
  265.         SQUARE sq, us;
  266.  
  267.         int s;
  268.  
  269.         for (pc = KNIGHT; pc < (KING+1); pc++) {
  270.                 for (sq = 0; sq < 64; sq++) {
  271.                         uint64_t bb = U64(0x0);
  272.                         tolist_rev (U64(0x0), pc, sq, buflist);
  273.                         for (list = buflist; *list != NOSQUARE; list++) {
  274.                                 bb |= U64(1) << *list;
  275.                         }
  276.                         Reach [pc] [sq] = bb;
  277.                 }
  278.         }
  279.  
  280.         for (side = 0; side < 2; side++) {
  281.                 index  = 1u ^ side;
  282.                 STEP_A = stp_a[side];
  283.                 STEP_B = stp_b[side];
  284.                 for (sq = 0; sq < 64; sq++) {
  285.  
  286.                         int sq88 = (int)map88(sq);
  287.                         uint64_t bb = U64(0x0);
  288.  
  289.                         list = buflist;
  290.        
  291.  
  292.                         s = sq88 + STEP_A;
  293.                         if (0 == (s & 0x88)) {
  294.                                 us = (SQUARE)unmap88(s);
  295.                                 *list++ = us;
  296.                         }
  297.                         s = sq88 + STEP_B;
  298.                         if (0 == (s & 0x88)) {
  299.                                 us = (SQUARE)unmap88(s);
  300.                                 *list++ = us;
  301.                         }
  302.                         *list = NOSQUARE;
  303.  
  304.                         for (list = buflist; *list != NOSQUARE; list++) {
  305.                                 bb |= U64(1) << *list;
  306.                         }
  307.                         Reach [index] [sq] = bb;
  308.                 }
  309.         }
  310.         reach_initialized_key = REACH_INITIALIZED_KEY;
  311. }
  312.  
  313. /*--------------------------------------------------------------------------------*/
  314.  
  315. static const int bstep[]  = { 17,  15, -15, -17,  0};
  316. static const int rstep[]  = {  1,  16,  -1, -16,  0};
  317. static const int nstep[]  = { 18,  33,  31,  14, -18, -33, -31, -14,  0};
  318. static const int kstep[]  = {  1,  17,  16,  15,  -1, -17, -16, -15,  0};
  319.          
  320. static const
  321. int *psteparr[] = {NULL, NULL, /* NOPIECE & PAWN */
  322.                    nstep, bstep, rstep, kstep, kstep /* same for Q & K*/
  323.                   };
  324. static const
  325. int   pslider[] = {FALSE, FALSE,
  326.                    FALSE,  TRUE,  TRUE,  TRUE, FALSE
  327.                   };
  328.        
  329. void
  330. tolist_rev (uint64_t occ, SQ_CONTENT input_piece, SQUARE sq, SQUARE *list)
  331. /* reversible moves from pieces. Output is a list of squares */
  332. {
  333.         int direction;
  334.         unsigned int pc;
  335.     int s;
  336.         int from;
  337.         int step;
  338.         const int *steparr;
  339.         bool_t slider;
  340.         SQUARE us;
  341.  
  342.     assert (sq < 64);
  343.  
  344.         /* i.e. no pawn allowed as input */
  345.         assert (input_piece == KNIGHT || input_piece == BISHOP ||
  346.                         input_piece == ROOK   || input_piece == QUEEN  ||
  347.                         input_piece == KING);
  348.  
  349.         from = (int)map88(sq);
  350.        
  351.         pc = input_piece & (PAWN|KNIGHT|BISHOP|ROOK|QUEEN|KING);
  352.  
  353.         steparr = psteparr [pc];
  354.         slider  = pslider  [pc];
  355.  
  356.         if (slider) {
  357.                
  358.                 for (direction = 0; steparr[direction] != 0; direction++) {
  359.                         step = steparr[direction];
  360.                         s = from + step;
  361.                         while (0 == (s & 0x88)) {
  362.                                 us = (SQUARE)unmap88(s);
  363.                                 if (0 != (0x1u & (unsigned int)(occ >> us)))
  364.                                         break;
  365.                                 *list++ = us;
  366.                                 s += step;
  367.                         }
  368.                 }
  369.  
  370.         } else {
  371.                
  372.                 for (direction = 0; steparr[direction] != 0; direction++) {
  373.                         step = steparr[direction];
  374.                         s = from + step;
  375.                         if (0 == (s & 0x88)) {
  376.                                 us = (SQUARE)unmap88(s);
  377.                                 if (0 == (0x1u & (unsigned int)(occ >> us))) {
  378.                                         *list++ = us;
  379.                                 }
  380.                         }
  381.                 }              
  382.         }
  383.  
  384.         *list = NOSQUARE;
  385.  
  386.         return;
  387. }      
  388.  
  389.  
  390.  
  391.