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

FCSFreecellSolvingAlgorithm.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 "FCSFreecellSolvingAlgorithm.h"
00012 #include "FCSAStarSolvingAlgorithm.h"
00013 #include "FCSBFSSolvingAlgorithm.h"
00014 #include "FCSDFSSolvingAlgorithm.h"
00015 #include "FCSRandomDFSSolvingAlgorithm.h"
00016 #include "FCSSoftDFSSolvingAlgorithm.h"
00017 #include "FCSStateStorage.h"
00018 
00019 FCSFreecellSolvingAlgorithm::FCSFreecellSolvingAlgorithm() : FCSFreecellData(), FCSFreecellAlgorithm()
00020 {
00021 }
00022 
00023 FCSFreecellSolvingAlgorithm::FCSFreecellSolvingAlgorithm(FCCommandLineArguments* CommandLine) : FCSFreecellData(CommandLine), FCSFreecellAlgorithm()
00024 {
00025 }
00026 
00027 FCSFreecellSolvingAlgorithm::~FCSFreecellSolvingAlgorithm()
00028 {
00029 }
00030 
00031 FCSFreecellSolvingAlgorithm* FCSFreecellSolvingAlgorithm::Create(FCCommandLineArguments* CommandLine)
00032 {
00033 
00034     if (CommandLine == NULL)
00035         return NULL;
00036 
00037     //determine with solving algorithm to create
00038     switch(CommandLine->GetSolvingMethodType())
00039     {
00040     case FCS_METHOD_HARD_DFS:
00041         return new FCSDFSSolvingAlgorithm<FCSFreecellSolvingAlgorithm>(CommandLine);
00042         break;
00043     case FCS_METHOD_SOFT_DFS:
00044         return new FCSSoftDFSSolvingAlgorithm<FCSFreecellSolvingAlgorithm>(CommandLine);
00045         break;
00046     case FCS_METHOD_BFS:
00047         return new FCSBFSSolvingAlgorithm<FCSFreecellSolvingAlgorithm>(CommandLine);
00048         break;
00049     case FCS_METHOD_A_STAR:
00050         return new FCSAStarSolvingAlgorithm<FCSFreecellSolvingAlgorithm>(CommandLine);
00051         break;
00052     case FCS_METHOD_RANDOM_DFS:
00053         return new FCSRandomDFSSolvingAlgorithm<FCSFreecellSolvingAlgorithm>(CommandLine);
00054         break;
00055     default:
00056         return NULL;
00057     }
00058 
00059     return NULL;
00060 }
00061 
00062 void FCSFreecellSolvingAlgorithm::FlipTopCard(FCSStateWithLocations *State, int Stack,
00063                                       FCSMove* Move, FCSMoveStack** MoveStack)
00064 {
00065     if (State->GetStackLength(Stack) != 0)
00066     {
00067         if (State->GetStackCard(Stack, State->GetStackLength(Stack) - 1)->GetFlipped() == 1)
00068         {
00069             State->GetStackCard(Stack, State->GetStackLength(Stack) - 1)->SetFlipped(0);
00070             Move->SetType(FCS_MOVE_TYPE_FLIP_CARD);
00071             Move->SetSourceStack(Stack);
00072             (*MoveStack)->Push(Move);
00073         }
00074     }
00075 }
00076 
00077 FCSStateSolvingReturnCodes FCSFreecellSolvingAlgorithm::RunTest(int TestNumber, FCSStateWithLocations*  StateWithLocations,
00078                                                       int Depth, int NumberOfFreeStacks,
00079                                                       int NumberOfFreecells,
00080                                                       FCSDerivedStatesList* DerivedStateList)
00081 {
00082     switch(TestNumber)
00083     {
00084     case 0:
00085         return MoveTopStackCardsToFounds(StateWithLocations, Depth, NumberOfFreeStacks,
00086                                         NumberOfFreecells, DerivedStateList);
00087     case 1:
00088         return MoveFreecellCardsToFounds(StateWithLocations, Depth, NumberOfFreeStacks,
00089                                         NumberOfFreecells, DerivedStateList);
00090     case 2:
00091         return MoveFreecellCardsToTopOfStacks(StateWithLocations, Depth, NumberOfFreeStacks,
00092                                         NumberOfFreecells, DerivedStateList);
00093     case 3:
00094         return MoveNonTopStackCardsToFounds(StateWithLocations, Depth, NumberOfFreeStacks,
00095                                         NumberOfFreecells, DerivedStateList);
00096     case 4:
00097         return MoveStackCardsToDifferentStacks(StateWithLocations, Depth, NumberOfFreeStacks,
00098                                         NumberOfFreecells, DerivedStateList);
00099     case 5:
00100         return MoveStackCardsToAParentOnTheSameStack(StateWithLocations, Depth, NumberOfFreeStacks,
00101                                         NumberOfFreecells, DerivedStateList);
00102     case 6:
00103         return MoveSequencesToFreeStacks(StateWithLocations, Depth, NumberOfFreeStacks,
00104                                         NumberOfFreecells, DerivedStateList);
00105     case 7:
00106         return MoveFreecellCardsToEmptyStack(StateWithLocations, Depth, NumberOfFreeStacks,
00107                                         NumberOfFreecells, DerivedStateList);
00108     case 8:
00109         return MoveCardsToADifferentParent(StateWithLocations, Depth, NumberOfFreeStacks,
00110                                         NumberOfFreecells, DerivedStateList);
00111     case 9:
00112         return EmptyStackIntoFreecells(StateWithLocations, Depth, NumberOfFreeStacks,
00113                                         NumberOfFreecells, DerivedStateList);
00114     default:
00115         return FCS_STATE_IS_NOT_SOLVEABLE;
00116     }
00117 }
00118 
00119 FCSStateSolvingReturnCodes FCSFreecellSolvingAlgorithm::MoveTopStackCardsToFounds(FCSStateWithLocations*  StateWithLocations,
00120                               int Depth,
00121                               int NumberOfFreeStacks,
00122                               int NumberOfFreecells,
00123                               FCSDerivedStatesList* DerivedStateList)
00124 {
00125     FCSStateWithLocations *NewStateWithLocations;
00126 
00127     FCSCard *Card, 
00128         *TempCard = FCSCard::Create();
00129     FCSStateSolvingReturnCodes Check;
00130 
00131     FCSMoveStack *Moves = CreateMoveStack();
00132     FCSMove *TempMove = FCSMove::Create();
00133 
00134     for(int Stack=0;Stack<m_NumberOfStacks;Stack++)
00135     {
00136         if (StateWithLocations->GetStackLength(Stack) <= 0)
00137             continue;
00138 
00139         // Get the top card in the stack
00140         Card = StateWithLocations->GetStackCard(Stack, StateWithLocations->GetStackLength(Stack)-1);
00141         for(int Deck=0;Deck < m_NumberOfDecks;Deck++)
00142         {
00143             if (StateWithLocations->GetFoundation(Deck*4 + Card->GetSuit()) != Card->GetCardNumber() - 1)
00144                 continue;
00145 
00146             // We can put it there
00147             CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
00148 
00149             NewStateWithLocations->PopStackCard(Stack, TempCard);
00150             NewStateWithLocations->IncrementFoundation(Deck*4+Card->GetSuit());
00151 
00152             TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_FOUNDATION);
00153             TempMove->SetSourceStack(Stack);
00154             TempMove->SetFoundation(Deck*4+Card->GetSuit());
00155 
00156             Moves->Push(TempMove);
00157 
00158             FlipTopCard(NewStateWithLocations, Stack, TempMove, &Moves);
00159 
00160             // The last move needs to be FCS_MOVE_TYPE_CANONIZE
00161             // because it indicates that the internal order of the 
00162             // stacks
00163             // and freecells may have changed.
00164             TempMove->SetType(FCS_MOVE_TYPE_CANONIZE);
00165             Moves->Push(TempMove);
00166 
00167             if (CheckStateEnd(&NewStateWithLocations, StateWithLocations, &DerivedStateList, 
00168                               &Moves, &TempMove, Depth, &Check))
00169             {
00170                 delete TempMove;
00171                 delete TempCard;
00172                 return Check;
00173             }
00174 
00175             break;
00176         }
00177     }
00178 
00179     delete [] Moves;
00180     delete TempMove;
00181     delete TempCard;
00182 
00183     return FCS_STATE_IS_NOT_SOLVEABLE;
00184 }
00185 
00186 FCSStateSolvingReturnCodes FCSFreecellSolvingAlgorithm::MoveFreecellCardsToFounds(FCSStateWithLocations*  StateWithLocations,
00187                               int Depth,
00188                               int NumberOfFreeStacks,
00189                               int NumberOfFreecells,
00190                               FCSDerivedStatesList* DerivedStateList)
00191 {
00192     FCSStateWithLocations *NewStateWithLocations;
00193     FCSCard *Card;
00194     FCSStateSolvingReturnCodes Check;
00195 
00196     FCSMoveStack *Moves = CreateMoveStack();
00197     FCSMove *TempMove = FCSMove::Create();
00198 
00199     // Now check the same for the free cells
00200     for(int Freecell=0;Freecell<m_NumberOfFreecells;Freecell++)
00201     {
00202         Card = StateWithLocations->GetFreecellCard(Freecell);
00203         if (Card->GetCardNumber() <= 0)
00204             continue;
00205 
00206         for(int Deck=0;Deck<m_NumberOfDecks;Deck++)
00207         {
00208             if (StateWithLocations->GetFoundation(Deck*4+Card->GetSuit()) != Card->GetCardNumber() - 1)
00209                 continue;
00210 
00211             // We can put it there
00212             CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
00213 
00214             NewStateWithLocations->EmptyFreecell(Freecell);
00215             NewStateWithLocations->IncrementFoundation(Deck*4+Card->GetSuit());
00216 
00217             TempMove->SetType(FCS_MOVE_TYPE_FREECELL_TO_FOUNDATION);
00218             TempMove->SetSourceFreecell(Freecell);
00219             TempMove->SetFoundation(Deck*4+Card->GetSuit());
00220 
00221             Moves->Push(TempMove);
00222 
00223             TempMove->SetType(FCS_MOVE_TYPE_CANONIZE);
00224             Moves->Push(TempMove);
00225 
00226             if (CheckStateEnd(&NewStateWithLocations, StateWithLocations, &DerivedStateList, 
00227                               &Moves, &TempMove, Depth, &Check))
00228             {
00229                 delete TempMove;
00230                 return Check;
00231             }
00232         }
00233     }
00234 
00235     delete TempMove;
00236     delete [] Moves;
00237 
00238     return FCS_STATE_IS_NOT_SOLVEABLE;
00239 }
00240 
00241 FCSStateSolvingReturnCodes FCSFreecellSolvingAlgorithm::MoveFreecellCardsToTopOfStacks(FCSStateWithLocations*  StateWithLocations,
00242                                   int Depth,
00243                                   int NumberOfFreeStacks,
00244                                   int NumberOfFreecells,
00245                                   FCSDerivedStatesList* DerivedStateList)
00246 {
00247     FCSStateWithLocations *NewStateWithLocations;
00248     int DestinationCardNumber, NumberOfCardsToRelocate, 
00249         FreecellsToFill, FreeStacksToFill, a, b;
00250     FCSCard *DestinationCard, *SourceCard, *DestBelowCard, 
00251             *TempCard = FCSCard::Create();
00252     FCSStateSolvingReturnCodes Check;
00253     bool IsSequenceInDestination;
00254 
00255     FCSMove *TempMove = FCSMove::Create();
00256     FCSMoveStack *Moves = CreateMoveStack();
00257 
00258     // Let's try to put cards in the freecells on top of stacks
00259     for(int DestinationStack=0;DestinationStack<m_NumberOfStacks;DestinationStack++)
00260     {
00261         DestinationCardNumber = StateWithLocations->GetStackLength(DestinationStack);
00262 
00263         // If the stack is not empty we can proceed
00264         if (DestinationCardNumber <= 0)
00265             continue;
00266 
00267         // Let's search for a suitable card in the stack
00268         for(int DestCard=DestinationCardNumber-1;DestCard>=0;DestCard--)
00269         {
00270             DestinationCard = StateWithLocations->GetStackCard(DestinationStack, DestCard);
00271 
00272             // Scan the freecells
00273             for(int Freecell=0;Freecell<m_NumberOfFreecells;Freecell++)
00274             {
00275                 SourceCard = StateWithLocations->GetFreecellCard(Freecell);
00276 
00277                 // If the freecell is not empty and dest_card is its parent
00278                 if ( (SourceCard->GetCardNumber() <= 0) || (!IsParentCard(SourceCard,DestinationCard)))
00279                     continue;
00280 
00281                 // Let's check if we can put it there
00282                 // Check if the destination card is already below a suitable card
00283                 IsSequenceInDestination = false;
00284                 if (DestinationCardNumber - 1 > DestCard)
00285                 {
00286                     DestBelowCard = StateWithLocations->GetStackCard(DestinationStack, DestCard+1);
00287                     if (IsParentCard(DestBelowCard, DestinationCard))
00288                     {
00289                         IsSequenceInDestination = true;
00290                     }
00291                 }
00292 
00293 
00294                 if (IsSequenceInDestination)
00295                     continue;
00296 
00297                 NumberOfCardsToRelocate = DestinationCardNumber - DestCard - 1;
00298                 FreecellsToFill = min(NumberOfCardsToRelocate, NumberOfFreecells);
00299                 NumberOfCardsToRelocate -= FreecellsToFill;
00300 
00301                 if (m_EmptyStacksFill == FCS_ES_FILLED_BY_ANY_CARD)
00302                 {
00303                     FreeStacksToFill = min(NumberOfCardsToRelocate, NumberOfFreeStacks);
00304                     NumberOfCardsToRelocate -= FreeStacksToFill;
00305                 }
00306                 else
00307                 {
00308                     FreeStacksToFill = 0;
00309                 }
00310 
00311                 if (NumberOfCardsToRelocate != 0)
00312                     continue;
00313 
00314                 //  We can move it
00315                 CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
00316 
00317                 // Fill the freecells with the top cards
00318                 for(a=0 ; a<FreecellsToFill ; a++)
00319                 {
00320                     // Find a vacant freecell
00321                     for(b=0;b<m_NumberOfFreecells;b++)
00322                     {
00323                         if (NewStateWithLocations->GetFreecellCardNumber(b) == 0)
00324                             break;
00325                     }
00326 
00327                     NewStateWithLocations->PopStackCard(DestinationStack, TempCard);
00328 
00329                     NewStateWithLocations->PutCardInFreecell(b, TempCard);
00330 
00331                     TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_FREECELL);
00332                     TempMove->SetSourceStack(DestinationStack);
00333                     TempMove->SetDestFreecell(b);
00334                     Moves->Push(TempMove);
00335                 }
00336 
00337                 // Fill the free stacks with the cards below them
00338                 for(a=0; a <FreeStacksToFill; a++)
00339                 {
00340                     // Find a vacant stack
00341                     for(b=0;b<m_NumberOfStacks;b++)
00342                     {
00343                         if (NewStateWithLocations->GetStackLength(b) == 0)
00344                             break;
00345                     }
00346 
00347                     NewStateWithLocations->PopStackCard(DestinationStack, TempCard);
00348                     NewStateWithLocations->PushCardIntoStack(b, TempCard);
00349                     TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
00350                     TempMove->SetSourceStack(DestinationStack);
00351                     TempMove->SetDestStack(b);
00352                     TempMove->SetNumberOfCardsInSequence(1);
00353                     Moves->Push(TempMove);
00354                 }
00355 
00356                 // Now put the freecell card on top of the stack
00357                 NewStateWithLocations->PushCardIntoStack(DestinationStack, SourceCard);
00358                 NewStateWithLocations->EmptyFreecell(Freecell);
00359                 TempMove->SetType(FCS_MOVE_TYPE_FREECELL_TO_STACK);
00360                 TempMove->SetSourceFreecell(Freecell);
00361                 TempMove->SetDestStack(DestinationStack);
00362                 Moves->Push(TempMove);
00363 
00364                 if (CheckStateEnd(&NewStateWithLocations, StateWithLocations, &DerivedStateList, 
00365                       &Moves, &TempMove, Depth, &Check))
00366                 {
00367                     delete TempMove;
00368                     delete TempCard;
00369                     return Check;
00370                 }
00371             }
00372         }
00373     }
00374 
00375     delete [] Moves;
00376     delete TempMove;
00377     delete TempCard;
00378 
00379     return FCS_STATE_IS_NOT_SOLVEABLE;
00380 }
00381 
00382 FCSStateSolvingReturnCodes FCSFreecellSolvingAlgorithm::MoveNonTopStackCardsToFounds(FCSStateWithLocations*  StateWithLocations,
00383                                   int Depth,
00384                                   int NumberOfFreeStacks,
00385                                   int NumberOfFreecells,
00386                                   FCSDerivedStatesList* DerivedStateList)
00387 {
00388     FCSStateWithLocations *NewStateWithLocations;
00389     FCSCard *Card, 
00390         *TempCard = FCSCard::Create();
00391     FCSStateSolvingReturnCodes Check;
00392 
00393     int NumberOfCards, a, b;
00394 
00395     FCSMoveStack *Moves = CreateMoveStack();
00396     FCSMove *TempMove = FCSMove::Create();
00397 
00398     // Now let's check if a card that is under some other cards can be placed 
00399     // in the foundations.
00400 
00401     for(int Stack=0;Stack<m_NumberOfStacks;Stack++)
00402     {
00403         NumberOfCards = StateWithLocations->GetStackLength(Stack);
00404 
00405          // We starts from cards_num-2 because the top card is already covered
00406          // by move_top_stack_cards_to_founds.
00407         for(int c=NumberOfCards-2;c>=0;c--)
00408         {
00409             Card = StateWithLocations->GetStackCard(Stack, c);
00410             for(int Deck=0;Deck<m_NumberOfDecks;Deck++)
00411             {
00412                 if (StateWithLocations->GetFoundation(Deck*4+Card->GetSuit()) != Card->GetCardNumber() -1)
00413                     continue;
00414 
00415                 // The card is foundation-able. Now let's check if we 
00416                 // can move the cards above it to the freecells and stacks
00417 
00418                 if ((NumberOfFreecells + 
00419                     ((m_EmptyStacksFill == FCS_ES_FILLED_BY_ANY_CARD) ? 
00420                         NumberOfFreeStacks : 
00421                         0
00422                     )) 
00423                         >= NumberOfCards-(c+1))
00424                 {
00425                     // We can move it
00426                     CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
00427 
00428                     // Fill the freecells with the top cards
00429                     for(a=0 ; a<min(NumberOfFreecells, NumberOfCards-(c+1)) ; a++)
00430                     {
00431                         // Find a vacant freecell
00432                         for(b=0; b<m_NumberOfFreecells; b++)
00433                         {
00434                             if (NewStateWithLocations->GetFreecellCardNumber(b) == 0)
00435                                 break;
00436                         }
00437 
00438                         NewStateWithLocations->PopStackCard(Stack, TempCard);
00439                         NewStateWithLocations->PutCardInFreecell(b, TempCard);
00440 
00441                         TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_FREECELL);
00442                         TempMove->SetSourceStack(Stack);
00443                         TempMove->SetDestFreecell(b);
00444     
00445                         Moves->Push(TempMove);
00446 
00447                         FlipTopCard(NewStateWithLocations, Stack, TempMove, &Moves);
00448                     }
00449 
00450                     // Fill the free stacks with the cards below them
00451                     for(a=0; a < NumberOfCards-(c+1) - min(NumberOfFreecells, NumberOfCards-(c+1)) ; a++)
00452                     {
00453                         /* Find a vacant stack */
00454                         for(b=0;b<m_NumberOfStacks;b++)
00455                         {
00456                             if (NewStateWithLocations->GetStackLength(b) == 0)
00457                                 break;
00458                         }
00459 
00460                         NewStateWithLocations->PopStackCard(Stack, TempCard);
00461                         NewStateWithLocations->PushCardIntoStack(b, TempCard);
00462 
00463                         TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
00464                         TempMove->SetSourceStack(Stack);
00465                         TempMove->SetDestStack(b);
00466                         TempMove->SetNumberOfCardsInSequence(1);
00467 
00468                         Moves->Push(TempMove);
00469 
00470                         FlipTopCard(NewStateWithLocations, Stack, TempMove, &Moves);
00471                     }
00472 
00473                     NewStateWithLocations->PopStackCard(Stack, TempCard);
00474                     NewStateWithLocations->IncrementFoundation(Deck*4+TempCard->GetSuit());
00475 
00476                     TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_FOUNDATION);
00477                     TempMove->SetSourceStack(Stack);
00478                     TempMove->SetFoundation(Deck*4+TempCard->GetSuit());
00479 
00480                     Moves->Push(TempMove);
00481 
00482                     FlipTopCard(NewStateWithLocations, Stack, TempMove, &Moves);
00483 
00484                     if (CheckStateEnd(&NewStateWithLocations, StateWithLocations, &DerivedStateList, 
00485                                   &Moves, &TempMove, Depth, &Check))
00486                     {
00487                         delete TempCard;
00488                         delete TempMove;
00489                         return Check;
00490                     }
00491                 }
00492                 break;
00493             }
00494         }
00495     }
00496 
00497     delete [] Moves;
00498     delete TempMove;
00499     delete TempCard;
00500 
00501     return FCS_STATE_IS_NOT_SOLVEABLE;
00502 }
00503 
00504 FCSStateSolvingReturnCodes FCSFreecellSolvingAlgorithm::MoveStackCardsToDifferentStacks(FCSStateWithLocations*  StateWithLocations,
00505                                   int Depth,
00506                                   int NumberOfFreeStacks,
00507                                   int NumberOfFreecells,
00508                                   FCSDerivedStatesList* DerivedStateList)
00509 {
00510     FCSStateWithLocations *NewStateWithLocations;
00511     FCSCard *Card, 
00512             *TempCard = FCSCard::Create(), 
00513             *DestCard, *DestBelowCard;
00514     FCSStateSolvingReturnCodes Check;
00515 
00516     int NumberOfCards, SequenceEnd, 
00517         NumberOfDestinationCards, NumberOfCardsToRelocate,
00518         FreecellsToFill, FreeStacksToFill, a, b;
00519 
00520     bool IsSequenceInDestination;
00521 
00522     FCSMoveStack *Moves = CreateMoveStack();
00523     FCSMove *TempMove = FCSMove::Create();
00524 
00525     // Now let's try to move a card from one stack to the other
00526     // Note that it does not involve moving cards lower than king
00527     // to empty stacks
00528     for (int Stack=0;Stack<m_NumberOfStacks;Stack++)
00529     {
00530         NumberOfCards = StateWithLocations->GetStackLength(Stack);
00531 
00532         for (int c=0 ; c<NumberOfCards; c=SequenceEnd+1)
00533         {   
00534             // Check if there is a sequence here.
00535             for(SequenceEnd=c ; SequenceEnd<NumberOfCards-1 ; SequenceEnd++)
00536             {
00537                 if (!IsParentCard(StateWithLocations->GetStackCard(Stack, SequenceEnd+1), 
00538                                   StateWithLocations->GetStackCard(Stack, SequenceEnd)))
00539                     break;
00540             }
00541 
00542             // Find a card which this card can be put on
00543             Card = StateWithLocations->GetStackCard(Stack, c);
00544 
00545             // Make sure the card is not flipped or else we can't move it
00546             if (Card->GetFlipped() != 0)
00547                 continue;
00548 
00549             for(int DestinationStack=0 ; DestinationStack<m_NumberOfStacks; DestinationStack++)
00550             {
00551                 if (DestinationStack == Stack)
00552                     continue;
00553 
00554                 NumberOfDestinationCards = StateWithLocations->GetStackLength(DestinationStack);
00555                 for(int DestinationCard=0;DestinationCard<NumberOfDestinationCards;DestinationCard++)
00556                 {
00557                     DestCard = StateWithLocations->GetStackCard(DestinationStack, DestinationCard);
00558 
00559                     if (!IsParentCard(Card, DestCard))
00560                         continue;
00561 
00562                     // Corresponding cards - see if it is feasible to move
00563                     //  the source to the destination.
00564                     IsSequenceInDestination = false;
00565                     if (NumberOfDestinationCards - 1 > DestinationCard)
00566                     {
00567                         DestBelowCard = StateWithLocations->GetStackCard(DestinationStack, DestinationCard+1);
00568                         if (IsParentCard(DestBelowCard, DestCard))
00569                             IsSequenceInDestination = true;
00570                     }
00571 
00572                     if (IsSequenceInDestination)
00573                         continue;
00574 
00575                     NumberOfCardsToRelocate = NumberOfDestinationCards - DestinationCard - 1 + NumberOfCards - SequenceEnd - 1;
00576                     FreecellsToFill = min(NumberOfCardsToRelocate, NumberOfFreecells);
00577                     NumberOfCardsToRelocate -= FreecellsToFill;
00578 
00579                     if (m_EmptyStacksFill == FCS_ES_FILLED_BY_ANY_CARD)
00580                     {
00581                         FreeStacksToFill = min(NumberOfCardsToRelocate, NumberOfFreeStacks);
00582 
00583                         NumberOfCardsToRelocate -= FreeStacksToFill;
00584                     }
00585                     else
00586                     {
00587                         FreeStacksToFill = 0;
00588                     }
00589 
00590                     if ((NumberOfCardsToRelocate != 0) || 
00591                         (CalculateMaxSequenceMoves(NumberOfFreecells-FreecellsToFill, NumberOfFreeStacks-FreeStacksToFill) < 
00592                             SequenceEnd - c + 1))
00593                         continue;
00594 
00595                     // We can move it
00596                     int FromWhichStack;
00597 
00598                     CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
00599 
00600                     // Fill the freecells with the top cards
00601                     for(a=0 ; a<FreecellsToFill ; a++)
00602                     {
00603                         // Find a vacant freecell
00604                         for(b=0;b<m_NumberOfFreecells;b++)
00605                         {
00606                             if (NewStateWithLocations->GetFreecellCardNumber(b) == 0)
00607                                 break;
00608                         }
00609 
00610                         if (NewStateWithLocations->GetStackLength(DestinationStack) == DestinationCard+1)
00611                         {
00612                             FromWhichStack = Stack;
00613                         }
00614                         else
00615                         {
00616                             FromWhichStack = DestinationStack;
00617                         }
00618                         NewStateWithLocations->PopStackCard(FromWhichStack, TempCard);
00619                         NewStateWithLocations->PutCardInFreecell(b, TempCard);
00620 
00621                         TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_FREECELL);
00622                         TempMove->SetSourceStack(FromWhichStack);
00623                         TempMove->SetDestFreecell(b);
00624 
00625                         Moves->Push(TempMove);
00626 
00627                         FlipTopCard(NewStateWithLocations, FromWhichStack, TempMove, &Moves);
00628                     }
00629 
00630                     // Fill the free stacks with the cards below them
00631                     for(a=0; a < FreeStacksToFill ; a++)
00632                     {
00633                         //  Find a vacant stack
00634                         for(b=0;b<m_NumberOfStacks;b++)
00635                         {
00636                             if (NewStateWithLocations->GetStackLength(b) == 0)
00637                                 break;
00638                         }
00639 
00640                         if (NewStateWithLocations->GetStackLength(DestinationStack) == DestinationCard+1)
00641                         {
00642                             FromWhichStack = Stack;
00643                         }
00644                         else
00645                         {
00646                             FromWhichStack = DestinationStack;
00647                         }
00648 
00649                         NewStateWithLocations->PopStackCard(FromWhichStack, TempCard);
00650                         NewStateWithLocations->PushCardIntoStack(b, TempCard);
00651 
00652                         TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
00653                         TempMove->SetSourceStack(FromWhichStack);
00654                         TempMove->SetDestStack(b);
00655                         TempMove->SetNumberOfCardsInSequence(1);
00656 
00657                         Moves->Push(TempMove);
00658 
00659                         FlipTopCard(NewStateWithLocations, FromWhichStack, TempMove, &Moves);
00660                     }
00661 
00662                     for(a=c ; a <= SequenceEnd ; a++)
00663                         NewStateWithLocations->PushStackCardIntoStack(DestinationStack, Stack, a);
00664 
00665                     for(a=0; a < SequenceEnd-c+1 ;a++)
00666                         NewStateWithLocations->PopStackCard(Stack, TempCard);
00667 
00668                     TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
00669                     TempMove->SetSourceStack(Stack);
00670                     TempMove->SetDestStack(DestinationStack);
00671                     TempMove->SetNumberOfCardsInSequence(SequenceEnd-c+1);
00672 
00673                     Moves->Push(TempMove);
00674 
00675                     FlipTopCard(NewStateWithLocations, Stack, TempMove, &Moves);
00676 
00677                     if (CheckStateEnd(&NewStateWithLocations, StateWithLocations, &DerivedStateList, 
00678                                       &Moves, &TempMove, Depth, &Check))
00679                     {
00680                         delete TempCard;
00681                         delete TempMove;
00682                         return Check;
00683                     }
00684                 }
00685             }
00686         }
00687     }
00688 
00689     delete [] Moves;
00690     delete TempMove;
00691     delete TempCard;
00692 
00693     return FCS_STATE_IS_NOT_SOLVEABLE;
00694 }
00695 
00696 FCSStateSolvingReturnCodes FCSFreecellSolvingAlgorithm::MoveStackCardsToAParentOnTheSameStack(FCSStateWithLocations*  StateWithLocations,
00697                                           int Depth,
00698                                           int NumberOfFreeStacks,
00699                                           int NumberOfFreecells,
00700                                           FCSDerivedStatesList* DerivedStateList)
00701 {
00702     FCSStateWithLocations *NewStateWithLocations;
00703     FCSCard *Card, 
00704             *TempCard = FCSCard::Create(), 
00705             *PreviousCard, *DestCard, *DestBelowCard,
00706             *MovedCard = FCSCard::Create();
00707 
00708     FCSStateSolvingReturnCodes Check;
00709 
00710     int NumberOfCards, NumberOfDestinationCards, NumberOfCardsToRelocate,
00711         FreecellsToFill, FreeStacksToFill, a, b;
00712 
00713     bool IsSequenceInDestination;
00714 
00715     FCSMoveStack *Moves = CreateMoveStack();
00716     FCSMove *TempMove = FCSMove::Create();
00717 
00718     // Now let's try to move a stack card to a parent card which is found
00719     // on the same stack.
00720     for (int Stack=0;Stack<m_NumberOfStacks;Stack++)
00721     {
00722         NumberOfCards = StateWithLocations->GetStackLength(Stack);
00723 
00724         for (int c=0; c<NumberOfCards; c++)
00725         {   
00726             // Find a card which this card can be put on.
00727             Card = StateWithLocations->GetStackCard(Stack, c);
00728 
00729             // Do not move cards that are already found above a suitable parent
00730             a = 1;
00731             if (c != 0)
00732             {
00733                 PreviousCard = StateWithLocations->GetStackCard(Stack, c-1);
00734                 if ((PreviousCard->GetCardNumber() == Card->GetCardNumber()+1) &&
00735                     ((PreviousCard->GetSuit() & 0x1) != (Card->GetSuit() & 0x1)))
00736                 {
00737                    a = 0;  
00738                 }
00739             }
00740 
00741             if (!a)
00742                 continue;
00743 
00744             // Check if it can be moved to something on the same stack
00745             NumberOfDestinationCards = StateWithLocations->GetStackLength(Stack);
00746 
00747             for(int DestinationCard=0;DestinationCard<c-1;DestinationCard++)
00748             {
00749                 DestCard = StateWithLocations->GetStackCard(Stack, DestinationCard);
00750                 if (!IsParentCard(Card, DestCard))
00751                     continue;
00752                 // Corresponding cards - see if it is feasible to move
00753                 //  the source to the destination.
00754                 IsSequenceInDestination = false;
00755                 DestBelowCard = StateWithLocations->GetStackCard(Stack, DestinationCard+1);
00756                 if (IsParentCard(DestBelowCard, DestCard))
00757                     IsSequenceInDestination = true;
00758 
00759                 if (IsSequenceInDestination)
00760                     continue;
00761 
00762                 NumberOfCardsToRelocate = NumberOfDestinationCards - DestinationCard - 1;
00763                 FreecellsToFill = min(NumberOfCardsToRelocate, NumberOfFreecells);
00764                 NumberOfCardsToRelocate -= FreecellsToFill;
00765 
00766                 if (m_EmptyStacksFill == FCS_ES_FILLED_BY_ANY_CARD)
00767                 {
00768                     FreeStacksToFill = min(NumberOfCardsToRelocate, NumberOfFreeStacks);
00769                     NumberOfCardsToRelocate -= FreeStacksToFill;
00770                 }
00771                 else
00772                 {
00773                     FreeStacksToFill = 0;
00774                 }
00775 
00776                 if (NumberOfCardsToRelocate != 0)
00777                     continue;
00778 
00779                 // We can move it
00780                 CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
00781 
00782                 int SourceType, SourceIndex,
00783                     iCardPosition = NewStateWithLocations->GetStackLength(Stack)-1;
00784 
00785                 a = 0;
00786                 while(iCardPosition>c)
00787                 {
00788                     if (a < FreecellsToFill)
00789                     {
00790                         for(b=0;b<m_NumberOfFreecells;b++)
00791                         {
00792                             if (NewStateWithLocations->GetFreecellCardNumber(b) == 0)
00793                                 break;
00794                         }
00795 
00796                         NewStateWithLocations->PopStackCard(Stack, TempCard);
00797                         NewStateWithLocations->PutCardInFreecell(b, TempCard);
00798 
00799                         TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_FREECELL);
00800                         TempMove->SetSourceStack(Stack);
00801                         TempMove->SetDestFreecell(b);
00802 
00803                         Moves->Push(TempMove);
00804                     }
00805                     else
00806                     {
00807 
00808                         //  Find a vacant stack
00809                         for(b=0;b<m_NumberOfStacks;b++)
00810                         {
00811                             if (NewStateWithLocations->GetStackLength(b) == 0)
00812                                 break;
00813                         }
00814 
00815                         NewStateWithLocations->PopStackCard(Stack, TempCard);
00816                         NewStateWithLocations->PushCardIntoStack(b, TempCard);
00817 
00818                         TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
00819                         TempMove->SetSourceStack(Stack);
00820                         TempMove->SetDestStack(b);
00821                         TempMove->SetNumberOfCardsInSequence(1);
00822 
00823                         Moves->Push(TempMove);
00824                     }
00825                     a++;
00826 
00827                     iCardPosition--;
00828                 }
00829 
00830                 NewStateWithLocations->PopStackCard(Stack, MovedCard);
00831                 if (a < FreecellsToFill)
00832                 {
00833                     for(b=0;b<m_NumberOfFreecells;b++)
00834                     {
00835                         if (NewStateWithLocations->GetFreecellCardNumber(b) == 0)
00836                             break;
00837                     }
00838 
00839                     NewStateWithLocations->PutCardInFreecell(b, MovedCard);
00840 
00841                     TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_FREECELL);
00842                     TempMove->SetSourceStack(Stack);
00843                     TempMove->SetDestFreecell(b);
00844 
00845                     Moves->Push(TempMove);
00846 
00847                     SourceType = 0;
00848                     SourceIndex = b;
00849                 }
00850                 else
00851                 {
00852                     for(b=0;b<m_NumberOfStacks;b++)
00853                     {
00854                         if (NewStateWithLocations->GetStackLength(b) == 0)
00855                             break;
00856                     }
00857 
00858                     NewStateWithLocations->PushCardIntoStack(b, MovedCard);
00859 
00860                     TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
00861                     TempMove->SetSourceStack(Stack);
00862                     TempMove->SetDestStack(b);
00863                     TempMove->SetNumberOfCardsInSequence(1);
00864 
00865                     Moves->Push(TempMove);
00866 
00867                     SourceType = 1;
00868                     SourceIndex = b;
00869                 }
00870                 iCardPosition--;
00871                 a++;
00872 
00873                 while(iCardPosition>DestinationCard)
00874                 {
00875                     if (a < FreecellsToFill)
00876                     {
00877                         for(b=0;b<m_NumberOfFreecells;b++)
00878                         {
00879                             if (NewStateWithLocations->GetFreecellCardNumber(b) == 0)
00880                                 break;
00881                         }
00882 
00883                         NewStateWithLocations->PopStackCard(Stack, TempCard);
00884                         NewStateWithLocations->PutCardInFreecell(b, TempCard);
00885 
00886                         TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_FREECELL);
00887                         TempMove->SetSourceStack(Stack);
00888                         TempMove->SetDestFreecell(b);
00889 
00890                         Moves->Push(TempMove);
00891                     }
00892                     else
00893                     {
00894 
00895                         //  Find a vacant stack
00896                         for(b=0;b<m_NumberOfStacks;b++)
00897                         {
00898                             if (NewStateWithLocations->GetStackLength(b) == 0)
00899                                 break;
00900                         }
00901 
00902                         NewStateWithLocations->PopStackCard(Stack, TempCard);
00903                         NewStateWithLocations->PushCardIntoStack(b, TempCard);
00904 
00905                         TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
00906                         TempMove->SetSourceStack(Stack);
00907                         TempMove->SetDestStack(b);
00908                         TempMove->SetNumberOfCardsInSequence(1);
00909 
00910                         Moves->Push(TempMove);
00911                     }
00912                     a++;
00913 
00914                     iCardPosition--;
00915                 }
00916 
00917                 if (SourceType == 0)
00918                 {
00919                     FCSCard* TempMoveCard = NewStateWithLocations->GetFreecellCard(SourceIndex);
00920                     MovedCard->Copy(TempMoveCard);
00921                     NewStateWithLocations->EmptyFreecell(SourceIndex);
00922 
00923                     TempMove->SetType(FCS_MOVE_TYPE_FREECELL_TO_STACK);
00924                     TempMove->SetSourceFreecell(SourceIndex);
00925                     TempMove->SetDestStack(Stack);
00926                     
00927                     Moves->Push(TempMove);
00928                 }
00929                 else
00930                 {
00931                     NewStateWithLocations->PopStackCard(SourceIndex, MovedCard);
00932                     
00933                     TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
00934                     TempMove->SetSourceStack(SourceIndex);
00935                     TempMove->SetDestStack(Stack);
00936                     TempMove->SetNumberOfCardsInSequence(1);
00937 
00938                     Moves->Push(TempMove);
00939                 }
00940 
00941                 NewStateWithLocations->PushCardIntoStack(Stack, MovedCard);
00942 
00943                 if (CheckStateEnd(&NewStateWithLocations, StateWithLocations, &DerivedStateList, 
00944                                   &Moves, &TempMove, Depth, &Check))
00945                 {
00946                     delete TempCard;
00947                     delete MovedCard;
00948                     delete TempMove;
00949                     return Check;
00950                 }
00951             }
00952         }
00953     }
00954 
00955     delete [] Moves;
00956     delete TempMove;
00957     delete TempCard;
00958     delete MovedCard;
00959 
00960     return FCS_STATE_IS_NOT_SOLVEABLE;
00961 }
00962 
00963 FCSStateSolvingReturnCodes FCSFreecellSolvingAlgorithm::MoveSequencesToFreeStacks(FCSStateWithLocations*  StateWithLocations,
00964                               int Depth,
00965                               int NumberOfFreeStacks,
00966                               int NumberOfFreecells,
00967                               FCSDerivedStatesList* DerivedStateList)
00968 {
00969     if ((m_EmptyStacksFill == FCS_ES_FILLED_BY_NONE) || (NumberOfFreeStacks <= 0))
00970         return FCS_STATE_IS_NOT_SOLVEABLE;
00971 
00972     FCSStateWithLocations *NewStateWithLocations;
00973     FCSCard *ThisCard, 
00974             *TempCard = FCSCard::Create(), 
00975             *PreviousCard;
00976     FCSStateSolvingReturnCodes Check;
00977 
00978     int NumberOfCards, SequenceEnd,
00979         MaxSequenceLength = CalculateMaxSequenceMoves(NumberOfFreecells, NumberOfFreeStacks-1), 
00980         NumberOfCardsToRelocate, FreecellsToFill, FreeStacksToFill, 
00981         DestinationStack, a, b;
00982 
00983     FCSMoveStack *Moves = CreateMoveStack();
00984     FCSMove *TempMove = FCSMove::Create();
00985 
00986     // Now try to move sequences to empty stacks
00987     for(int Stack=0;Stack<m_NumberOfStacks;Stack++)
00988     {
00989         NumberOfCards = StateWithLocations->GetStackLength(Stack);
00990 
00991         for(int c=0; c<NumberOfCards; c=SequenceEnd+1)
00992         {
00993             // Check if there is a sequence here.
00994             for(SequenceEnd=c ; SequenceEnd<NumberOfCards-1; SequenceEnd++)
00995             {
00996                 ThisCard = StateWithLocations->GetStackCard(Stack, SequenceEnd+1);
00997                 PreviousCard = StateWithLocations->GetStackCard(Stack, SequenceEnd);
00998 
00999                 if (!IsParentCard(ThisCard, PreviousCard))
01000                     break;
01001             }
01002 
01003             if ((StateWithLocations->GetStackCardNumber(Stack, c) != 13) &&
01004                 (m_EmptyStacksFill == FCS_ES_FILLED_BY_KINGS_ONLY))
01005                     continue;
01006 
01007             if (SequenceEnd == NumberOfCards-1)
01008             {
01009                 // One stack is the destination stack, so we have one
01010                 // less stack in that case
01011                 while ((MaxSequenceLength < NumberOfCards - c) && (c > 0))
01012                     c--;
01013 
01014                 if ((c <= 0) || ((m_EmptyStacksFill == FCS_ES_FILLED_BY_KINGS_ONLY) && 
01015                     (StateWithLocations->GetStackCard(Stack, c)->GetCardNumber() != 13)))
01016                     continue;
01017 
01018                 CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
01019 
01020                 for(DestinationStack=0;DestinationStack<m_NumberOfStacks;DestinationStack++)
01021                 {
01022                     if (StateWithLocations->GetStackLength(DestinationStack) == 0)
01023                         break;
01024                 }
01025 
01026                 for(a=c; a <= NumberOfCards-1; a++)
01027                     NewStateWithLocations->PushStackCardIntoStack(DestinationStack, Stack, a);
01028 
01029                 for(a=0;a<NumberOfCards-c;a++)
01030                     NewStateWithLocations->PopStackCard(Stack, TempCard);
01031 
01032                 TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
01033                 TempMove->SetSourceStack(Stack);
01034                 TempMove->SetDestStack(DestinationStack);
01035                 TempMove->SetNumberOfCardsInSequence(NumberOfCards-c);
01036 
01037                 Moves->Push(TempMove);
01038 
01039                 FlipTopCard(NewStateWithLocations, Stack, TempMove, &Moves);
01040 
01041                 if (CheckStateEnd(&NewStateWithLocations, StateWithLocations, &DerivedStateList, 
01042                                           &Moves, &TempMove, Depth, &Check))
01043                     return Check;
01044             }
01045             else
01046             {
01047                 NumberOfCardsToRelocate = NumberOfCards - SequenceEnd - 1;
01048                 FreecellsToFill = min(NumberOfCardsToRelocate, NumberOfFreecells);
01049                 NumberOfCardsToRelocate -= FreecellsToFill;
01050 
01051                 if (m_EmptyStacksFill == FCS_ES_FILLED_BY_ANY_CARD)
01052                 {
01053                     FreeStacksToFill = min(NumberOfCardsToRelocate, NumberOfFreeStacks);
01054                     NumberOfCardsToRelocate -= FreeStacksToFill;
01055                 }
01056                 else
01057                 {
01058                     FreeStacksToFill = 0;
01059                 }
01060 
01061                 if ((NumberOfCardsToRelocate != 0) || (NumberOfFreeStacks-FreeStacksToFill <= 0))
01062                     continue;
01063 
01064                 // We can move it
01065                 int SequenceStart = c;
01066                 while (
01067                     (CalculateMaxSequenceMoves(
01068                         NumberOfFreecells-FreecellsToFill,
01069                         NumberOfFreeStacks-FreeStacksToFill-1) < SequenceEnd-SequenceStart+1)
01070                         &&
01071                     (SequenceStart <= SequenceEnd)
01072                     )
01073                 {
01074                     SequenceStart++;
01075                 }
01076 
01077                 if ((SequenceStart > SequenceEnd) || ((m_EmptyStacksFill == FCS_ES_FILLED_BY_KINGS_ONLY) && 
01078                     (StateWithLocations->GetStackCard(Stack, SequenceStart)->GetCardNumber() != 13)))
01079                     continue;
01080                 
01081                 CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
01082 
01083                 // Fill the freecells with the top cards
01084                 for(a=0; a<FreecellsToFill ; a++)
01085                 {
01086                     // Find a vacant freecell
01087                     for(b=0;b<m_NumberOfFreecells;b++)
01088                         if (NewStateWithLocations->GetFreecellCardNumber(b) == 0)
01089                             break;
01090 
01091                     NewStateWithLocations->PopStackCard(Stack, TempCard);
01092                     NewStateWithLocations->PutCardInFreecell(b, TempCard);
01093 
01094                     TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_FREECELL);
01095                     TempMove->SetSourceStack(Stack);
01096                     TempMove->SetDestFreecell(b);
01097                     Moves->Push(TempMove);
01098                 }
01099 
01100                 // Fill the free stacks with the cards below them
01101                 for(a=0; a < FreeStacksToFill ; a++)
01102                 {
01103                     // Find a vacant stack
01104                     for(b=0; b<m_NumberOfStacks; b++)
01105                         if (NewStateWithLocations->GetStackLength(b) == 0)
01106                             break;
01107 
01108                     NewStateWithLocations->PopStackCard(Stack, TempCard);
01109                     NewStateWithLocations->PushCardIntoStack(b, TempCard);
01110 
01111                     TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
01112                     TempMove->SetSourceStack(Stack);
01113                     TempMove->SetDestStack(b);
01114                     TempMove->SetNumberOfCardsInSequence(1);
01115                     Moves->Push(TempMove);
01116                 }
01117 
01118                 // Find a vacant stack
01119                 for(b=0; b<m_NumberOfStacks; b++)
01120                 {
01121                     if (NewStateWithLocations->GetStackLength(b) == 0)
01122                         break;
01123                 }
01124 
01125                 for(a=SequenceStart; a <= SequenceEnd; a++)
01126                     NewStateWithLocations->PushStackCardIntoStack(b, Stack, a);
01127 
01128                 for(a=SequenceStart; a <= SequenceEnd; a++)
01129                     NewStateWithLocations->PopStackCard(Stack, TempCard);
01130 
01131                 TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
01132                 TempMove->SetSourceStack(Stack);
01133                 TempMove->SetDestStack(b);
01134                 TempMove->SetNumberOfCardsInSequence(SequenceEnd-SequenceStart+1);
01135 
01136                 Moves->Push(TempMove);
01137 
01138                 FlipTopCard(NewStateWithLocations, Stack, TempMove, &Moves);
01139 
01140                 if (CheckStateEnd(&NewStateWithLocations, StateWithLocations, &DerivedStateList, 
01141                                       &Moves, &TempMove, Depth, &Check))
01142                 {
01143                     delete TempCard;
01144                     delete TempMove;
01145                     return Check;
01146                 }
01147             }
01148         }
01149     }
01150 
01151     delete [] Moves;
01152     delete TempMove;
01153     delete TempCard;
01154 
01155     return FCS_STATE_IS_NOT_SOLVEABLE;
01156 }
01157 
01158 FCSStateSolvingReturnCodes FCSFreecellSolvingAlgorithm::MoveFreecellCardsToEmptyStack(FCSStateWithLocations*  StateWithLocations,
01159                                   int Depth,
01160                                   int NumberOfFreeStacks,
01161                                   int NumberOfFreecells,
01162                                   FCSDerivedStatesList* DerivedStateList)
01163 {
01164     // Let's try to put cards that occupy freecells on an empty stack
01165     if (m_EmptyStacksFill == FCS_ES_FILLED_BY_NONE)
01166         return FCS_STATE_IS_NOT_SOLVEABLE;
01167 
01168     FCSStateWithLocations *NewStateWithLocations;
01169     FCSCard *Card;
01170     FCSStateSolvingReturnCodes Check;
01171     int Stack;
01172     FCSMoveStack *Moves = CreateMoveStack();
01173     FCSMove *TempMove = FCSMove::Create();
01174 
01175     for(int Freecell=0;Freecell<m_NumberOfFreecells;Freecell++)
01176     {
01177         Card = StateWithLocations->GetFreecellCard(Freecell);
01178 
01179         if ((m_EmptyStacksFill == FCS_ES_FILLED_BY_KINGS_ONLY) ? 
01180             (Card->GetCardNumber() != 13) :
01181             (Card->GetCardNumber() == 0))
01182                 continue;
01183 
01184         for(Stack=0;Stack<m_NumberOfStacks;Stack++)
01185             if (StateWithLocations->GetStackLength(Stack) == 0)
01186                 break;
01187 
01188         if (Stack == m_NumberOfStacks)
01189             continue;
01190 
01191         // We can move it
01192         CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
01193 
01194         NewStateWithLocations->PushCardIntoStack(Stack, Card);
01195         NewStateWithLocations->EmptyFreecell(Freecell);
01196 
01197         TempMove->SetType(FCS_MOVE_TYPE_FREECELL_TO_STACK);
01198         TempMove->SetSourceFreecell(Freecell);
01199         TempMove->SetDestStack(Stack);
01200 
01201         Moves->Push(TempMove);
01202 
01203         if (CheckStateEnd(&NewStateWithLocations, StateWithLocations, &DerivedStateList, 
01204                           &Moves, &TempMove, Depth, &Check))
01205         {
01206             delete TempMove;
01207             return Check;
01208         }
01209     }
01210 
01211     delete [] Moves;
01212     delete TempMove;
01213 
01214     return FCS_STATE_IS_NOT_SOLVEABLE;
01215 }
01216 
01217 FCSStateSolvingReturnCodes FCSFreecellSolvingAlgorithm::MoveCardsToADifferentParent(FCSStateWithLocations*  StateWithLocations,
01218                               int Depth,
01219                               int NumberOfFreeStacks,
01220                               int NumberOfFreecells,
01221                               FCSDerivedStatesList* DerivedStateList)
01222 {
01223     FCSStateWithLocations *NewStateWithLocations;
01224     FCSCard *Card, 
01225             *TempCard = FCSCard::Create(), 
01226             *ThisCard, *PreviousCard,
01227             *DestCard, *DestBelowCard;
01228     FCSStateSolvingReturnCodes Check;
01229 
01230 
01231     int NumberOfCards, NumberOfCardsToRelocate, NumberOfDestinationCards,
01232         FreecellsToFill, FreeStacksToFill,
01233         a, b;
01234     bool IsSequenceInSource, IsSequenceInDestination;
01235 
01236     FCSMoveStack *Moves = CreateMoveStack();
01237     FCSMove *TempMove = FCSMove::Create();
01238 
01239     // This time try to move cards that are already on top of a parent to a different parent
01240     for (int Stack=0;Stack<m_NumberOfStacks;Stack++)
01241     {
01242         NumberOfCards = StateWithLocations->GetStackLength(Stack);
01243 
01244         for (int c=0 ; c<NumberOfCards ; c++)
01245         {   
01246             // Check if there is a sequence here.
01247             IsSequenceInSource = true;
01248             for(a=c+1 ; a<NumberOfCards ; a++)
01249             {
01250                 ThisCard = StateWithLocations->GetStackCard(Stack, a);
01251                 PreviousCard = StateWithLocations->GetStackCard(Stack, a-1);
01252 
01253                 if (!IsParentCard(ThisCard, PreviousCard))
01254                 {
01255                     IsSequenceInSource = false;
01256                     break;
01257                 }
01258             }
01259 
01260             // Find a card which this card can be put on;
01261             Card = StateWithLocations->GetStackCard(Stack, c);
01262 
01263             // Do not move cards that are already found above a suitable parent
01264             a = 1;
01265             if (c != 0)
01266             {
01267                 PreviousCard = StateWithLocations->GetStackCard(Stack, c-1);
01268                 if (IsParentCard(Card, PreviousCard))
01269                    a = 0;  
01270             }
01271 
01272             // And do not move cards that are flipped
01273             if (!a)
01274             {
01275                 ThisCard = StateWithLocations->GetStackCard(Stack, c);
01276                 if (ThisCard->GetFlipped())
01277                     a = 0;
01278             }
01279 
01280             if (a)
01281                 continue;
01282 
01283             for(int DestinationStack=0 ; DestinationStack<m_NumberOfStacks; DestinationStack++)
01284             {
01285                 if (DestinationStack == Stack)
01286                     continue;
01287 
01288                 NumberOfDestinationCards = StateWithLocations->GetStackLength(DestinationStack);
01289                 for(int DestinationCard=0;DestinationCard<NumberOfDestinationCards;DestinationCard++)
01290                 {
01291                     DestCard = StateWithLocations->GetStackCard(DestinationStack, DestinationCard);
01292 
01293                     if (!IsParentCard(Card, DestCard))
01294                         continue;
01295 
01296                     // Corresponding cards - see if it is feasible to move
01297                     // the source to the destination.
01298                     IsSequenceInDestination = false;
01299                     if (NumberOfDestinationCards - 1 > DestinationCard)
01300                     {
01301                         DestBelowCard = StateWithLocations->GetStackCard(DestinationStack, DestinationCard+1);
01302                         if (IsParentCard(DestBelowCard, DestCard))
01303                             IsSequenceInDestination = true;
01304                     }
01305 
01306                     if ((IsSequenceInDestination) || (!IsSequenceInSource))
01307                         continue;
01308 
01309                     NumberOfCardsToRelocate = NumberOfDestinationCards - DestinationCard - 1;
01310                     FreecellsToFill = min(NumberOfCardsToRelocate, NumberOfFreecells);
01311                     NumberOfCardsToRelocate -= FreecellsToFill;
01312 
01313                     if (m_EmptyStacksFill == FCS_ES_FILLED_BY_ANY_CARD)
01314                     {
01315                         FreeStacksToFill = min(NumberOfCardsToRelocate, NumberOfFreeStacks);
01316                         NumberOfCardsToRelocate -= FreeStacksToFill;
01317                     }
01318                     else
01319                     {
01320                         FreeStacksToFill = 0;
01321                     }
01322 
01323                     if ((NumberOfCardsToRelocate != 0) || (CalculateMaxSequenceMoves(NumberOfFreecells-FreecellsToFill, NumberOfFreeStacks-FreeStacksToFill) <
01324                         NumberOfCards - c))
01325                         continue;
01326 
01327                     // We can move it
01328                     CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
01329 
01330                     // Fill the freecells with the top cards
01331                     for(a=0 ; a<FreecellsToFill ; a++)
01332                     {
01333                         // Find a vacant freecell
01334                         for(b=0;b<m_NumberOfFreecells;b++)
01335                             if (NewStateWithLocations->GetFreecellCardNumber(b) == 0)
01336                                 break;
01337 
01338                         NewStateWithLocations->PopStackCard(DestinationStack, TempCard);
01339                         NewStateWithLocations->PutCardInFreecell(b, TempCard);
01340 
01341                         TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_FREECELL);
01342                         TempMove->SetSourceStack(DestinationStack);
01343                         TempMove->SetDestFreecell(b);
01344 
01345                         Moves->Push(TempMove);
01346                     }
01347 
01348                     // Fill the free stacks with the cards below them
01349                     for(a=0; a < FreeStacksToFill ; a++)
01350                     {
01351                         //  Find a vacant stack
01352                         for(b=0;b<m_NumberOfStacks;b++)
01353                             if (NewStateWithLocations->GetStackLength(b) == 0)
01354                                 break;
01355 
01356                         NewStateWithLocations->PopStackCard(DestinationStack, TempCard);
01357                         NewStateWithLocations->PushCardIntoStack(b, TempCard);
01358 
01359                         TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
01360                         TempMove->SetSourceStack(DestinationStack);
01361                         TempMove->SetDestStack(b);
01362                         TempMove->SetNumberOfCardsInSequence(1);
01363 
01364                         Moves->Push(TempMove);
01365                     }
01366 
01367                     for(a=c; a <= NumberOfCards-1 ; a++)
01368                         NewStateWithLocations->PushStackCardIntoStack(DestinationStack, Stack, a);
01369 
01370                     for(a=0;a<NumberOfCards-c;a++)
01371                         NewStateWithLocations->PopStackCard(Stack, TempCard);
01372 
01373                     TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
01374                     TempMove->SetSourceStack(Stack);
01375                     TempMove->SetDestStack(DestinationStack);
01376                     TempMove->SetNumberOfCardsInSequence(NumberOfCards-c);
01377 
01378                     Moves->Push(TempMove);
01379 
01380                     if (CheckStateEnd(&NewStateWithLocations, StateWithLocations, &DerivedStateList, 
01381                                       &Moves, &TempMove, Depth, &Check))
01382                     {
01383                         delete TempCard;
01384                         delete TempMove;
01385                         return Check;
01386                     }
01387                 }
01388             }
01389         }
01390     }
01391 
01392     delete [] Moves;   
01393     delete TempMove;
01394     delete TempCard;
01395 
01396     return FCS_STATE_IS_NOT_SOLVEABLE;
01397 }
01398 
01399 FCSStateSolvingReturnCodes FCSFreecellSolvingAlgorithm::EmptyStackIntoFreecells(FCSStateWithLocations*  StateWithLocations,
01400                           int Depth,
01401                           int NumberOfFreeStacks,
01402                           int NumberOfFreecells,
01403                           FCSDerivedStatesList* DerivedStateList)
01404 {
01405 
01406     if ((m_EmptyStacksFill == FCS_ES_FILLED_BY_NONE) || (NumberOfFreeStacks != 0))
01407         return FCS_STATE_IS_NOT_SOLVEABLE;
01408     
01409     FCSStateWithLocations *NewStateWithLocations;
01410     FCSCard *TempCard = FCSCard::Create();
01411     FCSStateSolvingReturnCodes Check;
01412 
01413     int NumberOfCards, b;
01414 
01415     FCSMoveStack *Moves = CreateMoveStack();
01416     FCSMove *TempMove = FCSMove::Create();
01417 
01418     // Now, let's try to empty an entire stack into the freecells, so other cards can 
01419     // inhabit it
01420     for(int Stack=0;Stack<m_NumberOfStacks;Stack++)
01421     {
01422         NumberOfCards = StateWithLocations->GetStackLength(Stack);
01423         if (NumberOfCards > NumberOfFreecells)
01424             continue;
01425 
01426         // We can empty it
01427         CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
01428 
01429         for(int c=0;c<NumberOfCards;c++)
01430         {
01431             // Find a vacant freecell
01432             for(b=0; b<m_NumberOfFreecells; b++)
01433                 if (NewStateWithLocations->GetFreecellCardNumber(b) == 0)
01434                     break;
01435 
01436             NewStateWithLocations->PopStackCard(Stack, TempCard);
01437             NewStateWithLocations->PutCardInFreecell(b, TempCard);
01438 
01439             TempMove->SetType(FCS_MOVE_TYPE_STACK_TO_FREECELL);
01440             TempMove->SetSourceStack(Stack);
01441             TempMove->SetDestFreecell(b);
01442 
01443             Moves->Push(TempMove);
01444         }
01445 
01446         if (CheckStateEnd(&NewStateWithLocations, StateWithLocations, &DerivedStateList, 
01447                           &Moves, &TempMove, Depth, &Check))
01448         {
01449             delete TempCard;
01450             delete TempMove;
01451             return Check;
01452         }
01453     }
01454 
01455     delete [] Moves;
01456     delete TempMove;
01457     delete TempCard;
01458 
01459     return FCS_STATE_IS_NOT_SOLVEABLE;
01460 }

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