1 /* 2 Copyright (C) 2005-2007 Tom Beaumont 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program; if not, write to the Free Software 16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 */ 18 19 20 struct HexPuzzle; 21 22 class LevelSave 23 { 24 friend struct HexPuzzle; 25 26 // CHECKME: If char is larger than 8 bits (== 1 byte???) 27 // the code is no longer big endian save? SWAP16/32 is necessary? 28 // Or is a byte always of the same size as char, e.g. 16 bits, so 29 // that int16_t is equally saved on big and little endian systems? 30 char * bestSolution; 31 int32_t bestSolutionLength; 32 int32_t bestScore; 33 #define NUM_LAST_SCORES 19 34 int32_t lastScores[NUM_LAST_SCORES]; 35 int32_t unlocked; 36 public: LevelSave()37 LevelSave() 38 { 39 Clear(); 40 } Clear()41 void Clear() 42 { 43 unlocked = 0; 44 bestSolution = 0; 45 bestScore = 0; 46 bestSolutionLength = 0; 47 memset(lastScores, 0, sizeof(lastScores)); 48 } LoadSave(FILE * f,bool save)49 void LoadSave(FILE* f, bool save) 50 { 51 typedef unsigned int _fn(void*, unsigned int, unsigned int, FILE*); 52 _fn * fn = save ? (_fn*)fwrite : (_fn*)fread; 53 54 // we write little endian data 55 bestSolutionLength = SWAP32(bestSolutionLength); 56 bestScore = SWAP32(bestScore); 57 for (int i=0; i<NUM_LAST_SCORES; ++i) 58 lastScores[i] = SWAP32(lastScores[i]); 59 unlocked = SWAP32(unlocked); 60 61 fn(&bestSolutionLength, sizeof(bestSolutionLength), 1, f); 62 fn(&bestScore, sizeof(bestScore), 1, f); 63 fn(&lastScores, sizeof(lastScores), 1, f); 64 fn(&unlocked, sizeof(unlocked), 1, f); 65 66 bestSolutionLength = SWAP32(bestSolutionLength); 67 bestScore = SWAP32(bestScore); 68 for (int i=0; i<NUM_LAST_SCORES; ++i) 69 lastScores[i] = SWAP32(lastScores[i]); 70 unlocked = SWAP32(unlocked); 71 72 if (bestSolutionLength) 73 { 74 if (!save) SetSolution(bestSolutionLength); 75 fn(bestSolution, sizeof(bestSolution[0]), bestSolutionLength, f); 76 } 77 } 78 Dump()79 void Dump() 80 { 81 for (int j=1; j<NUM_LAST_SCORES; j++) 82 if (lastScores[j]==lastScores[0]) 83 lastScores[j] = 0; 84 85 /* for (int i=0; i<NUM_LAST_SCORES && lastScores[i]; i++) 86 if (lastScores[i] != bestScore) 87 printf("\t% 8d\n", lastScores[i]);*/ 88 } Completed()89 bool Completed() 90 { 91 return bestScore != 0; 92 } IsNewCompletionBetter(int score)93 bool IsNewCompletionBetter(int score) 94 { 95 for (int i=0; i<NUM_LAST_SCORES; i++) 96 { 97 if (lastScores[i]==0) 98 lastScores[i] = score; 99 if (lastScores[i]==score) 100 break; 101 } 102 103 if (!Completed()) 104 return true; 105 106 return score <= bestScore; 107 } BeatsPar(int par)108 bool BeatsPar(int par) 109 { 110 if (!Completed()) 111 return false; 112 return bestScore < par; 113 } PassesPar(int par)114 bool PassesPar(int par) 115 { 116 if (!Completed()) 117 return false; 118 return bestScore <= par; 119 } GetScore()120 int GetScore() 121 { 122 return bestScore; 123 } SetScore(int s)124 void SetScore(int s) 125 { 126 bestScore = s; 127 } SetSolution(int l)128 void SetSolution(int l) { 129 delete [] bestSolution; 130 bestSolutionLength = l; 131 bestSolution = new char [ l ]; 132 } SetSolutionStep(int pos,int val)133 void SetSolutionStep(int pos, int val) 134 { 135 bestSolution[pos] = val; 136 } 137 }; 138 139 class SaveState 140 { 141 struct X : public LevelSave 142 { 143 X* next; 144 char* name; 145 nextX146 X(const char* n, X* nx=0) : next(nx) 147 { 148 name = new char[strlen(n)+1]; 149 strcpy(name, n); 150 } ~XX151 ~X() 152 { 153 delete [] name; 154 } 155 }; 156 157 struct General { 158 /// Change big endian data into little endian data, do nothing on little endian systems SwapBytesGeneral159 void SwapBytes() 160 { 161 scoringOn = SWAP32(scoringOn); 162 hintFlags = SWAP32(hintFlags); 163 completionPercentage = SWAP32(completionPercentage); 164 endSequence = SWAP32(endSequence); 165 masteredPercentage = SWAP32(masteredPercentage); 166 for (unsigned int i=0; i<sizeof(pad)/sizeof(int32_t); ++i) 167 pad[i] = SWAP32(pad[i]); 168 } 169 int32_t scoringOn; 170 int32_t hintFlags; 171 int32_t completionPercentage; 172 int32_t endSequence; 173 int32_t masteredPercentage; 174 int32_t pad[6]; 175 }; 176 177 X* first; 178 ClearRaw()179 void ClearRaw() 180 { 181 memset(&general, 0, sizeof(general)); 182 general.hintFlags = 1<<31 | 1<<30; 183 184 X* x=first; 185 while (x) 186 { 187 X* nx = x->next; 188 delete x; 189 x = nx; 190 } 191 first = 0; 192 193 } 194 195 public: 196 197 General general; 198 199 SaveState()200 SaveState() : first(0) 201 { 202 Clear(); 203 } 204 ~SaveState()205 ~SaveState() 206 { 207 ClearRaw(); 208 } 209 Clear()210 void Clear() 211 { 212 ClearRaw(); 213 ApplyStuff(); 214 } 215 216 void GetStuff(); 217 void ApplyStuff(); 218 LoadSave(FILE * f,bool save)219 void LoadSave(FILE* f, bool save) 220 { 221 if (save) 222 { 223 GetStuff(); 224 225 //printf("----\n"); 226 227 fputc('2', f); 228 general.SwapBytes(); // big==>little endian 229 fwrite(&general, sizeof(general), 1, f); 230 general.SwapBytes(); // revert changes 231 for(X* x=first; x; x=x->next) 232 { 233 int16_t len = strlen(x->name); 234 len = SWAP16(len); 235 fwrite(&len, sizeof(len), 1, f); 236 len = SWAP16(len); 237 fwrite(x->name, 1, len, f); 238 239 x->LoadSave(f,save); 240 241 if (x->Completed()) 242 { 243 //printf("% 8d %s\n", x->GetScore(), x->name); 244 x->Dump(); 245 } 246 } 247 } 248 else 249 { 250 ClearRaw(); 251 int v = fgetc(f); 252 if (v=='2') 253 { 254 fread(&general, sizeof(general), 1, f); 255 general.SwapBytes(); 256 v = '1'; 257 } 258 if (v=='1') 259 { 260 while(!feof(f)) 261 { 262 char temp[1000]; 263 int16_t len; 264 fread(&len, sizeof(len), 1, f); 265 len = SWAP16(len); 266 if (feof(f)) break; 267 fread(temp, len, 1, f); 268 temp[len] = 0; 269 first = new X(temp, first); 270 271 first->LoadSave(f,save); 272 } 273 } 274 275 ApplyStuff(); 276 } 277 } 278 GetLevel(const char * name,bool create)279 LevelSave* GetLevel(const char * name, bool create) 280 { 281 const char * l = strstr(name, "Levels"); 282 if (l) 283 name = l; 284 285 X* x = first; 286 if (x && strcmp(name, x->name)==0) return x; 287 while (x && x->next) 288 { 289 if (strcmp(name, x->next->name)==0) return x->next; 290 x = x->next; 291 } 292 if (create) 293 { 294 X* n = new X(name); 295 if (x) 296 x->next = n; 297 else 298 first = n; 299 return n; 300 } 301 else 302 { 303 return 0; 304 } 305 } 306 }; 307