00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <stdlib.h>
00010 #include <string.h>
00011 #include <stdio.h>
00012 #include <assert.h>
00013 #include "FCState.h"
00014 #include "FCTalonState.h"
00015 #include "FCDebugState.h"
00016 #include "FCCompactState.h"
00017 #include "FCIndirectState.h"
00018 #include "FCSDebugStateWithLocations.h"
00019 #include "FCSCompactStateWithLocations.h"
00020 #include "FCSIndirectStateWithLocations.h"
00021 #include "FCSTalonStateWithLocations.h"
00022
00024 FCStateType GlobalStateType = FC_DEBUG_STATE;
00025
00026 #ifdef min
00027 #undef min
00028 #endif
00029
00030 #define min(a,b) ((a)<(b)?(a):(b))
00031
00033 const char * const FreecellsPrefixes[] = { "FC:", "Freecells:", "Freecell:", ""};
00035 const char * const FoundationsPrefixes[] = { "Decks:", "Deck:", "Founds:", "Foundations:", "Foundation:", "Found:", ""};
00036
00037 #ifdef WIN32
00038 #define strncasecmp(a,b,c) (strnicmp((a),(b),(c)))
00039 #endif
00040
00041 FCSState::FCSState()
00042 {
00043 }
00044
00045 FCSState::~FCSState()
00046 {
00047 }
00048
00049 FCSStateWithLocations::FCSStateWithLocations()
00050 {
00051 char a;
00052
00053 m_Depth = 0;
00054 m_Visited = 0;
00055 m_VisitIterations = 0;
00056 m_Parent = NULL;
00057 m_MovesToParent = NULL;
00058
00059 for(a=0;a<MAX_NUM_STACKS;a++)
00060 {
00061 m_StackLocations[a] = a;
00062 }
00063 for(a=0;a<MAX_NUM_FREECELLS;a++)
00064 {
00065 m_FreecellLocations[a] = a;
00066 }
00067 }
00068
00069 FCSStateWithLocations::~FCSStateWithLocations()
00070 {
00071 }
00072
00073 void FCSStateWithLocations::Copy(FCSStateWithLocations* State)
00074 {
00075 memcpy(m_StackLocations, State->m_StackLocations, MAX_NUM_STACKS);
00076 m_Parent = State->m_Parent;
00077 m_MovesToParent = State->m_MovesToParent;
00078 memcpy(m_FreecellLocations, State->m_FreecellLocations, MAX_NUM_FREECELLS);
00079 m_Depth = State->m_Depth;
00080 m_Visited = State->m_Visited;
00081 m_VisitIterations = State->m_VisitIterations;
00082 }
00083
00084 FCSStateWithLocations* FCSStateWithLocations::CreateInitialState(const char *String,
00085 int NumberOfFreecells, int NumberOfStacks,
00086 int NumberOfDecks)
00087 {
00088 FCSStateWithLocations* ReturnState;
00089
00090 int DecksIndex[4], c, i;
00091 const char * Str;
00092 FCSCard* Card = FCSCard::Create();
00093 bool FirstLine = true,
00094 PrefixFound;
00095
00096 const char * const * Prefixes;
00097
00098 ReturnState = CreateStateWithLocations();
00099 ReturnState->Initialize(NumberOfStacks);
00100
00101 Str = String;
00102
00103 for(int s=0;s<NumberOfStacks;s++)
00104 {
00105
00106 if (!FirstLine)
00107 {
00108 while((*Str) != '\n')
00109 {
00110 Str++;
00111 }
00112 Str++;
00113 }
00114 FirstLine = false;
00115
00116 Prefixes = FreecellsPrefixes;
00117 PrefixFound = false;
00118 for(i=0;Prefixes[i][0] != '\0'; i++)
00119 {
00120 if (!strncasecmp(Str, Prefixes[i], strlen(Prefixes[i])))
00121 {
00122 PrefixFound = true;
00123 Str += strlen(Prefixes[i]);
00124 break;
00125 }
00126 }
00127
00128 if (PrefixFound)
00129 {
00130 for(c=0;c<NumberOfFreecells;c++)
00131 {
00132 ReturnState->EmptyFreecell(c);
00133 }
00134 for(c=0;c<NumberOfFreecells;c++)
00135 {
00136 if (c!=0)
00137 {
00138 while(
00139 ((*Str) != ' ') &&
00140 ((*Str) != '\t') &&
00141 ((*Str) != '\n') &&
00142 ((*Str) != '\r')
00143 )
00144 {
00145 Str++;
00146 }
00147 if ((*Str == '\n') || (*Str == '\r'))
00148 {
00149 break;
00150 }
00151 Str++;
00152 }
00153
00154 while ((*Str == ' ') || (*Str == '\t'))
00155 {
00156 Str++;
00157 }
00158 if ((*Str == '\r') || (*Str == '\n'))
00159 break;
00160
00161 if ((*Str == '*') || (*Str == '-'))
00162 {
00163 Card->EmptyCard();
00164 }
00165 else
00166 {
00167 Card->User2Perl(Str);
00168 }
00169
00170 ReturnState->PutCardInFreecell(c, Card);
00171 }
00172
00173 while ((*Str != '\n') && (*Str != '\0'))
00174 {
00175 Str++;
00176 }
00177 s--;
00178 continue;
00179 }
00180
00181 Prefixes = FoundationsPrefixes;
00182 PrefixFound = false;
00183 for(i=0;Prefixes[i][0] != '\0'; i++)
00184 {
00185 if (!strncasecmp(Str, Prefixes[i], strlen(Prefixes[i])))
00186 {
00187 PrefixFound = true;
00188 Str += strlen(Prefixes[i]);
00189 break;
00190 }
00191 }
00192
00193 if (PrefixFound)
00194 {
00195 int d;
00196
00197 for(d=0;d<NumberOfDecks*4;d++)
00198 {
00199 ReturnState->SetFoundation(d, 0);
00200 }
00201
00202 for(d=0;d<4;d++)
00203 {
00204 DecksIndex[d] = 0;
00205 }
00206 while (1)
00207 {
00208 while((*Str == ' ') || (*Str == '\t'))
00209 Str++;
00210 if ((*Str == '\n') || (*Str == '\r'))
00211 break;
00212 d = FCSCard::User2PerlSuit(Str);
00213 Str++;
00214 while (*Str == '-')
00215 Str++;
00216 c = FCSCard::User2PerlCardNumber(Str);
00217 while (
00218 (*Str != ' ') &&
00219 (*Str != '\t') &&
00220 (*Str != '\n') &&
00221 (*Str != '\r')
00222 )
00223 {
00224 Str++;
00225 }
00226
00227 ReturnState->SetFoundation(DecksIndex[d]*4+d, c);
00228 DecksIndex[d]++;
00229 if (DecksIndex[d] >= NumberOfDecks)
00230 {
00231 DecksIndex[d] = 0;
00232 }
00233 }
00234 s--;
00235 continue;
00236 }
00237
00238 for(c=0 ; c < MAX_NUM_CARDS_IN_A_STACK ; c++)
00239 {
00240
00241 if (c!=0)
00242 {
00243 while(
00244 ((*Str) != ' ') &&
00245 ((*Str) != '\t') &&
00246 ((*Str) != '\n') &&
00247 ((*Str) != '\r')
00248 )
00249 {
00250 Str++;
00251 }
00252 if ((*Str == '\n') || (*Str == '\r'))
00253 {
00254 break;
00255 }
00256 }
00257
00258 while ((*Str == ' ') || (*Str == '\t'))
00259 {
00260 Str++;
00261 }
00262 if ((*Str == '\n') || (*Str == '\r'))
00263 {
00264 break;
00265 }
00266 Card->User2Perl(Str);
00267
00268 ReturnState->PushCardIntoStack(s, Card);
00269 }
00270 }
00271
00272
00273 delete Card;
00274
00275 return ReturnState;
00276 }
00277
00278 int FCSStateWithLocations::CheckStateValidity(int NumberOfFreecells, int NumberOfStacks, int NumberOfDecks,
00279 FCSCard** MisplacedCard, FCSTalonType TalonType)
00280 {
00281 int Cards[4][14];
00282 int c, d;
00283
00284
00285 for(d=0;d<4;d++)
00286 for(c=1;c<=13;c++)
00287 Cards[d][c] = 0;
00288
00289
00290 for(d=0;d<NumberOfDecks*4;d++)
00291 for (c=1; c<=GetFoundation(d); c++)
00292 Cards[d%4][c]++;
00293
00294
00295 for(int f=0;f<NumberOfFreecells;f++)
00296 if (GetFreecellCardNumber(f) != 0)
00297 Cards[GetFreecellCardSuit(f)][GetFreecellCardNumber(f)]++;
00298
00299
00300 for(int s=0;s<NumberOfStacks;s++)
00301 {
00302 for (c=0; c<GetStackLength(s); c++)
00303 {
00304 if (GetStackCardNumber(s, c) == 0)
00305 {
00306 (*MisplacedCard) = FCSCard::Create();
00307 (*MisplacedCard)->EmptyCard();
00308 return 3;
00309 }
00310 Cards[GetStackCardSuit(s, c)][GetStackCardNumber(s, c)]++;
00311 }
00312 }
00313
00314
00315 for(d=0;d<4;d++)
00316 {
00317 for(c=1;c<=13;c++)
00318 {
00319 if (Cards[d][c] != NumberOfDecks)
00320 {
00321 (*MisplacedCard) = FCSCard::Create();
00322 (*MisplacedCard)->SetSuit(d);
00323 (*MisplacedCard)->SetCardNumber(c);
00324 return (Cards[d][c] < NumberOfDecks) ? 1 : 2;
00325 }
00326 }
00327 }
00328
00329 return 0;
00330 }
00331
00332 void FCSStateWithLocations::StateAsString(char* String, FCSDebugDisplayInfo* DebugInfo)
00333 {
00334 char Freecells[10], Decks[MAX_NUM_DECKS*4][10], StackCards[10];
00335 bool CardNumberIsNull;
00336 int MaxNumberOfCards, NumberOfCards, Length, b, s;
00337
00338 FCSCard* TempCard;
00339
00340 char Str2[128], Str3[128], *PtrStr2, *PtrStr3, *Str, a;
00341
00342 int StackLocations[MAX_NUM_STACKS];
00343 int FreecellLocations[MAX_NUM_FREECELLS];
00344
00345 if (DebugInfo->m_DisplayDebugOptions & DEBUG_CANONIZED_ORDER_OUTPUT)
00346 {
00347 for(a=0;a<DebugInfo->m_NumberOfStacks;a++)
00348 StackLocations[a] = a;
00349
00350 for(a=0;a<DebugInfo->m_NumberOfFreecells;a++)
00351 FreecellLocations[a] = a;
00352 }
00353 else
00354 {
00355 for(a=0;a<DebugInfo->m_NumberOfStacks;a++)
00356 StackLocations[m_StackLocations[a]] = a;
00357
00358 for(a=0;a<DebugInfo->m_NumberOfFreecells;a++)
00359 FreecellLocations[m_FreecellLocations[a]] = a;
00360 }
00361
00362 for(a=0;a<DebugInfo->m_NumberOfDecks*4;a++)
00363 {
00364 FCSCard::Perl2UserCardNumber(GetFoundation(a), Decks[a], &CardNumberIsNull,
00365 (DebugInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_10_AS_T), 0, DebugInfo->m_DisplayDebug);
00366 if (Decks[a][0] == ' ')
00367 Decks[a][0] = '0';
00368 }
00369
00370 Str = String;
00371
00372 if (!(DebugInfo->m_DisplayDebugOptions & DEBUG_IS_OUTPUT_PARSEABLE))
00373 {
00374 for(a=0;a<((DebugInfo->m_NumberOfFreecells/4)+(DebugInfo->m_NumberOfFreecells%4 !=0));a++)
00375 {
00376 PtrStr2 = Str2;
00377 PtrStr3 = Str3;
00378 for(b=0;b<min(DebugInfo->m_NumberOfFreecells-a*4, 4);b++)
00379 {
00380 TempCard = GetFreecellCard(m_FreecellLocations[a*4+b]);
00381 PtrStr2 += sprintf(PtrStr2, "%3s ",
00382 TempCard->Perl2User(Freecells, (DebugInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_10_AS_T),
00383 DebugInfo->m_DisplayDebug)
00384 );
00385 PtrStr3 += sprintf(PtrStr3, "--- ");
00386 }
00387 if (a < DebugInfo->m_NumberOfDecks)
00388 {
00389 Str += sprintf(Str, "%-16s H-%1s C-%1s D-%1s S-%1s\n",
00390 Str2,
00391 Decks[a*4],
00392 Decks[a*4+1],
00393 Decks[a*4+2],
00394 Decks[a*4+3]);
00395 }
00396 else
00397 {
00398 Str += sprintf(Str, "%s\n", Str2);
00399 }
00400 Str += sprintf(Str, "%s\n", Str3);
00401 }
00402 for(;a<DebugInfo->m_NumberOfDecks;a++)
00403 {
00404 Str += sprintf(Str, "%-16s H-%1s C-%1s D-%1s S-%1s\n",
00405 "",
00406 Decks[a*4],
00407 Decks[a*4+1],
00408 Decks[a*4+2],
00409 Decks[a*4+3]);
00410 }
00411 *(Str++) = '\n';
00412 *(Str++) = '\n';
00413 *Str = '\0';
00414
00415 for(s=0;s<DebugInfo->m_NumberOfStacks;s++)
00416 {
00417 Str += sprintf(Str, " -- ");
00418 }
00419 *(Str++) = '\n';
00420 *Str = '\0';
00421
00422 MaxNumberOfCards = 0;
00423 for(s=0;s<DebugInfo->m_NumberOfStacks;s++)
00424 if (GetStackLength(StackLocations[s]) > MaxNumberOfCards)
00425 MaxNumberOfCards = GetStackLength(StackLocations[s]);
00426
00427 for(NumberOfCards=0;NumberOfCards<MaxNumberOfCards;NumberOfCards++)
00428 {
00429 for(s = 0; s<DebugInfo->m_NumberOfStacks; s++)
00430 {
00431 if (NumberOfCards >= GetStackLength(StackLocations[s]))
00432 {
00433 strcpy(Str, " ");
00434 Str += strlen(Str);
00435 }
00436 else
00437 {
00438 TempCard = GetStackCard(StackLocations[s], NumberOfCards);
00439 Str += sprintf(Str, "%3s ",
00440 TempCard->Perl2User(StackCards, (DebugInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_10_AS_T),
00441 DebugInfo->m_DisplayDebug));
00442 }
00443 }
00444 strcpy(Str, "\n");
00445 Str += strlen(Str);
00446 }
00447 }
00448 else
00449 {
00450
00451 Str += sprintf(Str, "Foundations: ");
00452 for(a=0;a<DebugInfo->m_NumberOfDecks;a++)
00453 {
00454 Str += sprintf(Str,
00455 "H-%s C-%s D-%s S-%s ",
00456 Decks[a*4],
00457 Decks[a*4+1],
00458 Decks[a*4+2],
00459 Decks[a*4+3]
00460 );
00461 }
00462 Str += sprintf(Str, "\nFreecells: ");
00463
00464 for(a=0;a<DebugInfo->m_NumberOfFreecells;a++)
00465 {
00466 TempCard = GetFreecellCard(FreecellLocations[a]);
00467 Str += sprintf(Str, "%3s",
00468 TempCard->Perl2User(Freecells, (DebugInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_10_AS_T),
00469 DebugInfo->m_DisplayDebug)
00470 );
00471 if (a < DebugInfo->m_NumberOfFreecells-1)
00472 {
00473 *(Str++) = ' ';
00474 *Str = '\0';
00475 }
00476 }
00477 *(Str++) = '\n';
00478 *Str = '\0';
00479
00480 for(s=0;s<DebugInfo->m_NumberOfStacks;s++)
00481 {
00482 strcpy(Str, ": ");
00483 Str += strlen(Str);
00484
00485 Length = GetStackLength(StackLocations[s]);
00486 for(NumberOfCards=0;NumberOfCards<Length;NumberOfCards++)
00487 {
00488 TempCard = GetStackCard(StackLocations[s], NumberOfCards);
00489 TempCard->Perl2User(StackCards, (DebugInfo->m_DisplayDebugOptions & DEBUG_DISPLAY_10_AS_T),
00490 DebugInfo->m_DisplayDebug);
00491
00492 strcpy(Str, StackCards);
00493 Str += strlen(Str);
00494 if (NumberOfCards < Length-1)
00495 {
00496 strcpy(Str, " ");
00497 Str += strlen(Str);
00498 }
00499 }
00500 strcpy(Str,"\n");
00501 Str += strlen(Str);
00502 }
00503 }
00504 }
00505
00506 void FCSStateWithLocations::CleanState()
00507 {
00508 }
00509
00510 void FCSStateWithLocations::CacheStacks(AFCSGenericStackStorage* Storage, int StackNumber)
00511 {
00512 }
00513
00514 void FCSStateWithLocations::Initialize(int NumberOfStacks)
00515 {
00516 }
00517
00518 int GetFCSStateWithLocationsClassSize()
00519 {
00520 switch(GlobalStateType)
00521 {
00522 case FC_DEBUG_STATE:
00523 return sizeof(FCSDebugStateWithLocations<FCSStateWithLocations>);
00524 case FC_COMPACT_STATE:
00525 return sizeof(FCSCompactStateWithLocations<FCSStateWithLocations>);
00526 case FC_INDIRECT_STATE:
00527 return sizeof(FCSIndirectStateWithLocations<FCSStateWithLocations>);
00528 case FC_TALON_DEBUG_STATE:
00529 return sizeof(FCSDebugTalonStateWithLocations);
00530 case FC_TALON_COMPACT_STATE:
00531 return sizeof(FCSCompactTalonStateWithLocations);
00532 case FC_TALON_INDIRECT_STATE:
00533 return sizeof(FCSIndirectTalonStateWithLocations);
00534 default:
00535 return 0;
00536 }
00537 }
00538
00539 FCSStateWithLocations* CreateStateWithLocations()
00540 {
00541 switch(GlobalStateType)
00542 {
00543 case FC_DEBUG_STATE:
00544 return new FCSDebugStateWithLocations<FCSStateWithLocations>();
00545 case FC_COMPACT_STATE:
00546 return new FCSCompactStateWithLocations<FCSStateWithLocations>();
00547 case FC_INDIRECT_STATE:
00548 return new FCSIndirectStateWithLocations<FCSStateWithLocations>();
00549 case FC_TALON_DEBUG_STATE:
00550 return new FCSDebugTalonStateWithLocations();
00551 case FC_TALON_COMPACT_STATE:
00552 return new FCSCompactTalonStateWithLocations();
00553 case FC_TALON_INDIRECT_STATE:
00554 return new FCSIndirectTalonStateWithLocations();
00555 default:
00556 return NULL;
00557 }
00558 }
00559
00560 AFCSStateWithLocationsMatrix* CreateStateWithLocationsMatrix(int Size)
00561 {
00562 switch(GlobalStateType)
00563 {
00564 case FC_DEBUG_STATE:
00565 return new FCSStateWithLocationsMatrix<FCSDebugStateWithLocations<FCSStateWithLocations> >(Size);
00566 case FC_COMPACT_STATE:
00567 return new FCSStateWithLocationsMatrix<FCSCompactStateWithLocations<FCSStateWithLocations> >(Size);
00568 case FC_INDIRECT_STATE:
00569 return new FCSStateWithLocationsMatrix<FCSIndirectStateWithLocations<FCSStateWithLocations> >(Size);
00570 case FC_TALON_DEBUG_STATE:
00571 return new FCSStateWithLocationsMatrix<FCSDebugTalonStateWithLocations>(Size);
00572 case FC_TALON_COMPACT_STATE:
00573 return new FCSStateWithLocationsMatrix<FCSCompactTalonStateWithLocations>(Size);
00574 case FC_TALON_INDIRECT_STATE:
00575 return new FCSStateWithLocationsMatrix<FCSIndirectTalonStateWithLocations>(Size);
00576 default:
00577 return NULL;
00578 }
00579 }
00580
00581 void ReallocStateWithLocationsArray(FCSStateWithLocations*** Array, int OldSize, int NewSize)
00582 {
00583 switch (GlobalStateType)
00584 {
00585 case FC_DEBUG_STATE:
00586 Realloc<FCSDebugStateWithLocations<FCSStateWithLocations>*>((FCSDebugStateWithLocations<FCSStateWithLocations>***)Array, OldSize, NewSize);
00587 break;
00588 case FC_COMPACT_STATE:
00589 Realloc<FCSCompactStateWithLocations<FCSStateWithLocations>*>((FCSCompactStateWithLocations<FCSStateWithLocations>***)Array, OldSize, NewSize);
00590 break;
00591 case FC_INDIRECT_STATE:
00592 Realloc<FCSIndirectStateWithLocations<FCSStateWithLocations>*>((FCSIndirectStateWithLocations<FCSStateWithLocations>***)Array, OldSize, NewSize);
00593 break;
00594 case FC_TALON_DEBUG_STATE:
00595 Realloc<FCSDebugTalonStateWithLocations*>((FCSDebugTalonStateWithLocations***)Array, OldSize, NewSize);
00596 break;
00597 case FC_TALON_COMPACT_STATE:
00598 Realloc<FCSCompactTalonStateWithLocations*>((FCSCompactTalonStateWithLocations***)Array, OldSize, NewSize);
00599 break;
00600 case FC_TALON_INDIRECT_STATE:
00601 Realloc<FCSIndirectTalonStateWithLocations*>((FCSIndirectTalonStateWithLocations***)Array, OldSize, NewSize);
00602 break;
00603 default:
00604
00605 assert(false);
00606 }
00607 }
00608
00609
00610 FCSStateWithLocations* CreateInitialState(const char *String, int NumberOfFreecells,
00611 int NumberOfStacks, int NumberOfDecks, FCSTalonType TalonType)
00612 {
00613 if (TalonType == FCS_TALON_NONE)
00614 return FCSStateWithLocations::CreateInitialState(String, NumberOfFreecells,
00615 NumberOfStacks, NumberOfDecks);
00616
00617 return FCSTalonStateWithLocations::CreateInitialState(String, NumberOfFreecells,
00618 NumberOfStacks, NumberOfDecks, TalonType);
00619 }
00620
00621 int MD5StateWithLocationsHashAlgorithm::Hash(const FCSStateWithLocations* Key)
00622 {
00623 unsigned char HashValue[MD5_HASHBYTES];
00624 int RealHashValue;
00625
00626 m_MD5Hash.Init();
00627 m_MD5Hash.Update((unsigned char*)(((FCSStateWithLocations*)Key)->GetState()), ((FCSStateWithLocations*)Key)->GetState()->GetClassSize());
00628 m_MD5Hash.Final(HashValue);
00629
00630 RealHashValue = (*(int*)HashValue);
00631 if (RealHashValue < 0)
00632 {
00633
00634
00635 RealHashValue &= (~(1<<((sizeof(RealHashValue)<<3)-1)));
00636 }
00637
00638 return RealHashValue;
00639 }