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

FCSTalonSolvingAlgorithm.cpp

Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #include "FCSTalonSolvingAlgorithm.h"
00010 #include "FCSAStarSolvingAlgorithm.h"
00011 #include "FCSBFSSolvingAlgorithm.h"
00012 #include "FCSDFSSolvingAlgorithm.h"
00013 #include "FCSRandomDFSSolvingAlgorithm.h"
00014 #include "FCSSoftDFSSolvingAlgorithm.h"
00015 
00016 FCSTalonSolvingAlgorithm::FCSTalonSolvingAlgorithm() : FCSFreecellSolvingAlgorithm()
00017 {
00018     InitFCSTalonSolvingAlgorithm();
00019 }
00020 
00021 FCSTalonSolvingAlgorithm::FCSTalonSolvingAlgorithm(FCCommandLineArguments* CommandLine) : FCSFreecellSolvingAlgorithm(CommandLine)
00022 {
00023     InitFCSTalonSolvingAlgorithm();
00024 
00025     m_TalonType = CommandLine->GetTalonType();
00026 }
00027 
00028 void FCSTalonSolvingAlgorithm::InitFCSTalonSolvingAlgorithm()
00029 {
00030     m_TalonType = FCS_TALON_NONE;
00031     m_TalonsHash = NULL;
00032 }
00033 
00034 FCSTalonSolvingAlgorithm::~FCSTalonSolvingAlgorithm()
00035 {
00036     if (m_TalonsHash != NULL)
00037     {
00038         m_TalonsHash->DeleteItems();
00039         delete m_TalonsHash;
00040     }
00041 }
00042 
00043 FCSTalonSolvingAlgorithm* FCSTalonSolvingAlgorithm::Create(FCCommandLineArguments* CommandLine)
00044 {
00045 
00046     if (CommandLine == NULL)
00047         return NULL;
00048 
00049     //determine with solving algorithm to create
00050     switch(CommandLine->GetSolvingMethodType())
00051     {
00052     case FCS_METHOD_HARD_DFS:
00053         return new FCSDFSSolvingAlgorithm<FCSTalonSolvingAlgorithm>(CommandLine);
00054     case FCS_METHOD_SOFT_DFS:
00055         return new FCSSoftDFSSolvingAlgorithm<FCSTalonSolvingAlgorithm>(CommandLine);
00056     case FCS_METHOD_BFS:
00057         return new FCSBFSSolvingAlgorithm<FCSTalonSolvingAlgorithm>(CommandLine);
00058     case FCS_METHOD_A_STAR:
00059         return new FCSAStarSolvingAlgorithm<FCSTalonSolvingAlgorithm>(CommandLine);
00060     case FCS_METHOD_RANDOM_DFS:
00061         return new FCSRandomDFSSolvingAlgorithm<FCSTalonSolvingAlgorithm>(CommandLine);
00062     default:
00063         return NULL;
00064     }
00065 
00066     return NULL;
00067 }
00068 
00069 FCSStateSolvingReturnCodes FCSTalonSolvingAlgorithm::RunTest(int TestNumber, FCSStateWithLocations*  StateWithLocations,
00070                                                       int Depth, int NumberOfFreeStacks,
00071                                                       int NumberOfFreecells,
00072                                                       FCSDerivedStatesList* DerivedStateList)
00073 {
00074     switch(TestNumber)
00075     {
00076     case 0:
00077         return MoveTopStackCardsToFounds(StateWithLocations, Depth, NumberOfFreeStacks,
00078                                         NumberOfFreecells, DerivedStateList);
00079     case 1:
00080         return MoveNonTopStackCardsToFounds(StateWithLocations, Depth, NumberOfFreeStacks,
00081                                         NumberOfFreecells, DerivedStateList);
00082     case 2:
00083         return MoveStackCardsToDifferentStacks(StateWithLocations, Depth, NumberOfFreeStacks,
00084                                         NumberOfFreecells, DerivedStateList);
00085     case 3:
00086         return MoveStackCardsToAParentOnTheSameStack(StateWithLocations, Depth, NumberOfFreeStacks,
00087                                         NumberOfFreecells, DerivedStateList);
00088     case 4:
00089         return MoveSequencesToFreeStacks(StateWithLocations, Depth, NumberOfFreeStacks,
00090                                         NumberOfFreecells, DerivedStateList);
00091     case 5:
00092         return MoveCardsToADifferentParent(StateWithLocations, Depth, NumberOfFreeStacks,
00093                                         NumberOfFreecells, DerivedStateList);
00094     case 6:
00095         return GetCardFromKlondikeTalon(StateWithLocations, Depth, NumberOfFreeStacks,
00096                                         NumberOfFreecells, DerivedStateList);
00097     default:
00098         return FCS_STATE_IS_NOT_SOLVEABLE;
00099     }
00100 }
00101 
00102 void FCSTalonSolvingAlgorithm::InitSolve(FCSStateWithLocations* InitState)
00103 {
00104     // Initialize the Talon's Cache
00105     if (m_TalonType == FCS_TALON_KLONDIKE)
00106     {
00107         m_TalonsHash = new FCInternalHash<FCSTalonStateData, void>(TALON_CACHE_SIZE, 
00108                     &m_TalonCompareFunction, &m_TalonHashFunction, DELETE_HASH_ITEM);
00109     }
00110 
00111     FCSFreecellData::InitSolve(InitState);
00112 }
00113 
00114 FCSStateSolvingReturnCodes FCSTalonSolvingAlgorithm::CheckAndAddState(FCSStateWithLocations* NewState,
00115                          FCSStateWithLocations** ExistingState,
00116                          int Depth)
00117 {
00118     if (((m_MaxNumberOfCheckedStates >= 0) &&
00119         (m_NumberOfCheckedStates >= m_MaxNumberOfCheckedStates)) ||
00120         ((m_MaxNumberOfStatesInCollection >= 0) &&
00121         (m_NumberOfStatesInCollection >= m_MaxNumberOfStatesInCollection)))
00122     {
00123         return FCS_STATE_BEGIN_SUSPEND_PROCESS;
00124     }
00125 
00126     if ((m_MaxDepth >= 0) &&
00127         (m_MaxDepth <= Depth))
00128     {
00129         return FCS_STATE_EXCEEDS_MAX_DEPTH;
00130     }
00131 
00132     NewState->CanonizeState(m_NumberOfFreecells, m_NumberOfStacks);
00133     NewState->CacheStacks(m_StackStorage, m_NumberOfStacks);
00134     ((FCSTalonStateWithLocations*)NewState)->CacheTalonStacks(m_TalonsHash);
00135 
00136     if (m_StateStorage->CheckAndInsert(ExistingState, NewState))
00137     {
00138         // The new state was not found in the cache, and it was already inserted
00139         m_NumberOfStatesInCollection++;
00140         return FCS_STATE_DOES_NOT_EXIST;
00141     }
00142 
00143     return FCS_STATE_ALREADY_EXISTS;
00144 }
00145 
00146 FCSStateSolvingReturnCodes FCSTalonSolvingAlgorithm::GetCardFromKlondikeTalon(FCSStateWithLocations*  StateWithLocations,
00147                               int Depth,
00148                               int NumberOfFreeStacks,
00149                               int NumberOfFreecells,
00150                               FCSDerivedStatesList* DerivedStateList)
00151 {
00152     if (m_TalonType != FCS_TALON_KLONDIKE)
00153     {
00154         return FCS_STATE_IS_NOT_SOLVEABLE;
00155     }
00156 
00157     FCSStateWithLocations *NewStateWithLocations;
00158     FCSTalonStateData* TempTalonData = CreateTalonStateData();
00159     FCSMoveStack *Moves = CreateMoveStack();
00160     FCSMove *TempMove = FCSMove::Create();
00161 
00162     FCSStateSolvingReturnCodes Check;
00163     int NumberOfRedealsDone = 0,
00164         NumberOfCardsMoved[2] = {0,0};
00165 
00166     bool FirstIteration = true;
00167 
00168     FCSCard *CardToCheck = FCSCard::Create(),
00169             *TopCard = FCSCard::Create();
00170     
00171     // Duplicate the talon and its parameters into talon_temp
00172     TempTalonData->Copy(((FCSTalonStateWithLocations*)StateWithLocations)->GetTalonData());
00173 
00174     char SavedStackPosition = TempTalonData->GetKlondikeTalonStackPosition();
00175 
00176     // Make sure we redeal the talon only once
00177     int NumberOfRedealsLeft = TempTalonData->GetKlondikeNumberOfRedealsLeft();
00178     if (NumberOfRedealsLeft != 0)
00179         NumberOfRedealsLeft = 1;
00180 
00181     while (NumberOfRedealsLeft >= 0)
00182     {
00183         if ((TempTalonData->GetKlondikeTalonStackPosition() == -1) &&
00184             (TempTalonData->GetKlondikeTalonQueuePosition() == TempTalonData->GetKlondikeTalonLength()))
00185             break;
00186 
00187         if ((!FirstIteration) || (TempTalonData->GetKlondikeTalonStackPosition() == -1))
00188         {
00189             if (TempTalonData->GetKlondikeTalonStackPosition() == TempTalonData->GetKlondikeTalonLength() - 1)
00190             {
00191                 if (NumberOfRedealsLeft > 0)
00192                 {
00193                     //no cards left to redeal
00194                     TempTalonData->KlondikeTalonRedealBare();
00195 
00196                     NumberOfRedealsLeft--;
00197                     NumberOfRedealsDone++;
00198                 }
00199                 else
00200                 {
00201                     break;
00202                 }
00203             }
00204             else if ((NumberOfRedealsLeft <= 0) &&
00205                      (TempTalonData->GetKlondikeTalonStackPosition() >= SavedStackPosition - 1))
00206             {
00207                 break;
00208             }
00209 
00210             TempTalonData->KlondikeTalonQueueToStack();
00211             NumberOfCardsMoved[NumberOfRedealsDone]++;
00212         }
00213 
00214         FirstIteration = false;
00215 
00216         CardToCheck->Copy(TempTalonData->GetKlondikeTalonTopCard());
00217         if (CardToCheck->IsEmptyCard())
00218             continue;
00219 
00220         //check if the card can go on a foundation
00221         for(int Deck=0;Deck < m_NumberOfDecks;Deck++)
00222         {
00223             if (StateWithLocations->GetFoundation(Deck*4 + CardToCheck->GetSuit()) != CardToCheck->GetCardNumber() - 1)
00224                 continue;
00225 
00226             // We can put it there
00227             CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
00228 
00229             ((FCSTalonStateWithLocations*)NewStateWithLocations)->GetTalonData()->Copy(TempTalonData);
00230 
00231             for(int a=0;a<=NumberOfRedealsDone;a++)
00232             {
00233                 TempMove->SetType(FCS_MOVE_TYPE_KLONDIKE_FLIP_TALON);
00234                 TempMove->SetNumberOfCardsFlipped(NumberOfCardsMoved[a]);
00235                 Moves->Push(TempMove);
00236                 if (a != NumberOfRedealsDone)
00237                 {
00238                     TempMove->SetType(FCS_MOVE_TYPE_KLONDIKE_REDEAL_TALON);
00239                     Moves->Push(TempMove);
00240                 }
00241             }
00242 
00243             NewStateWithLocations->IncrementFoundation(Deck*4+CardToCheck->GetSuit());
00244             ((FCSTalonStateWithLocations*)NewStateWithLocations)->DecrementKlondikeTalonStack();
00245 
00246             TempMove->SetType(FCS_MOVE_TYPE_KLONDIKE_TALON_TO_FOUNDATION);
00247             TempMove->SetFoundation(Deck*4+CardToCheck->GetSuit());
00248             Moves->Push(TempMove);
00249 
00250 
00251             // The last move needs to be FCS_MOVE_TYPE_CANONIZE
00252             // because it indicates that the internal order of the 
00253             // stacks
00254             // and freecells may have changed.
00255             TempMove->SetType(FCS_MOVE_TYPE_CANONIZE);
00256             Moves->Push(TempMove);
00257 
00258             if (CheckStateEnd(&NewStateWithLocations, StateWithLocations, &DerivedStateList, 
00259                               &Moves, &TempMove, Depth, &Check))
00260             {
00261                 delete TempTalonData;
00262                 delete [] Moves;
00263                 delete TempMove;
00264                 delete CardToCheck;
00265                 delete TopCard;
00266                 return Check;
00267             }
00268 
00269             break;
00270         }
00271         
00272         //check if the card can go on a stack
00273         for(int Stack=0; Stack<m_NumberOfStacks; Stack++)
00274         {
00275             TopCard->Copy(StateWithLocations->GetStackCard(Stack, StateWithLocations->GetStackLength(Stack)-1));
00276 
00277             if ((!IsParentCard(CardToCheck, TopCard)) &&
00278                 ((StateWithLocations->GetStackLength(Stack) > 0) || 
00279                  (m_EmptyStacksFill == FCS_ES_FILLED_BY_NONE) || 
00280                  ((m_EmptyStacksFill == FCS_ES_FILLED_BY_KINGS_ONLY) && (CardToCheck->GetCardNumber() != 13))
00281                 )
00282                )
00283                 continue;
00284 
00285             // We have a card in the talon that we can move to the stack, so let's move it
00286             CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
00287 
00288             ((FCSTalonStateWithLocations*)NewStateWithLocations)->GetTalonData()->Copy(TempTalonData);
00289 
00290             for(int a=0;a<=NumberOfRedealsDone;a++)
00291             {
00292                 TempMove->SetType(FCS_MOVE_TYPE_KLONDIKE_FLIP_TALON);
00293                 TempMove->SetNumberOfCardsFlipped(NumberOfCardsMoved[a]);
00294                 Moves->Push(TempMove);
00295                 if (a != NumberOfRedealsDone)
00296                 {
00297                     TempMove->SetType(FCS_MOVE_TYPE_KLONDIKE_REDEAL_TALON);
00298                     Moves->Push(TempMove);
00299                 }
00300             }
00301 
00302             NewStateWithLocations->PushCardIntoStack(Stack, ((FCSTalonStateWithLocations*)NewStateWithLocations)->GetTalonData()->GetKlondikeTalonTopCard());
00303             ((FCSTalonStateWithLocations*)NewStateWithLocations)->DecrementKlondikeTalonStack();
00304 
00305             TempMove->SetType(FCS_MOVE_TYPE_KLONDIKE_TALON_TO_STACK);
00306             TempMove->SetDestStack(Stack);
00307             Moves->Push(TempMove);
00308 
00309             if (CheckStateEnd(&NewStateWithLocations, StateWithLocations, &DerivedStateList, 
00310                               &Moves, &TempMove, Depth, &Check))
00311             {
00312                 delete TempTalonData;
00313                 delete [] Moves;
00314                 delete TempMove;
00315                 delete CardToCheck;
00316                 delete TopCard;
00317                 return Check;
00318             }
00319         }
00320     }
00321 
00322     delete TempTalonData;
00323     delete [] Moves;
00324     delete TempMove;
00325     delete CardToCheck;
00326     delete TopCard;
00327 
00328     return FCS_STATE_IS_NOT_SOLVEABLE;
00329 }

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