File indexing completed on 2024-05-26 04:08:30
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 "grandfsolver.h" 0019 0020 // own 0021 #include "../grandf.h" 0022 #include "../kpat_debug.h" 0023 0024 #define PRINT 0 0025 0026 /* These two routines make and unmake moves. */ 0027 0028 void GrandfSolver::make_move(MOVE *m) 0029 { 0030 #if PRINT 0031 if (m->totype == O_Type) 0032 fprintf(stderr, "\nmake move %d from %d out (at %d)\n\n", m->card_index, m->from, m->turn_index); 0033 else if (m->from == offs) 0034 fprintf(stderr, "\nmake redeal\n\n"); 0035 else 0036 fprintf(stderr, "\nmake move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index); 0037 print_layout(); 0038 #else 0039 // print_layout(); 0040 #endif 0041 0042 card_t card = NONE; 0043 0044 auto from = m->from; 0045 auto to = m->to; 0046 0047 if (from == offs) { 0048 // redeal 0049 m_redeal++; 0050 0051 card_t deck[52]; 0052 int len = 0; 0053 0054 for (int i = m_redeal * 7; i < m_redeal * 7 + 7; ++i) { 0055 Wlen[i] = 0; 0056 Wp[i] = &W[i][-1]; 0057 } 0058 0059 for (int pos = 6; pos >= 0; --pos) { 0060 int oldpile = (m_redeal - 1) * 7 + pos; 0061 for (int l = 0; l < Wlen[oldpile]; ++l) { 0062 card_t card = W[oldpile][l]; 0063 deck[len++] = (SUIT(card) << 4) + RANK(card); 0064 } 0065 } 0066 0067 int start = 0; 0068 int stop = 7 - 1; 0069 int dir = 1; 0070 0071 for (int round = 0; round < 7; ++round) { 0072 int i = start; 0073 do { 0074 card_t card = NONE; 0075 if (len > 0) { 0076 card = deck[--len]; 0077 int currentpile = m_redeal * 7 + i; 0078 Wp[currentpile]++; 0079 *Wp[currentpile] = card; 0080 if (i != start) 0081 *Wp[currentpile] += (1 << 7); 0082 Wlen[currentpile]++; 0083 } 0084 i += dir; 0085 } while (i != stop + dir); 0086 int t = start; 0087 start = stop; 0088 stop = t + dir; 0089 dir = -dir; 0090 } 0091 0092 int j = 0; 0093 while (len > 0) { 0094 card_t card = deck[--len]; 0095 int currentpile = m_redeal * 7 + (j + 1); 0096 Wp[currentpile]++; 0097 *Wp[currentpile] = card; 0098 Wlen[currentpile]++; 0099 j = (j + 1) % 6; 0100 } 0101 0102 for (int round = 0; round < 7; ++round) { 0103 int currentpile = m_redeal * 7 + round; 0104 if (Wlen[currentpile]) { 0105 card_t card = W[currentpile][Wlen[currentpile] - 1]; 0106 W[currentpile][Wlen[currentpile] - 1] = (SUIT(card) << 4) + RANK(card); 0107 } 0108 hashpile(currentpile); 0109 hashpile(currentpile - 7); 0110 } 0111 0112 #if PRINT 0113 print_layout(); 0114 #endif 0115 return; 0116 } 0117 0118 for (int l = m->card_index; l >= 0; --l) { 0119 card = W[from][Wlen[from] - l - 1]; 0120 Wp[from]--; 0121 if (m->totype != O_Type) { 0122 Wp[to]++; 0123 *Wp[to] = card; 0124 Wlen[to]++; 0125 } 0126 } 0127 Wlen[from] -= m->card_index + 1; 0128 0129 if (m->turn_index == 0) { 0130 if (DOWN(card)) 0131 card = (SUIT(card) << 4) + RANK(card); 0132 else 0133 card += (1 << 7); 0134 W[to][Wlen[to] - m->card_index - 1] = card; 0135 } else if (m->turn_index != -1) { 0136 card_t card2 = *Wp[from]; 0137 if (DOWN(card2)) 0138 card2 = (SUIT(card2) << 4) + RANK(card2); 0139 *Wp[from] = card2; 0140 } 0141 0142 hashpile(from); 0143 /* Add to pile. */ 0144 0145 if (m->totype == O_Type) { 0146 if (DOWN(W[offs][to])) 0147 W[offs][to] = (SUIT(card) << 4) + PS_ACE; 0148 else 0149 W[offs][to]++; 0150 Q_ASSERT(m->card_index == 0); 0151 hashpile(offs); 0152 } else { 0153 hashpile(to); 0154 } 0155 #if PRINT 0156 print_layout(); 0157 #endif 0158 } 0159 0160 void GrandfSolver::undo_move(MOVE *m) 0161 { 0162 #if PRINT 0163 if (m->totype == O_Type) 0164 fprintf(stderr, "\nundo move %d from %d out (at %d)\n\n", m->card_index, m->from, m->turn_index); 0165 else if (m->from == offs) 0166 fprintf(stderr, "\nundo redeal\n\n"); 0167 else 0168 fprintf(stderr, "\nundo move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index); 0169 print_layout(); 0170 0171 #endif 0172 int from, to; 0173 card_t card; 0174 0175 from = m->from; 0176 to = m->to; 0177 0178 if (from == offs) { 0179 /* just erase */ 0180 0181 for (int i = 0; i < 7; ++i) { 0182 int pile = m_redeal * 7 + i; 0183 Wlen[pile] = 0; 0184 Wp[pile] = &W[pile][0]; 0185 hashpile(pile); 0186 } 0187 m_redeal--; 0188 #if PRINT 0189 print_layout(); 0190 #endif 0191 return; 0192 } 0193 0194 /* Add to 'from' pile. */ 0195 if (m->turn_index > 0) { 0196 card_t card2 = *Wp[from]; 0197 if (!DOWN(card2)) 0198 card2 = (SUIT(card2) << 4) + RANK(card2) + (1 << 7); 0199 *Wp[from] = card2; 0200 } 0201 0202 if (m->totype == O_Type) { 0203 card = W[offs][Osuit[to]]; 0204 W[offs][to]--; 0205 Wp[from]++; 0206 *Wp[from] = card; 0207 Wlen[from]++; 0208 } else { 0209 for (int l = m->card_index; l >= 0; --l) { 0210 card = W[to][Wlen[to] - l - 1]; 0211 Wp[from]++; 0212 *Wp[from] = card; 0213 Wlen[from]++; 0214 Wp[to]--; 0215 } 0216 Wlen[to] -= m->card_index + 1; 0217 hashpile(to); 0218 } 0219 0220 if (m->turn_index == 0) { 0221 card_t card = *Wp[from]; 0222 if (DOWN(card)) 0223 card = (SUIT(card) << 4) + RANK(card); 0224 else 0225 card += (1 << 7); 0226 *Wp[from] = card; 0227 } 0228 0229 hashpile(from); 0230 #if PRINT 0231 print_layout(); 0232 #endif 0233 } 0234 0235 /* Get the possible moves from a position, and store them in Possible[]. */ 0236 0237 int GrandfSolver::get_possible_moves(int *a, int *numout) 0238 { 0239 int w, o, empty; 0240 card_t card; 0241 MOVE *mp; 0242 0243 /* Check for moves from W to O. */ 0244 0245 int n = 0; 0246 mp = Possible; 0247 0248 for (w = m_redeal * 7 + 0; w < m_redeal * 7 + 7; ++w) { 0249 if (Wlen[w] > 0) { 0250 card = *Wp[w]; 0251 o = SUIT(card); 0252 empty = DOWN(W[offs][o]); 0253 if ((empty && (RANK(card) == PS_ACE)) || (!empty && (RANK(card) == RANK(W[offs][o]) + 1))) { 0254 mp->card_index = 0; 0255 mp->from = w; 0256 mp->to = o; 0257 mp->totype = O_Type; 0258 mp->pri = 127; /* unused */ 0259 mp->turn_index = -1; 0260 if (Wlen[w] > 1 && DOWN(W[w][Wlen[w] - 2])) 0261 mp->turn_index = 1; 0262 n++; 0263 mp++; 0264 0265 *a = true; 0266 return n; 0267 } 0268 } 0269 } 0270 0271 /* No more automoves, but remember if there were any moves out. */ 0272 0273 *a = false; 0274 *numout = n; 0275 0276 for (int i = m_redeal * 7 + 0; i < m_redeal * 7 + 7; ++i) { 0277 int len = Wlen[i]; 0278 for (int l = 0; l < len; ++l) { 0279 card_t card = W[i][Wlen[i] - 1 - l]; 0280 if (DOWN(card)) 0281 break; 0282 0283 for (int j = m_redeal * 7 + 0; j < m_redeal * 7 + 7; ++j) { 0284 if (i == j) 0285 continue; 0286 0287 int allowed = 0; 0288 0289 if (Wlen[j] > 0 && RANK(card) == RANK(*Wp[j]) - 1 && SUIT(card) == SUIT(*Wp[j])) { 0290 allowed = 1; 0291 } 0292 if (RANK(card) == PS_KING && Wlen[j] == 0) { 0293 if (l != Wlen[i] - 1) 0294 allowed = 4; 0295 else if (m_redeal < 2) 0296 allowed = 1; 0297 } 0298 // TODO: there is no point in moving if we're not opening anything 0299 // e.g. if both i and j have perfect runs below the cards 0300 #if 0 0301 fprintf( stderr, "%d %d %d\n", i, l, j ); 0302 printcard( card, stderr ); 0303 printcard( *Wp[j], stderr ); 0304 fprintf( stderr, " allowed %d\n",allowed ); 0305 #endif 0306 if (allowed) { 0307 mp->card_index = l; 0308 mp->from = i; 0309 mp->to = j; 0310 mp->totype = W_Type; 0311 mp->turn_index = -1; 0312 if (Wlen[i] > l + 1 && DOWN(W[i][Wlen[i] - l - 2])) 0313 mp->turn_index = 1; 0314 if (mp->turn_index > 0 || Wlen[i] == l + 1) 0315 mp->pri = 30; 0316 else 0317 mp->pri = 1; 0318 /*if (mp->pri == 30 && mp->from == 9 && mp->to == 10) 0319 abort();*/ 0320 n++; 0321 mp++; 0322 } 0323 } 0324 } 0325 } 0326 0327 if (m_redeal < 2) { 0328 mp->card_index = 0; 0329 mp->from = offs; 0330 mp->to = 0; // unused 0331 mp->totype = W_Type; 0332 mp->turn_index = -1; 0333 mp->pri = -1; 0334 n++; 0335 mp++; 0336 } 0337 0338 return n; 0339 } 0340 0341 unsigned int GrandfSolver::getClusterNumber() 0342 { 0343 return m_redeal; 0344 } 0345 0346 void GrandfSolver::unpack_cluster(unsigned int k) 0347 { 0348 m_redeal = k; 0349 } 0350 0351 bool GrandfSolver::isWon() 0352 { 0353 // maybe won? 0354 for (int o = 0; o < 4; ++o) { 0355 if (RANK(W[offs][o]) != PS_KING) { 0356 return false; 0357 } 0358 } 0359 0360 return true; 0361 } 0362 0363 int GrandfSolver::getOuts() 0364 { 0365 int outs = 0; 0366 for (int i = 0; i < 4; ++i) 0367 if (!DOWN(W[offs][i])) 0368 outs += RANK(W[offs][i]); 0369 return outs; 0370 } 0371 0372 GrandfSolver::GrandfSolver(const Grandf *dealer) 0373 : Solver() 0374 { 0375 Osuit[0] = PS_DIAMOND; 0376 Osuit[1] = PS_CLUB; 0377 Osuit[2] = PS_HEART; 0378 Osuit[3] = PS_SPADE; 0379 0380 offs = 7 * 3; 0381 deal = dealer; 0382 m_redeal = -1; 0383 } 0384 0385 void GrandfSolver::translate_layout() 0386 { 0387 /* Read the workspace. */ 0388 0389 m_redeal = deal->numberOfDeals - 1; 0390 0391 for (int w = 0; w < 7 * 3; ++w) 0392 Wlen[w] = 0; 0393 0394 for (int w = 0; w < 7; ++w) { 0395 int i = translate_pile(deal->store[w], W[w + m_redeal * 7], 52); 0396 Wp[w + m_redeal * 7] = &W[w + m_redeal * 7][i - 1]; 0397 Wlen[w + m_redeal * 7] = i; 0398 } 0399 0400 Wlen[offs] = 4; 0401 0402 for (int i = 0; i < 4; ++i) 0403 W[offs][i] = NONE; 0404 0405 for (int i = 0; i < 4; ++i) { 0406 KCard *c = deal->target[i]->topCard(); 0407 if (c) 0408 W[offs][translateSuit(c->suit()) >> 4] = translateSuit(c->suit()) + c->rank(); 0409 } 0410 for (int i = 0; i < 4; ++i) 0411 if (W[offs][i] == NONE) 0412 W[offs][i] = (i << 4) + PS_ACE + (1 << 7); 0413 0414 Wp[offs] = &W[offs][3]; 0415 } 0416 0417 MoveHint GrandfSolver::translateMove(const MOVE &m) 0418 { 0419 if (m.from == offs) 0420 return MoveHint(); 0421 0422 PatPile *frompile = nullptr; 0423 frompile = deal->store[m.from % 7]; 0424 0425 KCard *card = frompile->at(frompile->count() - m.card_index - 1); 0426 0427 if (m.totype == O_Type) { 0428 PatPile *target = nullptr; 0429 PatPile *empty = nullptr; 0430 for (int i = 0; i < 4; ++i) { 0431 KCard *c = deal->target[i]->topCard(); 0432 if (c) { 0433 if (c->suit() == card->suit()) { 0434 target = deal->target[i]; 0435 break; 0436 } 0437 } else if (!empty) 0438 empty = deal->target[i]; 0439 } 0440 if (!target) 0441 target = empty; 0442 return MoveHint(card, target, m.pri); 0443 } else { 0444 return MoveHint(card, deal->store[m.to % 7], m.pri); 0445 } 0446 } 0447 0448 void GrandfSolver::print_layout() 0449 { 0450 int i, w, o; 0451 0452 fprintf(stderr, "print-layout-begin\n"); 0453 for (w = 0; w < 21; ++w) { 0454 fprintf(stderr, "Play%d-%d(%d): ", w / 7, w % 7, w); 0455 for (i = 0; i < Wlen[w]; ++i) { 0456 printcard(W[w][i], stderr); 0457 } 0458 fputc('\n', stderr); 0459 } 0460 fprintf(stderr, "Off: "); 0461 for (o = 0; o < 4; ++o) { 0462 if (!DOWN(W[offs][o])) 0463 printcard(RANK(W[offs][o]) + Osuit[o], stderr); 0464 } 0465 fprintf(stderr, "\nRedeals: %d", m_redeal); 0466 fprintf(stderr, "\nprint-layout-end\n"); 0467 }