|
|
/***************************************************************************/ /** Microsoft Windows **/ /** Copyright(c) Microsoft Corp., 1991, 1992 **/ /***************************************************************************/
/****************************************************************************
computer.cpp
keithmo
****************************************************************************/
#include "hearts.h"
#include "main.h"
#include "resource.h"
//
// Static members.
//
//
// This array is used to prioritize the search for cards
// to pass. This basically maps the irritating A-K ordering
// used by CARDS.DLL into a more appropriate 2-A ordering.
//
int computer :: _VectorPriority[13] = { VECTOR_ACE, VECTOR_KING, VECTOR_QUEEN, VECTOR_JACK, VECTOR_10, VECTOR_9, VECTOR_8, VECTOR_7, VECTOR_6, VECTOR_5, VECTOR_4, VECTOR_3, VECTOR_2 };
//
// This array is used to prioritize the card suits.
//
int computer :: _SuitPriority[4] = { INDEX_HEARTS, INDEX_SPADES, INDEX_DIAMONDS, INDEX_CLUBS };
/****************************************************************************
computer constructor
****************************************************************************/ computer :: computer(int n) : player(n, n) { CString newname; TCHAR buf[MAXNAMELENGTH+1];
*buf = '\0'; RegEntry Reg(szRegPath); Reg.GetString(regvalPName[n-1], buf, sizeof(buf)); newname = buf;
if (newname.IsEmpty()) newname.LoadString(IDS_P1NAME + n - 1);
CClientDC dc(::pMainWnd); SetName(newname, dc); } // computer :: computer
/****************************************************************************
Keith: Make sure you Select(TRUE) cards you select, and SetMode(DONE_SELECTING) before you return.
****************************************************************************/ void computer :: SelectCardsToPass() { //
// This will hold the total number of cards that
// have been passed.
//
int cPassed = 0; int i; int nSuit; //
// First we must build our database.
//
ComputeVectors();
//
// Priority 1: Lose the Queen, King, and Ace of Spades.
//
PassCardsInVector( QuerySpadesVector() & QKA_CARDS, INDEX_SPADES, &cPassed );
//
// Priority 2: Lose the Jack, Queen, King, and Ace of Hearts.
//
PassCardsInVector( QueryHeartsVector() & JQKA_CARDS, INDEX_HEARTS, &cPassed );
//
// Priority 3: Pass any high cards not accompanied by two or
// more low cards.
//
for( i = 0 ; ( i < 4 ) && ( cPassed < 3 ) ; i++ ) { nSuit = _SuitPriority[i];
if( nSuit == INDEX_SPADES ) { continue; } if( CountBits( _CardVectors[nSuit] & LOW_CARDS ) < 2 ) { PassCardsInVector( _CardVectors[nSuit] & HIGH_CARDS, nSuit, &cPassed ); } }
//
// Priority 4: If we have the opportunity to "short suit" our
// hand, do it.
//
for( i = 0 ; ( i < 4 ) && ( cPassed < 3 ) ; i++ ) { nSuit = _SuitPriority[i]; if( CountBits( _CardVectors[nSuit] ) <= ( 3 - cPassed ) ) { PassCardsInVector( _CardVectors[nSuit], nSuit, &cPassed ); } }
//
// Priority 5: Hell, I don't know. Just find some cards to pass.
//
for( i = 0 ; ( i < 4 ) && ( cPassed < 3 ) ; i++ ) { nSuit = _SuitPriority[i]; PassCardsInVector( _CardVectors[nSuit], nSuit, &cPassed ); } SetMode( DONE_SELECTING ); } // computer :: SelectCardsToPass
/****************************************************************************
ComputeVectors
This method sets the _CardVectors[] array to reflect the current set of cards held by the computer. ****************************************************************************/ void computer :: ComputeVectors( void ) { //
// First, clear out the current vectors.
//
_CardVectors[0] = 0; _CardVectors[1] = 0; _CardVectors[2] = 0; _CardVectors[3] = 0;
//
// Now, scan the currently held cards, updating the vectors.
//
for( int i = 0 ; i < 13 ; i++ ) { if( cd[i].IsInHand() ) { AddCard( cd[i].ID() ); } }
} // computer :: ComputeVectors
/****************************************************************************
PassCardsInVector ****************************************************************************/ void computer :: PassCardsInVector( int nVector, int nSuit, int * pcPassed ) { int tmpVector; //
// Don't even try if the vector is already empty or we've already
// passed three cards.
//
if( ( nVector == 0 ) || ( *pcPassed >= 3 ) ) return;
//
// Scan the cards in our hand. Pass all of those whose suit
// matches nSuit & are in nVector. Prioritize the search
// via the _VectorPriority array.
//
for( int m = 0 ; ( m < 13 ) && ( *pcPassed < 3 ) ; m++ ) { tmpVector = nVector & _VectorPriority[m];
if( tmpVector == 0 ) continue;
for( int i = 0 ; i < 13 ; i++ ) { if( cd[i].Suit() != nSuit ) continue; if( ( tmpVector & CardToVector( cd[i].ID() ) ) == 0 ) continue; //
// We found a card. Mark it as selected.
//
cd[i].Select( TRUE );
//
// Remove the card from our local vector. Also
// remove it from the card database and update the
// number of passed cards.
//
nVector &= ~CardToVector( cd[i].ID() ); RemoveCard( cd[i].ID() ); (*pcPassed)++;
//
// Since there's always *exactly* one bit set in
// tmpVector, and we've found the card for that
// bit, we can exit this inner loop.
//
break; } //
// If the vector has become empty, we can terminate the
// outer loop.
//
if( nVector == 0 ) break; } } // computer :: PassCardsInVector
/****************************************************************************
CountBits ****************************************************************************/ int computer :: CountBits( int x ) const { x = ( ( x >> 1 ) & 0x5555 ) + ( x & 0x5555 ); x = ( ( x >> 2 ) & 0x3333 ) + ( x & 0x3333 ); x = ( ( x >> 4 ) & 0x0f0f ) + ( x & 0x0f0f ); x = ( ( x >> 8 ) & 0x00ff ) + ( x & 0x00ff );
return x; } // computer :: CountBits
|