1 /*
2 * File: tags.cc
3 * Summary: Auxilary functions to make savefile versioning simpler.
4 * Written by: Gordon Lipford
5 *
6 * Change History (most recent first):
7 *
8 * <2> 16 Mar 2001 GDL Added TAG_LEVEL_ATTITUDE
9 * <1> 27 Jan 2001 GDL Created
10 */
11
12 /* ------------------------- how tags work ----------------------------------
13
14 1. Tag types are enumerated in enum.h, from TAG_VERSION (more a placeholder
15 than anything else, it is not actually saved as a tag) to TAG_XXX. NUM_TAGS
16 is equal to the actual number of defined tags.
17
18 2. Tags are created with tag_construct(), which forwards the construction
19 request appropriately. tag_write() is then used to write the tag to an
20 output stream.
21
22 3. Tags are parsed with tag_read(), which tries to read a tag header and then
23 forwards the request appropriately, returning the ID of the tag it found,
24 or zero if no tag was found.
25
26 4. In order to know which tags are used by a particular file type, a client
27 calls tag_set_expected( fileType ), which sets up an array of chars.
28 Within the array, a value of 1 means the tag is expected; -1 means that
29 the tag is not expected. A client can then set values in this array to
30 anything other than 1 to indicate a successful tag_read() of that tag.
31
32 5. A case should be provided in tag_missing() for any tag which might be
33 missing from a tagged save file. For example, if a developer adds
34 TAG_YOU_NEW_STUFF to the player save file, he would have to provide a
35 case in tag_missing() for this tag since it might not be there in
36 earlier savefiles. The tags defined with the original tag system (and
37 so not needing cases in tag_missing()) are as follows:
38
39 TAG_YOU = 1, // 'you' structure
40 TAG_YOU_ITEMS, // your items
41 TAG_YOU_DUNGEON, // dungeon specs (stairs, branches, features)
42 TAG_LEVEL, // various grids & clouds
43 TAG_LEVEL_ITEMS, // items/traps
44 TAG_LEVEL_MONSTERS, // monsters
45 TAG_GHOST, // ghost
46
47 6. The marshalling and unmarshalling of data is done in network order and
48 is meant to keep savefiles cross-platform. They are non-ascii - always
49 FTP in binary mode. Note also that the marshalling sizes are 1,2, and 4
50 for byte, short, and long - assuming that 'int' would have been
51 insufficient on 16 bit systems (and that Crawl otherwise lacks
52 system-indepedent data types).
53
54 */
55
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h> // for memcpy
59
60 #ifdef LINUX
61 #include <sys/types.h>
62 #include <sys/stat.h>
63 #include <fcntl.h>
64 #include <unistd.h>
65 #endif
66
67 #ifdef USE_EMX
68 #include <sys/types.h>
69 #include <fcntl.h>
70 #include <unistd.h>
71 #endif
72
73 #ifdef OS9
74 #include <stat.h>
75 #else
76 #include <sys/stat.h>
77 #endif
78
79 #include "AppHdr.h"
80
81 #include "abl-show.h"
82 #include "enum.h"
83 #include "externs.h"
84 #include "files.h"
85 #include "itemname.h"
86 #include "monstuff.h"
87 #include "mon-util.h"
88 #include "randart.h"
89 #include "skills.h"
90 #include "skills2.h"
91 #include "stuff.h"
92 #include "tags.h"
93
94 // THE BIG IMPORTANT TAG CONSTRUCTION/PARSE BUFFER
95 static char *tagBuffer = NULL;
96
97 // These three are defined in overmap.cc
98 extern FixedArray < unsigned char, MAX_LEVELS, MAX_BRANCHES > altars_present;
99 extern FixedVector < char, MAX_BRANCHES > stair_level;
100 extern FixedArray < unsigned char, MAX_LEVELS, MAX_BRANCHES > feature;
101
102 extern unsigned char your_sign; /* these two are defined in view.cc */
103 extern unsigned char your_colour;
104
105 // temp file pairs used for file level cleanup
106 FixedArray < bool, MAX_LEVELS, MAX_BRANCHES > tmp_file_pairs;
107
108
109 // static helpers
110 static void tag_construct_you(struct tagHeader &th);
111 static void tag_construct_you_items(struct tagHeader &th);
112 static void tag_construct_you_dungeon(struct tagHeader &th);
113 static void tag_read_you(struct tagHeader &th, char minorVersion);
114 static void tag_read_you_items(struct tagHeader &th, char minorVersion);
115 static void tag_read_you_dungeon(struct tagHeader &th);
116
117 static void tag_construct_level(struct tagHeader &th);
118 static void tag_construct_level_items(struct tagHeader &th);
119 static void tag_construct_level_monsters(struct tagHeader &th);
120 static void tag_construct_level_attitude(struct tagHeader &th);
121 static void tag_read_level(struct tagHeader &th, char minorVersion);
122 static void tag_read_level_items(struct tagHeader &th, char minorVersion);
123 static void tag_read_level_monsters(struct tagHeader &th, char minorVersion);
124 static void tag_read_level_attitude(struct tagHeader &th);
125 static void tag_missing_level_attitude();
126
127 static void tag_construct_ghost(struct tagHeader &th);
128 static void tag_read_ghost(struct tagHeader &th, char minorVersion);
129
130 // provide a wrapper for file writing, just in case.
write2(FILE * file,char * buffer,unsigned int count)131 int write2(FILE * file, char *buffer, unsigned int count)
132 {
133 return fwrite(buffer, 1, count, file);
134 }
135
136 // provide a wrapper for file reading, just in case.
read2(FILE * file,char * buffer,unsigned int count)137 int read2(FILE * file, char *buffer, unsigned int count)
138 {
139 return fread(buffer, 1, count, file);
140 }
141
marshallByte(struct tagHeader & th,char data)142 void marshallByte(struct tagHeader &th, char data)
143 {
144 tagBuffer[th.offset] = data;
145 th.offset += 1;
146 }
147
unmarshallByte(struct tagHeader & th)148 char unmarshallByte(struct tagHeader &th)
149 {
150 char data = tagBuffer[th.offset];
151 th.offset += 1;
152 return data;
153 }
154
155 // marshall 2 byte short in network order
marshallShort(struct tagHeader & th,short data)156 void marshallShort(struct tagHeader &th, short data)
157 {
158 char b2 = (char)(data & 0x00FF);
159 char b1 = (char)((data & 0xFF00) >> 8);
160
161 tagBuffer[th.offset] = b1;
162 tagBuffer[th.offset + 1] = b2;
163
164 th.offset += 2;
165 }
166
167 // unmarshall 2 byte short in network order
unmarshallShort(struct tagHeader & th)168 short unmarshallShort(struct tagHeader &th)
169 {
170 short b1 = tagBuffer[th.offset];
171 short b2 = tagBuffer[th.offset + 1];
172
173 short data = (b1 << 8) | (b2 & 0x00FF);
174
175 th.offset += 2;
176 return data;
177 }
178
179 // marshall 4 byte int in network order
marshallLong(struct tagHeader & th,long data)180 void marshallLong(struct tagHeader &th, long data)
181 {
182 char b4 = (char) (data & 0x000000FF);
183 char b3 = (char)((data & 0x0000FF00) >> 8);
184 char b2 = (char)((data & 0x00FF0000) >> 16);
185 char b1 = (char)((data & 0xFF000000) >> 24);
186
187 tagBuffer[th.offset] = b1;
188 tagBuffer[th.offset + 1] = b2;
189 tagBuffer[th.offset + 2] = b3;
190 tagBuffer[th.offset + 3] = b4;
191
192 th.offset += 4;
193 }
194
195 // unmarshall 4 byte int in network order
unmarshallLong(struct tagHeader & th)196 long unmarshallLong(struct tagHeader &th)
197 {
198 long b1 = tagBuffer[th.offset];
199 long b2 = tagBuffer[th.offset + 1];
200 long b3 = tagBuffer[th.offset + 2];
201 long b4 = tagBuffer[th.offset + 3];
202
203 long data = (b1 << 24) | ((b2 & 0x000000FF) << 16);
204 data |= ((b3 & 0x000000FF) << 8) | (b4 & 0x000000FF);
205
206 th.offset += 4;
207 return data;
208 }
209
210 // single precision float -- marshall in network order.
marshallFloat(struct tagHeader & th,float data)211 void marshallFloat(struct tagHeader &th, float data)
212 {
213 long intBits = *((long *)(&data));
214 marshallLong(th, intBits);
215 }
216
217 // single precision float -- unmarshall in network order.
unmarshallFloat(struct tagHeader & th)218 float unmarshallFloat(struct tagHeader &th)
219 {
220 long intBits = unmarshallLong(th);
221
222 return *((float *)(&intBits));
223 }
224
225 // string -- marshall length & string data
marshallString(struct tagHeader & th,char * data,int maxSize)226 void marshallString(struct tagHeader &th, char *data, int maxSize)
227 {
228 // allow for very long strings.
229 short len = strlen(data);
230 if (maxSize > 0 && len > maxSize)
231 len = maxSize;
232 marshallShort(th, len);
233
234 // put in the actual string -- we'll null terminate on
235 // unmarshall.
236 memcpy(&tagBuffer[th.offset], data, len);
237
238 th.offset += len;
239 }
240
241 // string -- unmarshall length & string data
unmarshallString(struct tagHeader & th,char * data,int maxSize)242 void unmarshallString(struct tagHeader &th, char *data, int maxSize)
243 {
244 // get length
245 short len = unmarshallShort(th);
246 int copylen = len;
247 if (len > maxSize && maxSize > 0)
248 copylen = maxSize;
249
250 // read the actual string and null terminate
251 memcpy(data, &tagBuffer[th.offset], copylen);
252 data[copylen] = '\0';
253
254 th.offset += len;
255 }
256
257 // boolean (to avoid system-dependant bool implementations)
marshallBoolean(struct tagHeader & th,bool data)258 void marshallBoolean(struct tagHeader &th, bool data)
259 {
260 char charRep = 0; // for false
261 if (data)
262 charRep = 1;
263
264 tagBuffer[th.offset] = charRep;
265 th.offset += 1;
266 }
267
268 // boolean (to avoid system-dependant bool implementations)
unmarshallBoolean(struct tagHeader & th)269 bool unmarshallBoolean(struct tagHeader &th)
270 {
271 bool data;
272
273 if (tagBuffer[th.offset] == 1)
274 data = true;
275 else
276 data = false;
277
278 th.offset += 1;
279 return data;
280 }
281
282 // Saving the date as a string so we're not reliant on a particular epoch.
make_date_string(time_t in_date,char buff[20])283 void make_date_string( time_t in_date, char buff[20] )
284 {
285 if (in_date <= 0)
286 {
287 buff[0] = '\0';
288 return;
289 }
290
291
292 struct tm *date = localtime( &in_date );
293
294 snprintf( buff, 20,
295 "%4d%02d%02d%02d%02d%02d%s",
296 date->tm_year + 1900, date->tm_mon, date->tm_mday,
297 date->tm_hour, date->tm_min, date->tm_sec,
298 ((date->tm_isdst > 0) ? "D" : "S") );
299 }
300
get_val_from_string(const char * ptr,int len)301 static int get_val_from_string( const char *ptr, int len )
302 {
303 int ret = 0;
304 int pow = 1;
305
306 for (const char *chr = ptr + len - 1; chr >= ptr; chr--)
307 {
308 ret += (*chr - '0') * pow;
309 pow *= 10;
310 }
311
312 return (ret);
313 }
314
parse_date_string(char buff[20])315 time_t parse_date_string( char buff[20] )
316 {
317 struct tm date;
318
319 date.tm_year = get_val_from_string( &buff[0], 4 ) - 1900;
320 date.tm_mon = get_val_from_string( &buff[4], 2 );
321 date.tm_mday = get_val_from_string( &buff[6], 2 );
322 date.tm_hour = get_val_from_string( &buff[8], 2 );
323 date.tm_min = get_val_from_string( &buff[10], 2 );
324 date.tm_sec = get_val_from_string( &buff[12], 2 );
325
326 date.tm_isdst = (buff[14] == 'D');
327
328 return (mktime( &date ));
329 }
330
331 // PUBLIC TAG FUNCTIONS
tag_init(long largest_tag)332 void tag_init(long largest_tag)
333 {
334 if (tagBuffer != NULL)
335 return;
336
337 tagBuffer = (char *)malloc(largest_tag);
338 }
339
tag_construct(struct tagHeader & th,int tagID)340 void tag_construct(struct tagHeader &th, int tagID)
341 {
342 th.offset = 0;
343 th.tagID = tagID;
344
345 switch(tagID)
346 {
347 case TAG_YOU:
348 tag_construct_you(th);
349 break;
350 case TAG_YOU_ITEMS:
351 tag_construct_you_items(th);
352 break;
353 case TAG_YOU_DUNGEON:
354 tag_construct_you_dungeon(th);
355 break;
356 case TAG_LEVEL:
357 tag_construct_level(th);
358 break;
359 case TAG_LEVEL_ITEMS:
360 tag_construct_level_items(th);
361 break;
362 case TAG_LEVEL_MONSTERS:
363 tag_construct_level_monsters(th);
364 break;
365 case TAG_LEVEL_ATTITUDE:
366 tag_construct_level_attitude(th);
367 break;
368 case TAG_GHOST:
369 tag_construct_ghost(th);
370 break;
371 default:
372 // I don't know how to make that!
373 break;
374 }
375 }
376
tag_write(struct tagHeader & th,FILE * saveFile)377 void tag_write(struct tagHeader &th, FILE *saveFile)
378 {
379 const int tagHdrSize = 6;
380 int tagSize=0;
381
382 char swap[tagHdrSize];
383
384 // make sure there is some data to write!
385 if (th.offset == 0)
386 return;
387
388 // special case: TAG_VERSION. Skip tag header.
389 if (th.tagID != TAG_VERSION)
390 {
391 // swap out first few bytes
392 memcpy(swap, tagBuffer, tagHdrSize);
393
394 // save tag size
395 tagSize = th.offset;
396
397 // swap in the header
398 th.offset = 0;
399 marshallShort(th, th.tagID);
400 marshallLong(th, tagSize);
401
402 // write header
403 write2(saveFile, tagBuffer, th.offset);
404
405 // swap real data back in
406 memcpy(tagBuffer, swap, tagHdrSize);
407
408 // reset tag size
409 th.offset = tagSize;
410 }
411
412 // write tag data
413 write2(saveFile, tagBuffer, th.offset);
414 return;
415 }
416
417 // minorVersion is available for any sub-readers that need it
418 // (like TAG_LEVEL_MONSTERS)
tag_read(FILE * fp,char minorVersion)419 int tag_read(FILE *fp, char minorVersion)
420 {
421 const int tagHdrSize = 6;
422 struct tagHeader hdr, th;
423 th.offset = 0;
424
425 // read tag header
426 if (read2(fp, tagBuffer, tagHdrSize) != tagHdrSize)
427 return 0;
428
429 // unmarshall tag type and length (not including header)
430 hdr.tagID = unmarshallShort(th);
431 hdr.offset = unmarshallLong(th);
432
433 // sanity check
434 if (hdr.tagID <= 0 || hdr.offset <= 0)
435 return 0;
436
437 // now reset th and read actual data
438 th.offset = 0;
439 if (read2(fp, tagBuffer, hdr.offset) != hdr.offset)
440 return 0;
441
442 // ok, we have data now.
443 switch(hdr.tagID)
444 {
445 case TAG_YOU:
446 tag_read_you(th, minorVersion);
447 break;
448 case TAG_YOU_ITEMS:
449 tag_read_you_items(th, minorVersion);
450 break;
451 case TAG_YOU_DUNGEON:
452 tag_read_you_dungeon(th);
453 break;
454 case TAG_LEVEL:
455 tag_read_level(th, minorVersion);
456 break;
457 case TAG_LEVEL_ITEMS:
458 tag_read_level_items(th, minorVersion);
459 break;
460 case TAG_LEVEL_MONSTERS:
461 tag_read_level_monsters(th, minorVersion);
462 break;
463 case TAG_LEVEL_ATTITUDE:
464 tag_read_level_attitude(th);
465 break;
466 case TAG_GHOST:
467 tag_read_ghost(th, minorVersion);
468 break;
469 default:
470 // I don't know how to read that!
471 return 0;
472 }
473
474 return hdr.tagID;
475 }
476
477
478 // older savefiles might want to call this to get a tag
479 // properly initialized if it wasn't part of the savefile.
480 // For now, none are supported.
481
482 // This function will be called AFTER all other tags for
483 // the savefile are read, so everything that can be
484 // initialized should have been by now.
485
486 // minorVersion is available for any child functions that need
487 // it (currently none)
tag_missing(int tag,char minorVersion)488 void tag_missing(int tag, char minorVersion)
489 {
490 UNUSED( minorVersion );
491
492 switch(tag)
493 {
494 case TAG_LEVEL_ATTITUDE:
495 tag_missing_level_attitude();
496 break;
497 default:
498 perror("Tag %d is missing; file is likely corrupt.");
499 end(-1);
500 }
501 }
502
503 // utility
tag_set_expected(char tags[],int fileType)504 void tag_set_expected(char tags[], int fileType)
505 {
506 int i;
507
508 for(i=0; i<NUM_TAGS; i++)
509 {
510 tags[i] = -1;
511 switch(fileType)
512 {
513 case TAGTYPE_PLAYER:
514 if (i >= TAG_YOU && i <=TAG_YOU_DUNGEON)
515 tags[i] = 1;
516 break;
517 case TAGTYPE_LEVEL:
518 if (i >= TAG_LEVEL && i <= TAG_LEVEL_ATTITUDE)
519 tags[i] = 1;
520 break;
521 case TAGTYPE_GHOST:
522 if (i == TAG_GHOST)
523 tags[i] = 1;
524 default:
525 // I don't know what kind of file that is!
526 break;
527 }
528 }
529 }
530
531 // NEVER _MODIFY_ THE CONSTRUCT/READ FUNCTIONS, EVER. THAT IS THE WHOLE POINT
532 // OF USING TAGS. Apologies for the screaming.
533
534 // Note anyway that the formats are somewhat flexible; you could change map
535 // size, the # of slots in player inventory, etc. Constants like GXM,
536 // NUM_EQUIP, and NUM_DURATIONS are saved, so the appropriate amount will
537 // be restored even if a later version increases these constants.
538
539 // --------------------------- player tags (foo.sav) -------------------- //
tag_construct_you(struct tagHeader & th)540 static void tag_construct_you(struct tagHeader &th)
541 {
542 char buff[20]; // used for date string
543 int i,j;
544
545 marshallString(th, you.your_name, 30);
546
547 marshallByte(th,you.religion);
548 marshallByte(th,you.piety);
549 marshallByte(th,you.invis);
550 marshallByte(th,you.conf);
551 marshallByte(th,you.paralysis);
552 marshallByte(th,you.slow);
553 marshallByte(th,you.fire_shield);
554 marshallByte(th,you.rotting);
555 marshallByte(th,you.exhausted);
556 marshallByte(th,you.deaths_door);
557 marshallByte(th,your_sign);
558 marshallByte(th,your_colour);
559 marshallByte(th,you.pet_target);
560
561 marshallByte(th,you.max_level);
562 marshallByte(th,you.where_are_you);
563 marshallByte(th,you.char_direction);
564 marshallByte(th,you.your_level);
565 marshallByte(th,you.is_undead);
566 marshallByte(th,you.special_wield);
567 marshallByte(th,you.berserker);
568 marshallByte(th,you.berserk_penalty);
569 marshallByte(th,you.level_type);
570 marshallByte(th,you.synch_time);
571 marshallByte(th,you.disease);
572 marshallByte(th,you.species);
573
574 marshallShort(th, you.hp);
575
576 if (you.haste > 215)
577 you.haste = 215;
578
579 marshallByte(th,you.haste);
580
581 if (you.might > 215)
582 you.might = 215;
583
584 marshallByte(th,you.might);
585
586 if (you.levitation > 215)
587 you.levitation = 215;
588
589 marshallByte(th,you.levitation);
590
591 if (you.poison > 215)
592 you.poison = 215;
593
594 marshallByte(th,you.poison);
595
596 marshallShort(th, you.hunger);
597
598 // how many you.equip?
599 marshallByte(th, NUM_EQUIP);
600 for (i = 0; i < NUM_EQUIP; ++i)
601 marshallByte(th,you.equip[i]);
602
603 marshallByte(th,you.magic_points);
604 marshallByte(th,you.max_magic_points);
605 marshallByte(th,you.strength);
606 marshallByte(th,you.intel);
607 marshallByte(th,you.dex);
608 marshallByte(th,you.confusing_touch);
609 marshallByte(th,you.sure_blade);
610 marshallByte(th,you.hit_points_regeneration);
611 marshallByte(th,you.magic_points_regeneration);
612
613 marshallShort(th, you.hit_points_regeneration * 100);
614 marshallLong(th, you.experience);
615 marshallLong(th, you.gold);
616
617 marshallByte(th,you.char_class);
618 marshallByte(th,you.experience_level);
619 marshallLong(th, you.exp_available);
620
621 /* max values */
622 marshallByte(th,you.max_strength);
623 marshallByte(th,you.max_intel);
624 marshallByte(th,you.max_dex);
625
626 marshallShort(th, you.base_hp);
627 marshallShort(th, you.base_hp2);
628 marshallShort(th, you.base_magic_points);
629 marshallShort(th, you.base_magic_points2);
630
631 marshallShort(th, you.x_pos);
632 marshallShort(th, you.y_pos);
633
634 marshallString(th, you.class_name, 30);
635
636 marshallShort(th, you.burden);
637
638 // how many spells?
639 marshallByte(th, 25);
640 for (i = 0; i < 25; ++i)
641 marshallByte(th, you.spells[i]);
642
643 marshallByte(th, 52);
644 for (i = 0; i < 52; i++)
645 marshallByte( th, you.spell_letter_table[i] );
646
647 marshallByte(th, 52);
648 for (i = 0; i < 52; i++)
649 marshallShort( th, you.ability_letter_table[i] );
650
651 // how many skills?
652 marshallByte(th, 50);
653 for (j = 0; j < 50; ++j)
654 {
655 marshallByte(th,you.skills[j]); /* skills! */
656 marshallByte(th,you.practise_skill[j]); /* skills! */
657 marshallLong(th,you.skill_points[j]);
658 marshallByte(th,you.skill_order[j]); /* skills ordering */
659 }
660
661 // how many durations?
662 marshallByte(th, NUM_DURATIONS);
663 for (j = 0; j < NUM_DURATIONS; ++j)
664 marshallByte(th,you.duration[j]);
665
666 // how many attributes?
667 marshallByte(th, 30);
668 for (j = 0; j < 30; ++j)
669 marshallByte(th,you.attribute[j]);
670
671 // how many mutations/demon powers?
672 marshallShort(th, 100);
673 for (j = 0; j < 100; ++j)
674 {
675 marshallByte(th,you.mutation[j]);
676 marshallByte(th,you.demon_pow[j]);
677 }
678
679 // how many penances?
680 marshallByte(th, MAX_NUM_GODS);
681 for (i = 0; i < MAX_NUM_GODS; i++)
682 marshallByte(th, you.penance[i]);
683
684 // which gods have been worshipped by this character?
685 marshallByte(th, MAX_NUM_GODS);
686 for (i = 0; i < MAX_NUM_GODS; i++)
687 marshallByte(th, you.worshipped[i]);
688
689 marshallByte(th, you.gift_timeout);
690 marshallByte(th, you.normal_vision);
691 marshallByte(th, you.current_vision);
692 marshallByte(th, you.hell_exit);
693
694 // elapsed time
695 marshallFloat(th, (float)you.elapsed_time);
696
697 // wizard mode used
698 marshallByte(th, you.wizard);
699
700 // time of game start
701 make_date_string( you.birth_time, buff );
702 marshallString(th, buff, 20);
703
704 // real_time == -1 means game was started before this feature
705 if (you.real_time != -1)
706 {
707 const time_t now = time(NULL);
708 you.real_time += (now - you.start_time);
709
710 // Reset start_time now that real_time is being saved out...
711 // this may just be a level save.
712 you.start_time = now;
713 }
714
715 marshallLong( th, you.real_time );
716 marshallLong( th, you.num_turns );
717 }
718
tag_construct_you_items(struct tagHeader & th)719 static void tag_construct_you_items(struct tagHeader &th)
720 {
721 int i,j;
722
723 // how many inventory slots?
724 marshallByte(th, ENDOFPACK);
725 for (i = 0; i < ENDOFPACK; ++i)
726 {
727 marshallByte(th,you.inv[i].base_type);
728 marshallByte(th,you.inv[i].sub_type);
729 marshallShort(th,you.inv[i].plus);
730 marshallLong(th,you.inv[i].special);
731 marshallByte(th,you.inv[i].colour);
732 marshallLong(th,you.inv[i].flags);
733 marshallShort(th,you.inv[i].quantity);
734 marshallShort(th,you.inv[i].plus2);
735 }
736
737 // item descrip for each type & subtype
738 // how many types?
739 marshallByte(th, 5);
740 // how many subtypes?
741 marshallByte(th, 50);
742 for (i = 0; i < 5; ++i)
743 {
744 for (j = 0; j < 50; ++j)
745 marshallByte(th, you.item_description[i][j]);
746 }
747
748 // identification status
749 // how many types?
750 marshallByte(th, 4);
751 // how many subtypes?
752 marshallByte(th, 50);
753
754 // this is really dumb. We copy the id[] array from itemname
755 // to the stack, for no good reason that I can see.
756 char identy[4][50];
757
758 save_id(identy);
759
760 for (i = 0; i < 4; ++i)
761 {
762 for (j = 0; j < 50; ++j)
763 marshallByte(th, identy[i][j]);
764 }
765
766 // how many unique items?
767 marshallByte(th, 50);
768 for (j = 0; j < 50; ++j)
769 {
770 marshallByte(th,you.unique_items[j]); /* unique items */
771 marshallByte(th,you.had_book[j]);
772 }
773
774 // how many unrandarts?
775 marshallShort(th, NO_UNRANDARTS);
776
777 for (j = 0; j < NO_UNRANDARTS; ++j)
778 marshallBoolean(th, does_unrandart_exist(j));
779 }
780
tag_construct_you_dungeon(struct tagHeader & th)781 static void tag_construct_you_dungeon(struct tagHeader &th)
782 {
783 int i,j;
784
785 // how many unique creatures?
786 marshallByte(th, 50);
787 for (j = 0; j < 50; ++j)
788 marshallByte(th,you.unique_creatures[j]); /* unique beasties */
789
790 // how many branches?
791 marshallByte(th, MAX_BRANCHES);
792 for (j = 0; j < 30; ++j)
793 {
794 marshallByte(th,you.branch_stairs[j]);
795 marshallByte(th,stair_level[j]);
796 }
797
798 // how many levels?
799 marshallShort(th, MAX_LEVELS);
800 for (i = 0; i < MAX_LEVELS; ++i)
801 {
802 for (j = 0; j < MAX_BRANCHES; ++j)
803 {
804 marshallByte(th,altars_present[i][j]);
805 marshallByte(th,feature[i][j]);
806 marshallBoolean(th,tmp_file_pairs[i][j]);
807 }
808 }
809 }
810
tag_read_you(struct tagHeader & th,char minorVersion)811 static void tag_read_you(struct tagHeader &th, char minorVersion)
812 {
813 char buff[20]; // For birth date
814 int i,j;
815 char count_c;
816 short count_s;
817
818 unmarshallString(th, you.your_name, 30);
819
820 you.religion = unmarshallByte(th);
821 you.piety = unmarshallByte(th);
822 you.invis = unmarshallByte(th);
823 you.conf = unmarshallByte(th);
824 you.paralysis = unmarshallByte(th);
825 you.slow = unmarshallByte(th);
826 you.fire_shield = unmarshallByte(th);
827 you.rotting = unmarshallByte(th);
828 you.exhausted = unmarshallByte(th);
829 you.deaths_door = unmarshallByte(th);
830 your_sign = unmarshallByte(th);
831 your_colour = unmarshallByte(th);
832 you.pet_target = unmarshallByte(th);
833
834 you.max_level = unmarshallByte(th);
835 you.where_are_you = unmarshallByte(th);
836 you.char_direction = unmarshallByte(th);
837 you.your_level = unmarshallByte(th);
838 you.is_undead = unmarshallByte(th);
839 you.special_wield = unmarshallByte(th);
840 you.berserker = unmarshallByte(th);
841 you.berserk_penalty = unmarshallByte(th);
842 you.level_type = unmarshallByte(th);
843 you.synch_time = unmarshallByte(th);
844 you.disease = unmarshallByte(th);
845 you.species = unmarshallByte(th);
846 you.hp = unmarshallShort(th);
847 you.haste = unmarshallByte(th);
848 you.might = unmarshallByte(th);
849 you.levitation = unmarshallByte(th);
850 you.poison = unmarshallByte(th);
851 you.hunger = unmarshallShort(th);
852
853 // how many you.equip?
854 count_c = unmarshallByte(th);
855 for (i = 0; i < count_c; ++i)
856 you.equip[i] = unmarshallByte(th);
857
858 you.magic_points = unmarshallByte(th);
859 you.max_magic_points = unmarshallByte(th);
860 you.strength = unmarshallByte(th);
861 you.intel = unmarshallByte(th);
862 you.dex = unmarshallByte(th);
863 you.confusing_touch = unmarshallByte(th);
864 you.sure_blade = unmarshallByte(th);
865 you.hit_points_regeneration = unmarshallByte(th);
866 you.magic_points_regeneration = unmarshallByte(th);
867
868 you.hit_points_regeneration = unmarshallShort(th) / 100;
869 you.experience = unmarshallLong(th);
870 you.gold = unmarshallLong(th);
871
872 you.char_class = unmarshallByte(th);
873 you.experience_level = unmarshallByte(th);
874 you.exp_available = unmarshallLong(th);
875
876 /* max values */
877 you.max_strength = unmarshallByte(th);
878 you.max_intel = unmarshallByte(th);
879 you.max_dex = unmarshallByte(th);
880
881 you.base_hp = unmarshallShort(th);
882 you.base_hp2 = unmarshallShort(th);
883 you.base_magic_points = unmarshallShort(th);
884 you.base_magic_points2 = unmarshallShort(th);
885
886 you.x_pos = unmarshallShort(th);
887 you.y_pos = unmarshallShort(th);
888
889 unmarshallString(th, you.class_name, 30);
890
891 you.burden = unmarshallShort(th);
892
893 // how many spells?
894 you.spell_no = 0;
895 count_c = unmarshallByte(th);
896 for (i = 0; i < count_c; ++i)
897 {
898 you.spells[i] = unmarshallByte(th);
899 if (you.spells[i] != SPELL_NO_SPELL)
900 you.spell_no++;
901 }
902
903 if (minorVersion >= 2)
904 {
905 count_c = unmarshallByte(th);
906 for (i = 0; i < count_c; i++)
907 you.spell_letter_table[i] = unmarshallByte(th);
908
909 count_c = unmarshallByte(th);
910 for (i = 0; i < count_c; i++)
911 you.ability_letter_table[i] = unmarshallShort(th);
912 }
913 else
914 {
915 for (i = 0; i < 52; i++)
916 {
917 you.spell_letter_table[i] = -1;
918 you.ability_letter_table[i] = ABIL_NON_ABILITY;
919 }
920
921 for (i = 0; i < 25; i++)
922 {
923 if (you.spells[i] != SPELL_NO_SPELL)
924 you.spell_letter_table[i] = i;
925 }
926
927 if (you.religion != GOD_NO_GOD)
928 set_god_ability_slots();
929 }
930
931 // how many skills?
932 count_c = unmarshallByte(th);
933 for (j = 0; j < count_c; ++j)
934 {
935 you.skills[j] = unmarshallByte(th);
936 you.practise_skill[j] = unmarshallByte(th);
937 you.skill_points[j] = unmarshallLong(th);
938
939 if (minorVersion >= 2)
940 you.skill_order[j] = unmarshallByte(th);
941 }
942
943 // initialize ordering when we don't read it in:
944 if (minorVersion < 2)
945 init_skill_order();
946
947 // set up you.total_skill_points and you.skill_cost_level
948 calc_total_skill_points();
949
950 // how many durations?
951 count_c = unmarshallByte(th);
952 for (j = 0; j < count_c; ++j)
953 you.duration[j] = unmarshallByte(th);
954
955 // how many attributes?
956 count_c = unmarshallByte(th);
957 for (j = 0; j < count_c; ++j)
958 you.attribute[j] = unmarshallByte(th);
959
960 // how many mutations/demon powers?
961 count_s = unmarshallShort(th);
962 for (j = 0; j < count_s; ++j)
963 {
964 you.mutation[j] = unmarshallByte(th);
965 you.demon_pow[j] = unmarshallByte(th);
966 }
967
968 // how many penances?
969 count_c = unmarshallByte(th);
970 for (i = 0; i < count_c; i++)
971 you.penance[i] = unmarshallByte(th);
972
973 if (minorVersion >= 2)
974 {
975 count_c = unmarshallByte(th);
976 for (i = 0; i < count_c; i++)
977 you.worshipped[i] = unmarshallByte(th);
978 }
979 else
980 {
981 for (i = 0; i < count_c; i++)
982 you.worshipped[i] = false;
983
984 if (you.religion != GOD_NO_GOD)
985 you.worshipped[you.religion] = true;
986 }
987
988 you.gift_timeout = unmarshallByte(th);
989 you.normal_vision = unmarshallByte(th);
990 you.current_vision = unmarshallByte(th);
991 you.hell_exit = unmarshallByte(th);
992
993 // elapsed time
994 you.elapsed_time = (double)unmarshallFloat(th);
995
996 if (minorVersion >= 1)
997 {
998 // wizard mode
999 you.wizard = (bool) unmarshallByte(th);
1000
1001 // time of character creation
1002 unmarshallString( th, buff, 20 );
1003 you.birth_time = parse_date_string( buff );
1004 }
1005
1006 if (minorVersion >= 2)
1007 {
1008 you.real_time = unmarshallLong(th);
1009 you.num_turns = unmarshallLong(th);
1010 }
1011 else
1012 {
1013 you.real_time = -1;
1014 you.num_turns = -1;
1015 }
1016 }
1017
tag_convert_to_4_3_item(item_def & item)1018 static void tag_convert_to_4_3_item( item_def &item )
1019 {
1020 const unsigned char plus = item.plus;
1021 const unsigned char plus2 = item.plus2;
1022 const unsigned char ident = item.flags;
1023 const unsigned char special = item.special;
1024
1025 if (item.quantity <= 0)
1026 return;
1027
1028 // First, convert ident into flags:
1029 item.flags = (ident == 3) ? ISFLAG_IDENT_MASK :
1030 (ident > 0) ? ISFLAG_KNOW_CURSE
1031 : 0;
1032
1033 switch (item.base_type)
1034 {
1035 case OBJ_ARMOUR:
1036 if ((ident == 1 && special % 30 >= 25) || ident == 2)
1037 item.flags |= ISFLAG_KNOW_TYPE;
1038
1039 // Convert special values
1040 item.special %= 30;
1041 if (item.special < 25)
1042 {
1043 if (item.sub_type == ARM_HELMET)
1044 {
1045 item.plus2 = plus2 % 30;
1046 set_helmet_desc( item, (special / 30) << 8 );
1047 }
1048 else
1049 {
1050 switch (special / 30)
1051 {
1052 case DARM_EMBROIDERED_SHINY:
1053 set_equip_desc( item, ISFLAG_EMBROIDERED_SHINY );
1054 break;
1055 case DARM_RUNED:
1056 set_equip_desc( item, ISFLAG_RUNED );
1057 break;
1058 case DARM_GLOWING:
1059 set_equip_desc( item, ISFLAG_GLOWING );
1060 break;
1061 case DARM_ELVEN:
1062 set_equip_race( item, ISFLAG_ELVEN );
1063 break;
1064 case DARM_DWARVEN:
1065 set_equip_race( item, ISFLAG_DWARVEN );
1066 break;
1067 case DARM_ORCISH:
1068 set_equip_race( item, ISFLAG_ORCISH );
1069 break;
1070 default:
1071 break;
1072 }
1073 }
1074 }
1075 else if (item.special == 25)
1076 {
1077 item.flags |= ISFLAG_UNRANDART;
1078 item.special = 0;
1079 }
1080 else
1081 {
1082 item.flags |= ISFLAG_RANDART;
1083
1084 // calc old seed
1085 item.special = item.base_type * special
1086 + item.sub_type * (plus % 100)
1087 + plus2 * 100;
1088 }
1089 break;
1090
1091 case OBJ_WEAPONS:
1092 if ((ident == 1 && (special < 180 && special % 30 >= 25)) || ident == 2)
1093 item.flags |= ISFLAG_KNOW_TYPE;
1094
1095 // Convert special values
1096 if (special < 181) // don't mangle fixed artefacts
1097 {
1098 item.special %= 30;
1099 if (item.special < 25)
1100 {
1101 switch (special / 30)
1102 {
1103 case DWPN_RUNED:
1104 set_equip_desc( item, ISFLAG_RUNED );
1105 break;
1106 case DWPN_GLOWING:
1107 set_equip_desc( item, ISFLAG_GLOWING );
1108 break;
1109 case DWPN_ORCISH:
1110 set_equip_race( item, ISFLAG_ORCISH );
1111 break;
1112 case DWPN_ELVEN:
1113 set_equip_race( item, ISFLAG_ELVEN );
1114 break;
1115 case DWPN_DWARVEN:
1116 set_equip_race( item, ISFLAG_DWARVEN );
1117 break;
1118 default:
1119 break;
1120 }
1121 }
1122 else if (item.special == 25)
1123 {
1124 item.flags |= ISFLAG_UNRANDART;
1125 item.special = 0;
1126 }
1127 else
1128 {
1129 item.flags |= ISFLAG_RANDART;
1130
1131 // calc old seed
1132 item.special = item.base_type * special
1133 + item.sub_type * (plus % 100)
1134 + plus2 * 100;
1135 }
1136 }
1137 break;
1138
1139 case OBJ_MISSILES:
1140 // Needles were moved into the bonus eggplant spot. -- bwr
1141 if (item.sub_type == 6)
1142 item.sub_type = MI_NEEDLE;
1143
1144 if (ident == 2)
1145 item.flags |= ISFLAG_KNOW_TYPE;
1146
1147 // Convert special values
1148 item.special %= 30;
1149 switch (special / 30)
1150 {
1151 case DAMMO_ORCISH:
1152 set_equip_race( item, ISFLAG_ORCISH );
1153 break;
1154 case DAMMO_ELVEN:
1155 set_equip_race( item, ISFLAG_ELVEN );
1156 break;
1157 case DAMMO_DWARVEN:
1158 set_equip_race( item, ISFLAG_DWARVEN );
1159 break;
1160 default:
1161 break;
1162 }
1163 break;
1164
1165 case OBJ_WANDS:
1166 if (ident == 2)
1167 item.flags |= ISFLAG_KNOW_PLUSES;
1168 break;
1169
1170 case OBJ_JEWELLERY:
1171 if (ident == 1 && (special == 200 || special == 201))
1172 item.flags |= ISFLAG_KNOW_TYPE;
1173 else if (ident == 2)
1174 item.flags |= (ISFLAG_KNOW_TYPE | ISFLAG_KNOW_PLUSES);
1175
1176 if (special == 201)
1177 {
1178 item.flags |= ISFLAG_UNRANDART;
1179 item.special = 0;
1180 }
1181 else if (special == 200)
1182 {
1183 item.flags |= ISFLAG_RANDART;
1184
1185 // calc old seed
1186 item.special = item.base_type * special
1187 + item.sub_type * (plus % 100)
1188 + plus2 * 100;
1189 }
1190 break;
1191
1192 default:
1193 if (ident > 0)
1194 item.flags |= ISFLAG_KNOW_TYPE;
1195 break;
1196 }
1197
1198
1199 // Second, convert plus and plus2
1200 if (item.base_type == OBJ_WEAPONS
1201 || item.base_type == OBJ_MISSILES
1202 || item.base_type == OBJ_ARMOUR
1203 || item.base_type == OBJ_JEWELLERY)
1204 {
1205 item.plus = plus;
1206
1207 // item is cursed:
1208 if (plus > 100)
1209 {
1210 item.plus -= 100;
1211 item.flags |= ISFLAG_CURSED;
1212 }
1213
1214 // Weapons use both as pluses.
1215 // Non-artefact jewellery uses both as pluses.
1216 // Artefact jewellery has literal values for both pluses.
1217 // Armour and Missiles only use plus for their plus value.
1218 // Armour has literal usage of plus2 for sub-subtypes.
1219 if (item.base_type != OBJ_JEWELLERY)
1220 {
1221 item.plus -= 50;
1222
1223 if (item.base_type == OBJ_WEAPONS)
1224 item.plus2 -= 50;
1225 }
1226 else if (special != 200)
1227 {
1228 // regular jewellery & unrandarts -- unused pluses were 0s
1229 if (item.plus)
1230 item.plus -= 50;
1231
1232 if (item.plus2)
1233 item.plus2 -= 50;
1234 }
1235 else if (special == 200)
1236 {
1237 // Randart jewellery used pluses only as seeds, right now
1238 // they're always zero (since random artefact rings avoid
1239 // base types with pluses).
1240 item.plus = 0;
1241 item.plus2 = 0;
1242 }
1243 }
1244 }
1245
tag_read_you_items(struct tagHeader & th,char minorVersion)1246 static void tag_read_you_items(struct tagHeader &th, char minorVersion)
1247 {
1248 int i,j;
1249 char count_c, count_c2;
1250 short count_s;
1251
1252 // how many inventory slots?
1253 count_c = unmarshallByte(th);
1254 for (i = 0; i < count_c; ++i)
1255 {
1256 if (minorVersion < 1)
1257 {
1258 you.inv[i].base_type = (unsigned char) unmarshallByte(th);
1259 you.inv[i].sub_type = (unsigned char) unmarshallByte(th);
1260 you.inv[i].plus = (unsigned char) unmarshallByte(th);
1261 you.inv[i].special = (unsigned char) unmarshallByte(th);
1262 you.inv[i].colour = (unsigned char) unmarshallByte(th);
1263 you.inv[i].flags = (unsigned char) unmarshallByte(th);
1264 you.inv[i].quantity = unmarshallShort(th);
1265 you.inv[i].plus2 = (unsigned char) unmarshallByte(th);
1266
1267 tag_convert_to_4_3_item( you.inv[i] );
1268 }
1269 else
1270 {
1271 you.inv[i].base_type = (unsigned char) unmarshallByte(th);
1272 you.inv[i].sub_type = (unsigned char) unmarshallByte(th);
1273 you.inv[i].plus = unmarshallShort(th);
1274 you.inv[i].special = unmarshallLong(th);
1275 you.inv[i].colour = (unsigned char) unmarshallByte(th);
1276 you.inv[i].flags = (unsigned long) unmarshallLong(th);
1277 you.inv[i].quantity = unmarshallShort(th);
1278 you.inv[i].plus2 = unmarshallShort(th);
1279 }
1280
1281 // these never need to be saved for items in the inventory -- bwr
1282 you.inv[i].x = -1;
1283 you.inv[i].y = -1;
1284 you.inv[i].link = i;
1285 }
1286
1287 // item descrip for each type & subtype
1288 // how many types?
1289 count_c = unmarshallByte(th);
1290 // how many subtypes?
1291 count_c2 = unmarshallByte(th);
1292 for (i = 0; i < count_c; ++i)
1293 {
1294 for (j = 0; j < count_c2; ++j)
1295 you.item_description[i][j] = unmarshallByte(th);
1296 }
1297
1298 // identification status
1299 // how many types?
1300 count_c = unmarshallByte(th);
1301 // how many subtypes?
1302 count_c2 = unmarshallByte(th);
1303
1304 // argh.. this is awful.
1305 for (i = 0; i < count_c; ++i)
1306 {
1307 for (j = 0; j < count_c2; ++j)
1308 {
1309 char ch;
1310 ch = unmarshallByte(th);
1311
1312 switch (i)
1313 {
1314 case IDTYPE_WANDS:
1315 set_ident_type(OBJ_WANDS, j, ch);
1316 break;
1317 case IDTYPE_SCROLLS:
1318 set_ident_type(OBJ_SCROLLS, j, ch);
1319 break;
1320 case IDTYPE_JEWELLERY:
1321 set_ident_type(OBJ_JEWELLERY, j, ch);
1322 break;
1323 case IDTYPE_POTIONS:
1324 set_ident_type(OBJ_POTIONS, j, ch);
1325 break;
1326 }
1327 }
1328 }
1329
1330 // how many unique items?
1331 count_c = unmarshallByte(th);
1332 for (j = 0; j < count_c; ++j)
1333 {
1334 you.unique_items[j] = unmarshallByte(th);
1335 you.had_book[j] = unmarshallByte(th);
1336 }
1337
1338 // how many unrandarts?
1339 count_s = unmarshallShort(th);
1340 for (j = 0; j < count_s; ++j)
1341 set_unrandart_exist(j, unmarshallBoolean(th));
1342
1343 // # of unrandarts could certainly change. If it does,
1344 // the new ones won't exist yet - zero them out.
1345 for (; j < NO_UNRANDARTS; j++)
1346 set_unrandart_exist(j, 0);
1347 }
1348
tag_read_you_dungeon(struct tagHeader & th)1349 static void tag_read_you_dungeon(struct tagHeader &th)
1350 {
1351 int i,j;
1352 char count_c;
1353 short count_s;
1354
1355 // how many unique creatures?
1356 count_c = unmarshallByte(th);
1357 for (j = 0; j < count_c; ++j)
1358 you.unique_creatures[j] = unmarshallByte(th);
1359
1360 // how many branches?
1361 count_c = unmarshallByte(th);
1362 for (j = 0; j < count_c; ++j)
1363 {
1364 you.branch_stairs[j] = unmarshallByte(th);
1365 stair_level[j] = unmarshallByte(th);
1366 }
1367
1368 // how many levels?
1369 count_s = unmarshallShort(th);
1370 for (i = 0; i < count_s; ++i)
1371 {
1372 for (j = 0; j < count_c; ++j)
1373 {
1374 altars_present[i][j] = unmarshallByte(th);
1375 feature[i][j] = unmarshallByte(th);
1376 tmp_file_pairs[i][j] = unmarshallBoolean(th);
1377 }
1378 }
1379 }
1380
1381 // ------------------------------- level tags ---------------------------- //
1382
tag_construct_level(struct tagHeader & th)1383 static void tag_construct_level(struct tagHeader &th)
1384 {
1385 int i;
1386 int count_x, count_y;
1387
1388 marshallFloat(th, (float)you.elapsed_time);
1389
1390 // map grids
1391 // how many X?
1392 marshallShort(th, GXM);
1393 // how many Y?
1394 marshallShort(th, GYM);
1395 for (count_x = 0; count_x < GXM; count_x++)
1396 {
1397 for (count_y = 0; count_y < GYM; count_y++)
1398 {
1399 marshallByte(th, grd[count_x][count_y]);
1400 marshallByte(th, env.map[count_x][count_y]);
1401 marshallByte(th, env.cgrid[count_x][count_y]);
1402 }
1403 }
1404
1405 marshallShort(th, env.cloud_no);
1406
1407 // how many clouds?
1408 marshallShort(th, MAX_CLOUDS);
1409 for (i = 0; i < MAX_CLOUDS; i++)
1410 {
1411 marshallByte(th, env.cloud[i].x);
1412 marshallByte(th, env.cloud[i].y);
1413 marshallByte(th, env.cloud[i].type);
1414 marshallShort(th, env.cloud[i].decay);
1415 }
1416
1417 // how many shops?
1418 marshallByte(th, 5);
1419 for (i = 0; i < 5; i++)
1420 {
1421 marshallByte(th, env.shop[i].keeper_name[0]);
1422 marshallByte(th, env.shop[i].keeper_name[1]);
1423 marshallByte(th, env.shop[i].keeper_name[2]);
1424 marshallByte(th, env.shop[i].x);
1425 marshallByte(th, env.shop[i].y);
1426 marshallByte(th, env.shop[i].greed);
1427 marshallByte(th, env.shop[i].type);
1428 marshallByte(th, env.shop[i].level);
1429 }
1430 }
1431
tag_construct_level_items(struct tagHeader & th)1432 static void tag_construct_level_items(struct tagHeader &th)
1433 {
1434 int i;
1435
1436 // how many traps?
1437 marshallShort(th, MAX_TRAPS);
1438 for (i = 0; i < MAX_TRAPS; ++i)
1439 {
1440 marshallByte(th, env.trap[i].type);
1441 marshallByte(th, env.trap[i].x);
1442 marshallByte(th, env.trap[i].y);
1443 }
1444
1445 // how many items?
1446 marshallShort(th, MAX_ITEMS);
1447 for (i = 0; i < MAX_ITEMS; ++i)
1448 {
1449 marshallByte(th, mitm[i].base_type);
1450 marshallByte(th, mitm[i].sub_type);
1451 marshallShort(th, mitm[i].plus);
1452 marshallShort(th, mitm[i].plus2);
1453 marshallLong(th, mitm[i].special);
1454 marshallShort(th, mitm[i].quantity);
1455
1456 marshallByte(th, mitm[i].colour);
1457 marshallShort(th, mitm[i].x);
1458 marshallShort(th, mitm[i].y);
1459 marshallLong(th, mitm[i].flags);
1460
1461 marshallShort(th, mitm[i].link); // unused
1462 marshallShort(th, igrd[mitm[i].x][mitm[i].y]); // unused
1463 }
1464 }
1465
tag_construct_level_monsters(struct tagHeader & th)1466 static void tag_construct_level_monsters(struct tagHeader &th)
1467 {
1468 int i,j;
1469
1470 // how many mons_alloc?
1471 marshallByte(th, 20);
1472 for (i = 0; i < 20; ++i)
1473 marshallShort(th, env.mons_alloc[i]);
1474
1475 // how many monsters?
1476 marshallShort(th, MAX_MONSTERS);
1477 // how many monster enchantments?
1478 marshallByte(th, NUM_MON_ENCHANTS);
1479 // how many monster inventory slots?
1480 marshallByte(th, NUM_MONSTER_SLOTS);
1481
1482 for (i = 0; i < MAX_MONSTERS; i++)
1483 {
1484 marshallByte(th, menv[i].armour_class);
1485 marshallByte(th, menv[i].evasion);
1486 marshallByte(th, menv[i].hit_dice);
1487 marshallByte(th, menv[i].speed);
1488 marshallByte(th, menv[i].speed_increment);
1489 marshallByte(th, menv[i].behaviour);
1490 marshallByte(th, menv[i].x);
1491 marshallByte(th, menv[i].y);
1492 marshallByte(th, menv[i].target_x);
1493 marshallByte(th, menv[i].target_y);
1494 marshallByte(th, menv[i].flags);
1495
1496 for (j = 0; j < NUM_MON_ENCHANTS; j++)
1497 marshallByte(th, menv[i].enchantment[j]);
1498
1499 marshallShort(th, menv[i].type);
1500 marshallShort(th, menv[i].hit_points);
1501 marshallShort(th, menv[i].max_hit_points);
1502 marshallShort(th, menv[i].number);
1503
1504 for (j = 0; j < NUM_MONSTER_SLOTS; j++)
1505 marshallShort(th, menv[i].inv[j]);
1506 }
1507 }
1508
tag_construct_level_attitude(struct tagHeader & th)1509 void tag_construct_level_attitude(struct tagHeader &th)
1510 {
1511 int i;
1512
1513 // how many monsters?
1514 marshallShort(th, MAX_MONSTERS);
1515
1516 for (i = 0; i < MAX_MONSTERS; i++)
1517 {
1518 marshallByte(th, menv[i].attitude);
1519 marshallShort(th, menv[i].foe);
1520 }
1521 }
1522
1523
tag_read_level(struct tagHeader & th,char minorVersion)1524 static void tag_read_level( struct tagHeader &th, char minorVersion )
1525 {
1526 int i,j;
1527 int gx, gy;
1528
1529 env.elapsed_time = (double)unmarshallFloat(th);
1530
1531 // map grids
1532 // how many X?
1533 gx = unmarshallShort(th);
1534 // how many Y?
1535 gy = unmarshallShort(th);
1536 for (i = 0; i < gx; i++)
1537 {
1538 for (j = 0; j < gy; j++)
1539 {
1540 grd[i][j] = unmarshallByte(th);
1541 env.map[i][j] = unmarshallByte(th);
1542 if (env.map[i][j] == 201) // what is this??
1543 env.map[i][j] = 239;
1544
1545 mgrd[i][j] = NON_MONSTER;
1546 env.cgrid[i][j] = unmarshallByte(th);
1547
1548 if (minorVersion < 3)
1549 {
1550 // increased number of clouds to 100 in 4.3
1551 if (env.cgrid[i][j] > 30)
1552 env.cgrid[i][j] = 101;
1553 }
1554 }
1555 }
1556
1557 env.cloud_no = unmarshallShort(th);
1558
1559 // how many clouds?
1560 gx = unmarshallShort(th);
1561 for (i = 0; i < gx; i++)
1562 {
1563 env.cloud[i].x = unmarshallByte(th);
1564 env.cloud[i].y = unmarshallByte(th);
1565 env.cloud[i].type = unmarshallByte(th);
1566 env.cloud[i].decay = unmarshallShort(th);
1567 }
1568
1569 // how many shops?
1570 gx = unmarshallByte(th);
1571 for (i = 0; i < gx; i++)
1572 {
1573 env.shop[i].keeper_name[0] = unmarshallByte(th);
1574 env.shop[i].keeper_name[1] = unmarshallByte(th);
1575 env.shop[i].keeper_name[2] = unmarshallByte(th);
1576 env.shop[i].x = unmarshallByte(th);
1577 env.shop[i].y = unmarshallByte(th);
1578 env.shop[i].greed = unmarshallByte(th);
1579 env.shop[i].type = unmarshallByte(th);
1580 env.shop[i].level = unmarshallByte(th);
1581 }
1582 }
1583
tag_read_level_items(struct tagHeader & th,char minorVersion)1584 static void tag_read_level_items(struct tagHeader &th, char minorVersion)
1585 {
1586 int i;
1587 int count;
1588
1589 // how many traps?
1590 count = unmarshallShort(th);
1591 for (i = 0; i < count; ++i)
1592 {
1593 env.trap[i].type = unmarshallByte(th);
1594 env.trap[i].x = unmarshallByte(th);
1595 env.trap[i].y = unmarshallByte(th);
1596 }
1597
1598 // how many items?
1599 count = unmarshallShort(th);
1600 for (i = 0; i < count; ++i)
1601 {
1602 if (minorVersion < 3)
1603 {
1604 mitm[i].base_type = (unsigned char) unmarshallByte(th);
1605 mitm[i].sub_type = (unsigned char) unmarshallByte(th);
1606 mitm[i].plus = (unsigned char) unmarshallByte(th);
1607 mitm[i].plus2 = (unsigned char) unmarshallByte(th);
1608 mitm[i].special = (unsigned char) unmarshallByte(th);
1609 mitm[i].quantity = unmarshallLong(th);
1610 mitm[i].colour = (unsigned char) unmarshallByte(th);
1611 mitm[i].x = (unsigned char) unmarshallByte(th);
1612 mitm[i].y = (unsigned char) unmarshallByte(th);
1613 mitm[i].flags = (unsigned char) unmarshallByte(th);
1614
1615 tag_convert_to_4_3_item( mitm[i] );
1616 }
1617 else
1618 {
1619 mitm[i].base_type = (unsigned char) unmarshallByte(th);
1620 mitm[i].sub_type = (unsigned char) unmarshallByte(th);
1621 mitm[i].plus = unmarshallShort(th);
1622 mitm[i].plus2 = unmarshallShort(th);
1623 mitm[i].special = unmarshallLong(th);
1624 mitm[i].quantity = unmarshallShort(th);
1625 mitm[i].colour = (unsigned char) unmarshallByte(th);
1626 mitm[i].x = unmarshallShort(th);
1627 mitm[i].y = unmarshallShort(th);
1628 mitm[i].flags = (unsigned long) unmarshallLong(th);
1629 }
1630
1631 // pre 4.2 files had monster items stacked at (2,2) -- moved to (0,0)
1632 if (minorVersion < 2 && mitm[i].x == 2 && mitm[i].y == 2)
1633 {
1634 mitm[i].x = 0;
1635 mitm[i].y = 0;
1636 }
1637
1638 unmarshallShort(th); // mitm[].link -- unused
1639 unmarshallShort(th); // igrd[mitm[i].x][mitm[i].y] -- unused
1640 }
1641 }
1642
tag_read_level_monsters(struct tagHeader & th,char minorVersion)1643 static void tag_read_level_monsters(struct tagHeader &th, char minorVersion)
1644 {
1645 int i,j;
1646 int count, ecount, icount;
1647
1648 // how many mons_alloc?
1649 count = unmarshallByte(th);
1650 for (i = 0; i < count; ++i)
1651 env.mons_alloc[i] = unmarshallShort(th);
1652
1653 // how many monsters?
1654 count = unmarshallShort(th);
1655 // how many monster enchantments?
1656 ecount = unmarshallByte(th);
1657 // how many monster inventory slots?
1658 icount = unmarshallByte(th);
1659
1660 for (i = 0; i < count; i++)
1661 {
1662 menv[i].armour_class = unmarshallByte(th);
1663 menv[i].evasion = unmarshallByte(th);
1664 menv[i].hit_dice = unmarshallByte(th);
1665 menv[i].speed = unmarshallByte(th);
1666 menv[i].speed_increment = unmarshallByte(th);
1667 menv[i].behaviour = unmarshallByte(th);
1668 menv[i].x = unmarshallByte(th);
1669 menv[i].y = unmarshallByte(th);
1670 menv[i].target_x = unmarshallByte(th);
1671 menv[i].target_y = unmarshallByte(th);
1672 menv[i].flags = unmarshallByte(th);
1673
1674 // VERSION NOTICE: for pre 4.2 files, flags was either 0
1675 // or 1. Now, we can transfer ENCH_CREATED_FRIENDLY over
1676 // from the enchantments array to flags.
1677 // Also need to take care of ENCH_FRIEND_ABJ_xx flags
1678
1679 for (j = 0; j < ecount; j++)
1680 menv[i].enchantment[j] = unmarshallByte(th);
1681
1682 if (minorVersion < 2)
1683 {
1684 menv[i].flags = 0;
1685 for(j=0; j<NUM_MON_ENCHANTS; j++)
1686 {
1687 if (j>=ecount)
1688 menv[i].enchantment[j] = ENCH_NONE;
1689 else
1690 {
1691 if (menv[i].enchantment[j] == 71) // old ENCH_CREATED_FRIENDLY
1692 {
1693 menv[i].enchantment[j] = ENCH_NONE;
1694 menv[i].flags |= MF_CREATED_FRIENDLY;
1695 }
1696 if (menv[i].enchantment[j] >= 65 // old ENCH_FRIEND_ABJ_I
1697 && menv[i].enchantment[j] <= 70) // old ENCH_FRIEND_ABJ_VI
1698 {
1699 menv[i].enchantment[j] -= (65 - ENCH_ABJ_I);
1700 menv[i].flags |= MF_CREATED_FRIENDLY;
1701 }
1702 }
1703 }
1704 } // end minorversion < 2
1705
1706 menv[i].type = unmarshallShort(th);
1707 menv[i].hit_points = unmarshallShort(th);
1708 menv[i].max_hit_points = unmarshallShort(th);
1709 menv[i].number = unmarshallShort(th);
1710
1711 for (j = 0; j < icount; j++)
1712 menv[i].inv[j] = unmarshallShort(th);
1713
1714 // place monster
1715 if (menv[i].type != -1)
1716 mgrd[menv[i].x][menv[i].y] = i;
1717 }
1718 }
1719
tag_read_level_attitude(struct tagHeader & th)1720 void tag_read_level_attitude(struct tagHeader &th)
1721 {
1722 int i, count;
1723
1724 // how many monsters?
1725 count = unmarshallShort(th);
1726
1727 for (i = 0; i < count; i++)
1728 {
1729 menv[i].attitude = unmarshallByte(th);
1730 menv[i].foe = unmarshallShort(th);
1731 }
1732 }
1733
tag_missing_level_attitude()1734 void tag_missing_level_attitude()
1735 {
1736 // we don't really have to do a lot here.
1737 // just set foe to MHITNOT; they'll pick up
1738 // a foe first time through handle_monster() if
1739 // there's one around.
1740
1741 // as for attitude, a couple simple checks
1742 // can be used to determine friendly/neutral/
1743 // hostile.
1744 int i;
1745 bool isFriendly;
1746 unsigned int new_beh = BEH_WANDER;
1747
1748 for(i=0; i<MAX_MONSTERS; i++)
1749 {
1750 // only do actual monsters
1751 if (menv[i].type < 0)
1752 continue;
1753
1754 isFriendly = testbits(menv[i].flags, MF_CREATED_FRIENDLY);
1755
1756 menv[i].foe = MHITNOT;
1757
1758 switch(menv[i].behaviour)
1759 {
1760 case 0: // old BEH_SLEEP
1761 new_beh = BEH_SLEEP; // don't wake sleepers
1762 break;
1763 case 3: // old BEH_FLEE
1764 case 10: // old BEH_FLEE_FRIEND
1765 new_beh = BEH_FLEE;
1766 break;
1767 case 1: // old BEH_CHASING_I
1768 case 6: // old BEH_FIGHT
1769 new_beh = BEH_SEEK;
1770 break;
1771 case 7: // old BEH_ENSLAVED
1772 if (!mons_has_ench(&menv[i], ENCH_CHARM))
1773 isFriendly = true;
1774 break;
1775 default:
1776 break;
1777 }
1778
1779 menv[i].attitude = (isFriendly)?ATT_FRIENDLY : ATT_HOSTILE;
1780 menv[i].behaviour = new_beh;
1781 menv[i].foe_memory = 0;
1782 }
1783 }
1784
1785
1786 // ------------------------------- ghost tags ---------------------------- //
1787
tag_construct_ghost(struct tagHeader & th)1788 static void tag_construct_ghost(struct tagHeader &th)
1789 {
1790 int i;
1791
1792 marshallString(th, ghost.name, 20);
1793
1794 // how many ghost values?
1795 marshallByte(th, 20);
1796
1797 for (i = 0; i < 20; i++)
1798 marshallShort( th, ghost.values[i] );
1799 }
1800
tag_read_ghost(struct tagHeader & th,char minorVersion)1801 static void tag_read_ghost(struct tagHeader &th, char minorVersion)
1802 {
1803 int i, count_c;
1804
1805 snprintf( info, INFO_SIZE, "minor version = %d", minorVersion );
1806
1807 unmarshallString(th, ghost.name, 20);
1808
1809 // how many ghost values?
1810 count_c = unmarshallByte(th);
1811
1812 for (i = 0; i < count_c; i++)
1813 {
1814 // for version 4.4 we moved from unsigned char to shorts -- bwr
1815 if (minorVersion < 4)
1816 ghost.values[i] = unmarshallByte(th);
1817 else
1818 ghost.values[i] = unmarshallShort(th);
1819 }
1820
1821 if (minorVersion < 4)
1822 {
1823 // Getting rid 9of hopefulling the last) of this silliness -- bwr
1824 if (ghost.values[ GVAL_RES_FIRE ] >= 97)
1825 ghost.values[ GVAL_RES_FIRE ] -= 100;
1826
1827 if (ghost.values[ GVAL_RES_COLD ] >= 97)
1828 ghost.values[ GVAL_RES_COLD ] -= 100;
1829 }
1830 }
1831
1832 // ----------------------------------------------------------------------- //
1833