1 #include "game.h"
2 #include "map.h"
3 #include "message.h"
4 
5 typedef struct ASSOCIATIVE ASSOCIATIVE;
6 struct ASSOCIATIVE
7 {
8 	char *str;
9 	int val;
10 	ASSOCIATIVE *next;
11 };
12 ASSOCIATIVE *ass_linked = NULL;
13 
14 static void
ass_add(char * str,int val)15 ass_add (char *str, int val)
16 {
17 	ASSOCIATIVE *ass = malloc (sizeof *ass);
18 	ass->str = strdup (str);
19 	ass->val = val;
20 	ass->next = ass_linked;
21 	ass_linked = ass;
22 }
23 
24 static void
ass_read(PACKFILE * file)25 ass_read (PACKFILE *file)
26 {
27 	char str[100];
28 	PACKFILE *chunk;
29 	chunk = pack_fopen_chunk (file, 0);
30 	while (!pack_feof (chunk))
31 	{
32 		int p;
33 		for (p = 0; (str[p] = pack_getc (chunk)); p++);
34 		ass_add (str, pack_igetl (chunk));
35 	}
36 	pack_fclose_chunk (chunk);
37 }
38 
39 static void
ass_get(char const * str,int * ptr)40 ass_get (char const *str, int *ptr)
41 {
42 	ASSOCIATIVE *ass = ass_linked;
43 	for (; ass; ass = ass->next)
44 	{
45 
46 		if (!strcmp (str, ass->str))
47 		{
48 			*ptr = ass->val;
49 			break;
50 		}
51 	}
52 }
53 
54 static void
ass_clear(void)55 ass_clear (void)
56 {
57 	ASSOCIATIVE *ass = ass_linked, *next;
58 	for (; ass; ass = next)
59 	{
60 		next = ass->next;
61 		free (ass);
62 	}
63 	ass_linked = NULL;
64 }
65 
66 #define save(var) \
67 	pack_fwrite (#var, strlen (#var), chunk); \
68 	pack_putc ('\0', chunk); \
69 	pack_iputl (var, chunk);
70 
71 #define load(var) \
72 	ass_get (#var, &var);
73 
74 
75 static void
save_char(PACKFILE * file,int id)76 save_char (PACKFILE *file, int id)
77 {
78 	int type = list[id].type;
79 	PACKFILE *chunk;
80 	chunk = pack_fopen_chunk (file, 0);
81 	save (type);
82 	save (list[id].subtype);
83 	save (list[id].x);
84 	save (list[id].y);
85 	save (list[id].dx);
86 	save (list[id].dy);
87 	save (list[id].step);
88 	save (list[id].hit);
89 	save (list[id].alive);
90 	save (list[id].fighting);
91 	save (list[id].trapped);
92 	save (list[id].attacked);
93 	save (list[id].healing_time);
94 	save (list[id].delay);
95 	save (list[id].exp);
96 	save (list[id].next);
97 	save (list[id].lev);
98 	save (list[id].maxhit);
99 	save (list[id].dex);
100 	save (list[id].current_level);
101 	save (list[id].slain_foes[0]);
102 	save (list[id].slain_foes[1]);
103 	save (list[id].slain_foes[2]);
104 	save (list[id].slain_foes[3]);
105 	save (list[id].slain_foes[4]);
106 	save (list[id].slain_foes[5]);
107 	save (list[id].slain_foes[6]);
108 	save (list[id].slain_foes[7]);
109 	save (list[id].slain_foes[8]);
110 	save (list[id].slain_foes[9]);
111 	save (list[id].slain_foes[10]);
112 	save (list[id].slain_foes[11]);
113 	save (list[id].slain_foes[12]);
114 	save (list[id].slain_foes[13]);
115 	save (list[id].slain_foes[14]);
116 	save (list[id].slain_foes[15]);
117 	save (list[id].slain_foes[16]);
118 	save (list[id].slain_foes[17]);
119 	save (list[id].slain_foes[18]);
120 	save (list[id].slain_foes[19]);
121 	save (list[id].slain_foes[20]);
122 	save (list[id].deepest_level);
123 	save (list[id].potions);
124 	save (list[id].sacks);
125 	save (list[id].beacons);
126 	save (list[id].gold);
127 	save (list[id].weapon);
128 	save (list[id].map);
129 	save (list[id].sword);
130 	save (list[id].spells[0].amount);
131 	save (list[id].spells[0].active);
132 	save (list[id].spells[0].max);
133 	save (list[id].spells[1].amount);
134 	save (list[id].spells[1].active);
135 	save (list[id].spells[1].max);
136 	save (list[id].spells[2].amount);
137 	save (list[id].spells[2].active);
138 	save (list[id].spells[2].max);
139 	save (list[id].spells[3].amount);
140 	save (list[id].spells[3].active);
141 	save (list[id].spells[3].max);
142 	save (list[id].spells[4].amount);
143 	save (list[id].spells[4].active);
144 	save (list[id].spells[4].max);
145 	save (list[id].spells[5].amount);
146 	save (list[id].spells[5].active);
147 	save (list[id].spells[5].max);
148 	save (list[id].beaconx);
149 	save (list[id].beacony);
150 	save (list[id].sacrificed_gold);
151 	save (list[id].amulets_of_healing);
152 	save (list[id].amulets_of_light);
153 
154 	pack_fclose_chunk (chunk);
155 }
156 
157 static void
load_char(PACKFILE * file,int id)158 load_char (PACKFILE *file, int id)
159 {
160 	int type;
161 
162 	memset (&list[id], 0, sizeof list[id]);
163 
164 	ass_read (file);
165 	load (type);
166 	list[id].type = type;
167 	load (list[id].subtype);
168 	load (list[id].x);
169 	load (list[id].y);
170 	load (list[id].dx);
171 	load (list[id].dy);
172 	load (list[id].step);
173 	load (list[id].hit);
174 	load (list[id].alive);
175 	load (list[id].fighting);
176 	load (list[id].trapped);
177 	load (list[id].attacked);
178 	load (list[id].healing_time);
179 	load (list[id].delay);
180 	load (list[id].exp);
181 	load (list[id].next);
182 	load (list[id].lev);
183 	load (list[id].maxhit);
184 	load (list[id].dex);
185 	load (list[id].current_level);
186 	load (list[id].slain_foes[0]);
187 	load (list[id].slain_foes[1]);
188 	load (list[id].slain_foes[2]);
189 	load (list[id].slain_foes[3]);
190 	load (list[id].slain_foes[4]);
191 	load (list[id].slain_foes[5]);
192 	load (list[id].slain_foes[6]);
193 	load (list[id].slain_foes[7]);
194 	load (list[id].slain_foes[8]);
195 	load (list[id].slain_foes[9]);
196 	load (list[id].slain_foes[10]);
197 	load (list[id].slain_foes[11]);
198 	load (list[id].slain_foes[12]);
199 	load (list[id].slain_foes[13]);
200 	load (list[id].slain_foes[14]);
201 	load (list[id].slain_foes[15]);
202 	load (list[id].slain_foes[16]);
203 	load (list[id].slain_foes[17]);
204 	load (list[id].slain_foes[18]);
205 	load (list[id].slain_foes[19]);
206 	load (list[id].slain_foes[20]);
207 	load (list[id].deepest_level);
208 	load (list[id].potions);
209 	load (list[id].sacks);
210 	load (list[id].beacons);
211 	load (list[id].gold);
212 	load (list[id].weapon);
213 	load (list[id].map);
214 	load (list[id].sword);
215 	load (list[id].spells[0].amount);
216 	load (list[id].spells[0].active);
217 	load (list[id].spells[0].max);
218 	load (list[id].spells[1].amount);
219 	load (list[id].spells[1].active);
220 	load (list[id].spells[1].max);
221 	load (list[id].spells[2].amount);
222 	load (list[id].spells[2].active);
223 	load (list[id].spells[2].max);
224 	load (list[id].spells[3].amount);
225 	load (list[id].spells[3].active);
226 	load (list[id].spells[3].max);
227 	load (list[id].spells[4].amount);
228 	load (list[id].spells[4].active);
229 	load (list[id].spells[4].max);
230 	load (list[id].spells[5].amount);
231 	load (list[id].spells[5].active);
232 	load (list[id].spells[5].max);
233 	load (list[id].beaconx);
234 	load (list[id].beacony);
235 	load (list[id].sacrificed_gold);
236 	load (list[id].amulets_of_healing);
237 	load (list[id].amulets_of_light);
238 
239 	/* Save-file compatibility */
240 	{
241 		int i = 0;
242 		ass_get ("slain_foes", &i);
243 		list[id].slain_foes[0] += i;
244 	}
245 
246 	ass_clear ();
247 }
248 
249 
250 int
game_save(int nr)251 game_save (int nr)
252 {
253 	char name[256];
254 	PACKFILE *file;
255 
256 	sprintf (name, "data/save%i.dat", nr);
257 	file = pack_fopen (name, "wp");
258 
259 	if (file)
260 	{
261 		int i;
262 		int monster;
263 		PACKFILE *chunk = pack_fopen_chunk (file, 0);
264 		save (notrunning);
265 		save (won);
266 		save (gameover);
267 		save (spiral_map);
268 		save (swordrun);
269 		save (global_steps);
270 		save (char_num);
271 		monster = monster_count ();
272 		save (monster);
273 		save (monster_strength);
274 		save (monster_max);
275 		save (spawnpoints);
276 		save (spawnx[0]);
277 		save (spawny[0]);
278 		save (spawnx[1]);
279 		save (spawny[1]);
280 		save (spawnx[2]);
281 		save (spawny[2]);
282 		save (spawnx[3]);
283 		save (spawny[3]);
284 		save (spawnx[4]);
285 		save (spawny[4]);
286 		save (temple_x);
287 		save (temple_y);
288 		save (swordlev);
289 		save (mrand_seed);
290 		pack_fclose_chunk (chunk);
291 		for (i = 0; i < char_num; i++)
292 			save_char (file, i);
293 
294 		chunk = pack_fopen_chunk (file, 0);
295 		map_save (chunk);
296 		pack_fclose_chunk (chunk);
297 
298 		pack_fclose (file);
299 
300 		sprintf (name, "data/save%i.html", nr);
301 		messages_exit (name);
302 
303 		return 1;
304 	}
305 	return 0;
306 }
307 
308 int
game_load(int nr)309 game_load (int nr)
310 {
311 	char name[256];
312 	PACKFILE *file;
313 
314 	sprintf (name, "data/save%i.dat", nr);
315 	file = pack_fopen (name, "rp");
316 
317 	if (file)
318 	{
319 		int i;
320 		int monster;
321 		PACKFILE *chunk;
322 		ass_read (file);
323 		load (notrunning);
324 		load (won);
325 		load (gameover);
326 		load (spiral_map);
327 		load (swordrun);
328 		load (global_steps);
329 		load (char_num);
330 		load (monster);
331 		monster_set_count (monster);
332 		load (monster_strength);
333 		load (monster_max);
334 		load (spawnpoints);
335 		load (spawnx[0]);
336 		load (spawny[0]);
337 		load (spawnx[1]);
338 		load (spawny[1]);
339 		load (spawnx[2]);
340 		load (spawny[2]);
341 		load (spawnx[3]);
342 		load (spawny[3]);
343 		load (spawnx[4]);
344 		load (spawny[4]);
345 		load (temple_x);
346 		load (temple_y);
347 		load (swordlev);
348 		load (mrand_seed);
349 		ass_clear ();
350 		for (i = 0; i < char_num; i++)
351 			load_char (file, i);
352 
353 		chunk = pack_fopen_chunk (file, 0);
354 		map_load (chunk);
355 		pack_fclose_chunk (chunk);
356 
357 		pack_fclose (file);
358 
359 		sprintf (name, "data/save%i.html", nr);
360 		messages_init (name);
361 		return 1;
362 	}
363 	return 0;
364 }
365 
366 int
game_delete(int nr)367 game_delete (int nr)
368 {
369 	int ret = 1;
370 	char name[256];
371 	sprintf (name, "data/save%i.dat", nr);
372 	if (remove (name))
373 		ret = 0;
374 	sprintf (name, "data/save%i.html", nr);
375 	if (remove (name))
376 		ret = 0;
377 	return ret;
378 }
379