root/trunk/src/save.c

Revision 849, 17.8 kB (checked in by takkaria, 3 weeks ago)

Move the monster spell flags into their own spell array. Patch by Kenneth Boyd. (Patch Message-ID: <47F2627D.7010300@zaimoni.com>)

Line 
1 /*
2  * File: save.c
3  * Purpose: Old-style savefile saving
4  *
5  * Copyright (c) 1997 Ben Harrison
6  *
7  * This work is free software; you can redistribute it and/or modify it
8  * under the terms of either:
9  *
10  * a) the GNU General Public License as published by the Free Software
11  *    Foundation, version 2, or
12  *
13  * b) the "Angband licence":
14  *    This software may be copied and distributed for educational, research,
15  *    and not for profit purposes provided that this copyright and statement
16  *    are included in all such copies.  Other copyrights may also apply.
17  */
18 #include "angband.h"
19 #include "option.h"
20
21
22
23
24 /*
25  * Some "local" parameters, used to help write savefiles
26  */
27
28 static ang_file *fff;           /* Current save "file" */
29
30 static byte     xor_byte;       /* Simple encryption */
31
32 static u32b     v_stamp = 0L;   /* A simple "checksum" on the actual values */
33 static u32b     x_stamp = 0L;   /* A simple "checksum" on the encoded bytes */
34
35
36
37 /*
38  * These functions place information into a savefile a byte at a time
39  */
40
41 static void sf_put(byte v)
42 {
43         /* Encode the value, write a character */
44         xor_byte ^= v;
45         file_writec(fff, xor_byte);
46
47         /* Maintain the checksum info */
48         v_stamp += v;
49         x_stamp += xor_byte;
50 }
51
52 static void wr_byte(byte v)
53 {
54         sf_put(v);
55 }
56
57 static void wr_u16b(u16b v)
58 {
59         sf_put((byte)(v & 0xFF));
60         sf_put((byte)((v >> 8) & 0xFF));
61 }
62
63 static void wr_s16b(s16b v)
64 {
65         wr_u16b((u16b)v);
66 }
67
68 static void wr_u32b(u32b v)
69 {
70         sf_put((byte)(v & 0xFF));
71         sf_put((byte)((v >> 8) & 0xFF));
72         sf_put((byte)((v >> 16) & 0xFF));
73         sf_put((byte)((v >> 24) & 0xFF));
74 }
75
76 static void wr_s32b(s32b v)
77 {
78         wr_u32b((u32b)v);
79 }
80
81 static void wr_string(cptr str)
82 {
83         while (*str)
84         {
85                 wr_byte(*str);
86                 str++;
87         }
88         wr_byte(*str);
89 }
90
91
92 /*
93  * These functions write info in larger logical records
94  */
95
96
97 /*
98  * Write an "item" record
99  */
100 static void wr_item(const object_type *o_ptr)
101 {
102         wr_s16b(o_ptr->k_idx);
103
104         /* Location */
105         wr_byte(o_ptr->iy);
106         wr_byte(o_ptr->ix);
107
108         wr_byte(o_ptr->tval);
109         wr_byte(o_ptr->sval);
110         wr_s16b(o_ptr->pval);
111
112         wr_byte(o_ptr->pseudo);
113
114         wr_byte(o_ptr->number);
115         wr_s16b(o_ptr->weight);
116
117         wr_byte(o_ptr->name1);
118         wr_byte(o_ptr->name2);
119
120         wr_s16b(o_ptr->timeout);
121
122         wr_s16b(o_ptr->to_h);
123         wr_s16b(o_ptr->to_d);
124         wr_s16b(o_ptr->to_a);
125         wr_s16b(o_ptr->ac);
126         wr_byte(o_ptr->dd);
127         wr_byte(o_ptr->ds);
128
129         wr_byte(o_ptr->ident);
130
131         wr_byte(o_ptr->marked);
132
133         wr_byte(o_ptr->origin);
134         wr_byte(o_ptr->origin_depth);
135         wr_u16b(o_ptr->origin_xtra);
136
137         wr_u32b(o_ptr->flags1);
138         wr_u32b(o_ptr->flags2);
139         wr_u32b(o_ptr->flags3);
140
141         /* Held by monster index */
142         wr_s16b(o_ptr->held_m_idx);
143
144         /* Save the inscription (if any) */
145         if (o_ptr->note)
146         {
147                 wr_string(quark_str(o_ptr->note));
148         }
149         else
150         {
151                 wr_string("");
152         }
153 }
154
155
156 /*
157  * Write a "monster" record
158  */
159 static void wr_monster(const monster_type *m_ptr)
160 {
161         wr_s16b(m_ptr->r_idx);
162         wr_byte(m_ptr->fy);
163         wr_byte(m_ptr->fx);
164         wr_s16b(m_ptr->hp);
165         wr_s16b(m_ptr->maxhp);
166         wr_s16b(m_ptr->csleep);
167         wr_byte(m_ptr->mspeed);
168         wr_byte(m_ptr->energy);
169         wr_byte(m_ptr->stunned);
170         wr_byte(m_ptr->confused);
171         wr_byte(m_ptr->monfear);
172         wr_byte(0);
173 }
174
175
176 /*
177  * Write a "lore" record
178  */
179 static void wr_lore(int r_idx)
180 {
181         int i;
182
183         monster_race *r_ptr = &r_info[r_idx];
184         monster_lore *l_ptr = &l_list[r_idx];
185
186         /* Count sights/deaths/kills */
187         wr_s16b(l_ptr->sights);
188         wr_s16b(l_ptr->deaths);
189         wr_s16b(l_ptr->pkills);
190         wr_s16b(l_ptr->tkills);
191
192         /* Count wakes and ignores */
193         wr_byte(l_ptr->wake);
194         wr_byte(l_ptr->ignore);
195
196         /* Count drops */
197         wr_byte(l_ptr->drop_gold);
198         wr_byte(l_ptr->drop_item);
199
200         /* Count spells */
201         wr_byte(l_ptr->cast_innate);
202         wr_byte(l_ptr->cast_spell);
203
204         /* Count blows of each type */
205         for (i = 0; i < MONSTER_BLOW_MAX; i++)
206                 wr_byte(l_ptr->blows[i]);
207
208         /* Memorize flags */
209         for (i = 0; i < RACE_FLAG_STRICT_UB; i++)
210                 wr_u32b(l_ptr->flags[i]);
211         for (i = 0; i < RACE_FLAG_SPELL_STRICT_UB; i++)
212                 wr_u32b(l_ptr->spell_flags[i]);
213
214
215         /* Monster limit per level */
216         wr_byte(r_ptr->max_num);
217
218         /* Later (?) */
219         wr_byte(0);
220         wr_byte(0);
221         wr_byte(0);
222 }
223
224
225 /*
226  * Write an "xtra" record
227  */
228 static void wr_xtra(int k_idx)
229 {
230         byte tmp8u = 0;
231
232         object_kind *k_ptr = &k_info[k_idx];
233
234         if (k_ptr->aware) tmp8u |= 0x01;
235         if (k_ptr->tried) tmp8u |= 0x02;
236         if (k_ptr->squelch) tmp8u |= 0x04;
237         if (k_ptr->everseen) tmp8u |= 0x08;
238
239         wr_byte(tmp8u);
240 }
241
242
243 /*
244  * Write a "store" record
245  */
246 static void wr_store(const store_type *st_ptr)
247 {
248         int j;
249
250         /* XXX Old value (<= Angband 3.0.3) */
251         wr_u32b(0L);
252
253         /* XXX Old value (<= Angband 3.0.3) */
254         wr_s16b(0);
255
256         /* Save the current owner */
257         wr_byte(st_ptr->owner);
258
259         /* Save the stock size */
260         wr_byte(st_ptr->stock_num);
261
262         /* XXX Old values (<= Angband 3.0.3) */
263         wr_s16b(0);
264         wr_s16b(0);
265
266         /* Save the stock */
267         for (j = 0; j < st_ptr->stock_num; j++)
268         {
269                 /* Save each item in stock */
270                 wr_item(&st_ptr->stock[j]);
271         }
272 }
273
274
275 /*
276  * Write RNG state
277  */
278 static errr wr_randomizer(void)
279 {
280         int i;
281
282         /* Zero */
283         wr_u16b(0);
284
285         /* Place */
286         wr_u16b(Rand_place);
287
288         /* State */
289         for (i = 0; i < RAND_DEG; i++)
290         {
291                 wr_u32b(Rand_state[i]);
292         }
293
294         /* Success */
295         return (0);
296 }
297
298
299 /*
300  * Write the "options"
301  */
302 static void wr_options(void)
303 {
304         int i, k;
305
306         u32b flag[8];
307         u32b mask[8];
308         u32b window_flag[ANGBAND_TERM_MAX];
309         u32b window_mask[ANGBAND_TERM_MAX];
310
311
312         /*** Oops ***/
313
314         /* Oops */
315         for (i = 0; i < 4; i++) wr_u32b(0L);
316
317
318         /*** Special Options ***/
319
320         /* Write "delay_factor" */
321         wr_byte(op_ptr->delay_factor);
322
323         /* Write "hitpoint_warn" */
324         wr_byte(op_ptr->hitpoint_warn);
325
326         /* Write movement delay */
327         wr_u16b(lazymove_delay);
328
329
330         /*** Normal options ***/
331
332         /* Reset */
333         for (i = 0; i < 8; i++)
334         {
335                 flag[i] = 0L;
336                 mask[i] = 0L;
337         }
338
339         /* Analyze the options */
340         for (i = 0; i < OPT_MAX; i++)
341         {
342                 int os = i / 32;
343                 int ob = i % 32;
344
345                 /* Process real entries */
346                 if (option_name(i))
347                 {
348                         /* Set flag */
349                         if (op_ptr->opt[i])
350                         {
351                                 /* Set */
352                                 flag[os] |= (1L << ob);
353                         }
354
355                         /* Set mask */
356                         mask[os] |= (1L << ob);
357                 }
358         }
359
360         /* Dump the flags */
361         for (i = 0; i < 8; i++) wr_u32b(flag[i]);
362
363         /* Dump the masks */
364         for (i = 0; i < 8; i++) wr_u32b(mask[i]);
365
366
367         /*** Window options ***/
368
369         /* Reset */
370         for (i = 0; i < ANGBAND_TERM_MAX; i++)
371         {
372                 /* Flags */
373                 window_flag[i] = op_ptr->window_flag[i];
374
375                 /* Mask */
376                 window_mask[i] = 0L;
377
378                 /* Build the mask */
379                 for (k = 0; k < 32; k++)
380                 {
381                         /* Set mask */
382                         if (window_flag_desc[k])
383                         {
384                                 window_mask[i] |= (1L << k);
385                         }
386                 }
387         }
388
389         /* Dump the flags */
390         for (i = 0; i < ANGBAND_TERM_MAX; i++) wr_u32b(window_flag[i]);
391
392         /* Dump the masks */
393         for (i = 0; i < ANGBAND_TERM_MAX; i++) wr_u32b(window_mask[i]);
394 }
395
396
397 /*
398  * Hack -- Write the "ghost" info
399  */
400 static void wr_ghost(void)
401 {
402         int i;
403
404         /* Name */
405         wr_string("Broken Ghost");
406
407         /* Hack -- stupid data */
408         for (i = 0; i < 60; i++) wr_byte(0);
409 }
410
411
412 /*
413  * Write autoinscribe & squelch item-quality submenu to the savefile
414  */
415 static void wr_squelch(void)
416 {
417         int i;
418
419         /* Write number of squelch bytes */
420         wr_byte(SQUELCH_BYTES);
421         for (i = 0; i < SQUELCH_BYTES; i++)
422                 wr_byte(squelch_level[i]);
423
424         /* Write ego-item squelch bits */
425         wr_u16b(z_info->e_max);
426         for (i = 0; i < z_info->e_max; i++)
427         {
428                 byte flags = 0;
429
430                 /* Figure out and write the everseen flag */
431                 if (e_info[i].everseen) flags |= 0x02;
432                 wr_byte(flags);
433         }
434
435         /* Write the current number of auto-inscriptions */
436         wr_u16b(inscriptions_count);
437
438         /* Write the autoinscriptions array */
439         for (i = 0; i < inscriptions_count; i++)
440         {
441                 wr_s16b(inscriptions[i].kind_idx);
442                 wr_string(quark_str(inscriptions[i].inscription_idx));
443         }
444
445         return;
446 }
447
448
449 /*
450  * Write some "extra" info
451  */
452 static void wr_extra(void)
453 {
454         int i;
455
456         wr_string(op_ptr->full_name);
457
458         wr_string(p_ptr->died_from);
459
460         wr_string(p_ptr->history);
461
462         /* Race/Class/Gender/Spells */
463         wr_byte(p_ptr->prace);
464         wr_byte(p_ptr->pclass);
465         wr_byte(p_ptr->psex);
466         wr_byte(0);     /* oops */
467
468         wr_byte(p_ptr->hitdie);
469         wr_byte(p_ptr->expfact);
470
471         wr_s16b(p_ptr->age);
472         wr_s16b(p_ptr->ht);
473         wr_s16b(p_ptr->wt);
474
475         /* Dump the stats (maximum and current and birth) */
476         for (i = 0; i < A_MAX; ++i) wr_s16b(p_ptr->stat_max[i]);
477         for (i = 0; i < A_MAX; ++i) wr_s16b(p_ptr->stat_cur[i]);
478         for (i = 0; i < A_MAX; ++i) wr_s16b(p_ptr->stat_birth[i]);
479
480         wr_s16b(p_ptr->ht_birth);
481         wr_s16b(p_ptr->wt_birth);
482         wr_u32b(p_ptr->au_birth);
483
484         /* Padding */
485         wr_u32b(0);
486
487         wr_u32b(p_ptr->au);
488
489
490         wr_u32b(p_ptr->max_exp);
491         wr_u32b(p_ptr->exp);
492         wr_u16b(p_ptr->exp_frac);
493         wr_s16b(p_ptr->lev);
494
495         wr_s16b(p_ptr->mhp);
496         wr_s16b(p_ptr->chp);
497         wr_u16b(p_ptr->chp_frac);
498
499         wr_s16b(p_ptr->msp);
500         wr_s16b(p_ptr->csp);
501         wr_u16b(p_ptr->csp_frac);
502
503         /* Max Player and Dungeon Levels */
504         wr_s16b(p_ptr->max_lev);
505         wr_s16b(p_ptr->max_depth);
506
507         /* More info */
508         wr_s16b(0);     /* oops */
509         wr_s16b(0);     /* oops */
510         wr_s16b(0);     /* oops */
511         wr_s16b(0);     /* oops */
512         wr_s16b(p_ptr->sc);
513         wr_s16b(0);     /* oops */
514
515         wr_s16b(p_ptr->food);
516         wr_s16b(p_ptr->energy);
517         wr_s16b(p_ptr->word_recall);
518         wr_s16b(p_ptr->see_infra);
519         wr_byte(p_ptr->confusing);
520         wr_byte(p_ptr->searching);
521
522         /* Find the number of timed effects */
523         wr_byte(TMD_MAX);
524
525         /* Read all the effects, in a loop */
526         for (i = 0; i < TMD_MAX; i++)
527                 wr_s16b(p_ptr->timed[i]);
528
529         /* Future use */
530         for (i = 0; i < 10; i++) wr_u32b(0L);
531
532         wr_squelch();
533
534         /* Random artifact version */
535         wr_u32b(RANDART_VERSION);
536
537         /* Random artifact seed */
538         wr_u32b(seed_randart);
539
540
541         /* Ignore some flags */
542         wr_u32b(0L);    /* oops */
543         wr_u32b(0L);    /* oops */
544         wr_u32b(0L);    /* oops */
545
546
547         /* Write the "object seeds" */
548         wr_u32b(seed_flavor);
549         wr_u32b(seed_town);
550
551
552         /* Special stuff */
553         wr_u16b(p_ptr->panic_save);
554         wr_u16b(p_ptr->total_winner);
555         wr_u16b(p_ptr->noscore);
556
557
558         /* Write death */
559         wr_byte(p_ptr->is_dead);
560
561         /* Write feeling */
562         wr_byte(feeling);
563
564         /* Turn of last "feeling" */
565         wr_s32b(old_turn);
566
567         /* Current turn */
568         wr_s32b(turn);
569 }
570
571
572 /*
573  * Dump the random artifacts
574  */
575 static void wr_randarts(void)
576 {
577         int i;
578
579         wr_u16b(z_info->a_max);
580
581         for (i = 0; i < z_info->a_max; i++)
582         {
583                 artifact_type *a_ptr = &a_info[i];
584
585                 wr_byte(a_ptr->tval);
586                 wr_byte(a_ptr->sval);
587                 wr_s16b(a_ptr->pval);
588
589                 wr_s16b(a_ptr->to_h);
590                 wr_s16b(a_ptr->to_d);
591                 wr_s16b(a_ptr->to_a);
592                 wr_s16b(a_ptr->ac);
593
594                 wr_byte(a_ptr->dd);
595                 wr_byte(a_ptr->ds);
596
597                 wr_s16b(a_ptr->weight);
598
599                 wr_s32b(a_ptr->cost);
600
601                 wr_u32b(a_ptr->flags1);
602                 wr_u32b(a_ptr->flags2);
603                 wr_u32b(a_ptr->flags3);
604
605                 wr_byte(a_ptr->level);
606                 wr_byte(a_ptr->rarity);
607
608                 wr_byte(a_ptr->effect);
609                 wr_u16b(a_ptr->time_base);
610                 wr_u16b(a_ptr->time_dice);
611                 wr_u16b(a_ptr->time_sides);
612         }
613 }
614
615
616 /*
617  * The cave grid flags that get saved in the savefile
618  */
619 #define IMPORTANT_FLAGS (CAVE_MARK | CAVE_GLOW | CAVE_ICKY | CAVE_ROOM)
620
621
622 /*
623  * Write the current dungeon
624  */
625 static void wr_dungeon(void)
626 {
627         int i, y, x;
628
629         byte tmp8u;
630
631         byte count;
632         byte prev_char;
633
634
635         /*** Basic info ***/
636
637         /* Dungeon specific info follows */
638         wr_u16b(p_ptr->depth);
639         wr_u16b(0);
640         wr_u16b(p_ptr->py);
641         wr_u16b(p_ptr->px);
642         wr_u16b(DUNGEON_HGT);
643         wr_u16b(DUNGEON_WID);
644         wr_u16b(0);
645         wr_u16b(0);
646
647
648         /*** Simple "Run-Length-Encoding" of cave ***/
649
650         /* Note that this will induce two wasted bytes */
651         count = 0;
652         prev_char = 0;
653
654         /* Dump the cave */
655         for (y = 0; y < DUNGEON_HGT; y++)
656         {
657                 for (x = 0; x < DUNGEON_WID; x++)
658                 {
659                         /* Extract the important cave_info flags */
660                         tmp8u = (cave_info[y][x] & (IMPORTANT_FLAGS));
661
662                         /* If the run is broken, or too full, flush it */
663                         if ((tmp8u != prev_char) || (count == MAX_UCHAR))
664                         {
665                                 wr_byte((byte)count);
666                                 wr_byte((byte)prev_char);
667                                 prev_char = tmp8u;
668                                 count = 1;
669                         }
670
671                         /* Continue the run */
672                         else
673                         {
674                                 count++;
675                         }
676                 }
677         }
678
679         /* Flush the data (if any) */
680         if (count)
681         {
682                 wr_byte((byte)count);
683                 wr_byte((byte)prev_char);
684         }
685
686         /** Now dump the cave_info2[][] stuff **/
687
688         /* Note that this will induce two wasted bytes */
689         count = 0;
690         prev_char = 0;
691
692         /* Dump the cave */
693         for (y = 0; y < DUNGEON_HGT; y++)
694         {
695                 for (x = 0; x < DUNGEON_WID; x++)
696                 {
697                         /* Keep all the information from info2 */
698                         tmp8u = cave_info2[y][x];
699
700                         /* If the run is broken, or too full, flush it */
701                         if ((tmp8u != prev_char) || (count == MAX_UCHAR))
702                         {
703                                 wr_byte((byte)count);
704                                 wr_byte((byte)prev_char);
705                                 prev_char = tmp8u;
706                                 count = 1;
707                         }
708
709                         /* Continue the run */
710                         else
711                         {
712                                 count++;
713                         }
714                 }
715         }
716
717         /* Flush the data (if any) */
718         if (count)
719         {
720                 wr_byte((byte)count);
721                 wr_byte((byte)prev_char);
722         }
723
724
725         /*** Simple "Run-Length-Encoding" of cave ***/
726
727         /* Note that this will induce two wasted bytes */
728         count = 0;
729         prev_char = 0;
730
731         /* Dump the cave */
732         for (y = 0; y < DUNGEON_HGT; y++)
733         {
734                 for (x = 0; x < DUNGEON_WID; x++)
735                 {
736                         /* Extract a byte */
737                         tmp8u = cave_feat[y][x];
738
739                         /* If the run is broken, or too full, flush it */
740                         if ((tmp8u != prev_char) || (count == MAX_UCHAR))
741                         {
742                                 wr_byte((byte)count);
743                                 wr_byte((byte)prev_char);
744                                 prev_char = tmp8u;
745                                 count = 1;
746                         }
747
748                         /* Continue the run */
749                         else
750                         {
751                                 count++;
752                         }
753                 }
754         }
755
756         /* Flush the data (if any) */
757         if (count)
758         {
759                 wr_byte((byte)count);
760                 wr_byte((byte)prev_char);
761         }
762
763
764         /*** Compact ***/
765
766         /* Compact the objects */
767         compact_objects(0);
768
769         /* Compact the monsters */
770         compact_monsters(0);
771
772
773         /*** Dump objects ***/
774
775         /* Total objects */
776         wr_u16b(o_max);
777
778         /* Dump the objects */
779         for (i = 1; i < o_max; i++)
780         {
781                 object_type *o_ptr = &o_list[i];
782
783                 /* Dump it */
784                 wr_item(o_ptr);
785         }
786
787
788         /*** Dump the monsters ***/
789
790         /* Total monsters */
791         wr_u16b(mon_max);
792
793         /* Dump the monsters */
794         for (i = 1; i < mon_max; i++)
795         {
796                 monster_type *m_ptr = &mon_list[i];
797
798                 /* Dump it */
799                 wr_monster(m_ptr);
800         }
801 }
802
803
804
805 /*
806  * Actually write a save-file
807  */
808 static void wr_savefile_new(void)
809 {
810         int i;
811
812         u32b now;
813
814         u16b tmp16u;
815         u32b tmp32u;
816
817         /* Guess at the current time */
818         now = time((time_t *)0);
819
820
821         /* Note the operating system */
822         sf_xtra = 0L;
823
824         /* Note when the file was saved */
825         sf_when = now;
826
827         /* Note the number of saves */
828         sf_saves++;
829
830
831         /*** Actually write the file ***/
832
833         /* Dump the file header */
834         xor_byte = 0;
835         wr_byte(VERSION_MAJOR);
836         xor_byte = 0;
837         wr_byte(VERSION_MINOR);
838         xor_byte = 0;
839         wr_byte(VERSION_PATCH);
840         xor_byte = 0;
841         wr_byte(VERSION_EXTRA);
842
843
844         /* Reset the checksum */
845         v_stamp = 0L;
846         x_stamp = 0L;
847
848
849         /* Operating system */
850         wr_u32b(sf_xtra);
851
852
853         /* Time file last saved */
854         wr_u32b(sf_when);
855
856         /* Number of past lives */
857         wr_u16b(sf_lives);
858
859         /* Number of times saved */
860         wr_u16b(sf_saves);
861
862
863         /* Space */
864         wr_u32b(0L);
865         wr_u32b(0L);
866
867
868         /* Write the RNG state */
869         wr_randomizer();
870
871
872         /* Write the boolean "options" */
873         wr_options();
874
875
876         /* Dump the number of "messages" */
877         tmp16u = messages_num();
878         if (tmp16u > 80) tmp16u = 80;
879         wr_u16b(tmp16u);
880
881         /* Dump the messages (oldest first!) */
882         for (i = tmp16u - 1; i >= 0; i--)
883         {
884                 wr_string(message_str((s16b)i));
885                 wr_u16b(message_type((s16b)i));
886         }
887
888
889         /* Dump the monster lore */
890         tmp16u = z_info->r_max;
891         wr_u16b(tmp16u);
892         for (i = 0; i < tmp16u; i++) wr_lore(i);
893
894
895         /* Dump the object memory */
896         tmp16u = z_info->k_max;
897         wr_u16b(tmp16u);
898         for (i = 0; i < tmp16u; i++) wr_xtra(i);
899
900
901         /* Hack -- Dump the quests */
902         tmp16u = MAX_Q_IDX;
903         wr_u16b(tmp16u);
904         for (i = 0; i < tmp16u; i++)
905         {
906                 wr_byte(q_list[i].level);
907                 wr_byte(0);
908                 wr_byte(0);
909                 wr_byte(0);
910         }
911
912         /* Hack -- Dump the artifacts */
913         tmp16u = z_info->a_max;
914         wr_u16b(tmp16u);
915         for (i = 0; i < tmp16u; i++)
916         {
917                 artifact_type *a_ptr = &a_info[i];
918                 wr_byte(a_ptr->cur_num);
919                 wr_byte(0);
920                 wr_byte(0);
921                 wr_byte(0);
922         }
923
924
925         /* Write the "extra" information */
926         wr_extra();
927
928
929         /* Dump the "player hp" entries */
930         tmp16u = PY_MAX_LEVEL;
931         wr_u16b(tmp16u);
932         for (i = 0; i < tmp16u; i++)
933         {
934                 wr_s16b(p_ptr->player_hp[i]);
935         }
936
937
938         /* Write spell data */
939         wr_u16b(PY_MAX_SPELLS);
940
941         for (i = 0; i < PY_MAX_SPELLS; i++)
942         {
943                 wr_byte(p_ptr->spell_flags[i]);
944         }
945
946         /* Dump the ordered spells */
947         for (i = 0; i < PY_MAX_SPELLS; i++)
948         {
949                 wr_byte(p_ptr->spell_order[i]);
950         }
951
952
953         /* Write randart information */
954         if (adult_randarts)
955         {
956                 wr_randarts();
957         }
958
959
960         /* Write the inventory */
961         for (i = 0; i < INVEN_TOTAL; i++)
962         {
963                 object_type *o_ptr = &inventory[i];
964
965                 /* Skip non-objects */
966                 if (!o_ptr->k_idx) continue;
967
968                 /* Dump index */
969                 wr_u16b((u16b)i);
970
971                 /* Dump object */
972                 wr_item(o_ptr);
973         }
974
975         /* Add a sentinel */
976         wr_u16b(0xFFFF);
977
978
979         /* Note the stores */
980         tmp16u = MAX_STORES;
981         wr_u16b(tmp16u);
982
983         /* Dump the stores */
984         for (i = 0; i < tmp16u; i++) wr_store(&store[i]);
985
986
987         /* Player is not dead, write the dungeon */
988         if (!p_ptr->is_dead)
989         {
990                 /* Dump the dungeon */
991                 wr_dungeon();
992
993                 /* Dump the ghost */
994                 wr_ghost();
995         }
996
997         /* NEW (jdw): dumping history entries */
998         /* Dump the number of history entries */
999         tmp32u = history_get_num();
1000         wr_u32b(tmp32u);
1001
1002         /* Dump the history entries one-by-one */
1003         for (i = 0; i < tmp32u; i++)
1004         {
1005                 wr_u16b(history_list[i].type);
1006                 wr_s32b(history_list[i].turn);
1007                 wr_s16b(history_list[i].dlev);
1008                 wr_s16b(history_list[i].clev);
1009                 wr_byte(history_list[i].a_idx);
1010                 wr_string(history_list[i].event);
1011         }
1012
1013
1014         /* Write the "value check-sum" */
1015         wr_u32b(v_stamp);
1016
1017         /* Write the "encoded checksum" */
1018         wr_u32b(x_stamp);
1019 }
1020
1021
1022 /*
1023  * Medium level player saver
1024  */
1025 static bool save_player_aux(cptr name)
1026 {
1027         bool ok = TRUE;
1028
1029         /* No file yet */
1030         fff = NULL;
1031
1032         /* Open the savefile */
1033         safe_setuid_grab();
1034         fff = file_open(name, MODE_WRITE, FTYPE_SAVE);
1035         safe_setuid_drop();
1036
1037         /* Successful open */
1038         if (fff) wr_savefile_new();
1039         else ok = FALSE;
1040
1041         /* Attempt to close it */
1042         if (ok && !file_close(fff)) ok = FALSE;
1043
1044
1045         if (ok)
1046                 character_saved = TRUE;
1047
1048         return ok;
1049 }
1050
1051 #include <errno.h>
1052
1053 /*
1054  * Attempt to save the player in a savefile
1055  */
1056 bool old_save(void)
1057 {
1058         char new_savefile[1024];
1059         char old_savefile[1024];
1060
1061         /* New savefile */
1062         strnfmt(new_savefile, sizeof(new_savefile), "%s.new", savefile);
1063         strnfmt(old_savefile, sizeof(old_savefile), "%s.old", savefile);
1064
1065         /* Make sure that the savefile doesn't already exist */
1066         safe_setuid_grab();
1067         file_delete(new_savefile);
1068         file_delete(old_savefile);
1069         safe_setuid_drop();
1070
1071         /* Attempt to save the player */
1072         if (save_player_aux(new_savefile))
1073         {
1074                 safe_setuid_grab();
1075
1076                 file_move(savefile, old_savefile);
1077                 file_move(new_savefile, savefile);
1078                 file_delete(old_savefile);
1079
1080                 safe_setuid_drop();