00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "FCSFreecellData.h"
00010
00011
00012 #include "FCSTalonStateWithLocations.h"
00013
00014 FCSFreecellData::FCSFreecellData()
00015 {
00016 InitFCSFreecellData();
00017 }
00018
00019 void FCSFreecellData::InitFCSFreecellData()
00020 {
00021 IsOptimizeClass = false;
00022
00023 m_StateType = DEFAULT_STATE_TYPE;
00024
00025 m_StatePacks = NULL;
00026 m_MaxNumberOfStatePacks = 0;
00027 m_NumberOfStatePacks = 0;
00028 m_NumberOfStatesInLastPack = 0;
00029 m_StatePackLength = 0;
00030
00031 m_NumberOfCheckedStates = 0;
00032 m_SolutionStates = NULL;
00033 m_NumberOfSolutionStates = 0;
00034
00035 m_SolutionMoves = NULL;
00036 m_ProtoSolutionMoves = NULL;
00037
00038 m_NumberOfStatesInCollection = 0;
00039 m_MaxNumberOfStatesInCollection = -1;
00040
00041 m_MaxDepth = -1;
00042 m_MaxNumberOfCheckedStates = -1;
00043
00044 m_DebugDisplayInfo = NULL;
00045
00046 m_TestsOrderNumber = FCS_TESTS_NUM;
00047 for(int a=0;a<FCS_TESTS_NUM;a++)
00048 m_TestsOrder[a] = a;
00049
00050 m_StateStorage = NULL;
00051 m_StackStorage = NULL;
00052
00053 m_NumberOfFreecells = DEFAULT_NUMBER_OF_FREECELLS;
00054 m_NumberOfStacks = DEFAULT_NUMBER_OF_STACKS;
00055 m_NumberOfDecks = DEFAULT_NUMBER_OF_DECKS;
00056
00057 m_SequencesAreBuiltBy = DEFAULT_BUILD_SEQUENCE_TYPE;
00058 m_IsUnlimitedSequenceMove = false;
00059 m_EmptyStacksFill = DEFAULT_EMPTY_STACK_FILL_TYPE;
00060
00061 m_OptimizeSolutionPath = false;
00062
00063
00064
00065 m_IndirectCompare = NULL;
00066 m_IndirectHash = NULL;
00067 }
00068
00069 FCSFreecellData::FCSFreecellData(FCCommandLineArguments* CommandLine)
00070 {
00071 InitFCSFreecellData();
00072
00073
00074 m_StateType = CommandLine->GetStateType();
00075
00076
00077 m_MaxNumberOfStatePacks = IA_STATE_PACKS_GROW_BY;
00078 m_StatePacks = CreateStateWithLocationsMatrix(m_MaxNumberOfStatePacks);
00079 m_NumberOfStatePacks = 1;
00080 m_NumberOfStatesInLastPack = 0;
00081 m_StatePackLength = FC_MAX_STATE_PACK_LENGTH / GetFCSStateWithLocationsClassSize();
00082 m_StatePacks->CreateArray(0, m_StatePackLength);
00083
00084 m_MaxNumberOfStatesInCollection = CommandLine->GetMaxStoredStates();
00085 m_MaxDepth = CommandLine->GetMaxDepth();
00086 m_MaxNumberOfCheckedStates = CommandLine->GetMaxNumberOfIterations();
00087
00088 if (CommandLine->GetNumberOfTests() > 0)
00089 {
00090
00091 if (CommandLine->GetTestOrderNumber(0) != NULL)
00092 {
00093 int b;
00094 for (b = 0;CommandLine->GetTestOrderNumber(b) != NULL;b++)
00095 m_TestsOrder[b] = CommandLine->GetTestOrderNumber(b);
00096
00097 m_TestsOrderNumber = b;
00098 }
00099 }
00100
00101
00102
00103
00104 switch(CommandLine->GetStateStorageType())
00105 {
00106 case FC_AVL_TREE:
00107 m_StateStorage = new FCAVLTreeStateStorage(&m_CompareFunction);
00108 break;
00109 case FC_AVL_RED_BLACK_TREE:
00110 m_StateStorage = new FCAVLRedBlackTreeStateStorage(&m_CompareFunction);
00111 break;
00112 case FC_RED_BLACK_TREE:
00113 m_StateStorage = new FCRedBlackTreeStateStorage(&m_CompareFunction);
00114 break;
00115 case FC_GLIB_TREE:
00116 m_StateStorage = new FCGLIBTreeStateStorage(&m_CompareFunction);
00117 break;
00118 case FC_GLIB_HASH:
00119 m_StateStorage = new FCGLIBHashStateStorage(HASH_TABLE_SIZE, &m_CompareFunction, &m_MD5Hash);
00120 break;
00121 case FC_INTERNAL_HASH:
00122 m_StateStorage = new FCInternalHashStateStorage(HASH_TABLE_SIZE, &m_CompareFunction, &m_MD5Hash);
00123 break;
00124 case FC_INDIRECT_HASH:
00125 m_StateStorage = new FCIndirectStateStorage();
00126 break;
00127 default:
00128 m_StateStorage = NULL;
00129 }
00130
00131 if ((m_StateType == FC_INDIRECT_STATE) || (m_StateType == FC_TALON_INDIRECT_STATE))
00132 {
00133 m_IndirectCompare = new FCSIndirectCardCompareAlgorithm<FCSIndirectCard, void>();
00134 m_IndirectHash = new MD5HashAlgorithm<FCSIndirectCard>();
00135
00136 switch(CommandLine->GetStackStorageType())
00137 {
00138 case FC_AVL_TREE:
00139 m_StackStorage = new FCAVLTreeStackStorage(m_IndirectCompare);
00140 break;
00141 case FC_AVL_RED_BLACK_TREE:
00142 m_StackStorage = new FCAVLRedBlackTreeStackStorage(m_IndirectCompare);
00143 break;
00144 case FC_RED_BLACK_TREE:
00145 m_StackStorage = new FCRedBlackTreeStackStorage(m_IndirectCompare);
00146 break;
00147 case FC_GLIB_TREE:
00148 m_StackStorage = new FCGLIBTreeStackStorage(m_IndirectCompare);
00149 break;
00150 case FC_GLIB_HASH:
00151 m_StackStorage = new FCGLIBHashStackStorage(HASH_TABLE_SIZE, m_IndirectCompare, m_IndirectHash);
00152 break;
00153 case FC_INTERNAL_HASH:
00154 m_StackStorage = new FCInternalHashStackStorage(HASH_TABLE_SIZE, m_IndirectCompare, m_IndirectHash);
00155 break;
00156 default:
00157 m_StackStorage = NULL;
00158 }
00159 }
00160
00161 m_DebugDisplayInfo = CommandLine->GetDebugDisplayInfo();
00162 m_NumberOfFreecells = CommandLine->GetNumberOfFreecells();
00163 m_NumberOfStacks = CommandLine->GetNumberOfStacks();
00164 m_NumberOfDecks = CommandLine->GetNumberOfDecks();
00165
00166 m_SequencesAreBuiltBy = CommandLine->GetSequenceBuildType();
00167
00168 m_IsUnlimitedSequenceMove = CommandLine->GetIsSequenceMoveUnlimited();
00169 m_EmptyStacksFill = CommandLine->GetEmptyStacksFill();
00170
00171 m_OptimizeSolutionPath = CommandLine->GetOptimizeSolution();
00172 }
00173
00174 FCSFreecellData::~FCSFreecellData()
00175 {
00176 if (!IsOptimizeClass)
00177 {
00178 int p,s;
00179 for(p=0; p<m_NumberOfStatePacks-1;p++)
00180 for(s=0 ; s < m_StatePackLength ; s++)
00181 m_StatePacks->DeleteStateWithLocationsParent(p, s);
00182
00183 for(s=0; s < m_NumberOfStatesInLastPack ; s++)
00184 m_StatePacks->DeleteStateWithLocationsParent(p, s);
00185
00186
00187 for(int a=0;a<m_NumberOfStatePacks;a++)
00188 m_StatePacks->DeleteArray(a);
00189
00190 delete m_StatePacks;
00191
00192 delete m_StateStorage;
00193 delete m_StackStorage;
00194
00195 if (m_IndirectCompare != NULL)
00196 delete m_IndirectCompare;
00197
00198 if (m_IndirectHash != NULL)
00199 delete m_IndirectHash;
00200
00201 if (m_DebugDisplayInfo != NULL)
00202 delete m_DebugDisplayInfo;
00203 }
00204
00205 if (m_ProtoSolutionMoves != NULL)
00206 {
00207 delete [] m_ProtoSolutionMoves;
00208 m_ProtoSolutionMoves = NULL;
00209 }
00210
00211 if (m_SolutionMoves != NULL)
00212 {
00213 delete [] m_SolutionMoves;
00214 m_SolutionMoves = NULL;
00215 }
00216
00217 if (m_SolutionStates != NULL)
00218 {
00219 delete [] m_SolutionStates;
00220 m_SolutionStates = NULL;
00221 }
00222
00223 }
00224
00225 void FCSFreecellData::InitSolve(FCSStateWithLocations* InitState)
00226 {
00227
00228 FCSStateWithLocations *NoUse = NULL;
00229
00230
00231 CheckAndAddState(InitState, &NoUse, 0);
00232 }
00233
00234 void FCSFreecellData::CleanData()
00235 {
00236 for(int a=0;a<m_NumberOfSolutionStates-1;a++)
00237 {
00238 m_SolutionStates->Get(a, 0)->CleanState();
00239 m_SolutionStates->DeleteArray(a);
00240 delete m_ProtoSolutionMoves[a];
00241 }
00242
00243 delete [] m_SolutionStates;
00244 m_SolutionStates = NULL;
00245
00246 delete [] m_ProtoSolutionMoves;
00247 m_ProtoSolutionMoves = NULL;
00248 }
00249
00250 void FCSFreecellData::ShowSolution(FCSStateWithLocations* InitStateWithLocations,
00251 FCSStateWithLocations* DupStateWithLocations)
00252 {
00253
00254 CreateTotalMovesStack();
00255
00256 for(int a=0;a<m_NumberOfSolutionStates;a++)
00257 {
00258 m_SolutionStates->Get(a, 0)->CleanState();
00259 m_SolutionStates->Delete(a);
00260 }
00261
00262 delete [] m_SolutionStates;
00263 m_SolutionStates = NULL;
00264
00265 m_SolutionMoves->Normalize(InitStateWithLocations, m_NumberOfFreecells, m_NumberOfStacks, m_NumberOfDecks);
00266
00267 FCSMove* Move = FCSMove::Create();
00268 char AsString[STATE_STRING_SIZE];
00269 int NumberOfMoves = 0;
00270
00271 if (m_DebugDisplayInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_STATES)
00272 {
00273 cout << "-=-=-=-=-=-=-=-=-=-=-=-" << endl << endl;
00274 DupStateWithLocations->StateAsString(AsString, m_DebugDisplayInfo);
00275 cout << AsString << endl << endl << "====================" << endl << endl;
00276 }
00277
00278 while (GetNextMove(DupStateWithLocations, Move) == 0)
00279 {
00280 if (m_DebugDisplayInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_MOVES)
00281 {
00282 (m_DebugDisplayInfo->m_DisplayDebugOptions & DEBUG_USE_STANDARD_NOTATION) ?
00283 Move->MoveAsStringStandardNotation(AsString) :
00284 Move->MoveAsString(AsString);
00285
00286 if (m_DebugDisplayInfo->m_DisplayDebugOptions & (DEBUG_DISPLAY_STATES | DEBUG_USE_STANDARD_NOTATION))
00287 cout << "Move: ";
00288
00289 NumberOfMoves++;
00290
00291 cout << NumberOfMoves << ":\t" << AsString
00292 << ((m_DebugDisplayInfo->m_DisplayDebugOptions & DEBUG_USE_STANDARD_NOTATION) ? " " : "\n");
00293
00294 if ((m_DebugDisplayInfo->m_DisplayDebugOptions & DEBUG_USE_STANDARD_NOTATION) &&
00295 ((NumberOfMoves % 10 == 0) || (m_DebugDisplayInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_STATES)))
00296 cout << endl;
00297
00298 if (m_DebugDisplayInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_STATES)
00299 cout << endl;
00300 }
00301
00302 if (m_DebugDisplayInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_STATES)
00303 {
00304 DupStateWithLocations->StateAsString(AsString, m_DebugDisplayInfo);
00305 cout << AsString << endl;
00306 }
00307
00308 if (m_DebugDisplayInfo->m_DisplayDebugOptions & (DEBUG_DISPLAY_STATES | (!DEBUG_USE_STANDARD_NOTATION)))
00309 cout << endl << "====================" << endl << endl;
00310 }
00311
00312 if (m_DebugDisplayInfo->m_DisplayDebugOptions & (DEBUG_USE_STANDARD_NOTATION | (!DEBUG_DISPLAY_STATES )))
00313 cout << endl << endl;
00314
00315 delete Move;
00316 }
00317
00318 void FCSFreecellData::TraceSolution()
00319 {
00320
00321 FCSStateWithLocations* State = m_FinalState;
00322
00323
00324 m_NumberOfSolutionStates = State->m_Depth+1;
00325
00326 if (m_SolutionStates != NULL)
00327 delete [] m_SolutionStates;
00328
00329 if (m_ProtoSolutionMoves != NULL)
00330 delete [] m_ProtoSolutionMoves;
00331
00332
00333 m_SolutionStates = CreateStateWithLocationsMatrix(m_NumberOfSolutionStates);
00334 m_ProtoSolutionMoves = new FCSMoveStack*[m_NumberOfSolutionStates-1];
00335
00336
00337 while (State->m_Parent != NULL)
00338 {
00339
00340 State->m_Visited |= FCS_VISITED_IN_SOLUTION_PATH;
00341
00342
00343 m_ProtoSolutionMoves[State->m_Depth-1] = State->m_MovesToParent->Copy();
00344
00345
00346 m_SolutionStates->Create(State->m_Depth);
00347 m_SolutionStates->Get(State->m_Depth, 0)->Copy(State);
00348
00349
00350 State = State->m_Parent;
00351 }
00352
00353
00354 State->m_Visited |= FCS_VISITED_IN_SOLUTION_PATH;
00355 m_SolutionStates->Create(0);
00356 m_SolutionStates->Get(0, 0)->Copy(State);
00357 }
00358
00359 int FCSFreecellData::GetNumberOfCheckedStates()
00360 {
00361 return m_NumberOfCheckedStates;
00362 }
00363
00364 int FCSFreecellData::GetNumberOfStatesInCollection()
00365 {
00366 return m_NumberOfStatesInCollection;
00367 }
00368
00369 void FCSFreecellData::IncreaseMaxNumberOfCheckedStates()
00370 {
00371 m_MaxNumberOfCheckedStates += 10;
00372 }
00373
00374 int FCSFreecellData::GetNextMove(FCSStateWithLocations* StateWithLocations, FCSMove* Move)
00375 {
00376 int ReturnValue = m_SolutionMoves->Pop(&Move);
00377
00378 if (ReturnValue == 0)
00379 {
00380 ApplyMove(StateWithLocations, Move, m_NumberOfFreecells,
00381 m_NumberOfStacks, m_NumberOfDecks);
00382 }
00383
00384 return ReturnValue;
00385 }
00386
00387 void FCSFreecellData::CreateTotalMovesStack()
00388 {
00389 int Depth;
00390 m_SolutionMoves = CreateMoveStack();
00391
00392
00393
00394
00395 if (m_DebugDisplayInfo->m_DisplayDebug)
00396 {
00397 int Sum = 0;
00398 for(Depth=0 ; Depth <= m_NumberOfSolutionStates-2 ; Depth++)
00399 {
00400 Sum += m_ProtoSolutionMoves[Depth]->GetNumberOfMoves();
00401 cout << "Depth " << Depth << " : " << Sum << endl;
00402 }
00403 }
00404
00405 for(Depth=m_NumberOfSolutionStates-2;Depth>=0;Depth--)
00406 m_SolutionMoves->SwallowStack(m_ProtoSolutionMoves[Depth]);
00407
00408 delete [] m_ProtoSolutionMoves;
00409 m_ProtoSolutionMoves = NULL;
00410 }
00411
00412
00413 FCSStateWithLocations* FCSFreecellData::StatePackAlloc()
00414 {
00415 if (m_NumberOfStatesInLastPack == m_StatePackLength)
00416 {
00417 if (m_NumberOfStatePacks == m_MaxNumberOfStatePacks)
00418 {
00419 m_MaxNumberOfStatePacks += IA_STATE_PACKS_GROW_BY;
00420 m_StatePacks->ReallocArray(m_NumberOfStatePacks, m_MaxNumberOfStatePacks);
00421 }
00422 m_StatePacks->CreateArray(m_NumberOfStatePacks, m_StatePackLength);
00423 m_NumberOfStatePacks++;
00424 m_NumberOfStatesInLastPack = 0;
00425 }
00426
00427 return m_StatePacks->Get(m_NumberOfStatePacks-1, m_NumberOfStatesInLastPack++);
00428 }
00429
00430
00431 void FCSFreecellData::StatePackRelease()
00432 {
00433 m_NumberOfStatesInLastPack--;
00434 }
00435
00436 void FCSFreecellData::CheckStateBegin(FCSStateWithLocations** NewStateWithLocations, FCSStateWithLocations* StateWithLocations,
00437 FCSMoveStack *Move)
00438 {
00439 (*NewStateWithLocations) = StatePackAlloc();
00440 (*NewStateWithLocations)->Copy(StateWithLocations);
00441 (*NewStateWithLocations)->m_Parent = StateWithLocations;
00442 (*NewStateWithLocations)->m_MovesToParent = Move;
00443
00444
00445
00446 (*NewStateWithLocations)->m_Depth = StateWithLocations->m_Depth + 1;
00447 (*NewStateWithLocations)->m_Visited = FCS_VISITED_NOT_VISITED;
00448 Move->Reset();
00449 }
00450
00451 bool FCSFreecellData::CheckStateEnd(FCSStateWithLocations** NewStateWithLocations, FCSStateWithLocations* StateWithLocations,
00452 FCSDerivedStatesList** DerivedStateList, FCSMoveStack** Move, FCSMove** TempMove, int depth,
00453 FCSStateSolvingReturnCodes* ReturnCode)
00454 {
00455 FCSStateWithLocations* ExistingState;
00456 FCSStateSolvingReturnCodes Check;
00457
00458
00459
00460
00461
00462 (*TempMove)->SetType(FCS_MOVE_TYPE_CANONIZE);
00463 (*Move)->Push(*TempMove);
00464
00465 Check = CheckAndAddState(*NewStateWithLocations, &ExistingState, depth);
00466
00467 if ((Check == FCS_STATE_BEGIN_SUSPEND_PROCESS) ||
00468 (Check == FCS_STATE_SUSPEND_PROCESS))
00469 {
00470
00471
00472 (*NewStateWithLocations)->CleanState();
00473 *ReturnCode = Check;
00474 return true;
00475 }
00476 else if (Check == FCS_STATE_ALREADY_EXISTS)
00477 {
00478 StatePackRelease();
00479 (*DerivedStateList)->AddState(ExistingState);
00480 }
00481 else
00482 {
00483 (*DerivedStateList)->AddState(*NewStateWithLocations);
00484
00485
00486 (*Move) = CreateMoveStack();
00487 }
00488
00489 return false;
00490 }
00491
00492 FCSStateSolvingReturnCodes FCSFreecellData::CheckAndAddState(FCSStateWithLocations* NewState,
00493 FCSStateWithLocations** ExistingState,
00494 int Depth)
00495 {
00496 if (((m_MaxNumberOfCheckedStates >= 0) &&
00497 (m_NumberOfCheckedStates >= m_MaxNumberOfCheckedStates)) ||
00498 ((m_MaxNumberOfStatesInCollection >= 0) &&
00499 (m_NumberOfStatesInCollection >= m_MaxNumberOfStatesInCollection)))
00500 {
00501 return FCS_STATE_BEGIN_SUSPEND_PROCESS;
00502 }
00503
00504 if ((m_MaxDepth >= 0) &&
00505 (m_MaxDepth <= Depth))
00506 {
00507 return FCS_STATE_EXCEEDS_MAX_DEPTH;
00508 }
00509
00510 NewState->CanonizeState(m_NumberOfFreecells, m_NumberOfStacks);
00511 NewState->CacheStacks(m_StackStorage, m_NumberOfStacks);
00512
00513 if (m_StateStorage->CheckAndInsert(ExistingState, NewState))
00514 {
00515
00516 m_NumberOfStatesInCollection++;
00517 return FCS_STATE_DOES_NOT_EXIST;
00518 }
00519
00520 return FCS_STATE_ALREADY_EXISTS;
00521 }
00522
00523 bool FCSFreecellData::IsParentCard(FCSCard* Child, FCSCard* Parent)
00524 {
00525 return ((Child->GetCardNumber()+1 == Parent->GetCardNumber()) &&
00526 ((m_SequencesAreBuiltBy == FCS_SEQ_BUILT_BY_RANK) ?
00527 1 :
00528 ((m_SequencesAreBuiltBy == FCS_SEQ_BUILT_BY_SUIT) ?
00529 (Child->GetSuit() == Parent->GetSuit()) :
00530 ((Child->GetSuit() & 0x1) != (Parent->GetSuit()&0x1))
00531 ))
00532 );
00533 }
00534
00535 int FCSFreecellData::CalculateMaxSequenceMoves(int FreecellNumber, int FreeStackNumber)
00536 {
00537 return ( m_IsUnlimitedSequenceMove ? INT_MAX :
00538 (
00539 (m_EmptyStacksFill == FCS_ES_FILLED_BY_ANY_CARD) ?
00540 ((FreecellNumber+1)<<(FreeStackNumber)) :
00541 (FreecellNumber+1)
00542 )
00543 );
00544 }
00545
00546 void FCSFreecellData::MoveSequence(FCSStateWithLocations* NewStateWithLocations, FCSCard* Card, FCSMoveStack *MoveStack, FCSMove** TempMove,
00547 int DestStack, int SourceStack, int Start, int End)
00548 {
00549 int Loop;
00550
00551 for (Loop = Start; Loop <= End ; Loop++)
00552 NewStateWithLocations->PushStackCardIntoStack(DestStack, SourceStack, Loop);
00553
00554 for (Loop = Start; Loop <= End ; Loop++)
00555 NewStateWithLocations->PopStackCard(SourceStack, Card);
00556
00557 (*TempMove)->SetType(FCS_MOVE_TYPE_STACK_TO_STACK);
00558 (*TempMove)->SetSourceStack(SourceStack);
00559 (*TempMove)->SetDestStack(DestStack);
00560 (*TempMove)->SetNumberOfCardsInSequence(End-Start+1);
00561
00562 MoveStack->Push(*TempMove);
00563 }