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

FCSSimpleSimonSolvingAlgorithm.cpp

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

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