bool is_flush(int* hand) { for (int i =1; i< 5; i++) if (SUIT(hand[i]) != SUIT(hand[0])) return false; return true; }
void YukonSolver::make_move(MOVE *m) { #if PRINT if ( m->totype == O_Type ) fprintf( stderr, "\nmake move %d from %d out (at %d)\n\n", m->card_index, m->from, m->turn_index ); else fprintf( stderr, "\nmake move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index ); print_layout(); #else //print_layout(); #endif int from, to; card_t card = NONE; from = m->from; to = m->to; for ( int l = m->card_index; l >= 0; l-- ) { card = W[from][Wlen[from]-l-1]; Wp[from]--; if ( m->totype != O_Type ) { Wp[to]++; *Wp[to] = card; Wlen[to]++; } } Wlen[from] -= m->card_index + 1; if ( m->turn_index == 0 ) { if ( DOWN( card ) ) card = ( SUIT( card ) << 4 ) + RANK( card ); else card += ( 1 << 7 ); W[to][Wlen[to]-m->card_index-1] = card; } else if ( m->turn_index != -1 ) { card_t card2 = *Wp[from]; if ( DOWN( card2 ) ) card2 = ( SUIT( card2 ) << 4 ) + RANK( card2 ); *Wp[from] = card2; } hashpile(from); /* Add to pile. */ if (m->totype == O_Type) { O[to]++; Q_ASSERT( m->card_index == 0 ); } else { hashpile(to); } #if PRINT print_layout(); #endif }
void YukonSolver::undo_move(MOVE *m) { #if PRINT if ( m->totype == O_Type ) fprintf( stderr, "\nundo move %d from %d out (at %d)\n\n", m->card_index, m->from, m->turn_index ); else fprintf( stderr, "\nundo move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index ); print_layout(); #endif int from, to; card_t card; from = m->from; to = m->to; /* Add to 'from' pile. */ if ( m->turn_index > 0 ) { card_t card2 = *Wp[from]; if ( !DOWN( card2 ) ) card2 = ( SUIT( card2 ) << 4 ) + RANK( card2 ) + ( 1 << 7 ); *Wp[from] = card2; } if (m->totype == O_Type) { card = O[to] + Osuit[to]; O[to]--; Wp[from]++; *Wp[from] = card; Wlen[from]++; } else { for ( int l = m->card_index; l >= 0; l-- ) { card = W[to][Wlen[to]-l-1]; Wp[from]++; *Wp[from] = card; Wlen[from]++; *Wp[to]--; } Wlen[to] -= m->card_index + 1; hashpile(to); } if ( m->turn_index == 0 ) { card_t card = *Wp[from]; if ( DOWN( card ) ) card = ( SUIT( card ) << 4 ) + RANK( card ); else card += ( 1 << 7 ); *Wp[from] = card; } hashpile(from); #if PRINT print_layout(); #endif }
static inline int compareCards (int c0, int c1) { int t0 = SUIT(c0), t1 = SUIT(c1); int r = t1-t0; if (!r) { t0 = FACE(c0), t1 = FACE(c1); r = t0-t1; } return r; }
bool is_royal(int* hand) { for (int i=0; i<5; i++) { if (hand[i] > 20) return false; // contains card lower than 10 if (SUIT(hand[i]) != SUIT(hand[0])) return false; // contains mismatched suits } return true; }
void SimonSolver::make_move(MOVE *m) { #if PRINT //qDebug() << "\n\nmake_move\n"; if ( m->totype == O_Type ) fprintf( stderr, "move %d from %d out (at %d) Prio: %d\n\n", m->card_index, m->from, m->turn_index, m->pri ); else fprintf( stderr, "move %d from %d to %d (%d) Prio: %d\n\n", m->card_index, m->from, m->to, m->turn_index, m->pri ); print_layout(); #else //print_layout(); #endif int from, to; card_t card = NONE; from = m->from; to = m->to; if (m->totype == O_Type) { O[to] = SUIT( *Wp[from] ); Wlen[from] -= 13; Wp[from] -= 13; hashpile( from ); if ( Wlen[from] && DOWN( *Wp[from] ) ) { *Wp[from] = ( SUIT( *Wp[from] ) << 4 ) + RANK( *Wp[from] ); } #if PRINT print_layout(); #endif return; } for ( int l = m->card_index; l >= 0; --l ) { card = W[from][Wlen[from]-l-1]; Wp[from]--; if ( m->totype != O_Type ) { Wp[to]++; *Wp[to] = card; Wlen[to]++; } } Wlen[from] -= m->card_index + 1; hashpile(from); hashpile(to); #if PRINT print_layout(); #endif }
static GCC_INLINE void fc_pro_get_board(long gamenumber, Position * pos) { int i, j; /* generic counters */ int wLeft = 52; /* cards left to be chosen in shuffle */ CARD deck[52]; /* deck of 52 unique cards */ int col; CARD card, suit; memset(pos, '\0', sizeof(*pos)); /* shuffle cards */ for (i = 0; i < 52; i++) /* put unique card in each deck loc. */ { deck[i] = i; } for (i = 0; i < 52; i++) { j = microsoft_rand_rand(&gamenumber) % wLeft; col = (i%8); card = deck[j]; suit = SUIT(card); pos->tableau[col].cards[pos->tableau[col].count++] = (Card)((VALUE(card)+1) + (((suit == 3) ? suit : ((suit+1)%3))<<4)) ; deck[j] = deck[--wLeft]; } }
int has_suit(int *cl, int b, int e, int s) { int i, r = 0; for (i = b; i <= e; i++) if (SUIT(cl[i]) == s) r++; return r; }
inline bool higher( const card_t &c1, const card_t &c2) { // Sanity check. if (c1 == c2) return false; // Must be same suit. if ( SUIT( c1 ) != SUIT( c2 ) ) return false; // Aces form a special case. if (RANK( c2 ) == PS_ACE) return true; if (RANK( c1 ) == PS_ACE) return false; return (RANK( c1 ) < RANK( c2 )); }
void SimonSolver::undo_move(MOVE *m) { #if PRINT //qDebug() << "\n\nundo_move\n"; if ( m->totype == O_Type ) fprintf( stderr, "move %d from %d out (at %d)\n\n", m->card_index, m->from, m->turn_index ); else fprintf( stderr, "move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index ); print_layout(); #endif int from, to; card_t card; from = m->from; to = m->to; if (m->totype == O_Type) { for ( int j = PS_KING; j >= PS_ACE; --j ) { Wp[from]++; *Wp[from] = O[to] + j; Wlen[from]++; } O[to] = -1; hashpile( from ); #if PRINT print_layout(); #endif return; } /* Add to 'from' pile. */ if ( m->turn_index > 0 ) { card_t card2 = *Wp[from]; if ( !DOWN( card2 ) ) card2 = ( SUIT( card2 ) << 4 ) + RANK( card2 ) + ( 1 << 7 ); *Wp[from] = card2; } for ( int l = m->card_index; l >= 0; --l ) { card = W[to][Wlen[to]-l-1]; Wp[from]++; *Wp[from] = card; Wlen[from]++; Wp[to]--; } Wlen[to] -= m->card_index + 1; hashpile(to); hashpile(from); #if PRINT print_layout(); #endif }
string refresh(int *cl, int b, int e) { string output = ""; int i, ls, ns; if (b < 0 || e < 0) return output; if (cl[b] < 0 || cl[e] > 51) return output; output = sprintf("%18s%s:", "", suit_str[ls = ns = SUIT(cl[b])]); for (i = b; i <= e; i++) { ns = SUIT(cl[i]); if (ls == ns) output += rank_str[RANK(cl[i])] + " "; else { output = sprintf("%s\n%18s%s:", output, "", suit_str[ls = ns]); output += rank_str[RANK(cl[i])] + " "; } } return output + "\n"; }
char * card_to_string(char * s, CARD card, int not_append_ws, int print_ts) { int suit = SUIT(card); int v = VALUE(card)+1; if (v == 1) { strcpy(s, "A"); } else if (v < 10) { sprintf(s, "%i", v); } else if (v == 10) { if (print_ts) { strcpy(s, "T"); } else { strcpy(s, "10"); } } else { strcpy(s, (v == 11)?"J":((v == 12)?"Q":"K")); } switch (suit) { case CLUB: strcat(s, "C"); break; case DIAMOND: strcat(s, "D"); break; case HEART: strcat(s, "H"); break; case SPADE: strcat(s, "S"); break; } if (!not_append_ws) { strcat(s, " "); } return s; }
void IdiotSolver::make_move(MOVE *m) { #if PRINT if ( m->totype == O_Type ) fprintf( stderr, "\nmake move %d from %d out (at %d)\n\n", m->card_index, m->from, m->turn_index ); else fprintf( stderr, "\nmake move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index ); print_layout(); #else //print_layout(); #endif int from, to; card_t card = NONE; from = m->from; to = m->to; if ( from == 4 ) { Q_ASSERT( Wlen[from] >= 4 ); for ( int i = 0; i < 4; ++i ) { Wp[i]++; card = *Wp[from]; *Wp[i] = ( SUIT( card ) << 4 ) + RANK( card ); Wp[from]--; Wlen[from]--; Wlen[i]++; hashpile( i ); } hashpile( from ); } else { card = *Wp[from]; Wp[from]--; Wlen[from]--; *Wp[to]++; *Wp[to] = card; Wlen[to]++; hashpile( to ); hashpile(from); } #if PRINT print_layout(); #endif }
void GolfSolver::make_move(MOVE *m) { #if PRINT if ( m->totype == O_Type ) fprintf( stderr, "\nmake move %d from %d out (at %d)\n\n", m->card_index, m->from, m->turn_index ); else fprintf( stderr, "\nmake move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index ); print_layout(); #else //print_layout(); #endif int from = m->from; int to = m->to; Q_ASSERT( to == 7 ); Q_ASSERT( from != 7 ); // move to pile if ( from == 8 && to == 7 ) { card_t card = *Wp[8]; Wp[8]--; Wlen[8]--; card = ( SUIT( card ) << 4 ) + RANK( card ); Wp[7]++; *Wp[7] = card; Wlen[7]++; hashpile( 7 ); hashpile( 8 ); #if PRINT print_layout(); #endif return; } card_t card = *Wp[from]; Wp[from]--; Wlen[from]--; Wp[to]++; *Wp[to] = card; Wlen[to]++; hashpile(from); hashpile(to); #if PRINT print_layout(); #endif }
string card_cmp4(mapping cl, int s) { int i, bc; string bp; string *clkeys = keys(cl); if (sizeof(cl) != 4) return clkeys[0]; bc = s * 13; for (i = 0; i < 4; i++) if (SUIT(cl[clkeys[i]]) == s && cl[clkeys[i]] >= bc) bc = cl[bp = clkeys[i]]; return bp; }
char GetSuitChar(unsigned char c) { /* * */ const char suitChars[] = " hdcs"; if(ISCARDBACK(c)) return '?'; if(ISUNKNOWN(c)) return '_'; return suitChars[SUIT(c)]; }
void IdiotSolver::undo_move(MOVE *m) { #if PRINT if ( m->totype == O_Type ) fprintf( stderr, "\nundo move %d from %d out (at %d)\n\n", m->card_index, m->from, m->turn_index ); else fprintf( stderr, "\nundo move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index ); print_layout(); #endif int from, to; card_t card; from = m->from; to = m->to; if ( from == 4 ) { for ( int i = 3; i >= 0; --i ) { card = *Wp[i]; Wp[i]--; Wlen[i]--; Wp[from]++; *Wp[from] = ( SUIT( card ) << 4 ) + RANK( card ) + ( 1 << 7 ); Wlen[from]++; hashpile( i ); } hashpile( from ); } else { card = *Wp[to]; Wp[to]--; Wlen[to]--; *Wp[from]++; *Wp[from] = card; Wlen[from]++; hashpile( to ); hashpile(from); } #if PRINT print_layout(); #endif }
void GypsySolver::make_move(MOVE *m) { #if PRINT kDebug() << "\n\nmake_move\n"; if ( m->totype == O_Type ) fprintf( stderr, "move %d from %d out (at %d) Prio: %d\n\n", m->card_index, m->from, m->turn_index, m->pri ); else fprintf( stderr, "move %d from %d to %d (%d) Prio: %d\n\n", m->card_index, m->from, m->to, m->turn_index, m->pri ); print_layout(); #else //print_layout(); #endif int from, to; //card_t card = NONE; from = m->from; to = m->to; if ( m->from == deck ) { for ( int i = 0; i < 8; ++i ) { card_t card = *Wp[from]; card = ( SUIT( card ) << 4 ) + RANK( card ); ++Wp[i]; *Wp[i] = card; --Wp[from]; Wlen[i]++; hashpile( i ); Wlen[from]--; } hashpile( from ); #if PRINT print_layout(); #endif return; } card_t card = NONE; for ( int l = m->card_index; l >= 0; --l ) { card = W[from][Wlen[from]-l-1]; Wp[from]--; if ( m->totype != O_Type ) { Wp[to]++; *Wp[to] = card; Wlen[to]++; } } Wlen[from] -= m->card_index + 1; if ( m->turn_index == 0 ) { if ( DOWN( card ) ) card = ( SUIT( card ) << 4 ) + RANK( card ); else card += ( 1 << 7 ); W[to][Wlen[to]-m->card_index-1] = card; } else if ( m->turn_index != -1 ) { card_t card2 = *Wp[from]; if ( DOWN( card2 ) ) card2 = ( SUIT( card2 ) << 4 ) + RANK( card2 ); *Wp[from] = card2; } hashpile(from); /* Add to pile. */ if (m->totype == O_Type) { if ( Wlen[to] ) *Wp[to] = card; else { Wp[to]++; Wlen[to]++; *Wp[to] = card; } Q_ASSERT( m->card_index == 0 ); } hashpile(to); #if PRINT print_layout(); #endif }
int SimonSolver::get_possible_moves(int *a, int *numout) { MOVE *mp; /* Check for moves from W to O. */ int n = 0; mp = Possible; for (int w = 0; w < 10; ++w) { if (Wlen[w] >= 13 && RANK( *Wp[w] ) == PS_ACE ) { int ace_suit = SUIT( *Wp[w] ); bool stroke = true; for ( int l = 0; l < 13; ++l ) { if ( RANK( W[w][Wlen[w]-l-1] ) != l+1 || SUIT( W[w][Wlen[w]-l-1] ) != ace_suit ) { stroke = false; break; } } if ( !stroke ) continue; mp->card_index = 12; mp->from = w; int o = 0; while ( O[o] != -1) o++; // TODO I need a way to tell spades off from heart off mp->to = o; mp->totype = O_Type; mp->pri = 0; /* unused */ mp->turn_index = -1; n++; mp++; return 1; } } /* No more automoves, but remember if there were any moves out. */ *a = false; *numout = n; int conti[10]; for ( int j = 0; j < 10; ++j ) { conti[j] = 0; for ( ; conti[j] < Wlen[j]-1; ++conti[j] ) { if ( SUIT( *Wp[j] ) != SUIT( W[j][Wlen[j]-conti[j]-2] ) || DOWN( W[j][Wlen[j]-conti[j]-2] )) break; if ( RANK( W[j][Wlen[j]-conti[j]-1] ) != RANK( W[j][Wlen[j]-conti[j]-2] ) - 1) break; } conti[j]++; } for(int i=0; i<10; ++i) { int len = Wlen[i]; for (int l=0; l < len; ++l ) { card_t card = W[i][Wlen[i]-1-l]; if ( DOWN( card ) ) break; if ( l > 0 ) { card_t card_on_top = W[i][Wlen[i]-l]; if ( RANK( card ) != RANK( card_on_top ) + 1 ) break; if ( SUIT( card ) != SUIT( card_on_top ) ) break; } bool wasempty = false; for (int j = 0; j < 10; ++j) { if (i == j) continue; bool allowed = false; if ( Wlen[j] > 0 && RANK(card) == RANK(*Wp[j]) - 1 ) { allowed = true; } if ( Wlen[j] == 0 && !wasempty ) { if ( l != Wlen[i]-1 ) { allowed = true; wasempty = true; } } if ( allowed && Wlen[i] >= l+2 && Wlen[i] > 1 ) { Q_ASSERT( Wlen[i]-l-2 >= 0 ); card_t card_below = W[i][Wlen[i]-l-2]; if ( SUIT( card ) == SUIT( card_below ) && !DOWN( card_below ) && RANK( card_below ) == RANK( card ) + 1 ) { if ( conti[j]+l != 13 || conti[i]>conti[j]+l || SUIT( card ) != SUIT( *Wp[j] ) ) { // fprintf( stderr, "continue\n" ); continue; } } } if ( allowed ) { mp->card_index = l; mp->from = i; mp->to = j; mp->totype = W_Type; mp->turn_index = -1; int cont = conti[j]; if ( Wlen[j] ) cont++; if ( cont ) cont += l; mp->pri = 8 * cont + qMax( 0, 10 - Wlen[i] ); if ( Wlen[j] ) { if ( SUIT( card ) != SUIT( *Wp[j] ) ) { mp->pri /= 2; } } else { mp->pri = 2; // TODO: it should depend on the actual stack's order } if ( Wlen[i] == l+1 ) mp->pri = qMin( 127, mp->pri + 20 ); else mp->pri = qMin( 127, mp->pri + 2 ); /* and now check what sequence we open */ int conti_pos = l+1; for ( ; conti_pos < Wlen[i]-1; ++conti_pos ) { card_t top = W[i][Wlen[i]-l-2]; card_t theone = W[i][Wlen[i]-conti_pos-1]; card_t below = W[i][Wlen[i]-conti_pos-2]; if ( SUIT( top ) != SUIT( below ) || DOWN( below ) ) break; if ( RANK( theone ) != RANK( below ) - 1) break; } mp->pri = qMin( 127, mp->pri + 5 * ( conti_pos - l - 1 ) ); n++; mp++; } } } } return n; }
int KlondikeSolver::get_possible_moves(int *a, int *numout) { int w, o, empty; card_t card; MOVE *mp; /* Check for moves from W to O. */ int n = 0; mp = Possible; for (w = 0; w < 8; ++w) { if (Wlen[w] > 0) { card = *Wp[w]; o = SUIT(card); empty = (O[o] == NONE); if ((empty && (RANK(card) == PS_ACE)) || (!empty && (RANK(card) == O[o] + 1))) { mp->card_index = 0; mp->from = w; mp->to = o; mp->totype = O_Type; mp->pri = 3; /* unused */ mp->turn_index = -1; if ( Wlen[w] > 1 && DOWN( W[w][Wlen[w]-2] ) ) mp->turn_index = 1; n++; mp++; /* If it's an automove, just do it. Automoves from the pile are problematic though in draw=3 because automoves can break the offset and break winnable games */ if (good_automove(o, RANK(card)) && (w != 7 || m_draw == 1 || Wlen[7] < 3)) { *a = true; mp[-1].pri = 127; if (n != 1) { Possible[0] = mp[-1]; return 1; } return n; } } } } /* No more automoves, but remember if there were any moves out. */ *a = false; *numout = n; /* check for deck->pile */ if ( Wlen[8] ) { mp->card_index = qMin( m_draw, Wlen[8] ); mp->from = 8; mp->to = 7; mp->totype = W_Type; mp->pri = 5; mp->turn_index = 0; n++; mp++; } // we first check where to put a king, so we don't // try each king on each empty pile int first_empty_pile = -1; for(int i=0; i<8; ++i) if ( !Wlen[i] ) { first_empty_pile = i; break; } for(int i=0; i<8; ++i) { int len = Wlen[i]; if ( i == 7 && Wlen[i] > 0) len = 1; for (int l=0; l < len; ++l ) { card_t card = W[i][Wlen[i]-1-l]; if ( DOWN( card ) ) break; for (int j = 0; j < 7; ++j) { if (i == j) continue; int allowed = 0; if ( Wlen[j] > 0 && RANK(card) == RANK(*Wp[j]) - 1 && suitable( card, *Wp[j] ) ) { allowed = 1; if ( Wlen[i] == l + 1 ) { allowed = 2; } else { if ( DOWN( W[i][Wlen[i]-l-2] ) ) allowed = 3; } } if ( RANK( card ) == PS_KING && j == first_empty_pile ) { if ( l != Wlen[i]-1 || i == 7 ) allowed = 4; } if ( allowed && i == 7 ) allowed = 5; if ( allowed == 1 ) { //print_layout(); card_t below = W[i][Wlen[i]-2-l]; int o = SUIT(below); bool empty = (O[o] == NONE); //fprintf( stderr, "%d %d\n", i, l ); //printcard( below, stderr ); if ( ( empty && RANK( below ) != PS_ACE ) || ( !empty && RANK( below ) != O[o] + 1 ) ) allowed = 0; //fprintf( stderr, " allowed %d %d %d %d\n",allowed, empty, RANK( below ), PS_ACE); } if ( allowed ) { mp->card_index = l; mp->from = i; mp->to = j; mp->totype = W_Type; mp->turn_index = -1; if ( Wlen[i] > l+1 && DOWN( W[i][Wlen[i]-l-2] ) ) mp->turn_index = 1; if ( i == 7 ) mp->pri = 40; else { if ( mp->turn_index > 0 || Wlen[i] == l+1) mp->pri = 30; else mp->pri = 1; } n++; mp++; } } } } if ( Wlen[8] == 0 && Wlen[7] > 1 ) { mp->card_index = 0; mp->from = 7; mp->to = 8; mp->totype = W_Type; mp->turn_index = 0; mp->pri = 2; n++; mp++; } return n; }
void KlondikeSolver::make_move(MOVE *m) { #if PRINT if ( m->totype == O_Type ) fprintf( stderr, "\nmake move %d from %d out (at %d)\n\n", m->card_index, m->from, m->turn_index ); else fprintf( stderr, "\nmake move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index ); print_layout(); #else //print_layout(); #endif int from, to; card_t card = NONE; from = m->from; to = m->to; /* Remove from pile. */ if ( from == 7 && to == 8 ) { while ( Wlen[7] ) { card = W[7][Wlen[7]-1] + ( 1 << 7 ); Wlen[8]++; W[8][Wlen[8]-1] = card; Wlen[7]--; } Wp[7] = &W[7][0]; Wp[8] = &W[8][Wlen[8]-1]; hashpile( 7 ); hashpile( 8 ); #if PRINT print_layout(); #endif return; } // move to pile if ( from == 8 && to == 7 ) { for ( int i = 0; i < m->card_index; ++i ) { if ( !Wlen[8] ) continue; card = *Wp[8]; Wp[8]--; Wlen[8]--; card = ( SUIT( card ) << 4 ) + RANK( card ); Wp[7]++; *Wp[7] = card; Wlen[7]++; } hashpile( 7 ); hashpile( 8 ); #if PRINT print_layout(); #endif return; } for ( int l = m->card_index; l >= 0; --l ) { card = W[from][Wlen[from]-l-1]; Wp[from]--; if ( m->totype != O_Type ) { Wp[to]++; *Wp[to] = card; Wlen[to]++; } } Wlen[from] -= m->card_index + 1; if ( m->turn_index == 0 ) { if ( DOWN( card ) ) card = ( SUIT( card ) << 4 ) + RANK( card ); else card += ( 1 << 7 ); W[to][Wlen[to]-m->card_index-1] = card; } else if ( m->turn_index != -1 ) { card_t card2 = *Wp[from]; if ( DOWN( card2 ) ) card2 = ( SUIT( card2 ) << 4 ) + RANK( card2 ); *Wp[from] = card2; } hashpile(from); /* Add to pile. */ if (m->totype == O_Type) { O[to]++; Q_ASSERT( m->card_index == 0 ); } else { hashpile(to); } #if PRINT print_layout(); #endif }
int ClockSolver::get_possible_moves(int *a, int *numout) { MOVE *mp; /* Check for moves from W to O. */ int first_empty = -1; int left_in_play = 0; int n = 0; mp = Possible; for (int w = 0; w < 8; ++w) { left_in_play += Wlen[w]; if (Wlen[w] > 0) { card_t card = *Wp[w]; auto o = SUIT(card); for ( int i = 0; i < 12; ++i ) { if ( o != SUIT( W[8][i] ) ) continue; if ( RANK( card ) == PS_ACE ) { if ( RANK( W[8][i] ) != PS_KING ) continue; } else { if ( RANK( W[8][i] ) != RANK( card ) - 1 ) continue; } mp->card_index = 0; mp->from = w; mp->to = i; mp->totype = O_Type; mp->pri = 50; mp->turn_index = -1; n++; mp++; } } else if ( first_empty < 0 ) first_empty = w; } /* No more automoves, but remember if there were any moves out. */ *a = false; *numout = n; for(int i=0; i<8; ++i) { if ( !Wlen[i] ) continue; for (int j=0; j < 8; ++j ) { if ( i == j ) continue; card_t card = *Wp[i]; bool allowed = false; if ( Wlen[j] == 0 ) { if ( Wlen[i] > 1 && first_empty == j ) allowed = true; } else { card_t below = *Wp[j]; if ( RANK(card) == RANK( below ) - 1 ) { allowed = true; } } if ( allowed ) { mp->card_index = 0; mp->from = i; mp->to = j; mp->totype = W_Type; mp->turn_index = -1; mp->pri = 1; n++; mp++; } } } return n; }
void KlondikeSolver::undo_move(MOVE *m) { #if PRINT if ( m->totype == O_Type ) fprintf( stderr, "\nundo move %d from %d out (at %d)\n\n", m->card_index, m->from, m->turn_index ); else fprintf( stderr, "\nundo move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index ); print_layout(); #endif int from, to; card_t card; from = m->from; to = m->to; /* Remove from 'to' pile. */ if ( from == 7 && to == 8 ) { while ( Wlen[8] ) { card = W[8][Wlen[8]-1]; card = ( SUIT( card ) << 4 ) + RANK( card ); Wlen[7]++; W[7][Wlen[7]-1] = card; Wlen[8]--; } Wp[8] = &W[8][0]; Wp[7] = &W[7][Wlen[7]-1]; hashpile( 7 ); hashpile( 8 ); #if PRINT print_layout(); #endif return; } // move back to deck if ( from == 8 && to == 7 ) { for ( int i = 0; i < m->card_index; ++i ) { card = *Wp[7]; Wp[7]--; Wlen[7]--; card = ( SUIT( card ) << 4 ) + RANK( card ) + ( 1 << 7 ); Wp[8]++; *Wp[8] = card; Wlen[8]++; } hashpile( 7 ); hashpile( 8 ); #if PRINT print_layout(); #endif return; } /* Add to 'from' pile. */ if ( m->turn_index > 0 ) { card_t card2 = *Wp[from]; if ( !DOWN( card2 ) ) card2 = ( SUIT( card2 ) << 4 ) + RANK( card2 ) + ( 1 << 7 ); *Wp[from] = card2; } if (m->totype == O_Type) { card = O[to] + Osuit[to]; O[to]--; Wp[from]++; *Wp[from] = card; Wlen[from]++; } else { for ( int l = m->card_index; l >= 0; --l ) { card = W[to][Wlen[to]-l-1]; Wp[from]++; *Wp[from] = card; Wlen[from]++; Wp[to]--; } Wlen[to] -= m->card_index + 1; hashpile(to); } if ( m->turn_index == 0 ) { card_t card = *Wp[from]; if ( DOWN( card ) ) card = ( SUIT( card ) << 4 ) + RANK( card ); else card += ( 1 << 7 ); *Wp[from] = card; } hashpile(from); #if PRINT print_layout(); #endif }
/* * aLeftPlayer: next in turn * aRightPlayer: prev in turn * 0, 1th * 1th, 2nd */ Card *AlphaBetaPlayer::makeMove (Card *lMove, Card *rMove, Player *aLeftPlayer, Player *aRightPlayer, bool isPassOut) { qDebug() << type() << "("<< mPlayerNo << ") moves"; card_t hands[3][10]; card_t desk[3]; int crdLeft = 0; int trumpSuit = 0; Player *plst[3]; //again: plst[0] = plst[1] = plst[2] = 0; plst[mPlayerNo-1] = this; plst[aLeftPlayer->number()-1] = aLeftPlayer; plst[aRightPlayer->number()-1] = aRightPlayer; // build hands for (int c = 0; c < 3; c++) { Q_ASSERT(plst[c]); CardList *clst = &(plst[c]->mCards); //for (int f = 0; f < 10; f++) hds[c][f] = hands[c][f] = 0; int pos = 0; for (int f = 0; f < clst->size(); f++) { Card *ct = clst->at(f); if (!ct) continue; hands[c][pos++] = CARD(ct->face(), ct->suit()-1); if (pos > crdLeft) crdLeft = pos; } for (int f = pos; f < 10; f++) hands[c][f] = 0; xsortCards(hands[c], pos); } if (!lMove && !rMove && crdLeft == 10) { return AiPlayer::makeMove(lMove, rMove, aLeftPlayer, aRightPlayer, isPassOut); } // find game const eGameBid bid = m_model->currentGame(); gPassOutOrMisere = (bid == g86 || bid == g86catch || bid == raspass); trumpSuit = bid%10-1;//(bid-(bid/10)*10)-1; /* if (bid == g86catch || bid == g86 || bid == raspass) { return Player::moveSelectCard(lMove, rMove, aLeftPlayer, aRightPlayer); } */ if (bid == g86catch || bid == g86 || bid == raspass) { trumpSuit = 4; } if (trumpSuit < 0) trumpSuit = 4; fprintf(stderr, "po:%s; lm:%s, rm:%s\n", isPassOut?"y":"n", lMove?"y":"n", rMove?"y":"n"); if (isPassOut && rMove && !lMove) { // это распасы, первый или второй круг, первый ход gPassOutSuit = rMove->suit()-1; fprintf(stderr, "pass-out: %i\n", gPassOutSuit); rMove = 0; } else gPassOutSuit = -1; // build desk int turn = 0; if (lMove) { desk[turn++] = CARD(lMove->face(), lMove->suit()-1); if (rMove) desk[turn++] = CARD(rMove->face(), rMove->suit()-1); } else if (rMove) { desk[turn++] = CARD(rMove->face(), rMove->suit()-1); } // build hands for (int f = 0; f < 3; f++) { xHands[f].suitCount[0] = xHands[f].suitCount[1] = xHands[f].suitCount[2] = xHands[f].suitCount[3] = 0; xHands[f].suitStart[0] = xHands[f].suitStart[1] = xHands[f].suitStart[2] = xHands[f].suitStart[3] = 11; xHands[f].tricks = plst[f]->tricksTaken(); int st; for (int z = 0; z < 10; z++) { if (hands[f][z]) { xHands[f].faces[z] = FACE(hands[f][z]); st = xHands[f].suits[z] = SUIT(hands[f][z]); if (xHands[f].suitCount[st]++ == 0) xHands[f].suitStart[st] = z; } else xHands[f].faces[z] = 0; } } // build desk for (int f = 0; f < turn; f++) { xDeskFaces[f] = FACE(desk[f]); xDeskSuits[f] = SUIT(desk[f]); } int a, b, c, move; int me = this->number()-1; xCardsLeft = crdLeft; gTrumpSuit = trumpSuit; gIterations = 0; printf("%shand 0:", this->number()==0?"*":" "); printHand(&(xHands[0])); printf("%shand 1:", this->number()==1?"*":" "); printHand(&(xHands[1])); printf("%shand 2:", this->number()==2?"*":" "); printHand(&(xHands[2])); printDesk(turn); // оптимизации /* if (turn > 0) { // можем вообще взять? if (hands[me].suitCount( } */ stTime = QTime::currentTime(); stTime.start(); abcPrune(turn, me, -666, 666, 666, &a, &b, &c, &move); qDebug() << "face:" << FACE(hands[me][move]) << "suit:" << SUIT(hands[me][move])+1 << "move:" << move << "turn:" << turn << "moves:" << crdLeft << "trump:" << trumpSuit << "iters:" << gIterations << ""; /* for (int h = 0; h < 3; h++) { fprintf(stderr, (h == me)?"*":" "); fprintf(stderr, "hand %i:", h); for (int f = 0; f < 10; f++) { if (hands[h][f]) { fprintf(stderr, " %2i.%i(%3i)", FACE(hands[h][f]), SUIT(hands[h][f]), hands[h][f]); } else { fprintf(stderr, " %2i.%i(%3i)", 0, 0, hands[h][f]); } } fprintf(stderr, "\n"); } fprintf(stderr, "desk:"); for (int f = 0; f < turn; f++) { fprintf(stderr, " %2i.%i(%3i)", FACE(desk[f]), SUIT(desk[f]), desk[f]); } fprintf(stderr, "\n"); */ Q_ASSERT(move >= 0); Card *moveCard = getCard(FACE(hands[me][move]), SUIT(hands[me][move])+1); qDebug() << "move:" << moveCard->toString(); mCards.remove(moveCard); mCardsOut.insert(moveCard); return moveCard; }
void Mod3Solver::make_move(MOVE *m) { #if PRINT if ( m->totype == O_Type ) fprintf( stderr, "\nmake move %d from %d out %d (at %d)\n\n", m->card_index, m->from, m->to, m->turn_index ); else fprintf( stderr, "\nmake move %d from %d to %d (%d)\n\n", m->card_index, m->from, m->to, m->turn_index ); print_layout(); #else //print_layout(); #endif int from, to; from = m->from; to = m->to; if ( from == deck ) { int len = m->card_index; if ( len > 8 ) len = 8; for ( int i = 0; i < len; i++ ) { card_t card = *Wp[deck]; Wlen[deck]--; Wp[deck]--; card = ( card & PS_SUIT ) + RANK( card ); Wp[24 + i]++; Wlen[24 + i]++; *Wp[24 + i] = card; hashpile( 24 + i ); } hashpile( deck ); #if PRINT print_layout(); #endif return; } card_t card = *Wp[from]; Wlen[from]--; Wp[from]--; hashpile( from ); /* Add to pile. */ Wp[to]++; *Wp[to] = card; Wlen[to]++; hashpile( to ); if ( m->turn_index == 1 ) { card_t card2 = *Wp[deck]; Wlen[deck]--; Wp[deck]--; hashpile(deck); /* Add to pile. */ Wp[from]++; *Wp[from] = RANK( card2 ) + ( SUIT( card2 ) << 4 ); Wlen[from]++; } hashpile(from); #if PRINT print_layout(); #endif }
int FreecellSolver::get_possible_moves(int *a, int *numout) { int i, n, t, w, o, empty, emptyw; card_t card; MOVE *mp; /* Check for moves from W to O. */ n = 0; mp = Possible; for (w = 0; w < Nwpiles + Ntpiles; ++w) { if (Wlen[w] > 0) { card = *Wp[w]; o = SUIT(card); empty = (O[o] == NONE); if ((empty && (RANK(card) == PS_ACE)) || (!empty && (RANK(card) == O[o] + 1))) { mp->card_index = 0; mp->from = w; mp->to = o; mp->totype = O_Type; mp->turn_index = -1; mp->pri = 0; /* unused */ n++; mp++; /* If it's an automove, just do it. */ if (good_automove(o, RANK(card))) { *a = true; mp[-1].pri = 127; if (n != 1) { Possible[0] = mp[-1]; return 1; } return n; } } } } /* No more automoves, but remember if there were any moves out. */ *a = false; *numout = n; /* Check for moves from non-singleton W cells to one of any empty W cells. */ emptyw = -1; for (w = 0; w < Nwpiles; ++w) { if (Wlen[w] == 0) { emptyw = w; break; } } if (emptyw >= 0) { for (i = 0; i < Nwpiles + Ntpiles; ++i) { if (i == emptyw || Wlen[i] == 0) { continue; } bool allowed = false; if ( i < Nwpiles) allowed = true; if ( i >= Nwpiles ) allowed = true; if ( allowed ) { card = *Wp[i]; mp->card_index = 0; mp->from = i; mp->to = emptyw; mp->totype = W_Type; mp->turn_index = -1; if ( i >= Nwpiles ) mp->pri = Xparam[6]; else mp->pri = Xparam[3]; n++; mp++; } } } /* Check for moves from W to non-empty W cells. */ for (i = 0; i < Nwpiles + Ntpiles; ++i) { if (Wlen[i] > 0) { card = *Wp[i]; for (w = 0; w < Nwpiles; ++w) { if (i == w) { continue; } if (Wlen[w] > 0 && (RANK(card) == RANK(*Wp[w]) - 1 && suitable(card, *Wp[w]))) { mp->card_index = 0; mp->from = i; mp->to = w; mp->totype = W_Type; mp->turn_index = -1; if ( i >= Nwpiles ) mp->pri = Xparam[5]; else mp->pri = Xparam[4]; n++; mp++; } } } } /* Check for moves from W to one of any empty T cells. */ for (t = 0; t < Ntpiles; ++t) { if (!Wlen[t+Nwpiles]) { break; } } if (t < Ntpiles) { for (w = 0; w < Nwpiles; ++w) { if (Wlen[w] > 0) { card = *Wp[w]; mp->card_index = 0; mp->from = w; mp->turn_index = -1; mp->to = t+Nwpiles; mp->totype = W_Type; mp->pri = Xparam[7]; n++; mp++; } } } return n; }
void FreecellSolver::prioritize(MOVE *mp0, int n) { int i, j, s, w, pile[NNEED], npile; card_t card, need[4]; MOVE *mp; /* There are 4 cards that we "need": the next cards to go out. We give higher priority to the moves that remove cards from the piles containing these cards. */ for (i = 0; i < NNEED; ++i) { pile[i] = -1; } npile = 0; for (s = 0; s < 4; ++s) { need[s] = NONE; if (O[s] == NONE) { need[s] = Osuit[s] + PS_ACE; } else if (O[s] != PS_KING) { need[s] = Osuit[s] + O[s] + 1; } } /* Locate the needed cards. There's room for optimization here, like maybe an array that keeps track of every card; if maintaining such an array is not too expensive. */ for (w = 0; w < Nwpiles; ++w) { j = Wlen[w]; for (i = 0; i < j; ++i) { card = W[w][i]; s = SUIT(card); /* Save the locations of the piles containing not only the card we need next, but the card after that as well. */ if (need[s] != NONE && (card == need[s] || card == need[s] + 1)) { pile[npile++] = w; if (npile == NNEED) { break; } } } if (npile == NNEED) { break; } } /* Now if any of the moves remove a card from any of the piles listed in pile[], bump their priority. Likewise, if a move covers a card we need, decrease its priority. These priority increments and decrements were determined empirically. */ for (i = 0, mp = mp0; i < n; ++i, ++mp) { if (mp->card_index != -1) { w = mp->from; for (j = 0; j < npile; ++j) { if (w == pile[j]) { mp->pri += Xparam[0]; } } if (Wlen[w] > 1) { card = W[w][Wlen[w] - 2]; for (s = 0; s < 4; ++s) { if (card == need[s]) { mp->pri += Xparam[1]; break; } } } if (mp->totype == W_Type) { for (j = 0; j < npile; ++j) { if (mp->to == pile[j]) { mp->pri -= Xparam[2]; } } } } } }
static int board_save_lin(window_board_t *win, char *filename) { int cur; FILE *f; if ((f = fopen (filename, "w")) == NULL) return 0; setlocale (LC_NUMERIC, "C"); if (win->title) { fprintf (f, "vg|%s,%s,%s,%d,%d,%s,,%s,|\n", win->title, win->subtitle ? win->subtitle : "", "P", // FIXME 1, win->n_boards, win->team1 ? win->team1 : "", win->team2 ? win->team2 : ""); fprintf (f, "rs|"); for (cur = 0; cur < win->n_boards; cur++) { board *b = win->boards[cur]; fprintf (f, "%s,", lin_contract (b)); if (cur != win->n_boards - 1) fprintf (f, ","); } fprintf (f, "|\n"); fprintf (f, "pw|"); for (cur = 0; cur < win->n_boards; cur++) { board *b = win->boards[cur]; fprintf (f, "%s,%s,%s,%s", b->hand_name[south-1]->str, b->hand_name[west-1]->str, b->hand_name[north-1]->str, b->hand_name[east-1]->str); if (cur != win->n_boards - 1) fprintf (f, ","); } fprintf (f, "|\n"); fprintf (f, "mp|"); for (cur = 0; cur < win->n_boards; cur++) { board *b = win->boards[cur]; if (b->mp[0] == 0 && b->mp[1] == 0) fprintf (f, "--,--"); else { if (b->mp[0]) fprintf (f, "%.2f", b->mp[0] / 100.0); fprintf (f, ","); if (b->mp[1]) fprintf (f, "%.2f", b->mp[1] / 100.0); } if (cur != win->n_boards - 1) fprintf (f, ","); } fprintf (f, "|\n"); fprintf (f, "bn|"); for (cur = 0; cur < win->n_boards; cur++) { //board *b = win->boards[cur]; fprintf (f, "%d", cur + 1); // TODO: original number? if (cur != win->n_boards - 1) fprintf (f, ","); } fprintf (f, "|\n"); fprintf (f, "pg||\n"); } for (cur = 0; cur < win->n_boards; cur++) { board *b = win->boards[cur]; int i; if (win->n_boards > 1) fprintf (f, "qx|o%d|", cur + 1); // TODO: open/closed, real board number fprintf (f, "pn|%s,%s,%s,%s|", b->hand_name[south-1]->str, b->hand_name[west-1]->str, b->hand_name[north-1]->str, b->hand_name[east-1]->str); fprintf (f, "st||"); fprintf (f, "md|%d%s|", seat_mod(b->dealer + 1), lin_card_string(b)); // TODO: end positions fprintf (f, "rh||"); fprintf (f, "ah|%s|", b->name->str); fprintf (f, "sv|%c|", b->vuln[0] ? (b->vuln[1] ? 'b' : 'n') : (b->vuln[1] ? 'e' : 'o')); for (i = 0; i < b->n_bids; i++) { fprintf (f, "mb|%s|", lin_bid(b->bidding[i])); if (b->alerts[i]) fprintf (f, "an|%s|", *b->alerts[i] ? b->alerts[i] : "!"); } for (i = 0; i < 52; i++) { if (i % 4 == 0) fprintf (f, "pg||"); card c = b->played_cards[i]; if (c < 0) break; if (c == claim_rest) { fprintf (f, "mc|%d|", b->declarer_tricks >= 0 ? b->declarer_tricks : 0); break; } fprintf (f, "pc|%c%c|", "CDHS"[SUIT(c)], rank_char(RANK(c))); } fprintf (f, "pg||\n"); } int ret = 1, e = 0; if (ferror (f)) { ret = 0; e = errno; } fclose(f); errno = e; setlocale (LC_NUMERIC, ""); return ret; }
void on_menu_file_web_activate () { board *b = CUR_BOARD; GString *url = g_string_new ("http://www.bridgebase.com/tools/handviewer.html?"); /* non-lin interface int h; g_string_append_printf (url, "d=%c", seat_lc[b->dealer]); g_string_append_printf (url, "&v=%c", vuln_lc[b->vuln[0] + 2 * b->vuln[1]]); g_string_append_printf (url, "&n=%d", b->n + 1); // TODO: real board number for (h = west; h <= south; h++) { if (*b->hand_name[h - 1]->str) g_string_append_printf (url, "&%cn=%s", seat_lc[h], b->hand_name[h - 1]->str); g_string_append_printf (url, "&%c=", seat_lc[h]); int s; for (s = club; s <= spade; s++) { g_string_append_printf (url, "%s", trump_str_char[s]); int c; for (c = s * 13 + 12; c >= (int)s * 13; c--) if (b->dealt_cards[c] == h) g_string_append_printf(url, "%c", rank_char(RANK(c))); } } if (b->n_bids) { g_string_append_printf (url, "&a="); int i; for (i = 0; i < b->n_bids; i++) g_string_append_printf (url, "%s", lin_bid (b->bidding[i])); } if (b->n_played_cards) { g_string_append_printf (url, "&p="); int i; for (i = 0; i < b->n_played_cards; i++) g_string_append_printf (url, "%s%c", trump_str_char[SUIT(b->played_cards[i])], rank_char(RANK(b->played_cards[i]))); if (b->played_cards[b->n_played_cards] = claim_rest) g_string_append_printf (url, "&c=%d", b->declarer_tricks); } */ int i; // TODO: merge with code from board_save_lin g_string_append_printf (url, "lin=pn|%s,%s,%s,%s|", b->hand_name[south-1]->str, b->hand_name[west-1]->str, b->hand_name[north-1]->str, b->hand_name[east-1]->str); g_string_append_printf (url, "st||"); g_string_append_printf (url, "md|%d%s|", seat_mod(b->dealer + 1), lin_card_string(b)); // TODO: end positions g_string_append_printf (url, "rh||"); g_string_append_printf (url, "ah|%s|", b->name->str); g_string_append_printf (url, "sv|%c|", b->vuln[0] ? (b->vuln[1] ? 'b' : 'n') : (b->vuln[1] ? 'e' : 'o')); for (i = 0; i < b->n_bids; i++) { g_string_append_printf (url, "mb|%s|", lin_bid(b->bidding[i])); if (b->alerts[i]) g_string_append_printf (url, "an|%s|", *b->alerts[i] ? b->alerts[i] : "!"); } for (i = 0; i < 52; i++) { if (i % 4 == 0) g_string_append_printf (url, "pg||"); card c = b->played_cards[i]; if (c < 0) break; if (c == claim_rest) { g_string_append_printf (url, "mc|%d|", b->declarer_tricks >= 0 ? b->declarer_tricks : 0); break; } g_string_append_printf (url, "pc|%c%c|", "CDHS"[SUIT(c)], rank_char(RANK(c))); } g_string_append_printf (url, "pg||\n"); printf ("%s\n", url->str); GError *error = NULL; gtk_show_uri (gdk_screen_get_default (), url->str, GDK_CURRENT_TIME, &error); if (error) { printf ("%s\n", error->message); g_error_free (error); } g_string_free (url, TRUE); }
int YukonSolver::get_possible_moves(int *a, int *numout) { int w, o, empty; card_t card; MOVE *mp; /* Check for moves from W to O. */ int n = 0; mp = Possible; for (w = 0; w < 7; w++) { if (Wlen[w] > 0) { card = *Wp[w]; o = SUIT(card); empty = (O[o] == NONE); if ((empty && (RANK(card) == PS_ACE)) || (!empty && (RANK(card) == O[o] + 1))) { mp->card_index = 0; mp->from = w; mp->to = o; mp->totype = O_Type; mp->pri = 3; /* unused */ mp->turn_index = -1; if ( Wlen[w] > 1 && DOWN( W[w][Wlen[w]-2] ) ) mp->turn_index = 1; n++; mp++; /* If it's an automove, just do it. */ if (good_automove(o, RANK(card))) { *a = true; mp[-1].pri = 127; if (n != 1) { Possible[0] = mp[-1]; return 1; } return n; } } } } /* No more automoves, but remember if there were any moves out. */ *a = false; *numout = n; for(int i=0; i<7; i++) { int len = Wlen[i]; for (int l=0; l < len; ++l ) { card_t card = W[i][Wlen[i]-1-l]; if ( DOWN( card ) ) break; for (int j = 0; j < 7; j++) { if (i == j) continue; int allowed = 0; if ( Wlen[j] > 0 && RANK(card) == RANK(*Wp[j]) - 1 && suitable( card, *Wp[j] ) ) { allowed = 1; if ( Wlen[i] == l + 1 ) { allowed = 2; } else { if ( DOWN( W[i][Wlen[i]-l-2] ) ) allowed = 3; } } if ( RANK( card ) == PS_KING && Wlen[j] == 0 ) { if ( l != Wlen[i]-1 || i == 7 ) allowed = 4; } // TODO: there is no point in moving if we're not opening anything // e.g. if both i and j have perfect runs below the cards #if 0 fprintf( stderr, "%d %d %d\n", i, l, j ); printcard( card, stderr ); printcard( *Wp[j], stderr ); fprintf( stderr, " allowed %d\n",allowed ); #endif if ( allowed ) { mp->card_index = l; mp->from = i; mp->to = j; mp->totype = W_Type; mp->turn_index = -1; if ( Wlen[i] > l+1 && DOWN( W[i][Wlen[i]-l-2] ) ) mp->turn_index = 1; if ( mp->turn_index > 0 || Wlen[i] == l+1) mp->pri = 30; else mp->pri = 1; n++; mp++; } } } } return n; }