[BACK]Return to state.c CVS log [TXT][DIR] Up to [contributed] / early-roguelike / xrogue

Annotation of early-roguelike/xrogue/state.c, Revision 1.1.1.1

1.1       rubenllo    1: /*
                      2:     state.c - Portable Rogue Save State Code
                      3:
                      4:     Copyright (C) 2000 Nicholas J. Kisseberth
                      5:
                      6:     Redistribution and use in source and binary forms, with or without
                      7:     modification, are permitted provided that the following conditions
                      8:     are met:
                      9:     1. Redistributions of source code must retain the above copyright
                     10:        notice, this list of conditions and the following disclaimer.
                     11:     2. Redistributions in binary form must reproduce the above copyright
                     12:        notice, this list of conditions and the following disclaimer in the
                     13:        documentation and/or other materials provided with the distribution.
                     14:     3. Neither the name(s) of the author(s) nor the names of other contributors
                     15:        may be used to endorse or promote products derived from this software
                     16:        without specific prior written permission.
                     17:
                     18:     THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND
                     19:     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     20:     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     21:     ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE
                     22:     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     23:     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     24:     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     25:     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     26:     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     27:     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     28:     SUCH DAMAGE.
                     29: */
                     30:
                     31: #define RSXR_STATS        0xABCD0001
                     32: #define RSXR_THING        0xABCD0002
                     33: #define RSXR_OBJECT       0xABCD0003
                     34: #define RSXR_MAGICITEMS   0xABCD0004
                     35: #define RSXR_KNOWS        0xABCD0005
                     36: #define RSXR_GUESSES      0xABCD0006
                     37: #define RSXR_OBJECTLIST   0xABCD0007
                     38: #define RSXR_BAGOBJECT    0xABCD0008
                     39: #define RSXR_MONSTERLIST  0xABCD0009
                     40: #define RSXR_MONSTERSTATS 0xABCD000A
                     41: #define RSXR_MONSTERS     0xABCD000B
                     42: #define RSXR_TRAP         0xABCD000C
                     43: #define RSXR_WINDOW       0xABCD000D
                     44: #define RSXR_DAEMONS      0xABCD000E
                     45: #define RSXR_IWEAPS       0xABCD000F
                     46: #define RSXR_IARMOR       0xABCD0010
                     47: #define RSXR_SPELLS       0xABCD0011
                     48: #define RSXR_ILIST        0xABCD0012
                     49: #define RSXR_HLIST        0xABCD0013
                     50: #define RSXR_DEATHTYPE    0xABCD0014
                     51: #define RSXR_CTYPES       0XABCD0015
                     52: #define RSXR_COORDLIST    0XABCD0016
                     53: #define RSXR_ROOMS        0XABCD0017
                     54:
                     55: #ifdef HAVE_CONFIG_H
                     56: #include "config.h"
                     57: #endif
                     58:
                     59: #if defined(_WIN32)
                     60: #include <Windows.h>
                     61: #include <Lmcons.h>
                     62: #include <shlobj.h>
                     63: #include <Shlwapi.h>
                     64: #undef MOUSE_MOVED
                     65: #elif defined(__DJGPP__)
                     66: #include <process.h>
                     67: #else
                     68: #include <pwd.h>
                     69: #include <sys/wait.h>
                     70: #include <sys/utsname.h>
                     71: #include <unistd.h>
                     72: #endif
                     73:
                     74: #include <stdlib.h>
                     75: #include <string.h>
                     76: #include <curses.h>
                     77: #include <sys/stat.h>
                     78: #include <stdio.h>
                     79: #include <stdarg.h>
                     80: #include <assert.h>
                     81: #include <fcntl.h>
                     82: #include <limits.h>
                     83: #include <time.h>
                     84: #include <signal.h>
                     85: #include "rogue.h"
                     86: #include "mach_dep.h"
                     87:
                     88: #if defined(_WIN32)
                     89: #include <process.h>
                     90: #endif
                     91:
                     92: #ifdef HAVE_ARPA_INET_H
                     93: #include <arpa/inet.h>
                     94: #endif
                     95:
                     96: int md_fileno(FILE *fp);
                     97:
                     98: #define READSTAT ((format_error == 0) && (read_error == 0))
                     99: #define WRITESTAT (write_error == 0)
                    100:
                    101: int read_error   = FALSE;
                    102: int write_error  = FALSE;
                    103: int format_error = FALSE;
                    104:
                    105: int save_debug = FALSE;
                    106: #define DBG(x)   {if (save_debug) rsPrintf x;}
                    107:
                    108: bool rs_read_new_string(FILE *inf, char **s);
                    109: int find_list_ptr(struct linked_list *l, void *ptr);
                    110: bool rs_write_coord_list(FILE *savef, struct linked_list *l);
                    111: bool rs_read_coord_list(FILE *inf, struct linked_list **list);
                    112: int list_size(struct linked_list *l);
                    113: bool rs_write_object_list(FILE *savef, struct linked_list *l);
                    114: bool rs_read_object_list(FILE *inf, struct linked_list **list);
                    115:
                    116: int
                    117: rsPrintf(char *fmt, ...)
                    118: {
                    119:     va_list ap;
                    120:
                    121:     va_start(ap, fmt);
                    122:     vfprintf(stderr,fmt, ap);
                    123:     va_end(ap);
                    124:
                    125:     return(0);
                    126: }
                    127:
                    128:
                    129: void *
                    130: get_list_item(struct linked_list *l, int i)
                    131: {
                    132:     int count = 0;
                    133:
                    134:     while(l != NULL)
                    135:     {
                    136:         if (count == i)
                    137:             return(l->l_data);
                    138:
                    139:         l = l->l_next;
                    140:
                    141:         count++;
                    142:     }
                    143:
                    144:     return(NULL);
                    145: }
                    146:
                    147: bool
                    148: rs_write(FILE *savef, void *ptr, size_t size)
                    149: {
                    150:     size_t i = 0;
                    151:
                    152:     if (!write_error)
                    153:         i = ENCWRITE(ptr,size,savef);
                    154:     if (i != size)
                    155:         write_error = TRUE;
                    156:
                    157:     assert(write_error == 0);
                    158:     return(WRITESTAT);
                    159: }
                    160:
                    161: int end_of_file = FALSE;
                    162:
                    163: bool
                    164: rs_read(FILE *inf, void *ptr, size_t size)
                    165: {
                    166:     int actual;
                    167:     end_of_file =FALSE;
                    168:     if (!read_error && !format_error)
                    169:     {
                    170:         actual = ENCREAD(ptr, size, inf);
                    171:
                    172:         if ((actual == 0) && (size != 0))
                    173:            end_of_file = TRUE;
                    174:     }
                    175:
                    176:     if (read_error){
                    177:         printf("read error has occurred. restore short-circuited.\n");abort();}
                    178:     if (format_error)
                    179:         {printf("game format invalid. restore short-circuited.\n");abort();}
                    180:
                    181:     return(READSTAT);
                    182: }
                    183:
                    184: int big_endian = 0;
                    185:
                    186: bool
                    187: rs_write_uint(FILE *savef, unsigned int c)
                    188: {
                    189:     char bytes[4];
                    190:     char *buf = (char *) &c;
                    191:
                    192:     if (big_endian)
                    193:     {
                    194:         bytes[3] = buf[0];
                    195:         bytes[2] = buf[1];
                    196:         bytes[1] = buf[2];
                    197:         bytes[0] = buf[3];
                    198:         buf = bytes;
                    199:     }
                    200:
                    201:     rs_write(savef, buf, 4);
                    202:
                    203:     return(WRITESTAT);
                    204: }
                    205:
                    206: bool
                    207: rs_write_int(FILE *savef, int c)
                    208: {
                    209:     char bytes[4];
                    210:     char *buf = (char *) &c;
                    211:
                    212:     if (big_endian)
                    213:     {
                    214:         bytes[3] = buf[0];
                    215:         bytes[2] = buf[1];
                    216:         bytes[1] = buf[2];
                    217:         bytes[0] = buf[3];
                    218:         buf = bytes;
                    219:     }
                    220:
                    221:     rs_write(savef, buf, 4);
                    222:
                    223:     return(WRITESTAT);
                    224: }
                    225:
                    226: bool
                    227: rs_write_ulong(FILE *savef, unsigned long c)
                    228: {
                    229:     unsigned int c2;
                    230:     char bytes[4];
                    231:     char *buf = (char *)&c;
                    232:
                    233:     if ( (sizeof(long) == 8) && (sizeof(int) == 4) )
                    234:     {
                    235:         c2 = c;
                    236:         buf = (char *) &c2;
                    237:     }
                    238:
                    239:     if (big_endian)
                    240:     {
                    241:         bytes[3] = buf[0];
                    242:         bytes[2] = buf[1];
                    243:         bytes[1] = buf[2];
                    244:         bytes[0] = buf[3];
                    245:         buf = bytes;
                    246:     }
                    247:
                    248:     rs_write(savef, buf, 4);
                    249:
                    250:     return(WRITESTAT);
                    251: }
                    252:
                    253: bool
                    254: rs_write_long(FILE *savef, long c)
                    255: {
                    256:     int c2;
                    257:     char bytes[4];
                    258:     char *buf = (char *)&c;
                    259:
                    260:     if ( (sizeof(long) == 8) && (sizeof(int) == 4) )
                    261:     {
                    262:         c2 = c;
                    263:         buf = (char *) &c2;
                    264:     }
                    265:
                    266:     if (big_endian)
                    267:     {
                    268:         bytes[3] = buf[0];
                    269:         bytes[2] = buf[1];
                    270:         bytes[1] = buf[2];
                    271:         bytes[0] = buf[3];
                    272:         buf = bytes;
                    273:     }
                    274:
                    275:     rs_write(savef, buf, 4);
                    276:
                    277:     return(WRITESTAT);
                    278: }
                    279:
                    280: bool
                    281: rs_write_boolean(FILE *savef, bool c)
                    282: {
                    283:     char buf;
                    284:
                    285:     if (c == 0)
                    286:         buf = 0;
                    287:     else
                    288:         buf = 1;
                    289:
                    290:     rs_write(savef, &buf, 1);
                    291:
                    292:     return(WRITESTAT);
                    293: }
                    294:
                    295: bool
                    296: rs_read_int(FILE *inf, int *i)
                    297: {
                    298:     char bytes[4];
                    299:     int  input;
                    300:     char *buf = (char *)&input;
                    301:
                    302:     rs_read(inf, &input, 4);
                    303:
                    304:     if (big_endian)
                    305:     {
                    306:         bytes[3] = buf[0];
                    307:         bytes[2] = buf[1];
                    308:         bytes[1] = buf[2];
                    309:         bytes[0] = buf[3];
                    310:         buf = bytes;
                    311:     }
                    312:
                    313:     *i = *((int *) buf);
                    314:
                    315:     return(READSTAT);
                    316: }
                    317:
                    318: bool
                    319: rs_read_uint(FILE *inf, unsigned int *i)
                    320: {
                    321:     char bytes[4];
                    322:     int  input;
                    323:     char *buf = (char *)&input;
                    324:
                    325:     rs_read(inf, &input, 4);
                    326:
                    327:     if (big_endian)
                    328:     {
                    329:         bytes[3] = buf[0];
                    330:         bytes[2] = buf[1];
                    331:         bytes[1] = buf[2];
                    332:         bytes[0] = buf[3];
                    333:         buf = bytes;
                    334:     }
                    335:
                    336:     *i = *((int *) buf);
                    337:
                    338:     return(READSTAT);
                    339: }
                    340:
                    341: bool
                    342: rs_read_ulong(FILE *inf, unsigned long *i)
                    343: {
                    344:     char bytes[4];
                    345:     unsigned long input;
                    346:     char *buf = (char *) &input;
                    347:
                    348:     rs_read(inf, &input, 4);
                    349:
                    350:     if (big_endian)
                    351:     {
                    352:         bytes[3] = buf[0];
                    353:         bytes[2] = buf[1];
                    354:         bytes[1] = buf[2];
                    355:         bytes[0] = buf[3];
                    356:         buf = bytes;
                    357:     }
                    358:
                    359:     if ( (sizeof(long) == 8) && (sizeof(int) == 4) )
                    360:       *i = *((unsigned int *) buf);
                    361:     else
                    362:       *i = *((unsigned long *) buf);
                    363:     return(READSTAT);
                    364: }
                    365:
                    366: bool
                    367: rs_read_long(FILE *inf, long *i)
                    368: {
                    369:     char bytes[4];
                    370:     long input;
                    371:     char *buf = (char *) &input;
                    372:
                    373:     rs_read(inf, &input, 4);
                    374:
                    375:     if (big_endian)
                    376:     {
                    377:         bytes[3] = buf[0];
                    378:         bytes[2] = buf[1];
                    379:         bytes[1] = buf[2];
                    380:         bytes[0] = buf[3];
                    381:         buf = bytes;
                    382:     }
                    383:
                    384:     if ( (sizeof(long) == 8) && (sizeof(int) == 4) )
                    385:       *i = *((int *) buf);
                    386:     else
                    387:       *i = *((long *) buf);
                    388:     return(READSTAT);
                    389: }
                    390:
                    391: bool
                    392: rs_read_boolean(FILE *inf, bool *i)
                    393: {
                    394:     char buf;
                    395:
                    396:     rs_read(inf, &buf, 1);
                    397:
                    398:     *i = buf;
                    399:
                    400:     return(READSTAT);
                    401: }
                    402:
                    403: bool
                    404: rs_write_ints(FILE *savef, int *c, int count)
                    405: {
                    406:     int n=0;
                    407:
                    408:     rs_write_int(savef,count);
                    409:
                    410:     for(n=0;n<count;n++)
                    411:         rs_write_int(savef,c[n]);
                    412:
                    413:     return(WRITESTAT);
                    414: }
                    415:
                    416: bool
                    417: rs_write_short(FILE *savef, short c)
                    418: {
                    419:     char bytes[2];
                    420:     char *buf = (char *) &c;
                    421:
                    422:     if (big_endian)
                    423:     {
                    424:         bytes[1] = buf[0];
                    425:         bytes[0] = buf[1];
                    426:         buf = bytes;
                    427:     }
                    428:
                    429:     rs_write(savef, buf, 2);
                    430:
                    431:     return(WRITESTAT);
                    432: }
                    433:
                    434: bool
                    435: rs_read_short(FILE *inf, short *s)
                    436: {
                    437:     char  bytes[2];
                    438:     short input;
                    439:     char *buf = (char *)&input;
                    440:
                    441:     rs_read(inf, &input, 2);
                    442:
                    443:     if (big_endian)
                    444:     {
                    445:         bytes[1] = buf[0];
                    446:         bytes[0] = buf[1];
                    447:         buf = bytes;
                    448:     }
                    449:
                    450:     *s = *((short *) buf);
                    451:     return(READSTAT);
                    452: }
                    453:
                    454:
                    455: bool
                    456: rs_write_shorts(FILE *savef, short *c, int count)
                    457: {
                    458:     int n=0;
                    459:
                    460:     rs_write_int(savef,count);
                    461:
                    462:     for(n=0;n<count;n++)
                    463:         rs_write_short(savef,c[n]);
                    464:
                    465:     return(WRITESTAT);
                    466: }
                    467:
                    468: bool
                    469: rs_write_longs(FILE *savef, long *c, int count)
                    470: {
                    471:     int n=0;
                    472:
                    473:     rs_write_int(savef,count);
                    474:
                    475:     for(n=0;n<count;n++)
                    476:         rs_write_long(savef,c[n]);
                    477:
                    478:     return(WRITESTAT);
                    479: }
                    480:
                    481: bool
                    482: rs_write_ulongs(FILE *savef, unsigned long *c, int count)
                    483: {
                    484:     int n=0;
                    485:
                    486:     rs_write_int(savef,count);
                    487:
                    488:     for(n=0;n<count;n++)
                    489:         rs_write_ulong(savef,c[n]);
                    490:
                    491:     return(WRITESTAT);
                    492: }
                    493:
                    494: bool
                    495: rs_write_booleans(FILE *savef, bool *c, int count)
                    496: {
                    497:     int n=0;
                    498:
                    499:     rs_write_int(savef,count);
                    500:
                    501:     for(n=0;n<count;n++)
                    502:         rs_write_boolean(savef,c[n]);
                    503:
                    504:     return(WRITESTAT);
                    505: }
                    506:
                    507: bool
                    508: rs_read_ints(FILE *inf, int *i, int count)
                    509: {
                    510:     int n=0,value=0;
                    511:
                    512:     if (rs_read_int(inf,&value) != 0)
                    513:     {
                    514:         if (value != count)
                    515:             format_error = TRUE;
                    516:         else
                    517:         {
                    518:             for(n=0;n<value;n++)
                    519:                 rs_read_int(inf, &i[n]);
                    520:         }
                    521:     }
                    522:
                    523:     return(READSTAT);
                    524: }
                    525:
                    526: bool
                    527: rs_read_shorts(FILE *inf, short *i, int count)
                    528: {
                    529:     int n=0,value=0;
                    530:
                    531:     if (rs_read_int(inf,&value) != 0)
                    532:     {
                    533:         if (value != count)
                    534:             format_error = TRUE;
                    535:         else
                    536:         {
                    537:             for(n=0;n<value;n++)
                    538:                 rs_read_short(inf, &i[n]);
                    539:         }
                    540:     }
                    541:
                    542:     return(READSTAT);
                    543: }
                    544:
                    545: bool
                    546: rs_read_longs(FILE *inf, long *i, int count)
                    547: {
                    548:     int n=0,value=0;
                    549:
                    550:     if (rs_read_int(inf,&value) != 0)
                    551:     {
                    552:         if (value != count)
                    553:             format_error = TRUE;
                    554:         else
                    555:         {
                    556:             for(n=0;n<value;n++)
                    557:                 rs_read_long(inf, &i[n]);
                    558:         }
                    559:     }
                    560:
                    561:     return(READSTAT);
                    562: }
                    563:
                    564: bool
                    565: rs_read_ulongs(FILE *inf, unsigned long *i, int count)
                    566: {
                    567:     int n=0,value=0;
                    568:
                    569:     if (rs_read_int(inf,&value) != 0)
                    570:     {
                    571:         if (value != count)
                    572:             format_error = TRUE;
                    573:         else
                    574:         {
                    575:             for(n=0;n<value;n++)
                    576:                 rs_read_ulong(inf, &i[n]);
                    577:         }
                    578:     }
                    579:
                    580:     return(READSTAT);
                    581: }
                    582:
                    583: bool
                    584: rs_read_booleans(FILE *inf, bool *i, int count)
                    585: {
                    586:     int n=0,value=0;
                    587:
                    588:     if (rs_read_int(inf,&value) != 0)
                    589:     {
                    590:         if (value != count)
                    591:             format_error = TRUE;
                    592:         else
                    593:         {
                    594:             for(n=0;n<value;n++)
                    595:                 rs_read_boolean(inf, &i[n]);
                    596:         }
                    597:     }
                    598:
                    599:     return(READSTAT);
                    600: }
                    601:
                    602: bool
                    603: rs_write_levtype(FILE *savef, LEVTYPE c)
                    604: {
                    605:     int lt;
                    606:
                    607:     switch(c)
                    608:     {
                    609:         case NORMLEV: lt = 1; break;
                    610:         case POSTLEV: lt = 2; break;
                    611:         case MAZELEV: lt = 3; break;
                    612:         case OUTSIDE: lt = 4; break;
                    613:         case STARTLEV: lt = 5; break;
                    614:         default: lt = -1; break;
                    615:     }
                    616:
                    617:     rs_write_int(savef,lt);
                    618:
                    619:     return(WRITESTAT);
                    620: }
                    621:
                    622: bool
                    623: rs_read_levtype(FILE *inf, LEVTYPE *l)
                    624: {
                    625:     int lt;
                    626:
                    627:     rs_read_int(inf, &lt);
                    628:
                    629:     switch(lt)
                    630:     {
                    631:         case 1: *l = NORMLEV; break;
                    632:         case 2: *l = POSTLEV; break;
                    633:         case 3: *l = MAZELEV; break;
                    634:         case 4: *l = OUTSIDE; break;
                    635:         case 5: *l = STARTLEV; break;
                    636:         default: *l = NORMLEV; break;
                    637:     }
                    638:
                    639:     return(READSTAT);
                    640: }
                    641:
                    642: bool
                    643: rs_write_char(FILE *savef, char c)
                    644: {
                    645:     rs_write(savef, &c, 1);
                    646:     DBG(("%c",c));
                    647:
                    648:     return(WRITESTAT);
                    649: }
                    650:
                    651: bool
                    652: rs_read_char(FILE *inf, char *c)
                    653: {
                    654:     rs_read(inf, c, 1);
                    655:
                    656:     return(READSTAT);
                    657: }
                    658:
                    659: bool
                    660: rs_write_uchar(FILE *savef, unsigned char c)
                    661: {
                    662:     rs_write(savef, &c, 1);
                    663:     DBG(("%c",c));
                    664:
                    665:     return(WRITESTAT);
                    666: }
                    667:
                    668: bool
                    669: rs_read_uchar(FILE *inf, unsigned char *c)
                    670: {
                    671:     rs_read(inf, c, 1);
                    672:
                    673:     return(READSTAT);
                    674: }
                    675:
                    676: bool
                    677: rs_write_string(FILE *savef, char *s)
                    678: {
                    679:     int len = 0;
                    680:
                    681:     len = (s == NULL) ? 0 : (int) strlen(s) + 1;
                    682:
                    683:     rs_write_uint(savef, (unsigned int) len);
                    684:     rs_write(savef, s, len);
                    685:
                    686:     return(WRITESTAT);
                    687: }
                    688:
                    689: bool
                    690: rs_read_string_index(FILE *inf, struct words master[], int maxindex, char **str)
                    691: {
                    692:     int i;
                    693:
                    694:     if (rs_read_int(inf,&i) != 0)
                    695:     {
                    696:         if (i > maxindex)
                    697:         {
                    698:             printf("String index is out of range. %d > %d\n",
                    699:                 i, maxindex);
                    700:             printf("Sorry, invalid save game format\n");
                    701:             format_error = TRUE;
                    702:         }
                    703:         else if (i >= 0)
                    704:             *str = master[i].w_string;
                    705:         else
                    706:             *str = NULL;
                    707:     }
                    708:     return(READSTAT);
                    709: }
                    710:
                    711: bool
                    712: rs_write_string_index(FILE *savef, struct words master[], int maxindex, char *str)
                    713: {
                    714:     int i;
                    715:
                    716:     for(i = 0; i < maxindex; i++)
                    717:     {
                    718:         if (str == master[i].w_string)
                    719:         {
                    720:             rs_write_int(savef,i);
                    721:             return(WRITESTAT);
                    722:         }
                    723:     }
                    724:
                    725:     rs_write_int(savef,-1);
                    726:     return(WRITESTAT);
                    727: }
                    728:
                    729: bool
                    730: rs_read_scrolls(FILE *inf)
                    731: {
                    732:     int i;
                    733:
                    734:     for(i = 0; i < MAXSCROLLS; i++)
                    735:     {
                    736:         rs_read_new_string(inf,&s_names[i]);
                    737:         rs_read_boolean(inf,&s_know[i]);
                    738:         rs_read_new_string(inf,&s_guess[i]);
                    739:     }
                    740:
                    741:     return(READSTAT);
                    742: }
                    743:
                    744: bool
                    745: rs_write_scrolls(FILE *savef)
                    746: {
                    747:     int i;
                    748:
                    749:     for(i = 0; i < MAXSCROLLS; i++)
                    750:     {
                    751:         rs_write_string(savef,s_names[i]);
                    752:         rs_write_boolean(savef,s_know[i]);
                    753:         rs_write_string(savef,s_guess[i]);
                    754:     }
                    755:     return(WRITESTAT);
                    756: }
                    757:
                    758: bool
                    759: rs_read_potions(FILE *inf)
                    760: {
                    761:     int i;
                    762:
                    763:     for(i = 0; i < MAXPOTIONS; i++)
                    764:     {
                    765:         rs_read_string_index(inf,rainbow,NCOLORS,&p_colors[i]);
                    766:         rs_read_boolean(inf,&p_know[i]);
                    767:         rs_read_new_string(inf,&p_guess[i]);
                    768:     }
                    769:
                    770:     return(READSTAT);
                    771: }
                    772:
                    773: bool
                    774: rs_write_potions(FILE *savef)
                    775: {
                    776:     int i;
                    777:
                    778:     for(i = 0; i < MAXPOTIONS; i++)
                    779:     {
                    780:         rs_write_string_index(savef,rainbow,NCOLORS,p_colors[i]);
                    781:         rs_write_boolean(savef,p_know[i]);
                    782:         rs_write_string(savef,p_guess[i]);
                    783:     }
                    784:
                    785:     return(WRITESTAT);
                    786: }
                    787:
                    788: bool
                    789: rs_read_rings(FILE *inf)
                    790: {
                    791:     int i;
                    792:
                    793:     for(i = 0; i < MAXRINGS; i++)
                    794:     {
                    795:         rs_read_string_index(inf,stones,NSTONES,&r_stones[i]);
                    796:         rs_read_boolean(inf,&r_know[i]);
                    797:         rs_read_new_string(inf,&r_guess[i]);
                    798:     }
                    799:
                    800:     return(READSTAT);
                    801: }
                    802:
                    803: bool
                    804: rs_write_rings(FILE *savef)
                    805: {
                    806:     int i;
                    807:
                    808:     for(i = 0; i < MAXRINGS; i++)
                    809:     {
                    810:         rs_write_string_index(savef,stones,NSTONES,r_stones[i]);
                    811:         rs_write_boolean(savef,r_know[i]);
                    812:         rs_write_string(savef,r_guess[i]);
                    813:     }
                    814:
                    815:     return(WRITESTAT);
                    816: }
                    817:
                    818: bool
                    819: rs_read_misc(FILE *inf)
                    820: {
                    821:     int i;
                    822:
                    823:     for(i = 0; i < MAXMM; i++)
                    824:     {
                    825:         rs_read_boolean(inf,&m_know[i]);
                    826:         rs_read_new_string(inf,&m_guess[i]);
                    827:     }
                    828:
                    829:     return(READSTAT);
                    830: }
                    831:
                    832: bool
                    833: rs_write_misc(FILE *savef)
                    834: {
                    835:     int i;
                    836:
                    837:     for(i = 0; i < MAXMM; i++)
                    838:     {
                    839:         rs_write_boolean(savef,m_know[i]);
                    840:         rs_write_string(savef,m_guess[i]);
                    841:     }
                    842:
                    843:     return(WRITESTAT);
                    844: }
                    845:
                    846: bool
                    847: rs_write_sticks(FILE *savef)
                    848: {
                    849:     int i;
                    850:
                    851:     for (i = 0; i < MAXSTICKS; i++)
                    852:     {
                    853:         if (strcmp(ws_type[i],"staff") == 0)
                    854:         {
                    855:             rs_write_int(savef,0);
                    856:             rs_write_string_index(savef, wood, NWOOD, ws_made[i]);
                    857:         }
                    858:         else
                    859:         {
                    860:             rs_write_int(savef,1);
                    861:             rs_write_string_index(savef, metal, NMETAL, ws_made[i]);
                    862:         }
                    863:         rs_write_boolean(savef, ws_know[i]);
                    864:         rs_write_string(savef, ws_guess[i]);
                    865:     }
                    866:
                    867:     return(WRITESTAT);
                    868: }
                    869:
                    870: bool
                    871: rs_read_sticks(FILE *inf)
                    872: {
                    873:     int i = 0, list = 0;
                    874:
                    875:     for(i = 0; i < MAXSTICKS; i++)
                    876:     {
                    877:         rs_read_int(inf,&list);
                    878:         if (list == 0)
                    879:         {
                    880:             rs_read_string_index(inf,wood,NWOOD,&ws_made[i]);
                    881:             ws_type[i] = "staff";
                    882:         }
                    883:         else
                    884:         {
                    885:             rs_read_string_index(inf,metal,NMETAL,&ws_made[i]);
                    886:             ws_type[i] = "wand";
                    887:         }
                    888:         rs_read_boolean(inf, &ws_know[i]);
                    889:         rs_read_new_string(inf, &ws_guess[i]);
                    890:     }
                    891:
                    892:     return(READSTAT);
                    893: }
                    894:
                    895: bool
                    896: rs_read_string(FILE *inf, char *s, int max)
                    897: {
                    898:     int len = 0;
                    899:
                    900:     if (rs_read_int(inf, &len) != FALSE)
                    901:     {
                    902:         if (len > max)
                    903:         {
                    904:             printf("String too long to restore. %d > %d\n",len,max);
                    905:             printf("Sorry, invalid save game format\n");
                    906:             format_error = TRUE;
                    907:         }
                    908:
                    909:         rs_read(inf, s, len);
                    910:     }
                    911:
                    912:     return(READSTAT);
                    913: }
                    914:
                    915: bool
                    916: rs_read_new_string(FILE *inf, char **s)
                    917: {
                    918:     int len=0;
                    919:     char *buf=0;
                    920:
                    921:     if (rs_read_int(inf, &len) != 0)
                    922:     {
                    923:         if (len == 0)
                    924:             *s = NULL;
                    925:         else
                    926:         {
                    927:             buf = malloc(len);
                    928:
                    929:             if (buf == NULL)
                    930:                 read_error = TRUE;
                    931:             else
                    932:             {
                    933:                 rs_read(inf, buf, len);
                    934:                 *s = buf;
                    935:             }
                    936:         }
                    937:     }
                    938:
                    939:     return(READSTAT);
                    940: }
                    941:
                    942: bool
                    943: rs_write_strings(FILE *savef, char *s[], int count)
                    944: {
                    945:     int len = 0;
                    946:     int n = 0;
                    947:
                    948:     rs_write_int(savef,count);
                    949:
                    950:     for(n = 0; n < count; n++)
                    951:     {
                    952:         len = (s[n] == NULL) ? 0L : (int) strlen(s[n]) + 1;
                    953:         rs_write_int(savef, len);
                    954:         rs_write(savef, s[n], len);
                    955:         DBG(("%s",s[n]));
                    956:     }
                    957:
                    958:     return(WRITESTAT);
                    959: }
                    960:
                    961: bool
                    962: rs_write_words(FILE *savef, struct words *w, int count)
                    963: {
                    964:     int n = 0;
                    965:
                    966:     rs_write_int(savef,count);
                    967:
                    968:     for(n = 0; n < count; n++)
                    969:     {
                    970:         rs_write(savef, w[n].w_string, sizeof(w[n].w_string));
                    971:         DBG(("%s",w[n].w_string));
                    972:     }
                    973:
                    974:     return(WRITESTAT);
                    975: }
                    976:
                    977: bool
                    978: rs_read_words(FILE *inf, struct words *w, int count)
                    979: {
                    980:     int n = 0;
                    981:     int value = 0;
                    982:
                    983:     rs_read_int(inf,&value);
                    984:
                    985:     if (value != count)
                    986:     {
                    987:         printf("Incorrect number of words in block. %d != %d.",
                    988:                 value,count);
                    989:         printf("Sorry, invalid save game format");
                    990:         format_error = TRUE;
                    991:     }
                    992:     else for(n = 0; n < count; n++)
                    993:     {
                    994:         rs_read(inf, w[n].w_string, sizeof(w[n].w_string));
                    995:     }
                    996:
                    997:     return(READSTAT);
                    998: }
                    999:
                   1000: bool
                   1001: rs_read_new_strings(FILE *inf, char **s, int count)
                   1002: {
                   1003:     int len   = 0;
                   1004:     int n     = 0;
                   1005:     int value = 0;
                   1006:
                   1007:     if (rs_read_int(inf,&value) != 0)
                   1008:     {
                   1009:         if (value != count)
                   1010:         {
                   1011:             printf("Incorrect number of strings in block. %d > %d.",
                   1012:                 value,count);
                   1013:             printf("Sorry, invalid save game format");
                   1014:             format_error = TRUE;
                   1015:         }
                   1016:         else
                   1017:             for(n=0; n<value; n++)
                   1018:             {
                   1019:                 rs_read_int(inf, &len);
                   1020:
                   1021:                 if (len == 0)
                   1022:                     s[n]=0;
                   1023:                 else
                   1024:                 {
                   1025:                     s[n] = malloc(len);
                   1026:                     rs_read(inf,s[n],len);
                   1027:                 }
                   1028:             }
                   1029:     }
                   1030:
                   1031:     return(READSTAT);
                   1032: }
                   1033:
                   1034: bool
                   1035: rs_write_coord(FILE *savef, coord *c)
                   1036: {
                   1037:     DBG(("X ="));
                   1038:     rs_write_int(savef, c->x);
                   1039:     DBG(("Y ="));
                   1040:     rs_write_int(savef, c->y);
                   1041:
                   1042:     return(WRITESTAT);
                   1043: }
                   1044:
                   1045: bool
                   1046: rs_read_coord(FILE *inf, coord *c)
                   1047: {
                   1048:     rs_read_int(inf,&c->x);
                   1049:     rs_read_int(inf,&c->y);
                   1050:
                   1051:     return(READSTAT);
                   1052: }
                   1053:
                   1054: /* Assigns a number to an alchemy jug associated with a fuse, so it can be
                   1055:  * found and reassociated when restoring.
                   1056:  * 1 - 31: slot in pack
                   1057:  * 32+   : on floor
                   1058:  * Hopefully monsters do not pick them up.
                   1059:  */
                   1060: int number_alchemy_jug(struct object *obj) {
                   1061:     struct object *tobj = NULL;
                   1062:     struct linked_list *item;
                   1063:     int i = 1;
                   1064:     for (item = pack; item != NULL; item = next(item), i++) {
                   1065:        tobj = OBJPTR(item);
                   1066:        if (tobj         == obj         &&
                   1067:            tobj->o_type == MM          &&
                   1068:            tobj->o_which== MM_JUG)
                   1069:                break;
                   1070:     }
                   1071:     if (item == NULL) {
                   1072:        for (item = lvl_obj, i = 32; item != NULL; item = next(item), i++) {
                   1073:            tobj = OBJPTR(item);
                   1074:            if (tobj         == obj             &&
                   1075:                tobj->o_type == MM              &&
                   1076:                tobj->o_which== MM_JUG)
                   1077:                    break;
                   1078:        }
                   1079:     }
                   1080:     if (item == NULL)
                   1081:       return 0;
                   1082:     return i;
                   1083: }
                   1084:
                   1085: /* Takes an alchemy jug number and tracks down the object. */
                   1086: struct object *find_alchemy_jug(int n) {
                   1087:     struct object *tobj;
                   1088:     struct linked_list *item;
                   1089:
                   1090:     if (n <= 0) {
                   1091:         return NULL;
                   1092:     }
                   1093:     else if (n < 32) {
                   1094:         item = pack;
                   1095:         n -= 1;
                   1096:     }
                   1097:     else if (n < 1024) {
                   1098:         item = lvl_obj;
                   1099:         n -= 32;
                   1100:     }
                   1101:     else {
                   1102:         /* This is likely a bug, not 1024 actual items on the floor. */
                   1103:         return NULL;
                   1104:     }
                   1105:     while (item != NULL && n > 0) {
                   1106:         item = next(item);
                   1107:         n--;
                   1108:     }
                   1109:     if (item == NULL)
                   1110:         return NULL;
                   1111:     tobj = OBJPTR(item);
                   1112:     if (tobj->o_type != MM || tobj->o_which != MM_JUG)
                   1113:         return NULL;
                   1114:     return tobj;
                   1115: }
                   1116:
                   1117: bool
                   1118: rs_write_daemons(FILE *savef, struct delayed_action *d_list,int count)
                   1119: {
                   1120:     int i = 0;
                   1121:     int func = 0;
                   1122:
                   1123:     DBG(("Daemons\n"));
                   1124:     rs_write_int(savef, RSXR_DAEMONS);
                   1125:     rs_write_int(savef, count);
                   1126:
                   1127:     for(i=0; i < count; i++)
                   1128:     {
                   1129:         if (d_list[i].d_func == rollwand)
                   1130:             func = 1;
                   1131:         else if (d_list[i].d_func == doctor)
                   1132:             func = 2;
                   1133:         else if (d_list[i].d_func == stomach)
                   1134:             func = 3;
                   1135:         else if (d_list[i].d_func == trap_look)
                   1136:             func = 4;
                   1137:         else if (d_list[i].d_func == eat_gold)
                   1138:             func = 5;
                   1139:         else if (d_list[i].d_func == ring_search)
                   1140:             func = 6;
                   1141:         else if (d_list[i].d_func == ring_teleport)
                   1142:             func = 7;
                   1143:         else if (d_list[i].d_func == fumble)
                   1144:             func = 8;
                   1145:         else if (d_list[i].d_func == strangle)
                   1146:             func = 9;
                   1147:         else if (d_list[i].d_func == unconfuse)
                   1148:             func = 10;
                   1149:         else if (d_list[i].d_func == swander)
                   1150:             func = 11;
                   1151:         else if (d_list[i].d_func == spell_recovery)
                   1152:             func = 12;
                   1153:         else if (d_list[i].d_func == chant_recovery)
                   1154:             func = 13;
                   1155:         else if (d_list[i].d_func == prayer_recovery)
                   1156:             func = 14;
                   1157:         else if (d_list[i].d_func == cure_disease)
                   1158:             func = 15;
                   1159:         else if (d_list[i].d_func == unstink)
                   1160:             func = 16;
                   1161:         else if (d_list[i].d_func == res_strength)
                   1162:             func = 17;
                   1163:         else if (d_list[i].d_func == undance)
                   1164:             func = 18;
                   1165:         else if (d_list[i].d_func == suffocate)
                   1166:             func = 19;
                   1167:         else if (d_list[i].d_func == wghtchk)
                   1168:             func = 20;
                   1169:         else if (d_list[i].d_func == dust_appear)
                   1170:             func = 21;
                   1171:         else if (d_list[i].d_func == unchoke)
                   1172:             func = 22;
                   1173:         else if (d_list[i].d_func == sight)
                   1174:             func = 23;
                   1175:         else if (d_list[i].d_func == changeclass)
                   1176:             func = 24;
                   1177:         else if (d_list[i].d_func == cloak_charge)
                   1178:             func = 25;
                   1179:         else if (d_list[i].d_func == quill_charge)
                   1180:             func = 26;
                   1181:         else if (d_list[i].d_func == nohaste)
                   1182:             func = 27;
                   1183:         else if (d_list[i].d_func == noslow)
                   1184:             func = 28;
                   1185:         else if (d_list[i].d_func == unclrhead)
                   1186:             func = 29;
                   1187:         else if (d_list[i].d_func == unsee)
                   1188:             func = 30;
                   1189:         else if (d_list[i].d_func == unphase)
                   1190:             func = 31;
                   1191:         else if (d_list[i].d_func == land)
                   1192:             func = 32;
                   1193:         else if (d_list[i].d_func == appear)
                   1194:             func = 33;
                   1195:         else if (d_list[i].d_func == unskill)
                   1196:             func = 34;
                   1197:         else if (d_list[i].d_func == nofire)
                   1198:             func = 35;
                   1199:         else if (d_list[i].d_func == nocold)
                   1200:             func = 36;
                   1201:         else if (d_list[i].d_func == nobolt)
                   1202:             func = 37;
                   1203:         else if (d_list[i].d_func == alchemy)
                   1204:             func = 38;
                   1205:         else if (d_list[i].d_func == NULL)
                   1206:             func = 0;
                   1207:         else
                   1208:             func = -1;
                   1209:
                   1210:         rs_write_int(savef, d_list[i].d_type);
                   1211:         rs_write_int(savef, func);
                   1212:
                   1213:         if (d_list[i].d_func == doctor)
                   1214:            rs_write_int(savef, 1);
                   1215:         else if (d_list[i].d_func == eat_gold)
                   1216:         {
                   1217:             int index;
                   1218:             index = find_list_ptr(player.t_pack,d_list[i].d_arg.vp);
                   1219:             rs_write_int(savef,index);
                   1220:         }
                   1221:         else if (d_list[i].d_func == changeclass)
                   1222:         {
                   1223:             rs_write_int(savef, d_list[i].d_arg.i);
                   1224:         }
                   1225:         else if (d_list[i].d_func == cloak_charge)
                   1226:         {
                   1227:             int index;
                   1228:             index = find_list_ptr(player.t_pack,d_list[i].d_arg.vp);
                   1229:             rs_write_int(savef,index);
                   1230:         }
                   1231:         else if (d_list[i].d_func == alchemy)
                   1232:         {
                   1233:             rs_write_int(savef, number_alchemy_jug((void *) d_list[i].d_arg.vp));
                   1234:         }
                   1235:         else
                   1236:             rs_write_int(savef, d_list[i].d_arg.i);
                   1237:
                   1238:                rs_write_int(savef, d_list[i].d_time);
                   1239:     }
                   1240:
                   1241:     return(WRITESTAT);
                   1242: }
                   1243:
                   1244: bool
                   1245: rs_read_daemons(FILE *inf, struct delayed_action *d_list, int count)
                   1246: {
                   1247:     int i = 0;
                   1248:     int func = 0;
                   1249:     int value = 0;
                   1250:     int id = 0;
                   1251:     int dummy = 0;
                   1252:
                   1253:     if (d_list == NULL)
                   1254:         printf("HELP THERE ARE NO DAEMONS\n");
                   1255:
                   1256:     if (rs_read_int(inf, &id) != 0)
                   1257:     {
                   1258:         if (id != RSXR_DAEMONS)
                   1259:         {
                   1260:             printf("Invalid id. %x != %x(RSXR_DAEMONS)\n",
                   1261:                 id,RSXR_DAEMONS);
                   1262:             printf("Sorry, invalid save game format");
                   1263:             format_error = TRUE;
                   1264:         }
                   1265:         else if (rs_read_int(inf, &value) != 0)
                   1266:         {
                   1267:             if (value > count)
                   1268:             {
                   1269:                 printf("Incorrect number of daemons in block. %d > %d.",
                   1270:                     value,count);
                   1271:                 printf("Sorry, invalid save game format");
                   1272:                 format_error = TRUE;
                   1273:             }
                   1274:             else
                   1275:             {
                   1276:                 for(i=0; i < value; i++)
                   1277:                 {
                   1278:                     func = 0;
                   1279:                     rs_read_int(inf, &d_list[i].d_type);
                   1280:                     rs_read_int(inf, &func);
                   1281:
                   1282:                     switch(func)
                   1283:                     {
                   1284:                         case  1: d_list[i].d_func = rollwand;
                   1285:                                  break;
                   1286:                         case  2: d_list[i].d_func = doctor;
                   1287:                                  break;
                   1288:                         case  3: d_list[i].d_func = stomach;
                   1289:                                  break;
                   1290:                         case  4: d_list[i].d_func = trap_look;
                   1291:                                  break;
                   1292:                         case  5: d_list[i].d_func = eat_gold;
                   1293:                                  break;
                   1294:                         case  6: d_list[i].d_func = ring_search;
                   1295:                                  break;
                   1296:                         case  7: d_list[i].d_func = ring_teleport;
                   1297:                                  break;
                   1298:                         case  8: d_list[i].d_func = fumble;
                   1299:                                  break;
                   1300:                         case  9: d_list[i].d_func = strangle;
                   1301:                                  break;
                   1302:                         case 10: d_list[i].d_func = unconfuse;
                   1303:                                  break;
                   1304:                         case 11: d_list[i].d_func = swander;
                   1305:                                  break;
                   1306:                         case 12: d_list[i].d_func = spell_recovery;
                   1307:                                  break;
                   1308:                         case 13: d_list[i].d_func = chant_recovery;
                   1309:                                  break;
                   1310:                         case 14: d_list[i].d_func = prayer_recovery;
                   1311:                                  break;
                   1312:                         case 15: d_list[i].d_func = cure_disease;
                   1313:                                  break;
                   1314:                         case 16: d_list[i].d_func = unstink;
                   1315:                                  break;
                   1316:                         case 17: d_list[i].d_func = res_strength;
                   1317:                                  break;
                   1318:                         case 18: d_list[i].d_func = undance;
                   1319:                                  break;
                   1320:                         case 19: d_list[i].d_func = suffocate;
                   1321:                                  break;
                   1322:                         case 20: d_list[i].d_func = wghtchk;
                   1323:                                  break;
                   1324:                         case 21: d_list[i].d_func = dust_appear;
                   1325:                                  break;
                   1326:                         case 22: d_list[i].d_func = unchoke;
                   1327:                                  break;
                   1328:                         case 23: d_list[i].d_func = sight;
                   1329:                                  break;
                   1330:                         case 24: d_list[i].d_func = changeclass;
                   1331:                                  break;
                   1332:                         case 25: d_list[i].d_func = cloak_charge;
                   1333:                                  break;
                   1334:                         case 26: d_list[i].d_func = quill_charge;
                   1335:                                  break;
                   1336:                         case 27: d_list[i].d_func = nohaste;
                   1337:                                  break;
                   1338:                         case 28: d_list[i].d_func = noslow;
                   1339:                                  break;
                   1340:                         case 29: d_list[i].d_func = unclrhead;
                   1341:                                  break;
                   1342:                         case 30: d_list[i].d_func = unsee;
                   1343:                                  break;
                   1344:                         case 31: d_list[i].d_func = unphase;
                   1345:                                  break;
                   1346:                         case 32: d_list[i].d_func = land;
                   1347:                                  break;
                   1348:                         case 33: d_list[i].d_func = appear;
                   1349:                                  break;
                   1350:                         case 34: d_list[i].d_func = unskill;
                   1351:                                  break;
                   1352:                         case 35: d_list[i].d_func = nofire;
                   1353:                                  break;
                   1354:                         case 36: d_list[i].d_func = nocold;
                   1355:                                  break;
                   1356:                         case 37: d_list[i].d_func = nobolt;
                   1357:                                  break;
                   1358:                         case 38: d_list[i].d_func = alchemy;
                   1359:                                  break;
                   1360:                                                case 0:
                   1361:                                                case -1:
                   1362:                         default: d_list[i].d_func = NULL;
                   1363:                                  break;
                   1364:                     }
                   1365:
                   1366:                     if (d_list[i].d_func == doctor)
                   1367:                     {
                   1368:                         rs_read_int(inf, &dummy);
                   1369:                         d_list[i].d_arg.vp = (void *)&player;
                   1370:                     }
                   1371:                     else if (d_list[i].d_func == eat_gold)
                   1372:                     {
                   1373:                         rs_read_int(inf, &dummy);
                   1374:                         d_list[i].d_arg.vp = get_list_item(player.t_pack,dummy);
                   1375:                         if (d_list[i].d_arg.vp == NULL)
                   1376:                             d_list[i].d_type = 0;
                   1377:                     }
                   1378:                     else if (d_list[i].d_func == changeclass)
                   1379:                     {
                   1380:                         rs_read_int(inf, &d_list[i].d_arg.i);
                   1381:                     }
                   1382:                     else if (d_list[i].d_func == cloak_charge)
                   1383:                     {
                   1384:                         rs_read_int(inf, &dummy);
                   1385:                         d_list[i].d_arg.vp = get_list_item(player.t_pack,dummy);
                   1386:                         if (d_list[i].d_arg.vp == NULL)
                   1387:                             d_list[i].d_type = 0;
                   1388:                     }
                   1389:                     else if (d_list[i].d_func == alchemy)
                   1390:                     {
                   1391:                        rs_read_int(inf, &dummy);
                   1392:                         d_list[i].d_arg.vp = (void *) find_alchemy_jug(dummy);
                   1393:                        if (d_list[i].d_arg.vp == NULL)
                   1394:                            d_list[i].d_type = 0;
                   1395:                     }
                   1396:                     else
                   1397:                         rs_read_int(inf, &d_list[i].d_arg.i);
                   1398:
                   1399:                     rs_read_int(inf, &d_list[i].d_time);
                   1400:
                   1401:                                        if (d_list[i].d_func == NULL)
                   1402:                                        {
                   1403:                                                d_list[i].d_time = 0;
                   1404:                                                d_list[i].d_arg.vp = NULL;
                   1405:                                                d_list[i].d_type = 0;
                   1406:                                        }
                   1407:
                   1408:                 }
                   1409:             }
                   1410:         }
                   1411:     }
                   1412:
                   1413:     return(READSTAT);
                   1414: }
                   1415:
                   1416: bool
                   1417: rs_write_rooms(FILE *savef, struct room r[], int count)
                   1418: {
                   1419:     int n = 0,i = -1;
                   1420:     struct linked_list *l;
                   1421:
                   1422:     DBG(("Rooms\n"));
                   1423:     rs_write_int(savef, RSXR_ROOMS);
                   1424:     rs_write_int(savef, count);
                   1425:
                   1426:     for(n=0; n<count; n++)
                   1427:     {
                   1428:         rs_write_coord(savef, &r[n].r_pos);
                   1429:         rs_write_coord(savef, &r[n].r_max);
                   1430:         rs_write_long(savef, r[n].r_flags);
                   1431:         rs_write_coord_list(savef, r[n].r_exit);
                   1432:
                   1433:         l = r[n].r_fires;
                   1434:         i = list_size(l);
                   1435:
                   1436:         rs_write_int(savef, i);
                   1437:
                   1438:         if (i >0)
                   1439:             while (l != NULL)
                   1440:             {
                   1441:                 i = find_list_ptr(mlist,l->l_data);
                   1442:                 rs_write_int(savef,i);
                   1443:                 l = l->l_next;
                   1444:             }
                   1445:     }
                   1446:     return(WRITESTAT);
                   1447: }
                   1448:
                   1449: bool
                   1450: rs_read_rooms(FILE *inf, struct room *r, int count)
                   1451: {
                   1452:     int value = 0, n = 0, i = 0, index = 0, id = 0;
                   1453:     struct linked_list *fires=NULL, *item = NULL;
                   1454:
                   1455:     if (rs_read_int(inf,&id) != 0)
                   1456:     {
                   1457:         if (id != RSXR_ROOMS)
                   1458:         {
                   1459:             printf("Invalid id. %x != %x(RSXR_ROOMS)\n",
                   1460:                 id,RSXR_ROOMS);
                   1461:             printf("Sorry, invalid save game format");
                   1462:             format_error = TRUE;
                   1463:         }
                   1464:         else if (rs_read_int(inf,&value) != 0)
                   1465:         {
                   1466:             if (value != count)
                   1467:             {
                   1468:                 printf("Incorrect number of rooms in block. %d > %d.",
                   1469:                     value,count);
                   1470:                 printf("Sorry, invalid save game format");
                   1471:                 format_error = TRUE;
                   1472:             }
                   1473:             else
                   1474:             {
                   1475:                 for(n=0; n<value; n++)
                   1476:                 {
                   1477:                     rs_read_coord(inf,&r[n].r_pos);
                   1478:                     rs_read_coord(inf,&r[n].r_max);
                   1479:                     rs_read_long(inf,&r[n].r_flags);
                   1480:                     rs_read_coord_list(inf, &r[n].r_exit);
                   1481:
                   1482:                     rs_read_int(inf, &i);
                   1483:                     fires = NULL;
                   1484:                     while (i>0)
                   1485:                     {
                   1486:                         rs_read_int(inf,&index);
                   1487:
                   1488:                         if (index >= 0)
                   1489:                         {
                   1490:                             void *data;
                   1491:                             data = get_list_item(mlist,index);
                   1492:                             item = creat_item();
                   1493:                             item->l_data = data;
                   1494:                             if (fires == NULL)
                   1495:                                 fires = item;
                   1496:                             else
                   1497:                                 attach(fires,item);
                   1498:                         }
                   1499:                         i--;
                   1500:                     }
                   1501:                     r[n].r_fires=fires;
                   1502:                 }
                   1503:             }
                   1504:         }
                   1505:     }
                   1506:
                   1507:     return(READSTAT);
                   1508: }
                   1509:
                   1510: bool
                   1511: rs_write_object(FILE *savef, struct object *o)
                   1512: {
                   1513:     rs_write_int(savef, RSXR_OBJECT);
                   1514:     rs_write_int(savef, o->o_type);
                   1515:     rs_write_coord(savef, &o->o_pos);
                   1516:     rs_write_char(savef, o->o_launch);
                   1517:     rs_write(savef, o->o_damage, sizeof(o->o_damage));
                   1518:     rs_write(savef, o->o_hurldmg, sizeof(o->o_hurldmg));
                   1519:     rs_write_int(savef, o->o_count);
                   1520:     rs_write_int(savef, o->o_which);
                   1521:     rs_write_int(savef, o->o_hplus);
                   1522:     rs_write_int(savef, o->o_dplus);
                   1523:     rs_write_int(savef, o->o_ac);
                   1524:     rs_write_long(savef, o->o_flags);
                   1525:     rs_write_int(savef, o->o_group);
                   1526:     rs_write_int(savef, o->o_weight);
                   1527:     rs_write(savef, o->o_mark, MARKLEN);
                   1528:
                   1529:     DBG(("Object\n"));
                   1530:     DBG(("    SaveID  : %X\n",RSXR_OBJECT));
                   1531:     DBG(("    Type    : %d\n",o->o_type));
                   1532:     DBG(("    Pos     : %d %d\n",o->o_pos.x,o->o_pos.y));
                   1533:     DBG(("    Launch  : %c\n",o->o_launch));
                   1534:     DBG(("    Damage  : %s\n",o->o_damage));
                   1535:     DBG(("    Hurl    : %s\n",o->o_hurldmg));
                   1536:     DBG(("    Count   : %d\n",o->o_count));
                   1537:     DBG(("    Which   : %d\n",o->o_which));
                   1538:     DBG(("    HPlus   : %d\n",o->o_hplus));
                   1539:     DBG(("    DPlus   : %d\n",o->o_dplus));
                   1540:     DBG(("    AC      : %d\n",o->o_ac));
                   1541:     DBG(("    Flags   : %X\n",o->o_flags));
                   1542:     DBG(("    Group   : %d\n",o->o_group));
                   1543:     DBG(("    Weight  : %d\n",o->o_weight));
                   1544:     DBG(("    Mark    : %s\n",o->o_mark));
                   1545:     if (o->contents == NULL)
                   1546:     {
                   1547:         DBG(("    Contents: None\n"));
                   1548:     }
                   1549:     else
                   1550:     {
                   1551:         DBG(("    CONTENTS\n"));
                   1552:     }
                   1553:
                   1554:     rs_write_object_list(savef, o->contents);
                   1555:
                   1556:     if (o->contents != NULL)
                   1557:         DBG(("    END_CONTENTS\n"));
                   1558:
                   1559:     return(WRITESTAT);
                   1560: }
                   1561:
                   1562: bool
                   1563: rs_read_object(FILE *inf, struct object *o)
                   1564: {
                   1565:     int id;
                   1566:
                   1567:     if (rs_read_int(inf, &id) != 0)
                   1568:     {
                   1569:         if (id != RSXR_OBJECT)
                   1570:         {
                   1571:             printf("Invalid id. %x != %x(RSXR_OBJECT)\n", id,RSXR_OBJECT);
                   1572:             printf("Sorry, invalid save game format");
                   1573:             format_error = TRUE;
                   1574:         }
                   1575:         else
                   1576:         {
                   1577:             rs_read_int(inf, &o->o_type);
                   1578:             rs_read_coord(inf, &o->o_pos);
                   1579:             rs_read_char(inf, &o->o_launch);
                   1580:             rs_read(inf, o->o_damage,sizeof(o->o_damage));
                   1581:             rs_read(inf, o->o_hurldmg,sizeof(o->o_hurldmg));
                   1582:             rs_read_int(inf, &o->o_count);
                   1583:             rs_read_int(inf, &o->o_which);
                   1584:             rs_read_int(inf, &o->o_hplus);
                   1585:             rs_read_int(inf, &o->o_dplus);
                   1586:             rs_read_int(inf,&o->o_ac);
                   1587:             rs_read_long(inf,&o->o_flags);
                   1588:             rs_read_int(inf,&o->o_group);
                   1589:             rs_read_int(inf, &o->o_weight);
                   1590:             rs_read(inf, o->o_mark, MARKLEN);
                   1591:             rs_read_object_list(inf,&o->contents);
                   1592:
                   1593:         }
                   1594:     }
                   1595:
                   1596:     return(READSTAT);
                   1597: }
                   1598:
                   1599: bool
                   1600: rs_write_stats(FILE *savef, struct stats *s)
                   1601: {
                   1602:     DBG(("Stats\n"));
                   1603:     rs_write_int(savef, RSXR_STATS);
                   1604:
                   1605:     rs_write_short(savef, s->s_str);
                   1606:     rs_write_short(savef, s->s_intel);
                   1607:     rs_write_short(savef, s->s_wisdom);
                   1608:     rs_write_short(savef, s->s_dext);
                   1609:     rs_write_short(savef, s->s_const);
                   1610:     rs_write_short(savef, s->s_charisma);
                   1611:     rs_write_ulong(savef, s->s_exp);
                   1612:     rs_write_int(savef, s->s_lvladj);
                   1613:     rs_write_int(savef, s->s_lvl);
                   1614:     rs_write_int(savef, s->s_arm);
                   1615:     rs_write_int(savef, s->s_hpt);
                   1616:     rs_write_int(savef, s->s_pack);
                   1617:     rs_write_int(savef, s->s_carry);
                   1618:     rs_write(savef, s->s_dmg, sizeof(s->s_dmg));
                   1619:
                   1620:     return(WRITESTAT);
                   1621: }
                   1622:
                   1623: bool
                   1624: rs_read_stats(FILE *inf, struct stats *s)
                   1625: {
                   1626:     int id;
                   1627:
                   1628:     if (rs_read_int(inf, &id) != 0)
                   1629:     {
                   1630:         if (id != RSXR_STATS)
                   1631:         {
                   1632:             printf("Invalid id. %x != %x(RSXR_STATS)\n", id,RSXR_STATS);
                   1633:             printf("Sorry, invalid save game format");
                   1634:             format_error = TRUE;
                   1635:         }
                   1636:         else
                   1637:         {
                   1638:             rs_read_short(inf,&s->s_str);
                   1639:             rs_read_short(inf,&s->s_intel);
                   1640:             rs_read_short(inf,&s->s_wisdom);
                   1641:             rs_read_short(inf,&s->s_dext);
                   1642:             rs_read_short(inf,&s->s_const);
                   1643:             rs_read_short(inf,&s->s_charisma);
                   1644:             rs_read_ulong(inf,&s->s_exp);
                   1645:             rs_read_int(inf,&s->s_lvladj);
                   1646:             rs_read_int(inf,&s->s_lvl);
                   1647:             rs_read_int(inf,&s->s_arm);
                   1648:             rs_read_int(inf,&s->s_hpt);
                   1649:             rs_read_int(inf,&s->s_pack);
                   1650:             rs_read_int(inf,&s->s_carry);
                   1651:             rs_read(inf,s->s_dmg,sizeof(s->s_dmg));
                   1652:         }
                   1653:     }
                   1654:
                   1655:     return(READSTAT);
                   1656: }
                   1657:
                   1658: bool
                   1659: rs_write_mstats(FILE *savef, struct mstats *s)
                   1660: {
                   1661:     DBG(("M-Stats\n"));
                   1662:     rs_write_int(savef, RSXR_STATS);
                   1663:     rs_write_short(savef, s->ms_str);
                   1664:     /*printf("    Strength: %d\n",s->ms_str);*/
                   1665:     rs_write_short(savef, s->ms_dex);
                   1666:     rs_write_short(savef, s->ms_move);
                   1667:     rs_write_ulong(savef, s->ms_exp);
                   1668:     rs_write_short(savef, s->ms_lvl);
                   1669:     rs_write_short(savef, s->ms_arm);
                   1670:     rs_write(savef, s->ms_hpt, sizeof(s->ms_hpt));
                   1671:     rs_write(savef, s->ms_dmg, sizeof(s->ms_dmg));
                   1672:     /*printf("    Damage: %s\n",s->ms_dmg);*/
                   1673:
                   1674:     return(WRITESTAT);
                   1675: }
                   1676:
                   1677: bool
                   1678: rs_read_mstats(FILE *inf, struct mstats *s)
                   1679: {
                   1680:     int id;
                   1681:
                   1682:     if (rs_read_int(inf, &id) != 0)
                   1683:     {
                   1684:         if (id != RSXR_STATS)
                   1685:         {
                   1686:             printf("Invalid id. %x != %x(RSXR_STATS)\n", id,RSXR_STATS);
                   1687:             printf("Sorry, invalid save game format");
                   1688:             format_error = TRUE;
                   1689:         }
                   1690:         else
                   1691:         {
                   1692:             rs_read_short(inf,&s->ms_str);
                   1693:             /*printf("    Strength: %d\n",s->ms_str);*/
                   1694:             rs_read_short(inf,&s->ms_dex);
                   1695:             /*printf("    Dexterity: %d\n",s->ms_dex);*/
                   1696:             rs_read_short(inf,&s->ms_move);
                   1697:             /*printf("    Moves: %d\n",s->ms_move);*/
                   1698:             rs_read_ulong(inf,&s->ms_exp);
                   1699:             /*printf("    Experience: %d\n",s->ms_exp);*/
                   1700:             rs_read_short(inf,&s->ms_lvl);
                   1701:             /*printf("    Level: %d\n",s->ms_lvl);*/
                   1702:             rs_read_short(inf,&s->ms_arm);
                   1703:             /*printf("    Armor: %d\n",s->ms_arm);*/
                   1704:             rs_read(inf,s->ms_hpt,sizeof(s->ms_hpt));
                   1705:             /*printf("    HP: %s\n",s->ms_hpt);*/
                   1706:             rs_read(inf,s->ms_dmg,sizeof(s->ms_dmg));
                   1707:             /*printf("    Damage: %s\n",s->ms_dmg);*/
                   1708:         }
                   1709:     }
                   1710:
                   1711:     return(READSTAT);
                   1712: }
                   1713:
                   1714: bool
                   1715: rs_write_init_weps(FILE *savef, struct init_weps *w, int count)
                   1716: {
                   1717:     int i;
                   1718:
                   1719:     DBG(("Init-Weps\n"));
                   1720:     rs_write_int(savef, RSXR_IWEAPS);
                   1721:     rs_write_int(savef, count);
                   1722:
                   1723:     for(i=0;i<count;i++)
                   1724:     {
                   1725:         rs_write(savef, w[i].w_name, sizeof(w[i].w_name));
                   1726:         rs_write(savef, w[i].w_dam, sizeof(w[i].w_dam));
                   1727:         rs_write(savef, w[i].w_hrl, sizeof(w[i].w_hrl));
                   1728:         rs_write_char(savef, w[i].w_launch);
                   1729:         rs_write_int(savef, w[i].w_flags);
                   1730:         rs_write_int(savef, w[i].w_rate);
                   1731:         rs_write_int(savef, w[i].w_wght);
                   1732:         rs_write_int(savef, w[i].w_worth);
                   1733:     }
                   1734:     return(WRITESTAT);
                   1735: }
                   1736:
                   1737: bool
                   1738: rs_read_init_weps(FILE *inf, struct init_weps *w,int count)
                   1739: {
                   1740:     int id,value,i;
                   1741:
                   1742:     rs_read_int(inf, &id);
                   1743:     rs_read_int(inf, &value);
                   1744:
                   1745:     if (value != count)
                   1746:     {
                   1747:         printf("Incorrect number of init_weps in block. %d != %d.",
                   1748:                     value,count);
                   1749:         printf("Sorry, invalid save game format");
                   1750:         format_error = TRUE;
                   1751:     }
                   1752:     else for (i = 0; i < count; i++)
                   1753:     {
                   1754:         rs_read(inf, w[i].w_name, sizeof(w[i].w_name));
                   1755:         rs_read(inf, w[i].w_dam, sizeof(w[i].w_dam));
                   1756:         rs_read(inf, w[i].w_hrl, sizeof(w[i].w_hrl));
                   1757:         rs_read_char(inf, &w[i].w_launch);
                   1758:         rs_read_int(inf, &w[i].w_flags);
                   1759:         rs_read_int(inf, &w[i].w_rate);
                   1760:         rs_read_int(inf, &w[i].w_wght);
                   1761:         rs_read_int(inf, &w[i].w_worth);
                   1762:     }
                   1763:     return(READSTAT);
                   1764: }
                   1765:
                   1766: bool
                   1767: rs_write_init_armor(FILE *savef, struct init_armor *a, int count)
                   1768: {
                   1769:     int i;
                   1770:     DBG(("Init-Armor\n"));
                   1771:     rs_write_int(savef, RSXR_IARMOR);
                   1772:     rs_write_int(savef, count);
                   1773:     for(i=0;i<count;i++)
                   1774:     {
                   1775:         rs_write(savef, a[i].a_name, sizeof(a[i].a_name));
                   1776:         rs_write_int(savef, a[i].a_prob);
                   1777:         rs_write_int(savef, a[i].a_class);
                   1778:         rs_write_int(savef, a[i].a_worth);
                   1779:         rs_write_int(savef, a[i].a_wght);
                   1780:     }
                   1781:     return(WRITESTAT);
                   1782: }
                   1783:
                   1784: bool
                   1785: rs_read_init_armor(FILE *inf, struct init_armor *a,int count)
                   1786: {
                   1787:     int id,value,i;
                   1788:
                   1789:     rs_read_int(inf, &id);
                   1790:     rs_read_int(inf, &value);
                   1791:
                   1792:     for(i=0;i<count;i++)
                   1793:     {
                   1794:         rs_read(inf, a[i].a_name, sizeof(a[i].a_name));
                   1795:         rs_read_int(inf, &a[i].a_prob);
                   1796:         rs_read_int(inf, &a[i].a_class);
                   1797:         rs_read_int(inf, &a[i].a_worth);
                   1798:         rs_read_int(inf, &a[i].a_wght);
                   1799:     }
                   1800:
                   1801:     return(READSTAT);
                   1802: }
                   1803:
                   1804: bool
                   1805: rs_write_spells(FILE *savef, struct spells *s, int count)
                   1806: {
                   1807:     int i;
                   1808:     DBG(("Spells\n"));
                   1809:     rs_write_int(savef, RSXR_SPELLS);
                   1810:     rs_write_int(savef, count);
                   1811:     for(i=0;i<count;i++)
                   1812:     {
                   1813:         rs_write_short(savef, s[i].s_which);
                   1814:         rs_write_short(savef, s[i].s_cost);
                   1815:         rs_write_short(savef, s[i].s_type);
                   1816:         rs_write_int(savef, s[i].s_flag);
                   1817:     }
                   1818:     return(WRITESTAT);
                   1819: }
                   1820:
                   1821: bool
                   1822: rs_read_spells(FILE *inf, struct spells *s,int count)
                   1823: {
                   1824:     int id,value,i;
                   1825:
                   1826:     rs_read_int(inf, &id);
                   1827:     rs_read_int(inf, &value);
                   1828:
                   1829:     for(i=0;i<count;i++)
                   1830:     {
                   1831:         rs_read_short(inf, &s[i].s_which);
                   1832:         rs_read_short(inf, &s[i].s_cost);
                   1833:         rs_read_short(inf, &s[i].s_type);
                   1834:         rs_read_int(inf, &s[i].s_flag);
                   1835:     }
                   1836:     return(READSTAT);
                   1837: }
                   1838:
                   1839: bool
                   1840: rs_write_item_list(FILE *savef, struct item_list *i)
                   1841: {
                   1842:     DBG(("Item List\n"));
                   1843:     rs_write_int(savef, RSXR_ILIST);
                   1844:     rs_write_char(savef, i->item_ch);
                   1845:     rs_write(savef, i->item_desc, sizeof(i->item_desc));
                   1846:     return(WRITESTAT);
                   1847: }
                   1848:
                   1849: bool
                   1850: rs_read_item_list(FILE *inf, struct item_list *i)
                   1851: {
                   1852:     int id;
                   1853:
                   1854:     rs_read_int(inf, &id);
                   1855:
                   1856:     rs_read_uchar(inf, &i->item_ch);
                   1857:     rs_read(inf, i->item_desc,sizeof(i->item_desc));
                   1858:     return(READSTAT);
                   1859: }
                   1860:
                   1861: bool
                   1862: rs_write_h_list(FILE *savef, struct h_list *h)
                   1863: {
                   1864:     DBG(("H List\n"));
                   1865:     rs_write_int(savef, RSXR_HLIST);
                   1866:     rs_write_char(savef, h->h_ch);
                   1867:     rs_write(savef, h->h_desc, sizeof(h->h_desc));
                   1868:     return(WRITESTAT);
                   1869: }
                   1870:
                   1871: bool
                   1872: rs_read_h_list(FILE *inf, struct h_list *h)
                   1873: {
                   1874:     int id;
                   1875:
                   1876:     rs_read_int(inf, &id);
                   1877:
                   1878:     rs_read_char(inf, &h->h_ch);
                   1879:     rs_read(inf, h->h_desc,sizeof(h->h_desc));
                   1880:     return(READSTAT);
                   1881: }
                   1882:
                   1883: bool
                   1884: rs_write_death_types(FILE *savef, struct death_type *d,int count)
                   1885: {
                   1886:     int i;
                   1887:
                   1888:     DBG(("Death Types\n"));
                   1889:     rs_write_int(savef, RSXR_DEATHTYPE);
                   1890:     rs_write_int(savef, count);
                   1891:
                   1892:     for(i=0; i < count; i++)
                   1893:     {
                   1894:         rs_write_int(savef, d[i].reason);
                   1895:         rs_write(savef, d[i].name, sizeof(d[i].name));
                   1896:     }
                   1897:     return(WRITESTAT);
                   1898: }
                   1899:
                   1900: bool
                   1901: rs_read_death_types(FILE *inf, struct death_type *d, int count)
                   1902: {
                   1903:     int id,value,i;
                   1904:
                   1905:     rs_read_int(inf, &id);
                   1906:     rs_read_int(inf, &value);
                   1907:     if (value != count)
                   1908:     {
                   1909:         printf("Incorrect number of death_types in block. %d > %d.",
                   1910:                value,count);
                   1911:         printf("Sorry, invalid save game format");
                   1912:         format_error = TRUE;
                   1913:     }
                   1914:     else for(i=0;i < count;i++)
                   1915:     {
                   1916:         rs_read_int(inf, &d[i].reason);
                   1917:         rs_read(inf, d[i].name,sizeof(d[i].name));
                   1918:     }
                   1919:     return(READSTAT);
                   1920: }
                   1921:
                   1922: bool
                   1923: rs_write_character_types(FILE *savef, struct character_types *c, int count)
                   1924: {
                   1925:     int i;
                   1926:
                   1927:     DBG(("Character Types\n"));
                   1928:     rs_write_int(savef, RSXR_CTYPES);
                   1929:     rs_write_int(savef,count);
                   1930:
                   1931:     for(i=0;i<count;i++)
                   1932:     {
                   1933:         rs_write(savef, c[i].name, sizeof(c[i].name));
                   1934:         rs_write_long(savef, c[i].start_exp);
                   1935:         rs_write_long(savef, c[i].cap);
                   1936:         rs_write_int(savef, c[i].hit_pts);
                   1937:         rs_write_int(savef, c[i].base);
                   1938:         rs_write_int(savef, c[i].max_lvl);
                   1939:         rs_write_int(savef, c[i].factor);
                   1940:         rs_write_int(savef, c[i].offset);
                   1941:         rs_write_int(savef, c[i].range);
                   1942:     }
                   1943:     return(WRITESTAT);
                   1944: }
                   1945:
                   1946: bool
                   1947: rs_read_character_types(FILE *inf, struct character_types *c,int count)
                   1948: {
                   1949:     int id,value,i;
                   1950:
                   1951:     rs_read_int(inf, &id);
                   1952:     rs_read_int(inf, &value);
                   1953:
                   1954:     if (value != count)
                   1955:     {
                   1956:         printf("Incorrect number of character types in block. %d > %d.",
                   1957:                value,count);
                   1958:         printf("Sorry, invalid save game format");
                   1959:         format_error = TRUE;
                   1960:     }
                   1961:     else for (i = 0; i < count; i++)
                   1962:     {
                   1963:         rs_read(inf, c[i].name,sizeof(c[i].name));
                   1964:         rs_read_long(inf, &c[i].start_exp);
                   1965:         rs_read_long(inf, &c[i].cap);
                   1966:         rs_read_int(inf, &c[i].hit_pts);
                   1967:         rs_read_int(inf, &c[i].base);
                   1968:         rs_read_int(inf, &c[i].max_lvl);
                   1969:         rs_read_int(inf, &c[i].factor);
                   1970:         rs_read_int(inf, &c[i].offset);
                   1971:         rs_read_int(inf, &c[i].range);
                   1972:     }
                   1973:     return(READSTAT);
                   1974: }
                   1975:
                   1976: bool
                   1977: rs_write_traps(FILE *savef, struct trap *trap,int count)
                   1978: {
                   1979:     int n;
                   1980:
                   1981:     DBG(("Traps\n"));
                   1982:     rs_write_int(savef, RSXR_TRAP);
                   1983:     rs_write_int(savef, count);
                   1984:
                   1985:     for(n=0; n<count; n++)
                   1986:     {
                   1987:         rs_write_char(savef, trap[n].tr_type);
                   1988:         rs_write_char(savef, trap[n].tr_show);
                   1989:         rs_write_coord(savef, &trap[n].tr_pos);
                   1990:         rs_write_long(savef, trap[n].tr_flags);
                   1991:     }
                   1992:     return(WRITESTAT);
                   1993: }
                   1994:
                   1995: bool
                   1996: rs_read_traps(FILE *inf, struct trap *trap, int count)
                   1997: {
                   1998:     int id = 0, value = 0, n = 0;
                   1999:
                   2000:     if (rs_read_int(inf,&id) != 0)
                   2001:     {
                   2002:         if (id != RSXR_TRAP)
                   2003:         {
                   2004:             printf("Invalid id. %x != %x(RSXR_TRAP)\n",
                   2005:                 id,RSXR_TRAP);
                   2006:             printf("Sorry, invalid save game format");
                   2007:             format_error = TRUE;
                   2008:         }
                   2009:         else if (rs_read_int(inf,&value) != 0)
                   2010:         {
                   2011:             if (value != count)
                   2012:             {
                   2013:                 printf("Incorrect number of traps in block. %d > %d.",
                   2014:                     value,count);
                   2015:                 printf("Sorry, invalid save game format\n");
                   2016:                 format_error = TRUE;
                   2017:             }
                   2018:             else
                   2019:             {
                   2020:                 for(n=0;n<value;n++)
                   2021:                 {
                   2022:                     rs_read_uchar(inf,&trap[n].tr_type);
                   2023:                     rs_read_uchar(inf,&trap[n].tr_show);
                   2024:                     rs_read_coord(inf,&trap[n].tr_pos);
                   2025:                     rs_read_long(inf,&trap[n].tr_flags);
                   2026:                 }
                   2027:             }
                   2028:         }
                   2029:         else
                   2030:             format_error = TRUE;
                   2031:     }
                   2032:
                   2033:     return(READSTAT);
                   2034: }
                   2035:
                   2036: bool
                   2037: rs_write_monsters(FILE * savef, struct monster * m, int count)
                   2038: {
                   2039:     int n;
                   2040:
                   2041:     DBG(("Monsters\n"));
                   2042:     rs_write_int(savef, RSXR_MONSTERS);
                   2043:     rs_write_int(savef, count);
                   2044:
                   2045:     for(n=0;n<count;n++)
                   2046:     {
                   2047:         rs_write(savef, m[n].m_name, sizeof(m[n].m_name));
                   2048:         /*printf("Monster: %s/%d/%d\n",m[n].m_name,sizeof(m[n].m_name),strlen(m[n].m_name));*/
                   2049:         rs_write_short(savef, m[n].m_carry);
                   2050:         rs_write_boolean(savef, m[n].m_normal);
                   2051:         rs_write_boolean(savef, m[n].m_wander);
                   2052:         rs_write_char(savef, m[n].m_appear);
                   2053:         rs_write(savef, m[n].m_intel,sizeof(m[n].m_intel));
                   2054:         rs_write_longs(savef, m[n].m_flags, MAXFLAGS);
                   2055:         rs_write(savef, m[n].m_typesum,sizeof(m[n].m_typesum));
                   2056:         rs_write_short(savef, m[n].m_numsum);
                   2057:         rs_write_short(savef, m[n].m_add_exp);
                   2058:
                   2059:         rs_write_mstats(savef, &m[n].m_stats);
                   2060:     }
                   2061:
                   2062:     return(WRITESTAT);
                   2063: }
                   2064:
                   2065: bool
                   2066: rs_read_monsters(FILE *inf, struct monster *m, int count)
                   2067: {
                   2068:     int id = 0, value = 0, n = 0;
                   2069:     char buffer[1024];
                   2070:
                   2071:     if (rs_read_int(inf, &id) != 0)
                   2072:     {
                   2073:         if (id != RSXR_MONSTERS)
                   2074:         {
                   2075:             printf("Invalid id. %x != %x(RSXR_MONSTERS)\n",
                   2076:                 id,RSXR_MONSTERS);
                   2077:             printf("Sorry, invalid save game format");
                   2078:             format_error = TRUE;
                   2079:         }
                   2080:         else if (rs_read_int(inf, &value) != 0)
                   2081:         {
                   2082:             if (value != count)
                   2083:             {   printf("Incorrect number of monsters in block. %d != %d.",
                   2084:                     value,count);
                   2085:                 printf("Sorry, invalid save game format\n");
                   2086:                 format_error = TRUE;
                   2087:
                   2088:             }
                   2089:             else for(n=0;n<value;n++)
                   2090:             {
                   2091:                 rs_read(inf, buffer,sizeof(m[n].m_name));
                   2092:                 assert( strcmp(buffer,m[n].m_name) == 0);
                   2093:                 /*printf("Monster: %s\n",m[n].m_name);*/
                   2094:                 rs_read_short(inf, &m[n].m_carry);
                   2095:                 /*printf("    Carry: %d\n",m[n].m_carry); */
                   2096:                 rs_read_boolean(inf, &m[n].m_normal);
                   2097:                 /*printf("    Normal: %d\n",m[n].m_normal);*/
                   2098:                 rs_read_boolean(inf, &m[n].m_wander);
                   2099:                 /*printf("    Wander: %d\n",m[n].m_wander);*/
                   2100:                 rs_read_char(inf, &m[n].m_appear);
                   2101:                 /*printf("    Appears: %c\n",m[n].m_appear);*/
                   2102:                 rs_read(inf, m[n].m_intel,sizeof(m[n].m_intel));
                   2103:                 /*printf("    Intelligence: %s\n",m[n].m_intel);*/
                   2104:                 rs_read_longs(inf, m[n].m_flags, MAXFLAGS);
                   2105:                 /*printf("    Flags: %X\n",m[n].m_flags);*/
                   2106:                 rs_read(inf, m[n].m_typesum, sizeof(m[n].m_typesum));
                   2107:                 /*printf("    Summons: %s\n",m[n].m_typesum);*/
                   2108:                 rs_read_short(inf, &m[n].m_numsum);
                   2109:                 /*printf("    # Summons: %d\n",m[n].m_numsum);*/
                   2110:                 rs_read_short(inf, &m[n].m_add_exp);
                   2111:                 /*printf("    Experience: %d\n",m[n].m_add_exp);*/
                   2112:                 rs_read_mstats(inf, &m[n].m_stats);
                   2113:
                   2114:              }
                   2115:         }
                   2116:         else
                   2117:             format_error = TRUE;
                   2118:     }
                   2119:
                   2120:     return(READSTAT);
                   2121: }
                   2122:
                   2123: /*****************************************************************************/
                   2124:
                   2125: bool
                   2126: rs_write_coord_list(FILE *savef, struct linked_list *l)
                   2127: {
                   2128:     DBG(("Coordinate List\n"));
                   2129:     rs_write_int(savef, RSXR_COORDLIST);
                   2130:     rs_write_int(savef, list_size(l));
                   2131:
                   2132:     while (l != NULL)
                   2133:     {
                   2134:         rs_write_coord(savef, (coord *) l->l_data);
                   2135:         l = l->l_next;
                   2136:     }
                   2137:
                   2138:     return(WRITESTAT);
                   2139: }
                   2140:
                   2141: bool
                   2142: rs_read_coord_list(FILE *inf, struct linked_list **list)
                   2143: {
                   2144:     int id;
                   2145:     int i, cnt;
                   2146:     struct linked_list *l = NULL, *previous = NULL, *head = NULL;
                   2147:
                   2148:     if (rs_read_int(inf,&id) != 0)
                   2149:     {
                   2150:         if (id != RSXR_COORDLIST)
                   2151:         {
                   2152:             printf("Invalid id. %x != %x(RSXR_COORDLIST)\n",
                   2153:                 id,RSXR_COORDLIST);
                   2154:             printf("Sorry, invalid save game format");
                   2155:             format_error = TRUE;
                   2156:         }
                   2157:     else if (rs_read_int(inf,&cnt) != 0)
                   2158:         {
                   2159:             for (i = 0; i < cnt; i++)
                   2160:             {
                   2161:                 l = new_item(sizeof(coord));
                   2162:                 l->l_prev = previous;
                   2163:                 if (previous != NULL)
                   2164:                     previous->l_next = l;
                   2165:                 rs_read_coord(inf,(coord *) l->l_data);
                   2166:                 if (previous == NULL)
                   2167:                     head = l;
                   2168:                 previous = l;
                   2169:             }
                   2170:
                   2171:             if (l != NULL)
                   2172:                 l->l_next = NULL;
                   2173:
                   2174:             *list = head;
                   2175:         }
                   2176:         else
                   2177:             format_error = TRUE;
                   2178:     }
                   2179:     else
                   2180:         format_error = TRUE;
                   2181:
                   2182:     return(READSTAT);
                   2183: }
                   2184:
                   2185: bool
                   2186: rs_write_object_list(FILE *savef, struct linked_list *l)
                   2187: {
                   2188:     DBG(("Object List\n"));
                   2189:     rs_write_int(savef, RSXR_OBJECTLIST);
                   2190:     rs_write_int(savef, list_size(l));
                   2191:
                   2192:     while (l != NULL)
                   2193:     {
                   2194:         rs_write_object(savef, (struct object *) l->l_data);
                   2195:         l = l->l_next;
                   2196:     }
                   2197:
                   2198:     return(WRITESTAT);
                   2199: }
                   2200:
                   2201: bool
                   2202: rs_read_object_list(FILE *inf, struct linked_list **list)
                   2203: {
                   2204:     int id;
                   2205:     int i, cnt;
                   2206:     struct linked_list *l = NULL, *previous = NULL, *head = NULL;
                   2207:
                   2208:     if (rs_read_int(inf,&id) != 0)
                   2209:     {
                   2210:         if (rs_read_int(inf,&cnt) != 0)
                   2211:         {
                   2212:             for (i = 0; i < cnt; i++)
                   2213:             {
                   2214:                 l = new_item(sizeof(struct object));
                   2215:                 memset(l->l_data,0,sizeof(struct object));
                   2216:                 l->l_prev = previous;
                   2217:                 if (previous != NULL)
                   2218:                     previous->l_next = l;
                   2219:                 rs_read_object(inf,(struct object *) l->l_data);
                   2220:                 if (previous == NULL)
                   2221:                     head = l;
                   2222:                 previous = l;
                   2223:             }
                   2224:
                   2225:             if (l != NULL)
                   2226:                 l->l_next = NULL;
                   2227:
                   2228:             *list = head;
                   2229:         }
                   2230:         else
                   2231:             format_error = TRUE;
                   2232:     }
                   2233:     else
                   2234:         format_error = TRUE;
                   2235:
                   2236:
                   2237:     return(READSTAT);
                   2238: }
                   2239:
                   2240: int
                   2241: find_thing_coord(monlist, c)
                   2242: struct linked_list *monlist;
                   2243: coord *c;
                   2244: {
                   2245:     struct linked_list *mitem;
                   2246:     struct thing *tp;
                   2247:     int i = 0;
                   2248:
                   2249:     for(mitem = monlist; mitem != NULL; mitem = mitem->l_next)
                   2250:     {
                   2251:         tp = THINGPTR(mitem);
                   2252:         if (c == &tp->t_pos)
                   2253:             return(i);
                   2254:         i++;
                   2255:     }
                   2256:
                   2257:     return(-1);
                   2258: }
                   2259:
                   2260: int
                   2261: find_object_coord(objlist, c)
                   2262: struct linked_list *objlist;
                   2263: coord *c;
                   2264: {
                   2265:     struct linked_list *oitem;
                   2266:     struct object *obj;
                   2267:     int i = 0;
                   2268:
                   2269:     for(oitem = objlist; oitem != NULL; oitem = oitem->l_next)
                   2270:     {
                   2271:         obj = OBJPTR(oitem);
                   2272:         if (c == &obj->o_pos)
                   2273:             return(i);
                   2274:         i++;
                   2275:     }
                   2276:
                   2277:     return(-1);
                   2278: }
                   2279:
                   2280: bool
                   2281: rs_write_thing(FILE *savef, struct thing *t)
                   2282: {
                   2283:     int i = -1;
                   2284:
                   2285:     DBG(("Thing\n"));
                   2286:     rs_write_int(savef, RSXR_THING);
                   2287:     rs_write_boolean(savef,t->t_wasshot);
                   2288:     rs_write_char(savef, t->t_type);
                   2289:     rs_write_char(savef, t->t_disguise);
                   2290:     rs_write_char(savef, t->t_oldch);
                   2291:     rs_write_short(savef, t->t_ctype);
                   2292:     rs_write_short(savef, t->t_index);
                   2293:     rs_write_short(savef, t->t_no_move);
                   2294:     rs_write_short(savef, t->t_quiet);
                   2295:     rs_write_short(savef, t->t_movement);
                   2296:     rs_write_short(savef, t->t_action);
                   2297:     rs_write_short(savef, t->t_artifact);
                   2298:     rs_write_short(savef, t->t_wand);
                   2299:     rs_write_short(savef, t->t_summon);
                   2300:     rs_write_short(savef, t->t_cast);
                   2301:     rs_write_short(savef, t->t_breathe);
                   2302:
                   2303:     rs_write_string(savef,t->t_name);
                   2304:     rs_write_coord(savef, &t->t_doorgoal);
                   2305:
                   2306:     if (t->t_dest == &hero)
                   2307:     {
                   2308:         rs_write_int(savef,0);
                   2309:         rs_write_int(savef,1);
                   2310:     }
                   2311:     else if (t->t_dest != NULL)
                   2312:     {
                   2313:         i = find_thing_coord(mlist, t->t_dest);
                   2314:
                   2315:         if (i >= 0)
                   2316:         {
                   2317:             rs_write_int(savef,1);
                   2318:             rs_write_int(savef,i);
                   2319:         }
                   2320:         else
                   2321:         {
                   2322:             i = find_object_coord(lvl_obj, t->t_dest);
                   2323:
                   2324:             if (i >= 0)
                   2325:             {
                   2326:                 rs_write_int(savef,2);
                   2327:                 rs_write_int(savef,i);
                   2328:             }
                   2329:             else
                   2330:             {
                   2331:                 rs_write_int(savef,0);
                   2332:                 rs_write_int(savef,1); /* chase the hero anyway */
                   2333:             }
                   2334:         }
                   2335:     }
                   2336:     else
                   2337:     {
                   2338:         rs_write_int(savef,0);
                   2339:         rs_write_int(savef,0);
                   2340:     }
                   2341:
                   2342:     rs_write_coord(savef, &t->t_pos);
                   2343:     rs_write_coord(savef, &t->t_oldpos);
                   2344:     rs_write_coord(savef, &t->t_newpos);
                   2345:     rs_write_ulongs(savef, t->t_flags, 16);
                   2346:
                   2347:     DBG(("Thing\n"));
                   2348:     DBG(("    SaveID  : %X\n",RSXR_THING));
                   2349:     DBG(("    Name    : %s\n",t->t_name));
                   2350:     DBG(("    WasShot : %d\n",t->t_wasshot));
                   2351:     DBG(("    Type    : %c(%d)\n",t->t_type,t->t_type));
                   2352:     DBG(("    Disguise: %c(%d)\n",t->t_disguise,t->t_disguise));
                   2353:     DBG(("    OldCh   : %c(%d)\n",t->t_oldch,t->t_oldch));
                   2354:     DBG(("    CType   : %d\n",t->t_ctype));
                   2355:     DBG(("    Index   : %d\n",t->t_index));
                   2356:     DBG(("    NoMove  : %d\n",t->t_no_move));
                   2357:     DBG(("    Quiet   : %d\n",t->t_quiet));
                   2358:     DBG(("    Movement: %d\n",t->t_movement));
                   2359:     DBG(("    Action  : %d\n",t->t_action));
                   2360:     DBG(("    Artifact: %d\n",t->t_artifact));
                   2361:     DBG(("    Wand    : %d\n",t->t_wand));
                   2362:     DBG(("    Summon  : %d\n",t->t_summon));
                   2363:     DBG(("    Cast    : %d\n",t->t_cast));
                   2364:     DBG(("    Breathe : %d\n",t->t_breathe));
                   2365:     DBG(("    DoorGoal: %d %d\n",t->t_doorgoal.x,t->t_doorgoal.y));
                   2366:     if (t->t_dest)
                   2367:     {
                   2368:         DBG(("    Dest    : %d %d\n",t->t_dest->x,t->t_dest->y));
                   2369:     }
                   2370:     else
                   2371:     {
                   2372:         DBG(("    Dest    : None\n"));
                   2373:     }
                   2374:     DBG(("    Pos     : %d %d\n",t->t_pos.x,t->t_pos.y));
                   2375:     DBG(("    OldPos  : %d %d\n",t->t_oldpos.x,t->t_oldpos.y));
                   2376:     DBG(("    NewPos  : %d %d\n",t->t_newpos.x,t->t_newpos.y));
                   2377:     DBG(("    Flags   : "));
                   2378:     { int i; for(i=0;i<16;i++) {DBG(("%d ",t->t_flags[i]));} DBG(("\n")); }
                   2379:
                   2380:     rs_write_object_list(savef, t->t_pack);
                   2381:     i = -1;
                   2382:     if (t->t_using != NULL)
                   2383:         i = find_list_ptr(t->t_pack, t->t_using->l_data);
                   2384:     rs_write_int(savef, i);
                   2385:     rs_write_stats(savef, &t->t_stats);
                   2386:     rs_write_stats(savef, &t->maxstats);
                   2387:
                   2388:     return(WRITESTAT);
                   2389: }
                   2390:
                   2391: void
                   2392: rs_fix_thing(struct thing *t)
                   2393: {
                   2394:     struct linked_list *item;
                   2395:     struct thing *tp;
                   2396:
                   2397:     if (t->t_reserved < 0)
                   2398:         return;
                   2399:
                   2400:     item = get_list_item(mlist,t->t_reserved);
                   2401:
                   2402:     if (item != NULL)
                   2403:     {
                   2404:         tp = THINGPTR(item);
                   2405:         t->t_dest = &tp->t_pos;
                   2406:     }
                   2407: }
                   2408:
                   2409: bool
                   2410: rs_read_thing(FILE *inf, struct thing *t)
                   2411: {
                   2412:     int id;
                   2413:     int listid = 0, index = -1;
                   2414:     struct linked_list *item;
                   2415:
                   2416:     if (rs_read_int(inf, &id) != 0)
                   2417:     {
                   2418:         if (id != RSXR_THING)
                   2419:             format_error = TRUE;
                   2420:         else
                   2421:         {
                   2422:             rs_read_boolean(inf,&t->t_wasshot);
                   2423:             rs_read_uchar(inf, &t->t_type);
                   2424:             rs_read_uchar(inf, &t->t_disguise);
                   2425:             rs_read_uchar(inf, &t->t_oldch);
                   2426:             rs_read_short(inf, &t->t_ctype);
                   2427:             rs_read_short(inf, &t->t_index);
                   2428:             rs_read_short(inf, &t->t_no_move);
                   2429:             rs_read_short(inf, &t->t_quiet);
                   2430:             rs_read_short(inf, &t->t_movement);
                   2431:             rs_read_short(inf, &t->t_action);
                   2432:             rs_read_short(inf, &t->t_artifact);
                   2433:             rs_read_short(inf, &t->t_wand);
                   2434:             rs_read_short(inf, &t->t_summon);
                   2435:             rs_read_short(inf, &t->t_cast);
                   2436:             rs_read_short(inf, &t->t_breathe);
                   2437:             rs_read_new_string(inf,&t->t_name);
                   2438:             rs_read_coord(inf,&t->t_doorgoal);
                   2439:
                   2440:             rs_read_int(inf,&listid);
                   2441:             rs_read_int(inf,&index);
                   2442:             t->t_reserved = -1;
                   2443:             if (listid == 0)
                   2444:             {
                   2445:                 if (index == 1)
                   2446:                     t->t_dest = &hero;
                   2447:                 else
                   2448:                     t->t_dest = NULL;
                   2449:             }
                   2450:             else if (listid == 1)
                   2451:             {
                   2452:                 t->t_dest     = NULL;
                   2453:                 t->t_reserved = index;
                   2454:             }
                   2455:             else if (listid == 2)
                   2456:             {
                   2457:                 struct object *obj;
                   2458:                 item = get_list_item(lvl_obj,index);
                   2459:                 if (item != NULL)
                   2460:                 {
                   2461:                     obj = OBJPTR(item);
                   2462:                     t->t_dest = &obj->o_pos;
                   2463:                 }
                   2464:             }
                   2465:             else
                   2466:                 t->t_dest = NULL;
                   2467:
                   2468:             rs_read_coord(inf,&t->t_pos);
                   2469:             rs_read_coord(inf,&t->t_oldpos);
                   2470:             rs_read_coord(inf,&t->t_newpos);
                   2471:             rs_read_ulongs(inf,t->t_flags,16);
                   2472:             rs_read_object_list(inf,&t->t_pack);
                   2473:             rs_read_int(inf,&index);
                   2474:             t->t_using = get_list_item(t->t_pack, index);
                   2475:             rs_read_stats(inf,&t->t_stats);
                   2476:             rs_read_stats(inf,&t->maxstats);
                   2477:         }
                   2478:     }
                   2479:     else format_error = TRUE;
                   2480:
                   2481:     return(READSTAT);
                   2482: }
                   2483:
                   2484: int
                   2485: find_list_ptr(struct linked_list *l, void *ptr)
                   2486: {
                   2487:     int count = 0;
                   2488:
                   2489:     while(l != NULL)
                   2490:     {
                   2491:         if (l->l_data == ptr)
                   2492:             return(count);
                   2493:
                   2494:         l = l->l_next;
                   2495:         count++;
                   2496:     }
                   2497:
                   2498:     return(-1);
                   2499: }
                   2500:
                   2501:
                   2502: int
                   2503: list_size(struct linked_list *l)
                   2504: {
                   2505:     int count = 0;
                   2506:
                   2507:     while(l != NULL)
                   2508:     {
                   2509:         if (l->l_data == NULL)
                   2510:             return(count);
                   2511:
                   2512:         count++;
                   2513:
                   2514:         l = l->l_next;
                   2515:     }
                   2516:
                   2517:     return(count);
                   2518: }
                   2519:
                   2520:
                   2521: bool
                   2522: rs_write_monster_list(FILE *savef, struct linked_list *l)
                   2523: {
                   2524:     int cnt = 0;
                   2525:
                   2526:     DBG(("Monster List\n"));
                   2527:     rs_write_int(savef, RSXR_MONSTERLIST);
                   2528:
                   2529:     cnt = list_size(l);
                   2530:
                   2531:     rs_write_int(savef, cnt);
                   2532:
                   2533:     if (cnt < 1)
                   2534:         return(WRITESTAT);
                   2535:
                   2536:     while (l != NULL) {
                   2537:         rs_write_thing(savef, (struct thing *)l->l_data);
                   2538:         l = l->l_next;
                   2539:     }
                   2540:
                   2541:     return(WRITESTAT);
                   2542: }
                   2543:
                   2544: void
                   2545: rs_fix_monster_list(struct linked_list *list)
                   2546: {
                   2547:     struct linked_list *item;
                   2548:
                   2549:     for(item = list; item != NULL; item = item->l_next)
                   2550:         rs_fix_thing(THINGPTR(item));
                   2551: }
                   2552:
                   2553: bool
                   2554: rs_read_monster_list(FILE *inf, struct linked_list **list)
                   2555: {
                   2556:     int id;
                   2557:     int i, cnt;
                   2558:     struct linked_list *l = NULL, *previous = NULL, *head = NULL;
                   2559:
                   2560:     if (rs_read_int(inf,&id) != 0)
                   2561:     {
                   2562:         if (id != RSXR_MONSTERLIST)
                   2563:         {
                   2564:             printf("Invalid id. %x != %x(RSXR_MONSTERLIST)\n",
                   2565:                 id,RSXR_MONSTERLIST);
                   2566:             printf("Sorry, invalid save game format");
                   2567:             format_error = TRUE;
                   2568:         }
                   2569:         else if (rs_read_int(inf,&cnt) != 0)
                   2570:         {
                   2571:             for (i = 0; i < cnt; i++)
                   2572:             {
                   2573:                 l = new_item(sizeof(struct thing));
                   2574:                 l->l_prev = previous;
                   2575:                 if (previous != NULL)
                   2576:                     previous->l_next = l;
                   2577:                 rs_read_thing(inf,(struct thing *)l->l_data);
                   2578:                 if (previous == NULL)
                   2579:                     head = l;
                   2580:                 previous = l;
                   2581:             }
                   2582:
                   2583:
                   2584:             if (l != NULL)
                   2585:                 l->l_next = NULL;
                   2586:
                   2587:             *list = head;
                   2588:         }
                   2589:     }
                   2590:     else format_error = TRUE;
                   2591:
                   2592:     return(READSTAT);
                   2593: }
                   2594:
                   2595: bool
                   2596: rs_write_magic_items(FILE *savef, struct magic_item *i, int count)
                   2597: {
                   2598:     int n;
                   2599:
                   2600:     DBG(("Magic Items\n"));
                   2601:     rs_write_int(savef, RSXR_MAGICITEMS);
                   2602:     rs_write_int(savef, count);
                   2603:
                   2604:     for(n=0;n<count;n++)
                   2605:     {
                   2606:         rs_write(savef,i[n].mi_name,sizeof(i[n].mi_name));
                   2607:         rs_write_int(savef,i[n].mi_prob);
                   2608:         rs_write_int(savef,i[n].mi_worth);
                   2609:         rs_write_int(savef,i[n].mi_curse);
                   2610:         rs_write_int(savef,i[n].mi_bless);
                   2611:     }
                   2612:
                   2613:     return(WRITESTAT);
                   2614: }
                   2615:
                   2616: bool
                   2617: rs_read_magic_items(FILE *inf, struct magic_item *mi, int count)
                   2618: {
                   2619:     int id;
                   2620:     int n;
                   2621:     int value;
                   2622:
                   2623:     if (rs_read_int(inf, &id) != 0)
                   2624:     {
                   2625:         if (id != RSXR_MAGICITEMS)
                   2626:         {
                   2627:             printf("Invalid id. %x != %x(RSXR_MAGICITEMS)\n",
                   2628:                 id,RSXR_MAGICITEMS);
                   2629:             printf("Sorry, invalid save game format");
                   2630:             format_error = TRUE;
                   2631:         }
                   2632:         else if (rs_read_int(inf, &value) != 0)
                   2633:         {
                   2634:             if (value > count)
                   2635:             {
                   2636:                 printf("Incorrect number of magic items in block. %d > %d.",
                   2637:                     value,count);
                   2638:                 printf("Sorry, invalid save game format");
                   2639:                 format_error = TRUE;
                   2640:             }
                   2641:             else
                   2642:             {
                   2643:                 for(n = 0; n < value; n++)
                   2644:                 {
                   2645:                     rs_read(inf,mi[n].mi_name,sizeof(mi[n].mi_name));
                   2646:                     rs_read_int(inf,&mi[n].mi_prob);
                   2647:                     rs_read_int(inf,&mi[n].mi_worth);
                   2648:                     rs_read_int(inf,&mi[n].mi_curse);
                   2649:                     rs_read_int(inf,&mi[n].mi_bless);
                   2650:                 }
                   2651:             }
                   2652:         }
                   2653:     }
                   2654:
                   2655:     return(READSTAT);
                   2656: }
                   2657:
                   2658: bool
                   2659: rs_write_window(FILE *savef, WINDOW *win)
                   2660: {
                   2661:     int row,col,height,width;
                   2662:     width = getmaxx(win);
                   2663:     height = getmaxy(win);
                   2664:     DBG(("Window\n"));
                   2665:     rs_write_int(savef,height);
                   2666:     rs_write_int(savef,width);
                   2667:
                   2668:     for(row=0;row<height;row++)
                   2669:         for(col=0;col<width;col++)
                   2670:             rs_write_int(savef, mvwinch(win,row,col));
                   2671:
                   2672:     return(WRITESTAT);
                   2673: }
                   2674:
                   2675: bool
                   2676: rs_read_window(FILE *inf, WINDOW *win)
                   2677: {
                   2678:     int row,col,maxlines,maxcols,value,width,height;
                   2679:
                   2680:     width = getmaxx(win);
                   2681:     height = getmaxy(win);
                   2682:
                   2683:     rs_read_int(inf,&maxlines);
                   2684:     rs_read_int(inf,&maxcols);
                   2685:     if (maxlines > height)
                   2686:        abort();
                   2687:     if (maxcols > width)
                   2688:        abort();
                   2689:
                   2690:     for(row=0;row<maxlines;row++)
                   2691:         for(col=0;col<maxcols;col++)
                   2692:         {
                   2693:             rs_read_int(inf, &value);
                   2694:             if ((value == '-') || (value == 196))
                   2695:                 value = HORZWALL;
                   2696:             else if ((value == '|') || (value == 179))
                   2697:                 value = VERTWALL;
                   2698:             mvwaddch(win,row,col,value);
                   2699:         }
                   2700:
                   2701:     return(READSTAT);
                   2702: }
                   2703:
                   2704: bool
                   2705: rs_save_file(FILE *savef)
                   2706: {
                   2707:     int i, weapon, armor, ring, misc, room = -1;
                   2708:     int endian = 0x01020304;
                   2709:     big_endian = ( *((char *)&endian) == 0x01 );
                   2710:
                   2711:     rs_write_thing(savef, &player);                     /* rogue.c          */
                   2712:     rs_write_object_list(savef, lvl_obj);               /* rogue.c          */
                   2713:     rs_write_monster_list(savef, mlist);                /* rogue.c          */
                   2714:     rs_write_monster_list(savef, tlist);                /* rogue.c          */
                   2715:
                   2716:     rs_write_traps(savef, traps, MAXTRAPS);             /* rogue.c          */
                   2717:
                   2718:     armor = find_list_ptr(player.t_pack, cur_armor);
                   2719:     rs_write_int(savef, armor);                         /* rogue.c          */
                   2720:
                   2721:     for (i = 0; i < NUM_FINGERS; i++)
                   2722:     {
                   2723:         ring = find_list_ptr(player.t_pack, cur_ring[i]);
                   2724:         rs_write_int(savef, ring);                      /* rogue.c          */
                   2725:     }
                   2726:
                   2727:     for (i = 0; i < NUM_MM; i++)
                   2728:     {
                   2729:         misc = find_list_ptr(player.t_pack, cur_misc[i]);
                   2730:         rs_write_int(savef, misc);                      /* rogue.c          */
                   2731:     }
                   2732:
                   2733:     for (i=0; i<MAXRELIC; i++)
                   2734:        rs_write_int(savef,cur_relic[i]);                /* rogue.c          */
                   2735:
                   2736:
                   2737:     rs_write_rooms(savef, rooms, MAXROOMS);             /* rogue.c          */
                   2738:
                   2739:     for (i = 0; i < MAXROOMS; i++)
                   2740:         if (&rooms[i] == oldrp)
                   2741:             room = i;
                   2742:     rs_write_int(savef, room);                          /* rogue.c          */
                   2743:
                   2744:     weapon = find_list_ptr(player.t_pack, cur_weapon);
                   2745:     rs_write_int(savef, weapon);                        /* rogue..c         */
                   2746:     rs_write_int(savef,char_type);
                   2747:     rs_write_int(savef,foodlev);
                   2748:     rs_write_int(savef,ntraps);
                   2749:     rs_write_int(savef,trader);
                   2750:     rs_write_int(savef,curprice);
                   2751:     rs_write_int(savef,seed);
                   2752:     rs_write_int(savef,max_level);
                   2753:     rs_write_int(savef,cur_max);
                   2754:     rs_write_int(savef,prev_max);
                   2755:     rs_write_int(savef,move_free);
                   2756:     rs_write_int(savef,mpos);
                   2757:     rs_write_int(savef,level);
                   2758:     rs_write_long(savef,purse);
                   2759:     rs_write_int(savef,inpack);
                   2760:     rs_write_int(savef,total);
                   2761:     rs_write_int(savef,no_food);
                   2762:     rs_write_int(savef,foods_this_level);
                   2763:     rs_write_int(savef,count);
                   2764:     rs_write_int(savef,food_left);
                   2765:     rs_write_int(savef,group);
                   2766:     rs_write_int(savef,hungry_state);
                   2767:     rs_write_int(savef,infest_dam);
                   2768:     rs_write_int(savef,lost_str);
                   2769:     rs_write_int(savef,lastscore);
                   2770:     rs_write_int(savef,hold_count);
                   2771:     rs_write_int(savef,trap_tries);
                   2772:     rs_write_int(savef,chant_time);
                   2773:     rs_write_int(savef,pray_time);
                   2774:     rs_write_int(savef,spell_power);
                   2775:     rs_write_long(savef,turns);
                   2776:     rs_write_int(savef,quest_item);
                   2777:     rs_write_int(savef,cols);
                   2778:     rs_write_int(savef,lines);
                   2779:     rs_write_int(savef,nfloors);
                   2780:     rs_write(savef,curpurch,LINELEN);
                   2781:     rs_write_char(savef,PLAYER);
                   2782:     rs_write_char(savef,take);
                   2783:     rs_write_int(savef,1234);/*checkpoint*/
                   2784:     rs_write(savef,prbuf,LINELEN*2);
                   2785:     rs_write_int(savef,1234);/*checkpoint*/
                   2786:     rs_write_char(savef,runch);
                   2787:     rs_write_int(savef,1234);/*checkpoint*/
                   2788:     rs_write_scrolls(savef);
                   2789:     rs_write_potions(savef);
                   2790:     rs_write_rings(savef);
                   2791:     rs_write_sticks(savef);
                   2792:     rs_write_misc(savef);
                   2793:     rs_write_int(savef,1234);/*checkpoint*/
                   2794:     rs_write(savef,whoami,LINELEN);
                   2795:     rs_write_window(savef, cw);
                   2796:     rs_write_window(savef, hw);
                   2797:     rs_write_window(savef, mw);
                   2798:     rs_write_window(savef, msgw);
                   2799:     rs_write_window(savef, stdscr);
                   2800:     rs_write_boolean(savef,pool_teleport);
                   2801:     rs_write_boolean(savef,inwhgt);
                   2802:     rs_write_boolean(savef,after);
                   2803:     rs_write_boolean(savef,waswizard);
                   2804:     rs_write_boolean(savef, playing);                       /* rogue.h/init.c   */
                   2805:     rs_write_boolean(savef, running);                       /* rogue.h/init.c   */
                   2806:     rs_write_boolean(savef, wizard);                        /* rogue.h/init.c   */
                   2807:     rs_write_boolean(savef, notify);                        /* rogue.h/init.c   */
                   2808:     rs_write_boolean(savef, fight_flush);                   /* rogue.h/init.c   */
                   2809:     rs_write_boolean(savef, terse);                         /* rogue.h/init.c   */
                   2810:     rs_write_boolean(savef, auto_pickup);                     /* rogue.h/init.c   */
                   2811:     rs_write_boolean(savef, def_attr);                     /* rogue.h/init.c   */
                   2812:     rs_write_boolean(savef, menu_overlay);                     /* rogue.h/init.c   */
                   2813:     rs_write_boolean(savef, door_stop);                     /* rogue.h/init.c   */
                   2814:     rs_write_boolean(savef, jump);                          /* rogue.h/init.c   */
                   2815:     rs_write_boolean(savef, slow_invent);                   /* rogue.h/init.c   */
                   2816:     rs_write_boolean(savef, firstmove);                     /* rogue.h/init.c   */
                   2817:     rs_write_boolean(savef, askme);                         /* rogue.h/init.c   */
                   2818:     rs_write_boolean(savef, in_shell);                      /* rogue.h/init.c   */
                   2819:     rs_write_boolean(savef, daytime);                      /* rogue.h/init.c   */
                   2820:     rs_write_boolean(savef, funfont);                      /* rogue.h/init.c   */
                   2821:     rs_write_levtype(savef,levtype);
                   2822:     rs_write_character_types(savef,char_class,NUM_CHARTYPES);
                   2823:     rs_write_words(savef,abilities,NUMABILITIES);
                   2824:     for(i=0;i<9;i++)
                   2825:         rs_write_coord(savef,&grid[i]);
                   2826:     rs_write_death_types(savef,deaths,DEATHNUM);
                   2827:     rs_write_init_weps(savef,weaps,MAXWEAPONS);
                   2828:     rs_write_init_armor(savef,armors,MAXARMORS);
                   2829:     rs_write_magic_items(savef, things,   NUMTHINGS);   /* rogue.h/init.c   */
                   2830:     rs_write_magic_items(savef, s_magic,  MAXSCROLLS);  /* rogue.h/init.c   */
                   2831:     rs_write_magic_items(savef, p_magic,  MAXPOTIONS);  /* rogue.h/init.c   */
                   2832:     rs_write_magic_items(savef, r_magic,  MAXRINGS);    /* rogue.h/init.c   */
                   2833:     rs_write_magic_items(savef, ws_magic, MAXSTICKS);   /* rogue.h/init.c   */
                   2834:     rs_write_magic_items(savef, m_magic, MAXMM);   /* rogue.h/init.c   */
                   2835:     rs_write_magic_items(savef, rel_magic, MAXRELIC);   /* rogue.h/init.c   */
                   2836:     rs_write_magic_items(savef, foods, MAXFOODS);   /* rogue.h/init.c   */
                   2837:     rs_write_spells(savef,magic_spells,MAXSPELLS);
                   2838:     rs_write_spells(savef,cleric_spells,MAXPRAYERS);
                   2839:     rs_write_spells(savef,druid_spells,MAXCHANTS);
                   2840:     rs_write_spells(savef,quill_scrolls,MAXQUILL);
                   2841:
                   2842:     rs_write_int(savef,mf_count);                           /* actions.c        */
                   2843:     rs_write_int(savef,mf_jmpcnt);                          /* actions.c        */
                   2844:     rs_write_daemons(savef, d_list, MAXDAEMONS);            /* daemon.c         */
                   2845:     rs_write_daemons(savef, f_list, MAXFUSES);              /* daemon.c         */
                   2846:     rs_write_int(savef,demoncnt);                           /* daemon.c         */
                   2847:     rs_write_int(savef,fusecnt);                            /* daemon.c         */
                   2848:     rs_write_int(savef,killed_chance);                      /* fight.c          */
                   2849:     rs_write_words(savef,rainbow,NCOLORS);                  /* init.c   */
                   2850:     rs_write_words(savef,sylls,NSYLLS);                     /* init.c   */
                   2851:     rs_write_words(savef,stones,NSTONES);                   /* init.c   */
                   2852:     rs_write_words(savef,wood,NWOOD);                       /* init.c   */
                   2853:     rs_write_words(savef,metal,NMETAL);                     /* init.c   */
                   2854:     rs_write_monsters(savef,monsters,
                   2855:         sizeof(monsters)/sizeof(struct monster));           /* mons_def.c       */
                   2856:     rs_write_coord(savef,&move_nh);                         /* move.c           */
                   2857:     return(WRITESTAT);
                   2858: }
                   2859:
                   2860: bool
                   2861: rs_restore_file(FILE *inf)
                   2862: {
                   2863:     int weapon, armor, ring, misc, room = -1,i,checkpoint;
                   2864:     int endian = 0x01020304;
                   2865:     big_endian = ( *((char *)&endian) == 0x01 );
                   2866:
                   2867:     rs_read_thing(inf, &player);                        /* rogue.h          */
                   2868:     rs_read_object_list(inf, &lvl_obj);                 /* rogue.h/init.c   */
                   2869:     rs_read_monster_list(inf, &mlist);                  /* rogue.h/init.c   */
                   2870:     rs_read_monster_list(inf, &tlist);                  /* rogue.h/init.c   */
                   2871:     rs_fix_thing(&player);
                   2872:     rs_fix_monster_list(mlist);
                   2873:     rs_read_traps(inf, traps, MAXTRAPS);
                   2874:
                   2875:
                   2876:     rs_read_int(inf, &armor);                           /* rogue.h          */
                   2877:     cur_armor = get_list_item(player.t_pack,armor);
                   2878:
                   2879:     for(i = 0; i < NUM_FINGERS; i++)
                   2880:     {
                   2881:         rs_read_int(inf,&ring);
                   2882:         cur_ring[i] = get_list_item(player.t_pack,ring);
                   2883:     }
                   2884:
                   2885:     for(i = 0; i < NUM_MM; i++)
                   2886:     {
                   2887:         rs_read_int(inf,&misc);
                   2888:         cur_misc[i] = get_list_item(player.t_pack,misc);
                   2889:     }
                   2890:
                   2891:     for(i=0;i<MAXRELIC;i++)
                   2892:         rs_read_int(inf,&cur_relic[i]);
                   2893:
                   2894:     rs_read_rooms(inf, rooms, MAXROOMS);
                   2895:     rs_read_int(inf, &room);
                   2896:
                   2897:     oldrp = &rooms[room];
                   2898:
                   2899:     rs_read_int(inf,&weapon);
                   2900:     cur_weapon = get_list_item(player.t_pack,weapon);
                   2901:
                   2902:     rs_read_int(inf,&char_type);
                   2903:     rs_read_int(inf,&foodlev);
                   2904:     rs_read_int(inf,&ntraps);
                   2905:     rs_read_int(inf,&trader);
                   2906:     rs_read_int(inf,&curprice);
                   2907:     rs_read_int(inf,&seed);
                   2908:     rs_read_int(inf,&max_level);
                   2909:     rs_read_int(inf,&cur_max);
                   2910:     rs_read_int(inf,&prev_max);
                   2911:     rs_read_int(inf,&move_free);
                   2912:     rs_read_int(inf,&mpos);
                   2913:     rs_read_int(inf,&level);
                   2914:     rs_read_long(inf,&purse);
                   2915:     rs_read_int(inf,&inpack);
                   2916:     rs_read_int(inf,&total);
                   2917:     rs_read_int(inf,&no_food);
                   2918:     rs_read_int(inf,&foods_this_level);
                   2919:     rs_read_int(inf,&count);
                   2920:     rs_read_int(inf,&food_left);
                   2921:     rs_read_int(inf,&group);
                   2922:     rs_read_int(inf,&hungry_state);
                   2923:     rs_read_int(inf,&infest_dam);
                   2924:     rs_read_int(inf,&lost_str);
                   2925:     rs_read_int(inf,&lastscore);
                   2926:     rs_read_int(inf,&hold_count);
                   2927:     rs_read_int(inf,&trap_tries);
                   2928:     rs_read_int(inf,&chant_time);
                   2929:     rs_read_int(inf,&pray_time);
                   2930:     rs_read_int(inf,&spell_power);
                   2931:     rs_read_long(inf,&turns);
                   2932:     rs_read_int(inf,&quest_item);
                   2933:     rs_read_int(inf,&cols);
                   2934:     rs_read_int(inf,&lines);
                   2935:     rs_read_int(inf,&nfloors);
                   2936:     rs_read(inf,curpurch,LINELEN);
                   2937:     rs_read_char(inf,&PLAYER);
                   2938:     rs_read_char(inf,&take);
                   2939:     rs_read_int(inf,&checkpoint);
                   2940:     if (checkpoint != 1234){printf("Checkpoint failed");abort();}
                   2941:     rs_read(inf,prbuf,LINELEN*2);
                   2942:     rs_read_int(inf,&checkpoint);
                   2943:     if (checkpoint != 1234){printf("Checkpoint failed");abort();}
                   2944:     rs_read_char(inf,&runch);
                   2945:     rs_read_int(inf,&checkpoint);
                   2946:     if (checkpoint != 1234){printf("Checkpoint failed");abort();}
                   2947:     rs_read_scrolls(inf);
                   2948:     rs_read_potions(inf);
                   2949:     rs_read_rings(inf);
                   2950:     rs_read_sticks(inf);
                   2951:     rs_read_misc(inf);
                   2952:     rs_read_int(inf,&checkpoint);
                   2953:     if (checkpoint != 1234){printf("Checkpoint failed");abort();}
                   2954:     rs_read(inf,whoami,LINELEN);
                   2955:     rs_read_window(inf, cw);
                   2956:     rs_read_window(inf, hw);
                   2957:     rs_read_window(inf, mw);
                   2958:     rs_read_window(inf, msgw);
                   2959:     rs_read_window(inf, stdscr);
                   2960:     rs_read_boolean(inf,&pool_teleport);
                   2961:     rs_read_boolean(inf,&inwhgt);
                   2962:     rs_read_boolean(inf,&after);
                   2963:     rs_read_boolean(inf,&waswizard);
                   2964:     rs_read_boolean(inf, &playing);                       /* rogue.h/init.c   */
                   2965:     rs_read_boolean(inf, &running);                       /* rogue.h/init.c   */
                   2966:     rs_read_boolean(inf, &wizard);                        /* rogue.h/init.c   */
                   2967:     rs_read_boolean(inf, &notify);                        /* rogue.h/init.c   */
                   2968:     rs_read_boolean(inf, &fight_flush);                   /* rogue.h/init.c   */
                   2969:     rs_read_boolean(inf, &terse);                         /* rogue.h/init.c   */
                   2970:     rs_read_boolean(inf, &auto_pickup);                     /* rogue.h/init.c   */
                   2971:     rs_read_boolean(inf, &def_attr);                     /* rogue.h/init.c   */
                   2972:     rs_read_boolean(inf, &menu_overlay);                     /* rogue.h/init.c   */
                   2973:     rs_read_boolean(inf, &door_stop);                     /* rogue.h/init.c   */
                   2974:     rs_read_boolean(inf, &jump);                          /* rogue.h/init.c   */
                   2975:     rs_read_boolean(inf, &slow_invent);                   /* rogue.h/init.c   */
                   2976:     rs_read_boolean(inf, &firstmove);                     /* rogue.h/init.c   */
                   2977:     rs_read_boolean(inf, &askme);                         /* rogue.h/init.c   */
                   2978:     rs_read_boolean(inf, &in_shell);                      /* rogue.h/init.c   */
                   2979:     rs_read_boolean(inf, &daytime);                      /* rogue.h/init.c   */
                   2980:     rs_read_boolean(inf, &funfont);                      /* rogue.h/init.c   */
                   2981:     rs_read_levtype(inf,&levtype);
                   2982:     rs_read_character_types(inf,char_class,NUM_CHARTYPES);
                   2983:     rs_read_words(inf,abilities,NUMABILITIES);
                   2984:     for(i=0;i<9;i++)
                   2985:         rs_read_coord(inf,&grid[i]);
                   2986:     rs_read_death_types(inf,deaths,DEATHNUM);
                   2987:     rs_read_init_weps(inf,weaps,MAXWEAPONS);
                   2988:     rs_read_init_armor(inf,armors,MAXARMORS);
                   2989:     rs_read_magic_items(inf, things,NUMTHINGS);         /* rogue.h/init.c   */
                   2990:     rs_read_magic_items(inf, s_magic,MAXSCROLLS);       /* rogue.h/init.c   */
                   2991:     rs_read_magic_items(inf, p_magic,MAXPOTIONS);       /* rogue.h/init.c   */
                   2992:     rs_read_magic_items(inf, r_magic,MAXRINGS);         /* rogue.h/init.c   */
                   2993:     rs_read_magic_items(inf, ws_magic,MAXSTICKS);       /* rogue.h/init.c   */
                   2994:     rs_read_magic_items(inf, m_magic,MAXMM);       /* rogue.h/init.c   */
                   2995:     rs_read_magic_items(inf, rel_magic,MAXRELIC);       /* rogue.h/init.c   */
                   2996:     rs_read_magic_items(inf, foods,MAXFOODS);       /* rogue.h/init.c   */
                   2997:     rs_read_spells(inf,magic_spells,MAXSPELLS);
                   2998:     rs_read_spells(inf,cleric_spells,MAXPRAYERS);
                   2999:     rs_read_spells(inf,druid_spells,MAXCHANTS);
                   3000:     rs_read_spells(inf,quill_scrolls,MAXQUILL);
                   3001:
                   3002:     rs_read_int(inf,&mf_count);                             /* actions.c        */
                   3003:     rs_read_int(inf,&mf_jmpcnt);                            /* actions.c        */
                   3004:     rs_read_daemons(inf, d_list, MAXDAEMONS);               /* daemon.c         */
                   3005:     rs_read_daemons(inf, f_list, MAXFUSES);                 /* daemon.c         */
                   3006:     rs_read_int(inf,&demoncnt);                             /* daemon.c         */
                   3007:     rs_read_int(inf,&fusecnt);                              /* daemon.c         */
                   3008:     rs_read_int(inf,&killed_chance);                        /* fight.c          */
                   3009:     rs_read_words(inf,rainbow,NCOLORS);                     /* init.c   */
                   3010:     rs_read_words(inf,sylls,NSYLLS);                        /* init.c   */
                   3011:     rs_read_words(inf,stones,NSTONES);                      /* init.c   */
                   3012:     rs_read_words(inf,wood,NWOOD);                          /* init.c   */
                   3013:     rs_read_words(inf,metal,NMETAL);                        /* init.c   */
                   3014:
                   3015:     rs_read_monsters(inf,monsters,
                   3016:         sizeof(monsters)/sizeof(struct monster));           /* mons_def.c       */
                   3017:     rs_read_coord(inf,&move_nh);                            /* move.c           */
                   3018:
                   3019:     return(READSTAT);
                   3020: }
                   3021:
                   3022: void
                   3023: rs_write_scorefile(FILE *savef, struct sc_ent *entries, int count)
                   3024: {
                   3025:     int i;
                   3026:
                   3027:     rs_write_int(savef, count);
                   3028:     for(i = 0; i < count; i++)
                   3029:     {
                   3030:         rs_write_ulong(savef, entries[i].sc_score);
                   3031:         rs_write(savef, entries[i].sc_name, sizeof(entries[i].sc_name));
                   3032:         rs_write(savef, entries[i].sc_system, sizeof(entries[i].sc_system));
                   3033:         rs_write(savef, entries[i].sc_login, sizeof(entries[i].sc_login));
                   3034:         rs_write_short(savef, entries[i].sc_flags);
                   3035:         rs_write_short(savef, entries[i].sc_level);
                   3036:         rs_write_short(savef, entries[i].sc_ctype);
                   3037:         rs_write_short(savef, entries[i].sc_monster);
                   3038:         rs_write_short(savef, entries[i].sc_quest);
                   3039:     }
                   3040: }
                   3041:
                   3042: int
                   3043: rs_read_scorefile(FILE *savef, struct sc_ent *entries, int count)
                   3044: {
                   3045:     int i,available = 0;
                   3046:
                   3047:     rs_read_int(savef, &available);
                   3048:
                   3049:     if (end_of_file)
                   3050:        return(-1);
                   3051:
                   3052:     if (available != count)
                   3053:        return(-2);
                   3054:
                   3055:     for(i = 0; i < count; i++)
                   3056:     {
                   3057:         rs_read_ulong(savef, &entries[i].sc_score);
                   3058:         rs_read(savef, entries[i].sc_name, sizeof(entries[i].sc_name));
                   3059:         rs_read(savef, entries[i].sc_system, sizeof(entries[i].sc_system));
                   3060:         rs_read(savef, entries[i].sc_login, sizeof(entries[i].sc_login));
                   3061:         rs_read_short(savef, &entries[i].sc_flags);
                   3062:         rs_read_short(savef, &entries[i].sc_level);
                   3063:         rs_read_short(savef, &entries[i].sc_ctype);
                   3064:         rs_read_short(savef, &entries[i].sc_monster);
                   3065:         rs_read_short(savef, &entries[i].sc_quest);
                   3066:     }
                   3067:
                   3068:     return(0);
                   3069: }
                   3070:
                   3071:
                   3072:
                   3073: void
                   3074: rs_print_thing(FILE *outf, struct thing *thing, char *prefix, int list, int index)
                   3075: {
                   3076:     int i;
                   3077:
                   3078:     fprintf(outf,"%sList Ident : %d\n", prefix, list);
                   3079:     fprintf(outf,"%sList Index : %d\n", prefix, index);
                   3080:     fprintf(outf,"%st_wasshot  : %d\n", prefix, thing->t_wasshot);
                   3081:     fprintf(outf,"%st_type     : %c\n", prefix, thing->t_type);
                   3082:     fprintf(outf,"%st_disguise : %c\n", prefix, thing->t_disguise);
                   3083:     fprintf(outf,"%st_oldch    : %c\n", prefix, thing->t_oldch);
                   3084:     fprintf(outf,"%st_ctype    : %d\n", prefix, thing->t_ctype);
                   3085:     fprintf(outf,"%st_index    : %d\n", prefix, thing->t_index);
                   3086:     fprintf(outf,"%st_no_move  : %d\n", prefix, thing->t_no_move);
                   3087:     fprintf(outf,"%st_quiet    : %d\n", prefix, thing->t_quiet);
                   3088:     fprintf(outf,"%st_movement : %d\n", prefix, thing->t_movement);
                   3089:     fprintf(outf,"%st_action   : %d\n", prefix, thing->t_action);
                   3090:     fprintf(outf,"%st_artificat: %d\n", prefix, thing->t_artifact);
                   3091:     fprintf(outf,"%st_wand     : %d\n", prefix, thing->t_wand);
                   3092:     fprintf(outf,"%st_summon   : %d\n", prefix, thing->t_summon);
                   3093:     fprintf(outf,"%st_cast     : %d\n", prefix, thing->t_cast);
                   3094:     fprintf(outf,"%st_breathe  : %d\n", prefix, thing->t_breathe);
                   3095:     fprintf(outf,"%st_name     : %s\n", prefix, (thing->t_name == NULL) ? "none" :
                   3096:                                                 thing->t_name);
                   3097:     fprintf(outf,"%st_doorgoal : %d %d\n", prefix, thing->t_doorgoal.x, thing->t_doorgoal.y);
                   3098:     fprintf(outf,"%st_dest     : %p\n", prefix, thing->t_dest);
                   3099:     fprintf(outf,"%st_pos      : %d %d (%p)\n", prefix, thing->t_pos.x, thing->t_pos.y,&thing->t_pos);
                   3100:     fprintf(outf,"%st_oldpos   : %d %d\n", prefix, thing->t_oldpos.x, thing->t_oldpos.y);
                   3101:     fprintf(outf,"%st_newpos   : %d %d\n", prefix, thing->t_newpos.x, thing->t_newpos.y);
                   3102:     fprintf(outf,"%st_flags    : ", prefix);
                   3103:
                   3104:     for(i = 0; i<16; i++)
                   3105:         fprintf(outf,"%X ",thing->t_flags[i]);
                   3106:     fprintf(outf,"\n");
                   3107:
                   3108:     fprintf(outf,"%st_pack     : %p\n",prefix,thing->t_pack);
                   3109:     fprintf(outf,"%st_using    : %p\n",prefix,thing->t_using);
                   3110:     fprintf(outf,"%st_stats    : Not Implemented\n",prefix);
                   3111:     fprintf(outf,"%st_maxstats : Not Implemented\n",prefix);
                   3112:     fprintf(outf,"%st_reserved : %d\n",prefix,thing->t_reserved);
                   3113: }
                   3114:
                   3115: void
                   3116: rs_print_game_state(FILE *outf)
                   3117: {
                   3118:     fprintf(outf, "Player\n");
                   3119:
                   3120:     rs_print_thing(outf, &player, "    ", 0, 0);
                   3121: }
                   3122:
                   3123: /****
                   3124:  Machine Dependent Functions
                   3125:
                   3126:  md_getuid()
                   3127:  md_memused()
                   3128:  md_getusername()
                   3129:  md_gethostname()
                   3130:  md_gethomedir()
                   3131:  md_getroguedir()
                   3132:  md_getshell()
                   3133:  md_shellescape()
                   3134:  md_getpass()
                   3135:  md_crypt()
                   3136:  md_htons()
                   3137:  md_nstoh()
                   3138:  md_unlink()
                   3139:  md_isdir()
                   3140:  md_ntohl()
                   3141:  md_htonl()
                   3142:
                   3143: ****/
                   3144:
                   3145: int
                   3146: md_rand(int range)
                   3147: {
                   3148: #ifdef _WIN32
                   3149:     return(range <= 0 ? 0 : rand() % range);
                   3150: #else
                   3151:     return(range <= 0 ? 0 : random() % range);
                   3152: #endif
                   3153: }
                   3154:
                   3155: void
                   3156: md_srand(int seed)
                   3157: {
                   3158: #ifdef _WIN32
                   3159:     srand(seed);
                   3160: #else
                   3161:     srandom(seed);
                   3162: #endif
                   3163: }
                   3164:
                   3165: void
                   3166: md_flushinp(void)
                   3167: {
                   3168:     /* ioctl(0,TIOCFLUSH) */
                   3169:     /* ioctl(_tty_ch,TCFLSH,0) */
                   3170:     flushinp();
                   3171: }
                   3172:
                   3173: int
                   3174: md_getuid(void)
                   3175: {
                   3176: #ifdef _WIN32
                   3177:     return(42);
                   3178: #else
                   3179:     return(getuid());
                   3180: #endif
                   3181: }
                   3182:
                   3183: long
                   3184: md_memused(void)
                   3185: {
                   3186: #ifdef _WIN32
                   3187:     MEMORYSTATUS stat;
                   3188:
                   3189:     GlobalMemoryStatus(&stat);
                   3190:
                   3191:     return((long)stat.dwTotalPageFile);
                   3192: #else
                   3193:     return( (long)sbrk(0) );
                   3194: #endif
                   3195: }
                   3196:
                   3197: char *
                   3198: md_getusername(void)
                   3199: {
                   3200:     static char login[80];
                   3201:     char *l = NULL;
                   3202: #ifdef _WIN32
                   3203:     LPSTR mybuffer;
                   3204:     DWORD size = UNLEN + 1;
                   3205:     TCHAR buffer[UNLEN + 1];
                   3206:
                   3207:     mybuffer = buffer;
                   3208:     GetUserName(mybuffer,&size);
                   3209:     l = mybuffer;
                   3210: #endif
                   3211: #if !defined(_WIN32) && !defined(DJGPP)
                   3212:     struct passwd *pw;
                   3213:
                   3214:     pw = getpwuid(getuid());
                   3215:
                   3216:     if (pw != NULL)
                   3217:         l = pw->pw_name;
                   3218: #endif
                   3219:
                   3220:     if ((l == NULL) || (*l == '\0'))
                   3221:         if ( (l = getenv("USERNAME")) == NULL )
                   3222:             if ( (l = getenv("LOGNAME")) == NULL )
                   3223:                 if ( (l = getenv("USER")) == NULL )
                   3224:                     l = "nobody";
                   3225:
                   3226:     strncpy(login,l,80);
                   3227:     login[79] = 0;
                   3228:
                   3229:     return(login);
                   3230: }
                   3231:
                   3232: char *
                   3233: md_gethomedir(void)
                   3234: {
                   3235:     static char homedir[PATH_MAX];
                   3236:     char *h = NULL;
                   3237:     size_t len;
                   3238: #if defined(_WIN32)
                   3239:     TCHAR szPath[MAX_PATH];
                   3240: #endif
                   3241: #if defined(_WIN32) || defined(DJGPP)
                   3242:        char slash = '\\';
                   3243: #else
                   3244:     char slash = '/';
                   3245:     struct passwd *pw;
                   3246:     pw = getpwuid(getuid());
                   3247:
                   3248:     if (pw != NULL)
                   3249:     {
                   3250:         h = pw->pw_dir;
                   3251:         if (strcmp(h,"/") == 0)
                   3252:             h = NULL;
                   3253:     }
                   3254: #endif
                   3255:     homedir[0] = 0;
                   3256:
                   3257: #ifdef _WIN32
                   3258:        if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, szPath)))
                   3259:                h = szPath;
                   3260: #endif
                   3261:
                   3262:        if ( (h == NULL) || (*h == '\0') )
                   3263:         if ( (h = getenv("HOME")) == NULL )
                   3264:             if ( (h = getenv("HOMEDRIVE")) == NULL)
                   3265:                 h = "";
                   3266:             else
                   3267:             {
                   3268:                 strncpy(homedir,h,PATH_MAX-1);
                   3269:                 homedir[PATH_MAX-1] = 0;
                   3270:
                   3271:                 if ( (h = getenv("HOMEPATH")) == NULL)
                   3272:                     h = "";
                   3273:             }
                   3274:
                   3275:
                   3276:     len = strlen(homedir);
                   3277:     strncat(homedir,h,PATH_MAX-len-1);
                   3278:     len = strlen(homedir);
                   3279:
                   3280:     if ((len > 0) && (homedir[len-1] != slash)) {
                   3281:         homedir[len] = slash;
                   3282:         homedir[len+1] = 0;
                   3283:     }
                   3284:
                   3285:     return(homedir);
                   3286: }
                   3287:
                   3288: int
                   3289: directory_exists(char *dirname)
                   3290: {
                   3291:     struct stat sb;
                   3292:
                   3293:     if (stat(dirname, &sb) == 0) /* path exists */
                   3294:         return (sb.st_mode & S_IFDIR);
                   3295:
                   3296:     return(0);
                   3297: }
                   3298:
                   3299: char *
                   3300: md_getroguedir(void)
                   3301: {
                   3302:     static char path[1024];
                   3303:     char *end,*home;
                   3304:
                   3305:     if ( (home = getenv("ROGUEHOME")) != NULL)
                   3306:     {
                   3307:         if (*home)
                   3308:         {
                   3309:             strncpy(path, home, PATH_MAX - 20);
                   3310:
                   3311:             end = &path[strlen(path)-1];
                   3312:
                   3313:
                   3314:             while( (end >= path) && ((*end == '/') || (*end == '\\')))
                   3315:                 *end-- = '\0';
                   3316:
                   3317:             if (directory_exists(path))
                   3318:                 return(path);
                   3319:         }
                   3320:     }
                   3321:
                   3322:     if (directory_exists("/var/games/roguelike"))
                   3323:         return("/var/games/roguelike");
                   3324:     if (directory_exists("/var/lib/roguelike"))
                   3325:         return("/var/lib/roguelike");
                   3326:     if (directory_exists("/var/roguelike"))
                   3327:         return("/var/roguelike");
                   3328:     if (directory_exists("/usr/games/lib"))
                   3329:         return("/usr/games/lib");
                   3330:     if (directory_exists("/games/roguelik"))
                   3331:         return("/games/roguelik");
                   3332:
                   3333:     return("");
                   3334: }
                   3335:
                   3336: char *
                   3337: md_getshell(void)
                   3338: {
                   3339:     static char shell[PATH_MAX];
                   3340:     char *s = NULL;
                   3341: #ifdef _WIN32
                   3342:     char *def = "C:\\WINDOWS\\SYSTEM32\\CMD.EXE";
                   3343: #elif defined(__DJGPP__)
                   3344:     char *def = "C:\\COMMAND.COM";
                   3345: #else
                   3346:     char *def = "/bin/sh";
                   3347:     struct passwd *pw;
                   3348:     pw = getpwuid(getuid());
                   3349:     if (pw != NULL)
                   3350:         s = pw->pw_shell;
                   3351: #endif
                   3352:     if ((s == NULL) || (*s == '\0'))
                   3353:         if ( (s = getenv("COMSPEC")) == NULL)
                   3354:             if ( (s = getenv("SHELL")) == NULL)
                   3355:                 if ( (s = getenv("SystemRoot")) == NULL)
                   3356:                     s = def;
                   3357:
                   3358:     strncpy(shell,s,PATH_MAX);
                   3359:     shell[PATH_MAX-1] = 0;
                   3360:
                   3361:     return(shell);
                   3362: }
                   3363:
                   3364: char *
                   3365: md_gethostname(void)
                   3366: {
                   3367:     static char nodename[80];
                   3368:     char *n = NULL;
                   3369: #if !defined(_WIN32) && !defined(__DJGPP__)
                   3370:     struct utsname ourname;
                   3371:
                   3372:     if (uname(&ourname) == 0)
                   3373:         n = ourname.nodename;
                   3374: #endif
                   3375:     if ((n == NULL) || (*n == '\0'))
                   3376:         if ( (n = getenv("COMPUTERNAME")) == NULL)
                   3377:             if ( (n = getenv("HOSTNAME")) == NULL)
                   3378:                 n = "localhost";
                   3379:
                   3380:     strncpy(nodename, n, 80);
                   3381:     nodename[79] = 0;
                   3382:
                   3383:     return(nodename);
                   3384: }
                   3385:
                   3386: int
                   3387: md_shellescape(void)
                   3388: {
                   3389: #if (!defined(_WIN32) && !defined(__DJGPP__))
                   3390:     int ret_status;
                   3391:        int pid;
                   3392: #endif
                   3393:     char *sh;
                   3394:
                   3395:        sh = md_getshell();
                   3396:
                   3397: #if defined(_WIN32)
                   3398:     return(_spawnl(_P_WAIT,sh,"shell",NULL,0));
                   3399: #elif defined(__DJGPP__)
                   3400:     return ( spawnl(P_WAIT,sh,"shell",NULL,0) );
                   3401: #else
                   3402:     while((pid = fork()) < 0)
                   3403:         sleep(1);
                   3404:
                   3405:     if (pid == 0) /* Shell Process */
                   3406:     {
                   3407:         /*
                   3408:          * Set back to original user, just in case
                   3409:          */
                   3410:         setuid(getuid());
                   3411:         setgid(getgid());
                   3412:         execl(sh == NULL ? "/bin/sh" : sh, "shell", "-i", 0);
                   3413:         perror("No shelly");
                   3414:         _exit(-1);
                   3415:     }
                   3416:     else /* Application */
                   3417:     {
                   3418:         while (wait(&ret_status) != pid)
                   3419:             continue;
                   3420:     }
                   3421:
                   3422:     return(ret_status);
                   3423: #endif
                   3424: }
                   3425:
                   3426: int
                   3427: md_erasechar(void)
                   3428: {
                   3429: /*
                   3430:     return(_tty.sg_erase);
                   3431:     return(_tty.c_cc[VERASE]);
                   3432: */
                   3433:     return(erasechar());
                   3434: }
                   3435:
                   3436: int
                   3437: md_killchar(void)
                   3438: {
                   3439: /*
                   3440:     return(_tty.sg_kill);
                   3441:     return(_tty.c_cc[VKILL]);
                   3442: */
                   3443:     return(killchar());
                   3444: }
                   3445:
                   3446: int md_endian = 0x01020304;
                   3447:
                   3448: unsigned long int
                   3449: md_ntohl(unsigned long int x)
                   3450: {
                   3451: #ifndef HAVE_ARPA_INET_H
                   3452:     if ( *((char *)&md_endian) == 0x01 )
                   3453:         return(x);
                   3454:     else
                   3455:         return( ((x & 0x000000ffU) << 24) |
                   3456:                 ((x & 0x0000ff00U) <<  8) |
                   3457:                 ((x & 0x00ff0000U) >>  8) |
                   3458:                 ((x & 0xff000000U) >> 24) );
                   3459: #else
                   3460:     return( ntohl(x) );
                   3461: #endif
                   3462: }
                   3463:
                   3464: unsigned long int
                   3465: md_htonl(unsigned long int x)
                   3466: {
                   3467: #ifndef HAVE_ARPA_INET_H
                   3468:     if ( *((char *)&md_endian) == 0x01 )
                   3469:         return(x);
                   3470:     else
                   3471:         return( ((x & 0x000000ffU) << 24) |
                   3472:                 ((x & 0x0000ff00U) <<  8) |
                   3473:                 ((x & 0x00ff0000U) >>  8) |
                   3474:                 ((x & 0xff000000U) >> 24) );
                   3475: #else
                   3476:     return( htonl(x) );
                   3477: #endif
                   3478: }
                   3479:
                   3480: void
                   3481: md_init(void)
                   3482: {
                   3483: #ifdef __INTERIX
                   3484:     char *term;
                   3485:
                   3486:     term = getenv("TERM");
                   3487:
                   3488:     if (term == NULL)
                   3489:         setenv("TERM","interix");
                   3490: #endif
                   3491: #if defined(__DJGPP__) || defined(_WIN32)
                   3492:     _fmode = _O_BINARY;
                   3493: #endif
                   3494: }
                   3495:
                   3496: char *
                   3497: md_getpass(char *prompt)
                   3498: {
                   3499: #ifdef _WIN32
                   3500:     static char password_buffer[9];
                   3501:     char *p = password_buffer;
                   3502:     int c, count = 0;
                   3503:     int max_length = 9;
                   3504:
                   3505:     fflush(stdout);
                   3506:     /* If we can't prompt, abort */
                   3507:     if (fputs(prompt, stderr) < 0)
                   3508:     {
                   3509:         *p = '\0';
                   3510:         return NULL;
                   3511:     }
                   3512:
                   3513:     for(;;)
                   3514:     {
                   3515:         /* Get a character with no echo */
                   3516:         c = _getch();
                   3517:
                   3518:         /* Exit on interrupt (^c or ^break) */
                   3519:         if (c == '\003' || c == 0x100)
                   3520:             exit(1);
                   3521:
                   3522:         /* Terminate on end of line or file (^j, ^m, ^d, ^z) */
                   3523:         if (c == '\r' || c == '\n' || c == '\004' || c == '\032')
                   3524:             break;
                   3525:
                   3526:         /* Back up on backspace */
                   3527:         if (c == '\b')
                   3528:         {
                   3529:             if (count)
                   3530:                 count--;
                   3531:             else if (p > password_buffer)
                   3532:                p--;
                   3533:             continue;
                   3534:         }
                   3535:
                   3536:         /* Ignore DOS extended characters */
                   3537:         if ((c & 0xff) != c)
                   3538:             continue;
                   3539:
                   3540:         /* Add to password if it isn't full */
                   3541:         if (p < password_buffer + max_length - 1)
                   3542:             *p++ = c;
                   3543:         else
                   3544:             count++;
                   3545:     }
                   3546:    *p = '\0';
                   3547:
                   3548:    fputc('\n', stderr);
                   3549:
                   3550:    return password_buffer;
                   3551: #else
                   3552:    return( (char *) getpass(prompt) );
                   3553: #endif
                   3554: }
                   3555:
                   3556: #ifdef SIGTSTP
                   3557:
                   3558: /*
                   3559:  * handle stop and start signals
                   3560:  */
                   3561:
                   3562: /*UNUSED*/
                   3563: void
                   3564: tstp(int a)
                   3565: {
                   3566:     mvcur(0, cols - 1, lines - 1, 0);
                   3567:     fflush(stdout);
                   3568:     kill(0, SIGTSTP);
                   3569:     signal(SIGTSTP, tstp);
                   3570:     crmode();
                   3571:     noecho();
                   3572:     clearok(curscr, TRUE);
                   3573:     touchwin(cw);
                   3574:     draw(cw);
                   3575:     flushinp();
                   3576: }
                   3577: #endif
                   3578:
                   3579: void
                   3580: md_setup(void)
                   3581: {
                   3582: #ifdef SIGTSTP
                   3583:     signal(SIGTSTP, tstp);
                   3584: #endif
                   3585: #ifdef SIGHUP
                   3586:     signal(SIGHUP, auto_save);
                   3587: #endif
                   3588:     signal(SIGTERM, auto_save);
                   3589:     signal(SIGINT, quit);
                   3590: #ifdef SIGQUIT
                   3591:     signal(SIGQUIT, endit);
                   3592: #endif
                   3593: #if defined(__CYGWIN__) || defined(__MSYS__)
                   3594:     ESCDELAY = 250;
                   3595: #endif
                   3596:     nonl();
                   3597:     crmode();                        /* Cbreak mode */
                   3598:     noecho();                           /* Echo off */
                   3599: }
                   3600:
                   3601: void
                   3602: md_normaluser(void)
                   3603: {
                   3604: #ifndef _WIN32
                   3605:     setuid(getuid());
                   3606:     setgid(getgid());
                   3607: #endif
                   3608: }
                   3609:
                   3610: int
                   3611: md_fileno(FILE *fp)
                   3612: {
                   3613: #ifdef _WIN32
                   3614:     return( _fileno(fp) );
                   3615: #else
                   3616:     return( fileno(fp) );
                   3617: #endif
                   3618: }
                   3619:
                   3620: int
                   3621: md_unlink(char *file)
                   3622: {
                   3623: #ifdef _WIN32
                   3624:     chmod(file, 0600);
                   3625:     return( _unlink(file) );
                   3626: #else
                   3627:     return(unlink(file));
                   3628: #endif
                   3629: }
                   3630:
                   3631: unsigned int
                   3632: md_random_seed(void)
                   3633: {
                   3634:     unsigned int seed;
                   3635:     seed = (unsigned int) time((time_t *) NULL);
                   3636: #ifdef _WIN32
                   3637:     seed += _getpid();
                   3638: #else
                   3639:     seed += getpid();
                   3640: #endif
                   3641:     return seed;
                   3642: }

CVSweb