Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

FCState.cpp

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <stdio.h>
00012 #include <assert.h>
00013 #include "FCState.h"
00014 #include "FCTalonState.h"
00015 #include "FCDebugState.h"
00016 #include "FCCompactState.h"
00017 #include "FCIndirectState.h"
00018 #include "FCSDebugStateWithLocations.h"
00019 #include "FCSCompactStateWithLocations.h"
00020 #include "FCSIndirectStateWithLocations.h"
00021 #include "FCSTalonStateWithLocations.h"
00022 
00024 FCStateType GlobalStateType = FC_DEBUG_STATE;
00025 
00026 #ifdef min
00027 #undef min
00028 #endif
00029 
00030 #define min(a,b) ((a)<(b)?(a):(b))
00031 
00033 const char * const FreecellsPrefixes[] = { "FC:", "Freecells:", "Freecell:", ""};
00035 const char * const FoundationsPrefixes[] = { "Decks:", "Deck:", "Founds:", "Foundations:", "Foundation:", "Found:", ""};
00036 
00037 #ifdef WIN32
00038 #define strncasecmp(a,b,c) (strnicmp((a),(b),(c)))
00039 #endif
00040 
00041 FCSState::FCSState()
00042 {
00043 }
00044 
00045 FCSState::~FCSState()
00046 {
00047 }
00048 
00049 FCSStateWithLocations::FCSStateWithLocations()
00050 {
00051 char a;
00052 
00053     m_Depth = 0;
00054     m_Visited = 0;
00055     m_VisitIterations = 0;
00056     m_Parent = NULL;
00057     m_MovesToParent = NULL;
00058 
00059     for(a=0;a<MAX_NUM_STACKS;a++)
00060     {
00061         m_StackLocations[a] = a;
00062     }
00063     for(a=0;a<MAX_NUM_FREECELLS;a++)
00064     {
00065         m_FreecellLocations[a] = a;
00066     }
00067 }
00068 
00069 FCSStateWithLocations::~FCSStateWithLocations()
00070 {
00071 }
00072 
00073 void FCSStateWithLocations::Copy(FCSStateWithLocations* State)
00074 {
00075     memcpy(m_StackLocations, State->m_StackLocations, MAX_NUM_STACKS);
00076     m_Parent = State->m_Parent;
00077     m_MovesToParent = State->m_MovesToParent;
00078     memcpy(m_FreecellLocations, State->m_FreecellLocations, MAX_NUM_FREECELLS);
00079     m_Depth = State->m_Depth;
00080     m_Visited = State->m_Visited;
00081     m_VisitIterations = State->m_VisitIterations;
00082 }
00083 
00084 FCSStateWithLocations* FCSStateWithLocations::CreateInitialState(const char *String, 
00085                                             int NumberOfFreecells, int NumberOfStacks, 
00086                                             int NumberOfDecks)
00087 {
00088     FCSStateWithLocations* ReturnState;
00089 
00090     int DecksIndex[4], c, i;
00091     const char * Str;
00092     FCSCard* Card = FCSCard::Create();
00093     bool FirstLine = true,
00094          PrefixFound;
00095 
00096     const char * const * Prefixes;
00097 
00098     ReturnState = CreateStateWithLocations();
00099     ReturnState->Initialize(NumberOfStacks);
00100     
00101     Str = String;
00102 
00103     for(int s=0;s<NumberOfStacks;s++)
00104     {
00105         // Move to the next stack
00106         if (!FirstLine)
00107         {
00108             while((*Str) != '\n')
00109             {
00110                 Str++;
00111             }
00112             Str++;
00113         }
00114         FirstLine = false;
00115 
00116         Prefixes = FreecellsPrefixes;
00117         PrefixFound = false;
00118         for(i=0;Prefixes[i][0] != '\0'; i++)
00119         {
00120             if (!strncasecmp(Str, Prefixes[i], strlen(Prefixes[i])))
00121             {
00122                 PrefixFound = true;
00123                 Str += strlen(Prefixes[i]);
00124                 break;
00125             }
00126         }
00127 
00128         if (PrefixFound)
00129         {
00130             for(c=0;c<NumberOfFreecells;c++)
00131             {
00132                 ReturnState->EmptyFreecell(c);
00133             }
00134             for(c=0;c<NumberOfFreecells;c++)
00135             {
00136                 if (c!=0)
00137                 {
00138                     while(
00139                             ((*Str) != ' ') && 
00140                             ((*Str) != '\t') && 
00141                             ((*Str) != '\n') && 
00142                             ((*Str) != '\r')
00143                          )
00144                     {
00145                         Str++;
00146                     }
00147                     if ((*Str == '\n') || (*Str == '\r'))
00148                     {
00149                         break;
00150                     }
00151                     Str++;
00152                 }
00153 
00154                 while ((*Str == ' ') || (*Str == '\t'))
00155                 {
00156                     Str++;
00157                 }
00158                 if ((*Str == '\r') || (*Str == '\n'))
00159                     break;
00160 
00161                 if ((*Str == '*') || (*Str == '-'))
00162                 {
00163                     Card->EmptyCard();
00164                 }
00165                 else
00166                 {
00167                     Card->User2Perl(Str);
00168                 }
00169 
00170                 ReturnState->PutCardInFreecell(c, Card);
00171             }
00172 
00173             while ((*Str != '\n') && (*Str != '\0'))
00174             {
00175                 Str++;
00176             }
00177             s--;
00178             continue;
00179         }
00180 
00181         Prefixes = FoundationsPrefixes;
00182         PrefixFound = false;
00183         for(i=0;Prefixes[i][0] != '\0'; i++)
00184         {
00185             if (!strncasecmp(Str, Prefixes[i], strlen(Prefixes[i])))
00186             {
00187                 PrefixFound = true;
00188                 Str += strlen(Prefixes[i]);
00189                 break;
00190             }
00191         }
00192 
00193         if (PrefixFound)
00194         {
00195             int d;
00196 
00197             for(d=0;d<NumberOfDecks*4;d++)
00198             {
00199                 ReturnState->SetFoundation(d, 0);
00200             }
00201 
00202             for(d=0;d<4;d++)
00203             {
00204                 DecksIndex[d] = 0;
00205             }
00206             while (1)
00207             {
00208                 while((*Str == ' ') || (*Str == '\t'))
00209                     Str++;
00210                 if ((*Str == '\n') || (*Str == '\r'))
00211                     break;
00212                 d = FCSCard::User2PerlSuit(Str);
00213                 Str++;
00214                 while (*Str == '-')
00215                     Str++;
00216                 c = FCSCard::User2PerlCardNumber(Str);
00217                 while (
00218                         (*Str != ' ') && 
00219                         (*Str != '\t') && 
00220                         (*Str != '\n') && 
00221                         (*Str != '\r')
00222                       )
00223                 {
00224                     Str++;
00225                 }
00226 
00227                 ReturnState->SetFoundation(DecksIndex[d]*4+d, c);
00228                 DecksIndex[d]++;
00229                 if (DecksIndex[d] >= NumberOfDecks)
00230                 {
00231                     DecksIndex[d] = 0;
00232                 }
00233             }
00234             s--;
00235             continue;
00236         }
00237 
00238         for(c=0 ; c < MAX_NUM_CARDS_IN_A_STACK ; c++)
00239         {
00240             // Move to the next card
00241             if (c!=0)
00242             {
00243                 while(
00244                     ((*Str) != ' ') && 
00245                     ((*Str) != '\t') && 
00246                     ((*Str) != '\n') && 
00247                     ((*Str) != '\r')
00248                 )
00249                 {
00250                     Str++;
00251                 }
00252                 if ((*Str == '\n') || (*Str == '\r'))
00253                 {
00254                     break;
00255                 }
00256             }
00257 
00258             while ((*Str == ' ') || (*Str == '\t'))
00259             {
00260                 Str++;
00261             }
00262             if ((*Str == '\n') || (*Str == '\r'))
00263             {
00264                 break;
00265             }
00266             Card->User2Perl(Str);
00267 
00268             ReturnState->PushCardIntoStack(s, Card);
00269         } 
00270     }
00271 
00272     //this is needed becuase the "card type" is dymanic and can't be just a local variable
00273     delete Card;
00274 
00275     return ReturnState;
00276 }
00277 
00278 int FCSStateWithLocations::CheckStateValidity(int NumberOfFreecells, int NumberOfStacks, int NumberOfDecks, 
00279                                               FCSCard** MisplacedCard, FCSTalonType TalonType)
00280 {
00281     int Cards[4][14];
00282     int c, d;
00283 
00284     // Initialize all cards to 0
00285     for(d=0;d<4;d++)
00286         for(c=1;c<=13;c++)
00287             Cards[d][c] = 0;
00288 
00289     // Mark the cards in the decks
00290     for(d=0;d<NumberOfDecks*4;d++)
00291         for (c=1; c<=GetFoundation(d); c++)
00292             Cards[d%4][c]++;
00293 
00294     // Mark the cards in the freecells
00295     for(int f=0;f<NumberOfFreecells;f++)
00296         if (GetFreecellCardNumber(f) != 0)
00297             Cards[GetFreecellCardSuit(f)][GetFreecellCardNumber(f)]++;
00298 
00299     // Mark the cards in the stacks
00300     for(int s=0;s<NumberOfStacks;s++)
00301     {
00302         for (c=0; c<GetStackLength(s); c++)
00303         {
00304             if (GetStackCardNumber(s, c) == 0)
00305             {
00306                 (*MisplacedCard) = FCSCard::Create();
00307                 (*MisplacedCard)->EmptyCard();
00308                 return 3;
00309             }
00310             Cards[GetStackCardSuit(s, c)][GetStackCardNumber(s, c)]++;
00311         }
00312     }
00313 
00314     // Now check if there are extra or missing cards
00315     for(d=0;d<4;d++)
00316     {
00317         for(c=1;c<=13;c++)
00318         {
00319             if (Cards[d][c] != NumberOfDecks)
00320             {
00321                 (*MisplacedCard) = FCSCard::Create();
00322                 (*MisplacedCard)->SetSuit(d);
00323                 (*MisplacedCard)->SetCardNumber(c);
00324                 return (Cards[d][c] < NumberOfDecks) ? 1 : 2;
00325             }
00326         }
00327     }
00328 
00329     return 0;
00330 }
00331 
00332 void FCSStateWithLocations::StateAsString(char* String, FCSDebugDisplayInfo* DebugInfo)
00333 {
00334     char Freecells[10], Decks[MAX_NUM_DECKS*4][10], StackCards[10];
00335     bool CardNumberIsNull;
00336     int MaxNumberOfCards, NumberOfCards, Length, b, s;
00337 
00338     FCSCard* TempCard;
00339 
00340     char Str2[128], Str3[128], *PtrStr2, *PtrStr3, *Str, a;
00341 
00342     int StackLocations[MAX_NUM_STACKS];
00343     int FreecellLocations[MAX_NUM_FREECELLS];
00344 
00345     if (DebugInfo->m_DisplayDebugOptions & DEBUG_CANONIZED_ORDER_OUTPUT)
00346     {
00347         for(a=0;a<DebugInfo->m_NumberOfStacks;a++)
00348             StackLocations[a] = a;
00349 
00350         for(a=0;a<DebugInfo->m_NumberOfFreecells;a++)
00351             FreecellLocations[a] = a;
00352     }
00353     else
00354     {
00355         for(a=0;a<DebugInfo->m_NumberOfStacks;a++)
00356             StackLocations[m_StackLocations[a]] = a;
00357 
00358         for(a=0;a<DebugInfo->m_NumberOfFreecells;a++)
00359             FreecellLocations[m_FreecellLocations[a]] = a;
00360     }
00361 
00362     for(a=0;a<DebugInfo->m_NumberOfDecks*4;a++)
00363     {
00364         FCSCard::Perl2UserCardNumber(GetFoundation(a), Decks[a], &CardNumberIsNull,
00365                                     (DebugInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_10_AS_T), 0, DebugInfo->m_DisplayDebug);
00366         if (Decks[a][0] == ' ')
00367             Decks[a][0] = '0';
00368     }
00369 
00370     Str = String;
00371 
00372     if (!(DebugInfo->m_DisplayDebugOptions & DEBUG_IS_OUTPUT_PARSEABLE))
00373     {
00374         for(a=0;a<((DebugInfo->m_NumberOfFreecells/4)+(DebugInfo->m_NumberOfFreecells%4 !=0));a++)
00375         {
00376             PtrStr2 = Str2;
00377             PtrStr3 = Str3;
00378             for(b=0;b<min(DebugInfo->m_NumberOfFreecells-a*4, 4);b++)
00379             {
00380                 TempCard = GetFreecellCard(m_FreecellLocations[a*4+b]);
00381                 PtrStr2 += sprintf(PtrStr2, "%3s ", 
00382                     TempCard->Perl2User(Freecells, (DebugInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_10_AS_T),
00383                                         DebugInfo->m_DisplayDebug)
00384                     );
00385                 PtrStr3 += sprintf(PtrStr3, "--- ");
00386             }
00387             if (a < DebugInfo->m_NumberOfDecks)
00388             {
00389                 Str += sprintf(Str, "%-16s        H-%1s C-%1s D-%1s S-%1s\n",
00390                     Str2,
00391                     Decks[a*4],
00392                     Decks[a*4+1],
00393                     Decks[a*4+2],
00394                     Decks[a*4+3]);                    
00395             }
00396             else
00397             {
00398                 Str += sprintf(Str, "%s\n", Str2);
00399             }
00400             Str += sprintf(Str, "%s\n", Str3);
00401         }
00402         for(;a<DebugInfo->m_NumberOfDecks;a++)
00403         {
00404             Str += sprintf(Str, "%-16s        H-%1s C-%1s D-%1s S-%1s\n",
00405                     "",
00406                     Decks[a*4],
00407                     Decks[a*4+1],
00408                     Decks[a*4+2],
00409                     Decks[a*4+3]);    
00410         }
00411         *(Str++) = '\n';
00412         *(Str++) = '\n';
00413         *Str = '\0';
00414 
00415         for(s=0;s<DebugInfo->m_NumberOfStacks;s++)
00416         {
00417             Str += sprintf(Str, " -- ");
00418         }
00419         *(Str++) = '\n';
00420         *Str = '\0';
00421 
00422         MaxNumberOfCards = 0;
00423         for(s=0;s<DebugInfo->m_NumberOfStacks;s++)
00424             if (GetStackLength(StackLocations[s]) > MaxNumberOfCards)
00425                 MaxNumberOfCards = GetStackLength(StackLocations[s]);
00426 
00427         for(NumberOfCards=0;NumberOfCards<MaxNumberOfCards;NumberOfCards++)
00428         {
00429             for(s = 0; s<DebugInfo->m_NumberOfStacks; s++)
00430             {
00431                 if (NumberOfCards >= GetStackLength(StackLocations[s]))
00432                 {
00433                     strcpy(Str, "    ");
00434                     Str += strlen(Str);
00435                 }
00436                 else
00437                 {
00438                     TempCard = GetStackCard(StackLocations[s], NumberOfCards);
00439                     Str += sprintf(Str, "%3s ", 
00440                         TempCard->Perl2User(StackCards, (DebugInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_10_AS_T), 
00441                                             DebugInfo->m_DisplayDebug));                   
00442                 }
00443             }
00444             strcpy(Str, "\n");
00445             Str += strlen(Str);
00446         }
00447     }
00448     else
00449     {
00450 
00451         Str += sprintf(Str, "Foundations: ");
00452         for(a=0;a<DebugInfo->m_NumberOfDecks;a++)
00453         {
00454             Str += sprintf(Str,
00455                 "H-%s C-%s D-%s S-%s ",
00456                 Decks[a*4],
00457                 Decks[a*4+1],
00458                 Decks[a*4+2],
00459                 Decks[a*4+3]
00460                 );
00461         }
00462         Str += sprintf(Str, "\nFreecells: ");
00463     
00464         for(a=0;a<DebugInfo->m_NumberOfFreecells;a++)
00465         {
00466             TempCard = GetFreecellCard(FreecellLocations[a]);
00467             Str += sprintf(Str, "%3s", 
00468                 TempCard->Perl2User(Freecells, (DebugInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_10_AS_T), 
00469                                     DebugInfo->m_DisplayDebug)          
00470                 );
00471             if (a < DebugInfo->m_NumberOfFreecells-1)
00472             {
00473                 *(Str++) = ' ';
00474                 *Str = '\0';
00475             }
00476         }
00477         *(Str++) = '\n';
00478         *Str = '\0';
00479 
00480         for(s=0;s<DebugInfo->m_NumberOfStacks;s++)
00481         {
00482             strcpy(Str, ": ");
00483             Str += strlen(Str);
00484 
00485             Length = GetStackLength(StackLocations[s]);
00486             for(NumberOfCards=0;NumberOfCards<Length;NumberOfCards++)
00487             {
00488                 TempCard = GetStackCard(StackLocations[s], NumberOfCards);
00489                 TempCard->Perl2User(StackCards, (DebugInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_10_AS_T),
00490                                     DebugInfo->m_DisplayDebug);
00491 
00492                 strcpy(Str, StackCards);
00493                 Str += strlen(Str);
00494                 if (NumberOfCards < Length-1)
00495                 {
00496                     strcpy(Str, " ");
00497                     Str += strlen(Str);
00498                 }
00499             }
00500             strcpy(Str,"\n");
00501             Str += strlen(Str);
00502         }
00503     }
00504 }
00505 
00506 void FCSStateWithLocations::CleanState()
00507 {
00508 }
00509 
00510 void FCSStateWithLocations::CacheStacks(AFCSGenericStackStorage* Storage, int StackNumber)
00511 {
00512 }
00513 
00514 void FCSStateWithLocations::Initialize(int NumberOfStacks)
00515 {
00516 }
00517 
00518 int GetFCSStateWithLocationsClassSize()
00519 {
00520     switch(GlobalStateType)
00521     {
00522     case FC_DEBUG_STATE:
00523         return sizeof(FCSDebugStateWithLocations<FCSStateWithLocations>);
00524     case FC_COMPACT_STATE:
00525         return sizeof(FCSCompactStateWithLocations<FCSStateWithLocations>);
00526     case FC_INDIRECT_STATE:
00527         return sizeof(FCSIndirectStateWithLocations<FCSStateWithLocations>);
00528     case FC_TALON_DEBUG_STATE:
00529         return sizeof(FCSDebugTalonStateWithLocations);
00530     case FC_TALON_COMPACT_STATE:
00531         return sizeof(FCSCompactTalonStateWithLocations);
00532     case FC_TALON_INDIRECT_STATE:
00533         return sizeof(FCSIndirectTalonStateWithLocations);
00534     default:
00535         return 0;
00536     }
00537 }
00538 
00539 FCSStateWithLocations* CreateStateWithLocations()
00540 {
00541     switch(GlobalStateType)
00542     {
00543     case FC_DEBUG_STATE:
00544         return new FCSDebugStateWithLocations<FCSStateWithLocations>();
00545     case FC_COMPACT_STATE:
00546         return new FCSCompactStateWithLocations<FCSStateWithLocations>();
00547     case FC_INDIRECT_STATE:
00548         return new FCSIndirectStateWithLocations<FCSStateWithLocations>();
00549     case FC_TALON_DEBUG_STATE:
00550         return new FCSDebugTalonStateWithLocations();
00551     case FC_TALON_COMPACT_STATE:
00552         return new FCSCompactTalonStateWithLocations();
00553     case FC_TALON_INDIRECT_STATE:
00554         return new FCSIndirectTalonStateWithLocations();
00555     default:
00556         return NULL;
00557     }
00558 }
00559 
00560 AFCSStateWithLocationsMatrix* CreateStateWithLocationsMatrix(int Size)
00561 {
00562     switch(GlobalStateType)
00563     {
00564     case FC_DEBUG_STATE:
00565         return new FCSStateWithLocationsMatrix<FCSDebugStateWithLocations<FCSStateWithLocations> >(Size);
00566     case FC_COMPACT_STATE:
00567         return new FCSStateWithLocationsMatrix<FCSCompactStateWithLocations<FCSStateWithLocations> >(Size);
00568     case FC_INDIRECT_STATE:
00569         return new FCSStateWithLocationsMatrix<FCSIndirectStateWithLocations<FCSStateWithLocations> >(Size);
00570     case FC_TALON_DEBUG_STATE:
00571         return new FCSStateWithLocationsMatrix<FCSDebugTalonStateWithLocations>(Size);
00572     case FC_TALON_COMPACT_STATE:
00573         return new FCSStateWithLocationsMatrix<FCSCompactTalonStateWithLocations>(Size);
00574     case FC_TALON_INDIRECT_STATE:
00575         return new FCSStateWithLocationsMatrix<FCSIndirectTalonStateWithLocations>(Size);
00576     default:
00577         return NULL;
00578     }
00579 }
00580 
00581 void ReallocStateWithLocationsArray(FCSStateWithLocations*** Array, int OldSize, int NewSize)
00582 {
00583     switch (GlobalStateType)
00584     {
00585     case FC_DEBUG_STATE:
00586         Realloc<FCSDebugStateWithLocations<FCSStateWithLocations>*>((FCSDebugStateWithLocations<FCSStateWithLocations>***)Array, OldSize, NewSize);
00587         break;
00588     case FC_COMPACT_STATE:
00589         Realloc<FCSCompactStateWithLocations<FCSStateWithLocations>*>((FCSCompactStateWithLocations<FCSStateWithLocations>***)Array, OldSize, NewSize);
00590         break;
00591     case FC_INDIRECT_STATE:
00592         Realloc<FCSIndirectStateWithLocations<FCSStateWithLocations>*>((FCSIndirectStateWithLocations<FCSStateWithLocations>***)Array, OldSize, NewSize);
00593         break;
00594     case FC_TALON_DEBUG_STATE:
00595         Realloc<FCSDebugTalonStateWithLocations*>((FCSDebugTalonStateWithLocations***)Array, OldSize, NewSize);
00596         break;
00597     case FC_TALON_COMPACT_STATE:
00598         Realloc<FCSCompactTalonStateWithLocations*>((FCSCompactTalonStateWithLocations***)Array, OldSize, NewSize);
00599         break;
00600     case FC_TALON_INDIRECT_STATE:
00601         Realloc<FCSIndirectTalonStateWithLocations*>((FCSIndirectTalonStateWithLocations***)Array, OldSize, NewSize);
00602         break;
00603     default:
00604         //this shouldn't happen
00605         assert(false);
00606     }
00607 }
00608 
00609 
00610 FCSStateWithLocations* CreateInitialState(const char *String, int NumberOfFreecells, 
00611                                           int NumberOfStacks, int NumberOfDecks, FCSTalonType TalonType)
00612 {
00613     if (TalonType == FCS_TALON_NONE)
00614         return FCSStateWithLocations::CreateInitialState(String, NumberOfFreecells, 
00615                                                          NumberOfStacks, NumberOfDecks);
00616 
00617     return FCSTalonStateWithLocations::CreateInitialState(String, NumberOfFreecells, 
00618                                                           NumberOfStacks, NumberOfDecks, TalonType);
00619 }
00620 
00621 int MD5StateWithLocationsHashAlgorithm::Hash(const FCSStateWithLocations* Key)
00622 {
00623     unsigned char HashValue[MD5_HASHBYTES];
00624     int RealHashValue;
00625 
00626     m_MD5Hash.Init();
00627     m_MD5Hash.Update((unsigned char*)(((FCSStateWithLocations*)Key)->GetState()), ((FCSStateWithLocations*)Key)->GetState()->GetClassSize());
00628     m_MD5Hash.Final(HashValue);
00629 
00630     RealHashValue = (*(int*)HashValue);
00631     if (RealHashValue < 0)
00632     {
00633         // This is a bit mask that nullifies the sign bit of the
00634         // number so it will always be positive
00635         RealHashValue &= (~(1<<((sizeof(RealHashValue)<<3)-1)));
00636     }
00637 
00638     return RealHashValue;
00639 }

Generated on Sat Nov 5 11:20:15 2005 for Cpp Freecell Solver by  doxygen 1.4.4