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
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
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
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
00161
00162
00163
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
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
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
00259 for(int DestinationStack=0;DestinationStack<m_NumberOfStacks;DestinationStack++)
00260 {
00261 DestinationCardNumber = StateWithLocations->GetStackLength(DestinationStack);
00262
00263
00264 if (DestinationCardNumber <= 0)
00265 continue;
00266
00267
00268 for(int DestCard=DestinationCardNumber-1;DestCard>=0;DestCard--)
00269 {
00270 DestinationCard = StateWithLocations->GetStackCard(DestinationStack, DestCard);
00271
00272
00273 for(int Freecell=0;Freecell<m_NumberOfFreecells;Freecell++)
00274 {
00275 SourceCard = StateWithLocations->GetFreecellCard(Freecell);
00276
00277
00278 if ( (SourceCard->GetCardNumber() <= 0) || (!IsParentCard(SourceCard,DestinationCard)))
00279 continue;
00280
00281
00282
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
00315 CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
00316
00317
00318 for(a=0 ; a<FreecellsToFill ; a++)
00319 {
00320
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
00338 for(a=0; a <FreeStacksToFill; a++)
00339 {
00340
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
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
00399
00400
00401 for(int Stack=0;Stack<m_NumberOfStacks;Stack++)
00402 {
00403 NumberOfCards = StateWithLocations->GetStackLength(Stack);
00404
00405
00406
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
00416
00417
00418 if ((NumberOfFreecells +
00419 ((m_EmptyStacksFill == FCS_ES_FILLED_BY_ANY_CARD) ?
00420 NumberOfFreeStacks :
00421 0
00422 ))
00423 >= NumberOfCards-(c+1))
00424 {
00425
00426 CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
00427
00428
00429 for(a=0 ; a<min(NumberOfFreecells, NumberOfCards-(c+1)) ; a++)
00430 {
00431
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
00451 for(a=0; a < NumberOfCards-(c+1) - min(NumberOfFreecells, NumberOfCards-(c+1)) ; a++)
00452 {
00453
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
00526
00527
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
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
00543 Card = StateWithLocations->GetStackCard(Stack, c);
00544
00545
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
00563
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
00596 int FromWhichStack;
00597
00598 CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
00599
00600
00601 for(a=0 ; a<FreecellsToFill ; a++)
00602 {
00603
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
00631 for(a=0; a < FreeStacksToFill ; a++)
00632 {
00633
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
00719
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
00727 Card = StateWithLocations->GetStackCard(Stack, c);
00728
00729
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
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
00753
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
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
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
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
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
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
01010
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
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
01084 for(a=0; a<FreecellsToFill ; a++)
01085 {
01086
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
01101 for(a=0; a < FreeStacksToFill ; a++)
01102 {
01103
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
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
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
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
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
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
01261 Card = StateWithLocations->GetStackCard(Stack, c);
01262
01263
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
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
01297
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
01328 CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
01329
01330
01331 for(a=0 ; a<FreecellsToFill ; a++)
01332 {
01333
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
01349 for(a=0; a < FreeStacksToFill ; a++)
01350 {
01351
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
01419
01420 for(int Stack=0;Stack<m_NumberOfStacks;Stack++)
01421 {
01422 NumberOfCards = StateWithLocations->GetStackLength(Stack);
01423 if (NumberOfCards > NumberOfFreecells)
01424 continue;
01425
01426
01427 CheckStateBegin(&NewStateWithLocations, StateWithLocations, Moves);
01428
01429 for(int c=0;c<NumberOfCards;c++)
01430 {
01431
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 }