Merge branch 'better-than-par'
[hex-a-hop.git] / savestate.h
blob32cceec8daea0e7e0eeb00bd3d403ce0c9fefa48
1 /*
2 Copyright (C) 2005-2007 Tom Beaumont
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.
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.
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 */
20 struct HexPuzzle;
22 class LevelSave
24 friend struct HexPuzzle;
26 // CHECKME: If char is larger than 8 bits (== 1 byte???)
27 // the code is no longer big endian safe? 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:
37 LevelSave()
39 Clear();
41 void Clear()
43 unlocked = 0;
44 bestSolution = 0;
45 bestScore = 0;
46 bestSolutionLength = 0;
47 memset(lastScores, 0, sizeof(lastScores));
49 void LoadSave(FILE* f, bool save)
51 typedef unsigned int _fn(void*, unsigned int, unsigned int, FILE*);
52 _fn * fn = save ? (_fn*)fwrite : (_fn*)fread;
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);
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);
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);
72 if (bestSolutionLength)
74 if (!save) SetSolution(bestSolutionLength);
75 fn(bestSolution, sizeof(bestSolution[0]), bestSolutionLength, f);
79 void Dump()
81 for (int j=1; j<NUM_LAST_SCORES; j++)
82 if (lastScores[j]==lastScores[0])
83 lastScores[j] = 0;
85 /* for (int i=0; i<NUM_LAST_SCORES && lastScores[i]; i++)
86 if (lastScores[i] != bestScore)
87 printf("\t% 8d\n", lastScores[i]);*/
89 bool Completed()
91 return bestScore != 0;
93 bool IsNewCompletionBetter(int score)
95 for (int i=0; i<NUM_LAST_SCORES; i++)
97 if (lastScores[i]==0)
98 lastScores[i] = score;
99 if (lastScores[i]==score)
100 break;
103 if (!Completed())
104 return true;
106 return score <= bestScore;
108 bool BeatsPar(int par)
110 if (!Completed())
111 return false;
112 return bestScore < par;
114 bool PassesPar(int par)
116 if (!Completed())
117 return false;
118 return bestScore <= par;
120 int GetScore()
122 return bestScore;
124 void SetScore(int s)
126 bestScore = s;
128 void SetSolution(int l) {
129 delete [] bestSolution;
130 bestSolutionLength = l;
131 bestSolution = new char [ l ];
133 void SetSolutionStep(int pos, int val)
135 bestSolution[pos] = val;
139 class SaveState
141 struct X : public LevelSave
143 X* next;
144 char* name;
146 X(const char* n, X* nx=0) : next(nx)
148 name = new char[strlen(n)+1];
149 strcpy(name, n);
151 ~X()
153 delete [] name;
157 struct General {
158 /// Change big endian data into little endian data, do nothing on little endian systems
159 void SwapBytes()
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]);
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];
177 X* first;
179 void ClearRaw()
181 memset(&general, 0, sizeof(general));
182 general.hintFlags = 1<<31 | 1<<30;
184 X* x=first;
185 while (x)
187 X* nx = x->next;
188 delete x;
189 x = nx;
191 first = 0;
195 public:
197 General general;
200 SaveState() : first(0)
202 Clear();
205 ~SaveState()
207 ClearRaw();
210 void Clear()
212 ClearRaw();
213 ApplyStuff();
216 void GetStuff();
217 void ApplyStuff();
219 void LoadSave(FILE* f, bool save)
221 if (save)
223 GetStuff();
225 //printf("----\n");
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)
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);
239 x->LoadSave(f,save);
241 if (x->Completed())
243 //printf("% 8d %s\n", x->GetScore(), x->name);
244 x->Dump();
248 else
250 ClearRaw();
251 int v = fgetc(f);
252 if (v=='2')
254 fread(&general, sizeof(general), 1, f);
255 general.SwapBytes();
256 v = '1';
258 if (v=='1')
260 while(!feof(f))
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);
271 first->LoadSave(f,save);
275 ApplyStuff();
279 LevelSave* GetLevel(const char * name, bool create)
281 char * l = strstr(name, "Levels");
282 if (l)
283 name = l;
285 X* x = first;
286 if (x && strcmp(name, x->name)==0) return x;
287 while (x && x->next)
289 if (strcmp(name, x->next->name)==0) return x->next;
290 x = x->next;
292 if (create)
294 X* n = new X(name);
295 if (x)
296 x->next = n;
297 else
298 first = n;
299 return n;
301 else
303 return 0;