File indexing completed on 2024-06-09 04:03:37
0001 /* 0002 * Copyright (C) 2006-2009 Stephan Kulow <coolo@kde.org> 0003 * 0004 * This program is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU General Public License as 0006 * published by the Free Software Foundation; either version 2 of 0007 * the License, or (at your option) any later version. 0008 * 0009 * This program is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 * GNU General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU General Public License 0015 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0016 */ 0017 0018 #include "mod3solver.h" 0019 0020 // own 0021 #include "../kpat_debug.h" 0022 #include "../mod3.h" 0023 0024 #define PRINT 0 0025 #define PRINT2 0 0026 0027 /* These two routines make and unmake moves. */ 0028 0029 void Mod3Solver::make_move(MOVE *m) 0030 { 0031 #if PRINT 0032 if (m->totype == O_Type) 0033 fprintf(stderr, "\nmake move %d from %d out %d (at %d)\n\n", m->card_index, m->from, m->to, m->turn_index); 0034 else 0035 fprintf(stderr, "\nmake move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index); 0036 print_layout(); 0037 #endif 0038 0039 int from, to; 0040 from = m->from; 0041 to = m->to; 0042 0043 if (from == deck) { 0044 int len = m->card_index; 0045 if (len > 8) 0046 len = 8; 0047 for (int i = 0; i < len; i++) { 0048 card_t card = *Wp[deck]; 0049 Wlen[deck]--; 0050 Wp[deck]--; 0051 0052 card = (card & PS_SUIT) + RANK(card); 0053 Wp[24 + i]++; 0054 Wlen[24 + i]++; 0055 *Wp[24 + i] = card; 0056 hashpile(24 + i); 0057 } 0058 hashpile(deck); 0059 #if PRINT 0060 print_layout(); 0061 #endif 0062 return; 0063 } 0064 0065 card_t card = *Wp[from]; 0066 Wlen[from]--; 0067 Wp[from]--; 0068 hashpile(from); 0069 0070 /* Add to pile. */ 0071 0072 Wp[to]++; 0073 *Wp[to] = card; 0074 Wlen[to]++; 0075 hashpile(to); 0076 0077 if (m->turn_index == 1) { 0078 card_t card2 = *Wp[deck]; 0079 Wlen[deck]--; 0080 Wp[deck]--; 0081 0082 hashpile(deck); 0083 /* Add to pile. */ 0084 0085 Wp[from]++; 0086 *Wp[from] = RANK(card2) + (SUIT(card2) << 4); 0087 Wlen[from]++; 0088 } 0089 0090 hashpile(from); 0091 #if PRINT 0092 print_layout(); 0093 #endif 0094 } 0095 0096 void Mod3Solver::undo_move(MOVE *m) 0097 { 0098 #if PRINT2 0099 if (m->totype == O_Type) 0100 fprintf(stderr, "\nundo move %d from %d out (at %d)\n\n", m->card_index, m->from, m->turn_index); 0101 else 0102 fprintf(stderr, "\nundo move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index); 0103 print_layout(); 0104 #endif 0105 0106 int from, to; 0107 card_t card; 0108 0109 from = m->from; 0110 to = m->to; 0111 0112 if (from == deck) { 0113 int len = m->card_index; 0114 if (len > 8) 0115 len = 8; 0116 for (int i = len; i >= 0; i--) { 0117 if (Wlen[i] == 0) { 0118 // there exists no card to move 0119 /* TODO: determine if we need to call hashpile here 0120 / or do any other work */ 0121 continue; 0122 } 0123 card_t card = *Wp[24 + i]; 0124 Wlen[deck]++; 0125 Wp[deck]++; 0126 *Wp[deck] = (1 << 7) + card; 0127 0128 Wp[24 + i]--; 0129 Wlen[24 + i]--; 0130 hashpile(24 + i); 0131 } 0132 hashpile(deck); 0133 #if PRINT2 0134 print_layout(); 0135 #endif 0136 return; 0137 } 0138 0139 if (m->turn_index == 1) { 0140 card_t card = *Wp[from]; 0141 Wp[deck]++; 0142 Wlen[deck]++; 0143 *Wp[deck] = (1 << 7) + card; 0144 Wlen[from]--; 0145 Wp[from]--; 0146 0147 hashpile(deck); 0148 } 0149 0150 card = *Wp[to]; 0151 Wp[from]++; 0152 *Wp[from] = card; 0153 Wlen[from]++; 0154 Wp[to]--; 0155 Wlen[to]--; 0156 hashpile(to); 0157 hashpile(from); 0158 0159 #if PRINT2 0160 print_layout(); 0161 #endif 0162 } 0163 0164 /* Get the possible moves from a position, and store them in Possible[]. */ 0165 0166 int Mod3Solver::get_possible_moves(int *a, int *numout) 0167 { 0168 // print_layout(); 0169 0170 card_t card; 0171 MOVE *mp; 0172 0173 *a = false; 0174 *numout = 0; 0175 0176 int n = 0; 0177 mp = Possible; 0178 0179 int first_empty_pile = -1; 0180 0181 int firstfree[4] = {-1, -1, -1, -1}; 0182 0183 for (int i = 0; i < 32; ++i) { 0184 if (!Wlen[i]) 0185 continue; 0186 card = *Wp[i]; 0187 0188 if (RANK(card) == PS_ACE) { 0189 mp->card_index = 0; 0190 mp->from = i; 0191 mp->to = aces; 0192 mp->totype = O_Type; 0193 mp->pri = 127; /* unused */ 0194 mp->turn_index = -1; 0195 if (i >= 24 && Wlen[i] == 1 && Wlen[deck]) 0196 mp->turn_index = 1; 0197 n++; 0198 mp++; 0199 Possible[0] = mp[-1]; 0200 *numout = 1; 0201 return 1; 0202 } 0203 0204 for (int j = 0; j < 32; ++j) { 0205 if (i == j) 0206 continue; 0207 0208 int current_row = i / 8; 0209 int row = j / 8; 0210 0211 if (!Wlen[j]) { 0212 if (firstfree[row] < 0) 0213 firstfree[row] = j; 0214 0215 // fprintf(stderr, "firstfree %d %d %d\n", row, firstfree[row], j); 0216 if (j != firstfree[row] && row < 4) 0217 continue; 0218 } 0219 0220 if (Wlen[j] && RANK(*Wp[j]) != row + 2 + (Wlen[j] - 1) * 3) { 0221 // fprintf( stderr, "rank %d %d\n", i, j ); 0222 continue; 0223 } 0224 0225 if (row < 3) { 0226 int min = (card & PS_SUIT) + row + 2; 0227 if (Wlen[j]) { 0228 if (RANK(*Wp[j]) > 10) 0229 continue; 0230 min = (*Wp[j] & PS_SUIT) + row + 2 + Wlen[j] * 3; 0231 } 0232 if (min != card) 0233 continue; 0234 0235 // and now we figure if this makes sense at all 0236 if (current_row == row) { 0237 // if the only difference between i and j is the card, 0238 // then it's not worth it 0239 if (Wlen[i] == Wlen[j] + 1) 0240 continue; 0241 } 0242 0243 if (Wlen[j]) { 0244 mp->pri = qMin(119, 12 + 20 * Wlen[j] + current_row * 2 + RANK(*Wp[j]) * 5); 0245 } else { 0246 mp->pri = 119; // TODO: Find out if this is really correct. We can certainly not touch Wp[j], but is this the correct mp->pri value? 0247 } 0248 0249 mp->turn_index = -1; 0250 if (i >= 24 && Wlen[i] == 1 && Wlen[deck]) 0251 mp->turn_index = 1; 0252 0253 } else { 0254 if (Wlen[j] || (Wlen[i] > 1 && current_row != 3)) 0255 continue; 0256 0257 if (current_row == 3 && Wlen[i] == 1) 0258 continue; 0259 0260 if (RANK(card) == current_row + 2 && current_row != 3) 0261 continue; 0262 0263 if (first_empty_pile != -1 && first_empty_pile != j) 0264 continue; 0265 0266 if (first_empty_pile == -1) 0267 first_empty_pile = j; 0268 0269 mp->pri = 0; 0270 mp->turn_index = -1; 0271 } 0272 0273 mp->card_index = 0; 0274 mp->from = i; 0275 mp->to = j; 0276 mp->totype = W_Type; 0277 n++; 0278 mp++; 0279 } 0280 } 0281 0282 if (Wlen[deck]) { 0283 // move 0284 mp->card_index = 0; 0285 mp->from = deck; 0286 mp->to = 0; 0287 mp->totype = W_Type; 0288 mp->pri = -77; // last resort 0289 mp->turn_index = -1; 0290 mp->card_index = Wlen[deck]; 0291 n++; 0292 mp++; 0293 } 0294 0295 return n; 0296 } 0297 0298 bool Mod3Solver::isWon() 0299 { 0300 return getOuts() == 52 * 2; 0301 } 0302 0303 int Mod3Solver::getOuts() 0304 { 0305 int ret = Wlen[aces]; 0306 for (int i = 0; i < 8 * 3; i++) 0307 ret += Wlen[i]; 0308 return ret; 0309 } 0310 0311 Mod3Solver::Mod3Solver(const Mod3 *dealer) 0312 : Solver() 0313 { 0314 deal = dealer; 0315 } 0316 0317 void Mod3Solver::translate_layout() 0318 { 0319 /* Read the workspace. */ 0320 int w = 0; 0321 for (int row = 0; row < 4; ++row) { 0322 for (int col = 0; col < 8; ++col) { 0323 int i = translate_pile(deal->stack[row][col], W[w], 52); 0324 Wp[w] = &W[w][i - 1]; 0325 Wlen[w] = i; 0326 w++; 0327 } 0328 } 0329 0330 aces = w; 0331 int i = translate_pile(deal->aces, W[w], 52); 0332 Wp[w] = &W[w][i - 1]; 0333 Wlen[w] = i; 0334 0335 deck = ++w; 0336 0337 i = translate_pile(deal->talon, W[w], 104); 0338 Wp[w] = &W[w][i - 1]; 0339 Wlen[w] = i; 0340 } 0341 0342 MoveHint Mod3Solver::translateMove(const MOVE &m) 0343 { 0344 if (m.from == deck) 0345 return MoveHint(); 0346 0347 PatPile *frompile = deal->stack[m.from / 8][m.from % 8]; 0348 KCard *card = frompile->topCard(); 0349 0350 if (m.to == aces) { 0351 return MoveHint(card, deal->aces, m.pri); 0352 } else { 0353 return MoveHint(card, deal->stack[m.to / 8][m.to % 8], m.pri); 0354 } 0355 } 0356 0357 void Mod3Solver::print_layout() 0358 { 0359 int i, w = 0, o; 0360 0361 fprintf(stderr, "print-layout-begin\n"); 0362 for (int row = 0; row < 3; ++row) { 0363 fprintf(stderr, "Row%d: ", row); 0364 for (int col = 0; col < 8; col++) { 0365 if (Wlen[w]) 0366 printcard(*Wp[w], stderr); 0367 else 0368 fprintf(stderr, " "); 0369 fprintf(stderr, "(%02d) ", w); 0370 w++; 0371 } 0372 fputc('\n', stderr); 0373 } 0374 0375 for (int col = 0; col < 8; col++) { 0376 fprintf(stderr, "Play%02d: ", w); 0377 for (i = 0; i < Wlen[w]; ++i) { 0378 printcard(W[w][i], stderr); 0379 } 0380 fputc('\n', stderr); 0381 w++; 0382 } 0383 0384 fprintf(stderr, "Aces: "); 0385 for (o = 0; o < Wlen[aces]; ++o) { 0386 printcard(W[aces][o], stderr); 0387 } 0388 fputc('\n', stderr); 0389 0390 fprintf(stderr, "Deck: "); 0391 for (o = 0; o < Wlen[deck]; ++o) { 0392 printcard(W[deck][o], stderr); 0393 } 0394 0395 fprintf(stderr, "\nprint-layout-end\n"); 0396 }