Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

303 lines
6.5 KiB

  1. /***************************************************************************/
  2. /** Microsoft Windows **/
  3. /** Copyright(c) Microsoft Corp., 1991, 1992 **/
  4. /***************************************************************************/
  5. /****************************************************************************
  6. computer.cpp
  7. keithmo
  8. ****************************************************************************/
  9. #include "hearts.h"
  10. #include "main.h"
  11. #include "resource.h"
  12. //
  13. // Static members.
  14. //
  15. //
  16. // This array is used to prioritize the search for cards
  17. // to pass. This basically maps the irritating A-K ordering
  18. // used by CARDS.DLL into a more appropriate 2-A ordering.
  19. //
  20. int computer :: _VectorPriority[13] =
  21. {
  22. VECTOR_ACE,
  23. VECTOR_KING,
  24. VECTOR_QUEEN,
  25. VECTOR_JACK,
  26. VECTOR_10,
  27. VECTOR_9,
  28. VECTOR_8,
  29. VECTOR_7,
  30. VECTOR_6,
  31. VECTOR_5,
  32. VECTOR_4,
  33. VECTOR_3,
  34. VECTOR_2
  35. };
  36. //
  37. // This array is used to prioritize the card suits.
  38. //
  39. int computer :: _SuitPriority[4] =
  40. {
  41. INDEX_HEARTS,
  42. INDEX_SPADES,
  43. INDEX_DIAMONDS,
  44. INDEX_CLUBS
  45. };
  46. /****************************************************************************
  47. computer constructor
  48. ****************************************************************************/
  49. computer :: computer(int n) : player(n, n)
  50. {
  51. CString newname;
  52. TCHAR buf[MAXNAMELENGTH+1];
  53. *buf = '\0';
  54. RegEntry Reg(szRegPath);
  55. Reg.GetString(regvalPName[n-1], buf, sizeof(buf));
  56. newname = buf;
  57. if (newname.IsEmpty())
  58. newname.LoadString(IDS_P1NAME + n - 1);
  59. CClientDC dc(::pMainWnd);
  60. SetName(newname, dc);
  61. } // computer :: computer
  62. /****************************************************************************
  63. Keith: Make sure you Select(TRUE) cards you select, and
  64. SetMode(DONE_SELECTING) before you return.
  65. ****************************************************************************/
  66. void computer :: SelectCardsToPass()
  67. {
  68. //
  69. // This will hold the total number of cards that
  70. // have been passed.
  71. //
  72. int cPassed = 0;
  73. int i;
  74. int nSuit;
  75. //
  76. // First we must build our database.
  77. //
  78. ComputeVectors();
  79. //
  80. // Priority 1: Lose the Queen, King, and Ace of Spades.
  81. //
  82. PassCardsInVector( QuerySpadesVector() & QKA_CARDS,
  83. INDEX_SPADES,
  84. &cPassed );
  85. //
  86. // Priority 2: Lose the Jack, Queen, King, and Ace of Hearts.
  87. //
  88. PassCardsInVector( QueryHeartsVector() & JQKA_CARDS,
  89. INDEX_HEARTS,
  90. &cPassed );
  91. //
  92. // Priority 3: Pass any high cards not accompanied by two or
  93. // more low cards.
  94. //
  95. for( i = 0 ; ( i < 4 ) && ( cPassed < 3 ) ; i++ )
  96. {
  97. nSuit = _SuitPriority[i];
  98. if( nSuit == INDEX_SPADES )
  99. {
  100. continue;
  101. }
  102. if( CountBits( _CardVectors[nSuit] & LOW_CARDS ) < 2 )
  103. {
  104. PassCardsInVector( _CardVectors[nSuit] & HIGH_CARDS,
  105. nSuit,
  106. &cPassed );
  107. }
  108. }
  109. //
  110. // Priority 4: If we have the opportunity to "short suit" our
  111. // hand, do it.
  112. //
  113. for( i = 0 ; ( i < 4 ) && ( cPassed < 3 ) ; i++ )
  114. {
  115. nSuit = _SuitPriority[i];
  116. if( CountBits( _CardVectors[nSuit] ) <= ( 3 - cPassed ) )
  117. {
  118. PassCardsInVector( _CardVectors[nSuit],
  119. nSuit,
  120. &cPassed );
  121. }
  122. }
  123. //
  124. // Priority 5: Hell, I don't know. Just find some cards to pass.
  125. //
  126. for( i = 0 ; ( i < 4 ) && ( cPassed < 3 ) ; i++ )
  127. {
  128. nSuit = _SuitPriority[i];
  129. PassCardsInVector( _CardVectors[nSuit],
  130. nSuit,
  131. &cPassed );
  132. }
  133. SetMode( DONE_SELECTING );
  134. } // computer :: SelectCardsToPass
  135. /****************************************************************************
  136. ComputeVectors
  137. This method sets the _CardVectors[] array to reflect the current set
  138. of cards held by the computer.
  139. ****************************************************************************/
  140. void computer :: ComputeVectors( void )
  141. {
  142. //
  143. // First, clear out the current vectors.
  144. //
  145. _CardVectors[0] = 0;
  146. _CardVectors[1] = 0;
  147. _CardVectors[2] = 0;
  148. _CardVectors[3] = 0;
  149. //
  150. // Now, scan the currently held cards, updating the vectors.
  151. //
  152. for( int i = 0 ; i < 13 ; i++ )
  153. {
  154. if( cd[i].IsInHand() )
  155. {
  156. AddCard( cd[i].ID() );
  157. }
  158. }
  159. } // computer :: ComputeVectors
  160. /****************************************************************************
  161. PassCardsInVector
  162. ****************************************************************************/
  163. void computer :: PassCardsInVector( int nVector, int nSuit, int * pcPassed )
  164. {
  165. int tmpVector;
  166. //
  167. // Don't even try if the vector is already empty or we've already
  168. // passed three cards.
  169. //
  170. if( ( nVector == 0 ) || ( *pcPassed >= 3 ) )
  171. return;
  172. //
  173. // Scan the cards in our hand. Pass all of those whose suit
  174. // matches nSuit & are in nVector. Prioritize the search
  175. // via the _VectorPriority array.
  176. //
  177. for( int m = 0 ; ( m < 13 ) && ( *pcPassed < 3 ) ; m++ )
  178. {
  179. tmpVector = nVector & _VectorPriority[m];
  180. if( tmpVector == 0 )
  181. continue;
  182. for( int i = 0 ; i < 13 ; i++ )
  183. {
  184. if( cd[i].Suit() != nSuit )
  185. continue;
  186. if( ( tmpVector & CardToVector( cd[i].ID() ) ) == 0 )
  187. continue;
  188. //
  189. // We found a card. Mark it as selected.
  190. //
  191. cd[i].Select( TRUE );
  192. //
  193. // Remove the card from our local vector. Also
  194. // remove it from the card database and update the
  195. // number of passed cards.
  196. //
  197. nVector &= ~CardToVector( cd[i].ID() );
  198. RemoveCard( cd[i].ID() );
  199. (*pcPassed)++;
  200. //
  201. // Since there's always *exactly* one bit set in
  202. // tmpVector, and we've found the card for that
  203. // bit, we can exit this inner loop.
  204. //
  205. break;
  206. }
  207. //
  208. // If the vector has become empty, we can terminate the
  209. // outer loop.
  210. //
  211. if( nVector == 0 )
  212. break;
  213. }
  214. } // computer :: PassCardsInVector
  215. /****************************************************************************
  216. CountBits
  217. ****************************************************************************/
  218. int computer :: CountBits( int x ) const
  219. {
  220. x = ( ( x >> 1 ) & 0x5555 ) + ( x & 0x5555 );
  221. x = ( ( x >> 2 ) & 0x3333 ) + ( x & 0x3333 );
  222. x = ( ( x >> 4 ) & 0x0f0f ) + ( x & 0x0f0f );
  223. x = ( ( x >> 8 ) & 0x00ff ) + ( x & 0x00ff );
  224. return x;
  225. } // computer :: CountBits