home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume16 / nethck31 / part39 < prev    next >
Encoding:
Internet Message Format  |  1993-01-31  |  58.5 KB

  1. Path: uunet!news.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v16i047:  nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part39/108
  5. Message-ID: <4341@master.CNA.TEK.COM>
  6. Date: 30 Jan 93 01:12:33 GMT
  7. Sender: news@master.CNA.TEK.COM
  8. Lines: 2494
  9. Approved: billr@saab.CNA.TEK.COM
  10. Xref: uunet comp.sources.games:1596
  11.  
  12. Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
  13. Posting-number: Volume 16, Issue 47
  14. Archive-name: nethack31/Part39
  15. Supersedes: nethack3p9: Volume 10, Issue 46-102
  16. Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
  17.  
  18.  
  19.  
  20. #! /bin/sh
  21. # This is a shell archive.  Remove anything before this line, then unpack
  22. # it by saving it into a file and typing "sh file".  To overwrite existing
  23. # files, type "sh file -c".  You can also feed this as standard input via
  24. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  25. # will see the following message at the end:
  26. #        "End of archive 39 (of 108)."
  27. # Contents:  src/mthrowu.c sys/amiga/wb.c1
  28. # Wrapped by billr@saab on Wed Jan 27 16:09:01 1993
  29. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  30. if test -f 'src/mthrowu.c' -a "${1}" != "-c" ; then 
  31.   echo shar: Will not clobber existing file \"'src/mthrowu.c'\"
  32. else
  33. echo shar: Extracting \"'src/mthrowu.c'\" \(15122 characters\)
  34. sed "s/^X//" >'src/mthrowu.c' <<'END_OF_FILE'
  35. X/*    SCCS Id: @(#)mthrowu.c    3.1    92/11/14    */
  36. X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  37. X/* NetHack may be freely redistributed.  See license for details. */
  38. X
  39. X#include    "hack.h"
  40. X
  41. XSTATIC_DCL void FDECL(drop_throw,(struct obj *,BOOLEAN_P,int,int));
  42. X#ifndef MUSE
  43. XSTATIC_DCL void FDECL(m_throw,(struct monst *,int,int,int,int,int,struct obj *));
  44. X#endif
  45. X
  46. X#define URETREATING(x,y) (distmin(u.ux,u.uy,x,y) > distmin(u.ux0,u.uy0,x,y))
  47. X
  48. Xboolean FDECL(lined_up, (struct monst *));
  49. X
  50. X#ifndef OVLB
  51. X
  52. XSTATIC_DCL const char *breathwep[];
  53. X
  54. X#else /* OVLB */
  55. X
  56. X/*
  57. X * Keep consistent with breath weapons in zap.c, and AD_* in monattk.h.
  58. X */
  59. XSTATIC_OVL const char NEARDATA *breathwep[] = {
  60. X                "fragments",
  61. X                "fire",
  62. X                "frost",
  63. X                "sleep gas",
  64. X                "death",
  65. X                "lightning",
  66. X                "poison gas",
  67. X                "acid",
  68. X                "strange breath #8",
  69. X                "strange breath #9"
  70. X};
  71. X
  72. Xint
  73. Xthitu(tlev, dam, obj, name)    /* u is hit by sth, but not a monster */
  74. X    register int tlev, dam;
  75. X    struct obj *obj;
  76. X    register const char *name;
  77. X{
  78. X    const char *onm = (obj && obj_is_pname(obj)) ? the(name) : an(name);
  79. X    boolean is_acid = (obj && obj->otyp == ACID_VENOM);
  80. X
  81. X    if(u.uac + tlev <= rnd(20)) {
  82. X        if(Blind || !flags.verbose) pline("It misses.");
  83. X        else You("are almost hit by %s!", onm);
  84. X        return(0);
  85. X    } else {
  86. X        if(Blind || !flags.verbose) You("are hit!");
  87. X        else You("are hit by %s!", onm);
  88. X#ifdef POLYSELF
  89. X        if (obj && objects[obj->otyp].oc_material == SILVER
  90. X                && hates_silver(uasmon)) {
  91. X            dam += rnd(20);
  92. X            pline("The silver sears your flesh!");
  93. X            exercise(A_CON, FALSE);
  94. X        }
  95. X        if (is_acid && resists_acid(uasmon))
  96. X            pline("It doesn't seem to hurt you.");
  97. X        else {
  98. X#endif
  99. X            if (is_acid) pline("It burns!");
  100. X            if (Half_physical_damage) dam = (dam+1) / 2;
  101. X            losehp(dam, name, (obj && obj_is_pname(obj)) ?
  102. X                   KILLED_BY : KILLED_BY_AN);
  103. X            exercise(A_STR, FALSE);
  104. X#ifdef POLYSELF
  105. X        }
  106. X#endif
  107. X        return(1);
  108. X    }
  109. X}
  110. X
  111. X/* Be sure this corresponds with what happens to player-thrown objects in
  112. X * dothrow.c (for consistency). --KAA
  113. X */
  114. X
  115. XSTATIC_OVL void
  116. Xdrop_throw(obj, ohit, x, y)
  117. Xregister struct obj *obj;
  118. Xboolean ohit;
  119. Xint x,y;
  120. X{
  121. X    int create;
  122. X    struct monst *mtmp;
  123. X    struct trap *t;
  124. X
  125. X    if (obj->otyp == CREAM_PIE || obj->oclass == VENOM_CLASS)
  126. X        create = 0;
  127. X    else if (ohit &&
  128. X         ((obj->otyp >= ARROW && obj->otyp <= SHURIKEN) ||
  129. X          obj->otyp == ROCK))
  130. X        create = !rn2(3);
  131. X    else create = 1;
  132. X    if (create && !((mtmp = m_at(x, y)) && (mtmp->mtrapped) && 
  133. X            (t = t_at(x, y)) && ((t->ttyp == PIT) || 
  134. X            (t->ttyp == SPIKED_PIT))) && 
  135. X        !flooreffects(obj,x,y,"fall")) { /* don't double-dip on damage */
  136. X        place_object(obj, x, y);
  137. X        obj->nobj = fobj;
  138. X        fobj = obj;
  139. X        stackobj(fobj);
  140. X    } else obfree(obj, (struct obj*) 0);
  141. X}
  142. X
  143. X#endif /* OVLB */
  144. X#ifdef OVL1
  145. X
  146. X#ifndef MUSE
  147. XSTATIC_OVL
  148. X#endif
  149. Xvoid
  150. Xm_throw(mon, x, y, dx, dy, range, obj)
  151. X    register struct monst *mon;
  152. X    register int x,y,dx,dy,range;        /* direction and range */
  153. X    register struct obj *obj;
  154. X{
  155. X    register struct monst *mtmp;
  156. X    struct obj *singleobj;
  157. X    char sym = obj->oclass;
  158. X    int damage;
  159. X    int hitu, blindinc=0;
  160. X
  161. X    bhitpos.x = x;
  162. X    bhitpos.y = y;
  163. X
  164. X    singleobj = splitobj(obj, obj->quan - 1L);
  165. X    /* splitobj leaves the new object in the chain (i.e. the monster's
  166. X     * inventory).  Remove it.  We can do this in 1 line, but it's highly
  167. X     * dependent on the fact that we know splitobj() places it immediately
  168. X     * after obj.
  169. X     */
  170. X    obj->nobj = singleobj->nobj;
  171. X    /* Get rid of object.  This cannot be done later on; what if the
  172. X     * player dies before then, leaving the monster with 0 daggers?
  173. X     * (This caused the infamous 2^32-1 orcish dagger bug).
  174. X     */
  175. X    if (!obj->quan) {
  176. X        if(obj->oclass == VENOM_CLASS) {
  177. X        /* venom is not in the monster's inventory chain */
  178. X        dealloc_obj(obj);
  179. X        } else {
  180. X#ifdef MUSE
  181. X        /* not possibly_unwield, which checks the object's */
  182. X        /* location, not its existence */
  183. X        if (MON_WEP(mon) == obj)
  184. X            MON_NOWEP(mon);
  185. X#endif
  186. X        m_useup(mon, obj);
  187. X        }
  188. X    }
  189. X
  190. X    if (singleobj->cursed && (dx || dy) && !rn2(7)) {
  191. X        if(canseemon(mon) && flags.verbose) {
  192. X        if((singleobj->oclass == WEAPON_CLASS ||
  193. X                        singleobj->oclass == GEM_CLASS)
  194. X           && objects[singleobj->otyp].w_propellor)
  195. X            pline("%s misfires!", Monnam(mon));
  196. X        else
  197. X            pline("The %s slips as %s throws it!",
  198. X              xname(singleobj), mon_nam(mon));
  199. X        }
  200. X        dx = rn2(3)-1;
  201. X        dy = rn2(3)-1;
  202. X        /* pre-check validity of new direction */
  203. X        if((!dx && !dy)
  204. X           || !isok(bhitpos.x+dx,bhitpos.y+dy)
  205. X           /* missile hits the wall */
  206. X           || IS_WALL(levl[bhitpos.x+dx][bhitpos.y+dy].typ)
  207. X           || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SDOOR
  208. X           || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SCORR) {
  209. X        drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
  210. X        return;
  211. X        }
  212. X    }
  213. X
  214. X    /* Note: drop_throw may destroy singleobj.  Since obj must be destroyed
  215. X     * early to avoid the dagger bug, anyone who modifies this code should
  216. X     * be careful not to use either one after it's been freed.
  217. X     */
  218. X    if (sym) tmp_at(DISP_FLASH, obj_to_glyph(singleobj));
  219. X    while(range-- > 0) { /* Actually the loop is always exited by break */
  220. X        boolean vis;
  221. X
  222. X        bhitpos.x += dx;
  223. X        bhitpos.y += dy;
  224. X        vis = cansee(bhitpos.x, bhitpos.y);
  225. X        if(MON_AT(bhitpos.x, bhitpos.y)) {
  226. X            boolean ismimic;
  227. X
  228. X            mtmp = m_at(bhitpos.x,bhitpos.y);
  229. X            ismimic = mtmp->m_ap_type &&
  230. X            mtmp->m_ap_type != M_AP_MONSTER;
  231. X
  232. X            /* don't use distance/size modifiers since target was u */
  233. X            if(find_mac(mtmp) + 8 + singleobj->spe <= rnd(20)) {
  234. X            if (!ismimic) {
  235. X                if (!vis) pline("It is missed.");
  236. X                else miss(distant_name(singleobj,xname), mtmp);
  237. X            }
  238. X            if (!range) { /* Last position; object drops */
  239. X                drop_throw(singleobj, 0, mtmp->mx, mtmp->my);
  240. X                break;
  241. X            }
  242. X#ifdef MUSE
  243. X            } else if (singleobj->oclass == POTION_CLASS) {
  244. X            if (ismimic) seemimic(mtmp);
  245. X            if (vis) singleobj->dknown = 1;
  246. X            potionhit(mtmp, singleobj);
  247. X            break;
  248. X#endif
  249. X            } else {
  250. X            damage = dmgval(singleobj, mtmp->data);
  251. X            if (damage < 1) damage = 1;
  252. X            if (singleobj->otyp==ACID_VENOM && resists_acid(mtmp->data))
  253. X                damage = 0;
  254. X            if (ismimic) seemimic(mtmp);
  255. X            if (!vis) pline("It is hit%s", exclam(damage));
  256. X            else hit(distant_name(singleobj,xname),
  257. X                            mtmp,exclam(damage));
  258. X            if (singleobj->opoisoned) {
  259. X                if (resists_poison(mtmp->data)) {
  260. X                if (vis)
  261. X                  pline("The poison doesn't seem to affect %s.",
  262. X                                mon_nam(mtmp));
  263. X                } else {
  264. X                if (rn2(30)) damage += rnd(6);
  265. X                else {
  266. X                    if (vis)
  267. X                    pline("The poison was deadly...");
  268. X                    damage = mtmp->mhp;
  269. X                }
  270. X                }
  271. X            }
  272. X            if (objects[singleobj->otyp].oc_material == SILVER
  273. X                && hates_silver(mtmp->data)) {
  274. X                if (vis) pline("The silver sears %s's flesh!",
  275. X                mon_nam(mtmp));
  276. X                else pline("Its flesh is seared!");
  277. X            }
  278. X            if (singleobj->otyp==ACID_VENOM && cansee(mtmp->mx,mtmp->my)){
  279. X                if (resists_acid(mtmp->data)) {
  280. X                pline("%s is unaffected.", vis ? Monnam(mtmp)
  281. X                    : "It");
  282. X                damage = 0;
  283. X                } else if (vis)
  284. X                pline("The acid burns %s!", mon_nam(mtmp));
  285. X                else pline("It is burned!");
  286. X            }
  287. X            mtmp->mhp -= damage;
  288. X            if(mtmp->mhp < 1) {
  289. X                pline("%s is %s!", vis ? Monnam(mtmp) : "It",
  290. X                   (is_demon(mtmp->data) || 
  291. X                    is_undead(mtmp->data) || !vis) ?
  292. X                 "destroyed" : "killed");
  293. X                mondied(mtmp);
  294. X            }
  295. X
  296. X            if(((singleobj->otyp == CREAM_PIE) ||
  297. X                (singleobj->otyp == BLINDING_VENOM))
  298. X               && haseyes(mtmp->data)) {
  299. X                if (vis)
  300. X                pline("%s is blinded by %s.",
  301. X                      Monnam(mtmp), the(xname(singleobj)));
  302. X                if(mtmp->msleep) mtmp->msleep = 0;
  303. X                mtmp->mcansee = 0;
  304. X                {
  305. X                register unsigned rnd_tmp = rnd(25) + 20;
  306. X                if((mtmp->mblinded + rnd_tmp) > 127)
  307. X                    mtmp->mblinded = 127;
  308. X                else mtmp->mblinded += rnd_tmp;
  309. X                }
  310. X            }
  311. X            drop_throw(singleobj, 1, bhitpos.x, bhitpos.y);
  312. X            break;
  313. X            }
  314. X        }
  315. X        if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
  316. X            if (multi) nomul(0);
  317. X
  318. X#ifdef MUSE
  319. X            if (singleobj->oclass == POTION_CLASS) {
  320. X                if (!Blind) singleobj->dknown = 1;
  321. X                potionhit(&youmonst, singleobj);
  322. X                break;
  323. X            }
  324. X#endif
  325. X            switch(singleobj->otyp) {
  326. X                int dam, hitv;
  327. X                case CREAM_PIE:
  328. X                case BLINDING_VENOM:
  329. X                hitu = thitu(8, 0, singleobj, xname(singleobj));
  330. X                break;
  331. X                default:
  332. X                dam = dmgval(singleobj, uasmon);
  333. X                hitv = 3 - distmin(u.ux,u.uy, mon->mx,mon->my);
  334. X                if (hitv < -4) hitv = -4;
  335. X                if (is_elf(mon->data) &&
  336. X                    objects[singleobj->otyp].w_propellor
  337. X                                == WP_BOW) {
  338. X                    hitv++;
  339. X#ifdef MUSE
  340. X                    if (MON_WEP(mon) &&
  341. X                    MON_WEP(mon)->otyp == ELVEN_BOW)
  342. X                    hitv++;
  343. X#endif
  344. X                    if(singleobj->otyp == ELVEN_ARROW) dam++;
  345. X                }
  346. X#ifdef POLYSELF
  347. X                if (bigmonst(uasmon)) hitv++;
  348. X#endif
  349. X                hitv += 8+singleobj->spe;
  350. X
  351. X                if (dam < 1) dam = 1;
  352. X                hitu = thitu(hitv, dam,
  353. X                    singleobj, xname(singleobj));
  354. X            }
  355. X            if (hitu && singleobj->opoisoned)
  356. X                /* it's safe to call xname twice because it's the
  357. X                   same object both times... */
  358. X                poisoned(xname(singleobj), A_STR, xname(singleobj), 10);
  359. X            if(hitu && (singleobj->otyp == CREAM_PIE ||
  360. X                     singleobj->otyp == BLINDING_VENOM)) {
  361. X                blindinc = rnd(25);
  362. X                if(singleobj->otyp == CREAM_PIE) {
  363. X                if(!Blind) pline("Yecch!  You've been creamed.");
  364. X                else    pline("There's something sticky all over your %s.", body_part(FACE));
  365. X                } else {    /* venom in the eyes */
  366. X                if(Blindfolded) /* nothing */ ;
  367. X                else if(!Blind) pline("The venom blinds you.");
  368. X                else    Your("%s sting.",
  369. X                    makeplural(body_part(EYE)));
  370. X                }
  371. X            }
  372. X            stop_occupation();
  373. X            if (hitu || !range) {
  374. X                drop_throw(singleobj, hitu, u.ux, u.uy);
  375. X                break;
  376. X            }
  377. X        } else if (!range    /* reached end of path */
  378. X            /* missile hits edge of screen */
  379. X            || !isok(bhitpos.x+dx,bhitpos.y+dy)
  380. X            /* missile hits the wall */
  381. X            || IS_WALL(levl[bhitpos.x+dx][bhitpos.y+dy].typ)
  382. X            || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SDOOR
  383. X            || levl[bhitpos.x+dx][bhitpos.y+dy].typ == SCORR
  384. X#ifdef SINKS
  385. X            /* Thrown objects "sink" */
  386. X            || IS_SINK(levl[bhitpos.x][bhitpos.y].typ)
  387. X#endif
  388. X                                ) {
  389. X            drop_throw(singleobj, 0, bhitpos.x, bhitpos.y);
  390. X            break;
  391. X        }
  392. X        tmp_at(bhitpos.x, bhitpos.y);
  393. X        delay_output();
  394. X    }
  395. X    tmp_at(bhitpos.x, bhitpos.y);
  396. X    delay_output();
  397. X    tmp_at(DISP_END, 0);
  398. X    /* blindfold keeps substances out of your eyes */
  399. X    if (blindinc && !Blindfolded) {
  400. X        u.ucreamed += blindinc;
  401. X        make_blinded(Blinded + blindinc,FALSE);
  402. X    }
  403. X}
  404. X
  405. X#endif /* OVL1 */
  406. X#ifdef OVLB
  407. X
  408. X/* Remove an item from the monster's inventory.
  409. X */
  410. Xvoid
  411. Xm_useup(mon, obj)
  412. Xstruct monst *mon;
  413. Xstruct obj *obj;
  414. X{
  415. X    struct obj *otmp, *prev;
  416. X
  417. X    if (obj->quan > 1L) {
  418. X        obj->quan--;
  419. X        return;
  420. X    }
  421. X    prev = ((struct obj *) 0);
  422. X    for (otmp = mon->minvent; otmp; otmp = otmp->nobj) {
  423. X        if (otmp == obj) {
  424. X            if (prev)
  425. X                prev->nobj = obj->nobj;
  426. X            else
  427. X                mon->minvent = obj->nobj;
  428. X            dealloc_obj(obj);
  429. X            break;
  430. X        }
  431. X        prev = otmp;
  432. X    }
  433. X}
  434. X
  435. X#endif /* OVLB */
  436. X#ifdef OVL1
  437. X
  438. Xvoid
  439. Xthrwmu(mtmp)    /* monster throws item at you */
  440. Xregister struct monst *mtmp;
  441. X{
  442. X    struct obj *otmp;
  443. X    register xchar x, y;
  444. X
  445. X    if(lined_up(mtmp)) {
  446. X#ifdef MUSE
  447. X        if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
  448. X        mtmp->weapon_check = NEED_RANGED_WEAPON;
  449. X        /* mon_wield_item resets weapon_check as appropriate */
  450. X        if(mon_wield_item(mtmp) != 0) return;
  451. X        }
  452. X#endif
  453. X        if((otmp = select_rwep(mtmp))) {
  454. X        /* If you are coming toward the monster, the monster
  455. X         * should try to soften you up with missiles.  If you are
  456. X         * going away, you are probably hurt or running.  Give
  457. X         * chase, but if you are getting too far away, throw.
  458. X         */
  459. X        x = mtmp->mx;
  460. X        y = mtmp->my;
  461. X        if(!URETREATING(x,y) ||
  462. X           !rn2(BOLT_LIM-distmin(x,y,mtmp->mux,mtmp->muy)))
  463. X        {
  464. X            const char *verb = "throws";
  465. X
  466. X            if (otmp->otyp == ARROW
  467. X            || otmp->otyp == ELVEN_ARROW
  468. X            || otmp->otyp == ORCISH_ARROW
  469. X            || otmp->otyp == CROSSBOW_BOLT) verb = "shoots";
  470. X            if (canseemon(mtmp)) {
  471. X            pline("%s %s %s!", Monnam(mtmp), verb,
  472. X                  obj_is_pname(otmp) ?
  473. X                  the(singular(otmp, xname)) :
  474. X                  an(singular(otmp, xname)));
  475. X            }
  476. X            m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 
  477. X            distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp);
  478. X            nomul(0);
  479. X            return;
  480. X        }
  481. X        }
  482. X    }
  483. X}
  484. X
  485. X#endif /* OVL1 */
  486. X#ifdef OVLB
  487. X
  488. Xint
  489. Xspitmu(mtmp, mattk)        /* monster spits substance at you */
  490. Xregister struct monst *mtmp;
  491. Xregister struct attack *mattk;
  492. X{
  493. X    register struct obj *otmp;
  494. X
  495. X    if(mtmp->mcan) {
  496. X
  497. X        if(flags.soundok)
  498. X        pline("A dry rattle comes from %s throat", 
  499. X                              s_suffix(mon_nam(mtmp)));
  500. X        return 0;
  501. X    }
  502. X    if(lined_up(mtmp)) {
  503. X        switch (mattk->adtyp) {
  504. X            case AD_BLND:
  505. X            case AD_DRST:
  506. X            otmp = mksobj(BLINDING_VENOM, TRUE, FALSE);
  507. X            break;
  508. X            default:
  509. X            impossible("bad attack type in spitmu");
  510. X                /* fall through */
  511. X            case AD_ACID:
  512. X            otmp = mksobj(ACID_VENOM, TRUE, FALSE);
  513. X            break;
  514. X        }
  515. X        if(!rn2(BOLT_LIM-distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy))) {
  516. X            if (canseemon(mtmp))
  517. X            pline("%s spits venom!", Monnam(mtmp));
  518. X            m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), 
  519. X            distmin(mtmp->mx,mtmp->my,mtmp->mux,mtmp->muy), otmp);
  520. X            nomul(0);
  521. X            return 0;
  522. X        }
  523. X    }
  524. X    return 0;
  525. X}
  526. X
  527. X#endif /* OVLB */
  528. X#ifdef OVL1
  529. X
  530. Xint
  531. Xbreamu(mtmp, mattk)            /* monster breathes at you (ranged) */
  532. X    register struct monst *mtmp;
  533. X    register struct attack  *mattk;
  534. X{
  535. X    /* if new breath types are added, change AD_ACID to max type */
  536. X    int typ = (mattk->adtyp == AD_RBRE) ? rnd(AD_ACID) : mattk->adtyp ;
  537. X
  538. X    if(lined_up(mtmp)) {
  539. X
  540. X        if(mtmp->mcan) {
  541. X        if(flags.soundok) {
  542. X            if(canseemon(mtmp))
  543. X            pline("%s coughs.", Monnam(mtmp));
  544. X            else
  545. X            You("hear a cough.");
  546. X        }
  547. X        return(0);
  548. X        }
  549. X        if(!mtmp->mspec_used && rn2(3)) {
  550. X
  551. X        if((typ >= AD_MAGM) && (typ <= AD_ACID)) {
  552. X
  553. X            if(canseemon(mtmp))
  554. X            pline("%s breathes %s!", Monnam(mtmp),
  555. X                  breathwep[typ-1]);
  556. X            buzz((int) (-20 - (typ-1)), (int)mattk->damn,
  557. X             mtmp->mx, mtmp->my, sgn(tbx), sgn(tby));
  558. X            nomul(0);
  559. X            /* breath runs out sometimes. Also, give monster some
  560. X             * cunning; don't breath if the player fell asleep.
  561. X             */
  562. X            if(!rn2(3))
  563. X            mtmp->mspec_used = 10+rn2(20);
  564. X            if(typ == AD_SLEE && !Sleep_resistance)
  565. X            mtmp->mspec_used += rnd(20);
  566. X        } else impossible("Breath weapon %d used", typ-1);
  567. X        }
  568. X    }
  569. X    return(1);
  570. X}
  571. X
  572. Xboolean
  573. Xlinedup(ax, ay, bx, by)
  574. Xregister xchar ax, ay, bx, by;
  575. X{
  576. X    tbx = ax - bx;    /* These two values are set for use */
  577. X    tby = ay - by;    /* after successful return.        */
  578. X
  579. X    if((!tbx || !tby || abs(tbx) == abs(tby)) /* straight line or diagonal */
  580. X       && distmin(tbx, tby, 0, 0) < BOLT_LIM) {
  581. X
  582. X        if(ax == u.ux && ay == u.uy) return couldsee(bx,by);
  583. X        else if(clear_path(ax,ay,bx,by)) return TRUE;
  584. X    }
  585. X    return FALSE;
  586. X}
  587. X
  588. Xboolean
  589. Xlined_up(mtmp)        /* is mtmp in position to use ranged attack? */
  590. X    register struct monst *mtmp;
  591. X{
  592. X    return(linedup(mtmp->mux,mtmp->muy,mtmp->mx,mtmp->my));
  593. X}
  594. X
  595. X#endif /* OVL1 */
  596. X#ifdef OVL0
  597. X
  598. X/* Check if a monster is carrying a particular item.
  599. X */
  600. Xstruct obj *
  601. Xm_carrying(mtmp, type)
  602. Xstruct monst *mtmp;
  603. Xint type;
  604. X{
  605. X    register struct obj *otmp;
  606. X
  607. X    for(otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
  608. X        if(otmp->otyp == type)
  609. X            return(otmp);
  610. X    return((struct obj *) 0);
  611. X}
  612. X
  613. X#endif /* OVL0 */
  614. X
  615. X/*mthrowu.c*/
  616. END_OF_FILE
  617. if test 15122 -ne `wc -c <'src/mthrowu.c'`; then
  618.     echo shar: \"'src/mthrowu.c'\" unpacked with wrong size!
  619. fi
  620. # end of 'src/mthrowu.c'
  621. fi
  622. if test -f 'sys/amiga/wb.c1' -a "${1}" != "-c" ; then 
  623.   echo shar: Will not clobber existing file \"'sys/amiga/wb.c1'\"
  624. else
  625. echo shar: Extracting \"'sys/amiga/wb.c1'\" \(39564 characters\)
  626. sed "s/^X//" >'sys/amiga/wb.c1' <<'END_OF_FILE'
  627. X/*    SCCS Id: @(#)wb.c     2.1   93/01/08              */
  628. X/*    Copyright (c) Kenneth Lorber, Bethesda Maryland, 1991      */
  629. X/*    Copyright (c) Gregg Wonderly, Naperville IL, 1992, 1993      */
  630. X/* NetHack may be freely redistributed.  See license for details. */
  631. X
  632. X/* Friendly Intuition interface for NetHack 3.1 on the Amiga */
  633. X
  634. X#ifdef AZTEC_C
  635. X/* Aztec doesn't recognize __chip syntax */
  636. X# define __chip
  637. X#endif
  638. X
  639. X#include "Amiga:wbdefs.h"        /* Miscellany information */
  640. X#ifdef  INTUI_NEW_LOOK
  641. X#define NewWindow   ExtNewWindow
  642. X#define NewScreen   ExtNewScreen
  643. X#endif
  644. X#include "Amiga:wbstruct.h"
  645. X#include "Amiga:wbprotos.h"
  646. X
  647. X#include "Amiga:wbdata.c"        /* All structures and global data */
  648. X#include "Amiga:wbwin.c"        /* Has static definitions */
  649. X
  650. X#define C_GREY  0
  651. X#define C_BLACK 1
  652. X#define C_WHITE 2
  653. X#define C_BLUE  3
  654. X
  655. X#ifndef __SASC_60
  656. Xextern char *sys_errlist[];
  657. X#endif
  658. Xextern int errno;
  659. X
  660. Xchar pubscreen[ 80 ] = { "HackWB" };
  661. Xchar mytitle[ 80 ];
  662. X
  663. X#ifdef  INTUI_NEW_LOOK
  664. Xint scrlocked = 0;
  665. XUWORD scrnpens[] = { 0xffff };
  666. X
  667. Xstruct TagItem scrntags[] =
  668. X{
  669. X    (Tag)SA_Pens, (ULONG)scrnpens,
  670. X    TAG_DONE, 0,
  671. X    TAG_DONE, 0,
  672. X    TAG_DONE, 0,
  673. X    TAG_DONE, 0,
  674. X    TAG_DONE, 0,
  675. X    TAG_DONE, 0,
  676. X    TAG_DONE, 0,
  677. X};
  678. X#endif
  679. X
  680. X#define SPLIT            /* use splitter, if available */
  681. X#ifdef SPLIT
  682. Xint running_split=0;        /* if 0, using normal LoadSeg/UnLoadSeg */
  683. X#endif
  684. X
  685. X#ifdef AZTEC_C
  686. Xextern char *strdup(char *);
  687. X#endif
  688. X
  689. X#ifndef max
  690. X# define max(a, b) ((a) > (b) ? (a) : (b))
  691. X#endif
  692. X#ifndef min
  693. X# define min(x,y) ((x) < (y) ? (x) : (y))
  694. X#endif
  695. X
  696. Xvoid diskobj_filter(struct DiskObject *);
  697. Xstatic void UpdateInfoWin( struct Window *cwin );
  698. XBPTR s_LoadSeg(char *);
  699. Xvoid s_UnLoadSeg(void);
  700. X
  701. Xmain( argc, argv )
  702. X    int argc;
  703. X    struct WBStartup *argv;
  704. X{
  705. X    long mask, rmask;
  706. X    struct WBStartup *wbs;
  707. X    struct WBArg *wba;
  708. X    GPTR gptr;
  709. X    struct IntuiMessage *imsg;
  710. X    struct IntuiMessage mimsg;
  711. X    int i;
  712. X
  713. X    ZapOptions( curopts );
  714. X    InitWB( argc, argv );
  715. X    SetupWB( ); /* open window, build menus */
  716. X    errmsg( NO_FLASH, "Welcome to NetHack Version 3.1!" );
  717. X    CopyRight( );
  718. X
  719. X    ReadConfig( );
  720. X    LoadDefaults( defgname );
  721. X
  722. X    /* Initially, no game selected so disable menu items */
  723. X
  724. X    ChgGameItems( &MenuList1, 0 );
  725. X
  726. X    MapGadgets( R_DISK, 1 ); /* Display the icons */
  727. X
  728. X    /* Wait till user quits */
  729. X
  730. X    while( !quit )
  731. X    {
  732. X    /* Wait for a message */
  733. X
  734. X    mask = ( 1L << dosport->mp_SigBit ) ;
  735. X    if( wbopen )
  736. X        mask |= ( 1L << win->UserPort->mp_SigBit );
  737. X
  738. X    rmask = Wait( mask );
  739. X
  740. X    /* If displayed an error message before, clear it */
  741. X
  742. X    if( errup )
  743. X    {
  744. X        errmsg( NO_FLASH, "" );
  745. X        errup = 0;
  746. X    }
  747. X
  748. X    /* Process the messages on the port unless the workbench is
  749. X     * shutdown by a request to play a game.
  750. X     */
  751. X
  752. X    while( wbopen && ( imsg = ( struct IntuiMessage * )
  753. X        GetMsg( win->UserPort ) ) )
  754. X    {
  755. X        /* Copy the message.  This does not guarantee that all
  756. X         * fields will still be valid, but appears to work
  757. X         * here.  Note that we have to reply to the message
  758. X         * before the workbench window is closed.
  759. X         */
  760. X
  761. X        mimsg = *imsg;
  762. X        ReplyMsg( (struct Message *)imsg );
  763. X
  764. X        switch( mimsg.Class )
  765. X        {
  766. X        case NEWSIZE:
  767. X        ((struct Border *) Message.GadgetRender)->XY[2] =
  768. X            win->Width - win->BorderLeft -
  769. X            win->BorderRight - 1;
  770. X        RefreshGList( &Message, win, NULL, 1 );
  771. X        MapGadgets( R_SCROLL, 1 ); /* redisplay the icons */
  772. X#ifdef  INTUI_NEW_LOOK
  773. X        if( IntuitionBase->LibNode.lib_Version >= 37 )
  774. X            RefreshWindowFrame( win );
  775. X#endif
  776. X        break;
  777. X
  778. X        case MENUPICK:
  779. X        do_menu( mimsg.Code );
  780. X        break;
  781. X
  782. X        case RAWKEY:
  783. X        if( mimsg.Code == 0x5f )
  784. X        {
  785. X            /* Pick the correct help message */
  786. X
  787. X            if( lastgaddown == NULL )
  788. X            {
  789. X            text_requester( &Help1_NewWindowStructure7,
  790. X                &Help1_IntuiTextList7 );
  791. X            }
  792. X            else
  793. X            {
  794. X            text_requester( &Help2_NewWindowStructure8,
  795. X                &Help2_IntuiTextList8 );
  796. X            }
  797. X        }
  798. X        break;
  799. X
  800. X        case CLOSEWINDOW:
  801. X        if( Ask( "Ready to Quit?" ) )
  802. X            do_closewindow( );
  803. X        break;
  804. X
  805. X        case GADGETDOWN:
  806. X        do_gadgetdown( &mimsg );
  807. X        break;
  808. X
  809. X        case GADGETUP:
  810. X        do_gadgetup( &mimsg );
  811. X        break;
  812. X
  813. X        case DISKINSERTED:
  814. X        MapGadgets( R_DISK, 1 );
  815. X        break;
  816. X
  817. X        case MOUSEBUTTONS:
  818. X        do_buttons( &mimsg );
  819. X        break;
  820. X        }
  821. X    }
  822. X
  823. X    if( rmask & ( 1L << dosport->mp_SigBit ) )
  824. X    {
  825. X        /* Get process termination messages */
  826. X
  827. X        while( wbs = (struct WBStartup *) GetMsg( dosport ) )
  828. X        {
  829. X        /* Find the game that has terminated */
  830. X
  831. X        for( gptr = gamehead; gptr && gptr->seglist != wbs->sm_Segment;)
  832. X            gptr = gptr->next;
  833. X
  834. X        /* Make sure it is there */
  835. X
  836. X        if( gptr )
  837. X        {
  838. X#ifdef SPLIT
  839. X            if(!running_split)
  840. X#endif
  841. X            {
  842. X            /* Unload the code */
  843. X            UnLoadSeg( wbs->sm_Segment );
  844. X            }
  845. X
  846. X            /* Free the startup message resources */
  847. X            wba = (struct WBArg *)
  848. X            ((long)wbs + sizeof( struct WBStartup ));
  849. X            for( i = 0; i < wbs->sm_NumArgs; ++i )
  850. X            {
  851. X            FreeMem( wba[i].wa_Name,
  852. X                strlen( wba[i].wa_Name ) + 1 );
  853. X            UnLock( wba[i].wa_Lock );
  854. X            }
  855. X            FreeMem( wbs, wbs->sm_Message.mn_Length );
  856. X            wbs = NULL;
  857. X
  858. X            /* Say the game has completed */
  859. X
  860. X            gptr->prc = NULL;
  861. X            gptr->active = 0;
  862. X            active_count--;
  863. X        }
  864. X        }
  865. X
  866. X        /* If the workbench was closed, open it back up */
  867. X
  868. X        if( !wbopen )
  869. X        SetupWB( );
  870. X
  871. X        /* Reload to clear any deleted games */
  872. X
  873. X        MapGadgets( R_DISK, 1 );
  874. X    }
  875. X    }
  876. X    cleanup( 0 );
  877. X}
  878. X
  879. Xvoid CopyRight( )
  880. X{
  881. X    extern char *copyright_text[];
  882. X    int line;
  883. X
  884. X    SetDrMd( win->RPort, JAM2 );
  885. X    SetAPen( win->RPort, C_WHITE );
  886. X    SetBPen( win->RPort, C_GREY );
  887. X
  888. X    for(line=0;copyright_text[line];line++){
  889. X    Move( win->RPort, ORIGINX+3, ORIGINY + win->RPort->TxBaseline +
  890. X        (line*win->RPort->TxHeight));
  891. X    if(copyright_text[line][0])
  892. X         RPText( win->RPort, copyright_text[line]);
  893. X    }
  894. X
  895. X    Delay( 150 );
  896. X    ClearWindow( win );
  897. X}
  898. X
  899. X/*
  900. X * Do the one time initialization things.
  901. X */
  902. X
  903. Xvoid
  904. XInitWB( argc, wbs )
  905. X    int argc;
  906. X    register struct WBStartup *wbs;
  907. X{
  908. X    register int c, i, j;
  909. X    BPTR odir;
  910. X    char *s, **tools, **argv;
  911. X    register struct DiskObject *dobj;
  912. X    register struct WBArg *wba;
  913. X
  914. X    /* Open Libraries */
  915. X    GfxBase= (struct GfxBase *) OldOpenLibrary("graphics.library");
  916. X    IconBase= OldOpenLibrary("icon.library");
  917. X    DiskfontBase= (struct DiskfontBase *)OldOpenLibrary("diskfont.library");
  918. X    IntuitionBase= (struct IntuitionBase *)OldOpenLibrary("intuition.library");
  919. X
  920. X    if(!GfxBase || !IconBase || !DiskfontBase || !IntuitionBase)
  921. X    {
  922. X    error("library open failed");
  923. X    cleanup( 1 );
  924. X    }
  925. X
  926. X    /* Get Port for replied WBStartup messages */
  927. X
  928. X    if( ( dosport = CreatePort( NULL, 0 ) ) == NULL )
  929. X    {
  930. X    error("failed to create dosport" );
  931. X    cleanup( 1 );
  932. X    }
  933. X
  934. X    /* If started from CLI */
  935. X    if( argc != 0 )
  936. X    {
  937. X    argv = (char **)wbs;
  938. X    for( i = 1; i < argc; ++i )
  939. X    {
  940. X        if( argv[i][0] != '-' )
  941. X        break;
  942. X        for( j = 1; c = argv[i][j]; ++j )
  943. X        {
  944. X        switch( c )
  945. X        {
  946. X        case 'm':   /* Close screen and window during game to
  947. X                 * save memory  */
  948. X            shutdown++;
  949. X            break;
  950. X
  951. X        case 'c':       /* Configuration to load */
  952. X            if( i + 1 < argc && argv[i][j+1] == 0 )
  953. X            {
  954. X            strcpy( NetHackCnf, argv[ ++i ] );
  955. X            goto nextargv;
  956. X            }
  957. X            else
  958. X            {
  959. X            fprintf( stderr,
  960. X                "%s: missing config name after -c\n",
  961. X                argv[ 0 ] );
  962. X            cleanup( 1 );
  963. X            }
  964. X            break;
  965. X
  966. X        case 'N':       /* Public screen name */
  967. X            if( i + 1 < argc && argv[i][j+1] == 0 )
  968. X            {
  969. X            strcpy( pubscreen, argv[ ++i ] );
  970. X            goto nextargv;
  971. X            }
  972. X            else
  973. X            {
  974. X            fprintf( stderr,
  975. X                "%s: missing screen name after -N\n",
  976. X                argv[ 0 ] );
  977. X            cleanup( 1 );
  978. X            }
  979. X            break;
  980. X
  981. X        case 'f':       /* Default game "player" */
  982. X            if( i + 1 < argc && argv[i][j+1] == 0 )
  983. X            {
  984. X            strcpy( defgname, argv[ ++i ] );
  985. X            goto nextargv;
  986. X            }
  987. X            else
  988. X            {
  989. X            fprintf( stderr,
  990. X                "%s: missing name after -f\n",
  991. X                argv[ 0 ] );
  992. X                cleanup( 1 );
  993. X            }
  994. X            break;
  995. X
  996. X        default:
  997. X            fprintf( stderr, "%s: invalid option %c\n",
  998. X            argv[0], c );
  999. X            fprintf( stderr,
  1000. X            "usage: %s [-m] [-f name] [-c name][ -N screen] \n",
  1001. X            argv[ 0 ] );
  1002. X            cleanup( 1 );
  1003. X        }
  1004. X        }
  1005. Xnextargv:;
  1006. X    }
  1007. X    }
  1008. X    else
  1009. X    {
  1010. X    /* Process icon's ToolTypes */
  1011. X
  1012. X    wba = wbs->sm_ArgList;
  1013. X    odir = CurrentDir( wba->wa_Lock );
  1014. X    if( dobj = GetDiskObject( wba->wa_Name ) )
  1015. X    {
  1016. X        tools = (char **) dobj->do_ToolTypes;
  1017. X
  1018. X        if( s = FindToolType( tools, "OPTIONS" ) )
  1019. X        {
  1020. X        /* OPTIONS=SHUTDOWN will cause the screen to be closed
  1021. X         * when a game is started
  1022. X         */
  1023. X        if( MatchToolValue( s, "SHUTDOWN" ) )
  1024. X            ++shutdown;
  1025. X        }
  1026. X
  1027. X        /* A different configuration file name */
  1028. X
  1029. X        if( s = FindToolType( tools, "CONFIG" ) )
  1030. X        {
  1031. X        strcpy( NetHackCnf, s );
  1032. X        }
  1033. X
  1034. X        /* A different set of defaults then 'wbdefaults.def' */
  1035. X
  1036. X        if( s = FindToolType( tools, "DEFAULT" ) )
  1037. X        {
  1038. X        strcpy( defgname, s );
  1039. X        }
  1040. X
  1041. X        /* A Public screen to open onto */
  1042. X
  1043. X        if( s = FindToolType( tools, "SCREEN" ) )
  1044. X        {
  1045. X        strcpy( pubscreen, s );
  1046. X        }
  1047. X
  1048. X        FreeDiskObject( dobj );
  1049. X    }
  1050. X    if( odir )
  1051. X        CurrentDir( odir );
  1052. X    }
  1053. X}
  1054. X
  1055. X/*
  1056. X * Read a nethack.cnf like file and collect the configuration
  1057. X * information from it.
  1058. X */
  1059. Xvoid ReadConfig()
  1060. X{
  1061. X    register FILE *fp;
  1062. X    register char *buf, *t;
  1063. X
  1064. X    /* Use a dynamic buffer to limit stack use */
  1065. X
  1066. X    if( ( buf = xmalloc( 1024 ) ) == NULL )
  1067. X    {
  1068. X    error( "Can't alloc space to read config file" );
  1069. X    cleanup( 1 );
  1070. X    }
  1071. X
  1072. X    /* If the file is not there, can't load it */
  1073. X
  1074. X    if( ( fp = fopen( NetHackCnf, "r" ) ) == NULL )
  1075. X    {
  1076. X    errmsg( FLASH, "Can't load config file %s", NetHackCnf );
  1077. X    free( buf );
  1078. X    return;
  1079. X    }
  1080. X
  1081. X    /* Read the lines... */
  1082. X
  1083. X    while( fgets( buf, 1024, fp ) != NULL )
  1084. X    {
  1085. X    if( *buf == '#' )
  1086. X        continue;
  1087. X
  1088. X    if( ( t = strchr( buf, '\n' ) ) != NULL )
  1089. X        *t = 0;
  1090. X
  1091. X    if( strnicmp( buf, "PATH=", 5 ) == 0 )
  1092. X    {
  1093. X        setoneopt( PATH_IDX, buf + 5 );
  1094. X    }
  1095. X    else if( strnicmp( buf, "PENS=", 4 ) == 0 )
  1096. X    {
  1097. X        setoneopt( PENS_IDX, buf + 4 );
  1098. X    }
  1099. X    else if( strnicmp( buf, "OPTIONS=", 8 ) == 0 )
  1100. X    {
  1101. X        setoneopt( OPTIONS_IDX, buf + 8 );
  1102. X    }
  1103. X    else if( strnicmp( buf, "HACKDIR=", 8 ) == 0 )
  1104. X    {
  1105. X        setoneopt( HACKDIR_IDX, buf + 8 );
  1106. X    }
  1107. X    else if( strnicmp( buf, "LEVELS=", 7 ) == 0 )
  1108. X    {
  1109. X        setoneopt( LEVELS_IDX, buf + 7 );
  1110. X    }
  1111. X    else if( strnicmp( buf, "SAVE=", 5 ) == 0 )
  1112. X    {
  1113. X        setoneopt( SAVE_IDX, buf + 5 );
  1114. X    }
  1115. X    else
  1116. X    {
  1117. X        /* We don't allow manipulation of the other information */
  1118. X    }
  1119. X    }
  1120. X    fclose( fp );
  1121. X    free( buf );
  1122. X}
  1123. X
  1124. X/* Close the workbench screen and window */
  1125. X
  1126. Xvoid CloseDownWB( )
  1127. X{
  1128. X    ((struct Process *)FindTask( NULL ))->pr_WindowPtr = (APTR)oldwin;
  1129. X
  1130. X    if( win && win->RPort->TmpRas )
  1131. X    {
  1132. X    FreeRaster( tmprasp, width, height );
  1133. X    }
  1134. X
  1135. X    if( win )
  1136. X    SafeCloseWindow( win );
  1137. X
  1138. X#ifdef  INTUI_NEW_LOOK
  1139. X    if( IntuitionBase->LibNode.lib_Version >= 37 )
  1140. X    {
  1141. X    while( !scrlocked && CloseScreen( scrn ) == FALSE )
  1142. X    {
  1143. X        Ask("Close all vistor Windows to exit" );
  1144. X    }
  1145. X    }
  1146. X    else
  1147. X#endif
  1148. X    {
  1149. X    CloseScreen( scrn );
  1150. X    }
  1151. X    wbopen = 0;
  1152. X}
  1153. X
  1154. X/* Open the workbench screen and window. */
  1155. X
  1156. Xvoid SetupWB( )
  1157. X{
  1158. X    int cpyrwid, i;
  1159. X    int txtdiff;
  1160. X#ifdef  INTUI_NEW_LOOK
  1161. X    int pubopen = 0;
  1162. X#endif
  1163. X    static int once = 0;
  1164. X
  1165. X    scrlocked = 0;
  1166. X#ifdef  INTUI_NEW_LOOK
  1167. X    NewScreenStructure.Extension = scrntags;
  1168. X    NewScreenStructure.Type |= NS_EXTENDED;
  1169. X#endif
  1170. X
  1171. X    NewScreenStructure.Width = GfxBase->NormalDisplayColumns;
  1172. X    NewScreenStructure.Height = GfxBase->NormalDisplayRows;
  1173. X
  1174. X#ifdef  INTUI_NEW_LOOK
  1175. X    if( IntuitionBase->LibNode.lib_Version < 37 )
  1176. X    {
  1177. X#endif
  1178. X    if( ( scrn = OpenScreen( (void *)
  1179. X        &NewScreenStructure ) ) == NULL )
  1180. X    {
  1181. X        error( "Can't create screen" );
  1182. X        cleanup( 1 );
  1183. X    }
  1184. X
  1185. X    /* Only set the pens on the screen we open */
  1186. X    LoadRGB4( &scrn->ViewPort, Palette, PaletteColorCount );
  1187. X#ifdef  INTUI_NEW_LOOK
  1188. X    }
  1189. X    else
  1190. X    {
  1191. X    /* No tags beyond here yet */
  1192. X    scrntags[1].ti_Tag = TAG_DONE;
  1193. X
  1194. X    if( *pubscreen != 0 )
  1195. X    {
  1196. X        if( ( scrn = LockPubScreen( pubscreen ) ) == 0 )
  1197. X        {
  1198. X        scrntags[1].ti_Tag = SA_PubName;
  1199. X        scrntags[1].ti_Data = (ULONG) pubscreen;
  1200. X        scrntags[2].ti_Tag = TAG_DONE;
  1201. X        if( ( scrn = OpenScreen( (void *)
  1202. X            &NewScreenStructure ) ) == NULL )
  1203. X        {
  1204. X            error( "Can't create screen" );
  1205. X            cleanup( 1 );
  1206. X        }
  1207. X        pubopen = 1;
  1208. X        scrlocked = 0;
  1209. X        }
  1210. X        else
  1211. X        {
  1212. X        pubopen = 0;
  1213. X        scrlocked = 1;
  1214. X        }
  1215. X    }
  1216. X    else
  1217. X    {
  1218. X        if( ( scrn = LockPubScreen( NULL ) ) == 0 )
  1219. X        {
  1220. X        error( "Can't lock Workbench screen" );
  1221. X        cleanup( 1 );
  1222. X        }
  1223. X        scrlocked = 1;
  1224. X    }
  1225. X    }
  1226. X#endif
  1227. X
  1228. X    cpyrwid = 0;
  1229. X    for( i = 0; copyright_text[i]; ++i )
  1230. X    cpyrwid = max(cpyrwid, strlen( copyright_text[i] ) );
  1231. X
  1232. X    /* 28 is magic for the width of the sizing gadget under 2.04 and
  1233. X     * later.
  1234. X     */
  1235. X    NewWindowStructure1.Width = (cpyrwid * scrn->RastPort.TxWidth) +
  1236. X        scrn->WBorLeft + scrn->WBorRight + 28;
  1237. X
  1238. X    width = NewWindowStructure1.Width;
  1239. X
  1240. X    if( NewWindowStructure1.LeftEdge + width > scrn->Width )
  1241. X    {
  1242. X    if( width > scrn->Width )
  1243. X    {
  1244. X        NewWindowStructure1.LeftEdge = 0;
  1245. X        NewWindowStructure1.Width = scrn->Width;
  1246. X    }
  1247. X    else
  1248. X    {
  1249. X        NewWindowStructure1.LeftEdge = (scrn->Width - width)/2;
  1250. X    }
  1251. X    }
  1252. X    height = NewWindowStructure1.Height;
  1253. X    NewWindowStructure1.Screen = scrn;
  1254. X
  1255. X    txtdiff = scrn->RastPort.TxHeight - 8;
  1256. X
  1257. X#ifdef  INTUI_NEW_LOOK
  1258. X    if( scrlocked )
  1259. X    strcpy( mytitle, "NetHack WB 3.1 - Select a GAME or press HELP" );
  1260. X    else
  1261. X    strcpy( mytitle, "Select a GAME or press HELP" );
  1262. X
  1263. X    NewWindowStructure1.Title = mytitle;
  1264. X    if( IntuitionBase->LibNode.lib_Version >= 37 )
  1265. X    {
  1266. X    ((struct PropInfo *)Scroll.SpecialInfo)->Flags |= PROPNEWLOOK;
  1267. X    }
  1268. X#endif
  1269. X
  1270. X    if( !once )
  1271. X    {
  1272. X    ((struct Border *) Message.GadgetRender)->XY[2] =
  1273. X        NewWindowStructure1.Width +
  1274. X        Message.Width - Message.LeftEdge;
  1275. X    Message.TopEdge = scrn->RastPort.TxHeight + scrn->WBorTop + 1;
  1276. X    Message.Height = scrn->RastPort.TxHeight + 3;
  1277. X        ((struct Border *) Message.GadgetRender)->XY[1] =
  1278. X        (((struct Border *) Message.GadgetRender)->XY[3] +=
  1279. X        scrn->RastPort.TxHeight - 6 );
  1280. X    }
  1281. X
  1282. X    if( ( win = MyOpenWindow( &NewWindowStructure1 ) ) == NULL )
  1283. X    {
  1284. X#ifdef  INTUI_NEW_LOOK
  1285. X    if( IntuitionBase->LibNode.lib_Version >= 37 )
  1286. X    {
  1287. X        if( scrlocked )
  1288. X        UnlockPubScreen( NULL, scrn );
  1289. X    }
  1290. X#endif
  1291. X    error( "Can't create window" );
  1292. X    cleanup( 1 );
  1293. X    }
  1294. X#ifdef  INTUI_NEW_LOOK
  1295. X    if( IntuitionBase->LibNode.lib_Version >= 37 )
  1296. X    {
  1297. X    if( scrlocked )
  1298. X        UnlockPubScreen( NULL, scrn );
  1299. X    else if( pubopen )
  1300. X        PubScreenStatus( scrn, 0 );
  1301. X    }
  1302. X#endif
  1303. X
  1304. X    ((struct Border *) Message.GadgetRender)->XY[2] =
  1305. X        win->Width - win->BorderLeft -
  1306. X        win->BorderRight - 1;
  1307. X
  1308. X    RefreshGList( &Message, win, NULL, 1 );
  1309. X#ifdef  INTUI_NEW_LOOK
  1310. X    if( IntuitionBase->LibNode.lib_Version >= 37 )
  1311. X    RefreshWindowFrame( win );
  1312. X#endif
  1313. X
  1314. X    oldwin = (struct Window *)((struct Process *)FindTask( NULL ))->pr_WindowPtr;
  1315. X    ((struct Process *)FindTask( NULL ))->pr_WindowPtr = (APTR)win;
  1316. X
  1317. X    if( ( tmprasp = (void *) AllocRaster( width, height ) ) == NULL )
  1318. X    {
  1319. X    win->RPort->TmpRas = NULL;
  1320. X    fprintf( stderr, "No Space for raster %d x %d\n", height, width );
  1321. X    cleanup( 1 );
  1322. X    }
  1323. X
  1324. X    InitTmpRas( &tmpras, tmprasp, RASSIZE( width, height ) );
  1325. X
  1326. X    win->RPort->TmpRas = &tmpras;
  1327. X
  1328. X    SetUpMenus( &MenuList1, scrn );
  1329. X    SetMenuStrip( win, &MenuList1 );
  1330. X    wbopen = 1;
  1331. X    once = 1;
  1332. X}
  1333. X
  1334. X/* Map the gadgets onto the screen at the correct location */
  1335. X
  1336. Xvoid MapGadgets( reason, update )
  1337. X    int reason;
  1338. X    int update;
  1339. X{
  1340. X    GPTR gptr;
  1341. X
  1342. X    /* Make sure that any down gadget is popped back up */
  1343. X
  1344. X    if( lastgaddown )
  1345. X    SetGadgetUP( &lastgaddown->dobj->do_Gadget );
  1346. X    lastgaddown = NULL;
  1347. X
  1348. X    /* Grey Menu Items, no Game icon will be selected */
  1349. X
  1350. X    ChgGameItems( &MenuList1, 0 );
  1351. X
  1352. X    /* Remove them first */
  1353. X
  1354. X    for( gptr = windowgads; gptr; gptr = gptr->nextwgad )
  1355. X    {
  1356. X    RemoveGadget( win, &gptr->dobj->do_Gadget );
  1357. X    }
  1358. X    windowgads = NULL;
  1359. X
  1360. X    /* Remove any non-existant games */
  1361. X
  1362. X    ClearDelGames( );
  1363. X
  1364. X    /* If disk changed, reload existing icons */
  1365. X
  1366. X    if( reason == R_DISK )
  1367. X    {
  1368. X    LoadIcons( );
  1369. X    }
  1370. X
  1371. X    /* Always move back to home unless we were scrolling */
  1372. X
  1373. X    if( reason != R_SCROLL )
  1374. X    {
  1375. X    curcol = 0;
  1376. X    }
  1377. X
  1378. X    /* Calculate locations and display gadgets */
  1379. X
  1380. X    CalcLocs( update );
  1381. X}
  1382. X
  1383. Xvoid ClearWindow( win )
  1384. X    struct Window *win;
  1385. X{
  1386. X    /* Clear the old gadgets from the window */
  1387. X
  1388. X    SetAPen( win->RPort, C_GREY );
  1389. X    SetOPen( win->RPort, C_GREY );
  1390. X    SetDrPt( win->RPort, 0xffff );
  1391. X    SetDrMd( win->RPort, JAM2 );
  1392. X
  1393. X    RectFill( win->RPort, ORIGINX, ORIGINY, CORNERX-1, CORNERY-1 );
  1394. X}
  1395. X
  1396. X/* Calculate the place for and attach the gadgets to the window */
  1397. X
  1398. Xvoid
  1399. XCalcLocs( update )
  1400. X    int update;
  1401. X{
  1402. X    register GPTR gptr;
  1403. X    register USHORT ox, oy, cx, cy;
  1404. X    int gadid = GADNEWGAME;
  1405. X    int addx = 0, sizex, sizey;
  1406. X
  1407. X    cols = vcols = 0;
  1408. X    scol = -1;
  1409. X
  1410. X    /* Upper left corner of window */
  1411. X
  1412. X    ox = ORIGINX;
  1413. X    oy = ORIGINY;
  1414. X
  1415. X    /* Lower right corner of window */
  1416. X
  1417. X    cx = CORNERX;
  1418. X
  1419. X    /* Account for text labels at the bottom by pulling the bottom up. */
  1420. X    cy = CORNERY - win->RPort->TxHeight - 3;
  1421. X
  1422. X    ClearWindow( win );
  1423. X
  1424. X    /* Map the current list */
  1425. X
  1426. X    for( gptr = gamehead; gptr; gptr = gptr->next )
  1427. X    {
  1428. X    /* If not to the horizontal offset yet, don't display */
  1429. X
  1430. X    sizex = GADWIDTH( &gptr->dobj->do_Gadget );
  1431. X    sizey = gptr->dobj->do_Gadget.Height;
  1432. X    addx = max( sizex, addx );
  1433. X
  1434. X    /* If the current column comes before the visible column... */
  1435. X    if( cols < curcol )
  1436. X    {
  1437. X        oy += sizey + GADINCY + 3;
  1438. X        if( gptr->next )
  1439. X        {
  1440. X        if( oy + gptr->next->dobj->do_Gadget.Height + 3 >= cy )
  1441. X        {
  1442. X            cols++;
  1443. X            ox += addx + GADINCX;
  1444. X            if( GADWIDTH( &gptr->next->dobj->do_Gadget ) >
  1445. X            gptr->next->dobj->do_Gadget.Width )
  1446. X            {
  1447. X            ox += ( GADWIDTH( &gptr->next->dobj->do_Gadget ) -
  1448. X            gptr->next->dobj->do_Gadget.Width ) / 2 + 1;
  1449. X            }
  1450. X            oy = ORIGINY;
  1451. X            addx = 0;
  1452. X        }
  1453. X        }
  1454. X        continue;
  1455. X    }
  1456. X
  1457. X    if( scol == -1 )
  1458. X    {
  1459. X        ox = ORIGINX;
  1460. X        scol = cols;
  1461. X    }
  1462. X
  1463. X    /* If visible, draw it */
  1464. X
  1465. X    if( ox + sizex + GADINCX < cx )
  1466. X    {
  1467. X        /* Link to mapped gadgets list */
  1468. X
  1469. X        gptr->nextwgad = windowgads;
  1470. X        windowgads = gptr;
  1471. X
  1472. X        /* Set screen locations, if text is longer, scoot the
  1473. X         * gadget over to make room for it.
  1474. X         */
  1475. X
  1476. X        if( GADWIDTH( &gptr->dobj->do_Gadget ) >
  1477. X            gptr->dobj->do_Gadget.Width )
  1478. X        {
  1479. X        gptr->dobj->do_Gadget.LeftEdge = ox +
  1480. X            ( GADWIDTH( &gptr->dobj->do_Gadget ) -
  1481. X            gptr->dobj->do_Gadget.Width ) / 2 + 1;
  1482. X        }
  1483. X        else
  1484. X        gptr->dobj->do_Gadget.LeftEdge = ox;
  1485. X        addx = max( addx, GADWIDTH( &gptr->dobj->do_Gadget) );
  1486. X        gptr->dobj->do_Gadget.TopEdge = oy;
  1487. X        gptr->dobj->do_Gadget.GadgetID = gadid++;
  1488. X
  1489. X        AddGadget( win, &gptr->dobj->do_Gadget, 0 );
  1490. X    }
  1491. X
  1492. X    /* Stack vertically first, then horizontally */
  1493. X
  1494. X    if( gptr->next )
  1495. X    {
  1496. X        oy += sizey + GADINCY + 3;
  1497. X        if( oy + gptr->next->dobj->do_Gadget.Height + 3 >= cy )
  1498. X        {
  1499. X        ox += addx + GADINCX;
  1500. X        cols++;
  1501. X        if( ox + GADWIDTH( &gptr->next->dobj->do_Gadget) < cx )
  1502. X            vcols++;
  1503. X        addx = 0;
  1504. X        oy = ORIGINY;
  1505. X        }
  1506. X    }
  1507. X    }
  1508. X
  1509. X    /* Display all of the gadgets */
  1510. X
  1511. X    RefreshGList( win->FirstGadget, win, NULL, -1 );
  1512. X
  1513. X    /* Set up the slider if forcing a new position, otherwise
  1514. X     * the slider was probably moved and its position should be
  1515. X     * left where the user put it instead of jerking it around
  1516. X     */
  1517. X    if( update )
  1518. X    UpdatePropGad( win, &Scroll, vcols+1, cols+1, scol );
  1519. X}
  1520. X
  1521. X/* Open the indicated window and place the IntuiText list passed in that
  1522. X * window.  Then wait for the OKAY gadget to be clicked on.
  1523. X */
  1524. Xvoid text_requester( newwin, tlist )
  1525. X    register struct NewWindow *newwin;
  1526. X    struct IntuiText *tlist;
  1527. X{
  1528. X    register struct Window *win;
  1529. X    register struct IntuiMessage *imsg;
  1530. X    register struct Gadget *gd;
  1531. X    int done = 0;
  1532. X    int i;
  1533. X    long class;
  1534. X    struct NewWindow **aonce;
  1535. X    static struct NewWindow *once[ 6+1 ];
  1536. X    int lines[ 10 ], lcnt = 0, avone = -1;
  1537. X    register int txtdiff = scrn->RastPort.TxHeight - 8;
  1538. X
  1539. X    newwin->Screen = scrn;
  1540. X
  1541. X    for( i = 0; i < 6; ++i )
  1542. X    {
  1543. X    if( newwin == once[i] )
  1544. X        break;
  1545. X    if( once[i] == 0 && avone == -1 )
  1546. X        avone = i;
  1547. X    }
  1548. X    aonce = &once[avone];
  1549. X
  1550. X    /* If spacing not correct, fix it up now */
  1551. X    if( *aonce == NULL )
  1552. X    {
  1553. X    register struct IntuiText *ip = tlist;
  1554. X    for( ; ip; ip = ip->NextText )
  1555. X    {
  1556. X        if( lcnt == 0 )
  1557. X        lines[ lcnt++ ] = ip->TopEdge;
  1558. X        else
  1559. X        {
  1560. X        register found = 0;
  1561. X        for( i = 0; i < lcnt; ++i )
  1562. X        {
  1563. X            if( lines[ i ] > ip->TopEdge )
  1564. X            break;
  1565. X            if( lines[ i ] == ip->TopEdge )
  1566. X            {
  1567. X            found = 1;
  1568. X            break;
  1569. X            }
  1570. X        }
  1571. X
  1572. X        if( !found )
  1573. X        {
  1574. X            if( i < lcnt )
  1575. X            {
  1576. X            int j;
  1577. X            for( j = lcnt; j > i; --j )
  1578. X                lines[ j ] = lines[ j - 1 ];
  1579. X            }
  1580. X            lcnt++;
  1581. X            lines[ i ] = ip->TopEdge;
  1582. X        }
  1583. X        }
  1584. X    }
  1585. X
  1586. X    for( ip = tlist; ip; ip = ip->NextText )
  1587. X    {
  1588. X        for( i = 0; i < lcnt; ++i )
  1589. X        {
  1590. X        if( ip->TopEdge == lines[ i ] )
  1591. X        {
  1592. X            ip->TopEdge += txtdiff*i;
  1593. X            break;
  1594. X        }
  1595. X        }
  1596. X    }
  1597. X
  1598. X    gd = FindGadget( NULL, newwin, GADHELPOKAY );
  1599. X    gd->TopEdge += (lcnt+1)*txtdiff;
  1600. X    gd->Height += txtdiff;
  1601. X    SetBorder( gd, -1 );
  1602. X    newwin->Height += txtdiff * (lcnt+2);
  1603. X    *aonce = newwin;
  1604. X    }
  1605. X
  1606. X    if( ( win = MyOpenWindow( newwin ) ) == NULL )
  1607. X    {
  1608. X    errmsg( FLASH, "Can't create window" );
  1609. X    return;
  1610. X    }
  1611. X
  1612. X    PrintIText( win->RPort, tlist, 0, txtdiff );
  1613. X
  1614. X    while( !done )
  1615. X    {
  1616. X    WaitPort( win->UserPort );
  1617. X    while( ( imsg = (struct IntuiMessage * )
  1618. X        GetMsg( win->UserPort ) ) != NULL )
  1619. X    {
  1620. X        class = imsg->Class;
  1621. X        ReplyMsg( (struct Message *) imsg );
  1622. X        switch( class )
  1623. X        {
  1624. X        case CLOSEWINDOW: done = 1; break;
  1625. X        case VANILLAKEY: done = 1; break;
  1626. X        /* Should be GADHELPOKAY */
  1627. X        case GADGETUP: done = 1; break;
  1628. X        }
  1629. X    }
  1630. X    }
  1631. X    SafeCloseWindow( win );
  1632. X}
  1633. X
  1634. X/* Scroll through a file which is passed by name */
  1635. X
  1636. Xvoid help_requester( file )
  1637. X    char *file;
  1638. X{
  1639. X    register struct Window *win;
  1640. X    register struct IntuiMessage *imsg;
  1641. X    register struct Gadget *gd;
  1642. X    FILE *fp;
  1643. X    int done = 0, line = 0, lines, topline, tlines, i;
  1644. X    static int once = 0, lastdown;
  1645. X    char buf[ 100 ];
  1646. X    long loff[ 100 ];
  1647. X    long class, code;
  1648. X    int txtdiff = scrn->RastPort.TxHeight - 8;
  1649. X
  1650. X    if( ( fp = fopen( file, "r" ) ) == NULL )
  1651. X    {
  1652. X#ifdef  __SASC_60
  1653. X    errmsg( FLASH, "Can't open %s: %s", file, strerror(errno) );
  1654. X#else
  1655. X    errmsg( FLASH, "Can't open %s: %s", file, sys_errlist[errno] );
  1656. X#endif
  1657. X    return;
  1658. X    }
  1659. X    for( tlines = 0; tlines < 100 ; ++tlines )
  1660. X    {
  1661. X    loff[ tlines ] = ftell( fp );
  1662. X    if( fgets( buf, sizeof( buf ), fp ) == NULL )
  1663. X        break;
  1664. X    }
  1665. X
  1666. X    if( !once )
  1667. X    {
  1668. X    for( gd = Help3_NewWindowStructure10.FirstGadget;
  1669. X            gd; gd = gd->NextGadget )
  1670. X    {
  1671. X        if( gd->GadgetID != 0 )
  1672. X        {
  1673. X        if( gd->GadgetID == GADHELPFRWD ||
  1674. X            gd->GadgetID == GADHELPBKWD )
  1675. X        {
  1676. X            gd->Height += txtdiff;
  1677. X        }
  1678. X        SetBorder( gd, -1 );
  1679. X        }
  1680. X    }
  1681. X    once = 1;
  1682. X    Help3_NewWindowStructure10.Height += txtdiff;
  1683. X    }
  1684. X
  1685. X    Help3_NewWindowStructure10.Screen = scrn;
  1686. X    if( ( win = MyOpenWindow( &Help3_NewWindowStructure10 ) ) == NULL )
  1687. X    {
  1688. X    errmsg( FLASH, "Can't create requester window" );
  1689. X    fclose( fp );
  1690. X    return;
  1691. X    }
  1692. X    lines = ( (win->Height - win->BorderTop - 25 ) / win->RPort->TxHeight );
  1693. X    topline = win->BorderTop + win->RPort->TxBaseline + 2;
  1694. X    Move( win->RPort, win->BorderLeft, topline );
  1695. X
  1696. X    SetAPen( win->RPort, C_BLACK );
  1697. X    SetBPen( win->RPort, C_GREY );
  1698. X    SetDrMd( win->RPort, JAM2 );
  1699. X
  1700. X    for( i = 0; i < min( lines, tlines ); ++i )
  1701. X    {
  1702. X    getline( fp, loff, i, buf, sizeof( buf ) );
  1703. X    Move( win->RPort, win->BorderLeft + 2,
  1704. X        topline + (i * win->RPort->TxHeight) );
  1705. X    Text( win->RPort, buf, strlen( buf )-1 );
  1706. X    }
  1707. X
  1708. X    while( !done )
  1709. X    {
  1710. X    WaitPort( win->UserPort );
  1711. X    while( ( imsg = (void *) GetMsg( win->UserPort ) ) != NULL )
  1712. X    {
  1713. X        class = imsg->Class;
  1714. X        code = imsg->Code;
  1715. X        gd = (struct Gadget *)imsg->IAddress;
  1716. X
  1717. X        ReplyMsg( (struct Message *) imsg );
  1718. X
  1719. X        switch( class )
  1720. X        {
  1721. X        case VANILLAKEY:
  1722. X            if( code == 'u' || code == ('U'-64))
  1723. X            {
  1724. X            goto bkwd;
  1725. X            }
  1726. X            else if( code == 'd' || code == ('D'-64))
  1727. X            {
  1728. X            goto frwd;
  1729. X            }
  1730. X            else if( code == '\33' || code == 'q' )
  1731. X            {
  1732. X            done = 1;
  1733. X            }
  1734. X            break;
  1735. X
  1736. X        case CLOSEWINDOW:
  1737. X            done = 1;
  1738. X            break;
  1739. X
  1740. X        case GADGETUP:
  1741. X            lastdown = 0;
  1742. X            break;
  1743. X
  1744. X        case GADGETDOWN:
  1745. X            lastdown = gd->GadgetID;
  1746. X            break;
  1747. X
  1748. X        case INTUITICKS:
  1749. X            if( lastdown == GADHELPFRWD )
  1750. X            {
  1751. X            frwd:
  1752. X            if( line + lines < tlines )
  1753. X            {
  1754. X                line++;
  1755. X                WaitTOF();
  1756. X                ScrollRaster( win->RPort, 0,
  1757. X                win->RPort->TxHeight,
  1758. X                win->BorderLeft,
  1759. X                win->BorderTop + 2,
  1760. X                win->Width - win->BorderRight - 1,
  1761. X                win->BorderTop + 2 +
  1762. X                (lines*win->RPort->TxHeight) );
  1763. X                getline( fp, loff, line + lines - 1,
  1764. X                buf, sizeof( buf ) );
  1765. X                Move( win->RPort, win->BorderLeft + 2,
  1766. X                topline + ( ( lines - 1 ) *
  1767. X                win->RPort->TxHeight ) );
  1768. X                WaitTOF();
  1769. X                Text( win->RPort, buf, strlen( buf )-1 );
  1770. X            }
  1771. X            else
  1772. X            {
  1773. X                /* EOF */
  1774. X                DisplayBeep( scrn );
  1775. X            }
  1776. X            }
  1777. X            else if( lastdown == GADHELPBKWD )
  1778. X            {
  1779. X            bkwd:
  1780. X            if( line > 0 )
  1781. X            {
  1782. X                line--;
  1783. X                WaitTOF();
  1784. X                ScrollRaster( win->RPort, 0,
  1785. X                -win->RPort->TxHeight,
  1786. X                win->BorderLeft,
  1787. X                win->BorderTop + 2,
  1788. X                win->Width - win->BorderRight - 1,
  1789. X                win->BorderTop + 2 +
  1790. X                (lines*win->RPort->TxHeight) );
  1791. X                getline( fp, loff, line, buf, sizeof( buf ) );
  1792. X                Move( win->RPort, win->BorderLeft + 2, topline );
  1793. X                WaitTOF();
  1794. X                Text( win->RPort, buf, strlen( buf )-1 );
  1795. X            }
  1796. X            else
  1797. X            {
  1798. X                DisplayBeep( scrn );
  1799. X            }
  1800. X            }
  1801. X            break;
  1802. X
  1803. X        }
  1804. X    }
  1805. X    }
  1806. X    SafeCloseWindow( win );
  1807. X    fclose( fp );
  1808. X}
  1809. X
  1810. X/* Act on the menu item number passed */
  1811. X
  1812. Xvoid
  1813. Xdo_menu(mcode)
  1814. X    register int mcode;
  1815. X{
  1816. X    switch(MENUNUM(mcode))
  1817. X    {
  1818. X    case MENU_PROJECT:
  1819. X        switch(ITEMNUM(mcode))
  1820. X        {
  1821. X        case ITEM_HELP:
  1822. X            help_requester( "NetHack:HackWB.hlp" );
  1823. X            break;
  1824. X
  1825. X        case ITEM_ABOUT:
  1826. X            text_requester( &About_NewWindowStructure9,
  1827. X                &About_IntuiTextList9 );
  1828. X            break;
  1829. X
  1830. X        case ITEM_SCORES:
  1831. X            menu_scores( );
  1832. X            break;
  1833. X
  1834. X        case ITEM_RECOVER:
  1835. X            menu_recover( );
  1836. X            break;
  1837. X
  1838. X        case ITEM_EDDEF:
  1839. X            menu_editdef( GAME_FROM_DEFAULT );
  1840. X            break;
  1841. X
  1842. X        case ITEM_CONFIG:
  1843. X            menu_config( );
  1844. X            break;
  1845. X
  1846. X        case ITEM_QUIT:
  1847. X            quit = Ask( "Ready to Quit?" );
  1848. X            break;
  1849. X
  1850. X        }
  1851. X        break;
  1852. X
  1853. X    case MENU_GAME:
  1854. X        switch( ITEMNUM( mcode ) )
  1855. X        {
  1856. X
  1857. X        case ITEM_INFO:
  1858. X            menu_info( );
  1859. X            break;
  1860. X
  1861. X        case ITEM_SETCOMMENT:
  1862. X            menu_comment( );
  1863. X            break;
  1864. X
  1865. X        case ITEM_SETOPT:
  1866. X            menu_setopt( );
  1867. X            break;
  1868. X
  1869. X        case ITEM_COPYOPT:
  1870. X            menu_copyopt( );
  1871. X            break;
  1872. X
  1873. X        case ITEM_DISCARD:
  1874. X            menu_discard( );
  1875. X            break;
  1876. X
  1877. X        case ITEM_RENAME:
  1878. X            menu_rename( );
  1879. X            break;
  1880. X        }
  1881. X    }
  1882. X}
  1883. X
  1884. Xvoid
  1885. Xmenu_discard()
  1886. X{
  1887. X    register GPTR gptr;
  1888. X
  1889. X    if( ( gptr = NeedGame() ) == NULL )
  1890. X    return;
  1891. X
  1892. X    if( Ask("Discard Selected Game?") )
  1893. X    {
  1894. X    lastgaddown = NULL;
  1895. X    if( DeleteGame( gptr ) == 0 )
  1896. X    {
  1897. X        errmsg( FLASH, "Discard may have failed for %s",
  1898. X            GameName( gptr, NULL ) );
  1899. X    }
  1900. X
  1901. X    MapGadgets( R_DISK, 1 );
  1902. X    }
  1903. X}
  1904. X
  1905. Xvoid
  1906. Xrun_game( gptr )
  1907. X    register GPTR gptr;
  1908. X{
  1909. X    struct Task *ctask;
  1910. X    register struct MsgPort *proc = NULL;
  1911. X    char buf[ 100 ], *t;
  1912. X    char namebuf[ 100 ];
  1913. X    int once, tidx;
  1914. X
  1915. X    if( gptr->active )
  1916. X    {
  1917. X    errmsg( FLASH, "%s is already in progress", gptr->name );
  1918. X    return;
  1919. X    }
  1920. X
  1921. X    tidx = 0;
  1922. X
  1923. X    /* If newgame gadget, then check game name */
  1924. X
  1925. X    if( gptr->dobj->do_Gadget.GadgetID == GADNEWGAME )
  1926. X    {
  1927. X        /*
  1928. X        if currrent name in use, get new name
  1929. X        */
  1930. X
  1931. X    if( !defgame.plname )
  1932. X        defgame.plname = strdup( defgname );
  1933. X
  1934. X    /* Put options from gadgets into options[ OPTIONS_IDX ] */
  1935. X
  1936. X    PutOptions( curopts );
  1937. X
  1938. X    once = 0;
  1939. X    sprintf( buf, "%s/%s.sav", options[ SAVE_IDX ], defgame.plname );
  1940. X    while( access( buf, 0 ) == 0 )
  1941. X    {
  1942. X        if( StrRequest( "Game Already Exists, Enter a New Name",
  1943. X        namebuf, once ? namebuf : defgame.plname ) == 0 )
  1944. X        {
  1945. X        return;
  1946. X        }
  1947. X        once = 1;
  1948. X        sprintf( buf, "%s/%s.sav", options[ SAVE_IDX ], namebuf );
  1949. X    }
  1950. X
  1951. X    /* Set new name to use, if done one at all */
  1952. X    if( once )
  1953. X    {
  1954. X        if( defgame.plname ) free( defgame.plname );
  1955. X        defgame.plname = strdup( namebuf );
  1956. X    }
  1957. X
  1958. X        /* set defaults for this game from previous defaults. */
  1959. X    if( defgame.plname && stricmp( defgame.plname, "wbdefaults" ) )
  1960. X        SetToolLine( gptr, "NAME", defgame.plname );
  1961. X    if( defgame.pltype )
  1962. X        SetToolLine( gptr, "CHARACTER", players[ defgame.pltype ] );
  1963. X
  1964. X    gptr->gname = xmalloc( 20 + strlen( defgame.plname ) );
  1965. X    }
  1966. X    else
  1967. X    {
  1968. X    gptr->gname = xmalloc( 20 + strlen( gptr->name ) );
  1969. X    }
  1970. X
  1971. X    SetToolLine( gptr, "PATH", options[ PATH_IDX ] );
  1972. X    if( defgame.options )
  1973. X    SetToolLine( gptr, "OPTIONS", defgame.options );
  1974. X    else
  1975. X    SetToolLine( gptr, "OPTIONS", options[ OPTIONS_IDX ] );
  1976. X
  1977. X    /* Prefer a setting in the users data over the global one */
  1978. X    if( ( ( t = ToolsEntry( gptr, "PENS" ) ) == NULL || *t == 0 ) &&
  1979. X      ( ( t = ToolsEntry( gptr, "PEN" ) ) == NULL || *t == 0 ) )
  1980. X    {
  1981. X    t = options[ PENS_IDX ];
  1982. X    }
  1983. X    SetToolLine( gptr, "PENS", t );
  1984. X    SetToolLine( gptr, "HACKDIR", options[ HACKDIR_IDX ] );
  1985. X    SetToolLine( gptr, "LEVELS", options[ LEVELS_IDX ] );
  1986. X    SetToolLine( gptr, "SAVE", options[ SAVE_IDX ] );
  1987. X
  1988. X    gptr->wbs = AllocMem( sizeof( struct WBStartup ) +
  1989. X    ( sizeof( struct WBArg ) * 2 ), MEMF_PUBLIC | MEMF_CLEAR );
  1990. X
  1991. X    /* Check if we got everything */
  1992. X
  1993. X    if( !gptr->gname || !gptr->wbs )
  1994. X    {
  1995. X    fprintf( stderr, "Can't allocate memory\n" );
  1996. X    goto freemem;
  1997. X    }
  1998. X
  1999. X    /* Get the arguments structure space */
  2000. X
  2001. X    gptr->wba = ( struct WBArg * ) ((long)gptr->wbs +
  2002. X        sizeof( struct WBStartup ) );
  2003. X
  2004. X    /* Close down window and screen if requested */
  2005. X
  2006. X    if( shutdown )
  2007. X    CloseDownWB( );
  2008. X
  2009. X    /* Load the game into memory */
  2010. X#ifdef SPLIT
  2011. X    /* Which version do we run? */
  2012. X    {
  2013. X    char gi[80];
  2014. X
  2015. X    sprintf( gi, "%s.dir", GAMEIMAGE );
  2016. X    if( access( gi, 0 ) == 0 ){
  2017. X    gptr->seglist = (BPTR)s_LoadSeg( gi );
  2018. X    if( gptr->seglist ) running_split=1;
  2019. X    }else{
  2020. X    gptr->seglist = (BPTR)LoadSeg( GAMEIMAGE );
  2021. X    }
  2022. X    }
  2023. X#else
  2024. X    gptr->seglist = (BPTR)LoadSeg( GAMEIMAGE );
  2025. X#endif
  2026. X
  2027. X    if( gptr->seglist == NULL)
  2028. X    {
  2029. X    if( !wbopen )
  2030. X        SetupWB( );
  2031. X    errmsg( FLASH, "Can't load %s", GAMEIMAGE );
  2032. X    goto freemem;
  2033. X    }
  2034. X    /* Build WBStartup from current game info */
  2035. X
  2036. X    /* Set the game name for the status command */
  2037. X
  2038. X    sprintf( gptr->gname, "NetHack 3.1 %s", gptr->name );
  2039. X
  2040. X    /* Create a process for the game to execute in */
  2041. X
  2042. X    ctask = FindTask( NULL );
  2043. X    proc = CreateProc( gptr->gname, ctask->tc_Node.ln_Pri,
  2044. X    gptr->seglist, GAMESTACK );
  2045. X
  2046. X    /* Check if the create failed */
  2047. X
  2048. X    if( proc == NULL )
  2049. X    {
  2050. X    fprintf(stderr, "Error creating process %d\n", IoErr() );
  2051. X#ifdef SPLIT
  2052. X    if(!running_split)
  2053. X#endif
  2054. X        UnLoadSeg( gptr->seglist );
  2055. Xfreemem:
  2056. X    if( gptr->gname ) free( gptr->gname );
  2057. X    gptr->gname = NULL;
  2058. X
  2059. X    if( gptr->wbs ) FreeMem( gptr->wbs,
  2060. X    sizeof( struct WBStartup ) + sizeof( struct WBArg ) * 2 );
  2061. X    gptr->wbs = NULL;
  2062. X    if( !wbopen )
  2063. X    SetupWB( );
  2064. X    return;
  2065. X    }
  2066. X
  2067. X    /* Get the Process structure pointer */
  2068. X
  2069. X    gptr->prc = (struct Process *) (((long)proc) - sizeof( struct Task ));
  2070. X
  2071. X    /* Set the current directory */
  2072. X
  2073. X    gptr->prc->pr_CurrentDir=((struct Process *)FindTask(NULL))->pr_CurrentDir;
  2074. X
  2075. X    /* Fill in the startup message */
  2076. X
  2077. X    gptr->wbs->sm_Process = proc;
  2078. X    gptr->wbs->sm_Segment = gptr->seglist;
  2079. X    gptr->wbs->sm_NumArgs = 2;
  2080. X    gptr->wbs->sm_ToolWindow = "con:0/0/350/50/Amiga NetHack 3.1";
  2081. X    gptr->wbs->sm_ArgList = gptr->wba;
  2082. X
  2083. X    /* Fill in the args */
  2084. X
  2085. X    gptr->wba[0].wa_Name = Strdup( GAMEIMAGE );
  2086. X    gptr->wba[0].wa_Lock = Lock( dirname( GAMEIMAGE ), ACCESS_READ );
  2087. X
  2088. X    gptr->wba[1].wa_Name = Strdup( gptr->name );
  2089. X    gptr->wba[1].wa_Lock = Lock( gptr->dname, ACCESS_READ );
  2090. X
  2091. X    /* Write the updated tools types entries */
  2092. X
  2093. X    WriteDObj( gptr, gptr->wba[1].wa_Lock );
  2094. X
  2095. X    /* Set the message fields correctly */
  2096. X
  2097. X    gptr->wbs->sm_Message.mn_Node.ln_Type = NT_MESSAGE;
  2098. X    gptr->wbs->sm_Message.mn_Node.ln_Pri = 0;
  2099. X    gptr->wbs->sm_Message.mn_ReplyPort = dosport;
  2100. X    gptr->wbs->sm_Message.mn_Length =
  2101. X    sizeof( struct WBStartup ) + ( sizeof( struct WBArg ) * 2 );
  2102. X
  2103. X    /* mark game as in use */
  2104. X
  2105. X    active_count++;
  2106. X    gptr->active = 1;
  2107. X
  2108. X    /* Send the WB Startup message to let the game go... */
  2109. X
  2110. X    PutMsg( proc, &gptr->wbs->sm_Message );
  2111. X}
  2112. X
  2113. Xvoid CloseLibraries( )
  2114. X{
  2115. X    if( IntuitionBase )     CloseLibrary( (void *) IntuitionBase );
  2116. X    IntuitionBase = 0;
  2117. X    if( DiskfontBase )      CloseLibrary( (void *) DiskfontBase );
  2118. X    DiskfontBase = 0;
  2119. X    if( IconBase )          CloseLibrary(  IconBase );
  2120. X    IconBase = 0;
  2121. X    if( GfxBase )           CloseLibrary( (void *) GfxBase );
  2122. X    GfxBase = 0;
  2123. X}
  2124. X
  2125. Xvoid cleanup( code )
  2126. X    int code;
  2127. X{
  2128. X    if( active_count )
  2129. X    {
  2130. X    errmsg( FLASH, "There %s still %d game%s active...",
  2131. X        active_count > 1 ? "are" : "is",
  2132. X        active_count,
  2133. X        active_count > 1 ? "s" : "" );
  2134. X    return;
  2135. X    }
  2136. X
  2137. X    if( dosport ) DeletePort( dosport );
  2138. X    dosport = NULL;
  2139. X
  2140. X    CloseDownWB( );
  2141. X    CleanUpLists( );
  2142. X    CloseLibraries( );
  2143. X
  2144. X#ifdef SPLIT
  2145. X    if(running_split)s_UnLoadSeg();
  2146. X#endif
  2147. X    exit( code );
  2148. X}
  2149. X
  2150. XGPTR AllocGITEM( )
  2151. X{
  2152. X    register GPTR gptr;
  2153. X
  2154. X    if( gameavail )
  2155. X    {
  2156. X    gptr = gameavail;
  2157. X    gameavail = gameavail->next;
  2158. X    }
  2159. X    else
  2160. X    {
  2161. X    gptr = xmalloc( sizeof( GAMEITEM ) );
  2162. X    }
  2163. X
  2164. X    if( gptr )
  2165. X    memset( gptr, 0, sizeof( GAMEITEM ) );
  2166. X
  2167. X    return( gptr );
  2168. X}
  2169. X
  2170. Xvoid FreeGITEM( gptr )
  2171. X    register GPTR gptr;
  2172. X{
  2173. X    /* Free all of the pieces first */
  2174. X
  2175. X    if( gptr->talloc )
  2176. X    FreeTools( gptr );
  2177. X
  2178. X    if( gptr->dobj )
  2179. X    FreeDObj( gptr->dobj );
  2180. X
  2181. X    gptr->dobj = NULL;
  2182. X
  2183. X    if( gptr->name )
  2184. X    free( gptr->name );
  2185. X    gptr->name = NULL;
  2186. X
  2187. X    if( gptr->dname )
  2188. X    free( gptr->dname );
  2189. X    gptr->dname = NULL;
  2190. X
  2191. X    if( gptr->fname )
  2192. X    free( gptr->fname );
  2193. X    gptr->fname = NULL;
  2194. X
  2195. X    /* Connect it to free list */
  2196. X
  2197. X    gptr->next = gameavail;
  2198. X    gameavail = gptr;
  2199. X}
  2200. X
  2201. Xstruct DiskObject *AllocDObj( str )
  2202. X    register char *str;
  2203. X{
  2204. X    register struct DiskObject *doptr;
  2205. X    register char *t, *t1;
  2206. X
  2207. X    if( ( t = strrchr( str, '.' ) ) && stricmp( t, ".info" ) == 0 )
  2208. X    {
  2209. X    *t = 0;
  2210. X    }
  2211. X    else
  2212. X    {
  2213. X    t = NULL;
  2214. X    }
  2215. X
  2216. X    if( doptr = GetDiskObject( str ) )
  2217. X    {
  2218. X    struct IntuiText *ip;
  2219. X
  2220. X    diskobj_filter(doptr);  /* delete INTERNALCLI */
  2221. X
  2222. X    if( ip = xmalloc( sizeof( struct IntuiText ) ) )
  2223. X    {
  2224. X        memset( ip, 0, sizeof( struct IntuiText ) );
  2225. X        ip->FrontPen = C_BLACK;
  2226. X        ip->DrawMode = JAM1;
  2227. X        ip->LeftEdge = (doptr->do_Gadget.Width -
  2228. X        ( strlen( str ) * win->RPort->TxWidth ))/2;
  2229. X        ip->TopEdge = doptr->do_Gadget.Height;
  2230. X        ip->IText = strdup( str );
  2231. X        doptr->do_Gadget.GadgetText = ip;
  2232. X
  2233. X        /* Trim any .sav off of the end. */
  2234. X
  2235. X        if( ( t1 = strrchr( ip->IText, '.' ) ) &&
  2236. X            stricmp( t1, ".sav" ) == 0 )
  2237. X        {
  2238. X        *t1 = 0;
  2239. X        ip->LeftEdge += (2 * win->RPort->TxWidth);
  2240. X        }
  2241. X    }
  2242. X    }
  2243. X    if( t ) *t = '.';
  2244. X
  2245. X    return( doptr );
  2246. X}
  2247. X
  2248. Xvoid LoadIcons( )
  2249. X{
  2250. X    register GPTR gptr, newgame;
  2251. X    register BPTR savedir;
  2252. X    register char *t;
  2253. X    register struct FileInfoBlock *finfo;
  2254. X    char buf[ 200 ];
  2255. X
  2256. X    /* Check if we can access the new save directory */
  2257. X
  2258. X    if( ( savedir = Lock( options[ SAVE_IDX ], ACCESS_READ ) ) == NULL )
  2259. X    {
  2260. X    errmsg( FLASH,
  2261. X        "Can't access save directory: %s", options[ SAVE_IDX ] );
  2262. X    return;
  2263. X    }
  2264. X
  2265. X    if( ( finfo = (struct FileInfoBlock *)
  2266. X            xmalloc( sizeof( struct FileInfoBlock ) ) ) == NULL )
  2267. X    {
  2268. X    UnLock( savedir );
  2269. X    errmsg( FLASH, "Can't alloc memory" );
  2270. X    return;
  2271. X    }
  2272. X
  2273. X    if( newgame = gamehead )
  2274. X    gamehead = gamehead->next;
  2275. X
  2276. X    if( !Examine( savedir, finfo ) )
  2277. X    {
  2278. X    UnLock( savedir );
  2279. X    free( finfo );
  2280. X    errmsg( FLASH, "Can't Examine save directory" );
  2281. X    return;
  2282. X    }
  2283. X
  2284. X    /* Collect all of the entries */
  2285. X
  2286. X    while( ExNext( savedir, finfo ) )
  2287. X    {
  2288. X    /* If already got this game, continue */
  2289. X
  2290. X    if( gptr = FindGame( finfo->fib_FileName ) )
  2291. X        continue;
  2292. X
  2293. X    /* Get just the ones we are interested in */
  2294. X
  2295. X    if( ( t = strrchr( finfo->fib_FileName, '.' ) ) == NULL ||
  2296. X            stricmp( t, ".info" ) != 0 )
  2297. X        continue;
  2298. X
  2299. X    if( t == finfo->fib_FileName )
  2300. X        continue;
  2301. X
  2302. X    /* Get a gadget item */
  2303. X
  2304. X    if( gptr = GetWBIcon( savedir, options[ SAVE_IDX ], finfo ) )
  2305. X    {
  2306. X        gptr->next = gamehead;
  2307. X        gamehead = gptr;
  2308. X    }
  2309. X    }
  2310. X
  2311. X    /* Get the NewGame gadget */
  2312. X
  2313. X    UnLock( savedir );
  2314. X    if( newgame == NULL )
  2315. X    {
  2316. X    /* Pick up the new game if not there yet. */
  2317. X
  2318. X    sprintf( buf, "%sNewGame.info", options[ HACKDIR_IDX ] );
  2319. X    if( savedir = Lock( buf, ACCESS_READ ) )
  2320. X    {
  2321. X        if( Examine( savedir, finfo ) )
  2322. X        {
  2323. X        UnLock( savedir );
  2324. X        savedir = Lock( options[ HACKDIR_IDX ], ACCESS_READ );
  2325. X        if( gptr = GetWBIcon( savedir,
  2326. X            options[ HACKDIR_IDX ], finfo ) )
  2327. X        {
  2328. X            gptr->next = gamehead;
  2329. X            gamehead = gptr;
  2330. X        }
  2331. X        }
  2332. X        UnLock( savedir );
  2333. X        free( finfo );
  2334. X    }
  2335. X    else
  2336. X    {
  2337. X        errmsg( FLASH, "No access to %s", buf );
  2338. X    }
  2339. X    }
  2340. X    else
  2341. X    {
  2342. X    newgame->next = gamehead;
  2343. X    gamehead = newgame;
  2344. X    }
  2345. X}
  2346. X
  2347. Xvoid menu_recover()
  2348. X{
  2349. X    int execit = 1;
  2350. X    long class, code;
  2351. X    struct Gadget *gd, *lastact = 0;
  2352. X    int done = 0;
  2353. X    struct IntuiMessage *imsg;
  2354. X    struct Window *w;
  2355. X    static int once = 0;
  2356. X    int txtdiff = scrn->RastPort.TxHeight - 8;
  2357. X    struct IntuiText *ip;
  2358. X
  2359. X    if( !once )
  2360. X    {
  2361. X    for( gd = Rst_NewWindowStructure12.FirstGadget;
  2362. X            gd; gd = gd->NextGadget )
  2363. X    {
  2364. X        switch( gd->GadgetID )
  2365. X        {
  2366. X        case GADRESTDIR:
  2367. X            gd->TopEdge += txtdiff;
  2368. X            gd->Height += txtdiff;
  2369. X            SetBorder( gd, -1 );
  2370. X            strcpy(RstDir,options[LEVELS_IDX]);
  2371. X            break;
  2372. X        case GADRESTOLD:
  2373. X            gd->TopEdge += txtdiff*2;
  2374. X            gd->Height += txtdiff;
  2375. X            SetBorder( gd, -1 );
  2376. X            strcpy(RstOld,"levels");
  2377. X            break;
  2378. X        case GADRESTNEW:
  2379. X            gd->TopEdge += txtdiff*3;
  2380. X            gd->Height += txtdiff;
  2381. X            SetBorder( gd, -1 );
  2382. X            break;
  2383. X        case GADRESTOKAY:
  2384. X            gd->TopEdge += txtdiff*4;
  2385. X            gd->Height += txtdiff;
  2386. X            SetBorder( gd, -1 );
  2387. X            break;
  2388. X        case GADRESTCAN:
  2389. X            gd->TopEdge += txtdiff*4;
  2390. X            gd->Height += txtdiff;
  2391. X            SetBorder( gd, -1 );
  2392. X            break;
  2393. X        }
  2394. X    }
  2395. X    Rst_NewWindowStructure12.Height += txtdiff*5;
  2396. X    for( ip = &Rst_IntuiTextList12; ip; ip = ip->NextText )
  2397. X    {
  2398. X        if( *ip->IText == 'O' )
  2399. X        ip->TopEdge += txtdiff;
  2400. X        else if( *ip->IText == 'N' )
  2401. X        ip->TopEdge += txtdiff*2;
  2402. X    }
  2403. X    once = 1;
  2404. X    }
  2405. X
  2406. X    Rst_NewWindowStructure12.Screen = scrn;
  2407. X    if( ( w = MyOpenWindow( &Rst_NewWindowStructure12 ) ) == NULL )
  2408. X    {
  2409. X    errmsg( FLASH, "Can't create requester window" );
  2410. X    return;
  2411. X    }
  2412. X    PrintIText( w->RPort, &Rst_IntuiTextList12, 0, txtdiff );
  2413. X    lastact = FindGadget( w, NULL, GADRESTDIR );
  2414. X
  2415. X    while( !done )
  2416. X    {
  2417. X    WaitPort( w->UserPort );
  2418. X    while( imsg = (struct IntuiMessage *) GetMsg( w->UserPort ) )
  2419. X    {
  2420. X        class = imsg->Class;
  2421. X        code = imsg->Code;
  2422. X        gd = (struct Gadget *)imsg->IAddress;
  2423. X        ReplyMsg( (struct Message *) imsg );
  2424. X        switch( class )
  2425. X        {
  2426. X        case CLOSEWINDOW:
  2427. X            done = 1;
  2428. X            execit = 0;
  2429. X            break;
  2430. X
  2431. X        case ACTIVEWINDOW:
  2432. X            ActivateGadget( lastact, w, NULL );
  2433. X            break;
  2434. X
  2435. X        case GADGETUP:
  2436. X            if( gd->GadgetID == GADRESTOKAY )
  2437. X            done = 1;
  2438. X            else if( gd->GadgetID == GADRESTCAN )
  2439. X            {
  2440. X            execit = 0;
  2441. X            done = 1;
  2442. X            }
  2443. X            else if( gd->GadgetID == GADRESTDIR )
  2444. X            {
  2445. X            if( gd = FindGadget( w, NULL, GADRESTOLD ) )
  2446. X                ActivateGadget( lastact = gd, w, NULL );
  2447. X            }
  2448. X            else if( gd->GadgetID == GADRESTOLD )
  2449. X            {
  2450. X            if( gd = FindGadget( w, NULL, GADRESTNEW ) )
  2451. X                ActivateGadget( lastact = gd, w, NULL );
  2452. X            }
  2453. X            break;
  2454. X
  2455. X        case VANILLAKEY:
  2456. X            if( code == '\33' )
  2457. X            {
  2458. X            done = 1;
  2459. X            execit = 0;
  2460. X            }
  2461. X            break;
  2462. X        }
  2463. X    }
  2464. X    }
  2465. X
  2466. X    SafeCloseWindow( w );
  2467. X
  2468. X    if( execit )
  2469. X    {
  2470. X    char buf[255];
  2471. X    sprintf( buf, "stack 65000\nNetHack:Recover -d %s %s", RstDir, RstOld );
  2472. X    Execute( buf, NULL, NULL );
  2473. X    MapGadgets( R_DISK, 1);
  2474. X    }
  2475. X}
  2476. X
  2477. END_OF_FILE
  2478. if test 39564 -ne `wc -c <'sys/amiga/wb.c1'`; then
  2479.     echo shar: \"'sys/amiga/wb.c1'\" unpacked with wrong size!
  2480. fi
  2481. # end of 'sys/amiga/wb.c1'
  2482. fi
  2483. echo shar: End of archive 39 \(of 108\).
  2484. cp /dev/null ark39isdone
  2485. MISSING=""
  2486. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
  2487. 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
  2488. 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
  2489. 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
  2490. 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
  2491. 101 102 103 104 105 106 107 108 ; do
  2492.     if test ! -f ark${I}isdone ; then
  2493.     MISSING="${MISSING} ${I}"
  2494.     fi
  2495. done
  2496. if test "${MISSING}" = "" ; then
  2497.     echo You have unpacked all 108 archives.
  2498.     echo "Now execute 'rebuild.sh'"
  2499.     rm -f ark10[0-8]isdone 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.