1 /*
2  * (c) Copyright 1997, Qun Zhang.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software
5  * and its documentation for any purpose is hereby granted without fee,
6  * provided that the above copyright notice appear in all copies and
7  * that both that copyright notice and this permission notice appear in
8  * supporting documentation, and that the name of Qun Zhang not be used
9  * in advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  Qun Zhang make no
11  * representations about the suitability of this software for any purpose.
12  * It is provided "as is" without express or implied warranty.
13  *
14  * THE ABOVE-NAMED DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE ABOVE-NAMED BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
18  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  *
22  */
23 
24 #include "Card.h"
25 #include "Hands.h"
26 
27 
28 const int	 Hands::Ratio[11] = {0, 1, 1, 2, 3, 4, 5, 7, 20, 50, 100 };
29 const char * Hands::HandNames[11] = { "          ",
30                             "          ",
31                             " One Pair ",
32                             " Two Pairs",
33                             " 3 of a Kind",
34                             " Straight ",
35                             " Flush ",
36                             " Full House",
37                             " 4 of a Kind",
38                             " Straight Flush ",
39                             " Royal Flush " };
40 
41 
Hands()42 Hands::Hands() : _score(0), _hand(EX)
43 {
44       for(int i=0; i < 5; i++)
45 			_cards[i] = ( Card *)0;
46 		_next = 0;
47 }
48 
HandValue() const49 enum Hands::Hand Hands::HandValue() const
50 {
51 	return _hand;
52 }
53 
NumOfCards() const54 int Hands::NumOfCards() const
55 {
56 	return (_cards[0] == (Card*) 0) ? 0 : 5;
57 }
58 
Score() const59 long Hands::Score() const
60 {
61 	if(_score == 0)
62 		SortCards();
63 #ifdef DEBUG
64    cout << "Score: " <<  _score <<endl;
65 #endif
66 	return _score;
67 }
68 
HandName() const69 const char* const Hands::HandName() const
70 {
71 	return Hands::HandNames[_hand];
72 }
73 
PayRate() const74 int Hands::PayRate() const
75 {
76 	return Ratio[ (int)_hand ];
77 }
78 
AddCard(Card * card)79 void Hands::AddCard(Card *card)
80 {
81 	_cards[_next++] = card;
82 }
83 
NewGame()84 void Hands::NewGame()
85 {
86    _score =0;
87 	_hand = EX;
88    _next = 0;
89 //   for(int i=0; i < 5; i++)
90 //      _cards[i] = ( Card *)0;
91 
92 }
93 
Cards() const94 Card** Hands::Cards() const
95 {
96 	return (Card**)_cards;
97 }
98 
SortCards() const99 void Hands::SortCards() const
100 {
101 	char ranks[6];
102 
103    if(!_next) return;
104 
105    for(int i=0; i<5; i++)
106 		ranks[i] = _cards[i]->Rank();
107 
108 	for(int j=0; j < 4; j++) // sorting based on rank
109 		for(int i=0; i < 4-j; i++)
110 		{
111 			if( ranks[i] < ranks[i+1] )
112 			{
113 				ranks[6] = ranks[i];
114 				ranks[i] = ranks[i+1];
115 				ranks[i+1] = ranks[6];
116 			}
117 		}
118 	ranks[6] = '\0';
119 
120    // first looking to 1p, 2p, 3k, fh and 4k
121 
122 	char r = ranks[0];
123 	char board[4];
124 	for(int i =0; i<4; i++) board[i] = '\0';
125 
126    int s=1;
127    for (int i=1; i< 6; i++)
128    {
129 		if( r == ranks[i] ) s++;
130 		else{
131 			switch(s){
132 			case 2:
133 			{
134 				int t = (board[0] == '\0') ? 0 : 1;
135 				board[t] = r;
136 			}
137 				break;
138 			case 3:
139 				board[2] = r;
140 				break;
141 			case 4:
142 				board[3] = r;
143 				break;
144 			}
145 			s = 1;
146 			r = ranks[i];
147 		}
148 	}
149 
150 	((Hands*)this) ->_hand = NP;
151 
152    if( board[0] || board[1] || board[2] || board[3] )
153 	{
154 		if(board[3])
155 			((Hands*)this) ->_hand = K4;
156 		else if(board[2])
157 			((Hands*)this) ->_hand = (board[0]) ? FH : K3;
158 		else
159 			((Hands*)this) ->_hand = (board[1]) ? P2 : P1;
160 
161 		((Hands*)this) ->ReArrange(ranks, 5, board, _hand);
162    }
163 	else{
164 		if(ranks[0] == (char) '\14') ranks[5] = '\1';
165 		int i;
166 		for(i =0; i < 4; i++)
167 			if(_cards[i]->Suit() != _cards[i+1]->Suit())
168 			{
169 				i = 8;
170 				break;
171 			}
172 		if( i != 8 ) ((Hands*)this) ->_hand = FL;
173 		for( i = 0; i<4; i++)
174 			if(ranks[i] != ranks[i+1] + 1)
175 			{
176 				i=8;
177 				break;
178 			}
179 		if(i==8 && ranks[i] == '\14') // for ACE as the first one
180 			for(i=1; i<4; i++)
181 				if(ranks[i] != ranks[i+1] + 1)
182 				{
183 					i=8; break;
184 				}
185 		if( i != 8 )
186 		{
187 			((Hands*)this) ->_hand = ( _hand == FL ) ? SF : ST;
188 			if(ranks[4] == ranks[5]+1)
189 				for(ranks[5] = '\14',i=0; i<5; i++)
190 					ranks[i] = ranks[i+1];
191 			if(ranks[0] == '\14'&& _hand == SF) ((Hands*)this) ->_hand = RF;
192 		}
193 	}
194 
195 // calculate the score for a hand
196 
197 	((Hands*)this) ->_score = ((int)_hand -1) * 7529536;
198 	((Hands*)this) ->_score+=((((ranks[0]*14)+ranks[1])*14+ranks[2])*14+ranks[3])*14+ranks[4];
199 
200 // rearrange cards order
201 
202 	Card* tmpcards[5];
203    for(int i = 0; i < 5; i++) tmpcards[i] = _cards[i];
204 	for(int i = 0; i < 5; i++)
205 		for(int j=0; j<5; j++)
206 			if(tmpcards[j] && ranks[i]==tmpcards[j]->Rank())
207 			{
208 				((Hands*)this) ->_cards[i] = tmpcards[j];
209 				tmpcards[j] = (Card *)0;
210 				break;
211 			}
212 
213 #ifdef DEBUG
214 		for(int i = 0; i < 5; i++)
215 		  cout << _cards[i]->Suit() << (int) _cards[i]->Rank() << " ";
216       cout << endl;
217 #endif
218 
219 }
220 
ReArrange(char * ranks,int nel,char * board,Hand score)221 void    Hands::ReArrange(char* ranks , int nel,char* board, Hand score)
222 {
223 	int i, j=0 , k = 0;
224 	char tmprank[10];
225    for( i = 0; i < nel; i++)  // copy all the cards to the tmprank
226 		tmprank[i] = *(ranks+i);
227 	tmprank[nel] = '\0';
228 
229 	switch(score) {
230 	case  P1:
231 		for( k=2,i = 0; i < nel; i++)
232 			if(tmprank[i] == *board) *(ranks+j) = tmprank[i], j++;
233 		   else *(ranks+k) = tmprank[i], k++;
234 		break;
235 	case  P2:
236 		for( k=2,i = 0; i < nel; i++)
237 			if(tmprank[i] == *board) *(ranks+j) = tmprank[i], j++;
238 		   else if(tmprank[i] == *(board+1)) *(ranks+k) = tmprank[i], k++;
239 			else *(ranks+4) =  tmprank[i];
240 		break;
241 	case  K3:
242 	case  FH:
243 		for( k=3,i = 0; i < nel; i++)
244 			if(tmprank[i] == *(board+2)) *(ranks+j) = tmprank[i], j++;
245 		   else *(ranks+k) = tmprank[i], k++;
246 		break;
247 	case  K4:
248 		for(i = 0; i < nel; i++)
249 			if(tmprank[i] !=*(board+3) )
250 			{
251 		     *(ranks+i) = *(board+3);
252 			  *(ranks+4) = tmprank[i];
253 			  break;
254 			}
255    }
256 }
257 
258