home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume10 / nethack3p9 / part27 < prev    next >
Internet Message Format  |  1990-07-27  |  60KB

  1. Path: uunet!cs.utexas.edu!rice!uw-beaver!zephyr.ens.tek.com!tekred!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v10i072:  nethack3p9 -  display oriented dungeons & dragons (Ver. 3.0i), Part27/56
  5. Message-ID: <5930@tekred.CNA.TEK.COM>
  6. Date: 12 Jul 90 16:03:29 GMT
  7. Sender: news@tekred.CNA.TEK.COM
  8. Lines: 2495
  9. Approved: billr@saab.CNA.TEK.COM
  10.  
  11. Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
  12. Posting-number: Volume 10, Issue 72
  13. Archive-name: nethack3p9/Part27
  14. Supersedes: NetHack3: Volume 7, Issue 56-93
  15.  
  16.  
  17.  
  18. #! /bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 27 (of 56)."
  25. # Contents:  others/msdos.c src/restore.c
  26. # Wrapped by billr@saab on Wed Jul 11 17:11:32 1990
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'others/msdos.c' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'others/msdos.c'\"
  30. else
  31. echo shar: Extracting \"'others/msdos.c'\" \(30281 characters\)
  32. sed "s/^X//" >'others/msdos.c' <<'END_OF_FILE'
  33. X/*    SCCS Id: @(#)msdos.c    3.0    89/12/26
  34. X/* NetHack may be freely redistributed.  See license for details. */
  35. X/* An assortment of MSDOS functions.
  36. X */
  37. X
  38. X#define NEED_VARARGS
  39. X#include "hack.h"
  40. X
  41. X#ifdef MSDOS
  42. X
  43. X# ifdef TOS
  44. X#  include <osbind.h>
  45. X#  ifndef WORD
  46. X#    define WORD short        /* 16 bits -- redefine if necessary */
  47. X#  endif
  48. X# else
  49. X#  ifdef __TURBOC__    /* avoid incompatible redeclaration */
  50. X#   undef getdate
  51. X#  endif
  52. X#  include <dos.h>
  53. X# endif
  54. X# ifdef OS2
  55. X#  include "def_os2.h"   /* OS2 definitions (Timo Hakulinen) */
  56. X# endif
  57. X
  58. X#include <ctype.h>
  59. X#include <fcntl.h>
  60. X#include <process.h>
  61. X
  62. Xstatic char NDECL(DOSgetch);
  63. X# ifdef DGK
  64. Xstatic char NDECL(BIOSgetch);
  65. X# endif
  66. X# ifdef TOS
  67. Xstatic void NDECL(init_aline);
  68. Xchar *_a_line;            /* for Line A variables */
  69. X# else
  70. Xstatic unsigned int FDECL(ioctl, (int,int,unsigned));
  71. Xstatic boolean NDECL(comspec_exists);
  72. X# endif
  73. X
  74. Xstatic int FDECL(findfirst, (char *));
  75. Xstatic int NDECL(findnext);
  76. Xstatic boolean NDECL(record_exists);
  77. X# if !defined(TOS) && !defined(__TURBOC__) && !defined(OS2)
  78. Xstatic char NDECL(switchar);
  79. X# endif
  80. X# ifndef OS2
  81. Xstatic char * NDECL(getdta);
  82. X# endif
  83. X
  84. Xvoid
  85. Xflushout()
  86. X{
  87. X    (void) fflush(stdout);
  88. X    return;
  89. X}
  90. X
  91. Xint
  92. Xtgetch() {
  93. X    char ch;
  94. X
  95. X# ifdef DGK
  96. X    /* BIOSgetch can use the numeric key pad on IBM compatibles. */
  97. X    if (flags.IBMBIOS)
  98. X        ch = BIOSgetch();
  99. X    else
  100. X# endif
  101. X        ch = DOSgetch();
  102. X    return ((ch == '\r') ? '\n' : ch);
  103. X}
  104. X
  105. X# if !defined(OS2) && !defined(TOS)
  106. X/*
  107. X * MS-DOS functions
  108. X */
  109. X#define DIRECT_INPUT    0x07    /* Unfiltered Character Input Without Echo */
  110. X#define FATINFO     0x1B    /* Get Default Drive Data */
  111. X/* MS-DOS 2.0+: */
  112. X#define GETDTA        0x2F    /* Get DTA Address */
  113. X#define FREESPACE    0x36    /* Get Drive Allocation Info */
  114. X#define GETSWITCHAR    0x3700    /* Get Switch Character */
  115. X#define FINDFIRST    0x4E    /* Find First File */
  116. X#define FINDNEXT    0x4F    /* Find Next File */
  117. X#define SETFILETIME    0x5701    /* Set File Date & Time */
  118. X/*
  119. X * BIOS interrupts
  120. X */
  121. X#define KEYBRD_BIOS    0x16
  122. X#define VIDEO_BIOS    0x10
  123. X/*
  124. X * Keyboard BIOS functions
  125. X */
  126. X#define READCHAR    0x00    /* Read Character from Keyboard */
  127. X#define GETKEYFLAGS    0x02    /* Get Keyboard Flags */
  128. X/*
  129. X * Video BIOS functions
  130. X */
  131. X#define SETCURPOS    0x02    /* Set Cursor Position */
  132. X#define GETMODE     0x0f    /* Get Video Mode */
  133. X#define FONTINFO    0x1130    /* Get Font Info */
  134. X# endif
  135. X
  136. X
  137. X/*
  138. X *  Keyboard translation tables.
  139. X */
  140. X#  ifdef TOS
  141. X#define KEYPADLO    0x61
  142. X#define KEYPADHI    0x71
  143. X#  else
  144. X#define KEYPADLO    0x47
  145. X#define KEYPADHI    0x53
  146. X#  endif
  147. X
  148. X#define PADKEYS     (KEYPADHI - KEYPADLO + 1)
  149. X#define iskeypad(x)    (KEYPADLO <= (x) && (x) <= KEYPADHI)
  150. X
  151. X/*
  152. X * Keypad keys are translated to the normal values below.
  153. X * When IBM_BIOS is active, shifted keypad keys are translated to the
  154. X *    shift values below.
  155. X */
  156. Xstatic const struct pad {
  157. X    char normal, shift, cntrl;
  158. X} keypad[PADKEYS] = {
  159. X#  ifdef TOS
  160. X            {C('['), 'Q', C('[')},        /* UNDO */
  161. X            {'?', '/', '?'},        /* HELP */
  162. X            {'(', 'a', '('},        /* ( */
  163. X            {')', 'w', ')'},        /* ) */
  164. X            {'/', '/', '/'},        /* / */
  165. X            {C('p'), '$', C('p')},        /* * */
  166. X#  endif
  167. X            {'y', 'Y', C('y')},        /* 7 */
  168. X            {'k', 'K', C('k')},        /* 8 */
  169. X            {'u', 'U', C('u')},        /* 9 */
  170. X#  ifndef TOS
  171. X            {'m', C('p'), C('p')},        /* - */
  172. X#  endif
  173. X            {'h', 'H', C('h')},        /* 4 */
  174. X#  ifdef TOS
  175. X            {'.', '.', '.'},
  176. X#  else
  177. X            {'g', 'g', 'g'},        /* 5 */
  178. X#  endif
  179. X            {'l', 'L', C('l')},        /* 6 */
  180. X#  ifndef TOS
  181. X            {'p', 'P', C('p')},        /* + */
  182. X#  endif
  183. X            {'b', 'B', C('b')},        /* 1 */
  184. X            {'j', 'J', C('j')},        /* 2 */
  185. X            {'n', 'N', C('n')},        /* 3 */
  186. X            {'i', 'I', C('i')},        /* Ins */
  187. X            {'.', ':', ':'}            /* Del */
  188. X}, numpad[PADKEYS] = {
  189. X#  ifdef TOS
  190. X            {C('['), 'Q', C('[')}    ,    /* UNDO */
  191. X            {'?', '/', '?'},        /* HELP */
  192. X            {'(', 'a', '('},        /* ( */
  193. X            {')', 'w', ')'},        /* ) */
  194. X            {'/', '/', '/'},        /* / */
  195. X            {C('p'), '$', C('p')},        /* * */
  196. X#  endif
  197. X            {'7', M('7'), '7'},        /* 7 */
  198. X            {'8', M('8'), '8'},        /* 8 */
  199. X            {'9', M('9'), '9'},        /* 9 */
  200. X#  ifndef TOS
  201. X            {'m', C('p'), C('p')},        /* - */
  202. X#  endif
  203. X            {'4', M('4'), '4'},        /* 4 */
  204. X#  ifdef TOS
  205. X            {'.', '.', '.'},        /* 5 */
  206. X#  else
  207. X            {'g', 'G', 'g'},        /* 5 */
  208. X#  endif
  209. X            {'6', M('6'), '6'},        /* 6 */
  210. X#  ifndef TOS
  211. X            {'p', 'P', C('p')},        /* + */
  212. X#  endif
  213. X            {'1', M('1'), '1'},        /* 1 */
  214. X            {'2', M('2'), '2'},        /* 2 */
  215. X            {'3', M('3'), '3'},        /* 3 */
  216. X            {'i', 'I', C('i')},        /* Ins */
  217. X            {'.', ':', ':'}            /* Del */
  218. X};
  219. X
  220. X/*
  221. X * Unlike Ctrl-letter, the Alt-letter keystrokes have no specific ASCII
  222. X * meaning unless assigned one by a keyboard conversion table, so the
  223. X * keyboard BIOS normally does not return a character code when Alt-letter
  224. X * is pressed.    So, to interpret unassigned Alt-letters, we must use a
  225. X * scan code table to translate the scan code into a letter, then set the
  226. X * "meta" bit for it.  -3.
  227. X */
  228. X#define SCANLO        0x10
  229. X#define SCANHI        0x32
  230. X#define SCANKEYS    (SCANHI - SCANLO + 1)
  231. X#define inmap(x)    (SCANLO <= (x) && (x) <= SCANHI)
  232. X
  233. Xstatic const char scanmap[SCANKEYS] = {     /* ... */
  234. X    'q','w','e','r','t','y','u','i','o','p','[',']', '\n',
  235. X    0, 'a','s','d','f','g','h','j','k','l',';','\'', '`',
  236. X    0, '\\', 'z','x','c','v','b','N','m'     /* ... */
  237. X};
  238. X
  239. X# ifdef DGK
  240. X/*
  241. X * BIOSgetch gets keys directly with a BIOS call.
  242. X */
  243. X#define SHIFT        (0x1 | 0x2)
  244. X#define CTRL        0x4
  245. X#define ALT        0x8
  246. X
  247. Xstatic char
  248. XBIOSgetch() {
  249. X    unsigned char scan, shift, ch;
  250. X    const struct pad *kpad;
  251. X
  252. X#  ifdef OS2
  253. X    KBDKEYINFO CharData;
  254. X    USHORT IOWait = 0;
  255. X    HKBD KbdHandle = 0;
  256. X
  257. X    KbdCharIn(&CharData,IOWait,KbdHandle);
  258. X    ch = CharData.chChar;
  259. X    scan = CharData.chScan;
  260. X    shift = CharData.fsState;
  261. X#  else /* OS2 */
  262. X#   ifdef TOS
  263. X    long  x;
  264. X#   else
  265. X    union REGS regs;
  266. X#   endif
  267. X
  268. X    /* Get scan code.
  269. X     */
  270. X#   ifdef TOS
  271. X    x = Crawcin();
  272. X    ch = x & 0x0ff;
  273. X    scan = (x & 0x00ff0000L) >> 16;
  274. X#   else
  275. X    regs.h.ah = READCHAR;
  276. X    int86(KEYBRD_BIOS, ®s, ®s);
  277. X    ch = regs.h.al;
  278. X    scan = regs.h.ah;
  279. X#   endif
  280. X    /* Get shift status.
  281. X     */
  282. X#   ifdef TOS
  283. X    shift = Kbshift(-1);
  284. X#   else
  285. X    regs.h.ah = GETKEYFLAGS;
  286. X    int86(KEYBRD_BIOS, ®s, ®s);
  287. X    shift = regs.h.al;
  288. X#   endif
  289. X#  endif /* OS2 */
  290. X
  291. X    /* Translate keypad keys */
  292. X    if (iskeypad(scan)) {
  293. X        kpad = flags.num_pad ? numpad : keypad;
  294. X        if (shift & SHIFT)
  295. X            ch = kpad[scan - KEYPADLO].shift;
  296. X        else if (shift & CTRL)
  297. X            ch = kpad[scan - KEYPADLO].cntrl;
  298. X        else
  299. X            ch = kpad[scan - KEYPADLO].normal;
  300. X    }
  301. X    /* Translate unassigned Alt-letters */
  302. X    if ((shift & ALT) && !ch) {
  303. X        if (inmap(scan))
  304. X            ch = scanmap[scan - SCANLO];
  305. X        return (isprint(ch) ? M(ch) : ch);
  306. X    }
  307. X    return ch;
  308. X}
  309. X
  310. Xstatic char
  311. XDOSgetch() {
  312. X# ifdef TOS
  313. X    return (Crawcin() & 0x007f);
  314. X# else
  315. X#  ifdef OS2
  316. X    KBDKEYINFO CharData;
  317. X    USHORT IOWait = 0;
  318. X    HKBD KbdHandle = 0;
  319. X
  320. X    KbdCharIn(&CharData,IOWait,KbdHandle);
  321. X    if (CharData.chChar == 0) {    /* an extended code -- not yet supported */
  322. X        KbdCharIn(&CharData,IOWait,KbdHandle);       /* eat the next character */
  323. X        CharData.chChar = 0;        /* and return a 0 */
  324. X    }
  325. X    return (CharData.chChar);
  326. X#  else
  327. X    union REGS regs;
  328. X    char ch;
  329. X    struct pad (*kpad)[PADKEYS];
  330. X
  331. X    regs.h.ah = DIRECT_INPUT;
  332. X    intdos(®s, ®s);
  333. X    ch = regs.h.al;
  334. X
  335. X    /*
  336. X     * The extended codes for Alt-shifted letters, and unshifted keypad
  337. X     * and function keys, correspond to the scan codes.  So we can still
  338. X     * translate the unshifted cursor keys and Alt-letters.  -3.
  339. X     */
  340. X    if (ch == 0) {        /* an extended key */
  341. X        regs.h.ah = DIRECT_INPUT;
  342. X        intdos(®s, ®s);    /* get the extended key code */
  343. X        ch = regs.h.al;
  344. X
  345. X        if (iskeypad(ch)) {    /* unshifted keypad keys */
  346. X            kpad = (void *)(flags.num_pad ? numpad : keypad);
  347. X            ch = (*kpad)[ch - KEYPADLO].normal;
  348. X        } else if (inmap(ch)) { /* Alt-letters */
  349. X            ch = scanmap[ch - SCANLO];
  350. X            if (isprint(ch)) ch = M(ch);
  351. X        } else ch = 0;        /* munch it */
  352. X    }
  353. X    return (ch);
  354. X#  endif /* OS2 */
  355. X# endif /* TOS */
  356. X}
  357. X
  358. X
  359. X#  ifndef TOS
  360. X
  361. X#   ifdef __TURBOC__
  362. X#define switchar()    (char)getswitchar()
  363. X#   else
  364. X#    ifndef OS2
  365. Xstatic char
  366. Xswitchar()
  367. X{
  368. X    union REGS regs;
  369. X
  370. X    regs.x.ax = GETSWITCHAR;
  371. X    intdos(®s, ®s);
  372. X    return regs.h.dl;
  373. X}
  374. X#    endif /* OS2 */
  375. X#   endif /* __TURBOC__ */
  376. X# endif  /* TOS */
  377. X
  378. Xstatic const char *COMSPEC = 
  379. X# ifdef TOS
  380. X"SHELL";
  381. X# else
  382. X"COMSPEC";
  383. X# endif
  384. X
  385. X#define getcomspec() getenv(COMSPEC)
  386. X
  387. X# ifdef SHELL
  388. Xint
  389. Xdosh() {
  390. X    extern char orgdir[];
  391. X    char *comspec;
  392. X
  393. X    if (comspec = getcomspec()) {
  394. X#  if defined(DGK) && !defined(TOS)    /* TOS has a variety of shells */
  395. X        settty("To return to NetHack, enter \"exit\" at the DOS prompt.\n");
  396. X#  else
  397. X        settty((char *)0);
  398. X#  endif /* DGK */
  399. X        chdirx(orgdir, 0);
  400. X        if (spawnl(P_WAIT, comspec, comspec, NULL) < 0) {
  401. X            Printf("\nCan't spawn \"%s\"!\n", comspec);
  402. X            flags.toplin = 0;
  403. X            more();
  404. X        }
  405. X#ifdef TOS
  406. X/* Some shells (e.g. Gulam) turn the cursor off when they exit */
  407. X        if (flags.IBMBIOS) {
  408. X            (void)Cursconf(1, -1);
  409. X            get_scr_size(); /* maybe they changed the screen */
  410. X        }
  411. X#else
  412. X        gettty(); /* ctrl-P might get turned back on (TH) */
  413. X        get_scr_size(); /* maybe the screen mode changed (TH) */
  414. X#endif
  415. X        chdirx(hackdir, 0);
  416. X        start_screen();
  417. X        docrt();
  418. X    } else
  419. X#  ifdef OS2
  420. X        pline("Can't execute CMD.EXE");
  421. X#  else
  422. X#   ifdef TOS
  423. X        pline("Can't find SHELL.");
  424. X#   else
  425. X        pline("Can't find COMSPEC.");
  426. X#   endif
  427. X#  endif /* OS2 */
  428. X    return 0;
  429. X}
  430. X# endif /* SHELL */
  431. X
  432. X#ifndef TOS
  433. X
  434. Xlong
  435. Xfreediskspace(path)
  436. Xchar *path;
  437. X{
  438. X#   ifdef OS2
  439. X    struct {
  440. X        ULONG  idFileSystem;
  441. X        ULONG  cSectorUnit;
  442. X        ULONG  cUnit;
  443. X        ULONG  cUnitAvail;
  444. X        USHORT cbSector;
  445. X    } FSInfoBuf;
  446. X    USHORT DriveNumber, FSInfoLevel = 1, res;
  447. X
  448. X    if (path[0] && path[1] == ':')
  449. X        DriveNumber = (toupper(path[0]) - 'A') + 1;
  450. X    else
  451. X        DriveNumber = 0;
  452. X    res = DosQFSInfo(DriveNumber,FSInfoLevel,(PBYTE)&FSInfoBuf,sizeof(FSInfoBuf));
  453. X    if (res)
  454. X        return -1L;        /* error */
  455. X    else
  456. X        return ((long) FSInfoBuf.cSectorUnit * FSInfoBuf.cUnitAvail *
  457. X                   FSInfoBuf.cbSector);
  458. X#   else /* OS2 */
  459. X    union REGS regs;
  460. X
  461. X    regs.h.ah = FREESPACE;
  462. X    if (path[0] && path[1] == ':')
  463. X        regs.h.dl = (toupper(path[0]) - 'A') + 1;
  464. X    else
  465. X        regs.h.dl = 0;
  466. X    intdos(®s, ®s);
  467. X    if (regs.x.ax == 0xFFFF)
  468. X        return -1L;        /* bad drive number */
  469. X    else
  470. X        return ((long) regs.x.bx * regs.x.cx * regs.x.ax);
  471. X#   endif /* OS2 */
  472. X}
  473. X
  474. X#   ifdef OS2
  475. XFILEFINDBUF ResultBuf;
  476. XHDIR DirHandle;
  477. X#   endif
  478. X
  479. X/* Functions to get filenames using wildcards
  480. X */
  481. Xstatic int
  482. Xfindfirst(path)
  483. Xchar *path;
  484. X{
  485. X#   ifdef OS2
  486. X    USHORT res, SearchCount = 1;
  487. X
  488. X    DirHandle = 1;
  489. X    res = DosFindFirst((PSZ)path,&DirHandle,0,&ResultBuf,sizeof(FILEFINDBUF),&SearchCount,0L);
  490. X    return(!res);
  491. X#   else
  492. X    union REGS regs;
  493. X    struct SREGS sregs;
  494. X
  495. X    regs.h.ah = FINDFIRST;
  496. X    regs.x.cx = 0;        /* attribute: normal files */
  497. X    regs.x.dx = FP_OFF(path);
  498. X    sregs.ds = FP_SEG(path);
  499. X    intdosx(®s, ®s, &sregs);
  500. X    return !regs.x.cflag;
  501. X#   endif /* OS2 */
  502. X}
  503. X
  504. Xstatic int
  505. Xfindnext() {
  506. X#   ifdef OS2
  507. X    USHORT res, SearchCount = 1;
  508. X
  509. X    res = DosFindNext(DirHandle,&ResultBuf,sizeof(FILEFINDBUF),&SearchCount);
  510. X    return(!res);
  511. X#   else
  512. X    union REGS regs;
  513. X
  514. X    regs.h.ah = FINDNEXT;
  515. X    intdos(®s, ®s);
  516. X    return !regs.x.cflag;
  517. X#   endif /* OS2 */
  518. X}
  519. X
  520. X#   ifndef OS2
  521. X/* Get disk transfer area, Turbo C already has getdta */
  522. Xstatic char *
  523. Xgetdta() {
  524. X    union REGS regs;
  525. X    struct SREGS sregs;
  526. X    char *ret;
  527. X
  528. X    regs.h.ah = GETDTA;
  529. X    intdosx(®s, ®s, &sregs);
  530. X#    ifdef MK_FP
  531. X    ret = MK_FP(sregs.es, regs.x.bx);
  532. X#    else
  533. X    FP_OFF(ret) = regs.x.bx;
  534. X    FP_SEG(ret) = sregs.es;
  535. X#    endif
  536. X    return ret;
  537. X}
  538. X#   endif /* OS2 */
  539. X
  540. X#  else /* TOS */
  541. X
  542. Xlong
  543. Xfreediskspace(path)
  544. Xchar *path;
  545. X{
  546. X    int drive = 0;
  547. X    struct {
  548. X        long freal; /*free allocation units*/
  549. X        long total; /*total number of allocation units*/
  550. X        long bps;   /*bytes per sector*/
  551. X        long pspal; /*physical sectors per allocation unit*/
  552. X    } freespace;
  553. X    if (path[0] && path[1] == ':')
  554. X        drive = (toupper(path[0]) - 'A') + 1;
  555. X    if (Dfree(&freespace,drive)<0) return -1;
  556. X    return freespace.freal*freespace.bps*freespace.pspal;
  557. X}
  558. X
  559. Xstatic int
  560. Xfindfirst(path)
  561. Xchar *path;
  562. X{
  563. X    return (Fsfirst(path, 0) == 0);
  564. X}
  565. X
  566. Xstatic int findnext() {
  567. X    return (Fsnext() == 0);
  568. X}
  569. X
  570. Xstatic char *
  571. Xgetdta() {
  572. X    return (char *) Fgetdta();
  573. X}
  574. X
  575. X#  endif /* TOS */
  576. X
  577. Xlong
  578. Xfilesize(file)
  579. Xchar *file;
  580. X{
  581. X#  ifndef OS2
  582. X    char *dta;
  583. X#  endif
  584. X
  585. X    if (findfirst(file)) {
  586. X#  ifdef OS2
  587. X        return  (* (long *) (ResultBuf.cbFileAlloc));
  588. X#  else
  589. X        dta = getdta();
  590. X        return  (* (long *) (dta + 26));
  591. X#  endif
  592. X    } else
  593. X        return -1L;
  594. X}
  595. X
  596. Xvoid
  597. Xeraseall(path, files)
  598. Xconst char *path, *files;
  599. X{
  600. X#  ifndef OS2
  601. X    char *dta;
  602. X#  endif
  603. X    char buf[PATHLEN];
  604. X
  605. X#  ifndef OS2
  606. X    dta = getdta();
  607. X#  endif
  608. X    Sprintf(buf, "%s%s", path, files);
  609. X    if (findfirst(buf))
  610. X        do {
  611. X            Sprintf(buf, "%s%s", path,
  612. X#  ifdef OS2
  613. X                ResultBuf.achName
  614. X#  else
  615. X                dta + 30
  616. X#  endif
  617. X                );
  618. X            (void) unlink(buf);
  619. X        } while (findnext());
  620. X    return;
  621. X}
  622. X
  623. X/* Rewritten for version 3.3 to be faster
  624. X */
  625. Xvoid
  626. Xcopybones(mode)
  627. Xint mode;
  628. X{
  629. X    char from[PATHLEN], to[PATHLEN], last[13];
  630. X    char *frompath, *topath;
  631. X#  ifndef OS2
  632. X    char *dta;
  633. X#  endif
  634. X#  ifndef TOS
  635. X    int status;
  636. X    char copy[8], *comspec;
  637. X    extern saveprompt;
  638. X#  endif
  639. X
  640. X    if (!ramdisk)
  641. X        return;
  642. X
  643. X    /* Find the name of the last file to be transferred
  644. X     */
  645. X    frompath = (mode != TOPERM) ? permbones : levels;
  646. X#  ifndef OS2
  647. X    dta = getdta();
  648. X#  endif
  649. X    last[0] = '\0';
  650. X    Sprintf(from, "%s%s", frompath, allbones);
  651. X    topath = (mode == TOPERM) ? permbones : levels;
  652. X#  ifdef TOS
  653. X    eraseall(topath, allbones);
  654. X#  endif
  655. X    if (findfirst(from))
  656. X        do {
  657. X#  ifdef TOS
  658. X            Sprintf(from, "%s%s", frompath, dta+30); 
  659. X            Sprintf(to, "%s%s", topath, dta+30);
  660. X            if (_copyfile(from, to))
  661. X                goto error_copying;
  662. X#  endif
  663. X            Strcpy(last,
  664. X#  ifdef OS2
  665. X                ResultBuf.achName
  666. X#  else
  667. X                dta + 30
  668. X#  endif
  669. X                );
  670. X        } while (findnext());
  671. X#  ifdef TOS
  672. X    else
  673. X        return;
  674. X#  else
  675. X    if (last[0]) {
  676. X        Sprintf(copy, "%cC copy",
  677. X#   ifdef OS2
  678. X            '/'
  679. X#   else
  680. X            switchar()
  681. X#   endif
  682. X            );
  683. X
  684. X        /* Remove any bones files in `to' directory.
  685. X         */
  686. X        eraseall(topath, allbones);
  687. X
  688. X        /* Copy `from' to `to' */
  689. X        Sprintf(to, "%s%s", topath, allbones);
  690. X        comspec = getcomspec();
  691. X        status =spawnl(P_WAIT, comspec, comspec, copy, from,
  692. X            to, "> nul", NULL);
  693. X    } else
  694. X        return;
  695. X#  endif /* TOS */
  696. X
  697. X    /* See if the last file got there.  If so, remove the ramdisk bones
  698. X     * files.
  699. X     */
  700. X    Sprintf(to, "%s%s", topath, last);
  701. X    if (findfirst(to)) {
  702. X        if (mode == TOPERM)
  703. X            eraseall(frompath, allbones);
  704. X        return;
  705. X    }
  706. X
  707. X#  ifdef TOS
  708. Xerror_copying:
  709. X#  endif
  710. X    /* Last file didn't get there.
  711. X     */
  712. X    Sprintf(to, "%s%s", topath, allbones);
  713. X    msmsg("Can't copy \"%s\" to \"%s\" -- ", from, to);
  714. X#  ifndef TOS
  715. X    if (status < 0)
  716. X        msmsg("can't spawn \"%s\"!", comspec);
  717. X    else
  718. X#  endif
  719. X        msmsg((freediskspace(topath) < filesize(from)) ?
  720. X            "insufficient disk space." : "bad path(s)?");
  721. X    if (mode == TOPERM) {
  722. X        msmsg("Bones will be left in \"%s\"\n",
  723. X            *levels ? levels : hackdir);
  724. X    } else {
  725. X        /* Remove all bones files on the RAMdisk */
  726. X        eraseall(levels, allbones);
  727. X        playwoRAMdisk();
  728. X    }
  729. X    return;
  730. X}
  731. X
  732. X#if 0 /* defined(MSDOS) && !defined(TOS) && !defined(OS2) */
  733. Xboolean
  734. Xremoveable_drive(drive)
  735. Xchar drive;
  736. X/* check whether current drive is a fixed disk,
  737. X   so we don't ask the player to insert one */
  738. X{
  739. X    union REGS regs;
  740. X    char *fat_id;
  741. X
  742. X    regs.h.ah = FATINFO;
  743. X    intdos(®s, ®s);
  744. X    /* also returns size info, as
  745. X       AL (sectors/cluster) * CX (bytes/sector) * DX (clusters/disk) */
  746. X#   ifdef MK_FP
  747. X    fat_id = MK_FP(sregs.ds, regs.x.bx);
  748. X#   else
  749. X    FP_OFF(fat_id) = regs.x.bx;
  750. X    FP_SEG(fat_id) = sregs.ds;
  751. X#   endif
  752. X    return (*fat_id != 0xF8);
  753. X}
  754. X#endif /* 0 */
  755. X
  756. Xvoid
  757. XplaywoRAMdisk() {
  758. X    msmsg("Do you wish to play without a RAMdisk? ");
  759. X
  760. X    /* Set ramdisk false *before* exit-ing (because msexit calls
  761. X     * copybones)
  762. X     */
  763. X    ramdisk = FALSE;
  764. X    if (yn() != 'y') {
  765. X        settty("Be seeing you...\n");
  766. X        exit(0);
  767. X    }
  768. X    set_lock_and_bones();
  769. X    return;
  770. X}
  771. X
  772. Xint
  773. XsaveDiskPrompt(start)
  774. Xint start;
  775. X{
  776. X    extern saveprompt;
  777. X    char buf[BUFSIZ], *bp;
  778. X    int fd;
  779. X
  780. X    if (saveprompt) {
  781. X        /* Don't prompt if you can find the save file */
  782. X        if ((fd = open(SAVEF, 0)) >= 0) {
  783. X            (void) close(fd);
  784. X            return 1;
  785. X        }
  786. X        remember_topl();
  787. X        home();
  788. X        cl_end();
  789. X        msmsg("If save file is on a save disk, insert that disk now.\n");
  790. X        cl_end();
  791. X        msmsg("File name (default \"%s\"%s) ? ", SAVEF,
  792. X            start ? "" : ", <Esc> cancels save");
  793. X        getlin(buf);
  794. X        home();
  795. X        cl_end();
  796. X        curs(1, 2);
  797. X        cl_end();
  798. X        if (!start && *buf == '\033')
  799. X            return 0;
  800. X
  801. X        /* Strip any whitespace. Also, if nothing was entered except
  802. X         * whitespace, do not change the value of SAVEF.
  803. X         */
  804. X        for (bp = buf; *bp; bp++)
  805. X            if (!isspace(*bp)) {
  806. X                strncpy(SAVEF, bp, PATHLEN);
  807. X                break;
  808. X            }
  809. X    }
  810. X    return 1;
  811. X}
  812. X
  813. X/* Return 1 if the record file was found */
  814. Xstatic boolean
  815. Xrecord_exists() {
  816. X    int fd;
  817. X#  ifdef OS2_CODEVIEW
  818. X    char tmp[PATHLEN];
  819. X
  820. X    Strcpy(tmp,hackdir);
  821. X    append_slash(tmp);
  822. X    Strcat(tmp,RECORD);
  823. X    if ((fd = open(tmp, 0)) >= 0) {
  824. X#  else
  825. X    if ((fd = open(RECORD, 0)) >= 0) {
  826. X#  endif
  827. X        (void) close(fd);
  828. X        return TRUE;
  829. X    }
  830. X    return FALSE;
  831. X}
  832. X
  833. X#  ifdef TOS
  834. X#define comspec_exists() 1
  835. X#  else
  836. X/* Return 1 if the comspec was found */
  837. Xstatic boolean
  838. Xcomspec_exists() {
  839. X    int fd;
  840. X    char *comspec;
  841. X
  842. X    if (comspec = getcomspec())
  843. X        if ((fd = open(comspec, 0)) >= 0) {
  844. X            (void) close(fd);
  845. X            return TRUE;
  846. X        }
  847. X    return FALSE;
  848. X}
  849. X#  endif
  850. X
  851. X/* Prompt for game disk, then check for record file.
  852. X */
  853. Xvoid
  854. XgameDiskPrompt() {
  855. X    extern int saveprompt;
  856. X
  857. X    if (saveprompt) {
  858. X        if (record_exists() && comspec_exists())
  859. X            return;
  860. X        (void) putchar('\n');
  861. X        getreturn("when the game disk has been inserted");
  862. X    }
  863. X    if (comspec_exists() && record_exists())
  864. X        return;
  865. X
  866. X    if (!comspec_exists())
  867. X        msmsg("\n\nWARNING: can't find command processor \"%s\"!\n", getcomspec());
  868. X        if (!record_exists())
  869. X        msmsg("\n\nWARNING: can't find record file \"%s\"!\n", RECORD);
  870. X    msmsg("If the game disk is not in, insert it now.\n");
  871. X    getreturn("to continue");
  872. X    return;
  873. X}
  874. X
  875. X# endif /* DGK */
  876. X
  877. X/* Read configuration */
  878. Xvoid
  879. Xread_config_file() {
  880. X# ifdef DGK
  881. X    char    tmp_ramdisk[PATHLEN];
  882. X    extern    int saveprompt;
  883. X# else
  884. X#define fopenp fopen
  885. X# endif
  886. X    char    tmp_levels[PATHLEN];
  887. X    char    buf[BUFSZ], *bufp;
  888. X    FILE    *fp;
  889. X    extern    char plname[];
  890. X
  891. X# ifdef DGK
  892. X    tmp_ramdisk[0] = 0;
  893. X# endif
  894. X    tmp_levels[0] = 0;
  895. X    if ((fp = fopenp(configfile, "r")) == (FILE *)0) {
  896. X        msmsg("Warning: no configuration file!\n");
  897. X        getreturn("to continue");
  898. X        return;
  899. X    }
  900. X    while (fgets(buf, BUFSZ, fp)) {
  901. X        if (*buf == '#')
  902. X            continue;
  903. X
  904. X        /* remove trailing whitespace
  905. X         */
  906. X        bufp = index(buf, '\n');
  907. X        while (bufp > buf && isspace(*bufp))
  908. X            bufp--;
  909. X        if (bufp == buf)
  910. X            continue;        /* skip all-blank lines */
  911. X        else
  912. X            *(bufp + 1) = 0;    /* 0 terminate line */
  913. X
  914. X        /* find the '=' */
  915. X        if (!(bufp = strchr(buf, '='))) {
  916. X            msmsg("Bad option line: \"%s\"\n", buf);
  917. X            getreturn("to continue");
  918. X            continue;
  919. X        }
  920. X        
  921. X        /* skip  whitespace between '=' and value */
  922. X        while (isspace(*++bufp))
  923. X            ;
  924. X
  925. X        /* Go through possible variables */
  926. X        if (!strncmp(buf, "HACKDIR", 4)) {
  927. X            strncpy(hackdir, bufp, PATHLEN);
  928. X        
  929. X# ifdef DGK
  930. X        } else if (!strncmp(buf, "RAMDISK", 3)) {
  931. X            strncpy(tmp_ramdisk, bufp, PATHLEN);
  932. X# endif
  933. X
  934. X        } else if (!strncmp(buf, "LEVELS", 4)) {
  935. X            strncpy(tmp_levels, bufp, PATHLEN);
  936. X
  937. X        } else if (!strncmp(buf, "OPTIONS", 4)) {
  938. X            parseoptions(bufp, TRUE);
  939. X            if (plname[0])        /* If a name was given */
  940. X                plnamesuffix();    /* set the character class */
  941. X
  942. X        } else if (!strncmp(buf, "SAVE", 4)) {
  943. X# ifdef DGK
  944. X            char *ptr;
  945. X            if (ptr = index(bufp, ';')) {
  946. X                *ptr = '\0';
  947. X                if (*(ptr+1) == 'n' || *(ptr+1) == 'N')
  948. X                    saveprompt = FALSE;
  949. X            }
  950. X# endif /* DGK */
  951. X            (void) strncpy(SAVEF, bufp, PATHLEN);
  952. X            (void) strncpy(SAVEP, bufp, PATHLEN);
  953. X            append_slash(SAVEF);
  954. X            append_slash(SAVEP);
  955. X        } else if (!strncmp(buf, "GRAPHICS", 4)) {
  956. X            unsigned int translate[MAXPCHARS+1];
  957. X            int lth;
  958. X#ifdef OVERLAY
  959. X            /* THIS is what I call a stupid hack, but MSC cannot survive
  960. X               the overlays without it (TH) */
  961. X            lth = sscanf(bufp,
  962. X    "%d%d%d%d%d%d%d%d%d%d%d%d",
  963. X                &translate[0], &translate[1], &translate[2],
  964. X                &translate[3], &translate[4], &translate[5],
  965. X                &translate[6], &translate[7], &translate[8],
  966. X                &translate[9], &translate[10], &translate[11]);
  967. X            lth += sscanf(bufp,
  968. X    "%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%d%d%d%d%d%d%d%d%d%d%d%d",
  969. X                &translate[12], &translate[13], &translate[14],
  970. X                &translate[15], &translate[16], &translate[17],
  971. X                &translate[18], &translate[19], &translate[20],
  972. X                &translate[21], &translate[22], &translate[23]);
  973. X            lth += sscanf(bufp,
  974. X    "%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%*d%d%d%d%d%d%d%d%d%d%d%d",
  975. X                &translate[24], &translate[25], &translate[26],
  976. X                &translate[27], &translate[28], &translate[29],
  977. X                &translate[30], &translate[31], &translate[32],
  978. X                &translate[33], &translate[34]);
  979. X#else
  980. X             lth = sscanf(bufp,
  981. X    "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
  982. X                &translate[0], &translate[1], &translate[2],
  983. X                &translate[3], &translate[4], &translate[5],
  984. X                &translate[6], &translate[7], &translate[8],
  985. X                &translate[9], &translate[10], &translate[11],
  986. X                &translate[12], &translate[13], &translate[14],
  987. X                &translate[15], &translate[16], &translate[17],
  988. X                &translate[18], &translate[19], &translate[20],
  989. X                &translate[21], &translate[22], &translate[23],
  990. X                &translate[24], &translate[25], &translate[26],
  991. X                &translate[27], &translate[28], &translate[29],
  992. X                &translate[30], &translate[31], &translate[32],
  993. X                &translate[33], &translate[34]);
  994. X#endif /* OVERLAY */
  995. X            if (lth <= 0) {
  996. X                msmsg ("Syntax error in GRAPHICS\n");
  997. X                getreturn("to continue");
  998. X            }
  999. X            assign_graphics(translate, lth);
  1000. X        } else {
  1001. X            msmsg("Bad option line: \"%s\"\n", buf);
  1002. X            getreturn("to continue");
  1003. X        }
  1004. X    }
  1005. X    (void) fclose(fp);
  1006. X
  1007. X# ifdef DGK
  1008. X    Strcpy(permbones, tmp_levels);
  1009. X    if (tmp_ramdisk[0]) {
  1010. X        Strcpy(levels, tmp_ramdisk);
  1011. X        if (strcmp(permbones, levels))        /* if not identical */
  1012. X            ramdisk = TRUE;
  1013. X    } else
  1014. X# endif /* DGK */
  1015. X        Strcpy(levels, tmp_levels);
  1016. X    Strcpy(bones, levels);
  1017. X    return;
  1018. X}
  1019. X
  1020. X# ifdef DGK
  1021. X/* Set names for bones[] and lock[]
  1022. X */
  1023. Xvoid
  1024. Xset_lock_and_bones() {
  1025. X    if (!ramdisk) {
  1026. X        Strcpy(levels, permbones);
  1027. X        Strcpy(bones, permbones);
  1028. X    }
  1029. X    append_slash(permbones);
  1030. X    append_slash(levels);
  1031. X    append_slash(bones);
  1032. X    Strcat(bones, allbones);
  1033. X    Strcpy(lock, levels);
  1034. X    Strcat(lock, alllevels);
  1035. X    return;
  1036. X}
  1037. X# endif /* DGK */
  1038. X
  1039. X/* Add a backslash to any name not ending in /, \ or :   There must
  1040. X * be room for the \
  1041. X */
  1042. Xvoid
  1043. Xappend_slash(name)
  1044. Xchar *name;
  1045. X{
  1046. X    char *ptr;
  1047. X
  1048. X    if (!*name)
  1049. X        return;
  1050. X    ptr = name + (strlen(name) - 1);
  1051. X    if (*ptr != '\\' && *ptr != '/' && *ptr != ':') {
  1052. X        *++ptr = '\\';
  1053. X        *++ptr = '\0';
  1054. X    }
  1055. X    return;
  1056. X}
  1057. X
  1058. Xvoid
  1059. Xgetreturn(str)
  1060. Xconst char *str;
  1061. X{
  1062. X# ifdef TOS
  1063. X    msmsg("Hit <Return> %s.", str);
  1064. X# else
  1065. X    msmsg("Hit <Enter> %s.", str);
  1066. X# endif
  1067. X    while (Getchar() != '\n') ;
  1068. X    return;
  1069. X}
  1070. X
  1071. Xvoid
  1072. Xmsmsg VA_DECL(const char *, fmt)
  1073. X    VA_START(fmt);
  1074. X    VA_INIT(fmt, const char *);
  1075. X    Vprintf(fmt, VA_ARGS);
  1076. X    flushout();
  1077. X    VA_END();
  1078. X    return;
  1079. X}
  1080. X
  1081. X/* Chdrive() changes the default drive.
  1082. X */
  1083. X# ifndef __TURBOC__
  1084. X#  ifndef OS2
  1085. X#define SELECTDISK    0x0E
  1086. X#  endif
  1087. Xvoid
  1088. Xchdrive(str)
  1089. Xchar *str;
  1090. X{
  1091. X    char *ptr;
  1092. X#  ifndef TOS
  1093. X#   ifndef OS2
  1094. X    union REGS inregs;
  1095. X#   endif
  1096. X#  endif
  1097. X    char drive;
  1098. X
  1099. X    if ((ptr = index(str, ':')) != NULL) {
  1100. X        drive = toupper(*(ptr - 1));
  1101. X#  ifdef TOS
  1102. X        (void)Dsetdrv(drive - 'A');
  1103. X#  else
  1104. X#   ifdef OS2
  1105. X        DosSelectDisk((USHORT)(drive - 'A' + 1));
  1106. X#   else
  1107. X        inregs.h.ah = SELECTDISK;
  1108. X        inregs.h.dl = drive - 'A';
  1109. X        intdos(&inregs, &inregs);
  1110. X#   endif
  1111. X#  endif
  1112. X    }
  1113. X    return;
  1114. X}
  1115. X# else
  1116. Xextern int setdisk(int);
  1117. X
  1118. Xvoid
  1119. Xchdrive(str)
  1120. Xchar *str;
  1121. X{
  1122. X    if (str[1] == ':')
  1123. X        (void)setdisk((int)(toupper(str[0]) - 'A'));
  1124. X    return;
  1125. X}
  1126. X# endif
  1127. X
  1128. X# ifndef TOS
  1129. X/* Use the IOCTL DOS function call to change stdin and stdout to raw
  1130. X * mode.  For stdin, this prevents MSDOS from trapping ^P, thus
  1131. X * freeing us of ^P toggling 'echo to printer'.
  1132. X * Thanks to Mark Zbikowski (markz@microsoft.UUCP).
  1133. X */
  1134. X
  1135. X#  ifndef OS2
  1136. X#define DEVICE        0x80
  1137. X#define RAW        0x20
  1138. X#define IOCTL        0x44
  1139. X#define STDIN        fileno(stdin)
  1140. X#define STDOUT        fileno(stdout)
  1141. X#define GETBITS        0
  1142. X#define SETBITS        1
  1143. X#  endif
  1144. X
  1145. Xstatic unsigned    int old_stdin, old_stdout;
  1146. X
  1147. Xvoid
  1148. Xdisable_ctrlP() {
  1149. X#  ifdef OS2
  1150. X    KBDINFO KbdInfo;
  1151. X    HKBD KbdHandle = 0;
  1152. X#  endif
  1153. X
  1154. X#  ifdef DGK
  1155. X    if (!flags.rawio) return;
  1156. X#  endif
  1157. X#  ifdef OS2
  1158. X    KbdInfo.cb = sizeof(KbdInfo);
  1159. X    KbdGetStatus(&KbdInfo,KbdHandle);
  1160. X    KbdInfo.fsMask &= 0xFFF7; /* ASCII off */
  1161. X    KbdInfo.fsMask |= 0x0004; /* BINARY on */
  1162. X    KbdSetStatus(&KbdInfo,KbdHandle);
  1163. X#  else
  1164. X    old_stdin = ioctl(STDIN, GETBITS, 0);
  1165. X    old_stdout = ioctl(STDOUT, GETBITS, 0);
  1166. X    if (old_stdin & DEVICE)
  1167. X        ioctl(STDIN, SETBITS, old_stdin | RAW);
  1168. X    if (old_stdout & DEVICE)
  1169. X        ioctl(STDOUT, SETBITS, old_stdout | RAW);
  1170. X#  endif /* OS2 */
  1171. X    return;
  1172. X}
  1173. X
  1174. Xvoid
  1175. Xenable_ctrlP() {
  1176. X#  ifdef OS2
  1177. X    KBDINFO KbdInfo;
  1178. X    HKBD KbdHandle = 0;
  1179. X#  endif
  1180. X
  1181. X#  ifdef DGK
  1182. X    if (!flags.rawio) return;
  1183. X#  endif
  1184. X#  ifdef OS2
  1185. X    KbdInfo.cb = sizeof(KbdInfo);
  1186. X    KbdGetStatus(&KbdInfo,KbdHandle);
  1187. X    KbdInfo.fsMask &= 0xFFFB; /* BINARY off */
  1188. X    KbdInfo.fsMask |= 0x0008; /* ASCII on */
  1189. X    KbdSetStatus(&KbdInfo,KbdHandle);
  1190. X#  else
  1191. X    if (old_stdin)
  1192. X        (void) ioctl(STDIN, SETBITS, old_stdin);
  1193. X    if (old_stdout)
  1194. X        (void) ioctl(STDOUT, SETBITS, old_stdout);
  1195. X#  endif
  1196. X    return;
  1197. X}
  1198. X
  1199. X#  ifndef OS2
  1200. Xstatic unsigned int
  1201. Xioctl(handle, mode, setvalue)
  1202. Xint handle, mode;
  1203. Xunsigned setvalue;
  1204. X{
  1205. X    union REGS regs;
  1206. X
  1207. X    regs.h.ah = IOCTL;
  1208. X    regs.h.al = mode;
  1209. X    regs.x.bx = handle;
  1210. X    regs.h.dl = setvalue;
  1211. X    regs.h.dh = 0;            /* Zero out dh */
  1212. X    intdos(®s, ®s);
  1213. X    return (regs.x.dx);
  1214. X}
  1215. X#  endif /* OS2 */
  1216. X# endif /* TOS */
  1217. X
  1218. X# ifdef DGK
  1219. X/* Follow the PATH, trying to fopen the file.
  1220. X */
  1221. X#  ifdef TOS
  1222. X#define PATHSEP    ','
  1223. X#  else
  1224. X#define PATHSEP    ';'
  1225. X#  endif
  1226. X
  1227. XFILE *
  1228. Xfopenp(name, mode)
  1229. Xconst char *name, *mode;
  1230. X{
  1231. X    char buf[BUFSIZ], *bp, *pp, lastch = 0;
  1232. X    FILE *fp;
  1233. X
  1234. X    /* Try the default directory first.  Then look along PATH.
  1235. X     */
  1236. X    Strcpy(buf, name);
  1237. X    if (fp = fopen(buf, mode))
  1238. X        return fp;
  1239. X    else {
  1240. X        pp = getenv("PATH");
  1241. X        while (pp && *pp) {
  1242. X            bp = buf;
  1243. X            while (*pp && *pp != PATHSEP)
  1244. X                lastch = *bp++ = *pp++;
  1245. X            if (lastch != '\\' && lastch != '/')
  1246. X                *bp++ = '\\';
  1247. X            Strcpy(bp, name);
  1248. X            if (fp = fopen(buf, mode))
  1249. X                return fp;
  1250. X            if (*pp)
  1251. X                pp++;
  1252. X        }
  1253. X    }
  1254. X#  ifdef OS2_CODEVIEW /* one more try for hackdir */
  1255. X    Strcpy(buf,hackdir);
  1256. X    append_slash(buf);
  1257. X    Strcat(buf,name);
  1258. X    if(fp = fopen(buf,mode))
  1259. X        return fp;
  1260. X#  endif
  1261. X    return (FILE *)0;
  1262. X}
  1263. X# endif /* DGK */
  1264. X
  1265. X/* Chdir back to original directory
  1266. X */
  1267. X#undef exit
  1268. X# ifdef TOS
  1269. Xextern boolean run_from_desktop;    /* set in pcmain.c */
  1270. X# endif
  1271. X
  1272. Xvoid exit(int);
  1273. Xvoid
  1274. Xmsexit(code)
  1275. Xint code;
  1276. X{
  1277. X# ifdef CHDIR
  1278. X    extern char orgdir[];
  1279. X# endif
  1280. X
  1281. X    flushout();
  1282. X# ifndef TOS
  1283. X    enable_ctrlP();        /* in case this wasn't done */
  1284. X# endif
  1285. X# ifdef DGK
  1286. X    if (ramdisk) copybones(TOPERM);
  1287. X# endif
  1288. X# ifdef CHDIR
  1289. X    chdir(orgdir);        /* chdir, not chdirx */
  1290. X    chdrive(orgdir);
  1291. X# endif
  1292. X# ifdef TOS
  1293. X    if (run_from_desktop)
  1294. X        getreturn("to continue"); /* so the user can read the score list */
  1295. X#  ifdef TEXTCOLOR
  1296. X    if (flags.IBMBIOS && flags.use_color)
  1297. X        restore_colors();
  1298. X#  endif
  1299. X# endif
  1300. X    exit(code);
  1301. X    return;
  1302. X}
  1303. X
  1304. X#  ifdef DGK        /* for flags.IBMBIOS */
  1305. Xvoid
  1306. Xget_scr_size()
  1307. X{
  1308. X#   ifdef OS2
  1309. X    VIOMODEINFO ModeInfo;
  1310. X    HVIO VideoHandle = 0;
  1311. X
  1312. X    ModeInfo.cb = sizeof(ModeInfo);
  1313. X
  1314. X    (void) VioGetMode(&ModeInfo,VideoHandle);
  1315. X
  1316. X    CO = ModeInfo.col;
  1317. X    LI = ModeInfo.row;
  1318. X#   else
  1319. X#    ifndef TOS
  1320. X    union REGS regs;
  1321. X
  1322. X    if (!flags.IBMBIOS) {        /* assume standard screen size */
  1323. X        CO = 80;
  1324. X        LI = 24;
  1325. X        return;
  1326. X    }
  1327. X
  1328. X    regs.x.ax = FONTINFO;
  1329. X    regs.x.bx = 0;            /* current ROM BIOS font */
  1330. X    regs.h.dl = 24;            /* default row count */
  1331. X                    /* in case no EGA/MCGA/VGA */
  1332. X    int86(VIDEO_BIOS, ®s, ®s); /* Get Font Information */
  1333. X
  1334. X    /* MDA/CGA/PCjr ignore INT 10h, Function 11h, but since we
  1335. X     * cleverly loaded up DL with the default, everything's fine.
  1336. X     *
  1337. X     * Otherwise, DL now contains rows - 1.  Also, CX contains the
  1338. X     * points (bytes per character) and ES:BP points to the font
  1339. X     * table.  -3.
  1340. X     */
  1341. X
  1342. X    regs.h.ah = GETMODE;
  1343. X    int86(VIDEO_BIOS, ®s, ®s); /* Get Video Mode */
  1344. X
  1345. X    /* This goes back all the way to the original PC.  Completely
  1346. X     * safe.  AH contains # of columns, AL contains display mode,
  1347. X     * and BH contains the active display page.
  1348. X     */
  1349. X
  1350. X    LI = regs.h.dl + 1;
  1351. X    CO = regs.h.ah;
  1352. X#    else  /* TOS */
  1353. X    init_aline();
  1354. X    LI = (*((WORD  *)(_a_line + -42L))) + 1;
  1355. X    CO = (*((WORD  *)(_a_line + -44L))) + 1;
  1356. X#    endif /* TOS */
  1357. X#   endif /* OS2 */
  1358. X}
  1359. X
  1360. X#   ifndef TOS
  1361. Xvoid
  1362. Xgotoxy(x,y)
  1363. Xint x,y;
  1364. X{
  1365. X#    ifdef OS2
  1366. X    HVIO VideoHandle = 0;
  1367. X
  1368. X    x--; y--;            /* (0,0) is upper right corner */
  1369. X
  1370. X    (void) VioSetCurPos(x, y, VideoHandle);
  1371. X#    else
  1372. X    union REGS regs;
  1373. X
  1374. X    x--; y--;            /* (0,0) is upper right corner */
  1375. X
  1376. X    regs.h.ah = SETCURPOS;
  1377. X    regs.h.bh = 0;            /* display page */
  1378. X    regs.h.dh = y;            /* row */
  1379. X    regs.h.dl = x;            /* column */
  1380. X    int86(VIDEO_BIOS, ®s, ®s); /* Set Cursor Position */
  1381. X
  1382. X    /* This, too, goes back all the way to the original PC.  If
  1383. X     * we ever get so fancy as to swap display pages (i doubt it),
  1384. X     * then we'll need to set BH appropriately.  This function
  1385. X     * returns nothing.  -3.
  1386. X     */
  1387. X#    endif /* OS2 */
  1388. X}
  1389. X#   endif /* TOS */
  1390. X#  endif /* DGK */
  1391. X
  1392. X#endif /* MSDOS */
  1393. X
  1394. X
  1395. X#ifdef TOS
  1396. X# define BIGBUF  8192
  1397. X
  1398. Xint
  1399. X_copyfile(from, to)
  1400. Xchar *from, *to;
  1401. X{
  1402. X    int fromfd, tofd, r;
  1403. X    char *buf;
  1404. X
  1405. X    if ((fromfd = open(from, O_RDONLY|O_BINARY, 0)) < 0)
  1406. X        return -1;
  1407. X    if ((tofd = open(to, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, FCMASK)) < 0)
  1408. X        return -1;
  1409. X    if (!(buf = (char *)malloc((size_t)BIGBUF)))
  1410. X        return -1;
  1411. X    while ( (r = read(fromfd, buf, BIGBUF)) > 0)
  1412. X        write(tofd, buf, r);
  1413. X    close(fromfd);
  1414. X    close(tofd);
  1415. X    free(buf);
  1416. X    return 0;    /* successful */
  1417. X}
  1418. X
  1419. Xint kbhit()
  1420. X{
  1421. X    return Cconis();
  1422. X}
  1423. X
  1424. Xstatic void
  1425. Xinit_aline()
  1426. X{
  1427. X# ifdef __GNUC__
  1428. X    asm(" .word 0xa000; movel d0, __a_line");
  1429. X# else
  1430. X    asm(" .dc.w 0xa000");    /* tweak as necessary for your compiler */
  1431. X    asm(" move.l d0, __a_line");
  1432. X# endif
  1433. X}
  1434. X
  1435. X# ifdef TEXTCOLOR
  1436. Xstatic unsigned orig_color[4] = {-1, -1, -1, -1};
  1437. Xstatic unsigned new_color[4] = { 0x0, 0x730, 0x047, 0x555 };
  1438. Xstatic int numcolors = 2;
  1439. X
  1440. Xvoid set_colors()
  1441. X{
  1442. X    int i;
  1443. X    char *s;
  1444. X    static char newhe[] = "\033q\033b\017\033c0";
  1445. X
  1446. X    if (!flags.IBMBIOS)
  1447. X        return;
  1448. X    init_aline();
  1449. X    numcolors = 1 << (((unsigned char *) _a_line)[1]);
  1450. X    if (numcolors == 2) {            /* mono */
  1451. X        flags.use_color = FALSE;
  1452. X        return;
  1453. X    }
  1454. X    else if (numcolors == 4) {
  1455. X        for (i = 0; i < 4; i++)
  1456. X            orig_color[i] = Setcolor(i, new_color[i]);
  1457. X    }
  1458. X    else {
  1459. X        orig_color[0] = Setcolor(0, new_color[0]);
  1460. X        orig_color[1] = Setcolor(15, 0x777);
  1461. X        hilites[0] = "";
  1462. X        for (i = 1; i < 16; i++) {
  1463. X            s = (char *) alloc(sizeof("\033b0"));
  1464. X            sprintf(s, "\033b%c", '0'+i);
  1465. X            hilites[i] = s;
  1466. X        }
  1467. X        HE = newhe;
  1468. X    }
  1469. X}
  1470. X
  1471. Xvoid restore_colors()
  1472. X{
  1473. X    int i;
  1474. X
  1475. X    if (numcolors == 2)
  1476. X        return;
  1477. X    else if (numcolors == 4)
  1478. X        for (i = 0; i < 4; i++)
  1479. X            (void) Setcolor(i, orig_color[i]);
  1480. X    else {
  1481. X        (void) Setcolor(0, orig_color[0]);
  1482. X        (void) Setcolor(15, orig_color[1]);
  1483. X    }
  1484. X}
  1485. X# endif /* TEXTCOLOR */
  1486. X#endif /* TOS */
  1487. END_OF_FILE
  1488. if test 30281 -ne `wc -c <'others/msdos.c'`; then
  1489.     echo shar: \"'others/msdos.c'\" unpacked with wrong size!
  1490. fi
  1491. # end of 'others/msdos.c'
  1492. fi
  1493. if test -f 'src/restore.c' -a "${1}" != "-c" ; then 
  1494.   echo shar: Will not clobber existing file \"'src/restore.c'\"
  1495. else
  1496. echo shar: Extracting \"'src/restore.c'\" \(25217 characters\)
  1497. sed "s/^X//" >'src/restore.c' <<'END_OF_FILE'
  1498. X/*    SCCS Id: @(#)restore.c    3.0    88/10/25
  1499. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  1500. X/* NetHack may be freely redistributed.  See license for details. */
  1501. X
  1502. X#include "hack.h"
  1503. X#include "lev.h"
  1504. X
  1505. X#ifdef WORM
  1506. X#include "wseg.h"
  1507. X#endif
  1508. X
  1509. Xstatic void FDECL(stuff_objs, (struct obj *));
  1510. Xstatic void NDECL(find_lev_obj);
  1511. X#ifndef NO_SIGNAL
  1512. Xstatic void NDECL(inven_inuse);
  1513. X#endif
  1514. Xstatic struct obj * FDECL(restobjchn, (int,BOOLEAN_P));
  1515. Xstatic struct monst * FDECL(restmonchn, (int,BOOLEAN_P));
  1516. Xstatic void FDECL(restgenoinfo, (int));
  1517. X
  1518. Xboolean restoring = FALSE;
  1519. X#ifdef TUTTI_FRUTTI
  1520. Xstatic struct fruit NEARDATA *oldfruit;
  1521. X#endif
  1522. Xstatic long NEARDATA omoves;
  1523. X
  1524. X/*
  1525. X * "stuff" objects back into containers (relink the fcobj list).
  1526. X */
  1527. Xstatic void
  1528. Xstuff_objs(cobj)
  1529. Xregister struct obj *cobj;
  1530. X{
  1531. X    register struct obj *otmp, *otmp2;
  1532. X
  1533. X    for(; cobj; cobj = cobj->nobj)
  1534. X        if(Is_container(cobj))
  1535. X
  1536. X        for(otmp = cobj->nobj;
  1537. X            otmp && otmp->cobj == (struct obj *) -1; otmp = otmp2) {
  1538. X
  1539. X            otmp2 = otmp->nobj;
  1540. X
  1541. X            otmp->cobj = cobj;
  1542. X            cobj->nobj = otmp2;
  1543. X            otmp->nobj = fcobj;
  1544. X            fcobj = otmp;
  1545. X        }
  1546. X}
  1547. X
  1548. X/* Recalculate level.objects[x][y], since this info was not saved. */
  1549. Xstatic void
  1550. Xfind_lev_obj()
  1551. X{
  1552. X    register struct obj *fobjtmp = (struct obj *)0;
  1553. X    register struct obj *otmp;
  1554. X    int x,y;
  1555. X
  1556. X    for(x=0; x<COLNO; x++) for(y=0; y<ROWNO; y++)
  1557. X        level.objects[x][y] = (struct obj *)0;
  1558. X
  1559. X    /* Reverse the entire fobj chain, which is necessary so that we can
  1560. X     * place the objects in the proper order.
  1561. X     */
  1562. X    while(otmp = fobj) {
  1563. X        fobj = otmp->nobj;
  1564. X        otmp->nobj = fobjtmp;
  1565. X        fobjtmp = otmp;
  1566. X    }
  1567. X    /* Set level.objects (as well as reversing the chain back again) */
  1568. X    while(otmp = fobjtmp) {
  1569. X        place_object(otmp, otmp->ox, otmp->oy);
  1570. X        fobjtmp = otmp->nobj;
  1571. X        otmp->nobj = fobj;
  1572. X        fobj = otmp;
  1573. X    }
  1574. X}
  1575. X
  1576. X#ifndef NO_SIGNAL
  1577. Xstatic void
  1578. Xinven_inuse()
  1579. X/* Things that were marked "in_use" when the game was saved (ex. via the
  1580. X * infamous "HUP" cheat) get used up here.
  1581. X */
  1582. X{
  1583. X    register struct obj *otmp, *otmp2;
  1584. X
  1585. X    for(otmp = invent; otmp; otmp = otmp2) {
  1586. X        otmp2 = otmp->nobj;
  1587. X        if(otmp->olet != ARMOR_SYM && otmp->olet != WEAPON_SYM
  1588. X            && otmp->otyp != PICK_AXE && otmp->otyp != UNICORN_HORN
  1589. X            && otmp->in_use) {
  1590. X            pline("Finishing off %s...", xname(otmp));
  1591. X            useup(otmp);
  1592. X        }
  1593. X    }
  1594. X}
  1595. X#endif
  1596. X
  1597. Xstatic struct obj *
  1598. Xrestobjchn(fd, ghostly)
  1599. Xregister int fd;
  1600. Xboolean ghostly;
  1601. X{
  1602. X    register struct obj *otmp, *otmp2;
  1603. X    register struct obj *first = 0;
  1604. X#ifdef TUTTI_FRUTTI
  1605. X    register struct fruit *oldf;
  1606. X#endif
  1607. X    int xl;
  1608. X#if defined(LINT) || defined(__GNULINT__)
  1609. X    /* suppress "used before set" warning from lint */
  1610. X    otmp2 = 0;
  1611. X#endif
  1612. X    while(1) {
  1613. X        mread(fd, (genericptr_t) &xl, sizeof(xl));
  1614. X        if(xl == -1) break;
  1615. X        otmp = newobj(xl);
  1616. X        if(!first) first = otmp;
  1617. X        else otmp2->nobj = otmp;
  1618. X        mread(fd, (genericptr_t) otmp, (unsigned) xl + sizeof(struct obj));
  1619. X        if(!otmp->o_id) otmp->o_id = flags.ident++;
  1620. X#ifdef TUTTI_FRUTTI
  1621. X        if(ghostly && otmp->otyp == SLIME_MOLD) {
  1622. X            for(oldf=oldfruit; oldf; oldf=oldf->nextf)
  1623. X                if (oldf->fid == otmp->spe) break;
  1624. X            if(!oldf) impossible("no old fruit?");
  1625. X            else otmp->spe = fruitadd(oldf->fname);
  1626. X        }
  1627. X#endif
  1628. X    /* Ghost levels get object age shifted from old player's clock to
  1629. X     * new player's clock.  Assumption: new player arrived immediately
  1630. X     * after old player died.
  1631. X     */
  1632. X        if (ghostly) otmp->age = monstermoves-omoves+otmp->age;
  1633. X        otmp2 = otmp;
  1634. X    }
  1635. X    if(first && otmp2->nobj){
  1636. X        impossible("Restobjchn: error reading objchn.");
  1637. X        otmp2->nobj = 0;
  1638. X    }
  1639. X
  1640. X    stuff_objs(first);
  1641. X    return(first);
  1642. X}
  1643. X
  1644. Xstatic struct monst *
  1645. Xrestmonchn(fd, ghostly)
  1646. Xregister int fd;
  1647. Xboolean ghostly;
  1648. X{
  1649. X    register struct monst *mtmp, *mtmp2;
  1650. X    register struct monst *first = 0;
  1651. X    int xl;
  1652. X
  1653. X    struct permonst *monbegin;
  1654. X    off_t differ;
  1655. X
  1656. X    mread(fd, (genericptr_t)&monbegin, sizeof(monbegin));
  1657. X#if !defined(MSDOS) && !defined(M_XENIX) && !defined(THINKC4) && !defined(HPUX) && !defined(VAXC)
  1658. X    differ = (genericptr_t)(&mons[0]) - (genericptr_t)(monbegin);
  1659. X#else
  1660. X    differ = (long)(&mons[0]) - (long)(monbegin);
  1661. X#endif
  1662. X
  1663. X#if defined(LINT) || defined(__GNULINT__)
  1664. X    /* suppress "used before set" warning from lint */
  1665. X    mtmp2 = 0;
  1666. X#endif
  1667. X    while(1) {
  1668. X        mread(fd, (genericptr_t) &xl, sizeof(xl));
  1669. X        if(xl == -1) break;
  1670. X        mtmp = newmonst(xl);
  1671. X        if(!first) first = mtmp;
  1672. X        else mtmp2->nmon = mtmp;
  1673. X        mread(fd, (genericptr_t) mtmp, (unsigned) xl + sizeof(struct monst));
  1674. X        if(!mtmp->m_id)
  1675. X            mtmp->m_id = flags.ident++;
  1676. X#if !defined(MSDOS) && !defined(M_XENIX) && !defined(THINKC4) && !defined(HPUX) && !defined(VAXC)
  1677. X        /* ANSI type for differ is ptrdiff_t --
  1678. X         * long may be wrong for segmented architecture --
  1679. X         * may be better to cast pointers to (struct permonst *)
  1680. X         * rather than (genericptr_t)
  1681. X         * this code handles save file -- so any bug should glow
  1682. X         * probably best not to keep lint from complaining
  1683. X         */
  1684. X/*#ifdef LINT    /* possible compiler/hardware dependency - */
  1685. X/*        if (differ) mtmp->data = NULL;*/
  1686. X/*#else*/
  1687. X        mtmp->data = (struct permonst *)
  1688. X            ((genericptr_t)mtmp->data + differ);
  1689. X/*#endif    /*LINT*/
  1690. X#else
  1691. X        mtmp->data = (struct permonst *)
  1692. X            ((long) mtmp->data + differ);
  1693. X#endif
  1694. X        if(mtmp->minvent)
  1695. X            mtmp->minvent = restobjchn(fd, ghostly);
  1696. X        mtmp2 = mtmp;
  1697. X    }
  1698. X    if(first && mtmp2->nmon){
  1699. X        impossible("Restmonchn: error reading monchn.");
  1700. X        mtmp2->nmon = 0;
  1701. X    }
  1702. X    return(first);
  1703. X}
  1704. X
  1705. Xstatic void
  1706. Xrestgenoinfo(fd)
  1707. Xregister int fd;
  1708. X{
  1709. X    register int i;
  1710. X
  1711. X    for (i = 0; i < NUMMONS; i++)
  1712. X        mread(fd, (genericptr_t) &(mons[i].geno), sizeof(unsigned));
  1713. X}
  1714. X
  1715. Xint
  1716. Xdorecover(fd)
  1717. Xregister int fd;
  1718. X{
  1719. X    register int nfd;
  1720. X    int tmp;        /* not a register ! */
  1721. X    xchar ltmp;
  1722. X    unsigned int mid;        /* idem */
  1723. X    struct obj *otmp;
  1724. X#ifdef TUTTI_FRUTTI
  1725. X    struct fruit *fruit;
  1726. X#endif
  1727. X    struct flag oldflags;
  1728. X
  1729. X    oldflags = flags;
  1730. X
  1731. X#ifdef ZEROCOMP
  1732. X    minit();
  1733. X#endif
  1734. X    restoring = TRUE;
  1735. X    getlev(fd, 0, (xchar)0, FALSE);
  1736. X    invent = restobjchn(fd, FALSE);
  1737. X    for(otmp = invent; otmp; otmp = otmp->nobj)
  1738. X        if(otmp->owornmask)
  1739. X            setworn(otmp, otmp->owornmask);
  1740. X    fallen_down = restmonchn(fd, FALSE);
  1741. X    restgenoinfo(fd);
  1742. X    mread(fd, (genericptr_t) &tmp, sizeof tmp);
  1743. X#ifdef WIZARD
  1744. X    if(!wizard)
  1745. X#endif
  1746. X        if(tmp != getuid()) {        /* strange ... */
  1747. X        (void) close(fd);
  1748. X        (void) unlink(SAVEF);
  1749. X#ifdef AMIGA_WBENCH
  1750. X        ami_wbench_unlink(SAVEF);
  1751. X#endif
  1752. X        (void) puts("Saved game was not yours.");
  1753. X        restoring = FALSE;
  1754. X        return(0);
  1755. X        }
  1756. X    mread(fd, (genericptr_t) &flags, sizeof(struct flag));
  1757. X    /* Some config file and command line OPTIONS take precedence over
  1758. X     * those in save file.
  1759. X     */
  1760. X    flags.DECgraphics = oldflags.DECgraphics;
  1761. X    flags.IBMgraphics = oldflags.IBMgraphics;
  1762. X#if defined(MSDOS) && defined(DGK)
  1763. X    flags.rawio = oldflags.rawio;
  1764. X    flags.IBMBIOS = oldflags.IBMBIOS;
  1765. X#endif
  1766. X#ifdef TEXTCOLOR
  1767. X    flags.use_color = oldflags.use_color;
  1768. X#endif
  1769. X    /* these come from the current environment; ignore saved values */
  1770. X    flags.echo = oldflags.echo;
  1771. X    flags.cbreak = oldflags.cbreak;
  1772. X
  1773. X    mread(fd, (genericptr_t) &dlevel, sizeof dlevel);
  1774. X    mread(fd, (genericptr_t) &maxdlevel, sizeof maxdlevel);
  1775. X    mread(fd, (genericptr_t) &moves, sizeof moves);
  1776. X    mread(fd, (genericptr_t) &monstermoves, sizeof monstermoves);
  1777. X    mread(fd, (genericptr_t) &wiz_level, sizeof wiz_level);
  1778. X    mread(fd, (genericptr_t) &medusa_level, sizeof medusa_level);
  1779. X    mread(fd, (genericptr_t) &bigroom_level, sizeof bigroom_level);
  1780. X#ifdef ORACLE
  1781. X    mread(fd, (genericptr_t) &oracle_level, sizeof oracle_level);
  1782. X#endif
  1783. X#ifdef REINCARNATION
  1784. X    mread(fd, (genericptr_t) &rogue_level, sizeof rogue_level);
  1785. X    if (dlevel==rogue_level)
  1786. X        (void) memcpy((genericptr_t)savesyms,
  1787. X                  (genericptr_t)showsyms, sizeof savesyms);
  1788. X#endif
  1789. X#ifdef STRONGHOLD
  1790. X    mread(fd, (genericptr_t) &stronghold_level, sizeof stronghold_level);
  1791. X    mread(fd, (genericptr_t) &tower_level, sizeof tower_level);
  1792. X    mread(fd, (genericptr_t) tune, sizeof tune);
  1793. X#  ifdef MUSIC
  1794. X    mread(fd, (genericptr_t) &music_heard, sizeof music_heard);
  1795. X#  endif
  1796. X#endif
  1797. X    mread(fd, (genericptr_t) &is_maze_lev, sizeof is_maze_lev);
  1798. X    mread(fd, (genericptr_t) &u, sizeof(struct you));
  1799. X    if(u.uhp <= 0) {
  1800. X        (void) close(fd);
  1801. X        (void) unlink(SAVEF);
  1802. X#ifdef AMIGA_WBENCH
  1803. X        ami_wbench_unlink(SAVEF);
  1804. X#endif
  1805. X        (void) puts("You were not healthy enough to survive restoration.");
  1806. X        restoring = FALSE;
  1807. X        return(0);
  1808. X    }
  1809. X#ifdef SPELLS
  1810. X    mread(fd, (genericptr_t) spl_book, 
  1811. X                sizeof(struct spell) * (MAXSPELL + 1));
  1812. X#endif
  1813. X#ifdef NAMED_ITEMS
  1814. X    mread(fd, (genericptr_t) artiexist, 
  1815. X            (unsigned int)(sizeof(boolean) * artifact_num));
  1816. X#endif
  1817. X    if(u.ustuck)
  1818. X        mread(fd, (genericptr_t) &mid, sizeof mid);
  1819. X    mread(fd, (genericptr_t) pl_character, sizeof pl_character);
  1820. X#ifdef TUTTI_FRUTTI
  1821. X    mread(fd, (genericptr_t) pl_fruit, sizeof pl_fruit);
  1822. X    mread(fd, (genericptr_t) ¤t_fruit, sizeof current_fruit);
  1823. X    ffruit = 0;
  1824. X    while (fruit = newfruit(),
  1825. X           mread(fd, (genericptr_t)fruit, sizeof(struct fruit)),
  1826. X           fruit->fid) {
  1827. X        fruit->nextf = ffruit;
  1828. X        ffruit = fruit;
  1829. X    }
  1830. X    free((genericptr_t) fruit);
  1831. X#endif
  1832. X
  1833. X    restnames(fd);
  1834. X#if defined(DGK) || defined(MACOS)
  1835. X# ifdef MACOS
  1836. X#define msmsg printf
  1837. X# endif
  1838. X    msmsg("\n");
  1839. X    cl_end();
  1840. X    msmsg("You got as far as level %d%s.\n", maxdlevel,
  1841. X        flags.debug ? " in WIZARD mode" :
  1842. X        flags.explore ? " in discovery mode" : "");
  1843. X    cl_end();
  1844. X    msmsg("Restoring: ");
  1845. X#endif
  1846. X    while(1) {
  1847. X#ifdef ZEROCOMP
  1848. X        if(mread(fd, (genericptr_t) <mp, sizeof ltmp) < 0)
  1849. X#else
  1850. X        if(read(fd, (genericptr_t) <mp, sizeof ltmp) != sizeof ltmp)
  1851. X#endif
  1852. X            break;
  1853. X        getlev(fd, 0, ltmp, FALSE);
  1854. X        glo(ltmp);
  1855. X#if defined(DGK) || defined(MACOS)
  1856. X        msmsg(".");
  1857. X#endif
  1858. X#if defined(MSDOS) && !defined(TOS)
  1859. X        nfd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK);
  1860. X#else
  1861. X# ifdef MACOS
  1862. X        {
  1863. X            Str255    fileName;
  1864. X            OSErr    er;
  1865. X            struct term_info    *t;
  1866. X            short    oldVolume;
  1867. X            extern WindowPtr    HackWindow;
  1868. X            
  1869. X            t = (term_info *)GetWRefCon(HackWindow);
  1870. X            (void)GetVol(&fileName, &oldVolume);
  1871. X            (void)SetVol(0L, t->system.sysVRefNum);
  1872. X            fileName[0] = (uchar)strlen(lock);
  1873. X            Strcpy((char *)&fileName[1], lock);
  1874. X            
  1875. X            if (er = Create(&fileName, 0, CREATOR, LEVEL_TYPE))
  1876. X                SysBeep(1);
  1877. X            msmsg(".");
  1878. X            nfd = open(lock, O_WRONLY | O_BINARY);
  1879. X            (void)SetVol(0L, oldVolume);
  1880. X        }
  1881. X# else
  1882. X        nfd = creat(lock, FCMASK);
  1883. X# endif /* MACOS */
  1884. X#endif
  1885. X        if (nfd < 0)    panic("Cannot open temp file %s!\n", lock);
  1886. X#if defined(DGK)
  1887. X        if (!savelev(nfd, ltmp, COUNT | WRITE)) {
  1888. X
  1889. X            /* The savelev can't proceed because the size required
  1890. X             * is greater than the available disk space.
  1891. X             */
  1892. X            msmsg("\nNot enough space on `%s' to restore your game.\n",
  1893. X                levels);
  1894. X
  1895. X            /* Remove levels and bones that may have been created.
  1896. X             */
  1897. X            (void) close(nfd);
  1898. X            eraseall(levels, alllevels);
  1899. X            eraseall(levels, allbones);
  1900. X
  1901. X            /* Perhaps the person would like to play without a
  1902. X             * RAMdisk.
  1903. X             */
  1904. X            if (ramdisk) {
  1905. X                /* PlaywoRAMdisk may not return, but if it does
  1906. X                 * it is certain that ramdisk will be 0.
  1907. X                 */
  1908. X                playwoRAMdisk();
  1909. X                /* Rewind save file and try again */
  1910. X                (void) lseek(fd, (off_t)0, 0);
  1911. X                return dorecover(fd);
  1912. X            } else {
  1913. X                msmsg("Be seeing you...\n");
  1914. X                exit(0);
  1915. X            }
  1916. X        }
  1917. X#else
  1918. X        savelev(nfd, ltmp);
  1919. X#endif
  1920. X#ifdef ZEROCOMP
  1921. X        bflush(nfd);
  1922. X#endif
  1923. X        (void) close(nfd);
  1924. X    }
  1925. X#ifdef BSD
  1926. X    (void) lseek(fd, 0L, 0);
  1927. X#else
  1928. X    (void) lseek(fd, (off_t)0, 0);
  1929. X#endif
  1930. X#ifdef ZEROCOMP
  1931. X    minit();
  1932. X#endif
  1933. X    getlev(fd, 0, (xchar)0, FALSE);
  1934. X    (void) close(fd);
  1935. X#if defined(WIZARD) || defined(EXPLORE_MODE)
  1936. X    if(
  1937. X# ifdef WIZARD
  1938. X       !wizard
  1939. X#  ifdef EXPLORE_MODE
  1940. X           &&
  1941. X#  endif
  1942. X# endif
  1943. X# ifdef EXPLORE_MODE
  1944. X              !discover
  1945. X# endif
  1946. X                )
  1947. X#endif
  1948. X        (void) unlink(SAVEF);
  1949. X#ifdef AMIGA_WBENCH
  1950. X        ami_wbench_unlink(SAVEF);
  1951. X#endif
  1952. X#ifdef REINCARNATION
  1953. X    /* this can't be done earlier because we need to check the initial
  1954. X     * showsyms against the one saved in each of the non-rogue levels */
  1955. X    if (dlevel==rogue_level) {
  1956. X        (void) memcpy((genericptr_t)showsyms,
  1957. X                  (genericptr_t)defsyms, sizeof showsyms);
  1958. X        showsyms[S_ndoor] = showsyms[S_vodoor] =
  1959. X            showsyms[S_hodoor] = '+';
  1960. X    }
  1961. X#endif
  1962. X    if(u.ustuck) {
  1963. X        register struct monst *mtmp;
  1964. X
  1965. X        for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  1966. X            if(mtmp->m_id == mid) goto monfnd;
  1967. X        panic("Cannot find the monster ustuck.");
  1968. X    monfnd:
  1969. X        u.ustuck = mtmp;
  1970. X    }
  1971. X    setsee();  /* only to recompute seelx etc. - these weren't saved */
  1972. X#ifdef DGK
  1973. X    gameDiskPrompt();
  1974. X#endif
  1975. X    max_rank_sz(); /* to recompute mrank_sz (pri.c) */
  1976. X#ifdef POLYSELF
  1977. X    set_uasmon();
  1978. X#endif
  1979. X    /* take care of iron ball & chain */
  1980. X    for(otmp = fobj; otmp; otmp = otmp->nobj)
  1981. X        if(otmp->owornmask)
  1982. X            setworn(otmp, otmp->owornmask);
  1983. X#ifndef NO_SIGNAL
  1984. X    /* in_use processing must be after:
  1985. X     *  inven has been read so fcobj has been built and freeinv() works
  1986. X     *  current level has been restored so billing information is available
  1987. X     */
  1988. X    inven_inuse();
  1989. X#endif
  1990. X    docrt();
  1991. X    restoring = FALSE;
  1992. X    return(1);
  1993. X}
  1994. X
  1995. Xvoid
  1996. Xgetlev(fd, pid, lev, ghostly)
  1997. Xint fd, pid;
  1998. Xxchar lev;
  1999. Xboolean ghostly;
  2000. X{
  2001. X    register struct gold *gold;
  2002. X    register struct trap *trap;
  2003. X    register struct monst *mtmp;
  2004. X#ifdef WORM
  2005. X    register struct wseg *wtmp;
  2006. X    register int tmp;
  2007. X#endif
  2008. X    long nhp;
  2009. X    int hpid;
  2010. X    xchar dlvl;
  2011. X    symbol_array osymbol;
  2012. X    int x, y;
  2013. X    uchar osym, nsym;
  2014. X#ifdef TOS
  2015. X    short tlev;
  2016. X#endif
  2017. X
  2018. X#if defined(MSDOS) && !defined(TOS) && !defined(LATTICE) && !defined(AZTEC_C)
  2019. X    setmode(fd, O_BINARY);        /* is this required for TOS??? NO --ERS */
  2020. X#endif
  2021. X#ifdef TUTTI_FRUTTI
  2022. X    /* Load the old fruit info.  We have to do it first, so the infor-
  2023. X     * mation is available when restoring the objects.  
  2024. X     */
  2025. X    if (ghostly) {
  2026. X        struct fruit *fruit;
  2027. X
  2028. X        oldfruit = 0;
  2029. X        while (fruit = newfruit(),
  2030. X               mread(fd, (genericptr_t)fruit, sizeof(struct fruit)),
  2031. X               fruit->fid) {
  2032. X            fruit->nextf = oldfruit;
  2033. X            oldfruit = fruit;
  2034. X        }
  2035. X        free((genericptr_t) fruit);
  2036. X    }
  2037. X#endif
  2038. X
  2039. X    /* First some sanity checks */
  2040. X    mread(fd, (genericptr_t) &hpid, sizeof(hpid));
  2041. X#ifdef TOS
  2042. X    mread(fd, (genericptr_t) &tlev, sizeof(tlev));
  2043. X    dlvl=tlev&0x00ff;
  2044. X#else
  2045. X    mread(fd, (genericptr_t) &dlvl, sizeof(dlvl));
  2046. X#endif
  2047. X    if((pid && pid != hpid) || (lev && dlvl != lev)) {
  2048. X#ifdef WIZARD
  2049. X        if (wizard) {
  2050. X            if (pid && pid != hpid)
  2051. X                pline("PID (%d) doesn't match saved PID (%d)!", hpid, pid);
  2052. X            else if (lev && dlvl != lev)
  2053. X                pline("This is level %d, not %d!", dlvl, lev);
  2054. X        }
  2055. X#endif
  2056. X        pline("Strange, this map is not as I remember it.");
  2057. X        pline("Somebody is trying some trickery here...");
  2058. X        pline("This game is void.");
  2059. X        done(TRICKED);
  2060. X    }
  2061. X
  2062. X#if defined(SMALLDATA) && defined(MACOS)
  2063. X    {
  2064. X    /* this assumes that the size of a row of struct rm's is <128 */
  2065. X        short    i, length, j;
  2066. X        char    *ptr, *src, *p, *d;
  2067. X        
  2068. X        d = calloc(ROWNO*COLNO, sizeof(struct rm));
  2069. X        p = d;
  2070. X        mread(fd, (genericptr_t)&j, sizeof(short));
  2071. X        mread(fd, (genericptr_t)d, j);
  2072. X        for (i = 0; i < COLNO; i++) {
  2073. X            length = (short)(*p++);
  2074. X            ptr = p;
  2075. X            src = (char *)&levl[i][0];
  2076. X            UnpackBits(&ptr, &src, ROWNO * sizeof(struct rm));
  2077. X            if ((ptr - p) != length) 
  2078. X                panic("restore - corrupted file on unpacking\n");
  2079. X            p = ptr;
  2080. X        }
  2081. X        free(d);
  2082. X    }
  2083. X#else
  2084. X    mread(fd, (genericptr_t) levl, sizeof(levl));
  2085. X#endif
  2086. X    mread(fd, (genericptr_t) osymbol, sizeof(osymbol));
  2087. X#ifdef REINCARNATION
  2088. X    if (memcmp((genericptr_t) osymbol, ((dlevel==rogue_level)
  2089. X            ? (genericptr_t)savesyms : (genericptr_t)showsyms),
  2090. X            sizeof (osymbol))
  2091. X        && dlvl != rogue_level) {
  2092. X        /* rogue level always uses default syms.  Although showsyms
  2093. X         * will be properly initialized from environment when restoring
  2094. X         * a game, this routine is called upon saving as well as
  2095. X         * restoring; when saving on the Rogue level, showsyms will
  2096. X         * be wrong, so use savesyms (which is always right, both on
  2097. X         * saving and restoring).
  2098. X         */
  2099. X#else
  2100. X    if (memcmp((genericptr_t) osymbol,
  2101. X           (genericptr_t) showsyms, sizeof (showsyms))) {
  2102. X#endif
  2103. X        for (x = 0; x < COLNO; x++)
  2104. X            for (y = 0; y < ROWNO; y++) {
  2105. X                osym = levl[x][y].scrsym;
  2106. X                nsym = 0;
  2107. X                switch (levl[x][y].typ) {
  2108. X                case STONE:
  2109. X                case SCORR:
  2110. X                    if (osym == osymbol[S_stone])
  2111. X                        nsym = showsyms[S_stone];
  2112. X                    break;
  2113. X                case ROOM:
  2114. X#ifdef STRONGHOLD
  2115. X                case DRAWBRIDGE_DOWN:
  2116. X#endif /* STRONGHOLD /**/
  2117. X                    if (osym == osymbol[S_room])
  2118. X                        nsym = showsyms[S_room];
  2119. X                    break;
  2120. X                case DOOR:
  2121. X                    if (osym == osymbol[S_ndoor])
  2122. X                        nsym = showsyms[S_ndoor];
  2123. X                    else if (osym == osymbol[S_vodoor])
  2124. X                        nsym = showsyms[S_vodoor];
  2125. X                    else if (osym == osymbol[S_hodoor])
  2126. X                        nsym = showsyms[S_hodoor];
  2127. X                    else if (osym == osymbol[S_cdoor])
  2128. X                        nsym = showsyms[S_cdoor];
  2129. X                    break;
  2130. X                case CORR:
  2131. X                    if (osym == osymbol[S_corr])
  2132. X                        nsym = showsyms[S_corr];
  2133. X                    break;
  2134. X                case VWALL:
  2135. X                    if (osym == osymbol[S_vwall])
  2136. X                        nsym = showsyms[S_vwall];
  2137. X#ifdef STRONGHOLD
  2138. X                    else if (osym == osymbol[S_dbvwall])
  2139. X                        nsym = showsyms[S_dbvwall];
  2140. X#endif
  2141. X                    break;
  2142. X                case HWALL:
  2143. X                    if (osym == osymbol[S_hwall])
  2144. X                        nsym = showsyms[S_hwall];
  2145. X#ifdef STRONGHOLD
  2146. X                    else if (osym == osymbol[S_dbhwall])
  2147. X                        nsym = showsyms[S_dbhwall];
  2148. X#endif
  2149. X                    break;
  2150. X                case TLCORNER:
  2151. X                    if (osym == osymbol[S_tlcorn])
  2152. X                        nsym = showsyms[S_tlcorn];
  2153. X                    break;
  2154. X                case TRCORNER:
  2155. X                    if (osym == osymbol[S_trcorn])
  2156. X                        nsym = showsyms[S_trcorn];
  2157. X                    break;
  2158. X                case BLCORNER:
  2159. X                    if (osym == osymbol[S_blcorn])
  2160. X                        nsym = showsyms[S_blcorn];
  2161. X                    break;
  2162. X                case BRCORNER:
  2163. X                    if (osym == osymbol[S_brcorn])
  2164. X                        nsym = showsyms[S_brcorn];
  2165. X                    break;
  2166. X                case SDOOR:
  2167. X                    if (osym == osymbol[S_vwall])
  2168. X                        nsym = showsyms[S_vwall];
  2169. X                    else if (osym == osymbol[S_hwall])
  2170. X                        nsym = showsyms[S_hwall];
  2171. X                    break;
  2172. X                case CROSSWALL:
  2173. X                    if (osym == osymbol[S_crwall])
  2174. X                        nsym = showsyms[S_crwall];
  2175. X                    break;
  2176. X                case TUWALL:
  2177. X                    if (osym == osymbol[S_tuwall])
  2178. X                        nsym = showsyms[S_tuwall];
  2179. X                    break;
  2180. X                case TDWALL:
  2181. X                    if (osym == osymbol[S_tdwall])
  2182. X                        nsym = showsyms[S_tdwall];
  2183. X                    break;
  2184. X                case TLWALL:
  2185. X                    if (osym == osymbol[S_tlwall])
  2186. X                        nsym = showsyms[S_tlwall];
  2187. X                    break;
  2188. X                case TRWALL:
  2189. X                    if (osym == osymbol[S_trwall])
  2190. X                        nsym = showsyms[S_trwall];
  2191. X                    break;
  2192. X                case STAIRS:
  2193. X                    if (osym == osymbol[S_upstair])
  2194. X                        nsym = showsyms[S_upstair];
  2195. X                    else if (osym == osymbol[S_dnstair])
  2196. X                        nsym = showsyms[S_dnstair];
  2197. X                    break;
  2198. X#ifdef STRONGHOLD
  2199. X                case LADDER:
  2200. X                    if (osym == osymbol[S_upladder])
  2201. X                        nsym = showsyms[S_upladder];
  2202. X                    else if (osym == osymbol[S_dnladder])
  2203. X                        nsym = showsyms[S_dnladder];
  2204. X                    break;
  2205. X#endif /* STRONGHOLD /**/
  2206. X                case POOL:
  2207. X                case MOAT:
  2208. X#ifdef STRONGHOLD
  2209. X                case DRAWBRIDGE_UP:
  2210. X#endif /* STRONGHOLD /**/
  2211. X                    if (osym == osymbol[S_pool])
  2212. X                        nsym = showsyms[S_pool];
  2213. X                    break;
  2214. X#ifdef FOUNTAINS
  2215. X                case FOUNTAIN:
  2216. X                    if (osym == osymbol[S_fountain])
  2217. X                        nsym = showsyms[S_fountain];
  2218. X                    break;
  2219. X#endif /* FOUNTAINS /**/
  2220. X#ifdef THRONES
  2221. X                case THRONE:
  2222. X                    if (osym == osymbol[S_throne])
  2223. X                        nsym = showsyms[S_throne];
  2224. X                    break;
  2225. X#endif /* THRONES /**/
  2226. X#ifdef SINKS
  2227. X                case SINK:
  2228. X                    if (osym == osymbol[S_sink])
  2229. X                        nsym = showsyms[S_sink];
  2230. X                    break;
  2231. X#endif /* SINKS /**/
  2232. X#ifdef ALTARS
  2233. X                case ALTAR:
  2234. X                    if (osym == osymbol[S_altar])
  2235. X                        nsym = showsyms[S_altar];
  2236. X                    break;
  2237. X#endif /* ALTARS /**/
  2238. X                default:
  2239. X                    break;
  2240. X                }
  2241. X                if (nsym)
  2242. X                    levl[x][y].scrsym = nsym;
  2243. X            }
  2244. X    }
  2245. X
  2246. X    mread(fd, (genericptr_t)&omoves, sizeof(omoves));
  2247. X    mread(fd, (genericptr_t)&xupstair, sizeof(xupstair));
  2248. X    mread(fd, (genericptr_t)&yupstair, sizeof(yupstair));
  2249. X    mread(fd, (genericptr_t)&xdnstair, sizeof(xdnstair));
  2250. X    mread(fd, (genericptr_t)&ydnstair, sizeof(ydnstair));
  2251. X#ifdef STRONGHOLD
  2252. X    mread(fd, (genericptr_t)&xupladder, sizeof(xupladder));
  2253. X    mread(fd, (genericptr_t)&yupladder, sizeof(yupladder));
  2254. X    mread(fd, (genericptr_t)&xdnladder, sizeof(xdnladder));
  2255. X    mread(fd, (genericptr_t)&ydnladder, sizeof(ydnladder));
  2256. X#endif
  2257. X    mread(fd, (genericptr_t)&fountsound, sizeof(fountsound));
  2258. X    mread(fd, (genericptr_t)&sinksound, sizeof(sinksound));
  2259. X    fmon = restmonchn(fd, ghostly);
  2260. X
  2261. X    /* regenerate animals while on another level */
  2262. X    { long tmoves = (monstermoves > omoves) ? monstermoves-omoves : 0;
  2263. X      register struct monst *mtmp2;
  2264. X
  2265. X      for(mtmp = fmon; mtmp; mtmp = mtmp2) {
  2266. X
  2267. X        mtmp2 = mtmp->nmon;
  2268. X        if((mtmp->data->geno&G_GENOD) && !(mtmp->data->geno&G_UNIQ)) {
  2269. X            /* mondead() would try to link the monster's objects
  2270. X             * into fobj and the appropriate nexthere chain.
  2271. X             * unfortunately, such things will not have sane
  2272. X             * values until after find_lev_obj() well below
  2273. X             * here, so we'd go chasing random pointers if we
  2274. X             * tried that.  we could save the monster's objects
  2275. X             * in another chain and insert them in the level
  2276. X             * later, but that's a lot of work for very little
  2277. X             * gain.  hence, just throw the objects away via
  2278. X             * mongone() and pretend the monster wandered off
  2279. X             * somewhere private before the genocide.
  2280. X             */
  2281. X            mongone(mtmp);
  2282. X            continue;
  2283. X        }
  2284. X
  2285. X        if (ghostly) {
  2286. X            /* reset peaceful/malign relative to new character */
  2287. X            if(!mtmp->isshk)
  2288. X                /* shopkeepers will reset based on name */
  2289. X                mtmp->mpeaceful = peace_minded(mtmp->data);
  2290. X            set_malign(mtmp);
  2291. X        } else if (mtmp->mtame && tmoves > 250)
  2292. X              mtmp->mtame = mtmp->mpeaceful = 0;
  2293. X
  2294. X        /* restore shape changers - Maarten Jan Huisjes */
  2295. X        if (mtmp->data == &mons[PM_CHAMELEON]
  2296. X            && !Protection_from_shape_changers
  2297. X            && !mtmp->cham)
  2298. X            mtmp->cham = 1;
  2299. X        else if(Protection_from_shape_changers) {
  2300. X            if (mtmp->cham) {
  2301. X                mtmp->cham = 0;
  2302. X                (void) newcham(mtmp, &mons[PM_CHAMELEON]);
  2303. X            } else if(is_were(mtmp->data) && !is_human(mtmp->data))
  2304. X                (void) new_were(mtmp);
  2305. X        }
  2306. X
  2307. X        if (!ghostly) {
  2308. X            nhp = mtmp->mhp +
  2309. X                (regenerates(mtmp->data) ? tmoves : tmoves/20);
  2310. X            if(!mtmp->mcansee && mtmp->mblinded) {
  2311. X                if (mtmp->mblinded < tmoves) mtmp->mblinded = 0;
  2312. X                else mtmp->mblinded -= tmoves;
  2313. X            }
  2314. X            if(!mtmp->mcanmove && mtmp->mfrozen) {
  2315. X                if (mtmp->mfrozen < tmoves) mtmp->mfrozen = 0;
  2316. X                else mtmp->mfrozen -= tmoves;
  2317. X            }
  2318. X            if(nhp > mtmp->mhpmax)
  2319. X                mtmp->mhp = mtmp->mhpmax;
  2320. X            else
  2321. X#ifdef LINT    /* (long)newhp -> (schar = short int) mhp; ok in context of text above */
  2322. X                mtmp->mhp = 0;
  2323. X#else
  2324. X                mtmp->mhp = nhp;
  2325. X#endif
  2326. X        }
  2327. X      }
  2328. X    }
  2329. X
  2330. X    fgold = 0;
  2331. X    while(gold = newgold(),
  2332. X          mread(fd, (genericptr_t)gold, sizeof(struct gold)),
  2333. X          gold->gx) {
  2334. X        gold->ngold = fgold;
  2335. X        fgold = gold;
  2336. X    }
  2337. X    free((genericptr_t) gold);
  2338. X    ftrap = 0;
  2339. X    while (trap = newtrap(),
  2340. X           mread(fd, (genericptr_t)trap, sizeof(struct trap)),
  2341. X           trap->tx) {
  2342. X        trap->ntrap = ftrap;
  2343. X        ftrap = trap;
  2344. X    }
  2345. X    free((genericptr_t) trap);
  2346. X    fobj = restobjchn(fd, ghostly);
  2347. X    find_lev_obj();
  2348. X    billobjs = restobjchn(fd, ghostly);
  2349. X    rest_engravings(fd);
  2350. X    mread(fd, (genericptr_t)rooms, sizeof(rooms));
  2351. X    mread(fd, (genericptr_t)doors, sizeof(doors));
  2352. X#ifdef WORM
  2353. X    mread(fd, (genericptr_t)wsegs, sizeof(wsegs));
  2354. X    for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){
  2355. X        wheads[tmp] = wsegs[tmp] = wtmp = newseg();
  2356. X        while(1) {
  2357. X            mread(fd, (genericptr_t)wtmp, sizeof(struct wseg));
  2358. X            if(!wtmp->nseg) break;
  2359. X            wheads[tmp]->nseg = wtmp = newseg();
  2360. X            wheads[tmp] = wtmp;
  2361. X        }
  2362. X    }
  2363. X    mread(fd, (genericptr_t)wgrowtime, sizeof(wgrowtime));
  2364. X#endif
  2365. X
  2366. X    /* reset level.monsters for new level */
  2367. X    for (x = 0; x < COLNO; x++)
  2368. X        for (y = 0; y < ROWNO; y++)
  2369. X        level.monsters[x][y] = (struct monst *) 0;
  2370. X    for (mtmp = level.monlist; mtmp; mtmp = mtmp->nmon)
  2371. X        place_monster(mtmp, mtmp->mx, mtmp->my);
  2372. X
  2373. X#ifdef TUTTI_FRUTTI
  2374. X    /* Now get rid of all the temp fruits... */
  2375. X    if (ghostly) {
  2376. X        struct fruit *fruit;
  2377. X
  2378. X        while(oldfruit) {
  2379. X            fruit = oldfruit->nextf;
  2380. X            free((genericptr_t) oldfruit);
  2381. X            oldfruit = fruit;
  2382. X        }
  2383. X    }
  2384. X#endif
  2385. X    if(ghostly && lev > medusa_level && lev < stronghold_level &&
  2386. X                        xdnstair == 0) {
  2387. X        coord cc;
  2388. X
  2389. X        mazexy(&cc);
  2390. X        xdnstair = cc.x;
  2391. X        ydnstair = cc.y;
  2392. X        levl[cc.x][cc.y].typ = STAIRS;
  2393. X    }
  2394. X}
  2395. X
  2396. X#ifdef ZEROCOMP
  2397. X#define RLESC '\0'     /* Leading character for run of RLESC's */
  2398. X
  2399. Xstatic unsigned char NEARDATA inbuf[BUFSZ];
  2400. Xstatic unsigned short NEARDATA inbufp = 0;
  2401. Xstatic unsigned short NEARDATA inbufsz = 0;
  2402. Xstatic short NEARDATA inrunlength = -1;
  2403. Xstatic int NEARDATA mreadfd;
  2404. Xstatic int NDECL(mgetc);
  2405. X
  2406. Xstatic int
  2407. Xmgetc()
  2408. X{
  2409. X    if (inbufp >= inbufsz) {
  2410. X      inbufsz = read(mreadfd, (genericptr_t)inbuf, (int)sizeof inbuf);
  2411. X      if (!inbufsz) {
  2412. X      if (inbufp > sizeof inbuf)
  2413. X          error("EOF on file #%d.\n", mreadfd);
  2414. X      inbufp = 1 + sizeof inbuf;  /* exactly one warning :-) */
  2415. X      return -1;
  2416. X      }
  2417. X      inbufp = 0;
  2418. X    }
  2419. X    return inbuf[inbufp++];
  2420. X}
  2421. X
  2422. Xvoid
  2423. Xminit()
  2424. X{
  2425. X    inbufsz = 0;
  2426. X    inbufp = 0;
  2427. X    inrunlength = -1;
  2428. X}
  2429. X
  2430. Xint
  2431. Xmread(fd, buf, len)
  2432. Xint fd;
  2433. Xgenericptr_t buf;
  2434. Xregister unsigned len;
  2435. X{
  2436. X    /*register int readlen = 0;*/
  2437. X    mreadfd = fd;
  2438. X    while (len--) {
  2439. X      if (inrunlength > 0) {
  2440. X      inrunlength--;
  2441. X      *(*((char **)&buf))++ = '\0';
  2442. X      } else {
  2443. X      register short ch = mgetc();
  2444. X      if (ch < 0) return -1; /*readlen;*/
  2445. X      if ((*(*(char **)&buf)++ = ch) == RLESC) {
  2446. X          inrunlength = mgetc();
  2447. X      }
  2448. X      }
  2449. X      /*readlen++;*/
  2450. X    }
  2451. X    return 0; /*readlen;*/
  2452. X}
  2453. X
  2454. X#else /* ZEROCOMP */
  2455. X
  2456. Xvoid
  2457. Xmread(fd, buf, len)
  2458. Xregister int fd;
  2459. Xregister genericptr_t buf;
  2460. Xregister unsigned int len;
  2461. X{
  2462. X    register int rlen;
  2463. X
  2464. X#if defined(BSD) || defined(ULTRIX)
  2465. X    rlen = read(fd, buf, (int) len);
  2466. X    if(rlen != len){
  2467. X#else /* e.g. SYSV, __TURBOC__ */
  2468. X    rlen = read(fd, buf, (unsigned) len);
  2469. X    if((unsigned)rlen != len){
  2470. X#endif
  2471. X        pline("Read %d instead of %u bytes.\n", rlen, len);
  2472. X        if(restoring) {
  2473. X            (void) unlink(SAVEF);
  2474. X#ifdef AMIGA_WBENCH
  2475. X            ami_wbench_unlink(SAVEF);
  2476. X#endif
  2477. X            error("Error restoring old game.");
  2478. X        }
  2479. X        panic("Error reading level file.");
  2480. X    }
  2481. X}
  2482. X#endif /* ZEROCOMP */
  2483. END_OF_FILE
  2484. if test 25217 -ne `wc -c <'src/restore.c'`; then
  2485.     echo shar: \"'src/restore.c'\" unpacked with wrong size!
  2486. fi
  2487. # end of 'src/restore.c'
  2488. fi
  2489. echo shar: End of archive 27 \(of 56\).
  2490. cp /dev/null ark27isdone
  2491. MISSING=""
  2492. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 ; do
  2493.     if test ! -f ark${I}isdone ; then
  2494.     MISSING="${MISSING} ${I}"
  2495.     fi
  2496. done
  2497. if test "${MISSING}" = "" ; then
  2498.     echo You have unpacked all 56 archives.
  2499.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2500. else
  2501.     echo You still need to unpack the following archives:
  2502.     echo "        " ${MISSING}
  2503. fi
  2504. ##  End of shell archive.
  2505. exit 0
  2506.