From 4a3b9038720ba74b63b9cc47093c5e1521baabdb Mon Sep 17 00:00:00 2001 From: NetHack DevTeam Date: Wed, 20 Mar 2002 00:00:00 +0000 Subject: [PATCH] NetHack 3.4.0 --- Files | 114 +- Porting | 2 +- README | 132 +- dat/Arch.des | 15 +- dat/Barb.des | 2 +- dat/Caveman.des | 2 +- dat/Healer.des | 2 +- dat/Knight.des | 2 +- dat/Monk.des | 8 +- dat/Priest.des | 2 +- dat/Ranger.des | 48 +- dat/Rogue.des | 63 +- dat/Samurai.des | 2 +- dat/Tourist.des | 2 +- dat/Valkyrie.des | 2 +- dat/Wizard.des | 16 +- dat/bigroom.des | 2 +- dat/castle.des | 2 +- dat/cmdhelp | 6 +- dat/data.base | 116 +- dat/dungeon.def | 8 +- dat/endgame.des | 11 +- dat/gehennom.des | 2 +- dat/help | 22 +- dat/hh | 15 +- dat/history | 113 +- dat/knox.des | 2 +- dat/medusa.des | 2 +- dat/mines.des | 861 ++++- dat/opthelp | 9 +- dat/oracle.des | 2 +- dat/quest.txt | 754 +++-- dat/rumors.fal | 5 +- dat/rumors.tru | 11 +- dat/sokoban.des | 7 +- dat/tower.des | 2 +- dat/wizhelp | 11 + dat/yendor.des | 2 +- doc/Guidebook.mn | 411 ++- doc/Guidebook.tex | 469 ++- doc/Guidebook.txt | 2350 +++++++------ doc/fixes22.0 | 353 ++ doc/fixes31.1 | 110 + doc/fixes31.2 | 92 + doc/fixes31.3 | 22 + doc/fixes32.0 | 344 ++ doc/fixes32.1 | 133 + doc/fixes32.2 | 128 + doc/fixes32.3 | 30 + doc/fixes33.0 | 372 +++ doc/fixes33.1 | 444 +++ doc/fixes34.0 | 592 ++++ doc/nethack.6 | 31 +- doc/nethack.txt | 417 +-- doc/window.doc | 262 +- include/align.h | 2 +- include/amiconf.h | 21 +- include/artifact.h | 3 +- include/artilist.h | 90 +- include/attrib.h | 2 +- include/beconf.h | 2 +- include/color.h | 2 +- include/config.h | 32 +- include/config1.h | 12 +- include/coord.h | 4 +- include/decl.h | 27 +- include/def_os2.h | 2 +- include/dgn_file.h | 2 +- include/display.h | 13 +- include/dlb.h | 2 +- include/dungeon.h | 2 +- include/edog.h | 2 +- include/emin.h | 2 +- include/engrave.h | 2 +- include/epri.h | 2 +- include/eshk.h | 2 +- include/extern.h | 173 +- include/flag.h | 125 +- include/func_tab.h | 2 +- include/global.h | 13 +- include/hack.h | 55 +- include/lev.h | 33 +- include/macconf.h | 72 +- include/macpopup.h | 9 +- include/mactty.h | 2 +- include/macwin.h | 2 +- include/mail.h | 2 +- include/mfndpos.h | 2 +- include/micro.h | 2 +- include/mkroom.h | 2 +- include/monattk.h | 4 +- include/mondata.h | 16 +- include/monflag.h | 2 +- include/monst.h | 6 +- include/monsym.h | 2 +- include/mttypriv.h | 2 +- include/nhlan.h | 2 +- include/ntconf.h | 50 +- include/obj.h | 36 +- include/objclass.h | 13 +- include/os2conf.h | 6 +- include/patchlevel.h | 47 +- include/pcconf.h | 21 +- include/permonst.h | 2 +- include/prop.h | 2 +- include/qt_clust.h | 2 +- include/qt_kde0.h | 4 +- include/qt_win.h | 51 +- include/qt_xpms.h | 13 + include/qtext.h | 25 +- include/qttableview.h | 251 ++ include/quest.h | 7 +- include/rect.h | 4 +- include/region.h | 2 +- include/rm.h | 4 +- include/skills.h | 2 +- include/sp_lev.h | 2 +- include/spell.h | 2 +- include/system.h | 32 +- include/tcap.h | 2 +- include/tile2x11.h | 6 +- include/timeout.h | 13 +- include/tradstdc.h | 6 +- include/trampoli.h | 2 +- include/trap.h | 16 +- include/unixconf.h | 33 +- include/vault.h | 2 +- include/vision.h | 2 +- include/vmsconf.h | 6 +- include/winGnome.h | 2 +- include/winX.h | 5 +- include/winami.h | 2 +- include/wingem.h | 2 +- include/winprocs.h | 82 +- include/wintty.h | 4 +- include/wintype.h | 2 +- include/xwindow.h | 2 +- include/xwindowp.h | 2 +- include/you.h | 16 +- include/youprop.h | 2 +- src/allmain.c | 25 +- src/alloc.c | 2 +- src/apply.c | 503 ++- src/artifact.c | 247 +- src/attrib.c | 10 +- src/ball.c | 126 +- src/bones.c | 25 +- src/botl.c | 16 +- src/cmd.c | 257 +- src/dbridge.c | 35 +- src/decl.c | 42 +- src/detect.c | 254 +- src/dig.c | 196 +- src/display.c | 62 +- src/dlb.c | 9 +- src/do.c | 257 +- src/do_name.c | 104 +- src/do_wear.c | 336 +- src/dog.c | 73 +- src/dogmove.c | 74 +- src/dokick.c | 167 +- src/dothrow.c | 464 ++- src/drawing.c | 12 +- src/dungeon.c | 14 +- src/eat.c | 470 ++- src/end.c | 222 +- src/engrave.c | 106 +- src/exper.c | 21 +- src/explode.c | 81 +- src/extralev.c | 18 +- src/files.c | 315 +- src/fountain.c | 37 +- src/hack.c | 601 +++- src/hacklib.c | 15 +- src/invent.c | 524 ++- src/light.c | 20 +- src/lock.c | 15 +- src/mail.c | 5 +- src/makemon.c | 114 +- src/mapglyph.c | 232 ++ src/mcastu.c | 916 +++-- src/mhitm.c | 139 +- src/mhitu.c | 460 ++- src/minion.c | 38 +- src/mklev.c | 19 +- src/mkmap.c | 3 +- src/mkmaze.c | 66 +- src/mkobj.c | 155 +- src/mkroom.c | 23 +- src/mon.c | 318 +- src/mondata.c | 98 +- src/monmove.c | 165 +- src/monst.c | 181 +- src/mplayer.c | 15 +- src/mthrowu.c | 272 +- src/muse.c | 208 +- src/music.c | 52 +- src/o_init.c | 7 +- src/objects.c | 47 +- src/objnam.c | 362 +- src/options.c | 1238 +++++-- src/pager.c | 44 +- src/pickup.c | 624 ++-- src/pline.c | 13 +- src/polyself.c | 198 +- src/potion.c | 321 +- src/pray.c | 412 ++- src/priest.c | 73 +- src/quest.c | 24 +- src/questpgr.c | 11 +- src/read.c | 254 +- src/rect.c | 2 +- src/region.c | 15 +- src/restore.c | 67 +- src/rip.c | 8 +- src/rnd.c | 2 +- src/role.c | 335 +- src/rumors.c | 43 +- src/save.c | 60 +- src/shk.c | 782 +++-- src/shknam.c | 36 +- src/sit.c | 45 +- src/sounds.c | 124 +- src/sp_lev.c | 33 +- src/spell.c | 158 +- src/steal.c | 278 +- src/steed.c | 163 +- src/teleport.c | 78 +- src/timeout.c | 205 +- src/topten.c | 44 +- src/track.c | 2 +- src/trap.c | 783 ++++- src/u_init.c | 152 +- src/uhitm.c | 365 +- src/vault.c | 95 +- src/version.c | 4 +- src/vision.c | 20 +- src/weapon.c | 236 +- src/were.c | 4 +- src/wield.c | 103 +- src/windows.c | 19 +- src/wizard.c | 80 +- src/worm.c | 2 +- src/worn.c | 146 +- src/write.c | 20 +- src/zap.c | 461 ++- sys/amiga/Build.ami | 146 + sys/amiga/Install.ami | 200 ++ sys/amiga/Makefile.agc | 1337 ++++++++ sys/amiga/Makefile.ami | 1679 ++++++++++ sys/amiga/NetHack.cnf | 212 ++ sys/amiga/amidos.c | 490 +++ sys/amiga/amidos.p | 42 + sys/amiga/amifont.uu | 9 + sys/amiga/amifont8.uu | 59 + sys/amiga/amigst.c | 43 + sys/amiga/amii.hlp | 31 + sys/amiga/amimenu.c | 95 + sys/amiga/amirip.c | 405 +++ sys/amiga/amisnd.c | 284 ++ sys/amiga/amistack.c | 21 + sys/amiga/amitty.c | 67 + sys/amiga/amiwind.c | 953 ++++++ sys/amiga/amiwind.p | 40 + sys/amiga/clipwin.c | 268 ++ sys/amiga/colorwin.c | 256 ++ sys/amiga/cvtsnd.c | 96 + sys/amiga/grave16.xpm | 223 ++ sys/amiga/ifchange | 56 + sys/amiga/mkdmake | 14 + sys/amiga/txt2iff.c | 457 +++ sys/amiga/winami.c | 1723 ++++++++++ sys/amiga/winami.p | 57 + sys/amiga/winchar.c | 1246 +++++++ sys/amiga/windefs.h | 203 ++ sys/amiga/winext.h | 144 + sys/amiga/winfuncs.c | 2451 ++++++++++++++ sys/amiga/winkey.c | 106 + sys/amiga/winmenu.c | 1597 +++++++++ sys/amiga/winproto.h | 151 + sys/amiga/winreq.c | 1177 +++++++ sys/amiga/winstr.c | 522 +++ sys/amiga/xpm2iff.c | 353 ++ sys/atari/Install.tos | 6 +- sys/be/bemain.c | 5 +- sys/mac/Files.r | 73 +- sys/mac/Install.mw | 2 +- sys/mac/MacHelp | 23 +- sys/mac/NHDeflts | 106 +- sys/mac/NHrsrc.hqx | 2000 ++++++----- sys/mac/News | 4 +- sys/mac/README | 11 + sys/mac/macerrs.c | 28 +- sys/mac/macfile.c | 45 +- sys/mac/macmain.c | 16 +- sys/mac/macmenu.c | 61 +- sys/mac/macsnd.c | 7 +- sys/mac/mactopl.c | 9 +- sys/mac/mactty.c | 2 +- sys/mac/macunix.c | 19 +- sys/mac/macwin.c | 86 +- sys/mac/mgetline.c | 13 +- sys/mac/mmodal.c | 641 +--- sys/mac/mrecover.c | 2 +- sys/mac/mttymain.c | 57 +- sys/msdos/Install.dos | 8 +- sys/msdos/Makefile.BC | 11 +- sys/msdos/Makefile.GCC | 13 +- sys/msdos/Makefile.MSC | 15 +- sys/msdos/Makefile.SC | 4 +- sys/msdos/NHAccess.nh | 2 +- sys/msdos/compwarn.lst | 16 + sys/msdos/def2mak.c | 383 +++ sys/msdos/genschem.l | 326 ++ sys/msdos/msdos.c | 6 +- sys/msdos/msdoshlp.txt | 2 +- sys/msdos/ovlinit.c | 2 +- sys/msdos/pckeys.c | 2 +- sys/msdos/pctiles.c | 3 +- sys/msdos/pctiles.h | 2 +- sys/msdos/pcvideo.h | 4 +- sys/msdos/portio.h | 2 +- sys/msdos/prebuild.mak | 67 + sys/msdos/schema1 | 606 ++++ sys/msdos/schema1.BC | 2 +- sys/msdos/schema2 | 669 ++++ sys/msdos/schema2.BC | 2 +- sys/msdos/schema3 | 600 ++++ sys/msdos/schema3.MSC | 26 +- sys/msdos/setup.bat | 9 +- sys/msdos/sound.c | 2 +- sys/msdos/template.mak | 2232 +++++++++++++ sys/msdos/tile2bin.c | 4 +- sys/msdos/video.c | 30 +- sys/msdos/vidtxt.c | 5 +- sys/msdos/vidvga.c | 73 +- sys/os2/Install.os2 | 12 +- sys/os2/Makefile.os2 | 685 ++-- sys/os2/os2.c | 2 +- sys/share/Makefile.lib | 2 +- sys/share/NetHack.cnf | 24 +- sys/share/dgn_lex.c | 29 +- sys/share/dgn_yacc.c | 2 +- sys/share/ioctl.c | 2 +- sys/share/lev_lex.c | 809 +++-- sys/share/lev_yacc.c | 2 +- sys/share/nhlan.c | 2 +- sys/share/pcmain.c | 52 +- sys/share/pcsys.c | 28 +- sys/share/pctty.c | 2 +- sys/share/pcunix.c | 66 +- sys/share/sounds/README | 2 +- sys/share/tclib.c | 2 +- sys/share/unixtty.c | 7 +- sys/share/uudecode.c | 250 ++ sys/unix/Install.unx | 8 +- sys/unix/Makefile.dat | 10 +- sys/unix/Makefile.doc | 8 +- sys/unix/Makefile.src | 77 +- sys/unix/Makefile.top | 36 +- sys/unix/Makefile.utl | 20 +- sys/unix/README.linux | 89 + sys/unix/depend.awk | 2 +- sys/unix/nethack.sh | 2 +- sys/unix/setup.sh | 0 sys/unix/unixmain.c | 62 +- sys/unix/unixres.c | 213 ++ sys/unix/unixunix.c | 137 +- sys/vms/Install.vms | 22 +- sys/vms/Makefile.dat | 13 +- sys/vms/Makefile.doc | 2 +- sys/vms/Makefile.src | 38 +- sys/vms/Makefile.top | 2 +- sys/vms/Makefile.utl | 13 +- sys/vms/lev_lex.h | 2 +- sys/vms/oldcrtl.c | 2 +- sys/vms/vmsbuild.com | 11 +- sys/vms/vmsfiles.c | 2 +- sys/vms/vmsmail.c | 2 +- sys/vms/vmsmain.c | 6 +- sys/vms/vmsmisc.c | 2 +- sys/vms/vmstty.c | 2 +- sys/vms/vmsunix.c | 51 +- sys/winnt/Install.nt | 475 ++- sys/winnt/Makefile.bcc | 1311 ++++++++ sys/winnt/Makefile.gcc | 1309 ++++++++ sys/winnt/Makefile.msc | 1345 ++++++++ sys/winnt/console.rc | 11 + sys/winnt/defaults.nh | 145 + sys/winnt/mapimail.c | 2 +- sys/winnt/nethack.def | 2 +- sys/winnt/nhico.uu | 50 +- sys/winnt/nhsetup.bat | 144 +- sys/winnt/ntsound.c | 2 +- sys/winnt/nttty.c | 386 ++- sys/winnt/porthelp | 300 ++ sys/winnt/win32api.h | 2 +- sys/winnt/winnt.c | 11 +- util/dgn_comp.l | 29 +- util/dgn_comp.y | 2 +- util/dgn_main.c | 6 +- util/dlb_main.c | 2 +- util/lev_comp.l | 33 +- util/lev_comp.y | 2 +- util/lev_main.c | 46 +- util/makedefs.c | 54 +- util/panic.c | 2 +- util/recover.c | 35 +- win/Qt/Install.Qt | 18 +- win/Qt/nhsplash.xpm | 374 +++ win/Qt/qt_clust.cpp | 2 +- win/Qt/qt_win.cpp | 1600 +++++++-- win/Qt/qttableview.cpp | 2275 +++++++++++++ win/Qt/tileedit.cpp | 11 +- win/Qt/tileedit.h | 2 +- win/X11/Install.X11 | 6 + win/X11/NetHack.ad | 8 +- win/X11/Window.c | 2 +- win/X11/nh32icon | 8 +- win/X11/nh56icon | 14 +- win/X11/nh72icon | 2 +- win/X11/tile2x11.c | 68 +- win/X11/winX.c | 54 +- win/X11/winmap.c | 272 +- win/X11/winmenu.c | 2 +- win/X11/winmesg.c | 2 +- win/X11/winmisc.c | 62 +- win/X11/winstat.c | 10 +- win/X11/wintext.c | 20 +- win/X11/winval.c | 2 +- win/gem/Install.gem | 2 +- win/gem/gr_rect.c | 181 + win/gem/gr_rect.h | 14 + win/gem/load_img.c | 7 +- win/gem/wingem.c | 376 ++- win/gem/wingem1.c | 1006 ++++-- win/gem/xpm2img.c | 164 + win/gnome/gn_xpms.h | 2 +- win/gnome/gnaskstr.c | 2 +- win/gnome/gnaskstr.h | 2 +- win/gnome/gnbind.c | 267 +- win/gnome/gnbind.h | 2 +- win/gnome/gnglyph.c | 34 +- win/gnome/gnglyph.h | 2 +- win/gnome/gnmain.c | 59 +- win/gnome/gnmain.h | 2 +- win/gnome/gnmap.c | 14 +- win/gnome/gnmap.h | 2 +- win/gnome/gnmenu.c | 2 +- win/gnome/gnmenu.h | 2 +- win/gnome/gnmesg.c | 2 +- win/gnome/gnmesg.h | 2 +- win/gnome/gnomeprv.h | 2 +- win/gnome/gnopts.c | 2 +- win/gnome/gnopts.h | 2 +- win/gnome/gnplayer.c | 46 +- win/gnome/gnplayer.h | 7 +- win/gnome/gnsignal.c | 359 +- win/gnome/gnsignal.h | 2 +- win/gnome/gnstatus.c | 19 +- win/gnome/gnstatus.h | 2 +- win/gnome/gntext.c | 5 +- win/gnome/gntext.h | 2 +- win/gnome/gnyesno.c | 2 +- win/gnome/gnyesno.h | 2 +- win/share/monsters.txt | 56 +- win/share/objects.txt | 652 ++-- win/share/other.txt | 1578 +++++++-- win/share/thintile.c | 16 +- win/share/tile.h | 2 + win/share/tile2bmp.c | 86 +- win/share/tilemap.c | 35 +- win/share/tiletext.c | 2 +- win/tty/getline.c | 27 +- win/tty/termcap.c | 16 +- win/tty/topl.c | 69 +- win/tty/wintty.c | 327 +- win/win32/dgncomp.dsp | 297 ++ win/win32/dgnstuff.dsp | 97 + win/win32/dgnstuff.mak | 59 + win/win32/dlb_main.dsp | 179 + win/win32/levcomp.dsp | 198 ++ win/win32/levstuff.dsp | 97 + win/win32/levstuff.mak | 59 + win/win32/makedefs.dsp | 198 ++ win/win32/mhaskyn.c | 11 + win/win32/mhaskyn.h | 11 + win/win32/mhdlg.c | 729 ++++ win/win32/mhdlg.h | 15 + win/win32/mhfont.c | 194 ++ win/win32/mhfont.h | 15 + win/win32/mhinput.c | 85 + win/win32/mhinput.h | 35 + win/win32/mhmain.c | 915 +++++ win/win32/mhmain.h | 16 + win/win32/mhmap.c | 954 ++++++ win/win32/mhmap.h | 20 + win/win32/mhmenu.c | 1367 ++++++++ win/win32/mhmenu.h | 18 + win/win32/mhmsg.h | 61 + win/win32/mhmsgwnd.c | 540 +++ win/win32/mhmsgwnd.h | 15 + win/win32/mhrip.c | 265 ++ win/win32/mhrip.h | 15 + win/win32/mhsplash.c | 169 + win/win32/mhsplash.h | 13 + win/win32/mhstatus.c | 176 + win/win32/mhstatus.h | 14 + win/win32/mhtext.c | 254 ++ win/win32/mhtext.h | 14 + win/win32/mnsel.uu | 9 + win/win32/mnselcnt.uu | 9 + win/win32/mnunsel.uu | 9 + win/win32/mswproc.c | 2017 +++++++++++ win/win32/nethack.dsw | 215 ++ win/win32/nethackw.dsp | 1108 ++++++ win/win32/petmark.uu | 9 + win/win32/recover.dsp | 146 + win/win32/resource.h | 149 + win/win32/rip.uu | 1805 ++++++++++ win/win32/splash.uu | 7045 +++++++++++++++++++++++++++++++++++++++ win/win32/tile2bmp.dsp | 146 + win/win32/tilemap.dsp | 281 ++ win/win32/tiles.dsp | 97 + win/win32/tiles.mak | 21 + win/win32/uudecode.dsp | 146 + win/win32/winMS.h | 187 ++ win/win32/winhack.c | 287 ++ win/win32/winhack.h | 18 + win/win32/winhack.rc | 332 ++ 530 files changed, 80911 insertions(+), 12899 deletions(-) create mode 100644 doc/fixes22.0 create mode 100644 doc/fixes31.1 create mode 100644 doc/fixes31.2 create mode 100644 doc/fixes31.3 create mode 100644 doc/fixes32.0 create mode 100644 doc/fixes32.1 create mode 100644 doc/fixes32.2 create mode 100644 doc/fixes32.3 create mode 100644 doc/fixes33.0 create mode 100644 doc/fixes33.1 create mode 100644 doc/fixes34.0 create mode 100644 include/qttableview.h create mode 100644 src/mapglyph.c create mode 100644 sys/amiga/Build.ami create mode 100644 sys/amiga/Install.ami create mode 100644 sys/amiga/Makefile.agc create mode 100644 sys/amiga/Makefile.ami create mode 100644 sys/amiga/NetHack.cnf create mode 100644 sys/amiga/amidos.c create mode 100644 sys/amiga/amidos.p create mode 100644 sys/amiga/amifont.uu create mode 100644 sys/amiga/amifont8.uu create mode 100644 sys/amiga/amigst.c create mode 100644 sys/amiga/amii.hlp create mode 100644 sys/amiga/amimenu.c create mode 100644 sys/amiga/amirip.c create mode 100644 sys/amiga/amisnd.c create mode 100644 sys/amiga/amistack.c create mode 100644 sys/amiga/amitty.c create mode 100644 sys/amiga/amiwind.c create mode 100644 sys/amiga/amiwind.p create mode 100644 sys/amiga/clipwin.c create mode 100644 sys/amiga/colorwin.c create mode 100644 sys/amiga/cvtsnd.c create mode 100644 sys/amiga/grave16.xpm create mode 100644 sys/amiga/ifchange create mode 100644 sys/amiga/mkdmake create mode 100644 sys/amiga/txt2iff.c create mode 100644 sys/amiga/winami.c create mode 100644 sys/amiga/winami.p create mode 100644 sys/amiga/winchar.c create mode 100644 sys/amiga/windefs.h create mode 100644 sys/amiga/winext.h create mode 100644 sys/amiga/winfuncs.c create mode 100644 sys/amiga/winkey.c create mode 100644 sys/amiga/winmenu.c create mode 100644 sys/amiga/winproto.h create mode 100644 sys/amiga/winreq.c create mode 100644 sys/amiga/winstr.c create mode 100644 sys/amiga/xpm2iff.c create mode 100644 sys/msdos/compwarn.lst create mode 100644 sys/msdos/def2mak.c create mode 100644 sys/msdos/genschem.l create mode 100644 sys/msdos/prebuild.mak create mode 100644 sys/msdos/schema1 create mode 100644 sys/msdos/schema2 create mode 100644 sys/msdos/schema3 create mode 100644 sys/msdos/template.mak create mode 100644 sys/share/uudecode.c create mode 100644 sys/unix/README.linux mode change 100755 => 100644 sys/unix/setup.sh create mode 100644 sys/unix/unixres.c create mode 100644 sys/winnt/Makefile.bcc create mode 100644 sys/winnt/Makefile.gcc create mode 100644 sys/winnt/Makefile.msc create mode 100644 sys/winnt/console.rc create mode 100644 sys/winnt/defaults.nh create mode 100644 sys/winnt/porthelp create mode 100644 win/Qt/nhsplash.xpm create mode 100644 win/Qt/qttableview.cpp create mode 100644 win/gem/gr_rect.c create mode 100644 win/gem/gr_rect.h create mode 100644 win/gem/xpm2img.c create mode 100644 win/win32/dgncomp.dsp create mode 100644 win/win32/dgnstuff.dsp create mode 100644 win/win32/dgnstuff.mak create mode 100644 win/win32/dlb_main.dsp create mode 100644 win/win32/levcomp.dsp create mode 100644 win/win32/levstuff.dsp create mode 100644 win/win32/levstuff.mak create mode 100644 win/win32/makedefs.dsp create mode 100644 win/win32/mhaskyn.c create mode 100644 win/win32/mhaskyn.h create mode 100644 win/win32/mhdlg.c create mode 100644 win/win32/mhdlg.h create mode 100644 win/win32/mhfont.c create mode 100644 win/win32/mhfont.h create mode 100644 win/win32/mhinput.c create mode 100644 win/win32/mhinput.h create mode 100644 win/win32/mhmain.c create mode 100644 win/win32/mhmain.h create mode 100644 win/win32/mhmap.c create mode 100644 win/win32/mhmap.h create mode 100644 win/win32/mhmenu.c create mode 100644 win/win32/mhmenu.h create mode 100644 win/win32/mhmsg.h create mode 100644 win/win32/mhmsgwnd.c create mode 100644 win/win32/mhmsgwnd.h create mode 100644 win/win32/mhrip.c create mode 100644 win/win32/mhrip.h create mode 100644 win/win32/mhsplash.c create mode 100644 win/win32/mhsplash.h create mode 100644 win/win32/mhstatus.c create mode 100644 win/win32/mhstatus.h create mode 100644 win/win32/mhtext.c create mode 100644 win/win32/mhtext.h create mode 100644 win/win32/mnsel.uu create mode 100644 win/win32/mnselcnt.uu create mode 100644 win/win32/mnunsel.uu create mode 100644 win/win32/mswproc.c create mode 100644 win/win32/nethack.dsw create mode 100644 win/win32/nethackw.dsp create mode 100644 win/win32/petmark.uu create mode 100644 win/win32/recover.dsp create mode 100644 win/win32/resource.h create mode 100644 win/win32/rip.uu create mode 100644 win/win32/splash.uu create mode 100644 win/win32/tile2bmp.dsp create mode 100644 win/win32/tilemap.dsp create mode 100644 win/win32/tiles.dsp create mode 100644 win/win32/tiles.mak create mode 100644 win/win32/uudecode.dsp create mode 100644 win/win32/winMS.h create mode 100644 win/win32/winhack.c create mode 100644 win/win32/winhack.h create mode 100644 win/win32/winhack.rc diff --git a/Files b/Files index f3ad555..011f2ca 100644 --- a/Files +++ b/Files @@ -1,4 +1,4 @@ -This is a listing of all files in a full NetHack 3.3 distribution, organized +This is a listing of all files in a full NetHack 3.4 distribution, organized in their standard manner on a UNIX system. It indicates which files are necessary for which versions, so that you can tell which files may be deleted from or not transferred to your system if you wish. @@ -22,8 +22,11 @@ wizhelp yendor.des doc: (files for all versions) Guidebook.mn Guidebook.tex Guidebook.txt dgn_comp.6 dgn_comp.txt -dlb.6 dlb.txt lev_comp.6 lev_comp.txt nethack.6 -nethack.txt recover.6 recover.txt tmac.n window.doc +dlb.6 dlb.txt fixes22.0 fixes31.1 fixes31.2 +fixes31.3 fixes32.0 fixes32.1 fixes32.2 fixes32.3 +fixes33.0 fixes33.1 fixes34.0 lev_comp.6 lev_comp.txt +nethack.6 nethack.txt recover.6 recover.txt tmac.n +window.doc include: (files for all versions) @@ -47,7 +50,7 @@ wintty.h (files for X versions) tile2x11.h winX.h xwindow.h xwindowp.h (files for Qt versions) -qt_clust.h qt_kde0.h qt_win.h qt_xpms.h +qt_clust.h qt_kde0.h qt_win.h qt_xpms.h qttableview.h (files for Gem versions) bitmfile.h gem_rsc.h load_img.h wingem.h (file for GNOME versions) @@ -64,42 +67,33 @@ do.c do_name.c do_wear.c dog.c dogmove.c dokick.c dothrow.c drawing.c dungeon.c eat.c end.c engrave.c exper.c explode.c extralev.c files.c fountain.c hack.c hacklib.c invent.c -light.c lock.c mail.c makemon.c mcastu.c -mhitm.c mhitu.c minion.c mklev.c mkmap.c -mkmaze.c mkobj.c mkroom.c mon.c mondata.c -monmove.c monst.c mplayer.c mthrowu.c muse.c -music.c o_init.c objects.c objnam.c options.c -pager.c pickup.c pline.c polyself.c potion.c -pray.c priest.c quest.c questpgr.c read.c -rect.c region.c restore.c rip.c rnd.c -role.c rumors.c save.c shk.c shknam.c -sit.c sounds.c sp_lev.c spell.c steal.c -steed.c teleport.c timeout.c topten.c track.c -trap.c u_init.c uhitm.c vault.c version.c -vision.c weapon.c were.c wield.c windows.c -wizard.c worm.c worn.c write.c zap.c +light.c lock.c mail.c makemon.c mapglyph.c +mcastu.c mhitm.c mhitu.c minion.c mklev.c +mkmap.c mkmaze.c mkobj.c mkroom.c mon.c +mondata.c monmove.c monst.c mplayer.c mthrowu.c +muse.c music.c o_init.c objects.c objnam.c +options.c pager.c pickup.c pline.c polyself.c +potion.c pray.c priest.c quest.c questpgr.c +read.c rect.c region.c restore.c rip.c +rnd.c role.c rumors.c save.c shk.c +shknam.c sit.c sounds.c sp_lev.c spell.c +steal.c steed.c teleport.c timeout.c topten.c +track.c trap.c u_init.c uhitm.c vault.c +version.c vision.c weapon.c were.c wield.c +windows.c wizard.c worm.c worn.c write.c +zap.c sys/amiga: (files for Amiga versions) -Build.ami HackWB.uu Install.ami Makefile.ami NHinfo.uu -NetHack.cnf NewGame.uu amidos.c amidos.p amifont.uu -amifont8.uu amigst.c amii.hlp amilib.c amimenu.c -amirip.c amisnd.c amistack.c amitty.c amiwbench.c -amiwind.c amiwind.p ask.uu char.c charwin.uu -clipwin.c clipwin.uu colors.uu colorwin.c cvtsnd.c -dflticon.uu dispmap.s grave16.xpm hackwb.hlp ifchange -mkdmake randwin.c randwin.uu scroll.uu string.uu -txt2iff.c wb.c wbcli.c wbdata.c wbdefs.h -wbgads.c wbprotos.h wbstruct.h wbwin.c wbwin.uu +Build.ami Install.ami Makefile.ami Makefile.agc NetHack.cnf +amidos.c amidos.p amifont.uu amifont8.uu amigst.c +amii.hlp amimenu.c amirip.c amisnd.c amistack.c +amitty.c amiwind.c amiwind.p clipwin.c colorwin.c +cvtsnd.c grave16.xpm ifchange mkdmake txt2iff.c winami.c winami.p winchar.c windefs.h winext.h winfuncs.c winkey.c winmenu.c winproto.h winreq.c winstr.c xpm2iff.c -sys/amiga/splitter: -(more files for Amiga versions) -amiout.h arg.c arg.h loader.c multi.c -multi.h split.doc split.h splitter.c - sys/atari: (files for Atari version) Install.tos atarifnt.uue nethack.mnu setup.g tos.c @@ -117,12 +111,6 @@ macerrs.c macfile.c machelp.hqx macmain.c macmenu.c macsnd.c mactopl.c mactty.c macunix.c macwin.c mgetline.c mmodal.c mrecover.c mrecover.hqx mttymain.c -sys/mac/old: -(files for old Think and MPW C compilers) -DCproj.hqx Install.mpw Install.thk LCproj.hqx MDproj.hqx -NHmake.hqx NHproj.hqx NetHack.r macsegs mhdump.c -mpwhack.h mstring.c - sys/msdos: (files for MSDOS version) Install.dos Makefile.BC Makefile.GCC Makefile.MSC Makefile.SC @@ -133,12 +121,6 @@ tile2bin.c video.c vidtxt.c vidvga.c (files for running MSDOS binary under Windows) nhico.uu nhpif.uu -sys/msdos/old: -(files for old MSC compiler) -MakeMSC.src MakeMSC.utl Makefile.dat README.old exesmurf.c -exesmurf.doc maintovl.doc ovlmgr.asm ovlmgr.doc ovlmgr.uu -schema.old trampoli.c - sys/os2: (files for OS/2 version) Install.os2 Makefile.os2 nhpmico.uu os2.c @@ -158,6 +140,8 @@ ioctl.c unixtty.c nhlan.c (Berkeley random number file, which may be included in any version) random.c +(Berkeley uudecode file, which may be used in build process of any version) +uudecode.c (file for VMS version) tclib.c (file for MSDOS, OS/2, and VMS versions) @@ -175,8 +159,8 @@ wdnflute.uu wdnharp.uu sys/unix: (files for UNIX versions) Install.unx Makefile.dat Makefile.doc Makefile.src Makefile.top -Makefile.utl depend.awk nethack.sh setup.sh unixmain.c -unixunix.c +Makefile.utl README.linux depend.awk nethack.sh setup.sh +unixmain.c unixunix.c unixres.c (files for replacement cpp, apparently only needed by some UNIX systems) cpp1.shr cpp2.shr cpp3.shr (file for sound driver for 386 UNIX) @@ -190,10 +174,10 @@ spec_lev.com vmsbuild.com vmsfiles.c vmsmail.c vmsmain.c vmsmisc.c vmstty.c vmsunix.c sys/winnt: -(files for Windows NT and Windows'95 version) -Install.nt Makefile.nt mapimail.c nethack.def nhico.uu -nhsetup.bat ntsound.c nttty.c win32api.h winnt.c -winnt.cnf +(files for Windows 9x, NT and Windows2000 version) +console.rc defaults.nh Install.nt Makefile.bcc Makefile.gcc +Makefile.msc mapimail.c nethack.def nhico.uu nhsetup.bat +ntsound.c nttty.c porthelp win32api.h winnt.c util: (files for all versions) @@ -204,8 +188,8 @@ dgn_comp.l dgn_comp.y lev_comp.l lev_comp.y win/Qt: (files for the Qt X11 widget library) -Install.Qt knethack.lnk knh-mini.xpm knh.xpm qt_clust.cpp -qt_win.cpp tileedit.cpp tileedit.h +Install.Qt knethack.lnk knh-mini.xpm knh.xpm nhsplash.xpm +qt_clust.cpp qt_win.cpp qttableview.cpp tileedit.cpp tileedit.h win/X11: (files for X versions) @@ -217,8 +201,9 @@ wintext.c winval.c win/gem: (files for GEM versions) -Install.gem bitmfile.c gem_rsc.uu gem_rso.uu load_img.c -tile2img.c title.uu wingem.c wingem1.c +Install.gem bitmfile.c gem_rsc.uu gem_rso.uu gr_rect.c +gr_rect.h load_img.c tile2img.c title.uu wingem.c +wingem1.c xpm2img.c win/gnome: (files for GNOME versions) @@ -232,15 +217,26 @@ gntext.h gnyesno.c gnyesno.h gn_xpms.h mapbg.xpm win/share: (files for versions using optional tiles) gifread.c monsters.txt objects.txt other.txt ppmwrite.c -thintile.c tile.doc tile.h tilemap.c tiletext.c +thintile.c tile.doc tile.h tile2bmp.c tilemap.c +tiletext.c win/tty: (files for tty versions) getline.c termcap.c topl.c wintty.c win/win32: -(files for NT and Windows'9x Win32 version) -tile2bmp.c +(files for Windows 9x, NT, Windows 2000, and Windows XP version) +dgncomp.dsp dgnstuff.dsp dgnstuff.mak dlb_main.dsp levcomp.dsp +levstuff.dsp levstuff.mak makedefs.dsp mhaskyn.c mhaskyn.h +mhdlg.c mhdlg.h mhfont.c mhfont.h mhinput.c +mhinput.h mhmain.c mhmain.h mhmap.c mhmap.h +mhmenu.c mhmenu.h mhmsg.h mhmsgwnd.c mhmsgwnd.h +mhrip.c mhrip.h mhsplash.h mhsplash.c mhstatus.c +mhstatus.h mhtext.c mhtext.h mnsel.uu mnselcnt.uu +mnunsel.uu mswproc.c nethack.dsw nethackw.dsp petmark.uu +recover.dsp resource.h rip.uu splash.uu tile2bmp.dsp +tilemap.dsp tiles.dsp tiles.mak uudecode.dsp winhack.c +winhack.h winhack.rc winMS.h @@ -289,7 +285,7 @@ monstr.c vis_tab.c (file optionally generated by tilemap at compile time) tile.c (files generated by 'moc' for Qt interface at compile time) -qt_kde0.moc qt_win.moc +qt_kde0.moc qt_win.moc qttableview.moc NOTE: If your binaries were compiled with the data librarian (DLB) option, your playground will not contain all of the files listed here. All diff --git a/Porting b/Porting index 1b2efd6..16f9cc2 100644 --- a/Porting +++ b/Porting @@ -1,4 +1,4 @@ - NetHack Porting Guidelines v 3.3 99-11-29 + NetHack Porting Guidelines v 3.4 1999-11-29 1.0 Introduction diff --git a/README b/README index 77b2d93..2c581a4 100644 --- a/README +++ b/README @@ -1,16 +1,50 @@ - NetHack 3.3.1 -- General information + NetHack 3.4.0 -- General information -NetHack 3.3.1 is an enhancement to the dungeon exploration game NetHack. +NetHack 3.4.0 is an enhancement to the dungeon exploration game NetHack. It is a distant descendent of Rogue and Hack, and a direct descendent of -NetHack 3.2 and 3.3.0. This version is primarily a bug fix release. - -Here is a brief overview of new additions and changes in the game. -To give more would be cheating, wouldn't it? - -o Many, many bug fixes and minor tweaks -o New warning system that is more pleasant than the old one -o The Amiga and Atari ports are resurrected -o The Gnome toolkit interface is now offered as an experimental option +NetHack 3.3. + +There are a great number of bug fixes in this release, as well as +many changes and surprises beyond what you see listed below. +Here is a brief overview of some new additions and changes in the game. + +o Many, many bug fixes and tweaks to the core code and to several ports +o Enhanced config file processing and player selection prompts for some ports +o Stamina affects ability to throw heavy things +o Objects merge in containers +o Wish for "nothing", and genocide "none" to preserve your conduct +o Several small refinements to race/role separation +o Config file BOULDER option to specify the symbol for displaying boulders +o New travel command which is particularly helpful for mouse navigation on + handheld computers +o more feedback about skill advancement from #enhance command +o End-of-game disclose options can be individually tuned to your liking +o Mac: command-key shortcuts in the player selection dialog +o Amiga: screenmode requester +o Win32: new graphical interface contributed by Alex Kompel + +We've also included variations of enhancements contributed by members +of the NetHack community at large. Among them: + +o Scott Bigham's new T-shirt messages and his option to turn off + resistance display effects +o Malcolm Ryan's option for "autodig" +o Jay Tilton's full-screen message window display via control-P +o Dylan O'Donnell's patch for optionally starting with no pet +o Tom Friedetzky's blessed/uncursed/cursed selection patch for menustyle:full +o Jason Short's additonal lens uses +o Kelly Bailey's Gnomish Mines changes +o Ken Arnold's patch to display prices in your inventory + +Carried forward +o The Gnome toolkit interface is still considered an experimental option. + We have not enhanced the port ourselves, and so far we have not received + any contributions doing so from the NetHack community. + +A fuller list of changes for this release can be found in the file +doc/fixes34.0 in the source distribution. The text in there was written +for the development team's own use and is provided "as is", so please do +not ask us to further explain the entries in that file. - - - - - - - - - - - @@ -35,31 +69,26 @@ Please read items (1), (2) and (3) BEFORE doing anything with your new code. h. A 'sys/share/sounds' subsubdirectory, which contains sound files shared by some OSs. i. A 'sys/amiga' subdirectory, which contains files specific to AmigaDOS. - j. A 'sys/amiga/splitter' subsubdirectory, which contains files - for the Amiga splitter program. + j. A 'sys/amiga/ship' subsubdirectory k. A 'sys/atari' subdirectory, which contains files specific to TOS. l. A 'sys/be' subdirectory, which contains files specific to Be OS. m. A 'sys/mac' subdirectory, which contains files specific to MacOS. - n. A 'sys/mac/old' subdirectory which contains files used by - compilers that haven't been tested/used in a while. - o. A 'sys/msdos' subdirectory, which contains files specific to MS-DOS. - p. A 'sys/msdos/old' subsubdirectory, which contains files for old - MS-DOS compilers (no longer officially supported). - q. A 'sys/os2' subdirectory, which contains files specific to OS/2. - r. A 'sys/unix' subdirectory, which contains files specific to UNIX. - s. A 'sys/vms' subdirectory, which contains files specific to VMS. - t. A 'sys/winnt' subdirectory, which contains files specific to Windows NT. - u. A 'win' directory, which contains subdirectories for files that + n. A 'sys/msdos' subdirectory, which contains files specific to MS-DOS. + o. A 'sys/os2' subdirectory, which contains files specific to OS/2. + p. A 'sys/unix' subdirectory, which contains files specific to UNIX. + q. A 'sys/vms' subdirectory, which contains files specific to VMS. + r. A 'sys/winnt' subdirectory, which contains files specific to Windows NT. + s. A 'win' directory, which contains subdirectories for files that are windowing-system specific (but not operating-system specific). - v. A 'win/share' subdirectory, which contains files shared by some + t. A 'win/share' subdirectory, which contains files shared by some windowing systems. - w. A 'win/Qt' subdirectory, which contains files specific to Qt. - x. A 'win/X11' subdirectory, which contains files specific to X11. - y. A 'win/gem' subdirectory, which contains files specific to GEM. - z. A 'win/gnome' subdirectory, which contains files specific to GNOME. - A. A 'win/tty' subdirectory, which contains files specific to ttys. - B. A 'win/win32' subdirectory, which contains files specific to the - Windows NT Win32 API. + u. A 'win/Qt' subdirectory, which contains files specific to Qt. + v. A 'win/X11' subdirectory, which contains files specific to X11. + w. A 'win/gem' subdirectory, which contains files specific to GEM. + x. A 'win/gnome' subdirectory, which contains files specific to GNOME. + y. A 'win/tty' subdirectory, which contains files specific to ttys. + z. A 'win/win32' subdirectory, which contains files specific to the + Windows Win32 API. The names of these directories should not be changed unless you are ready to go through the makefiles and the makedefs program and change @@ -78,7 +107,7 @@ Please read items (1), (2) and (3) BEFORE doing anything with your new code. to compile and run on your particular system. It is worth mentioning that the default configuration is SysV/Sun/Solaris2.x (simply because the code was housed on such a system). It is also worth mentioning - here that NetHack 3.3 is a huge program. If you intend to run it on a + here that NetHack 3.4 is a huge program. If you intend to run it on a small machine, you'll have to make hard choices among the options available in config.h. @@ -88,7 +117,7 @@ Please read items (1), (2) and (3) BEFORE doing anything with your new code. for particular windowing environments. Reading them, and the man pages, should answer most of your questions. - At the time of this release, NetHack 3.3 is known to run/compile on: + At the time of this release, NetHack 3.4 is known to run/compile on: Apple Macintosh running MacOS 7.5 or higher, LinuxPPC, BeOS 4.0 Atari ST/TT/Falcon running TOS (or MultiTOS) with GCC @@ -97,18 +126,15 @@ Please read items (1), (2) and (3) BEFORE doing anything with your new code. DEC Alpha/VMS (aka OpenVMS AXP), running V1.x through V7.0 DEC VAX/VMS, running V4.6 through V7.0 HP 9000s700 running HP-UX 10.x, 11.x - IBM PC compatibles running MS-DOS with Microsoft C, Borland C++ 3.1, or - DJGPP. It is recommended to have at least an 80386 processor. IBM PS/2 and AT compatibles running OS/2 - 2.0 and up with GCC emx - Intel 80386 or greater (or clone) and DEC Alpha desktop machines - running Windows NT + Intel 80386 or greater (or clone) boxes running MS-DOS with DPMI. Intel 80386 or greater (or clone) boxes running Linux, BSDI, or - Windows 95,98,2000 + Windows 95/98/NT/2000 Intel Pentium or better (or clone) running BeOS 4.5 Sun SPARC based machine running SunOS 4.x, Solaris 2.x, or Solaris 7 Previous versions of NetHack were tested on the following systems, - and we expect that NetHack 3.3 will work on them as well: + and we expect that NetHack 3.4 will work on them as well: AT&T 3B1 running System V (3.51) AT&T 3B2/600 & 3B2/622 running System V R3.2.1 @@ -139,18 +165,20 @@ Please read items (1), (2) and (3) BEFORE doing anything with your new code. Unless otherwise mentioned, the compiler used was the OS-vendor's C compiler. - The Atari and Amiga ports are struggling to stay supported due to a - lack of people with machines and time. - With the demise of Windows NT on the DEC Alpha, no attempt has been - made to build NetHack 3.3.1 on that platform. + made to build NetHack 3.4.0 on that platform. + + No attempt has been made to build or run NetHack 3.4.0 on Windows Me + or Windows XP at this point. It may work, but then again it may not. A build for Intel 80286 machines and DOS "real mode" overlaid versions - has been produced for 3.3.1, with a marginal attempt at tuning it for - suitable performance. If someone has access to real-mode compiler and - lots of spare time on their hands, you may be able to enhance the - performance even further. We don't know how well it runs on a real - 80286 since we no longer have access to one. + has not been produced for 3.4.0. Nobody on the porting team has + the time or the software to attempt the necessary tuning that will allow + it to achieve the balance of having just the right amount of available + memory, and still have acceptable performance. The sources necessary + to do so are still included in the source distribution, so if someone + has access to a real-mode compiler and lots of spare time on their hands, + you may be able to get things working. Of course you do so at your own risk. - - - - - - - - - - - @@ -178,20 +206,20 @@ o We don't give hints for playing the game. o Don't bother to ask when the next version will be out. You will not get a reply. Alternatively, you may fill out the bug report form on our web -page at www.nethack.org. +page at http://www.nethack.org/. Patches especially should be directed to this address. If you've changed something to get NetHack to run on your system, it's likely that others have done it by making slightly different modifications. By routing your patches through the development team, we should be able to avoid making everyone else choose among variant patches claiming to do the same thing, to keep most of -the copies of 3.3 synchronized by means of official patches, and to maintain +the copies of 3.4 synchronized by means of official patches, and to maintain the painfully-created file organization. (This process has been working since the time when everyone just posted their own patches to 2.3. At that time, there were no archived bug-fixes to give to people who got 2.3 after its initial release, so the same bugs kept being discovered by new batches of people.) We have been successful in preventing this from happening since the 3.0 -release. Please cooperate to keep this from happening to 3.3. +release. Please cooperate to keep this from happening to 3.4. It is inevitable that we will reject some proposed additions of new features either because they do not fit our conception of the game, or because they @@ -200,7 +228,7 @@ you are free, of course, to post the patches to the net yourself and let the marketplace decide their worth. All of this amounts to the following: If you decide to apply a free-lanced -patch to your 3.3 code, you are on your own. In our own patches, we will +patch to your 3.4 code, you are on your own. In our own patches, we will assume that your code is synchronized with ours. -- Good luck, and happy Hacking -- diff --git a/dat/Arch.des b/dat/Arch.des index a7cba58..414cf50 100644 --- a/dat/Arch.des +++ b/dat/Arch.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)Arch.des 3.3 97/01/31 +# SCCS Id: @(#)Arch.des 3.4 1997/01/31 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1991 by M. Stephenson # NetHack may be freely redistributed. See license for details. @@ -145,7 +145,7 @@ ENDMAP # Dungeon Description REGION:(00,00,75,19),lit,"ordinary" REGION:(25,04,28,07),lit,"temple" -REGION:(25,09,28,11),unlit,"ordinary" +REGION:(25,09,28,11),unlit,"temple" REGION:(25,13,28,16),lit,"temple" REGION:(30,04,30,16),lit,"ordinary" REGION:(32,04,32,16),unlit,"ordinary" @@ -199,6 +199,11 @@ OBJECT:random,random,random OBJECT:random,random,random OBJECT:random,random,random OBJECT:random,random,random +# Treasure? +ENGRAVING:random,engrave,"X marks the spot." +ENGRAVING:random,engrave,"X marks the spot." +ENGRAVING:random,engrave,"X marks the spot." +ENGRAVING:random,engrave,"X marks the spot." # Random traps TRAP:"spiked pit",(24,02) TRAP:"spiked pit",(37,00) @@ -255,8 +260,8 @@ MONSTER:'M',random,random # # The "goal" level for the quest. # -# Here you meet Minion of Huhetol your nemesis monster. You have to -# defeat Minion of Huhetol in combat to gain the artifact you have +# Here you meet Minion of Huhetotl your nemesis monster. You have to +# defeat Minion of Huhetotl in combat to gain the artifact you have # been assigned to retrieve. # @@ -313,7 +318,7 @@ REGION:(52,13,52,15),unlit,"ordinary" STAIR:(38,10),up # Non diggable walls NON_DIGGABLE:(00,00,75,19) -# The altar of Set. Unattended. +# The altar of Huhetotl. Unattended. ALTAR:(50,14),chaos,altar # Objects OBJECT:'(',"crystal ball",(50,14),blessed,5,"The Orb of Detection" diff --git a/dat/Barb.des b/dat/Barb.des index e91484d..c746295 100644 --- a/dat/Barb.des +++ b/dat/Barb.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)Barb.des 3.3 91/12/22 +# SCCS Id: @(#)Barb.des 3.4 1991/12/22 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1991 by M. Stephenson # NetHack may be freely redistributed. See license for details. diff --git a/dat/Caveman.des b/dat/Caveman.des index 6f782cc..3f408fe 100644 --- a/dat/Caveman.des +++ b/dat/Caveman.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)Caveman.des 3.3 95/10/07 +# SCCS Id: @(#)Caveman.des 3.4 1995/10/07 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1991 by M. Stephenson # NetHack may be freely redistributed. See license for details. diff --git a/dat/Healer.des b/dat/Healer.des index 0521067..e75aa18 100644 --- a/dat/Healer.des +++ b/dat/Healer.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)Healer.des 3.3 95/04/16 +# SCCS Id: @(#)Healer.des 3.4 1995/04/16 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1991, 1993 by M. Stephenson, P. Winner # NetHack may be freely redistributed. See license for details. diff --git a/dat/Knight.des b/dat/Knight.des index c2cb521..ba63140 100644 --- a/dat/Knight.des +++ b/dat/Knight.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)Knight.des 3.3 95/04/16 +# SCCS Id: @(#)Knight.des 3.4 1995/04/16 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1991,92 by M. Stephenson # NetHack may be freely redistributed. See license for details. diff --git a/dat/Monk.des b/dat/Monk.des index d44930d..656cb85 100644 --- a/dat/Monk.des +++ b/dat/Monk.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)Monk.des 3.3 1999/12/05 +# SCCS Id: @(#)Monk.des 3.4 2001/09/01 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1991-2 by M. Stephenson # NetHack may be freely redistributed. See license for details. @@ -105,9 +105,9 @@ MONSTER: 'X',"xorn",(01,17) MAZE: "Mon-loca",' ' GEOMETRY:center,center -MAP # 1 2 3 4 5 6 7 #123456789012345678901234567890123456789012345678901234567890123456789012345 +MAP ---------------------------------------------------- -------- ---.................................................- --.....| ---...--------........------........................--- ---...| @@ -121,11 +121,11 @@ MAP |......----- ---.........- | -----...|............| |..........----- ----...........--- -------......||...........|| |..............-----................--- |............|||..........| -|------...............................--- |...........|| |.........|| +|-S----...............................--- |...........|| |.........|| |.....|..............------.............-----..........|| ||........| |.....|.............-- ---.........................|| |.......|| |.....|.............- ---.....................--| ||......| -|------------.......---- --.................---- |.....|| +|---S--------.......---- --.................---- |.....|| |...........|..........--------..............----- ||....| |...........|............................----- |....| ------------------------------------------ ------ diff --git a/dat/Priest.des b/dat/Priest.des index 4b9deeb..ea75ab1 100644 --- a/dat/Priest.des +++ b/dat/Priest.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)Priest.des 3.3 92/09/22 +# SCCS Id: @(#)Priest.des 3.4 1992/09/22 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1991-2 by M. Stephenson # NetHack may be freely redistributed. See license for details. diff --git a/dat/Ranger.des b/dat/Ranger.des index 01f83d8..78df233 100644 --- a/dat/Ranger.des +++ b/dat/Ranger.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)Ranger.des 3.3 1999/11/26 +# SCCS Id: @(#)Ranger.des 3.4 2001/02/01 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1991 by M. Stephenson # NetHack may be freely redistributed. See license for details. @@ -14,34 +14,34 @@ INIT_MAP:'.','.',true,true,lit,false GEOMETRY:left,center #1234567890123456789012345678901234567890123456789012345678901234567890 MAP - TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT.. - TT...................................TT. -TT..TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT..TT -T..TT...............F...............TT..T -T.TT..TTTTTTTTTTTTT.F.TTTTTTTTTTTTT..TT.T -T.T..TT.............F.............TT..T.T -T.T.TT..TTTTTTTTTTTTTTTTTTTTTTTTT..TT.T.T -T.T.T..TT.......................TT..T...T -T.T.T.TT..TTTTTTTTTTTTTTTTTTTTT..TT.TTTTT -T...T.T..TT.|.....................T...... -TFFFT.T.TT..S..................TTTTTTTTTT -T...T.T..TT.|.................TT....T...T -T.T.T.TT..TTTTTTTTTTTTTTTTTTTTT..TT.T.T.T -T.T.T..TT.......................TT..T.T.T -T.T.TT..TTTTTTTTTTTTTTTTTTTTTTTTT..TT.T.T -T.T..TT.............F.............TT..T.T -T.TT..TTTTTTTTTTTTT.F.TTTTTTTTTTTTT..TT.T -T..TT...............F...............TT..T -TT..TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT..TT - TT...................................TT. - TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT.. + .. + ................................... . + .. .. + .. ...............F............... .. + . .. .F. .. . + . .. .............F............. .. . + . . .. .. . . + . . .. ....................... .. ... + . . . .. .. . + ... . .. .|..................... ...... + FFF . . ..S.................. + ... . .. .|................. .... ... + . . . .. .. . . . + . . .. ....................... .. . . + . . .. .. . . + . .. .............F............. .. . + . .. .F. .. . + .. ...............F............... .. + .. .. + ................................... . + .. ENDMAP # Dungeon Description REGION:(00,00,40,20),lit,"ordinary" # Stairs STAIR:(10,10),down -# Portal arrival point -BRANCH:levregion(01,00,79,20),(0,0,40,20) +# Portal arrival point; just about anywhere on the right hand side of the map +BRANCH:levregion(51,2,77,18),(0,0,40,20) # Orion MONSTER:'@',"Orion",(20,10) # The treasure of Orion diff --git a/dat/Rogue.des b/dat/Rogue.des index 5d610e9..cd38a97 100644 --- a/dat/Rogue.des +++ b/dat/Rogue.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)Rogue.des 3.3 93/05/10 +# SCCS Id: @(#)Rogue.des 3.4 2002/02/15 # Copyright (c) 1992 by Dean Luick # NetHack may be freely redistributed. See license for details. # @@ -10,22 +10,22 @@ MAZE: "Rog-strt",' ' FLAGS: noteleport, hardfloor, nommap GEOMETRY:center,center -MAP # 1 2 3 4 5 6 7 #123456789012345678901234567890123456789012345678901234567890123456789012345 +MAP ---------------------------------.------------------------------------------ |.....|.||..........|....|......|.|.........|.......+............---.......| -|.....|..+..........+....---....S.|...-------.-----.|............+.+.......| +|.....|..+..........+....---....S.|...-S-----.-----.|............+.+.......| |.....+.||........---......|....|.|...|.....|.|...|.---.....------.--------| |-----|.-------|..|........------.-----.....|.--..|...-------..............| -|.....|........------+------..........+.....|..------.........------.-----.. +|.....|........------+------..........+.....|..--S---.........------.-----.. |.....|.------...............-----.}}.--------.|....-------.---....|.+...--| |..-+--.|....|-----.--------.|...|.....+.....|.|....|.....+.+......|.--....| |..|....|....|....+.|......|.|...-----.|.....|.--...|.....|.|......|..|....| -|..|.----------...|.+....-----...|...|.----..|..|.---....--.---S-----.|----| +|..|.-----S----...|.+....-----...|...|.----..|..|.---....--.---S-----.|----| |..|.|........|...------.|.S.....|...|....-----.+.|......|..|.......|.|....| |---.-------..|...|....|.|.|.....|...----.|...|.|---.....|.|-.......|.---..| -...........|..|...|....---.----S----..|...|...+.|..-------.---+-....|...--+| +...........|..S...|....---.----S----..|...|...+.|..-------.---+-....|...--+| |---------.---------...|......|....S..|.---...|.|..|...........----.---....| |........|.........|...+.------....|---.---...|.--+-.----.----....|.+...--+| |........|.---+---.|----.--........|......-----......|..|..|.--+-.|.-S-.|..| @@ -58,6 +58,10 @@ DOOR: locked, (56,17) DOOR: locked, (57,17) DOOR: locked, (11,19) DOOR: locked, (37,19) +DOOR: locked, (39, 2) +DOOR: locked, (49, 5) +DOOR: locked, (10, 9) +DOOR: locked, (14,12) # Doors (regular) DOOR: closed, (52, 1) DOOR: closed, ( 9, 2) @@ -171,9 +175,9 @@ MONSTER: ':',"chameleon",random,hostile MAZE: "Rog-loca",' ' GEOMETRY:center,center -MAP # 1 2 3 4 5 6 7 #123456789012345678901234567890123456789012345678901234567890123456789012345 +MAP ---------------------------------------------------- -------- ---.................................................- --.....| ---...--------........-------.......................--- ---...| @@ -191,7 +195,7 @@ MAP |.....|..............------.............-----..........|| ||........| |.....|.............-- ---.........................|| |.......|| |.....|.............- ---.....................--| ||......| -|------------.......---- --.................---- |.....|| +|-S----------.......---- --.................---- |.....|| |...........|..........--------..............----- ||....| |...........|............................----- |....| ------------------------------------------ ------ @@ -206,7 +210,7 @@ STAIR:random,down # Non diggable walls NON_DIGGABLE:(00,00,75,20) # Objects -OBJECT:random,random,random +OBJECT:'?',"teleportation",(11,18),cursed,0 OBJECT:random,random,random OBJECT:random,random,random OBJECT:random,random,random @@ -264,36 +268,37 @@ MONSTER: ':',"chameleon",random,hostile MONSTER: ':',"chameleon",random,hostile # -# The "goal" level for the quest. +# The "goal" level for the quest. Teleportation and digging are +# disallowed. # -# Here you meet The Master Assassin your nemesis monster. You have to -# defeat The Master Assassin in combat to gain the artifact you have -# been assigned to retrieve. +# You have to reach The Master Assassin via some means other than +# simple searching or digging since there is no path between your +# arrival point and his location. # MAZE: "Rog-goal", ' ' FLAGS: noteleport GEOMETRY:center,center -MAP # 1 2 3 4 5 6 7 #123456789012345678901234567890123456789012345678901234567890123456789012345 +MAP ----- -------.......................................|-----------------| |...| -----.....|.......................................|.................| |...----...|.....|.......................................|....---------....| |.---......---..--.................................------------.......|....| |...............|..................................|..|...|...----........-| -|.....-----....--.................................|-..--..-|.....---------| -|------...|....|.................................|-........-|....|........| +|.....-----....--.................................|-..--..-|.....----S----| +|--S---...|....|.................................|-........-|....|........| |.........---------.............................|-....}}....-|...|...|....| -|....|.....|......|............................|-.....}}.....-|..--.------| +|....|.....S......|............................|-.....}}.....-|..--.------| |-----.....--.....|...........................|-...}}}}}}}}...-|....|.....-- -|...........--....------------...............|-....}}}}}}}}....-|..........| -|............--........|...|.|..............--.....}}.}}........------------ -|.............|........|...|.|..............|......}}}}}}}}......|...|.....| -|--.---.---.---.---.---|...|.------------...--........}}.}}.....--..---....| -|.---.---.---.---.---..-----.|....|.....|....|-....}}}}}}}}....---..|.|--..| -|...|.......|..........|...---....---...S.....|-...}}}}}}}}...-|.|..|...|..| -|...|..|....|..........|............|..--..----|-.....}}.....-|..----...---- -|...|---....----.......|----- ......|...---| |-....}}....-|...|..-----..| +|...........--....------S-----...............|-....}}}}}}}}....-|..........| +|............--........|...| |..............--.....}}.}}........----------S- +|.............|........|...| |..............|......}}}}}}}}......|...|.....| +|S-.---.---.---.---.---|...| ------------...--........}}.}}.....--..---....| +|.---.---.---.---.-S-..----- |....|.....|....|-....}}}}}}}}....---..S.|--..| +|...|.......|..........|...---....---...S.....|-...}}}}}}}}...-|.S..|...|..| +|...|..|....|..........|............|..--..----|-.....}}.....-|..----...-S-- +|...|---....----.......|----- ......|...---| |-....}}....-|...|..--.--..| -----.....---.....--.---....--...--------..| |-........-|....|.........| |.............|..........|.............S... |S-------|.....|..-----..| ---------------------------------------- ...... ---------- ---- @@ -301,7 +306,7 @@ ENDMAP # Dungeon Description REGION:(00,00,75,20),lit,"ordinary" # Stairs -STAIR:random,up +STAIR:levregion(01,00,15,20),(01,18,04,20),up # Doors # Non diggable walls NON_DIGGABLE:(00,00,75,20) @@ -309,7 +314,7 @@ NON_DIGGABLE:(00,00,75,20) TRAP:"spiked pit",(37,07) # Objects OBJECT:'(',"skeleton key",(38,10),blessed,0,"The Master Key of Thievery" -OBJECT:random,random,random +OBJECT:'%',"tin",(26,12),"chameleon",0 OBJECT:random,random,random OBJECT:random,random,random OBJECT:random,random,random @@ -371,6 +376,10 @@ MONSTER: ':',"chameleon",random,hostile MONSTER: ':',"chameleon",random,hostile MONSTER: ':',"chameleon",random,hostile MONSTER: ':',"chameleon",random,hostile +MONSTER:';',"shark",(51,14),hostile +MONSTER:';',"shark",(53,09),hostile +MONSTER:';',"shark",(55,15),hostile +MONSTER:';',"shark",(58,10),hostile # # The "fill" level for the quest. diff --git a/dat/Samurai.des b/dat/Samurai.des index fd4f153..13545cd 100644 --- a/dat/Samurai.des +++ b/dat/Samurai.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)Samurai.des 3.3 95/06/29 +# SCCS Id: @(#)Samurai.des 3.4 1995/06/29 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1991-92 by M. Stephenson, P. Winner # NetHack may be freely redistributed. See license for details. diff --git a/dat/Tourist.des b/dat/Tourist.des index 2bf1b19..348b9b7 100644 --- a/dat/Tourist.des +++ b/dat/Tourist.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)Tourist.des 3.3 92/09/26 +# SCCS Id: @(#)Tourist.des 3.4 1992/09/26 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1991,92 by M. Stephenson, P. Winner # NetHack may be freely redistributed. See license for details. diff --git a/dat/Valkyrie.des b/dat/Valkyrie.des index 3a9286a..e371b1b 100644 --- a/dat/Valkyrie.des +++ b/dat/Valkyrie.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)Valkyrie.des 3.3 97/01/31 +# SCCS Id: @(#)Valkyrie.des 3.4 1997/01/31 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1991-2 by M. Stephenson # NetHack may be freely redistributed. See license for details. diff --git a/dat/Wizard.des b/dat/Wizard.des index d111a42..14f99c9 100644 --- a/dat/Wizard.des +++ b/dat/Wizard.des @@ -1,10 +1,10 @@ -# SCCS Id: @(#)Wizard.des 3.3 92/07/11 +# SCCS Id: @(#)Wizard.des 3.4 1992/07/11 # Copyright (c) 1992 by David Cohrs # NetHack may be freely redistributed. See license for details. # # The "start" level for the quest. # -# Here you meet your (besieged) class leader, the Wizard of Balance +# Here you meet your (besieged) class leader, Neferet the Green # and receive your quest assignment. # MAZE: "Wiz-strt",' ' @@ -51,9 +51,9 @@ DOOR:locked,(35,10) DOOR:closed,(15,10) DOOR:locked,(19,10) DOOR:locked,(20,10) -# Wizard of Balance -MONSTER:'@',"Wizard of Balance",(23,05) -# The treasure of Wizard of Balance +# Neferet the Green, the quest leader +MONSTER:'@',"Neferet the Green",(23,05) +# The treasure of the quest leader OBJECT:'(',"chest",(24,05) # apprentice guards for the audience chamber MONSTER:'@',"apprentice",(30,07) @@ -236,9 +236,9 @@ MAP -------|...........-------------------...........| |......S...........|..|..|..|..|..|..|...........| |......|...........|..|..|..|..|..|..|...........| - |......|...........--+--+--+--+--+--+-...........| + |......|...........-F+-F+-F+-F+-F+-F+-...........| --S----|...........S.................+...........| - |......|...........--+--+--+--+--+--+-...........| + |......|...........-F+-F+-F+-F+-F+-F+-...........| |......|...........|..|..|..|..|..|..|...........| |......|...........|..|..|..|..|..|..|...........| -------|...........-------------------...........| @@ -349,6 +349,8 @@ MONSTER:'@',"wizard",(32,11),peaceful,asleep,"Newt" MONSTER:'@',"Grey-elf",(44,11),peaceful MONSTER:'H',"hill giant",(47,11),peaceful,asleep MONSTER:'G',"gnomish wizard",(38,06),peaceful +MONSTER:'@',"prisoner",(35,11),peaceful +MONSTER:'@',"prisoner",(41,11),peaceful,asleep # # The "fill" levels for the quest. diff --git a/dat/bigroom.des b/dat/bigroom.des index 0c2d07f..142ca85 100644 --- a/dat/bigroom.des +++ b/dat/bigroom.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)bigroom.des 3.3 90/04/15 +# SCCS Id: @(#)bigroom.des 3.4 1990/04/15 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1990 by M. Stephenson # NetHack may be freely redistributed. See license for details. diff --git a/dat/castle.des b/dat/castle.des index 1458540..9c6bca1 100644 --- a/dat/castle.des +++ b/dat/castle.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)castle.des 3.3 95/11/19 +# SCCS Id: @(#)castle.des 3.4 1995/11/19 # Copyright (c) 1989 by Jean-Christophe Collet # NetHack may be freely redistributed. See license for details. # diff --git a/dat/cmdhelp b/dat/cmdhelp index 273b98f..790c528 100644 --- a/dat/cmdhelp +++ b/dat/cmdhelp @@ -30,7 +30,7 @@ f Fire ammunition from quiver F Followed by direction, fight a monster (even if you don't sense it) g Followed by direction, move until you are near something G Followed by direction, same as control-direction -h Go west 1 space +h Go west 1 space (if number_pad is on, display help message) H Go west until you are on top of something ^H Go west until you are near something i Show your inventory @@ -82,6 +82,7 @@ Z Zap (cast) a spell & Tell what a command does ! Do a shell escape (only if defined) \ Show what object types have been discovered +_ Travel via a shortest-path algorithm to a point on the map . Rest one move while doing nothing Rest one move while doing nothing (if rest_on_space option is on) : Look at what is on the floor @@ -97,7 +98,8 @@ Z Zap (cast) a spell $ Count your gold + List known spells # Perform an extended command -M-2 Toggle two-weapon combat +M-? Display extended command help (if the platform allows this) +M-2 Toggle two-weapon combat (unless number_pad is enabled) M-a Adjust inventory letters M-c Talk to someone M-d Dip an object into something diff --git a/dat/data.base b/dat/data.base index 2da7977..f09fabf 100644 --- a/dat/data.base +++ b/dat/data.base @@ -1,4 +1,4 @@ -# SCCS Id: @(#)data.base 3.3 1999/11/28 +# SCCS Id: @(#)data.base 3.4 2001/09/01 # Copyright (c) 1994, 1995, 1996 by the NetHack Development Team # Copyright (c) 1994 by Boudewijn Wayers # NetHack may be freely redistributed. See license for details. @@ -183,6 +183,12 @@ apple and disciples have advanced so far as to be able to say when. [ The Devil's Dictionary, by Ambrose Bierce ] +archeologist + Archeology is the search for fact, not truth. [...] + So forget any ideas you've got about lost cities, exotic travel, + and digging up the world. We do not follow maps to buried + treasure, and X never, ever, marks the spot. + [ Indiana Jones and the Last Crusade ] archon Archons are the predominant inhabitants of the heavens. However unusual their appearance, they are not generally @@ -901,6 +907,7 @@ pup* loyalty to man and gentleness with children, it is the world's most popular domestic animal. It can easily be trained to perform various tasks. +~trap*door *door doorway Through me you pass into the city of woe: @@ -914,6 +921,19 @@ doorway All hope abandon ye who enter here. [ The Inferno, from The Divine Comedy of Dante Alighieri, translated by H.F. Cary ] +doppelganger + Xander: Let go! I have to kill the demon bot! + Xander Double (grabbing the gun): Anya, get out of the way. + Buffy: Xander! + Xander Double: That's all right, Buffy. I have him. + Xander: No, Buffy, I'm me. Help me! + Anya: My gun, he's got my gun. + Riley: You own a gun? + Buffy: Xander, gun holding Xander, give it to me. + Anya: Buffy, which one's real? + Xander: I am. + Xander Double: No, _I_ am. + [ Buffy the Vampire Slayer, Episode 5.03, "The Replacement" ] *dragon *xoth In the West the dragon was the natural enemy of man. Although @@ -942,6 +962,7 @@ doorway being who ever joined in the fierce, mad, intoxicating revel of the Dum-Dum. [ Tarzan of the Apes, by Edgar Rice Burroughs ] +~dwarf ??m* dwarf* Dwarfs have faces like men (ugly men, with wrinkled, leathery skins), but are generally either flat-footed, duck-footed, or @@ -1007,7 +1028,7 @@ elbereth A Elbereth Gilthoniel, silivren penna miriel o menel aglar elenath! - Na-chaered palen-diriel + Na-chaered palan-diriel o galadhremmin ennorath, Fanuilos, le linnathon nef aear, si nef aearon! @@ -1339,7 +1360,22 @@ gnomish wizard of his hat but forgot to doff it. 'What is the trouble, Alaraba?' said Ramon Alonzo. 'White magic. Run!' said the gnome .. - [ The Charwoman's Shadow, by Lord Dunsany ] + [ The Charwoman's Shadow, by Lord Dunsany ] + + "Muggles have garden gnomes, too, you know," Harry told Ron as + they crossed the lawn. + "Yeah, I've seen those things they think are gnomes," said Ron, + bent double with his head in a peony bush, "like fat little + Santa Clauses with fishing rods..." + There was a violent scuffling noise, the peony bush shuddered, + and Ron straightened up. "This is a gnome," he said grimly. + "Geroff me! Gerroff me!" squealed the gnome. + It was certainly nothing like Santa Claus. It was small and + leathery looking, with a large, knobby, bald head exactly like + a potato. Ron held it at arm's length as it kicked out at him + with its horny little feet; he grasped it around the ankles + and turned it upside down. + [ Harry Potter and the Chamber of Secrets, by J. K. Rowling ] goblin Now goblins are cruel, wicked, and bad-hearted. They make no beautiful things, but they make many clever ones. They @@ -1703,6 +1739,8 @@ cave*man chieftain guard healer +grand master +master kaen monk ninja nurse @@ -1724,6 +1762,16 @@ player resent the intrusion of such beasts. They are capable of using weapons and magic, and it is even rumored that the Wizard of Yendor is a member of this species. +hunter + What of the hunting, hunter bold? + Brother, the watch was long and cold. + What of the quarry ye went to kill? + Brother, he crops in the jungle still. + Where is the power that made your pride? + Brother, it ebbs from my flank and side. + Where is the haste that ye hurry by? + Brother, I go to my lair to die. + [ The Jungle Book, by Rudyard Kipling ] ice devil Ice devils are large semi-insectoid creatures, who are equally at home in the fires of Hell and the cold of Limbo, @@ -2587,6 +2635,15 @@ neanderthal* 1. Valley between Duesseldorf and Elberfeld in Germany, where an ancient skull of a prehistoric ancestor to modern man was found. 2. Human(oid) of the race mentioned above. +neferet +neferet the green + Neferet the Green holds office in her hidden tower, only + reachable by magical means, where she teaches her apprentices + the enigmatic skills of occultism. Despite her many years, she + continues to investigate new spells, especially those involving + translocation. It is further rumored that when she was an + apprentice herself, she accidentally turned her skin green, and + has kept it that way ever since. newt (kinds of) small animal, like a lizard, which spends most of its time in the water. @@ -2864,6 +2921,15 @@ pick*ax* it to kill and devour it, though in any other way they move but exceeding slow. [ the Bestiary of Xygag ] +piranha + They live in "schools." Many times they will wait for prey + to come to the shallow water of the river. Then the large + group of piranhas will attack. These large groups are able + to kill large animals... Their lower teeth fit perfectly + into the spaces of their upper teeth, creating a tremendous + vice-like bite... Piranhas are attracted to any disturbance + in the water. + [ http://www.animalsoftherainforest.com ] pit spiked pit Amid the thought of the fiery destruction that impended, the @@ -2885,7 +2951,7 @@ platinum yendorian express card This is an ancient artifact made of an unknown material. It is rectangular in shape, very thin, and inscribed with unreadable ancient runes. When carried, it grants the one - who carries it ESP, and reduces all physical damage done to + who carries it ESP, and reduces all spell induced damage done to the carrier by half. It also protects from magic missile attacks. Finally, its power is such that when invoked, it can charge other objects. @@ -3015,6 +3081,15 @@ quetzalcoatl he had to leave his empire. ... But all the legends of Quetzalcoatl unanimously agree that he promised to come again. [ Gods, Graves, and Scholars, by C. W. Ceram ] +quit* + Maltar: [...] I remembered a little saying I learned my first + day at the academy. + Natalie: Yeah, yeah, I know. Winners never quit and quitters + never win. + Maltar: What? No! Winners never quit and quitters should be + cast into the flaming pit of death. + [ Snow Day, directed by Chris Koch, + written by Will McRobb and Chris Viscardi ] raijin raiden The god of thunder. @@ -3253,7 +3328,7 @@ scorpius As Scorpius rises in the east, Orion sets in the west. [ 365 Starry Nights, by Chet Raymo ] *scroll -scroll of * +scroll * And I was gazing on the surges prone, With many a scalding tear and many a groan, When at my feet emerg'd an old man's hand, @@ -3287,8 +3362,32 @@ shan*lai*ching seas - which deals with the monster Kung Kung trying to seize power from Yao, the fourth emperor. [ Spectrum Atlas van de Mythologie ] +shark + As the shark moved, its dark top reflected virtually no + light. The denticles on its skin muted the whoosh of its + movements as the shark rose, driven by the power of the + great tail sweeping from side to side, like a scythe. + The fish exploded upward. + Charles Bruder felt a slight vacuum tug in the motion of + the sea, noted it as a passing current, the pull of a wave, + the tickle of undertow. He could not have heard the faint + sucking rush of water not far beneath him. He couldn't + have seen or heard what was hurtling from the murk at + astonishing speed, jaws unhinging, widening, for the + enormous first bite. It was the classic attack + that no other creature in nature could make -- a bomb from + the depths. + [ Close to Shore, by Michael Capuzzo ] shito A Japanese stabbing knife. +shrieker + With a single, savage thrust of her spear, the warrior-woman + impaled the fungus, silencing it. However, it was too late: + the alarm had been raised[...] + Suddenly, a large, dark shape rose from the abyss before them, + its fetid bulk looming overhead...The monster was some kind of + great dark worm, but that was about all they were sure of. + [ The Adventurers, Epic IV, by Thomas A. Miller ] skeleton A skeleton is a magically animated undead creature. Unlike shades, only a humanoid creature can be used to create a @@ -3730,6 +3829,7 @@ tree Poems are made by fools like me, But only God can make a tree. [ Trees - Joyce Kilmer ] +tripe tripe ration If you start from scratch, cooking tripe is a long-drawn-out affair. Fresh whole tripe calls for a minimum of 12 hours of @@ -3978,12 +4078,6 @@ web flat on his back upon a cold stone with his hands on his breast. [ The Fellowship of the Ring, by J.R.R. Tolkien ] -wizard of balance - The Wizard of Balance holds office in his hidden tower, only - reachable by magical means, where he teaches his apprentices - the enigmatic skills of occultism. He considers himself a - guardian of the equilibrium of the universe, and goes out of - his way to promote stability. wizard of yendor No one knows how old this mighty wizard is, or from whence he came. It is known that, having lived a span far greater than diff --git a/dat/dungeon.def b/dat/dungeon.def index 61db720..fbb17bc 100644 --- a/dat/dungeon.def +++ b/dat/dungeon.def @@ -1,4 +1,4 @@ -# SCCS Id: @(#)dungeon.def 3.3 96/03/10 +# SCCS Id: @(#)dungeon.def 3.4 1996/03/10 # Copyright (c) 1990-95 by M. Stephenson # NetHack may be freely redistributed. See license for details. # @@ -70,11 +70,9 @@ LEVEL: "fakewiz2" "G" @ (-6,4) DUNGEON: "The Gnomish Mines" "M" (8, 2) ALIGNMENT: lawful DESCRIPTION: mazelike -# LEVEL: "minetown" "T" @ (3, 2) -RNDLEVEL: "minetn" "T" @ (3, 2) 2 +RNDLEVEL: "minetn" "T" @ (3, 2) 7 LEVELDESC: town -# LEVEL: "mine_end" "E" @ (-1, 0) -RNDLEVEL: "minend" "E" @ (-1, 0) 2 +RNDLEVEL: "minend" "E" @ (-1, 0) 3 # # The Questdungeon diff --git a/dat/endgame.des b/dat/endgame.des index 02352ad..60500e1 100644 --- a/dat/endgame.des +++ b/dat/endgame.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)endgame.des 3.3 96/11/09 +# SCCS Id: @(#)endgame.des 3.4 2002/01/19 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1992,1993 by Izchak Miller, David Cohrs, # and Timo Hakulinen @@ -158,8 +158,13 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAACCCCCCAAACCCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAACCAAAAAACCCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ENDMAP -TELEPORT_REGION:(09,16,09,16),(0,0,0,0) -PORTAL:(30,0,75,19),(00,00,09,16),"fire" +# Use up and down regions to partition the level into three parts; +# teleportation can't cross from one part into another. +# The up region is where you'll arrive after activating the portal from +# the preceding level; the exit portal is placed inside the down region. +TELEPORT_REGION:levregion(01,00,24,20),levregion(25,00,79,20),up +TELEPORT_REGION:levregion(56,00,79,20),levregion(01,00,55,20),down +PORTAL:levregion(57,01,78,19),(0,0,0,0),"fire" REGION:(00,00,75,19),lit,"ordinary" MONSTER:'E',"air elemental",random,hostile MONSTER:'E',"air elemental",random,hostile diff --git a/dat/gehennom.des b/dat/gehennom.des index 8028283..bee336f 100644 --- a/dat/gehennom.des +++ b/dat/gehennom.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)gehennom.des 3.3 96/11/09 +# SCCS Id: @(#)gehennom.des 3.4 1996/11/09 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1992 by M. Stephenson and Izchak Miller # NetHack may be freely redistributed. See license for details. diff --git a/dat/help b/dat/help index a49b158..e559b2e 100644 --- a/dat/help +++ b/dat/help @@ -1,4 +1,4 @@ - Welcome to NetHack! ( description of version 3.3 ) + Welcome to NetHack! ( description of version 3.4 ) NetHack is a Dungeons and Dragons like game where you (the adventurer) descend into the depths of the dungeon in search of the Amulet of Yendor, @@ -43,6 +43,7 @@ on. \ An opulent throne. ` A boulder or statue. A to Z, a to z, and several others: Monsters. + I Invisible or unseen monster's last known location You can find out what a symbol represents by typing '/' and following the directions to move the cursor @@ -57,9 +58,15 @@ h-.-l 4-.-6 YUHJKLBN: go in specified direction until you b j n 1 2 3 g: run in direction until something numberpad interesting is seen G, same, except a branching corridor isn't - < up ^: considered interesting + < up ^: considered interesting (the ^ in this + case means the Control key, not a caret) > down m: move without picking up objects + F: fight even if you don't sense a monster If the number_pad option is set, the number keys move instead. + Depending on the platform, Shift number (on the numberpad), + Meta number, or Alt number will invoke the YUHJKLBN commands. + Control may or may not work when number_pad is enabled, + depending on the platform's capabilities. Commands: NetHack knows the following commands: @@ -70,6 +77,7 @@ Commands: < Go up a staircase (if you are standing on it). > Go down a staircase (if you are standing on it). . Rest, do nothing for one turn. + _ Travel via a shortest-path algorithm to a point on the map a Apply (use) a tool (pick-axe, key, lamp...) A Remove all armor. ^A Redo the previous command @@ -133,6 +141,7 @@ Commands: W Wear armor. x Swap wielded and secondary weapons. X Switch the game to explore (discovery) mode. + ^X Show your attributes. z Zap a wand. Z Cast a spell. ^Z Suspend the game. @@ -159,15 +168,17 @@ Commands: has a meta key (which, when pressed in combination with another key, modifies it by setting the 'meta' (8th, or 'high') bit), these extended commands can be invoked by meta-ing the first - letter of the command. + letter of the command. An alt key may have a similar effect. If the "number_pad" option is on, some additional letter commands are available: + h displays the help menu, like '?' j Jump to another location. k Kick (for doors, usually). l Loot a box on the floor. - n Name an object or type of object. + n followed by number of times to repeat the next command + N Name an object or type of object. u Untrap a trapped object or door. You can put a number before a command to repeat it that many times, @@ -175,7 +186,8 @@ Commands: must type 'n' to prefix the count, as in "n40." or "n20s". - Some information is displayed on the bottom line. You see your + Some information is displayed on the bottom line or perhaps in a + box, depending on the platform you are using. You see your attributes, your alignment, what dungeon level you are on, how many hit points you have now (and will have when fully recovered), what your armor class is (the lower the better), your experience level, diff --git a/dat/hh b/dat/hh index 0294587..ddd6f18 100644 --- a/dat/hh +++ b/dat/hh @@ -5,10 +5,15 @@ h-.-l 4-.-6 YUHJKLBN: go in specified direction until you b j n 1 2 3 g: run in direction until something numberpad interesting is seen G, same, except a branching corridor isn't - < up ^: considered interesting + < up ^: considered interesting (the ^ in this + case means the Control key, not a caret) > down m: move without picking up objects/fighting F: fight even if you don't sense a monster If the number_pad option is set, the number keys move instead. + Depending on the platform, Shift number (on the numberpad), + Meta number, or Alt number will invoke the YUHJKLBN commands. + Control may or may not work when number_pad is enabled, + depending on the platform's capabilities. General commands: ? help display one of several informative texts @@ -30,6 +35,7 @@ X explore switch the game to explore (discovery) mode Game commands: ^D kick kick (a door, or something else) ^T 'port teleport (if you can) +^X show show your attributes a apply apply or use a tool (pick-axe, key, camera, etc.) A armor take off all armor c close close a door @@ -67,6 +73,7 @@ Z Zap cast a spell * ask for combination of ),[,=,",( all at once $ gold count your gold + spells list the spells you know; also rearrange them if desired +_ travel move via a shortest-path algorithm to a point on the map . rest wait a moment , pickup pick up all you can carry @ toggle "pickup" (auto pickup) option on and off @@ -76,7 +83,8 @@ $ gold count your gold Keyboards that have a meta key can also use these extended commands via the meta modifier instead of the # prefix: -M-2 twoweapon toggle two-weapon combat +M-? Display extended command help (if the platform allows this) +M-2 twoweapon toggle two-weapon combat (unless number_pad is enabled) M-a adjust adjust inventory letters M-c chat talk to someone M-d dip dip an object into something @@ -90,7 +98,7 @@ M-n name name an item or type of object M-o offer offer a sacrifice to the gods M-p pray pray to the gods for help M-q quit stop playing -M-r rub rub a lamp +M-r rub rub a lamp or a stone M-s sit sit down M-t turn turn undead M-u untrap untrap something @@ -100,6 +108,7 @@ M-w wipe wipe off your face If the "number_pad" option is on, these additional variants are available: n followed by number of times to repeat the next command +h help display one of several informative texts, like '?' j jump jump to another location k kick kick something (usually a door) l loot loot a box on the floor diff --git a/dat/history b/dat/history index dcc3632..06d071f 100644 --- a/dat/history +++ b/dat/history @@ -1,4 +1,4 @@ -NetHack History file for release 3.3 +NetHack History file for release 3.4 Behold, mortal, the origins of NetHack... @@ -100,30 +100,56 @@ Warren Cheung combined SLASH with the Wizard Patch to produce Slash'em, and with the help of Kevin Hugo, added more features. Kevin later joined the DevTeam and incorporated the best of these ideas in NetHack 3.3. -The 3.3 development team consisted of Michael Allison, Ken Arromdee, -David Cohrs, Jessie Collet, Steve Creps, Kevin Darcy, Timo Hakulinen, -Kevin Hugo, Steve Linhart, Dean Luick, Pat Rankin, Eric Smith, Mike -Stephenson, Janet Walz, and Paul Winner. - -As with version 3.2, various people contributed to the game as a whole as +The final update to 3.2 was the bug fix release 3.2.3, which was released +simultaneously with 3.3.0 in December 1999 just in time for the Year 2000. + +The 3.3 development team, consisting of Michael Allison, Ken Arromdee, +David Cohrs, Jessie Collet, Steve Creps, Kevin Darcy, Timo Hakulinen, +Kevin Hugo, Steve Linhart, Ken Lorber, Dean Luick, Pat Rankin, Eric Smith, +Mike Stephenson, Janet Walz, and Paul Winner, released 3.3.0 in +December 1999 and 3.3.1 in August of 2000. + +Version 3.3 offered many firsts. It was the first version to separate race +and profession. The Elf class was removed in preference to an elf race, +and the races of dwarves, gnomes, and orcs made their first appearance in +the game alongside the familiar human race. Monk and Ranger roles joined +Archeologists, Barbarians, Cavemen, Healers, Knights, Priests, Rogues, +Samurai, Tourists, Valkyries and of course, Wizards. It was also the first +version to allow you to ride a steed, and was the first version to have a +publicly available web-site listing all the bugs that had been discovered. +Despite that constantly growing bug list, 3.3 proved stable enough to last +for more than a year and a half. + + +The 3.4 development team initially consisted of Michael Allison, Ken Arromdee, +David Cohrs, Jessie Collet, Kevin Hugo, Ken Lorber, Dean Luick, Pat Rankin, +Mike Stephenson, Janet Walz, and Paul Winner, with Warwick Allison joining +just before the release of NetHack 3.4.0 in March 2002. + +As with version 3.3, various people contributed to the game as a whole as well as supporting ports on the different platforms that NetHack runs on: -Pat Rankin maintained 3.3 for VMS. +Pat Rankin maintained 3.4 for VMS. -Michael Allison ported NetHack 3.3 for the MS-DOS platform. Paul Winner -and Yitzhak Sapir provided encouragement. +Michael Allison maintained NetHack 3.4 for the MS-DOS platform. +Paul Winner and Yitzhak Sapir provided encouragement. Dean Luick, Mark Modrall, and Kevin Hugo maintained and enhanced the -Macintosh port of 3.3. +Macintosh port of 3.4. + +Michael Allison, David Cohrs, Alex Kompel, Dion Nicolaas, and Yitzhak Sapir +maintained and enhanced 3.4 for the Microsoft Windows platform. Alex Kompel +contributed a new graphical interface for the Windows port. -Michael Allison ported 3.3 for the Microsoft Windows NT platform. +Ron Van Iwaarden maintained 3.4 for OS/2. -Ron Van Iwaarden took over responsibility for the OS/2 port. +Janne Salmijarvi and Teemu Suikki maintained and enhanced the +Amiga port of 3.4 after Janne Salmijarvi resurrected it for 3.3.1. -The Amiga port of NetHack was resurrected for 3.3.1 by Janne Salmijarvi. +Christian `Marvin' Bressler maintained 3.4 for the Atari after he +resurrected it for 3.3.1. -The Atari port of NetHack was resurrected for 3.3.1 by Christian "Marvin" -Bressler. +There is a NetHack web site maintained by Ken Lorber at http://www.nethack.org/. - - - - - - - - - - @@ -132,31 +158,34 @@ particularly intriguing modification to help out with the game. The Gods of the Dungeon sometimes make note of the names of the worst of these miscreants in this, the list of Dungeoneers: - Adam Aronow Irina Rempt-Drijfhout Mike Gallop - Andy Church Izchak Miller Mike Passaretti - Andy Swanson Janet Walz Mike Stephenson - Ari Huttunen Janne Salmijarvi Norm Meluch - Barton House Jean-Christophe Collet Olaf Seibert - Benson I. Margulies Jochen Erwied Pat Rankin - Bill Dyer John Kallen Paul Winner - Boudewijn Waijers John Rupley Pierre Martineau - Bruce Cox John S. Bien Ralf Brown - Bruce Holloway Johnny Lee Richard Addison - Bruce Mewborne Jon W{tte Richard Beigel - Carl Schelin Jonathan Handler Richard P. Hughey - Chris Russo Joshua Delahunty Rob Menke - David Cohrs Keizo Yamamoto Robin Johnson - David Damerell Ken Arromdee Roland McGrath - David Gentzel Ken Lorber Ron Van Iwaarden - David Hairston Ken Washikita Ronnen Miller - Dean Luick Kevin Darcy Ross Brown - Del Lamb Kevin Hugo Sascha Wostmann - Deron Meranda Kevin Sitze Scott R. Turner - Dylan O'Donnell Kevin Smolkowski Stephen Spackman - Eric Backus Kevin Sweet Stephen White - Eric Hendrickson Lars Huttar Steve Creps - Eric R. Smith Mark Gooderum Steve Linhart - Eric S. Raymond Mark Modrall Steve VanDevender + Adam Aronow Helge Hafting Mike Engber + Alex Kompel Irina Rempt-Drijfhout Mike Gallop + Andreas Dorn Izchak Miller Mike Passaretti + Andy Church J. Ali Harlow Mike Stephenson + Andy Swanson Janet Walz Norm Meluch + Ari Huttunen Janne Salmijarvi Olaf Seibert + Barton House Jean-Christophe Collet Pat Rankin + Benson I. Margulies Jochen Erwied Paul Winner + Bill Dyer John Kallen Pierre Martineau + Boudewijn Waijers John Rupley Ralf Brown + Bruce Cox John S. Bien Richard Addison + Bruce Holloway Johnny Lee Richard Beigel + Bruce Mewborne Jon W{tte Richard P. Hughey + Carl Schelin Jonathan Handler Rob Menke + Chris Russo Joshua Delahunty Robin Johnson + David Cohrs Keizo Yamamoto Roland McGrath + David Damerell Ken Arnold Ron Van Iwaarden + David Gentzel Ken Arromdee Ronnen Miller + David Hairston Ken Lorber Ross Brown + Dean Luick Ken Washikita Sascha Wostmann + Del Lamb Kevin Darcy Scott Bigham + Deron Meranda Kevin Hugo Scott R. Turner + Dion Nicolaas Kevin Sitze Stephen Spackman + Dylan O'Donnell Kevin Smolkowski Stephen White + Eric Backus Kevin Sweet Steve Creps + Eric Hendrickson Lars Huttar Steve Linhart + Eric R. Smith Mark Gooderum Steve VanDevender + Eric S. Raymond Mark Modrall Teemu Suikki Erik Andersen Marvin Bressler Tim Lennan Frederick Roeber Matthew Day Timo Hakulinen Gil Neiger Merlyn LeRoy Tom Almy @@ -164,4 +193,4 @@ in this, the list of Dungeoneers: Greg Olson Michael Feir Warren Cheung Gregg Wonderly Michael Hamel Warwick Allison Hao-yang Wang Michael Sokolov Yitzhak Sapir - Helge Hafting Mike Engber + diff --git a/dat/knox.des b/dat/knox.des index 0886742..8ff123a 100644 --- a/dat/knox.des +++ b/dat/knox.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)knox.des 3.3 94/08/20 +# SCCS Id: @(#)knox.des 3.4 1994/08/20 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1992 by Izchak Miller # NetHack may be freely redistributed. See license for details. diff --git a/dat/medusa.des b/dat/medusa.des index 97b2a6d..879868f 100644 --- a/dat/medusa.des +++ b/dat/medusa.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)medusa.des 3.3 96/05/11 +# SCCS Id: @(#)medusa.des 3.4 1996/05/11 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1990, 1991 by M. Stephenson # NetHack may be freely redistributed. See license for details. diff --git a/dat/mines.des b/dat/mines.des index ccd73fe..87a87b6 100644 --- a/dat/mines.des +++ b/dat/mines.des @@ -1,18 +1,62 @@ -# SCCS Id: @(#)mines.des 3.3 95/10/07 +# SCCS Id: @(#)mines.des 3.4 2002/01/01 # Copyright (c) 1989-95 by Jean-Christophe Collet # Copyright (c) 1991-95 by M. Stephenson # NetHack may be freely redistributed. See license for details. # +# The "fill" level for the mines. +# +# This level is used to fill out any levels not occupied by +# specific levels as defined below. +# +MAZE: "minefill" , ' ' +INIT_MAP: '.' , ' ' , true , true , random , true +NOMAP +# +STAIR: random, up +STAIR: random, down +# +OBJECT: '*', random, random +OBJECT: '*', random, random +OBJECT: '*', random, random +OBJECT: '(', random, random +OBJECT: random, random, random +OBJECT: random, random, random +OBJECT: random, random, random +# +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome lord", random +MONSTER: 'h', "dwarf", random +MONSTER: 'h', "dwarf", random +MONSTER: 'G', random, random +MONSTER: 'G', random, random +MONSTER: 'h', random, random +# +TRAP: random, random +TRAP: random, random +TRAP: random, random +TRAP: random, random +TRAP: random, random +TRAP: random, random + + +# Minetown variant 1 +# "Frontier Town" +# LEVEL: "minetn-1" ROOM: "ordinary" , lit, (3,3), (center,center), (31,15) NAME: "town" FOUNTAIN: (13, 7) FOUNTAIN: (20, 7) -# -# The Town Watch. -# + +# The Town Watch MONSTER: '@', "watchman", random, peaceful MONSTER: '@', "watchman", random, peaceful MONSTER: '@', "watchman", random, peaceful @@ -82,107 +126,17 @@ MONSTER: 'G', "gnome", random RANDOM_CORRIDORS -MAZE: "minend-1", ' ' -GEOMETRY:center,center -MAP ---------------------------------------------------------------------------- -| |.......| |.......-...| |.....| | -| --------- ----.......-------...........| ---...--- | -| |.......| |..........................--- --.......| | -| |......------- ---........................| |.......-- | -| |..--........-----..........................| -.-..---- | -| --..--.-----........-.....................--- --..-- | -| --..--..| -----------..................---.----------..-- | -| |...--.| |..S...S..............---................-- | -| ----..----- ------------........--- ------------...--- | -| |.........-- ---------- ---...-- ----- | -| --.....---..-- -------- --...---...-- | -| ----..-..-- --..--------------------- --......-- ---........| | -|--....----- --..-..................--- |........| |.......-- | -|.......| --......................| --......-- ---..---- | -|--.--.-- ----.................--- ------..------...-- | -| |....| |...............-..| |...........| | ---------------------------------------------------------------------------- -ENDMAP -# Dungeon Description -REGION:(26,01,32,01),unlit,"ordinary",filled,true -REGION:(20,08,21,08),unlit,"ordinary" -REGION:(23,08,25,08),unlit,"ordinary" -# Secret doors -DOOR:locked,(22,08) -DOOR:locked,(26,08) -# Stairs -STAIR:(36,04),up -# Non diggable walls -NON_DIGGABLE:(00,00,74,17) -# Objects -OBJECT:'*',"diamond",(21,08) -OBJECT:'*',random,(21,08) -OBJECT:'*',"diamond",(21,08) -OBJECT:'*',random,(21,08) -OBJECT:'*',"emerald",(21,08) -OBJECT:'*',random,(21,08) -OBJECT:'*',"emerald",(21,08) -OBJECT:'*',random,(21,08) -OBJECT:'*',"emerald",(21,08) -OBJECT:'*',random,(21,08) -OBJECT:'*',"ruby",(21,08) -OBJECT:'*',random,(21,08) -OBJECT:'*',"ruby",(21,08) -OBJECT:'*',"amethyst",(21,08) -OBJECT:'*',random,(21,08) -OBJECT:'*',"amethyst",(21,08) -OBJECT:'*',"luckstone",(21,08) -OBJECT:'*',random,random -OBJECT:'*',random,random -OBJECT:'*',random,random -OBJECT:'*',random,random -OBJECT:'*',random,random -OBJECT:'*',random,random -OBJECT:'*',random,random -OBJECT:'(',random,random -OBJECT:'(',random,random -OBJECT:random,random,random -OBJECT:random,random,random -OBJECT:random,random,random -# Random traps -TRAP:random,random -TRAP:random,random -TRAP:random,random -TRAP:random,random -TRAP:random,random -TRAP:random,random -# Random monsters. -MONSTER:'G',"gnome king",random -MONSTER:'G',"gnome lord",random -MONSTER:'G',"gnome lord",random -MONSTER:'G',"gnome lord",random -MONSTER:'G',"gnomish wizard",random -MONSTER:'G',"gnomish wizard",random -MONSTER:'G',"gnome",random -MONSTER:'G',"gnome",random -MONSTER:'G',"gnome",random -MONSTER:'G',"gnome",random -MONSTER:'G',"gnome",random -MONSTER:'G',"gnome",random -MONSTER:'G',"gnome",random -MONSTER:'G',"gnome",random -MONSTER:'G',"gnome",random -MONSTER:'h',"hobbit",random -MONSTER:'h',"hobbit",random -MONSTER:'h',"dwarf",random -MONSTER:'h',"dwarf",random -MONSTER:'h',"dwarf",random -MONSTER:'h',random,random +# Minetown variant 2 +# "Town Square" +# LEVEL: "minetn-2" ROOM: "ordinary" , lit, (3,3), (center,center), (31,15) NAME: "town" FOUNTAIN: (17, 5) FOUNTAIN: (13, 8) -# -# The Town Watch. -# + +# The Town Watch MONSTER: '@', "watchman", random, peaceful MONSTER: '@', "watchman", random, peaceful MONSTER: '@', "watchman", random, peaceful @@ -268,6 +222,576 @@ MONSTER: 'G', "gnome", random RANDOM_CORRIDORS + +# Minetown variant 3 by Kelly Bailey +# "Alley Town" +# +LEVEL: "minetn-3" +ROOM: "ordinary",lit,(3,3),(center,center),(31,15) +NAME: "town" +FOUNTAIN:(01,06) +FOUNTAIN:(29,13) +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watch captain", random, peaceful + +SUBROOM:"ordinary",random,(2,2),(2,2),"town" +DOOR: false,closed,south,random + +SUBROOM:"tool shop",lit,(5,3),(2,3),"town" +CHANCE: 30 +DOOR: false,closed,south,random + +SUBROOM:"ordinary",random,(2,10),(2,3),"town" +DOOR: false, locked, north, random +MONSTER: 'G',random,random + +SUBROOM:"ordinary",random,(5,9),(2,2),"town" +DOOR: false,closed,north,random + +SUBROOM:"temple",lit,(10,2),(3,4),"town" +DOOR: false,closed,east,random +ALTAR:(1,1),align[0],shrine +MONSTER: 'G', "gnomish wizard", random +MONSTER: 'G', "gnomish wizard", random + +SUBROOM:"ordinary",random,(11,7),(2,2),"town" +DOOR: false,closed,west,random + +SUBROOM:"shop",lit,(10,10),(3,3),"town" +DOOR:false,closed,west,random + +SUBROOM:"ordinary",random,(14,8),(2,2),"town" +DOOR:false,locked,north,random +MONSTER: 'G',random,random + +SUBROOM:"ordinary",random,(14,11),(2,2),"town" +DOOR:false,closed,south,random + +SUBROOM:"tool shop",lit,(17,10),(3,3),"town" +CHANCE:40 +DOOR:false,closed,north,random + +SUBROOM:"ordinary",random,(21,11),(2,2),"town" +DOOR:false,locked,east,random +MONSTER:'G',random,random + +SUBROOM:"food shop",lit,(26,8),(3,2),"town" +CHANCE:90 +DOOR:false,closed,west,random + +SUBROOM:"ordinary",random,(16,2),(2,2),"town" +DOOR:false,closed,west,random + +SUBROOM:"ordinary",random,(19,2),(2,2),"town" +DOOR:false,closed,north,random + +SUBROOM:"wand shop",lit,(19,5),(3,2),"town" +CHANCE:30 +DOOR:false,closed,west,random + +SUBROOM: "candle shop",lit,(25,2),(3,3),"town" +DOOR:false,closed,south,random + +ROOM: "ordinary", random, random, random, random +STAIR: random, up + +ROOM: "ordinary" , random, random, random, random +STAIR: random, down +TRAP: random, random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random + +ROOM: "ordinary" , random, random, random, random +MONSTER: 'h', "dwarf", random + +ROOM: "ordinary" , random, random, random, random +TRAP: random, random +MONSTER: 'G', "gnome", random + +RANDOM_CORRIDORS + + +# Minetown variant 4 by Kelly Bailey +# "College Town" +# +LEVEL: "minetn-4" +ROOM: "ordinary",lit,(3,3),(center,center),(30,15) +NAME: "town" +FOUNTAIN:(08,07) +FOUNTAIN:(18,07) +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watch captain", random, peaceful + +SUBROOM:"book shop",lit,(4,2),(3,3),"town" +DOOR: false,closed,south,random + +SUBROOM:"ordinary",random,(8,2),(2,2),"town" +DOOR: false,closed,south,random + +SUBROOM:"temple",lit,(11,3),(5,4),"town" +DOOR: false,closed,south,random +ALTAR:(2,1),align[0],shrine +MONSTER: 'G', "gnomish wizard", random +MONSTER: 'G', "gnomish wizard", random + +SUBROOM:"ordinary",random,(19,2),(2,2),"town" +DOOR: false,closed,south,random +MONSTER: 'G', random, random + +SUBROOM:"candle shop",lit,(22,2),(3,3),"town" +DOOR:false,closed,south,random + +SUBROOM:"ordinary",random,(26,2),(2,2),"town" +DOOR:false,locked,east,random +MONSTER: 'G',random,random + +SUBROOM:"tool shop",lit,(4,10),(3,3),"town" +CHANCE:90 +DOOR:false,closed,north,random + +SUBROOM:"ordinary",random,(8,11),(2,2),"town" +DOOR:false,locked,south,random +MONSTER: 'k',"kobold shaman",random +MONSTER: 'k',"kobold shaman",random +MONSTER: 'f',"kitten",random +MONSTER: 'f',random,random + +SUBROOM:"food shop",lit,(11,11),(3,2),"town" +CHANCE:90 +DOOR:false,closed,east,random + +SUBROOM:"ordinary",random,(17,11),(2,2),"town" +DOOR:false,closed,west,random + +SUBROOM:"ordinary",random,(20,10),(2,2),"town" +DOOR:false,locked,north,random +MONSTER:'G',random,random + +SUBROOM:"shop",lit,(23,10),(3,3),"town" +CHANCE:90 +DOOR:false,closed,north,random + +ROOM: "ordinary" , random, random, random, random +STAIR: random, up + +ROOM: "ordinary" , random, random, random, random +STAIR: random, down +TRAP: random, random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random + +ROOM: "ordinary" , random, random, random, random +MONSTER: 'h', "dwarf", random + +ROOM: "ordinary" , random, random, random, random +TRAP: random, random +MONSTER: 'G', "gnome", random + +RANDOM_CORRIDORS + + +# "Grotto Town" by Kelly Bailey +# +MAZE: "minetn-5",' ' +GEOMETRY:center,center +MAP +----- --------- +|...--- ------.......-- ------- --------------- +|.....----.........--..| |.....| ------- |.............| +--..-....-.----------..| |.....| |.....| --+---+- .----+- + --.--.....---- ---- |.....| ------ --....---- |..-...--.-.+..| + ---.........---- ----- ---+--- |..+.| ---..-..----..---+-..---..| + ----.-....|..----...-- |.| |..|.| ---+-.....-+--........--+- + -----..|....-.....---- |.| |..|.------......--................| + ------ |..|.............---.-- ----.+..|-.......--..--------+--..-- + |....| --......---...........----- |.|..|-...{....---|.........|..-- + |....| |........-...-...........----.|..|--.......| |.........|...| + ---+--------....-------...---......--.-------....---- -----------...| + ------.---...--...--..-..--...-..---...|.--..-...-....------- |.......-- + |..|-.........-..---..-..---.....--....|........---...-|....| |.------- + |..+...............-+---+-----..--..........--....--...+....| |.|...S. +-----.....{....----...............-...........--...-...-|....| |.|...| +|..............-- --+--.---------.........--..-........------- |.--+------- +-+-----.........| |...|.|....| --.......------...|....---------.....|....| +|...| --..------- |...|.+....| ---...--- --..|...--......-...{..+..-+| +|...| ---- ------|....| ----- -----.....----........|..|.| +----- ------ ------- --------------- +ENDMAP +STAIR:(01,01),up +STAIR:(46,03),down + +REGION:(00,00,74,20),unlit,"ordinary" +REGION:(09,13,11,17),lit,"ordinary" +REGION:(08,14,12,16),lit,"ordinary" +REGION:(49,07,51,11),lit,"ordinary" +REGION:(48,08,52,10),lit,"ordinary" +REGION:(64,17,68,19),lit,"ordinary" +REGION:(37,13,39,17),lit,"ordinary" +REGION:(36,14,40,17),lit,"ordinary" +REGION:(59,02,72,10),lit,"ordinary" + +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watch captain", random, peaceful +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome lord", random +MONSTER: 'G', "gnome lord", random +MONSTER: 'h', "dwarf", random +MONSTER: 'h', "dwarf", random +MONSTER: 'h', "dwarf", random + +# The shops +REGION:(25,17,28,19),lit,"candle shop" +DOOR:closed,(24,18) +REGION:(59,9,67,10),lit,"shop" +DOOR:closed,(66,08) +REGION:(57,13,60,15),lit,"tool shop" +DOOR:closed,(56,14) +REGION:(05,09,08,10),lit,"food shop" +DOOR:closed,(07,11) +# Gnome homes +DOOR:closed,(04,14) +DOOR:locked,(01,17) +MONSTER: 'G', "gnomish wizard", (02,19) +DOOR:locked,(20,16) +MONSTER: 'G', random, (20,18) +DOOR:random,(21,14) +DOOR:random,(25,14) +DOOR:random,(42,08) +DOOR:locked,(40,05) +MONSTER: 'G', random, (38,07) +DOOR:random,(59,03) +DOOR:random,(58,06) +DOOR:random,(63,03) +DOOR:random,(63,05) +DOOR:locked,(71,03) +DOOR:locked,(71,06) +DOOR:closed,(69,04) +DOOR:closed,(67,16) +MONSTER: 'G', "gnomish wizard", (67,14) +OBJECT: '=', random, (70,14) +DOOR:locked,(69,18) +MONSTER: 'G', "gnome lord", (71,19) +DOOR:locked,(73,18) +OBJECT: '(', "chest", (73,19) +DOOR:locked,(50,06) +OBJECT: '(', random, (50,03) +OBJECT: '`', "statue", (38,15), "gnome king", 1 +# Temple +REGION:(29,02,33,04),lit,"temple" +DOOR:closed,(31,05) +ALTAR:(31,03),align[0],shrine + + +# "Bustling Town" by Kelly Bailey +# +MAZE: "minetn-6",' ' +INIT_MAP:'.','-',true,true,lit,true +GEOMETRY:center,top +MAP +.-----................----------------. +.|...|................|...|..|...|...|. +.|...+..--+--.........|...|..|...|...|. +.|...|..|...|..-----..|...|..|-+---+--. +.-----..|...|--|...|..--+---+-......... +........|...|..|...+.............-----. +........-----..|...|......--+-...|...|. +.----...|...|+------..{...|..|...+...|. +.|..+...|...|.............|..|...|...|. +.|..|...|...|-+-.....---+-------------. +.----...--+--..|..-+-|................. +...|........|..|..|..|----....--------- +...|..T.....----..|..|...+....|......|- +...|-....{........|..|...|....+......|- +...--..-....T.....--------....|......|- +.......--.....................--------- +ENDMAP +REGION:(00,00,38,15),lit,"ordinary" +STAIR:levregion(01,03,20,19),(0,0,38,15),up +STAIR:levregion(21,03,75,19),(0,0,38,15),down +REGION:(13,5,14,6),unlit,"ordinary" +REGION:(9,7,11,9),lit,"candle shop" +REGION:(16,4,18,6),lit,"tool shop" +REGION:(23,1,25,3),lit,"shop" +REGION:(22,12,24,13),lit,"food shop" +REGION:(31,12,36,14),lit,"temple" +ALTAR:(35,13),align[0],shrine + +DOOR:closed,(5,2) +DOOR:locked,(4,8) +DOOR:closed,(10,2) +DOOR:closed,(10,10) +DOOR:locked,(13,7) +DOOR:locked,(14,9) +DOOR:closed,(19,5) +DOOR:closed,(19,10) +DOOR:closed,(24,4) +DOOR:closed,(24,9) +DOOR:closed,(25,12) +DOOR:closed,(28,4) +DOOR:locked,(28,6) +DOOR:closed,(30,13) +DOOR:closed,(31,3) +DOOR:closed,(35,3) +DOOR:closed,(33,7) + +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", (14,6) +MONSTER: 'G', "gnome lord", (14,5) +MONSTER: 'G', "gnome", (27,8) +MONSTER: 'G', "gnome lord", random +MONSTER: 'G', "gnome lord", random +MONSTER: 'h', "dwarf", random +MONSTER: 'h', "dwarf", random +MONSTER: 'h', "dwarf", random +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watch captain", random, peaceful +MONSTER: '@', "watch captain", random, peaceful + + +# "Bazaar Town" by Kelly Bailey +# +LEVEL: "minetn-7" +ROOM: "ordinary" , lit, (3,3), (center,center), (30,15) +NAME: "town" +FOUNTAIN: (12, 07) +FOUNTAIN: (11, 13) + +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watchman", random, peaceful +MONSTER: '@', "watch captain", random, peaceful +MONSTER:'G',"gnome",random +MONSTER:'G',"gnome",random +MONSTER:'G',"gnome",random +MONSTER:'G',"gnome lord",random +MONSTER:'Y',"monkey",random +MONSTER:'Y',"monkey",random + +SUBROOM: "ordinary", random, (2,2), (4,2), "town" +DOOR: false, closed, south, random + +SUBROOM: "ordinary", random, (7,2), (2,2), "town" +DOOR: false, closed, north, random + +SUBROOM: "ordinary", random, (7,5), (2,2), "town" +DOOR: false, closed, south, random + +SUBROOM: "ordinary", lit, (10,2), (3,4), "town" +MONSTER:'G',"gnome",random +MONSTER:'Y',"monkey",random +MONSTER:'Y',"monkey",random +MONSTER:'Y',"monkey",random +DOOR: false, closed, south, random + +SUBROOM: "ordinary", random, (14,2), (4,2), "town" +DOOR: false, closed, south, 0 +MONSTER: 'n', random, random + +SUBROOM: "ordinary", random, (16,5), (2,2), "town" +DOOR: false, closed, south, random + +SUBROOM: "ordinary", unlit, (19,2), (2,2), "town" +DOOR: false, locked, east, random +MONSTER: 'G',"gnome king",random + +SUBROOM: "food shop", lit, (19,5), (2,3), "town" +CHANCE: 50 +DOOR: false, closed, south, random + +SUBROOM: "ordinary", random, (2,7), (2,2), "town" +DOOR: false, closed, east, random + +SUBROOM: "tool shop", lit, (2,10), (2,3), "town" +CHANCE: 50 +DOOR: false, closed, south, random + +SUBROOM: "candle shop", lit, (5,10),(3,3), "town" +DOOR: false, closed, north, random + +SUBROOM: "ordinary", random, (11,10), (2,2), "town" +DOOR: false, locked, west, random +MONSTER: 'G',random,random + +SUBROOM: "shop", lit, (14,10), (2,3), "town" +CHANCE: 60 +DOOR: false, closed, north, random + +SUBROOM: "ordinary", random, (17,11), (4,2), "town" +DOOR: false, closed, north, random + +SUBROOM: "ordinary", random, (22,11), (2,2), "town" +DOOR: false, closed, south, random +SINK: (00,00) + +SUBROOM: "food shop", lit, (25,11), (3,2), "town" +CHANCE: 50 +DOOR: false, closed, east, random + +SUBROOM: "tool shop", lit, (25,2), (3,3), "town" +CHANCE: 30 +DOOR: false, closed, west, random + +SUBROOM: "temple", lit, (24,6), (4,4), "town" +DOOR: false, closed, west, random +ALTAR:(02,01),align[0],shrine +MONSTER: 'G', "gnomish wizard", random +MONSTER: 'G', "gnomish wizard", random + +ROOM: "ordinary" , random, random, random, random +STAIR: random, up + +ROOM: "ordinary" , random, random, random, random +STAIR: random, down +TRAP: random, random +MONSTER: 'G', "gnome", random +MONSTER: 'G', "gnome", random + +ROOM: "ordinary" , random, random, random, random +MONSTER: 'h', "dwarf", random + +ROOM: "ordinary" , random, random, random, random +TRAP: random, random +MONSTER: 'G', "gnome", random + +RANDOM_CORRIDORS + + +# Mine end level variant 1 +# "Mimic of the Mines" +# +MAZE: "minend-1", ' ' +GEOMETRY:center,center +#1234567890123456789012345678901234567890123456789012345678901234567890 +MAP +------------------------------------------------------------------ ------ +| |.......| |.......-...| |.....|. | +| --------- ----.......-------...........| ---...-S- | +| |.......| |..........................-S- --.......| | +| |......------- ---........................|. |.......-- | +| |..--........-----..........................|. -.-..---- | +| --..--.-----........-.....................--- --..-- | +| --..--..| -----------..................---.----------..-- | +| |...--.| |..S...S..............---................-- | +| ----..----- ------------........--- ------------...--- | +| |.........-- ---------- ---...-- ----- | +| --.....---..-- -------- --...---...-- | +| ----..-..-- --..--------------------- --......-- ---........| | +|--....----- --..-..................--- |........| |.......-- | +|.......| --......................S.. --......-- ---..---- | +|--.--.-- ----.................--- ------..------...-- | +| |....S.. |...............-..| ..S...........| | +-------- -------------------- ------------------------ +ENDMAP +# Dungeon Description +RANDOM_PLACES:(08,16),(13,07),(21,08),(41,14),(50,04),(50,16),(66,01) +REGION:(26,01,32,01),unlit,"ordinary",filled,true +REGION:(20,08,21,08),unlit,"ordinary" +REGION:(23,08,25,08),unlit,"ordinary" +# Secret doors +DOOR:locked,(07,16) +DOOR:locked,(22,08) +DOOR:locked,(26,08) +DOOR:locked,(40,14) +DOOR:locked,(50,03) +DOOR:locked,(51,16) +DOOR:locked,(66,02) +# Stairs +STAIR:(36,04),up +# Non diggable walls +NON_DIGGABLE:(00,00,74,17) +# Niches +# Note: place[6] empty +OBJECT:'*',"diamond",place[0] +OBJECT:'*',"emerald",place[0] +OBJECT:'*',"worthless piece of violet glass",place[0] +MONSTER:'m',random,place[0], m_object "luckstone" +OBJECT:'*',"worthless piece of white glass",place[1] +OBJECT:'*',"emerald",place[1] +OBJECT:'*',"amethyst",place[1] +MONSTER:'m',random,place[1], m_object "loadstone" +OBJECT:'*',"diamond",place[2] +OBJECT:'*',"worthless piece of green glass",place[2] +OBJECT:'*',"amethyst",place[2] +MONSTER:'m',random,place[2], m_object "flint" +OBJECT:'*',"worthless piece of white glass",place[3] +OBJECT:'*',"emerald",place[3] +OBJECT:'*',"worthless piece of violet glass",place[3] +MONSTER:'m',random,place[3], m_object "touchstone" +OBJECT:'*',"worthless piece of red glass",place[4] +OBJECT:'*',"ruby",place[4] +OBJECT:'*',"loadstone",place[4] +OBJECT:'*',"ruby",place[5] +OBJECT:'*',"worthless piece of red glass",place[5] +OBJECT:'*',"luckstone",place[5] +# Random objects +OBJECT:'*',random,random +OBJECT:'*',random,random +OBJECT:'*',random,random +OBJECT:'*',random,random +OBJECT:'*',random,random +OBJECT:'*',random,random +OBJECT:'*',random,random +OBJECT:'(',random,random +OBJECT:'(',random,random +OBJECT:random,random,random +OBJECT:random,random,random +OBJECT:random,random,random +# Random traps +TRAP:random,random +TRAP:random,random +TRAP:random,random +TRAP:random,random +TRAP:random,random +TRAP:random,random +# Random monsters +MONSTER:'G',"gnome king",random +MONSTER:'G',"gnome lord",random +MONSTER:'G',"gnome lord",random +MONSTER:'G',"gnome lord",random +MONSTER:'G',"gnomish wizard",random +MONSTER:'G',"gnomish wizard",random +MONSTER:'G',"gnome",random +MONSTER:'G',"gnome",random +MONSTER:'G',"gnome",random +MONSTER:'G',"gnome",random +MONSTER:'G',"gnome",random +MONSTER:'G',"gnome",random +MONSTER:'G',"gnome",random +MONSTER:'G',"gnome",random +MONSTER:'G',"gnome",random +MONSTER:'h',"hobbit",random +MONSTER:'h',"hobbit",random +MONSTER:'h',"dwarf",random +MONSTER:'h',"dwarf",random +MONSTER:'h',"dwarf",random +MONSTER:'h',random,random + + +# Mine end level variant 2 +# "Gnome King's Wine Cellar" +# MAZE: "minend-2", ' ' GEOMETRY:center,center MAP @@ -284,7 +808,7 @@ MAP |.|---|..|--|.......|----------------------------|..|..... | |...........|----.--|......................| |..|....... | |-----------|...|.| |------------------|.|.|-----|..|.....|.. | -|-----------|...|.|--------------------|.|..........|.....|.... | +|-----------|.{.|.|--------------------|.|..........|.....|.... | |...............|.S......................|-------------..-----... | |.--------------|.|--------------------|.|......................... | |.................| |.....................|........ | @@ -383,45 +907,102 @@ MONSTER:'h',"dwarf",random MONSTER:'h',"dwarf",random MONSTER:'h',random,random -# -# The "fill" level for the mines. -# -# This level is used to fill out any levels not occupied by specific -# levels as defined above. -# -MAZE: "minefill" , ' ' -INIT_MAP: '.' , ' ' , true , true , random , true -NOMAP -# -STAIR: random, up -STAIR: random, down -# -OBJECT: '*', random, random -OBJECT: '*', random, random -OBJECT: '*', random, random -OBJECT: '(', random, random -OBJECT: random, random, random -OBJECT: random, random, random -OBJECT: random, random, random -# -MONSTER: 'G', "gnome", random -MONSTER: 'G', "gnome", random -MONSTER: 'G', "gnome", random -MONSTER: 'G', "gnome", random -MONSTER: 'G', "gnome", random -MONSTER: 'G', "gnome", random -MONSTER: 'G', "gnome", random -MONSTER: 'G', "gnome lord", random -MONSTER: 'h', "dwarf", random -MONSTER: 'h', "dwarf", random -MONSTER: 'G', random, random -MONSTER: 'G', random, random -MONSTER: 'h', random, random +# "Catacombs" by Kelly Bailey +# Relies on some very specific behavior of MAZEWALK. # -TRAP: random, random -TRAP: random, random -TRAP: random, random -TRAP: random, random -TRAP: random, random -TRAP: random, random +MAZE:"minend-3",'-' +FLAGS:nommap +GEOMETRY:center,bottom +MAP + - - - - - - - - - - -- -- - - . - - - - - - - - - -- - - -- - - - - . - - | +------...---------.-----------...-----.-------.------- ----------------| + - - - - - - - - - - - . - - - . - - - - - - - - - - -- - -- - . - - - - - | +------------.---------...-------------------------.--- ------------------| + - - - - - - - - - - . . - - --- - . - - - - - - - - -- -- - - - - |.....| | +--.---------------.......------------------------------- ----------|.....S-| + - - - - |.. ..| - ....... . - - - - |.........| - - - --- - - - - |.....| | +----.----|.....|------.......--------|.........|--------------.------------| + - - - - |..{..| - - -.... . --- - -.S.........S - - - - - - - - - - - - - | +---------|.....|--.---...------------|.........|---------------------------| + - - - - |.. ..| - - - . - - - - - - |.........| - --- . - - - - - - - - - | +----------------------...-------.---------------------...------------------| +---..| - - - - - - - - . --- - - - - - - - - - - - - - . - - --- - - --- - | +-.S..|----.-------.------- ---------.-----------------...----- -----.------- +---..| - - - - - - - -- - - -- . - - - - - . - - - . - . - - -- -- - - - -- +-.S..|--------.---.--- -...---------------...{.--------- --------- +--|. - - - - - - - -- - - - -- . - - - --- - - - . . - - - - -- - - - - - - +ENDMAP +RANDOM_PLACES:(1,15),(68,6),(1,13) +NON_DIGGABLE:(67,3,73,7) +NON_DIGGABLE:(0,14,2,16) +REGION:(0,0,75,16),unlit,"ordinary" +REGION:(38,6,46,10),lit,"ordinary" +DOOR:closed,(37,8) +DOOR:closed,(47,8) +DOOR:closed,(73,5) +DOOR:closed,(2,15) +MAZEWALK:(36,8),west +STAIR:(42,8),up + +# Objects +OBJECT:'*',"diamond",random +OBJECT:'*',random,random +OBJECT:'*',"diamond",random +OBJECT:'*',random,random +OBJECT:'*',"emerald",random +OBJECT:'*',random,random +OBJECT:'*',"emerald",random +OBJECT:'*',random,random +OBJECT:'*',"emerald",random +OBJECT:'*',random,random +OBJECT:'*',"ruby",random +OBJECT:'*',random,random +OBJECT:'*',"ruby",random +OBJECT:'*',"amethyst",random +OBJECT:'*',random,random +OBJECT:'*',"amethyst",random +OBJECT:'*',"luckstone",place[0] +OBJECT:'*',"flint",place[1] +OBJECT:'?',random,random +OBJECT:'?',random,random +OBJECT:'?',random,random +OBJECT:'?',random,random +OBJECT:'?',random,random +OBJECT:'+',random,random +OBJECT:'+',random,random +OBJECT:'+',random,random +OBJECT:'+',random,random +OBJECT:random,random,random +OBJECT:random,random,random +OBJECT:random,random,random +TRAP:random,random +TRAP:random,random +TRAP:random,random +TRAP:random,random +TRAP:random,random +TRAP:random,random +TRAP:random,random +# One-time annoyance factor +TRAP:"level teleport",place[0] +TRAP:"level teleport",place[1] +MONSTER:'M',random,random +MONSTER:'M',random,random +MONSTER:'M',random,random +MONSTER:'M',random,random +MONSTER:'M',random,random +MONSTER:'M',"ettin mummy",random +MONSTER:'V',random,random +MONSTER:'Z',random,random +MONSTER:'Z',random,random +MONSTER:'Z',random,random +MONSTER:'Z',random,random +MONSTER:'Z',random,random +MONSTER:'V',random,random +MONSTER:'e',random,random +MONSTER:'e',random,random +MONSTER:'e',random,random +MONSTER:'e',random,random + + +# end mines.des diff --git a/dat/opthelp b/dat/opthelp index d1fbe3a..c287b11 100644 --- a/dat/opthelp +++ b/dat/opthelp @@ -2,6 +2,7 @@ Boolean options not under specific compile flags (with default values in []): (You can learn which options exist in your version by checking your current option setting, which is reached via the 'O' cmd.) +autodig dig if moving and wielding digging tool [FALSE] autopickup automatically pick up objects you move over [TRUE] autoquiver when firing with an empty quiver, select some suitable inventory weapon to fill the quiver [FALSE] @@ -33,6 +34,8 @@ sortpack group similar kinds of objects in inventory [TRUE] sound enable messages about what your character hears [TRUE] (note: this has nothing to do with your computer's audio capabilities, and the game resets it periodically) +sparkle display sparkly effect for resisted magical [TRUE] + attacks (e.g. fire attack on fire-resistant monster) standout use standout mode for --More-- on messages [FALSE] time display elapsed game time, in moves [FALSE] tombstone print tombstone when you die [TRUE] @@ -69,6 +72,9 @@ timed_delay on unix and VMS, use a timer instead of sending display effect. on MSDOS without the termcap lib, whether or not to pause for visual effect. [TRUE] +Boolean option if TTY_GRAPHICS was set at compile time: +msg_window show previous messages in a screen-size window [FALSE] + Boolean option if USE_TILES was set at compile time (MSDOS protected mode only): preload_tiles control whether tiles get pre-loaded into RAM at the start of the game. Doing so enhances performance @@ -81,6 +87,7 @@ Compound options are written as option_name:option_value. Compound options which can be set during the game are: +boulder override the default boulder symbol with another default:` disclose the types of information you want offered at the end of the game [all] fruit the name of a fruit you enjoy eating [slime mold] @@ -177,7 +184,7 @@ name the name of your character [obtained by asking the system or objects like dungeon, but for object symbols default: ])[="(%!?+/$*`0_. pettype your preferred type of pet (cat or dog), if your character - class uses both types [RANDOM] + class uses both types; or none for no pet [RANDOM] race Your starting race (e.g., race:Human, race:Elf). [RANDOM] role Your starting role (e.g., role:Barbarian, role:Valk). Although you can specify just the first letter(s), it will diff --git a/dat/oracle.des b/dat/oracle.des index 3aaa00f..0e8f176 100644 --- a/dat/oracle.des +++ b/dat/oracle.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)oracle.des 3.3 95/10/07 +# SCCS Id: @(#)oracle.des 3.4 1995/10/07 # NetHack may be freely redistributed. See license for details. # # Oracle level diff --git a/dat/quest.txt b/dat/quest.txt index f8ba9aa..2a37b69 100644 --- a/dat/quest.txt +++ b/dat/quest.txt @@ -1,8 +1,8 @@ -# SCCS Id: @(#)quest.txt 3.3 2000/01/31 +# SCCS Id: @(#)quest.txt 3.4 2002/01/30 # Copyright (c) 1991 by M. Stephenson # NetHack may be freely redistributed. See license for details. # -# The quest text file for NetHack 3.3 +# The quest text file for NetHack 3.4 # # These are the "standard" message numbers from qtext.h. All class # dialogue must have at least these entries. @@ -11,20 +11,21 @@ # QT_NEXTTIME 2 # QT_OTHERTIME 3 # -# QT_GUARDTALK 5 /* 5 random things for guards to say */ +# QT_GUARDTALK 5 /* 5 random things guards say before quest */ +# QT_GUARDTALK2 10 /* 5 random things guards say after quest */ # -# QT_FIRSTLEADER 10 -# QT_NEXTLEADER 11 -# QT_OTHERLEADER 12 -# QT_LASTLEADER 13 -# QT_BADLEVEL 14 -# QT_BADALIGN 15 -# QT_ASSIGNQUEST 16 +# QT_FIRSTLEADER 15 +# QT_NEXTLEADER 16 +# QT_OTHERLEADER 17 +# QT_LASTLEADER 18 +# QT_BADLEVEL 19 +# QT_BADALIGN 20 +# QT_ASSIGNQUEST 21 # -# QT_ENCOURAGE 20 /* 1-10 random encouragement messages */ +# QT_ENCOURAGE 25 /* 1-10 random encouragement messages */ # -# QT_FIRSTLOCATE 30 -# QT_NEXTLOCATE 31 +# QT_FIRSTLOCATE 35 +# QT_NEXTLOCATE 36 # # QT_FIRSTACQUIRE 40 # QT_NEXTACQUIRE 41 @@ -81,39 +82,54 @@ You have an odd feeling this may be the last time you ever come here. %Cp Arc 00009 "So you're %ls prize pupil! I don't know what he sees in you." %E -%Cc Arc 00010 +%Cp Arc 00010 +"Did you see Lash LaRue in 'Song of Old Wyoming' the other night?" +%E +%Cp Arc 00011 +"Hey man, got any potions of hallucination for sale?" +%E +%Cp Arc 00012 +"I guess you are guaranteed to make full professor now." +%E +%Cp Arc 00013 +"So, what was worse, %n or your entrance exams?" +%E +%Cp Arc 00014 +"%oC is impressive, but nothing like the bones I dug up!" +%E +%Cc Arc 00015 "Finally you have returned, %p. You were always my most promising student. Allow me to see if you are ready for the most difficult task of your career." %E -%Cp Arc 00011 +%Cp Arc 00016 "Again, %p, you stand before me. Let me see if you have gained experience in the interim." %E -%Cp Arc 00012 +%Cp Arc 00017 "Once more, %p, you have returned from the field. Are you finally ready for the task that must be accomplished?" %E -%Cc Arc 00013 +%Cc Arc 00018 "%p, you have failed us. All of my careful training has been in vain. Begone! Your tenure at this college has been revoked! "You are a disgrace to the profession!" %E -%Cc Arc 00014 +%Cc Arc 00019 "%p, you are yet too inexperienced to undertake such a demanding quest. A mere %r could not possibly face the rigors demanded and survive. Go forth, and come here again when your adventures have further taught you." %E -%Cc Arc 00015 +%Cc Arc 00020 "%pC! I've heard that you've been using sloppy techniques. Your results lately can hardly be called suitable for %ra! "How could you have strayed from the %a path? Go from here, and come back only when you have purified yourself." %E -%Cc Arc 00016 +%Cc Arc 00021 "Grave times have befallen the college, for %na has stolen %o. Without it, the board of directors of the university will soon have no choice but to revoke our research grants. @@ -121,7 +137,7 @@ the university will soon have no choice but to revoke our research grants. "You must locate the entrance to %i. Within it, you will find %n. -"You must the defeat %n and return %o +"You must then defeat %n and return %o to me. "Only in this way will we be able to prevent the budget cuts that could @@ -129,45 +145,45 @@ close this college. "May the wisdom of %d be your guide." %E -%Cp Arc 00020 +%Cp Arc 00025 "Beware, for %n is powerful and cunning." %E -%Cp Arc 00021 +%Cp Arc 00026 "To locate the entrance to %i, you must pass many traps." %E -%Cp Arc 00022 +%Cp Arc 00027 "A %nt may be vulnerable to attacks by magical cold." %E -%Cp Arc 00023 +%Cp Arc 00028 "Call upon %d when you encounter %n." %E -%Cp Arc 00024 +%Cp Arc 00029 "You must destroy %n. It will pursue you otherwise." %E -%Cp Arc 00025 +%Cp Arc 00030 "%oC is a mighty talisman. With it you can destroy %n." %E -%Cp Arc 00026 +%Cp Arc 00031 "Go forth with the blessings of %d." %E -%Cp Arc 00027 +%Cp Arc 00032 "I will have my %gP watch for your return." %E -%Cp Arc 00028 +%Cp Arc 00033 "Remember not to stray from the true %a path." %E -%Cp Arc 00029 +%Cp Arc 00034 "You may be able to sense %o when you are near." %E -%Cc Arc 00030 +%Cc Arc 00035 A plain opens before you. Beyond the plain lies a foreboding edifice. You have the feeling that you will soon find the entrance to %i. %E -%Cp Arc 00031 +%Cp Arc 00036 Once again, you are near the entrance to %i. %E %Cc Arc 00040 @@ -278,7 +294,7 @@ Amulet on that altar to fulfill your destiny. # %Cc Bar 00001 Warily you scan your surroundings, all of your senses alert for signs -of possible danger. Off in the distance, you can see the familiar shapes +of possible danger. Off in the distance, you can %x the familiar shapes of %H. But why, you think, should %l be there? @@ -313,19 +329,34 @@ Again, and you think possibly for the last time, you approach %Cp Bar 00009 "%lC is a strange one, but he has helped defend us." %E -%Cc Bar 00010 +%Cp Bar 00010 +"The battles here have been good -- our enemies' blood soaks the soil!" +%E +%Cp Bar 00011 +"Remember that glory is crushing your enemies beneath your feet!" +%E +%Cp Bar 00012 +"Times will be good again, now that the horde is vanquished." +%E +%Cp Bar 00013 +"You have brought our clan much honor in defeating %n." +%E +%Cp Bar 00014 +"You will be a worthy successor to %l." +%E +%Cc Bar 00015 "Ah, %p. You have returned at last. The world is in dire need of your help. There is a great quest you must undertake. "But first, I must see if you are ready to take on such a challenge." %E -%Cp Bar 00011 +%Cp Bar 00016 "%p, you are back. Are you ready now for the challenge?" %E -%Cp Bar 00012 +%Cp Bar 00017 "Again, you stand before me, %p. Surely you have prepared yourself." %E -%Cc Bar 00013 +%Cc Bar 00018 "Pah! You have betrayed the gods, %p. You will never attain the glory which you aspire to. Your failure to follow the true path has closed this future to you. @@ -333,18 +364,18 @@ closed this future to you. "I will protect these people as best I can, but soon %n will overcome me and destroy all who once called you %s. Now begone!" %E -%Cc Bar 00014 +%Cc Bar 00019 "%p, I fear that you are as yet too inexperienced to face %n. Only %Ra with the help of %d could ever hope to defeat him." %E -%Cc Bar 00015 +%Cc Bar 00020 "%pC! You have wandered from the path of the %a! If you attempt to overcome %n in this state, he will surely enslave your soul. Your only hope, and ours, lies in your purification. Go forth, and return when you feel ready." %E -%Cc Bar 00016 +%Cc Bar 00021 "The world is in great need of your assistance, %p. "About six months ago, I learned that a mysterious sorcerer, known @@ -369,44 +400,44 @@ and with %d behind you, you alone can defeat %n. %n, defeat him, and return %o to us. Only then will the world be safe." %E -%Cp Bar 00020 +%Cp Bar 00025 "%nC is strong in the dark arts, but not immune to cold steel." %E -%Cp Bar 00021 +%Cp Bar 00026 "Remember that %n is a great sorcerer. He lived in the time of Atlantis." %E -%Cp Bar 00022 +%Cp Bar 00027 "If you fail, %p, I will not be able to protect these people long." %E -%Cp Bar 00023 +%Cp Bar 00028 "To enter %i, you must be very stealthy. The horde will be on guard." %E -%Cp Bar 00024 +%Cp Bar 00029 "Call upon %d in your time of need." %E -%Cp Bar 00025 +%Cp Bar 00030 "May %d protect you, and guide your steps." %E -%Cp Bar 00026 +%Cp Bar 00031 "If you can lay hands upon %o, carry it for good fortune." %E -%Cp Bar 00027 +%Cp Bar 00032 "I cannot stand against %ns sorcery. But %d will help you." %E -%Cp Bar 00028 +%Cp Bar 00033 "Do not fear %n. I know you can defeat him." %E -%Cp Bar 00029 +%Cp Bar 00034 "You have a great road to travel, %p, but only after you defeat %n." %E -%Cc Bar 00030 +%Cc Bar 00035 The scent of water comes to you in the desert breeze. You know that you have located %i. %E -%Cp Bar 00031 +%Cp Bar 00036 Yet again you have a chance to infiltrate %i. %E %Cc Bar 00040 @@ -558,7 +589,22 @@ off our access to the outer world." %Cp Cav 00009 "%lC grows old. We know not who will guide us after he ascends." %E -%Cc Cav 00010 +%Cp Cav 00010 +"The rains have returned and the land grows lush again." +%E +%Cp Cav 00011 +"Peace has returned, give thanks to %d!" +%E +%Cp Cav 00012 +"Welcome back! Did you find %o?" +%E +%Cp Cav 00013 +"So, %p, tell us the story of your fight with %n." +%E +%Cp Cav 00014 +"%lC grows old. Perhaps you will guide us after he ascends." +%E +%Cc Cav 00015 "You have returned from your vision quest, %p. Thank %d. "We are in dire need of your help, my %S. @@ -566,13 +612,13 @@ off our access to the outer world." "But first, I must see if you are yet capable of the quest I would ask you to undertake." %E -%Cp Cav 00011 +%Cp Cav 00016 "Again, you return to us, %p. Let me see if you are ready now." %E -%Cp Cav 00012 +%Cp Cav 00017 "Ah, %p. Are you finally ready?" %E -%Cc Cav 00013 +%Cc Cav 00018 "%pC! You have sealed our fate. You seem unable to reform yourself, so I must select another to take your place. @@ -581,7 +627,7 @@ the path of the %C over the true path of the %L. "You no longer live in our eyes." %E -%Cc Cav 00014 +%Cc Cav 00019 "Alas, %p, you are as yet too inexperienced to embark upon such a difficult quest as that I propose to give you. @@ -591,13 +637,13 @@ a difficult quest as that I propose to give you. "Adventure some more, and you will learn the skills you will require. %d decrees it." %E -%Cc Cav 00015 +%Cc Cav 00020 "%pC! You have deviated from my teachings. You no longer follow the path of the %a as you should. I banish you from these caves, to go forth and purify yourself. Then, you might be able to accomplish this quest." %E -%Cc Cav 00016 +%Cc Cav 00021 "You are indeed ready now, %p. I shall tell you a tale of great suffering among your people: @@ -617,41 +663,41 @@ we can make our caves safe once more. "Please, %p, recover %o for us, and return it here." %E -%Cp Cav 00020 +%Cp Cav 00025 "%nC is immune to her own breath weapons. You should use magic upon her that she does not use herself." %E -%Cp Cav 00021 +%Cp Cav 00026 "When you encounter %n, call upon %d for assistance." %E -%Cp Cav 00022 +%Cp Cav 00027 "There will be nowhere to hide inside %ns inner sanctum." %E -%Cp Cav 00023 +%Cp Cav 00028 "Your best chance with %n will be to keep moving." %E -%Cp Cav 00024 +%Cp Cav 00029 "Do not be distracted by the great treasures in %ns lair. Concentrate on %o." %E -%Cp Cav 00025 +%Cp Cav 00030 "%oC is the only object that %n truly fears." %E -%Cp Cav 00026 +%Cp Cav 00031 "Do not be fooled by %ns size. She is fast, and it is rumored that she uses magic." %E -%Cp Cav 00027 +%Cp Cav 00032 "I would send a party of %gP with you, but we will need all of our strength to defend ourselves." %E -%Cp Cav 00028 +%Cp Cav 00033 "Remember, be %a at all times. This is your strength." %E -%Cp Cav 00029 +%Cp Cav 00034 "If only we had an amulet of reflection, this would not have happened." %E -%Cc Cav 00030 +%Cc Cav 00035 You %x many large claw marks on the ground. The tunnels ahead of you are larger than most of those in any cave complex you have ever been in before. @@ -659,7 +705,7 @@ ever been in before. Your nose detects the smell of carrion from within, and bones litter the sides of the tunnels. %E -%Cp Cav 00031 +%Cp Cav 00036 Once again, you approach %i. %E %Cc Cav 00040 @@ -805,7 +851,23 @@ to be %Ra to know that %n is on the verge of victory. "We think %n has used his alchemists, and %o, to unleash a new disease we call 'the cold' on Gehennom." %E -%Cc Hea 00010 +%Cp Hea 00010 +"Did you read that new treatise on the therapeutic use of leeches?" +%E +%Cp Hea 00011 +"Paint a red caduceus on your shield and monsters won't hit you." +%E +%Cp Hea 00012 +"How are you feeling? Perhaps a good bleeding will improve your sprits." +%E +%Cp Hea 00013 +"Have you heard the absurd new theory that diseases are caused by +microscopic organisms, and not ill humors?" +%E +%Cp Hea 00014 +"I see that you bring %o, now you can cure this plague!" +%E +%Cc Hea 00015 "Feebly, %l raises his head to look at you. "It is good to see you again, %p. I see the concern in your @@ -816,24 +878,24 @@ I need your fresh strength to carry on our work. "Come closer and let me lay hands on you, and determine if you have the skills necessary to accomplish this mission." %E -%Cp Hea 00011 +%Cp Hea 00016 "Again you return to me, %p. I sense that each trip back the pleurisy and maladies of our land begin to infect you. Let us hope and pray to %d that you become ready for your task before you fall victim to the bad humors." %E -%Cp Hea 00012 +%Cp Hea 00017 "Chiron has fallen, Hermes has fallen, what else must I tell you to impress upon you the importance of your mission! I hope that you have come prepared this time." %E -%Cc Hea 00013 +%Cc Hea 00018 "You have failed us, %p. You are a quack! A charlatan! "Hades will be happy to hear that you are once again practicing your arts on the unsuspecting." %E -%Cc Hea 00014 +%Cc Hea 00019 "Alas, %p, you are yet too inexperienced to deal with the rigors of such a task. You must be able to draw on the knowledge of botany, vetenary, and alchemy before I can send you on this quest with good @@ -841,14 +903,14 @@ conscience. "Return when you wear %Ra's caduceus." %E -%Cc Hea 00015 +%Cc Hea 00020 "You have learned much of the remedies that benefit, but you must also know which physic for which ail. That is why %ds teachings are a part of your training. "Return to us when you have healed thyself." %E -%Cc Hea 00016 +%Cc Hea 00021 For the first time, you sense a smile on %ls face. You have indeed learned as much as we can teach you in preparation @@ -867,46 +929,46 @@ For the first time, you sense a smile on %ls face. You must travel into the swamps to %i, and from there follow the trail to %ns island lair. Be careful. %E -%Cp Hea 00020 +%Cp Hea 00025 "Remember, %p, to always wash your hands before operating." %E -%Cp Hea 00021 +%Cp Hea 00026 "%nC has no real magic of his own. To this he is vulnerable." %E -%Cp Hea 00022 +%Cp Hea 00027 "If you have been true to %d, you can draw on the power of %o." %E -%Cp Hea 00023 +%Cp Hea 00028 "Bring with you antidotes for poisons." %E -%Cp Hea 00024 +%Cp Hea 00029 "Remember this, %n can twist the powers of %o to hurt instead of heal." %E -%Cp Hea 00025 +%Cp Hea 00030 "I have sent for Chiron, but I am afraid he will come too late." %E -%Cp Hea 00026 +%Cp Hea 00031 "Maybe when you return the snakes will once again begin to shed." %E -%Cp Hea 00027 +%Cp Hea 00032 "The plague grows worse as we speak. Hurry, %p!" %E -%Cp Hea 00028 +%Cp Hea 00033 "Many times %n has caused trouble in these lands. It is time that he was eradicated like the diseases he has caused." %E -%Cp Hea 00029 +%Cp Hea 00034 "With but one eye, %n should be easy to blind. Remember this." %E -%Cc Hea 00030 +%Cc Hea 00035 You stand before the entrance to %i. Strange scratching noises come from within the building. The swampy ground around you seems to stink with disease. %E -%Cp Hea 00031 +%Cp Hea 00036 Once again you stand at the entrance to %i. %E %Cc Hea 00040 @@ -1049,24 +1111,40 @@ near %i." %Cp Kni 00009 "Many brave %cP died when %n attacked." %E -%Cc Kni 00010 +%Cp Kni 00010 +"Hail, %p! Verily, thou lookest well." +%E +%Cp Kni 00011 +"So, %p, didst thou find %n in the fens +near %i?" +%E +%Cp Kni 00012 +"Worthy %p, hast thou proven thy right purpose on the body of %n?" +%E +%Cp Kni 00013 +"Verily, %l could have no better champion, %p." +%E +%Cp Kni 00014 +"Hast thou indeed recovered %o?" +%E +%Cc Kni 00015 "Ah, %p. We see thou hast received our summons. We are in dire need of thy prowess. But first, We must needs decide if thou art ready for this great undertaking." %E -%Cp Kni 00011 +%Cp Kni 00016 "Welcome again, %p. We hope thou art ready now." %E -%Cp Kni 00012 +%Cp Kni 00017 "Once again, thou standest before us, %p. Art thou ready now?" %E -%Cc Kni 00013 +%Cc Kni 00018 "Thou disgracest this noble court with thine impure presence. We have been lenient with thee, but no more. Thy name shall be spoken no more. We hereby strip thee of thy title, thy lands, and thy standing as %ca. Begone from our sight!" %E -%Cc Kni 00014 +%Cc Kni 00019 "Verily, %p, thou hast done well. That thou hast survived thus far is a credit to thy valor, but thou art yet unprepared for the demands required as Our Champion. %rA, no matter how @@ -1075,12 +1153,12 @@ pure, could never hope to defeat the foul %n. "Journey forth from this place, and hone thy skills. Return to Our presence when thou hast attained the noble title of %R." %E -%Cc Kni 00015 +%Cc Kni 00020 "Thou dishonourest us, %p! Thou hast strayed from the path of chivalry! Go from our presence and do penance. Only when thou art again pure mayst thou return hence." %E -%Cc Kni 00016 +%Cc Kni 00021 "Ah, %p. Thou art truly ready, as no %c before thee hath been. Hear now Our words: @@ -1102,44 +1180,44 @@ Merlin will not regain his health. beast, and return to Us %o. Only then can We restore Merlin to health." %E -%Cp Kni 00020 +%Cp Kni 00025 "Remember, %p, follow always the path of %d." %E -%Cp Kni 00021 +%Cp Kni 00026 "Though %n is verily a mighty foe, we have confidence in thy victory." %E -%Cp Kni 00022 +%Cp Kni 00027 "Beware, for %n hath surrounded himself with hordes of foul creatures." %E -%Cp Kni 00023 +%Cp Kni 00028 "Great treasure, 'tis said, is hoarded in the lair of %n." %E -%Cp Kni 00024 +%Cp Kni 00029 "If thou possessest %o, %p, %ns magic shall therewith be thwarted." %E -%Cp Kni 00025 +%Cp Kni 00030 "The gates of %i are guarded by forces unseen, %p. Go carefully." %E -%Cp Kni 00026 +%Cp Kni 00031 "Return %o to us quickly, %p." %E -%Cp Kni 00027 +%Cp Kni 00032 "Destroy %n, %p, else %H shall surely fall." %E -%Cp Kni 00028 +%Cp Kni 00033 "Call upon %d when thou art in need." %E -%Cp Kni 00029 +%Cp Kni 00034 "To find %i, thou must keep thy heart pure." %E -%Cc Kni 00030 +%Cc Kni 00035 You stand at the foot of %i. Atop, you can %x a shrine. Strange energies seem to be focused here, and the hair on the back of your neck stands on end. %E -%Cp Kni 00031 +%Cp Kni 00036 Again, you stand at the foot of %i. %E %Cc Kni 00040 @@ -1280,30 +1358,45 @@ the final time you come here. %Cp Mon 00009 "May %d be with you, %s." %E -%Cc Mon 00010 +%Cp Mon 00010 +"Greetings, honorable %r. It is good to see you again." +%E +%Cp Mon 00011 +"Ah, %p! Our deepest gratitude for all of your help." +%E +%Cp Mon 00012 +"Greetings, %s. Perhaps you will take some time to meditate with us?" +%E +%Cp Mon 00013 +"With this test behind you, may %d bring you enlightenment." +%E +%Cp Mon 00014 +"May %d be with you, %s." +%E +%Cc Mon 00015 "Ah, %p, my %S. You have returned to us at last. A great blow has befallen our order; perhaps you can help us. First, however, I must determine if you are prepared for this great challenge." %E -%Cp Mon 00011 +%Cp Mon 00016 "Again, my %S, you stand before me. Are you ready now to help us?" %E -%Cp Mon 00012 +%Cp Mon 00017 "Once more, %p, you stand within the sanctum. Are you ready now?" %E -%Cc Mon 00013 +%Cc Mon 00018 "You are a heretic, %p! How can you, %ra, deviate so from the teachings of %d? Begone from this temple. You are no longer %sa to this order. We will pray to %d for other assistance, as you have failed us utterly." %E -%Cc Mon 00014 +%Cc Mon 00019 "Alas, %p, it is not yet to be. A mere %r could never withstand the might of %n. Go forth, again into the world, and return when you have attained the post of %R." %E -%Cc Mon 00015 +%Cc Mon 00020 "This is terrible, %p. You have deviated from the true path! You know that %d requires the most strident devotion of this order. The %shood must stand for utmost piety. @@ -1311,7 +1404,7 @@ order. The %shood must stand for utmost piety. "Go from here, atone for your sins against %d. Return only when you have purified yourself." %E -%Cc Mon 00016 +%Cc Mon 00021 "Yes, %p. You are truly ready now. Attend to me and I shall tell you of what has transpired: @@ -1329,42 +1422,42 @@ legions of elementals that slay our students. "Go with %d as your guide, %p." %E -%Cp Mon 00020 +%Cp Mon 00025 "You can prevail, if you rely on %d." %E -%Cp Mon 00021 +%Cp Mon 00026 "Remember that %n has great magic at his command." %E -%Cp Mon 00022 +%Cp Mon 00027 "Be pure, my %S." %E -%Cp Mon 00023 +%Cp Mon 00028 "Beware, %i is surrounded by hordes of earth elementals." %E -%Cp Mon 00024 +%Cp Mon 00029 "Remember your studies, and you will prevail!" %E -%Cp Mon 00025 +%Cp Mon 00030 "Acquire and wear %o if you can. They will aid you against %n." %E -%Cp Mon 00026 +%Cp Mon 00031 "Call upon %d when your need is greatest. You will be answered." %E -%Cp Mon 00027 +%Cp Mon 00032 "Remember that use the elementals' strength against them!" %E -%Cp Mon 00028 +%Cp Mon 00033 "Do not lose faith, %p. If you do so, %n will grow stronger." %E -%Cp Mon 00029 +%Cp Mon 00034 "Wear %o. They will assist you in your efforts." %E -%Cc Mon 00030 +%Cc Mon 00035 You remember the descriptions of %i, given to you by the %l. It is ahead that you will find %n's trail. %E -%Cp Mon 00031 +%Cp Mon 00036 Again, you stand before %i. %E %Cc Mon 00040 @@ -1457,6 +1550,15 @@ of Yendor. "Go forth, and let %d guide your steps." %E +%Cc Mon 00082 +%lC studies %o for a moment, +then returns his gaze to you. + +"%oC must remain with you. Use them +as you resume your search for the Amulet. +%Z await your return through the magic portal +that brought you here." +%E %Cp Mon 00090 "Welcome back, %p. How is your quest for the Amulet going?" %E @@ -1499,30 +1601,45 @@ the final time you come here. %Cp Pri 00009 "May %d be with you, %s." %E -%Cc Pri 00010 +%Cp Pri 00010 +"Greetings, %r. It is good to see you again." +%E +%Cp Pri 00011 +"Ah, %p! Our deepest gratitude for all of your help." +%E +%Cp Pri 00012 +"Welcome back, %s! With %o, no undead can stand against us." +%E +%Cp Pri 00013 +"Praise be to %d, for delivering us from %n." +%E +%Cp Pri 00014 +"May %d be with you, %s." +%E +%Cc Pri 00015 "Ah, %p, my %S. You have returned to us at last. A great blow has befallen our order; perhaps you can help us. First, however, I must determine if you are prepared for this great challenge." %E -%Cp Pri 00011 +%Cp Pri 00016 "Again, my %S, you stand before me. Are you ready now to help us?" %E -%Cp Pri 00012 +%Cp Pri 00017 "Once more, %p, you stand within the sanctum. Are you ready now?" %E -%Cc Pri 00013 +%Cc Pri 00018 "You are a heretic, %p! How can you, %ra, deviate so from the teachings of %d? Begone from this temple. You are no longer %sa to this order. We will pray to %d for other assistance, as you have failed us utterly." %E -%Cc Pri 00014 +%Cc Pri 00019 "Alas, %p, it is not yet to be. A mere %r could never withstand the might of %n. Go forth, again into the world, and return when you have attained the post of %R." %E -%Cc Pri 00015 +%Cc Pri 00020 "This is terrible, %p. You have deviated from the true path! You know that %d requires the most strident devotion of this order. The %shood must stand for utmost piety. @@ -1530,7 +1647,7 @@ order. The %shood must stand for utmost piety. "Go from here, atone for your sins against %d. Return only when you have purified yourself." %E -%Cc Pri 00016 +%Cc Pri 00021 "Yes, %p. You are truly ready now. Attend to me and I shall tell you of what has transpired: @@ -1549,38 +1666,38 @@ undead that befoul the land. "Go with %d as your guide, %p." %E -%Cp Pri 00020 +%Cp Pri 00025 "You can prevail, if you rely on %d." %E -%Cp Pri 00021 +%Cp Pri 00026 "Remember that %n has great magic at his command." %E -%Cp Pri 00022 +%Cp Pri 00027 "Be pure, my %S." %E -%Cp Pri 00023 +%Cp Pri 00028 "Beware, %i is surrounded by a great graveyard." %E -%Cp Pri 00024 +%Cp Pri 00029 "You may be able to affect %n with magical cold." %E -%Cp Pri 00025 +%Cp Pri 00030 "Acquire and wear %o if you can. It will aid you against %n." %E -%Cp Pri 00026 +%Cp Pri 00031 "Call upon %d when your need is greatest. You will be answered." %E -%Cp Pri 00027 +%Cp Pri 00032 "The undead legions are weakest during the daylight hours." %E -%Cp Pri 00028 +%Cp Pri 00033 "Do not lose faith, %p. If you do so, %n will grow stronger." %E -%Cp Pri 00029 +%Cp Pri 00034 "Wear %o. It will assist you against the undead." %E -%Cc Pri 00030 +%Cc Pri 00035 You stand facing a large graveyard. The sky above is filled with clouds that seem to get thicker closer to the center. You sense the presence of undead in larger numbers than you have ever encountered before. @@ -1588,7 +1705,7 @@ undead in larger numbers than you have ever encountered before. You remember the descriptions of %i, given to you by %lC. It is ahead that you will find %ns trail. %E -%Cp Pri 00031 +%Cp Pri 00036 Again, you stand before %i. %E %Cc Pri 00040 @@ -1730,37 +1847,52 @@ distraction of leatherwings." %Cp Ran 00009 "We must regain %o. Without it we will be overrun." %E -%Cc Ran 00010 +%Cp Ran 00010 +"%pC! I have not seen you in many moons. How do you fare?" +%E +%Cp Ran 00011 +"Birdsong has returned to the grove, surely this means you have defeated %n." +%E +%Cp Ran 00012 +"%lC seems to have regained some of his strength." +%E +%Cp Ran 00013 +"So, tell us how you entered %i, in case some new evil arises there." +%E +%Cp Ran 00014 +"Is that truely %o that I see you carrying?" +%E +%Cc Ran 00015 "%pC! You have returned! Thank %d. "We have great need of you. But first, I must see if you have the required abilities to take on this responsibility." %E -%Cp Ran 00011 +%Cp Ran 00016 "Once again, %p, you stand in our midst. Are you ready now?" %E -%Cp Ran 00012 +%Cp Ran 00017 "Ah, you are here again, %p. Allow me to determine your readiness..." %E -%Cc Ran 00013 +%Cc Ran 00018 "%pC! You have doomed us all. You fairly radiate %L influences and weaken the power we have raised in this grove as a result! "Begone! We renounce your %shood with us! You are an outcast now!" %E -%Cc Ran 00014 +%Cc Ran 00019 "%p, you are yet too inexperienced to withstand the demands of that which we need you to do. %RA might just be able to do this thing. "Return to us when you have learned more, my %S." %E -%Cc Ran 00015 +%Cc Ran 00020 "You have strayed, %p! You know that %d requires that we maintain a pure devotion to things %a! "You must go from us. Return when you have purified yourself." %E -%Cc Ran 00016 +%Cc Ran 00021 "You are indeed ready, %p. I shall tell you what has transpired, and why we so desperately need your help: @@ -1783,40 +1915,40 @@ underground cavern of %n. He has always coveted "Recover %o for us, %p! Only then will %d be safe." %E -%Cp Ran 00020 +%Cp Ran 00025 "It is rumored that the Forest and Mountain Centaurs have resolved their ancient feud and now band together against us." %E -%Cp Ran 00021 +%Cp Ran 00026 "%nC is strong, and very smart." %E -%Cp Ran 00022 +%Cp Ran 00027 "Use %o, when you find it. It will help you survive to reach us." %E -%Cp Ran 00023 +%Cp Ran 00028 "Remember, let %d be your guide." %E -%Cp Ran 00024 +%Cp Ran 00029 "Call upon %d when you face %n. The very act of doing so will infuriate him, and give you advantage." %E -%Cp Ran 00025 +%Cp Ran 00030 "%n and his kind have always hated us." %E -%Cp Ran 00026 +%Cp Ran 00031 "We cannot hold the grove much longer, %p. Hurry!" %E -%Cp Ran 00027 +%Cp Ran 00032 "To infiltrate %i, you must be very stealthy." %E -%Cp Ran 00028 +%Cp Ran 00033 "Remember that %n is a braggart. Trust not what he says." %E -%Cp Ran 00029 +%Cp Ran 00034 "You can triumph, %p, if you trust in %d." %E -%Cc Ran 00030 +%Cc Ran 00035 This must be %i. You are in a cave built of many different rooms, all interconnected @@ -1829,7 +1961,7 @@ You are in room 9 of the cave. There are tunnels to rooms *rustle* *rustle* (must be bats nearby) *sniff* (I can smell the evil wumpus nearby!) %E -%Cc Ran 00031 +%Cc Ran 00036 Once again, you descend into %i. *whoosh* (I feel a draft from some pits). @@ -1975,23 +2107,40 @@ with %l. "Be careful what you steal, I hear the boss has perfected turning rocks into worthless pieces of glass." %E -%Cc Rog 00010 +%Cp Rog 00010 +"I was sure wrong about Lady Tyvefelle's house; I barely got away with my +life and lost my lock pick in the process." +%E +%Cp Rog 00011 +"You're back? Even the Twain don't come back anymore." +%E +%Cp Rog 00012 +"Can you spare an old cutpurse a zorkmid for some grog?" +%E +%Cp Rog 00013 +"Fritz tried to join the other side, and now he's hell-hound chow." +%E +%Cp Rog 00014 +"Be careful what you steal, I hear the boss has perfected turning +rocks into worthless pieces of glass." +%E +%Cc Rog 00015 "Well, look who it is boys -- %p has come home. You seem to have fallen behind in your dues. I should kill you as an example to these other worthless cutpurses, but I have a better plan. If you are ready maybe you could work off your back dues by performing a little job for me. Let us just see if you are ready..." %E -%Cp Rog 00011 +%Cp Rog 00016 "Well, I didn't expect to see you back. It shows that you are either stupid, or you are finally ready to accept my offer. Let us hope for your sake it isn't stupidity that brings you back." %E -%Cp Rog 00012 +%Cp Rog 00017 "Did you perhaps mistake me for some other %lt? You must think me as stupid as your behavior. I warn you not to try my patience." %E -%Cc Rog 00013 +%Cc Rog 00018 "Well %gp, it looks like our friend has forgotten who is the boss around here. Our friend seems to think that %rp have been put in charge. Wrong. DEAD WRONG!" @@ -1999,19 +2148,19 @@ charge. Wrong. DEAD WRONG!" Your sudden shift in surroundings prevents you from hearing the end of %ls curse. %E -%Cc Rog 00014 +%Cc Rog 00019 "In the time that you've been gone you've only been able to master the arts of %ra? I've trained ten times again as many %Rp in that time. Maybe I should send one of them, no? Where would that leave you, %p? Oh yeah, I remember, I was going to kill you!" %E -%Cc Rog 00015 +%Cc Rog 00020 "Maybe I should chain you to my perch here for a while. Perhaps watching real %a men at work will bring some sense back to you. I don't think I could stand the sight of you for that long though. Come back when you can be trusted to act properly." %E -%Cc Rog 00016 +%Cc Rog 00021 "Will everyone not going to retrieve %o from that jerk, %n, take one step backwards. Good choice, %p, because I was going to send you anyway. My other %gp @@ -2022,44 +2171,44 @@ has %o. You are going to get %o and bring it back to me. So simple an assignment even you can understand it." %E -%Cp Rog 00020 +%Cp Rog 00025 "You don't seem to understand, %o isn't here so neither should you be!" %E -%Cp Rog 00021 +%Cp Rog 00026 "May %d curse you with lead fingers. Get going!" %E -%Cp Rog 00022 +%Cp Rog 00027 "We don't have all year. GET GOING!" %E -%Cp Rog 00023 +%Cp Rog 00028 "How would you like a scar necklace? I'm just the jeweler to do it!" %E -%Cp Rog 00024 +%Cp Rog 00029 "Lazy S.O.B. Maybe I should call up someone else..." %E -%Cp Rog 00025 +%Cp Rog 00030 "Maybe I should open your skull and see if my instructions are inside?" %E -%Cp Rog 00026 +%Cp Rog 00031 "This is not a task you can complete in the afterlife, you know." %E -%Cp Rog 00027 +%Cp Rog 00032 "Inside every living person is a dead person trying to get out, and I have your key!" %E -%Cp Rog 00028 +%Cp Rog 00033 "We're almost out of hell-hound chow, so why don't you just get moving!" %E -%Cp Rog 00029 +%Cp Rog 00034 "You know, %o isn't going to come when you whistle. You must get it yourself." %E -%Cc Rog 00030 +%Cc Rog 00035 Those damn little hairs tell you that you are nearer to %o. %E -%Cp Rog 00031 +%Cp Rog 00036 Not wanting to face %l without having stolen %o, you continue. %E @@ -2173,9 +2322,9 @@ show you what to do with it. Once that's done, we will be invincible!" Even before your senses adjust, you recognize the kami of %H. -But why is the standard of your teki, %n, flying -above the town? Why are ninja wandering freely, where are the -samurai of your daimyo, %l? +You %x the standard of your teki, %n, flying above +the town. How could such a thing have happened? Why are ninja +wandering freely; where are the samurai of your daimyo, %l? You quickly say a prayer to Izanagi and Izanami and walk towards town. @@ -2205,40 +2354,55 @@ the kami of %H before you return again. %Cp Sam 00009 "If %o is not returned, we will all be ninja." %E -%Cc Sam 00010 +%Cp Sam 00010 +"Come, join us in celebrating with some sake." +%E +%Cp Sam 00011 +"Ikaga desu ka?" +%E +%Cp Sam 00012 +"You have brought our clan and %l much honor." +%E +%Cp Sam 00013 +"Please %r, sit for a while and tell us how you overcame the Ninja." +%E +%Cp Sam 00014 +"%lC still lives! You have saved us from becoming ronin." +%E +%Cc Sam 00015 "Ah, %p-san, it is good to see you again. I need someone who can lead my samurai against %n. If you are ready, you will be that person." %E -%Cp Sam 00011 +%Cp Sam 00016 "Once again, %p-san, you kneel before me. Are you yet capable of being my vassal?" %E -%Cp Sam 00012 +%Cp Sam 00017 "You begin to test my matsu, %p-san. If you cannot determine what I want in a samurai, how can I rely on you to figure out what I need from a samurai?" %E -%Cc Sam 00013 +%Cc Sam 00018 "You are no longer my samurai, %p. "Hara-kiri is denied. You are ordered to shave your head and then to become a monk. Your fief and family are forfeit. Wakarimasu?" %E -%Cc Sam 00014 +%Cc Sam 00019 "%p-san, you have learned well and honored your family. I require the skills of %Ra in order to defeat %n. Go and seek out teachers. Learn what they have learned. When you are ready, return to me." %E -%Cc Sam 00015 +%Cc Sam 00020 "%p-san, you would do better to join the kyokaku. "You have skills, but until you can call upon the bushido to know when and how to use them you are not samurai. When you can think %a and act %a then return." %E -%Cc Sam 00016 +%Cc Sam 00021 "Domo %p-san, indeed you are ready. I can now tell you what it is that I require of you. @@ -2256,42 +2420,42 @@ cha-no-you in 5 sticks. "Wakarimasu?" %E -%Cp Sam 00020 +%Cp Sam 00025 "To defeat %n you must overcome the seven emotions: hate, adoration, joy, anxiety, anger, grief, and fear." %E -%Cp Sam 00021 +%Cp Sam 00026 "Remember your honor is my honor, you perform in my name." %E -%Cp Sam 00022 +%Cp Sam 00027 "I will go to the temple and burn incense for your safe return." %E -%Cp Sam 00023 +%Cp Sam 00028 "Sayonara." %E -%Cp Sam 00024 +%Cp Sam 00029 "There can be honor in defeat, but no gain." %E -%Cp Sam 00025 +%Cp Sam 00030 "Your kami must be strong in order to succeed." %E -%Cp Sam 00026 +%Cp Sam 00031 "You are indeed a worthy %R, but now you must be a worthy samurai." %E -%Cp Sam 00027 +%Cp Sam 00032 "If you fail, %n will be like a tai-fun on the land." %E -%Cp Sam 00028 +%Cp Sam 00033 "If you are truly %a, %d will listen." %E -%Cp Sam 00029 +%Cp Sam 00034 "Sharpen your swords and your wits for the task before you." %E -%Cc Sam 00030 +%Cc Sam 00035 You instinctively reach for your swords. You do not recognize the lay of this land, but you know that your teki are everywhere. %E -%Cp Sam 00031 +%Cp Sam 00036 Thankful that your %sp at %H cannot see your fear, you prepare again to advance. %E @@ -2444,33 +2608,48 @@ Things appear to have become so bad that you fear that soon %Cp Tou 00009 "They told me that this was the off season!" %E -%Cc Tou 00010 +%Cp Tou 00010 +"Gehennom on 5 zorkmids a day -- more like 500 a day if you ask me." +%E +%Cp Tou 00011 +"Do you know where I could find some nice postcards of The Gnomish Mines?" +%E +%Cp Tou 00012 +"Have you tried the weird toilets?" +%E +%Cp Tou 00013 +"If you stick around, I'll show you the pictures from my latest trip." +%E +%Cp Tou 00014 +"Did you bring me back any souvenirs?" +%E +%Cc Tou 00015 "Is it really you, %p! I had given up hope for your return. As you can %x, we are desperately in need of your talents. Someone must defeat %n if our town is become what it once was. "Let me see if you are ready to be that someone." %E -%Cp Tou 00011 +%Cp Tou 00016 "Things are getting worse, %p. I hope that this time you are ready." %E -%Cp Tou 00012 +%Cp Tou 00017 "I hope that for the sake of %H you have prepared yourself this time." %E -%Cc Tou 00013 +%Cc Tou 00018 "It is too late, %p. You are not even worthy to die amongst us. Leave %H and never return." %E -%Cc Tou 00014 +%Cc Tou 00019 "There is still too much that you have to learn before you can undertake the next step. Return to us as a proven %R, and perhaps then you will be ready. "Go back now, and may the teachings of %d serve you well." %E -%Cc Tou 00015 +%Cc Tou 00020 "It would be an affront to %d to have one not true to the %a path undertake her bidding. @@ -2478,7 +2657,7 @@ you will be ready. bad influences on your actions. Remember, only by following the %a path can you hope to overcome the obstacles you will face." %E -%Cc Tou 00016 +%Cc Tou 00021 %E "You have indeed proven yourself a worthy %c, %p. @@ -2494,44 +2673,44 @@ and recover %o. "Do not be distracted on your quest. If you do not return quickly I fear that all will be lost. Let us both pray now that %d will guide you and keep you safe." -%Cp Tou 00020 +%Cp Tou 00025 "Do not be fooled by the false promises of %n." %E -%Cp Tou 00021 +%Cp Tou 00026 "To enter %i you must pass many traps." %E -%Cp Tou 00022 +%Cp Tou 00027 "If you do not return with %o, your quest will be in vain." %E -%Cp Tou 00023 +%Cp Tou 00028 "Do not be afraid to call upon %d if you truly need help." %E -%Cp Tou 00024 +%Cp Tou 00029 "If you do not destroy %n, he will follow you back here!" %E -%Cp Tou 00025 +%Cp Tou 00030 "Take %o from %n and you may be able to defeat him." %E -%Cp Tou 00026 +%Cp Tou 00031 "You must hurry, %p!" %E -%Cp Tou 00027 +%Cp Tou 00032 "You are like %Sa to me, %p. Do not let me down." %E -%Cp Tou 00028 +%Cp Tou 00033 "If you are %a at all times you may succeed, %p." %E -%Cp Tou 00029 +%Cp Tou 00034 "Let all who meet you on your journey know that you are on an quest for %l and grant safe passage." %E -%Cc Tou 00030 +%Cc Tou 00035 Only your faith in %d keeps you from trembling. You %x the handiwork of %ns henchlings everywhere. %E -%Cp Tou 00031 +%Cp Tou 00036 You know that this time you must find and destroy %n. %E %Cc Tou 00040 @@ -2678,40 +2857,55 @@ that this may be the last time you come here. %Cp Val 00009 "I would deal with this foul %n myself, but %d forbids it." %E -%Cc Val 00010 +%Cp Val 00010 +"Hail, and well met, brave %c." +%E +%Cp Val 00011 +"May %d guide your steps, %p." +%E +%Cp Val 00012 +"%lC told us you had succeeded!" +%E +%Cp Val 00013 +"You recovered %o just in time, %p." +%E +%Cp Val 00014 +"Hail %d, for delivering %o back to us." +%E +%Cc Val 00015 "Ah, %p, my %S. You have returned to %H at last. We are in dire need of your aid, but I must determine if you are yet ready for such an undertaking. "Let me read your fate..." %E -%Cp Val 00011 +%Cp Val 00016 "Let me read the future for you now, %p, perhaps you have managed to change it enough..." %E -%Cp Val 00012 +%Cp Val 00017 "Again, I shall read your fate, my %S. Let us both hope that you have made changes to become ready for this task..." %E -%Cc Val 00013 +%Cc Val 00018 "No, %p. Your fate is sealed. I must cast about for another champion. Begone from my presence, and never return. Know this, that you shall never succeed in this life, and Valhalla is denied to you." %E -%Cc Val 00014 +%Cc Val 00019 "I see you and %n fighting, %p. But you are not prepared and shall die at %ns hand if you proceed. No. This will not do. Go back out into the world, and grow more experienced at the ways of war. Only when you have returned %Ra will you be able to defeat %n." %E -%Cc Val 00015 +%Cc Val 00020 "NO! This is terrible. I see you becoming an ally of %n, and leading his armies in the final great battles. This must not come to pass! You have strayed from the %a path. You must purge yourself, and return here only when you have regained a state of purity." %E -%Cc Val 00016 +%Cc Val 00021 "It is not clear, %p, for my sight is limited without %o. But it is now likely that you can defeat %n, and recover %o. @@ -2731,45 +2925,45 @@ unless %o is returned into my care, %n may start Ragnarok. from there and you will find %ns lair. Defeat him and return %o to me." %E -%Cp Val 00020 +%Cp Val 00025 "Go with the blessings of %d." %E -%Cp Val 00021 +%Cp Val 00026 "Call upon %d when you are in need." %E -%Cp Val 00022 +%Cp Val 00027 "Use %o if you can. It will protect you." %E -%Cp Val 00023 +%Cp Val 00028 "Magical cold is very effective against %n." %E -%Cp Val 00024 +%Cp Val 00029 "To face %n, you will need to be immune to fire." %E -%Cp Val 00025 +%Cp Val 00030 "May %d strengthen your sword-arm." %E -%Cp Val 00026 +%Cp Val 00031 "Trust in %d. He will not desert you." %E -%Cp Val 00027 +%Cp Val 00032 "It becomes more likely that Ragnarok will come with every passing moment. You must hurry, %p." %E -%Cp Val 00028 +%Cp Val 00033 "If %n can master %o, he will be powerful enough to face %d far earlier than is fated. This must not be!" %E -%Cp Val 00029 +%Cp Val 00034 "Remember your training, %p. You can succeed." %E -%Cc Val 00030 +%Cc Val 00035 The ice and snow gives way to a valley floor. You %x ahead of you a huge round hill surrounded by pools of lava. This then is the entrance to %i. It looks like you're not going to get in without a fight though. %E -%Cp Val 00031 +%Cp Val 00036 Once again, you stand before the entrance to %i. %E %Cc Val 00040 @@ -2877,13 +3071,13 @@ Amulet interferes with mine. I hope for your success." %Cc Wiz 00001 You are suddenly in familiar surroundings. You notice what appears to be a large, squat stone structure nearby. Wait! That looks like the -tower of your old master, %l. +tower of your former teacher, %l. However, things are not the same as when you were last here. Mists and areas of unexplained darkness surround the tower. There is movement in the shadows. -Your master would never allow such unaesthetic forms to surround the +Your teacher would never allow such unaesthetic forms to surround the tower... unless something were dreadfully wrong! %E %Cp Wiz 00002 @@ -2904,45 +3098,61 @@ You have an odd feeling this may be the last time you ever come here. portal spell!!" %E %Cp Wiz 00008 -"We must strive to return balance to the world, or all is lost." +"The spells of %n were just to powerful for us to withstand." %E %Cp Wiz 00009 "I, too, will venture into the world, because %n is but one of many evils to be vanquished." %E -%Cc Wiz 00010 +%Cp Wiz 00010 +"I have some eye of newt to trade, do you have a spare blind-worm's sting?" +%E +%Cp Wiz 00011 +"The magic portal now seems like it will remain stable for quite some time." +%E +%Cp Wiz 00012 +"Have you noticed how much stronger %l is since %o was recovered?" +%E +%Cp Wiz 00013 +"Thank %d! We weren't positive you would defeat %n." +%E +%Cp Wiz 00014 +"I, too, will venture into the world, because %n was but one of +many evils to be vanquished." +%E +%Cc Wiz 00015 "Come closer, %p, for my voice falters in my old age. Yes, I see that you have come a long way since you went out into the world, leaving the safe confines of this tower. However, I must first determine if you have all of the skills required to take on the task I require of you." %E -%Cp Wiz 00011 +%Cp Wiz 00016 "Well, %p, you have returned. Perhaps you are now ready..." %E -%Cp Wiz 00012 +%Cp Wiz 00017 "This is getting tedious, %p, but perseverance is a sign of a true mage. I certainly hope that you are truly ready this time!" %E -%Cc Wiz 00013 +%Cc Wiz 00018 "You fool, %p! Why did I waste all of those years teaching you the esoteric arts? Get out of here! I shall find another." %E -%Cc Wiz 00014 +%Cc Wiz 00019 "Alas, %p, you have not yet shown your proficiency as a worthy spellcaster. As %ra, you would surely be overcome in the challenge ahead. Go, now, expand your horizons, and return when you have attained renown as %Ra." %E -%Cc Wiz 00015 -"You amaze me, %p! How many times did I tell you that Balance -requires care. One must use the world with care, lest one leave it in ruins -and simplify the task of %n. +%Cc Wiz 00020 +"You amaze me, %p! How many times did I tell you that the way of a mage +is an exacting one. One must use the world with care, lest one leave it +in ruins and simplify the task of %n. "You must go back and show your worthiness. Do not return until you are truly ready for this quest. May %d guide you in this task." %E -%Cc Wiz 00016 +%Cc Wiz 00021 %E "Yes, %p, you truly are ready for this dire task. Listen, carefully, for what I tell you now will be of vital importance. @@ -2965,42 +3175,42 @@ shall soon perish. "You must travel to %i, and within its dungeons, find and overcome %n, and return %o to me. -"Go now, with %d, and return Balance to the world." -%Cp Wiz 00020 +"Go now, with %d, and complete this quest before it is too late." +%Cp Wiz 00025 "Beware, for %n is immune to most magical attacks." %E -%Cp Wiz 00021 +%Cp Wiz 00026 "To enter %i you must pass many traps." %E -%Cp Wiz 00022 +%Cp Wiz 00027 "%nC may be vulnerable to physical attacks." %E -%Cp Wiz 00023 +%Cp Wiz 00028 "%d will come to your aid when you call." %E -%Cp Wiz 00024 +%Cp Wiz 00029 "You must utterly destroy %n. He will pursue you otherwise." %E -%Cp Wiz 00025 +%Cp Wiz 00030 "%oC is a mighty artifact. With it you can destroy %n." %E -%Cp Wiz 00026 +%Cp Wiz 00031 "Go forth with the blessings of %d." %E -%Cp Wiz 00027 +%Cp Wiz 00032 "I will have my %gP watch for your return." %E -%Cp Wiz 00028 +%Cp Wiz 00033 "Feel free to take any items in that chest that might aid you." %E -%Cp Wiz 00029 +%Cp Wiz 00034 "You will know when %o is near. Proceed with care!" %E -%Cc Wiz 00030 +%Cc Wiz 00035 Wisps of fog swirl nearby. You feel that %ns lair is close. %E -%Cp Wiz 00031 +%Cp Wiz 00036 You believe that you may once again invade %i. %E %Cc Wiz 00040 diff --git a/dat/rumors.fal b/dat/rumors.fal index 6d88513..9d1aec0 100644 --- a/dat/rumors.fal +++ b/dat/rumors.fal @@ -60,6 +60,7 @@ Drinking potions of booze may land you in jail if you are under 21. Drop your vanity and get rid of your jewels! Pickpockets about! Eat 10 cloves of garlic and keep all humans at a two-square distance. Eels hide under mud. Use a unicorn to clear the water and make them visible. +Elf has extra speed. Engrave your wishes with a wand of wishing. Eventually you will come to admire the swift elegance of a retreating nymph. Ever heard hissing outside? I *knew* you hadn't! @@ -236,6 +237,7 @@ They say that counting your eggs before they hatch shows that you care. They say that dipping a bag of tricks in a fountain won't make it an icebox. They say that dipping an eel and brown mold in hot water makes bouillabaisse. They say that donating a doubloon is extremely pious charity. +They say that dungeoneers prefer dark chocolate. They say that eating royal jelly attracts grizzly owlbears. They say that eggs, pancakes and juice are just a mundane breakfast. They say that everyone knows why Medusa stands alone in the dark. @@ -300,7 +302,7 @@ They say that the NetHack gods generally welcome your sacrifices. They say that the Three Rings are named Vilya, Nenya and Narya. They say that the Wizard of Yendor has a death wish. They say that the `hair of the dog' is sometimes an effective remedy. -They say that the best time to save your game is now before its too late. +They say that the best time to save your game is now before it's too late. They say that the biggest obstacle in NetHack is your mind. They say that the gods are angry when they hit you with objects. They say that the priesthood are specially favored by the gods. @@ -378,6 +380,7 @@ You can get a genuine Amulet of Yendor by doing the following: --More-- You can make holy water by boiling the hell out of it. You can protect yourself from black dragons by doing the following: --More-- You can't get by the snake. +You choke on the fortune cookie. --More-- You feel like someone is pulling your leg. You have to outwit the Sphynx or pay her. You hear the fortune cookie's hissing! diff --git a/dat/rumors.tru b/dat/rumors.tru index 0c87d65..3273664 100644 --- a/dat/rumors.tru +++ b/dat/rumors.tru @@ -50,7 +50,6 @@ Eating a tengu is like eating a nymph. Eating a wraith is a rewarding experience! Eating unpaid leprechauns may be advantageous. Elbereth has quite a reputation around these parts. -Elf has extra speed. Elf corpses are incompatible with the sandman, and at times the gods as well. Elven cloaks cannot rust. Even evil players have a guardian angel. @@ -91,6 +90,7 @@ It is bad manners to use a wand in a shop. It is dangerous to visit a graveyard at midnight. It is not always a good idea to whistle for your dog. It is rumored that the Wizard has hired some help. +It is the letter 'c' and not 'e' that changes status to statue. It might be a good idea to offer the unicorn a ruby. It would be peculiarly sad were your dog turned to stone. It's a `d' eats `d' world. @@ -144,10 +144,9 @@ Some monsters can be tamed. I once saw a hacker with a tame dragon! Someone once said that what goes up < might come down >. Someone's been spiking the pits! Sometimes monsters are more likely to fight each other than attack you. -Spinach, carrot, and a melon -- a meal fit for a nurse! +Spinach, carrot, and jelly -- a meal fit for a nurse! Tainted meat is even more sickening than poison! Telepathy is just a trick: once you know how to do it, it's easy. -The darker the warning, the more dire the danger. The Leprechaun Gold Tru$t is no division of the Magic Memory Vault. The Wizard finds death to be quite an experience. The best equipment for your work is, of course, the most expensive. @@ -163,6 +162,7 @@ There is a big treasure hidden in the zoo! There is more magic in this cave than meets the eye. There is no harm in praising a large dog. There is nothing like eating a mimic. +There once was a Knight named Lancelot who liked to ride with his lance a lot. They say a gelatinous cube can paralyze you... They say that Juiblex is afraid of a wand of digging. They say that Medusa would like to put you on a pedestal. @@ -213,9 +213,8 @@ They say that demigods must leave behind their prized earthly possessions. They say that disturbing a djinni can be a costly mistake. They say that dragon scales can be quite enchanting. They say that dropping coins into a fountain will not grant you a wish. -They say that dungeoneers prefer dark chocolate. They say that dwarves lawfully mind their own business. -They say that eating a bat corpse will make you batty, for awhile. +They say that eating a bat corpse will make you batty, for a while. They say that eating a cram ration is a smart move. They say that eating blue jelly is cool if you don't fight the feeling. They say that escaping a dungeon is only the beginning of the end. @@ -314,7 +313,7 @@ They say that with a floating eye you could see in the dark. They say that you are lucky if you can get a unicorn to catch a ruby. They say that you are what you eat. They say that you can find named weapons at an altar if you're lucky. -They say that you can safely touch cockatrices eggs but why bother? +They say that you can safely touch cockatrice eggs but why bother? They say that you can't break an amulet of reflection. They say that you don't always get what you wish for. They say that you should always be prepared for a final challenge. diff --git a/dat/sokoban.des b/dat/sokoban.des index 56f04e3..2e1fd0e 100644 --- a/dat/sokoban.des +++ b/dat/sokoban.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)sokoban.des 3.3 99/03/15 +# SCCS Id: @(#)sokoban.des 3.4 1999/03/15 # Copyright (c) 1998-1999 by Kevin Hugo # NetHack may be freely redistributed. See license for details. # @@ -508,6 +508,9 @@ TRAP:"hole",(21,01) TRAP:"hole",(22,01) TRAP:"hole",(23,01) +MONSTER:'m',"giant mimic", random, m_object "boulder" +MONSTER:'m',"giant mimic", random, m_object "boulder" + # Random objects OBJECT:'%',random,random OBJECT:'%',random,random @@ -599,6 +602,8 @@ TRAP:"hole",(20,01) TRAP:"hole",(21,01) TRAP:"hole",(22,01) +MONSTER:'m',"giant mimic", random, m_object "boulder" +MONSTER:'m',"giant mimic", random, m_object "boulder" # Random objects OBJECT:'%',random,random diff --git a/dat/tower.des b/dat/tower.des index 0468b03..f5cc292 100644 --- a/dat/tower.des +++ b/dat/tower.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)tower.des 3.3 90/02/26 +# SCCS Id: @(#)tower.des 3.4 1990/02/26 # Copyright (c) 1989 by Jean-Christophe Collet # NetHack may be freely redistributed. See license for details. # diff --git a/dat/wizhelp b/dat/wizhelp index d2b0c24..a025641 100644 --- a/dat/wizhelp +++ b/dat/wizhelp @@ -9,3 +9,14 @@ Debug-Mode Quick Reference: ^V == do trans-level teleport. ^W == make wish. ^X == show attributes including intrinsic attributes. + +#levelchange == change experience level +#light sources == show mobile light sources +#monpoly_control == control monster polymorphs +#poly == polymorph self +#seenv == show seen vectors +#stats == show memory statistics +#timeout == look at timeout queue +#vision == show vision array +#wmode == show wall modes + diff --git a/dat/yendor.des b/dat/yendor.des index 9260cde..8583457 100644 --- a/dat/yendor.des +++ b/dat/yendor.des @@ -1,4 +1,4 @@ -# SCCS Id: @(#)yendor.des 3.3 96/10/20 +# SCCS Id: @(#)yendor.des 3.4 1996/10/20 # Copyright (c) 1989 by Jean-Christophe Collet # Copyright (c) 1992 by M. Stephenson and Izchak Miller # NetHack may be freely redistributed. See license for details. diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index e82836c..cdf6336 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -1,16 +1,16 @@ .ds h0 "NetHack Guidebook .ds h1 .ds h2 % -.ds vr "NetHack 3.3 +.ds vr "NetHack 3.4 .ds f0 "\*(vr .ds f1 -.ds f2 "August 2, 2000 +.ds f2 "March 20, 2002 .mt A Guide to the Mazes of Menace -(Guidebook for NetHack 3.3) +(Guidebook for NetHack) .au Eric S. Raymond -(Extensively edited and expanded for 3.0 by Mike Threepoint) +(Extensively edited and expanded for 3.4) .hn 1 Introduction @@ -189,6 +189,7 @@ In order to understand what is going on in NetHack, first you must understand what NetHack is doing with the screen. The NetHack screen replaces the ``You see ...'' descriptions of text adventure games. Figure 1 is a sample of what a NetHack screen might look like. +The way the screen looks for you depends on your platform. .TS S center tab(~); @@ -205,7 +206,7 @@ The bat bites! -Player the Rambler St:12 Dx:7 Co:18 In:11 Wi:9 Ch:15 Neutral +Player the Rambler St:12 Dx:7 Co:18 In:11 Wi:9 Ch:15 Neutral Dlvl:1 $:0 HP:9(12) Pw:3(3) AC:10 Exp:1/19 T:257 Weak _ @@ -227,8 +228,10 @@ Your character's name and professional ranking (based on the experience level, see below). .lp Strength A measure of your character's strength; one of your six basic -attributes. Your attributes can range from 3 to 18 inclusive -(occasionally you may get super-strengths of the form 18/xx). The +attributes. A human character's attributes can range from 3 to 18 inclusive; +non-humans may exceed these limits +(occasionally you may get super-strengths of the form 18/xx, and magic can +also cause attributes to exceed the normal limits). The higher your strength, the stronger you are. Strength affects how successfully you perform physical tasks, how much damage you do in combat, and how much loot you can carry. @@ -365,6 +368,10 @@ An opulent throne. Letters and certain other symbols represent the various inhabitants of the Mazes of Menace. Watch out, they can be nasty and vicious. Sometimes, however, they can be helpful. +.lp I +This marks the last known location of an invisible or otherwise unseen +monster. Note that the monster could have moved. The 'F' and 'm' commands +may be useful here. .pg You need not memorize all these symbols; you can ask the game what any symbol represents with the `/' command (see the next section for @@ -430,11 +437,12 @@ always gives any additional information available about that name. .lp & Tell what a command does. .lp < -Go up to the previous level (if you are on the staircase or ladder). +Go up to the previous level (if you are on a staircase or ladder). .lp > -Go down to the next level (if you are on the staircase or ladder). +Go down to the next level (if you are on a staircase or ladder). .lp [yuhjklbn] -Go one step in the direction indicated (see Figure 2). If you can sense +Go one step in the direction indicated (see Figure 2). If you sense +or remember a monster there, you will fight the monster instead. Only these one-step movement commands cause you to fight monsters; the others (below) are ``safe.'' @@ -466,6 +474,11 @@ Prefix: move far, no pickup. Prefix: move until something interesting is found. .lp "G[yuhjklbn] or [yuhjklbn] Prefix: same as `g', but forking of corridors is not considered interesting. +.lp _ +Travel to a map location via a shortest-path algorithm. Stops on most of +the same conditions as the `G' command does. For ports with mouse +support, the command is also invoked when a mouse-click takes place on a +location further than 1 cell away from the current position. .lp . Rest, do nothing for one turn. .lp a @@ -598,7 +611,7 @@ the various deities in your game. .lp z Zap a wand. To aim at yourself, use `.' for the direction. .lp Z -Zap (cast) a spell. +Zap (cast) a spell. To cast at yourself, use `.' for the direction. .lp ^Z Suspend the game .ux " versions with job control only)." ( @@ -652,7 +665,8 @@ option is ``on''). .lp #chat Talk to someone. .lp #conduct -List which challenges you have adhered to. +List which challenges you have adhered to. See the section below entitled +``Conduct'' for details. .lp #dip Dip an object into something. .lp #enhance @@ -679,7 +693,7 @@ Quit the program without saving your game. .lp #ride Ride (or stop riding) a monster. .lp #rub -Rub a lamp. +Rub a lamp or a stone. .lp #sit Sit down. .lp #turn @@ -706,8 +720,10 @@ letter of the command. .\" on the Amiga set the {\it altmeta\/} option to get this behavior. In NT, OS/2, and PC NetHack, the `Alt' key can be used in this fashion. +.lp M-? +#? (not supported by all platforms) .lp M-2 -#twoweapon +#twoweapon (unless the number_pad option is enabled) .lp M-a #adjust .lp M-c @@ -750,6 +766,8 @@ can be used in this fashion. If the .op number_pad option is on, some additional letter commands are available: +.lp h +Help menu: display one of several help texts available, like ``?''. .lp j Jump to another location. Same as ``#jump'' or ``M-j''. .lp k @@ -758,7 +776,7 @@ Kick something (usually a door). Same as `^D'. Loot a box or bag on the floor beneath you, or the saddle from a horse standing next to you. Same as ``#loot'' or ``M-l''. .lp N -Name an item or type of object. Same as ``#name'' or ``M-N''. +Name an item or type of object. Same as ``#name'' or ``M-n''. .lp u Untrap a trap, door, or chest. Same as ``#untrap'' or ``M-u''. @@ -870,6 +888,15 @@ If you see a monster and you wish to fight it, just attempt to walk into it. Many monsters you find will mind their own business unless you attack them. Some of them are very dangerous when angered. Remember: discretion is the better part of valor. +.pg +If you can't see a monster (if it is invisible, or if you are blinded), +the symbol `I' will be shown when you learn of its presence. +If you attempt to walk into it, you will try to fight it just like +a monster that you can see; of course, +if the monster has moved, you will attack empty air. If you guess +that the monster has moved and you don't wish to fight, you can use the `m' +command to move without fighting; likewise, if you don't remember a monster +but want to try fighting anyway, you can use the `F' command. .hn 2 Your pet .pg @@ -1032,7 +1059,7 @@ exchanges your primary (the one being wielded) and secondary weapons. And if you have proficiency in the ``two weapon combat'' skill, you may wield both primary and secondary weapons simultaneously; use the `#twoweapon' extended command to engage or disengage that. Only -some types of characters (barbarians, for instance), have the necessary +some types of characters (barbarians, for instance) have the necessary skill available. Even with that skill, using two weapons at once incurs a penalty in the chance to hit your target compared to using just one weapon at a time. @@ -1043,7 +1070,7 @@ allows you to unwield the current weapon in addition to taking off other worn items. .pg Those of you in the audience who are AD&D players, be aware that each -weapon which exists in AD&D does roughly the same damage to monsters in +weapon which existed in AD&D does roughly the same damage to monsters in NetHack. Some of the more obscure weapons (such as the \fIaklys\fP, \fIlucern hammer\fP, and \fIbec-de-corbin\fP) are defined in an appendix to \fIUnearthed Arcana\fP, an AD&D supplement. @@ -1073,23 +1100,26 @@ also an option, which has NetHack choose another item to automatically fill your quiver when the inventory slot used for `Q' runs out. .pg -Some characters will throw multiple items in a single action. Rangers, -for instance, or anyone who achieves a high level of proficiency in -the relevant weapon skill (in bow skill if you're wielding one to -shoot arrows, or in sling skill if you're wielding one to shoot stones). -There is little you can do -to control this; if NetHack decides that you'll be shooting 3 arrows -on the current shot, then three arrows will travel in the direction -you've indicated, even if the first or second succeeds in killing the -target. You can explicitly limit the number of shots by using a numeric -prefix before the `t' or `f' command. +Some characters have the ability to fire a volley of multiple items in a +single turn. Knowing how to load several rounds of ammunition at +once -- or hold several missiles in your hand -- and still hit a +target is not an easy task. Rangers are among those who are adept +at this task, as are those with a high level of proficiency in the +relevant weapon skill (in bow skill if you're wielding one to +shoot arrows, in crossbow skill if you're wielding one to shoot bolts, +or in sling skill if you're wielding one to shoot stones). +The number of items that the character has a chance to fire varies from +turn to turn. You can explicitly limit the number of shots by using a +numeric prefix before the `t' or `f' command. For example, ``2f'' (or ``n2f'' if using .op number_pad mode) would ensure that at most 2 arrows are shot -even if NetHack decides that your skill warrants 3. If you specify +even if you could have fired 3. If you specify a larger number than would have been shot (``4f'' in this example), you'll just end up shooting the same number (3, here) as if no limit -had been specified. +had been specified. Once the volley is in motion, all of the items +will travel in the same direction; if the first ones kill a monster, +the others can still continue beyond that spot. .hn 3 Weapon proficiency .pg @@ -1308,10 +1338,17 @@ a time when your luck is particularly bad, you can end up wasting both the energy and the time required in casting. .pg Casting a spell calls forth magical energies and focuses them with -your naked mind. Releasing the magical energy releases some of your -memory of the spell with it. Each time you cast a spell, your -familiarity with it will dwindle, until you eventually forget the -details completely and must relearn it. +your naked mind. Some of the magical energy released comes from within +you, and casting several spells in a row may tire you. +Casting of spells also requires practice. With practice, your +skill in each category of spell casting will improve. Over time, however, +your memory of each spell will dim, and you will need to relearn it. +.pg +Some spells are +directional\(emyou must give a direction in which to cast them. You can also +cast them at yourself (just give a `.' or `s' for the direction). Be warned, +however, for this is often unwise. Other spells are nondirectional\(emthey +don't require a direction. .pg Just as weapons are divided into groups in which a character can become proficient (to varying degrees), spells are similarly grouped. @@ -1324,8 +1361,9 @@ Casting a spell also requires flexible movement, and wearing various types of armor may interfere with that. .pg The command to read a spellbook is the same as for scrolls, `r' -(read). The `+' command lists your current spells and the number of -spell points they require. The `Z' (cast) command casts a spell. +(read). The `+' command lists your current spells, their levels, +categories, and chances for failure. +The `Z' (cast) command casts a spell. .hn 2 Tools (`(') .pg @@ -1536,14 +1574,15 @@ Using a configuration file Any line in the configuration file starting with ``OPTIONS='' may be filled out with options in the same syntax as in NETHACKOPTIONS. Any line starting with ``DUNGEON='', ``EFFECTS='', ``MONSTERS='', -``OBJECTS='', or ``TRAPS='' +``OBJECTS='', ``TRAPS='', or ``BOULDER='' is taken as defining the corresponding .op dungeon, .op effects, .op monsters, .op objects -or .op traps +or +.op boulder option in a different syntax, a sequence of decimal numbers giving the character position in the current font to be used in displaying each entry. @@ -1565,6 +1604,9 @@ Your starting alignment (align:lawful, align:neutral, or align:chaotic). You may specify just the first letter. The default is to randomly pick an appropriate alignment. Cannot be set with the `O' command. +.lp autodig +Automatically dig if you are wielding a digging tool and moving into a place +that can be dug (default false). .lp "autopickup " Automatically pick up things onto which you move (default on). .lp "autoquiver " @@ -1580,6 +1622,8 @@ Use BIOS calls to update the screen display quickly and to read the keyboard (allowing the use of arrow keys to move) on machines with an IBM PC compatible BIOS ROM (default off, OS/2, PC, and ST NetHack only). +.lp boulder +Set the character used to display boulders (default is rock class symbol). .lp catname Name your starting cat (ex. ``catname:Morris''). Cannot be set with the `O' command. @@ -1596,9 +1640,6 @@ Check free disk space before writing files to disk (default on). You may have to turn this off if you have more than 2 GB free space on the partition used for your save and level files. Only applies when MFLOPPY was defined during compilation. -.lp "color " -Use color for different monsters, objects, and dungeon features -(default on for microcomputers). .lp "confirm " Have user confirm attacks on pets, shopkeepers, and other peaceable creatures (default on). @@ -1610,11 +1651,40 @@ This option also sets up proper handling of graphics characters for such terminals, so you should specify it when appropriate even if you override the selections with your own graphics strings. .lp disclose -Offer to disclose various information when the game ends (default all). -The possibilities are identifying your inventory ('i'), -disclosing your attributes ('a'), summarizing monsters that have been -vanquished ('v'), listing monster species that have been genocided ('g'), -and displaying your conduct ('c'). +Controls options for disclosing various information when the game ends (defaults +to all possibilities being disclosed). +The possibilities are: +.sd +.si +i - disclose your inventory. +a - disclose your attributes. +v - summarize monsters that have been vanquished. +g - list monster species that have been genocided. +c - display your conduct. +.ei +.ed +Each disclosure possibility can optionally be preceded by a prefix which +let you refine how it behaves. Here are the valid prefixes: +.sd +.si +y - prompt you and default to yes on the prompt. +n - prompt you and default to no on the prompt. ++ - disclose it without prompting. +- - do not disclose it and do not prompt. +.ei +.ed +(ex. ``disclose:yi na +v -g -c'') +The example sets +.op inventory +to prompt and default to yes, +.op attributes +to prompt and default to no, +.op vanquished +to disclose without prompting, +.op genocided +to not disclose and not to prompt, +.op conduct +to not disclose and not to prompt. Note that the vanquished monsters list includes all monsters killed by traps and each other as well as by you. .lp dogname @@ -1680,11 +1750,6 @@ Note that in the next release, new symbols may be added, or the present ones rearranged. Cannot be set with the `O' command. -.lp eight_bit_tty -Pass eight-bit character values (for example, specified with the -.op traps -option) straight through to your terminal (default off). Only applies -to the tty port. .lp extmenu Changes the extended commands interface to pop-up a menu of available commands. It is keystroke compatible with the traditional interface except that it does @@ -1715,10 +1780,6 @@ with the `/' command, ask if you want to see it (default on). Turning help off makes just looking at things faster, since you aren't interrupted with the ``More info?'' prompt, but it also means that you might miss some interesting and/or important information. -.lp hilite_pet -Visually distinguish pets from similar animals (default off). -In text windowing, use text highlighting when color is turned off; -with X tiles, display a heart symbol near pets. .lp horsename Name your starting horse (ex. ``horsename:Trigger''). Cannot be set with the `O' command. @@ -1737,7 +1798,7 @@ Display an introductory message when starting the game (default on). Show corridor squares seen by night vision or a light source held by your character as lit (default off). .lp "mail " -Enable mail delivery during the game. +Enable mail delivery during the game (default on). .lp "male " An obsolete synonym for ``gender:male''. Cannot be set with the `O' command. @@ -1756,47 +1817,47 @@ object classes rather than a character prompt, and then a menu of matching objects for selection. .lp menu_deselect_all Menu character accelerator to deselect all items in a menu. -Implemented by the X11 and tty ports. +Implemented by the Amiga, Gem, X11 and tty ports. Default '-'. .lp menu_deselect_page Menu character accelerator deselect all items on this page of a menu. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default '\e'. .lp menu_first_page Menu character accelerator to jump to the first page in a menu. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default '^'. .lp menu_invert_all Menu character accelerator to invert all items in a menu. -Implemented by the X11 and tty ports. +Implemented by the Amiga, Gem, X11 and tty ports. Default '@'. .lp menu_invert_page Menu character accelerator to invert all items on this page of a menu. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default '~'. .lp menu_last_page Menu character accelerator to jump to the last page in a menu. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default '|'. .lp menu_next_page Menu character accelerator to goto the next menu page. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default '>'. .lp menu_previous_page Menu character accelerator to goto the previous menu page. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default '<'. .lp menu_search Menu character accelerator to search for a menu item. -Implemented only by the X11 port. +Implemented by the Amiga, Gem and X11 ports. Default ':'. .lp menu_select_all Menu character accelerator to select all items in a menu. -Implemented by the X11 and tty ports. +Implemented by the Amiga, Gem, X11 and tty ports. Default '.'. .lp menu_select_page Menu character accelerator to select all items on this page of a menu. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default ','. .lp monsters Set the characters used to display monster classes (default @@ -1830,6 +1891,9 @@ Cannot be set with the `O' command. .lp msghistory The number of top line messages to save (and recall with ^P) (default 20). Cannot be set with the `O' command. +.lp msg_window +Use a screen-size window to show the previous messages with ^P instead of +showing them one at a time. (Currently implemented for tty only.) .lp "name " Set your character's name (defaults to your user name). You can also set your character's role by appending a dash and one or more letters of @@ -1868,7 +1932,8 @@ If true, always display your current inventory in a window. This only makes sense for windowing system interfaces that implement this feature. .lp pettype Specify the type of your initial pet, if you are playing a character class -that uses multiple types of pets. Possible values are ``cat'' and ``dog''. +that uses multiple types of pets; or choose to have no initial pet at all. +Possible values are ``cat'', ``dog'' and ``none''. Cannot be set with the `O' command. .lp pickup_burden When you pick up an item that would exceed this encumbrance @@ -1881,11 +1946,6 @@ Specify the object types to be picked up when is on. Default is all types. .lp prayconfirm Prompt for confirmation before praying (default on). -.lp preload_tiles -For the protected mode MSDOS version, control whether tiles -get pre-loaded into RAM at the start of the game. Doing so -enhances performance of the tile graphics, but uses more memory. (default on). -Cannot be set with the `O' command. .lp pushweapon Using the `w' (wield) command when already wielding something pushes the old item into your secondary weapon slot (default off). @@ -1919,6 +1979,9 @@ Show your approximate accumulated score on bottom line (default off). Suppress terminal beeps (default on). .lp sortpack Sort the pack contents by type when displaying inventory (default on). +.lp sparkle +Display a sparkly effect when a monster (including yourself) is hit by an +attack to which it is resistant (default on). .lp standout Boldface monsters and ``\fB--More--\fP'' (default off). .lp suppress_alert @@ -1978,6 +2041,95 @@ Select which windowing system to use, such as ``tty'' or ``X11'' (default depends on version). Cannot be set with the `O' command. .hn 2 +Window Port Customization options +.pg +Here are explanations of the various options that are +used to customize and change the characteristics of the +windowtype that you have chosen. +Character strings that are too long may be truncated. +Not all window ports will adjust for all settings listed +here. You can safely add any of these options to your config +file, and if the window port is capable of adjusting to +suit your preferences, it will attempt to do so. If it +can't it will silently ignore it. You can find out if an +option is supported by the window port that you are currently +using by checking to see if it shows up in the Options list. +Some options are dynamic and can be specified during the game +with the `O' command. +.lp align_message +Where to align or place the message window (top, bottom, left, or right) +.lp align_status +Where to align or place the status window (top, bottom, left, or right). +.lp ascii_map +NetHack should display an ascii character map if it can. +.lp color +NetHack should display color if it can for different monsters, +objects, and dungeon features +.lp eight_bit_tty +NetHack should pass eight-bit character values (for example, specified with the +.op traps +option) straight through to your terminal (default off). +.lp font_map +NetHack should use a font by the chosen name for the map window. +.lp font_menu +NetHack should use a font by the chosen name for menu windows. +.lp font_message +NetHack should use a font by the chosen name for the message window. +.lp font_status +NetHack should use a font by the chosen name for the status window. +.lp font_text +NetHack should use a font by the chosen name for text windows. +.lp font_size_map +NetHack should use this size font for the map window. +.lp font_size_menu +NetHack should use this size font for menu windows. +.lp font_size_message +NetHack should use this size font for the message window. +.lp font_size_status +NetHack should use this size font for the status window. +.lp font_size_text +NetHack should use this size font for text windows. +.lp hilite_pet +Visually distinguish pets from similar animals (default off). +The behavior of this option depends on the type of windowing you use. +In text windowing, text highlighting or inverse video is often used; +with tiles, generally displays a heart symbol near pets. +.lp large_font +NetHack should use a large font. +.lp map_mode +NetHack should display the map in the manner specified. +.lp player_selection +NetHack should pop up dialog boxes, or use prompts for character selection. +.lp popup_dialog +NetHack should pop up dialog boxes for input. +.lp preload_tiles +NetHack should preload tiles into memory. +For example, in the protected mode MSDOS version, control whether tiles +get pre-loaded into RAM at the start of the game. Doing so +enhances performance of the tile graphics, but uses more memory. (default on). +Cannot be set with the `O' command. +.lp scroll_margin +NetHack should scroll the display when the hero or cursor +is this number of cells away from the edge of the window. +.lp splash_screen +NetHack should display an opening splash screen when it starts up (default yes). +.lp tiled_map +NetHack should display a tiled map if it can. +.lp tile_file +Specify the name of an alternative tile file to override the default. +.lp tile_height +Specify the preferred height of each tile in a tile capable port. +.lp tile_width +Specify the preferred width of each tile in a tile capable port +.lp use_inverse +NetHack should display inverse when the game specifies it. +.lp vary_msgcount +NetHack should display this number of messages at a time in +the message window. +.lp windowcolors +NetHack should display windows with the specified foreground/background +colors if it can. +.hn 2 Configuring NetHack for Play by the Blind .pg NetHack can be set up to use only standard ASCII characters for making @@ -2010,9 +2162,9 @@ make the game accessible are: Disable IBMgraphics by commenting out this option. .lp menustyle:traditional This will assist in the interface to speech synthesizers. -.lp \!number_pad +.lp number_pad A lot of speech access programs use the number-pad to review the screen. -If this is the case, turn off the number_pad option and use the traditional +If this is the case, disable the number_pad option and use the traditional Rogue-like commands. .lp "Character graphics" Comment out all character graphics sets found near the bottom of the @@ -2182,30 +2334,59 @@ and with the help of \fBKevin Hugo\fP, added more features. Kevin later joined the DevTeam and incorporated the best of these ideas in NetHack 3.3. .pg -The 3.3 development team consisted of \fBMichael Allison\fP, \fBKen Arromdee\fP, -\fBDavid Cohrs\fP, \fBJessie Collet\fP, \fBSteve Creps\fP, \fBKevin Darcy\fP, \fBTimo Hakulinen\fP, -\fBKevin Hugo\fP, \fBSteve Linhart\fP, \fBDean Luick\fP, \fBPat Rankin\fP, \fBEric Smith\fP, \fBMike -Stephenson\fP, \fBJanet Walz\fP, and \fBPaul Winner\fP. -.pg -As with version 3.2, various people contributed to the game as a whole as +The final update to 3.2 was the bug fix release 3.2.3, which was released +simultaneously with 3.3.0 in December 1999 just in time for the Year 2000. +.pg +The 3.3 development team, consisting of \fBMichael Allison\fP, \fBKen Arromdee\fP, +\fBDavid Cohrs\fP, \fBJessie Collet\fP, \fBSteve Creps\fP, \fBKevin Darcy\fP, +\fBTimo Hakulinen\fP, \fBKevin Hugo\fP, \fBSteve Linhart\fP, \fBKen Lorber\fP, +\fBDean Luick\fP, \fBPat Rankin\fP, \fBEric Smith\fP, \fBMike Stephenson\fP, +\fBJanet Walz\fP, and \fBPaul Winner\fP, released 3.3.0 in +December 1999 and 3.3.1 in August of 2000. +.pg +Version 3.3 offered many firsts. It was the first version to separate race +and profession. The Elf class was removed in preference to an elf race, +and the races of dwarves, gnomes, and orcs made their first appearance in +the game alongside the familiar human race. Monk and Ranger roles joined +Archeologists, Barbarians, Cavemen, Healers, Knights, Priests, Rogues, Samurai, +Tourists, Valkyries and of course, Wizards. It was also the first version +to allow you to ride a steed, and was the first version to have a publicly +available web-site listing all the bugs that had been discovered. Despite +that constantly growing bug list, 3.3 proved stable enough to last for +more than a year and a half. +.pg +The 3.4 development team initially consisted of +\fBMichael Allison\fP, \fBKen Arromdee\fP, +\fBDavid Cohrs\fP, \fBJessie Collet\fP, \fBKevin Hugo\fP, \fBKen Lorber\fP, +\fBDean Luick\fP, \fBPat Rankin\fP, \fBMike Stephenson\fP, +\fBJanet Walz\fP, and \fBPaul Winner\fP, with \fB Warwick Allison\fP joining +just before the release of NetHack 3.4.0 in March 2002. +.pg +As with version 3.3, various people contributed to the game as a whole as well as supporting ports on the different platforms that NetHack runs on: .pg -\fBPat Rankin\fP maintained 3.3 for VMS. +\fBPat Rankin\fP maintained 3.4 for VMS. .pg -\fBMichael Allison\fP maintained NetHack 3.3 for the MS-DOS platform. \fBPaul Winner\fP +\fBMichael Allison\fP maintained NetHack 3.4 for the MS-DOS platform. \fBPaul Winner\fP and \fBYitzhak Sapir\fP provided encouragement. .pg \fBDean Luick\fP, \fBMark Modrall\fP, and \fBKevin Hugo\fP maintained and enhanced the -Macintosh port of 3.3. +Macintosh port of 3.4. +.pg +\fBMichael Allison\fP, \fBDavid Cohrs\fP, \fBAlex Kompel\fP, \fBDion Nicolaas\fP, and +\fBYitzhak Sapir\fP maintained and enhanced 3.4 for the Microsoft Windows platform. +\fBAlex Kompel\fP contributed a new graphical interface for the Windows port. .pg -\fBMichael Allison\fP maintained and enhanced 3.3 for the Microsoft Windows NT platform. +\fBRon Van Iwaarden\fP maintained 3.4 for OS/2. .pg -\fBRon Van Iwaarden\fP took over responsibility for the OS/2 port. +\fBJanne Salmijarvi\fP and \fBTeemu Suikki\fP maintained and +enhanced the Amiga port of 3.4 after \fBJanne Salmijarvi\fP resurrected +it for 3.3.1. .pg -The Amiga port of NetHack was resurrected for 3.3.1 by \fBJanne Salmijarvi\fP. +\fBChristian ``Marvin'' Bressler\fP maintained 3.4 for the Atari after he +resurrected it for 3.3.1. .pg -The Atari port of NetHack was resurrected for 3.3.1 by \fBChristian ``Marvin'' -Bressler\fP. +There is a NetHack web site maintained by \fBKen Lorber\fP at http://www.nethack.org/. .pg - - - - - - - - - - .pg @@ -2219,31 +2400,34 @@ in this, the list of Dungeoneers: center; c c c. .\"TABLE_START -Adam Aronow Irina Rempt-Drijfhout Mike Gallop -Andy Church Izchak Miller Mike Passaretti -Andy Swanson Janet Walz Mike Stephenson -Ari Huttunen Janne Salmijarvi Norm Meluch -Barton House Jean-Christophe Collet Olaf Seibert -Benson I. Margulies Jochen Erwied Pat Rankin -Bill Dyer John Kallen Paul Winner -Boudewijn Waijers John Rupley Pierre Martineau -Bruce Cox John S. Bien Ralf Brown -Bruce Holloway Johnny Lee Richard Addison -Bruce Mewborne Jon W{tte Richard Beigel -Carl Schelin Jonathan Handler Richard P. Hughey -Chris Russo Joshua Delahunty Rob Menke -David Cohrs Keizo Yamamoto Robin Johnson -David Damerell Ken Arromdee Roland McGrath -David Gentzel Ken Lorber Ron Van Iwaarden -David Hairston Ken Washikita Ronnen Miller -Dean Luick Kevin Darcy Ross Brown -Del Lamb Kevin Hugo Sascha Wostmann -Deron Meranda Kevin Sitze Scott R. Turner -Dylan O'Donnell Kevin Smolkowski Stephen Spackman -Eric Backus Kevin Sweet Stephen White -Eric Hendrickson Lars Huttar Steve Creps -Eric R. Smith Mark Gooderum Steve Linhart -Eric S. Raymond Mark Modrall Steve VanDevender +Adam Aronow Helge Hafting Mike Engber +Alex Kompel Irina Rempt-Drijfhout Mike Gallop +Andreas Dorn Izchak Miller Mike Passaretti +Andy Church J. Ali Harlow Mike Stephenson +Andy Swanson Janet Walz Norm Meluch +Ari Huttunen Janne Salmijarvi Olaf Seibert +Barton House Jean-Christophe Collet Pat Rankin +Benson I. Margulies Jochen Erwied Paul Winner +Bill Dyer John Kallen Pierre Martineau +Boudewijn Waijers John Rupley Ralf Brown +Bruce Cox John S. Bien Richard Addison +Bruce Holloway Johnny Lee Richard Beigel +Bruce Mewborne Jon W{tte Richard P. Hughey +Carl Schelin Jonathan Handler Rob Menke +Chris Russo Joshua Delahunty Robin Johnson +David Cohrs Keizo Yamamoto Roland McGrath +David Damerell Ken Arnold Ron Van Iwaarden +David Gentzel Ken Arromdee Ronnen Miller +David Hairston Ken Lorber Ross Brown +Dean Luick Ken Washikita Sascha Wostmann +Del Lamb Kevin Darcy Scott Bigham +Deron Meranda Kevin Hugo Scott R. Turner +Dion Nicolaas Kevin Sitze Stephen Spackman +Dylan O'Donnell Kevin Smolkowski Stephen White +Eric Backus Kevin Sweet Steve Creps +Eric Hendrickson Lars Huttar Steve Linhart +Eric R. Smith Mark Gooderum Steve VanDevender +Eric S. Raymond Mark Modrall Teemu Suikki Erik Andersen Marvin Bressler Tim Lennan Frederick Roeber Matthew Day Timo Hakulinen Gil Neiger Merlyn LeRoy Tom Almy @@ -2251,7 +2435,6 @@ Greg Laskin Michael Allison Tom West Greg Olson Michael Feir Warren Cheung Gregg Wonderly Michael Hamel Warwick Allison Hao-yang Wang Michael Sokolov Yitzhak Sapir -Helge Hafting Mike Engber .\"TABLE_END Do not delete this line. .TE .ed diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 0225908..0729c62 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -34,12 +34,12 @@ %.mt \title{\LARGE A Guide to the Mazes of Menace:\\ -\Large Guidebook for {\it NetHack\/} 3.3} +\Large Guidebook for {\it NetHack\/}} %.au \author{Eric S. Raymond\\ -(Extensively edited and expanded for 3.0 by Mike Threepoint)} -\date{August 2, 2000} +(Extensively edited and expanded for 3.4)} +\date{March 20, 2002} \maketitle @@ -274,6 +274,7 @@ \section{What do all those things on the screen mean?} understand what {\it NetHack\/} is doing with the screen. The {\it NetHack\/} screen replaces the ``You see \ldots'' descriptions of text adventure games. Figure 1 is a sample of what a {\it NetHack\/} screen might look like. +The way the screen looks for you depends on your platform. \vbox{ \begin{verbatim} @@ -288,7 +289,7 @@ \section{What do all those things on the screen mean?} - Player the Rambler St:12 Dx:7 Co:18 In:11 Wi:9 Ch:15 Neutral + Player the Rambler St:12 Dx:7 Co:18 In:11 Wi:9 Ch:15 Neutral Dlvl:1 $:0 HP:9(12) Pw:3(3) AC:10 Exp:1/19 T:257 Weak \end{verbatim} \begin{center} @@ -315,8 +316,10 @@ \subsection*{The status lines (bottom)} %.lp \item[\bb{Strength}] A measure of your character's strength; one of your six basic -attributes. Your attributes can range from 3 to 18 inclusive -(occasionally you may get super-strengths of the form 18/xx). The +attributes. A human character's attributes can range from 3 to 18 inclusive; +non-humans may exceed these limits +(occasionally you may get super-strengths of the form 18/xx, and magic can +also cause attributes to exceed the normal limits). The higher your strength, the stronger you are. Strength affects how successfully you perform physical tasks, how much damage you do in combat, and how much loot you can carry. @@ -503,6 +506,11 @@ \subsection*{The map (rest of the screen)} Letters and certain other symbols represent the various inhabitants of the Mazes of Menace. Watch out, they can be nasty and vicious. Sometimes, however, they can be helpful. +%.lp +\item[\tb{I}] +This marks the last known location of an invisible or otherwise unseen +monster. Note that the monster could have moved. The `F' and `m' commands +may be useful here. \elist %.pg @@ -581,13 +589,14 @@ \section{Commands} Tell what a command does. %.lp \item[\tb{<}] -Go up to the previous level (if you are on the staircase or ladder). +Go up to the previous level (if you are on a staircase or ladder). %.lp \item[\tb{>}] -Go down to the next level (if you are on the staircase or ladder). +Go down to the next level (if you are on a staircase or ladder). %.lp \item[\tb{[yuhjklbn]}] -Go one step in the direction indicated (see Figure 2). If you can sense +Go one step in the direction indicated (see Figure 2). If you sense +or remember a monster there, you will fight the monster instead. Only these one-step movement commands cause you to fight monsters; the others (below) are ``safe.'' @@ -627,6 +636,12 @@ \section{Commands} Prefix: Same as `{\tt g}', but forking of corridors is not considered interesting. %.lp +\item[\tb{_}] +Travel to a map location via a shortest-path algorithm. Stops on most of +the same conditions as the `G' command does. For ports with mouse +support, the command is also invoked when a mouse-click takes place on a +location further than 1 cell away from the current position. +%.lp \item[\tb{.}] Rest, do nothing for one turn. %.lp @@ -797,7 +812,7 @@ \section{Commands} Zap a wand. To aim at yourself, use `{\tt .}' for the direction. %.lp \item[\tb{Z}] -Zap (cast) a spell. +Zap (cast) a spell. To cast at yourself, use `{\tt .}' for the direction. %.lp \item[\tb{\^{}Z}] Suspend the game (UNIX versions with job control only). @@ -868,7 +883,8 @@ \section{Commands} Talk to someone. %.lp \item[\tb{\#conduct}] -List which challenges you have adhered to. +List which challenges you have adhered to. See the section below entitled +``Conduct'' for details. %.lp \item[\tb{\#dip}] Dip an object into something. @@ -908,7 +924,7 @@ \section{Commands} Ride (or stop riding) a monster. %.lp \item[\tb{\#rub}] -Rub a lamp. +Rub a lamp or a stone. %.lp \item[\tb{\#sit}] Sit down. @@ -945,9 +961,12 @@ \section{Commands} In {\it NT, OS/2, {\rm and} PC NetHack}, the `Alt' key can be used in this fashion. \blist{} +%.lp +\item[\tb{M-?}] +{\tt\#?} (not supported by all platforms) %.lp \item[\tb{M-2}] -{\tt\#twoweapon} +{\tt\#twoweapon} (unless the {\it number\_pad\/} option is enabled) %.lp \item[\tb{M-a}] {\tt\#adjust} @@ -1011,6 +1030,9 @@ \section{Commands} \nd If the {\it number\_pad\/} option is on, some additional letter commands are available: \blist{} +%.lp +\item[\tb{h}] +Help menu: display one of several help texts available, like ``{\tt ?}''. %.lp \item[\tb{j}] Jump to another location. Same as ``{\tt \#jump}'' or ``{\tt M-j}''. @@ -1023,7 +1045,7 @@ \section{Commands} from a horse standing next to you. Same as ``{\tt \#loot}'' or ``{\tt M-l}''. %.lp \item[\tb{N}] -Name an object or type of object. Same as ``{\tt \#name}'' or ``{\tt M-N}''. +Name an object or type of object. Same as ``{\tt \#name}'' or ``{\tt M-n}''. %.lp \item[\tb{u}] Untrap a trap, door, or chest. Same as ``{\tt \#untrap}'' or ``{\tt M-u}''. @@ -1160,6 +1182,16 @@ \subsection*{Fighting} you attack them. Some of them are very dangerous when angered. Remember: discretion is the better part of valor. +%.pg +If you can't see a monster (if it is invisible, or if you are blinded), +the symbol `I' will be shown when you learn of its presence. +If you attempt to walk into it, you will try to fight it just like +a monster that you can see; of course, +if the monster has moved, you will attack empty air. If you guess +that the monster has moved and you don't wish to fight, you can use the `m' +command to move without fighting; likewise, if you don't remember a monster +but want to try fighting anyway, you can use the `F' command. + %.hn 2 \subsection*{Your pet} @@ -1344,7 +1376,7 @@ \subsection*{Weapons (`{\tt )}')} And if you have proficiency in the ``two weapon combat'' skill, you may wield both primary and secondary weapons simultaneously; use the `{\tt \#twoweapon}' extended command to engage or disengage that. Only -some types of characters (barbarians, for instance), have the necessary +some types of characters (barbarians, for instance) have the necessary skill available. Even with that skill, using two weapons at once incurs a penalty in the chance to hit your target compared to using just one weapon at a time. @@ -1357,7 +1389,7 @@ \subsection*{Weapons (`{\tt )}')} %.pg Those of you in the audience who are AD\&D players, be aware that each -weapon which exists in AD\&D does roughly the same damage to monsters in +weapon which existed in AD\&D does roughly the same damage to monsters in {\it NetHack}. Some of the more obscure weapons (such as the % {\it aklys}, {\it lucern hammer}, and {\it bec-de-corbin\/}) are defined in an appendix to {\it Unearthed Arcana}, an AD\&D supplement. @@ -1392,23 +1424,26 @@ \subsection*{Throwing and shooting} quiver when the inventory slot used for `{\tt Q}' runs out. %.pg -Some characters will throw multiple items in a single action. Rangers, -for instance, or anyone who achieves a high level of proficiency in -the relevant weapon skill (in bow skill if you're wielding one to -shoot arrows, or in sling skill if you're wielding one to shoot stones). -There is little you can do -to control this; if {\it NetHack\/} decides that you'll be shooting 3 arrows -on the current shot, then three arrows will travel in the direction -you've indicated, even if the first or second succeeds in killing the -target. You can explicitly limit the number of shots by using a numeric -prefix before the `{\tt t}' or `{\tt f}' command. +Some characters have the ability to fire a volley of multiple items in a +single turn. Knowing how to load several rounds of ammunition at +once---or hold several missiles in your hand---and still hit a +target is not an easy task. Rangers are among those who are adept +at this task, as are those with a high level of proficiency in the +relevant weapon skill (in bow skill if you're wielding one to +shoot arrows, in crossbow skill if you're wielding one to shoot bolts, +or in sling skill if you're wielding one to shoot stones). +The number of items that the character has a chance to fire varies from +turn to turn. You can explicitly limit the number of shots by using a +numeric prefix before the `{\tt t}' or `{\tt f}' command. For example, ``{\tt 2f}'' (or ``{\tt n2f}'' if using {\it number\_pad\/} mode) would ensure that at most 2 arrows are shot -even if {\it NetHack\/} decides that your skill warrants 3. If you specify +even if you could have fired 3. If you specify a larger number than would have been shot (``{\tt 4f}'' in this example), you'll just end up shooting the same number (3, here) as if no limit -had been specified. +had been specified. Once the volley is in motion, all of the items +will travel in the same direction; if the first ones kill a monster, +the others can still continue beyond that spot. %.hn 3 \subsection*{Weapon proficiency} @@ -1663,10 +1698,18 @@ \subsection*{Spellbooks (`{\tt +}')} %.pg Casting a spell calls forth magical energies and focuses them with -your naked mind. Releasing the magical energy releases some of your -memory of the spell with it. Each time you cast a spell, your -familiarity with it will dwindle, until you eventually forget the -details completely and must relearn it. +your naked mind. Some of the magical energy released comes from within +you, and casting several spells in a row may tire you. +Casting of spells also requires practice. With practice, your +skill in each category of spell casting will improve. Over time, however, +your memory of each spell will dim, and you will need to relearn it. + +%.pg +Some spells are +directional---you must give a direction in which to cast them. You can also +cast them at yourself (just give a `{\tt .}' or `{\tt s}' for the direction). +Be warned, however, for this is often unwise. Other spells are +nondirectional---they don't require a direction. %.pg Just as weapons are divided into groups in which a character can become @@ -1682,8 +1725,9 @@ \subsection*{Spellbooks (`{\tt +}')} %.pg The command to read a spellbook is the same as for scrolls, `{\tt r}' -(read). The `{\tt +}' command lists your current spells and the number of -spell points they require. The `{\tt Z}' (cast) command casts a spell. +(read). The `{\tt +}' command lists your current spells, their levels, +categories, and chances for failure. +The `{\tt Z}' (cast) command casts a spell. %.hn 2 \subsection*{Tools (`{\tt (}')} @@ -1940,10 +1984,11 @@ \subsection*{Using a configuration file} Any line in the configuration file starting with ``{\tt OPTIONS=}'' may be filled out with options in the same syntax as in NETHACKOPTIONS. Any line starting with ``{\tt DUNGEON=}'', ``{\tt EFFECTS=}'', -``{\tt MONSTERS=}'', ``{\tt OBJECTS=}'', or ``{\tt TRAPS=}'' +``{\tt MONSTERS=}'', ``{\tt OBJECTS=}'', ``{\tt TRAPS=}'', +or ``{\tt BOULDER=}'' is taken as defining the corresponding {\it dungeon}, -{\it effects}, {\it monsters}, {\it objects}, or -{\it traps\/} option in a different syntax, +{\it effects}, {\it monsters}, {\it objects}, {\it traps\/} or +{\it boulder\/} option in a different syntax, a sequence of decimal numbers giving the character position in the current font to be used in displaying each entry. Such a sequence can be continued to multiple lines by putting a @@ -1971,6 +2016,10 @@ \subsection*{Customization options} The default is to randomly pick an appropriate alignment. Cannot be set with the `{\tt O}' command. %.lp +\item[\ib{autodig}] +Automatically dig if you are wielding a digging tool and moving into a place +that can be dug (default false). +%.lp \item[\ib{autopickup}] Automatically pick up things onto which you move (default on). %.Ip @@ -1988,6 +2037,9 @@ \subsection*{Customization options} (allowing the use of arrow keys to move) on machines with an IBM PC compatible BIOS ROM (default off, {\it OS/2, PC\/ {\rm and} ST NetHack\/} only). %.lp +\item[\ib{boulder}] +Set the character used to display boulders (default is rock class symbol). +%.lp \item[\ib{catname}] Name your starting cat (ex.\ ``{\tt catname:Morris}''). Cannot be set with the `{\tt O}' command. @@ -2008,10 +2060,6 @@ \subsection*{Customization options} on the partition used for your save and level files. Only applies when MFLOPPY was defined during compilation. %.lp -\item[\ib{color}] -Use color for different monsters, objects, and dungeon features -(default on for microcomputers). -%.lp \item[\ib{confirm}] Have user confirm attacks on pets, shopkeepers, and other peaceable creatures (default on). @@ -2025,13 +2073,40 @@ \subsection*{Customization options} even if you override the selections with your own graphics strings. %.lp \item[\ib{disclose}] -Offer to disclose various information when the game ends (default all). -The possibilities are identifying your inventory (`{\tt i}'), -disclosing your attributes (`{\tt a}'), summarizing monsters that have been -vanquished (`{\tt v}'), listing monster species that have been -genocided (`{\tt g}'), and displaying your conduct (`{\tt c}'). +Controls options for disclosing various information when the game ends (defaults +to all possibilities being disclosed). +The possibilities are: + +%.sd +%.si +{\tt i} --- disclose your inventory.\\ +{\tt a} --- disclose your attributes.\\ +{\tt v} --- summarize monsters that have been vanquished.\\ +{\tt g} --- list monster species that have been genocided.\\ +{\tt c} --- display your conduct. +%.ei +%.ed + +Each disclosure possibility can optionally be preceded by a prefix which +let you refine how it behaves. Here are the valid prefixes: + +%.sd +%.si +{\tt y} --- prompt you and default to yes on the prompt.\\ +{\tt n} --- prompt you and default to no on the prompt.\\ +{\tt +} --- disclose it without prompting.\\ +{\tt -} --- do not disclose it and do not prompt. +%.ei +%.ed + +(ex.\ ``{\tt disclose:yi na +v -g -c}'') +The example sets {\it inventory\/} to {\it prompt\/} and default to {\it yes\/}, +{\it attributes\/} to {\it prompt\/} and default to {\it no\/}, +{\it vanquished\/} to {\it disclose without prompting\/}, +{\it genocided\/} to {\it not disclose\/} and not to {\it prompt\/}, and +{\it conduct\/} to {\it not disclose\/} and not to {\it prompt\/}. Note that the vanquished monsters list includes all monsters killed by -traps and each other as well as by you. +traps and each other as well as by you. %.lp \item[\ib{dogname}] Name your starting dog (ex.\ ``{\tt dogname:Fang}''). @@ -2095,11 +2170,6 @@ \subsection*{Customization options} Cannot be set with the `{\tt O}' command. %.lp -\item[\ib{eight\_bit\_tty}] -Pass eight-bit character values (for example, specified with the {\it -traps \/} option) straight through to your terminal (default off). -Only applies to the tty port. -%.lp \item[\ib{extmenu}] Changes the extended commands interface to pop-up a menu of available commands. It is keystroke compatible with the traditional interface except that it does @@ -2136,11 +2206,6 @@ \subsection*{Customization options} interrupted with the ``{\tt More info?}'' prompt, but it also means that you might miss some interesting and/or important information. %.lp -\item[\ib{hilite\_pet}] -Visually distinguish pets from similar animals (default off). -In text windowing, use text highlighting when color is turned off; -with X tiles, display a heart symbol near pets. -%.lp \item[\ib{horsename}] Name your starting horse (ex.\ ``{\tt horsename:Trigger}''). Cannot be set with the `{\tt O}' command. @@ -2164,7 +2229,7 @@ \subsection*{Customization options} character as lit (default off). %.lp \item[\ib{mail}] -Enable mail delivery during the game. +Enable mail delivery during the game (default on). %.lp \item[\ib{male}] An obsolete synonym for ``{\tt gender:male}''. Cannot be set with the @@ -2185,47 +2250,47 @@ \subsection*{Customization options} objects for selection. \item[\ib{menu\_deselect\_all}] Menu character accelerator to deselect all items in a menu. -Implemented by the X11 and tty ports. +Implemented by the Amiga, Gem, X11 and tty ports. Default `-'. \item[\ib{menu\_deselect\_page}] Menu character accelerator deselect all items on this page of a menu. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default `\verb+\+'. \item[\ib{menu\_first\_page}] Menu character accelerator to jump to the first page in a menu. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default `\verb+^+'. \item[\ib{menu\_invert\_all}] Menu character accelerator to invert all items in a menu. -Implemented by the X11 and tty ports. +Implemented by the Amiga, Gem, X11 and tty ports. Default `@'. \item[\ib{menu\_invert\_page}] Menu character accelerator to invert all items on this page of a menu. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default `\verb+~+'. \item[\ib{menu\_last\_page}] Menu character accelerator to jump to the last page in a menu. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default `\verb+|+'. \item[\ib{menu\_next\_page}] Menu character accelerator to goto the next menu page. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default `\verb+>+'. \item[\ib{menu\_previous\_page}] Menu character accelerator to goto the previous menu page. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default `\verb+<+'. \item[\ib{menu\_search}] Menu character accelerator to search for a menu item. -Implemented only by the X11 port. +Implemented by the Amiga, Gem and X11 ports. Default `:'. \item[\ib{menu\_select\_all}] Menu character accelerator to select all items in a menu. -Implemented by the X11 and tty ports. +Implemented by the Amiga, Gem, X11 and tty ports. Default `.'. \item[\ib{menu\_select\_page}] Menu character accelerator to select all items on this page of a menu. -Implemented only by the tty port. +Implemented by the Amiga, Gem and tty ports. Default `,'. %.lp \item[\ib{monsters}] @@ -2261,6 +2326,10 @@ \subsection*{Customization options} The number of top line messages to save (and recall with `{\tt \^{}P}') (default 20). Cannot be set with the `{\tt O}' command. %.lp +\item[\ib{msg\_window}] +Use a screen-size window to show the previous messages with `{\tt \^{}P}' +instead of showing them one at a time. (Currently implemented for tty only.) +%.lp \item[\ib{name}] Set your character's name (defaults to your user name). You can also set your character's role by appending a dash and one or more letters of @@ -2303,8 +2372,8 @@ \subsection*{Customization options} %.lp \item[\ib{pettype}] Specify the type of your initial pet, if you are playing a character class -that uses multiple types of pets. Possible values are ``{\tt cat}'' -and ``{\tt dog}''. +that uses multiple types of pets; or choose to have no initial pet at all. +Possible values are ``{\tt cat}'', ``{\tt dog}'' and ``{\tt none}''. Cannot be set with the `{\tt O}' command. %.Ip \item[\ib{pickup\_burden}] @@ -2320,12 +2389,6 @@ \subsection*{Customization options} \item[\ib{prayconfirm}] Prompt for confirmation before praying (default on). %.lp -\item[\ib{preload\_tiles}] -For the protected mode MSDOS version, control whether tiles -get pre-loaded into RAM at the start of the game. Doing so -enhances performance of the tile graphics, but uses more memory. (default on). -Cannot be set with the `{\tt O}' command. -%.lp \item[\ib{pushweapon}] Using the `w' (wield) command when already wielding something pushes the old item into your secondary weapon slot (default off). @@ -2373,6 +2436,10 @@ \subsection*{Customization options} \item[\ib{standout}] Boldface monsters and ``{\tt --More--}'' (default off). %.lp +\item[\ib{sparkle}] +Display a sparkly effect when a monster (including yourself) is hit by an +attack to which it is resistant (default on). +%.lp \item[\ib{suppress\_alert}] This option may be set to a NetHack version level to suppress alert notification messages about feature changes for that @@ -2438,6 +2505,128 @@ \subsection*{Customization options} Cannot be set with the `{\tt O}' command. \elist +%.hn 2 +\subsection*{Window Port Customization options} + +%.pg +Here are explanations of the various options that are +used to customize and change the characteristics of the +windowtype that you have chosen. +Character strings that are too long may be truncated. +Not all window ports will adjust for all settings listed +here. You can safely add any of these options to your +config file, and if the window port is capable of adjusting +to suit your preferences, it will attempt to do so. If it +can't it will silently ignore it. You can find out if an +option is supported by the window port that you are currently +using by checking to see if it shows up in the Options list. +Some options are dynamic and can be specified during the game +with the `{\tt O}' command. + +\blist{} +%.lp +\item[\ib{align\_message}] + Where to align or place the message window (top, bottom, left, or right) +%.lp +\item[\ib{align\_status}] + Where to align or place the status window (top, bottom, left, or right). +%.lp +\item[\ib{ascii\_map}] +NetHack should display an ascii map if it can. +%.lp +\item[\ib{color}] +NetHack should display color if it can for different monsters, +objects, and dungeon features +%.lp +\item[\ib{eight\_bit\_tty}] +Pass eight-bit character values (for example, specified with the {\it +traps \/} option) straight through to your terminal (default off). +%.lp +\item[\ib{font\_map}] +NetHack should use a font by the chosen name for the map window. +%.lp +\item[\ib{font\_menu}] +NetHack should use a font by the chosen name for menu windows. +%.lp +\item[\ib{font\_message}] +NetHack should use a font by the chosen name for the message window. +%.lp +\item[\ib{font\_status}] +NetHack should use a font by the chosen name for the status window. +%.lp +\item[\ib{font\_text}] +NetHack should use a font by the chosen name for text windows. +%.lp +\item[\ib{font\_size\_map}] +NetHack should use this size font for the map window. +%.lp +\item[\ib{font\_size\_menu}] +NetHack should use this size font for menu windows. +%.lp +\item[\ib{font\_size\_message}] +NetHack should use this size font for the message window. +%.lp +\item[\ib{font\_size\_status}] +NetHack should use this size font for the status window. +%.lp +\item[\ib{font\_size\_text}] +NetHack should use this size font for text windows. +%.lp +\item[\ib{hilite\_pet}] +Visually distinguish pets from similar animals (default off). +The behavior of this option depends on the type of windowing you use. +In text windowing, text highlighting or inverse video is often used; +with tiles, generally displays a heart symbol near pets. +%.lp +\item[\ib{large\_font}] +NetHack should use a large font. +%.lp +\item[\ib{map\_mode}] +NetHack should display the map in the manner specified. +%.lp +\item[\ib{player\_selection}] +NetHack should pop up dialog boxes or use prompts for character selection. +%.lp +\item[\ib{popup\_dialog}] +NetHack should pop up dialog boxes for input. +%.lp +\item[\ib{preload\_tiles}] +NetHack should preload tiles into memory. +For example, in the protected mode MSDOS version, control whether tiles +get pre-loaded into RAM at the start of the game. Doing so +enhances performance of the tile graphics, but uses more memory. (default on). +Cannot be set with the `{\tt O}' command. +%.lp +\item[\ib{scroll\_margin}] +NetHack should scroll the display when the hero or cursor +is this number of cells away from the edge of the window. +%.lp +\item[\ib{splash\_screen}] +NetHack should display an opening splash screen when it starts up (default yes). +%.lp +\item[\ib{tiled\_map}] +NetHack should display a tiled map if it can. +%.lp +\item[\ib{tile\_file}] +Specify the name of an alternative tile file to override the default. +%.lp +\item[\ib{tile\_height}] +Specify the preferred height of each tile in a tile capable port. +%.lp +\item[\ib{tile\_width}] +Specify the preferred width of each tile in a tile capable port +%.lp +\item[\ib{use\_inverse}] +NetHack should display inverse when the game specifies it. +%.lp +\item[\ib{vary\_msgcount}] +NetHack should display this number of messages at a time in the message window. +%.lp +\item[\ib{windowcolors}] +NetHack should display windows with the specified foreground/background +colors if it can. +\elist + %.hn 2 \subsection*{Configuring NetHack for Play by the Blind} @@ -2476,9 +2665,9 @@ \subsection*{Configuring NetHack for Play by the Blind} \item[\ib{menustyle:traditional}] This will assist in the interface to speech synthesizers. %.lp -\item[\ib{!number\_pad}] +\item[\ib{number\_pad}] A lot of speech access programs use the number-pad to review the screen. -If this is the case, turn off the number\_pad option and use the traditional +If this is the case, disable the number\_pad option and use the traditional Rogue-like commands. %.lp \item[\ib{Character graphics}] @@ -2703,49 +2892,85 @@ \section{Credits} %.pg \medskip -The 3.3 development team consisted of {\it Michael Allison}, {\it Ken Arromdee}, -{\it David Cohrs}, {\it Jessie Collet}, {\it Steve Creps}, {\it Kevin Darcy}, -{\it Timo Hakulinen}, -{\it Kevin Hugo}, {\it Steve Linhart}, {\it Dean Luick}, {\it Pat Rankin}, -{\it Eric Smith}, {\it Mike Stephenson}, {\it Janet Walz}, and {\it Paul Winner}. +The final update to 3.2 was the bug fix release 3.2.3, which was released +simultaneously with 3.3.0 in December 1999 just in time for the Year 2000. %.pg \medskip -As with version 3.2, various people contributed to the game as a whole as +The 3.3 development team, consisting of {\it Michael Allison}, {\it Ken Arromdee}, +{\it David Cohrs}, {\it Jessie Collet}, {\it Steve Creps}, {\it Kevin Darcy}, +{\it Timo Hakulinen}, {\it Kevin Hugo}, {\it Steve Linhart}, {\it Ken Lorber}, +{\it Dean Luick}, {\it Pat Rankin}, {\it Eric Smith}, {\it Mike Stephenson}, +{\it Janet Walz}, and {\it Paul Winner}, released 3.3.0 in +December 1999 and 3.3.1 in August of 2000. + +%.pg +\medskip +Version 3.3 offered many firsts. It was the first version to separate race +and profession. The Elf class was removed in preference to an elf race, +and the races of dwarves, gnomes, and orcs made their first appearance in +the game alongside the familiar human race. Monk and Ranger roles joined +Archeologists, Barbarians, Cavemen, Healers, Knights, Priests, Rogues, Samurai, +Tourists, Valkyries and of course, Wizards. It was also the first version +to allow you to ride a steed, and was the first version to have a publicly +available web-site listing all the bugs that had been discovered. Despite +that constantly growing bug list, 3.3 proved stable enough to last for +more than a year and a half. + +%.pg +\medskip +The 3.4 development team initially consisted of +{\it Michael Allison}, {\it Ken Arromdee}, +{\it David Cohrs}, {\it Jessie Collet}, {\it Kevin Hugo}, {\it Ken Lorber}, +{\it Dean Luick}, {\it Pat Rankin}, {\it Mike Stephenson}, +{\it Janet Walz}, and {\it Paul Winner}, with {\it Warwick Allison} joining +just before the release of NetHack 3.4.0 in March 2002. + +%.pg +\medskip +As with version 3.3, various people contributed to the game as a whole as well as supporting ports on the different platforms that {\it NetHack\/} runs on: %.pg \medskip -\nd{\it Pat Rankin} maintained 3.3 for VMS. +\nd{\it Pat Rankin} maintained 3.4 for VMS. %.pg \medskip -\nd {\it Michael Allison} maintained NetHack 3.3 for the MS-DOS platform. +\nd {\it Michael Allison} maintained NetHack 3.4 for the MS-DOS platform. {\it Paul Winner} and {\it Yitzhak Sapir} provided encouragement. %.pg \medskip \nd {\it Dean Luick}, {\it Mark Modrall}, and {\it Kevin Hugo} maintained and -enhanced the Macintosh port of 3.3. +enhanced the Macintosh port of 3.4. + +%.pg +\medskip +\nd {\it Michael Allison}, {\it David Cohrs}, {\it Alex Kompel}, {\it Dion Nicolaas}, and +{\it Yitzhak Sapir} maintained and enhanced 3.4 for the Microsoft Windows platform. +{\it Alex Kompel} contributed a new graphical interface for the Windows port. %.pg \medskip -\nd {\it Michael Allison} maintained and enhanced 3.3 for the Microsoft Windows NT platform. +\nd {\it Ron Van Iwaarden} maintained 3.4 for OS/2. %.pg \medskip -\nd {\it Ron Van Iwaarden} took over responsibility for the OS/2 port. +\nd {\it Janne Salmij\"{a}rvi} and {\it Teemu Suikki} maintained +and enhanced the Amiga port of 3.4 after {\it Janne Salmij\"{a}rvi} resurrected +it for 3.3.1. %.pg \medskip -\nd The Amiga port of NetHack was resurrected for 3.3.1 by {\it Janne -Salmij\"{a}rvi}. +\nd {\it Christian ``Marvin'' Bressler} maintained 3.4 for the Atari after he +resurrected it for 3.3.1. %.pg \medskip -\nd The Atari port of NetHack was resurrected for 3.3.1 by {\it Christian -``Marvin'' Bressler}. +\nd There is a NetHack web site maintained by {\it Ken Lorber} at +http:{\tt /}{\tt /}www.nethack.org{\tt /}. %.pg \bigskip @@ -2758,39 +2983,41 @@ \section{Credits} \begin{center} \begin{tabular}{lll} %TABLE_START -Adam Aronow & Irina Rempt-Drijfhout & Mike Gallop\\ -Andy Church & Izchak Miller & Mike Passaretti\\ -Andy Swanson & Janet Walz & Mike Stephenson\\ -Ari Huttunen & Janne Salmij\"{a}rvi & Norm Meluch\\ -Barton House & Jean-Christophe Collet & Olaf Seibert\\ -Benson I. Margulies & Jochen Erwied & Pat Rankin\\ -Bill Dyer & John Kallen & Paul Winner\\ -Boudewijn Waijers & John Rupley & Pierre Martineau\\ -Bruce Cox & John S. Bien & Ralf Brown\\ -Bruce Holloway & Johnny Lee & Richard Addison\\ -Bruce Mewborne & Jon W\{tte & Richard Beigel\\ -Carl Schelin & Jonathan Handler & Richard P. Hughey\\ -Chris Russo & Joshua Delahunty & Rob Menke\\ -David Cohrs & Keizo Yamamoto & Robin Johnson\\ -David Damerell & Ken Arromdee & Roland McGrath\\ -David Gentzel & Ken Lorber & Ron Van Iwaarden\\ -David Hairston & Ken Washikita & Ronnen Miller\\ -Dean Luick & Kevin Darcy & Ross Brown\\ -Del Lamb & Kevin Hugo & Sascha Wostmann\\ -Deron Meranda & Kevin Sitze & Scott R. Turner\\ -Dylan O'Donnell & Kevin Smolkowski & Stephen Spackman\\ -Eric Backus & Kevin Sweet & Stephen White\\ -Eric Hendrickson & Lars Huttar & Steve Creps\\ -Eric R. Smith & Mark Gooderum & Steve Linhart\\ -Eric S. Raymond & Mark Modrall & Steve VanDevender\\ +Adam Aronow & Helge Hafting & Mike Engber\\ +Alex Kompel & Irina Rempt-Drijfhout & Mike Gallop\\ +Andreas Dorn & Izchak Miller & Mike Passaretti\\ +Andy Church & J. Ali Harlow & Mike Stephenson\\ +Andy Swanson & Janet Walz & Norm Meluch\\ +Ari Huttunen & Janne Salmij\"{a}rvi & Olaf Seibert\\ +Barton House & Jean-Christophe Collet & Pat Rankin\\ +Benson I. Margulies & Jochen Erwied & Paul Winner\\ +Bill Dyer & John Kallen & Pierre Martineau\\ +Boudewijn Waijers & John Rupley & Ralf Brown\\ +Bruce Cox & John S. Bien & Richard Addison\\ +Bruce Holloway & Johnny Lee & Richard Beigel\\ +Bruce Mewborne & Jon W\{tte & Richard P. Hughey\\ +Carl Schelin & Jonathan Handler & Rob Menke\\ +Chris Russo & Joshua Delahunty & Robin Johnson\\ +David Cohrs & Keizo Yamamoto & Roland McGrath\\ +David Damerell & Ken Arnold & Ron Van Iwaarden\\ +David Gentzel & Ken Arromdee & Ronnen Miller\\ +David Hairston & Ken Lorber & Ross Brown\\ +Dean Luick & Ken Washikita & Sascha Wostmann\\ +Del Lamb & Kevin Darcy & Scott Bigham\\ +Deron Meranda & Kevin Hugo & Scott R. Turner\\ +Dion Nicolaas & Kevin Sitze & Stephen Spackman\\ +Dylan O'Donnell & Kevin Smolkowski & Stephen White\\ +Eric Backus & Kevin Sweet & Steve Creps\\ +Eric Hendrickson & Lars Huttar & Steve Linhart\\ +Eric R. Smith & Mark Gooderum & Steve VanDevender\\ +Eric S. Raymond & Mark Modrall & Teemu Suikki\\ Erik Andersen & Marvin Bressler & Tim Lennan\\ Frederick Roeber & Matthew Day & Timo Hakulinen\\ Gil Neiger & Merlyn LeRoy & Tom Almy\\ Greg Laskin & Michael Allison & Tom West\\ Greg Olson & Michael Feir & Warren Cheung\\ Gregg Wonderly & Michael Hamel & Warwick Allison\\ -Hao-yang Wang & Michael Sokolov & Yitzhak Sapir\\ -Helge Hafting & Mike Engber +Hao-yang Wang & Michael Sokolov & Yitzhak Sapir %TABLE_END Do not delete this line. \end{tabular} \end{center} diff --git a/doc/Guidebook.txt b/doc/Guidebook.txt index 239d035..fb13a34 100644 --- a/doc/Guidebook.txt +++ b/doc/Guidebook.txt @@ -9,33 +9,33 @@ A Guide to the Mazes of Menace - (Guidebook for NetHack 3.3) + (Guidebook for NetHack) Eric S. Raymond - (Extensively edited and expanded for 3.0 by Mike Threepoint) + (Extensively edited and expanded for 3.4) 1. Introduction Recently, you have begun to find yourself unfulfilled and distant - in your daily occupation. Strange dreams of prospecting, steal- - ing, crusading, and combat have haunted you in your sleep for - many months, but you aren't sure of the reason. You wonder - whether you have in fact been having those dreams all your life, - and somehow managed to forget about them until now. Some nights + in your daily occupation. Strange dreams of prospecting, steal- + ing, crusading, and combat have haunted you in your sleep for + many months, but you aren't sure of the reason. You wonder + whether you have in fact been having those dreams all your life, + and somehow managed to forget about them until now. Some nights you awaken suddenly and cry out, terrified at the vivid recollec- - tion of the strange and powerful creatures that seem to be lurk- - ing behind every corner of the dungeon in your dream. Could - these details haunting your dreams be real? As each night passes, - you feel the desire to enter the mysterious caverns near the - ruins grow stronger. Each morning, however, you quickly put the - idea out of your head as you recall the tales of those who en- - tered the caverns before you and did not return. Eventually you - can resist the yearning to seek out the fantastic place in your - dreams no longer. After all, when other adventurers came back - this way after spending time in the caverns, they usually seemed + tion of the strange and powerful creatures that seem to be lurk- + ing behind every corner of the dungeon in your dream. Could + these details haunting your dreams be real? As each night pass- + es, you feel the desire to enter the mysterious caverns near the + ruins grow stronger. Each morning, however, you quickly put the + idea out of your head as you recall the tales of those who en- + tered the caverns before you and did not return. Eventually you + can resist the yearning to seek out the fantastic place in your + dreams no longer. After all, when other adventurers came back + this way after spending time in the caverns, they usually seemed better off than when they passed through the first time. And who was to say that all of those who did not return had not just kept going? @@ -66,23 +66,23 @@ - NetHack Guidebook 2 + In the morning you awake, collect your belongings, and set - off for the dungeon. After several days of uneventful travel, - you see the ancient ruins that mark the entrance to the Mazes of - Menace. It is late at night, so you make camp at the entrance - and spend the night sleeping under the open skies. In the morn- - ing, you gather your gear, eat what may be your last meal out- + off for the dungeon. After several days of uneventful travel, + you see the ancient ruins that mark the entrance to the Mazes of + Menace. It is late at night, so you make camp at the entrance + and spend the night sleeping under the open skies. In the morn- + ing, you gather your gear, eat what may be your last meal out- side, and enter the dungeon... 2. What is going on here? You have just begun a game of NetHack. Your goal is to grab - as much treasure as you can, retrieve the Amulet of Yendor, and + as much treasure as you can, retrieve the Amulet of Yendor, and escape the Mazes of Menace alive. Your abilities and strengths for dealing with the hazards of @@ -92,27 +92,27 @@ them to move quickly and sneak up on the local nasties. They start equipped with the tools for a proper scientific expedition. - Barbarians are warriors out of the hinterland, hardened to + Barbarians are warriors out of the hinterland, hardened to battle. They begin their quests with naught but uncommon strength, a trusty hauberk, and a great two-handed sword. - Cavemen and Cavewomen start with exceptional strength but, + Cavemen and Cavewomen start with exceptional strength but, unfortunately, with neolithic weapons. Healers are wise in medicine and apothecary. They know the - herbs and simples that can restore vitality, ease pain, anesthe- - tize, and neutralize poisons; and with their instruments, they + herbs and simples that can restore vitality, ease pain, anes- + thetize, and neutralize poisons; and with their instruments, they can divine a being's state of health or sickness. Their medical practice earns them quite reasonable amounts of money, with which they enter the dungeon. - Knights are distinguished from the common skirmisher by - their devotion to the ideals of chivalry and by the surpassing + Knights are distinguished from the common skirmisher by + their devotion to the ideals of chivalry and by the surpassing excellence of their armor. Monks are ascetics, who by rigorous practice of physical and mental disciplines have become capable of fighting as effectively - without weapons as with. They wear no armor but make up for it + without weapons as with. They wear no armor but make up for it with increased mobility. Priests and Priestesses are clerics militant, crusaders ad- @@ -126,8 +126,7 @@ as well as tracking and stealthy movement. - NetHack 3.3 August 2, 2000 - + NetHack 3.4 March 20, 2002 @@ -136,6 +135,7 @@ NetHack Guidebook 3 + Rogues are agile and stealthy thieves, with knowledge of locks, traps, and poisons. Their advantage lies in surprise, which they employ to great advantage. @@ -153,15 +153,15 @@ cold, and instills in them stealth and cunning. Wizards start out with a knowledge of magic, a selection of - magical items, and a particular affinity for dweomercraft. - Although seemingly weak and easy to overcome at first sight, an - experienced Wizard is a deadly foe. + magical items, and a particular affinity for dweomercraft. Al- + though seemingly weak and easy to overcome at first sight, an ex- + perienced Wizard is a deadly foe. You may also choose the race of your character: Dwarves are smaller than humans or elves, but are stocky and - solid individuals. Dwarves' most notable trait is their great - expertise in mining and metalwork. Dwarvish armor is said to be + solid individuals. Dwarves' most notable trait is their great + expertise in mining and metalwork. Dwarvish armor is said to be second in quality not even to the mithril armor of the Elves. Elves are agile, quick, and perceptive; very little of what @@ -169,13 +169,13 @@ often gives them an advantage in arms and armor. Gnomes are smaller than but generally similar to dwarves. - Gnomes are known to be expert miners, and it is known that a - secret underground mine complex built by this race exists within + Gnomes are known to be expert miners, and it is known that a se- + cret underground mine complex built by this race exists within the Mazes of Menace, filled with both riches and danger. Humans are by far the most common race of the surface world, - and are thus the norm by which other races are often compared. - Although they have no special abilities, they can succeed in any + and are thus the norm by which other races are often compared. + Although they have no special abilities, they can succeed in any role. Orcs are a cruel and barbaric race that hate every living @@ -192,8 +192,7 @@ - NetHack 3.3 August 2, 2000 - + NetHack 3.4 March 20, 2002 @@ -202,6 +201,7 @@ NetHack Guidebook 4 + When NetHack's ancestor rogue first appeared, its screen orientation was almost unique among computer fantasy games. Since then, screen orientation has become the norm rather than @@ -214,13 +214,13 @@ will be used for the map. NetHack can even be played by blind players, with the assis- - tance of Braille readers or speech synthesisers. Instructions - for configuring NetHack for the blind are included later in this + tance of Braille readers or speech synthesisers. Instructions + for configuring NetHack for the blind are included later in this document. NetHack generates a new dungeon every time you play it; even - the authors still find it an entertaining and exciting game - despite having won several times. + the authors still find it an entertaining and exciting game de- + spite having won several times. NetHack offers a variety of display options. The options available to you will vary from port to port, depending on the @@ -230,21 +230,22 @@ ter interface, a color character interface, and a graphical in- terface using small pictures called tiles. The two character in- terfaces allow fonts with other characters to be substituted, but - the default assignments use standard ASCII characters to - represent everything. There is no difference between the various - display options with respect to game play. Because we cannot - reproduce the tiles or colors in the Guidebook, and because it is - common to all ports, we will use the default ASCII characters - from the monochrome character display when referring to things - you might see on the screen during your game. + the default assignments use standard ASCII characters to repre- + sent everything. There is no difference between the various dis- + play options with respect to game play. Because we cannot repro- + duce the tiles or colors in the Guidebook, and because it is com- + mon to all ports, we will use the default ASCII characters from + the monochrome character display when referring to things you + might see on the screen during your game. In order to understand what is going on in NetHack, first you must understand what NetHack is doing with the screen. The NetHack screen replaces the ``You see ...'' descriptions of text adventure games. Figure 1 is a sample of what a NetHack screen - might look like. + might look like. The way the screen looks for you depends on + your platform. - _______________________________________________________________________ + -------------------------------------------------------------------- The bat bites! ------ @@ -256,10 +257,8 @@ - Player the Rambler St:12 Dx:7 Co:18 In:11 Wi:9 Ch:15 Neutral - - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 @@ -268,17 +267,21 @@ NetHack Guidebook 5 + + + + Player the Rambler St:12 Dx:7 Co:18 In:11 Wi:9 Ch:15 Neutral Dlvl:1 $:0 HP:9(12) Pw:3(3) AC:10 Exp:1/19 T:257 Weak - _______________________________________________________________________ + -------------------------------------------------------------------- Figure 1 3.1. The status lines (bottom) - The bottom two lines of the screen contain several cryptic - pieces of information describing your current status. If either - status line becomes longer than the width of the screen, you + The bottom two lines of the screen contain several cryptic + pieces of information describing your current status. If either + status line becomes longer than the width of the screen, you might not see all of it. Here are explanations of what the vari- ous status items mean (though your configuration may not have all the status items listed below): @@ -288,21 +291,23 @@ experience level, see below). Strength - A measure of your character's strength; one of your six - basic attributes. Your attributes can range from 3 to 18 - inclusive (occasionally you may get super-strengths of the - form 18/xx). The higher your strength, the stronger you - are. Strength affects how successfully you perform physical - tasks, how much damage you do in combat, and how much loot + A measure of your character's strength; one of your six ba- + sic attributes. A human character's attributes can range + from 3 to 18 inclusive; non-humans may exceed these limits + (occasionally you may get super-strengths of the form 18/xx, + and magic can also cause attributes to exceed the normal + limits). The higher your strength, the stronger you are. + Strength affects how successfully you perform physical + tasks, how much damage you do in combat, and how much loot you can carry. Dexterity - Dexterity affects your chances to hit in combat, to avoid - traps, and do other tasks requiring agility or manipulation + Dexterity affects your chances to hit in combat, to avoid + traps, and do other tasks requiring agility or manipulation of objects. Constitution - Constitution affects your ability to recover from injuries + Constitution affects your ability to recover from injuries and other strains on your stamina. Intelligence @@ -315,17 +320,11 @@ Charisma Charisma affects how certain creatures react toward you. In - particular, it can affect the prices shopkeepers offer you. + particular, it can affect the prices shopkeepers offer you. - Alignment - Lawful, Neutral, or Chaotic. Often, Lawful is taken as good - and Chaotic as evil, but legal and ethical do not always - coincide. Your alignment influences how other monsters - react toward you. Monsters of a like alignment are more - likely to be non-aggressive, while those of an opposing - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 @@ -334,18 +333,24 @@ NetHack Guidebook 6 - alignment are more likely to be seriously offended at your - presence. + + Alignment + Lawful, Neutral, or Chaotic. Often, Lawful is taken as good + and Chaotic as evil, but legal and ethical do not always co- + incide. Your alignment influences how other monsters react + toward you. Monsters of a like alignment are more likely to + be non-aggressive, while those of an opposing alignment are + more likely to be seriously offended at your presence. Dungeon Level How deep you are in the dungeon. You start at level one and - the number increases as you go deeper into the dungeon. - Some levels are special, and are identified by a name and - not a number. The Amulet of Yendor is reputed to be some- + the number increases as you go deeper into the dungeon. + Some levels are special, and are identified by a name and + not a number. The Amulet of Yendor is reputed to be some- where beneath the twentieth level. Gold - The number of gold pieces you are openly carrying. Gold + The number of gold pieces you are openly carrying. Gold which you have concealed in containers is not counted. Hit Points @@ -357,13 +362,13 @@ your hit points can reach. Power - Spell points. This tells you how much mystic energy (mana) - you have available for spell casting. Again, resting will + Spell points. This tells you how much mystic energy (mana) + you have available for spell casting. Again, resting will regenerate the amount available. Armor Class A measure of how effectively your armor stops blows from un- - friendly creatures. The lower this number is, the more ef- + friendly creatures. The lower this number is, the more ef- fective the armor; it is quite possible to have negative ar- mor class. @@ -376,45 +381,44 @@ here. Time - The number of turns elapsed so far, displayed if you have + The number of turns elapsed so far, displayed if you have the time option set. Hunger status Your current hunger status, ranging from Satiated down to - Fainting. If your hunger status is normal, it is not - displayed. - - Additional status flags may appear after the hunger status: - Conf when you're confused, FoodPois or Ill when sick, Blind when - you can't see, Stun when stunned, and Hallu when hallucinating. + Fainting. If your hunger status is normal, it is not dis- + played. + NetHack 3.4 March 20, 2002 - NetHack 3.3 August 2, 2000 + NetHack Guidebook 7 - NetHack Guidebook 7 + Additional status flags may appear after the hunger status: + Conf when you're confused, FoodPois or Ill when sick, Blind when + you can't see, Stun when stunned, and Hallu when hallucinating. 3.2. The message line (top) - The top line of the screen is reserved for messages that - describe things that are impossible to represent visually. If - you see a ``--More--'' on the top line, this means that NetHack - has another message to display on the screen, but it wants to - make certain that you've read the one that is there first. To - read the next message, just press the space bar. + The top line of the screen is reserved for messages that de- + scribe things that are impossible to represent visually. If you + see a ``--More--'' on the top line, this means that NetHack has + another message to display on the screen, but it wants to make + certain that you've read the one that is there first. To read + the next message, just press the space bar. 3.3. The map (rest of the screen) - The rest of the screen is the map of the level as you have - explored it so far. Each symbol on the screen represents some- - thing. You can set various graphics options to change some of - the symbols the game uses; otherwise, the game will use default + The rest of the screen is the map of the level as you have + explored it so far. Each symbol on the screen represents some- + thing. You can set various graphics options to change some of + the symbols the game uses; otherwise, the game will use default symbols. Here is a list of what the default symbols mean: - and | @@ -422,7 +426,7 @@ . The floor of a room, ice, or a doorless doorway. - # A corridor, or iron bars, or a tree, or possibly a kitchen + # A corridor, or iron bars, or a tree, or possibly a kitchen sink (if your dungeon has sinks), or a drawbridge. > Stairs down: a way to the next level. @@ -450,21 +454,21 @@ = A ring. - ! A potion. - ( A useful item (pick-axe, key, lamp...). + NetHack 3.4 March 20, 2002 - NetHack 3.3 August 2, 2000 + NetHack Guidebook 8 - NetHack Guidebook 8 + ! A potion. + ( A useful item (pick-axe, key, lamp...). " An amulet or a spider web. @@ -483,10 +487,14 @@ \ An opulent throne. a-zA-Z and other symbols - Letters and certain other symbols represent the various in- - habitants of the Mazes of Menace. Watch out, they can be + Letters and certain other symbols represent the various in- + habitants of the Mazes of Menace. Watch out, they can be nasty and vicious. Sometimes, however, they can be helpful. + I This marks the last known location of an invisible or other- + wise unseen monster. Note that the monster could have + moved. The 'F' and 'm' commands may be useful here. + You need not memorize all these symbols; you can ask the game what any symbol represents with the `/' command (see the next section for more info). @@ -500,9 +508,9 @@ additional information, for example a direction, or an object to be used. For those commands that require additional information, NetHack will present you with either a menu of choices or with a - command line prompt requesting information. Which you are - presented with will depend chiefly on how you have set the menus- - tyle option. + command line prompt requesting information. Which you are pre- + sented with will depend chiefly on how you have set the menustyle + option. For example, a common question, in the form ``What do you want to use? [a-zA-Z ?*]'', asks you to choose an object you are @@ -512,26 +520,26 @@ example, there is also a `*' indicating that you may choose an object not on the list, if you wanted to use something unexpect- ed. Typing a `*' lists your entire inventory, so you can see the - inventory letters of every object you're carrying. Finally, if - you change your mind and decide you don't want to do this command - after all, you can press the ESC key to abort the command. - You can put a number before some commands to repeat them - that many times; for example, ``10s'' will search ten times. If - you have the number_pad option set, you must type `n' to prefix a - count, so the example above would be typed ``n10s'' instead. + NetHack 3.4 March 20, 2002 - NetHack 3.3 August 2, 2000 + NetHack Guidebook 9 - NetHack Guidebook 9 + inventory letters of every object you're carrying. Finally, if + you change your mind and decide you don't want to do this command + after all, you can press the ESC key to abort the command. + You can put a number before some commands to repeat them + that many times; for example, ``10s'' will search ten times. If + you have the number_pad option set, you must type `n' to prefix a + count, so the example above would be typed ``n10s'' instead. Commands for which counts make no sense ignore them. In addi- tion, movement commands can be prefixed for greater control (see below). To cancel a count or a prefix, press the ESC key. @@ -543,63 +551,65 @@ ? Help menu: display one of several help texts available. - / Tell what a symbol represents. You may choose to specify a + / Tell what a symbol represents. You may choose to specify a location or type a symbol (or even a whole word) to explain. Specifying a location is done by moving the cursor to a par- - ticular spot on the map and then pressing one of `.', `,', - `;', or `:'. `.' will explain the symbol at the chosen lo- - cation, conditionally check for ``More info?'' depending - upon whether the help option is on, and then you will be - asked to pick another location; `,' will explain the symbol - but skip any additional information; `;' will skip addition- - al info and also not bother asking you to choose another lo- - cation to examine; `:' will show additional info, if any, - without asking for confirmation. When picking a location, - pressing the ESC key will terminate this command, or press- - ing `?' will give a brief reminder about how it works. + ticular spot on the map and then pressing one of `.', `,', + `;', or `:'. `.' will explain the symbol at the chosen lo- + cation, conditionally check for ``More info?'' depending up- + on whether the help option is on, and then you will be asked + to pick another location; `,' will explain the symbol but + skip any additional information; `;' will skip additional + info and also not bother asking you to choose another loca- + tion to examine; `:' will show additional info, if any, + without asking for confirmation. When picking a location, + pressing the ESC key will terminate this command, or press- + ing `?' will give a brief reminder about how it works. Specifying a name rather than a location always gives any additional information available about that name. & Tell what a command does. - < Go up to the previous level (if you are on the staircase or + < Go up to the previous level (if you are on a staircase or ladder). - > Go down to the next level (if you are on the staircase or - ladder). + > Go down to the next level (if you are on a staircase or lad- + der). [yuhjklbn] - Go one step in the direction indicated (see Figure 2). If - you can sense a monster there, you will fight the monster - instead. Only these one-step movement commands cause you to - fight monsters; the others (below) are ``safe.'' - - y k u 7 8 9 - \ | / \ | / - h- . -l 4- . -6 - / | \ / | \ - b j n 1 2 3 - (if number_pad is set) + Go one step in the direction indicated (see Figure 2). If + you sense or remember a monster there, you will fight the + monster instead. Only these one-step movement commands + cause you to fight monsters; the others (below) are + ``safe.'' + - Figure 2 + NetHack 3.4 March 20, 2002 - NetHack 3.3 August 2, 2000 + NetHack Guidebook 10 - NetHack Guidebook 10 + y k u 7 8 9 + \ | / \ | / + h- . -l 4- . -6 + / | \ / | \ + b j n 1 2 3 + (if number_pad is set) + + Figure 2 [YUHJKLBN] - Go in that direction until you hit a wall or run into some- + Go in that direction until you hit a wall or run into some- thing. m[yuhjklbn] @@ -607,7 +617,7 @@ if you remember a monster there) F[yuhjklbn] - Prefix: fight a monster (even if you only guess one is + Prefix: fight a monster (even if you only guess one is there) M[yuhjklbn] @@ -620,12 +630,18 @@ Prefix: same as `g', but forking of corridors is not con- sidered interesting. + _ Travel to a map location via a shortest-path algorithm. + Stops on most of the same conditions as the `G' command + does. For ports with mouse support, the command is also in- + voked when a mouse-click takes place on a location further + than 1 cell away from the current position. + . Rest, do nothing for one turn. a Apply (use) a tool (pick-axe, key, lamp...). A Remove one or more worn items, such as armor. Use `T' (take - off) to take off only one piece of armor or `R' (remove) to + off) to take off only one piece of armor or `R' (remove) to take off only one accessory. ^A Redo the previous command. @@ -636,57 +652,57 @@ ^C Panic button. Quit the game. - d Drop something. Ex. ``d7a'' means drop seven items of ob- - ject a. - D Drop several things. In answer to the question ``What kinds - of things do you want to drop? [!%= aium]'' you should type - zero or more object symbols possibly followed by `a' and/or - `i' and/or `u' and/or `m'. - Da - drop all objects, without asking for confirmation. - Di - examine your inventory before dropping anything. - Du - drop only unpaid objects (when in a shop). - Dm - use a menu to pick which object(s) to drop. - D%u - drop only unpaid food. + NetHack 3.4 March 20, 2002 - ^D Kick something (usually a door). - NetHack 3.3 August 2, 2000 + NetHack Guidebook 11 + d Drop something. Ex. ``d7a'' means drop seven items of ob- + ject a. + D Drop several things. In answer to the question ``What kinds + of things do you want to drop? [!%= aium]'' you should type + zero or more object symbols possibly followed by `a' and/or + `i' and/or `u' and/or `m'. - NetHack Guidebook 11 + Da - drop all objects, without asking for confirmation. + Di - examine your inventory before dropping anything. + Du - drop only unpaid objects (when in a shop). + Dm - use a menu to pick which object(s) to drop. + D%u - drop only unpaid food. + ^D Kick something (usually a door). e Eat food. - E Engrave a message on the floor. Engraving the word ``El- - bereth'' will cause most monsters to not attack you hand- - to-hand (but if you attack, you will rub it out); this is - often useful to give yourself a breather. (This feature may - be compiled out of the game, so your version might not have + E Engrave a message on the floor. Engraving the word ``El- + bereth'' will cause most monsters to not attack you hand-to- + hand (but if you attack, you will rub it out); this is often + useful to give yourself a breather. (This feature may be + compiled out of the game, so your version might not have it.) - E- - write in the dust with your fingers. + E- - write in the dust with your fingers. - f Fire one of the objects placed in your quiver. You may - select ammunition with a previous `Q' command, or let the - computer pick something appropriate if autoquiver is true. + f Fire one of the objects placed in your quiver. You may se- + lect ammunition with a previous `Q' command, or let the com- + puter pick something appropriate if autoquiver is true. i List your inventory (everything you're carrying). I List selected parts of your inventory. - I* - list all gems in inventory; - Iu - list all unpaid items; - Ix - list all used up items that are on your shopping bill; - I$ - count your money. + I* - list all gems in inventory; + Iu - list all unpaid items; + Ix - list all used up items that are on your shopping bill; + I$ - count your money. o Open a door. @@ -702,40 +718,40 @@ p Pay your shopping bill. - P Put on a ring or other accessory (amulet, blindfold). - ^P Repeat previous message (subsequent ^P's repeat earlier mes- - sages). - q Quaff (drink) a potion. + NetHack 3.4 March 20, 2002 - Q Select an object for your quiver. You can then throw this - using the `f' command. (In versions prior to 3.3 this was - the command to quit the game, which has now been moved to - `#quit'.) - r Read a scroll or spellbook. - R Remove an accessory (ring, amulet, etc). + NetHack Guidebook 12 - NetHack 3.3 August 2, 2000 + P Put on a ring or other accessory (amulet, blindfold). + ^P Repeat previous message (subsequent ^P's repeat earlier mes- + sages). + q Quaff (drink) a potion. + Q Select an object for your quiver. You can then throw this + using the `f' command. (In versions prior to 3.3 this was + the command to quit the game, which has now been moved to + `#quit'.) - NetHack Guidebook 12 + r Read a scroll or spellbook. + R Remove an accessory (ring, amulet, etc). ^R Redraw the screen. s Search for secret doors and traps around you. It usually takes several tries to find something. - S Save (and suspend) the game. The game will be restored au- + S Save (and suspend) the game. The game will be restored au- tomatically the next time you play. t Throw an object or shoot a projectile. @@ -750,7 +766,7 @@ w Wield weapon. - w- - wield nothing, use your bare hands. + w- - wield nothing, use your bare hands. W Wear armor. @@ -765,36 +781,35 @@ ^X Display your name, role, race, gender, and alignment as well as the various deities in your game. - z Zap a wand. To aim at yourself, use `.' for the direction. + z Zap a wand. To aim at yourself, use `.' for the direction. - Z Zap (cast) a spell. - ^Z Suspend the game (UNIX(R) versions with job control only). - : Look at what is here. - ; Show what type of thing a visible symbol corresponds to. + NetHack 3.4 March 20, 2002 - , Pick up some things. - @ Toggle the autopickup option on and off. - ^ Ask for the type of a trap you found earlier. - __________ - (R)UNIX is a registered trademark of AT&T. + NetHack Guidebook 13 - NetHack 3.3 August 2, 2000 + Z Zap (cast) a spell. To cast at yourself, use `.' for the + direction. + ^Z Suspend the game (UNIX(R) versions with job control only). + : Look at what is here. + ; Show what type of thing a visible symbol corresponds to. + , Pick up some things. - NetHack Guidebook 13 + @ Toggle the autopickup option on and off. + ^ Ask for the type of a trap you found earlier. ) Tell what weapon you are wielding. @@ -806,7 +821,7 @@ ( Tell what tools you are using. - * Tell what equipment you are using; combines the preceding + * Tell what equipment you are using; combines the preceding five type-specific commands into one. $ Count your gold pieces. @@ -823,50 +838,53 @@ ! Escape to a shell. # Perform an extended command. As you can see, the authors of - NetHack used up all the letters, so this is a way to intro- - duce the less frequently used commands. What extended com- - mands are available depends on what features the game was + NetHack used up all the letters, so this is a way to intro- + duce the less frequently used commands. What extended com- + mands are available depends on what features the game was compiled with. #adjust Adjust inventory letters (most useful when the fixinv option is ``on''). - #chat - Talk to someone. - #conduct - List which challenges you have adhered to. + __________ + (R)UNIX is a registered trademark of AT&T. - #dip Dip an object into something. - #enhance - Advance or check weapons and spell skills. + NetHack 3.4 March 20, 2002 - #force - Force a lock. - #invoke - Invoke an object's special powers. + NetHack Guidebook 14 - NetHack 3.3 August 2, 2000 + #chat + Talk to someone. + #conduct + List which challenges you have adhered to. See the section + below entitled ``Conduct'' for details. + #dip Dip an object into something. + #enhance + Advance or check weapons and spell skills. - NetHack Guidebook 14 + #force + Force a lock. + #invoke + Invoke an object's special powers. #jump Jump to another location. #loot - Loot a box or bag on the floor beneath you, or the saddle + Loot a box or bag on the floor beneath you, or the saddle from a horse standing next to you. #monster @@ -888,7 +906,7 @@ #ride Ride (or stop riding) a monster. - #rub Rub a lamp. + #rub Rub a lamp or a stone. #sit Sit down. @@ -896,9 +914,21 @@ Turn undead. #twoweapon - Toggle two-weapon combat on or off. Note that you must use - suitable weapons for this type of combat, or it will be au- - tomatically turned off. + Toggle two-weapon combat on or off. Note that you must use + suitable weapons for this type of combat, or it will be + + + NetHack 3.4 March 20, 2002 + + + + + + NetHack Guidebook 15 + + + + automatically turned off. #untrap Untrap something (trap, door, or chest). @@ -912,23 +942,14 @@ #? Help menu: get the list of available extended commands. If your keyboard has a meta key (which, when pressed in com- - bination with another key, modifies it by setting the `meta' - [8th, or `high'] bit), you can invoke many extended commands by - meta-ing the first letter of the command. In NT, OS/2, and PC + bination with another key, modifies it by setting the `meta' + [8th, or `high'] bit), you can invoke many extended commands by + meta-ing the first letter of the command. In NT, OS/2, and PC NetHack, the `Alt' key can be used in this fashion. + M-? #? (not supported by all platforms) - NetHack 3.3 August 2, 2000 - - - - - - - NetHack Guidebook 15 - - - M-2 #twoweapon + M-2 #twoweapon (unless the number_pad option is enabled) M-a #adjust @@ -960,39 +981,43 @@ M-s #sit - M-t #turn - M-u #untrap - M-v #version - M-w #wipe + NetHack 3.4 March 20, 2002 - If the number_pad option is on, some additional letter com- - mands are available: - j Jump to another location. Same as ``#jump'' or ``M-j''. - k Kick something (usually a door). Same as `^D'. - l Loot a box or bag on the floor beneath you, or the saddle - from a horse standing next to you. Same as ``#loot'' or - ``M-l''. - N Name an item or type of object. Same as ``#name'' or ``M- - N''. + NetHack Guidebook 16 - NetHack 3.3 August 2, 2000 + M-t #turn + M-u #untrap + M-v #version + M-w #wipe + If the number_pad option is on, some additional letter com- + mands are available: + h Help menu: display one of several help texts available, + like ``?''. - NetHack Guidebook 16 + j Jump to another location. Same as ``#jump'' or ``M-j''. + + k Kick something (usually a door). Same as `^D'. + + l Loot a box or bag on the floor beneath you, or the saddle + from a horse standing next to you. Same as ``#loot'' or + ``M-l''. + N Name an item or type of object. Same as ``#name'' or ``M- + n''. u Untrap a trap, door, or chest. Same as ``#untrap'' or ``M- u''. @@ -1000,9 +1025,9 @@ 5. Rooms and corridors - Rooms and corridors in the dungeon are either lit or dark. - Any lit areas within your line of sight will be displayed; dark - areas are only displayed if they are within one space of you. + Rooms and corridors in the dungeon are either lit or dark. + Any lit areas within your line of sight will be displayed; dark + areas are only displayed if they are within one space of you. Walls and corridors remain on the map as you explore them. Secret corridors are hidden. You can find them with the `s' @@ -1011,55 +1036,55 @@ 5.1. Doorways Doorways connect rooms and corridors. Some doorways have no - doors; you can walk right through. Others have doors in them, + doors; you can walk right through. Others have doors in them, which may be open, closed, or locked. To open a closed door, use - the `o' (open) command; to close it again, use the `c' (close) + the `o' (open) command; to close it again, use the `c' (close) command. - You can get through a locked door by using a tool to pick + You can get through a locked door by using a tool to pick the lock with the `a' (apply) command, or by kicking it open with the `^D' (kick) command. - Open doors cannot be entered diagonally; you must approach - them straight on, horizontally or vertically. Doorways without + Open doors cannot be entered diagonally; you must approach + them straight on, horizontally or vertically. Doorways without doors are not restricted in this fashion. - Doors can be useful for shutting out monsters. Most mon- + + NetHack 3.4 March 20, 2002 + + + + + + NetHack Guidebook 17 + + + + Doors can be useful for shutting out monsters. Most mon- sters cannot open doors, although a few don't need to (ex. ghosts can walk through doors). - Secret doors are hidden. You can find them with the `s' - (search) command. Once found they are in all ways equivalent to + Secret doors are hidden. You can find them with the `s' + (search) command. Once found they are in all ways equivalent to normal doors. 5.2. Traps (`^') - There are traps throughout the dungeon to snare the unwary - delver. For example, you may suddenly fall into a pit and be + There are traps throughout the dungeon to snare the unwary + delver. For example, you may suddenly fall into a pit and be stuck for a few turns trying to climb out. Traps don't appear on your map until you see one triggered by moving onto it, see some- thing fall into it, or you discover it with the `s' (search) com- - mand. Monsters can fall prey to traps, too, which can be a very + mand. Monsters can fall prey to traps, too, which can be a very useful defensive strategy. There is a special pre-mapped branch of the dungeon based on - the classic computer game ``Sokoban.'' The goal is to push the - boulders into the pits or holes. With careful foresight, it is - possible to complete all of the levels according to the tradi- - tional rules of Sokoban. Some allowances are permitted in case + the classic computer game ``Sokoban.'' The goal is to push the + boulders into the pits or holes. With careful foresight, it is + possible to complete all of the levels according to the tradi- + tional rules of Sokoban. Some allowances are permitted in case the player gets stuck; however, they will lower your luck. - - NetHack 3.3 August 2, 2000 - - - - - - - NetHack Guidebook 17 - - 5.3. Stairs (`<', `>') In general, each level in the dungeon will have a staircase @@ -1069,19 +1094,19 @@ two down staircases, one continuing into the dungeon and the oth- er branching into an area known as the Gnomish Mines. Those mines eventually hit a dead end, so after exploring them (if you - choose to do so), you'll need to climb back up to the main - dungeon. + choose to do so), you'll need to climb back up to the main dun- + geon. When you traverse a set of stairs, or trigger a trap which - sends you to another level, the level you're leaving will be - deactivated and stored in a file on disk. If you're moving to a + sends you to another level, the level you're leaving will be de- + activated and stored in a file on disk. If you're moving to a previously visited level, it will be loaded from its file on disk and reactivated. If you're moving to a level which has not yet been visited, it will be created (from scratch for most random levels, from a template for some ``special'' levels, or loaded from the remains of an earlier game for a ``bones'' level as - briefly described below). Monsters are only active on the - current level; those on other levels are essentially placed into + briefly described below). Monsters are only active on the cur- + rent level; those on other levels are essentially placed into stasis. Ordinarily when you climb a set of stairs, you will arrive @@ -1089,6 +1114,18 @@ pets (see below) and some other monsters will follow along if they're close enough when you travel up or down stairs, and occa- sionally one of these creatures will displace you during the + + + NetHack 3.4 March 20, 2002 + + + + + + NetHack Guidebook 18 + + + climb. When that occurs, the pet or other monster will arrive on the staircase and you will end up nearby. @@ -1106,26 +1143,13 @@ magic items can help you locate them before they locate you (which some monsters can do very well). - The commands `/' and `;' may be used to obtain information - about those monsters who are displayed on the screen. The com- - mand `C' allows you to assign a name to a monster, which may be - useful to help distinguish one from another when multiple mon- - sters are present. Assigning a name which is just a space will + The commands `/' and `;' may be used to obtain information + about those monsters who are displayed on the screen. The com- + mand `C' allows you to assign a name to a monster, which may be + useful to help distinguish one from another when multiple mon- + sters are present. Assigning a name which is just a space will remove any prior name. - - - - NetHack 3.3 August 2, 2000 - - - - - - - NetHack Guidebook 18 - - The extended command ``#chat'' can be used to interact with an adjacent monster. There is no actual dialog (in other words, you don't get to choose what you'll say), but chatting with some @@ -1139,6 +1163,16 @@ business unless you attack them. Some of them are very dangerous when angered. Remember: discretion is the better part of valor. + If you can't see a monster (if it is invisible, or if you + are blinded), the symbol `I' will be shown when you learn of its + presence. If you attempt to walk into it, you will try to fight + it just like a monster that you can see; of course, if the mon- + ster has moved, you will attack empty air. If you guess that the + monster has moved and you don't wish to fight, you can use the + `m' command to move without fighting; likewise, if you don't re- + member a monster but want to try fighting anyway, you can use the + `F' command. + 6.2. Your pet You start the game with a little dog (`d'), cat (`f'), or @@ -1146,21 +1180,33 @@ sters with you. Like you, your pet needs food to survive. It usually feeds itself on fresh carrion and other meats. If you're worried about it or want to train it, you can feed it, too, by - throwing it food. A properly trained pet can be very useful - under certain circumstances. + + + NetHack 3.4 March 20, 2002 + + + + + + NetHack Guidebook 19 + + + + throwing it food. A properly trained pet can be very useful un- + der certain circumstances. Your pet also gains experience from killing monsters, and can grow over time, gaining hit points and doing more damage. Initially, your pet may even be better at killing things than you, which makes pets useful for low-level characters. - Your pet will follow you up and down staircases if it is - next to you when you move. Otherwise your pet will be stranded - and may become wild. Similarly, when you trigger certain types - of traps which alter your location (for instance, a trap door - which drops you to a lower dungeon level), any adjacent pet will + Your pet will follow you up and down staircases if it is + next to you when you move. Otherwise your pet will be stranded + and may become wild. Similarly, when you trigger certain types + of traps which alter your location (for instance, a trap door + which drops you to a lower dungeon level), any adjacent pet will accompany you and any non-adjacent pet will be left behind. Your - pet may trigger such traps itself; you will not be carried along + pet may trigger such traps itself; you will not be carried along with it even if adjacent at the time. 6.3. Steeds @@ -1168,8 +1214,8 @@ Some types of creatures in the dungeon can actually be rid- den if you have the right equipment and skill. Convincing a wild beast to let you saddle it up is difficult to say the least. - Many a dungeoneer has had to resort to magic and wizardry in ord- - er to forge the alliance. Once you do have the beast under your + Many a dungeoneer has had to resort to magic and wizardry in or- + der to forge the alliance. Once you do have the beast under your control however, you can easily climb in and out of the saddle with the `#ride' command. Lead the beast around the dungeon when riding, in the same manner as you would move yourself. It is the @@ -1178,47 +1224,45 @@ Riding skill is managed by the `#enhance' command. See the section on Weapon proficiency for more information about that. + 6.4. Bones levels + You may encounter the shades and corpses of other adventur- + ers (or even former incarnations of yourself!) and their personal + effects. Ghosts are hard to kill, but easy to avoid, since + they're slow and do little damage. You can plunder the deceased + adventurer's possessions; however, they are likely to be cursed. + Beware of whatever killed the former player; it is probably still + lurking around, gloating over its last victory. + 7. Objects - NetHack 3.3 August 2, 2000 - - + When you find something in the dungeon, it is common to want + to pick it up. In NetHack, this is accomplished automatically by + walking over the object (unless you turn off the autopickup op- + tion (see below), or move with the `m' prefix (see above)), or + manually by using the `,' command. + If you're carrying too many items, NetHack will tell you so + and you won't be able to pick up anything more. Otherwise, it + will add the object(s) to your pack and tell you what you just + NetHack 3.4 March 20, 2002 - NetHack Guidebook 19 - 6.4. Bones levels - You may encounter the shades and corpses of other adventur- - ers (or even former incarnations of yourself!) and their personal - effects. Ghosts are hard to kill, but easy to avoid, since - they're slow and do little damage. You can plunder the deceased - adventurer's possessions; however, they are likely to be cursed. - Beware of whatever killed the former player; it is probably still - lurking around, gloating over its last victory. + NetHack Guidebook 20 - 7. Objects - When you find something in the dungeon, it is common to want - to pick it up. In NetHack, this is accomplished automatically by - walking over the object (unless you turn off the autopickup op- - tion (see below), or move with the `m' prefix (see above)), or - manually by using the `,' command. - If you're carrying too many items, NetHack will tell you so - and you won't be able to pick up anything more. Otherwise, it - will add the object(s) to your pack and tell you what you just picked up. As you add items to your inventory, you also add the weight - of that object to your load. The amount that you can carry - depends on your strength and your constitution. The stronger you + of that object to your load. The amount that you can carry de- + pends on your strength and your constitution. The stronger you are, the less the additional load will affect you. There comes a point, though, when the weight of all of that stuff you are car- rying around with you through the dungeon will encumber you. @@ -1227,61 +1271,60 @@ you'll be so overloaded that you'll either have to discard some of what you're carrying or collapse under its weight. - NetHack will tell you how badly you have loaded yourself. - The symbols `Burdened', `Stressed', `Strained', `Overtaxed' and + NetHack will tell you how badly you have loaded yourself. + The symbols `Burdened', `Stressed', `Strained', `Overtaxed' and `Overloaded' are displayed on the bottom line display to indicate your condition. - When you pick up an object, it is assigned an inventory - letter. Many commands that operate on objects must ask you to - find out which object you want to use. When NetHack asks you to - choose a particular object you are carrying, you are usually - presented with a list of inventory letters to choose from (see - Commands, above). - - Some objects, such as weapons, are easily differentiated. - Others, like scrolls and potions, are given descriptions which - vary according to type. During a game, any two objects with the - same description are the same type. However, the descriptions + When you pick up an object, it is assigned an inventory let- + ter. Many commands that operate on objects must ask you to find + out which object you want to use. When NetHack asks you to + choose a particular object you are carrying, you are usually pre- + sented with a list of inventory letters to choose from (see Com- + mands, above). + + Some objects, such as weapons, are easily differentiated. + Others, like scrolls and potions, are given descriptions which + vary according to type. During a game, any two objects with the + same description are the same type. However, the descriptions will vary from game to game. + When you use one of these objects, if its effect is obvious, + NetHack will remember what it is for you. If its effect isn't + extremely obvious, you will be asked what you want to call this + type of object so you will recognize it later. You can also use + the ``#name'' command for the same purpose at any time, to name + all objects of a particular type or just an individual object. + When you use ``#name'' on an object which has already been named, + specifying a space as the value will remove the prior name in- + stead of assigning a new one. + 7.1. Curses and Blessings + Any object that you find may be cursed, even if the object + is otherwise helpful. The most common effect of a curse is being + stuck with (and to) the item. Cursed weapons weld themselves to + your hand when wielded, so you cannot unwield them. Any cursed + item you wear is not removable by ordinary means. In addition, + cursed arms and armor usually, but not always, bear negative en- + chantments that make them less effective in combat. Other cursed + objects may act poorly or detrimentally in other ways. - NetHack 3.3 August 2, 2000 + Objects can also be blessed. Blessed items usually work + better or more beneficially than normal uncursed items. For + NetHack 3.4 March 20, 2002 - NetHack Guidebook 20 + NetHack Guidebook 21 - When you use one of these objects, if its effect is obvious, - NetHack will remember what it is for you. If its effect isn't - extremely obvious, you will be asked what you want to call this - type of object so you will recognize it later. You can also use - the ``#name'' command for the same purpose at any time, to name - all objects of a particular type or just an individual object. - When you use ``#name'' on an object which has already been named, - specifying a space as the value will remove the prior name in- - stead of assigning a new one. - 7.1. Curses and Blessings - Any object that you find may be cursed, even if the object - is otherwise helpful. The most common effect of a curse is being - stuck with (and to) the item. Cursed weapons weld themselves to - your hand when wielded, so you cannot unwield them. Any cursed - item you wear is not removable by ordinary means. In addition, - cursed arms and armor usually, but not always, bear negative en- - chantments that make them less effective in combat. Other cursed - objects may act poorly or detrimentally in other ways. - - Objects can also be blessed. Blessed items usually work - better or more beneficially than normal uncursed items. For ex- - ample, a blessed weapon will do more damage against demons. + example, a blessed weapon will do more damage against demons. There are magical means of bestowing or removing curses upon objects, so even if you are stuck with one, you can still have @@ -1290,18 +1333,18 @@ they can more easily avoid cursed objects than other character roles. - An item with unknown status will be reported in your inven- + An item with unknown status will be reported in your inven- tory with no prefix. An item which you know the state of will be - distinguished in your inventory by the presence of the word + distinguished in your inventory by the presence of the word ``cursed'', ``uncursed'' or ``blessed'' in the description of the item. 7.2. Weapons (`)') - Given a chance, most monsters in the Mazes of Menace will - gratuitously try to kill you. You need weapons for self-defense - (killing them first). Without a weapon, you do only 1-2 hit - points of damage (plus bonuses, if any). Monk characters are an + Given a chance, most monsters in the Mazes of Menace will + gratuitously try to kill you. You need weapons for self-defense + (killing them first). Without a weapon, you do only 1-2 hit + points of damage (plus bonuses, if any). Monk characters are an exception; they normally do much more damage with bare hands than they do with weapons. @@ -1309,26 +1352,14 @@ weapons, like arrows and spears. To hit monsters with a weapon, you must wield it and attack them, or throw it at them. You can simply elect to throw a spear. To shoot an arrow, you should - first wield a bow, then throw the arrow. Crossbows shoot - crossbow bolts. Slings hurl rocks and (other) stones (like - gems). - - - NetHack 3.3 August 2, 2000 - - - - - - - NetHack Guidebook 21 - + first wield a bow, then throw the arrow. Crossbows shoot cross- + bow bolts. Slings hurl rocks and (other) stones (like gems). Enchanted weapons have a ``plus'' (or ``to hit enhancement'' - which can be either positive or negative) that adds to your - chance to hit and the damage you do to a monster. The only way + which can be either positive or negative) that adds to your + chance to hit and the damage you do to a monster. The only way to determine a weapon's enchantment is to have it magically iden- - tified somehow. Most weapons are subject to some type of damage + tified somehow. Most weapons are subject to some type of damage like rust. Such ``erosion'' damage can be repaired. The chance that an attack will successfully hit a monster, @@ -1340,27 +1371,39 @@ of armor - is a factor too; also, some monsters are particularly vulnerable to certain types of weapons. - Many weapons can be wielded in one hand; some require both - hands. When wielding a two-handed weapon, you can not wear a - shield, and vice versa. When wielding a one-handed weapon, you - can have another weapon ready to use by setting things up with - the `x' command, which exchanges your primary (the one being - wielded) and secondary weapons. And if you have proficiency in - the ``two weapon combat'' skill, you may wield both primary and - secondary weapons simultaneously; use the `#twoweapon' extended - command to engage or disengage that. Only some types of charac- - ters (barbarians, for instance), have the necessary skill avail- - able. Even with that skill, using two weapons at once incurs a - penalty in the chance to hit your target compared to using just + Many weapons can be wielded in one hand; some require both + hands. When wielding a two-handed weapon, you can not wear a + shield, and vice versa. When wielding a one-handed weapon, you + can have another weapon ready to use by setting things up with + the `x' command, which exchanges your primary (the one being + wielded) and secondary weapons. And if you have proficiency in + the ``two weapon combat'' skill, you may wield both primary and + + + NetHack 3.4 March 20, 2002 + + + + + + NetHack Guidebook 22 + + + + secondary weapons simultaneously; use the `#twoweapon' extended + command to engage or disengage that. Only some types of charac- + ters (barbarians, for instance) have the necessary skill avail- + able. Even with that skill, using two weapons at once incurs a + penalty in the chance to hit your target compared to using just one weapon at a time. - There might be times when you'd rather not wield any weapon - at all. To accomplish that, wield `-', or else use the `A' com- - mand which allows you to unwield the current weapon in addition + There might be times when you'd rather not wield any weapon + at all. To accomplish that, wield `-', or else use the `A' com- + mand which allows you to unwield the current weapon in addition to taking off other worn items. Those of you in the audience who are AD&D players, be aware - that each weapon which exists in AD&D does roughly the same dam- + that each weapon which existed in AD&D does roughly the same dam- age to monsters in NetHack. Some of the more obscure weapons (such as the aklys, lucern hammer, and bec-de-corbin) are defined in an appendix to Unearthed Arcana, an AD&D supplement. @@ -1376,46 +1419,50 @@ in your inventory which are considered likely to be thrown, or picking `*' will list your entire inventory. After you've chosen what to throw, you will be prompted for a direction rather than - for a specific target. The distance something can be thrown - depends mainly on the type of object and your strength. Arrows + for a specific target. The distance something can be thrown de- + pends mainly on the type of object and your strength. Arrows can + be thrown by hand, but can be thrown much farther and will be + more likely to hit when thrown while you are wielding a bow. + You can simplify the throwing operation by using the `Q' + command to select your preferred ``missile'', then using the `f' + command to throw it. You'll be prompted for a direction as + above, but you don't have to specify which item to throw each + time you use `f'. There is also an option, autoquiver, which has + NetHack choose another item to automatically fill your quiver + when the inventory slot used for `Q' runs out. - NetHack 3.3 August 2, 2000 + Some characters have the ability to fire a volley of multi- + ple items in a single turn. Knowing how to load several rounds + of ammunition at once -- or hold several missiles in your hand -- + and still hit a target is not an easy task. Rangers are among + those who are adept at this task, as are those with a high level + of proficiency in the relevant weapon skill (in bow skill if + you're wielding one to shoot arrows, in crossbow skill if you're + wielding one to shoot bolts, or in sling skill if you're wielding + one to shoot stones). The number of items that the character has + a chance to fire varies from turn to turn. You can explicitly + limit the number of shots by using a numeric prefix before the + `t' or `f' command. For example, ``2f'' (or ``n2f'' if using + NetHack 3.4 March 20, 2002 - NetHack Guidebook 22 + NetHack Guidebook 23 - can be thrown by hand, but can be thrown much farther and will be - more likely to hit when thrown while you are wielding a bow. - You can simplify the throwing operation by using the `Q' - command to select your preferred ``missile'', then using the `f' - command to throw it. You'll be prompted for a direction as - above, but you don't have to specify which item to throw each - time you use `f'. There is also an option, autoquiver, which has - NetHack choose another item to automatically fill your quiver - when the inventory slot used for `Q' runs out. - Some characters will throw multiple items in a single ac- - tion. Rangers, for instance, or anyone who achieves a high level - of proficiency in the relevant weapon skill (in bow skill if - you're wielding one to shoot arrows, or in sling skill if you're - wielding one to shoot stones). There is little you can do to - control this; if NetHack decides that you'll be shooting 3 arrows - on the current shot, then three arrows will travel in the direc- - tion you've indicated, even if the first or second succeeds in - killing the target. You can explicitly limit the number of shots - by using a numeric prefix before the `t' or `f' command. For ex- - ample, ``2f'' (or ``n2f'' if using number_pad mode) would ensure - that at most 2 arrows are shot even if NetHack decides that your - skill warrants 3. If you specify a larger number than would have - been shot (``4f'' in this example), you'll just end up shooting - the same number (3, here) as if no limit had been specified. + number_pad mode) would ensure that at most 2 arrows are shot even + if you could have fired 3. If you specify a larger number than + would have been shot (``4f'' in this example), you'll just end up + shooting the same number (3, here) as if no limit had been speci- + fied. Once the volley is in motion, all of the items will travel + in the same direction; if the first ones kill a monster, the oth- + ers can still continue beyond that spot. 7.2.2. Weapon proficiency @@ -1432,30 +1479,19 @@ become highly skilled in daggers or staves but not in swords or bows. - The `#enhance' extended command is used to review current - weapons proficiency (also spell proficiency) and to choose which + The `#enhance' extended command is used to review current + weapons proficiency (also spell proficiency) and to choose which skill(s) to improve when you've used one or more skills enough to become eligible to do so. The skill rankings are ``none'' (some- - times also referred to as ``restricted'', because you won't be - able to advance), ``unskilled'', ``basic'', ``skilled'', and + times also referred to as ``restricted'', because you won't be + able to advance), ``unskilled'', ``basic'', ``skilled'', and ``expert''. Restricted skills simply will not appear in the list - shown by `#enhance'. (Divine intervention might unrestrict a + shown by `#enhance'. (Divine intervention might unrestrict a particular skill, in which case it will start at unskilled and be - limited to basic.) Some characters can enhance their barehanded - combat or martial arts skill beyond expert to ``master'' or + limited to basic.) Some characters can enhance their barehanded + combat or martial arts skill beyond expert to ``master'' or ``grand master''. - - NetHack 3.3 August 2, 2000 - - - - - - - NetHack Guidebook 23 - - Use of a weapon in which you're restricted or unskilled will incur a modest penalty in the chance to hit a monster and also in the amount of damage done when you do hit; at basic level, there @@ -1471,14 +1507,29 @@ tal overall skills, so you need to actively choose which skills to enhance and which to ignore. + + + + + + NetHack 3.4 March 20, 2002 + + + + + + NetHack Guidebook 24 + + + 7.3. Armor (`[') Lots of unfriendly things lurk about; you need armor to pro- tect yourself from their blows. Some types of armor offer better - protection than others. Your armor class is a measure of this + protection than others. Your armor class is a measure of this protection. Armor class (AC) is measured as in AD&D, with 10 be- - ing the equivalent of no armor, and lower numbers meaning better - armor. Each suit of armor which exists in AD&D gives the same + ing the equivalent of no armor, and lower numbers meaning better + armor. Each suit of armor which exists in AD&D gives the same protection in NetHack. Here is an (incomplete) list of the armor classes provided by various suits of armor: @@ -1505,42 +1556,45 @@ can only wear one item of each category (one suit of armor, one cloak, one helmet, one shield, and so on) at a time. - If a piece of armor is enchanted, its armor protection will - be better (or worse) than normal, and its ``plus'' (or minus) - will subtract from your armor class. For example, a +1 chain - mail would give you better protection than normal chain mail, + If a piece of armor is enchanted, its armor protection will + be better (or worse) than normal, and its ``plus'' (or minus) + will subtract from your armor class. For example, a +1 chain + mail would give you better protection than normal chain mail, lowering your armor class one unit further to 4. When you put on + a piece of armor, you immediately find out the armor class and + any ``plusses'' it provides. Cursed pieces of armor usually have + negative enchantments (minuses) in addition to being unremovable. + + Many types of armor are subject to some kind of damage like + rust. Such damage can be repaired. Some types of armor may in- + hibit spell casting. + + The commands to use armor are `W' (wear) and `T' (take off). + The `A' command can also be used to take off armor as well as + other worn items. - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 - NetHack Guidebook 24 - a piece of armor, you immediately find out the armor class and - any ``plusses'' it provides. Cursed pieces of armor usually have - negative enchantments (minuses) in addition to being unremovable. - Many types of armor are subject to some kind of damage like - rust. Such damage can be repaired. Some types of armor may in- - hibit spell casting. + NetHack Guidebook 25 + - The commands to use armor are `W' (wear) and `T' (take off). - The `A' command can also be used to take off armor as well as - other worn items. 7.4. Food (`%') - Food is necessary to survive. If you go too long without - eating you will faint, and eventually die of starvation. Some - types of food will spoil, and become unhealthy to eat, if not + Food is necessary to survive. If you go too long without + eating you will faint, and eventually die of starvation. Some + types of food will spoil, and become unhealthy to eat, if not protected. Food stored in ice boxes or tins (``cans'') will usu- - ally stay fresh, but ice boxes are heavy, and tins take a while + ally stay fresh, but ice boxes are heavy, and tins take a while to open. When you kill monsters, they usually leave corpses which are @@ -1548,10 +1602,10 @@ give you special powers when you eat them. A good rule of thumb is ``you are what you eat.'' - Some character roles and some monsters are vegetarian. - Vegetarian monsters will typically never eat animal corpses, - while vegetarian players can, but with some rather unpleasant - side-effects. + Some character roles and some monsters are vegetarian. Veg- + etarian monsters will typically never eat animal corpses, while + vegetarian players can, but with some rather unpleasant side-ef- + fects. You can name one food item after something you like to eat with the fruit option. @@ -1560,8 +1614,8 @@ 7.5. Scrolls (`?') - Scrolls are labeled with various titles, probably chosen by - ancient wizards for their amusement value (ex. ``READ ME,'' or + Scrolls are labeled with various titles, probably chosen by + ancient wizards for their amusement value (ex. ``READ ME,'' or ``THANX MAUD'' backwards). Scrolls disappear after you read them (except for blank ones, without magic spells on them). @@ -1576,31 +1630,33 @@ feature on versions where NetHack mail delivery is triggered by electronic mail appearing in your system mailbox, you must let NetHack know where to look for new mail by setting the ``MAIL'' + environment variable to the file name of your mailbox. You may + also want to set the ``MAILREADER'' environment variable to the + file name of your favorite reader, so NetHack can shell to it + when you read the scroll. On versions of NetHack where mail is + randomly generated internal to the game, these environment vari- + ables are ignored. You can disable the mail daemon by turning + off the mail option. + The command to read a scroll is `r'. - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 - NetHack Guidebook 25 - environment variable to the file name of your mailbox. You may - also want to set the ``MAILREADER'' environment variable to the - file name of your favorite reader, so NetHack can shell to it - when you read the scroll. On versions of NetHack where mail is - randomly generated internal to the game, these environment vari- - ables are ignored. You can disable the mail daemon by turning - off the mail option. - The command to read a scroll is `r'. + NetHack Guidebook 26 + + 7.6. Potions (`!') - Potions are distinguished by the color of the liquid inside + Potions are distinguished by the color of the liquid inside the flask. They disappear after you quaff them. Clear potions are potions of water. Sometimes these are @@ -1614,10 +1670,10 @@ 7.7. Wands (`/') Magic wands usually have multiple magical charges. Some - wands are directional-you must give a direction in which to zap + wands are directional--you must give a direction in which to zap them. You can also zap them at yourself (just give a `.' or `s' for the direction). Be warned, however, for this is often unwise. - Other wands are nondirectional-they don't require a direction. + Other wands are nondirectional--they don't require a direction. The number of charges in a wand is random and decreases by one whenever you use it. @@ -1631,8 +1687,8 @@ the wand is recharged. In a truly desperate situation, when your back is up against - the wall, you might decide to go for broke and break your wand. - This is not for the faint of heart. Doing so will almost cer- + the wall, you might decide to go for broke and break your wand. + This is not for the faint of heart. Doing so will almost cer- tainly cause a catastrophic release of magical energies. When you have fully identified a particular wand, inventory @@ -1641,32 +1697,30 @@ then by its current number of charges. A current charge count of -1 is a special case indicating that the wand has been cancelled. + The command to use a wand is `z' (zap). To break one, use + the `a' (apply) command. + 7.8. Rings (`=') + Rings are very useful items, since they are relatively per- + manent magic, unlike the usually fleeting effects of potions, + scrolls, and wands. - NetHack 3.3 August 2, 2000 - - + Putting on a ring activates its magic. You can wear only + two rings, one on each ring finger. + NetHack 3.4 March 20, 2002 - NetHack Guidebook 26 - The command to use a wand is `z' (zap). To break one, use - the `a' (apply) command. - 7.8. Rings (`=') + NetHack Guidebook 27 - Rings are very useful items, since they are relatively per- - manent magic, unlike the usually fleeting effects of potions, - scrolls, and wands. - Putting on a ring activates its magic. You can wear only - two rings, one on each ring finger. - Most rings also cause you to grow hungry more rapidly, the + Most rings also cause you to grow hungry more rapidly, the rate varying with the type of ring. The commands to use rings are `P' (put on) and `R' (remove). @@ -1674,23 +1728,31 @@ 7.9. Spellbooks (`+') Spellbooks are tomes of mighty magic. When studied with the - `r' (read) command, they transfer to the reader the knowledge of - a spell (and therefore eventually become unreadable) - unless the - attempt backfires. Reading a cursed spellbook or one with mystic - runes beyond your ken can be harmful to your health! - - A spell (even when learned) can also backfire when you cast - it. If you attempt to cast a spell well above your experience - level, or if you have little skill with the appropriate spell - type, or cast it at a time when your luck is particularly bad, - you can end up wasting both the energy and the time required in + `r' (read) command, they transfer to the reader the knowledge of + a spell (and therefore eventually become unreadable) -- unless + the attempt backfires. Reading a cursed spellbook or one with + mystic runes beyond your ken can be harmful to your health! + + A spell (even when learned) can also backfire when you cast + it. If you attempt to cast a spell well above your experience + level, or if you have little skill with the appropriate spell + type, or cast it at a time when your luck is particularly bad, + you can end up wasting both the energy and the time required in casting. Casting a spell calls forth magical energies and focuses - them with your naked mind. Releasing the magical energy releases - some of your memory of the spell with it. Each time you cast a - spell, your familiarity with it will dwindle, until you eventual- - ly forget the details completely and must relearn it. + them with your naked mind. Some of the magical energy released + comes from within you, and casting several spells in a row may + tire you. Casting of spells also requires practice. With prac- + tice, your skill in each category of spell casting will improve. + Over time, however, your memory of each spell will dim, and you + will need to relearn it. + + Some spells are directional--you must give a direction in + which to cast them. You can also cast them at yourself (just + give a `.' or `s' for the direction). Be warned, however, for + this is often unwise. Other spells are nondirectional--they + don't require a direction. Just as weapons are divided into groups in which a character can become proficient (to varying degrees), spells are similarly @@ -1703,29 +1765,28 @@ various types of armor may interfere with that. The command to read a spellbook is the same as for scrolls, - `r' (read). The `+' command lists your current spells and the - number of spell points they require. The `Z' (cast) command - casts a spell. - + `r' (read). The `+' command lists your current spells, their + levels, categories, and chances for failure. The `Z' (cast) com- + mand casts a spell. + 7.10. Tools (`(') + Tools are miscellaneous objects with various purposes. Some + tools have a limited number of uses, akin to wand charges. For + example, lamps burn out after a while. Other tools are - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 - NetHack Guidebook 27 + NetHack Guidebook 28 - 7.10. Tools (`(') - Tools are miscellaneous objects with various purposes. Some - tools have a limited number of uses, akin to wand charges. For - example, lamps burn out after a while. Other tools are con- - tainers, which objects can be placed into or taken out of. + containers, which objects can be placed into or taken out of. The command to use tools is `a' (apply). @@ -1758,8 +1819,8 @@ 7.12. Gems (`*') - Some gems are valuable, and can be sold for a lot of gold. - They are also a far more efficient way of carrying your riches. + Some gems are valuable, and can be sold for a lot of gold. + They are also a far more efficient way of carrying your riches. Valuable gems increase your score if you bring them with you when you exit. @@ -1770,24 +1831,26 @@ 7.13. Large rocks (``') - Statues and boulders are not particularly useful, and are - generally heavy. It is rumored that some statues are not what + Statues and boulders are not particularly useful, and are + generally heavy. It is rumored that some statues are not what they seem. + Very large humanoids (giants and their ilk) have been known + to use boulders as weapons. - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 - NetHack Guidebook 28 - Very large humanoids (giants and their ilk) have been known - to use boulders as weapons. + NetHack Guidebook 29 + + 7.14. Gold (`$') @@ -1799,79 +1862,78 @@ 8. Conduct - As if winning NetHack were not difficult enough, certain - players seek to challenge themselves by imposing restrictions on - the way they play the game. The game automatically tracks some - of these challenges, which can be checked at any time with the - #conduct command or at the end of the game. When you perform an - action which breaks a challenge, it will no longer be listed. + As if winning NetHack were not difficult enough, certain + players seek to challenge themselves by imposing restrictions on + the way they play the game. The game automatically tracks some + of these challenges, which can be checked at any time with the + #conduct command or at the end of the game. When you perform an + action which breaks a challenge, it will no longer be listed. This gives players extra ``bragging rights'' for winning the game - with these challenges. Note that it is perfectly acceptable to - win the game without resorting to these restrictions and that it - is unusual for players to adhere to challenges the first time + with these challenges. Note that it is perfectly acceptable to + win the game without resorting to these restrictions and that it + is unusual for players to adhere to challenges the first time they win the game. - Several of the challenges are related to eating behavior. - The most difficult of these is the foodless challenge. Although + Several of the challenges are related to eating behavior. + The most difficult of these is the foodless challenge. Although creatures can survive long periods of time without food, there is - a physiological need for water; thus there is no restriction on - drinking beverages, even if they provide some minor food bene- - fits. Calling upon your god for help with starvation does not + a physiological need for water; thus there is no restriction on + drinking beverages, even if they provide some minor food bene- + fits. Calling upon your god for help with starvation does not violate any food challenges either. - A strict vegan diet is one which avoids any food derived - from animals. The primary source of nutrition is fruits and - vegetables. The corpses and tins of blobs (`b'), jellies (`j'), - and fungi (`F') are also considered to be vegetable matter. Cer- - tain human food is prepared without animal products; namely, lem- - bas wafers, cram rations, food rations (gunyoki), K-rations, and - C-rations. Metal or another normally indigestible material eaten + A strict vegan diet is one which avoids any food derived + from animals. The primary source of nutrition is fruits and veg- + etables. The corpses and tins of blobs (`b'), jellies (`j'), and + fungi (`F') are also considered to be vegetable matter. Certain + human food is prepared without animal products; namely, lembas + wafers, cram rations, food rations (gunyoki), K-rations, and C- + rations. Metal or another normally indigestible material eaten while polymorphed into a creature that can digest it is also con- - sidered vegan food. Note however that eating such items still + sidered vegan food. Note however that eating such items still counts against foodless conduct. - Vegetarians do not eat animals; however, they are less - selective about eating animal byproducts than vegans. In addi- - tion to the vegan items listed above, they may eat any kind of - pudding (`P') other than the black puddings, eggs and food made - from eggs (fortune cookies and pancakes), food made with milk - (cream pies and candy bars), and lumps of royal jelly. Monks are - expected to observe a vegetarian diet. + Vegetarians do not eat animals; however, they are less se- + lective about eating animal byproducts than vegans. In addition + to the vegan items listed above, they may eat any kind of pudding + (`P') other than the black puddings, eggs and food made from eggs + (fortune cookies and pancakes), food made with milk (cream pies + and candy bars), and lumps of royal jelly. Monks are expected to + observe a vegetarian diet. Eating any kind of meat violates the vegetarian, vegan, and foodless conducts. This includes tripe rations, the corpses or + tins of any monsters not mentioned above, and the various other + chunks of meat found in the dungeon. Swallowing and digesting a + monster while polymorphed is treated as if you ate the creature's - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 + NetHack Guidebook 30 - NetHack Guidebook 29 - tins of any monsters not mentioned above, and the various other - chunks of meat found in the dungeon. Swallowing and digesting a - monster while polymorphed is treated as if you ate the creature's - corpse. Eating leather, dragon hide, or bone items while po- - lymorphed into a creature that can digest it, or eating monster - brains while polymorphed into a (master) mind flayer, is con- - sidered eating an animal, although wax is only an animal bypro- - duct. - - Regardless of conduct, there will be some items which are - indigestible, and others which are hazardous to eat. Using a + corpse. Eating leather, dragon hide, or bone items while poly- + morphed into a creature that can digest it, or eating monster + brains while polymorphed into a (master) mind flayer, is consid- + ered eating an animal, although wax is only an animal byproduct. + + Regardless of conduct, there will be some items which are + indigestible, and others which are hazardous to eat. Using a swallow-and-digest attack against a monster is equivalent to eat- ing the monster's corpse. Please note that the term ``vegan'' is - used here only in the context of diet. You are still free to - choose not to use or wear items derived from animals (e.g. leath- - er, dragon hide, bone, horns, coral), but the game will not keep - track of this for you. Also note that ``milky'' potions may be a - translucent white, but they do not contain milk, so they are com- - patible with a vegan diet. Slime molds or player-defined - ``fruits'', although they could be anything from ``cherries'' to + used here only in the context of diet. You are still free to + choose not to use or wear items derived from animals (e.g. + leather, dragon hide, bone, horns, coral), but the game will not + keep track of this for you. Also note that ``milky'' potions may + be a translucent white, but they do not contain milk, so they are + compatible with a vegan diet. Slime molds or player-defined + ``fruits'', although they could be anything from ``cherries'' to ``pork chops'', are also assumed to be vegan. An atheist is one who rejects religion. This means that you @@ -1885,15 +1947,15 @@ figure; a true atheist would hear the words but attach no special meaning to them. - Most players fight with a wielded weapon (or tool intended + Most players fight with a wielded weapon (or tool intended to be wielded as a weapon). Another challenge is to win the game - without using such a wielded weapon. You are still permitted to - throw, fire, and kick weapons; use a wand, spell, or other type + without using such a wielded weapon. You are still permitted to + throw, fire, and kick weapons; use a wand, spell, or other type of item; or fight with your hands and feet. - In NetHack, a pacifist refuses to cause the death of any - other monster (i.e. if you would get experience for the death). - This is a particularly difficult challenge, although it is still + In NetHack, a pacifist refuses to cause the death of any + other monster (i.e. if you would get experience for the death). + This is a particularly difficult challenge, although it is still possible to gain experience by other means. An illiterate character cannot read or write. This includes @@ -1906,22 +1968,22 @@ starting inventory is assumed to be learned from your teachers prior to the start of the game and isn't counted. + There are several other minor challenges. It is possible to + eliminate a species of monsters by genocide; playing without this + feature is considered a challenge. You can change the form of + any object into another object of the same type (``polypiling'') - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 + NetHack Guidebook 31 - NetHack Guidebook 30 - There are several other minor challenges. It is possible to - eliminate a species of monsters by genocide; playing without this - feature is considered a challenge. You can change the form of - any object into another object of the same type (``polypiling'') or the form of your own body into another creature (``polyself'') by wand, spell, or potion of polymorph; avoiding these effects are each considered challenges. Finally, you may sometimes re- @@ -1932,33 +1994,33 @@ 9. Options - Due to variations in personal tastes and conceptions of how + Due to variations in personal tastes and conceptions of how NetHack should do things, there are options you can set to change how NetHack behaves. 9.1. Setting the options - Options may be set in a number of ways. Within the game, + Options may be set in a number of ways. Within the game, the `O' command allows you to view all options and change most of - them. You can also set options automatically by placing them in - the NETHACKOPTIONS environment variable or in a configuration + them. You can also set options automatically by placing them in + the NETHACKOPTIONS environment variable or in a configuration file. Some versions of NetHack also have front-end programs that allow you to set options before starting the game. 9.2. Using the NETHACKOPTIONS environment variable - The NETHACKOPTIONS variable is a comma-separated list of in- - itial values for the various options. Some can only be turned on - or off. You turn one of these on by adding the name of the op- - tion to the list, and turn it off by typing a `!' or ``no'' be- + The NETHACKOPTIONS variable is a comma-separated list of + initial values for the various options. Some can only be turned + on or off. You turn one of these on by adding the name of the + option to the list, and turn it off by typing a `!' or ``no'' be- fore the name. Others take a character string as a value. You can set string options by typing the option name, a colon or equals sign, and then the value of the string. The value is ter- minated by the next comma or the end of string. For example, to set up an environment variable so that ``au- - toquiver'' is on, ``autopickup'' is off, the name is set to - ``Blue Meanie'', and the fruit is set to ``papaya'', you would + toquiver'' is on, ``autopickup'' is off, the name is set to + ``Blue Meanie'', and the fruit is set to ``papaya'', you would enter the command % setenv NETHACKOPTIONS "autoquiver,\!autopickup,name:Blue Meanie,fruit:papaya" @@ -1971,35 +2033,35 @@ in sh or ksh. + 9.3. Using a configuration file + Any line in the configuration file starting with ``OP- + TIONS='' may be filled out with options in the same syntax as in + NETHACKOPTIONS. Any line starting with ``DUNGEON='', - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 + NetHack Guidebook 32 - NetHack Guidebook 31 - 9.3. Using a configuration file + ``EFFECTS='', ``MONSTERS='', ``OBJECTS='', ``TRAPS='', or ``BOUL- + DER='' is taken as defining the corresponding dungeon, effects, + monsters, objects traps or boulder option in a different syntax, + a sequence of decimal numbers giving the character position in + the current font to be used in displaying each entry. Such a se- + quence can be continued to multiple lines by putting a `\' at the + end of each line to be continued. Any line starting with `#' is + treated as a comment. - Any line in the configuration file starting with ``OP- - TIONS='' may be filled out with options in the same syntax as in - NETHACKOPTIONS. Any line starting with ``DUNGEON='', ``EF- - FECTS='', ``MONSTERS='', ``OBJECTS='', or ``TRAPS='' is taken as - defining the corresponding dungeon, effects, monsters, objects or - traps option in a different syntax, a sequence of decimal numbers - giving the character position in the current font to be used in - displaying each entry. Such a sequence can be continued to mul- - tiple lines by putting a `\' at the end of each line to be con- - tinued. Any line starting with `#' is treated as a comment. - - The default name of the configuration file varies on dif- - ferent operating systems, but NETHACKOPTIONS can also be set to - the full name of a file you want to use (possibly preceded by an + The default name of the configuration file varies on differ- + ent operating systems, but NETHACKOPTIONS can also be set to the + full name of a file you want to use (possibly preceded by an `@'). 9.4. Customization options @@ -2014,18 +2076,22 @@ default is to randomly pick an appropriate alignment. Can- not be set with the `O' command. + autodig + Automatically dig if you are wielding a digging tool and + moving into a place that can be dug (default false). + autopickup Automatically pick up things onto which you move (default on). autoquiver - This option controls what happens when you attempt the `f' + This option controls what happens when you attempt the `f' (fire) command with an empty quiver. When true, the comput- - er will fill your quiver with some suitable weapon. Note - that it will not take into account the blessed/cursed - status, enchantment, damage, or quality of the weapon; you - are free to manually fill your quiver with the `Q' command - instead. If no weapon is found or the option is false, the + er will fill your quiver with some suitable weapon. Note + that it will not take into account the blessed/cursed sta- + tus, enchantment, damage, or quality of the weapon; you are + free to manually fill your quiver with the `Q' command in- + stead. If no weapon is found or the option is false, the `t' (throw) command is executed instead. (default false) BIOS @@ -2034,46 +2100,45 @@ on machines with an IBM PC compatible BIOS ROM (default off, OS/2, PC, and ST NetHack only). - catname - Name your starting cat (ex. ``catname:Morris''). Cannot be - set with the `O' command. + boulder + Set the character used to display boulders (default is rock + class symbol). - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 + NetHack Guidebook 33 + - NetHack Guidebook 32 + catname + Name your starting cat (ex. ``catname:Morris''). Cannot be + set with the `O' command. character - Pick your type of character (ex. ``character:Monk''); - synonym for ``role''. See ``name'' for an alternate method - of specifying your role. Normally only the first letter of - the value is examined; the string ``random'' is an excep- - tion. + Pick your type of character (ex. ``character:Monk''); syn- + onym for ``role''. See ``name'' for an alternate method of + specifying your role. Normally only the first letter of the + value is examined; the string ``random'' is an exception. checkpoint - Save game state after each level change, for possible - recovery after program crash (default on). + Save game state after each level change, for possible recov- + ery after program crash (default on). checkspace - Check free disk space before writing files to disk (default - on). You may have to turn this off if you have more than 2 - GB free space on the partition used for your save and level - files. Only applies when MFLOPPY was defined during compi- + Check free disk space before writing files to disk (default + on). You may have to turn this off if you have more than 2 + GB free space on the partition used for your save and level + files. Only applies when MFLOPPY was defined during compi- lation. - color - Use color for different monsters, objects, and dungeon - features (default on for microcomputers). - confirm - Have user confirm attacks on pets, shopkeepers, and other + Have user confirm attacks on pets, shopkeepers, and other peaceable creatures (default on). DECgraphics @@ -2086,119 +2151,132 @@ override the selections with your own graphics strings. disclose - Offer to disclose various information when the game ends - (default all). The possibilities are identifying your in- - ventory ('i'), disclosing your attributes ('a'), summarizing - monsters that have been vanquished ('v'), listing monster - species that have been genocided ('g'), and displaying your - conduct ('c'). Note that the vanquished monsters list in- - cludes all monsters killed by traps and each other as well - as by you. + Controls options for disclosing various information when the + game ends (defaults to all possibilities being disclosed). + The possibilities are: - dogname - Name your starting dog (ex. ``dogname:Fang''). Cannot be - set with the `O' command. + i - disclose your inventory. + a - disclose your attributes. + v - summarize monsters that have been vanquished. + g - list monster species that have been genocided. + c - display your conduct. - dungeon - Set the graphics symbols for displaying the dungeon (default - `` |--------||.-|++##.##<><>_|\\#{}.}..## #}''). The - dungeon option should be followed by a string of 1-41 char- - acters to be used instead of the default map-drawing + Each disclosure possibility can optionally be preceded by a + prefix which let you refine how it behaves. Here are the + valid prefixes: + y - prompt you and default to yes on the prompt. + n - prompt you and default to no on the prompt. + + - disclose it without prompting. + - - do not disclose it and do not prompt. - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 - NetHack Guidebook 33 + + NetHack Guidebook 34 + - characters. The dungeon map will use the characters you - specify instead of the default symbols, and default symbols - for any you do not specify. Remember that you may need to - escape some of these characters on a command line if they - are special to your shell. + (ex. ``disclose:yi na +v -g -c'') The example sets inventory + to prompt and default to yes, attributes to prompt and de- + fault to no, vanquished to disclose without prompting, geno- + cided to not disclose and not to prompt, conduct to not dis- + close and not to prompt. Note that the vanquished monsters + list includes all monsters killed by traps and each other as + well as by you. - Note that NetHack escape-processes this option string in - conventional C fashion. This means that `\' is a prefix to - take the following character literally. Thus `\' needs to - be represented as `\\'. The special escape form `\m' + dogname + Name your starting dog (ex. ``dogname:Fang''). Cannot be + set with the `O' command. + + dungeon + Set the graphics symbols for displaying the dungeon (default + `` |--------||.-|++##.##<><>_|\\#{}.}..## #}''). The dun- + geon option should be followed by a string of 1-41 charac- + ters to be used instead of the default map-drawing charac- + ters. The dungeon map will use the characters you specify + instead of the default symbols, and default symbols for any + you do not specify. Remember that you may need to escape + some of these characters on a command line if they are spe- + cial to your shell. + + Note that NetHack escape-processes this option string in + conventional C fashion. This means that `\' is a prefix to + take the following character literally. Thus `\' needs to + be represented as `\\'. The special escape form `\m' switches on the meta bit in the following character, and the `^' prefix causes the following character to be treated as a control character. - The order of the symbols is: solid rock, vertical wall, - horizontal wall, upper left corner, upper right corner, - lower left corner, lower right corner, cross wall, upward T + The order of the symbols is: solid rock, vertical wall, + horizontal wall, upper left corner, upper right corner, low- + er left corner, lower right corner, cross wall, upward T wall, downward T wall, leftward T wall, rightward T wall, no - door, vertical open door, horizontal open door, vertical - closed door, horizontal closed door, iron bars, tree, floor - of a room, dark corridor, lit corridor, stairs up, stairs - down, ladder up, ladder down, altar, grave, throne, kitchen - sink, fountain, pool or moat, ice, lava, vertical lowered - drawbridge, horizontal lowered drawbridge, vertical raised - drawbridge, horizontal raised drawbridge, air, cloud, under + door, vertical open door, horizontal open door, vertical + closed door, horizontal closed door, iron bars, tree, floor + of a room, dark corridor, lit corridor, stairs up, stairs + down, ladder up, ladder down, altar, grave, throne, kitchen + sink, fountain, pool or moat, ice, lava, vertical lowered + drawbridge, horizontal lowered drawbridge, vertical raised + drawbridge, horizontal raised drawbridge, air, cloud, under water. You might want to use `+' for the corners and T walls for a - more aesthetic, boxier display. Note that in the next - release, new symbols may be added, or the present ones rear- + more aesthetic, boxier display. Note that in the next re- + lease, new symbols may be added, or the present ones rear- ranged. Cannot be set with the `O' command. effects Set the graphics symbols for displaying special effects (de- - fault ``|-\\/*!)(0#@*/-\\||\\-//-\\| |\\-/''). The effects - option should be followed by a string of 1-29 characters to - be used instead of the default special-effects characters. - This string is subjected to the same processing as the - dungeon option. + fault ``|-\\/*!)(0#@*/-\\||\\-//-\\| |\\-/''). The effects - The order of the symbols is: vertical beam, horizontal - beam, left slant, right slant, digging beam, camera flash - beam, left boomerang, right boomerang, four glyphs giving - the sequence for magic resistance displays, the eight sur- - rounding glyphs for swallowed display, nine glyphs for ex- - plosions. An explosion consists of three rows (top, middle, - and bottom) of three characters. The explosion is centered - in the center of this 3 by 3 array. - Note that in the next release, new symbols may be added, or - the present ones rearranged. + NetHack 3.4 March 20, 2002 - NetHack 3.3 August 2, 2000 + NetHack Guidebook 35 + option should be followed by a string of 1-29 characters to + be used instead of the default special-effects characters. + This string is subjected to the same processing as the dun- + geon option. - NetHack Guidebook 34 + The order of the symbols is: vertical beam, horizontal + beam, left slant, right slant, digging beam, camera flash + beam, left boomerang, right boomerang, four glyphs giving + the sequence for magic resistance displays, the eight sur- + rounding glyphs for swallowed display, nine glyphs for ex- + plosions. An explosion consists of three rows (top, middle, + and bottom) of three characters. The explosion is centered + in the center of this 3 by 3 array. + Note that in the next release, new symbols may be added, or + the present ones rearranged. Cannot be set with the `O' command. - eight_bit_tty - Pass eight-bit character values (for example, specified with - the traps option) straight through to your terminal (default - off). Only applies to the tty port. - extmenu Changes the extended commands interface to pop-up a menu of - available commands. It is keystroke compatible with the + available commands. It is keystroke compatible with the traditional interface except that it does not require that you hit Enter. It is implemented only by the tty port (de- fault off), when the game has been compiled to support tty graphics. female - An obsolete synonym for ``gender:female''. Cannot be set + An obsolete synonym for ``gender:female''. Cannot be set with the `O' command. fixinv @@ -2215,41 +2293,34 @@ ready exist in NetHack, so don't use those. gender - Your starting gender (gender:male or gender:female). You - may specify just the first letter. Although you can still - denote your gender using the ``male'' and ``female'' op- - tions, the ``gender'' option will take precedence. The de- - fault is to randomly pick an appropriate gender. Cannot be + Your starting gender (gender:male or gender:female). You + may specify just the first letter. Although you can still + denote your gender using the ``male'' and ``female'' op- + tions, the ``gender'' option will take precedence. The de- + fault is to randomly pick an appropriate gender. Cannot be set with the `O' command. help If more information is available for an object looked at with the `/' command, ask if you want to see it (default - on). Turning help off makes just looking at things faster, - since you aren't interrupted with the ``More info?'' prompt, - but it also means that you might miss some interesting - and/or important information. - - hilite_pet - Visually distinguish pets from similar animals (default - off). In text windowing, use text highlighting when color - is turned off; with X tiles, display a heart symbol near - pets. + NetHack 3.4 March 20, 2002 - NetHack 3.3 August 2, 2000 - + NetHack Guidebook 36 - NetHack Guidebook 35 + on). Turning help off makes just looking at things faster, + since you aren't interrupted with the ``More info?'' prompt, + but it also means that you might miss some interesting + and/or important information. horsename - Name your starting horse (ex. ``horsename:Trigger''). Can- + Name your starting horse (ex. ``horsename:Trigger''). Can- not be set with the `O' command. IBMgraphics @@ -2273,135 +2344,150 @@ held by your character as lit (default off). mail - Enable mail delivery during the game. + Enable mail delivery during the game (default on). male An obsolete synonym for ``gender:male''. Cannot be set with the `O' command. menustyle - Controls the interface used when you need to choose various - objects (in response to the Drop command, for instance). + Controls the interface used when you need to choose various + objects (in response to the Drop command, for instance). The value specified should be the first letter of one of the following: traditional, combination, partial, or full. - Traditional was the only interface available for earlier - versions; it consists of a prompt for object class charac- - ters, followed by an object-by-object prompt for all items - matching the selected object class(es). Combination starts - with a prompt for object class(es) of interest, but then - displays a menu of matching objects rather than prompting - one-by-one. Partial skips the object class filtering and + Traditional was the only interface available for earlier + versions; it consists of a prompt for object class charac- + ters, followed by an object-by-object prompt for all items + matching the selected object class(es). Combination starts + with a prompt for object class(es) of interest, but then + displays a menu of matching objects rather than prompting + one-by-one. Partial skips the object class filtering and immediately displays a menu of all objects. Full displays a - menu of object classes rather than a character prompt, and + menu of object classes rather than a character prompt, and then a menu of matching objects for selection. menu_deselect_all Menu character accelerator to deselect all items in a menu. - Implemented by the X11 and tty ports. Default '-'. - menu_deselect_page - Menu character accelerator deselect all items on this page - of a menu. Implemented only by the tty port. Default '\'. + NetHack 3.4 March 20, 2002 - NetHack 3.3 August 2, 2000 + NetHack Guidebook 37 - NetHack Guidebook 36 + Implemented by the Amiga, Gem, X11 and tty ports. Default + '-'. + + menu_deselect_page + Menu character accelerator deselect all items on this page + of a menu. Implemented by the Amiga, Gem and tty ports. + Default '\'. menu_first_page Menu character accelerator to jump to the first page in a - menu. Implemented only by the tty port. Default '^'. + menu. Implemented by the Amiga, Gem and tty ports. Default + '^'. menu_invert_all Menu character accelerator to invert all items in a menu. - Implemented by the X11 and tty ports. Default '@'. + Implemented by the Amiga, Gem, X11 and tty ports. Default + '@'. menu_invert_page Menu character accelerator to invert all items on this page - of a menu. Implemented only by the tty port. Default '~'. + of a menu. Implemented by the Amiga, Gem and tty ports. + Default '~'. menu_last_page Menu character accelerator to jump to the last page in a - menu. Implemented only by the tty port. Default '|'. + menu. Implemented by the Amiga, Gem and tty ports. Default + '|'. menu_next_page Menu character accelerator to goto the next menu page. Im- - plemented only by the tty port. Default '>'. + plemented by the Amiga, Gem and tty ports. Default '>'. menu_previous_page - Menu character accelerator to goto the previous menu page. - Implemented only by the tty port. Default '<'. + Menu character accelerator to goto the previous menu page. + Implemented by the Amiga, Gem and tty ports. Default '<'. menu_search Menu character accelerator to search for a menu item. Im- - plemented only by the X11 port. Default ':'. + plemented by the Amiga, Gem and X11 ports. Default ':'. menu_select_all - Menu character accelerator to select all items in a menu. - Implemented by the X11 and tty ports. Default '.'. + Menu character accelerator to select all items in a menu. + Implemented by the Amiga, Gem, X11 and tty ports. Default + '.'. menu_select_page - Menu character accelerator to select all items on this page - of a menu. Implemented only by the tty port. Default ','. + Menu character accelerator to select all items on this page + of a menu. Implemented by the Amiga, Gem and tty ports. + Default ','. monsters - Set the characters used to display monster classes (default - ``abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX- - YZ@ '&;:~]''). This string is subjected to the same pro- - cessing as the dungeon option. The order of the symbols is - ant or other insect, blob, cockatrice, dog or other canine, - eye or sphere, feline, gremlin, humanoid, imp or minor - demon, jelly, kobold, leprechaun, mimic, nymph, orc, pi- - ercer, quadruped, rodent, spider, trapper or lurker above, - horse or unicorn, vortex, worm, xan or other - mythical/fantastic insect, light, zruty, angelic being, bat - or bird, centaur, dragon, elemental, fungus or mold, gnome, - giant humanoid, invisible monster, jabberwock, Keystone Kop, - lich, mummy, naga, ogre, pudding or ooze, quantum mechanic, - rust monster, snake, troll, umber hulk, vampire, wraith, - xorn, yeti or ape or other large beast, zombie, human, - ghost, golem, demon, sea monster, lizard, long worm tail, - and mimic. Cannot be set with the `O' command. + Set the characters used to display monster classes (default + ``abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTU- + VWXYZ@ '&;:~]''). This string is subjected to the same - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 + NetHack Guidebook 38 - NetHack Guidebook 37 + processing as the dungeon option. The order of the symbols + is ant or other insect, blob, cockatrice, dog or other ca- + nine, eye or sphere, feline, gremlin, humanoid, imp or minor + demon, jelly, kobold, leprechaun, mimic, nymph, orc, + piercer, quadruped, rodent, spider, trapper or lurker above, + horse or unicorn, vortex, worm, xan or other mythical/fan- + tastic insect, light, zruty, angelic being, bat or bird, + centaur, dragon, elemental, fungus or mold, gnome, giant hu- + manoid, invisible monster, jabberwock, Keystone Kop, lich, + mummy, naga, ogre, pudding or ooze, quantum mechanic, rust + monster, snake, troll, umber hulk, vampire, wraith, xorn, + yeti or ape or other large beast, zombie, human, ghost, + golem, demon, sea monster, lizard, long worm tail, and mim- + ic. Cannot be set with the `O' command. + msghistory The number of top line messages to save (and recall with ^P) (default 20). Cannot be set with the `O' command. + msg_window + Use a screen-size window to show the previous messages with + ^P instead of showing them one at a time. (Currently imple- + mented for tty only.) + name Set your character's name (defaults to your user name). You can also set your character's role by appending a dash and one or more letters of the role (that is, by suffixing one of -A -B -C -H -K -M -P -Ra -Ro -S -T -V -W). If -@ is used - for the role, then a random one will be automatically - chosen. Cannot be set with the `O' command. + for the role, then a random one will be automatically cho- + sen. Cannot be set with the `O' command. news - Read the NetHack news file, if present (default on). Since - the news is shown at the beginning of the game, there's no + Read the NetHack news file, if present (default on). Since + the news is shown at the beginning of the game, there's no point in setting this with the `O' command. null Send padding nulls to the terminal (default off). number_pad - Use the number keys to move instead of [yuhjklbn] (default + Use the number keys to move instead of [yuhjklbn] (default off). objects @@ -2413,6 +2499,19 @@ wand, gold, gem or rock, boulder or statue, iron ball, chain, and venom. Cannot be set with the `O' command. + + + + NetHack 3.4 March 20, 2002 + + + + + + NetHack Guidebook 39 + + + packorder Specify the order to list object types in (default ``")[%?+!=/(*`0_''). The value of this option should be a @@ -2427,26 +2526,14 @@ pettype Specify the type of your initial pet, if you are playing a - character class that uses multiple types of pets. Possible - values are ``cat'' and ``dog''. Cannot be set with the `O' - command. + character class that uses multiple types of pets; or choose + to have no initial pet at all. Possible values are ``cat'', + ``dog'' and ``none''. Cannot be set with the `O' command. pickup_burden - When you pick up an item that would exceed this encumbrance - level (Unburdened, Burdened, streSsed, straiNed, overTaxed, - - - NetHack 3.3 August 2, 2000 - - - - - - - NetHack Guidebook 38 - - - or overLoaded), you will be asked if you want to continue. + When you pick up an item that would exceed this encumbrance + level (Unburdened, Burdened, streSsed, straiNed, overTaxed, + or overLoaded), you will be asked if you want to continue. (Default `S'). pickup_types @@ -2456,15 +2543,9 @@ prayconfirm Prompt for confirmation before praying (default on). - preload_tiles - For the protected mode MSDOS version, control whether tiles - get pre-loaded into RAM at the start of the game. Doing so - enhances performance of the tile graphics, but uses more - memory. (default on). Cannot be set with the `O' command. - pushweapon - Using the `w' (wield) command when already wielding some- - thing pushes the old item into your secondary weapon slot + Using the `w' (wield) command when already wielding some- + thing pushes the old item into your secondary weapon slot (default off). race Selects your race (for example, ``race:human''). Default is @@ -2485,6 +2566,18 @@ for ``character''. See ``name'' for an alternate method of specifying your role. Normally only the first letter of the value is examined; `r' is an exception with ``Rogue'', + + + NetHack 3.4 March 20, 2002 + + + + + + NetHack Guidebook 40 + + + ``Ranger'', and ``random'' values. safe_pet @@ -2492,28 +2585,17 @@ on). scores - Control what parts of the score list you are shown at the + Control what parts of the score list you are shown at the end (ex. ``scores:5 top scores/4 around my score/own - scores''). Only the first letter of each category (`t', + scores''). Only the first letter of each category (`t', `a', or `o') is necessary. showexp Show your accumulated experience points on bottom line (de- fault off). - - NetHack 3.3 August 2, 2000 - - - - - - - NetHack Guidebook 39 - - showscore - Show your approximate accumulated score on bottom line (de- + Show your approximate accumulated score on bottom line (de- fault off). silent @@ -2523,34 +2605,51 @@ Sort the pack contents by type when displaying inventory (default on). + sparkle + Display a sparkly effect when a monster (including yourself) + is hit by an attack to which it is resistant (default on). + standout Boldface monsters and ``--More--'' (default off). suppress_alert - This option may be set to a NetHack version level to - suppress alert notification messages about feature changes - for that and prior versions (ex. ``suppress_alert:3.3.1''). + This option may be set to a NetHack version level to sup- + press alert notification messages about feature changes for + that and prior versions (ex. ``suppress_alert:3.3.1''). time Show the elapsed game time in turns on bottom line (default off). timed_delay - When pausing momentarily for display effect, such as with + When pausing momentarily for display effect, such as with explosions and moving objects, use a timer rather than send- ing extra characters to the screen. (Applies to ``tty'' in- - terface only; ``X11'' interface always uses a timer based + terface only; ``X11'' interface always uses a timer based delay. The default is on if configured into the program.) tombstone Draw a tombstone graphic upon your death (default on). + + + + NetHack 3.4 March 20, 2002 + + + + + + NetHack Guidebook 41 + + + toptenwin - Put the ending display in a NetHack window instead of on - stdout (default off). Setting this option makes the score - list visible when a windowing version of NetHack is started - without a parent window, but it no longer leaves the score - list around after game end on a terminal or emulating win- + Put the ending display in a NetHack window instead of on + stdout (default off). Setting this option makes the score + list visible when a windowing version of NetHack is started + without a parent window, but it no longer leaves the score + list around after game end on a terminal or emulating win- dow. traps @@ -2563,20 +2662,9 @@ The order of the symbols is: arrow trap, dart trap, falling rock trap, squeaky board, bear trap, land mine, rolling boulder trap, sleeping gas trap, rust trap, fire trap, pit, - spiked pit, hole, trap door, teleportation trap, level - teleporter, magic portal, web, statue trap, magic trap, - anti-magic field, polymorph trap. - - - NetHack 3.3 August 2, 2000 - - - - - - - NetHack Guidebook 40 - + spiked pit, hole, trap door, teleportation trap, level tele- + porter, magic portal, web, statue trap, magic trap, anti- + magic field, polymorph trap. Cannot be set with the `O' command. @@ -2585,25 +2673,191 @@ videocolors Set the color palette for PC systems using NO_TERMS (default - 4-2-6-1-5-3-15-12-10-14-9-13-11). The order of colors is - red, green, brown, blue, magenta, cyan, bright.white, - bright.red, bright.green, yellow, bright.blue, - bright.magenta, and bright.cyan. Cannot be set with the `O' - command. + 4-2-6-1-5-3-15-12-10-14-9-13-11). The order of colors is + red, green, brown, blue, magenta, cyan, bright.white, + bright.red, bright.green, yellow, bright.blue, bright.magen- + ta, and bright.cyan. Cannot be set with the `O' command. videoshades - Set the intensity level of the three gray scales available - (default dark normal light, PC NetHack only). If the game + Set the intensity level of the three gray scales available + (default dark normal light, PC NetHack only). If the game display is difficult to read, try adjusting these scales; if - this does not correct the problem, try !color. Cannot be + this does not correct the problem, try !color. Cannot be set with the `O' command. windowtype - Select which windowing system to use, such as ``tty'' or - ``X11'' (default depends on version). Cannot be set with + Select which windowing system to use, such as ``tty'' or + ``X11'' (default depends on version). Cannot be set with the `O' command. - 9.5. Configuring NetHack for Play by the Blind + 9.5. Window Port Customization options + + Here are explanations of the various options that are used + to customize and change the characteristics of the windowtype + that you have chosen. Character strings that are too long may be + truncated. Not all window ports will adjust for all settings + listed here. You can safely add any of these options to your + config file, and if the window port is capable of adjusting to + + + NetHack 3.4 March 20, 2002 + + + + + + NetHack Guidebook 42 + + + + suit your preferences, it will attempt to do so. If it can't it + will silently ignore it. You can find out if an option is sup- + ported by the window port that you are currently using by check- + ing to see if it shows up in the Options list. Some options are + dynamic and can be specified during the game with the `O' com- + mand. + + align_message + Where to align or place the message window (top, bottom, + left, or right) + + align_status + Where to align or place the status window (top, bottom, + left, or right). + + ascii_map + NetHack should display an ascii character map if it can. + + color + NetHack should display color if it can for different mon- + sters, objects, and dungeon features + + eight_bit_tty + NetHack should pass eight-bit character values (for example, + specified with the traps option) straight through to your + terminal (default off). + + font_map + NetHack should use a font by the chosen name for the map + window. + + font_menu + NetHack should use a font by the chosen name for menu win- + dows. + + font_message + NetHack should use a font by the chosen name for the message + window. + + font_status + NetHack should use a font by the chosen name for the status + window. + + font_text + NetHack should use a font by the chosen name for text win- + dows. + + font_size_map + NetHack should use this size font for the map window. + + font_size_menu + NetHack should use this size font for menu windows. + + + + + NetHack 3.4 March 20, 2002 + + + + + + NetHack Guidebook 43 + + + + font_size_message + NetHack should use this size font for the message window. + + font_size_status + NetHack should use this size font for the status window. + + font_size_text + NetHack should use this size font for text windows. + + hilite_pet + Visually distinguish pets from similar animals (default + off). The behavior of this option depends on the type of + windowing you use. In text windowing, text highlighting or + inverse video is often used; with tiles, generally displays + a heart symbol near pets. + + large_font + NetHack should use a large font. + + map_mode + NetHack should display the map in the manner specified. + + player_selection + NetHack should pop up dialog boxes, or use prompts for char- + acter selection. + + popup_dialog + NetHack should pop up dialog boxes for input. + + preload_tiles + NetHack should preload tiles into memory. For example, in + the protected mode MSDOS version, control whether tiles get + pre-loaded into RAM at the start of the game. Doing so en- + hances performance of the tile graphics, but uses more memo- + ry. (default on). Cannot be set with the `O' command. + + scroll_margin + NetHack should scroll the display when the hero or cursor is + this number of cells away from the edge of the window. + + splash_screen + NetHack should display an opening splash screen when it + starts up (default yes). + + tiled_map + NetHack should display a tiled map if it can. + + tile_file + Specify the name of an alternative tile file to override the + default. + + tile_height + Specify the preferred height of each tile in a tile capable + port. + + + NetHack 3.4 March 20, 2002 + + + + + + NetHack Guidebook 44 + + + + tile_width + Specify the preferred width of each tile in a tile capable + port + + use_inverse + NetHack should display inverse when the game specifies it. + + vary_msgcount + NetHack should display this number of messages at a time in + the message window. + + windowcolors + NetHack should display windows with the specified fore- + ground/background colors if it can. + + 9.6. Configuring NetHack for Play by the Blind NetHack can be set up to use only standard ASCII characters for making maps of the dungeons. This makes the MS-DOS versions @@ -2632,37 +2886,37 @@ and with editing files, you may want to alter settings to better suit your preferences. Instructions on how to do this are includ- ed in the NHAccess.nh file itself. The most crucial settings to + make the game accessible are: + IBMgraphics + Disable IBMgraphics by commenting out this option. - NetHack 3.3 August 2, 2000 + menustyle:traditional + This will assist in the interface to speech synthesizers. + number_pad + A lot of speech access programs use the number-pad to review + NetHack 3.4 March 20, 2002 - NetHack Guidebook 41 - make the game accessible are: + NetHack Guidebook 45 - IBMgraphics - Disable IBMgraphics by commenting out this option. - menustyle:traditional - This will assist in the interface to speech synthesizers. - number_pad - A lot of speech access programs use the number-pad to review - the screen. If this is the case, turn off the number_pad - option and use the traditional Rogue-like commands. + the screen. If this is the case, disable the number_pad op- + tion and use the traditional Rogue-like commands. Character graphics - Comment out all character graphics sets found near the bot- - tom of the defaults.nh file. Most of these replace - NetHack's default representation of the dungeon using stan- - dard ASCII characters with fancier characters from extended - character sets, and these fancier characters can annoy + Comment out all character graphics sets found near the bot- + tom of the defaults.nh file. Most of these replace + NetHack's default representation of the dungeon using stan- + dard ASCII characters with fancier characters from extended + character sets, and these fancier characters can annoy screen-readers. 10. Scoring @@ -2686,7 +2940,7 @@ whatever you have. If you quit, you keep all your gold, but if you swing and live, you might find more. - If you just want to see what the current top players/games + If you just want to see what the current top players/games list is, you can type nethack -s all on most versions. @@ -2699,30 +2953,34 @@ files and cheat death, at the paltry cost of not getting on the high score list. + There are two ways of enabling explore mode. One is to + start the game with the -X switch. The other is to issue the `X' + command while already playing the game. The other benefits of + explore mode are left for the trepid reader to discover. - NetHack 3.3 August 2, 2000 - NetHack Guidebook 42 + NetHack 3.4 March 20, 2002 + + - There are two ways of enabling explore mode. One is to - start the game with the -X switch. The other is to issue the `X' - command while already playing the game. The other benefits of - explore mode are left for the trepid reader to discover. + + NetHack Guidebook 46 + 12. Credits - The original hack game was modeled on the Berkeley UNIX ro- - gue game. Large portions of this paper were shamelessly cribbed - from A Guide to the Dungeons of Doom, by Michael C. Toy and Ken- - neth C. R. C. Arnold. Small portions were adapted from Further - Exploration of the Dungeons of Doom, by Ken Arromdee. + The original hack game was modeled on the Berkeley UNIX + rogue game. Large portions of this paper were shamelessly + cribbed from A Guide to the Dungeons of Doom, by Michael C. Toy + and Kenneth C. R. C. Arnold. Small portions were adapted from + Further Exploration of the Dungeons of Doom, by Ken Arromdee. NetHack is the product of literally dozens of people's work. Main events in the course of the game development are described @@ -2733,55 +2991,55 @@ Woodland, Mike Thome and Jon Payne. Andries Brouwer did a major re-write, transforming Hack into - a very different game, and published (at least) three versions + a very different game, and published (at least) three versions (1.0.1, 1.0.2, and 1.0.3) for UNIX machines to the Usenet. - Don G. Kneller ported Hack 1.0.3 to Microsoft C and MS-DOS, - producing PC HACK 1.01e, added support for DEC Rainbow graphics - in version 1.03g, and went on to produce at least four more ver- + Don G. Kneller ported Hack 1.0.3 to Microsoft C and MS-DOS, + producing PC HACK 1.01e, added support for DEC Rainbow graphics + in version 1.03g, and went on to produce at least four more ver- sions (3.0, 3.2, 3.51, and 3.6). R. Black ported PC HACK 3.51 to Lattice C and the Atari 520/1040ST, producing ST Hack 1.03. Mike Stephenson merged these various versions back together, - incorporating many of the added features, and produced NetHack - 1.4. He then coordinated a cast of thousands in enhancing and - debugging NetHack 1.4 and released NetHack versions 2.2 and 2.3. + incorporating many of the added features, and produced NetHack + 1.4. He then coordinated a cast of thousands in enhancing and + debugging NetHack 1.4 and released NetHack versions 2.2 and 2.3. Later, Mike coordinated a major rewrite of the game, heading a team which included Ken Arromdee, Jean-Christophe Collet, Steve - Creps, Eric Hendrickson, Izchak Miller, John Rupley, Mike - Threepoint, and Janet Walz, to produce NetHack 3.0c. + Creps, Eric Hendrickson, Izchak Miller, John Rupley, Mike Threep- + oint, and Janet Walz, to produce NetHack 3.0c. NetHack 3.0 was ported to the Atari by Eric R. Smith, to OS/2 by Timo Hakulinen, and to VMS by David Gentzel. The three of them and Kevin Darcy later joined the main development team to produce subsequent revisions of 3.0. - Olaf Seibert ported NetHack 2.3 and 3.0 to the Amiga. Norm - Meluch, Stephen Spackman and Pierre Martineau designed overlay - code for PC NetHack 3.0. Johnny Lee ported NetHack 3.0 to the - Macintosh. Along with various other Dungeoneers, they continued - to enhance the PC, Macintosh, and Amiga ports through the later + Olaf Seibert ported NetHack 2.3 and 3.0 to the Amiga. Norm + Meluch, Stephen Spackman and Pierre Martineau designed overlay + code for PC NetHack 3.0. Johnny Lee ported NetHack 3.0 to the + Macintosh. Along with various other Dungeoneers, they continued + to enhance the PC, Macintosh, and Amiga ports through the later + revisions of 3.0. + Headed by Mike Stephenson and coordinated by Izchak Miller + and Janet Walz, the development team which now included Ken Ar- + romdee, David Cohrs, Jean-Christophe Collet, Kevin Darcy, Matt + Day, Timo Hakulinen, Steve Linhart, Dean Luick, Pat Rankin, Eric - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 - NetHack Guidebook 43 + NetHack Guidebook 47 - revisions of 3.0. - Headed by Mike Stephenson and coordinated by Izchak Miller - and Janet Walz, the development team which now included Ken Ar- - romdee, David Cohrs, Jean-Christophe Collet, Kevin Darcy, Matt - Day, Timo Hakulinen, Steve Linhart, Dean Luick, Pat Rankin, Eric Raymond, and Eric Smith undertook a radical revision of 3.0. They re-structured the game's design, and re-wrote major parts of the code. They added multiple dungeons, a new display, special @@ -2799,17 +3057,17 @@ Jon W{tte and Hao-yang Wang, with help from Ross Brown, Mike Engber, David Hairston, Michael Hamel, Jonathan Handler, Johnny Lee, Tim Lennan, Rob Menke, and Andy Swanson, developed NetHack - 3.1 for the Macintosh, porting it for MPW. Building on their - development, Barton House added a Think C port. + 3.1 for the Macintosh, porting it for MPW. Building on their de- + velopment, Barton House added a Think C port. Timo Hakulinen ported NetHack 3.1 to OS/2. Eric Smith port- ed NetHack 3.1 to the Atari. Pat Rankin, with help from Joshua Delahunty, was responsible for the VMS version of NetHack 3.1. Michael Allison ported NetHack 3.1 to Windows NT. - Dean Luick, with help from David Cohrs, developed NetHack - 3.1 for X11. Warwick Allison wrote a tiled version of NetHack - for the Atari; he later contributed the tiles to the DevTeam and + Dean Luick, with help from David Cohrs, developed NetHack + 3.1 for X11. Warwick Allison wrote a tiled version of NetHack + for the Atari; he later contributed the tiles to the DevTeam and tile support was then added to other platforms. The 3.2 development team, comprised of Michael Allison, Ken @@ -2820,75 +3078,118 @@ Version 3.2 marked the tenth anniversary of the formation of the development team. In a testament to their dedication to the - game, all thirteen members of the original development team - remained on the team at the start of work on that release. Dur- - ing the interval between the release of 3.1.3 and 3.2, one of the + game, all thirteen members of the original development team re- + mained on the team at the start of work on that release. During + the interval between the release of 3.1.3 and 3.2, one of the founding members of the development team, Dr. Izchak Miller, was diagnosed with cancer and passed away. That release of the game was dedicated to him by the development and porting teams. - During the lifespan of NetHack 3.1 and 3.2, several - enthusiasts of the game added their own modifications to the game - and made these ``variants'' publicly available: + During the lifespan of NetHack 3.1 and 3.2, several enthusi- + asts of the game added their own modifications to the game and + made these ``variants'' publicly available: + Tom Proudfoot and Yuval Oren created NetHack++, which was + quickly renamed NetHack--. Working independently, Stephen White + wrote NetHack Plus. Tom Proudfoot later merged NetHack Plus and + his own NetHack-- to produce SLASH. Larry Stewart-Zerba and War- + wick Allison improved the spell casting system with the Wizard - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 - NetHack Guidebook 44 + NetHack Guidebook 48 - Tom Proudfoot and Yuval Oren created NetHack++, which was - quickly renamed NetHack--. Working independently, Stephen White - wrote NetHack Plus. Tom Proudfoot later merged NetHack Plus and - his own NetHack-- to produce SLASH. Larry Stewart-Zerba and - Warwick Allison improved the spell casting system with the Wizard - Patch. Warwick Allison also ported NetHack to use the Qt inter- + + Patch. Warwick Allison also ported NetHack to use the Qt inter- face. - Warren Cheung combined SLASH with the Wizard Patch to pro- - duce Slash'em, and with the help of Kevin Hugo, added more - features. Kevin later joined the DevTeam and incorporated the - best of these ideas in NetHack 3.3. + Warren Cheung combined SLASH with the Wizard Patch to pro- + duce Slash'em, and with the help of Kevin Hugo, added more fea- + tures. Kevin later joined the DevTeam and incorporated the best + of these ideas in NetHack 3.3. - The 3.3 development team consisted of Michael Allison, Ken - Arromdee, David Cohrs, Jessie Collet, Steve Creps, Kevin Darcy, - Timo Hakulinen, Kevin Hugo, Steve Linhart, Dean Luick, Pat Ran- - kin, Eric Smith, Mike Stephenson, Janet Walz, and Paul Winner. + The final update to 3.2 was the bug fix release 3.2.3, which + was released simultaneously with 3.3.0 in December 1999 just in + time for the Year 2000. - As with version 3.2, various people contributed to the game + The 3.3 development team, consisting of Michael Allison, Ken + Arromdee, David Cohrs, Jessie Collet, Steve Creps, Kevin Darcy, + Timo Hakulinen, Kevin Hugo, Steve Linhart, Ken Lorber, Dean + Luick, Pat Rankin, Eric Smith, Mike Stephenson, Janet Walz, and + Paul Winner, released 3.3.0 in December 1999 and 3.3.1 in August + of 2000. + + Version 3.3 offered many firsts. It was the first version to + separate race and profession. The Elf class was removed in pref- + erence to an elf race, and the races of dwarves, gnomes, and orcs + made their first appearance in the game alongside the familiar + human race. Monk and Ranger roles joined Archeologists, Barbar- + ians, Cavemen, Healers, Knights, Priests, Rogues, Samurai, + Tourists, Valkyries and of course, Wizards. It was also the + first version to allow you to ride a steed, and was the first + version to have a publicly available web-site listing all the + bugs that had been discovered. Despite that constantly growing + bug list, 3.3 proved stable enough to last for more than a year + and a half. + + The 3.4 development team initially consisted of Michael Al- + lison, Ken Arromdee, David Cohrs, Jessie Collet, Kevin Hugo, Ken + Lorber, Dean Luick, Pat Rankin, Mike Stephenson, Janet Walz, and + Paul Winner, with Warwick Allison joining just before the re- + lease of NetHack 3.4.0 in March 2002. + + As with version 3.3, various people contributed to the game as a whole as well as supporting ports on the different platforms that NetHack runs on: - Pat Rankin maintained 3.3 for VMS. + Pat Rankin maintained 3.4 for VMS. - Michael Allison maintained NetHack 3.3 for the MS-DOS plat- + Michael Allison maintained NetHack 3.4 for the MS-DOS plat- form. Paul Winner and Yitzhak Sapir provided encouragement. - Dean Luick, Mark Modrall, and Kevin Hugo maintained and - enhanced the Macintosh port of 3.3. + Dean Luick, Mark Modrall, and Kevin Hugo maintained and en- + hanced the Macintosh port of 3.4. - Michael Allison maintained and enhanced 3.3 for the Micro- - soft Windows NT platform. + Michael Allison, David Cohrs, Alex Kompel, Dion Nicolaas, + and Yitzhak Sapir maintained and enhanced 3.4 for the Microsoft + Windows platform. Alex Kompel contributed a new graphical inter- + face for the Windows port. - Ron Van Iwaarden took over responsibility for the OS/2 port. - The Amiga port of NetHack was resurrected for 3.3.1 by Janne - Salmijarvi. + NetHack 3.4 March 20, 2002 - The Atari port of NetHack was resurrected for 3.3.1 by - Christian ``Marvin'' Bressler. + + + + + NetHack Guidebook 49 + + + + Ron Van Iwaarden maintained 3.4 for OS/2. + + Janne Salmijarvi and Teemu Suikki maintained and enhanced + the Amiga port of 3.4 after Janne Salmijarvi resurrected it for + 3.3.1. + + Christian ``Marvin'' Bressler maintained 3.4 for the Atari + after he resurrected it for 3.3.1. + + There is a NetHack web site maintained by Ken Lorber at + http://www.nethack.org/. - - - - - - - - - - - From time to time, some depraved individual out there in - netland sends a particularly intriguing modification to help out - with the game. The Gods of the Dungeon sometimes make note of - the names of the worst of these miscreants in this, the list of + From time to time, some depraved individual out there in + netland sends a particularly intriguing modification to help out + with the game. The Gods of the Dungeon sometimes make note of + the names of the worst of these miscreants in this, the list of Dungeoneers: @@ -2898,41 +3199,73 @@ - NetHack 3.3 August 2, 2000 - NetHack Guidebook 45 - Adam Aronow Irina Rempt-Drijfhout Mike Gallop - Andy Church Izchak Miller Mike Passaretti - Andy Swanson Janet Walz Mike Stephenson - Ari Huttunen Janne Salmijarvi Norm Meluch - Barton House Jean-Christophe Collet Olaf Seibert - Benson I. Margulies Jochen Erwied Pat Rankin - Bill Dyer John Kallen Paul Winner - Boudewijn Waijers John Rupley Pierre Martineau - Bruce Cox John S. Bien Ralf Brown - Bruce Holloway Johnny Lee Richard Addison - Bruce Mewborne Jon W{tte Richard Beigel - Carl Schelin Jonathan Handler Richard P. Hughey - Chris Russo Joshua Delahunty Rob Menke - David Cohrs Keizo Yamamoto Robin Johnson - David Damerell Ken Arromdee Roland McGrath - David Gentzel Ken Lorber Ron Van Iwaarden - David Hairston Ken Washikita Ronnen Miller - Dean Luick Kevin Darcy Ross Brown - Del Lamb Kevin Hugo Sascha Wostmann - Deron Meranda Kevin Sitze Scott R. Turner - Dylan O'Donnell Kevin Smolkowski Stephen Spackman - Eric Backus Kevin Sweet Stephen White - Eric Hendrickson Lars Huttar Steve Creps - Eric R. Smith Mark Gooderum Steve Linhart - Eric S. Raymond Mark Modrall Steve VanDevender + + + + + + + + + + + + + + + + + + + + + + NetHack 3.4 March 20, 2002 + + + + + + NetHack Guidebook 50 + + + + Adam Aronow Helge Hafting Mike Engber + Alex Kompel Irina Rempt-Drijfhout Mike Gallop + Andreas Dorn Izchak Miller Mike Passaretti + Andy Church J. Ali Harlow Mike Stephenson + Andy Swanson Janet Walz Norm Meluch + Ari Huttunen Janne Salmijarvi Olaf Seibert + Barton House Jean-Christophe Collet Pat Rankin + Benson I. Margulies Jochen Erwied Paul Winner + Bill Dyer John Kallen Pierre Martineau + Boudewijn Waijers John Rupley Ralf Brown + Bruce Cox John S. Bien Richard Addison + Bruce Holloway Johnny Lee Richard Beigel + Bruce Mewborne Jon W{tte Richard P. Hughey + Carl Schelin Jonathan Handler Rob Menke + Chris Russo Joshua Delahunty Robin Johnson + David Cohrs Keizo Yamamoto Roland McGrath + David Damerell Ken Arnold Ron Van Iwaarden + David Gentzel Ken Arromdee Ronnen Miller + David Hairston Ken Lorber Ross Brown + Dean Luick Ken Washikita Sascha Wostmann + Del Lamb Kevin Darcy Scott Bigham + Deron Meranda Kevin Hugo Scott R. Turner + Dion Nicolaas Kevin Sitze Stephen Spackman + Dylan O'Donnell Kevin Smolkowski Stephen White + Eric Backus Kevin Sweet Steve Creps + Eric Hendrickson Lars Huttar Steve Linhart + Eric R. Smith Mark Gooderum Steve VanDevender + Eric S. Raymond Mark Modrall Teemu Suikki Erik Andersen Marvin Bressler Tim Lennan Frederick Roeber Matthew Day Timo Hakulinen Gil Neiger Merlyn LeRoy Tom Almy @@ -2940,9 +3273,8 @@ Greg Olson Michael Feir Warren Cheung Gregg Wonderly Michael Hamel Warwick Allison Hao-yang Wang Michael Sokolov Yitzhak Sapir - Helge Hafting Mike Engber - Brand and product names are trademarks or registered trademarks + Brand and product names are trademarks or registered trademarks of their respective holders. @@ -2962,9 +3294,7 @@ - - - NetHack 3.3 August 2, 2000 + NetHack 3.4 March 20, 2002 diff --git a/doc/fixes22.0 b/doc/fixes22.0 new file mode 100644 index 0000000..decc0b9 --- /dev/null +++ b/doc/fixes22.0 @@ -0,0 +1,353 @@ + NetHack Fixes List Revision 2.2 + +Fixes and Modified Features +--------------------------- +Guidebook.mn New file "Guide to the Mazes of Menace". By Eric Raymond. +Guidebook A file for preparation using the "mn" macros supplied with + the 2.11 news release, as well as an ascii version of the + same. + +NetHack.cnf Sample configuration file for the PC. (creps@silver) + +Makefiles Corrected problem in which the linking was done on build and +(unix/xenix) on install. (Contributed by Janet Walz - walz@mimsy) + +Makefile.att Added a makefile for the AT&T Unix PC using shared libraries. + (Contributed by ahby@umn-cs) + +Makefile.pc Streamlined compilation of main.o, tty.o, and unix.o +Makefile.tcc (Contributed by polder@cs.vu.nl). + +data.base deletion of duplicate lines and spelling fixes. (sweet@scubed) + +invent.c REDO problem with "What do you want to..." text fixed. + down stairway identification fixed. + Alloc "buf" to allow for variable length HI/HE. (tom@uw-warp) + +engrave.c Correction to "feel" code. (mike@genat) + Corrected switch for message determination. (patrickm@hpisof0) + BURN'ed engravings made un-erasable again. (kyrimis@princeton) + +pri.c Added colour highliting functions (sweet@scubed) + +prisym.c changed "symbol.room" to "ROOM_SYM" (one I missed) + (Ralf.Brown@b.gp.cs.cmu.edu) + Changed "dirlet()" to return an int. (maartenj@cs.vu.nl) + +msdos.c Changed "symbol" to "showsyms" (Ralf.Brown@b.gp.cs.cmu.edu) + Fixed up REDO & IBMBIOS stuff. (Kevin Sweet - sweet@scubed) + +do.c Dropping gold asked for only when gold posessed. (walz@mimsy) + Potential unsigned value problem fixed (u.ucreamed) + Added leash dropping code. (maartenj@cs.vu.nl) + Blind modifications for blindfolding. (eric@snark) + Value wrap fixed for u.ucreamed + +fight.c Dog's name now used in hitting avoidence message. (walz@mimsy) + Variable initialization fixed w.r.t. #ifdef / #else. + (Reported by Erwin Unruh - unruh@infbs) + Added giant rats and kobolds back into code. (sweet@scubed) + +spell.c Potential unsigned value problem fixed (u.ulevel). + Typos corrected. (Tom May - tom@uw-warp) + Blind modifications for blindfolding. (eric@snark) + +shk.c "inshop" crash bug corrected (many sources). + extern declaration of carrying() moved to avoid a Turbo-C + type mismatch msg. (Ralf.Brown@b.gp.cs.cmu.edu) + Added new "online()" which executes faster. (tom@uw-warp) + Blind modifications for blindfolding. (eric@snark) + Added item pricing shopkeeper talk. + (Idea from a hacked up 1.0.1 source sent in by michael@stb) + Cleaned up Kops code. (sweet@scubed) + +mhitu.c Argument mismatches fixed. (walz@mimsy) + Scorpion/spider mixup fix. (William LeFebvre - phil@rice.edu) + Blind modifications for blindfolding. (eric@snark) + +potion.c Argument mismatch fixed. (walz@mimsy) + Blind modifications for blindfolding. (eric@snark) + Poison handling made more dependant on poison resistance. + (From an idea by Steve Creps - creps@silver) + +mklev.c Fixed up installation of vamp traps. (sweet@scubed) + +makemon.c Monster creation location bug fixed. (walz@mimsy) + Monster creation crash fixed. (many sources) + Monster posessions bug fixed. (S. Wrammerfors stewr@obelix) + Added giant rats and kobolds back into code. (sweet@scubed) + +hack.c "Elbereth" effectiveness increased under "HARD" option to + be reasonable. (walz@mimsy) + Declaration of "register struct monst *m_at()" fixed. (many) + Typo fixed. (tom@uw-warp) + Fixed scroll of scare monster pickup problems (and giveaway) + (polder@cs.vu.nl) + Documentation modifications for blindfolding. (eric@snark) + +ioctl.c ioctl call for SET changed to function properly under + +unixtty.c Sys V R3 mods. (tom@uw-warp) + +decl.c in_doagain initialized. (many sources) + +wield.c Ability to remove cursed weapons w. w- removed. (many sources) + +options.c Major rewrite of options help. Now uses pager. (mike@genat) + Rewrote GRAPHICS setup. (maartenj@cs.vu.nl) + Allowed reassignment of inventory order #ifdef DGK + (polder@cs.vu.nl) + +pray.c Fixed mk_obj of spellbook under all conditions to make book + if "SPELLS" defined, and scroll otherwise. (unruh@infbs) + Fixed typo in "gods angry" text. (tom@uw-warp) + Fixed blessing code. (Simon Brown - simon@its63b) + Blind modifications for blindfolding. (eric@snark) + +zap.c Potion of invis. breakage message improved. (unruh@infbs) + Added WAN_PROBING to "zapyourself". + Changed "dirlet()" to return an int. (maartenj@cs.vu.nl) + Fixed cancellation code to work properly on wands (spe + set to -1 instead of 0) this means no infinite wands of + wishing. (Ron Wessels - ron@utcsri) + Fixed bug in "buzz()" causing crash when destroying a + trapper from inside with a wand/spell. (mike@genat) + Added fcn to destroy wands with zero charges. (sweet@scubed) + +pcmain.c Added a routine to zero out the fileinfo array in order to + prevent crashes on level change. (ralf@b.gp.cs.cmu.edu) + Added chdir to HACKDIR before looking for .CNF file. + Added call "uptodate(savefile)". (polder@cs.vu.nl) + +pager.c changed "cornline()" to use xputs for HI/HE. (tom@uw-warp) + added choice for dowhatis() to allow letter or cursor object + selection. (polder@cs.vu.nl) + +cmd.c Added ^W (wish) and ^I (ident-all) commands for WIZARD-mode. + (Paul Polderman - polder@cs.vu.nl) + Added "Z" as alternate to "# cast" (Eric Raymond - eric@snark) + +u_init.c Expanded a tab which didn't show in raw mode. + Changed trobj.trotyp to "unsigned short" to avoid >255 + problems. (Maarten Jan Huisjes - maartenj@cs.vu.nl) + Removed wand of wishing from WIZARD's inventory (due to + the above cmd additions). (polder@cs.vu.nl) + Fixed declaration of leash. (simon@its63b) + Beefed up Wizard class. + Added Wakizashi for Samurai. + Added holy water for Priest(ess)es. + Modifications to provide blindfolds. (eric@snark) + +end.c changed inventory identification on death to list form. + (polder@cs.vu.nl) + added hallucination effects to done_in_by() + added posession of amulet flag for scoreboard (sweet@scubed) + +wizard.c corrected "nasties" decl. (maartenj@cs.vu.nl) + Blind modifications for blindfolding. (eric@snark) + +do_wear.c Prot. from shape changers logic fixed. (maartenj@cs.vu.nl) + +lev.c Prot. from shape changers logic fixed. (maartenj@cs.vu.nl) + +mon.c Inserted cast to fix compiler warning. (maartenj@cs.vu.nl) + Nymphs now leave potions of object detection when killed. + Kops now don't leave treasure behind. (sweet@scubed) + +topl.c Changed size of "toplines" to avoid overflow in "parseoptions" + when help is asked for. (probably n/a) (maartenj@cs.vu.nl) + +topten.c Added longer death descriptions, including name of + shopkeeper who killed character. (many sources) + +termcap.c Changed allocation of HI/HO for copying SI/SO to allow room + for null. (maartenj@cs.vu.nl) + Added PCHack 3.61 termcap stuff. + Added colour highliting code. (sweet@scubed) + +version.c Expanded a tab for rawmode io. (maartenj@cs.vu.nl) + +objnam.c Allow the WIZARD to wish for really excessive objects. + (polder@cs.vu.nl) + +makedefs.c Added "freopen" which works (MSC 4.0 drops first couple + of lines). Solves missing #define AMULET... problem. + (Nathan Glasser - nathan@mit-eddie) + +rnd.c Changed around random number generation: + BSD uses "random()". (Paul Eggert - eggert@grand) + SYSV uses "lrand48()". (mike@genat from above) + +eat.c Changed "choke()" code to waste food rather than choke on + it #ifndef HARD. (Allan Pratt - apratt@atari) + Blind modifications for blindfolding. (eric@snark) + +objects.h added blindfold object (tool). (eric@snark) + +you.h changed Blind/BLIND to Blinded/Blinded + added Blindfolded/BLINDFOLDED + redefined Blind in terms of above parameters. (eric@snark) + +apply.c added blindfold code. (eric@snark) + +timeout.c Blind modifications for blindfolding. (eric@snark) + +sit.c Blind modifications for blindfolding. (eric@snark) + +trap.c Blind modifications for blindfolding. (eric@snark) + Level teleportation to hell fixed so that it will not + do so unless character has Fire_resistance. (many sources) + Added polymorph trap. (many sources) + +monmove.c added check on presence of "fobj" before atl() call + to avoid potential segmentation problem with ROCKMOLE. + (Reported by Doug Rudoff - doug@wiley) + +various files Fixed typos. Also converted British English words to + American English for uniformity. (Original list of typos + submitted by Steve Creps - creps@silver) + + +New Features +------------ + 1) New flags in "config.h" (some of these were included in 1.4f): + + COM_COMPL Command line completion by John S. Bien + GRAPHICS Funky screen character support (Eric S. Raymond) + HACKOPTIONS Support DGK-style HACKOPTIONS processing (ESR) + RPH Various hacks by Richard P. Hughey + KJSMODS Various changes made by Kevin Sweet + BVH Additions by Bruce Holloway + + In addition, in an MSDOS enviornment, when GRAPHICS is defined: + + MSDOSCOLOR Colour highlighting of monsters, etc. + + Of the above, I haven't tested HACKOPTIONS and MSDOSCOLOR. If you + find bugs in these, send me the reports. + + 2) New objects: + + blindfold - allows you to avoid the gaze of a Floating Eye and to + use your telepathy on command if you have it. + + mirror - scares monsters if you use it on them (and other uses). + + ring of polymorph - (usually cursed) forces random polymorphs. + + ring of polymorph control - prevents system shock and allows choice of + creature to polymorph into. + + 3) New Files: + + - A new set of documentation, the "Guidebook to the Mazes of Menace" + has been supplied by Eric S. Raymond. The guidebook is written for + nroff using the "mn" macro set supplied with Bnews 2.11 or greater. + Since not everyone has these macros, I have run the guidebook through + nroff, and supplied it in flat ascii format as well. [Moderator's + note: because of past problems, I ran the formatted version + through "col -b" before passing it on to remove ^H's, etc. -br] + + - A copy of "HACK.CNF" which has been renamed "NetHack.cnf" was + supplied by Steve Creps. The file decl.c has been updated to reflect + this change. + + - A new "Makefile" for the AT&T Unix machines has been added. + + - I was hoping to get documentation on "NANSI.SYS" as well, but got + no responses to the mail I sent the author, direct and via Bill + Randle at tekred. As per usual, I will gladly publish any relevant + documentation I get. + + 4) Major game changes: + + - Shop generation has been significantly changed. A new structure + has been introduced which allows shops (except the "general" type) + to have up to three different types of object inside. There is also + a new "distribution pattern" parameter which tells the generation + code how to lay out the shop (this is preliminary to the addition of + two new types of shop, the temple and barracks - more on this later). + + - Shopkeepers will now tell you how much they expect for each object + you pick up. This gives you the ability to haggle with the merchant + in question by dropping and picking up objects until you are more or + less satisfied with the price. I have re-written "getprice()" in + shk.c in an attempt to make sure that you cannot actually sell any + particular object for more than the shopkeeper will charge for it. + + - Another change to shopkeepers has them potentially getting angry if + you stay beside them after not paying your bill. Each they time they + ask you to pay up, there is a chance they will decide they don't like + people who don't pay... + + - A new monster, the hydra, has been added (as you have probably seen + on the net). I haven't had much chance to test out this feature of + the game. Mirrors have also been added, and seem to work quite well. + + - Changes have been made to the object ocurrence chances in objects.h, + so that the relatively rare tools, etc. have at least a 1% chance of + showing up. + + - Throwing and zapping code has been modified so that there is a + chance that said can be done through a doorway. Bolts can still + bounce however... + + - The infamous and dreaded makemon() bug has been eliminated. In + addition to this, "r"ats and "K"obolds have been added back into the + game. "K"ops no longer leave treasure (just what they were carrying, + plus maybe a club or whistle). + + - Two new "super"swords have been added. They are the katana named + "Snickersnee" which is +5 on damage (due to sharpness), and the long + sword "Excalibur" which is +rnd(10) to hit, +5 on damage, and has a + couple of other features I won't go into right now. The only way + for a character to get "Excalibur" is as a gift from someone. You + cannot write the word "Excalibur" on things for some reason... + + - There have been two additions to disallow infinite wand charges. + First of all, wands with less than zero charges will automatically + turn to dust (thanks to Kevin Sweet). Next, a wand of cancellation + will set the number of charges in the wand to -1, which will make it + forever useless, (thanks to Ron Wessels). + + 5) Minor game changes: + + - The fountain code has been tightened slightly so you can no longer + dip objects into a fountain or drink from one while you are floating + in mid-air due to levitation. + + - Teleporting to hell via a teleportation trap will no longer occur + if the character does not have fire resistance. I found this just + too arbitrary a way to die (and so did several other people who com- + plained about it). + + - A new trap, the "polymorph" trap has been added by Richard Hughey. + It's inclusion is dependant on having "KAA" defined. + + - In wizard mode, the wizard player has infinite wishes, and the + ability to instantly identify everything (s)he is carrying. The wizard + player is also no longer limited by the standard multiple / bonus res- + trictions on objects wished for. + + - Random number generation has been changed around to make it (I hope) + more unpredictable. + + - A large number of typos have been fixed, and all of the British + spellings converted to American. I would like to see a shell script + to allow conversion back (or something like that) in the future. + + - I have done a "make depend" for the makefiles to reflect a slight + restructuring in the order of inclusion of header files. + + 6) Future additions: + + - Steve Creps is working on "barracks" and "soldier" code which is + now ready for addition. I have added the "soldier" side into the + game, but haven't really tested it. Steve will be adding the + "barracks" section in and sending me the resulting patches. There + will be a minor (read patch) release as soon as he can get the code + integrated into this release and sent up here to me. + + - There are also several other new room projects in the works which + should be able to be included in that minor release, along with any + bug reports that are made in the interim. diff --git a/doc/fixes31.1 b/doc/fixes31.1 new file mode 100644 index 0000000..402166f --- /dev/null +++ b/doc/fixes31.1 @@ -0,0 +1,110 @@ +Makefile.utl vs. GNU make (*_lex.o needs explicit *_lex.c dependency) +defining MAKE in more makefiles (symptom is "sh: makedefs: not found") +finding test in makefiles (needs shell meta-char, >/dev/null or || exit 1) +splitter hunk sizes with SAS 6.x (wouldn't fit on floppy) + +OpenWindows 2.x documentation (?) +',' and ';' in help files, including Guidebook +Guidebook date (nroff and pre-processed versions) +VMS options syntax (config file description omitted "OPTIONS=" requirement) + +phase of moon for Mac and MSDOS ports -- revert to old, portable phase of + moon code +polymorphing into bees (divide by zero core dump, reported as + floating point error on Sparcs) +monster throwing boulder into pool could free object twice +candle burn-out accessing free'd object while traversing list (Mac core dump) +inappropriate candle merging (lit with unlit) +several levelflags (fountains, etc.) not being handled on special levels +subrooms[] not initialized +coredump on messed DEFAULT_WIN_SYS +deleting lock.0 files on early quit +number_pad/mouse coexistence +jumping onto doors or boulders +tombstone gold neglected gold in containers, although score was correct +initial gold record neglected gold in containers +reeling monsters leaving ghosts (missing newsym) +display getobj prompt for non-REDO +packorder option parsing +inconsisent option parsing with IBM vs. IBMg, etc. +throwing Mjollnir at adjacent hard things causes panic/core dump +throwing at ghosts in walls left objects stuck in walls +throwing unpaid objects in shops (donated to player by shk) +Shopkeeper administration out of order (buying group of used up items) +pricing chains, uball, or other nocharge objects, when they couldn't be sold +knocking uball down a hole by dropping another object caused crash +kicking monsters while levitating (core dump if monster "reels" or killed) +kicking empty space while levitating could give free move (recoil) +panic when nurse is fixing your damage and disappears +core dump 'D'ropping everything with gold but no inventory (null pointer access) +core dump using getpos() "move to feature" response when map shows something + covering furniture (displayed glyph leads to invalid subscript use) +deity gender reference in opening legacy message +makeplural() said "poisoned yas" instead of "poisoned ya" +zapping on entry to water left trails +allow level teleports to be cancelled +excess choking when eating corpses +funny death message (or coredump) when you choke on a tin of spinach + after partially eating something else +Magicbane expulsion confused cutworm() +charging for several overlooked items (mainly magical instruments) +taming a sticking monster (e.g mimic) wouldn't set you free +panic when tinning while standing on stairs with a full pack and object drops +zapping down into ice with wand of digging (core dump) +rust monsters wouldn't ever hurt armor, even non-rustproof armor. conversely, + unrustable things rusted. +mysterious rust damage on damp levels (improper object chain traversal + when any item landed in pool after being thrown or dropped) +very eroded nonrustable/corrodable/flammable objects displayed as "very +0..." +map window wasn't being initialized correctly, causing some 'a'filled screens +using magic marker with full pack leaves you with an item in the '#' slot +spellbook merging caused multiple books to fade away when you re-read + them enough times +Master of Thieves in Tourist quest not created with Bell of Opening, making + game virtually un-winnable +could wish for quest items +If an eel managed to drown you, it would say "Drowned by a drowning" +stop making bones from non-branch portal levels +reading blank scrolls exercised wisdom +inverted use of crystal ball "vision in unclear" feedback message +special room entry messages (shop welcome) given before level change map update +limbless blobs like gelatinous cubes could not pick up +The level compiler missed first level flag if more than one was specified. +The level compiler accumulated level flags when compiling multiple files. +make the 32-bit monster flags fields unsigned long rather than just long +mksobj() created gold a factor of 10 too light +indefinite articles in quest text +Alt-n didn't execute #name on some ports, made Alt-? do #? +correct tense and grammar of various messages +obsolete oracle about using mirror to locate Wizard & Medusa removed +Nurses would zap you with wands, et al, instead of healing you +Shopkeepers residence was sometimes wrong on bones level, esp. in the minetown +Some zaps, esp. by monsters, at the map edge could cause core dumps +panic relmon bug possible when #turn'ing multiple monsters at once +it wasn't possible to get underwater when polymorphed to a swimmer +total digestion wasn't working +lycanthropy could change sex +interrupting dosinkring() allowed free ring identification +killing some hostile humans (like Croesus and priests) lost telepathy, etc. + +tty specific: long input lines and improved interrupt handling +X11: NetHack.ad: "*map*grey" should be "*map*gray" +X11: NetHack.ad: remove excess quotes +HPs and X (SYSV conflict caused by X11 headers) +Handle WM_DELETE_WINDOW protocol in X11 window-port. +X11 popups are now positioned so that the cursor is bottom center. +Both X11 fonts now have a pool symbol that coveres the whole rectangle. +X11_getlin will now allow empty strings to be returned. +X11: implement score in the status window. +X11: make displaying experience optional. +X11: position getline and yn popups center,bottom instead of center,center. +X11: autofocus mode made more reliable at program startup +X11: number of objects removed from containers could wrap negative +X11: allow translation tables +X11: initial window would "sweep" shut and reopen +micros: save and restore progress reports weren't appearing during save + and restore (they would appear immediately afterwards) + also error messages from dots aimed off right edge of screen +Atari: colors were not properly set in medium resolution +Atari: terminal size was set incorrectly after a ^Z +OS/2: HPFS support was incomplete diff --git a/doc/fixes31.2 b/doc/fixes31.2 new file mode 100644 index 0000000..8a790f4 --- /dev/null +++ b/doc/fixes31.2 @@ -0,0 +1,92 @@ +revived barbarians didn't gain levels from potions +pets wouldn't keep their armor or weapons (blessed figurine of Archon) +avoid "rot" v. "burn" damage for organics +identify +/- known rings/armor as "uncursed" +loop through identification as long as additional "charges" are available +successive disease attacks made you less sick, also make nurses cure sickness +NO_MAILREADER non-mail daemon message fix +make fortune cookies, pancakes yellow and lightning white +cavemen were red while cavewomen and all other characters were "domestic" +monsters might not change color when growing up +redisplay cancelled objects in case their color changed (potions, spellbooks) +ask if you want to play heard passtune +add: make ^T intrinsic teleports use magical energy +don't encase the Amulet (or invocation tools) inside cockatrice induced statues +fix eating taking 1 turn less than number necessary, cheating you of nutrition +fix inventory to avoid % in user-supplied names [pline(xprname())] +fix crash when #force destroys unpaid chest in shop +fix crash when movement reaches edge of screen on rogue level +fix crash when two items in a row vanish from magic bag +set bknown when Priests see item, fixing missing checks elsewhere +set alignment of priest's quest artifact to match priest's starting alignment +if the Mitre of Holiness gets stolen by the Wizard, reset int & wis stats +always unlock quest stairs whenever leader acknowledges quest completion +make mysterious force which locks quest stairs block objects as well as player +duplicate shopkeeper names were possible on town level +trying to rename shopkeepers left dangling pointers +credit balance can prevent Kop summoning when player leaves shop suddenly +suppress several shopkeeper messages (and buy|sell) is shk is asleep|paralyzed +using charged objects ((engrave) wands, horns of plenty, etc.) in shops was free +don't double bill for food eaten off shop floor (multi-turn to eat only) +fix to prevent unpaid objects differing only in price from merging (only in + inventory; they're not "unpaid" any more when dropped, so might merge) +missing #ifdef SOUNDS in vault.c +inconsistent MFLOPPY/MICRO use of dotcnt for saving +add: wands of striking break potions +add: directional healing spells +add: pickup_types option, pickup -> autopickup +disclosure option takes optional string value; killed counts and genocide list +give better message when trying to set options which are compiled out +add: hungry pets make begging noises +centaurs and mariliths could wear inappropriate armor +remove Medusa's tail and give her wings +separate creatures that don't breathe from creatures that can breathe water +you can't choke if you don't breathe +Fort Knox eels were placed outside moat +jellies for Juiblex, not Jabberwocks +don't heal while praying, so that gods are more likely to heal you +fix fireballs burning fire resistant players +floating eyes could paralyze monsters indefinitely +fix monster sleep/wakeup induced my musical instruments +players hit by wands of sleep get chance to wake up when attacked by monster +iron balls keep their "very heavy" weight +fix vorpal blade/long worm misses +allow monsters to kill players with vorpal blade and tsurugi +fix objects falling through trapdoors; "shipping destination"'s overloaded use + of obj coordinates could cause bogus screen update attempt (y >= ROWNO) +prevent bad argument to rnl() from prayer_done() when praying in gehennom +display message when boulder is pushed into pit +avoid monsters deciding displaced or invisible characters were off the screen +kicking embedded objects loose would break fobj chain (-> freeobj() panic) +when using the cursor to look at remote objects, if the target object is + embedded in something, mention that fact +dropping gold inside a monster -> freeobj() panic +gold picked up by pets wasn't in mgold and thus didn't show up on probing +fix "stop *opening* the lock" even when you were locking it +succubus stealing ring of adornment caused crash if she already had one +monsters created by monster reading create monster didn't appear for scroll ID +monsters explicitly casting spells of sleep or cold had messages reversed +elf character could get impossible("snow boots not found?") stepping onto ice +accept gray/grey except for spellbooks +keep monsters from teleporting on no-teleport levels +don't allow digging of trapdoors on the three wizard levels +don't allow digging down (including drum of earthquake) to destroy portals +fix digging down from within walls and solid rock; monsters could enter + the resulting trapdoor/pit, but players couldn't +fix digging down while flying; don't fall through +destroy any engraving if a hole is dug down thru it, or ice it's in gets melted +change many hardcoded "floor"s and a few "ground"s to use actual surface type +fix blessed unicorn horn's restore ability feature (strength gain when weak) +underwater: prevent turbulence from placing character inside solid wall +underwater: suppress "you inhale water" message when removing amulet of + magical breathing if you're polymorphed into a swimmer or nonbreather +when using the 'A' command to take off armor from underneath other armor, + account for time needed to take off and put back on outer garment(s) +don't create doors over pits and trap doors when using a wand of locking +fix mapping when you drop objects while following the guard out of a vault + +X11: some status didn't show up after restore +UNIX: fix potential security hole accessing file through NETHACKOPTIONS setuid +VMS: disable installed privileges when assigning i/o channel to terminal, + opening termcap, or accessing user-specified config file +Amiga: invalid showscore and numberpad options inserted by frontend diff --git a/doc/fixes31.3 b/doc/fixes31.3 new file mode 100644 index 0000000..c700d51 --- /dev/null +++ b/doc/fixes31.3 @@ -0,0 +1,22 @@ +avoid divide by zero crash for eggs produced from horn of plenty +prevent monsters from eating the invocation tools or Rider corpses +make artifacts much less likely to be destroyed +fix freezing lava in front a raised drawbridge +fix digging pits in front of raised drawbridge; improve digging next to pools +since random teleports have no --More-- prompt, have them purge REDO data + to avoid repeating previous command before noticing changed context +make magic portals function for monsters +make numerous priest blessings increasingly rare, with an upper limit +fix missing quotation marks in quest speech +prevent monsters like killer bees from opening tins +add: keep track of # player deaths, save game start time in struct u +don't used "uncursed" with gold in containers in ending inventory display + +PC: Fix black/gray/white display problem + +X11: set input text portion of the dialog box so it is the width of the box +X11: fix message window seperator redraw problem (thanks to + Ivan D. Brawley ) +VMS: avoid false "trickery" detection for bonesX#.##;1 levels +VMS: prevent display of really long broadcast messages from clobbering stack +VMS: prevent endless input loop upon remote terminal disconnect diff --git a/doc/fixes32.0 b/doc/fixes32.0 new file mode 100644 index 0000000..d811b7b --- /dev/null +++ b/doc/fixes32.0 @@ -0,0 +1,344 @@ +protect the Amulet and invocation tools from being destroyed when a + disintegrated monster's inventory gets deleted +prevent the Amulet and invocation tools from being buried, similar to box + behavior (Book of the Dead would rot away as paper when buried) +don't let polymorphed players eat any of the invocation tools +pets are no longer highlighted when hallucinating +keep glass gems from shattering in chests +return errors from dgn_comp and lev_comp when called for +fix hallucinated fruit juice message +fix several monsters conveying inappropriate resistances +fix misspellings of "Assassins' Guild" and "Minion of Huhetotl" +set personal name flag for Pelias and Thoth Amon; clear it for Chromatic Dragon +don't say "Picking the lock..." when using a skeleton key +give feedback when applying key to current location but no boxes are present +can't manipulate floor locks (chests) while levitating +don't crash onto sink if permanently levitating due to eating a ring +avoid resuming interrupted lock operation on chest that's been polymorphed +wide-angle disintegration Beams O' Wrath disintegrate non-resistant + shields and armor +don't access zapped wand after it's been destroyed by divine lightning bolt +separate graphics symbols for each trap, differently-colored traps +allow wishes for greased objects, correct wishes for "poisoned + rustproof" objects +damage was calculated incorrectly when hitting with statues and boulders +allow digging to finish when digging statues embedded in undiggable walls +list identified invocation tools as "the item" instead of "a item" +ignore rknown for unerodable objects when determining if it's fully identified +flush output after eating mimic so '$' appears right away +update botl for spell power after ^T or #invoke of "energy boost" artifact +correct hunger check when casting spells +correct various messages +fix deliberately jumping into Stronghold trap doors +make random level changes while escaping with Amulet more equitable +when mysterious force randomly picks a location on the current level, send + player into Wizard's tower if and only if already inside that tower +any level change from one tower level to another preserves occupancy state +mysterious force won't kick in when using portal to go up into Wizard's tower +avoid "bad cursor position" situation when mystery force or cursed gain + level potion causes level change within the Wizard's tower +don't allow the Wizard to be resurrected on the Astral level +only list "likely" objects when prompting for what to #invoke +reset encumbrance and movement rate during successful prayer, in case it + cures lycanthropy +prevent cursed weapon that slips when thrown by monster from embedding in stone +ki-rin is not humanoid +all elves can see invisible +gain intrinisics from eating amulets +lose divine protection by killing co-aligned priests or converting alignment +have quest leader check for absolute alignment as well as for piousness +fix tombstone message when dying from kicking door while levitating +bite, &c. attacks on displaced images said "swings wildly and misses" +calculate score before creating bones, otherwise gold in bags gets overlooked +Unique monsters no longer placed in bones files +for blessed genocide, don't report failure for other classes' quest monsters +could get both compressed and uncompressed explore mode save files +ZEROCOMP's bwrite ignored possibility of write failure +mimics imitating fruit caused "Bad fruit #0" on help commands +fix off by one bug in level teleport trap destination for monsters +if g.cube eats a non-empty container, engulf contents rather than devour them +allow wizard to use blessed genocide of '*' to wipe out all monsters on level +when digging a hole in ice, don't describe it as digging in the "floor" + and unearth any objects buried there even when it refills with water +when digging in a pit trap which ends up filling with water instead of + becoming trap door, remove the trap; likewise for overflowing fountains +can't dig pits under drawbridge portcullis; break bridge if hole would be made +can't dig while caught in a web +don't "swing your pick-axe through thin air" if target location is a web +mark webs as seen when "monster is caught in a web" message is given +whirly monsters pass through webs; some huge monsters tear them +Sting cuts through webs +have shk use plural if called for when referring to player's pick-axe(s) +fix price stated by shk when picking up container holding merged items +fix price stated by shk for #chat when standing on a container +don't adjust food price due to hunger when player is selling, only when buying +don't double bill shop corpses turned into tins +don't make mundane objects known when they're outside the shk's expertise +change to have shks possibly identify items sold for credit just like for cash +when player sells something to broke shk for credit, don't offer more for it + in credit than will be charged for it if player buys the item back +when selling items in shop, don't try to adjust message/prompt based on COLNO +when dying in shop entrance, make sure inventory in bones data is placed all + the way inside the shop, hence owned by the shk +make shk notice when shop door destroyed by wand or spell or digging downward +reset unpaid objects if shk poly'd into jumpy monster teleports out of shop +fix handling for shop objects kicked or thrown from one shop into another + and for shop objects hit by cancellation beam +add potions of oil; lamps can be refilled with them +dipping rusty weapons in potions of oil removes rust +allowing drinking from surrounding water if you are underwater +fix non-merging potions of water due to water damage's incompatible dilution +fix mon-merging scrolls of blank paper due to SCR_SCARE_MONSTER's spe usage +fix D(ropping) subset of wielded darts,&c (worn mask got out of synch) +fix #adjust merging wielded darts,&c into non-wielded ones +allow #adjust when fixinv option disabled +fix getobj's '?' help displaying one item when fixinv option disabled +don't give characters with maxed out luck complete immunity to water damage +don't allow AC -17 or better to provide invulnerability to zap attacks +kicking cockatrices while barefooted will stone you +change to inhibit displacement from operating through solid walls +fix mblinded assignment for monsters hit by potion fumes +give runesword same damage adjustments as broadsword +extra verbosity for attacks caused by Stormbringer +allow ghosts to step on garlic +don't let vampires step on altars +don't let monsters jump into polymorph traps covered by boulders, unless + they can carry such, pass through, or squeeze under +giants polymorphed into something else must drop any boulders being carried +giants in pits become untrapped if a boulder is pushed in +prevent traps from being generated on ladders +don't "detect trigger hidden in soil" for previously detected land mine +exploding and crashing doors wake up nearby monsters +factor rings of increase damage into kicking damage +handle omitted case for ball movement that would leave chain in odd position +returning to stairs on top row of map is valid (fixes rogue quest bug) +avoid giving "sad feeling" message for pet if lifesaving prevents its death +don't rot away Rider's corpse if something is standing on it at revival time +kill any engulfer (including poly'd player) trying to digest a Rider +give Riders non-zero nutritional value so tinning kit doesn't ignore them +save & restore u.usick_cause properly +an eating pet can continue & finish eating while you're off its level +fix object names: "a Dark One corpse", "statue of a Wizard of Yendor" +killer_format: poisoned "by Pestilence", not "by a Pestilence"; ditto Juiblex +killer prefix might be wrong after having been life-saved +fix to avoid "invisible invisible {Priest|Minion of Whoever}" on tombstone +fix bug with cold-resistant monsters attacking jellies (etc.) +fix possible panics when restoring while swallowed or held +when taming, make holder/swallower let go even if it just becomes peaceful +reset area of visibility when hurtling backwards from recoil while levitating +don't let hostile monsters who follow up/down stairs share final ascension +add bodypart(HAIR) to correct some inappropriate messages +display monsters inventory (if any) when mon zapped with wand of probing +display inventory of encased items in statues zapped with wand of probing +display inventory of buried items below, by zapping wand of probing downwards +set dknown bit for all objects hit by probing beam +add ceiling function to alter the ceiling messages appropriately +fix 3.1.2's fix for reseting certain class-specific artifact properties +add selection menus to pickup and some apply functions +pre-menu container interface: don't let "%a" select all objects if no food + is present; make user's " a" become "A" instead +wake up monsters hit by potions thrown by other monsters +suppress vault hint messages if player is in the vault +make lev_comp check full object and monster names ([ring of] "protection" in + objects[] was matching "protection from shape changers" in .des file) +guarantee that stairs down from Juiblex swamp level always get created + [sometimes got impossible("couldn't place lregion type 0")] +prevent a three room level which has the stairs to the mines from also having + a special room [so that those stairs can't end up placed in a shop] +allow quest nemeses and other invocation tool guardians to wield artifacts +Mitre of Holiness is not a weapon +don't give "heat and smoke are gone" message when entering Vlad's tower if + arriving from somewhere other than Gehennom (portal via W's quest arti) +when a wielded cockatrice corpse rots away, set `unweapon' so that + further combat will elicit "bashing with gloved hands" message +fix behaviour of wielded eggs (breaking, stoning, etc) +tiny chance for "queen bee" eggs, rather than always killer bee eggs +change Tourist quest home base to Ankh-Morpork +prevent activated statue traps from creating hidden monsters +handle activated statue being the only object poly'd player is hiding under +prevent reference to unseen underwater object when hiding monster attacks +don't pluralize name when smelling opened tin of unique monster's meat +make tins of unique monster's meat be empty in bones file +don't leave a corpse in bones file if killed by disintegration breath +don't leave a corpse when monsters disintegrate other monsters +any food could be tinned (yielding giant ant meat) when corpse in inventory +destroy all boulders in invocation area when creating stairs down to sanctum +boulders landing on previously seen trapdoors will plug them instead of + falling through or settling on top +boulders on ice which gets melted will fill pool as if dropped +don't let dead or sleeping priests give temple greetings +chatting wakes up sleeping priests +don't exercise wisdom when making prediscovered objects known during init +don't generate any generic giants (mummy/zombie placeholder) on castle level +pets and g.cubes will polymorph if they eat chameleon corpses +slippery ice (temporary fumbling) only lasts until the next move +avoid leash limbo if quest leader ejects you while leashed pet's not adjacent + (ditto other unconventional level changes, like W's quest artifact) +release attached leash if poly'd player eats it +crash fix: handle other forms of monster-induced level change besides quest + ejection (swallower expels onto portal, level teleporter, trap door) +fix magic mapping of previously mapped maze walls dug away out of view +assorted drawbridge fixes (kill credit, auto-pickup, drown survival handling) +passtune becomes fully known once successfully played +wiping out engravings leaves partial letters +wipe random letters of trap engravings ("ad aerarium", "Vlad was here") +eating wolfsbane while in werecritter form rehumanizes in addition to purifying +don't penalize player (shop charges in general; bad luck for mirror) when + a monster breaks something with a wand of striking +when loading bones, keep track of unique monsters to avoid their duplication +don't allow a demon prince to summon two copies of a unique demon lord +enlightenment luck display ("extra", "reduced") did not agree with actual luck +avoid duplicate spellbooks in character's initial inventory (affects priest) +fix pets moving reluctantly onto cursed objects +can't #loot while overtaxed +time passes when items disappear on use of a cursed bag of holding +#offer cannot convert or destroy an unaligned altar +MUSEr's reflecting shield or amulet shouldn't become known when not seen +fix check for wearing shield when monsters wield two-handed weapons +don't restrict MUSE scimitar usage to strong monsters +make dwarves less eager to switch back and forth between weapon and pick-axe +clip swallow display at left & right map borders +prevent recoil [hurtle() while levitating] when caught in a trap +downward zap which freezes water or lava shouldn't bounce back up +Vorpal Blade: don't let damage penalty (very low strength, negatively charged + ring of increase damage) prevent beheaded monster from dying +make sure player polymorphed into jabberwock is vulnerable to beheading +make sure that when "The fiery blade burns the shade!" that it actually does + damage (double-damage for non-silver must do at least 1hp damage) +prevent divide by zero crash when hitting tame shade with non-silver weapon +don't lose alignment when throwing gems to/at peaceful unicorns +don't apply grease to worn armor if it's covered by other armor +fix unnaming monsters via `C ' +fix calling object types via `#name n ' +fix off by one problem when shuffling some descriptions (scroll label "KIRJE" + and "thick" spellbook never used; breathing amulet always "octagonal") +exploding land mines can scatter or destroy objects at the trap location +add rolling boulder traps +try harder to make monster hit point and level gain avoid anomalous losses +reduce odds of undead corpses on castle level and priest quest home level, + to make it harder to lure wraiths to more favorable spot +can't polymorph large piles of rocks into gems +hit point gain from nurse healing throttled substantially +make cursed bells be much less effective as instruments of abuse +fully implement object charges for Bell of Opening +allow '%' as destination on rogue level when specifying position by map feature +fire traps can burn up scrolls and spellbooks on the floor +fix inverted cancellation check for AD_SLOW and AD_DREN damage +bullwhips can be applied to disarm monsters and hero +bullwhips can be applied by hero to haul themself out of a pit +ensure that thrown potions hit their mark if you are swallowed +attempting to engrave on an altar causes altar_wrath +differentiate between a hole and a trapdoor, digging always makes a hole +check the right hit point values when polymorphed and encumbered +improve guard behaviour in vaults when player is blind +prevent dwarves from digging while wielding cursed weapons +displacing a pet mimic unhides it +'(' shows the proper tools as in use +improve shk's handling of pick-axe damage and taming +aging of items in ice boxes left in bones files +fix genocide of '@' while polymorphed +add gender to some unique monsters +disallow digging down while phasing through non-diggable walls +general fixes to various message sequencing problems +prevent shopkeeper names from showing up while you are hallucinating +prevent paralyzed pets from picking up items +jellies for Juiblex, not Jabberwocks (done properly this time) +rust monsters can't eat rustproofed objects +general fixes to inventory merging of items +monster inventory undergoes merging too; potentially affects probing and theft +monsters ignore items they want to pick up that are on 'Elbereth' +bows wielded by monsters now do proper (low) damage +even nymphs may not pick up rider corpses +treat cockatrice corpses in multiple item piles the same as one item piles +"PACKORDER" feedback incorrect on parsing failure +you can no longer choke on liquid +stethoscope on secret doors displays properly when blind +monster-hurled potions no longer produce quaff messages (or djinn) +giant eels now hide with mundetected, not invisibility +eels on the plane of water don't hide and aren't negatively impacted by being + out of water +don't give the big point bonus for eels if player is wearing breathing amulet +fix display bug (newsym after Wait! message) +temple priests now wear their cloaks +Orcus is no longer peaceful (had been made so by bad bribery check) +'uskin' save and restore done properly +don't improperly adjust int & wis for stolen non-worn P quest artifact +don't allow Vorpal Blade to behead a monster when it swallowed you +golems are not living and don't "die" in messages +fix "Rocky solidifies. Now it's Rocky!" +polymorphing into a flesh golem, which gets petrified by turning into a stone + golem, now works when stoned +correct "killed by a died" +allow the Wizard to come back and harass at his next reincarnation time even + if he's been left alive on some other level (fixes "paralysis" cheat) +make monsters subject to "mysterious force" in Gehnnom while climbing stairs + with the Amulet, so that once the Wizard has stolen it, his retreat + when wounded doesn't become an easy way to carry it up +changing attributes immediately checks encumber messages +confused monsters get confused SCR_TELEPORTATION effects +fixed "choked on eating too rich a meal" +kicked objects won't stop at stairs if they don't fall +general fixes to stealing from monster carrying cockatrice corpse +a nymph who polymorphs herself while you're frozen during a multi-turn armor + theft can't complete the theft if transformed into non-stealer monster +consistent corpse probability no matter what killed monster (also removes a + loophole allowing permanent rider death) +MUSE monsters no longer wield weapon same as (not better than) current one +incubi/succubi have hands, not claws +make #jump be ineffective on air and water levels +allow multiple sickness causes; vomiting only cures those involving food +#prayer reward: give books for not-yet-known spells preference to known ones +marker use no longer uses wishing interface, fixing several obscure bugs +archeologists' and rogues' initial sack starts out empty +candelabra "has now" 7 candles fixed. +kicked objects would set dknown when the kick caused an injury, even though + safely kicked objects wouldn't +make cloaks subject to burning +make exposed shirts subject to burning and rotting; greased ones defend + against wrap attacks +all types of fire damage affect worn armor [adds explosions, fire traps, and + zapping yourself to previously handled zap/breath attacks by monsters] +for explosions, destroy carried objects before killing player [affects bones] +replace triggered land mine with pit before doing damage [bones] +black dragon breath no longer referred to as "death" instead of disintegration +don't make ring of gain strength known when gauntlets of power mask its effect +can't have "slippery minor currents" or similar silly nohands body parts +proper support for polymorphed players using wrap attacks +cannibalism reduces luck as well as causing aggravation +picking up an item which will merge works even when all 52 slots in use +moving through diagonal openings checks how much you're carrying, not how much + free space you have left +monsters have same restrictions as players moving through diagonal openings +picking up subset of heavy group works for picking one and gets feedback right +taking subset of heavy merged group out of containers works the same as + picking up subset of heavy merged group from floor +when putting gold into containers, don't count its weight twice, thereby + messing up the status line's encumbrance feedback +fix the option parser's handling of attempting to negate string values +teleporting a monster on a trap with a magic whistle sets the trap off +iron ball dragging no longer confuses autopickup +cumulative temporary intrinsic increments can't spill over into permanent bits +eating food shouldn't give messages for intermediate states +don't make wand of death become known after casting finger of death at yourself +ignore case when checking artifacts against wish- or #name-specified name +ignore confusion when reading scrolls of mail +exploding runes for spellbook read failure doesn't imply that book explodes +divine rescue from strangling destroys worn amulet of strangulation +boulders pushed on level teleporters will level teleport; also, make one random + level teleport function to keep all level teleports consistent + +MSDOS: add fake mail daemon +MSDOS: add VGA tiles to tty port +VMS: switch to lint-free, non-GPL'd termcap support code +X11: map behind popup edges was occasionally not refreshed +X11: allow permanent inventory window +X11: when using tiles, highlight pets with "heart" overlay (should be changed + to honor the `hilite_pet' run-time option) +X11: click-in-message-windows crash fixed +tty: fix panic when freeing endwin +tty: fix behavior when recalled text needs to wrap beyond top line +tty: allow selection from single line "help menu" (getobj's '?' response) +tty: don't format data.base with hardcoded tabs that are ugly on non-tty ports +tty: get rid of extra NHW_MENU space (improperly added when the menu was longer + than the screen) +tty: fix repeated "who are you?" prompting at game startup diff --git a/doc/fixes32.1 b/doc/fixes32.1 new file mode 100644 index 0000000..f30afef --- /dev/null +++ b/doc/fixes32.1 @@ -0,0 +1,133 @@ +General Fixes and Modified Features +----------------------------------- +give invocation message when teleporting onto invocation position +flying players with water breathing may retrieve things from water +remove message inconsistently assuming players can be mindless +monsters wear best armor (not first armor) and may switch armors +god doesn't give "strayed" message when your god is angry but a different god + is the one giving the message +divine wrath can hit engulfer if you are swallowed +plug minor topten and oracle memory leaks +monster throwing must allow for 0 damage (cream pies, non-silver vs. shades) +break drawbridge if wand of striking is zapped down at open bridge or either + up or down at its portcullis +wand of striking zapped at ceiling might cause a rock to drop (like digging) +wand of striking hitting a secret door with expose and break it +zapping {teleportation,cancellation,make invisible,polymorph} down affects + any existing engraving similarly to writing with such wands +monsters may use fire horns and frost horns +Guidebook.mn now formats backslashes correctly when using GNU groff tools +Add missing trident case to weapon type categorization. +Fix weapon proficiency handling for missiles. +accept "armour" spelling again for marker use (when writing was disconnected + from wishing, this got lost) +restrict writing scrolls and books by description +give better feedback for some writing results +whirly/wall-passing monsters should not be immune to falling rocks +relearn spellbook even when spell already known (object amnesia fix) +objects that have been called something but not ID'd are subject to amnesia +ask what to call unknown spellbook which crumbles to dust when mis-read +bullwhip only tries to get you out of a pit when you're in a pit +humanoids, gnomes, and ogres now eat; fungi and jellies don't +centaurs, giants, and various others can respond to #chat +potion of paralysis doesn't inherit prior nomovemsg +#naming a nameable artifact when the object already had a name of the same + length didn't create an artifact +applying unID'd potion of oil is possible even not carrying any other items + eligible to be applied +make potion of oil become known after lighting it via apply +fix remaining inconsistency which allowed diluted water +don't let breaking a wand of digging on castle level produce holes, just pits +make Nazgul's sleep gas actually put victims temporarily to sleep +applying a carried, unlocked, trapped chest will set off the trap +explosion due to #untrap failure on trapped door destroys it +shouldn't hear curse/bless status of unseen scroll being read by monster +give some variation in the amount of time it takes a corpse to rot away +breakable objects hitting the ceiling or the hero's head will now break +undead turning now gives credit to player for destroyed monsters +undead turning now brings dead eggs back to hatchable status +code added to support hatching of all eggs in a merged group of eggs +fix display updating at egg's former location when floor egg hatches +fix learning of egg type for hatched eggs +statue traps created with monster inventory inside them +probing shows contents of everything with contents, not just statues +spells of healing and extra healing don't make target monster angry +use cornuthaum cancellation factor +can't kick underwater objects from land or vice versa +objects falling through holes/trapdoors to random destinations obey arrival + restrictions imposed by special levels +being bare-handed counts as wrong projector when throwing projectiles +reduce the range that Mjollnir can be thrown +keep Medusa from continuing to move after she's been killed by reflection + of her own gaze (fixes relmon panic) +medusa's reflected gaze won't affect it if it has amulet/shield of reflection +eating amulet of strangulation can choke when not satiated; also not gluttony +intelligent pets hold onto one pick-axe and one unicorn horn +keep exploding boulders from land mines from hitting you with "a rocks" +objects carried by migrating monsters have no location +more robust parsing of user-supplied option names; trailing characters matter +don't generate spellbooks inside statues of tiny monsters +treat Medusa level statues as petrified monsters (can't be stone-resistant, + and have inventory) +Medusa doesn't gaze more than once per round +data.base: eliminate duplication of Orcrist/goblin king entry +handle luck conferring artifacts correctly (both inventory and enlightenment) +prevent arming land mines and bear traps in various inappropriate locations +prevent easy shop exit by having shopkeeper disarm and pick up trap objects +oilskin cloaks allow defender to slip away from grabbing attacker +make reading the cursed Book of the Dead riskier +enchanting stat-affecting armor now identifies it +fix crash caused by specifying "pickup_types" without a value in config file + or NETHACKOPTIONS (avoid attempt to use menu prior to interface init) +kicking at empty lit corridor with lit_corridor enabled doesn't redraw as unlit +when starting out with an oil lamp, make pre-discovered potions of oil show up + in the discoveries list so that their varying description is available +being crowned Hand of Elbereth enables minimal longsword proficiency even when + Excalibur isn't bestowed +bare-handed and martial arts weapon skill rankings use names instead of numbers + + +Platform- and/or Interface-Specific Fixes +----------------------------------------- +tty: reduce alloc/free activity done for message history +tty: windowtype:unsupported_value pauses between listing allowed value(s) + and proceding under default interface +X11: free allocated memory during pre-exit cleanup +X11: display help when DLB is enabled +X11: fix popup inventory window shown for 'i' response to "what type of + object?" prompt with menustyle={T,C} +DLB: avoid excessive fseek calls (major performance hit for MSDOS) +MFLOPPY: wasn't safe to enter endgame! traps, timers, and other level- + specific data ended up being inherited from level 1 +MSDOS: now can re-enter game after chdir'ing in shell from "!" +MSDOS: fix it so -H allows starting a healer game, rather than usage statement +MSDOS: display cursor during input prompts, not just when in the map +MSDOS: fix several cursor-related glitches when moving the display +MSDOS: prevent the use of F3,F4, and F5 before the map window is ready +MSDOS: make flags.BIOS and flags.rawio the default when VGA tiles are used +TERMINFO: colors were wrong for some systems, such as Linux +Amiga: count substitute tiles properly +MAC: avoid MW 68K struct copy optimization bug (in all developer releases up + to and including DR9) by adjusting our structures so it doesn't + occur +MAC: fix crash when trying to drag scrollbar +MAC: add UPP setup for UserItem FrameItem() +MAC: boost partitions to 2M minimum + + +General New Features +-------------------- +#qualifications command eliminated; subsumed into #enhance +OEXTRA temporary compile-time option +menu support for group accelerators to choose objects by class +lev_comp supports specification of percentage chance for monsters and objects +wielding Sunsword provides protection from light-induced blindness +interactive setting of options via menu (Per Liboriussen, liborius@daimi.aau.dk) + + +Platform- and/or Interface-Specific New Features +------------------------------------------------ +MSDOS: Add support for preloading all tiles in protected mode environments +MSDOS: Add support and initial tty Makefile for yet another compiler (Symantec) +BeOS: preliminary support for new BeBox platform; initially tty only + diff --git a/doc/fixes32.2 b/doc/fixes32.2 new file mode 100644 index 0000000..ad79094 --- /dev/null +++ b/doc/fixes32.2 @@ -0,0 +1,128 @@ +General Fixes and Modified Features +----------------------------------- +make `recover' work with the additional element of version info added in 3.2.1 +floating eyes cannot escape down stairs and ladders +do not use body_part() inappropriately when snatching monster's weapon +fix feedback for a confused long worm attacking itself +avoid converting locked secret door into closed+locked normal door; + doors should be flagged as either locked or closed but not both +kicking a locked secret door mustn't yield an open normal door +fixes for dipping weapons into potions of oil +fix crash triggered when knocking off worn blindfold by applying cursed towel +update screen display for vault guard picking up gold from fake corridor +Chromatic Dragon was missing appropriate resistances for orange (sleep) and + yellow (acid + stoning) dragons +when triggering a chest trap, clear the trap flag immediately [bones fodder] +when a boulder gets pushed into a pit where a monster is trapped, immediately + redisplay the monster after giving messages +rings of hunger dropped in sinks should have an effect even if player is blind +player #offering a cockatrice corpse must pass a touch check +hitting a rust monster with a pick-axe, iron ball, or chain will trigger rust + damage to the weapon; ditto for rust traps when wielding such items +cosmetic martial arts and bare-handed changes to skill arrays in u_init.c +gain or lose weapon skill slots appropriately when polymorph into new person +fix crash occuring when self-hit by uncaught boomerang +when delivering a pline message during level change, don't display areas of + the new level using line-of-sight data from the old one +heavy iron balls may be thrown multiple spaces (presumably they roll), + restoring old ball behavior +get rid of "non-null minvent despite MM_NOINVENT" warning +prevent a negative damage adjustment from boosting a target monster's HP +give "bashing" message when first attacking something with unconventional + wielded items besides just throwing weapons and non-weapon tools +when restoring, reset weapon so that "bashing" message can be given again +hole traps in bones data shouldn't be marked as unseen +when carrying 52 items, don't check shop goods for mergability with invent + because it will give false matches, yielding non-gold in slot '#' +kicking a cockatrice corpse is now as dangerous as kicking a live cockatrice +fix set_apparxy() crash when the Wizard returns via migrating monster list +monster wearing armor is protected from disintegration breath like player +monster wearing amulet of life saving survives disintegration breath +greased helmets will block AD_DRIN attacks +get rid of ancient check for welded weapons, which arbitrarily named or didn't + name the weapon for no particular reason. +levitation: sitting makes you tumble, kicking requires bracing +empty bag of tricks won't cause bag of holding to explode +prevent "force bolt" from hitting false match on *orc* data.base entry +prevent "{wand,scroll,spellbook} of light" from matching "* light" entry +non-confused genocide of player should not kill by "genocidal confusion" +re-word message for monster grasping already-wielded unicorn horn +fix various killer reasons +when pushing boulders, make sure current is always top object at its location +always clear unpaid items off shop bill when shk is teleported away, even + if shk was already angry +don't let broken wand of digging create traps at locations which already + have traps (prevent it from turning a hole into a pit) +don't give messages about unseen objects falling down holes +fix to prevent kicked objects which stop on holes/downstairs from becoming + unattached from any object list +don't let flying creatures set off a rolling boulder trap +fix to prevent seeing into a room by kicking an undiscovered locked secret + door from outside +account for case of monster throwing gem at PC unicorn +schedule repair for shop door smashed by big monster +update status line for energy used when "you fail to cast the spell correctly" +polymorphed character will mimic gold after eating mimic corpse +fix relmon panic when bashing weak undead with wielded potion of holy water +holy and unholy water can trigger transformation in werecritters +call update_inventory() when discovering or undiscovering (call " ") an object +fix goto_level panic: if quest leader seals portal, delete portal trap from + quest home level as well as from main dungeon's branch level [possible + return to quest via 'W' quest artifact] +prefix quest leader and/or nemesis name with "the" when appropriate at + run-time rather than using hard-coded text in quest.txt +fix endgame crash caused by string overflow when formatting priest|minion names +dokick.c compiles when WEAPON_SKILLS is disabled +burning objects go out when kicked +monsters with arms but not legs (salamander, marilith) can't kick +knights can't jump while poly'd into anything without legs +try harder to get names for corpses of unique monsters right +very high dexterity doesn't guarantee a hit for thrown potions and eggs +blinding ammo thrown from inside an engulfer can't blind it +monsters going through endgame portals arrive in same area as the player + instead of ending up at the portal to the next level +treat most of the moat on fakewiz levels as outside the special central + area, so that falling or wading into the water and auto-teleporting + out of it can't strand the character inside the room +monsters created by animating a named figurine will inherit that name +prevent possible player-controlled creation of unique monsters via tossing + statues of such onto statue trap locations +activating a statue trap with wand or pick-axe won't discard statue contents +cursed non-weapons can't slip when thrown, as it was in 3.1.x +don't reveal patron deity of high priests with the 'C' command's prompt +two flags structures now, flags and iflags, the latter not saved with the game +object name prefix buffer wasn't big enough for biggest possible case +negatively enchanted weapons thrown by monsters could do negative damage +prevent xorns from phazing through walls on astral level +live Wizard won't teleport to your level if he's carrying the Amulet +can't use 'C' to give the Wizard a name +fix charging for shop goods broken via striking/force bolt +prevent disintegration breath from destroying Famine and Pestilence + and from triggering impossible("monster with zero hp?") for Death +prevent attached ball and/or chain from becoming part of iron golem formed + during polypiling (ball & chain movement later accessed freed memory, + which either crashed or got "remove_object: obj not on floor" panic) + + +Platform- and/or Interface-Specific Fixes +----------------------------------------- +Mac: update `mrecover' +Mac: handle `-@' character name suffix for explicitly requesting random role +msdos: suppress tiles on rogue level when restoring games that were saved there +tty: support group accelerators for PICK_ONE menus +tty: after at a yn() prompt, don't blindly accept the character + used to get back to the prompt as the yn() result [could trigger + impossible("invalid sell response")] +Unix+tty: guard against problems with delay_output,TRUE/FALSE macros +X11: fix group accelerators and support them for PICK_ONE menus +X11: implement tty-style counts for menu selections +X11: proper pop-up placement with old-style window managers (eg X11R6 twm) + + +General New Features +-------------------- + + +Platform- and/or Interface-Specific New Features +------------------------------------------------ + diff --git a/doc/fixes32.3 b/doc/fixes32.3 new file mode 100644 index 0000000..9a33655 --- /dev/null +++ b/doc/fixes32.3 @@ -0,0 +1,30 @@ +General Fixes and Modified Features +----------------------------------- +Y2K fix: use 4 digit year values for the dates in the score file +updated COPYRIGHT_BANNER_A to reflect year of release +prevent "late" pline calls from triggering a crash when the RIP window was + displayed at end of game (observed when bones file rename failure + under Win95 was reported to wizard mode users) +being punished on the Plane of Water doesn't trigger a panic when air bubbles + try to move the ball&chain or you around +avoid rn2(0) divide by 0 for empty inventory when trying to crawl out of water +don't let randomly placed monsters on special levels prevent explicitly + placed monsters who target that location from being created (a web + trap's spider resulted in no quest nemesis) +don't let randomly placed stairs on special levels be covered by explicitly + placed features such as fountains +pager: guard against '%' in output from being treated as a printf formatting + directive (using '/' or ';' to look at food yields "% blah blah") +prayer result of ``escape from solid rock'' isn't inhibited by teleport + restrictions (attempting to fix all troubles got stuck in a loop) +report "file empty?" rather than "version mismatch" when that's the reason + why a data file fails its validation check +drum of earthquake can't destroy the high altars + + +Platform- and/or Interface-Specific Fixes +----------------------------------------- +micro (assorted): readmail()--don't show fake mail text when blind; also, + update the "report bugs to" message to specify +msdos: fix missing $(INCL) in dependency in djgpp Makefile +mac: Will only dispatch events if the window system is initialized diff --git a/doc/fixes33.0 b/doc/fixes33.0 new file mode 100644 index 0000000..119de07 --- /dev/null +++ b/doc/fixes33.0 @@ -0,0 +1,372 @@ +General Fixes and Modified Features +----------------------------------- +objects falling down a level don't cause everything at destination to scatter +randomize visible trap glyphs during hallucination +don't match statue entry when looking up statue trap [after trap detection] +do match statue entry when looking up "statue of a " when foo happens + to precede statue in the database; likewise for figurines +initialize random number generator before processing user configuration file + (random role selection always selected tourist) +support "character:X" and "role:X" in NETHACKOPTIONS as well as in config file +allow colon as an alternative to equals sign for `OPTIONS:whatever' and + equals sign as an alternative to colon for `pickup_types=?!="$' +make rndexp (blessed gain level) be safe for 16 bit integer configurations +don't add player's weapon proficiency bonus for weapon attacks by monsters +create quest artifact crystal balls with 5 charges instead of 0 +store ghost names in the same manner as other monster names (fix pet bug) +boost kobold shaman level to 2 (was 1, too low to ever cast a spell) +boost ogre king level to 9 (was 7, same as ogre lord) +throwing quest artifact to quest leader won't cause anger; also, artifact + will be caught and thrown back instead of being explicitly ignored +boost level of fake players in endgame to match their rank titles +don't lose odd hit points (integer division truncation) when splitting HP + for cloned monsters +update status line when cloning yourself halves your hit points +suppress clone's initial inventory for poly'd player just as for monsters +update the documention describing the O command +polyself: immediately update vision when reverting to human from eyeless form +use right pronoun when a mind flayer's attack is blocked by a monster's helmet +tins of lizard meat are never rotten, just like the corresponding corpses +tattered capes should not match ape entry in database +booze should not match ooze entry in database +lowered drawbridge should not match werecritter entry +lengthen option file line length to 4*BUFSZ +make zaps of death at polymorphed players work properly +change way invisibility works, add remembered invis monsters and 'F' command +don't list pick-axe and unicorn horn as likely candidates for charging +give more accurate message when nymph steals multi-turn armor from female char +fix splitting merged group of wielded weapons for menu mode version of #loot +if a buried container rots away, bury rather than destroy any contents +the 'W'ear command now only shows armor you can actually wear at this instant, + instead of all armor you're not currently wearing +wishing for a genocided monster egg gets a dead egg, not a generic egg +"Unfortunately it is still genocided" printed only if monster is in range + (particularly important for lifesaved monster genocided off-level). +message for monster growing into genocided monster only printed if in range +include number of attached candles when formatting candelabrum's name +support attaching already lit candles to candelabrum +range of candlelight varies with number of candles +dropping ring of hunger onto sink won't falsely claim that undestroyed objects + like the Amulet have vanished +winged gargoyle can't wear body armor +self probing and stethoscope display speed with same detail as enlightenment +throwing attacks can trigger reprisals similar to hand-to-hand and zap attacks +'A' now works in dropping like when picking up +make setting bear traps and land mines be a multi-turn occupation +make lava be properly lit on special levels +add orig.female flag to handle E quest monster situation +clean up inconsistent quest text +in initial legacy message, use "goddess" when appropriate +allow FIRSTNEMESIS message to actually be printed +taking a peaceful monster's weapon with applied bullwhip will anger victim +applying an unpaid magic lamp will charge a low lighting fee instead of the + djinni release fee +teleporting a Rider will usually bring it near you instead of sending it away +Riders can open locked doors without a key, just like the Wizard +Riders, angels, and elves won't avoid stepping on Elbereth/scare monster when + deciding where to walk +Riders and angels will ignore the sanctuary effect of temples +mind flayers cannot suck out brains by hitting long worm tails +don't ignore object age when #offering a partially eaten corpse +inability to pick up is not as general as nolimbs (blobs may pick up with + pseudopods and purple worms by swallowing) +wishing for a magic lamp produces an oil lamp, not a no-charges, possibly lit, + magic lamp +blobs may not ooze under doors if their inventory can't be squeezed through +peaceful/tame monsters will not use bullwhips on the player +ghosts were not inheriting player gender in bones files +cannot wish for tins of untinnable (due to insubstantiality) monsters +flying monsters cannot fall down stairs +prevent divine retribution from destroying a wand which is being broken +fix resuming to read a spellbook which has become blank since the prior read + attempt got interrupted +make recharging cancelled wands behave like recharging other cancelled objects +prevent "late" pline calls from triggering a crash when the RIP window was + displayed at end of game (observed when bones file rename failure + under Win95 was reported to wizard mode users) +cannot shatter soft weapons (whips, rubber hoses) +being punished on the Plane of Water doesn't trigger a panic when air bubbles + try to move the ball&chain or you around +seen-invisible monsters are consistently visible but transparent, rather + than looking like normal monsters +kicked object message for hitting another object no longer claims it "stops" +kicked object hits objects (plural) if quan>1 but there is nothing else there +kicking an object which is embedded in a closed door behaves like one in rock +can't kick object out of a known pit, but could when pit hadn't been seen yet +pets, shopkeepers, unique monsters, trolls, and Riders retain + their characteristics when killed and brought back to life +being polymorphed into a black light makes you hallucination resistant +don't attempt to perform panic save if the game is already over +don't leave old game's timers, light sources, and shop data in place if + aborted restore attempt reverts to starting new game [eventual panic] +Magicbane carried by mplayers has a lower enchantment than other artifacts +if pets take longer to untame than to starve, make them go wild anyway +split up erosion to allow both rust and acid (or fire and rot) +rust/fire/corrosion/rot now work in all cases (monster/monster, monster/you) +upon arrival to quest, mark return portal as seen +can't be blinded by light while asleep +can't put boulders or big statues into containers +engulfers which engulf a pile engulf 'several objects' +polyself: use right set of hit points for hunger and strength loss +polyself: likewise when checking for troubles during prayer +polyself: stop mimicking gold immediately if shape change occurs +polyself: change monster type when sex change occurs for succubus or incubus +Y2K fix: use 4 digit year values for the dates in the score file +when changing levels, update the screen to show the new level sooner +when changing levels, a monster might displace you from the stairs upon arrival +petrify polymorphed player who has protected hands but is using a non-hand + attack on a cockatrice +fix bug where barehanded AT_WEAP by polymorphed player on cockatrice worked +prevent multiple purchases of clairvoyance at temple from overflowing the + intrinsic's timed subfield and becoming permanent +when cursed, greased or oilskin cloak might fail to protect against grabbing +when any corpse wielded by a monster rots away, unwield it to avoid "bad + monster weapon restore" +hallucination affects priest and minion names +don't try to make the word "aklys" singular +bullwhip can't yank welded weapon from target +eroded T-shirts now display the eroded shirt text consistently +fix "killed by kicking something weird" when kicking a fountain +disallow fruit names whose prefixes are valid for food (uncursed, numbers, etc.) +properly handle wishing for fruits which start with other prefixes +avoid rn2(0) divide by 0 for empty inventory when trying to crawl out of water +don't let randomly placed monsters on special levels prevent explicitly + placed monsters who target that location from being created (a web + trap's spider resulted in no quest nemesis) +don't let randomly placed stairs on special levels be covered by explicitly + placed features such as fountains +substitute random monsters when special level monsters have been genocided +fix intrinsic blockage by worn items so that wielding a mummy wrapping or + cornuthaum won't have the same special effect as wearing one +magic markers created via polymorphing tools are flagged as being recharged +unseen rust monster eating messages, and make tame rust monsters consistent + with wild ones with regard to rustproofed items +pager: guard against '%' in output from being treated as a printf formatting + directive (using '/' or ';' to look at food yields "% blah blah") +getpos: support shifted movement letters in number_pad as per help text +getpos: properly truncate diagonal movements at map edge +using #name to call an object type something could be used to distinguish + fake amulet of yendor (appeared in discoveries list) from real (didn't) +upon quest completion, leader now IDs quest artifact and also tells player + that Bell of Opening is necessary if character doesn't already have it +remove unwanted quote marks from quest message R 70 +make polymorphed objects be likely to retain magic state: non-magic items + usually yield other non-magic items, magic items yield magic ones +make artifact mirrors unlikely to break when used to hit monsters +make sure that nemeses don't leave corpses if the message says there's no body +fix wizard-mode problem with generating Master of Thieves (was singularizing it) +allow weapon-using monsters who ignore gems to throw darts +make flint stones be the preferred ammo for sling wielding monsters +gaining/losing telepathy via polymorph (i.e. mind flayer) redisplays monsters +prayer result of ``escape from solid rock'' isn't inhibited by teleport + restrictions (attempting to fix all troubles got stuck in a loop) +fix surviving level teleport to a negative destination from somewhere other + than the main dungeon (was corrupting the level maps) +surviving level teleport to a negative destination ("you float down to earth") + escapes the dungeon instead of arriving on level 1 +dying due to level teleport directly to heaven won't leave bones +kicking shades with blessed boots, punching with blessed gloves or when wearing + silver rings, does the appropriate damage to them +add artifacts to ending score and display +prevent used objects like scrolls and potions which immediately cause the + character's death from remaining in final inventory (disclosure+bones) +blessed genocide of '@' will list the player's role during genocide disclosure +moved skill definitions to their own file (skills.h) and embedded them in + the object table. +increased the maximum number of branches supported by dgn_comp. +increased the number of characters permitted in a role name. +the number of bits available for properties are expanded. +water demons should not chat about being freed. +since hallucinating players see monsters constantly change anyway, don't print + message when werecritter changes +artifacts which do fire/cold/electric damage to their targets can destroy + carried objects which are susceptible to that type of damage +some artifacts are now unaligned in order to be more accessible to all types + of characters +wizard mode ^F command reveals floor traps along with the map +pager: '/' was not finding data.base entries for shopkeepers, mimics, or + race/role spit when picking from the screen +small monsters like hobbits and gnome zombies couldn't wear cloaks/wraps +make sure non-erodable objects aren't eroded or erodeproof (could happen by + wishing or object polymorph) +consistently let iron non-weapons rust, etc. +handle more spelling variations ("boots of speed",&c) when granting wishes +fix 3.2.0 change which flags the castle and priest quest levels as graveyards +when stepping on a spot where "there are several objects here" (so many + objects that they aren't automatically shown to the user), report any + dungeon feature such as stairs just like when there are fewer objects +report "file empty?" rather than "version mismatch" when that's the reason + why a data file fails its validation check +to-hit bonuses don't accumulate for monsters with multiple weapon + attacks +skill definitions moved to skills.h +skills are stored in the objects[] table. +intrinsics and extrinsics are now >32 bit +number of roles no longer limited to 26 letters +renamed typename() to obj_typename() +add "You hear a nearby zap" when monster is close +fixed a bug that would print of "a Book of the Dead" instead of "The" +fixed a bug so there is no delay when a rolling boulder trap is + triggered completely out of sight +fixed emergency_disrobe() so it will drop gold +fixed a missing case that occurs (rarely) when praying during a + full moon and your god is very pleased +ask for confirmation before praying; no more accidental Alt-P +more guilt messages when you do something which lowers alignment +mplayers get more suitable equipment for their role +allow spaces before = in the options file +dragon scales/scale mail of all colors now work when worn by monsters (in + 3.2.x, only gray conferred any special benefit) +when shopkeeper takes cash from dead player's corpse, clear `been robbed' + status if there's enough gold to cover the amount so that next + player who loads level as bones data won't start out owing money +merged scrolls of scare monster crumble to dust together, matching the + existing feedback (was destroying one and leaving the rest) +properly disallow wishing for venom and allow wishing for iron balls by class +drum of earthquake can't destroy the high altars +potion of oil can't be ignited while underwater +zapping a wand of digging upwards while underwater won't dislodge a rock + from the ceiling +add "born" field so monster extinction limits the number created, not killed +allow "okonomiyaki", etc. to pluralize properly (Ranma 1/2 is popular) +fix off-by-one bug that disabled the check to see if you tried to name your + fruit after a previously existing corpse or egg +avoid a "glorkum" message if an object conveying a warning is stolen before + the warning message is delivered +flags.made_amulet flag was never being set +make sure proper message is given when tinning cockatrice while a flesh golem +fix punctuation on cancelled cobra's dry rattle message +leash cannot choke monsters that do not breathe +rothes are now brown, harder to confuse with much more powerful grey quadrupeds +defer level change for every schedule_goto() call, not just while monsters + are moving (player's move could cause an engulfer to expel character + onto a level changing trap, then attempt to access stale monster and + possibly trigger relmon panic or crash) +fix obscure worm bug which did not consider the tail tip to be visible. Bug + produced "You miss it" on 3.2 and a blatantly obvious 'I' in prerelease 3.3. +water prayer: treat already blessed potions as `other' rather than as `water' +water prayer: potions being blessed glow light blue rather than amber; + hallucination affects the color seen when changed potions glow +fix Death/Sandman #9 joke (should be 8) and make sure the message can be seen +zapping Death with wand of death multiple times could cause hit points to wrap +when pet attacks monster that attacks back, be sure it's in range (could be a + worm attacked on the tail) + + +Platform- and/or Interface-Specific Fixes +----------------------------------------- +micro: -uwizard-{class} counts as -uwizard when allowing debug mode +micro (assorted): readmail()--don't show fake mail text when blind; also, + update the "report bugs to" message to specify devteam@nethack.org +msdos: fix overlay separations in weapon.c +msdos: fix problem breaking compile without REINCARNATION +msdos: fix dependency in djgpp Makefile (wintty.c -> hack.h) +tty: try to use terminfo sgr0 (aka termcap me) attribute to turn off all + text attributes, instead of just using "rmso" (aka "se") attribute. +tty: change name of nethack's termcap.h to be tcap.h +tty: ^P at a long prompt printed an extra newline (and then wrapped oddly) +tty: get repeat to work properly on extended commands +tty/ASCIIGRAPH: rogue level uses PC Rogue colors and symbols +nt: in TTY port, non-English keyboard layouts that depended on AltGr-+ sequence + were getting "Unknown command 'M-\'" for '\','@','$','{','[',']','}'. +tty and X11: avoid crashing trying to display long (>128 char) menu items +X11: avoid setuid install problems by changing uid to real uid while + opening the X11 connection. +unix: compress/uncompress detects failure of the compressor, such as for + filesystem full or missing compressor, and no longer deletes the + valid file. In the uncompress case, such as uncompressing the save + file, a message is generated as well. +dlb: handle situation where lseek(,,SEEK_END) doesn't yield the size of the + contents of a file (specifically, VMS "variable length" record format) +vms: install.com couldn't handle the `copy readonly files' step when DLB + wasn't enabled +mac: added unix tty-ish menu flexability +mac: stoped using OLDROUTINENAMES +mac: added dlb support +mac: Increased the maximum number of menu items, so the inventory + won't get cut off at the bottom. +mac: Changed the behavior of Cmd-Q so it uses the new #quit command. +mac: Will only dispatch events if the window system is initialized. + This fixes a bug that would crash the system if the user had an + invalid option in the NetHack Defaults file. +mac: Added an appropriate message when eating an apple. +mac: Change the askname dialog for the new role patch. +mac: Add a gray background to all dialogs. +mac: Replace some improper calls to InitCursor(). +mac: Remove a whole bunch of unused code. +mac: Added Balloon Help messages. +mac: Pop-up menus display the 3-letter file code instead of a single + letter. +mac: Pop-up menus and text item have a 3-dimensional look. + + +General New Features +-------------------- +incorporate the "wizard patch" +`#quit' command added +`*' command added; displays inventory of all equipment currently in use +add Stone To Flesh spell +wands eventually explode if rechaged too many times +show IDed Amulet of Yendor + invocation tools in own section of discoveries + list; likewise for IDed artifacts +add infravision +add Eyes of the Overworld +add lenses +split players race from role in life +cursed figurines cam spontaneously transform when carried +`in_use' struct obj field is unconditional rather than just #if !NO_SIGNAL +add the secondary weapon slot, e(x)change command, #twoweapon + command, and "pushweapon" option. +add the quiver slot, (Q)uiver command, (f)ire command, and + "autoquiver" option (defaults to false). +add the "pickup_burden" option which controls when the user + is asked for confirmation when picking up an item. +pole-weapons can be applied at a distance, and similarly used by monsters. +'/' command's pick-a-location input (getpos) supports shortcuts to bypass the + "more info?" prompt; ':' for '.'+'y', ',' for '.'+'n', ';' for ','+ESC +monsters can throw cockatrice eggs at players +prayer trouble "stuck in wall" takes boulders into consideration +crysknives can be "fixed" +vampires now #chat back +new monsters: chickatrice,pyrolisk,fox,coyote,winter wolf cub,dingo, + gas spore,flaming sphere,shocking sphere,lynx,panther,raven, + glass piercer,mastodon,woodchuck,centipede,master mind flayer, + pony,horse,warhorse,silver dragon,lichen,storm giant,arch-lich, + dwarf mummy,green slime,disenchanter,monkey,dwarf zombie,ghoul, + paper golem, gold golem,glass golem,prisoner,jellyfish,piranha, + shark +new objects: amulet of unchanging,silver dagger,silver spear, + silver dragon scales/mail,robe,alchemy smock,kicking boots, + kelp frond,eucalyptus leaf,scroll of earth,spell of drain life, + potion of acid,potion of full healing,potion of polymorph, + potion of sleeping,ring of free action,ring of gain constitution, + ring of increase accuracy,ring of slow digestion,grappling hook, + ring of sustain ability,wand of enlightenment,saddle,various gems +add Monk role +the old Elf role is replaced by the Ranger +add Human, Elf, Dwarf, Gnome, and Orc races +add multishot ammunition +add graves, iron bars, trees, and arboreal levels +dwarvish mattocks can be used to dig +add leprechaun, cockatrice, and anthole special rooms +add the Sokoban dungeon +implement talking artifacts +members of the clergy (aligned/high/player priests and monks) are + generated with a robe instead of chain mail. +new tin of meat types +tinning kits and cameras have charges +blessed magic mapping detects secret doors +starting spells are known at start of game +pre-discoveries are listed with an * +voluntary challenges with #conduct +add a funny message when eating tridents and flint stones +allow debug-mode level teleport to the sanctum +some #monster commands now consume energy +trees can be kicked as a possible source of fruit +Wile E. Coyote references when using '/' on a coyote + +Platform- and/or Interface-Specific New Features +------------------------------------------------ +WinNT: implement mail support +WinNT: console mouse support added to TTY port + diff --git a/doc/fixes33.1 b/doc/fixes33.1 new file mode 100644 index 0000000..4b4a1c3 --- /dev/null +++ b/doc/fixes33.1 @@ -0,0 +1,444 @@ +General Fixes and Modified Features +----------------------------------- +discarding a tin without eating should not count towards food conduct +expand 'nethack.cnf' in dat/help to include new names on some platforms +using 'C' to name a steed produces a "pony tail" +stopping reading a spellbook when "too much to comprehend" left in_use set +conduct: eating meat{ball,stick,ring,huge chunk} counts as eating meat +don't select gems--aside from rocks and known glass or flint--via autoquiver +skilled slingers can shoot multiple rocks with one shot, like other archers +orcs shooting orcish arrows from orcish bows get multishot bonus, like elves +have 'Q' offer gems/stones as likely quiver candidates when wielding a sling +'Q' command--don't offer tools as likely quiver candidates +spell hunger effect for wizards of high intelligence was not computed correctly +fix "killed by the [master] mind flayer" bug +redisplay correct trap glyphs when hallucination ends +monsters under Conflict cannot attack other monsters that are already dead +monsters that steal gold from monsters should teleport +fix mummy wrappings worn by monsters to block invisibility +applying a weapon or wieldable tool would sometimes give spurious messages + about two-weapon combat +applying a weapon or wieldable tool might not always end two-weapon combat +receiving a divine gift artifact while wielding two weapons would unrestrict + two-weapon skill instead of the skill for the artifact's type +throwing and kicking while wielding two weapons exercised two-weapon skill +when wielding two weapons, ')' command should show both +giants cannot "easily pick up" boulders on the Sokoban level +W command would let you wear an arbitrary item in your body armor slot if that + was empty & uncovered and you carried extra armor for any filled slot +W command would list entire inventory if you answered '?' to the "what do + you want to wear?" prompt when all unworn armor couldn't be worn +#looting and applying containers with menustyle != traditional would do bad + things if you split a merged stack in quiver or secondary weapon slot +save/restore while mounted or stuck could cause a game crash or other errors +baby gray dragons should not be visible to infravision +dying from a failed saddle attempt should name the monster without using + hallucination +spurious "Bummer, you've hit the ground" when hallucinating and dismounting +constitution of <3 and >18 (possible in 3.3 because the ring of gain + constitution was added) was not handled properly +potion and wand of invisibility (on yourself) should not print message if you + are already invisible, even if you can see invisible +reviving tame monsters ended up tame but not peaceful and would attack you +wishing for "rotproof" item is recognized as synonym for erodeproof +your pair of boots "are" not affected when kicking rust monster should be "is" +use article "a", not "an", with "eucalyptus leaf" +fix crash if reviving troll has been genocided +shouldn't see candles flicker when blind +gas clouds use cloud symbol +unchanging suppresses amulet of change, intrinsic lost by life-saving +missing lucern hammer, silver dagger, silver spear in monster weapons +buckled boots are brown +Scorpius and centipedes are not web-makers +race placeholders are M2_NOPOLY +Monk species/leader/guardians are M1_HERBIVORE +leader/nemesis flags fixed with |= instead of = +freezing spheres won't leave corpses +artifacts should add to ending score even if they are inside a bag +being killed by a gas spore should not be treated as burning (most noticeable + problem was that the death message did not include "killed by") +remove a double period from "Caught himself in his own fireball.." +automatic dog names restricted to dogs +chatting with a monster that teleports after the chat (succubus, bribable + demon) would put an 'I' symbol at the monster's destination +stethoscope/probing should reveal identity of invisible monster, not use "it" +wand of probing zapped at 'I' square with no monster should clear the 'I' +cursed potion of invisibility drunk by monster should reveal 'I' +kicked monster that evades kick by moving to unseen square should not leave + 'I' in original position of monster +closing a door on an invisible monster reveals the 'I' +gas spores are recognized as having passive damage for purposes of pet attack +since iron armor can now corrode, don't call all corroded armor "bronze armor" +properly handle attacking a black pudding with a corrodeable weapon +do not print "You still cannot see" when blind and removing lenses +remove possibility of crashes when unseen monster engulfs items +object shattered by wand should use plural verb when object is plural +don't anger monsters when hitting them with invisibility or helpful unholy water +for initial inventory, don't give out spellbooks in restricted spell skills +for tourists' initial inventory, put darts in quiver rather than wield them +artifact discoveries sometimes showed undiscovered object types (for example, + Snickersnee as "katana" when katana was still known as "samurai sword") +"iron bars" singularization exception should not also catch "candy bars" +if a monster kills a monster by throwing acid, don't credit the kill to you +leave two-weapon combat mode if either weapon is stolen or otherwise unwielded +use worse of (two weapon skill, current weapon skill) when figuring skill + bonuses and penaltys while fighting with two weapons +never give back-stabbing or weapon-shattering bonus when using two weapons +engulfing monster will not engulf your pony while you are riding +arch-lich usually starts with an athame or quarterstaff +do not say that "an" Asmodeus reads a scroll +'?' command--short options help sometimes included garbage output +'?' command--longer options help omitted several recent options +eating an amulet of restful sleep now works properly +getting hit by a potion of sleeping now works properly +sleeping is reported by enlightenment +detect unseen / secret door detection refreshes unseen monster (`I') glyphs +monsters won't pick up objects in water (especially kelp) +unseen check for monsters in explosions +fixed "petrified by an " +silver arrows cost a little more than other arrows +javelin back in its own class +dipping weapons in potion of oil now works properly +freed prisoners become peaceful +monk titles shortened so they aren't cut off +elven Priests get their starting musical instrument +you can now correctly ride centaurs +fixed steed getting teleported (e.g. by Quantum mechanic) +fix stethoscope/probing speed reporting, and slowing attack on player +blessed detect monsters increments (not sets) the timeout, and produces a + message if no monsters are on the level +put "Elbereth" under the sokoban prize so that monsters don't eat it +a weak race can still have a high strength if polymorphed into a strong monster +make dingos non barking canines +suppress zap up/down message for stone to flesh on non-stone levels +fix missing spaces on sokoban level that made level impossible without cheating +use case-insensitive comparison for wishing (needed for Master Key of Thievery) +avoid commas in the player name because they confuse the record file +note Sliming when using probing/stethoscope on yourself +fix inconsistency: reflecting medusa's gaze while invisible didn't work, + reflecting floating eye's gaze did +Medusa should not drink potion of invisibility (the code only checked for wands) +restore confirmation prompt for kicking pets and peaceful monsters +ask for confirmation about kicking steed when kicking while mounted +converting secondary weapon into an artifact (naming, dipping) stops #twoweapon +a fully ID'd object converted into an artifact is no longer fully ID'd +polymorphing an object by dipping in potion while inside a shop will only + anger the shopkeeper if the object is shop merchandize +make {wand,spellbook,potion} of polymorph immune to being polymorphed +turning undead should count as calling on a deity for purposes of conduct +fix "monster trail" problem caused by reading a scroll of magic mapping while + engulfed +don't give Slow_digestion-related message when non-digesting engulfer expels you +vary vampire's chat responses according to time of day, tameness, and player + form +added fish_parts to mbodypart/body_part +fixed do-while loop test criteria in create_mplayers() +fix crash if reviving troll has been completely drained by Stormbringer, et al +a stinking cloud should not kill a monster more than once +player stops riding when nymph steals saddle +don't ask for name for eaten ring of slow digestion if already identified +don't let engulfed lifesaved monster beat you up while supposedly being + totally digested +lev_comp: honor class in OBJECT entries (user's '+',"identify" made scroll) +fix uninitialized buffer/unprintable characters error when eggs hatch +accept "aluminium" as variant spelling for "aluminum" +don't die from lava while praying +correctly display gems for the final score even when blinded +throwing a boomerang from {wielded,secondary,quiver} weapon slot will have + it be restored to that slot if caught upon return +don't allow iron balls to pass through iron bars +fix "What weird role is this? (E)" for names taken from 3.2.x score records +make spell of jumping work properly when restricted in escape spells +save traits of petrified monsters; animated statues are like revived corpses +unmoving monsters seen by infrared are removed from/displayed on the screen + when they leave/enter direct line-of-sight +Sting and Orcrist get their anti-orc bonus against orc player characters +buffer overrun caused by many long names in a single message +polymorph can't indirectly transform scrolls of mail into blank scrolls via + paper golem creation +don't let savebones() name a ghost without checking for sufficient space +don't report "killed by ghost of Foo called Foo" on tombstone or in record +when breaking create monster wands, don't place monsters inside solid rock +don't allow tainted cockatrice corpses to prevent stoning if you eat one +oil isn't seen as dimly glowing if you're blind +properly consider hallucination and blindness when printing sliming messages +don't allow the player to jump through iron bars or walls (the latter only + when wearing the Eyes of the Overworld) +don't allow the player to hurtle through iron bars +work around race condition between breaking a wand of teleportation, + teleport control and autopickup +rust traps should affect scrolls +lev_comp returns error if level cannot be fully written out +blank scrolls/spellbooks don't count as reading material +fix seduction attacks to treat characters polymorphed into golems as neuter +chaotic sacrificing on a chaotic altar may crash if demon creation fails +failed demon summoning might cause monsndx panic +avoid possible crash when casting fireball spell while engulfed or near the + edge of the map +prevent observation of dust clouds in rogue level doorways when blind +cans of grease will no longer rust +skip already dead monsters when scanning the full monster list; avoids + monsndx panic and other potential trouble +skip already dead shopkeepers when checking for tended shops +level teleport high in the air while lifesaved should result in an escape +the "stoned" flag wasn't reset when a monster was lifesaved from turning to + stone, so the next monster you killed would always turn to stone +wooden harp is not a magical object +player characters got left at 10 when "normal" speed was increased to 12 +time it takes a monster to change armor doesn't depend on whether you see it +character can't be totally digested on first turn of being swallowed +level 25 engulfer would trigger divide by 0 crash via evaluating rnd(0) +wielded egg that hatched wasn't cleaning up worn objects and might cause crash +mirror shouldn't show location of unseen monsters +cloth headwear was being reported as leather when fire damaged +modify moveloop so that time (moves) is not relative to the player's speed +fix moveloop to account for player not accumulating enough movement points + to move in a turn -- this fixes the reported "time is wrong when + burdened" problem +monsters should not teleport on levels that disallow teleportation +consider existing poison resistance when printing message while eating +don't allow various spells/effects to turn monsters into genocided species +don't crash on abusing guardian angel (accessing edog) +call useupall() rather than useup() for organic items burned by lava +revive any Rider corpse which gets teleported +wishing for gold should affect conduct +gold detection should detect gold golems +grease should affect the secondary weapon in two-weapon mode +falling drawbridge, eating cockatrice eggs, delayed self-genocide all caused + monsters to be fully named instead of using "it". +change the You_hear message if hero is asleep +various inventory changes did not immediately update when perm_invent was set +avoid crash when multiple, cascading explosions occur +pets are no longer permanently weakened by a brush with starvation +doeat() doesn't leave rotten food half-set-up for resumption +don't allow trying to resume eating a revived rider corpse +shopkeepers, priests and peaceful monsters should get angry when you cast + stinking cloud on them +when crowning a neutral wizard who knows finger of death but isn't carrying + its spellbook, don't drop his weapon (crash likely) +similar greased and non-greased objects would merge together into one stack +monster reading scroll of earth may be allowed an extra attack +change message for failed attempt to mount steed while punished +fix multi-shot throwing for darts and shuriken +update monster multi-shot throwing to match player throwing +prevent inappropriate use of "lungs" in creatures that have none +change several instances of 'pline("The ' to 'pline_The("' +monk characters kick as characters rather than as kicking monsters +fix kicking shades by character polymorphed into kicking monster +fix articles in some Sokoban trap messages and eliminate some + superfluous messages +restoring with damaged subroom shops on non-current level could dereference + stale shk pointer +prevent removal of levitation in sokoban pits from causing you to + "float gently to the ground" +peaceful/tame mindflayer now mindblasts hostile monsters and vice versa (the + check was backwards) +fix suppression of stone-to-flesh on unique monster statues +kill player when drain life induces negative HPs +rumors used as engravings should not refer to fortune cookies +magic-resistant players/monsters unhurt by monsters zapping wands of striking +fix time problem where disrobing took too long +saddle that comes with a knight's initial horse should be known to player +iron golems are sensitive to more ways of getting wet with water +prevent odd contents of initial tourist tins and eggs (the contents were + mostly from the quest level, producing many cave spider eggs) +breaking a wielded wand doesn't leave it wielded +if nymph hits monster on first attack and teleports away, suppress second attack +kicking a mimic should reveal its presence +using 'F' command on a pet with safepet should not produce "thin air" message +polymorphing into slime or fire creature removes Slimed; becoming a new man + resets the Slimed timer +throwing cockatrice corpse barehanded should stone the player +avoid "petrified by petrification" on tombstone +avoid "turning into green slime" on tombstone (KILLED_BY didn't work if Slimed) +since unchanging prevents sliming, make it reset any sliming already present +avoid "You turn into a female succubus" redundancy +player hit by potion of acid should take damage like monster +"You are protected" in enlightenment display should include u.uspellprot +chameleons that change into a non-moving, non-attacking form shouldn't get stuck +fix bug where monsters didn't wield bow (etc.) before shooting arrows (etc.) +medium size is too large for giant bats (it allows leaving plate mails when + killed) +player polymorphed to a ghoul resists sickness just like a ghoul monster +player in werecritter beast form shouldn't polymorph into "human" +player wearing scales of genocided dragon was getting duplicate "you feel + dragon-ish" messages when polymorphing +fix luck timeout for full moon and friday 13th +monsters must wield polearms before using them, just like players +when saving bones data, shopkeepers will claim dropped objects inside shops +pets will now wear objects they pick up +pets will now wield pick-axes when necessary +limbless pets are no longer able to carry objects +monsters cannot consider a mattock for digging if they are wearing a shield +avoid a case where monsters keep switching between pick-axe and weapon +override hallucination when reporting pets that ascended or escaped with player +avoid duplicate pickup() calls when landing after falling through a hole +added squeaky board traps to Lord Surtur's lair entrances +cursed lenses no longer considered a major problem by deity +prevent "seeing an image of someone stalking you" when Blind +disallow potion of polymorph / ring of polymorph control starting combo +disallow starting with blank paper +tools shouldn't charge beyond 127 charges +getting money from a fountain should set the looted flag +pole-weapons won't bash and will advance skill when on steed +blessed genocide of polymorphed unchanging player should kill +picking up nothing should take no time +quiver command should take no time +potions should not be autoquivered as worthless glass +players should not get double-billed when using or altering items +silver dragons should have same resistance as other dragons +golems should be un (reverse-)genocidable +player should get blamed for destroying Minetown fountains by Excalibur dipping +player should not get blamed for others destroying Minetown fountains +digesting ghosts and shades as a purple worm should be nonvegan but vegetarian +eating brains as a mind flayer should be nonvegetarian +eating eggs should be nonvegan but vegetarian +eating tripe, meat sticks, chunks of meat should be nonvegetarian +headstones now implemented through engraving +luck penalty for the remaining forms of "creative NetHacking" in sokoban +don't penalize a turn if player cancels #ride direction +Ranger quest is no longer a rip-off of the old Elf quest +several Hello() messages were inappropriate for various monsters +storm giants should talk +monk leader and guardians should use clerical spells +monks shouldn't start with scrolls of enchant weapon +movement rate when saddled was miscalculated +items under lava shouldn't been seen or picked up +clicking in status line during `/' shouldn't cause getpos error +huge chunk of meat should count as dogfood +"Pardon me" when moving directly into peaceful monster +shouldn't glow amulet and save life of digested monsters +" gets angry!" only when you can see the square +"Never hit with a wielded weapon" conduct should only count + weapons and weptools +lynxes should not have cold attacks +Naming a specific object asks "What do you want to name *this* ___" +"Having fun sitting on the floor" shouldn't over fountain +"ball lightning" changed to "ball of lightning" +"poisoned by a poisoned crude arrow" should be "killed by a poisoned + orcish arrow" +shouldn't see invisible monsters oozing under a door +fix apostrophe for invisible seen-invisible crumbling-to-dust liches +amulet of change when polymorphed into single-gender monster could produce + inconsistent role name for Priest(ess) and Cave(wo)man +prevent Fire Brand from "burning" a water elemental +snatching cockatrice corpse gloveless by applying bullwhip will now stone +inventory description of wielded two-handed weapon uses "weapon in hands" +inventory description of secondary weapon explicitly lists it as non-wielded + to reduce confusion about two weapon combat +Bell of Opening removes attached iron ball when performing opening magic +chatting to a monster who responds with "I'm trapped" reveals the trap +Make tmp_at() work when called in the midst of a previous tmp_at() sequence +Make the messages for attempting to wear lenses over a blindfold more clear +Prevent buffer overflow when reading engravings that are BUFSZ in length +paralyzation message on steed should not say your feet are frozen to the floor +avoid buffer overflows and associated security problems from getenv(), + program name, and user name + + +Platform- and/or Interface-Specific Fixes +----------------------------------------- +Mac: legacy message was being truncated +Mac: black background left mess on backspace +Mac: backgrounds set too early on game startup +Mac: tty window positions not remembered after move +Mac: tty window turned B&W when moved to bottom of screen +Mac: tty quit command fixed +Mac: remnants of previous hunger status now cleared +MFLOPPY: add checkspace option to avoid problems with >2GB free space +MSDOS: fix clearlocks() to look for the right file names, + and not LEVELS.* (MFLOPPY only) +MSDOS: remove djgpp stuff from the Microsoft C Makefile +MSDOS: change NetHack.cnf to defaults.nh in NHAccess.nh comments +MSDOS: add missing files to gcc 'make spotless' +NT: WIN32 specific code in tty_nh_poskey() was missing the + necessary code to clear window flags so after hitting ESC + messages that should have displayed did not +Linux: set MAILPATH properly +Linux: don't use control characters on Rogue level with IBM graphics +DEC UNIX: set MAILPATH properly, type lex functions properly, avoid conflict + with curses over naming +Qt: remove intermediate files on 'make spotless' +Qt: modify makefile to allow use with BSD make and FreeBSD +Qt: have player selection dialog come up when name specified +Qt: use default menu accelerators and allow remapping +X11: fix memory leaks is reading from dialogs +X11, tty: avoid crashing when displaying empty menus, as from 'i' with + perm_invent and no inventory +tty: when given the choice of ANSI color (AF) vs standard color (Sf), choose + ANSI since there is some disagreement as to the correct color order + for Sf, but no such disagreement for AF. +tty: add workaround for termcap misfeature in some Linux distributions which + affects DECgraphics display +Amiga: minimal functionality restored +Amiga: recover created empty (and unused) save.info files +Amiga: ^P works properly +Amiga: windowcreating modified for better adaptivity +Amiga: changed from intuition menus to gadtools menus +Amiga: changed default colors in tilemode to those of gfxfile +Amiga: window backfill works +Amiga: playerselection adopted from tty-port +Amiga: linesplitting in msg/inv/menu windows fixed +Amiga: obey user configured pens in nethack.cnf +Atari: tty port rescued from oblivion, Gem windowing added + + +General New Features +-------------------- +gold/glass golems, glass piercers now resist acid +added sharks, piranha, jellyfish, prisoners, and iron bars to special levels +piranha can appear in swamp rooms +hero falls off steed when fumbling or falling down stairs +artifacts speak when applied +engraving "x" is not literacy +demons and vampires engrave in blood +shopkeepers don't like riding customers +can #chat down to steed +own race in Gnomish Mines replaced with random monsters +differentiate between light/gaze-induced blindness and other causes of blindness +yellow dragon scale mail provides acid resistance +polymorphed player digests engulf victims more slowly if Slow_digestion +Conflict now affects steed's desire to keep its rider +undead turning of bones level player corpse causes ghost to reunite with + the corpse +control-x in regular mode displays name, role, race, gender, and your deities. +wizard mode can wish for pools of lava +pythons now have infravision to emulate real pythons heat sense organ +M-2 added as a shortcut for #twoweapon +general file location mechanism +you can choose to #loot the saddle from something now +message changes for silver dragon scale mail glowing silver and pit vipers + falling into pits +support explicit `race=random', `alignment=random', and `gender=random' + in startup options +manes now grow up into lemures +potions of healing and sickness affect Pestilence in the opposite way to + their effect on other monsters +introduction of a new method of warning where you sense the danger level of + monsters on the level by displaying it at the monster's location +introduction of a new method of warning for specific monsters the way Sting + does for Orcs; you sense their presence anywhere on the current level +artifacts can belong to specific races and won't be given as gift when "hated" +Archeologists get a penalty for breaking "historic" statues +hatching eggs in male player's inventory have chance of "Daddy?" +steeds affected by more types of wands zapped down +opening/knock versus steed drops saddle +unwearing your steed's saddle (e.g. stolen, opening) causes dismount +yet another funny message when whipping a horse corpse +yet another funny message when mounting when hallucinating +Bell, Book, and Candelabrum added to final score like artifacts +new keywords coaligned and noncoaligned for altars (and monsters/priests) + in special level descriptions +quest start levels get coaligned altars if their roles have multiple + alignments, and goal levels get noncoaligned altars +ice vortices and freezing spheres are infravisible + + +Platform- and/or Interface-Specific New Features +------------------------------------------------ +X11, tty, Amiga: offer for player selection only choices consistent with those + already made by config file/command line (e.g., only offer roles that + are compatible with specified race) +tty: eight_bit_tty option +Amiga: implement menu_* accelerators and counting +mac: the "record" file is created if it does not exist diff --git a/doc/fixes34.0 b/doc/fixes34.0 new file mode 100644 index 0000000..799fc8b --- /dev/null +++ b/doc/fixes34.0 @@ -0,0 +1,592 @@ +General Fixes and Modified Features +----------------------------------- +prevent an extraneous selection prompt when a role with only a single + possible gender, race, or align is specified +be consistent with the use of twice and thrice in end of game reports +use "kill" vs "destroy" more consistently +looting bag of tricks on the floor doesn't then prompt for direction +suppress "the" in "you kill the poor Fido" +iron bars added to the Dark One's prison +shouldn't be able to #loot without hands +level compiler can specify cockatrice nests, leprechaun halls, antholes +fix level compiler to allow specifying golems via '\'' in MONSTER directives +fix bug where excalibur blasted lawful non-Knights +unification of the strings "he"/"him"/"his" +conflict caused vanishing vault guards to be killed with player getting + credit/blame (also dmonsfree warning for double removal from map) +monsters' conflict resistance check was unintentionally being affected by + character's experience level +stone-to-flesh was accessing freed memory, passing bad map coordinates + to newsym that might be harmless but could trigger a crash +prevent spurious "placing steed on map?" impossibles during save/restore +prevent real "placing steed on map?" impossibility [sic] when creating bones +dropping secondary or quivered weapon to lighten load in order to crawl + out of water left the item flagged as still worn +if #adjust combined two or more of main weapon, alternate weapon, and quiver + the resulting stack would be flagged as worn in multiple slots and + eventually trigger "Setworn: mask = ##." impossibility +remove curse operated on secondary weapon even though it wasn't wielded +update conduct immediately when eating corpses (character killed by eating + poisonous corpse as first meal was described as "strict vegan") +fix problem with amulets of change when polymorphed into succubus/incubus +YAFM for pit fiends/pit vipers and pits should require seeing the monster +woodchucks, cockatrices, and vampire bats should eat +specifying a non-numeric value for amount when donating to temple priest or + bribing demon prince produced random result +mastodons can tear through webs +praying on wrong deity's altar cursed holy water but ignored uncursed water +polymorphed player's gaze now works properly as a pyrolisk +fix "You drop the Wizard of Yendor's corpse into Wizard of Yendor's interior." +make sure status line gets updated when turning-into-slime state changes +when eating green slime, don't reset slime countdown if already infected +stop current activity when you noticed you're turning into slime +message given when displacing an unnamed pet into a polymorph trapped referred + to it by its new monster type rather than by what you displaced +player killed by ghoul turns into one in the bones file +slings are not made of wood +for post-amnesia deja vu messages, use "seems" rather than "looks" when blind +avoid encumberance messages during startup attribute adjusting +even a wumpus cannot escape the pits in Sokoban +when a steed dies in a shop, don't charge for the saddle +shopkeeper did not charge for use of an unpaid camera +shopkeeper did not charge for items burned by breaking a wand of fire +shopkeeper should charge when you transmute a potion +shk notices if you use a grappling hook to remove an item from the shop +adjust robbed shopkeeper's feedback when he or she plunders hero's corpse +avoid giving away which monsters are saddled while hallucinating +when polymorphed into a herbivorous monster, you should prefer vegan "corpses" +when polymorphed into a hider, stop hiding after picking up the last object + at a location +throwing a wielded, returning weapon should not disable twoweapon mode +monster should not wield cockatrice corpse without gloves on +sharks have thick skin +better message when killed by drinking a potion of sickness from a sink +telepathically detected monsters will be described by name if they try + to attack praying character +taking cockatrice from or putting it into a container should stone you + if you are unprotected +don't fall into pits (or other traps) twice when dismounting +fix two weapon combat bonus/penalty to avoid "weapon_hit_bonus: bad skill 2" +unicorns were at a disadvantage on a noteleport level +missing a cockatrice when polymorphed into a weapon-using monster but + fighting hand-to-hand would stone the player +eliminate ghoul creation abuse when engraving on a headstone +loss of levitation due to a sink will result in touching a wielded cockatrice + corpse, just like falling down stairs while burdened +falling into a sink when constitution is greater than 20 won't raise hit points +stinking cloud should not affect migrating monsters, causes dmonsfree error +only display message about monster using a weapon against another monster + if you can see the monster +don't count artifact amulets (wizard's quest artifact) twice in final score +prevent pets from picking up Rider corpses +when polymorphed into a centaur, don't keep kicking monsters after they die +when throwing at a monster that you see with infravision, don't say "it" +avoid "the arrow misses the mimic" which left the mimic concealed +#sit while water walking over a submerged object should sit on the water's + surface rather than on that unreachable object +suppress extra "the" when printing the names of certain mplayers +do not try to engulf green slimes (same as for cockatrices) +trying to eat the brains of a green slime is now properly handled for players +monsters touching cockatrices check boots for feet and nothing for tentacles +if being petrified, don't disable messages from further petrify attacks +trap detection would generally not find trapped doors +avoid spurious done eating message after choking and vomiting +attribute distribution for several player types did not add up +monsters shouldn't try to eat green slime as a cure for stoning +lighting of arboreal levels should not be stopped by trees +need to recalculate visible locations immediately when monster blinds player +monsters shouldn't see through walls because player wears Eyes of the Overworld +when pricing glass the same as valuable gems, be sure to use gems of same color +nymph stealing armor from a fainted player should wake the player +ensure status line updates when you stop running when time is shown +repairing a trap in a shop doorway must replace the broken door or wall as well +sleeping steed cannot climb stairs/ladders +can't change levels when mounted on a steed which is carrying the Amulet +more artifacts granted by a deity are rustproof +monster name feedback when using the m movement prefix allowed player to + distinguish between peaceful and hostile monsters while hallucinating +scrolls should not fade when hitting rust monsters, only from rust traps +blank scrolls should not fade even from rust traps +can't eat or #offer food off the floor under circumstances other than + encumbrance where you couldn't have picked it up off the floor first +ensure correct message after passive freeze attack by gelatinous cube +avoid buffer overwrite when several weapons slip from your hands at once +prevent portal placement on Ranger quest from stranding player in left margin +avoid crash when a trouble gets fixed before you finish praying +sensed hidden monsters should fight back when attacked +mindless monsters won't be grateful after unsuccessful #untrap attempts +turning affects your religious conduct, even if your god does not help you +rolling boulder trap's boulder will knock another one that it collides + with into motion in its place +make it harder to abuse detect monster and confusion spells +prevent D[a from producing odd message sequence in (c)ombination mode +avoid messages like "the silver bell" after being drained by mind flayer +after polymorph, actually drop both weapons when a message says this happened +curb unicorn horn creation abuse by limiting the chance of a unicorn + leaving one if it has been revived +accept -p and -r options with nethack -s, as documented +avoid printing "spellbook of" Book of the Dead in list of discoveries +eating non-food items made of leather or other animal parts now violates + vegan/vegetarian conduct +use correct skill when throwing something while in twoweapon mode +secondary weapon can rust when hitting a rustmonster in twoweapon mode +extra healing spell cures monster's blindness +add missing quest message for throwing the quest artifact to the Monk leader +pits, arrow and dart traps, webs, polymorph traps and sleeping gas + traps can affect the steed +allow game restoration while polymorphed and your race is genocided +ensure that crysknives revert to worm teeth, even in containers +do not print gas spore's name if you cannot see a gas spore explosion +cursed two-handed weapons now keep you from changing body armor +trapped pets cannot follow you to another level +no corpse when unchanging hero dies while polymorphed into a G_NOCORPSE monster +A-removing armour under cursed stuff no longer fails silently +grease protects gloves from contact poison on books +items picked up from an abandoned shop sometimes wouldn't merge with other + compatible items in inventory ("no charge" bit wasn't being cleared) +prevent cut-off death message by increasing DTHSZ +check to not control teleports when unconscious should now work properly +if armor the hero is donning is stolen or seduced off, attributes + can be left permanently mis-adjusted +ensure a message is printed in all non-obvious cases where a monster flees +a fleeing monster that is holding you always results in a "get released" message +ensure a monster flees for at least one "turn" +explosion type can now be one of dark, noxious, muddy, wet, magical, + fiery, or frosty +flying (jumping or throwing recoil) over some traps (magic portals, fire traps) + will now trigger the trap +displacement does not work through walls +you can't trip and fall or trip over rocks while riding +reduce the chances of a monkey successfully stealing armor you are wearing +monkeys can't steal cursed items that you're unable to remove or attached + iron ball or items too heavy for them to carry +trapped doors are not always detected after returning to a previous level +trap detection sometimes showed non-trap locations to be traps +eucalyptus was never chosen in random tree fruits due to an off-by-one bug +allow knights to pursue and attack thieving monkeys without alignment penalty +gaining levitation while over on sink causes an immediate fall +quest leader should avoid leaving the quest start level voluntarily +blind Medusa cannot gaze +prevent dipping attached iron ball or embedded dragon scales into a potion + of polymorph from confusing the game about what items are in use +should not be able to cut down trees on Ranger quest start level +arrow traps are not currently intended to shoot poisoned arrows +fall off the horse if you mimic a pile of gold while riding +martial attacks will not remove monsters from traps and will cause + monsters to set off traps they land on while reeling/staggering +prevent topten from using alloc after alloc failure +Nazgul and erinyes are nopoly to ensure their numbers are never exceeded +"player-@" randomly selects a race and "player -@" randomly selects + everything that is not specified +prevent spurious "quest portal already gone" when you use an artifact to + return to the quest after being previously expelled +prevent limbless shopkeepers from "leaping" and "grabbing" your backpack + by changing the messages that you get +prevent panic when riding while punished and falling down the stairs +armor class shouldn't wrap from very negative to very positive +searching should only credit you with finding an undetected monster if + you couldn't sense it or spot it already +monsters should not generally lose invisibility when polymorphing +monster must have eyes or breathe to be affected by potion vapors +stop dungeon file open failure from causing vision-related crash +wishing for {statue,figurine,corpse} of long worm tail yields long worm instead +chatting to an arbitrary shopkeeper (not a petrified one) who was created + via statue animation produced strange results +Yeenoghu's confusion attack is not a touch of death +an eating steed should not be able to go up or down stairs, etc. +you don't feel "great" when recovering with a unicorn horn but Slimed; also, + make the same check for potions that make you feel "great" +avoid panic during player-as-demon demon summoning when no demon is available +change "Ouch! You bump into a door" message when riding +prevent voluntary dismount of steed from passing you through walls in + tight spots +prevent throwing boulders, boxes, and chests and medium-to-large + corpses and statues through iron bars +only living eggs which touch cockatrices get turned to stone +since monsters already refuse to zap empty wands, they shouldn't pick them up +after praying, try to give a spellbook for which the player is not restricted +after #dipping your weapon in hand or quiver into a potion of polymorph, + leave it where it was +message from rust trap states "robe" instead of "cloak" when applicable +gas spore explosions were affecting your human hitpoints even if you were + polyd and consequently you did not rehumanize +prevent "You attack empty water" when attacking a spot on land while + underwater +prevent spurious "But you aren't drowning. You touch bottom." message when + removing an amulet of magical breathing as an amphibious creature +fix message given when a monster tries to disarm your multiple welded daggers + with a bullwhip +camera flash no longer stops at invisible monster +monsters inside a stinking cloud should be blinded, just like the hero is +vault guard shouldn't initiate conversation with you when you're hidden +adult wolves are not small but lynxes are small +turn off vision during a save operation to prevent impossible() from + triggering a crash +rolling boulder trap's boulder susceptible to land mines and teleport traps +polymorphing below level 1 should kill player (needed to fix max-HP abuse) +prevent "obj not free" panic when shopkeeper cannot get to a thrown pick-axe +give feedback if Sokoban prevents polymorphed player from passing through walls +eliminate Wounded_legs enlightenment message when riding since it refers to + the steed's legs, not the hero's +adjust the fumbling pick-axe message to reflect that the steed's + legs got damaged, not the hero's +quaffing a noncursed potion of speed no longer heals the steed's wounded legs +prevent mounting of steed when you have Wounded_legs to prevent abuse; + dismount does an unconditional healing of Wounded_legs during the + Wounded_legs context switch +wounded legs on a steed doesn't count as a prayer trouble +wounded legs on a steed doesn't abuse dexterity +make wounded legs gained by falling off a steed consistent (dexterity loss) +land mines while mounted should hurt the steed +self-genocide while sitting on a throne should not refer to scroll of genocide +eating dogfood or fixing a squeaky board conveys experience but didn't + check for gaining a new level +demon bribes are 4x larger than they should be for co-aligned players +specific monster warning no longer reveals the true monster name when you + use the '/' command while hallucinating +start_corpse_timeout() now takes corpse age into consideration rather than + always assuming a fresh corpse, thus fixing potential icebox abuse +player on an immediate diagonal from a monster reading a scroll of earth + should be affected, just like monsters in similar locations +objects that fall from monster's minvent as a result of monster polymorph + are not polymorphed, consistent with items that remain in minvent +quaffing a potion of gain ability while wearing ring of sustain ability + displayed no message and identified the potion +monsters still with WAITFORU strategy should not follow up/downstairs +messages should reflect the fact that the Eyes of the Overworld mask the + effects of blindness +Amulet of life saving should save you from sickness that will kick in this turn +player should stop waiting when a monster uses a polearm from a distance +avoid stone-to-flesh blood pooling message when zapping ice and not stone +when polymorphed into a silent creature, do not "pronounce" scroll formula +ensure hilite turns off immediately when pet stops being tame +hitting with a polearm counts as hitting with a weapon for conduct +traps detected while blind and levitating were not displayed +when a mind flayer uses its mind attack, it should wake the victim +shapechangers restored from disk would no longer change shape +blind, cancelled or nonseen invisible Medusa cannot gaze at other monsters +fix impossible when spinning web on falling rock, rolling boulder and fire traps +rust monsters can only eat items made of rustable material +wands of fire are no longer flammable no matter what material they are +displacing you pet into a trap which kills it affects killer conduct +pets can now be displaced in untended shops +only show lit walls if, like doors, the position next to them is lit too +charge for an unpaid weapon used for engraving +shopkeeper should charge for unpaid balls and used candles in containers +when swallowed you could drop or throw a cockatrice corpse into a + monster's stomach without stoning it despite the guaranteed hit +steed would often not respond to an attack, even if you didn't move that turn +after stepping in a polymorph trap, a monster may pick up the wrong items +breaking an unpaid wand of teleportation wouldn't result in the proper charge +next_shkp() was used inconsistently, potentially triggering an endless loop +chaotic wizards usually get a spellbook when crowned, just like neutral ones +monk quest: fix the two inaccessible chambers on the locate level +rogue quest: fix the four inaccessible chambers on the home level; + link the two inaccessible chambers on the locate level and provide + a means of escaping from them; on the goal level, link most + chambers together, resulting in just four disconnected regions, + and force stairs to be in a different region from the nemesis +angels can fly +under #twoweapon fix it so that only Stormbringer carries out the + blood-thirsty attacks, not both +booby-trapped doors shouldn't make you stagger if you're riding +encumbrance exertion checks should happen each time player moves +mksobj_at: add way to suppress the chance of a new object being an artifact +steed should be the one caught in a bear trap, even if player is polymorphed +use a more appropriate message than "being held" when using < or > while + swallowed or engulfed on stairs +stinking cloud isn't useless and shouldn't be excluded from initial inventory +shopkeeper will not try to buy food you are eating when inventory is full +don't duplicate any gold inside containers when saving bones data +can't tell between acid and holy/unholy water that burns like acid +tame stuck monsters should release you after regaining their senses +engraving Elbereth exercises wisdom, engraving anything else does not +artifact bows get any special attack bonus added to missile to-hit roll +monsters with gaze attacks should not try to blind the hero with potions +players polymorphed into umber hulks should not try to eat boulders in Sokoban +when a monster uses up a partially eaten food item, cleanup was not performed +temple priests shouldn't be created with two robes +give some quest leaders and nemeses equipment appropriate for their class +mis-engraving "X" or "x" shouldn't violate illiterate conduct +Heart of Ahriman now explicitly does double damage +prevent NO_ATTK artifacts from accidentally doing double damage +player polymorphed into monster that loses hp out of water should lose hp too +make sure that all leashed monsters get released when bones data is saved +eating a ring of levitation doesn't confer permanent intrinsic levitation +silver hating monster using a bullwhip shouldn't snatch silver weapons into + its inventory +fracturing one of several boulders at a location should not unblock vision +don't hide stairs, thrones, &c under spider webs when creating levels +rediscovering forgotten object types behaved differently depending upon + whether they had user assigned names at the time of amnesia +taming while engulfed is limited to the engulfer +restore blindness resistance to Archons +if a shk is polymorphed into monster form which has Wizard-style tactics, + don't let him teleport to the stairs if he's inside his shop +when the player digs a hole through a shop's floor, don't let shopkeeper + wander out of that shop while multi-turn digging is in progress +don't protect alternate weapon and quivered objects against being taken + by shk who grabs your pack when you dig a hole through his shop floor +add missing break to POT_WATER case in potionbreath() +keep monster from forgetting its weapon is cursed every other round +multiple shot throwing stops immediately whenever you hurtle backwards +don't panic if being billed for a burning or other timed object +food that makes a monster peaceful should not re-anger it at the same time +abusing a leashed pet could result in a leashed peaceful monster +couldn't unleash steed while mounted +trying and failing to wield an item could leave current weapon flagged as both + "weapon in hand" and "alternate weapon" when `pushweapon' option is set +handle OBJ_CONTAINED case for corpse revival so that trolls can revive + from inside containers +eating one of several merged partly eaten food items should take nutrition + from only one of them +coyote names should not disable printing of "tame" or "peaceful" +Eyes of the Overworld protect from stun effect of Archon's radiance attack +give feedback when putting on or taking off the Eyes of the Overworld causes + blindness state to be toggled +avoid spurious "you can see again" when temporary blindness being overridden + by the Eyes of the Overworld times out +removing blindfold or lenses via 'A(' gives same results as via 'R' +make blindness with just 1 turn remaining be a candicate for repair by + unicorn horn and healing potions/spells +healing potions/spells shouldn't fix being creamed +make pie throwing and venom spitting by the player be consistent with the + effects of those attacks by monsters +offering & tinning corpses on altars should work even while riding +It was possible to faint after eating a fortune cookie and still read + the fortune's text despite being unconscious +when filling a pit containing a vortex, a surviving vortex gets untrapped +teleporting no longer moves the iron ball to under you if that's not necessary; + prevents odd ball movement when crawling out of water +monsters now prefer to wear speed boots over other boots +prevent crash when loading a special level specifying a mimic using m_object +prevent crashes caused by dropping or shipping quivered or secondary weapons +don't trigger spurious encumbrance messages on last turn of a multi-turn meal +prevent food being restored to untouched status if interrupted while eating +troll revival shouldn't increment the troll creation counter +breaking mirrors and your eggs should be bad luck when kicking chests as well + as throwing +vampires should be G_NOCORPSE so you can't wish for them +glass objects should break when thrown, just like when kicked in chests +rocks/gems shouldn't be hard to throw by hand because they are ammo +avoid all cases where splitting an object would result in two objects being + quivered, wielded or otherwise having its owornflag set +allow 'a' prompt when dropping many objects in shop for credit (Wingnut) +monsters who get polymorphed while wearing dragon armor turn into dragons +shape changers can't be killed by system shock when hit by polymorph +Chromatic Dragon has silver scales too (she reflects) +being killed when wishing for an artifact should retain that item in bones data +the drain life spell should not wipe out engravings (especially not using a + function that requires you to be able to reach the floor) +monsters who can cast undirected spells don't need to be in combat with you + to do so +messages consistent for all monster spells +monsters casting spells at your displaced image now set mspec_used +monsters without ranged spells don't print curse messages for ranged spells +going down to floor using > should set Heart of Ahriman invocation timeout +riding a steed into water kills the steed if it cannot swim, with penalties +gaze attacks now stop occupation +proper death message when killed by "plain" high priest +don't conceal the identity of Moloch's high priest +blessed full healing can't recover levels lost when polymorphing into new man +blessed full healing can recover at most half of other lost levels +golden glow when praying will recover lost level if blessed full healing could +gaining a level while polymorphed increases current monst hit points as well + as latent human (or whatever) hit points +pets should not try to go after food that they can't reach +monsters shouldn't use wands of digging in Sokoban +objects dropped in or travelling across lava pools can take damage +monsters that enter lava can take damage +eating an unpaid tin should calculate cost before not after eating +spells shouldn't do negative damage +when reading spellbooks, don't "continue studying" wrong book if original one + gets destroyed after previous reading attempt has been interrupted +correctly handle polymorphed quest leader +swallowing zombies/mummies whole makes you sick, like when eating them normally +impose additional teleport restrictions on the no-teleport Plane of Air +landmines set off by pushed boulders have same effects as stepping on them +secret corridor detected out of vision range is still displayed (prevents bug + where wand of secret door detection found nothing but still identified) +getobj can now see user-specified count when using inventory to make selection +scalpel is stainless steel (i.e. METAL) not regular steel (IRON) +eggs, potions & other breakables may break when they fall down stairs +hurtling via grappling hook does not apply effects of destination location +consider vortexes to be nonliving +dragons have scales, not fur +if player teleports a monster while swallowed on a noteleport level, the + player should not teleport along with the monster +prefixes that can appear in any order when wishing should include +/- and empty +don't allow untrapping of adjacent traps in locations you can't move to +summoning should summon any alignment if summoner's base alignment is A_NONE +when dipping unicorn horn in potion, the potion might change bless status, so + set bknown to FALSE +grammar fixes such as "Eyes of the Overworld resists" and others +score bonus was missing from scrolls of identify and fire +make wands of speed or slow monster known if their effect + on monsters is observed; likewise for speed boots +gold detection "materially poor" message inappropriate if you have hidden_gold() +cannot reflect back an invisible umber hulk or medusa's attack +monsters with M3_WANTSBOOK often couldn't move in the Wizard-level +Vlad should want the Candelabrum +if you float_down on a trap in which you're already trapped, don't retrap +applying whip toward hidden mimic displays mimic name before "Wait!" message +stealing a container didn't multiply cost of stolen contained objects by quan +halve air elemental damage to compensate for side effect of speed system +strengthen Death; weaken Famine, Pestilence, and Demogorgon +pet purple worms get nutrition from engulfing attack +throwing an artifact upwards will trigger artifact hit effects when it falls +being hit by Fire Brand stops the turning-into-slime process +monsters hitting other monsters can split puddings with weapons +be consistent with checking for iron weapons when splitting puddings +prevent corpses of undead creatures just killed by undead turning from being + instantly revived by the same undead turning attack +allow fake player monsters to handle artifacts that don't match alignment/role +chaotic monsters can use Stormbringer; lawful monsters can use Excalibur +No "corridor disappears" message if Vault guard dies off-level +slip while mounting and levitating at will should not cause damage +if you see a monster jump into a trap in a secret corridor, it's not secret +fixed a few places where unblock_point wasn't called but should have been +cloned monsters should have the same name and tameness as the original +you should stop eating (etc.) if a monster attacks you and misses +half physical damage should apply to gas spores +iron bars should affect wall corner wallification +potion of polymorph shouldn't be identified if object being dipped into + it ends up as the same type of object after polymorphing +don't slap against the floor while riding and eating bad food +got rid of "nori" (since it doesn't really translate "kelp frond" accurately) +engraving in fog-covered location on in the Wizard quest said you + engraved in air, not dust +dipping non-weapons into burning potions of oil had no effect +dipping arrows into burning potions resulted in rust damage + + +Platform- and/or Interface-Specific Fixes +----------------------------------------- +amiga: random crashes when opening menu window in fontmode eliminated +amiga: proper action taken (cancel) when closing the menu window + with closegadget or escape +amiga: allow #/altmeta combination on foreign keymaps +amiga: prevent plname[] overflow from askname() +amiga: prevent writing outside basewindow (bottom) +amiga: tilemode tombstone corrected on cybergfx screen +amiga: don't clutter levels/ with foo.0 when quitting at playerselection +micro: prevent a guaranteed impossible() if we ever have more than (COLNO - 1) + levels in the game +micro: fix out of bounds memory modification for file opens via PATH +msdos: placeholder tiles accepted by the thin tile builder +tiles: use pixel-accurate grid bug tile for grid bugs +tty: correctly dismiss 1-line menus +tty: clear screen before version incompatibility message so it doesn't just + print the message overwriting previous screen text +tty: pet was not always hilited +tty: don't crash if the news file is present but empty +unix/tty: give user a chance to see any error produced by (de)compression +win32/tty: menus can take advantage of consoles larger than 80x25 +win32/tty: add support for inverse attribute +Gnome: workaround for GTK+ attempts to disallow setgid executables +Qt: honor user preferences in startup dialog +X11: map not displayed in color when using X11 windowtype w/o tiles +X11: viewport scrolling could scroll the the wrong place with resized window +X11: allow extra space added to map widget to be removed if widget shrinks +X11: general solution to the problem that the meaning of font height varies + among different implementations of X11 +X11: make "slow" mode the default since it seems to be very prevalent + + +General New Features +-------------------- +added travel command via '_' or mouse click +config file processing detects multiple use of the same OPTION and + prints a warning when it does +make the player selection prompt more explicit in the information + that it is going to request +remove curse now operates on cursed leashes that are in active use +give feedback when shooting/throwing more than one missile at a time +monsters can now deliberately eat dead lizards to cure confusion +general warning now allows you to attack unseen monsters, as long as you can + see the warning glyph on the screen +wand of fire & fireballs now burn webs +wand of locking / wizard lock zapped down will close and remove trap doors +exploding monsters wake nearby monsters +various mindless, sphere monsters no longer need to breath +sleeping gas no longer affects nonbreathing monsters +vault guard doesn't notice you if you're mimicking gold +good chance of untrapping monsters and pets caught in webs if you are + polymorphed into a spider, and extremely small chance even if not +stamina affects ability to throw heavy things +objects merge in containers +wishing for "nothing" yields no object and preserves wishless conduct +genociding "none" destroys no monsters and preserves genocideless conduct +coyote id naming shows only the true latin name if coyote is cancelled +xorns can "speak" and can smell valuable metal +if you find a trap but there is too much clutter to see it, have the + game display it temporarily until a keypress +rename the Wizard of Balance to Neferet the Green +double the number of messages that apprentices/guards utter, with 5 for + before the quest, and 5 after +wizard mode ^G command can create monster by class, not just by name +wizard mode ^G command takes a count +kicking a sleeping/paralyzed steed now causes special effects +allow overriding of the default boulder symbol via BOULDER option +blessed scroll of detect food provides you with a one time ability to + recognize food that may be harmful to you +wizard mode WIZKIT config file option added to ease adding items to + starting inventory for a debug session +helping a sleeping/frozen monster from a trap might wake/unfreeze monster +if the hero comes upon an obviously trapped monster the trap is considered seen +thrown weapons that hit are now subject to passive damage +locomotion-specific use of words, rather than just using "stagger" +if you come upon a physically trapped, visible monster, you see the trap + too, without searching for it +allow looking and pickup inside monster's stomach or interior when swallowed +add body_part(STOMACH) +pets like tame nymphs, et al, now only steal non-cursed items +monks usually get a spellbook rather than a weapon when crowned +blessed gold detection now detects anything made of gold, not just + coins, including candelabrum and gold rings +new T-shirt messages from Scott Bigham +option to get rid of resistance 'sparkle' (shieldeffect) (Scott Bigham) +option for autodig (Malcolm Ryan) +glowing Sunsword (inspired by Slashem) +msg_window option for ^P in TTY mode (Jay Tilton) +ninjas should get multishot bonus with yumi and ya (Dylan O'Donnell) +put prisoners in the Dark One's dungeon (Dylan O'Donnell) +touchstones; Archeologists start with one +add leather cloak so soldiers don't have elven cloaks +add Tom Friedetzky's BUC-patch with some alterations to the original +add wizard #poly and #levelchange (originally levelgain; Dylan O'Donnell), +add Jason Short's additional lenses use patch +add new Gnomish Mines levels from Kelly Bailey's patch +add Ken Arnold's patch to show unpaid item prices in inventory +jousting by players wielding a lance while riding +Knights start with lance rather than spear +can start game without a pet via pettype:none (Dylan O'Donnell) +allow disclose options to be more finally tuned, including being able + to specify the default response for being prompted +debug mode SPLEVTYPE environment variable to choose specific levels from + when there are random selections +artifacts have individual prices +new window-port preference options added, and some existing options + moved into the window-port preferences section +made each of the end disclosure options customizable to "prompt;default no", + "prompt;default yes", "show it without prompt", and + "don't show it and don't prompt" +add female role level names "Medica ossium", "Magistra", "Chevaliere", "Dame" +more feedback about skill advancement from #enhance command +USER_SOUNDS compilation option to enable use of SOUND and SOUNDDIR variables + in the config file for user-specified sound clips for + user-specified, regex-based message patterns +resistance does not protect inventory from artifacts (cold vs Frost Brand,&c) +phrase the prompts for P and R commands using "put on" and "remove" as the + actions rather than repeating W and T commands' "wear" and "take off" +dipping candles, et al, into burning potions lights them + + +Platform- and/or Interface-Specific New Features +------------------------------------------------ +amiga: screenmode requester +amiga: 16 color font mode +mac: command-key shortcuts in the player selection dialog +vms: default compiler configuration in sys/vms/Makefile.* switched to DEC C +win32: new graphical port contribution by Alex Kompel + diff --git a/doc/nethack.6 b/doc/nethack.6 index 923be69..5d248ee 100644 --- a/doc/nethack.6 +++ b/doc/nethack.6 @@ -1,8 +1,10 @@ -.TH NETHACK 6 "17 November 1999" +.TH NETHACK 6 "12 March 2002" .UC 4 .SH NAME nethack \- Exploring The Mazes of Menace .SH SYNOPSIS +.na +.hy 0 .B nethack [ .B \-d @@ -32,7 +34,7 @@ nethack \- Exploring The Mazes of Menace [ .B \-ibm ] -.br +.PP .B nethack [ .B \-d @@ -53,6 +55,8 @@ nethack \- Exploring The Mazes of Menace [ .I playernames ] +.ad +.hy 14 .SH DESCRIPTION .PP .I NetHack @@ -105,8 +109,8 @@ graphics characters), options may also be included in a configuration file. The default is located in your home directory and named .nethackrc on Unix systems. On other systems, the default may be -different, usually NetHack.cnf. On DOS the name is defaults.nh, while -on the Macintosh or BeOS, it is NetHack Defaults. +different, usually NetHack.cnf. On DOS or Windows, the name is +defaults.nh, while on the Macintosh or BeOS, it is NetHack Defaults. The configuration file's location may be specified by setting NETHACKOPTIONS to a string consisting of an @ character followed by the filename. .PP @@ -123,7 +127,20 @@ Conversely, you must use the appropriate player name to restore a saved game. .PP A .I playername -suffix or a separate option, +suffix can be used to specify the profession, race, alignment and/or gender +of the character. The full syntax of the playername that includes a +suffix is "name-ppp-rrr-aaa-ggg". "ppp" are at least the first three letters +of the profession (this can also be specified using a separate +.B \-p +.I profession +option). "rrr" are at least the first three letters of the character's +race (this can also be specified using a separate +.B \-r +.I race +option). "aaa" are at last the first three letters of the character's +alignment, and "ggg" are at least the first three letters of the +character's gender. Any of the parts of the suffix may be left out. +.PP .B \-p .I profession can be used to determine the character role. You can specify either the @@ -140,9 +157,9 @@ Likewise, .I race can be used to explicitly request that a race be chosen. .PP +Leaving out any of these characteristics will result in you being prompted +during the game startup for the information. .PP -Leaving out either of these will result in you being prompted during -the game startup for the information. .PP The .B \-s diff --git a/doc/nethack.txt b/doc/nethack.txt index a8e2686..7d7b0ff 100644 --- a/doc/nethack.txt +++ b/doc/nethack.txt @@ -1,264 +1,207 @@ - - - -NETHACK(6) 1999 NETHACK(6) +NETHACK(6) NETHACK(6) NAME - nethack - Exploring The Mazes of Menace + nethack - Exploring The Mazes of Menace SYNOPSIS - nethack [ -d directory ] [ -n ] [ -p profession (role) ] [ - -r race ] [ -[DX] ] [ -u playername ] [ -dec ] [ -ibm ] - nethack [ -d directory ] -s [ -v ] [ -p profession (role) ] - [ -r race ] [ playernames ] - -DESCRIPTION - NetHack is a display oriented Dungeons & Dragons(tm) - like - game. The standard tty display and command structure resem- - ble rogue. - - Other, more graphical display options exist if you are using - either a PC, or an X11 interface. - - To get started you really only need to know two commands. - The command ? will give you a list of the available commands - (as well as other information) and the command / will iden- - tify the things you see on the screen. - - To win the game (as opposed to merely playing to beat other - people's high scores) you must locate the Amulet of Yendor - which is somewhere below the 20th level of the dungeon and - get it out. Nobody has achieved this yet; anybody who does - will probably go down in history as a hero among heros. - - When the game ends, whether by your dying, quitting, or - escaping from the caves, NetHack will give you (a fragment - of) the list of top scorers. The scoring is based on many - aspects of your behavior, but a rough estimate is obtained - by taking the amount of gold you've found in the cave plus - four times your (real) experience. Precious stones may be - worth a lot of gold when brought to the exit. There is a - 10% penalty for getting yourself killed. - - The environment variable NETHACKOPTIONS can be used to ini- - tialize many run-time options. The ? command provides a - description of these options and syntax. (The -dec and -ibm - command line options are equivalent to the decgraphics and - ibmgraphics run-time options described there, and are pro- - vided purely for convenience on systems supporting multiple - types of terminals.) - - Because the option list can be very long (particularly when - specifying graphics characters), options may also be - included in a configuration file. The default is located in - your home directory and named .nethackrc on Unix systems. - On other systems, the default may be different, usually - NetHack.cnf. On DOS the name is defaults.nh, while on the - Macintosh or BeOS, it is NetHack Defaults. The - - - -November Last change: 17 1 - - - - - - -NETHACK(6) 1999 NETHACK(6) - - + nethack [ -d directory ] [ -n ] [ -p profession (role) ] [ + -r race ] [ -[DX] ] [ -u playername ] [ -dec ] [ -ibm ] - configuration file's location may be specified by setting - NETHACKOPTIONS to a string consisting of an @ character fol- - lowed by the filename. + nethack [ -d directory ] -s [ -v ] [ -p profession (role) + ] [ -r race ] [ playernames ] - The -u playername option supplies the answer to the question - "Who are you?". It overrides any name from the options or - configuration file, USER, LOGNAME, or getlogin(), which will - otherwise be tried in order. If none of these provides a - useful name, the player will be asked for one. Player names - (in conjunction with uids) are used to identify save files, - so you can have several saved games under different names. - Conversely, you must use the appropriate player name to - restore a saved game. - - A playername suffix or a separate option, -p profession can - be used to determine the character role. You can specify - either the male or female name for the character role, or - the first three characters of the role as an abbreviation. - -p @ has been retained to explicitly request that a random - role be chosen. It may need to be quoted with a backslash - (\@) if @ is the "kill" character (see "stty") for the ter- - minal, in order to prevent the current input line from being - cleared. - - Likewise, -r race can be used to explicitly request that a - race be chosen. - - Leaving out either of these will result in you being - prompted during the game startup for the information. - - The -s option alone will print out the list of your scores - on the current version. An immediately following -v reports - on all versions present in the score file. The -s may also - be followed by arguments -p and -r to print the scores of - particular roles and races only. It may also be followed by - one or more player names to print the scores of the players - mentioned, by 'all' to print out all scores, or by a number - to print that many top scores. - - The -n option suppresses printing of any news from the game - administrator. - - The -D or -X option will start the game in a special non- - scoring discovery mode. -D will, if the player is the game - administrator, start in debugging (wizard) mode instead. - - The -d option, which must be the first argument if it - appears, supplies a directory which is to serve as the play- - ground. It overrides the value from NETHACKDIR, HACKDIR, or - the directory specified by the game administrator during - compilation (usually /usr/games/lib/nethackdir). This - option is usually only useful to the game administrator. - - - -November Last change: 17 2 - - - - - - -NETHACK(6) 1999 NETHACK(6) - - - - The playground must contain several auxiliary files such as - help files, the list of top scorers, and a subdirectory save - where games are saved. +DESCRIPTION + NetHack is a display oriented Dungeons & Dragons(tm) - + like game. The standard tty display and command structure + resemble rogue. + + Other, more graphical display options exist if you are + using either a PC, or an X11 interface. + + To get started you really only need to know two commands. + The command ? will give you a list of the available com- + mands (as well as other information) and the command / + will identify the things you see on the screen. + + To win the game (as opposed to merely playing to beat + other people's high scores) you must locate the Amulet of + Yendor which is somewhere below the 20th level of the dun- + geon and get it out. Nobody has achieved this yet; any- + body who does will probably go down in history as a hero + among heros. + + When the game ends, whether by your dying, quitting, or + escaping from the caves, NetHack will give you (a fragment + of) the list of top scorers. The scoring is based on many + aspects of your behavior, but a rough estimate is obtained + by taking the amount of gold you've found in the cave plus + four times your (real) experience. Precious stones may be + worth a lot of gold when brought to the exit. There is a + 10% penalty for getting yourself killed. + + The environment variable NETHACKOPTIONS can be used to + initialize many run-time options. The ? command provides + a description of these options and syntax. (The -dec and + -ibm command line options are equivalent to the decgraph- + ics and ibmgraphics run-time options described there, and + are provided purely for convenience on systems supporting + multiple types of terminals.) + + Because the option list can be very long (particularly + when specifying graphics characters), options may also be + included in a configuration file. The default is located + in your home directory and named .nethackrc on Unix sys- + tems. On other systems, the default may be different, + usually NetHack.cnf. On DOS or Windows, the name is + defaults.nh, while on the Macintosh or BeOS, it is NetHack + Defaults. The configuration file's location may be speci- + fied by setting NETHACKOPTIONS to a string consisting of + an @ character followed by the filename. + + The -u playername option supplies the answer to the ques- + tion "Who are you?". It overrides any name from the + options or configuration file, USER, LOGNAME, or getlo- + gin(), which will otherwise be tried in order. If none of + these provides a useful name, the player will be asked for + one. Player names (in conjunction with uids) are used to + identify save files, so you can have several saved games + under different names. Conversely, you must use the + appropriate player name to restore a saved game. + + A playername suffix can be used to specify the profession, + race, alignment and/or gender of the character. The full + syntax of the playername that includes a suffix is "name- + ppp-rrr-aaa-ggg". "ppp" are at least the first three let- + ters of the profession (this can also be specified using a + separate -p profession option). "rrr" are at least the + first three letters of the character's race (this can also + be specified using a separate -r race option). "aaa" are + at last the first three letters of the character's align- + ment, and "ggg" are at least the first three letters of + the character's gender. Any of the parts of the suffix + may be left out. + + -p profession can be used to determine the character role. + You can specify either the male or female name for the + character role, or the first three characters of the role + as an abbreviation. -p @ has been retained to explicitly + request that a random role be chosen. It may need to be + quoted with a backslash (\@) if @ is the "kill" character + (see "stty") for the terminal, in order to prevent the + current input line from being cleared. + + Likewise, -r race can be used to explicitly request that a + race be chosen. + + Leaving out any of these characteristics will result in + you being prompted during the game startup for the infor- + mation. + + + The -s option alone will print out the list of your scores + on the current version. An immediately following -v + reports on all versions present in the score file. The -s + may also be followed by arguments -p and -r to print the + scores of particular roles and races only. It may also be + followed by one or more player names to print the scores + of the players mentioned, by 'all' to print out all + scores, or by a number to print that many top scores. + + The -n option suppresses printing of any news from the + game administrator. + + The -D or -X option will start the game in a special non- + scoring discovery mode. -D will, if the player is the + game administrator, start in debugging (wizard) mode + instead. + + The -d option, which must be the first argument if it + appears, supplies a directory which is to serve as the + playground. It overrides the value from NETHACKDIR, HACK- + DIR, or the directory specified by the game administrator + during compilation (usually /usr/games/lib/nethackdir). + This option is usually only useful to the game administra- + tor. The playground must contain several auxiliary files + such as help files, the list of top scorers, and a subdi- + rectory save where games are saved. AUTHORS - Jay Fenlason (+ Kenny Woodland, Mike Thome and Jon Payne) - wrote the original hack, very much like rogue (but full of - bugs). + Jay Fenlason (+ Kenny Woodland, Mike Thome and Jon Payne) + wrote the original hack, very much like rogue (but full of + bugs). - Andries Brouwer continuously deformed their sources into an - entirely different game. + Andries Brouwer continuously deformed their sources into + an entirely different game. - Mike Stephenson has continued the perversion of sources, - adding various warped character classes and sadistic traps - with the help of many strange people who reside in that - place between the worlds, the Usenet Zone. A number of - these miscreants are immortalized in the historical roll of - dishonor and various other places. + Mike Stephenson has continued the perversion of sources, + adding various warped character classes and sadistic traps + with the help of many strange people who reside in that + place between the worlds, the Usenet Zone. A number of + these miscreants are immortalized in the historical roll + of dishonor and various other places. - The resulting mess is now called NetHack, to denote its - development by the Usenet. Andries Brouwer has made this - request for the distinction, as he may eventually release a - new version of his own. + The resulting mess is now called NetHack, to denote its + development by the Usenet. Andries Brouwer has made this + request for the distinction, as he may eventually release + a new version of his own. FILES - All files are in the playground, normally - /usr/games/lib/nethackdir. If DLB was defined during the - compile, the data files and special levels will be inside a - larger file, normally nhdat, instead of being separate - files. - nethack The program itself. - data, oracles, rumors Data files used by NetHack. - options, quest.dat More data files. - help, hh Help data files. - cmdhelp, opthelp, wizhelp More help data files. - *.lev Predefined special levels. - dungeon Control file for special levels. - history A short history of NetHack. - license Rules governing redistribution. - record The list of top scorers. - logfile An extended list of games - played. - xlock.nnn Description of a dungeon level. - perm Lock file for xlock.dd. - bonesDD.nn Descriptions of the ghost and - belongings of a deceased - adventurer. - save A subdirectory containing the - saved games. + All files are in the playground, normally + /usr/games/lib/nethackdir. If DLB was defined during the + compile, the data files and special levels will be inside + a larger file, normally nhdat, instead of being separate + files. + nethack The program itself. + data, oracles, rumors Data files used by NetHack. + options, quest.dat More data files. + help, hh Help data files. + cmdhelp, opthelp, wizhelp More help data files. + *.lev Predefined special levels. + dungeon Control file for special lev- + els. + history A short history of NetHack. + license Rules governing redistribu- + tion. + record The list of top scorers. + logfile An extended list of games + played. + xlock.nnn Description of a dungeon + level. + perm Lock file for xlock.dd. + bonesDD.nn Descriptions of the ghost and + belongings of a deceased + adventurer. + save A subdirectory containing the + saved games. ENVIRONMENT - USER or LOGNAME Your login name. - - - -November Last change: 17 3 - - - - - - -NETHACK(6) 1999 NETHACK(6) - - - - HOME Your home directory. - SHELL Your shell. - TERM The type of your terminal. - HACKPAGER or PAGER Replacement for default pager. - MAIL Mailbox file. - MAILREADER Replacement for default reader - (probably /bin/mail or /usr/ucb/mail). - NETHACKDIR Playground. - NETHACKOPTIONS String predefining several NetHack - options. - - In addition, SHOPTYPE is used in debugging (wizard) mode. + USER or LOGNAME Your login name. + HOME Your home directory. + SHELL Your shell. + TERM The type of your terminal. + HACKPAGER or PAGER Replacement for default pager. + MAIL Mailbox file. + MAILREADER Replacement for default reader + (probably /bin/mail or + /usr/ucb/mail). + NETHACKDIR Playground. + NETHACKOPTIONS String predefining several NetHack + options. + + In addition, SHOPTYPE is used in debugging (wizard) mode. SEE ALSO - dgn_comp(6), lev_comp(6), recover(6) + dgn_comp(6), lev_comp(6), recover(6) BUGS - Probably infinite. - - - - Dungeons & Dragons is a Trademark of TSR Inc. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Probably infinite. -November Last change: 17 4 + Dungeons & Dragons is a Trademark of TSR Inc. + 12 March 2002 NETHACK(6) diff --git a/doc/window.doc b/doc/window.doc index 67a6f31..f2aa220 100644 --- a/doc/window.doc +++ b/doc/window.doc @@ -5,16 +5,18 @@ NetHack. The support is through a standard interface, separating the main NetHack code from window-system specific code. The implementation supports multiple window systems in the same binary. Even if you only wish to support one window-port on your port, you will need to follow -the instructions in Section VII to get a compilable binary. +the instructions in Section IX to get a compilable binary. Contents: - I. Window Types and Terminology - II. Interface Specification - III. Global variables - IV. New or respecified common, high level routines - V. Game startup - VI. Conventions - VII. Implementation and Multi-window support + I. Window Types and Terminology + II. Interface Specification + III. Global variables + IV. WINCAP preferences support + V. New or respecified common, high level routines + VI. Helper routines + VII. Game startup + VIII. Conventions + IX. Implementation and Multi-window support I. Window Types and Terminology @@ -163,6 +165,9 @@ getlin(const char *ques, char *input) -- getlin() must call flush_screen(1) before doing anything. -- This uses the top line in the tty window-port, other ports might use a popup. + -- getlin() can assume the input buffer is at least BUFSZ + bytes in size and must truncate inputs to fit, including + the nul character. int get_ext_cmd(void) -- Get an extended command in a window-port specific way. An index into extcmdlist[] is returned on a successful @@ -251,7 +256,9 @@ add_menu(windid window, int glyph, const anything identifier, window port cannot or does not want to display it, this is OK. If there is no glyph applicable, then this value will be NO_GLYPH. - -- All accelerators should be in the range [A-Za-z]. + -- All accelerators should be in the range [A-Za-z], + but there are a few exceptions such as the tty player + selection code which uses '*'. -- It is expected that callers do not mix accelerator choices. Either all selectable items have an accelerator or let the window system pick them. Don't do both. @@ -347,6 +354,15 @@ outrip(winid, int) -- The tombstone code. If you want the traditional code use genl_outrip for the value and check the #if in rip.c. +preference_update(preference) + -- The player has just changed one of the wincap preference + settings, and the NetHack core is notifying your window + port of that change. If your window-port is capable of + dynamically adjusting to the change then it should do so. + Your window-port will only be notified of a particular + change if it indicated that it wants to be by setting the + corresponding bit in the wincap mask. + III. Global variables The following global variables are defined in decl.c and must be used by @@ -366,7 +382,209 @@ window-port should also declare this variable in one of your sys/*.c files. short ospeed; Set and declared in sys/unix/unixtty.c (don't know about other sys files). -IV. New or respecified common, high level routines +The following global variable is defined in options.c. It equates a +list of wincap option names with their associated bit-mask [see +section IV WINCAP preferences support]. The array is zero-terminated. + +struct wc_Opt wc_options[]; + One entry for each available WINCAP option. + Each entry has a wc_name field and a wc_bit + field. + +IV. WINCAP preferences support + +Starting with NetHack 3.4.0, the window interface was enhanced to provide +a common way of setting window port user preferences from the config file, +and from the command line for some settings. + +The wincap preference settings all have their underlying values stored +in iflags fields. The names of the wincap related fields are all pre- +fixed with wc_ to make it easy to identify them. Your window port can +access the fields directly. + +Your window port identifies what options it will react to and support +by setting bits in the window_procs wincap mask. See section IX for +details of where the wincap mask resides. + +Two things control whether any preference setting appears in the +'O' command options menu during the game: + 1. The option must be marked as being supported by having its + bit set in the window_procs wincap mask. + 2. The option must have its optflag field set to SET_IN_GAME in order + to be able to set the option, or marked DISP_IN_GAME if you just + want to reveal what the option is set to. +Both conditions must be true to be able to see or set the option from +within NetHack. + +The default values for the optflag field for all the options are +hard-coded into the option in options.c. The default value for +the options can be altered by calling + set_wc_option_mod_status(optmask, status) +specifying the option modification status to one of SET_IN_FILE, +DISP_IN_GAME, or SET_IN_GAME. + +The setting of any wincap option is handled by the NetHack core option +processing code. You do not have to provide a parser in your window +port, nor should you set the values for the iflags.wc_* fields +directly within the port code. The port code should honor whatever +values were put there by the core when processing options, either +in the config file, or by the 'O' command. + +You may be wondering what values your window port will find in the +iflags.wc_* fields for options that the user has not specified +in his/her config file. Put another way, how does you port code +tell if an option has not been set? The next paragraph explains that. + +If the core does not set an option, it will still be initialized +to its default value. Those default values for the +iflags.wc_* fields are: + + o All boolean fields are initialized to the starting + value specified for that option in the boolopt array in + options.c. The window-port should respect that setting + unless it has a very good reason for not doing so. + o All int fields are initialized to zero. Zero is not a valid + setting for any of the int options, so if your port code + encounters a zero there, it can assume that the preference + option was not specified. In that case, the window-port code + should use a default setting that the port is comfortable with. + It should write the default setting back into the iflags.wc_* + field. That is the only time that your window-port could should + update those fields. + o All "char *" fields will be null pointers. Be sure to check for + that in your window-port code before using such a pointer, or + you'll end up triggering a nasty fault. + +Here are the wincap preference settings that your port can choose +to support: + + +--------------------+--------------------+--------------------+--------+ + | | | iflags field | data | + | player option | bit in wincap mask | for value | type | + |--------------------+--------------------+--------------------+--------+ + | align_message | WC_ALIGN_MESSAGE | wc_align_message |int | + | align_status | WC_ALIGN_STATUS | wc_align_status |int | + | ascii_map | WC_ASCII_MAP | wc_ascii_map |boolean | + | color | WC_COLOR | wc_color |boolean | + | eight_bit_tty | WC_EIGHT_BIT_IN | wc_eight_bit_input |boolean | + | font_map | WC_FONT_MAP | wc_font_map |char * | + | font_menu | WC_FONT_MENU | wc_font_menu |char * | + | font_message | WC_FONT_MESSAGE | wc_font_message |char * | + | font_status | WC_FONT_STATUS | wc_font_status |char * | + | font_text | WC_FONT_TEXT | wc_font_text |char * | + | font_size_map | WC_FONTSIZ_MAP | wc_fontsiz_map |int | + | font_size_menu | WC_FONTSIZ_MENU | wc_fontsiz_menu |int | + | font_size_message | WC_FONTSIZ_MESSAGE | wc_fontsiz_message |int | + | font_size_status | WC_FONTSIZ_STATUS | wc_fontsiz_status |int | + | font_size_text | WC_FONTSIZ_TEXT | wc_fontsiz_text |int | + | hilite_pet | WC_HILITE_PET | wc_hilite_pet |boolean | + | large_font | WC_LARGE_FONT | wc_large_font |boolean | + | map_mode | WC_MAP_MODE | wc_map_mode |int | + | player_selection | WC_PLAYER_SELECTION| wc_player_selection|int | + | popup_dialog | WC_POPUP_DIALOG | wc_popup_dialog |boolean | + | preload_tiles | WC_PRELOAD_TILES | wc_preload_tiles |boolean | + | scroll_margin | WC_SCROLL_MARGIN | wc_scroll_margin |int | + | splash_screen | WC_SPLASH_SCREEN | wc_splash_screen |boolean | + | tiled_map | WC_TILED_MAP | wc_tiled_map |boolean | + | tile_width | WC_TILE_WIDTH | wc_tile_width |int | + | tile_height | WC_TILE_HEIGHT | wc_tile_height |int | + | tile_file | WC_TILE_FILE | wc_tile_file |char * | + | use_inverse | WC_INVERSE | wc_inverse |boolean | + | vary_msgcount | WC_VARY_MSGCOUNT | wc_vary_msgcount |int | + | windowcolors | WC_WINDOWCOLORS | wc_foregrnd_menu |char * | + | | | wc_backgrnd_menu |char * | + | | | wc_foregrnd_message|char * | + | | | wc_backgrnd_message|char * | + | | | wc_foregrnd_status |char * | + | | | wc_backgrnd_status |char * | + | | | wc_foregrnd_text |char * | + | | | wc_backgrnd_text |char * | + +--------------------+--------------------+--------------------+--------+ + +align_message -- where to place message window (top, bottom, left, right) +align_status -- where to place status window (top, bottom, left, right). +ascii_map -- port should display an ascii map if it can. +color -- port should display color if it can. +eight_bit_tty -- port should allow eight bit input. +font_map -- port should use a font by this name for map window. +font_menu -- port should use a font by this name for menu windows. +font_message -- port should use a font by this name for message window. +font_size_map -- port should use this size font for the map window. +font_size_menu -- port should use this size font for menu windows. +font_size_message + -- port should use this size font for the message window. +font_size_status-- port should use this size font for the status window. +font_size_text -- port should use this size font for text windows. +font_status -- port should use a font by this name for status window. +font_text -- port should use a font by this name for text windows. +hilite_pet -- port should mark pets in some special way on the map. +large_font -- port should use a large font. +map_mode -- port should display the map in the manner specified. +player_selection + -- dialog or prompts for choosing character. +popup_dialog -- port should pop up dialog boxes for input. +preload_tiles -- port should preload tiles into memory. +scroll_margin -- port should scroll the display when the hero or cursor + is this number of cells away from the edge of the window. +splash_screen -- port should/should not display an opening splashscreen. +tiled_map -- port should display a tiled map if it can. +tile_width -- port should display tiles with this width or round to closest + if it can. +tile_height -- port should display tiles with this height or round to closest + if it can. +tile_file -- open this alternative tile file. The file name is likely to be + window-port or platform specific. +use_inverse -- port should display inverse when NetHack asks for it. +vary_msgcount -- port should display this number of messages at a time in + the message window. +windowcolors + -- port should use these colors for window foreground/background + colors. Syntax: + menu fore/back message fore/back status fore/back text fore/back + +Whenever one of these settings is adjusted, the port is notified of a change +to the setting by calling the port's preference_update() routine. The port +is only notified if it has indicated that it supports that option by setting +the option's bit in the port's wincap mask. The port can choose to adjust +for the change to an option that it receives notification about, or ignore it. +The former approach is recommended. If you don't want to deal with a +user-initiated setting change, then the port should call +set_wc_option_mod_status(mask, SET_IN_FILE) to make the option invisible to +the user. + +Functions available for the window port to call: + +set_wc_option_mod_status(optmask, status) + -- Adjust the optflag field for a set of options to + specify whether the port wants the option to appear + in the 'O' command options menu, The second parameter, + "status" can be set to SET_IN_FILE, DISP_IN_GAME, + or SET_IN_GAME (SET_IN_FILE implies that the option + is completely hidden during the game). + +set_option_mod_status(optnam, status) + -- Adjust the optflag field for one of the core options + that is not part of the wincap suite. A port might use + this to override the default initialization setting for + status specified in options.c. Note that you have to + specify the option by name and that you can only set + one option per call unlike set_wc_option_mod_status(). + + +Adding a new wincap option: + +To add a new wincap option, please follow all these steps: + 1. Add the option to the wincap preference settings table above. + 2. Add the description to the paragraph below the chart. + 3. Add the WC_ to the bit list in include/winprocs.h (if there is room). + 4. Add the wc_ field(s) to the iflags structure in flag.h. + 5. Add an appropriate parser to parseoptions() in options.c. + 6. Add code to display current value to get_compopt_value() in options.c. + 7. Document the option in Guidebook.mn and Guidebook.tex. + 8. Add the bit name to the OR'd values in your window port's winprocs struct + wincap mask if your port supports the option. + +V. New or respecified common, high level routines These are not part of the interface, but mentioned here for your information. @@ -388,8 +606,20 @@ pline(str, ...) by Norep() and pline(). If the window system is not active (!iflags.window_inited) pline() uses raw_print(). +VI. Helper Routines + +These are not part of the interface. They may be called by your +window port routines to perform the desired task, instead of duplicating +the necessary code in each window port. + +mapglyph(int glyph, int *ochar, int *ocolor, unsigned *special, int x, int y) + -- Maps glyph at x,y to NetHack ascii character and color. + If it represents something special such as a pet, that + information is returned as set bits in "special." + Usually called from the window port's print_glyph() + routine. -V. Game startup +VII. Game startup The following is the general order in which calls from main() should be made, as they relate to the window system. The actual code may differ, but the @@ -422,7 +652,7 @@ Process_options() is currently still unique to each port. There may be need in the future to make it possible to replace this on a per window-port basis. -VI. Conventions +VIII. Conventions init_nhwindows() is expected to display a gee-whiz banner window, including the Copyright message. It is recommended that the COPYRIGHT_BANNER_A, @@ -447,7 +677,7 @@ in win/X11. The files in these directories contain _only_ window port code, and may be replaced completely by other window ports. -VII. Implementation and Multi-window support +IX. Implementation and Multi-window support NetHack 3.2 and higher support multiple window systems in the same binary. When writing a new window-port, you need to follow the following guidelines: @@ -478,7 +708,9 @@ When writing a new window-port, you need to follow the following guidelines: 3) Declare a structure, "struct window_procs prefix_procs", (with your prefix instead of "prefix") and fill in names of all of your interface functions. The first entry in this structure is the name - of your window-port, which should be the prefix. The other entries + of your window-port, which should be the prefix. The second entry + is the wincap mask that identifies what window port preference + settings your port will react to and support. The other entries are the function addresses. Assuming that you followed the convention in (2), you can safely copy @@ -525,7 +757,7 @@ When writing a new window-port, you need to follow the following guidelines: 9) Look at your port's portmain.c (the file containing main()) and make sure that all of the calls match the the requirements laid out in - Section V. + Section VII. Now, proceed with compilation and installation as usual. Don't forget to edit Makefile.src (or its equivalent) and config.h to set the diff --git a/include/align.h b/include/align.h index 199c5cc..1925f14 100644 --- a/include/align.h +++ b/include/align.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)align.h 3.3 91/12/29 */ +/* SCCS Id: @(#)align.h 3.4 1991/12/29 */ /* Copyright (c) Mike Stephenson, Izchak Miller 1991. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/amiconf.h b/include/amiconf.h index 276ed8f..4cc3963 100644 --- a/include/amiconf.h +++ b/include/amiconf.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)amiconf.h 3.3 2000/01/12 */ +/* SCCS Id: @(#)amiconf.h 3.4 2000/01/12 */ /* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1990, 1991, 1992, 1993. */ /* NetHack may be freely redistributed. See license for details. */ @@ -30,13 +30,23 @@ # define DCC30_BUG /* A bitfield bug (from dog.c, others) in DICE 3.0. */ #endif +#ifndef __GNUC__ typedef long off_t; +#endif #define MICRO /* must be defined to allow some inclusions */ +#define NOCWD_ASSUMPTIONS /* Allow paths to be specified for HACKDIR, + LEVELDIR, SAVEDIR, BONESDIR, DATADIR, + SCOREDIR, LOCKDIR, and CONFIGDIR. */ + /* data librarian defs */ -#define DLBFILE "NetHack:nhdat" /* main library */ -#define DLBFILE2 "NetHack:nhsdat" /* sound library */ +#ifndef NOCWD_ASSUMPTIONS +# define DLBFILE "NetHack:nhdat" /* main library */ +# define DLBFILE2 "NetHack:nhsdat" /* sound library */ +#else +# define DLBFILE "nhdat" /* main library */ +# define DLBFILE2 "nhsdat" /* sound library */ #define FILENAME_CMP stricmp /* case insensitive */ #ifndef __SASC_60 @@ -86,7 +96,8 @@ extern void FDECL(ami_argset, (int *, char *[])); extern void FDECL(ami_mkargline, (int *, char **[])); extern void ami_wininit_data(void); -extern boolean FromWBench; /* how were we run? */ +#define FromWBench 0 /* A hint for compiler ... */ +/* extern boolean FromWBench; /* how were we run? */ extern int ami_argc; extern char **ami_argv; @@ -101,7 +112,7 @@ extern char **ami_argv; #define remove(x) unlink(x) /* DICE wants rewind() to return void. We want it to return int. */ -#ifdef _DCC +#if defined(_DCC) || defined(__GNUC__) # define rewind(f) fseek(f, 0, 0) #endif diff --git a/include/artifact.h b/include/artifact.h index c97a71d..88dd223 100644 --- a/include/artifact.h +++ b/include/artifact.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)artifact.h 3.3 95/05/31 */ +/* SCCS Id: @(#)artifact.h 3.4 1995/05/31 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -47,6 +47,7 @@ struct artifact { aligntyp alignment; /* alignment of bequeathing gods */ short role; /* character role associated with */ short race; /* character race associated with */ + long cost; /* price when sold to hero (default 100 x base cost) */ }; /* invoked properties with special powers */ diff --git a/include/artilist.h b/include/artilist.h index 5111b10..78bc8af 100644 --- a/include/artilist.h +++ b/include/artilist.h @@ -1,18 +1,18 @@ -/* SCCS Id: @(#)artilist.h 3.3 2000/07/22 */ +/* SCCS Id: @(#)artilist.h 3.4 2001/11/17 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #ifdef MAKEDEFS_C /* in makedefs.c, all we care about is the list of names */ -#define A(nam,typ,s1,s2,mt,atk,dfn,cry,inv,al,cl,rac) nam +#define A(nam,typ,s1,s2,mt,atk,dfn,cry,inv,al,cl,rac,cost) nam static const char *artifact_names[] = { #else /* in artifact.c, set up the actual artifact list structure */ -#define A(nam,typ,s1,s2,mt,atk,dfn,cry,inv,al,cl, rac) \ - { typ, nam, s1, s2, mt, atk, dfn, cry, inv, al, cl, rac } +#define A(nam,typ,s1,s2,mt,atk,dfn,cry,inv,al,cl,rac,cost) \ + { typ, nam, s1, s2, mt, atk, dfn, cry, inv, al, cl, rac, cost } #define NO_ATTK {0,0,0,0} /* no attack */ #define NO_DFNS {0,0,0,0} /* no defense */ @@ -29,41 +29,48 @@ static const char *artifact_names[] = { STATIC_OVL NEARDATA struct artifact artilist[] = { #endif /* MAKEDEFS_C */ +/* Artifact cost rationale: + * 1. The more useful the artifact, the better its cost. + * 2. Quest artifacts are highly valued. + * 3. Chaotic artifacts are inflated due to scarcity (and balance). + */ + + /* dummy element #0, so that all interesting indices are non-zero */ A("", STRANGE_OBJECT, - 0, 0, 0, NO_ATTK, NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + 0, 0, 0, NO_ATTK, NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 0L ), A("Excalibur", LONG_SWORD, (SPFX_NOGEN|SPFX_RESTR|SPFX_SEEK|SPFX_DEFN|SPFX_INTEL|SPFX_SEARCH),0,0, - PHYS(5,10), DRLI(0,0), NO_CARY, 0, A_LAWFUL, PM_KNIGHT, NON_PM ), + PHYS(5,10), DRLI(0,0), NO_CARY, 0, A_LAWFUL, PM_KNIGHT, NON_PM, 4000L ), /* * Stormbringer only has a 2 because it can drain a level, * providing 8 more. */ A("Stormbringer", RUNESWORD, (SPFX_RESTR|SPFX_ATTK|SPFX_DEFN|SPFX_INTEL|SPFX_DRLI), 0, 0, - DRLI(5,2), DRLI(0,0), NO_CARY, 0, A_CHAOTIC, NON_PM, NON_PM ), + DRLI(5,2), DRLI(0,0), NO_CARY, 0, A_CHAOTIC, NON_PM, NON_PM, 8000L ), /* * Mjollnir will return to the hand of the wielder when thrown * if the wielder is a Valkyrie wearing Gauntlets of Power. */ A("Mjollnir", WAR_HAMMER, /* Mjo:llnir */ (SPFX_RESTR|SPFX_ATTK), 0, 0, - ELEC(5,24), NO_DFNS, NO_CARY, 0, A_NEUTRAL, PM_VALKYRIE, NON_PM ), + ELEC(5,24), NO_DFNS, NO_CARY, 0, A_NEUTRAL, PM_VALKYRIE, NON_PM, 4000L ), A("Cleaver", BATTLE_AXE, SPFX_RESTR, 0, 0, - PHYS(3,6), NO_DFNS, NO_CARY, 0, A_NEUTRAL, PM_BARBARIAN, NON_PM ), + PHYS(3,6), NO_DFNS, NO_CARY, 0, A_NEUTRAL, PM_BARBARIAN, NON_PM, 1500L ), A("Grimtooth", ORCISH_DAGGER, SPFX_RESTR, 0, 0, - PHYS(2,6), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ORC ), + PHYS(2,6), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ORC, 300L ), /* * Orcrist and Sting have same alignment as elves. */ A("Orcrist", ELVEN_BROADSWORD, SPFX_DFLAG2, 0, M2_ORC, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF, 2000L ), /* * The combination of SPFX_WARN and M2_something on an artifact @@ -73,50 +80,50 @@ A("Orcrist", ELVEN_BROADSWORD, */ A("Sting", ELVEN_DAGGER, (SPFX_WARN|SPFX_DFLAG2), 0, M2_ORC, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_CHAOTIC, NON_PM, PM_ELF, 800L ), /* * Magicbane is a bit different! Its magic fanfare * unbalances victims in addition to doing some damage. */ A("Magicbane", ATHAME, (SPFX_RESTR|SPFX_ATTK|SPFX_DEFN), 0, 0, - STUN(3,4), DFNS(AD_MAGM), NO_CARY, 0, A_NEUTRAL, PM_WIZARD, NON_PM ), + STUN(3,4), DFNS(AD_MAGM), NO_CARY, 0, A_NEUTRAL, PM_WIZARD, NON_PM, 3500L ), A("Frost Brand", LONG_SWORD, (SPFX_RESTR|SPFX_ATTK|SPFX_DEFN), 0, 0, - COLD(5,0), COLD(0,0), NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + COLD(5,0), COLD(0,0), NO_CARY, 0, A_NONE, NON_PM, NON_PM, 3000L ), A("Fire Brand", LONG_SWORD, (SPFX_RESTR|SPFX_ATTK|SPFX_DEFN), 0, 0, - FIRE(5,0), FIRE(0,0), NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + FIRE(5,0), FIRE(0,0), NO_CARY, 0, A_NONE, NON_PM, NON_PM, 3000L ), A("Dragonbane", BROADSWORD, (SPFX_RESTR|SPFX_DCLAS), 0, S_DRAGON, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 500L ), A("Demonbane", LONG_SWORD, (SPFX_RESTR|SPFX_DFLAG2), 0, M2_DEMON, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM, 2500L ), A("Werebane", SILVER_SABER, (SPFX_RESTR|SPFX_DFLAG2), 0, M2_WERE, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 1500L ), A("Grayswandir", SILVER_SABER, (SPFX_RESTR|SPFX_HALRES), 0, 0, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM, 8000L ), A("Giantslayer", LONG_SWORD, (SPFX_RESTR|SPFX_DFLAG2), 0, M2_GIANT, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NEUTRAL, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NEUTRAL, NON_PM, NON_PM, 200L ), A("Ogresmasher", WAR_HAMMER, (SPFX_RESTR|SPFX_DCLAS), 0, S_OGRE, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 200L ), A("Trollsbane", MORNING_STAR, (SPFX_RESTR|SPFX_DCLAS), 0, S_TROLL, - PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM ), + PHYS(5,0), NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 200L ), /* * Two problems: 1) doesn't let trolls regenerate heads, * 2) doesn't give unusual message for 2-headed monsters (but @@ -124,7 +131,7 @@ A("Trollsbane", MORNING_STAR, */ A("Vorpal Blade", LONG_SWORD, (SPFX_RESTR|SPFX_BEHEAD), 0, 0, - PHYS(5,1), NO_DFNS, NO_CARY, 0, A_NEUTRAL, NON_PM, NON_PM ), + PHYS(5,1), NO_DFNS, NO_CARY, 0, A_NEUTRAL, NON_PM, NON_PM, 4000L ), /* * Ah, never shall I forget the cry, * or the shriek that shrieked he, @@ -135,11 +142,11 @@ A("Vorpal Blade", LONG_SWORD, */ A("Snickersnee", KATANA, SPFX_RESTR, 0, 0, - PHYS(0,8), NO_DFNS, NO_CARY, 0, A_LAWFUL, PM_SAMURAI, NON_PM ), + PHYS(0,8), NO_DFNS, NO_CARY, 0, A_LAWFUL, PM_SAMURAI, NON_PM, 1200L ), A("Sunsword", LONG_SWORD, (SPFX_RESTR|SPFX_DFLAG2), 0, M2_UNDEAD, - PHYS(5,0), DFNS(AD_BLND), NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM ), + PHYS(5,0), DFNS(AD_BLND), NO_CARY, 0, A_LAWFUL, NON_PM, NON_PM, 1500L ), /* * The artifacts for the quest dungeon, all self-willed. @@ -148,85 +155,86 @@ A("Sunsword", LONG_SWORD, A("The Orb of Detection", CRYSTAL_BALL, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL), (SPFX_ESP|SPFX_HSPDAM), 0, NO_ATTK, NO_DFNS, CARY(AD_MAGM), - INVIS, A_LAWFUL, PM_ARCHEOLOGIST, NON_PM ), + INVIS, A_LAWFUL, PM_ARCHEOLOGIST, NON_PM, 2500L ), A("The Heart of Ahriman", LUCKSTONE, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL), SPFX_STLTH, 0, - NO_ATTK, NO_DFNS, NO_CARY, - LEVITATION, A_NEUTRAL, PM_BARBARIAN, NON_PM ), + /* this stone does double damage if used as a projectile weapon */ + PHYS(5,0), NO_DFNS, NO_CARY, + LEVITATION, A_NEUTRAL, PM_BARBARIAN, NON_PM, 2500L ), A("The Sceptre of Might", MACE, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_DALIGN), 0, 0, PHYS(5,0), NO_DFNS, CARY(AD_MAGM), - CONFLICT, A_LAWFUL, PM_CAVEMAN, NON_PM ), + CONFLICT, A_LAWFUL, PM_CAVEMAN, NON_PM, 2500L ), #if 0 /* OBSOLETE */ A("The Palantir of Westernesse", CRYSTAL_BALL, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL), (SPFX_ESP|SPFX_REGEN|SPFX_HSPDAM), 0, NO_ATTK, NO_DFNS, NO_CARY, - TAMING, A_CHAOTIC, NON_PM , PM_ELF), + TAMING, A_CHAOTIC, NON_PM , PM_ELF, 8000L ), #endif A("The Staff of Aesculapius", QUARTERSTAFF, (SPFX_NOGEN|SPFX_RESTR|SPFX_ATTK|SPFX_INTEL|SPFX_DRLI|SPFX_REGEN), 0,0, DRLI(0,0), DRLI(0,0), NO_CARY, - HEALING, A_NEUTRAL, PM_HEALER, NON_PM ), + HEALING, A_NEUTRAL, PM_HEALER, NON_PM, 5000L ), A("The Magic Mirror of Merlin", MIRROR, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_SPEAK), SPFX_ESP, 0, NO_ATTK, NO_DFNS, CARY(AD_MAGM), - 0, A_LAWFUL, PM_KNIGHT, NON_PM ), + 0, A_LAWFUL, PM_KNIGHT, NON_PM, 1500L ), A("The Eyes of the Overworld", LENSES, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_XRAY), 0, 0, NO_ATTK, NO_DFNS, CARY(AD_MAGM), - ENLIGHTENING, A_NEUTRAL, PM_MONK, NON_PM ), + ENLIGHTENING, A_NEUTRAL, PM_MONK, NON_PM, 2500L ), A("The Mitre of Holiness", HELM_OF_BRILLIANCE, (SPFX_NOGEN|SPFX_RESTR|SPFX_DFLAG2|SPFX_INTEL), 0, M2_UNDEAD, NO_ATTK, NO_DFNS, CARY(AD_FIRE), - ENERGY_BOOST, A_LAWFUL, PM_PRIEST, NON_PM ), + ENERGY_BOOST, A_LAWFUL, PM_PRIEST, NON_PM, 2000L ), A("The Longbow of Diana", BOW, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_REFLECT), SPFX_ESP, 0, PHYS(5,0), NO_DFNS, NO_CARY, - CREATE_AMMO, A_CHAOTIC, PM_RANGER, NON_PM ), + CREATE_AMMO, A_CHAOTIC, PM_RANGER, NON_PM, 4000L ), A("The Master Key of Thievery", SKELETON_KEY, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_SPEAK), (SPFX_WARN|SPFX_TCTRL|SPFX_HPHDAM), 0, NO_ATTK, NO_DFNS, NO_CARY, - UNTRAP, A_CHAOTIC, PM_ROGUE, NON_PM ), + UNTRAP, A_CHAOTIC, PM_ROGUE, NON_PM, 3500L ), A("The Tsurugi of Muramasa", TSURUGI, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_BEHEAD|SPFX_LUCK), 0, 0, PHYS(0,8), NO_DFNS, NO_CARY, - 0, A_LAWFUL, PM_SAMURAI, NON_PM ), + 0, A_LAWFUL, PM_SAMURAI, NON_PM, 4500L ), #ifdef TOURIST A("The Platinum Yendorian Express Card", CREDIT_CARD, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_DEFN), (SPFX_ESP|SPFX_HSPDAM), 0, NO_ATTK, NO_DFNS, CARY(AD_MAGM), - CHARGE_OBJ, A_NEUTRAL, PM_TOURIST, NON_PM ), + CHARGE_OBJ, A_NEUTRAL, PM_TOURIST, NON_PM, 7000L ), #endif A("The Orb of Fate", CRYSTAL_BALL, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL|SPFX_LUCK), (SPFX_WARN|SPFX_HSPDAM|SPFX_HPHDAM), 0, NO_ATTK, NO_DFNS, NO_CARY, - LEV_TELE, A_NEUTRAL, PM_VALKYRIE, NON_PM ), + LEV_TELE, A_NEUTRAL, PM_VALKYRIE, NON_PM, 3500L ), A("The Eye of the Aethiopica", AMULET_OF_ESP, (SPFX_NOGEN|SPFX_RESTR|SPFX_INTEL), (SPFX_EREGEN|SPFX_HSPDAM), 0, NO_ATTK, NO_DFNS, CARY(AD_MAGM), - CREATE_PORTAL, A_NEUTRAL, PM_WIZARD, NON_PM ), + CREATE_PORTAL, A_NEUTRAL, PM_WIZARD, NON_PM, 4000L ), /* * terminator; otyp must be zero */ -A(0, 0, 0, 0, 0, NO_ATTK, NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM ) +A(0, 0, 0, 0, 0, NO_ATTK, NO_DFNS, NO_CARY, 0, A_NONE, NON_PM, NON_PM, 0L ) }; /* artilist[] (or artifact_names[]) */ diff --git a/include/attrib.h b/include/attrib.h index afb87d8..7148191 100644 --- a/include/attrib.h +++ b/include/attrib.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)attrib.h 3.3 90/22/02 */ +/* SCCS Id: @(#)attrib.h 3.4 1990/22/02 */ /* Copyright 1988, Mike Stephenson */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/beconf.h b/include/beconf.h index feb652f..56df16e 100644 --- a/include/beconf.h +++ b/include/beconf.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)beconf.h 3.3 98/07/08 */ +/* SCCS Id: @(#)beconf.h 3.4 1998/07/08 */ /* Copyright (c) Dean Luick 1996. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/color.h b/include/color.h index 79c3672..f791ffa 100644 --- a/include/color.h +++ b/include/color.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)color.h 3.3 92/02/02 */ +/* SCCS Id: @(#)color.h 3.4 1992/02/02 */ /* Copyright (c) Steve Linhart, Eric Raymond, 1989. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/config.h b/include/config.h index 0184d49..fddb257 100644 --- a/include/config.h +++ b/include/config.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)config.h 3.3 2000/07/20 */ +/* SCCS Id: @(#)config.h 3.4 2002/03/17 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -46,6 +46,7 @@ /* #define X11_GRAPHICS */ /* X11 interface */ /* #define QT_GRAPHICS */ /* Qt interface */ /* #define GNOME_GRAPHICS */ /* Gnome interface */ +/* #define MSWIN_GRAPHICS */ /* Windows NT, CE, Graphics */ /* * Define the default window system. This should be one that is compiled @@ -82,6 +83,7 @@ #endif #ifdef QT_GRAPHICS +# define USER_SOUNDS /* Use sounds */ # define USE_XPM /* Use XPM format for images (required) */ # define GRAPHIC_TOMBSTONE /* Use graphical tombstone (rip.ppm) */ # ifndef DEFAULT_WINDOW_SYS @@ -97,6 +99,16 @@ # endif #endif +#ifdef MSWIN_GRAPHICS +# ifdef TTY_GRAPHICS +# undef TTY_GRAPHICS +# endif +# ifndef DEFAULT_WINDOW_SYS +# define DEFAULT_WINDOW_SYS "mswin" +# endif +# define HACKDIR "\\nethack" +#endif + #ifndef DEFAULT_WINDOW_SYS # define DEFAULT_WINDOW_SYS "tty" #endif @@ -186,7 +198,11 @@ * otherwise it will be the current directory. */ # ifndef HACKDIR -# define HACKDIR "/usr/games/lib/nethackdir" /* nethack directory */ +# ifdef __APPLE__ +# define HACKDIR "nethackdir" /* nethack directory */ +# else +# define HACKDIR "/usr/games/lib/nethackdir" +# endif # endif /* @@ -322,6 +338,18 @@ typedef unsigned char uchar; #define EXP_ON_BOTL /* Show experience on bottom line */ /* #define SCORE_ON_BOTL */ /* added by Gary Erickson (erickson@ucivax) */ +/* + * Section 5: EXPERIMENTAL STUFF + * + * Conditional compilation of new or experimental options are controlled here. + * Enable any of these at your own risk -- there are almost certainly + * bugs left here. + */ + +/*#define GOLDOBJ */ /* Gold is kept on obj chains - Helge Hafting */ + +/* End of Section 5 */ + #include "global.h" /* Define everything else according to choices above */ #endif /* CONFIG_H */ diff --git a/include/config1.h b/include/config1.h index 25ec295..a38e13c 100644 --- a/include/config1.h +++ b/include/config1.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)config1.h 3.3 1999/12/05 */ +/* SCCS Id: @(#)config1.h 3.4 1999/12/05 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -32,7 +32,7 @@ /* * Mac Stuff. */ -#ifdef applec /* MPW auto-defined symbol */ +#ifdef macintosh /* Auto-defined symbol for MPW compilers (sc and mrc) */ # define MAC #endif @@ -41,7 +41,7 @@ # define NEED_VARARGS #endif -#ifdef __MWERKS__ /* defined by Metrowerks compiler */ +#ifdef __MWERKS__ /* defined by Metrowerks' Codewarrior compiler */ # ifndef __BEOS__ /* BeOS */ # define MAC # endif @@ -108,6 +108,11 @@ /* * Windows NT Autodetection */ +#ifdef _WIN32_WCE +# ifndef WIN32 +# define WIN32 +# endif +#endif #ifdef WIN32 # undef UNIX @@ -116,6 +121,7 @@ # define STRNCMPI # define USE_STDARG # define NEED_VARARGS + #endif diff --git a/include/coord.h b/include/coord.h index ae102ce..3322820 100644 --- a/include/coord.h +++ b/include/coord.h @@ -1,11 +1,11 @@ -/* SCCS Id: @(#)coord.h 3.3 90/02/22 */ +/* SCCS Id: @(#)coord.h 3.4 1990/02/22 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #ifndef COORD_H #define COORD_H -typedef struct { +typedef struct nhcoord { xchar x,y; } coord; diff --git a/include/decl.h b/include/decl.h index ae8ec81..717a23f 100644 --- a/include/decl.h +++ b/include/decl.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)decl.h 3.3 2000/06/12 */ +/* SCCS Id: @(#)decl.h 3.4 2001/12/10 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -27,7 +27,9 @@ E char SAVEP[]; E NEARDATA int bases[MAXOCLASSES]; E NEARDATA int multi; +#if 0 E NEARDATA int warnlevel; +#endif E NEARDATA int nroom; E NEARDATA int nsubroom; E NEARDATA int occtime; @@ -142,7 +144,7 @@ E struct linfo level_info[MAXLINFO]; E NEARDATA struct sinfo { int gameover; /* self explanatory? */ int stopprint; /* inhibit further end of game disclosure */ -#if defined(UNIX) || defined(VMS) || defined (__EMX__) +#if defined(UNIX) || defined(VMS) || defined (__EMX__) || defined(WIN32) int done_hup; /* SIGHUP or moral equivalent received * -- no more screen output */ #endif @@ -162,6 +164,9 @@ E const char ynqchars[]; E const char ynaqchars[]; E const char ynNaqchars[]; E NEARDATA long yn_number; + +E const char disclosure_options[]; + E NEARDATA int smeq[]; E NEARDATA int doorindex; E NEARDATA char *save_cm; @@ -171,6 +176,9 @@ E NEARDATA char *save_cm; E NEARDATA int killer_format; E const char *killer; E const char *delayed_killer; +#ifdef GOLDOBJ +E long done_money; +#endif E char killer_buf[BUFSZ]; E const char *configfile; E NEARDATA char plname[PL_NSIZ]; @@ -188,11 +196,14 @@ E const schar xdir[], ydir[], zdir[]; E NEARDATA schar tbx, tby; /* set in mthrowu.c */ +E NEARDATA struct multishot { int n, i; short o; boolean s; } m_shot; + E NEARDATA struct dig_info { /* apply.c, hack.c */ int effort; d_level level; coord pos; - boolean down, chew; + long lastdigtime; + boolean down, chew, warned, quiet; } digging; E NEARDATA long moves, monstermoves; @@ -236,10 +247,6 @@ E NEARDATA struct obj *migrating_objs; E NEARDATA struct obj *billobjs; E NEARDATA struct obj zeroobj; /* init'd and defined in decl.c */ -E const char *he[3]; -E const char *him[3]; -E const char *his[3]; - #include "you.h" E NEARDATA struct you u; @@ -274,12 +281,15 @@ E NEARDATA struct c_color_names { #define purple c_color_names.c_purple #define White c_color_names.c_white +/* The names of the colors used for gems, etc. */ +E const char *c_obj_colors[]; + E struct c_common_strings { const char *const c_nothing_happens, *const c_thats_enough_tries, *const c_silly_thing_to, *const c_shudder_for_moment, *const c_something, *const c_Something, *const c_You_can_move_again, - *const c_Never_mind; + *const c_Never_mind, *c_vision_clears; } c_common_strings; #define nothing_happens c_common_strings.c_nothing_happens #define thats_enough_tries c_common_strings.c_thats_enough_tries @@ -289,6 +299,7 @@ E struct c_common_strings { #define Something c_common_strings.c_Something #define You_can_move_again c_common_strings.c_You_can_move_again #define Never_mind c_common_strings.c_Never_mind +#define vision_clears c_common_strings.c_vision_clears /* material strings */ E const char *materialnm[]; diff --git a/include/def_os2.h b/include/def_os2.h index 58713e5..7ba40e4 100644 --- a/include/def_os2.h +++ b/include/def_os2.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)def_os2.h 3.3 93/01/19 */ +/* SCCS Id: @(#)def_os2.h 3.4 1993/01/19 */ /* Copyright (c) Timo Hakulinen, 1990, 1991, 1992, 1993. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/dgn_file.h b/include/dgn_file.h index 1146c41..2fa3214 100644 --- a/include/dgn_file.h +++ b/include/dgn_file.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dgn_file.h 3.3 93/01/17 */ +/* SCCS Id: @(#)dgn_file.h 3.4 1993/01/17 */ /* Copyright (c) 1989 by M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/display.h b/include/display.h index 5a5c480..fa458ba 100644 --- a/include/display.h +++ b/include/display.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)display.h 3.3 1999/11/30 */ +/* SCCS Id: @(#)display.h 3.4 1999/11/30 */ /* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */ /* and Dave Cohrs, 1990. */ /* NetHack may be freely redistributed. See license for details. */ @@ -245,6 +245,11 @@ * is the dungeon features and other miscellaneous things. * Count: MAXPCHARS * + * explosions A set of nine for each of the following seven explosion types: + * dark, noxious, muddy, wet, magical, fiery, frosty. + * The nine positions represent those surrounding the hero. + * Count: MAXEXPCHARS * EXPL_MAX (EXPL_MAX is defined in hack.h) + * * zap beam A set of four (there are four directions) for each beam type. * The beam type is shifted over 2 positions and the direction * is stored in the lower 2 bits. Count: NUM_ZAP << 2 @@ -268,7 +273,8 @@ #define GLYPH_RIDDEN_OFF (NUMMONS + GLYPH_BODY_OFF) #define GLYPH_OBJ_OFF (NUMMONS + GLYPH_RIDDEN_OFF) #define GLYPH_CMAP_OFF (NUM_OBJECTS + GLYPH_OBJ_OFF) -#define GLYPH_ZAP_OFF (MAXPCHARS + GLYPH_CMAP_OFF) +#define GLYPH_EXPLODE_OFF ((MAXPCHARS - MAXEXPCHARS) + GLYPH_CMAP_OFF) +#define GLYPH_ZAP_OFF ((MAXEXPCHARS * EXPL_MAX) + GLYPH_EXPLODE_OFF) #define GLYPH_SWALLOW_OFF ((NUM_ZAP << 2) + GLYPH_ZAP_OFF) #define GLYPH_WARNING_OFF ((NUMMONS << 3) + GLYPH_SWALLOW_OFF) #define MAX_GLYPH (WARNCOUNT + GLYPH_WARNING_OFF) @@ -295,6 +301,9 @@ (int) (obj)->otyp + GLYPH_OBJ_OFF)) #define cmap_to_glyph(cmap_idx) ((int) (cmap_idx) + GLYPH_CMAP_OFF) +#define explosion_to_glyph(expltype,idx) \ + ((((expltype) * MAXEXPCHARS) + ((idx) - S_explode1)) + GLYPH_EXPLODE_OFF) + #define trap_to_glyph(trap) \ cmap_to_glyph(trap_to_defsym(what_trap((trap)->ttyp))) diff --git a/include/dlb.h b/include/dlb.h index 0527100..3af4462 100644 --- a/include/dlb.h +++ b/include/dlb.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dlb.h 3.3 97/07/29 */ +/* SCCS Id: @(#)dlb.h 3.4 1997/07/29 */ /* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1993. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/dungeon.h b/include/dungeon.h index 8f0b7db..46e8636 100644 --- a/include/dungeon.h +++ b/include/dungeon.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dungeon.h 3.3 99/07/02 */ +/* SCCS Id: @(#)dungeon.h 3.4 1999/07/02 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/edog.h b/include/edog.h index ef9f9a1..eadc5b3 100644 --- a/include/edog.h +++ b/include/edog.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)edog.h 3.3 97/10/23 */ +/* SCCS Id: @(#)edog.h 3.4 1997/10/23 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/emin.h b/include/emin.h index ccc0b4b..811bf23 100644 --- a/include/emin.h +++ b/include/emin.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)emin.h 3.3 97/05/01 */ +/* SCCS Id: @(#)emin.h 3.4 1997/05/01 */ /* Copyright (c) David Cohrs, 1990. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/engrave.h b/include/engrave.h index 105fd8b..02c5d9e 100644 --- a/include/engrave.h +++ b/include/engrave.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)engrave.h 3.3 91/07/31 */ +/* SCCS Id: @(#)engrave.h 3.4 1991/07/31 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/epri.h b/include/epri.h index f09a566..56b14ac 100644 --- a/include/epri.h +++ b/include/epri.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)epri.h 3.3 97/05/01 */ +/* SCCS Id: @(#)epri.h 3.4 1997/05/01 */ /* Copyright (c) Izchak Miller, 1989. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/eshk.h b/include/eshk.h index 0408acd..72a30e3 100644 --- a/include/eshk.h +++ b/include/eshk.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)eshk.h 3.3 97/05/01 */ +/* SCCS Id: @(#)eshk.h 3.4 1997/05/01 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/extern.h b/include/extern.h index 89b1a5b..7bfb13e 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)extern.h 3.3 2000/07/14 */ +/* SCCS Id: @(#)extern.h 3.4 2002/03/09 */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -34,7 +34,7 @@ E int NDECL(dojump); E int FDECL(jump, (int)); E int NDECL(number_leashed); E void FDECL(o_unleash, (struct obj *)); -E void FDECL(m_unleash, (struct monst *)); +E void FDECL(m_unleash, (struct monst *,BOOLEAN_P)); E void NDECL(unleash_all); E boolean NDECL(next_to_u); E struct obj *FDECL(get_mleash, (struct monst *)); @@ -43,10 +43,12 @@ E boolean FDECL(wield_tool, (struct obj *)); E boolean FDECL(um_dist, (XCHAR_P,XCHAR_P,XCHAR_P)); E boolean FDECL(snuff_candle, (struct obj *)); E boolean FDECL(snuff_lit, (struct obj *)); +E boolean FDECL(catch_lit, (struct obj *)); E void FDECL(use_unicorn_horn, (struct obj *)); E boolean FDECL(tinnable, (struct obj *)); E void NDECL(reset_trapset); E void FDECL(fig_transform, (genericptr_t, long)); +E int FDECL(unfixable_trouble_count,(BOOLEAN_P)); /* ### artifact.c ### */ @@ -74,7 +76,10 @@ E boolean FDECL(artifact_hit, (struct monst *,struct monst *, struct obj *,int *,int)); E int NDECL(doinvoke); E void FDECL(arti_speak, (struct obj *)); +E boolean FDECL(artifact_light, (struct obj *)); E long FDECL(spec_m2, (struct obj *)); +E boolean FDECL(artifact_has_invprop, (struct obj *,UCHAR_P)); +E long FDECL(arti_cost, (struct obj *)); /* ### attrib.c ### */ @@ -166,7 +171,7 @@ E int FDECL(movecmd, (CHAR_P)); E int FDECL(getdir, (const char *)); E void NDECL(confdir); E int FDECL(isok, (int,int)); -E int FDECL(click_to_cmd, (int,int,int)); +E const char *FDECL(click_to_cmd, (int,int,int)); E char NDECL(readchar); #ifdef WIZARD E void NDECL(sanity_check); @@ -192,6 +197,7 @@ E void NDECL(decl_init); /* ### detect.c ### */ E struct obj *FDECL(o_in, (struct obj*,CHAR_P)); +E struct obj *FDECL(o_material, (struct obj*,unsigned)); E int FDECL(gold_detect, (struct obj *)); E int FDECL(food_detect, (struct obj *)); E int FDECL(object_detect, (struct obj *,int)); @@ -215,6 +221,7 @@ E void NDECL(sokoban_detect); /* ### dig.c ### */ +E boolean NDECL(is_digging); #ifdef USE_TRAMPOLI E int NDECL(dig); #endif @@ -223,7 +230,9 @@ E boolean FDECL(dig_check, (struct monst *, BOOLEAN_P, int, int)); E void FDECL(digactualhole, (int,int,struct monst *,int)); E boolean FDECL(dighole, (BOOLEAN_P)); E int FDECL(use_pick_axe, (struct obj *)); +E int FDECL(use_pick_axe2, (struct obj *)); E boolean FDECL(mdig_tunnel, (struct monst *)); +E void FDECL(watch_dig, (struct monst *,XCHAR_P,XCHAR_P,BOOLEAN_P)); E void NDECL(zap_dig); E struct obj *FDECL(bury_an_obj, (struct obj *)); E void FDECL(bury_objs, (int,int)); @@ -287,6 +296,7 @@ E void FDECL(doaltarobj, (struct obj *)); E boolean FDECL(canletgo, (struct obj *,const char *)); E void FDECL(dropx, (struct obj *)); E void FDECL(dropy, (struct obj *)); +E void FDECL(obj_no_longer_held, (struct obj *)); E int NDECL(doddrop); E int NDECL(dodown); E int NDECL(doup); @@ -324,15 +334,15 @@ E char *FDECL(y_monnam, (struct monst *)); E char *FDECL(Adjmonnam, (struct monst *,const char *)); E char *FDECL(Amonnam, (struct monst *)); E char *FDECL(a_monnam, (struct monst *)); +E char *FDECL(distant_monnam, (struct monst *,int,char *)); E const char *NDECL(rndmonnam); E const char *FDECL(hcolor, (const char *)); -E char *FDECL(self_pronoun, (const char *,const char *)); #ifdef REINCARNATION E const char *NDECL(roguename); #endif E struct obj *FDECL(realloc_obj, (struct obj *, int, genericptr_t, int, const char *)); -E char *FDECL(coyotename, (char *)); +E char *FDECL(coyotename, (struct monst *,char *)); /* ### do_wear.c ### */ @@ -417,7 +427,8 @@ E int NDECL(dothrow); E int NDECL(dofire); E void FDECL(hitfloor, (struct obj *)); E void FDECL(hurtle, (int,int,int,BOOLEAN_P)); -E void FDECL(throwit, (struct obj *,long)); +E void FDECL(mhurtle, (struct monst *,int,int,int)); +E void FDECL(throwit, (struct obj *,long,BOOLEAN_P)); E int FDECL(omon_adj, (struct monst *,struct obj *,BOOLEAN_P)); E int FDECL(thitmonst, (struct monst *,struct obj *)); E int FDECL(hero_breaks, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P)); @@ -516,6 +527,8 @@ E int FDECL(eaten_stat, (int,struct obj *)); E void FDECL(food_disappears, (struct obj *)); E void FDECL(food_substitution, (struct obj *,struct obj *)); E void NDECL(fix_petrification); +E void FDECL(consume_oeaten, (struct obj *,int)); +E boolean FDECL(maybe_finished_meal, (BOOLEAN_P)); /* ### end.c ### */ @@ -568,7 +581,7 @@ E long NDECL(rndexp); /* ### explode.c ### */ -E void FDECL(explode, (int,int,int,int,CHAR_P)); +E void FDECL(explode, (int,int,int,int,CHAR_P,int)); E void FDECL(scatter, (int, int, int, unsigned int, struct obj *)); E void FDECL(splatter_burning_oil, (int, int)); @@ -617,8 +630,14 @@ E void FDECL(compress, (const char *)); E void FDECL(uncompress, (const char *)); E boolean FDECL(lock_file, (const char *,int,int)); E void FDECL(unlock_file, (const char *)); +#ifdef USER_SOUNDS +E boolean FDECL(can_read_file, (const char *)); +#endif E void FDECL(read_config_file, (const char *)); E void FDECL(check_recordfile, (const char *)); +#if defined(WIZARD) +E void NDECL(read_wizkit); +#endif /* ### fountain.c ### */ @@ -643,6 +662,7 @@ E boolean FDECL(may_dig, (XCHAR_P,XCHAR_P)); E boolean FDECL(may_passwall, (XCHAR_P,XCHAR_P)); E boolean FDECL(bad_rock, (struct permonst *,XCHAR_P,XCHAR_P)); E boolean FDECL(invocation_pos, (XCHAR_P,XCHAR_P)); +E boolean FDECL(test_move, (int, int, int, int, BOOLEAN_P)); E void NDECL(domove); E void NDECL(invocation_message); E void FDECL(spoteffects, (BOOLEAN_P)); @@ -661,6 +681,9 @@ E int FDECL(calc_capacity, (int)); E int NDECL(max_capacity); E boolean FDECL(check_capacity, (const char *)); E int NDECL(inv_cnt); +#ifdef GOLDOBJ +E long FDECL(money_cnt, (struct obj *)); +#endif /* ### hacklib.c ### */ @@ -669,6 +692,7 @@ E boolean FDECL(letter, (CHAR_P)); E char FDECL(highc, (CHAR_P)); E char FDECL(lowc, (CHAR_P)); E char *FDECL(lcase, (char *)); +E char *FDECL(upstart, (char *)); E char *FDECL(mungspaces, (char *)); E char *FDECL(eos, (char *)); E char *FDECL(s_suffix, (const char *)); @@ -731,19 +755,19 @@ E boolean FDECL(is_worn, (struct obj *)); E struct obj *FDECL(g_at, (int,int)); E struct obj *FDECL(mkgoldobj, (long)); E struct obj *FDECL(getobj, (const char *,const char *)); -E int FDECL(ggetobj, (const char *,int (*)(OBJ_P),int,BOOLEAN_P)); +E int FDECL(ggetobj, (const char *,int (*)(OBJ_P),int,BOOLEAN_P,unsigned *)); E void FDECL(fully_identify_obj, (struct obj *)); E int FDECL(identify, (struct obj *)); E void FDECL(identify_pack, (int)); E int FDECL(askchain, (struct obj **,const char *,int,int (*)(OBJ_P), int (*)(OBJ_P),int,const char *)); E void FDECL(prinv, (const char *,struct obj *,long)); -E char *FDECL(xprname, (struct obj *,const char *,CHAR_P,BOOLEAN_P,long)); +E char *FDECL(xprname, (struct obj *,const char *,CHAR_P,BOOLEAN_P,long,long)); E int NDECL(ddoinv); E char FDECL(display_inventory, (const char *,BOOLEAN_P)); E int FDECL(display_binventory, (int,int,BOOLEAN_P)); E struct obj *FDECL(display_cinventory,(struct obj *)); -E struct obj *FDECL(display_minventory,(struct monst *,int)); +E struct obj *FDECL(display_minventory,(struct monst *,int,char *)); E int NDECL(dotypeinv); E const char *FDECL(dfeature_at, (int,int,char *)); E int FDECL(look_here, (int,BOOLEAN_P)); @@ -763,7 +787,9 @@ E void NDECL(free_invbuf); E void NDECL(reassign); E int NDECL(doorganize); E int FDECL(count_unpaid, (struct obj *)); +E int FDECL(count_buc, (struct obj *,int)); E void FDECL(carry_obj_effects, (struct obj *)); +E const char *FDECL(currency, (long)); /* ### ioctl.c ### */ @@ -878,10 +904,18 @@ E int FDECL(golemhp, (int)); E boolean FDECL(peace_minded, (struct permonst *)); E void FDECL(set_malign, (struct monst *)); E void FDECL(set_mimic_sym, (struct monst *)); +E int FDECL(mbirth_limit, (int)); +#ifdef GOLDOBJ +E void FDECL(mkmonmoney, (struct monst *, long)); +#endif + +/* ### mapglyph.c ### */ + +E void FDECL(mapglyph, (int, int *, int *, unsigned *, int, int)); /* ### mcastu.c ### */ -E int FDECL(castmu, (struct monst *,struct attack *)); +E int FDECL(castmu, (struct monst *,struct attack *,BOOLEAN_P,BOOLEAN_P)); E int FDECL(buzzmu, (struct monst *,struct attack *)); /* ### mhitm.c ### */ @@ -898,6 +932,7 @@ E const char *FDECL(mpoisons_subj, (struct monst *,struct attack *)); E void NDECL(u_slow_down); E struct monst *NDECL(cloneu); E void FDECL(expels, (struct monst *,struct permonst *,BOOLEAN_P)); +E struct attack *FDECL(getmattk, (struct permonst *,int,int *,struct attack *)); E int FDECL(mattacku, (struct monst *)); E int FDECL(gazemu, (struct monst *,struct attack *)); E void FDECL(mdamageu, (struct monst *,int)); @@ -967,7 +1002,7 @@ E void FDECL(restore_waterlevel, (int)); /* ### mkobj.c ### */ E struct obj *FDECL(mkobj_at, (CHAR_P,int,int,BOOLEAN_P)); -E struct obj *FDECL(mksobj_at, (int,int,int,BOOLEAN_P)); +E struct obj *FDECL(mksobj_at, (int,int,int,BOOLEAN_P,BOOLEAN_P)); E struct obj *FDECL(mkobj, (CHAR_P,BOOLEAN_P)); E int NDECL(rndmonnum); E struct obj *FDECL(splitobj, (struct obj *,long)); @@ -992,6 +1027,7 @@ E void FDECL(curse, (struct obj *)); E void FDECL(uncurse, (struct obj *)); E void FDECL(blessorcurse, (struct obj *,int)); E boolean FDECL(is_flammable, (struct obj *)); +E boolean FDECL(is_rottable, (struct obj *)); E void FDECL(place_object, (struct obj *,int,int)); E void FDECL(remove_object, (struct obj *)); E void FDECL(discard_minvent, (struct monst *)); @@ -999,7 +1035,7 @@ E void FDECL(obj_extract_self, (struct obj *)); E void FDECL(extract_nobj, (struct obj *, struct obj **)); E void FDECL(extract_nexthere, (struct obj *, struct obj **)); E int FDECL(add_to_minv, (struct monst *, struct obj *)); -E void FDECL(add_to_container, (struct obj *, struct obj *)); +E struct obj *FDECL(add_to_container, (struct obj *, struct obj *)); E void FDECL(add_to_migration, (struct obj *)); E void FDECL(add_to_buried, (struct obj *)); E void FDECL(dealloc_obj, (struct obj *)); @@ -1030,9 +1066,9 @@ E struct mkroom *FDECL(search_special, (SCHAR_P)); E int FDECL(undead_to_corpse, (int)); E int FDECL(pm_to_cham, (int)); -E int FDECL(minwater, (struct monst *)); +E int FDECL(minliquid, (struct monst *)); E int NDECL(movemon); -E int FDECL(meatgold, (struct monst *)); +E int FDECL(meatmetal, (struct monst *)); E int FDECL(meatobj, (struct monst *)); E void FDECL(mpickgold, (struct monst *)); E boolean FDECL(mpickstuff, (struct monst *,const char *)); @@ -1047,6 +1083,7 @@ E void NDECL(mcalcdistress); E void FDECL(replmon, (struct monst *,struct monst *)); E void FDECL(relmon, (struct monst *)); E struct obj *FDECL(mlifesaver, (struct monst *)); +E boolean FDECL(corpse_chance,(struct monst *,struct monst *,BOOLEAN_P)); E void FDECL(mondead, (struct monst *)); E void FDECL(mondied, (struct monst *)); E void FDECL(mongone, (struct monst *)); @@ -1070,7 +1107,7 @@ E void NDECL(rescham); E void NDECL(restartcham); E void FDECL(restore_cham, (struct monst *)); E void FDECL(mon_animal_list, (BOOLEAN_P)); -E int FDECL(newcham, (struct monst *,struct permonst *)); +E int FDECL(newcham, (struct monst *,struct permonst *,BOOLEAN_P)); E int FDECL(can_be_hatched, (int)); E int FDECL(egg_type_from_parent, (int,BOOLEAN_P)); E boolean FDECL(dead_species, (int,BOOLEAN_P)); @@ -1082,6 +1119,7 @@ E void NDECL(pacify_guards); /* ### mondata.c ### */ E void FDECL(set_mon_data, (struct monst *,struct permonst *,int)); +E struct attack *FDECL(attacktype_fordmg, (struct permonst *,int,int)); E boolean FDECL(attacktype, (struct permonst *,int)); E boolean FDECL(poly_when_stoned, (struct permonst *)); E boolean FDECL(resists_drli, (struct monst *)); @@ -1095,6 +1133,7 @@ E boolean FDECL(breakarm, (struct permonst *)); E boolean FDECL(sliparm, (struct permonst *)); E boolean FDECL(sticks, (struct permonst *)); /* E boolean FDECL(canseemon, (struct monst *)); */ +E struct attack *FDECL(dmgtype_fromattack, (struct permonst *,int,int)); E boolean FDECL(dmgtype, (struct permonst *,int)); E int FDECL(max_passive_dmg, (struct monst *,struct monst *)); E int FDECL(monsndx, (struct permonst *)); @@ -1105,6 +1144,7 @@ E boolean FDECL(levl_follower, (struct monst *)); E int FDECL(little_to_big, (int)); E int FDECL(big_to_little, (int)); E const char *FDECL(locomotion, (const struct permonst *,const char *)); +E const char *FDECL(stagger, (const struct permonst *,const char *)); /* ### monmove.c ### */ @@ -1113,6 +1153,7 @@ E boolean FDECL(mb_trapped, (struct monst *)); E void FDECL(mon_regen, (struct monst *,BOOLEAN_P)); E int FDECL(dochugw, (struct monst *)); E boolean FDECL(onscary, (int,int,struct monst *)); +E void FDECL(monflee, (struct monst *, int, BOOLEAN_P, BOOLEAN_P)); E int FDECL(dochug, (struct monst *)); E int FDECL(m_move, (struct monst *,int)); E boolean FDECL(closed_door, (int,int)); @@ -1270,22 +1311,29 @@ E char *FDECL(simple_typename, (int)); E boolean FDECL(obj_is_pname, (struct obj *)); E char *FDECL(distant_name, (struct obj *,char *(*)(OBJ_P))); E char *FDECL(xname, (struct obj *)); +E char *FDECL(mshot_xname, (struct obj *)); +E boolean FDECL(the_unique_obj, (struct obj *obj)); E char *FDECL(doname, (struct obj *)); E boolean FDECL(not_fully_identified, (struct obj *)); -E const char *FDECL(corpse_xname, (struct obj *,BOOLEAN_P)); +E char *FDECL(corpse_xname, (struct obj *,BOOLEAN_P)); +E char *FDECL(cxname, (struct obj *)); E const char *FDECL(singular, (struct obj *,char *(*)(OBJ_P))); E char *FDECL(an, (const char *)); E char *FDECL(An, (const char *)); E char *FDECL(The, (const char *)); E char *FDECL(the, (const char *)); E char *FDECL(aobjnam, (struct obj *,const char *)); +E char *FDECL(Tobjnam, (struct obj *,const char *)); +E char *FDECL(otense, (struct obj *,const char *)); +E char *FDECL(vtense, (const char *,const char *)); E char *FDECL(Doname2, (struct obj *)); E char *FDECL(yname, (struct obj *)); E char *FDECL(Yname2, (struct obj *)); E char *FDECL(makeplural, (const char *)); E char *FDECL(makesingular, (const char *)); -E struct obj *FDECL(readobjnam, (char *)); +E struct obj *FDECL(readobjnam, (char *,struct obj *,BOOLEAN_P)); E int FDECL(rnd_class, (int,int)); +E const char *FDECL(cloak_simple_name, (struct obj *)); /* ### options.c ### */ @@ -1302,6 +1350,9 @@ E void FDECL(add_menu_cmd_alias, (CHAR_P, CHAR_P)); E char FDECL(map_menu_cmd, (CHAR_P)); E void FDECL(assign_warnings, (uchar *)); E char *FDECL(nh_getenv, (const char *)); +E void FDECL(set_duplicate_opt_detection, (int)); +E void FDECL(set_wc_option_mod_status, (unsigned long, int)); +E void FDECL(set_option_mod_status, (char *, int)); /* ### pager.c ### */ @@ -1355,7 +1406,6 @@ E void FDECL(msleep, (unsigned)); /* ### pcunix.c ### */ #if defined(MICRO) -E void FDECL(gethdate, (char *)); E void FDECL(regularize, (char *)); #endif /* MICRO */ #if defined(PC_LOCKING) @@ -1364,8 +1414,13 @@ E void NDECL(getlock); /* ### pickup.c ### */ +#ifdef GOLDOBJ +E int FDECL(collect_obj_classes, + (char *,struct obj *,BOOLEAN_P,boolean FDECL((*),(OBJ_P)))); +#else E int FDECL(collect_obj_classes, (char *,struct obj *,BOOLEAN_P,BOOLEAN_P,boolean FDECL((*),(OBJ_P)))); +#endif E void FDECL(add_valid_menu_class, (int)); E boolean FDECL(allow_all, (struct obj *)); E boolean FDECL(allow_category, (struct obj *)); @@ -1385,6 +1440,7 @@ E struct obj *FDECL(pick_obj, (struct obj *)); E int NDECL(encumber_msg); E int NDECL(doloot); E int FDECL(use_container, (struct obj *,int)); +E int FDECL(loot_mon, (struct monst *,int *,boolean *)); /* ### pline.c ### */ @@ -1410,7 +1466,7 @@ E void NDECL(self_invis_message); E void NDECL(set_uasmon); E void NDECL(change_sex); -E void NDECL(polyself); +E void FDECL(polyself, (BOOLEAN_P)); E int FDECL(polymon, (int)); E void NDECL(rehumanize); E int NDECL(dobreathe); @@ -1418,9 +1474,10 @@ E int NDECL(dospit); E int NDECL(doremove); E int NDECL(dospinweb); E int NDECL(dosummon); -E int NDECL(doconfuse); +E int NDECL(dogaze); E int NDECL(dohide); E int NDECL(domindblast); +E void FDECL(skinback, (BOOLEAN_P)); E const char *FDECL(mbodypart, (struct monst *,int)); E const char *FDECL(body_part, (int)); E int NDECL(poly_gender); @@ -1447,6 +1504,7 @@ E boolean FDECL(get_wet, (struct obj *)); E int NDECL(dodip); E void FDECL(djinni_from_bottle, (struct obj *)); E struct monst *FDECL(split_mon, (struct monst *,struct monst *)); +E const char *NDECL(bottlename); /* ### pray.c ### */ @@ -1507,7 +1565,6 @@ E void NDECL(unload_qtlist); E short FDECL(quest_info, (int)); E const char *NDECL(ldrname); E boolean FDECL(is_quest_artifact, (struct obj*)); -E boolean NDECL(leaderless); E void FDECL(com_pager, (int)); E void FDECL(qt_pager, (int)); E struct permonst *NDECL(qt_montype); @@ -1607,17 +1664,20 @@ E int FDECL(str2race, (char *)); E int FDECL(str2gend, (char *)); E int FDECL(str2align, (char *)); E boolean FDECL(ok_role, (int, int, int, int)); -E int FDECL(pick_role, (int, int, int)); +E int FDECL(pick_role, (int, int, int, int)); E boolean FDECL(ok_race, (int, int, int, int)); -E int FDECL(pick_race, (int, int, int)); +E int FDECL(pick_race, (int, int, int, int)); E boolean FDECL(ok_gend, (int, int, int, int)); -E int FDECL(pick_gend, (int, int, int)); +E int FDECL(pick_gend, (int, int, int, int)); E boolean FDECL(ok_align, (int, int, int, int)); -E int FDECL(pick_align, (int, int, int)); +E int FDECL(pick_align, (int, int, int, int)); E void NDECL(role_init); +E void NDECL(rigid_role_checks); E void NDECL(plnamesuffix); E const char *FDECL(Hello, (struct monst *)); E const char *NDECL(Goodbye); +E char *FDECL(build_plselection_prompt, (char *, int, int, int, int, int)); +E char *FDECL(root_plselection_prompt, (char *, int, int, int, int, int)); /* ### rumors.c ### */ @@ -1631,7 +1691,7 @@ E int FDECL(doconsult, (struct monst *)); /* ### save.c ### */ E int NDECL(dosave); -#if defined(UNIX) || defined(VMS) || defined(__EMX__) +#if defined(UNIX) || defined(VMS) || defined(__EMX__) || defined(WIN32) E void FDECL(hangup, (int)); #endif E int NDECL(dosave0); @@ -1656,6 +1716,10 @@ E void NDECL(freedynamicdata); /* ### shk.c ### */ +#ifdef GOLDOBJ +E long FDECL(money2mon, (struct monst *, long)); +E void FDECL(money2u, (struct monst *, long)); +#endif E char *FDECL(shkname, (struct monst *)); E void FDECL(shkgone, (struct monst *)); E void FDECL(set_residency, (struct monst *,BOOLEAN_P)); @@ -1663,6 +1727,7 @@ E void FDECL(replshk, (struct monst *,struct monst *)); E void FDECL(restshk, (struct monst *,BOOLEAN_P)); E char FDECL(inside_shop, (XCHAR_P,XCHAR_P)); E void FDECL(u_left_shop, (char *,BOOLEAN_P)); +E void FDECL(remote_burglary, (XCHAR_P,XCHAR_P)); E void FDECL(u_entered_shop, (char *)); E boolean FDECL(same_price, (struct obj *,struct obj *)); E void NDECL(shopper_financial_report); @@ -1679,7 +1744,7 @@ E int NDECL(dopay); E boolean FDECL(paybill, (BOOLEAN_P)); E void NDECL(finish_paybill); E struct obj *FDECL(find_oid, (unsigned)); -E long FDECL(contained_cost, (struct obj *,struct monst *,long,BOOLEAN_P)); +E long FDECL(contained_cost, (struct obj *,struct monst *,long,BOOLEAN_P, BOOLEAN_P)); E long FDECL(contained_gold, (struct obj *)); E void FDECL(picked_container, (struct obj *)); E long FDECL(unpaid_cost, (struct obj *)); @@ -1687,10 +1752,10 @@ E void FDECL(addtobill, (struct obj *,BOOLEAN_P,BOOLEAN_P,BOOLEAN_P)); E void FDECL(splitbill, (struct obj *,struct obj *)); E void FDECL(subfrombill, (struct obj *,struct monst *)); E long FDECL(stolen_value, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P,BOOLEAN_P)); -E void FDECL(sellobj_state, (BOOLEAN_P)); +E void FDECL(sellobj_state, (int)); E void FDECL(sellobj, (struct obj *,XCHAR_P,XCHAR_P)); E int FDECL(doinvbill, (int)); -E int FDECL(shkcatch, (struct obj *,XCHAR_P,XCHAR_P)); +E struct monst *FDECL(shkcatch, (struct obj *,XCHAR_P,XCHAR_P)); E void FDECL(add_damage, (XCHAR_P,XCHAR_P,long)); E int FDECL(repair_damage, (struct monst *,struct damage *,BOOLEAN_P)); E int FDECL(shk_move, (struct monst *)); @@ -1731,7 +1796,9 @@ E void FDECL(yelp, (struct monst *)); E void FDECL(whimper, (struct monst *)); E void FDECL(beg, (struct monst *)); E int NDECL(dotalk); - +#ifdef USER_SOUNDS +E int FDECL(add_sound_mapping, (const char *)); +#endif /* ### sys/msdos/sound.c ### */ @@ -1755,6 +1822,7 @@ E boolean FDECL(load_special, (const char *)); E int NDECL(learn); #endif E int FDECL(study_book, (struct obj *)); +E void FDECL(book_disappears, (struct obj *)); E void FDECL(book_substitution, (struct obj *,struct obj *)); E void NDECL(age_spells); E int NDECL(docast); @@ -1769,13 +1837,20 @@ E void FDECL(initialspell, (struct obj *)); #ifdef USE_TRAMPOLI E int NDECL(stealarm); #endif +#ifdef GOLDOBJ +E long FDECL(somegold, (long)); +#else E long NDECL(somegold); +#endif E void FDECL(stealgold, (struct monst *)); E void FDECL(remove_worn_item, (struct obj *)); -E int FDECL(steal, (struct monst *)); +E int FDECL(steal, (struct monst *, char *)); E int FDECL(mpickobj, (struct monst *,struct obj *)); E void FDECL(stealamulet, (struct monst *)); E void FDECL(relobj, (struct monst *,int,BOOLEAN_P)); +#ifdef GOLDOBJ +E struct obj *FDECL(findgold, (struct obj *)); +#endif /* ### steed.c ### */ @@ -1863,13 +1938,13 @@ E coord *FDECL(gettrack, (int,int)); E boolean FDECL(burnarmor,(struct monst *)); E boolean FDECL(rust_dmg, (struct obj *,const char *,int,BOOLEAN_P,struct monst *)); -E void FDECL(grease_protect, (struct obj *,const char *,BOOLEAN_P,struct monst *)); +E void FDECL(grease_protect, (struct obj *,const char *,struct monst *)); E struct trap *FDECL(maketrap, (int,int,int)); E void FDECL(fall_through, (BOOLEAN_P)); E struct monst *FDECL(animate_statue, (struct obj *,XCHAR_P,XCHAR_P,int,int *)); E struct monst *FDECL(activate_statue_trap, (struct trap *,XCHAR_P,XCHAR_P,BOOLEAN_P)); -E void FDECL(dotrap, (struct trap *)); +E void FDECL(dotrap, (struct trap *, unsigned)); E void FDECL(seetrap, (struct trap *)); E int FDECL(mintrap, (struct monst *)); E void FDECL(instapetrify, (const char *)); @@ -1879,6 +1954,7 @@ E void FDECL(mselftouch, (struct monst *,const char *,BOOLEAN_P)); E void NDECL(float_up); E void FDECL(fill_pit, (int,int)); E int FDECL(float_down, (long, long)); +E int FDECL(fire_damage, (struct obj *,BOOLEAN_P,BOOLEAN_P,XCHAR_P,XCHAR_P)); E void FDECL(water_damage, (struct obj *,BOOLEAN_P,BOOLEAN_P)); E boolean NDECL(drown); E void FDECL(drain_en, (int)); @@ -1891,6 +1967,7 @@ E struct trap *FDECL(t_at, (int,int)); E void FDECL(b_trapped, (const char *,int)); E boolean NDECL(unconscious); E boolean NDECL(lava_effects); +E void FDECL(blow_up_landmine, (struct trap *)); E int FDECL(launch_obj,(SHORT_P,int,int,int,int,int)); /* ### u_init.c ### */ @@ -1907,6 +1984,7 @@ E boolean FDECL(hmon, (struct monst *,struct obj *,int)); E int FDECL(damageum, (struct monst *,struct attack *)); E void FDECL(missum, (struct monst *,struct attack *)); E int FDECL(passive, (struct monst *,BOOLEAN_P,int,UCHAR_P)); +E void FDECL(passive_obj, (struct monst *,struct obj *,struct attack *)); E void FDECL(stumble_onto_mimic, (struct monst *)); E int FDECL(flash_hits_mon, (struct monst *,struct obj *)); @@ -1933,7 +2011,6 @@ E void VDECL(error, (const char *,...)) PRINTF_F(1,2); /* ### unixunix.c ### */ #ifdef UNIX -E void FDECL(gethdate, (const char *)); E void NDECL(getlock); E void FDECL(regularize, (char *)); # ifdef SHELL @@ -1944,6 +2021,14 @@ E int FDECL(child, (int)); # endif #endif /* UNIX */ +/* ### unixres.c ### */ + +#ifdef UNIX +# ifdef GNOME_GRAPHICS +E int FDECL(hide_privileges, (BOOLEAN_P)); +# endif +#endif /* UNIX */ + /* ### vault.c ### */ E boolean FDECL(grddead, (struct monst *)); @@ -2049,7 +2134,6 @@ E void FDECL(msleep, (unsigned)); /* ### vmsunix.c ### */ -E void FDECL(gethdate, (const char *)); E void NDECL(getlock); E void FDECL(regularize, (char *)); E int NDECL(vms_getuid); @@ -2116,15 +2200,17 @@ E void NDECL(untwoweapon); E void NDECL(uwepgone); E void NDECL(uswapwepgone); E void NDECL(uqwepgone); -E void FDECL(erode_weapon, (struct obj *,BOOLEAN_P)); +E void FDECL(erode_obj, (struct obj *,BOOLEAN_P,BOOLEAN_P)); E int FDECL(chwepon, (struct obj *,int)); E int FDECL(welded, (struct obj *)); E void FDECL(weldmsg, (struct obj *)); +E void FDECL(setmnotwielded, (struct monst *,struct obj *)); /* ### windows.c ### */ E void FDECL(choose_windows, (const char *)); E char FDECL(genl_message_menu, (CHAR_P,int,const char *)); +E void FDECL(genl_preference_update, (const char *)); /* ### wizard.c ### */ @@ -2135,7 +2221,7 @@ E int FDECL(tactics, (struct monst *)); E void NDECL(aggravate); E void NDECL(clonewiz); E int NDECL(pick_nasty); -E void FDECL(nasty, (struct monst*)); +E int FDECL(nasty, (struct monst*)); E void NDECL(resurrect); E void NDECL(intervene); E void NDECL(wizdead); @@ -2164,12 +2250,14 @@ E boolean FDECL(worm_known, (struct monst *)); E void FDECL(setworn, (struct obj *,long)); E void FDECL(setnotworn, (struct obj *)); E void FDECL(mon_set_minvis, (struct monst *)); -E void FDECL(mon_adjust_speed, (struct monst *,int)); +E void FDECL(mon_adjust_speed, (struct monst *,int,struct obj *)); E void FDECL(update_mon_intrinsics, (struct monst *,struct obj *,BOOLEAN_P)); E int FDECL(find_mac, (struct monst *)); E void FDECL(m_dowear, (struct monst *,BOOLEAN_P)); E struct obj *FDECL(which_armor, (struct monst *,long)); -E void FDECL(mon_break_armor, (struct monst *)); +E void FDECL(mon_break_armor, (struct monst *,BOOLEAN_P)); +E void FDECL(bypass_obj, (struct obj *)); +E void NDECL(clear_bypasses); /* ### write.c ### */ @@ -2181,12 +2269,13 @@ E int FDECL(bhitm, (struct monst *,struct obj *)); E void FDECL(probe_monster, (struct monst *)); E boolean FDECL(get_obj_location, (struct obj *,xchar *,xchar *,int)); E boolean FDECL(get_mon_location, (struct monst *,xchar *,xchar *,int)); +E struct monst *FDECL(get_container_location, (struct obj *obj, int *, int *)); E struct monst *FDECL(montraits, (struct obj *,coord *)); E struct monst *FDECL(revive, (struct obj *)); E int FDECL(unturn_dead, (struct monst *)); E void FDECL(cancel_item, (struct obj *)); E boolean FDECL(drain_item, (struct obj *)); -E void FDECL(poly_obj, (struct obj *, int)); +E struct obj *FDECL(poly_obj, (struct obj *, int)); E boolean FDECL(obj_resists, (struct obj *,int,int)); E boolean FDECL(obj_shudders, (struct obj *)); E void FDECL(do_osshock, (struct obj *)); @@ -2206,7 +2295,7 @@ E void FDECL(miss, (const char *,struct monst *)); E struct monst *FDECL(bhit, (int,int,int,int,int (*)(MONST_P,OBJ_P), int (*)(OBJ_P,OBJ_P),struct obj *)); E struct monst *FDECL(boomhit, (int,int)); -E int FDECL(burn_floor_paper, (int,int,BOOLEAN_P)); +E int FDECL(burn_floor_paper, (int,int,BOOLEAN_P,BOOLEAN_P)); E void FDECL(buzz, (int,int,XCHAR_P,XCHAR_P,int,int)); E void FDECL(melt_ice, (XCHAR_P,XCHAR_P)); E int FDECL(zap_over_floor, (XCHAR_P,XCHAR_P,int,boolean *)); diff --git a/include/flag.h b/include/flag.h index b5a4ffe..ddc6070 100644 --- a/include/flag.h +++ b/include/flag.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)flag.h 3.3 2000/01/19 */ +/* SCCS Id: @(#)flag.h 3.4 2000/01/19 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -22,6 +22,7 @@ struct flag { #ifdef MFLOPPY boolean asksavedisk; #endif + boolean autodig; /* MRKR: Automatically dig */ boolean autoquiver; /* Automatically fill quiver */ boolean beginner; #ifdef MAIL @@ -53,6 +54,7 @@ struct flag { boolean mon_moving; /* monsters' turn to move */ boolean move; boolean mv; + boolean bypasses; /* bypass flag is set on at least one fobj */ boolean nap; /* `timed_delay' option for display effects */ boolean nopick; /* do not pickup objects (as when running) */ boolean null; /* OK to send nulls to the terminal */ @@ -74,6 +76,7 @@ struct flag { boolean silent; /* whether the bell rings or not */ boolean sortpack; /* sorted inventory */ boolean soundok; /* ok to tell about sounds heard */ + boolean sparkle; /* show "resisting" special FX (Scott Bigham) */ boolean standout; /* use standout for --More-- */ boolean time; /* display elapsed 'time' */ boolean tombstone; /* print tombstone */ @@ -87,15 +90,23 @@ struct flag { #define NEW_MOON 0 #define FULL_MOON 4 unsigned no_of_wizards; /* 0, 1 or 2 (wizard and his shadow) */ + boolean travel; /* find way automatically to u.tx,u.ty */ unsigned run; /* 0: h (etc), 1: H (etc), 2: fh (etc) */ /* 3: FH, 4: ff+, 5: ff-, 6: FF+, 7: FF- */ + /* 8: travel */ unsigned long warntype; /* warn_of_mon monster type M2 */ int warnlevel; int djinni_count, ghost_count; /* potion effect tuning */ int pickup_burden; /* maximum burden before prompt */ char inv_order[MAXOCLASSES]; char pickup_types[MAXOCLASSES]; - char end_disclose[6]; /* disclose various info upon exit */ +#define NUM_DISCLOSURE_OPTIONS 5 +#define DISCLOSE_PROMPT_DEFAULT_YES 'y' +#define DISCLOSE_PROMPT_DEFAULT_NO 'n' +#define DISCLOSE_YES_WITHOUT_PROMPT '+' +#define DISCLOSE_NO_WITHOUT_PROMPT '-' + char end_disclose[NUM_DISCLOSURE_OPTIONS + 1]; /* disclose various info + upon exit */ char menu_style; /* User interface style setting */ #ifdef AMII_GRAPHICS int numcols; @@ -133,6 +144,7 @@ struct flag { int initrace; /* starting race (index into races[]) */ int initgend; /* starting gender (index into genders[]) */ int initalign; /* starting alignment (index into aligns[]) */ + int randomall; /* randomly assign everything not specified */ int pantheon; /* deity selection for priest character */ }; @@ -146,34 +158,24 @@ struct instance_flags { boolean cbreak; /* in cbreak mode, rogue format */ boolean DECgraphics; /* use DEC VT-xxx extended character set */ boolean echo; /* 1 to echo characters */ -#ifdef TTY_GRAPHICS - boolean eight_bit_tty; /* pass eight-bit characters through to tty */ - boolean extmenu; /* extended commands use menu interface */ -#endif boolean IBMgraphics; /* use IBM extended character set */ unsigned msg_history; /* hint: # of top lines to save */ boolean num_pad; /* use numbers for movement commands */ boolean news; /* print news */ boolean window_inited; /* true if init_nhwindows() completed */ + boolean vision_inited; /* true if vision is ready */ + boolean menu_tab_sep; /* Use tabs to separate option menu fields */ int purge_monsters; /* # of dead monsters still on fmon list */ - + int *opt_booldup; /* for duplication of boolean opts in config file */ + int *opt_compdup; /* for duplication of compound opts in config file */ + uchar bouldersym; /* symbol for boulder display */ #ifdef WIZARD boolean sanity_check; /* run sanity checks */ + boolean mon_polycontrol; /* debug: control monster polymorphs */ #endif -#ifdef TEXTCOLOR - boolean hilite_pet; /* hilight pets on monochome displays */ - boolean use_color; /* use color graphics */ -#endif -#ifdef MAC_GRAPHICS_ENV - boolean large_font; /* draw in larger fonts (say, 12pt instead - of 9pt) */ - boolean MACgraphics; /* use Macintosh extended character set, as - as defined in the special font HackFont */ - unsigned use_stone; /* use the stone ppats */ -#endif -#ifdef MAC - boolean popup_dialog; /* put queries in pop up dialogs instead of - in the message window */ +#ifdef TTY_GRAPHICS + boolean prevmsg_window; /* show more old messages at a time */ + boolean extmenu; /* extended commands use menu interface */ #endif #ifdef MFLOPPY boolean checkspace; /* check disk space before writing files */ @@ -184,30 +186,93 @@ struct instance_flags { boolean BIOS; /* use IBM or ST BIOS calls when appropriate */ boolean rawio; /* whether can use rawio (IOCTL call) */ #endif -#ifdef MSDOS - boolean hasvga; /* has a vga adapter */ - boolean usevga; /* use the vga adapter */ - boolean has8514; - boolean use8514; - boolean hasvesa; - boolean usevesa; - boolean grmode; /* currently in graphics mode */ +#ifdef MAC_GRAPHICS_ENV + boolean MACgraphics; /* use Macintosh extended character set, as + as defined in the special font HackFont */ + unsigned use_stone; /* use the stone ppats */ #endif #if defined(MSDOS) || defined(WIN32) boolean hassound; /* has a sound card */ boolean usesound; /* use the sound card */ boolean usepcspeaker; /* use the pc speaker */ - boolean preload_tiles; /* preload the tiles into RAM */ boolean tile_view; boolean over_view; boolean traditional_view; #endif +#ifdef MSDOS + boolean hasvga; /* has a vga adapter */ + boolean usevga; /* use the vga adapter */ + boolean grmode; /* currently in graphics mode */ +#endif #ifdef LAN_FEATURES boolean lan_mail; /* mail is initialized */ boolean lan_mail_fetched; /* mail is awaiting display */ #endif +/* + * Window capability support. + */ + boolean wc_color; /* use color graphics */ + boolean wc_hilite_pet; /* hilight pets */ + boolean wc_ascii_map; /* show map using traditional ascii */ + boolean wc_tiled_map; /* show map using tiles */ + boolean wc_preload_tiles; /* preload tiles into memory */ + int wc_tile_width; /* tile width */ + int wc_tile_height; /* tile height */ + char *wc_tile_file; /* name of tile file;overrides default */ + boolean wc_inverse; /* use inverse video for some things */ + int wc_align_status; /* status win at top|bot|right|left */ + int wc_align_message; /* message win at top|bot|right|left */ + int wc_vary_msgcount; /* show more old messages at a time */ + char *wc_foregrnd_menu; /* points to foregrnd color name for menu win */ + char *wc_backgrnd_menu; /* points to backgrnd color name for menu win */ + char *wc_foregrnd_message; /* points to foregrnd color name for msg win */ + char *wc_backgrnd_message; /* points to backgrnd color name for msg win */ + char *wc_foregrnd_status; /* points to foregrnd color name for status win */ + char *wc_backgrnd_status; /* points to backgrnd color name for status win */ + char *wc_foregrnd_text; /* points to foregrnd color name for text win */ + char *wc_backgrnd_text; /* points to backgrnd color name for text win */ + char *wc_font_map; /* points to font name for the map win */ + char *wc_font_message; /* points to font name for message win */ + char *wc_font_status; /* points to font name for status win */ + char *wc_font_menu; /* points to font name for menu win */ + char *wc_font_text; /* points to font name for text win */ + int wc_fontsiz_map; /* font size for the map win */ + int wc_fontsiz_message; /* font size for the message window */ + int wc_fontsiz_status; /* font size for the status window */ + int wc_fontsiz_menu; /* font size for the menu window */ + int wc_fontsiz_text; /* font size for text windows */ + int wc_scroll_margin; /* scroll map when this far from + the edge */ + int wc_map_mode; /* specify map viewing options, mostly + for backward compatibility */ + int wc_player_selection; /* method of choosing character */ + boolean wc_splash_screen; /* display an opening splash screen or not */ + boolean wc_popup_dialog; /* put queries in pop up dialogs instead of + in the message window */ + boolean wc_large_font; /* draw in larger fonts (say, 12pt instead + of 9pt) */ + boolean wc_eight_bit_input; /* allow eight bit input */ }; +/* + * Old deprecated names + */ +#ifdef TTY_GRAPHICS +#define eight_bit_tty wc_eight_bit_input +#endif +#ifdef TEXTCOLOR +#define use_color wc_color +#endif +#define hilite_pet wc_hilite_pet +#define use_inverse wc_inverse +#ifdef MAC_GRAPHICS_ENV +#define large_font wc_large_font +#endif +#ifdef MAC +#define popup_dialog wc_popup_dialog +#endif +#define preload_tiles wc_preload_tiles + extern NEARDATA struct flag flags; extern NEARDATA struct instance_flags iflags; diff --git a/include/func_tab.h b/include/func_tab.h index 1418674..769801d 100644 --- a/include/func_tab.h +++ b/include/func_tab.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)func_tab.h 3.3 92/04/03 */ +/* SCCS Id: @(#)func_tab.h 3.4 1992/04/03 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/global.h b/include/global.h index fb79a7d..f21f02a 100644 --- a/include/global.h +++ b/include/global.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)global.h 3.3 99/07/02 */ +/* SCCS Id: @(#)global.h 3.4 2002/03/12 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -8,7 +8,7 @@ #include -/*#define BETA */ /* if a beta-test copy [MRS] */ +/* #define BETA */ /* if a beta-test copy [MRS] */ /* * Files expected to exist in the playground directory. @@ -215,7 +215,12 @@ typedef xchar boolean; /* 0 or 1 */ # define PORT_ID "VMS" # endif # ifdef WIN32 -# define PORT_ID "NT" +# define PORT_ID "Windows" +# ifdef MSWIN_GRAPHICS +# define PORT_SUB_ID "graphical" +# else +# define PORT_SUB_ID "tty" +# endif # endif #endif @@ -246,7 +251,7 @@ typedef xchar boolean; /* 0 or 1 */ # define EXIT_FAILURE 1 #endif -#if defined(X11_GRAPHICS) || defined(QT_GRAPHICS) || defined(GNOME_GRAPHICS) +#if defined(X11_GRAPHICS) || defined(QT_GRAPHICS) || defined(GNOME_GRAPHICS) || defined(MSWIN_GRAPHICS) # ifndef USE_TILES # define USE_TILES /* glyph2tile[] will be available */ # endif diff --git a/include/hack.h b/include/hack.h index 2f76ea4..6529f4f 100644 --- a/include/hack.h +++ b/include/hack.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)hack.h 3.3 2000/01/28 */ +/* SCCS Id: @(#)hack.h 3.4 2001/04/12 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -43,9 +43,22 @@ #define DISMOUNT_THROWN 2 #define DISMOUNT_POLY 3 #define DISMOUNT_ENGULFED 4 -#define DISMOUNT_BYCHOICE 5 +#define DISMOUNT_BONES 5 +#define DISMOUNT_BYCHOICE 6 #endif +/* Special returns from mapglyph() */ +#define MG_CORPSE 0x01 +#define MG_INVIS 0x02 +#define MG_DETECT 0x04 +#define MG_PET 0x08 +#define MG_RIDDEN 0x10 + +/* sellobj_state() states */ +#define SELL_NORMAL (0) +#define SELL_DELIBERATE (1) +#define SELL_DONTSELL (2) + /* * This is the way the game ends. If these are rearranged, the arrays * in end.c and topten.c will need to be changed. Some parts of the @@ -125,6 +138,10 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */ #define MM_EMIN 0x08 /* add emin structure */ #define MM_ANGRY 0x10 /* monster is created angry */ #define MM_NONAME 0x20 /* monster is not christened */ +#define MM_NOCOUNTBIRTH 0x40 /* don't increment born counter (for revival) */ + +/* flags for special ggetobj status returns */ +#define ALL_FINISHED 0x01 /* called routine already finished the job */ /* flags to control query_objlist() */ #define BY_NEXTHERE 0x1 /* follow objlist by nexthere field */ @@ -141,6 +158,11 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */ #define ALL_TYPES 0x10 #define BILLED_TYPES 0x20 #define CHOOSE_ALL 0x40 +#define BUC_BLESSED 0x80 +#define BUC_CURSED 0x100 +#define BUC_UNCURSED 0x200 +#define BUC_UNKNOWN 0x400 +#define BUC_ALLBKNOWN (BUC_BLESSED|BUC_CURSED|BUC_UNCURSED) #define ALL_TYPES_SELECTED -2 /* Flags to control find_mid() */ @@ -149,6 +171,13 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */ #define FM_MYDOGS 0x04 /* search mydogs */ #define FM_EVERYWHERE (FM_FMON | FM_MIGRATE | FM_MYDOGS) +/* Flags to control pick_[race,role,gend,align] routines in role.c */ +#define PICK_RANDOM 0 +#define PICK_RIGID 1 + +/* Flags to control dotrap() in trap.c */ +#define NOWEBMSG 0x01 /* suppress stumble into web message */ + /*** some utility macros ***/ #define yn(query) yn_function(query,ynchars, 'n') #define ynq(query) yn_function(query,ynqchars, 'q') @@ -169,6 +198,16 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */ #define ROLL 1 #define FLING 2 +/* Macros for explosion types */ +#define EXPL_DARK 0 +#define EXPL_NOXIOUS 1 +#define EXPL_MUDDY 2 +#define EXPL_WET 3 +#define EXPL_MAGICAL 4 +#define EXPL_FIERY 5 +#define EXPL_FROSTY 6 +#define EXPL_MAX 7 + /* Macros for messages referring to hands, eyes, feet, etc... */ #define ARM 0 #define EYE 1 @@ -187,6 +226,8 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */ #define HAIR 14 #define BLOOD 15 #define LUNG 16 +#define NOSE 17 +#define STOMACH 18 /* Flags to control menus */ #define MENUTYPELEN sizeof("traditional ") @@ -198,6 +239,16 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */ #define MENU_SELECTED TRUE #define MENU_UNSELECTED FALSE +/* + * Option flags + * Each higher number includes the characteristics of the numbers + * below it. + */ +#define SET_IN_FILE 0 /* config file option only */ +#define SET_VIA_PROG 1 /* may be set via extern program, not seen in game */ +#define DISP_IN_GAME 2 /* may be set via extern program, displayed in game */ +#define SET_IN_GAME 3 /* may be set via extern program or set in the game */ + #define FEATURE_NOTICE_VER(major,minor,patch) (((unsigned long)major << 24) | \ ((unsigned long)minor << 16) | \ ((unsigned long)patch << 8) | \ diff --git a/include/lev.h b/include/lev.h index 1554c9f..afc845a 100644 --- a/include/lev.h +++ b/include/lev.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)lev.h 3.3 94/03/18 */ +/* SCCS Id: @(#)lev.h 3.4 1994/03/18 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -15,4 +15,35 @@ #define perform_bwrite(mode) ((mode) & (COUNT_SAVE|WRITE_SAVE)) #define release_data(mode) ((mode) & FREE_SAVE) +/* The following are used in mkmaze.c */ +struct container { + struct container *next; + xchar x, y; + short what; + genericptr_t list; +}; + +#define CONS_OBJ 0 +#define CONS_MON 1 +#define CONS_HERO 2 +#define CONS_TRAP 3 + +struct bubble { + xchar x, y; /* coordinates of the upper left corner */ + schar dx, dy; /* the general direction of the bubble's movement */ + uchar *bm; /* pointer to the bubble bit mask */ + struct bubble *prev, *next; /* need to traverse the list up and down */ + struct container *cons; +}; + +/* used in light.c */ +typedef struct ls_t { + struct ls_t *next; + xchar x, y; /* source's position */ + short range; /* source's current range */ + short flags; + short type; /* type of light source */ + genericptr_t id; /* source's identifier */ +} light_source; + #endif /* LEV_H */ diff --git a/include/macconf.h b/include/macconf.h index 618aaf6..7332a0a 100644 --- a/include/macconf.h +++ b/include/macconf.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)macconf.h 3.3 99/10/25 */ +/* SCCS Id: @(#)macconf.h 3.4 1999/10/25 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -9,9 +9,10 @@ /* * Compiler selection is based on the following symbols: * - * applec MPW compiler + * __SC__ sc, a MPW 68k compiler + * __MRC__ mrc, a MPW PowerPC compiler * THINK_C Think C compiler - * __MWERKS__ Metrowerks compiler + * __MWERKS__ Metrowerks' Codewarrior compiler * * We use these early in config.h to define some needed symbols, * including MAC. @@ -20,21 +21,18 @@ # WIDENED_PROTOTYPES (defined if UNWIDENED_PROTOTYPES is undefined and # NHSTDC is defined). */ -# ifdef applec -# define MAC_MPW32 /* Headers, and for avoiding a bug */ -# endif -# ifndef __powerc -# define MAC68K /* 68K mac (non-powerpc) */ -# endif +#ifndef __powerc +# define MAC68K /* 68K mac (non-powerpc) */ +#endif -# define RANDOM -# define NO_SIGNAL /* You wouldn't believe our signals ... */ -# define FILENAME 256 -# define NO_TERMS /* For tty port (see wintty.h) */ +#define RANDOM +#define NO_SIGNAL /* You wouldn't believe our signals ... */ +#define FILENAME 256 +#define NO_TERMS /* For tty port (see wintty.h) */ -# define TEXTCOLOR /* For Mac TTY interface */ -# define CHANGE_COLOR +#define TEXTCOLOR /* For Mac TTY interface */ +#define CHANGE_COLOR /* Use these two includes instead of system.h. */ #include @@ -42,61 +40,50 @@ /* Uncomment this line if your headers don't already define off_t */ /*typedef long off_t;*/ +#include /* for time_t */ /* * Try and keep the number of files here to an ABSOLUTE minimum ! * include the relevant files in the relevant .c files instead ! */ #include -/* - * Turn off the Macsbug calls for the production version. - */ -#if 0 -# undef Debugger -# undef DebugStr -# define Debugger() -# define DebugStr(aStr) -#endif /* * We could use the PSN under sys 7 here ... + * ...but it wouldn't matter... */ -#ifndef __CONDITIONALMACROS__ /* universal headers */ -# define getpid() 1 -# define getuid() 1 -#endif -# define index strchr -# define rindex strrchr +#define getpid() 1 +#define getuid() 1 +#define index strchr +#define rindex strrchr -# define Rand random +#define Rand random extern void error(const char *,...); -# if !defined(O_WRONLY) -# ifdef __MWERKS__ -#include -# ifndef O_EXCL - /* MW 4.5 doesn't have this, so just use a bogus value */ -# define O_EXCL 0x80000000 -# endif -# else -#include -# endif +#if !defined(O_WRONLY) +# ifdef __MWERKS__ +# include # endif +# include +#endif /* * Don't redefine these Unix IO functions when making LevComp or DgnComp for * MPW. With MPW, we make them into MPW tools, which use unix IO. SPEC_LEV * and DGN_COMP are defined when compiling for LevComp and DgnComp respectively. */ -#if !(defined(applec) && (defined(SPEC_LEV) || defined(DGN_COMP))) +#if !((defined(__SC__) || defined(__MRC__)) && (defined(SPEC_LEV) || defined(DGN_COMP))) # define creat maccreat # define open macopen # define close macclose # define read macread # define write macwrite # define lseek macseek +# define unlink _unlink #endif +#define YY_NEVER_INTERACTIVE + # define TEXT_TYPE 'TEXT' # define LEVL_TYPE 'LEVL' # define BONE_TYPE 'BONE' @@ -104,6 +91,7 @@ extern void error(const char *,...); # define PREF_TYPE 'PREF' # define DATA_TYPE 'DATA' # define MAC_CREATOR 'nh31' /* Registered with DTS ! */ +# define TEXT_CREATOR 'ttxt' /* Something the user can actually edit */ /* * Define PORT_HELP to be the name of the port-specfic help file. diff --git a/include/macpopup.h b/include/macpopup.h index 3b9eecb..7565fb4 100644 --- a/include/macpopup.h +++ b/include/macpopup.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)macpopup.h 3.3 99/10/25 */ +/* SCCS Id: @(#)macpopup.h 3.4 1999/10/25 */ /* Copyright (c) Nethack Develpment Team, 1999. */ /* NetHack may be freely redistributed. See license for details. */ @@ -12,11 +12,4 @@ extern char queued_resp(char *resp); extern char topl_yn_function(const char *query, const char *resp, char def); extern int get_line_from_key_queue(char *bufp); -#define ENABLE_MAC_POPUP 0 -#if ENABLE_MAC_POPUP - -extern char popup_yn_function(const char *query, const char *resp, char def); -extern void popup_getlin (const char *query, char *bufp); - -#endif /* ENABLE_MAC_POPUP */ #endif /* MACPOPUP_H */ diff --git a/include/mactty.h b/include/mactty.h index 50f204d..146ed4e 100644 --- a/include/mactty.h +++ b/include/mactty.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mactty.h 3.3 93/03/01 */ +/* SCCS Id: @(#)mactty.h 3.4 1993/03/01 */ /* Copyright (c) Jon W{tte 1993. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/macwin.h b/include/macwin.h index c402ab8..aa9cb16 100644 --- a/include/macwin.h +++ b/include/macwin.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)macwin.h 3.3 96/01/15 */ +/* SCCS Id: @(#)macwin.h 3.4 1996/01/15 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/mail.h b/include/mail.h index 5c782d8..daa8b30 100644 --- a/include/mail.h +++ b/include/mail.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mail.h 3.3 91/10/11 */ +/* SCCS Id: @(#)mail.h 3.4 1991/10/11 */ /* NetHack may be freely redistributed. See license for details. */ /* used by ckmailstatus() to pass information to the mail-daemon in newmail() */ diff --git a/include/mfndpos.h b/include/mfndpos.h index f4d407a..96c5dd5 100644 --- a/include/mfndpos.h +++ b/include/mfndpos.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mfndpos.h 3.3 93/05/15 */ +/* SCCS Id: @(#)mfndpos.h 3.4 1993/05/15 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/micro.h b/include/micro.h index 0947a39..7d5e90f 100644 --- a/include/micro.h +++ b/include/micro.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)micro.h 3.3 90/02/22 */ +/* SCCS Id: @(#)micro.h 3.4 1990/02/22 */ /* micro.h - function declarations for various microcomputers */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/mkroom.h b/include/mkroom.h index c8ad0a4..72bd504 100644 --- a/include/mkroom.h +++ b/include/mkroom.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mkroom.h 3.3 92/11/14 */ +/* SCCS Id: @(#)mkroom.h 3.4 1992/11/14 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/monattk.h b/include/monattk.h index baaa7cf..996a765 100644 --- a/include/monattk.h +++ b/include/monattk.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)monattk.h 3.3 95/01/28 */ +/* SCCS Id: @(#)monattk.h 3.4 1995/01/28 */ /* NetHack may be freely redistributed. See license for details. */ /* Copyright 1988, M. Stephenson */ @@ -75,7 +75,7 @@ #define AD_FAMN 39 /* for Famine only */ #define AD_SLIM 40 /* turns you into green slime */ #define AD_ENCH 41 /* remove enchantment (disenchanter) */ -#define AD_CORRODE 42 /* corrode armor (black pudding) */ +#define AD_CORR 42 /* corrode armor (black pudding) */ #define AD_CLRC 240 /* random clerical spell */ #define AD_SPEL 241 /* random magic spell */ diff --git a/include/mondata.h b/include/mondata.h index 81fb91a..457ccf5 100644 --- a/include/mondata.h +++ b/include/mondata.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mondata.h 3.3 2000/07/14 */ +/* SCCS Id: @(#)mondata.h 3.4 2001/02/14 */ /* Copyright (c) 1989 Mike Threepoint */ /* NetHack may be freely redistributed. See license for details. */ @@ -33,12 +33,16 @@ #define hides_under(ptr) (((ptr)->mflags1 & M1_CONCEAL) != 0L) #define is_hider(ptr) (((ptr)->mflags1 & M1_HIDE) != 0L) #define haseyes(ptr) (((ptr)->mflags1 & M1_NOEYES) == 0L) +#define eyecount(ptr) (!haseyes(ptr) ? 0 : \ + ((ptr) == &mons[PM_CYCLOPS] || \ + (ptr) == &mons[PM_FLOATING_EYE]) ? 1 : 2) #define nohands(ptr) (((ptr)->mflags1 & M1_NOHANDS) != 0L) #define nolimbs(ptr) (((ptr)->mflags1 & M1_NOLIMBS) == M1_NOLIMBS) #define notake(ptr) (((ptr)->mflags1 & M1_NOTAKE) != 0L) #define has_head(ptr) (((ptr)->mflags1 & M1_NOHEAD) == 0L) #define is_whirly(ptr) ((ptr)->mlet == S_VORTEX || \ (ptr) == &mons[PM_AIR_ELEMENTAL]) +#define is_silent(ptr) ((ptr)->msound == MS_SILENT) #define unsolid(ptr) (((ptr)->mflags1 & M1_UNSOLID) != 0L) #define mindless(ptr) (((ptr)->mflags1 & M1_MINDLESS) != 0L) #define humanoid(ptr) (((ptr)->mflags1 & M1_HUMANOID) != 0L) @@ -90,6 +94,7 @@ #define strongmonst(ptr) (((ptr)->mflags2 & M2_STRONG) != 0L) #define can_breathe(ptr) attacktype(ptr, AT_BREA) #define cantwield(ptr) (nohands(ptr) || verysmall(ptr)) +#define could_twoweap(ptr) ((ptr)->mattk[1].aatyp == AT_WEAP) #define cantweararm(ptr) (breakarm(ptr) || sliparm(ptr)) #define throws_rocks(ptr) (((ptr)->mflags2 & M2_ROCKTHROW) != 0L) #define type_is_pname(ptr) (((ptr)->mflags2 & M2_PNAME) != 0L) @@ -125,6 +130,9 @@ (ptr) == &mons[PM_GIANT] || \ (ptr) == &mons[PM_ELF] || \ (ptr) == &mons[PM_HUMAN]) +/* return TRUE if the monster tends to revive */ +#define is_reviver(ptr) (is_rider(ptr) || (ptr)->mlet == S_TROLL) + /* this returns the light's range, or 0 if none; if we add more light emitting monsters, we'll likely have to add a new light range field to mons[] */ #define emits_light(ptr) (((ptr)->mlet == S_LIGHT || \ @@ -149,7 +157,8 @@ #define is_mind_flayer(ptr) ((ptr) == &mons[PM_MIND_FLAYER] || \ (ptr) == &mons[PM_MASTER_MIND_FLAYER]) -#define nonliving(ptr) (is_golem(ptr) || is_undead(ptr)) +#define nonliving(ptr) (is_golem(ptr) || is_undead(ptr) || \ + (ptr)->mlet == S_VORTEX) /* Used for conduct with corpses, tins, and digestion attacks */ /* G_NOCORPSE monsters might still be swallowed as a purple worm */ @@ -169,4 +178,7 @@ ((ptr)->mlet == S_PUDDING && \ (ptr) != &mons[PM_BLACK_PUDDING])) +#define befriend_with_obj(ptr, obj) ((obj)->oclass == FOOD_CLASS && \ + is_domestic(ptr)) + #endif /* MONDATA_H */ diff --git a/include/monflag.h b/include/monflag.h index 0d0b025..8ea8c15 100644 --- a/include/monflag.h +++ b/include/monflag.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)monflag.h 3.3 96/05/04 */ +/* SCCS Id: @(#)monflag.h 3.4 1996/05/04 */ /* Copyright (c) 1989 Mike Threepoint */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/monst.h b/include/monst.h index 0d0bb5d..c7de88f 100644 --- a/include/monst.h +++ b/include/monst.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)monst.h 3.3 99/01/04 */ +/* SCCS Id: @(#)monst.h 3.4 1999/01/04 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -83,7 +83,7 @@ struct monst { Bitfield(mspeed,2); /* current speed */ Bitfield(permspeed,2); /* intrinsic mspeed value */ Bitfield(mrevived,1); /* has been revived from the dead */ - Bitfield(not_used,1); /*** available ***/ + Bitfield(mavenge,1); /* did something to deserve retaliation */ Bitfield(mflee,1); /* fleeing */ Bitfield(mfleetim,7); /* timeout for mflee */ @@ -128,7 +128,9 @@ struct monst { long mtrapseen; /* bitmap of traps we've been trapped in */ long mlstmv; /* for catching up with lost time */ +#ifndef GOLDOBJ long mgold; +#endif struct obj *minvent; struct obj *mw; diff --git a/include/monsym.h b/include/monsym.h index 152f75c..7bf393c 100644 --- a/include/monsym.h +++ b/include/monsym.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)monsym.h 3.3 92/10/18 */ +/* SCCS Id: @(#)monsym.h 3.4 1992/10/18 */ /* Monster symbols and creation information rev 1.0 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/mttypriv.h b/include/mttypriv.h index 48c6c93..83ce114 100644 --- a/include/mttypriv.h +++ b/include/mttypriv.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mttypriv.h 3.3 93/03/01 */ +/* SCCS Id: @(#)mttypriv.h 3.4 1993/03/01 */ /* Copyright (c) Jon W{tte 1993. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/nhlan.h b/include/nhlan.h index 6790214..1cb9bf1 100644 --- a/include/nhlan.h +++ b/include/nhlan.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)nhlan.h 3.3 97/04/12 */ +/* SCCS Id: @(#)nhlan.h 3.4 1997/04/12 */ /* Copyright (c) Michael Allison, 1997 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/ntconf.h b/include/ntconf.h index f7f5e3a..4d84871 100644 --- a/include/ntconf.h +++ b/include/ntconf.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)ntconf.h 3.3 96/10/14 */ +/* SCCS Id: @(#)ntconf.h 3.4 2002/03/10 */ /* Copyright (c) NetHack PC Development Team 1993, 1994. */ /* NetHack may be freely redistributed. See license for details. */ @@ -8,15 +8,12 @@ /* #define SHELL /* nt use of pcsys routines caused a hang */ #define RANDOM /* have Berkeley random(3) */ - #define TEXTCOLOR /* Color text */ -#define PATHLEN 64 /* maximum pathlength */ -#define FILENAME 80 /* maximum filename length (conservative) */ #define EXEPATH /* Allow .exe location to be used as HACKDIR */ #define TRADITIONAL_GLYPHMAP /* Store glyph mappings at level change time */ #ifdef WIN32CON -#define LAN_FEATURES /* Include code for lan-aware features. */ +#define LAN_FEATURES /* Include code for lan-aware features. Untested in 3.4.0*/ #endif #define PC_LOCKING /* Prevent overwrites of aborted or in-progress games */ @@ -36,6 +33,18 @@ #define NO_TERMS #define ASCIIGRAPH +#ifdef OPTIONS_USED +#undef OPTIONS_USED +#endif +#ifdef MSWIN_GRAPHICS +#define OPTIONS_USED "guioptions" +#else +#define OPTIONS_USED "ttyoptions" +#endif +#define OPTIONS_FILE OPTIONS_USED + +#define PORT_HELP "porthelp" + /* The following is needed for prototypes of certain functions */ #if defined(_MSC_VER) #include /* Provides prototypes of exit(), spawn() */ @@ -48,6 +57,23 @@ #include #include +#ifdef __BORLANDC__ +#undef randomize +#undef random +#endif + +#define PATHLEN BUFSZ /* maximum pathlength */ +#define FILENAME BUFSZ /* maximum filename length (conservative) */ + +#if defined(_MAX_PATH) && defined(_MAX_FNAME) +# if (_MAX_PATH < BUFSZ) && (_MAX_FNAME < BUFSZ) +#undef PATHLEN +#undef FILENAME +#define PATHLEN _MAX_PATH +#define FILENAME _MAX_FNAME +# endif +#endif + #define NO_SIGNAL #define index strchr @@ -85,8 +111,20 @@ #endif #include +#ifndef __BORLANDC__ #include #include +#else +int _RTLENTRY _EXPFUNC _chdrive(int __drive); +int _RTLENTRYF _EXPFUNC32 chdir( const char _FAR *__path ); +char _FAR * _RTLENTRY _EXPFUNC getcwd( char _FAR *__buf, int __buflen ); +int _RTLENTRY _EXPFUNC write (int __handle, const void _FAR *__buf, unsigned __len); +int _RTLENTRY _EXPFUNC creat (const char _FAR *__path, int __amode); +int _RTLENTRY _EXPFUNC close (int __handle); +int _RTLENTRY _EXPFUNC open (const char _FAR *__path, int __access,... /*unsigned mode*/); +long _RTLENTRY _EXPFUNC lseek (int __handle, long __offset, int __fromwhere); +int _RTLENTRY _EXPFUNC read (int __handle, void _FAR *__buf, unsigned __len); +#endif #include #undef kbhit /* Use our special NT kbhit */ #define kbhit (*nt_kbhit) @@ -118,4 +156,6 @@ #endif #endif +extern int FDECL(set_win32_option, (const char *, const char *)); + #endif /* NTCONF_H */ diff --git a/include/obj.h b/include/obj.h index 1157e0f..e118b1d 100644 --- a/include/obj.h +++ b/include/obj.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)obj.h 3.3 1999/12/13 */ +/* SCCS Id: @(#)obj.h 3.4 2002/01/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -65,6 +65,7 @@ struct obj { #define MAX_ERODE 3 #define orotten oeroded /* rotten food */ #define odiluted oeroded /* diluted potions */ +#define norevive oeroded2 Bitfield(oerodeproof,1); /* erodeproof weapon/armor */ Bitfield(olocked,1); /* object is locked */ Bitfield(obroken,1); /* lock has been broken */ @@ -84,7 +85,8 @@ struct obj { #define OATTACHED_UNUSED3 3 Bitfield(in_use,1); /* for magic items before useup items */ - /* 7 free bits */ + Bitfield(bypass,1); /* mark this as an object to be skipped by bhito() */ + /* 6 free bits */ int corpsenm; /* type of corpse is mons[corpsenm] */ #define leashmon corpsenm /* gets m_id of attached pet */ @@ -197,11 +199,41 @@ struct obj { #define Is_mbag(otmp) (otmp->otyp == BAG_OF_HOLDING || \ otmp->otyp == BAG_OF_TRICKS) +/* dragon gear */ +#define Is_dragon_scales(obj) ((obj)->otyp >= GRAY_DRAGON_SCALES && \ + (obj)->otyp <= YELLOW_DRAGON_SCALES) +#define Is_dragon_mail(obj) ((obj)->otyp >= GRAY_DRAGON_SCALE_MAIL && \ + (obj)->otyp <= YELLOW_DRAGON_SCALE_MAIL) +#define Is_dragon_armor(obj) (Is_dragon_scales(obj) || Is_dragon_mail(obj)) +#define Dragon_scales_to_pm(obj) &mons[PM_GRAY_DRAGON + (obj)->otyp \ + - GRAY_DRAGON_SCALES] +#define Dragon_mail_to_pm(obj) &mons[PM_GRAY_DRAGON + (obj)->otyp \ + - GRAY_DRAGON_SCALE_MAIL] +#define Dragon_to_scales(pm) (GRAY_DRAGON_SCALES + (pm - mons)) + /* Light sources */ #define Is_candle(otmp) (otmp->otyp == TALLOW_CANDLE || \ otmp->otyp == WAX_CANDLE) #define MAX_OIL_IN_FLASK 400 /* maximum amount of oil in a potion of oil */ +/* special stones */ +#define is_graystone(obj) ((obj)->otyp == LUCKSTONE || \ + (obj)->otyp == LOADSTONE || \ + (obj)->otyp == FLINT || \ + (obj)->otyp == TOUCHSTONE) + +/* misc */ +#ifdef KOPS +#define is_flimsy(otmp) (objects[(otmp)->otyp].oc_material <= LEATHER || \ + (otmp)->otyp == RUBBER_HOSE) +#else +#define is_flimsy(otmp) (objects[(otmp)->otyp].oc_material <= LEATHER) +#endif + +/* helpers, simple enough to be macros */ +#define is_plural(o) ((o)->quan > 1 || \ + (o)->oartifact == ART_EYES_OF_THE_OVERWORLD) + /* Flags for get_obj_location(). */ #define CONTAINED_TOO 0x1 #define BURIED_TOO 0x2 diff --git a/include/objclass.h b/include/objclass.h index a052068..c5cff43 100644 --- a/include/objclass.h +++ b/include/objclass.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)objclass.h 3.3 96/06/16 */ +/* SCCS Id: @(#)objclass.h 3.4 1996/06/16 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -68,14 +68,14 @@ struct objclass { objects[otmp->otyp].oc_material <= MITHRIL) /* primary damage: fire/rust/--- */ -/* is_flammable() in mkobj.c */ +/* is_flammable(otmp), is_rottable(otmp) in mkobj.c */ #define is_rustprone(otmp) (objects[otmp->otyp].oc_material == IRON) /* secondary damage: rot/acid/acid */ -#define is_rottable(otmp) is_flammable(otmp) /* we might want to change this */ #define is_corrodeable(otmp) (objects[otmp->otyp].oc_material == COPPER || objects[otmp->otyp].oc_material == IRON) -#define is_damageable(otmp) (is_rustprone(otmp) || is_flammable(otmp) || is_corrodeable(otmp)) +#define is_damageable(otmp) (is_rustprone(otmp) || is_flammable(otmp) || \ + is_rottable || is_corrodeable(otmp)) schar oc_subtyp; #define oc_skill oc_subtyp /* Skills of weapons, spellbooks, tools, gems */ @@ -91,9 +91,8 @@ struct objclass { uchar oc_oprop; /* property (invis, &c.) conveyed */ char oc_class; /* object class */ schar oc_delay; /* delay when using such an object */ -#ifdef TEXTCOLOR - uchar oc_color; /* display color of the object */ -#endif /* TEXTCOLOR */ + uchar oc_color; /* color of the object */ + short oc_prob; /* probability, used in mkobj() */ unsigned short oc_weight; /* encumbrance (1 cn = 0.1 lb.) */ short oc_cost; /* base cost in shops */ diff --git a/include/os2conf.h b/include/os2conf.h index 65163c3..b706df1 100644 --- a/include/os2conf.h +++ b/include/os2conf.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)os2conf.h 3.3 96/10/29 */ +/* SCCS Id: @(#)os2conf.h 3.4 1996/10/29 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Timo Hakulinen, 1990, 1991, 1992, 1993, 1996. */ /* NetHack may be freely redistributed. See license for details. */ @@ -13,7 +13,7 @@ */ /* #define OS2_MSC /* Microsoft C 5.1 and 6.0 */ -/* #define OS2_GCC /* GCC emx 0.8f */ +#define OS2_GCC /* GCC emx 0.8f */ /* #define OS2_CSET2 /* IBM C Set/2 (courtesy Jeff Urlwin) */ /* #define OS2_CSET2_VER_1 /* CSet/2 version selection */ /* #define OS2_CSET2_VER_2 /* - " - */ @@ -34,7 +34,7 @@ * reason to touch the defaults, I think. */ -#define MFLOPPY /* floppy and ramdisk support */ +/*#define MFLOPPY /* floppy and ramdisk support */ #define RANDOM /* Berkeley random(3) */ #define SHELL /* shell escape */ /* #define TERMLIB /* use termcap file */ diff --git a/include/patchlevel.h b/include/patchlevel.h index de40e81..1f5d55a 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -1,14 +1,14 @@ -/* SCCS Id: @(#)patchlevel.h 3.3 2000/07/22 */ +/* SCCS Id: @(#)patchlevel.h 3.4 2002/03/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ -/* NetHack 3.3.1 */ +/* NetHack 3.4.0 */ #define VERSION_MAJOR 3 -#define VERSION_MINOR 3 +#define VERSION_MINOR 4 /* * PATCHLEVEL is updated for each release. */ -#define PATCHLEVEL 1 +#define PATCHLEVEL 0 /* * Incrementing EDITLEVEL can be used to force invalidation of old bones * and save files. @@ -16,7 +16,7 @@ #define EDITLEVEL 0 #define COPYRIGHT_BANNER_A \ -"NetHack, Copyright 1985-2000" +"NetHack, Copyright 1985-2002" #define COPYRIGHT_BANNER_B \ " By Stichting Mathematisch Centrum and M. Stephenson." @@ -34,11 +34,41 @@ * PP = patch level, ee = edit level, L = literal suffix "L", * with all four numbers specified as two hexadecimal digits. */ -#define VERSION_COMPATIBILITY 0x03030000L +#define VERSION_COMPATIBILITY 0x03030100L #endif /*****************************************************************************/ -/* Version 3.3.1 */ +/* Version 3.4.0 */ + +/* + * NetHack 3.4.0, March 20, 2002 + * + * Hundreds of general bug fixes including some for sliming, zapping, conduct, + * and several more for riding + * Eliminated a few potentially fatal bugs including one for stone-to-flesh, + * trouble-fixing during prayer, riding down stairs while punished, + * polyd player demon summoning, throwing digging tools into shops, and + * a couple from having the vision system enabled at inappropriate times + * Corrected some incorrect calculations in final scoring + * Enhanced config file processing and alert to duplication of entries + * Player selection prompt enhancements for TTY and X11 + * Objects merge in containers + * Wish for "nothing", and genocide "none" to preserve your conduct + * Changes to Wizard quest + * Added the travel command which works by mouse click or '_' command + * Config file BOULDER option to specify the symbol for displaying boulders + * Incorporate modified versions of several 3.3.1 patches that have been + * in circulation in the NetHack community + * New Gnomish Mines levels (courtesy Kelly Bailey) + * Mac: command-key shortcuts in the player selection dialog + * Amiga: screenmode requester, and several amiga specific bug fixes + * Win32 graphical port contributed by Alex Kompel is now included + */ + +/* Version 3.4 */ + +/*****************************************************************************/ +/* Version 3.3.x */ /* Patch 1, August 9, 2000 * Many, many general fixes, including a number for riding, twoweapon, @@ -75,10 +105,11 @@ * updated COPYRIGHT_BANNER_A to reflect year of release. * Dozens of other bug fixes, and minor improvements. */ + /* Version 3.3 */ /*****************************************************************************/ -/* Version 3.2.3 */ +/* Version 3.2.x */ /* Patch 3, December 10, 1999 * Released simultaneously with 3.3.0 for the benefit of diff --git a/include/pcconf.h b/include/pcconf.h index 36d6be9..59c3fc3 100644 --- a/include/pcconf.h +++ b/include/pcconf.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pcconf.h 3.3 95/10/11 */ +/* SCCS Id: @(#)pcconf.h 3.4 1995/10/11 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -17,7 +17,7 @@ * _MSC_VER is defined automatically by Microsoft C. * __BORLANDC__ is defined automatically by Borland C. * __SC__ is defined automatically by Symantec C. - * Note: 3.3.0 was not verified with Symantec C. + * Note: 3.4.0 was not verified with Symantec C. */ /* @@ -29,7 +29,7 @@ * For pre-V7.0 Microsoft Compilers only, manually define OVERLAY here. */ -/*#define OVERLAY /* Manual overlay definition (MSC 6.0ax only) */ +/*#define OVERLAY */ /* Manual overlay definition (MSC 6.0ax only) */ # ifndef __GO32__ #define MFLOPPY /* Support for floppy drives and ramdisks by dgk */ @@ -51,23 +51,23 @@ * or NO_TERMS */ -/* # define TERMLIB /* enable use of termcap file /etc/termcap */ +/* # define TERMLIB */ /* enable use of termcap file /etc/termcap */ /* or ./termcap for MSDOS (SAC) */ /* compile and link in Fred Fish's termcap library, */ /* enclosed in TERMCAP.ARC, to use this */ -/* # define ANSI_DEFAULT /* allows NetHack to run without a ./termcap */ +/* # define ANSI_DEFAULT */ /* allows NetHack to run without a ./termcap */ # define NO_TERMS /* Allows Nethack to run without ansi.sys by linking */ /* screen routines into the .exe */ # ifdef NO_TERMS /* if NO_TERMS select one screen package below */ #define SCREEN_BIOS /* Use bios calls for all screen control */ -/* #define SCREEN_DJGPPFAST /* Use djgpp fast screen routines */ +/* #define SCREEN_DJGPPFAST */ /* Use djgpp fast screen routines */ # endif -/* # define PC9800 /* Allows NetHack to run on NEC PC-9800 machines */ +/* # define PC9800 */ /* Allows NetHack to run on NEC PC-9800 machines */ /* Yamamoto Keizo */ @@ -99,7 +99,7 @@ /* amiconf.h). In the future this will be the */ /* hook for mail reader implementation. */ -/*# define PC_LOCKING /* Allow confirmation before overwriting game */ +/*# define PC_LOCKING */ /* Allow confirmation before overwriting game */ /* that is in progress or aborted when another */ /* game is started with the same player name. */ @@ -139,6 +139,10 @@ # ifdef PCMUSIC #define TIMED_DELAY /* need it anyway */ # endif +#define NOCWD_ASSUMPTIONS /* Allow paths to be specified for HACKDIR, + LEVELDIR, SAVEDIR, BONESDIR, DATADIR, + SCOREDIR, LOCKDIR, and CONFIGDIR */ + #endif /* MSDOS configuration stuff */ #define PATHLEN 64 /* maximum pathlength */ @@ -147,6 +151,7 @@ #include "micro.h" /* contains necessary externs for [os_name].c */ #endif + /* =================================================== * The remaining code shouldn't need modification. */ diff --git a/include/permonst.h b/include/permonst.h index 4031a8b..a971f01 100644 --- a/include/permonst.h +++ b/include/permonst.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)permonst.h 3.3 99/07/02 */ +/* SCCS Id: @(#)permonst.h 3.4 1999/07/02 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/prop.h b/include/prop.h index 23e24f9..f2ce274 100644 --- a/include/prop.h +++ b/include/prop.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)prop.h 3.3 1999/07/07 */ +/* SCCS Id: @(#)prop.h 3.4 1999/07/07 */ /* Copyright (c) 1989 Mike Threepoint */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/qt_clust.h b/include/qt_clust.h index 720eec8..96fec93 100644 --- a/include/qt_clust.h +++ b/include/qt_clust.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)qt_clust.h 3.3 1999/11/19 */ +/* SCCS Id: @(#)qt_clust.h 3.4 1999/11/19 */ /* Copyright (c) Warwick Allison, 1999. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/qt_kde0.h b/include/qt_kde0.h index f2c1404..4d64a42 100644 --- a/include/qt_kde0.h +++ b/include/qt_kde0.h @@ -1,10 +1,10 @@ -/* SCCS Id: @(#)qt_kde0.h 3.3 1999/11/19 */ +/* SCCS Id: @(#)qt_kde0.h 3.4 1999/11/19 */ /* Copyright (c) Warwick Allison, 1999. */ /* NetHack may be freely redistributed. See license for details. */ #ifndef QT_DUMMYKDE #define QT_DUMMYKDE -class KTopLevelWidget : public QWidget { +class KTopLevelWidget : public QMainWindow { Q_OBJECT }; #endif diff --git a/include/qt_win.h b/include/qt_win.h index 443ae53..6355586 100644 --- a/include/qt_win.h +++ b/include/qt_win.h @@ -1,8 +1,8 @@ -// SCCS Id: @(#)qt_win.h 3.3 1999/11/19 +// SCCS Id: @(#)qt_win.h 3.4 1999/11/19 // Copyright (c) Warwick Allison, 1999. // NetHack may be freely redistributed. See license for details. // -// Qt Binding for NetHack 3.3 +// Qt Binding for NetHack 3.4 // // Unfortunately, this doesn't use Qt as well as I would like, // primarily because NetHack is fundamentally a getkey-type @@ -21,7 +21,11 @@ #include #include #include +#if defined(QWS) +#include +#else #include +#endif #include #include #include @@ -32,7 +36,15 @@ #include #include #include +#if QT_VERSION >= 300 +#include +// Should stop using QTableView +#define QTableView QtTableView +#else #include +#endif +#include +#include #ifdef KDE #include @@ -103,6 +115,7 @@ class NetHackQtKeyBuffer { bool Full() const; void Put(int k, int ascii, int state); + void Put(char a); void Put(const char* str); int GetKey(); int GetAscii(); @@ -144,6 +157,12 @@ class NetHackQtClickBuffer { }; +class NetHackQtSavedGameSelector : public QDialog { +public: + NetHackQtSavedGameSelector(const char** saved); + + int choose(); +}; class NetHackQtPlayerSelector : private QDialog { Q_OBJECT @@ -175,6 +194,7 @@ public slots: NhPSListView* race; QRadioButton **gender; QRadioButton **alignment; + bool fully_specified_role; }; class NetHackQtStringRequestor : QDialog { @@ -268,6 +288,8 @@ class NetHackQtMapWindow : public QWidget, public NetHackQtWindow { QPixmap pet_annotation; Clusterizer change; QFont *rogue_font; + QString messages; + QRect messages_rect; void Changed(int x,int y); @@ -276,6 +298,7 @@ class NetHackQtMapWindow : public QWidget, public NetHackQtWindow { private slots: void updateTiles(); + void moveMessages(int x, int y); protected: virtual void paintEvent(QPaintEvent*); @@ -296,6 +319,11 @@ private slots: virtual void PrintGlyph(int x,int y,int glyph); void Scroll(int dx, int dy); + + // For messages + void displayMessages(bool block); + void putMessage(int attr, const char* text); + void clearMessages(); }; class NetHackQtScrollText; @@ -312,9 +340,12 @@ class NetHackQtMessageWindow : QObject, public NetHackQtWindow { void Scroll(int dx, int dy); + void setMap(NetHackQtMapWindow*); + private: NetHackQtScrollText* list; bool changed; + NetHackQtMapWindow* map; private slots: void updateFont(); @@ -558,6 +589,7 @@ class NetHackQtRIP : public QWidget { protected: virtual void paintEvent(QPaintEvent* event); + QSize sizeHint() const; }; @@ -580,7 +612,6 @@ public slots: protected: virtual void done(int); - virtual void resizeEvent(QResizeEvent*); virtual void keyPressEvent(QKeyEvent*); private slots: @@ -673,6 +704,7 @@ class NetHackQtMainWindow : public KTopLevelWidget { public slots: void doMenuItem(int); + void doKeys(const QString&); protected: virtual void resizeEvent(QResizeEvent*); @@ -681,6 +713,9 @@ public slots: private slots: void layout(); + void raiseMap(); + void raiseMessages(); + void raiseStatus(); private: void ShowIfReady(); @@ -693,14 +728,16 @@ private slots: NetHackQtMessageWindow* message; NetHackQtMapWindow* map; NetHackQtStatusWindow* status; - NetHackQtInvUsageWindow invusage; + NetHackQtInvUsageWindow* invusage; NetHackQtKeyBuffer& keysink; + QWidgetStack* stack; const char* *macro; }; class NetHackQtYnDialog : QDialog { + Q_OBJECT private: const char* question; const char* choices; @@ -711,6 +748,9 @@ class NetHackQtYnDialog : QDialog { virtual void keyPressEvent(QKeyEvent*); virtual void done(int); +private slots: + void doneItem(int); + public: NetHackQtYnDialog(NetHackQtKeyBuffer& keysource,const char*,const char*,char); @@ -719,6 +759,8 @@ class NetHackQtYnDialog : QDialog { #ifdef KDE #define NetHackQtBindBase KApplication +#elif defined(QWS) +#define NetHackQtBindBase QPEApplication #else #define NetHackQtBindBase QApplication #endif @@ -733,6 +775,7 @@ class NetHackQtBind : NetHackQtBindBase { static NetHackQtKeyBuffer keybuffer; static NetHackQtClickBuffer clickbuffer; + static QWidget* splash; static NetHackQtMainWindow* main; public: diff --git a/include/qt_xpms.h b/include/qt_xpms.h index 2276e93..fcb4b8d 100644 --- a/include/qt_xpms.h +++ b/include/qt_xpms.h @@ -932,6 +932,19 @@ static const char *pet_mark_xpm[] = { ".... ..." }; /* XPM */ +static const char *pet_mark_small_xpm[] = { +/* width height ncolors chars_per_pixel */ +"5 5 2 1", +/* colors */ +". c None", +"X c #FF0000", +/* pixels */ +".X.X.", +"XXXXX", +".XXX.", +"..X.." +}; +/* XPM */ static const char *satiated_xpm[] = { /* width height ncolors chars_per_pixel */ "40 40 23 1", diff --git a/include/qtext.h b/include/qtext.h index 41f7f9c..9ac4f16 100644 --- a/include/qtext.h +++ b/include/qtext.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)qtext.h 3.3 97/02/02 */ +/* SCCS Id: @(#)qtext.h 3.4 1997/02/02 */ /* Copyright (c) Mike Stephenson 1991. */ /* NetHack may be freely redistributed. See license for details. */ @@ -59,20 +59,21 @@ struct qtlists { #define QT_NEXTTIME 2 #define QT_OTHERTIME 3 -#define QT_GUARDTALK 5 /* 5 random things for guards to say */ +#define QT_GUARDTALK 5 /* 5 random things guards say before quest */ +#define QT_GUARDTALK2 10 /* 5 random things guards say after quest */ -#define QT_FIRSTLEADER 10 -#define QT_NEXTLEADER 11 -#define QT_OTHERLEADER 12 -#define QT_LASTLEADER 13 -#define QT_BADLEVEL 14 -#define QT_BADALIGN 15 -#define QT_ASSIGNQUEST 16 +#define QT_FIRSTLEADER 15 +#define QT_NEXTLEADER 16 +#define QT_OTHERLEADER 17 +#define QT_LASTLEADER 18 +#define QT_BADLEVEL 19 +#define QT_BADALIGN 20 +#define QT_ASSIGNQUEST 21 -#define QT_ENCOURAGE 20 /* 1-10 random encouragement messages */ +#define QT_ENCOURAGE 25 /* 1-10 random encouragement messages */ -#define QT_FIRSTLOCATE 30 -#define QT_NEXTLOCATE 31 +#define QT_FIRSTLOCATE 35 +#define QT_NEXTLOCATE 36 #define QT_FIRSTGOAL 40 #define QT_NEXTGOAL 41 diff --git a/include/qttableview.h b/include/qttableview.h new file mode 100644 index 0000000..f6e5e98 --- /dev/null +++ b/include/qttableview.h @@ -0,0 +1,251 @@ +/********************************************************************** +** $Id: qttableview.h,v 1.2 2002/03/09 03:13:13 jwalz Exp $ +** +** Definition of QtTableView class +** +** Created : 941115 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file contains a class moved out of the Qt GUI Toolkit API. It +** may be used, distributed and modified without limitation. +** +**********************************************************************/ + +#ifndef QTTABLEVIEW_H +#define QTTABLEVIEW_H + +#ifndef QT_H +#include +#endif // QT_H + +#ifndef QT_NO_QTTABLEVIEW + +class QScrollBar; +class QCornerSquare; + + +class QtTableView : public QFrame +{ + Q_OBJECT +public: + virtual void setBackgroundColor( const QColor & ); + virtual void setPalette( const QPalette & ); + void show(); + + void repaint( bool erase=TRUE ); + void repaint( int x, int y, int w, int h, bool erase=TRUE ); + void repaint( const QRect &, bool erase=TRUE ); + +protected: + QtTableView( QWidget *parent=0, const char *name=0, WFlags f=0 ); + ~QtTableView(); + + int numRows() const; + virtual void setNumRows( int ); + int numCols() const; + virtual void setNumCols( int ); + + int topCell() const; + virtual void setTopCell( int row ); + int leftCell() const; + virtual void setLeftCell( int col ); + virtual void setTopLeftCell( int row, int col ); + + int xOffset() const; + virtual void setXOffset( int ); + int yOffset() const; + virtual void setYOffset( int ); + virtual void setOffset( int x, int y, bool updateScrBars = TRUE ); + + virtual int cellWidth( int col ); + virtual int cellHeight( int row ); + int cellWidth() const; + int cellHeight() const; + virtual void setCellWidth( int ); + virtual void setCellHeight( int ); + + virtual int totalWidth(); + virtual int totalHeight(); + + uint tableFlags() const; + bool testTableFlags( uint f ) const; + virtual void setTableFlags( uint f ); + void clearTableFlags( uint f = ~0 ); + + bool autoUpdate() const; + virtual void setAutoUpdate( bool ); + + void updateCell( int row, int column, bool erase=TRUE ); + + QRect cellUpdateRect() const; + QRect viewRect() const; + + int lastRowVisible() const; + int lastColVisible() const; + + bool rowIsVisible( int row ) const; + bool colIsVisible( int col ) const; + + QScrollBar *verticalScrollBar() const; + QScrollBar *horizontalScrollBar() const; + +private slots: + void horSbValue( int ); + void horSbSliding( int ); + void horSbSlidingDone(); + void verSbValue( int ); + void verSbSliding( int ); + void verSbSlidingDone(); + +protected: + virtual void paintCell( QPainter *, int row, int col ) = 0; + virtual void setupPainter( QPainter * ); + + void paintEvent( QPaintEvent * ); + void resizeEvent( QResizeEvent * ); + + int findRow( int yPos ) const; + int findCol( int xPos ) const; + + bool rowYPos( int row, int *yPos ) const; + bool colXPos( int col, int *xPos ) const; + + int maxXOffset(); + int maxYOffset(); + int maxColOffset(); + int maxRowOffset(); + + int minViewX() const; + int minViewY() const; + int maxViewX() const; + int maxViewY() const; + int viewWidth() const; + int viewHeight() const; + + void scroll( int xPixels, int yPixels ); + void updateScrollBars(); + void updateTableSize(); + +private: + void coverCornerSquare( bool ); + void snapToGrid( bool horizontal, bool vertical ); + virtual void setHorScrollBar( bool on, bool update = TRUE ); + virtual void setVerScrollBar( bool on, bool update = TRUE ); + void updateView(); + int findRawRow( int yPos, int *cellMaxY, int *cellMinY = 0, + bool goOutsideView = FALSE ) const; + int findRawCol( int xPos, int *cellMaxX, int *cellMinX = 0, + bool goOutsideView = FALSE ) const; + int maxColsVisible() const; + + void updateScrollBars( uint ); + void updateFrameSize(); + + void doAutoScrollBars(); + void showOrHideScrollBars(); + + int nRows; + int nCols; + int xOffs, yOffs; + int xCellOffs, yCellOffs; + short xCellDelta, yCellDelta; + short cellH, cellW; + + uint eraseInPaint : 1; + uint verSliding : 1; + uint verSnappingOff : 1; + uint horSliding : 1; + uint horSnappingOff : 1; + uint coveringCornerSquare : 1; + uint sbDirty : 8; + uint inSbUpdate : 1; + + uint tFlags; + QRect cellUpdateR; + + QScrollBar *vScrollBar; + QScrollBar *hScrollBar; + QCornerSquare *cornerSquare; + +private: // Disabled copy constructor and operator= +#if defined(Q_DISABLE_COPY) + QtTableView( const QtTableView & ); + QtTableView &operator=( const QtTableView & ); +#endif +}; + + +const uint Tbl_vScrollBar = 0x00000001; +const uint Tbl_hScrollBar = 0x00000002; +const uint Tbl_autoVScrollBar = 0x00000004; +const uint Tbl_autoHScrollBar = 0x00000008; +const uint Tbl_autoScrollBars = 0x0000000C; + +const uint Tbl_clipCellPainting = 0x00000100; +const uint Tbl_cutCellsV = 0x00000200; +const uint Tbl_cutCellsH = 0x00000400; +const uint Tbl_cutCells = 0x00000600; + +const uint Tbl_scrollLastHCell = 0x00000800; +const uint Tbl_scrollLastVCell = 0x00001000; +const uint Tbl_scrollLastCell = 0x00001800; + +const uint Tbl_smoothHScrolling = 0x00002000; +const uint Tbl_smoothVScrolling = 0x00004000; +const uint Tbl_smoothScrolling = 0x00006000; + +const uint Tbl_snapToHGrid = 0x00008000; +const uint Tbl_snapToVGrid = 0x00010000; +const uint Tbl_snapToGrid = 0x00018000; + + +inline int QtTableView::numRows() const +{ return nRows; } + +inline int QtTableView::numCols() const +{ return nCols; } + +inline int QtTableView::topCell() const +{ return yCellOffs; } + +inline int QtTableView::leftCell() const +{ return xCellOffs; } + +inline int QtTableView::xOffset() const +{ return xOffs; } + +inline int QtTableView::yOffset() const +{ return yOffs; } + +inline int QtTableView::cellHeight() const +{ return cellH; } + +inline int QtTableView::cellWidth() const +{ return cellW; } + +inline uint QtTableView::tableFlags() const +{ return tFlags; } + +inline bool QtTableView::testTableFlags( uint f ) const +{ return (tFlags & f) != 0; } + +inline QRect QtTableView::cellUpdateRect() const +{ return cellUpdateR; } + +inline bool QtTableView::autoUpdate() const +{ return isUpdatesEnabled(); } + +inline void QtTableView::repaint( bool erase ) +{ repaint( 0, 0, width(), height(), erase ); } + +inline void QtTableView::repaint( const QRect &r, bool erase ) +{ repaint( r.x(), r.y(), r.width(), r.height(), erase ); } + +inline void QtTableView::updateScrollBars() +{ updateScrollBars( 0 ); } + + +#endif // QT_NO_QTTABLEVIEW + +#endif // QTTABLEVIEW_H diff --git a/include/quest.h b/include/quest.h index 60f872e..98b9e3a 100644 --- a/include/quest.h +++ b/include/quest.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)quest.h 3.3 92/11/15 */ +/* SCCS Id: @(#)quest.h 3.4 1992/11/15 */ /* Copyright (c) Mike Stephenson 1991. */ /* NetHack may be freely redistributed. See license for details. */ @@ -25,6 +25,11 @@ struct q_score { /* Quest "scorecard" */ Bitfield(touched_artifact,1); /* for a special message */ Bitfield(offered_artifact,1); /* offered to leader */ Bitfield(got_thanks,1); /* final message from leader */ + + /* keep track of leader presence/absence even if leader is + polymorphed, raised from dead, etc */ + Bitfield(leader_is_dead,1); + unsigned leader_m_id; }; #define MAX_QUEST_TRIES 7 /* exceed this and you "fail" */ diff --git a/include/rect.h b/include/rect.h index afd0326..a7deafb 100644 --- a/include/rect.h +++ b/include/rect.h @@ -1,11 +1,11 @@ -/* SCCS Id: @(#)rect.h 3.3 90/02/22 */ +/* SCCS Id: @(#)rect.h 3.4 1990/02/22 */ /* Copyright (c) 1990 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ #ifndef RECT_H #define RECT_H -typedef struct { +typedef struct nhrect { xchar lx, ly; xchar hx, hy; } NhRect; diff --git a/include/region.h b/include/region.h index 59dc5fc..96ebd99 100644 --- a/include/region.h +++ b/include/region.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)region.h 3.3 96/06/17 */ +/* SCCS Id: @(#)region.h 3.4 1996/06/17 */ /* Copyright (c) 1996 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/rm.h b/include/rm.h index f3309ef..c2da275 100644 --- a/include/rm.h +++ b/include/rm.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)rm.h 3.3 1999/12/12 */ +/* SCCS Id: @(#)rm.h 3.4 1999/12/12 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -213,6 +213,7 @@ #define MAXDCHARS 41 /* maximum of mapped dungeon characters */ #define MAXTCHARS 22 /* maximum of mapped trap characters */ #define MAXECHARS 29 /* maximum of mapped effects characters */ +#define MAXEXPCHARS 9 /* number of explosion characters */ struct symdef { uchar sym; @@ -425,6 +426,7 @@ struct rm { #define icedpool flags #define blessedftn horizontal /* a fountain that grants attribs */ +#define disturbed horizontal /* a grave that has been disturbed */ struct damage { struct damage *next; diff --git a/include/skills.h b/include/skills.h index 08d04c2..09bc3be 100644 --- a/include/skills.h +++ b/include/skills.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)skills.h 3.3 1999/10/27 */ +/* SCCS Id: @(#)skills.h 3.4 1999/10/27 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/sp_lev.h b/include/sp_lev.h index 1a96026..f549f53 100644 --- a/include/sp_lev.h +++ b/include/sp_lev.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)sp_lev.h 3.3 96/05/08 */ +/* SCCS Id: @(#)sp_lev.h 3.4 1996/05/08 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/spell.h b/include/spell.h index 22e22a4..6b43e21 100644 --- a/include/spell.h +++ b/include/spell.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)spell.h 3.3 95/06/01 */ +/* SCCS Id: @(#)spell.h 3.4 1995/06/01 */ /* Copyright 1986, M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/system.h b/include/system.h index 2171c78..abb6e1a 100644 --- a/include/system.h +++ b/include/system.h @@ -1,11 +1,11 @@ -/* SCCS Id: @(#)system.h 3.3 99/07/02 */ +/* SCCS Id: @(#)system.h 3.4 2001/12/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #ifndef SYSTEM_H #define SYSTEM_H -#ifndef __GO32__ /* djgpp compiler for msdos */ +#if !defined(__cplusplus) && !defined(__GO32__) #define E extern @@ -24,7 +24,9 @@ # if !defined(_SIZE_T) && !defined(__size_t) /* __size_t for CSet/2 */ # define _SIZE_T # if !((defined(MSDOS) || defined(OS2)) && defined(_SIZE_T_DEFINED)) /* MSC 5.1 */ +# if !(defined(__GNUC__) && defined(AMIGA)) typedef unsigned int size_t; +# endif # endif # endif #endif /* MICRO && !TOS */ @@ -44,7 +46,7 @@ typedef unsigned int size_t; typedef long off_t; #endif -#endif /* __GO32__ */ +#endif /* !__cplusplus && !__GO32__ */ /* You may want to change this to fit your system, as this is almost * impossible to get right automatically. @@ -68,7 +70,7 @@ typedef long off_t; # define SIG_RET_TYPE int (*)() #endif -#ifndef __GO32__ +#if !defined(__cplusplus) && !defined(__GO32__) #if defined(BSD) || defined(ULTRIX) || defined(RANDOM) # ifdef random @@ -116,7 +118,7 @@ E void FDECL(free, (genericptr_t)); # endif # endif #if !defined(__SASC_60) && !defined(_DCC) && !defined(__SC__) -# if defined(AMIGA) && !defined(AZTEC_50) +# if defined(AMIGA) && !defined(AZTEC_50) && !defined(__GNUC__) E int FDECL(perror, (const char *)); # else # if !(defined(ULTRIX_PROTO) && defined(__GNUC__)) @@ -247,7 +249,10 @@ E int FDECL(atexit, (void (*)(void))); E int FDECL(atoi, (const char *)); E int FDECL(chdir, (const char *)); E int FDECL(chown, (const char *,unsigned,unsigned)); -# ifndef __DECC_VER /* suppress for recent DEC C */ +# ifdef __DECC_VER +E int FDECL(chmod, (const char *,mode_t)); +E mode_t FDECL(umask, (mode_t)); +# else E int FDECL(chmod, (const char *,int)); E int FDECL(umask, (int)); # endif @@ -361,7 +366,10 @@ E long NDECL(getpid); E pid_t NDECL(getpid); E uid_t NDECL(getuid); E gid_t NDECL(getgid); -# else +# ifdef VMS +E pid_t NDECL(getppid); +# endif +# else /*!POSIX_TYPES*/ # ifndef getpid /* Borland C defines getpid() as a macro */ E int NDECL(getpid); # endif @@ -370,14 +378,14 @@ E int NDECL(getppid); E unsigned NDECL(getuid); E unsigned NDECL(getgid); # endif -# endif -# if defined(ULTRIX) && !defined(_UNISTD_H_) +# if defined(ULTRIX) && !defined(_UNISTD_H_) E unsigned NDECL(getuid); E unsigned NDECL(getgid); E int FDECL(setgid, (int)); E int FDECL(setuid, (int)); -# endif -#endif +# endif +# endif /*?POSIX_TYPES*/ +#endif /*?(HPUX && !_POSIX_SOURCE)*/ /* add more architectures as needed */ #if defined(HPUX) @@ -538,6 +546,6 @@ E int FDECL(atoi, (const char *)); #undef E -#endif /* __GO32__ */ +#endif /* !__cplusplus && !__GO32__ */ #endif /* SYSTEM_H */ diff --git a/include/tcap.h b/include/tcap.h index 79d9474..09cff27 100644 --- a/include/tcap.h +++ b/include/tcap.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)tcap.h 3.3 92/10/21 */ +/* SCCS Id: @(#)tcap.h 3.4 1992/10/21 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1989. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/tile2x11.h b/include/tile2x11.h index 78400db..3f16285 100644 --- a/include/tile2x11.h +++ b/include/tile2x11.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)tile2x11.h 3.3 95/01/25 */ +/* SCCS Id: @(#)tile2x11.h 3.4 1995/01/25 */ /* NetHack may be freely redistributed. See license for details. */ #ifndef TILE2X11_H @@ -13,6 +13,10 @@ typedef struct { unsigned long tile_width; unsigned long tile_height; unsigned long ntiles; + unsigned long per_row; } x11_header; +/* how wide each row in the tile file is, in tiles */ +#define TILES_PER_ROW (40) + #endif /* TILE2X11_H */ diff --git a/include/timeout.h b/include/timeout.h index d3f9785..481bf95 100644 --- a/include/timeout.h +++ b/include/timeout.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)timeout.h 3.3 1999/02/13 */ +/* SCCS Id: @(#)timeout.h 3.4 1999/02/13 */ /* Copyright 1994, Dean Luick */ /* NetHack may be freely redistributed. See license for details. */ @@ -30,4 +30,15 @@ typedef void FDECL((*timeout_proc), (genericptr_t, long)); #define FIG_TRANSFORM 5 #define NUM_TIME_FUNCS 6 +/* used in timeout.c */ +typedef struct fe { + struct fe *next; /* next item in chain */ + long timeout; /* when we time out */ + unsigned long tid; /* timer ID */ + short kind; /* kind of use */ + short func_index; /* what to call when we time out */ + genericptr_t arg; /* pointer to timeout argument */ + Bitfield (needs_fixup,1); /* does arg need to be patched? */ +} timer_element; + #endif /* TIMEOUT_H */ diff --git a/include/tradstdc.h b/include/tradstdc.h index efbaed7..b7292d1 100644 --- a/include/tradstdc.h +++ b/include/tradstdc.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)tradstdc.h 3.3 93/05/30 */ +/* SCCS Id: @(#)tradstdc.h 3.4 1993/05/30 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -167,7 +167,7 @@ # define FDECL(f,p) f() # define VDECL(f,p) f() -# if defined(AMIGA) || defined(HPUX) || defined(POSIX_TYPES) || defined(__DECC) +# if defined(AMIGA) || defined(HPUX) || defined(POSIX_TYPES) || defined(__DECC) || defined(__BORLANDC__) # define genericptr void * # endif # ifndef genericptr @@ -203,7 +203,7 @@ typedef genericptr genericptr_t; /* (void *) or (char *) */ #if defined(AMIGA) && !defined(AZTEC_50) #define UNWIDENED_PROTOTYPES #endif -#if defined(applec) +#if defined(macintosh) && (defined(__SC__) || defined(__MRC__)) #define UNWIDENED_PROTOTYPES #endif #if defined(__MWERKS__) && defined(__BEOS__) diff --git a/include/trampoli.h b/include/trampoli.h index 7da3f3b..fde5ab2 100644 --- a/include/trampoli.h +++ b/include/trampoli.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)trampoli.h 3.3 95/06/01 */ +/* SCCS Id: @(#)trampoli.h 3.4 1995/06/01 */ /* Copyright (c) 1989, by Norm Meluch and Stephen Spackman */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/trap.h b/include/trap.h index 8158b8b..f74f328 100644 --- a/include/trap.h +++ b/include/trap.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)trap.h 3.3 92/09/28 */ +/* SCCS Id: @(#)trap.h 3.4 2000/08/30 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -7,6 +7,11 @@ #ifndef TRAP_H #define TRAP_H +union vlaunchinfo { + short v_launch_otyp; /* type of object to be triggered */ + coord v_launch2; /* secondary launch point (for boulders) */ +}; + struct trap { struct trap *ntrap; xchar tx,ty; @@ -22,12 +27,9 @@ struct trap { when you untrap a monster. It would be too easy to make a monster peaceful if you could set a trap for it and then untrap it. */ - union { - short v_launch_otyp; /* type of object to be triggered */ - coord v_launch2; /* secondary launch point (for boulders) */ - } v; -#define launch_otyp v.v_launch_otyp -#define launch2 v.v_launch2 + union vlaunchinfo vl; +#define launch_otyp vl.v_launch_otyp +#define launch2 vl.v_launch2 }; extern struct trap *ftrap; diff --git a/include/unixconf.h b/include/unixconf.h index bc6b5bd..442f02b 100644 --- a/include/unixconf.h +++ b/include/unixconf.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)unixconf.h 3.3 99/07/02 */ +/* SCCS Id: @(#)unixconf.h 3.4 1999/07/02 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -80,7 +80,7 @@ /* #define RANDOM */ /* if neither random/srandom nor lrand48/srand48 is available from your system */ -/* see sys/unix/snd86.shr for more information on these */ +/* see sys/unix/snd86unx.shr for more information on these */ /* #define UNIX386MUSIC */ /* play real music through speaker on systems with music driver installed */ /* #define VPIX_MUSIC */ /* play real music through speaker on systems @@ -174,7 +174,7 @@ #define DEF_MAILREADER "/usr/ucb/Mail" # endif #else -# if defined(SYSV) || defined(DGUX) || defined(HPUX) +# if (defined(SYSV) || defined(DGUX) || defined(HPUX)) && !defined(LINUX) # if defined(M_XENIX) || defined(__FreeBSD__) #define DEF_MAILREADER "/usr/bin/mail" # else @@ -297,14 +297,14 @@ #endif /* Use the high quality random number routines. */ -#if defined(BSD) || defined(ULTRIX) || defined(CYGWIN32) || defined(RANDOM) +#if defined(BSD) || defined(ULTRIX) || defined(CYGWIN32) || defined(RANDOM) || defined(__APPLE__) #define Rand() random() #else #define Rand() lrand48() #endif #ifdef TIMED_DELAY -# if defined(SUNOS4) || defined(LINUX) +# if defined(SUNOS4) || defined(LINUX) || (defined(BSD) && !defined(ULTRIX)) # define msleep(k) usleep((k)*1000) # endif # ifdef ULTRIX @@ -320,5 +320,28 @@ # undef hc #endif +#if defined(GNOME_GRAPHICS) +#if defined(LINUX) +# include +# if defined(__NR_getresuid) && defined(__NR_getresgid) /* ie., >= v2.1.44 */ +# define GETRES_SUPPORT +# endif +#else +# if defined(BSD) || defined(SVR4) +/* + * [ALI] We assume that SVR4 means we can safely include syscall.h + * (although it's really a BSDism). This is certainly true for Solaris 2.5, + * Solaris 7, Solaris 8 and Compaq Tru64 5.1 + * Later BSD systems will have the getresid system calls. + */ +# include +# if (defined (SYS_getuid) || defined(SYS_getresuid)) && \ + (defined(SYS_getgid) || defined(SYS_getresgid)) +# define GETRES_SUPPORT +# endif +# endif /* BSD || SVR4 */ +#endif /* LINUX */ +#endif /* GNOME_GRAPHICS */ + #endif /* UNIXCONF_H */ #endif /* UNIX */ diff --git a/include/vault.h b/include/vault.h index d6db116..6e0a162 100644 --- a/include/vault.h +++ b/include/vault.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)vault.h 3.3 97/05/01 */ +/* SCCS Id: @(#)vault.h 3.4 1997/05/01 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/vision.h b/include/vision.h index 87925d9..29396eb 100644 --- a/include/vision.h +++ b/include/vision.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)vision.h 3.3 95/01/26 */ +/* SCCS Id: @(#)vision.h 3.4 1995/01/26 */ /* Copyright (c) Dean Luick, with acknowledgements to Dave Cohrs, 1990. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/vmsconf.h b/include/vmsconf.h index 9185e3c..d6572d3 100644 --- a/include/vmsconf.h +++ b/include/vmsconf.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)vmsconf.h 3.3 98/07/16 */ +/* SCCS Id: @(#)vmsconf.h 3.4 2001/12/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -190,6 +190,10 @@ typedef __uid_t uid_t; # define __GID_T typedef __gid_t gid_t; # endif +# ifndef __MODE_T +# define __MODE_T +typedef __mode_t mode_t; +# endif #endif /* _DECC_V4_SOURCE */ #include diff --git a/include/winGnome.h b/include/winGnome.h index 9163562..e894ac8 100644 --- a/include/winGnome.h +++ b/include/winGnome.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)winGnome.h 3.3. 2000/07/16 */ +/* SCCS Id: @(#)winGnome.h 3.4. 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* Copyright (C) 1998 by Anthony Taylor */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/winX.h b/include/winX.h index 376be90..7ded018 100644 --- a/include/winX.h +++ b/include/winX.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)winX.h 3.3 96/08/18 */ +/* SCCS Id: @(#)winX.h 3.4 1996/08/18 */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -56,6 +56,8 @@ struct tile_map_info_t { unsigned short glyphs[ROWNO][COLNO]; /* Saved glyph numbers. */ GC white_gc; GC black_gc; + unsigned long image_width; /* dimensions of tile image */ + unsigned long image_height; }; struct map_info_t { @@ -277,6 +279,7 @@ E void FDECL(positionpopup,(Widget,BOOLEAN_P)); /* ### winX.c ### */ E struct xwindow *FDECL(find_widget,(Widget)); E Boolean FDECL(nhApproxColor,(Screen*, Colormap, char*, XColor*)); +E Dimension FDECL(nhFontHeight,(Widget)); E char FDECL(key_event_to_char,(XKeyEvent*)); E void FDECL(msgkey, (Widget, XtPointer, XEvent*)); E void FDECL(nh_XtPopup, (Widget, int, Widget)); diff --git a/include/winami.h b/include/winami.h index 92b9945..ea2c0ec 100644 --- a/include/winami.h +++ b/include/winami.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)winami.h 3.3 93/01/17 */ +/* SCCS Id: @(#)winami.h 3.4 1993/01/17 */ /* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1991. */ /* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1992, 1993. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/wingem.h b/include/wingem.h index ddafee0..cef5418 100644 --- a/include/wingem.h +++ b/include/wingem.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)wingem.h 3.3 1999/12/10 */ +/* SCCS Id: @(#)wingem.h 3.4 1999/12/10 */ /* Copyright (c) Christian Bressler, 1999 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/winprocs.h b/include/winprocs.h index 28d4f28..87a21ca 100644 --- a/include/winprocs.h +++ b/include/winprocs.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)winprocs.h 3.3 96/02/18 */ +/* SCCS Id: @(#)winprocs.h 3.4 1996/02/18 */ /* Copyright (c) David Cohrs, 1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -7,6 +7,7 @@ struct window_procs { const char *name; + unsigned long wincap; /* window port capability options supported */ void FDECL((*win_init_nhwindows), (int *, char **)); void NDECL((*win_player_selection)); void NDECL((*win_askname)); @@ -62,6 +63,7 @@ struct window_procs { void NDECL((*win_end_screen)); void FDECL((*win_outrip), (winid,int)); + void FDECL((*win_preference_update), (const char *)); }; extern NEARDATA struct window_procs windowprocs; @@ -125,4 +127,82 @@ extern NEARDATA struct window_procs windowprocs; #define end_screen (*windowprocs.win_end_screen) #define outrip (*windowprocs.win_outrip) +#define preference_update (*windowprocs.win_preference_update) + +/* + * WINCAP + * Window port preference capability bits. + * Some day this might be better in its own wincap.h file. + */ +#define WC_COLOR 0x01L /* 01 Port can display things in color */ +#define WC_HILITE_PET 0x02L /* 02 supports hilite pet */ +#define WC_ASCII_MAP 0x04L /* 03 supports an ascii map */ +#define WC_TILED_MAP 0x08L /* 04 supports a tiled map */ +#define WC_PRELOAD_TILES 0x10L /* 05 supports pre-loading tiles */ +#define WC_TILE_WIDTH 0x20L /* 06 prefer this width of tile */ +#define WC_TILE_HEIGHT 0x40L /* 07 prefer this height of tile */ +#define WC_TILE_FILE 0x80L /* 08 alternative tile file name */ +#define WC_INVERSE 0x100L /* 09 Port supports inverse video */ +#define WC_ALIGN_MESSAGE 0x200L /* 10 supports message alignmt top|b|l|r */ +#define WC_ALIGN_STATUS 0x400L /* 11 supports status alignmt top|b|l|r */ +#define WC_VARY_MSGCOUNT 0x800L /* 12 supports varying message window */ +#define WC_FONT_MAP 0x1000L /* 13 supports specification of map win font */ +#define WC_FONT_MESSAGE 0x2000L /* 14 supports specification of msg win font */ +#define WC_FONT_STATUS 0x4000L /* 15 supports specification of sts win font */ +#define WC_FONT_MENU 0x8000L /* 16 supports specification of mnu win font */ +#define WC_FONT_TEXT 0x10000L /* 17 supports specification of txt win font */ +#define WC_FONTSIZ_MAP 0x20000L /* 18 supports specification of map win font */ +#define WC_FONTSIZ_MESSAGE 0x40000L /* 19 supports specification of msg win font */ +#define WC_FONTSIZ_STATUS 0x80000L /* 20 supports specification of sts win font */ +#define WC_FONTSIZ_MENU 0x100000L /* 21 supports specification of mnu win font */ +#define WC_FONTSIZ_TEXT 0x200000L /* 22 supports specification of txt win font */ +#define WC_SCROLL_MARGIN 0x400000L /* 23 supports setting scroll margin for map */ +#define WC_SPLASH_SCREEN 0x800000L /* 24 supports setting scroll margin for map */ +#define WC_POPUP_DIALOG 0x1000000L /* 25 supports queries in pop dialogs */ +#define WC_LARGE_FONT 0x2000000L /* 26 Port supports large font */ +#define WC_EIGHT_BIT_IN 0x4000000L /* 27 8-bit character input */ +#define WC_PERM_INVENT 0x8000000L /* 28 8-bit character input */ +#define WC_MAP_MODE 0x10000000L /* 29 map_mode option */ +#define WC_WINDOWCOLORS 0x20000000L /* 30 background color for message window */ +#define WC_PLAYER_SELECTION 0x40000000L /* 31 background color for message window */ + /* 1 free bit */ + +#define ALIGN_LEFT 1 +#define ALIGN_RIGHT 2 +#define ALIGN_TOP 3 +#define ALIGN_BOTTOM 4 + +/* player_selection */ +#define VIA_DIALOG 0 +#define VIA_PROMPTS 1 + +/* map_mode settings - deprecated */ +#define MAP_MODE_TILES 0 +#define MAP_MODE_ASCII4x6 1 +#define MAP_MODE_ASCII6x8 2 +#define MAP_MODE_ASCII8x8 3 +#define MAP_MODE_ASCII16x8 4 +#define MAP_MODE_ASCII7x12 5 +#define MAP_MODE_ASCII8x12 6 +#define MAP_MODE_ASCII16x12 7 +#define MAP_MODE_ASCII12x16 8 +#define MAP_MODE_ASCII10x18 9 +#define MAP_MODE_ASCII_FIT_TO_SCREEN 10 +#define MAP_MODE_TILES_FIT_TO_SCREEN 11 + +#if 0 +#define WC_SND_SOUND 0x01L /* 01 Port has some sound capabilities */ +#define WC_SND_SPEAKER 0x02L /* 02 Sound supported via built-in speaker */ +#define WC_SND_STEREO 0x04L /* 03 Stereo sound supported */ +#define WC_SND_RAW 0x08L /* 04 Raw sound supported */ +#define WC_SND_WAVE 0x10L /* 05 Wave support */ +#define WC_SND_MIDI 0x20L /* 06 Midi support */ + /* 26 free bits */ #endif + +struct wc_Opt { + char *wc_name; + unsigned long wc_bit; +}; + +#endif /* WINPROCS_H */ diff --git a/include/wintty.h b/include/wintty.h index b47a33d..fc123d8 100644 --- a/include/wintty.h +++ b/include/wintty.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)wintty.h 3.3 96/02/18 */ +/* SCCS Id: @(#)wintty.h 3.4 1996/02/18 */ /* Copyright (c) David Cohrs, 1991,1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -111,7 +111,7 @@ E void FDECL(xputc, (CHAR_P)); #endif E void FDECL(xputs, (const char *)); #if defined(SCREEN_VGA) || defined(SCREEN_8514) -E void FDECL(xputg, (int, int)); +E void FDECL(xputg, (int, int, unsigned)); #endif E void NDECL(cl_end); E void NDECL(clear_screen); diff --git a/include/wintype.h b/include/wintype.h index be1c1e1..2491d0e 100644 --- a/include/wintype.h +++ b/include/wintype.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)wintype.h 3.3 96/02/18 */ +/* SCCS Id: @(#)wintype.h 3.4 1996/02/18 */ /* Copyright (c) David Cohrs, 1991 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/xwindow.h b/include/xwindow.h index 1145e89..94c7d3a 100644 --- a/include/xwindow.h +++ b/include/xwindow.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)xwindow.h 3.3 92/03/07 */ +/* SCCS Id: @(#)xwindow.h 3.4 1992/03/07 */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/xwindowp.h b/include/xwindowp.h index c2a9050..bbbe378 100644 --- a/include/xwindowp.h +++ b/include/xwindowp.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)xwindowp.h 3.3 92/03/07 */ +/* SCCS Id: @(#)xwindowp.h 3.4 1992/03/07 */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/include/you.h b/include/you.h index c616c6f..2ca496d 100644 --- a/include/you.h +++ b/include/you.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)you.h 3.3 2000/05/21 */ +/* SCCS Id: @(#)you.h 3.4 2000/05/21 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -207,6 +207,12 @@ struct Gender { /* increment to 3 if you allow neuter roles */ extern const struct Gender genders[]; /* table of available genders */ +#define uhe() (genders[flags.female ? 1 : 0].he) +#define uhim() (genders[flags.female ? 1 : 0].him) +#define uhis() (genders[flags.female ? 1 : 0].his) +#define mhe(mtmp) (genders[pronoun_gender(mtmp)].he) +#define mhim(mtmp) (genders[pronoun_gender(mtmp)].him) +#define mhis(mtmp) (genders[pronoun_gender(mtmp)].his) /*** Unified structure specifying alignment information ***/ @@ -227,6 +233,7 @@ struct you { xchar ux, uy; schar dx, dy, dz; /* direction of move (or zap or ... ) */ schar di; /* direction of FF */ + xchar tx, ty; /* destination of travel */ xchar ux0, uy0; /* initial position FF */ d_level uz, uz0; /* your level on this and the previous turn */ d_level utolev; /* level monster teleported you to, or uz */ @@ -295,7 +302,8 @@ struct you { Bitfield(mfemale,1); /* saved human value of flags.female */ Bitfield(uinvulnerable,1); /* you're invulnerable (praying) */ Bitfield(uburied,1); /* you're buried */ - /* 2 free bits! */ + Bitfield(uedibility,1); /* blessed food detection; sense unsafe food */ + /* 1 free bit! */ unsigned udg_cnt; /* how long you have been demigod */ struct u_event uevent; /* certain events have happened */ @@ -328,7 +336,11 @@ struct you { int ugangr; /* if the gods are angry at you */ int ugifts; /* number of artifacts bestowed */ int ublessed, ublesscnt; /* blessing/duration from #pray */ +#ifndef GOLDOBJ long ugold, ugold0; +#else + long umoney0; +#endif long uexp, urexp; long ucleansed; /* to record moves when player was cleansed */ long usleep; /* sleeping; monstermove you last started */ diff --git a/include/youprop.h b/include/youprop.h index 86cef9b..fb80f63 100644 --- a/include/youprop.h +++ b/include/youprop.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)youprop.h 3.3 99/07/02 */ +/* SCCS Id: @(#)youprop.h 3.4 1999/07/02 */ /* Copyright (c) 1989 Mike Threepoint */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/src/allmain.c b/src/allmain.c index a3c5eca..bcdc12b 100644 --- a/src/allmain.c +++ b/src/allmain.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)allmain.c 3.3 2000/05/05 */ +/* SCCS Id: @(#)allmain.c 3.4 2002/01/04 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -138,6 +138,7 @@ moveloop() /* once-per-turn things go here */ /********************************/ + if (flags.bypasses) clear_bypasses(); if(Glib) glibr(); nh_timeout(); run_regions(); @@ -156,16 +157,22 @@ moveloop() if (u.uinvulnerable) { /* for the moment at least, you're in tiptop shape */ wtcap = UNENCUMBERED; + } else if (Upolyd && youmonst.data->mlet == S_EEL && !is_pool(u.ux,u.uy) && !Is_waterlevel(&u.uz)) { + if (u.mh > 1) { + u.mh--; + flags.botl = 1; + } else if (u.mh < 1) + rehumanize(); } else if (Upolyd && u.mh < u.mhmax) { if (u.mh < 1) - rehumanize(); + rehumanize(); else if (Regeneration || (wtcap < MOD_ENCUMBER && !(moves%20))) { flags.botl = 1; u.mh++; } } else if (u.uhp < u.uhpmax && - (wtcap < MOD_ENCUMBER || !flags.mv || Regeneration)) { + (wtcap < MOD_ENCUMBER || !u.umoved || Regeneration)) { if (u.ulevel > 9 && !(moves % 3)) { int heal, Con = (int) ACURR(A_CON); @@ -187,7 +194,8 @@ moveloop() } } - if (wtcap > MOD_ENCUMBER && flags.mv) { + /* moving around while encumbered is hard work */ + if (wtcap > MOD_ENCUMBER && u.umoved) { if(!(wtcap < EXT_ENCUMBER ? moves%30 : moves%10)) { if (Upolyd && u.mh > 1) { u.mh--; @@ -235,7 +243,7 @@ moveloop() stop_occupation(); else nomul(0); - if (change == 1) polyself(); + if (change == 1) polyself(FALSE); else you_were(); change = 0; } @@ -371,11 +379,12 @@ moveloop() if (!multi) { /* lookaround may clear multi */ flags.move = 0; + if (flags.time) flags.botl = 1; continue; } if (flags.mv) { if(multi < COLNO && !--multi) - flags.mv = flags.run = 0; + flags.travel = flags.mv = flags.run = 0; domove(); } else { --multi; @@ -406,8 +415,10 @@ void stop_occupation() { if(occupation) { - You("stop %s.", occtxt); + if (!maybe_finished_meal(TRUE)) + You("stop %s.", occtxt); occupation = 0; + flags.botl = 1; /* in case u.uhs changed */ /* fainting stops your occupation, there's no reason to sync. sync_hunger(); */ diff --git a/src/alloc.c b/src/alloc.c index a254dd8..e8f7e9d 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)alloc.c 3.3 95/10/04 */ +/* SCCS Id: @(#)alloc.c 3.4 1995/10/04 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/src/apply.c b/src/apply.c index eed36d6..1b4dad8 100644 --- a/src/apply.c +++ b/src/apply.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)apply.c 3.3 2000/07/23 */ +/* SCCS Id: @(#)apply.c 3.4 2002/03/09 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -9,7 +9,7 @@ static const char tools[] = { TOOL_CLASS, WEAPON_CLASS, WAND_CLASS, 0 }; static const char tools_too[] = { ALL_CLASSES, TOOL_CLASS, POTION_CLASS, - WEAPON_CLASS, WAND_CLASS, 0 }; + WEAPON_CLASS, WAND_CLASS, GEM_CLASS, 0 }; #ifdef TOURIST STATIC_DCL int FDECL(use_camera, (struct obj *)); @@ -30,6 +30,7 @@ STATIC_DCL void FDECL(use_tinning_kit, (struct obj *)); STATIC_DCL void FDECL(use_figurine, (struct obj *)); STATIC_DCL void FDECL(use_grease, (struct obj *)); STATIC_DCL void FDECL(use_trap, (struct obj *)); +STATIC_DCL void FDECL(use_stone, (struct obj *)); STATIC_PTR int NDECL(set_trap); /* occupation callback */ STATIC_DCL int FDECL(use_whip, (struct obj *)); STATIC_DCL int FDECL(use_pole, (struct obj *)); @@ -37,6 +38,7 @@ STATIC_DCL int FDECL(use_grapple, (struct obj *)); STATIC_DCL int FDECL(do_break_wand, (struct obj *)); STATIC_DCL boolean FDECL(figurine_location_checks, (struct obj *, coord *, BOOLEAN_P)); +STATIC_DCL boolean NDECL(uhave_graystone); #ifdef AMIGA void FDECL( amii_speaker, ( struct obj *, char *, int ) ); @@ -61,12 +63,13 @@ use_camera(obj) pline(nothing_happens); return (1); } + check_unpaid(obj); obj->spe--; if (obj->cursed && !rn2(2)) { (void) zapyourself(obj, TRUE); } else if (u.uswallow) { You("take a picture of %s %s.", s_suffix(mon_nam(u.ustuck)), - is_animal(u.ustuck->data) ? "stomach" : "interior"); + mbodypart(u.ustuck, STOMACH)); } else if (u.dz) { You("take a picture of the %s.", (u.dz > 0) ? surface(u.ux,u.uy) : ceiling(u.ux,u.uy)); @@ -275,6 +278,7 @@ use_stethoscope(obj) case SCORR: You_hear(hollow_str, "passage"); lev->typ = CORR; + unblock_point(rx,ry); if (Blind) feel_location(rx,ry); else newsym(rx,ry); return res; @@ -356,11 +360,18 @@ register struct obj *otmp; } void -m_unleash(mtmp) /* mtmp is about to die, or become untame */ +m_unleash(mtmp, feedback) /* mtmp is about to die, or become untame */ register struct monst *mtmp; +boolean feedback; { register struct obj *otmp; + if (feedback) { + if (canseemon(mtmp)) + pline("%s pulls free of %s leash!", Monnam(mtmp), mhis(mtmp)); + else + Your("leash falls slack."); + } for(otmp = invent; otmp; otmp = otmp->nobj) if(otmp->otyp == LEASH && otmp->leashmon == (int)mtmp->m_id) @@ -377,7 +388,7 @@ unleash_all() /* player is about to die (for bones) */ for(otmp = invent; otmp; otmp = otmp->nobj) if(otmp->otyp == LEASH) otmp->leashmon = 0; for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) - if(mtmp->mtame) mtmp->mleashed = 0; + mtmp->mleashed = 0; } #define MAXLEASHED 2 @@ -402,6 +413,13 @@ struct obj *obj; y = u.uy + u.dy; if((x == u.ux) && (y == u.uy)) { +#ifdef STEED + if (u.usteed && u.dz > 0) { + mtmp = u.usteed; + spotmon = 1; + goto got_target; + } +#endif pline("Leash yourself? Very funny..."); return; } @@ -412,6 +430,9 @@ struct obj *obj; } spotmon = canspotmon(mtmp); +#ifdef STEED + got_target: +#endif if(!mtmp->mtame) { if(!spotmon) @@ -492,6 +513,10 @@ next_to_u() } } } +#ifdef STEED + /* no pack mules for the Amulet */ + if (u.usteed && mon_has_amulet(u.usteed)) return FALSE; +#endif return(TRUE); } @@ -524,7 +549,7 @@ register xchar x, y; if(um_dist(mtmp->mx, mtmp->my, 5)) { pline("%s leash snaps loose!", s_suffix(Monnam(mtmp))); - m_unleash(mtmp); + m_unleash(mtmp, FALSE); } else { if(um_dist(mtmp->mx, mtmp->my, 3)) { You("pull on the leash."); @@ -641,7 +666,7 @@ struct obj *obj; } if(u.uswallow) { if (!Blind) You("reflect %s %s.", s_suffix(mon_nam(u.ustuck)), - is_animal(u.ustuck->data)? "stomach" : "interior"); + mbodypart(u.ustuck, STOMACH)); return 1; } if(Underwater) { @@ -676,7 +701,8 @@ struct obj *obj; } else if (mlet == S_VAMPIRE || mlet == S_GHOST) { if (vis) pline ("%s doesn't have a reflection.", Monnam(mtmp)); - } else if(!mtmp->mcan && mtmp->data == &mons[PM_MEDUSA]) { + } else if(!mtmp->mcan && !mtmp->minvis && + mtmp->data == &mons[PM_MEDUSA]) { if (mon_reflects(mtmp, "The gaze is reflected away by %s %s!")) return 1; if (vis) @@ -687,9 +713,6 @@ struct obj *obj; mtmp->data == &mons[PM_FLOATING_EYE]) { int tmp = d((int)mtmp->m_lev, (int)mtmp->data->mattk[0].damd); if (!rn2(4)) tmp = 120; - /* Note: floating eyes cannot use their abilities while invisible, - * but Medusa and umber hulks can. - */ if (vis) pline("%s is frozen by its reflection.", Monnam(mtmp)); else You_hear("%s stop moving.",something); @@ -697,7 +720,8 @@ struct obj *obj; if ( (int) mtmp->mfrozen + tmp > 127) mtmp->mfrozen = 127; else mtmp->mfrozen += tmp; - } else if(!mtmp->mcan && mtmp->data == &mons[PM_UMBER_HULK]) { + } else if(!mtmp->mcan && !mtmp->minvis && + mtmp->data == &mons[PM_UMBER_HULK]) { if (vis) pline ("%s confuses itself!", Monnam(mtmp)); mtmp->mconf = 1; @@ -714,10 +738,8 @@ struct obj *obj; } else if (!is_unicorn(mtmp->data) && !humanoid(mtmp->data) && (!mtmp->minvis || perceives(mtmp->data)) && rn2(5)) { if (vis) - pline ("%s is frightened by its reflection.", - Monnam(mtmp)); - mtmp->mflee = 1; - mtmp->mfleetim += d(2,4); + pline("%s is frightened by its reflection.", Monnam(mtmp)); + monflee(mtmp, d(2,4), FALSE, FALSE); } else if (!Blind) { if (mtmp->minvis && !See_invisible) ; @@ -727,7 +749,7 @@ struct obj *obj; Monnam(mtmp)); else pline("%s ignores %s reflection.", - Monnam(mtmp), his[pronoun_gender(mtmp)]); + Monnam(mtmp), mhis(mtmp)); } return 1; } @@ -768,12 +790,13 @@ register struct obj *obj; u.ux, u.uy, NO_MINVENT)) != 0) { You("summon %s!", a_monnam(mtmp)); if (!obj_resists(obj, 93, 100)) { - pline("%s has shattered!", The(xname(obj))); + pline("%s shattered!", Tobjnam(obj, "have")); useup(obj); } else switch (rn2(3)) { default: break; - case 1: mon_adjust_speed(mtmp, 2); + case 1: + mon_adjust_speed(mtmp, 2, (struct obj *)0); break; case 2: /* no explanation; it just happens... */ nomovemsg = ""; @@ -803,8 +826,8 @@ register struct obj *obj; wakem = TRUE; } else if (invoking) { - pline("%s issues an unsettling shrill sound...", - The(xname(obj))); + pline("%s an unsettling shrill sound...", + Tobjnam(obj, "issue")); #ifdef AMIGA amii_speaker( obj, "aefeaefeaefeaefeaefe", AMII_LOUDER_VOLUME ); #endif @@ -852,50 +875,47 @@ STATIC_OVL void use_candelabrum(obj) register struct obj *obj; { + char *s = obj->spe != 1 ? "candles" : "candle"; + if(Underwater) { You("cannot make fire under water."); return; } if(obj->lamplit) { - You("snuff the candle%s.", obj->spe > 1 ? "s" : ""); + You("snuff the %s.", s); end_burn(obj, TRUE); return; } if(obj->spe <= 0) { - pline("This %s has no candles.", xname(obj)); + pline("This %s has no %s.", xname(obj), s); return; } if(u.uswallow || obj->cursed) { if (!Blind) - pline_The("candle%s flicker%s for a moment, then die%s.", - obj->spe > 1 ? "s" : "", - obj->spe > 1 ? "" : "s", - obj->spe > 1 ? "" : "s"); + pline_The("%s %s for a moment, then %s.", + s, vtense(s, "flicker"), vtense(s, "die")); return; } if(obj->spe < 7) { - There("%s only %d candle%s in %s.", - obj->spe == 1 ? "is" : "are", - obj->spe, - obj->spe > 1 ? "s" : "", - the(xname(obj))); + There("%s only %d %s in %s.", + vtense(s, "are"), obj->spe, s, the(xname(obj))); if (!Blind) - pline("%s lit. %s shines dimly.", - obj->spe == 1 ? "It is" : "They are", The(xname(obj))); + pline("%s lit. %s dimly.", + obj->spe == 1 ? "It is" : "They are", + Tobjnam(obj, "shine")); } else { - pline("%s's candles burn%s", The(xname(obj)), + pline("%s's %s burn%s", The(xname(obj)), s, (Blind ? "." : " brightly!")); } if (!invocation_pos(u.ux, u.uy)) { - pline_The("candle%s being rapidly consumed!", - (obj->spe > 1 ? "s are" : " is")); + pline_The("%s %s being rapidly consumed!", s, vtense(s, "are")); obj->age /= 2; } else { if(obj->spe == 7) { if (Blind) - pline("%s radiates a strange warmth!", The(xname(obj))); + pline("%s a strange warmth!", Tobjnam(obj, "radiate")); else - pline("%s glows with a strange light!", The(xname(obj))); + pline("%s with a strange light!", Tobjnam(obj, "glow")); } obj->known = 1; } @@ -907,6 +927,7 @@ use_candle(obj) register struct obj *obj; { register struct obj *otmp; + char *s = obj->quan != 1 ? "candles" : "candle"; char qbuf[QBUFSZ]; if(u.uswallow) { @@ -933,17 +954,15 @@ register struct obj *obj; return; } else { if ((long)otmp->spe + obj->quan > 7L) - (void)splitobj(obj, 7L - (long)otmp->spe); - You("attach %ld%s candle%s to %s.", + obj = splitobj(obj, 7L - (long)otmp->spe); + You("attach %ld%s %s to %s.", obj->quan, !otmp->spe ? "" : " more", - plur(obj->quan), the(xname(otmp))); + s, the(xname(otmp))); if (!otmp->spe || otmp->age > obj->age) otmp->age = obj->age; otmp->spe += (int)obj->quan; if (otmp->lamplit && !obj->lamplit) - pline_The("new candle%s magically ignite%s!", - plur(obj->quan), - (obj->quan > 1L) ? "" : "s"); + pline_The("new %s magically %s!", s, vtense(s, "ignite")); else if (!otmp->lamplit && obj->lamplit) pline("%s out.", (obj->quan > 1L) ? "They go" : "It goes"); if (obj->unpaid) @@ -952,8 +971,8 @@ register struct obj *obj; (obj->quan > 1L) ? "them" : "it", (obj->quan > 1L) ? "them" : "it"); if (obj->quan < 7L && otmp->spe == 7) - pline("%s now has seven%s candles attached.", - The(xname(otmp)), otmp->lamplit ? " lit" : ""); + pline("%s now has seven%s %s attached.", + The(xname(otmp)), otmp->lamplit ? " lit" : "", s); /* candelabrum's light range might increase */ if (otmp->lamplit) obj_merge_light_sources(otmp, otmp); /* candles are no longer a separate light source */ @@ -1001,7 +1020,7 @@ struct obj *obj; obj->otyp == BRASS_LANTERN || obj->otyp == POT_OIL) { (void) get_obj_location(obj, &x, &y, 0); if (obj->where == OBJ_MINVENT ? cansee(x,y) : !Blind) - pline("%s goes out!", Yname2(obj)); + pline("%s %s out!", Yname2(obj), otense(obj, "go")); end_burn(obj, TRUE); return TRUE; } @@ -1010,6 +1029,39 @@ struct obj *obj; return FALSE; } +/* Called when potentially lightable object is affected by fire_damage(). + Return TRUE if object was lit and FALSE otherwise --ALI */ +boolean +catch_lit(obj) +struct obj *obj; +{ + xchar x, y; + + if (!obj->lamplit && (obj->otyp == CANDELABRUM_OF_INVOCATION || + obj->otyp == WAX_CANDLE || obj->otyp == TALLOW_CANDLE || + obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP || + obj->otyp == BRASS_LANTERN || obj->otyp == POT_OIL)) { + if ((obj->otyp == MAGIC_LAMP || + obj->otyp == CANDELABRUM_OF_INVOCATION) && + obj->spe == 0) + return FALSE; + else if (obj->otyp != MAGIC_LAMP && obj->age == 0) + return FALSE; + if (!get_obj_location(obj, &x, &y, 0)) + return FALSE; + if (obj->otyp == CANDELABRUM_OF_INVOCATION && obj->cursed) + return FALSE; + if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP || + obj->otyp == BRASS_LANTERN) && obj->cursed && !rn2(2)) + return FALSE; + if (obj->where == OBJ_MINVENT ? cansee(x,y) : !Blind) + pline("%s %s light!", Yname2(obj), otense(obj, "catch")); + begin_burn(obj, TRUE); + return TRUE; + } + return FALSE; +} + STATIC_OVL void use_lamp(obj) struct obj *obj; @@ -1038,20 +1090,17 @@ struct obj *obj; return; } if (obj->cursed && !rn2(2)) { - pline("%s flicker%s for a moment, then die%s.", - The(xname(obj)), - obj->quan > 1L ? "" : "s", - obj->quan > 1L ? "" : "s"); + pline("%s for a moment, then %s.", + Tobjnam(obj, "flicker"), otense(obj, "die")); } else { if(obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP || obj->otyp == BRASS_LANTERN) { check_unpaid(obj); pline("%s lamp is now on.", Shk_Your(buf, obj)); } else { /* candle(s) */ - pline("%s flame%s burn%s%s", + pline("%s flame%s %s%s", s_suffix(Yname2(obj)), - plur(obj->quan), - obj->quan > 1L ? "" : "s", + plur(obj->quan), otense(obj, "burn"), Blind ? "." : " brightly!"); if (obj->unpaid && costly_spot(u.ux, u.uy) && obj->age == 20L * (long)objects[obj->otyp].oc_cost) { @@ -1098,12 +1147,13 @@ light_cocktail(obj) * for an item, but (Yendorian Fuel) Taxes are inevitable... */ check_unpaid(obj); + verbalize("That's in addition to the cost of the potion, of course."); bill_dummy_object(obj); } makeknown(obj->otyp); if (obj->quan > 1L) { - (void) splitobj(obj, 1L); + obj = splitobj(obj, 1L); begin_burn(obj, FALSE); /* burn before free to get position */ obj_extract_self(obj); /* free from inv */ @@ -1114,13 +1164,23 @@ light_cocktail(obj) begin_burn(obj, FALSE); } -static NEARDATA const char cuddly[] = { TOOL_CLASS, 0 }; +static NEARDATA const char cuddly[] = { TOOL_CLASS, GEM_CLASS, 0 }; int dorub() { struct obj *obj = getobj(cuddly, "rub"); + if (obj && obj->oclass == GEM_CLASS) { + if (is_graystone(obj)) { + use_stone(obj); + return 1; + } else { + pline("Sorry, I don't know how to use that."); + return 0; + } + } + if(!obj || (obj != uwep && !wield_tool(obj))) return 0; /* now uwep is obj */ @@ -1133,6 +1193,7 @@ dorub() uwep->spe = 0; /* for safety */ uwep->age = rn1(500,1000); if (uwep->lamplit) begin_burn(uwep, TRUE); + update_inventory(); } else if (rn2(2) && !Blind) You("see a puff of smoke."); else pline(nothing_happens); @@ -1180,6 +1241,11 @@ int magic; /* 0=Physical, otherwise skill level */ pline("This calls for swimming, not jumping!"); return 0; } else if (u.ustuck) { + if (u.ustuck->mtame && !Conflict && !u.ustuck->mconf) { + You("pull free from %s.", mon_nam(u.ustuck)); + u.ustuck = 0; + return 1; + } if (magic) { You("writhe a little in the grasp of %s!", mon_nam(u.ustuck)); return 1; @@ -1206,7 +1272,7 @@ int magic; /* 0=Physical, otherwise skill level */ if (wl == BOTH_SIDES) bp = makeplural(bp); #ifdef STEED if (u.usteed) - pline("%s is in no shape for jumping.", Monnam(u.usteed)); + pline("%s is in no shape for jumping.", Monnam(u.usteed)); else #endif Your("%s%s %s in no shape for jumping.", @@ -1424,16 +1490,13 @@ struct obj *obj; /* collect property troubles */ if (Sick) prop_trouble(SICK); - if (Blinded > (long)(u.ucreamed + 1)) prop_trouble(BLINDED); + if (Blinded > (long)u.ucreamed) prop_trouble(BLINDED); if (HHallucination) prop_trouble(HALLUC); if (Vomiting) prop_trouble(VOMITING); if (HConfusion) prop_trouble(CONFUSION); if (HStun) prop_trouble(STUNNED); - /* keep track of unfixed trouble, for message adjustment below - (can't "feel great" with these problems present) */ - if (Stoned) unfixable_trbl++; - if (Strangled) unfixable_trbl++; - if (Wounded_legs) unfixable_trbl++; + + unfixable_trbl = unfixable_trouble_count(TRUE); /* collect attribute troubles */ for (idx = 0; idx < A_MAX; idx++) { @@ -1482,7 +1545,7 @@ struct obj *obj; did_prop++; break; case prop2trbl(BLINDED): - make_blinded(u.ucreamed ? (long)(u.ucreamed+1) : 0L, TRUE); + make_blinded((long)u.ucreamed, TRUE); did_prop++; break; case prop2trbl(HALLUC): @@ -1551,17 +1614,17 @@ long timeout; silent = (timeout != monstermoves); /* happened while away */ okay_spot = get_obj_location(figurine, &cc.x, &cc.y, 0); if (figurine->where == OBJ_INVENT || - figurine->where == OBJ_MINVENT) - okay_spot = enexto(&cc, cc.x, cc.y, + figurine->where == OBJ_MINVENT) + okay_spot = enexto(&cc, cc.x, cc.y, &mons[figurine->corpsenm]); if (!okay_spot || !figurine_location_checks(figurine,&cc, TRUE)) { - /* reset the timer to try again later */ + /* reset the timer to try again later */ (void) start_timer((long)rnd(5000), TIMER_OBJECT, FIG_TRANSFORM, (genericptr_t)figurine); return; } - + cansee_spot = cansee(cc.x, cc.y); mtmp = make_familiar(figurine, cc.x, cc.y, TRUE); if (mtmp) { @@ -1587,8 +1650,8 @@ long timeout; case OBJ_MINVENT: if (cansee_spot && !silent) { - struct monst *mon; - mon = figurine->ocarry; + struct monst *mon; + mon = figurine->ocarry; /* figurine carring monster might be invisible */ if (canseemon(figurine->ocarry)) { Sprintf(carriedby, "%s pack", @@ -1626,7 +1689,7 @@ coord *cc; boolean quietly; { xchar x,y; - + x = cc->x; y = cc->y; if (!isok(x,y)) { if (!quietly) @@ -1636,7 +1699,8 @@ boolean quietly; if (IS_ROCK(levl[x][y].typ) && !(passes_walls(&mons[obj->corpsenm]) && may_passwall(x,y))) { if (!quietly) - You("cannot place a figurine in solid rock!"); + You("cannot place a figurine in %s!", + IS_TREE(levl[x][y].typ) ? "a tree" : "solid rock"); return FALSE; } if (sobj_at(BOULDER,x,y) && !passes_walls(&mons[obj->corpsenm]) @@ -1654,7 +1718,7 @@ register struct obj *obj; { xchar x, y; coord cc; - + if(!getdir((char *)0)) { flags.move = multi = 0; return; @@ -1688,7 +1752,7 @@ struct obj *obj; if (Glib) { dropx(obj); - pline("%s slips from your %s.", The(xname(obj)), + pline("%s from your %s.", Tobjnam(obj, "slip"), makeplural(body_part(FINGER))); return; } @@ -1698,7 +1762,7 @@ struct obj *obj; check_unpaid(obj); obj->spe--; dropx(obj); - pline("%s slips from your %s.", The(xname(obj)), + pline("%s from your %s.", Tobjnam(obj, "slip"), makeplural(body_part(FINGER))); return; } @@ -1735,9 +1799,12 @@ struct obj *obj; makeplural(body_part(FINGER))); } } else { - pline("%s %s empty.", The(xname(obj)), - obj->known ? "is" : "seems to be"); + if (obj->known) + pline("%s empty.", Tobjnam(obj, "are")); + else + pline("%s to be empty.", Tobjnam(obj, "seem")); } + update_inventory(); } static struct trapinfo { @@ -1752,6 +1819,138 @@ reset_trapset() trapinfo.tobj = 0; } +/* touchstones - by Ken Arnold */ +STATIC_OVL void +use_stone(tstone) +struct obj *tstone; +{ + struct obj *obj; + boolean do_scratch; + const char *streak_color; + char stonebuf[QBUFSZ]; + static const char scritch[] = "\"scritch, scritch\""; + static char allowall[3] = { GOLD_CLASS, ALL_CLASSES, 0 }; +#ifndef GOLDOBJ + struct obj goldobj; +#endif + + Sprintf(stonebuf, "rub on the stone%s", plur(tstone->quan)); + if ((obj = getobj(allowall, stonebuf)) == 0) + return; +#ifndef GOLDOBJ + if (obj->oclass == GOLD_CLASS) { + u.ugold += obj->quan; /* keep botl up to date */ + goldobj = *obj; + dealloc_obj(obj); + obj = &goldobj; + } +#endif + + if (obj == tstone && obj->quan == 1) { + You_cant("rub %s on itself.", the(xname(obj))); + return; + } + + if (tstone->otyp == TOUCHSTONE && tstone->cursed && + obj->oclass == GEM_CLASS && !is_graystone(obj) && + !obj_resists(obj, 80, 100)) { + if (Blind) + pline("You feel something shatter."); + else if (Hallucination) + pline("Oh, wow, look at the pretty shards."); + else + pline("A sharp crack shatters %s%s.", + (obj->quan > 1) ? "one of " : "", the(xname(obj))); +#ifndef GOLDOBJ + /* assert(obj != &goldobj); */ +#endif + useup(obj); + return; + } + + if (Blind) { + pline(scritch); + return; + } else if (Hallucination) { + pline("Oh wow, man: Fractals!"); + return; + } + + do_scratch = FALSE; + streak_color = 0; + + switch (obj->oclass) { + case GEM_CLASS: /* these have class-specific handling below */ + case RING_CLASS: + if (tstone->otyp != TOUCHSTONE) { + do_scratch = TRUE; + } else if (obj->oclass == GEM_CLASS && (tstone->blessed || + (!tstone->cursed && + (Role_if(PM_ARCHEOLOGIST) || Race_if(PM_GNOME))))) { + makeknown(TOUCHSTONE); + makeknown(obj->otyp); + prinv((char *)0, obj, 0L); + return; + } else { + /* either a ring or the touchstone was not effective */ + if (objects[obj->otyp].oc_material == GLASS) { + do_scratch = TRUE; + break; + } + } + streak_color = c_obj_colors[objects[obj->otyp].oc_color]; + break; /* gem or ring */ + + default: + switch (objects[obj->otyp].oc_material) { + case CLOTH: + pline("%s a little more polished now.", Tobjnam(tstone, "look")); + return; + case LIQUID: + if (!obj->known) /* note: not "whetstone" */ + You("must think this is a wetstone, do you?"); + else + pline("%s a little wetter now.", Tobjnam(tstone, "are")); + return; + case WAX: + streak_color = "waxy"; + break; /* okay even if not touchstone */ + case WOOD: + streak_color = "wooden"; + break; /* okay even if not touchstone */ + case GOLD: + do_scratch = TRUE; /* scratching and streaks */ + streak_color = "golden"; + break; + case SILVER: + do_scratch = TRUE; /* scratching and streaks */ + streak_color = "silvery"; + break; + default: + /* Objects passing the is_flimsy() test will not + scratch a stone. They will leave streaks on + non-touchstones and touchstones alike. */ + if (is_flimsy(obj)) + streak_color = c_obj_colors[objects[obj->otyp].oc_color]; + else + do_scratch = (tstone->otyp != TOUCHSTONE); + break; + } + break; /* default oclass */ + } + + Sprintf(stonebuf, "stone%s", plur(tstone->quan)); + if (do_scratch) + pline("You make %s%sscratch marks on the %s.", + streak_color ? streak_color : (const char *)"", + streak_color ? " " : "", stonebuf); + else if (streak_color) + pline("You see %s streaks on the %s.", streak_color, stonebuf); + else + pline(scritch); + return; +} + /* Place a landmine/bear trap. Helge Hafting */ STATIC_OVL void use_trap(otmp) @@ -1845,7 +2044,7 @@ set_trap() } You("finish arming %s.", the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation)); - if ((otmp->cursed || Fumbling) && (rnl(10) > 5)) dotrap(ttmp); + if ((otmp->cursed || Fumbling) && (rnl(10) > 5)) dotrap(ttmp, 0); } else { /* this shouldn't happen */ Your("trap setting attempt fails."); @@ -1930,16 +2129,14 @@ struct obj *obj; dam = rnd(2) + dbon() + obj->spe; if (dam <= 0) dam = 1; You("hit your %s with your bullwhip.", body_part(FOOT)); - /* self_pronoun() won't work twice in a sentence */ - Strcpy(buf, self_pronoun("killed %sself with %%s bullwhip", "him")); - losehp(dam, self_pronoun(buf, "his"), NO_KILLER_PREFIX); + Sprintf(buf, "killed %sself with %s bullwhip", uhim(), uhis()); + losehp(dam, buf, NO_KILLER_PREFIX); flags.botl = 1; return 1; } else if ((Fumbling || Glib) && !rn2(5)) { pline_The("bullwhip slips out of your %s.", body_part(HAND)); dropx(obj); - setuwep((struct obj *)0); } else if (u.utrap && u.utraptype == TT_PIT) { /* @@ -2005,7 +2202,7 @@ struct obj *obj; const char *mon_hand; boolean gotit = proficient && (!Fumbling || !rn2(10)); - Strcpy(onambuf, xname(otmp)); + Strcpy(onambuf, cxname(otmp)); if (gotit) { mon_hand = mbodypart(mtmp, HAND); if (bimanual(otmp)) mon_hand = makeplural(mon_hand); @@ -2017,7 +2214,7 @@ struct obj *obj; if (gotit && otmp->cursed) { pline("%s welded to %s %s%c", (otmp->quan == 1L) ? "It is" : "They are", - his[pronoun_gender(mtmp)], mon_hand, + mhis(mtmp), mon_hand, !otmp->bknown ? '!' : '.'); otmp->bknown = 1; gotit = FALSE; /* can't pull it free */ @@ -2025,18 +2222,13 @@ struct obj *obj; if (gotit) { obj_extract_self(otmp); possibly_unwield(mtmp); - otmp->owornmask &= ~W_WEP; + setmnotwielded(mtmp,otmp); switch (rn2(proficient + 1)) { case 2: /* to floor near you */ You("yank %s %s to the %s!", s_suffix(mon_nam(mtmp)), onambuf, surface(u.ux, u.uy)); - if (otmp->otyp == CRYSKNIFE && - (!otmp->oerodeproof || !rn2(10))) { - otmp->otyp = WORM_TOOTH; - otmp->oerodeproof = 0; - } place_object(otmp, u.ux, u.uy); stackobj(otmp); break; @@ -2053,7 +2245,7 @@ struct obj *obj; dmgval(otmp, &youmonst), otmp, (char *)0); if (hitu) { - You("The %s hits you as you try to snatch it!", + pline_The("%s hits you as you try to snatch it!", the(onambuf)); } place_object(otmp, u.ux, u.uy); @@ -2071,7 +2263,7 @@ struct obj *obj; char kbuf[BUFSZ]; Sprintf(kbuf, "%s corpse", - an(mons[otmp->corpsenm].mname)); + an(mons[otmp->corpsenm].mname)); pline("Snatching %s is a fatal mistake.", kbuf); instapetrify(kbuf); } @@ -2082,11 +2274,7 @@ struct obj *obj; /* to floor beneath mon */ You("yank %s from %s %s!", the(onambuf), s_suffix(mon_nam(mtmp)), mon_hand); - if (otmp->otyp == CRYSKNIFE && - (!otmp->oerodeproof || !rn2(10))) { - otmp->otyp = WORM_TOOTH; - otmp->oerodeproof = 0; - } + obj_no_longer_held(otmp); place_object(otmp, mtmp->mx, mtmp->my); stackobj(otmp); break; @@ -2096,7 +2284,10 @@ struct obj *obj; } wakeup(mtmp); } else { - You("flick your bullwhip towards %s.", mon_nam(mtmp)); + if (mtmp->m_ap_type && + !Protection_from_shape_changers && !sensemon(mtmp)) + stumble_onto_mimic(mtmp); + else You("flick your bullwhip towards %s.", mon_nam(mtmp)); if (proficient) { if (attack(mtmp)) return 1; else pline(msg_snap); @@ -2165,9 +2356,17 @@ use_pole (obj) } /* Attack the monster there */ - if ((mtmp = m_at(cc.x, cc.y)) != (struct monst *)0) + if ((mtmp = m_at(cc.x, cc.y)) != (struct monst *)0) { + int oldhp = mtmp->mhp; + (void) thitmonst(mtmp, uwep); - else + /* check the monster's HP because thitmonst() doesn't return + * an indication of whether it hit. Not perfect (what if it's a + * non-silver weapon on a shade?) + */ + if (mtmp->mhp < oldhp) + u.uconduct.weaphit++; + } else /* Now you know that nothing is there... */ pline(nothing_happens); return (1); @@ -2215,8 +2414,7 @@ use_grapple (obj) } /* What did you hit? */ - switch (rn2(5)) - { + switch (rn2(5)) { case 0: /* Trap */ /* FIXME -- untrap needs to deal with non-adjacent traps */ break; @@ -2244,9 +2442,13 @@ use_grapple (obj) } /* FALL THROUGH */ case 3: /* Surface */ - You("are yanked toward the %s!", - surface(cc.x, cc.y)); - hurtle(sgn(cc.x-u.ux), sgn(cc.y-u.uy), 1, FALSE); + if (IS_AIR(levl[cc.x][cc.y].typ) || is_pool(cc.x, cc.y)) + pline_The("hook slices through the %s.", surface(cc.x, cc.y)); + else { + You("are yanked toward the %s!", surface(cc.x, cc.y)); + hurtle(sgn(cc.x-u.ux), sgn(cc.y-u.uy), 1, FALSE); + spoteffects(TRUE); + } return (1); default: /* Yourself (oops!) */ if (P_SKILL(typ) <= P_BASIC) { @@ -2273,7 +2475,8 @@ do_break_wand(obj) register struct monst *mon; int dmg, damage; boolean affects_objects; - char confirm[QBUFSZ], the_wand[BUFSZ]; + int expltype = EXPL_MAGICAL; + char confirm[QBUFSZ], the_wand[BUFSZ], buf[BUFSZ]; Strcpy(the_wand, yname(obj)); Sprintf(confirm, "Are you really sure you want to break %s?", the_wand); @@ -2289,6 +2492,14 @@ do_break_wand(obj) pline("Raising %s high above your %s, you break it in two!", the_wand, body_part(HEAD)); + /* [ALI] Do this first so that wand is removed from bill. Otherwise, + * the freeinv() below also hides it from setpaid() which causes problems. + */ + if (obj->unpaid) { + check_unpaid(obj); /* Extra charge for use */ + bill_dummy_object(obj); + } + current_wand = obj; /* destroy_item might reset this */ freeinv(obj); /* hide it from destroy_item instead... */ setnotworn(obj); /* so we need to do this ourselves */ @@ -2314,12 +2525,17 @@ do_break_wand(obj) goto discard_broken_wand; case WAN_DEATH: case WAN_LIGHTNING: - dmg *= 2; + dmg *= 4; + goto wanexpl; case WAN_FIRE: + expltype = EXPL_FIERY; case WAN_COLD: + if (expltype == EXPL_MAGICAL) expltype = EXPL_FROSTY; dmg *= 2; case WAN_MAGIC_MISSILE: - explode(u.ux, u.uy, (obj->otyp - WAN_MAGIC_MISSILE), dmg, WAND_CLASS); + wanexpl: + explode(u.ux, u.uy, + (obj->otyp - WAN_MAGIC_MISSILE), dmg, WAND_CLASS, expltype); makeknown(obj->otyp); /* explode described the effect */ goto discard_broken_wand; case WAN_STRIKING: @@ -2337,7 +2553,7 @@ do_break_wand(obj) } /* magical explosion and its visual effect occur before specific effects */ - explode(obj->ox, obj->oy, 0, rnd(dmg), WAND_CLASS); + explode(obj->ox, obj->oy, 0, rnd(dmg), WAND_CLASS, EXPL_MAGICAL); /* this makes it hit us last, so that we can see the action first */ for (i = 0; i <= 8; i++) { @@ -2366,11 +2582,10 @@ do_break_wand(obj) if (flags.botl) bot(); /* potion effects */ } damage = zapyourself(obj, FALSE); - if (damage) - losehp(damage, - self_pronoun("killed %sself by breaking a wand", - "him"), - NO_KILLER_PREFIX); + if (damage) { + Sprintf(buf, "killed %sself by breaking a wand", uhim()); + losehp(damage, buf, NO_KILLER_PREFIX); + } if (flags.botl) bot(); /* blindness */ } else if ((mon = m_at(x, y)) != 0) { (void) bhitm(mon, obj); @@ -2389,15 +2604,23 @@ do_break_wand(obj) discard_broken_wand: obj = current_wand; /* [see dozap() and destroy_item()] */ current_wand = 0; - if (obj) { - /* extra charge for _use_ prior to destruction */ - check_unpaid(obj); + if (obj) delobj(obj); - } nomul(0); return 1; } +STATIC_OVL boolean +uhave_graystone() +{ + register struct obj *otmp; + + for(otmp = invent; otmp; otmp = otmp->nobj) + if(is_graystone(otmp)) + return TRUE; + return FALSE; +} + int doapply() { @@ -2405,7 +2628,8 @@ doapply() register int res = 1; if(check_capacity((char *)0)) return (0); - obj = getobj(carrying(POT_OIL) ? tools_too : tools, "use or apply"); + obj = getobj(carrying(POT_OIL) || uhave_graystone() + ? tools_too : tools, "use or apply"); if(!obj) return 0; if (obj->oclass == WAND_CLASS) @@ -2419,7 +2643,7 @@ doapply() } else if (!ublindf) Blindf_on(obj); else You("are already %s.", - ublindf->otyp == TOWEL ? "covered by a towel" : + ublindf->otyp == TOWEL ? "covered by a towel" : ublindf->otyp == BLINDFOLD ? "wearing a blindfold" : "wearing lenses"); break; @@ -2589,6 +2813,12 @@ doapply() case BEARTRAP: use_trap(obj); break; + case FLINT: + case LUCKSTONE: + case LOADSTONE: + case TOUCHSTONE: + use_stone(obj); + break; default: /* Pole-weapons can strike at a distance */ if (is_pole(obj)) { @@ -2608,6 +2838,37 @@ doapply() return res; } +/* Keep track of unfixable troubles for purposes of messages saying you feel + * great. + */ +int unfixable_trouble_count(is_horn) + boolean is_horn; +{ + int unfixable_trbl = 0; + + if (Stoned) unfixable_trbl++; + if (Strangled) unfixable_trbl++; + if (Wounded_legs +#ifdef STEED + && !u.usteed +#endif + ) unfixable_trbl++; + if (Slimed) unfixable_trbl++; + /* lycanthropy is not desirable, but it doesn't actually make you feel + bad */ + + /* we'll assume that intrinsic stunning from being a bat/stalker + doesn't make you feel bad */ + if (!is_horn) { + if (Confusion) unfixable_trbl++; + if (Sick) unfixable_trbl++; + if (HHallucination) unfixable_trbl++; + if (Vomiting) unfixable_trbl++; + if (HStun) unfixable_trbl++; + } + return unfixable_trbl; +} + #endif /* OVLB */ /*apply.c*/ diff --git a/src/artifact.c b/src/artifact.c index a0e7850..a8db867 100644 --- a/src/artifact.c +++ b/src/artifact.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)artifact.c 3.3 2000/01/11 */ +/* SCCS Id: @(#)artifact.c 3.4 2002/02/21 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -23,13 +23,15 @@ extern boolean notonhead; /* for long worms */ STATIC_DCL int FDECL(spec_applies, (const struct artifact *,struct monst *)); STATIC_DCL int FDECL(arti_invoke, (struct obj*)); -/* The amount added to normal damage which should guarantee that the +/* The amount added to the victim's total hit points to insure that the victim will be killed even after damage bonus/penalty adjustments. - It needs to be big enough so that halving will still kill, but not - so big that doubling ends up overflowing 15 bits. This value used - to be 1234, but it was possible for players to accumulate enough - hit points so that taking (uhp + 1234)/2 damage was survivable. */ -#define FATAL_DAMAGE 9999 + Most such penalties are small, and 200 is plenty; the exception is + half physical damage. 3.3.1 and previous versions tried to use a very + large number to account for this case; now, we just compute the fatal + damage by adding it to 2 times the total hit points instead of 1 time. + Note: this will still break if they have more than about half the number + of hit points that will fit in a 15 bit integer. */ +#define FATAL_DAMAGE_MODIFIER 200 #ifndef OVLB STATIC_DCL int spec_dbon_applies; @@ -60,7 +62,7 @@ hack_artifacts() /* Excalibur can be used by any lawful character, not just knights */ if (!Role_if(PM_KNIGHT)) - artilist[ART_EXCALIBUR].role = 0; /****FIXME****/ + artilist[ART_EXCALIBUR].role = NON_PM; /* Fix up the quest artifact */ if (urole.questarti) { @@ -472,16 +474,18 @@ touch_artifact(obj,mon) /* all quest artifacts are self-willed; it this ever changes, `badclass' will have to be extended to explicitly include quest artifacts */ self_willed = ((oart->spfx & SPFX_INTEL) != 0); - if (yours || !(mon->data->mflags3 & M3_WANTSALL)) { - badclass = (self_willed && (!yours || - (oart->role != NON_PM && !Role_if(oart->role)) || - (oart->race != NON_PM && !Race_if(oart->race)))); - badalign = (oart->spfx & SPFX_RESTR) && - oart->alignment != A_NONE && - ((oart->alignment != - (yours ? u.ualign.type : sgn(mon->data->maligntyp))) || - (yours && u.ualign.record < 0)); - } else { /* an M3_WANTSxxx monster */ + if (yours) { + badclass = self_willed && + ((oart->role != NON_PM && !Role_if(oart->role)) || + (oart->race != NON_PM && !Race_if(oart->race))); + badalign = (oart->spfx & SPFX_RESTR) && oart->alignment != A_NONE && + (oart->alignment != u.ualign.type || u.ualign.record < 0); + } else if (!is_covetous(mon->data) && !is_mplayer(mon->data)) { + badclass = self_willed && + oart->role != NON_PM && oart != &artilist[ART_EXCALIBUR]; + badalign = (oart->spfx & SPFX_RESTR) && oart->alignment != A_NONE && + (oart->alignment != sgn(mon->data->maligntyp)); + } else { /* an M3_WANTSxxx monster or a fake player */ /* special monsters trying to take the Amulet, invocation tools or quest item can touch anything except for `spec_applies' artifacts */ badclass = badalign = FALSE; @@ -511,7 +515,7 @@ touch_artifact(obj,mon) /* can pick it up unless you're totally non-synch'd with the artifact */ if (badclass && badalign && self_willed) { - if (yours) pline("%s evades your grasp!", The(xname(obj))); + if (yours) pline("%s your grasp!", Tobjnam(obj, "evade")); return 0; } @@ -596,8 +600,11 @@ struct monst *mon; { register const struct artifact *weap = get_artifact(otmp); - if (weap && spec_applies(weap, mon)) - return weap->attk.damn ? rnd((int)weap->attk.damn) : 0; + /* no need for an extra check for `NO_ATTK' because this will + always return 0 for any artifact which has that attribute */ + + if (weap && weap->attk.damn && spec_applies(weap, mon)) + return rnd((int)weap->attk.damn); return 0; } @@ -610,7 +617,13 @@ int tmp; { register const struct artifact *weap = get_artifact(otmp); - if ((spec_dbon_applies = (weap && spec_applies(weap, mon))) != 0) + if (!weap || (weap->attk.adtyp == AD_PHYS && /* check for `NO_ATTK' */ + weap->attk.damn == 0 && weap->attk.damd == 0)) + spec_dbon_applies = FALSE; + else + spec_dbon_applies = spec_applies(weap, mon); + + if (spec_dbon_applies) return weap->attk.damd ? rnd((int)weap->attk.damd) : max(tmp,1); return 0; } @@ -695,9 +708,11 @@ int dieroll; /* needed for Magicbane and vorpal blades */ boolean vis = (!youattack && magr && cansee(magr->mx, magr->my)) || (!youdefend && cansee(mdef->mx, mdef->my)); boolean realizes_damage; - + const char *wepdesc; static const char you[] = "you"; - const char *hittee = youdefend ? you : mon_nam(mdef); + char hittee[BUFSZ]; + + Strcpy(hittee, youdefend ? you : mon_nam(mdef)); /* The following takes care of most of the damage, but not all-- * the exception being for level draining, which is specially @@ -706,51 +721,61 @@ int dieroll; /* needed for Magicbane and vorpal blades */ *dmgptr += spec_dbon(otmp, mdef, *dmgptr); if (youattack && youdefend) { - impossible("attacking yourself with weapon?"); - return FALSE; - } else if (!spec_dbon_applies) { - /* since damage bonus didn't apply, nothing more to do */ - return FALSE; + impossible("attacking yourself with weapon?"); + return FALSE; } realizes_damage = (youdefend || vis); /* the four basic attacks: fire, cold, shock and missiles */ if (attacks(AD_FIRE, otmp)) { - if (realizes_damage) { - pline_The("fiery blade %s %s!", + if (realizes_damage) + pline_The("fiery blade %s %s%c", + !spec_dbon_applies ? "hits" : (mdef->data == &mons[PM_WATER_ELEMENTAL]) ? - "vaporizes part of" : "burns", hittee); - if (!rn2(4)) (void) destroy_mitem(mdef, POTION_CLASS, AD_FIRE); - if (!rn2(4)) (void) destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE); - if (!rn2(7)) (void) destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE); - return TRUE; - } + "vaporizes part of" : "burns", + hittee, !spec_dbon_applies ? '.' : '!'); + if (!rn2(4)) (void) destroy_mitem(mdef, POTION_CLASS, AD_FIRE); + if (!rn2(4)) (void) destroy_mitem(mdef, SCROLL_CLASS, AD_FIRE); + if (!rn2(7)) (void) destroy_mitem(mdef, SPBOOK_CLASS, AD_FIRE); + if (youdefend && Slimed) burn_away_slime(); + return realizes_damage; } if (attacks(AD_COLD, otmp)) { - if (realizes_damage) { - pline_The("ice-cold blade freezes %s!", hittee); - if (!rn2(4)) (void) destroy_mitem(mdef, POTION_CLASS, AD_COLD); - return TRUE; - } + if (realizes_damage) + pline_The("ice-cold blade %s %s%c", + !spec_dbon_applies ? "hits" : "freezes", + hittee, !spec_dbon_applies ? '.' : '!'); + if (!rn2(4)) (void) destroy_mitem(mdef, POTION_CLASS, AD_COLD); + return realizes_damage; } if (attacks(AD_ELEC, otmp)) { if (realizes_damage) { - if(youattack && otmp != uwep) - pline("%s hits %s!", The(xname(otmp)), hittee); - pline("Lightning strikes %s!", hittee); - if (!rn2(5)) (void) destroy_mitem(mdef, RING_CLASS, AD_ELEC); - if (!rn2(5)) (void) destroy_mitem(mdef, WAND_CLASS, AD_ELEC); - return TRUE; + if (youattack ? otmp != uwep : !spec_dbon_applies) + pline("%s %s%c", Tobjnam(otmp, "hit"), + hittee, !spec_dbon_applies ? '.' : '!'); + if (spec_dbon_applies) + pline("Lightning strikes %s!", hittee); } + if (!rn2(5)) (void) destroy_mitem(mdef, RING_CLASS, AD_ELEC); + if (!rn2(5)) (void) destroy_mitem(mdef, WAND_CLASS, AD_ELEC); + return realizes_damage; } if (attacks(AD_MAGM, otmp)) { - if (realizes_damage) { - if(youattack && otmp != uwep) - pline("%s hits %s!", The(xname(otmp)), hittee); - pline("A hail of magic missiles strikes %s!", hittee); - return TRUE; - } + if (realizes_damage) { + if (youattack ? otmp != uwep : !spec_dbon_applies) + pline("%s %s%c", Tobjnam(otmp, "hit"), + hittee, !spec_dbon_applies ? '.' : '!'); + if (spec_dbon_applies) + pline("A hail of magic missiles strikes %s!", hittee); + } + return realizes_damage; + } + + if (!spec_dbon_applies) { + /* since damage bonus didn't apply, nothing more to do; + no further attacks have side-effects on inventory */ + return FALSE; } /* @@ -803,7 +828,7 @@ int dieroll; /* needed for Magicbane and vorpal blades */ else { nomul(-3); nomovemsg = ""; - if ((magr == u.ustuck) + if (magr && magr == u.ustuck && sticks(youmonst.data)) { u.ustuck = (struct monst *)0; You("release %s!", mon_nam(magr)); @@ -813,18 +838,7 @@ int dieroll; /* needed for Magicbane and vorpal blades */ if (rn2(2) && resist(mdef,SPBOOK_CLASS,0,0)) { MB_RESIST_ATTACK; } else { - if (mdef == u.ustuck) { - if (u.uswallow) - expels(mdef,mdef->data,TRUE); - else { - if (!sticks(youmonst.data)) { - u.ustuck = (struct monst *)0; - You("get released!"); - } - } - } - mdef->mflee = 1; - mdef->mfleetim += 3; + monflee(mdef, 3, FALSE, TRUE); } } } @@ -926,10 +940,11 @@ int dieroll; /* needed for Magicbane and vorpal blades */ /* reverse from AD&D. */ if (spec_ability(otmp, SPFX_BEHEAD)) { if (otmp->oartifact == ART_TSURUGI_OF_MURAMASA && dieroll == 1) { + wepdesc = "The razor-sharp blade"; /* not really beheading, but so close, why add another SPFX */ if (youattack && u.uswallow && mdef == u.ustuck) { You("slice %s wide open!", mon_nam(mdef)); - *dmgptr = mdef->mhp + FATAL_DAMAGE; + *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER; return TRUE; } if (!youdefend) { @@ -943,19 +958,18 @@ int dieroll; /* needed for Magicbane and vorpal blades */ mon_nam(mdef)); else if (vis) pline("%s cuts deeply into %s!", - Monnam(magr), mon_nam(mdef)); + Monnam(magr), hittee); *dmgptr *= 2; return TRUE; } - *dmgptr = mdef->mhp + FATAL_DAMAGE; - pline_The("razor-sharp blade cuts %s in half!", - mon_nam(mdef)); + *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER; + pline("%s cuts %s in half!", wepdesc, mon_nam(mdef)); otmp->dknown = TRUE; return TRUE; } else { if (bigmonst(youmonst.data)) { pline("%s cuts deeply into you!", - Monnam(magr)); + magr ? Monnam(magr) : wepdesc); *dmgptr *= 2; return TRUE; } @@ -965,8 +979,8 @@ int dieroll; /* needed for Magicbane and vorpal blades */ * value to the damage so that this reduction in * damage does not prevent death. */ - *dmgptr = (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE; - pline_The("razor-sharp blade cuts you in half!"); + *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE_MODIFIER; + pline("%s cuts you in half!", wepdesc); otmp->dknown = TRUE; return TRUE; } @@ -979,6 +993,7 @@ int dieroll; /* needed for Magicbane and vorpal blades */ if (youattack && u.uswallow && mdef == u.ustuck) return FALSE; + wepdesc = artilist[ART_VORPAL_BLADE].name; if (!youdefend) { if (!has_head(mdef->data) || notonhead || u.uswallow) { if (youattack) @@ -991,32 +1006,32 @@ int dieroll; /* needed for Magicbane and vorpal blades */ return ((boolean)(youattack || vis)); } if (noncorporeal(mdef->data) || amorphous(mdef->data)) { - pline("%s slices through %s %s.", - artilist[ART_VORPAL_BLADE].name, - s_suffix(mon_nam(mdef)), mbodypart(mdef,NECK)); + pline("%s slices through %s %s.", wepdesc, + s_suffix(mon_nam(mdef)), + mbodypart(mdef,NECK)); return TRUE; } - *dmgptr = mdef->mhp + FATAL_DAMAGE; + *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER; pline(behead_msg[rn2(SIZE(behead_msg))], - artilist[ART_VORPAL_BLADE].name, - mon_nam(mdef)); + wepdesc, mon_nam(mdef)); otmp->dknown = TRUE; return TRUE; } else { if (!has_head(youmonst.data)) { pline("Somehow, %s misses you wildly.", - mon_nam(magr)); + magr ? mon_nam(magr) : wepdesc); *dmgptr = 0; return TRUE; } if (noncorporeal(youmonst.data) || amorphous(youmonst.data)) { pline("%s slices through your %s.", - artilist[ART_VORPAL_BLADE].name, body_part(NECK)); + wepdesc, body_part(NECK)); return TRUE; } - *dmgptr = (Upolyd ? u.mh : u.uhp) + FATAL_DAMAGE; + *dmgptr = 2 * (Upolyd ? u.mh : u.uhp) + + FATAL_DAMAGE_MODIFIER; pline(behead_msg[rn2(SIZE(behead_msg))], - artilist[ART_VORPAL_BLADE].name, "you"); + wepdesc, "you"); otmp->dknown = TRUE; /* Should amulets fall off? */ return TRUE; @@ -1036,7 +1051,7 @@ int dieroll; /* needed for Magicbane and vorpal blades */ mon_nam(mdef)); } if (mdef->m_lev == 0) { - *dmgptr = mdef->mhp + FATAL_DAMAGE; + *dmgptr = 2 * mdef->mhp + FATAL_DAMAGE_MODIFIER; } else { int drain = rnd(8); *dmgptr += drain; @@ -1060,7 +1075,7 @@ int dieroll; /* needed for Magicbane and vorpal blades */ pline("%s drains your life!", The(distant_name(otmp, xname))); losexp("life drainage"); - if (magr->mhp < magr->mhpmax) { + if (magr && magr->mhp < magr->mhpmax) { magr->mhp += (u.uhpmax - oldhpmax)/2; if (magr->mhp > magr->mhpmax) magr->mhp = magr->mhpmax; } @@ -1111,17 +1126,19 @@ arti_invoke(obj) switch(oart->inv_prop) { case TAMING: { - struct obj *pseudo = mksobj(SPE_CHARM_MONSTER, FALSE, FALSE); - pseudo->blessed = pseudo->cursed = 0; - pseudo->quan = 20L; /* do not let useup get it */ - (void) seffects(pseudo); - obfree(pseudo, (struct obj *)0); /* now, get rid of it */ + struct obj pseudo; + + pseudo = zeroobj; /* neither cursed nor blessed */ + pseudo.otyp = SCR_TAMING; + (void) seffects(&pseudo); break; } case HEALING: { int healamt = (u.uhpmax + 1 - u.uhp) / 2; + long creamed = (long)u.ucreamed; + if (Upolyd) healamt = (u.mhmax + 1 - u.mh) / 2; - if(healamt || Sick || (Blinded > 1)) + if (healamt || Sick || Blinded > creamed) You_feel("better."); else goto nothing_special; @@ -1131,7 +1148,7 @@ arti_invoke(obj) } if(Sick) make_sick(0L,(char *)0,FALSE,SICK_ALL); if(Slimed) Slimed = 0L; - if(Blinded > 1) make_blinded(0L,FALSE); + if (Blinded > creamed) make_blinded(creamed, FALSE); flags.botl = 1; break; } @@ -1162,8 +1179,10 @@ arti_invoke(obj) obj->age = 0; return 0; } - b_effect = obj->blessed && (Role_switch == oart->role || !oart->role); + b_effect = obj->blessed && + (Role_switch == oart->role || !oart->role); recharge(otmp, b_effect ? 1 : obj->cursed ? -1 : 0); + update_inventory(); break; } case LEV_TELE: @@ -1276,8 +1295,10 @@ arti_invoke(obj) else You_feel("the tension decrease around you."); break; case LEVITATION: - if(on) float_up(); - else (void) float_down(I_SPECIAL|TIMEOUT, W_ARTI); + if(on) { + float_up(); + spoteffects(FALSE); + } else (void) float_down(I_SPECIAL|TIMEOUT, W_ARTI); break; case INVIS: if (!See_invisible && !Blind) { @@ -1297,6 +1318,14 @@ arti_invoke(obj) } +/* WAC return TRUE if artifact is always lit */ +boolean +artifact_light(obj) + struct obj *obj; +{ + return (get_artifact(obj) && obj->oartifact == ART_SUNSWORD); +} + /* KMH -- Talking artifacts are finally implemented */ void arti_speak(obj) struct obj *obj; @@ -1313,11 +1342,33 @@ void arti_speak(obj) line = getrumor(bcsign(obj), buf, TRUE); if (!*line) line = "NetHack rumors file closed for renovation."; - pline("%s whispers:", The(xname(obj))); + pline("%s:", Tobjnam(obj, "whisper")); verbalize("%s", line); return; } +boolean +artifact_has_invprop(otmp, inv_prop) +struct obj *otmp; +uchar inv_prop; +{ + const struct artifact *arti = get_artifact(otmp); + + return((boolean)(arti && (arti->inv_prop == inv_prop))); +} + +/* Return the price sold to the hero of a given artifact or unique item */ +long +arti_cost(otmp) +struct obj *otmp; +{ + if (!otmp->oartifact) + return ((long)objects[otmp->otyp].oc_cost); + else if (artilist[(int) otmp->oartifact].cost) + return (artilist[(int) otmp->oartifact].cost); + else + return (100L * (long)objects[otmp->otyp].oc_cost); +} #endif /* OVLB */ diff --git a/src/attrib.c b/src/attrib.c index f0c8c0b..0605cda 100644 --- a/src/attrib.c +++ b/src/attrib.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)attrib.c 3.3 2000/05/17 */ +/* SCCS Id: @(#)attrib.c 3.4 2000/05/17 */ /* Copyright 1988, 1989, 1990, 1992, M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ @@ -155,7 +155,7 @@ adjattrib(ndx, incr, msgflg) (incr > 1 || incr < -1) ? "very ": "", (incr > 0) ? plusattr[ndx] : minusattr[ndx]); flags.botl = 1; - if (moves > 0 && (ndx == A_STR || ndx == A_CON)) + if (moves > 1 && (ndx == A_STR || ndx == A_CON)) (void)encumber_msg(); return TRUE; } @@ -350,7 +350,11 @@ exerper() if(Sick || Vomiting) exercise(A_CON, FALSE); if(Confusion || Hallucination) exercise(A_WIS, FALSE); - if(Wounded_legs || Fumbling || HStun) exercise(A_DEX, FALSE); + if((Wounded_legs +#ifdef STEED + && !u.usteed +#endif + ) || Fumbling || HStun) exercise(A_DEX, FALSE); } } diff --git a/src/ball.c b/src/ball.c index 30a7fdf..d325d65 100644 --- a/src/ball.c +++ b/src/ball.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)ball.c 3.3 97/04/23 */ +/* SCCS Id: @(#)ball.c 3.4 1997/04/23 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -345,7 +345,8 @@ xchar ballx, bally, chainx, chainy; /* only matter !before */ /* return TRUE if ball could be dragged * - * Should not be called while swallowed. + * Should not be called while swallowed. Should be called before movement, + * because we might want to move the ball or chain to the hero's old position. */ boolean drag_ball(x, y, bc_control, ballx, bally, chainx, chainy, cause_delay) @@ -368,27 +369,108 @@ boolean *cause_delay; return TRUE; } - if (carried(uball) || dist2(x, y, uball->ox, uball->oy) < 3 || - (uball->ox == uchain->ox && uball->oy == uchain->oy)) { - /* - * Case where the ball doesn't move but the chain can't just move - * to the player's position: - * @ _ - * _ moving southwest becomes @_ and not @ - * 0 0 0 - */ + /* only need to move the chain? */ + if (carried(uball) || distmin(x, y, uball->ox, uball->oy) <= 2) { *bc_control = BC_CHAIN; move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy); - if (dist2(x, y, uball->ox, uball->oy) == 2 && - dist2(x, y, uchain->ox, uchain->oy) == 4) { - if (uchain->oy == y) - *chainx = uball->ox; - else - *chainy = uball->oy; - } else { - *chainx = u.ux; - *chainy = u.uy; + if (carried(uball)) { + /* move chain only if necessary; assume they didn't teleport */ + if (distmin(x, y, uchain->ox, uchain->oy) > 1) { + *chainx = u.ux; + *chainy = u.uy; + } + return TRUE; + } +#define CHAIN_IN_MIDDLE(chx, chy) \ +(distmin(x, y, chx, chy) <= 1 && distmin(chx, chy, uball->ox, uball->oy) <= 1) + switch(dist2(x, y, uball->ox, uball->oy)) { + /* two spaces diagonal from ball, move chain inbetween */ + case 8: + *chainx = (uball->ox + x)/2; + *chainy = (uball->oy + y)/2; + break; + + /* player is distance 2/1 from ball; move chain to one of the + * two spaces between + * @ + * __ + * 0 + */ + case 5: { + xchar tempx, tempy, tempx2, tempy2; + + /* find position closest to current position of chain */ + /* no effect if current position is already OK */ + if (abs(x - uball->ox) == 1) { + tempx = x; + tempx2 = uball->ox; + tempy = tempy2 = (uball->oy + y)/2; + } else { + tempx = tempx2 = (uball->ox + x)/2; + tempy = y; + tempy2 = uball->oy; + } + if (dist2(tempx, tempy, uchain->ox, uchain->oy) < + dist2(tempx2, tempy2, uchain->ox, uchain->oy) || + ((dist2(tempx, tempy, uchain->ox, uchain->oy) == + dist2(tempx2, tempy2, uchain->ox, uchain->oy)) && rn2(2))) { + *chainx = tempx; + *chainy = tempy; + } else { + *chainx = tempx2; + *chainy = tempy2; + } + break; + } + + /* ball is two spaces horizontal or vertical from player; move*/ + /* chain inbetween *unless* current chain position is OK */ + case 4: + if (CHAIN_IN_MIDDLE(uchain->ox, uchain->oy)) + break; + *chainx = (x + uchain->ox)/2; + *chainy = (y + uchain->oy)/2; + break; + + /* ball is one space diagonal from player. Check for the + * following special case: + * @ + * _ moving southwest becomes @_ + * 0 0 + * (This will also catch teleporting that happens to resemble + * this case, but oh well.) Otherwise fall through. + */ + case 2: + if (dist2(x, y, uball->ox, uball->oy) == 2 && + dist2(x, y, uchain->ox, uchain->oy) == 4) { + if (uchain->oy == y) + *chainx = uball->ox; + else + *chainy = uball->oy; + break; + } + /* fall through */ + case 1: + case 0: + /* do nothing if possible */ + if (CHAIN_IN_MIDDLE(uchain->ox, uchain->oy)) + break; + /* otherwise try to drag chain to player's old position */ + if (CHAIN_IN_MIDDLE(u.ux, u.uy)) { + *chainx = u.ux; + *chainy = u.uy; + break; + } + /* otherwise use player's new position (they must have + teleported, for this to happen) */ + *chainx = x; + *chainy = y; + break; + + default: impossible("bad chain movement"); + break; } +#undef CHAIN_IN_MIDDLE return TRUE; } @@ -559,9 +641,7 @@ litter() while (otmp) { nextobj = otmp->nobj; if ((otmp != uball) && (rnd(capacity) <= (int)otmp->owt)) { - if (otmp == uwep) - setuwep((struct obj *)0); - if ((otmp != uwep) && (canletgo(otmp, ""))) { + if (canletgo(otmp, "")) { Your("%s you down the stairs.", aobjnam(otmp, "follow")); dropx(otmp); diff --git a/src/bones.c b/src/bones.c index c1f1964..ca4997e 100644 --- a/src/bones.c +++ b/src/bones.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)bones.c 3.3 2000/05/28 */ +/* SCCS Id: @(#)bones.c 3.4 2001/04/12 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985,1993. */ /* NetHack may be freely redistributed. See license for details. */ @@ -126,11 +126,12 @@ struct obj *cont; while ((otmp = invent) != 0) { obj_extract_self(otmp); + obj_no_longer_held(otmp); otmp->owornmask = 0; /* lamps don't go out when dropped */ - if (cont && obj_is_burning(otmp)) /* smother in statue */ - end_burn(otmp, otmp->otyp != MAGIC_LAMP); + if ((cont || artifact_light(otmp)) && obj_is_burning(otmp)) + end_burn(otmp, TRUE); /* smother in statue */ if(otmp->otyp == SLIME_MOLD) goodfruit(otmp->spe); @@ -138,17 +139,20 @@ struct obj *cont; if (mtmp) (void) add_to_minv(mtmp, otmp); else if (cont) - add_to_container(cont, otmp); + (void) add_to_container(cont, otmp); else place_object(otmp, u.ux, u.uy); } +#ifndef GOLDOBJ if(u.ugold) { long ugold = u.ugold; if (mtmp) mtmp->mgold = ugold; - else if (cont) add_to_container(cont, mkgoldobj(ugold)); + else if (cont) (void) add_to_container(cont, mkgoldobj(ugold)); else (void)mkgold(ugold, u.ux, u.uy); u.ugold = ugold; /* undo mkgoldobj()'s removal */ } +#endif + if (cont) cont->owt = weight(cont); } /* check whether bones are feasible */ @@ -208,7 +212,9 @@ struct obj *corpse; return; } +#ifdef WIZARD make_bones: +#endif unleash_all(); /* in case these characters are not in their home bases */ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { @@ -220,14 +226,7 @@ struct obj *corpse; mongone(mtmp); } #ifdef STEED - if (u.usteed) { - coord cc; - - /* Move the steed to an adjacent square */ - if (enexto(&cc, u.ux, u.uy, u.usteed->data)) - rloc_to(u.usteed, cc.x, cc.y); - u.usteed = 0; - } + if (u.usteed) dismount_steed(DISMOUNT_BONES); #endif dmonsfree(); /* discard dead or gone monsters */ diff --git a/src/botl.c b/src/botl.c index 45c182f..8c7ed2c 100644 --- a/src/botl.c +++ b/src/botl.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)botl.c 3.3 96/07/15 */ +/* SCCS Id: @(#)botl.c 3.4 1996/07/15 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -147,10 +147,17 @@ long botl_score() { int deepest = deepest_lev_reached(FALSE); +#ifndef GOLDOBJ long ugold = u.ugold + hidden_gold(); if ((ugold -= u.ugold0) < 0L) ugold = 0L; return ugold + u.urexp + (long)(50 * (deepest - 1)) +#else + long umoney = money_cnt(invent) + hidden_gold(); + + if ((umoney -= u.umoney0) < 0L) umoney = 0L; + return umoney + u.urexp + (long)(50 * (deepest - 1)) +#endif + (long)(deepest > 30 ? 10000 : deepest > 20 ? 1000*(deepest - 20) : 0); } @@ -248,7 +255,12 @@ bot2() (void) describe_level(newbot2); Sprintf(nb = eos(newbot2), "%c:%-2ld HP:%d(%d) Pw:%d(%d) AC:%-2d", oc_syms[GOLD_CLASS], - u.ugold, hp, hpmax, u.uen, u.uenmax, u.uac); +#ifndef GOLDOBJ + u.ugold, +#else + money_cnt(invent), +#endif + hp, hpmax, u.uen, u.uenmax, u.uac); if (Upolyd) Sprintf(nb = eos(nb), " HD:%d", mons[u.umonnum].mlevel); diff --git a/src/cmd.c b/src/cmd.c index 35ff6eb..e1915a8 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)cmd.c 3.3 2000/05/05 */ +/* SCCS Id: @(#)cmd.c 3.4 2002/01/17 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -14,6 +14,8 @@ #define NR_OF_EOFS 20 #endif +#define CMD_TRAVEL (char)0x90 + #ifdef DEBUG /* * only one "wiz_debug_cmd" routine should be available (in whatever @@ -105,6 +107,7 @@ STATIC_PTR int NDECL(doprev_message); STATIC_PTR int NDECL(timed_occupation); STATIC_PTR int NDECL(doextcmd); STATIC_PTR int NDECL(domonability); +STATIC_PTR int NDECL(dotravel); # ifdef WIZARD STATIC_PTR int NDECL(wiz_wish); STATIC_PTR int NDECL(wiz_identify); @@ -112,11 +115,14 @@ STATIC_PTR int NDECL(wiz_map); STATIC_PTR int NDECL(wiz_genesis); STATIC_PTR int NDECL(wiz_where); STATIC_PTR int NDECL(wiz_detect); +STATIC_PTR int NDECL(wiz_polyself); STATIC_PTR int NDECL(wiz_level_tele); +STATIC_PTR int NDECL(wiz_level_change); STATIC_PTR int NDECL(wiz_show_seenv); STATIC_PTR int NDECL(wiz_show_vision); +STATIC_PTR int NDECL(wiz_mon_polycontrol); STATIC_PTR int NDECL(wiz_show_wmodes); -#ifdef __BORLANDC__ +#if defined(__BORLANDC__) && !defined(_WIN32) extern void FDECL(show_borlandc_stats, (winid)); #endif STATIC_DCL void FDECL(count_obj, (struct obj *, long *, long *, BOOLEAN_P, BOOLEAN_P)); @@ -138,6 +144,8 @@ static void NDECL(end_of_input); #endif #endif /* OVLB */ +static const char* readchar_queue=""; + STATIC_DCL char *NDECL(parse); #ifdef OVL1 @@ -297,7 +305,7 @@ doextlist() /* here after #? - now list all full-word commands */ putstr(datawin, 0, ""); for(efp = extcmdlist; efp->ef_txt; efp++) { - Sprintf(buf, " %-14s - %s.", efp->ef_txt, efp->ef_desc); + Sprintf(buf, " %-15s - %s.", efp->ef_txt, efp->ef_desc); putstr(datawin, 0, buf); } display_nhwindow(datawin, FALSE); @@ -433,7 +441,7 @@ domonability() if (can_breathe(youmonst.data)) return dobreathe(); else if (attacktype(youmonst.data, AT_SPIT)) return dospit(); else if (youmonst.data->mlet == S_NYMPH) return doremove(); - else if (youmonst.data->mlet == S_UMBER) return doconfuse(); + else if (attacktype(youmonst.data, AT_GAZE)) return dogaze(); else if (is_were(youmonst.data)) return dosummon(); else if (webmaker(youmonst.data)) return dospinweb(); else if (is_hider(youmonst.data)) return dohide(); @@ -548,6 +556,61 @@ wiz_level_tele() return 0; } +STATIC_PTR int +wiz_mon_polycontrol() +{ + iflags.mon_polycontrol = !iflags.mon_polycontrol; + pline("Monster polymorph control is %s.", + iflags.mon_polycontrol ? "on" : "off"); + return 0; +} + +STATIC_PTR int +wiz_level_change() +{ + char buf[BUFSZ]; + int newlevel; + int ret; + + getlin("To what experience level do you want to be set?", buf); + (void)mungspaces(buf); + if (buf[0] == '\033' || buf[0] == '\0') ret = 0; + else ret = sscanf(buf, "%d", &newlevel); + + if (ret != 1) { + pline(Never_mind); + return 0; + } + if (newlevel == u.ulevel) { + You("are already that experienced."); + } else if (newlevel < u.ulevel) { + if (u.ulevel == 1) { + You("are already as inexperienced as you can get."); + return 0; + } + if (newlevel < 1) newlevel = 1; + while (u.ulevel > newlevel) + losexp((const char *)0); + } else { + if (u.ulevel >= MAXULEV) { + You("are already as experienced as you can get."); + return 0; + } + if (newlevel > MAXULEV) newlevel = MAXULEV; + while (u.ulevel < newlevel) + pluslvl(FALSE); + } + u.ulevelmax = u.ulevel; + return 0; +} + +STATIC_PTR int +wiz_polyself() +{ + polyself(TRUE); + return 0; +} + STATIC_PTR int wiz_show_seenv() { @@ -639,7 +702,7 @@ wiz_show_wmodes() lev = &levl[x][y]; if (x == u.ux && y == u.uy) row[x] = '@'; - if (IS_WALL(lev->typ) || lev->typ == SDOOR) + else if (IS_WALL(lev->typ) || lev->typ == SDOOR) row[x] = '0' + (lev->wall_info & WM_MASK); else if (lev->typ == CORR) row[x] = '#'; @@ -743,6 +806,7 @@ int final; /* 0 => still in progress; 1 => over, survived; 2 => dead */ if (Stone_resistance) you_are("petrification resistant"); if (Invulnerable) you_are("invulnerable"); + if (u.uedibility) you_can("recognize detrimental food"); /*** Troubles ***/ if (Halluc_resistance) @@ -758,6 +822,18 @@ int final; /* 0 => still in progress; 1 => over, survived; 2 => dead */ if (u.usick_type & SICK_NONVOMITABLE) you_are("sick from illness"); } + /* added by JDS */ + if (u.uhitinc) { + Sprintf(buf, "%s%i %s to hit", u.uhitinc > 0 ? "+" : "", + u.uhitinc, u.uhitinc > 0 ? "bonus" : "penalty"); + you_have(buf); + + } + if (u.udaminc) { + Sprintf(buf, "%s%i %s to damage", u.udaminc > 0 ? "+" : "", + u.udaminc, u.udaminc > 0 ? "bonus" : "penalty"); + you_have(buf); + } /* end JDS portion */ } if (Stoned) you_are("turning to stone"); if (Slimed) you_are("turning into slime"); @@ -767,10 +843,22 @@ int final; /* 0 => still in progress; 1 => over, survived; 2 => dead */ you_have(buf); } if (Fumbling) enl_msg("You fumble", "", "d", ""); - if (Wounded_legs) { + if (Wounded_legs +#ifdef STEED + && !u.usteed +#endif + ) { Sprintf(buf, "wounded %s", makeplural(body_part(LEG))); you_have(buf); } +#if defined(WIZARD) && defined(STEED) + if (Wounded_legs && u.usteed && wizard) { + Strcpy(buf, x_monnam(u.usteed, ARTICLE_YOUR, (char *)0, + SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION, FALSE)); + *buf = highc(*buf); + enl_msg(buf, " has", " had", " wounded legs"); + } +#endif if (Sleeping) enl_msg("You ", "fall", "fell", " asleep"); if (Hunger) enl_msg("You hunger", "", "ed", " rapidly"); @@ -790,6 +878,7 @@ int final; /* 0 => still in progress; 1 => over, survived; 2 => dead */ if (Clairvoyant) you_are("clairvoyant"); if (Infravision) you_have("infravision"); if (Detect_monsters) you_are("sensing the presence of monsters"); + if (u.umconf) you_are("going to confuse monsters"); /*** Appearance and behavior ***/ if (Adornment) you_are("adorned"); @@ -959,6 +1048,7 @@ minimal_enlightenment() anything any; char buf[BUFSZ], buf2[BUFSZ]; static char fmtstr[] = "%-15s: %-12s"; + static char deity_fmtstr[] = "%-17s%s"; any.a_void = 0; buf[0] = buf2[0] = '\0'; @@ -986,7 +1076,11 @@ minimal_enlightenment() add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, "Current", FALSE); Sprintf(buf, fmtstr, "race", Upolyd ? youmonst.data->mname : urace.noun); add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE); - if (!Upolyd) { + if (Upolyd) { + Sprintf(buf, fmtstr, "role (base)", + (u.mfemale && urole.name.f) ? urole.name.f : urole.name.m); + add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE); + } else { Sprintf(buf, fmtstr, "role", (flags.female && urole.name.f) ? urole.name.f : urole.name.m); add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE); @@ -1006,7 +1100,7 @@ minimal_enlightenment() /* Deity list */ add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, "", FALSE); add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_BOLD, "Deities", FALSE); - Sprintf(buf2, "%-17s%s", align_gname(A_CHAOTIC), + Sprintf(buf2, deity_fmtstr, align_gname(A_CHAOTIC), (u.ualignbase[A_ORIGINAL] == u.ualign.type && u.ualign.type == A_CHAOTIC) ? " (s,c)" : (u.ualignbase[A_ORIGINAL] == A_CHAOTIC) ? " (s)" : @@ -1014,7 +1108,7 @@ minimal_enlightenment() Sprintf(buf, fmtstr, "chaotic deity", buf2); add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE); - Sprintf(buf2, "%-17s%s", align_gname(A_NEUTRAL), + Sprintf(buf2, deity_fmtstr, align_gname(A_NEUTRAL), (u.ualignbase[A_ORIGINAL] == u.ualign.type && u.ualign.type == A_NEUTRAL) ? " (s,c)" : (u.ualignbase[A_ORIGINAL] == A_NEUTRAL) ? " (s)" : @@ -1022,7 +1116,7 @@ minimal_enlightenment() Sprintf(buf, fmtstr, "neutral deity", buf2); add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, FALSE); - Sprintf(buf2, "%-17s%s", align_gname(A_LAWFUL), + Sprintf(buf2, deity_fmtstr, align_gname(A_LAWFUL), (u.ualignbase[A_ORIGINAL] == u.ualign.type && u.ualign.type == A_LAWFUL) ? " (s,c)" : (u.ualignbase[A_ORIGINAL] == A_LAWFUL) ? " (s)" : (u.ualign.type == A_LAWFUL) ? " (c)" : ""); @@ -1273,6 +1367,7 @@ static const struct func_tab cmdlist[] = { {GOLD_SYM, TRUE, doprgold}, {SPBOOK_SYM, TRUE, dovspell}, /* Mike Stephenson */ {'#', TRUE, doextcmd}, + {'_', TRUE, dotravel}, {0,0,0,0} }; @@ -1295,7 +1390,7 @@ struct ext_func_tab extcmdlist[] = { #ifdef STEED {"ride", "ride (or stop riding) a monster", doride, FALSE}, #endif - {"rub", "rub a lamp", dorub, FALSE}, + {"rub", "rub a lamp or a stone", dorub, FALSE}, {"sit", "sit down", dosit, FALSE}, {"turn", "turn undead", doturn, TRUE}, {"twoweapon", "toggle two-weapon combat", dotwoweapon, FALSE}, @@ -1314,6 +1409,9 @@ struct ext_func_tab extcmdlist[] = { {(char *)0, (char *)0, donull, TRUE}, {(char *)0, (char *)0, donull, TRUE}, {(char *)0, (char *)0, donull, TRUE}, + {(char *)0, (char *)0, donull, TRUE}, + {(char *)0, (char *)0, donull, TRUE}, + {(char *)0, (char *)0, donull, TRUE}, #ifdef DEBUG {(char *)0, (char *)0, donull, TRUE}, #endif @@ -1324,7 +1422,10 @@ struct ext_func_tab extcmdlist[] = { #if defined(WIZARD) static const struct ext_func_tab debug_extcmdlist[] = { + {"levelchange", "change experience level", wiz_level_change, TRUE}, {"light sources", "show mobile light sources", wiz_light_sources, TRUE}, + {"monpoly_control", "control monster polymorphs", wiz_mon_polycontrol, TRUE}, + {"poly", "polymorph self", wiz_polyself, TRUE}, {"seenv", "show seen vectors", wiz_show_seenv, TRUE}, {"stats", "show memory statistics", wiz_show_stats, TRUE}, {"timeout", "look at timeout queue", wiz_timeout_queue, TRUE}, @@ -1531,7 +1632,7 @@ wiz_show_stats() Sprintf(buf, template, "Total", total_mon_count, total_mon_size); putstr(win, 0, buf); -#ifdef __BORLANDC__ +#if defined(__BORLANDC__) && !defined(_WIN32) show_borlandc_stats(win); #endif @@ -1589,6 +1690,7 @@ register char *cmd; /* handle most movement commands */ do_walk = do_rush = prefix_seen = FALSE; + flags.travel = 0; switch (*cmd) { case 'g': if (movecmd(cmd[1])) { flags.run = 2; @@ -1635,6 +1737,12 @@ register char *cmd; flags.move = FALSE; multi = 0; return; + case CMD_TRAVEL: + flags.travel = 1; + flags.run = 8; + flags.nopick = 1; + do_rush = TRUE; + break; default: if (movecmd(*cmd)) { /* ordinary movement */ do_walk = TRUE; } else if (movecmd(iflags.num_pad ? @@ -1768,8 +1876,8 @@ const char *s; { char dirsym; -#ifdef REDO - if(in_doagain) +#ifdef REDO + if(in_doagain || *readchar_queue) dirsym = readchar(); else #endif @@ -1817,34 +1925,85 @@ static NEARDATA int last_multi; /* * convert a MAP window position into a movecmd */ -int +const char * click_to_cmd(x, y, mod) int x, y, mod; { + int dir; + static char cmd[4]; + cmd[1]=0; + x -= u.ux; y -= u.uy; - /* convert without using floating point, allowing sloppy clicking */ - if(x > 2*abs(y)) - x = 1, y = 0; - else if(y > 2*abs(x)) - x = 0, y = 1; - else if(x < -2*abs(y)) - x = -1, y = 0; - else if(y < -2*abs(x)) - x = 0, y = -1; - else + + if ( abs(x) <= 1 && abs(y) <= 1 ) { x = sgn(x), y = sgn(y); + } else { + u.tx = u.ux+x; + u.ty = u.uy+y; + cmd[0] = CMD_TRAVEL; + return cmd; + } + + if(x == 0 && y == 0) { + /* here */ + if(IS_FOUNTAIN(levl[u.ux][u.uy].typ) || IS_SINK(levl[u.ux][u.uy].typ)) { + cmd[0]=mod == CLICK_1 ? 'q' : M('d'); + return cmd; + } else if(IS_THRONE(levl[u.ux][u.uy].typ)) { + cmd[0]=M('s'); + return cmd; + } else if((u.ux == xupstair && u.uy == yupstair) + || (u.ux == sstairs.sx && u.uy == sstairs.sy && sstairs.up) + || (u.ux == xupladder && u.uy == yupladder)) { + return "<"; + } else if((u.ux == xdnstair && u.uy == ydnstair) + || (u.ux == sstairs.sx && u.uy == sstairs.sy && !sstairs.up) + || (u.ux == xdnladder && u.uy == ydnladder)) { + return ">"; + } else if(OBJ_AT(u.ux, u.uy)) { + cmd[0] = Is_container(level.objects[u.ux][u.uy]) ? M('l') : ','; + return cmd; + } else { + return "."; /* just rest */ + } + } + + /* directional commands */ - if(x == 0 && y == 0) /* map click on player to "rest" command */ - return '.'; + dir = xytod(x, y); - x = xytod(x, y); + if (!m_at(u.ux+x, u.uy+y) && !test_move(u.ux, u.uy, x, y, 1)) { + cmd[1] = (iflags.num_pad ? ndir[dir] : sdir[dir]); + cmd[2] = 0; + if (IS_DOOR(levl[u.ux+x][u.uy+y].typ)) { + /* slight assistance to the player: choose kick/open for them */ + if (levl[u.ux+x][u.uy+y].doormask & D_LOCKED) { + cmd[0] = C('d'); + return cmd; + } + if (levl[u.ux+x][u.uy+y].doormask & D_CLOSED) { + cmd[0] = 'o'; + return cmd; + } + } + if (levl[u.ux+x][u.uy+y].typ <= SCORR) { + cmd[0] = 's'; + cmd[1] = 0; + return cmd; + } + } + + /* move, attack, etc. */ + cmd[1] = 0; if(mod == CLICK_1) { - return (iflags.num_pad ? ndir[x] : sdir[x]); + cmd[0] = (iflags.num_pad ? ndir[dir] : sdir[dir]); } else { - return (iflags.num_pad ? M(ndir[x]) : - (sdir[x] - 'a' + 'A')); /* run command */ + cmd[0] = (iflags.num_pad ? M(ndir[dir]) : + (sdir[dir] - 'a' + 'A')); /* run command */ } + + return cmd; } STATIC_OVL char * @@ -1941,10 +2100,13 @@ readchar() register int sym; int x = u.ux, y = u.uy, mod = 0; + if ( *readchar_queue ) + sym = *readchar_queue++; + else #ifdef REDO - sym = in_doagain ? Getchar() : nh_poskey(&x, &y, &mod); + sym = in_doagain ? Getchar() : nh_poskey(&x, &y, &mod); #else - sym = Getchar(); + sym = Getchar(); #endif #ifdef UNIX @@ -1966,10 +2128,35 @@ readchar() end_of_input(); #endif /* UNIX */ - if(sym == 0) /* click event */ - sym = click_to_cmd(x, y, mod); + if(sym == 0) { + /* click event */ + readchar_queue = click_to_cmd(x, y, mod); + sym = *readchar_queue++; + } return((char) sym); } + +STATIC_PTR int +dotravel() +{ + /* Keyboard travel command */ + static char cmd[2]; + coord cc; + cmd[1]=0; + cc.x = u.ux; + cc.y = u.uy; + pline("Where do you want to travel to?"); + if (getpos(&cc, TRUE, "the desired destination") < 0) { + /* user pressed ESC */ + return 0; + } + u.tx = cc.x; + u.ty = cc.y; + cmd[0] = CMD_TRAVEL; + readchar_queue = cmd; + return 0; +} + #endif /* OVL0 */ /*cmd.c*/ diff --git a/src/dbridge.c b/src/dbridge.c index f92f744..589d569 100644 --- a/src/dbridge.c +++ b/src/dbridge.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dbridge.c 3.3 2000/02/05 */ +/* SCCS Id: @(#)dbridge.c 3.4 2000/02/05 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -336,39 +336,14 @@ struct entity *etmp; const char *verb; { static char wholebuf[80]; - char verbbuf[30]; Strcpy(wholebuf, is_u(etmp) ? "You" : Monnam(etmp->emon)); - if (!*verb) - return(wholebuf); + if (!*verb) return(wholebuf); Strcat(wholebuf, " "); - verbbuf[0] = '\0'; if (is_u(etmp)) - Strcpy(verbbuf, verb); - else { - if (!strcmp(verb, "are")) - Strcpy(verbbuf, "is"); - if (!strcmp(verb, "have")) - Strcpy(verbbuf, "has"); - if (!verbbuf[0]) { - Strcpy(verbbuf, verb); - switch (verbbuf[strlen(verbbuf) - 1]) { - case 'y': - verbbuf[strlen(verbbuf) - 1] = '\0'; - Strcat(verbbuf, "ies"); - break; - case 'h': - case 'o': - case 's': - Strcat(verbbuf, "es"); - break; - default: - Strcat(verbbuf, "s"); - break; - } - } - } - Strcat(wholebuf, verbbuf); + Strcat(wholebuf, verb); + else + Strcat(wholebuf, vtense((char *)0, verb)); return(wholebuf); } diff --git a/src/decl.c b/src/decl.c index 088ef72..a82e493 100644 --- a/src/decl.c +++ b/src/decl.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)decl.c 3.3 99/05/07 */ +/* SCCS Id: @(#)decl.c 3.2 2001/12/10 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -20,7 +20,9 @@ char *catmore = 0; /* default pager */ NEARDATA int bases[MAXOCLASSES] = DUMMY; NEARDATA int multi = 0; +#if 0 NEARDATA int warnlevel = 0; /* used by movemon and dochugw */ +#endif NEARDATA int nroom = 0; NEARDATA int nsubroom = 0; NEARDATA int occtime = 0; @@ -48,6 +50,9 @@ NEARDATA char *save_cm = 0; NEARDATA int killer_format = 0; const char *killer = 0; const char *delayed_killer = 0; +#ifdef GOLDOBJ +NEARDATA long done_money = 0; +#endif char killer_buf[BUFSZ] = DUMMY; const char *nomovemsg = 0; const char nul[40] = DUMMY; /* contains zeros */ @@ -70,6 +75,8 @@ const char ynaqchars[] = "ynaq"; const char ynNaqchars[] = "yn#aq"; NEARDATA long yn_number = 0L; +const char disclosure_options[] = "iavgc"; + #ifdef MICRO char hackdir[PATHLEN]; /* where rumors, help, record are */ char levels[PATHLEN]; /* where levels are */ @@ -97,6 +104,10 @@ const schar zdir[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 1,-1 }; NEARDATA schar tbx = 0, tby = 0; /* mthrowu: target */ +/* for xname handling of multiple shot missile volleys: + number of shots, index of current one, validity check, shoot vs throw */ +NEARDATA struct multishot m_shot = { 0, 0, STRANGE_OBJECT, FALSE }; + NEARDATA struct dig_info digging; NEARDATA dungeon dungeons[MAXDUNGEON]; /* ini'ed by init_dungeon() */ @@ -184,16 +195,11 @@ NEARDATA struct obj *billobjs = (struct obj *)0; /* used to zero all elements of a struct obj */ NEARDATA struct obj zeroobj = DUMMY; -/* monster pronouns, index is return value of gender(mtmp) */ -const char *he[3] = { "he", "she", "it" }; -const char *him[3] = { "him", "her", "it" }; -const char *his[3] = { "his", "her", "its" }; - /* originally from dog.c */ NEARDATA char dogname[PL_PSIZ] = DUMMY; NEARDATA char catname[PL_PSIZ] = DUMMY; NEARDATA char horsename[PL_PSIZ] = DUMMY; -char preferred_pet; /* '\0', 'c', 'd' */ +char preferred_pet; /* '\0', 'c', 'd', 'n' (none) */ /* monsters that went down/up together with @ */ NEARDATA struct monst *mydogs = (struct monst *)0; /* monsters that are moving to another dungeon level */ @@ -208,10 +214,30 @@ NEARDATA struct c_color_names c_color_names = { "white" }; +const char *c_obj_colors[] = { + "black", /* CLR_BLACK */ + "red", /* CLR_RED */ + "green", /* CLR_GREEN */ + "brown", /* CLR_BROWN */ + "blue", /* CLR_BLUE */ + "magenta", /* CLR_MAGENTA */ + "cyan", /* CLR_CYAN */ + "gray", /* CLR_GRAY */ + "transparent", /* no_color */ + "orange", /* CLR_ORANGE */ + "bright green", /* CLR_BRIGHT_GREEN */ + "yellow", /* CLR_YELLOW */ + "bright blue", /* CLR_BRIGHT_BLUE */ + "bright magenta", /* CLR_BRIGHT_MAGENTA */ + "bright cyan", /* CLR_BRIGHT_CYAN */ + "white", /* CLR_WHITE */ +}; + struct c_common_strings c_common_strings = { "Nothing happens.", "That's enough tries!", "That is a silly thing to %s.", "shudder for a moment.", - "something", "Something", "You can move again.", "Never mind." + "something", "Something", "You can move again.", "Never mind.", + "vision quickly clears." }; /* NOTE: the order of these words exactly corresponds to the diff --git a/src/detect.c b/src/detect.c index a94f88d..60eda70 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)detect.c 3.3 1999/12/06 */ +/* SCCS Id: @(#)detect.c 3.4 1999/12/06 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -13,8 +13,8 @@ extern boolean known; /* from read.c */ STATIC_DCL void FDECL(do_dknown_of, (struct obj *)); -STATIC_DCL boolean FDECL(check_map_spot, (int,int,CHAR_P)); -STATIC_DCL boolean FDECL(clear_stale_map, (CHAR_P)); +STATIC_DCL boolean FDECL(check_map_spot, (int,int,CHAR_P,unsigned)); +STATIC_DCL boolean FDECL(clear_stale_map, (CHAR_P,unsigned)); STATIC_DCL void FDECL(sense_trap, (struct trap *,XCHAR_P,XCHAR_P,int)); STATIC_DCL void FDECL(show_map_spot, (int,int)); STATIC_PTR void FDECL(findone,(int,int,genericptr_t)); @@ -40,6 +40,26 @@ char oclass; return (struct obj *) 0; } +/* Recursively search obj for an object made of specified material and return 1st found */ +struct obj * +o_material(obj, material) +struct obj* obj; +unsigned material; +{ + register struct obj* otmp; + struct obj *temp; + + if (objects[obj->otyp].oc_material == material) return obj; + + if (Has_contents(obj)) { + for (otmp = obj->cobj; otmp; otmp = otmp->nobj) + if (objects[otmp->otyp].oc_material == material) return otmp; + else if (Has_contents(otmp) && (temp = o_material(otmp, material))) + return temp; + } + return (struct obj *) 0; +} + STATIC_OVL void do_dknown_of(obj) struct obj *obj; @@ -55,9 +75,10 @@ struct obj *obj; /* Check whether the location has an outdated object displayed on it. */ STATIC_OVL boolean -check_map_spot(x, y, oclass) +check_map_spot(x, y, oclass, material) int x, y; register char oclass; +unsigned material; { register int glyph; register struct obj *otmp; @@ -69,20 +90,45 @@ register char oclass; if (oclass == ALL_CLASSES) { return((boolean)( !(level.objects[x][y] || /* stale if nothing here */ ((mtmp = m_at(x,y)) != 0 && - (mtmp->mgold || mtmp->minvent))))); - } else if (objects[glyph_to_obj(glyph)].oc_class == oclass) { - /* the object shown here is of interest */ - for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) - if (o_in(otmp, oclass)) return FALSE; - /* didn't find it; perhaps a monster is carrying it */ - if ((mtmp = m_at(x,y)) != 0) { - if (oclass == GOLD_CLASS && mtmp->mgold) - return FALSE; - else for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) - if (o_in(otmp, oclass)) return FALSE; + ( +#ifndef GOLDOBJ + mtmp->mgold || +#endif + mtmp->minvent))))); + } else { + if (material && objects[glyph_to_obj(glyph)].oc_material == material) { + /* the object shown here is of interest because material matches */ + for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) + if (o_material(otmp, GOLD)) return FALSE; + /* didn't find it; perhaps a monster is carrying it */ + if ((mtmp = m_at(x,y)) != 0) { + for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) + if (o_material(otmp, GOLD)) return FALSE; + } + /* detection indicates removal of this object from the map */ + return TRUE; } - /* detection indicates removal of this object from the map */ - return TRUE; + if (oclass && objects[glyph_to_obj(glyph)].oc_class == oclass) { + /* the object shown here is of interest because its class matches */ + for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) + if (o_in(otmp, oclass)) return FALSE; + /* didn't find it; perhaps a monster is carrying it */ +#ifndef GOLDOBJ + if ((mtmp = m_at(x,y)) != 0) { + if (oclass == GOLD_CLASS && mtmp->mgold) + return FALSE; + else for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) + if (o_in(otmp, oclass)) return FALSE; + } +#else + if ((mtmp = m_at(x,y)) != 0) { + for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) + if (o_in(otmp, oclass)) return FALSE; + } +#endif + /* detection indicates removal of this object from the map */ + return TRUE; + } } } return FALSE; @@ -95,15 +141,16 @@ register char oclass; change occurs. */ STATIC_OVL boolean -clear_stale_map(oclass) +clear_stale_map(oclass, material) register char oclass; +unsigned material; { register int zx, zy; register boolean change_made = FALSE; for (zx = 1; zx < COLNO; zx++) for (zy = 0; zy < ROWNO; zy++) - if (check_map_spot(zx, zy, oclass)) { + if (check_map_spot(zx, zy, oclass,material)) { unmap_object(zx, zy); change_made = TRUE; } @@ -122,31 +169,60 @@ register struct obj *sobj; struct obj *temp; boolean stale; - known = stale = clear_stale_map(GOLD_CLASS); + known = stale = clear_stale_map(GOLD_CLASS, + (unsigned)(sobj->blessed ? GOLD : 0)); /* look for gold carried by monsters (might be in a container) */ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { if (DEADMONSTER(mtmp)) continue; /* probably not needed in this case but... */ +#ifndef GOLDOBJ if (mtmp->mgold || monsndx(mtmp->data) == PM_GOLD_GOLEM) { +#else + if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) { +#endif known = TRUE; goto outgoldmap; /* skip further searching */ } else for (obj = mtmp->minvent; obj; obj = obj->nobj) - if (o_in(obj, GOLD_CLASS)) { + if (sobj->blessed && o_material(obj, GOLD)) { + known = TRUE; + goto outgoldmap; + } else if (o_in(obj, GOLD_CLASS)) { known = TRUE; goto outgoldmap; /* skip further searching */ } } /* look for gold objects */ - for (obj = fobj; obj; obj = obj->nobj) - if (o_in(obj, GOLD_CLASS)) { + for (obj = fobj; obj; obj = obj->nobj) { + if (sobj->blessed && o_material(obj, GOLD)) { + known = TRUE; + if (obj->ox != u.ux || obj->oy != u.uy) goto outgoldmap; + } else if (o_in(obj, GOLD_CLASS)) { known = TRUE; if (obj->ox != u.ux || obj->oy != u.uy) goto outgoldmap; } + } if (!known) { - /* no gold found */ - if (sobj) strange_feeling(sobj, "You feel materially poor."); + /* no gold found on floor or monster's inventory. + adjust message if you have gold in your inventory */ + if (sobj) { + char buf[BUFSZ]; + if (youmonst.data == &mons[PM_GOLD_GOLEM]) { + Sprintf(buf, "You feel like a million %s!", + currency(2L)); + } else if (hidden_gold() || +#ifndef GOLDOBJ + u.ugold) +#else + money_cnt(invent)) +#endif + Strcpy(buf, + "You feel worried about your future financial situation."); + else + Strcpy(buf, "You feel materially poor."); + strange_feeling(sobj, buf); + } return(1); } /* only under me - no separate display required */ @@ -159,17 +235,28 @@ register struct obj *sobj; u.uinwater = 0; /* Discover gold locations. */ - for (obj = fobj; obj; obj = obj->nobj) - if ((temp = o_in(obj, GOLD_CLASS))) { + for (obj = fobj; obj; obj = obj->nobj) { + if (sobj->blessed && (temp = o_material(obj, GOLD))) { + if (temp != obj) { + temp->ox = obj->ox; + temp->oy = obj->oy; + } + map_object(temp,1); + } else if ((temp = o_in(obj, GOLD_CLASS))) { if (temp != obj) { temp->ox = obj->ox; temp->oy = obj->oy; } map_object(temp,1); } + } for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { if (DEADMONSTER(mtmp)) continue; /* probably overkill here */ +#ifndef GOLDOBJ if (mtmp->mgold || monsndx(mtmp->data) == PM_GOLD_GOLEM) { +#else + if (findgold(mtmp->minvent) || monsndx(mtmp->data) == PM_GOLD_GOLEM) { +#endif struct obj gold; gold.otyp = GOLD_PIECE; @@ -177,7 +264,12 @@ register struct obj *sobj; gold.oy = mtmp->my; map_object(&gold,1); } else for (obj = mtmp->minvent; obj; obj = obj->nobj) - if ((temp = o_in(obj, GOLD_CLASS))) { + if (sobj->blessed && (temp = o_material(obj, GOLD))) { + temp->ox = mtmp->mx; + temp->oy = mtmp->my; + map_object(temp,1); + break; + } else if ((temp = o_in(obj, GOLD_CLASS))) { temp->ox = mtmp->mx; temp->oy = mtmp->my; map_object(temp,1); @@ -210,7 +302,7 @@ register struct obj *sobj; const char *what = confused ? something : "food"; int uw = u.uinwater; - stale = clear_stale_map(oclass); + stale = clear_stale_map(oclass, 0); for (obj = fobj; obj; obj = obj->nobj) if (o_in(obj, oclass)) { @@ -231,12 +323,31 @@ register struct obj *sobj; if (stale) { docrt(); You("sense a lack of %s nearby.", what); - } else if (sobj) - strange_feeling(sobj, "Your nose twitches."); + if (sobj && sobj->blessed) { + if (!u.uedibility) Your("%s starts to tingle.", body_part(NOSE)); + u.uedibility = 1; + } + } else if (sobj) { + char buf[BUFSZ]; + Sprintf(buf, "Your %s twitches%s.", body_part(NOSE), + (sobj->blessed && !u.uedibility) ? " then starts to tingle" : ""); + if (sobj->blessed && !u.uedibility) { + boolean savebeginner = flags.beginner; /* prevent non-delivery of */ + flags.beginner = FALSE; /* message */ + strange_feeling(sobj, buf); + flags.beginner = savebeginner; + u.uedibility = 1; + } else + strange_feeling(sobj, buf); + } return !stale; } else if (!ct) { known = TRUE; You("%s %s nearby.", sobj ? "smell" : "sense", what); + if (sobj && sobj->blessed) { + if (!u.uedibility) pline("Your %s starts to tingle.", body_part(NOSE)); + u.uedibility = 1; + } } else { struct obj *temp; known = TRUE; @@ -260,7 +371,14 @@ register struct obj *sobj; break; /* skip rest of this monster's inventory */ } newsym(u.ux,u.uy); - if (sobj) Your("nose tingles and you smell %s.", what); + if (sobj) { + if (sobj->blessed) { + Your("%s %s to tingle and you smell %s.", body_part(NOSE), + u.uedibility ? "continues" : "starts", what); + u.uedibility = 1; + } else + Your("%s tingles and you smell %s.", body_part(NOSE), what); + } else You("sense %s.", what); display_nhwindow(WIN_MAP, TRUE); exercise(A_WIS, TRUE); @@ -329,13 +447,17 @@ int class; /* an object class, 0 for all */ } if ((is_cursed && mtmp->m_ap_type == M_AP_OBJECT && (!class || class == objects[mtmp->mappearance].oc_class)) || +#ifndef GOLDOBJ (mtmp->mgold && (!class || class == GOLD_CLASS))) { +#else + (findgold(mtmp->minvent) && (!class || class == GOLD_CLASS))) { +#endif ct++; break; } } - if (!clear_stale_map(!class ? ALL_CLASSES : class) && !ct) { + if (!clear_stale_map(!class ? ALL_CLASSES : class, 0) && !ct) { if (!ctu) { if (detector) strange_feeling(detector, "You feel a lack of something."); @@ -407,7 +529,11 @@ int class; /* an object class, 0 for all */ temp.oy = mtmp->my; temp.corpsenm = PM_TENGU; /* if mimicing a corpse */ map_object(&temp, 1); +#ifndef GOLDOBJ } else if (mtmp->mgold && (!class || class == GOLD_CLASS)) { +#else + } else if (findgold(mtmp->minvent) && (!class || class == GOLD_CLASS)) { +#endif struct obj gold; gold.otyp = GOLD_PIECE; @@ -551,10 +677,10 @@ register struct obj *sobj; else found = TRUE; } } - for (door = 0; door <= doorindex; door++) { + for (door = 0; door < doorindex; door++) { cc = doors[door]; if (levl[cc.x][cc.y].doormask & D_TRAPPED) { - if (cc.x != u.ux || cc.x != u.uy) + if (cc.x != u.ux || cc.y != u.uy) goto outtrapmap; else found = TRUE; } @@ -579,7 +705,7 @@ register struct obj *sobj; if ((obj->otyp==LARGE_BOX || obj->otyp==CHEST) && obj->otrapped) sense_trap((struct trap *)0, obj->ox, obj->oy, sobj && sobj->cursed); - for (door = 0; door <= doorindex; door++) { + for (door = 0; door < doorindex; door++) { cc = doors[door]; if (levl[cc.x][cc.y].doormask & D_TRAPPED) sense_trap((struct trap *)0, cc.x, cc.y, sobj && sobj->cursed); @@ -643,32 +769,32 @@ struct obj *obj; { char ch; int oops; - const char *bname = xname(obj); if (Blind) { - pline("Too bad you can't see %s", the(bname)); + pline("Too bad you can't see %s.", the(xname(obj))); return; } oops = (rnd(20) > ACURR(A_INT) || obj->cursed); if (oops && (obj->spe > 0)) { switch (rnd(obj->oartifact ? 4 : 5)) { - case 1 : pline("%s is too much to comprehend!", The(bname)); + case 1 : pline("%s too much to comprehend!", Tobjnam(obj, "are")); break; - case 2 : pline("%s confuses you!", The(bname)); + case 2 : pline("%s you!", Tobjnam(obj, "confuse")); make_confused(HConfusion + rnd(100),FALSE); break; case 3 : if (!resists_blnd(&youmonst)) { - pline("%s damages your vision!", The(bname)); + pline("%s your vision!", Tobjnam(obj, "damage")); make_blinded(Blinded + rnd(100),FALSE); + if (!Blind) Your(vision_clears); } else { - pline("%s assaults your vision.", The(bname)); + pline("%s your vision.", Tobjnam(obj, "assault")); You("are unaffected!"); } break; - case 4 : pline("%s zaps your mind!", The(bname)); + case 4 : pline("%s your mind!", Tobjnam(obj, "zap")); make_hallucinated(HHallucination + rnd(100),FALSE,0L); break; - case 5 : pline("%s explodes!", The(bname)); + case 5 : pline("%s!", Tobjnam(obj, "explode")); useup(obj); losehp(rnd(30), "exploding crystal ball", KILLED_BY_AN); break; @@ -711,7 +837,7 @@ struct obj *obj; if (flags.verbose) pline(Never_mind); return; } - You("peer into %s...", the(bname)); + You("peer into %s...", the(xname(obj))); nomul(-rnd(10)); nomovemsg = ""; if (obj->spe <= 0) @@ -853,10 +979,13 @@ genericptr_t num; if(levl[zx][zy].typ == SDOOR) { cvt_sdoor_to_door(&levl[zx][zy]); /* .typ = DOOR */ + magic_map_background(zx, zy, 0); newsym(zx, zy); (*(int*)num)++; } else if(levl[zx][zy].typ == SCORR) { levl[zx][zy].typ = CORR; + unblock_point(zx,zy); + magic_map_background(zx, zy, 0); newsym(zx, zy); (*(int*)num)++; } else if ((ttmp = t_at(zx, zy)) != 0) { @@ -918,10 +1047,12 @@ genericptr_t num; levl[zx][zy].doormask = D_NODOOR; } else levl[zx][zy].doormask = D_ISOPEN; + unblock_point(zx, zy); newsym(zx, zy); (*(int*)num)++; } else if(levl[zx][zy].typ == SCORR) { levl[zx][zy].typ = CORR; + unblock_point(zx, zy); newsym(zx, zy); (*(int*)num)++; } else if ((ttmp = t_at(zx, zy)) != 0) { @@ -970,14 +1101,29 @@ find_trap(trap) struct trap *trap; { int tt = what_trap(trap->ttyp); + boolean cleared = FALSE; - You("find %s.", an(defsyms[trap_to_defsym(tt)].explanation)); trap->tseen = 1; exercise(A_WIS, TRUE); if (Blind) feel_location(trap->tx, trap->ty); else newsym(trap->tx, trap->ty); + + if (levl[trap->tx][trap->ty].glyph != trap_to_glyph(trap)) { + /* There's too much clutter to see your find otherwise */ + cls(); + map_trap(trap, 1); + display_self(); + cleared = TRUE; + } + + You("find %s.", an(defsyms[trap_to_defsym(tt)].explanation)); + + if (cleared) { + display_nhwindow(WIN_MAP, TRUE); /* wait */ + docrt(); + } } int @@ -1003,7 +1149,10 @@ register int aflag; } else { int fund = (uwep && uwep->oartifact && spec_ability(uwep, SPFX_SEARCH)) ? - ((uwep->spe > 5) ? 5 : uwep->spe) : 0; + uwep->spe : 0; + if (ublindf && ublindf->otyp == LENSES && !Blind) + fund += 2; /* JDS: lenses help searching */ + if (fund > 5) fund = 5; for(x = u.ux-1; x < u.ux+2; x++) for(y = u.uy-1; y < u.uy+2; y++) { if(!isok(x,y)) continue; @@ -1045,18 +1194,17 @@ register int aflag; You_feel("an unseen monster!"); map_invisible(x, y); } - } else + } else if (!sensemon(mtmp)) You("find %s.", a_monnam(mtmp)); return(1); } - if(mtmp->mundetected && - (is_hider(mtmp->data) || mtmp->data->mlet == S_EEL)) { - mtmp->mundetected = 0; + if(!canspotmon(mtmp)) { + if (mtmp->mundetected && + (is_hider(mtmp->data) || mtmp->data->mlet == S_EEL)) + mtmp->mundetected = 0; newsym(x,y); goto find; } - if (!canspotmon(mtmp)) - goto find; } /* see if an invisible monster has moved--if Blind, diff --git a/src/dig.c b/src/dig.c index 8f43993..d9aa5e5 100644 --- a/src/dig.c +++ b/src/dig.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dig.c 3.3 2000/04/19 */ +/* SCCS Id: @(#)dig.c 3.4 2001/09/06 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -134,6 +134,15 @@ xchar x, y; IS_TREE(levl[x][y].typ) ? 4: 0); } +boolean +is_digging() +{ + if (occupation == dig) { + return TRUE; + } + return FALSE; +} + #define BY_YOU (&youmonst) #define BY_OBJECT ((struct monst *)0) @@ -211,24 +220,34 @@ dig() } } if(Fumbling && !rn2(3)) { - switch(rn2(3)) { - case 0: if(!welded(uwep)) { - You("fumble and drop your %s.", xname(uwep)); - dropx(uwep); - setuwep((struct obj *)0); - } else { - pline("Ouch! Your %s bounces and hits you!", - xname(uwep)); - set_wounded_legs(RIGHT_SIDE, 5 + rnd(5)); - } - break; - case 1: pline("Bang! You hit with the broad side of %s!", - the(xname(uwep))); - break; - default: Your("swing misses its mark."); - break; + switch(rn2(3)) { + case 0: + if(!welded(uwep)) { + You("fumble and drop your %s.", xname(uwep)); + dropx(uwep); + } else { +#ifdef STEED + if (u.usteed) + Your("%s %s and %s %s!", + xname(uwep), + otense(uwep, "bounce"), otense(uwep, "hit"), + mon_nam(u.usteed)); + else +#endif + pline("Ouch! Your %s %s and %s you!", + xname(uwep), + otense(uwep, "bounce"), otense(uwep, "hit")); + set_wounded_legs(RIGHT_SIDE, 5 + rnd(5)); } - return(0); + break; + case 1: + pline("Bang! You hit with the broad side of %s!", + the(xname(uwep))); + break; + default: Your("swing misses its mark."); + break; + } + return(0); } digging.effort += 10 + rn2(5) + abon() + @@ -276,7 +295,14 @@ dig() */ digtxt = (char *)0; } else if ((obj = sobj_at(BOULDER, dpx, dpy)) != 0) { + struct obj *bobj; + fracture_rock(obj); + if ((bobj = sobj_at(BOULDER, dpx, dpy)) != 0) { + /* another boulder here, restack it to the top */ + obj_extract_self(bobj); + place_object(bobj, dpx, dpy); + } digtxt = "The boulder falls apart."; } else if (lev->typ == STONE || lev->typ == SCORR || IS_TREE(lev->typ)) { @@ -326,12 +352,13 @@ dig() lev->doormask = D_BROKEN; } else return(0); /* statue or boulder got taken */ - unblock_point(dpx,dpy); /* vision: can see through */ + if(!does_block(dpx,dpy,&levl[dpx][dpy])) + unblock_point(dpx,dpy); /* vision: can see through */ if(Blind) feel_location(dpx, dpy); else newsym(dpx, dpy); - if(digtxt) pline(digtxt); /* after newsym */ + if(digtxt && !digging.quiet) pline(digtxt); /* after newsym */ if(dmgtxt) pay_for_damage(dmgtxt); @@ -356,6 +383,8 @@ dig() newsym(dpx, dpy); } cleanup: + digging.lastdigtime = moves; + digging.quiet = FALSE; digging.level.dnum = 0; digging.level.dlevel = -1; return(0); @@ -462,7 +491,12 @@ int ttyp; ttyp = PIT; } - Strcpy(surface_type, surface(x,y)); /* maketrap() might change it */ + /* maketrap() might change it, also, in this situation, + surface() returns an inappropriate string for a grave */ + if (IS_GRAVE(lev->typ)) + Strcpy(surface_type, "grave"); + else + Strcpy(surface_type, surface(x,y)); shopdoor = IS_DOOR(lev->typ) && *in_rooms(x, y, SHOPBASE); oldobjs = level.objects[x][y]; ttmp = maketrap(x, y, ttyp); @@ -746,9 +780,8 @@ struct obj *obj; char dirsyms[12]; char qbuf[QBUFSZ]; register char *dsp = dirsyms; - register struct rm *lev; register int rx, ry; - int dig_target, res = 0; + int res = 0; register const char *sdp; if(iflags.num_pad) sdp = ndir; else sdp = sdir; /* DICE workaround */ @@ -777,6 +810,22 @@ struct obj *obj; Sprintf(qbuf, "In what direction do you want to dig? [%s]", dirsyms); if(!getdir(qbuf)) return(res); + + return(use_pick_axe2(obj)); +} + +/* MRKR: use_pick_axe() is split in two to allow autodig to bypass */ +/* the "In what direction do you want to dig?" query. */ +/* use_pick_axe2() uses the existing u.dx, u.dy and u.dz */ + +int +use_pick_axe2(obj) +struct obj *obj; +{ + register int rx, ry; + register struct rm *lev; + int dig_target; + if (u.uswallow && attack(u.ustuck)) { ; /* return(1) */ } else if (Underwater) { @@ -793,10 +842,9 @@ struct obj *obj; dam = rnd(2) + dbon() + obj->spe; if (dam <= 0) dam = 1; You("hit yourself with %s.", yname(uwep)); - /* self_pronoun() won't work twice in a sentence */ - Strcpy(buf, self_pronoun("killed %sself with %%s pick-axe", - "him")); - losehp(dam, self_pronoun(buf, "his"), NO_KILLER_PREFIX); + Sprintf(buf, "%s own %s", uhis(), + OBJ_NAME(objects[obj->otyp])); + losehp(dam, buf, KILLED_BY); flags.botl=1; return(1); } else if(u.dz == 0) { @@ -820,8 +868,8 @@ struct obj *obj; seetrap(trap); There("is a spider web there!"); } - Your("%s becomes entangled in the web.", - aobjnam(obj, (char *)0)); + Your("%s entangled in the web.", + aobjnam(obj, "become")); /* you ought to be able to let go; tough luck */ /* (maybe `move_into_trap()' would be better) */ nomul(-d(2,2)); @@ -837,20 +885,32 @@ struct obj *obj; "chopping at the door", "cutting the tree" }; + did_dig_msg = FALSE; + digging.quiet = FALSE; if (digging.pos.x != rx || digging.pos.y != ry || !on_level(&digging.level, &u.uz) || digging.down) { + if (flags.autodig && !dig_target && !digging.down && + digging.pos.x == u.ux && + digging.pos.y == u.uy && + (moves <= digging.lastdigtime+2 && + moves >= digging.lastdigtime)) { + /* avoid messages if repeated autodigging */ + did_dig_msg = TRUE; + digging.quiet = TRUE; + } digging.down = digging.chew = FALSE; + digging.warned = FALSE; digging.pos.x = rx; digging.pos.y = ry; assign_level(&digging.level, &u.uz); digging.effort = 0; - You("start %s.", d_action[dig_target]); + if (!digging.quiet) + You("start %s.", d_action[dig_target]); } else { You("%s %s.", digging.chew ? "begin" : "continue", d_action[dig_target]); digging.chew = FALSE; } - did_dig_msg = FALSE; set_occupation(dig, "digging", 0); } } else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) { @@ -867,6 +927,7 @@ struct obj *obj; !on_level(&digging.level, &u.uz) || !digging.down) { digging.chew = FALSE; digging.down = TRUE; + digging.warned = FALSE; digging.pos.x = u.ux; digging.pos.y = u.uy; assign_level(&digging.level, &u.uz); @@ -881,6 +942,56 @@ struct obj *obj; return(1); } +/* + * Town Watchmen frown on damage to the town walls or fountains. + * It's OK to dig holes in the ground, however. + * If mtmp is assumed to be a watchman, a watchman is found if mtmp == 0 + * zap == TRUE if wand/spell of digging, FALSE otherwise (chewing) + */ +void +watch_dig(mtmp, x, y, zap) + struct monst *mtmp; + xchar x, y; + boolean zap; +{ + s_level *slev = Is_special(&u.uz); + struct rm *lev = &levl[x][y]; + + if (slev && slev->flags.town && + (closed_door(x, y) || lev->typ == SDOOR || + IS_WALL(lev->typ) || IS_FOUNTAIN(lev->typ))) { + if (!mtmp) { + for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { + if (DEADMONSTER(mtmp)) continue; + if ((mtmp->data == &mons[PM_WATCHMAN] || + mtmp->data == &mons[PM_WATCH_CAPTAIN]) && + mtmp->mcansee && m_canseeu(mtmp) && + couldsee(mtmp->mx, mtmp->my) && mtmp->mpeaceful) + break; + } + } + + if (mtmp) { + if(zap || digging.warned) { + verbalize("Halt, vandal! You're under arrest!"); + (void) angry_guards(!(flags.soundok)); + } else { + char *str; + if (IS_DOOR(lev->typ)) + str = "door"; + else if (IS_WALL(lev->typ)) + str = "wall"; + else + str = "fountain"; + verbalize("Hey, stop damaging that %s!", str); + digging.warned = TRUE; + } + if (is_digging()) + stop_occupation(); + } + } +} + #endif /* OVLB */ #ifdef OVL0 @@ -949,7 +1060,7 @@ register struct monst *mtmp; if (pile && pile < 5) /* leave behind some rocks? */ (void) mksobj_at((pile == 1) ? BOULDER : ROCK, - mtmp->mx, mtmp->my, TRUE); + mtmp->mx, mtmp->my, TRUE, FALSE); newsym(mtmp->mx, mtmp->my); if (!sobj_at(BOULDER, mtmp->mx, mtmp->my)) unblock_point(mtmp->mx, mtmp->my); /* vision */ @@ -983,7 +1094,8 @@ zap_dig() if (!is_whirly(mtmp->data)) { if (is_animal(mtmp->data)) - You("pierce %s stomach wall!", s_suffix(mon_nam(mtmp))); + You("pierce %s %s wall!", + s_suffix(mon_nam(mtmp)), mbodypart(mtmp, STOMACH)); mtmp->mhp = 1; /* almost dead */ expels(mtmp, mtmp->data, !is_animal(mtmp->data)); } @@ -1001,12 +1113,14 @@ zap_dig() pline("It falls on your %s!", body_part(HEAD)); losehp(rnd((uarmh && is_metallic(uarmh)) ? 2 : 6), "falling rock", KILLED_BY_AN); - if ((otmp = mksobj_at(ROCK, u.ux, u.uy, FALSE)) != 0) { + otmp = mksobj_at(ROCK, u.ux, u.uy, FALSE, FALSE); + if (otmp) { (void)xname(otmp); /* set dknown, maybe bknown */ stackobj(otmp); } if (Invisible) newsym(u.ux, u.uy); } else { + watch_dig((struct monst *)0, u.ux, u.uy, TRUE); (void) dighole(FALSE); } } @@ -1034,6 +1148,7 @@ zap_dig() room->typ = DOOR; else if (cansee(zx, zy)) pline_The("door is razed!"); + watch_dig((struct monst *)0, zx, zy, TRUE); room->doormask = D_NODOOR; unblock_point(zx,zy); /* vision */ digdepth -= 2; @@ -1065,6 +1180,7 @@ zap_dig() add_damage(zx, zy, 200L); shopwall = TRUE; } + watch_dig((struct monst *)0, zx, zy, TRUE); if (level.flags.is_cavernous_lev) { room->typ = CORR; } else { @@ -1232,10 +1348,12 @@ long timeout; /* unused */ x = obj->ox; y = obj->oy; } else if (in_invent) { - if (flags.verbose) - Your("%s%s rot%s away%c", - obj == uwep ? "wielded " : "", corpse_xname(obj, FALSE), - obj->quan == 1L ? "s" : "", obj == uwep ? '!' : '.'); + if (flags.verbose) { + char *cname = corpse_xname(obj, FALSE); + Your("%s%s %s away%c", + obj == uwep ? "wielded " : nul, cname, + vtense(cname, "rot"), obj == uwep ? '!' : '.'); + } if (obj == uwep) { uwepgone(); /* now bare handed */ stop_occupation(); @@ -1248,7 +1366,7 @@ long timeout; /* unused */ } } else if (obj->where == OBJ_MINVENT && obj->owornmask) { if (obj == MON_WEP(obj->ocarry)) { - obj->owornmask &= ~W_WEP; + setmnotwielded(obj->ocarry,obj); MON_NOWEP(obj->ocarry); } } diff --git a/src/display.c b/src/display.c index 8c55b50..268f7cf 100644 --- a/src/display.c +++ b/src/display.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)display.c 3.3 2000/07/27 */ +/* SCCS Id: @(#)display.c 3.4 2000/07/27 */ /* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */ /* and Dave Cohrs, 1990. */ /* NetHack may be freely redistributed. See license for details. */ @@ -337,6 +337,9 @@ void map_location(x,y,show) _map_location(x,y,show); } +#define DETECTED 2 +#define PHYSICALLY_SEEN 1 +#define is_worm_tail(mon) ((mon) && ((x != (mon)->mx) || (y != (mon)->my))) /* * display_monster() @@ -350,10 +353,11 @@ void map_location(x,y,show) * */ STATIC_OVL void -display_monster(x, y, mon, in_sight, worm_tail) +display_monster(x, y, mon, sightflags, worm_tail) register xchar x, y; /* display position */ register struct monst *mon; /* monster to display */ - int in_sight; /* TRUE if the monster is physically seen */ + int sightflags; /* 1 if the monster is physically seen */ + /* 2 if detected using Detect_monsters */ register xchar worm_tail; /* mon is actually a worm tail */ { register boolean mon_mimic = (mon->m_ap_type != M_AP_NOTHING); @@ -366,7 +370,7 @@ display_monster(x, y, mon, in_sight, worm_tail) * the mimic was mimicing. */ - if (mon_mimic && in_sight) { + if (mon_mimic && sightflags) { switch (mon->m_ap_type) { default: impossible("display_monster: bad m_ap_type value [ = %d ]", @@ -403,7 +407,7 @@ display_monster(x, y, mon, in_sight, worm_tail) } case M_AP_MONSTER: - show_glyph(x,y, monnum_to_glyph(what_mon(mon->mappearance))); + show_glyph(x,y, monnum_to_glyph(what_mon((int)mon->mappearance))); break; } @@ -413,7 +417,10 @@ display_monster(x, y, mon, in_sight, worm_tail) if (!mon_mimic || sensed) { int num; - if (Detect_monsters) { + /* [ALI] Only use detected glyphs when monster wouldn't be + * visible by any other means. + */ + if (sightflags == DETECTED) { if (worm_tail) num = detected_monnum_to_glyph(what_mon(PM_LONG_WORM_TAIL)); else @@ -589,7 +596,9 @@ feel_location(x, y) } /* draw monster on top if we can sense it */ if ((x != u.ux || y != u.uy) && (mon = m_at(x,y)) && sensemon(mon)) - display_monster(x,y,mon,1,((x != mon->mx) || (y != mon->my))); + display_monster(x, y, mon, + (tp_sensemon(mon) || MATCH_WARN_OF_MON(mon)) ? PHYSICALLY_SEEN : DETECTED, + is_worm_tail(mon)); } /* @@ -653,15 +662,27 @@ newsym(x,y) } else { mon = m_at(x,y); - worm_tail = mon && ((x != mon->mx) || (y != mon->my)); - if (mon && - ((see_it = (worm_tail - ? (!mon->minvis || See_invisible) - : (mon_visible(mon)) || sensemon(mon))))) { + worm_tail = is_worm_tail(mon); + see_it = mon && (worm_tail + ? (!mon->minvis || See_invisible) + : (mon_visible(mon)) || tp_sensemon(mon) || MATCH_WARN_OF_MON(mon)); + if (mon && (see_it || (!worm_tail && Detect_monsters))) { + if (mon->mtrapped) { + struct trap *trap = t_at(x, y); + int tt = trap ? trap->ttyp : NO_TRAP; + + /* if monster is in a physical trap, you see the trap too */ + if (tt == BEAR_TRAP || tt == PIT || + tt == SPIKED_PIT ||tt == WEB) { + trap->tseen = TRUE; + } + } _map_location(x,y,0); /* map under the monster */ /* also gets rid of any invisibility glyph */ - display_monster(x,y,mon,see_it,worm_tail); + display_monster(x, y, mon, see_it ? PHYSICALLY_SEEN : DETECTED, worm_tail); } + else if (mon && mon_warning(mon) && !is_worm_tail(mon)) + display_warning(mon); else if (glyph_is_invisible(levl[x][y].glyph)) map_invisible(x, y); else @@ -677,15 +698,16 @@ newsym(x,y) if (canseeself()) display_self(); } else if ((mon = m_at(x,y)) - && (sensemon(mon) - || (see_with_infrared(mon) && mon_visible(mon))) - && !((x != mon->mx) || (y != mon->my))) { + && ((see_it = (tp_sensemon(mon) || MATCH_WARN_OF_MON(mon) + || (see_with_infrared(mon) && mon_visible(mon)))) + || Detect_monsters) + && !is_worm_tail(mon)) { /* Monsters are printed every time. */ /* This also gets rid of any invisibility glyph */ - display_monster(x,y,mon,0,0); + display_monster(x, y, mon, see_it ? 0 : DETECTED, 0); } else if ((mon = m_at(x,y)) && mon_warning(mon) && - !((x != mon->mx) || (y != mon->my))) { + !is_worm_tail(mon)) { display_warning(mon); } @@ -725,6 +747,7 @@ newsym(x,y) } } +#undef is_worm_tail /* * shieldeff() @@ -738,6 +761,7 @@ shieldeff(x,y) { register int i; + if (!flags.sparkle) return; if (cansee(x,y)) { /* Don't see anything if can't see the location */ for (i = 0; i < SHIELD_COUNT; i++) { show_glyph(x, y, cmap_to_glyph(shield_static[i])); @@ -1183,6 +1207,8 @@ show_glyph(x,y,glyph) text = "swallow border"; offset = glyph - GLYPH_SWALLOW_OFF; } else if (glyph >= GLYPH_ZAP_OFF) { /* zap beam */ text = "zap beam"; offset = glyph - GLYPH_ZAP_OFF; + } else if (glyph >= GLYPH_EXPLODE_OFF) { /* explosion */ + text = "explosion"; offset = glyph - GLYPH_EXPLODE_OFF; } else if (glyph >= GLYPH_CMAP_OFF) { /* cmap */ text = "cmap_index"; offset = glyph - GLYPH_CMAP_OFF; } else if (glyph >= GLYPH_OBJ_OFF) { /* object */ diff --git a/src/dlb.c b/src/dlb.c index ad95c5e..d6f2bf5 100644 --- a/src/dlb.c +++ b/src/dlb.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dlb.c 3.3 97/07/29 */ +/* SCCS Id: @(#)dlb.c 3.4 1997/07/29 */ /* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1993. */ /* NetHack may be freely redistributed. See license for details. */ @@ -350,6 +350,13 @@ lib_dlb_fgets(buf, len, dp) } *bp = '\0'; +#if defined(MSDOS) || defined(WIN32) + if ((bp = index(buf, '\r')) != 0) { + *bp++ = '\n'; + *bp = '\0'; + } +#endif + return buf; } diff --git a/src/do.c b/src/do.c index 0dbd95d..2b7bbe9 100644 --- a/src/do.c +++ b/src/do.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)do.c 3.3 1999/11/29 */ +/* SCCS Id: @(#)do.c 3.4 2001/11/29 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -48,11 +48,15 @@ static NEARDATA const char drop_types[] = int dodrop() { +#ifndef GOLDOBJ int result, i = (invent || u.ugold) ? 0 : (SIZE(drop_types) - 1); +#else + int result, i = (invent) ? 0 : (SIZE(drop_types) - 1); +#endif - if (*u.ushops) sellobj_state(TRUE); + if (*u.ushops) sellobj_state(SELL_DELIBERATE); result = drop(getobj(&drop_types[i], "drop")); - if (*u.ushops) sellobj_state(FALSE); + if (*u.ushops) sellobj_state(SELL_NORMAL); reset_occupations(); return result; @@ -162,14 +166,16 @@ const char *verb; if (((mtmp = m_at(x, y)) && mtmp->mtrapped) || (u.utrap && u.ux == x && u.uy == y)) { if (*verb) - pline_The("boulder %ss into the pit%s.", verb, + pline_The("boulder %s into the pit%s.", + vtense((const char *)0, verb), (mtmp) ? "" : " with you"); if (mtmp) { if (!passes_walls(mtmp->data) && !throws_rocks(mtmp->data)) { - if (hmon(mtmp, obj, TRUE)) + if (hmon(mtmp, obj, TRUE) && !is_whirly(mtmp->data)) return FALSE; /* still alive */ - } else mtmp->mtrapped = 0; + } + mtmp->mtrapped = 0; } else { if (!Passes_walls && !throws_rocks(youmonst.data)) { losehp(rnd(15), "squished under a boulder", @@ -197,6 +203,8 @@ const char *verb; bury_objs(x, y); newsym(x,y); return TRUE; + } else if (is_lava(x, y)) { + return fire_damage(obj, FALSE, FALSE, x, y); } else if (is_pool(x, y)) { water_damage(obj, FALSE, FALSE); } @@ -210,20 +218,20 @@ void doaltarobj(obj) /* obj is an object dropped on an altar */ register struct obj *obj; { - if (Blind) return; + if (Blind || obj->oclass == GOLD_CLASS) + return; /* KMH, conduct */ u.uconduct.gnostic++; if (obj->blessed || obj->cursed) { - There("is %s flash as %s hit%s the altar.", + There("is %s flash as %s %s the altar.", an(hcolor(obj->blessed ? amber : Black)), - doname(obj), - (obj->quan == 1L) ? "s" : ""); + doname(obj), otense(obj, "hit")); if (!Hallucination) obj->bknown = 1; } else { - pline("%s land%s on the altar.", Doname2(obj), - (obj->quan == 1L) ? "s" : ""); + pline("%s %s on the altar.", Doname2(obj), + otense(obj, "land")); obj->bknown = 1; } } @@ -302,8 +310,8 @@ register struct obj *obj; if (otmp != uball && otmp != uchain && !obj_resists(otmp, 1, 99)) { if (!Blind) { - pline("Suddenly, %s vanishes from the sink!", - doname(otmp)); + pline("Suddenly, %s %s from the sink!", + doname(otmp), otense(otmp, "vanish")); ideed = TRUE; } delobj(otmp); @@ -446,7 +454,6 @@ register struct obj *obj; return(0); } setuwep((struct obj *)0); - if(uwep) return 0; /* lifesaved and rewielded */ } if(obj == uquiver) { setuqwep((struct obj *)0); @@ -458,10 +465,14 @@ register struct obj *obj; if (u.uswallow) { /* barrier between you and the floor */ if(flags.verbose) - You("drop %s into %s %s.", doname(obj), - s_suffix(mon_nam(u.ustuck)), - is_animal(u.ustuck->data) ? - "stomach" : "interior"); + { + char buf[BUFSZ]; + + /* doname can call s_suffix, reusing its buffer */ + Strcpy(buf, s_suffix(mon_nam(u.ustuck))); + You("drop %s into %s %s.", doname(obj), buf, + mbodypart(u.ustuck, STOMACH)); + } } else { #ifdef SINKS if((obj->oclass == RING_CLASS || obj->otyp == MEAT_RING) && @@ -491,8 +502,17 @@ void dropx(obj) register struct obj *obj; { - /* Money is usually not in our inventory */ +#ifndef GOLDOBJ if (obj->oclass != GOLD_CLASS || obj == invent) freeinv(obj); +#else + /* Ensure update when we drop gold objects */ + if (obj->oclass == GOLD_CLASS) flags.botl = 1; + /* Money is usually not in our inventory */ + /*if (obj->oclass != GOLD_CLASS || obj == invent)*/ + /* !!!! make sure we don't drop "created" gold not in inventory any more,*/ + /* or this will crash !!!! */ + freeinv(obj); +#endif if (!u.uswallow && ship_object(obj, u.ux, u.uy, FALSE)) return; dropy(obj); } @@ -501,27 +521,59 @@ void dropy(obj) register struct obj *obj; { + if (obj == uwep) setuwep((struct obj *)0); + if (obj == uquiver) setuqwep((struct obj *)0); + if (obj == uswapwep) setuswapwep((struct obj *)0); + if (!u.uswallow && flooreffects(obj,u.ux,u.uy,"drop")) return; - /* KMH -- Fixed crysknives have only 10% chance of reverting */ - if (obj->otyp == CRYSKNIFE && (!obj->oerodeproof || !rn2(10))) { - obj->otyp = WORM_TOOTH; - obj->oerodeproof = 0; - } /* uswallow check done by GAN 01/29/87 */ if(u.uswallow) { - if (obj != uball) { /* mon doesn't pick up ball */ - (void) mpickobj(u.ustuck,obj); + boolean could_petrify; + if (obj != uball) { /* mon doesn't pick up ball */ + could_petrify = obj->otyp == CORPSE && + touch_petrifies(&mons[obj->corpsenm]); + (void) mpickobj(u.ustuck,obj); + if (could_petrify && is_animal(u.ustuck->data)) { + minstapetrify(u.ustuck, TRUE); + /* Don't leave a cockatrice corpse available in a statue */ + if (!u.uswallow) delobj(obj); } + } } else { - place_object(obj, u.ux, u.uy); - if (obj == uball) - drop_ball(u.ux,u.uy); - else - sellobj(obj, u.ux, u.uy); - stackobj(obj); - if(Blind && Levitation) - map_object(obj, 0); - newsym(u.ux,u.uy); /* remap location under self */ + place_object(obj, u.ux, u.uy); + if (obj == uball) + drop_ball(u.ux,u.uy); + else + sellobj(obj, u.ux, u.uy); + stackobj(obj); + if(Blind && Levitation) + map_object(obj, 0); + newsym(u.ux,u.uy); /* remap location under self */ + } +} + +/* things that must change when not held; recurse into containers. + Called for both player and monsters */ +void +obj_no_longer_held(obj) +struct obj *obj; +{ + if (!obj) { + return; + } else if ((Is_container(obj) || obj->otyp == STATUE) && obj->cobj) { + struct obj *contents; + for(contents=obj->cobj; contents; contents=contents->nobj) + obj_no_longer_held(contents); + } + switch(obj->otyp) { + case CRYSKNIFE: + /* KMH -- Fixed crysknives have only 10% chance of reverting */ + /* only changes when not held by player or monster */ + if (!obj->oerodeproof || !rn2(10)) { + obj->otyp = WORM_TOOTH; + obj->oerodeproof = 0; + } + break; } } @@ -532,11 +584,11 @@ doddrop() int result = 0; add_valid_menu_class(0); /* clear any classes already there */ - if (*u.ushops) sellobj_state(TRUE); + if (*u.ushops) sellobj_state(SELL_DELIBERATE); if (flags.menu_style != MENU_TRADITIONAL || - (result = ggetobj("drop", drop, 0, FALSE)) < -1) + (result = ggetobj("drop", drop, 0, FALSE, (unsigned *)0)) < -1) result = menu_drop(result); - if (*u.ushops) sellobj_state(FALSE); + if (*u.ushops) sellobj_state(SELL_NORMAL); reset_occupations(); return result; @@ -549,11 +601,15 @@ int retry; { int n, i, n_dropped = 0; long cnt; - struct obj *otmp, *otmp2, *u_gold = 0; + struct obj *otmp, *otmp2; +#ifndef GOLDOBJ + struct obj *u_gold = 0; +#endif menu_item *pick_list; boolean all_categories = TRUE; boolean drop_everything = FALSE; +#ifndef GOLDOBJ if (u.ugold) { /* Hack: gold is not in the inventory, so make a gold object and put it at the head of the inventory list. */ @@ -563,14 +619,15 @@ int retry; u_gold->nobj = invent; invent = u_gold; } - +#endif if (retry) { all_categories = (retry == -2); } else if (flags.menu_style == MENU_FULL) { all_categories = FALSE; n = query_category("Drop what type of items?", invent, - UNPAID_TYPES | ALL_TYPES | CHOOSE_ALL, + UNPAID_TYPES | ALL_TYPES | CHOOSE_ALL | + BUC_BLESSED | BUC_CURSED | BUC_UNCURSED | BUC_UNKNOWN, &pick_list, PICK_ANY); if (!n) goto drop_done; for (i = 0; i < n; i++) { @@ -583,10 +640,15 @@ int retry; } free((genericptr_t) pick_list); } else if (flags.menu_style == MENU_COMBINATION) { + unsigned ggoresults = 0; all_categories = FALSE; /* Gather valid classes via traditional NetHack method */ - i = ggetobj("drop", drop, 0, TRUE); + i = ggetobj("drop", drop, 0, TRUE, &ggoresults); if (i == -2) all_categories = TRUE; + if (ggoresults & ALL_FINISHED) { + n_dropped = i; + goto drop_done; + } } if (drop_everything) { @@ -605,11 +667,12 @@ int retry; cnt = pick_list[i].count; if (cnt < otmp->quan && !welded(otmp) && (!otmp->cursed || otmp->otyp != LOADSTONE)) { - otmp2 = splitobj(otmp, cnt); - /* assume other worn items aren't mergable */ - if (otmp == uwep) setuwep(otmp2); - if (otmp == uquiver) setuqwep(otmp2); - if (otmp == uswapwep) setuswapwep(otmp2); +#ifndef GOLDOBJ + if (otmp->oclass == GOLD_CLASS) + (void) splitobj(otmp, otmp->quan - cnt); + else +#endif + otmp = splitobj(otmp, cnt); } n_dropped += drop(otmp); } @@ -618,12 +681,15 @@ int retry; } drop_done: +#ifndef GOLDOBJ if (u_gold && invent && invent->oclass == GOLD_CLASS) { /* didn't drop [all of] it */ u_gold = invent; invent = u_gold->nobj; dealloc_obj(u_gold); + update_inventory(); } +#endif return n_dropped; } @@ -641,11 +707,33 @@ dodown() (u.ux == sstairs.sx && u.uy == sstairs.sy && !sstairs.up)), ladder_down = (u.ux == xdnladder && u.uy == ydnladder); +#ifdef STEED + if (u.usteed && !u.usteed->mcanmove) { + pline("%s won't move!", Monnam(u.usteed)); + return(0); + } else if (u.usteed && u.usteed->meating) { + pline("%s is still eating.", Monnam(u.usteed)); + return(0); + } else +#endif if (Levitation) { if ((HLevitation & I_SPECIAL) || (ELevitation & W_ARTI)) { /* end controlled levitation */ - if (float_down(I_SPECIAL|TIMEOUT, W_ARTI)) - return (1); /* came down, so moved */ + if (ELevitation & W_ARTI) { + struct obj *obj; + + for(obj = invent; obj; obj = obj->nobj) { + if (obj->oartifact && + artifact_has_invprop(obj,LEVITATION)) { + if (obj->age < monstermoves) + obj->age = monstermoves + rnz(100); + else + obj->age += rnz(100); + } + } + } + if (float_down(I_SPECIAL|TIMEOUT, W_ARTI)) + return (1); /* came down, so moved */ } floating_above(stairs_down ? "stairs" : ladder_down ? "ladder" : surface(u.ux, u.uy)); @@ -660,7 +748,9 @@ dodown() } } if(u.ustuck) { - You("are being held, and cannot go down."); + You("are %s, and cannot go down.", + !u.uswallow ? "being held" : is_animal(u.ustuck->data) ? + "swallowed" : "engulfed"); return(1); } if (on_level(&valley_level, &u.uz) && !u.uevent.gehennom_entered) { @@ -702,8 +792,19 @@ doup() You_cant("go up here."); return(0); } +#ifdef STEED + if (u.usteed && !u.usteed->mcanmove) { + pline("%s won't move!", Monnam(u.usteed)); + return(0); + } else if (u.usteed && u.usteed->meating) { + pline("%s is still eating.", Monnam(u.usteed)); + return(0); + } else +#endif if(u.ustuck) { - You("are being held, and cannot go up."); + You("are %s, and cannot go up.", + !u.uswallow ? "being held" : is_animal(u.ustuck->data) ? + "swallowed" : "engulfed"); return(1); } if(near_capacity() > SLT_ENCUMBER) { @@ -1019,7 +1120,10 @@ boolean at_stairs, falling, portal; } losehp(rnd(3), "falling downstairs", KILLED_BY); #ifdef STEED - if (u.usteed) dismount_steed(DISMOUNT_FELL); + if (u.usteed) { + dismount_steed(DISMOUNT_FELL); + if (Punished) unplacebc(); + } #endif selftouch("Falling, you"); } else if (u.dz && at_ladder) @@ -1127,22 +1231,27 @@ boolean at_stairs, falling, portal; static const char *fam_msgs[4] = { "You have a sense of deja vu.", "You feel like you've been here before.", - "This place looks familiar...", + "This place %s familiar...", 0 /* no message */ }; static const char *halu_fam_msgs[4] = { - "Whoa! Everything looks different.", + "Whoa! Everything %s different.", "You are surrounded by twisty little passages, all alike.", - "Gee, this looks like uncle Conan's place...", + "Gee, this %s like uncle Conan's place...", 0 /* no message */ }; const char *mesg; + char buf[BUFSZ]; int which = rn2(4); if (Hallucination) mesg = halu_fam_msgs[which]; else mesg = fam_msgs[which]; + if (mesg && index(mesg, '%')) { + Sprintf(buf, mesg, !Blind ? "looks" : "seems"); + mesg = buf; + } if (mesg) pline(mesg); } @@ -1158,7 +1267,7 @@ boolean at_stairs, falling, portal; /* the message from your quest leader */ if (!In_quest(&u.uz0) && at_dgn_entrance("The Quest") && - !(u.uevent.qexpelled || u.uevent.qcompleted || leaderless())) { + !(u.uevent.qexpelled || u.uevent.qcompleted || quest_status.leader_is_dead)) { if (u.uevent.qcalled) { com_pager(Role_if(PM_ROGUE) ? 4 : 3); @@ -1324,12 +1433,22 @@ struct obj *corpse; boolean is_uwep, chewed; xchar where; char *cname, cname_buf[BUFSZ]; - + struct obj *container = (struct obj *)0; + int container_where = 0; + where = corpse->where; is_uwep = corpse == uwep; cname = eos(strcpy(cname_buf, "bite-covered ")); Strcpy(cname, corpse_xname(corpse, TRUE)); mcarry = (where == OBJ_MINVENT) ? corpse->ocarry : 0; + + if (where == OBJ_CONTAINED) { + struct monst *mtmp2 = (struct monst *)0; + container = corpse->ocontainer; + mtmp2 = get_container_location(container, &container_where, (int *)0); + /* container_where is the outermost container's location even if nested */ + if (container_where == OBJ_MINVENT && mtmp2) mcarry = mtmp2; + } mtmp = revive(corpse); /* corpse is gone if successful */ if (mtmp) { @@ -1359,7 +1478,27 @@ struct obj *corpse; Adjmonnam(mtmp, "bite-covered") : Monnam(mtmp)); } break; - + case OBJ_CONTAINED: + if (container_where == OBJ_MINVENT && cansee(mtmp->mx, mtmp->my) && + mcarry && canseemon(mcarry) && container) { + char sackname[BUFSZ]; + Sprintf(sackname, "%s %s", s_suffix(mon_nam(mcarry)), + xname(container)); + pline("%s writhes out of %s!", Amonnam(mtmp), sackname); + } else if (container_where == OBJ_INVENT && container) { + char sackname[BUFSZ]; + Strcpy(sackname, an(xname(container))); + pline("%s %s out of %s in your pack!", + Blind ? Something : Amonnam(mtmp), + locomotion(mtmp->data,"writhes"), + sackname); + } else if (container_where == OBJ_FLOOR && container && + cansee(mtmp->mx, mtmp->my)) { + char sackname[BUFSZ]; + Strcpy(sackname, an(xname(container))); + pline("%s escapes from %s!", Amonnam(mtmp), sackname); + } + break; default: /* we should be able to handle the other cases... */ impossible("revive_corpse: lost corpse @ %d", where); diff --git a/src/do_name.c b/src/do_name.c index 22165a9..193863b 100644 --- a/src/do_name.c +++ b/src/do_name.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)do_name.c 3.3 2000/06/12 */ +/* SCCS Id: @(#)do_name.c 3.4 2002/01/17 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -155,7 +155,7 @@ const char *goal; } /* column */ } /* row */ } /* pass */ - pline("Can't find dungeon feature '%c'", c); + pline("Can't find dungeon feature '%c'.", c); msg_given = TRUE; goto nxtc; } else { @@ -268,10 +268,7 @@ do_mname() return(0); } /* special case similar to the one in lookat() */ - if (mtmp->data != &mons[PM_HIGH_PRIEST]) - Strcpy(buf, x_monnam(mtmp, ARTICLE_THE, (char *)0, 0, TRUE)); - else - Sprintf(buf, "the high priest%s", mtmp->female ? "ess" : ""); + (void) distant_monnam(mtmp, ARTICLE_THE, buf); Sprintf(qbuf, "What do you want to call %s?", buf); getlin(qbuf,buf); if(!*buf || *buf == '\033') return(0); @@ -299,7 +296,7 @@ register struct obj *obj; short objtyp; Sprintf(qbuf, "What do you want to name %s %s?", - (obj->quan > 1L) ? "these" : "this", xname(obj)); + is_plural(obj) ? "these" : "this", xname(obj)); getlin(qbuf, buf); if(!*buf || *buf == '\033') return; /* strip leading and trailing spaces; unnames item if all spaces */ @@ -580,6 +577,7 @@ boolean called; struct permonst *mdat = mtmp->data; boolean do_hallu, do_invis, do_it, do_saddle; boolean name_at_start, has_adjectives; + char *bp; if (program_state.gameover) suppress |= SUPPRESS_HALLUCINATION; @@ -600,6 +598,12 @@ boolean called; buf[0] = 0; + /* unseen monsters, etc. Use "it" */ + if (do_it) { + Strcpy(buf, "it"); + return buf; + } + /* priests and minions: don't even use this function */ if (mtmp->ispriest || mtmp->isminion) { char priestnambuf[BUFSZ]; @@ -618,12 +622,6 @@ boolean called; return strcpy(buf, name); } - /* unseen monsters, etc. Use "it" */ - if (do_it) { - Strcpy(buf, "it"); - return buf; - } - /* Shopkeepers: use shopkeeper name. For normal shopkeepers, just * "Asidonhopo"; for unusual ones, "Asidonhopo the invisible * shopkeeper" or "Asidonhopo the blue dragon". If hallucinating, @@ -654,7 +652,8 @@ boolean called; if (do_invis) Strcat(buf, "invisible "); #ifdef STEED - if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) && !Blind) + if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) && + !Blind && !Hallucination) Strcat(buf, "saddled "); #endif if (buf[0] != 0) @@ -669,13 +668,25 @@ boolean called; name_at_start = FALSE; } else if (mtmp->mnamelth) { char *name = NAME(mtmp); - + if (mdat == &mons[PM_GHOST]) { Sprintf(eos(buf), "%s ghost", s_suffix(name)); name_at_start = TRUE; } else if (called) { Sprintf(eos(buf), "%s called %s", mdat->mname, name); name_at_start = (boolean)type_is_pname(mdat); + } else if (is_mplayer(mdat) && (bp = strstri(name, " the ")) != 0) { + /* the */ + char pbuf[BUFSZ]; + + Strcpy(pbuf, name); + pbuf[bp - name + 5] = '\0'; /* adjectives right after " the " */ + if (has_adjectives) + Strcat(pbuf, buf); + Strcat(pbuf, bp + 5); /* append the rest of the name */ + Strcpy(buf, pbuf); + article = ARTICLE_NONE; + name_at_start = TRUE; } else { Strcat(buf, name); name_at_start = TRUE; @@ -697,6 +708,9 @@ boolean called; article = ARTICLE_THE; else article = ARTICLE_NONE; + } else if (mons[monsndx(mdat)].geno & G_UNIQ && + article == ARTICLE_A) { + article = ARTICLE_THE; } { @@ -827,6 +841,27 @@ register struct monst *mtmp; return(bp); } +/* used for monster ID by the '/', ';', and 'C' commands to block remote + identification of the endgame altars via their attending priests */ +char * +distant_monnam(mon, article, outbuf) +struct monst *mon; +int article; /* only ARTICLE_NONE and ARTICLE_THE are handled here */ +char *outbuf; +{ + /* high priest(ess)'s identity is concealed on the Astral Plane, + unless you're adjacent (overridden for hallucination which does + its own obfuscation) */ + if (mon->data == &mons[PM_HIGH_PRIEST] && !Hallucination && + Is_astralevel(&u.uz) && distu(mon->mx, mon->my) > 2) { + Strcpy(outbuf, article == ARTICLE_THE ? "the " : ""); + Strcat(outbuf, mon->female ? "high priestess" : "high priest"); + } else { + Strcpy(outbuf, x_monnam(mon, article, (char *)0, 0, TRUE)); + } + return outbuf; +} + static const char *bogusmons[] = { "jumbo shrimp", "giant pigmy", "gnu", "killer penguin", "giant cockroach", "giant slug", "maggot", "pterodactyl", @@ -901,31 +936,6 @@ rndmonnam() return mons[name].mname; } -const char *pronoun_pairs[][2] = { - {"him", "her"}, {"Him", "Her"}, {"his", "her"}, {"His", "Her"}, - {"he", "she"}, {"He", "She"}, - {0, 0} -}; - -char * -self_pronoun(str, pronoun) -const char *str; -const char *pronoun; -{ - static NEARDATA char buf[BUFSZ]; - register int i; - - for(i=0; pronoun_pairs[i][0]; i++) { - if(!strncmp(pronoun, pronoun_pairs[i][0], 3)) { - Sprintf(buf, str, pronoun_pairs[i][flags.female]); - return buf; - } - } - impossible("never heard of pronoun %s?", pronoun); - Sprintf(buf, str, pronoun_pairs[i][0]); - return buf; -} - #ifdef REINCARNATION const char * roguename() /* Name of a Rogue player */ @@ -986,14 +996,16 @@ static const char *coynames[] = { "Nemesis Riduclii","Canis latrans" }; -char *coyotename(buf) +char *coyotename(mtmp, buf) +struct monst *mtmp; char *buf; { - if (buf) - Sprintf(buf, - "coyote - %s", - coynames[rn2(SIZE(coynames)-1)]); - return buf; + if (mtmp && buf) { + Sprintf(buf, "%s - %s", + x_monnam(mtmp, ARTICLE_NONE, (char *)0, 0, TRUE), + mtmp->mcan ? coynames[SIZE(coynames)-1] : coynames[rn2(SIZE(coynames)-1)]); + } + return buf; } #endif /* OVL2 */ diff --git a/src/do_wear.c b/src/do_wear.c index 06ed345..d361696 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)do_wear.c 3.3 2000/05/05 */ +/* SCCS Id: @(#)do_wear.c 3.4 2002/02/23 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -13,6 +13,7 @@ STATIC_DCL long takeoff_mask, taking_off; STATIC_OVL NEARDATA long takeoff_mask = 0L, taking_off = 0L; static NEARDATA int todelay; +static boolean cancelled_don = FALSE; static NEARDATA const char see_yourself[] = "see yourself"; static NEARDATA const char unknown_type[] = "Unknown type of %s (%d)"; @@ -67,9 +68,16 @@ STATIC_OVL void on_msg(otmp) register struct obj *otmp; { - if(flags.verbose) - You("are now wearing %s.", - obj_is_pname(otmp) ? the(xname(otmp)) : an(xname(otmp))); + if (flags.verbose) { + char how[BUFSZ]; + + how[0] = '\0'; + if (otmp->otyp == TOWEL) + Sprintf(how, " around your %s", body_part(HEAD)); + You("are now wearing %s%s.", + obj_is_pname(otmp) ? the(xname(otmp)) : an(xname(otmp)), + how); + } } /* @@ -81,8 +89,8 @@ STATIC_PTR int Boots_on() { - long oldprop = u.uprops[objects[uarmf->otyp].oc_oprop].extrinsic & ~WORN_BOOTS; - + long oldprop = + u.uprops[objects[uarmf->otyp].oc_oprop].extrinsic & ~WORN_BOOTS; switch(uarmf->otyp) { case LOW_BOOTS: @@ -117,6 +125,7 @@ Boots_on() if (!oldprop && !HLevitation) { makeknown(uarmf->otyp); float_up(); + spoteffects(FALSE); } break; default: impossible(unknown_type, c_boots, uarmf->otyp); @@ -128,7 +137,7 @@ int Boots_off() { int otyp = uarmf->otyp; - long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_BOOTS; + long oldprop = u.uprops[objects[otyp].oc_oprop].extrinsic & ~WORN_BOOTS; /* For levitation, float_down() returns if Levitation, so we @@ -137,22 +146,22 @@ Boots_off() setworn((struct obj *)0, W_ARMF); switch (otyp) { case SPEED_BOOTS: - if (!Very_fast) { + if (!Very_fast && !cancelled_don) { makeknown(otyp); You_feel("yourself slow down%s.", Fast ? " a bit" : ""); } break; case WATER_WALKING_BOOTS: - if (is_pool(u.ux,u.uy) && !Levitation - && !Flying && !is_clinger(youmonst.data)) { + if (is_pool(u.ux,u.uy) && !Levitation && !Flying && + !is_clinger(youmonst.data) && !cancelled_don) { makeknown(otyp); /* make boots known in case you survive the drowning */ spoteffects(TRUE); } break; case ELVEN_BOOTS: - if (!oldprop && !HStealth && !BStealth) { + if (!oldprop && !HStealth && !BStealth && !cancelled_don) { makeknown(otyp); You("sure are noisy."); } @@ -162,7 +171,7 @@ Boots_off() HFumbling = EFumbling = 0; break; case LEVITATION_BOOTS: - if (!oldprop && !HLevitation) { + if (!oldprop && !HLevitation && !cancelled_don) { (void) float_down(0L, 0L); makeknown(otyp); } @@ -175,14 +184,15 @@ Boots_off() break; default: impossible(unknown_type, c_boots, otyp); } + cancelled_don = FALSE; return 0; } STATIC_OVL int Cloak_on() { - long oldprop = u.uprops[objects[uarmc->otyp].oc_oprop].extrinsic & ~WORN_CLOAK; - + long oldprop = + u.uprops[objects[uarmc->otyp].oc_oprop].extrinsic & ~WORN_CLOAK; switch(uarmc->otyp) { case ELVEN_CLOAK: @@ -194,6 +204,7 @@ Cloak_on() case DWARVISH_CLOAK: case CLOAK_OF_MAGIC_RESISTANCE: case ROBE: + case LEATHER_CLOAK: break; case MUMMY_WRAPPING: /* Note: it's already being worn, so we have to cheat here. */ @@ -215,7 +226,7 @@ Cloak_on() } break; case OILSKIN_CLOAK: - pline("%s fits very tightly.",The(xname(uarmc))); + pline("%s very tightly.", Tobjnam(uarmc, "fit")); break; /* Alchemy smock gives poison _and_ acid resistance */ case ALCHEMY_SMOCK: @@ -244,6 +255,7 @@ Cloak_off() case CLOAK_OF_DISPLACEMENT: case OILSKIN_CLOAK: case ROBE: + case LEATHER_CLOAK: break; case MUMMY_WRAPPING: if (Invis && !Blind) { @@ -305,9 +317,11 @@ Helmet_on() /*FALLTHRU*/ case DUNCE_CAP: if (!uarmh->cursed) { - pline("%s %s%s for a moment.", The(xname(uarmh)), - Blind ? "vibrates" : "glows ", - Blind ? (const char *)"" : hcolor(Black)); + if (Blind) + pline("%s for a moment.", Tobjnam(uarmh, "vibrate")); + else + pline("%s %s for a moment.", + Tobjnam(uarmh, "glow"), hcolor(Black)); curse(uarmh); } flags.botl = 1; /* reveal new alignment or INT & WIS */ @@ -337,30 +351,33 @@ Helmet_off() case ELVEN_LEATHER_HELM: case DWARVISH_IRON_HELM: case ORCISH_HELM: - break; + break; case DUNCE_CAP: - flags.botl = 1; - break; + flags.botl = 1; + break; case CORNUTHAUM: + if (!cancelled_don) { ABON(A_CHA) += (Role_if(PM_WIZARD) ? -1 : 1); flags.botl = 1; - break; + } + break; case HELM_OF_TELEPATHY: - /* need to update ability before calling see_monsters() */ - setworn((struct obj *)0, W_ARMH); - see_monsters(); - return 0; + /* need to update ability before calling see_monsters() */ + setworn((struct obj *)0, W_ARMH); + see_monsters(); + return 0; case HELM_OF_BRILLIANCE: - adj_abon(uarmh, -uarmh->spe); - break; + if (!cancelled_don) adj_abon(uarmh, -uarmh->spe); + break; case HELM_OF_OPPOSITE_ALIGNMENT: - u.ualign.type = u.ualignbase[A_CURRENT]; - u.ublessed = 0; /* lose the other god's protection */ - flags.botl = 1; - break; + u.ualign.type = u.ualignbase[A_CURRENT]; + u.ublessed = 0; /* lose the other god's protection */ + flags.botl = 1; + break; default: impossible(unknown_type, c_helmet, uarmh->otyp); } setworn((struct obj *)0, W_ARMH); + cancelled_don = FALSE; return 0; } @@ -369,8 +386,7 @@ int Gloves_on() { long oldprop = - u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES; - + u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES; switch(uarmg->otyp) { case LEATHER_GLOVES: @@ -395,50 +411,51 @@ int Gloves_off() { long oldprop = - u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES; - + u.uprops[objects[uarmg->otyp].oc_oprop].extrinsic & ~WORN_GLOVES; switch(uarmg->otyp) { case LEATHER_GLOVES: - break; + break; case GAUNTLETS_OF_FUMBLING: - if (!oldprop && !(HFumbling & ~TIMEOUT)) - HFumbling = EFumbling = 0; - break; + if (!oldprop && !(HFumbling & ~TIMEOUT)) + HFumbling = EFumbling = 0; + break; case GAUNTLETS_OF_POWER: - makeknown(uarmg->otyp); - flags.botl = 1; /* taken care of in attrib.c */ - break; + makeknown(uarmg->otyp); + flags.botl = 1; /* taken care of in attrib.c */ + break; case GAUNTLETS_OF_DEXTERITY: - adj_abon(uarmg, -uarmg->spe); - break; + if (!cancelled_don) adj_abon(uarmg, -uarmg->spe); + break; default: impossible(unknown_type, c_gloves, uarmg->otyp); } setworn((struct obj *)0, W_ARMG); + cancelled_don = FALSE; /* Prevent wielding cockatrice when not wearing gloves */ if (uwep && uwep->otyp == CORPSE && touch_petrifies(&mons[uwep->corpsenm])) { char kbuf[BUFSZ]; - You("wield the %s corpse in your bare %s.", - mons[uwep->corpsenm].mname, makeplural(body_part(HAND))); - Sprintf(kbuf, "%s corpse", an(mons[uwep->corpsenm].mname)); + You("wield the %s in your bare %s.", + corpse_xname(uwep, TRUE), makeplural(body_part(HAND))); + Strcpy(kbuf, an(corpse_xname(uwep, TRUE))); instapetrify(kbuf); uwepgone(); /* life-saved still doesn't allow touching cockatrice */ } - /* KMH -- ...or your secondary weapon when you're wielding it */ - if (u.twoweap && uswapwep && uswapwep->otyp == CORPSE && - touch_petrifies(&mons[uswapwep->corpsenm])) { + + /* KMH -- ...or your secondary weapon when you're wielding it */ + if (u.twoweap && uswapwep && uswapwep->otyp == CORPSE && + touch_petrifies(&mons[uswapwep->corpsenm])) { char kbuf[BUFSZ]; - You("wield the %s corpse in your bare %s.", - mons[uswapwep->corpsenm].mname, body_part(HAND)); + You("wield the %s in your bare %s.", + corpse_xname(uswapwep, TRUE), body_part(HAND)); - Sprintf(kbuf, "%s corpse", an(mons[uswapwep->corpsenm].mname)); + Strcpy(kbuf, an(corpse_xname(uswapwep, TRUE))); instapetrify(kbuf); - uswapwepgone(); /* life-saved still doesn't allow touching cockatrice */ - } + uswapwepgone(); /* lifesaved still doesn't allow touching cockatrice */ + } return 0; } @@ -497,6 +514,7 @@ int Armor_off() { setworn((struct obj *)0, W_ARM); + cancelled_don = FALSE; return 0; } @@ -507,6 +525,7 @@ int Armor_gone() { setnotworn(uarm); + cancelled_don = FALSE; return 0; } @@ -544,6 +563,10 @@ Amulet_on() changed the character's base sex */ You("don't feel like yourself."); pline_The("amulet disintegrates!"); + if (orig_sex == poly_gender() && uamul->dknown && + !objects[AMULET_OF_CHANGE].oc_name_known && + !objects[AMULET_OF_CHANGE].oc_uname) + docall(uamul); useup(uamul); break; } @@ -578,13 +601,14 @@ Amulet_off() break; case AMULET_OF_MAGICAL_BREATHING: if (Underwater) { - if (!breathless(youmonst.data) && !amphibious(youmonst.data) - && !Swimming) - You("suddenly inhale an unhealthy amount of water!"); /* HMagical_breathing must be set off - before calling drown() */ + before calling drown() */ setworn((struct obj *)0, W_AMUL); - (void) drown(); + if (!breathless(youmonst.data) && !amphibious(youmonst.data) + && !Swimming) { + You("suddenly inhale an unhealthy amount of water!"); + (void) drown(); + } return; } break; @@ -613,10 +637,9 @@ register struct obj *obj; long oldprop = u.uprops[objects[obj->otyp].oc_oprop].extrinsic; int old_attrib; - - if (obj == uwep) setuwep((struct obj *) 0); - if (obj == uswapwep) setuswapwep((struct obj *) 0); - if (obj == uquiver) setuqwep((struct obj *) 0); + if (obj == uwep) setuwep((struct obj *) 0); + if (obj == uswapwep) setuswapwep((struct obj *) 0); + if (obj == uquiver) setuqwep((struct obj *) 0); /* only mask out W_RING when we don't have both left and right rings of the same type */ @@ -683,6 +706,7 @@ register struct obj *obj; float_up(); makeknown(RIN_LEVITATION); obj->known = TRUE; + spoteffects(FALSE); /* for sinks */ } break; case RIN_GAIN_STRENGTH: @@ -720,6 +744,7 @@ register struct obj *obj; if (obj->spe || objects[RIN_PROTECTION].oc_name_known) { makeknown(RIN_PROTECTION); obj->known = TRUE; + update_inventory(); } break; } @@ -839,22 +864,30 @@ void Blindf_on(otmp) register struct obj *otmp; { - long already_blinded = Blinded; + boolean already_blind = Blind, changed = FALSE; if (otmp == uwep) setuwep((struct obj *) 0); if (otmp == uswapwep) - setuswapwep((struct obj *) 0); + setuswapwep((struct obj *) 0); if (otmp == uquiver) - setuqwep((struct obj *) 0); + setuqwep((struct obj *) 0); setworn(otmp, W_TOOL); - if (otmp->otyp == TOWEL && flags.verbose) - You("wrap %s around your %s.", an(xname(otmp)), body_part(HEAD)); on_msg(otmp); - if (!already_blinded) { - if (Punished) set_bc(0); /* Set ball&chain variables before */ - /* the hero goes blind. */ - if (Blind_telepat || Infravision) see_monsters(); /* sense monsters */ + + if (Blind && !already_blind) { + changed = TRUE; + if (flags.verbose) You_cant("see any more."); + /* set ball&chain variables before the hero goes blind */ + if (Punished) set_bc(0); + } else if (already_blind && !Blind) { + changed = TRUE; + /* "You are now wearing the Eyes of the Overworld." */ + You("can see!"); + } + if (changed) { + /* blindness has just been toggled */ + if (Blind_telepat || Infravision) see_monsters(); vision_full_recalc = 1; /* recalc vision limits */ flags.botl = 1; } @@ -864,23 +897,34 @@ void Blindf_off(otmp) register struct obj *otmp; { - long was_blind = Blind; /* may still be able to see */ + boolean was_blind = Blind, changed = FALSE; setworn((struct obj *)0, otmp->owornmask); off_msg(otmp); if (Blind) { - if (otmp->otyp == LENSES) - ; /* "still cannot see" makes no sense for lenses; do nothing */ - else if (was_blind) - You("still cannot see."); - else - You("cannot see anything now!"); - } else if (!Blinded) { + if (was_blind) { + /* "still cannot see" makes no sense when removing lenses + since they can't have been the cause of your blindness */ + if (otmp->otyp != LENSES) + You("still cannot see."); + } else { + changed = TRUE; /* !was_blind */ + /* "You were wearing the Eyes of the Overworld." */ + You_cant("see anything now!"); + /* set ball&chain variables before the hero goes blind */ + if (Punished) set_bc(0); + } + } else if (was_blind) { + changed = TRUE; /* !Blind */ + You("can see again."); + } + if (changed) { + /* blindness has just been toggled */ if (Blind_telepat || Infravision) see_monsters(); + vision_full_recalc = 1; /* recalc vision limits */ + flags.botl = 1; } - vision_full_recalc = 1; /* recalc vision limits */ - flags.botl = 1; } /* called in main to set intrinsics of worn start-up items */ @@ -912,6 +956,8 @@ cancel_don() * wasting time on it (and don't dereference it when donning would * otherwise finish) */ + cancelled_don = (afternmv == Boots_on || afternmv == Helmet_on || + afternmv == Gloves_on || afternmv == Armor_on); afternmv = 0; nomovemsg = (char *)0; multi = 0; @@ -975,6 +1021,16 @@ dotakeoff() is_sword(uwep) ? c_sword : c_weapon); uwep->bknown = TRUE; return 0; + } else if (welded(uwep) && bimanual(uwep) && + (otmp == uarm +#ifdef TOURIST + || otmp == uarmu +#endif + )) { + You("seem unable to take off %s while holding your %s.", + the(xname(otmp)), is_sword(uwep) ? c_sword : c_weapon); + uwep->bknown = TRUE; + return 0; } if (otmp == uarmg && Glib) { You_cant("remove the slippery gloves with your slippery fingers."); @@ -1011,7 +1067,7 @@ doremring() pline("Not wearing any accessories."); return(0); } - if (Accessories != 1) otmp = getobj(accessories, "take off"); + if (Accessories != 1) otmp = getobj(accessories, "remove"); if(!otmp) return(0); if(!(otmp->owornmask & (W_RING | W_AMUL | W_TOOL))) { You("are not wearing that."); @@ -1171,6 +1227,18 @@ boolean noisy; return 0; } + if (welded(uwep) && bimanual(uwep) && + (otmp == uarm +#ifdef TOURIST + || otmp == uarmu +#endif + )) { + if (noisy) + You("cannot do that while holding your %s.", + is_sword(uwep) ? c_sword : c_weapon); + return 0; + } + if (is_helmet(otmp)) { if (uarmh) { if (noisy) already_wearing(an(c_helmet)); @@ -1229,7 +1297,7 @@ boolean noisy; if (noisy) already_wearing(an(c_shirt)); } else { if (noisy) You_cant("wear that over your %s.", - (uarm && !uarmc) ? c_armor : c_cloak); + (uarm && !uarmc) ? c_armor : cloak_simple_name(uarmc)); } err++; } else @@ -1237,13 +1305,13 @@ boolean noisy; #endif } else if (is_cloak(otmp)) { if (uarmc) { - if (noisy) already_wearing(an(c_cloak)); + if (noisy) already_wearing(an(cloak_simple_name(uarmc))); err++; } else *mask = W_ARMC; } else if (is_suit(otmp)) { if (uarmc) { - if (noisy) You("cannot wear armor over a cloak."); + if (noisy) You("cannot wear armor over a %s.", cloak_simple_name(uarmc)); err++; } else if (uarm) { if (noisy) already_wearing("some armor"); @@ -1338,7 +1406,7 @@ doputon() ublindf->otyp==LENSES ? "some lenses" : "a blindfold"); return(0); } - otmp = getobj(accessories, "wear"); + otmp = getobj(accessories, "put on"); if(!otmp) return(0); if(otmp->owornmask & (W_RING | W_AMUL | W_TOOL)) { already_wearing(c_that_); @@ -1350,6 +1418,10 @@ doputon() } if(otmp == uwep) setuwep((struct obj *)0); + if(otmp == uswapwep) + setuswapwep((struct obj *) 0); + if(otmp == uquiver) + setuqwep((struct obj *) 0); if(otmp->oclass == RING_CLASS || otmp->otyp == MEAT_RING) { if(nolimbs(youmonst.data)) { You("cannot make the ring stick to your body."); @@ -1438,7 +1510,8 @@ doputon() Blindf_on(otmp); return(1); } - prinv((char *)0, otmp, 0L); + if (is_worn(otmp)) + prinv((char *)0, otmp, 0L); return(1); } @@ -1464,6 +1537,7 @@ find_ac() if(uright && uright->otyp == RIN_PROTECTION) uac -= uright->spe; if (HProtection & INTRINSIC) uac -= u.ublessed; uac -= u.uspellprot; + if (uac < -128) uac = -128; /* u.uac is an schar */ if(uac != u.uac){ u.uac = uac; flags.botl = 1; @@ -1552,60 +1626,17 @@ struct monst *victim; return(otmph); } +/* erode some arbitrary armor worn by the victim */ void -erode_armor(victim,acid_dmg) +erode_armor(victim, acid_dmg) struct monst *victim; boolean acid_dmg; { - register struct obj *otmph = some_armor(victim); - int erosion; - boolean vismon = (victim != &youmonst) && canseemon(victim); - - if (!otmph) return; - erosion = acid_dmg ? otmph->oeroded2 : otmph->oeroded; - if (otmph != uarmf) { - if (otmph->greased) { - grease_protect(otmph,(char *)0,FALSE,victim); - return; - } - if (otmph->oerodeproof || - (acid_dmg ? !is_corrodeable(otmph) : !is_rustprone(otmph))) { - if (flags.verbose || !(otmph->oerodeproof && otmph->rknown)) { - if (victim == &youmonst) - Your("%s not affected.", aobjnam(otmph, "are")); - else if (vismon) - pline("%s's %s not affected.", Monnam(victim), - aobjnam(otmph, "are")); - } - if (otmph->oerodeproof) otmph->rknown = TRUE; - return; - } - if (erosion < MAX_ERODE) { - if (victim == &youmonst) - Your("%s%s!", aobjnam(otmph, acid_dmg ? "corrode" : "rust"), - erosion+1 == MAX_ERODE ? " completely" : - erosion ? " further" : ""); - else if (vismon) - pline("%s's %s%s!", Monnam(victim), - aobjnam(otmph, acid_dmg ? "corrode" : "rust"), - erosion+1 == MAX_ERODE ? " completely" : - erosion ? " further" : ""); - if (acid_dmg) - otmph->oeroded2++; - else - otmph->oeroded++; - return; - } - if (flags.verbose) { - if (victim == &youmonst) - Your("%s completely %s.", - aobjnam(otmph, Blind ? "feel" : "look"), - acid_dmg ? "corroded" : "rusty"); - else if (vismon) - pline("%s's %s completely %s.", Monnam(victim), - aobjnam(otmph, "look"), - acid_dmg ? "corroded" : "rusty"); - } + struct obj *otmph = some_armor(victim); + + if (otmph && (otmph != uarmf)) { + erode_obj(otmph, acid_dmg, FALSE); + if (carried(otmph)) update_inventory(); } } @@ -1614,16 +1645,21 @@ int select_off(otmp) register struct obj *otmp; { + char buf[BUFSZ]; + if(!otmp) return(0); if(cursed(otmp)) return(0); if((otmp->oclass==RING_CLASS || otmp->otyp == MEAT_RING) && nolimbs(youmonst.data)) return(0); if(welded(uwep) && (otmp==uarmg || otmp==uright || (otmp==uleft - && bimanual(uwep)))) + && bimanual(uwep)))) { + You("cannot free a weapon hand to take off the ring."); return(0); + } if(uarmg && uarmg->cursed && (otmp==uright || otmp==uleft)) { uarmg->bknown = TRUE; + You("cannot remove your gloves to take off the ring."); return(0); } if(otmp == uarmf && u.utrap && (u.utraptype == TT_BEARTRAP || @@ -1635,11 +1671,15 @@ register struct obj *otmp; || otmp==uarmu #endif ) && uarmc && uarmc->cursed) { + Strcpy(buf, the(xname(uarmc))); + You("cannot remove %s to take off %s.", buf, the(xname(otmp))); uarmc->bknown = TRUE; return(0); } #ifdef TOURIST if(otmp==uarmu && uarm && uarm->cursed) { + Strcpy(buf, the(xname(uarm))); + You("cannot remove %s to take off %s.", buf, the(xname(otmp))); uarm->bknown = TRUE; return(0); } @@ -1719,11 +1759,7 @@ do_takeoff() otmp = uright; if(!cursed(otmp)) Ring_off(uright); } else if (taking_off == WORN_BLINDF) { - if(!cursed(ublindf)) { - setworn((struct obj *)0, ublindf->owornmask); - if(!Blinded) make_blinded(1L,FALSE); /* See on next move */ - else You("still cannot see."); - } + if (!cursed(ublindf)) Blindf_off(ublindf); } else impossible("do_takeoff: taking off %lx", taking_off); return(otmp); @@ -1844,7 +1880,7 @@ doddoremarm() add_valid_menu_class(0); /* reset */ if (flags.menu_style != MENU_TRADITIONAL || - (result = ggetobj("take off", select_off, 0, FALSE)) < -1) + (result = ggetobj("take off", select_off, 0, FALSE, (unsigned *)0)) < -1) result = menu_remarm(result); if (takeoff_mask) @@ -1880,7 +1916,7 @@ int retry; free((genericptr_t) pick_list); } else if (flags.menu_style == MENU_COMBINATION) { all_worn_categories = FALSE; - if (ggetobj("take off", select_off, 0, TRUE) == -2) + if (ggetobj("take off", select_off, 0, TRUE, (unsigned *)0) == -2) all_worn_categories = TRUE; } @@ -1892,7 +1928,7 @@ int retry; for (i = 0; i < n; i++) (void) select_off(pick_list[i].item.a_obj); free((genericptr_t) pick_list); - } else if (n < 0) { + } else if (n < 0 && flags.menu_style != MENU_COMBINATION) { There("is nothing else you can remove or unwield."); } return 0; @@ -1908,7 +1944,7 @@ register struct obj *atmp; (!obj_resists(otmp, 0, 90))) if (DESTROY_ARM(uarmc)) { - Your("cloak crumbles and turns to dust!"); + Your("%s crumbles and turns to dust!", cloak_simple_name(uarmc)); (void) Cloak_off(); useup(otmp); } else if (DESTROY_ARM(uarm)) { diff --git a/src/dog.c b/src/dog.c index acdf8fd..31089d2 100644 --- a/src/dog.c +++ b/src/dog.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dog.c 3.3 1999/10/20 */ +/* SCCS Id: @(#)dog.c 3.4 2002/03/09 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -15,6 +15,7 @@ register struct monst *mtmp; { mtmp->mtame = is_domestic(mtmp->data) ? 10 : 5; mtmp->mpeaceful = 1; + mtmp->mavenge = 0; set_malign(mtmp); /* recalc alignment now that it's tamed */ mtmp->mleashed = 0; mtmp->meating = 0; @@ -90,6 +91,7 @@ boolean quietly; if (!quietly) You("get a bad feeling about this."); mtmp->mpeaceful = 0; + set_malign(mtmp); } } /* if figurine has been named, give same name to the monster */ @@ -118,6 +120,8 @@ makedog() int pettype; static int petname_used = 0; + if (preferred_pet == 'n') return((struct monst *) 0); + pettype = pet_type(); if (pettype == PM_LITTLE_DOG) petname = dogname; @@ -410,6 +414,13 @@ long nmv; /* number of moves */ mtmp->mtame = mtmp->mpeaceful = 0; } + if (!mtmp->mtame && mtmp->mleashed) { + /* leashed monsters should always be with hero, consequently + never losing any time to be accounted for later */ + impossible("catching up for leashed monster?"); + m_unleash(mtmp, FALSE); + } + /* recover lost hit points */ if (!regenerates(mtmp->data)) imv /= 20; if (mtmp->mhp + imv >= mtmp->mhpmax) @@ -442,7 +453,9 @@ boolean pets_only; /* true for ascension or final escape */ the amulet; if you don't have it, will chase you only if in range. -3. */ (u.uhave.amulet && mtmp->iswiz)) - && !mtmp->msleeping && mtmp->mcanmove) { + && !mtmp->msleeping && mtmp->mcanmove + /* monster won't follow if it hasn't noticed you yet */ + && !(mtmp->mstrategy & STRAT_WAITFORU)) { stay_behind = FALSE; if (mtmp->mtame && mtmp->meating) { if (canseemon(mtmp)) @@ -453,18 +466,21 @@ boolean pets_only; /* true for ascension or final escape */ pline("%s seems very disoriented for a moment.", Monnam(mtmp)); stay_behind = TRUE; + } else if (mtmp->mtame && mtmp->mtrapped) { + if (canseemon(mtmp)) + pline("%s is still trapped.", Monnam(mtmp)); + stay_behind = TRUE; } - if (stay_behind #ifdef STEED - && mtmp != u.usteed + if (mtmp == u.usteed) stay_behind = FALSE; #endif - ) { + if (stay_behind) { if (mtmp->mleashed) { pline("%s leash suddenly comes loose.", humanoid(mtmp->data) ? (mtmp->female ? "Her" : "His") : "Its"); - m_unleash(mtmp); + m_unleash(mtmp, FALSE); } continue; } @@ -503,7 +519,7 @@ boolean pets_only; /* true for ascension or final escape */ /* this can happen if your quest leader ejects you from the "home" level while a leashed pet isn't next to you */ pline("%s leash goes slack.", s_suffix(Monnam(mtmp))); - m_unleash(mtmp); + m_unleash(mtmp, FALSE); } } } @@ -541,14 +557,13 @@ migrate_to_level(mtmp, tolev, xyloc, cc) obj->no_charge = 0; } + if (mtmp->mleashed) { + mtmp->mtame--; + m_unleash(mtmp, TRUE); + } relmon(mtmp); mtmp->nmon = migrating_mons; migrating_mons = mtmp; - if (mtmp->mleashed) { - m_unleash(mtmp); - mtmp->mtame--; - pline_The("leash comes off!"); - } newsym(mtmp->mx,mtmp->my); new_lev.dnum = ledger_to_dnum((xchar)tolev); @@ -648,10 +663,11 @@ register struct obj *obj; return(TABU); if (mon->data == &mons[PM_GELATINOUS_CUBE] && is_organic(obj)) return(ACCFOOD); - if (metallivorous(mon->data) && is_metallic(obj)) + if (metallivorous(mon->data) && is_metallic(obj) && (is_rustprone(obj) || mon->data != &mons[PM_RUST_MONSTER])) { /* Non-rustproofed ferrous based metals are preferred. */ - return(objects[obj->otyp].oc_material == IRON && - !obj->oerodeproof ? DOGFOOD : ACCFOOD); + return((is_rustprone(obj) && !obj->oerodeproof) ? DOGFOOD : + ACCFOOD); + } if(!obj->cursed && obj->oclass != BALL_CLASS && obj->oclass != CHAIN_CLASS) return(APPORT); @@ -711,7 +727,7 @@ register struct obj *obj; Monnam(mtmp), the(xname(obj)), !big_corpse ? "." : ", or vice versa!"); } else if (cansee(mtmp->mx,mtmp->my)) - pline("%s stops.", The(xname(obj))); + pline("%s.", Tobjnam(obj, "stop")); /* dog_eat expects a floor object */ place_object(obj, mtmp->mx, mtmp->my); (void) dog_eat(mtmp, obj, mtmp->mx, mtmp->my, FALSE); @@ -730,6 +746,9 @@ register struct obj *obj; (is_demon(mtmp->data) && !is_demon(youmonst.data)) || (obj && dogfood(mtmp, obj) >= MANFOOD)) return (struct monst *)0; + if (mtmp->m_id == quest_status.leader_m_id) + return((struct monst *)0); + /* make a new monster which has the pet extension */ mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth); *mtmp2 = *mtmp; @@ -796,6 +815,13 @@ boolean quietly; mtmp->mpeaceful = mtmp->mtame = 0; } } + if (!mtmp->mtame) { + newsym(mtmp->mx, mtmp->my); + /* a life-saved monster might be leashed; + don't leave it that way if it's no longer tame */ + if (mtmp->mleashed) m_unleash(mtmp, TRUE); + } + /* if its still a pet, start a clean pet-slate now */ if (has_edog && mtmp->mtame) { EDOG(mtmp)->revivals++; @@ -814,12 +840,19 @@ struct monst *mtmp; else mtmp->mtame--; if (mtmp->mtame && !mtmp->isminion) - EDOG(mtmp)->abuse++; + EDOG(mtmp)->abuse++; - if (mtmp->mtame && rn2(mtmp->mtame)) yelp(mtmp); - else growl(mtmp); /* give them a moment's worry */ + if (!mtmp->mtame && mtmp->mleashed) + m_unleash(mtmp, TRUE); + + /* don't make a sound if pet is in the middle of leaving the level */ + /* newsym isn't necessary in this case either */ + if (mtmp->mx != 0) { + if (mtmp->mtame && rn2(mtmp->mtame)) yelp(mtmp); + else growl(mtmp); /* give them a moment's worry */ - if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my); + if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my); + } } #endif /* OVLB */ diff --git a/src/dogmove.c b/src/dogmove.c index 6a1d4a5..fcfeb68 100644 --- a/src/dogmove.c +++ b/src/dogmove.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dogmove.c 3.3 97/05/25 */ +/* SCCS Id: @(#)dogmove.c 3.4 2002/03/09 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -16,6 +16,8 @@ STATIC_DCL int FDECL(dog_invent,(struct monst *,struct edog *,int)); STATIC_DCL int FDECL(dog_goal,(struct monst *,struct edog *,int,int,int)); STATIC_DCL struct obj *FDECL(DROPPABLES, (struct monst *)); +STATIC_DCL boolean FDECL(can_reach_food,(struct monst *,XCHAR_P,XCHAR_P,XCHAR_P, + XCHAR_P)); STATIC_OVL struct obj * DROPPABLES(mon) @@ -156,7 +158,7 @@ boolean devour; } else /* hack: observe the action if either new or old location is in view */ if (cansee(x, y) || cansee(mtmp->mx, mtmp->my)) - pline("%s %s %s.", Monnam(mtmp), + pline("%s %s %s.", noit_Monnam(mtmp), devour ? "devours" : "eats", (obj->oclass == FOOD_CLASS) ? singular(obj, doname) : doname(obj)); @@ -182,9 +184,10 @@ boolean devour; delobj(obj); } else if (obj == uchain) unpunish(); - else if (obj->quan > 1L && obj->oclass == FOOD_CLASS) + else if (obj->quan > 1L && obj->oclass == FOOD_CLASS) { obj->quan--; - else + obj->owt = weight(obj); + } else delobj(obj); if (poly) { @@ -198,7 +201,7 @@ boolean devour; #ifdef STEED mtmp->misc_worn_check = mw; #endif - if (newcham(mtmp, (struct permonst *)0) && + if (newcham(mtmp, (struct permonst *)0, FALSE) && cansee(mtmp->mx, mtmp->my)) { uchar save_mnamelth = mtmp->mnamelth; mtmp->mnamelth = 0; @@ -242,6 +245,7 @@ register struct edog *edog; beg(mtmp); else You_feel("worried about %s.", y_monnam(mtmp)); + stop_occupation(); } else if (monstermoves > edog->hungrytime + 750 || mtmp->mhp < 1) { dog_died: if (mtmp->mleashed) @@ -279,7 +283,11 @@ int udist; /* if we are carrying sth then we drop it (perhaps near @) */ /* Note: if apport == 1 then our behaviour is independent of udist */ /* Use udist+1 so steed won't cause divide by zero */ +#ifndef GOLDOBJ if(DROPPABLES(mtmp) || mtmp->mgold) { +#else + if(DROPPABLES(mtmp)) { +#endif if (!rn2(udist+1) || !rn2(edog->apport)) if(rn2(10) < edog->apport){ relobj(mtmp, (int)mtmp->minvis, TRUE); @@ -375,7 +383,8 @@ int after, udist, whappr; continue; if (cursed_object_at(nx, ny)) continue; - if (otyp < MANFOOD) { + if (otyp < MANFOOD && + can_reach_food(mtmp, mtmp->mx, mtmp->my, nx, ny)) { if (otyp < gtyp || DDIST(nx,ny) < DDIST(gx,gy)) { gx = nx; gy = ny; @@ -556,6 +565,11 @@ register int after; /* this is extra fast monster movement */ } } + if (!Conflict && !mtmp->mconf && + mtmp == u.ustuck && !sticks(youmonst.data)) { + unstuck(mtmp); /* swallowed case handled above */ + You("get released!"); + } if (!nohands(mtmp->data) && !verysmall(mtmp->data)) { allowflags |= OPENDOOR; if (m_carrying(mtmp, SKELETON_KEY)) allowflags |= BUSTDOOR; @@ -702,8 +716,8 @@ register int after; /* this is extra fast monster movement */ if (info[chi] & ALLOW_U) { if (mtmp->mleashed) { /* play it safe */ pline("%s breaks loose of %s leash!", - Monnam(mtmp), his[pronoun_gender(mtmp)]); - m_unleash(mtmp); + Monnam(mtmp), mhis(mtmp)); + m_unleash(mtmp, FALSE); } (void) mattacku(mtmp); return(0); @@ -767,6 +781,50 @@ register int after; /* this is extra fast monster movement */ return(1); } +/* Hack to prevent a dog from being endlessly stuck near a piece of food that + * it can't reach, such as caught in a teleport scroll niche. It recursively + * checks to see if the squares inbetween are good. The checking could be a + * little smarter; a full check would probably be useful in m_move() too. + * Since the maximum food distance is 5, this should never be more than 5 calls + * deep. + */ +STATIC_OVL boolean +can_reach_food(mon, mx, my, fx, fy) +struct monst *mon; +xchar mx, my, fx, fy; +{ + int i, j; + int dist; + + if (mx == fx && my == fy) return TRUE; + if (!isok(mx, my)) return FALSE; /* should not happen */ + + dist = dist2(mx, my, fx, fy); + for(i=mx-1; i<=mx+1; i++) { + for(j=my-1; j<=my+1; j++) { + if (!isok(i, j)) + continue; + if (dist2(i, j, fx, fy) >= dist) + continue; + if (IS_ROCK(levl[i][j].typ) && !passes_walls(mon->data) && + (!may_dig(i,j) || !tunnels(mon->data))) + continue; + if (IS_DOOR(levl[i][j].typ) && + (levl[i][j].doormask & (D_CLOSED | D_LOCKED))) + continue; + if (is_pool(i, j) && !is_swimmer(mon->data)) + continue; + if (is_lava(i, j) && !likes_lava(mon->data)) + continue; + if (sobj_at(BOULDER,i,j) && !throws_rocks(mon->data)) + continue; + if (can_reach_food(mon, i, j, fx, fy)) + return TRUE; + } + } + return FALSE; +} + #endif /* OVL0 */ #ifdef OVLB diff --git a/src/dokick.c b/src/dokick.c index 8be5880..b5b9032 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dokick.c 3.3 2000/04/21 */ +/* SCCS Id: @(#)dokick.c 3.4 2000/04/21 */ /* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -23,8 +23,6 @@ STATIC_DCL void FDECL(drop_to, (coord *,SCHAR_P)); static NEARDATA struct obj *kickobj; -#define IS_SHOP(x) (rooms[x].rtype >= SHOPBASE) - static const char kick_passes_thru[] = "kick passes harmlessly through"; STATIC_OVL void @@ -66,7 +64,8 @@ register boolean clumsy; /* it is unchivalrous to attack the defenseless or from behind */ if (Role_if(PM_KNIGHT) && u.ualign.type == A_LAWFUL && u.ualign.record > -10 && - (!mon->mcanmove || mon->msleeping || mon->mflee)) { + (!mon->mcanmove || mon->msleeping || + (mon->mflee && !mon->mavenge))) { You_feel("like a caitiff!"); adjalign(-1); } @@ -74,12 +73,10 @@ register boolean clumsy; /* squeeze some guilt feelings... */ if(mon->mtame) { abuse_dog(mon); - mon->mflee = mon->mtame ? 1 : 0; -#ifdef HISX - mon->mfleetim = mon->mfleetim + (dmg ? rnd(dmg) : 1); -#else - mon->mfleetim += (dmg ? rnd(dmg) : 1); -#endif + if (mon->mtame) + monflee(mon, (dmg ? rnd(dmg) : 1), FALSE, FALSE); + else + mon->mflee = 0; } if (dmg > 0) { @@ -97,19 +94,20 @@ register boolean clumsy; dmg += u.udaminc; /* add ring(s) of increase damage */ if (dmg > 0) mon->mhp -= dmg; - if(mon->mhp > 0 && martial() && !bigmonst(mon->data) && !rn2(3) - && mon->mcanmove && mon != u.ustuck) { + if (mon->mhp > 0 && martial() && !bigmonst(mon->data) && !rn2(3) && + mon->mcanmove && mon != u.ustuck && !mon->mtrapped) { /* see if the monster has a place to move into */ mdx = mon->mx + u.dx; mdy = mon->my + u.dy; if(goodpos(mdx, mdy, mon)) { pline("%s reels from the blow.", Monnam(mon)); - if (!m_in_out_region(mon, mdx, mdy)) { + if (m_in_out_region(mon, mdx, mdy)) { remove_monster(mon->mx, mon->my); newsym(mon->mx, mon->my); place_monster(mon, mdx, mdy); newsym(mon->mx, mon->my); set_apparxy(mon); + (void) mintrap(mon); } } } @@ -165,6 +163,8 @@ register xchar x, y; You("kick %s.", mon_nam(mon)); sum = damageum(mon, uattk); (void)passive(mon, (boolean)(sum > 0), (sum != 2), AT_KICK); + if (sum == 2) + break; /* Defender died */ } else { missum(mon, uattk); (void)passive(mon, 0, 1, AT_KICK); @@ -217,7 +217,7 @@ register xchar x, y; pline("%s %s, %s evading your %skick.", Monnam(mon), (can_teleport(mon->data) ? "teleports" : is_floater(mon->data) ? "floats" : - is_flyer(mon->data) ? "flutters" : + is_flyer(mon->data) ? "swoops" : (nolimbs(mon->data) || slithy(mon->data)) ? "slides" : "jumps"), clumsy ? "easily" : "nimbly", @@ -247,6 +247,9 @@ register struct obj *gold; if (canseemon(mtmp)) pline_The("gold hits %s.", mon_nam(mtmp)); } else { +#ifdef GOLDOBJ + long value = gold->quan * objects[gold->otyp].oc_cost; +#endif mtmp->msleeping = 0; mtmp->meating = 0; if(!rn2(4)) setmangry(mtmp); /* not always pleasing */ @@ -254,25 +257,35 @@ register struct obj *gold; /* greedy monsters catch gold */ if (cansee(mtmp->mx, mtmp->my)) pline("%s catches the gold.", Monnam(mtmp)); +#ifndef GOLDOBJ mtmp->mgold += gold->quan; +#endif if (mtmp->isshk) { long robbed = ESHK(mtmp)->robbed; if (robbed) { +#ifndef GOLDOBJ robbed -= gold->quan; +#else + robbed -= value; +#endif if (robbed < 0) robbed = 0; pline_The("amount %scovers %s recent losses.", !robbed ? "" : "partially ", - his[mtmp->female]); + mhis(mtmp)); ESHK(mtmp)->robbed = robbed; if(!robbed) make_happy_shk(mtmp, FALSE); } else { if(mtmp->mpeaceful) { +#ifndef GOLDOBJ ESHK(mtmp)->credit += gold->quan; - You("have %ld zorkmid%s in credit.", +#else + ESHK(mtmp)->credit += value; +#endif + You("have %ld %s in credit.", ESHK(mtmp)->credit, - plur(ESHK(mtmp)->credit)); + currency(ESHK(mtmp)->credit)); } else verbalize("Thanks, scum!"); } } else if (mtmp->ispriest) { @@ -293,8 +306,13 @@ register struct obj *gold; goldreqd = 750L; if (goldreqd) { +#ifndef GOLDOBJ if (gold->quan > goldreqd + (u.ugold + u.ulevel*rn2(5))/ACURR(A_CHA)) +#else + if (value > goldreqd + + (money_cnt(invent) + u.ulevel*rn2(5))/ACURR(A_CHA)) +#endif mtmp->mpeaceful = TRUE; } } @@ -303,7 +321,11 @@ register struct obj *gold; else verbalize("That's not enough, coward!"); } +#ifndef GOLDOBJ dealloc_obj(gold); +#else + add_to_minv(mtmp, gold); +#endif return(1); } return(0); @@ -346,16 +368,16 @@ xchar x, y; if(kickobj->otyp == CORPSE && touch_petrifies(&mons[kickobj->corpsenm]) && !Stone_resistance && !uarmf) { - char kbuf[BUFSZ]; + char kbuf[BUFSZ]; - You("kick the %s corpse with your bare %s.", - mons[kickobj->corpsenm].mname, makeplural(body_part(FOOT))); + You("kick the %s with your bare %s.", + corpse_xname(kickobj, TRUE), makeplural(body_part(FOOT))); if (!(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) { You("turn to stone..."); killer_format = KILLED_BY; /* KMH -- otmp should be kickobj */ - Sprintf(kbuf, "kicking a %s corpse without boots", - mons[kickobj->corpsenm].mname); + Sprintf(kbuf, "kicking %s without boots", + an(corpse_xname(kickobj, TRUE))); killer = kbuf; done(STONING); } @@ -407,6 +429,13 @@ xchar x, y; result = "cracking"; } if (result) { + if (otmp->otyp == MIRROR) + change_luck(-2); + /* eggs laid by you */ + /* penalty is -1 per egg, max 5, but it's always + exactly 1 that breaks */ + if (otmp->otyp == EGG && otmp->spe && otmp->corpsenm >= LOW_PM) + change_luck(-1); You_hear("a muffled %s.",result); if(costly) loss += stolen_value(otmp, x, y, (boolean)shkp->mpeaceful, TRUE); @@ -420,11 +449,12 @@ xchar x, y; } if(costly && loss) { if(!insider) { - You("caused %ld zorkmids worth of damage!", loss); + You("caused %ld %s worth of damage!", + loss, currency(loss)); make_angry_shk(shkp, x, y); } else { - You("owe %s %ld zorkmids for objects destroyed.", - mon_nam(shkp), loss); + You("owe %s %ld %s for objects destroyed.", + mon_nam(shkp), loss, currency(loss)); } } @@ -455,15 +485,15 @@ xchar x, y; || IS_ROCK(levl[u.ux][u.uy].typ) || closed_door(u.ux, u.uy)) { if (Blind) pline("It doesn't come loose."); - else pline("%s do%sn't come loose.", + else pline("%s %sn't come loose.", The(distant_name(kickobj, xname)), - (kickobj->quan == 1L) ? "es" : ""); + otense(kickobj, "do")); return(!rn2(3) || martial()); } if (Blind) pline("It comes loose."); - else pline("%s come%s loose.", + else pline("%s %s loose.", The(distant_name(kickobj, xname)), - (kickobj->quan == 1L) ? "s" : ""); + otense(kickobj, "come")); obj_extract_self(kickobj); newsym(x, y); if (costly && (!costly_spot(u.ux, u.uy) @@ -488,12 +518,11 @@ xchar x, y; return(!rn2(3) || martial()); } - if (kickobj->quan > 1L && !isgold) (void) splitobj(kickobj, 1L); + if (kickobj->quan > 1L && !isgold) kickobj = splitobj(kickobj, 1L); if (slide && !Blind) - pline("Whee! %s slide%s across the %s.", Doname2(kickobj), - kickobj->quan > 1L ? "" : "s", - surface(x,y)); + pline("Whee! %s %s across the %s.", Doname2(kickobj), + otense(kickobj, "slide"), surface(x,y)); obj_extract_self(kickobj); (void) snuff_candle(kickobj); @@ -541,12 +570,12 @@ char *buf; if (kickobj) what = distant_name(kickobj,doname); else if (IS_DOOR(maploc->typ)) what = "a door"; + else if (IS_TREE(maploc->typ)) what = "a tree"; else if (IS_STWALL(maploc->typ)) what = "a wall"; else if (IS_ROCK(maploc->typ)) what = "a rock"; else if (IS_THRONE(maploc->typ)) what = "a throne"; else if (IS_FOUNTAIN(maploc->typ)) what = "a fountain"; else if (IS_GRAVE(maploc->typ)) what = "a headstone"; - else if (IS_TREE(maploc->typ)) what = "a tree"; #ifdef SINKS else if (IS_SINK(maploc->typ)) what = "a sink"; #endif @@ -830,10 +859,10 @@ dokick() if (!rn2(2) && !(maploc->looted & TREE_LOOTED) && (treefruit = rnd_treefruit_at(x, y))) { treefruit->quan = (long)(8 - rnl(8)); - if (treefruit->quan > 1L) - pline("Some %s fall from the tree!", xname(treefruit)); + if (is_plural(treefruit)) + pline("Some %s fall from the tree!", xname(treefruit)); else - pline("%s falls from the tree!", An(xname(treefruit))); + pline("%s falls from the tree!", An(xname(treefruit))); scatter(x,y,2,MAY_HIT,treefruit); exercise(A_DEX, TRUE); exercise(A_WIS, TRUE); /* discovered a new food source! */ @@ -844,7 +873,7 @@ dokick() int cnt = rnl(5); coord mm; mm.x = x; mm.y = y; - pline("You've disturbed the occupants!"); + pline("You've attracted the tree's former occupants!"); while (cnt--) if (enexto(&mm, mm.x, mm.y, &mons[PM_KILLER_BEE])) (void) makemon(&mons[PM_KILLER_BEE], @@ -991,7 +1020,10 @@ dokick() mtmp->data == &mons[PM_WATCH_CAPTAIN]) && couldsee(mtmp->mx, mtmp->my) && mtmp->mpeaceful) { - pline("%s yells:", Amonnam(mtmp)); + if (canspotmon(mtmp)) + pline("%s yells:", Amonnam(mtmp)); + else + You_hear("someone yell:"); verbalize("Halt, thief! You're under arrest!"); (void) angry_guards(FALSE); break; @@ -1007,7 +1039,10 @@ dokick() if ((mtmp->data == &mons[PM_WATCHMAN] || mtmp->data == &mons[PM_WATCH_CAPTAIN]) && mtmp->mpeaceful && couldsee(mtmp->mx, mtmp->my)) { - pline("%s yells:", Amonnam(mtmp)); + if (canspotmon(mtmp)) + pline("%s yells:", Amonnam(mtmp)); + else + You_hear("someone yell:"); if(levl[x][y].looted & D_WARNED) { verbalize("Halt, vandal! You're under arrest!"); (void) angry_guards(FALSE); @@ -1150,7 +1185,7 @@ xchar x, y, dlev; if(costly && shkp && price) { if(ESHK(shkp)->robbed > robbed) { - You("removed %ld zorkmids worth of goods!", price); + You("removed %ld %s worth of goods!", price, currency(price)); if(cansee(shkp->mx, shkp->my)) { if(ESHK(shkp)->customer[0] == 0) (void) strncpy(ESHK(shkp)->customer, @@ -1163,10 +1198,12 @@ xchar x, y, dlev; (void) angry_guards(FALSE); return; } - if(ESHK(shkp)->debit > debit) - You("owe %s %ld zorkmids for goods lost.", + if(ESHK(shkp)->debit > debit) { + long amt = (ESHK(shkp)->debit - debit); + You("owe %s %ld %s for goods lost.", Monnam(shkp), - (ESHK(shkp)->debit - debit)); + amt, currency(amt)); + } } } @@ -1243,6 +1280,33 @@ boolean shop_floor_obj; otmp->no_charge = 0; } + if (otmp == uwep) setuwep((struct obj *)0); + if (otmp == uquiver) setuqwep((struct obj *)0); + if (otmp == uswapwep) setuswapwep((struct obj *)0); + + /* some things break rather than ship */ + if (breaktest(otmp)) { + char *result; + if (objects[otmp->otyp].oc_material == GLASS +#ifdef TOURIST + || otmp->otyp == EXPENSIVE_CAMERA +#endif + ) { + if (otmp->otyp == MIRROR) + change_luck(-2); + result = "crash"; + } else { + /* penalty for breaking eggs laid by you */ + if (otmp->otyp == EGG && otmp->spe && otmp->corpsenm >= LOW_PM) + change_luck((schar) -min(otmp->quan, 5L)); + result = "splat"; + } + You_hear("a muffled %s.",result); + obj_extract_self(otmp); + obfree(otmp, (struct obj *) 0); + return TRUE; + } + add_to_migration(otmp); otmp->ox = cc.x; otmp->oy = cc.y; @@ -1319,19 +1383,18 @@ long num; xname(otmp)); if(num) { /* means: other objects are impacted */ - Sprintf(eos(obuf), " hit%s %s object%s", - otmp->quan == 1L ? "s" : "", - num == 1L ? "another" : "other", - num > 1L ? "s" : ""); + Sprintf(eos(obuf), " %s %s object%s", + otense(otmp, "hit"), + num == 1L ? "another" : "other", + num > 1L ? "s" : ""); if(nodrop) Sprintf(eos(obuf), "."); else - Sprintf(eos(obuf), " and fall%s %s.", - otmp->quan == 1L ? "s" : "", gate_str); + Sprintf(eos(obuf), " and %s %s.", + otense(otmp, "fall"), gate_str); pline("%s", obuf); } else if(!nodrop) - pline("%s fall%s %s.", obuf, - otmp->quan == 1L ? "s" : "", gate_str); + pline("%s %s %s.", obuf, otense(otmp, "fall"), gate_str); } /* migration destination for objects which fall down to next level */ diff --git a/src/dothrow.c b/src/dothrow.c index 2bad10a..675182f 100644 --- a/src/dothrow.c +++ b/src/dothrow.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dothrow.c 3.3 2000/04/16 */ +/* SCCS Id: @(#)dothrow.c 3.4 2002/02/21 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -9,6 +9,7 @@ STATIC_DCL int FDECL(throw_obj, (struct obj *,int)); STATIC_DCL void NDECL(autoquiver); STATIC_DCL int FDECL(gem_accept, (struct monst *, struct obj *)); +STATIC_DCL void FDECL(tmiss, (struct obj *, struct monst *)); STATIC_DCL int FDECL(throw_gold, (struct obj *)); STATIC_DCL void FDECL(check_shop_obj, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P)); STATIC_DCL void FDECL(breakobj, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P,BOOLEAN_P)); @@ -16,6 +17,7 @@ STATIC_DCL void FDECL(breakmsg, (struct obj *,BOOLEAN_P)); STATIC_DCL boolean FDECL(toss_up,(struct obj *, BOOLEAN_P)); STATIC_DCL boolean FDECL(throwing_weapon, (struct obj *)); STATIC_DCL void FDECL(sho_obj_return_to_u, (struct obj *obj)); +STATIC_DCL boolean FDECL(mhurtle_step, (genericptr_t,int,int)); static NEARDATA const char toss_objs[] = @@ -37,8 +39,10 @@ int shotlimit; int multishot = 1; schar skill; long wep_mask; + boolean twoweap; /* ask "in what direction?" */ +#ifndef GOLDOBJ if (!getdir((char *)0)) { if (obj->oclass == GOLD_CLASS) { u.ugold += obj->quan; @@ -49,6 +53,24 @@ int shotlimit; } if(obj->oclass == GOLD_CLASS) return(throw_gold(obj)); +#else + if (!getdir((char *)0)) { + /* obj might need to be merged back into the singular gold object */ + freeinv(obj); + addinv(obj); + return(0); + } + + /* + Throwing money is usually for getting rid of it when + a leprechaun approaches, or for bribing an oncoming + angry monster. So throw the whole object. + + If the money is in quiver, throw one coin at a time, + possibly using a sling. + */ + if(obj->oclass == GOLD_CLASS && obj != uquiver) return(throw_gold(obj)); +#endif if(!canletgo(obj,"throw")) return(0); @@ -66,6 +88,7 @@ int shotlimit; You("cannot throw an object at yourself."); return(0); } + u_wipe_engr(2); if (!uarmg && !Stone_resistance && (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm]))) { You("throw the %s corpse with your bare %s.", @@ -73,7 +96,10 @@ int shotlimit; Sprintf(killer_buf, "%s corpse", an(mons[obj->corpsenm].mname)); instapetrify(killer_buf); } - u_wipe_engr(2); + if (welded(obj)) { + weldmsg(obj); + return 1; + } /* Multishot calculations */ @@ -116,43 +142,42 @@ int shotlimit; } } - if (obj->quan < multishot) multishot = (int)obj->quan; + if ((long)multishot > obj->quan) multishot = (int)obj->quan; multishot = rnd(multishot); if (shotlimit > 0 && multishot > shotlimit) multishot = shotlimit; - while (obj && multishot-- > 0) { - wep_mask = obj->owornmask; - /* Split this object off from its slot */ - otmp = (struct obj *)0; - if (obj == uquiver) { - if(obj->quan > 1L) - setuqwep(otmp = splitobj(obj, 1L)); - else - setuqwep((struct obj *)0); - } else if (obj == uswapwep) { - if(obj->quan > 1L) - setuswapwep(otmp = splitobj(obj, 1L)); - else - setuswapwep((struct obj *)0); - } else if (obj == uwep) { - if (welded(obj)) { - weldmsg(obj); - return(1); - } - if (obj->quan > 1L) - setworn(otmp = splitobj(obj, 1L), W_WEP); - /* not setuwep; do not change unweapon */ - else { - setuwep((struct obj *)0); - if (uwep) return(1); /* unwielded, died, rewielded */ - } - } else if(obj->quan > 1L) - otmp = splitobj(obj, 1L); - freeinv(obj); - throwit(obj, wep_mask); - obj = otmp; - } /* while (multishot) */ - return(1); + m_shot.s = ammo_and_launcher(obj,uwep) ? TRUE : FALSE; + /* give a message if shooting more than one, or if player + attempted to specify a count */ + if (multishot > 1 || shotlimit > 0) { + /* "You shoot N arrows." or "You throw N daggers." */ + You("%s %d %s.", + m_shot.s ? "shoot" : "throw", + multishot, /* (might be 1 if player gave shotlimit) */ + (multishot == 1) ? singular(obj, xname) : xname(obj)); + } + + wep_mask = obj->owornmask; + m_shot.o = obj->otyp; + m_shot.n = multishot; + for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++) { + twoweap = u.twoweap; + /* split this object off from its slot if necessary */ + if (obj->quan > 1L) { + otmp = splitobj(obj, 1L); + } else { + otmp = obj; + if (otmp->owornmask && otmp != uball) + remove_worn_item(otmp); + } + freeinv(otmp); + throwit(otmp, wep_mask, twoweap); + } + m_shot.n = m_shot.i = 0; + m_shot.o = STRANGE_OBJECT; + m_shot.s = FALSE; + + return 1; } @@ -193,49 +218,53 @@ autoquiver() register struct obj *otmp, *oammo = 0, *omissile = 0, *omisc = 0; if (uquiver) - return; + return; /* Scan through the inventory */ for (otmp = invent; otmp; otmp = otmp->nobj) { - if (otmp->owornmask || otmp->oartifact || !otmp->dknown) { - ; /* Skip it */ - } else if (otmp->otyp == ROCK || + if (otmp->owornmask || otmp->oartifact || !otmp->dknown) { + ; /* Skip it */ + } else if (otmp->otyp == ROCK || /* seen rocks or known flint or known glass */ (objects[otmp->otyp].oc_name_known && otmp->otyp == FLINT) || (objects[otmp->otyp].oc_name_known && otmp->oclass == GEM_CLASS && objects[otmp->otyp].oc_material == GLASS)) { - if (uslinging()) - oammo = otmp; - else if (!omisc) - omisc = otmp; - } else if (otmp->oclass == GEM_CLASS) { - ; /* skip non-rock gems--they're ammo but - player has to select them explicitly */ - } else if (is_ammo(otmp)) { - if (ammo_and_launcher(otmp, uwep)) - /* Ammo matched with launcher (bow and arrow, crossbow and bolt) */ - oammo = otmp; - else - /* Mismatched ammo (no better than an ordinary weapon) */ - omisc = otmp; - } else if (is_missile(otmp)) { - /* Missile (dart, shuriken, etc.) */ - omissile = otmp; - } else if (otmp->oclass == WEAPON_CLASS && !is_launcher(otmp)) { - /* Ordinary weapon */ - omisc = otmp; - } + if (uslinging()) + oammo = otmp; + else if (!omisc) + omisc = otmp; + } else if (otmp->oclass == GEM_CLASS) { + ; /* skip non-rock gems--they're ammo but + player has to select them explicitly */ + } else if (is_ammo(otmp)) { + if (ammo_and_launcher(otmp, uwep)) + /* Ammo matched with launcher (bow and arrow, crossbow and bolt) */ + oammo = otmp; + else + /* Mismatched ammo (no better than an ordinary weapon) */ + omisc = otmp; + } else if (is_missile(otmp)) { + /* Missile (dart, shuriken, etc.) */ + omissile = otmp; + } else if (otmp->oclass == WEAPON_CLASS && throwing_weapon(otmp)) { + /* Ordinary weapon */ + if (objects[otmp->otyp].oc_skill == P_DAGGER + && !omissile) + omissile = otmp; + else + omisc = otmp; + } } /* Pick the best choice */ if (oammo) - setuqwep(oammo); + setuqwep(oammo); else if (omissile) - setuqwep(omissile); + setuqwep(omissile); else if (omisc) - setuqwep(omisc); + setuqwep(omisc); return; } @@ -380,7 +409,7 @@ walk_path(src_cc, dest_cc, check_proc, arg) * Single step for the hero flying through the air from jumping, flying, * etc. Called from hurtle() and jump() via walk_path(). We expect the * argument to be a pointer to an integer -- the range -- which is - * used in the calculation of points off it we hit something. + * used in the calculation of points off if we hit something. * * Bumping into monsters won't cause damage but will wake them and make * them angry. Auto-pickup isn't done, since you don't have control over @@ -403,7 +432,8 @@ hurtle_step(arg, x, y) struct obj *obj; struct monst *mon; boolean may_pass = TRUE; - + struct trap *ttmp; + if (!isok(x,y)) { You_feel("the spirits holding you back."); return FALSE; @@ -411,9 +441,16 @@ hurtle_step(arg, x, y) if (!Passes_walls || !(may_pass = may_passwall(x, y))) { if (IS_ROCK(levl[x][y].typ) || closed_door(x,y)) { + char *s; + pline("Ouch!"); - losehp(rnd(2+*range), IS_ROCK(levl[x][y].typ) ? - "bumping into a wall" : "bumping into a door", KILLED_BY); + if (IS_TREE(levl[x][y].typ)) + s = "bumping into a tree"; + else if (IS_ROCK(levl[x][y].typ)) + s = "bumping into a wall"; + else + s = "bumping into a door"; + losehp(rnd(2+*range), s, KILLED_BY); return FALSE; } if (levl[x][y].typ == IRONBARS) { @@ -439,6 +476,14 @@ hurtle_step(arg, x, y) wakeup(mon); return FALSE; } + if ((u.ux - x) && (u.uy - y) && + bad_rock(youmonst.data,u.ux,y) && bad_rock(youmonst.data,x,u.uy)) { + /* Move at a diagonal. */ + if (In_sokoban(&u.uz)) { + You("come to an abrupt halt!"); + return FALSE; + } + } ox = u.ux; oy = u.uy; @@ -447,6 +492,33 @@ hurtle_step(arg, x, y) newsym(ox, oy); /* update old position */ vision_recalc(1); /* update for new position */ flush_screen(1); + /* FIXME: + * Each trap should really trigger on the recoil if + * it would trigger during normal movement. However, + * not all the possible side-effects of this are + * tested [as of 3.4.0] so we trigger those that + * we have tested, and offer a message for the + * ones that we have not yet tested. + */ + if ((ttmp = t_at(x, y)) != 0) { + if (ttmp->ttyp == MAGIC_PORTAL) { + dotrap(ttmp,0); + return FALSE; + } else if (ttmp->ttyp == FIRE_TRAP) { + dotrap(ttmp,0); + } else if ((ttmp->ttyp == PIT || ttmp->ttyp == SPIKED_PIT || + ttmp->ttyp == HOLE || ttmp->ttyp == TRAPDOOR) && + In_sokoban(&u.uz)) { + /* Air currents overcome the recoil */ + dotrap(ttmp,0); + return FALSE; + } else { + if (ttmp->tseen) + You("pass right over %s %s.", + (ttmp->ttyp == ARROW_TRAP) ? "an" : "a", + defsyms[trap_to_defsym(ttmp->ttyp)].explanation); + } + } if (--*range < 0) /* make sure our range never goes negative */ *range = 0; if (*range != 0) @@ -454,6 +526,28 @@ hurtle_step(arg, x, y) return TRUE; } +STATIC_OVL boolean +mhurtle_step(arg, x, y) + genericptr_t arg; + int x, y; +{ + struct monst *mon = (struct monst *)arg; + + /* TODO: Treat walls, doors, iron bars, pools, lava, etc. specially + * rather than just stopping before. + */ + if (goodpos(x, y, mon) && m_in_out_region(mon, x, y)) { + remove_monster(mon->mx, mon->my); + newsym(mon->mx, mon->my); + place_monster(mon, x, y); + newsym(mon->mx, mon->my); + set_apparxy(mon); + (void) mintrap(mon); + return TRUE; + } + return FALSE; +} + /* * The player moves through the air for a few squares as a result of * throwing or kicking something. @@ -497,6 +591,13 @@ hurtle(dx, dy, range, verbose) nomul(-range); if (verbose) You("%s in the opposite direction.", range > 1 ? "hurtle" : "float"); + /* if we're in the midst of shooting multiple projectiles, stop */ + if (m_shot.i < m_shot.n) { + /* last message before hurtling was "you shoot N arrows" */ + You("stop %sing after the first %s.", + m_shot.s ? "shoot" : "throw", m_shot.s ? "shot" : "toss"); + m_shot.n = m_shot.i; /* make current shot be the last */ + } if (In_sokoban(&u.uz)) change_luck(-1); /* Sokoban guilt */ uc.x = u.ux; @@ -507,6 +608,39 @@ hurtle(dx, dy, range, verbose) (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t)&range); } +/* Move a monster through the air for a few squares. + */ +void +mhurtle(mon, dx, dy, range) + struct monst *mon; + int dx, dy, range; +{ + coord mc, cc; + + /* At the very least, debilitate the monster */ + mon->movement = 0; + mon->mstun = 1; + + /* Is the monster stuck or too heavy to push? + * (very large monsters have too much inertia, even floaters and flyers) + */ + if (mon->data->msize >= MZ_HUGE || mon == u.ustuck || mon->mtrapped) + return; + + /* Make sure dx and dy are [-1,0,1] */ + dx = sgn(dx); + dy = sgn(dy); + if(!range || (!dx && !dy)) return; /* paranoia */ + + /* Send the monster along the path */ + mc.x = mon->mx; + mc.y = mon->my; + cc.x = mon->mx + (dx * range); + cc.y = mon->my + (dy * range); + (void) walk_path(&mc, &cc, mhurtle_step, (genericptr_t)mon); + return; +} + STATIC_OVL void check_shop_obj(obj, x, y, broken) register struct obj *obj; @@ -578,6 +712,11 @@ boolean hitsroof; int otyp = obj->otyp, ocorpsenm = obj->corpsenm; int blindinc; + /* need to check for blindness result prior to destroying obj */ + blindinc = (otyp == CREAM_PIE || otyp == BLINDING_VENOM) && + /* AT_WEAP is ok here even if attack type was AT_SPIT */ + can_blnd(&youmonst, &youmonst, AT_WEAP, obj) ? rnd(25) : 0; + breakmsg(obj, !Blind); breakobj(obj, u.ux, u.uy, TRUE, TRUE); obj = 0; /* it's now gone */ @@ -590,13 +729,12 @@ boolean hitsroof; case CREAM_PIE: case BLINDING_VENOM: pline("You've got it all over your %s!", body_part(FACE)); - blindinc = rnd(25); - if (blindinc && !Blindfolded) { - if (otyp != BLINDING_VENOM) - u.ucreamed += blindinc; - else if (!Blind) + if (blindinc) { + if (otyp == BLINDING_VENOM && !Blind) pline("It blinds you!"); - make_blinded(Blinded + blindinc, FALSE); + u.ucreamed += blindinc; + make_blinded(Blinded + (long)blindinc, FALSE); + if (!Blind) Your(vision_clears); } break; default: @@ -604,9 +742,14 @@ boolean hitsroof; } return FALSE; } else { /* neither potion nor other breaking object */ - boolean less_damage = uarmh && is_metallic(uarmh); + boolean less_damage = uarmh && is_metallic(uarmh), artimsg = FALSE; int dmg = dmgval(obj, &youmonst); + if (obj->oartifact) + /* need a fake die roll here; rn1(18,2) avoids 1 and 20 */ + artimsg = artifact_hit((struct monst *)0, &youmonst, + obj, &dmg, rn1(18,2)); + if (!dmg) { /* probably wasn't a weapon; base damage on weight */ dmg = (int) obj->owt / 100; if (dmg < 1) dmg = 1; @@ -618,11 +761,13 @@ boolean hitsroof; if (dmg > 1 && less_damage) dmg = 1; if (dmg > 0) dmg += u.udaminc; if (dmg < 0) dmg = 0; /* beware negative rings of increase damage */ + if (Half_physical_damage) dmg = (dmg + 1) / 2; if (uarmh) { - if (less_damage && dmg < (Upolyd ? u.mh : u.uhp)) - pline("Fortunately, you are wearing a hard helmet."); - else if (flags.verbose && + if (less_damage && dmg < (Upolyd ? u.mh : u.uhp)) { + if (!artimsg) + pline("Fortunately, you are wearing a hard helmet."); + } else if (flags.verbose && !(obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm]))) Your("%s does not protect you.", xname(uarmh)); } else if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) { @@ -675,9 +820,10 @@ struct obj *obj; } void -throwit(obj, wep_mask) +throwit(obj, wep_mask, twoweap) register struct obj *obj; long wep_mask; /* used to re-equip returning boomerang */ +boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */ { register struct monst *mon; register int range, urange; @@ -687,13 +833,13 @@ long wep_mask; /* used to re-equip returning boomerang */ if ((obj->cursed || obj->greased) && (u.dx || u.dy) && !rn2(7)) { boolean slipok = TRUE; if (ammo_and_launcher(obj, uwep)) - pline("%s misfires!", The(xname(obj))); + pline("%s!", Tobjnam(obj, "misfire")); else { /* only slip if it's greased or meant to be thrown */ if (obj->greased || throwing_weapon(obj)) /* BUG: this message is grammatically incorrect if obj has a plural name; greased gloves or boots for instance. */ - pline("%s slips as you throw it!", The(xname(obj))); + pline("%s as you throw it!", Tobjnam(obj, "slip")); else slipok = FALSE; } if (slipok) { @@ -704,6 +850,19 @@ long wep_mask; /* used to re-equip returning boomerang */ } } + if ((u.dx || u.dy || (u.dz < 1)) && + calc_capacity((int)obj->owt) > SLT_ENCUMBER && + (Upolyd ? (u.mh < 5 && u.mh != u.mhmax) + : (u.uhp < 10 && u.uhp != u.uhpmax)) && + obj->owt > (unsigned)((Upolyd ? u.mh : u.uhp) * 2) && + !Is_airlevel(&u.uz)) { + You("have so little stamina, %s drops from your grasp.", + the(xname(obj))); + exercise(A_CON, FALSE); + u.dx = u.dy = 0; + u.dz = 1; + } + if(u.uswallow) { mon = u.ustuck; bhitpos.x = mon->mx; @@ -711,11 +870,12 @@ long wep_mask; /* used to re-equip returning boomerang */ } else if(u.dz) { if (u.dz < 0 && Role_if(PM_VALKYRIE) && obj->oartifact == ART_MJOLLNIR && !impaired) { - pline("%s hits the %s and returns to your hand!", - The(xname(obj)), ceiling(u.ux,u.uy)); + pline("%s the %s and returns to your hand!", + Tobjnam(obj, "hit"), ceiling(u.ux,u.uy)); obj = addinv(obj); (void) encumber_msg(); setuwep(obj); + u.twoweap = twoweap; } else if (u.dz < 0 && !Is_airlevel(&u.uz) && !Underwater && !Is_waterlevel(&u.uz)) { (void) toss_up(obj, rn2(5)); @@ -732,8 +892,10 @@ long wep_mask; /* used to re-equip returning boomerang */ exercise(A_DEX, TRUE); obj = addinv(obj); (void) encumber_msg(); - if (wep_mask && !(obj->owornmask & wep_mask)) + if (wep_mask && !(obj->owornmask & wep_mask)) { setworn(obj, wep_mask); + u.twoweap = twoweap; + } return; } } else { @@ -756,7 +918,7 @@ long wep_mask; /* used to re-equip returning boomerang */ if (is_ammo(obj)) { if (ammo_and_launcher(obj, uwep)) range++; - else + else if (obj->oclass != GEM_CLASS) range /= 2; } @@ -819,25 +981,33 @@ long wep_mask; /* used to re-equip returning boomerang */ sho_obj_return_to_u(obj); /* display its flight */ if (!impaired && rn2(100)) { - pline("%s returns to your hand!", The(xname(obj))); + pline("%s to your hand!", Tobjnam(obj, "return")); obj = addinv(obj); (void) encumber_msg(); setuwep(obj); + u.twoweap = twoweap; if(cansee(bhitpos.x, bhitpos.y)) newsym(bhitpos.x,bhitpos.y); } else { - int dmg = rnd(4); - if (Blind) - pline("%s hits your %s!", - The(xname(obj)), body_part(ARM)); - else - pline("%s flies back toward you, hitting your %s!", - The(xname(obj)), body_part(ARM)); - (void) artifact_hit((struct monst *) 0, &youmonst, - obj, &dmg, 0); - losehp(dmg, xname(obj), KILLED_BY); - if(ship_object(obj, u.ux, u.uy, FALSE)) - return; + int dmg = rn2(2); + if (!dmg) { + pline(Blind ? "%s lands %s your %s." : + "%s back to you, landing %s your %s.", + Blind ? Something : Tobjnam(obj, "return"), + Levitation ? "beneath" : "at", + makeplural(body_part(FOOT))); + } else { + dmg += rnd(3); + pline(Blind ? "%s your %s!" : + "%s back toward you, hitting your %s!", + Tobjnam(obj, Blind ? "hit" : "fly"), + body_part(ARM)); + (void) artifact_hit((struct monst *)0, + &youmonst, obj, &dmg, 0); + losehp(dmg, xname(obj), KILLED_BY); + } + if (ship_object(obj, u.ux, u.uy, FALSE)) + return; dropy(obj); } return; @@ -854,10 +1024,7 @@ long wep_mask; /* used to re-equip returning boomerang */ return; } if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return; - if (obj->otyp == CRYSKNIFE && (!obj->oerodeproof || !rn2(10))) { - obj->otyp = WORM_TOOTH; - obj->oerodeproof = 0; - } + obj_no_longer_held(obj); if (mon && mon->isshk && is_pick(obj)) { if (cansee(bhitpos.x, bhitpos.y)) pline("%s snatches up %s.", @@ -931,7 +1098,17 @@ tmiss(obj, mon) struct obj *obj; struct monst *mon; { - miss(xname(obj), mon); + const char *missile = mshot_xname(obj); + + /* If the target can't be seen or doesn't look like a valid target, + avoid "the arrow misses it," or worse, "the arrows misses the mimic." + An attentive player will still notice that this is different from + an arrow just landing short of any target (no message in that case), + so will realize that there is a valid target here anyway. */ + if (!canseemon(mon) || (mon->m_ap_type && mon->m_ap_type != M_AP_MONSTER)) + pline("%s misses.", The(missile)); + else + miss(missile, mon); if (!rn2(3)) wakeup(mon); return; } @@ -1051,16 +1228,20 @@ register struct obj *obj; } else { tmp += uwep->spe - greatest_erosion(uwep); tmp += weapon_hit_bonus(uwep); + if (uwep->oartifact) tmp += spec_abon(uwep, mon); /* * Elves and Samurais are highly trained w/bows, * especially their own special types of bow. * Polymorphing won't make you a bow expert. */ if ((Race_if(PM_ELF) || Role_if(PM_SAMURAI)) && + (!Upolyd || your_race(youmonst.data)) && objects[uwep->otyp].oc_skill == P_BOW) { tmp++; - if (is_elf(youmonst.data) && uwep->otyp == ELVEN_BOW) tmp++; - else if (Role_if(PM_SAMURAI) && uwep->otyp == YUMI) tmp++; + if (Race_if(PM_ELF) && uwep->otyp == ELVEN_BOW) + tmp++; + else if (Role_if(PM_SAMURAI) && uwep->otyp == YUMI) + tmp++; } } } else { @@ -1090,6 +1271,7 @@ register struct obj *obj; obfree(obj, (struct obj *)0); return 1; } + passive_obj(mon, obj, (struct attack *)0); } else { tmiss(obj, mon); } @@ -1128,15 +1310,31 @@ register struct obj *obj; potionhit(mon, obj, TRUE); return 1; - } else if (obj->oclass == FOOD_CLASS && - is_domestic(mon->data) && tamedog(mon,obj)) { - return 1; /* food is gone */ + } else if (befriend_with_obj(mon->data, obj)) { + if (tamedog(mon, obj)) + return 1; /* obj is gone */ + else { + /* not tmiss(), which angers non-tame monsters */ + miss(xname(obj), mon); + mon->msleeping = 0; + mon->mstrategy &= ~STRAT_WAITMASK; + } } else if (guaranteed_hit) { /* this assumes that guaranteed_hit is due to swallowing */ - pline("%s vanishes into %s %s.", - The(xname(obj)), s_suffix(mon_nam(mon)), - is_animal(u.ustuck->data) ? "entrails" : "currents"); wakeup(mon); + if (obj->otyp == CORPSE && touch_petrifies(&mons[obj->corpsenm])) { + if (is_animal(u.ustuck->data)) { + minstapetrify(u.ustuck, TRUE); + /* Don't leave a cockatrice corpse available in a statue */ + if (!u.uswallow) { + delobj(obj); + return 1; + } + } + } + pline("%s into %s %s.", + Tobjnam(obj, "vanish"), s_suffix(mon_nam(mon)), + is_animal(u.ustuck->data) ? "entrails" : "currents"); } else { tmiss(obj, mon); } @@ -1161,6 +1359,7 @@ register struct obj *obj; Strcpy(buf,Monnam(mon)); mon->mpeaceful = 1; + mon->mavenge = 0; /* object properly identified */ if(obj->dknown && objects[obj->otyp].oc_name_known) { @@ -1300,10 +1499,21 @@ boolean from_invent; if (obj->otyp == POT_OIL && obj->lamplit) { splatter_burning_oil(x,y); } else if (distu(x,y) <= 2) { - /* [what about "familiar odor" when known?] */ - if (obj->otyp != POT_WATER) - You("smell a peculiar odor..."); - potionbreathe(obj); + if (!breathless(youmonst.data) || haseyes(youmonst.data)) { + if (obj->otyp != POT_WATER) { + if (!breathless(youmonst.data)) + /* [what about "familiar odor" when known?] */ + You("smell a peculiar odor..."); + else { + int numeyes = eyecount(youmonst.data); + Your("%s water%s.", + (numeyes == 1) ? body_part(EYE) : + makeplural(body_part(EYE)), + (numeyes == 1) ? "s" : ""); + } + } + potionbreathe(obj); + } } /* monster breathing isn't handled... [yet?] */ break; @@ -1350,9 +1560,10 @@ breaktest(obj) struct obj *obj; { if (obj_resists(obj, 1, 99)) return 0; + if (objects[obj->otyp].oc_material == GLASS && !obj->oartifact && + obj->oclass != GEM_CLASS) + return 1; switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) { - case MIRROR: - case CRYSTAL_BALL: #ifdef TOURIST case EXPENSIVE_CAMERA: #endif @@ -1376,6 +1587,11 @@ boolean in_view; to_pieces = ""; switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) { + default: /* glass or crystal wand */ + if (obj->oclass != WAND_CLASS) + impossible("breaking odd object?"); + case CRYSTAL_PLATE_MAIL: + case LENSES: case MIRROR: case CRYSTAL_BALL: #ifdef TOURIST @@ -1411,15 +1627,29 @@ throw_gold(obj) struct obj *obj; { int range, odx, ody; +#ifndef GOLDOBJ long zorks = obj->quan; +#endif register struct monst *mon; + if(!u.dx && !u.dy && !u.dz) { + You("cannot throw gold at yourself."); + return(0); + } +#ifdef GOLDOBJ + freeinv(obj); +#endif if(u.uswallow) { pline(is_animal(u.ustuck->data) ? "%s in the %s's entrails." : "%s into %s.", +#ifndef GOLDOBJ "The gold disappears", mon_nam(u.ustuck)); u.ustuck->mgold += zorks; dealloc_obj(obj); +#else + "The money disappears", mon_nam(u.ustuck)); + add_to_minv(u.ustuck, obj); +#endif return(1); } diff --git a/src/drawing.c b/src/drawing.c index 70cd408..02d96e9 100644 --- a/src/drawing.c +++ b/src/drawing.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)drawing.c 3.3 1999/12/02 */ +/* SCCS Id: @(#)drawing.c 3.4 1999/12/02 */ /* Copyright (c) NetHack Development Team 1992. */ /* NetHack may be freely redistributed. See license for details. */ @@ -269,7 +269,7 @@ const struct symdef defsyms[MAXPCHARS] = { {'"', "web", C(CLR_GRAY)}, /* web */ {'^', "statue trap", C(CLR_GRAY)}, /* trap */ /*60*/ {'^', "magic trap", C(HI_ZAP)}, /* trap */ - {'^', "anti-magic trap field", C(HI_ZAP)}, /* trap */ + {'^', "anti-magic field", C(HI_ZAP)}, /* trap */ {'^', "polymorph trap", C(CLR_BRIGHT_GREEN)}, /* trap */ {'|', "wall", C(CLR_GRAY)}, /* vbeam */ {'-', "wall", C(CLR_GRAY)}, /* hbeam */ @@ -741,7 +741,7 @@ static const uchar r_oc_syms[MAXOCLASSES] = { static const uchar IBM_r_oc_syms[MAXOCLASSES] = { /* a la EPYX Rogue */ /* 0*/ '\0', ILLOBJ_SYM, -# if defined(MSDOS) || defined(WIN32) || defined(OS2) +# if defined(MSDOS) || defined(OS2) || ( defined(WIN32) && !defined(MSWIN_GRAPHICS) ) 0x18, /* weapon: up arrow */ /* 0x0a, */ ARMOR_SYM, /* armor: Vert rect with o */ /* 0x09, */ RING_SYM, /* ring: circle with arrow */ @@ -794,12 +794,12 @@ boolean is_rlevel; /* Use a loop: char != uchar on some machines. */ for (i = 0; i < MAXMCLASSES; i++) monsyms[i] = def_monsyms[i]; -# ifdef ASCIIGRAPH +# if defined(ASCIIGRAPH) && !defined(MSWIN_GRAPHICS) if (iflags.IBMgraphics # if defined(USE_TILES) && defined(MSDOS) && !iflags.grmode # endif - ) + ) monsyms[S_HUMAN] = 0x01; /* smiley face */ # endif for (i = 0; i < MAXPCHARS; i++) @@ -842,6 +842,7 @@ boolean is_rlevel; showsyms[S_litcorr] = 0xb2; showsyms[S_upstair] = 0xf0; /* Greek Xi */ showsyms[S_dnstair] = 0xf0; +#ifndef MSWIN_GRAPHICS showsyms[S_arrow_trap] = 0x04; /* diamond (cards) */ showsyms[S_dart_trap] = 0x04; showsyms[S_falling_rock_trap] = 0x04; @@ -864,6 +865,7 @@ boolean is_rlevel; showsyms[S_magic_trap] = 0x04; showsyms[S_anti_magic_trap] = 0x04; showsyms[S_polymorph_trap] = 0x04; +#endif } #endif /* ASCIIGRAPH */ diff --git a/src/dungeon.c b/src/dungeon.c index 048b028..6e7b448 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dungeon.c 3.3 1999/10/30 */ +/* SCCS Id: @(#)dungeon.c 3.4 1999/10/30 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -380,7 +380,10 @@ insert_branch(new_branch, extract_first) new_branch->next = (branch *) 0; /* Convert the branch into a unique number so we can sort them. */ -#define branch_val(bp) ((((long)(bp)->end1.dnum * (MAXLEVEL+1) + (long)(bp)->end1.dlevel) * (MAXDUNGEON+1) * (MAXLEVEL+1)) + ((long)(bp)->end2.dnum * (MAXLEVEL+1) + (long)(bp)->end2.dlevel)) +#define branch_val(bp) \ + ((((long)(bp)->end1.dnum * (MAXLEVEL+1) + \ + (long)(bp)->end1.dlevel) * (MAXDUNGEON+1) * (MAXLEVEL+1)) + \ + ((long)(bp)->end2.dnum * (MAXLEVEL+1) + (long)(bp)->end2.dlevel)) /* * Insert the new branch into the correct place in the branch list. @@ -661,6 +664,11 @@ init_dungeons() /* initialize the "dungeon" structs */ /* validate the data's version against the program's version */ Fread((genericptr_t) &vers_info, sizeof vers_info, 1, dgn_file); + /* we'd better clear the screen now, since when error messages come from + * check_version() they will be printed using pline(), which doesn't + * mix with the raw messages that might be already on the screen + */ + if (iflags.window_inited) clear_nhwindow(WIN_MAP); if (!check_version(&vers_info, DUNGEON_FILE, TRUE)) panic("Dungeon description not valid."); @@ -734,7 +742,7 @@ init_dungeons() /* initialize the "dungeon" structs */ } else if (pd.tmpdungeon[i].entry_lev > 0) { dungeons[i].entry_lev = pd.tmpdungeon[i].entry_lev; if (dungeons[i].entry_lev > dungeons[i].num_dunlevs) - dungeons[i].entry_lev = pd.tmpdungeon[i].entry_lev; + dungeons[i].entry_lev = dungeons[i].num_dunlevs; } else { /* default */ dungeons[i].entry_lev = 1; /* defaults to top level */ } diff --git a/src/eat.c b/src/eat.c index 2e859f6..4cd2427 100644 --- a/src/eat.c +++ b/src/eat.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)eat.c 3.3 1999/12/13 */ +/* SCCS Id: @(#)eat.c 3.4 2002/01/02 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -35,11 +35,12 @@ STATIC_DCL void FDECL(start_eating, (struct obj *)); STATIC_DCL void FDECL(fprefx, (struct obj *)); STATIC_DCL void FDECL(fpostfx, (struct obj *)); STATIC_DCL int NDECL(bite); +STATIC_DCL int FDECL(edibility_prompts, (struct obj *)); STATIC_DCL int FDECL(rottenfood, (struct obj *)); STATIC_DCL void NDECL(eatspecial); STATIC_DCL void FDECL(eataccessory, (struct obj *)); -STATIC_DCL const char * FDECL(foodword, (struct obj *)); +STATIC_DCL const char *FDECL(foodword, (struct obj *)); char msgbuf[BUFSZ]; @@ -103,7 +104,8 @@ register struct obj *obj; /* above also prevents the Amulet from being eaten, so we must never allow fake amulets to be eaten either [which is already the case] */ - if (metallivorous(youmonst.data) && is_metallic(obj)) + if (metallivorous(youmonst.data) && is_metallic(obj) && + (youmonst.data != &mons[PM_RUST_MONSTER] || is_rustprone(obj))) return TRUE; if (u.umonnum == PM_GELATINOUS_CUBE && is_organic(obj) && /* [g.cubes can eat containers and retain all contents @@ -139,6 +141,7 @@ static const struct { const char *txt; int nut; } tintxts[] = { {"boiled", 50}, {"dried", 55}, {"szechuan", 70}, +#define FRENCH_FRIED_TIN 11 {"french fried", 40}, {"sauteed", 95}, {"broiled", 80}, @@ -223,7 +226,7 @@ choke(food) /* To a full belly all food is bad. (It.) */ { /* only happens if you were satiated */ if (u.uhs != SATIATED) { - if (food->otyp != AMULET_OF_STRANGULATION) + if (!food || food->otyp != AMULET_OF_STRANGULATION) return; } else if (Role_if(PM_KNIGHT) && u.ualign.type == A_LAWFUL) { adjalign(-1); /* gluttony is unchivalrous */ @@ -234,12 +237,13 @@ choke(food) /* To a full belly all food is bad. (It.) */ if (Breathless || (!Strangled && !rn2(20))) { /* choking by eating AoS doesn't involve stuffing yourself */ - if (food->otyp == AMULET_OF_STRANGULATION) { + if (food && food->otyp == AMULET_OF_STRANGULATION) { You("choke, but recover your composure."); return; } You("stuff yourself and then vomit voluminously."); morehungry(1000); /* you just got *very* sick! */ + nomovemsg = 0; vomit(); } else { killer_format = KILLED_BY_AN; @@ -263,19 +267,18 @@ choke(food) /* To a full belly all food is bad. (It.) */ } } +/* modify object wt. depending on time spent consuming it */ STATIC_OVL void -recalc_wt() /* modify object wt. depending on time spent consuming it */ +recalc_wt() { - register struct obj *piece = victual.piece; + struct obj *piece = victual.piece; #ifdef DEBUG debugpline("Old weight = %d", piece->owt); debugpline("Used time = %d, Req'd time = %d", victual.usedtime, victual.reqtime); #endif - /* weight(piece) = weight of full item */ - if(victual.usedtime) - piece->owt = eaten_stat(weight(piece), piece); + piece->owt = weight(piece); #ifdef DEBUG debugpline("New weight = %d", piece->owt); #endif @@ -302,9 +305,9 @@ register struct obj *otmp; { if (otmp->quan > 1L) { if(!carried(otmp)) - (void) splitobj(otmp, 1L); + (void) splitobj(otmp, otmp->quan - 1L); else - otmp = splitobj(otmp, otmp->quan - 1L); + otmp = splitobj(otmp, 1L); #ifdef DEBUG debugpline("split object,"); #endif @@ -326,10 +329,15 @@ register struct obj *otmp; if (carried(otmp)) { freeinv(otmp); - if (inv_cnt() >= 52 && !merge_choice(invent, otmp)) + if (inv_cnt() >= 52) { + sellobj_state(SELL_DONTSELL); dropy(otmp); - else - otmp = addinv(otmp); /* unlikely but a merge is possible */ + sellobj_state(SELL_NORMAL); + } else { + otmp->oxlth++; /* hack to prevent merge */ + otmp = addinv(otmp); + otmp->oxlth--; + } } return(otmp); } @@ -482,13 +490,16 @@ register int pm; return; } case PM_GREEN_SLIME: - if (!Unchanging && youmonst.data != &mons[PM_FIRE_VORTEX] && - youmonst.data != &mons[PM_FIRE_ELEMENTAL] && - youmonst.data != &mons[PM_GREEN_SLIME]) { - You("don't feel very well."); - Slimed = 10L; - } - /* Fall through */ + if (!Slimed && !Unchanging && + youmonst.data != &mons[PM_FIRE_VORTEX] && + youmonst.data != &mons[PM_FIRE_ELEMENTAL] && + youmonst.data != &mons[PM_SALAMANDER] && + youmonst.data != &mons[PM_GREEN_SLIME]) { + You("don't feel very well."); + Slimed = 10L; + flags.botl = 1; + } + /* Fall through */ default: if (acidic(&mons[pm]) && Stoned) fix_petrification(); @@ -810,8 +821,11 @@ register int pm; tmp += 20; if (youmonst.data->mlet != S_MIMIC) { char buf[BUFSZ]; - You_cant("resist the temptation to mimic a pile of gold."); +#ifdef STEED + /* A pile of gold can't ride. */ + if (u.usteed) dismount_steed(DISMOUNT_FELL); +#endif nomul(-tmp); Sprintf(buf, "You now prefer mimicking %s again.", an(Upolyd ? youmonst.data->mname : urace.noun)); @@ -846,7 +860,7 @@ register int pm; /* case PM_SANDESTIN: */ if (!Unchanging) { You_feel("a change coming over you."); - polyself(); + polyself(FALSE); } break; case PM_MIND_FLAYER: @@ -1003,11 +1017,18 @@ opentin() /* called during each move whilst opening a tin */ tin.tin->dknown = tin.tin->known = TRUE; cprefx(tin.tin->corpsenm); cpostfx(tin.tin->corpsenm); + if(((!carried(tin.tin) && costly_spot(tin.tin->ox, tin.tin->oy) && + !tin.tin->no_charge) + || tin.tin->unpaid)) { + verbalize("You open it, you bought it!"); + bill_dummy_object(tin.tin); + } + /* check for vomiting added by GAN 01/16/87 */ if(tintxts[r].nut < 0) make_vomiting((long)rn1(15,10), FALSE); else lesshungry(tintxts[r].nut); - if(r == 0) { /* Deep Fried */ + if(r == 0 || r == FRENCH_FRIED_TIN) { /* Assume !Glib, because you can't open tins when Glib. */ incr_itimeout(&Glib, rnd(15)); pline("Eating deep fried food made your %s very slippery.", @@ -1015,8 +1036,8 @@ opentin() /* called during each move whilst opening a tin */ } } else { if (tin.tin->cursed) - pline("It contains some decaying %s substance.", - hcolor(green)); + pline("It contains some decaying%s%s substance.", + Blind ? "" : " ", Blind ? "" : hcolor(green)); else pline("It contains spinach."); @@ -1027,6 +1048,15 @@ opentin() /* called during each move whilst opening a tin */ You("discard the open tin."); goto use_me; } + + tin.tin->dknown = tin.tin->known = TRUE; + if(((!carried(tin.tin) && costly_spot(tin.tin->ox, tin.tin->oy) && + !tin.tin->no_charge) + || tin.tin->unpaid)) { + verbalize("You open it, you bought it!"); + bill_dummy_object(tin.tin); + } + if (!tin.tin->cursed) pline("This makes you feel like %s!", Hallucination ? "Swee'pea" : "Popeye"); @@ -1034,7 +1064,6 @@ opentin() /* called during each move whilst opening a tin */ gainstr(tin.tin, 0); u.uconduct.food++; } - tin.tin->dknown = tin.tin->known = TRUE; use_me: if (carried(tin.tin)) useup(tin.tin); else useupf(tin.tin, 1L); @@ -1086,11 +1115,7 @@ start_tin(otmp) /* called when starting to open a tin */ pline_The("tin slips from your %s.", makeplural(body_part(FINGER))); if(otmp->quan > 1L) { - register struct obj *obj; - obj = splitobj(otmp, 1L); - if (otmp == uwep) setuwep(obj); - if (otmp == uswapwep) setuswapwep(obj); - if (otmp == uquiver) setuqwep(obj); + otmp = splitobj(otmp, 1L); } if (carried(otmp)) dropx(otmp); else stackobj(otmp); @@ -1125,6 +1150,7 @@ struct obj *obj; } else if(!rn2(4) && !Blind) { pline("Everything suddenly goes dark."); make_blinded((long)d(2,10),FALSE); + if (!Blind) Your(vision_clears); } else if(!rn2(3)) { const char *what, *where; if (!Blind) @@ -1133,7 +1159,11 @@ struct obj *obj; Is_waterlevel(&u.uz)) what = "you lose control of", where = "yourself"; else - what = "you slap against the", where = surface(u.ux,u.uy); + what = "you slap against the", where = +#ifdef STEED + (u.usteed) ? "saddle" : +#endif + surface(u.ux,u.uy); pline_The("world spins and %s %s.", what, where); flags.soundok = 0; nomul(-rnd(10)); @@ -1155,6 +1185,10 @@ eatcorpse(otmp) /* called when a corpse is selected as food */ boolean stoneable = (touch_petrifies(&mons[mnum]) && !Stone_resistance && !poly_when_stoned(youmonst.data)); + /* KMH, conduct */ + if (!vegan(&mons[mnum])) u.uconduct.unvegan++; + if (!vegetarian(&mons[mnum])) violated_vegetarian(); + if (mnum != PM_LIZARD && mnum != PM_LICHEN) { long age = peek_at_iced_corpse_age(otmp); @@ -1185,19 +1219,12 @@ eatcorpse(otmp) /* called when a corpse is selected as food */ s_suffix(mons[mnum].mname)); make_sick(sick_time, buf, TRUE, SICK_VOMITABLE); } - - /* KMH, conduct */ - if (!vegan(&mons[mnum])) - u.uconduct.unvegan++; - if (!vegetarian(&mons[mnum])) - violated_vegetarian(); - if (carried(otmp)) useup(otmp); else useupf(otmp, 1L); return(2); } else if (acidic(&mons[mnum]) && !Acid_resistance) { tp++; - You("have a very bad case of stomach acid."); + You("have a very bad case of stomach acid."); /* not body_part() */ losehp(rnd(15), "acidic corpse", KILLED_BY_AN); } else if (poisonous(&mons[mnum]) && rn2(5)) { tp++; @@ -1223,22 +1250,27 @@ eatcorpse(otmp) /* called when a corpse is selected as food */ otmp->orotten = TRUE; (void)touchfood(otmp); retcode = 1; - } else - otmp->oeaten >>= 2; + } + + if (!mons[otmp->corpsenm].cnutrit) { + /* no nutrution: rots away, no message if you passed out */ + if (!retcode) pline_The("corpse rots away completely."); + if (carried(otmp)) useup(otmp); + else useupf(otmp, 1L); + retcode = 2; + } + + if (!retcode) consume_oeaten(otmp, 2); /* oeaten >>= 2 */ } else { pline("%s%s %s!", !uniq ? "This " : !type_is_pname(&mons[mnum]) ? "The " : "", food_xname(otmp, FALSE), - (carnivorous(youmonst.data) && !herbivorous(youmonst.data)) ? - "is delicious" : "tastes terrible"); + (vegan(&mons[mnum]) ? + (!carnivorous(youmonst.data) && herbivorous(youmonst.data)) : + (carnivorous(youmonst.data) && !herbivorous(youmonst.data))) + ? "is delicious" : "tastes terrible"); } - /* KMH, conduct */ - if (!vegan(&mons[mnum])) - u.uconduct.unvegan++; - if (!vegetarian(&mons[mnum])) - violated_vegetarian(); - return(retcode); } @@ -1284,23 +1316,24 @@ struct obj *otmp; switch(otmp->otyp) { case FOOD_RATION: if(u.uhunger <= 200) - if (Hallucination) pline("Oh wow, like, superior, man!"); - else pline("That food really hit the spot!"); - else if(u.uhunger <= 700) pline("That satiated your stomach!"); + pline(Hallucination ? "Oh wow, like, superior, man!" : + "That food really hit the spot!"); + else if(u.uhunger <= 700) pline("That satiated your %s!", + body_part(STOMACH)); break; case TRIPE_RATION: if (carnivorous(youmonst.data) && !humanoid(youmonst.data)) pline("That tripe ration was surprisingly good!"); + else if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC))) + pline(Hallucination ? "Tastes great! Less filling!" : + "Mmm, tripe... not bad!"); else { pline("Yak - dog food!"); more_experienced(1,0); - flags.botl = 1; - } - if (rn2(2) && - (Upolyd ? (!carnivorous(youmonst.data) || - (humanoid(youmonst.data) && - !is_orc(youmonst.data))) - : !CANNIBAL_ALLOWED())) { + newexplevel(); + /* not cannibalism, but we use similar criteria + for deciding whether to be sickened by this meal */ + if (rn2(2) && !CANNIBAL_ALLOWED()) make_vomiting((long)rn1(victual.reqtime, 14), FALSE); } break; @@ -1390,11 +1423,11 @@ eataccessory(otmp) struct obj *otmp; { int typ = otmp->otyp; - int oldprop; + long oldprop; /* Note: rings are not so common that this is unbalancing. */ /* (How often do you even _find_ 3 rings of polymorph in a game?) */ - oldprop = !!(u.uprops[objects[typ].oc_oprop].intrinsic); + oldprop = u.uprops[objects[typ].oc_oprop].intrinsic; if (otmp == uleft || otmp == uright) { Ring_gone(otmp); if (u.uhp <= 0) return; /* died from sink fall */ @@ -1416,14 +1449,14 @@ struct obj *otmp; set_mimic_blocking(); see_monsters(); if (Invis && !oldprop && !ESee_invisible && - !perceives(youmonst.data) && !Blind) { + !perceives(youmonst.data) && !Blind) { newsym(u.ux,u.uy); pline("Suddenly you can see yourself."); makeknown(typ); } break; case RIN_INVISIBILITY: - if (!oldprop && !EInvis && !BInvis && + if (!oldprop && !EInvis && !BInvis && !See_invisible && !Blind) { newsym(u.ux,u.uy); Your("body takes on a %s transparency...", @@ -1435,6 +1468,8 @@ struct obj *otmp; rescham(); break; case RIN_LEVITATION: + /* undo the `.intrinsic |= FROMOUTSIDE' done above */ + u.uprops[LEVITATION].intrinsic = oldprop; if (!Levitation) { float_up(); incr_itimeout(&HLevitation, d(10,20)); @@ -1504,6 +1539,11 @@ eatspecial() /* called after eating non-food */ victual.piece = (struct obj *)0; victual.eating = 0; if (otmp->oclass == GOLD_CLASS) { +#ifdef GOLDOBJ + if (carried(otmp)) + useupall(otmp); + else +#endif dealloc_obj(otmp); return; } @@ -1570,7 +1610,7 @@ register struct obj *otmp; you_unwere(TRUE); break; case CARROT: - make_blinded(0L,TRUE); + make_blinded((long)u.ucreamed,TRUE); break; case FORTUNE_COOKIE: outrumor(bcsign(otmp), BY_COOKIE); @@ -1621,13 +1661,147 @@ register struct obj *otmp; return; } +/* + * return 0 if the food was not dangerous. + * return 1 if the food was dangerous and you chose to stop. + * return 2 if the food was dangerous and you chose to eat it anyway. + */ +STATIC_OVL int +edibility_prompts(otmp) +struct obj *otmp; +{ + /* blessed food detection granted you a one-use + ability to detect food that is unfit for consumption + or dangerous and avoid it. */ + + char buf[BUFSZ], foodsmell[BUFSZ]; + char *eat_it_anyway = "Eat it anyway?"; + boolean cadaver = (otmp->otyp == CORPSE); + boolean stoneorslime = FALSE; + int material = objects[otmp->otyp].oc_material; + long rotted = 0L; + int mnum; + +#ifdef GCC_WARN + mnum = 0; +#endif + + Strcpy(foodsmell, Tobjnam(otmp, "smell")); + if (cadaver || otmp->otyp == EGG || otmp->otyp == TIN) { + mnum = otmp->corpsenm; + /* These checks must match those in eatcorpse() */ + stoneorslime = (touch_petrifies(&mons[mnum]) && + !Stone_resistance && !poly_when_stoned(youmonst.data)); + + if (mnum == PM_GREEN_SLIME) + stoneorslime = (!Unchanging && + youmonst.data != &mons[PM_FIRE_VORTEX] && + youmonst.data != &mons[PM_FIRE_ELEMENTAL] && + youmonst.data != &mons[PM_SALAMANDER] && + youmonst.data != &mons[PM_GREEN_SLIME]); + + if (cadaver && mnum != PM_LIZARD && mnum != PM_LICHEN) { + long age = peek_at_iced_corpse_age(otmp); + /* worst case rather than random + in this calculation to force prompt */ + rotted = (monstermoves - age)/(10L + 0 /* was rn2(20) */); + if (otmp->cursed) rotted += 2L; + else if (otmp->blessed) rotted -= 2L; + } + } + + /* + * These problems with food should be checked in + * order from most detrimental to least detrimental. + */ + + if (cadaver && mnum != PM_ACID_BLOB && rotted > 5L && !Sick_resistance) { + /* Tainted meat */ + Sprintf(buf, "%s like it could be tainted! %s", + foodsmell, eat_it_anyway); + if (yn_function(buf,ynchars,'n')=='n') return 1; + else return 2; + } + if (stoneorslime) { + Sprintf(buf, "%s like it could be something very dangerous! %s", + foodsmell, eat_it_anyway); + if (yn_function(buf,ynchars,'n')=='n') return 1; + else return 2; + } + if (otmp->orotten || (cadaver && rotted > 3L)) { + /* Rotten */ + Sprintf(buf, "%s like it could be rotten! %s", + foodsmell, eat_it_anyway); + if (yn_function(buf,ynchars,'n')=='n') return 1; + else return 2; + } + if (cadaver && poisonous(&mons[mnum]) && !Poison_resistance) { + /* poisonous */ + Sprintf(buf, "%s like it might be poisonous! %s", + foodsmell, eat_it_anyway); + if (yn_function(buf,ynchars,'n')=='n') return 1; + else return 2; + } + if (cadaver && !vegetarian(&mons[mnum]) && + !u.uconduct.unvegetarian && Role_if(PM_MONK)) { + Sprintf(buf, "%s unhealthy. %s", + foodsmell, eat_it_anyway); + if (yn_function(buf,ynchars,'n')=='n') return 1; + else return 2; + } + if (cadaver && acidic(&mons[mnum]) && !Acid_resistance) { + Sprintf(buf, "%s rather acidic. %s", + foodsmell, eat_it_anyway); + if (yn_function(buf,ynchars,'n')=='n') return 1; + else return 2; + } + if (Upolyd && + (u.umonnum == PM_RUST_MONSTER && is_metallic(otmp) && otmp->oerodeproof)) { + Sprintf(buf, "%s disgusting to you right now. %s", + foodsmell, eat_it_anyway); + if (yn_function(buf,ynchars,'n')=='n') return 1; + else return 2; + } + + /* + * Breaks conduct, but otherwise safe. + */ + + if (!u.uconduct.unvegan && + ((material == LEATHER || material == BONE || + material == DRAGON_HIDE || material == WAX) || + (cadaver && !vegan(&mons[mnum])))) { + Sprintf(buf, "%s foul and unfamiliar to you. %s", + foodsmell, eat_it_anyway); + if (yn_function(buf,ynchars,'n')=='n') return 1; + else return 2; + } + if (!u.uconduct.unvegetarian && + ((material == LEATHER || material == BONE || material == DRAGON_HIDE) || + (cadaver && !vegetarian(&mons[mnum])))) { + Sprintf(buf, "%s unfamiliar to you. %s", + foodsmell, eat_it_anyway); + if (yn_function(buf,ynchars,'n')=='n') return 1; + else return 2; + } + + if (cadaver && mnum != PM_ACID_BLOB && rotted > 5L && Sick_resistance) { + /* Tainted meat with Sick_resistance */ + Sprintf(buf, "%s like it could be tainted! %s", + foodsmell, eat_it_anyway); + if (yn_function(buf,ynchars,'n')=='n') return 1; + else return 2; + } + return 0; +} + int doeat() /* generic "eat" command funtion (see cmd.c) */ { register struct obj *otmp; int basenutrit; /* nutrition of full item */ boolean dont_start = FALSE; - + if (Strangled) { pline("If you can't breathe air, how can you consume solids?"); return 0; @@ -1635,6 +1809,16 @@ doeat() /* generic "eat" command funtion (see cmd.c) */ if (!(otmp = floorfood("eat", 0))) return 0; if (check_capacity((char *)0)) return 0; + if (u.uedibility) { + int res = edibility_prompts(otmp); + if (res) { + Your("%s stops tingling and your sense of smell returns to normal.", + body_part(NOSE)); + u.uedibility = 0; + if (res == 1) return 0; + } + } + /* We have to make non-foods take 1 move to eat, unless we want to * do ridiculous amounts of coding to deal with partly eaten plate * mails, players who polymorph back to human in the middle of their @@ -1656,10 +1840,10 @@ doeat() /* generic "eat" command funtion (see cmd.c) */ u.umonnum == PM_RUST_MONSTER && otmp->oerodeproof) { otmp->rknown = TRUE; if (otmp->quan > 1L) { - if(!carried(otmp)) - (void) splitobj(otmp, 1L); - else - otmp = splitobj(otmp, otmp->quan - 1L); + if(!carried(otmp)) + (void) splitobj(otmp, otmp->quan - 1L); + else + otmp = splitobj(otmp, 1L); } pline("Ulch - That %s was rustproofed!", xname(otmp)); /* The regurgitated object's rustproofing is gone now */ @@ -1684,6 +1868,7 @@ doeat() /* generic "eat" command funtion (see cmd.c) */ return (1); } if (otmp->oclass != FOOD_CLASS) { + int material; victual.reqtime = 1; victual.piece = otmp; /* Don't split it, we don't need to if it's 1 move */ @@ -1701,6 +1886,14 @@ doeat() /* generic "eat" command funtion (see cmd.c) */ victual.nmod = basenutrit; victual.eating = TRUE; /* needed for lesshungry() */ + material = objects[otmp->otyp].oc_material; + if (material == LEATHER || material == BONE || material == DRAGON_HIDE) { + u.uconduct.unvegan++; + violated_vegetarian(); + } else if (material == WAX) + u.uconduct.unvegan++; + u.uconduct.food++; + if (otmp->cursed) (void) rottenfood(otmp); @@ -1716,7 +1909,6 @@ doeat() /* generic "eat" command funtion (see cmd.c) */ otmp->oclass == GOLD_CLASS ? foodword(otmp) : singular(otmp, xname)); - u.uconduct.food++; eatspecial(); return 1; } @@ -1728,10 +1920,7 @@ doeat() /* generic "eat" command funtion (see cmd.c) */ * they shouldn't be able to choke now. */ if (u.uhs != SATIATED) victual.canchoke = FALSE; - if(!carried(victual.piece)) { - if(victual.piece->quan > 1L) - (void) splitobj(victual.piece, 1L); - } + victual.piece = touchfood(otmp); You("resume your meal."); start_eating(victual.piece); return(1); @@ -1777,7 +1966,7 @@ doeat() /* generic "eat" command funtion (see cmd.c) */ otmp->orotten = TRUE; dont_start = TRUE; } - otmp->oeaten >>= 1; + consume_oeaten(otmp, 1); /* oeaten >>= 1 */ } else fprefx(otmp); } @@ -1830,10 +2019,10 @@ bite() force_save_hs = TRUE; if(victual.nmod < 0) { lesshungry(-victual.nmod); - victual.piece->oeaten -= -victual.nmod; + consume_oeaten(victual.piece, victual.nmod); /* -= -nmod */ } else if(victual.nmod > 0 && (victual.usedtime % victual.nmod)) { lesshungry(1); - victual.piece->oeaten--; + consume_oeaten(victual.piece, -1); /* -= 1 */ } force_save_hs = FALSE; recalc_wt(); @@ -1900,17 +2089,19 @@ void lesshungry(num) /* called after eating (and after drinking fruit juice) */ register int num; { + /* See comments in newuhs() for discussion on force_save_hs */ + boolean iseating = (occupation == eatfood) || force_save_hs; #ifdef DEBUG debugpline("lesshungry(%d)", num); #endif u.uhunger += num; if(u.uhunger >= 2000) { - if (!victual.eating || victual.canchoke) { - if (victual.eating) { - choke(victual.piece); - reset_eat(); + if (!iseating || victual.canchoke) { + if (iseating) { + choke(victual.piece); + reset_eat(); } else - choke(tin.tin); /* may be null */ + choke(occupation == opentin ? tin.tin : (struct obj *)0); /* no reset_eat() */ } } else { @@ -2083,10 +2274,11 @@ boolean incr; "You still have the munchies." : "The munchies are interfering with your motor capabilities."); else if (incr && - (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE))) + (Role_if(PM_WIZARD) || Race_if(PM_ELF) || + Role_if(PM_VALKYRIE))) pline("%s needs food, badly!", - (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? - urole.name.m : "Elf"); + (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ? + urole.name.m : "Elf"); else You((!incr) ? "feel weak now." : (u.uhunger < 45) ? "feel weak." : @@ -2125,6 +2317,16 @@ floorfood(verb,corpsecheck) /* get food from floor or pack */ char c; boolean feeding = (!strcmp(verb, "eat")); + /* if we can't touch floor objects then use invent food only */ + if (!can_reach_floor() || +#ifdef STEED + (feeding && u.usteed) || /* can't eat off floor while riding */ +#endif + ((is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) && + (Wwalking || is_clinger(youmonst.data) || + (Flying && !Breathless)))) + goto skipfloor; + if (feeding && metallivorous(youmonst.data)) { struct obj *gold; struct trap *ttmp = t_at(u.ux, u.uy); @@ -2145,10 +2347,7 @@ floorfood(verb,corpsecheck) /* get food from floor or pack */ } } - if ( -#ifdef STEED - !u.usteed && -#endif + if (youmonst.data != &mons[PM_RUST_MONSTER] && (gold = g_at(u.ux, u.uy)) != 0) { if (gold->quan == 1L) Sprintf(qbuf, "There is 1 gold piece here; eat it?"); @@ -2165,19 +2364,13 @@ floorfood(verb,corpsecheck) /* get food from floor or pack */ } /* Is there some food (probably a heavy corpse) here on the ground? */ - if ( -#ifdef STEED - !u.usteed && -#endif - !(Levitation && !Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) - && !u.uswallow) { - for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) { + for (otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) { if(corpsecheck ? (otmp->otyp==CORPSE && (corpsecheck == 1 || tinnable(otmp))) : feeding ? (otmp->oclass != GOLD_CLASS && is_edible(otmp)) : otmp->oclass==FOOD_CLASS) { Sprintf(qbuf, "There %s %s here; %s %s?", - (otmp->quan == 1L) ? "is" : "are", + otense(otmp, "are"), doname(otmp), verb, (otmp->quan == 1L) ? "it" : "one"); if((c = yn_function(qbuf,ynqchars,'n')) == 'y') @@ -2185,8 +2378,9 @@ floorfood(verb,corpsecheck) /* get food from floor or pack */ else if(c == 'q') return((struct obj *) 0); } - } } + + skipfloor: /* We cannot use ALL_CLASSES since that causes getobj() to skip its * "ugly checks" and we need to check for inedible items. */ @@ -2219,11 +2413,85 @@ register struct obj *obj; uneaten_amt = (long)obj->oeaten; full_amount = (obj->otyp == CORPSE) ? (long)mons[obj->corpsenm].cnutrit : (long)objects[obj->otyp].oc_nutrition; + if (uneaten_amt > full_amount) { + impossible( + "partly eaten food (%ld) more nutritious than untouched food (%ld)", + uneaten_amt, full_amount); + uneaten_amt = full_amount; + } base = (int)(full_amount ? (long)base * uneaten_amt / full_amount : 0L); return (base < 1) ? 1 : base; } +/* reduce obj's oeaten field, making sure it never hits or passes 0 */ +void +consume_oeaten(obj, amt) +struct obj *obj; +int amt; +{ + /* + * This is a hack to try to squelch several long standing mystery + * food bugs. A better solution would be to rewrite the entire + * victual handling mechanism from scratch using a less complex + * model. Alternatively, this routine could call done_eating() + * or food_disappears() but its callers would need revisions to + * cope with victual.piece unexpectedly going away. + * + * Multi-turn eating operates by setting the food's oeaten field + * to its full nutritional value and then running a counter which + * independently keeps track of whether there is any food left. + * The oeaten field can reach exactly zero on the last turn, and + * the object isn't removed from inventory until the next turn + * when the "you finish eating" message gets delivered, so the + * food would be restored to the status of untouched during that + * interval. This resulted in unexpected encumbrance messages + * at the end of a meal (if near enough to a threshold) and would + * yield full food if there was an interruption on the critical + * turn. Also, there have been reports over the years of food + * becoming massively heavy or producing unlimited satiation; + * this would occur if reducing oeaten via subtraction attempted + * to drop it below 0 since its unsigned type would produce a + * huge positive value instead. So far, no one has figured out + * _why_ that inappropriate subtraction might sometimes happen. + */ + + if (amt > 0) { + /* bit shift to divide the remaining amount of food */ + obj->oeaten >>= amt; + } else { + /* simple decrement; value is negative so we actually add it */ + if ((int) obj->oeaten > -amt) + obj->oeaten += amt; + else + obj->oeaten = 0; + } + + if (obj->oeaten == 0) { + if (obj == victual.piece) /* always true unless wishing... */ + victual.reqtime = victual.usedtime; /* no bites left */ + obj->oeaten = 1; /* smallest possible positive value */ + } +} + #endif /* OVLB */ +#ifdef OVL1 + +/* called when eatfood occupation has been interrupted, + or in the case of theft, is about to be interrupted */ +boolean +maybe_finished_meal(stopping) +boolean stopping; +{ + /* in case consume_oeaten() has decided that the food is all gone */ + if (occupation == eatfood && victual.usedtime >= victual.reqtime) { + if (stopping) occupation = 0; /* for do_reset_eat */ + (void) eatfood(); /* calls done_eating() to use up victual.piece */ + return TRUE; + } + return FALSE; +} + +#endif /* OVL1 */ /*eat.c*/ diff --git a/src/end.c b/src/end.c index 20032b3..5cbdd73 100644 --- a/src/end.c +++ b/src/end.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)end.c 3.3 2000/06/10 */ +/* SCCS Id: @(#)end.c 3.4 2001/09/24 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -40,8 +40,9 @@ STATIC_DCL void FDECL(sort_valuables, (struct valuable_data *,int)); STATIC_DCL void FDECL(add_artifact_score, (struct obj *)); STATIC_DCL void FDECL(display_artifact_score, (struct obj *,winid)); STATIC_DCL void FDECL(savelife, (int)); -STATIC_DCL void NDECL(list_vanquished); -STATIC_DCL void NDECL(list_genocided); +STATIC_DCL void FDECL(list_vanquished, (int, BOOLEAN_P)); +STATIC_DCL void FDECL(list_genocided, (int, BOOLEAN_P)); +STATIC_DCL boolean FDECL(should_query_disclose_option, (int, int*)); #if defined(__BEOS__) || defined(MICRO) || defined(WIN32) || defined(OS2) extern void FDECL(nethack_exit,(int)); @@ -52,7 +53,6 @@ extern void FDECL(nethack_exit,(int)); #define done_stopprint program_state.stopprint #ifdef AMIGA -void NDECL(clear_icon); # define NH_abort() Abort(0) #else # ifdef SYSV @@ -186,7 +186,9 @@ register struct monst *mtmp; You("die..."); mark_synch(); /* flush buffered screen output */ buf[0] = '\0'; - if ((mtmp->data->geno & G_UNIQ) != 0) { + /* "killed by the high priest of Crom" is okay, "killed by the high + priest" alone isn't */ + if ((mtmp->data->geno & G_UNIQ) != 0 && !(mtmp->data == &mons[PM_HIGH_PRIEST] && !mtmp->ispriest)) { if (!type_is_pname(mtmp->data)) Strcat(buf, "the "); killer_format = KILLED_BY; @@ -226,6 +228,8 @@ register struct monst *mtmp; u.ugrave_arise = urace.mummynum; else if (mtmp->data->mlet == S_VAMPIRE && Race_if(PM_HUMAN)) u.ugrave_arise = PM_VAMPIRE; + else if (mtmp->data == &mons[PM_GHOUL]) + u.ugrave_arise = PM_GHOUL; if (u.ugrave_arise >= LOW_PM && (mvitals[u.ugrave_arise].mvflags & G_GENOD)) u.ugrave_arise = NON_PM; @@ -283,57 +287,101 @@ panic VA_DECL(const char *, str) done(PANICKED); } +STATIC_OVL boolean +should_query_disclose_option(category, defquery) +int category; +int *defquery; +{ + int idx; + char *dop = index(disclosure_options, category); + if (dop && defquery) { + idx = (dop - disclosure_options) / sizeof(char); + if (idx < 0 || idx > (NUM_DISCLOSURE_OPTIONS - 1)) { + impossible( + "should_query_disclose_option: bad disclosure index %d %c", + idx, category); + *defquery = DISCLOSE_PROMPT_DEFAULT_YES; + return TRUE; + } + if (flags.end_disclose[idx] == DISCLOSE_YES_WITHOUT_PROMPT) { + *defquery = 'y'; + return FALSE; + } else if (flags.end_disclose[idx] == DISCLOSE_NO_WITHOUT_PROMPT) { + *defquery = 'n'; + return FALSE; + } else if (flags.end_disclose[idx] == DISCLOSE_PROMPT_DEFAULT_YES) { + *defquery = 'y'; + return TRUE; + } else if (flags.end_disclose[idx] == DISCLOSE_PROMPT_DEFAULT_NO) { + *defquery = 'n'; + return TRUE; + } + } + if (defquery)impossible("should_query_disclose_option: bad category %c", category); + else impossible("should_query_disclose_option: null defquery"); + return TRUE; +} + STATIC_OVL void disclose(how,taken) int how; boolean taken; { - char c; + char c = 0; char qbuf[QBUFSZ]; + int defquery; + boolean ask; - if (invent && !done_stopprint && - (!flags.end_disclose[0] || index(flags.end_disclose, 'i'))) { + if (invent) { if(taken) Sprintf(qbuf,"Do you want to see what you had when you %s?", (how == QUIT) ? "quit" : "died"); else Strcpy(qbuf,"Do you want your possessions identified?"); - if ((c = yn_function(qbuf, ynqchars, 'y')) == 'y') { - /* New dump format by maartenj@cs.vu.nl */ - struct obj *obj; - for (obj = invent; obj; obj = obj->nobj) { - makeknown(obj->otyp); - obj->known = obj->bknown = obj->dknown = obj->rknown = 1; + ask = should_query_disclose_option('i', &defquery); + if (!done_stopprint) { + if (ask) + c = yn_function(qbuf, ynqchars, defquery); + if ((!ask && defquery == 'y') || (ask && c == 'y')) { + /* New dump format by maartenj@cs.vu.nl */ + struct obj *obj; + + for (obj = invent; obj; obj = obj->nobj) { + makeknown(obj->otyp); + obj->known = obj->bknown = obj->dknown = obj->rknown = 1; + } + (void) display_inventory((char *)0, TRUE); + container_contents(invent, TRUE, TRUE); } - (void) display_inventory((char *)0, TRUE); - container_contents(invent, TRUE, TRUE); + if (ask && c == 'q') done_stopprint++; } - if (c == 'q') done_stopprint++; } - if (!done_stopprint && - (!flags.end_disclose[0] || index(flags.end_disclose, 'a'))) { - c = yn_function("Do you want to see your attributes?",ynqchars,'y'); - if (c == 'y') enlightenment(how >= PANICKED ? 1 : 2); /* final */ - if (c == 'q') done_stopprint++; + ask = should_query_disclose_option('a', &defquery); + if (!done_stopprint) { + if (ask) + c = yn_function("Do you want to see your attributes?",ynqchars, defquery); + if ((!ask && defquery == 'y') || (ask && c == 'y')) + enlightenment(how >= PANICKED ? 1 : 2); /* final */ + if (ask && c == 'q') done_stopprint++; } - if (!done_stopprint && - (!flags.end_disclose[0] || index(flags.end_disclose, 'v'))) { - list_vanquished(); - } + ask = should_query_disclose_option('v', &defquery); + if (!done_stopprint) + list_vanquished(defquery, ask); - if (!done_stopprint && - (!flags.end_disclose[0] || index(flags.end_disclose, 'g'))) { - list_genocided(); - } + ask = should_query_disclose_option('g', &defquery); + if (!done_stopprint) + list_genocided(defquery, ask); - if (!done_stopprint && - (!flags.end_disclose[0] || index(flags.end_disclose, 'c'))) { - c = yn_function("Do you want to see your conduct?",ynqchars,'y'); - if (c == 'y') show_conduct(how >= PANICKED ? 1 : 2); - if (c == 'q') done_stopprint++; + ask = should_query_disclose_option('c', &defquery); + if (!done_stopprint) { + if (ask) + c = yn_function("Do you want to see your conduct?",ynqchars,defquery); + if ((!ask && defquery == 'y') || (ask && c == 'y')) + show_conduct(how >= PANICKED ? 1 : 2); + if (ask && c == 'q') done_stopprint++; } } @@ -348,6 +396,11 @@ int how; u.uhunger = 500; newuhs(FALSE); } + /* cure impending doom of sickness hero won't have time to fix */ + if ((Sick & TIMEOUT) == 1) { + u.usick_type = 0; + Sick = 0; + } if (how == CHOKING) init_uhunger(); nomovemsg = "You survived that attempt on your life."; flags.move = 0; @@ -370,18 +423,19 @@ struct obj *list; /* inventory or container contents */ register struct obj *obj; register int i; - /* find amulets and gems, ignoring artifacts except for the AoY. */ + /* find amulets and gems, ignoring all artifacts */ for (obj = list; obj; obj = obj->nobj) if (Has_contents(obj)) { get_valuables(obj->cobj); + } else if (obj->oartifact) { + continue; } else if (obj->oclass == AMULET_CLASS) { i = obj->otyp - FIRST_AMULET; if (!amulets[i].count) { amulets[i].count = obj->quan; amulets[i].typ = obj->otyp; } else amulets[i].count += obj->quan; /* always adds one */ - } else if (obj->oclass == GEM_CLASS && obj->otyp < LUCKSTONE && - !obj->oartifact) { + } else if (obj->oclass == GEM_CLASS && obj->otyp < LUCKSTONE) { i = min(obj->otyp, LAST_GEM + 1) - FIRST_GEM; if (!gems[i].count) { gems[i].count = obj->quan; @@ -428,8 +482,7 @@ struct obj *list; otmp->otyp == BELL_OF_OPENING || otmp->otyp == SPE_BOOK_OF_THE_DEAD || otmp->otyp == CANDELABRUM_OF_INVOCATION) { - /* shopkeepers charge 100x; 250x is arbitrary */ - u.urexp += 250L * (long)objects[otmp->otyp].oc_cost; + u.urexp += (arti_cost(otmp) * 5 / 2); if (Has_contents(otmp)) add_artifact_score(otmp->cobj); } @@ -454,11 +507,12 @@ winid endwin; otmp->known = otmp->bknown = otmp->dknown = otmp->rknown = 1; /* assumes artifacts don't have quan>1 */ - Sprintf(pbuf, "%s (worth %ld zorkmids and %ld points)", + Sprintf(pbuf, "%s%s (worth %ld %s and %ld points)", + the_unique_obj(otmp) ? "The " : "", otmp->oartifact ? artifact_name(xname(otmp), &dummy) : OBJ_NAME(objects[otmp->otyp]), - 100L * (long)objects[otmp->otyp].oc_cost, - 250L * (long)objects[otmp->otyp].oc_cost); + arti_cost(otmp), currency(2L), + arti_cost(otmp) * 5 / 2); putstr(endwin, 0, pbuf); } if (Has_contents(otmp)) @@ -476,13 +530,14 @@ int how; winid endwin = WIN_ERR; boolean bones_ok, have_windows = iflags.window_inited; struct obj *corpse = (struct obj *)0; + long umoney; /* kilbuf: used to copy killer in case it comes from something like * xname(), which would otherwise get overwritten when we call * xname() when listing possessions * pbuf: holds Sprintf'd output for raw_print and putstr */ - if (how == ASCENDED) + if (how == ASCENDED || (!killer && how == GENOCIDED)) killer_format = NO_KILLER_PREFIX; /* Avoid killed by "a" burning or "a" starvation */ if (!killer && (how == STARVING || how == BURNING)) @@ -540,8 +595,8 @@ int how; program_state.gameover = 1; /* in case of a subsequent panic(), there's no point trying to save */ program_state.something_worth_saving = 0; - /* turn off vision subsystem */ - vision_recalc(2); + /* render vision subsystem inoperative */ + iflags.vision_inited = 0; /* might have been killed while using a disposable item, so make sure it's gone prior to inventory disclosure and creation of bones data */ inven_inuse(TRUE); @@ -551,7 +606,7 @@ int how; * smiling... :-) -3. */ if (moves <= 1 && how < PANICKED) /* You die... --More-- */ - pline("Do not pass go. Do not collect 200 zorkmids."); + pline("Do not pass go. Do not collect 200 %s.", currency(200L)); if (have_windows) wait_synch(); /* flush screen output */ #ifndef NO_SIGNAL @@ -573,7 +628,8 @@ int how; u.ugrave_arise = (NON_PM - 2); /* leave no corpse */ else if (how == STONING) u.ugrave_arise = (NON_PM - 1); /* statue instead of corpse */ - else if (u.ugrave_arise == NON_PM) { + else if (u.ugrave_arise == NON_PM && + !(mvitals[u.umonnum].mvflags & G_NOCORPSE)) { corpse = mk_named_object(CORPSE, &mons[u.umonnum], u.ux, u.uy, plname); Sprintf(pbuf, "%s, %s%s", plname, @@ -604,9 +660,7 @@ int how; } else taken = FALSE; /* lint; assert( !bones_ok ); */ clearlocks(); -#ifdef AMIGA - clear_icon(); -#endif + if (have_windows) display_nhwindow(WIN_MESSAGE, FALSE); if (strcmp(flags.end_disclose, "none") && how != PANICKED) @@ -619,8 +673,16 @@ int how; long tmp; int deepest = deepest_lev_reached(FALSE); - u.ugold += hidden_gold(); /* accumulate gold from containers */ - tmp = u.ugold - u.ugold0; +#ifndef GOLDOBJ + umoney = u.ugold; + tmp = u.ugold0; +#else + umoney = money_cnt(invent); + tmp = u.umoney0; +#endif + umoney += hidden_gold(); /* accumulate gold from containers */ + tmp = umoney - tmp; /* net gain */ + if (tmp < 0L) tmp = 0L; if (how < PANICKED) @@ -642,6 +704,14 @@ int how; corpse = (struct obj *)0; } + /* update gold for the rip output, which can't use hidden_gold() + (containers will be gone by then if bones just got saved...) */ +#ifndef GOLDOBJ + u.ugold = umoney; +#else + done_money = umoney; +#endif + /* clean up unneeded windows */ if (have_windows) { wait_synch(); @@ -744,9 +814,9 @@ int how; otmp->dknown = 1; /* seen it (blindness fix) */ otmp->onamelth = 0; otmp->quan = count; - Sprintf(pbuf, "%8ld %s (worth %ld zorkmids),", + Sprintf(pbuf, "%8ld %s (worth %ld %s),", count, xname(otmp), - count * (long)objects[typ].oc_cost); + count * (long)objects[typ].oc_cost, currency(2L)); obfree(otmp, (struct obj *)0); } else { Sprintf(pbuf, @@ -782,7 +852,7 @@ int how; if (!done_stopprint) { Sprintf(pbuf, "and %ld piece%s of gold, after %ld move%s.", - u.ugold, plur(u.ugold), moves, plur(moves)); + umoney, plur(umoney), moves, plur(moves)); putstr(endwin, 0, pbuf); } if (!done_stopprint) { @@ -842,7 +912,7 @@ boolean identified, all_containers; if (all_containers) container_contents(box->cobj, identified, TRUE); } else { - pline("%s is empty.", The(xname(box))); + pline("%s empty.", Tobjnam(box, "are")); display_nhwindow(WIN_MESSAGE, FALSE); } } @@ -871,7 +941,9 @@ int status; } STATIC_OVL void -list_vanquished() +list_vanquished(defquery, ask) +int defquery; +boolean ask; { register int i, lev; int ntypes = 0, max_lev = 0, nkilled; @@ -891,10 +963,11 @@ list_vanquished() * includes all dead monsters, not just those killed by the player */ if (ntypes != 0) { - c = yn_function("Do you want an account of creatures vanquished?", - ynqchars, 'n'); - if (c == 'q') done_stopprint++; - if (c == 'y') { + if (ask) + c = yn_function("Do you want an account of creatures vanquished?", + ynqchars, defquery); + if (ask && c == 'q') done_stopprint++; + if ((!ask && defquery == 'y') || (ask && c == 'y')) { klwin = create_nhwindow(NHW_MENU); putstr(klwin, 0, "Vanquished creatures:"); putstr(klwin, 0, ""); @@ -907,9 +980,15 @@ list_vanquished() Sprintf(buf, "%s%s", !type_is_pname(&mons[i]) ? "The " : "", mons[i].mname); - if (nkilled > 1) - Sprintf(eos(buf)," (%d time%s)", - nkilled, plur(nkilled)); + if (nkilled > 1) { + switch (nkilled) { + case 2: Sprintf(eos(buf)," (twice)"); break; + case 3: Sprintf(eos(buf)," (thrice)"); break; + default: Sprintf(eos(buf)," (%d time%s)", + nkilled, plur(nkilled)); + break; + } + } } else { /* trolls or undead might have come back, but we don't keep track of that */ @@ -949,7 +1028,9 @@ num_genocides() } STATIC_OVL void -list_genocided() +list_genocided(defquery, ask) +int defquery; +boolean ask; { register int i; int ngenocided; @@ -961,10 +1042,11 @@ list_genocided() /* genocided species list */ if (ngenocided != 0) { - c = yn_function("Do you want a list of species genocided?", - ynqchars, 'n'); - if (c == 'q') done_stopprint++; - if (c == 'y') { + if (ask) + c = yn_function("Do you want a list of species genocided?", + ynqchars, defquery); + if (ask && c == 'q') done_stopprint++; + if ((!ask && defquery == 'y') || (ask && c == 'y')) { klwin = create_nhwindow(NHW_MENU); putstr(klwin, 0, "Genocided species:"); putstr(klwin, 0, ""); diff --git a/src/engrave.c b/src/engrave.c index 5898536..9fdabf8 100644 --- a/src/engrave.c +++ b/src/engrave.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)engrave.c 3.3 1999/08/16 */ +/* SCCS Id: @(#)engrave.c 3.4 2001/11/04 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -153,7 +153,7 @@ register int x, y; if ((x == u.ux) && (y == u.uy) && u.uswallow && is_animal(u.ustuck->data)) return "maw"; - else if (IS_AIR(lev->typ)) + else if (IS_AIR(lev->typ) && Is_airlevel(&u.uz)) return "air"; else if (is_pool(x,y)) return "water"; @@ -336,7 +336,7 @@ register int x,y; char *et; unsigned maxelen = BUFSZ - sizeof("You feel the words: \"\". "); if (strlen(ep->engr_txt) > maxelen) { - strncpy(buf, ep->engr_txt, maxelen); + (void) strncpy(buf, ep->engr_txt, (int)maxelen); buf[maxelen] = '\0'; et = buf; } else @@ -369,7 +369,8 @@ register xchar e_type; ep->engr_y = y; ep->engr_txt = (char *)(ep + 1); Strcpy(ep->engr_txt, s); - if(strcmp(s, "Elbereth")) exercise(A_WIS, TRUE); + /* engraving Elbereth shows wisdom */ + if(!strcmp(s, "Elbereth")) exercise(A_WIS, TRUE); ep->engr_time = e_time; ep->engr_type = e_type > 0 ? e_type : rnd(N_ENGRAVE-1); ep->engr_lth = strlen(s) + 1; @@ -450,16 +451,14 @@ doengrave() char post_engr_text[BUFSZ]; /* Text displayed after engraving prompt */ const char *everb; /* Present tense of engraving type */ const char *eloc; /* Where the engraving is (ie dust/floor/...) */ - register char *sp; /* Place holder for space count of engr text */ - register int len; /* # of nonspace chars of new engraving text */ - register int maxelen; /* Max allowable length of new engraving text */ - register int spct; /* # of spaces in new engraving text */ - register struct engr *oep = engr_at(u.ux,u.uy); + char *sp; /* Place holder for space count of engr text */ + int len; /* # of nonspace chars of new engraving text */ + int maxelen; /* Max allowable length of engraving text */ + struct engr *oep = engr_at(u.ux,u.uy); /* The current engraving */ - register struct obj *otmp; /* Object selected with which to engrave */ + struct obj *otmp; /* Object selected with which to engrave */ char *writer; - multi = 0; /* moves consumed */ nomovemsg = (char *)0; /* occupation end message */ @@ -531,10 +530,13 @@ doengrave() return(0); } if (IS_GRAVE(levl[u.ux][u.uy].typ)) { + if (!levl[u.ux][u.uy].disturbed) { You("disturb the undead!"); + levl[u.ux][u.uy].disturbed = 1; (void) makemon(&mons[PM_GHOUL], u.ux, u.uy, NO_MM_FLAGS); exercise(A_WIS, FALSE); - return(0); + return(1); + } } /* SPFX for items */ @@ -676,7 +678,7 @@ doengrave() break; case WAN_CANCELLATION: case WAN_MAKE_INVISIBLE: - if(oep) { + if (oep && oep->engr_type != HEADSTONE) { if (!Blind) pline_The("engraving on the %s vanishes!", surface(u.ux,u.uy)); @@ -684,7 +686,7 @@ doengrave() } break; case WAN_TELEPORTATION: - if (oep) { + if (oep && oep->engr_type != HEADSTONE) { if (!Blind) pline_The("engraving on the %s vanishes!", surface(u.ux,u.uy)); @@ -783,15 +785,16 @@ doengrave() if (!Blind) You("wipe out the message here."); else - Your("%s gets %s.", xname(otmp), - is_ice(u.ux,u.uy) ? - "frosty" : "dusty"); + Your("%s %s %s.", xname(otmp), + otense(otmp, "get"), + is_ice(u.ux,u.uy) ? + "frosty" : "dusty"); dengr = TRUE; } else Your("%s can't wipe out this engraving.", xname(otmp)); else - Your("%s gets %s.", xname(otmp), + Your("%s %s %s.", xname(otmp), otense(otmp, "get"), is_ice(u.ux,u.uy) ? "frosty" : "dusty"); break; default: @@ -811,6 +814,18 @@ doengrave() break; } + if (IS_GRAVE(levl[u.ux][u.uy].typ)) { + if (type == ENGRAVE || type == 0) + type = HEADSTONE; + else { + /* ensures the "cannot wipe out" case */ + type = DUST; + dengr = FALSE; + teleengr = FALSE; + buf[0] = (char)0; + } + } + /* End of implement setup */ /* Identify stylus */ @@ -839,8 +854,9 @@ doengrave() if (zapwand && (otmp->spe < 0)) { pline("%s %sturns to dust.", The(xname(otmp)), Blind ? "" : "glows violently, then "); - You("are not going to get anywhere trying to write in the %s with your dust.", - is_ice(u.ux,u.uy) ? "frost" : "dust"); + if (!IS_GRAVE(levl[u.ux][u.uy].typ)) + You("are not going to get anywhere trying to write in the %s with your dust.", + is_ice(u.ux,u.uy) ? "frost" : "dust"); useup(otmp); ptext = FALSE; } @@ -860,7 +876,10 @@ doengrave() /* Give player the choice to add to engraving. */ - if ( (type == oep->engr_type) && (!Blind || + if (type == HEADSTONE) { + /* no choice, only append */ + c = 'y'; + } else if ( (type == oep->engr_type) && (!Blind || (oep->engr_type == BURN) || (oep->engr_type == ENGRAVE)) ) { c = yn_function("Do you want to add to the current engraving?", ynqchars, 'y'); @@ -898,7 +917,7 @@ doengrave() You("will overwrite the current message."); eow = TRUE; } - } + } } eloc = surface(u.ux,u.uy); @@ -943,23 +962,15 @@ doengrave() Sprintf(qbuf,"What do you want to %s the %s here?", everb, eloc); getlin(qbuf, ebuf); - /* Mix up engraving if surface or state of mind is unsound. */ - /* Original kludge by stewr 870708. modified by njm 910722. */ - for (sp = ebuf; *sp; sp++) - if ( ((type == DUST || type == ENGR_BLOOD) && !rn2(25)) || - (Blind && !rn2(9)) || (Confusion && !rn2(12)) || - (Stunned && !rn2(4)) || (Hallucination && !rn2(1)) ) - *sp = '!' + rn2(93); /* ASCII-code only */ - /* Count the actual # of chars engraved not including spaces */ len = strlen(ebuf); + for (sp = ebuf; *sp; sp++) if (isspace(*sp)) len -= 1; - for (sp = ebuf, spct = 0; *sp; sp++) if (isspace(*sp)) spct++; - - if ( (len == spct) || index(ebuf, '\033') ) { + if (len == 0 || index(ebuf, '\033')) { if (zapwand) { if (!Blind) - pline("%s glows, then fades.", The(xname(otmp))); + pline("%s, then %s.", + Tobjnam(otmp, "glow"), otense(otmp, "fade")); return(1); } else { pline(Never_mind); @@ -967,12 +978,21 @@ doengrave() } } - len -= spct; - /* A single `x' is the traditional signature of an illiterate person */ if (len != 1 || (!index(ebuf, 'x') && !index(ebuf, 'X'))) u.uconduct.literate++; + /* Mix up engraving if surface or state of mind is unsound. + Note: this won't add or remove any spaces. */ + for (sp = ebuf; *sp; sp++) { + if (isspace(*sp)) continue; + if (((type == DUST || type == ENGR_BLOOD) && !rn2(25)) || + (Blind && !rn2(11)) || (Confusion && !rn2(7)) || + (Stunned && !rn2(4)) || (Hallucination && !rn2(2))) + *sp = ' ' + rnd(96 - 2); /* ASCII '!' thru '~' + (excludes ' ' and DEL) */ + } + /* Previous engraving is overwritten */ if (eow) { del_engr(oep); @@ -1004,12 +1024,19 @@ doengrave() * "ere", then "th". */ Your("%s dull.", aobjnam(otmp, "get")); + if (otmp->unpaid) { + struct monst *shkp = shop_keeper(*u.ushops); + if (shkp) { + You("damage it, you pay for it!"); + bill_dummy_object(otmp); + } + } if (len > maxelen) { multi = -maxelen; otmp->spe = -3; - } else - if (len > 1) otmp->spe -= len >> 1; - else otmp->spe -= 1; /* Prevent infinite engraving */ + } else if (len > 1) + otmp->spe -= len >> 1; + else otmp->spe -= 1; /* Prevent infinite engraving */ } else if ( (otmp->oclass == RING_CLASS) || (otmp->oclass == GEM_CLASS) ) @@ -1067,6 +1094,7 @@ doengrave() if (doblind && !resists_blnd(&youmonst)) { You("are blinded by the flash!"); make_blinded((long)rnd(50),FALSE); + if (!Blind) Your(vision_clears); } return(1); diff --git a/src/exper.c b/src/exper.c index 3b25498..a310a63 100644 --- a/src/exper.c +++ b/src/exper.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)exper.c 3.3 2000/07/23 */ +/* SCCS Id: @(#)exper.c 3.4 2002/01/15 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -39,7 +39,7 @@ int experience(mtmp, nk) /* return # of exp points for mtmp after nk killed */ register struct monst *mtmp; register int nk; -#if defined(applec) +#if defined(macintosh) && (defined(__SC__) || defined(__MRC__)) # pragma unused(nk) #endif { @@ -139,11 +139,11 @@ const char *drainer; /* cause of death, if drain should be fatal */ else if (u.uhp > u.uhpmax) u.uhp = u.uhpmax; if (u.ulevel < urole.xlev) - num = rn1(u.ulevel/2 + urole.enadv.lornd + urace.enadv.lornd, - urole.enadv.lofix + urace.enadv.lofix); + num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.lornd + urace.enadv.lornd, + urole.enadv.lofix + urace.enadv.lofix); else - num = rn1(u.ulevel/2 + urole.enadv.hirnd + urace.enadv.hirnd, - urole.enadv.hifix + urace.enadv.hifix); + num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.hirnd + urace.enadv.hirnd, + urole.enadv.hifix + urace.enadv.hifix); num = enermod(num); /* M. Stephenson */ u.uenmax -= num; if (u.uenmax < 0) u.uenmax = 0; @@ -179,12 +179,17 @@ boolean incr; /* true iff via incremental experience growth */ num = newhp(); u.uhpmax += num; u.uhp += num; + if (Upolyd) { + num = rnd(8); + u.mhmax += num; + u.mh += num; + } if (u.ulevel < urole.xlev) num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.lornd + urace.enadv.lornd, - urole.enadv.lofix + urace.enadv.lofix); + urole.enadv.lofix + urace.enadv.lofix); else num = rn1((int)ACURR(A_WIS)/2 + urole.enadv.hirnd + urace.enadv.hirnd, - urole.enadv.hifix + urace.enadv.hifix); + urole.enadv.hifix + urace.enadv.hifix); num = enermod(num); /* M. Stephenson */ u.uenmax += num; u.uen += num; diff --git a/src/explode.c b/src/explode.c index 691b09d..05173ac 100644 --- a/src/explode.c +++ b/src/explode.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)explode.c 3.3 2000/07/07 */ +/* SCCS Id: @(#)explode.c 3.4 2000/07/07 */ /* Copyright (C) 1990 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -22,11 +22,12 @@ static int expl[3][3] = { * these disadvantages.... */ void -explode(x, y, type, dam, olet) +explode(x, y, type, dam, olet, expltype) int x, y; int type; /* the same as in zap.c */ int dam; char olet; +int expltype; { int i, j, k, damu = dam; boolean starting = 1; @@ -39,6 +40,7 @@ char olet; int explmask[3][3]; /* 0=normal explosion, 1=do shieldeff, 2=do nothing */ boolean shopdamage = FALSE; + boolean generic = FALSE; if (olet == WAND_CLASS) /* retributive strike */ switch (Role_switch) { @@ -180,7 +182,7 @@ char olet; for (i=0; i<3; i++) for (j=0; j<3; j++) { if (explmask[i][j] == 2) continue; tmp_at(starting ? DISP_BEAM : DISP_CHANGE, - cmap_to_glyph(expl[i][j])); + explosion_to_glyph(expltype,expl[i][j])); tmp_at(i+x-1, j+y-1); starting = 0; } @@ -205,7 +207,8 @@ char olet; /* Cover last shield glyph with blast symbol. */ for (i=0; i<3; i++) for (j=0; j<3; j++) { if (explmask[i][j] == 1) - show_glyph(i+x-1,j+y-1,cmap_to_glyph(expl[i][j])); + show_glyph(i+x-1,j+y-1, + explosion_to_glyph(expltype, expl[i][j])); } } else { /* delay a little bit. */ @@ -215,7 +218,11 @@ char olet; tmp_at(DISP_END, 0); /* clear the explosion */ } else { - if (flags.soundok) You_hear("a blast."); + if (olet == MON_EXPLODE) { + str = "explosion"; + generic = TRUE; + } + if (flags.soundok) You_hear("a blast."); } if (dam) @@ -258,7 +265,7 @@ char olet; (adtyp == AD_ACID) ? "burned" : "fried"); } else if (cansee(i+x-1, j+y-1)) - pline("%s is caught in the %s!", Monnam(mtmp), str); + pline("%s is caught in the %s!", Monnam(mtmp), str); idamres += destroy_mitem(mtmp, SCROLL_CLASS, (int) adtyp); idamres += destroy_mitem(mtmp, SPBOOK_CLASS, (int) adtyp); @@ -277,9 +284,9 @@ char olet; int mdam = dam; if (resist(mtmp, olet, 0, FALSE)) { - if (cansee(i+x-1,j+y-1)) - pline("%s resists the %s!", Monnam(mtmp), str); - mdam = dam/2; + if (cansee(i+x-1,j+y-1)) + pline("%s resists the %s!", Monnam(mtmp), str); + mdam = dam/2; } if (mtmp == u.ustuck) mdam *= 2; @@ -294,7 +301,7 @@ char olet; /* KMH -- Don't blame the player for pets killing gas spores */ if (!flags.mon_moving) killed(mtmp); else monkilled(mtmp, "", (int)adtyp); - } + } else if (!flags.mon_moving) setmangry(mtmp); } /* Do your injury last */ @@ -316,18 +323,27 @@ char olet; destroy_item(WAND_CLASS, (int) adtyp); ugolemeffects((int) adtyp, damu); - if (uhurt == 2) u.uhp -= damu, flags.botl = 1; + if (uhurt == 2) { + if (Upolyd) + u.mh -= damu; + else + u.uhp -= damu; + flags.botl = 1; + } - if (u.uhp <= 0) { + if (u.uhp <= 0 || (Upolyd && u.mh <= 0)) { + if (Upolyd) { + rehumanize(); + } else { if (olet == MON_EXPLODE) { /* killer handled by caller */ - if (str != killer_buf) + if (str != killer_buf && !generic) Strcpy(killer_buf, str); killer_format = KILLED_BY_AN; } else if (type >= 0 && olet != SCROLL_CLASS) { killer_format = NO_KILLER_PREFIX; Sprintf(killer_buf, "caught %sself in %s own %s", - him[flags.female], his[flags.female], str); + uhim(), uhis(), str); } else { killer_format = KILLED_BY; Strcpy(killer_buf, str); @@ -336,6 +352,7 @@ char olet; /* Known BUG: BURNING suppresses corpse in bones data, but done does not handle killer reason correctly */ done((adtyp == AD_FIRE) ? BURNING : DIED); + } } exercise(A_STR, FALSE); } @@ -345,6 +362,11 @@ char olet; adtyp == AD_COLD ? "shatter" : adtyp == AD_DISN ? "disintegrate" : "destroy"); } + + /* explosions are noisy */ + i = dam * dam; + if (i < 50) i = 50; /* in case random damage is very small */ + wake_nearto(x, y, i); } #endif /* OVL0 */ #ifdef OVL1 @@ -394,20 +416,18 @@ struct obj *obj; /* only scatter this obj */ qtmp = otmp->quan - 1; if (qtmp > LARGEST_INT) qtmp = LARGEST_INT; qtmp = (long)rnd((int)qtmp); - (void) splitobj(otmp, qtmp); - if (qtmp < otmp->quan) - split_up = TRUE; + otmp = splitobj(otmp, qtmp); + if (rn2(qtmp)) + split_up = TRUE; else - split_up = FALSE; - } + split_up = FALSE; + } else + split_up = FALSE; if (individual_object) { - if (split_up) { - if (otmp->where == OBJ_FLOOR) - obj = otmp->nexthere; - else - obj = otmp->nobj; + if (split_up) { + obj = otmp; } else - obj = (struct obj *)0; + obj = (struct obj *)0; } obj_extract_self(otmp); used_up = FALSE; @@ -417,15 +437,20 @@ struct obj *obj; /* only scatter this obj */ && ((otmp->otyp == BOULDER) || (otmp->otyp == STATUE)) && rn2(10)) { if (otmp->otyp == BOULDER) { - pline("%s breaks apart.",The(xname(otmp))); + pline("%s apart.", Tobjnam(otmp, "break")); fracture_rock(otmp); place_object(otmp, sx, sy); /* put fragments on floor */ + if ((otmp = sobj_at(BOULDER, sx, sy)) != 0) { + /* another boulder here, restack it to the top */ + obj_extract_self(otmp); + place_object(otmp, sx, sy); + } } else { struct trap *trap; if ((trap = t_at(sx,sy)) && trap->ttyp == STATUE_TRAP) deltrap(trap); - pline("%s crumbles.",The(xname(otmp))); + pline("%s.", Tobjnam(otmp, "crumble")); (void) break_statue(otmp); place_object(otmp, sx, sy); /* put fragments on floor */ } @@ -543,7 +568,7 @@ splatter_burning_oil(x, y) { /* ZT_SPELL(ZT_FIRE) = ZT_SPELL(AD_FIRE-1) = 10+(2-1) = 11 */ #define ZT_SPELL_O_FIRE 11 /* value kludge, see zap.c */ - explode(x, y, ZT_SPELL_O_FIRE, d(4,4), BURNING_OIL); + explode(x, y, ZT_SPELL_O_FIRE, d(4,4), BURNING_OIL, EXPL_FIERY); } #endif /* OVL1 */ diff --git a/src/extralev.c b/src/extralev.c index 7d46cb6..8312402 100644 --- a/src/extralev.c +++ b/src/extralev.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)extralev.c 3.3 1999/11/26 */ +/* SCCS Id: @(#)extralev.c 3.4 2001/09/06 */ /* Copyright 1988, 1989 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -302,42 +302,42 @@ makerogueghost() ghost = christen_monst(ghost, roguename()); if (rn2(4)) { - ghostobj = mksobj_at(FOOD_RATION,x,y,FALSE); + ghostobj = mksobj_at(FOOD_RATION, x, y, FALSE, FALSE); ghostobj->quan = (long) rnd(7); ghostobj->owt = weight(ghostobj); } if (rn2(2)) { - ghostobj = mksobj_at(MACE,x,y,FALSE); + ghostobj = mksobj_at(MACE, x, y, FALSE, FALSE); ghostobj->spe = rnd(3); if (rn2(4)) curse(ghostobj); } else { - ghostobj = mksobj_at(TWO_HANDED_SWORD,x,y,FALSE); + ghostobj = mksobj_at(TWO_HANDED_SWORD, x, y, FALSE, FALSE); ghostobj->spe = rnd(5) - 2; if (rn2(4)) curse(ghostobj); } - ghostobj = mksobj_at(BOW,x,y,FALSE); + ghostobj = mksobj_at(BOW, x, y, FALSE, FALSE); ghostobj->spe = 1; if (rn2(4)) curse(ghostobj); - ghostobj = mksobj_at(ARROW,x,y,FALSE); + ghostobj = mksobj_at(ARROW, x, y, FALSE, FALSE); ghostobj->spe = 0; ghostobj->quan = (long) rn1(10,25); ghostobj->owt = weight(ghostobj); if (rn2(4)) curse(ghostobj); if (rn2(2)) { - ghostobj = mksobj_at(RING_MAIL,x,y,FALSE); + ghostobj = mksobj_at(RING_MAIL, x, y, FALSE, FALSE); ghostobj->spe = rn2(3); if (!rn2(3)) ghostobj->oerodeproof = TRUE; if (rn2(4)) curse(ghostobj); } else { - ghostobj = mksobj_at(PLATE_MAIL,x,y,FALSE); + ghostobj = mksobj_at(PLATE_MAIL, x, y, FALSE, FALSE); ghostobj->spe = rnd(5) - 2; if (!rn2(3)) ghostobj->oerodeproof = TRUE; if (rn2(4)) curse(ghostobj); } if (rn2(2)) { - ghostobj = mksobj_at(FAKE_AMULET_OF_YENDOR,x,y,TRUE); + ghostobj = mksobj_at(FAKE_AMULET_OF_YENDOR, x, y, TRUE, FALSE); ghostobj->known = TRUE; } } diff --git a/src/files.c b/src/files.c index 1838431..79e3a39 100644 --- a/src/files.c +++ b/src/files.c @@ -1,10 +1,14 @@ -/* SCCS Id: @(#)files.c 3.3 2000/04/27 */ +/* SCCS Id: @(#)files.c 3.4 2002/02/23 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" #include "dlb.h" +#ifdef TTY_GRAPHICS +#include "wintty.h" /* more() */ +#endif + #include #if !defined(MAC) && !defined(O_WRONLY) && !defined(AZTEC_C) @@ -71,6 +75,12 @@ char SAVEF[SAVESIZE]; /* holds relative path of save file from playground */ char SAVEP[SAVESIZE]; /* holds path of directory for save file */ #endif +#ifdef WIZARD +#define WIZKIT_MAX 128 +static char wizkit[WIZKIT_MAX]; +STATIC_DCL FILE *NDECL(fopen_wizkit_file); +#endif + #ifdef AMIGA extern char PATH[]; /* see sys/amiga/amidos.c */ extern char bbs_id[]; @@ -80,6 +90,7 @@ static int lockptr; # endif #include +extern void FDECL(amii_set_text_font, ( char *, int )); #endif #if defined(WIN32) || defined(MSDOS) @@ -91,13 +102,17 @@ static int lockptr; #define DeleteFile unlink #endif +#ifdef USER_SOUNDS +extern char *sounddir; +#endif + extern int n_dgns; /* from dungeon.c */ STATIC_DCL char *FDECL(set_bonesfile_name, (char *,d_level*)); STATIC_DCL char *NDECL(set_bonestemp_name); #ifdef COMPRESS -STATIC_DCL void FDECL(redirect, (char *,char *,FILE *,BOOLEAN_P)); -STATIC_DCL void FDECL(docompress_file, (char *,BOOLEAN_P)); +STATIC_DCL void FDECL(redirect, (const char *,const char *,FILE *,BOOLEAN_P)); +STATIC_DCL void FDECL(docompress_file, (const char *,BOOLEAN_P)); #endif STATIC_DCL char *FDECL(make_lockname, (const char *,char *)); STATIC_DCL FILE *FDECL(fopen_config_file, (const char *)); @@ -148,12 +163,9 @@ boolean use_scoreprefix; { FILE *fp; -#ifdef AMIGA - fp = fopenp(filename, mode); -#else filename = fqname(filename, use_scoreprefix ? SCOREPREFIX : DATAPREFIX, 0); -# ifdef VMS /* essential to have punctuation, to avoid logical names */ +#ifdef VMS /* essential to have punctuation, to avoid logical names */ { char tmp[BUFSIZ]; @@ -161,9 +173,8 @@ boolean use_scoreprefix; filename = strcat(strcpy(tmp, filename), ";0"); fp = fopen(filename, mode, "mbc=16"); } -# else +#else fp = fopen(filename, mode); -# endif #endif return fp; } @@ -185,9 +196,7 @@ set_lock_and_bones() strncat(levels, bbs_id, PATHLEN); #endif append_slash(bones); -#ifndef AMIGA /* We'll want bones & levels in the user specified directory -jhsa */ Strcat(bones, "bonesnn.*"); -#endif Strcpy(lock, levels); #ifndef AMIGA Strcat(lock, alllevels); @@ -322,20 +331,9 @@ d_level *lev; { s_level *sptr; char *dptr; -#ifdef AMIGA - char bonetmp[16]; -#endif -#ifdef AMIGA /* We'll want the bones go the user defined Levels directory -jhsa */ - /* permbones should be subsumed by fqn_prefix[BONESPREFIX] */ - Sprintf(bonetmp, "bon%c%s", dungeons[lev->dnum].boneid, - In_quest(lev) ? urole.filecode : "0"); - Strcpy(file, permbones); - Strcat(file, bonetmp); -#else Sprintf(file, "bon%c%s", dungeons[lev->dnum].boneid, In_quest(lev) ? urole.filecode : "0"); -#endif dptr = eos(file); if ((sptr = Is_special(lev)) != 0) Sprintf(dptr, ".%c", sptr->boneid); @@ -567,31 +565,27 @@ create_savefile() const char *fq_save; int fd; -#ifdef AMIGA - fd = ami_wbench_getsave(O_WRONLY | O_CREAT | O_TRUNC); -#else fq_save = fqname(SAVEF, SAVEPREFIX, 0); -# ifdef MICRO +#ifdef MICRO fd = open(fq_save, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FCMASK); -# else -# ifdef MAC +#else +# ifdef MAC fd = maccreat(fq_save, SAVE_TYPE); -# else +# else fd = creat(fq_save, FCMASK); -# endif -# if defined(VMS) && !defined(SECURE) +# endif +# if defined(VMS) && !defined(SECURE) /* Make sure the save file is owned by the current process. That's the default for non-privileged users, but for priv'd users the file will be owned by the directory's owner instead of the user. */ -# ifdef getuid /*(see vmsunix.c)*/ -# undef getuid -# endif +# ifdef getuid /*(see vmsunix.c)*/ +# undef getuid +# endif (void) chown(fq_save, getuid(), getgid()); -# endif /* VMS && !SECURE */ -# endif /* MICRO */ -#endif /* AMIGA */ +# endif /* VMS && !SECURE */ +#endif /* MICRO */ return fd; } @@ -604,16 +598,12 @@ open_savefile() const char *fq_save; int fd; -#ifdef AMIGA - fd = ami_wbench_getsave(O_RDONLY); -#else fq_save = fqname(SAVEF, SAVEPREFIX, 0); -# ifdef MAC +#ifdef MAC fd = macopen(fq_save, O_RDONLY | O_BINARY, SAVE_TYPE); -# else +#else fd = open(fq_save, O_RDONLY | O_BINARY, 0); -# endif -#endif /* AMIGA */ +#endif return fd; } @@ -622,9 +612,6 @@ open_savefile() int delete_savefile() { -#ifdef AMIGA - ami_wbench_unlink(SAVEF); -#endif (void) unlink(fqname(SAVEF, SAVEPREFIX, 0)); return 0; /* for restore_saved_game() (ex-xxxmain.c) test */ } @@ -639,13 +626,8 @@ restore_saved_game() set_savefile_name(); #ifdef MFLOPPY - if ( -# ifdef AMIGA - !(FromWBench || saveDiskPrompt(1)) -# else - !saveDiskPrompt(1) -# endif - ) return -1; + if (!saveDiskPrompt(1)) + return -1; #endif /* MFLOPPY */ fq_save = fqname(SAVEF, SAVEPREFIX, 0); @@ -668,7 +650,7 @@ restore_saved_game() STATIC_OVL void redirect(filename, mode, stream, uncomp) -char *filename, *mode; +const char *filename, *mode; FILE *stream; boolean uncomp; { @@ -688,7 +670,7 @@ boolean uncomp; */ STATIC_OVL void docompress_file(filename, uncomp) -char *filename; +const char *filename; boolean uncomp; { char cfn[80]; @@ -699,6 +681,9 @@ boolean uncomp; # endif int i = 0; int f; +# ifdef TTY_GRAPHICS + boolean istty = !strncmpi(windowprocs.name, "tty", 3); +# endif Strcpy(cfn, filename); # ifdef COMPRESS_EXTENSION @@ -738,7 +723,24 @@ boolean uncomp; args[++i] = (char *)0; f = fork(); +# ifdef TTY_GRAPHICS + /* If we don't do this and we are right after a y/n question *and* + * there is an error message from the compression, the 'y' or 'n' can + * end up being displayed after the error message. + */ + if (istty) + mark_synch(); +# endif if (f == 0) { /* child */ +# ifdef TTY_GRAPHICS + /* any error messages from the compression must come out after + * the first line, because the more() to let the user read + * them will have to clear the first line. This should be + * invisible if there are no error messages. + */ + if (istty) + raw_print(""); +# endif /* run compressor without privileges, in case other programs * have surprises along the line of gzip once taking filenames * in GZIP. @@ -789,6 +791,21 @@ boolean uncomp; /* no message needed for compress case; life will go on */ (void) unlink(cfn); } +#ifdef TTY_GRAPHICS + /* Give them a chance to read any error messages from the + * compression--these would go to stdout or stderr and would get + * overwritten only in tty mode. It's still ugly, since the + * messages are being written on top of the screen, but at least + * the user can read them. + */ + if (istty) + { + clear_nhwindow(WIN_MESSAGE); + more(); + /* No way to know if this is feasible */ + /* doredraw(); */ + } +#endif } } #endif /* COMPRESS */ @@ -799,7 +816,7 @@ compress(filename) const char *filename; { #ifndef COMPRESS -#if defined(applec) || defined(__MWERKS__) +#if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__) # pragma unused(filename) #endif #else @@ -814,7 +831,7 @@ uncompress(filename) const char *filename; { #ifndef COMPRESS -#if defined(applec) || defined(__MWERKS__) +#if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__) # pragma unused(filename) #endif #else @@ -840,7 +857,7 @@ make_lockname(filename, lockname) const char *filename; char *lockname; { -#if defined(applec) || defined(__MWERKS__) +#if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__) # pragma unused(filename,lockname) return (char*)0; #else @@ -877,7 +894,7 @@ const char *filename; int whichprefix; int retryct; { -#if defined(applec) || defined(__MWERKS__) +#if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__) # pragma unused(filename, retryct) #endif char locknambuf[BUFSZ]; @@ -986,7 +1003,7 @@ int retryct; void unlock_file(filename) const char *filename; -#if defined(applec) +#if defined(macintosh) && (defined(__SC__) || defined(__MRC__)) # pragma unused(filename) #endif { @@ -1230,7 +1247,7 @@ char *buf; char *tmp_ramdisk; char *tmp_levels; { -#if defined(applec) || defined(__MWERKS__) +#if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__) # pragma unused(tmp_ramdisk,tmp_levels) #endif char *bufp, *altp; @@ -1288,18 +1305,18 @@ char *tmp_levels; #else /*NOCWD_ASSUMPTIONS*/ # ifdef MICRO } else if (match_varname(buf, "HACKDIR", 4)) { - (void) strncpy(hackdir, bufp, PATHLEN); + (void) strncpy(hackdir, bufp, PATHLEN-1); # ifdef MFLOPPY } else if (match_varname(buf, "RAMDISK", 3)) { /* The following ifdef is NOT in the wrong * place. For now, we accept and silently * ignore RAMDISK */ # ifndef AMIGA - (void) strncpy(tmp_ramdisk, bufp, PATHLEN); + (void) strncpy(tmp_ramdisk, bufp, PATHLEN-1); # endif # endif } else if (match_varname(buf, "LEVELS", 4)) { - (void) strncpy(tmp_levels, bufp, PATHLEN); + (void) strncpy(tmp_levels, bufp, PATHLEN-1); } else if (match_varname(buf, "SAVE", 4)) { # ifdef MFLOPPY @@ -1319,7 +1336,7 @@ char *tmp_levels; saveprompt = flags.asksavedisk; # endif - (void) strncpy(SAVEP, bufp, PATHLEN); + (void) strncpy(SAVEP, bufp, SAVESIZE-1); append_slash(SAVEP); # endif /* MICRO */ #endif /*NOCWD_ASSUMPTIONS*/ @@ -1336,6 +1353,8 @@ char *tmp_levels; } else if (match_varname(buf, "CATNAME", 3)) { (void) strncpy(catname, bufp, PL_PSIZ-1); + } else if (match_varname(buf, "BOULDER", 3)) { + (void) get_uchars(fp, buf, bufp, &iflags.bouldersym, 1, "BOULDER"); } else if (match_varname(buf, "GRAPHICS", 4)) { len = get_uchars(fp, buf, bufp, translate, MAXPCHARS, "GRAPHICS"); assign_graphics(translate, len, MAXPCHARS, 0); @@ -1361,10 +1380,13 @@ char *tmp_levels; (void) get_uchars(fp, buf, bufp, translate, WARNCOUNT, "WARNINGS"); assign_warnings(translate); +#ifdef WIZARD + } else if (match_varname(buf, "WIZKIT", 6)) { + (void) strncpy(wizkit, bufp, WIZKIT_MAX-1); +#endif #ifdef AMIGA } else if (match_varname(buf, "FONT", 4)) { char *t; - extern void amii_set_text_font( char *, int ); if( t = strchr( buf+5, ':' ) ) { @@ -1373,9 +1395,7 @@ char *tmp_levels; *t = ':'; } } else if (match_varname(buf, "PATH", 4)) { - (void) strncpy(PATH, bufp, PATHLEN); -#endif -#ifdef AMIGA + (void) strncpy(PATH, bufp, PATHLEN-1); } else if (match_varname(buf, "DEPTH", 5)) { extern int amii_numcolors; int val = atoi( bufp ); @@ -1390,8 +1410,10 @@ char *tmp_levels; } } else if (match_varname(buf, "SCREENMODE", 10 )) { extern long amii_scrnmode; - if( sscanf(bufp, "%x", &amii_scrnmode) != 1 ) - amii_scrnmode = 0; + if (!stricmp(bufp,"req")) + amii_scrnmode = 0xffffffff; /* Requester */ + else if( sscanf(bufp, "%x", &amii_scrnmode) != 1 ) + amii_scrnmode = 0; } else if (match_varname(buf, "MSGPENS", 7)) { extern int amii_msgAPen, amii_msgBPen; char *t = strtok(bufp, ",/"); @@ -1449,6 +1471,34 @@ char *tmp_levels; sscanf(t, "%hx", &amii_init_map[i]); } amii_setpens( amii_numcolors = i ); + } else if (match_varname(buf, "FGPENS", 6)) { + extern int foreg[ AMII_MAXCOLORS ]; + int i; + char *t; + + for (i = 0, t = strtok(bufp, ",/"); + i < AMII_MAXCOLORS && t != (char *)0; + t = strtok((char *)0, ",/"), ++i) + { + sscanf(t, "%d", &foreg[i]); + } + } else if (match_varname(buf, "BGPENS", 6)) { + extern int backg[ AMII_MAXCOLORS ]; + int i; + char *t; + + for (i = 0, t = strtok(bufp, ",/"); + i < AMII_MAXCOLORS && t != (char *)0; + t = strtok((char *)0, ",/"), ++i) + { + sscanf(t, "%d", &backg[i]); + } +#endif +#ifdef USER_SOUNDS + } else if (match_varname(buf, "SOUNDDIR", 8)) { + sounddir = (char *)strdup(bufp); + } else if (match_varname(buf, "SOUND", 5)) { + add_sound_mapping(bufp); #endif #ifdef QT_GRAPHICS } else if (match_varname(buf, "QT_TILEWIDTH", 12)) { @@ -1463,12 +1513,24 @@ char *tmp_levels; extern char *qt_fontsize; if (qt_fontsize == NULL) qt_fontsize=(char *)strdup(bufp); + } else if (match_varname(buf, "QT_COMPACT", 10)) { + extern int qt_compact_mode; + qt_compact_mode = atoi(bufp); #endif } else return 0; return 1; } +#ifdef USER_SOUNDS +boolean +can_read_file(filename) +const char *filename; +{ + return (access(filename, 4) == 0); +} +#endif /* USER_SOUNDS */ + void read_config_file(filename) const char *filename; @@ -1499,14 +1561,19 @@ const char *filename; # endif tmp_levels[0] = 0; #endif + /* begin detection of duplicate configfile options */ + set_duplicate_opt_detection(1); while (fgets(buf, 4*BUFSZ, fp)) { if (!parse_config_line(fp, buf, tmp_ramdisk, tmp_levels)) { - raw_printf("Bad option line: \"%s\"", buf); + raw_printf("Bad option line: \"%.50s\"", buf); wait_synch(); } } (void) fclose(fp); + + /* turn off detection of duplicate configfile options */ + set_duplicate_opt_detection(0); #if defined(MICRO) && !defined(NOCWD_ASSUMPTIONS) /* should be superseded by fqn_prefix[] */ @@ -1527,6 +1594,104 @@ const char *filename; return; } +#ifdef WIZARD +STATIC_OVL FILE * +fopen_wizkit_file() +{ + FILE *fp; +#if defined(VMS) || defined(UNIX) + char tmp_wizkit[BUFSZ]; +#endif + char *envp; + + envp = nh_getenv("WIZKIT"); + if (envp && *envp) (void) strncpy(wizkit, envp, WIZKIT_MAX - 1); + if (!wizkit[0]) return (FILE *)0; + +#ifdef UNIX + if (access(wizkit, 4) == -1) { + /* 4 is R_OK on newer systems */ + /* nasty sneaky attempt to read file through + * NetHack's setuid permissions -- this is a + * place a file name may be wholly under the player's + * control + */ + raw_printf("Access to %s denied (%d).", + wizkit, errno); + wait_synch(); + /* fall through to standard names */ + } else +#endif + if ((fp = fopenp(wizkit, "r")) != (FILE *)0) { + return(fp); +#if defined(UNIX) || defined(VMS) + } else { + /* access() above probably caught most problems for UNIX */ + raw_printf("Couldn't open requested config file %s (%d).", + wizkit, errno); + wait_synch(); +#endif + } + +#if defined(MICRO) || defined(MAC) || defined(__BEOS__) || defined(WIN32) + if ((fp = fopenp(fqname(wizkit, CONFIGPREFIX, 0), "r")) + != (FILE *)0) + return(fp); +#else +# ifdef VMS + envp = nh_getenv("HOME"); + if (envp) + Sprintf(tmp_wizkit, "%s%s", envp, wizkit); + else + Sprintf(tmp_wizkit, "%s%s", "sys$login:", wizkit); + if ((fp = fopenp(tmp_wizkit, "r")) != (FILE *)0) + return(fp); +# else /* should be only UNIX left */ + envp = nh_getenv("HOME"); + if (envp) + Sprintf(tmp_wizkit, "%s/%s", envp, wizkit); + else Strcpy(tmp_wizkit, wizkit); + if ((fp = fopenp(tmp_wizkit, "r")) != (FILE *)0) + return(fp); + else if (errno != ENOENT) { + /* e.g., problems when setuid NetHack can't search home + * directory restricted to user */ + raw_printf("Couldn't open default wizkit file %s (%d).", + tmp_wizkit, errno); + wait_synch(); + } +# endif +#endif + return (FILE *)0; +} + +void +read_wizkit() +{ + FILE *fp; + char *ep, buf[BUFSZ]; + struct obj *otmp; + if (!wizard || !(fp = fopen_wizkit_file())) return; + + while (fgets(buf, 4*BUFSZ, fp)) { + if ((ep = index(buf, '\n'))) *ep = '\0'; + if (buf[0]) { + otmp = readobjnam(buf, (struct obj *)0, FALSE); + if (otmp) { + if (otmp != &zeroobj) + otmp = addinv(otmp); + } else { + raw_printf("Bad wizkit item: \"%.50s\"", buf); + wait_synch(); + } + } + } + (void) fclose(fp); + return; +} + +#endif /*WIZARD*/ + /* ---------- END CONFIG FILE HANDLING ----------- */ /* ---------- BEGIN SCOREBOARD CREATION ----------- */ @@ -1536,7 +1701,7 @@ void check_recordfile(dir) const char *dir; { -#if defined(applec) || defined(__MWERKS__) +#if (defined(macintosh) && (defined(__SC__) || defined(__MRC__))) || defined(__MWERKS__) # pragma unused(dir) #endif const char *fq_record; @@ -1586,7 +1751,7 @@ const char *dir; if ((fd = open(fq_record, O_RDWR)) < 0) { /* try to create empty record */ -# if defined(AZTEC_C) || defined(_DCC) +# if defined(AZTEC_C) || defined(_DCC) || (defined(__GNUC__) && defined(__AMIGA__)) /* Aztec doesn't use the third argument */ /* DICE doesn't like it */ if ((fd = open(fq_record, O_CREAT|O_RDWR)) < 0) { diff --git a/src/fountain.c b/src/fountain.c index caeb33e..a8f4f85 100644 --- a/src/fountain.c +++ b/src/fountain.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)fountain.c 3.3 1999/08/16 */ +/* SCCS Id: @(#)fountain.c 3.4 2001/09/06 */ /* Copyright Scott R. Turner, srt@ucla, 10/27/86 */ /* NetHack may be freely redistributed. See license for details. */ @@ -55,7 +55,7 @@ dowaterdemon() /* Water demon */ /* Give those on low levels a (slightly) better chance of survival */ if (rnd(100) > (80 + level_difficulty())) { pline("Grateful for %s release, %s grants you a wish!", - his[pronoun_gender(mtmp)], he[pronoun_gender(mtmp)]); + mhis(mtmp), mhe(mtmp)); makewish(); mongone(mtmp); } else if (t_at(mtmp->mx, mtmp->my)) @@ -126,7 +126,7 @@ genericptr_t poolcnt; water_damage(level.objects[x][y], FALSE, TRUE); if ((mtmp = m_at(x, y)) != 0) - (void) minwater(mtmp); + (void) minliquid(mtmp); else newsym(x,y); } @@ -135,8 +135,9 @@ STATIC_OVL void dofindgem() /* Find a gem in the sparkling waters. */ { if (!Blind) You("spot a gem in the sparkling waters!"); + else You_feel("a gem here!"); (void) mksobj_at(rnd_class(DILITHIUM_CRYSTAL, LUCKSTONE-1), - u.ux, u.uy, FALSE); + u.ux, u.uy, FALSE, FALSE); levl[u.ux][u.uy].looted |= F_LOOTED; newsym(u.ux, u.uy); exercise(A_WIS, TRUE); /* a discovery! */ @@ -325,7 +326,7 @@ drinkfountain() pline("This water gives you bad breath!"); for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(!DEADMONSTER(mtmp)) - mtmp->mflee = 1; + monflee(mtmp, 0, FALSE, FALSE); } break; @@ -380,6 +381,7 @@ register struct obj *obj; obj->oerodeproof = TRUE; exercise(A_WIS, TRUE); } + update_inventory(); levl[u.ux][u.uy].typ = ROOM; levl[u.ux][u.uy].looted = 0; if(Invisible) newsym(u.ux, u.uy); @@ -437,12 +439,34 @@ register struct obj *obj; break; case 28: /* Strange feeling */ pline("An urge to take a bath overwhelms you."); +#ifndef GOLDOBJ if (u.ugold > 10) { u.ugold -= somegold() / 10; You("lost some of your gold in the fountain!"); levl[u.ux][u.uy].looted &= ~F_LOOTED; exercise(A_WIS, FALSE); } +#else + { + long money = money_cnt(invent); + struct obj *otmp; + if (money > 10) { + /* Amount to loose. Might get rounded up as fountains don't pay change... */ + money = somegold(money) / 10; + for (otmp = invent; otmp && money > 0; otmp = otmp->nobj) if (otmp->oclass == GOLD_CLASS) { + int denomination = objects[otmp->otyp].oc_cost; + long coin_loss = (money + denomination - 1) / denomination; + coin_loss = min(coin_loss, otmp->quan); + otmp->quan -= coin_loss; + money -= coin_loss * denomination; + if (!otmp->quan) delobj(otmp); + } + You("lost some of your money in the fountain!"); + levl[u.ux][u.uy].looted &= ~F_LOOTED; + exercise(A_WIS, FALSE); + } + } +#endif break; case 29: /* You see coins */ @@ -461,6 +485,7 @@ register struct obj *obj; newsym(u.ux,u.uy); break; } + update_inventory(); dryup(u.ux, u.uy, TRUE); } @@ -552,7 +577,7 @@ drinksink() case 10: pline("This water contains toxic wastes!"); if (!Unchanging) { You("undergo a freakish metamorphosis!"); - polyself(); + polyself(FALSE); } break; /* more odd messages --JJB */ diff --git a/src/hack.c b/src/hack.c index 8e00f62..b9e820f 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1,17 +1,18 @@ -/* SCCS Id: @(#)hack.c 3.3 2000/04/22 */ +/* SCCS Id: @(#)hack.c 3.4 2002/03/09 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" #ifdef OVL1 -static void NDECL(maybe_wail); +STATIC_DCL void NDECL(maybe_wail); #endif /*OVL1*/ STATIC_DCL int NDECL(moverock); STATIC_DCL int FDECL(still_chewing,(XCHAR_P,XCHAR_P)); #ifdef SINKS STATIC_DCL void NDECL(dosinkfall); #endif +STATIC_DCL void NDECL(findtravelpath); STATIC_DCL boolean FDECL(monstinroom, (struct permonst *,int)); STATIC_DCL void FDECL(move_update, (BOOLEAN_P)); @@ -132,16 +133,14 @@ moverock() switch(ttmp->ttyp) { case LANDMINE: if (rn2(10)) { - pline("KAABLAMM!!! %s triggers %s land mine.", - The(xname(otmp)), + pline("KAABLAMM!!! %s %s land mine.", + Tobjnam(otmp, "trigger"), ttmp->madeby_u ? "your" : "a"); obj_extract_self(otmp); place_object(otmp, rx, ry); - deltrap(ttmp); - del_engr_at(rx,ry); - scatter(rx,ry, 4, - MAY_DESTROY|MAY_HIT|MAY_FRACTURE|VIS_EFFECTS, - (struct obj *)0); + blow_up_landmine(ttmp); + /* if the boulder remains, it should fill the pit */ + fill_pit(u.ux, u.uy); if (cansee(rx,ry)) newsym(rx,ry); continue; } @@ -160,9 +159,15 @@ moverock() continue; case HOLE: case TRAPDOOR: - pline("%s %s and plugs a %s in the %s!", - The(xname(otmp)), - (ttmp->ttyp == TRAPDOOR) ? "triggers" : "falls into", + if (Blind) + pline("Kerplunk! You no longer feel %s.", + the(xname(otmp))); + else + pline("%s%s and %s a %s in the %s!", + Tobjnam(otmp, + (ttmp->ttyp == TRAPDOOR) ? "trigger" : "fall"), + (ttmp->ttyp == TRAPDOOR) ? nul : " into", + otense(otmp, "plug"), (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole", surface(rx, ry)); deltrap(ttmp); @@ -313,28 +318,36 @@ still_chewing(x,y) (void) memset((genericptr_t)&digging, 0, sizeof digging); if (!boulder && IS_ROCK(lev->typ) && !may_dig(x,y)) { - You("hurt your teeth on the hard stone."); + You("hurt your teeth on the %s.", + IS_TREE(lev->typ) ? "tree" : "hard stone"); nomul(0); return 1; } else if (digging.pos.x != x || digging.pos.y != y || !on_level(&digging.level, &u.uz)) { digging.down = FALSE; digging.chew = TRUE; + digging.warned = FALSE; digging.pos.x = x; digging.pos.y = y; assign_level(&digging.level, &u.uz); /* solid rock takes more work & time to dig through */ - digging.effort = (IS_ROCK(lev->typ) ? 30 : 60) + u.udaminc; + digging.effort = + (IS_ROCK(lev->typ) && !IS_TREE(lev->typ) ? 30 : 60) + u.udaminc; You("start chewing %s %s.", - boulder ? "on a" : "a hole in the", - boulder ? "boulder" : IS_ROCK(lev->typ) ? "rock" : "door"); + (boulder || IS_TREE(lev->typ)) ? "on a" : "a hole in the", + boulder ? "boulder" : + IS_TREE(lev->typ) ? "tree" : IS_ROCK(lev->typ) ? "rock" : "door"); + watch_dig((struct monst *)0, x, y, FALSE); return 1; } else if ((digging.effort += (30 + u.udaminc)) <= 100) { if (flags.verbose) You("%s chewing on the %s.", digging.chew ? "continue" : "begin", - boulder ? "boulder" : IS_ROCK(lev->typ) ? "rock" : "door"); + boulder ? "boulder" : + IS_TREE(lev->typ) ? "tree" : + IS_ROCK(lev->typ) ? "rock" : "door"); digging.chew = TRUE; + watch_dig((struct monst *)0, x, y, FALSE); return 1; } @@ -434,18 +447,19 @@ dosinkfall() register struct obj *obj; if (is_floater(youmonst.data) || (HLevitation & FROMOUTSIDE)) { - You("wobble unsteadily for a moment."); + You("wobble unsteadily for a moment."); } else { - You("crash to the floor!"); - losehp((rn1(10, 20 - (int)ACURR(A_CON))), - fell_on_sink, NO_KILLER_PREFIX); - exercise(A_DEX, FALSE); - for(obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) - if(obj->oclass == WEAPON_CLASS) { - You("fell on %s.",doname(obj)); - losehp(rnd(3), fell_on_sink, NO_KILLER_PREFIX); - exercise(A_CON, FALSE); - } + You("crash to the floor!"); + losehp(rn1(8, 25 - (int)ACURR(A_CON)), + fell_on_sink, NO_KILLER_PREFIX); + exercise(A_DEX, FALSE); + selftouch("Falling, you"); + for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) + if (obj->oclass == WEAPON_CLASS || is_weptool(obj)) { + You("fell on %s.", doname(obj)); + losehp(rnd(3), fell_on_sink, NO_KILLER_PREFIX); + exercise(A_CON, FALSE); + } } ELevitation &= ~W_ARTI; @@ -511,11 +525,205 @@ xchar x, y; #endif /* OVL1 */ #ifdef OVL3 +/* return TRUE if (dx,dy) is an OK place to move */ +boolean +test_move(ux, uy, dx, dy, test_only) +int ux, uy, dx, dy; +boolean test_only; +{ + int x = ux+dx; + int y = uy+dy; + register struct rm *tmpr = &levl[x][y]; + register struct rm *ust; + + /* + * Check for physical obstacles. First, the place we are going. + */ + if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) { + if (Blind && !test_only) feel_location(x,y); + if (Passes_walls && may_passwall(x,y)) { + ; /* do nothing */ + } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) { + /* Eat the rock. */ + if (!test_only && still_chewing(x,y)) return FALSE; + } else if (flags.autodig && !flags.run && !flags.nopick && + uwep && is_pick(uwep)) { + /* MRKR: Automatic digging when wielding the appropriate tool */ + if (!test_only) + (void) use_pick_axe2(uwep); + return FALSE; + } else { + if ( !test_only ) { + if (Is_stronghold(&u.uz) && is_db_wall(x,y)) + pline_The("drawbridge is up!"); + if (Passes_walls && !may_passwall(x,y) && In_sokoban(&u.uz)) + pline_The("Sokoban walls resist your ability."); + } + return FALSE; + } + } else if (IS_DOOR(tmpr->typ)) { + if (closed_door(x,y)) { + if (Blind && !test_only) feel_location(x,y); + if (Passes_walls) + ; /* do nothing */ + else if (can_ooze(&youmonst)) { + if ( !test_only ) You("ooze under the door."); + } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) { + /* Eat the door. */ + if (!test_only && still_chewing(x,y)) return FALSE; + } else { + if ( !test_only ) { + if (amorphous(youmonst.data)) + You("try to ooze under the door, but can't squeeze your possessions through."); + else if (x == ux || y == uy) { + if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) { +#ifdef STEED + if (u.usteed) + You_cant("lead %s through that closed door.", + x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + (char *)0, SUPPRESS_SADDLE, FALSE)); + else { +#else + pline("Ouch! You bump into a door."); + exercise(A_DEX, FALSE); +#endif +#ifdef STEED + } +#endif + } else pline("That door is closed."); + } + } + return FALSE; + } + } else if (dx && dy && !Passes_walls + && ((tmpr->doormask & ~D_BROKEN) +#ifdef REINCARNATION + || Is_rogue_level(&u.uz) +#endif + || block_door(x,y))) { + /* Diagonal moves into a door are not allowed. */ + if ( Blind && !test_only ) + feel_location(x,y); + return FALSE; + } + } + if (dx && dy + && bad_rock(youmonst.data,ux,y) && bad_rock(youmonst.data,x,uy)) { + /* Move at a diagonal. */ + if (In_sokoban(&u.uz)) { + if ( !test_only ) + You("cannot pass that way."); + return FALSE; + } + if (bigmonst(youmonst.data)) { + if ( !test_only ) + Your("body is too large to fit through."); + return FALSE; + } + if (invent && (inv_weight() + weight_cap() > 600)) { + if ( !test_only ) + You("are carrying too much to get through."); + return FALSE; + } + } + + ust = &levl[ux][uy]; + + /* Now see if other things block our way . . */ + if (dx && dy && !Passes_walls + && (IS_DOOR(ust->typ) && ((ust->doormask & ~D_BROKEN) +#ifdef REINCARNATION + || Is_rogue_level(&u.uz) +#endif + || block_entry(x, y)) + )) { + /* Can't move at a diagonal out of a doorway with door. */ + return FALSE; + } + + if (sobj_at(BOULDER,x,y) && (In_sokoban(&u.uz) || !Passes_walls)) { + if (!(Blind || Hallucination) && (flags.run >= 2)) + return FALSE; + if (!test_only) { + /* tunneling monsters will chew before pushing */ + if (tunnels(youmonst.data) && !needspick(youmonst.data) && + !In_sokoban(&u.uz)) { + if (still_chewing(x,y)) return FALSE; + } else + if (moverock() < 0) return FALSE; + } + /* test_only will assume you'll be able to push it when you get there... */ + } + + /* OK, it is a legal place to move. */ + return TRUE; +} + +static void findtravelpath() +{ + if ( u.tx != u.ux || u.ty != u.uy ) { + xchar travel[COLNO][ROWNO]; + xchar travelstepx[2][COLNO*ROWNO]; + xchar travelstepy[2][COLNO*ROWNO]; + int n=1; + int set=0; + int dia=1; + + (void) memset((genericptr_t)travel,0,sizeof(travel)); + + travelstepx[0][0] = u.tx; + travelstepy[0][0] = u.ty; + while ( n ) { + int i; + int nn=0; + for (i=0; i %d,%d by %d,%d\n",u.ux,u.uy,u.tx,u.ty,u.dx,u.dy); + */ + return; + } else { + /*printf("%d %d %d",isok(nx,ny), !travel[nx][ny], ACCESSIBLE(levl[nx][ny].typ));*/ + if ( !travel[nx][ny] ) { + travelstepx[1-set][nn]=nx; + travelstepy[1-set][nn]=ny; + travel[nx][ny]=dia; + nn++; + } + } + } + } + } + n = nn; + set = 1-set; + dia++; + } + + /* give up */ + } + + u.dx = 0; + u.dy = 0; + nomul(0); +} + void domove() { register struct monst *mtmp; - register struct rm *tmpr,*ust; + register struct rm *tmpr; register xchar x,y; struct trap *trap; int wtcap; @@ -526,6 +734,9 @@ domove() u_wipe_engr(rnd(5)); + if ( flags.travel ) + findtravelpath(); + if(((wtcap = near_capacity()) >= OVERLOADED || (wtcap > SLT_ENCUMBER && (Upolyd ? (u.mh < 5 && u.mh != u.mhmax) @@ -636,9 +847,12 @@ domove() * otherwise: * 7.5% chance of getting away. * [strength ought to be a factor] + * If holder is tame and there is no conflict, + * guaranteed escape. */ switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) { case 0: case 1: case 2: + pull_free: You("pull free from %s.", mon_nam(u.ustuck)); u.ustuck = 0; break; @@ -650,6 +864,9 @@ domove() } /*FALLTHRU*/ default: + if (u.ustuck->mtame && + !Conflict && !u.ustuck->mconf) + goto pull_free; You("cannot escape from %s!", mon_nam(u.ustuck)); nomul(0); return; @@ -702,7 +919,7 @@ domove() if(mtmp->m_ap_type && !Protection_from_shape_changers && !sensemon(mtmp)) stumble_onto_mimic(mtmp); - else if (mtmp->mpeaceful) + else if (mtmp->mpeaceful && !Hallucination) pline("Pardon me, %s.", m_monnam(mtmp)); else You("move right into %s.", mon_nam(mtmp)); @@ -735,7 +952,10 @@ domove() if (flags.forcefight || /* remembered an 'I' && didn't use a move command */ (glyph_is_invisible(levl[x][y].glyph) && !flags.nopick)) { - You("attack %s.", Underwater ? "empty water" : "thin air"); + char buf[BUFSZ]; + Sprintf(buf,"a vacant spot on the %s", surface(x,y)); + You("attack %s.", + !Underwater ? "thin air" : is_pool(x,y) ? "empty water" : buf); unmap_object(x, y); /* known empty -- remove 'I' if present */ newsym(x, y); nomul(0); @@ -748,7 +968,10 @@ domove() /* not attacking an animal, so we try to move */ #ifdef STEED if (u.usteed && !u.usteed->mcanmove && (u.dx || u.dy)) { - pline("%s won't move!", Monnam(u.usteed)); + pline("%s won't move!", + upstart(x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + (char *)0, SUPPRESS_SADDLE, FALSE))); nomul(0); return; } else @@ -770,20 +993,52 @@ domove() } else if (!(--u.utrap)) { You("%s to the edge of the pit.", (In_sokoban(&u.uz) && Levitation) ? - "struggle against the air currents and float" : "crawl"); + "struggle against the air currents and float" : +#ifdef STEED + u.usteed ? "ride" : +#endif + "crawl"); fill_pit(u.ux, u.uy); vision_full_recalc = 1; /* vision limits change */ - } else if (flags.verbose) + } else if (flags.verbose) { +#ifdef STEED + if (u.usteed) + Norep("%s is still in a pit.", + upstart(x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + (char *)0, SUPPRESS_SADDLE, FALSE))); + else +#endif Norep( (Hallucination && !rn2(5)) ? "You've fallen, and you can't get up." : "You are still in a pit." ); + } } else if (u.utraptype == TT_LAVA) { - if(flags.verbose) - Norep("You are stuck in the lava."); + if(flags.verbose) { + char *predicament = "stuck in the lava"; +#ifdef STEED + if (u.usteed) + Norep("%s is %s.", + upstart(x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + (char *)0, SUPPRESS_SADDLE, FALSE)), + predicament); + else +#endif + Norep("You are %s.", predicament); + } if(!is_lava(x,y)) { u.utrap--; if((u.utrap & 0xff) == 0) { - You("pull yourself to the edge of the lava."); +#ifdef STEED + if (u.usteed) + You("lead %s to the edge of the lava.", + x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + (char *)0, SUPPRESS_SADDLE, FALSE)); + else +#endif + You("pull yourself to the edge of the lava."); u.utrap = 0; } } @@ -795,128 +1050,81 @@ domove() return; } if(--u.utrap) { - if(flags.verbose) - Norep("You are stuck to the web."); - } else You("disentangle yourself."); + if(flags.verbose) { + char *predicament = "stuck to the web"; +#ifdef STEED + if (u.usteed) + Norep("%s is %s.", + upstart(x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + (char *)0, SUPPRESS_SADDLE, FALSE)), + predicament); + else +#endif + Norep("You are %s.", predicament); + } + } else { +#ifdef STEED + if (u.usteed) + pline("%s breaks out of the web.", + upstart(x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + (char *)0, SUPPRESS_SADDLE, FALSE))); + else +#endif + You("disentangle yourself."); + } } else if (u.utraptype == TT_INFLOOR) { if(--u.utrap) { - if(flags.verbose) - Norep("You are stuck in the %s.", - surface(u.ux, u.uy)); - } else You("finally wiggle free."); - } else { - if(flags.verbose) - Norep("You are caught in a bear trap."); - if((u.dx && u.dy) || !rn2(5)) u.utrap--; - } - return; - } - - - /* - * Check for physical obstacles. First, the place we are going. - */ - if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) { - if (Blind) feel_location(x,y); - if (Passes_walls && may_passwall(x,y)) { - ; /* do nothing */ - } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) { - /* Eat the rock. */ - if (still_chewing(x,y)) return; - } else { - if (Is_stronghold(&u.uz) && is_db_wall(x,y)) - pline_The("drawbridge is up!"); - flags.move = 0; - nomul(0); - return; - } - } else if (IS_DOOR(tmpr->typ)) { - if (closed_door(x,y)) { - if (Blind) feel_location(x,y); - if (Passes_walls) - ; /* do nothing */ - else if (can_ooze(&youmonst)) - You("ooze under the door."); - else if (tunnels(youmonst.data) && !needspick(youmonst.data)) { - /* Eat the door. */ - if (still_chewing(x,y)) return; + if(flags.verbose) { + char *predicament = "stuck in the"; +#ifdef STEED + if (u.usteed) + Norep("%s is %s %s.", + upstart(x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + (char *)0, SUPPRESS_SADDLE, FALSE)), + predicament, surface(u.ux, u.uy)); + else +#endif + Norep("You are %s %s.", predicament, surface(u.ux, u.uy)); + } + } else { +#ifdef STEED + if (u.usteed) + pline("%s finally wiggles free.", + upstart(x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + (char *)0, SUPPRESS_SADDLE, FALSE))); + else +#endif + You("finally wiggle free."); + } } else { - flags.move = 0; - if (amorphous(youmonst.data)) - You("try to ooze under the door, but can't squeeze your possessions through."); - else if (x == u.ux || y == u.uy) { - if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) { - pline("Ouch! You bump into a door."); - exercise(A_DEX, FALSE); - } else pline("That door is closed."); + if(flags.verbose) { + char *predicament = "caught in a bear trap"; +#ifdef STEED + if (u.usteed) + Norep("%s is %s.", + upstart(x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + (char *)0, SUPPRESS_SADDLE, FALSE)), + predicament); + else +#endif + Norep("You are %s.", predicament); } - nomul(0); - return; + if((u.dx && u.dy) || !rn2(5)) u.utrap--; } - } else if (u.dx && u.dy && !Passes_walls - && ((tmpr->doormask & ~D_BROKEN) -#ifdef REINCARNATION - || Is_rogue_level(&u.uz) -#endif - || block_door(x,y))) { - /* Diagonal moves into a door are not allowed. */ - if (Blind) feel_location(x,y); /* ?? */ - flags.move = 0; - nomul(0); return; - } } - if (u.dx && u.dy - && bad_rock(youmonst.data,u.ux,y) && bad_rock(youmonst.data,x,u.uy)) { - /* Move at a diagonal. */ - if (In_sokoban(&u.uz)) { - You("cannot pass that way."); - nomul(0); - return; - } - if (bigmonst(youmonst.data)) { - Your("body is too large to fit through."); - nomul(0); - return; - } - if (invent && (inv_weight() + weight_cap() > 600)) { - You("are carrying too much to get through."); - nomul(0); - return; - } - } - - ust = &levl[u.ux][u.uy]; - /* Now see if other things block our way . . */ - if (u.dx && u.dy && !Passes_walls - && (IS_DOOR(ust->typ) && ((ust->doormask & ~D_BROKEN) -#ifdef REINCARNATION - || Is_rogue_level(&u.uz) -#endif - || block_entry(x, y)) - )) { - /* Can't move at a diagonal out of a doorway with door. */ + if ( !test_move( u.ux, u.uy, x-u.ux, y-u.uy, 0 ) ) { flags.move = 0; nomul(0); return; } - if (sobj_at(BOULDER,x,y) && (In_sokoban(&u.uz) || !Passes_walls)) { - if (!(Blind || Hallucination) && (flags.run >= 2)) { - nomul(0); - flags.move = 0; - return; - } - /* tunneling monsters will chew before pushing */ - if (tunnels(youmonst.data) && !needspick(youmonst.data)) { - if (still_chewing(x,y)) return; - } else - if (moverock() < 0) return; - } - - /* OK, it is a legal place to move. */ - /* Move ball and chain. */ if (Punished) if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy, @@ -958,6 +1166,7 @@ domove() if (mtmp->mtrapped) { if (!rn2(mtmp->mtame)) { mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0; + if (mtmp->mleashed) m_unleash(mtmp, TRUE); growl(mtmp); } else { yelp(mtmp); @@ -974,15 +1183,19 @@ domove() /* can't swap places with pet pinned in a pit by a boulder */ u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */ } else { + char pnambuf[BUFSZ]; + + /* save its current description in case of polymorph */ + Strcpy(pnambuf, y_monnam(mtmp)); mtmp->mtrapped = 0; remove_monster(x, y); place_monster(mtmp, u.ux0, u.uy0); /* check for displacing it into pools and traps */ - switch (minwater(mtmp) ? 2 : mintrap(mtmp)) { + switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) { case 0: You("%s %s.", mtmp->mtame ? "displaced" : "frightened", - y_monnam(mtmp)); + pnambuf); break; case 1: /* trapped */ case 3: /* changed levels */ @@ -999,6 +1212,11 @@ domove() u.ugangr++; adjalign(-15); } + + /* you killed your pet by direct action. + * minliquid and mintrap don't know to do this + */ + u.uconduct.killer++; break; default: pline("that's strange, unknown mintrap result!"); @@ -1009,6 +1227,7 @@ domove() reset_occupations(); if (flags.run) { + if ( flags.run < 8 ) if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ) || IS_FURNITURE(tmpr->typ)) nomul(0); @@ -1111,10 +1330,23 @@ boolean pick; stillinwater:; if (!Levitation && !u.ustuck && !Flying) { /* limit recursive calls through teleds() */ - if(is_lava(u.ux,u.uy) && lava_effects()) - return; - if(is_pool(u.ux,u.uy) && !Wwalking && drown()) + if (is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) { +#ifdef STEED + if (u.usteed && !is_flyer(u.usteed->data) && + !is_floater(u.usteed->data) && + !is_clinger(u.usteed->data)) { + dismount_steed(Underwater ? + DISMOUNT_FELL : DISMOUNT_GENERIC); + /* dismount_steed() -> float_down() -> pickup() */ + if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz)) + pick = FALSE; + } else +#endif + if (is_lava(u.ux, u.uy)) { + if (lava_effects()) return; + } else if (!Wwalking && drown()) return; + } } check_special_room(FALSE); #ifdef SINKS @@ -1123,8 +1355,9 @@ stillinwater:; #endif if (pick && !in_steed_dismounting) (void) pickup(1); - if ((trap = t_at(u.ux,u.uy)) != 0) - dotrap(trap); /* fall into pit, arrow trap, etc. */ + /* if dismounting, we'll check again later */ + if ((trap = t_at(u.ux,u.uy)) != 0 && !in_steed_dismounting) + dotrap(trap, 0); /* fall into pit, arrow trap, etc. */ if((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) { mtmp->mundetected = mtmp->msleeping = 0; switch(mtmp->data->mlet) { @@ -1416,6 +1649,7 @@ dopickup() multi = 0; /* always reset */ /* uswallow case added by GAN 01/29/87 */ if(u.uswallow) { + if (!u.ustuck->minvent) { if (is_animal(u.ustuck->data)) { You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck))); pline("But it's kind of slimy, so you drop it."); @@ -1423,6 +1657,10 @@ dopickup() You("don't %s anything in here to pick up.", Blind ? "feel" : "see"); return(1); + } else { + int tmpcount = -count; + return loot_mon(u.ustuck, &tmpcount, (boolean *)0); + } } if(is_pool(u.ux, u.uy)) { if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data) @@ -1476,16 +1714,16 @@ lookaround() register struct monst *mtmp; register struct trap *trap; - /* Grid bugs stop if trying to move diagonal, even if blind. Maybe */ - /* they polymorphed while in the middle of a long move. */ - if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) { - nomul(0); - return; - } + /* Grid bugs stop if trying to move diagonal, even if blind. Maybe */ + /* they polymorphed while in the middle of a long move. */ + if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) { + nomul(0); + return; + } - if(Blind || flags.run == 0) return; - for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) { - if(!isok(x,y)) continue; + if(Blind || flags.run == 0) return; + for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) { + if(!isok(x,y)) continue; if(u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy) continue; @@ -1513,7 +1751,7 @@ lookaround() } else if (levl[x][y].typ == CORR) { bcorr: if(levl[u.ux][u.uy].typ != ROOM) { - if(flags.run == 1 || flags.run == 3) { + if(flags.run == 1 || flags.run == 3 || flags.run == 8) { i = dist2(x,y,u.ux+u.dx,u.uy+u.dy); if(i > 2) continue; if(corrct == 1 && dist2(x,y,x0,y0) != 1) @@ -1546,6 +1784,7 @@ lookaround() continue; } else { /* e.g. objects or trap or stairs */ if(flags.run == 1) goto bcorr; + if(flags.run == 8) continue; if(mtmp) continue; /* d */ if(((x == u.ux - u.dx) && (y != u.uy + u.dy)) || ((y == u.uy - u.dy) && (x != u.ux + u.dx))) @@ -1557,8 +1796,9 @@ lookaround() } /* end for loops */ if(corrct > 1 && flags.run == 2) goto stop; - if((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 && - (corrct == 1 || (corrct == 2 && i0 == 1))) { + if((flags.run == 1 || flags.run == 3 || flags.run == 8) && + !noturn && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1))) + { /* make sure that we do not turn too far */ if(i0 == 2) { if(u.dx == y0-u.uy && u.dy == u.ux-x0) @@ -1621,7 +1861,7 @@ nomul(nval) u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */ u.usleep = 0; multi = nval; - flags.mv = flags.run = 0; + flags.travel = flags.mv = flags.run = 0; } /* called when a non-movement, multi-turn action has completed */ @@ -1641,7 +1881,7 @@ const char *msg_override; #endif /* OVL2 */ #ifdef OVL1 -static void +STATIC_OVL void maybe_wail() { static short powers[] = { TELEPORT, SEE_INVIS, POISON_RES, COLD_RES, @@ -1745,17 +1985,24 @@ int inv_weight() { register struct obj *otmp = invent; - register int wt; + register int wt = 0; +#ifndef GOLDOBJ /* when putting stuff into containers, gold is inserted at the head of invent for easier manipulation by askchain & co, but it's also retained in u.ugold in order to keep the status line accurate; we mustn't add its weight in twice under that circumstance */ wt = (otmp && otmp->oclass == GOLD_CLASS) ? 0 : (int)((u.ugold + 50L) / 100L); - +#endif while (otmp) { +#ifndef GOLDOBJ if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data)) +#else + if (otmp->oclass == GOLD_CLASS) + wt += (int)(((long)otmp->quan + 50L) / 100L); + else if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data)) +#endif wt += otmp->owt; otmp = otmp->nobj; } @@ -1823,6 +2070,22 @@ inv_cnt() return(ct); } +#ifdef GOLDOBJ +/* Counts the money in an object chain. */ +/* Intended use is for your or some monsters inventory, */ +/* now that u.gold/m.gold is gone.*/ +/* Counting money in a container might be possible too. */ +long money_cnt(otmp) +struct obj *otmp; +{ + while(otmp) { + /* Must change when silver & copper is implemented: */ + if (otmp->oclass == GOLD_CLASS) return otmp->quan; + otmp = otmp->nobj; + } + return 0; +} +#endif #endif /* OVLB */ /*hack.c*/ diff --git a/src/hacklib.c b/src/hacklib.c index 0a71929..1e8aed6 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)hacklib.c 3.3 99/04/10 */ +/* SCCS Id: @(#)hacklib.c 3.4 1999/04/10 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Robert Patrick Rankin, 1991 */ /* NetHack may be freely redistributed. See license for details. */ @@ -15,6 +15,7 @@ NetHack, except that rounddiv may call panic(). char highc (char) char lowc (char) char * lcase (char *) + char * upstart (char *) char * mungspaces (char *) char * eos (char *) char * s_suffix (const char *) @@ -92,6 +93,14 @@ lcase(s) /* convert a string into all lowercase */ return s; } +char * +upstart(s) /* convert first character of a string to uppercase */ + char *s; +{ + if (s) *s = highc(*s); + return s; +} + /* remove excess whitespace from a string buffer (in place) */ char * mungspaces(bp) @@ -429,7 +438,7 @@ fuzzymatch(s1, s2, ignore_chars, caseblind) * - determination of what files are "very old" */ -#if defined(AMIGA) && !defined(AZTEC_C) && !defined(__SASC_60) && !defined(_DCC) +#if defined(AMIGA) && !defined(AZTEC_C) && !defined(__SASC_60) && !defined(_DCC) && !defined(__GNUC__) extern struct tm *FDECL(localtime,(time_t *)); #endif static struct tm *NDECL(getlt); @@ -443,7 +452,7 @@ setrandom() #ifdef RANDOM /* srandom() from sys/share/random.c */ srandom((unsigned int) time((time_t *)0)); #else -# if defined(BSD) || defined(ULTRIX) || defined(CYGWIN32) /* system srandom() */ +# if defined(__APPLE__) || defined(BSD) || defined(ULTRIX) || defined(CYGWIN32) /* system srandom() */ # ifdef BSD # if defined(SUNOS4) (void) diff --git a/src/invent.c b/src/invent.c index c97b822..a80a2cc 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)invent.c 3.3 2000/04/12 */ +/* SCCS Id: @(#)invent.c 3.4 2002/02/23 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -16,13 +16,17 @@ STATIC_DCL boolean FDECL(worn_wield_only, (struct obj *)); STATIC_DCL boolean FDECL(only_here, (struct obj *)); #endif /* OVL1 */ STATIC_DCL void FDECL(compactify,(char *)); +STATIC_DCL boolean FDECL(taking_off, (const char *)); +STATIC_DCL boolean FDECL(putting_on, (const char *)); STATIC_PTR int FDECL(ckunpaid,(struct obj *)); +STATIC_PTR int FDECL(ckvalidcat,(struct obj *)); +static char FDECL(display_pickinv, (const char *,BOOLEAN_P, long *)); #ifdef OVLB STATIC_DCL boolean FDECL(this_type_only, (struct obj *)); STATIC_DCL void NDECL(dounpaid); STATIC_DCL struct obj *FDECL(find_unpaid,(struct obj *,struct obj **)); STATIC_DCL void FDECL(menu_identify, (int)); -static boolean FDECL(tool_in_use, (struct obj *)); +STATIC_DCL boolean FDECL(tool_in_use, (struct obj *)); #endif /* OVLB */ STATIC_DCL char FDECL(obj_to_let,(struct obj *)); @@ -49,6 +53,14 @@ register struct obj *otmp; register int i; register struct obj *obj; +#ifdef GOLDOBJ + /* There is only one of these in inventory... */ + if (otmp->oclass == GOLD_CLASS) { + otmp->invlet = GOLD_SYM; + return; + } +#endif + for(i = 0; i < 52; i++) inuse[i] = FALSE; for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) { i = obj->invlet; @@ -164,7 +176,11 @@ struct obj **potmp, **pobj; / (otmp->quan + obj->quan); otmp->quan += obj->quan; - otmp->owt += obj->owt; +#ifdef GOLDOBJ + /* temporary special case for gold objects!!!! */ +#endif + if (otmp->oclass == GOLD_CLASS) otmp->owt = weight(otmp); + else otmp->owt += obj->owt; if(!otmp->onamelth && obj->onamelth) otmp = *potmp = oname(otmp, ONAME(obj)); obj_extract_self(obj); @@ -174,21 +190,40 @@ struct obj **potmp, **pobj; if (obj->timed) obj_stop_timers(obj); /* follows lights */ /* fixup for `#adjust' merging wielded darts, daggers, &c */ - if (obj->owornmask) { - otmp->owornmask |= obj->owornmask; - /* (it isn't necessary to "unwear" `obj' first) */ - if (carried(otmp)) - setworn(otmp, otmp->owornmask); + if (obj->owornmask && carried(otmp)) { + long wmask = otmp->owornmask | obj->owornmask; + + /* Both the items might be worn in competing slots; + merger preference (regardless of which is which): + primary weapon + alternate weapon -> primary weapon; + primary weapon + quiver -> primary weapon; + alternate weapon + quiver -> alternate weapon. + (Prior to 3.3.0, it was not possible for the two + stacks to be worn in different slots and `obj' + didn't need to be unworn when merging.) */ + if (wmask & W_WEP) wmask = W_WEP; + else if (wmask & W_SWAPWEP) wmask = W_SWAPWEP; + else if (wmask & W_QUIVER) wmask = W_QUIVER; + else { + impossible("merging strangely worn items (%lx)", wmask); + wmask = otmp->owornmask; + } + if ((otmp->owornmask & ~wmask) != 0L) setnotworn(otmp); + setworn(otmp, wmask); + setnotworn(obj); + } #if 0 - /* (this should never be necessary, since items - already in a monster's inventory don't ever get - merged into other objects [only vice versa]) */ - else if (mcarried(otmp)) { - if (obj == MON_WEP(otmp->ocarry)) - MON_WEP(otmp->ocarry) = otmp; - } -#endif + /* (this should not be necessary, since items + already in a monster's inventory don't ever get + merged into other objects [only vice versa]) */ + else if (obj->owornmask && mcarried(otmp)) { + if (obj == MON_WEP(otmp->ocarry)) { + MON_WEP(otmp->ocarry) = otmp; + otmp->owornmask = W_WEP; + } } +#endif /*0*/ + obfree(obj,otmp); /* free(obj), bill->otmp */ return(1); } @@ -211,8 +246,11 @@ addinv_core1(obj) struct obj *obj; { if (obj->oclass == GOLD_CLASS) { +#ifndef GOLDOBJ u.ugold += obj->quan; +#else flags.botl = 1; +#endif } else if (obj->otyp == AMULET_OF_YENDOR) { if (u.uhave.amulet) impossible("already have amulet?"); u.uhave.amulet = 1; @@ -269,11 +307,14 @@ struct obj *obj; if (obj->where != OBJ_FREE) panic("addinv: obj not free"); + obj->no_charge = 0; /* not meaningful for invent */ addinv_core1(obj); +#ifndef GOLDOBJ /* if handed gold, we're done */ if (obj->oclass == GOLD_CLASS) return obj; +#endif /* merge if possible; find end of chain in the process */ for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj) @@ -360,10 +401,7 @@ const char *drop_fmt, *drop_arg, *hold_msg; if (drop_fmt) pline(drop_fmt, drop_arg); /* undo any merge which took place */ if (obj->quan > oquan) { - struct obj *otmp = splitobj(obj, oquan); - /* might have merged with weapon */ - if (obj->owornmask) - setworn(otmp, obj->owornmask); + obj = splitobj(obj, oquan); } dropx(obj); } else { @@ -418,7 +456,9 @@ freeinv_core(obj) struct obj *obj; { if (obj->oclass == GOLD_CLASS) { +#ifndef GOLDOBJ u.ugold -= obj->quan; +#endif flags.botl = 1; return; } else if (obj->otyp == AMULET_OF_YENDOR) { @@ -537,6 +577,14 @@ register int type; return((struct obj *) 0); } +const char * +currency(amount) +long amount; +{ + if (amount == 1L) return "zorkmid"; + else return "zorkmids"; +} + boolean have_lizard() { @@ -593,7 +641,7 @@ register int x, y; #endif /* OVL2 */ #ifdef OVLB - +#ifndef GOLDOBJ /* Make a gold object from the hero's gold. */ struct obj * mkgoldobj(q) @@ -608,7 +656,7 @@ register long q; flags.botl = 1; return(otmp); } - +#endif #endif /* OVLB */ #ifdef OVL1 @@ -642,11 +690,31 @@ register char *buf; } } +/* match the prompt for either 'T' or 'R' command */ +STATIC_OVL boolean +taking_off(action) +const char *action; +{ + return !strcmp(action, "take off") || !strcmp(action, "remove"); +} + +/* match the prompt for either 'W' or 'P' command */ +STATIC_OVL boolean +putting_on(action) +const char *action; +{ + return !strcmp(action, "wear") || !strcmp(action, "put on"); +} + /* * getobj returns: * struct obj *xxx: object to do something with. * (struct obj *) 0 error return: no object. * &zeroobj explicitly no object (as in w-). +#ifdef GOLDOBJ +!!!! test if gold can be used in unusual ways (eaten etc.) +!!!! may be able to remove "usegold" +#endif */ struct obj * getobj(let,word) @@ -659,10 +727,10 @@ register const char *let,*word; register int foo = 0; register char *bp = buf; xchar allowcnt = 0; /* 0, 1 or 2 */ - boolean allowgold = FALSE, usegold = FALSE; - /* Two possibilities: they can't use gold because it's illegal, - * or they can't use gold because they don't have any. - */ +#ifndef GOLDOBJ + boolean allowgold = FALSE; /* can't use gold because they don't have any */ +#endif + boolean usegold = FALSE; /* can't use gold because its illegal */ boolean allowall = FALSE; boolean allownone = FALSE; xchar foox = 0; @@ -671,12 +739,20 @@ register const char *let,*word; long dummymask; if(*let == ALLOW_COUNT) let++, allowcnt = 1; +#ifndef GOLDOBJ if(*let == GOLD_CLASS) let++, usegold = TRUE, allowgold = (u.ugold ? TRUE : FALSE); +#else + if(*let == GOLD_CLASS) let++, usegold = TRUE; +#endif /* Equivalent of an "ugly check" for gold */ if (usegold && !strcmp(word, "eat") && !metallivorous(youmonst.data)) +#ifndef GOLDOBJ usegold = allowgold = FALSE; +#else + usegold = FALSE; +#endif if(*let == ALL_CLASSES) let++, allowall = TRUE; if(*let == ALLOW_NONE) let++, allownone = TRUE; @@ -689,26 +765,36 @@ register const char *let,*word; if(allowall && !strcmp(word, "read")) allowall = FALSE; if(allownone) *bp++ = '-'; +#ifndef GOLDOBJ if(allowgold) *bp++ = def_oc_syms[GOLD_CLASS]; +#endif if(bp > buf && bp[-1] == '-') *bp++ = ' '; ap = altlets; ilet = 'a'; for (otmp = invent; otmp; otmp = otmp->nobj) { - if (!flags.invlet_constant) otmp->invlet = ilet; /* reassign() */ - if (!*let || index(let, otmp->oclass)) { + if (!flags.invlet_constant) +#ifdef GOLDOBJ + if (otmp->invlet != GOLD_SYM) /* don't reassign this */ +#endif + otmp->invlet = ilet; /* reassign() */ + if (!*let || index(let, otmp->oclass) +#ifdef GOLDOBJ + || (usegold && otmp->invlet == GOLD_SYM) +#endif + ) { register int otyp = otmp->otyp; bp[foo++] = otmp->invlet; /* ugly check: remove inappropriate things */ - if((!strcmp(word, "take off") && + if ((taking_off(word) && (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) || (otmp==uarm && uarmc) #ifdef TOURIST || (otmp==uarmu && (uarm || uarmc)) #endif )) - || (!strcmp(word, "wear") && + || (putting_on(word) && (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))) /* already worn */ || (!strcmp(word, "wield") && @@ -723,7 +809,7 @@ register const char *let,*word; /* Second ugly check; unlike the first it won't trigger an * "else" in "you don't have anything else to ___". */ - else if ((!strcmp(word, "wear") && + else if ((putting_on(word) && ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING) || (otmp->oclass == TOOL_CLASS && otyp != BLINDFOLD && otyp != TOWEL && otyp != LENSES))) @@ -739,9 +825,10 @@ register const char *let,*word; || (!strcmp(word, "tin") && (otyp != CORPSE || !tinnable(otmp))) || (!strcmp(word, "rub") && - (otmp->oclass == TOOL_CLASS && - otyp != OIL_LAMP && otyp != MAGIC_LAMP && - otyp != BRASS_LANTERN)) + ((otmp->oclass == TOOL_CLASS && + otyp != OIL_LAMP && otyp != MAGIC_LAMP && + otyp != BRASS_LANTERN) || + (otmp->oclass == GEM_CLASS && !is_graystone(otmp)))) || ((!strcmp(word, "use or apply") || !strcmp(word, "untrap with")) && /* Picks, axes, pole-weapons, bullwhips */ @@ -751,7 +838,8 @@ register const char *let,*word; /* only applicable potion is oil, and it will only be offered as a choice when already discovered */ (otyp != POT_OIL || !otmp->dknown || - !objects[POT_OIL].oc_name_known)))) + !objects[POT_OIL].oc_name_known)) + || (otmp->oclass == GEM_CLASS && !is_graystone(otmp)))) || (!strcmp(word, "invoke") && (!otmp->oartifact && !objects[otyp].oc_unique && (otyp != FAKE_AMULET_OF_YENDOR || otmp->known) && @@ -767,7 +855,7 @@ register const char *let,*word; ) foo--; /* ugly check for unworn armor that can't be worn */ - else if (!strcmp(word, "wear") && *let == ARMOR_CLASS && + else if (putting_on(word) && *let == ARMOR_CLASS && !canwearobj(otmp, &dummymask, FALSE)) { foo--; allowall = TRUE; @@ -794,7 +882,11 @@ register const char *let,*word; compactify(bp); *ap = '\0'; +#ifndef GOLDOBJ if(!foo && !allowall && !allowgold && !allownone) { +#else + if(!foo && !allowall && !allownone) { +#endif You("don't have anything %sto %s.", foox ? "else " : "", word); return((struct obj *)0); @@ -836,13 +928,15 @@ register const char *let,*word; return(allownone ? &zeroobj : (struct obj *) 0); } if(ilet == def_oc_syms[GOLD_CLASS]) { - if(!usegold){ - You("cannot %s gold.", word); - return(struct obj *)0; + if (!usegold) { + You("cannot %s gold.", word); + return(struct obj *)0; +#ifndef GOLDOBJ } else if (!allowgold) { You("are not carrying any gold."); return(struct obj *)0; - } +#endif + } if(cnt == 0 && prezero) return((struct obj *)0); /* Historic note: early Nethack had a bug which was * first reported for Larn, where trying to drop 2^32-n @@ -855,28 +949,26 @@ register const char *let,*word; return(struct obj *)0; } +#ifndef GOLDOBJ if(!(allowcnt == 2 && cnt < u.ugold)) cnt = u.ugold; return(mkgoldobj(cnt)); - } - if(allowcnt == 2 && !strcmp(word,"throw")) { - /* permit counts for throwing gold, but don't accept - * counts for other things since the throw code will - * split off a single item anyway */ - allowcnt = 1; - if(cnt == 0 && prezero) return((struct obj *)0); - if(cnt > 1) { - You("can only throw one item at a time."); - continue; - } +#endif } if(ilet == '?' || ilet == '*') { char *allowed_choices = (ilet == '?') ? lets : (char *)0; + long ctmp = 0; if (ilet == '?' && !*lets && *altlets) allowed_choices = altlets; - ilet = display_inventory(allowed_choices, TRUE); + ilet = display_pickinv(allowed_choices, TRUE, + allowcnt ? &ctmp : (long *)0); if(!ilet) continue; + if (allowcnt && ctmp >= 0) { + cnt = ctmp; + if (!cnt) prezero = TRUE; + allowcnt = 2; + } if(ilet == '\033') { if(flags.verbose) pline(Never_mind); @@ -884,6 +976,23 @@ register const char *let,*word; } /* they typed a letter (not a space) at the prompt */ } + if(allowcnt == 2 && !strcmp(word,"throw")) { + /* permit counts for throwing gold, but don't accept + * counts for other things since the throw code will + * split off a single item anyway */ +#ifdef GOLDOBJ + if (ilet != def_oc_syms[GOLD_CLASS]) +#endif + allowcnt = 1; + if(cnt == 0 && prezero) return((struct obj *)0); + if(cnt > 1) { + You("can only throw one item at a time."); + continue; + } + } +#ifdef GOLDOBJ + flags.botl = 1; /* May have changed the amount of money */ +#endif #ifdef REDO savech(ilet); #endif @@ -905,25 +1014,26 @@ register const char *let,*word; } break; } - if(!allowall && let && !index(let,otmp->oclass)) { + if(!allowall && let && !index(let,otmp->oclass) +#ifdef GOLDOBJ + && !(usegold && otmp->oclass == GOLD_CLASS) +#endif + ) { pline(silly_thing_to, word); return((struct obj *)0); } if(allowcnt == 2) { /* cnt given */ - if(cnt == 0) return (struct obj *)0; - if(cnt != otmp->quan) { - register struct obj *obj = splitobj(otmp, cnt); + if(cnt == 0) return (struct obj *)0; + if(cnt != otmp->quan) { + otmp = splitobj(otmp, cnt); /* Very ugly kludge necessary to prevent someone from trying * to drop one of several loadstones and having the loadstone * now be separate. */ - if (!strcmp(word, "drop") && - obj->otyp == LOADSTONE && obj->cursed) - otmp->corpsenm = obj->invlet; - if(otmp == uwep) setuwep(obj); - else if (otmp == uquiver) setuqwep(obj); - if (otmp == uswapwep) setuswapwep(obj); - } + if (!strcmp(word, "drop") && + otmp->otyp == LOADSTONE && otmp->cursed) + otmp->corpsenm = otmp->invlet; + } } return(otmp); } @@ -931,6 +1041,14 @@ register const char *let,*word; #endif /* OVL1 */ #ifdef OVLB +STATIC_PTR int +ckvalidcat(otmp) +register struct obj *otmp; +{ + /* use allow_category() from pickup.c */ + return((int)allow_category(otmp)); +} + STATIC_PTR int ckunpaid(otmp) register struct obj *otmp; @@ -966,26 +1084,38 @@ static NEARDATA const char removeables[] = /* Takeoff (A). Return the number of times fn was called successfully */ /* If combo is TRUE, we just use this to get a category list */ int -ggetobj(word, fn, mx, combo) +ggetobj(word, fn, mx, combo, resultflags) const char *word; int FDECL((*fn),(OBJ_P)), mx; boolean combo; /* combination menu flag */ +unsigned *resultflags; { int FDECL((*ckfn),(OBJ_P)) = (int FDECL((*),(OBJ_P))) 0; boolean FDECL((*filter),(OBJ_P)) = (boolean FDECL((*),(OBJ_P))) 0; boolean takeoff, ident, allflag, m_seen; +#ifndef GOLDOBJ int oletct, iletct, allowgold, unpaid, oc_of_sym; +#else + int oletct, iletct, unpaid, oc_of_sym; +#endif char sym, *ip, olets[MAXOCLASSES+5], ilets[MAXOCLASSES+5]; char buf[BUFSZ], qbuf[QBUFSZ]; + if (resultflags) *resultflags = 0; +#ifndef GOLDOBJ allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0; +#endif takeoff = ident = allflag = m_seen = FALSE; +#ifndef GOLDOBJ if(!invent && !allowgold){ +#else + if(!invent){ +#endif You("have nothing to %s.", word); return(0); } - if (combo) add_valid_menu_class(0); /* reset */ - if (!strcmp(word, "take off")) { + add_valid_menu_class(0); /* reset */ + if (taking_off(word)) { takeoff = TRUE; filter = is_worn; } else if (!strcmp(word, "identify")) { @@ -994,7 +1124,11 @@ boolean combo; /* combination menu flag */ } iletct = collect_obj_classes(ilets, invent, - FALSE, (allowgold != 0), filter); + FALSE, +#ifndef GOLDOBJ + (allowgold != 0), +#endif + filter); unpaid = count_unpaid(invent); if (ident && !iletct) { @@ -1002,6 +1136,10 @@ boolean combo; /* combination menu flag */ } else if (!takeoff && (unpaid || invent)) { ilets[iletct++] = ' '; if (unpaid) ilets[iletct++] = 'u'; + if (count_buc(invent, BUC_BLESSED)) ilets[iletct++] = 'B'; + if (count_buc(invent, BUC_UNCURSED)) ilets[iletct++] = 'U'; + if (count_buc(invent, BUC_CURSED)) ilets[iletct++] = 'C'; + if (count_buc(invent, BUC_UNKNOWN)) ilets[iletct++] = 'X'; if (invent) ilets[iletct++] = 'a'; } else if (takeoff && invent) { ilets[iletct++] = ' '; @@ -1051,18 +1189,34 @@ boolean combo; /* combination menu flag */ } if (oc_of_sym == GOLD_CLASS && !combo) { +#ifndef GOLDOBJ if (allowgold == 1) (*fn)(mkgoldobj(u.ugold)); else if (!u.ugold) You("have no gold."); allowgold = 2; +#else + flags.botl = 1; +#endif } else if (sym == 'a') { allflag = TRUE; } else if (sym == 'A') { /* same as the default */ ; - } else if (sym == 'u' || sym == 'U') { + } else if (sym == 'u') { add_valid_menu_class('u'); ckfn = ckunpaid; + } else if (sym == 'B') { + add_valid_menu_class('B'); + ckfn = ckvalidcat; + } else if (sym == 'U') { + add_valid_menu_class('U'); + ckfn = ckvalidcat; + } else if (sym == 'C') { + add_valid_menu_class('C'); + ckfn = ckvalidcat; + } else if (sym == 'X') { + add_valid_menu_class('X'); + ckfn = ckvalidcat; } else if (sym == 'm') { m_seen = TRUE; } else if (oc_of_sym == MAXOCLASSES) { @@ -1080,10 +1234,27 @@ boolean combo; /* combination menu flag */ return (allflag || (!oletct && ckfn != ckunpaid)) ? -2 : -3; else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag) return 0; +#ifndef GOLDOBJ else if (allowgold == 2 && !oletct) return 1; /* you dropped gold (or at least tried to) */ - else - return askchain(&invent, olets, allflag, fn, ckfn, mx, word); + else { +#else + else /*!!!! if (allowgold == 2 && !oletct) + !!!! return 1; you dropped gold (or at least tried to) + !!!! test gold dropping + else*/ { +#endif + int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word); + /* + * askchain() has already finished the job in this case + * so set a special flag to convey that back to the caller + * so that it won't continue processing. + * Fix for bug C331-1 reported by Irina Rempt-Drijfhout. + */ + if (combo && allflag && resultflags) + *resultflags |= ALL_FINISHED; + return cnt; + } } /* @@ -1106,7 +1277,7 @@ register int FDECL((*fn),(OBJ_P)), FDECL((*ckfn),(OBJ_P)); boolean takeoff, nodot, ident, ininv; char qbuf[QBUFSZ]; - takeoff = !strcmp(word, "take off"); + takeoff = taking_off(word); ident = !strcmp(word, "identify"); nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") || ident || takeoff); @@ -1128,7 +1299,7 @@ register int FDECL((*fn),(OBJ_P)), FDECL((*ckfn),(OBJ_P)); if (ckfn && !(*ckfn)(otmp)) continue; if (!allflag) { Strcpy(qbuf, !ininv ? doname(otmp) : - xprname(otmp, (char *)0, ilet, !nodot, 0L)); + xprname(otmp, (char *)0, ilet, !nodot, 0L, 0L)); Strcat(qbuf, "?"); sym = (takeoff || ident || otmp->quan < 2L) ? nyaq(qbuf) : nyNaq(qbuf); @@ -1148,13 +1319,7 @@ register int FDECL((*fn),(OBJ_P)), FDECL((*ckfn),(OBJ_P)); sym = 'y'; if (yn_number < otmp->quan && !welded(otmp) && (!otmp->cursed || otmp->otyp != LOADSTONE)) { - struct obj *otmpx = splitobj(otmp, yn_number); - if (!otmpx || otmpx->nobj != otmp2) - impossible("bad object split in askchain"); - /* assume other worn items aren't mergable */ - if (otmp == uwep) setuwep(otmpx); - if (otmp == uquiver) setuqwep(otmpx); - if (otmp == uswapwep) setuswapwep(otmpx); + otmp = splitobj(otmp, yn_number); } } } @@ -1272,7 +1437,7 @@ int id_limit; n = 0; if (flags.menu_style == MENU_TRADITIONAL) do { - n = ggetobj("identify", identify, id_limit, FALSE); + n = ggetobj("identify", identify, id_limit, FALSE, (unsigned *)0); if (n < 0) break; /* quit or no eligible items */ } while ((id_limit -= n) > 0); if (n == 0 || n < -1) @@ -1288,8 +1453,10 @@ STATIC_OVL char obj_to_let(obj) /* should of course only be called for things in invent */ register struct obj *obj; { +#ifndef GOLDOBJ if (obj->oclass == GOLD_CLASS) return GOLD_SYM; +#endif if (!flags.invlet_constant) { obj->invlet = NOINVSYM; reassign(); @@ -1307,32 +1474,37 @@ const char *prefix; register struct obj *obj; long quan; { - long savequan = obj->quan; - if (quan) obj->quan = quan; if (!prefix) prefix = ""; pline("%s%s%s", prefix, *prefix ? " " : "", - xprname(obj, (char *)0, obj_to_let(obj), TRUE, 0L)); - if (quan) obj->quan = savequan; + xprname(obj, (char *)0, obj_to_let(obj), TRUE, 0L, quan)); } #endif /* OVL2 */ #ifdef OVL1 char * -xprname(obj, txt, let, dot, cost) +xprname(obj, txt, let, dot, cost, quan) struct obj *obj; const char *txt; /* text to print instead of obj */ char let; /* inventory letter */ boolean dot; /* append period; (dot && cost => Iu) */ long cost; /* cost (for inventory of unpaid or expended items) */ +long quan; /* if non-0, print this quantity, not obj->quan */ { #ifdef LINT /* handle static char li[BUFSZ]; */ - char li[BUFSZ]; + char li[BUFSZ]; #else - static char li[BUFSZ]; + static char li[BUFSZ]; #endif - boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM; + boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM; + long savequan = 0; + + if (quan && obj) { + savequan = obj->quan; + obj->quan = quan; + } + /* * If let is: * * Then obj == null and we are printing a total amount. @@ -1340,18 +1512,22 @@ long cost; /* cost (for inventory of unpaid or expended items) */ */ if (cost != 0 || let == '*') { /* if dot is true, we're doing Iu, otherwise Ix */ - Sprintf(li, "%c - %-45s %6ld zorkmid%s", + Sprintf(li, "%c - %-45s %6ld %s", (dot && use_invlet ? obj->invlet : let), - (txt ? txt : doname(obj)), cost, plur(cost)); - } else if (obj->oclass == GOLD_CLASS) { + (txt ? txt : doname(obj)), cost, currency(cost)); +#ifndef GOLDOBJ + } else if (obj && obj->oclass == GOLD_CLASS) { Sprintf(li, "%ld gold piece%s%s", obj->quan, plur(obj->quan), (dot ? "." : "")); +#endif } else { /* ordinary inventory display or pickup message */ Sprintf(li, "%c - %s%s", (use_invlet ? obj->invlet : let), (txt ? txt : doname(obj)), (dot ? "." : "")); } + if (savequan) obj->quan = savequan; + return li; } @@ -1400,16 +1576,15 @@ find_unpaid(list, last_found) } /* - * If lets == NULL or "", list all objects in the inventory. Otherwise, - * list all objects with object classes that match the order in lets. - * - * Returns the letter identifier of a selected item, or 0 if nothing - * was selected. + * Internal function used by display_inventory and getobj that can display + * inventory and return a count as well as a letter. If out_cnt is not null, + * any count returned from the menu selection is placed here. */ -char -display_inventory(lets, want_reply) +static char +display_pickinv(lets, want_reply, out_cnt) register const char *lets; boolean want_reply; +long* out_cnt; { struct obj *otmp; char ilet, ret; @@ -1441,7 +1616,11 @@ boolean want_reply; to here is short circuited away. */ if (!invent && !(flags.perm_invent && !lets && !want_reply)) { +#ifndef GOLDOBJ pline("Not carrying anything%s.", u.ugold ? " except gold" : ""); +#else + pline("Not carrying anything."); +#endif return 0; } @@ -1456,8 +1635,8 @@ boolean want_reply; for (otmp = invent; otmp; otmp = otmp->nobj) { if (otmp->invlet == lets[0]) { ret = message_menu(lets[0], - want_reply ? PICK_ONE : PICK_NONE, - xprname(otmp, (char *)0, lets[0], TRUE, 0L)); + want_reply ? PICK_ONE : PICK_NONE, + xprname(otmp, (char *)0, lets[0], TRUE, 0L, 0L)); break; } } @@ -1499,6 +1678,7 @@ boolean want_reply; n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected); if (n > 0) { ret = selected[0].item.a_char; + if (out_cnt) *out_cnt = selected[0].count; free((genericptr_t)selected); } else ret = !n ? '\0' : '\033'; /* cancelled */ @@ -1506,6 +1686,21 @@ boolean want_reply; return ret; } +/* + * If lets == NULL or "", list all objects in the inventory. Otherwise, + * list all objects with object classes that match the order in lets. + * + * Returns the letter identifier of a selected item, or 0 if nothing + * was selected. + */ +char +display_inventory(lets, want_reply) +register const char *lets; +boolean want_reply; +{ + return display_pickinv(lets, want_reply, (long *)0); +} + /* * Returns the number of unpaid items within the given list. This includes * contained objects. @@ -1525,6 +1720,45 @@ count_unpaid(list) return count; } +/* + * Returns the number of items with b/u/c/unknown within the given list. + * This does NOT include contained objects. + */ +int +count_buc(list, type) + struct obj *list; + int type; +{ + int count = 0; + + while (list) { + switch(type) { + case BUC_BLESSED: + if (list->oclass != GOLD_CLASS && list->bknown && list->blessed) + count++; + break; + case BUC_CURSED: + if (list->oclass != GOLD_CLASS && list->bknown && list->cursed) + count++; + break; + case BUC_UNCURSED: + if (list->oclass != GOLD_CLASS && + list->bknown && !list->blessed && !list->cursed) + count++; + break; + case BUC_UNKNOWN: + if (list->oclass != GOLD_CLASS && !list->bknown) + count++; + break; + default: + impossible("need count of curse status %d?", type); + return 0; + } + list = list->nobj; + } + return count; +} + STATIC_OVL void dounpaid() { @@ -1548,7 +1782,7 @@ dounpaid() pline("%s", xprname(otmp, distant_name(otmp, doname), marker ? otmp->invlet : CONTAINED_SYM, - TRUE, unpaid_cost(otmp))); + TRUE, unpaid_cost(otmp), 0L)); return; } @@ -1573,7 +1807,7 @@ dounpaid() save_unpaid = otmp->unpaid; otmp->unpaid = 0; putstr(win, 0, xprname(otmp, distant_name(otmp, doname), - ilet, TRUE, cost)); + ilet, TRUE, cost, 0L)); otmp->unpaid = save_unpaid; num_so_far++; } @@ -1599,7 +1833,7 @@ dounpaid() marker->unpaid = 0; /* suppress "(unpaid)" suffix */ putstr(win, 0, xprname(marker, distant_name(marker, doname), - CONTAINED_SYM, TRUE, cost)); + CONTAINED_SYM, TRUE, cost, 0L)); marker->unpaid = save_unpaid; } } @@ -1607,7 +1841,7 @@ dounpaid() } putstr(win, 0, ""); - putstr(win, 0, xprname((struct obj *)0, "Total:", '*', FALSE, totcost)); + putstr(win, 0, xprname((struct obj *)0, "Total:", '*', FALSE, totcost, 0L)); display_nhwindow(win, FALSE); destroy_nhwindow(win); } @@ -1636,7 +1870,11 @@ dotypeinv() boolean traditional = TRUE; const char *prompt = "What type of object do you want an inventory of?"; +#ifndef GOLDOBJ if (!invent && !u.ugold && !billx) { +#else + if (!invent && !billx) { +#endif You("aren't carrying anything."); return 0; } @@ -1657,7 +1895,10 @@ dotypeinv() /* collect a list of classes of objects carried, for use as a prompt */ types[0] = 0; class_count = collect_obj_classes(types, invent, - FALSE, (u.ugold != 0), + FALSE, +#ifndef GOLDOBJ + (u.ugold != 0), +#endif (boolean FDECL((*),(OBJ_P))) 0); if (unpaid_count) { Strcat(types, "u"); @@ -1810,9 +2051,26 @@ boolean picked_some; winid tmpwin; boolean skip_objects = (obj_cnt >= 5); - if (u.uswallow) { + if (u.uswallow && u.ustuck) { + struct monst *mtmp = u.ustuck; + Sprintf(fbuf, "Contents of %s %s", + s_suffix(mon_nam(mtmp)), mbodypart(mtmp, STOMACH)); + /* Skip "Contents of " by using fbuf index 12 */ + You("%s to %s what is lying in %s.", + Blind ? "try" : "look around", verb, &fbuf[12]); + otmp = mtmp->minvent; + if (otmp) { + for ( ; otmp; otmp = otmp->nobj) { + /* If swallower is an animal, it should have become stone but... */ + if (otmp->otyp == CORPSE) feel_cockatrice(otmp, FALSE); + } + if (Blind) Strcpy(fbuf, "You feel"); + Strcat(fbuf,":"); + (void) display_minventory(mtmp, MINV_ALL, fbuf); + } else { You("%s no objects here.", verb); - return(!!Blind); + } + return(!!Blind); } if (!skip_objects && (trap = t_at(u.ux,u.uy)) && trap->tseen) There("is %s here.", @@ -1928,7 +2186,16 @@ STATIC_OVL boolean mergable(otmp, obj) /* returns TRUE if obj & otmp can be merged */ register struct obj *otmp, *obj; { +#ifndef GOLDOBJ if (obj->otyp != otmp->otyp || obj->unpaid != otmp->unpaid || +#else + if (obj->otyp != otmp->otyp) return FALSE; + + /* Coins of the same kind will always merge. */ + if (obj->oclass == GOLD_CLASS) return TRUE; + + if (obj->unpaid != otmp->unpaid || +#endif obj->spe != otmp->spe || obj->dknown != otmp->dknown || (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST)) || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed || @@ -1941,7 +2208,8 @@ mergable(otmp, obj) /* returns TRUE if obj & otmp can be merged */ #endif obj->greased != otmp->greased || obj->oeroded != otmp->oeroded || - obj->oeroded2 != otmp->oeroded2) + obj->oeroded2 != otmp->oeroded2 || + obj->bypass != otmp->bypass) return(FALSE); if ((obj->oclass==WEAPON_CLASS || obj->oclass==ARMOR_CLASS) && @@ -1960,7 +2228,7 @@ mergable(otmp, obj) /* returns TRUE if obj & otmp can be merged */ /* hatching eggs don't merge; ditto for revivable corpses */ if ((obj->otyp == EGG && (obj->timed || otmp->timed)) || (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM && - mons[otmp->corpsenm].mlet == S_TROLL)) + is_reviver(&mons[otmp->corpsenm]))) return FALSE; /* allow candle merging only if their ages are close */ @@ -2000,10 +2268,18 @@ doprgold() { /* the messages used to refer to "carrying gold", but that didn't take containers into account */ +#ifndef GOLDOBJ if(!u.ugold) Your("wallet is empty."); else Your("wallet contains %ld gold piece%s.", u.ugold, plur(u.ugold)); +#else + long umoney = money_cnt(invent); + if(!umoney) + Your("wallet is empty."); + else + Your("wallet contains %ld %s.", umoney, currency(umoney)); +#endif shopper_financial_report(); return 0; } @@ -2078,7 +2354,7 @@ dopramulet() return 0; } -static boolean +STATIC_OVL boolean tool_in_use(obj) struct obj *obj; { @@ -2139,7 +2415,7 @@ long numused; /* burn_floor_paper() keeps an object pointer that it tries to * useupf() multiple times, so obj must survive if plural */ if (obj->quan > numused) - otmp = splitobj(obj, obj->quan - numused); + otmp = splitobj(obj, numused); else otmp = obj; if(costly_spot(otmp->ox, otmp->oy)) { @@ -2364,27 +2640,40 @@ struct obj *obj; * MINV_ALL - display all inventory */ struct obj * -display_minventory(mon, dflags) +display_minventory(mon, dflags, title) register struct monst *mon; int dflags; +char *title; { - struct obj *ret, m_gold; + struct obj *ret; +#ifndef GOLDOBJ + struct obj m_gold; +#endif char tmp[QBUFSZ]; int n; menu_item *selected = 0; +#ifndef GOLDOBJ int do_all = (dflags & MINV_ALL) != 0, do_gold = (do_all && mon->mgold); +#else + int do_all = (dflags & MINV_ALL) != 0; +#endif Sprintf(tmp,"%s %s:", s_suffix(noit_Monnam(mon)), do_all ? "possessions" : "armament"); +#ifndef GOLDOBJ if (do_all ? (mon->minvent || mon->mgold) +#else + if (do_all ? (mon->minvent != 0) +#endif : (mon->misc_worn_check || MON_WEP(mon))) { /* Fool the 'weapon in hand' routine into * displaying 'weapon in claw', etc. properly. */ youmonst.data = mon->data; +#ifndef GOLDOBJ if (do_gold) { /* * Make temporary gold object and insert at the head of @@ -2401,27 +2690,32 @@ int dflags; panic("display_minventory: static object freed."); } - n = query_objlist(tmp, mon->minvent, INVORDER_SORT, &selected, +#endif + n = query_objlist(title ? title : tmp, mon->minvent, INVORDER_SORT, &selected, (dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE, do_all ? allow_all : worn_wield_only); +#ifndef GOLDOBJ if (do_gold) obj_extract_self(&m_gold); +#endif set_uasmon(); } else { - invdisp_nothing(tmp, "(none)"); + invdisp_nothing(title ? title : tmp, "(none)"); n = 0; } if (n > 0) { ret = selected[0].item.a_obj; free((genericptr_t)selected); +#ifndef GOLDOBJ /* * Unfortunately, we can't return a pointer to our temporary * gold object. We'll have to work out a scheme where this * can happen. Maybe even put gold in the inventory list... */ if (ret == &m_gold) ret = (struct obj *) 0; +#endif } else ret = (struct obj *) 0; return ret; diff --git a/src/light.c b/src/light.c index 8deda16..5e7229c 100644 --- a/src/light.c +++ b/src/light.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)light.c 3.3 97/04/10 */ +/* SCCS Id: @(#)light.c 3.4 1997/04/10 */ /* Copyright (c) Dean Luick, 1994 */ /* NetHack may be freely redistributed. See license for details. */ @@ -40,15 +40,6 @@ #ifdef OVL3 -typedef struct ls_t { - struct ls_t *next; - xchar x, y; /* source's position */ - short range; /* source's current range */ - short flags; - short type; /* type of light source */ - genericptr_t id; /* source's identifier */ -} light_source; - /* flags */ #define LSF_SHOW 0x1 /* display the light source */ #define LSF_NEEDS_FIXUP 0x2 /* need oid fixup */ @@ -462,6 +453,12 @@ snuff_light_source(x, y) if (ls->type == LS_OBJECT && ls->x == x && ls->y == y) { obj = (struct obj *) ls->id; if (obj_is_burning(obj)) { + /* The only way to snuff Sunsword is to unwield it. Darkness + * scrolls won't affect it. (If we got here because it was + * dropped or thrown inside a monster, this won't matter anyway + * because it will go out when dropped.) + */ + if (artifact_light(obj)) continue; end_burn(obj, obj->otyp != MAGIC_LAMP); /* * The current ls element has just been removed (and @@ -494,7 +491,8 @@ obj_is_burning(obj) || obj->otyp == CANDELABRUM_OF_INVOCATION || obj->otyp == TALLOW_CANDLE || obj->otyp == WAX_CANDLE - || obj->otyp == POT_OIL)); + || obj->otyp == POT_OIL + || artifact_light(obj))); } /* copy the light source(s) attachted to src, and attach it/them to dest */ diff --git a/src/lock.c b/src/lock.c index c5bb838..58da7e6 100644 --- a/src/lock.c +++ b/src/lock.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)lock.c 3.3 2000/02/06 */ +/* SCCS Id: @(#)lock.c 3.4 2000/02/06 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -103,7 +103,7 @@ picklock() /* try to open/close a lock */ return((xlock.usedtime = 0)); } - if(rn2(100) > xlock.chance) return(1); /* still busy */ + if(rn2(100) >= xlock.chance) return(1); /* still busy */ You("succeed in %s.", lock_action()); if (xlock.door) { @@ -160,7 +160,7 @@ forcelock() /* try to force a locked chest */ } else /* blunt */ wake_nearby(); /* due to hammering on the container */ - if(rn2(100) > xlock.chance) return(1); /* still busy */ + if(rn2(100) >= xlock.chance) return(1); /* still busy */ You("succeed in forcing the lock."); xlock.box->olocked = 0; @@ -201,7 +201,7 @@ forcelock() /* try to force a locked chest */ if (costly) loss += stolen_value(xlock.box, u.ux, u.uy, (boolean)shkp->mpeaceful, TRUE); - if(loss) You("owe %ld zorkmids for objects destroyed.", loss); + if(loss) You("owe %ld %s for objects destroyed.", loss, currency(loss)); delobj(xlock.box); } exercise((xlock.picktyp) ? A_DEX : A_STR, TRUE); @@ -476,7 +476,7 @@ doforce() /* try to force a chest with your weapon */ else You("start bashing it with your %s.", xname(uwep)); xlock.box = otmp; - xlock.chance = objects[otmp->otyp].oc_wldam * 2; + xlock.chance = objects[uwep->otyp].oc_wldam * 2; xlock.picktyp = picktyp; xlock.usedtime = 0; break; @@ -877,8 +877,9 @@ struct obj *otmp; long save_Blinded; if (otmp->oclass == POTION_CLASS) { - You("%s a flask shatter!", Blind ? "hear" : "see"); - potionbreathe(otmp); + You("%s a %s shatter!", Blind ? "hear" : "see", bottlename()); + if (!breathless(youmonst.data) || haseyes(youmonst.data)) + potionbreathe(otmp); return; } /* We have functions for distant and singular names, but not one */ diff --git a/src/mail.c b/src/mail.c index 1a44690..99d7637 100644 --- a/src/mail.c +++ b/src/mail.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mail.c 3.3 1999/08/24 */ +/* SCCS Id: @(#)mail.c 3.4 2002/01/13 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -446,7 +446,8 @@ struct obj *otmp; "Only Amiga makes it possible.", "CATS have all the answers.", #endif - "Report bugs to ." + "Report bugs to .", + "Invitation: Visit the NetHack web site at http://www.nethack.org!" }; if (Blind) { diff --git a/src/makemon.c b/src/makemon.c index 0697520..8039a10 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)makemon.c 3.3 2000/06/02 */ +/* SCCS Id: @(#)makemon.c 3.4 2002/02/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -12,6 +12,13 @@ STATIC_VAR NEARDATA struct monst zeromonst; +/* this assumes that a human quest leader or nemesis is an archetype + of the corresponding role; that isn't so for some roles (tourist + for instance) but is for the priests and monks we use it for... */ +#define quest_mon_represents_role(mptr,role_pm) \ + (mptr->mlet == S_HUMAN && Role_if(role_pm) && \ + (mptr->msound == MS_LEADER || mptr->msound == MS_NEMESIS)) + #ifdef OVL0 STATIC_DCL boolean FDECL(uncommon, (int)); STATIC_DCL int FDECL(align_shift, (struct permonst *)); @@ -125,6 +132,7 @@ register int x, y, n; if (enexto(&mm, mm.x, mm.y, mtmp->data)) { mon = makemon(mtmp->data, mm.x, mm.y, NO_MM_FLAGS); mon->mpeaceful = FALSE; + mon->mavenge = 0; set_malign(mon); /* Undo the second peace_minded() check in makemon(); if the * monster turned out to be peaceful the first time we @@ -238,7 +246,8 @@ register struct monst *mtmp; (void)mongets(mtmp, PICK_AXE); if (!rn2(50)) (void)mongets(mtmp, CRYSTAL_BALL); } - } else if (ptr->msound == MS_PRIEST) { + } else if (ptr->msound == MS_PRIEST || + quest_mon_represents_role(ptr,PM_PRIEST)) { otmp = mksobj(MACE, FALSE, FALSE); if(otmp) { otmp->spe = rnd(3); @@ -466,6 +475,22 @@ register struct monst *mtmp; #endif /* OVL2 */ #ifdef OVL1 +#ifdef GOLDOBJ +/* + * Makes up money for monster's inventory. + * This will change with silver & copper coins + */ +void +mkmonmoney(mtmp, amount) +struct monst *mtmp; +long amount; +{ + struct obj *gold = mksobj(GOLD_PIECE, FALSE, FALSE); + gold->quan = amount; + add_to_minv(mtmp, gold); +} +#endif + STATIC_OVL void m_initinv(mtmp) register struct monst *mtmp; @@ -526,7 +551,7 @@ register struct monst *mtmp; if (mac < 10 && rn2(3)) mac += 1 + mongets(mtmp, LEATHER_GLOVES); else if (mac < 10 && rn2(2)) - mac += 1 + mongets(mtmp, ELVEN_CLOAK); + mac += 1 + mongets(mtmp, LEATHER_CLOAK); if(ptr != &mons[PM_GUARD] && ptr != &mons[PM_WATCHMAN] && @@ -547,10 +572,20 @@ register struct monst *mtmp; case 2: (void) mongets(mtmp, POT_HEALING); case 3: (void) mongets(mtmp, WAN_STRIKING); } - } else if (ptr->msound == MS_PRIEST) { - (void) mongets(mtmp, ROBE); + } else if (ptr->msound == MS_PRIEST || + quest_mon_represents_role(ptr,PM_PRIEST)) { + (void) mongets(mtmp, rn2(7) ? ROBE : + rn2(3) ? CLOAK_OF_PROTECTION : + CLOAK_OF_MAGIC_RESISTANCE); (void) mongets(mtmp, SMALL_SHIELD); +#ifndef GOLDOBJ mtmp->mgold = (long)rn1(10,20); +#else + mkmonmoney(mtmp,(long)rn1(10,20)); +#endif + } else if (quest_mon_represents_role(ptr,PM_MONK)) { + (void) mongets(mtmp, rn2(11) ? ROBE : + CLOAK_OF_MAGIC_RESISTANCE); } break; case S_NYMPH: @@ -601,7 +636,11 @@ register struct monst *mtmp; } break; case S_LEPRECHAUN: +#ifndef GOLDOBJ mtmp->mgold = (long) d(level_difficulty(), 30); +#else + mkmonmoney(mtmp, (long) d(level_difficulty(), 30)); +#endif break; default: break; @@ -614,9 +653,14 @@ register struct monst *mtmp; (void) mongets(mtmp, rnd_defensive_item(mtmp)); if ((int) mtmp->m_lev > rn2(100)) (void) mongets(mtmp, rnd_misc_item(mtmp)); +#ifndef GOLDOBJ if (likes_gold(ptr) && !mtmp->mgold && !rn2(5)) mtmp->mgold = (long) d(level_difficulty(), mtmp->minvent ? 5 : 10); +#else + if (likes_gold(ptr) && !findgold(mtmp->minvent) && !rn2(5)) + mkmonmoney(mtmp, (long) d(level_difficulty(), mtmp->minvent ? 5 : 10)); +#endif } struct monst * @@ -645,7 +689,9 @@ struct monst *mon; m2->minvent = (struct obj *) 0; /* objects don't clone */ m2->mleashed = FALSE; +#ifndef GOLDOBJ m2->mgold = 0L; +#endif /* Max HP the same, but current HP halved for both. The caller * might want to override this by halving the max HP also. * When current HP is odd, the original keeps the extra point. @@ -658,31 +704,42 @@ struct monst *mon; * polymorphed away from their original forms, the clone doesn't have * room for the extra information. we also don't want two shopkeepers * around for the same shop. - * similarly, clones of named monsters don't have room for the name, - * so we just make the clone unnamed instead of bothering to create - * a clone with room and copying over the name from the right place - * (which changes if the original was a shopkeeper or guard). */ if (mon->isshk) m2->isshk = FALSE; if (mon->isgd) m2->isgd = FALSE; if (mon->ispriest) m2->ispriest = FALSE; m2->mxlth = 0; - m2->mnamelth = 0; place_monster(m2, m2->mx, m2->my); if (emits_light(m2->data)) new_light_source(m2->mx, m2->my, emits_light(m2->data), LS_MONSTER, (genericptr_t)m2); + if (m2->mnamelth) { + m2->mnamelth = 0; /* or it won't get allocated */ + m2 = christen_monst(m2, NAME(mon)); + } newsym(m2->mx,m2->my); /* display the new monster */ if (mon->mtame) { struct monst *m3; - /* because m2 is a copy of mon it is tame but not init'ed. - * however, tamedog will not re-tame a tame dog, so m2 - * must be made non-tame to get initialized properly. - */ - m2->mtame = 0; - if ((m3 = tamedog(m2, (struct obj *)0)) != 0) + if (mon->isminion) { + m3 = newmonst(sizeof(struct epri) + mon->mnamelth); + *m3 = *m2; + m3->mxlth = sizeof(struct epri); + if (m2->mnamelth) Strcpy(NAME(m3), NAME(m2)); + *(EPRI(m3)) = *(EPRI(mon)); + replmon(m2, m3); m2 = m3; + } else { + /* because m2 is a copy of mon it is tame but not init'ed. + * however, tamedog will not re-tame a tame dog, so m2 + * must be made non-tame to get initialized properly. + */ + m2->mtame = 0; + if ((m3 = tamedog(m2, (struct obj *)0)) != 0) { + m2 = m3; + *(EDOG(m2)) = *(EDOG(mon)); + } + } } return m2; } @@ -705,6 +762,7 @@ register int mmflags; boolean anymon = (!ptr); boolean byyou = (x == u.ux && y == u.uy); boolean allow_minvent = ((mmflags & NO_MINVENT) == 0); + boolean countbirth = ((mmflags & MM_NOCOUNTBIRTH) == 0); uchar lim; /* if caller wants random location, do it here */ @@ -772,11 +830,11 @@ register int mmflags; * the caller manually decrement mvitals if the monster is created * under circumstances where one would not logically expect the * creation to reduce the supply of wild monsters. Monster cloning - * might be one such case, but we go against logic there in order to + * might be one such case, but we go against logic there in order to * reduce the possibility of abuse. */ - if (mvitals[mndx].born < 255) mvitals[mndx].born++; - lim = (mndx == PM_NAZGUL ? 9 : mndx == PM_ERINYS ? 3 : MAXMONNO); + if (mvitals[mndx].born < 255 && countbirth) mvitals[mndx].born++; + lim = mbirth_limit(mndx); if ((int) mvitals[mndx].born >= lim && !(mons[mndx].geno & G_NOGEN) && !(mvitals[mndx].mvflags & G_EXTINCT)) { #ifdef DEBUG @@ -798,6 +856,8 @@ register int mmflags; mtmp->m_id = flags.ident++; if (!mtmp->m_id) mtmp->m_id = flags.ident++; /* ident overflowed */ set_mon_data(mtmp, ptr, 0); + if (mtmp->data->msound == MS_LEADER) + quest_status.leader_m_id = mtmp->m_id; mtmp->mxlth = xlth; mtmp->mnum = mndx; @@ -832,6 +892,8 @@ register int mmflags; if (In_sokoban(&u.uz) && !mindless(ptr)) /* know about traps here */ mtmp->mtrapseen = (1L << (PIT - 1)) | (1L << (HOLE - 1)); + if (ptr->msound == MS_LEADER) /* leader knows about portal */ + mtmp->mtrapseen |= (1 << (MAGIC_PORTAL-1)); place_monster(mtmp, x, y); mtmp->mcansee = mtmp->mcanmove = TRUE; @@ -877,7 +939,7 @@ register int mmflags; break; case S_BAT: if (Inhell && is_bat(ptr)) - mon_adjust_speed(mtmp, 2); + mon_adjust_speed(mtmp, 2, (struct obj *)0); break; } if ((ct = emits_light(mtmp->data)) > 0) @@ -893,7 +955,7 @@ register int mmflags; mtmp->cham = CHAM_ORDINARY; else { mtmp->cham = mcham; - (void) newcham(mtmp, rndmonst()); + (void) newcham(mtmp, rndmonst(), FALSE); } } else if (mndx == PM_WIZARD_OF_YENDOR) { mtmp->iswiz = TRUE; @@ -931,6 +993,7 @@ register int mmflags; } if(is_dprince(ptr) && ptr->msound == MS_BRIBE) { mtmp->mpeaceful = mtmp->minvis = mtmp->perminvis = 1; + mtmp->mavenge = 0; if (uwep && uwep->oartifact == ART_EXCALIBUR) mtmp->mpeaceful = mtmp->mtame = FALSE; } @@ -981,6 +1044,13 @@ register int mmflags; return(mtmp); } +int +mbirth_limit(mndx) +int mndx; +{ + return (mndx == PM_NAZGUL ? 9 : mndx == PM_ERINYS ? 3 : MAXMONNO); +} + /* used for wand/scroll/spell of create monster */ /* returns TRUE iff you know monsters have been created */ boolean @@ -1326,7 +1396,7 @@ struct monst *mtmp, *victim; if (mvitals[newtype].mvflags & G_GENOD) { /* allow G_EXTINCT */ if (sensemon(mtmp)) pline("As %s grows up into %s, %s %s!", mon_nam(mtmp), - an(ptr->mname), he[pronoun_gender(mtmp)], + an(ptr->mname), mhe(mtmp), nonliving(ptr) ? "expires" : "dies"); set_mon_data(mtmp, ptr, -1); /* keep mvitals[] accurate */ mondied(mtmp); diff --git a/src/mapglyph.c b/src/mapglyph.c new file mode 100644 index 0000000..6ea4d96 --- /dev/null +++ b/src/mapglyph.c @@ -0,0 +1,232 @@ +/* SCCS Id: @(#)mapglyph.c 3.4 2000/08/18 */ +/* Copyright (c) David Cohrs, 1991 */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "hack.h" +#if defined(TTY_GRAPHICS) +#include "wintty.h" /* for prototype of has_color() only */ +#endif +#include "color.h" + +int explcolors[] = { + CLR_BLACK, /* dark */ + CLR_GREEN, /* noxious */ + CLR_BROWN, /* muddy */ + CLR_BLUE, /* wet */ + CLR_MAGENTA, /* magical */ + CLR_ORANGE, /* fiery */ + CLR_WHITE, /* frosty */ +}; + +#if !defined(TTY_GRAPHICS) +#define has_color(n) TRUE +#endif + +#ifdef TEXTCOLOR +#define zap_color(n) color = iflags.use_color ? zapcolors[n] : NO_COLOR +#define cmap_color(n) color = iflags.use_color ? defsyms[n].color : NO_COLOR +#define obj_color(n) color = iflags.use_color ? objects[n].oc_color : NO_COLOR +#define mon_color(n) color = iflags.use_color ? mons[n].mcolor : NO_COLOR +#define invis_color(n) color = NO_COLOR +#define pet_color(n) color = iflags.use_color ? mons[n].mcolor : NO_COLOR +#define warn_color(n) color = iflags.use_color ? def_warnsyms[n].color : NO_COLOR +#define explode_color(n) color = iflags.use_color ? explcolors[n] : NO_COLOR +# if defined(REINCARNATION) && defined(ASCIIGRAPH) +# define ROGUE_COLOR +# endif + +#else /* no text color */ + +#define zap_color(n) +#define cmap_color(n) +#define obj_color(n) +#define mon_color(n) +#define invis_color(n) +#define pet_color(c) +#define warn_color(n) +#define explode_color(n) +#endif + +#ifdef ROGUE_COLOR +# if defined(USE_TILES) && defined(MSDOS) +#define HAS_ROGUE_IBM_GRAPHICS (iflags.IBMgraphics && !iflags.grmode && \ + Is_rogue_level(&u.uz)) +# else +#define HAS_ROGUE_IBM_GRAPHICS (iflags.IBMgraphics && Is_rogue_level(&u.uz)) +# endif +#endif + +/*ARGSUSED*/ +void +mapglyph(glyph, ochar, ocolor, ospecial, x, y) +int glyph, *ocolor, x, y; +int *ochar; +unsigned *ospecial; +{ + register int offset; + int color = NO_COLOR; + uchar ch; + unsigned special = 0; + + /* + * Map the glyph back to a character and color. + * + * Warning: For speed, this makes an assumption on the order of + * offsets. The order is set in display.h. + */ + if ((offset = (glyph - GLYPH_WARNING_OFF)) >= 0) { /* a warning flash */ + ch = warnsyms[offset]; +# ifdef ROGUE_COLOR + if (HAS_ROGUE_IBM_GRAPHICS) + color = NO_COLOR; + else +# endif + warn_color(offset); + } else if ((offset = (glyph - GLYPH_SWALLOW_OFF)) >= 0) { /* swallow */ + /* see swallow_to_glyph() in display.c */ + ch = (uchar) showsyms[S_sw_tl + (offset & 0x7)]; +#ifdef ROGUE_COLOR + if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) + color = NO_COLOR; + else +#endif + mon_color(offset >> 3); + } else if ((offset = (glyph - GLYPH_ZAP_OFF)) >= 0) { /* zap beam */ + /* see zapdir_to_glyph() in display.c */ + ch = showsyms[S_vbeam + (offset & 0x3)]; +#ifdef ROGUE_COLOR + if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) + color = NO_COLOR; + else +#endif + zap_color((offset >> 2)); + } else if ((offset = (glyph - GLYPH_EXPLODE_OFF)) >= 0) { /* explosion */ + ch = showsyms[(offset % MAXEXPCHARS) + S_explode1]; + explode_color(offset / MAXEXPCHARS); + } else if ((offset = (glyph - GLYPH_CMAP_OFF)) >= 0) { /* cmap */ + ch = showsyms[offset]; +#ifdef ROGUE_COLOR + if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) { + if (offset >= S_vwall && offset <= S_hcdoor) + color = CLR_BROWN; + else if (offset >= S_arrow_trap && offset <= S_polymorph_trap) + color = CLR_MAGENTA; + else if (offset == S_corr || offset == S_litcorr) + color = CLR_GRAY; + else if (offset >= S_room && offset <= S_water) + color = CLR_GREEN; + else + color = NO_COLOR; + } else +#endif + cmap_color(offset); + } else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) { /* object */ + if (offset == BOULDER && iflags.bouldersym) ch = iflags.bouldersym; + else ch = oc_syms[(int)objects[offset].oc_class]; +#ifdef ROGUE_COLOR + if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) { + switch(objects[offset].oc_class) { + case GOLD_CLASS: color = CLR_YELLOW; break; + case FOOD_CLASS: color = CLR_RED; break; + default: color = CLR_BRIGHT_BLUE; break; + } + } else +#endif + obj_color(offset); + } else if ((offset = (glyph - GLYPH_RIDDEN_OFF)) >= 0) { /* mon ridden */ + ch = monsyms[(int)mons[offset].mlet]; +#ifdef ROGUE_COLOR + if (HAS_ROGUE_IBM_GRAPHICS) + /* This currently implies that the hero is here -- monsters */ + /* don't ride (yet...). Should we set it to yellow like in */ + /* the monster case below? There is no equivalent in rogue. */ + color = NO_COLOR; /* no need to check iflags.use_color */ + else +#endif + mon_color(offset); + special |= MG_RIDDEN; + } else if ((offset = (glyph - GLYPH_BODY_OFF)) >= 0) { /* a corpse */ + ch = oc_syms[(int)objects[CORPSE].oc_class]; +#ifdef ROGUE_COLOR + if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) + color = CLR_RED; + else +#endif + mon_color(offset); + special |= MG_CORPSE; + } else if ((offset = (glyph - GLYPH_DETECT_OFF)) >= 0) { /* mon detect */ + ch = monsyms[(int)mons[offset].mlet]; +#ifdef ROGUE_COLOR + if (HAS_ROGUE_IBM_GRAPHICS) + color = NO_COLOR; /* no need to check iflags.use_color */ + else +#endif + mon_color(offset); + /* Disabled for now; anyone want to get reverse video to work? */ + /* is_reverse = TRUE; */ + special |= MG_DETECT; + } else if ((offset = (glyph - GLYPH_INVIS_OFF)) >= 0) { /* invisible */ + ch = DEF_INVISIBLE; +#ifdef ROGUE_COLOR + if (HAS_ROGUE_IBM_GRAPHICS) + color = NO_COLOR; /* no need to check iflags.use_color */ + else +#endif + invis_color(offset); + special |= MG_INVIS; + } else if ((offset = (glyph - GLYPH_PET_OFF)) >= 0) { /* a pet */ + ch = monsyms[(int)mons[offset].mlet]; +#ifdef ROGUE_COLOR + if (HAS_ROGUE_IBM_GRAPHICS) + color = NO_COLOR; /* no need to check iflags.use_color */ + else +#endif + pet_color(offset); + special |= MG_PET; + } else { /* a monster */ + ch = monsyms[(int)mons[glyph].mlet]; +#ifdef ROGUE_COLOR + if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) { + if (x == u.ux && y == u.uy) + /* actually player should be yellow-on-gray if in a corridor */ + color = CLR_YELLOW; + else + color = NO_COLOR; + } else +#endif + mon_color(glyph); + } + +#ifdef TEXTCOLOR + /* Turn off color if no color defined, or rogue level w/o PC graphics. */ +# ifdef REINCARNATION +# ifdef ASCIIGRAPH + if (!has_color(color) || (Is_rogue_level(&u.uz) && !HAS_ROGUE_IBM_GRAPHICS)) +# else + if (!has_color(color) || Is_rogue_level(&u.uz)) +# endif +# else + if (!has_color(color)) +# endif + color = NO_COLOR; +#endif + if (ochar) + *ochar = (int)ch; + else + impossible("glyphmap(): Invalid output character buffer."); + + if (ospecial) + *ospecial = special; + else + impossible("glyphmap(): Invalid special feature return buffer."); + +#ifdef TEXTCOLOR + if (ocolor) + *ocolor = color; + else + impossible("glyphmap(): Invalid color buffer."); +#endif + return; +} + +/*mapglyph.c*/ diff --git a/src/mcastu.c b/src/mcastu.c index dcc4135..13827d4 100644 --- a/src/mcastu.c +++ b/src/mcastu.c @@ -1,10 +1,42 @@ -/* SCCS Id: @(#)mcastu.c 3.3 97/11/02 */ +/* SCCS Id: @(#)mcastu.c 3.4 2002/02/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" -STATIC_DCL void FDECL(cursetxt,(struct monst *)); +/* monster mage spells */ +#define MGC_PSI_BOLT 0 +#define MGC_CURE_SELF 1 +#define MGC_HASTE_SELF 2 +#define MGC_STUN_YOU 3 +#define MGC_DISAPPEAR 4 +#define MGC_WEAKEN_YOU 5 +#define MGC_DESTRY_ARMR 6 +#define MGC_CURSE_ITEMS 7 +#define MGC_AGGRAVATION 8 +#define MGC_SUMMON_MONS 9 +#define MGC_CLONE_WIZ 10 +#define MGC_DEATH_TOUCH 11 + +/* monster cleric spells */ +#define CLC_OPEN_WOUNDS 0 +#define CLC_CURE_SELF 1 +#define CLC_CONFUSE_YOU 2 +#define CLC_PARALYZE 3 +#define CLC_BLIND_YOU 4 +#define CLC_INSECTS 5 +#define CLC_CURSE_ITEMS 6 +#define CLC_LIGHTNING 7 +#define CLC_FIRE_PILLAR 8 +#define CLC_GEYSER 9 + +STATIC_DCL void FDECL(cursetxt,(struct monst *,BOOLEAN_P)); +STATIC_DCL int FDECL(choose_magic_spell, (int)); +STATIC_DCL int FDECL(choose_clerical_spell, (int)); +STATIC_DCL void FDECL(cast_wizard_spell,(struct monst *, int,int)); +STATIC_DCL void FDECL(cast_cleric_spell,(struct monst *, int,int)); +STATIC_DCL boolean FDECL(is_undirected_spell,(unsigned int,int)); +STATIC_DCL boolean FDECL(spell_would_be_useless,(struct monst *,unsigned int,int)); #ifdef OVL0 @@ -13,13 +45,16 @@ extern const char *flash_types[]; /* from zap.c */ /* feedback when frustrated monster couldn't cast a spell */ STATIC_OVL void -cursetxt(mtmp) +cursetxt(mtmp, undirected) struct monst *mtmp; +boolean undirected; { - if (canseemon(mtmp)) { + if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my)) { const char *point_msg; /* spellcasting monsters are impolite */ - if ((Invis && !perceives(mtmp->data) && + if (undirected) + point_msg = "all around, then curses"; + else if ((Invis && !perceives(mtmp->data) && (mtmp->mux != u.ux || mtmp->muy != u.uy)) || (youmonst.m_ap_type == M_AP_OBJECT && youmonst.mappearance == STRANGE_OBJECT) || @@ -39,34 +74,198 @@ struct monst *mtmp; #endif /* OVL0 */ #ifdef OVLB +/* convert a level based random selection into a specific mage spell; + inappropriate choices will be screened out by spell_would_be_useless() */ +STATIC_OVL int +choose_magic_spell(spellval) +int spellval; +{ + switch (spellval) { + case 22: + case 21: + case 20: + return MGC_DEATH_TOUCH; + case 19: + case 18: + return MGC_CLONE_WIZ; + case 17: + case 16: + case 15: + return MGC_SUMMON_MONS; /* also aggravates */ + case 14: + case 13: + return MGC_AGGRAVATION; + case 12: + case 11: + case 10: + return MGC_CURSE_ITEMS; + case 9: + case 8: + return MGC_DESTRY_ARMR; + case 7: + case 6: + return MGC_WEAKEN_YOU; + case 5: + case 4: + return MGC_DISAPPEAR; + case 3: + return MGC_STUN_YOU; + case 2: + return MGC_HASTE_SELF; + case 1: + return MGC_CURE_SELF; + case 0: + default: + return MGC_PSI_BOLT; + } +} + +/* convert a level based random selection into a specific cleric spell */ +STATIC_OVL int +choose_clerical_spell(spellnum) +int spellnum; +{ + switch (spellnum) { + case 13: + return CLC_GEYSER; + case 12: + return CLC_FIRE_PILLAR; + case 11: + return CLC_LIGHTNING; + case 10: + case 9: + return CLC_CURSE_ITEMS; + case 8: + return CLC_INSECTS; + case 7: + case 6: + return CLC_BLIND_YOU; + case 5: + case 4: + return CLC_PARALYZE; + case 3: + case 2: + return CLC_CONFUSE_YOU; + case 1: + return CLC_CURE_SELF; + case 0: + default: + return CLC_OPEN_WOUNDS; + } +} + +/* return values: + * 1: successful spell + * 0: unsuccessful spell + */ int -castmu(mtmp, mattk) /* monster casts spell at you */ +castmu(mtmp, mattk, thinks_it_foundyou, foundyou) register struct monst *mtmp; register struct attack *mattk; + boolean thinks_it_foundyou; + boolean foundyou; { int dmg, ml = mtmp->m_lev; + int ret; + int spellnum = 0; - if(mtmp->mcan || mtmp->mspec_used || !ml) { /* could not attack */ - cursetxt(mtmp); + /* Three cases: + * -- monster is attacking you. Search for a useful spell. + * -- monster thinks it's attacking you. Search for a useful spell, + * without checking for undirected. If the spell found is directed, + * it fails with cursetxt() and loss of mspec_used. + * -- monster isn't trying to attack. Select a spell once. Don't keep + * searching; if that spell is not useful (or if it's directed), + * return and do something else. + * Since most spells are directed, this means that a monster that isn't + * attacking casts spells only a small portion of the time that an + * attacking monster does. + */ + if (mattk->adtyp == AD_SPEL || mattk->adtyp == AD_CLRC) { + int cnt = 40; + + do { + spellnum = rn2(ml); + if (mattk->adtyp == AD_SPEL) + spellnum = choose_magic_spell(spellnum); + else + spellnum = choose_clerical_spell(spellnum); + /* not trying to attack? don't allow directed spells */ + if (!thinks_it_foundyou) { + if (!is_undirected_spell(mattk->adtyp, spellnum) || + spell_would_be_useless(mtmp, mattk->adtyp, spellnum)) { + if (foundyou) + impossible("spellcasting monster found you and doesn't know it?"); + return 0; + } + break; + } + } while(--cnt > 0 && + spell_would_be_useless(mtmp, mattk->adtyp, spellnum)); + if (cnt == 0) return 0; + } + + /* monster unable to cast spells? */ + if(mtmp->mcan || mtmp->mspec_used || !ml) { + cursetxt(mtmp, is_undirected_spell(mattk->adtyp, spellnum)); return(0); - } else { - nomul(0); - if(rn2(ml*10) < (mtmp->mconf ? 100 : 20)) { /* fumbled attack */ - if (canseemon(mtmp) && flags.soundok) - pline_The("air crackles around %s.", mon_nam(mtmp)); - return(0); - } } + + if (mattk->adtyp == AD_SPEL || mattk->adtyp == AD_CLRC) { + mtmp->mspec_used = 10 - mtmp->m_lev; + if (mtmp->mspec_used < 2) mtmp->mspec_used = 2; + } + + /* monster can cast spells, but is casting a directed spell at the + wrong place? If so, give a message, and return. Do this *after* + penalizing mspec_used. */ + if (!foundyou && thinks_it_foundyou && + !is_undirected_spell(mattk->adtyp, spellnum)) { + pline("%s casts a spell at %s!", + canseemon(mtmp) ? Monnam(mtmp) : "Something", + levl[mtmp->mux][mtmp->muy].typ == WATER + ? "empty water" : "thin air"); + return(0); + } + + nomul(0); + if(rn2(ml*10) < (mtmp->mconf ? 100 : 20)) { /* fumbled attack */ + if (canseemon(mtmp) && flags.soundok) + pline_The("air crackles around %s.", mon_nam(mtmp)); + return(0); + } + if (canspotmon(mtmp) || !is_undirected_spell(mattk->adtyp, spellnum)) { + pline("%s casts a spell%s!", + canspotmon(mtmp) ? Monnam(mtmp) : "Something", + is_undirected_spell(mattk->adtyp, spellnum) ? "" : + (Invisible && !perceives(mtmp->data) && + (mtmp->mux != u.ux || mtmp->muy != u.uy)) ? + " at a spot near you" : + (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy)) ? + " at your displaced image" : + " at you"); + } + /* * As these are spells, the damage is related to the level * of the monster casting the spell. */ - if (mattk->damd) - dmg = d((int)((ml/3) + mattk->damn), (int)mattk->damd); - else dmg = d((int)((ml/3) + 1), 6); + if (!foundyou) { + dmg = 0; + if (mattk->adtyp != AD_SPEL && mattk->adtyp != AD_CLRC) { + impossible( + "%s casting non-hand-to-hand version of hand-to-hand spell %d?", + Monnam(mtmp), mattk->adtyp); + return(0); + } + } else if (mattk->damd) + dmg = d((int)((ml/2) + mattk->damn), (int)mattk->damd); + else dmg = d((int)((ml/2) + 1), 6); if (Half_spell_damage) dmg = (dmg+1) / 2; - switch(mattk->adtyp) { + ret = 1; + + switch (mattk->adtyp) { case AD_FIRE: pline("You're enveloped in flames."); @@ -93,229 +292,459 @@ castmu(mtmp, mattk) /* monster casts spell at you */ dmg = 0; } else dmg = d((int)mtmp->m_lev/2 + 1,6); break; - case AD_SPEL: /* random spell */ - - mtmp->mspec_used = 10 - mtmp->m_lev; - if (mtmp->mspec_used < 2) mtmp->mspec_used = 2; - switch(rn2((int)mtmp->m_lev)) { - case 22: - case 21: - case 20: - pline("Oh no, %s's using the touch of death!", - humanoid(mtmp->data) - ? (mtmp->female ? "she" : "he") - : "it" - ); - if (nonliving(youmonst.data) || is_demon(youmonst.data)) - You("seem no deader than before."); - else if (!Antimagic && rn2(ml) > 12) { - - if(Hallucination) - You("have an out of body experience."); - else { - killer_format = KILLED_BY_AN; - killer = "touch of death"; - done(DIED); - } - } else { - if(Antimagic) shieldeff(u.ux, u.uy); - pline("Lucky for you, it didn't work!"); - } - dmg = 0; - break; - case 19: - case 18: - if(mtmp->iswiz && flags.no_of_wizards == 1) { - pline("Double Trouble..."); - clonewiz(); - dmg = 0; - break; - } /* else fall into the next case */ - case 17: - case 16: - case 15: - if(mtmp->iswiz) - verbalize("Destroy the thief, my pets!"); - nasty(mtmp); /* summon something nasty */ - /* fall into the next case */ - case 14: /* aggravate all monsters */ - case 13: - aggravate(); - dmg = 0; - break; - case 12: /* curse random items */ - case 11: - case 10: - rndcurse(); - dmg = 0; - break; - case 9: - case 8: /* destroy armor */ - if (Antimagic) { - shieldeff(u.ux, u.uy); - pline("A field of force surrounds you!"); - } else if(!destroy_arm(some_armor(&youmonst))) - Your("skin itches."); - dmg = 0; - break; - case 7: - case 6: /* drain strength */ - if(Antimagic) { - shieldeff(u.ux, u.uy); - You_feel("momentarily weakened."); - } else { - You("suddenly feel weaker!"); - dmg = ml - 6; - if(Half_spell_damage) dmg = (dmg+1) / 2; - losestr(rnd(dmg)); - if(u.uhp < 1) - done_in_by(mtmp); - } - dmg = 0; - break; - case 5: /* make invisible if not */ - case 4: - if (!mtmp->minvis && !mtmp->invis_blkd) { - if(canseemon(mtmp) && !See_invisible) - pline("%s suddenly disappears!", Monnam(mtmp)); - mon_set_minvis(mtmp); - dmg = 0; - break; - } /* else fall into the next case */ - case 3: /* stun */ - if (Antimagic || Free_action) { - shieldeff(u.ux, u.uy); - if(!Stunned) - You_feel("momentarily disoriented."); - make_stunned(1L, FALSE); - } else { - if (Stunned) - You("struggle to keep your balance."); - else - You("reel..."); - dmg = d(ACURR(A_DEX) < 12 ? 6 : 4, 4); - if(Half_spell_damage) dmg = (dmg+1) / 2; - make_stunned(HStun + dmg, FALSE); - } - dmg = 0; - break; - case 2: /* haste self */ - mon_adjust_speed(mtmp, 1); - dmg = 0; - break; - case 1: /* cure self */ - if(mtmp->mhp < mtmp->mhpmax) { - if((mtmp->mhp += rnd(8)) > mtmp->mhpmax) - mtmp->mhp = mtmp->mhpmax; - dmg = 0; - break; - } /* else fall through to default case */ - default: /* psi bolt */ - if(Antimagic) { - shieldeff(u.ux, u.uy); - You("get a slight %sache.",body_part(HEAD)); - dmg = 1; - } else { - if (dmg <= 10) - Your("brain is on fire!"); - else Your("%s suddenly aches!", body_part(HEAD)); - } - break; - } + case AD_SPEL: /* wizard spell */ + case AD_CLRC: /* clerical spell */ + { + if (mattk->adtyp == AD_SPEL) + cast_wizard_spell(mtmp, dmg, spellnum); + else + cast_cleric_spell(mtmp, dmg, spellnum); + dmg = 0; /* done by the spell casting functions */ break; - - case AD_CLRC: /* clerical spell */ - mtmp->mspec_used = 10 - mtmp->m_lev; - if (mtmp->mspec_used < 2) mtmp->mspec_used = 2; - switch(rn2((int)mtmp->m_lev)) { - /* Other ideas: lightning bolts, towers of flame, - gush of water -3. */ - - default: /* confuse */ - if(Antimagic) { - shieldeff(u.ux, u.uy); - You_feel("momentarily dizzy."); - } else { - dmg = (int)mtmp->m_lev; - if(Half_spell_damage) dmg = (dmg+1) / 2; - make_confused(HConfusion + dmg, TRUE); - } - dmg = 0; - break; - case 12: /* curse random items */ - case 11: - case 10: - rndcurse(); - dmg = 0; - break; - case 9: - case 8: /* insects */ - /* Try for insects, and if there are none - left, go for (sticks to) snakes. -3. */ - { - int i; - struct permonst *pm = mkclass(S_ANT,0); - struct monst *mtmp2; - char let = (pm ? S_ANT : S_SNAKE); - - for (i = 0; i <= (int) mtmp->m_lev; i++) - if ((pm = mkclass(let,0)) && - (mtmp2 = makemon(pm, u.ux, u.uy, NO_MM_FLAGS))) { - mtmp2->msleeping = mtmp2->mpeaceful = - mtmp2->mtame = 0; - set_malign(mtmp2); - } - } - dmg = 0; - break; - case 6: - case 7: /* blindness */ - /* note: resists_blnd() doesn't apply here */ - if (!Blinded) { - pline("Scales cover your %s!", makeplural(body_part(EYE))); - make_blinded(Half_spell_damage ? 100L:200L, FALSE); - dmg = 0; - break; - } - case 4: - case 5: /* wound */ - if(Antimagic) { - shieldeff(u.ux, u.uy); - Your("skin itches badly for a moment."); - dmg = 0; - } else { - pline("Wounds appear on your body!"); - dmg = d(2,8) + 1; - if (Half_spell_damage) dmg = (dmg+1) / 2; - } - break; - case 3: /* hold */ - if (Antimagic || Free_action) { - shieldeff(u.ux, u.uy); - if(multi >= 0) - You("stiffen briefly."); - nomul(-1); - } else { - if (multi >= 0) - You("are frozen in place!"); - dmg = 4 + (int)mtmp->m_lev; - if (Half_spell_damage) dmg = (dmg+1) / 2; - nomul(-dmg); - } - dmg = 0; - break; - case 2: - case 1: /* cure self */ - if(mtmp->mhp < mtmp->mhpmax) { - if((mtmp->mhp += rnd(8)) > mtmp->mhpmax) - mtmp->mhp = mtmp->mhpmax; - dmg = 0; - break; - } /* else fall through to default case */ - } + } } if(dmg) mdamageu(mtmp, dmg); - return(1); + return(ret); +} + +/* monster wizard and cleric spellcasting functions */ +/* + If dmg is zero, then the monster is not casting at you. + If the monster is intentionally not casting at you, we have previously + called spell_would_be_useless() and spellnum should always be a valid + undirected spell. + If you modify either of these, be sure to change is_undirected_spell() + and spell_would_be_useless(). + */ +STATIC_OVL +void +cast_wizard_spell(mtmp, dmg, spellnum) +struct monst *mtmp; +int dmg; +int spellnum; +{ + if (dmg == 0 && !is_undirected_spell(AD_SPEL, spellnum)) { + impossible("cast directed wizard spell (%d) with dmg=0?", spellnum); + return; + } + + switch (spellnum) { + case MGC_DEATH_TOUCH: + pline("Oh no, %s's using the touch of death!", mhe(mtmp)); + if (nonliving(youmonst.data) || is_demon(youmonst.data)) { + You("seem no deader than before."); + } else if (!Antimagic && rn2(mtmp->m_lev) > 12) { + if (Hallucination) { + You("have an out of body experience."); + } else { + killer_format = KILLED_BY_AN; + killer = "touch of death"; + done(DIED); + } + } else { + if (Antimagic) shieldeff(u.ux, u.uy); + pline("Lucky for you, it didn't work!"); + } + dmg = 0; + break; + case MGC_CLONE_WIZ: + if (mtmp->iswiz && flags.no_of_wizards == 1) { + pline("Double Trouble..."); + clonewiz(); + dmg = 0; + } else + impossible("bad wizard cloning?"); + break; + case MGC_SUMMON_MONS: /* also aggravates */ + { + int count; + + count = nasty(mtmp); /* summon something nasty */ + if (mtmp->iswiz) + verbalize("Destroy the thief, my pet%s!", plur(count)); + else { + const char *mappear = + (count == 1) ? "A monster appears" : "Monsters appear"; + + /* messages not quite right if plural monsters created but + only a single monster is seen */ + if (Invisible && !perceives(mtmp->data) && + (mtmp->mux != u.ux || mtmp->muy != u.uy)) + pline("%s around a spot near you!", mappear); + else if (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy)) + pline("%s around your displaced image!", mappear); + else + pline("%s from nowhere!", mappear); + } + dmg = 0; + break; + } + case MGC_AGGRAVATION: + You_feel("that monsters are aware of your presence."); + aggravate(); + dmg = 0; + break; + case MGC_CURSE_ITEMS: + You_feel("as if you need some help."); + rndcurse(); + dmg = 0; + break; + case MGC_DESTRY_ARMR: + if (Antimagic) { + shieldeff(u.ux, u.uy); + pline("A field of force surrounds you!"); + } else if (!destroy_arm(some_armor(&youmonst))) { + Your("skin itches."); + } + dmg = 0; + break; + case MGC_WEAKEN_YOU: /* drain strength */ + if (Antimagic) { + shieldeff(u.ux, u.uy); + You_feel("momentarily weakened."); + } else { + You("suddenly feel weaker!"); + dmg = mtmp->m_lev - 6; + if (Half_spell_damage) dmg = (dmg + 1) / 2; + losestr(rnd(dmg)); + if (u.uhp < 1) + done_in_by(mtmp); + } + dmg = 0; + break; + case MGC_DISAPPEAR: /* makes self invisible */ + if (!mtmp->minvis && !mtmp->invis_blkd) { + if (canseemon(mtmp)) + pline("%s suddenly %s!", Monnam(mtmp), + !See_invisible ? "disappears" : "becomes transparent"); + mon_set_minvis(mtmp); + dmg = 0; + } else + impossible("no reason for monster to cast disappear spell?"); + break; + case MGC_STUN_YOU: + if (Antimagic || Free_action) { + shieldeff(u.ux, u.uy); + if (!Stunned) + You_feel("momentarily disoriented."); + make_stunned(1L, FALSE); + } else { + You(Stunned ? "struggle to keep your balance." : "reel..."); + dmg = d(ACURR(A_DEX) < 12 ? 6 : 4, 4); + if (Half_spell_damage) dmg = (dmg + 1) / 2; + make_stunned(HStun + dmg, FALSE); + } + dmg = 0; + break; + case MGC_HASTE_SELF: + mon_adjust_speed(mtmp, 1, (struct obj *)0); + dmg = 0; + break; + case MGC_CURE_SELF: + if (mtmp->mhp < mtmp->mhpmax) { + if (canseemon(mtmp)) + pline("%s looks better.", Monnam(mtmp)); + /* note: player healing does 6d4; this used to do 1d8 */ + if ((mtmp->mhp += d(3,6)) > mtmp->mhpmax) + mtmp->mhp = mtmp->mhpmax; + dmg = 0; + } + break; + case MGC_PSI_BOLT: + /* prior to 3.4.0 Antimagic was setting the damage to 1--this + made the spell virtually harmless to players with magic res. */ + if (Antimagic) { + shieldeff(u.ux, u.uy); + dmg = (dmg + 1) / 2; + } + if (dmg <= 5) + You("get a slight %sache.", body_part(HEAD)); + else if (dmg <= 10) + Your("brain is on fire!"); + else if (dmg <= 20) + Your("%s suddenly aches painfully!", body_part(HEAD)); + else + Your("%s suddenly aches very painfully!", body_part(HEAD)); + break; + default: + impossible("mcastu: invalid magic spell (%d)", spellnum); + dmg = 0; + break; + } + + if (dmg) mdamageu(mtmp, dmg); +} + +STATIC_OVL +void +cast_cleric_spell(mtmp, dmg, spellnum) +struct monst *mtmp; +int dmg; +int spellnum; +{ + if (dmg == 0 && !is_undirected_spell(AD_CLRC, spellnum)) { + impossible("cast directed cleric spell (%d) with dmg=0?", spellnum); + return; + } + + switch (spellnum) { + case CLC_GEYSER: + /* this is physical damage, not magical damage */ + pline("A sudden geyser slams into you from nowhere!"); + dmg = d(8, 6); + if (Half_physical_damage) dmg = (dmg + 1) / 2; + break; + case CLC_FIRE_PILLAR: + pline("A pillar of fire strikes all around you!"); + if (Fire_resistance) { + shieldeff(u.ux, u.uy); + dmg = 0; + } else + dmg = d(8, 6); + if (Half_spell_damage) dmg = (dmg + 1) / 2; + burn_away_slime(); + (void) burnarmor(&youmonst); + destroy_item(SCROLL_CLASS, AD_FIRE); + destroy_item(POTION_CLASS, AD_FIRE); + destroy_item(SPBOOK_CLASS, AD_FIRE); + (void) burn_floor_paper(u.ux, u.uy, TRUE, FALSE); + break; + case CLC_LIGHTNING: + { + boolean reflects; + + pline("A bolt of lightning strikes down at you from above!"); + reflects = ureflects("It bounces off your %s%s.", ""); + if (reflects || Shock_resistance) { + shieldeff(u.ux, u.uy); + dmg = 0; + if (reflects) + break; + } else + dmg = d(8, 6); + if (Half_spell_damage) dmg = (dmg + 1) / 2; + destroy_item(WAND_CLASS, AD_ELEC); + destroy_item(RING_CLASS, AD_ELEC); + break; + } + case CLC_CURSE_ITEMS: + You_feel("as if you need some help."); + rndcurse(); + dmg = 0; + break; + case CLC_INSECTS: + { + /* Try for insects, and if there are none + left, go for (sticks to) snakes. -3. */ + struct permonst *pm = mkclass(S_ANT,0); + struct monst *mtmp2 = (struct monst *)0; + char let = (pm ? S_ANT : S_SNAKE); + boolean success; + int i; + coord bypos; + + success = pm ? TRUE : FALSE; + for (i = 0; i <= (int) mtmp->m_lev; i++) { + if (!enexto(&bypos, mtmp->mux, mtmp->muy, mtmp->data)) + break; + if ((pm = mkclass(let,0)) != 0 && + (mtmp2 = makemon(pm, bypos.x, bypos.y, NO_MM_FLAGS)) != 0) { + success = TRUE; + mtmp2->msleeping = mtmp2->mpeaceful = mtmp2->mtame = 0; + set_malign(mtmp2); + } + } + /* Not quite right: + * -- message doesn't always make sense for unseen caster (particularly + * the first message) + * -- message assumes plural monsters summoned (non-plural should be + * very rare, unlike in nasty()) + * -- message assumes plural monsters seen + */ + if (!success) + pline("%s casts at a clump of sticks, but nothing happens.", + Monnam(mtmp)); + else if (let == S_SNAKE) + pline("%s transforms a clump of sticks into snakes!", + Monnam(mtmp)); + else if (Invisible && !perceives(mtmp->data) && + (mtmp->mux != u.ux || mtmp->muy != u.uy)) + pline("%s summons insects around a spot near you!", + Monnam(mtmp)); + else if (Displaced && (mtmp->mux != u.ux || mtmp->muy != u.uy)) + pline("%s summons insects around your displaced image!", + Monnam(mtmp)); + else + pline("%s summons insects!", Monnam(mtmp)); + dmg = 0; + break; + } + case CLC_BLIND_YOU: + /* note: resists_blnd() doesn't apply here */ + if (!Blinded) { + int num_eyes = eyecount(youmonst.data); + pline("Scales cover your %s!", + (num_eyes == 1) ? + body_part(EYE) : makeplural(body_part(EYE))); + make_blinded(Half_spell_damage ? 100L : 200L, FALSE); + if (!Blind) Your(vision_clears); + dmg = 0; + } else + impossible("no reason for monster to cast blindness spell?"); + break; + case CLC_PARALYZE: + if (Antimagic || Free_action) { + shieldeff(u.ux, u.uy); + if (multi >= 0) + You("stiffen briefly."); + nomul(-1); + } else { + if (multi >= 0) + You("are frozen in place!"); + dmg = 4 + (int)mtmp->m_lev; + if (Half_spell_damage) dmg = (dmg + 1) / 2; + nomul(-dmg); + } + dmg = 0; + break; + case CLC_CONFUSE_YOU: + if (Antimagic) { + shieldeff(u.ux, u.uy); + You_feel("momentarily dizzy."); + } else { + boolean oldprop = !!Confusion; + + dmg = (int)mtmp->m_lev; + if (Half_spell_damage) dmg = (dmg + 1) / 2; + make_confused(HConfusion + dmg, TRUE); + if (Hallucination) + You_feel("%s!", oldprop ? "trippier" : "trippy"); + else + You_feel("%sconfused!", oldprop ? "more " : ""); + } + dmg = 0; + break; + case CLC_CURE_SELF: + if (mtmp->mhp < mtmp->mhpmax) { + if (canseemon(mtmp)) + pline("%s looks better.", Monnam(mtmp)); + /* note: player healing does 6d4; this used to do 1d8 */ + if ((mtmp->mhp += d(3,6)) > mtmp->mhpmax) + mtmp->mhp = mtmp->mhpmax; + dmg = 0; + } + break; + case CLC_OPEN_WOUNDS: + if (Antimagic) { + shieldeff(u.ux, u.uy); + dmg = (dmg + 1) / 2; + } + if (dmg <= 5) + Your("skin itches badly for a moment."); + else if (dmg <= 10) + pline("Wounds appear on your body!"); + else if (dmg <= 20) + pline("Severe wounds appear on your body!"); + else + Your("body is covered with painful wounds!"); + break; + default: + impossible("mcastu: invalid clerical spell (%d)", spellnum); + dmg = 0; + break; + } + + if (dmg) mdamageu(mtmp, dmg); +} + +STATIC_DCL +boolean +is_undirected_spell(adtyp, spellnum) +unsigned int adtyp; +int spellnum; +{ + if (adtyp == AD_SPEL) { + switch (spellnum) { + case MGC_CLONE_WIZ: + case MGC_SUMMON_MONS: + case MGC_AGGRAVATION: + case MGC_DISAPPEAR: + case MGC_HASTE_SELF: + case MGC_CURE_SELF: + return TRUE; + default: + break; + } + } else if (adtyp == AD_CLRC) { + switch (spellnum) { + case CLC_INSECTS: + case CLC_CURE_SELF: + return TRUE; + default: + break; + } + } + return FALSE; +} + +/* Some spells are useless under some circumstances. */ +STATIC_DCL +boolean +spell_would_be_useless(mtmp, adtyp, spellnum) +struct monst *mtmp; +unsigned int adtyp; +int spellnum; +{ + /* Some spells don't require the player to really be there and can be cast + * by the monster when you're invisible, yet still shouldn't be cast when + * the monster doesn't even think you're there. + * This check isn't quite right because it always uses your real position. + * We really want something like "if the monster could see mux, muy". + */ + boolean mcouldseeu = couldsee(mtmp->mx, mtmp->my); + + if (adtyp == AD_SPEL) { + /* aggravate monsters, etc. won't be cast by peaceful monsters */ + if (mtmp->mpeaceful && (spellnum == MGC_AGGRAVATION || + spellnum == MGC_SUMMON_MONS || spellnum == MGC_CLONE_WIZ)) + return TRUE; + /* haste self when already fast */ + if (mtmp->permspeed == MFAST && spellnum == MGC_HASTE_SELF) + return TRUE; + /* invisibility when already invisible */ + if ((mtmp->minvis || mtmp->invis_blkd) && spellnum == MGC_DISAPPEAR) + return TRUE; + /* peaceful monster won't cast invisibility if you can't see invisible, + same as when monsters drink potions of invisibility. This doesn't + really make a lot of sense, but lets the player avoid hitting + peaceful monsters by mistake */ + if (mtmp->mpeaceful && !See_invisible && spellnum == MGC_DISAPPEAR) + return TRUE; + /* healing when already healed */ + if (mtmp->mhp == mtmp->mhpmax && spellnum == MGC_CURE_SELF) + return TRUE; + /* don't summon monsters if it doesn't think you're around */ + if (!mcouldseeu && (spellnum == MGC_SUMMON_MONS || + (!mtmp->iswiz && spellnum == MGC_CLONE_WIZ))) + return TRUE; + if ((!mtmp->iswiz || flags.no_of_wizards > 1) + && spellnum == MGC_CLONE_WIZ) + return TRUE; + } else if (adtyp == AD_CLRC) { + /* summon insects/sticks to snakes won't be cast by peaceful monsters */ + if (mtmp->mpeaceful && spellnum == CLC_INSECTS) + return TRUE; + /* healing when already healed */ + if (mtmp->mhp == mtmp->mhpmax && spellnum == CLC_CURE_SELF) + return TRUE; + /* don't summon insects if it doesn't think you're around */ + if (!mcouldseeu && spellnum == CLC_INSECTS) + return TRUE; + /* blindness spell on blinded player */ + if (Blinded && spellnum == CLC_BLIND_YOU) + return TRUE; + } + return FALSE; } #endif /* OVLB */ @@ -329,8 +758,13 @@ buzzmu(mtmp, mattk) /* monster uses spell (ranged) */ register struct monst *mtmp; register struct attack *mattk; { - if(mtmp->mcan || mattk->adtyp > AD_SPC2) { - cursetxt(mtmp); + /* don't print constant stream of curse messages for 'normal' + spellcasting monsters at range */ + if (mattk->adtyp > AD_SPC2) + return(0); + + if (mtmp->mcan) { + cursetxt(mtmp, FALSE); return(0); } if(lined_up(mtmp) && rn2(3)) { diff --git a/src/mhitm.c b/src/mhitm.c index 8b00022..99cbf42 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mhitm.c 3.3 2000/07/29 */ +/* SCCS Id: @(#)mhitm.c 3.4 2002/02/17 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -189,7 +189,7 @@ mattackm(magr, mdef) attk, /* attack attempted this time */ struck = 0, /* hit at least once */ res[NATTK]; /* results of all attacks */ - struct attack *mattk; + struct attack *mattk, alt_attk; struct permonst *pa, *pd; if (!magr || !mdef) return(MM_MISS); /* mike@genat */ @@ -233,7 +233,7 @@ mattackm(magr, mdef) /* Now perform all attacks for the monster. */ for (i = 0; i < NATTK; i++) { res[i] = MM_MISS; - mattk = &(pa->mattk[i]); + mattk = getmattk(pa, i, res, &alt_attk); otmp = (struct obj *)0; attk = 1; switch (mattk->aatyp) { @@ -274,9 +274,22 @@ mattackm(magr, mdef) /* KMH -- don't accumulate to-hit bonuses */ if (otmp) tmp -= hitval(otmp, mdef); - if (strike) + if (strike) { res[i] = hitmm(magr, mdef, mattk); - else + if((mdef->data == &mons[PM_BLACK_PUDDING] || mdef->data == &mons[PM_BROWN_PUDDING]) + && otmp && objects[otmp->otyp].oc_material == IRON + && mdef->mhp > 1 && !mdef->mcan) + { + if (clone_mon(mdef)) { + if (vis) { + char buf[BUFSZ]; + + Strcpy(buf, Monnam(mdef)); + pline("%s divides as %s hits it!", buf, mon_nam(magr)); + } + } + } + } else missmm(magr, mdef, mattk); break; @@ -393,8 +406,8 @@ hitmm(magr, mdef, mattk) default: Sprintf(buf,"%s hits", magr_name); } + pline("%s %s.", buf, mon_nam_too(mdef_name, mdef, magr)); } - pline("%s %s.", buf, mon_nam_too(mdef_name, mdef, magr)); } else noises(magr, mattk); return(mdamagem(magr, mdef, mattk)); } @@ -412,10 +425,38 @@ gazemm(magr, mdef, mattk) pline("%s %s...", buf, mon_nam(mdef)); } - if (!mdef->mcansee || mdef->msleeping) { + if (magr->mcan || !magr->mcansee || + (magr->minvis && !perceives(mdef->data)) || + !mdef->mcansee || mdef->msleeping) { if(vis) pline("but nothing happens."); return(MM_MISS); } + /* call mon_reflects 2x, first test, then, if visible, print message */ + if (magr->data == &mons[PM_MEDUSA] && mon_reflects(mdef, (char *)0)) { + if (canseemon(mdef)) + (void) mon_reflects(mdef, + "The gaze is reflected away by %s %s."); + if (mdef->mcansee) { + if (mon_reflects(magr, (char *)0)) { + if (canseemon(magr)) + (void) mon_reflects(magr, + "The gaze is reflected away by %s %s."); + return (MM_MISS); + } + if (mdef->minvis && !perceives(magr->data)) { + if (canseemon(magr)) { + pline("%s doesn't seem to notice that %s gaze was reflected.", + Monnam(magr), mhis(magr)); + } + return (MM_MISS); + } + if (canseemon(magr)) + pline("%s is turned to stone!", Monnam(magr)); + monstone(magr); + if (magr->mhp > 0) return (MM_MISS); + return (MM_AGR_DIED); + } + } return(mdamagem(magr, mdef, mattk)); } @@ -526,11 +567,15 @@ mdamagem(magr, mdef, mattk) int tmp = d((int)mattk->damn,(int)mattk->damd); struct obj *obj; char buf[BUFSZ]; + int protector = + mattk->aatyp == AT_TENT ? 0 : + mattk->aatyp == AT_KICK ? W_ARMF : W_ARMG; + int num; if (touch_petrifies(pd) && !resists_ston(magr) && (mattk->aatyp != AT_WEAP || !otmp) && (mattk->aatyp != AT_GAZE && mattk->aatyp != AT_EXPL) && - !(magr->misc_worn_check & W_ARMG)) { + !(magr->misc_worn_check & protector)) { if (poly_when_stoned(pa)) { mon_to_stone(magr); return MM_HIT; /* no damage during the polymorph */ @@ -564,10 +609,37 @@ mdamagem(magr, mdef, mattk) tmp = mdef->mhp; /* Use up amulet of life saving */ if (!!(obj = mlifesaver(mdef))) m_useup(mdef, obj); + + /* Is a corpse for nutrition possible? It may kill magr */ + if (!corpse_chance(mdef, magr, TRUE) || magr->mhp < 1) + break; + + /* Pets get nutrition from swallowing monster whole. + * No nutrition from G_NOCORPSE monster, eg, undead. + * DGST monsters don't die from undead corpses + */ + num = monsndx(mdef->data); + if (magr->mtame && !magr->isminion && + !(mvitals[num].mvflags & G_NOCORPSE)) { + struct obj *virtualcorpse = mksobj(CORPSE, FALSE, FALSE); + int nutrit; + + virtualcorpse->corpsenm = num; + virtualcorpse->owt = weight(virtualcorpse); + nutrit = dog_nutrition(magr, virtualcorpse); + dealloc_obj(virtualcorpse); + + /* only 50% nutrition, 25% of normal eating time */ + if (magr->meating > 1) magr->meating = (magr->meating+3)/4; + if (nutrit > 1) nutrit /= 2; + EDOG(magr)->hungrytime += nutrit; + } break; case AD_STUN: if (magr->mcan) break; - if(vis) pline("%s staggers for a moment.", Monnam(mdef)); + if (canseemon(mdef)) + pline("%s %s for a moment.", Monnam(mdef), + makeplural(stagger(mdef->data, "stagger"))); mdef->mstun = 1; /* fall through */ case AD_WERE: @@ -607,6 +679,7 @@ mdamagem(magr, mdef, mattk) } if (vis) pline("%s is %s!", Monnam(mdef), + mdef->data == &mons[PM_WATER_ELEMENTAL] ? "boiling" : mattk->aatyp == AT_HUGS ? "being roasted" : "on fire"); if (pd == &mons[PM_STRAW_GOLEM] || @@ -679,7 +752,7 @@ mdamagem(magr, mdef, mattk) pline("It burns %s!", mon_nam(mdef)); } if (!rn2(30)) erode_armor(mdef, TRUE); - if (!rn2(6)) erode_weapon(MON_WEP(mdef), TRUE); + if (!rn2(6)) erode_obj(MON_WEP(mdef), TRUE, TRUE); break; case AD_RUST: if (!magr->mcan && pd == &mons[PM_IRON_GOLEM]) { @@ -694,8 +767,8 @@ mdamagem(magr, mdef, mattk) hurtmarmor(mdef, AD_RUST); tmp = 0; break; - case AD_CORRODE: - hurtmarmor(mdef, AD_CORRODE); + case AD_CORR: + hurtmarmor(mdef, AD_CORR); tmp = 0; break; case AD_DCAY: @@ -771,7 +844,7 @@ label2: if (mdef->mhp > 0) return 0; if (!magr->mcan && vis && mdef->mspeed != MSLOW) { unsigned int oldspeed = mdef->mspeed; - mon_adjust_speed(mdef, -1); + mon_adjust_speed(mdef, -1, (struct obj *)0); if (mdef->mspeed != oldspeed && vis) pline("%s slows down.", Monnam(mdef)); } @@ -834,12 +907,25 @@ label2: if (mdef->mhp > 0) return 0; break; case AD_SGLD: tmp = 0; +#ifndef GOLDOBJ if (magr->mcan || !mdef->mgold) break; /* technically incorrect; no check for stealing gold from * between mdef's feet... */ magr->mgold += mdef->mgold; mdef->mgold = 0; +#else + if (magr->mcan) break; + /* technically incorrect; no check for stealing gold from + * between mdef's feet... + */ + { + struct obj *gold = findgold(mdef->minvent); + if (!gold) break; + obj_extract_self(gold); + add_to_minv(magr, gold); + } +#endif if (vis) { Strcpy(buf, Monnam(magr)); pline("%s steals some gold from %s.", buf, mon_nam(mdef)); @@ -867,14 +953,20 @@ label2: if (mdef->mhp > 0) return 0; #endif case AD_SITM: /* for now these are the same */ case AD_SEDU: - if (!magr->mcan && mdef->minvent) { + /* find an object to steal, non-cursed if magr is tame */ + for (obj = mdef->minvent; obj; obj = obj->nobj) { + if (!magr->mtame || !obj->cursed) + break; + } + + if (!magr->mcan && obj) { char onambuf[BUFSZ], mdefnambuf[BUFSZ]; /* make a special x_monnam() call that never omits the saddle, and save it for later messages */ Strcpy(mdefnambuf, x_monnam(mdef, ARTICLE_THE, (char *)0, 0, FALSE)); - otmp = mdef->minvent; + otmp = obj; #ifdef STEED if (u.usteed == mdef && otmp == which_armor(mdef, W_SADDLE)) @@ -884,6 +976,8 @@ label2: if (mdef->mhp > 0) return 0; obj_extract_self(otmp); if (otmp->owornmask) { mdef->misc_worn_check &= ~otmp->owornmask; + if (otmp->owornmask & W_WEP) + setmnotwielded(mdef,otmp); otmp->owornmask = 0L; update_mon_intrinsics(mdef, otmp, FALSE); } @@ -933,6 +1027,7 @@ label2: if (mdef->mhp > 0) return 0; case AD_DRIN: if (notonhead || !has_head(pd)) { if (vis) pline("%s doesn't seem harmed.", Monnam(mdef)); + /* Not clear what to do for green slimes */ tmp = 0; break; } @@ -941,7 +1036,7 @@ label2: if (mdef->mhp > 0) return 0; Strcpy(buf, s_suffix(Monnam(mdef))); pline("%s helmet blocks %s attack to %s head.", buf, s_suffix(mon_nam(magr)), - his[pronoun_gender(mdef)]); + mhis(mdef)); } break; } @@ -962,9 +1057,10 @@ label2: if (mdef->mhp > 0) return 0; case AD_SLIM: if (!rn2(4) && mdef->data != &mons[PM_FIRE_VORTEX] && mdef->data != &mons[PM_FIRE_ELEMENTAL] && + mdef->data != &mons[PM_SALAMANDER] && mdef->data != &mons[PM_GREEN_SLIME]) { if (vis) pline("%s turns into slime.", Monnam(mdef)); - (void) newcham(mdef, &mons[PM_GREEN_SLIME]); + (void) newcham(mdef, &mons[PM_GREEN_SLIME], FALSE); tmp = 0; } break; @@ -1054,7 +1150,7 @@ register struct obj *obj; if (!magr || !mdef || !obj) return; /* just in case */ - if (dmgtype(mdef->data, AD_CORRODE)) + if (dmgtype(mdef->data, AD_CORR)) is_acid = TRUE; else if (dmgtype(mdef->data, AD_RUST)) is_acid = FALSE; @@ -1088,11 +1184,11 @@ register struct monst *magr, *mdef; register struct obj *otemp; { char buf[BUFSZ]; + if (!flags.verbose || Blind || !mon_visible(magr)) return; Strcpy(buf, mon_nam(mdef)); - if (!flags.verbose || Blind) return; pline("%s %s %s %s at %s.", Monnam(magr), (objects[otemp->otyp].oc_dir & PIERCE) ? "thrusts" : "swings", - his[pronoun_gender(magr)], xname(otemp), buf); + mhis(magr), singular(otemp, xname), buf); } /* @@ -1198,7 +1294,8 @@ int mdead; if (!magr->mstun) { magr->mstun = 1; if (canseemon(magr)) - pline("%s staggers...", Monnam(magr)); + pline("%s %s...", Monnam(magr), + makeplural(stagger(magr->data, "stagger"))); } tmp = 0; break; diff --git a/src/mhitu.c b/src/mhitu.c index 834d0d7..a70add9 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mhitu.c 3.3 2000/04/19 */ +/* SCCS Id: @(#)mhitu.c 3.4 2002/02/17 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -99,6 +99,7 @@ register struct attack *mattk; else pline("%s just misses!", Monnam(mtmp)); } + stop_occupation(); } STATIC_OVL void @@ -110,7 +111,7 @@ register struct obj *otemp; return; pline("%s %s %s %s.", Monnam(mtmp), (objects[otemp->otyp].oc_dir & PIERCE) ? "thrusts" : "swings", - his[pronoun_gender(mtmp)], xname(otemp)); + mhis(mtmp), singular(otemp, xname)); } /* return how a poison attack was delivered */ @@ -265,6 +266,30 @@ boolean message; #endif /* OVLB */ #ifdef OVL0 +/* select a monster's next attack, possibly substituting for its usual one */ +struct attack * +getmattk(mptr, indx, prev_result, alt_attk_buf) +struct permonst *mptr; +int indx, prev_result[]; +struct attack *alt_attk_buf; +{ + struct attack *attk = &mptr->mattk[indx]; + + /* prevent a monster with two consecutive disease or hunger attacks + from hitting with both of them on the same turn; if the first has + already hit, switch to a stun attack for the second */ + if (indx > 0 && prev_result[indx - 1] > 0 && + (attk->adtyp == AD_DISE || + attk->adtyp == AD_PEST || + attk->adtyp == AD_FAMN) && + attk->adtyp == mptr->mattk[indx - 1].adtyp) { + *alt_attk_buf = *attk; + attk = alt_attk_buf; + attk->adtyp = AD_STUN; + } + return attk; +} + /* * mattacku: monster attacks you * returns 1 if monster dies (e.g. "yellow light"), 0 otherwise @@ -278,7 +303,7 @@ int mattacku(mtmp) register struct monst *mtmp; { - struct attack *mattk; + struct attack *mattk, alt_attk; int i, j, tmp, sum[NATTK]; struct permonst *mdat = mtmp->data; boolean ranged = (distu(mtmp->mx, mtmp->my) > 3); @@ -319,7 +344,7 @@ mattacku(mtmp) i = mattackm(mtmp, u.usteed); if ((i & MM_AGR_DIED)) return (1); - if (i & MM_DEF_DIED || u.ux != u.ux0 || u.uy != u.uy0) + if (i & MM_DEF_DIED || u.umoved) return (0); /* Let your steed retaliate */ return (!!(mattackm(u.usteed, mtmp) & MM_DEF_DIED)); @@ -343,7 +368,7 @@ mattacku(mtmp) newsym(u.ux,u.uy); } else { pline("%s is killed by a falling %s (you)!", - Monnam(mtmp), youmonst.data->mname); + Monnam(mtmp), youmonst.data->mname); killed(mtmp); newsym(u.ux,u.uy); if (mtmp->mhp > 0) return 0; @@ -399,7 +424,8 @@ mattacku(mtmp) } return(0); } - if (youmonst.data->mlet == S_MIMIC && youmonst.m_ap_type && !range2 && foundyou && !u.uswallow) { + if (youmonst.data->mlet == S_MIMIC && youmonst.m_ap_type && + !range2 && foundyou && !u.uswallow) { if (!youseeit) pline("It gets stuck on you."); else pline("Wait, %s! That's a %s named %s!", m_monnam(mtmp), youmonst.data->mname, plname); @@ -475,11 +501,11 @@ mattacku(mtmp) } if(u.uinvulnerable) { - /* monster's won't attack you */ + /* monsters won't attack you */ if(mtmp == u.ustuck) pline("%s loosens its grip slightly.", Monnam(mtmp)); else if(!range2) { - if(youseeit) + if (youseeit || sensemon(mtmp)) pline("%s starts to attack you, but pulls back.", Monnam(mtmp)); else @@ -498,7 +524,7 @@ mattacku(mtmp) for(i = 0; i < NATTK; i++) { sum[i] = 0; - mattk = &(mdat->mattk[i]); + mattk = getmattk(mdat, i, sum, &alt_attk); if (u.uswallow && (mattk->aatyp != AT_ENGL)) continue; switch(mattk->aatyp) { @@ -554,18 +580,17 @@ mattacku(mtmp) } else { missmu(mtmp, (tmp == j), mattk); } - } else if (is_animal(mtmp->data)) - pline("%s gulps some air!", youseeit ? - Monnam(mtmp) : "It"); - else - if (youseeit) - pline("%s lunges forward and recoils!", - Monnam(mtmp)); - else - You_hear("a %s nearby.", - is_whirly(mtmp->data)? - "rushing noise" : - "splat"); + } else if (is_animal(mtmp->data)) { + pline("%s gulps some air!", Monnam(mtmp)); + } else { + if (youseeit) + pline("%s lunges forward and recoils!", + Monnam(mtmp)); + else + You_hear("a %s nearby.", + is_whirly(mtmp->data) ? + "rushing noise" : "splat"); + } } break; case AT_BREA: @@ -597,7 +622,6 @@ mattacku(mtmp) if (mon_wield_item(mtmp) != 0) break; } if (foundyou) { - possibly_unwield(mtmp); otmp = MON_WEP(mtmp); if(otmp) { hittmp = hitval(otmp, &youmonst); @@ -618,20 +642,12 @@ mattacku(mtmp) case AT_MAGC: if (range2) sum[i] = buzzmu(mtmp, mattk); - else + else { if (foundyou) - sum[i] = castmu(mtmp, mattk); + sum[i] = castmu(mtmp, mattk, TRUE, TRUE); else - pline("%s casts a spell at %s!", - youseeit ? Monnam(mtmp) : "It", - levl[mtmp->mux][mtmp->muy].typ == WATER - ? "empty water" : "thin air"); - /* FIXME: castmu includes spells that are not - * cast at the player and thus should be - * possible whether the monster knows your - * location or not. - * --KAA - */ + sum[i] = castmu(mtmp, mattk, TRUE, FALSE); + } break; default: /* no attack */ @@ -668,7 +684,7 @@ int attk; switch(attk) { /* 0 is burning, which we should never be called with */ case AD_RUST: hurt = 1; break; - case AD_CORRODE: hurt = 3; break; + case AD_CORR: hurt = 3; break; default: hurt = 2; break; } @@ -760,7 +776,7 @@ struct attack *mattk; /* avoid "slippery slippery cloak" for undiscovered oilskin cloak */ (obj->greased || objects[obj->otyp].oc_name_known) ? - xname(obj) : "cloak"); + xname(obj) : cloak_simple_name(obj)); if (obj->greased && !rn2(2)) { pline_The("grease wears off."); @@ -784,7 +800,7 @@ hitmu(mtmp, mattk) { register struct permonst *mdat = mtmp->data; register int uncancelled, ptmp; - int dmg, armpro; + int dmg, armpro, permdmg; char buf[BUFSZ]; struct permonst *olduasmon = youmonst.data; int res; @@ -833,6 +849,7 @@ hitmu(mtmp, mattk) armpro = objects[uarmh->otyp].a_can; uncancelled = !mtmp->mcan && ((rn2(3) >= armpro) || !rn2(50)); + permdmg = 0; /* Now, adjust damages via resistances or specific attacks */ switch(mattk->adtyp) { case AD_PHYS: @@ -867,6 +884,7 @@ hitmu(mtmp, mattk) hitmsg(mtmp, mattk); if (!dmg) break; if (u.mh > 1 && u.mh > ((u.uac>0) ? dmg : dmg+u.uac) && + objects[otmp->otyp].oc_material == IRON && (u.umonnum==PM_BLACK_PUDDING || u.umonnum==PM_BROWN_PUDDING)) { /* This redundancy necessary because you have to @@ -895,6 +913,8 @@ hitmu(mtmp, mattk) hitmsg(mtmp, mattk); if (uncancelled) { pline("You're %s!", + youmonst.data == &mons[PM_WATER_ELEMENTAL] ? + "boiling" : mattk->aatyp == AT_HUGS ? "being roasted" : "on fire"); if (youmonst.data == &mons[PM_STRAW_GOLEM] || @@ -955,6 +975,7 @@ hitmu(mtmp, mattk) if (can_blnd(mtmp, &youmonst, mattk->aatyp, (struct obj*)0)) { if (!Blind) pline("%s blinds you!", Monnam(mtmp)); make_blinded(Blinded+(long)dmg,FALSE); + if (!Blind) Your(vision_clears); } dmg = 0; break; @@ -981,6 +1002,7 @@ hitmu(mtmp, mattk) hitmsg(mtmp, mattk); if (defends(AD_DRIN, uwep) || !has_head(youmonst.data)) { You("don't seem harmed."); + /* Not clear what to do for green slimes */ break; } if (u_slip_free(mtmp,mattk)) break; @@ -1094,7 +1116,7 @@ hitmu(mtmp, mattk) } case AD_STON: /* cockatrice */ hitmsg(mtmp, mattk); - if(!rn2(3) && !Stoned) { + if(!rn2(3)) { if (mtmp->mcan) { if (flags.soundok) You_hear("a cough from %s!", mon_nam(mtmp)); @@ -1104,7 +1126,7 @@ hitmu(mtmp, mattk) if(!rn2(10) || (flags.moonphase == NEW_MOON && !have_lizard())) { do_stone: - if (!Stone_resistance + if (!Stoned && !Stone_resistance && !(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) { Stoned = 5; @@ -1203,7 +1225,8 @@ hitmu(mtmp, mattk) } break; } - switch (steal(mtmp)) { + buf[0] = '\0'; + switch (steal(mtmp, buf)) { case -1: return 2; case 0: @@ -1211,7 +1234,19 @@ hitmu(mtmp, mattk) default: if (!is_animal(mtmp->data) && !tele_restrict(mtmp)) rloc(mtmp); - mtmp->mflee = 1; + if (is_animal(mtmp->data) && *buf) { + /* set mavenge bit for animals so knights won't + suffer an alignment penalty during retaliation; + note that only happens when the thief succeeds + in getting something (*buf != 0) */ + mtmp->mavenge = 1; + if (canseemon(mtmp)) + pline("%s tries to %s away with %s.", + Monnam(mtmp), + locomotion(mtmp->data, "run"), + buf); + } + monflee(mtmp, 0, FALSE, FALSE); return 3; } break; @@ -1251,10 +1286,10 @@ hitmu(mtmp, mattk) } hurtarmor(AD_RUST); break; - case AD_CORRODE: + case AD_CORR: hitmsg(mtmp, mattk); if (mtmp->mcan) break; - hurtarmor(AD_CORRODE); + hurtarmor(AD_CORR); break; case AD_DCAY: hitmsg(mtmp, mattk); @@ -1303,10 +1338,7 @@ hitmu(mtmp, mattk) return 2; } else if (!rn2(33)) { if (!tele_restrict(mtmp)) rloc(mtmp); - if (!mtmp->mflee) { - mtmp->mflee = 1; - mtmp->mfleetim = d(3,6); - } + monflee(mtmp, d(3, 6), TRUE, FALSE); return 3; } dmg = 0; @@ -1375,7 +1407,8 @@ hitmu(mtmp, mattk) else You("are getting confused."); make_confused(HConfusion + dmg, FALSE); } - /* fall through to next case */ + dmg = 0; + break; case AD_DETH: pline("%s reaches out with its deadly touch.", Monnam(mtmp)); if (is_undead(youmonst.data)) { @@ -1383,16 +1416,24 @@ hitmu(mtmp, mattk) pline("Was that the touch of death?"); break; } - if(!Antimagic && rn2(20) > 16) { - killer_format = KILLED_BY_AN; - killer = "touch of death"; - done(DIED); - } else { - if(!rn2(5)) { - if(Antimagic) shieldeff(u.ux, u.uy); - pline("Lucky for you, it didn't work!"); + switch (rn2(20)) { + case 19: case 18: case 17: + if (!Antimagic) { + killer_format = KILLED_BY_AN; + killer = "touch of death"; + done(DIED); dmg = 0; - } else You_feel("your life force draining away..."); + break; + } /* else FALLTHRU */ + default: /* case 16: ... case 5: */ + You_feel("your life force draining away..."); + permdmg = 1; /* actual damage done below */ + break; + case 4: case 3: case 2: case 1: case 0: + if (Antimagic) shieldeff(u.ux, u.uy); + pline("Lucky for you, it didn't work!"); + dmg = 0; + break; } break; case AD_PEST: @@ -1408,36 +1449,38 @@ hitmu(mtmp, mattk) /* plus the normal damage */ break; case AD_SLIM: - hitmsg(mtmp, mattk); - if (!uncancelled) break; - if (youmonst.data == &mons[PM_FIRE_VORTEX] || - youmonst.data == &mons[PM_FIRE_ELEMENTAL]) { - pline_The("slime burns away!"); - dmg = 0; - } else if (Unchanging || - youmonst.data == &mons[PM_GREEN_SLIME]) { - You("are unaffected."); - dmg = 0; - } else if (!Slimed) { - You("don't feel very well."); - Slimed = 10L; + hitmsg(mtmp, mattk); + if (!uncancelled) break; + if (youmonst.data == &mons[PM_FIRE_VORTEX] || + youmonst.data == &mons[PM_SALAMANDER] || + youmonst.data == &mons[PM_FIRE_ELEMENTAL]) { + pline_The("slime burns away!"); + dmg = 0; + } else if (Unchanging || + youmonst.data == &mons[PM_GREEN_SLIME]) { + You("are unaffected."); + dmg = 0; + } else if (!Slimed) { + You("don't feel very well."); + Slimed = 10L; + flags.botl = 1; killer_format = KILLED_BY_AN; delayed_killer = mtmp->data->mname; - } else - pline("Yuck!"); - break; + } else + pline("Yuck!"); + break; case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */ - hitmsg(mtmp, mattk); - /* uncancelled is sufficient enough; please - don't make this attack less frequent */ - if (uncancelled) { - struct obj *obj = some_armor(&youmonst); - - if (drain_item(obj)) { - Your("%s less effective.", aobjnam(obj, "seem")); - } - } - break; + hitmsg(mtmp, mattk); + /* uncancelled is sufficient enough; please + don't make this attack less frequent */ + if (uncancelled) { + struct obj *obj = some_armor(&youmonst); + + if (drain_item(obj)) { + Your("%s less effective.", aobjnam(obj, "seem")); + } + } + break; default: dmg = 0; break; } @@ -1457,15 +1500,49 @@ hitmu(mtmp, mattk) || (Role_if(PM_PRIEST) && uarmh && is_quest_artifact(uarmh) && (is_undead(mtmp->data) || is_demon(mtmp->data)))) dmg = (dmg+1) / 2; + + if (permdmg) { /* Death's life force drain */ + int lowerlimit, *hpmax_p; + /* + * Apply some of the damage to permanent hit points: + * polymorphed 100% against poly'd hpmax + * hpmax > 25*lvl 100% against normal hpmax + * hpmax > 10*lvl 50..100% + * hpmax > 5*lvl 25..75% + * otherwise 0..50% + * Never reduces hpmax below 1 hit point per level. + */ + permdmg = rn2(dmg / 2 + 1); + if (Upolyd || u.uhpmax > 25 * u.ulevel) permdmg = dmg; + else if (u.uhpmax > 10 * u.ulevel) permdmg += dmg / 2; + else if (u.uhpmax > 5 * u.ulevel) permdmg += dmg / 4; + + if (Upolyd) { + hpmax_p = &u.mhmax; + /* [can't use youmonst.m_lev] */ + lowerlimit = min((int)youmonst.data->mlevel, u.ulevel); + } else { + hpmax_p = &u.uhpmax; + lowerlimit = u.ulevel; + } + if (*hpmax_p - permdmg > lowerlimit) + *hpmax_p -= permdmg; + else if (*hpmax_p > lowerlimit) + *hpmax_p = lowerlimit; + else /* unlikely... */ + ; /* already at or below minimum threshold; do nothing */ + flags.botl = 1; + } + mdamageu(mtmp, dmg); } - if (dmg) { + if (dmg) res = passiveum(olduasmon, mtmp, mattk); - stop_occupation(); - return res; - } else - return 1; + else + res = 1; + stop_occupation(); + return res; } #endif /* OVL1 */ @@ -1519,10 +1596,9 @@ gulpmu(mtmp, mattk) /* monster swallows you, or damage if u.uswallow */ i = number_leashed(); if (i > 0) { - pline_The("leash%s snap%s loose.", - (i > 1) ? "es" : "", - (i > 1) ? "" : "s"); - unleash_all(); + char *s = (i > 1) ? "leashes" : "leash"; + pline_The("%s %s loose.", s, vtense(s, "snap")); + unleash_all(); } if (touch_petrifies(youmonst.data) && !resists_ston(mtmp)) { @@ -1585,6 +1661,7 @@ gulpmu(mtmp, mattk) /* monster swallows you, or damage if u.uswallow */ if(!Blind) { You_cant("see in here!"); make_blinded((long)tmp,FALSE); + if (!Blind) Your(vision_clears); } else /* keep him blind until disgorged */ make_blinded(Blinded+1,FALSE); @@ -1700,6 +1777,7 @@ boolean ufound; if (mon_visible(mtmp) || (rnd(tmp /= 2) > u.ulevel)) { You("are blinded by a blast of light!"); make_blinded((long)tmp, FALSE); + if (!Blind) Your(vision_clears); } else if (flags.verbose) You("get the impression it was not terribly bright."); } @@ -1726,6 +1804,7 @@ boolean ufound; } } mondead(mtmp); + wake_nearto(mtmp->mx, mtmp->my, 7*7); if (mtmp->mhp > 0) return(0); return(2); /* it dies */ } @@ -1737,13 +1816,20 @@ gazemu(mtmp, mattk) /* monster gazes at you */ { switch(mattk->adtyp) { case AD_STON: - if (mtmp->mcan) { - if (mtmp->data == &mons[PM_MEDUSA] && canseemon(mtmp)) - pline("%s doesn't look all that ugly.", Monnam(mtmp)); + if (mtmp->mcan || !mtmp->mcansee) { + if (mtmp->data == &mons[PM_MEDUSA] && canseemon(mtmp)) { + if (mtmp->mcan) { + pline("%s doesn't look all that ugly.", + Monnam(mtmp)); + break; + } + } + if (canseemon(mtmp)) + pline("%s gazes ineffectually.", Monnam(mtmp)); break; } - if(Reflecting && mtmp->mcansee && - !mtmp->mcan && mtmp->data == &mons[PM_MEDUSA]) { + if (Reflecting && canspotmon(mtmp) && + mtmp->data == &mons[PM_MEDUSA]) { if(!Blind) { (void) ureflects("%s gaze is reflected by your %s.", s_suffix(Monnam(mtmp))); @@ -1753,7 +1839,7 @@ gazemu(mtmp, mattk) /* monster gazes at you */ if (!m_canseeu(mtmp)) { /* probably you're invisible */ pline("%s doesn't seem to notice that %s gaze was reflected.", Monnam(mtmp), - his[pronoun_gender(mtmp)]); + mhis(mtmp)); break; } pline("%s is turned to stone!", Monnam(mtmp)); @@ -1764,19 +1850,22 @@ gazemu(mtmp, mattk) /* monster gazes at you */ if (mtmp->mhp > 0) break; return 2; } - if (canseemon(mtmp) && !Stone_resistance) { + if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my) && + !Stone_resistance) { You("meet %s gaze.", s_suffix(mon_nam(mtmp))); + stop_occupation(); if(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) break; You("turn to stone..."); killer_format = KILLED_BY; - killer = mons[PM_MEDUSA].mname; + killer = mtmp->data->mname; done(STONING); } break; case AD_CONF: - if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee && - !mtmp->mspec_used && rn2(5)) { + if(!mtmp->mcan && canseemon(mtmp) && + couldsee(mtmp->mx, mtmp->my) && + mtmp->mcansee && !mtmp->mspec_used && rn2(5)) { int conf = d(3,4); mtmp->mspec_used = mtmp->mspec_used + (conf + rn2(6)); @@ -1786,52 +1875,65 @@ gazemu(mtmp, mattk) /* monster gazes at you */ else You("are getting more and more confused."); make_confused(HConfusion + conf, FALSE); + stop_occupation(); } break; case AD_STUN: - if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee && - !mtmp->mspec_used && rn2(5)) { + if(!mtmp->mcan && canseemon(mtmp) && + couldsee(mtmp->mx, mtmp->my) && + mtmp->mcansee && !mtmp->mspec_used && rn2(5)) { int stun = d(2,6); mtmp->mspec_used = mtmp->mspec_used + (stun + rn2(6)); make_stunned(HStun + stun, TRUE); pline("%s stares piercingly at you!", Monnam(mtmp)); + stop_occupation(); } break; case AD_BLND: if (!mtmp->mcan && canseemon(mtmp) && !resists_blnd(&youmonst) && distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) { int blnd = d((int)mattk->damn, (int)mattk->damd); - make_blinded((long)blnd,FALSE); - make_stunned((long)d(1,3),TRUE); + You("are blinded by %s radiance!", s_suffix(mon_nam(mtmp))); + make_blinded((long)blnd,FALSE); + stop_occupation(); + /* not blind at this point implies you're wearing + the Eyes of the Overworld; make them block this + particular stun attack too */ + if (!Blind) Your(vision_clears); + else make_stunned((long)d(1,3),TRUE); } break; case AD_FIRE: - if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee && - !mtmp->mspec_used && rn2(5)) { - int dmg = d(2,6); - pline("%s attacks you with a fiery gaze!", - Monnam(mtmp)); - if (Fire_resistance) { - pline_The("fire doesn't feel hot!"); - dmg = 0; - } - burn_away_slime(); - if((int) mtmp->m_lev > rn2(20)) - destroy_item(SCROLL_CLASS, AD_FIRE); - if((int) mtmp->m_lev > rn2(20)) - destroy_item(POTION_CLASS, AD_FIRE); - if((int) mtmp->m_lev > rn2(25)) - destroy_item(SPBOOK_CLASS, AD_FIRE); - if (dmg) mdamageu(mtmp, dmg); - } + if (!mtmp->mcan && canseemon(mtmp) && + couldsee(mtmp->mx, mtmp->my) && + mtmp->mcansee && !mtmp->mspec_used && rn2(5)) { + int dmg = d(2,6); + + pline("%s attacks you with a fiery gaze!", Monnam(mtmp)); + stop_occupation(); + if (Fire_resistance) { + pline_The("fire doesn't feel hot!"); + dmg = 0; + } + burn_away_slime(); + if ((int) mtmp->m_lev > rn2(20)) + destroy_item(SCROLL_CLASS, AD_FIRE); + if ((int) mtmp->m_lev > rn2(20)) + destroy_item(POTION_CLASS, AD_FIRE); + if ((int) mtmp->m_lev > rn2(25)) + destroy_item(SPBOOK_CLASS, AD_FIRE); + if (dmg) mdamageu(mtmp, dmg); + } break; #ifdef PM_BEHOLDER /* work in progress */ case AD_SLEE: - if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee && + if(!mtmp->mcan && canseemon(mtmp) && + couldsee(mtmp->mx, mtmp->my) && mtmp->mcansee && multi >= 0 && !rn2(5) && !Sleep_resistance) { + fall_asleep(-rnd(10), TRUE); pline("%s gaze makes you very sleepy...", s_suffix(Monnam(mtmp))); @@ -1841,7 +1943,9 @@ gazemu(mtmp, mattk) /* monster gazes at you */ if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee && (HFast & (INTRINSIC|TIMEOUT)) && !defends(AD_SLOW, uwep) && !rn2(4)) + u_slow_down(); + stop_occupation(); break; #endif default: impossible("Gaze attack %d?", mattk->adtyp); @@ -1880,7 +1984,7 @@ register struct obj *obj; boolean is_acid; if (!mon || !obj) return; /* just in case */ - if (dmgtype(youmonst.data, AD_CORRODE)) + if (dmgtype(youmonst.data, AD_CORR)) is_acid = TRUE; else if (dmgtype(youmonst.data, AD_RUST)) is_acid = FALSE; @@ -1978,7 +2082,7 @@ register struct monst *mon; if (mon->mcan || mon->mspec_used) { pline("%s acts as though %s has got a %sheadache.", - Monnam(mon), he[pronoun_gender(mon)], + Monnam(mon), mhe(mon), mon->mcan ? "severe " : ""); return 0; } @@ -2064,7 +2168,7 @@ register struct monst *mon; else pline("%s murmurs in your ear, while helping you undress.", Blind ? (fem ? "She" : "He") : Monnam(mon)); - mayberem(uarmc, "cloak"); + mayberem(uarmc, cloak_simple_name(uarmc)); if(!uarmc) mayberem(uarm, "suit"); mayberem(uarmf, "boots"); @@ -2088,11 +2192,11 @@ register struct monst *mon; /* by this point you have discovered mon's identity, blind or not... */ pline("Time stands still while you and %s lie in each other's arms...", - mon_nam(mon)); + noit_mon_nam(mon)); if (rn2(35) > ACURR(A_CHA) + ACURR(A_INT)) { /* Don't bother with mspec_used here... it didn't get tired! */ pline("%s seems to have enjoyed it more than you...", - Monnam(mon)); + noit_Monnam(mon)); switch (rn2(5)) { case 0: You_feel("drained of energy."); u.uen = 0; @@ -2130,43 +2234,46 @@ register struct monst *mon; } } else { mon->mspec_used = rnd(100); /* monster is worn out */ - You("seem to have enjoyed it more than %s...", mon_nam(mon)); + You("seem to have enjoyed it more than %s...", + noit_mon_nam(mon)); switch (rn2(5)) { - case 0: You_feel("raised to your full potential."); - exercise(A_CON, TRUE); - u.uen = (u.uenmax += rnd(5)); - break; - case 1: You_feel("good enough to do it again."); - (void) adjattrib(A_CON, 1, TRUE); - exercise(A_CON, TRUE); - flags.botl = 1; - break; - case 2: You("will always remember %s...", mon_nam(mon)); - (void) adjattrib(A_WIS, 1, TRUE); - exercise(A_WIS, TRUE); - flags.botl = 1; - break; - case 3: pline("That was a very educational experience."); - pluslvl(FALSE); - exercise(A_WIS, TRUE); - break; - case 4: You_feel("restored to health!"); - u.uhp = u.uhpmax; - if (Upolyd) u.mh = u.mhmax; - exercise(A_STR, TRUE); - flags.botl = 1; - break; + case 0: You_feel("raised to your full potential."); + exercise(A_CON, TRUE); + u.uen = (u.uenmax += rnd(5)); + break; + case 1: You_feel("good enough to do it again."); + (void) adjattrib(A_CON, 1, TRUE); + exercise(A_CON, TRUE); + flags.botl = 1; + break; + case 2: You("will always remember %s...", noit_mon_nam(mon)); + (void) adjattrib(A_WIS, 1, TRUE); + exercise(A_WIS, TRUE); + flags.botl = 1; + break; + case 3: pline("That was a very educational experience."); + pluslvl(FALSE); + exercise(A_WIS, TRUE); + break; + case 4: You_feel("restored to health!"); + u.uhp = u.uhpmax; + if (Upolyd) u.mh = u.mhmax; + exercise(A_STR, TRUE); + flags.botl = 1; + break; } } if (mon->mtame) /* don't charge */ ; else if (rn2(20) < ACURR(A_CHA)) { pline("%s demands that you pay %s, but you refuse...", - Monnam(mon), him[fem]); + noit_Monnam(mon), + Blind ? (fem ? "her" : "him") : mhim(mon)); } else if (u.umonnum == PM_LEPRECHAUN) pline("%s tries to take your money, but fails...", - Monnam(mon)); + noit_Monnam(mon)); else { +#ifndef GOLDOBJ long cost; if (u.ugold > (long)LARGEST_INT - 10L) @@ -2180,12 +2287,33 @@ register struct monst *mon; if (cost > u.ugold) cost = u.ugold; if (!cost) verbalize("It's on the house!"); else { - pline("%s takes %ld zorkmid%s for services rendered!", - Monnam(mon), cost, plur(cost)); + pline("%s takes %ld %s for services rendered!", + noit_Monnam(mon), cost, currency(cost)); u.ugold -= cost; mon->mgold += cost; flags.botl = 1; } +#else + long cost; + long umoney = money_cnt(invent); + + if (umoney > (long)LARGEST_INT - 10L) + cost = (long) rnd(LARGEST_INT) + 500L; + else + cost = (long) rnd((int)umoney + 10) + 500L; + if (mon->mpeaceful) { + cost /= 5L; + if (!cost) cost = 1L; + } + if (cost > umoney) cost = umoney; + if (!cost) verbalize("It's on the house!"); + else { + pline("%s takes %ld %s for services rendered!", + noit_Monnam(mon), cost, currency(cost)); + money2mon(mon, cost); + flags.botl = 1; + } +#endif } if (!rn2(25)) mon->mcan = 1; /* monster is worn out */ if (!tele_restrict(mon)) rloc(mon); @@ -2262,14 +2390,18 @@ register struct attack *mattk; } } else tmp = 0; if (!rn2(30)) erode_armor(mtmp, TRUE); - if (!rn2(6)) erode_weapon(MON_WEP(mtmp), TRUE); + if (!rn2(6)) erode_obj(MON_WEP(mtmp), TRUE, TRUE); goto assess_dmg; case AD_STON: /* cockatrice */ + { + int protector = + mattk->aatyp == AT_TENT ? 0 : + mattk->aatyp == AT_KICK ? W_ARMF : W_ARMG; if (!resists_ston(mtmp) && (mattk->aatyp != AT_WEAP || !MON_WEP(mtmp)) && mattk->aatyp != AT_GAZE && mattk->aatyp != AT_EXPL && mattk->aatyp != AT_MAGC && - !(mtmp->misc_worn_check & W_ARMG)) { + !(mtmp->misc_worn_check & protector)) { if(poly_when_stoned(mtmp->data)) { mon_to_stone(mtmp); return (1); @@ -2281,6 +2413,7 @@ register struct attack *mattk; return 2; } return 1; + } case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */ if (otmp) { (void) drain_item(otmp); @@ -2345,7 +2478,8 @@ register struct attack *mattk; case AD_STUN: /* Yellow mold */ if (!mtmp->mstun) { mtmp->mstun = 1; - pline("%s staggers.", Monnam(mtmp)); + pline("%s %s.", Monnam(mtmp), + makeplural(stagger(mtmp->data, "stagger"))); } tmp = 0; break; diff --git a/src/minion.c b/src/minion.c index 87cf39c..2dfd0d1 100644 --- a/src/minion.c +++ b/src/minion.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)minion.c 3.3 2000/06/05 */ +/* SCCS Id: @(#)minion.c 3.4 2002/01/23 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -11,7 +11,7 @@ msummon(ptr) /* ptr summons a monster */ register struct permonst *ptr; { register int dtype = NON_PM, cnt = 0; - aligntyp atyp = sgn(ptr->maligntyp); + aligntyp atyp = (ptr->maligntyp==A_NONE) ? A_NONE : sgn(ptr->maligntyp); if (is_dprince(ptr) || (ptr == &mons[PM_WIZARD_OF_YENDOR])) { dtype = (!rn2(20)) ? dprince(atyp) : @@ -131,13 +131,17 @@ register struct monst *mtmp; if (!tele_restrict(mtmp)) rloc(mtmp); return(1); } +#ifndef GOLDOBJ demand = (u.ugold * (rnd(80) + 20 * Athome)) / - 100 * (1 + (sgn(u.ualign.type) == sgn(mtmp->data->maligntyp))); +#else + demand = (money_cnt(invent) * (rnd(80) + 20 * Athome)) / +#endif + (100 * (1 + (sgn(u.ualign.type) == sgn(mtmp->data->maligntyp)))); if (!demand) /* you have no gold */ return mtmp->mpeaceful = 0; else { - pline("%s demands %ld zorkmid%s for safe passage.", - Amonnam(mtmp), demand, plur(demand)); + pline("%s demands %ld %s for safe passage.", + Amonnam(mtmp), demand, currency(demand)); if ((offer = bribe(mtmp)) >= demand) { pline("%s vanishes, laughing about cowardly mortals.", @@ -162,26 +166,40 @@ struct monst *mtmp; { char buf[BUFSZ]; long offer; +#ifdef GOLDOBJ + long umoney = money_cnt(invent); +#endif getlin("How much will you offer?", buf); - (void) sscanf(buf, "%ld", &offer); + if (sscanf(buf, "%ld", &offer) != 1) offer = 0L; /*Michael Paddon -- fix for negative offer to monster*/ /*JAR880815 - */ if (offer < 0L) { You("try to shortchange %s, but fumble.", mon_nam(mtmp)); - offer = 0L; + return 0L; } else if (offer == 0L) { You("refuse."); + return 0L; +#ifndef GOLDOBJ } else if (offer >= u.ugold) { You("give %s all your gold.", mon_nam(mtmp)); offer = u.ugold; - } else You("give %s %ld zorkmid%s.", mon_nam(mtmp), offer, - plur(offer)); - + } else { + You("give %s %ld %s.", mon_nam(mtmp), offer, currency(offer)); + } u.ugold -= offer; mtmp->mgold += offer; +#else + } else if (offer >= umoney) { + You("give %s all your gold.", mon_nam(mtmp)); + offer = umoney; + } else { + You("give %s %ld %s.", mon_nam(mtmp), offer, currency(offer)); + } + (void) money2mon(mtmp, offer); +#endif flags.botl = 1; return(offer); } diff --git a/src/mklev.c b/src/mklev.c index a6449ae..dfcc739 100644 --- a/src/mklev.c +++ b/src/mklev.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mklev.c 3.3 99/04/22 */ +/* SCCS Id: @(#)mklev.c 3.4 2001/11/29 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -34,7 +34,9 @@ STATIC_DCL struct mkroom *FDECL(pos_to_room, (XCHAR_P, XCHAR_P)); STATIC_DCL boolean FDECL(place_niche,(struct mkroom *,int*,int*,int*)); STATIC_DCL void FDECL(makeniche,(int)); STATIC_DCL void NDECL(make_niches); + STATIC_PTR int FDECL(do_comp,(const genericptr,const genericptr)); + STATIC_DCL void FDECL(dosdoor,(XCHAR_P,XCHAR_P,struct mkroom *,int)); STATIC_DCL void FDECL(join,(int,int,BOOLEAN_P)); STATIC_DCL void FDECL(do_room_or_subroom, (struct mkroom *,int,int,int,int, @@ -498,8 +500,9 @@ int trap_type; dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR); else { if (!level.flags.noteleport) - (void) mksobj_at(SCR_TELEPORTATION, xx, yy+dy, TRUE); - if(!rn2(3)) (void) mkobj_at(0, xx, yy+dy, TRUE); + (void) mksobj_at(SCR_TELEPORTATION, + xx, yy+dy, TRUE, FALSE); + if (!rn2(3)) (void) mkobj_at(0, xx, yy+dy, TRUE); } } return; @@ -761,8 +764,8 @@ makelevel() x = somex(croom); y = somey(croom); tmonst = makemon((struct permonst *) 0, x,y,NO_MM_FLAGS); if (tmonst && tmonst->data == &mons[PM_GIANT_SPIDER] && - !is_pool(x,y)) - (void) maketrap (x,y,WEB); + !occupied(x, y)) + (void) maketrap(x, y, WEB); } /* put traps and mimics inside */ goldseen = FALSE; @@ -796,7 +799,7 @@ makelevel() */ if(!rn2(nroom * 5 / 2)) (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, - somex(croom), somey(croom), TRUE); + somex(croom), somey(croom), TRUE, FALSE); /* maybe make some graffiti */ if(!rn2(27 + 3 * abs(depth(&u.uz)))) { @@ -848,7 +851,7 @@ mineralize() for (y = 1; y < (ROWNO - 1); y++) if ((levl[x][y].typ == POOL && !rn2(10)) || (levl[x][y].typ == MOAT && !rn2(30))) - (void)mksobj_at(KELP_FROND, x, y, TRUE); + (void) mksobj_at(KELP_FROND, x, y, TRUE, FALSE); /* determine if it is even allowed; almost all special levels are excluded */ @@ -1403,7 +1406,7 @@ struct mkroom *croom; } /* Leave a bell, in case we accidentally buried someone alive */ - if (dobell) (void) mksobj_at(BELL, m.x, m.y, TRUE); + if (dobell) (void) mksobj_at(BELL, m.x, m.y, TRUE, FALSE); return; } diff --git a/src/mkmap.c b/src/mkmap.c index 65e3d94..f9a68d6 100644 --- a/src/mkmap.c +++ b/src/mkmap.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mkmap.c 3.3 96/05/23 */ +/* SCCS Id: @(#)mkmap.c 3.4 1996/05/23 */ /* Copyright (c) J. C. Collet, M. Stephenson and D. Cohrs, 1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -348,6 +348,7 @@ finish_map(fg_typ, bg_typ, lit, walled) for(j=0; jrndlevs) { + char *ep = getenv("SPLEVTYPE"); /* not nh_getenv */ + if (ep) { + /* rindex always succeeds due to code in prior block */ + int len = (rindex(protofile, '-') - protofile) + 1; + + while (ep && *ep) { + if (!strncmp(ep, protofile, len)) { + int pick = atoi(ep + len); + /* use choice only if valid */ + if (pick > 0 && pick <= (int) sp->rndlevs) + Sprintf(protofile + len, "%d", pick); + break; + } else { + ep = index(ep, ','); + if (ep) ++ep; + } + } + } + } +#endif + if(*protofile) { Strcat(protofile, LEV_EXT); if(load_special(protofile)) { fixup_special(); /* some levels can end up with monsters - on dead mon list, including light source monsters */ + on dead mon list, including light source monsters */ dmonsfree(); return; /* no mazification right now */ } @@ -540,7 +566,7 @@ register const char *s; maze0xy(&mm); walkfrom((int) mm.x, (int) mm.y); /* put a boulder at the maze center */ - (void) mksobj_at(BOULDER, (int) mm.x, (int) mm.y, TRUE); + (void) mksobj_at(BOULDER, (int) mm.x, (int) mm.y, TRUE, FALSE); #ifdef WALLIFIED_MAZE wallification(2, 2, x_maze_max, y_maze_max); @@ -603,7 +629,7 @@ register const char *s; } for(x = rn1(10,2); x; x--) { mazexy(&mm); - (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE); + (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE, FALSE); } for (x = rn2(3); x; x--) { mazexy(&mm); @@ -880,24 +906,12 @@ register xchar x, y, todnum, todlevel; /* to ease the work of debuggers at this stage */ #define register -struct container { - struct container *next; - xchar x, y; - short what; - genericptr_t list; -}; #define CONS_OBJ 0 #define CONS_MON 1 #define CONS_HERO 2 #define CONS_TRAP 3 -static struct bubble { - xchar x, y; /* coordinates of the upper left corner */ - schar dx, dy; /* the general direction of the bubble's movement */ - uchar *bm; /* pointer to the bubble bit mask */ - struct bubble *prev, *next; /* need to traverse the list up and down */ - struct container *cons; -} *bbubbles, *ebubbles; +static struct bubble *bbubbles, *ebubbles; static struct trap *wportal; static int xmin, ymin, xmax, ymax; /* level boundaries */ diff --git a/src/mkobj.c b/src/mkobj.c index 69f83fb..a0e8c44 100644 --- a/src/mkobj.c +++ b/src/mkobj.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mkobj.c 3.3 2000/02/19 */ +/* SCCS Id: @(#)mkobj.c 3.4 2001/12/03 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -78,26 +78,26 @@ const struct icp hellprobs[] = { }; struct obj * -mkobj_at(let,x,y, artif) +mkobj_at(let, x, y, artif) char let; -int x,y; +int x, y; boolean artif; { - register struct obj *otmp; + struct obj *otmp; - otmp = mkobj(let,artif); + otmp = mkobj(let, artif); place_object(otmp, x, y); return(otmp); } struct obj * -mksobj_at(otyp,x,y,init) -int otyp,x,y; -boolean init; +mksobj_at(otyp, x, y, init, artif) +int otyp, x, y; +boolean init, artif; { - register struct obj *otmp; + struct obj *otmp; - otmp = mksobj(otyp,init,TRUE); + otmp = mksobj(otyp, init, artif); place_object(otmp, x, y); return(otmp); } @@ -107,7 +107,7 @@ mkobj(oclass, artif) char oclass; boolean artif; { - register int tprob, i, prob = rnd(1000); + int tprob, i, prob = rnd(1000); if(oclass == RANDOM_CLASS) { const struct icp *iprobs = @@ -138,21 +138,21 @@ mkbox_cnts(box) struct obj *box; { register int n; - register struct obj *otmp, *gold = 0; + register struct obj *otmp; box->cobj = (struct obj *) 0; - switch(box->otyp) { - case ICE_BOX: n = 20; break; - case CHEST: n = 5; break; - case LARGE_BOX: n = 3; break; - case SACK: - case OILSKIN_SACK: + switch (box->otyp) { + case ICE_BOX: n = 20; break; + case CHEST: n = 5; break; + case LARGE_BOX: n = 3; break; + case SACK: + case OILSKIN_SACK: /* initial inventory: sack starts out empty */ if (moves <= 1 && !in_mklev) { n = 0; break; } /*else FALLTHRU*/ - case BAG_OF_HOLDING: n = 1; break; - default: n = 0; break; + case BAG_OF_HOLDING: n = 1; break; + default: n = 0; break; } for (n = rn2(n+1); n > 0; n--) { @@ -178,13 +178,7 @@ struct obj *box; if (otmp->oclass == GOLD_CLASS) { /* 2.5 x level's usual amount; weight adjusted below */ otmp->quan = (long)(rnd(level_difficulty()+2) * rnd(75)); - if (gold) { /* gold already in this box */ - gold->quan += otmp->quan; /* merge */ - dealloc_obj(otmp); /* note: not yet in any chain */ - continue; - } else { - gold = otmp; /* remember this object */ - } + otmp->owt = weight(otmp); } else while (otmp->otyp == ROCK) { otmp->otyp = rnd_class(DILITHIUM_CRYSTAL, LOADSTONE); if (otmp->quan > 2L) otmp->quan = 1L; @@ -199,10 +193,8 @@ struct obj *box; otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING); } } - add_to_container(box, otmp); + (void) add_to_container(box, otmp); } - if (gold) gold->owt = weight(gold); /* quantity was diddled */ - return; } int @@ -225,10 +217,10 @@ rndmonnum() /* select a random, common monster type */ } /* - * Split obj so that it gets size num. The remainder is put in the object - * structure delivered by this call. The object is positioned just - * following the original in the nobj chain (and nexthere chain when on - * the floor). + * Split obj so that it gets size gets reduced by num. The quantity num is + * put in the object structure delivered by this call. The returned object + * has its wornmask cleared and is positioned just following the original + * in the nobj chain (and nexthere chain when on the floor). */ struct obj * splitobj(obj, num) @@ -237,7 +229,7 @@ long num; { struct obj *otmp; - if (obj->cobj || num <= 0L || obj->quan < num) + if (obj->cobj || num <= 0L || obj->quan <= num) panic("splitobj"); /* can't split containers */ otmp = newobj(obj->oxlth + obj->onamelth); *otmp = *obj; /* copies whole structure */ @@ -245,9 +237,10 @@ long num; if (!otmp->o_id) otmp->o_id = flags.ident++; /* ident overflowed */ otmp->timed = 0; /* not timed, yet */ otmp->lamplit = 0; /* ditto */ - obj->quan = num; + otmp->owornmask = 0L; /* new object isn't worn */ + obj->quan -= num; obj->owt = weight(obj); - otmp->quan -= num; + otmp->quan = num; otmp->owt = weight(otmp); /* -= obj->owt ? */ obj->nobj = otmp; /* Only set nexthere when on the floor, nexthere is also used */ @@ -452,14 +445,17 @@ boolean artif; case SLIME_MOLD: otmp->spe = current_fruit; break; + case KELP_FROND: + otmp->quan = (long) rnd(2); + break; } - if (otmp->otyp == CORPSE || otmp->otyp == MEAT_RING) break; + if (otmp->otyp == CORPSE || otmp->otyp == MEAT_RING || + otmp->otyp == KELP_FROND) break; /* fall into next case */ case GEM_CLASS: if (otmp->otyp == LOADSTONE) curse(otmp); else if (otmp->otyp == ROCK) otmp->quan = (long) rn1(6,6); - else if (otmp->otyp == KELP_FROND) otmp->quan = (long) rnd(2); else if (otmp->otyp != LUCKSTONE && !rn2(6)) otmp->quan = 2L; else otmp->quan = 1L; break; @@ -609,7 +605,8 @@ boolean artif; otmp->corpsenm = rndmonnum(); if (!verysmall(&mons[otmp->corpsenm]) && rn2(level_difficulty()/2 + 10) > 10) - add_to_container(otmp, mkobj(SPBOOK_CLASS,FALSE)); + (void) add_to_container(otmp, + mkobj(SPBOOK_CLASS,FALSE)); } break; case GOLD_CLASS: @@ -627,27 +624,32 @@ boolean artif; } /* - * Start a corpse decay or revive timer. This assumes that the corpse - * was just dropped and its age is 0. + * Start a corpse decay or revive timer. + * This takes the age of the corpse into consideration as of 3.4.0. */ void start_corpse_timeout(body) struct obj *body; { - long when; + long when; /* rot away when this old */ + long corpse_age; /* age of corpse */ int rot_adjust; short action; #define TAINT_AGE (50L) /* age when corpses go bad */ #define TROLL_REVIVE_CHANCE 37 /* 1/37 chance for 50 turns ~ 75% chance */ -#define ROT_AGE (250L) /* age when corpses rot away */ +#define ROT_AGE (250L) /* age when corpses rot away */ /* lizards and lichen don't rot or revive */ if (body->corpsenm == PM_LIZARD || body->corpsenm == PM_LICHEN) return; action = ROT_CORPSE; /* default action: rot away */ - when = ROT_AGE; /* rot away when this old */ rot_adjust = in_mklev ? 25 : 10; /* give some variation */ + corpse_age = monstermoves - body->age; + if (corpse_age > ROT_AGE) + when = rot_adjust; + else + when = ROT_AGE - corpse_age; when += (long)(rnz(rot_adjust) - rot_adjust); if (is_rider(&mons[body->corpsenm])) { @@ -659,7 +661,7 @@ start_corpse_timeout(body) for (when = 12L; when < 500L; when++) if (!rn2(3)) break; - } else if (mons[body->corpsenm].mlet == S_TROLL) { + } else if (mons[body->corpsenm].mlet == S_TROLL && !body->norevive) { long age; for (age = 2; age <= TAINT_AGE; age++) if (!rn2(TROLL_REVIVE_CHANCE)) { /* troll revives */ @@ -668,7 +670,8 @@ start_corpse_timeout(body) break; } } - + + if (body->norevive) body->norevive = 0; (void) start_timer(when, TIMER_OBJECT, action, (genericptr_t)body); } @@ -819,9 +822,15 @@ register struct obj *obj; return wt + cwt; } - if (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM) - return (int)obj->quan * mons[obj->corpsenm].cwt; - else if (obj->oclass == GOLD_CLASS) + if (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM) { + long long_wt = obj->quan * (long) mons[obj->corpsenm].cwt; + + wt = (long_wt > LARGEST_INT) ? LARGEST_INT : (int)long_wt; + if (obj->oeaten) wt = eaten_stat(wt, obj); + return wt; + } else if (obj->oclass == FOOD_CLASS && obj->oeaten) { + return eaten_stat((int)obj->quan * wt, obj); + } else if (obj->oclass == GOLD_CLASS) return (int)((obj->quan + 50L) / 100L); else if (obj->otyp == HEAVY_IRON_BALL && obj->owt != 0) return((int)(obj->owt)); /* kludge for "very" heavy iron ball */ @@ -832,8 +841,9 @@ static int treefruits[] = {APPLE,ORANGE,PEAR,BANANA,EUCALYPTUS_LEAF}; struct obj * rnd_treefruit_at(x,y) +int x, y; { - return mksobj_at(treefruits[rn2(SIZE(treefruits)-1)],x,y,TRUE); + return mksobj_at(treefruits[rn2(SIZE(treefruits))], x, y, TRUE, FALSE); } #endif /* OVL0 */ #ifdef OVLB @@ -845,11 +855,12 @@ int x, y; { register struct obj *gold = g_at(x,y); - if (amount <= 0L) amount = (long)(1 + rnd(level_difficulty()+2) * rnd(30)); + if (amount <= 0L) + amount = (long)(1 + rnd(level_difficulty()+2) * rnd(30)); if (gold) { gold->quan += amount; } else { - gold = mksobj_at(GOLD_PIECE,x,y,TRUE); + gold = mksobj_at(GOLD_PIECE, x, y, TRUE, FALSE); gold->quan = amount; } gold->owt = weight(gold); @@ -886,7 +897,7 @@ boolean init; if (objtype != CORPSE && objtype != STATUE) impossible("making corpstat type %d", objtype); - otmp = mksobj_at(objtype, x, y, init); + otmp = mksobj_at(objtype, x, y, init, FALSE); if (otmp) { if (mtmp) { struct obj *otmp2; @@ -955,8 +966,9 @@ struct monst *mtmp; if (otmp && otmp->oxlth) { struct monst *mtmp2 = (struct monst *)otmp->oextra; if (mtmp->data) mtmp2->mnum = monsndx(mtmp->data); - /* invalidate pointers and m_id */ - mtmp2->m_id = 0; + /* invalidate pointers */ + /* m_id is needed to know if this is a revived quest leader */ + /* but m_id must be cleared when loading bones */ mtmp2->nmon = (struct monst *)0; mtmp2->data = (struct permonst *)0; mtmp2->minvent = (struct obj *)0; @@ -1007,7 +1019,7 @@ register int x, y; /* player statues never contain books */ initialize_it = (objtype != STATUE); - if ((otmp = mksobj_at(objtype, x, y, initialize_it)) != 0) { + if ((otmp = mksobj_at(objtype, x, y, initialize_it, FALSE)) != 0) { /* tt_oname will return null if the scoreboard is empty */ if ((otmp2 = tt_oname(otmp)) != 0) otmp = otmp2; } @@ -1036,8 +1048,19 @@ is_flammable(otmp) register struct obj *otmp; { int otyp = otmp->otyp; + int omat = objects[otyp].oc_material; - if (objects[otyp].oc_oprop == FIRE_RES) return FALSE; + if (objects[otyp].oc_oprop == FIRE_RES || otyp == WAN_FIRE) + return FALSE; + + return((boolean)((omat <= WOOD && omat != LIQUID) || omat == PLASTIC)); +} + +boolean +is_rottable(otmp) +register struct obj *otmp; +{ + int otyp = otmp->otyp; return((boolean)(objects[otyp].oc_material <= WOOD && objects[otyp].oc_material != LIQUID)); @@ -1062,6 +1085,7 @@ int x, y; if (otmp->where != OBJ_FREE) panic("place_object: obj not free"); + obj_no_longer_held(otmp); if (otmp->otyp == BOULDER) block_point(x,y); /* vision */ /* obj goes under boulders */ @@ -1361,17 +1385,30 @@ add_to_minv(mon, obj) return 0; /* obj on mon's inventory chain */ } -void +/* + * Add obj to container, make sure obj is "free". Returns (merged) obj. + * The input obj may be deleted in the process. + */ +struct obj * add_to_container(container, obj) struct obj *container, *obj; { + struct obj *otmp; + if (obj->where != OBJ_FREE) panic("add_to_container: obj not free"); + if (container->where != OBJ_INVENT && container->where != OBJ_MINVENT) + obj_no_longer_held(obj); + + /* merge if possible */ + for (otmp = container->cobj; otmp; otmp = otmp->nobj) + if (merged(&otmp, &obj)) return (otmp); obj->where = OBJ_CONTAINED; obj->ocontainer = container; obj->nobj = container->cobj; container->cobj = obj; + return (obj); } void diff --git a/src/mkroom.c b/src/mkroom.c index f6e435e..1be8b0d 100644 --- a/src/mkroom.c +++ b/src/mkroom.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mkroom.c 3.3 97/05/25 */ +/* SCCS Id: @(#)mkroom.c 3.4 2001/09/06 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -325,31 +325,35 @@ struct mkroom *sroom; (void) mk_tt_object(CORPSE, sx, sy); if(!rn2(10)) /* lots of treasure buried with dead */ (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, - sx, sy, TRUE); + sx, sy, TRUE, FALSE); if (!rn2(5)) make_grave(sx, sy, (char *)0); break; case BEEHIVE: if(!rn2(3)) - (void) mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy, TRUE); + (void) mksobj_at(LUMP_OF_ROYAL_JELLY, + sx, sy, TRUE, FALSE); break; case BARRACKS: if(!rn2(20)) /* the payroll and some loot */ (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, - sx, sy, TRUE); + sx, sy, TRUE, FALSE); break; case COCKNEST: if(!rn2(3)) { struct obj *sobj = mk_tt_object(STATUE, sx, sy); - if (sobj) - for (i = rn2(5); i; i--) - add_to_container(sobj, mkobj(RANDOM_CLASS, FALSE)); + if (sobj) { + for (i = rn2(5); i; i--) + (void) add_to_container(sobj, + mkobj(RANDOM_CLASS, FALSE)); + sobj->owt = weight(sobj); + } } break; case ANTHOLE: if(!rn2(3)) - (void) mkobj_at(FOOD_CLASS, sx, sy, TRUE); + (void) mkobj_at(FOOD_CLASS, sx, sy, FALSE); break; } } @@ -360,7 +364,8 @@ struct mkroom *sroom; levl[tx][ty].typ = THRONE; (void) somexy(sroom, &mm); (void) mkgold((long) rn1(50 * level_difficulty(),10), mm.x, mm.y); - chest = mksobj_at(CHEST, mm.x, mm.y, TRUE); /* the royal coffers */ + /* the royal coffers */ + chest = mksobj_at(CHEST, mm.x, mm.y, TRUE, FALSE); chest->spe = 2; /* so it can be found later */ level.flags.has_court = 1; break; diff --git a/src/mon.c b/src/mon.c index 3fc077c..816370e 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mon.c 3.3 2000/07/24 */ +/* SCCS Id: @(#)mon.c 3.4 2002/03/09 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -12,7 +12,6 @@ #include "edog.h" #include -STATIC_DCL boolean FDECL(corpse_chance,(struct monst *)); STATIC_DCL boolean FDECL(restrap,(struct monst *)); STATIC_DCL long FDECL(mm_aggression, (struct monst *,struct monst *)); #ifdef OVL2 @@ -21,6 +20,16 @@ STATIC_DCL int FDECL(select_newcham_form, (struct monst *)); STATIC_DCL void FDECL(kill_eggs, (struct obj *)); #endif +#ifdef REINCARNATION +#define LEVEL_SPECIFIC_NOCORPSE(mdat) \ + (Is_rogue_level(&u.uz) || \ + (level.flags.graveyard && is_undead(mdat) && rn2(3))) +#else +#define LEVEL_SPECIFIC_NOCORPSE(mdat) \ + (level.flags.graveyard && is_undead(mdat) && rn2(3)) +#endif + + #if 0 /* part of the original warning code which was replaced in 3.3.1 */ #ifdef OVL1 @@ -99,11 +108,9 @@ STATIC_VAR short cham_to_pm[] = { PM_SANDESTIN, }; -/* return TRUE if the monster tends to revive */ -#define REVIVER(ptr) (is_rider(ptr) || ptr->mlet == S_TROLL) - #define KEEPTRAITS(mon) (mon->isshk || mon->mtame || \ - (mon->data->geno & G_UNIQ) || REVIVER(mon->data)) + (mon->data->geno & G_UNIQ) || is_reviver(mon->data) || \ + (mon->m_id == quest_status.leader_m_id)) /* Creates a monster corpse, a "special" corpse, or nothing if it doesn't * leave corpses. Monsters which leave "special" corpses should have @@ -136,8 +143,8 @@ register struct monst *mtmp; /* Make dragon scales. This assumes that the order of the */ /* dragons is the same as the order of the scales. */ if (!rn2(mtmp->mrevived ? 20 : 3)) { - obj = mksobj_at(GRAY_DRAGON_SCALES + - monsndx(mdat)-PM_GRAY_DRAGON, x, y, FALSE); + num = GRAY_DRAGON_SCALES + monsndx(mdat) - PM_GRAY_DRAGON; + obj = mksobj_at(num, x, y, FALSE, FALSE); obj->spe = 0; obj->cursed = obj->blessed = FALSE; } @@ -146,10 +153,15 @@ register struct monst *mtmp; case PM_WHITE_UNICORN: case PM_GRAY_UNICORN: case PM_BLACK_UNICORN: - (void) mksobj_at(UNICORN_HORN, x, y, TRUE); + if (mtmp->mrevived && rn2(20)) { + if (canseemon(mtmp)) + pline("%s recently regrown horn crumbles to dust.", + s_suffix(Monnam(mtmp))); + } else + (void) mksobj_at(UNICORN_HORN, x, y, TRUE, FALSE); goto default_1; case PM_LONG_WORM: - (void) mksobj_at(WORM_TOOTH, x, y, TRUE); + (void) mksobj_at(WORM_TOOTH, x, y, TRUE, FALSE); goto default_1; case PM_VAMPIRE: case PM_VAMPIRE_LORD: @@ -181,17 +193,17 @@ register struct monst *mtmp; case PM_IRON_GOLEM: num = d(2,6); while (num--) - obj = mksobj_at(IRON_CHAIN, x, y, TRUE); + obj = mksobj_at(IRON_CHAIN, x, y, TRUE, FALSE); mtmp->mnamelth = 0; break; case PM_GLASS_GOLEM: num = d(2,4); /* very low chance of creating all glass gems */ while (num--) - obj = mksobj_at((LAST_GEM + rnd(9)), x, y, TRUE); + obj = mksobj_at((LAST_GEM + rnd(9)), x, y, TRUE, FALSE); mtmp->mnamelth = 0; break; case PM_CLAY_GOLEM: - obj = mksobj_at(ROCK, x, y, FALSE); + obj = mksobj_at(ROCK, x, y, FALSE, FALSE); obj->quan = (long)(rn2(20) + 50); obj->owt = weight(obj); mtmp->mnamelth = 0; @@ -203,18 +215,14 @@ register struct monst *mtmp; case PM_WOOD_GOLEM: num = d(2,4); while(num--) { - obj = mksobj_at(QUARTERSTAFF, x, y, TRUE); - if (obj && obj->oartifact) { /* don't allow this */ - artifact_exists(obj, ONAME(obj), FALSE); - Strcpy(ONAME(obj), ""); obj->onamelth = 0; - } + obj = mksobj_at(QUARTERSTAFF, x, y, TRUE, FALSE); } mtmp->mnamelth = 0; break; case PM_LEATHER_GOLEM: num = d(2,4); while(num--) - obj = mksobj_at(LEATHER_ARMOR, x, y, TRUE); + obj = mksobj_at(LEATHER_ARMOR, x, y, TRUE, FALSE); mtmp->mnamelth = 0; break; case PM_GOLD_GOLEM: @@ -223,9 +231,9 @@ register struct monst *mtmp; mtmp->mnamelth = 0; break; case PM_PAPER_GOLEM: - num = d(2,3); + num = rnd(4); while (num--) - obj = mksobj_at(SCR_BLANK_PAPER, x, y, TRUE); + obj = mksobj_at(SCR_BLANK_PAPER, x, y, TRUE, FALSE); mtmp->mnamelth = 0; break; default_1: @@ -239,6 +247,10 @@ register struct monst *mtmp; } /* All special cases should precede the G_NOCORPSE check */ + /* if polymorph or undead turning has killed this monster, + prevent the same attack beam from hitting its corpse */ + if (flags.bypasses) bypass_obj(obj); + if (mtmp->mnamelth) obj = oname(obj, NAME(mtmp)); @@ -306,19 +318,21 @@ warn_effects() } #endif /* 0 */ -/* check mtmp and water for compatibility, 0 (survived), 1 (drowned) */ +/* check mtmp and water/lava for compatibility, 0 (survived), 1 (died) */ int -minwater(mtmp) +minliquid(mtmp) register struct monst *mtmp; { - boolean inpool, infountain; + boolean inpool, inlava, infountain; inpool = is_pool(mtmp->mx,mtmp->my) && !is_flyer(mtmp->data) && !is_floater(mtmp->data); + inlava = is_lava(mtmp->mx,mtmp->my) && + !is_flyer(mtmp->data) && !is_floater(mtmp->data); infountain = IS_FOUNTAIN(levl[mtmp->mx][mtmp->my].typ); #ifdef STEED - /* Flying and levitation keeps our steed out of the water */ + /* Flying and levitation keeps our steed out of the liquid */ /* (but not water-walking or swimming) */ if (mtmp == u.usteed && (Flying || Levitation)) return (0); @@ -347,7 +361,36 @@ register struct monst *mtmp; return (0); } - if (inpool) { + if (inlava) { + /* + * Lava effects much as water effects. Lava likers are able to + * protect their stuff. Fire resistant monsters can only protect + * themselves --ALI + */ + if (!is_clinger(mtmp->data) && !likes_lava(mtmp->data)) { + if (!resists_fire(mtmp)) { + if (cansee(mtmp->mx,mtmp->my)) + pline("%s burns to a crisp.", Monnam(mtmp)); + mondead(mtmp); + } + else { + if (--mtmp->mhp < 1) { + if (cansee(mtmp->mx,mtmp->my)) + pline("%s surrenders to the fire.", Monnam(mtmp)); + mondead(mtmp); + } + else if (cansee(mtmp->mx,mtmp->my)) + pline("%s burns slightly.", Monnam(mtmp)); + } + if (mtmp->mhp > 0) { + (void) fire_damage(mtmp->minvent, FALSE, FALSE, + mtmp->mx, mtmp->my); + rloc(mtmp); + return 0; + } + return (1); + } + } else if (inpool) { /* Most monsters drown in pools. flooreffects() will take care of * water damage to dead monsters' inventory, but survivors need to * be handled here. Swimmers are able to protect their stuff... @@ -369,8 +412,7 @@ register struct monst *mtmp; /* but eels have a difficult time outside */ if (mtmp->data->mlet == S_EEL && !Is_waterlevel(&u.uz)) { if(mtmp->mhp > 1) mtmp->mhp--; - mtmp->mflee = 1; - mtmp->mfleetim += 2; + monflee(mtmp, 2, FALSE, FALSE); } } return (0); @@ -420,7 +462,7 @@ mcalcdistress() /* possibly polymorph shapechangers and lycanthropes */ if (mtmp->cham && !rn2(6)) - (void) newcham(mtmp, (struct permonst *)0); + (void) newcham(mtmp, (struct permonst *)0, FALSE); were_change(mtmp); /* gradually time out temporary problems */ @@ -477,7 +519,9 @@ movemon() if (mtmp->movement >= NORMAL_SPEED) somebody_can_move = TRUE; - if (minwater(mtmp)) continue; + if (vision_full_recalc) vision_recalc(0); /* vision! */ + + if (minliquid(mtmp)) continue; if (is_hider(mtmp->data)) { /* unwatched mimics and piercers may hide again [MRS] */ @@ -541,7 +585,7 @@ movemon() * has young and old forms). */ int -meatgold(mtmp) +meatmetal(mtmp) register struct monst *mtmp; { register struct obj *otmp; @@ -553,7 +597,9 @@ meatgold(mtmp) /* Eats topmost metal object if it is there */ for (otmp = level.objects[mtmp->mx][mtmp->my]; - otmp; otmp = otmp->nexthere) + otmp; otmp = otmp->nexthere) { + if (mtmp->data == &mons[PM_RUST_MONSTER] && !is_rustprone(otmp)) + continue; if (is_metallic(otmp) && !obj_resists(otmp, 5, 95) && touch_artifact(otmp,mtmp)) { if (mtmp->data == &mons[PM_RUST_MONSTER] && otmp->oerodeproof) { @@ -596,7 +642,7 @@ meatgold(mtmp) delobj(otmp); ptr = mtmp->data; if (poly) { - if (newcham(mtmp, (struct permonst *)0)) + if (newcham(mtmp, (struct permonst *)0, FALSE)) ptr = mtmp->data; } else if (grow) { ptr = grow_up(mtmp, (struct monst *)0); @@ -616,11 +662,13 @@ meatgold(mtmp) if (!ptr) return 2; /* it died */ } /* Left behind a pile? */ - if(rnd(25) < 3) (void) mksobj_at(ROCK, mtmp->mx, mtmp->my, TRUE); + if (rnd(25) < 3) + (void)mksobj_at(ROCK, mtmp->mx, mtmp->my, TRUE, FALSE); newsym(mtmp->mx, mtmp->my); return 1; } } + } return 0; } @@ -679,7 +727,7 @@ meatobj(mtmp) /* for gelatinous cubes */ delobj(otmp); /* munch */ ptr = mtmp->data; if (poly) { - if (newcham(mtmp, (struct permonst *)0)) ptr = mtmp->data; + if (newcham(mtmp, (struct permonst *)0, FALSE)) ptr = mtmp->data; } else if (grow) { ptr = grow_up(mtmp, (struct monst *)0); } else if (heal) { @@ -720,11 +768,19 @@ mpickgold(mtmp) register struct obj *gold; if ((gold = g_at(mtmp->mx, mtmp->my)) != 0) { +#ifndef GOLDOBJ mtmp->mgold += gold->quan; delobj(gold); if (cansee(mtmp->mx, mtmp->my) ) { if (flags.verbose && !mtmp->isgd) pline("%s picks up some gold.", Monnam(mtmp)); +#else + obj_extract_self(gold); + add_to_minv(mtmp, gold); + if (cansee(mtmp->mx, mtmp->my) ) { + if (flags.verbose && !mtmp->isgd) + pline("%s picks up some money.", Monnam(mtmp)); +#endif newsym(mtmp->mx, mtmp->my); } } @@ -747,16 +803,11 @@ mpickstuff(mtmp, str) /* Nymphs take everything. Most monsters don't pick up corpses. */ if (!str ? searches_for_item(mtmp,otmp) : !!(index(str, otmp->oclass))) { - if (otmp->otyp == CORPSE && ( - is_rider(&mons[otmp->corpsenm]) || - (touch_petrifies(&mons[otmp->corpsenm]) - && !(mtmp->misc_worn_check & W_ARMG)) || - (mtmp->data->mlet != S_NYMPH - && !touch_petrifies(&mons[otmp->corpsenm]) - && otmp->corpsenm != PM_LIZARD - && !acidic(&mons[otmp->corpsenm])) - )) - continue; + if (otmp->otyp == CORPSE && mtmp->data->mlet != S_NYMPH && + /* let a handful of corpse types thru to can_carry() */ + !touch_petrifies(&mons[otmp->corpsenm]) && + otmp->corpsenm != PM_LIZARD && + !acidic(&mons[otmp->corpsenm])) continue; if (!touch_artifact(otmp,mtmp)) continue; if (!can_carry(mtmp,otmp)) continue; if (is_pool(mtmp->mx,mtmp->my)) continue; @@ -840,6 +891,8 @@ struct obj *otmp; if (otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]) && !(mtmp->misc_worn_check & W_ARMG) && !resists_ston(mtmp)) return FALSE; + if (otyp == CORPSE && is_rider(&mons[otmp->corpsenm])) + return FALSE; if (objects[otyp].oc_material == SILVER && hates_silver(mdat) && (otyp != BELL_OF_OPENING || !is_covetous(mdat))) return FALSE; @@ -1188,7 +1241,7 @@ m_detach(mtmp, mptr) struct monst *mtmp; struct permonst *mptr; /* reflects mtmp->data _prior_ to mtmp's death */ { - if(mtmp->mleashed) m_unleash(mtmp); + if (mtmp->mleashed) m_unleash(mtmp, FALSE); /* to prevent an infinite relobj-flooreffects-hmon-killed loop */ mtmp->mtrapped = 0; mtmp->mhp = 0; /* simplify some tests: force mhp to 0 */ @@ -1310,6 +1363,10 @@ register struct monst *mtmp; */ tmp = monsndx(mtmp->data); if (mvitals[tmp].died < 255) mvitals[tmp].died++; + + /* if it's a (possibly polymorphed) quest leader, mark him as dead */ + if (mtmp->m_id == quest_status.leader_m_id) + quest_status.leader_is_dead = TRUE; #ifdef MAIL /* if the mail daemon dies, no more mail delivery. -3. */ if (tmp == PM_MAIL_DAEMON) mvitals[tmp].mvflags |= G_GENOD; @@ -1337,19 +1394,20 @@ register struct monst *mtmp; m_detach(mtmp, mptr); } -STATIC_OVL boolean -corpse_chance(mon) +/* TRUE if corpse might be dropped, magr may die if mon was swallowed */ +boolean +corpse_chance(mon, magr, was_swallowed) struct monst *mon; +struct monst *magr; /* killer, if swallowed */ +boolean was_swallowed; /* digestion */ { struct permonst *mdat = mon->data; int i, tmp; - if (mdat == &mons[PM_VLAD_THE_IMPALER] || mdat->mlet == S_LICH) { - if (cansee(mon->mx, mon->my)) - pline("%s body crumbles into dust.", - s_suffix(Monnam(mon))); - return FALSE; + if (cansee(mon->mx, mon->my) && !was_swallowed) + pline("%s body crumbles into dust.", s_suffix(Monnam(mon))); + return FALSE; } /* Gas spores always explode upon death */ @@ -1361,10 +1419,33 @@ struct monst *mon; else if(mdat->mattk[i].damd) tmp = d((int)mdat->mlevel+1, (int)mdat->mattk[i].damd); else tmp = 0; + if (Half_physical_damage) tmp = (tmp+1) / 2; + if (was_swallowed && magr) { + if (magr == &youmonst) { + There("is an explosion in your %s!", + body_part(STOMACH)); + Sprintf(killer_buf, "%s explosion", + s_suffix(mdat->mname)); + losehp(tmp, killer_buf, KILLED_BY_AN); + } else { + if (flags.soundok) You_hear("an explosion."); + magr->mhp -= tmp; + if (magr->mhp < 1) mondied(magr); + if (magr->mhp < 1) { /* maybe lifesaved */ + if (canspotmon(magr)) + pline("%s rips open!", Monnam(magr)); + } else if (canseemon(magr)) + pline("%s seems to have indigestion.", + Monnam(magr)); + } + + return FALSE; + } + Sprintf(killer_buf, "%s explosion", s_suffix(mdat->mname)); killer = killer_buf; killer_format = KILLED_BY_AN; - explode(mon->mx, mon->my, -1, tmp, MON_EXPLODE); + explode(mon->mx, mon->my, -1, tmp, MON_EXPLODE, EXPL_NOXIOUS); return (FALSE); } } @@ -1372,11 +1453,7 @@ struct monst *mon; /* must duplicate this below check in xkilled() since it results in * creating no objects as well as no corpse */ - if ( -#ifdef REINCARNATION - Is_rogue_level(&u.uz) || -#endif - (level.flags.graveyard && is_undead(mdat) && rn2(3))) + if (LEVEL_SPECIFIC_NOCORPSE(mdat)) return FALSE; if (bigmonst(mdat) || mdat == &mons[PM_LIZARD] @@ -1396,7 +1473,7 @@ register struct monst *mdef; mondead(mdef); if (mdef->mhp > 0) return; /* lifesaved */ - if (corpse_chance(mdef)) + if (corpse_chance(mdef, (struct monst *)0, FALSE)) (void) make_corpse(mdef); } @@ -1412,7 +1489,9 @@ register struct monst *mdef; #endif discard_minvent(mdef); /* release monster's inventory */ +#ifndef GOLDOBJ mdef->mgold = 0L; +#endif m_detach(mdef, mdef->data); } @@ -1423,6 +1502,7 @@ register struct monst *mdef; { struct obj *otmp, *obj; xchar x = mdef->mx, y = mdef->my; + boolean wasinside = FALSE; /* we have to make the statue before calling mondead, to be able to * put inventory in it, and we have to check for lifesaving before @@ -1441,6 +1521,9 @@ register struct monst *mdef; /* some objects may end up outside the statue */ while ((obj = mdef->minvent) != 0) { obj_extract_self(obj); + obj_no_longer_held(obj); + if (obj->owornmask & W_WEP) + setmnotwielded(mdef,obj); obj->owornmask = 0L; if (obj->otyp == BOULDER || #if 0 /* monsters don't carry statues */ @@ -1451,30 +1534,40 @@ register struct monst *mdef; place_object(obj, x, y); } else { if (obj->lamplit) end_burn(obj, TRUE); - add_to_container(otmp, obj); + (void) add_to_container(otmp, obj); } } +#ifndef GOLDOBJ if (mdef->mgold) { struct obj *au; au = mksobj(GOLD_PIECE, FALSE, FALSE); au->quan = mdef->mgold; au->owt = weight(au); - add_to_container(otmp, au); + (void) add_to_container(otmp, au); mdef->mgold = 0; } +#endif /* Archeologists should not break unique statues */ if (mdef->data->geno & G_UNIQ) otmp->spe = 1; otmp->owt = weight(otmp); } else - otmp = mksobj_at(ROCK, x, y, TRUE); + otmp = mksobj_at(ROCK, x, y, TRUE, FALSE); stackobj(otmp); /* mondead() already does this, but we must do it before the newsym */ if(glyph_is_invisible(levl[x][y].glyph)) unmap_object(x, y); if (cansee(x, y)) newsym(x,y); + /* We don't currently trap the hero in the statue in this case but we could */ + if (u.uswallow && u.ustuck == mdef) wasinside = TRUE; mondead(mdef); + if (wasinside) { + if (is_animal(mdef->data)) + You("%s through an opening in the new %s.", + locomotion(youmonst.data, "jump"), + xname(otmp)); + } } /* another monster has killed the monster mdef */ @@ -1554,21 +1647,25 @@ xkilled(mtmp, dest) u.uconduct.killer++; if (dest & 1) { - if(!wasinside && !canspotmon(mtmp)) - You("destroy it!"); + const char *verb = nonliving(mtmp->data) ? "destroy" : "kill"; + + if (!wasinside && !canspotmon(mtmp)) + You("%s it!", verb); else { - You("destroy %s!", - mtmp->mtame - ? x_monnam(mtmp, ARTICLE_THE, "poor", - mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE) - : mon_nam(mtmp)); + You("%s %s!", verb, + !mtmp->mtame ? mon_nam(mtmp) : + x_monnam(mtmp, + mtmp->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + "poor", + mtmp->mnamelth ? SUPPRESS_SADDLE : 0, + FALSE)); } } - if (mtmp->mtrapped && - ((t = t_at(x, y)) && (t->ttyp == PIT || t->ttyp == SPIKED_PIT)) && - sobj_at(BOULDER, x, y)) - dest ^= 2; /* + if (mtmp->mtrapped && (t = t_at(x, y)) != 0 && + (t->ttyp == PIT || t->ttyp == SPIKED_PIT) && + sobj_at(BOULDER, x, y)) + dest |= 2; /* * Prevent corpses/treasure being created "on top" * of the boulder that is about to fall in. This is * out of order, but cannot be helped unless this @@ -1601,16 +1698,12 @@ xkilled(mtmp, dest) goto cleanup; } - if((dest & 2) -#ifdef REINCARNATION - || Is_rogue_level(&u.uz) -#endif - || (level.flags.graveyard && is_undead(mdat) && rn2(3))) + if((dest & 2) || LEVEL_SPECIFIC_NOCORPSE(mdat)) goto cleanup; #ifdef MAIL if(mdat == &mons[PM_MAIL_DAEMON]) { - stackobj(mksobj_at(SCR_MAIL, x, y, FALSE)); + stackobj(mksobj_at(SCR_MAIL, x, y, FALSE, FALSE)); redisp = TRUE; } #endif @@ -1644,7 +1737,7 @@ xkilled(mtmp, dest) * different from whether or not the corpse is "special"; * if we want both, we have to specify it explicitly. */ - if (corpse_chance(mtmp)) + if (corpse_chance(mtmp, (struct monst *)0, FALSE)) (void) make_corpse(mtmp); } if(redisp) newsym(x,y); @@ -1672,7 +1765,7 @@ xkilled(mtmp, dest) newexplevel(); /* will decide if you go up */ /* adjust alignment points */ - if (mdat->msound == MS_LEADER) { /* REAL BAD! */ + if (mtmp->m_id == quest_status.leader_m_id) { /* REAL BAD! */ adjalign(-(u.ualign.record+(int)ALIGNLIM/2)); pline("That was %sa bad idea...", u.uevent.qcompleted ? "probably " : ""); @@ -1710,7 +1803,7 @@ mon_to_stone(mtmp) /* it's a golem, and not a stone golem */ if(canseemon(mtmp)) pline("%s solidifies...", Monnam(mtmp)); - if (newcham(mtmp, &mons[PM_STONE_GOLEM])) { + if (newcham(mtmp, &mons[PM_STONE_GOLEM], FALSE)) { if(canseemon(mtmp)) pline("Now it's %s.", an(mtmp->data->mname)); } else { @@ -1871,7 +1964,7 @@ register struct monst *mtmp; } aggravate(); } - if(mtmp->data == &mons[PM_MEDUSA] && !mtmp->mcan) { + if(mtmp->data == &mons[PM_MEDUSA]) { register int i; for(i = 0; i < NATTK; i++) if(mtmp->data->mattk[i].aatyp == AT_GAZE) { @@ -1993,7 +2086,7 @@ rescham() mcham = (int) mtmp->cham; if (mcham) { mtmp->cham = CHAM_ORDINARY; - (void) newcham(mtmp, &mons[cham_to_pm[mcham]]); + (void) newcham(mtmp, &mons[cham_to_pm[mcham]], FALSE); } if(is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN) new_were(mtmp); @@ -2036,11 +2129,11 @@ struct monst *mon; mcham = (int) mon->cham; if (mcham) { mon->cham = CHAM_ORDINARY; - (void) newcham(mon, &mons[cham_to_pm[mcham]]); + (void) newcham(mon, &mons[cham_to_pm[mcham]], FALSE); } else if (is_were(mon->data) && !is_human(mon->data)) { new_were(mon); } - } else { + } else if (mon->cham == CHAM_ORDINARY) { mon->cham = pm_to_cham(monsndx(mon->data)); } } @@ -2051,7 +2144,8 @@ restrap(mtmp) register struct monst *mtmp; { if(mtmp->cham || mtmp->mcan || mtmp->m_ap_type || - cansee(mtmp->mx, mtmp->my) || rn2(3) || (mtmp == u.ustuck)) + cansee(mtmp->mx, mtmp->my) || rn2(3) || (mtmp == u.ustuck) || + (sensemon(mtmp) && distu(mtmp->mx, mtmp->my) <= 2)) return(FALSE); if(mtmp->data->mlet == S_MIMIC) { @@ -2121,17 +2215,44 @@ struct monst *mon; if (!rn2(3)) mndx = pick_animal(); break; case CHAM_ORDINARY: + { + struct obj *m_armr = which_armor(mon, W_ARM); + + if (m_armr && Is_dragon_scales(m_armr)) + mndx = Dragon_scales_to_pm(m_armr) - mons; + else if (m_armr && Is_dragon_mail(m_armr)) + mndx = Dragon_mail_to_pm(m_armr) - mons; + } break; } +#ifdef WIZARD + /* For debugging only: allow control of polymorphed monster; not saved */ + if (wizard && iflags.mon_polycontrol) { + char pprompt[BUFSZ], buf[BUFSZ]; + int tries = 0; + do { + Sprintf(pprompt, + "Change %s into what kind of monster? [type the name]", + mon_nam(mon)); + getlin(pprompt,buf); + mndx = name_to_mon(buf); + if (mndx < LOW_PM) + You("cannot polymorph %s into that.", mon_nam(mon)); + else break; + } while(++tries < 5); + if (tries==5) pline(thats_enough_tries); + } +#endif /*WIZARD*/ if (mndx == NON_PM) mndx = rn1(SPECIAL_PM - LOW_PM, LOW_PM); return mndx; } /* make a chameleon look like a new monster; returns 1 if it actually changed */ int -newcham(mtmp, mdat) +newcham(mtmp, mdat, polyspot) struct monst *mtmp; struct permonst *mdat; +boolean polyspot; /* change is the result of wand or spell of polymorph */ { int mhp, hpn, hpd; int mndx, tryct; @@ -2223,7 +2344,8 @@ struct permonst *mdat; new_light_source(mtmp->mx, mtmp->my, emits_light(mtmp->data), LS_MONSTER, (genericptr_t)mtmp); } - mtmp->perminvis = pm_invisible(mdat); + if (!mtmp->perminvis || pm_invisible(olddata)) + mtmp->perminvis = pm_invisible(mdat); mtmp->minvis = mtmp->invis_blkd ? 0 : mtmp->perminvis; if (!(hides_under(mdat) && OBJ_AT(mtmp->mx, mtmp->my)) && !(mdat->mlet == S_EEL && is_pool(mtmp->mx, mtmp->my))) @@ -2263,7 +2385,7 @@ struct permonst *mdat; newsym(mtmp->mx,mtmp->my); - mon_break_armor(mtmp); + mon_break_armor(mtmp, polyspot); if (!(mtmp->misc_worn_check & W_ARMG)) mselftouch(mtmp, "No longer petrify-resistant, ", !flags.mon_moving); @@ -2282,6 +2404,9 @@ struct permonst *mdat; for (otmp = mtmp->minvent; otmp; otmp = otmp2) { otmp2 = otmp->nobj; if (otmp->otyp == BOULDER) { + /* this keeps otmp from being polymorphed in the + same zap that the monster that held it is polymorphed */ + if (polyspot) bypass_obj(otmp); obj_extract_self(otmp); /* probably ought to give some "drop" message here */ if (flooreffects(otmp, mtmp->mx, mtmp->my, "")) continue; @@ -2410,7 +2535,7 @@ kill_genocided_monsters() mndx = monsndx(mtmp->data); if ((mvitals[mndx].mvflags & G_GENOD) || kill_cham[mtmp->cham]) { if (mtmp->cham && !kill_cham[mtmp->cham]) - (void) newcham(mtmp, (struct permonst *)0); + (void) newcham(mtmp, (struct permonst *)0, FALSE); else mondead(mtmp); } @@ -2442,13 +2567,8 @@ int damtype, dam; return; } if (slow) { - if (mon->mspeed != MSLOW) { - unsigned int oldspeed = mon->mspeed; - - mon_adjust_speed(mon, -1); - if (mon->mspeed != oldspeed && cansee(mon->mx, mon->my)) - pline("%s seems to be moving slower.", Monnam(mon)); - } + if (mon->mspeed != MSLOW) + mon_adjust_speed(mon, -1, (struct obj *)0); } if (heal) { if (mon->mhp < mon->mhpmax) { diff --git a/src/mondata.c b/src/mondata.c index a58abb7..026184f 100644 --- a/src/mondata.c +++ b/src/mondata.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mondata.c 3.3 2000/07/14 */ +/* SCCS Id: @(#)mondata.c 3.4 2001/12/05 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -6,6 +6,10 @@ #include "eshk.h" #include "epri.h" +/* fake attack and damage types */ +#define AT_ANY (-1) +#define AD_ANY (-1) + /* These routines provide basic data for any type of monster. */ #ifdef OVLB @@ -29,17 +33,26 @@ int flag; #endif /* OVLB */ #ifdef OVL0 -boolean -attacktype(ptr, atyp) - register struct permonst *ptr; - register int atyp; +struct attack * +attacktype_fordmg(ptr, atyp, dtyp) +struct permonst *ptr; +int atyp, dtyp; { - int i; + struct attack *a; - for(i = 0; i < NATTK; i++) - if(ptr->mattk[i].aatyp == atyp) return(TRUE); + for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++) + if (a->aatyp == atyp && (dtyp == AD_ANY || a->adtyp == dtyp)) + return a; - return(FALSE); + return (struct attack *)0; +} + +boolean +attacktype(ptr, atyp) +struct permonst *ptr; +int atyp; +{ + return attacktype_fordmg(ptr, atyp, AD_ANY) ? TRUE : FALSE; } #endif /* OVL0 */ @@ -105,9 +118,9 @@ struct monst *mon; paralysis does too, we can't check it */ mon->msleeping)) return TRUE; - /* AD_BLND => yellow light, Archon, !cobra, !raven */ - if (dmgtype(ptr, AD_BLND) && - !attacktype(ptr, AT_SPIT) && !attacktype(ptr, AT_CLAW)) + /* yellow light, Archon; !dust vortex, !cobra, !raven */ + if (dmgtype_fromattack(ptr, AD_BLND, AT_EXPL) || + dmgtype_fromattack(ptr, AD_BLND, AT_GAZE)) return TRUE; o = is_you ? uwep : MON_WEP(mon); if (o && o->oartifact && defends(AD_BLND, o)) @@ -282,17 +295,26 @@ sticks(ptr) /* creature sticks other creatures it hits */ attacktype(ptr,AT_HUGS))); } -boolean -dmgtype(ptr, dtyp) - register struct permonst *ptr; - register int dtyp; +struct attack * +dmgtype_fromattack(ptr, dtyp, atyp) +struct permonst *ptr; +int dtyp, atyp; { - int i; + struct attack *a; - for(i = 0; i < NATTK; i++) - if(ptr->mattk[i].adtyp == dtyp) return TRUE; + for (a = &ptr->mattk[0]; a < &ptr->mattk[NATTK]; a++) + if (a->adtyp == dtyp && (atyp == AT_ANY || a->aatyp == atyp)) + return a; - return FALSE; + return (struct attack *)0; +} + +boolean +dmgtype(ptr, dtyp) +struct permonst *ptr; +int dtyp; +{ + return dmgtype_fromattack(ptr, dtyp, AT_ANY) ? TRUE : FALSE; } /* returns the maximum damage a defender can do to the attacker via @@ -583,11 +605,13 @@ int montype; return montype; } -static const char *levitate[2] = { "float", "Float" }; -static const char *fly[2] = { "fly", "Fly" }; -static const char *slither[2] = { "slither", "Slither" }; -static const char *ooze[2] = { "ooze", "Ooze" }; -static const char *crawl[2] = { "crawl", "Crawl" }; +static const char *levitate[4] = { "float", "Float", "wobble", "Wobble" }; +static const char *flys[4] = { "fly", "Fly", "flutter", "Flutter" }; +static const char *flyl[4] = { "fly", "Fly", "stagger", "Stagger" }; +static const char *slither[4] = { "slither", "Slither", "falter", "Falter" }; +static const char *ooze[4] = { "ooze", "Ooze", "tremble", "Tremble" }; +static const char *immobile[4] = { "wiggle", "Wiggle", "pulsate", "Pulsate" }; +static const char *crawl[4] = { "crawl", "Crawl", "falter", "Falter" }; const char * locomotion(ptr, def) @@ -598,9 +622,31 @@ const char *def; return ( is_floater(ptr) ? levitate[capitalize] : - is_flyer(ptr) ? fly[capitalize] : + (is_flyer(ptr) && ptr->msize <= MZ_SMALL) ? flys[capitalize] : + (is_flyer(ptr) && ptr->msize > MZ_SMALL) ? flyl[capitalize] : + slithy(ptr) ? slither[capitalize] : + amorphous(ptr) ? ooze[capitalize] : + !ptr->mmove ? immobile[capitalize] : + nolimbs(ptr) ? crawl[capitalize] : + def + ); + +} + +const char * +stagger(ptr, def) +const struct permonst *ptr; +const char *def; +{ + int capitalize = 2 + (*def == highc(*def)); + + return ( + is_floater(ptr) ? levitate[capitalize] : + (is_flyer(ptr) && ptr->msize <= MZ_SMALL) ? flys[capitalize] : + (is_flyer(ptr) && ptr->msize > MZ_SMALL) ? flyl[capitalize] : slithy(ptr) ? slither[capitalize] : amorphous(ptr) ? ooze[capitalize] : + !ptr->mmove ? immobile[capitalize] : nolimbs(ptr) ? crawl[capitalize] : def ); diff --git a/src/monmove.c b/src/monmove.c index 62565e0..04b4806 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)monmove.c 3.3 2000/07/24 */ +/* SCCS Id: @(#)monmove.c 3.4 2000/08/16 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -69,6 +69,9 @@ register struct monst *mtmp; } stop_occupation(); } + } else if (is_digging()) { + /* chewing, wand/spell of digging are checked elsewhere */ + watch_dig(mtmp, digging.pos.x, digging.pos.y, FALSE); } } } @@ -198,6 +201,41 @@ disturb(mtmp) return(0); } +/* monster begins fleeing for the specified time, 0 means untimed flee + * if first, only adds fleetime if monster isn't already fleeing + * if fleemsg, prints a message about new flight, otherwise, caller should */ +void +monflee(mtmp, fleetime, first, fleemsg) +struct monst *mtmp; +int fleetime; +boolean first; +boolean fleemsg; +{ + if (u.ustuck == mtmp) { + if (u.uswallow) + expels(mtmp, mtmp->data, TRUE); + else if (!sticks(youmonst.data)) { + unstuck(mtmp); /* monster lets go when fleeing */ + You("get released!"); + } + } + + if (!first || !mtmp->mflee) { + /* don't lose untimed scare */ + if (!fleetime) + mtmp->mfleetim = 0; + else if (!mtmp->mflee || mtmp->mfleetim) { + fleetime += mtmp->mfleetim; + /* ensure monster flees long enough to visibly stop fighting */ + if (fleetime == 1) fleetime++; + mtmp->mfleetim = min(fleetime, 127); + } + if (!mtmp->mflee && fleemsg && canseemon(mtmp)) + pline("%s turns to flee!", (Monnam(mtmp))); + mtmp->mflee = 1; + } +} + STATIC_OVL void distfleeck(mtmp,inrange,nearby,scared) register struct monst *mtmp; @@ -227,18 +265,11 @@ int *inrange, *nearby, *scared; (!mtmp->mpeaceful && in_your_sanctuary(mtmp, 0, 0)))); - if(*scared && !mtmp->mflee) { - if (!sticks(youmonst.data)) - unstuck(mtmp); /* monster lets go when fleeing */ - mtmp->mflee = 1; -#ifdef STUPID + if(*scared) { if (rn2(7)) - mtmp->mfleetim = rnd(10); + monflee(mtmp, rnd(10), TRUE, TRUE); else - mtmp->mfleetim = rnd(100); -#else - mtmp->mfleetim = rnd(rn2(7) ? 10 : 100); -#endif + monflee(mtmp, rnd(100), TRUE, TRUE); } } @@ -265,6 +296,9 @@ register struct monst *mtmp; register struct permonst *mdat; register int tmp=0; int inrange, nearby, scared; +#ifdef GOLDOBJ + struct obj *ygold = 0, *lepgold = 0; +#endif /* Pre-movement adjustments */ @@ -314,7 +348,7 @@ register struct monst *mtmp; } if (mdat->msound == MS_SHRIEK && !um_dist(mtmp->mx, mtmp->my, 1)) m_respond(mtmp); - if (mdat == &mons[PM_MEDUSA] && cansee(mtmp->mx, mtmp->my)) + if (mdat == &mons[PM_MEDUSA] && couldsee(mtmp->mx, mtmp->my)) m_respond(mtmp); if (mtmp->mhp <= 0) return(1); /* m_respond gaze can kill medusa */ @@ -406,10 +440,13 @@ register struct monst *mtmp; m2->mhp -= rnd(15); if (m2->mhp <= 0) monkilled(m2, "", AD_DRIN); + else + m2->msleeping = 0; } } } toofar: + /* If monster is nearby you, and has to wield a weapon, do so. This * costs the monster a move, of course. */ @@ -432,11 +469,40 @@ register struct monst *mtmp; /* Now the actual movement phase */ +#ifndef GOLDOBJ if(!nearby || mtmp->mflee || scared || mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) || (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) || +#else + if (mdat->mlet == S_LEPRECHAUN) { + ygold = findgold(invent); + lepgold = findgold(mtmp->minvent); + } + + if(!nearby || mtmp->mflee || scared || + mtmp->mconf || mtmp->mstun || (mtmp->minvis && !rn2(3)) || + (mdat->mlet == S_LEPRECHAUN && !ygold && (lepgold || rn2(2))) || +#endif (is_wanderer(mdat) && !rn2(4)) || (Conflict && !mtmp->iswiz) || (!mtmp->mcansee && !rn2(4)) || mtmp->mpeaceful) { + /* Possibly cast an undirected spell if not attacking you */ + /* note that most of the time castmu() will pick a directed + spell and do nothing, so the monster moves normally */ + /* arbitrary distance restriction to keep monster far away + from you from having cast dozens of sticks-to-snakes + or similar spells by the time you reach it */ + if (dist2(mtmp->mx, mtmp->my, u.ux, u.uy) <= 64 && !mtmp->mspec_used) { + struct attack *a; + + for (a = &mdat->mattk[0]; a < &mdat->mattk[NATTK]; a++) { + if (a->aatyp == AT_MAGC && (a->adtyp == AD_SPEL || a->adtyp == AD_CLRC)) { + if (castmu(mtmp, a, FALSE, FALSE)) { + tmp = 3; + break; + } + } + } + } tmp = m_move(mtmp, 0); distfleeck(mtmp,&inrange,&nearby,&scared); /* recalc */ @@ -445,6 +511,10 @@ register struct monst *mtmp; case 0: /* no movement, but it can still attack you */ case 3: /* absolutely no movement */ /* for pets, case 0 and 3 are equivalent */ + /* vault guard might have vanished */ + if (mtmp->isgd && (mtmp->mhp < 1 || + (mtmp->mx == 0 && mtmp->my == 0))) + return 1; /* behave as if it died */ /* During hallucination, monster appearance should * still change - even if it doesn't move. */ @@ -526,7 +596,8 @@ register int after; boolean likegold=0, likegems=0, likeobjs=0, likemagic=0, conceals=0; boolean likerock=0, can_tunnel=0; boolean can_open=0, can_unlock=0, doorbuster=0; - boolean uses_items=0; + boolean uses_items=0, setlikes=0; + boolean avoid=FALSE; struct permonst *ptr; struct monst *mtoo; schar mmoved = 0; /* not strictly nec.: chi >= 0 will do */ @@ -643,6 +714,9 @@ register int after; if (mtmp->mconf || (u.uswallow && mtmp == u.ustuck)) appr = 0; else { +#ifdef GOLDOBJ + struct obj *lepgold, *ygold; +#endif boolean should_see = (couldsee(omx, omy) && (levl[gx][gy].lit || !levl[omx][omy].lit) && @@ -658,7 +732,12 @@ register int after; appr = 0; if(monsndx(ptr) == PM_LEPRECHAUN && (appr == 1) && +#ifndef GOLDOBJ (mtmp->mgold > u.ugold)) +#else + ( (lepgold = findgold(mtmp->minvent)) && + (lepgold->quan > ((ygold = findgold(invent)) ? ygold->quan : 0L)) )) +#endif appr = -1; if (!should_see && can_track(ptr)) { @@ -699,6 +778,7 @@ register int after; likemagic = (likes_magic(ptr) && pctload < 85); likerock = (throws_rocks(ptr) && pctload < 50 && !In_sokoban(&u.uz)); conceals = hides_under(ptr); + setlikes = TRUE; } } @@ -807,7 +887,8 @@ register int after; flag |= (ALLOW_SANCT | ALLOW_SSM); else flag |= ALLOW_U; if (is_minion(ptr) || is_rider(ptr)) flag |= ALLOW_SANCT; - if (is_unicorn(ptr)) flag |= NOTONL; + /* unicorn may not be able to avoid hero on a noteleport level */ + if (is_unicorn(ptr) && !level.flags.noteleport) flag |= NOTONL; if (passes_walls(ptr)) flag |= (ALLOW_WALL | ALLOW_ROCK); if (can_tunnel) flag |= ALLOW_DIG; if (is_human(ptr) || ptr == &mons[PM_MINOTAUR]) flag |= ALLOW_SSM; @@ -831,8 +912,14 @@ register int after; /* allow monsters be shortsighted on some levels for balance */ if(!mtmp->mpeaceful && level.flags.shortsighted && nidist > (couldsee(nix,niy) ? 144 : 36) && appr == 1) appr = 0; + if (is_unicorn(ptr) && level.flags.noteleport) { + /* on noteleport levels, perhaps we cannot avoid hero */ + for(i = 0; i < cnt; i++) + if(!(info[i] & NOTONL)) avoid=TRUE; + } for(i=0; i < cnt; i++) { + if (avoid && (info[i] & NOTONL)) continue; nx = poss[i].x; ny = poss[i].y; @@ -1042,9 +1129,27 @@ register int after; newsym(mtmp->mx,mtmp->my); } if(OBJ_AT(mtmp->mx, mtmp->my) && mtmp->mcanmove) { + /* recompute the likes tests, in case we polymorphed + * or if the "likegold" case got taken above */ + if (setlikes) { + register int pctload = (curr_mon_load(mtmp) * 100) / + max_mon_load(mtmp); + + /* look for gold or jewels nearby */ + likegold = (likes_gold(ptr) && pctload < 95); + likegems = (likes_gems(ptr) && pctload < 85); + uses_items = (!mindless(ptr) && !is_animal(ptr) + && pctload < 75); + likeobjs = (likes_objs(ptr) && pctload < 75); + likemagic = (likes_magic(ptr) && pctload < 85); + likerock = (throws_rocks(ptr) && pctload < 50 && + !In_sokoban(&u.uz)); + conceals = hides_under(ptr); + } + /* Maybe a rock mole just ate some metal object */ if (metallivorous(ptr)) { - if (meatgold(mtmp) == 2) return 2; /* it died */ + if (meatmetal(mtmp) == 2) return 2; /* it died */ } if(g_at(mtmp->mx,mtmp->my) && likegold) mpickgold(mtmp); @@ -1114,6 +1219,9 @@ register struct monst *mtmp; { boolean notseen, gotu; register int disp, mx = mtmp->mux, my = mtmp->muy; +#ifdef GOLDOBJ + long umoney = money_cnt(invent); +#endif /* * do cheapest and/or most likely tests first @@ -1128,8 +1236,21 @@ register struct monst *mtmp; notseen = (!mtmp->mcansee || (Invis && !perceives(mtmp->data))); /* add cases as required. eg. Displacement ... */ - disp = ((notseen || Underwater) ? 1 : - Displaced ? (couldsee(mx, my) ? 2 : 1) : 0); + if (notseen || Underwater) { + /* Xorns can smell valuable metal like gold, treat as seen */ + if ((mtmp->data == &mons[PM_XORN]) && +#ifndef GOLDOBJ + u.ugold +#else + umoney +#endif + && !Underwater) + disp = 0; + else + disp = 1; + } else if (Displaced) { + disp = couldsee(mx, my) ? 2 : 1; + } else disp = 0; if (!disp) goto found_you; /* without something like the following, invis. and displ. @@ -1152,7 +1273,8 @@ register struct monst *mtmp; || ((mx != u.ux || my != u.uy) && !passes_walls(mtmp->data) && (!ACCESSIBLE(levl[mx][my].typ) || - (closed_door(mx, my) && !can_ooze(mtmp))))); + (closed_door(mx, my) && !can_ooze(mtmp)))) + || !couldsee(mx, my)); } else { found_you: mx = u.ux; @@ -1171,15 +1293,22 @@ struct monst *mtmp; if (!amorphous(mtmp->data)) return FALSE; if (mtmp == &youmonst) { +#ifndef GOLDOBJ if (u.ugold > 100L) return FALSE; +#endif chain = invent; } else { +#ifndef GOLDOBJ if (mtmp->mgold > 100L) return FALSE; +#endif chain = mtmp->minvent; } for (obj = chain; obj; obj = obj->nobj) { int typ = obj->otyp; +#ifdef GOLDOBJ + if (typ == GOLD_CLASS && obj->quan > 100L) return FALSE; +#endif if (obj->oclass != GEM_CLASS && !(typ >= ARROW && typ <= BOOMERANG) && !(typ >= DAGGER && typ <= CRYSKNIFE) && diff --git a/src/monst.c b/src/monst.c index 6e1bdf3..629d3fb 100644 --- a/src/monst.c +++ b/src/monst.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)monst.c 3.3 2000/07/14 */ +/* SCCS Id: @(#)monst.c 3.4 2000/07/14 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -174,23 +174,24 @@ NEARDATA struct permonst mons[] = { ATTK(AT_NONE, AD_STON, 0, 0), NO_ATTK, NO_ATTK, NO_ATTK), SIZ(10, 10, 0, MS_HISS, MZ_TINY), MR_POISON|MR_STONE, MR_POISON|MR_STONE, - M1_ANIMAL|M1_NOHANDS, M2_HOSTILE, M3_INFRAVISIBLE, CLR_BROWN), + M1_ANIMAL|M1_NOHANDS|M1_OMNIVORE, M2_HOSTILE, + M3_INFRAVISIBLE, CLR_BROWN), MON("cockatrice", S_COCKATRICE, LVL(5, 6, 6, 30, 0), (G_GENO|5), A(ATTK(AT_BITE, AD_PHYS, 1, 3), ATTK(AT_TUCH, AD_STON, 0, 0), ATTK(AT_NONE, AD_STON, 0, 0), NO_ATTK, NO_ATTK, NO_ATTK), SIZ(30, 30, 0, MS_HISS, MZ_SMALL), MR_POISON|MR_STONE, MR_POISON|MR_STONE, - M1_ANIMAL|M1_NOHANDS|M1_OVIPAROUS, M2_HOSTILE, M3_INFRAVISIBLE, - CLR_YELLOW), + M1_ANIMAL|M1_NOHANDS|M1_OMNIVORE|M1_OVIPAROUS, M2_HOSTILE, + M3_INFRAVISIBLE, CLR_YELLOW), MON("pyrolisk", S_COCKATRICE, LVL(6, 6, 6, 30, 0), (G_GENO|1), A(ATTK(AT_GAZE, AD_FIRE, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(30, 30, 0, MS_HISS, MZ_SMALL), MR_POISON|MR_FIRE, MR_POISON|MR_FIRE, - M1_ANIMAL|M1_NOHANDS|M1_OVIPAROUS, M2_HOSTILE, M3_INFRAVISIBLE, - CLR_RED), + M1_ANIMAL|M1_NOHANDS|M1_OMNIVORE|M1_OVIPAROUS, M2_HOSTILE, + M3_INFRAVISIBLE, CLR_RED), /* * dogs & other canines */ @@ -254,7 +255,7 @@ NEARDATA struct permonst mons[] = { LVL(5, 12, 4, 0, 0), (G_GENO|G_SGROUP|2), A(ATTK(AT_BITE, AD_PHYS, 2, 4), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), - SIZ(500, 250, 0, MS_BARK, MZ_SMALL), 0, 0, + SIZ(500, 250, 0, MS_BARK, MZ_MEDIUM), 0, 0, M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_HOSTILE, M3_INFRAVISIBLE, CLR_BROWN), MON("werewolf", S_DOG, @@ -316,7 +317,7 @@ NEARDATA struct permonst mons[] = { A(ATTK(AT_BOOM, AD_PHYS, 4, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(10, 10, 0, MS_SILENT, MZ_SMALL), 0, 0, - M1_FLY|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS, + M1_FLY|M1_BREATHLESS|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS, M2_HOSTILE|M2_NEUTER, 0, CLR_GRAY), MON("floating eye", S_EYE, LVL(2, 1, 9, 10, 0), (G_GENO|5), @@ -330,21 +331,21 @@ NEARDATA struct permonst mons[] = { A(ATTK(AT_EXPL, AD_COLD, 4, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(10, 10, 0, MS_SILENT, MZ_SMALL), MR_COLD, MR_COLD, - M1_FLY|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_NOTAKE, + M1_FLY|M1_BREATHLESS|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_NOTAKE, M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, CLR_WHITE), MON("flaming sphere", S_EYE, LVL(6, 13, 4, 0, 0), (G_NOCORPSE|G_GENO|2), A(ATTK(AT_EXPL, AD_FIRE, 4, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(10, 10, 0, MS_SILENT, MZ_SMALL), MR_FIRE, MR_FIRE, - M1_FLY|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS, + M1_FLY|M1_BREATHLESS|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS, M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, CLR_RED), MON("shocking sphere", S_EYE, LVL(6, 13, 4, 0, 0), (G_NOCORPSE|G_GENO|2), A(ATTK(AT_EXPL, AD_ELEC, 4, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(10, 10, 0, MS_SILENT, MZ_SMALL), MR_ELEC, MR_ELEC, - M1_FLY|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS, + M1_FLY|M1_BREATHLESS|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS, M2_HOSTILE|M2_NEUTER, M3_INFRAVISIBLE, HI_ZAP), #if 0 /* not yet implemented */ MON("beholder", S_EYE, @@ -384,7 +385,7 @@ NEARDATA struct permonst mons[] = { LVL(5, 15, 6, 0, 0), (G_GENO|1), A(ATTK(AT_CLAW, AD_PHYS, 1, 4), ATTK(AT_CLAW, AD_PHYS, 1, 4), ATTK(AT_BITE, AD_PHYS, 1, 10), NO_ATTK, NO_ATTK, NO_ATTK), - SIZ(600, 300, 0, MS_GROWL, MZ_LARGE), 0, 0, + SIZ(600, 300, 0, MS_GROWL, MZ_SMALL), 0, 0, M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE,M2_HOSTILE, M3_INFRAVISIBLE, CLR_CYAN), MON("panther", S_FELINE, @@ -477,7 +478,7 @@ NEARDATA struct permonst mons[] = { LVL(9, 12, 5, 90, -8), (G_GENO|1), A(ATTK(AT_WEAP, AD_PHYS, 1, 4), ATTK(AT_TENT, AD_DRIN, 2, 1), ATTK(AT_TENT, AD_DRIN, 2, 1), ATTK(AT_TENT, AD_DRIN, 2, 1), - ATTK(AT_TENT, AD_DRIN, 2, 1), NO_ATTK), + NO_ATTK, NO_ATTK), SIZ(1450, 400, 0, MS_HISS, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_FLY|M1_SEE_INVIS|M1_OMNIVORE, M2_HOSTILE|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_COLLECT, @@ -486,7 +487,7 @@ NEARDATA struct permonst mons[] = { LVL(13, 12, 0, 90, -8), (G_GENO|1), A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_TENT, AD_DRIN, 2, 1), ATTK(AT_TENT, AD_DRIN, 2, 1), ATTK(AT_TENT, AD_DRIN, 2, 1), - ATTK(AT_TENT, AD_DRIN, 2, 1), NO_ATTK), + ATTK(AT_TENT, AD_DRIN, 2, 1), ATTK(AT_TENT, AD_DRIN, 2, 1)), SIZ(1450, 400, 0, MS_HISS, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_FLY|M1_SEE_INVIS|M1_OMNIVORE, M2_HOSTILE|M2_NASTY|M2_GREEDY|M2_JEWELS|M2_COLLECT, @@ -834,7 +835,7 @@ NEARDATA struct permonst mons[] = { A(ATTK(AT_BITE, AD_PHYS, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(30, 30, 0, MS_SILENT, MZ_SMALL), 0, 0, - M1_TUNNEL/*LOGGING*/|M1_ANIMAL|M1_NOHANDS|M1_SWIM, + M1_TUNNEL/*LOGGING*/|M1_ANIMAL|M1_NOHANDS|M1_SWIM|M1_HERBIVORE, /* In reality, they tunnel instead of cutting lumber. Oh, well. */ M2_WANDER|M2_HOSTILE, M3_INFRAVISIBLE, CLR_BROWN), /* @@ -1085,12 +1086,12 @@ NEARDATA struct permonst mons[] = { CLR_YELLOW), MON("Angel", S_ANGEL, LVL(14, 10, -4, 55, 12), (G_NOHELL|G_NOCORPSE|1), - A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_CLAW, AD_PHYS, 1, 4), - ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MAGC, AD_MAGM, 2, 6), + A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), + ATTK(AT_CLAW, AD_PHYS, 1, 4), ATTK(AT_MAGC, AD_MAGM, 2, 6), NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, sizeof(struct epri), MS_CUSS, MZ_HUMAN), MR_COLD|MR_ELEC|MR_SLEEP|MR_POISON, 0, - M1_HUMANOID|M1_SEE_INVIS, + M1_FLY|M1_HUMANOID|M1_SEE_INVIS, M2_NOPOLY|M2_MINION|M2_STALK|M2_STRONG|M2_NASTY|M2_COLLECT, M3_INFRAVISIBLE|M3_INFRAVISION, CLR_WHITE), MON("ki-rin", S_ANGEL, @@ -1104,8 +1105,8 @@ NEARDATA struct permonst mons[] = { M3_INFRAVISIBLE|M3_INFRAVISION, HI_GOLD), MON("Archon", S_ANGEL, LVL(19, 16, -6, 80, 15), (G_NOHELL|G_NOCORPSE|1), - A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_GAZE, AD_BLND, 2, 6), - ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_CLAW, AD_PHYS, 1, 8), + A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_WEAP, AD_PHYS, 2, 4), + ATTK(AT_GAZE, AD_BLND, 2, 6), ATTK(AT_CLAW, AD_PHYS, 1, 8), ATTK(AT_MAGC, AD_SPEL, 4, 6), NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_CUSS, MZ_LARGE), MR_FIRE|MR_COLD|MR_ELEC|MR_SLEEP|MR_POISON, 0, @@ -1142,8 +1143,8 @@ NEARDATA struct permonst mons[] = { A(ATTK(AT_BITE, AD_PHYS, 1, 6), ATTK(AT_BITE, AD_DRST, 0, 0), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(30, 20, 0, MS_SQEEK, MZ_SMALL), MR_SLEEP|MR_POISON, 0, - M1_FLY|M1_BREATHLESS|M1_ANIMAL|M1_NOHANDS|M1_POIS|M1_REGEN, - M2_UNDEAD|M2_HOSTILE, M3_INFRAVISIBLE, CLR_BLACK), + M1_FLY|M1_ANIMAL|M1_NOHANDS|M1_POIS|M1_REGEN|M1_OMNIVORE, + M2_HOSTILE, M3_INFRAVISIBLE, CLR_BLACK), /* * Centaurs */ @@ -1362,7 +1363,7 @@ NEARDATA struct permonst mons[] = { M2_WANDER|M2_STALK|M2_HOSTILE|M2_STRONG, M3_INFRAVISION, CLR_WHITE), MON("air elemental", S_ELEMENTAL, LVL(8, 36, 2, 30, 0), (G_NOCORPSE|1), - A(ATTK(AT_ENGL, AD_PHYS, 2,10), + A(ATTK(AT_ENGL, AD_PHYS, 1, 10), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(0, 0, 0, MS_SILENT, MZ_HUGE), MR_POISON|MR_STONE, 0, M1_NOEYES|M1_NOLIMBS|M1_NOHEAD|M1_MINDLESS|M1_UNSOLID|M1_FLY, @@ -1832,7 +1833,7 @@ struct permonst _mons2[] = { M2_HOSTILE|M2_NEUTER, 0, CLR_BROWN), MON("black pudding", S_PUDDING, LVL(10, 6, 6, 0, 0), (G_GENO|1), - A(ATTK(AT_BITE, AD_CORRODE, 3, 8), ATTK(AT_NONE, AD_CORRODE, 0, 0), + A(ATTK(AT_BITE, AD_CORR, 3, 8), ATTK(AT_NONE, AD_CORR, 0, 0), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(900, 250, 0, MS_SILENT, MZ_LARGE), MR_COLD|MR_ELEC|MR_POISON|MR_ACID|MR_STONE, MR_COLD|MR_ELEC|MR_POISON, @@ -1934,7 +1935,7 @@ struct permonst _mons2[] = { */ MON("troll", S_TROLL, LVL(7, 12, 4, 0, -3), (G_GENO|2), - A(ATTK(AT_CLAW, AD_PHYS, 4, 2), ATTK(AT_WEAP, AD_PHYS, 4, 2), + A(ATTK(AT_WEAP, AD_PHYS, 4, 2), ATTK(AT_CLAW, AD_PHYS, 4, 2), ATTK(AT_BITE, AD_PHYS, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK), SIZ(800, 350, 0, MS_GRUNT, MZ_LARGE), 0, 0, M1_HUMANOID|M1_REGEN|M1_CARNIVORE, @@ -1942,7 +1943,7 @@ struct permonst _mons2[] = { CLR_BROWN), MON("ice troll", S_TROLL, LVL(9, 10, 2, 20, -3), (G_NOHELL|G_GENO|1), - A(ATTK(AT_CLAW, AD_COLD, 2, 6), ATTK(AT_WEAP, AD_PHYS, 2, 6), + A(ATTK(AT_WEAP, AD_PHYS, 2, 6), ATTK(AT_CLAW, AD_COLD, 2, 6), ATTK(AT_BITE, AD_PHYS, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK), SIZ(1000, 300, 0, MS_GRUNT, MZ_LARGE), MR_COLD, MR_COLD, M1_HUMANOID|M1_REGEN|M1_CARNIVORE, @@ -1950,7 +1951,7 @@ struct permonst _mons2[] = { CLR_WHITE), MON("rock troll", S_TROLL, LVL(9, 12, 0, 0, -3), (G_GENO|1), - A(ATTK(AT_CLAW, AD_PHYS, 2, 8), ATTK(AT_WEAP, AD_PHYS, 3, 6), + A(ATTK(AT_WEAP, AD_PHYS, 3, 6), ATTK(AT_CLAW, AD_PHYS, 2, 8), ATTK(AT_BITE, AD_PHYS, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK), SIZ(1200, 300, 0, MS_GRUNT, MZ_LARGE), 0, 0, M1_HUMANOID|M1_REGEN|M1_CARNIVORE, @@ -1958,7 +1959,7 @@ struct permonst _mons2[] = { M3_INFRAVISIBLE|M3_INFRAVISION, CLR_CYAN), MON("water troll", S_TROLL, LVL(11, 14, 4, 40, -3), (G_NOGEN|G_GENO), - A(ATTK(AT_CLAW, AD_PHYS, 2, 8), ATTK(AT_WEAP, AD_PHYS, 2, 8), + A(ATTK(AT_WEAP, AD_PHYS, 2, 8), ATTK(AT_CLAW, AD_PHYS, 2, 8), ATTK(AT_BITE, AD_PHYS, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK), SIZ(1200, 350, 0, MS_GRUNT, MZ_LARGE), 0, 0, M1_HUMANOID|M1_REGEN|M1_CARNIVORE|M1_SWIM, @@ -1966,7 +1967,7 @@ struct permonst _mons2[] = { CLR_BLUE), MON("Olog-hai", S_TROLL, LVL(13, 12, -4, 0, -7), (G_GENO|1), - A(ATTK(AT_CLAW, AD_PHYS, 2, 8), ATTK(AT_WEAP, AD_PHYS, 3, 6), + A(ATTK(AT_WEAP, AD_PHYS, 3, 6), ATTK(AT_CLAW, AD_PHYS, 2, 8), ATTK(AT_BITE, AD_PHYS, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK), SIZ(1500, 400, 0, MS_GRUNT, MZ_LARGE), 0, 0, M1_HUMANOID|M1_REGEN|M1_CARNIVORE, @@ -1986,7 +1987,7 @@ struct permonst _mons2[] = { * Vampires */ MON("vampire", S_VAMPIRE, - LVL(10, 12, 1, 25, -8), (G_GENO|1), + LVL(10, 12, 1, 25, -8), (G_GENO|G_NOCORPSE|1), A(ATTK(AT_CLAW, AD_PHYS, 1, 6), ATTK(AT_BITE, AD_DRLI, 1, 6), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0, @@ -1994,7 +1995,7 @@ struct permonst _mons2[] = { M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY, M3_INFRAVISIBLE, CLR_RED), MON("vampire lord", S_VAMPIRE, - LVL(12, 14, 0, 50, -9), (G_GENO|1), + LVL(12, 14, 0, 50, -9), (G_GENO|G_NOCORPSE|1), A(ATTK(AT_CLAW, AD_PHYS, 1, 8), ATTK(AT_BITE, AD_DRLI, 1, 8), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0, @@ -2003,7 +2004,7 @@ struct permonst _mons2[] = { M3_INFRAVISIBLE, CLR_BLUE), #if 0 /* DEFERRED */ MON("vampire mage", S_VAMPIRE, - LVL(20, 14, -4, 50, -9), (G_GENO|1), + LVL(20, 14, -4, 50, -9), (G_GENO|G_NOCORPSE|1), A(ATTK(AT_CLAW, AD_DRLI, 2, 8), ATTK(AT_BITE, AD_DRLI, 1, 8), ATTK(AT_MAGC, AD_SPEL, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0, @@ -2019,14 +2020,14 @@ struct permonst _mons2[] = { M1_FLY|M1_BREATHLESS|M1_HUMANOID|M1_POIS|M1_REGEN, M2_NOPOLY|M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_PNAME|M2_STRONG| M2_NASTY|M2_PRINCE|M2_MALE, - M3_WAITFORU|M3_WANTSBOOK|M3_INFRAVISIBLE, HI_LORD), + M3_WAITFORU|M3_WANTSCAND|M3_INFRAVISIBLE, HI_LORD), /* * Wraiths */ MON("barrow wight", S_WRAITH, LVL(3, 12, 5, 5, -3), (G_GENO|G_NOCORPSE|1), - A(ATTK(AT_CLAW, AD_PHYS, 1, 4), ATTK(AT_MAGC, AD_SPEL, 0, 0), - ATTK(AT_WEAP, AD_DRLI, 0, 0), NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_DRLI, 0, 0), ATTK(AT_MAGC, AD_SPEL, 0, 0), + ATTK(AT_CLAW, AD_PHYS, 1, 4), NO_ATTK, NO_ATTK, NO_ATTK), SIZ(1200, 0, 0, MS_SPELL, MZ_HUMAN), MR_COLD|MR_SLEEP|MR_POISON, 0, M1_BREATHLESS|M1_HUMANOID, M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_COLLECT, 0, CLR_GRAY), @@ -2044,7 +2045,7 @@ struct permonst _mons2[] = { NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 0, 0, MS_SPELL, MZ_HUMAN), MR_COLD|MR_SLEEP|MR_POISON, 0, M1_BREATHLESS|M1_HUMANOID, - M2_UNDEAD|M2_STALK|M2_STRONG|M2_HOSTILE|M2_MALE|M2_COLLECT, + M2_NOPOLY|M2_UNDEAD|M2_STALK|M2_STRONG|M2_HOSTILE|M2_MALE|M2_COLLECT, 0, HI_LORD), /* * Xorn @@ -2054,7 +2055,7 @@ struct permonst _mons2[] = { A(ATTK(AT_CLAW, AD_PHYS, 1, 3), ATTK(AT_CLAW, AD_PHYS, 1, 3), ATTK(AT_CLAW, AD_PHYS, 1, 3), ATTK(AT_BITE, AD_PHYS, 4, 6), NO_ATTK, NO_ATTK), - SIZ(1200, 700, 0, MS_SILENT, MZ_MEDIUM), + SIZ(1200, 700, 0, MS_ROAR, MZ_MEDIUM), MR_FIRE|MR_COLD|MR_STONE, MR_STONE, M1_BREATHLESS|M1_WALLWALK|M1_THICK_HIDE|M1_METALLIVORE, M2_HOSTILE|M2_STRONG, 0, CLR_BROWN), @@ -2465,8 +2466,8 @@ struct permonst _mons2[] = { */ MON("Medusa", S_HUMAN, LVL(20, 12, 2, 50, -15), (G_NOGEN|G_UNIQ), - A(ATTK(AT_CLAW, AD_PHYS, 1, 8), ATTK(AT_GAZE, AD_STON, 0, 0), - ATTK(AT_BITE, AD_DRST, 1, 6), ATTK(AT_WEAP, AD_PHYS, 2, 4), + A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_CLAW, AD_PHYS, 1, 8), + ATTK(AT_GAZE, AD_STON, 0, 0), ATTK(AT_BITE, AD_DRST, 1, 6), NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_HISS, MZ_LARGE), MR_POISON|MR_STONE, MR_POISON|MR_STONE, @@ -2578,7 +2579,8 @@ struct permonst _mons2[] = { NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_SILENT, MZ_HUMAN), MR_FIRE|MR_POISON, 0, M1_HUMANOID|M1_POIS, - M2_DEMON|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_FEMALE|M2_COLLECT, + M2_NOPOLY|M2_DEMON|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY|M2_FEMALE| + M2_COLLECT, M3_INFRAVISIBLE|M3_INFRAVISION, CLR_RED), MON("barbed devil", S_DEMON, LVL(8, 12, 0, 35, 8), (G_HELL|G_NOCORPSE|G_SGROUP|2), @@ -2590,8 +2592,8 @@ struct permonst _mons2[] = { MON("marilith", S_DEMON, LVL(7, 12, -6, 80, -12), (G_HELL|G_NOCORPSE|1), A(ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_WEAP, AD_PHYS, 2, 4), - ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_WEAP, AD_PHYS, 2, 4), - ATTK(AT_WEAP, AD_PHYS, 2, 4), ATTK(AT_WEAP, AD_PHYS, 2, 4)), + ATTK(AT_CLAW, AD_PHYS, 2, 4), ATTK(AT_CLAW, AD_PHYS, 2, 4), + ATTK(AT_CLAW, AD_PHYS, 2, 4), ATTK(AT_CLAW, AD_PHYS, 2, 4)), SIZ(WT_HUMAN, 400, 0, MS_CUSS, MZ_LARGE), MR_FIRE|MR_POISON, 0, M1_HUMANOID|M1_SLITHY|M1_SEE_INVIS|M1_POIS, M2_DEMON|M2_STALK|M2_HOSTILE|M2_NASTY|M2_FEMALE|M2_COLLECT, @@ -2668,7 +2670,7 @@ struct permonst _mons2[] = { MON("Yeenoghu", S_DEMON, LVL(56, 18, -5, 80, -15), (G_HELL|G_NOCORPSE|G_NOGEN|G_UNIQ), A(ATTK(AT_WEAP, AD_PHYS, 3, 6), ATTK(AT_WEAP, AD_CONF, 2, 8), - ATTK(AT_WEAP, AD_PLYS, 1, 6), ATTK(AT_MAGC, AD_MAGM, 2, 6), + ATTK(AT_CLAW, AD_PLYS, 1, 6), ATTK(AT_MAGC, AD_MAGM, 2, 6), NO_ATTK, NO_ATTK), SIZ(900, 500, 0, MS_ORC, MZ_LARGE), MR_FIRE|MR_POISON, 0, M1_FLY|M1_SEE_INVIS|M1_POIS, @@ -2677,8 +2679,8 @@ struct permonst _mons2[] = { M3_WANTSAMUL|M3_INFRAVISIBLE|M3_INFRAVISION, HI_LORD), MON("Orcus", S_DEMON, LVL(66, 9, -6, 85, -20), (G_HELL|G_NOCORPSE|G_NOGEN|G_UNIQ), - A(ATTK(AT_MAGC, AD_SPEL, 8, 6), ATTK(AT_WEAP, AD_PHYS, 3, 6), - ATTK(AT_CLAW, AD_PHYS, 3, 4), ATTK(AT_CLAW, AD_PHYS, 3, 4), + A(ATTK(AT_WEAP, AD_PHYS, 3, 6), ATTK(AT_CLAW, AD_PHYS, 3, 4), + ATTK(AT_CLAW, AD_PHYS, 3, 4), ATTK(AT_MAGC, AD_SPEL, 8, 6), ATTK(AT_STNG, AD_DRST, 2, 4), NO_ATTK), SIZ(1500, 500, 0, MS_ORC, MZ_HUGE), MR_FIRE|MR_POISON, 0, M1_FLY|M1_SEE_INVIS|M1_POIS, @@ -2811,7 +2813,7 @@ struct permonst _mons2[] = { NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(500, 350, 0, MS_SILENT, MZ_LARGE), 0, 0, M1_SWIM|M1_AMPHIBIOUS|M1_ANIMAL|M1_SLITHY|M1_NOLIMBS| - M1_CARNIVORE|M1_OVIPAROUS|M1_NOTAKE, + M1_CARNIVORE|M1_OVIPAROUS|M1_THICK_HIDE|M1_NOTAKE, M2_HOSTILE, 0, CLR_GRAY), MON("giant eel", S_EEL, LVL(5, 9, -1, 0, 0), (G_GENO|G_NOGEN), @@ -2917,15 +2919,15 @@ struct permonst _mons2[] = { */ MON("archeologist", S_HUMAN, LVL(10, 12, 10, 1, 3), G_NOGEN, - A(ATTK(AT_WEAP, AD_PHYS, 1, 6), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_TUNNEL|M1_NEEDPICK|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC), MON("barbarian", S_HUMAN, LVL(10, 12, 10, 1, 0), G_NOGEN, - A(ATTK(AT_WEAP, AD_PHYS, 1, 6), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), MR_POISON, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC), @@ -2954,15 +2956,15 @@ struct permonst _mons2[] = { M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC), MON("knight", S_HUMAN, LVL(10, 12, 10, 1, 3), G_NOGEN, - A(ATTK(AT_WEAP, AD_PHYS, 1, 6), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC), MON("monk", S_HUMAN, LVL(10, 12, 10, 2, 0), G_NOGEN, - A(ATTK(AT_KICK, AD_PHYS, 1, 8), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_CLAW, AD_PHYS, 1, 8), ATTK(AT_KICK, AD_PHYS, 1, 8), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_HERBIVORE, M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT|M2_MALE, @@ -2993,32 +2995,32 @@ struct permonst _mons2[] = { HI_DOMESTIC), MON("rogue", S_HUMAN, LVL(10, 12, 10, 1, -3), G_NOGEN, - A(ATTK(AT_WEAP, AD_PHYS, 1, 6), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_GREEDY|M2_JEWELS|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC), MON("samurai", S_HUMAN, LVL(10, 12, 10, 1, 3), G_NOGEN, - A(ATTK(AT_WEAP, AD_PHYS, 1, 8), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 8), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC), #ifdef TOURIST MON("tourist", S_HUMAN, LVL(10, 12, 10, 1, 0), G_NOGEN, - A(ATTK(AT_WEAP, AD_PHYS, 1, 6), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC), #endif MON("valkyrie", S_HUMAN, LVL(10, 12, 10, 1, -1), G_NOGEN, - A(ATTK(AT_WEAP, AD_PHYS, 1, 8), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 8), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), MR_COLD, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_STRONG|M2_FEMALE|M2_COLLECT, M3_INFRAVISIBLE, @@ -3094,8 +3096,8 @@ struct permonst _mons2[] = { M3_CLOSE|M3_INFRAVISIBLE, HI_LORD), MON("King Arthur", S_HUMAN, LVL(20, 12, 0, 40, 20), (G_NOGEN|G_UNIQ), - A(ATTK(AT_WEAP, AD_PHYS, 1, 6), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE| @@ -3143,8 +3145,8 @@ struct permonst _mons2[] = { M3_CLOSE|M3_INFRAVISIBLE, HI_LORD), MON("Lord Sato", S_HUMAN, LVL(20, 12, 0, 30, 20), (G_NOGEN|G_UNIQ), - A(ATTK(AT_WEAP, AD_PHYS, 1, 8), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 6), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE| @@ -3153,8 +3155,8 @@ struct permonst _mons2[] = { #ifdef TOURIST MON("Twoflower", S_HUMAN, LVL(20, 12, 10, 20, 0), (G_NOGEN|G_UNIQ), - A(ATTK(AT_WEAP, AD_PHYS, 1, 6), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_PNAME|M2_PEACEFUL|M2_STRONG|M2_MALE| @@ -3163,21 +3165,22 @@ struct permonst _mons2[] = { #endif MON("Norn", S_HUMAN, LVL(20, 12, 0, 80, 0), (G_NOGEN|G_UNIQ), - A(ATTK(AT_WEAP, AD_PHYS, 1, 8), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 6), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), MR_COLD, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_FEMALE| M2_COLLECT|M2_MAGIC, M3_CLOSE|M3_INFRAVISIBLE, HI_LORD), - MON("Wizard of Balance", S_HUMAN, + MON("Neferet the Green", S_HUMAN, LVL(20, 12, 0, 60, 0), (G_NOGEN|G_UNIQ), - A(ATTK(AT_WEAP, AD_PHYS, 1, 6), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MAGC, AD_SPEL, 2, 8), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_LEADER, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, - M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT|M2_MAGIC, - M3_CLOSE|M3_INFRAVISIBLE, HI_LORD), + M2_NOPOLY|M2_HUMAN|M2_FEMALE|M2_PNAME|M2_PEACEFUL| + M2_STRONG|M2_COLLECT|M2_MAGIC, + M3_CLOSE|M3_INFRAVISIBLE, CLR_GREEN), /* * quest nemeses */ @@ -3192,8 +3195,8 @@ struct permonst _mons2[] = { M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISION|M3_INFRAVISIBLE, CLR_RED), MON("Thoth Amon", S_HUMAN, LVL(16, 12, 0, 10, -14), (G_NOGEN|G_UNIQ|G_NOCORPSE), - A(ATTK(AT_MAGC, AD_SPEL, 0, 0), ATTK(AT_MAGC, AD_SPEL, 0, 0), - ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_CLAW, AD_SAMU, 1, 4), + A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MAGC, AD_SPEL, 0, 0), + ATTK(AT_MAGC, AD_SPEL, 0, 0), ATTK(AT_CLAW, AD_SAMU, 1, 4), NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_NEMESIS, MZ_HUMAN), MR_POISON, 0, M1_HUMANOID|M1_OMNIVORE, @@ -3311,8 +3314,8 @@ struct permonst _mons2[] = { M3_WANTSARTI|M3_WAITFORU|M3_INFRAVISION|M3_INFRAVISIBLE, HI_LORD), MON("Dark One", S_HUMAN, LVL(15, 12, 0, 80, -10), (G_NOGEN|G_UNIQ|G_NOCORPSE), - A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_MAGC, AD_SPEL, 0, 0), - ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_CLAW, AD_SAMU, 1, 4), + A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), + ATTK(AT_CLAW, AD_SAMU, 1, 4), ATTK(AT_MAGC, AD_SPEL, 0, 0), NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_NEMESIS, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, @@ -3366,8 +3369,8 @@ struct permonst _mons2[] = { HI_DOMESTIC), MON("page", S_HUMAN, LVL(5, 12, 10, 10, 3), G_NOGEN, - A(ATTK(AT_WEAP, AD_PHYS, 1, 6), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_GUARDIAN, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, @@ -3398,24 +3401,24 @@ struct permonst _mons2[] = { M3_INFRAVISION|M3_INFRAVISIBLE, HI_DOMESTIC), MON("thug", S_HUMAN, LVL(5, 12, 10, 10, -3), G_NOGEN, - A(ATTK(AT_WEAP, AD_PHYS, 1, 6), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 6), ATTK(AT_WEAP, AD_PHYS, 1, 6), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_GUARDIAN, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_GREEDY|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC), MON("ninja", S_HUMAN, LVL(5, 12, 10, 10, 3), G_NOGEN, - A(ATTK(AT_WEAP, AD_PHYS, 1, 8), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 8), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_HUMANOID, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_HOSTILE|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, HI_DOMESTIC), MON("roshi", S_HUMAN, LVL(5, 12, 10, 10, 3), G_NOGEN, - A(ATTK(AT_WEAP, AD_PHYS, 1, 8), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 8), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_GUARDIAN, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, @@ -3432,8 +3435,8 @@ struct permonst _mons2[] = { #endif MON("warrior", S_HUMAN, LVL(5, 12, 10, 10, -1), G_NOGEN, - A(ATTK(AT_WEAP, AD_PHYS, 1, 8), - NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), + A(ATTK(AT_WEAP, AD_PHYS, 1, 8), ATTK(AT_WEAP, AD_PHYS, 1, 8), + NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), SIZ(WT_HUMAN, 400, 0, MS_GUARDIAN, MZ_HUMAN), 0, 0, M1_HUMANOID|M1_OMNIVORE, M2_NOPOLY|M2_HUMAN|M2_PEACEFUL|M2_STRONG|M2_COLLECT, M3_INFRAVISIBLE, diff --git a/src/mplayer.c b/src/mplayer.c index e263d87..a62fba8 100644 --- a/src/mplayer.c +++ b/src/mplayer.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mplayer.c 3.3 97/02/04 */ +/* SCCS Id: @(#)mplayer.c 3.4 1997/02/04 */ /* Copyright (c) Izchak Miller, 1992. */ /* NetHack may be freely redistributed. See license for details. */ @@ -9,7 +9,7 @@ STATIC_DCL void FDECL(get_mplname, (struct monst *, char *)); STATIC_DCL void FDECL(mk_mplayer_armor, (struct monst *, SHORT_P)); /* These are the names of those who - * contributed to the development of NetHack 3.2/3.3. + * contributed to the development of NetHack 3.2/3.3/3.4. * * Keep in alphabetical order within teams. * Same first name is entered once within each team. @@ -18,17 +18,18 @@ static const char *developers[] = { /* devteam */ "Dave", "Dean", "Eric", "Izchak", "Janet", "Jessie", "Ken", "Kevin", "Michael", "Mike", "Pat", "Paul", "Steve", "Timo", + "Warwick", /* PC team */ "Bill", "Eric", "Keizo", "Ken", "Kevin", "Michael", "Mike", "Paul", "Stephen", "Steve", "Timo", "Yitzhak", /* Amiga team */ - "Andy", "Gregg", "Keni", "Mike", "Olaf", "Richard", + "Andy", "Gregg", "Janne", "Keni", "Mike", "Olaf", "Richard", /* Mac team */ "Andy", "Chris", "Dean", "Jon", "Jonathan", "Kevin", "Wang", /* Atari team */ - "Eric", "Warwick", + "Eric", "Marvin", "Warwick", /* NT team */ - "Michael", + "Alex", "Dion", "Michael", /* OS/2 team */ "Helge", "Ron", "Timo", /* VMS team */ @@ -255,7 +256,11 @@ register boolean special; (void)mongets(mtmp, rnd_class(DILITHIUM_CRYSTAL, JADE)); /* To get the gold "right" would mean a player can double his */ /* gold supply by killing one mplayer. Not good. */ +#ifndef GOLDOBJ mtmp->mgold = rn2(1000); +#else + mkmonmoney(mtmp, rn2(1000)); +#endif quan = rn2(10); while(quan--) (void) mpickobj(mtmp, mkobj(RANDOM_CLASS, FALSE)); diff --git a/src/mthrowu.c b/src/mthrowu.c index 2377ad2..1943b3d 100644 --- a/src/mthrowu.c +++ b/src/mthrowu.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mthrowu.c 3.3 2000/07/07 */ +/* SCCS Id: @(#)mthrowu.c 3.4 2001/12/10 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -32,9 +32,9 @@ STATIC_OVL NEARDATA const char *breathwep[] = { "strange breath #9" }; - +/* hero is hit by something other than a monster */ int -thitu(tlev, dam, obj, name) /* u is hit by sth, but not a monster */ +thitu(tlev, dam, obj, name) int tlev, dam; struct obj *obj; const char *name; /* if null, then format `obj' */ @@ -48,7 +48,8 @@ const char *name; /* if null, then format `obj' */ unsigned save_ocknown; if (!obj) panic("thitu: name & obj both null?"); - name = strcpy(onmbuf, (obj->quan > 1L) ? doname(obj) : xname(obj)); + name = strcpy(onmbuf, + (obj->quan > 1L) ? doname(obj) : mshot_xname(obj)); /* killer name should be more specific; however, exact info like blessed/cursed and rustproof make things too verbose */ otmp = *obj; @@ -71,11 +72,11 @@ const char *name; /* if null, then format `obj' */ if(u.uac + tlev <= rnd(20)) { if(Blind || !flags.verbose) pline("It misses."); - else You("are almost hit by %s!", onm); + else You("are almost hit by %s.", onm); return(0); } else { if(Blind || !flags.verbose) You("are hit!"); - else You("are hit by %s!", onm); + else You("are hit by %s%s", onm, exclam(dam)); if (obj && objects[obj->otyp].oc_material == SILVER && hates_silver(youmonst.data)) { @@ -129,6 +130,10 @@ int x,y; if (!objgone) { if (!flooreffects(obj,x,y,"fall")) { /* don't double-dip on damage */ place_object(obj, x, y); + if (!mtmp && x == u.ux && y == u.uy) + mtmp = &youmonst; + if (mtmp && ohit) + passive_obj(mtmp, obj, (struct attack *)0); stackobj(obj); retvalu = 0; } @@ -161,7 +166,7 @@ boolean verbose; /* give message(s) even when you can't see what happened */ tmp = 5 + find_mac(mtmp) + omon_adj(mtmp, otmp, FALSE); if (tmp < rnd(20)) { if (!ismimic) { - if (vis) miss(distant_name(otmp, xname), mtmp); + if (vis) miss(distant_name(otmp, mshot_xname), mtmp); else if (verbose) pline("It is missed."); } if (!range) { /* Last position; object drops */ @@ -180,7 +185,7 @@ boolean verbose; /* give message(s) even when you can't see what happened */ damage = 0; if (ismimic) seemimic(mtmp); mtmp->msleeping = 0; - if (vis) hit(distant_name(otmp,xname), mtmp, exclam(damage)); + if (vis) hit(distant_name(otmp,mshot_xname), mtmp, exclam(damage)); else if (verbose) pline("It is hit%s", exclam(damage)); if (otmp->opoisoned) { @@ -218,7 +223,8 @@ boolean verbose; /* give message(s) even when you can't see what happened */ pline("%s is %s!", Monnam(mtmp), (nonliving(mtmp->data) || !vis) ? "destroyed" : "killed"); - mondied(mtmp); + if (!flags.mon_moving) xkilled(mtmp,0); + else mondied(mtmp); } if (can_blnd((struct monst*)0, mtmp, @@ -270,14 +276,14 @@ m_throw(mon, x, y, dx, dy, range, obj) /* not possibly_unwield, which checks the object's */ /* location, not its existence */ if (MON_WEP(mon) == obj) { - obj->owornmask &= ~W_WEP; + setmnotwielded(mon,obj); MON_NOWEP(mon); } obj_extract_self(obj); singleobj = obj; obj = (struct obj *) 0; } else { - singleobj = splitobj(obj, obj->quan - 1L); + singleobj = splitobj(obj, 1L); obj_extract_self(singleobj); } @@ -288,8 +294,8 @@ m_throw(mon, x, y, dx, dy, range, obj) if(is_ammo(singleobj)) pline("%s misfires!", Monnam(mon)); else - pline("%s slips as %s throws it!", - The(xname(singleobj)), mon_nam(mon)); + pline("%s as %s throws it!", + Tobjnam(singleobj, "slip"), mon_nam(mon)); } dx = rn2(3)-1; dy = rn2(3)-1; @@ -389,26 +395,33 @@ m_throw(mon, x, y, dx, dy, range, obj) poisoned(onmbuf, A_STR, knmbuf, 10); objects[otmp.otyp].oc_name_known = save_ocknown; } - if(hitu && (singleobj->otyp == CREAM_PIE || - singleobj->otyp == BLINDING_VENOM)) { + if(hitu && + can_blnd((struct monst*)0, &youmonst, + (uchar)(singleobj->otyp == BLINDING_VENOM ? + AT_SPIT : AT_WEAP), singleobj)) { blindinc = rnd(25); if(singleobj->otyp == CREAM_PIE) { if(!Blind) pline("Yecch! You've been creamed."); - else pline("There's %s sticky all over your %s.", - something, - body_part(FACE)); - } else { /* venom in the eyes */ - if(ublindf) /* nothing */ ; - else if(!Blind) pline_The("venom blinds you."); - else Your("%s sting.", makeplural(body_part(EYE))); + else pline("There's %s sticky all over your %s.", + something, + body_part(FACE)); + } else if(singleobj->otyp == BLINDING_VENOM) { + int num_eyes = eyecount(youmonst.data); + /* venom in the eyes */ + if(!Blind) pline_The("venom blinds you."); + else Your("%s sting%s.", + (num_eyes == 1) ? body_part(EYE) : + makeplural(body_part(EYE)), + (num_eyes == 1) ? "s" : ""); } } if (hitu && singleobj->otyp == EGG) { if (!Stone_resistance - && !(poly_when_stoned(youmonst.data) && - polymon(PM_STONE_GOLEM))) + && !(poly_when_stoned(youmonst.data) && + polymon(PM_STONE_GOLEM))) { Stoned = 5; killer = (char *) 0; + } } stop_occupation(); if (hitu || !range) { @@ -434,10 +447,11 @@ m_throw(mon, x, y, dx, dy, range, obj) tmp_at(bhitpos.x, bhitpos.y); delay_output(); tmp_at(DISP_END, 0); - /* blindfolds, towels, & lenses keep substances out of your eyes */ - if (blindinc && !ublindf) { + + if (blindinc) { u.ucreamed += blindinc; - make_blinded(Blinded + blindinc,FALSE); + make_blinded(Blinded + (long)blindinc, FALSE); + if (!Blind) Your(vision_clears); } } @@ -452,6 +466,7 @@ struct obj *obj; { if (obj->quan > 1L) { obj->quan--; + obj->owt = weight(obj); } else { obj_extract_self(obj); possibly_unwield(mon); @@ -459,22 +474,23 @@ struct obj *obj; mon->misc_worn_check &= ~obj->owornmask; update_mon_intrinsics(mon, obj, FALSE); } - dealloc_obj(obj); + obfree(obj, (struct obj*) 0); } } #endif /* OVLB */ #ifdef OVL1 +/* monster attempts ranged weapon attack against player */ void -thrwmu(mtmp) /* monster throws item at you */ -register struct monst *mtmp; +thrwmu(mtmp) +struct monst *mtmp; { struct obj *otmp, *mwep; - register xchar x, y; - boolean ispole; + xchar x, y; schar skill; - int multishot = 1; + int multishot; + const char *onm; /* Rearranged beginning so monsters can use polearms not in a line */ if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) { @@ -486,102 +502,114 @@ register struct monst *mtmp; /* Pick a weapon */ otmp = select_rwep(mtmp); if (!otmp) return; - ispole = is_pole(otmp); - skill = objects[otmp->otyp].oc_skill; - mwep = MON_WEP(mtmp); /* wielded weapon */ - if(ispole || lined_up(mtmp)) { - /* If you are coming toward the monster, the monster - * should try to soften you up with missiles. If you are - * going away, you are probably hurt or running. Give - * chase, but if you are getting too far away, throw. - */ - x = mtmp->mx; - y = mtmp->my; - if(ispole || !URETREATING(x,y) || - !rn2(BOLT_LIM-distmin(x,y,mtmp->mux,mtmp->muy))) - { - const char *verb = "throws"; - - if (otmp->otyp == ARROW - || otmp->otyp == ELVEN_ARROW - || otmp->otyp == ORCISH_ARROW - || otmp->otyp == YA - || otmp->otyp == CROSSBOW_BOLT) verb = "shoots"; - if (ispole) { - if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) <= - POLE_LIM && couldsee(mtmp->mx, mtmp->my)) - verb = "thrusts"; - else return; /* Out of range, or intervening wall */ - } + if (is_pole(otmp)) { + int dam, hitv; - if (canseemon(mtmp)) { - pline("%s %s %s!", Monnam(mtmp), verb, - obj_is_pname(otmp) ? - the(singular(otmp, xname)) : - an(singular(otmp, xname))); - } + if (dist2(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy) > POLE_LIM || + !couldsee(mtmp->mx, mtmp->my)) + return; /* Out of range, or intervening wall */ - /* Use a pole */ - if (ispole) { - int dam = dmgval(otmp, &youmonst); - int hitv = 3 - distmin(u.ux,u.uy, mtmp->mx,mtmp->my); + if (canseemon(mtmp)) { + onm = xname(otmp); + pline("%s thrusts %s.", Monnam(mtmp), + obj_is_pname(otmp) ? the(onm) : an(onm)); + } - if (hitv < -4) hitv = -4; - if (bigmonst(youmonst.data)) hitv++; - hitv += 8 + otmp->spe; - if (dam < 1) dam = 1; - (void) thitu(hitv, dam, otmp, (char *)0); + dam = dmgval(otmp, &youmonst); + hitv = 3 - distmin(u.ux,u.uy, mtmp->mx,mtmp->my); + if (hitv < -4) hitv = -4; + if (bigmonst(youmonst.data)) hitv++; + hitv += 8 + otmp->spe; + if (dam < 1) dam = 1; - return; - } + (void) thitu(hitv, dam, otmp, (char *)0); + stop_occupation(); + return; + } - /* Multishot calculations */ - if ((ammo_and_launcher(otmp, mwep) || skill == P_DAGGER || - skill == -P_DART || skill == -P_SHURIKEN) && - !mtmp->mconf) { - /* Assumes lords are skilled, princes are expert */ - if (is_lord(mtmp->data)) multishot++; - if (is_prince(mtmp->data)) multishot += 2; - - switch (monsndx(mtmp->data)) { - case PM_RANGER: - multishot++; - break; - case PM_ROGUE: - if (skill == P_DAGGER) multishot++; - break; - case PM_SAMURAI: - if (otmp->otyp == YA && mwep && - mwep->otyp == YUMI) multishot++; - break; - default: - break; - } - { /* racial bonus */ - if (is_elf(mtmp->data) && - otmp->otyp == ELVEN_ARROW && - mwep && mwep->otyp == ELVEN_BOW) - multishot++; - else if (is_orc(mtmp->data) && - otmp->otyp == ORCISH_ARROW && - mwep && mwep->otyp == ORCISH_BOW) - multishot++; - } - } - if (otmp->quan < multishot) multishot = (int)otmp->quan; - if (multishot < 1) multishot = 1; - else multishot = rnd(multishot); - while (multishot-- > 0) - m_throw(mtmp, mtmp->mx, mtmp->my, - sgn(tbx), sgn(tby), - distmin(mtmp->mx, mtmp->my, - mtmp->mux, mtmp->muy), - otmp); - nomul(0); - return; - } + x = mtmp->mx; + y = mtmp->my; + /* If you are coming toward the monster, the monster + * should try to soften you up with missiles. If you are + * going away, you are probably hurt or running. Give + * chase, but if you are getting too far away, throw. + */ + if (!lined_up(mtmp) || + (URETREATING(x,y) && + rn2(BOLT_LIM - distmin(x,y,mtmp->mux,mtmp->muy)))) + return; + + skill = objects[otmp->otyp].oc_skill; + mwep = MON_WEP(mtmp); /* wielded weapon */ + + /* Multishot calculations */ + multishot = 1; + if ((ammo_and_launcher(otmp, mwep) || skill == P_DAGGER || + skill == -P_DART || skill == -P_SHURIKEN) && !mtmp->mconf) { + /* Assumes lords are skilled, princes are expert */ + if (is_prince(mtmp->data)) multishot += 2; + else if (is_lord(mtmp->data)) multishot++; + + switch (monsndx(mtmp->data)) { + case PM_RANGER: + multishot++; + break; + case PM_ROGUE: + if (skill == P_DAGGER) multishot++; + break; + case PM_NINJA: + case PM_SAMURAI: + if (otmp->otyp == YA && mwep && + mwep->otyp == YUMI) multishot++; + break; + default: + break; + } + /* racial bonus */ + if ((is_elf(mtmp->data) && + otmp->otyp == ELVEN_ARROW && + mwep && mwep->otyp == ELVEN_BOW) || + (is_orc(mtmp->data) && + otmp->otyp == ORCISH_ARROW && + mwep && mwep->otyp == ORCISH_BOW)) + multishot++; + + if ((long)multishot > otmp->quan) multishot = (int)otmp->quan; + if (multishot < 1) multishot = 1; + else multishot = rnd(multishot); } + + if (canseemon(mtmp)) { + char onmbuf[BUFSZ]; + + if (multishot > 1) { + /* "N arrows"; multishot > 1 implies otmp->quan > 1, so + xname()'s result will already be pluralized */ + Sprintf(onmbuf, "%d %s", multishot, xname(otmp)); + onm = onmbuf; + } else { + /* "an arrow" */ + onm = singular(otmp, xname); + onm = obj_is_pname(otmp) ? the(onm) : an(onm); + } + m_shot.s = ammo_and_launcher(otmp,mwep) ? TRUE : FALSE; + pline("%s %s %s!", Monnam(mtmp), + m_shot.s ? "shoots" : "throws", onm); + m_shot.o = otmp->otyp; + } else { + m_shot.o = STRANGE_OBJECT; /* don't give multishot feedback */ + } + + m_shot.n = multishot; + for (m_shot.i = 1; m_shot.i <= m_shot.n; m_shot.i++) + m_throw(mtmp, mtmp->mx, mtmp->my, sgn(tbx), sgn(tby), + distmin(mtmp->mx, mtmp->my, mtmp->mux, mtmp->muy), otmp); + m_shot.n = m_shot.i = 0; + m_shot.o = STRANGE_OBJECT; + m_shot.s = FALSE; + + nomul(0); } #endif /* OVL1 */ diff --git a/src/muse.c b/src/muse.c index b00d443..f1e7f0d 100644 --- a/src/muse.c +++ b/src/muse.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)muse.c 3.3 2000/06/02 */ +/* SCCS Id: @(#)muse.c 3.4 2002/02/07 */ /* Copyright (C) 1990 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -19,6 +19,7 @@ boolean m_using = FALSE; * don't know not to read scrolls, etc.... */ +STATIC_DCL struct permonst *FDECL(muse_newcham_mon, (struct monst *)); STATIC_DCL int FDECL(precheck, (struct monst *,struct obj *)); STATIC_DCL void FDECL(mzapmsg, (struct monst *,struct obj *,BOOLEAN_P)); STATIC_DCL void FDECL(mreadmsg, (struct monst *,struct obj *)); @@ -28,6 +29,8 @@ STATIC_DCL void FDECL(mbhit, (struct monst *,int,int FDECL((*),(MONST_P,OBJ_P)), int FDECL((*),(OBJ_P,OBJ_P)),struct obj *)); STATIC_DCL void FDECL(you_aggravate, (struct monst *)); +STATIC_DCL void FDECL(mon_consume_unstone, (struct monst *,struct obj *, + BOOLEAN_P,BOOLEAN_P)); static struct musable { struct obj *offensive; @@ -153,7 +156,7 @@ boolean self; "nearby" : "distant"); } else if (self) pline("%s zaps %sself with %s!", - Monnam(mtmp), him[pronoun_gender(mtmp)], doname(otmp)); + Monnam(mtmp), mhim(mtmp), doname(otmp)); else { pline("%s zaps %s!", Monnam(mtmp), an(xname(otmp))); stop_occupation(); @@ -196,7 +199,7 @@ struct obj *otmp; if (mtmp->mconf) pline("Being confused, %s mispronounces the magic words...", - vismon ? mon_nam(mtmp) : he[pronoun_gender(mtmp)]); + vismon ? mon_nam(mtmp) : mhe(mtmp)); } STATIC_OVL void @@ -234,6 +237,7 @@ struct obj *otmp; #define MUSE_BUGLE 16 #define MUSE_UNICORN_HORN 17 #define MUSE_POT_FULL_HEALING 18 +#define MUSE_LIZARD_CORPSE 19 /* #define MUSE_INNATE_TPT 9999 * We cannot use this. Since monsters get unlimited teleportation, if they @@ -281,6 +285,16 @@ struct monst *mtmp; } } + if (mtmp->mconf) { + for(obj = mtmp->minvent; obj; obj = obj->nobj) { + if (obj->otyp == CORPSE && obj->corpsenm == PM_LIZARD) { + m.defensive = obj; + m.has_defense = MUSE_LIZARD_CORPSE; + return TRUE; + } + } + } + /* It so happens there are two unrelated cases when we might want to * check specifically for healing alone. The first is when the monster * is blind (healing cures blindness). The second is when the monster @@ -419,6 +433,8 @@ struct monst *mtmp; if (obj->otyp == WAN_DIGGING && obj->spe > 0 && !stuck && !t && !mtmp->isshk && !mtmp->isgd && !mtmp->ispriest && !is_floater(mtmp->data) + /* monsters digging in Sokoban can ruin things */ + && !In_sokoban(&u.uz) /* digging wouldn't be effective; assume they know that */ && !(levl[x][y].wall_info & W_NONDIGGABLE) && !(Is_botlevel(&u.uz) || In_endgame(&u.uz)) @@ -509,7 +525,7 @@ struct monst *mtmp; rushing right straight back; don't override if already scared */ fleetim = !mtmp->mflee ? (33 - (30 * mtmp->mhp / mtmp->mhpmax)) : 0; #define m_flee(m) if (fleetim && !m->iswiz) \ - { m->mflee = 1; m->mfleetim = fleetim; } + { monflee(m, fleetim, FALSE, FALSE); } switch(m.has_defense) { case MUSE_UNICORN_HORN: @@ -701,6 +717,10 @@ struct monst *mtmp; pline("%s %s into a %s!", Monnam(mtmp), makeplural(locomotion(mtmp->data, "jump")), t->ttyp == TRAPDOOR ? "trap door" : "hole"); + if (levl[trapx][trapy].typ == SCORR) { + levl[trapx][trapy].typ = CORR; + unblock_point(trapx, trapy); + } seetrap(t_at(trapx,trapy)); } @@ -734,7 +754,7 @@ struct monst *mtmp; (dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz) - 3)) { if (vismon) pline( "As %s climbs the stairs, a mysterious force momentarily surrounds %s...", - mon_nam(mtmp), him[pronoun_gender(mtmp)]); + mon_nam(mtmp), mhim(mtmp)); /* simpler than for the player; this will usually be the Wizard and he'll immediately go right to the upstairs, so there's not much point in having any @@ -787,6 +807,10 @@ struct monst *mtmp; if (vis) { pline("%s %s onto a teleport trap!", Monnam(mtmp), makeplural(locomotion(mtmp->data, "jump"))); + if (levl[trapx][trapy].typ == SCORR) { + levl[trapx][trapy].typ = CORR; + unblock_point(trapx, trapy); + } seetrap(t_at(trapx,trapy)); } /* don't use rloc_to() because worm tails must "move" */ @@ -839,6 +863,10 @@ struct monst *mtmp; if (oseen) makeknown(otmp->otyp); m_useup(mtmp, otmp); return 2; + case MUSE_LIZARD_CORPSE: + /* not actually called for its unstoning effect */ + mon_consume_unstone(mtmp, otmp, FALSE, FALSE); + return 2; case 0: return 0; /* i.e. an exploded wand */ default: impossible("%s wanted to perform action %d?", Monnam(mtmp), m.has_defense); @@ -987,7 +1015,7 @@ struct monst *mtmp; m.has_offense = MUSE_POT_PARALYSIS; } nomore(MUSE_POT_BLINDNESS); - if(obj->otyp == POT_BLINDNESS) { + if(obj->otyp == POT_BLINDNESS && !attacktype(mtmp->data, AT_GAZE)) { m.offensive = obj; m.has_offense = MUSE_POT_BLINDNESS; } @@ -1332,7 +1360,7 @@ struct monst *mtmp; if (canspotmon(mtmp2)) pline("%s's %s does not protect %s.", Monnam(mtmp2), xname(helmet), - him[pronoun_gender(mtmp2)]); + mhim(mtmp2)); } } mtmp2->mhp -= mdmg; @@ -1352,7 +1380,7 @@ struct monst *mtmp; } m_useup(mtmp, otmp); /* Attack the player */ - if (dist2(mmx, mmy, u.ux, u.uy) == 1 && !otmp->cursed) { + if (distmin(mmx, mmy, u.ux, u.uy) == 1 && !otmp->cursed) { int dmg; struct obj *otmp2; @@ -1579,7 +1607,7 @@ struct monst *mtmp; if(obj->otyp == WAN_MAKE_INVISIBLE && obj->spe > 0 && !mtmp->minvis && !mtmp->invis_blkd && (!mtmp->mpeaceful || See_invisible) && - (mdat != &mons[PM_MEDUSA] || mtmp->mcan)) { + (!attacktype(mtmp->data, AT_GAZE) || mtmp->mcan)) { m.misc = obj; m.has_misc = MUSE_WAN_MAKE_INVISIBLE; } @@ -1587,7 +1615,7 @@ struct monst *mtmp; if(obj->otyp == POT_INVISIBILITY && !mtmp->minvis && !mtmp->invis_blkd && (!mtmp->mpeaceful || See_invisible) && - (mdat != &mons[PM_MEDUSA] || mtmp->mcan)) { + (!attacktype(mtmp->data, AT_GAZE) || mtmp->mcan)) { m.misc = obj; m.has_misc = MUSE_POT_INVISIBILITY; } @@ -1620,6 +1648,23 @@ struct monst *mtmp; #undef nomore } +/* type of monster to polymorph into; defaults to one suitable for the + current level rather than the totally arbitrary choice of newcham() */ +static struct permonst * +muse_newcham_mon(mon) +struct monst *mon; +{ + struct obj *m_armr; + + if ((m_armr = which_armor(mon, W_ARM)) != 0) { + if (Is_dragon_scales(m_armr)) + return Dragon_scales_to_pm(m_armr); + else if (Is_dragon_mail(m_armr)) + return Dragon_mail_to_pm(m_armr); + } + return rndmonst(); +} + int use_misc(mtmp) struct monst *mtmp; @@ -1701,7 +1746,7 @@ struct monst *mtmp; case MUSE_WAN_SPEED_MONSTER: mzapmsg(mtmp, otmp, TRUE); otmp->spe--; - mon_adjust_speed(mtmp, 1); + mon_adjust_speed(mtmp, 1, otmp); return 2; case MUSE_POT_SPEED: mquaffmsg(mtmp, otmp); @@ -1709,22 +1754,19 @@ struct monst *mtmp; different methods of maintaining speed ratings: player's character becomes "very fast" temporarily; monster becomes "one stage faster" permanently */ - if (vismon) - pline("%s is suddenly moving faster.", Monnam(mtmp)); - if (oseen) makeknown(POT_SPEED); - mon_adjust_speed(mtmp, 1); + mon_adjust_speed(mtmp, 1, otmp); m_useup(mtmp, otmp); return 2; case MUSE_WAN_POLYMORPH: mzapmsg(mtmp, otmp, TRUE); otmp->spe--; - (void) newcham(mtmp, rndmonst()); + (void) newcham(mtmp, muse_newcham_mon(mtmp), TRUE); if (oseen) makeknown(WAN_POLYMORPH); return 2; case MUSE_POT_POLYMORPH: mquaffmsg(mtmp, otmp); if (vismon) pline("%s suddenly mutates!", Monnam(mtmp)); - (void) newcham(mtmp, rndmonst()); + (void) newcham(mtmp, muse_newcham_mon(mtmp), FALSE); if (oseen) makeknown(POT_POLYMORPH); m_useup(mtmp, otmp); return 2; @@ -1742,7 +1784,7 @@ struct monst *mtmp; if (mtmp->wormno) worm_move(mtmp); newsym(trapx, trapy); - (void) newcham(mtmp, (struct permonst *)0); + (void) newcham(mtmp, (struct permonst *)0, FALSE); return 2; case MUSE_BULLWHIP: /* attempt to disarm hero */ @@ -1767,16 +1809,21 @@ struct monst *mtmp; } pline("%s wraps around %s you're wielding!", The_whip, the_weapon); - if (obj->cursed) { - pline("%s is welded to your %s%c", - (obj->quan == 1L) ? "It" : "They", + if (welded(obj)) { + pline("%s welded to your %s%c", + !is_plural(obj) ? "It is" : "They are", hand, !obj->bknown ? '!' : '.'); - obj->bknown = 1; + /* obj->bknown = 1; */ /* welded() takes care of this */ where_to = 0; } if (!where_to) { pline_The("whip slips free."); /* not `The_whip' */ return 1; + } else if (where_to == 3 && hates_silver(mtmp->data) && + objects[obj->otyp].oc_material == SILVER) { + /* this monster won't want to catch a silver + weapon; drop it at hero's feet instead */ + where_to = 2; } freeinv(obj); uwepgone(); @@ -1784,10 +1831,6 @@ struct monst *mtmp; case 1: /* onto floor beneath mon */ pline("%s yanks %s from your %s!", Monnam(mtmp), the_weapon, hand); - if (obj->otyp == CRYSKNIFE && (!obj->oerodeproof || !rn2(10))) { - obj->otyp = WORM_TOOTH; - obj->oerodeproof = 0; - } place_object(obj, mtmp->mx, mtmp->my); break; case 2: /* onto floor beneath you */ @@ -1886,12 +1929,14 @@ struct obj *obj; return FALSE; if (typ == WAN_MAKE_INVISIBLE || typ == POT_INVISIBILITY) - return (boolean)(!mon->minvis && !mon->invis_blkd); + return (boolean)(!mon->minvis && !mon->invis_blkd && !attacktype(mon->data, AT_GAZE)); if (typ == WAN_SPEED_MONSTER || typ == POT_SPEED) return (boolean)(mon->mspeed != MFAST); switch (obj->oclass) { case WAND_CLASS: + if (obj->spe <= 0) + return FALSE; if (typ == WAN_DIGGING) return (boolean)(!is_floater(mon->data)); if (typ == WAN_POLYMORPH) @@ -1911,9 +1956,10 @@ struct obj *obj; typ == POT_PARALYSIS || typ == POT_SLEEPING || typ == POT_ACID || - typ == POT_BLINDNESS || typ == POT_CONFUSION) return TRUE; + if (typ == POT_BLINDNESS && !attacktype(mon->data, AT_GAZE)) + return TRUE; break; case SCROLL_CLASS: if (typ == SCR_TELEPORTATION || typ == SCR_CREATE_MONSTER @@ -1932,7 +1978,7 @@ struct obj *obj; if (typ == UNICORN_HORN) return (boolean)(!obj->cursed && !is_unicorn(mon->data)); if (typ == FROST_HORN || typ == FIRE_HORN) - return TRUE; + return (obj->spe > 0); break; case FOOD_CLASS: if (typ == CORPSE) @@ -1940,7 +1986,8 @@ struct obj *obj; touch_petrifies(&mons[obj->corpsenm])) || (!resists_ston(mon) && (obj->corpsenm == PM_LIZARD || - acidic(&mons[obj->corpsenm])))); + (acidic(&mons[obj->corpsenm]) && + obj->corpsenm != PM_GREEN_SLIME)))); if (typ == EGG) return (boolean)(touch_petrifies(&mons[obj->corpsenm])); break; @@ -1976,7 +2023,8 @@ const char *str; if (str) pline(str, s_suffix(mon_nam(mon)), "armor"); return TRUE; - } else if (mon->data == &mons[PM_SILVER_DRAGON]) { + } else if (mon->data == &mons[PM_SILVER_DRAGON] || + mon->data == &mons[PM_CHROMATIC_DRAGON]) { /* Silver dragons only reflect when mature; babies do not */ if (str) pline(str, s_suffix(mon_nam(mon)), "scales"); @@ -2034,51 +2082,67 @@ boolean by_you; for(obj = mon->minvent; obj; obj = obj->nobj) { /* Monsters can also use potions of acid */ if ((obj->otyp == POT_ACID) || (obj->otyp == CORPSE && - (obj->corpsenm == PM_LIZARD || acidic(&mons[obj->corpsenm])))) { - int nutrit = dog_nutrition(mon, obj); /* also sets meating */ - - if (canseemon(mon)) { - long save_quan = obj->quan; - - obj->quan = 1L; - pline("%s %ss %s.", Monnam(mon), - (obj->otyp == POT_ACID) ? "quaff" : "eat", - distant_name(obj,doname)); - obj->quan = save_quan; - } else if (flags.soundok) - You_hear("%s.", (obj->otyp == POT_ACID) ? "drinking" : "chewing"); - m_useup(mon, obj); - if (((obj->otyp == POT_ACID) || acidic(&mons[obj->corpsenm])) && - !resists_acid(mon)) { - mon->mhp -= rnd(15); - pline("%s has a very bad case of stomach acid.", - Monnam(mon)); - } - if (mon->mhp <= 0) { - pline("%s dies!", Monnam(mon)); - if (by_you) xkilled(mon, 0); - else mondead(mon); - return TRUE; - } - if (canseemon(mon)) { - if (Hallucination) - pline("What a pity - %s just ruined a future piece of art!", - mon_nam(mon)); - else - pline("%s seems limber!", Monnam(mon)); - } - if (mon->mtame && !mon->isminion) { - struct edog *edog = EDOG(mon); - - if (edog->hungrytime < moves) edog->hungrytime = moves; - edog->hungrytime += nutrit; - mon->mconf = 0; - } - mon->mlstmv = monstermoves; /* it takes a turn */ + (obj->corpsenm == PM_LIZARD || (acidic(&mons[obj->corpsenm]) && obj->corpsenm != PM_GREEN_SLIME)))) { + mon_consume_unstone(mon, obj, by_you, TRUE); return TRUE; } } return FALSE; } +STATIC_OVL void +mon_consume_unstone(mon, obj, by_you, stoning) +struct monst *mon; +struct obj *obj; +boolean by_you; +boolean stoning; +{ + int nutrit = (obj->otyp == CORPSE) ? dog_nutrition(mon, obj) : 0; + /* also sets meating */ + + if (canseemon(mon)) { + long save_quan = obj->quan; + + obj->quan = 1L; + pline("%s %ss %s.", Monnam(mon), + (obj->otyp == POT_ACID) ? "quaff" : "eat", + distant_name(obj,doname)); + obj->quan = save_quan; + } else if (flags.soundok) + You_hear("%s.", (obj->otyp == POT_ACID) ? "drinking" : "chewing"); + m_useup(mon, obj); + if (((obj->otyp == POT_ACID) || acidic(&mons[obj->corpsenm])) && + !resists_acid(mon)) { + mon->mhp -= rnd(15); + pline("%s has a very bad case of stomach acid.", + Monnam(mon)); + } + if (mon->mhp <= 0) { + pline("%s dies!", Monnam(mon)); + if (by_you) xkilled(mon, 0); + else mondead(mon); + return; + } + if (stoning && canseemon(mon)) { + if (Hallucination) + pline("What a pity - %s just ruined a future piece of art!", + mon_nam(mon)); + else + pline("%s seems limber!", Monnam(mon)); + } + if (obj->otyp == CORPSE && obj->corpsenm == PM_LIZARD && mon->mconf) { + mon->mconf = 0; + if (canseemon(mon)) + pline("%s seems steadier now.", Monnam(mon)); + } + if (mon->mtame && !mon->isminion && nutrit > 0) { + struct edog *edog = EDOG(mon); + + if (edog->hungrytime < monstermoves) edog->hungrytime = monstermoves; + edog->hungrytime += nutrit; + mon->mconf = 0; + } + mon->mlstmv = monstermoves; /* it takes a turn */ +} + /*muse.c*/ diff --git a/src/music.c b/src/music.c index bcff5d2..6cdb54f 100644 --- a/src/music.c +++ b/src/music.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)music.c 3.3 1999/08/19 */ +/* SCCS Id: @(#)music.c 3.4 2001/12/03 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -73,8 +73,8 @@ int distance; mtmp->mfrozen = 0; /* May scare some monsters */ if (distm < distance/3 && - !resist(mtmp, SCROLL_CLASS, 0, NOTELL)) - mtmp->mflee = 1; + !resist(mtmp, TOOL_CLASS, 0, NOTELL)) + monflee(mtmp, 0, FALSE, TRUE); } } mtmp = mtmp->nmon; @@ -93,7 +93,7 @@ int distance; while(mtmp) { if (!DEADMONSTER(mtmp) && distu(mtmp->mx, mtmp->my) < distance && - sleep_monst(mtmp, d(10,10), WAND_CLASS)) { + sleep_monst(mtmp, d(10,10), TOOL_CLASS)) { mtmp->msleeping = 1; /* 10d10 turns + wake_nearby to rouse */ slept_monst(mtmp); } @@ -117,6 +117,7 @@ int distance; distu(mtmp->mx, mtmp->my) < distance) { was_peaceful = mtmp->mpeaceful; mtmp->mpeaceful = 1; + mtmp->mavenge = 0; could_see_mon = canseemon(mtmp); mtmp->mundetected = 0; newsym(mtmp->mx, mtmp->my); @@ -149,6 +150,7 @@ int distance; distu(mtmp->mx, mtmp->my) < distance) { mtmp->msleeping = 0; mtmp->mpeaceful = 1; + mtmp->mavenge = 0; if (canseemon(mtmp)) pline( "%s listens cheerfully to the music, then seems quieter.", @@ -179,22 +181,29 @@ awaken_soldiers() } } -/* Charm monsters in range. Note that they may resist the spell. */ +/* Charm monsters in range. Note that they may resist the spell. + * If swallowed, range is reduced to 0. + */ STATIC_OVL void charm_monsters(distance) int distance; { - register struct monst *mtmp = fmon, *mtmp2; + struct monst *mtmp, *mtmp2; - while(mtmp) { + if (u.uswallow) { + if (!resist(u.ustuck, TOOL_CLASS, 0, NOTELL)) + (void) tamedog(u.ustuck, (struct obj *) 0); + } else { + for (mtmp = fmon; mtmp; mtmp = mtmp2) { mtmp2 = mtmp->nmon; - if (!DEADMONSTER(mtmp)) { - if (distu(mtmp->mx, mtmp->my) <= distance) - if(!resist(mtmp, SCROLL_CLASS, 0, NOTELL)) - (void) tamedog(mtmp, (struct obj *) 0); + if (DEADMONSTER(mtmp)) continue; + + if (distu(mtmp->mx, mtmp->my) <= distance) { + if (!resist(mtmp, TOOL_CLASS, 0, NOTELL)) + (void) tamedog(mtmp, (struct obj *) 0); } - mtmp = mtmp2; + } } } @@ -329,6 +338,7 @@ do_pit: chasm = maketrap(x,y,PIT); if (*in_rooms(x, y, SHOPBASE)) add_damage(x, y, 0L); levl[x][y].doormask = D_NODOOR; + unblock_point(x,y); newsym(x,y); break; } @@ -383,8 +393,7 @@ struct obj *instr; } /* else FALLTHRU */ case WOODEN_FLUTE: /* May charm snakes */ do_spec &= (rn2(ACURR(A_DEX)) + u.ulevel > 25); - pline("%s %s.", The(xname(instr)), - do_spec ? "trills" : "toots"); + pline("%s.", Tobjnam(instr, do_spec ? "trill" : "toot")); if (do_spec) charm_snakes(u.ulevel * 3); exercise(A_DEX, TRUE); break; @@ -394,14 +403,14 @@ struct obj *instr; check_unpaid(instr); instr->spe--; if (!getdir((char *)0)) { - pline("%s vibrates.", The(xname(instr))); + pline("%s.", Tobjnam(instr, "vibrate")); break; } else if (!u.dx && !u.dy && !u.dz) { - if ((damage = zapyourself(instr, TRUE)) != 0) - losehp(damage, - self_pronoun("using a magical horn on %sself", - "him"), - NO_KILLER_PREFIX); + if ((damage = zapyourself(instr, TRUE)) != 0) { + char buf[BUFSZ]; + Sprintf(buf, "using a magical horn on %sself", uhim()); + losehp(damage, buf, NO_KILLER_PREFIX); + } } else { buzz((instr->otyp == FROST_HORN) ? AD_COLD-1 : AD_FIRE-1, rn1(6,6), u.ux, u.uy, u.dx, u.dy); @@ -423,8 +432,7 @@ struct obj *instr; if (do_spec && instr->spe > 0) { check_unpaid(instr); instr->spe--; - pline("%s produces very attractive music.", - The(xname(instr))); + pline("%s very attractive music.", Tobjnam(instr, "produce")); charm_monsters((u.ulevel - 1) / 3 + 1); exercise(A_DEX, TRUE); break; diff --git a/src/o_init.c b/src/o_init.c index 4c5a0c4..bb93754 100644 --- a/src/o_init.c +++ b/src/o_init.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)o_init.c 3.3 1999/12/09 */ +/* SCCS Id: @(#)o_init.c 3.4 1999/12/09 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -75,9 +75,7 @@ shuffle(o_low, o_high, domaterial) { int i, j, num_to_shuffle; short sw; -#ifdef TEXTCOLOR int color; -#endif /* TEXTCOLOR */ for (num_to_shuffle = 0, j=o_low; j <= o_high; j++) if (!objects[j].oc_name_known) num_to_shuffle++; @@ -94,11 +92,10 @@ shuffle(o_low, o_high, domaterial) sw = objects[j].oc_tough; objects[j].oc_tough = objects[i].oc_tough; objects[i].oc_tough = sw; -#ifdef TEXTCOLOR color = objects[j].oc_color; objects[j].oc_color = objects[i].oc_color; objects[i].oc_color = color; -#endif /* TEXTCOLOR */ + /* shuffle material */ if (domaterial) { sw = objects[j].oc_material; diff --git a/src/objects.c b/src/objects.c index cf68a05..845e5a2 100644 --- a/src/objects.c +++ b/src/objects.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)objects.c 3.3 2000/02/18 */ +/* SCCS Id: @(#)objects.c 3.4 2002/02/13 */ /* Copyright (c) Mike Threepoint, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -13,12 +13,8 @@ struct monst { struct monst *dummy; }; /* lint: struct obj's union */ #else /* !OBJECTS_PASS_2_ */ /* second pass */ -# ifdef TEXTCOLOR #include "color.h" # define COLOR_FIELD(X) X, -# else -# define COLOR_FIELD(X) /*empty*/ -# endif #endif /* !OBJECTS_PASS_2_ */ @@ -135,7 +131,7 @@ WEAPON("silver dagger", (char *)0, WEAPON("athame", (char *)0, 1, 1, 0, 0, 10, 4, 4, 3, 2, S, P_DAGGER, IRON, HI_METAL), WEAPON("scalpel", (char *)0, - 1, 1, 0, 0, 5, 4, 3, 3, 2, S, P_KNIFE, IRON, HI_METAL), + 1, 1, 0, 0, 5, 6, 3, 3, 2, S, P_KNIFE, METAL, HI_METAL), WEAPON("knife", (char *)0, 1, 1, 0, 20, 5, 4, 3, 2, 0, P|S, P_KNIFE, IRON, HI_METAL), WEAPON("stiletto", (char *)0, @@ -263,7 +259,7 @@ BOW("bow", (char *)0, 1, 24, 30, 60, 0, WOOD, P_BOW, HI_WOOD), BOW("elven bow", "runed bow", 0, 12, 30, 60, 0, WOOD, P_BOW, HI_WOOD), BOW("orcish bow", "crude bow", 0, 12, 30, 60, 0, WOOD, P_BOW, CLR_BLACK), BOW("yumi", "long bow", 0, 0, 30, 60, 0, WOOD, P_BOW, HI_WOOD), -BOW("sling", (char *)0, 1, 40, 3, 20, 0, WOOD, P_SLING, HI_WOOD), +BOW("sling", (char *)0, 1, 40, 3, 20, 0, LEATHER, P_SLING, HI_LEATHER), BOW("crossbow", (char *)0, 1, 45, 50, 40, 0, WOOD, P_CROSSBOW, HI_WOOD), #undef P @@ -410,32 +406,34 @@ ARMOR("T-shirt", (char *)0, CLOAK("mummy wrapping", (char *)0, 1, 0, 0, 0, 0, 3, 2, 10, 1, CLOTH, CLR_GRAY), CLOAK("elven cloak", "faded pall", - 0, 1, STEALTH, 10, 0, 10, 60, 9, 3, CLOTH, CLR_BLACK), + 0, 1, STEALTH, 8, 0, 10, 60, 9, 3, CLOTH, CLR_BLACK), CLOAK("orcish cloak", "coarse mantelet", - 0, 0, 0, 10, 0, 10, 40, 10, 2, CLOTH, CLR_BLACK), + 0, 0, 0, 8, 0, 10, 40, 10, 2, CLOTH, CLR_BLACK), CLOAK("dwarvish cloak", "hooded cloak", - 0, 0, 0, 10, 0, 10, 50, 10, 2, CLOTH, HI_CLOTH), + 0, 0, 0, 8, 0, 10, 50, 10, 2, CLOTH, HI_CLOTH), CLOAK("oilskin cloak", "slippery cloak", - 0, 0, 0, 10, 0, 10, 50, 9, 3, CLOTH, HI_CLOTH), + 0, 0, 0, 8, 0, 10, 50, 9, 3, CLOTH, HI_CLOTH), CLOAK("robe", (char *)0, - 1, 1, 0, 0, 0, 15, 50, 8, 3, CLOTH, CLR_RED), + 1, 1, 0, 3, 0, 15, 50, 8, 3, CLOTH, CLR_RED), CLOAK("alchemy smock", "apron", 0, 1, POISON_RES, 9, 0, 10, 50, 9, 1, CLOTH, CLR_WHITE), +CLOAK("leather cloak", (char *)0, + 1, 0, 0, 8, 0, 15, 40, 9, 1, LEATHER, CLR_BROWN), /* With shuffled appearances... */ CLOAK("cloak of protection", "tattered cape", - 0, 1, PROTECTION,10, 0, 10, 50, 7, 3, CLOTH, HI_CLOTH), + 0, 1, PROTECTION, 9, 0, 10, 50, 7, 3, CLOTH, HI_CLOTH), CLOAK("cloak of invisibility", "opera cloak", - 0, 1, INVIS, 11, 0, 10, 60, 9, 2, CLOTH, CLR_BRIGHT_MAGENTA), + 0, 1, INVIS, 10, 0, 10, 60, 9, 2, CLOTH, CLR_BRIGHT_MAGENTA), CLOAK("cloak of magic resistance", "ornamental cope", 0, 1, ANTIMAGIC, 2, 0, 10, 60, 9, 3, CLOTH, CLR_WHITE), CLOAK("cloak of displacement", "piece of cloth", - 0, 1, DISPLACED, 11, 0, 10, 50, 9, 2, CLOTH, HI_CLOTH), + 0, 1, DISPLACED, 10, 0, 10, 50, 9, 2, CLOTH, HI_CLOTH), /* shields */ SHIELD("small shield", (char *)0, 1, 0, 0, 0, 6, 0, 30, 3, 9, 0, WOOD, HI_WOOD), SHIELD("elven shield", "blue and green shield", - 0, 0, 0, 0, 2, 0, 50, 7, 8, 0, IRON, CLR_GREEN), + 0, 0, 0, 0, 2, 0, 40, 7, 8, 0, WOOD, CLR_GREEN), SHIELD("Uruk-hai shield", "white-handed shield", 0, 0, 0, 0, 2, 0, 50, 7, 9, 0, IRON, HI_METAL), SHIELD("orcish shield", "red-eyed shield", @@ -555,7 +553,7 @@ OBJECT(OBJ("cheap plastic imitation of the Amulet of Yendor", AMULET_CLASS, 0, 0, 20, 0, 0, 0, 0, 0, 1, HI_METAL), OBJECT(OBJ("Amulet of Yendor", /* note: description == name */ "Amulet of Yendor"), BITS(0,0,1,0,1,0,1,1,0,0,0,0,MITHRIL), 0, - AMULET_CLASS, 0, 0, 20, 3500, 0, 0, 0, 0, 20, HI_METAL), + AMULET_CLASS, 0, 0, 20, 30000, 0, 0, 0, 0, 20, HI_METAL), #undef AMULET /* tools ... */ @@ -655,10 +653,10 @@ WEPTOOL("unicorn horn", (char *)0, /* two special unique artifact "tools" */ OBJECT(OBJ("Candelabrum of Invocation", "candelabrum"), BITS(0,0,1,0,1,0,1,1,0,0,0,P_NONE,GOLD), 0, - TOOL_CLASS, 0, 0,10, 3000, 0, 0, 0, 0, 200, HI_GOLD), + TOOL_CLASS, 0, 0,10, 5000, 0, 0, 0, 0, 200, HI_GOLD), OBJECT(OBJ("Bell of Opening", "silver bell"), BITS(0,0,1,0,1,1,1,1,0,0,0,P_NONE,SILVER), 0, - TOOL_CLASS, 0, 0,10, 1000, 0, 0, 0, 0, 50, HI_SILVER), + TOOL_CLASS, 0, 0,10, 5000, 0, 0, 0, 0, 50, HI_SILVER), #undef TOOL #undef WEPTOOL @@ -837,7 +835,7 @@ SPELL("freeze sphere", "hardcover", P_MATTER_SPELL, 20, 2, 1, 1, NODIR, CLR SPELL("blank paper", "plain", P_NONE, 18, 0, 0, 0, 0, HI_PAPER), /* a special, one of a kind, spellbook */ OBJECT(OBJ("Book of the Dead", "papyrus"), BITS(0,0,1,0,1,0,1,1,0,0,0,P_NONE,PAPER), 0, - SPBOOK_CLASS, 0, 0,20, 3500, 0, 0, 0, 7, 20, HI_PAPER), + SPBOOK_CLASS, 0, 0,20, 10000, 0, 0, 0, 7, 20, HI_PAPER), #undef SPELL /* wands ... */ @@ -875,10 +873,10 @@ WAND((char *)0, "jeweled", 0, 150, 1, 0, IRON, HI_MINERAL), #undef WAND /* coins ... - so far, gold is all there is */ -#define COIN(name,prob,metal) OBJECT( \ +#define COIN(name,prob,metal,worth) OBJECT( \ OBJ(name,(char *)0), BITS(0,1,0,0,0,0,0,0,0,0,0,P_NONE,metal), 0, \ - GOLD_CLASS, prob, 0, 1, 0, 0, 0, 0, 0, 0, HI_GOLD ) - COIN("gold piece", 1000, GOLD), + GOLD_CLASS, prob, 0, 1, worth, 0, 0, 0, 0, 0, HI_GOLD ) + COIN("gold piece", 1000, GOLD,1), #undef COIN /* gems ... - includes stones and rocks but not boulders */ @@ -925,7 +923,8 @@ GEM("worthless piece of violet glass", "violet", 77, 1, 0, 6, 5, GLASS, CLR_MAGE ROCK("luckstone", "gray", 0, 10, 10, 60, 3, 3, 1, 10, 7, MINERAL, CLR_GRAY), ROCK("loadstone", "gray", 0, 10, 500, 1, 3, 3, 1, 10, 6, MINERAL, CLR_GRAY), -ROCK("flint", "gray", 0, 18, 10, 1, 6, 6, 0, 10, 7, MINERAL, CLR_GRAY), +ROCK("touchstone", "gray", 0, 8, 10, 45, 3, 3, 1, 10, 6, MINERAL, CLR_GRAY), +ROCK("flint", "gray", 0, 10, 10, 1, 6, 6, 0, 10, 7, MINERAL, CLR_GRAY), ROCK("rock", (char *)0, 1,100, 10, 0, 3, 3, 0, 10, 7, MINERAL, CLR_GRAY), #undef GEM #undef ROCK diff --git a/src/objnam.c b/src/objnam.c index 26c78ac..2050612 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)objnam.c 3.3 2000/07/23 */ +/* SCCS Id: @(#)objnam.c 3.4 2002/02/22 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -7,14 +7,14 @@ /* "an uncursed greased partly eaten guardian naga hatchling [corpse]" */ #define PREFIX 80 /* (56) */ #define SCHAR_LIM 127 +#define NUMOBUF 12 STATIC_DCL char *FDECL(strprepend,(char *,const char *)); -#ifdef OVL0 -static boolean FDECL(the_unique_obj, (struct obj *obj)); -#endif #ifdef OVLB static boolean FDECL(wishymatch, (const char *,const char *,BOOLEAN_P)); #endif +static char *NDECL(nextobuf); +static void FDECL(add_erosion_words, (struct obj *, char *)); struct Jitem { int item; @@ -47,7 +47,6 @@ STATIC_OVL struct Jitem Japanese_items[] = { { HELMET, "kabuto" }, { LEATHER_GLOVES, "yugake" }, { FOOD_RATION, "gunyoki" }, - { KELP_FROND, "nori" }, { POT_BOOZE, "sake" }, {0, "" } }; @@ -77,22 +76,28 @@ register const char *pref; #endif /* OVL1 */ #ifdef OVLB +/* manage a pool of BUFSZ buffers, so callers don't have to */ +static char * +nextobuf() +{ + static char NEARDATA bufs[NUMOBUF][BUFSZ]; + static int bufidx = 0; + + bufidx = (bufidx + 1) % NUMOBUF; + return bufs[bufidx]; +} + char * obj_typename(otyp) register int otyp; { -#ifdef LINT /* static char buf[BUFSZ]; */ - char buf[BUFSZ]; -#else - static char NEARDATA buf[BUFSZ]; -#endif + char *buf = nextobuf(); register struct objclass *ocl = &objects[otyp]; register const char *actualn = OBJ_NAME(*ocl); register const char *dn = OBJ_DESCR(*ocl); register const char *un = ocl->oc_uname; register int nn = ocl->oc_name_known; - if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp)) actualn = Japanese_item_name(otyp); switch(ocl->oc_class) { @@ -144,8 +149,12 @@ register int otyp; return(buf); } /* here for ring/scroll/potion/wand */ - if(nn) + if(nn) { + if (ocl->oc_unique) + Strcpy(buf, actualn); /* avoid spellbook of Book of the Dead */ + else Sprintf(eos(buf), " of %s", actualn); + } if(un) Sprintf(eos(buf), " called %s", un); if(dn) @@ -207,12 +216,7 @@ char * xname(obj) register struct obj *obj; { -#ifdef LINT /* lint may handle static decl poorly -- static char bufr[]; */ - char bufr[BUFSZ]; -#else - static char bufr[BUFSZ]; -#endif - register char *buf = &(bufr[PREFIX]); /* leave room for "17 -3 " */ + register char *buf; register int typ = obj->otyp; register struct objclass *ocl = &objects[typ]; register int nn = ocl->oc_name_known; @@ -220,10 +224,19 @@ register struct obj *obj; register const char *dn = OBJ_DESCR(*ocl); register const char *un = ocl->oc_uname; + buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */ if (Role_if(PM_SAMURAI) && Japanese_item_name(typ)) actualn = Japanese_item_name(typ); buf[0] = '\0'; + /* + * clean up known when it's tied to oc_name_known, eg after AD_DRIN + * This is only required for unique objects and the Fake AoY since the + * article printed for the object is tied to the combination of the two + * and printing the wrong article gives away information. + */ + if (!nn && ocl->oc_uses_known && + (ocl->oc_unique || typ == FAKE_AMULET_OF_YENDOR)) obj->known = 0; if (!Blind) obj->dknown = TRUE; if (Role_if(PM_PRIEST)) obj->bknown = TRUE; if (obj_is_pname(obj)) @@ -451,11 +464,30 @@ register struct obj *obj; return(buf); } +/* xname() output augmented for multishot missile feedback */ +char * +mshot_xname(obj) +struct obj *obj; +{ + char tmpbuf[BUFSZ]; + char *onm = xname(obj); + + if (m_shot.n > 1 && m_shot.o == obj->otyp) { + /* copy xname's result so that we can reuse its return buffer */ + Strcpy(tmpbuf, onm); + /* "the Nth arrow"; value will eventually be passed to an() or + The(), both of which correctly handle this "the " prefix */ + Sprintf(onm, "the %d%s %s", m_shot.i, ordin(m_shot.i), tmpbuf); + } + + return onm; +} + #endif /* OVL1 */ #ifdef OVL0 /* used for naming "the unique_item" instead of "a unique_item" */ -static boolean +boolean the_unique_obj(obj) register struct obj *obj; { @@ -714,8 +746,19 @@ register struct obj *obj; Strcat(bp, " (alternate weapon; not wielded)"); } if(obj->owornmask & W_QUIVER) Strcat(bp, " (in quiver)"); - if(obj->unpaid) - Strcat(bp, " (unpaid)"); + if(obj->unpaid) { + xchar ox, oy; + long quotedprice = unpaid_cost(obj); + struct monst *shkp = (struct monst *)0; + + if (Has_contents(obj) && + get_obj_location(obj, &ox, &oy, BURIED_TOO|CONTAINED_TOO) && + costly_spot(ox, oy) && + (shkp = shop_keeper(*in_rooms(ox, oy, SHOPBASE)))) + quotedprice += contained_cost(obj, shkp, 0L, FALSE, TRUE); + Sprintf(eos(bp), " (unpaid, %ld %s)", + quotedprice, currency(quotedprice)); + } if (!strncmp(prefix, "a ", 2) && index(vowels, *(prefix+2) ? *(prefix+2) : *bp) && (*(prefix+2) || (strncmp(bp, "uranium", 7) @@ -765,17 +808,13 @@ register struct obj *otmp; is_flammable(otmp)); } -/* The result is actually modifiable, but caller shouldn't rely on that - * due to the small buffer size. - */ -const char * +char * corpse_xname(otmp, ignore_oquan) struct obj *otmp; boolean ignore_oquan; /* to force singular */ { - static char NEARDATA nambuf[40]; + char *nambuf = nextobuf(); - /* assert( strlen(mons[otmp->corpsenm].mname) <= 32 ); */ Sprintf(nambuf, "%s corpse", mons[otmp->corpsenm].mname); if (ignore_oquan || otmp->quan < 2) @@ -784,6 +823,16 @@ boolean ignore_oquan; /* to force singular */ return makeplural(nambuf); } +/* xname, unless it's a corpse, then corpse_xname(obj, FALSE) */ +char * +cxname(obj) +struct obj *obj; +{ + if (obj->otyp == CORPSE) + return corpse_xname(obj, FALSE); + return xname(obj); +} + /* * Used if only one of a collection of objects is named (e.g. in eat.c). */ @@ -810,7 +859,7 @@ char * an(str) register const char *str; { - static char NEARDATA buf[BUFSZ]; + char *buf = nextobuf(); buf[0] = '\0'; @@ -849,7 +898,7 @@ char * the(str) const char *str; { - static char NEARDATA buf[BUFSZ]; + char *buf = nextobuf(); boolean insert_the = FALSE; if (!strncmpi(str, "the ", 4)) { @@ -901,12 +950,13 @@ const char *str; return tmp; } +/* returns "count cxname(otmp)" or just cxname(otmp) if count == 1 */ char * aobjnam(otmp,verb) register struct obj *otmp; register const char *verb; { - register char *bp = xname(otmp); + register char *bp = cxname(otmp); char prefix[PREFIX]; if(otmp->quan != 1L) { @@ -915,20 +965,122 @@ register const char *verb; } if(verb) { - /* verb is given in plural (without trailing s) */ - Strcat(bp, " "); - if(otmp->quan != 1L) - Strcat(bp, verb); - else if(!strcmp(verb, "are")) - Strcat(bp, "is"); - else { - Strcat(bp, verb); - Strcat(bp, "s"); - } + Strcat(bp, " "); + Strcat(bp, otense(otmp, verb)); + } + return(bp); +} + +/* like aobjnam, but prepend "The", not count, and use xname */ +char * +Tobjnam(otmp, verb) +register struct obj *otmp; +register const char *verb; +{ + char *bp = The(xname(otmp)); + + if(verb) { + Strcat(bp, " "); + Strcat(bp, otense(otmp, verb)); } return(bp); } +/* return form of the verb (input plural) if xname(otmp) were the subject */ +char * +otense(otmp, verb) +register struct obj *otmp; +register const char *verb; +{ + char *buf; + + /* + * verb is given in plural (without trailing s). Return as input + * if the result of xname(otmp) would be plural. Don't bother + * recomputing xname(otmp) at this time. + */ + if (!is_plural(otmp)) + return vtense((char *)0, verb); + + buf = nextobuf(); + Strcpy(buf, verb); + return buf; +} + +/* return form of the verb (input plural) for present tense 3rd person subj */ +char * +vtense(subj, verb) +register const char *subj; +register const char *verb; +{ + char *buf = nextobuf(); + int len; + const char *spot; + const char *sp; + + /* + * verb is given in plural (without trailing s). Return as input + * if subj appears to be plural. Add special cases as necessary. + * Many hard cases can already be handled by using otense() instead. + * If this gets much bigger, consider decomposing makeplural. + * Note: monster names are not expected here (except before corpse). + * + * special case: allow null sobj to get the singular 3rd person + * present tense form so we don't duplicate this code elsewhere. + */ + if (subj) { + spot = (const char *)0; + for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) { + if (!strncmp(sp, " of ", 4) || + !strncmp(sp, " called ", 8) || + !strncmp(sp, " named ", 7) || + !strncmp(sp, " labeled ", 9)) { + if (sp != subj) spot = sp - 1; + break; + } + } + len = strlen(subj); + if (!spot) spot = subj + len - 1; + + /* + * plural: anything that ends in 's', but not '*us'. + * Guess at a few other special cases that makeplural creates. + */ + if ((*spot == 's' && spot != subj && *(spot-1) != 'u') || + ((spot - subj) >= 4 && !strncmp(spot-3, "eeth", 4)) || + ((spot - subj) >= 3 && !strncmp(spot-3, "feet", 4)) || + ((spot - subj) >= 2 && !strncmp(spot-1, "ia", 2)) || + ((spot - subj) >= 2 && !strncmp(spot-1, "ae", 2))) { + Strcpy(buf, verb); + return buf; + } + } + + len = strlen(verb); + spot = verb + len - 1; + + if (!strcmp(verb, "are")) + Strcpy(buf, "is"); + else if (!strcmp(verb, "have")) + Strcpy(buf, "has"); + else if (index("zxs", *spot) || + (len >= 2 && *spot=='h' && index("cs", *(spot-1))) || + (len == 2 && *spot == 'o')) { + /* Ends in z, x, s, ch, sh; add an "es" */ + Strcpy(buf, verb); + Strcat(buf, "es"); + } else if (*spot == 'y' && (!index(vowels, *(spot-1)))) { + /* like "y" case in makeplural */ + Strcpy(buf, verb); + Strcpy(buf + len - 1, "ies"); + } else { + Strcpy(buf, verb); + Strcat(buf, "s"); + } + + return buf; +} + /* capitalized variant of doname() */ char * Doname2(obj) @@ -945,11 +1097,11 @@ char * yname(obj) struct obj *obj; { - static char outbuf[BUFSZ]; + char *outbuf = nextobuf(); char *s = shk_your(outbuf, obj); /* assert( s == outbuf ); */ - int space_left = sizeof outbuf - strlen(s) - sizeof " "; + int space_left = BUFSZ - strlen(s) - sizeof " "; - return strncat(strcat(s, " "), xname(obj), space_left); + return strncat(strcat(s, " "), cxname(obj), space_left); } /* capitalized variant of yname() */ @@ -995,7 +1147,7 @@ const char *oldstr; { /* Note: cannot use strcmpi here -- it'd give MATZot, CAVEMeN,... */ register char *spot; - static char NEARDATA str[BUFSZ]; + char *str = nextobuf(); const char *excess = (char *)0; int len; @@ -1008,14 +1160,11 @@ const char *oldstr; Strcpy(str, oldstr); /* - Skip changing "pair of" to "pairs of". According to Webster, usual - English usage is use pairs for humans, e.g. 3 pairs of dancers, - and pair for objects and non-humans, e.g. 3 pair of boots. We don't - refer to pairs of humans in this game so just skip to the bottom. - - Actually, none of the "pair" objects -- gloves, boots, and lenses -- - currently merge, so this isn't used. - */ + * Skip changing "pair of" to "pairs of". According to Webster, usual + * English usage is use pairs for humans, e.g. 3 pairs of dancers, + * and pair for objects and non-humans, e.g. 3 pair of boots. We don't + * refer to pairs of humans in this game so just skip to the bottom. + */ if (!strncmp(str, "pair of ", 8)) goto bottom; @@ -1059,12 +1208,12 @@ const char *oldstr; (len >= 3 && !strcmp(spot-2, " ya")) || (len >= 4 && (!strcmp(spot-3, "fish") || !strcmp(spot-3, "tuna") || - !strcmp(spot-3, "deer") || !strcmp(spot-3, "yaki") || - !strcmp(spot-3, "nori"))) || + !strcmp(spot-3, "deer") || !strcmp(spot-3, "yaki"))) || (len >= 5 && (!strcmp(spot-4, "sheep") || !strcmp(spot-4, "ninja") || !strcmp(spot-4, "ronin") || !strcmp(spot-4, "shito") || + !strcmp(spot-7, "shuriken") || !strcmp(spot-4, "tengu") || !strcmp(spot-4, "manes"))) || (len >= 6 && !strcmp(spot-5, "ki-rin")) || @@ -1120,8 +1269,10 @@ const char *oldstr; goto bottom; } - /* fungus/fungi, homunculus/homunculi, but wumpuses */ - if (!strcmp(spot-1, "us") && (len < 6 || strcmp(spot-5, "wumpus"))) { + /* fungus/fungi, homunculus/homunculi, but buses, lotuses, wumpuses */ + if (len > 3 && !strcmp(spot-1, "us") && + (len < 5 || (strcmp(spot-4, "lotus") && + (len < 6 || strcmp(spot-5, "wumpus"))))) { *(spot--) = (char)0; *spot = 'i'; goto bottom; @@ -1258,13 +1409,12 @@ STATIC_OVL NEARDATA const struct o_range o_ranges[] = { * of readobjnam, and is also used in pager.c to singularize the string * for which help is sought. */ - char * makesingular(oldstr) const char *oldstr; { register char *p, *bp; - static char NEARDATA str[BUFSZ]; + char *str = nextobuf(); if (!oldstr || !*oldstr) { impossible("singular of null?"); @@ -1442,13 +1592,19 @@ struct alt_spellings { { (const char *)0, 0 }, }; -/* Return something wished for. If not an object, return &zeroobj; if an error - * (no matching object), return (struct obj *)0. Giving readobjnam() a null - * pointer skips the error return and creates a random object instead. +/* + * Return something wished for. Specifying a null pointer for + * the user request string results in a random object. Otherwise, + * if asking explicitly for "nothing" (or "nil") return no_wish; + * if not an object return &zeroobj; if an error (no matching object), + * return null. + * If from_user is false, we're reading from the wizkit, nothing was typed in. */ struct obj * -readobjnam(bp) +readobjnam(bp, no_wish, from_user) register char *bp; +struct obj *no_wish; +boolean from_user; { register char *p; register int i; @@ -1501,6 +1657,10 @@ register char *bp; if (!bp) goto any; /* first, remove extra whitespace they may have typed */ (void)mungspaces(bp); + /* allow wishing for "nothing" to preserve wishless conduct... + [now requires "wand of nothing" if that's what was really wanted] */ + if (!strcmpi(bp, "nothing") || !strcmpi(bp, "nil")) return no_wish; + /* save the [nearly] unmodified choice string */ Strcpy(fruitbuf, bp); for(;;) { @@ -1517,6 +1677,12 @@ register char *bp; while(digit(*bp)) bp++; while(*bp == ' ') bp++; l = 0; + } else if (*bp == '+' || *bp == '-') { + spesgn = (*bp++ == '+') ? 1 : -1; + spe = atoi(bp); + while(digit(*bp)) bp++; + while(*bp == ' ') bp++; + l = 0; } else if (!strncmpi(bp, "blessed ", l=8) || !strncmpi(bp, "holy ", l=5)) { blessed = 1; @@ -1576,21 +1742,14 @@ register char *bp; ishistoric = 1; } else if (!strncmpi(bp, "diluted ", l=8)) { isdiluted = 1; + } else if(!strncmpi(bp, "empty ", l=6)) { + contents = EMPTY; } else break; bp += l; } if(!cnt) cnt = 1; /* %% what with "gems" etc. ? */ - if(!strncmpi(bp, "empty ", 6)) { - contents = EMPTY; - bp += 6; - } if (strlen(bp) > 1) { - if (*bp == '+' || *bp == '-') { - spesgn = (*bp++ == '+') ? 1 : -1; - spe = atoi(bp); - while(digit(*bp)) bp++; - while(*bp == ' ') bp++; - } else if ((p = rindex(bp, '(')) != 0) { + if ((p = rindex(bp, '(')) != 0) { if (p > bp && p[-1] == ' ') p[-1] = 0; else *p = 0; p++; @@ -1712,7 +1871,7 @@ register char *bp; int mntmptoo, mntmplen; /* double check for rank title */ char *obp = bp; mntmptoo = title_to_mon(bp, (int *)0, &mntmplen); - bp += mntmp != mntmptoo ? strlen(mons[mntmp].mname) : mntmplen; + bp += mntmp != mntmptoo ? (int)strlen(mons[mntmp].mname) : mntmplen; if (*bp == ' ') bp++; else if (!strncmpi(bp, "s ", 2)) bp += 2; else if (!strncmpi(bp, "es ", 3)) bp += 3; @@ -1784,10 +1943,19 @@ register char *bp; #endif ) cnt=5000; if (cnt < 1) cnt=1; - pline("%d gold piece%s.", cnt, plur(cnt)); +#ifndef GOLDOBJ + if (from_user) + pline("%d gold piece%s.", cnt, plur(cnt)); u.ugold += cnt; flags.botl=1; return (&zeroobj); +#else + otmp = mksobj(GOLD_PIECE, FALSE, FALSE); + otmp->quan = cnt; + otmp->owt = weight(otmp); + flags.botl=1; + return (otmp); +#endif } if (strlen(bp) == 1 && (i = def_char_to_objclass(*bp)) < MAXOCLASSES && i > ILLOBJ_CLASS @@ -1983,7 +2151,7 @@ register char *bp; /* must come after objects check so wizards can still wish for * trap objects like beartraps */ - if (wizard) { + if (wizard && from_user) { int trap; for (trap = NO_TRAP+1; trap < TRAPNUM; trap++) { @@ -2075,6 +2243,7 @@ register char *bp; levl[u.ux][u.uy].typ = TREE; pline("A tree."); newsym(u.ux, u.uy); + block_point(u.ux, u.uy); return &zeroobj; } @@ -2101,7 +2270,7 @@ register char *bp; #endif switch (typ) { case AMULET_OF_YENDOR: - typ = FAKE_AMULET_OF_YENDOR; + typ = FAKE_AMULET_OF_YENDOR; break; case CANDELABRUM_OF_INVOCATION: typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE); @@ -2215,7 +2384,10 @@ register char *bp; } /* set otmp->corpsenm or dragon scale [mail] */ - if (mntmp >= LOW_PM) switch(typ) { + if (mntmp >= LOW_PM) { + if (mntmp == PM_LONG_WORM_TAIL) mntmp = PM_LONG_WORM; + + switch (typ) { case TIN: otmp->spe = 0; /* No spinach */ if (dead_species(mntmp, FALSE)) { @@ -2268,6 +2440,7 @@ register char *bp; otmp->otyp = GRAY_DRAGON_SCALE_MAIL + mntmp - PM_GRAY_DRAGON; break; + } } /* set blessed/cursed -- setting the fields directly is safe @@ -2371,23 +2544,21 @@ register char *bp; artifact_exists(otmp, ONAME(otmp), FALSE); obfree(otmp, (struct obj *) 0); otmp = &zeroobj; - pline( - "For a moment, you feel %s in your %s, but it disappears!", + pline("For a moment, you feel %s in your %s, but it disappears!", something, makeplural(body_part(HAND))); } - otmp->owt = weight(otmp); - if (very && otmp->otyp == HEAVY_IRON_BALL) otmp->owt += 160; if (halfeaten && otmp->oclass == FOOD_CLASS) { if (otmp->otyp == CORPSE) otmp->oeaten = mons[otmp->corpsenm].cnutrit; else otmp->oeaten = objects[otmp->otyp].oc_nutrition; - otmp->owt /= 2; - otmp->oeaten /= 2; - if (!otmp->owt) otmp->owt = 1; - if (!otmp->oeaten) otmp->oeaten = 1; + /* (do this adjustment before setting up object's weight) */ + consume_oeaten(otmp, 1); } + otmp->owt = weight(otmp); + if (very && otmp->otyp == HEAVY_IRON_BALL) otmp->owt += 160; + return(otmp); } @@ -2423,6 +2594,27 @@ int i; } return (const char *)0; } + +const char * +cloak_simple_name(cloak) +struct obj *cloak; +{ + if (cloak) { + switch (cloak->otyp) { + case ROBE: + return "robe"; + case MUMMY_WRAPPING: + return "wrapping"; + case ALCHEMY_SMOCK: + return (objects[cloak->otyp].oc_name_known && + cloak->dknown) ? "smock" : "apron"; + default: + break; + } + } + return "cloak"; +} + #endif /* OVLB */ /*objnam.c*/ diff --git a/src/options.c b/src/options.c index f9dce68..a63de72 100644 --- a/src/options.c +++ b/src/options.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)options.c 3.3 2000/08/01 */ +/* SCCS Id: @(#)options.c 3.4 2002/02/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -22,173 +22,172 @@ NEARDATA struct instance_flags iflags; /* provide linkage */ * options help (option_help()), the long options help (dat/opthelp), * and the current options setting display function (doset()), * and also the Guidebooks. + * + * The order matters. If an option is a an initial substring of another + * option (e.g. time and timed_delay) the shorter one must come first. */ static struct Bool_Opt { const char *name; boolean *addr, initvalue; + int optflags; } boolopt[] = { #ifdef AMIGA - {"altmeta", &flags.altmeta, TRUE}, + {"altmeta", &flags.altmeta, TRUE, DISP_IN_GAME}, #else - {"altmeta", (boolean *)0, TRUE}, + {"altmeta", (boolean *)0, TRUE, DISP_IN_GAME}, #endif + {"ascii_map", &iflags.wc_ascii_map, TRUE, SET_IN_GAME}, /*WC*/ #ifdef MFLOPPY - {"asksavedisk", &flags.asksavedisk, FALSE}, + {"asksavedisk", &flags.asksavedisk, FALSE, SET_IN_GAME}, #else - {"asksavedisk", (boolean *)0, FALSE}, + {"asksavedisk", (boolean *)0, FALSE, SET_IN_FILE}, #endif - {"autopickup", &flags.pickup, TRUE}, - {"autoquiver", &flags.autoquiver, FALSE}, + {"autodig", &flags.autodig, FALSE, SET_IN_GAME}, + {"autopickup", &flags.pickup, TRUE, SET_IN_GAME}, + {"autoquiver", &flags.autoquiver, FALSE, SET_IN_GAME}, #if defined(MICRO) && !defined(AMIGA) - {"BIOS", &iflags.BIOS, FALSE}, + {"BIOS", &iflags.BIOS, FALSE, SET_IN_FILE}, #else - {"BIOS", (boolean *)0, FALSE}, + {"BIOS", (boolean *)0, FALSE, SET_IN_FILE}, #endif #ifdef INSURANCE - {"checkpoint", &flags.ins_chkpt, TRUE}, + {"checkpoint", &flags.ins_chkpt, TRUE, SET_IN_GAME}, #else - {"checkpoint", (boolean *)0, FALSE}, + {"checkpoint", (boolean *)0, FALSE, SET_IN_FILE}, #endif #ifdef MFLOPPY - {"checkspace", &iflags.checkspace, TRUE}, + {"checkspace", &iflags.checkspace, TRUE, SET_IN_GAME}, #else - {"checkspace", (boolean *)0, FALSE}, + {"checkspace", (boolean *)0, FALSE, SET_IN_FILE}, #endif -#ifdef TEXTCOLOR # ifdef MICRO - {"color", &iflags.use_color, TRUE}, + {"color", &iflags.wc_color,TRUE, SET_IN_GAME}, /*WC*/ # else /* systems that support multiple terminals, many monochrome */ - {"color", &iflags.use_color, FALSE}, + {"color", &iflags.wc_color, FALSE, SET_IN_GAME}, /*WC*/ # endif + {"confirm",&flags.confirm, TRUE, SET_IN_GAME}, +#if defined(TERMLIB) && !defined(MAC_GRAPHICS_ENV) + {"DECgraphics", &iflags.DECgraphics, FALSE, SET_IN_GAME}, #else - {"color", (boolean *)0, FALSE}, -#endif - {"confirm",&flags.confirm, TRUE}, -#ifdef TERMLIB - {"DECgraphics", &iflags.DECgraphics, FALSE}, -#else - {"DECgraphics", (boolean *)0, FALSE}, + {"DECgraphics", (boolean *)0, FALSE, SET_IN_FILE}, #endif + {"eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, SET_IN_GAME}, /*WC*/ #ifdef TTY_GRAPHICS - {"eight_bit_tty", &iflags.eight_bit_tty, FALSE}, - {"extmenu", &iflags.extmenu, FALSE}, + {"extmenu", &iflags.extmenu, FALSE, SET_IN_GAME}, #else - {"eight_bit_tty", (boolean *)0, FALSE}, - {"extmenu", (boolean *)0, FALSE}, + {"extmenu", (boolean *)0, FALSE, SET_IN_FILE}, #endif #ifdef OPT_DISPMAP - {"fast_map", &flags.fast_map, TRUE}, + {"fast_map", &flags.fast_map, TRUE, SET_IN_GAME}, #else - {"fast_map", (boolean *)0, TRUE}, + {"fast_map", (boolean *)0, TRUE, SET_IN_FILE}, #endif - {"female", &flags.female, FALSE}, - {"fixinv", &flags.invlet_constant, TRUE}, + {"female", &flags.female, FALSE, DISP_IN_GAME}, + {"fixinv", &flags.invlet_constant, TRUE, SET_IN_GAME}, #ifdef AMIFLUSH - {"flush", &flags.amiflush, FALSE}, + {"flush", &flags.amiflush, FALSE, SET_IN_GAME}, #else - {"flush", (boolean *)0, FALSE}, -#endif - {"help", &flags.help, TRUE}, -#ifdef TEXTCOLOR - {"hilite_pet", &iflags.hilite_pet, FALSE}, -#else - {"hilite_pet", (boolean *)0, FALSE}, + {"flush", (boolean *)0, FALSE, SET_IN_FILE}, #endif + {"help", &flags.help, TRUE, SET_IN_GAME}, + {"hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME}, /*WC*/ #ifdef ASCIIGRAPH - {"IBMgraphics", &iflags.IBMgraphics, FALSE}, + {"IBMgraphics", &iflags.IBMgraphics, FALSE, SET_IN_GAME}, #else - {"IBMgraphics", (boolean *)0, FALSE}, + {"IBMgraphics", (boolean *)0, FALSE, SET_IN_FILE}, #endif - {"ignintr", &flags.ignintr, FALSE}, -#ifdef MAC_GRAPHICS_ENV - {"large_font", &iflags.large_font, FALSE}, +#ifndef MAC + {"ignintr", &flags.ignintr, FALSE, SET_IN_GAME}, #else - {"large_font", (boolean *)0, FALSE}, + {"ignintr", (boolean *)0, FALSE, SET_IN_FILE}, #endif - {"legacy", &flags.legacy, TRUE}, - {"lit_corridor", &flags.lit_corridor, FALSE}, + {"large_font", &iflags.wc_large_font, FALSE, SET_IN_FILE}, /*WC*/ + {"legacy", &flags.legacy, TRUE, DISP_IN_GAME}, + {"lit_corridor", &flags.lit_corridor, FALSE, SET_IN_GAME}, #ifdef MAC_GRAPHICS_ENV - {"Macgraphics", &iflags.MACgraphics, TRUE}, + {"Macgraphics", &iflags.MACgraphics, TRUE, SET_IN_GAME}, #else - {"Macgraphics", (boolean *)0, FALSE}, + {"Macgraphics", (boolean *)0, FALSE, SET_IN_FILE}, #endif #ifdef MAIL - {"mail", &flags.biff, TRUE}, + {"mail", &flags.biff, TRUE, SET_IN_GAME}, #else - {"mail", (boolean *)0, TRUE}, + {"mail", (boolean *)0, TRUE, SET_IN_FILE}, #endif -#ifdef NEWS - {"news", &iflags.news, TRUE}, +#ifdef WIZARD + /* for menu debugging only*/ + {"menu_tab_sep", &iflags.menu_tab_sep, FALSE, SET_IN_GAME}, #else - {"news", (boolean *)0, FALSE}, + {"menu_tab_sep", (boolean *)0, FALSE, SET_IN_FILE}, #endif - {"null", &flags.null, TRUE}, - {"number_pad", &iflags.num_pad, FALSE}, -#ifdef MAC - {"page_wait", &flags.page_wait, TRUE}, +#ifdef TTY_GRAPHICS + {"msg_window", &iflags.prevmsg_window, FALSE, SET_IN_GAME}, #else - {"page_wait", (boolean *)0, FALSE}, + {"msg_window", (boolean *)0, FALSE, SET_IN_FILE}, #endif - {"perm_invent", &flags.perm_invent, FALSE}, -#ifdef MAC - {"popup_dialog", &iflags.popup_dialog, FALSE}, +#ifdef NEWS + {"news", &iflags.news, TRUE, DISP_IN_GAME}, #else - {"popup_dialog", (boolean *)0, FALSE}, + {"news", (boolean *)0, FALSE, SET_IN_FILE}, #endif - {"prayconfirm", &flags.prayconfirm, TRUE}, -#if defined(MSDOS) && defined(USE_TILES) - {"preload_tiles", &iflags.preload_tiles, TRUE}, + {"null", &flags.null, TRUE, SET_IN_GAME}, + {"number_pad", &iflags.num_pad, FALSE, SET_IN_GAME}, +#ifdef MAC + {"page_wait", &flags.page_wait, TRUE, SET_IN_GAME}, #else - {"preload_tiles", (boolean *)0, FALSE}, + {"page_wait", (boolean *)0, FALSE, SET_IN_FILE}, #endif - {"pushweapon", &flags.pushweapon, FALSE}, -#if defined(MICRO) && !defined(AMIGA) - {"rawio", &iflags.rawio, FALSE}, + {"perm_invent", &flags.perm_invent, FALSE, SET_IN_GAME}, + {"popup_dialog", &iflags.wc_popup_dialog, FALSE, SET_IN_GAME}, /*WC*/ + {"prayconfirm", &flags.prayconfirm, TRUE, SET_IN_GAME}, + {"preload_tiles", &iflags.wc_preload_tiles, TRUE, DISP_IN_GAME}, /*WC*/ + {"pushweapon", &flags.pushweapon, FALSE, SET_IN_GAME}, +#if defined(MICRO) && !defined(AMIGA) && !defined(MSWIN_GRAPHICS) + {"rawio", &iflags.rawio, FALSE, DISP_IN_GAME}, #else - {"rawio", (boolean *)0, FALSE}, + {"rawio", (boolean *)0, FALSE, SET_IN_FILE}, #endif - {"rest_on_space", &flags.rest_on_space, FALSE}, - {"safe_pet", &flags.safe_dog, TRUE}, + {"rest_on_space", &flags.rest_on_space, FALSE, SET_IN_GAME}, + {"safe_pet", &flags.safe_dog, TRUE, SET_IN_GAME}, #ifdef WIZARD - {"sanity_check", &iflags.sanity_check, FALSE}, + {"sanity_check", &iflags.sanity_check, FALSE, SET_IN_GAME}, #else - {"sanity_check", (boolean *)0, FALSE}, + {"sanity_check", (boolean *)0, FALSE, SET_IN_FILE}, #endif #ifdef EXP_ON_BOTL - {"showexp", &flags.showexp, FALSE}, + {"showexp", &flags.showexp, FALSE, SET_IN_GAME}, #else - {"showexp", (boolean *)0, FALSE}, + {"showexp", (boolean *)0, FALSE, SET_IN_FILE}, #endif #ifdef SCORE_ON_BOTL - {"showscore", &flags.showscore, FALSE}, + {"showscore", &flags.showscore, FALSE, SET_IN_GAME}, #else - {"showscore", (boolean *)0, FALSE}, + {"showscore", (boolean *)0, FALSE, SET_IN_FILE}, #endif - {"silent", &flags.silent, TRUE}, - {"sortpack", &flags.sortpack, TRUE}, - {"sound", &flags.soundok, TRUE}, - {"standout", &flags.standout, FALSE}, - {"time", &flags.time, FALSE}, + {"silent", &flags.silent, TRUE, SET_IN_GAME}, + {"sortpack", &flags.sortpack, TRUE, SET_IN_GAME}, + {"sound", &flags.soundok, TRUE, SET_IN_GAME}, + {"sparkle", &flags.sparkle, TRUE, SET_IN_GAME}, + {"standout", &flags.standout, FALSE, SET_IN_GAME}, + {"splash_screen", &iflags.wc_splash_screen, TRUE, DISP_IN_GAME}, /*WC*/ + {"tiled_map", &iflags.wc_tiled_map, FALSE, DISP_IN_GAME}, /*WC*/ + {"time", &flags.time, FALSE, SET_IN_GAME}, #ifdef TIMED_DELAY - {"timed_delay", &flags.nap, TRUE}, + {"timed_delay", &flags.nap, TRUE, SET_IN_GAME}, #else - {"timed_delay", (boolean *)0, FALSE}, + {"timed_delay", (boolean *)0, FALSE, SET_IN_GAME}, #endif - {"tombstone",&flags.tombstone, TRUE}, - {"toptenwin",&flags.toptenwin, FALSE}, - {"verbose", &flags.verbose, TRUE}, - {(char *)0, (boolean *)0, FALSE} + {"tombstone",&flags.tombstone, TRUE, SET_IN_GAME}, + {"toptenwin",&flags.toptenwin, FALSE, SET_IN_GAME}, + {"use_inverse", &iflags.wc_inverse, FALSE, SET_IN_GAME}, /*WC*/ + {"verbose", &flags.verbose, TRUE, SET_IN_GAME}, + {(char *)0, (boolean *)0, FALSE, 0} }; /* compound options, for option_help() and external programs like Amiga * frontend */ -#define SET_IN_FILE 0 /* config file option only, not visible in game - * or via program */ -#define SET_VIA_PROG 1 /* may be set via extern program, not seen in game */ -#define DISP_IN_GAME 2 /* may be set via extern program, displayed in game */ -#define SET_IN_GAME 3 /* may be set via extern program or set in the game */ static struct Comp_Opt { const char *name, *descr; @@ -201,14 +200,18 @@ static struct Comp_Opt } compopt[] = { { "align", "your starting alignment (lawful, neutral, or chaotic)", 8, DISP_IN_GAME }, + { "align_message", "message window alignment", 20, DISP_IN_GAME }, /*WC*/ + { "align_status", "status window alignment", 20, DISP_IN_GAME }, /*WC*/ #ifdef MAC { "background", "the color of the background (black or white)", 6, SET_IN_FILE }, #endif + { "boulder", "the symbol to use for displaying boulders", + 1, SET_IN_GAME }, { "catname", "the name of your (first) cat (e.g., catname:Tabby)", PL_PSIZ, DISP_IN_GAME }, { "disclose", "the kinds of information to disclose at end of game", - sizeof(flags.end_disclose), + sizeof(flags.end_disclose) * 2, SET_IN_GAME }, { "dogname", "the name of your (first) dog (e.g., dogname:Fang)", PL_PSIZ, DISP_IN_GAME }, @@ -216,18 +219,24 @@ static struct Comp_Opt MAXDCHARS+1, SET_IN_FILE }, { "effects", "the symbols to use in drawing special effects", MAXECHARS+1, SET_IN_FILE }, -#ifdef MAC - { "fontmap", "the font to use in the map window", 40, SET_IN_FILE }, - { "fontmessage", "the font to use in the message window", - 40, SET_IN_FILE }, - { "fonttext", "the font to use in text windows", 40, SET_IN_FILE }, -#endif + { "font_map", "the font to use in the map window", 40, DISP_IN_GAME }, /*WC*/ + { "font_menu", "the font to use in menus", 40, DISP_IN_GAME }, /*WC*/ + { "font_message", "the font to use in the message window", + 40, DISP_IN_GAME }, /*WC*/ + { "font_size_map", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/ + { "font_size_menu", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/ + { "font_size_message", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/ + { "font_size_status", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/ + { "font_size_text", "the size of the map font", 20, DISP_IN_GAME }, /*WC*/ + { "font_status", "the font to use in status window", 40, DISP_IN_GAME }, /*WC*/ + { "font_text", "the font to use in text windows", 40, DISP_IN_GAME }, /*WC*/ { "fruit", "the name of a fruit you enjoy eating", PL_FSIZ, SET_IN_GAME }, { "gender", "your starting gender (male or female)", 8, DISP_IN_GAME }, { "horsename", "the name of your (first) horse (e.g., horsename:Silver)", PL_PSIZ, DISP_IN_GAME }, + { "map_mode", "map display mode under Windows", 20, DISP_IN_GAME }, /*WC*/ { "menustyle", "user interface for object selection", MENUTYPELEN, SET_IN_GAME }, { "menu_deselect_all", "deselect all items in a menu", 4, SET_IN_FILE }, @@ -268,22 +277,29 @@ static struct Comp_Opt 20, SET_IN_GAME }, { "pickup_types", "types of objects to pick up automatically", MAXOCLASSES, SET_IN_GAME }, + { "player_selection", "choose character via dialog or prompts", + 12, DISP_IN_GAME }, { "race", "your starting race (e.g., Human, Elf)", PL_CSIZ, DISP_IN_GAME }, { "role", "your starting role (e.g., Barbarian, Valkyrie)", PL_CSIZ, DISP_IN_GAME }, { "scores", "the parts of the score list you wish to see", 32, SET_IN_GAME }, + { "scroll_margin", "scroll map when this far from the edge", 20, DISP_IN_GAME }, /*WC*/ #ifdef MSDOS { "soundcard", "type of sound card to use", 20, SET_IN_FILE }, #endif { "suppress_alert", "suppress alerts about version-specific features", 8, SET_IN_GAME }, + { "tile_width", "width of tiles", 20, DISP_IN_GAME}, /*WC*/ + { "tile_height", "height of tiles", 20, DISP_IN_GAME}, /*WC*/ + { "tile_file", "name of tile file", 70, DISP_IN_GAME}, /*WC*/ { "traps", "the symbols to use in drawing traps", MAXTCHARS+1, SET_IN_FILE }, #ifdef MAC {"use_stone", "use stone background patterns", 8, SET_IN_FILE }, #endif + { "vary_msgcount", "show more old messages at a time", 20, DISP_IN_GAME }, /*WC*/ #ifdef MSDOS { "video", "method of video updating", 20, SET_IN_FILE }, #endif @@ -293,11 +309,10 @@ static struct Comp_Opt { "videoshades", "gray shades to map to black/gray/white", 32, DISP_IN_GAME }, #endif -#if 0 - { "warnlevel", "minimum monster level to trigger warning", 4, SET_IN_GAME }, -#endif + { "windowcolors", "the foreground/background colors of windows", /*WC*/ + 80, DISP_IN_GAME }, { "windowtype", "windowing system to use", WINTYPELEN, DISP_IN_GAME }, - { (char *)0, (char *)0, 0 } + { (char *)0, (char *)0, 0, 0 } }; #ifdef OPTION_LISTS_ONLY @@ -383,7 +398,6 @@ static boolean initial, from_file; STATIC_DCL void FDECL(doset_add_menu, (winid,const char *,int)); STATIC_DCL void FDECL(nmcpy, (char *, const char *, int)); STATIC_DCL void FDECL(escapes, (const char *, char *)); -STATIC_DCL int FDECL(boolopt_only_initial, (int)); STATIC_DCL void FDECL(rejectoption, (const char *)); STATIC_DCL void FDECL(badoption, (const char *)); STATIC_DCL char *FDECL(string_for_opt, (char *,BOOLEAN_P)); @@ -396,9 +410,12 @@ STATIC_DCL int FDECL(feature_alert_opts, (char *, const char *)); STATIC_DCL const char *FDECL(get_compopt_value, (const char *, char *)); STATIC_DCL boolean FDECL(special_handling, (const char *, BOOLEAN_P, BOOLEAN_P)); STATIC_DCL void FDECL(warning_opts, (char *,const char *)); -#if 0 -STATIC_DCL int FDECL(warnlevel_opts, (char *, const char *)); -#endif +STATIC_DCL void FDECL(duplicate_opt_detection, (const char *, int)); + +STATIC_OVL void FDECL(wc_set_font_name, (int, char *)); +STATIC_OVL int FDECL(wc_set_window_colors, (char *)); +STATIC_OVL boolean FDECL(is_wc_option, (const char *)); +STATIC_OVL boolean FDECL(wc_supported, (const char *)); /* check whether a user-supplied option string is a proper leading substring of a particular option name; option string might have @@ -451,6 +468,9 @@ initoptions() /* initialize the random number generator */ setrandom(); + /* for detection of configfile options specified multiple times */ + iflags.opt_booldup = iflags.opt_compdup = (int *)0; + for (i = 0; boolopt[i].name; i++) { if (boolopt[i].addr) *(boolopt[i].addr) = boolopt[i].initvalue; @@ -474,6 +494,7 @@ initoptions() monsyms[i] = (uchar) def_monsyms[i]; for (i = 0; i < WARNCOUNT; i++) warnsyms[i] = def_warnsyms[i].sym; + iflags.bouldersym = 0; flags.warnlevel = 1; flags.warntype = 0L; @@ -483,6 +504,8 @@ initoptions() flags.pickup_types[0] = '\0'; flags.pickup_burden = MOD_ENCUMBER; + for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) + flags.end_disclose[i] = DISCLOSE_PROMPT_DEFAULT_NO; switch_graphics(ASCII_GRAPHICS); /* set default characters */ #if defined(UNIX) && defined(TTY_GRAPHICS) /* @@ -537,9 +560,7 @@ initoptions() } else #endif read_config_file((char *)0); -#ifdef AMIGA - ami_wbench_init(); /* must be here or can't set fruit */ -#endif + (void)fruitadd(pl_fruit); /* Remove "slime mold" from list of object names; this will */ /* prevent it from being wished unless it's actually present */ @@ -628,35 +649,12 @@ char *tp; *tp = '\0'; } -/* some boolean options can only be set on start-up */ -STATIC_OVL int -boolopt_only_initial(i) -int i; -{ - return (boolopt[i].addr == &flags.female - || boolopt[i].addr == &flags.legacy -#if defined(MICRO) && !defined(AMIGA) - || boolopt[i].addr == &iflags.rawio - || boolopt[i].addr == &iflags.BIOS -#endif -#if defined(MSDOS) && defined(USE_TILES) - || boolopt[i].addr == &iflags.preload_tiles -#endif - ); -} - STATIC_OVL void rejectoption(optname) const char *optname; { #ifdef MICRO -# ifdef AMIGA - if(FromWBench){ - pline("\"%s\" settable only from %s or in icon.", - optname, configfile); - } else -# endif - pline("\"%s\" settable only from %s.", optname, configfile); + pline("\"%s\" settable only from %s.", optname, configfile); #else pline("%s can be set only from NETHACKOPTIONS or %s.", optname, configfile); @@ -678,16 +676,11 @@ const char *opts; else return; #endif -# ifdef AMIGA - if(ami_wbench_badopt(opts)) { -# endif if(from_file) raw_printf("Bad syntax in OPTIONS in %s: %s.", configfile, opts); else raw_printf("Bad syntax in NETHACKOPTIONS: %s.", opts); -# ifdef AMIGA - } -# endif + wait_synch(); } @@ -749,8 +742,12 @@ char *op; char *sp, buf[BUFSZ]; num = 0; +#ifndef GOLDOBJ if (!index(op, GOLD_SYM)) buf[num++] = GOLD_CLASS; +#else + /* !!!! probably unnecessary with gold as normal inventory */ +#endif for (sp = op; *sp; sp++) { oc_sym = def_char_to_objclass(*sp); @@ -826,48 +823,6 @@ register uchar *graph_chars; warnsyms[i] = graph_chars[i]; } -#if 0 -/* warnlevel is unnecessary with the new warning introduced in 3.3.1 */ -STATIC_OVL int -warnlevel_opts(op, optn) -char *op; -const char *optn; -{ - char buf[BUFSZ]; - int twarnlevel; - boolean rejectlevel = FALSE; - - if (op) { - twarnlevel = atoi(op); - if (twarnlevel >= WARNCOUNT || twarnlevel < 1) - rejectlevel = TRUE; - else { - flags.warnlevel = twarnlevel; - see_monsters(); - } - } - if (rejectlevel) { - if (!initial) - pline("warnlevel must be 1 to %d.", WARNCOUNT - 1); - else { - Sprintf(buf, - "\n%s=%s Invalid warnlevel ignored (must be 1 to %d)", - optn, op, WARNCOUNT - 1); - badoption(buf); - } - return 0; - } - if (!initial) { - if (flags.warnlevel < WARNCOUNT -1) - Sprintf(buf, "s %d to %d", flags.warnlevel, WARNCOUNT - 1); - else - Sprintf(buf, " %d", flags.warnlevel); - pline("Warning level%s will be displayed.", buf); - } - return 1; -} -#endif - STATIC_OVL int feature_alert_opts(op, optn) char *op; @@ -901,6 +856,79 @@ const char *optn; return 1; } +void +set_duplicate_opt_detection(on_or_off) +int on_or_off; +{ + int k, *optptr; + if (on_or_off != 0) { + /*-- ON --*/ + if (iflags.opt_booldup) + impossible("iflags.opt_booldup already on (memory leak)"); + iflags.opt_booldup = (int *)alloc(SIZE(boolopt) * sizeof(int)); + optptr = iflags.opt_booldup; + for (k = 0; k < SIZE(boolopt); ++k) + *optptr++ = 0; + + if (iflags.opt_compdup) + impossible("iflags.opt_compdup already on (memory leak)"); + iflags.opt_compdup = (int *)alloc(SIZE(compopt) * sizeof(int)); + optptr = iflags.opt_compdup; + for (k = 0; k < SIZE(compopt); ++k) + *optptr++ = 0; + } else { + /*-- OFF --*/ + if (iflags.opt_booldup) free((genericptr_t) iflags.opt_booldup); + iflags.opt_booldup = (int *)0; + if (iflags.opt_compdup) free((genericptr_t) iflags.opt_compdup); + iflags.opt_compdup = (int *)0; + } +} + +STATIC_OVL void +duplicate_opt_detection(opts, bool_or_comp) +const char *opts; +int bool_or_comp; /* 0 == boolean option, 1 == compound */ +{ + int i, *optptr; +#if defined(MAC) + /* the Mac has trouble dealing with the output of messages while + * processing the config file. That should get fixed one day. + * For now just return. + */ + return; +#endif + if ((bool_or_comp == 0) && iflags.opt_booldup && initial && from_file) { + for (i = 0; boolopt[i].name; i++) { + if (match_optname(opts, boolopt[i].name, 3, FALSE)) { + optptr = iflags.opt_booldup + i; + if (*optptr == 1) { + raw_printf( + "\nWarning - Boolean option specified multiple times: %s.\n", + opts); + wait_synch(); + } + *optptr += 1; + break; /* don't match multiple options */ + } + } + } else if ((bool_or_comp == 1) && iflags.opt_compdup && initial && from_file) { + for (i = 0; compopt[i].name; i++) { + if (match_optname(opts, compopt[i].name, strlen(compopt[i].name), TRUE)) { + optptr = iflags.opt_compdup + i; + if (*optptr == 1) { + raw_printf( + "\nWarning - compound option specified multiple times: %s.\n", + compopt[i].name); + wait_synch(); + } + *optptr += 1; + break; /* don't match multiple options */ + } + } + } +} + void parseoptions(opts, tinitial, tfrom_file) register char *opts; @@ -940,6 +968,8 @@ boolean tinitial, tfrom_file; if (match_optname(opts, "colour", 5, FALSE)) Strcpy(opts, "color"); /* fortunately this isn't longer */ + duplicate_opt_detection(opts, 1); /* 1 means compound opts */ + /* special boolean options */ if (match_optname(opts, "female", 3, FALSE)) { @@ -983,11 +1013,15 @@ boolean tinitial, tfrom_file; case 'F': preferred_pet = 'c'; break; + case 'n': /* no pet */ + case 'N': + preferred_pet = 'n'; + break; default: pline("Unrecognized pet type '%s'", op); break; } - } else if (negated) preferred_pet = 0; + } else if (negated) preferred_pet = 'n'; return; } @@ -1024,6 +1058,78 @@ boolean tinitial, tfrom_file; return; } + /* WINCAP + * setting font options */ + fullname = "font"; + if (!strncmpi(opts, fullname, 4)) + { + int wintype = -1; + char *fontopts = opts + 4; + + if (!strncmpi(fontopts, "map", 3) || + !strncmpi(fontopts, "_map", 4)) + wintype = NHW_MAP; + else if (!strncmpi(fontopts, "message", 7) || + !strncmpi(fontopts, "_message", 8)) + wintype = NHW_MESSAGE; + else if (!strncmpi(fontopts, "text", 4) || + !strncmpi(fontopts, "_text", 5)) + wintype = NHW_TEXT; + else if (!strncmpi(fontopts, "menu", 4) || + !strncmpi(fontopts, "_menu", 5)) + wintype = NHW_MENU; + else if (!strncmpi(fontopts, "status", 6) || + !strncmpi(fontopts, "_status", 7)) + wintype = NHW_STATUS; + else if (!strncmpi(fontopts, "_size", 5)) { + if (!strncmpi(fontopts, "_size_map", 8)) + wintype = NHW_MAP; + else if (!strncmpi(fontopts, "_size_message", 12)) + wintype = NHW_MESSAGE; + else if (!strncmpi(fontopts, "_size_text", 9)) + wintype = NHW_TEXT; + else if (!strncmpi(fontopts, "_size_menu", 9)) + wintype = NHW_MENU; + else if (!strncmpi(fontopts, "_size_status", 11)) + wintype = NHW_STATUS; + else { + badoption(opts); + return; + } + if (wintype > 0 && !negated && + (op = string_for_opt(opts, FALSE)) != 0) { + switch(wintype) { + case NHW_MAP: + iflags.wc_fontsiz_map = atoi(op); + break; + case NHW_MESSAGE: + iflags.wc_fontsiz_message = atoi(op); + break; + case NHW_TEXT: + iflags.wc_fontsiz_text = atoi(op); + break; + case NHW_MENU: + iflags.wc_fontsiz_menu = atoi(op); + break; + case NHW_STATUS: + iflags.wc_fontsiz_status = atoi(op); + break; + } + } + return; + } else { + badoption(opts); + } + if (wintype > 0 && + (op = string_for_opt(opts, FALSE)) != 0) { + wc_set_font_name(wintype, op); +#ifdef MAC + set_font_name (wintype, op); +#endif + return; + } else if (negated) bad_negation(fullname, TRUE); + return; + } #ifdef CHANGE_COLOR #ifdef MAC fullname = "use_stone"; @@ -1047,30 +1153,13 @@ boolean tinitial, tfrom_file; } return; } - - fullname = "font"; - if (!strncmpi(opts, fullname, 4)) - { int wintype = -1; - - opts += 4; - if (!strncmpi (opts, "map", 3)) - wintype = NHW_MAP; - else if (!strncmpi (opts, "message", 7)) - wintype = NHW_MESSAGE; - else if (!strncmpi (opts, "text", 4)) - wintype = NHW_TEXT; - - if (wintype > 0 && (op = string_for_env_opt(fullname, opts, FALSE)) != 0) - { set_font_name (wintype, op); - } - return; - } -#endif +#endif + if (match_optname(opts, "palette", 3, TRUE) # ifdef MAC - || match_optname(opts, "hicolor", 3, TRUE) + || match_optname(opts, "hicolor", 3, TRUE) # endif - ) { + ) { int color_number, color_incr; # ifdef MAC @@ -1138,7 +1227,7 @@ boolean tinitial, tfrom_file; } return; } -#endif +#endif /* CHANGE_COLOR */ if (match_optname(opts, "fruit", 2, TRUE)) { char empty_str = '\0'; @@ -1266,15 +1355,26 @@ boolean tinitial, tfrom_file; else warning_opts(opts, fullname); return; } -#if 0 - fullname = "warnlevel"; - if (match_optname(opts, fullname, 5, TRUE)) { - op = string_for_opt(opts, negated); - if (negated) bad_negation(fullname, FALSE); - else if (op) (void) warnlevel_opts(op,fullname); - return; + /* boulder:symbol */ + fullname = "boulder"; + if (match_optname(opts, fullname, 7, TRUE)) { + if (negated) { + bad_negation(fullname, FALSE); + return; + } +/* if (!(opts = string_for_env_opt(fullname, opts, FALSE))) */ + if (!(opts = string_for_opt(opts, FALSE))) + return; + escapes(opts, opts); + + /* + * Override the default boulder symbol. + */ + iflags.bouldersym = (uchar) opts[0]; + if (!initial) need_redraw = TRUE; + return; } -#endif + /* name:string */ fullname = "name"; if (match_optname(opts, fullname, 4, TRUE)) { @@ -1324,9 +1424,47 @@ boolean tinitial, tfrom_file; return; } + /* WINCAP + * align_status:[left|top|right|bottom] */ + fullname = "align_status"; + if (match_optname(opts, fullname, sizeof("align_status")-1, TRUE)) { + op = string_for_opt(opts, negated); + if (op && !negated) { + if (!strncmpi (op, "left", sizeof("left")-1)) + iflags.wc_align_status = ALIGN_LEFT; + else if (!strncmpi (op, "top", sizeof("top")-1)) + iflags.wc_align_status = ALIGN_TOP; + else if (!strncmpi (op, "right", sizeof("right")-1)) + iflags.wc_align_status = ALIGN_RIGHT; + else if (!strncmpi (op, "bottom", sizeof("bottom")-1)) + iflags.wc_align_status = ALIGN_BOTTOM; + else + badoption(opts); + } else if (negated) bad_negation(fullname, TRUE); + return; + } + /* WINCAP + * align_message:[left|top|right|bottom] */ + fullname = "align_message"; + if (match_optname(opts, fullname, sizeof("align_message")-1, TRUE)) { + op = string_for_opt(opts, negated); + if (op && !negated) { + if (!strncmpi (op, "left", sizeof("left")-1)) + iflags.wc_align_message = ALIGN_LEFT; + else if (!strncmpi (op, "top", sizeof("top")-1)) + iflags.wc_align_message = ALIGN_TOP; + else if (!strncmpi (op, "right", sizeof("right")-1)) + iflags.wc_align_message = ALIGN_RIGHT; + else if (!strncmpi (op, "bottom", sizeof("bottom")-1)) + iflags.wc_align_message = ALIGN_BOTTOM; + else + badoption(opts); + } else if (negated) bad_negation(fullname, TRUE); + return; + } /* align:string */ fullname = "align"; - if (match_optname(opts, fullname, 4, TRUE)) { + if (match_optname(opts, fullname, sizeof("align")-1, TRUE)) { if (negated) bad_negation(fullname, FALSE); else if ((op = string_for_env_opt(fullname, opts, FALSE)) != 0) if ((flags.initalign = str2align(op)) == ROLE_NONE) @@ -1359,19 +1497,19 @@ boolean tinitial, tfrom_file; case 'u': flags.pickup_burden = UNENCUMBERED; break; - /* Burdened (slight encumberance) */ + /* Burdened (slight encumbrance) */ case 'b': flags.pickup_burden = SLT_ENCUMBER; break; - /* streSsed (moderate encumberance) */ + /* streSsed (moderate encumbrance) */ case 's': flags.pickup_burden = MOD_ENCUMBER; break; - /* straiNed (heavy encumberance) */ + /* straiNed (heavy encumbrance) */ case 'n': flags.pickup_burden = HVY_ENCUMBER; break; - /* OverTaxed (extreme encumberance) */ + /* OverTaxed (extreme encumbrance) */ case 'o': case 't': flags.pickup_burden = EXT_ENCUMBER; @@ -1447,10 +1585,46 @@ boolean tinitial, tfrom_file; } return; } + /* WINCAP + * player_selection: dialog | prompts */ + fullname = "player_selection"; + if (match_optname(opts, fullname, sizeof("player_selection")-1, TRUE)) { + op = string_for_opt(opts, negated); + if (op && !negated) { + if (!strncmpi (op, "dialog", sizeof("dialog")-1)) + iflags.wc_player_selection = VIA_DIALOG; + else if (!strncmpi (op, "prompt", sizeof("prompt")-1)) + iflags.wc_player_selection = VIA_PROMPTS; + else + badoption(opts); + } else if (negated) bad_negation(fullname, TRUE); + return; + } /* things to disclose at end of game */ - if (match_optname(opts, "disclose", 4, TRUE)) { - flags.end_disclose[0] = '\0'; /* all */ + if (match_optname(opts, "disclose", 7, TRUE)) { + /* + * The order that the end_disclore options are stored: + * inventory, attribs, vanquished, genocided, conduct + * There is an array in flags: + * end_disclose[NUM_DISCLOSURE_OPT]; + * with option settings for the each of the following: + * iagvc [see disclosure_options in decl.c]: + * Legal setting values in that array are: + * DISCLOSE_PROMPT_DEFAULT_YES ask with default answer yes + * DISCLOSE_PROMPT_DEFAULT_NO ask with default answer no + * DISCLOSE_YES_WITHOUT_PROMPT always disclose and don't ask + * DISCLOSE_NO_WITHOUT_PROMPT never disclose and don't ask + * + * Those setting values can be used in the option + * string as a prefix to get the desired behaviour. + * + * For backward compatibility, no prefix is required, + * and the presence of a i,a,g,v, or c without a + * prefix sets the corresponding value to DISCLOSE_YES_WITHOUT_PROMPT; + */ + boolean badopt = FALSE; + int idx, prefix_val; if (!(op = string_for_opt(opts, TRUE))) { /* for backwards compatibility, "disclose" without a * value means all (was inventory and attributes, @@ -1458,7 +1632,11 @@ boolean tinitial, tfrom_file; * it means "none" * (note "none" contains none of "iavkgc") */ - if (negated) Strcpy(flags.end_disclose, "none"); + for (num = 0; num < NUM_DISCLOSURE_OPTIONS; num++) { + if (negated) + flags.end_disclose[num] = DISCLOSE_NO_WITHOUT_PROMPT; + else flags.end_disclose[num] = DISCLOSE_PROMPT_DEFAULT_YES; + } return; } if (negated) { @@ -1466,16 +1644,40 @@ boolean tinitial, tfrom_file; return; } num = 0; + prefix_val = -1; while (*op && num < sizeof flags.end_disclose - 1) { - register char c; + register char c, *dop; + static char valid_settings[] = { + DISCLOSE_PROMPT_DEFAULT_YES, + DISCLOSE_PROMPT_DEFAULT_NO, + DISCLOSE_YES_WITHOUT_PROMPT, + DISCLOSE_NO_WITHOUT_PROMPT, + '\0' + }; c = lowc(*op); if (c == 'k') c = 'v'; /* killed -> vanquished */ - if (!index(flags.end_disclose, c)) { - flags.end_disclose[num++] = c; - flags.end_disclose[num] = '\0'; /* for index */ - } + dop = index(disclosure_options, c); + if (dop) { + idx = dop - disclosure_options; + if (idx < 0 || idx > NUM_DISCLOSURE_OPTIONS - 1) { + impossible("bad disclosure index %d %c", + idx, c); + continue; + } + if (prefix_val != -1) { + flags.end_disclose[idx] = prefix_val; + prefix_val = -1; + } else + flags.end_disclose[idx] = DISCLOSE_YES_WITHOUT_PROMPT; + } else if (index(valid_settings, c)) { + prefix_val = c; + } else if (c == ' ') { + /* do nothing */ + } else + badopt = TRUE; op++; } + if (badopt) badoption(opts); return; } @@ -1590,6 +1792,91 @@ boolean tinitial, tfrom_file; } #endif /* MSDOS */ + /* WINCAP + * map_mode:[tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8|ascii7x12|ascii8x12| + ascii16x12|ascii12x16|ascii10x18|fit_to_screen] */ + fullname = "map_mode"; + if (match_optname(opts, fullname, sizeof("map_mode")-1, TRUE)) { + op = string_for_opt(opts, negated); + if (op && !negated) { + if (!strncmpi (op, "tiles", sizeof("tiles")-1)) + iflags.wc_map_mode = MAP_MODE_TILES; + else if (!strncmpi (op, "ascii4x6", sizeof("ascii4x6")-1)) + iflags.wc_map_mode = MAP_MODE_ASCII4x6; + else if (!strncmpi (op, "ascii6x8", sizeof("ascii6x8")-1)) + iflags.wc_map_mode = MAP_MODE_ASCII6x8; + else if (!strncmpi (op, "ascii8x8", sizeof("ascii8x8")-1)) + iflags.wc_map_mode = MAP_MODE_ASCII8x8; + else if (!strncmpi (op, "ascii16x8", sizeof("ascii16x8")-1)) + iflags.wc_map_mode = MAP_MODE_ASCII16x8; + else if (!strncmpi (op, "ascii7x12", sizeof("ascii7x12")-1)) + iflags.wc_map_mode = MAP_MODE_ASCII7x12; + else if (!strncmpi (op, "ascii8x12", sizeof("ascii8x12")-1)) + iflags.wc_map_mode = MAP_MODE_ASCII8x12; + else if (!strncmpi (op, "ascii16x12", sizeof("ascii16x12")-1)) + iflags.wc_map_mode = MAP_MODE_ASCII16x12; + else if (!strncmpi (op, "ascii12x16", sizeof("ascii12x16")-1)) + iflags.wc_map_mode = MAP_MODE_ASCII12x16; + else if (!strncmpi (op, "ascii10x18", sizeof("ascii10x18")-1)) + iflags.wc_map_mode = MAP_MODE_ASCII10x18; + else if (!strncmpi (op, "fit_to_screen", sizeof("fit_to_screen")-1)) + iflags.wc_map_mode = MAP_MODE_ASCII_FIT_TO_SCREEN; + else + badoption(opts); + } else if (negated) bad_negation(fullname, TRUE); + return; + } + /* WINCAP + * scroll_margin:nn */ + fullname = "scroll_margin"; + if (match_optname(opts, fullname, sizeof("scroll_margin")-1, TRUE)) { + op = string_for_opt(opts, negated); + if ((negated && !op) || (!negated && op)) { + iflags.wc_scroll_margin = negated ? 5 : atoi(op); + } else if (negated) bad_negation(fullname, TRUE); + return; + } + /* WINCAP + * tile_width:nn */ + fullname = "tile_width"; + if (match_optname(opts, fullname, sizeof("tile_width")-1, TRUE)) { + op = string_for_opt(opts, negated); + if ((negated && !op) || (!negated && op)) { + iflags.wc_tile_width = negated ? 0 : atoi(op); + } else if (negated) bad_negation(fullname, TRUE); + return; + } + /* WINCAP + * tile_file:name */ + fullname = "tile_file"; + if (match_optname(opts, fullname, sizeof("tile_file")-1, TRUE)) { + if ((op = string_for_opt(opts, FALSE)) != 0) { + if (iflags.wc_tile_file) free(iflags.wc_tile_file); + iflags.wc_tile_file = (char *)alloc(strlen(op) + 1); + Strcpy(iflags.wc_tile_file, op); + } + return; + } + /* WINCAP + * tile_height:nn */ + fullname = "tile_height"; + if (match_optname(opts, fullname, sizeof("tile_height")-1, TRUE)) { + op = string_for_opt(opts, negated); + if ((negated && !op) || (!negated && op)) { + iflags.wc_tile_height = negated ? 0 : atoi(op); + } else if (negated) bad_negation(fullname, TRUE); + return; + } + /* WINCAP + * vary_msgcount:nn */ + fullname = "vary_msgcount"; + if (match_optname(opts, fullname, sizeof("vary_msgcount")-1, TRUE)) { + op = string_for_opt(opts, negated); + if ((negated && !op) || (!negated && op)) { + iflags.wc_vary_msgcount = negated ? 0 : atoi(op); + } else if (negated) bad_negation(fullname, TRUE); + return; + } fullname = "windowtype"; if (match_optname(opts, fullname, 3, TRUE)) { @@ -1604,6 +1891,19 @@ boolean tinitial, tfrom_file; return; } + /* WINCAP + * setting window colors + * syntax: windowcolors=menu foregrnd/backgrnd text foregrnd/backgrnd + */ + fullname = "windowcolors"; + if (match_optname(opts, fullname, 7, TRUE)) { + if ((op = string_for_opt(opts, FALSE)) != 0) { + if (!wc_set_window_colors(op)) + badoption(opts); + } else if (negated) bad_negation(fullname, TRUE); + return; + } + /* menustyle:traditional or combo or full or partial */ if (match_optname(opts, "menustyle", 4, TRUE)) { int tmp; @@ -1681,13 +1981,15 @@ boolean tinitial, tfrom_file; return; } /* options that must come from config file */ - if (!initial && boolopt_only_initial(i)) { + if (!initial && (boolopt[i].optflags == SET_IN_FILE)) { rejectoption(boolopt[i].name); return; } *(boolopt[i].addr) = !negated; + duplicate_opt_detection(boolopt[i].name, 0); + #if defined(TERMLIB) || defined(ASCIIGRAPH) || defined(MAC_GRAPHICS_ENV) if (FALSE # ifdef TERMLIB @@ -1763,10 +2065,14 @@ boolean tinitial, tfrom_file; vision_recalc(2); /* shut down vision */ vision_full_recalc = 1; /* delayed recalc */ } - + else if ((boolopt[i].addr) == &iflags.use_inverse) { + need_redraw = TRUE; + } + else if ((boolopt[i].addr) == &iflags.hilite_pet) { + need_redraw = TRUE; + } #ifdef TEXTCOLOR - else if ((boolopt[i].addr) == &iflags.use_color - || (boolopt[i].addr) == &iflags.hilite_pet) { + else if ((boolopt[i].addr) == &iflags.use_color) { need_redraw = TRUE; # ifdef TOS if ((boolopt[i].addr) == &iflags.use_color @@ -1861,6 +2167,7 @@ map_menu_cmd(ch) #endif static char fmtstr_doset_add_menu[] = "%s%-15s [%s] "; +static char fmtstr_doset_add_menu_tab[] = "%s\t[%s]"; STATIC_OVL void doset_add_menu(win, option, indexoffset) @@ -1893,7 +2200,10 @@ doset_add_menu(win, option, indexoffset) } } /* " " replaces "a - " -- assumes menus follow that style */ - Sprintf(buf, fmtstr_doset_add_menu, (any.a_int ? "" : " "), option, value); + if (!iflags.menu_tab_sep) + Sprintf(buf, fmtstr_doset_add_menu, any.a_int ? "" : " ", option, value); + else + Sprintf(buf, fmtstr_doset_add_menu_tab, option, value); add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); } @@ -1922,15 +2232,23 @@ doset() for (pass = 0; pass <= 1; pass++) for (i = 0; boolopt[i].name; i++) if ((bool_p = boolopt[i].addr) != 0 && - (boolopt_only_initial(i) ^ pass)) { + ((boolopt[i].optflags == DISP_IN_GAME && pass == 0) || + (boolopt[i].optflags == SET_IN_GAME && pass == 1))) { if (bool_p == &flags.female) continue; /* obsolete */ #ifdef WIZARD if (bool_p == &iflags.sanity_check && !wizard) continue; + if (bool_p == &iflags.menu_tab_sep && !wizard) continue; #endif + if (is_wc_option(boolopt[i].name) && + !wc_supported(boolopt[i].name)) continue; any.a_int = (pass == 0) ? 0 : i + 1; - Sprintf(buf, "%s%-13s [%s]", + if (!iflags.menu_tab_sep) + Sprintf(buf, "%s%-13s [%s]", pass == 0 ? " " : "", boolopt[i].name, *bool_p ? "true" : "false"); + else + Sprintf(buf, "%s\t[%s]", + boolopt[i].name, *bool_p ? "true" : "false"); add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); } @@ -1954,8 +2272,9 @@ doset() strlen(compopt[i].name) > (unsigned) biggest_name) biggest_name = (int) strlen(compopt[i].name); if (biggest_name > 30) biggest_name = 30; - Sprintf(fmtstr_doset_add_menu, "%%s%%-%ds [%%s]", biggest_name); - + if (!iflags.menu_tab_sep) + Sprintf(fmtstr_doset_add_menu, "%%s%%-%ds [%%s]", biggest_name); + /* deliberately put `name', `role', `race', `gender' first */ doset_add_menu(tmpwin, "name", 0); doset_add_menu(tmpwin, "role", 0); @@ -1970,6 +2289,9 @@ doset() !strcmp(compopt[i].name, "race") || !strcmp(compopt[i].name, "gender")) continue; + else if (is_wc_option(compopt[i].name) && + !wc_supported(compopt[i].name)) + continue; else doset_add_menu(tmpwin, compopt[i].name, (pass == DISP_IN_GAME) ? 0 : indexoffset); @@ -1997,6 +2319,8 @@ doset() Sprintf(buf, "%s%s", *boolopt[opt_indx].addr ? "!" : "", boolopt[opt_indx].name); parseoptions(buf, setinitial, fromfile); + if (wc_supported(boolopt[opt_indx].name)) + preference_update(boolopt[opt_indx].name); } else { /* compound option */ opt_indx -= boolcount; @@ -2009,6 +2333,8 @@ doset() /* pass the buck */ parseoptions(buf, setinitial, fromfile); } + if (wc_supported(compopt[opt_indx].name)) + preference_update(compopt[opt_indx].name); } } free((genericptr_t)pick_list); @@ -2032,7 +2358,7 @@ boolean setinitial,setfromfile; char buf[BUFSZ]; boolean retval = FALSE; - /* Special handling of menustyle, pickup_burden, and pickup_types. */ + /* Special handling of menustyle, pickup_burden, and pickup_types, disclose options. */ if (!strcmp("menustyle", optname)) { const char *style_name; menu_item *style_pick = (menu_item *)0; @@ -2064,7 +2390,7 @@ boolean setinitial,setfromfile; add_menu(tmpwin, NO_GLYPH, &any, burden_letters[i], 0, ATR_NONE, burden_name, MENU_UNSELECTED); } - end_menu(tmpwin, "Select encumberence level:"); + end_menu(tmpwin, "Select encumbrance level:"); if (select_menu(tmpwin, PICK_ONE, &burden_pick) > 0) { flags.pickup_burden = burden_pick->item.a_int - 1; free((genericptr_t)burden_pick); @@ -2075,6 +2401,70 @@ boolean setinitial,setfromfile; /* parseoptions will prompt for the list of types */ parseoptions(strcpy(buf, "pickup_types"), setinitial, setfromfile); retval = TRUE; + } else if (!strcmp("disclose", optname)) { + int pick_cnt, pick_idx, opt_idx; + menu_item *disclosure_category_pick = (menu_item *)0; + /* + * The order of disclose_names[] + * must correspond to disclosure_options in decl.h + */ + static const char *disclosure_names[] = { + "inventory", "attributes", "vanquished", "genocides", "conduct" + }; + int disc_cat[NUM_DISCLOSURE_OPTIONS]; + const char *disclosure_name; + + tmpwin = create_nhwindow(NHW_MENU); + start_menu(tmpwin); + for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) { + disclosure_name = disclosure_names[i]; + any.a_int = i + 1; + add_menu(tmpwin, NO_GLYPH, &any, disclosure_options[i], 0, + ATR_NONE, disclosure_name, MENU_UNSELECTED); + disc_cat[i] = 0; + } + end_menu(tmpwin, "Change which disclosure options categories:"); + if ((pick_cnt = select_menu(tmpwin, PICK_ANY, &disclosure_category_pick)) > 0) { + for (pick_idx = 0; pick_idx < pick_cnt; ++pick_idx) { + opt_idx = disclosure_category_pick[pick_idx].item.a_int - 1; + disc_cat[opt_idx] = 1; + } + free((genericptr_t)disclosure_category_pick); + disclosure_category_pick = (menu_item *)0; + } + destroy_nhwindow(tmpwin); + + for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) { + if (disc_cat[i]) { + char dbuf[BUFSZ]; + menu_item *disclosure_option_pick = (menu_item *)0; + Sprintf(dbuf, "Disclosure options for %s:", disclosure_names[i]); + tmpwin = create_nhwindow(NHW_MENU); + start_menu(tmpwin); + any.a_char = DISCLOSE_NO_WITHOUT_PROMPT; + add_menu(tmpwin, NO_GLYPH, &any, 'a', 0, + ATR_NONE,"Never disclose and don't prompt", MENU_UNSELECTED); + any.a_void = 0; + any.a_char = DISCLOSE_YES_WITHOUT_PROMPT; + add_menu(tmpwin, NO_GLYPH, &any, 'b', 0, + ATR_NONE,"Always disclose and don't prompt", MENU_UNSELECTED); + any.a_void = 0; + any.a_char = DISCLOSE_PROMPT_DEFAULT_NO; + add_menu(tmpwin, NO_GLYPH, &any, 'c', 0, + ATR_NONE,"Prompt and default answer to \"No\"", MENU_UNSELECTED); + any.a_void = 0; + any.a_char = DISCLOSE_PROMPT_DEFAULT_YES; + add_menu(tmpwin, NO_GLYPH, &any, 'd', 0, + ATR_NONE,"Prompt and default answer to \"Yes\"", MENU_UNSELECTED); + end_menu(tmpwin, dbuf); + if (select_menu(tmpwin, PICK_ONE, &disclosure_option_pick) > 0) { + flags.end_disclose[i] = disclosure_option_pick->item.a_char; + free((genericptr_t)disclosure_option_pick); + } + destroy_nhwindow(tmpwin); + } + } + retval = TRUE; } return retval; } @@ -2091,31 +2481,99 @@ char *buf; { char ocl[MAXOCLASSES+1]; static const char none[] = "(none)", randomrole[] = "random", - to_be_done[] = "(to be done)"; -#ifdef PREFIXES_IN_USE + to_be_done[] = "(to be done)", + defopt[] = "default", + defbrief[] = "def"; int i; -#endif buf[0] = '\0'; - if (!strcmp(optname,"align")) + if (!strcmp(optname,"align_message")) + Sprintf(buf, "%s", iflags.wc_align_message == ALIGN_TOP ? "top" : + iflags.wc_align_message == ALIGN_LEFT ? "left" : + iflags.wc_align_message == ALIGN_BOTTOM ? "bottom" : + iflags.wc_align_message == ALIGN_RIGHT ? "right" : + defopt); + else if (!strcmp(optname,"align_status")) + Sprintf(buf, "%s", iflags.wc_align_status == ALIGN_TOP ? "top" : + iflags.wc_align_status == ALIGN_LEFT ? "left" : + iflags.wc_align_status == ALIGN_BOTTOM ? "bottom" : + iflags.wc_align_status == ALIGN_RIGHT ? "right" : + defopt); + else if (!strcmp(optname,"align")) Sprintf(buf, "%s", rolestring(flags.initalign, aligns, adj)); + else if (!strcmp(optname, "boulder")) + Sprintf(buf, "%c", iflags.bouldersym ? + iflags.bouldersym : oc_syms[(int)objects[BOULDER].oc_class]); else if (!strcmp(optname, "catname")) Sprintf(buf, "%s", catname[0] ? catname : none ); - else if (!strcmp(optname, "disclose")) - Sprintf(buf, "%s", - flags.end_disclose[0] ? flags.end_disclose : "all" ); + else if (!strcmp(optname, "disclose")) { + for (i = 0; i < NUM_DISCLOSURE_OPTIONS; i++) { + char topt[2]; + if (i) Strcat(buf," "); + topt[1] = '\0'; + topt[0] = flags.end_disclose[i]; + Strcat(buf, topt); + topt[0] = disclosure_options[i]; + Strcat(buf, topt); + } + } else if (!strcmp(optname, "dogname")) Sprintf(buf, "%s", dogname[0] ? dogname : none ); else if (!strcmp(optname, "dungeon")) Sprintf(buf, "%s", to_be_done); else if (!strcmp(optname, "effects")) Sprintf(buf, "%s", to_be_done); + else if (!strcmp(optname, "font_map")) + Sprintf(buf, "%s", iflags.wc_font_map ? iflags.wc_font_map : defopt); + else if (!strcmp(optname, "font_message")) + Sprintf(buf, "%s", iflags.wc_font_message ? iflags.wc_font_message : defopt); + else if (!strcmp(optname, "font_status")) + Sprintf(buf, "%s", iflags.wc_font_status ? iflags.wc_font_status : defopt); + else if (!strcmp(optname, "font_menu")) + Sprintf(buf, "%s", iflags.wc_font_menu ? iflags.wc_font_menu : defopt); + else if (!strcmp(optname, "font_text")) + Sprintf(buf, "%s", iflags.wc_font_text ? iflags.wc_font_text : defopt); + else if (!strcmp(optname, "font_size_map")) { + if (iflags.wc_fontsiz_map) Sprintf(buf, "%d", iflags.wc_fontsiz_map); + else Strcpy(buf, defopt); + } + else if (!strcmp(optname, "font_size_message")) { + if (iflags.wc_fontsiz_message) Sprintf(buf, "%d", + iflags.wc_fontsiz_message); + else Strcpy(buf, defopt); + } + else if (!strcmp(optname, "font_size_status")) { + if (iflags.wc_fontsiz_status) Sprintf(buf, "%d", iflags.wc_fontsiz_status); + else Strcpy(buf, defopt); + } + else if (!strcmp(optname, "font_size_menu")) { + if (iflags.wc_fontsiz_menu) Sprintf(buf, "%d", iflags.wc_fontsiz_menu); + else Strcpy(buf, defopt); + } + else if (!strcmp(optname, "font_size_text")) { + if (iflags.wc_fontsiz_text) Sprintf(buf, "%d",iflags.wc_fontsiz_text); + else Strcpy(buf, defopt); + } else if (!strcmp(optname, "fruit")) Sprintf(buf, "%s", pl_fruit); else if (!strcmp(optname, "gender")) Sprintf(buf, "%s", rolestring(flags.initgend, genders, adj)); else if (!strcmp(optname, "horsename")) Sprintf(buf, "%s", horsename[0] ? horsename : none); + else if (!strcmp(optname, "map_mode")) + Sprintf(buf, "%s", + iflags.wc_map_mode == MAP_MODE_TILES ? "tiles" : + iflags.wc_map_mode == MAP_MODE_ASCII4x6 ? "ascii4x6" : + iflags.wc_map_mode == MAP_MODE_ASCII6x8 ? "ascii6x8" : + iflags.wc_map_mode == MAP_MODE_ASCII8x8 ? "ascii8x8" : + iflags.wc_map_mode == MAP_MODE_ASCII16x8 ? "ascii16x8" : + iflags.wc_map_mode == MAP_MODE_ASCII7x12 ? "ascii7x12" : + iflags.wc_map_mode == MAP_MODE_ASCII8x12 ? "ascii8x12" : + iflags.wc_map_mode == MAP_MODE_ASCII16x12 ? "ascii16x12" : + iflags.wc_map_mode == MAP_MODE_ASCII12x16 ? "ascii12x16" : + iflags.wc_map_mode == MAP_MODE_ASCII10x18 ? "ascii10x18" : + iflags.wc_map_mode == MAP_MODE_ASCII_FIT_TO_SCREEN ? + "fit_to_screen" : defopt); else if (!strcmp(optname, "menustyle")) Sprintf(buf, "%s", menutype[(int)flags.menu_style] ); else if (!strcmp(optname, "menu_deselect_all")) @@ -2158,7 +2616,8 @@ char *buf; #endif else if (!strcmp(optname, "pettype")) Sprintf(buf, "%s", (preferred_pet == 'c') ? "cat" : - (preferred_pet == 'd') ? "dog" : "random" ); + (preferred_pet == 'd') ? "dog" : + (preferred_pet == 'n') ? "none" : "random"); else if (!strcmp(optname, "pickup_burden")) Sprintf(buf, "%s", burdentype[flags.pickup_burden] ); else if (!strcmp(optname, "pickup_types")) { @@ -2172,7 +2631,13 @@ char *buf; else if (!strcmp(optname, "scores")) { Sprintf(buf, "%d top/%d around%s", flags.end_top, flags.end_around, flags.end_own ? "/own" : ""); - } + } + else if (!strcmp(optname, "scroll_margin")) { + if (iflags.wc_scroll_margin) Sprintf(buf, "%d",iflags.wc_scroll_margin); + else Strcpy(buf, defopt); + } + else if (!strcmp(optname, "player_selection")) + Sprintf(buf, "%s", iflags.wc_player_selection ? "prompts" : "dialog"); #ifdef MSDOS else if (!strcmp(optname, "soundcard")) Sprintf(buf, "%s", to_be_done); @@ -2185,8 +2650,23 @@ char *buf; FEATURE_NOTICE_VER_MAJ, FEATURE_NOTICE_VER_MIN, FEATURE_NOTICE_VER_PATCH); - } else if (!strcmp(optname, "traps")) + } + else if (!strcmp(optname, "tile_file")) + Sprintf(buf, "%s", iflags.wc_tile_file ? iflags.wc_tile_file : defopt); + else if (!strcmp(optname, "tile_height")) { + if (iflags.wc_tile_height) Sprintf(buf, "%d",iflags.wc_tile_height); + else Strcpy(buf, defopt); + } + else if (!strcmp(optname, "tile_width")) { + if (iflags.wc_tile_width) Sprintf(buf, "%d",iflags.wc_tile_width); + else Strcpy(buf, defopt); + } + else if (!strcmp(optname, "traps")) Sprintf(buf, "%s", to_be_done); + else if (!strcmp(optname, "vary_msgcount")) { + if (iflags.wc_vary_msgcount) Sprintf(buf, "%d",iflags.wc_vary_msgcount); + else Strcpy(buf, defopt); + } #ifdef MSDOS else if (!strcmp(optname, "video")) Sprintf(buf, "%s", to_be_done); @@ -2204,12 +2684,18 @@ char *buf; ttycolors[CLR_BRIGHT_MAGENTA], ttycolors[CLR_BRIGHT_CYAN]); #endif /* VIDEOSHADES */ -#if 0 - else if (!strcmp(optname, "warnlevel")) - Sprintf(buf, "%d", flags.warnlevel); -#endif else if (!strcmp(optname, "windowtype")) Sprintf(buf, "%s", windowprocs.name); + else if (!strcmp(optname, "windowcolors")) + Sprintf(buf, "%s/%s %s/%s %s/%s %s/%s", + iflags.wc_foregrnd_menu ? iflags.wc_foregrnd_menu : defbrief, + iflags.wc_backgrnd_menu ? iflags.wc_backgrnd_menu : defbrief, + iflags.wc_foregrnd_message ? iflags.wc_foregrnd_message : defbrief, + iflags.wc_backgrnd_message ? iflags.wc_backgrnd_message : defbrief, + iflags.wc_foregrnd_status ? iflags.wc_foregrnd_status : defbrief, + iflags.wc_backgrnd_status ? iflags.wc_backgrnd_status : defbrief, + iflags.wc_foregrnd_text ? iflags.wc_foregrnd_text : defbrief, + iflags.wc_backgrnd_text ? iflags.wc_backgrnd_text : defbrief); #ifdef PREFIXES_IN_USE else { for (i = 0; i < PREFIX_COUNT; ++i) @@ -2273,12 +2759,7 @@ option_help() winid datawin; datawin = create_nhwindow(NHW_TEXT); -#ifdef AMIGA - if (FromWBench) - Sprintf(buf, "Set options as OPTIONS= in %s or in icon", configfile); - else -#endif - Sprintf(buf, "Set options as OPTIONS= in %s", configfile); + Sprintf(buf, "Set options as OPTIONS= in %s", configfile); opt_intro[CONFIG_SLOT] = (const char *) buf; for (i = 0; opt_intro[i]; i++) putstr(datawin, 0, opt_intro[i]); @@ -2288,6 +2769,7 @@ option_help() if (boolopt[i].addr) { #ifdef WIZARD if (boolopt[i].addr == &iflags.sanity_check && !wizard) continue; + if (boolopt[i].addr == &iflags.menu_tab_sep && !wizard) continue; #endif next_opt(datawin, boolopt[i].name); } @@ -2531,6 +3013,242 @@ char *class_select; return ret; } +struct wc_Opt wc_options[] = { + {"ascii_map", WC_ASCII_MAP}, + {"color", WC_COLOR}, + {"eight_bit_tty", WC_EIGHT_BIT_IN}, + {"hilite_pet", WC_HILITE_PET}, + {"large_font", WC_LARGE_FONT}, /* now obsolete */ + {"popup_dialog", WC_POPUP_DIALOG}, + {"preload_tiles", WC_PRELOAD_TILES}, + {"tiled_map", WC_TILED_MAP}, + {"tile_file", WC_TILE_FILE}, + {"tile_width", WC_TILE_WIDTH}, + {"tile_height", WC_TILE_HEIGHT}, + {"use_inverse", WC_INVERSE}, + {"align_message", WC_ALIGN_MESSAGE}, + {"align_status", WC_ALIGN_STATUS}, + {"font_map", WC_FONT_MAP}, + {"font_menu", WC_FONT_MENU}, + {"font_message",WC_FONT_MESSAGE}, +#if 0 + {"perm_invent",WC_PERM_INVENT}, +#endif + {"font_size_map", WC_FONTSIZ_MAP}, + {"font_size_menu", WC_FONTSIZ_MENU}, + {"font_size_message", WC_FONTSIZ_MESSAGE}, + {"font_size_status", WC_FONTSIZ_STATUS}, + {"font_size_text", WC_FONTSIZ_TEXT}, + {"font_status", WC_FONT_STATUS}, + {"font_text", WC_FONT_TEXT}, + {"map_mode", WC_MAP_MODE}, + {"scroll_margin", WC_SCROLL_MARGIN}, + {"vary_msgcount",WC_VARY_MSGCOUNT}, + {(char *)0, 0L} +}; + + +/* + * If a port wants to change or ensure that the + * SET_IN_FILE, DISP_IN_GAME, or SET_IN_GAME status of an option is + * correct (for controlling its display in the option menu) call + * set_option_mod_status() + * with the second argument of 0,2, or 3 respectively. + */ +void +set_option_mod_status(optnam, status) +char *optnam; +int status; +{ + int k; + if (status < SET_IN_FILE || status > SET_IN_GAME) { + impossible("set_option_mod_status: status out of range %d.", status); + return; + } + for (k = 0; boolopt[k].name; k++) { + if (!strncmpi(boolopt[k].name, optnam, strlen(optnam))) { + boolopt[k].optflags = status; + return; + } + } + for (k = 0; compopt[k].name; k++) { + if (!strncmpi(compopt[k].name, optnam, strlen(optnam))) { + compopt[k].optflags = status; + return; + } + } +} + +/* + * You can set several wc_options in one call to + * set_wc_option_mod_status() by setting + * the appropriate bits for each option that you + * are setting in the optmask argument + * prior to calling. + * example: set_wc_option_mod_status(WC_COLOR|WC_SCROLL_MARGIN, SET_IN_GAME); + */ +void +set_wc_option_mod_status(optmask, status) +unsigned long optmask; +int status; +{ + int k = 0; + if (status < SET_IN_FILE || status > SET_IN_GAME) { + impossible("set_option_mod_status: status out of range %d.", status); + return; + } + while (wc_options[k].wc_name) { + if (optmask & wc_options[k].wc_bit) { + set_option_mod_status(wc_options[k].wc_name, status); + } + k++; + } +} + +STATIC_OVL boolean +is_wc_option(optnam) +const char *optnam; +{ + int k = 0; + while (wc_options[k].wc_name) { + if (strcmp(wc_options[k].wc_name, optnam) == 0) + return TRUE; + k++; + } + return FALSE; +} + +STATIC_OVL boolean +wc_supported(optnam) +const char *optnam; +{ + int k = 0; + while (wc_options[k].wc_name) { + if (!strcmp(wc_options[k].wc_name, optnam) && + (windowprocs.wincap & wc_options[k].wc_bit)) + return TRUE; + k++; + } + return FALSE; +} + +STATIC_OVL void +wc_set_font_name(wtype, fontname) +int wtype; +char *fontname; +{ + char **fn = (char **)0; + if (!fontname) return; + switch(wtype) { + case NHW_MAP: + fn = &iflags.wc_font_map; + break; + case NHW_MESSAGE: + fn = &iflags.wc_font_message; + break; + case NHW_TEXT: + fn = &iflags.wc_font_text; + break; + case NHW_MENU: + fn = &iflags.wc_font_menu; + break; + case NHW_STATUS: + fn = &iflags.wc_font_status; + break; + default: + return; + } + if (fn) { + if (*fn) free(*fn); + *fn = (char *)alloc(strlen(fontname) + 1); + Strcpy(*fn, fontname); + } + return; +} + +STATIC_OVL int +wc_set_window_colors(op) +char *op; +{ + /* syntax: + * menu white/black message green/yellow status white/blue text white/black + */ + + int j; + char buf[BUFSZ]; + char *wn, *tfg, *tbg, *newop; + static char *wnames[] = {"menu", "message", "status", "text"}; + static char *shortnames[] = {"mnu", "msg", "sts", "txt"}; + static char **fgp[] = { + &iflags.wc_foregrnd_menu, + &iflags.wc_foregrnd_message, + &iflags.wc_foregrnd_status, + &iflags.wc_foregrnd_text + }; + static char **bgp[] = { + &iflags.wc_backgrnd_menu, + &iflags.wc_backgrnd_message, + &iflags.wc_backgrnd_status, + &iflags.wc_backgrnd_text + }; + + Strcpy(buf, op); + newop = mungspaces(buf); + while (newop && *newop) { + + wn = tfg = tbg = (char *)0; + + /* until first non-space in case there's leading spaces - before colorname*/ + while(*newop && isspace(*newop)) newop++; + if (*newop) wn = newop; + else return 0; + + /* until first space - colorname*/ + while(*newop && !isspace(*newop)) newop++; + if (*newop) *newop = '\0'; + else return 0; + newop++; + + /* until first non-space - before foreground*/ + while(*newop && isspace(*newop)) newop++; + if (*newop) tfg = newop; + else return 0; + + /* until slash - foreground */ + while(*newop && *newop != '/') newop++; + if (*newop) *newop = '\0'; + else return 0; + newop++; + + /* until first non-space (in case there's leading space after slash) - before background */ + while(*newop && isspace(*newop)) newop++; + if (*newop) tbg = newop; + else return 0; + + /* until first space - background */ + while(*newop && !isspace(*newop)) newop++; + if (*newop) *newop++ = '\0'; + + for (j = 0; j < 4; ++j) { + if (!strcmpi(wn, wnames[j]) || + !strcmpi(wn, shortnames[j])) { + if (tfg && !strstri(tfg, " ")) { + if (*fgp[j]) free(*fgp[j]); + *fgp[j] = (char *)alloc(strlen(tfg) + 1); + Strcpy(*fgp[j], tfg); + } + if (tbg && !strstri(tbg, " ")) { + if (*bgp[j]) free(*bgp[j]); + *bgp[j] = (char *)alloc(strlen(tbg) + 1); + Strcpy(*bgp[j], tbg); + } + break; + } + } + } + return 1; +} + #endif /* OPTION_LISTS_ONLY */ /*options.c*/ diff --git a/src/pager.c b/src/pager.c index 0dd1a9f..240b0f3 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pager.c 3.3 1999/10/10 */ +/* SCCS Id: @(#)pager.c 3.4 2002/01/17 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -98,18 +98,23 @@ lookat(x, y, buf, monbuf) bhitpos.x = x; bhitpos.y = y; mtmp = m_at(x,y); - if(mtmp != (struct monst *) 0) { - register boolean hp = (mtmp->data == &mons[PM_HIGH_PRIEST]); + if (mtmp != (struct monst *) 0) { + char *name, monnambuf[BUFSZ]; + boolean accurate = !Hallucination; + + if (mtmp->data == &mons[PM_COYOTE] && accurate) + name = coyotename(mtmp, monnambuf); + else + name = distant_monnam(mtmp, ARTICLE_NONE, monnambuf); pm = mtmp->data; Sprintf(buf, "%s%s%s", (mtmp->mx != x || mtmp->my != y) ? - ((mtmp->isshk && !Hallucination) + ((mtmp->isshk && accurate) ? "tail of " : "tail of a ") : "", - (!hp && mtmp->mtame && !Hallucination) ? "tame " : - (!hp && mtmp->mpeaceful && !Hallucination) ? - "peaceful " : "", - (hp ? "high priest" : x_monnam(mtmp, ARTICLE_NONE, (char *)0, 0, TRUE))); + (mtmp->mtame && accurate) ? "tame " : + (mtmp->mpeaceful && accurate) ? "peaceful " : "", + name); if (u.ustuck == mtmp) Strcat(buf, (Upolyd && sticks(youmonst.data)) ? ", being held" : ", holding you"); @@ -176,8 +181,13 @@ lookat(x, y, buf, monbuf) } if (MATCH_WARN_OF_MON(mtmp)) { char wbuf[BUFSZ]; - Sprintf(wbuf, "warned of %s", makeplural(mtmp->data->mname)); - Strcat(monbuf, wbuf); + if (Hallucination) + Strcat(monbuf, "paranoid delusion"); + else { + Sprintf(wbuf, "warned of %s", + makeplural(mtmp->data->mname)); + Strcat(monbuf, wbuf); + } if (ways_seen-- > 1) Strcat(monbuf, ", "); } } @@ -485,6 +495,8 @@ do_look(quick) sym = showsyms[trap_to_defsym(glyph_to_trap(glyph))]; } else if (glyph_is_object(glyph)) { sym = oc_syms[(int)objects[glyph_to_obj(glyph)].oc_class]; + if (sym == '`' && iflags.bouldersym && (int)glyph_to_obj(glyph) == BOULDER) + sym = iflags.bouldersym; } else if (glyph_is_monster(glyph)) { /* takes care of pets, detected, ridden, and regular mons */ sym = monsyms[(int)mons[glyph_to_mon(glyph)].mlet]; @@ -606,7 +618,7 @@ do_look(quick) } /* Now check for warning symbols */ - for (i = 0; i < WARNCOUNT; i++) { + for (i = 1; i < WARNCOUNT; i++) { x_str = def_warnsyms[i].explanation; if (sym == (from_screen ? warnsyms[i] : def_warnsyms[i].sym)) { if (!found) { @@ -633,6 +645,10 @@ do_look(quick) } } + /* handle optional boulder symbol as a special case */ + if (iflags.bouldersym && sym == iflags.bouldersym) + found += append_str(out_str, "boulder"); + /* * If we are looking at the screen, follow multiple possibilities or * an ambiguous explanation by something more detailed. @@ -640,14 +656,12 @@ do_look(quick) if (from_screen) { if (found > 1 || need_to_look) { char monbuf[BUFSZ]; - char temp_buf[BUFSZ], coybuf[QBUFSZ]; + char temp_buf[BUFSZ]; pm = lookat(cc.x, cc.y, look_buf, monbuf); firstmatch = look_buf; if (*firstmatch) { - Sprintf(temp_buf, " (%s)", - (pm == &mons[PM_COYOTE]) ? - coyotename(coybuf) : firstmatch); + Sprintf(temp_buf, " (%s)", firstmatch); (void)strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1); found = 1; /* we have something to look up */ } diff --git a/src/pickup.c b/src/pickup.c index a127c9c..19a8bf5 100644 --- a/src/pickup.c +++ b/src/pickup.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pickup.c 3.3 2000/03/01 */ +/* SCCS Id: @(#)pickup.c 3.4 2001/03/14 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -9,8 +9,13 @@ #include "hack.h" STATIC_DCL void FDECL(simple_look, (struct obj *,BOOLEAN_P)); +#ifndef GOLDOBJ STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *, const char *,struct obj *,BOOLEAN_P,BOOLEAN_P,int *)); +#else +STATIC_DCL boolean FDECL(query_classes, (char *,boolean *,boolean *, + const char *,struct obj *,BOOLEAN_P,int *)); +#endif STATIC_DCL void FDECL(check_here, (BOOLEAN_P)); STATIC_DCL boolean FDECL(n_or_more, (struct obj *)); STATIC_DCL boolean FDECL(all_but_uchain, (struct obj *)); @@ -80,18 +85,29 @@ boolean here; /* flag for type of obj list linkage */ } } +#ifndef GOLDOBJ int collect_obj_classes(ilets, otmp, here, incl_gold, filter) char ilets[]; register struct obj *otmp; boolean here, incl_gold; boolean FDECL((*filter),(OBJ_P)); +#else +int +collect_obj_classes(ilets, otmp, here, filter) +char ilets[]; +register struct obj *otmp; +boolean here; +boolean FDECL((*filter),(OBJ_P)); +#endif { register int iletct = 0; register char c; +#ifndef GOLDOBJ if (incl_gold) ilets[iletct++] = def_oc_syms[GOLD_CLASS]; +#endif ilets[iletct] = '\0'; /* terminate ilets so that index() will work */ while (otmp) { c = def_oc_syms[(int)otmp->oclass]; @@ -115,6 +131,7 @@ boolean FDECL((*filter),(OBJ_P)); * "?/a" or "a?/" or "/a?",&c picks all '?' even though no '/' * (ie, treated as if it had just been "?a"). */ +#ifndef GOLDOBJ STATIC_OVL boolean query_classes(oclasses, one_at_a_time, everything, action, objs, here, incl_gold, menu_on_demand) @@ -124,6 +141,17 @@ const char *action; struct obj *objs; boolean here, incl_gold; int *menu_on_demand; +#else +STATIC_OVL boolean +query_classes(oclasses, one_at_a_time, everything, action, objs, + here, menu_on_demand) +char oclasses[]; +boolean *one_at_a_time, *everything; +const char *action; +struct obj *objs; +boolean here; +int *menu_on_demand; +#endif { char ilets[20], inbuf[BUFSZ]; int iletct, oclassct; @@ -133,7 +161,10 @@ int *menu_on_demand; oclasses[oclassct = 0] = '\0'; *one_at_a_time = *everything = m_seen = FALSE; - iletct = collect_obj_classes(ilets, objs, here, incl_gold, + iletct = collect_obj_classes(ilets, objs, here, +#ifndef GOLDOBJ + incl_gold, +#endif (boolean FDECL((*),(OBJ_P))) 0); if (iletct == 0) { return FALSE; @@ -284,6 +315,18 @@ struct obj *obj; if (((index(valid_menu_classes,'u') != (char *)0) && obj->unpaid) || (index(valid_menu_classes, obj->oclass) != (char *)0)) return TRUE; + else if (((index(valid_menu_classes,'U') != (char *)0) && + (obj->oclass != GOLD_CLASS && obj->bknown && !obj->blessed && !obj->cursed))) + return TRUE; + else if (((index(valid_menu_classes,'B') != (char *)0) && + (obj->oclass != GOLD_CLASS && obj->bknown && obj->blessed))) + return TRUE; + else if (((index(valid_menu_classes,'C') != (char *)0) && + (obj->oclass != GOLD_CLASS && obj->bknown && obj->cursed))) + return TRUE; + else if (((index(valid_menu_classes,'X') != (char *)0) && + (obj->oclass != GOLD_CLASS && !obj->bknown))) + return TRUE; else return FALSE; } @@ -314,7 +357,8 @@ register struct obj *otmp; } /* - * Have the hero pick things from the ground. + * Have the hero pick things from the ground + * or a monster's inventory if swallowed. * * Arg what: * >0 autopickup @@ -331,47 +375,57 @@ int what; /* should be a long */ int i, n, res, count, n_tried = 0, n_picked = 0; menu_item *pick_list = (menu_item *) 0; boolean autopickup = what > 0; + struct obj *objchain; + int traverse_how; if (what < 0) /* pick N of something */ count = -what; else /* pick anything */ count = 0; - /* no auto-pick if no-pick move, nothing there, or in a pool */ - if (autopickup && (flags.nopick || !OBJ_AT(u.ux, u.uy) || + if (!u.uswallow) { + /* no auto-pick if no-pick move, nothing there, or in a pool */ + if (autopickup && (flags.nopick || !OBJ_AT(u.ux, u.uy) || (is_pool(u.ux, u.uy) && !Underwater) || is_lava(u.ux, u.uy))) { - read_engr_at(u.ux, u.uy); - return (0); - } + read_engr_at(u.ux, u.uy); + return (0); + } - /* no pickup if levitating & not on air or water level */ - if (!can_reach_floor()) { - if ((multi && !flags.run) || (autopickup && !flags.pickup)) - read_engr_at(u.ux, u.uy); - return (0); - } + /* no pickup if levitating & not on air or water level */ + if (!can_reach_floor()) { + if ((multi && !flags.run) || (autopickup && !flags.pickup)) + read_engr_at(u.ux, u.uy); + return (0); + } - /* multi && !flags.run means they are in the middle of some other - * action, or possibly paralyzed, sleeping, etc.... and they just - * teleported onto the object. They shouldn't pick it up. - */ - if ((multi && !flags.run) || (autopickup && !flags.pickup)) { - check_here(FALSE); - return (0); - } + /* multi && !flags.run means they are in the middle of some other + * action, or possibly paralyzed, sleeping, etc.... and they just + * teleported onto the object. They shouldn't pick it up. + */ + if ((multi && !flags.run) || (autopickup && !flags.pickup)) { + check_here(FALSE); + return (0); + } + if (notake(youmonst.data)) { + if (!autopickup) + You("are physically incapable of picking anything up."); + else + check_here(FALSE); + return (0); + } - if (notake(youmonst.data)) { - if (!autopickup) - You("are physically incapable of picking anything up."); - else - check_here(FALSE); - return (0); + /* if there's anything here, stop running */ + if (OBJ_AT(u.ux,u.uy) && flags.run && flags.run != 8 && !flags.nopick) nomul(0); } - /* if there's anything here, stop running */ - if (OBJ_AT(u.ux,u.uy) && flags.run && !flags.nopick) nomul(0); - add_valid_menu_class(0); /* reset */ + if (!u.uswallow) { + objchain = level.objects[u.ux][u.uy]; + traverse_how = BY_NEXTHERE; + } else { + objchain = u.ustuck->minvent; + traverse_how = 0; /* nobj */ + } /* * Start the actual pickup process. This is split into two main * sections, the newer menu and the older "traditional" methods. @@ -379,7 +433,7 @@ int what; /* should be a long */ * to make things less confusing. */ if (autopickup) { - n = autopick(level.objects[u.ux][u.uy], BY_NEXTHERE, &pick_list); + n = autopick(objchain, traverse_how, &pick_list); goto menu_pickup; } @@ -390,15 +444,15 @@ int what; /* should be a long */ char buf[QBUFSZ]; Sprintf(buf, "Pick %d of what?", count); val_for_n_or_more = count; /* set up callback selector */ - n = query_objlist(buf, level.objects[u.ux][u.uy], - BY_NEXTHERE|AUTOSELECT_SINGLE|INVORDER_SORT, + n = query_objlist(buf, objchain, + traverse_how|AUTOSELECT_SINGLE|INVORDER_SORT, &pick_list, PICK_ONE, n_or_more); /* correct counts, if any given */ for (i = 0; i < n; i++) pick_list[i].count = count; } else { - n = query_objlist("Pick up what?", level.objects[u.ux][u.uy], - BY_NEXTHERE|AUTOSELECT_SINGLE|INVORDER_SORT, + n = query_objlist("Pick up what?", objchain, + traverse_how|AUTOSELECT_SINGLE|INVORDER_SORT, &pick_list, PICK_ANY, all_but_uchain); } menu_pickup: @@ -424,12 +478,13 @@ int what; /* should be a long */ selective = FALSE; /* ask for each item */ /* check for more than one object */ - for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere) + for (obj = objchain; + obj; obj = (traverse_how == BY_NEXTHERE) ? obj->nexthere : obj->nobj) ct++; if (ct == 1 && count) { /* if only one thing, then pick it */ - obj = level.objects[u.ux][u.uy]; + obj = objchain; lcount = min(obj->quan, (long)count); n_tried++; if (pickup_object(obj, lcount, FALSE) > 0) @@ -442,20 +497,27 @@ int what; /* should be a long */ There("are %s objects here.", (ct <= 10) ? "several" : "many"); if (!query_classes(oclasses, &selective, &all_of_a_type, - "pick up", level.objects[u.ux][u.uy], - TRUE, FALSE, &via_menu)) { + "pick up", objchain, + traverse_how == BY_NEXTHERE, +#ifndef GOLDOBJ + FALSE, +#endif + &via_menu)) { if (!via_menu) return (0); n = query_objlist("Pick up what?", - level.objects[u.ux][u.uy], - BY_NEXTHERE|(selective ? 0 : INVORDER_SORT), + objchain, + traverse_how|(selective ? 0 : INVORDER_SORT), &pick_list, PICK_ANY, via_menu == -2 ? allow_all : allow_category); goto menu_pickup; } } - for (obj = level.objects[u.ux][u.uy]; obj; obj = obj2) { - obj2 = obj->nexthere; /* perhaps obj will be picked up */ + for (obj = objchain; obj; obj = obj2) { + if (traverse_how == BY_NEXTHERE) + obj2 = obj->nexthere; /* perhaps obj will be picked up */ + else + obj2 = obj->nobj; lcount = -1L; if (!selective && oclasses[0] && !index(oclasses,obj->oclass)) @@ -494,11 +556,15 @@ int what; /* should be a long */ ; /* semicolon needed by brain-damaged compilers */ } - /* position may need updating (invisible hero) */ - if (n_picked) newsym(u.ux,u.uy); + if (!u.uswallow) { + if (!OBJ_AT(u.ux,u.uy)) u.uundetected = 0; + + /* position may need updating (invisible hero) */ + if (n_picked) newsym(u.ux,u.uy); - /* see whether there's anything else here, after auto-pickup is done */ - if (autopickup) check_here(n_picked > 0); + /* see whether there's anything else here, after auto-pickup is done */ + if (autopickup) check_here(n_picked > 0); + } return (n_tried > 0); } @@ -662,14 +728,33 @@ int how; /* type of query */ char invlet; int ccount; boolean do_unpaid = FALSE; + boolean do_blessed = FALSE, do_cursed = FALSE, do_uncursed = FALSE, + do_buc_unknown = FALSE; + int num_buc_types = 0; *pick_list = (menu_item *) 0; if (!olist) return 0; if ((qflags & UNPAID_TYPES) && count_unpaid(olist)) do_unpaid = TRUE; + if ((qflags & BUC_BLESSED) && count_buc(olist, BUC_BLESSED)) { + do_blessed = TRUE; + num_buc_types++; + } + if ((qflags & BUC_CURSED) && count_buc(olist, BUC_CURSED)) { + do_cursed = TRUE; + num_buc_types++; + } + if ((qflags & BUC_UNCURSED) && count_buc(olist, BUC_UNCURSED)) { + do_uncursed = TRUE; + num_buc_types++; + } + if ((qflags & BUC_UNKNOWN) && count_buc(olist, BUC_UNKNOWN)) { + do_buc_unknown = TRUE; + num_buc_types++; + } ccount = count_categories(olist, qflags); /* no point in actually showing a menu for a single category */ - if (ccount == 1 && !do_unpaid && !(qflags & BILLED_TYPES)) { + if (ccount == 1 && !do_unpaid && num_buc_types <= 1 && !(qflags & BILLED_TYPES)) { for (curr = olist; curr; curr = FOLLOW(curr, qflags)) { if ((qflags & WORN_TYPES) && !(curr->owornmask & (W_ARMOR|W_RING|W_AMUL|W_TOOL|W_WEP|W_SWAPWEP|W_QUIVER))) @@ -751,6 +836,36 @@ int how; /* type of query */ "Auto-select every item being worn" : "Auto-select every item", MENU_UNSELECTED); } + /* items with b/u/c/unknown if there are any */ + if (do_blessed) { + invlet = 'B'; + any.a_void = 0; + any.a_int = 'B'; + add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE, + "Items known to be Blessed", MENU_UNSELECTED); + } + if (do_cursed) { + invlet = 'C'; + any.a_void = 0; + any.a_int = 'C'; + add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE, + "Items known to be Cursed", MENU_UNSELECTED); + } + if (do_uncursed) { + invlet = 'U'; + any.a_void = 0; + any.a_int = 'U'; + add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE, + "Items known to be Uncursed", MENU_UNSELECTED); + } + if (do_buc_unknown) { + invlet = 'X'; + any.a_void = 0; + any.a_int = 'X'; + add_menu(win, NO_GLYPH, &any, invlet, 0, ATR_NONE, + "Items of unknown B/C/U status", + MENU_UNSELECTED); + } end_menu(win, qstr); n = select_menu(win, how, pick_list); destroy_nhwindow(win); @@ -801,13 +916,18 @@ int *wt_before, *wt_after; is_gold = obj->oclass == GOLD_CLASS; int wt, iw, ow, oow; long qq, savequan; +#ifdef GOLDOBJ + long umoney = money_cnt(invent); +#endif unsigned saveowt; const char *verb, *prefx1, *prefx2, *suffx; char obj_nambuf[BUFSZ], where[BUFSZ]; savequan = obj->quan; saveowt = obj->owt; + iw = max_capacity(); + if (count != savequan) { obj->quan = count; obj->owt = (unsigned)weight(obj); @@ -816,30 +936,50 @@ int *wt_before, *wt_after; if (adjust_wt) wt -= (container->otyp == BAG_OF_HOLDING) ? (int)DELTA_CWT(container, obj) : (int)obj->owt; +#ifndef GOLDOBJ if (is_gold) /* merged gold might affect cumulative weight */ wt -= (GOLD_WT(u.ugold) + GOLD_WT(count) - GOLD_WT(u.ugold + count)); +#else + /* This will go with silver+copper & new gold weight */ + if (is_gold) /* merged gold might affect cumulative weight */ + wt -= (GOLD_WT(umoney) + GOLD_WT(count) - GOLD_WT(umoney + count)); +#endif if (count != savequan) { obj->quan = savequan; obj->owt = saveowt; } *wt_before = iw; *wt_after = wt; + if (wt < 0) return count; /* see how many we can lift */ if (is_gold) { +#ifndef GOLDOBJ iw -= (int)GOLD_WT(u.ugold); if (!adjust_wt) { qq = GOLD_CAPACITY((long)iw, u.ugold); } else { oow = 0; qq = 50L - (u.ugold % 100L) - 1L; +#else + iw -= (int)GOLD_WT(umoney); + if (!adjust_wt) { + qq = GOLD_CAPACITY((long)iw, umoney); + } else { + oow = 0; + qq = 50L - (umoney % 100L) - 1L; +#endif if (qq < 0L) qq += 100L; for ( ; qq <= count; qq += 100L) { obj->quan = qq; obj->owt = (unsigned)GOLD_WT(qq); +#ifndef GOLDOBJ ow = (int)GOLD_WT(u.ugold + qq); +#else + ow = (int)GOLD_WT(umoney + qq); +#endif ow -= (container->otyp == BAG_OF_HOLDING) ? (int)DELTA_CWT(container, obj) : (int)obj->owt; if (iw + ow >= 0) break; @@ -850,7 +990,11 @@ int *wt_before, *wt_after; } if (qq < 0L) qq = 0L; else if (qq > count) qq = count; +#ifndef GOLDOBJ wt = iw + (int)GOLD_WT(u.ugold + qq); +#else + wt = iw + (int)GOLD_WT(umoney + qq); +#endif } else if (count > 1 || count < obj->quan) { /* * Ugh. Calc num to lift by changing the quan of of the @@ -902,7 +1046,11 @@ int *wt_before, *wt_after; } if (!container) Strcpy(where, "here"); /* slightly shorter form */ +#ifndef GOLDOBJ if (invent || u.ugold) { +#else + if (invent || umoney) { +#endif prefx1 = "you cannot "; prefx2 = ""; suffx = " any more"; @@ -912,7 +1060,7 @@ int *wt_before, *wt_after; suffx = ""; } There("%s %s %s, but %s%s%s%s.", - (obj->quan == 1L) ? "is" : "are", obj_nambuf, where, + otense(obj, "are"), obj_nambuf, where, prefx1, prefx2, verb, suffx); /* *wt_after = iw; */ @@ -921,14 +1069,14 @@ int *wt_before, *wt_after; /* determine whether character is able and player is willing to carry `obj' */ STATIC_OVL -int lift_object(obj, container, cnt_p, telekinesis) +int +lift_object(obj, container, cnt_p, telekinesis) struct obj *obj, *container; /* object to pick up, bag it's coming out of */ long *cnt_p; boolean telekinesis; { int result, old_wt, new_wt, prev_encumbr, next_encumbr; - if (obj->otyp == BOULDER && In_sokoban(&u.uz)) { You("cannot get your %s around this %s.", body_part(HAND), xname(obj)); @@ -941,8 +1089,12 @@ boolean telekinesis; *cnt_p = carry_count(obj, container, *cnt_p, telekinesis, &old_wt, &new_wt); if (*cnt_p < 1L) { result = -1; /* nothing lifted */ +#ifndef GOLDOBJ } else if (obj->oclass != GOLD_CLASS && inv_cnt() >= 52 && !merge_choice(invent, obj)) { +#else + } else if (inv_cnt() >= 52 && !merge_choice(invent, obj)) { +#endif Your("knapsack cannot accommodate any more items."); result = -1; /* nothing lifted */ } else { @@ -990,8 +1142,10 @@ long count; boolean telekinesis; /* not picking it up directly by hand */ { int res, nearload; +#ifndef GOLDOBJ const char *where = (obj->ox == u.ux && obj->oy == u.uy) ? "here" : "there"; +#endif if (obj->quan < count) { impossible("pickup_object: count %ld > quan %ld?", @@ -1011,6 +1165,7 @@ boolean telekinesis; /* not picking it up directly by hand */ return 0; } else if (obj->oartifact && !touch_artifact(obj,&youmonst)) { return 0; +#ifndef GOLDOBJ } else if (obj->oclass == GOLD_CLASS) { /* Special consideration for gold pieces... */ long iw = (long)max_capacity() - GOLD_WT(u.ugold); @@ -1019,7 +1174,7 @@ boolean telekinesis; /* not picking it up directly by hand */ if (gold_capacity <= 0L) { pline( "There %s %ld gold piece%s %s, but you cannot carry any more.", - (obj->quan == 1L) ? "is" : "are", + otense(obj, "are"), obj->quan, plur(obj->quan), where); return 0; } else if (gold_capacity < count) { @@ -1049,17 +1204,17 @@ boolean telekinesis; /* not picking it up directly by hand */ flags.botl = 1; if (flags.run) nomul(0); return 1; +#endif } else if (obj->otyp == CORPSE) { - if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg + if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg && !Stone_resistance && !telekinesis) { if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) display_nhwindow(WIN_MESSAGE, FALSE); else { char kbuf[BUFSZ]; - pline("Touching %s corpse is a fatal mistake.", - an(mons[obj->corpsenm].mname)); - Sprintf(kbuf, "%s corpse", an(mons[obj->corpsenm].mname)); + Strcpy(kbuf, an(corpse_xname(obj, TRUE))); + pline("Touching %s is a fatal mistake.", kbuf); instapetrify(kbuf); return -1; } @@ -1074,8 +1229,8 @@ boolean telekinesis; /* not picking it up directly by hand */ if (obj->blessed) obj->blessed = 0; else if (!obj->spe && !obj->cursed) obj->spe = 1; else { - pline_The("scroll%s turn%s to dust as you %s %s up.", - plur(obj->quan), (obj->quan == 1L) ? "s" : "", + pline_The("scroll%s %s to dust as you %s %s up.", + plur(obj->quan), otense(obj, "turn"), telekinesis ? "raise" : "pick", (obj->quan == 1L) ? "it" : "them"); if (!(objects[SCR_SCARE_MONSTER].oc_name_known) && @@ -1090,14 +1245,19 @@ boolean telekinesis; /* not picking it up directly by hand */ if ((res = lift_object(obj, (struct obj *)0, &count, telekinesis)) <= 0) return res; +#ifdef GOLDOBJ + /* Whats left of the special case for gold :-) */ + if (obj->oclass == GOLD_CLASS) flags.botl = 1; +#endif if (obj->quan != count && obj->otyp != LOADSTONE) - (void) splitobj(obj, count); + obj = splitobj(obj, count); obj = pick_obj(obj); if (uwep && uwep == obj) mrg_to_wielded = TRUE; nearload = near_capacity(); - prinv(nearload == SLT_ENCUMBER ? moderateloadmsg : (char *) 0, obj, count); + prinv(nearload == SLT_ENCUMBER ? moderateloadmsg : (char *) 0, + obj, count); mrg_to_wielded = FALSE; return 1; } @@ -1108,19 +1268,35 @@ boolean telekinesis; /* not picking it up directly by hand */ * pointer to the object where otmp ends up. This may be different * from otmp because of merging. * - * Gold never reaches this routine. + * Gold never reaches this routine unless GOLDOBJ is defined. */ struct obj * pick_obj(otmp) -register struct obj *otmp; +struct obj *otmp; { obj_extract_self(otmp); - if (*u.ushops && costly_spot(u.ux, u.uy) && - otmp != uball) /* don't charge for this - kd, 1/17/90 */ - /* sets obj->unpaid if necessary */ + if (otmp->no_charge) { + /* this attribute only applies to objects outside invent */ + otmp->no_charge = 0; + } else if (otmp != uball && costly_spot(otmp->ox, otmp->oy)) { + char saveushops[5], fakeshop[2]; + + /* addtobill cares about your location rather than the object's; + usually they'll be the same, but not when using telekinesis + (if ever implemented) or a grappling hook */ + Strcpy(saveushops, u.ushops); + fakeshop[0] = *in_rooms(otmp->ox, otmp->oy, SHOPBASE); + fakeshop[1] = '\0'; + Strcpy(u.ushops, fakeshop); + /* sets obj->unpaid if necessary */ addtobill(otmp, TRUE, FALSE, FALSE); - if(Invisible) newsym(u.ux,u.uy); - return(addinv(otmp)); /* might merge it with other objects */ + Strcpy(u.ushops, saveushops); + /* if you're outside the shop, make shk notice */ + if (!index(u.ushops, *fakeshop)) + remote_burglary(otmp->ox, otmp->oy); + } + if (Invisible) newsym(otmp->ox, otmp->oy); + return addinv(otmp); /* might merge it with other objects */ } /* @@ -1139,7 +1315,8 @@ encumber_msg() break; case 2: You("rebalance your load. Movement is difficult."); break; - case 3: You("stagger under your heavy load. Movement is very hard."); + case 3: You("%s under your heavy load. Movement is very hard.", + stagger(youmonst.data, "stagger")); break; default: You("%s move a handspan with this load!", newcap == 4 ? "can barely" : "can't even"); @@ -1154,7 +1331,8 @@ encumber_msg() break; case 2: You("rebalance your load. Movement is still difficult."); break; - case 3: You("stagger under your load. Movement is still very hard."); + case 3: You("%s under your load. Movement is still very hard.", + stagger(youmonst.data, "stagger")); break; } flags.botl = 1; @@ -1234,16 +1412,17 @@ doloot() /* loot a container on the floor. */ const char *dont_find_anything = "don't find anything"; struct monst *mtmp; char qbuf[QBUFSZ]; -#ifdef STEED - struct obj *otmp; - boolean saddled_there = FALSE; - boolean got_saddle = FALSE; -#endif + int prev_inquiry = 0; + boolean prev_loot = FALSE; if (check_capacity((char *)0)) { /* "Can't do that while carrying so much stuff." */ return 0; } + if (nohands(youmonst.data)) { + You("have no hands!"); /* not `body_part(HAND)' */ + return 0; + } x = u.ux; y = u.uy; lootcont: @@ -1264,11 +1443,12 @@ doloot() /* loot a container on the floor. */ continue; } if (cobj->otyp == BAG_OF_TRICKS) { + int tmp; You("carefully open the bag..."); pline("It develops a huge set of teeth and bites you!"); - c = rnd(10); - if (Half_physical_damage) c = (c+1) / 2; - losehp(c, "carnivorous bag", KILLED_BY_AN); + tmp = rnd(10); + if (Half_physical_damage) tmp = (tmp+1) / 2; + losehp(tmp, "carnivorous bag", KILLED_BY_AN); makeknown(BAG_OF_TRICKS); timepassed = 1; continue; @@ -1280,9 +1460,22 @@ doloot() /* loot a container on the floor. */ } } } else if (Confusion) { +#ifndef GOLDOBJ if (u.ugold){ long contribution = rnd((int)min(LARGEST_INT,u.ugold)); struct obj *goldob = mkgoldobj(contribution); +#else + struct obj *goldob; + /* Find a money object to mess with */ + for (goldob = invent; goldob; goldob = goldob->nobj) { + if (goldob->oclass == GOLD_CLASS) break; + } + if (goldob){ + long contribution = rnd((int)min(LARGEST_INT, goldob->quan)); + if (contribution < goldob->quan) + goldob = splitobj(goldob, contribution); + freeinv(goldob); +#endif if (IS_THRONE(levl[u.ux][u.uy].typ)){ struct obj *coffers; int pass; @@ -1292,22 +1485,15 @@ doloot() /* loot a container on the floor. */ if (coffers->otyp == CHEST && coffers->spe == pass) goto gotit; /* two level break */ gotit: - if (coffers){ - struct obj *tmp; + if (coffers) { verbalize("Thank you for your contribution to reduce the debt."); - for (tmp = coffers->cobj; tmp; tmp = tmp->nobj) - if (tmp->otyp == goldob->otyp) break; - - if (tmp) { - tmp->quan += goldob->quan; - delobj(goldob); - } else { - add_to_container(coffers, goldob); - } + (void) add_to_container(coffers, goldob); + coffers->owt = weight(coffers); } else { struct monst *mon = makemon(courtmon(), u.ux, u.uy, NO_MM_FLAGS); if (mon) { +#ifndef GOLDOBJ mon->mgold += goldob->quan; delobj(goldob); pline("The exchequer accepts your contribution."); @@ -1317,6 +1503,16 @@ doloot() /* loot a container on the floor. */ } } else { dropx(goldob); +#else + add_to_minv(mon, goldob); + pline("The exchequer accepts your contribution."); + } else { + dropy(goldob); + } + } + } else { + dropy(goldob); +#endif pline("Ok, now there is loot here."); } } @@ -1346,14 +1542,57 @@ doloot() /* loot a container on the floor. */ return timepassed; } mtmp = m_at(x, y); + if (mtmp) timepassed = loot_mon(mtmp, &prev_inquiry, &prev_loot); + + /* Preserve pre-3.3.1 behaviour for containers. + * Adjust this if-block to allow container looting + * from one square away to change that in the future. + */ + if (!underfoot) { + if (container_at(x, y, FALSE)) { + if (mtmp) { + You_cant("loot anything %sthere with %s in the way.", + prev_inquiry ? "else " : "", mon_nam(mtmp)); + return timepassed; + } else { + You("have to be at a container to loot it."); + } + } else { + You("%s %sthere to loot.", dont_find_anything, + (prev_inquiry || prev_loot) ? "else " : ""); + return timepassed; + } + } + } else if (c != 'y' && c != 'n') { + You("%s %s to loot.", dont_find_anything, + underfoot ? "here" : "there"); + } + return (timepassed); +} + +/* loot_mon() returns amount of time passed. + */ +int +loot_mon(mtmp, passed_info, prev_loot) +struct monst *mtmp; +int *passed_info; +boolean *prev_loot; +{ + int c = -1; + int timepassed = 0; #ifdef STEED - /* 3.3.1 introduced the ability to remove saddle from a steed */ - if (mtmp && mtmp != u.usteed && (otmp = which_armor(mtmp, W_SADDLE))) { - long unwornmask; - saddled_there = TRUE; - Sprintf(qbuf, "Do you want to remove the saddle from %s?", + struct obj *otmp; + char qbuf[QBUFSZ]; + + /* 3.3.1 introduced the ability to remove saddle from a steed */ + /* *passed_info is set to TRUE if a loot query was given. */ + /* *prev_loot is set to TRUE if something was actually acquired in here. */ + if (mtmp && mtmp != u.usteed && (otmp = which_armor(mtmp, W_SADDLE))) { + long unwornmask; + if (passed_info) *passed_info = 1; + Sprintf(qbuf, "Do you want to remove the saddle from %s?", x_monnam(mtmp, ARTICLE_THE, (char *)0, SUPPRESS_SADDLE, FALSE)); - if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') { + if ((c = yn_function(qbuf, ynqchars, 'n')) == 'y') { if (nolimbs(youmonst.data)) { You_cant("do that without limbs."); /* not body_part(HAND) */ return (0); @@ -1375,69 +1614,18 @@ doloot() /* loot a container on the floor. */ otmp = hold_another_object(otmp, "You drop %s!", doname(otmp), (const char *)0); timepassed = rnd(3); - got_saddle = TRUE; - } else if (c == 'q') { + if (prev_loot) *prev_loot = TRUE; + } else if (c == 'q') { return (0); - } } -# if 0 - /* Loot your steed, even if you can't reach the floor */ - if (u.usteed) { - Sprintf(qbuf, "Do you want to loot %s inventory?", - s_suffix(x_monnam(u.usteed, ARTICLE_YOUR, - (char *)0, SUPPRESS_SADDLE, FALSE))); - switch (c = ynq(qbuf)) { - case 'y': - if (!u.usteed->minvent) { - impossible("no saddle?"); - break; - } - /* TO DO: get and put things into the inventory */ - You("peek at %s inventory...", - s_suffix(x_monnam(u.usteed, ARTICLE_YOUR, - (char *)0, SUPPRESS_SADDLE, FALSE))); - (void) display_minventory(u.usteed, MINV_ALL); - timepassed = 1; - break; - case 'n': - break; - case 'q': - return (0); - } - } -# endif + } #endif /* STEED */ - - /* Preserve pre-3.3.1 behaviour for containers. - * Adjust this if-block to allow container looting - * from one square away to change that in the future. - */ - if (!underfoot) { - if (container_at(x, y, FALSE)) { - if (mtmp) { - You("can't loot anything %sthere with %s in the way.", -#ifdef STEED - saddled_there ? "else " : -#endif - "", mon_nam(mtmp)); - return timepassed; - } else { - You("have to be at a container to loot it."); - } - } else { - You("%s %sthere to loot.", dont_find_anything, -#ifdef STEED - (saddled_there || got_saddle) ? "else " : -#endif - ""); - return timepassed; - } - } - } else if (c != 'y' && c != 'n') { - You("%s %s to loot.", dont_find_anything, - underfoot ? "here" : "there"); + /* 3.4.0 introduced the ability to pick things up from within swallower's stomach */ + if (u.uswallow) { + int count = passed_info ? *passed_info : 0; + timepassed = pickup(count); } - return (timepassed); + return timepassed; } /* @@ -1477,7 +1665,6 @@ STATIC_PTR int in_container(obj) register struct obj *obj; { - register struct obj *gold; boolean is_gold = (obj->oclass == GOLD_CLASS); boolean floor_container = !carried(current_container); char buf[BUFSZ]; @@ -1510,7 +1697,7 @@ register struct obj *obj; pline("%s cannot be confined in such trappings.", The(xname(obj))); return 0; } else if (obj->otyp == LEASH && obj->leashmon != 0) { - pline("%s is attached to your pet.", The(xname(obj))); + pline("%s attached to your pet.", Tobjnam(obj, "are")); return 0; } else if (obj == uwep) { if (welded(obj)) { @@ -1527,6 +1714,22 @@ register struct obj *obj; if (uquiver) return 0; /* unwielded, died, rewielded */ } + if (obj->otyp == CORPSE) { + if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg + && !Stone_resistance) { + if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) + display_nhwindow(WIN_MESSAGE, FALSE); + else { + char kbuf[BUFSZ]; + + Strcpy(kbuf, an(corpse_xname(obj, TRUE))); + pline("Touching %s is a fatal mistake.", kbuf); + instapetrify(kbuf); + return -1; + } + } + } + /* boxes, boulders, and big statues can't fit into any container */ if (obj->otyp == ICE_BOX || Is_box(obj) || obj->otyp == BOULDER || (obj->otyp == STATUE && bigmonst(&mons[obj->corpsenm]))) { @@ -1544,39 +1747,24 @@ register struct obj *obj; freeinv(obj); - if (is_gold) { /* look for other money to merge within the container */ - for (gold = current_container->cobj; gold; gold = gold->nobj) - if (gold->otyp == obj->otyp) break; - } else - gold = 0; - - if (gold) { - gold->quan += obj->quan; - } else { - add_to_container(current_container, obj); - } - - current_container->owt = weight(current_container); - - Strcpy(buf, the(xname(current_container))); - You("put %s into %s.", doname(obj), buf); - if (obj_is_burning(obj)) /* this used to be part of freeinv() */ (void) snuff_lit(obj); if (floor_container && costly_spot(u.ux, u.uy)) { - sellobj_state(TRUE); + sellobj_state(SELL_DELIBERATE); sellobj(obj, u.ux, u.uy); - sellobj_state(FALSE); + sellobj_state(SELL_NORMAL); } if (Icebox && obj->otyp != OIL_LAMP && obj->otyp != BRASS_LANTERN && !Is_candle(obj)) { obj->age = monstermoves - obj->age; /* actual age */ /* stop any corpse timeouts when frozen */ if (obj->otyp == CORPSE && obj->timed) { - (void) stop_timer(ROT_CORPSE, (genericptr_t)obj); + long rot_alarm = stop_timer(ROT_CORPSE, (genericptr_t)obj); (void) stop_timer(REVIVE_MON, (genericptr_t)obj); - } + /* mark a non-reviving corpse as such */ + if (rot_alarm) obj->norevive = 1; + } } else if (Is_mbag(current_container) && mbag_explodes(obj, 0)) { @@ -1590,6 +1778,8 @@ register struct obj *obj; (void)stolen_value(current_container, u.ux, u.uy, (boolean)shkp->mpeaceful, FALSE); } + /* did not actually insert obj yet */ + obfree(obj, (struct obj *)0); delete_contents(current_container); if (!floor_container) useup(current_container); @@ -1602,10 +1792,14 @@ register struct obj *obj; current_container = 0; /* baggone = TRUE; */ } - if (is_gold) { - if (gold) dealloc_obj(obj); - bot(); /* update character's gold piece count immediately */ + if (current_container) { + Strcpy(buf, the(xname(current_container))); + You("put %s into %s.", doname(obj), buf); + + (void) add_to_container(current_container, obj); + current_container->owt = weight(current_container); } + if (is_gold) bot(); /* update gold piece count immediately */ return(current_container ? 1 : -1); } @@ -1636,12 +1830,28 @@ register struct obj *obj; if(obj->oartifact && !touch_artifact(obj,&youmonst)) return 0; + if (obj->otyp == CORPSE) { + if ( (touch_petrifies(&mons[obj->corpsenm])) && !uarmg + && !Stone_resistance) { + if (poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM)) + display_nhwindow(WIN_MESSAGE, FALSE); + else { + char kbuf[BUFSZ]; + + Strcpy(kbuf, an(corpse_xname(obj, TRUE))); + pline("Touching %s is a fatal mistake.", kbuf); + instapetrify(kbuf); + return -1; + } + } + } + count = obj->quan; if ((res = lift_object(obj, current_container, &count, FALSE)) <= 0) return res; if (obj->quan != count && obj->otyp != LOADSTONE) - (void) splitobj(obj, count); + obj = splitobj(obj, count); /* Remove the object from the list. */ obj_extract_self(obj); @@ -1674,7 +1884,9 @@ register struct obj *obj; otmp, count); if (is_gold) { +#ifndef GOLDOBJ dealloc_obj(obj); +#endif bot(); /* update character's gold piece count immediately */ } return 1; @@ -1687,7 +1899,10 @@ use_container(obj, held) register struct obj *obj; register int held; { - struct obj *curr, *otmp, *u_gold = (struct obj *)0; + struct obj *curr, *otmp; +#ifndef GOLDOBJ + struct obj *u_gold = (struct obj *)0; +#endif struct monst *shkp; boolean one_by_one, allflag, loot_out = FALSE, loot_in = FALSE; char select[MAXOCLASSES+1]; @@ -1697,7 +1912,7 @@ register int held; menu_on_request; if (obj->olocked) { - pline("%s seems to be locked.", The(xname(obj))); + pline("%s to be locked.", Tobjnam(obj, "seem")); if (held) You("must put it down to unlock."); return 0; } else if (obj->otrapped) { @@ -1738,7 +1953,8 @@ register int held; obj->ox, obj->oy, sc); if (ocat) { obj_extract_self(ocat); - add_to_container(obj, ocat); /* weight handled below */ + (void) add_to_container(obj, ocat); + /* weight handled below */ } pline_The("%s inside the box is dead!", Hallucination ? rndmonnam() : "housecat"); @@ -1777,13 +1993,13 @@ register int held; } if (cnt && loss) - You("owe %ld zorkmids for lost item%s.", - loss, lcnt > 1 ? "s" : ""); + You("owe %ld %s for lost item%s.", + loss, currency(loss), lcnt > 1 ? "s" : ""); obj->owt = weight(obj); if (!cnt) { - pline("%s is empty.", Yname2(obj)); + pline("%s %s empty.", Yname2(obj), otense(obj, "are")); } else { Sprintf(qbuf, "Do you want to take %s out of %s?", something, yname(obj)); @@ -1812,7 +2028,11 @@ register int held; case 'y': if (query_classes(select, &one_by_one, &allflag, "take out", current_container->cobj, - FALSE, FALSE, &menu_on_request)) { + FALSE, +#ifndef GOLDOBJ + FALSE, +#endif + &menu_on_request)) { if (askchain((struct obj **)¤t_container->cobj, (one_by_one ? (char *)0 : select), allflag, out_container, @@ -1833,7 +2053,11 @@ register int held; } } +#ifndef GOLDOBJ if (!invent && u.ugold == 0) { +#else + if (!invent) { +#endif /* nothing to put in, but some feedback is necessary */ You("don't have anything to put in."); return used; @@ -1847,6 +2071,7 @@ register int held; * putting things in an ice chest. */ if (loot_in) { +#ifndef GOLDOBJ if (u.ugold) { /* * Hack: gold is not in the inventory, so make a gold object @@ -1858,6 +2083,7 @@ register int held; u_gold->nobj = invent; invent = u_gold; } +#endif add_valid_menu_class(0); /* reset */ if (flags.menu_style != MENU_TRADITIONAL) { used |= menu_loot(0, current_container, TRUE) > 0; @@ -1865,7 +2091,10 @@ register int held; /* traditional code */ menu_on_request = 0; if (query_classes(select, &one_by_one, &allflag, "put in", - invent, FALSE, (u.ugold != 0L), + invent, FALSE, +#ifndef GOLDOBJ + (u.ugold != 0L), +#endif &menu_on_request)) { (void) askchain((struct obj **)&invent, (one_by_one ? (char *)0 : select), allflag, @@ -1878,13 +2107,14 @@ register int held; } } +#ifndef GOLDOBJ if (u_gold && invent && invent->oclass == GOLD_CLASS) { /* didn't stash [all of] it */ u_gold = invent; invent = u_gold->nobj; dealloc_obj(u_gold); } - +#endif return used; } @@ -1909,7 +2139,8 @@ boolean put_in; } else if (flags.menu_style == MENU_FULL) { all_categories = FALSE; Sprintf(buf,"%s what type of objects?", put_in ? putin : takeout); - mflags = put_in ? ALL_TYPES : ALL_TYPES|CHOOSE_ALL; + mflags = put_in ? ALL_TYPES | BUC_ALLBKNOWN | BUC_UNKNOWN : + ALL_TYPES | CHOOSE_ALL | BUC_ALLBKNOWN | BUC_UNKNOWN; n = query_category(buf, put_in ? invent : container->cobj, mflags, &pick_list, PICK_ANY); if (!n) return 0; @@ -1943,11 +2174,8 @@ boolean put_in; otmp = pick_list[i].item.a_obj; count = pick_list[i].count; if (count > 0 && count < otmp->quan) { - otmp2 = splitobj(otmp, count); + otmp = splitobj(otmp, count); /* special split case also handled by askchain() */ - if (otmp == uwep) setuwep(otmp2); - if (otmp == uquiver) setuqwep(otmp2); - if (otmp == uswapwep) setuswapwep(otmp2); } res = put_in ? in_container(otmp) : out_container(otmp); if (res < 0) @@ -1975,12 +2203,12 @@ struct obj *obj; start_menu(win); any.a_int = 1; Sprintf(buf,"Take %s out of %s", something, the(xname(obj))); - add_menu(win, NO_GLYPH, &any, 'a', 0, ATR_NONE, buf, MENU_UNSELECTED); + add_menu(win, NO_GLYPH, &any, 'o', 0, ATR_NONE, buf, MENU_UNSELECTED); any.a_int = 2; Sprintf(buf,"Put %s into %s", something, the(xname(obj))); - add_menu(win, NO_GLYPH, &any, 'b', 0, ATR_NONE, buf, MENU_UNSELECTED); + add_menu(win, NO_GLYPH, &any, 'i', 0, ATR_NONE, buf, MENU_UNSELECTED); any.a_int = 3; - add_menu(win, NO_GLYPH, &any, 'c', 0, ATR_NONE, + add_menu(win, NO_GLYPH, &any, 'b', 0, ATR_NONE, "Both of the above", MENU_UNSELECTED); end_menu(win, prompt); n = select_menu(win, PICK_ONE, &pick_list); diff --git a/src/pline.c b/src/pline.c index b515b25..08a6d19 100644 --- a/src/pline.c +++ b/src/pline.c @@ -1,10 +1,13 @@ -/* SCCS Id: @(#)pline.c 3.3 1999/11/28 */ +/* SCCS Id: @(#)pline.c 3.4 1999/11/28 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #define NEED_VARARGS /* Uses ... */ /* comment line for pre-compiled headers */ #include "hack.h" #include "epri.h" +#ifdef WIZARD +#include "edog.h" +#endif #ifdef OVLB @@ -282,7 +285,13 @@ register struct monst *mtmp; info[0] = 0; if (mtmp->mtame) { Strcat(info, ", tame"); #ifdef WIZARD - if (wizard) Sprintf(eos(info), " (%d)", mtmp->mtame); + if (wizard) { + Sprintf(eos(info), " (%d", mtmp->mtame); + if (!mtmp->isminion) + Sprintf(eos(info), "; hungry %ld; apport %d", + EDOG(mtmp)->hungrytime, EDOG(mtmp)->apport); + Strcat(info, ")"); + } #endif } else if (mtmp->mpeaceful) Strcat(info, ", peaceful"); diff --git a/src/polyself.c b/src/polyself.c index 70e88a8..019c846 100644 --- a/src/polyself.c +++ b/src/polyself.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)polyself.c 3.3 2000/07/14 */ +/* SCCS Id: @(#)polyself.c 3.4 2002/01/15 */ /* Copyright (C) 1987, 1988, 1989 by Ken Arromdee */ /* NetHack may be freely redistributed. See license for details. */ @@ -16,7 +16,6 @@ STATIC_DCL void FDECL(polyman, (const char *,const char *)); STATIC_DCL void NDECL(break_armor); STATIC_DCL void FDECL(drop_weapon,(int)); -STATIC_DCL void NDECL(skinback); STATIC_DCL void NDECL(uunstick); STATIC_DCL int FDECL(armor_to_dragon,(int)); STATIC_DCL void NDECL(newman); @@ -48,7 +47,7 @@ const char *fmt, *arg; u.mh = u.mhmax = 0; u.mtimedone = 0; - skinback(); + skinback(FALSE); u.uundetected = 0; if (sticky) uunstick(); @@ -104,13 +103,15 @@ change_sex() boolean already_polyd = (boolean) Upolyd; /* Some monsters are always of one sex and their sex can't be changed */ - /* succubi/incubi are handled below */ - if (u.umonnum != PM_SUCCUBUS && u.umonnum != PM_INCUBUS && !is_male(youmonst.data) && !is_female(youmonst.data) && !is_neuter(youmonst.data)) + /* succubi/incubi can change, but are handled below */ + /* !already_polyd check necessary because is_male() and is_female() + are true if the player is a priest/priestess */ + if (!already_polyd || (!is_male(youmonst.data) && !is_female(youmonst.data) && !is_neuter(youmonst.data))) flags.female = !flags.female; if (already_polyd) /* poly'd: also change saved sex */ u.mfemale = !u.mfemale; max_rank_sz(); /* [this appears to be superfluous] */ - if (flags.female && urole.name.f) + if ((already_polyd ? u.mfemale : flags.female) && urole.name.f) Strcpy(pl_character, urole.name.f); else Strcpy(pl_character, urole.name.m); @@ -119,6 +120,7 @@ change_sex() if (!already_polyd) { u.umonnum = u.umonster; } else if (u.umonnum == PM_SUCCUBUS || u.umonnum == PM_INCUBUS) { + flags.female = !flags.female; /* change monster type to match new sex */ u.umonnum = (u.umonnum == PM_SUCCUBUS) ? PM_INCUBUS : PM_SUCCUBUS; set_uasmon(); @@ -128,24 +130,34 @@ change_sex() STATIC_OVL void newman() { - int tmp, tmp2; - - if (!rn2(10)) change_sex(); + int tmp, oldlvl; tmp = u.uhpmax; - tmp2 = u.ulevel; + oldlvl = u.ulevel; u.ulevel = u.ulevel + rn1(5, -2); - if (u.ulevel > 127 || u.ulevel < 1) u.ulevel = 1; + if (u.ulevel > 127 || u.ulevel < 1) { /* level went below 0? */ + u.ulevel = oldlvl; /* restore old level in case they lifesave */ + goto dead; + } if (u.ulevel > MAXULEV) u.ulevel = MAXULEV; + /* If your level goes down, your peak level goes down by + the same amount so that you can't simply use blessed + full healing to undo the decrease. But if your level + goes up, your peak level does *not* undergo the same + adjustment; you might end up losing out on the chance + to regain some levels previously lost to other causes. */ + if (u.ulevel < oldlvl) u.ulevelmax -= (oldlvl - u.ulevel); if (u.ulevelmax < u.ulevel) u.ulevelmax = u.ulevel; - adjabil(tmp2, (int)u.ulevel); + if (!rn2(10)) change_sex(); + + adjabil(oldlvl, (int)u.ulevel); reset_rndmonst(NON_PM); /* new monster generation criteria */ /* random experience points for the new experience level */ u.uexp = rndexp(); - /* u.uhpmax * u.ulevel / tmp2: proportionate hit points to new level + /* u.uhpmax * u.ulevel / oldlvl: proportionate hit points to new level * -10 and +10: don't apply proportionate HP to 10 of a starting * character's hit points (since a starting character's hit points * are not on the same scale with hit points obtained through level @@ -153,7 +165,7 @@ newman() * 9 - rn2(19): random change of -9 to +9 hit points */ #ifndef LINT - u.uhpmax = ((u.uhpmax - 10) * (long)u.ulevel / tmp2 + 10) + + u.uhpmax = ((u.uhpmax - 10) * (long)u.ulevel / oldlvl + 10) + (9 - rn2(19)); #endif @@ -165,7 +177,7 @@ newman() tmp = u.uenmax; #ifndef LINT - u.uenmax = u.uenmax * (long)u.ulevel / tmp2 + 9 - rn2(19); + u.uenmax = u.uenmax * (long)u.ulevel / oldlvl + 9 - rn2(19); #endif if (u.uenmax < 0) u.uenmax = 0; #ifndef LINT @@ -174,7 +186,6 @@ newman() redist_attr(); u.uhunger = rn1(500,500); - newuhs(FALSE); if (Sick) make_sick(0L, (char *) 0, FALSE, SICK_ALL); Stoned = 0; delayed_killer = 0; @@ -183,12 +194,16 @@ newman() if (u.uhp <= 0) u.uhp = 1; if (u.uhpmax <= 0) u.uhpmax = 1; } else { +dead: /* we come directly here if their experience level went to 0 or less */ Your("new form doesn't seem healthy enough to survive."); killer_format = KILLED_BY_AN; killer="unsuccessful polymorph"; done(DIED); + newuhs(FALSE); + return; /* lifesaved */ } } + newuhs(FALSE); polyman("feel like a new %s!", (flags.female && urace.individual.f) ? urace.individual.f : (urace.individual.m) ? urace.individual.m : urace.noun); @@ -202,7 +217,8 @@ newman() } void -polyself() +polyself(forcecontrol) +boolean forcecontrol; { char buf[BUFSZ]; int old_light, new_light; @@ -214,7 +230,7 @@ polyself() boolean iswere = (u.ulycn >= LOW_PM || is_were(youmonst.data)); boolean isvamp = (youmonst.data->mlet == S_VAMPIRE || u.umonnum == PM_VAMPIRE_BAT); - if(!Polymorph_control && !draconian && !iswere && !isvamp) { + if(!Polymorph_control && !forcecontrol && !draconian && !iswere && !isvamp) { if (rn2(20) > ACURR(A_CON)) { You(shudder_for_moment); losehp(rnd(30), "system shock", KILLED_BY_AN); @@ -224,7 +240,7 @@ polyself() } old_light = Upolyd ? emits_light(youmonst.data) : 0; - if (Polymorph_control) { + if (Polymorph_control || forcecontrol) { do { getlin("Become what kind of monster? [type the name]", buf); @@ -388,12 +404,14 @@ int mntmp; You("no longer feel sick."); } if (Slimed) { - if (mntmp == PM_FIRE_VORTEX || mntmp == PM_FIRE_ELEMENTAL) { + if (mntmp == PM_FIRE_VORTEX || mntmp == PM_FIRE_ELEMENTAL || mntmp == PM_SALAMANDER) { pline_The("slime burns away!"); - Slimed = 0; + Slimed = 0L; + flags.botl = 1; } else if (mntmp == PM_GREEN_SLIME) { /* do it silently */ - Slimed = 0; + Slimed = 0L; + flags.botl = 1; } } if (nohands(youmonst.data)) Glib = 0; @@ -428,7 +446,7 @@ int mntmp; } if (uskin && mntmp != armor_to_dragon(uskin->otyp)) - skinback(); + skinback(FALSE); break_armor(); drop_weapon(1); if (hides_under(youmonst.data)) @@ -470,8 +488,8 @@ int mntmp; pline(use_thec,monsterc,"spit venom"); if (youmonst.data->mlet == S_NYMPH) pline(use_thec,monsterc,"remove an iron ball"); - if (youmonst.data->mlet == S_UMBER) - pline(use_thec,monsterc,"confuse monsters"); + if (attacktype(youmonst.data, AT_GAZE)) + pline(use_thec,monsterc,"gaze at monsters"); if (is_hider(youmonst.data)) pline(use_thec,monsterc,"hide"); if (is_were(youmonst.data)) @@ -549,11 +567,11 @@ break_armor() } if ((otmp = uarmc) != 0) { if(otmp->oartifact) { - Your("cloak falls off!"); + Your("%s falls off!", cloak_simple_name(otmp)); (void) Cloak_off(); dropx(otmp); } else { - Your("cloak tears apart!"); + Your("%s tears apart!", cloak_simple_name(otmp)); (void) Cloak_off(); useup(otmp); } @@ -573,8 +591,8 @@ break_armor() } if ((otmp = uarmc) != 0) { if (is_whirly(youmonst.data)) - Your("cloak falls, unsupported!"); - else You("shrink out of your cloak!"); + Your("%s falls, unsupported!", cloak_simple_name(otmp)); + else You("shrink out of your %s!", cloak_simple_name(otmp)); (void) Cloak_off(); dropx(otmp); } @@ -628,6 +646,8 @@ drop_weapon(alone) int alone; { struct obj *otmp; + struct obj *otmp2; + if ((otmp = uwep) != 0) { /* !alone check below is currently superfluous but in the * future it might not be so if there are monsters which cannot @@ -638,10 +658,16 @@ int alone; if (alone) You("find you must drop your weapon%s!", u.twoweap ? "s" : ""); + otmp2 = u.twoweap ? uswapwep : 0; uwepgone(); if (!wep->cursed || wep->otyp != LOADSTONE) dropx(otmp); - untwoweapon(); + if (otmp2 != 0) { + uswapwepgone(); + if (!otmp2->cursed || otmp2->otyp != LOADSTONE) + dropx(otmp2); + } + untwoweapon(); } } } @@ -714,7 +740,7 @@ dospit() otmp = mksobj(u.umonnum==PM_COBRA ? BLINDING_VENOM : ACID_VENOM, TRUE, FALSE); otmp->spe = 1; /* to indicate it's yours */ - throwit(otmp, 0L); + throwit(otmp, 0L, FALSE); return(1); } @@ -806,9 +832,16 @@ dospinweb() deltrap(ttmp); if (Invisible) newsym(u.ux, u.uy); return 1; + case ROLLING_BOULDER_TRAP: + You("spin a web, jamming the trigger."); + deltrap(ttmp); + if (Invisible) newsym(u.ux, u.uy); + return(1); case ARROW_TRAP: case DART_TRAP: case BEAR_TRAP: + case ROCKTRAP: + case FIRE_TRAP: case LANDMINE: case SLP_GAS_TRAP: case RUST_TRAP: @@ -816,7 +849,7 @@ dospinweb() case ANTI_MAGIC: case POLY_TRAP: You("have triggered a trap!"); - dotrap(ttmp); + dotrap(ttmp, 0); return(1); default: impossible("Webbing over trap type %d?", ttmp->ttyp); @@ -849,15 +882,29 @@ dosummon() } int -doconfuse() +dogaze() { register struct monst *mtmp; int looked = 0; char qbuf[QBUFSZ]; + int i; + uchar adtyp = 0; + + for (i = 0; i < NATTK; i++) { + if(youmonst.data->mattk[i].aatyp == AT_GAZE) { + adtyp = youmonst.data->mattk[i].adtyp; + break; + } + } + if (adtyp != AD_CONF && adtyp != AD_FIRE) { + impossible("gaze attack %d?", adtyp); + return 0; + } + if (Blind) { - You_cant("see anything to gaze at."); - return 0; + You_cant("see anything to gaze at."); + return 0; } if (u.uen < 15) { You("lack the energy to use your special gaze!"); @@ -868,7 +915,7 @@ doconfuse() for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { if (DEADMONSTER(mtmp)) continue; - if (canseemon(mtmp)) { + if (canseemon(mtmp) && couldsee(mtmp->mx, mtmp->my)) { looked++; if (Invis && !perceives(mtmp->data)) pline("%s seems not to notice your gaze.", Monnam(mtmp)); @@ -884,7 +931,9 @@ doconfuse() } else { if (flags.confirm && mtmp->mpeaceful && !Confusion && !Hallucination) { - Sprintf(qbuf, "Really confuse %s?", mon_nam(mtmp)); + Sprintf(qbuf, "Really %s %s?", + (adtyp == AD_CONF) ? "confuse" : "attack", + mon_nam(mtmp)); if (yn(qbuf) != 'y') continue; setmangry(mtmp); } @@ -893,15 +942,37 @@ doconfuse() looked--; continue; } - if (!mon_reflects(mtmp,"Your gaze is reflected by %s %s.")){ + /* No reflection check for consistency with when a monster + * gazes at *you*--only medusa gaze gets reflected then. + */ + if (adtyp == AD_CONF) { if (!mtmp->mconf) Your("gaze confuses %s!", mon_nam(mtmp)); else pline("%s is getting more and more confused.", - Monnam(mtmp)); + Monnam(mtmp)); mtmp->mconf = 1; + } else if (adtyp == AD_FIRE) { + int dmg = d(2,6); + You("attack %s with a fiery gaze!", mon_nam(mtmp)); + if (resists_fire(mtmp)) { + pline_The("fire doesn't burn %s!", mon_nam(mtmp)); + dmg = 0; + } + if((int) u.ulevel > rn2(20)) + (void) destroy_mitem(mtmp, SCROLL_CLASS, AD_FIRE); + if((int) u.ulevel > rn2(20)) + (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE); + if((int) u.ulevel > rn2(25)) + (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE); + if (dmg && !DEADMONSTER(mtmp)) mtmp->mhp -= dmg; + if (mtmp->mhp <= 0) killed(mtmp); } - if ((mtmp->data==&mons[PM_FLOATING_EYE]) && !mtmp->mcan) { + /* For consistency with passive() in uhitm.c, this only + * affects you if the monster is still alive. + */ + if (!DEADMONSTER(mtmp) && + (mtmp->data==&mons[PM_FLOATING_EYE]) && !mtmp->mcan) { if (!Free_action) { You("are frozen by %s gaze!", s_suffix(mon_nam(mtmp))); @@ -914,7 +985,13 @@ doconfuse() You("stiffen momentarily under %s gaze.", s_suffix(mon_nam(mtmp))); } - if ((mtmp->data == &mons[PM_MEDUSA]) && !mtmp->mcan) { + /* Technically this one shouldn't affect you at all because + * the Medusa gaze is an active monster attack that only + * works on the monster's turn, but for it to *not* have an + * effect would be too weird. + */ + if (!DEADMONSTER(mtmp) && + (mtmp->data == &mons[PM_MEDUSA]) && !mtmp->mcan) { pline( "Gazing at the awake %s is not a very good idea.", l_monnam(mtmp)); @@ -996,11 +1073,12 @@ uunstick() u.ustuck = 0; } -STATIC_OVL void -skinback() +void +skinback(silently) +boolean silently; { if (uskin) { - Your("skin returns to its original form."); + if (!silently) Your("skin returns to its original form."); uarm = uskin; uskin = (struct obj *)0; /* undo save/restore hack */ @@ -1019,40 +1097,44 @@ int part; static NEARDATA const char *humanoid_parts[] = { "arm", "eye", "face", "finger", "fingertip", "foot", "hand", "handed", "head", "leg", - "light headed", "neck", "spine", "toe", "hair", "blood", "lung"}, + "light headed", "neck", "spine", "toe", "hair", + "blood", "lung", "nose", "stomach"}, *jelly_parts[] = { "pseudopod", "dark spot", "front", "pseudopod extension", "pseudopod extremity", "pseudopod root", "grasp", "grasped", "cerebral area", "lower pseudopod", "viscous", "middle", "surface", - "pseudopod extremity", "ripples", "juices", "surface" }, + "pseudopod extremity", "ripples", "juices", + "surface", "sensor", "stomach" }, *animal_parts[] = { "forelimb", "eye", "face", "foreclaw", "claw tip", "rear claw", "foreclaw", "clawed", "head", "rear limb", "light headed", "neck", "spine", "rear claw tip", - "fur", "blood", "lung" }, + "fur", "blood", "lung", "nose", "stomach" }, *horse_parts[] = { "foreleg", "eye", "face", "forehoof", "hoof tip", "rear hoof", "foreclaw", "hooved", "head", "rear leg", "light headed", "neck", "backbone", "rear hoof tip", - "mane", "blood", "lung" }, + "mane", "blood", "lung", "nose", "stomach"}, *sphere_parts[] = { "appendage", "optic nerve", "body", "tentacle", "tentacle tip", "lower appendage", "tentacle", "tentacled", "body", "lower tentacle", "rotational", "equator", "body", - "lower tentacle tip", "cilia", "life force", "retina" }, + "lower tentacle tip", "cilia", "life force", "retina", + "olfactory nerve", "interior" }, *fungus_parts[] = { "mycelium", "visual area", "front", "hypha", "hypha", "root", "strand", "stranded", "cap area", "rhizome", "sporulated", "stalk", "root", "rhizome tip", - "spores", "juices", "gill" }, + "spores", "juices", "gill", "gill", "interior" }, *vortex_parts[] = { "region", "eye", "front", "minor current", "minor current", "lower current", "swirl", "swirled", "central core", "lower current", "addled", "center", - "currents", "edge", "currents", "life force", "center" }, + "currents", "edge", "currents", "life force", + "center", "leading edge", "interior" }, *snake_parts[] = { "vestigial limb", "eye", "face", "large scale", "large scale tip", "rear region", "scale gap", "scale gapped", "head", "rear region", "light headed", "neck", "length", - "rear scale", "scales", "blood", "lung" }, + "rear scale", "scales", "blood", "lung", "forked tongue", "stomach" }, *fish_parts[] = { "fin", "eye", "premaxillary", "pelvic axillary", "pelvic fin", "anal fin", "pectoral fin", "finned", "head", "peduncle", "played out", "gills", "dorsal fin", "caudal fin", - "scales", "blood", "gill" }; + "scales", "blood", "gill", "nostril", "stomach" }; /* claw attacks are overloaded in mons[]; most humanoids with such attacks should still reference hands rather than claws */ static const char not_claws[] = { @@ -1073,8 +1155,16 @@ int part; mptr != &mons[PM_INCUBUS] && mptr != &mons[PM_SUCCUBUS]) return part == HAND ? "claw" : "clawed"; } + if ((mptr == &mons[PM_MUMAK] || mptr == &mons[PM_MASTODON]) && + part == NOSE) + return "trunk"; if (mptr == &mons[PM_SHARK] && part == HAIR) return "skin"; /* sharks don't have scales */ + if (mptr == &mons[PM_JELLYFISH] && (part == ARM || part == FINGER || + part == HAND || part == FOOT || part == TOE)) + return "tentacle"; + if (mptr == &mons[PM_FLOATING_EYE] && part == EYE) + return "cornea"; if (humanoid(mptr) && (part == ARM || part == FINGER || part == FINGERTIP || part == HAND || part == HANDED)) @@ -1084,7 +1174,7 @@ int part; return horse_parts[part]; if (mptr->mlet == S_EEL && mptr != &mons[PM_JELLYFISH]) return fish_parts[part]; - if (slithy(mptr)) + if (slithy(mptr) || (mptr->mlet == S_DRAGON && part == HAIR)) return snake_parts[part]; if (mptr->mlet == S_EYE) return sphere_parts[part]; diff --git a/src/potion.c b/src/potion.c index 396ca7a..c18b80f 100644 --- a/src/potion.c +++ b/src/potion.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)potion.c 3.3 2000/06/02 */ +/* SCCS Id: @(#)potion.c 3.4 2002/03/05 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -83,7 +83,14 @@ boolean talk; Hallucination ? "less wobbly" : "a bit steadier"); } if (xtime && !old) { - if (talk) You("stagger..."); + if (talk) { +#ifdef STEED + if (u.usteed) + You("wobble in the saddle."); + else +#endif + You("%s...", stagger(youmonst.data, "stagger")); + } } if ((!xtime && old) || (xtime && !old)) flags.botl = TRUE; @@ -157,34 +164,77 @@ long xtime; boolean talk; { long old = Blinded; - boolean changed = FALSE; + boolean u_could_see, can_see_now; + int eyecnt; + char buf[BUFSZ]; + static const char + vismsg[] = "vision seems to %s for a moment but is %s now.", + eyemsg[] = "%s momentarily %s."; + + /* we need to probe ahead in case the Eyes of the Overworld + are or will be overriding blindness */ + u_could_see = !Blind; + Blinded = xtime ? 1L : 0L; + can_see_now = !Blind; + Blinded = old; /* restore */ if (u.usleep) talk = FALSE; - if (!xtime && old && !Blindfolded && haseyes(youmonst.data)) { + if (can_see_now && !u_could_see) { /* regaining sight */ if (talk) { if (Hallucination) pline("Far out! Everything is all cosmic again!"); - else You("can see again."); + else + You("can see again."); + } + } else if (old && !xtime) { + /* clearing temporary blindness without toggling blindness */ + if (talk) { + if (!haseyes(youmonst.data)) { + strange_feeling((struct obj *)0, (char *)0); + } else if (Blindfolded) { + Strcpy(buf, body_part(EYE)); + eyecnt = eyecount(youmonst.data); + Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf), + (eyecnt == 1) ? "itches" : "itch"); + } else { /* Eyes of the Overworld */ + Your(vismsg, "brighten", + Hallucination ? "sadder" : "normal"); + } } - changed = TRUE; } - if (xtime && !old && !Blindfolded && haseyes(youmonst.data)) { + + if (u_could_see && !can_see_now) { /* losing sight */ if (talk) { if (Hallucination) - pline("Oh, bummer! Everything is dark! Help!"); + pline("Oh, bummer! Everything is dark! Help!"); else - pline("A cloud of darkness falls upon you."); + pline("A cloud of darkness falls upon you."); } - changed = TRUE; - /* Before the hero goes blind, set the ball&chain variables. */ if (Punished) set_bc(0); + } else if (!old && xtime) { + /* setting temporary blindness without toggling blindness */ + if (talk) { + if (!haseyes(youmonst.data)) { + strange_feeling((struct obj *)0, (char *)0); + } else if (Blindfolded) { + Strcpy(buf, body_part(EYE)); + eyecnt = eyecount(youmonst.data); + Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf), + (eyecnt == 1) ? "twitches" : "twitch"); + } else { /* Eyes of the Overworld */ + Your(vismsg, "dim", + Hallucination ? "happier" : "normal"); + } + } } + set_itimeout(&Blinded, xtime); - if (changed) { + + if (u_could_see ^ can_see_now) { /* one or the other but not both */ flags.botl = 1; - vision_full_recalc = 1; + vision_full_recalc = 1; /* blindness just got toggled */ if (Blind_telepat || Infravision) see_monsters(); } } @@ -352,7 +402,9 @@ peffects(otmp) break; } else { pline("Wow! This makes you feel %s!", - (otmp->blessed) ? "great" : "good"); + (otmp->blessed) ? + (unfixable_trouble_count(FALSE) ? "better" : "great") + : "good"); i = rn2(A_MAX); /* start at a random point */ for (ii = 0; ii < A_MAX; ii++) { lim = AMAX(i); @@ -517,7 +569,7 @@ peffects(otmp) } case POT_PARALYSIS: if (Free_action) - You("stiffen momentarily."); + You("stiffen momentarily."); else { if (Levitation||Is_airlevel(&u.uz)||Is_waterlevel(&u.uz)) You("are motionlessly suspended."); @@ -533,7 +585,7 @@ peffects(otmp) exercise(A_DEX, FALSE); } break; - case POT_SLEEPING: + case POT_SLEEPING: if(Sleep_resistance || Free_action) You("yawn."); else { @@ -548,7 +600,12 @@ peffects(otmp) if (Detect_monsters) nothing++; unkn++; - incr_itimeout(&HDetect_monsters, 20+rnd(40)); + /* after a while, repeated uses become less effective */ + if (HDetect_monsters >= 300L) + i = 1; + else + i = rn1(40,21); + incr_itimeout(&HDetect_monsters, i); for (x = 1; x < COLNO; x++) { for (y = 0; y < ROWNO; y++) { if (levl[x][y].glyph == GLYPH_INVISIBLE) { @@ -577,8 +634,14 @@ peffects(otmp) if (otmp->blessed) { pline("(But in fact it was mildly stale %s juice.)", pl_fruit); - if (!Role_if(PM_HEALER)) - losehp(1, "mildly contaminated potion", KILLED_BY_AN); + if (!Role_if(PM_HEALER)) { + if (otmp->corpsenm) + losehp(1, + "mildly contaminated tap water", KILLED_BY); + else + losehp(1, + "mildly contaminated potion", KILLED_BY_AN); + } } else { if(Poison_resistance) pline( @@ -595,9 +658,14 @@ peffects(otmp) Poison_resistance ? -1 : -rn1(4,3), TRUE); } - if(!Poison_resistance) + if(!Poison_resistance) { + if (otmp->corpsenm) + losehp(rnd(10)+5*!!(otmp->cursed), + "contaminated tap water", KILLED_BY); + else losehp(rnd(10)+5*!!(otmp->cursed), "contaminated potion", KILLED_BY_AN); + } exercise(A_CON, FALSE); } } @@ -622,6 +690,8 @@ peffects(otmp) if(otmp->cursed) { pline("Ulch! That potion tasted foul!"); unkn++; + } else if (Fixed_abil) { + nothing++; } else { /* If blessed, increase all; if not, try up to */ int itmp; /* 6 times to find one which can be increased. */ i = -1; /* increment to 0 */ @@ -636,11 +706,15 @@ peffects(otmp) } break; case POT_SPEED: - if(Wounded_legs && !otmp->cursed) { + if(Wounded_legs && !otmp->cursed +#ifdef STEED + && !u.usteed /* heal_legs() would heal steeds legs */ +#endif + ) { heal_legs(); unkn++; break; - } /* and fall through */ + } /* and fall through */ case SPE_HASTE_SELF: if(!Very_fast) /* wwf@doe.carleton.ca */ You("are suddenly moving %sfaster.", @@ -657,7 +731,7 @@ peffects(otmp) if(Blind) nothing++; make_blinded(itimeout_incr(Blinded, rn1(200, 250 - 125 * bcsign(otmp))), - TRUE); + (boolean)!Blind); break; case POT_GAIN_LEVEL: if (otmp->cursed) { @@ -706,12 +780,16 @@ peffects(otmp) exercise(A_CON, TRUE); exercise(A_STR, TRUE); break; - case POT_FULL_HEALING: + case POT_FULL_HEALING: You_feel("completely healed."); healup(400, 4+4*bcsign(otmp), !otmp->cursed, TRUE); /* Restore one lost level if blessed */ - if (otmp->blessed && (u.ulevel < u.ulevelmax)) - pluslvl(FALSE); + if (otmp->blessed && u.ulevel < u.ulevelmax) { + /* when multiple levels have been lost, drinking + multiple potions will only get half of them back */ + u.ulevelmax -= 1; + pluslvl(FALSE); + } make_hallucinated(0L,TRUE,0L); exercise(A_STR, TRUE); exercise(A_CON, TRUE); @@ -744,6 +822,7 @@ peffects(otmp) incr_itimeout(&HLevitation, rn1(50,250)); HLevitation |= I_SPECIAL; } else incr_itimeout(&HLevitation, rn1(140,10)); + spoteffects(FALSE); /* for sinks */ break; case POT_GAIN_ENERGY: /* M. Stephenson */ { register int num; @@ -786,16 +865,17 @@ peffects(otmp) pline("This tastes %s.", Hallucination ? "tangy" : "sour"); else { pline("This burns%s!", otmp->blessed ? " a little" : - otmp->cursed ? " a lot" : ""); + otmp->cursed ? " a lot" : " like acid"); losehp(d(otmp->cursed ? 2 : 1, otmp->blessed ? 4 : 8), "potion of acid", KILLED_BY_AN); exercise(A_CON, FALSE); } if (Stoned) fix_petrification(); + unkn++; /* holy/unholy water can burn like acid too */ break; case POT_POLYMORPH: You_feel("a little %s.", Hallucination ? "normal" : "strange"); - if (!Unchanging) polyself(); + if (!Unchanging) polyself(FALSE); break; default: impossible("What a funny potion! (%u)", otmp->otyp); @@ -829,7 +909,7 @@ strange_feeling(obj,txt) register struct obj *obj; register const char *txt; { - if(flags.beginner) + if (flags.beginner || !txt) You("have a %s feeling for a moment, then it passes.", Hallucination ? "normal" : "strange"); else @@ -848,13 +928,20 @@ const char *bottlenames[] = { "bottle", "phial", "flagon", "carafe", "flask", "jar", "vial" }; + +const char * +bottlename() +{ + return bottlenames[rn2(SIZE(bottlenames))]; +} + void potionhit(mon, obj, your_fault) register struct monst *mon; register struct obj *obj; boolean your_fault; { - register const char *botlnam = bottlenames[rn2(SIZE(bottlenames))]; + register const char *botlnam = bottlename(); boolean isyou = (mon == &youmonst); int distance; @@ -886,7 +973,7 @@ boolean your_fault; /* oil doesn't instantly evaporate */ if (obj->otyp != POT_OIL && cansee(mon->mx,mon->my)) - pline("%s evaporates.", The(xname(obj))); + pline("%s.", Tobjnam(obj, "evaporate")); if (isyou) { switch (obj->otyp) { @@ -896,7 +983,7 @@ boolean your_fault; break; case POT_POLYMORPH: You_feel("a little %s.", Hallucination ? "normal" : "strange"); - if (!Unchanging && !Antimagic) polyself(); + if (!Unchanging && !Antimagic) polyself(FALSE); break; case POT_ACID: if (!Acid_resistance) { @@ -930,7 +1017,7 @@ boolean your_fault; case POT_SICKNESS: if (mon->data == &mons[PM_PESTILENCE]) goto do_healing; if (dmgtype(mon->data, AD_DISE) || - dmgtype(mon->data, AD_PEST) || + dmgtype(mon->data, AD_PEST) || /* won't happen, see prior goto */ resists_poison(mon)) { if (canseemon(mon)) pline("%s looks unharmed.", Monnam(mon)); @@ -971,7 +1058,7 @@ boolean your_fault; break; case POT_SPEED: angermon = FALSE; - mon_adjust_speed(mon, 1); + mon_adjust_speed(mon, 1, obj); break; case POT_BLINDNESS: if(haseyes(mon->data)) { @@ -986,7 +1073,8 @@ boolean your_fault; if (is_undead(mon->data) || is_demon(mon->data) || is_were(mon->data)) { if (obj->blessed) { - pline("%s shrieks in pain!", Monnam(mon)); + pline("%s %s in pain!", Monnam(mon), + is_silent(mon->data) ? "writhes" : "shrieks"); mon->mhp -= d(2,6); /* should only be by you */ if (mon->mhp < 1) killed(mon); @@ -1019,7 +1107,8 @@ boolean your_fault; break; case POT_ACID: if (!resists_acid(mon) && !resist(mon, POTION_CLASS, 0, NOTELL)) { - pline("%s shrieks in pain!", Monnam(mon)); + pline("%s %s in pain!", Monnam(mon), + is_silent(mon->data) ? "writhes" : "shrieks"); mon->mhp -= d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8); if (mon->mhp < 1) { if (your_fault) @@ -1048,7 +1137,8 @@ boolean your_fault; } /* Note: potionbreathe() does its own docall() */ - if (distance==0 || ((distance < 3) && rn2(5))) + if ((distance==0 || ((distance < 3) && rn2(5))) && + (!breathless(youmonst.data) || haseyes(youmonst.data))) potionbreathe(obj); else if (obj->dknown && !objects[obj->otyp].oc_name_known && !objects[obj->otyp].oc_uname && cansee(mon->mx,mon->my)) @@ -1068,6 +1158,7 @@ boolean your_fault; obfree(obj, (struct obj *)0); } +/* vapors are inhaled or get in your eyes */ void potionbreathe(obj) register struct obj *obj; @@ -1078,7 +1169,14 @@ register struct obj *obj; case POT_RESTORE_ABILITY: case POT_GAIN_ABILITY: if(obj->cursed) { - pline("Ulch! That potion smells terrible!"); + if (!breathless(youmonst.data)) + pline("Ulch! That potion smells terrible!"); + else if (haseyes(youmonst.data)) { + int numeyes = eyecount(youmonst.data); + Your("%s sting%s!", + (numeyes == 1) ? body_part(EYE) : makeplural(body_part(EYE)), + (numeyes == 1) ? "s" : ""); + } break; } else { i = rn2(A_MAX); /* start at a random point */ @@ -1136,16 +1234,16 @@ register struct obj *obj; break; case POT_PARALYSIS: kn++; - if (!Free_action) { + if (!Free_action) { pline("%s seems to be holding you.", Something); nomul(-rnd(5)); nomovemsg = You_can_move_again; exercise(A_DEX, FALSE); - } else You("stiffen momentarily."); + } else You("stiffen momentarily."); break; case POT_SLEEPING: kn++; - if (!Free_action && !Sleep_resistance) { + if (!Free_action && !Sleep_resistance) { You_feel("rather tired."); nomul(-rnd(5)); nomovemsg = You_can_move_again; @@ -1163,6 +1261,7 @@ register struct obj *obj; pline("It suddenly gets dark."); } make_blinded(itimeout_incr(Blinded, rnd(5)), FALSE); + if (!Blind && !u.usleep) Your(vision_clears); break; case POT_WATER: if(u.umonnum == PM_GREMLIN) { @@ -1175,6 +1274,7 @@ register struct obj *obj; else if (obj->cursed && !Upolyd) you_were(); } + break; case POT_ACID: case POT_POLYMORPH: exercise(A_CON, FALSE); @@ -1232,7 +1332,7 @@ register struct obj *o1, *o2; case POT_GAIN_ENERGY: return POT_FULL_HEALING; } - case POT_FULL_HEALING: + case POT_FULL_HEALING: switch (o2->otyp) { case POT_GAIN_LEVEL: case POT_GAIN_ENERGY: @@ -1307,7 +1407,7 @@ register struct obj *obj; if (snuff_lit(obj)) return(TRUE); if (obj->greased) { - grease_protect(obj,(char *)0,FALSE,&youmonst); + grease_protect(obj,(char *)0,&youmonst); return(FALSE); } (void) Shk_Your(Your_buf, obj); @@ -1359,9 +1459,8 @@ register struct obj *obj; ) { if (!Blind) { boolean oq1 = obj->quan == 1L; - pline_The("scroll%s fade%s.", - oq1 ? "" : "s", - oq1 ? "s" : ""); + pline_The("scroll%s %s.", + oq1 ? "" : "s", otense(obj, "fade")); } if(obj->unpaid && costly_spot(u.ux, u.uy)) { You("erase it, you pay for it."); @@ -1382,7 +1481,7 @@ register struct obj *obj; if (!Blind) { boolean oq1 = obj->quan == 1L; pline_The("spellbook%s fade%s.", - oq1 ? "" : "s", oq1 ? "s" : ""); + oq1 ? "" : "s", otense(obj, "fade")); } if(obj->unpaid && costly_spot(u.ux, u.uy)) { You("erase it, you pay for it."); @@ -1402,6 +1501,7 @@ int dodip() { register struct obj *potion, *obj; + struct obj *singlepotion; const char *tmp; uchar here; char allowall[2]; @@ -1500,16 +1600,34 @@ dodip() if (obj->otyp == potion->otyp || /* both POT_POLY */ obj->otyp == WAN_POLYMORPH || obj->otyp == SPE_POLYMORPH || + obj == uball || obj == uskin || obj_resists(obj->otyp == POT_POLYMORPH ? potion : obj, 5, 95)) { pline(nothing_happens); } else { + boolean was_wep = FALSE, was_swapwep = FALSE, was_quiver = FALSE; + short save_otyp = obj->otyp; /* KMH, conduct */ u.uconduct.polypiles++; - poly_obj(obj, STRANGE_OBJECT); - makeknown(POT_POLYMORPH); - useup(potion); + if (obj == uwep) was_wep = TRUE; + else if (obj == uswapwep) was_swapwep = TRUE; + else if (obj == uquiver) was_quiver = TRUE; + + obj = poly_obj(obj, STRANGE_OBJECT); + + if (was_wep) setuwep(obj); + else if (was_swapwep) setuswapwep(obj); + else if (was_quiver) setuqwep(obj); + + if (obj->otyp != save_otyp) { + makeknown(POT_POLYMORPH); + useup(potion); + prinv((char *)0, obj, 0L); + } else { + pline("Nothing seems to happen."); + useup(potion); + } } return(1); } else if(obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) { @@ -1519,7 +1637,8 @@ dodip() if (obj->cursed || obj->otyp == POT_ACID || !rn2(10)) { pline("BOOM! They explode!"); exercise(A_STR, FALSE); - potionbreathe(obj); + if (!breathless(youmonst.data) || haseyes(youmonst.data)) + potionbreathe(obj); useup(obj); useup(potion); losehp(rnd(10), "alchemic blast", KILLED_BY_AN); @@ -1596,9 +1715,12 @@ dodip() if(is_poisonable(obj)) { if(potion->otyp == POT_SICKNESS && !obj->opoisoned) { char buf[BUFSZ]; - Strcpy(buf, The(xname(potion))); - pline("%s form%s a coating on %s.", - buf, potion->quan == 1L ? "s" : "", the(xname(obj))); + if (potion->quan > 1L) + Sprintf(buf, "One of %s", the(xname(potion))); + else + Strcpy(buf, The(xname(potion))); + pline("%s forms a coating on %s.", + buf, the(xname(obj))); obj->opoisoned = TRUE; goto poof; } else if(obj->opoisoned && @@ -1611,19 +1733,20 @@ dodip() } } - if (potion->otyp == POT_OIL && - (obj->oclass == WEAPON_CLASS || is_weptool(obj))) { + if (potion->otyp == POT_OIL) { boolean wisx = FALSE; if (potion->lamplit) { /* burning */ int omat = objects[obj->otyp].oc_material; - if (obj->oerodeproof || obj_resists(obj, 5, 95) || - /* `METAL' should not be confused with is_metallic() */ - omat == METAL || omat == MITHRIL || omat == BONE) { - pline("%s seem%s to burn for a moment.", - Yname2(obj), - (obj->quan > 1L) ? "" : "s"); + /* the code here should be merged with fire_damage */ + if (catch_lit(obj)) { + /* catch_lit does all the work if true */ + } else if (obj->oerodeproof || obj_resists(obj, 5, 95) || + !is_flammable(obj) || obj->oclass == FOOD_CLASS) { + pline("%s %s to burn for a moment.", + Yname2(obj), otense(obj, "seem")); } else { - if (omat == PLASTIC) obj->oeroded = MAX_ERODE; + if ((omat == PLASTIC || omat == PAPER) && !obj->oartifact) + obj->oeroded = MAX_ERODE; pline_The("burning oil %s %s.", obj->oeroded == MAX_ERODE ? "destroys" : "damages", yname(obj)); @@ -1632,8 +1755,12 @@ dodip() obfree(obj, (struct obj *)0); obj = (struct obj *) 0; } else { - /* should check for and do something about - damaging unpaid shop goods here */ + /* we know it's carried */ + if (obj->unpaid) { + /* create a dummy duplicate to put on bill */ + verbalize("You burnt it, you bought it!"); + bill_dummy_object(obj); + } obj->oeroded++; } } @@ -1641,20 +1768,21 @@ dodip() pline_The("potion spills and covers your %s with oil.", makeplural(body_part(FINGER))); incr_itimeout(&Glib, d(2,10)); + } else if (obj->oclass != WEAPON_CLASS && !is_weptool(obj)) { + /* the following cases apply only to weapons */ + goto more_dips; /* Oil removes rust and corrosion, but doesn't unburn. * Arrows, etc are classed as metallic due to arrowhead * material, but dipping in oil shouldn't repair them. */ } else if ((!is_rustprone(obj) && !is_corrodeable(obj)) || - is_ammo(obj) || (!obj->oeroded && !obj->oeroded2)) { + is_ammo(obj) || (!obj->oeroded && !obj->oeroded2)) { /* uses up potion, doesn't set obj->greased */ - pline("%s gleam%s with an oily sheen.", - Yname2(obj), - (obj->quan > 1L) ? "" : "s"); + pline("%s %s with an oily sheen.", + Yname2(obj), otense(obj, "gleam")); } else { pline("%s %s less %s.", - Yname2(obj), - (obj->quan > 1L) ? "are" : "is", + Yname2(obj), otense(obj, "are"), (obj->oeroded && obj->oeroded2) ? "corroded and rusty" : obj->oeroded ? "rusty" : "corroded"); if (obj->oeroded > 0) obj->oeroded--; @@ -1666,6 +1794,7 @@ dodip() useup(potion); return 1; } + more_dips: /* Allow filling of MAGIC_LAMPs to prevent identification by player */ if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP) && @@ -1673,7 +1802,7 @@ dodip() /* Turn off engine before fueling, turn off fuel too :-) */ if (obj->lamplit || potion->lamplit) { useup(potion); - explode(u.ux, u.uy, 11, d(6,6), 0); + explode(u.ux, u.uy, 11, d(6,6), 0, EXPL_FIERY); exercise(A_WIS, FALSE); return 1; } @@ -1683,7 +1812,7 @@ dodip() obj->age = 0; } if (obj->age > 1000L) { - pline("%s is full.", Yname2(obj)); + pline("%s %s full.", Yname2(obj), otense(obj, "are")); } else { You("fill %s with oil.", yname(obj)); check_unpaid(potion); /* Yendorian Fuel Tax */ @@ -1692,6 +1821,7 @@ dodip() useup(potion); exercise(A_WIS, TRUE); } + makeknown(POT_OIL); obj->spe = 1; update_inventory(); return 1; @@ -1699,34 +1829,45 @@ dodip() if ((obj->otyp == UNICORN_HORN || obj->otyp == AMETHYST) && (mixture = mixtype(obj, potion)) != 0) { - /* with multiple merged potions, we should split off one and - just clear it, but clearing them all together is easier */ - boolean more_than_one = potion->quan > 1L; - potion->otyp = mixture; - potion->blessed = 0; + boolean more_than_one = potion->quan > 1; + /* with multiple merged potions, split off one and + just clear it */ + if (potion->quan > 1L) { + singlepotion = splitobj(potion, 1L); + } else singlepotion = potion; + + if(singlepotion->unpaid && costly_spot(u.ux, u.uy)) { + You("use it, you pay for it."); + bill_dummy_object(singlepotion); + } + singlepotion->otyp = mixture; + singlepotion->blessed = 0; if (mixture == POT_WATER) - potion->cursed = potion->odiluted = 0; + singlepotion->cursed = singlepotion->odiluted = 0; else - potion->cursed = obj->cursed; /* odiluted left as-is */ + singlepotion->cursed = obj->cursed; /* odiluted left as-is */ + singlepotion->bknown = FALSE; if (Blind) - potion->dknown = FALSE; + singlepotion->dknown = FALSE; else { if (mixture == POT_WATER && #ifdef DCC30_BUG - (potion->dknown = !Hallucination, - potion->dknown != 0)) + (singlepotion->dknown = !Hallucination, + singlepotion->dknown != 0)) #else - (potion->dknown = !Hallucination) != 0) + (singlepotion->dknown = !Hallucination) != 0) #endif - pline_The("potion%s clear%s.", - more_than_one ? "s" : "", - more_than_one ? "" : "s"); + pline_The("potion%s clears.", + more_than_one ? " that you dipped into" : ""); else - pline_The("potion%s turn%s %s.", - more_than_one ? "s" : "", - more_than_one ? "" : "s", + pline_The("potion%s turns %s.", + more_than_one ? " that you dipped into" : "", hcolor(OBJ_DESCR(objects[mixture]))); } + obj_extract_self(singlepotion); + singlepotion = hold_another_object(singlepotion, + "You juggle and drop %s!", + doname(singlepotion), (const char *)0); update_inventory(); return(1); } diff --git a/src/pray.c b/src/pray.c index 4425960..1d2280e 100644 --- a/src/pray.c +++ b/src/pray.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pray.c 3.3 2000/06/29 */ +/* SCCS Id: @(#)pray.c 3.4 2002/03/02 */ /* Copyright (c) Benson I. Margulies, Mike Stephenson, Steve Linhart, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -9,6 +9,10 @@ STATIC_PTR int NDECL(prayer_done); STATIC_DCL int NDECL(in_trouble); STATIC_DCL void FDECL(fix_worst_trouble,(int)); STATIC_DCL void FDECL(angrygods,(ALIGNTYP_P)); +STATIC_DCL void FDECL(at_your_feet, (const char *)); +#ifdef ELBERETH +STATIC_DCL void NDECL(gcrownu); +#endif /*ELBERETH*/ STATIC_DCL void FDECL(pleased,(ALIGNTYP_P)); STATIC_DCL void FDECL(godvoice,(ALIGNTYP_P,const char*)); STATIC_DCL void FDECL(god_zaps_you,(ALIGNTYP_P)); @@ -164,7 +168,11 @@ in_trouble() if(Blinded > 1) return(TROUBLE_BLIND); for(i=0; i= HUNGRY) return(TROUBLE_HUNGRY); if(HStun) return (TROUBLE_STUNNED); if(HConfusion) return (TROUBLE_CONFUSED); @@ -188,11 +196,13 @@ register int trouble; case TROUBLE_STONED: You_feel("more limber."); Stoned = 0; + flags.botl = 1; delayed_killer = 0; break; case TROUBLE_SLIMED: pline_The("slime disappears."); Slimed = 0; + flags.botl = 1; delayed_killer = 0; break; case TROUBLE_STRANGLED: @@ -202,6 +212,7 @@ register int trouble; } You("can breathe again."); Strangled = 0; + flags.botl = 1; break; case TROUBLE_LAVA: You("are back on solid ground."); @@ -215,7 +226,7 @@ register int trouble; losestr(-1); /* fall into... */ case TROUBLE_HUNGRY: - Your("stomach feels content."); + Your("%s feels content.", body_part(STOMACH)); init_uhunger(); flags.botl = 1; break; @@ -325,8 +336,9 @@ register int trouble; if (!Blind) Your("%s %s.", what ? what : - (const char *)aobjnam (otmp, "softly glow"), + (const char *)aobjnam(otmp, "softly glow"), hcolor(amber)); + update_inventory(); break; case TROUBLE_POISONED: if (Hallucination) @@ -342,9 +354,14 @@ register int trouble; (void) encumber_msg(); break; case TROUBLE_BLIND: - Your("%s feel better.", makeplural(body_part(EYE))); - make_blinded(0L,FALSE); - break; + { + int num_eyes = eyecount(youmonst.data); + Your("%s feel%s better.", + (num_eyes == 1) ? body_part(EYE) : makeplural(body_part(EYE)), + (num_eyes == 1) ? "s" : ""); + make_blinded(0L,FALSE); + break; + } case TROUBLE_WOUNDED_LEGS: heal_legs(); break; @@ -437,7 +454,7 @@ aligntyp resp_god; summon_minion(resp_god, FALSE); summon_minion(resp_god, FALSE); summon_minion(resp_god, FALSE); - verbalize("Destroy %s, my servants!", him[flags.female]); + verbalize("Destroy %s, my servants!", uhim()); } } } @@ -522,11 +539,180 @@ aligntyp resp_god; return; } +/* helper to print "str appears at your feet", or appropriate */ +static void +at_your_feet(str) + const char *str; +{ + if (Blind) str = Something; + if (u.uswallow) { + /* barrier between you and the floor */ + pline("%s %s into %s %s.", str, vtense(str, "drop"), + s_suffix(mon_nam(u.ustuck)), mbodypart(u.ustuck, STOMACH)); + } else { + pline("%s %s %s your %s!", str, + Blind ? "lands" : vtense(str, "appear"), + Levitation ? "beneath" : "at", + makeplural(body_part(FOOT))); + } +} + +#ifdef ELBERETH +STATIC_OVL void +gcrownu() +{ + struct obj *obj; + boolean already_exists, in_hand; + short class_gift; + int sp_no; +#define ok_wep(o) ((o) && ((o)->oclass == WEAPON_CLASS || is_weptool(o))) + + HSee_invisible |= FROMOUTSIDE; + HFire_resistance |= FROMOUTSIDE; + HCold_resistance |= FROMOUTSIDE; + HShock_resistance |= FROMOUTSIDE; + HSleep_resistance |= FROMOUTSIDE; + HPoison_resistance |= FROMOUTSIDE; + godvoice(u.ualign.type, (char *)0); + + obj = ok_wep(uwep) ? uwep : 0; + already_exists = in_hand = FALSE; /* lint suppression */ + switch (u.ualign.type) { + case A_LAWFUL: + u.uevent.uhand_of_elbereth = 1; + verbalize("I crown thee... The Hand of Elbereth!"); + break; + case A_NEUTRAL: + u.uevent.uhand_of_elbereth = 2; + in_hand = (uwep && uwep->oartifact == ART_VORPAL_BLADE); + already_exists = exist_artifact(LONG_SWORD, artiname(ART_VORPAL_BLADE)); + verbalize("Thou shalt be my Envoy of Balance!"); + break; + case A_CHAOTIC: + u.uevent.uhand_of_elbereth = 3; + in_hand = (uwep && uwep->oartifact == ART_STORMBRINGER); + already_exists = exist_artifact(RUNESWORD, artiname(ART_STORMBRINGER)); + verbalize("Thou art chosen to %s for My Glory!", + already_exists && !in_hand ? "take lives" : "steal souls"); + break; + } + + class_gift = STRANGE_OBJECT; + /* 3.3.[01] had this in the A_NEUTRAL case below, + preventing chaotic wizards from receiving a spellbook */ + if (Role_if(PM_WIZARD) && + (!uwep || (uwep->oartifact != ART_VORPAL_BLADE && + uwep->oartifact != ART_STORMBRINGER)) && + !carrying(SPE_FINGER_OF_DEATH)) { + class_gift = SPE_FINGER_OF_DEATH; + make_splbk: + obj = mksobj(class_gift, TRUE, FALSE); + bless(obj); + obj->bknown = TRUE; + at_your_feet("A spellbook"); + dropy(obj); + u.ugifts++; + /* when getting a new book for known spell, enhance + currently wielded weapon rather than the book */ + for (sp_no = 0; sp_no < MAXSPELL; sp_no++) + if (spl_book[sp_no].sp_id == class_gift) { + if (ok_wep(uwep)) obj = uwep; /* to be blessed,&c */ + break; + } + } else if (Role_if(PM_MONK) && + (!uwep || !uwep->oartifact) && + !carrying(SPE_RESTORE_ABILITY)) { + /* monks rarely wield a weapon */ + class_gift = SPE_RESTORE_ABILITY; + goto make_splbk; + } + + switch (u.ualign.type) { + case A_LAWFUL: + if (class_gift != STRANGE_OBJECT) { + ; /* already got bonus above */ + } else if (obj && obj->otyp == LONG_SWORD && !obj->oartifact) { + if (!Blind) Your("sword shines brightly for a moment."); + obj = oname(obj, artiname(ART_EXCALIBUR)); + if (obj && obj->oartifact == ART_EXCALIBUR) u.ugifts++; + } + /* acquire Excalibur's skill regardless of weapon or gift */ + unrestrict_weapon_skill(P_LONG_SWORD); + if (obj && obj->oartifact == ART_EXCALIBUR) + discover_artifact(ART_EXCALIBUR); + break; + case A_NEUTRAL: + if (class_gift != STRANGE_OBJECT) { + ; /* already got bonus above */ + } else if (in_hand) { + Your("%s goes snicker-snack!", xname(obj)); + obj->dknown = TRUE; + } else if (!already_exists) { + obj = mksobj(LONG_SWORD, FALSE, FALSE); + obj = oname(obj, artiname(ART_VORPAL_BLADE)); + obj->spe = 1; + at_your_feet("A sword"); + dropy(obj); + u.ugifts++; + } + /* acquire Vorpal Blade's skill regardless of weapon or gift */ + unrestrict_weapon_skill(P_LONG_SWORD); + if (obj && obj->oartifact == ART_VORPAL_BLADE) + discover_artifact(ART_VORPAL_BLADE); + break; + case A_CHAOTIC: + { + char swordbuf[BUFSZ]; + + Sprintf(swordbuf, "%s sword", hcolor(Black)); + if (class_gift != STRANGE_OBJECT) { + ; /* already got bonus above */ + } else if (in_hand) { + Your("%s hums ominously!", swordbuf); + obj->dknown = TRUE; + } else if (!already_exists) { + obj = mksobj(RUNESWORD, FALSE, FALSE); + obj = oname(obj, artiname(ART_STORMBRINGER)); + at_your_feet(An(swordbuf)); + obj->spe = 1; + dropy(obj); + u.ugifts++; + } + /* acquire Stormbringer's skill regardless of weapon or gift */ + unrestrict_weapon_skill(P_BROAD_SWORD); + if (obj && obj->oartifact == ART_STORMBRINGER) + discover_artifact(ART_STORMBRINGER); + break; + } + default: + obj = 0; /* lint */ + break; + } + + /* enhance weapon regardless of alignment or artifact status */ + if (ok_wep(obj)) { + bless(obj); + obj->oeroded = obj->oeroded2 = 0; + obj->oerodeproof = TRUE; + obj->bknown = obj->rknown = TRUE; + if (obj->spe < 1) obj->spe = 1; + /* acquire skill in this weapon */ + unrestrict_weapon_skill(weapon_type(obj)); + } else if (class_gift == STRANGE_OBJECT) { + /* opportunity knocked, but there was nobody home... */ + You_feel("unworthy."); + } + update_inventory(); + return; +} +#endif /*ELBERETH*/ + STATIC_OVL void pleased(g_align) aligntyp g_align; { - int trouble = p_trouble; /* what's your worst difficulty? */ + /* don't use p_trouble, worst trouble may get fixed while praying */ + int trouble = in_trouble(); /* what's your worst difficulty? */ int pat_on_head = 0, kick_on_butt; You_feel("that %s is %s.", align_gname(g_align), @@ -555,8 +741,10 @@ pleased(g_align) If your luck is at least 0, then you are guaranteed rescued from your worst major problem. */ - if (!trouble && u.ualign.record >= DEVOUT) pat_on_head = 1; - else { + if (!trouble && u.ualign.record >= DEVOUT) { + /* if hero was in trouble, but got better, no special favor */ + if (p_trouble == 0) pat_on_head = 1; + } else { int action = rn1(on_altar() ? 3 + on_shrine() : 2, Luck+1); if (!on_altar()) action = max(action,2); @@ -590,7 +778,7 @@ pleased(g_align) *repair_buf = '\0'; if (uwep->oeroded || uwep->oeroded2) Sprintf(repair_buf, " and %s now as good as new", - uwep->quan == 1L ? "is" : "are"); + otense(uwep, "are")); if (uwep->cursed) { uncurse(uwep); @@ -623,6 +811,7 @@ pleased(g_align) Your("%s as good as new!", aobjnam(uwep, Blind ? "feel" : "look")); } + update_inventory(); } break; case 3: @@ -646,10 +835,18 @@ pleased(g_align) /* Otherwise, falls into next case */ case 2: if (!Blind) - You("are surrounded by %s glow.", - an(hcolor(golden))); - if (Upolyd) u.mh = u.mhmax += 5; - u.uhp = u.uhpmax += 5; + You("are surrounded by %s glow.", an(hcolor(golden))); + /* if any levels have been lost (and not yet regained), + treat this effect like blessed full healing */ + if (u.ulevel < u.ulevelmax) { + u.ulevelmax -= 1; /* see potion.c */ + pluslvl(FALSE); + } else { + u.uhpmax += 5; + if (Upolyd) u.mhmax += 5; + } + u.uhp = u.uhpmax; + if (Upolyd) u.mh = u.mhmax; ABASE(A_STR) = AMAX(A_STR); if (u.uhunger < 900) init_uhunger(); if (u.uluck < 0) u.uluck = 0; @@ -658,6 +855,7 @@ pleased(g_align) break; case 4: { register struct obj *otmp; + int any = 0; if (Blind) You_feel("the power of %s.", u_gname()); @@ -670,9 +868,11 @@ pleased(g_align) Your("%s %s.", aobjnam(otmp, "softly glow"), hcolor(amber)); otmp->bknown = TRUE; + ++any; } } } + if (any) update_inventory(); break; } case 5: { @@ -703,133 +903,25 @@ pleased(g_align) case 9: /* KMH -- can occur during full moons */ #ifdef ELBERETH if (u.ualign.record >= PIOUS && !u.uevent.uhand_of_elbereth) { - register struct obj *obj = uwep; /* to be blessed */ - boolean already_exists, in_hand; - const char *dropped_item; - int sp_no; - - HSee_invisible |= FROMOUTSIDE; - HFire_resistance |= FROMOUTSIDE; - HCold_resistance |= FROMOUTSIDE; - HPoison_resistance |= FROMOUTSIDE; - godvoice(u.ualign.type,(char *)0); - - switch(u.ualign.type) { - case A_LAWFUL: - u.uevent.uhand_of_elbereth = 1; - verbalize("I crown thee... The Hand of Elbereth!"); - if (obj && (obj->otyp == LONG_SWORD) && !obj->oartifact) { - obj = oname(obj, artiname(ART_EXCALIBUR)); - if (obj && obj->oartifact == ART_EXCALIBUR) u.ugifts++; - } - /* acquire this skill regardless of weapon */ - unrestrict_weapon_skill(P_LONG_SWORD); - if (obj && obj->oartifact == ART_EXCALIBUR) - discover_artifact(ART_EXCALIBUR); - break; - case A_NEUTRAL: - u.uevent.uhand_of_elbereth = 2; - verbalize("Thou shalt be my Envoy of Balance!"); - dropped_item = 0; - if (uwep && uwep->oartifact == ART_VORPAL_BLADE) { - obj = uwep; /* to be blessed and rustproofed */ - Your("%s goes snicker-snack!", xname(obj)); - obj->dknown = TRUE; - } else if (Role_if(PM_WIZARD) && - !carrying(SPE_FINGER_OF_DEATH)) { - obj = mksobj(SPE_FINGER_OF_DEATH, TRUE, FALSE); - bless(obj); - dropped_item = "A spellbook appears"; - } else if (!exist_artifact(LONG_SWORD, - artiname(ART_VORPAL_BLADE))) { - obj = mksobj(LONG_SWORD, FALSE, FALSE); - obj = oname(obj, artiname(ART_VORPAL_BLADE)); - obj->spe = 1; - dropped_item = "A sword appears"; - } - if (dropped_item) { - if (Blind) dropped_item = "Something lands"; - pline("%s %s your %s!", dropped_item, - Levitation ? "beneath" : "at", - makeplural(body_part(FOOT))); - dropy(obj); - u.ugifts++; - } - /* acquire this skill regardless of weapon (or book) */ - unrestrict_weapon_skill(P_LONG_SWORD); - if (obj && obj->oartifact == ART_VORPAL_BLADE) - discover_artifact(ART_VORPAL_BLADE); - /* when getting a new book for known spell, enhance - currently wielded weapon rather than the book */ - if (obj && obj->otyp == SPE_FINGER_OF_DEATH) { - for (sp_no = 0; sp_no < MAXSPELL; sp_no++) - if (spl_book[sp_no].sp_id == SPE_FINGER_OF_DEATH) { - if (uwep) obj = uwep; /* to be blessed,&c */ - break; - } - } - break; - case A_CHAOTIC: - u.uevent.uhand_of_elbereth = 3; - in_hand = (uwep && uwep->oartifact == ART_STORMBRINGER); - already_exists = exist_artifact(RUNESWORD, - artiname(ART_STORMBRINGER)); - verbalize("Thou art chosen to %s for My Glory!", - already_exists && !in_hand ? - "take lives" : "steal souls"); - if (in_hand) { - obj = uwep; /* to be blessed and rustproofed */ - } else if (!already_exists) { - obj = mksobj(RUNESWORD, FALSE, FALSE); - obj = oname(obj, artiname(ART_STORMBRINGER)); - pline("%s %s %s your %s!", Blind ? Something : - An(hcolor(Black)), - Blind ? "lands" : "sword appears", - Levitation ? "beneath" : "at", - makeplural(body_part(FOOT))); - obj->spe = 1; - dropy(obj); - u.ugifts++; - } - /* acquire this skill regardless of weapon */ - unrestrict_weapon_skill(P_BROAD_SWORD); - if (obj && obj->oartifact == ART_STORMBRINGER) - discover_artifact(ART_STORMBRINGER); - break; - default: - obj = 0; /* lint */ - break; - } - /* enhance weapon regardless of alignment or artifact status */ - if (obj && (obj->oclass == WEAPON_CLASS || is_weptool(obj))) { - bless(obj); - obj->oeroded = obj->oeroded2 = 0; - obj->oerodeproof = TRUE; - obj->bknown = obj->rknown = TRUE; - if (obj->spe < 1) obj->spe = 1; - /* acquire skill in this weapon */ - unrestrict_weapon_skill(weapon_type(obj)); - } else if (obj && (obj->oclass == SPBOOK_CLASS)) { - obj->bknown = TRUE; - } else /* opportunity knocked, but there was nobody home... */ - You_feel("unworthy."); + gcrownu(); break; - } + } /* else FALLTHRU */ #endif /*ELBERETH*/ - case 6: { struct obj *otmp; int sp_no, trycnt = u.ulevel + 1; - pline("An object appears at your %s!", - makeplural(body_part(FOOT))); + at_your_feet("An object"); /* not yet known spells given preference over already known ones */ + /* Also, try to grant a spell for which there is a skill slot */ otmp = mkobj(SPBOOK_CLASS, TRUE); while (--trycnt > 0) { if (otmp->otyp != SPE_BLANK_PAPER) { for (sp_no = 0; sp_no < MAXSPELL; sp_no++) if (spl_book[sp_no].sp_id == otmp->otyp) break; - if (sp_no == MAXSPELL) break; /* not yet known */ + if (sp_no == MAXSPELL && + !P_RESTRICTED(spell_skilltype(otmp->otyp))) + break; /* usable, but not yet known */ } else { if (!objects[SPE_BLANK_PAPER].oc_name_known || carrying(MAGIC_MARKER)) break; @@ -867,7 +959,8 @@ water_prayer(bless_water) for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp->nexthere) { /* turn water into (un)holy water */ - if (otmp->otyp == POT_WATER && (boolean)otmp->blessed != bless_water) { + if (otmp->otyp == POT_WATER && + (bless_water ? !otmp->blessed : !otmp->cursed)) { otmp->blessed = bless_water; otmp->cursed = !bless_water; otmp->bknown = bc_known; @@ -1089,7 +1182,7 @@ dosacrifice() } /* corpse */ if (otmp->otyp == AMULET_OF_YENDOR) { - if (!In_endgame(&u.uz)) { + if (!Is_astralevel(&u.uz)) { if (Hallucination) You_feel("homesick."); else @@ -1294,14 +1387,15 @@ verbalize("In return for thy service, I grant thee the gift of Immortality!"); /* you were already in pretty good standing */ /* The player can gain an artifact */ /* The chance goes down as the number of artifacts goes up */ - if (u.ulevel > 2 && !rn2(10 + (2 * u.ugifts * nartifacts))) { + if (u.ulevel > 2 && u.uluck >= 0 && + !rn2(10 + (2 * u.ugifts * nartifacts))) { otmp = mk_artifact((struct obj *)0, a_align(u.ux,u.uy)); if (otmp) { if (otmp->spe < 0) otmp->spe = 0; if (otmp->cursed) uncurse(otmp); + otmp->oerodeproof = TRUE; dropy(otmp); - pline("An object appears at your %s!", - makeplural(body_part(FOOT))); + at_your_feet("An object"); godvoice(u.ualign.type, "Use my gift wisely!"); u.ugifts++; u.ublesscnt = rnz(300 + (50 * nartifacts)); @@ -1313,6 +1407,7 @@ verbalize("In return for thy service, I grant thee the gift of Immortality!"); } } change_luck((value * LUCKMAX) / (MAXVALUE * 2)); + if ((int)u.uluck < 0) u.uluck = 0; if (u.uluck != saved_luck) { if (Blind) You("think %s brushed your %s.",something, body_part(FOOT)); @@ -1379,11 +1474,17 @@ boolean praying; /* false means no messages should be given */ int dopray() { - /* Confirm accidental slips of Alt-P */ - if (flags.prayconfirm) - if (yn("Are you sure you want to pray?") == 'n') - return (0); - u.uconduct.gnostic++; + /* Confirm accidental slips of Alt-P */ + if (flags.prayconfirm) + if (yn("Are you sure you want to pray?") == 'n') + return 0; + + u.uconduct.gnostic++; + /* Praying implies that the hero is conscious and since we have + no deafness attribute this implies that all verbalized messages + can be heard. So, in case the player has used the 'O' command + to toggle this accessible flag off, force it to be on. */ + flags.soundok = 1; /* set up p_type and p_alignment */ if (!can_pray(TRUE)) return 0; @@ -1489,6 +1590,8 @@ doturn() You("don't know how to turn undead!"); return(0); } + u.uconduct.gnostic++; + if ((u.ualign.type != A_CHAOTIC && (is_demon(youmonst.data) || is_undead(youmonst.data))) || u.ugangr > 6 /* "Die, mortal!" */) { @@ -1506,7 +1609,6 @@ doturn() } pline("Calling upon %s, you chant an arcane formula.", u_gname()); exercise(A_WIS, TRUE); - u.uconduct.gnostic++; /* note: does not perform unturn_dead() on victims' inventories */ range = BOLT_LIM + (u.ulevel / 5); /* 5 to 11 */ @@ -1534,23 +1636,25 @@ doturn() switch (mtmp->data->mlet) { /* this is intentional, lichs are tougher than zombies. */ - case S_LICH: xlev += 2; - case S_GHOST: xlev += 2; - case S_VAMPIRE: xlev += 2; - case S_WRAITH: xlev += 2; - case S_MUMMY: xlev += 2; + case S_LICH: xlev += 2; /*FALLTHRU*/ + case S_GHOST: xlev += 2; /*FALLTHRU*/ + case S_VAMPIRE: xlev += 2; /*FALLTHRU*/ + case S_WRAITH: xlev += 2; /*FALLTHRU*/ + case S_MUMMY: xlev += 2; /*FALLTHRU*/ case S_ZOMBIE: - mtmp->mflee = 1; /* at least */ - if(u.ulevel >= xlev && - !resist(mtmp, '\0', 0, NOTELL)) { - if(u.ualign.type == A_CHAOTIC) { + if (u.ulevel >= xlev && + !resist(mtmp, '\0', 0, NOTELL)) { + if (u.ualign.type == A_CHAOTIC) { mtmp->mpeaceful = 1; + set_malign(mtmp); } else { /* damn them */ killed(mtmp); } - } - break; - default: mtmp->mflee = 1; + break; + } /* else flee */ + /*FALLTHRU*/ + default: + monflee(mtmp, 0, FALSE, TRUE); break; } } diff --git a/src/priest.c b/src/priest.c index ba20e56..22492bb 100644 --- a/src/priest.c +++ b/src/priest.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)priest.c 3.3 2000/02/19 */ +/* SCCS Id: @(#)priest.c 3.4 2001/11/07 */ /* Copyright (c) Izchak Miller, Steve Linhart, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -8,6 +8,9 @@ #include "epri.h" #include "emin.h" +/* this matches the categorizations shown by enlightenment */ +#define ALGN_SINNED (-4) /* worse than strayed */ + #ifdef OVLB STATIC_DCL boolean FDECL(histemple_at,(struct monst *,XCHAR_P,XCHAR_P)); @@ -190,9 +193,9 @@ struct mkroom *sroom; int sx, sy; boolean sanctum; /* is it the seat of the high priest? */ { - register struct monst *priest; - register struct obj *otmp; - register int cnt; + struct monst *priest; + struct obj *otmp; + int cnt; if(MON_AT(sx+1, sy)) rloc(m_at(sx+1, sy)); /* insurance */ @@ -216,25 +219,17 @@ boolean sanctum; /* is it the seat of the high priest? */ on_level(&sanctum_level, &u.uz)) { (void) mongets(priest, AMULET_OF_YENDOR); } - /* Do NOT put the rest in m_initinv. */ - /* Priests created elsewhere than in a */ - /* temple should not carry these items, */ - cnt = rn1(2,3); - while(cnt) { - otmp = mkobj(SPBOOK_CLASS, FALSE); - if(otmp) (void) mpickobj(priest, otmp); - cnt--; + /* 2 to 4 spellbooks */ + for (cnt = rn1(3,2); cnt > 0; --cnt) { + (void) mpickobj(priest, mkobj(SPBOOK_CLASS, FALSE)); } - if(p_coaligned(priest)) - (void) mongets(priest, ROBE); - else { - otmp = mksobj(ROBE, TRUE, FALSE); - if(otmp) { - if(!rn2(2)) curse(otmp); - (void) mpickobj(priest, otmp); - } + /* robe [via makemon()] */ + if (rn2(2) && (otmp = which_armor(priest, W_ARMC)) != 0) { + if (p_coaligned(priest)) + uncurse(otmp); + else + curse(otmp); } - m_dowear(priest, TRUE); } } @@ -368,8 +363,8 @@ register int roomno; } if(!sanctum) { /* !tended -> !shrined */ - if(!shrined || !p_coaligned(priest) || - u.ualign.record < -5) + if (!shrined || !p_coaligned(priest) || + u.ualign.record <= ALGN_SINNED) You("have a%s forbidding feeling...", (!shrined) ? "" : " strange"); else You("experience a strange sense of peace."); @@ -405,7 +400,6 @@ register struct monst *priest; boolean coaligned = p_coaligned(priest); boolean strayed = (u.ualign.record < 0); - /* KMH, conduct */ u.uconduct.gnostic++; @@ -427,7 +421,7 @@ register struct monst *priest; if(!priest->mcanmove || priest->msleeping) { pline("%s breaks out of %s reverie!", - Monnam(priest), his[pronoun_gender(priest)]); + Monnam(priest), mhis(priest)); priest->mfrozen = priest->msleeping = 0; priest->mcanmove = 1; } @@ -443,7 +437,7 @@ register struct monst *priest; priest->mpeaceful = 0; return; } - +#ifndef GOLDOBJ if(!u.ugold) { if(coaligned && !strayed) { if (priest->mgold > 0L) { @@ -456,6 +450,16 @@ register struct monst *priest; u.ugold = 1L; priest->mgold -= u.ugold; flags.botl = 1; +#else + if(!money_cnt(invent)) { + if(coaligned && !strayed) { + long pmoney = money_cnt(priest->minvent); + if (pmoney > 0L) { + /* Note: two bits is actually 25 cents. Hmm. */ + pline("%s gives you %s for an ale.", Monnam(priest), + (pmoney == 1L) ? "one bit" : "two bits"); + money2u(priest, pmoney > 1L ? 2 : 1); +#endif } else pline("%s preaches the virtues of poverty.", Monnam(priest)); exercise(A_WIS, TRUE); @@ -471,7 +475,11 @@ register struct monst *priest; verbalize("Thou shalt regret thine action!"); if(coaligned) adjalign(-1); } else if(offer < (u.ulevel * 200)) { +#ifndef GOLDOBJ if(u.ugold > (offer * 2L)) verbalize("Cheapskate."); +#else + if(money_cnt(invent) > (offer * 2L)) verbalize("Cheapskate."); +#endif else { verbalize("I thank thee for thy contribution."); /* give player some token */ @@ -479,8 +487,13 @@ register struct monst *priest; } } else if(offer < (u.ulevel * 400)) { verbalize("Thou art indeed a pious individual."); +#ifndef GOLDOBJ if(u.ugold < (offer * 2L)) { - if(coaligned && u.ualign.record < -5) adjalign(1); +#else + if(money_cnt(invent) < (offer * 2L)) { +#endif + if (coaligned && u.ualign.record <= ALGN_SINNED) + adjalign(1); verbalize("I bestow upon thee a blessing."); incr_itimeout(&HClairvoyant, rn1(500,500)); } @@ -494,7 +507,11 @@ register struct monst *priest; } else u.ublessed++; } else { verbalize("Thy selfless generosity is deeply appreciated."); +#ifndef GOLDOBJ if(u.ugold < (offer * 2L) && coaligned) { +#else + if(money_cnt(invent) < (offer * 2L) && coaligned) { +#endif if(strayed && (moves - u.ucleansed) > 5000L) { u.ualign.record = 0; /* cleanse thee */ u.ucleansed = moves; @@ -565,7 +582,7 @@ xchar x, y; if (is_minion(mon->data) || is_rider(mon->data)) return FALSE; x = mon->mx, y = mon->my; } - if (u.ualign.record < -3) /* sinned or worse */ + if (u.ualign.record <= ALGN_SINNED) /* sinned or worse */ return FALSE; if ((roomno = temple_occupied(u.urooms)) == 0 || roomno != *in_rooms(x, y, TEMPLE)) diff --git a/src/quest.c b/src/quest.c index 21a7162..01d8bf7 100644 --- a/src/quest.c +++ b/src/quest.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)quest.c 3.3 2000/05/05 */ +/* SCCS Id: @(#)quest.c 3.4 2000/05/05 */ /* Copyright 1991, M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ @@ -152,6 +152,7 @@ boolean seal; !seal ? 1 : -1; schedule_goto(dest, FALSE, FALSE, portal_flag, (char *)0, (char *)0); if (seal) { /* remove the portal to the quest - sealing it off */ + int reexpelled = u.uevent.qexpelled; u.uevent.qexpelled = 1; /* Delete the near portal now; the far (main dungeon side) portal will be deleted as part of arrival on that level. @@ -160,7 +161,7 @@ boolean seal; for (t = ftrap; t; t = t->ntrap) if (t->ttyp == MAGIC_PORTAL) break; if (t) deltrap(t); /* (display might be briefly out of sync) */ - else impossible("quest portal already gone?"); + else if (!reexpelled) impossible("quest portal already gone?"); } } @@ -194,6 +195,7 @@ struct obj *obj; /* quest artifact; possibly null if carrying Amulet */ /* behave as if leader imparts sufficient info about the quest artifact */ fully_identify_obj(obj); + update_inventory(); } } @@ -293,7 +295,8 @@ nemesis_speaks() { if(!Qstat(in_battle)) { if(u.uhave.questart) qt_pager(QT_NEMWANTSIT); - else if(Qstat(made_goal) == 1) qt_pager(QT_FIRSTNEMESIS); + else if(Qstat(made_goal) == 1 || !Qstat(met_nemesis)) + qt_pager(QT_FIRSTNEMESIS); else if(Qstat(made_goal) < 4) qt_pager(QT_NEXTNEMESIS); else if(Qstat(made_goal) < 7) qt_pager(QT_OTHERNEMESIS); else if(!rn2(5)) qt_pager(rn1(10, QT_DISCOURAGE)); @@ -307,7 +310,10 @@ STATIC_OVL void chat_with_guardian() { /* These guys/gals really don't have much to say... */ - qt_pager(rn1(5, QT_GUARDTALK)); + if (u.uhave.questart && Qstat(killed_nemesis)) + qt_pager(rn1(5, QT_GUARDTALK2)); + else + qt_pager(rn1(5, QT_GUARDTALK)); } STATIC_OVL void @@ -336,8 +342,11 @@ void quest_chat(mtmp) register struct monst *mtmp; { + if (mtmp->m_id == Qstat(leader_m_id)) { + chat_with_leader(); + return; + } switch(mtmp->data->msound) { - case MS_LEADER: chat_with_leader(); break; case MS_NEMESIS: chat_with_nemesis(); break; case MS_GUARDIAN: chat_with_guardian(); break; default: impossible("quest_chat: Unknown quest character %s.", @@ -349,8 +358,11 @@ void quest_talk(mtmp) register struct monst *mtmp; { + if (mtmp->m_id == Qstat(leader_m_id)) { + leader_speaks(mtmp); + return; + } switch(mtmp->data->msound) { - case MS_LEADER: leader_speaks(mtmp); break; case MS_NEMESIS: nemesis_speaks(); break; case MS_DJINNI: prisoner_speaks(mtmp); break; default: break; diff --git a/src/questpgr.c b/src/questpgr.c index 93351a6..ff0c9a7 100644 --- a/src/questpgr.c +++ b/src/questpgr.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)questpgr.c 3.3 2000/05/05 */ +/* SCCS Id: @(#)questpgr.c 3.4 2000/05/05 */ /* Copyright 1991, M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ @@ -209,15 +209,6 @@ homebase() /* return your role leader's location */ return(urole.homebase); } -boolean -leaderless() /* return true iff leader is dead */ -{ - int i = urole.ldrnum; - /* BUG: This doesn't take the possibility of resurrection - via wand or spell of undead turning into account. */ - return (boolean)(mvitals[i].died > 0); -} - STATIC_OVL struct qtmsg * msg_in(qtm_list, msgnum) struct qtmsg *qtm_list; diff --git a/src/read.c b/src/read.c index e434b79..32516e2 100644 --- a/src/read.c +++ b/src/read.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)read.c 3.3 2000/03/03 */ +/* SCCS Id: @(#)read.c 3.4 2001/12/03 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -38,6 +38,7 @@ static void FDECL(p_glow2,(struct obj *,const char *)); static void FDECL(randomize,(int *, int)); static void FDECL(forget_single_object, (int)); static void FDECL(forget, (int)); +static void FDECL(maybe_tame, (struct monst *,struct obj *)); STATIC_PTR void FDECL(set_lit, (int,int,genericptr_t)); @@ -62,6 +63,24 @@ doread() return(1); #ifdef TOURIST } else if (scroll->otyp == T_SHIRT) { + static const char *shirt_msgs[] = { /* Scott Bigham */ + "I explored the Dungeons of Doom and all I got was this lousy T-shirt!", + "Is that Mjollnir in your pocket or are you just happy to see me?", + "It's not the size of your sword, it's how #enhance'd you are with it.", + "Madame Elvira's House O' Succubi Lifetime Customer", + "Madame Elvira's House O' Succubi Employee of the Month", + "Ludios Vault Guards Do It In Small, Dark Rooms", + "Yendor Military Soldiers Do It In Large Groups", + "I survived Yendor Military Boot Camp", + "Ludios Accounting School Intra-Mural Lacrosse Team", + "Oracle(TM) Fountains 10th Annual Wet T-Shirt Contest", + "Hey, black dragon! Disintegrate THIS!", + "I'm With Stupid -->", + "Don't blame me, I voted for Izchak!", + "Don't Panic", /* HHGTTG */ + "Furinkan High School Athletic Dept.", /* Ranma 1/2 */ + "Hel-LOOO, Nurse!", /* Animaniacs */ + }; char buf[BUFSZ]; int erosion; @@ -72,13 +91,7 @@ doread() u.uconduct.literate++; if(flags.verbose) pline("It reads:"); - Sprintf(buf, "I explored the Dungeons of Doom, %s.", - Hallucination ? - (scroll == uarmu ? - /* (force these two to have identical length) */ - "and never did any laundry..." : - "and couldn't find my way out") : - "but all I got was this lousy T-shirt"); + Strcpy(buf, shirt_msgs[scroll->o_id % SIZE(shirt_msgs)]); erosion = greatest_erosion(scroll); if (erosion) wipeout_text(buf, @@ -123,14 +136,16 @@ doread() scroll->in_use = TRUE; /* scroll, not spellbook, now being read */ if(scroll->otyp != SCR_BLANK_PAPER) { if(Blind) - pline("As you pronounce the formula on it, the scroll disappears."); + pline("As you %s the formula on it, the scroll disappears.", + is_silent(youmonst.data) ? "cogitate" : "pronounce"); else pline("As you read the scroll, it disappears."); if(confused) { if (Hallucination) pline("Being so trippy, you screw up..."); else - pline("Being confused, you mispronounce the magic words..."); + pline("Being confused, you mis%s the magic words...", + is_silent(youmonst.data) ? "understand" : "pronounce"); } } if(!seffects(scroll)) { @@ -158,7 +173,7 @@ register struct obj *obj; obj->spe = 0; if (obj->otyp == OIL_LAMP || obj->otyp == BRASS_LANTERN) obj->age = 0; - Your("%s vibrates briefly.",xname(obj)); + Your("%s %s briefly.",xname(obj), otense(obj, "vibrate")); } else pline(nothing_happens); } } @@ -168,7 +183,7 @@ p_glow1(otmp) register struct obj *otmp; { Your("%s %s briefly.", xname(otmp), - Blind ? "vibrates" : "glows"); + otense(otmp, Blind ? "vibrate" : "glow")); } static void @@ -176,10 +191,11 @@ p_glow2(otmp,color) register struct obj *otmp; register const char *color; { - Your("%s %s%s for a moment.", + Your("%s %s%s%s for a moment.", xname(otmp), - Blind ? "vibrates" : "glows ", - Blind ? (const char *)"" : hcolor(color)); + otense(otmp, Blind ? "vibrate" : "glow"), + Blind ? "" : " ", + Blind ? nul : hcolor(color)); } /* Is the object chargeable? For purposes of inventory display; it is */ @@ -270,8 +286,8 @@ int curse_bless; /* destruction depends on current state, not adjustment */ if (obj->spe > rn2(7) || obj->spe <= -5) { - Your("%s pulsates momentarily, then explodes!", - xname(obj)); + Your("%s %s momentarily, then %s!", + xname(obj), otense(obj,"pulsate"), otense(obj,"explode")); if (is_on) Ring_gone(obj); s = rnd(3 * abs(obj->spe)); /* amount of damage */ useup(obj); @@ -350,7 +366,7 @@ int curse_bless; stripspe(obj); if (obj->lamplit) { if (!Blind) - pline("%s goes out!", The(xname(obj))); + pline("%s out!", Tobjnam(obj, "go")); end_burn(obj, TRUE); } } else if (is_blessed) { @@ -430,12 +446,11 @@ forget_single_object(obj_id) objects[obj_id].oc_name_known = 0; objects[obj_id].oc_pre_discovered = 0; /* a discovery when relearned */ if (objects[obj_id].oc_uname) { - /* this only works if oc_name_known is false */ - undiscover_object(obj_id); - free((genericptr_t)objects[obj_id].oc_uname); objects[obj_id].oc_uname = 0; } + undiscover_object(obj_id); /* after clearing oc_name_known */ + /* clear & free object names from matching inventory items too? */ } @@ -623,6 +638,22 @@ int howmuch; docrt(); /* this correctly will reset vision */ } +/* monster is hit by scroll of taming's effect */ +static void +maybe_tame(mtmp, sobj) +struct monst *mtmp; +struct obj *sobj; +{ + if (sobj->cursed) { + setmangry(mtmp); + } else { + if (mtmp->isshk) + make_happy_shk(mtmp, FALSE); + else if (!resist(mtmp, sobj->oclass, 0, NOTELL)) + (void) tamedog(mtmp, (struct obj *) 0); + } +} + int seffects(sobj) register struct obj *sobj; @@ -664,26 +695,28 @@ register struct obj *sobj; otmp->oerodeproof = !(sobj->cursed); if(Blind) { otmp->rknown = FALSE; - Your("%s feels warm for a moment.", - xname(otmp)); + Your("%s %s warm for a moment.", + xname(otmp), otense(otmp, "feel")); } else { otmp->rknown = TRUE; - Your("%s is covered by a %s %s %s!", - xname(otmp), + Your("%s %s covered by a %s %s %s!", + xname(otmp), otense(otmp, "are"), sobj->cursed ? "mottled" : "shimmering", hcolor(sobj->cursed ? Black : golden), sobj->cursed ? "glow" : (is_shield(otmp) ? "layer" : "shield")); } - if (otmp->oerodeproof && (otmp->oeroded || otmp->oeroded2)) { + if (otmp->oerodeproof && + (otmp->oeroded || otmp->oeroded2)) { otmp->oeroded = otmp->oeroded2 = 0; Your("%s %s as good as new!", - xname(otmp), Blind ? "feels" : "looks"); + xname(otmp), + otense(otmp, Blind ? "feel" : "look")); } break; } special_armor = is_elven_armor(otmp) || - (Role_if(PM_WIZARD) && otmp->otyp == CORNUTHAUM); + (Role_if(PM_WIZARD) && otmp->otyp == CORNUTHAUM); if (sobj->cursed) same_color = (otmp->otyp == BLACK_DRAGON_SCALE_MAIL || @@ -698,11 +731,13 @@ register struct obj *sobj; /* KMH -- catch underflow */ s = sobj->cursed ? -otmp->spe : otmp->spe; if (s > (special_armor ? 5 : 3) && rn2(s)) { - Your("%s violently %s%s%s for a while, then evaporates.", - xname(otmp), - Blind ? "vibrates" : "glows", - (!Blind && !same_color) ? " " : nul, - (Blind || same_color) ? nul : hcolor(sobj->cursed ? Black : silver)); + Your("%s violently %s%s%s for a while, then %s.", + xname(otmp), + otense(otmp, Blind ? "vibrate" : "glow"), + (!Blind && !same_color) ? " " : nul, + (Blind || same_color) ? nul : + hcolor(sobj->cursed ? Black : silver), + otense(otmp, "evaporate")); if(is_cloak(otmp)) (void) Cloak_off(); if(is_boots(otmp)) (void) Boots_off(); if(is_helmet(otmp)) (void) Helmet_off(); @@ -735,7 +770,7 @@ register struct obj *sobj; Your("%s %s%s%s%s for a %s.", xname(otmp), s == 0 ? "violently " : nul, - Blind ? "vibrates" : "glows", + otense(otmp, Blind ? "vibrate" : "glow"), (!Blind && !same_color) ? " " : nul, (Blind || same_color) ? nul : hcolor(sobj->cursed ? Black : silver), (s*s>1) ? "while" : "moment"); @@ -750,8 +785,8 @@ register struct obj *sobj; if ((otmp->spe > (special_armor ? 5 : 3)) && (special_armor || !rn2(7))) - Your("%s suddenly vibrates %s.", - xname(otmp), + Your("%s suddenly %s %s.", + xname(otmp), otense(otmp, "vibrate"), Blind ? "again" : "unexpectedly"); break; } @@ -778,7 +813,7 @@ register struct obj *sobj; } else known = TRUE; } else { /* armor and scroll both cursed */ - Your("%s vibrates.", xname(otmp)); + Your("%s %s.", xname(otmp), otense(otmp, "vibrate")); if (otmp->spe >= -6) otmp->spe--; make_stunned(HStun + rn1(10, 10), TRUE); } @@ -821,7 +856,11 @@ register struct obj *sobj; makeplural(body_part(HAND)), u.umconf ? "n even more" : "", hcolor(red)); - u.umconf += rn1(8, 2); + /* after a while, repeated uses become less effective */ + if (u.umconf >= 40) + u.umconf++; + else + u.umconf += rn1(8, 2); } } break; @@ -838,7 +877,7 @@ register struct obj *sobj; mtmp->mcanmove = 1; } else if (! resist(mtmp, sobj->oclass, 0, NOTELL)) - mtmp->mflee = 1; + monflee(mtmp, 0, FALSE, FALSE); if(!mtmp->mtame) ct++; /* pets don't laugh at you */ } } @@ -873,16 +912,21 @@ register struct obj *sobj; else You_feel("like someone is helping you."); - if(sobj->cursed) pline_The("scroll disintegrates."); - else { - for(obj = invent; obj ; obj = obj->nobj) - if(sobj->blessed || obj->owornmask || - (obj->otyp == LOADSTONE)) { + if (sobj->cursed) { + pline_The("scroll disintegrates."); + } else { + for (obj = invent; obj; obj = obj->nobj) + if (sobj->blessed || + (obj->owornmask && + ((obj->owornmask & ~W_SWAPWEP) || u.twoweap)) || + obj->otyp == LOADSTONE || + (obj->otyp == LEASH && obj->leashmon)) { if(confused) blessorcurse(obj, 2); else uncurse(obj); } } if(Punished && !confused) unpunish(); + update_inventory(); break; } case SCR_CREATE_MONSTER: @@ -924,23 +968,19 @@ register struct obj *sobj; break; case SCR_TAMING: case SPE_CHARM_MONSTER: - { register int i,j; - register int bd = confused ? 5 : 1; - register struct monst *mtmp; + if (u.uswallow) { + maybe_tame(u.ustuck, sobj); + } else { + int i, j, bd = confused ? 5 : 1; + struct monst *mtmp; - for(i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) - if(isok(u.ux+i, u.uy+j) && (mtmp = m_at(u.ux+i, u.uy+j))) { - if(sobj->cursed) { - setmangry(mtmp); - } else { - if (mtmp->isshk) - make_happy_shk(mtmp, FALSE); - else if (!resist(mtmp, sobj->oclass, 0, NOTELL)) - (void) tamedog(mtmp, (struct obj *) 0); + for (i = -bd; i <= bd; i++) for(j = -bd; j <= bd; j++) { + if (!isok(u.ux + i, u.uy + j)) continue; + if ((mtmp = m_at(u.ux + i, u.uy + j)) != 0) + maybe_tame(mtmp, sobj); } } break; - } case SCR_GENOCIDE: You("have found a scroll of genocide!"); known = TRUE; @@ -987,6 +1027,7 @@ register struct obj *sobj; /* Note: if rn2(5)==0, identify all items */ if (cval == 1 && sobj->blessed && Luck > 0) ++cval; } else cval = 1; + if(!objects[sobj->otyp].oc_name_known) more_experienced(0,10); useup(sobj); makeknown(SCR_IDENTIFY); id: @@ -1065,6 +1106,7 @@ register struct obj *sobj; * some damage under all potential cases. */ cval = bcsign(sobj); + if(!objects[sobj->otyp].oc_name_known) more_experienced(0,10); useup(sobj); makeknown(SCR_FIRE); if(confused) { @@ -1089,7 +1131,7 @@ register struct obj *sobj; burn_away_slime(); } explode(u.ux, u.uy, 11, (2*(rn1(3, 3) + 2 * cval) + 1)/3, - SCROLL_CLASS); + SCROLL_CLASS, EXPL_FIERY); return(1); case SCR_EARTH: /* TODO: handle steeds */ @@ -1153,7 +1195,7 @@ register struct obj *sobj; if (canspotmon(mtmp)) pline("%s's %s does not protect %s.", Monnam(mtmp), xname(helmet), - him[pronoun_gender(mtmp)]); + mhim(mtmp)); } } mtmp->mhp -= mdmg; @@ -1286,7 +1328,11 @@ struct obj *obj; pline("It seems even darker in here than before."); return; } - You("are surrounded by darkness!"); + if (uwep && artifact_light(uwep) && uwep->lamplit) + pline("Suddenly, the only light left comes from %s!", + the(xname(uwep))); + else + You("are surrounded by darkness!"); } /* the magic douses lamps, et al, too */ @@ -1298,8 +1344,9 @@ struct obj *obj; if (Blind) goto do_it; if(u.uswallow){ if (is_animal(u.ustuck->data)) - pline("%s stomach is lit.", - s_suffix(Monnam(u.ustuck))); + pline("%s %s is lit.", + s_suffix(Monnam(u.ustuck)), + mbodypart(u.ustuck, STOMACH)); else if (is_whirly(u.ustuck->data)) pline("%s shines briefly.", @@ -1376,6 +1423,9 @@ do_class_genocide() buf); (void)mungspaces(buf); } while (buf[0]=='\033' || !buf[0]); + /* choosing "none" preserves genocideless conduct */ + if (!strcmpi(buf, "none")) return; + if (strlen(buf) == 1) { if (buf[0] == ILLOBJ_SYM) buf[0] = def_monsyms[S_MIMIC]; @@ -1499,12 +1549,14 @@ do_class_genocide() #define REALLY 1 #define PLAYER 2 +#define ONTHRONE 4 void do_genocide(how) int how; /* 0 = no genocide; create monsters (cursed scroll) */ /* 1 = normal genocide */ /* 3 = forced genocide of player */ +/* 5 (4 | 1) = normal genocide from throne */ { char buf[BUFSZ]; register int i, killplayer = 0; @@ -1525,6 +1577,17 @@ int how; } getlin("What monster do you want to genocide? [type the name]", buf); + (void)mungspaces(buf); + /* choosing "none" preserves genocideless conduct */ + if (!strcmpi(buf, "none")) { + /* ... but no free pass if cursed */ + if (!(how & REALLY)) { + ptr = rndmonst(); + if (!ptr) return; /* no message, like normal case */ + mndx = monsndx(ptr); + break; /* remaining checks don't apply */ + } else return; + } mndx = name_to_mon(buf); if (mndx == NON_PM || (mvitals[mndx].mvflags & G_GENOD)) { @@ -1591,11 +1654,17 @@ int how; mvitals[urace.malenum].mvflags |= (G_GENOD | G_NOCORPSE); u.uhp = -1; - killer_format = KILLED_BY_AN; - if (how & PLAYER) - killer = "genocidal confusion"; - else /* selected player deliberately, not confused */ - killer = "scroll of genocide"; + if (how & PLAYER) { + killer_format = KILLED_BY; + killer = "genocidal confusion"; + } else if (how & ONTHRONE) { + /* player selected while on a throne */ + killer_format = KILLED_BY_AN; + killer = "imperious order"; + } else { /* selected player deliberately, not confused */ + killer_format = KILLED_BY_AN; + killer = "scroll of genocide"; + } /* Polymorphed characters will die as soon as they're rehumanized. */ /* KMH -- Unchanging prevents rehumanization */ @@ -1700,23 +1769,56 @@ boolean revival; boolean create_particular() { - char buf[BUFSZ]; - int which, tries = 0; + char buf[BUFSZ], monclass = MAXMCLASSES; + int which = PM_PLAYERMON, tries = 0, i; + struct permonst *whichpm = 0; + struct monst *mtmp; + boolean madeany = FALSE; + boolean maketame = FALSE; do { - getlin("Create what kind of monster? [type the name]", buf); + getlin("Create what kind of monster? [type the name or symbol]", + buf); if (buf[0] == '\033') return FALSE; - which = name_to_mon(buf); - if (which < LOW_PM) pline("I've never heard of such monsters."); - else break; + (void)mungspaces(buf); + if (strlen(buf) == 1) { + monclass = def_char_to_monclass(buf[0]); + if (monclass == MAXMCLASSES) + pline("I've never heard of such monsters."); + else break; + } else { + if (!strncmpi(buf, "tame ", 5)) { + which = name_to_mon(buf+5); + maketame = TRUE; + } else { + which = name_to_mon(buf); + maketame = FALSE; + } + if (which < LOW_PM) pline("I've never heard of such monsters."); + else { + whichpm = &mons[which]; + break; + } + } } while (++tries < 5); if (tries == 5) pline(thats_enough_tries); else { (void) cant_create(&which, FALSE); - return((boolean)(makemon(&mons[which], - u.ux, u.uy, NO_MM_FLAGS) != 0)); + for (i = 0; i <= multi; i++) { + if (monclass != MAXMCLASSES) + whichpm = mkclass(monclass, 0); + if (maketame) { + mtmp = makemon(whichpm, u.ux, u.uy, MM_EDOG); + if (mtmp) { + initedog(mtmp); + set_malign(mtmp); + } + } else + mtmp = makemon(whichpm, u.ux, u.uy, NO_MM_FLAGS); + if (mtmp) madeany = TRUE; + } } - return FALSE; + return madeany; } #endif /* WIZARD */ diff --git a/src/rect.c b/src/rect.c index a967ca8..dc6be73 100644 --- a/src/rect.c +++ b/src/rect.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)rect.c 3.3 90/02/22 */ +/* SCCS Id: @(#)rect.c 3.4 1990/02/22 */ /* Copyright (c) 1990 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/src/region.c b/src/region.c index a5b9b97..3e0d63f 100644 --- a/src/region.c +++ b/src/region.c @@ -1,8 +1,9 @@ -/* SCCS Id: @(#)region.c 3.3 1999/12/29 */ +/* SCCS Id: @(#)region.c 3.4 1999/12/29 */ /* Copyright (c) 1996 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" +#include "lev.h" /* * This should really go into the level structure, but @@ -391,7 +392,7 @@ run_regions() /* Check if any monster is inside region */ if (f_indx != NO_CALLBACK) { for (j = 0; j < regions[i]->n_monst; j++) { - struct monst *mtmp = find_mid(regions[i]->monsters[j], FM_EVERYWHERE); + struct monst *mtmp = find_mid(regions[i]->monsters[j], FM_FMON); if (!mtmp || mtmp->mhp <= 0 || (*callbacks[f_indx])(regions[i], mtmp)) { @@ -613,6 +614,8 @@ int mode; int i, j; unsigned n; + if (!perform_bwrite(mode)) goto skip_lots; + bwrite(fd, (genericptr_t) &moves, sizeof (moves)); /* timestamp */ bwrite(fd, (genericptr_t) &n_regions, sizeof (n_regions)); for (i = 0; i < n_regions; i++) { @@ -647,6 +650,10 @@ int mode; bwrite(fd, (genericptr_t) ®ions[i]->glyph, sizeof (int)); bwrite(fd, (genericptr_t) ®ions[i]->arg, sizeof (genericptr_t)); } + +skip_lots: + if (release_data(mode)) + clear_regions(); } void @@ -883,6 +890,10 @@ genericptr_t p2; if (cansee(mtmp->mx, mtmp->my)) pline("%s coughs!", Monnam(mtmp)); setmangry(mtmp); + if (haseyes(mtmp->data) && mtmp->mcansee) { + mtmp->mblinded = 1; + mtmp->mcansee = 0; + } if (resists_poison(mtmp)) return FALSE; mtmp->mhp -= rnd(dam) + 5; diff --git a/src/restore.c b/src/restore.c index 9dee238..7038693 100644 --- a/src/restore.c +++ b/src/restore.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)restore.c 3.3 1999/11/20 */ +/* SCCS Id: @(#)restore.c 3.4 1999/11/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -8,6 +8,7 @@ #ifdef MICRO extern int dotcnt; /* shared with save */ +extern int dotrow; /* shared with save */ #endif #ifdef USE_TILES @@ -220,6 +221,7 @@ boolean ghostly, frozen; for (otmp3 = otmp->cobj; otmp3; otmp3 = otmp3->nobj) otmp3->ocontainer = otmp; } + if (otmp->bypass) otmp->bypass = 0; otmp2 = otmp; } @@ -338,9 +340,9 @@ register struct obj *otmp; STATIC_OVL boolean -restgamestate(fd, mid, steedid) +restgamestate(fd, stuckid, steedid) register int fd; -unsigned int *mid, *steedid; /* STEED */ +unsigned int *stuckid, *steedid; /* STEED */ { struct obj *otmp; int uid; @@ -357,6 +359,8 @@ unsigned int *mid, *steedid; /* STEED */ } mread(fd, (genericptr_t) &flags, sizeof(struct flag)); + flags.bypasses = 0; /* never use the saved value of bypasses */ + role_init(); /* Reset the initial role, race, gender, and alignment */ #ifdef AMII_GRAPHICS amii_setpens(amii_numcolors); /* use colors from save file */ @@ -366,7 +370,7 @@ unsigned int *mid, *steedid; /* STEED */ #ifdef CLIPPING cliparound(u.ux, u.uy); #endif - if(u.uhp <= 0) { + if(u.uhp <= 0 && (!Upolyd || u.mh <= 0)) { u.ux = u.uy = 0; /* affects pline() [hence You()] */ You("were not healthy enough to survive restoration."); /* wiz1_level.dlevel is used by mklev.c to see if lots of stuff is @@ -409,10 +413,10 @@ unsigned int *mid, *steedid; /* STEED */ sizeof(struct spell) * (MAXSPELL + 1)); restore_artifacts(fd); restore_oracles(fd); - if(u.ustuck) - mread(fd, (genericptr_t) mid, sizeof (*mid)); + if (u.ustuck) + mread(fd, (genericptr_t) stuckid, sizeof (*stuckid)); #ifdef STEED - if(u.usteed) + if (u.usteed) mread(fd, (genericptr_t) steedid, sizeof (*steedid)); #endif mread(fd, (genericptr_t) pl_character, sizeof pl_character); @@ -434,19 +438,19 @@ unsigned int *mid, *steedid; /* STEED */ * don't dereference a wild u.ustuck when saving the game state, for instance) */ STATIC_OVL void -restlevelstate(mid, steedid) -unsigned int mid, steedid; /* STEED */ +restlevelstate(stuckid, steedid) +unsigned int stuckid, steedid; /* STEED */ { register struct monst *mtmp; - if (u.ustuck) { + if (stuckid) { for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) - if (mtmp->m_id == mid) break; + if (mtmp->m_id == stuckid) break; if (!mtmp) panic("Cannot find the monster ustuck."); u.ustuck = mtmp; } #ifdef STEED - if (u.usteed) { + if (steedid) { for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) if (mtmp->m_id == steedid) break; if (!mtmp) panic("Cannot find the monster usteed."); @@ -461,7 +465,7 @@ STATIC_OVL int restlevelfile(fd, ltmp) register int fd; xchar ltmp; -#ifdef applec +#if defined(macintosh) && (defined(__SC__) || defined(__MRC__)) # pragma unused(fd) #endif { @@ -519,14 +523,14 @@ int dorecover(fd) register int fd; { - unsigned int mid = 0, steedid = 0; /* not a register */ + unsigned int stuckid = 0, steedid = 0; /* not a register */ xchar ltmp; int rtmp; struct obj *otmp; restoring = TRUE; getlev(fd, 0, (xchar)0, FALSE); - if (!restgamestate(fd, &mid, &steedid)) { + if (!restgamestate(fd, &stuckid, &steedid)) { display_nhwindow(WIN_MESSAGE, TRUE); savelev(-1, 0, FREE_SAVE); /* discard current level */ (void) close(fd); @@ -534,13 +538,23 @@ register int fd; restoring = FALSE; return(0); } - restlevelstate(mid, steedid); + restlevelstate(stuckid, steedid); #ifdef INSURANCE savestateinlock(); #endif rtmp = restlevelfile(fd, ledger_no(&u.uz)); if (rtmp < 2) return(rtmp); /* dorecover called recursively */ + /* these pointers won't be valid while we're processing the + * other levels, but they'll be reset again by restlevelstate() + * afterwards, and in the meantime at least u.usteed may mislead + * place_monster() on other levels + */ + u.ustuck = (struct monst *)0; +#ifdef STEED + u.usteed = (struct monst *)0; +#endif + #ifdef MICRO # ifdef AMII_GRAPHICS { @@ -560,6 +574,7 @@ register int fd; flags.explore ? " while in explore mode" : ""); curs(WIN_MAP, 1, 1); dotcnt = 0; + dotrow = 2; if (strncmpi("X11", windowprocs.name, 3)) putstr(WIN_MAP, 0, "Restoring:"); #endif @@ -572,7 +587,11 @@ register int fd; break; getlev(fd, 0, ltmp, FALSE); #ifdef MICRO - curs(WIN_MAP, 1+dotcnt++, 2); + curs(WIN_MAP, 1+dotcnt++, dotrow); + if (dotcnt >= (COLNO - 1)) { + dotrow++; + dotcnt = 0; + } if (strncmpi("X11", windowprocs.name, 3)){ putstr(WIN_MAP, 0, "."); } @@ -599,7 +618,7 @@ register int fd; #ifdef USE_TILES substitute_tiles(&u.uz); #endif - restlevelstate(mid, steedid); + restlevelstate(stuckid, steedid); #ifdef MFLOPPY gameDiskPrompt(); #endif @@ -732,6 +751,10 @@ boolean ghostly; mread(fd, (genericptr_t)&level.flags, sizeof(level.flags)); mread(fd, (genericptr_t)doors, sizeof(doors)); rest_rooms(fd); /* No joke :-) */ + if (nroom) + doorindex = rooms[nroom - 1].fdoor + rooms[nroom - 1].doorct; + else + doorindex = 0; restore_timers(fd, RANGE_LEVEL, ghostly, monstermoves - omoves); restore_light_sources(fd); @@ -920,7 +943,12 @@ boolean ghostly; { struct obj *otmp; unsigned oldid, nid; - for (otmp = fobj; otmp; otmp = otmp->nobj) + for (otmp = fobj; otmp; otmp = otmp->nobj) { + if (ghostly && otmp->oattached == OATTACHED_MONST && otmp->oxlth) { + struct monst *mtmp = (struct monst *)otmp->oextra; + + mtmp->m_id = 0; + } if (ghostly && otmp->oattached == OATTACHED_M_ID) { (void) memcpy((genericptr_t)&oldid, (genericptr_t)otmp->oextra, sizeof(oldid)); @@ -930,6 +958,7 @@ boolean ghostly; else otmp->oattached = OATTACHED_NOTHING; } + } } diff --git a/src/rip.c b/src/rip.c index 344170a..cab4d2e 100644 --- a/src/rip.c +++ b/src/rip.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)rip.c 3.3 97/11/08 */ +/* SCCS Id: @(#)rip.c 3.4 2001/09/24 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -8,7 +8,7 @@ STATIC_DCL void FDECL(center, (int, char *)); extern const char *killed_by_prefix[]; -#if defined(TTY_GRAPHICS) || defined(X11_GRAPHICS) || defined(GEM_GRAPHICS) +#if defined(TTY_GRAPHICS) || defined(X11_GRAPHICS) || defined(GEM_GRAPHICS) || defined(MSWIN_GRAPHICS) # define TEXT_TOMBSTONE #endif #if defined(mac) || defined(__BEOS__) || defined(WIN32_GRAPHICS) @@ -108,7 +108,11 @@ int how; center(NAME_LINE, buf); /* Put $ on stone */ +#ifndef GOLDOBJ Sprintf(buf, "%ld Au", u.ugold); +#else + Sprintf(buf, "%ld Au", done_money); +#endif buf[STONE_LINE_LEN] = 0; /* It could be a *lot* of gold :-) */ center(GOLD_LINE, buf); diff --git a/src/rnd.c b/src/rnd.c index f359ac7..313b70b 100644 --- a/src/rnd.c +++ b/src/rnd.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)rnd.c 3.3 96/02/07 */ +/* SCCS Id: @(#)rnd.c 3.4 1996/02/07 */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" diff --git a/src/role.c b/src/role.c index e51f430..9da6409 100644 --- a/src/role.c +++ b/src/role.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)role.c 3.3 2000/05/21 */ +/* SCCS Id: @(#)role.c 3.4 2000/08/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */ /* NetHack may be freely redistributed. See license for details. */ @@ -108,9 +108,9 @@ const struct Role roles[] = { {"Empiric", 0}, {"Embalmer", 0}, {"Dresser", 0}, - {"Medici ossium", 0}, + {"Medicus ossium", "Medica ossium"}, {"Herbalist", 0}, - {"Magister", 0}, + {"Magister", "Magistra"}, {"Physician", 0}, {"Chirurgeon", 0} }, "_Athena", "Hermes", "Poseidon", /* Greek */ @@ -122,7 +122,7 @@ const struct Role roles[] = { MH_HUMAN|MH_GNOME | ROLE_MALE|ROLE_FEMALE | ROLE_NEUTRAL, /* Str Int Wis Dex Con Cha */ { 7, 7, 13, 7, 11, 16 }, - { 15, 20, 20, 15, 25, 10 }, + { 15, 20, 20, 15, 25, 5 }, /* Init Lower Higher */ { 11, 0, 0, 8, 1, 0 }, /* Hit points */ { 1, 4, 0, 1, 0, 2 },20, /* Energy */ @@ -135,8 +135,8 @@ const struct Role roles[] = { {"Sergeant", 0}, {"Knight", 0}, {"Banneret", 0}, - {"Chevalier", 0}, - {"Seignieur", 0}, + {"Chevalier", "Chevaliere"}, + {"Seignieur", "Dame"}, {"Paladin", 0} }, "Lugh", "_Brigit", "Manannan Mac Lir", /* Celtic */ "Kni", "Camelot Castle", "the Isle of Glass", @@ -147,7 +147,7 @@ const struct Role roles[] = { MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL, /* Str Int Wis Dex Con Cha */ { 13, 7, 14, 8, 10, 17 }, - { 20, 15, 15, 10, 20, 10 }, + { 30, 15, 15, 10, 20, 10 }, /* Init Lower Higher */ { 14, 0, 0, 8, 2, 0 }, /* Hit points */ { 1, 4, 0, 1, 0, 2 },10, /* Energy */ @@ -277,7 +277,7 @@ const struct Role roles[] = { { {"Samurai", 0}, { {"Hatamoto", 0}, /* Banner Knight */ {"Ronin", 0}, /* no allegiance */ - {"Ninja", 0}, /* secret society */ + {"Ninja", "Kunoichi"}, /* secret society */ {"Joshu", 0}, /* heads a castle */ {"Ryoshu", 0}, /* has a territory */ {"Kokushu", 0}, /* heads a province */ @@ -293,7 +293,7 @@ const struct Role roles[] = { MH_HUMAN | ROLE_MALE|ROLE_FEMALE | ROLE_LAWFUL, /* Str Int Wis Dex Con Cha */ { 10, 8, 7, 10, 17, 6 }, - { 30, 10, 10, 30, 14, 10 }, + { 30, 10, 8, 30, 14, 8 }, /* Init Lower Higher */ { 13, 0, 0, 8, 1, 0 }, /* Hit points */ { 1, 0, 0, 1, 0, 1 },11, /* Energy */ @@ -362,9 +362,9 @@ const struct Role roles[] = { {"Wizard", 0}, {"Mage", 0} }, "Ptah", "Thoth", "Anhur", /* Egyptian */ - "Wiz", "the Tower of the Balance", "the Tower of Darkness", + "Wiz", "the Lonely Tower", "the Tower of Darkness", PM_WIZARD, NON_PM, PM_KITTEN, - PM_WIZARD_OF_BALANCE, PM_APPRENTICE, PM_DARK_ONE, + PM_NEFERET_THE_GREEN, PM_APPRENTICE, PM_DARK_ONE, PM_VAMPIRE_BAT, PM_XORN, S_BAT, S_WRAITH, ART_EYE_OF_THE_AETHIOPICA, MH_HUMAN|MH_ELF|MH_GNOME|MH_ORC | ROLE_MALE|ROLE_FEMALE | @@ -502,6 +502,10 @@ const struct Align aligns[] = { {"evil", "unaligned", "Una", 0, A_NONE} }; +STATIC_DCL char * FDECL(promptsep, (char *, int)); +STATIC_DCL int FDECL(role_gendercount, (int)); +STATIC_DCL int FDECL(race_alignmentcount, (int)); + /* used by str2XXX() */ static char NEARDATA randomstr[] = "random"; @@ -789,9 +793,11 @@ int rolenum, racenum, gendnum, alignnum; } /* pick a random role subject to any racenum/gendnum/alignnum constraints */ +/* If pickhow == PICK_RIGID a role is returned only if there is */ +/* a single possibility */ int -pick_role(racenum, gendnum, alignnum) -int racenum, gendnum, alignnum; +pick_role(racenum, gendnum, alignnum, pickhow) +int racenum, gendnum, alignnum, pickhow; { int i; int roles_ok = 0; @@ -800,7 +806,7 @@ int racenum, gendnum, alignnum; if (ok_role(i, racenum, gendnum, alignnum)) roles_ok++; } - if (roles_ok == 0) + if (roles_ok == 0 || (roles_ok > 1 && pickhow == PICK_RIGID)) return ROLE_NONE; roles_ok = rn2(roles_ok); for (i = 0; i < SIZE(roles)-1; i++) { @@ -853,9 +859,11 @@ int rolenum, racenum, gendnum, alignnum; } /* pick a random race subject to any rolenum/gendnum/alignnum constraints */ +/* If pickhow == PICK_RIGID a race is returned only if there is */ +/* a single possibility */ int -pick_race(rolenum, gendnum, alignnum) -int rolenum, gendnum, alignnum; +pick_race(rolenum, gendnum, alignnum, pickhow) +int rolenum, gendnum, alignnum, pickhow; { int i; int races_ok = 0; @@ -864,7 +872,7 @@ int rolenum, gendnum, alignnum; if (ok_race(rolenum, i, gendnum, alignnum)) races_ok++; } - if (races_ok == 0) + if (races_ok == 0 || (races_ok > 1 && pickhow == PICK_RIGID)) return ROLE_NONE; races_ok = rn2(races_ok); for (i = 0; i < SIZE(races)-1; i++) { @@ -913,9 +921,11 @@ int rolenum, racenum, gendnum, alignnum; /* pick a random gender subject to any rolenum/racenum/alignnum constraints */ /* gender and alignment are not comparable (and also not constrainable) */ +/* If pickhow == PICK_RIGID a gender is returned only if there is */ +/* a single possibility */ int -pick_gend(rolenum, racenum, alignnum) -int rolenum, racenum, alignnum; +pick_gend(rolenum, racenum, alignnum, pickhow) +int rolenum, racenum, alignnum, pickhow; { int i; int gends_ok = 0; @@ -924,7 +934,7 @@ int rolenum, racenum, alignnum; if (ok_gend(rolenum, racenum, i, alignnum)) gends_ok++; } - if (gends_ok == 0) + if (gends_ok == 0 || (gends_ok > 1 && pickhow == PICK_RIGID)) return ROLE_NONE; gends_ok = rn2(gends_ok); for (i = 0; i < ROLE_GENDERS; i++) { @@ -973,9 +983,11 @@ int rolenum, racenum, gendnum, alignnum; /* pick a random alignment subject to any rolenum/racenum/gendnum constraints */ /* alignment and gender are not comparable (and also not constrainable) */ +/* If pickhow == PICK_RIGID an alignment is returned only if there is */ +/* a single possibility */ int -pick_align(rolenum, racenum, gendnum) -int rolenum, racenum, gendnum; +pick_align(rolenum, racenum, gendnum, pickhow) +int rolenum, racenum, gendnum, pickhow; { int i; int aligns_ok = 0; @@ -984,7 +996,7 @@ int rolenum, racenum, gendnum; if (ok_align(rolenum, racenum, gendnum, i)) aligns_ok++; } - if (aligns_ok == 0) + if (aligns_ok == 0 || (aligns_ok > 1 && pickhow == PICK_RIGID)) return ROLE_NONE; aligns_ok = rn2(aligns_ok); for (i = 0; i < ROLE_ALIGNS; i++) { @@ -998,6 +1010,283 @@ int rolenum, racenum, gendnum; return ROLE_NONE; } +void +rigid_role_checks() +{ + /* Some roles are limited to a single race, alignment, or gender and + * calling this routine prior to XXX_player_selection() will help + * prevent an extraneous prompt that actually doesn't allow + * you to choose anything further. Note the use of PICK_RIGID which + * causes the pick_XX() routine to return a value only if there is one + * single possible selection, otherwise it returns ROLE_NONE. + * + */ + if (flags.initrole == ROLE_RANDOM) { + /* If the role was explicitly specified as ROLE_RANDOM + * via -uXXXX-@ then choose the role in here to narrow down + * later choices. Pick a random role in this case. + */ + flags.initrole = pick_role(flags.initrace, flags.initgend, + flags.initalign, PICK_RANDOM); + if (flags.initrole < 0) + flags.initrole = randrole(); + } + if (flags.initrole != ROLE_NONE) { + if (flags.initrace == ROLE_NONE) + flags.initrace = pick_race(flags.initrole, flags.initgend, + flags.initalign, PICK_RIGID); + if (flags.initalign == ROLE_NONE) + flags.initalign = pick_align(flags.initrole, flags.initrace, + flags.initgend, PICK_RIGID); + if (flags.initgend == ROLE_NONE) + flags.initgend = pick_gend(flags.initrole, flags.initrace, + flags.initalign, PICK_RIGID); + } +} + +#define BP_ALIGN 0 +#define BP_GEND 1 +#define BP_RACE 2 +#define BP_ROLE 3 +#define NUM_BP 4 + +STATIC_VAR char pa[NUM_BP], post_attribs; + +STATIC_OVL char * +promptsep(buf, num_post_attribs) +char *buf; +int num_post_attribs; +{ + const char *conj = "and "; + if (num_post_attribs > 1 + && post_attribs < num_post_attribs && post_attribs > 1) + Strcat(buf, ","); + Strcat(buf, " "); + --post_attribs; + if (!post_attribs && num_post_attribs > 1) Strcat(buf, conj); + return buf; +} + +STATIC_OVL int +role_gendercount(rolenum) +int rolenum; +{ + int gendcount = 0; + if (validrole(rolenum)) { + if (roles[rolenum].allow & ROLE_MALE) ++gendcount; + if (roles[rolenum].allow & ROLE_FEMALE) ++gendcount; + if (roles[rolenum].allow & ROLE_NEUTER) ++gendcount; + } + return gendcount; +} + +STATIC_OVL int +race_alignmentcount(racenum) +int racenum; +{ + int aligncount = 0; + if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) { + if (races[racenum].allow & ROLE_CHAOTIC) ++aligncount; + if (races[racenum].allow & ROLE_LAWFUL) ++aligncount; + if (races[racenum].allow & ROLE_NEUTRAL) ++aligncount; + } + return aligncount; +} + +char * +root_plselection_prompt(suppliedbuf, buflen, rolenum, racenum, gendnum, alignnum) +char *suppliedbuf; +int buflen, rolenum, racenum, gendnum, alignnum; +{ + int k, gendercount = 0, aligncount = 0; + char buf[BUFSZ]; + char *err_ret = " character's"; + boolean donefirst = FALSE; + + if (!suppliedbuf || buflen < 1) return err_ret; + + /* initialize these static variables each time this is called */ + post_attribs = 0; + for (k=0; k < NUM_BP; ++k) + pa[k] = 0; + buf[0] = '\0'; + *suppliedbuf = '\0'; + + /* How many alignments are allowed for the desired race? */ + if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) + aligncount = race_alignmentcount(racenum); + + if (alignnum != ROLE_NONE && alignnum != ROLE_RANDOM) { + /* if race specified, and multiple choice of alignments for it */ + if ((racenum >= 0) && (aligncount > 1)) { + if (donefirst) Strcat(buf, " "); + Strcat(buf, aligns[alignnum].adj); + donefirst = TRUE; + } else { + if (donefirst) Strcat(buf, " "); + Strcat(buf, aligns[alignnum].adj); + donefirst = TRUE; + } + } else { + /* if alignment not specified, but race is specified + and only one choice of alignment for that race then + don't include it in the later list */ + if ((((racenum != ROLE_NONE && racenum != ROLE_RANDOM) && + ok_race(rolenum, racenum, gendnum, alignnum)) + && (aligncount > 1)) + || (racenum == ROLE_NONE || racenum == ROLE_RANDOM)) { + pa[BP_ALIGN] = 1; + post_attribs++; + } + } + /* */ + + /* How many genders are allowed for the desired role? */ + if (validrole(rolenum)) + gendercount = role_gendercount(rolenum); + + if (gendnum != ROLE_NONE && gendnum != ROLE_RANDOM) { + if (validrole(rolenum)) { + /* if role specified, and multiple choice of genders for it, + and name of role itself does not distinguish gender */ + if ((rolenum != ROLE_NONE) && (gendercount > 1) + && !roles[rolenum].name.f) { + if (donefirst) Strcat(buf, " "); + Strcat(buf, genders[gendnum].adj); + donefirst = TRUE; + } + } else { + if (donefirst) Strcat(buf, " "); + Strcat(buf, genders[gendnum].adj); + donefirst = TRUE; + } + } else { + /* if gender not specified, but role is specified + and only one choice of gender then + don't include it in the later list */ + if ((validrole(rolenum) && (gendercount > 1)) || !validrole(rolenum)) { + pa[BP_GEND] = 1; + post_attribs++; + } + } + /* */ + + if (racenum != ROLE_NONE && racenum != ROLE_RANDOM) { + if (validrole(rolenum) && ok_race(rolenum, racenum, gendnum, alignnum)) { + if (donefirst) Strcat(buf, " "); + Strcat(buf, (rolenum == ROLE_NONE) ? + races[racenum].noun : + races[racenum].adj); + donefirst = TRUE; + } else if (!validrole(rolenum)) { + if (donefirst) Strcat(buf, " "); + Strcat(buf, races[racenum].noun); + donefirst = TRUE; + } else { + pa[BP_RACE] = 1; + post_attribs++; + } + } else { + pa[BP_RACE] = 1; + post_attribs++; + } + /* || */ + + if (validrole(rolenum)) { + if (donefirst) Strcat(buf, " "); + if (gendnum != ROLE_NONE) { + if (gendnum == 1 && roles[rolenum].name.f) + Strcat(buf, roles[rolenum].name.f); + else + Strcat(buf, roles[rolenum].name.m); + } else { + if (roles[rolenum].name.f) { + Strcat(buf, roles[rolenum].name.m); + Strcat(buf, "/"); + Strcat(buf, roles[rolenum].name.f); + } else + Strcat(buf, roles[rolenum].name.m); + } + donefirst = TRUE; + } else if (rolenum == ROLE_NONE) { + pa[BP_ROLE] = 1; + post_attribs++; + } + + if ((racenum == ROLE_NONE || racenum == ROLE_RANDOM) && !validrole(rolenum)) { + if (donefirst) Strcat(buf, " "); + Strcat(buf, "character"); + donefirst = TRUE; + } + /* || + * || + */ + if (buflen > (int) (strlen(buf) + 1)) { + Strcpy(suppliedbuf, buf); + return suppliedbuf; + } else + return err_ret; +} + +char * +build_plselection_prompt(buf, buflen, rolenum, racenum, gendnum, alignnum) +char *buf; +int buflen, rolenum, racenum, gendnum, alignnum; +{ + const char *defprompt = "Shall I pick a character for you? [ynq] "; + int num_post_attribs = 0; + char tmpbuf[BUFSZ]; + + if (buflen < QBUFSZ) + return (char *)defprompt; + + Strcpy(tmpbuf, "Shall I pick "); + if (racenum != ROLE_NONE || validrole(rolenum)) + Strcat(tmpbuf, "your "); + else { + Strcat(tmpbuf, "a "); + } + /* */ + + (void) root_plselection_prompt(eos(tmpbuf), buflen - strlen(tmpbuf), + rolenum, racenum, gendnum, alignnum); + Sprintf(buf, "%s", s_suffix(tmpbuf)); + + /* buf should now be: + * < your lawful female gnomish cavewoman's> || + * || + * + * Now append the post attributes to it + */ + + num_post_attribs = post_attribs; + if (post_attribs) { + if (pa[BP_RACE]) { + (void) promptsep(eos(buf), num_post_attribs); + Strcat(buf, "race"); + } + if (pa[BP_ROLE]) { + (void) promptsep(eos(buf), num_post_attribs); + Strcat(buf, "role"); + } + if (pa[BP_GEND]) { + (void) promptsep(eos(buf), num_post_attribs); + Strcat(buf, "gender"); + } + if (pa[BP_ALIGN]) { + (void) promptsep(eos(buf), num_post_attribs); + Strcat(buf, "alignment"); + } + } + Strcat(buf, " for you? [ynq] "); + return buf; +} + +#undef BP_ALIGN +#undef BP_GEND +#undef BP_RACE +#undef BP_ROLE +#undef NUM_BP void plnamesuffix() diff --git a/src/rumors.c b/src/rumors.c index 6476cc6..3272d1c 100644 --- a/src/rumors.c +++ b/src/rumors.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)rumors.c 3.3 96/04/20 */ +/* SCCS Id: @(#)rumors.c 3.4 1996/04/20 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -146,11 +146,16 @@ int mechanism; boolean reading = (mechanism == BY_COOKIE || mechanism == BY_PAPER); - if (reading && Blind) { + if (reading) { + /* deal with various things that prevent reading */ + if (is_fainted() && mechanism == BY_COOKIE) + return; + else if (Blind) { if (mechanism == BY_COOKIE) pline(fortune_msg); pline("What a pity that you cannot read it!"); - return; + return; + } } line = getrumor(truth, buf, reading ? FALSE : TRUE); if (!*line) @@ -282,6 +287,9 @@ int doconsult(oracl) register struct monst *oracl; { +#ifdef GOLDOBJ + long umoney = money_cnt(invent); +#endif int u_pay, minor_cost = 50, major_cost = 500 + 50 * u.ulevel; int add_xpts; char qbuf[QBUFSZ]; @@ -294,38 +302,59 @@ register struct monst *oracl; } else if (!oracl->mpeaceful) { pline("%s is in no mood for consultations.", Monnam(oracl)); return 0; +#ifndef GOLDOBJ } else if (!u.ugold) { +#else + } else if (!umoney) { +#endif You("have no money."); return 0; } Sprintf(qbuf, - "\"Wilt thou settle for a minor consultation?\" (%d zorkmids)", - minor_cost); + "\"Wilt thou settle for a minor consultation?\" (%d %s)", + minor_cost, currency((long)minor_cost)); switch (ynq(qbuf)) { default: case 'q': return 0; case 'y': +#ifndef GOLDOBJ if (u.ugold < (long)minor_cost) { +#else + if (umoney < (long)minor_cost) { +#endif You("don't even have enough money for that!"); return 0; } u_pay = minor_cost; break; case 'n': +#ifndef GOLDOBJ if (u.ugold <= (long)minor_cost || /* don't even ask */ +#else + if (umoney <= (long)minor_cost || /* don't even ask */ +#endif (oracle_cnt == 1 || oracle_flg < 0)) return 0; Sprintf(qbuf, - "\"Then dost thou desire a major one?\" (%d zorkmids)", - major_cost); + "\"Then dost thou desire a major one?\" (%d %s)", + major_cost, currency((long)major_cost)); if (yn(qbuf) != 'y') return 0; +#ifndef GOLDOBJ u_pay = (u.ugold < (long)major_cost ? (int)u.ugold : major_cost); +#else + u_pay = (umoney < (long)major_cost ? (int)umoney + : major_cost); +#endif break; } +#ifndef GOLDOBJ u.ugold -= (long)u_pay; oracl->mgold += (long)u_pay; +#else + money2mon(oracl, (long)u_pay); +#endif flags.botl = 1; add_xpts = 0; /* first oracle of each type gives experience points */ if (u_pay == minor_cost) { diff --git a/src/save.c b/src/save.c index 536065b..31f347a 100644 --- a/src/save.c +++ b/src/save.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)save.c 3.3 2000/07/27 */ +/* SCCS Id: @(#)save.c 3.4 2002/01/19 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -20,7 +20,7 @@ static int count_only; #endif #ifdef MICRO -int dotcnt; /* also used in restore */ +int dotcnt, dotrow; /* also used in restore */ #endif #ifdef ZEROCOMP @@ -43,14 +43,10 @@ static long nulls[10]; #define nulls nul #endif -#if defined(UNIX) || defined(VMS) || defined(__EMX__) +#if defined(UNIX) || defined(VMS) || defined(__EMX__) || defined(WIN32) #define HUP if (!program_state.done_hup) #else -# ifdef WIN32 -#define HUP if (!program_state.exiting) -# else #define HUP -# endif #endif /* need to preserve these during save to avoid accessing freed memory */ @@ -81,7 +77,7 @@ dosave() } -#if defined(UNIX) || defined(VMS) || defined (__EMX__) +#if defined(UNIX) || defined(VMS) || defined (__EMX__) || defined(WIN32) /*ARGSUSED*/ void hangup(sig_unused) /* called as signal() handler, so sent at least one arg */ @@ -94,14 +90,18 @@ int sig_unused; terminate(EXIT_FAILURE); # endif # else /* SAVEONHANGUP */ - if (!program_state.done_hup++ && program_state.something_worth_saving) { + if (!program_state.done_hup++) { + if (program_state.something_worth_saving) (void) dosave0(); # ifdef VMS - /* don't call exit when already within an exit handler; - that would cancel any other pending user-mode handlers */ - if (!program_state.exiting) + /* don't call exit when already within an exit handler; + that would cancel any other pending user-mode handlers */ + if (!program_state.exiting) # endif - terminate(EXIT_FAILURE); + { + clearlocks(); + terminate(EXIT_FAILURE); + } } # endif return; @@ -156,6 +156,9 @@ dosave0() return(0); } + vision_recalc(2); /* shut down vision to prevent problems + in the event of an impossible() call */ + /* undo date-dependent luck adjustments made at startup time */ if(flags.moonphase == FULL_MOON) /* ut-sally!fletcher */ change_luck(-1); /* and unido!ab */ @@ -166,6 +169,7 @@ dosave0() #ifdef MICRO dotcnt = 0; + dotrow = 2; curs(WIN_MAP, 1, 1); if (strncmpi("X11", windowprocs.name, 3)) putstr(WIN_MAP, 0, "Saving:"); @@ -182,9 +186,6 @@ dosave0() for (ltmp = 1; ltmp <= maxledgerno(); ltmp++) if (ltmp != ledger_no(&u.uz) && level_info[ltmp].where) needed += level_info[ltmp].size + (sizeof ltmp); -# ifdef AMIGA - needed += ami_wbench_iconsize(fq_save); -# endif fds = freediskspace(fq_save); if (needed > fds) { HUP { @@ -216,12 +217,23 @@ dosave0() */ uz_save = u.uz; u.uz.dnum = u.uz.dlevel = 0; + /* these pointers are no longer valid, and at least u.usteed + * may mislead place_monster() on other levels + */ + u.ustuck = (struct monst *)0; +#ifdef STEED + u.usteed = (struct monst *)0; +#endif for(ltmp = (xchar)1; ltmp <= maxledgerno(); ltmp++) { if (ltmp == ledger_no(&uz_save)) continue; if (!(level_info[ltmp].flags & LFILE_EXISTS)) continue; #ifdef MICRO - curs(WIN_MAP, 1 + dotcnt++, 2); + curs(WIN_MAP, 1 + dotcnt++, dotrow); + if (dotcnt >= (COLNO - 1)) { + dotrow++; + dotcnt = 0; + } if (strncmpi("X11", windowprocs.name, 3)){ putstr(WIN_MAP, 0, "."); } @@ -250,9 +262,6 @@ dosave0() delete_levelfile(ledger_no(&u.uz)); delete_levelfile(0); compress(fq_save); -#ifdef AMIGA - ami_wbench_iconwrite(fq_save); -#endif return(1); } @@ -831,7 +840,8 @@ register struct obj *otmp; if (Has_contents(otmp)) saveobjchn(fd,otmp->cobj,mode); if (release_data(mode)) { - if(otmp->oclass == FOOD_CLASS) food_disappears(otmp); + if (otmp->oclass == FOOD_CLASS) food_disappears(otmp); + if (otmp->oclass == SPBOOK_CLASS) book_disappears(otmp); otmp->where = OBJ_FREE; /* set to free so dealloc will work */ otmp->timed = 0; /* not timed any more */ otmp->lamplit = 0; /* caller handled lights */ @@ -981,6 +991,14 @@ freedynamicdata() free_waterlevel(); free_dungeons(); + /* some pointers in iflags */ + if (iflags.wc_font_map) free(iflags.wc_font_map); + if (iflags.wc_font_message) free(iflags.wc_font_message); + if (iflags.wc_font_text) free(iflags.wc_font_text); + if (iflags.wc_font_menu) free(iflags.wc_font_menu); + if (iflags.wc_font_status) free(iflags.wc_font_status); + if (iflags.wc_tile_file) free(iflags.wc_tile_file); + #endif /* FREE_ALL_MEMORY */ return; } diff --git a/src/shk.c b/src/shk.c index 7f69cd4..4c9b3b7 100644 --- a/src/shk.c +++ b/src/shk.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)shk.c 3.3 2000/03/28 */ +/* SCCS Id: @(#)shk.c 3.4 2002/01/19 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -63,6 +63,9 @@ STATIC_DCL void FDECL(dropped_container, (struct obj *, struct monst *, STATIC_DCL void FDECL(add_to_billobjs, (struct obj *)); STATIC_DCL void FDECL(bill_box_content, (struct obj *, BOOLEAN_P, BOOLEAN_P, struct monst *)); +#ifdef OVL1 +static void FDECL(rob_shop, (struct monst *)); +#endif #ifdef OVLB /* @@ -70,6 +73,81 @@ STATIC_DCL void FDECL(bill_box_content, (struct obj *, BOOLEAN_P, BOOLEAN_P, obj->quan <= bp->bquan */ + +#ifdef GOLDOBJ +/* + Transfer money from inventory to monster when paying + shopkeepers, priests, oracle, succubus, & other demons. + Simple with only gold coins. + This routine will handle money changing when multiple + coin types is implemented, only appropriate + monsters will pay change. (Peaceful shopkeepers, priests + & the oracle try to maintain goodwill while selling + their wares or services. Angry monsters and all demons + will keep anything they get their hands on. + Returns the amount actually paid, so we can know + if the monster kept the change. + */ +long money2mon(mon, amount) +struct monst *mon; +long amount; +{ + struct obj *ygold = findgold(invent); + + if (amount <= 0) { + impossible("%s payment in money2mon!", amount ? "negative" : "zero"); + return 0L; + } + if (!ygold || ygold->quan < amount) { + impossible("Paying without %s money?", ygold ? "enough" : ""); + return 0L; + } + + if (ygold->quan > amount) ygold = splitobj(ygold, amount); + else if (ygold->owornmask) remove_worn_item(ygold); /* quiver */ + freeinv(ygold); + add_to_minv(mon, ygold); + flags.botl = 1; + return amount; +} + + +/* + Transfer money from monster to inventory. + Used when the shopkeeper pay for items, and when + the priest gives you money for an ale. + */ +void +money2u(mon, amount) +struct monst *mon; +long amount; +{ + struct obj *mongold = findgold(mon->minvent); + + if (amount <= 0) { + impossible("%s payment in money2u!", amount ? "negative" : "zero"); + return; + } + if (!mongold || mongold->quan < amount) { + impossible("%s paying without %s money?", a_monnam(mon), + mongold ? "enough" : ""); + return; + } + + if (mongold->quan > amount) mongold = splitobj(mongold, amount); + obj_extract_self(mongold); + + if (!merge_choice(invent, mongold) && inv_cnt() >= 52) { + You("have no room for the money!"); + dropy(mongold); + } else { + addinv(mongold); + flags.botl = 1; + } +} + +#endif /* GOLDOBJ */ + STATIC_OVL struct monst * next_shkp(shkp, withbill) register struct monst *shkp; @@ -99,24 +177,36 @@ register struct monst *mtmp; void shkgone(mtmp) /* called in mon.c */ -register struct monst *mtmp; -{ - register struct eshk *eshk = ESHK(mtmp); +struct monst *mtmp; +{ + struct eshk *eshk = ESHK(mtmp); + struct mkroom *sroom = &rooms[eshk->shoproom - ROOMOFFSET]; + struct obj *otmp; + char *p; + int sx, sy; + + /* [BUG: some of this should be done on the shop level */ + /* even when the shk dies on a different level.] */ + if (on_level(&eshk->shoplevel, &u.uz)) { + remove_damage(mtmp, TRUE); + sroom->resident = (struct monst *)0; + if (!search_special(ANY_SHOP)) + level.flags.has_shop = 0; + + /* items on shop floor revert to ordinary objects */ + for (sx = sroom->lx; sx <= sroom->hx; sx++) + for (sy = sroom->ly; sy <= sroom->hy; sy++) + for (otmp = level.objects[sx][sy]; otmp; otmp = otmp->nexthere) + otmp->no_charge = 0; - if(on_level(&(eshk->shoplevel), &u.uz)) { - remove_damage(mtmp, TRUE); - rooms[eshk->shoproom - ROOMOFFSET].resident - = (struct monst *)0; - if(!search_special(ANY_SHOP)) - level.flags.has_shop = 0; - } - /* make sure bill is set only when the - * dead shk is the resident shk. */ - if(*u.ushops == eshk->shoproom) { - setpaid(mtmp); - /* dump core when referenced */ - ESHK(mtmp)->bill_p = (struct bill_x *) -1000; - u.ushops[0] = '\0'; + /* Make sure bill is set only when the + dead shk is the resident shk. */ + if ((p = index(u.ushops, eshk->shoproom)) != 0) { + setpaid(mtmp); + eshk->bill_p = (struct bill_x *)0; + /* remove eshk->shoproom from u.ushops */ + do { *p = *(p + 1); } while (*++p); + } } } @@ -178,13 +268,17 @@ register struct obj *list; #endif /*OVL3*/ #ifdef OVLB +/* either you paid or left the shop or the shopkeeper died */ STATIC_OVL void -setpaid(shkp) /* either you paid or left the shop or the shopkeeper died */ +setpaid(shkp) register struct monst *shkp; { register struct obj *obj; register struct monst *mtmp; + /* FIXME: object handling should be limited to + items which are on this particular shk's bill */ + clear_unpaid(invent); clear_unpaid(fobj); clear_unpaid(level.buriedobjlist); @@ -292,12 +386,11 @@ register xchar x, y; void u_left_shop(leavestring, newlev) -register char *leavestring; -register boolean newlev; +char *leavestring; +boolean newlev; { - register struct monst *shkp; - register struct eshk *eshkp; - register long total; + struct monst *shkp; + struct eshk *eshkp; /* * IF player @@ -311,14 +404,11 @@ register boolean newlev; return; shkp = shop_keeper(*u.ushops0); - - if(!shkp || !inhishop(shkp)) - /* shk died, teleported, changed levels... */ - return; + if (!shkp || !inhishop(shkp)) + return; /* shk died, teleported, changed levels... */ eshkp = ESHK(shkp); - - if(!eshkp->billct && !eshkp->debit) /* bill is settled */ + if (!eshkp->billct && !eshkp->debit) /* bill is settled */ return; if (!*leavestring && shkp->mcanmove && !shkp->msleeping) { @@ -332,10 +422,54 @@ register boolean newlev; plname); return; } + + rob_shop(shkp); + +#ifdef KOPS + call_kops(shkp, (!newlev && levl[u.ux0][u.uy0].edge)); +#else + (void) angry_guards(FALSE); +#endif +} + +/* robbery from outside the shop via telekinesis or grappling hook */ +void +remote_burglary(x, y) +xchar x, y; +{ + struct monst *shkp; + struct eshk *eshkp; + + shkp = shop_keeper(*in_rooms(x, y, SHOPBASE)); + if (!shkp || !inhishop(shkp)) + return; /* shk died, teleported, changed levels... */ + + eshkp = ESHK(shkp); + if (!eshkp->billct && !eshkp->debit) /* bill is settled */ + return; + + rob_shop(shkp); + +#ifdef KOPS + /* [might want to set 2nd arg based on distance from shop doorway] */ + call_kops(shkp, FALSE); +#else + (void) angry_guards(FALSE); +#endif +} + +static void +rob_shop(shkp) +struct monst *shkp; +{ + struct eshk *eshkp; + long total; + + eshkp = ESHK(shkp); total = (addupbill(shkp) + eshkp->debit); if (eshkp->credit >= total) { - Your("credit of %ld zorkmid%s is used to cover your shopping bill.", - eshkp->credit, plur(eshkp->credit)); + Your("credit of %ld %s is used to cover your shopping bill.", + eshkp->credit, currency(eshkp->credit)); total = 0L; /* credit gets cleared by setpaid() */ } else { You("escaped the shop without paying!"); @@ -346,17 +480,12 @@ register boolean newlev; /* by this point, we know an actual robbery has taken place */ eshkp->robbed += total; - You("stole %ld zorkmid%s worth of merchandise.", - total, plur(total)); + You("stole %ld %s worth of merchandise.", + total, currency(total)); if (!Role_if(PM_ROGUE)) /* stealing is unlawful */ adjalign(-sgn(u.ualign.type)); hot_pursuit(shkp); -#ifdef KOPS - call_kops(shkp, (!newlev && levl[u.ux0][u.uy0].edge)); -#else - (void) angry_guards(FALSE); -#endif } void @@ -452,6 +581,8 @@ register char *enterstring; tool = "mattock"; while ((mattock = mattock->nobj) != 0) if (mattock->otyp == DWARVISH_MATTOCK) ++cnt; + /* [ALI] Shopkeeper identifies mattock(s) */ + if (!Blind) makeknown(DWARVISH_MATTOCK); } verbalize(NOTANGRY(shkp) ? "Will you please leave your %s%s outside?" : @@ -488,14 +619,14 @@ struct obj *obj1, *obj2; /* look up the first object by finding shk whose bill it's on */ for (shkp1 = next_shkp(fmon, TRUE); shkp1; - shkp1 = next_shkp(shkp1, TRUE)) + shkp1 = next_shkp(shkp1->nmon, TRUE)) if ((bp1 = onbill(obj1, shkp1, TRUE)) != 0) break; /* second object is probably owned by same shk; if not, look harder */ if (shkp1 && (bp2 = onbill(obj2, shkp1, TRUE)) != 0) { shkp2 = shkp1; } else { for (shkp2 = next_shkp(fmon, TRUE); shkp2; - shkp2 = next_shkp(shkp2, TRUE)) + shkp2 = next_shkp(shkp2->nmon, TRUE)) if ((bp2 = onbill(obj2, shkp2, TRUE)) != 0) break; } @@ -546,14 +677,14 @@ shopper_financial_report() if ((shkp != this_shkp) ^ pass) continue; eshkp = ESHK(shkp); if ((amt = eshkp->credit) != 0) - You("have %ld zorkmid%s credit at %s %s.", - amt, plur(amt), s_suffix(shkname(shkp)), + You("have %ld %s credit at %s %s.", + amt, currency(amt), s_suffix(shkname(shkp)), shtypes[eshkp->shoptype - SHOPBASE].name); else if (shkp == this_shkp) You("have no credit in here."); if ((amt = shop_debt(eshkp)) != 0) - You("owe %s %ld zorkmid%s.", - shkname(shkp), amt, plur(amt)); + You("owe %s %ld %s.", + shkname(shkp), amt, currency(amt)); else if (shkp == this_shkp) You("don't owe any money here."); } @@ -642,16 +773,16 @@ register struct obj *obj, *merge; register struct bill_x *bpm; register struct monst *shkp; - if (obj->otyp == LEASH && obj->leashmon) o_unleash(obj); if (obj->oclass == FOOD_CLASS) food_disappears(obj); + if (obj->oclass == SPBOOK_CLASS) book_disappears(obj); if (Has_contents(obj)) delete_contents(obj); shkp = 0; if (obj->unpaid) { /* look for a shopkeeper who owns this object */ for (shkp = next_shkp(fmon, TRUE); shkp; - shkp = next_shkp(shkp, TRUE)) + shkp = next_shkp(shkp->nmon, TRUE)) if (onbill(obj, shkp, TRUE)) break; } /* sanity check, more or less */ @@ -723,8 +854,13 @@ register struct monst *shkp; long robbed = ESHK(shkp)->robbed; long balance = ((tmp <= 0L) ? tmp : check_credit(tmp, shkp)); +#ifndef GOLDOBJ u.ugold -= balance; shkp->mgold += balance; +#else + if (balance > 0) money2mon(shkp, balance); + else if (balance < 0) money2u(shkp, -balance); +#endif flags.botl = 1; if(robbed) { robbed -= tmp; @@ -927,7 +1063,10 @@ dopay() register struct monst *shkp; struct monst *nxtm, *resident; long ltmp; - int pass, tmp, shk_pronoun, sk = 0, seensk = 0; +#ifdef GOLDOBJ + long umoney; +#endif + int pass, tmp, sk = 0, seensk = 0; boolean paid = FALSE, stashed_gold = (hidden_gold() > 0L); multi = 0; @@ -1027,32 +1166,50 @@ dopay() return 0; } eshkp = ESHK(shkp); - shk_pronoun = pronoun_gender(shkp); ltmp = eshkp->robbed; + if(shkp != resident && NOTANGRY(shkp)) { +#ifdef GOLDOBJ + umoney = money_cnt(invent); +#endif if(!ltmp) You("do not owe %s anything.", mon_nam(shkp)); +#ifndef GOLDOBJ else if(!u.ugold) { +#else + else if(!umoney) { +#endif You("%shave no money.", stashed_gold ? "seem to " : ""); if(stashed_gold) pline("But you have some gold stashed away."); } else { +#ifndef GOLDOBJ long ugold = u.ugold; - if(ugold > ltmp) { +#else + if(umoney > ltmp) { +#endif You("give %s the %ld gold piece%s %s asked for.", - mon_nam(shkp), ltmp, plur(ltmp), he[shk_pronoun]); + mon_nam(shkp), ltmp, plur(ltmp), mhe(shkp)); pay(ltmp, shkp); } else { You("give %s all your%s gold.", mon_nam(shkp), stashed_gold ? " openly kept" : ""); +#ifndef GOLDOBJ pay(u.ugold, shkp); +#else + pay(umoney, shkp); +#endif if (stashed_gold) pline("But you have hidden gold!"); } +#ifndef GOLDOBJ if((ugold < ltmp/2L) || (ugold < ltmp && stashed_gold)) +#else + if((umoney < ltmp/2L) || (umoney < ltmp && stashed_gold)) +#endif pline("Unfortunately, %s doesn't look satisfied.", - he[shk_pronoun]); + mhe(shkp)); else make_happy_shk(shkp, FALSE); } @@ -1061,40 +1218,67 @@ dopay() /* ltmp is still eshkp->robbed here */ if (!eshkp->billct && !eshkp->debit) { +#ifdef GOLDOBJ + umoney = money_cnt(invent); +#endif if(!ltmp && NOTANGRY(shkp)) { You("do not owe %s anything.", mon_nam(shkp)); +#ifndef GOLDOBJ if (!u.ugold) +#else + if (!umoney) +#endif pline(no_money, stashed_gold ? " seem to" : ""); } else if(ltmp) { pline("%s is after blood, not money!", Monnam(shkp)); +#ifndef GOLDOBJ if(u.ugold < ltmp/2L || (u.ugold < ltmp && stashed_gold)) { if (!u.ugold) +#else + if(umoney < ltmp/2L || + (umoney < ltmp && stashed_gold)) { + if (!umoney) +#endif pline(no_money, stashed_gold ? " seem to" : ""); - else pline(not_enough_money, him[shk_pronoun]); + else pline(not_enough_money, mhim(shkp)); return(1); } pline("But since %s shop has been robbed recently,", - his[shk_pronoun]); + mhis(shkp)); pline("you %scompensate %s for %s losses.", - (u.ugold < ltmp) ? "partially " : "", - mon_nam(shkp), his[shk_pronoun]); +#ifndef GOLDOBJ + (u.ugold < ltmp) ? +#else + (umoney < ltmp) ? +#endif + "partially " : "", + mon_nam(shkp), mhis(shkp)); +#ifndef GOLDOBJ pay(u.ugold < ltmp ? u.ugold : ltmp, shkp); +#else + pay(umoney < ltmp ? umoney : ltmp, shkp); +#endif make_happy_shk(shkp, FALSE); } else { /* shopkeeper is angry, but has not been robbed -- * door broken, attacked, etc. */ pline("%s is after your hide, not your money!", Monnam(shkp)); +#ifndef GOLDOBJ if(u.ugold < 1000L) { if (!u.ugold) +#else + if(umoney < 1000L) { + if (!umoney) +#endif pline(no_money, stashed_gold ? " seem to" : ""); - else pline(not_enough_money, him[shk_pronoun]); + else pline(not_enough_money, mhim(shkp)); return(1); } You("try to appease %s by giving %s 1000 gold pieces.", x_monnam(shkp, ARTICLE_THE, "angry", 0, FALSE), - him[shk_pronoun]); + mhim(shkp)); pay(1000L,shkp); if (strncmp(eshkp->customer, plname, PL_NSIZ) || rn2(3)) make_happy_shk(shkp, FALSE); @@ -1107,15 +1291,17 @@ dopay() impossible("dopay: not to shopkeeper?"); if(resident) setpaid(resident); return(0); - } + } /* pay debt, if any, first */ if(eshkp->debit) { long dtmp = eshkp->debit; long loan = eshkp->loan; char sbuf[BUFSZ]; - - Sprintf(sbuf, "You owe %s %ld zorkmid%s ", - shkname(shkp), dtmp, plur(dtmp)); +#ifdef GOLDOBJ + umoney = money_cnt(invent); +#endif + Sprintf(sbuf, "You owe %s %ld %s ", + shkname(shkp), dtmp, currency(dtmp)); if(loan) { if(loan == dtmp) Strcat(sbuf, "you picked up in the store."); @@ -1123,7 +1309,11 @@ dopay() "for gold picked up and the use of merchandise."); } else Strcat(sbuf, "for the use of merchandise."); pline(sbuf); +#ifndef GOLDOBJ if (u.ugold + eshkp->credit < dtmp) { +#else + if (umoney + eshkp->credit < dtmp) { +#endif pline("But you don't%s have enough gold%s.", stashed_gold ? " seem to" : "", eshkp->credit ? " or credit" : ""); @@ -1135,8 +1325,12 @@ dopay() eshkp->loan = 0L; Your("debt is covered by your credit."); } else if (!eshkp->credit) { +#ifndef GOLDOBJ u.ugold -= dtmp; - shkp->mgold += dtmp; + shkp->mgold += dtmp; +#else + money2mon(shkp, dtmp); +#endif eshkp->debit = 0L; eshkp->loan = 0L; You("pay that debt."); @@ -1144,8 +1338,12 @@ dopay() } else { dtmp -= eshkp->credit; eshkp->credit = 0L; +#ifndef GOLDOBJ u.ugold -= dtmp; shkp->mgold += dtmp; +#else + money2mon(shkp, dtmp); +#endif eshkp->debit = 0L; eshkp->loan = 0L; pline("That debt is partially offset by your credit."); @@ -1158,14 +1356,22 @@ dopay() /* now check items on bill */ if (eshkp->billct) { register boolean itemize; - +#ifndef GOLDOBJ if (!u.ugold && !eshkp->credit) { +#else + umoney = money_cnt(invent); + if (!umoney && !eshkp->credit) { +#endif You("%shave no money or credit%s.", stashed_gold ? "seem to " : "", paid ? " left" : ""); return(0); } +#ifndef GOLDOBJ if ((u.ugold + eshkp->credit) < cheapest_item(shkp)) { +#else + if ((umoney + eshkp->credit) < cheapest_item(shkp)) { +#endif You("don't have enough money to buy%s the item%s you picked.", eshkp->billct > 1 ? " any of" : "", plur(eshkp->billct)); if(stashed_gold) @@ -1251,6 +1457,9 @@ boolean itemize; { register struct obj *obj = *obj_p; long ltmp, quan, save_quan; +#ifdef GOLDOBJ + long umoney = money_cnt(invent); +#endif int buy; boolean stashed_gold = (hidden_gold() > 0L), consumed = (which == 0); @@ -1259,7 +1468,11 @@ boolean itemize; impossible("Paid object on bill??"); return PAY_BUY; } +#ifndef GOLDOBJ if(itemize && u.ugold + ESHK(shkp)->credit == 0L){ +#else + if(itemize && umoney + ESHK(shkp)->credit == 0L){ +#endif You("%shave no money or credit left.", stashed_gold ? "seem to " : ""); return PAY_BROKE; @@ -1283,8 +1496,8 @@ boolean itemize; if (itemize) { char qbuf[BUFSZ]; - Sprintf(qbuf,"%s for %ld zorkmid%s. Pay?", quan == 1L ? - Doname2(obj) : doname(obj), ltmp, plur(ltmp)); + Sprintf(qbuf,"%s for %ld %s. Pay?", quan == 1L ? + Doname2(obj) : doname(obj), ltmp, currency(ltmp)); if (yn(qbuf) == 'n') { buy = PAY_SKIP; /* don't want to buy */ } else if (quan < bp->bquan && !consumed) { /* partly used goods */ @@ -1295,7 +1508,11 @@ boolean itemize; buy = PAY_SKIP; /* shk won't sell */ } } +#ifndef GOLDOBJ if (buy == PAY_BUY && u.ugold + ESHK(shkp)->credit < ltmp) { +#else + if (buy == PAY_BUY && umoney + ESHK(shkp)->credit < ltmp) { +#endif You("don't%s have gold%s enough to pay for %s.", stashed_gold ? " seem to" : "", (ESHK(shkp)->credit > 0L) ? " or credit" : "", @@ -1378,9 +1595,13 @@ int numsk; boolean croaked; { long loss = 0L; +#ifdef GOLDOBJ + long umoney; +#endif struct eshk *eshkp = ESHK(shkp); boolean take = FALSE, taken = FALSE; int roomno = *u.ushops; + char takes[BUFSZ]; /* the simplifying principle is that first-come */ /* already took everything you had. */ @@ -1416,32 +1637,48 @@ boolean croaked; } if (eshkp->following || ANGRY(shkp) || take) { +#ifndef GOLDOBJ if (!invent && !u.ugold) goto skip; - +#else + if (!invent) goto skip; + umoney = money_cnt(invent); +#endif + takes[0] = '\0'; + if (shkp->msleeping || !shkp->mcanmove) + Strcat(takes, "wakes up and "); + if (distu(shkp->mx, shkp->my) > 2) + Strcat(takes, "comes and "); + Strcat(takes, "takes"); + +#ifndef GOLDOBJ if (loss > u.ugold || !loss || roomno == eshkp->shoproom) { eshkp->robbed -= u.ugold; if (eshkp->robbed < 0L) eshkp->robbed = 0L; shkp->mgold += u.ugold; u.ugold = 0L; +#else + if (loss > umoney || !loss || roomno == eshkp->shoproom) { + eshkp->robbed -= umoney; + if (eshkp->robbed < 0L) eshkp->robbed = 0L; + money2mon(shkp, umoney); +#endif flags.botl = 1; - pline("%s %s%stakes all your possessions.", - shkname(shkp), - (shkp->msleeping || !shkp->mcanmove) ? - "wakes up and " : "", - (distu(shkp->mx, shkp->my) > 2) ? - "comes and " : ""); + pline("%s %s all your possessions.", + shkname(shkp), takes); taken = TRUE; /* where to put player's invent (after disclosure) */ set_repo_loc(eshkp); } else { +#ifndef GOLDOBJ shkp->mgold += loss; u.ugold -= loss; +#else + money2mon(shkp, loss); +#endif flags.botl = 1; - pline("%s %sand takes %ld zorkmid%s %sowed %s.", - Monnam(shkp), - (shkp->msleeping || !shkp->mcanmove) ? - "wakes up " : "comes ", - loss, plur(loss), + pline("%s %s the %ld %s %sowed %s.", + Monnam(shkp), takes, + loss, currency(loss), strncmp(eshkp->customer, plname, PL_NSIZ) ? "" : "you ", shkp->female ? "her" : "him"); @@ -1568,16 +1805,50 @@ register struct monst *shkp; /* if angry, impose a surcharge */ /* shopkeeper may notice if the player isn't very knowledgeable - especially when gem prices are concerned */ if (!obj->dknown || !objects[obj->otyp].oc_name_known) { - if (obj->oclass == GEM_CLASS) { - /* all gems are priced high - real or not */ - if (objects[obj->otyp].oc_material == GLASS) { - int i = obj->otyp - LUCKSTONE + JADE + 1; - /* real gem's cost (worthless gems come - after jade but before luckstone) */ - tmp = (long) objects[i].oc_cost; - } + if (obj->oclass == GEM_CLASS && + objects[obj->otyp].oc_material == GLASS) { + int i; + /* get a value that's 'random' from game to game, but the + same within the same game */ + boolean pseudorand = + (((int)u.ubirthday % obj->otyp) >= obj->otyp/2); + + /* all gems are priced high - real or not */ + switch(obj->otyp - LAST_GEM) { + case 1: /* white */ + i = pseudorand ? DIAMOND : OPAL; + break; + case 2: /* blue */ + i = pseudorand ? SAPPHIRE : AQUAMARINE; + break; + case 3: /* red */ + i = pseudorand ? RUBY : JASPER; + break; + case 4: /* yellowish brown */ + i = pseudorand ? AMBER : TOPAZ; + break; + case 5: /* orange */ + i = pseudorand ? JACINTH : AGATE; + break; + case 6: /* yellow */ + i = pseudorand ? CITRINE : CHRYSOBERYL; + break; + case 7: /* black */ + i = pseudorand ? BLACK_OPAL : JET; + break; + case 8: /* green */ + i = pseudorand ? EMERALD : JADE; + break; + case 9: /* violet */ + i = pseudorand ? AMETHYST : FLUORITE; + break; + default: impossible("bad glass gem %d?", obj->otyp); + i = STRANGE_OBJECT; + break; + } + tmp = (long) objects[i].oc_cost; } else if (!(obj->o_id % 4)) /* arbitrarily impose surcharge */ - tmp += tmp / 3L; + tmp += tmp / 3L; } #ifdef TOURIST if ((Role_if(PM_TOURIST) && u.ulevel < (MAXULEV/2)) @@ -1608,11 +1879,12 @@ register struct monst *shkp; /* if angry, impose a surcharge */ * a different price quoted for selling as vs. buying. */ long -contained_cost(obj, shkp, price, usell) +contained_cost(obj, shkp, price, usell, unpaid_only) register struct obj *obj; register struct monst *shkp; long price; register boolean usell; +register boolean unpaid_only; { register struct obj *otmp; @@ -1627,12 +1899,13 @@ register boolean usell; !(Is_candle(otmp) && otmp->age < 20L * (long)objects[otmp->otyp].oc_cost)) price += set_cost(otmp, shkp); - } else if (!otmp->no_charge) { + } else if (!otmp->no_charge && + (!unpaid_only || (unpaid_only && otmp->unpaid))) { price += get_cost(otmp, shkp) * otmp->quan; } if (Has_contents(otmp)) - price += contained_cost(otmp, shkp, price, usell); + price += contained_cost(otmp, shkp, price, usell, unpaid_only); } return(price); @@ -1801,7 +2074,7 @@ add_to_billobjs(obj) if (obj->where != OBJ_FREE) panic("add_to_billobjs: obj not free"); if (obj->timed) - panic("add_to_billobjs: obj is timed"); + obj_stop_timers(obj); obj->nobj = billobjs; billobjs = obj; @@ -1914,7 +2187,7 @@ register boolean ininv, dummy, silent; goto speak; } } else { - cltmp += contained_cost(obj, shkp, cltmp, FALSE); + cltmp += contained_cost(obj, shkp, cltmp, FALSE, FALSE); gltmp += contained_gold(obj); } @@ -1962,12 +2235,12 @@ register boolean ininv, dummy, silent; (quan > 1L) ? "per" : "for this", xname(obj)); obj->quan = quan; } else - pline("%s will cost you %ld zorkmid%s%s.", - The(xname(obj)), ltmp, plur(ltmp), + pline("%s will cost you %ld %s%s.", + The(xname(obj)), ltmp, currency(ltmp), (obj->quan > 1L) ? " each" : ""); } else if(!silent) { - if(ltmp) pline_The("list price of %s is %ld zorkmid%s%s.", - the(xname(obj)), ltmp, plur(ltmp), + if(ltmp) pline_The("list price of %s is %ld %s%s.", + the(xname(obj)), ltmp, currency(ltmp), (obj->quan > 1L) ? " each" : ""); else pline("%s does not notice.", Monnam(shkp)); } @@ -2102,14 +2375,11 @@ register boolean ininv; if (!Has_contents(otmp)) { if(ininv) { if(otmp->unpaid) - price += get_cost(otmp, shkp); + price += otmp->quan * get_cost(otmp, shkp); } else { if(!otmp->no_charge) { - if(!(otmp->oclass == BALL_CLASS || - (otmp->oclass == FOOD_CLASS && otmp->oeaten) || - (Is_candle(otmp) && otmp->age < - 20L * (long)objects[otmp->otyp].oc_cost)) - ) price += get_cost(otmp, shkp); + if(otmp->oclass != FOOD_CLASS || !otmp->oeaten) + price += otmp->quan * get_cost(otmp, shkp); } otmp->no_charge = 0; } @@ -2150,15 +2420,28 @@ register boolean peaceful, silent; value += gvalue; if(peaceful) { + boolean credit_use = !!ESHK(shkp)->credit; value = check_credit(value, shkp); ESHK(shkp)->debit += value; if(!silent) { + char *still = ""; + if (credit_use) { + if (ESHK(shkp)->credit) { + You("have %ld %s credit remaining.", + ESHK(shkp)->credit, currency(ESHK(shkp)->credit)); + return value; + } else if (!value) { + You("have no credit remaining."); + return 0; + } + still = "still "; + } if(obj->oclass == GOLD_CLASS) - You("owe %s %ld zorkmids!", mon_nam(shkp), value); - else You("owe %s %ld zorkmids for %s!", + You("%sowe %s %ld %s!", still, mon_nam(shkp), value, currency(value)); + else You("%sowe %s %ld %s for %s!", still, mon_nam(shkp), - value, + value, currency(value), obj->quan > 1L ? "them" : "it"); } } else { @@ -2180,20 +2463,24 @@ register boolean peaceful, silent; /* auto-response flag for/from "sell foo?" 'a' => 'y', 'q' => 'n' */ static char sell_response = 'a'; -static boolean sell_voluntarily = FALSE; +static int sell_how = SELL_NORMAL; +/* can't just use sell_response='y' for auto_credit because the 'a' response + shouldn't carry over from ordinary selling to credit selling */ +static boolean auto_credit = FALSE; void -sellobj_state(deliberate) /* called from dodrop(do.c) and doddrop() */ -boolean deliberate; +sellobj_state(deliberate) +int deliberate; { /* If we're deliberately dropping something, there's no automatic - response to the shopkeeper's "want to sell" query; however, if we - accidentally drop anything, the shk will buy it/them without asking. - This retains the old pre-query risk that slippery fingers while in - shops entailed: you drop it, you've lost it. + response to the shopkeeper's "want to sell" query; however, if we + accidentally drop anything, the shk will buy it/them without asking. + This retains the old pre-query risk that slippery fingers while in + shops entailed: you drop it, you've lost it. */ - sell_response = deliberate ? '\0' : 'a'; - sell_voluntarily = deliberate; + sell_response = (deliberate != SELL_NORMAL) ? '\0' : 'a'; + sell_how = deliberate; + auto_credit = FALSE; } void @@ -2206,6 +2493,7 @@ xchar x, y; long ltmp = 0L, cltmp = 0L, gltmp = 0L, offer; boolean saleitem, cgold = FALSE, container = Has_contents(obj); boolean isgold = (obj->oclass == GOLD_CLASS); + boolean only_partially_your_contents = FALSE; if(!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) || !inhishop(shkp)) return; @@ -2218,7 +2506,7 @@ xchar x, y; } if(container) { /* find the price of content before subfrombill */ - cltmp += contained_cost(obj, shkp, cltmp, TRUE); + cltmp += contained_cost(obj, shkp, cltmp, TRUE, FALSE); /* find the value of contained gold */ gltmp += contained_gold(obj); cgold = (gltmp > 0L); @@ -2231,7 +2519,8 @@ xchar x, y; offer = ltmp + cltmp; /* get one case out of the way: nothing to sell, and no gold */ - if(!isgold && (offer + gltmp) == 0L) { + if(!isgold && + ((offer + gltmp) == 0L || sell_how == SELL_DONTSELL)) { register boolean unpaid = (obj->unpaid || (container && count_unpaid(obj->cobj))); @@ -2243,7 +2532,7 @@ xchar x, y; subfrombill(obj, shkp); } else obj->no_charge = 1; - if(!unpaid) + if(!unpaid && (sell_how != SELL_DONTSELL)) pline("%s seems uninterested.", Monnam(shkp)); return; } @@ -2305,8 +2594,8 @@ xchar x, y; eshkp->loan = 0L; Your("debt is paid off."); } - pline("%ld zorkmid%s added to your credit.", - delta, delta > 1L ? "s are" : " is"); + pline("%ld %s %s added to your credit.", + delta, currency(delta), delta > 1L ? "are" : "is"); } if(offer) goto move_on; else { @@ -2334,25 +2623,35 @@ xchar x, y; obj->no_charge = 1; return; } - + +#ifndef GOLDOBJ if(!shkp->mgold) { +#else + if(!money_cnt(shkp->minvent)) { +#endif char c, qbuf[BUFSZ]; long tmpcr = ((offer * 9L) / 10L) + (offer <= 1L); - if (!sell_voluntarily) { + if (sell_how == SELL_NORMAL || auto_credit) { c = sell_response = 'y'; } else if (sell_response != 'n') { pline("%s cannot pay you at present.", Monnam(shkp)); Sprintf(qbuf, - "Will you accept %ld zorkmid%s in credit for %s?", - tmpcr, plur(tmpcr), doname(obj)); + "Will you accept %ld %s in credit for %s?", + tmpcr, currency(tmpcr), doname(obj)); /* won't accept 'a' response here */ - c = ynq(qbuf); + /* KLY - 3/2000 yes, we will, it's a damn nuisance + to have to constantly hit 'y' to sell for credit */ + c = ynaq(qbuf); + if (c == 'a') { + c = 'y'; + auto_credit = TRUE; + } } else /* previously specified "quit" */ c = 'n'; if (c == 'y') { - shk_names_obj(shkp, obj, sell_voluntarily ? + shk_names_obj(shkp, obj, (sell_how != SELL_NORMAL) ? "traded %s for %ld zorkmid%s in %scredit." : "relinquish %s and acquire %ld zorkmid%s in %scredit.", tmpcr, @@ -2368,18 +2667,28 @@ xchar x, y; } } else { char qbuf[BUFSZ]; +#ifndef GOLDOBJ boolean short_funds = (offer > shkp->mgold); - if (short_funds) offer = shkp->mgold; - +#else + long shkmoney = money_cnt(shkp->minvent); + boolean short_funds = (offer > shkmoney); + if (short_funds) offer = shkmoney; +#endif if (!sell_response) { + only_partially_your_contents = + (contained_cost(obj, shkp, 0L, FALSE, FALSE) != + contained_cost(obj, shkp, 0L, FALSE, TRUE)); Sprintf(qbuf, "%s offers%s %ld gold piece%s for%s %s %s. Sell %s?", Monnam(shkp), short_funds ? " only" : "", offer, plur(offer), - (!ltmp && cltmp) ? " the contents of" : "", - obj->unpaid ? "the" : "your", xname(obj), - (obj->quan == 1L) ? "it" : "them"); + (!ltmp && cltmp && only_partially_your_contents) ? + " your items in" : (!ltmp && cltmp) ? " the contents of" : "", + obj->unpaid ? "the" : "your", cxname(obj), + (obj->quan == 1L && + !(!ltmp && cltmp && only_partially_your_contents)) ? + "it" : "them"); } else qbuf[0] = '\0'; /* just to pacify lint */ switch (sell_response ? sell_response : ynaq(qbuf)) { @@ -2395,7 +2704,9 @@ xchar x, y; if (!obj->unpaid && !saleitem) obj->no_charge = 1; subfrombill(obj, shkp); pay(-offer, shkp); - shk_names_obj(shkp, obj, sell_voluntarily ? + shk_names_obj(shkp, obj, (sell_how != SELL_NORMAL) ? + (!ltmp && cltmp && only_partially_your_contents) ? + "sold some items inside %s for %ld gold pieces%s.%s" : "sold %s for %ld gold piece%s.%s" : "relinquish %s and receive %ld gold piece%s in compensation.%s", offer, ""); @@ -2461,11 +2772,9 @@ int mode; /* 0: deliver count 1: paged */ uquan = (bp->useup ? bp->bquan : bp->bquan - oquan); thisused = bp->price * uquan; totused += thisused; - obj->quan = uquan; /* cheat doname */ obj->unpaid = 0; /* ditto */ /* Why 'x'? To match `I x', more or less. */ - buf_p = xprname(obj, (char *)0, 'x', FALSE, thisused); - obj->quan = oquan; /* restore value */ + buf_p = xprname(obj, (char *)0, 'x', FALSE, thisused, uquan); #ifdef __SASC /* SAS/C 6.2 can't cope for some reason */ sasc_bug(obj,save_unpaid); @@ -2481,10 +2790,10 @@ int mode; /* 0: deliver count 1: paged */ totused += eshkp->debit; buf_p = xprname((struct obj *)0, "usage charges and/or other fees", - GOLD_SYM, FALSE, eshkp->debit); + GOLD_SYM, FALSE, eshkp->debit, 0L); putstr(datawin, 0, buf_p); } - buf_p = xprname((struct obj *)0, "Total:", '*', FALSE, totused); + buf_p = xprname((struct obj *)0, "Total:", '*', FALSE, totused, 0L); putstr(datawin, 0, ""); putstr(datawin, 0, buf_p); display_nhwindow(datawin, FALSE); @@ -2502,6 +2811,10 @@ boolean shk_buying; { register long tmp = (long) objects[obj->otyp].oc_cost; + if (obj->oartifact) { + tmp = arti_cost(obj); + if (shk_buying) tmp /= 4; + } switch(obj->oclass) { case FOOD_CLASS: /* simpler hunger check, (2-4)*cost */ @@ -2525,12 +2838,11 @@ boolean shk_buying; tmp /= 2L; break; } - if (obj->oartifact) tmp *= 25L; return tmp; } /* shk catches thrown pick-axe */ -int +struct monst * shkcatch(obj, x, y) register struct obj *obj; register xchar x, y; @@ -2548,8 +2860,10 @@ register xchar x, y; if (mnearto(shkp, x, y, TRUE)) verbalize("Out of my way, scum!"); if (cansee(x, y)) { - pline("%s nimbly catches %s.", - Monnam(shkp), the(xname(obj))); + pline("%s nimbly%s catches %s.", + Monnam(shkp), + (x == shkp->mx && y == shkp->my) ? "" : " reaches over and", + the(xname(obj))); if (!canspotmon(shkp)) map_invisible(x, y); delay_output(); @@ -2557,9 +2871,9 @@ register xchar x, y; } subfrombill(obj, shkp); (void) mpickobj(shkp, obj); - return(1); + return shkp; } - return(0); + return (struct monst *)0; } void @@ -2745,17 +3059,21 @@ boolean catchup; /* restoring a level */ (void) mpickobj(shkp, otmp); } deltrap(ttmp); + if(IS_DOOR(tmp_dam->typ)) { + levl[x][y].doormask = D_CLOSED; /* arbitrary */ + block_point(x, y); + } else if (IS_WALL(tmp_dam->typ)) { + levl[x][y].typ = tmp_dam->typ; + block_point(x, y); + } newsym(x, y); return(3); } if (IS_ROOM(tmp_dam->typ)) { - /* No messages if player already filled trap door */ - if (catchup || !ttmp) - return(1); - newsym(x, y); - return(2); + /* No messages, because player already filled trap door */ + return(1); } - if (!ttmp && (tmp_dam->typ == levl[x][y].typ) && + if ((tmp_dam->typ == levl[x][y].typ) && (!IS_DOOR(tmp_dam->typ) || (levl[x][y].doormask > D_BROKEN))) /* No messages if player already replaced shop door */ return(1); @@ -2887,7 +3205,14 @@ register struct monst *shkp; gy = eshkp->shk.y; satdoor = (gx == omx && gy == omy); if(eshkp->following || ((z = holetime()) >= 0 && z*z <= udist)){ - if(udist > 4) + /* [This distance check used to apply regardless of + whether the shk was following, but that resulted in + m_move() sometimes taking the shk out of the shop if + the player had fenced him in with boulders or traps. + Such voluntary abandonment left unpaid objects in + invent, triggering billing impossibilities on the + next level once the character fell through the hole.] */ + if (udist > 4 && eshkp->following) return(-1); /* leave it to m_move */ gx = u.ux; gy = u.uy; @@ -2951,9 +3276,17 @@ shopdig(fall) register int fall; { register struct monst *shkp = shop_keeper(*u.ushops); + int lang = 0; + char *grabs = "grabs"; if(!shkp) return; + /* 0 == can't speak, 1 == makes animal noises, 2 == speaks */ + if (!is_silent(shkp->data) && shkp->data->msound <= MS_ANIMAL) + lang = 1; + else if (shkp->data->msound >= MS_HUMANOID) + lang = 2; + if(!inhishop(shkp)) { if (Role_if(PM_KNIGHT)) { You_feel("like a common thief."); @@ -2963,12 +3296,15 @@ register int fall; } if(!fall) { - if(u.utraptype == TT_PIT) - verbalize("Be careful, %s, or you might fall through the floor.", - flags.female ? "madam" : "sir"); - else - verbalize("%s, do not damage the floor here!", + if (lang == 2) { + if(u.utraptype == TT_PIT) + verbalize( + "Be careful, %s, or you might fall through the floor.", + flags.female ? "madam" : "sir"); + else + verbalize("%s, do not damage the floor here!", flags.female ? "Madam" : "Sir"); + } if (Role_if(PM_KNIGHT)) { You_feel("like a common thief."); adjalign(-sgn(u.ualign.type)); @@ -2977,23 +3313,40 @@ register int fall; !shkp->msleeping && shkp->mcanmove && (ESHK(shkp)->billct || ESHK(shkp)->debit)) { register struct obj *obj, *obj2; - + if (nolimbs(shkp->data)) { + grabs = "knocks off"; +#if 0 + /* This is what should happen, but for balance + * reasons, it isn't currently. + */ + if (lang == 2) + pline("%s curses %s inability to grab your backpack!", + shkname(shkp), mhim(shkp)); + rile_shk(shkp); + return; +#endif + } if (distu(shkp->mx, shkp->my) > 2) { mnexto(shkp); /* for some reason the shopkeeper can't come next to you */ if (distu(shkp->mx, shkp->my) > 2) { - pline("%s curses you in anger and frustration!", - shkname(shkp)); + if (lang == 2) + pline("%s curses you in anger and frustration!", + shkname(shkp)); rile_shk(shkp); return; - } else pline("%s leaps, and grabs your backpack!", - shkname(shkp)); - } else pline("%s grabs your backpack!", shkname(shkp)); + } else + pline("%s %s, and %s your backpack!", + shkname(shkp), + makeplural(locomotion(shkp->data,"leap")), grabs); + } else + pline("%s %s your backpack!", shkname(shkp), grabs); for(obj = invent; obj; obj = obj2) { obj2 = obj->nobj; - if(obj->owornmask) continue; - if(obj->otyp == LEASH && obj->leashmon) continue; + if ((obj->owornmask & ~(W_SWAPWEP|W_QUIVER)) != 0 || + (obj == uswapwep && u.twoweap) || + (obj->otyp == LEASH && obj->leashmon)) continue; freeinv(obj); subfrombill(obj, shkp); (void) add_to_minv(shkp, obj); /* may free obj */ @@ -3141,7 +3494,11 @@ const char *dmgstr; } if((um_dist(x, y, 1) && !uinshp) || +#ifndef GOLDOBJ (u.ugold + ESHK(shkp)->credit) < cost_of_damage +#else + (money_cnt(invent) + ESHK(shkp)->credit) < cost_of_damage +#endif || !rn2(50)) { if(um_dist(x, y, 1) && !uinshp) { pline("%s shouts:", shkname(shkp)); @@ -3156,13 +3513,17 @@ const char *dmgstr; return; } - if(Invis) Your("invisibility does not fool %s!", shkname(shkp)); - Sprintf(qbuf,"\"Cad! You did %ld zorkmids worth of damage!\" Pay? ", - cost_of_damage); + if (Invis) Your("invisibility does not fool %s!", shkname(shkp)); + Sprintf(qbuf,"\"Cad! You did %ld %s worth of damage!\" Pay? ", + cost_of_damage, currency(cost_of_damage)); if(yn(qbuf) != 'n') { cost_of_damage = check_credit(cost_of_damage, shkp); +#ifndef GOLDOBJ u.ugold -= cost_of_damage; shkp->mgold += cost_of_damage; +#else + money2mon(shkp, cost_of_damage); +#endif flags.botl = 1; pline("Mollified, %s accepts your restitution.", shkname(shkp)); @@ -3236,11 +3597,11 @@ register struct obj *first_obj; cost = (otmp->no_charge || otmp == uball || otmp == uchain) ? 0L : get_cost(otmp, (struct monst *)0); if (Has_contents(otmp)) - cost += contained_cost(otmp, shkp, 0L, FALSE); + cost += contained_cost(otmp, shkp, 0L, FALSE, FALSE); if (!cost) { Strcpy(price, "no charge"); } else { - Sprintf(price, "%ld zorkmid%s%s", cost, plur(cost), + Sprintf(price, "%ld %s%s", cost, currency(cost), otmp->quan > 1L ? " each" : ""); } Sprintf(buf, "%s, %s", doname(otmp), price); @@ -3255,9 +3616,9 @@ register struct obj *first_obj; /* print cost in slightly different format, so can't reuse buf */ cost = get_cost(first_obj, (struct monst *)0); if (Has_contents(first_obj)) - cost += contained_cost(first_obj, shkp, 0L, FALSE); - pline("%s, price %ld zorkmid%s%s%s", doname(first_obj), - cost, plur(cost), first_obj->quan > 1L ? " each" : "", + cost += contained_cost(first_obj, shkp, 0L, FALSE, FALSE); + pline("%s, price %ld %s%s%s", doname(first_obj), + cost, currency(cost), first_obj->quan > 1L ? " each" : "", shk_embellish(first_obj, cost)); } } @@ -3313,13 +3674,29 @@ const char *Izchak_speaks[]={ void shk_chat(shkp) -register struct monst *shkp; +struct monst *shkp; { - register struct eshk *eshk = ESHK(shkp); + struct eshk *eshk; +#ifdef GOLDOBJ + long shkmoney; +#endif + if (!shkp->isshk) { + /* The monster type is shopkeeper, but this monster is + not actually a shk, which could happen if someone + wishes for a shopkeeper statue and then animates it. + (Note: shkname() would be "" in a case like this.) */ + pline("%s asks whether you've seen any untended shops recently.", + Monnam(shkp)); + /* [Perhaps we ought to check whether this conversation + is taking place inside an untended shop, but a shopless + shk can probably be expected to be rather disoriented.] */ + return; + } + eshk = ESHK(shkp); if (ANGRY(shkp)) pline("%s mentions how much %s dislikes %s customers.", - shkname(shkp), he[shkp->female], + shkname(shkp), mhe(shkp), eshk->robbed ? "non-paying" : "rude"); else if (eshk->following) { if (strncmp(eshk->customer, plname, PL_NSIZ)) { @@ -3327,24 +3704,33 @@ register struct monst *shkp; Hello(shkp), plname, eshk->customer); eshk->following = 0; } else { - verbalize("%s %s! Didn't you forget to pay?", Hello(shkp), plname); + verbalize("%s %s! Didn't you forget to pay?", + Hello(shkp), plname); } } else if (eshk->billct) { register long total = addupbill(shkp) + eshk->debit; - pline("%s says that your bill comes to %ld zorkmid%s.", - shkname(shkp), total, plur(total)); + pline("%s says that your bill comes to %ld %s.", + shkname(shkp), total, currency(total)); } else if (eshk->debit) - pline("%s reminds you that you owe %s %ld zorkmid%s.", - shkname(shkp), him[shkp->female], - eshk->debit, plur(eshk->debit)); + pline("%s reminds you that you owe %s %ld %s.", + shkname(shkp), mhim(shkp), + eshk->debit, currency(eshk->debit)); else if (eshk->credit) - pline("%s encourages you to use your %ld zorkmid%s of credit.", - shkname(shkp), eshk->credit, plur(eshk->credit)); + pline("%s encourages you to use your %ld %s of credit.", + shkname(shkp), eshk->credit, currency(eshk->credit)); else if (eshk->robbed) pline("%s complains about a recent robbery.", shkname(shkp)); +#ifndef GOLDOBJ else if (shkp->mgold < 50) +#else + else if ((shkmoney = money_cnt(shkp->minvent)) < 50) +#endif pline("%s complains that business is bad.", shkname(shkp)); +#ifndef GOLDOBJ else if (shkp->mgold > 4000) +#else + else if (shkmoney > 4000) +#endif pline("%s says that business is good.", shkname(shkp)); else if (strcmp(shkname(shkp), "Izchak") == 0) pline(Izchak_speaks[rn2(SIZE(Izchak_speaks))],shkname(shkp)); @@ -3413,13 +3799,17 @@ boolean altusage; /* some items have an "alternate" use with different cost */ (otmp->otyp >= MAGIC_FLUTE && otmp->otyp <= DRUM_OF_EARTHQUAKE) || /* 5 - 9 */ otmp->oclass == WAND_CLASS) { /* 3 - 11 */ - if (otmp->spe > 1) tmp /= 4L; + if (otmp->spe > 1) tmp /= 4L; } else if (otmp->oclass == SPBOOK_CLASS) { - tmp -= tmp / 5L; - } else if (otmp->otyp == CAN_OF_GREASE) { - tmp /= 10L; + tmp -= tmp / 5L; + } else if (otmp->otyp == CAN_OF_GREASE +#ifdef TOURIST + || otmp->otyp == EXPENSIVE_CAMERA +#endif + ) { + tmp /= 10L; } else if (otmp->otyp == POT_OIL) { - tmp /= 5L; + tmp /= 5L; } return(tmp); } @@ -3450,19 +3840,19 @@ boolean altusage; arg1 = arg2 = ""; if (otmp->oclass == SPBOOK_CLASS) { - fmt = "%sYou owe%s %ld zorkmids."; + fmt = "%sYou owe%s %ld %s."; arg1 = rn2(2) ? "This is no free library, cad! " : ""; arg2 = ESHK(shkp)->debit > 0L ? " an additional" : ""; } else if (otmp->otyp == POT_OIL) { - fmt = "%s%sThat will cost you %ld zorkmids (Yendorian Fuel Tax)."; + fmt = "%s%sThat will cost you %ld %s (Yendorian Fuel Tax)."; } else { - fmt = "%s%sUsage fee, %ld zorkmids."; + fmt = "%s%sUsage fee, %ld %s."; if (!rn2(3)) arg1 = "Hey! "; if (!rn2(3)) arg2 = "Ahem. "; } if (shkp->mcanmove || !shkp->msleeping) - verbalize(fmt, arg1, arg2, tmp); + verbalize(fmt, arg1, arg2, tmp, currency(tmp)); ESHK(shkp)->debit += tmp; exercise(A_WIS, TRUE); /* you just got info */ } @@ -3491,8 +3881,8 @@ register long amount; eshkp = ESHK(shkp); if(eshkp->credit >= amount) { if(eshkp->credit > amount) - Your("credit is reduced by %ld zorkmid%s.", - amount, plur(amount)); + Your("credit is reduced by %ld %s.", + amount, currency(amount)); else Your("credit is erased."); eshkp->credit -= amount; } else { @@ -3500,10 +3890,10 @@ register long amount; if(eshkp->credit) Your("credit is erased."); if(eshkp->debit) - Your("debt increases by %ld zorkmid%s.", - delta, plur(delta)); - else You("owe %s %ld zorkmid%s.", - shkname(shkp), delta, plur(delta)); + Your("debt increases by %ld %s.", + delta, currency(delta)); + else You("owe %s %ld %s.", + shkname(shkp), delta, currency(delta)); eshkp->debit += delta; eshkp->loan += delta; eshkp->credit = 0L; diff --git a/src/shknam.c b/src/shknam.c index 17ca9a0..76fd007 100644 --- a/src/shknam.c +++ b/src/shknam.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)shknam.c 3.3 97/05/25 */ +/* SCCS Id: @(#)shknam.c 3.4 2001/09/06 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -115,7 +115,7 @@ static const char *shktools[] = { "Erreip", "Nehpets", "Mron", "Snivek", "Lapu", "Kahztiy", #endif #ifdef WIN32 - "Lechaim", + "Lechaim", "Lexa", "Niod", #endif #ifdef MAC "Nhoj-lee", "Evad\'kh", "Ettaw-noj", "Tsew-mot", "Ydna-s", @@ -246,21 +246,25 @@ mkshobj_at(shp, sx, sy) const struct shclass *shp; int sx, sy; { - register struct monst *mtmp; + struct monst *mtmp; int atype; struct permonst *ptr; if (rn2(100) < depth(&u.uz) && - !MON_AT(sx, sy) && (ptr = mkclass(S_MIMIC,0)) && - (mtmp=makemon(ptr,sx,sy,NO_MM_FLAGS))) { - /* note: makemon will set the mimic symbol to a shop item */ - if (rn2(10) >= depth(&u.uz)) { - mtmp->m_ap_type = M_AP_OBJECT; - mtmp->mappearance = STRANGE_OBJECT; - } - } else if ((atype = get_shop_item(shp - shtypes)) < 0) - (void) mksobj_at(-atype, sx, sy, TRUE); - else (void) mkobj_at(atype, sx, sy, TRUE); + !MON_AT(sx, sy) && (ptr = mkclass(S_MIMIC,0)) && + (mtmp = makemon(ptr,sx,sy,NO_MM_FLAGS)) != 0) { + /* note: makemon will set the mimic symbol to a shop item */ + if (rn2(10) >= depth(&u.uz)) { + mtmp->m_ap_type = M_AP_OBJECT; + mtmp->mappearance = STRANGE_OBJECT; + } + } else { + atype = get_shop_item(shp - shtypes); + if (atype < 0) + (void) mksobj_at(-atype, sx, sy, TRUE, TRUE); + else + (void) mkobj_at(atype, sx, sy, TRUE); + } } /* extract a shopkeeper name for the given shop type */ @@ -402,7 +406,13 @@ struct mkroom *sroom; ESHK(shk)->visitct = 0; ESHK(shk)->following = 0; ESHK(shk)->billct = 0; +#ifndef GOLDOBJ shk->mgold = 1000L + 30L*(long)rnd(100); /* initial capital */ +#else + mkmonmoney(shk, 1000L + 30L*(long)rnd(100)); /* initial capital */ +#endif + if (shp->shknms == shkrings) + (void) mongets(shk, TOUCHSTONE); nameshk(shk, shp->shknms); return(sh); diff --git a/src/sit.c b/src/sit.c index d835867..e11bd23 100644 --- a/src/sit.c +++ b/src/sit.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)sit.c 3.3 96/07/15 */ +/* SCCS Id: @(#)sit.c 3.4 2000/11/09 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -8,6 +8,7 @@ void take_gold() { +#ifndef GOLDOBJ if (u.ugold <= 0) { You_feel("a strange sensation."); } else { @@ -15,6 +16,22 @@ take_gold() u.ugold = 0; flags.botl = 1; } +#else + struct obj *otmp; + int lost_money = 0; + for (otmp = invent; otmp; otmp = otmp->nobj) { + if (otmp->oclass == GOLD_CLASS) { + lost_money = 1; + delobj(otmp); + } + } + if (!lost_money) { + You_feel("a strange sensation."); + } else { + You("notice you have no money!"); + flags.botl = 1; + } +#endif } int @@ -38,6 +55,8 @@ dosit() else You("are sitting on air."); return 0; + } else if (is_pool(u.ux, u.uy) && !Underwater) { /* water walking */ + goto in_water; } if(OBJ_AT(u.ux, u.uy)) { @@ -45,7 +64,8 @@ dosit() obj = level.objects[u.ux][u.uy]; You("sit on %s.", the(xname(obj))); - if(!Is_box(obj)) pline("It's not very comfortable..."); + if (!(Is_box(obj) || objects[obj->otyp].oc_material == CLOTH)) + pline("It's not very comfortable..."); } else if ((trap = t_at(u.ux, u.uy)) != 0) { @@ -76,7 +96,7 @@ dosit() } } else { You("sit down."); - dotrap(trap); + dotrap(trap, 0); } } else if(Underwater || Is_waterlevel(&u.uz)) { if (Is_waterlevel(&u.uz)) @@ -84,7 +104,7 @@ dosit() else You("sit down on the muddy bottom."); } else if(is_pool(u.ux, u.uy)) { - + in_water: You("sit in the water."); if (!rn2(10) && uarm) (void) rust_dmg(uarm, "armor", 1, TRUE, &youmonst); @@ -191,7 +211,7 @@ dosit() pline("A voice echoes:"); verbalize("By thy Imperious order, %s...", flags.female ? "Dame" : "Sire"); - do_genocide(1); + do_genocide(5); /* REALLY|ONTHRONE, see do_genocide() */ break; case 9: pline("A voice echoes:"); @@ -241,13 +261,18 @@ dosit() default: impossible("throne effect"); break; } - } else You_feel("somehow out of place..."); + } else { + if (is_prince(youmonst.data)) + You_feel("very comfortable here."); + else + You_feel("somehow out of place..."); + } if (!rn2(3) && IS_THRONE(levl[u.ux][u.uy].typ)) { /* may have teleported */ pline_The("throne vanishes in a puff of logic."); levl[u.ux][u.uy].typ = ROOM; - if(Invisible) newsym(u.ux,u.uy); + newsym(u.ux,u.uy); } } else if (lays_eggs(youmonst.data)) { @@ -301,7 +326,7 @@ rndcurse() /* curse a few inventory items at random! */ for (otmp = invent; otmp; otmp = otmp->nobj) nobj++; - if (nobj) + if (nobj) { for (cnt = rnd(6/((!!Antimagic) + (!!Half_spell_damage) + 1)); cnt > 0; cnt--) { onum = rn2(nobj); @@ -310,7 +335,7 @@ rndcurse() /* curse a few inventory items at random! */ if(otmp->oartifact && spec_ability(otmp, SPFX_INTEL) && rn2(10) < 8) { - pline("%s resists!", The(xname(otmp))); + pline("%s!", Tobjnam(otmp, "resist")); continue; } @@ -319,6 +344,8 @@ rndcurse() /* curse a few inventory items at random! */ else curse(otmp); } + update_inventory(); + } } void diff --git a/src/sounds.c b/src/sounds.c index 903716a..4c8c952 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1,9 +1,12 @@ -/* SCCS Id: @(#)sounds.c 3.3 2000/07/24 */ +/* SCCS Id: @(#)sounds.c 3.4 2001/02/14 */ /* Copyright (c) 1989 Janet Walz, Mike Threepoint */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" #include "edog.h" +#ifdef USER_SOUNDS +#include +#endif #ifdef OVLB @@ -77,7 +80,7 @@ dosounds() int which = rn2(3)+hallu; if (which != 2) You_hear(throne_msg[which]); - else pline(throne_msg[2], his[flags.female]); + else pline(throne_msg[2], uhis()); return; } } @@ -319,7 +322,7 @@ register struct monst *mtmp; else growl_verb = growl_sound(mtmp); if (growl_verb) { - pline("%s %s!", Monnam(mtmp), makeplural(growl_verb)); + pline("%s %s!", Monnam(mtmp), vtense((char *)0, growl_verb)); if(flags.run) nomul(0); wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 18); } @@ -360,7 +363,7 @@ register struct monst *mtmp; break; } if (yelp_verb) { - pline("%s %ss!", Monnam(mtmp), yelp_verb); + pline("%s %s!", Monnam(mtmp), vtense((char *)0, yelp_verb)); if(flags.run) nomul(0); wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 12); } @@ -392,7 +395,7 @@ register struct monst *mtmp; break; } if (whimper_verb) { - pline("%s %ss.", Monnam(mtmp), whimper_verb); + pline("%s %s.", Monnam(mtmp), vtense((char *)0, whimper_verb)); if(flags.run) nomul(0); wake_nearto(mtmp->mx, mtmp->my, mtmp->data->mlevel * 6); } @@ -408,7 +411,7 @@ register struct monst *mtmp; return; /* presumably nearness and soundok checks have already been made */ - if (mtmp->data->msound != MS_SILENT && mtmp->data->msound <= MS_ANIMAL) + if (!is_silent(mtmp->data) && mtmp->data->msound <= MS_ANIMAL) (void) domonnoise(mtmp); else if (mtmp->data->msound >= MS_HUMANOID) { if (!canspotmon(mtmp)) @@ -428,7 +431,7 @@ register struct monst *mtmp; /* presumably nearness and sleep checks have already been made */ if (!flags.soundok) return(0); - if (ptr->msound == MS_SILENT) return(0); + if (is_silent(ptr)) return(0); /* be sure to do this before talking; the monster might teleport away, in * which case we want to check its pre-teleport position @@ -500,7 +503,14 @@ register struct monst *mtmp; }; if (kindred) verbl_msg = "This is my hunting ground that you dare to prowl!"; - else { + else if (youmonst.data == &mons[PM_SILVER_DRAGON] || + youmonst.data == &mons[PM_BABY_SILVER_DRAGON]) { + /* Silver dragons are silver in color, not made of silver */ + Sprintf(verbuf, "%s! Your silver sheen does not frighten me!", + youmonst.data == &mons[PM_SILVER_DRAGON] ? + "Fool" : "Young Fool"); + verbl_msg = verbuf; + } else { vampindex = rn2(SIZE(vampmsg)); if (vampindex == 0) { Sprintf(verbuf, vampmsg[vampindex], body_part(BLOOD)); @@ -518,7 +528,7 @@ register struct monst *mtmp; case MS_WERE: if (flags.moonphase == FULL_MOON && (night() ^ !rn2(13))) { pline("%s throws back %s head and lets out a blood curdling %s!", - Monnam(mtmp), his[pronoun_gender(mtmp)], + Monnam(mtmp), mhis(mtmp), ptr == &mons[PM_HUMAN_WERERAT] ? "shriek" : "howl"); wake_nearto(mtmp->mx, mtmp->my, 11*11); } else @@ -636,7 +646,7 @@ register struct monst *mtmp; if (!mtmp->mpeaceful) { switch (rn2(4)) { case 0: pline("%s boasts about %s gem collection.", - Monnam(mtmp), his[pronoun_gender(mtmp)]); + Monnam(mtmp), mhis(mtmp)); break; case 1: pline_msg = "complains about a diet of mutton."; break; @@ -766,7 +776,11 @@ register struct monst *mtmp; else verbl_msg = "Relax, this won't hurt a bit."; break; case MS_GUARD: +#ifndef GOLDOBJ if (u.ugold) +#else + if (money_cnt(invent)) +#endif verbl_msg = "Please drop that gold and follow me."; else verbl_msg = "Please follow me."; @@ -817,7 +831,7 @@ dochat() register int tx,ty; struct obj *otmp; - if (youmonst.data->msound == MS_SILENT) { + if (is_silent(youmonst.data)) { pline("As %s, you cannot speak.", an(youmonst.data->mname)); return(0); } @@ -846,7 +860,7 @@ dochat() return(1); } - (void) getdir("Talk to whom? [in what direction]"); + (void) getdir("Talk to whom? (in what direction)"); #ifdef STEED if (u.usteed && u.dz > 0) @@ -898,6 +912,92 @@ dochat() return domonnoise(mtmp); } +#ifdef USER_SOUNDS + +extern void FDECL(play_usersound, (const char*, int)); + +typedef struct audio_mapping_rec { + struct re_pattern_buffer regex; + char *filename; + int volume; + struct audio_mapping_rec *next; +} audio_mapping; + +static audio_mapping *soundmap = 0; + +char* sounddir = "."; + +/* adds a sound file mapping, returns 0 on failure, 1 on success */ +int +add_sound_mapping(mapping) +const char *mapping; +{ + char text[256]; + char filename[256]; + char filespec[256]; + int volume; + + if (sscanf(mapping, "MESG \"%255[^\"]\"%*[\t ]\"%255[^\"]\" %d", + text, filename, &volume) == 3) { + const char *err; + audio_mapping *new_map; + + if (strlen(sounddir) + strlen(filename) > 254) { + raw_print("sound file name too long"); + return 0; + } + Sprintf(filespec, "%s/%s", sounddir, filename); + + if (can_read_file(filespec)) { + new_map = (audio_mapping *)alloc(sizeof(audio_mapping)); + new_map->regex.translate = 0; + new_map->regex.fastmap = 0; + new_map->regex.buffer = 0; + new_map->regex.allocated = 0; + new_map->regex.regs_allocated = REGS_FIXED; + new_map->filename = strdup(filespec); + new_map->volume = volume; + new_map->next = soundmap; + + err = re_compile_pattern(text, strlen(text), &new_map->regex); + + if (err) { + raw_print(err); + free(new_map->filename); + free(new_map); + return 0; + } else { + soundmap = new_map; + } + } else { + Sprintf(text, "cannot read %.243s", filespec); + raw_print(text); + return 0; + } + } else { + raw_print("syntax error in SOUND"); + return 0; + } + + return 1; +} + +void +play_sound_for_message(msg) +const char* msg; +{ + audio_mapping* cursor = soundmap; + + while (cursor) { + if (re_search(&cursor->regex, msg, strlen(msg), 0, 9999, 0) >= 0) { + play_usersound(cursor->filename, cursor->volume); + } + cursor = cursor->next; + } +} + +#endif /* USER_SOUNDS */ + #endif /* OVLB */ /*sounds.c*/ diff --git a/src/sp_lev.c b/src/sp_lev.c index 56b53e7..6224c06 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)sp_lev.c 3.3 1999/11/16 */ +/* SCCS Id: @(#)sp_lev.c 3.4 2001/09/06 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -850,8 +850,8 @@ struct mkroom *croom; case M_AP_OBJECT: for (i = 0; i < NUM_OBJECTS; i++) - if (!strcmp(OBJ_NAME(objects[i]), - m->appear_as.str)) + if (OBJ_NAME(objects[i]) && + !strcmp(OBJ_NAME(objects[i]),m->appear_as.str)) break; if (i == NUM_OBJECTS) { impossible( @@ -912,8 +912,10 @@ struct mkroom *croom; struct obj *otmp; schar x, y; char c; + boolean named; /* has a name been supplied in level description? */ if (rn2(100) < o->chance) { + named = o->name.str ? TRUE : FALSE; x = o->x; y = o->y; if (croom) @@ -929,9 +931,9 @@ struct mkroom *croom; c = 0; if (!c) - otmp = mkobj_at(RANDOM_CLASS, x, y, TRUE); + otmp = mkobj_at(RANDOM_CLASS, x, y, !named); else if (o->id != -1) - otmp = mksobj_at(o->id, x, y, TRUE); + otmp = mksobj_at(o->id, x, y, TRUE, !named); else { /* * The special levels are compiled with the default "text" object @@ -944,9 +946,9 @@ struct mkroom *croom; /* KMH -- Create piles of gold properly */ if (oclass == GOLD_CLASS) - otmp = mkgold(0L, x, y); + otmp = mkgold(0L, x, y); else - otmp = mkobj_at(oclass, x, y, TRUE); + otmp = mkobj_at(oclass, x, y, !named); } if (o->spe != -127) /* That means NOT RANDOM! */ @@ -973,9 +975,8 @@ struct mkroom *croom; attach_egg_hatch_timeout(otmp); /* attach new hatch timeout */ } - if (o->name.str) { /* Give a name to that object */ + if (named) otmp = oname(otmp, o->name.str); - } switch(o->containment) { static struct obj *container = 0; @@ -987,7 +988,7 @@ struct mkroom *croom; break; } remove_object(otmp); - add_to_container(container, otmp); + (void) add_to_container(container, otmp); goto o_done; /* don't stack, but do other cleanup */ /* container */ case 2: @@ -1025,8 +1026,9 @@ struct mkroom *croom; obj = was->minvent; obj->owornmask = 0; obj_extract_self(obj); - add_to_container(otmp, obj); + (void) add_to_container(otmp, obj); } + otmp->owt = weight(otmp); mongone(was); } @@ -1128,7 +1130,7 @@ create_altar(a, croom) levl[x][y].typ = ALTAR; levl[x][y].altarmask = amask; - if (a->shrine == -11) a->shrine = rn2(1); /* handle random case */ + if (a->shrine < 0) a->shrine = rn2(2); /* handle random case */ if (oldtyp == FOUNTAIN) level.flags.nfountains--; @@ -1309,7 +1311,7 @@ schar ftyp, btyp; if(ftyp != CORR || rn2(100)) { crm->typ = ftyp; if(nxcor && !rn2(50)) - (void) mksobj_at(BOULDER, xx, yy, TRUE); + (void) mksobj_at(BOULDER, xx, yy, TRUE, FALSE); } else { crm->typ = SCORR; } @@ -2187,7 +2189,8 @@ dlb *fd; if (x != xstart && (IS_WALL(levl[x-1][y].typ) || levl[x-1][y].horizontal)) levl[x][y].horizontal = 1; - } else if(levl[x][y].typ == HWALL) + } else if(levl[x][y].typ == HWALL || + levl[x][y].typ == IRONBARS) levl[x][y].horizontal = 1; else if(levl[x][y].typ == LAVAPOOL) levl[x][y].lit = 1; @@ -2584,7 +2587,7 @@ dlb *fd; } for(x = rnd((int) (12 * mapfact) / 100); x; x--) { maze1xy(&mm, DRY); - (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE); + (void) mksobj_at(BOULDER, mm.x, mm.y, TRUE, FALSE); } for (x = rn2(2); x; x--) { maze1xy(&mm, DRY); diff --git a/src/spell.c b/src/spell.c index 7e55001..ab72822 100644 --- a/src/spell.c +++ b/src/spell.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)spell.c 3.3 2000/01/10 */ +/* SCCS Id: @(#)spell.c 3.4 2002/02/12 */ /* Copyright (c) M. Stephenson 1988 */ /* NetHack may be freely redistributed. See license for details. */ @@ -20,17 +20,17 @@ static NEARDATA struct obj *book; /* last/current book being xscribed */ #define spellet(spell) \ ((char)((spell < 26) ? ('a' + spell) : ('A' + spell - 26))) -static int FDECL(spell_let_to_idx, (CHAR_P)); -static void FDECL(cursed_book, (int)); -static void FDECL(deadbook, (struct obj *)); +STATIC_DCL int FDECL(spell_let_to_idx, (CHAR_P)); +STATIC_DCL void FDECL(cursed_book, (int)); +STATIC_DCL void FDECL(deadbook, (struct obj *)); STATIC_PTR int NDECL(learn); -static boolean FDECL(getspell, (int *)); -static boolean FDECL(dospellmenu, (const char *,int,int *)); -static int FDECL(percent_success, (int)); -static int NDECL(throwspell); -static void NDECL(cast_protection); -static const char *FDECL(spelltypemnemonic, (int)); -static int FDECL(isqrt, (int)); +STATIC_DCL boolean FDECL(getspell, (int *)); +STATIC_DCL boolean FDECL(dospellmenu, (const char *,int,int *)); +STATIC_DCL int FDECL(percent_success, (int)); +STATIC_DCL int NDECL(throwspell); +STATIC_DCL void NDECL(cast_protection); +STATIC_DCL const char *FDECL(spelltypemnemonic, (int)); +STATIC_DCL int FDECL(isqrt, (int)); /* The roles[] table lists the role-specific values for tuning * percent_success(). @@ -53,7 +53,7 @@ static int FDECL(isqrt, (int)); * * The arms penalty is lessened for trained fighters Bar, Kni, Ran, * Sam, Val - - * the penalty is its metal interference, not encumberance. + * the penalty is its metal interference, not encumbrance. * The `spelspec' is a single spell which is fundamentally easier * for that role to cast. * @@ -89,7 +89,7 @@ static int FDECL(isqrt, (int)); static const char explodes[] = "radiates explosive energy"; /* convert a letter into a number in the range 0..51, or -1 if not a letter */ -static int +STATIC_OVL int spell_let_to_idx(ilet) char ilet; { @@ -102,7 +102,7 @@ char ilet; return -1; } -static void +STATIC_OVL void cursed_book(lev) register int lev; { @@ -131,10 +131,15 @@ cursed_book(lev) if (uarmg->oerodeproof || !is_corrodeable(uarmg)) { Your("gloves seem unaffected."); } else if (uarmg->oeroded2 < MAX_ERODE) { - Your("gloves corrode%s!", - uarmg->oeroded2+1 == MAX_ERODE ? " completely" : - uarmg->oeroded2 ? " further" : ""); - uarmg->oeroded2++; + if (uarmg->greased) { + grease_protect(uarmg, "gloves", &youmonst); + } else { + Your("gloves corrode%s!", + uarmg->oeroded2+1 == MAX_ERODE ? + " completely" : uarmg->oeroded2 ? + " further" : ""); + uarmg->oeroded2++; + } } else Your("gloves %s completely corroded.", Blind ? "feel" : "look"); @@ -162,7 +167,7 @@ cursed_book(lev) } /* special effects for The Book of the Dead */ -static void +STATIC_OVL void deadbook(book2) struct obj *book2; { @@ -238,7 +243,9 @@ struct obj *book2; } else if(book2->blessed) { for(mtmp = fmon; mtmp; mtmp = mtmp2) { mtmp2 = mtmp->nmon; /* tamedog() changes chain */ - if(!DEADMONSTER(mtmp) && is_undead(mtmp->data) && cansee(mtmp->mx, mtmp->my)) { + if (DEADMONSTER(mtmp)) continue; + + if (is_undead(mtmp->data) && cansee(mtmp->mx, mtmp->my)) { mtmp->mpeaceful = TRUE; if(sgn(mtmp->data->maligntyp) == sgn(u.ualign.type) && distu(mtmp->mx, mtmp->my) < 4) @@ -247,7 +254,7 @@ struct obj *book2; mtmp->mtame++; } else (void) tamedog(mtmp, (struct obj *)0); - else mtmp->mflee = TRUE; + else monflee(mtmp, 0, FALSE, TRUE); } } } else { @@ -273,6 +280,8 @@ learn() char splname[BUFSZ]; boolean costly = TRUE; + /* JDS: lenses give 50% faster reading; 33% smaller read time */ + if (delay && ublindf && ublindf->otyp == LENSES && rn2(2)) delay++; if (delay) { /* not if (delay++), so at end delay == 0 */ delay++; return(1); /* still busy */ @@ -372,29 +381,31 @@ register struct obj *spellbook; /* Books are often wiser than their readers (Rus.) */ spellbook->in_use = TRUE; - if (!spellbook->blessed && spellbook->otyp != SPE_BOOK_OF_THE_DEAD) { - if (spellbook->cursed) { - too_hard = TRUE; - } else { - /* uncursed - chance to fail */ - int read_ability = ACURR(A_INT) + 4 + u.ulevel/2 - - 2*objects[booktype].oc_level; - /* only wizards know if a spell is too difficult */ - if (Role_if(PM_WIZARD) && read_ability < 20) { - char qbuf[QBUFSZ]; - Sprintf(qbuf, + if (!spellbook->blessed && + spellbook->otyp != SPE_BOOK_OF_THE_DEAD) { + if (spellbook->cursed) { + too_hard = TRUE; + } else { + /* uncursed - chance to fail */ + int read_ability = ACURR(A_INT) + 4 + u.ulevel/2 + - 2*objects[booktype].oc_level + + ((ublindf && ublindf->otyp == LENSES) ? 2 : 0); + /* only wizards know if a spell is too difficult */ + if (Role_if(PM_WIZARD) && read_ability < 20) { + char qbuf[QBUFSZ]; + Sprintf(qbuf, "This spellbook is %sdifficult to comprehend. Continue?", - (read_ability < 12 ? "very " : "")); - if (yn(qbuf) != 'y') { - spellbook->in_use = FALSE; - return(1); - } - } - /* its up to random luck now */ - if (rnd(20) > read_ability) { - too_hard = TRUE; + (read_ability < 12 ? "very " : "")); + if (yn(qbuf) != 'y') { + spellbook->in_use = FALSE; + return(1); } } + /* its up to random luck now */ + if (rnd(20) > read_ability) { + too_hard = TRUE; + } + } } if (too_hard) { @@ -442,6 +453,15 @@ register struct obj *spellbook; return(1); } +/* a spellbook has been destroyed or the character has changed levels; + the stored address for the current book is no longer valid */ +void +book_disappears(obj) +struct obj *obj; +{ + if (obj == book) book = (struct obj *)0; +} + /* renaming an object usually results in it having a different address; so the sequence start reading, get interrupted, name the book, resume reading would read the "new" book from scratch */ @@ -473,7 +493,7 @@ age_spells() * Return TRUE if a spell was picked, with the spell index in the return * parameter. Otherwise return FALSE. */ -static boolean +STATIC_OVL boolean getspell(spell_no) int *spell_no; { @@ -526,7 +546,7 @@ docast() return 0; } -static const char * +STATIC_OVL const char * spelltypemnemonic(skill) int skill; { @@ -558,7 +578,7 @@ int booktype; return (objects[booktype].oc_skill); } -static void +STATIC_OVL void cast_protection() { int loglev = 0; @@ -742,15 +762,17 @@ boolean atme; n=rnd(8)+1; while(n--) { if(!u.dx && !u.dy && !u.dz) { - if ((damage = zapyourself(pseudo, TRUE)) != 0) - losehp(damage, - self_pronoun("zapped %sself with a spell", - "him"), - NO_KILLER_PREFIX); + if ((damage = zapyourself(pseudo, TRUE)) != 0) { + char buf[BUFSZ]; + Sprintf(buf, "zapped %sself with a spell", uhim()); + losehp(damage, buf, NO_KILLER_PREFIX); + } } else { explode(u.dx, u.dy, pseudo->otyp - SPE_MAGIC_MISSILE + 10, - u.ulevel/2 + 1 + spell_damage_bonus(), 0); + u.ulevel/2 + 1 + spell_damage_bonus(), 0, + (pseudo->otyp == SPE_CONE_OF_COLD) ? + EXPL_FROSTY : EXPL_FIERY); } u.dx = cc.x+rnd(3)-2; u.dy = cc.y+rnd(3)-2; if (!isok(u.dx,u.dy) || !cansee(u.dx,u.dy) || @@ -787,13 +809,14 @@ boolean atme; if (atme) u.dx = u.dy = u.dz = 0; else (void) getdir((char *)0); if(!u.dx && !u.dy && !u.dz) { - if ((damage = zapyourself(pseudo, TRUE)) != 0) - losehp(damage, - self_pronoun("zapped %sself with a spell", - "him"), - NO_KILLER_PREFIX); + if ((damage = zapyourself(pseudo, TRUE)) != 0) { + char buf[BUFSZ]; + Sprintf(buf, "zapped %sself with a spell", uhim()); + losehp(damage, buf, NO_KILLER_PREFIX); + } } else weffects(pseudo); } else weffects(pseudo); + update_inventory(); /* spell may modify inventory */ break; /* these are all duplicates of scroll effects */ @@ -832,6 +855,7 @@ boolean atme; if (Slimed) { pline_The("slime disappears!"); Slimed = 0; + /* flags.botl = 1; -- healup() handles this */ } healup(0, 0, TRUE, FALSE); break; @@ -868,7 +892,7 @@ boolean atme; } /* Choose location where spell takes effect. */ -static int +STATIC_OVL int throwspell() { coord cc; @@ -948,7 +972,7 @@ dovspell() return 0; } -static boolean +STATIC_OVL boolean dospellmenu(prompt, splaction, spell_no) const char *prompt; int splaction; /* SPELLMENU_CAST, SPELLMENU_VIEW, or spl_book[] index */ @@ -973,10 +997,14 @@ int *spell_no; * To do it right would require that we implement columns * in the window-ports (say via a tab character). */ - Sprintf(buf, "%-20s Level %-12s Fail", " Name", "Category"); + if (!iflags.menu_tab_sep) + Sprintf(buf, "%-20s Level %-12s Fail", " Name", "Category"); + else + Sprintf(buf, "Name\tLevel\tCategory\tFail"); add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); for (i = 0; i < MAXSPELL && spellid(i) != NO_SPELL; i++) { - Sprintf(buf, "%-20s %2d%s %-12s %3d%%", + Sprintf(buf, iflags.menu_tab_sep ? + "%s\t%-d%s\t%s\t%-d%%" : "%-20s %2d%s %-12s %3d%%", spellname(i), spellev(i), spellknow(i) ? " " : "*", spelltypemnemonic(spell_skilltype(spellid(i))), @@ -1015,7 +1043,7 @@ int *spell_no; } /* Integer square root function without using floating point. */ -static int +STATIC_OVL int isqrt(val) int val; { @@ -1029,7 +1057,7 @@ int val; return rt; } -static int +STATIC_OVL int percent_success(spell) int spell; { @@ -1084,7 +1112,8 @@ int spell; * The difficulty is based on the hero's level and their skill level * in that spell type. */ - skill = P_SKILL(spell_skilltype(spellid(spell)))-1; + skill = P_SKILL(spell_skilltype(spellid(spell))); + skill = max(skill,P_UNSKILLED) - 1; /* unskilled => 0 */ difficulty= (spellev(spell)-1) * 4 - ((skill * 6) + (u.ulevel/3) + 1); if (difficulty > 0) { @@ -1122,8 +1151,8 @@ int spell; /* Finally, chance (based on player intell/wisdom and level) is * combined with ability (based on player intrinsics and - * encumberances). No matter how intelligent/wise and advanced - * a player is, intrinsics and encumberance can prevent casting; + * encumbrances). No matter how intelligent/wise and advanced + * a player is, intrinsics and encumbrance can prevent casting; * and no matter how able, learning is always required. */ chance = chance * (20-splcaster) / 15 - splcaster; @@ -1160,5 +1189,4 @@ struct obj *obj; return; } - /*spell.c*/ diff --git a/src/steal.c b/src/steal.c index 4153d4f..c020b2e 100644 --- a/src/steal.c +++ b/src/steal.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)steal.c 3.3 1999/02/13 */ +/* SCCS Id: @(#)steal.c 3.4 2002/01/04 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -20,10 +20,11 @@ register struct obj *otmp; (otmp == uarmf) ? "boots" : (otmp == uarms) ? "shield" : (otmp == uarmg) ? "gloves" : - (otmp == uarmc) ? "cloak" : + (otmp == uarmc) ? cloak_simple_name(otmp) : (otmp == uarmh) ? "helmet" : "armor"); } +#ifndef GOLDOBJ long /* actually returns something that fits in an int */ somegold() { @@ -50,17 +51,89 @@ register struct monst *mtmp; Monnam(mtmp), makeplural(body_part(FOOT))); if(!u.ugold || !rn2(5)) { if (!tele_restrict(mtmp)) rloc(mtmp); - mtmp->mflee = 1; + monflee(mtmp, 0, FALSE, FALSE); } } else if(u.ugold) { u.ugold -= (tmp = somegold()); Your("purse feels lighter."); mtmp->mgold += tmp; + if (!tele_restrict(mtmp)) rloc(mtmp); + monflee(mtmp, 0, FALSE, FALSE); + flags.botl = 1; + } +} + +#else /* !GOLDOBJ */ + +long /* actually returns something that fits in an int */ +somegold(umoney) +long umoney; +{ +#ifdef LINT /* long conv. ok */ + return(0L); +#else + return (long)( (umoney < 100) ? umoney : + (umoney > 10000) ? rnd(10000) : rnd((int) umoney) ); +#endif +} + +/* +Find the first (and hopefully only) gold object in a chain. +Used when leprechaun (or you as leprechaun) looks for +someone else's gold. Returns a pointer so the gold may +be seized without further searching. +May search containers too. +Deals in gold only, as leprechauns don't care for lesser coins. +*/ +struct obj * +findgold(chain) +register struct obj *chain; +{ + while (chain && chain->otyp != GOLD_PIECE) chain = chain->nobj; + return chain; +} + +/* +Steal gold coins only. Leprechauns don't care for lesser coins. +*/ +void +stealgold(mtmp) +register struct monst *mtmp; +{ + register struct obj *fgold = g_at(u.ux, u.uy); + register struct obj *ygold; + register long tmp; + + /* skip lesser coins on the floor */ + while (fgold && fgold->otyp != GOLD_PIECE) fgold = fgold->nexthere; + + /* Do you have real gold? */ + ygold = findgold(invent); + + if (fgold && ( !ygold || fgold->quan > ygold->quan || !rn2(5))) { + obj_extract_self(fgold); + add_to_minv(mtmp, fgold); + newsym(u.ux, u.uy); + pline("%s quickly snatches some gold from between your %s!", + Monnam(mtmp), makeplural(body_part(FOOT))); + if(!ygold || !rn2(5)) { + if (!tele_restrict(mtmp)) rloc(mtmp); + monflee(mtmp, 0, FALSE, FALSE); + } + } else if(ygold) { + const int gold_price = objects[GOLD_PIECE].oc_cost; + tmp = (somegold(money_cnt(invent)) + gold_price - 1) / gold_price; + tmp = min(tmp, ygold->quan); + if (tmp < ygold->quan) ygold = splitobj(ygold, tmp); + freeinv(ygold); + add_to_minv(mtmp, ygold); + Your("purse feels lighter."); if (!tele_restrict(mtmp)) rloc(mtmp); - mtmp->mflee = 1; + monflee(mtmp, 0, FALSE, FALSE); flags.botl = 1; } } +#endif /* GOLDOBJ */ /* steal armor after you finish taking it off */ unsigned int stealoid; /* object to be stolen */ @@ -84,7 +157,7 @@ stealarm() freeinv(otmp); pline("%s steals %s!", Monnam(mtmp), doname(otmp)); (void) mpickobj(mtmp,otmp); /* may free otmp */ - mtmp->mflee = 1; + monflee(mtmp, 0, FALSE, FALSE); if (!tele_restrict(mtmp)) rloc(mtmp); break; } @@ -96,7 +169,7 @@ botm: stealoid = 0; return 0; } -/* An object you're wearing has been taken off my a monster (theft or +/* An object you're wearing has been taken off by a monster (theft or seduction). Also used if a worn item gets transformed (stone to flesh). */ void remove_worn_item(obj) @@ -107,18 +180,11 @@ struct obj *obj; if (!obj->owornmask) return; - switch (obj->oclass) { - case TOOL_CLASS: - if (obj == ublindf) Blindf_off(obj); - break; - case AMULET_CLASS: - Amulet_off(); - break; - case RING_CLASS: - case FOOD_CLASS: /* meat ring */ - Ring_gone(obj); - break; - case ARMOR_CLASS: + if (obj->owornmask & W_ARMOR) { + if (obj == uskin) { + impossible("Removing embedded scales?"); + skinback(TRUE); /* uarm = uskin; uskin = 0; */ + } if (obj == uarm) (void) Armor_off(); else if (obj == uarmc) (void) Cloak_off(); else if (obj == uarmf) (void) Boots_off(); @@ -126,12 +192,25 @@ struct obj *obj; else if (obj == uarmh) (void) Helmet_off(); else if (obj == uarms) (void) Shield_off(); else setworn((struct obj *)0, obj->owornmask & W_ARMOR); - break; - default: - /* shouldn't reach here, but just in case... */ - setnotworn(obj); - break; + } else if (obj->owornmask & W_AMUL) { + Amulet_off(); + } else if (obj->owornmask & W_RING) { + Ring_gone(obj); + } else if (obj->owornmask & W_TOOL) { + Blindf_off(obj); + } else if (obj->owornmask & (W_BALL|W_CHAIN)) { + unpunish(); + } else if (obj->owornmask & (W_WEP|W_SWAPWEP|W_QUIVER)) { + if (obj == uwep) + uwepgone(); + else if (obj == uswapwep) + uswapwepgone(); + else if (obj == uquiver) + uqwepgone(); } + + /* catchall */ + if (obj->owornmask) setnotworn(obj); } /* Returns 1 when something was stolen (or at least, when N should flee now) @@ -139,15 +218,23 @@ struct obj *obj; * Avoid stealing the object stealoid */ int -steal(mtmp) +steal(mtmp, objnambuf) struct monst *mtmp; +char *objnambuf; { struct obj *otmp; - int tmp, could_petrify, named = 0; + int tmp, could_petrify, named = 0, armordelay; + boolean monkey_business; /* true iff an animal is doing the thievery */ + if (objnambuf) *objnambuf = '\0'; /* the following is true if successful on first of two attacks. */ if(!monnear(mtmp, u.ux, u.uy)) return(0); + /* food being eaten might already be used up but will not have + been removed from inventory yet; we don't want to steal that, + so this will cause it to be removed now */ + if (occupation) (void) maybe_finished_meal(FALSE); + if (!invent || (inv_cnt() == 1 && uskin)) { nothing_to_steal: /* Not even a thousand men in armor can strip a naked man. */ @@ -159,7 +246,10 @@ struct monst *mtmp; return(1); /* let her flee */ } - if (Adornment & LEFT_RING) { + monkey_business = is_animal(mtmp->data); + if (monkey_business) { + ; /* skip ring special cases */ + } else if (Adornment & LEFT_RING) { otmp = uleft; goto gotobj; } else if (Adornment & RIGHT_RING) { @@ -183,7 +273,7 @@ struct monst *mtmp; #ifdef INVISIBLE_OBJECTS && (!otmp->oinvis || perceives(mtmp->data)) #endif - ) + ) if((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1)) < 0) break; @@ -203,7 +293,39 @@ struct monst *mtmp; gotobj: if(otmp->o_id == stealoid) return(0); - if(otmp->otyp == LEASH && otmp->leashmon) o_unleash(otmp); + /* animals can't overcome curse stickiness nor unlock chains */ + if (monkey_business) { + boolean ostuck; + /* is the player prevented from voluntarily giving up this item? + (ignores loadstones; the !can_carry() check will catch those) */ + if (otmp == uball) + ostuck = TRUE; /* effectively worn; curse is implicit */ + else if (otmp == uquiver || (otmp == uswapwep && !u.twoweap)) + ostuck = FALSE; /* not really worn; curse doesn't matter */ + else + ostuck = (otmp->cursed && otmp->owornmask); + + if (ostuck || !can_carry(mtmp, otmp)) { + static const char *how[] = { "steal","snatch","grab","take" }; + cant_take: + pline("%s tries to %s your %s but gives up.", + Monnam(mtmp), how[rn2(SIZE(how))], + (otmp->owornmask & W_ARMOR) ? equipname(otmp) : + cxname(otmp)); + /* the fewer items you have, the less likely the thief + is going to stick around to try again (0) instead of + running away (1) */ + return !rn2(inv_cnt() / 5 + 2); + } + } + + if (otmp->otyp == LEASH && otmp->leashmon) { + if (monkey_business && otmp->cursed) goto cant_take; + o_unleash(otmp); + } + + /* you're going to notice the theft... */ + stop_occupation(); if((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))){ switch(otmp->oclass) { @@ -211,33 +333,43 @@ struct monst *mtmp; case AMULET_CLASS: case RING_CLASS: case FOOD_CLASS: /* meat ring */ + remove_worn_item(otmp); + break; + case ARMOR_CLASS: + armordelay = objects[otmp->otyp].oc_delay; + /* Stop putting on armor which has been stolen. */ + if (donning(otmp)) { remove_worn_item(otmp); break; - case ARMOR_CLASS: - /* Stop putting on armor which has been stolen. */ - if (donning(otmp) || is_animal(mtmp->data)) { - remove_worn_item(otmp); - break; - } else { + } else if (monkey_business) { + /* animals usually don't have enough patience + to take off items which require extra time */ + if (armordelay >= 1 && rn2(10)) goto cant_take; + remove_worn_item(otmp); + break; + } else { int curssv = otmp->cursed; + int slowly; otmp->cursed = 0; - stop_occupation(); + /* can't charm you without first waking you */ + if (multi < 0 && is_fainted()) unmul((char *)0); + slowly = (armordelay >= 1 || multi < 0); if(flags.female) pline("%s charms you. You gladly %s your %s.", Blind ? "She" : Monnam(mtmp), curssv ? "let her take" : - (objects[otmp->otyp].oc_delay > 1) ? "start removing" : "hand over", + slowly ? "start removing" : "hand over", equipname(otmp)); else pline("%s seduces you and %s off your %s.", Blind ? "It" : Adjmonnam(mtmp, "beautiful"), curssv ? "helps you to take" : - (objects[otmp->otyp].oc_delay > 1) ? "you start taking" : "you take", + slowly ? "you start taking" : "you take", equipname(otmp)); named++; /* the following is to set multi for later on */ - nomul(-objects[otmp->otyp].oc_delay); + nomul(-armordelay); remove_worn_item(otmp); otmp->cursed = curssv; if(multi < 0){ @@ -252,20 +384,22 @@ struct monst *mtmp; return(0); } } - break; + break; default: - impossible("Tried to steal a strange worn thing."); + impossible("Tried to steal a strange worn thing. [%d]", + otmp->oclass); } } - else if (otmp == uwep) uwepgone(); - else if (otmp == uquiver) uqwepgone(); - else if (otmp == uswapwep) uswapwepgone(); + else if (otmp->owornmask) + remove_worn_item(otmp); - if(otmp == uball) unpunish(); + /* do this before removing it from inventory */ + if (objnambuf) Strcpy(objnambuf, yname(otmp)); freeinv(otmp); pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp)); - could_petrify = otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]); + could_petrify = (otmp->otyp == CORPSE && + touch_petrifies(&mons[otmp->corpsenm])); (void) mpickobj(mtmp,otmp); /* may free otmp */ if (could_petrify && !(mtmp->misc_worn_check & W_ARMG)) { minstapetrify(mtmp, TRUE); @@ -285,32 +419,35 @@ register struct obj *otmp; { int freed_otmp; +#ifndef GOLDOBJ if (otmp->oclass == GOLD_CLASS) { mtmp->mgold += otmp->quan; obfree(otmp, (struct obj *)0); freed_otmp = 1; } else { - boolean snuff_otmp = FALSE; - /* don't want hidden light source inside the monster; assumes that - engulfers won't have external inventories; whirly monsters cause - the light to be extinguished rather than letting it shine thru */ - if (otmp->lamplit && /* hack to avoid function calls for most objs */ - obj_sheds_light(otmp) && - attacktype(mtmp->data, AT_ENGL)) { - /* this is probably a burning object that you dropped or threw */ - if (u.uswallow && mtmp == u.ustuck && !Blind) - pline("%s go%s out.", The(xname(otmp)), - otmp->quan == 1L ? "es" : ""); - snuff_otmp = TRUE; - } - /* Must do carrying effects on object prior to add_to_minv() */ - carry_obj_effects(otmp); - /* add_to_minv() might free otmp [if merged with something else], - so we have to call it after doing the object checks */ - freed_otmp = add_to_minv(mtmp, otmp); - /* and we had to defer this until object is in mtmp's inventory */ - if (snuff_otmp) snuff_light_source(mtmp->mx, mtmp->my); +#endif + boolean snuff_otmp = FALSE; + /* don't want hidden light source inside the monster; assumes that + engulfers won't have external inventories; whirly monsters cause + the light to be extinguished rather than letting it shine thru */ + if (otmp->lamplit && /* hack to avoid function calls for most objs */ + obj_sheds_light(otmp) && + attacktype(mtmp->data, AT_ENGL)) { + /* this is probably a burning object that you dropped or threw */ + if (u.uswallow && mtmp == u.ustuck && !Blind) + pline("%s out.", Tobjnam(otmp, "go")); + snuff_otmp = TRUE; } + /* Must do carrying effects on object prior to add_to_minv() */ + carry_obj_effects(otmp); + /* add_to_minv() might free otmp [if merged with something else], + so we have to call it after doing the object checks */ + freed_otmp = add_to_minv(mtmp, otmp); + /* and we had to defer this until object is in mtmp's inventory */ + if (snuff_otmp) snuff_light_source(mtmp->mx, mtmp->my); +#ifndef GOLDOBJ + } +#endif return freed_otmp; } @@ -399,6 +536,13 @@ boolean is_pet; /* If true, pet should keep wielded/worn items */ continue; } mtmp->misc_worn_check &= ~(otmp->owornmask); +#ifdef STEED + /* don't charge for an owned saddle on dead pet */ + if (mtmp->mtame && mtmp->mhp == 0 && + (otmp->owornmask & W_SADDLE) && !otmp->unpaid && + costly_spot(mtmp->mx, mtmp->my)) + otmp->no_charge = 1; +#endif otmp->owornmask = 0L; } if (is_pet && cansee(omx, omy) && flags.verbose) @@ -413,7 +557,7 @@ boolean is_pet; /* If true, pet should keep wielded/worn items */ keepobj = otmp->nobj; (void) add_to_minv(mtmp, otmp); } - +#ifndef GOLDOBJ if (mtmp->mgold) { register long g = mtmp->mgold; (void) mkgold(g, omx, omy); @@ -422,6 +566,8 @@ boolean is_pet; /* If true, pet should keep wielded/worn items */ g, plur(g)); mtmp->mgold = 0L; } +#endif + if (show & cansee(omx, omy)) newsym(omx, omy); } diff --git a/src/steed.c b/src/steed.c index c051728..deeeb45 100644 --- a/src/steed.c +++ b/src/steed.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)steed.c 3.3 2000/07/29 */ +/* SCCS Id: @(#)steed.c 3.4 2002/03/09 */ /* Copyright (c) Kevin Hugo, 1998-1999. */ /* NetHack may be freely redistributed. See license for details. */ @@ -12,6 +12,7 @@ static NEARDATA const char steeds[] = { S_QUADRUPED, S_UNICORN, S_ANGEL, S_CENTAUR, S_DRAGON, S_JABBERWOCK, '\0' }; +STATIC_DCL boolean FDECL(landing_spot, (coord *, int)); /*** Putting the saddle on ***/ @@ -200,6 +201,26 @@ mount_steed(mtmp, force) pline("Maybe you should find a designated driver."); return (FALSE); } + /* While riding Wounded_legs refers to the steed's, + * not the hero's legs. + * That opens up a potential abuse where the player + * can mount a steed, then dismount immediately to + * heal leg damage, because leg damage is always + * healed upon dismount (Wounded_legs context switch). + * By preventing a hero with Wounded_legs from + * mounting a steed, the potential for abuse is + * minimized, if not eliminated altogether. + */ + if (Wounded_legs) { + Your("%s are in no shape for riding.", makeplural(body_part(LEG))); +#ifdef WIZARD + if (force && wizard && yn("Heal your legs?") == 'y') + HWounded_legs = EWounded_legs = 0; + else +#endif + return (FALSE); + } + if (Upolyd && (!humanoid(youmonst.data) || verysmall(youmonst.data) || bigmonst(youmonst.data))) { if (!force) @@ -251,7 +272,11 @@ mount_steed(mtmp, force) return (FALSE); } if (!force && !Role_if(PM_KNIGHT) && !(--mtmp->mtame)) { - pline("%s resists!", Monnam(mtmp)); + /* no longer tame */ + newsym(mtmp->mx, mtmp->my); + pline("%s resists%s!", Monnam(mtmp), + mtmp->mleashed ? " and its leash comes off" : ""); + if (mtmp->mleashed) m_unleash(mtmp, FALSE); return (FALSE); } if (!force && Underwater && !is_swimmer(ptr)) { @@ -278,8 +303,13 @@ mount_steed(mtmp, force) return (FALSE); } if (!force && (Confusion || Fumbling || Glib || Wounded_legs || - otmp->cursed || (u.ulevel+mtmp->mtame < rnd(MAXULEV/2+5)))) { + otmp->cursed || (u.ulevel+mtmp->mtame < rnd(MAXULEV/2+5)))) { + if (Levitation) { + pline("%s slips away from you.", Monnam(mtmp)); + return FALSE; + } You("slip while trying to get on %s.", mon_nam(mtmp)); + /* Unfortunately we don't have a version of the monster-naming * function that works well with "a" and "the" but ignores * hallucination. Fortunately, we know the monster must be saddled @@ -327,12 +357,40 @@ exercise_steed() void kick_steed() { + char He[4]; if (!u.usteed) return; + /* [ALI] Various effects of kicking sleeping/paralyzed steeds */ + if (u.usteed->msleeping || !u.usteed->mcanmove) { + /* We assume a message has just been output of the form + * "You kick ." + */ + Strcpy(He, mhe(u.usteed)); + *He = highc(*He); + if ((u.usteed->mcanmove || u.usteed->mfrozen) && !rn2(2)) { + if (u.usteed->mcanmove) + u.usteed->msleeping = 0; + else if (u.usteed->mfrozen > 2) + u.usteed->mfrozen -= 2; + else { + u.usteed->mfrozen = 0; + u.usteed->mcanmove = 1; + } + if (u.usteed->msleeping || !u.usteed->mcanmove) + pline("%s stirs.", He); + else + pline("%s rouses %sself!", He, mhim(u.usteed)); + } else + pline("%s does not respond.", He); + return; + } + /* Make the steed less tame and check if it resists */ if (u.usteed->mtame) u.usteed->mtame--; + if (!u.usteed->mtame && u.usteed->mleashed) m_unleash(u.usteed, TRUE); if (!u.usteed->mtame || (u.ulevel+u.usteed->mtame < rnd(MAXULEV/2+5))) { + newsym(u.usteed->mx, u.usteed->my); dismount_steed(DISMOUNT_THROWN); return; } @@ -342,6 +400,45 @@ kick_steed() return; } +/* + * Try to find a dismount point adjacent to the steed's location. + * If all else fails, try enexto(). Use enexto() as a last resort because + * enexto() chooses its point randomly, possibly even outside the + * room's walls, which is not what we want. + * Adapted from mail daemon code. + */ +STATIC_OVL boolean +landing_spot(spot, forceit) +coord *spot; /* landing position (we fill it in) */ +int forceit; +{ + int x, y, distance, min_distance = -1; + boolean found = FALSE; + + for (x = u.ux-1; x <= u.ux+1; x++) + for (y = u.uy-1; y <= u.uy+1; y++) { + if (!isok(x, y) || (x == u.ux && y == u.uy)) continue; + + if (ACCESSIBLE(levl[x][y].typ) && + !MON_AT(x,y) && !closed_door(x,y)) { + distance = distu(x,y); + if (min_distance < 0 || distance < min_distance || + (distance == min_distance && rn2(2))) { + spot->x = x; + spot->y = y; + min_distance = distance; + found = TRUE; + } + } + } + + /* If we didn't find a good spot and forceit is on, try enexto(). */ + if (forceit && min_distance < 0 && + !enexto(spot, u.ux, u.uy, youmonst.data)) + return FALSE; + + return found; +} /* Stop riding the current steed */ void @@ -354,10 +451,11 @@ dismount_steed(reason) const char *verb = "fall"; boolean repair_leg_damage = TRUE; unsigned save_utrap = u.utrap; + boolean have_spot = landing_spot(&cc,0); - /* Sanity checks */ - if (!(mtmp = u.usteed)) - /* Just return silently */ + mtmp = u.usteed; /* make a copy of steed pointer */ + /* Sanity check */ + if (!mtmp) /* Just return silently */ return; /* Check the reason for dismounting */ @@ -367,17 +465,21 @@ dismount_steed(reason) verb = "are thrown"; case DISMOUNT_FELL: You("%s off of %s!", verb, mon_nam(mtmp)); + if (!have_spot) have_spot = landing_spot(&cc,1); losehp(rn1(10,10), "riding accident", KILLED_BY_AN); - HWounded_legs += rn1(5, 5); - EWounded_legs |= BOTH_SIDES; + set_wounded_legs(BOTH_SIDES, (int)HWounded_legs + rn1(5,5)); repair_leg_damage = FALSE; break; case DISMOUNT_POLY: You("can no longer ride %s.", mon_nam(u.usteed)); + if (!have_spot) have_spot = landing_spot(&cc,1); break; case DISMOUNT_ENGULFED: /* caller displays message */ break; + case DISMOUNT_BONES: + /* hero has just died... */ + break; case DISMOUNT_GENERIC: /* no messages, just make it so */ break; @@ -388,15 +490,19 @@ dismount_steed(reason) otmp->bknown = TRUE; return; } + if (!have_spot) { + You("can't. There isn't anywhere for you to stand."); + return; + } if (!mtmp->mnamelth) { pline("You've been through the dungeon on %s with no name.", - an(mtmp->data->mname)); + an(mtmp->data->mname)); if (Hallucination) pline("It felt good to get out of the rain."); } else You("dismount %s.", mon_nam(mtmp)); } - /* While riding these refer to the steed's legs + /* While riding these refer to the steed's legs * so after dismounting they refer to the player's * legs once again. */ @@ -406,10 +512,19 @@ dismount_steed(reason) u.usteed = 0; u.ugallop = 0L; - /* Set player and steed's position. Try moving the player first */ + /* Set player and steed's position. Try moving the player first + unless we're in the midst of creating a bones file. */ + if (reason == DISMOUNT_BONES) { + /* move the steed to an adjacent square */ + if (enexto(&cc, u.ux, u.uy, mtmp->data)) + rloc_to(mtmp, cc.x, cc.y); + else /* evidently no room nearby; move steed elsewhere */ + rloc(mtmp); + return; + } if (!DEADMONSTER(mtmp)) { place_monster(mtmp, u.ux, u.uy); - if (!u.uswallow && !u.ustuck && enexto(&cc, u.ux, u.uy, youmonst.data)) { + if (!u.uswallow && !u.ustuck && have_spot) { struct permonst *mdat = mtmp->data; /* The steed may drop into water/lava */ @@ -447,15 +562,19 @@ dismount_steed(reason) * able to walk onto a square with a hole, and autopickup before * falling into the hole). */ - /* Keep steed here, move the player to cc; teleds() clears u.utrap */ - in_steed_dismounting = TRUE; - teleds(cc.x, cc.y); - in_steed_dismounting = FALSE; - - /* Put your steed in your trap */ - if (save_utrap) - (void) mintrap(mtmp); - + /* [ALI] No need to move the player if the steed died. */ + if (!DEADMONSTER(mtmp)) { + /* Keep steed here, move the player to cc; + * teleds() clears u.utrap + */ + in_steed_dismounting = TRUE; + teleds(cc.x, cc.y); + in_steed_dismounting = FALSE; + + /* Put your steed in your trap */ + if (save_utrap) + (void) mintrap(mtmp); + } /* Couldn't... try placing the steed */ } else if (enexto(&cc, u.ux, u.uy, mtmp->data)) { /* Keep player here, move the steed to cc */ @@ -469,7 +588,9 @@ dismount_steed(reason) } /* Return the player to the floor */ + in_steed_dismounting = TRUE; (void) float_down(0L, W_SADDLE); + in_steed_dismounting = FALSE; flags.botl = 1; if (reason != DISMOUNT_ENGULFED) { (void)encumber_msg(); diff --git a/src/teleport.c b/src/teleport.c index 385fb4e..05e2d2a 100644 --- a/src/teleport.c +++ b/src/teleport.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)teleport.c 3.3 2000/03/03 */ +/* SCCS Id: @(#)teleport.c 3.4 2002/03/09 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -204,7 +204,19 @@ void teleds(nux, nuy) register int nux,nuy; { - if (Punished) unplacebc(); + boolean dont_teleport_ball = FALSE; + + if (Punished) { + /* If they're teleporting to a position where the ball doesn't need + * to be moved, don't place the ball. Especially useful when this + * function is being called for crawling out of water instead of + * real teleportation. + */ + if (!carried(uball) && distmin(nux, nuy, uball->ox, uball->oy) <= 2) + dont_teleport_ball = TRUE; + else + unplacebc(); + } u.utrap = 0; u.ustuck = 0; u.ux0 = u.ux; @@ -228,7 +240,20 @@ register int nux,nuy; u.uswldtim = u.uswallow = 0; docrt(); } - if (Punished) placebc(); + if (Punished) { + if (dont_teleport_ball) { + int bc_control; + xchar ballx, bally, chainx, chainy; + boolean cause_delay; + + /* this should only drag the chain (and never give a near- + capacity message) since we already checked ball distance */ + (void) drag_ball(u.ux, u.uy, &bc_control, &ballx, &bally, + &chainx, &chainy, &cause_delay); + move_bc(0, bc_control, ballx, bally, chainx, chainy); + } else + placebc(); + } initrack(); /* teleports mess up tracking monsters without this */ update_player_regions(); #ifdef STEED @@ -248,6 +273,7 @@ register int nux,nuy; see_monsters(); vision_full_recalc = 1; nomul(0); + vision_recalc(0); /* vision before effects */ spoteffects(TRUE); invocation_message(); } @@ -306,7 +332,7 @@ boolean force_it; } else { Your("leash goes slack."); release_it: - m_unleash(mtmp); + m_unleash(mtmp, FALSE); return TRUE; } } @@ -485,6 +511,7 @@ level_tele() register int newlev; d_level newlevel; const char *escape_by_flying = 0; /* when surviving dest of -N */ + char buf[BUFSZ]; if ((u.uhave.amulet || In_endgame(&u.uz) || In_sokoban(&u.uz)) #ifdef WIZARD @@ -499,7 +526,7 @@ level_tele() || wizard #endif ) { - char buf[BUFSZ], qbuf[BUFSZ]; + char qbuf[BUFSZ]; int trycnt = 0; Strcpy(qbuf, "To what level do you want to teleport?"); @@ -520,7 +547,8 @@ level_tele() if (trycnt >= 10) goto random_levtport; if (ynq("Go to Nowhere. Are you sure?") != 'y') return; - You("scream in agony as your body begins to warp..."); + You("%s in agony as your body begins to warp...", + is_silent(youmonst.data) ? "writhe" : "scream"); display_nhwindow(WIN_MESSAGE, FALSE); You("cease to exist."); killer_format = NO_KILLER_PREFIX; @@ -598,9 +626,11 @@ level_tele() } else { pline("Unfortunately, you don't know how to fly."); You("plummet a few thousand feet to your death."); + Sprintf(buf, + "teleported out of the dungeon and fell to %s death", + uhis()); + killer = buf; killer_format = NO_KILLER_PREFIX; - killer = - self_pronoun("teleported out of the dungeon and fell to %s death","his"); } } @@ -791,6 +821,7 @@ struct monst *mtmp; register int x, y; { register int oldx = mtmp->mx, oldy = mtmp->my; + boolean resident_shk = mtmp->isshk && inhishop(mtmp); if (x == mtmp->mx && y == mtmp->my) /* that was easy */ return; @@ -820,6 +851,11 @@ register int x, y; newsym(x, y); /* update new location */ set_apparxy(mtmp); /* orient monster */ + + /* shopkeepers will only teleport if you zap them with a wand of + teleportation or if they've been transformed into a jumpy monster; + the latter only happens if you've attacked them with polymorph */ + if (resident_shk && !inhishop(mtmp)) make_angry_shk(mtmp, oldx, oldy); } /* place a monster at a random location, typically due to teleport */ @@ -828,7 +864,6 @@ rloc(mtmp) struct monst *mtmp; /* mx==0 implies migrating monster arrival */ { register int x, y, trycount; - xchar omx = mtmp->mx, omy = mtmp->my; #ifdef STEED if (mtmp == u.usteed) { @@ -837,7 +872,7 @@ struct monst *mtmp; /* mx==0 implies migrating monster arrival */ } #endif - if (mtmp->iswiz && omx) { /* Wizard, not just arriving */ + if (mtmp->iswiz && mtmp->mx) { /* Wizard, not just arriving */ if (!In_W_tower(u.ux, u.uy, &u.uz)) x = xupstair, y = yupstair; else if (!xdnladder) /* bottom level of tower */ @@ -872,10 +907,6 @@ struct monst *mtmp; /* mx==0 implies migrating monster arrival */ found_xy: rloc_to(mtmp, x, y); - /* shopkeepers will only teleport if you zap them with a wand of - teleportation or if they've been transformed into a jumpy monster; - the latter only happens if you've attacked them with polymorph */ - if (mtmp->isshk && !inhishop(mtmp)) make_angry_shk(mtmp, omx, omy); } STATIC_OVL void @@ -1118,14 +1149,17 @@ boolean give_feedback; if (give_feedback) pline("%s resists your magic!", Monnam(mtmp)); return FALSE; - } else { - if (is_rider(mtmp->data) && rn2(13) && - enexto(&cc, u.ux, u.uy, mtmp->data)) - rloc_to(mtmp, cc.x, cc.y); - else - rloc(mtmp); - return TRUE; - } + } else if (level.flags.noteleport && u.uswallow && mtmp == u.ustuck) { + if (give_feedback) + You("are no longer inside %s!", mon_nam(mtmp)); + unstuck(mtmp); + rloc(mtmp); + } else if (is_rider(mtmp->data) && rn2(13) && + enexto(&cc, u.ux, u.uy, mtmp->data)) + rloc_to(mtmp, cc.x, cc.y); + else + rloc(mtmp); + return TRUE; } /*teleport.c*/ diff --git a/src/timeout.c b/src/timeout.c index cfa39ba..9a68ed8 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)timeout.c 3.3 2000/05/26 */ +/* SCCS Id: @(#)timeout.c 3.4 2000/09/28 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -12,6 +12,7 @@ STATIC_DCL void NDECL(slime_dialogue); STATIC_DCL void NDECL(slip_or_trip); STATIC_DCL void FDECL(see_lamp_flicker, (struct obj *, const char *)); STATIC_DCL void FDECL(lantern_message, (struct obj *)); +STATIC_DCL void FDECL(cleanup_burn, (genericptr_t,long)); #ifdef OVLB @@ -29,11 +30,11 @@ stoned_dialogue() { register long i = (Stoned & TIMEOUT); - if(i > 0 && i <= SIZE(stoned_texts)) + if (i > 0L && i <= SIZE(stoned_texts)) pline(stoned_texts[SIZE(stoned_texts) - i]); - if(i == 5) + if (i == 5L) HFast = 0L; - if(i == 3) + if (i == 3L) nomul(-3); exercise(A_DEX, FALSE); } @@ -120,21 +121,24 @@ slime_dialogue() { register long i = (Slimed & TIMEOUT) / 2L; - if (((Slimed & TIMEOUT) % 2L) && i >= 0 + if (((Slimed & TIMEOUT) % 2L) && i >= 0L && i < SIZE(slime_texts)) { - const char *str = slime_texts[SIZE(slime_texts)-i-1]; + const char *str = slime_texts[SIZE(slime_texts) - i - 1L]; if (index(str, '%')) { - if (i == 4) { - if (!Blind) + if (i == 4L) { /* "you are turning green" */ + if (!Blind) /* [what if you're already green?] */ pline(str, hcolor(green)); } else pline(str, an(Hallucination ? rndmonnam() : "green slime")); } else pline(str); } - if(i == 4) - HFast = 0; + if (i == 3L) { /* limbs becoming oozy */ + HFast = 0L; /* lose intrinsic speed */ + stop_occupation(); + if (multi > 0) nomul(0); + } exercise(A_DEX, FALSE); } @@ -144,6 +148,7 @@ burn_away_slime() if (Slimed) { pline_The("slime that covers you is burned away!"); Slimed = 0L; + flags.botl = 1; } return; } @@ -489,7 +494,8 @@ long timeout; if (cansee_hatchspot) { Sprintf(monnambuf, "%s%s", siblings ? "some " : "", - siblings ? makeplural(m_monnam(mon)) : a_monnam(mon)); + siblings ? + makeplural(m_monnam(mon)) : an(m_monnam(mon))); /* we don't learn the egg type here because learning an egg type requires either seeing the egg hatch or being familiar with the egg already, @@ -610,8 +616,12 @@ slip_or_trip() struct obj *otmp = vobj_at(u.ux, u.uy); const char *what, *pronoun; char buf[BUFSZ]; + boolean on_foot = TRUE; +#ifdef STEED + if (u.usteed) on_foot = FALSE; +#endif - if (otmp) { /* trip over something in particular */ + if (otmp && on_foot) { /* trip over something in particular */ /* If there is only one item, it will have just been named during the move, so refer to by via pronoun; otherwise, @@ -634,26 +644,52 @@ slip_or_trip() You("trip over %s.", what); } } else if (rn2(3) && is_ice(u.ux, u.uy)) { - You("%s on the ice.", rn2(2) ? "slip" : "slide"); - } else switch (rn2(4)) { - case 1: - You("trip over your own %s.", Hallucination ? - "elbow" : makeplural(body_part(FOOT))); - break; - case 2: - You("slip %s.", Hallucination ? - "on a banana peel" : "and nearly fall"); - break; - case 3: - You("flounder."); - break; - default: - You("stumble."); - break; - } + pline("%s %s%s on the ice.", #ifdef STEED - if (u.usteed) dismount_steed(DISMOUNT_FELL); + u.usteed ? upstart(x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + (char *)0, SUPPRESS_SADDLE, FALSE)) : #endif + "You", rn2(2) ? "slip" : "slide", on_foot ? "" : "s"); + } else { + if (on_foot) { + switch (rn2(4)) { + case 1: + You("trip over your own %s.", Hallucination ? + "elbow" : makeplural(body_part(FOOT))); + break; + case 2: + You("slip %s.", Hallucination ? + "on a banana peel" : "and nearly fall"); + break; + case 3: + You("flounder."); + break; + default: + You("stumble."); + break; + } + } +#ifdef STEED + else { + switch (rn2(4)) { + case 1: + Your("%s slip out of the stirrups.", makeplural(body_part(FOOT))); + break; + case 2: + You("let go of the reins."); + break; + case 3: + You("bang into the saddle-horn."); + break; + default: + You("slide to one side of the saddle."); + break; + } + dismount_steed(DISMOUNT_FELL); + } +#endif + } } /* Print a lamp flicker message with tailer. */ @@ -1007,7 +1043,8 @@ begin_burn(obj, already_lit) long turns = 0; boolean do_timer = TRUE; - if (obj->age == 0 && obj->otyp != MAGIC_LAMP) return; + if (obj->age == 0 && obj->otyp != MAGIC_LAMP && !artifact_light(obj)) + return; switch (obj->otyp) { case MAGIC_LAMP: @@ -1049,8 +1086,15 @@ begin_burn(obj, already_lit) break; default: - impossible("begin burn: unexpected %s", xname(obj)); - turns = obj->age; + /* [ALI] Support artifact light sources */ + if (artifact_light(obj)) { + obj->lamplit = 1; + do_timer = FALSE; + radius = 2; + } else { + impossible("begin burn: unexpected %s", xname(obj)); + turns = obj->age; + } break; } @@ -1059,11 +1103,14 @@ begin_burn(obj, already_lit) BURN_OBJECT, (genericptr_t)obj)) { obj->lamplit = 1; obj->age -= turns; - if (obj->where == OBJ_INVENT && !already_lit) + if (carried(obj) && !already_lit) update_inventory(); } else { obj->lamplit = 0; } + } else { + if (carried(obj) && !already_lit) + update_inventory(); } if (obj->lamplit && !already_lit) { @@ -1085,30 +1132,55 @@ end_burn(obj, timer_attached) struct obj *obj; boolean timer_attached; { - long expire_time; - if (!obj->lamplit) { impossible("end_burn: obj %s not lit", xname(obj)); return; } - del_light_source(LS_OBJECT, (genericptr_t) obj); + if (obj->otyp == MAGIC_LAMP || artifact_light(obj)) + timer_attached = FALSE; + + if (!timer_attached) { + /* [DS] Cleanup explicitly, since timer cleanup won't happen */ + del_light_source(LS_OBJECT, (genericptr_t)obj); + obj->lamplit = 0; + if (obj->where == OBJ_INVENT) + update_inventory(); + } else if (!stop_timer(BURN_OBJECT, (genericptr_t) obj)) + impossible("end_burn: obj %s not timed!", xname(obj)); +} - if (obj->otyp == MAGIC_LAMP) timer_attached = FALSE; - if (timer_attached) { - expire_time = stop_timer(BURN_OBJECT, (genericptr_t) obj); - if (expire_time) - /* restore unused time */ - obj->age += expire_time - monstermoves; - else - impossible("end_burn: obj %s not timed!", xname(obj)); - } - obj->lamplit = 0; +#endif /* OVL1 */ +#ifdef OVL0 + +/* + * Cleanup a burning object if timer stopped. + */ +static void +cleanup_burn(arg, expire_time) + genericptr_t arg; + long expire_time; +{ + struct obj *obj = (struct obj *)arg; + if (!obj->lamplit) { + impossible("cleanup_burn: obj %s not lit", xname(obj)); + return; + } + + del_light_source(LS_OBJECT, arg); + + /* restore unused time */ + obj->age += expire_time - monstermoves; + + obj->lamplit = 0; - if (obj->where == OBJ_INVENT) - update_inventory(); + if (obj->where == OBJ_INVENT) + update_inventory(); } +#endif /* OVL0 */ +#ifdef OVL1 + void do_storms() { @@ -1205,17 +1277,6 @@ do_storms() * Stop all timers attached to obj. */ - -typedef struct fe { - struct fe *next; /* next item in chain */ - long timeout; /* when we time out */ - unsigned long tid; /* timer ID */ - short kind; /* kind of use */ - short func_index; /* what to call when we time out */ - genericptr_t arg; /* pointer to timeout argument */ - Bitfield (needs_fixup,1); /* does arg need to be patched? */ -} timer_element; - #ifdef WIZARD STATIC_DCL const char *FDECL(kind_name, (SHORT_P)); STATIC_DCL void FDECL(print_queue, (winid, timer_element *)); @@ -1223,6 +1284,7 @@ STATIC_DCL void FDECL(print_queue, (winid, timer_element *)); STATIC_DCL void FDECL(insert_timer, (timer_element *)); STATIC_DCL timer_element *FDECL(remove_timer, (timer_element **, SHORT_P, genericptr_t)); +STATIC_DCL void FDECL(write_timer, (int, timer_element *)); STATIC_DCL boolean FDECL(mon_is_local, (struct monst *)); STATIC_DCL boolean FDECL(timer_is_local, (timer_element *)); STATIC_DCL int FDECL(maybe_write_timer, (int, int, BOOLEAN_P)); @@ -1235,23 +1297,23 @@ static unsigned long timer_id = 1; #define VERBOSE_TIMER typedef struct { - timeout_proc f; + timeout_proc f, cleanup; #ifdef VERBOSE_TIMER const char *name; -# define TTAB(a, b) {a,b} +# define TTAB(a, b, c) {a,b,c} #else -# define TTAB(a, b) {a} +# define TTAB(a, b, c) {a,b} #endif } ttable; /* table of timeout functions */ static ttable timeout_funcs[NUM_TIME_FUNCS] = { - TTAB(rot_organic, "rot_organic"), - TTAB(rot_corpse, "rot_corpse"), - TTAB(revive_mon, "revive_mon"), - TTAB(burn_object, "burn_object"), - TTAB(hatch_egg, "hatch_egg"), - TTAB(fig_transform, "fig_transform") + TTAB(rot_organic, (timeout_proc)0, "rot_organic"), + TTAB(rot_corpse, (timeout_proc)0, "rot_corpse"), + TTAB(revive_mon, (timeout_proc)0, "revive_mon"), + TTAB(burn_object, cleanup_burn, "burn_object"), + TTAB(hatch_egg, (timeout_proc)0, "hatch_egg"), + TTAB(fig_transform, (timeout_proc)0, "fig_transform") }; #undef TTAB @@ -1418,6 +1480,8 @@ genericptr_t arg; timeout = doomed->timeout; if (doomed->kind == TIMER_OBJECT) ((struct obj *)arg)->timed--; + if (timeout_funcs[doomed->func_index].cleanup) + (*timeout_funcs[doomed->func_index].cleanup)(arg, timeout); free((genericptr_t) doomed); return timeout; } @@ -1483,6 +1547,9 @@ obj_stop_timers(obj) prev->next = curr->next; else timer_base = curr->next; + if (timeout_funcs[curr->func_index].cleanup) + (*timeout_funcs[curr->func_index].cleanup)(curr->arg, + curr->timeout); free((genericptr_t) curr); } else { prev = curr; diff --git a/src/topten.c b/src/topten.c index 41b39dc..a2f6e52 100644 --- a/src/topten.c +++ b/src/topten.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)topten.c 3.3 2000/01/21 */ +/* SCCS Id: @(#)topten.c 3.4 2000/01/21 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -31,7 +31,7 @@ static long final_fpos; #define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry)) #define dealloc_ttentry(ttent) free((genericptr_t) (ttent)) #define NAMSZ 10 -#define DTHSZ 60 +#define DTHSZ 100 #define ROLESZ 3 #define PERSMAX 3 /* entries per name/uid per char. allowed */ #define POINTSMIN 1 /* must be > 0 */ @@ -79,7 +79,7 @@ STATIC_DCL void FDECL(nsb_unmung_line,(char*)); NEARDATA const char *killed_by_prefix[] = { "killed by ", "choked on ", "poisoned by ", "", "drowned in ", "", "dissolved in ", "crushed to death by ", "petrified by ", - "turned to slime by ", "", "", "", "", "", "" + "turned to slime by ", "killed by ", "", "", "", "", "" }; static winid toptenwin = WIN_ERR; @@ -264,6 +264,13 @@ int how; return; #endif +/* If we are in the midst of a panic, cut out topten entirely. + * topten uses alloc() several times, which will lead to + * problems if the panic was the result of an alloc() failure. + */ + if (program_state.panicking) + return; + if (flags.toptenwin) { toptenwin = create_nhwindow(NHW_TEXT); } @@ -707,7 +714,16 @@ int uid; #endif for (i = 0; i < playerct; i++) { - if (strcmp(players[i], "all") == 0 || + if (players[i][0] == '-' && index("pr", players[i][1]) && + players[i][2] == 0 && i + 1 < playerct) { + char *arg = (char *)players[i + 1]; + if ((players[i][1] == 'p' && + str2role(arg) == str2role(t1->plrole)) || + (players[i][1] == 'r' && + str2race(arg) == str2race(t1->plrace))) + return 1; + i++; + } else if (strcmp(players[i], "all") == 0 || strncmp(t1->name, players[i], NAMSZ) == 0 || (players[i][0] == '-' && players[i][1] == t1->plrole[0] && @@ -841,18 +857,28 @@ char **argv; if (playerct > 1) Strcat(pbuf, "any of "); for (i = 0; i < playerct; i++) { Strcat(pbuf, players[i]); - if (i < playerct-1) Strcat(pbuf, ":"); + if (i < playerct-1) { + if (players[i][0] == '-' && + index("pr", players[i][1]) && players[i][2] == 0) + Strcat(pbuf, " "); + else Strcat(pbuf, ":"); + } } } raw_print(pbuf); - raw_printf("Call is: %s -s [-v] [-role] [maxrank] [playernames]", + raw_printf("Usage: %s -s [-v] [maxrank] [playernames]", + hname); + raw_printf("Player types are: [-p role] [-r race]"); } free_ttlist(tt_head); #ifdef AMIGA - display_nhwindow(amii_rawprwin, 1); - destroy_nhwindow(amii_rawprwin); - amii_rawprwin = WIN_ERR; + { + extern winid amii_rawprwin; + display_nhwindow(amii_rawprwin, 1); + destroy_nhwindow(amii_rawprwin); + amii_rawprwin = WIN_ERR; + } #endif } diff --git a/src/track.c b/src/track.c index 2200590..d8d9e71 100644 --- a/src/track.c +++ b/src/track.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)track.c 3.3 87/08/08 */ +/* SCCS Id: @(#)track.c 3.4 87/08/08 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ /* track.c - version 1.0.2 */ diff --git a/src/trap.c b/src/trap.c index 4f1be02..82d0745 100644 --- a/src/trap.c +++ b/src/trap.c @@ -1,9 +1,11 @@ -/* SCCS Id: @(#)trap.c 3.3 2000/07/07 */ +/* SCCS Id: @(#)trap.c 3.4 2001/09/06 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" +extern const char *destroy_strings[]; + STATIC_DCL void FDECL(dofiretrap, (struct obj *)); STATIC_DCL void NDECL(domagictrap); STATIC_DCL boolean FDECL(emergency_disrobe,(boolean *)); @@ -12,7 +14,7 @@ STATIC_DCL void FDECL(cnv_trap_obj, (int, int, struct trap *)); STATIC_DCL void FDECL(move_into_trap, (struct trap *)); STATIC_DCL int FDECL(try_disarm, (struct trap *,BOOLEAN_P)); STATIC_DCL void FDECL(reward_untrap, (struct trap *, struct monst *)); -STATIC_DCL int FDECL(disarm_beartrap, (struct trap *)); +STATIC_DCL int FDECL(disarm_holdingtrap, (struct trap *)); STATIC_DCL int FDECL(disarm_landmine, (struct trap *)); STATIC_DCL int FDECL(disarm_squeaky_board, (struct trap *)); STATIC_DCL int FDECL(disarm_shooting_trap, (struct trap *, int)); @@ -22,7 +24,9 @@ STATIC_DCL boolean FDECL(thitm, (int, struct monst *, struct obj *, int)); STATIC_DCL int FDECL(mkroll_launch, (struct trap *,XCHAR_P,XCHAR_P,SHORT_P,long)); STATIC_DCL boolean FDECL(isclearpath,(coord *, int, SCHAR_P, SCHAR_P)); -STATIC_DCL void FDECL(blow_up_landmine, (struct trap *)); +#ifdef STEED +STATIC_OVL int FDECL(steedintrap, (struct trap *, struct obj *)); +#endif #ifndef OVLB STATIC_VAR const char *a_your[2]; @@ -67,7 +71,7 @@ struct monst *victim; case 1: item = (victim == &youmonst) ? uarmc : which_armor(victim, W_ARMC); if (item) { - (void) burn_dmg(item, "cloak"); + (void) burn_dmg(item, cloak_simple_name(item)); return TRUE; } item = (victim == &youmonst) ? uarm : which_armor(victim, W_ARM); @@ -116,7 +120,6 @@ struct monst *victim; static NEARDATA const char *action[] = { "smoulder", "rust", "rot", "corrode" }; static NEARDATA const char *msg[] = { "burnt", "rusted", "rotten", "corroded" }; boolean vulnerable = FALSE; - boolean plural; boolean grprot = FALSE; boolean is_primary = TRUE; boolean vismon = (victim != &youmonst) && canseemon(victim); @@ -142,76 +145,73 @@ struct monst *victim; if (!print && (!vulnerable || otmp->oerodeproof || erosion == MAX_ERODE)) return FALSE; - plural = (is_gloves(otmp) || is_boots(otmp)) && - !strstri(ostr, "pair of "); /* "pair of *s" is singular */ - if (!vulnerable) { if (flags.verbose) { if (victim == &youmonst) - Your("%s %s not affected.", ostr, plural ? "are" : "is"); + Your("%s %s not affected.", ostr, vtense(ostr, "are")); else if (vismon) pline("%s's %s %s not affected.", Monnam(victim), ostr, - plural ? "are" : "is"); + vtense(ostr, "are")); } } else if (erosion < MAX_ERODE) { if (grprot && otmp->greased) { - grease_protect(otmp,ostr,plural,victim); + grease_protect(otmp,ostr,victim); } else if (otmp->oerodeproof || (otmp->blessed && !rnl(4))) { if (flags.verbose) { if (victim == &youmonst) pline("Somehow, your %s %s not affected.", - ostr, plural ? "are" : "is"); + ostr, vtense(ostr, "are")); else if (vismon) pline("Somehow, %s's %s %s not affected.", - mon_nam(victim), ostr, plural ? "are" : "is"); + mon_nam(victim), ostr, vtense(ostr, "are")); } } else { if (victim == &youmonst) - Your("%s %s%s%s!", ostr, action[type], - plural ? "" : "s", - erosion+1 == MAX_ERODE ? " completely" : - erosion ? " further" : ""); + Your("%s %s%s!", ostr, + vtense(ostr, action[type]), + erosion+1 == MAX_ERODE ? " completely" : + erosion ? " further" : ""); else if (vismon) - pline("%s's %s %s%s%s!", Monnam(victim), ostr, action[type], - plural ? "" : "s", + pline("%s's %s %s%s!", Monnam(victim), ostr, + vtense(ostr, action[type]), erosion+1 == MAX_ERODE ? " completely" : - erosion ? " further" : ""); + erosion ? " further" : ""); if (is_primary) otmp->oeroded++; else otmp->oeroded2++; + update_inventory(); } } else { if (flags.verbose) { if (victim == &youmonst) - Your("%s %s%s completely %s.", ostr, - Blind ? "feel" : "look", - plural ? "" : "s", msg[type]); + Your("%s %s completely %s.", ostr, + vtense(ostr, Blind ? "feel" : "look"), + msg[type]); else if (vismon) - pline("%s's %s look%s completely %s.", - Monnam(victim), ostr, - plural ? "" : "s", msg[type]); + pline("%s's %s %s completely %s.", + Monnam(victim), ostr, + vtense(ostr, "look"), msg[type]); } } return(TRUE); } void -grease_protect(otmp,ostr,plu,victim) +grease_protect(otmp,ostr,victim) register struct obj *otmp; register const char *ostr; -register boolean plu; struct monst *victim; { static const char txt[] = "protected by the layer of grease!"; - boolean vismon = (victim != &youmonst) && canseemon(victim); + boolean vismon = victim && (victim != &youmonst) && canseemon(victim); if (ostr) { if (victim == &youmonst) - Your("%s %s %s",ostr,plu ? "are" : "is", txt); + Your("%s %s %s", ostr, vtense(ostr, "are"), txt); else if (vismon) pline("%s's %s %s %s", Monnam(victim), - ostr, plu ? "are" : "is", txt); + ostr, vtense(ostr, "are"), txt); } else { if (victim == &youmonst) Your("%s %s",aobjnam(otmp,"are"), txt); @@ -219,9 +219,11 @@ struct monst *victim; pline("%s's %s %s", Monnam(victim), aobjnam(otmp,"are"), txt); } if (!rn2(2)) { - pline_The("grease dissolves."); otmp->greased = 0; - update_inventory(); + if (carried(otmp)) { + pline_The("grease dissolves."); + update_inventory(); + } } } @@ -263,8 +265,9 @@ register int x, y, typ; otmp = mtmp->minvent; otmp->owornmask = 0; obj_extract_self(otmp); - add_to_container(statue, otmp); + (void) add_to_container(statue, otmp); } + statue->owt = weight(statue); mongone(mtmp); break; } @@ -490,12 +493,14 @@ boolean shatter; } void -dotrap(trap) +dotrap(trap, trflags) register struct trap *trap; +unsigned trflags; { register int ttype = trap->ttyp; register struct obj *otmp; boolean already_seen = trap->tseen; + boolean webmsgok = (!(trflags & NOWEBMSG)); nomul(0); @@ -540,6 +545,11 @@ register struct trap *trap; otmp = mksobj(ARROW, TRUE, FALSE); otmp->quan = 1L; otmp->owt = weight(otmp); + otmp->opoisoned = 0; +#ifdef STEED + if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) /* nothing */; + else +#endif if (thitu(8, dmgval(otmp, &youmonst), otmp, "arrow")) { obfree(otmp, (struct obj *)0); } else { @@ -556,6 +566,10 @@ register struct trap *trap; otmp->quan = 1L; otmp->owt = weight(otmp); if (!rn2(6)) otmp->opoisoned = 1; +#ifdef STEED + if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) /* nothing */; + else +#endif if (thitu(7, dmgval(otmp, &youmonst), otmp, "little dart")) { if (otmp->opoisoned) poisoned("dart",A_CON,"poison dart",10); @@ -572,7 +586,7 @@ register struct trap *trap; int dmg = d(2,6); /* should be std ROCK dmg? */ seetrap(trap); - otmp = mksobj_at(ROCK, u.ux, u.uy, TRUE); + otmp = mksobj_at(ROCK, u.ux, u.uy, TRUE, FALSE); otmp->quan = 1L; otmp->owt = weight(otmp); @@ -623,7 +637,11 @@ register struct trap *trap; A_Your[trap->madeby_u]); break; } - if(youmonst.data->msize <= MZ_SMALL) { + if( +#ifdef STEED + !u.usteed && +#endif + youmonst.data->msize <= MZ_SMALL) { pline("%s bear trap closes harmlessly over you.", A_Your[trap->madeby_u]); break; @@ -634,7 +652,7 @@ register struct trap *trap; if (u.usteed) { pline("%s bear trap closes on %s %s!", A_Your[trap->madeby_u], s_suffix(mon_nam(u.usteed)), - body_part(FOOT)); + mbodypart(u.usteed, FOOT)); } else #endif { @@ -648,7 +666,7 @@ register struct trap *trap; case SLP_GAS_TRAP: seetrap(trap); - if(Sleep_resistance) { + if(Sleep_resistance || breathless(youmonst.data)) { You("are enveloped in a cloud of gas!"); break; } @@ -656,6 +674,9 @@ register struct trap *trap; flags.soundok = 0; fall_asleep(-rnd(25), TRUE); afternmv = Hear_again; +#ifdef STEED + (void) steedintrap(trap, (struct obj *)0); +#endif break; case RUST_TRAP: @@ -688,7 +709,7 @@ register struct trap *trap; if (rust_dmg(uarms, "shield", 1, TRUE, &youmonst)) break; if (u.twoweap || (uwep && bimanual(uwep))) - erode_weapon(u.twoweap ? uswapwep : uwep, FALSE); + erode_obj(u.twoweap ? uswapwep : uwep, FALSE, TRUE); glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); /* Not "metal gauntlets" since it gets called * even if it's leather for the message @@ -697,14 +718,15 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); case 2: pline("%s your right %s!", A_gush_of_water_hits, body_part(ARM)); - erode_weapon(uwep, FALSE); + erode_obj(uwep, FALSE, TRUE); goto glovecheck; default: pline("%s you!", A_gush_of_water_hits); for (otmp=invent; otmp; otmp = otmp->nobj) (void) snuff_lit(otmp); if (uarmc) - (void) rust_dmg(uarmc, "cloak", 1, TRUE, &youmonst); + (void) rust_dmg(uarmc, cloak_simple_name(uarmc), + 1, TRUE, &youmonst); else if (uarm) (void) rust_dmg(uarm, "armor", 1, TRUE, &youmonst); #ifdef TOURIST @@ -712,6 +734,7 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); (void) rust_dmg(uarmu, "shirt", 1, TRUE, &youmonst); #endif } + update_inventory(); break; case FIRE_TRAP: @@ -724,7 +747,7 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); /* KMH -- You can't escape the Sokoban level traps */ if (!In_sokoban(&u.uz) && (Levitation || Flying)) break; seetrap(trap); - if (is_clinger(youmonst.data)) { + if (!In_sokoban(&u.uz) && is_clinger(youmonst.data)) { if(trap->tseen) { You("see %s %spit below you.", a_your[trap->madeby_u], ttype == SPIKED_PIT ? "spiked " : ""); @@ -736,8 +759,19 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); } break; } - if (!In_sokoban(&u.uz)) - You("fall into %s pit!", a_your[trap->madeby_u]); + if (!In_sokoban(&u.uz)) { + char verbbuf[BUFSZ]; +#ifdef STEED + if (u.usteed) + Sprintf(verbbuf,"lead %s", + x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + "poor", SUPPRESS_SADDLE, FALSE)); + else +#endif + Strcpy(verbbuf,"fall"); + You("%s into %s pit!", verbbuf, a_your[trap->madeby_u]); + } /* wumpus reference */ if (Role_if(PM_RANGER) && !trap->madeby_u && !trap->once && In_quest(&u.uz) && Is_qlocate(&u.uz)) { @@ -746,11 +780,24 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); } else if (u.umonnum == PM_PIT_VIPER || u.umonnum == PM_PIT_FIEND) pline("How pitiful. Isn't that the pits?"); - if (ttype == SPIKED_PIT) - You("land on a set of sharp iron spikes!"); + if (ttype == SPIKED_PIT) { + char *predicament = "on a set of sharp iron spikes"; +#ifdef STEED + if (u.usteed) { + pline("%s lands %s!", + upstart(x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + "poor", SUPPRESS_SADDLE, FALSE)), predicament); + } else +#endif + You("land %s!", predicament); + } if (!Passes_walls) u.utrap = rn1(6,2); u.utraptype = TT_PIT; +#ifdef STEED + if (!steedintrap(trap, (struct obj *)0)) { +#endif if (ttype == SPIKED_PIT) { losehp(rnd(10),"fell into a pit of iron spikes", NO_KILLER_PREFIX); @@ -767,6 +814,9 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); vision_full_recalc = 1; /* vision limits change */ exercise(A_STR, FALSE); exercise(A_DEX, FALSE); +#ifdef STEED + } +#endif break; case HOLE: case TRAPDOOR: @@ -794,26 +844,40 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); unsolid(youmonst.data)) { if (acidic(youmonst.data) || u.umonnum == PM_GELATINOUS_CUBE || u.umonnum == PM_FIRE_ELEMENTAL) { - You("%s %s spider web!", - (u.umonnum == PM_FIRE_ELEMENTAL) ? "burn" : "dissolve", - a_your[trap->madeby_u]); + if (webmsgok) + You("%s %s spider web!", + (u.umonnum == PM_FIRE_ELEMENTAL) ? "burn" : "dissolve", + a_your[trap->madeby_u]); deltrap(trap); newsym(u.ux,u.uy); break; } - You("flow through %s spider web.", + if (webmsgok) You("flow through %s spider web.", a_your[trap->madeby_u]); break; } if (webmaker(youmonst.data)) { - pline(trap->madeby_u ? "You take a walk on your web." + if (webmsgok) + pline(trap->madeby_u ? "You take a walk on your web." : "There is a spider web here."); break; } - You("%s into %s spider web!", - Levitation ? (const char *)"float" : - locomotion(youmonst.data, "stumble"), - a_your[trap->madeby_u]); + if (webmsgok) { + char verbbuf[BUFSZ]; + verbbuf[0] = '\0'; +#ifdef STEED + if (u.usteed) + Sprintf(verbbuf,"lead %s", + x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + "poor", SUPPRESS_SADDLE, FALSE)); + else +#endif + + Sprintf(verbbuf, "%s", Levitation ? (const char *)"float" : + locomotion(youmonst.data, "stumble")); + You("%s into %s spider web!", verbbuf, a_your[trap->madeby_u]); + } u.utraptype = TT_WEB; /* Time stuck in the web depends on your strength. */ @@ -829,7 +893,8 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); else if (str < 69) u.utrap = 1; else { u.utrap = 0; - You("tear through %s web!", a_your[trap->madeby_u]); + if (webmsgok) + You("tear through %s web!", a_your[trap->madeby_u]); deltrap(trap); newsym(u.ux,u.uy); /* get rid of trap symbol */ } @@ -850,6 +915,9 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); Your("body absorbs some of the magical energy!"); u.uen = (u.uenmax += 2); } else domagictrap(); +#ifdef STEED + (void) steedintrap(trap, (struct obj *)0); +#endif break; case ANTI_MAGIC: @@ -860,23 +928,36 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); } else drain_en(rnd(u.ulevel) + 1); break; - case POLY_TRAP: + case POLY_TRAP: { + char verbbuf[BUFSZ]; seetrap(trap); - You("%s onto a polymorph trap!", +#ifdef STEED + if (u.usteed) + Sprintf(verbbuf, "lead %s", + x_monnam(u.usteed, + u.usteed->mnamelth ? ARTICLE_NONE : ARTICLE_THE, + (char *)0, SUPPRESS_SADDLE, FALSE)); + else +#endif + Sprintf(verbbuf,"%s", Levitation ? (const char *)"float" : locomotion(youmonst.data, "step")); + You("%s onto a polymorph trap!", verbbuf); if(Antimagic || Unchanging) { shieldeff(u.ux, u.uy); You_feel("momentarily different."); /* Trap did nothing; don't remove it --KAA */ } else { +#ifdef STEED + (void) steedintrap(trap, (struct obj *)0); +#endif deltrap(trap); /* delete trap before polymorph */ newsym(u.ux,u.uy); /* get rid of trap symbol */ You_feel("a change coming over you."); - polyself(); + polyself(FALSE); } break; - + } case LANDMINE: if (Levitation || Flying) { if (!already_seen && rn2(3)) break; @@ -890,9 +971,23 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); already_seen ? a_your[trap->madeby_u] : "", already_seen ? " land mine" : "it"); } else { +#ifdef STEED + /* prevent landmine from killing steed, throwing you to + * the ground, and you being affected again by the same + * mine because it hasn't been deleted yet + */ + static boolean recursive_mine = FALSE; + + if (recursive_mine) break; +#endif seetrap(trap); pline("KAABLAMM!!! You triggered %s land mine!", a_your[trap->madeby_u]); +#ifdef STEED + recursive_mine = TRUE; + (void) steedintrap(trap, (struct obj *)0); + recursive_mine = FALSE; +#endif set_wounded_legs(LEFT_SIDE, rn1(35, 41)); set_wounded_legs(RIGHT_SIDE, rn1(35, 41)); exercise(A_DEX, FALSE); @@ -901,7 +996,8 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); newsym(u.ux,u.uy); /* update trap symbol */ losehp(rnd(16), "land mine", KILLED_BY_AN); /* fall recursively into the pit... */ - if ((trap = t_at(u.ux, u.uy)) != 0) dotrap(trap); + if ((trap = t_at(u.ux, u.uy)) != 0) dotrap(trap, 0); + fill_pit(u.ux, u.uy); break; case ROLLING_BOULDER_TRAP: @@ -926,8 +1022,99 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst); } } +#ifdef STEED +STATIC_OVL int +steedintrap(trap, otmp) +struct trap *trap; +struct obj *otmp; +{ + struct monst *mtmp = u.usteed; + struct permonst *mptr; + int tt; + boolean in_sight; + boolean trapkilled = FALSE; + boolean steedhit = FALSE; + + if (!u.usteed || !trap) return 0; + mptr = mtmp->data; + tt = trap->ttyp; + mtmp->mx = u.ux; + mtmp->my = u.uy; + + in_sight = !Blind; + switch (tt) { + case ARROW_TRAP: + if(!otmp) { + impossible("steed hit by non-existant arrow?"); + return 0; + } + if(thitm(8, mtmp, otmp, 0)) trapkilled = TRUE; + steedhit = TRUE; + break; + case DART_TRAP: + if(!otmp) { + impossible("steed hit by non-existant dart?"); + return 0; + } + if(thitm(7, mtmp, otmp, 0)) trapkilled = TRUE; + steedhit = TRUE; + break; + case SLP_GAS_TRAP: + if (!resists_sleep(mtmp) && !breathless(mptr) && + !mtmp->msleeping && mtmp->mcanmove) { + mtmp->mcanmove = 0; + mtmp->mfrozen = rnd(25); + if (in_sight) { + pline("%s suddenly falls asleep!", + Monnam(mtmp)); + } + } + steedhit = TRUE; + break; + case LANDMINE: + if (thitm(0, mtmp, (struct obj *)0, rnd(16))) + trapkilled = TRUE; + steedhit = TRUE; + break; + case PIT: + case SPIKED_PIT: + if (mtmp->mhp <= 0 || + thitm(0, mtmp, (struct obj *)0, + rnd((tt == PIT) ? 6 : 10))) + trapkilled = TRUE; + steedhit = TRUE; + break; + case POLY_TRAP: + if (!resists_magm(mtmp)) { + if (!resist(mtmp, WAND_CLASS, 0, NOTELL)) { + (void) newcham(mtmp, (struct permonst *)0, FALSE); + if (!can_saddle(mtmp) || !can_ride(mtmp)) { + dismount_steed(DISMOUNT_POLY); + } else { + You("have to adjust yourself in the saddle on %s.", + x_monnam(mtmp, + mtmp->mnamelth ? ARTICLE_NONE : ARTICLE_A, + (char *)0, SUPPRESS_SADDLE, FALSE)); + } + + } + steedhit = TRUE; + break; + default: + return 0; + } + } + if(trapkilled) { + dismount_steed(DISMOUNT_POLY); + return 2; + } + else if(steedhit) return 1; + else return 0; +} +#endif /*STEED*/ + /* some actions common to both player and monsters for triggered landmine */ -STATIC_OVL void +void blow_up_landmine(trap) struct trap *trap; { @@ -938,8 +1125,8 @@ struct trap *trap; wake_nearto(trap->tx, trap->ty, 400); if (IS_DOOR(levl[trap->tx][trap->ty].typ)) levl[trap->tx][trap->ty].doormask = D_BROKEN; - /* TODO: destroy drawbridge if present; - sometimes delete trap instead of always leaving a pit */ + /* TODO: destroy drawbridge if present */ + /* caller may subsequently fill pit, e.g. with a boulder */ trap->ttyp = PIT; /* explosion creates a pit */ trap->madeby_u = FALSE; /* resulting pit isn't yours */ } @@ -961,7 +1148,7 @@ register int x1,y1,x2,y2; int style; { register struct monst *mtmp; - register struct obj *otmp; + register struct obj *otmp, *otmp2; register int dx,dy; struct obj *singleobj; boolean used_up = FALSE; @@ -990,7 +1177,7 @@ int style; singleobj = otmp; otmp = (struct obj *) 0; } else { - singleobj = splitobj(otmp, otmp->quan - 1L); + singleobj = splitobj(otmp, 1L); obj_extract_self(singleobj); } newsym(x1,y1); @@ -1019,6 +1206,7 @@ int style; /* Set the object in motion */ while(dist-- > 0 && !used_up) { + struct trap *t; tmp_at(bhitpos.x, bhitpos.y); tmp = delaycnt; @@ -1028,7 +1216,8 @@ int style; bhitpos.x += dx; bhitpos.y += dy; - + t = t_at(bhitpos.x, bhitpos.y); + if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) { if (otyp == BOULDER && throws_rocks(mtmp->data)) { if (rn2(3)) { @@ -1058,15 +1247,74 @@ int style; break; } } + if (t && otyp == BOULDER) { + switch(t->ttyp) { + case LANDMINE: + if (rn2(10) > 2) { + pline( + "KAABLAMM!!!%s", + cansee(bhitpos.x, bhitpos.y) ? + " The rolling boulder triggers a land mine." : ""); + deltrap(t); + del_engr_at(bhitpos.x,bhitpos.y); + place_object(singleobj, bhitpos.x, bhitpos.y); + fracture_rock(singleobj); + scatter(bhitpos.x,bhitpos.y, 4, + MAY_DESTROY|MAY_HIT|MAY_FRACTURE|VIS_EFFECTS, + (struct obj *)0); + if (cansee(bhitpos.x,bhitpos.y)) + newsym(bhitpos.x,bhitpos.y); + used_up = TRUE; + } + break; + case LEVEL_TELEP: + case TELEP_TRAP: + if (cansee(bhitpos.x, bhitpos.y)) + pline("Suddenly the rolling boulder disappears!"); + else + You_hear("a rumbling stop abruptly."); + if (t->ttyp == TELEP_TRAP) + rloco(singleobj); + else { + int newlev = random_teleport_level(); + d_level dest; + + if (newlev == depth(&u.uz) || In_endgame(&u.uz)) + continue; + add_to_migration(singleobj); + get_level(&dest, newlev); + singleobj->ox = dest.dnum; + singleobj->oy = dest.dlevel; + singleobj->owornmask = (long)MIGR_RANDOM; + } + seetrap(t); + used_up = TRUE; + break; + } + if (used_up) break; + } if (flooreffects(singleobj, bhitpos.x, bhitpos.y, "fall")) { used_up = TRUE; break; } + if (otyp == BOULDER && + (otmp2 = sobj_at(BOULDER, bhitpos.x, bhitpos.y)) != 0) { + char *bmsg = + " as one boulder sets another in motion"; + You_hear("a loud crash%s!", + cansee(bhitpos.x, bhitpos.y) ? bmsg : ""); + obj_extract_self(otmp2); + place_object(singleobj, bhitpos.x, bhitpos.y); + singleobj = otmp2; + otmp2 = (struct obj *)0; + wake_nearto(bhitpos.x, bhitpos.y, 10*10); + } } if (otyp == BOULDER && closed_door(bhitpos.x,bhitpos.y)) { if (cansee(bhitpos.x, bhitpos.y)) pline_The("boulder crashes through a door."); levl[bhitpos.x][bhitpos.y].doormask = D_BROKEN; + if (dist) unblock_point(bhitpos.x, bhitpos.y); } } tmp_at(DISP_END, 0); @@ -1192,6 +1440,17 @@ register struct monst *mtmp; if (!trap) { mtmp->mtrapped = 0; /* perhaps teleported? */ } else if (mtmp->mtrapped) { /* is currently in the trap */ + if (!trap->tseen && + cansee(mtmp->mx, mtmp->my) && canseemon(mtmp) && + (trap->ttyp == SPIKED_PIT || trap->ttyp == BEAR_TRAP || + trap->ttyp == HOLE || trap->ttyp == PIT || + trap->ttyp == WEB)) { + /* If you come upon an obviously trapped monster, then + * you must be able to see the trap it's in too. + */ + seetrap(trap); + } + if (!rn2(40)) { if (sobj_at(BOULDER, mtmp->mx, mtmp->my) && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT)) { @@ -1246,6 +1505,7 @@ register struct monst *mtmp; otmp = mksobj(ARROW, TRUE, FALSE); otmp->quan = 1L; otmp->owt = weight(otmp); + otmp->opoisoned = 0; if (in_sight) seetrap(trap); if(thitm(8, mtmp, otmp, 0)) trapkilled = TRUE; break; @@ -1297,7 +1557,7 @@ register struct monst *mtmp; break; case SLP_GAS_TRAP: - if (!resists_sleep(mtmp) && + if (!resists_sleep(mtmp) && !breathless(mptr) && !mtmp->msleeping && mtmp->mcanmove) { mtmp->mcanmove = 0; mtmp->mfrozen = rnd(25); @@ -1332,7 +1592,7 @@ register struct monst *mtmp; break; target = MON_WEP(mtmp); if (target && bimanual(target)) - erode_weapon(target, FALSE); + erode_obj(target, FALSE, TRUE); glovecheck: target = which_armor(mtmp, W_ARMG); (void) rust_dmg(target, "gauntlets", 1, TRUE, mtmp); break; @@ -1340,7 +1600,7 @@ glovecheck: target = which_armor(mtmp, W_ARMG); if (in_sight) pline("%s %s's right %s!", A_gush_of_water_hits, mon_nam(mtmp), mbodypart(mtmp, ARM)); - erode_weapon(MON_WEP(mtmp), FALSE); + erode_obj(MON_WEP(mtmp), FALSE, TRUE); goto glovecheck; default: if (in_sight) @@ -1350,7 +1610,8 @@ glovecheck: target = which_armor(mtmp, W_ARMG); (void) snuff_lit(otmp); target = which_armor(mtmp, W_ARMC); if (target) - (void) rust_dmg(target, "cloak", 1, TRUE, mtmp); + (void) rust_dmg(target, cloak_simple_name(target), + 1, TRUE, mtmp); else { target = which_armor(mtmp, W_ARM); if (target) @@ -1408,7 +1669,7 @@ glovecheck: target = which_armor(mtmp, W_ARMG); (void) destroy_mitem(mtmp, SPBOOK_CLASS, AD_FIRE); (void) destroy_mitem(mtmp, POTION_CLASS, AD_FIRE); } - if (burn_floor_paper(mtmp->mx, mtmp->my, see_it) && + if (burn_floor_paper(mtmp->mx, mtmp->my, see_it, FALSE) && !see_it && distu(mtmp->mx, mtmp->my) <= 3*3) You("smell smoke."); if (is_ice(mtmp->mx,mtmp->my)) @@ -1431,10 +1692,10 @@ glovecheck: target = which_armor(mtmp, W_ARMG); pline("%s %s into %s pit!", Monnam(mtmp), fallverb, a_your[trap->madeby_u]); + if (mptr == &mons[PM_PIT_VIPER] || mptr == &mons[PM_PIT_FIEND]) + pline("How pitiful. Isn't that the pits?"); seetrap(trap); } - if (mptr == &mons[PM_PIT_VIPER] || mptr == &mons[PM_PIT_FIEND]) - pline("How pitiful. Isn't that the pits?"); mselftouch(mtmp, "Falling, ", FALSE); if (mtmp->mhp <= 0 || thitm(0, mtmp, (struct obj *)0, @@ -1536,6 +1797,7 @@ glovecheck: target = which_armor(mtmp, W_ARMG); case PM_IRON_GOLEM: case PM_BALROG: case PM_KRAKEN: + case PM_MASTODON: tear_web = TRUE; break; } @@ -1587,6 +1849,9 @@ glovecheck: target = which_armor(mtmp, W_ARMG); /* monsters recursively fall into new pit */ if (mintrap(mtmp) == 2) trapkilled=TRUE; } + /* a boulder may fill the new pit, crushing monster */ + fill_pit(trap->tx, trap->ty); + if (mtmp->mhp <= 0) trapkilled = TRUE; if (unconscious()) { multi = -1; nomovemsg="The explosion awakens you!"; @@ -1597,7 +1862,7 @@ glovecheck: target = which_armor(mtmp, W_ARMG); if (resists_magm(mtmp)) { shieldeff(mtmp->mx, mtmp->my); } else if (!resist(mtmp, WAND_CLASS, 0, NOTELL)) { - (void) newcham(mtmp, (struct permonst *)0); + (void) newcham(mtmp, (struct permonst *)0, FALSE); if (in_sight) seetrap(trap); } break; @@ -1815,45 +2080,45 @@ long hmask, emask; /* might cancel timeout */ } } if (!trap) { - trap = t_at(u.ux,u.uy); - if(Is_airlevel(&u.uz)) - You("begin to tumble in place."); - else if (Is_waterlevel(&u.uz) && !no_msg) - You_feel("heavier."); - /* u.uinwater msgs already in spoteffects()/drown() */ - else if (!u.uinwater && !no_msg) { + trap = t_at(u.ux,u.uy); + if(Is_airlevel(&u.uz)) + You("begin to tumble in place."); + else if (Is_waterlevel(&u.uz) && !no_msg) + You_feel("heavier."); + /* u.uinwater msgs already in spoteffects()/drown() */ + else if (!u.uinwater && !no_msg) { #ifdef STEED - if (!(emask & W_SADDLE)) + if (!(emask & W_SADDLE)) #endif - { - boolean sokoban_trap = (In_sokoban(&u.uz) && trap); - if (Hallucination) - pline("Bummer! You've %s.", - is_pool(u.ux,u.uy) ? - "splashed down" : sokoban_trap ? "crashed" : - "hit the ground"); + { + boolean sokoban_trap = (In_sokoban(&u.uz) && trap); + if (Hallucination) + pline("Bummer! You've %s.", + is_pool(u.ux,u.uy) ? + "splashed down" : sokoban_trap ? "crashed" : + "hit the ground"); + else { + if (!sokoban_trap) + You("float gently to the %s.", + surface(u.ux, u.uy)); else { - if (!sokoban_trap) - You("float gently to the %s.", - surface(u.ux, u.uy)); - else { - /* Justification elsewhere for Sokoban traps - * is based on air currents. This is - * consistent with that. - * The unexpected additional force of the - * air currents once leviation - * ceases knocks you off your feet. - */ - You("fall over."); - losehp(rnd(2), "wind swept", KILLED_BY); + /* Justification elsewhere for Sokoban traps + * is based on air currents. This is + * consistent with that. + * The unexpected additional force of the + * air currents once leviation + * ceases knocks you off your feet. + */ + You("fall over."); + losehp(rnd(2), "dangerous winds", KILLED_BY); #ifdef STEED - if (u.usteed) dismount_steed(DISMOUNT_FELL); + if (u.usteed) dismount_steed(DISMOUNT_FELL); #endif - selftouch("As you fall, you"); - } + selftouch("As you fall, you"); } } } + } } /* can't rely on u.uz0 for detecting trap door-induced level change; @@ -1870,7 +2135,8 @@ long hmask, emask; /* might cancel timeout */ break; /* fall into next case */ default: - dotrap(trap); + if (!u.utrap) /* not already in the trap */ + dotrap(trap, 0); } if (!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz) && !u.uswallow && @@ -1921,7 +2187,7 @@ struct obj *box; /* null for floor trap */ destroy_item(SPBOOK_CLASS, AD_FIRE); destroy_item(POTION_CLASS, AD_FIRE); } - if (!box && burn_floor_paper(u.ux, u.uy, see_it) && !see_it) + if (!box && burn_floor_paper(u.ux, u.uy, see_it, TRUE) && !see_it) You("smell paper burning."); if (is_ice(u.ux, u.uy)) melt_ice(u.ux, u.uy); @@ -1941,6 +2207,7 @@ domagictrap() if (!resists_blnd(&youmonst)) { You("are momentarily blinded by a flash of light!"); make_blinded((long)rn1(5,10),FALSE); + if (!Blind) Your(vision_clears); } else if (!Blind) { You("see a flash of light!"); } else @@ -2006,22 +2273,120 @@ domagictrap() case 20: /* uncurse stuff */ - { register struct obj *obj; - - /* below plines added by GAN 10/30/86 */ - You_feel(Hallucination ? - "in touch with the Universal Oneness." : - "like someone is helping you."); - for(obj = invent; obj ; obj = obj->nobj) - if(obj->owornmask || obj->otyp == LOADSTONE) - uncurse(obj); - if(Punished) unpunish(); - break; + { struct obj pseudo; + long save_conf = HConfusion; + + pseudo = zeroobj; /* neither cursed nor blessed */ + pseudo.otyp = SCR_REMOVE_CURSE; + HConfusion = 0L; + (void) seffects(&pseudo); + HConfusion = save_conf; + break; } default: break; } } +/* + * Scrolls, spellbooks, potions, and flammable items + * may get affected by the fire. + * + * Return number of objects destroyed. --ALI + */ +int +fire_damage(chain, force, here, x, y) +struct obj *chain; +boolean force, here; +xchar x, y; +{ + int chance; + struct obj *obj, *otmp, *nobj, *ncobj; + int retval = 0; + int in_sight = !Blind && couldsee(x, y); /* Don't care if it's lit */ + int dindx; + + for (obj = chain; obj; obj = nobj) { + nobj = here ? obj->nexthere : obj->nobj; + + /* object might light in a controlled manner */ + if (catch_lit(obj)) + continue; + + if (Is_container(obj)) { + switch (obj->otyp) { + case ICE_BOX: + continue; /* Immune */ + /*NOTREACHED*/ + break; + case CHEST: + chance = 40; + break; + case LARGE_BOX: + chance = 30; + break; + default: + chance = 20; + break; + } + if (!force && (Luck + 5) > rn2(chance)) + continue; + /* Container is burnt up - dump contents out */ + if (in_sight) pline("%s catches fire and burns.", Yname2(obj)); + if (Has_contents(obj)) { + if (in_sight) pline("Its contents fall out."); + for (otmp = obj->cobj; otmp; otmp = ncobj) { + ncobj = otmp->nobj; + obj_extract_self(otmp); + if (!flooreffects(otmp, x, y, "")) + place_object(otmp, x, y); + } + } + delobj(obj); + retval++; + } else if (!force && (Luck + 5) > rn2(20)) { + /* chance per item of sustaining damage: + * max luck (full moon): 5% + * max luck (elsewhen): 10% + * avg luck (Luck==0): 75% + * awful luck (Luck<-4): 100% + */ + continue; + } else if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS) { + if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL) + continue; + if (obj->otyp == SPE_BOOK_OF_THE_DEAD) { + if (in_sight) pline("Smoke rises from %s.", the(xname(obj))); + continue; + } + dindx = (obj->oclass == SCROLL_CLASS) ? 2 : 3; + if (in_sight) + pline("%s %s.", Yname2(obj), (obj->quan > 1) ? + destroy_strings[dindx*3 + 1] : destroy_strings[dindx*3]); + delobj(obj); + retval++; + } else if (obj->oclass == POTION_CLASS) { + dindx = 1; + if (in_sight) + pline("%s %s.", Yname2(obj), (obj->quan > 1) ? + destroy_strings[dindx*3 + 1] : destroy_strings[dindx*3]); + delobj(obj); + retval++; + } else if (is_flammable(obj) && obj->oeroded < MAX_ERODE && + !(obj->oerodeproof || (obj->blessed && !rnl(4)))) { + if (in_sight) { + pline("%s %s%s.", Yname2(obj), otense(obj, "burn"), + obj->oeroded+1 == MAX_ERODE ? " completely" : + obj->oeroded ? " further" : ""); + } + obj->oeroded++; + } + } + + if (retval && !in_sight) + You("smell smoke."); + return retval; +} + void water_damage(obj, force, here) register struct obj *obj; @@ -2122,7 +2487,7 @@ boolean *lostsome; /* else continue */ } } - +#ifndef GOLDOBJ if (!otmp) { /* Nothing available left to drop; try gold */ if (u.ugold) { @@ -2135,16 +2500,17 @@ boolean *lostsome; assigninvlet(obj); /* might end up as NOINVSYM */ obj->nobj = invent; invent = obj; + *lostsome = TRUE; dropx(obj); continue; /* Try again */ } /* We can't even drop gold! */ return (FALSE); } - - if (otmp == uarmh) (void) Helmet_off(); - else if (otmp == uarms) (void) Shield_off(); - else if (otmp == uwep) setuwep((struct obj *)0); +#else + if (!otmp) return (FALSE); /* nothing to drop! */ +#endif + if (otmp->owornmask && otmp != uball) remove_worn_item(otmp); *lostsome = TRUE; dropx(otmp); invc--; @@ -2306,7 +2672,7 @@ dountrap() /* disarm a trap */ pline("You're too strained to do that."); return 0; } - if (nohands(youmonst.data) || !youmonst.data->mmove) { + if ((nohands(youmonst.data) && !webmaker(youmonst.data)) || !youmonst.data->mmove) { pline("And just how do you expect to do that?"); return 0; } else if (u.ustuck && sticks(youmonst.data)) { @@ -2330,6 +2696,9 @@ struct trap *ttmp; { int chance = 3; + /* Only spiders know how to deal with webs reliably */ + if (ttmp->ttyp == WEB && !webmaker(youmonst.data)) + chance = 30; if (Confusion || Hallucination) chance++; if (Blind) chance++; if (Stunned) chance += 2; @@ -2339,7 +2708,7 @@ struct trap *ttmp; if (Role_if(PM_ROGUE)) { if (rn2(2 * MAXULEV) < u.ulevel) chance--; if (u.uhave.questart && chance > 1) chance--; - } else if (Role_if(PM_RANGER)) chance--; + } else if (Role_if(PM_RANGER) && chance > 1) chance--; return rn2(chance); } @@ -2353,6 +2722,9 @@ struct trap *ttmp; struct obj *otmp = mksobj(otyp, TRUE, FALSE); otmp->quan=cnt; otmp->owt = weight(otmp); + /* Only dart traps are capable of being poisonous */ + if (otyp != DART) + otmp->opoisoned = 0; place_object(otmp, ttmp->tx, ttmp->ty); /* Sell your own traps only... */ if (ttmp->madeby_u) sellobj(otmp, ttmp->tx, ttmp->ty); @@ -2396,9 +2768,10 @@ boolean force_failure; struct monst *mtmp = m_at(ttmp->tx,ttmp->ty); int ttype = ttmp->ttyp; boolean under_u = (!u.dx && !u.dy); - + boolean holdingtrap = (ttype == BEAR_TRAP || ttype == WEB); + /* Test for monster first, monsters are displayed instead of trap. */ - if (mtmp && (!mtmp->mtrapped || ttype != BEAR_TRAP)) { + if (mtmp && (!mtmp->mtrapped || !holdingtrap)) { pline("%s is in the way.", Monnam(mtmp)); return 0; } @@ -2408,6 +2781,18 @@ boolean force_failure; There("is a boulder in your way."); return 0; } + /* duplicate tight-space checks from test_move */ + if (u.dx && u.dy && + bad_rock(youmonst.data,u.ux,ttmp->ty) && + bad_rock(youmonst.data,ttmp->tx,u.uy)) { + if ((invent && (inv_weight() + weight_cap() > 600)) || + bigmonst(youmonst.data)) { + /* don't allow untrap if they can't get thru to it */ + You("are unable to reach the %s!", + defsyms[trap_to_defsym(ttype)].explanation); + return 0; + } + } /* untrappable traps are located on the ground. */ if (!can_reach_floor()) { #ifdef STEED @@ -2425,18 +2810,30 @@ boolean force_failure; if (force_failure || untrap_prob(ttmp)) { if (rnl(5)) { pline("Whoops..."); - if (mtmp) { /* must be a bear trap */ - if (mtmp->mtame) abuse_dog(mtmp); - if ((mtmp->mhp -= rnd(4)) <= 0) killed(mtmp); + if (mtmp) { /* must be a trap that holds monsters */ + if (ttype == BEAR_TRAP) { + if (mtmp->mtame) abuse_dog(mtmp); + if ((mtmp->mhp -= rnd(4)) <= 0) killed(mtmp); + } else if (ttype == WEB) { + if (!webmaker(youmonst.data)) { + struct trap *ttmp2 = maketrap(u.ux, u.uy, WEB); + if (ttmp2) { + pline_The("webbing sticks to you. You're caught too!"); + dotrap(ttmp2, NOWEBMSG); + } + } else + pline("%s remains entangled.", Monnam(mtmp)); + } } else if (under_u) { - dotrap(ttmp); + dotrap(ttmp, 0); } else { move_into_trap(ttmp); } } else { - pline("%s %s is difficult to disarm.", + pline("%s %s is difficult to %s.", ttmp->madeby_u ? "Your" : under_u ? "This" : "That", - defsyms[trap_to_defsym(ttype)].explanation); + defsyms[trap_to_defsym(ttype)].explanation, + (ttype == WEB) ? "remove" : "disarm"); } return 1; } @@ -2449,23 +2846,24 @@ struct trap *ttmp; struct monst *mtmp; { if (!ttmp->madeby_u) { - if (rnl(10)<8 && !mtmp->mpeaceful && - mtmp->data->mlet != S_HUMAN) { - mtmp->mpeaceful = 1; - set_malign(mtmp); /* reset alignment */ - pline("%s is grateful.", Monnam(mtmp)); - } - /* Helping someone out of a trap is a nice thing to do, - * A lawful may be rewarded, but not too often. */ - if (!rn2(3) && !rnl(8) && u.ualign.type == A_LAWFUL) { - adjalign(1); - You_feel("that you did the right thing."); - } + if (rnl(10) < 8 && !mtmp->mpeaceful && + !mindless(mtmp->data) && + mtmp->data->mlet != S_HUMAN) { + mtmp->mpeaceful = 1; + set_malign(mtmp); /* reset alignment */ + pline("%s is grateful.", Monnam(mtmp)); + } + /* Helping someone out of a trap is a nice thing to do, + * A lawful may be rewarded, but not too often. */ + if (!rn2(3) && !rnl(8) && u.ualign.type == A_LAWFUL) { + adjalign(1); + You_feel("that you did the right thing."); + } } } STATIC_OVL int -disarm_beartrap(ttmp) /* Helge Hafting */ +disarm_holdingtrap(ttmp) /* Helge Hafting */ struct trap *ttmp; { struct monst *mtmp; @@ -2479,11 +2877,20 @@ struct trap *ttmp; There's no need for a cockatrice test, only the trap is touched */ if ((mtmp = m_at(ttmp->tx,ttmp->ty)) != 0) { mtmp->mtrapped = 0; - You("remove %s bear trap from %s.", the_your[ttmp->madeby_u], + You("remove %s %s from %s.", the_your[ttmp->madeby_u], + (ttmp->ttyp == BEAR_TRAP) ? "bear trap" : "webbing", mon_nam(mtmp)); reward_untrap(ttmp, mtmp); - } else You("disarm %s bear trap.", the_your[ttmp->madeby_u]); - cnv_trap_obj(BEARTRAP, 1, ttmp); + } else { + if (ttmp->ttyp == BEAR_TRAP) { + You("disarm %s bear trap.", the_your[ttmp->madeby_u]); + cnv_trap_obj(BEARTRAP, 1, ttmp); + } else /* if (ttmp->ttyp == WEB) */ { + You("succeed in removing %s web.", the_your[ttmp->madeby_u]); + deltrap(ttmp); + } + } + newsym(u.ux + u.dx, u.uy + u.dy); return 1; } @@ -2533,6 +2940,7 @@ struct trap *ttmp; deltrap(ttmp); newsym(u.ux + u.dx, u.uy + u.dy); more_experienced(1, 5); + newexplevel(); return 1; } @@ -2561,16 +2969,17 @@ boolean stuff; { int wc = weight_cap(); - if ((((wt<<1) / wc)+1) >= EXT_ENCUMBER) { - pline("%s is %s for you to lift.", Monnam(mtmp), - stuff ? "carrying too much" : "too heavy"); - if (!ttmp->madeby_u && !mtmp->mpeaceful - && mtmp->data->mlet != S_HUMAN && rnl(10) < 3) { - mtmp->mpeaceful = 1; - set_malign(mtmp); /* reset alignment */ - pline("%s thinks it was nice of you to try.", Monnam(mtmp)); - } - return 0; + if (((wt * 2) / wc) >= HVY_ENCUMBER) { + pline("%s is %s for you to lift.", Monnam(mtmp), + stuff ? "carrying too much" : "too heavy"); + if (!ttmp->madeby_u && !mtmp->mpeaceful && mtmp->mcanmove && + !mindless(mtmp->data) && + mtmp->data->mlet != S_HUMAN && rnl(10) < 3) { + mtmp->mpeaceful = 1; + set_malign(mtmp); /* reset alignment */ + pline("%s thinks it was nice of you to try.", Monnam(mtmp)); + } + return 0; } return 1; } @@ -2583,6 +2992,7 @@ struct trap *ttmp; { int wt; struct obj *otmp; + boolean uprob; /* * This works when levitating too -- consistent with the ability @@ -2601,7 +3011,7 @@ struct trap *ttmp; if (check_capacity((char *)0)) return 1; /* Will our hero succeed? */ - if (untrap_prob(ttmp)) { + if ((uprob = untrap_prob(ttmp)) && !mtmp->msleeping && mtmp->mcanmove) { You("try to reach out your %s, but %s backs away skeptically.", makeplural(body_part(ARM)), mon_nam(mtmp)); @@ -2625,9 +3035,30 @@ struct trap *ttmp; return 1; } } + /* need to do cockatrice check first if sleeping or paralyzed */ + if (uprob) { + You("try to grab %s, but cannot get a firm grasp.", + mon_nam(mtmp)); + if (mtmp->msleeping) { + mtmp->msleeping = 0; + pline("%s awakens.", Monnam(mtmp)); + } + return 1; + } + You("reach out your %s and grab %s.", makeplural(body_part(ARM)), mon_nam(mtmp)); + if (mtmp->msleeping) { + mtmp->msleeping = 0; + pline("%s awakens.", Monnam(mtmp)); + } else if (mtmp->mfrozen && !rn2(mtmp->mfrozen)) { + /* After such manhandling, perhaps the effect wears off */ + mtmp->mcanmove = 1; + mtmp->mfrozen = 0; + pline("%s stirs.", Monnam(mtmp)); + } + /* is the monster too heavy? */ wt = inv_weight() + mtmp->data->cwt; if (!try_lift(mtmp, ttmp, wt, FALSE)) return 1; @@ -2667,7 +3098,8 @@ boolean force; } switch(ttmp->ttyp) { case BEAR_TRAP: - return disarm_beartrap(ttmp); + case WEB: + return disarm_holdingtrap(ttmp); case LANDMINE: return disarm_landmine(ttmp); case SQKY_BOARD: @@ -2859,7 +3291,7 @@ boolean disarm; insider = (*u.ushops && inside_shop(u.ux, u.uy) && *in_rooms(ox, oy, SHOPBASE) == *u.ushops); - pline("%s explodes!", The(xname(obj))); + pline("%s!", Tobjnam(obj, "explode")); Sprintf(buf, "exploding %s", xname(obj)); if(costly) @@ -2880,11 +3312,11 @@ boolean disarm; exercise(A_STR, FALSE); if(costly && loss) { if(insider) - You("owe %ld zorkmids for objects destroyed.", - loss); + You("owe %ld %s for objects destroyed.", + loss, currency(loss)); else { - You("caused %ld zorkmids worth of damage!", - loss); + You("caused %ld %s worth of damage!", + loss, currency(loss)); make_angry_shk(shkp, ox, oy); } } @@ -2950,9 +3382,11 @@ boolean disarm; if (Hallucination) pline("What a groovy feeling!"); else if (Blind) - You("stagger and get dizzy..."); + You("%s and get dizzy...", + stagger(youmonst.data, "stagger")); else - You("stagger and your vision blurs..."); + You("%s and your vision blurs...", + stagger(youmonst.data, "stagger")); } make_stunned(HStun + rn1(7, 16),FALSE); make_hallucinated(HHallucination + rn1(5, 16),FALSE,0L); @@ -3068,9 +3502,8 @@ int d_override; * obj->spe into account. */ if(!strike) { - if (cansee(mon->mx, mon->my)) - pline("%s is almost hit by %s!", Monnam(mon), - doname(obj)); + if (obj && cansee(mon->mx, mon->my)) + pline("%s is almost hit by %s!", Monnam(mon), doname(obj)); } else { int dam = 1; @@ -3105,8 +3538,8 @@ unconscious() { return((boolean)(multi < 0 && (!nomovemsg || u.usleep || - !strncmp(nomovemsg,"You regain con", 15) || - !strncmp(nomovemsg,"You are consci", 15)))); + !strncmp(nomovemsg,"You regain con", 14) || + !strncmp(nomovemsg,"You are consci", 14)))); } static char lava_killer[] = "molten lava"; diff --git a/src/u_init.c b/src/u_init.c index 89c8127..f3b9cfb 100644 --- a/src/u_init.c +++ b/src/u_init.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)u_init.c 3.3 2000/06/11 */ +/* SCCS Id: @(#)u_init.c 3.4 2002/03/02 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -12,10 +12,10 @@ struct trobj { Bitfield(trbless,2); }; -static void FDECL(ini_inv, (struct trobj *)); -static void FDECL(knows_object,(int)); -static void FDECL(knows_class,(CHAR_P)); -static boolean FDECL(restricted_spell_discipline, (int)); +STATIC_DCL void FDECL(ini_inv, (struct trobj *)); +STATIC_DCL void FDECL(knows_object,(int)); +STATIC_DCL void FDECL(knows_class,(CHAR_P)); +STATIC_DCL boolean FDECL(restricted_spell_discipline, (int)); #define UNDEF_TYP 0 #define UNDEF_SPE '\177' @@ -33,6 +33,7 @@ static struct trobj Archeologist[] = { { FOOD_RATION, 0, FOOD_CLASS, 3, 0 }, { PICK_AXE, UNDEF_SPE, TOOL_CLASS, 1, UNDEF_BLESS }, { TINNING_KIT, UNDEF_SPE, TOOL_CLASS, 1, UNDEF_BLESS }, + { TOUCHSTONE, 0, GEM_CLASS, 1, 0 }, { SACK, 0, TOOL_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; @@ -69,8 +70,8 @@ static struct trobj Healer[] = { { 0, 0, 0, 0, 0 } }; static struct trobj Knight[] = { - { LONG_SWORD, 0, WEAPON_CLASS, 1, UNDEF_BLESS }, - { SPEAR, 2, WEAPON_CLASS, 1, UNDEF_BLESS }, + { LONG_SWORD, 1, WEAPON_CLASS, 1, UNDEF_BLESS }, + { LANCE, 1, WEAPON_CLASS, 1, UNDEF_BLESS }, { RING_MAIL, 1, ARMOR_CLASS, 1, UNDEF_BLESS }, { HELMET, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, { SMALL_SHIELD, 0, ARMOR_CLASS, 1, UNDEF_BLESS }, @@ -80,7 +81,7 @@ static struct trobj Knight[] = { { 0, 0, 0, 0, 0 } }; static struct trobj Monk[] = { -#define M_BOOK 2 +#define M_BOOK 2 { LEATHER_GLOVES, 2, ARMOR_CLASS, 1, UNDEF_BLESS }, { ROBE, 1, ARMOR_CLASS, 1, UNDEF_BLESS }, { UNDEF_TYP, UNDEF_SPE, SPBOOK_CLASS, 1, 1 }, @@ -212,6 +213,12 @@ static struct trobj Wishing[] = { { WAN_WISHING, 3, WAND_CLASS, 1, 0 }, { 0, 0, 0, 0, 0 } }; +#ifdef GOLDOBJ +static struct trobj Money[] = { + { GOLD_PIECE, 0 , GOLD_CLASS, 1, 0 }, + { 0, 0, 0, 0, 0 } +}; +#endif /* race-based substitutions for initial inventory; the weaker cloak for elven rangers is intentional--they shoot better */ @@ -269,7 +276,7 @@ static struct def_skill Skill_B[] = { { P_TWO_HANDED_SWORD, P_EXPERT }, { P_SCIMITAR, P_SKILLED }, { P_SABER, P_BASIC }, { P_CLUB, P_SKILLED }, { P_MACE, P_SKILLED }, { P_MORNING_STAR, P_SKILLED }, - { P_FLAIL, P_BASIC }, { P_HAMMER, P_EXPERT }, + { P_FLAIL, P_BASIC }, { P_HAMMER, P_EXPERT }, { P_QUARTERSTAFF, P_BASIC }, { P_SPEAR, P_SKILLED }, { P_TRIDENT, P_SKILLED }, { P_BOW, P_BASIC }, { P_ATTACK_SPELL, P_SKILLED }, @@ -382,15 +389,15 @@ static struct def_skill Skill_R[] = { static struct def_skill Skill_Ran[] = { { P_DAGGER, P_EXPERT }, { P_KNIFE, P_SKILLED }, - { P_AXE, P_SKILLED }, { P_PICK_AXE, P_BASIC }, - { P_SHORT_SWORD, P_BASIC }, { P_MORNING_STAR, P_BASIC }, - { P_FLAIL, P_SKILLED }, { P_HAMMER, P_BASIC }, + { P_AXE, P_SKILLED }, { P_PICK_AXE, P_BASIC }, + { P_SHORT_SWORD, P_BASIC }, { P_MORNING_STAR, P_BASIC }, + { P_FLAIL, P_SKILLED }, { P_HAMMER, P_BASIC }, { P_QUARTERSTAFF, P_BASIC }, { P_POLEARMS, P_SKILLED }, - { P_SPEAR, P_SKILLED }, { P_JAVELIN, P_EXPERT }, - { P_TRIDENT, P_BASIC }, { P_BOW, P_EXPERT }, - { P_SLING, P_EXPERT }, { P_CROSSBOW, P_EXPERT }, - { P_DART, P_EXPERT }, { P_SHURIKEN, P_SKILLED }, - { P_BOOMERANG, P_EXPERT }, { P_WHIP, P_BASIC }, + { P_SPEAR, P_SKILLED }, { P_JAVELIN, P_EXPERT }, + { P_TRIDENT, P_BASIC }, { P_BOW, P_EXPERT }, + { P_SLING, P_EXPERT }, { P_CROSSBOW, P_EXPERT }, + { P_DART, P_EXPERT }, { P_SHURIKEN, P_SKILLED }, + { P_BOOMERANG, P_EXPERT }, { P_WHIP, P_BASIC }, { P_HEALING_SPELL, P_BASIC }, { P_DIVINATION_SPELL, P_EXPERT }, { P_ESCAPE_SPELL, P_BASIC }, @@ -485,7 +492,7 @@ static struct def_skill Skill_W[] = { }; -static void +STATIC_OVL void knows_object(obj) register int obj; { @@ -496,7 +503,7 @@ register int obj; /* Know ordinary (non-magical) objects of a certain class, * like all gems except the loadstone and luckstone. */ -static void +STATIC_OVL void knows_class(sym) register char sym; { @@ -601,8 +608,8 @@ u_init() if(!rn2(10)) ini_inv(Tinopener); else if(!rn2(4)) ini_inv(Lamp); else if(!rn2(10)) ini_inv(Magicmarker); - knows_class(GEM_CLASS); knows_object(SACK); + knows_object(TOUCHSTONE); skill_init(Skill_A); break; case PM_BARBARIAN: @@ -622,7 +629,11 @@ u_init() skill_init(Skill_C); break; case PM_HEALER: +#ifndef GOLDOBJ u.ugold = u.ugold0 = rn1(1000, 1001); +#else + u.umoney0 = rn1(1000, 1001); +#endif ini_inv(Healer); if(!rn2(25)) ini_inv(Lamp); knows_object(POT_FULL_HEALING); @@ -664,38 +675,6 @@ u_init() */ break; case PM_RANGER: -#if 0 /* superseded by inv_subs[] */ - switch (rn2(100) / 20) { - case 0: /* Special racial bow */ - case 1: - case 2: - switch (Race_switch) { - case PM_ELF: - Ranger[RAN_BOW].trotyp = ELVEN_BOW; - Ranger[RAN_TWO_ARROWS].trotyp = - Ranger[RAN_ZERO_ARROWS].trotyp = ELVEN_ARROW; - break; - case PM_GNOME: - Ranger[RAN_BOW].trotyp = CROSSBOW; - Ranger[RAN_TWO_ARROWS].trotyp = - Ranger[RAN_ZERO_ARROWS].trotyp = CROSSBOW_BOLT; - break; - case PM_ORC: - Ranger[RAN_BOW].trotyp = ORCISH_BOW; - Ranger[RAN_TWO_ARROWS].trotyp = - Ranger[RAN_ZERO_ARROWS].trotyp = ORCISH_ARROW; - break; - default: break; /* Use default bow + arrow */ - } - break; - case 3: /* Missiles */ - Ranger[RAN_BOW].trotyp = BOOMERANG; - Ranger[RAN_TWO_ARROWS].trotyp = - Ranger[RAN_ZERO_ARROWS].trotyp = DART; - break; - default: break; /* Use default bow + arrow */ - } -#endif /*0*/ Ranger[RAN_TWO_ARROWS].trquan = rn1(10, 50); Ranger[RAN_ZERO_ARROWS].trquan = rn1(10, 30); ini_inv(Ranger); @@ -703,7 +682,11 @@ u_init() break; case PM_ROGUE: Rogue[R_DAGGERS].trquan = rn1(10, 6); +#ifndef GOLDOBJ u.ugold = u.ugold0 = 0; +#else + u.umoney0 = 0; +#endif ini_inv(Rogue); if(!rn2(5)) ini_inv(Blindfold); knows_object(SACK); @@ -720,7 +703,11 @@ u_init() #ifdef TOURIST case PM_TOURIST: Tourist[T_DARTS].trquan = rn1(20, 21); +#ifndef GOLDOBJ u.ugold = u.ugold0 = rnd(1000); +#else + u.umoney0 = rnd(1000); +#endif ini_inv(Tourist); if(!rn2(25)) ini_inv(Tinopener); else if(!rn2(25)) ini_inv(Leash); @@ -730,7 +717,6 @@ u_init() break; #endif case PM_VALKYRIE: - flags.female = TRUE; ini_inv(Valkyrie); if(!rn2(6)) ini_inv(Lamp); knows_class(WEAPON_CLASS); @@ -819,11 +805,21 @@ u_init() default: /* impossible */ break; } - + if (discover) ini_inv(Wishing); +#ifdef WIZARD + if (wizard) + read_wizkit(); +#endif + +#ifndef GOLDOBJ u.ugold0 += hidden_gold(); /* in case sack has gold in it */ +#else + if (u.umoney0) ini_inv(Money); + u.umoney0 += hidden_gold(); /* in case sack has gold in it */ +#endif find_ac(); /* get initial ac value */ init_attr(75); /* init attribute values */ @@ -850,7 +846,7 @@ u_init() } /* skills aren't initialized, so we use the role-specific skill lists */ -static boolean +STATIC_OVL boolean restricted_spell_discipline(otyp) int otyp; { @@ -883,7 +879,7 @@ int otyp; return TRUE; } -static void +STATIC_OVL void ini_inv(trop) register struct trobj *trop; { @@ -933,7 +929,6 @@ register struct trobj *trop; || otyp == POT_ACID || otyp == SCR_AMNESIA || otyp == SCR_FIRE - || otyp == SCR_STINKING_CLOUD || otyp == SCR_BLANK_PAPER || otyp == SPE_BLANK_PAPER || otyp == RIN_AGGRAVATE_MONSTER @@ -984,20 +979,32 @@ register struct trobj *trop; nocreate4 = otyp; } - obj->dknown = obj->bknown = obj->rknown = 1; - if (objects[otyp].oc_uses_known) obj->known = 1; - obj->cursed = 0; - if (obj->opoisoned && u.ualign.type != A_CHAOTIC) - obj->opoisoned = 0; - if(obj->oclass == WEAPON_CLASS || obj->oclass == TOOL_CLASS) { - obj->quan = (long) trop->trquan; - trop->trquan = 1; +#ifdef GOLDOBJ + if (trop->trclass == GOLD_CLASS) { + /* no "blessed" or "identified" money */ + obj->quan = u.umoney0; + } else { +#endif + obj->dknown = obj->bknown = obj->rknown = 1; + if (objects[otyp].oc_uses_known) obj->known = 1; + obj->cursed = 0; + if (obj->opoisoned && u.ualign.type != A_CHAOTIC) + obj->opoisoned = 0; + if (obj->oclass == WEAPON_CLASS || + obj->oclass == TOOL_CLASS) { + obj->quan = (long) trop->trquan; + trop->trquan = 1; + } else if (obj->oclass == GEM_CLASS && + is_graystone(obj) && obj->otyp != FLINT) { + obj->quan = 1L; + } + if (trop->trspe != UNDEF_SPE) + obj->spe = trop->trspe; + if (trop->trbless != UNDEF_BLESS) + obj->blessed = trop->trbless; +#ifdef GOLDOBJ } - if(trop->trspe != UNDEF_SPE) - obj->spe = trop->trspe; - if(trop->trbless != UNDEF_BLESS) - obj->blessed = trop->trbless; - +#endif /* defined after setting otyp+quan + blessedness */ obj->owt = weight(obj); obj = addinv(obj); @@ -1009,9 +1016,10 @@ register struct trobj *trop; discover_object(POT_OIL, TRUE, FALSE); if(obj->oclass == ARMOR_CLASS){ - if (is_shield(obj) && !uarms) + if (is_shield(obj) && !uarms) { setworn(obj, W_ARMS); - else if (is_helmet(obj) && !uarmh) + if (uswapwep) setuswapwep((struct obj *) 0); + } else if (is_helmet(obj) && !uarmh) setworn(obj, W_ARMH); else if (is_gloves(obj) && !uarmg) setworn(obj, W_ARMG); diff --git a/src/uhitm.c b/src/uhitm.c index 82fa299..2ebb86b 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)uhitm.c 3.3 2000/02/20 */ +/* SCCS Id: @(#)uhitm.c 3.4 2002/02/17 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -37,7 +37,7 @@ int attk; switch(attk) { /* 0 is burning, which we should never be called with */ case AD_RUST: hurt = 1; break; - case AD_CORRODE: hurt = 3; break; + case AD_CORR: hurt = 3; break; default: hurt = 2; break; } /* What the following code does: it keeps looping until it @@ -87,6 +87,7 @@ int attk; } } +/* FALSE means it's OK to attack */ boolean attack_checks(mtmp, wep) register struct monst *mtmp; @@ -114,13 +115,16 @@ struct obj *wep; /* uwep for attack(), null for kick_monster() */ return FALSE; } - /* Put up an invisible monster marker, but one exception is for - * monsters that hide. That already prints a warning message and + /* Put up an invisible monster marker, but with exceptions for + * monsters that hide and monsters you've been warned about. + * The former already prints a warning message and * prevents you from hitting the monster just via the hidden monster * code below; if we also did that here, similar behavior would be - * happening two turns in a row. + * happening two turns in a row. The latter shows a glyph on + * the screen, so you know something is there. */ if (!canspotmon(mtmp) && + !glyph_is_warning(glyph_at(u.ux+u.dx,u.uy+u.dy)) && !glyph_is_invisible(levl[u.ux+u.dx][u.uy+u.dy].glyph) && !(!Blind && mtmp->mundetected && hides_under(mtmp->data))) { pline("Wait! There's %s there you can't see!", @@ -137,8 +141,9 @@ struct obj *wep; /* uwep for attack(), null for kick_monster() */ return TRUE; } - if(mtmp->m_ap_type && !Protection_from_shape_changers - && !sensemon(mtmp)) { + if (mtmp->m_ap_type && !Protection_from_shape_changers && + !sensemon(mtmp) && + !glyph_is_warning(glyph_at(u.ux+u.dx,u.uy+u.dy))) { /* If a hidden mimic was in a square where a player remembers * some (probably different) unseen monster, the player is in * luck--he attacks it even though it's hidden. @@ -152,6 +157,7 @@ struct obj *wep; /* uwep for attack(), null for kick_monster() */ } if (mtmp->mundetected && !canseemon(mtmp) && + !glyph_is_warning(glyph_at(u.ux+u.dx,u.uy+u.dy)) && (hides_under(mtmp->data) || mtmp->data->mlet == S_EEL)) { mtmp->mundetected = mtmp->msleeping = 0; newsym(mtmp->mx, mtmp->my); @@ -171,6 +177,15 @@ struct obj *wep; /* uwep for attack(), null for kick_monster() */ } } + /* + * make sure to wake up a monster from the above cases if the + * hero can sense that the monster is there. + */ + if ((mtmp->mundetected || mtmp->m_ap_type) && sensemon(mtmp)) { + mtmp->mundetected = 0; + wakeup(mtmp); + } + if (flags.confirm && mtmp->mpeaceful && !Confusion && !Hallucination && !Stunned) { /* Intelligent chaotic weapons (Stormbringer) want blood */ @@ -202,7 +217,8 @@ register struct monst *mtmp; /* it is unchivalrous to attack the defenseless or from behind */ if (Role_if(PM_KNIGHT) && u.ualign.type == A_LAWFUL && - (!mtmp->mcanmove || mtmp->msleeping || mtmp->mflee) && + (!mtmp->mcanmove || mtmp->msleeping || + (mtmp->mflee && !mtmp->mavenge)) && u.ualign.record > -10) { You("caitiff!"); adjalign(-1); @@ -284,16 +300,22 @@ register struct monst *mtmp; * there's also a chance of displacing a "frozen" monster. * sleeping monsters might magically walk in their sleep. */ - unsigned int foo = (Punished || - !rn2(7) || is_longworm(mtmp->data)); + boolean foo = (Punished || !rn2(7) || is_longworm(mtmp->data)), + inshop = FALSE; + char *p; - if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE) || foo - || (IS_ROCK(levl[u.ux][u.uy].typ) && + for (p = in_rooms(mtmp->mx, mtmp->my, SHOPBASE); *p; p++) + if (tended_shop(&rooms[*p - ROOMOFFSET])) { + inshop = TRUE; + break; + } + + if (inshop || foo || + (IS_ROCK(levl[u.ux][u.uy].typ) && !passes_walls(mtmp->data))) { char buf[BUFSZ]; - mtmp->mflee = 1; - mtmp->mfleetim = rnd(6); + monflee(mtmp, rnd(6), FALSE, FALSE); Strcpy(buf, y_monnam(mtmp)); buf[0] = highc(buf[0]); You("stop. %s is in the way!", buf); @@ -397,24 +419,30 @@ struct attack *uattk; /* we hit the monster; be careful: it might die! */ notonhead = (mon->mx != u.ux+u.dx || mon->my != u.uy+u.dy); malive = hmon(mon, uwep, 0); - if (malive && u.twoweap) malive = hmon(mon, uswapwep, 0); + /* This assumes that Stormbringer was uwep not uswapwep */ + if (malive && u.twoweap && !override_confirmation) + malive = hmon(mon, uswapwep, 0); if (malive) { /* monster still alive */ if(!rn2(25) && mon->mhp < mon->mhpmax/2 && !(u.uswallow && mon == u.ustuck)) { /* maybe should regurgitate if swallowed? */ - mon->mflee = 1; if(!rn2(3)) { - mon->mfleetim = rnd(100); - if (!Blind) pline("%s turns to flee!", (Monnam(mon))); - } + monflee(mon, rnd(100), FALSE, TRUE); + } else monflee(mon, 0, FALSE, TRUE); + if(u.ustuck == mon && !u.uswallow && !sticks(youmonst.data)) u.ustuck = 0; } /* Vorpal Blade hit converted to miss */ /* could be headless monster or worm tail */ - if (mon->mhp == oldhp) - *mhit = 0; + if (mon->mhp == oldhp) { + *mhit = 0; + /* a miss does not break conduct */ + if (uwep && + (uwep->oclass == WEAPON_CLASS || is_weptool(uwep))) + --u.uconduct.weaphit; + } if (mon->wormno && *mhit) cutworm(mon, u.ux+u.dx, u.uy+u.dy, uwep); } @@ -475,6 +503,9 @@ int thrown; boolean get_dmg_bonus = TRUE; boolean ispoisoned = FALSE, needpoismsg = FALSE, poiskilled = FALSE; boolean silvermsg = FALSE; +#ifdef STEED + boolean jousting = FALSE; +#endif boolean valid_weapon_attack = FALSE; int wtype; struct obj *monwep; @@ -544,9 +575,9 @@ int thrown; ((wtype = uwep_skill_type()) != P_NONE && P_SKILL(wtype) >= P_SKILLED) && ((monwep = MON_WEP(mon)) != 0 && - weapon_type(monwep) != P_WHIP && - !obj_resists(monwep, - 50 + 15 * greatest_erosion(monwep), 100))) { + !is_flimsy(monwep) && + !obj_resists(monwep, + 50 + 15 * greatest_erosion(obj), 100))) { /* * 2.5% chance of shattering defender's weapon when * using a two-handed weapon; less if uwep is rusted. @@ -554,17 +585,16 @@ int thrown; * -bisecting hit, in case of special artifact damage; * the percentage chance is (1/20)*(50/100).] */ - monwep->owornmask &= ~W_WEP; + setmnotwielded(mon,monwep); MON_NOWEP(mon); mon->weapon_check = NEED_WEAPON; - pline("%s %s shatter%s from the force of your blow!", + pline("%s %s %s from the force of your blow!", s_suffix(Monnam(mon)), xname(monwep), - (monwep->quan) == 1L ? "s" : ""); + otense(monwep, "shatter")); m_useup(mon, monwep); /* If someone just shattered MY weapon, I'd flee! */ - if (rn2(4) && !mon->mflee) { - mon->mflee = 1; - mon->mfleetim = d(2,3); + if (rn2(4)) { + monflee(mon, d(2,3), TRUE, TRUE); } hittxt = TRUE; } @@ -579,6 +609,11 @@ int thrown; if (objects[obj->otyp].oc_material == SILVER && hates_silver(mdat)) silvermsg = TRUE; +#ifdef STEED + if (u.usteed && !thrown && + weapon_type(obj) == P_LANCE && mon != u.ustuck) + jousting = TRUE; +#endif if(!thrown && obj == uwep && obj->otyp == BOOMERANG && !rnl(3)) { pline("As you hit %s, %s breaks into splinters.", @@ -607,7 +642,7 @@ int thrown; } } else if(obj->oclass == POTION_CLASS) { if (obj->quan > 1L) - setworn(splitobj(obj, 1L), W_WEP); + obj = splitobj(obj, 1L); else setuwep((struct obj *)0); freeinv(obj); @@ -705,7 +740,7 @@ int thrown; (cnt > 1L) ? "some" : "an"; You("hit %s with %s egg%s.", mon_nam(mon), eggp, plur(cnt)); - if (touch_petrifies(mdat)) { + if (touch_petrifies(mdat) && !stale_egg(obj)) { pline_The("egg%s %s alive any more...", plur(cnt), (cnt == 1L) ? "isn't" : "aren't"); @@ -728,9 +763,7 @@ int thrown; } case CLOVE_OF_GARLIC: /* no effect against demons */ if (is_undead(mdat)) { - mon->mflee = 1; - mon->mfleetim += d(2,4); - pline("%s turns to flee!", Monnam(mon)); + monflee(mon, d(2, 4), FALSE, TRUE); } tmp = 1; break; @@ -835,8 +868,8 @@ int thrown; } if (obj && !rn2(nopoison)) { obj->opoisoned = FALSE; - Your("%s%s no longer poisoned.", xname(obj), - (obj->quan == 1L) ? " is" : "s are"); /**FIXME**/ + Your("%s %s no longer poisoned.", xname(obj), + otense(obj, "are")); } if (resists_poison(mon)) needpoismsg = TRUE; @@ -859,29 +892,24 @@ int thrown; } } +#ifdef STEED + if (jousting) { + You("joust %s%s", + mon_nam(mon), canseemon(mon) ? exclam(tmp) : "."); + mhurtle(mon, u.dx, u.dy, 1); + hittxt = TRUE; + } else +#endif + /* VERY small chance of stunning opponent if unarmed. */ if (tmp > 1 && !thrown && !obj && !uwep && !uarm && !uarms && !Upolyd) { if (rnd(100) < P_SKILL(P_BARE_HANDED_COMBAT) && !bigmonst(mdat) && !thick_skinned(mdat)) { if (canspotmon(mon)) - pline("%s staggers from your powerful strike!", - Monnam(mon)); - mon->mstun = 1; + pline("%s %s from your powerful strike!", Monnam(mon), + makeplural(stagger(mon->data, "stagger"))); + mhurtle(mon, u.dx, u.dy, 1); hittxt = TRUE; - if (mon->mcanmove && mon != u.ustuck) { - xchar mdx, mdy; - - /* see if the monster has a place to move into */ - mdx = mon->mx + u.dx; - mdy = mon->my + u.dy; - if (goodpos(mdx, mdy, mon)) { - remove_monster(mon->mx, mon->my); - newsym(mon->mx, mon->my); - place_monster(mon, mdx, mdy); - newsym(mon->mx, mon->my); - set_apparxy(mon); - } - } } } @@ -889,12 +917,8 @@ int thrown; if(mon->mhp < 1) destroyed = TRUE; if (mon->mtame && (!mon->mflee || mon->mfleetim) && tmp > 0) { - unsigned fleetim; - abuse_dog(mon); - mon->mflee = TRUE; /* Rick Richardson */ - fleetim = mon->mfleetim + (unsigned)(10 * rnd(tmp)); - mon->mfleetim = min(fleetim,127); + monflee(mon, 10 * rnd(tmp), FALSE, FALSE); } if((mdat == &mons[PM_BLACK_PUDDING] || mdat == &mons[PM_BROWN_PUDDING]) && obj && obj == uwep @@ -907,11 +931,10 @@ int thrown; } } - if(!hittxt && !destroyed) { - if(thrown) - /* thrown => obj exists */ - hit(xname(obj), mon, exclam(tmp) ); - else if(!flags.verbose) You("hit it."); + if (!hittxt && /*( thrown => obj exists )*/ + (!destroyed || (thrown && m_shot.n > 1 && m_shot.o == obj->otyp))) { + if (thrown) hit(mshot_xname(obj), mon, exclam(tmp)); + else if (!flags.verbose) You("hit it."); else You("%s %s%s", Role_if(PM_BARBARIAN) ? "smite" : "hit", mon_nam(mon), canseemon(mon) ? exclam(tmp) : "."); } @@ -991,7 +1014,7 @@ struct attack *mattk; /* avoid "slippery slippery cloak" for undiscovered oilskin cloak */ (obj->greased || objects[obj->otyp].oc_name_known) ? - xname(obj) : "cloak"); + xname(obj) : cloak_simple_name(obj)); if (obj->greased && !rn2(2)) { pline_The("grease wears off."); @@ -1013,11 +1036,13 @@ STATIC_DCL void NDECL(demonpet); STATIC_OVL void demonpet() { + int i; struct permonst *pm; struct monst *dtmp; pline("Some hell-p has arrived!"); - pm = !rn2(6) ? &mons[ndemon(u.ualign.type)] : youmonst.data; + i = !rn2(6) ? ndemon(u.ualign.type) : NON_PM; + pm = i != NON_PM ? &mons[i] : youmonst.data; if ((dtmp = makemon(pm, u.ux, u.uy, NO_MM_FLAGS)) != 0) (void)tamedog(dtmp, (struct obj *)0); exercise(A_WIS, TRUE); @@ -1069,8 +1094,7 @@ struct attack *mattk; mon_nam(mdef)); else You("seduce %s and %s starts to take off %s clothes.", - mon_nam(mdef), he[pronoun_gender(mdef)], - his[pronoun_gender(mdef)]); + mon_nam(mdef), mhe(mdef), mhis(mdef)); } while ((otmp = mdef->minvent) != 0) { @@ -1078,12 +1102,14 @@ struct attack *mattk; obj_extract_self(otmp); if ((unwornmask = otmp->owornmask) != 0L) { mdef->misc_worn_check &= ~unwornmask; + if (otmp->owornmask & W_WEP) + setmnotwielded(mdef,otmp); otmp->owornmask = 0L; update_mon_intrinsics(mdef, otmp, FALSE); if (otmp == stealoid) /* special message for final item */ pline("%s finishes taking off %s suit.", - Monnam(mdef), his[pronoun_gender(mdef)]); + Monnam(mdef), mhis(mdef)); } /* give the object to the character */ otmp = hold_another_object(otmp, "You steal %s.", @@ -1126,7 +1152,8 @@ register struct attack *mattk; switch(mattk->adtyp) { case AD_STUN: if(!Blind) - pline("%s staggers for a moment.", Monnam(mdef)); + pline("%s %s for a moment.", Monnam(mdef), + makeplural(stagger(mdef->data, "stagger"))); mdef->mstun = 1; /* fall through to next case */ case AD_WERE: /* no effect on monsters */ @@ -1149,6 +1176,7 @@ register struct attack *mattk; case AD_FIRE: if (!Blind) pline("%s is %s!", Monnam(mdef), + mdef->data == &mons[PM_WATER_ELEMENTAL] ? "boiling" : mattk->aatyp == AT_HUGS ? "being roasted" : "on fire"); if (pd == &mons[PM_STRAW_GOLEM] || @@ -1210,11 +1238,29 @@ register struct attack *mattk; tmp = 0; break; case AD_SGLD: +#ifndef GOLDOBJ if (mdef->mgold) { u.ugold += mdef->mgold; mdef->mgold = 0; Your("purse feels heavier."); } +#else + /* This you as a leprechaun, so steal + real gold only, no lesser coins */ + { + struct obj *mongold = findgold(mdef->minvent); + if (mongold) { + obj_extract_self(mongold); + if (merge_choice(invent, mongold) || inv_cnt() < 52) { + addinv(mongold); + Your("purse feels heavier."); + } else { + You("grab %s's gold, but find no room in your knapsack.", mon_nam(mdef)); + dropy(mongold); + } + } + } +#endif exercise(A_DEX, TRUE); tmp = 0; break; @@ -1277,8 +1323,8 @@ register struct attack *mattk; hurtmarmor(mdef, AD_RUST); tmp = 0; break; - case AD_CORRODE: - hurtmarmor(mdef, AD_CORRODE); + case AD_CORR: + hurtmarmor(mdef, AD_CORR); tmp = 0; break; case AD_DCAY: @@ -1310,18 +1356,29 @@ register struct attack *mattk; if (notonhead || !has_head(mdef->data)) { pline("%s doesn't seem harmed.", Monnam(mdef)); tmp = 0; + if (!Unchanging && mdef->data == &mons[PM_GREEN_SLIME]) { + if (!Slimed) { + You("suck in some slime and don't feel very well."); + Slimed = 10L; + } + } break; } if (m_slips_free(mdef, mattk)) break; if ((mdef->misc_worn_check & W_ARMH) && rn2(8)) { pline("%s helmet blocks your attack to %s head.", - s_suffix(Monnam(mdef)), his[pronoun_gender(mdef)]); + s_suffix(Monnam(mdef)), mhis(mdef)); break; } You("eat %s brain!", s_suffix(mon_nam(mdef))); u.uconduct.food++; + if (touch_petrifies(mdef->data) && !Stone_resistance && !Stoned) { + Stoned = 5; + killer_format = KILLED_BY_AN; + delayed_killer = mdef->data->mname; + } if (!vegan(mdef->data)) u.uconduct.unvegan++; if (!vegetarian(mdef->data)) @@ -1387,9 +1444,10 @@ register struct attack *mattk; case AD_SLIM: if (!rn2(4) && mdef->data != &mons[PM_FIRE_VORTEX] && mdef->data != &mons[PM_FIRE_ELEMENTAL] && + mdef->data != &mons[PM_SALAMANDER] && mdef->data != &mons[PM_GREEN_SLIME]) { You("turn %s into slime.", mon_nam(mdef)); - (void) newcham(mdef, &mons[PM_GREEN_SLIME]); + (void) newcham(mdef, &mons[PM_GREEN_SLIME], FALSE); tmp = 0; } break; @@ -1515,7 +1573,8 @@ register struct attack *mattk; for (otmp = mdef->minvent; otmp; otmp = otmp->nobj) (void) snuff_lit(otmp); - if(!touch_petrifies(mdef->data) || Stone_resistance) { + if((!touch_petrifies(mdef->data) || Stone_resistance) && + (Unchanging || mdef->data != &mons[PM_GREEN_SLIME])) { #ifdef LINT /* static char msgbuf[BUFSZ]; */ char msgbuf[BUFSZ]; #else @@ -1554,12 +1613,19 @@ register struct attack *mattk; newuhs(FALSE); xkilled(mdef,2); if (mdef->mhp > 0) { /* monster lifesaved */ - You("hurriedly regurgitate the sizzling in your stomach."); + You("hurriedly regurgitate the sizzling in your %s.", + body_part(STOMACH)); } else { - u.uhunger += mdef->data->cnutrit; + tmp = 1 + (mdef->data->cwt >> 8); + if (corpse_chance(mdef, &youmonst, TRUE) && + !(mvitals[monsndx(mdef->data)].mvflags & + G_NOCORPSE)) { + /* nutrition only if there can be a corpse */ + u.uhunger += (mdef->data->cnutrit+1) / 2; + } else tmp = 0; Sprintf(msgbuf, "You totally digest %s.", mon_nam(mdef)); - if ((tmp = 3 + (mdef->data->cwt >> 6)) != 0) { + if (tmp != 0) { /* setting afternmv = end_engulf is tempting, * but will cause problems if the player is * attacked (which uses his real location) or @@ -1669,7 +1735,7 @@ hmonas(mon, tmp) /* attack monster as a monster. */ register struct monst *mon; register int tmp; { - register struct attack *mattk; + struct attack *mattk, alt_attk; int i, sum[NATTK], hittmp = 0; int nsum = 0; int dhit = 0; @@ -1677,7 +1743,7 @@ register int tmp; for(i = 0; i < NATTK; i++) { sum[i] = 0; - mattk = &(youmonst.data->mattk[i]); + mattk = getmattk(youmonst.data, i, sum, &alt_attk); switch(mattk->aatyp) { case AT_WEAP: use_weapon: @@ -1702,7 +1768,7 @@ register int tmp; if (!known_hitum(mon,&dhit,mattk)) { sum[i] = 2; break; - } else sum[i] = 1; + } else sum[i] = dhit; /* might be a worm that gets cut in half */ if (m_at(u.ux+u.dx, u.uy+u.dy) != mon) return((boolean)(nsum != 0)); /* Do not print "You hit" message, since known_hitum @@ -1804,8 +1870,18 @@ register int tmp; if (mon->data == &mons[PM_SHADE]) Your("attempt to surround %s is harmless.", mon_nam(mon)); - else + else { sum[i]= gulpum(mon,mattk); + if (sum[i] == 2 && + (mon->data->mlet == S_ZOMBIE || + mon->data->mlet == S_MUMMY) && + rn2(5) && + !Sick_resistance) { + You_feel("%ssick.", + (Sick) ? "very " : ""); + mdamageu(mon, rnd(8)); + } + } } else missum(mon, mattk); break; @@ -1889,12 +1965,13 @@ uchar aatyp; mdamageu(mon, tmp); if(!rn2(30)) erode_armor(&youmonst, TRUE); } - if(mhit && !rn2(6)) { + if (mhit) { if (aatyp == AT_KICK) { - if (uarmf) - (void) rust_dmg(uarmf, xname(uarmf), 3, TRUE, &youmonst); - } else if (aatyp == AT_WEAP || aatyp == AT_CLAW || aatyp == AT_MAGC || aatyp == AT_TUCH) - erode_weapon(uwep, TRUE); + if (uarmf && !rn2(6)) + (void)rust_dmg(uarmf, xname(uarmf), 3, TRUE, &youmonst); + } else if (aatyp == AT_WEAP || aatyp == AT_CLAW || + aatyp == AT_MAGC || aatyp == AT_TUCH) + passive_obj(mon, (struct obj*)0, &(ptr->mattk[i])); } exercise(A_STR, FALSE); break; @@ -1918,22 +1995,22 @@ uchar aatyp; break; case AD_RUST: if(mhit && !mon->mcan) { - if (aatyp == AT_KICK) { - if (uarmf) - (void) rust_dmg(uarmf, xname(uarmf), 1, TRUE, &youmonst); - } else if (aatyp == AT_WEAP || aatyp == AT_CLAW || - aatyp == AT_MAGC || aatyp == AT_TUCH) - erode_weapon(uwep, FALSE); + if (aatyp == AT_KICK) { + if (uarmf) + (void)rust_dmg(uarmf, xname(uarmf), 1, TRUE, &youmonst); + } else if (aatyp == AT_WEAP || aatyp == AT_CLAW || + aatyp == AT_MAGC || aatyp == AT_TUCH) + passive_obj(mon, (struct obj*)0, &(ptr->mattk[i])); } break; - case AD_CORRODE: + case AD_CORR: if(mhit && !mon->mcan) { - if (aatyp == AT_KICK) { - if (uarmf) - (void) rust_dmg(uarmf, xname(uarmf), 3, TRUE, &youmonst); - } else if (aatyp == AT_WEAP || aatyp == AT_CLAW || - aatyp == AT_MAGC || aatyp == AT_TUCH) - erode_weapon(uwep, TRUE); + if (aatyp == AT_KICK) { + if (uarmf) + (void)rust_dmg(uarmf, xname(uarmf), 3, TRUE, &youmonst); + } else if (aatyp == AT_WEAP || aatyp == AT_CLAW || + aatyp == AT_MAGC || aatyp == AT_TUCH) + passive_obj(mon, (struct obj*)0, &(ptr->mattk[i])); } break; case AD_MAGM: @@ -1947,17 +2024,16 @@ uchar aatyp; } break; case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */ - { - struct obj *obj = (aatyp == AT_KICK) ? uarmf : - uwep ? uwep : uarmg; - - if (mhit && !mon->mcan && obj) { - if (drain_item(obj) && (obj->known || - obj->oclass == ARMOR_CLASS)) - Your("%s less effective.", aobjnam(obj, "seem")); - } - break; + if (mhit) { + struct obj *obj = (struct obj *)0; + + if (aatyp == AT_KICK) { + obj = uarmf; + if (!obj) break; + } + passive_obj(mon, obj, &(ptr->mattk[i])); } + break; default: break; } @@ -1994,6 +2070,7 @@ uchar aatyp; You("momentarily stiffen."); } else { /* gelatinous cube */ You("are frozen by %s!", mon_nam(mon)); + nomovemsg = 0; /* default: "you can move again" */ nomul(-tmp); exercise(A_DEX, FALSE); } @@ -2049,6 +2126,68 @@ uchar aatyp; return(malive | mhit); } +/* + * Special (passive) attacks on an attacking object by monsters done here. + * Assumes the attack was successful. + */ +void +passive_obj(mon, obj, mattk) +register struct monst *mon; +register struct obj *obj; /* null means pick uwep, uswapwep or uarmg */ +struct attack *mattk; /* null means we find one internally */ +{ + register struct permonst *ptr = mon->data; + register int i; + + /* if caller hasn't specified an object, use uwep, uswapwep or uarmg */ + if (!obj) { + obj = (u.twoweap && uswapwep && !rn2(2)) ? uswapwep : uwep; + if (!obj && mattk->adtyp == AD_ENCH) + obj = uarmg; /* no weapon? then must be gloves */ + if (!obj) return; /* no object to affect */ + } + + /* if caller hasn't specified an attack, find one */ + if (!mattk) { + for(i = 0; ; i++) { + if(i >= NATTK) return; /* no passive attacks */ + if(ptr->mattk[i].aatyp == AT_NONE) break; /* try this one */ + } + mattk = &(ptr->mattk[i]); + } + + switch(mattk->adtyp) { + + case AD_ACID: + if(!rn2(6)) { + erode_obj(obj, TRUE, FALSE); + } + break; + case AD_RUST: + if(!mon->mcan) { + erode_obj(obj, FALSE, FALSE); + } + break; + case AD_CORR: + if(!mon->mcan) { + erode_obj(obj, TRUE, FALSE); + } + break; + case AD_ENCH: + if (!mon->mcan) { + if (drain_item(obj) && carried(obj) && + (obj->known || obj->oclass == ARMOR_CLASS)) { + Your("%s less effective.", aobjnam(obj, "seem")); + } + break; + } + default: + break; + } + + if (carried(obj)) update_inventory(); +} + /* Note: caller must ascertain mtmp is mimicking... */ void stumble_onto_mimic(mtmp) @@ -2149,8 +2288,10 @@ struct obj *otmp; /* source of flash */ if (mtmp->mhp > 0) { if (!flags.mon_moving) setmangry(mtmp); if (tmp < 9 && !mtmp->isshk && rn2(4)) { - mtmp->mflee = 1; - if (rn2(4)) mtmp->mfleetim = rnd(100); + if (rn2(4)) + monflee(mtmp, rnd(100), FALSE, TRUE); + else + monflee(mtmp, 0, FALSE, TRUE); } mtmp->mcansee = 0; mtmp->mblinded = (tmp < 3) ? 0 : rnd(1 + 50/tmp); diff --git a/src/vault.c b/src/vault.c index 617ef2e..51fca67 100644 --- a/src/vault.c +++ b/src/vault.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)vault.c 3.3 96/06/05 */ +/* SCCS Id: @(#)vault.c 3.4 2001/05/24 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -7,6 +7,9 @@ STATIC_DCL struct monst *NDECL(findgd); +#define g_monnam(mtmp) \ + x_monnam(mtmp, ARTICLE_NONE, (char *)0, SUPPRESS_IT, FALSE) + #ifdef OVLB STATIC_DCL boolean FDECL(clear_fcorr, (struct monst *,BOOLEAN_P)); @@ -23,6 +26,8 @@ register boolean forceshow; register int fcx, fcy, fcbeg; register struct monst *mtmp; + if (!on_level(&(EGD(grd)->gdlevel), &u.uz)) return TRUE; + while((fcbeg = EGD(grd)->fcbeg) < EGD(grd)->fcend) { fcx = EGD(grd)->fakecorr[fcbeg].fx; fcy = EGD(grd)->fakecorr[fcbeg].fy; @@ -142,7 +147,9 @@ invault() char buf[BUFSZ]; register int x, y, dd, gx, gy; int lx = 0, ly = 0; - +#ifdef GOLDOBJ + long umoney; +#endif /* first find the goal for the guard */ for(dd = 2; (dd < ROWNO || dd < COLNO); dd++) { for(y = u.uy-dd; y <= u.uy+dd; ly = y, y++) { @@ -233,9 +240,17 @@ incr_radius: ; } reset_faint(); /* if fainted - wake up */ - pline("Suddenly one of the Vault's guards enters!"); + pline("Suddenly one of the Vault's %s enters!", + makeplural(g_monnam(guard))); newsym(guard->mx,guard->my); - if (Strangled || youmonst.data->msound == MS_SILENT) { + if ((youmonst.m_ap_type == M_AP_OBJECT && + youmonst.mappearance == GOLD_PIECE) || u.uundetected) { + /* You're mimicking a pile of gold or you're hidden. */ + pline("Puzzled, %s turns around and leaves.", mhe(guard)); + mongone(guard); + return; + } + if (Strangled || is_silent(youmonst.data)) { verbalize("I'll be back when you're ready to speak to me!"); mongone(guard); return; @@ -271,6 +286,7 @@ incr_radius: ; return; } verbalize("I don't know you."); +#ifndef GOLDOBJ if (!u.ugold && !hidden_gold()) verbalize("Please follow me."); else { @@ -279,6 +295,17 @@ incr_radius: ; verbalize("Most likely all your gold was stolen from this vault."); verbalize("Please drop that gold and follow me."); } +#else + umoney = money_cnt(invent); + if (!umoney && !hidden_gold()) + verbalize("Please follow me."); + else { + if (!umoney) + verbalize("You have hidden money."); + verbalize("Most likely all your money was stolen from this vault."); + verbalize("Please drop that money and follow me."); + } +#endif EGD(guard)->gdx = gx; EGD(guard)->gdy = gy; EGD(guard)->fcbeg = 0; @@ -404,7 +431,7 @@ struct monst *grd; if(movedgold || fixed) { if(in_fcorridor(grd, grd->mx, grd->my) || cansee(grd->mx, grd->my)) - pline_The("guard whispers an incantation."); + pline_The("%s whispers an incantation.", g_monnam(grd)); else You_hear("a distant chant."); if(movedgold) pline("A mysterious force moves the gold into the vault."); @@ -431,8 +458,12 @@ register struct monst *grd; grd_in_vault = *in_rooms(grd->mx, grd->my, VAULT)? TRUE : FALSE; boolean disappear_msg_seen = FALSE, semi_dead = (grd->mhp <= 0); +#ifndef GOLDOBJ register boolean u_carry_gold = ((u.ugold + hidden_gold()) > 0L); - +#else + long umoney = money_cnt(invent); + register boolean u_carry_gold = ((umoney + hidden_gold()) > 0L); +#endif if(!on_level(&(egrd->gdlevel), &u.uz)) return(-1); nx = ny = m = n = 0; if(!u_in_vault && !grd_in_vault) @@ -463,9 +494,16 @@ register struct monst *grd; (u_carry_gold || um_dist(grd->mx, grd->my, 1))) { if(egrd->warncnt == 3) verbalize("I repeat, %sfollow me!", - u_carry_gold ? (!u.ugold ? + u_carry_gold ? ( +#ifndef GOLDOBJ + !u.ugold ? "drop that hidden gold and " : "drop that gold and ") : ""); +#else + !umoney ? + "drop that hidden money and " : + "drop that money and ") : ""); +#endif if(egrd->warncnt == 7) { m = grd->mx; n = grd->my; @@ -490,13 +528,13 @@ register struct monst *grd; newsym(m,n); grd->mpeaceful = 0; letknow: - if(!cansee(grd->mx, grd->my)) + if (!cansee(grd->mx, grd->my) || !mon_visible(grd)) You_hear("the shrill sound of a guard's whistle."); else You(um_dist(grd->mx, grd->my, 2) ? "see an angry %s approaching." : "are confronted by an angry %s.", - l_monnam(grd)); + g_monnam(grd)); return(-1); } else { verbalize("Well, begone."); @@ -512,7 +550,7 @@ register struct monst *grd; !egrd->gddone && !in_fcorridor(grd, u.ux, u.uy) && levl[egrd->fakecorr[0].fx][egrd->fakecorr[0].fy].typ == egrd->fakecorr[0].ftyp) { - pline_The("guard, confused, disappears."); + pline_The("%s, confused, disappears.", g_monnam(grd)); disappear_msg_seen = TRUE; goto cleanup; } @@ -547,8 +585,13 @@ register struct monst *grd; if (m == u.ux && n == u.uy) { struct obj *gold = g_at(m,n); /* Grab the gold from between the hero's feet. */ +#ifndef GOLDOBJ grd->mgold += gold->quan; delobj(gold); +#else + obj_extract_self(gold); + add_to_minv(grd, gold); +#endif newsym(m,n); } else if (m == x && n == y) { mpickgold(grd); /* does a newsym */ @@ -687,7 +730,7 @@ nextnxy: ; if(!semi_dead && (in_fcorridor(grd, u.ux, u.uy) || cansee(x, y))) { if (!disappear_msg_seen) - pline("Suddenly, the guard disappears."); + pline("Suddenly, the %s disappears.", g_monnam(grd)); return(1); } return(-2); @@ -706,15 +749,30 @@ void paygd() { register struct monst *grd = findgd(); +#ifndef GOLDOBJ struct obj *gold; +#else + long umoney = money_cnt(invent); + struct obj *coins, *nextcoins; +#endif int gx,gy; char buf[BUFSZ]; +#ifndef GOLDOBJ if (!u.ugold || !grd) return; +#else + if (!umoney || !grd) return; +#endif if (u.uinvault) { - Your("%ld zorkmid%s goes into the Magic Memory Vault.", - u.ugold, plur(u.ugold)); + Your("%ld %s goes into the Magic Memory Vault.", +#ifndef GOLDOBJ + u.ugold, + currency(u.ugold)); +#else + umoney, + currency(umoney)); +#endif gx = u.ux; gy = u.uy; } else { @@ -731,8 +789,19 @@ paygd() plname, mons[u.umonster].mname); make_grave(gx, gy, buf); } +#ifndef GOLDOBJ place_object(gold = mkgoldobj(u.ugold), gx, gy); stackobj(gold); +#else + for (coins = invent; coins; coins = nextcoins) { + nextcoins = coins->nobj; + if (objects[coins->otyp].oc_class == GOLD_CLASS) { + freeinv(coins); + place_object(coins, gx, gy); + stackobj(coins); + } + } +#endif mongone(grd); } diff --git a/src/version.c b/src/version.c index fed52cd..02f577e 100644 --- a/src/version.c +++ b/src/version.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)version.c 3.3 1999/12/01 */ +/* SCCS Id: @(#)version.c 3.4 1999/12/01 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -68,7 +68,7 @@ boolean complain; version_data->entity_count != VERSION_SANITY1 || version_data->struct_sizes != VERSION_SANITY2) { if (complain) - pline("Configuration incompatability for file \"%s\".", + pline("Configuration incompatibility for file \"%s\".", filename); return FALSE; } diff --git a/src/vision.c b/src/vision.c index 0adda20..b807bea 100644 --- a/src/vision.c +++ b/src/vision.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)vision.c 3.3 99/02/18 */ +/* SCCS Id: @(#)vision.c 3.4 1999/02/18 */ /* Copyright (c) Dean Luick, with acknowledgements to Dave Cohrs, 1990. */ /* NetHack may be freely redistributed. See license for details. */ @@ -242,6 +242,7 @@ vision_reset() } } + iflags.vision_inited = 1; /* vision is ready */ vision_full_recalc = 1; /* we want to run vision_recalc() */ } @@ -510,7 +511,7 @@ vision_recalc(control) int oldseenv; /* previous seenv value */ vision_full_recalc = 0; /* reset flag */ - if (in_mklev) return; + if (in_mklev || !iflags.vision_inited) return; #ifdef GCC_WARN row = 0; @@ -725,12 +726,13 @@ vision_recalc(control) /* * We see this position because it is lit. */ - if (IS_DOOR(lev->typ) && !viz_clear[row][col]) { + if ((IS_DOOR(lev->typ) || lev->typ == SDOOR || + IS_WALL(lev->typ)) && !viz_clear[row][col]) { /* - * Make sure doors, boulders or mimics don't show up + * Make sure doors, walls, boulders or mimics don't show up * at the end of dark hallways. We do this by checking * the adjacent position. If it is lit, then we can see - * the door, otherwise we can't. + * the door or wall, otherwise we can't. */ dx = u.ux - col; dx = sign(dx); flev = &(levl[col+dx][row+dy]); @@ -793,7 +795,13 @@ vision_recalc(control) colbump[u.ux] = colbump[u.ux+1] = 0; skip: - newsym(u.ux,u.uy); /* Make sure the hero shows up! */ + /* This newsym() caused a crash delivering msg about failure to open + * dungeon file init_dungeons() -> panic() -> done(11) -> + * vision_recalc(2) -> newsym() -> crash! u.ux and u.uy are 0 and + * program_state.panicking == 1 under those circumstances + */ + if (!program_state.panicking) + newsym(u.ux, u.uy); /* Make sure the hero shows up! */ /* Set the new min and max pointers. */ viz_rmin = next_rmin; diff --git a/src/weapon.c b/src/weapon.c index cc79fd0..1c94bd8 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)weapon.c 3.3 2000/01/22 */ +/* SCCS Id: @(#)weapon.c 3.4 2002/02/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -26,6 +26,8 @@ #define PN_ESCAPE_SPELL (-13) #define PN_MATTER_SPELL (-14) +STATIC_DCL void FDECL(give_may_advance_msg, (int)); + #ifndef OVLB STATIC_DCL NEARDATA const short skill_names_indices[]; @@ -93,6 +95,8 @@ int skill; #endif /* OVLB */ STATIC_DCL boolean FDECL(can_advance, (int, BOOLEAN_P)); +STATIC_DCL boolean FDECL(could_advance, (int)); +STATIC_DCL boolean FDECL(peaked_skill, (int)); STATIC_DCL int FDECL(slots_required, (int)); #ifdef OVL1 @@ -181,6 +185,7 @@ struct monst *mon; * Second edition AD&D came out a few years later; luckily it used the same * table. As of this writing (1999), third edition is in progress but not * released. Let's see if the weapon table stays the same. --KAA + * October 2000: It didn't. Oh, well. */ /* @@ -507,12 +512,15 @@ register struct monst *mtmp; /* only strong monsters can wield big (esp. long) weapons */ /* big weapon is basically the same as bimanual */ /* all monsters can wield the remaining weapons */ - for (i = 0; i < SIZE(hwep); i++) + for (i = 0; i < SIZE(hwep); i++) { + if (hwep[i] == CORPSE && !(mtmp->misc_worn_check & W_ARMG)) + continue; if (((strong && !wearing_shield) || !objects[hwep[i]].oc_bimanual) && (objects[hwep[i]].oc_material != SILVER || !hates_silver(mtmp->data))) Oselect(hwep[i]); + } /* failure */ return (struct obj *)0; @@ -538,7 +546,7 @@ register struct monst *mon; return; } if (!attacktype(mon->data, AT_WEAP)) { - mw_tmp->owornmask &= ~W_WEP; + setmnotwielded(mon, mw_tmp); MON_NOWEP(mon); mon->weapon_check = NO_WEAPON_WANTED; obj_extract_self(obj); @@ -565,7 +573,8 @@ register struct monst *mon; * polymorphed into little monster. But it's not quite clear how to * handle this anyway.... */ - mon->weapon_check = NEED_WEAPON; + if (!(mw_tmp->cursed && mon->weapon_check == NO_WEAPON_WANTED)) + mon->weapon_check = NEED_WEAPON; } /* Let a monster try to wield a weapon, based on mon->weapon_check. @@ -615,8 +624,8 @@ register struct monst *mon; if (bimanual(mw_tmp)) mon_hand = makeplural(mon_hand); Sprintf(welded_buf, "%s welded to %s %s", - (mw_tmp->quan == 1L) ? "is" : "are", - his[pronoun_gender(mon)], mon_hand); + otense(mw_tmp, "are"), + mhis(mon), mon_hand); if (obj->otyp == PICK_AXE) { pline("Since %s weapon%s %s,", @@ -637,18 +646,24 @@ register struct monst *mon; return 1; } mon->mw = obj; /* wield obj */ - if (mw_tmp) mw_tmp->owornmask &= ~W_WEP; + setmnotwielded(mon, mw_tmp); mon->weapon_check = NEED_WEAPON; if (canseemon(mon)) { - pline("%s wields %s!", Monnam(mon), doname(obj)); - if (obj->cursed && obj->otyp != CORPSE) { - pline("%s %s to %s %s!", - The(xname(obj)), - (obj->quan == 1L) ? "welds itself" - : "weld themselves", - s_suffix(mon_nam(mon)), mbodypart(mon,HAND)); - obj->bknown = 1; - } + pline("%s wields %s!", Monnam(mon), doname(obj)); + if (obj->cursed && obj->otyp != CORPSE) { + pline("%s %s to %s %s!", + Tobjnam(obj, "weld"), + is_plural(obj) ? "themselves" : "itself", + s_suffix(mon_nam(mon)), mbodypart(mon,HAND)); + obj->bknown = 1; + } + } + if (artifact_light(obj) && !obj->lamplit) { + begin_burn(obj, FALSE); + if (canseemon(mon)) + pline("%s brilliantly in %s %s!", + Tobjnam(obj, "glow"), + s_suffix(mon_nam(mon)), mbodypart(mon,HAND)); } obj->owornmask = W_WEP; return 1; @@ -750,6 +765,7 @@ int skill; } /* return true if this skill can be advanced */ +/*ARGSUSED*/ STATIC_OVL boolean can_advance(skill, speedy) int skill; @@ -766,6 +782,30 @@ boolean speedy; && u.weapon_slots >= slots_required(skill))); } +/* return true if this skill could be advanced if more slots were available */ +STATIC_OVL boolean +could_advance(skill) +int skill; +{ + return !P_RESTRICTED(skill) + && P_SKILL(skill) < P_MAX_SKILL(skill) && ( + (P_ADVANCE(skill) >= + (unsigned) practice_needed_to_advance(P_SKILL(skill)) + && u.skills_advanced < P_SKILL_LIMIT)); +} + +/* return true if this skill has reached its maximum and there's been enough + practice to become eligible for the next step if that had been possible */ +STATIC_OVL boolean +peaked_skill(skill) +int skill; +{ + return !P_RESTRICTED(skill) + && P_SKILL(skill) >= P_MAX_SKILL(skill) && ( + (P_ADVANCE(skill) >= + (unsigned) practice_needed_to_advance(P_SKILL(skill)))); +} + STATIC_OVL void skill_advance(skill) int skill; @@ -775,8 +815,8 @@ int skill; u.skill_record[u.skills_advanced++] = skill; /* subtly change the advance message to indicate no more advancement */ You("are now %s skilled in %s.", - P_SKILL(skill) >= P_MAX_SKILL(skill) ? "most" : "more", - P_NAME(skill)); + P_SKILL(skill) >= P_MAX_SKILL(skill) ? "most" : "more", + P_NAME(skill)); } static struct skill_range { @@ -799,14 +839,15 @@ static struct skill_range { int enhance_weapon_skill() { - int pass, i, n, len, longest, to_advance; - char buf[BUFSZ], buf2[BUFSZ]; + int pass, i, n, len, longest, + to_advance, eventually_advance, maxxed_cnt; + char buf[BUFSZ], sklnambuf[BUFSZ]; + const char *prefix; menu_item *selected; anything any; winid win; boolean speedy = FALSE; - #ifdef WIZARD if (wizard && yn("Advance skills without practice?") == 'y') speedy = TRUE; @@ -814,15 +855,44 @@ enhance_weapon_skill() do { /* find longest available skill name, count those that can advance */ - for (longest = 0, to_advance = 0, i = 0; i < P_NUM_SKILLS; i++) { - if (!P_RESTRICTED(i) && (len = strlen(P_NAME(i))) > longest) + to_advance = eventually_advance = maxxed_cnt = 0; + for (longest = 0, i = 0; i < P_NUM_SKILLS; i++) { + if (P_RESTRICTED(i)) continue; + if ((len = strlen(P_NAME(i))) > longest) longest = len; if (can_advance(i, speedy)) to_advance++; + else if (could_advance(i)) eventually_advance++; + else if (peaked_skill(i)) maxxed_cnt++; } win = create_nhwindow(NHW_MENU); start_menu(win); + /* start with a legend if any entries will be annotated + with "*" or "#" below */ + if (eventually_advance > 0 || maxxed_cnt > 0) { + any.a_int = 0; + if (eventually_advance > 0) { + Sprintf(buf, + "(Skill%s flagged by \"*\" may be enhanced %s.)", + plur(eventually_advance), + (u.ulevel < MAXULEV) ? + "when you're more experienced" : + "if skill slots become available"); + add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, + buf, MENU_UNSELECTED); + } + if (maxxed_cnt > 0) { + Sprintf(buf, + "(Skill%s flagged by \"#\" cannot be enhanced any further.)", + plur(maxxed_cnt)); + add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, + buf, MENU_UNSELECTED); + } + add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, + "", MENU_UNSELECTED); + } + /* List the skills, making ones that could be advanced selectable. List the miscellaneous skills first. Possible future enhancement: list spell skills before @@ -838,32 +908,55 @@ enhance_weapon_skill() if (P_RESTRICTED(i)) continue; /* - * Sigh, this assumes a monospaced font. + * Sigh, this assumes a monospaced font unless + * iflags.menu_tab_sep is set in which case it puts + * tabs between columns. * The 12 is the longest skill level name. * The " " is room for a selection letter and dash, "a - ". */ -#ifdef WIZARD - if (wizard) - Sprintf(buf2, " %s%-*s %-12s %4d(%4d)", - to_advance == 0 || can_advance(i, speedy) ? "" : " " , - longest, P_NAME(i), - skill_level_name(i, buf), - P_ADVANCE(i), practice_needed_to_advance(P_SKILL(i))); + if (can_advance(i, speedy)) + prefix = ""; /* will be preceded by menu choice */ + else if (could_advance(i)) + prefix = " * "; + else if (peaked_skill(i)) + prefix = " # "; else + prefix = (to_advance + eventually_advance + + maxxed_cnt > 0) ? " " : ""; + (void) skill_level_name(i, sklnambuf); +#ifdef WIZARD + if (wizard) { + if (!iflags.menu_tab_sep) + Sprintf(buf, " %s%-*s %-12s %5d(%4d)", + prefix, longest, P_NAME(i), sklnambuf, + P_ADVANCE(i), + practice_needed_to_advance(P_SKILL(i))); + else + Sprintf(buf, " %s%s\t%s\t%5d(%4d)", + prefix, P_NAME(i), sklnambuf, + P_ADVANCE(i), + practice_needed_to_advance(P_SKILL(i))); + } else #endif - Sprintf(buf2, " %s %-*s [%s]", - to_advance == 0 || can_advance(i, speedy) ? "" : " ", - longest, P_NAME(i), - skill_level_name(i, buf)); - + { + if (!iflags.menu_tab_sep) + Sprintf(buf, " %s %-*s [%s]", + prefix, longest, P_NAME(i), sklnambuf); + else + Sprintf(buf, " %s%s\t[%s]", + prefix, P_NAME(i), sklnambuf); + } any.a_int = can_advance(i, speedy) ? i+1 : 0; - add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf2, MENU_UNSELECTED); + add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, + buf, MENU_UNSELECTED); } - Strcpy(buf, to_advance ? "Pick a skill to advance:" : "Current skills:"); + Strcpy(buf, (to_advance > 0) ? "Pick a skill to advance:" : + "Current skills:"); #ifdef WIZARD - if (wizard && !speedy) Sprintf(eos(buf), " (%d slot%s available)", - u.weapon_slots, plur(u.weapon_slots)); + if (wizard && !speedy) + Sprintf(eos(buf), " (%d slot%s available)", + u.weapon_slots, plur(u.weapon_slots)); #endif end_menu(win, buf); n = select_menu(win, to_advance ? PICK_ONE : PICK_NONE, &selected); @@ -991,10 +1084,13 @@ int weapon_hit_bonus(weapon) struct obj *weapon; { - int type, skill, bonus = 0; + int type, wep_type, skill, bonus = 0; static const char bad_skill[] = "weapon_hit_bonus: bad skill %d"; - type = u.twoweap ? P_TWO_WEAPON_COMBAT : weapon_type(weapon); + wep_type = weapon_type(weapon); + /* use two weapon skill only if attacking with one of the wielded weapons */ + type = (u.twoweap && (weapon == uwep || weapon == uswapwep)) ? + P_TWO_WEAPON_COMBAT : wep_type; if (type == P_NONE) { bonus = 0; } else if (type <= P_LAST_WEAPON) { @@ -1008,9 +1104,9 @@ struct obj *weapon; } } else if (type == P_TWO_WEAPON_COMBAT) { skill = P_SKILL(P_TWO_WEAPON_COMBAT); - if (P_SKILL(weapon->otyp) < skill) skill = P_SKILL(weapon->otyp); + if (P_SKILL(wep_type) < skill) skill = P_SKILL(wep_type); switch (skill) { - default: impossible(bad_skill, P_SKILL(type)); /* fall through */ + default: impossible(bad_skill, skill); /* fall through */ case P_ISRESTRICTED: case P_UNSKILLED: bonus = -9; break; case P_BASIC: bonus = -7; break; @@ -1018,8 +1114,18 @@ struct obj *weapon; case P_EXPERT: bonus = -3; break; } } else if (type == P_BARE_HANDED_COMBAT) { - /* restricted == 0 */ - bonus = ((P_SKILL(type) + 1) * (martial_bonus() ? 2 : 1)) / 2; + /* + * b.h. m.a. + * unskl: +1 n/a + * basic: +1 +3 + * skild: +2 +4 + * exprt: +2 +5 + * mastr: +3 +6 + * grand: +3 +7 + */ + bonus = P_SKILL(type); + bonus = max(bonus,P_UNSKILLED) - 1; /* unskilled => 0 */ + bonus = ((bonus + 2) * (martial_bonus() ? 2 : 1)) / 2; } #ifdef STEED @@ -1047,9 +1153,12 @@ int weapon_dam_bonus(weapon) struct obj *weapon; { - int type, skill, bonus = 0; + int type, wep_type, skill, bonus = 0; - type = u.twoweap ? P_TWO_WEAPON_COMBAT : weapon_type(weapon); + wep_type = weapon_type(weapon); + /* use two weapon skill only if attacking with one of the wielded weapons */ + type = (u.twoweap && (weapon == uwep || weapon == uswapwep)) ? + P_TWO_WEAPON_COMBAT : wep_type; if (type == P_NONE) { bonus = 0; } else if (type <= P_LAST_WEAPON) { @@ -1064,7 +1173,7 @@ struct obj *weapon; } } else if (type == P_TWO_WEAPON_COMBAT) { skill = P_SKILL(P_TWO_WEAPON_COMBAT); - if (P_SKILL(weapon->otyp) < skill) skill = P_SKILL(weapon->otyp); + if (P_SKILL(wep_type) < skill) skill = P_SKILL(wep_type); switch (skill) { default: case P_ISRESTRICTED: @@ -1074,7 +1183,18 @@ struct obj *weapon; case P_EXPERT: bonus = 1; break; } } else if (type == P_BARE_HANDED_COMBAT) { - bonus = (P_SKILL(type) * (martial_bonus() ? 3 : 1)) / 2; + /* + * b.h. m.a. + * unskl: 0 n/a + * basic: +1 +3 + * skild: +1 +4 + * exprt: +2 +6 + * mastr: +2 +7 + * grand: +3 +9 + */ + bonus = P_SKILL(type); + bonus = max(bonus,P_UNSKILLED) - 1; /* unskilled => 0 */ + bonus = ((bonus + 1) * (martial_bonus() ? 3 : 1)) / 2; } #ifdef STEED @@ -1165,6 +1285,22 @@ struct def_skill *class_skill; } } +void +setmnotwielded(mon,obj) +register struct monst *mon; +register struct obj *obj; +{ + if (!obj) return; + if (artifact_light(obj) && obj->lamplit) { + end_burn(obj, FALSE); + if (canseemon(mon)) + pline("%s in %s %s %s glowing.", The(xname(obj)), + s_suffix(mon_nam(mon)), mbodypart(mon,HAND), + otense(obj, "stop")); + } + obj->owornmask &= ~W_WEP; +} + #endif /* OVLB */ /*weapon.c*/ diff --git a/src/were.c b/src/were.c index b7b4874..97c9111 100644 --- a/src/were.c +++ b/src/were.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)were.c 3.3 97/05/25 */ +/* SCCS Id: @(#)were.c 3.4 1997/05/25 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -82,7 +82,7 @@ register struct monst *mon; /* regenerate by 1/4 of the lost hit points */ mon->mhp += (mon->mhpmax - mon->mhp) / 4; newsym(mon->mx,mon->my); - mon_break_armor(mon); + mon_break_armor(mon, FALSE); possibly_unwield(mon); } diff --git a/src/wield.c b/src/wield.c index 38d643b..c78d537 100644 --- a/src/wield.c +++ b/src/wield.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)wield.c 3.3 2000/06/04 */ +/* SCCS Id: @(#)wield.c 3.4 2001/12/23 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -50,7 +50,7 @@ */ -static int FDECL(ready_weapon, (struct obj *)); +STATIC_DCL int FDECL(ready_weapon, (struct obj *)); /* elven weapons vibrate warningly when enchanted beyond a limit */ #define is_elven_weapon(optr) ((optr)->otyp == ELVEN_ARROW\ @@ -84,11 +84,6 @@ static int FDECL(ready_weapon, (struct obj *)); * 5. Emptying the slot, by passing a null object. NEVER pass * zeroobj! * - * Note: setuwep() with a null obj, and uwepgone(), are NOT the same! - * Sometimes unwielding a weapon can kill you, and lifesaving will then - * put it back into your hand. If lifesaving is permitted to do this, - * use setwuep((struct obj *)0); otherwise use uwepgone(). - * * If the item is being moved from another slot, it is the caller's * responsibility to handle that. It's also the caller's responsibility * to print the appropriate messages. @@ -97,8 +92,17 @@ void setuwep(obj) register struct obj *obj; { + struct obj *olduwep = uwep; + if (obj == uwep) return; /* necessary to not set unweapon */ + /* This message isn't printed in the caller because it happens + * *whenever* Sunsword is unwielded, from whatever cause. + */ setworn(obj, W_WEP); + if (uwep == obj && artifact_light(olduwep) && olduwep->lamplit) { + end_burn(olduwep, FALSE); + if (!Blind) pline("%s glowing.", Tobjnam(olduwep, "stop")); + } /* Note: Explicitly wielding a pick-axe will not give a "bashing" * message. Wielding one via 'a'pplying it will. * 3.2.2: Wielding arbitrary objects will give bashing message too. @@ -106,14 +110,17 @@ register struct obj *obj; if (obj) { unweapon = (obj->oclass == WEAPON_CLASS) ? is_launcher(obj) || is_ammo(obj) || - is_missile(obj) || is_pole(obj) : - !is_weptool(obj); + is_missile(obj) || (is_pole(obj) +#ifdef STEED + && !u.usteed +#endif + ) : !is_weptool(obj); } else unweapon = TRUE; /* for "bare hands" message */ update_inventory(); } -static int +STATIC_OVL int ready_weapon(wep) struct obj *wep; { @@ -174,6 +181,12 @@ struct obj *wep; /* KMH -- Talking artifacts are finally implemented */ arti_speak(wep); + if (artifact_light(wep) && !wep->lamplit) { + begin_burn(wep, FALSE); + if (!Blind) + pline("%s to glow brilliantly!", Tobjnam(wep, "begin")); + } + #if 0 /* we'll get back to this someday, but it's not balanced yet */ if (Race_if(PM_ELF) && !wep->oartifact && @@ -227,7 +240,7 @@ static NEARDATA const char bullets[] = /* (note: different from dothrow.c) */ int dowield() { - register struct obj *wep; + register struct obj *wep, *oldwep; int result; /* May we attempt this? */ @@ -267,9 +280,10 @@ dowield() } /* Set your new primary weapon */ - if (flags.pushweapon && uwep) - setuswapwep(uwep); + oldwep = uwep; result = ready_weapon(wep); + if (flags.pushweapon && oldwep && uwep != oldwep) + setuswapwep(oldwep); untwoweapon(); return (result); @@ -355,7 +369,7 @@ dowieldquiver() } else if (newquiver == uwep) { /* Prevent accidentally readying the main weapon */ pline("%s already being used as a weapon!", - (uwep->quan == 1L) ? "That is" : "They are"); + !is_plural(uwep) ? "That is" : "They are"); return(0); } else if (newquiver->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL #ifdef STEED @@ -393,23 +407,23 @@ can_twoweapon() struct obj *otmp; #define NOT_WEAPON(obj) (!is_weptool(obj) && obj->oclass != WEAPON_CLASS) - if (Upolyd) - You("can only use two weapons in your normal form."); + if (!could_twoweap(youmonst.data)) + You_cant("use two weapons in your current form."); else if (!uwep || !uswapwep) Your("%s%s%s empty.", uwep ? "left " : uswapwep ? "right " : "", body_part(HAND), (!uwep && !uswapwep) ? "s are" : " is"); else if (NOT_WEAPON(uwep) || NOT_WEAPON(uswapwep)) { otmp = NOT_WEAPON(uwep) ? uwep : uswapwep; pline("%s %s.", Yname2(otmp), - (otmp->quan) > 1L ? "aren't weapons" : "isn't a weapon"); + is_plural(otmp) ? "aren't weapons" : "isn't a weapon"); } else if (bimanual(uwep) || bimanual(uswapwep)) { otmp = bimanual(uwep) ? uwep : uswapwep; pline("%s isn't one-handed.", Yname2(otmp)); } else if (uarms) You_cant("use two weapons while wearing a shield."); else if (uswapwep->oartifact) - pline("%s resists being held second to another weapon!", - Yname2(uswapwep)); + pline("%s %s being held second to another weapon!", + Yname2(uswapwep), otense(uswapwep, "resist")); else if (!uarmg && !Stone_resistance && (uswapwep->otyp == CORPSE && touch_petrifies(&mons[uswapwep->corpsenm]))) { char kbuf[BUFSZ]; @@ -419,13 +433,14 @@ can_twoweapon() Sprintf(kbuf, "%s corpse", an(mons[uswapwep->corpsenm].mname)); instapetrify(kbuf); } else if (Glib || uswapwep->cursed) { + char str[BUFSZ]; struct obj *obj = uswapwep; - Your("%s from your %s!", aobjnam(obj, "slip"), - makeplural(body_part(HAND))); + /* Avoid trashing makeplural's static buffer */ + Strcpy(str, makeplural(body_part(HAND))); + Your("%s from your %s!", aobjnam(obj, "slip"), str); if (!Glib) obj->bknown = TRUE; - setuswapwep((struct obj *) 0); dropx(obj); } else return (TRUE); @@ -464,6 +479,10 @@ void uwepgone() { if (uwep) { + if (artifact_light(uwep) && uwep->lamplit) { + end_burn(uwep, FALSE); + if (!Blind) pline("%s glowing.", Tobjnam(uwep, "stop")); + } setworn((struct obj *)0, W_WEP); unweapon = TRUE; update_inventory(); @@ -499,31 +518,35 @@ untwoweapon() return; } -/* Maybe rust weapon, or corrode it if acid damage is called for */ +/* Maybe rust object, or corrode it if acid damage is called for */ void -erode_weapon(target, acid_dmg) -struct obj *target; +erode_obj(target, acid_dmg, fade_scrolls) +struct obj *target; /* object (e.g. weapon or armor) to erode */ boolean acid_dmg; +boolean fade_scrolls; { int erosion; struct monst *victim; boolean vismon; + boolean visobj; if (!target) return; - if (!carried(target) && !mcarried(target)) - panic("erode whose weapon? (%d)", (int)target->where); - victim = carried(target) ? &youmonst : target->ocarry; - vismon = (victim != &youmonst) && canseemon(victim); + victim = carried(target) ? &youmonst : + mcarried(target) ? target->ocarry : (struct monst *)0; + vismon = victim && (victim != &youmonst) && canseemon(victim); + visobj = !victim && cansee(bhitpos.x, bhitpos.y); /* assume thrown */ erosion = acid_dmg ? target->oeroded2 : target->oeroded; if (target->greased) { - grease_protect(target,(char *)0,FALSE,victim); + grease_protect(target,(char *)0,victim); } else if (target->oclass == SCROLL_CLASS) { + if(fade_scrolls && target->otyp != SCR_BLANK_PAPER #ifdef MAIL - if(target->otyp != SCR_MAIL) + && target->otyp != SCR_MAIL #endif + ) { if (!Blind) { if (victim == &youmonst) @@ -531,6 +554,8 @@ boolean acid_dmg; else if (vismon) pline("%s's %s.", Monnam(victim), aobjnam(target, "fade")); + else if (visobj) + pline_The("%s.", aobjnam(target, "fade")); } target->otyp = SCR_BLANK_PAPER; target->spe = 0; @@ -543,6 +568,7 @@ boolean acid_dmg; else if (vismon) pline("%s's %s not affected.", Monnam(victim), aobjnam(target, "are")); + /* no message if not carried */ } if (target->oerodeproof) target->rknown = TRUE; } else if (erosion < MAX_ERODE) { @@ -555,6 +581,11 @@ boolean acid_dmg; aobjnam(target, acid_dmg ? "corrode" : "rust"), erosion+1 == MAX_ERODE ? " completely" : erosion ? " further" : ""); + else if (visobj) + pline_The("%s%s!", + aobjnam(target, acid_dmg ? "corrode" : "rust"), + erosion+1 == MAX_ERODE ? " completely" : + erosion ? " further" : ""); if (acid_dmg) target->oeroded2++; else @@ -569,6 +600,10 @@ boolean acid_dmg; pline("%s's %s completely %s.", Monnam(victim), aobjnam(target, "look"), acid_dmg ? "corroded" : "rusty"); + else if (visobj) + pline_The("%s completely %s.", + aobjnam(target, "look"), + acid_dmg ? "corroded" : "rusty"); } } } @@ -615,9 +650,9 @@ register int amount; if(((uwep->spe > 5 && amount >= 0) || (uwep->spe < -5 && amount < 0)) && rn2(3)) { if (!Blind) - Your("%s %s for a while and then evaporate%s.", + Your("%s %s for a while and then %s.", aobjnam(uwep, "violently glow"), color, - uwep->quan == 1L ? "s" : ""); + otense(uwep, "evaporate")); else Your("%s.", aobjnam(uwep, "evaporate")); @@ -674,7 +709,7 @@ register struct obj *obj; savewornmask = obj->owornmask; Your("%s %s welded to your %s!", - xname(obj), (obj->quan == 1L) ? "is" : "are", + xname(obj), otense(obj, "are"), bimanual(obj) ? (const char *)makeplural(body_part(HAND)) : body_part(HAND)); obj->owornmask = savewornmask; diff --git a/src/windows.c b/src/windows.c index a18fba2..3c59080 100644 --- a/src/windows.c +++ b/src/windows.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)windows.c 3.3 96/05/19 */ +/* SCCS Id: @(#)windows.c 3.4 1996/05/19 */ /* Copyright (c) D. Cohrs, 1993. */ /* NetHack may be freely redistributed. See license for details. */ @@ -37,6 +37,9 @@ extern struct window_procs win32_procs; #include "winGnome.h" extern struct window_procs Gnome_procs; #endif +#ifdef MSWIN_GRAPHICS +extern struct window_procs mswin_procs; +#endif STATIC_DCL void FDECL(def_raw_print, (const char *s)); @@ -74,6 +77,9 @@ struct win_choices { #endif #ifdef GNOME_GRAPHICS { &Gnome_procs, 0 }, +#endif +#ifdef MSWIN_GRAPHICS + { &mswin_procs, 0 }, #endif { 0, 0 } /* must be last */ }; @@ -126,4 +132,15 @@ const char *mesg; return 0; } +/*ARGSUSED*/ +void +genl_preference_update(pref) +const char *pref; +{ + /* window ports are expected to provide + their own preference update routine + for the preference capabilities that + they support. + Just return in this genl one. */ +} /*windows.c*/ diff --git a/src/wizard.c b/src/wizard.c index af36d55..c9d00a0 100644 --- a/src/wizard.c +++ b/src/wizard.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)wizard.c 3.3 99/03/29 */ +/* SCCS Id: @(#)wizard.c 3.4 2001/12/06 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -64,11 +64,11 @@ amulet() if(ttmp->ttyp == MAGIC_PORTAL) { int du = distu(ttmp->tx, ttmp->ty); if (du <= 9) - pline("%s feels hot!", The(xname(amu))); + pline("%s hot!", Tobjnam(amu, "feel")); else if (du <= 64) - pline("%s feels very warm.", The(xname(amu))); + pline("%s very warm.", Tobjnam(amu, "feel")); else if (du <= 144) - pline("%s feels warm.", The(xname(amu))); + pline("%s warm.", Tobjnam(amu, "feel")); /* else, the amulet feels normal */ break; } @@ -240,7 +240,12 @@ strategy(mtmp) { long strat, dstrat; - if(!is_covetous(mtmp->data)) return(STRAT_NONE); + if (!is_covetous(mtmp->data) || + /* perhaps a shopkeeper has been polymorphed into a master + lich; we don't want it teleporting to the stairs to heal + because that will leave its shop untended */ + (mtmp->isshk && inhishop(mtmp))) + return STRAT_NONE; switch((mtmp->mhp*3)/mtmp->mhpmax) { /* 0-3 */ @@ -336,28 +341,32 @@ tactics(mtmp) return(0); } if(where == STRAT_GROUND) { - if(!MON_AT(tx, ty) || (mtmp->mx == tx && mtmp->my == ty)) { - /* teleport to it and pick it up */ - rloc_to(mtmp, tx, ty); /* clean old pos */ - - if ((otmp = on_ground(which_arti(targ))) != 0) { - if (cansee(mtmp->mx, mtmp->my)) - pline("%s picks up %s.", - Monnam(mtmp), - (distu(mtmp->my, mtmp->my) <= 5) ? - doname(otmp) : distant_name(otmp, doname)); - obj_extract_self(otmp); - (void) mpickobj(mtmp, otmp); - return(1); - } else return(0); - } + if(!MON_AT(tx, ty) || (mtmp->mx == tx && mtmp->my == ty)) { + /* teleport to it and pick it up */ + rloc_to(mtmp, tx, ty); /* clean old pos */ + + if ((otmp = on_ground(which_arti(targ))) != 0) { + if (cansee(mtmp->mx, mtmp->my)) + pline("%s picks up %s.", + Monnam(mtmp), + (distu(mtmp->my, mtmp->my) <= 5) ? + doname(otmp) : distant_name(otmp, doname)); + obj_extract_self(otmp); + (void) mpickobj(mtmp, otmp); + return(1); + } else return(0); + } else { + /* a monster is standing on it - cause some trouble */ + if (!rn2(5)) mnexto(mtmp); + return(0); + } } else { /* a monster has it - 'port beside it. */ (void) mnearto(mtmp, tx, ty, TRUE); return(0); } } } - /* NOTREACHED */ + /*NOTREACHED*/ return(0); } @@ -405,33 +414,44 @@ pick_nasty() /* create some nasty monsters, aligned or neutral with the caster */ /* a null caster defaults to a chaotic caster (e.g. the wizard) */ -void +int nasty(mcast) struct monst *mcast; { register struct monst *mtmp; register int i, j, tmp; int castalign = (mcast ? mcast->data->maligntyp : -1); + coord bypos; + int count=0; - if(!rn2(10) && Inhell) msummon(&mons[PM_WIZARD_OF_YENDOR]); - else { + if(!rn2(10) && Inhell) { + msummon(&mons[PM_WIZARD_OF_YENDOR]); + count++; + } else { tmp = (u.ulevel > 3) ? u.ulevel/3 : 1; /* just in case -- rph */ - + /* if we don't have a casting monster, the nasties appear around you */ + bypos.x = u.ux; + bypos.y = u.uy; for(i = rnd(tmp); i > 0; --i) for(j=0; j<20; j++) { + if (mcast && + !enexto(&bypos, mcast->mux, mcast->muy, mcast->data)) + continue; if ((mtmp = makemon(&mons[pick_nasty()], - u.ux, u.uy, NO_MM_FLAGS)) != 0) { + bypos.x, bypos.y, NO_MM_FLAGS)) != 0) { mtmp->msleeping = mtmp->mpeaceful = mtmp->mtame = 0; set_malign(mtmp); } else /* GENOD? */ mtmp = makemon((struct permonst *)0, - u.ux, u.uy, NO_MM_FLAGS); + bypos.x, bypos.y, NO_MM_FLAGS); if(mtmp && (mtmp->data->maligntyp == 0 || - sgn(mtmp->data->maligntyp) == sgn(castalign)) ) + sgn(mtmp->data->maligntyp) == sgn(castalign)) ) { + count++; break; + } } } - return; + return count; } /* Let's resurrect the wizard, for some unexpected fun. */ @@ -501,7 +521,7 @@ intervene() break; case 3: aggravate(); break; - case 4: nasty((struct monst *)0); + case 4: (void)nasty((struct monst *)0); break; case 5: resurrect(); break; diff --git a/src/worm.c b/src/worm.c index a8cd406..43db7aa 100644 --- a/src/worm.c +++ b/src/worm.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)worm.c 3.3 95/01/28 */ +/* SCCS Id: @(#)worm.c 3.4 1995/01/28 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/src/worn.c b/src/worn.c index 5c55c79..99b4967 100644 --- a/src/worn.c +++ b/src/worn.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)worn.c 3.3 2000/02/19 */ +/* SCCS Id: @(#)worn.c 3.4 2002/02/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -6,6 +6,7 @@ STATIC_DCL void FDECL(m_lose_armor, (struct monst *,struct obj *)); STATIC_DCL void FDECL(m_dowear_type, (struct monst *,long,BOOLEAN_P)); +STATIC_DCL int FDECL(extra_pref, (struct monst *, struct obj *)); const struct worn { long w_mask; @@ -114,16 +115,16 @@ register struct obj *obj; if (!obj) return; if (obj == uwep || obj == uswapwep) u.twoweap = 0; for(wp = worn; wp->w_mask; wp++) - if(obj == *(wp->w_obj)) { - *(wp->w_obj) = 0; - p = objects[obj->otyp].oc_oprop; - u.uprops[p].extrinsic = u.uprops[p].extrinsic & ~wp->w_mask; - obj->owornmask &= ~wp->w_mask; - if (obj->oartifact) - set_artifact_intrinsic(obj, 0, wp->w_mask); - if ((p = w_blocks(obj,wp->w_mask)) != 0) - u.uprops[p].blocked &= ~wp->w_mask; - } + if(obj == *(wp->w_obj)) { + *(wp->w_obj) = 0; + p = objects[obj->otyp].oc_oprop; + u.uprops[p].extrinsic = u.uprops[p].extrinsic & ~wp->w_mask; + obj->owornmask &= ~wp->w_mask; + if (obj->oartifact) + set_artifact_intrinsic(obj, 0, wp->w_mask); + if ((p = w_blocks(obj,wp->w_mask)) != 0) + u.uprops[p].blocked &= ~wp->w_mask; + } update_inventory(); } @@ -140,15 +141,19 @@ struct monst *mon; } void -mon_adjust_speed(mon, adjust) +mon_adjust_speed(mon, adjust, obj) struct monst *mon; int adjust; /* positive => increase speed, negative => decrease */ +struct obj *obj; /* item to make known if effect can be seen */ { struct obj *otmp; + boolean give_msg = !in_mklev; + unsigned int oldspeed = mon->mspeed; switch (adjust) { case 2: mon->permspeed = MFAST; + give_msg = FALSE; /* special case monster creation */ break; case 1: if (mon->permspeed == MSLOW) mon->permspeed = 0; @@ -162,6 +167,7 @@ int adjust; /* positive => increase speed, negative => decrease */ break; case -2: mon->permspeed = MSLOW; + give_msg = FALSE; /* (not currently used) */ break; } @@ -172,6 +178,23 @@ int adjust; /* positive => increase speed, negative => decrease */ mon->mspeed = MFAST; else mon->mspeed = mon->permspeed; + + if (give_msg && mon->mspeed != oldspeed && canseemon(mon)) { + /* fast to slow (skipping intermediate state) or vice versa */ + const char *howmuch = (mon->mspeed + oldspeed == MFAST + MSLOW) ? + "much " : ""; + + if (adjust > 0 || mon->mspeed == MFAST) + pline("%s is suddenly moving %sfaster.", Monnam(mon), howmuch); + else + pline("%s seems to be moving %sslower.", Monnam(mon), howmuch); + + /* might discover an object if we see the speed change happen, but + avoid making possibly forgotten book known when casting its spell */ + if (obj != 0 && obj->dknown && + objects[obj->otyp].oc_class != SPBOOK_CLASS) + makeknown(obj->otyp); + } } /* armor put on or taken off; might be magical variety */ @@ -195,7 +218,7 @@ boolean on; mon->minvis = !mon->invis_blkd; break; case FAST: - mon_adjust_speed(mon, 0); + mon_adjust_speed(mon, 0, obj); break; /* properties handled elsewhere */ case ANTIMAGIC: @@ -230,7 +253,7 @@ boolean on; mon->minvis = mon->perminvis; break; case FAST: - mon_adjust_speed(mon, 0); + mon_adjust_speed(mon, 0, obj); break; case FIRE_RES: case COLD_RES: @@ -404,7 +427,8 @@ boolean creation; * it would forget spe and once again think the object is better * than what it already has. */ - if (best && (ARM_BONUS(best) >= ARM_BONUS(obj))) continue; + if (best && (ARM_BONUS(best) + extra_pref(mon,best) >= ARM_BONUS(obj) + extra_pref(mon,obj))) + continue; best = obj; } outer_break: @@ -476,18 +500,65 @@ struct obj *obj; } void -mon_break_armor(mon) +clear_bypasses() +{ + struct obj *otmp, *nobj; + + for (otmp = fobj; otmp; otmp = nobj) { + nobj = otmp->nobj; + if (otmp->bypass) { + otmp->bypass = 0; +#if 0 + /* setting otmp->bypass changes mergability. + * If monster can ever drop anything that + * can and should merge, this code block + * should be enabled. + */ + { + struct obj *obj; + xchar ox, oy; + (void) get_obj_location(otmp, &ox, &oy, 0); + obj_extract_self(otmp); + obj = merge_choice(fobj, otmp); + /* If it can't merge, then place it */ + if (!obj || (obj && !merged(&obj, &otmp))) + place_object(otmp, ox, oy); + newsym(ox, oy); + } +#endif + } + } + flags.bypasses = FALSE; +} + +void +bypass_obj(obj) +struct obj *obj; +{ + obj->bypass = 1; + flags.bypasses = TRUE; +} + +void +mon_break_armor(mon, polyspot) struct monst *mon; +boolean polyspot; { register struct obj *otmp; struct permonst *mdat = mon->data; boolean vis = cansee(mon->mx, mon->my); - const char *pronoun = him[pronoun_gender(mon)], - *ppronoun = his[pronoun_gender(mon)]; + const char *pronoun = mhim(mon), + *ppronoun = mhis(mon); if (breakarm(mdat)) { if ((otmp = which_armor(mon, W_ARM)) != 0) { - if (vis) + if ((Is_dragon_scales(otmp) && + mdat == Dragon_scales_to_pm(otmp)) || + (Is_dragon_mail(otmp) && mdat == Dragon_mail_to_pm(otmp))) + ; /* no message here; + "the dragon merges with his scaly armor" is odd + and the monster's previous form is already gone */ + else if (vis) pline("%s breaks out of %s armor!", Monnam(mon), ppronoun); else You_hear("a cracking sound."); @@ -496,11 +567,14 @@ struct monst *mon; if ((otmp = which_armor(mon, W_ARMC)) != 0) { if (otmp->oartifact) { if (vis) - pline("%s cloak falls off!", s_suffix(Monnam(mon))); + pline("%s %s falls off!", s_suffix(Monnam(mon)), + cloak_simple_name(otmp)); + if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } else { if (vis) - pline("%s cloak tears apart!", s_suffix(Monnam(mon))); + pline("%s %s tears apart!", s_suffix(Monnam(mon)), + cloak_simple_name(otmp)); else You_hear("a ripping sound."); m_useup(mon, otmp); @@ -522,17 +596,19 @@ struct monst *mon; s_suffix(Monnam(mon)), pronoun); else You_hear("a thud."); + if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } if ((otmp = which_armor(mon, W_ARMC)) != 0) { if (vis) { if (is_whirly(mon->data)) - pline("%s cloak falls, unsupported!", - s_suffix(Monnam(mon))); + pline("%s %s falls, unsupported!", + s_suffix(Monnam(mon)), cloak_simple_name(otmp)); else - pline("%s shrinks out of %s cloak!", Monnam(mon), - ppronoun); + pline("%s shrinks out of %s %s!", Monnam(mon), + ppronoun, cloak_simple_name(otmp)); } + if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } #ifdef TOURIST @@ -545,6 +621,7 @@ struct monst *mon; pline("%s becomes much too small for %s shirt!", Monnam(mon), ppronoun); } + if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } #endif @@ -555,6 +632,7 @@ struct monst *mon; pline("%s drops %s gloves%s!", Monnam(mon), ppronoun, MON_WEP(mon) ? " and weapon" : ""); possibly_unwield(mon); + if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } if ((otmp = which_armor(mon, W_ARMS)) != 0) { @@ -563,6 +641,7 @@ struct monst *mon; ppronoun); else You_hear("a clank."); + if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } if ((otmp = which_armor(mon, W_ARMH)) != 0) { @@ -571,6 +650,7 @@ struct monst *mon; s_suffix(Monnam(mon)), surface(mon->mx, mon->my)); else You_hear("a clank."); + if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } } @@ -585,12 +665,14 @@ struct monst *mon; s_suffix(Monnam(mon)), verysmall(mdat) ? "slide" : "are pushed", ppronoun); } + if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); } } #ifdef STEED if (!can_saddle(mon)) { if ((otmp = which_armor(mon, W_SADDLE)) != 0) { + if (polyspot) bypass_obj(otmp); m_lose_armor(mon, otmp); if (vis) pline("%s saddle falls off.", s_suffix(Monnam(mon))); @@ -615,4 +697,18 @@ struct monst *mon; return; } +/* bias a monster's preferences towards armor that has special benefits. */ +/* currently only does speed boots, but might be expanded if monsters get to + use more armor abilities */ +static int +extra_pref(mon, obj) +struct monst *mon; +struct obj *obj; +{ + if (obj) { + if (obj->otyp == SPEED_BOOTS && mon->permspeed != MFAST) + return 20; + } + return 0; +} /*worn.c*/ diff --git a/src/write.c b/src/write.c index a0739b8..03f804f 100644 --- a/src/write.c +++ b/src/write.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)write.c 3.3 96/05/05 */ +/* SCCS Id: @(#)write.c 3.4 2001/11/29 */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" @@ -85,8 +85,8 @@ register struct obj *pen; return 0; } else if (Glib) { dropx(pen); - pline("%s slips from your %s.", The(xname(pen)), - makeplural(body_part(FINGER))); + pline("%s from your %s.", + Tobjnam(pen, "slip"), makeplural(body_part(FINGER))); return 1; } @@ -178,17 +178,18 @@ register struct obj *pen; curseval = bcsign(pen) + bcsign(paper); exercise(A_WIS, TRUE); /* dry out marker */ - if(pen->spe < actualcost) { + if (pen->spe < actualcost) { + pen->spe = 0; Your("marker dries out!"); /* scrolls disappear, spellbooks don't */ - if (paper->oclass == SPBOOK_CLASS) + if (paper->oclass == SPBOOK_CLASS) { pline_The( "spellbook is left unfinished and your writing fades."); - else { + update_inventory(); /* pen charges */ + } else { pline_The("scroll is now useless and disappears!"); useup(paper); } - pen->spe = 0; obfree(new_obj, (struct obj *) 0); return(1); } @@ -200,10 +201,11 @@ register struct obj *pen; (rnl(Role_if(PM_WIZARD) ? 3 : 15))) { You("%s to write that!", by_descr ? "fail" : "don't know how"); /* scrolls disappear, spellbooks don't */ - if (paper->oclass == SPBOOK_CLASS) + if (paper->oclass == SPBOOK_CLASS) { You( "write in your best handwriting: \"My Diary\", but it quickly fades."); - else { + update_inventory(); /* pen charges */ + } else { if (by_descr) { Strcpy(namebuf, OBJ_DESCR(objects[new_obj->otyp])); wipeout_text(namebuf, (6+MAXULEV - u.ulevel)/6, 0); diff --git a/src/zap.c b/src/zap.c index 35bc58a..318e77f 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)zap.c 3.3 2000/08/01 */ +/* SCCS Id: @(#)zap.c 3.4 2002/02/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -28,7 +28,7 @@ STATIC_DCL boolean FDECL(zap_updown, (struct obj *)); STATIC_DCL int FDECL(zhitm, (struct monst *,int,int,struct obj **)); STATIC_DCL void FDECL(zhitu, (int,int,const char *,XCHAR_P,XCHAR_P)); STATIC_DCL void FDECL(revive_egg, (struct obj *)); -STATIC_DCL boolean FDECL(hits_bars, (int)); +STATIC_DCL boolean FDECL(hits_bars, (struct obj *)); #ifdef STEED STATIC_DCL boolean FDECL(zap_steed, (struct obj *)); #endif @@ -139,7 +139,8 @@ struct obj *otmp; case WAN_SLOW_MONSTER: case SPE_SLOW_MONSTER: if (!resist(mtmp, otmp->oclass, 0, NOTELL)) { - mon_adjust_speed(mtmp, -1); + mon_adjust_speed(mtmp, -1, otmp); + m_dowear(mtmp, FALSE); /* might want speed boots */ if (u.uswallow && (mtmp == u.ustuck) && is_whirly(mtmp->data)) { You("disrupt %s!", mon_nam(mtmp)); @@ -149,8 +150,10 @@ struct obj *otmp; } break; case WAN_SPEED_MONSTER: - if (!resist(mtmp, otmp->oclass, 0, NOTELL)) - mon_adjust_speed(mtmp, 1); + if (!resist(mtmp, otmp->oclass, 0, NOTELL)) { + mon_adjust_speed(mtmp, 1, otmp); + m_dowear(mtmp, FALSE); /* might want speed boots */ + } break; case WAN_UNDEAD_TURNING: case SPE_TURN_UNDEAD: @@ -163,8 +166,10 @@ struct obj *otmp; if(dbldam) dmg *= 2; if (otyp == SPE_TURN_UNDEAD) dmg += spell_damage_bonus(); - if(!resist(mtmp, otmp->oclass, dmg, NOTELL)) - mtmp->mflee = TRUE; + flags.bypasses = TRUE; /* for make_corpse() */ + if (!resist(mtmp, otmp->oclass, dmg, NOTELL)) { + if (mtmp->mhp > 0) monflee(mtmp, 0, FALSE, TRUE); + } } break; case WAN_POLYMORPH: @@ -175,17 +180,22 @@ struct obj *otmp; it guard against involuntary polymorph attacks too... */ shieldeff(mtmp->mx, mtmp->my); } else if (!resist(mtmp, otmp->oclass, 0, NOTELL)) { - if (!rn2(25)) { + /* natural shapechangers aren't affected by system shock + (unless protection from shapechangers is interfering + with their metabolism...) */ + if (mtmp->cham == CHAM_ORDINARY && !rn2(25)) { if (canseemon(mtmp)) { pline("%s shudders!", Monnam(mtmp)); makeknown(otyp); } + /* flags.bypasses = TRUE; ## for make_corpse() */ /* no corpse after system shock */ xkilled(mtmp, 3); - } - else if (newcham(mtmp, (struct permonst *)0) ) + } else if (newcham(mtmp, (struct permonst *)0, + (otyp != POT_POLYMORPH))) { if (!Hallucination && canspotmon(mtmp)) makeknown(otyp); + } } break; case WAN_CANCELLATION: @@ -250,6 +260,10 @@ struct obj *otmp; mtmp->mhp += d(6, otyp == SPE_EXTRA_HEALING ? 8 : 4); if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax; + if (mtmp->mblinded) { + mtmp->mblinded = 0; + mtmp->mcansee = 1; + } if (canseemon(mtmp)) pline("%s looks%s better.", Monnam(mtmp), otyp == SPE_EXTRA_HEALING ? " much" : "" ); @@ -280,7 +294,7 @@ struct obj *otmp; if (monsndx(mtmp->data) == PM_STONE_GOLEM) { char *name = Monnam(mtmp); /* turn into flesh golem */ - if (newcham(mtmp, &mons[PM_FLESH_GOLEM])) { + if (newcham(mtmp, &mons[PM_FLESH_GOLEM], FALSE)) { if (canseemon(mtmp)) pline("%s turns to flesh!", name); } else { @@ -302,12 +316,12 @@ struct obj *otmp; mtmp->mhp > 0) { mtmp->mhp -= dmg; mtmp->mhpmax -= dmg; - if (mtmp->mhp <= 0 || mtmp->mhpmax <= 0 || mtmp->m_lev <= 0) - xkilled(mtmp, 1); + if (mtmp->mhp <= 0 || mtmp->mhpmax <= 0 || mtmp->m_lev < 1) + xkilled(mtmp, 1); else { - mtmp->m_lev--; - if (canseemon(mtmp)) - pline("%s suddenly seems weaker!", Monnam(mtmp)); + mtmp->m_lev--; + if (canseemon(mtmp)) + pline("%s suddenly seems weaker!", Monnam(mtmp)); } } break; @@ -344,10 +358,14 @@ struct monst *mtmp; mstatusline(mtmp); if (notonhead) return; /* don't show minvent for long worm tail */ +#ifndef GOLDOBJ if (mtmp->minvent || mtmp->mgold) { +#else + if (mtmp->minvent) { +#endif for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) otmp->dknown = 1; /* treat as "seen" */ - (void) display_minventory(mtmp, MINV_ALL); + (void) display_minventory(mtmp, MINV_ALL, (char *)0); } else { pline("%s is not carrying anything.", noit_Monnam(mtmp)); } @@ -442,7 +460,7 @@ coord *cc; if (mtmp2->mhpmax <= 0 && !is_rider(mtmp2->data)) return (struct monst *)0; mtmp = makemon(mtmp2->data, - cc->x, cc->y, NO_MINVENT|MM_NOWAIT); + cc->x, cc->y, NO_MINVENT|MM_NOWAIT|MM_NOCOUNTBIRTH); if (!mtmp) return mtmp; /* heal the monster */ @@ -451,7 +469,11 @@ coord *cc; mtmp2->mhp = mtmp2->mhpmax; /* Get these ones from mtmp */ mtmp2->minvent = mtmp->minvent; /*redundant*/ - mtmp2->m_id = mtmp->m_id; + /* monster ID is available if the monster died in the current + game, but should be zero if the corpse was in a bones level + (we cleared it when loading bones) */ + if (!mtmp2->m_id) + mtmp2->m_id = mtmp->m_id; mtmp2->mx = mtmp->mx; mtmp2->my = mtmp->my; mtmp2->mux = mtmp->mux; @@ -468,6 +490,7 @@ coord *cc; mtmp2->mlstmv = mtmp->mlstmv; mtmp2->m_ap_type = mtmp->m_ap_type; /* set these ones explicitly */ + mtmp2->mavenge = 0; mtmp2->meating = 0; mtmp2->mleashed = 0; mtmp2->mtrapped = 0; @@ -484,6 +507,38 @@ coord *cc; return mtmp2; } +/* + * get_container_location() returns the following information + * about the outermost container: + * loc argument gets set to: + * OBJ_INVENT if in hero's inventory; return 0. + * OBJ_FLOOR if on the floor; return 0. + * OBJ_BURIED if buried; return 0. + * OBJ_MINVENT if in monster's inventory; return monster. + * container_nesting is updated with the nesting depth of the containers + * if applicable. + */ +struct monst * +get_container_location(obj, loc, container_nesting) +struct obj *obj; +int *loc; +int *container_nesting; +{ + if (!obj || !loc) + return 0; + + if (container_nesting) *container_nesting = 0; + while (obj && obj->where == OBJ_CONTAINED) { + if (container_nesting) *container_nesting += 1; + obj = obj->ocontainer; + } + if (obj) { + *loc = obj->where; /* outermost container's location */ + if (obj->where == OBJ_MINVENT) return obj->ocarry; + } + return (struct monst *)0; +} + /* * Attempt to revive the given corpse, return the revived monster if * successful. Note: this does NOT use up the corpse if it fails. @@ -493,16 +548,57 @@ revive(obj) register struct obj *obj; { register struct monst *mtmp = (struct monst *)0; + struct obj *container = (struct obj *)0; + int container_nesting = 0; schar savetame = 0; boolean recorporealization = FALSE; - + boolean in_container = FALSE; if(obj->otyp == CORPSE) { int montype = obj->corpsenm; xchar x, y; - /* only for invent, minvent, or floor */ - if (!get_obj_location(obj, &x, &y, 0)) - return (struct monst *) 0; + if (obj->where == OBJ_CONTAINED) { + /* deal with corpses in [possibly nested] containers */ + struct monst *carrier; + int holder = 0; + + container = obj->ocontainer; + carrier = get_container_location(container, &holder, + &container_nesting); + switch(holder) { + case OBJ_MINVENT: + x = carrier->mx; y = carrier->my; + in_container = TRUE; + break; + case OBJ_INVENT: + x = u.ux; y = u.uy; + in_container = TRUE; + break; + case OBJ_FLOOR: + if (!get_obj_location(obj, &x, &y, CONTAINED_TOO)) + return (struct monst *) 0; + in_container = TRUE; + break; + default: + return (struct monst *)0; + } + } else { + /* only for invent, minvent, or floor */ + if (!get_obj_location(obj, &x, &y, 0)) + return (struct monst *) 0; + } + if (in_container) { + /* Rules for revival from containers: + - the container cannot be locked + - the container cannot be heavily nested (>2 is arbitrary) + - the container cannot be a statue or bag of holding + (except in very rare cases for the latter) + */ + if (!x || !y || container->olocked || container_nesting > 2 || + container->otyp == STATUE || + (container->otyp == BAG_OF_HOLDING && rn2(40))) + return (struct monst *)0; + } if (MON_AT(x,y)) { coord new_xy; @@ -517,7 +613,7 @@ register struct obj *obj; NO_MINVENT|MM_NOWAIT); if (mtmp) { mtmp->mhp = mtmp->mhpmax = 100; - mon_adjust_speed(mtmp, 2); /* MFAST */ + mon_adjust_speed(mtmp, 2, (struct obj *)0); /* MFAST */ } } else { if (obj->oxlth && (obj->oattached == OATTACHED_MONST)) { @@ -528,7 +624,7 @@ register struct obj *obj; wary_dog(mtmp, TRUE); } else mtmp = makemon(&mons[montype], x, y, - NO_MINVENT|MM_NOWAIT); + NO_MINVENT|MM_NOWAIT|MM_NOCOUNTBIRTH); if (mtmp) { if (obj->oxlth && (obj->oattached == OATTACHED_M_ID)) { unsigned m_id; @@ -554,6 +650,10 @@ register struct obj *obj; /* Monster retains its name */ if (obj->onamelth) mtmp = christen_monst(mtmp, ONAME(obj)); + /* flag the quest leader as alive. */ + if (mtmp->data->msound == MS_LEADER || mtmp->m_id == + quest_status.leader_m_id) + quest_status.leader_is_dead = FALSE; } } if (mtmp) { @@ -584,13 +684,17 @@ register struct obj *obj; x = obj->ox, y = obj->oy; /* not useupf(), which charges */ if (obj->quan > 1L) - (void) splitobj(obj, 1L); + obj = splitobj(obj, 1L); delobj(obj); newsym(x, y); break; case OBJ_MINVENT: m_useup(obj->ocarry, obj); break; + case OBJ_CONTAINED: + obj_extract_self(obj); + obfree(obj, (struct obj *) 0); + break; default: panic("revive"); } @@ -792,7 +896,6 @@ register struct obj *obj; { boolean u_ring; - /* Is this a charged/enchanted object? */ if (!obj || (!objects[obj->otyp].oc_charged && obj->oclass != WEAPON_CLASS && @@ -852,6 +955,7 @@ register struct obj *obj; flags.botl = 1; break; } + if (carried(obj)) update_inventory(); return (TRUE); } @@ -1018,7 +1122,7 @@ create_polymon(obj, okind) mtmp = makemon(mdat, obj->ox, obj->oy, NO_MM_FLAGS); polyuse(obj, okind, (int)mons[pm_index].cwt); - if(!Blind && mtmp) { + if(mtmp && cansee(mtmp->mx, mtmp->my)) { pline("Some %sobjects meld, and %s arises from the pile!", material, a_monnam(mtmp)); } @@ -1048,9 +1152,9 @@ struct obj *obj; /* if quan > 1 then some will survive intact */ if (obj->quan > 1L) { if (obj->quan > LARGEST_INT) - (void) splitobj(obj, (long)rnd(30000)); + obj = splitobj(obj, (long)rnd(30000)); else - (void) splitobj(obj, (long)rnd((int)obj->quan - 1)); + obj = splitobj(obj, (long)rnd((int)obj->quan - 1)); } /* appropriately add damage to bill */ @@ -1072,11 +1176,12 @@ struct obj *obj; * "polymorph" case). If ID is set to a specific object, inhibit fusing * n objects into 1. This could have been added as a flag, but currently * it is tied to not being the standard polymorph case. The new polymorphed - * object replaces obj in its link chains. + * object replaces obj in its link chains. Return value is a pointer to + * the new object. * * This should be safe to call for an object anywhere. */ -void +struct obj * poly_obj(obj, id) struct obj *obj; int id; @@ -1219,7 +1324,7 @@ poly_obj(obj, id) while (otmp->otyp == SPE_POLYMORPH) otmp->otyp = rnd_class(SPE_DIG, SPE_BLANK_PAPER); /* reduce spellbook abuse */ - otmp->spestudied += 1; + otmp->spestudied = obj->spestudied + 1; break; case GEM_CLASS: @@ -1295,7 +1400,7 @@ poly_obj(obj, id) if ((!obj->no_charge || (Has_contents(obj) && - (contained_cost(obj, shkp, 0L, FALSE) != 0L))) + (contained_cost(obj, shkp, 0L, FALSE, FALSE) != 0L))) && inhishop(shkp)) { if(shkp->mpeaceful) { if(*u.ushops && *in_rooms(u.ux, u.uy, 0) == @@ -1310,7 +1415,7 @@ poly_obj(obj, id) } } delobj(obj); - return; + return otmp; } /* @@ -1323,8 +1428,40 @@ struct obj *obj, *otmp; { int res = 1; /* affected object by default */ + if (obj->bypass) { + /* The bypass bit is currently only used as follows: + * + * POLYMORPH - When a monster being polymorphed drops something + * from its inventory as a result of the change. + * If the items fall to the floor, they are not + * subject to direct subsequent polymorphing + * themselves on that same zap. This makes it + * consistent with items that remain in the + * monster's inventory. They are not polymorphed + * either. + * UNDEAD_TURNING - When an undead creature gets killed via + * undead turning, prevent its corpse from being + * immediately revived by the same effect. + * + * The bypass bit on all objects is reset each turn, whenever + * flags.bypasses is set. + * + * We check the obj->bypass bit above AND flags.bypasses + * as a safeguard against any stray occurrence left in an obj + * struct someplace, although that should never happen. + */ + if (flags.bypasses) + return 0; + else { +#ifdef DEBUG + pline("%s for a moment.", Tobjnam(obj, "pulsate")); +#endif + obj->bypass = 0; + } + } + /* - * Some parts of this function expect the object to on the floor + * Some parts of this function expect the object to be on the floor * obj->{ox,oy} to be valid. The exception to this (so far) is * for the STONE_TO_FLESH spell. */ @@ -1361,16 +1498,16 @@ struct obj *obj, *otmp; do_osshock(obj); break; } - poly_obj(obj, STRANGE_OBJECT); + obj = poly_obj(obj, STRANGE_OBJECT); newsym(obj->ox,obj->oy); break; case WAN_PROBING: res = !obj->dknown; /* target object has now been "seen (up close)" */ obj->dknown = 1; - if (Has_contents(obj)) { + if (Is_container(obj) || obj->otyp == STATUE) { if (!obj->cobj) - pline("%s is empty.", The(xname(obj))); + pline("%s empty.", Tobjnam(obj, "are")); else { struct obj *o; /* view contents (not recursively) */ @@ -1454,7 +1591,7 @@ struct obj *obj, *otmp; switch (objects[obj->otyp].oc_class) { case ROCK_CLASS: /* boulders and statues */ if (obj->otyp == BOULDER) { - poly_obj(obj, HUGE_CHUNK_OF_MEAT); + obj = poly_obj(obj, HUGE_CHUNK_OF_MEAT); if (In_sokoban(&u.uz)) change_luck(-1); /* Sokoban guilt */ goto smell; @@ -1472,7 +1609,7 @@ makecorpse: if (mons[obj->corpsenm].geno & /* Unlikely to get here since genociding * monsters also sets the G_NOCORPSE flag. */ - poly_obj(obj, CORPSE); + obj = poly_obj(obj, CORPSE); break; } } else { /* new rock class object... */ @@ -1502,13 +1639,13 @@ makecorpse: if (mons[obj->corpsenm].geno & } /* maybe add weird things to become? */ case RING_CLASS: /* some of the rings are stone */ - poly_obj(obj, MEAT_RING); + obj = poly_obj(obj, MEAT_RING); goto smell; case WAND_CLASS: /* marble wand */ - poly_obj(obj, MEAT_STICK); + obj = poly_obj(obj, MEAT_STICK); goto smell; case GEM_CLASS: /* rocks & gems */ - poly_obj(obj, MEATBALL); + obj = poly_obj(obj, MEATBALL); smell: if (herbivorous(youmonst.data) && !carnivorous(youmonst.data)) @@ -1667,9 +1804,11 @@ dozap() pline("%s glows and fades.", The(xname(obj))); /* make him pay for knowing !NODIR */ } else if(!u.dx && !u.dy && !u.dz && !(objects[obj->otyp].oc_dir == NODIR)) { - if ((damage = zapyourself(obj, TRUE)) != 0) - losehp(damage, self_pronoun("zapped %sself with a wand", "him"), - NO_KILLER_PREFIX); + if ((damage = zapyourself(obj, TRUE)) != 0) { + char buf[BUFSZ]; + Sprintf(buf, "zapped %sself with a wand", uhim()); + losehp(damage, buf, NO_KILLER_PREFIX); + } } else { /* Are we having fun yet? @@ -1684,7 +1823,7 @@ dozap() current_wand = 0; } if (obj && obj->spe < 0) { - pline("%s turns to dust.", The(xname(obj))); + pline("%s to dust.", Tobjnam(obj, "turn")); useup(obj); } update_inventory(); /* maybe used a charge */ @@ -1697,6 +1836,7 @@ struct obj *obj; boolean ordinary; { int damage = 0; + char buf[BUFSZ]; switch(obj->otyp) { case WAN_STRIKING: @@ -1731,12 +1871,13 @@ boolean ordinary; if (!resists_blnd(&youmonst)) { You(are_blinded_by_the_flash); make_blinded((long)rnd(100),FALSE); + if (!Blind) Your(vision_clears); } break; case SPE_FIREBALL: You("explode a fireball on top of yourself!"); - explode(u.ux, u.uy, 11, d(6,6), WAND_CLASS); + explode(u.ux, u.uy, 11, d(6,6), WAND_CLASS, EXPL_FIERY); break; case WAN_FIRE: makeknown(WAN_FIRE); @@ -1788,7 +1929,7 @@ boolean ordinary; makeknown(WAN_POLYMORPH); case SPE_POLYMORPH: if (!Unchanging) - polyself(); + polyself(FALSE); break; case WAN_CANCELLATION: @@ -1873,8 +2014,9 @@ boolean ordinary; : "You seem no deader than before."); break; } + Sprintf(buf, "shot %sself with a death ray", uhim()); + killer = buf; killer_format = NO_KILLER_PREFIX; - killer = self_pronoun("shot %sself with a death ray","him"); You("irradiate yourself with pure energy!"); You("die."); makeknown(obj->otyp); @@ -1910,6 +2052,7 @@ boolean ordinary; You(are_blinded_by_the_flash); make_blinded((long)damage, FALSE); makeknown(obj->otyp); + if (!Blind) Your(vision_clears); } damage = 0; /* reset */ break; @@ -2101,12 +2244,15 @@ struct obj *obj; /* wand or spell */ int x, y, xx, yy, ptmp; struct obj *otmp; struct engr *e; + struct trap *ttmp; char buf[BUFSZ]; /* some wands have special effects other than normal bhitpile */ /* drawbridge might change */ x = xx = u.ux; /* is zap location */ y = yy = u.uy; /* is drawbridge (portcullis) position */ + ttmp = t_at(x, y); /* trap if there is one */ + switch (obj->otyp) { case WAN_PROBING: ptmp = 0; @@ -2156,11 +2302,26 @@ struct obj *obj; /* wand or spell */ ceiling(x, y), body_part(HEAD)); losehp(rnd((uarmh && is_metallic(uarmh)) ? 2 : 6), "falling rock", KILLED_BY_AN); - if ((otmp = mksobj_at(ROCK, x, y, FALSE)) != 0) { + if ((otmp = mksobj_at(ROCK, x, y, FALSE, FALSE)) != 0) { (void)xname(otmp); /* set dknown, maybe bknown */ stackobj(otmp); } newsym(x, y); + } else if (!striking && ttmp && ttmp->ttyp == TRAPDOOR && u.dz > 0) { + if (!Blind) { + if (ttmp->tseen) { + pline("A trap door beneath you closes up then vanishes."); + disclose = TRUE; + } else { + You("see a swirl of %s beneath you.", + is_ice(x,y) ? "frost" : "dust"); + } + } else { + You_hear("a twang followed by a thud."); + } + deltrap(ttmp); + ttmp = (struct trap *)0; + newsym(x, y); } break; case SPE_STONE_TO_FLESH: @@ -2172,13 +2333,19 @@ struct obj *obj; /* wand or spell */ } else if (u.dz > 0 && !OBJ_AT(u.ux, u.uy)) { /* Print this message only if there wasn't an engraving - affected here. + affected here. If water or ice, act like waterlevel case. */ e = engr_at(u.ux, u.uy); - if (!(e && e->engr_type == ENGRAVE)) - pline("Blood pools at your %s.", - makeplural(body_part(FOOT))); + if (!(e && e->engr_type == ENGRAVE)) { + if (is_pool(u.ux, u.uy) || is_ice(u.ux, u.uy)) + pline(nothing_happens); + else + pline("Blood %ss %s your %s.", + is_lava(u.ux, u.uy) ? "boil" : "pool", + Levitation ? "beneath" : "at", + makeplural(body_part(FOOT))); } + } break; default: break; @@ -2218,9 +2385,6 @@ struct obj *obj; /* wand or spell */ case SPE_FORCE_BOLT: wipe_engr_at(x, y, d(2,4)); break; - case SPE_DRAIN_LIFE: - u_wipe_engr(3); - break; default: break; } @@ -2365,9 +2529,11 @@ register const char *str; register struct monst *mtmp; register const char *force; /* usually either "." or "!" */ { - if(!cansee(bhitpos.x,bhitpos.y) || !flags.verbose) - pline("%s hits it.", The(str)); - else pline("%s hits %s%s", The(str), mon_nam(mtmp), force); + if((!cansee(bhitpos.x,bhitpos.y) && !canspotmon(mtmp)) + || !flags.verbose) + pline("%s %s it.", The(str), vtense(str, "hit")); + else pline("%s %s %s%s", The(str), vtense(str, "hit"), + mon_nam(mtmp), force); } void @@ -2375,8 +2541,9 @@ miss(str,mtmp) register const char *str; register struct monst *mtmp; { - pline("%s misses %s.", The(str), - (cansee(bhitpos.x,bhitpos.y) && flags.verbose) ? + pline("%s %s %s.", The(str), vtense(str, "miss"), + ((cansee(bhitpos.x,bhitpos.y) || canspotmon(mtmp)) + && flags.verbose) ? mon_nam(mtmp) : "it"); } #endif /*OVL0*/ @@ -2384,14 +2551,19 @@ register struct monst *mtmp; /* return TRUE if obj_type can't pass through iron bars */ static boolean -hits_bars(obj_type) -int obj_type; +hits_bars(obj) +struct obj *obj; { + int obj_type = obj->otyp; /* - There should be a _lot_ of things here..., but lets start - with what started this change... + There should be a _lot_ of things here..., but iron ball + started this change and boulders, chests, and boxes were added later... + Corpses and statues that are at least medium size are also screened. */ - if (obj_type == HEAVY_IRON_BALL) + if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL || obj_type == LARGE_BOX || + obj_type == CHEST || obj_type == ICE_BOX || + ((obj_type == CORPSE || obj_type == STATUE) + && mons[obj->corpsenm].msize >= MZ_MEDIUM)) return TRUE; return FALSE; } @@ -2455,16 +2627,16 @@ struct obj *obj; /* object tossed/used */ } if(is_pick(obj) && inside_shop(x, y) && - shkcatch(obj, x, y)) { + (mtmp = shkcatch(obj, x, y))) { tmp_at(DISP_END, 0); - return(m_at(x, y)); + return(mtmp); } typ = levl[bhitpos.x][bhitpos.y].typ; /* iron bars will block anything big enough */ if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON) - && typ == IRONBARS && hits_bars(obj->otyp)) { + && typ == IRONBARS && hits_bars(obj)) { bhitpos.x -= ddx; bhitpos.y -= ddy; break; @@ -2498,21 +2670,37 @@ struct obj *obj; /* object tossed/used */ if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) { notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my); - /* TODO: FLASHED_LIGHT hitting invisible monster - should pass through instead of stop... */ - if(weapon != ZAPPED_WAND) { - if(weapon != INVIS_BEAM) tmp_at(DISP_END, 0); - if (cansee(bhitpos.x,bhitpos.y) && !canspotmon(mtmp)) { + if (weapon != FLASHED_LIGHT) { + if(weapon != ZAPPED_WAND) { + if(weapon != INVIS_BEAM) tmp_at(DISP_END, 0); + if (cansee(bhitpos.x,bhitpos.y) && !canspotmon(mtmp)) { + if (weapon != INVIS_BEAM) { + map_invisible(bhitpos.x, bhitpos.y); + return(mtmp); + } + } else + return(mtmp); + } if (weapon != INVIS_BEAM) { - map_invisible(bhitpos.x, bhitpos.y); - return(mtmp); + (*fhitm)(mtmp, obj); + range -= 3; } - } else - return(mtmp); - } - if (weapon != INVIS_BEAM) { - (*fhitm)(mtmp, obj); - range -= 3; + } else { + /* FLASHED_LIGHT hitting invisible monster + should pass through instead of stop so + we call flash_hits_mon() directly rather + than returning mtmp back to caller. That + allows the flash to keep on going. Note + that we use mtmp->minvis not canspotmon() + because it makes no difference whether + the hero can see the monster or not.*/ + if (mtmp->minvis) { + obj->ox = u.ux, obj->oy = u.uy; + (void) flash_hits_mon(mtmp, obj); + } else { + tmp_at(DISP_END, 0); + return(mtmp); /* caller will call flash_hits_mon */ + } } } else { if (weapon == ZAPPED_WAND && obj->otyp == WAN_PROBING && @@ -2574,7 +2762,8 @@ boolean costly = shop_keeper(*in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) && delay_output(); /* kicked objects fall in pools */ if((weapon == KICKED_WEAPON) && - is_pool(bhitpos.x, bhitpos.y)) + (is_pool(bhitpos.x, bhitpos.y) || + is_lava(bhitpos.x, bhitpos.y))) break; #ifdef SINKS if(IS_SINK(typ) && weapon != FLASHED_LIGHT) @@ -2800,7 +2989,7 @@ struct obj **ootmp; /* to return worn armor for caller to disintegrate */ break; } tmp = d(nd,6); - if (!rn2(6)) erode_weapon(MON_WEP(mon), TRUE); + if (!rn2(6)) erode_obj(MON_WEP(mon), TRUE, TRUE); if (!rn2(6)) erode_armor(mon, TRUE); break; } @@ -2810,6 +2999,7 @@ struct obj **ootmp; /* to return worn armor for caller to disintegrate */ if (tmp > 0 && type >= 0 && resist(mon, type < ZT_SPELL(0) ? WAND_CLASS : '\0', 0, NOTELL)) tmp /= 2; + if (tmp < 0) tmp = 0; /* don't allow negative damage */ #ifdef WIZ_PATCH_DEBUG pline("zapped monster hp = %d (= %d - %d)", mon->mhp-tmp,mon->mhp,tmp); #endif @@ -2928,8 +3118,8 @@ xchar sx, sy; exercise(A_STR, FALSE); } /* using two weapons at once makes both of them more vulnerable */ - if (!rn2(u.twoweap ? 3 : 6)) erode_weapon(uwep, TRUE); - if (u.twoweap && !rn2(3)) erode_weapon(uswapwep, TRUE); + if (!rn2(u.twoweap ? 3 : 6)) erode_obj(uwep, TRUE, TRUE); + if (u.twoweap && !rn2(3)) erode_obj(uswapwep, TRUE, TRUE); if (!rn2(6)) erode_armor(&youmonst, TRUE); break; } @@ -2949,9 +3139,10 @@ xchar sx, sy; * return the number of scrolls and spellbooks burned */ int -burn_floor_paper(x, y, give_feedback) +burn_floor_paper(x, y, give_feedback, u_caused) int x, y; boolean give_feedback; /* caller needs to decide about visibility checks */ +boolean u_caused; { struct obj *obj, *obj2; long i, scrquan, delquan; @@ -2972,8 +3163,9 @@ boolean give_feedback; /* caller needs to decide about visibility checks */ /* save name before potential delobj() */ what = !give_feedback ? 0 : (x == u.ux && y == u.uy) ? xname(obj) : distant_name(obj, xname); - /* not useupf(), which charges */ - if (delquan < scrquan) obj->quan -= delquan; + /* useupf(), which charges, only if hero caused damage */ + if (u_caused) useupf(obj, delquan); + else if (delquan < scrquan) obj->quan -= delquan; else delobj(obj); cnt += delquan; if (give_feedback) { @@ -3105,7 +3297,8 @@ register int dx,dy; pline("%s disintegrates.", Monnam(mon)); pline("%s body reintegrates before your %s!", s_suffix(Monnam(mon)), - makeplural(body_part(EYE))); + (eyecount(youmonst.data) == 1) ? + body_part(EYE) : makeplural(body_part(EYE))); pline("%s resurrects!", Monnam(mon)); } mon->mhp = mon->mhpmax; @@ -3131,7 +3324,9 @@ register int dx,dy; else hit(fltxt, mon, "!"); } +#ifndef GOLDOBJ mon->mgold = 0L; +#endif /* note: worn amulet of life saving must be preserved in order to operate */ #define oresist_disintegration(obj) \ @@ -3204,6 +3399,7 @@ register int dx,dy; if (abstype == ZT_LIGHTNING && !resists_blnd(&youmonst)) { You(are_blinded_by_the_flash); make_blinded((long)d(nd,50),FALSE); + if (!Blind) Your(vision_clears); } stop_occupation(); nomul(0); @@ -3248,7 +3444,7 @@ register int dx,dy; } tmp_at(DISP_END,0); if (type == ZT_SPELL(ZT_FIRE)) - explode(sx, sy, type, d(12,6), 0); + explode(sx, sy, type, d(12,6), 0, EXPL_FIERY); if (shopdamage) pay_for_damage(abstype == ZT_FIRE ? "burn away" : abstype == ZT_COLD ? "shatter" : @@ -3312,6 +3508,14 @@ boolean *shopdamage; int rangemod = 0; if(abstype == ZT_FIRE) { + struct trap *t = t_at(x, y); + + if (t && t->ttyp == WEB) { + /* a burning web is too flimsy to notice if you can't see it */ + if (cansee(x,y)) Norep("A web bursts into flames!"); + (void) delfloortrap(t); + if (cansee(x,y)) newsym(x,y); + } if(is_ice(x, y)) { melt_ice(x, y); } else if(is_pool(x,y)) { @@ -3465,7 +3669,7 @@ boolean *shopdamage; } if(OBJ_AT(x, y) && abstype == ZT_FIRE) - if (burn_floor_paper(x, y, FALSE) && couldsee(x, y)) { + if (burn_floor_paper(x, y, FALSE, type > 0) && couldsee(x, y)) { newsym(x,y); You("%s of smoke.", !Blind ? "see a puff" : "smell a whiff"); @@ -3504,6 +3708,8 @@ register struct obj *obj; /* no texts here! */ obj->onamelth = 0; /* no names */ obj->oxlth = 0; /* no extra data */ obj->oattached = OATTACHED_NOTHING; + obj_extract_self(obj); /* move rocks back on top */ + place_object(obj, obj->ox, obj->oy); if(!does_block(obj->ox,obj->oy,&levl[obj->ox][obj->oy])) unblock_point(obj->ox,obj->oy); if(cansee(obj->ox,obj->oy)) @@ -3639,8 +3845,10 @@ register int osym, dmgtyp; pline("%s %s %s!", mult, xname(obj), (cnt > 1L) ? destroy_strings[dindx*3 + 1] : destroy_strings[dindx*3]); - if(osym == POTION_CLASS && dmgtyp != AD_COLD) - potionbreathe(obj); + if(osym == POTION_CLASS && dmgtyp != AD_COLD) { + if (!breathless(youmonst.data) || haseyes(youmonst.data)) + potionbreathe(obj); + } if (obj->owornmask) { if (obj->owornmask & W_RING) /* ring being worn */ Ring_gone(obj); @@ -3779,8 +3987,10 @@ int damage, tell; /* attack level */ switch (oclass) { case WAND_CLASS: alev = 12; break; + case TOOL_CLASS: alev = 10; break; case SCROLL_CLASS: alev = 9; break; case POTION_CLASS: alev = 6; break; + case RING_CLASS: alev = 5; break; default: alev = u.ulevel; break; /* spell */ } /* defense level */ @@ -3789,18 +3999,20 @@ int damage, tell; else if (dlev < 1) dlev = is_mplayer(mtmp->data) ? u.ulevel : 1; resisted = rn2(100 + alev - dlev) < mtmp->data->mr; - if(resisted) { - - if(tell) { - shieldeff(mtmp->mx, mtmp->my); - pline("%s resists!", Monnam(mtmp)); - } - mtmp->mhp -= damage/2; - } else mtmp->mhp -= damage; + if (resisted) { + if (tell) { + shieldeff(mtmp->mx, mtmp->my); + pline("%s resists!", Monnam(mtmp)); + } + damage = (damage + 1) / 2; + } - if(mtmp->mhp < 1) { + if (damage) { + mtmp->mhp -= damage; + if (mtmp->mhp < 1) { if(m_using) monkilled(mtmp, "", AD_RBRE); else killed(mtmp); + } } return(resisted); } @@ -3809,33 +4021,53 @@ void makewish() { char buf[BUFSZ]; - register struct obj *otmp; + struct obj *otmp, nothing; int tries = 0; + nothing = zeroobj; /* lint suppression; only its address matters */ if (flags.verbose) You("may wish for an object."); retry: getlin("For what do you wish?", buf); if(buf[0] == '\033') buf[0] = 0; /* * Note: if they wished for and got a non-object successfully, - * otmp == &zeroobj + * otmp == &zeroobj. That includes gold, or an artifact that + * has been denied. Wishing for "nothing" requires a separate + * value to remain distinct. */ - otmp = readobjnam(buf); + otmp = readobjnam(buf, ¬hing, TRUE); if (!otmp) { pline("Nothing fitting that description exists in the game."); if (++tries < 5) goto retry; pline(thats_enough_tries); - if (!(otmp = readobjnam((char *)0))) - return; /* for safety; should never happen */ + otmp = readobjnam((char *)0, (struct obj *)0, TRUE); + if (!otmp) return; /* for safety; should never happen */ + } else if (otmp == ¬hing) { + /* explicitly wished for "nothing", presumeably attempting + to retain wishless conduct */ + return; } /* KMH, conduct */ u.uconduct.wishes++; if (otmp != &zeroobj) { - if(otmp->oartifact && !touch_artifact(otmp,&youmonst)) - dropy(otmp); - else + /* place_object looses these */ + boolean crysknife = (otmp->otyp == CRYSKNIFE); + int oerode = otmp->oerodeproof; + + /* in case touching this object turns out to be fatal */ + place_object(otmp, u.ux, u.uy); + + if (otmp->oartifact && !touch_artifact(otmp,&youmonst)) { + obj_extract_self(otmp); /* remove it from the floor */ + dropy(otmp); /* now put it back again :-) */ + } else { + obj_extract_self(otmp); + if (crysknife) { + otmp->otyp = CRYSKNIFE; + otmp->oerodeproof = oerode; + } /* The(aobjnam()) is safe since otmp is unidentified -dlc */ (void) hold_another_object(otmp, u.uswallow ? "Oops! %s out of your reach!" : @@ -3846,6 +4078,7 @@ makewish() Is_airlevel(&u.uz) || u.uinwater ? "slip" : "drop")), (const char *)0); + } u.ublesscnt += rn1(100,50); /* the gods take notice */ } } diff --git a/sys/amiga/Build.ami b/sys/amiga/Build.ami new file mode 100644 index 0000000..17c1392 --- /dev/null +++ b/sys/amiga/Build.ami @@ -0,0 +1,146 @@ + + Compiling Amiga NetHack 3.4 + Last Revision: 21 February 2002 for NetHack 3.4.0 + + + We would like to thank each and every one of the people who took + the time and effort to report bugs to us. THANK YOU! (And keep + up the good work!) + +I. Introduction + + The Amiga-specific documentation has been split since the 3.1.3 release + - please read the file Install.ami for information specific to the + Amiga port before continuing. + + If you have problems with compilation, installation, or think you have + found a bug in the game, please report it by electronic mail to the + development group at nethack-bugs@nethack.org, where it will be routed + to the appropriate person. Include your configuration, the version of + NetHack you are playing (use the 'v' command or see + include/patchlevel.h), and as much specific information as possible. + As NetHack runs on many different machines, be sure to mention that you + are playing the Amiga version and also mention if you are using the + version for mc68k or ppc. + + If you want to find out about distributing NetHack, read the license + (in NetHack:license or type ?i during the game). + +II. Compiling Amiga NetHack 3.4 + +II.A. Compilation Overview + Compiling NetHack is not very hard - basically you do a little + configuration and start make. It does, however, require a good amount + of disk space and time. It also needs a good bit of memory, especially + for linking. + +II.B. Basic Compilation + + NetHack can be built with SAS/C version 6.5x. The commercial version + of DICE might work, but NetHack version 3.2.2 or later haven't been + compiled with it. The "official" compiler for NetHack 3.4 is SAS/C 6.58 + - we have dropped support for SAS/C 5.x. + + The Manx/Aztec port has not been tested recently and is certainly + broken. Anyone managing to compile NetHack with this compiler is + encouraged to submit context diffs of the required changes. When last + tested, NetHack required version 5.0B of that compiler. + + Compiling with gcc should also work. + +II.B.1. Introduction to Compiling NetHack + Before doing any compilation, read the README files distributed with + the source. These should familiarize you with the source tree layout + and what files are shared with what computers; everything in the + sys/amiga directory is used exclusively by the Amiga. + + The makefile (sys/amiga/Makefile.ami) depends on certain assignments, + providing the developer with a fairly flexible environment. See + sys/amiga/Makefile.ami for assignment assumptions. DICE users should + see section II.B.3 for information on creating a DMakefile usable with + DMake. + + Edit config.h to your liking and system configuration. The defaults + should be satisfactory for most systems. + + Read VERY CAREFULLY through the Makefile to familiarize yourself + with which assignments are assumed. Otherwise, you're going to get + something like "Insert NH: in any drive." You will need uudecode, + and, if you need to modify dgn_comp or lev_comp, flex, and bison. + The first thing Makefile.ami does is build makedefs, which handles + a variety of data file generation, and then lev_comp and dgn_comp + which compile the special levels. Makedefs will then be run to create + a few files, followed by a roughly alphabetically sorted compilation + of the entire source tree. This process will compile selected files + from the sys/amiga, sys/share, win/tty, and src directories, eventually + creating sbin/nethack. After building the main binary, a make install + will build the auxiliary files including help files, special levels, + icons, and the font files and will put these files into their final + positions - most will be in dlb archives (if DLB was defined in config.h). + The first make run should be done in NH:obj and the make install should be + done in NetHack:; for both runs, the makefile is NH:sys/amiga/Makefile.ami + (or NH:sys/amiga/DMakefile for DMake and NH:sys/amiga/Makefile.agc for + gcc). + + Note that not all the source is simple C code. If you are modifying + lev_comp or dgn_comp you may need bison and/or flex (depending on what + modifications you are making). You do not need any of these tools to + simply build NetHack - all the C output files are provided in the source + distribution. Also, the ifchange script requires a version of diff that + produces standard Unix format context diffs for proper operation - the + version shipped with SAS/C is not sufficient. + + If you do not have bison and flex, copy the files from sys/share. The + include files go in include/ and the C files go in util/. If the compile + fails due to prototype errors for malloc and realloc, try deleting + the first line of lev_comp.c and dgn_comp.c. + +II.B.2. Compiling NetHack with SAS/C version 6.58 + + NOTE WELL - Amiga NetHack has dropped support for SAS/C version 5. + This version of NetHack was developed with SAS/C 6.58. Earlier versions + than version of the compiler are known to cause problems - don't use them. + + A couple of notes and warnings from the SAS/C users on the team: + + * Included in the SAS/C port is code for generating a SnapShot.tb + file upon catching various internal disasters. That is why the + debug=l flag is in the makefile. This adds about 270K to the disk + image, but it does not increase the run time memory requirements. + + * The 5.10b optimizer did not produce correct code for NetHack. The + current optimizer has not been tested. + +II.B.3. Compiling NetHack with the commercial version of DICE + + IMPORTANT NOTE: If you are using DMake, you need to create DMakefile + from Makefile.ami. Do the following: + + cd NH:sys/amiga + edit from Makefile.ami to DMakefile with mkdmake opt w255 + + Some versions of DMake have been known to crash horribly on the + makefile - if this happens, you'll need to download another make + utility, such as AMake (ftp://ftp.dragonfire.net/amiga/utils/amake), + which will run in DMake-compatibility mode if invoked with the -C switch + (e.g. "amake -C -f NH:sys/amiga/DMakefile", or just + "alias dmake amake -C"). + + SECOND IMPORTANT NOTE: The score list is currently disabled when + compiling under DICE, due to an as-yet-unknown problem which causes + system crashes when displaying the score list. + + NetHack can be compiled using the commercial version of DICE only. The + registered shareware version had a bug in it which resulted in odd- + aligned procedures. (It is possible to patch DC1 to fix this problem; + however, this is not recommended, and you should upgrade to the + commercial version.) + + DICE 3.0 (the first commercial release) has a couple of bugs in it which + turn up in several of the NetHack sources; the DCC30_BUG define fixes + them. If you have a more recent version of the compiler, you may be + able to compile without this (and get slightly more efficient code) by + commenting out the define in amiconf.h. + + During compilation, DICE will output a lot of warnings; they can be + safely ignored. diff --git a/sys/amiga/Install.ami b/sys/amiga/Install.ami new file mode 100644 index 0000000..145b1b0 --- /dev/null +++ b/sys/amiga/Install.ami @@ -0,0 +1,200 @@ + + Using and Installing Amiga NetHack 3.4 + (or Everything You Never Wanted to Know Before NetHacking) + (or Not Everything That Happens Always Comes Knocking) + + Last Revision: 28 March 2000 for NetHack 3.4.0 + + +0. Pre-intro for NetHack 3.4.0: + Amiga-specific changes for 3.4.0: + Most (around 99%) known bugs fixed (volunteers welcome). + HackWB and HackCli are no longer supported. Use the main binary. + + We would like to thank each and every one of the people who took + the time and effort to report bugs to us. THANK YOU! + +I. Introduction + +I.A. Overview + Welcome to Amiga NetHack! If this is your first visit to our fair + city, you are in for an amazing but dangerous journey; if you have + visited us before, beware! the city has changed in many strange and + subtle ways; it has also grown quite a bit. This missive brings to + light those mundane tasks which must be dealt with before beginning + your journey; for those of you who are faced with the task of + installing the pre-fabricated version of our town, section III + (Installing Amiga NetHack 3.4) will guide you through the task at + hand. If you are ready to visit, the local visitors guide is in + section II (Using Amiga NetHack 3.4); please also see the general + guide packaged separately (the file "GuideBook"). + + To all our visitors, a hearty Welcome! - and please be careful. + + [Those responsible for the previous paragraphs have been sacked. The + documentation has been completed at great expense in a more traditional + style. -- The Management] + +I.B. Getting Help + If you have questions about strategy, weapons, or monsters, the best + place to go for help is the Usenet newsgroup rec.games.roguelike.nethack. + + If you have problems with installation or think you have found a bug + in the game, please report it by electronic mail to the development + team at nethack-bugs@nethack.org, where it will be routed to the + appropriate person. Include your configuration, the version of + NetHack you are playing (use the 'v' command), whether or not you are + using an official binary release (and if so which one) and as much + specific information as possible. As NetHack runs on many different + machines, be sure to mention that you are playing the Amiga version. + +I.C. Credits + Olaf Seibert first ported NetHack 2.3 and 3.0 to the Amiga. Richard + Addison, Andrew Church, Jochen Erwied, Mark Gooderum, Ken Lorber, + Greg Olson, Mike Passaretti, and Gregg Wonderly polished and extended + the 3.0 and 3.1 ports. Andrew Church, Ken Lorber, and Gregg Wonderly + are responsible for the 3.2 port. Janne Salmijärvi resurrected the + amigaport for 3.3 and Teemu Suikki joined before 3.4.0. + +II. Using Amiga NetHack 3.4 + Run NetHack from the shell or from some tool that allows that, + ie. ToolManager. See the NetHack.txt file for command line options + and other usage. + +II.A. Sources of Information + Where to go depends on what you want to find out. If you want to find + out about distributing NetHack, read the license (in NetHack:license + or type ?i during the game). For an introduction to NetHack, read + the GuideBook file. To find out what options are compiled into your + copy of NetHack, type #v during the game. Finally, for information + during the game on all kinds of things, type ? and select from the + menu or by pressing Help key. + +II.B. The Amiga NetHack WorkBench Front End + Starting from 3.3.0 HackWB is not supported. + +II.C. The Amiga NetHack CLI Front End + Starting from 3.3.0 CLI Front end is not supported either. + + Instead, use the main binary. See NetHack.txt file for the standard Unix + flags for NetHack. In addition to those flags, Amiga NetHack accepts + the flags -l to force non-interlaced mode and -L to force interlaced mode. + +II.D. Amiga-Specific Information for NetHack + + There are several options that are unique to the Amiga version of + NetHack that may be specified in the NetHack.cnf file or on an + OPTIONS line: + + altmeta allows the ALT keys to function as META keys. The default + is altmeta. + flush flush discards all characters in the queue except the first, + which limits typeahead accidents. The default is !flush. + silent turn off the audio output. The default is silent. + + The current version of Amiga NetHack also supports menu accelerators. + See Guidebook.txt for a detailed description. Also supported is + selecting the number of stacked objects to drop, used with the (D)rop + command. Type the number and then select an item (or items with + accelerators). Items with a count associated with them are denoted + with # in place of -. I.e. 'd - 3 blessed daggers' becomes + 'd # 3 blessed daggers'. You can clear the count by hitting esc + while counting or deselect and reselect the item. The default + is to drop all selected items (as before). + + For other options how to configure the screen setting and colors refer + to Nethack.cnf. + +III. Installing Amiga NetHack 3.4 + +III.A. General Installation + Installation should be easy - basically it consists of putting files + where they belong and adding an assign to your startup. If you are + installing from the official binary distribution, simply unpacking + the archive in the appropriate directory will put the files in the + places they belong. + + IF YOU ALREADY HAVE A PREVIOUS VERSION INSTALLED YOU MUST DELETE THE + OLD SAVE AND BONES FILES - THEY WILL NOT WORK! This includes save + and bones files from all previous versions of NetHack (yes, even 3.3.1). + If you have a game in progress and want to finish it, use your + current version and then update. + +Will NetHack fit on your machine? + NetHack 3.4 is large. NetHack 3.4 is very large. You will need: + > Any standard series Amiga: 500, 600, 1000, 1200, 2000, 2500, 3000, 4000. + > WorkBench 2.04 or later. + > At least 3 meg of RAM. NetHack will NOT run in 1 meg (probably even 2). + > Mass storage: A hard drive with over 3 meg of free space is highly + recommended. + +Hard Disk Installation: + Unpack the archive to your place of choice. Since you are reading this + you've probably done that already. Now just assign NetHack: to + NetHack directory containing the executable and datafiles and other needed + directories. + + Use the table in the next section to see where things should end up. + Be sure that the file 8 ends up in NetHack:hack/8. + +Configuration + Using your favorite text editor, edit NetHack:NetHack.cnf to match + your system. + + Create the save file directory (makedir NetHack:save) and the levels file + directory (makedir NetHack:levels), if they don't already exist. + + Create the score file (echo to NetHack:record) and, if desired, the log + file (echo to NetHack:logfile), if they don't already exist. You may + leave out logfile, but record is needed. + +III.B. File Location Table +NetHack: + amii.hlp Guidebook.txt hack.font + license NetHack NetHack.cnf + NetHack.txt nhdat nhsdat + record Recover Recover.txt + logfile (optional, but useful) +NetHack:hack + 8 +NetHack:tiles + monsters.iff objects.iff other.iff + +IV. BBS Interface + + [Since HackCli and split binary is no longer supported the following + probably doesn't apply anymore. Due to lack of a suitable environment + it is also untested.] + + The BBS mode is based on the standard NetHack tty port and is designed + for use in a BBS setting - it is specifically not recommended for use + on the console. The current TTY mode has changed significantly since + the preliminary version released with 3.1.2. In particular, BBS mode + now works with split binaries (only), and now supports multiple games + in progress at the same time for multi-line boards (note however that + any individual user should not be allowed to run two instances of + NetHack at the same time). + + To set up NetHack for use with a BBS, set OPTIONS=windowtype:tty + and unset DUNGEONS, TRAPS, and EFFECTS in NetHack.cnf. Configure + the BBS to expect I/O through stdin and stdout, and have NetHack + invoked as: + HackCLI :uid -u uname options... + where uid is any string (without embedded spaces, colons, or slashes) + that is unique for each BBS user and uname is some corresponding human- + readable name for that user. Uid is used in constructing file names + to prevent collisions between simultaneous games and to prevent + people from using other people's save files. Uname is the name the + character will have in the game and the name that will appear in the + record file. + + The terminal is assumed to be a 24x80 ANSI-compatible terminal. + The present version does not deal with situations such as low + memory gracefully - as NetHack uses a considerable amount of + memory this is particularly painful with multiple games in + progress. Sysops are reminded to be familiar with the recover + utility, which may be needed from time to time and which should + probably not be available directly to users. Bug reports and + suggestions for improvements are requested from the user community - + this is still considered alpha software. + diff --git a/sys/amiga/Makefile.agc b/sys/amiga/Makefile.agc new file mode 100644 index 0000000..ea1d36b --- /dev/null +++ b/sys/amiga/Makefile.agc @@ -0,0 +1,1337 @@ +# NetHack Makefile. +# SCCS Id: @(#)Makefile.agc 3.2 2000/01/12 +# Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1991,1992,1993,1996. +# NetHack may be freely redistributed. See license for details. + +### +### modified for gcc by Teemu Suikki (zu@iki.fi) +### +### note: you need to use smake.. sorry +### + +### +### DIRECTORY STRUCTURE +### + +NH = nh: + +SBIN = $(NH)sbin/ +SLIB = $(NH)slib/ +NETHACK = $(NH)NetHack/ +HACKEXE = $(NH)HackExe/ +AMI = $(NH)sys/amiga/ +DAT = $(NH)dat/ +DOC = $(NH)doc/ +I = $(NH)include/ +SHARE = $(NH)sys/share/ +NHS = $(NH)src/ +TTY = $(NH)win/tty/ +WSHARE = $(NH)win/share/ +UTIL = $(NH)util/ +O = $(NH)obj/ +OO = $(NH)objo/ +# NB: O and OO MUST be different directories + +### +### INVOCATION +### + +MAKE = smake + +# Startup makefile with: +# +# $(MAKE) -f $(AMI)Makefile.amigcc +# $(MAKE) -f $(AMI)Makefile.amigcc install +# +# You may use following targets on $(MAKE) command lines: +# all do it all (default) +# link just create binary from object files +# obj just create common object files +# obja just create amiga object files +# objs just create shared object files +# clean deletes the object files +# spotless deletes the object files, main binary, and more +# +# Note: We do not build the Guidebook here since it needs tbl +# (See the file sys/unix/Makefile.doc for more information) + +#[SAS5] [and gcc?] +# If we were to use the precompiled header file feature in a newer version +# of SAS/C, we would comment out these following two lines. +# If we don't use precompiled header files, we uncomment it as well. + +HDEP = $(I)hack.h +CSYM = + +#Pathname for uudecode program: +UUDEC = uudecode + +# Flex/Bison command assignments -- Useful only if you have flex/bison +FLEX = flex +BISON = bison +# FBFIL and FBLIB may be used, if required by your version of flex or bison, +# to specify additional files or libraries to be linked with +FBFIL = +FBLIB = #lib lib:compat.lib + +# If you're compiling this on a 1.3 system, you'll have to uncomment the +# following (for use with the ifchange script below). Also useful instead of +# "protect ifchange +s" +EXECUTE = execute + +# Headers we depend on +AMDEP = $(AMI)winproto.h $(AMI)winext.h $(AMI)windefs.h $(I)winami.h + +# Pathname for the C compiler being used. + +CC = gcc -c +ASM = as + +# Compilation flags for selected C Compiler: +# $(CFLAGS) should appear before filename arguments of $(CC) command line. + +CFLAGS = -O3 -I $(I) + +# Components of various link command lines: +# $(LINK) should be the pathname of the linker being used (with any options +# that should appear at the beginning of the command line). The name of the +# output file should appear immediately after $(LNSPEC). $(LIN) should +# appear before the list of object files in each link command. $(LLINK) +# should appear as the list of object files in the link command line that +# creates the NetHack executable. $(LLIB) should appear at the end of each +# link command line. + +LINK = gcc -noixemul -O3 +LIN = +LLINK = +LLIB = +FLLIB = +OBJSPEC = -o +PNSPEC = -o +LNSPEC = -o +CCLINK = gcc -noixemul +CLFLAGS = -O3 +INCLSPEC = -I +DEFSPEC = -D +IGNSPEC = -j + +### +### FILE LISTS +### + +# A more reasonable random number generator (recommended for the Amiga): + +RANDOBJ = $(O)random.o + +.PRECIOUS: $(I)config.h $(I)decl.h $(I)hack.h $(I)permonst.h $(I)you.h + +# Almost nothing below this line should have to be changed. +# (Exceptions are marked by [SAS6], [MANX], etc.) +# +# Other things that have to be reconfigured are in config.h, +# (amiconf.h, pcconf.h), and possibly system.h, tradstdc.h. + +# Object files for makedefs: + +MAKEOBJS = \ + $(OO)makedefs.o $(O)monst.o $(O)objects.o + +# Object files for special levels compiler: + +SPLEVOBJS = \ + $(OO)lev_yacc.o $(OO)lev_lex.o $(OO)lev_main.o \ + $(O)decl.o $(O)drawing.o $(O)monst.o \ + $(O)objects.o $(OO)panic.o + +# Object files for dungeon compiler + +DGNCOMPOBJS = \ + $(OO)dgn_yacc.o $(OO)dgn_lex.o $(OO)dgn_main.o $(O)alloc.o $(OO)panic.o + +# Object files for NetHack: + +COMMOBJ = \ + $(O)allmain.o $(O)alloc.o $(O)apply.o $(O)artifact.o \ + $(O)attrib.o $(O)ball.o $(O)bones.o $(O)botl.o \ + $(O)cmd.o $(O)dbridge.o $(O)decl.o $(O)detect.o \ + $(O)dig.o $(O)display.o $(O)dlb.o $(O)do.o \ + $(O)do_name.o $(O)do_wear.o $(O)dog.o $(O)dogmove.o \ + $(O)dokick.o $(O)dothrow.o $(O)drawing.o $(O)dungeon.o \ + $(O)eat.o $(O)end.o $(O)engrave.o $(O)exper.o \ + $(O)explode.o $(O)extralev.o $(O)files.o $(O)fountain.o \ + $(O)hack.o $(O)hacklib.o $(O)invent.o $(O)light.o \ + $(O)lock.o $(O)mail.o $(O)makemon.o $(O)mapglyph.o \ + $(O)mcastu.o $(O)mhitm.o $(O)mhitu.o $(O)minion.o \ + $(O)mklev.o $(O)mkmap.o $(O)mkmaze.o $(O)mkobj.o \ + $(O)mkroom.o $(O)mon.o $(O)mondata.o $(O)monmove.o \ + $(O)monst.o $(O)mplayer.o $(O)mthrowu.o $(O)muse.o \ + $(O)music.o $(O)o_init.o $(O)objects.o $(O)objnam.o \ + $(O)options.o $(O)pager.o $(O)pickup.o $(O)pline.o \ + $(O)polyself.o $(O)potion.o $(O)pray.o $(O)priest.o \ + $(O)quest.o $(O)questpgr.o $(O)read.o $(O)rect.o \ + $(O)region.o $(O)restore.o $(O)rnd.o $(O)role.o \ + $(O)rumors.o $(O)save.o $(O)shk.o $(O)shknam.o \ + $(O)sit.o $(O)sounds.o $(O)sp_lev.o $(O)spell.o \ + $(O)steal.o $(O)steed.o $(O)teleport.o $(O)timeout.o \ + $(O)topten.o $(O)track.o $(O)trap.o $(O)u_init.o \ + $(O)uhitm.o $(O)vault.o $(O)version.o $(O)vision.o \ + $(O)weapon.o $(O)were.o $(O)wield.o $(O)windows.o \ + $(O)wizard.o $(O)worm.o $(O)worn.o $(O)write.o \ + $(O)zap.o + +MAKEDEFOBJ = \ + $(O)monstr.o + +AMIGAOBJ = \ + $(O)amidos.o $(O)amirip.o $(O)amisnd.o $(O)amistack.o \ + $(O)amiwind.o $(O)winami.o $(O)winchar.o $(O)winfuncs.o \ + $(O)winkey.o $(O)winmenu.o $(O)winreq.o $(O)winstr.o + +# Objects from assembly sources (because DMake can't handle default rules) +AMIGAOBJ2 = \ +# $(O)dispmap.o + +SHAREOBJ = \ + $(O)pcmain.o $(RANDOBJ) + +TTYOBJ = \ + $(O)getline.o $(O)termcap.o $(O)topl.o $(O)wintty.o $(O)amitty.o \ + $(O)rip.o + +# Yuck yuck yuck. Have to tell DMake where these are, since they're not +# all in the same place. +TTYSRC = \ + $(TTY)getline.c $(TTY)termcap.c $(TTY)topl.c $(TTY)wintty.c \ + $(AMI)amitty.c $(NHS)rip.c + +# All the object files for NetHack: + +HOBJ = $(COMMOBJ) $(AMIGAOBJ) $(AMIGAOBJ2) $(SHAREOBJ) $(MAKEDEFOBJ) $(TTYOBJ) + +### +### DATA FILES +### + +# quest files +ADFILES1= $(SLIB)Arc-fila.lev $(SLIB)Arc-filb.lev $(SLIB)Arc-loca.lev \ + $(SLIB)Arc-strt.lev +ADFILES= $(SLIB)Arc-goal.lev $(ADFILES1) + +BDFILES1= $(SLIB)Bar-fila.lev $(SLIB)Bar-filb.lev $(SLIB)Bar-loca.lev \ + $(SLIB)Bar-strt.lev +BDFILES= $(SLIB)Bar-goal.lev $(BDFILES1) + +CDFILES1= $(SLIB)Cav-fila.lev $(SLIB)Cav-filb.lev $(SLIB)Cav-loca.lev \ + $(SLIB)Cav-strt.lev +CDFILES= $(SLIB)Cav-goal.lev $(CDFILES1) + +HDFILES1= $(SLIB)Hea-fila.lev $(SLIB)Hea-filb.lev $(SLIB)Hea-loca.lev \ + $(SLIB)Hea-strt.lev +HDFILES= $(SLIB)Hea-goal.lev $(HDFILES1) + +KDFILES1= $(SLIB)Kni-fila.lev $(SLIB)Kni-filb.lev $(SLIB)Kni-loca.lev \ + $(SLIB)Kni-strt.lev +KDFILES= $(SLIB)Kni-goal.lev $(KDFILES1) + +MDFILES1= $(SLIB)Mon-fila.lev $(SLIB)Mon-filb.lev $(SLIB)Mon-loca.lev \ + $(SLIB)Mon-strt.lev +MDFILES= $(SLIB)Mon-goal.lev $(MDFILES1) + +PDFILES1= $(SLIB)Pri-fila.lev $(SLIB)Pri-filb.lev $(SLIB)Pri-loca.lev \ + $(SLIB)Pri-strt.lev +PDFILES= $(SLIB)Pri-goal.lev $(PDFILES1) + +RDFILES1= $(SLIB)Rog-fila.lev $(SLIB)Rog-filb.lev $(SLIB)Rog-loca.lev \ + $(SLIB)Rog-strt.lev +RDFILES= $(SLIB)Rog-goal.lev $(RDFILES1) + +RANFILES1= $(SLIB)Ran-fila.lev $(SLIB)Ran-filb.lev $(SLIB)Ran-loca.lev \ + $(SLIB)Ran-strt.lev +RANFILES= $(SLIB)Ran-goal.lev $(RANFILES1) + +SDFILES1= $(SLIB)Sam-fila.lev $(SLIB)Sam-filb.lev $(SLIB)Sam-loca.lev \ + $(SLIB)Sam-strt.lev +SDFILES= $(SLIB)Sam-goal.lev $(SDFILES1) + +TDFILES1= $(SLIB)Tou-fila.lev $(SLIB)Tou-filb.lev $(SLIB)Tou-loca.lev \ + $(SLIB)Tou-strt.lev +TDFILES= $(SLIB)Tou-goal.lev $(TDFILES1) + +VDFILES1= $(SLIB)Val-fila.lev $(SLIB)Val-filb.lev $(SLIB)Val-loca.lev \ + $(SLIB)Val-strt.lev +VDFILES= $(SLIB)Val-goal.lev $(VDFILES1) + +WDFILES1= $(SLIB)Wiz-fila.lev $(SLIB)Wiz-filb.lev $(SLIB)Wiz-loca.lev \ + $(SLIB)Wiz-strt.lev +WDFILES= $(SLIB)Wiz-goal.lev $(WDFILES1) + +XDFILES= $(ADFILES) $(BDFILES) $(CDFILES) $(HDFILES) $(KDFILES) \ + $(MDFILES) $(PDFILES) $(RDFILES) $(RANFILES) $(SDFILES) $(TDFILES) \ + $(VDFILES) $(WDFILES) + +SOUNDFILES= \ + $(SBIN)cvtsnd \ + $(SLIB)sounds \ + $(SLIB)sounds/Bell $(SLIB)sounds/Bugle \ + $(SLIB)sounds/Drum_Of_Earthquake \ + $(SLIB)sounds/Fire_Horn $(SLIB)sounds/Frost_Horn \ + $(SLIB)sounds/Leather_Drum $(SLIB)sounds/Magic_Flute \ + $(SLIB)sounds/Magic_Harp $(SLIB)sounds/Tooled_Horn \ + $(SLIB)sounds/Wooden_Flute $(SLIB)sounds/Wooden_Harp + +TILEFILES= \ + $(SBIN)txt2iff \ + $(NETHACK)tiles \ + $(NETHACK)tiles/objects.iff \ + $(NETHACK)tiles/monsters.iff \ + $(NETHACK)tiles/other.iff + +INSTDUNGEONFILES1= \ + $(SLIB)air.lev $(SLIB)asmodeus.lev $(SLIB)astral.lev \ + $(SLIB)baalz.lev $(SLIB)bigrm-1.lev $(SLIB)bigrm-2.lev \ + $(SLIB)bigrm-3.lev $(SLIB)bigrm-4.lev $(SLIB)bigrm-5.lev \ + $(SLIB)castle.lev $(SLIB)dungeon $(SLIB)earth.lev \ + $(SLIB)fakewiz1.lev $(SLIB)fakewiz2.lev $(SLIB)fire.lev \ + $(SLIB)juiblex.lev $(SLIB)knox.lev $(SLIB)medusa-1.lev \ + $(SLIB)medusa-2.lev $(SLIB)minend-1.lev $(SLIB)minend-2.lev \ + $(SLIB)minetn-1.lev $(SLIB)minetn-2.lev $(SLIB)minefill.lev \ + $(SLIB)options $(SLIB)oracle.lev $(SLIB)orcus.lev \ + $(SLIB)sanctum.lev $(SLIB)soko1-1.lev $(SLIB)soko1-2.lev \ + $(SLIB)soko2-1.lev $(SLIB)soko2-2.lev $(SLIB)soko3-1.lev \ + $(SLIB)soko3-2.lev $(SLIB)soko4-1.lev $(SLIB)soko4-2.lev \ + $(SLIB)tower1.lev $(SLIB)tower2.lev $(SLIB)tower3.lev \ + $(SLIB)valley.lev $(SLIB)water.lev $(SLIB)wizard1.lev \ + $(SLIB)wizard2.lev $(SLIB)wizard3.lev \ + $(XDFILES) + +INSTDUNGEONFILES= $(NETHACK)NetHack.cnf $(INSTDUNGEONFILES1) + + +INSTDATAFILES= \ + $(NETHACK)license $(NETHACK)logfile $(NETHACK)record \ + $(NETHACK)tomb.iff $(NETHACK)amii.hlp $(NETHACK)Recover.txt \ + $(NETHACK)GuideBook.txt $(NETHACK)NetHack.txt $(NETHACK)Install.ami \ +# $(NETHACK)HackWB.hlp $(NETHACK)WBDefaults.def + +LIBFILES= \ + $(INSTDUNGEONFILES1) \ + $(SLIB)cmdhelp $(SLIB)data $(SLIB)dungeon \ + $(SLIB)help $(SLIB)hh $(SLIB)history \ + $(SLIB)opthelp $(SLIB)oracles $(SLIB)rumors \ + $(SLIB)quest.dat $(SLIB)wizhelp + +### +### Getting down to business: +### + +all: $(COMPACT_HEADERS) $(SBIN)lev_comp $(SBIN)dgn_comp $(SBIN)NetHack \ + $(SBIN)dlb $(NETHACK)recover #$(NETHACK)HackCli $(SBIN)splitter \ +# $(NETHACK)HackWB + +install: inst-data inst-dungeon inst-fonts inst-sounds inst-tiles \ + $(NETHACK)recover $(NETHACK)NetHack $(NETHACK)nhdat + #$(NETHACK)NetHack.dir inst-icons + +$(SBIN)NetHack: link + +$(NETHACK)NetHack: $(SBIN)NetHack + copy $(SBIN)NetHack $(NETHACK)NetHack + +## uuh this is messy.. smake has weird command line length limit +link: $(HOBJ) + list to t:link lformat="$(O)%s" $(O)\#?.o QUICK NOHEAD + echo "\#sh" to t:cc + echo "$(LINK) $(LNSPEC) $(SBIN)NetHack $(LIN) $(LLIB) $(LLINK) " >>t:cc noline + fmt -u -w 2500 t:link >>t:cc + sh t:cc + delete t:cc t:link + + +## dlb support +$(OO)dlb_main.o: $(UTIL)dlb_main.c $(HDEP) $(I)dlb.h $(I)date.h + $(CC) $(CFLAGS) $(OBJSPEC)$(OO)dlb_main.o $(UTIL)dlb_main.c + +$(SBIN)dlb: $(OO)dlb_main.o $(O)dlb.o $(O)alloc.o $(OO)panic.o + $(LINK) $(PNSPEC) $(SBIN)dlb $(LIN) $(OO)dlb_main.o $(O)dlb.o \ + $(O)alloc.o $(OO)panic.o $(LLIB) + +obj: $(HOBJ) + +obja: $(AMIGAOBJ) + +objs: $(SHAREOBJ) + + +SUFFIXES = .lev .des +.des.lev: + $(SBIN)lev_comp $< + +# The default method for creating object files: + +#$(O)%.o: $(NHS)%.c +.c.o: + $(CC) $(CFLAGS) $(CSYM) $(OBJSPEC)$@ $< + +clean: + -delete $(O)\#?.o $(OO)\#?.o + +spotless: clean + -delete $(SBIN)NetHack $(SBIN)lev_comp $(SBIN)makedefs $(SBIN)dgn_comp + -delete $(SBIN)cvtsnd $(SBIN)dlb $(SBIN)txt2iff $(SBIN)splitter + -delete $(SBIN)tilemap + -delete $(SLIB)data $(SLIB)rumors + -delete $(SLIB)\#?.lev + -delete $(SLIB)dungeon + -delete $(SLIB)cmdhelp $(SLIB)help $(SLIB)hh $(SLIB)history + -delete $(SLIB)opthelp $(SLIB)options $(SLIB)oracles + -delete $(SLIB)quest.dat $(SLIB)wizhelp +# -delete $(SLIB)earth.lev $(SLIB)air.lev $(SLIB)fire.lev +# -delete $(SLIB)water.lev $(SLIB)astral.lev +# -delete $(SLIB)tower1.lev $(SLIB)tower2.lev $(SLIB)tower3.lev +# -delete $(SLIB)fakewiz1.lev $(SLIB)fakewiz2.lev +# -delete $(SLIB)medusa-1.lev $(SLIB)medusa-2.lev +# -delete $(SLIB)oracle.lev $(SLIB)wizard1.lev $(SLIB)wizard2.lev +# -delete $(SLIB)wizard3.lev $(DAT)dungeon.pdf $(SLIB)valley.lev +# -delete $(SLIB)minefill.lev +# -delete $(SLIB)minetn-1 $(SLIB)minetn-2 $(SLIB)minend-1 $(SLIB)minend-2 +# -delete $(SLIB)soko1-1.lev $(SLIB)soko1-2.lev $(SLIB)soko2-1.lev +# -delete $(SLIB)soko2-2.lev $(SLIB)soko3-1.lev $(SLIB)soko3-2.lev +# -delete $(SLIB)soko4-1.lev $(SLIB)soko4-2.lev +# -delete $(ADFILES) +# -delete $(BDFILES) +# -delete $(CDFILES) +# -delete $(HDFILES) +# -delete $(KDFILES) +# -delete $(MDFILES) +# -delete $(PDFILES) +# -delete $(RDFILES) +# -delete $(RANFILES) +# -delete $(SDFILES) +# -delete $(TDFILES) +# -delete $(VDFILES) +# -delete $(WDFILES) + -delete $(I)onames.h $(I)pm.h $(I)date.h + -delete $(NHS)tile.c $(NHS)monstr.c + -delete $(I)tile.h +# -echo to $(I)onames.h "" noline +# -c:wait 2 +# -echo to $(I)pm.h "" noline +# -c:wait 2 +# -setdate $(UTIL)makedefs.c +# -c:wait 2 + +# Creating precompiled version of $(I)hack.h to save disk I/O. + +# +# Please note: The dependency lines for the modules here are +# deliberately incorrect. Including "hack.h" in +# the dependency list would cause a dependency +# loop. +# + +$(SBIN)makedefs: $(MAKEOBJS) + $(LINK) $(LNSPEC) $(SBIN)makedefs $(LIN) $(MAKEOBJS) $(LLIB) + +$(OO)makedefs.o: $(UTIL)makedefs.c $(I)config.h $(I)permonst.h $(I)monsym.h \ + $(I)objclass.h $(I)patchlevel.h $(I)qtext.h $(I)artilist.h + $(CC) $(DEFSPEC)MAKEDEFS_C $(CFLAGS) $(OBJSPEC)$@ $(UTIL)makedefs.c + +$(SBIN)lev_comp: $(SPLEVOBJS) + $(LINK) $(LNSPEC) $(SBIN)lev_comp $(LIN) $(SPLEVOBJS) $(FBFIL) $(FLLIB) + +$(SBIN)dgn_comp: $(DGNCOMPOBJS) + $(LINK) $(LNSPEC) $(SBIN)dgn_comp $(LIN) $(DGNCOMPOBJS) $(FBFIL) $(FLLIB) + +$(OO)lev_yacc.o: $(UTIL)lev_yacc.c $(HDEP) $(I)sp_lev.h $(I)pm.h $(I)onames.h +# setdate $(UTIL)lev_yacc.c + $(CC) $(DEFSPEC)LEV_LEX_C $(DEFSPEC)PREFIX="NH:slib/" $(CFLAGS) \ + $(DEFSPEC)alloca=malloc $(OBJSPEC)$@ $(UTIL)lev_yacc.c + +$(OO)lev_lex.o: $(UTIL)lev_lex.c $(HDEP) $(I)lev_comp.h $(I)sp_lev.h + $(CC) $(DEFSPEC)LEV_LEX_C $(CFLAGS) $(OBJSPEC)$@ $(UTIL)lev_lex.c + +$(OO)lev_main.o: $(UTIL)lev_main.c $(HDEP) $(I)pm.h $(I)onames.h $(I)date.h + $(CC) $(DEFSPEC)LEV_LEX_C $(DEFSPEC)AMIGA $(CFLAGS) $(OBJSPEC)$@ \ + $(UTIL)lev_main.c + +$(OO)dgn_yacc.o: $(UTIL)dgn_yacc.c $(HDEP) $(I)dgn_file.h $(I)patchlevel.h + $(CC) $(DEFSPEC)LEV_LEX_C $(CFLAGS) $(DEFSPEC)alloca=malloc \ + $(OBJSPEC)$@ $(UTIL)dgn_yacc.c + +$(OO)dgn_lex.o: $(UTIL)dgn_lex.c $(I)config.h $(I)dgn_comp.h $(I)dgn_file.h + $(CC) $(DEFSPEC)LEV_LEX_C $(CFLAGS) $(OBJSPEC)$@ $(UTIL)dgn_lex.c + +$(OO)dgn_main.o: $(UTIL)dgn_main.c $(I)config.h $(I)date.h + $(CC) $(DEFSPEC)LEV_LEX_C $(DEFSPEC)AMIGA $(CFLAGS) $(OBJSPEC)$@ \ + $(UTIL)dgn_main.c + +$(OO)panic.o: $(UTIL)panic.c $(HDEP) + +$(OO)recover.o: $(UTIL)recover.c $(I)config.h $(I)date.h + $(CC) $(DEFSPEC)LEV_LEX_C $(DEFSPEC)AMIGA $(CFLAGS) $(OBJSPEC)$@ \ + $(UTIL)recover.c + +$(NETHACK)recover: $(OO)recover.o + $(LINK) $(LNSPEC) $(NETHACK)recover $(LIN) $(OO)recover.o $(LLIB) + +# [OPTION] -- If you have flex/bison, leave these uncommented. Otherwise, +# comment them out and be careful! (You're not guaranteed to have the most +# up to date *_comp.c, *_comp.h and *_lex.c) + +$(I)lev_comp.h: $(UTIL)lev_yacc.c $(I)patchlevel.h + +$(UTIL)lev_yacc.c: $(UTIL)lev_comp.y $(I)patchlevel.h + $(BISON) -d $(UTIL)lev_comp.y +# copy y.tab.c $(UTIL)lev_yacc.c +# copy y.tab.h $(I)lev_comp.h + copy $(UTIL)lev_comp.tab.c $(UTIL)lev_yacc.c + copy $(UTIL)lev_comp.tab.h $(I)lev_comp.h +# delete y.tab.c +# delete y.tab.h + delete $(UTIL)lev_comp.tab.c + delete $(UTIL)lev_comp.tab.h + +$(UTIL)lev_lex.c: $(UTIL)lev_comp.l $(I)patchlevel.h + $(FLEX) $(UTIL)lev_comp.l + copy lex.yy.c $(UTIL)lev_lex.c + delete lex.yy.c + +$(I)dgn_comp.h: $(UTIL)dgn_yacc.c $(I)patchlevel.h + +$(UTIL)dgn_yacc.c: $(UTIL)dgn_comp.y $(I)patchlevel.h + $(BISON) -d $(UTIL)dgn_comp.y +# copy y.tab.c $(UTIL)dgn_yacc.c +# copy y.tab.h $(I)dgn_comp.h + copy $(UTIL)dgn_comp.tab.c $(UTIL)dgn_yacc.c + copy $(UTIL)dgn_comp.tab.h $(I)dgn_comp.h +# delete y.tab.c +# delete y.tab.h + delete $(UTIL)dgn_comp.tab.c + delete $(UTIL)dgn_comp.tab.h + +$(UTIL)dgn_lex.c: $(UTIL)dgn_comp.l $(I)patchlevel.h + $(FLEX) $(UTIL)dgn_comp.l + copy lex.yy.c $(UTIL)dgn_lex.c + delete lex.yy.c + +# +# The following include files depend on makedefs to be created. +# As a result, they are not defined in HACKINCL, instead, their +# dependencies are explicitly outlined here. +# + +# +# date.h should be remade any time any of the source or include code +# is modified. Unfortunately, this would make the contents of this +# file far more complex. Since "hack.h" depends on most of the include +# files, we kludge around this by making date.h dependent on hack.h, +# even though it doesn't include this file. +# + +$(I)date.h $(DAT)options: $(HDEP) $(SBIN)makedefs $(AMIGAOBJ) $(I)patchlevel.h + $(SBIN)makedefs -v + $(EXECUTE) ifchange MOVE $(I)t.date.h $(I)date.h + -c:wait 2 + +$(I)onames.h: $(SBIN)makedefs + $(SBIN)makedefs -o + $(EXECUTE) ifchange TOUCH $(I)t.onames.h $(I)onames.h $(I)decl.h + $(EXECUTE) ifchange MOVE $(I)t.onames.h $(I)onames.h + -c:wait 2 + +$(I)pm.h: $(SBIN)makedefs + $(SBIN)makedefs -p + $(EXECUTE) ifchange TOUCH $(I)t.pm.h $(I)pm.h $(I)decl.h $(I)youprop.h + $(EXECUTE) ifchange MOVE $(I)t.pm.h $(I)pm.h + -c:wait 2 + +$(SLIB)quest.dat: $(DAT)quest.txt $(SBIN)makedefs + $(SBIN)makedefs -q + +$(NHS)monstr.c: $(HDEP) $(SBIN)makedefs + $(SBIN)makedefs -m + -c:wait 2 + +$(SLIB)oracles: $(DAT)oracles.txt $(SBIN)makedefs + $(SBIN)makedefs -h + -c:wait 2 + +# +# The following programs vary depending on what OS you are using. +# As a result, they are not defined in HACKSRC and their dependencies +# are explicitly outlined here. +# + +$(O)amidos.o: $(AMI)amidos.c $(HDEP) + +$(O)amirip.o: $(AMI)amirip.c $(HDEP) + +$(O)aglue.o: $(AMI)aglue.a + $(ASM) $(AFLAGS) $(AOBJSPEC)$(O)aglue.o $(AMI)aglue.a + +$(O)amisnd.o: $(AMI)amisnd.c $(HDEP) + +$(O)winchar.o: $(AMI)winchar.c $(NHS)tile.c $(HDEP) + +$(NHS)tile.c: $(WSHARE)tilemap.c + $(CCLINK) $(CFLAGS) $(PNSPEC) $(SBIN)tilemap $(WSHARE)tilemap.c + $(SBIN)tilemap + +$(O)winstr.o: $(AMI)winstr.c $(HDEP) $(AMDEP) + +$(O)winreq.o: $(AMI)winreq.c $(HDEP) $(AMDEP) $(AMI)colorwin.c $(AMI)clipwin.c + +$(O)winfuncs.o: $(AMI)winfuncs.c $(HDEP) $(AMDEP) $(I)patchlevel.h + +$(O)winkey.o: $(AMI)winkey.c $(HDEP) $(AMDEP) + +$(O)winmenu.o: $(AMI)winmenu.c $(HDEP) $(AMDEP) + +$(O)winami.o: $(AMI)winami.c $(HDEP) $(AMDEP) #$(AMI)char.c $(AMI)randwin.c + +#$(O)amilib.o: $(AMI)amilib.c $(HDEP) $(AMDEP) + +$(O)amiwind.o: $(AMI)amiwind.c $(AMI)amimenu.c $(HDEP) $(AMDEP) + +$(O)amiwbench.o: $(AMI)amiwbench.c $(HDEP) + +$(O)random.o: $(SHARE)random.c + +$(O)pcmain.o: $(SHARE)pcmain.c $(HDEP) $(I)dlb.h + +$(O)dispmap.o: $(AMI)dispmap.s + $(ASM) $(AFLAGS) $(AOBJSPEC)$@ $< + +# Stuff to build the front ends +$(NETHACK)HackWB: $(OO)wb.o $(OO)wbx.o $(OO)loader.o $(OO)multi.o + $(LINK) $(LNSPEC) $(NETHACK)HackWB $(LIN) $(OO)wb.o $(OO)wbx.o \ + $(OO)loader.o $(OO)multi.o $(LLIB) + +$(NETHACK)HackCli: $(OO)cli.o $(OO)loader.o $(OO)multi.o + $(LINK) $(LNSPEC) $(NETHACK)HackCli $(LIN) $(OO)cli.o $(OO)loader.o \ + $(OO)multi.o $(LLIB) + +# This needs to exist to eliminate the HackWB startup message +$(NETHACK)WBDefaults.def: + echo to $(NETHACK)WBDefaults.def + +WBH = $(AMI)wbdefs.h $(AMI)wbstruct.h $(AMI)wbprotos.h +ASP = $(AMI)splitter +$(OO)wb.o: $(WBH) $(AMI)wb.c $(AMI)wbwin.c $(AMI)wbdata.c $(AMI)wbgads.c \ + $(I)patchlevel.h + $(CC) $(WBCFLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)wb.o $(AMI)wb.c + +$(OO)wbx.o: $(WBH) $(AMI)wbcli.c $(AMI)wbwin.c $(AMI)wbdata.c \ + $(I)patchlevel.h $(I)date.h + $(CC) $(WBCFLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)wbx.o $(AMI)wbcli.c + +$(OO)loader.o: $(ASP)/loader.c $(ASP)/split.h $(ASP)/amiout.h $(ASP)/multi.h + $(CC) $(WBCFLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)loader.o $(ASP)/loader.c + +$(OO)multi.o: $(ASP)/multi.c $(ASP)/multi.h + $(CC) $(WBCFLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)multi.o $(ASP)/multi.c + +$(OO)cli.o: $(WBH) $(AMI)wbcli.c $(I)patchlevel.h $(I)date.h + $(CC) $(WBCFLAGS) $(WBC2FLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)cli.o \ + $(AMI)wbcli.c + +#### +# splitter support +$(SBIN)splitter: $(OO)splitter.o $(OO)arg.o + $(LINK) $(LNSPEC) $(SBIN)splitter $(LIN) $(OO)splitter.o $(OO)arg.o \ + $(LLIB) + +$(NETHACK)NetHack.dir: $(SBIN)splitter $(SBIN)NetHack + $(SBIN)splitter $(SBIN)NetHack + +$(OO)splitter.o: $(ASP)/splitter.c $(ASP)/split.h $(ASP)/amiout.h $(ASP)/arg.h + $(CC) $(WBCFLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)splitter.o \ + $(ASP)/splitter.c + +$(OO)arg.o: $(ASP)/arg.c $(ASP)/arg.h + $(CC) $(WBCFLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)arg.o $(ASP)/arg.c + +# Create/copy other stuff into NetHack: directory: + +$(NETHACK)tomb.iff: $(SBIN)xpm2iff $(AMI)grave16.xpm + $(SBIN)xpm2iff $(AMI)grave16.xpm $(NETHACK)tomb.iff + +$(OO)xpm2iff.o: $(AMI)xpm2iff.c + $(CC) $(CFLAGS) $(INCLSPEC)$(WSHARE) $(OBJSPEC)$@ $(AMI)xpm2iff.c + +$(SBIN)xpm2iff: $(OO)xpm2iff.o + $(LINK) $(LNSPEC) $@ $(LIN) $(OO)xpm2iff.o $(FLLIB) + +# Tile installation for the tile version of the game +inst-tiles: $(TILEFILES) + +$(NETHACK)tiles: + -makedir $(NETHACK)tiles + +$(OO)txt2iff.o: $(AMI)txt2iff.c + $(CC) $(CFLAGS) $(CSYM) $(INCLSPEC)$(WSHARE) $(OBJSPEC)$@ \ + $(AMI)txt2iff.c + +$(OO)ppmwrite.o: $(WSHARE)ppmwrite.c + $(CC) $(CFLAGS) $(CSYM) $(INCLSPEC)$(WSHARE) $(OBJSPEC)$@ $(WSHARE)ppmwrite.c + +$(OO)tiletext.o: $(WSHARE)tiletext.c $(I)config.h $(WSHARE)tile.h + $(CC) $(CFLAGS) $(CSYM) $(INCLSPEC)$(WSHARE) $(OBJSPEC)$@ $(WSHARE)tiletext.c + +$(OO)tiletxt.o: $(WSHARE)tilemap.c $(I)hack.h + $(CC) $(CFLAGS) $(CSYM) $(DEFSPEC)TILETEXT $(INCLSPEC)$(WSHARE) $(OBJSPEC)$@ $(WSHARE)tilemap.c + +NAMEOBJS = $(O)drawing.o $(O)decl.o $(O)monst.o $(O)objects.o + +$(SBIN)txt2ppm: $(OO)ppmwrite.o $(NAMEOBJS) $(O)alloc.o $(OO)panic.o $(OO)tiletext.o $(OO)tiletxt.o + $(LINK) $(LNSPEC) $@ $(LIN) $(OO)ppmwrite.o $(NAMEOBJS) $(OO)tiletext.o $(OO)tiletxt.o $(O)alloc.o $(OO)panic.o $(FLLIB) + +$(SBIN)txt2iff: $(OO)txt2iff.o $(NAMEOBJS) $(OO)tiletext.o $(OO)tiletxt.o + $(LINK) $(LNSPEC) $@ $(LIN) $(OO)txt2iff.o $(NAMEOBJS) $(OO)tiletext.o \ + $(OO)tiletxt.o $(FLLIB) + +$(NETHACK)tiles/objects.iff: $(WSHARE)objects.txt $(SBIN)txt2iff + $(SBIN)txt2iff $(WSHARE)objects.txt $(NETHACK)tiles/objects.iff + +$(NETHACK)tiles/monsters.iff: $(WSHARE)monsters.txt $(SBIN)txt2iff + $(SBIN)txt2iff $(WSHARE)monsters.txt $(NETHACK)tiles/monsters.iff + +$(NETHACK)tiles/other.iff: $(WSHARE)other.txt $(SBIN)txt2iff + $(SBIN)txt2iff $(WSHARE)other.txt $(NETHACK)tiles/other.iff + +# Sound installation rules. +inst-sounds: $(SOUNDFILES) + list to T:nhsdat.lst $(SLIB)sounds QUICK NOHEAD + echo >T:make-nhsdat $(SBIN)dlb cCfI $(SLIB)sounds $(NETHACK)nhsdat T:nhsdat.lst + echo >>T:make-nhsdat if not exists $(NETHACK)nhsdat + echo >>T:make-nhsdat copy $(SLIB)sounds/\#? $(NETHACK)sounds + echo >>T:make-nhsdat endif + execute T:make-nhsdat + -delete T:make-nhsdat + +$(SLIB)sounds: + -makedir $(SLIB)sounds + +$(SBIN)cvtsnd: $(OO)cvtsnd.o + $(LINK) $(LNSPEC) $@ $(LIN) $(OO)cvtsnd.o $(FLLIB) + +$(OO)cvtsnd.o: $(AMI)cvtsnd.c + +$(SLIB)sounds/Bell: $(SHARE)sounds/bell.uu + $(UUDEC) $(SHARE)sounds/bell.uu + $(SBIN)cvtsnd Bell $(SLIB)sounds/Bell + -delete Bell + +$(SLIB)sounds/Bugle: $(SHARE)sounds/bugle.uu + $(UUDEC) $(SHARE)sounds/bugle.uu + $(SBIN)cvtsnd Bugle $(SLIB)sounds/Bugle + -delete Bugle + +$(SLIB)sounds/Drum_Of_Earthquake: $(SHARE)sounds/erthdrum.uu + $(UUDEC) $(SHARE)sounds/erthdrum.uu + $(SBIN)cvtsnd Drum_Of_Earthquake $(SLIB)sounds/Drum_Of_Earthquake + -delete Drum_Of_Earthquake + +$(SLIB)sounds/Fire_Horn: $(SHARE)sounds/firehorn.uu + $(UUDEC) $(SHARE)sounds/firehorn.uu + $(SBIN)cvtsnd Fire_Horn $(SLIB)sounds/Fire_Horn + -delete Fire_Horn + +$(SLIB)sounds/Frost_Horn: $(SHARE)sounds/frsthorn.uu + $(UUDEC) $(SHARE)sounds/frsthorn.uu + $(SBIN)cvtsnd Frost_Horn $(SLIB)sounds/Frost_Horn + -delete Frost_Horn + +$(SLIB)sounds/Leather_Drum: $(SHARE)sounds/lethdrum.uu + $(UUDEC) $(SHARE)sounds/lethdrum.uu + $(SBIN)cvtsnd Leather_Drum $(SLIB)sounds/Leather_Drum + -delete Leather_Drum + +$(SLIB)sounds/Magic_Flute: $(SHARE)sounds/mgcflute.uu + $(UUDEC) $(SHARE)sounds/mgcflute.uu + $(SBIN)cvtsnd Magic_Flute $(SLIB)sounds/Magic_Flute + -delete Magic_Flute + +$(SLIB)sounds/Magic_Harp: $(SHARE)sounds/mgcharp.uu + $(UUDEC) $(SHARE)sounds/mgcharp.uu + $(SBIN)cvtsnd Magic_Harp $(SLIB)sounds/Magic_Harp + -delete Magic_Harp + +$(SLIB)sounds/Tooled_Horn: $(SHARE)sounds/toolhorn.uu + $(UUDEC) $(SHARE)sounds/toolhorn.uu + $(SBIN)cvtsnd Tooled_Horn $(SLIB)sounds/Tooled_Horn + -delete Tooled_Horn + +$(SLIB)sounds/Wooden_Flute: $(SHARE)sounds/wdnflute.uu + $(UUDEC) $(SHARE)sounds/wdnflute.uu + $(SBIN)cvtsnd Wooden_Flute $(SLIB)sounds/Wooden_Flute + -delete Wooden_Flute + +$(SLIB)sounds/Wooden_Harp: $(SHARE)sounds/wdnharp.uu + $(UUDEC) $(SHARE)sounds/wdnharp.uu + $(SBIN)cvtsnd Wooden_Harp $(SLIB)sounds/Wooden_Harp + -delete Wooden_Harp + +inst-dungeon: $(INSTDUNGEONFILES) + +$(NETHACK)options : $(DAT)options + copy $(DAT)options $@ + +# Create compiled dungeon files +BGM= $(SLIB)bigrm-2.lev $(SLIB)bigrm-3.lev $(SLIB)bigrm-4.lev $(SLIB)bigrm-5.lev +$(BGM): $(SLIB)bigrm-1.lev + +$(SLIB)bigrm-1.lev: $(DAT)bigroom.des $(SBIN)lev_comp + +$(SLIB)castle.lev: $(DAT)castle.des $(SBIN)lev_comp + +ENDGAME1= $(SLIB)air.lev $(SLIB)earth.lev $(SLIB)fire.lev $(SLIB)water.lev +$(ENDGAME1): $(SLIB)astral.lev + +$(SLIB)astral.lev: $(DAT)endgame.des $(SBIN)lev_comp + +GEHENNOM1= $(SLIB)asmodeus.lev $(SLIB)baalz.lev $(SLIB)juiblex.lev \ + $(SLIB)orcus.lev $(SLIB)sanctum.lev +$(GEHENNOM1): $(SLIB)valley.lev + +$(SLIB)valley.lev: $(DAT)gehennom.des $(SBIN)lev_comp + +$(SLIB)knox.lev: $(DAT)knox.des $(SBIN)lev_comp + +MINES1= $(SLIB)minend-1.lev $(SLIB)minend-2.lev $(SLIB)minetn-1.lev $(SLIB)minetn-2.lev +$(MINES1): $(SLIB)minefill.lev + +$(SLIB)minefill.lev: $(DAT)mines.des $(SBIN)lev_comp + +$(SLIB)oracle.lev: $(DAT)oracle.des $(SBIN)lev_comp + +TOWER1= $(SLIB)tower1.lev $(SLIB)tower2.lev +$(TOWER1): $(SLIB)tower3.lev + +$(SLIB)tower3.lev: $(DAT)tower.des $(SBIN)lev_comp + +WIZARD1= $(SLIB)wizard1.lev $(SLIB)wizard2.lev $(SLIB)wizard3.lev \ + $(SLIB)fakewiz1.lev +$(WIZARD1): $(SLIB)fakewiz2.lev + +$(SLIB)fakewiz2.lev: $(DAT)yendor.des $(SBIN)lev_comp + +MEDUSA1= $(SLIB)medusa-1.lev +$(MEDUSA1): $(SLIB)medusa-2.lev + +$(SLIB)medusa-2.lev: $(DAT)medusa.des $(SBIN)lev_comp + +SOKOBAN1= $(SLIB)soko1-1.lev $(SLIB)soko1-2.lev $(SLIB)soko2-1.lev \ + $(SLIB)soko2-2.lev $(SLIB)soko3-1.lev $(SLIB)soko3-2.lev \ + $(SLIB)soko4-1.lev +$(SOKOBAN1): $(SLIB)soko4-2.lev + +$(SLIB)soko4-2.lev: $(DAT)sokoban.des $(SBIN)lev_comp + +$(ADFILES1): $(SLIB)Arc-goal.lev + +$(SLIB)Arc-goal.lev: $(DAT)Arch.des $(SBIN)lev_comp + +$(BDFILES1): $(SLIB)Bar-goal.lev + +$(SLIB)Bar-goal.lev: $(DAT)Barb.des $(SBIN)lev_comp + +$(CDFILES1): $(SLIB)Cav-goal.lev + +$(SLIB)Cav-goal.lev: $(DAT)Caveman.des $(SBIN)lev_comp + +$(HDFILES1): $(SLIB)Hea-goal.lev + +$(SLIB)Hea-goal.lev: $(DAT)Healer.des $(SBIN)lev_comp + +$(KDFILES1): $(SLIB)Kni-goal.lev + +$(SLIB)Kni-goal.lev: $(DAT)Knight.des $(SBIN)lev_comp + +$(MDFILES1): $(SLIB)Mon-goal.lev + +$(SLIB)Mon-goal.lev: $(DAT)Monk.des $(SBIN)lev_comp + +$(PDFILES1): $(SLIB)Pri-goal.lev + +$(SLIB)Pri-goal.lev: $(DAT)Priest.des $(SBIN)lev_comp + +$(RDFILES1): $(SLIB)Rog-goal.lev + +$(SLIB)Rog-goal.lev: $(DAT)Rogue.des $(SBIN)lev_comp + +$(RANFILES1): $(SLIB)Ran-goal.lev + +$(SLIB)Ran-goal.lev: $(DAT)Ranger.des $(SBIN)lev_comp + +$(SDFILES1): $(SLIB)Sam-goal.lev + +$(SLIB)Sam-goal.lev: $(DAT)Samurai.des $(SBIN)lev_comp + +$(TDFILES1): $(SLIB)Tou-goal.lev + +$(SLIB)Tou-goal.lev: $(DAT)Tourist.des $(SBIN)lev_comp + +$(VDFILES1): $(SLIB)Val-goal.lev + +$(SLIB)Val-goal.lev: $(DAT)Valkyrie.des $(SBIN)lev_comp + +$(WDFILES1): $(SLIB)Wiz-goal.lev + +$(SLIB)Wiz-goal.lev: $(DAT)Wizard.des $(SBIN)lev_comp + +$(SLIB)dungeon: $(DAT)dungeon.def $(SBIN)makedefs $(SBIN)dgn_comp + $(SBIN)makedefs -e + $(SBIN)dgn_comp $(DAT)dungeon.pdf + copy $(DAT)dungeon $(SLIB)dungeon + delete $(DAT)dungeon + +inst-data: $(INSTDATAFILES) + +$(NETHACK)amii.hlp: $(AMI)amii.hlp + copy $(AMI)amii.hlp $@ + +#$(NETHACK)data: $(DAT)data +# copy $(DAT)data $@ + +$(SLIB)data: $(DAT)data.base $(I)config.h $(SBIN)makedefs + $(SBIN)makedefs -d + +#$(NETHACK)rumors: $(DAT)rumors +# copy $(DAT)rumors $@ + +$(SLIB)rumors: $(DAT)rumors.tru $(DAT)rumors.fal $(SBIN)makedefs + $(SBIN)makedefs -r + +$(SLIB)cmdhelp: $(DAT)cmdhelp + copy $(DAT)cmdhelp $@ + +$(SLIB)help: $(DAT)help + copy $(DAT)help $@ + +$(SLIB)hh: $(DAT)hh + copy $(DAT)hh $@ + +$(NETHACK)HackWB.hlp: $(AMI)HackWB.hlp + copy $(AMI)HackWB.hlp $@ + +$(SLIB)history: $(DAT)history + copy $(DAT)history $@ + +$(NETHACK)license: $(DAT)license + copy $(DAT)license $@ + +$(SLIB)opthelp: $(DAT)opthelp + copy $(DAT)opthelp $@ + +$(NETHACK)Recover.txt: $(DOC)Recover.txt + copy $(DOC)Recover.txt $@ + +$(NETHACK)GuideBook.txt: $(DOC)GuideBook.txt + copy $(DOC)GuideBook.txt $@ + +$(NETHACK)NetHack.txt: $(DOC)NetHack.txt + copy $(DOC)NetHack.txt $@ + +$(NETHACK)Install.ami: $(AMI)Install.ami + copy $(AMI)Install.ami $@ + +$(NETHACK)logfile: + echo to $@ + +$(NETHACK)record: + echo to $@ + +$(SLIB)wizhelp: $(DAT)wizhelp + copy $(DAT)wizhelp $@ + +# Create the directories here because NetHack.cnf puts them there by default +$(NETHACK)NetHack.cnf: $(AMI)NetHack.cnf + copy $(AMI)NetHack.cnf $@ + -makedir $(NETHACK)save + -makedir $(NETHACK)levels + +# Unpack and install fonts + +INSTFONTFILES= $(NETHACK)hack.font $(NETHACK)hack $(NETHACK)hack/8 + +inst-fonts: $(INSTFONTFILES) + +$(NETHACK)hack/8: $(AMI)amifont8.uu $(NETHACK)hack + $(UUDEC) $(AMI)amifont8.uu + copy 8 $(NETHACK)hack/8 + delete 8 + +$(NETHACK)hack.font: $(AMI)amifont.uu + $(UUDEC) $(AMI)amifont.uu + copy hack.font $(NETHACK)hack.font + delete hack.font + +$(NETHACK)hack: + -makedir $@ + +INSTICONFILES= \ + $(NETHACK)default.icon $(NETHACK)NetHack.info $(NETHACK)NewGame.info \ + $(NETHACK)HackWB.info + +inst-icons: $(INSTICONFILES) + +# Unpack the icons into place + +$(NETHACK)default.icon: $(AMI)dflticon.uu + $(UUDEC) $(AMI)dflticon.uu +# copy default.icon $(NETHACK)default.icon +# delete default.icon + +$(NETHACK)NetHack.info: $(AMI)NHinfo.uu + $(UUDEC) $(AMI)NHinfo.uu +# copy NetHack.info $(NETHACK)NetHack.info +# delete NetHack.info + +$(NETHACK)NewGame.info: $(AMI)NewGame.uu + $(UUDEC) $(AMI)NewGame.uu +# copy NewGame.info $(NETHACK)NewGame.info +# delete NewGame.info + +$(NETHACK)HackWB.info: $(AMI)HackWB.uu + $(UUDEC) $(AMI)HackWB.uu +# copy HackWB.info $(NETHACK)HackWB.info +# delete HackWB.info + +# If DLB is defined, create the nhdat library file in the playground +# directory. If not, move all the data files there. +$(NETHACK)nhdat: $(LIBFILES) + list to T:nhdat.lst $(SLIB) QUICK NOHEAD FILES + echo >T:make-nhdat $(SBIN)dlb cCfI $(SLIB) $(NETHACK)nhdat T:nhdat.lst + echo >>T:make-nhdat if not exists $(NETHACK)nhdat + echo >>T:make-nhdat copy $(SLIB)\#? $(NETHACK) + echo >>T:make-nhdat endif + execute T:make-nhdat + -delete T:make-nhdat + +# DO NOT DELETE THIS LINE + +$(O)allmain.o: $(NHS)allmain.c $(HDEP) + +$(O)alloc.o: $(NHS)alloc.c $(I)config.h + +$(O)apply.o: $(NHS)apply.c $(HDEP) $(I)edog.h + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)apply.c + +$(O)artifact.o: $(NHS)artifact.c $(HDEP) $(I)artifact.h $(I)artilist.h + +$(O)attrib.o: $(NHS)attrib.c $(HDEP) $(I)artifact.h + +$(O)ball.o: $(NHS)ball.c $(HDEP) + +$(O)bones.o: $(NHS)bones.c $(HDEP) $(I)lev.h + +$(O)botl.o: $(NHS)botl.c $(HDEP) + +$(O)cmd.o: $(NHS)cmd.c $(HDEP) $(I)func_tab.h + +$(O)dbridge.o: $(NHS)dbridge.c $(HDEP) + +$(O)decl.o: $(NHS)decl.c $(HDEP) $(I)quest.h + +$(O)detect.o: $(NHS)detect.c $(HDEP) $(I)artifact.h + +$(O)dig.o: $(NHS)dig.c $(HDEP) $(I)edog.h + +$(O)display.o: $(NHS)display.c $(HDEP) + +$(O)dlb.o: $(NHS)dlb.c $(HDEP) $(I)dlb.h + +$(O)do.o: $(NHS)do.c $(HDEP) $(I)lev.h + +$(O)do_name.o: $(NHS)do_name.c $(HDEP) + +$(O)do_wear.o: $(NHS)do_wear.c $(HDEP) + +$(O)dog.o: $(NHS)dog.c $(HDEP) $(I)edog.h + +$(O)dogmove.o: $(NHS)dogmove.c $(HDEP) $(I)mfndpos.h $(I)edog.h + +$(O)dokick.o: $(NHS)dokick.c $(HDEP) $(I)eshk.h + +$(O)dothrow.o: $(NHS)dothrow.c $(HDEP) + +$(O)drawing.o: $(NHS)drawing.c $(HDEP) $(I)tcap.h + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)drawing.c + +$(O)dungeon.o: $(NHS)dungeon.c $(HDEP) $(I)dgn_file.h $(I)dlb.h + +$(O)eat.o: $(NHS)eat.c $(HDEP) + +$(O)end.o: $(NHS)end.c $(HDEP) $(I)eshk.h $(I)dlb.h + +$(O)engrave.o: $(NHS)engrave.c $(HDEP) $(I)lev.h + +$(O)exper.o: $(NHS)exper.c $(HDEP) + +$(O)explode.o: $(NHS)explode.c $(HDEP) + +$(O)extralev.o: $(NHS)extralev.c $(HDEP) + +$(O)files.o: $(NHS)files.c $(HDEP) $(I)dlb.h $(I)date.h + +$(O)fountain.o: $(NHS)fountain.c $(HDEP) + +$(O)hack.o: $(NHS)hack.c $(HDEP) + +$(O)hacklib.o: $(NHS)hacklib.c $(HDEP) + +$(O)invent.o: $(NHS)invent.c $(HDEP) $(I)artifact.h + +$(O)light.o: $(NHS)light.c $(HDEP) $(I)lev.h + +$(O)lock.o: $(NHS)lock.c $(HDEP) + +$(O)mail.o: $(NHS)mail.c $(HDEP) $(I)mail.h + +$(O)makemon.o: $(NHS)makemon.c $(HDEP) $(I)epri.h $(I)emin.h $(I)edog.h + +$(O)mapglyph.o: $(NHS)mapglyph.c $(HDEP) + +$(O)mcastu.o: $(NHS)mcastu.c $(HDEP) + +$(O)mhitm.o: $(NHS)mhitm.c $(HDEP) $(I)artifact.h $(I)edog.h + +$(O)mhitu.o: $(NHS)mhitu.c $(HDEP) $(I)artifact.h $(I)edog.h + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)mhitu.c + +$(O)minion.o: $(NHS)minion.c $(HDEP) $(I)emin.h $(I)epri.h + +$(O)mklev.o: $(NHS)mklev.c $(HDEP) + +$(O)mkmap.o: $(NHS)mkmap.c $(HDEP) $(I)sp_lev.h + +$(O)mkmaze.o: $(NHS)mkmaze.c $(HDEP) $(I)sp_lev.h $(I)lev.h + +$(O)mkobj.o: $(NHS)mkobj.c $(HDEP) $(I)artifact.h $(I)prop.h + +$(O)mkroom.o: $(NHS)mkroom.c $(HDEP) + +$(O)mon.o: $(NHS)mon.c $(HDEP) $(I)mfndpos.h $(I)edog.h + +$(O)mondata.o: $(NHS)mondata.c $(HDEP) $(I)eshk.h $(I)epri.h + +$(O)monmove.o: $(NHS)monmove.c $(HDEP) $(I)mfndpos.h $(I)artifact.h + +$(O)monst.o: $(NHS)monst.c $(I)config.h $(I)permonst.h $(I)monsym.h \ + $(I)eshk.h $(I)vault.h $(I)epri.h $(I)color.h + +$(O)monstr.o: $(NHS)monstr.c $(HDEP) + +$(O)mplayer.o: $(NHS)mplayer.c $(HDEP) + +$(O)mthrowu.o: $(NHS)mthrowu.c $(HDEP) + +$(O)muse.o: $(NHS)muse.c $(HDEP) + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)muse.c + +$(O)music.o: $(NHS)music.c $(HDEP) #interp.c + +$(O)o_init.o: $(NHS)o_init.c $(HDEP) $(I)lev.h + +$(O)objects.o: $(NHS)objects.c $(I)config.h $(I)obj.h $(I)objclass.h \ + $(I)prop.h $(I)skills.h $(I)color.h + $(CC) $(CFLAGS) $(INCLSPEC)$(NHS) $(OBJSPEC)$@ $(NHS)objects.c + +$(O)objnam.o: $(NHS)objnam.c $(HDEP) + +$(O)options.o: $(NHS)options.c $(HDEP) $(I)tcap.h $(I)config.h \ + $(I)objclass.h $(I)flag.h + +$(O)pager.o: $(NHS)pager.c $(HDEP) $(I)dlb.h + +$(O)pickup.o: $(NHS)pickup.c $(HDEP) + +$(O)pline.o: $(NHS)pline.c $(HDEP) $(I)epri.h + +$(O)polyself.o: $(NHS)polyself.c $(HDEP) + +$(O)potion.o: $(NHS)potion.c $(HDEP) + +$(O)pray.o: $(NHS)pray.c $(HDEP) $(I)epri.h + +$(O)priest.o: $(NHS)priest.c $(HDEP) $(I)mfndpos.h $(I)eshk.h $(I)epri.h \ + $(I)emin.h + +$(O)quest.o: $(NHS)quest.c $(HDEP) $(I)quest.h $(I)qtext.h + +$(O)questpgr.o: $(NHS)questpgr.c $(HDEP) $(I)qtext.h $(I)dlb.h + +$(O)read.o: $(NHS)read.c $(HDEP) + +$(O)rect.o: $(NHS)rect.c $(HDEP) + +$(O)region.o: $(NHS)region.c $(HDEP) + +$(O)restore.o: $(NHS)restore.c $(HDEP) $(I)lev.h $(I)tcap.h $(I)quest.h + +$(O)rnd.o: $(NHS)rnd.c $(HDEP) + +$(O)role.o: $(NHS)role.c $(HDEP) + +$(O)rumors.o: $(NHS)rumors.c $(HDEP) $(I)dlb.h + +$(O)save.o: $(NHS)save.c $(HDEP) $(I)lev.h $(I)quest.h + +$(O)shk.o: $(NHS)shk.c $(HDEP) $(I)eshk.h + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)shk.c + +$(O)shknam.o: $(NHS)shknam.c $(HDEP) $(I)eshk.h + +$(O)sit.o: $(NHS)sit.c $(HDEP) $(I)artifact.h + +$(O)sounds.o: $(NHS)sounds.c $(HDEP) $(I)edog.h + +$(O)sp_lev.o: $(NHS)sp_lev.c $(HDEP) $(I)sp_lev.h $(I)rect.h $(I)dlb.h + +$(O)spell.o: $(NHS)spell.c $(HDEP) + +$(O)steal.o: $(NHS)steal.c $(HDEP) + +$(O)steed.o: $(NHS)steed.c $(HDEP) + +$(O)teleport.o: $(NHS)teleport.c $(HDEP) + +$(O)timeout.o: $(NHS)timeout.c $(HDEP) $(I)lev.h + +$(O)topten.o: $(NHS)topten.c $(HDEP) $(I)dlb.h + +$(O)track.o: $(NHS)track.c $(HDEP) + +$(O)trap.o: $(NHS)trap.c $(HDEP) + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)trap.c + +$(O)u_init.o: $(NHS)u_init.c $(HDEP) + +$(O)uhitm.o: $(NHS)uhitm.c $(HDEP) + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)uhitm.c + +$(O)vault.o: $(NHS)vault.c $(HDEP) $(I)vault.h + +$(O)version.o: $(NHS)version.c $(HDEP) $(I)date.h $(I)patchlevel.h + +$(O)vision.o: $(NHS)vision.c $(HDEP) #$(I)vis_tab.h + +$(O)weapon.o: $(NHS)weapon.c $(HDEP) + +$(O)were.o: $(NHS)were.c $(HDEP) + +$(O)wield.o: $(NHS)wield.c $(HDEP) + +$(O)windows.o: $(NHS)windows.c $(HDEP) $(I)wintty.h + +$(O)wizard.o: $(NHS)wizard.c $(HDEP) $(I)qtext.h + +$(O)worm.o: $(NHS)worm.c $(HDEP) $(I)lev.h + +$(O)worn.o: $(NHS)worn.c $(HDEP) + +$(O)write.o: $(NHS)write.c $(HDEP) + +$(O)zap.o: $(NHS)zap.c $(HDEP) + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)zap.c + +$(O)getline.o: $(TTY)getline.c $(HDEP) $(I)wintty.h + +$(O)termcap.o: $(TTY)termcap.c $(HDEP) $(I)wintty.h $(I)tcap.h + +$(O)topl.o: $(TTY)topl.c $(HDEP) $(I)wintty.h $(I)tcap.h + +$(O)wintty.o: $(TTY)wintty.c $(HDEP) $(I)wintty.h $(I)tcap.h \ + $(I)patchlevel.h + +$(O)amitty.o: $(AMI)amitty.c $(HDEP) + +$(O)amistack.o: $(AMI)amistack.c + $(CC) $(CFLAGS3) $(CSYM) $(OBJSPEC)$@ $(AMI)amistack.c + +$(O)rip.o: $(NHS)rip.c $(HDEP) + + +$(I)config.h: $(I)config1.h $(I)tradstdc.h $(I)global.h + -setdate $(I)config.h + -c:wait 2 + +# onames.h handled at onames.h target, pm.h + +$(I)decl.h: $(I)quest.h $(I)spell.h $(I)color.h $(I)obj.h $(I)you.h + -setdate $(I)decl.h + -c:wait 2 + +$(I)global.h: $(I)coord.h $(I)pcconf.h $(I)amiconf.h + -setdate $(I)global.h + -c:wait 2 + +$(I)hack.h: $(I)config.h $(I)trap.h $(I)decl.h $(I)dungeon.h $(I)monsym.h \ + $(I)mkroom.h $(I)objclass.h $(I)flag.h $(I)rm.h $(I)vision.h \ + $(I)display.h $(I)wintype.h $(I)engrave.h $(I)rect.h \ + $(I)region.h $(I)trampoli.h + -setdate $(I)hack.h + -c:wait 2 + +$(I)permonst.h: $(I)monattk.h $(I)monflag.h $(I)align.h + -setdate $(I)permonst.h + -c:wait 2 + +$(I)you.h: $(I)align.h $(I)attrib.h $(I)monst.h $(I)youprop.h $(I)skills.h + -setdate $(I)you.h + -c:wait 2 + +# pm.h handled at target + +$(I)youprop.h: $(I)prop.h $(I)permonst.h $(I)mondata.h + -setdate $(I)youprop.h + -c:wait 2 + +$(I)display.h: $(I)vision.h $(I)mondata.h + -setdate $(I)display.h + -c:wait 2 + +$(I)dungeon.h: $(I)align.h + -setdate $(I)dungeon.h + -c:wait 2 + +$(I)emin.h: $(I)dungeon.h + -setdate $(I)emin.h + -c:wait 2 + +$(I)epri.h: $(I)dungeon.h $(I)align.h + -setdate $(I)epri.h + -c:wait 2 + +$(I)eshk.h: $(I)dungeon.h + -setdate $(I)eshk.h + -c:wait 2 + +$(I)engrave.h: $(I)trampoli.h $(I)rect.h + -setdate $(I)engrave.h + -c:wait 2 + +$(I)mondata.h: $(I)align.h + -setdate $(I)mondata.h + -c:wait 2 + +$(I)monst.h: $(I)align.h + -setdate $(I)monst.h + -c:wait 2 + +$(I)pcconf.h: $(I)micro.h $(I)system.h + -setdate $(I)pcconf.h + -c:wait 2 + +$(I)rm.h: $(I)align.h + -setdate $(I)rm.h + -c:wait 2 + +$(I)vault.h: $(I)dungeon.h + -setdate $(I)vault.h + -c:wait 2 + +#notes +# install keeps doing re-install because it keeps rebuilding lev_comp??? +# fixed(?) - deleted setdate diff --git a/sys/amiga/Makefile.ami b/sys/amiga/Makefile.ami new file mode 100644 index 0000000..5e334a9 --- /dev/null +++ b/sys/amiga/Makefile.ami @@ -0,0 +1,1679 @@ +# NetHack Makefile. +# SCCS Id: @(#)Makefile.ami 3.4 2002/21/02 +# Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1991,1992,1993,1996. +# NetHack may be freely redistributed. See license for details. + +### +### INTRODUCTION +### + +# This makefile is arranged for compiling for the Amiga with SAS/C 6.51 but +# can be configured for compiling with Manx C 5 or commercial DICE with +# simple changes. The appropriate changes are identified by #[compiler] +# where compiler is one of: SAS6, MANX, or DICE; the options in this +# makefile as should be set according to the compiler being used. (But see +# note 3 below.) + +# Note: When using the Manx compiler, an alternate make utility is +# required. The bundled Aztec make is just too damaged. + +# Note 2: The #SFD_xxx lines are used with mkdmake to generate a DMake- +# compatible makefile (DMakefile) from this file. Any line beginning with +# #SFD_INSTEAD replaces, in DMakefile, the following line from Makefile.ami. +# #SFD_BEGIN, #SFD_ELSE, and #SFD_END bracket multi-line sections for the two +# makefile formats. +# When changing this file, #SFD_INSTEAD lines will need to be inserted for +# the following cases: +# - Dependencies with different numbers of filenames (both > 1) on +# either side. The #SFD_INSTEAD line should immediately precede +# the line with the colon, and should contain a double colon "::" +# instead of a single colon. +# - Special command lists that override the default. A line containing +# "#SFD_INSTEAD #none" should precede such a rule. If the rule is +# more than one line long, precede it with "#SFD_BEGIN" and +# "#SFD_ELSE", and follow it with "#SFD_END". +# - Files not in the src, sys/amiga, sys/share, or win/tty directories +# that rely on the default ".c.o" rule. Following the dependency +# should be "#SFD_INSTEAD " with the filename inserted +# into the default rule where appropriate, then a line contianing +# "#none". +# In any SFD_BEGIN/ELSE/END block added, put a '##' before every line +# between the BEGIN and ELSE. Any line that's really a comment needs three +# '#'s, e.g. "### DICE comment". + +# Note 2A: Whenever an SFD line/block is added, the appropriate repeat count +# in mkdmake must be changed. (The repeat count "0" meaning "repeat +# until end of file" doesn't work as advertised.) + +# Note 3: mkdmake will automatically substitute DICE flags, etc. for SAS +# where appropriate. Since the makefile is already set up for SAS, +# the only people who end up having to make changes here are Manx +# users (or people who want to change the defaults). + +### +### DIRECTORY STRUCTURE +### + +NH = NH: +SBIN = $(NH)sbin/ +SLIB = $(NH)slib/ +NETHACK = $(NH)NetHack/ +HACKEXE = $(NH)HackExe/ +AMI = $(NH)sys/amiga/ +DAT = $(NH)dat/ +DOC = $(NH)doc/ +I = $(NH)include/ +SHARE = $(NH)sys/share/ +NHS = $(NH)src/ +TTY = $(NH)win/tty/ +WSHARE = $(NH)win/share/ +UTIL = $(NH)util/ +O = $(NH)obj/ +OO = $(NH)objo/ +# NB: O and OO MUST be different directories + +### +### INVOCATION +### + +#[SAS6] +#MAKE = smake +#[MANX] +#MAKE = make +#[DICE] +#MAKE = dmake + +# Startup makefile with: +# +#[SAS6] +#[MANX] +# $(MAKE) -f $(AMI)Makefile.ami +# $(MAKE) -f $(AMI)Makefile.ami install +# +#[DICE] +# $(MAKE) -f $(AMI)DMakefile +# $(MAKE) -f $(AMI)DMakefile install +# +# +# You may use following targets on $(MAKE) command lines: +# all do it all (default) +# link just create binary from object files +# obj just create common object files +# obja just create amiga object files +# objs just create shared object files +# clean deletes the object files +# spotless deletes the object files, main binary, and more +# +# Note: We do not build the Guidebook here since it needs tbl +# (See the file sys/unix/Makefile.doc for more information) + +#X# Precompiled header files: +#X# $(HDEP) should appear in any dependency list for an object file where +#X# we would want to make use of the precompiled version of $(I)hack.h, +#X# while $(CSYM) should appear in the C compiler command line that creates +#X# any such object file. (Changes made here should agree with the $(HDEP): +#X# target that appears later in this makefile.) +#X# + +#SFD_BEGIN +## +###[DICE] +### If we were compiling with DICE and wanted to use the symbol table +### pre-loading feature, we would uncomment these following two lines. +## +##HDEP = $(I)hack.sym +##CSYM = -H$(I)hack.sym=hack.h +## +#SFD_ELSE + +#[SAS5] +# If we were to use the precompiled header file feature in a newer version +# of SAS/C, we would comment out these following two lines. +# If we don't use precompiled header files, we uncomment it as well. + +HDEP = $(I)hack.h $(I)pm.h $(I)onames.h +CSYM = + +#[MANX] +# If we were compiling with Aztec, and wanted to use the symbol table +# pre-loading feature, we would uncomment these following two lines. + +#HDEP = Ram:hack.sym +#CSYM = +IRam:hack.sym + +#SFD_END + +#Pathname for uudecode program: +UUDEC = uudecode + +# Flex/Bison command assignments -- Useful only if you have flex/bison +FLEX = flex +BISON = bison +# FBFIL and FBLIB may be used, if required by your version of flex or bison, +# to specify additional files or libraries to be linked with +FBFIL = +FBLIB = #lib lib:compat.lib + +# If you're compiling this on a 1.3 system, you'll have to uncomment the +# following (for use with the ifchange script below). Also useful instead of +# "protect ifchange +s" +EXECUTE = execute + +# Headers we depend on +AMDEP = $(AMI)winproto.h $(AMI)winext.h $(AMI)windefs.h $(I)winami.h + +# Pathname for the C compiler being used. + +#SFD_BEGIN +## +###[DICE] +##CC = dcc +##ASM = das +## +#SFD_ELSE + +#[SAS6] +CC = sc +ASM = asm + +#[MANX] +#CC = cc + +#SFD_END + +# Compilation flags for selected C Compiler: +# $(CFLAGS) should appear before filename arguments of $(CC) command line. + +#SFD_BEGIN +## +###[DICE] +##CFLAGS = -c -I$(I) -mC -mD -ms -// +##CFLAGS2 = +##WBCFLAGS = -c -I$(I) -mC -mD -ms -// +##WBC2FLAGS = -DCLI +##SPLFLAGS = -DSPLIT +## +#SFD_ELSE + +#[SAS6] +# Note: make sure your CLI stack size is large (at least 50K) or lev_comp +# and makedefs may fail terribly - stack checking is disabled. +# +# **** WARNING **** GST support is not fool proof. You must make makedefs +# without a GST first so that the generated headers +# that are part of the GST can be made. +# +#GSTSRC=$(AMI)gst.c +# +#GSTHEAD=$(I)hack.h $(I)pm.h $(I)trap.h $(I)onames.h \ +# $(AMI)winami.p $(AMI)amidos.p $(AMI)amiwind.p +# +#GSTFILE=$(O)NetHack.gst +# undefine this to not compile with GSTs +#GST=gst=$(GSTFILE) +# +DEBUG=debug=symbol +CPU=cpu=68000 +#OPTFLAGS=opt opttime optpeep optgo optinl optsched optcomp=10 optdep=5 optrdep=5 #optalias +OPTTIME -OPTSIZE +CFLAGS = data=far nominc $(DEBUG) idir=$(I) $(CPU) nostkchk nover \ + codename=nhcode dataname=nhdata strmerge $(OPTFLAGS) $(TILES) $(SAVEDS) \ + afp $(ERRREXX) $(GST) +# for files that are too large for the standard flags: +CFLAGS2 = code=far strmerge $(SAVEDS) +WBCFLAGS = ignore=217,62 data=far ansi nminc code=far idir=$(I) $(CPU) afp \ + $(DEBUG) $(ERRREXX) define=AMIGA $(GST) +XXX = data=far ansi nminc idir=$(I) $(CPU) afp opt optinline optinlocal \ + optloop opttime +WBC2FLAGS = define=CLI +SPLFLAGS = define=SPLIT #dollarok +#for amistack.c +CFLAGS3 = data=near dataname=__MERGED nominc $(DEBUG) idir=$(I) $(CPU) nover nostkchk \ + codename=nhcode strmerge $(OPTFLAGS) $(TILES) $(SAVEDS) \ + afp $(ERRREXX) $(GST) + +#[MANX] +#CFLAGS = -i$(I) -mc -md -ms -pa -ps -bs -wo -qq +#WBCFLAGS = -mc -md -ms -pa -ps -bs -wo -qq -pp + +#SFD_END + +# Assembly flags: + +#SFD_BEGIN +## +###[DICE] +##AFLAGS = +##AOBJSPEC = -o +## +#SFD_ELSE + +#[SAS6] +AFLAGS = #what to put here? +AOBJSPEC = -o + +#SFD_END + +# Components of various link command lines: +# $(LINK) should be the pathname of the linker being used (with any options +# that should appear at the beginning of the command line). The name of the +# output file should appear immediately after $(LNSPEC). $(LIN) should +# appear before the list of object files in each link command. $(LLINK) +# should appear as the list of object files in the link command line that +# creates the NetHack executable. $(LLIB) should appear at the end of each +# link command line. + +# Note: amiga.lib added due to missing prototypes/pragmas. +# Should be deleted when this is resolved. + +#SFD_BEGIN +## +###[DICE] +### If you have flex/bison libraries, use the second definition of FLLIB +### instead of the first. +## +##LINK = dcc -mD +##LIN = +##LLINK = @$(AMI)ami.lnk +##LLIB = +##FLLIB = +###FLLIB = -l$(FBLIB) +##OBJSPEC = -o +##PNSPEC = -o +##LNSPEC = -o +##CCLINK = dcc +##CLFLAGS = -I$(I) -mC -mD -ms -// +##INCLSPEC = -I +##DEFSPEC = -D +##IGNSPEC = -j +## +#SFD_ELSE + +#[SAS6] + +LINK = slink noicons verbose maxhunk 262144 stripdebug +LIN = from lib:catch.o +LLINK = with $(AMI)ami.lnk +LLIB = lib lib:scnb.lib BATCH #lib lib:amiga.lib BATCH #scnb.lib or sc.lib +FLLIB = $(FBLIB) lib Lib:sc.lib BATCH +OBJSPEC = objname= +PNSPEC = noicons to #pname= +LNSPEC = to +CCLINK = sc link +INCLSPEC = idir= +DEFSPEC = define= +IGNSPEC = ignore= +COMPACT_HEADERS=$(GSTFILE) + +#[MANX] + +#LINK = ln -g +q +ss -o +#LIN = +#LLINK = -f $(AMI)ami.lnk +#LLIB = -lcl16 +#FLLIB = -lcl16 +#OBJSPEC = -o +#PNSPEC = -o +#LNSPEC = -o +#CCLINK = cc +#INCLSPEC = -i +#DEFSPEC = -d +#IGNSPEC = -j + +#SFD_END + +### +### FILE LISTS +### + +# A more reasonable random number generator (recommended for the Amiga): + +RANDOBJ = $(O)random.o + +#SFD_INSTEAD #none +.PRECIOUS: $(I)config.h $(I)decl.h $(I)hack.h $(I)permonst.h $(I)you.h + +# Almost nothing below this line should have to be changed. +# (Exceptions are marked by [SAS6], [MANX], etc.) +# +# Other things that have to be reconfigured are in config.h, +# (amiconf.h, pcconf.h), and possibly system.h, tradstdc.h. + +# Object files for makedefs: + +MAKEOBJS = \ + $(OO)makedefs.o $(O)monst.o $(O)objects.o + +# Object files for special levels compiler: + +SPLEVOBJS = \ + $(OO)lev_yacc.o $(OO)lev_lex.o $(OO)lev_main.o \ + $(O)decl.o $(O)drawing.o $(O)monst.o \ + $(O)objects.o $(OO)panic.o + +# Object files for dungeon compiler + +DGNCOMPOBJS = \ + $(OO)dgn_yacc.o $(OO)dgn_lex.o $(OO)dgn_main.o $(O)alloc.o $(OO)panic.o + +# Object files for NetHack: + +COMMOBJ = \ + $(O)allmain.o $(O)alloc.o $(O)apply.o $(O)artifact.o \ + $(O)attrib.o $(O)ball.o $(O)bones.o $(O)botl.o \ + $(O)cmd.o $(O)dbridge.o $(O)decl.o $(O)detect.o \ + $(O)dig.o $(O)display.o $(O)dlb.o $(O)do.o \ + $(O)do_name.o $(O)do_wear.o $(O)dog.o $(O)dogmove.o \ + $(O)dokick.o $(O)dothrow.o $(O)drawing.o $(O)dungeon.o \ + $(O)eat.o $(O)end.o $(O)engrave.o $(O)exper.o \ + $(O)explode.o $(O)extralev.o $(O)files.o $(O)fountain.o \ + $(O)hack.o $(O)hacklib.o $(O)invent.o $(O)light.o \ + $(O)lock.o $(O)mail.o $(O)makemon.o $(O)mapglyph.o \ + $(O)mcastu.o $(O)mhitm.o $(O)mhitu.o $(O)minion.o \ + $(O)mklev.o $(O)mkmap.o $(O)mkmaze.o $(O)mkobj.o \ + $(O)mkroom.o $(O)mon.o $(O)mondata.o $(O)monmove.o \ + $(O)monst.o $(O)mplayer.o $(O)mthrowu.o $(O)muse.o \ + $(O)music.o $(O)o_init.o $(O)objects.o $(O)objnam.o \ + $(O)options.o $(O)pager.o $(O)pickup.o $(O)pline.o \ + $(O)polyself.o $(O)potion.o $(O)pray.o $(O)priest.o \ + $(O)quest.o $(O)questpgr.o $(O)read.o $(O)rect.o \ + $(O)region.o $(O)restore.o $(O)rnd.o $(O)role.o \ + $(O)rumors.o $(O)save.o $(O)shk.o $(O)shknam.o \ + $(O)sit.o $(O)sounds.o $(O)sp_lev.o $(O)spell.o \ + $(O)steal.o $(O)steed.o $(O)teleport.o $(O)timeout.o \ + $(O)topten.o $(O)track.o $(O)trap.o $(O)u_init.o \ + $(O)uhitm.o $(O)vault.o $(O)version.o $(O)vision.o \ + $(O)weapon.o $(O)were.o $(O)wield.o $(O)windows.o \ + $(O)wizard.o $(O)worm.o $(O)worn.o $(O)write.o \ + $(O)zap.o + +MAKEDEFOBJ = \ + $(O)monstr.o + +AMIGAOBJ = \ + $(O)amidos.o $(O)amirip.o $(O)amisnd.o $(O)amistack.o \ + $(O)amiwind.o $(O)winami.o $(O)winchar.o $(O)winfuncs.o \ + $(O)winkey.o $(O)winmenu.o $(O)winreq.o $(O)winstr.o + +# Objects from assembly sources (because DMake can't handle default rules) +AMIGAOBJ2 = \ +# $(O)dispmap.o + +SHAREOBJ = \ + $(O)pcmain.o $(RANDOBJ) + +TTYOBJ = \ + $(O)getline.o $(O)termcap.o $(O)topl.o $(O)wintty.o $(O)amitty.o \ + $(O)rip.o + +# Yuck yuck yuck. Have to tell DMake where these are, since they're not +# all in the same place. +TTYSRC = \ + $(TTY)getline.c $(TTY)termcap.c $(TTY)topl.c $(TTY)wintty.c \ + $(AMI)amitty.c $(NHS)rip.c + +# All the object files for NetHack: + +HOBJ = $(COMMOBJ) $(AMIGAOBJ) $(AMIGAOBJ2) $(SHAREOBJ) $(MAKEDEFOBJ) $(TTYOBJ) + +### +### DATA FILES +### + +# quest files +ADFILES1= $(SLIB)Arc-fila.lev $(SLIB)Arc-filb.lev $(SLIB)Arc-loca.lev \ + $(SLIB)Arc-strt.lev +ADFILES= $(SLIB)Arc-goal.lev $(ADFILES1) + +BDFILES1= $(SLIB)Bar-fila.lev $(SLIB)Bar-filb.lev $(SLIB)Bar-loca.lev \ + $(SLIB)Bar-strt.lev +BDFILES= $(SLIB)Bar-goal.lev $(BDFILES1) + +CDFILES1= $(SLIB)Cav-fila.lev $(SLIB)Cav-filb.lev $(SLIB)Cav-loca.lev \ + $(SLIB)Cav-strt.lev +CDFILES= $(SLIB)Cav-goal.lev $(CDFILES1) + +HDFILES1= $(SLIB)Hea-fila.lev $(SLIB)Hea-filb.lev $(SLIB)Hea-loca.lev \ + $(SLIB)Hea-strt.lev +HDFILES= $(SLIB)Hea-goal.lev $(HDFILES1) + +KDFILES1= $(SLIB)Kni-fila.lev $(SLIB)Kni-filb.lev $(SLIB)Kni-loca.lev \ + $(SLIB)Kni-strt.lev +KDFILES= $(SLIB)Kni-goal.lev $(KDFILES1) + +MDFILES1= $(SLIB)Mon-fila.lev $(SLIB)Mon-filb.lev $(SLIB)Mon-loca.lev \ + $(SLIB)Mon-strt.lev +MDFILES= $(SLIB)Mon-goal.lev $(MDFILES1) + +PDFILES1= $(SLIB)Pri-fila.lev $(SLIB)Pri-filb.lev $(SLIB)Pri-loca.lev \ + $(SLIB)Pri-strt.lev +PDFILES= $(SLIB)Pri-goal.lev $(PDFILES1) + +RDFILES1= $(SLIB)Rog-fila.lev $(SLIB)Rog-filb.lev $(SLIB)Rog-loca.lev \ + $(SLIB)Rog-strt.lev +RDFILES= $(SLIB)Rog-goal.lev $(RDFILES1) + +RANFILES1= $(SLIB)Ran-fila.lev $(SLIB)Ran-filb.lev $(SLIB)Ran-loca.lev \ + $(SLIB)Ran-strt.lev +RANFILES= $(SLIB)Ran-goal.lev $(RANFILES1) + +SDFILES1= $(SLIB)Sam-fila.lev $(SLIB)Sam-filb.lev $(SLIB)Sam-loca.lev \ + $(SLIB)Sam-strt.lev +SDFILES= $(SLIB)Sam-goal.lev $(SDFILES1) + +TDFILES1= $(SLIB)Tou-fila.lev $(SLIB)Tou-filb.lev $(SLIB)Tou-loca.lev \ + $(SLIB)Tou-strt.lev +TDFILES= $(SLIB)Tou-goal.lev $(TDFILES1) + +VDFILES1= $(SLIB)Val-fila.lev $(SLIB)Val-filb.lev $(SLIB)Val-loca.lev \ + $(SLIB)Val-strt.lev +VDFILES= $(SLIB)Val-goal.lev $(VDFILES1) + +WDFILES1= $(SLIB)Wiz-fila.lev $(SLIB)Wiz-filb.lev $(SLIB)Wiz-loca.lev \ + $(SLIB)Wiz-strt.lev +WDFILES= $(SLIB)Wiz-goal.lev $(WDFILES1) + +XDFILES= $(ADFILES) $(BDFILES) $(CDFILES) $(HDFILES) $(KDFILES) \ + $(MDFILES) $(PDFILES) $(RDFILES) $(RANFILES) $(SDFILES) $(TDFILES) \ + $(VDFILES) $(WDFILES) + +SOUNDFILES= \ + $(SBIN)cvtsnd \ + $(SLIB)sounds \ + $(SLIB)sounds/Bell $(SLIB)sounds/Bugle \ + $(SLIB)sounds/Drum_Of_Earthquake \ + $(SLIB)sounds/Fire_Horn $(SLIB)sounds/Frost_Horn \ + $(SLIB)sounds/Leather_Drum $(SLIB)sounds/Magic_Flute \ + $(SLIB)sounds/Magic_Harp $(SLIB)sounds/Tooled_Horn \ + $(SLIB)sounds/Wooden_Flute $(SLIB)sounds/Wooden_Harp + +TILEFILES= \ + $(SBIN)txt2iff \ + $(NETHACK)tiles \ + $(NETHACK)tiles/objects.iff \ + $(NETHACK)tiles/monsters.iff \ + $(NETHACK)tiles/other.iff + +INSTDUNGEONFILES1= \ + $(SLIB)air.lev $(SLIB)asmodeus.lev $(SLIB)astral.lev \ + $(SLIB)baalz.lev $(SLIB)bigrm-1.lev $(SLIB)bigrm-2.lev \ + $(SLIB)bigrm-3.lev $(SLIB)bigrm-4.lev $(SLIB)bigrm-5.lev \ + $(SLIB)castle.lev $(SLIB)dungeon $(SLIB)earth.lev \ + $(SLIB)fakewiz1.lev $(SLIB)fakewiz2.lev $(SLIB)fire.lev \ + $(SLIB)juiblex.lev $(SLIB)knox.lev $(SLIB)medusa-1.lev \ + $(SLIB)medusa-2.lev $(SLIB)minend-1.lev $(SLIB)minend-2.lev \ + $(SLIB)minetn-1.lev $(SLIB)minetn-2.lev $(SLIB)minefill.lev \ + $(SLIB)options $(SLIB)oracle.lev $(SLIB)orcus.lev \ + $(SLIB)sanctum.lev $(SLIB)soko1-1.lev $(SLIB)soko1-2.lev \ + $(SLIB)soko2-1.lev $(SLIB)soko2-2.lev $(SLIB)soko3-1.lev \ + $(SLIB)soko3-2.lev $(SLIB)soko4-1.lev $(SLIB)soko4-2.lev \ + $(SLIB)tower1.lev $(SLIB)tower2.lev $(SLIB)tower3.lev \ + $(SLIB)valley.lev $(SLIB)water.lev $(SLIB)wizard1.lev \ + $(SLIB)wizard2.lev $(SLIB)wizard3.lev \ + $(XDFILES) + +INSTDUNGEONFILES= $(NETHACK)NetHack.cnf $(INSTDUNGEONFILES1) + + +INSTDATAFILES= \ + $(NETHACK)license $(NETHACK)logfile $(NETHACK)record \ + $(NETHACK)tomb.iff $(NETHACK)amii.hlp $(NETHACK)Recover.txt \ + $(NETHACK)GuideBook.txt $(NETHACK)NetHack.txt $(NETHACK)Install.ami + +LIBFILES= \ + $(INSTDUNGEONFILES1) \ + $(SLIB)cmdhelp $(SLIB)data $(SLIB)dungeon \ + $(SLIB)help $(SLIB)hh $(SLIB)history \ + $(SLIB)opthelp $(SLIB)oracles $(SLIB)rumors \ + $(SLIB)quest.dat $(SLIB)wizhelp + +### +### Getting down to business: +### + +#SFD_INSTEAD all: $(SBIN)lev_comp $(SBIN)dgn_comp $(SBIN)NetHack \ +all: $(COMPACT_HEADERS) $(SBIN)lev_comp $(SBIN)dgn_comp $(SBIN)NetHack \ + $(SBIN)dlb $(NETHACK)recover + +install: all inst-data inst-dungeon inst-fonts inst-sounds inst-tiles \ + $(NETHACK)nhdat $(NETHACK)NetHack + +$(SBIN)NetHack: $(HOBJ) $(AMI)ami.lnk + $(LINK) $(LNSPEC) $(SBIN)NetHack $(LIN) $(LLINK) $(LLIB) + +$(NETHACK)NetHack: $(SBIN)NetHack + copy $(SBIN)NetHack $(NETHACK)NetHack + +link: + $(LINK) $(LNSPEC) $(SBIN)NetHack $(LIN) $(LLINK) $(LLIB) + +$(AMI)ami.lnk: $(AMI)Makefile.ami + list to $(AMI)ami.lnk lformat="$(O)%s" $(O)\#?.o QUICK NOHEAD + +## dlb support +$(OO)dlb_main.o: $(UTIL)dlb_main.c $(HDEP) $(I)dlb.h $(I)date.h + $(CC) $(CFLAGS) $(OBJSPEC)$(OO)dlb_main.o $(UTIL)dlb_main.c + +$(SBIN)dlb: $(OO)dlb_main.o $(O)dlb.o $(O)alloc.o $(OO)panic.o + $(LINK) $(PNSPEC) $(SBIN)dlb $(LIN) $(OO)dlb_main.o $(O)dlb.o \ + $(O)alloc.o $(OO)panic.o $(LLIB) + +obj: $(HOBJ) + +obja: $(AMIGAOBJ) + +objs: $(SHAREOBJ) + + +#SFD_BEGIN +#SFD_ELSE +SUFFIXES = .lev .des +.des.lev: + $(SBIN)lev_comp $< +#SFD_END + + +# The default method for creating object files: + +#SFD_BEGIN +## +###[DICE] +## +##$(COMMOBJ): $(COMMOBJ:"$(O)*.o":"$(NHS)%1.c") +## $(CC) $(CFLAGS) $(CSYM) $(OBJSPEC)%(left) %(right) +## +##$(AMIGAOBJ): $(AMIGAOBJ:"$(O)*.o":"$(AMI)%1.c") +## $(CC) $(CFLAGS) $(CSYM) $(OBJSPEC)%(left) %(right) +## +##$(SHAREOBJ): $(SHAREOBJ:"$(O)*.o":"$(SHARE)%1.c") +## $(CC) $(CFLAGS) $(CSYM) $(OBJSPEC)%(left) %(right) +## +##$(TTYOBJ): $(TTYSRC) +## $(CC) $(CFLAGS) $(CSYM) $(OBJSPEC)%(left) %(right) +## +#SFD_ELSE + +#[SAS6] + +.c.o: + $(CC) $(CFLAGS) $(CSYM) $(OBJSPEC)$@ $< + +#SFD_END + + +clean: + -delete $(O)\#?.o $(OO)\#?.o + +spotless: clean + -delete $(SBIN)NetHack $(SBIN)lev_comp $(SBIN)makedefs $(SBIN)dgn_comp + -delete $(SBIN)cvtsnd $(SBIN)dlb $(SBIN)txt2iff $(SBIN)splitter + -delete $(SBIN)tilemap + -delete $(SLIB)data $(SLIB)rumors + -delete $(SLIB)\#?.lev + -delete $(SLIB)dungeon + -delete $(SLIB)cmdhelp $(SLIB)help $(SLIB)hh $(SLIB)history + -delete $(SLIB)opthelp $(SLIB)options $(SLIB)oracles + -delete $(SLIB)quest.dat $(SLIB)wizhelp +# -delete $(SLIB)earth.lev $(SLIB)air.lev $(SLIB)fire.lev +# -delete $(SLIB)water.lev $(SLIB)astral.lev +# -delete $(SLIB)tower1.lev $(SLIB)tower2.lev $(SLIB)tower3.lev +# -delete $(SLIB)fakewiz1.lev $(SLIB)fakewiz2.lev +# -delete $(SLIB)medusa-1.lev $(SLIB)medusa-2.lev +# -delete $(SLIB)oracle.lev $(SLIB)wizard1.lev $(SLIB)wizard2.lev +# -delete $(SLIB)wizard3.lev $(DAT)dungeon.pdf $(SLIB)valley.lev +# -delete $(SLIB)minefill.lev +# -delete $(SLIB)minetn-1 $(SLIB)minetn-2 $(SLIB)minend-1 $(SLIB)minend-2 +# -delete $(SLIB)soko1-1.lev $(SLIB)soko1-2.lev $(SLIB)soko2-1.lev +# -delete $(SLIB)soko2-2.lev $(SLIB)soko3-1.lev $(SLIB)soko3-2.lev +# -delete $(SLIB)soko4-1.lev $(SLIB)soko4-2.lev +# -delete $(ADFILES) +# -delete $(BDFILES) +# -delete $(CDFILES) +# -delete $(HDFILES) +# -delete $(KDFILES) +# -delete $(MDFILES) +# -delete $(PDFILES) +# -delete $(RDFILES) +# -delete $(RANFILES) +# -delete $(SDFILES) +# -delete $(TDFILES) +# -delete $(VDFILES) +# -delete $(WDFILES) + -delete $(I)onames.h $(I)pm.h $(I)date.h + -delete $(NHS)tile.c $(NHS)monstr.c + -delete $(I)tile.h +# -echo to $(I)onames.h "" noline +# -wait 2 +# -echo to $(I)pm.h "" noline +# -wait 2 +# -setdate $(UTIL)makedefs.c +# -wait 2 + +# Creating precompiled version of $(I)hack.h to save disk I/O. + +#SFD_BEGIN +## +###[DICE] +### If we were compiling with DICE and wanted to use the symbol table +### pre-loading feature, we would technically not need a rule to make the +### precompiled header file, because DCC handles this automatically; +### however, we must delete the precompiled header file if any of the +### includes change, and we need to create it manually because the +### sys/amiga sources, compiled first, define things differently than the +### main sources want them. +## +##$(HDEP): $(I)hack.h $(I)pm.h $(I)onames.h +## -delete $(I)hack.sym +## echo to Ram:hackincl.c "#include " +## $(CC) $(CFLAGS) $(CSYM) $(OBJSPEC)Ram:hackincl.o Ram:hackincl.c +## -delete Ram:hackincl.c Ram:hackincl.o +## +#SFD_ELSE + +#X#[SAS5] +#X# If we were to use the precompiled header file feature of SAS/C, we +#X# would uncomment the following lines. (Also see defines for HDEP and +#X# CSYM near the beginning of this file, as these should be appropriately +#X# defined.) + +#X#$(HDEP): $(I)hack.h $(SBIN)makedefs +#X# echo to Ram:hackincl.c "#include <$(I)hack.h>" +#X# $(CC) $(CFLAGS) -ph $(OBJSPEC)$@ Ram:hackincl.c +#X# -delete Ram:hackincl.c + +#[MANX] +# If we were compiling with Aztec, and wanted to use the symbol table +# pre-loading feature, we would uncomment these following two lines. + +#$(HDEP): $(I)hack.h $(SBIN)makedefs +# $(CC) $(CFLAGS) -a $(OBJSPEC)Ram:hack.asm +h$@ $(I)hack.h +# -delete Ram:hack.asm + +#SFD_END + +# +# Please note: The dependency lines for the modules here are +# deliberately incorrect. Including "hack.h" in +# the dependency list would cause a dependency +# loop. +# + +$(SBIN)makedefs: $(MAKEOBJS) + $(LINK) $(LNSPEC) $(SBIN)makedefs $(LIN) $(MAKEOBJS) $(LLIB) + +$(OO)makedefs.o: $(UTIL)makedefs.c $(I)config.h $(I)permonst.h $(I)monsym.h \ + $(I)objclass.h $(I)patchlevel.h $(I)qtext.h $(I)artilist.h + $(CC) $(DEFSPEC)MAKEDEFS_C $(CFLAGS) $(OBJSPEC)$@ $(UTIL)makedefs.c + +$(SBIN)lev_comp: $(SPLEVOBJS) + $(LINK) $(LNSPEC) $(SBIN)lev_comp $(LIN) $(SPLEVOBJS) $(FBFIL) $(FLLIB) + +$(SBIN)dgn_comp: $(DGNCOMPOBJS) + $(LINK) $(LNSPEC) $(SBIN)dgn_comp $(LIN) $(DGNCOMPOBJS) $(FBFIL) $(FLLIB) + +$(OO)lev_yacc.o: $(UTIL)lev_yacc.c $(HDEP) $(I)sp_lev.h $(I)pm.h $(I)onames.h +# setdate $(UTIL)lev_yacc.c + $(CC) $(DEFSPEC)LEV_LEX_C $(DEFSPEC)PREFIX="NH:slib/" $(CFLAGS) \ + $(DEFSPEC)alloca=malloc $(OBJSPEC)$@ $(UTIL)lev_yacc.c + +$(OO)lev_lex.o: $(UTIL)lev_lex.c $(HDEP) $(I)lev_comp.h $(I)sp_lev.h + $(CC) $(DEFSPEC)LEV_LEX_C $(CFLAGS) $(OBJSPEC)$@ $(UTIL)lev_lex.c + +$(OO)lev_main.o: $(UTIL)lev_main.c $(HDEP) $(I)pm.h $(I)onames.h $(I)date.h + $(CC) $(DEFSPEC)LEV_LEX_C $(DEFSPEC)AMIGA $(CFLAGS) $(OBJSPEC)$@ \ + $(UTIL)lev_main.c + +$(OO)dgn_yacc.o: $(UTIL)dgn_yacc.c $(HDEP) $(I)dgn_file.h $(I)patchlevel.h + $(CC) $(DEFSPEC)LEV_LEX_C $(CFLAGS) $(DEFSPEC)alloca=malloc \ + $(OBJSPEC)$@ $(UTIL)dgn_yacc.c + +$(OO)dgn_lex.o: $(UTIL)dgn_lex.c $(I)config.h $(I)dgn_comp.h $(I)dgn_file.h + $(CC) $(DEFSPEC)LEV_LEX_C $(CFLAGS) $(OBJSPEC)$@ $(UTIL)dgn_lex.c + +$(OO)dgn_main.o: $(UTIL)dgn_main.c $(I)config.h $(I)date.h + $(CC) $(DEFSPEC)LEV_LEX_C $(DEFSPEC)AMIGA $(CFLAGS) $(OBJSPEC)$@ \ + $(UTIL)dgn_main.c + +$(OO)panic.o: $(UTIL)panic.c $(HDEP) +#SFD_INSTEAD $(CC) $(CFLAGS) $(OBJSPEC)%(left) $(UTIL)panic.c +#none + +$(OO)recover.o: $(UTIL)recover.c $(I)config.h $(I)date.h + $(CC) $(DEFSPEC)LEV_LEX_C $(DEFSPEC)AMIGA $(CFLAGS) $(OBJSPEC)$@ \ + $(UTIL)recover.c + +$(NETHACK)recover: $(OO)recover.o + $(LINK) $(LNSPEC) $(NETHACK)recover $(LIN) $(OO)recover.o $(LLIB) + +# [OPTION] -- If you have flex/bison, leave these uncommented. Otherwise, +# comment them out and be careful! (You're not guaranteed to have the most +# up to date *_comp.c, *_comp.h and *_lex.c) + +$(I)lev_comp.h: $(UTIL)lev_yacc.c $(I)patchlevel.h + +$(UTIL)lev_yacc.c: $(UTIL)lev_comp.y $(I)patchlevel.h + $(BISON) -d $(UTIL)lev_comp.y +# copy y.tab.c $(UTIL)lev_yacc.c +# copy y.tab.h $(I)lev_comp.h + copy $(UTIL)lev_comp.tab.c $(UTIL)lev_yacc.c + copy $(UTIL)lev_comp.tab.h $(I)lev_comp.h +# delete y.tab.c +# delete y.tab.h + delete $(UTIL)lev_comp.tab.c + delete $(UTIL)lev_comp.tab.h + +$(UTIL)lev_lex.c: $(UTIL)lev_comp.l $(I)patchlevel.h + $(FLEX) $(UTIL)lev_comp.l + copy lex.yy.c $(UTIL)lev_lex.c + delete lex.yy.c + +$(I)dgn_comp.h: $(UTIL)dgn_yacc.c $(I)patchlevel.h + +$(UTIL)dgn_yacc.c: $(UTIL)dgn_comp.y $(I)patchlevel.h + $(BISON) -d $(UTIL)dgn_comp.y +# copy y.tab.c $(UTIL)dgn_yacc.c +# copy y.tab.h $(I)dgn_comp.h + copy $(UTIL)dgn_comp.tab.c $(UTIL)dgn_yacc.c + copy $(UTIL)dgn_comp.tab.h $(I)dgn_comp.h +# delete y.tab.c +# delete y.tab.h + delete $(UTIL)dgn_comp.tab.c + delete $(UTIL)dgn_comp.tab.h + +$(UTIL)dgn_lex.c: $(UTIL)dgn_comp.l $(I)patchlevel.h + $(FLEX) $(UTIL)dgn_comp.l + copy lex.yy.c $(UTIL)dgn_lex.c + delete lex.yy.c + +# +# The following include files depend on makedefs to be created. +# As a result, they are not defined in HACKINCL, instead, their +# dependencies are explicitly outlined here. +# + +# +# date.h should be remade any time any of the source or include code +# is modified. Unfortunately, this would make the contents of this +# file far more complex. Since "hack.h" depends on most of the include +# files, we kludge around this by making date.h dependent on hack.h, +# even though it doesn't include this file. +# + +#SFD_INSTEAD $(I)date.h $(DAT)options:: $(HDEP) $(SBIN)makedefs $(AMIGAOBJ) +$(I)date.h $(DAT)options: $(HDEP) $(SBIN)makedefs $(AMIGAOBJ) $(I)patchlevel.h + $(SBIN)makedefs -v + $(EXECUTE) $(AMI)ifchange MOVE $(I)t.date.h $(I)date.h + -wait 2 + +$(I)onames.h: $(SBIN)makedefs + $(SBIN)makedefs -o + $(EXECUTE) $(AMI)ifchange TOUCH $(I)t.onames.h $(I)onames.h $(I)decl.h + $(EXECUTE) $(AMI)ifchange MOVE $(I)t.onames.h $(I)onames.h + -wait 2 + +$(I)pm.h: $(SBIN)makedefs + $(SBIN)makedefs -p + $(EXECUTE) $(AMI)ifchange TOUCH $(I)t.pm.h $(I)pm.h $(I)decl.h $(I)youprop.h + $(EXECUTE) $(AMI)ifchange MOVE $(I)t.pm.h $(I)pm.h + -wait 2 + +$(SLIB)quest.dat: $(DAT)quest.txt $(SBIN)makedefs + $(SBIN)makedefs -q + +$(NHS)monstr.c: $(HDEP) $(SBIN)makedefs + $(SBIN)makedefs -m + -wait 2 + +$(SLIB)oracles: $(DAT)oracles.txt $(SBIN)makedefs + $(SBIN)makedefs -h + -wait 2 + +# +# The following programs vary depending on what OS you are using. +# As a result, they are not defined in HACKSRC and their dependencies +# are explicitly outlined here. +# + +$(O)amidos.o: $(AMI)amidos.c $(HDEP) + +$(O)amirip.o: $(AMI)amirip.c $(HDEP) + +$(O)aglue.o: $(AMI)aglue.a + $(ASM) $(AFLAGS) $(AOBJSPEC)$(O)aglue.o $(AMI)aglue.a + +$(O)amisnd.o: $(AMI)amisnd.c $(HDEP) + +$(O)winchar.o: $(AMI)winchar.c $(NHS)tile.c $(HDEP) + +$(NHS)tile.c: $(WSHARE)tilemap.c +#SFD_INSTEAD $(CCLINK) $(CLFLAGS) $(PNSPEC) $(SBIN)tilemap $(WSHARE)tilemap.c + $(CCLINK) $(CFLAGS) $(PNSPEC) $(SBIN)tilemap $(WSHARE)tilemap.c + $(SBIN)tilemap + +$(O)winstr.o: $(AMI)winstr.c $(HDEP) $(AMDEP) + +$(O)winreq.o: $(AMI)winreq.c $(HDEP) $(AMDEP) $(AMI)colorwin.c $(AMI)clipwin.c + +$(O)winfuncs.o: $(AMI)winfuncs.c $(HDEP) $(AMDEP) $(I)patchlevel.h + +$(O)winkey.o: $(AMI)winkey.c $(HDEP) $(AMDEP) + +$(O)winmenu.o: $(AMI)winmenu.c $(HDEP) $(AMDEP) + +$(O)winami.o: $(AMI)winami.c $(HDEP) $(AMDEP) #$(AMI)char.c $(AMI)randwin.c + +#$(O)amilib.o: $(AMI)amilib.c $(HDEP) $(AMDEP) + +$(O)amiwind.o: $(AMI)amiwind.c $(AMI)amimenu.c $(HDEP) $(AMDEP) + +$(O)amiwbench.o: $(AMI)amiwbench.c $(HDEP) + +$(O)random.o: $(SHARE)random.c + +$(O)pcmain.o: $(SHARE)pcmain.c $(HDEP) $(I)dlb.h + +$(O)dispmap.o: $(AMI)dispmap.s + $(ASM) $(AFLAGS) $(AOBJSPEC)$@ $< + +# Stuff to build the front ends +$(NETHACK)HackWB: $(OO)wb.o $(OO)wbx.o $(OO)loader.o $(OO)multi.o + $(LINK) $(LNSPEC) $(NETHACK)HackWB $(LIN) $(OO)wb.o $(OO)wbx.o \ + $(OO)loader.o $(OO)multi.o $(LLIB) + +$(NETHACK)HackCli: $(OO)cli.o $(OO)loader.o $(OO)multi.o + $(LINK) $(LNSPEC) $(NETHACK)HackCli $(LIN) $(OO)cli.o $(OO)loader.o \ + $(OO)multi.o $(LLIB) + +# This needs to exist to eliminate the HackWB startup message +#SFD_INSTEAD $(NETHACK)WBDefaults.def: $(NETHACK)WBDefaults.def +$(NETHACK)WBDefaults.def: + echo to $(NETHACK)WBDefaults.def + +WBH = $(AMI)wbdefs.h $(AMI)wbstruct.h $(AMI)wbprotos.h +ASP = $(AMI)splitter +$(OO)wb.o: $(WBH) $(AMI)wb.c $(AMI)wbwin.c $(AMI)wbdata.c $(AMI)wbgads.c \ + $(I)patchlevel.h + $(CC) $(WBCFLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)wb.o $(AMI)wb.c + +$(OO)wbx.o: $(WBH) $(AMI)wbcli.c $(AMI)wbwin.c $(AMI)wbdata.c \ + $(I)patchlevel.h $(I)date.h + $(CC) $(WBCFLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)wbx.o $(AMI)wbcli.c + +$(OO)loader.o: $(ASP)/loader.c $(ASP)/split.h $(ASP)/amiout.h $(ASP)/multi.h + $(CC) $(WBCFLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)loader.o $(ASP)/loader.c + +$(OO)multi.o: $(ASP)/multi.c $(ASP)/multi.h + $(CC) $(WBCFLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)multi.o $(ASP)/multi.c + +$(OO)cli.o: $(WBH) $(AMI)wbcli.c $(I)patchlevel.h $(I)date.h + $(CC) $(WBCFLAGS) $(WBC2FLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)cli.o \ + $(AMI)wbcli.c + +#### +# splitter support +$(SBIN)splitter: $(OO)splitter.o $(OO)arg.o + $(LINK) $(LNSPEC) $(SBIN)splitter $(LIN) $(OO)splitter.o $(OO)arg.o \ + $(LLIB) + +$(NETHACK)NetHack.dir: $(SBIN)splitter $(SBIN)NetHack + $(SBIN)splitter $(SBIN)NetHack + +$(OO)splitter.o: $(ASP)/splitter.c $(ASP)/split.h $(ASP)/amiout.h $(ASP)/arg.h + $(CC) $(WBCFLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)splitter.o \ + $(ASP)/splitter.c + +$(OO)arg.o: $(ASP)/arg.c $(ASP)/arg.h + $(CC) $(WBCFLAGS) $(SPLFLAGS) $(OBJSPEC)$(OO)arg.o $(ASP)/arg.c + +# Create/copy other stuff into NetHack: directory: + +$(NETHACK)tomb.iff: $(SBIN)xpm2iff $(AMI)grave16.xpm + $(SBIN)xpm2iff $(AMI)grave16.xpm $(NETHACK)tomb.iff + +$(OO)xpm2iff.o: $(AMI)xpm2iff.c + $(CC) $(CFLAGS) $(INCLSPEC)$(WSHARE) $(OBJSPEC)$@ $(AMI)xpm2iff.c + +$(SBIN)xpm2iff: $(OO)xpm2iff.o + $(LINK) $(LNSPEC) $@ $(LIN) $(OO)xpm2iff.o $(FLLIB) + +# Tile installation for the tile version of the game +inst-tiles: $(TILEFILES) + +#SFD_INSTEAD $(NETHACK)tiles: $(NETHACK)tiles +$(NETHACK)tiles: + -makedir $(NETHACK)tiles + +$(OO)txt2iff.o: $(AMI)txt2iff.c + $(CC) $(CFLAGS) $(CSYM) $(INCLSPEC)$(WSHARE) $(OBJSPEC)$@ \ + $(AMI)txt2iff.c + +$(OO)ppmwrite.o: $(WSHARE)ppmwrite.c + $(CC) $(CFLAGS) $(CSYM) $(INCLSPEC)$(WSHARE) $(OBJSPEC)$@ $(WSHARE)ppmwrite.c + +$(OO)tiletext.o: $(WSHARE)tiletext.c $(I)config.h $(WSHARE)tile.h + $(CC) $(CFLAGS) $(CSYM) $(INCLSPEC)$(WSHARE) $(OBJSPEC)$@ $(WSHARE)tiletext.c + +$(OO)tiletxt.o: $(WSHARE)tilemap.c $(I)hack.h + $(CC) $(CFLAGS) $(CSYM) $(DEFSPEC)TILETEXT $(INCLSPEC)$(WSHARE) $(OBJSPEC)$@ $(WSHARE)tilemap.c + +NAMEOBJS = $(O)drawing.o $(O)decl.o $(O)monst.o $(O)objects.o + +$(SBIN)txt2ppm: $(OO)ppmwrite.o $(NAMEOBJS) $(O)alloc.o $(OO)panic.o $(OO)tiletext.o $(OO)tiletxt.o + $(LINK) $(LNSPEC) $@ $(LIN) $(OO)ppmwrite.o $(NAMEOBJS) $(OO)tiletext.o $(OO)tiletxt.o $(O)alloc.o $(OO)panic.o $(FLLIB) + +$(SBIN)txt2iff: $(OO)txt2iff.o $(NAMEOBJS) $(OO)tiletext.o $(OO)tiletxt.o + $(LINK) $(LNSPEC) $@ $(LIN) $(OO)txt2iff.o $(NAMEOBJS) $(OO)tiletext.o \ + $(OO)tiletxt.o $(FLLIB) + +$(NETHACK)tiles/objects.iff: $(WSHARE)objects.txt $(SBIN)txt2iff + $(SBIN)txt2iff $(WSHARE)objects.txt $(NETHACK)tiles/objects.iff + +$(NETHACK)tiles/monsters.iff: $(WSHARE)monsters.txt $(SBIN)txt2iff + $(SBIN)txt2iff $(WSHARE)monsters.txt $(NETHACK)tiles/monsters.iff + +$(NETHACK)tiles/other.iff: $(WSHARE)other.txt $(SBIN)txt2iff + $(SBIN)txt2iff $(WSHARE)other.txt $(NETHACK)tiles/other.iff + +# Sound installation rules. +inst-sounds: $(SOUNDFILES) + list to T:nhsdat.lst $(SLIB)sounds QUICK NOHEAD + echo >T:make-nhsdat $(SBIN)dlb cCfI $(SLIB)sounds $(NETHACK)nhsdat T:nhsdat.lst + echo >>T:make-nhsdat if not exists $(NETHACK)nhsdat + echo >>T:make-nhsdat copy $(SLIB)sounds/\#? $(NETHACK)sounds + echo >>T:make-nhsdat endif + execute T:make-nhsdat + -delete T:make-nhsdat + +#SFD_INSTEAD $(SLIB)sounds: $(SLIB)sounds +$(SLIB)sounds: + -makedir $(SLIB)sounds + +$(SBIN)cvtsnd: $(OO)cvtsnd.o + $(LINK) $(LNSPEC) $@ $(LIN) $(OO)cvtsnd.o $(FLLIB) + +$(OO)cvtsnd.o: $(AMI)cvtsnd.c +#SFD_INSTEAD $(CC) $(CFLAGS) $(OBJSPEC)%(left) %(right) +#none + +$(SLIB)sounds/Bell: $(SHARE)sounds/bell.uu + $(UUDEC) $(SHARE)sounds/bell.uu + $(SBIN)cvtsnd Bell $(SLIB)sounds/Bell + -delete Bell + +$(SLIB)sounds/Bugle: $(SHARE)sounds/bugle.uu + $(UUDEC) $(SHARE)sounds/bugle.uu + $(SBIN)cvtsnd Bugle $(SLIB)sounds/Bugle + -delete Bugle + +$(SLIB)sounds/Drum_Of_Earthquake: $(SHARE)sounds/erthdrum.uu + $(UUDEC) $(SHARE)sounds/erthdrum.uu + $(SBIN)cvtsnd Drum_Of_Earthquake $(SLIB)sounds/Drum_Of_Earthquake + -delete Drum_Of_Earthquake + +$(SLIB)sounds/Fire_Horn: $(SHARE)sounds/firehorn.uu + $(UUDEC) $(SHARE)sounds/firehorn.uu + $(SBIN)cvtsnd Fire_Horn $(SLIB)sounds/Fire_Horn + -delete Fire_Horn + +$(SLIB)sounds/Frost_Horn: $(SHARE)sounds/frsthorn.uu + $(UUDEC) $(SHARE)sounds/frsthorn.uu + $(SBIN)cvtsnd Frost_Horn $(SLIB)sounds/Frost_Horn + -delete Frost_Horn + +$(SLIB)sounds/Leather_Drum: $(SHARE)sounds/lethdrum.uu + $(UUDEC) $(SHARE)sounds/lethdrum.uu + $(SBIN)cvtsnd Leather_Drum $(SLIB)sounds/Leather_Drum + -delete Leather_Drum + +$(SLIB)sounds/Magic_Flute: $(SHARE)sounds/mgcflute.uu + $(UUDEC) $(SHARE)sounds/mgcflute.uu + $(SBIN)cvtsnd Magic_Flute $(SLIB)sounds/Magic_Flute + -delete Magic_Flute + +$(SLIB)sounds/Magic_Harp: $(SHARE)sounds/mgcharp.uu + $(UUDEC) $(SHARE)sounds/mgcharp.uu + $(SBIN)cvtsnd Magic_Harp $(SLIB)sounds/Magic_Harp + -delete Magic_Harp + +$(SLIB)sounds/Tooled_Horn: $(SHARE)sounds/toolhorn.uu + $(UUDEC) $(SHARE)sounds/toolhorn.uu + $(SBIN)cvtsnd Tooled_Horn $(SLIB)sounds/Tooled_Horn + -delete Tooled_Horn + +$(SLIB)sounds/Wooden_Flute: $(SHARE)sounds/wdnflute.uu + $(UUDEC) $(SHARE)sounds/wdnflute.uu + $(SBIN)cvtsnd Wooden_Flute $(SLIB)sounds/Wooden_Flute + -delete Wooden_Flute + +$(SLIB)sounds/Wooden_Harp: $(SHARE)sounds/wdnharp.uu + $(UUDEC) $(SHARE)sounds/wdnharp.uu + $(SBIN)cvtsnd Wooden_Harp $(SLIB)sounds/Wooden_Harp + -delete Wooden_Harp + +inst-dungeon: $(INSTDUNGEONFILES) + +$(NETHACK)options : $(DAT)options + copy $(DAT)options $@ + +# Create compiled dungeon files +BGM= $(SLIB)bigrm-2.lev $(SLIB)bigrm-3.lev $(SLIB)bigrm-4.lev $(SLIB)bigrm-5.lev +$(BGM): $(SLIB)bigrm-1.lev + +$(SLIB)bigrm-1.lev: $(DAT)bigroom.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)bigroom.des +#none + +$(SLIB)castle.lev: $(DAT)castle.des $(SBIN)lev_comp + +ENDGAME1= $(SLIB)air.lev $(SLIB)earth.lev $(SLIB)fire.lev $(SLIB)water.lev +$(ENDGAME1): $(SLIB)astral.lev + +$(SLIB)astral.lev: $(DAT)endgame.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)endgame.des +#none + +GEHENNOM1= $(SLIB)asmodeus.lev $(SLIB)baalz.lev $(SLIB)juiblex.lev \ + $(SLIB)orcus.lev $(SLIB)sanctum.lev +$(GEHENNOM1): $(SLIB)valley.lev + +$(SLIB)valley.lev: $(DAT)gehennom.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)gehennom.des +#none + +$(SLIB)knox.lev: $(DAT)knox.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)knox.des +#none + +MINES1= $(SLIB)minend-1.lev $(SLIB)minend-2.lev $(SLIB)minetn-1.lev $(SLIB)minetn-2.lev +$(MINES1): $(SLIB)minefill.lev + +$(SLIB)minefill.lev: $(DAT)mines.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)mines.des +#none + +$(SLIB)oracle.lev: $(DAT)oracle.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)oracle.des +#none + +TOWER1= $(SLIB)tower1.lev $(SLIB)tower2.lev +$(TOWER1): $(SLIB)tower3.lev + +$(SLIB)tower3.lev: $(DAT)tower.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)tower.des +#none + +WIZARD1= $(SLIB)wizard1.lev $(SLIB)wizard2.lev $(SLIB)wizard3.lev \ + $(SLIB)fakewiz1.lev +$(WIZARD1): $(SLIB)fakewiz2.lev + +$(SLIB)fakewiz2.lev: $(DAT)yendor.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)yendor.des +#none + +MEDUSA1= $(SLIB)medusa-1.lev +$(MEDUSA1): $(SLIB)medusa-2.lev + +$(SLIB)medusa-2.lev: $(DAT)medusa.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)medusa.des +#none + +SOKOBAN1= $(SLIB)soko1-1.lev $(SLIB)soko1-2.lev $(SLIB)soko2-1.lev \ + $(SLIB)soko2-2.lev $(SLIB)soko3-1.lev $(SLIB)soko3-2.lev \ + $(SLIB)soko4-1.lev +$(SOKOBAN1): $(SLIB)soko4-2.lev + +$(SLIB)soko4-2.lev: $(DAT)sokoban.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)sokoban.des +#none + +$(ADFILES1): $(SLIB)Arc-goal.lev + +$(SLIB)Arc-goal.lev: $(DAT)Arch.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)Arch.des +#none + +$(BDFILES1): $(SLIB)Bar-goal.lev + +$(SLIB)Bar-goal.lev: $(DAT)Barb.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)Barb.des +#none + +$(CDFILES1): $(SLIB)Cav-goal.lev + +$(SLIB)Cav-goal.lev: $(DAT)Caveman.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)Caveman.des +#none + +$(HDFILES1): $(SLIB)Hea-goal.lev + +$(SLIB)Hea-goal.lev: $(DAT)Healer.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)Healer.des +#none + +$(KDFILES1): $(SLIB)Kni-goal.lev + +$(SLIB)Kni-goal.lev: $(DAT)Knight.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)Knight.des +#none + +$(MDFILES1): $(SLIB)Mon-goal.lev + +$(SLIB)Mon-goal.lev: $(DAT)Monk.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)Monk.des +#none + +$(PDFILES1): $(SLIB)Pri-goal.lev + +$(SLIB)Pri-goal.lev: $(DAT)Priest.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)Priest.des +#none + +$(RDFILES1): $(SLIB)Rog-goal.lev + +$(SLIB)Rog-goal.lev: $(DAT)Rogue.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)Rogue.des +#none + +$(RANFILES1): $(SLIB)Ran-goal.lev + +$(SLIB)Ran-goal.lev: $(DAT)Ranger.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)Ranger.des +#none + +$(SDFILES1): $(SLIB)Sam-goal.lev + +$(SLIB)Sam-goal.lev: $(DAT)Samurai.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)Samurai.des +#none + +$(TDFILES1): $(SLIB)Tou-goal.lev + +$(SLIB)Tou-goal.lev: $(DAT)Tourist.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)Tourist.des +#none + +$(VDFILES1): $(SLIB)Val-goal.lev + +$(SLIB)Val-goal.lev: $(DAT)Valkyrie.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)Valkyrie.des +#none + +$(WDFILES1): $(SLIB)Wiz-goal.lev + +$(SLIB)Wiz-goal.lev: $(DAT)Wizard.des $(SBIN)lev_comp +#SFD_INSTEAD $(SBIN)lev_comp $(DAT)Wizard.des +#none + +$(SLIB)dungeon: $(DAT)dungeon.def $(SBIN)makedefs $(SBIN)dgn_comp + $(SBIN)makedefs -e + $(SBIN)dgn_comp $(DAT)dungeon.pdf + copy $(DAT)dungeon $(SLIB)dungeon + delete $(DAT)dungeon + +inst-data: $(INSTDATAFILES) + +$(NETHACK)amii.hlp: $(AMI)amii.hlp + copy $(AMI)amii.hlp $@ + +#$(NETHACK)data: $(DAT)data +# copy $(DAT)data $@ + +$(SLIB)data: $(DAT)data.base $(I)config.h $(SBIN)makedefs + $(SBIN)makedefs -d + +#$(NETHACK)rumors: $(DAT)rumors +# copy $(DAT)rumors $@ + +$(SLIB)rumors: $(DAT)rumors.tru $(DAT)rumors.fal $(SBIN)makedefs + $(SBIN)makedefs -r + +$(SLIB)cmdhelp: $(DAT)cmdhelp + copy $(DAT)cmdhelp $@ + +$(SLIB)help: $(DAT)help + copy $(DAT)help $@ + +$(SLIB)hh: $(DAT)hh + copy $(DAT)hh $@ + +$(NETHACK)HackWB.hlp: $(AMI)HackWB.hlp + copy $(AMI)HackWB.hlp $@ + +$(SLIB)history: $(DAT)history + copy $(DAT)history $@ + +$(NETHACK)license: $(DAT)license + copy $(DAT)license $@ + +$(SLIB)opthelp: $(DAT)opthelp + copy $(DAT)opthelp $@ + +$(NETHACK)Recover.txt: $(DOC)Recover.txt + copy $(DOC)Recover.txt $@ + +$(NETHACK)GuideBook.txt: $(DOC)GuideBook.txt + copy $(DOC)GuideBook.txt $@ + +$(NETHACK)NetHack.txt: $(DOC)NetHack.txt + copy $(DOC)NetHack.txt $@ + +$(NETHACK)Install.ami: $(AMI)Install.ami + copy $(AMI)Install.ami $@ + +#SFD_INSTEAD $(NETHACK)logfile: $(NETHACK)logfile +$(NETHACK)logfile: + echo to $@ + +#SFD_INSTEAD $(NETHACK)record: $(NETHACK)record +$(NETHACK)record: + echo to $@ + +$(SLIB)wizhelp: $(DAT)wizhelp + copy $(DAT)wizhelp $@ + +# Create the directories here because NetHack.cnf puts them there by default +$(NETHACK)NetHack.cnf: $(AMI)NetHack.cnf + copy $(AMI)NetHack.cnf $@ + -makedir $(NETHACK)save + -makedir $(NETHACK)levels + +#SFD_BEGIN +#SFD_ELSE +$(O)NetHack.gst: $(GSTSRC) $(I)hack.h + sc makegst=$(GSTFILE) $(CFLAGS) $(GSTSRC) +#SFD_END + +# Unpack and install fonts + +INSTFONTFILES= $(NETHACK)hack.font $(NETHACK)hack $(NETHACK)hack/8 + +inst-fonts: $(INSTFONTFILES) + +$(NETHACK)hack/8: $(AMI)amifont8.uu $(NETHACK)hack + $(UUDEC) $(AMI)amifont8.uu + copy 8 $(NETHACK)hack/8 + delete 8 + +$(NETHACK)hack.font: $(AMI)amifont.uu + $(UUDEC) $(AMI)amifont.uu + copy hack.font $(NETHACK)hack.font + delete hack.font + +#SFD_INSTEAD $(NETHACK)hack: $(NETHACK)hack +$(NETHACK)hack: + -makedir $@ + +INSTICONFILES= \ + $(NETHACK)default.icon $(NETHACK)NetHack.info $(NETHACK)NewGame.info \ + $(NETHACK)HackWB.info + +inst-icons: $(INSTICONFILES) + +# Unpack the icons into place + +$(NETHACK)default.icon: $(AMI)dflticon.uu + $(UUDEC) $(AMI)dflticon.uu +# copy default.icon $(NETHACK)default.icon +# delete default.icon + +$(NETHACK)NetHack.info: $(AMI)NHinfo.uu + $(UUDEC) $(AMI)NHinfo.uu +# copy NetHack.info $(NETHACK)NetHack.info +# delete NetHack.info + +$(NETHACK)NewGame.info: $(AMI)NewGame.uu + $(UUDEC) $(AMI)NewGame.uu +# copy NewGame.info $(NETHACK)NewGame.info +# delete NewGame.info + +$(NETHACK)HackWB.info: $(AMI)HackWB.uu + $(UUDEC) $(AMI)HackWB.uu +# copy HackWB.info $(NETHACK)HackWB.info +# delete HackWB.info + +# If DLB is defined, create the nhdat library file in the playground +# directory. If not, move all the data files there. +$(NETHACK)nhdat: $(LIBFILES) $(SBIN)dlb + list to T:nhdat.lst $(SLIB) QUICK NOHEAD FILES + echo >T:make-nhdat $(SBIN)dlb cCfI $(SLIB) $(NETHACK)nhdat T:nhdat.lst + echo >>T:make-nhdat if not exists $(NETHACK)nhdat + echo >>T:make-nhdat copy $(SLIB)\#? $(NETHACK) + echo >>T:make-nhdat endif + execute T:make-nhdat + -delete T:make-nhdat + +# DO NOT DELETE THIS LINE + +$(O)allmain.o: $(NHS)allmain.c $(HDEP) + +$(O)alloc.o: $(NHS)alloc.c $(I)config.h + +$(O)apply.o: $(NHS)apply.c $(HDEP) $(I)edog.h +#SFD_INSTEAD #none + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)apply.c + +$(O)artifact.o: $(NHS)artifact.c $(HDEP) $(I)artifact.h $(I)artilist.h + +$(O)attrib.o: $(NHS)attrib.c $(HDEP) $(I)artifact.h + +$(O)ball.o: $(NHS)ball.c $(HDEP) + +$(O)bones.o: $(NHS)bones.c $(HDEP) $(I)lev.h + +$(O)botl.o: $(NHS)botl.c $(HDEP) + +$(O)cmd.o: $(NHS)cmd.c $(HDEP) $(I)func_tab.h + +$(O)dbridge.o: $(NHS)dbridge.c $(HDEP) + +$(O)decl.o: $(NHS)decl.c $(HDEP) $(I)quest.h + +$(O)detect.o: $(NHS)detect.c $(HDEP) $(I)artifact.h + +$(O)dig.o: $(NHS)dig.c $(HDEP) $(I)edog.h + +$(O)display.o: $(NHS)display.c $(HDEP) + +$(O)dlb.o: $(NHS)dlb.c $(HDEP) $(I)dlb.h + +$(O)do.o: $(NHS)do.c $(HDEP) $(I)lev.h + +$(O)do_name.o: $(NHS)do_name.c $(HDEP) + +$(O)do_wear.o: $(NHS)do_wear.c $(HDEP) + +$(O)dog.o: $(NHS)dog.c $(HDEP) $(I)edog.h + +$(O)dogmove.o: $(NHS)dogmove.c $(HDEP) $(I)mfndpos.h $(I)edog.h + +$(O)dokick.o: $(NHS)dokick.c $(HDEP) $(I)eshk.h + +$(O)dothrow.o: $(NHS)dothrow.c $(HDEP) + +$(O)drawing.o: $(NHS)drawing.c $(HDEP) $(I)tcap.h + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)drawing.c + +$(O)dungeon.o: $(NHS)dungeon.c $(HDEP) $(I)dgn_file.h $(I)dlb.h + +$(O)eat.o: $(NHS)eat.c $(HDEP) + +$(O)end.o: $(NHS)end.c $(HDEP) $(I)eshk.h $(I)dlb.h + +$(O)engrave.o: $(NHS)engrave.c $(HDEP) $(I)lev.h + +$(O)exper.o: $(NHS)exper.c $(HDEP) + +$(O)explode.o: $(NHS)explode.c $(HDEP) + +$(O)extralev.o: $(NHS)extralev.c $(HDEP) + +$(O)files.o: $(NHS)files.c $(HDEP) $(I)dlb.h $(I)date.h + +$(O)fountain.o: $(NHS)fountain.c $(HDEP) + +$(O)hack.o: $(NHS)hack.c $(HDEP) + +$(O)hacklib.o: $(NHS)hacklib.c $(HDEP) + +$(O)invent.o: $(NHS)invent.c $(HDEP) $(I)artifact.h + +$(O)light.o: $(NHS)light.c $(HDEP) $(I)lev.h + +$(O)lock.o: $(NHS)lock.c $(HDEP) + +$(O)mail.o: $(NHS)mail.c $(HDEP) $(I)mail.h + +$(O)makemon.o: $(NHS)makemon.c $(HDEP) $(I)epri.h $(I)emin.h $(I)edog.h + +$(O)mapglyph.o: $(NHS)mapglyph.c $(HDEP) + +$(O)mcastu.o: $(NHS)mcastu.c $(HDEP) + +$(O)mhitm.o: $(NHS)mhitm.c $(HDEP) $(I)artifact.h $(I)edog.h + +$(O)mhitu.o: $(NHS)mhitu.c $(HDEP) $(I)artifact.h $(I)edog.h + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)mhitu.c + +$(O)minion.o: $(NHS)minion.c $(HDEP) $(I)emin.h $(I)epri.h + +$(O)mklev.o: $(NHS)mklev.c $(HDEP) + +$(O)mkmap.o: $(NHS)mkmap.c $(HDEP) $(I)sp_lev.h + +$(O)mkmaze.o: $(NHS)mkmaze.c $(HDEP) $(I)sp_lev.h $(I)lev.h + +$(O)mkobj.o: $(NHS)mkobj.c $(HDEP) $(I)artifact.h $(I)prop.h + +$(O)mkroom.o: $(NHS)mkroom.c $(HDEP) + +$(O)mon.o: $(NHS)mon.c $(HDEP) $(I)mfndpos.h $(I)edog.h + +$(O)mondata.o: $(NHS)mondata.c $(HDEP) $(I)eshk.h $(I)epri.h + +$(O)monmove.o: $(NHS)monmove.c $(HDEP) $(I)mfndpos.h $(I)artifact.h + +$(O)monst.o: $(NHS)monst.c $(I)config.h $(I)permonst.h $(I)monsym.h \ + $(I)eshk.h $(I)vault.h $(I)epri.h $(I)color.h + +$(O)monstr.o: $(NHS)monstr.c $(HDEP) +#SFD_INSTEAD $(CC) $(CFLAGS) $(OBJSPEC)%(left) $(NHS)monstr.c +#none + +$(O)mplayer.o: $(NHS)mplayer.c $(HDEP) + +$(O)mthrowu.o: $(NHS)mthrowu.c $(HDEP) + +$(O)muse.o: $(NHS)muse.c $(HDEP) + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)muse.c + +$(O)music.o: $(NHS)music.c $(HDEP) #interp.c + +$(O)o_init.o: $(NHS)o_init.c $(HDEP) $(I)lev.h + +$(O)objects.o: $(NHS)objects.c $(I)config.h $(I)obj.h $(I)objclass.h \ + $(I)prop.h $(I)skills.h $(I)color.h +#SFD_INSTEAD #none + $(CC) $(CFLAGS) $(INCLSPEC)$(NHS) $(OBJSPEC)$@ $(NHS)objects.c + +$(O)objnam.o: $(NHS)objnam.c $(HDEP) + +$(O)options.o: $(NHS)options.c $(HDEP) $(I)tcap.h $(I)config.h \ + $(I)objclass.h $(I)flag.h + +$(O)pager.o: $(NHS)pager.c $(HDEP) $(I)dlb.h + +$(O)pickup.o: $(NHS)pickup.c $(HDEP) + +$(O)pline.o: $(NHS)pline.c $(HDEP) $(I)epri.h + +$(O)polyself.o: $(NHS)polyself.c $(HDEP) + +$(O)potion.o: $(NHS)potion.c $(HDEP) + +$(O)pray.o: $(NHS)pray.c $(HDEP) $(I)epri.h + +$(O)priest.o: $(NHS)priest.c $(HDEP) $(I)mfndpos.h $(I)eshk.h $(I)epri.h \ + $(I)emin.h + +$(O)quest.o: $(NHS)quest.c $(HDEP) $(I)quest.h $(I)qtext.h + +$(O)questpgr.o: $(NHS)questpgr.c $(HDEP) $(I)qtext.h $(I)dlb.h + +$(O)read.o: $(NHS)read.c $(HDEP) + +$(O)rect.o: $(NHS)rect.c $(HDEP) + +$(O)region.o: $(NHS)region.c $(HDEP) + +$(O)restore.o: $(NHS)restore.c $(HDEP) $(I)lev.h $(I)tcap.h $(I)quest.h + +$(O)rnd.o: $(NHS)rnd.c $(HDEP) + +$(O)role.o: $(NHS)role.c $(HDEP) + +$(O)rumors.o: $(NHS)rumors.c $(HDEP) $(I)dlb.h + +$(O)save.o: $(NHS)save.c $(HDEP) $(I)lev.h $(I)quest.h + +$(O)shk.o: $(NHS)shk.c $(HDEP) $(I)eshk.h +#SFD_INSTEAD #none + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)shk.c + +$(O)shknam.o: $(NHS)shknam.c $(HDEP) $(I)eshk.h + +$(O)sit.o: $(NHS)sit.c $(HDEP) $(I)artifact.h + +$(O)sounds.o: $(NHS)sounds.c $(HDEP) $(I)edog.h + +$(O)sp_lev.o: $(NHS)sp_lev.c $(HDEP) $(I)sp_lev.h $(I)rect.h $(I)dlb.h + +$(O)spell.o: $(NHS)spell.c $(HDEP) + +$(O)steal.o: $(NHS)steal.c $(HDEP) + +$(O)steed.o: $(NHS)steed.c $(HDEP) + +$(O)teleport.o: $(NHS)teleport.c $(HDEP) + +$(O)timeout.o: $(NHS)timeout.c $(HDEP) $(I)lev.h + +$(O)topten.o: $(NHS)topten.c $(HDEP) $(I)dlb.h + +$(O)track.o: $(NHS)track.c $(HDEP) + +$(O)trap.o: $(NHS)trap.c $(HDEP) +#SFD_INSTEAD #none + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)trap.c + +$(O)u_init.o: $(NHS)u_init.c $(HDEP) + +$(O)uhitm.o: $(NHS)uhitm.c $(HDEP) + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)uhitm.c + +$(O)vault.o: $(NHS)vault.c $(HDEP) $(I)vault.h + +$(O)version.o: $(NHS)version.c $(HDEP) $(I)date.h $(I)patchlevel.h + +# DMake doesn't grok mid-line comments +#SFD_INSTEAD $(O)vision.o: $(NHS)vision.c $(HDEP) +$(O)vision.o: $(NHS)vision.c $(HDEP) #$(I)vis_tab.h + +$(O)weapon.o: $(NHS)weapon.c $(HDEP) + +$(O)were.o: $(NHS)were.c $(HDEP) + +$(O)wield.o: $(NHS)wield.c $(HDEP) + +$(O)windows.o: $(NHS)windows.c $(HDEP) $(I)wintty.h + +$(O)wizard.o: $(NHS)wizard.c $(HDEP) $(I)qtext.h + +$(O)worm.o: $(NHS)worm.c $(HDEP) $(I)lev.h + +$(O)worn.o: $(NHS)worn.c $(HDEP) + +$(O)write.o: $(NHS)write.c $(HDEP) + +$(O)zap.o: $(NHS)zap.c $(HDEP) + $(CC) $(CFLAGS) $(CFLAGS2) $(OBJSPEC)$@ $(NHS)zap.c + +$(O)getline.o: $(TTY)getline.c $(HDEP) $(I)wintty.h + +$(O)termcap.o: $(TTY)termcap.c $(HDEP) $(I)wintty.h $(I)tcap.h + +$(O)topl.o: $(TTY)topl.c $(HDEP) $(I)wintty.h $(I)tcap.h + +$(O)wintty.o: $(TTY)wintty.c $(HDEP) $(I)wintty.h $(I)tcap.h \ + $(I)patchlevel.h + +$(O)amitty.o: $(AMI)amitty.c $(HDEP) + +$(O)amistack.o: $(AMI)amistack.c + $(CC) $(CFLAGS3) $(CSYM) $(OBJSPEC)$@ $(AMI)amistack.c + +$(O)rip.o: $(NHS)rip.c $(HDEP) + + +$(I)config.h: $(I)config1.h $(I)tradstdc.h $(I)global.h + -setdate $(I)config.h + -wait 2 + +# onames.h handled at onames.h target, pm.h + +$(I)decl.h: $(I)quest.h $(I)spell.h $(I)color.h $(I)obj.h $(I)you.h + -setdate $(I)decl.h + -wait 2 + +$(I)global.h: $(I)coord.h $(I)pcconf.h $(I)amiconf.h + -setdate $(I)global.h + -wait 2 + +$(I)hack.h: $(I)config.h $(I)trap.h $(I)decl.h $(I)dungeon.h $(I)monsym.h \ + $(I)mkroom.h $(I)objclass.h $(I)flag.h $(I)rm.h $(I)vision.h \ + $(I)display.h $(I)wintype.h $(I)engrave.h $(I)rect.h \ + $(I)region.h $(I)trampoli.h + -setdate $(I)hack.h + -wait 2 + +$(I)permonst.h: $(I)monattk.h $(I)monflag.h $(I)align.h + -setdate $(I)permonst.h + -wait 2 + +$(I)you.h: $(I)align.h $(I)attrib.h $(I)monst.h $(I)youprop.h $(I)skills.h + -setdate $(I)you.h + -wait 2 + +# pm.h handled at target + +$(I)youprop.h: $(I)prop.h $(I)permonst.h $(I)mondata.h + -setdate $(I)youprop.h + -wait 2 + +$(I)display.h: $(I)vision.h $(I)mondata.h + -setdate $(I)display.h + -wait 2 + +$(I)dungeon.h: $(I)align.h + -setdate $(I)dungeon.h + -wait 2 + +$(I)emin.h: $(I)dungeon.h + -setdate $(I)emin.h + -wait 2 + +$(I)epri.h: $(I)dungeon.h $(I)align.h + -setdate $(I)epri.h + -wait 2 + +$(I)eshk.h: $(I)dungeon.h + -setdate $(I)eshk.h + -wait 2 + +$(I)engrave.h: $(I)trampoli.h $(I)rect.h + -setdate $(I)engrave.h + -wait 2 + +$(I)mondata.h: $(I)align.h + -setdate $(I)mondata.h + -wait 2 + +$(I)monst.h: $(I)align.h + -setdate $(I)monst.h + -wait 2 + +$(I)pcconf.h: $(I)micro.h $(I)system.h + -setdate $(I)pcconf.h + -wait 2 + +$(I)rm.h: $(I)align.h + -setdate $(I)rm.h + -wait 2 + +$(I)vault.h: $(I)dungeon.h + -setdate $(I)vault.h + -wait 2 + + +#notes +# install keeps doing re-install because it keeps rebuilding lev_comp??? +# fixed(?) - deleted setdate +# make nhdat rebuils sys/amiga objects diff --git a/sys/amiga/NetHack.cnf b/sys/amiga/NetHack.cnf new file mode 100644 index 0000000..90de3af --- /dev/null +++ b/sys/amiga/NetHack.cnf @@ -0,0 +1,212 @@ +# A '#' at the beginning of a line means the rest of the line is a comment. + +# This is an example configuration file. +# If several people are to use it, don't specify "name" or personal +# prefences like "dogname" or "packorder" in OPTIONS. + +# To change configuration, comment out the unwanted configurations, and +# remove the comment from the configuration you want. + +# Some options to set personal preferences. If several people are to +# use it, options like these should not be set here - use the command line +#OPTIONS=name:Janet-V,female,dogname:Fido,fruit:apricot +#OPTIONS=packorder:")[%?+/=!(*0_`,scores:10t/2a,noverbose +#OPTIONS=gender:male +#OPTIONS=role:random +#OPTIONS=race:random +#OPTIONS=align:chaotic +# Other general options +#OPTIONS=time,rest_on_space,noautopickup + +# The search path for files like record, help, opthelp, etc. +PATH=NetHack: + +# My own setup +#OPTIONS=nolegacy,fruit:lemon,time,autopickup,checkpoint,showexp,showscore,standout,nonews +#OPTIONS=nomail,flush,eight_bit_tty,scores:10t/2a,pickup_types:$,suppress_alert:3.3.0,autoquiver + +# The windowtype option must be set before any options regarding colors and palette +# are set otherwise previously set values will be overridden by the defaults +# +# The font version of the game +OPTIONS=windowtype:amii +# +# New tile version of the game +#OPTIONS=windowtype:amitile +# +# A hard disk configuration. +# +HACKDIR=NetHack: +LEVELS=Nethack:Levels +SAVE=Nethack:Save +BONESDIR=Nethack:Levels +SCOREDIR=Nethack: +LOCKDIR=Nethack: +CONFIGDIR=Nethack: +DATADIR=Nethack: + +# *** CHARACTER GRAPHICS *** +# +# See the on-line help or the Guidebook for which symbols are in which +# positions. +# +# Note that the hack.font has special graphics characters from 192 on. + +# An example using the hack.font graphics character set: +DUNGEON = 032 192 193 194 195 196 197 198 216 214 \ + 215 213 217 145 146 147 148 035 035 217 \ + 218 229 060 062 060 062 095 124 092 035 \ + 123 125 042 125 042 042 035 035 046 035 \ + 125 + +TRAPS = 094 094 094 094 094 094 094 094 094 094 \ + 094 094 094 094 094 094 094 034 094 094 \ + 094 094 + +EFFECTS = 241 240 242 243 042 033 123 125 \ + 064 038 042 035 \ + 244 245 246 247 239 248 249 250 \ + 230 234 231 236 212 237 232 235 233 + +WARNINGS = 048 049 050 051 052 053 + +# Monitors vary greatly in their color response. If the default colors +# are not good on your monitor, here are some other alternatives for the +# font version of the game: +# +# Last color of the palette is always used for the cursor. +# +#CBM 1960, set color/contrast for good pure red, green, and blue. True colors. +#PENS=000,fff,a61,7bb,0f0,e0c,00f,f00 +#CBM 1960, set color/contrast as above, better colors for NetHack. +#PENS=667,fff,da1,7bb,2f0,e0d,0af,f42 +#and other suggestions: +#PENS=888,ffc,840,0b8,4e4,e8b,7be,a04 +#PENS=000,fff,830,7ae,181,c06,23e,c00 +# +# For an "interlaced"+ line screen, the default font is courier:13. If you want +# a different font, set it here. The format is "fontname.font:size"; i.e. the +# .font extension is required. +#FONT=courier.font:13 +#FONT=topaz.font:8 +# +# Proportional fonts such as CGTimes are probably not a good idea because they +# result in many things not being spaced out correctly. +#FONT=CGTimes.font:15 +# +# This sized proportional font is readable, but still has spacing problems +#FONT=CGTimes.font:21 +# +# FOR AGA OR OTHER DISPLAYS CAPABLE OF 5 OR MORE PLANES... +# +# For a screen of depth 5 the following dripens provide a brown border +# using pens 16-31. +# +# Pens 16-31 can be redefined with PENS= if you want different colors, +# using the PENS= values below for a 4 plane screen as the first 16 colors. +# +#DEPTH=5 +#DRIPENS=0,0,0,17,27,23,1,23,15,0,23,27 +# +# The APEN and BPEN values in the various types of windows can be set in +# the manner shown below. These values are for the 16 color version of +# the tile game. +# +# These values are specified as APEN,BPEN (foreground,background) +# +#MSGPENS=1,12 +#STATUSPENS=1,12 +#MENUPENS=1,23 +#TEXTPENS=1,23 +#OTHERPENS=1,23 +# +# FOR ECS OR OTHERS ONLY CAPABLE OF 4 PLANES... +# +# These values work good for the TILE version of the game on ECS machines +# These are the default values for reference purposes. +# +#DEPTH=4 +#defaults for tilemode: +#PENS=000,fff,0bf,f60,00f,090,69b,f00,6f0,ff0,f0f,940,466,c40,ddb,fb9 +#DRIPENS=0,1,0,2,4,12,14,12,7,1,12,4 +#defaults for fontmode: +#PENS=000,fff,830,7ac,181,c06,23e,c00 +#DRIPENS=0,6,2,1,6,3,1,3,7,1,3,6 +# +# The APEN and BPEN values in the various types of windows can be set in +# the manner shown below. These values are for a 32 color version of +# the tile game. +# +# These values are specified as APEN,BPEN (foreground,background) +# +#MSGPENS=1,12 +#STATUSPENS=1,12 +#MENUPENS=0,14 +#TEXTPENS=0,14 +#OTHERPENS=1,12 +# +# New alternative color scheme for 16 color font mode. +# This changes the colors of monsters, objects etc. +# +# FGPENS and BGPENS define APEN and BPEN for objects and monsters on the map. +# The colors are in the following order: +# black, red, green, brown, blue, magenta, cyan, gray, no color, orange, +# bright green, yellow, bright blue, bright magenta, bright cyan, white +# +DEPTH=4 +PENS=000,fff,830,7ac,181,c06,23e,c00,888,f60,4f4,ff0,4af,f8f,8ff,f00 +FGPENS= 0, 7, 4, 2, 6, 5, 3, 8, 1, 9,10,11,12,13,14, 1 +BGPENS= 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +# +# Screen mode selections below should all work for either the font or tile +# version of the game. Other modes can be tried and as long as they are at +# least 640x200, the game should adapt to them... +# +# Select screenmode with a requester +#SCREENMODE=Req +# NTSC_MONITOR_ID +#SCREENMODE=0x00019000 +# PAL_MONITOR_ID +#SCREENMODE=0x00029000 +# NTSC_MONITOR_ID+LACE +#SCREENMODE=0x00019004 +# PAL_MONITOR_ID+LACE +#SCREENMODE=0x00029004 +# NTSC_MONITOR_ID+HIRES+LACE +#SCREENMODE=0x00019024 +# PAL_MONITOR_ID+HIRES+LACE +#SCREENMODE=0x00029024 +# VGA_MONITOR_ID +#SCREENMODE=0x00031000 +# VGAPRODUCT_KEY +#SCREENMODE=0x00039024 +# A2024TENHERTZ_KEY +#SCREENMODE=0x00041000 +# A2024FIFTEENHERTZ_KEY +#SCREENMODE=0x00049000 +# EURO72_MONITOR_ID +#SCREENMODE=0x00061000 +# EURO72PRODUCT_KEY +#SCREENMODE=0x00069024 +# EURO72PRODUCTLACE_KEY +#SCREENMODE=0x00069025 +# EURO72PRODUCTDBL_KEY +#SCREENMODE=0x00069020 +# EURO36_MONITOR_ID +#SCREENMODE=0x00071000 +# SUPER72HIRESDBL_KEY +#SCREENMODE=0x00089008 +# SUPER72SUPERDBL_KEY +#SCREENMODE=0x00089028 +# DBLNTSCHIRES_KEY +#SCREENMODE=0x00099000 +# DBLNTSCHIRESFF_KEY +#SCREENMODE=0x00099004 +# DBLNTSCHIRESLACE_KEY +#SCREENMODE=0x00099005 +# DBLPALHIRES_KEY +#SCREENMODE=0x000a9000 +# DBLPALHIRESFF_KEY +#SCREENMODE=0x000a9004 +# DBLPALHIRESLACE_KEY +#SCREENMODE=0x000a9005 diff --git a/sys/amiga/amidos.c b/sys/amiga/amidos.c new file mode 100644 index 0000000..e5a975c --- /dev/null +++ b/sys/amiga/amidos.c @@ -0,0 +1,490 @@ +/* SCCS Id: @(#)amidos.c 3.2 2000/01/12 +/* Copyright (c) Olaf Seibert, Nijmegen, The Netherlands, 1988,1990. */ +/* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1991,1992,1993,1996. */ +/* NetHack may be freely redistributed. See license for details. */ + +/* + * An assortment of imitations of cheap plastic MSDOS and Unix functions. + */ + +#include "hack.h" +#include "winami.h" + +/* Defined in config.h, let's undefine it here (static function below) */ +#undef strcmpi + +#include +#include +#include + +#undef COUNT +#if defined(__SASC_60) || defined(__GNUC__) +# include +# include +#endif + +#ifdef AZTEC_50 +# include +# undef strcmpi +#endif + +/* Prototypes */ +#include "NH:sys/amiga/winami.p" +#include "NH:sys/amiga/amiwind.p" +#include "NH:sys/amiga/amidos.p" + +extern char Initialized; +extern struct window_procs amii_procs; + +#ifndef __SASC_60 +int Enable_Abort = 0; /* for stdio package */ +#endif + +/* Initial path, so we can find NetHack.cnf */ +char PATH[PATHLEN] = "NetHack:"; + +static boolean record_exists(void); + +void +flushout() +{ + (void) fflush(stdout); +} + +#ifndef getuid +getuid() +{ + return 1; +} +#endif + +#ifndef getlogin +char * +getlogin() +{ + return ((char *) NULL); +} +#endif + +#ifndef AZTEC_50 +int +abs(x) +int x; +{ + return x < 0? -x: x; +} +#endif + +#ifdef SHELL +int +dosh() +{ + int i; + char buf[ BUFSZ ]; + extern struct ExecBase *SysBase; + + /* Only under 2.0 and later ROMs do we have System() */ + if( SysBase->LibNode.lib_Version >= 37 && !amibbs) + { + getlin("Enter CLI Command...", buf ); + if (buf[0] != '\033') + i = System( buf, NULL ); + } + else + { + i = 0; + pline("No mysterious force prevented you from using multitasking."); + } + return i; +} +#endif /* SHELL */ + +#ifdef MFLOPPY +# include + +# define Sprintf (void) sprintf + +#define EXTENSION 72 + +/* + * This routine uses an approximation of the free bytes on a disk. + * How large a file you can actually write depends on the number of + * extension blocks you need for it. + * In each extenstion block there are maximum 72 pointers to blocks, + * so every 73 disk blocks have only 72 available for data. + * The (necessary) file header is also good for 72 data block pointers. + */ +/* TODO: update this for FFS */ +long +freediskspace(path) +char *path; +{ + register long freeBytes = 0; + register struct InfoData *infoData; /* Remember... longword aligned */ + char fileName[32]; + + /* + * Find a valid path on the device of which we want the free space. + * If there is a colon in the name, it is an absolute path + * and all up to the colon is everything we need. + * Remember slashes in a volume name are allowed! + * If there is no colon, it is relative to the current directory, + * so must be on the current device, so "" is enough... + */ + { + register char *colon; + + strncpy(fileName, path, sizeof(fileName) - 1); + fileName[31] = 0; + if (colon = index(fileName, ':')) + colon[1] = '\0'; + else + fileName[0] = '\0'; + } + { + BPTR fileLock; + infoData = (struct InfoData *) alloc(sizeof(struct InfoData)); + if (fileLock = Lock(fileName, SHARED_LOCK)) { + if (Info(fileLock, infoData)) { + /* We got a kind of DOS volume, since we can Lock it. */ + /* Calculate number of blocks available for new file */ + /* Kludge for the ever-full VOID: (oops RAM:) device */ + if (infoData->id_UnitNumber == -1 && + infoData->id_NumBlocks == infoData->id_NumBlocksUsed) { + freeBytes = AvailMem(0L) - 64 * 1024L; + /* Just a stupid guess at the */ + /* Ram-Handler overhead per block: */ + freeBytes -= freeBytes/16; + } else { + /* Normal kind of DOS file system device/volume */ + freeBytes = infoData->id_NumBlocks - infoData->id_NumBlocksUsed; + freeBytes -= (freeBytes + EXTENSION) / (EXTENSION + 1); + freeBytes *= infoData->id_BytesPerBlock; + } + if (freeBytes < 0) + freeBytes = 0; + } + UnLock(fileLock); + } + free(infoData); + return freeBytes; + } +} + + +long +filesize(file) +char *file; +{ + register BPTR fileLock; + register struct FileInfoBlock *fileInfoBlock; + register long size = 0; + + fileInfoBlock = (struct FileInfoBlock *)alloc(sizeof(struct FileInfoBlock)); + if (fileLock = Lock(file, SHARED_LOCK)) { + if (Examine(fileLock, fileInfoBlock)) { + size = fileInfoBlock->fib_Size; + } + UnLock(fileLock); + } + free(fileInfoBlock); + return size; +} + +#if 0 +void +eraseall(path, files) +const char *path, *files; +{ + BPTR dirLock, dirLock2; + struct FileInfoBlock *fibp; + int chklen; +#ifdef BETA + if(files != alllevels)panic("eraseall"); +#endif + chklen=(int)index(files,'*')-(int)files; + + if (dirLock = Lock( (char *)path ,SHARED_LOCK)) { + dirLock2=DupLock(dirLock); + dirLock2= CurrentDir(dirLock2); + fibp=AllocMem(sizeof(struct FileInfoBlock),0); + if(fibp){ + if(Examine(dirLock,fibp)){ + while(ExNext(dirLock,fibp)){ + if(!strncmp(fibp->fib_FileName,files,chklen)){ + DeleteFile(fibp->fib_FileName); + } + } + } + FreeMem(fibp,sizeof(struct FileInfoBlock)); + } + UnLock(dirLock); + UnLock(CurrentDir(dirLock2)); + } +} +#endif + +/* This size makes that most files can be copied with two Read()/Write()s */ + +#if 0 /* Unused */ +#define COPYSIZE 4096 + +char *CopyFile(from, to) +const char *from, *to; +{ + register BPTR fromFile, toFile; + register char *buffer; + register long size; + char *error = NULL; + + buffer = (char *) alloc(COPYSIZE); + if (fromFile = Open( (char *)from, MODE_OLDFILE)) { + if (toFile = Open( (char *)to, MODE_NEWFILE)) { + while (size = Read(fromFile, buffer, (long)COPYSIZE)) { + if (size == -1){ + error = "Read error"; + break; + } + if (size != Write(toFile, buffer, size)) { + error = "Write error"; + break; + } + } + Close(toFile); + } else + error = "Cannot open destination"; + Close(fromFile); + } else + error = "Cannot open source (this should not occur)"; + free(buffer); + return error; +} +#endif + +/* this should be replaced */ +saveDiskPrompt(start) +{ + char buf[BUFSIZ], *bp; + BPTR fileLock; + + if (flags.asksavedisk) { + /* Don't prompt if you can find the save file */ + if (fileLock = Lock(SAVEF, SHARED_LOCK)) { + UnLock(fileLock); +#if defined(TTY_GRAPHICS) + if(windowprocs.win_init_nhwindows!=amii_procs.win_init_nhwindows) + clear_nhwindow( WIN_MAP ); +#endif +#if defined(AMII_GRAPHICS) + if(windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows) + clear_nhwindow( WIN_BASE ); +#endif + return 1; + } + pline( "If save file is on a SAVE disk, put that disk in now." ); + if( strlen( SAVEF ) > QBUFSZ - 25 - 22 ) + panic( "not enough buffer space for prompt" ); +/* THIS IS A HACK */ +#if defined(TTY_GRAPHICS) + if(windowprocs.win_init_nhwindows!=amii_procs.win_init_nhwindows){ + getlin("File name ?",buf); + clear_nhwindow( WIN_MAP ); + } +#endif +#if defined(AMII_GRAPHICS) + if(windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows){ + getlind("File name ?", buf, SAVEF); + clear_nhwindow( WIN_BASE ); + } +#endif + clear_nhwindow( WIN_MESSAGE); + if (!start && *buf == '\033') + return 0; + + /* Strip any whitespace. Also, if nothing was entered except + * whitespace, do not change the value of SAVEF. + */ + for (bp = buf; *bp; bp++) { + if (!isspace(*bp)) { + strncpy(SAVEF, bp, PATHLEN); + break; + } + } + } + return 1; +} + +/* Return 1 if the record file was found */ +static boolean +record_exists() +{ + FILE *file; + + if (file = fopenp(RECORD, "r")) { + fclose(file); + return TRUE; + } + return FALSE; +} + +#ifdef MFLOPPY +/* + * Under MSDOS: Prompt for game disk, then check for record file. + * For Amiga: do nothing, but called from restore.c + */ +void +gameDiskPrompt(){} +#endif + +/* + * Add a slash to any name not ending in / or :. There must + * be room for the /. + */ +void +append_slash(name) +char *name; +{ + char *ptr; + + if (!*name)return; + + ptr = eos(name) - 1; + if (*ptr != '/' && *ptr != ':') { + *++ptr = '/'; + *++ptr = '\0'; + } +} + + +void +getreturn(str) +const char *str; +{ + int ch; + + raw_printf("Hit %s.", str); + while ((ch = nhgetch()) != '\n' && ch != '\r' ) + continue; +} + +/* Follow the PATH, trying to fopen the file. + */ +#define PATHSEP ';' + +FILE * +fopenp(name, mode) +register const char *name, *mode; +{ + register char *bp, *pp, lastch; + register FILE *fp; + register BPTR theLock; + char buf[BUFSIZ]; + + /* Try the default directory first. Then look along PATH. + */ + if (strlen(name) >= BUFSIZ) return( NULL ); + strcpy(buf, name); + if (theLock = Lock(buf, SHARED_LOCK)) { + UnLock(theLock); + if (fp = fopen(buf, mode)) + return fp; + } + pp = PATH; + while (pp && *pp) { + bp = buf; + while (*pp && *pp != PATHSEP){ + if( bp > buf + BUFSIZ - 1 ) return( NULL ); + lastch = *bp++ = *pp++; + } + if (lastch != ':' && lastch != '/' && bp != buf) + *bp++ = '/'; + if (bp + strlen(name) > buf + BUFSIZ - 1) return( NULL ); + strcpy(bp, name); + if (theLock = Lock(buf, SHARED_LOCK)) { + UnLock(theLock); + if (fp = fopen(buf, mode)) return fp; + } + if (*pp) + pp++; + } + return NULL; +} +#endif /* MFLOPPY */ + +#ifdef CHDIR + +/* + * A not general-purpose directory changing routine. + * Assumes you want to return to the original directory eventually, + * by chdir()ing to orgdir (which is defined in pcmain.c). + * Assumes -1 is not a valid lock, since 0 is valid. + */ + +#define NO_LOCK ((BPTR) -1) + +static BPTR OrgDirLock = NO_LOCK; + +chdir(dir) +char *dir; +{ + extern char orgdir[]; + + if (dir == orgdir) { + /* We want to go back to where we came from. */ + if (OrgDirLock != NO_LOCK) { + UnLock(CurrentDir(OrgDirLock)); + OrgDirLock = NO_LOCK; + } + } else { + /* + * Go to some new place. If still at the original + * directory, save the FileLock. + */ + BPTR newDir; + + if (newDir = Lock( (char *)dir, SHARED_LOCK)) { + if (OrgDirLock == NO_LOCK) { + OrgDirLock = CurrentDir(newDir); + } else { + UnLock(CurrentDir(newDir)); + } + } else { + return -1; /* Failed */ + } + } + /* CurrentDir always succeeds if you have a lock */ + return 0; +} + +#endif /* CHDIR */ + +/* Chdir back to original directory + */ +#undef exit +void +nethack_exit(code) +{ +#ifdef CHDIR + extern char orgdir[]; +#endif + +#ifdef CHDIR + chdir(orgdir); /* chdir, not chdirx */ +#endif + +#ifdef AMII_GRAPHICS + if(windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows) + CleanUp(); +#endif + exit(code); +} + +void +regularize(s) /* normalize file name - we don't like :'s or /'s */ +register char *s; +{ + register char *lp; + + while((lp = index(s, ':')) || (lp = index(s, '/'))) + *lp = '_'; +} diff --git a/sys/amiga/amidos.p b/sys/amiga/amidos.p new file mode 100644 index 0000000..86c355d --- /dev/null +++ b/sys/amiga/amidos.p @@ -0,0 +1,42 @@ +/* SCCS Id: @(#)amidos.p 3.1 93/01/08 +/* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1992, 1993. */ +/* NetHack may be freely redistributed. See license for details. */ + +/* amidos.c */ +void NDECL(flushout ); +#ifndef getuid +int NDECL(getuid ); +#endif +#ifndef getpid +int NDECL(getpid ); +#endif +#ifndef getlogin +char *NDECL(getlogin ); +#endif +#ifndef abs +int FDECL(abs, (int )); +#endif +int NDECL(tgetch ); +int NDECL(dosh ); +long FDECL(freediskspace, (char *)); +long FDECL(filesize, (char *)); +void FDECL(eraseall, (const char * , const char *)); +char *FDECL(CopyFile, (const char * , const char *)); +void FDECL(copybones, (int )); +void NDECL(playwoRAMdisk ); +int FDECL(saveDiskPrompt, (int )); +void NDECL(gameDiskPrompt ); +void FDECL(append_slash, (char *)); +void FDECL(getreturn, (const char *)); +#ifndef msmsg +void FDECL(msmsg, ( const char *, ... )); +#endif +#if !defined(__SASC_60) && !defined(_DCC) +int FDECL(chdir, (char *)); +#endif +#ifndef strcmpi +int FDECL(strcmpi, (char * , char *)); +#endif +#if !defined(memcmp) && !defined(AZTEC_C) && !defined(_DCC) +int FDECL(memcmp, (unsigned char * , unsigned char * , int )); +#endif diff --git a/sys/amiga/amifont.uu b/sys/amiga/amifont.uu new file mode 100644 index 0000000..3290ddc --- /dev/null +++ b/sys/amiga/amifont.uu @@ -0,0 +1,9 @@ +begin 777 hack.font +M#P```6AA8VLO.``````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +G````````````````````````````````````````````````"`!` +` +end diff --git a/sys/amiga/amifont8.uu b/sys/amiga/amifont8.uu new file mode 100644 index 0000000..c6120e1 --- /dev/null +++ b/sys/amiga/amifont8.uu @@ -0,0 +1,59 @@ +begin 644 8 +M```#\P`````````!``````````````)E```#Z0```F5P_TYU```````````, +M`````!H/@``!``````````````````````````````````````````!&140` +M```````````,`````!H`````"20`"`!```@`!@`!```@_P```&X`M```!@X` +M```````````8;&P8`#@8##````````,\&#P\''X?G +MYVH```!J:A@````8&!@``!@88L!6`%96```8`!@8`*@5P8.BP:@5YP/_[W_^ +M````P,```P`\;&P^QFP8&!AF&`````9F.&9F/&`P9F9F&!@8`!AFQCQF9FQF +M9F9F&`9F8,;F;&9L9F9:9L/&9L/&,&`,.``8`&``!@`V`&```&`8```````` +M`!@````````8&!B<,Z6BH:&EI*2AI:6EI*2AI*3__\,8`&:DH:6EI:2DH:2D +MI58```!65CP````8&!@``!@\96-J`&IJ```8`!@8UB/$`\`C+"O4A`/_]Y_Y +M````P,```P`\`/Y@S&@P,`P\&`````QN&`8&;'Q@!F9F&!@P?@P&WCQFP&9@ +M8,!F&`9L8.[VQF;&9G`89F;&/&:,,#`,;``,/&P\-CPP.VPX!F889GP\W#WL +M/CYF9F-C9GX8&!@`S.7BY^?GY^?AY^?GY^3GY^?_`.<8`,/GX>?GY^?DY^?G +MY6K_#_!KZCP````8&!@``!AF8#97_];7`&8<`#@\;&I6)F1I/&F6YP./]]_[ +M#__PP,```P`8`&P\&'8`,`S_?@!^`!A^&!P,Y^&`9X8/[>QGS&?#@89F;6&#P8,!@,Q@``!G9F;F9X9G88!FP8=V9F9F9V +M8!AF9FLV9DQP&`X`,Z6BI*&AH:6AI:&EI:2EI*3_`.<8_P`E(24A)24D)20D +MI595/5Q55F;_#_`/\/\``-O#?AMJ5:JJ```?__C_JIPY:];X*]I;A`-F[\_S +M.``,/\//C^ +M\#YF?CSF_L;&./`\XSP\/AC&PSS^/`,\````.SP\.SQXQN8\9N8\8V8\8`;P +M?`P[ C&'X.&'``S`````````````````````#__\,8`&8````````````` +M`&H`:VH``,,`&!@``!B<&#P89F-6:E8``&88&!@`K`/`(\0L(T&"``/_W_F? +MP``#P````````````````````#```````````````````#`````````````` +M```````````````&`````````````````/X`````````?```/```````\`<` +M````````<```````,P````````````````````#__\,8`&8````````````` +M`%8`5E8`````&!@``!@``!@8`,!J5FH````8&!@``,&#J!7!HL&#``/_[_Y_ +MP``#P`````````@`"``(`!``"``8``@`(``(`"@`"``P``@`.``(`$``"`!( +M``@`4``(`%@`"`!@``@`:``(`'``"`!X``@`@``(`(@`"`"0``@`F``(`*`` +M"`"H``@`L``(`+@`"`#```@`R``(`-``"`#8``@`X``(`.@`"`#P``@`^``( +M`0``"`$(``@!$``(`1@`"`$@``@!*``(`3``"`$X``@!0``(`4@`"`%0``@! +M6``(`6``"`%H``@!<``(`7@`"`&```@!B``(`9``"`&8``@!H``(`:@`"`&P +M``@!N``(`<``"`'(``@!T``(`=@`"`'@``@!Z``(`?``"`'X``@"```(`@@` +M"`(0``@"&``(`B``"`(H``@",``(`C@`"`)```@"2``(`E``"`)8``@"8``( +M`F@`"`)P``@">``(`H``"`*(``@"D``(`I@`"`*@``@"J``(`K``"`*X``@" +MP``(`L@`"`+0``@"V``(`N``"`+H``@"\``(`O@`"`,```@#"``(`Q``"`,8 +M``@#(``(`R@`"`,P``@#.``(`T``"`-(``@#4``(`U@`"`-@``@#:``(`W`` +M"`-X``@#@``(`X@`"`.0``@#F``(`Z``"`.H``@#L``(`[@`"`/```@#R``( +M`]``"`/8``@#X``(`^@`"`/P``@#^``(!```"``(``@`$``(`!@`"``@``@` +M*``(`#``"``X``@`0``(`$@`"`!0``@`6``(`&``"`!H``@`<``(`'@`"`"` +M``@`B``(`)``"`"8``@`H``(`*@`"`"P``@`N``(`,``"`#(``@`T``(`-@` +M"`#@``@`Z``(`/``"`#X``@$"``(!!``"`08``@$(``(!"@`"`0P``@#J``( +M!#@`"`.8``@$0``(!$@`"`10``@$6``(!&``"`1H``@$<``(!'@`"`2```@$ +MB``(!)``"`28``@$H``(!*@`"`2P``@$N``(!,``"`3(``@!V``(`>``"`'H +M``@!\``(`?@`"`(```@$T``(!-@`"`3@``@$Z``(!/``"`3X``@%```(!0@` +M"`40``@%&``(!2``"`4H``@%,``(!3@`"`5```@%2``(!5``"`58``@%8``( +M!6@`"`5P``@%>``(!8``"`6(``@%D``(!9@`"`+8``@"X``(`N@`"`+P``@" +M^``(````"``````#[`````0`````````#@```$0```!<````8@````````/R +` +end diff --git a/sys/amiga/amigst.c b/sys/amiga/amigst.c new file mode 100644 index 0000000..04859c4 --- /dev/null +++ b/sys/amiga/amigst.c @@ -0,0 +1,43 @@ +/* SCCS Id: @(#)amigst.c 3.1 93/01/08 +/* Copyright (c) Gregg Wonderly, Naperville, IL, 1992, 1993 */ +/* NetHack may be freely redistributed. See license for details. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef strcmpi +#include +#include + +#ifdef __SASC +#include /* for __emit */ +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "hack.h" +#include "winprocs.h" +#include "winami.h" + +#ifdef AZTEC +#include +#endif + +#include "NH:sys/amiga/winami.p" +#include "NH:sys/amiga/amiwind.p" +#include "NH:sys/amiga/amidos.p" + +/* end amigst.c */ diff --git a/sys/amiga/amii.hlp b/sys/amiga/amii.hlp new file mode 100644 index 0000000..c014e42 --- /dev/null +++ b/sys/amiga/amii.hlp @@ -0,0 +1,31 @@ + Amiga-specific help file for NetHack 3.4 + +The Amiga port of NetHack supports a number of additional commands +and facilities specific to the Amiga. Listed below are the things +which are either specific to the Amiga port or might not appear +in other ports. + +While playing NetHack you can press: + + ALT-HELP Color requestor. + CTL-HELP Scale display (amitile only). + SHIFT-HELP Overview window (amitile only). + +Amiga-specific run-time options: + altmeta use the alt keys as meta keys + flush throw away keyboard type-ahead + +Command line options recognized are + + -n No News at game startup. + -X Play in discovery mode. + -D Play in debug mode. + -L Interlaced screen. + -l Never Interlaced screen. + -u Play as player given as + an argument. + -r Pick a race given as an + argument. + -p Pick a profession given + as an argument + -? Gives command line usage. diff --git a/sys/amiga/amimenu.c b/sys/amiga/amimenu.c new file mode 100644 index 0000000..422dfba --- /dev/null +++ b/sys/amiga/amimenu.c @@ -0,0 +1,95 @@ +/* SCCS Id: @(#)amimenu.c 3.2 96/02/04 */ +/* Copyright (c) Olaf 'Rhialto' Seibert, 1989 */ +/* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1992, 1993, 1996 */ +/* Copyright (c) Janne Salmijärvi, 2000 */ +/* NetHack may be freely redistributed. See license for details. */ + +/* Originally by John Toebes. */ + +/* GadTools menus by jhsa */ + +struct NewMenu GTHackMenu[] = { + { NM_TITLE, "Commands", 0, 0, 0, 0}, + { NM_ITEM, "? Display help menu", 0, 0, 0, (void *)'?'}, + { NM_ITEM, "& Explain a command", 0, 0, 0, (void *)'&'}, + { NM_ITEM, "O Set options", 0, 0, 0, (void *)'O'}, + { NM_ITEM, "! AmigaDos command", 0, 0, 0, (void *)'!'}, + { NM_ITEM, "v Version number", 0, 0, 0, (void *)'v'}, + { NM_ITEM, "V Long version and game history", 0, 0, 0, (void *)'V'}, + { NM_ITEM, "^R Redraw screen", 0, 0, 0, (void *)022}, + { NM_ITEM, "^P Repeat previous messages", 0, 0, 0, (void *)020}, + { NM_ITEM, "M-q #quit the game", 0, 0, 0, (void *)(128+'q')}, + { NM_ITEM, "S Save the game", 0, 0, 0, (void *)'S'}, + { NM_TITLE, "Inventory", 0, 0, 0, 0}, + { NM_ITEM, "i Inventory", 0, 0, 0, (void *)'i'}, + { NM_ITEM, "p Pay your bill", 0, 0, 0, (void *)'p'}, + { NM_ITEM, "d Drop an object", 0, 0, 0, (void *)'d'}, + { NM_ITEM, "D Drop several things", 0, 0, 0, (void *)'D'}, + { NM_ITEM, ", Pickup an object", 0, 0, 0, (void *)','}, + { NM_ITEM, "@ Toggle pickup", 0, 0, 0, (void *)'@'}, + { NM_ITEM, "/ Identify something", 0, 0, 0, (void *)'/'}, + { NM_ITEM, "C Christen a monster", 0, 0, 0, (void *)'C'}, + { NM_ITEM, "+ List known spells", 0, 0, 0, (void *)'+'}, + { NM_ITEM, "$ Your gold", 0, 0, 0, (void *)'$'}, + { NM_TITLE, "Actions", 0, 0, 0, 0}, + { NM_ITEM, "a Apply/use something", 0, 0, 0, (void *)'a'}, + { NM_ITEM, "e Eat something", 0, 0, 0, (void *)'e'}, + { NM_ITEM, "f Fire ammunition", 0, 0, 0, (void *)'f'}, + { NM_ITEM, "F Fight a monster", 0, 0, 0, (void *)'F'}, + { NM_ITEM, "q Quaff a monster", 0, 0, 0, (void *)'q'}, + { NM_ITEM, "r Read scroll/book", 0, 0, 0, (void *)'r'}, + { NM_ITEM, "t Throw something", 0, 0, 0, (void *)'t'}, + { NM_ITEM, "z Zap a wand", 0, 0, 0, (void *)'z'}, + { NM_ITEM, "Z Cast a spell", 0, 0, 0, (void *)'Z'}, + { NM_TITLE, "Preparations", 0, 0, 0, 0}, + { NM_ITEM, "A Remove all armor", 0, 0, 0, (void *)'A'}, + { NM_ITEM, "P Put on a ring", 0, 0, 0, (void *)'P'}, + { NM_ITEM, "R Remove ring", 0, 0, 0, (void *)'R'}, + { NM_ITEM, "Q Select ammunition for quiver", 0, 0, 0, (void *)'Q'}, + { NM_ITEM, "T Take off armor", 0, 0, 0, (void *)'T'}, + { NM_ITEM, "w Wield a weapon", 0, 0, 0, (void *)'w'}, + { NM_ITEM, "W Wear armor", 0, 0, 0, (void *)'W'}, + { NM_ITEM, "x Swap wielded and secondary weapons", 0, 0, 0, (void *)'x'}, + { NM_ITEM, ") Current weapon", 0, 0, 0, (void *)')'}, + { NM_ITEM, "[ Current armor", 0, 0, 0, (void *)'['}, + { NM_ITEM, "= Current rings", 0, 0, 0, (void *)'='}, + { NM_ITEM,"\" Current amulet", 0, 0, 0, (void *)'"'}, + { NM_ITEM, "( Current tools", 0, 0, 0, (void *)'('}, + { NM_ITEM, "* Current equipment", 0, 0, 0, (void *)'*'}, + { NM_TITLE, "Movement", 0, 0, 0, 0}, + { NM_ITEM, "o Open door", 0, 0, 0, (void *)'o'}, + { NM_ITEM, "c Close door", 0, 0, 0, (void *)'c'}, + { NM_ITEM, "^D Kick door", 0, 0, 0, (void *)004}, + { NM_ITEM, "s Search", 0, 0, 0, (void *)'s'}, + { NM_ITEM, "< Go up stairs", 0, 0, 0, (void *)'<'}, + { NM_ITEM, "> Go down stairs", 0, 0, 0, (void *)'>'}, + { NM_ITEM, "^T Teleport", 0, 0, 0, (void *)024}, + { NM_ITEM, ". Wait a moment", 0, 0, 0, (void *)'.'}, + { NM_ITEM, "E Engrave message on floor", 0, 0, 0, (void *)'E'}, + { NM_TITLE, "Extended", 0, 0, 0, 0}, + { NM_ITEM, "M-a #adjust inventory letters", 0, 0, 0, (void *)(128+'a')}, + { NM_ITEM, "M-c #chat with someone", 0, 0, 0, (void *)(128+'c')}, + { NM_ITEM, "M-d #dip an object into something", 0, 0, 0, (void *)(128+'d')}, +#ifdef WEAPON_SKILLS + { NM_ITEM, "M-e #enhance weapon skills", 0, 0, 0, (void *)(128+'e')}, +#endif + { NM_ITEM, "M-f #force a lock", 0, 0, 0, (void *)(128+'f')}, + { NM_ITEM, "M-i #invoke an object's special powers", 0, 0, 0, (void *)(128+'i')}, + { NM_ITEM, "M-j #jump to another location", 0, 0, 0, (void *)(128+'j')}, + { NM_ITEM, "M-l #loot a box on the floor", 0, 0, 0, (void *)(128+'l')}, + { NM_ITEM, "M-m Use a #monster's special ability", 0, 0, 0, (void *)(128+'m')}, + { NM_ITEM, "M-n #name an item or type of object", 0, 0, 0, (void *)(128+'n')}, + { NM_ITEM, "M-o #offer a sacrifice to the gods", 0, 0, 0, (void *)(128+'o')}, + { NM_ITEM, "M-p #pray to the gods for help", 0, 0, 0, (void *)(128+'p')}, + { NM_ITEM, "M-q #quit the game", 0, 0, 0, (void *)(128+'q')}, + { NM_ITEM, "M-r #rub a lamp", 0, 0, 0, (void *)(128+'r')}, + { NM_ITEM, "M-s #sit down", 0, 0, 0, (void *)(128+'s')}, + { NM_ITEM, "M-t #turn undead", 0, 0, 0, (void *)(128+'t')}, + { NM_ITEM, "M-u #untrap something", 0, 0, 0, (void *)(128+'u')}, + { NM_ITEM, "M-v Long #version information", 0, 0, 0, (void *)(128+'v')}, + { NM_ITEM, "M-w #wipe off your face", 0, 0, 0, (void *)(128+'w')}, + { NM_ITEM, " Your #conduct", 0, 0, 0, (void *)'#'}, /* "#co\n" */ + { NM_ITEM, " #ride your steed", 0, 0, 0, (void *)'#'}, /* "#ri\n" */ + { NM_ITEM, "M-2 Switch #twoweapon mode on/off", 0, 0, 0, (void *)(128+'2')}, + { NM_END, NULL, 0, 0, 0, 0} +}; diff --git a/sys/amiga/amirip.c b/sys/amiga/amirip.c new file mode 100644 index 0000000..c41110a --- /dev/null +++ b/sys/amiga/amirip.c @@ -0,0 +1,405 @@ +/* SCCS Id: @(#)amirip.c 3.2 96/02/04 */ +/* Copyright (c) Kenneth Lorber, Bethesda, Maryland 1991,1992,1993,1995,1996. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "hack.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "winami.h" +#include "windefs.h" +#include "winext.h" +#include "winproto.h" + +static struct RastPort *rp; + +#ifdef AMII_GRAPHICS + +#undef NULL +#define NULL 0 + +#ifdef AZTEC_C +# include +#else +# ifdef _DCC +# include +# include +# include +# include +# else +# include +# include +# include +# include +# endif + +static char *load_list[]={"tomb.iff",0}; +static BitMapHeader tomb_bmhd; +static struct BitMap *tbmp[ 1 ] = {0}; + +static int cols[2]={154,319}; /* X location of center of columns */ +static int cno = 0; /* current column */ +#define TEXT_TOP (65+yoff) + +static xoff, yoff; /* image centering */ + +/* terrible kludge */ +/* this is why prototypes should have ONLY types in them! */ +# undef red +# undef green +# undef blue +# undef index +# ifdef _DCC +# include +# include +# else +# include +# include +# endif +#endif /* AZTEC_C */ + +extern char *killed_by_prefix[]; +static struct Window *ripwin=0; +static void tomb_text(char*); +static void dofade(int,int,int); +static int search_cmap(int,int,int); + +#define STONE_LINE_LEN 13 /* # chars that fit on one line + * (note 1 ' ' border) */ + +#define DEATH_LINE 10 +#define YEAR_LINE 15 + +static unsigned short tomb_line; + +extern struct amii_DisplayDesc *amiIDisplay; +extern struct Screen *HackScreen; +extern int havelace; + +static unsigned short transpalette[ AMII_MAXCOLORS ] = { 0x0000, }; + +static struct NewWindow newwin = +{ + 0,0,640,200,1,0, + MOUSEBUTTONS|VANILLAKEY|NOCAREREFRESH, + BORDERLESS|ACTIVATE|SMART_REFRESH, + NULL,NULL,(UBYTE*)NULL,NULL,NULL,-1,-1,0xffff,0xffff,CUSTOMSCREEN +}; + +int wh; /* was local in outrip, but needed for SCALE macro */ + +int cmap_white, cmap_black; + +void +amii_outrip( tmpwin, how ) +winid tmpwin; +int how; +{ + int just_return = 0; + int done, rtxth; + struct IntuiMessage *imsg; + int i; + register char *dpx; + char buf[ 200 ]; + int line, tw, ww; + char *errstr = NULL; + + if(!WINVERS_AMIV || HackScreen->RastPort.BitMap->Depth < 4)goto cleanup; + + /* Use the users display size */ + newwin.Height = amiIDisplay->ypix - newwin.TopEdge; + newwin.Width = amiIDisplay->xpix; + newwin.Screen = HackScreen; + + for( i = 0; i < amii_numcolors; ++i ) + flags.amii_curmap[i] = GetRGB4( HackScreen->ViewPort.ColorMap, i ); + + ripwin = OpenWindow( (void *)&newwin ); + if( !ripwin ) goto cleanup; + + LoadRGB4( &HackScreen->ViewPort, transpalette, amii_numcolors ); + + rp= ripwin->RPort; + wh = ripwin->Height; + ww = ripwin->Width; + +#ifdef HACKFONT + if (HackFont) + SetFont(rp, HackFont); +#endif + + tomb_bmhd = ReadImageFiles(load_list, tbmp, &errstr ); + if(errstr)goto cleanup; + if(tomb_bmhd.w > ww || tomb_bmhd.h > wh)goto cleanup; + +#define GENOFF(full,used) ((((full)-(used))/2) & ~7) + xoff = GENOFF(ww,tomb_bmhd.w); + yoff = GENOFF(wh,tomb_bmhd.h); + for(i=0;iBitMap, xoff, yoff, tomb_bmhd.w, tomb_bmhd.h, 0xc0, 0xff, NULL); + + /* Put together death description */ + switch (killer_format) { + default: + impossible("bad killer format?"); + case KILLED_BY_AN: + Strcpy(buf, killed_by_prefix[how]); + Strcat(buf, an(killer)); + break; + case KILLED_BY: + Strcpy(buf, killed_by_prefix[how]); + Strcat(buf, killer); + break; + case NO_KILLER_PREFIX: + Strcpy(buf, killer); + break; + } + + tw = TextLength(rp,buf,STONE_LINE_LEN) + 40; + + { + char *p=buf; + int x, tmp; + for(x=STONE_LINE_LEN;x;x--)*p++='W'; + *p='\0'; + tmp = TextLength(rp,buf,STONE_LINE_LEN) + 40; + tw = max( tw, tmp); + } + + /* There are 5 lines of text on the stone. */ + rtxth = ripwin->RPort->TxHeight * 5; + + SetAfPt( rp, (UWORD *)NULL, 0 ); + SetDrPt( rp, 0xFFFF ); + + tomb_line=TEXT_TOP; + + SetDrMd(rp,JAM1); + + /* Put name on stone */ + Sprintf(buf, "%s", plname); + buf[STONE_LINE_LEN] = 0; + tomb_text(buf); + + /* Put $ on stone */ + Sprintf(buf, "%ld Au", +#ifndef GOLDOBJ + u.ugold); +#else + done_money); +#endif + buf[STONE_LINE_LEN] = 0; /* It could be a *lot* of gold :-) */ + tomb_text(buf); + + /* Put together death description */ + switch (killer_format) { + default: + impossible("bad killer format?"); + case KILLED_BY_AN: + Strcpy(buf, killed_by_prefix[how]); + Strcat(buf, an(killer)); + break; + case KILLED_BY: + Strcpy(buf, killed_by_prefix[how]); + Strcat(buf, killer); + break; + case NO_KILLER_PREFIX: + Strcpy(buf, killer); + break; + } + + /* Put death type on stone */ + for (line=DEATH_LINE, dpx = buf; line STONE_LINE_LEN) + { + for(i=STONE_LINE_LEN;((i0 > STONE_LINE_LEN) && i); i--) + { + if(dpx[i] == ' ') + i0 = i; + } + if(!i) + i0 = STONE_LINE_LEN; + } + + tmpchar = dpx[i0]; + dpx[i0] = 0; + tomb_text(dpx); + + if (tmpchar != ' ') + { + dpx[i0] = tmpchar; + dpx= &dpx[i0]; + } + else + { + dpx= &dpx[i0+1]; + } + } + + /* Put year on stone */ + Sprintf(buf, "%4d", getyear()); + tomb_text(buf); + +#ifdef NH320_DEDICATION + /* dedication */ + cno = 1; + tomb_line=TEXT_TOP; + tomb_text("This release"); + tomb_text("of NetHack"); + tomb_text("is dedicated"); + tomb_text("to the"); + tomb_text("memory of"); + tomb_text(""); + tomb_text("Izchak"); + tomb_text(" Miller"); + tomb_text(""); + tomb_text("1935-1994"); + tomb_text(""); + tomb_text("Ascended"); +#endif + /* Fade from black to full color */ + dofade(0,16,1); + + /* Flush all messages to avoid typeahead */ + while( imsg = (struct IntuiMessage *)GetMsg( ripwin->UserPort ) ) + ReplyMsg( (struct Message *) imsg ); + done = 0; + while( !done ) + { + WaitPort( ripwin->UserPort ); + while( imsg = (struct IntuiMessage *)GetMsg(ripwin->UserPort) ) + { + switch( imsg->Class ) + { + case MOUSEBUTTONS: + case VANILLAKEY: + done = 1; + break; + } + ReplyMsg( (struct Message *)imsg ); + } + } + + /* Fade out */ + dofade(16,0,-1); + just_return = 1; + +cleanup: + /* free everything */ + if(ripwin){ + Forbid(); + while( imsg = (struct IntuiMessage *)GetMsg( ripwin->UserPort ) ) + ReplyMsg( (struct Message *)imsg ); + CloseWindow( ripwin ); + Permit(); + } + LoadRGB4( &HackScreen->ViewPort, flags.amii_curmap, amii_numcolors ); + + if(tbmp[0])FreeImageFiles(load_list, tbmp); + if(just_return) return; + /* fall back to the straight-ASCII version */ + genl_outrip(tmpwin, how); +} + +static void tomb_text(p) +char *p; +{ + char buf[STONE_LINE_LEN*2]; + int l; + + tomb_line += rp->TxHeight; + + if( !*p ) + return; + sprintf(buf," %s ",p); + l=TextLength(rp,buf,strlen(buf)); + + SetAPen(rp,cmap_white); + Move(rp,cols[cno]-(l/2)-1, tomb_line); + Text(rp,buf,strlen(buf)); + + SetAPen(rp,cmap_white); + Move(rp,cols[cno]-(l/2)+1, tomb_line); + Text(rp,buf,strlen(buf)); + + SetAPen(rp,cmap_white); + Move(rp,cols[cno]-(l/2), tomb_line-1); + Text(rp,buf,strlen(buf)); + + SetAPen(rp,cmap_white); + Move(rp,cols[cno]-(l/2), tomb_line+1); + Text(rp,buf,strlen(buf)); + + SetAPen(rp,cmap_black); + Move(rp,cols[cno]-(l/2), tomb_line); + Text(rp,buf,strlen(buf)); +} + +/* search colormap for best match to given color */ +static int +search_cmap(int r0, int g0, int b0){ + int best = 0; + int bdiff = 0x0fffffff; + int x; + for(x=0;x> 8) & 15); + int g = g0-((amiv_init_map[x] >> 4) & 15); + int b = b0-((amiv_init_map[x] ) & 15); + int diff = (r*r) + (g*g) + (b*b); + if(diff> 8; + g = ( amiv_init_map[ j ] & 0xf0 ) >> 4; + b = ( amiv_init_map[ j ] & 0xf ); + r = ( r * i ) / 16; + g = ( g * i ) / 16; + b = ( b * i ) / 16; + transpalette[ j ] = ((r<<8)|(g<<4)|b); + } + LoadRGB4( &HackScreen->ViewPort, transpalette, amii_numcolors ); + Delay( 1 ); + } +} + + + +#endif /* AMII_GRAPHICS */ + +/* +TODO: + memory leaks + fix ReadImageFiles to return error instead of panic on error +*/ diff --git a/sys/amiga/amisnd.c b/sys/amiga/amisnd.c new file mode 100644 index 0000000..85a007d --- /dev/null +++ b/sys/amiga/amisnd.c @@ -0,0 +1,284 @@ +/* SCCS Id: @(#)amisnd.c 3.2 2000/01/12*/ +/* Copyright (c) 1992, 1993, 1995 by Gregg Wonderly */ +/* NetHack may be freely redistributed. See license for details. */ + +/* + * This file contains music playing code. + * + * If we were REALLY determined, we would make the sound play + * asynchronously, but I'll save that one for a rainy day... + */ + +#include "hack.h" +#include "dlb.h" + +#undef red +#undef blue +#undef green +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define AMII_AVERAGE_VOLUME 60 + +int amii_volume = AMII_AVERAGE_VOLUME; + +typedef struct VHDR +{ + char name[4]; + long len; + unsigned long oneshot, repeat, samples; + UWORD freq; + UBYTE n_octaves, compress; + LONG volume; +} VHDR; + +typedef struct IFFHEAD +{ + char FORM[4]; + long flen; + char _8SVX[4]; + VHDR vhdr; + char NAME[4]; + long namelen; +} IFFHEAD; + +extern struct GfxBase *GfxBase; + +UBYTE whichannel[] = { 1, 2, 4, 8 }; +void makesound( char *, char *, int vol); +void amii_speaker( struct obj *instr, char *melody, int vol ); + +/* A major scale in indexs to freqtab... */ +int notetab[] = { 0, 2, 4, 5, 7, 9, 11, 12 }; + +/* Frequencies for a scale starting at one octave below 'middle C' */ +long freqtab[] = { + 220, /*A */ + 233, /*Bb*/ + 246, /*B */ + 261, /*C */ + 277, /*Db*/ + 293, /*D */ + 311, /*Eb*/ + 329, /*E */ + 349, /*F */ + 370, /*Gb*/ + 392, /*G */ + 415, /*Ab*/ + 440, /*A */ +}; + +#ifdef TESTING +main( argc, argv ) + int argc; + char **argv; +{ + makesound( "wooden_flute", "AwBwCwDwEwFwGwawbwcwdwewfwgw", 60 ); + makesound( "wooden_flute", "AhBhChDhEhFhGhahbhchdhehfhgh", 60 ); + makesound( "wooden_flute", "AqBqCqDqEqFqGqaqbqcqdqeqfqgq", 60 ); + makesound( "wooden_flute", "AeBeCeDeEeFeGeaebecedeeefege", 60 ); + makesound( "wooden_flute", "AxBxCxDxExFxGxaxbxcxdxexfxgx", 60 ); + makesound( "wooden_flute", "AtBtCtDtEtFtGtatbtctdtetftgt", 60 ); + makesound( "wooden_flute", "AtBtCtDtEtFtGtatbtctdtetftgt", 60 ); + makesound( "wooden_flute", "AtBtCtDtEtFtGtatbtctdtetftgt", 60 ); + makesound( "wooden_flute", "AtBtCtDtEtFtGtatbtctdtetftgt", 60 ); + makesound( "wooden_flute", "AtBtCtDtEtFtGtatbtctdtetftgt", 60 ); + makesound( "wooden_flute", "AtBtCtDtEtFtGtatbtctdtetftgt", 60 ); + makesound( "wooden_flute", "AtBtCtDtEtFtGtatbtctdtetftgt", 60 ); + makesound( "wooden_flute", "AtBtCtDtEtFtGtatbtctdtetftgt", 60 ); + makesound( "wooden_flute", "AtBtCtDtEtFtGtatbtctdtetftgt", 60 ); +} +#else +void +amii_speaker( struct obj *instr, char *melody, int vol ) +{ + int typ = instr->otyp; + char * actualn = (char *)OBJ_NAME( objects[typ] ) ; + + /* Make volume be relative to users volume level, with 60 being the + * average level that will be passed to us. + */ + vol = vol * amii_volume / AMII_AVERAGE_VOLUME; + + makesound( actualn, melody, vol ); +} +#endif + +void +makesound ( char *actualn , char * melody, int vol ) +{ + char *t; + int c, cycles, dot, dlay; + dlb *stream = 0; + IFFHEAD iffhead; + struct IOAudio *AudioIO = 0; + struct MsgPort *AudioMP = 0; + struct Message *AudioMSG = 0; + ULONG device = -1; + BYTE *waveptr = 0; + LONG frequency=440, duration=1, clock, samp, samples, samcyc=1; + unsigned char name [ 100 ] ; + + if ( flags.silent ) + return; + + if( GfxBase->DisplayFlags & PAL ) + clock = 3546895; + else + clock = 3579545; + + /* + * Convert type to file name - if there's nothing to play we + * shouldn't be here in the first place. + */ + strncpy(name, actualn,sizeof(name) ) ; + for( t = strchr( name, ' ' ); t; t = strchr( name, ' ' ) ) + *t = '_'; + if( (stream = dlb_fopen( name, "r" )) == NULL ) + { + perror( name ); + return; + } + + AudioIO = (struct IOAudio *) + AllocMem( sizeof( struct IOAudio ), MEMF_PUBLIC|MEMF_CLEAR ); + if( AudioIO == 0 ) + goto killaudio; + + AudioMP = CreateMsgPort(); + if( AudioMP == 0 ) + goto killaudio; + + AudioIO->ioa_Request.io_Message.mn_ReplyPort = AudioMP; + AudioIO->ioa_Request.io_Message.mn_Node.ln_Pri = 0; + AudioIO->ioa_Request.io_Command = ADCMD_ALLOCATE; + AudioIO->ioa_Request.io_Flags = ADIOF_NOWAIT; + AudioIO->ioa_AllocKey = 0; + AudioIO->ioa_Data = whichannel; + AudioIO->ioa_Length = sizeof( whichannel ); + + device = OpenDevice( AUDIONAME, 0L, (struct IORequest *)AudioIO, 0L ); + if( device != 0 ) + goto killaudio; + + if( dlb_fread( (genericptr_t)&iffhead, sizeof( iffhead ), 1, stream ) != 1 ) + goto killaudio; + + /* This is an even number of bytes long */ + if( dlb_fread( name, (iffhead.namelen+1) & ~1, 1, stream ) != 1 ) + goto killaudio; + + if( dlb_fread( (genericptr_t)&samples, 4, 1, stream ) != 1 ) + goto killaudio; + + if( dlb_fread( (genericptr_t)&samples, 4, 1, stream ) != 1 ) + goto killaudio; + + waveptr = AllocMem( samples, MEMF_CHIP|MEMF_PUBLIC ); + if( !waveptr ) + goto killaudio; + + if( dlb_fread( waveptr, samples, 1, stream ) != 1 ) + goto killaudio; + + while( melody[0] && melody[1] ) + { + c = *melody++; + duration = *melody++; + dot = 0; + if( *melody == '.' ) + { + dot = 1; + ++melody; + } + switch( duration ) + { + case 'w': dlay = 3; duration = 1; cycles = 1; break; + case 'h': dlay = 3; duration = 2; cycles = 1; break; + case 'q': dlay = 2; duration = 4; cycles = 1; break; + case 'e': dlay = 1; duration = 8; cycles = 1; break; + case 'x': dlay = 0; duration = 16; cycles = 1; break; + case 't': dlay = 0; duration = 32; cycles = 1; break; + default: goto killaudio; /* unrecognized duration */ + } + + /* Lower case characters are one octave above upper case */ + switch( c ) + { + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': case 'g': + c -= 'a' - 7; + break; + + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': case 'G': + c -= 'A'; + break; + + default: + continue; + } + + samcyc = samples; + + /* lowercase start at middle 'C', upper case are one octave below */ + frequency = c > 7 ? freqtab[notetab[c%7]]*2 : freqtab[notetab[c]]; + + /* We can't actually do a dotted whole note unless we add code for a real + * 8SVX sample which includes sustain sample information to tell us how + * to hold the note steady... So when duration == 1, ignore 'dot'... + */ + if( dot && duration > 1 ) + samp = ((samples / duration) * 3) / 2; + else + samp = samples / duration; + + /* Only use some of the samples based on frequency */ + samp = frequency * samp / 880; + + /* The 22khz samples are middle C samples, so adjust the play + * back frequency accordingly + */ + frequency = (frequency * (iffhead.vhdr.freq*2)/3) / 440L; + + AudioIO->ioa_Request.io_Message.mn_ReplyPort = AudioMP; + AudioIO->ioa_Request.io_Command = CMD_WRITE; + AudioIO->ioa_Request.io_Flags = ADIOF_PERVOL; + AudioIO->ioa_Data = (BYTE *)waveptr; + AudioIO->ioa_Length = samp; + + /* The clock rate represents the unity rate, so dividing by + * the frequency gives us a period ratio... + */ +/*printf( "clock: %ld, freq: %ld, div: %ld\n", clock, frequency, clock/frequency );*/ + AudioIO->ioa_Period = clock/frequency; + AudioIO->ioa_Volume = vol; + AudioIO->ioa_Cycles = cycles; + + BeginIO( (struct IORequest *)AudioIO ); + WaitPort( AudioMP ); + AudioMSG = GetMsg( AudioMP ); + if( dlay ) + Delay( dlay ); + } + + killaudio: + if( stream ) dlb_fclose( stream ); + if( waveptr ) FreeMem( waveptr, samples ); + if( device == 0 ) CloseDevice( (struct IORequest *)AudioIO ); + if( AudioMP ) DeleteMsgPort( AudioMP ); + if( AudioIO ) FreeMem( AudioIO, sizeof( *AudioIO ) ); +} diff --git a/sys/amiga/amistack.c b/sys/amiga/amistack.c new file mode 100644 index 0000000..7e0b6fc --- /dev/null +++ b/sys/amiga/amistack.c @@ -0,0 +1,21 @@ +/* SCCS Id: @(#)amistack.c 3.4 2000/05/03 */ +/* Copyright (c) Janne Salmijärvi, Tampere, Finland, 2000 */ +/* NetHack may be freely redistributed. See license for details. */ + +/* + * Increase stack size to allow deep recursions. + * + * Note: This is SAS/C specific, using other compiler probably + * requires another method for increasing stack. + * + */ + +#ifdef __SASC_60 +#include + +/* + * At the moment 90*1024 would suffice, but just to be on the safe side ... + */ + +long __stack = 128*1024; +#endif diff --git a/sys/amiga/amitty.c b/sys/amiga/amitty.c new file mode 100644 index 0000000..236d4b3 --- /dev/null +++ b/sys/amiga/amitty.c @@ -0,0 +1,67 @@ +/* SCCS Id: @(#)amitty.c 3.2 2000/01/12 +/* Copyright (c) Kenneth Lorber, Bethesda, Maryland 1993,1996 */ +/* NetHack may be freely redistributed. See license for details. */ + +/* TTY-specific code for the Amiga + * This is still experimental. + * Still to do: + * add real termcap handling - currently requires ANSI_DEFAULT + */ + +#include "hack.h" +#include "tcap.h" +#include +#include + +#ifdef _DCC +# define getch() getchar() +#endif +#ifdef __SASC_60 +# include +#endif + +void NDECL( tty_change_color ); +char *NDECL( tty_get_color_string ); + +#ifdef TTY_GRAPHICS + +int amibbs=0; /* BBS mode */ +char bbs_id[80]=""; /* BBS uid equivalent */ +long afh_in, afh_out; /* BBS mode Amiga filehandles */ + +void settty(const char *s){ + end_screen(); + if(s)raw_print(s); + iflags.cbreak=ON; /* this is too easy: probably wrong */ +#if 1 /* should be version>=36 */ +/* if(IsInteractive(afh_in)){ */ + SetMode(afh_in,0); /* con mode */ +/* } */ +#endif +} +void gettty(){ +#if 1 /* should be VERSION >=36 */ +/* if(IsInteractive(afh_in)){ */ + SetMode(afh_in,1); /* raw mode */ +/* } */ +#endif +} +void setftty(){ + iflags.cbreak=ON; /* ditto */ +} +char kill_char='X'-'@'; +char erase_char='\b'; +tgetch(){ + char x; + Read(afh_in,&x,1); + return (x=='\r')?'\n':x; +} +void get_scr_size(){ + CO=80; + LI=24; +} + +#endif + +void tty_change_color() {} +char *tty_get_color_string() { return( "" ); } diff --git a/sys/amiga/amiwind.c b/sys/amiga/amiwind.c new file mode 100644 index 0000000..fab7f72 --- /dev/null +++ b/sys/amiga/amiwind.c @@ -0,0 +1,953 @@ +/* SCCS Id: @(#)amiwind.c 3.2 2000/01/12 +/* Copyright (c) Olaf Seibert (KosmoSoft), 1989, 1992 */ +/* Copyright (c) Kenneth Lorber, Bethesda, Maryland 1993,1996 */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "NH:sys/amiga/windefs.h" +#include "NH:sys/amiga/winext.h" +#include "NH:sys/amiga/winproto.h" + +/* Have to undef CLOSE as display.h and intuition.h both use it */ +#undef CLOSE + +#ifdef AMII_GRAPHICS /* too early in the file? too late? */ + +#ifdef AMIFLUSH +static struct Message *FDECL(GetFMsg,(struct MsgPort *)); +#endif + +static int BufferGetchar(void); +static void ProcessMessage( register struct IntuiMessage *message ); + +#define BufferQueueChar(ch) (KbdBuffer[KbdBuffered++] = (ch)) + +#ifdef __GNUC__ /* Conflicting includefiles ... */ +struct Device *ConsoleDevice; +#else +struct Library *ConsoleDevice; +#endif + +#include "NH:sys/amiga/amimenu.c" + +/* Now our own variables */ + +struct IntuitionBase *IntuitionBase; +struct Screen *HackScreen; +struct Window *pr_WindowPtr; +struct MsgPort *HackPort; +struct IOStdReq ConsoleIO; +struct Menu *MenuStrip; +APTR *VisualInfo; +char Initialized = 0; +WEVENT lastevent; + +#ifdef HACKFONT +struct GfxBase *GfxBase; +struct Library *DiskfontBase; +#endif + +#define KBDBUFFER 10 +static unsigned char KbdBuffer[KBDBUFFER]; +unsigned char KbdBuffered; + +#ifdef HACKFONT + +struct TextFont *TextsFont = NULL; +struct TextFont *HackFont = NULL; +struct TextFont *RogueFont = NULL; + +UBYTE FontName[] = "NetHack:hack.font"; + /* # chars in "NetHack:": */ +#define SIZEOF_DISKNAME 8 + +#endif + +struct TextAttr Hack80 = { +#ifdef HACKFONT + &FontName[SIZEOF_DISKNAME], +#else + (UBYTE *) "topaz.font", +#endif + 8, FS_NORMAL, FPF_DISKFONT | FPF_DESIGNED + | FPF_ROMFONT +}; + +struct TextAttr TextsFont13 = { + (UBYTE *) "courier.font", + 13, FS_NORMAL, FPF_DISKFONT | FPF_DESIGNED +#ifndef HACKFONT + | FPF_ROMFONT +#endif +}; + +/* Avoid doing a ReplyMsg through a window that no longer exists. */ +static enum {NoAction, CloseOver} delayed_key_action = NoAction; + +/* + * Open a window that shares the HackPort IDCMP. Use CloseShWindow() + * to close. + */ + +struct Window *OpenShWindow(nw) +struct NewWindow *nw; +{ + register struct Window *win; + register ULONG idcmpflags; + + if (!HackPort) /* Sanity check */ + return (struct Window *) 0; + + idcmpflags = nw->IDCMPFlags; + nw->IDCMPFlags = 0; + if (!(win = OpenWindow((void *)nw))) + { + nw->IDCMPFlags = idcmpflags; + return (struct Window *) 0; + } + + nw->IDCMPFlags = idcmpflags; + win->UserPort = HackPort; + ModifyIDCMP(win, idcmpflags); + return win; +} + + +/* + * Close a window that shared the HackPort IDCMP port. + */ + +void FDECL(CloseShWindow, (struct Window *)); +void CloseShWindow(win) +struct Window *win; +{ + register struct IntuiMessage *msg; + + if( !HackPort ) + panic("HackPort NULL in CloseShWindow" ); + if (!win) + return; + + Forbid(); + /* Flush all messages for all windows to avoid typeahead and other + * similar problems... + */ + while( msg = (struct IntuiMessage *)GetMsg( win->UserPort ) ) + ReplyMsg( (struct Message *) msg ); + KbdBuffered = 0; + win->UserPort = (struct MsgPort *) 0; + ModifyIDCMP(win, 0L); + Permit(); + CloseWindow(win); +} + +static int BufferGetchar() +{ + register int c; + + if (KbdBuffered > 0) { + c = KbdBuffer[0]; + KbdBuffered--; + /* Move the remaining characters */ + if( KbdBuffered < sizeof( KbdBuffer ) ) + memcpy( KbdBuffer, KbdBuffer+1, KbdBuffered ); + return c; + } + + return NO_CHAR; +} + +/* + * This should remind you remotely of DeadKeyConvert, but we are cheating + * a bit. We want complete control over the numeric keypad, and no dead + * keys... (they are assumed to be on Alted keys). + * + * Also assumed is that the IntuiMessage is of type RAWKEY. For some + * reason, IECODE_UP_PREFIX events seem to be lost when they occur while + * our console window is inactive. This is particulary troublesome with + * qualifier keys... Is this because I never RawKeyConvert those events??? + */ + +int ConvertKey(message) +register struct IntuiMessage *message; +{ + static struct InputEvent theEvent; + static char numpad[] = "bjnh.lyku"; + static char ctrl_numpad[] = "\x02\x0A\x0E\x08.\x0C\x19\x0B\x15"; + static char shift_numpad[] = "BJNH.LYKU"; + + unsigned char buffer[10]; + struct Window *w = message->IDCMPWindow; + register int length; + register ULONG qualifier; + char numeric_pad, shift, control, alt; + + if( amii_wins[ WIN_MAP ] ) + w = amii_wins[ WIN_MAP ]->win; + qualifier = message->Qualifier; + + control = (qualifier & IEQUALIFIER_CONTROL) != 0; + shift = (qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0; + alt = (qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT )) != 0; + + /* Allow ALT to function as a META key ... */ + /* But make it switchable - alt is needed for some non-US keymaps */ + if(flags.altmeta) + qualifier &= ~(IEQUALIFIER_LALT | IEQUALIFIER_RALT); + numeric_pad = (qualifier & IEQUALIFIER_NUMERICPAD) != 0; + + /* + * Shortcut for HELP and arrow keys. I suppose this is allowed. + * The defines are in intuition/intuition.h, and the keys don't + * serve 'text' input, normally. Also, parsing their escape + * sequences is such a mess... + */ + + switch (message->Code) { + case RAWHELP: + if( alt ) + { + EditColor(); + return( -1 ); + } +#ifdef CLIPPING + else if( WINVERS_AMIV && control ) + { + EditClipping(); + + CO = ( w->Width - w->BorderLeft - w->BorderRight ) / mxsize; + LI = ( w->Height - w->BorderTop - w->BorderBottom ) / mysize; + clipxmax = CO + clipx; + clipymax = LI + clipy; + if( CO < COLNO || LI < ROWNO ) + { + clipping = TRUE; + amii_cliparound( u.ux, u.uy ); + } + else + { + clipping = FALSE; + clipx = clipy = 0; + } + BufferQueueChar( 'R'-64 ); + return(-1); + } +#endif + else if( WINVERS_AMIV && shift ) + { + if( WIN_OVER == WIN_ERR ) + { + WIN_OVER = amii_create_nhwindow( NHW_OVER ); + BufferQueueChar( 'R'-64 ); + } + else + { + delayed_key_action = CloseOver; + } + return( -1 ); + } + return( '?' ); + break; + case CURSORLEFT: + length = '4'; + numeric_pad = 1; + goto arrow; + case CURSORDOWN: + length = '2'; + numeric_pad = 1; + goto arrow; + case CURSORUP: + length = '8'; + numeric_pad = 1; + goto arrow; + case CURSORRIGHT: + length = '6'; + numeric_pad = 1; + goto arrow; + } + + theEvent.ie_Class = IECLASS_RAWKEY; + theEvent.ie_Code = message->Code; + theEvent.ie_Qualifier = numeric_pad ? IEQUALIFIER_NUMERICPAD : qualifier; + theEvent.ie_EventAddress = (APTR) (message->IAddress); + + length = RawKeyConvert(&theEvent, (char *)buffer, + (long) sizeof(buffer), NULL); + + if (length == 1) { /* Plain ASCII character */ + length = buffer[0]; + /* + * If iflags.num_pad is set, movement is by 4286. + * If not set, translate 4286 into hjkl. + * This way, the numeric pad can /always/ be used + * for moving, though best results are when it is off. + */ +arrow: + if (!iflags.num_pad && numeric_pad && length >= '1' && length <= '9') { + length -= '1'; + if (control) { + length = ctrl_numpad[length]; + } else if (shift) { + length = shift_numpad[length]; + } else { + length = numpad[length]; + } + } + + /* Kludge to allow altmeta on eg. scandinavian keymap (# == shift+alt+3) + and prevent it from interfering with # command (M-#) */ + if (length == ('#'|0x80)) + return '#'; + if (alt && flags.altmeta) + length |= 0x80; + return(length); + } /* else shift, ctrl, alt, amiga, F-key, shift-tab, etc */ + else if( length > 1 ) + { + int i; + + if( length == 3 && buffer[ 0 ] == 155 && buffer[ 2 ] == 126 ) + { + int got = 1; + switch( buffer[ 1 ] ) + { + case 53: mxsize = mysize = 8; break; + case 54: mxsize = mysize = 16; break; + case 55: mxsize = mysize = 24; break; + case 56: mxsize = mysize = 32; break; + case 57: mxsize = mysize = 48; break; + default: got = 0; break; + } +#ifdef OPT_DISPMAP + dispmap_sanity(); +#endif + + if( got ) + { + CO = (w->Width-w->BorderLeft-w->BorderRight)/mxsize; + LI = (w->Height-w->BorderTop-w->BorderBottom)/mysize; + clipxmax = CO + clipx; + clipymax = LI + clipy; + if( CO < COLNO || LI < ROWNO ) + { + amii_cliparound( u.ux, u.uy ); + } + else + { + CO = COLNO; + LI = ROWNO; + } + reclip = 1; + doredraw(); + flush_screen( 1 ); + reclip = 0; + /*BufferQueueChar( 'R'-64 );*/ + return( -1 ); + } + } + printf( "Unrecognized key: %d ", (int)buffer[0]); + for( i = 1; i < length; ++i ) + printf( "%d ", (int)buffer[i]); + printf( "\n" ); + } + return( -1 ); +} + +/* + * Process an incoming IntuiMessage. + * It would certainly look nicer if this could be done using a + * PA_SOFTINT message port, but we cannot call RawKeyConvert() + * during a software interrupt. + * Anyway, amikbhit()/kbhit() is called often enough, and usually gets + * ahead of input demands, when the user types ahead. + */ + +static void ProcessMessage(message) +register struct IntuiMessage *message; +{ + int c; + int cnt; + menu_item *mip; + static int skip_mouse=0; /* need to ignore next mouse event on + * a window activation */ + struct Window *w = message->IDCMPWindow; + + switch(message->Class) { + case ACTIVEWINDOW: + if( alwaysinvent && WIN_INVEN != WIN_ERR && + w == amii_wins[ WIN_INVEN ]->win ) + { + cnt = DoMenuScroll( WIN_INVEN, 0, PICK_NONE, &mip ); + } + else if( scrollmsg && WIN_MESSAGE != WIN_ERR && + w == amii_wins[ WIN_MESSAGE ]->win ) + { + cnt = DoMenuScroll( WIN_MESSAGE, 0, PICK_NONE, &mip ); + } + else + { + skip_mouse=1; + } + break; + + case MOUSEBUTTONS: + { + if( skip_mouse ) + { + skip_mouse=0; + break; + } + + if( !amii_wins[ WIN_MAP ] || w != amii_wins[ WIN_MAP ]->win ) + break; + + if( message->Code == SELECTDOWN ) + { + lastevent.type = WEMOUSE; + lastevent.un.mouse.x = message->MouseX; + lastevent.un.mouse.y = message->MouseY; + /* With shift equals RUN */ + lastevent.un.mouse.qual = (message->Qualifier & + (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) != 0; + } + } + break; + + case MENUPICK: + { + USHORT thismenu; + struct MenuItem *item; + + thismenu = message->Code; + while (thismenu != MENUNULL) + { + item = ItemAddress(MenuStrip, (ULONG) thismenu); + if (KbdBuffered < KBDBUFFER) + BufferQueueChar((char)(GTMENUITEM_USERDATA(item))); + thismenu = item->NextSelect; + } + } + break; + + case REFRESHWINDOW: + { + if( scrollmsg + && amii_wins[ WIN_MESSAGE ] + && w == amii_wins[ WIN_MESSAGE ]->win + ){ + cnt = DoMenuScroll( WIN_MESSAGE, 0, PICK_NONE, &mip ); + } + } + break; + + case CLOSEWINDOW: + if( WIN_INVEN != WIN_ERR && w == amii_wins[ WIN_INVEN ]->win ) + { + dismiss_nhwindow( WIN_INVEN ); + } + if( WINVERS_AMIV + && ( WIN_OVER != WIN_ERR && w == amii_wins[ WIN_OVER ]->win ) + ){ + destroy_nhwindow( WIN_OVER ); + WIN_OVER = WIN_ERR; + } + break; + + case RAWKEY: + if (!(message->Code & IECODE_UP_PREFIX)){ + /* May queue multiple characters + * but doesn't do that yet... + */ + if( ( c = ConvertKey(message) ) > 0 ) + BufferQueueChar( c ); + } + break; + + case GADGETDOWN: + if( WIN_MESSAGE != WIN_ERR && w == amii_wins[ WIN_MESSAGE ]->win ) + { + cnt = DoMenuScroll( WIN_MESSAGE, 0, PICK_NONE, &mip ); + } + else if( WIN_INVEN != WIN_ERR && w == amii_wins[ WIN_INVEN ]->win ) + { + cnt = DoMenuScroll( WIN_INVEN, 0, PICK_NONE, &mip ); + } + break; + + case NEWSIZE: + if( WIN_MESSAGE != WIN_ERR && w == amii_wins[ WIN_MESSAGE ]->win ) + { + if( WINVERS_AMIV ) + { + /* Make sure that new size is honored for good. */ + SetAPen( w->RPort, amii_msgBPen ); + SetBPen( w->RPort, amii_msgBPen ); + SetDrMd( w->RPort, JAM2 ); + RectFill( w->RPort, w->BorderLeft, w->BorderTop, + w->Width - w->BorderRight-1, + w->Height - w->BorderBottom-1 ); + } + ReDisplayData( WIN_MESSAGE ); + } + else if( WIN_INVEN != WIN_ERR && w == amii_wins[ WIN_INVEN ]->win ) + { + ReDisplayData( WIN_INVEN ); + } + else if( WINVERS_AMIV + && ( WIN_OVER != WIN_ERR && w == amii_wins[ WIN_OVER ]->win ) + ){ + BufferQueueChar( 'R'-64 ); + } + else if( WIN_MAP != WIN_ERR && w == amii_wins[ WIN_MAP ]->win ) + { +#ifdef CLIPPING + CO = (w->Width-w->BorderLeft-w->BorderRight)/mxsize; + LI = (w->Height-w->BorderTop-w->BorderBottom)/mysize; + clipxmax = CO + clipx; + clipymax = LI + clipy; + if( CO < COLNO || LI < ROWNO ) + { + amii_cliparound( u.ux, u.uy ); + } + else + { + clipping = FALSE; + clipx = clipy = 0; + } + BufferQueueChar( 'R'-64 ); +#endif + } + break; + } + ReplyMsg((struct Message *) message); + + switch(delayed_key_action){ + case CloseOver: + amii_destroy_nhwindow( WIN_OVER ); + WIN_OVER = WIN_ERR; + delayed_key_action = NoAction; + case NoAction: + ; /* null */ + } +} + +#endif /* AMII_GRAPHICS */ +/* + * Get all incoming messages and fill up the keyboard buffer, + * thus allowing Intuition to (maybe) free up the IntuiMessages. + * Return when no more messages left, or keyboard buffer half full. + * We need to do this since there is no one-to-one correspondence + * between characters and incoming messages. + */ + +#if defined(TTY_GRAPHICS) && !defined(AMII_GRAPHICS) +int kbhit(){ + return 0; +} +#else +int +kbhit() +{ + int c; +# ifdef TTY_GRAPHICS + /* a kludge to defuse the mess in allmain.c */ + /* I hope this is the right approach */ + if(windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows)return 0; +# endif + c = amikbhit(); + if( c <= 0 ) + return( 0 ); + return( c ); +} +#endif + +#ifdef AMII_GRAPHICS + +int +amikbhit() +{ + register struct IntuiMessage *message; + while( KbdBuffered < KBDBUFFER / 2 ) + { +#ifdef AMIFLUSH + message = (struct IntuiMessage *) GetFMsg(HackPort); +#else + message = (struct IntuiMessage *) GetMsg(HackPort); +#endif + if(message) + { + ProcessMessage(message); + if( lastevent.type != WEUNK && lastevent.type != WEKEY ) + break; + } + else + break; + } + return ( lastevent.type == WEUNK ) ? KbdBuffered : -1; +} + +/* + * Get a character from the keyboard buffer, waiting if not available. + * Ignore other kinds of events that happen in the mean time. + */ + +int WindowGetchar( ) +{ + while ((lastevent.type = WEUNK), amikbhit() <= 0) { + WaitPort(HackPort); + } + return BufferGetchar(); +} + +WETYPE WindowGetevent() +{ + lastevent.type = WEUNK; + while (amikbhit() == 0) + { + WaitPort(HackPort); + } + + if( KbdBuffered ) + { + lastevent.type = WEKEY; + lastevent.un.key = BufferGetchar(); + } + return( lastevent.type ); +} + +/* + * Clean up everything. But before we do, ask the user to hit return + * when there is something that s/he should read. + */ + +void amii_cleanup() +{ + register struct IntuiMessage *msg; + + /* Close things up */ + if( HackPort ) + { + amii_raw_print(""); + amii_getret(); + } + + if (ConsoleIO.io_Device) + CloseDevice( (struct IORequest *)&ConsoleIO ); + ConsoleIO.io_Device = 0; + + if( ConsoleIO.io_Message.mn_ReplyPort ) + DeleteMsgPort( ConsoleIO.io_Message.mn_ReplyPort ); + ConsoleIO.io_Message.mn_ReplyPort = 0; + + /* Strip messages before deleting the port */ + if( HackPort ) + { + Forbid(); + while (msg = (struct IntuiMessage *) GetMsg(HackPort)) + ReplyMsg((struct Message *) msg); + kill_nhwindows( 1 ); + DeleteMsgPort( HackPort ); + HackPort = NULL; + Permit(); + } + + /* Close the screen, under v37 or greater it is a pub screen and there may + * be visitors, so check close status and wait till everyone is gone. + */ + if( HackScreen ) + { +#ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + { + if (MenuStrip) FreeMenus(MenuStrip); + if (VisualInfo) FreeVisualInfo(VisualInfo); + while( CloseScreen( HackScreen ) == FALSE ) + { + struct EasyStruct easy = + { + sizeof( struct EasyStruct ), + 0, + "Nethack Problem", + "Can't Close Screen, Close Visiting Windows", + "Okay" + }; + EasyRequest( NULL, &easy, NULL, NULL ); + } + } + else +#endif + { + CloseScreen(HackScreen); + } + HackScreen = NULL; + } + +#ifdef HACKFONT + if (HackFont) + { + CloseFont(HackFont); + HackFont = NULL; + } + + if( TextsFont ) + { + CloseFont( TextsFont ); + TextsFont = NULL; + } + + if( RogueFont ) + { + CloseFont( RogueFont ); + RogueFont = NULL; + } + + if( DiskfontBase ) + { + CloseLibrary(DiskfontBase); + DiskfontBase = NULL; + } +#endif + + if (GadToolsBase) { + CloseLibrary((struct Library *)GadToolsBase); + GadToolsBase=NULL; + } + + if (LayersBase) { + CloseLibrary((struct Library *)LayersBase); + LayersBase = NULL; + } + + if (GfxBase) { + CloseLibrary((struct Library *)GfxBase); + GfxBase = NULL; + } + + if (IntuitionBase) { + CloseLibrary((struct Library *)IntuitionBase); + IntuitionBase = NULL; + } + +#ifdef SHAREDLIB + if (DOSBase) { + CloseLibrary((struct Library *)DOSBase); + DOSBase = NULL; + } +#endif + + ((struct Process *) FindTask(NULL))->pr_WindowPtr = (APTR) pr_WindowPtr; + + Initialized = 0; +} + +#endif /* AMII_GRAPHICS */ + +#ifndef SHAREDLIB +void Abort(rc) +long rc; +{ + int fault = 1; +#ifdef CHDIR + extern char orgdir[]; + chdir(orgdir); +#endif +#ifdef AMII_GRAPHICS + if (Initialized + && ConsoleDevice + && windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows) { + printf("\n\nAbort with alert code %08lx...\n", rc); + amii_getret(); + } else +#endif + printf("\n\nAbort with alert code %08lx...\n",rc); + /* Alert(rc); this is too severe */ +#ifdef __SASC +# ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + { + struct EasyStruct es = + { + sizeof( struct EasyStruct ), + 0, + "NetHack Panic Request", + "NetHack is Aborting with code == 0x%08lx", + "Continue Abort|Return to Program|Clean up and exit", + }; + fault = EasyRequest( NULL, &es, NULL, (long)rc ); + if( fault == 2 ) + return; + } +# endif + if( fault == 1 ) + { +/* __emit(0x4afc); */ /* illegal instruction */ + __emit(0x40fc); /* divide by */ + __emit(0x0000); /* #0 */ + /* NOTE: don't move amii_cleanup() above here - */ + /* it is too likely to kill the system */ + /* before it can get the SnapShot out, if */ + /* there is something really wrong. */ + } +#endif +#ifdef AMII_GRAPHICS + if(windowprocs.win_init_nhwindows==amii_procs.win_init_nhwindows) + amii_cleanup(); +#endif +#undef exit +#ifdef AZTEC_C + _abort(); +#endif + exit((int) rc); +} + +void +CleanUp() +{ + amii_cleanup(); +} +#endif + +#ifdef AMII_GRAPHICS + +#ifdef AMIFLUSH +/* This routine adapted from AmigaMail IV-37 by Michael Sinz */ +static struct Message * +GetFMsg(port) + struct MsgPort *port; + { + struct IntuiMessage *msg,*succ,*succ1; + + if(msg=(struct IntuiMessage *)GetMsg(port)){ + if(!flags.amiflush)return((struct Message *)msg); + if(msg->Class==RAWKEY){ + Forbid(); + succ=(struct IntuiMessage *)(port->mp_MsgList.lh_Head); + while(succ1=(struct IntuiMessage *) + (succ->ExecMessage.mn_Node.ln_Succ)){ + if(succ->Class==RAWKEY){ + Remove((struct Node *)succ); + ReplyMsg((struct Message *)succ); + } + succ=succ1; + } + Permit(); + } + } + return((struct Message *)msg); +} +#endif + +struct NewWindow * +DupNewWindow( win ) + struct NewWindow *win; +{ + struct NewWindow *nwin; + struct Gadget *ngd, *gd, *pgd = NULL; + struct PropInfo *pip; + struct StringInfo *sip; + + /* Copy the (Ext)NewWindow structure */ + + nwin = (struct NewWindow *)alloc( sizeof( struct NewWindow ) ); + *nwin = *win; + + /* Now do the gadget list */ + + nwin->FirstGadget = NULL; + for( gd = win->FirstGadget; gd; gd = gd->NextGadget ) + { + ngd = (struct Gadget *)alloc( sizeof( struct Gadget ) ); + *ngd = *gd; + if( gd->GadgetType == STRGADGET ) + { + sip = (struct StringInfo *)alloc( sizeof( struct StringInfo ) ); + *sip = *((struct StringInfo *)gd->SpecialInfo); + sip->Buffer = (UBYTE *) alloc( sip->MaxChars ); + *sip->Buffer = 0; + ngd->SpecialInfo = (APTR)sip; + } + else if( gd->GadgetType == PROPGADGET ) + { + pip = (struct PropInfo *)alloc( sizeof( struct PropInfo ) ); + *pip = *((struct PropInfo *)gd->SpecialInfo); + ngd->SpecialInfo = (APTR)pip; + } + if( pgd ) + pgd->NextGadget = ngd; + else + nwin->FirstGadget = ngd; + pgd = ngd; + ngd->NextGadget = NULL; + ngd->UserData = (APTR) 0x45f35c3d; // magic cookie for FreeNewWindow() + } + return( nwin ); +} + +void +FreeNewWindow( win ) + struct NewWindow *win; +{ + register struct Gadget *gd, *pgd; + register struct StringInfo *sip; + + for( gd = win->FirstGadget; gd; gd = pgd ) { + pgd = gd->NextGadget; + if ((ULONG)gd->UserData == 0x45f35c3d) { + if( gd->GadgetType == STRGADGET ) { + sip = (struct StringInfo *)gd->SpecialInfo; + free( sip->Buffer ); + free( sip ); + } else if( gd->GadgetType == PROPGADGET ) { + free( (struct PropInfo *)gd->SpecialInfo ); + } + free( gd ); + } + } + free( win ); +} + +void +bell() +{ + if (flags.silent) return; + DisplayBeep(NULL); +} + +void +amii_delay_output() +{ + /* delay 50 ms */ + Delay(2L); +} + +void +amii_number_pad(state) +int state; +{ +} +#endif /* AMII_GRAPHICS */ + +#ifndef SHAREDLIB +void +amiv_loadlib( void ) +{ +} + +void +amii_loadlib( void ) +{ +} + +/* fatal error */ +/*VARARGS1*/ +void error VA_DECL(const char *, s) + VA_START(s); + VA_INIT(s, char *); + + putchar('\n'); + vprintf(s, VA_ARGS); + putchar('\n'); + + VA_END(); + Abort(0L); +} +#endif diff --git a/sys/amiga/amiwind.p b/sys/amiga/amiwind.p new file mode 100644 index 0000000..ca009d4 --- /dev/null +++ b/sys/amiga/amiwind.p @@ -0,0 +1,40 @@ +/* SCCS Id: @(#)amiwind.p 3.1 93/01/08 */ +/* Copyright (c) Gregg Wonderly, Naperville, IL, 1992, 1993 */ +/* NetHack may be freely redistributed. See license for details. */ + +/* amiwind.c */ +#ifdef INTUI_NEW_LOOK +struct Window *FDECL( OpenShWindow, (struct ExtNewWindow *) ); +#else +struct Window *FDECL( OpenShWindow, (struct NewWindow *) ); +#endif +void FDECL( CloseShWindow, (struct Window *)); +int NDECL( kbhit ); +int NDECL( amikbhit ); +int NDECL( WindowGetchar ); +WETYPE NDECL( WindowGetevent ); +void NDECL( WindowFlush ); +void FDECL( WindowPutchar, (char )); +void FDECL( WindowFPuts, (const char *)); +void FDECL( WindowPuts, (const char *)); +void FDECL( WindowPrintf, ( char *,... )); +void NDECL( CleanUp ); +int FDECL( ConvertKey, ( struct IntuiMessage * )); +#ifndef SHAREDLIB +void FDECL( Abort, (long )); +#endif +void FDECL( flush_glyph_buffer, (struct Window *)); +void FDECL( amiga_print_glyph, (winid , int , int )); +void FDECL( start_glyphout, (winid )); +void FDECL( amii_end_glyphout, (winid )); +#ifdef INTUI_NEW_LOOK +struct ExtNewWindow *FDECL( DupNewWindow, (struct ExtNewWindow *)); +void FDECL( FreeNewWindow, (struct ExtNewWindow *)); +#else +struct NewWindow *FDECL( DupNewWindow, (struct NewWindow *)); +void FDECL( FreeNewWindow, (struct NewWindow *)); +#endif +void NDECL( bell ); +void NDECL( amii_delay_output ); +void FDECL( amii_number_pad, (int )); +void amii_cleanup( void ); diff --git a/sys/amiga/clipwin.c b/sys/amiga/clipwin.c new file mode 100644 index 0000000..a5ede30 --- /dev/null +++ b/sys/amiga/clipwin.c @@ -0,0 +1,268 @@ +static USHORT Palette[] = { + 0x0AAA, /* color #0 */ + 0x0000, /* color #1 */ + 0x0FFF, /* color #2 */ + 0x058B, /* color #3 */ + 0x000F, /* color #4 */ + 0x0F0F, /* color #5 */ + 0x00FF, /* color #6 */ + 0x0FFF /* color #7 */ +#define PaletteColorCount 8 +}; + +#define PALETTE Palette + +static SHORT ClipBorderVectors1[] = { + 0,0, + 76,0, + 76,11, + 0,11, + 0,0 +}; +static struct Border ClipBorder1 = { + -1,-1, /* XY origin relative to container TopLeft */ + 3,0,JAM1, /* front pen, back pen and drawmode */ + 5, /* number of XY vectors */ + ClipBorderVectors1, /* pointer to XY vectors */ + NULL /* next border in list */ +}; + +static struct IntuiText ClipIText1 = { + 4,0,JAM1, /* front and back text pens, drawmode and fill byte */ + 15,1, /* XY origin relative to container TopLeft */ + NULL, /* font pointer or NULL for default */ + "Cancel", /* pointer to text */ + NULL /* next IntuiText structure */ +}; + +static struct Gadget ClipCancel = { + NULL, /* next gadget */ + 240,59, /* origin XY of hit box relative to window TopLeft */ + 75,10, /* hit box width and height */ + NULL, /* gadget flags */ + RELVERIFY, /* activation flags */ + BOOLGADGET, /* gadget type flags */ + (APTR)&ClipBorder1, /* gadget border or image to be rendered */ + NULL, /* alternate imagery for selection */ + &ClipIText1, /* first IntuiText structure */ + NULL, /* gadget mutual-exclude long word */ + NULL, /* SpecialInfo structure */ + GADCANCEL, /* user-definable data */ + NULL /* pointer to user-definable data */ +}; + +static SHORT ClipBorderVectors2[] = { + 0,0, + 78,0, + 78,11, + 0,11, + 0,0 +}; +static struct Border ClipBorder2 = { + -1,-1, /* XY origin relative to container TopLeft */ + 3,0,JAM1, /* front pen, back pen and drawmode */ + 5, /* number of XY vectors */ + ClipBorderVectors2, /* pointer to XY vectors */ + NULL /* next border in list */ +}; + +static struct IntuiText ClipIText2 = { + 4,0,JAM1, /* front and back text pens, drawmode and fill byte */ + 24,1, /* XY origin relative to container TopLeft */ + NULL, /* font pointer or NULL for default */ + "Okay", /* pointer to text */ + NULL /* next IntuiText structure */ +}; + +static struct Gadget ClipOkay = { + &ClipCancel, /* next gadget */ + 17,60, /* origin XY of hit box relative to window TopLeft */ + 77,10, /* hit box width and height */ + NULL, /* gadget flags */ + RELVERIFY, /* activation flags */ + BOOLGADGET, /* gadget type flags */ + (APTR)&ClipBorder2, /* gadget border or image to be rendered */ + NULL, /* alternate imagery for selection */ + &ClipIText2, /* first IntuiText structure */ + NULL, /* gadget mutual-exclude long word */ + NULL, /* SpecialInfo structure */ + GADOKAY, /* user-definable data */ + NULL /* pointer to user-definable data */ +}; + +static struct PropInfo ClipClipXCLIPSInfo = { + AUTOKNOB+FREEHORIZ, /* PropInfo flags */ + 24504,-1, /* horizontal and vertical pot values */ + 10922,-1, /* horizontal and vertical body values */ +}; + +static struct Image ClipImage1 = { + 43,0, /* XY origin relative to container TopLeft */ + 24,3, /* Image width and height in pixels */ + 0, /* number of bitplanes in Image */ + NULL, /* pointer to ImageData */ + 0x0000,0x0000, /* PlanePick and PlaneOnOff */ + NULL /* next Image structure */ +}; + +static struct IntuiText ClipIText3 = { + 3,0,JAM1, /* front and back text pens, drawmode and fill byte */ + -116,-1, /* XY origin relative to container TopLeft */ + NULL, /* font pointer or NULL for default */ + "X Clip Border:", /* pointer to text */ + NULL /* next IntuiText structure */ +}; + +static struct Gadget ClipXCLIP = { + &ClipOkay, /* next gadget */ + 134,37, /* origin XY of hit box relative to window TopLeft */ + -199,7, /* hit box width and height */ + GRELWIDTH, /* gadget flags */ + RELVERIFY+GADGIMMEDIATE, /* activation flags */ + PROPGADGET, /* gadget type flags */ + (APTR)&ClipImage1, /* gadget border or image to be rendered */ + NULL, /* alternate imagery for selection */ + &ClipIText3, /* first IntuiText structure */ + NULL, /* gadget mutual-exclude long word */ + (APTR)&ClipClipXCLIPSInfo, /* SpecialInfo structure */ + XCLIP, /* user-definable data */ + NULL /* pointer to user-definable data */ +}; + +static struct PropInfo ClipClipYCLIPSInfo = { + AUTOKNOB+FREEHORIZ, /* PropInfo flags */ + 13106,-1, /* horizontal and vertical pot values */ + 10922,-1, /* horizontal and vertical body values */ +}; + +static struct Image ClipImage2 = { + 22,0, /* XY origin relative to container TopLeft */ + 24,3, /* Image width and height in pixels */ + 0, /* number of bitplanes in Image */ + NULL, /* pointer to ImageData */ + 0x0000,0x0000, /* PlanePick and PlaneOnOff */ + NULL /* next Image structure */ +}; + +static struct IntuiText ClipIText4 = { + 3,0,JAM1, /* front and back text pens, drawmode and fill byte */ + -116,-1, /* XY origin relative to container TopLeft */ + NULL, /* font pointer or NULL for default */ + "Y Clip Border:", /* pointer to text */ + NULL /* next IntuiText structure */ +}; + +static struct Gadget ClipYCLIP = { + &ClipXCLIP, /* next gadget */ + 134,46, /* origin XY of hit box relative to window TopLeft */ + -199,7, /* hit box width and height */ + GRELWIDTH, /* gadget flags */ + RELVERIFY+GADGIMMEDIATE, /* activation flags */ + PROPGADGET, /* gadget type flags */ + (APTR)&ClipImage2, /* gadget border or image to be rendered */ + NULL, /* alternate imagery for selection */ + &ClipIText4, /* first IntuiText structure */ + NULL, /* gadget mutual-exclude long word */ + (APTR)&ClipClipYCLIPSInfo, /* SpecialInfo structure */ + YCLIP, /* user-definable data */ + NULL /* pointer to user-definable data */ +}; + +static struct PropInfo ClipClipXSIZESInfo = { + AUTOKNOB+FREEHORIZ, /* PropInfo flags */ + 26212,-1, /* horizontal and vertical pot values */ + 10922,-1, /* horizontal and vertical body values */ +}; + +static struct Image ClipImage3 = { + 45,0, /* XY origin relative to container TopLeft */ + 24,3, /* Image width and height in pixels */ + 0, /* number of bitplanes in Image */ + NULL, /* pointer to ImageData */ + 0x0000,0x0000, /* PlanePick and PlaneOnOff */ + NULL /* next Image structure */ +}; + +static struct IntuiText ClipIText5 = { + 3,0,JAM1, /* front and back text pens, drawmode and fill byte */ + -124,-1, /* XY origin relative to container TopLeft */ + NULL, /* font pointer or NULL for default */ + "X Scale Factor:", /* pointer to text */ + NULL /* next IntuiText structure */ +}; + +static struct Gadget ClipXSIZE = { + &ClipYCLIP, /* next gadget */ + 134,15, /* origin XY of hit box relative to window TopLeft */ + -199,7, /* hit box width and height */ + GRELWIDTH, /* gadget flags */ + RELVERIFY+GADGIMMEDIATE, /* activation flags */ + PROPGADGET, /* gadget type flags */ + (APTR)&ClipImage3, /* gadget border or image to be rendered */ + NULL, /* alternate imagery for selection */ + &ClipIText5, /* first IntuiText structure */ + NULL, /* gadget mutual-exclude long word */ + (APTR)&ClipClipXSIZESInfo, /* SpecialInfo structure */ + XSIZE, /* user-definable data */ + NULL /* pointer to user-definable data */ +}; + +static struct PropInfo ClipClipYSIZESInfo = { + AUTOKNOB+FREEHORIZ, /* PropInfo flags */ + -25937,-1, /* horizontal and vertical pot values */ + 10922,-1, /* horizontal and vertical body values */ +}; + +static struct Image ClipImage4 = { + 69,0, /* XY origin relative to container TopLeft */ + 24,3, /* Image width and height in pixels */ + 0, /* number of bitplanes in Image */ + NULL, /* pointer to ImageData */ + 0x0000,0x0000, /* PlanePick and PlaneOnOff */ + NULL /* next Image structure */ +}; + +static struct IntuiText ClipIText6 = { + 3,0,JAM1, /* front and back text pens, drawmode and fill byte */ + -124,-1, /* XY origin relative to container TopLeft */ + NULL, /* font pointer or NULL for default */ + "Y Scale Factor:", /* pointer to text */ + NULL /* next IntuiText structure */ +}; + +static struct Gadget ClipYSIZE = { + &ClipXSIZE, /* next gadget */ + 134,24, /* origin XY of hit box relative to window TopLeft */ + -199,7, /* hit box width and height */ + GRELWIDTH, /* gadget flags */ + RELVERIFY+GADGIMMEDIATE, /* activation flags */ + PROPGADGET, /* gadget type flags */ + (APTR)&ClipImage4, /* gadget border or image to be rendered */ + NULL, /* alternate imagery for selection */ + &ClipIText6, /* first IntuiText structure */ + NULL, /* gadget mutual-exclude long word */ + (APTR)&ClipClipYSIZESInfo, /* SpecialInfo structure */ + YSIZE, /* user-definable data */ + NULL /* pointer to user-definable data */ +}; + +#define ClipGadgetList1 ClipYSIZE + +static struct NewWindow ClipNewWindowStructure1 = { + 114,16, /* window XY origin relative to TopLeft of screen */ + 346,76, /* window width and height */ + 0,1, /* detail and block pens */ + NEWSIZE+MOUSEMOVE+GADGETDOWN+GADGETUP+CLOSEWINDOW+ACTIVEWINDOW+VANILLAKEY+INTUITICKS, /* IDCMP flags */ + WINDOWSIZING+WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE+ACTIVATE+NOCAREREFRESH, /* other window flags */ + &ClipYSIZE, /* first gadget in gadget list */ + NULL, /* custom CHECKMARK imagery */ + "Edit Clipping Parameters", /* window title */ + NULL, /* custom screen pointer */ + NULL, /* custom bitmap */ + 350,76, /* minimum width and height */ + -1,-1, /* maximum width and height */ + CUSTOMSCREEN /* destination screen type */ +}; + + +/* end of PowerWindows source generation */ diff --git a/sys/amiga/colorwin.c b/sys/amiga/colorwin.c new file mode 100644 index 0000000..a9cf25c --- /dev/null +++ b/sys/amiga/colorwin.c @@ -0,0 +1,256 @@ +SHORT Col_BorderVectors1[] = { + 0,0, + 59,0, + 59,12, + 0,12, + 0,0 +}; +struct Border Col_Border1 = { + -1,-1, /* XY origin relative to container TopLeft */ + 3,0,JAM1, /* front pen, back pen and drawmode */ + 5, /* number of XY vectors */ + Col_BorderVectors1, /* pointer to XY vectors */ + NULL /* next border in list */ +}; + +struct IntuiText Col_IText1 = { + 7,0,JAM1, /* front and back text pens, drawmode and fill byte */ + 13,1, /* XY origin relative to container TopLeft */ + NULL, /* font pointer or NULL for default */ + "Save", /* pointer to text */ + NULL /* next IntuiText structure */ +}; + +struct Gadget Col_Save = { + NULL, /* next gadget */ + 9,77, /* origin XY of hit box relative to window TopLeft */ + 58,11, /* hit box width and height */ + NULL, /* gadget flags */ + RELVERIFY, /* activation flags */ + BOOLGADGET, /* gadget type flags */ + (APTR)&Col_Border1, /* gadget border or image to be rendered */ + NULL, /* alternate imagery for selection */ + &Col_IText1, /* first IntuiText structure */ + NULL, /* gadget mutual-exclude long word */ + NULL, /* SpecialInfo structure */ + GADCOLSAVE, /* user-definable data */ + NULL /* pointer to user-definable data */ +}; + +SHORT Col_BorderVectors2[] = { + 0,0, + 59,0, + 59,12, + 0,12, + 0,0 +}; +struct Border Col_Border2 = { + -1,-1, /* XY origin relative to container TopLeft */ + 3,0,JAM1, /* front pen, back pen and drawmode */ + 5, /* number of XY vectors */ + Col_BorderVectors2, /* pointer to XY vectors */ + NULL /* next border in list */ +}; + +struct IntuiText Col_IText2 = { + 7,0,JAM1, /* front and back text pens, drawmode and fill byte */ + 17,1, /* XY origin relative to container TopLeft */ + NULL, /* font pointer or NULL for default */ + "Use", /* pointer to text */ + NULL /* next IntuiText structure */ +}; + +struct Gadget Col_Okay = { + &Col_Save, /* next gadget */ + 128,77, /* origin XY of hit box relative to window TopLeft */ + 58,11, /* hit box width and height */ + NULL, /* gadget flags */ + RELVERIFY, /* activation flags */ + BOOLGADGET, /* gadget type flags */ + (APTR)&Col_Border2, /* gadget border or image to be rendered */ + NULL, /* alternate imagery for selection */ + &Col_IText2, /* first IntuiText structure */ + NULL, /* gadget mutual-exclude long word */ + NULL, /* SpecialInfo structure */ + GADCOLOKAY, /* user-definable data */ + NULL /* pointer to user-definable data */ +}; + +SHORT Col_BorderVectors3[] = { + 0,0, + 59,0, + 59,12, + 0,12, + 0,0 +}; +struct Border Col_Border3 = { + -1,-1, /* XY origin relative to container TopLeft */ + 3,0,JAM1, /* front pen, back pen and drawmode */ + 5, /* number of XY vectors */ + Col_BorderVectors3, /* pointer to XY vectors */ + NULL /* next border in list */ +}; + +struct IntuiText Col_IText3 = { + 7,0,JAM1, /* front and back text pens, drawmode and fill byte */ + 6,1, /* XY origin relative to container TopLeft */ + NULL, /* font pointer or NULL for default */ + "Cancel", /* pointer to text */ + NULL /* next IntuiText structure */ +}; + +struct Gadget Col_Cancel = { + &Col_Okay, /* next gadget */ + 244,77, /* origin XY of hit box relative to window TopLeft */ + 58,11, /* hit box width and height */ + NULL, /* gadget flags */ + RELVERIFY, /* activation flags */ + BOOLGADGET, /* gadget type flags */ + (APTR)&Col_Border3, /* gadget border or image to be rendered */ + NULL, /* alternate imagery for selection */ + &Col_IText3, /* first IntuiText structure */ + NULL, /* gadget mutual-exclude long word */ + NULL, /* SpecialInfo structure */ + GADCOLCANCEL, /* user-definable data */ + NULL /* pointer to user-definable data */ +}; + +struct PropInfo Col_Col_RedPenSInfo = { + AUTOKNOB+FREEHORIZ, /* PropInfo flags */ + 0,0, /* horizontal and vertical pot values */ + -1,-1, /* horizontal and vertical body values */ +}; + +struct Image Col_Image1 = { + 0,0, /* XY origin relative to container TopLeft */ + 263,7, /* Image width and height in pixels */ + 0, /* number of bitplanes in Image */ + NULL, /* pointer to ImageData */ + 0x0000,0x0000, /* PlanePick and PlaneOnOff */ + NULL /* next Image structure */ +}; + +struct Gadget Col_RedPen = { + &Col_Cancel, /* next gadget */ + 32,12, /* origin XY of hit box relative to window TopLeft */ + 271,11, /* hit box width and height */ + NULL, /* gadget flags */ + RELVERIFY+GADGIMMEDIATE+FOLLOWMOUSE, /* activation flags */ + PROPGADGET, /* gadget type flags */ + (APTR)&Col_Image1, /* gadget border or image to be rendered */ + NULL, /* alternate imagery for selection */ + NULL, /* first IntuiText structure */ + NULL, /* gadget mutual-exclude long word */ + (APTR)&Col_Col_RedPenSInfo, /* SpecialInfo structure */ + GADREDPEN, /* user-definable data */ + NULL /* pointer to user-definable data */ +}; + +struct PropInfo Col_Col_GreenPenSInfo = { + AUTOKNOB+FREEHORIZ, /* PropInfo flags */ + 0,0, /* horizontal and vertical pot values */ + -1,-1, /* horizontal and vertical body values */ +}; + +struct Image Col_Image2 = { + 0,0, /* XY origin relative to container TopLeft */ + 263,7, /* Image width and height in pixels */ + 0, /* number of bitplanes in Image */ + NULL, /* pointer to ImageData */ + 0x0000,0x0000, /* PlanePick and PlaneOnOff */ + NULL /* next Image structure */ +}; + +struct Gadget Col_GreenPen = { + &Col_RedPen, /* next gadget */ + 32,24, /* origin XY of hit box relative to window TopLeft */ + 271,11, /* hit box width and height */ + NULL, /* gadget flags */ + RELVERIFY+GADGIMMEDIATE+FOLLOWMOUSE, /* activation flags */ + PROPGADGET, /* gadget type flags */ + (APTR)&Col_Image2, /* gadget border or image to be rendered */ + NULL, /* alternate imagery for selection */ + NULL, /* first IntuiText structure */ + NULL, /* gadget mutual-exclude long word */ + (APTR)&Col_Col_GreenPenSInfo, /* SpecialInfo structure */ + GADGREENPEN, /* user-definable data */ + NULL /* pointer to user-definable data */ +}; + +struct PropInfo Col_Col_BluePenSInfo = { + AUTOKNOB+FREEHORIZ, /* PropInfo flags */ + 0,0, /* horizontal and vertical pot values */ + -1,-1, /* horizontal and vertical body values */ +}; + +struct Image Col_Image3 = { + 0,0, /* XY origin relative to container TopLeft */ + 263,7, /* Image width and height in pixels */ + 0, /* number of bitplanes in Image */ + NULL, /* pointer to ImageData */ + 0x0000,0x0000, /* PlanePick and PlaneOnOff */ + NULL /* next Image structure */ +}; + +struct Gadget Col_BluePen = { + &Col_GreenPen, /* next gadget */ + 32,36, /* origin XY of hit box relative to window TopLeft */ + 271,11, /* hit box width and height */ + NULL, /* gadget flags */ + RELVERIFY+GADGIMMEDIATE+FOLLOWMOUSE, /* activation flags */ + PROPGADGET, /* gadget type flags */ + (APTR)&Col_Image3, /* gadget border or image to be rendered */ + NULL, /* alternate imagery for selection */ + NULL, /* first IntuiText structure */ + NULL, /* gadget mutual-exclude long word */ + (APTR)&Col_Col_BluePenSInfo, /* SpecialInfo structure */ + GADBLUEPEN, /* user-definable data */ + NULL /* pointer to user-definable data */ +}; + +#define Col_GadgetList1 Col_BluePen + +struct IntuiText Col_IText6 = { + 3,0,JAM1, /* front and back text pens, drawmode and fill byte */ + 17,38, /* XY origin relative to container TopLeft */ + NULL, /* font pointer or NULL for default */ + "B", /* pointer to text */ + NULL /* next IntuiText structure */ +}; + +struct IntuiText Col_IText5 = { + 4,0,JAM1, /* front and back text pens, drawmode and fill byte */ + 16,26, /* XY origin relative to container TopLeft */ + NULL, /* font pointer or NULL for default */ + "G", /* pointer to text */ + &Col_IText6 /* next IntuiText structure */ +}; + +struct IntuiText Col_IText4 = { + 7,0,JAM1, /* front and back text pens, drawmode and fill byte */ + 16,14, /* XY origin relative to container TopLeft */ + NULL, /* font pointer or NULL for default */ + "R", /* pointer to text */ + &Col_IText5 /* next IntuiText structure */ +}; + +#define Col_IntuiTextList1 Col_IText4 + +struct NewWindow Col_NewWindowStructure1 = { + 175,45, /* window XY origin relative to TopLeft of screen */ + 312,93, /* window width and height */ + 0,1, /* detail and block pens */ + MOUSEBUTTONS+MOUSEMOVE+GADGETDOWN+GADGETUP+CLOSEWINDOW+VANILLAKEY+INTUITICKS, /* IDCMP flags */ + WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE+ACTIVATE+NOCAREREFRESH, /* other window flags */ + &Col_BluePen, /* first gadget in gadget list */ + NULL, /* custom CHECKMARK imagery */ + "Edit Screen Colors", /* window title */ + NULL, /* custom screen pointer */ + NULL, /* custom bitmap */ + 5,5, /* minimum width and height */ + -1,-1, /* maximum width and height */ + CUSTOMSCREEN /* destination screen type */ +}; + + +/* end of PowerWindows source generation */ diff --git a/sys/amiga/cvtsnd.c b/sys/amiga/cvtsnd.c new file mode 100644 index 0000000..0e5f9c5 --- /dev/null +++ b/sys/amiga/cvtsnd.c @@ -0,0 +1,96 @@ +/* SCCS Id: @(#)cvtsnd.c 3.2 95/09/10 */ +/* Copyright (c) 1995, Andrew Church, Olney, Maryland */ +/* NetHack may be freely redistributed. See license for details. */ + +#include +#include +#include + +typedef struct { + short namelen; + char name[62]; + char misc[64]; /* rest of MacBinary header */ + long FORM; + long flen; + long AIFF; + long SSND; + long sndlen; +} AIFF; + +typedef struct { + char FORM[4]; + long flen; + char _8SVX[4]; + char VHDR[4]; + long vhlen; + long oneshot, repeat; + long samples; /* 'samplesPerHiCycle' in the docs - usually 32, so + * we'll use that */ + short freq; + char octaves, compress; + long volume; + char NAME[4]; + long nlen; /* should be 64; see name[] comment */ + char name[64]; /* for simplicity, i.e. just fwrite() entiree header */ + char BODY[4]; + long blen; +} IFF; + + +main(int ac, char **av) +{ + FILE *in, *out; + AIFF aiff; + IFF iff; + static char buf[16384]; + long n, len; + + if (ac != 3) { + fprintf(stderr, "Usage: %s input-file output-file\n", av[0]); + exit(20); + } + if (!(in = fopen(av[1], "r"))) { + fprintf(stderr, "Can't open input file\n"); + exit(20); + } + if (!(out = fopen(av[2], "w"))) { + fprintf(stderr, "Can't open output file\n"); + exit(20); + } + + fread(&aiff, sizeof(aiff), 1, in); + memcpy(iff.FORM, "FORM", 4); + iff.flen = sizeof(iff) + aiff.sndlen - 8; + memcpy(iff._8SVX, "8SVX", 4); + memcpy(iff.VHDR, "VHDR", 4); + iff.vhlen = 20; + iff.oneshot = aiff.sndlen; + iff.repeat = 0; + iff.samples = 32; + iff.freq = 22000; + iff.octaves = 1; + iff.compress= 0; + iff.volume = 0x10000; + memcpy(iff.NAME, "NAME", 4); + iff.nlen = 64; + strncpy(iff.name, aiff.name, 62); iff.name[aiff.namelen] = 0; + memcpy(iff.BODY, "BODY", 4); + iff.blen = aiff.sndlen; + fwrite(&iff, sizeof(iff), 1, out); + len = aiff.sndlen; + do { + if (len >= sizeof(buf)) + n = fread(buf, 1, sizeof(buf), in); + else + n = fread(buf, 1, len, in); + if (n) { + fwrite(buf, 1, n, out); + len -= n; + } + } while (len && n); + + if (len) + fprintf(stderr, "Warning: %ld bytes of sample missing\n", len); + fclose(in); fclose(out); + exit(0); +} diff --git a/sys/amiga/grave16.xpm b/sys/amiga/grave16.xpm new file mode 100644 index 0000000..bb0466d --- /dev/null +++ b/sys/amiga/grave16.xpm @@ -0,0 +1,223 @@ +/* XPM */ +static char *noname[] = { +/* width height ncolors chars_per_pixel */ +"400 200 16 1", +/* colors */ +"` c #66686A", +"a c #797979", +"b c #929291", +"c c #43444A", +"d c #758A74", +"e c #F2F2F2", +"f c #D1D0CE", +"g c #066906", +"h c #065506", +"i c #53535C", +"j c #0C0D0F", +"k c #A3A5A2", +"l c #2D332E", +"m c #C3C4C1", +"n c #B4B4B2", +"o c #07840A", +/* pixels */ +"jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjljjjjjjjjjjjjjjjljjjjjjjjjjjljljjljljjljjllljljclljlllljlllljlllllllllllllllcicl``clcllclclllclclclcclclclcccccccccccccccccccii`iiccicicicciiciiiiiibiic`iii`a`iiii`icaii`iiii`iiii`ii`ii`iii```iii`i`ii`ii`ii`iiii`iii`ii`iifi`ii`ii`iiiiiiiiiiiiiiiiiiiiii`iciibicicicicciiccciiibiicciiiiccccbicicccccccciccclcccccclc`aiciiiciccclilccccccccccclcccacccccccclccclcclccc", +"jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjljjjjjjjljjjjjjljjjjjjajljjljljljljjjjljjljc`baljjllcljjcjlljllllllllllllllllllllllcclllllllclllcclcllclclccccccccclccccccccccccicciicciicicicic`cciiciciciciacicii`iiiiii``iiakii`iiii`ii`ii`iiii`bkb`i`ci``iiiiii`iii`ii``i`iiiiiaiiiiiiiiii`iiiiiiiiiiiiiiiiiiiiiciiciciicicciciiiicllic`iciiiicicciliccccccccccccc`ccccliccccccccciciccclccccclclclclcclccclclclllccclcllccll", +"ijjjjjjjjjjjjjjjjjjljjjjjjjjljjjjjjjjjjjljjjljjjjjjljljjjjjjjljjjljljljljjjjlljljljljcclljllllljlllljllllllllllllllllcclccclcjcllclclclclllcclclcccccccccccciccccciiic`a`icciiccciciiiiiiiiibi`iiiiii`ii`ci`iii`ii`i`iiiiiiiii`iii``ici`i`i`i``ii`ii`iiiiiiic``iiiiiiiiiiiiiiaiiiiiiiiiiciicicii`iiiiiliiccicicccicccci`ccicccicccclccinccccccccclcccaccccccclccccccccccilcl`lllccclcclcclcllcllclcccclllilcllci", +"jjjjjjjjjjjjj`cjjjjljjjjjjjjcljljjjjjjjljjljijjljjjjjjjljljljjljljljlljljllljjljllflcjljllljljlljllllcllllllllllllcllllccllcc`clclllcllcclclcccclccccccccciccciciccccccic`iciic`iiiiciiiiiiiaiii`iii`i`icak`c``i`iiiiii`ii`i`iii`i`ii`iiiiiiici`iii`ii`i`ii``iiii`c`iiiiiiiii`iiiiiiiiciiiiiiiiiiiccccciccicicciiccccciaillcccciiciccclcccccccccccccc`cclclccillccllcliibilikaicllcclccccclcccclcccccllccllcclcl", +"jjcjjjjjjjjljjjjjjjjjjjjjjjjljjjljjjjjjjjjjjljjjjjljjcjjjljjljjljjjljjljljjjlljllljlllcljllllllllllllcclllllllllclllcclccibccclclcclcclcllicicccccccclcccccccciciicciccciaaiciccciiiiiiii`ciiiiii`iiiii`ic`iiiiiiii`ii`iiiiiiiiii`iiiiiciiiii`i`iiiii`ii`iiiciiiiiiiiiiiiiiciiiciiciciiccicciiiiiicicc`cccccccicccccicciiccicccicclilccccccclccccclccllcccilcccclcciclccciclcclccclccclclllcllcllccllcccclaacccl", +"jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjljljjjjjjjlljjjjljljjjjjljjljjljljlljljlljlllllljajljljlllllllllllllllcllllllllclccilcicclc`clalcclclclcclcccicclclccccciiccicciccciciiiiiiciib`iiiiiiiiiii`iiii``i`i`iiiiiiii`iiiiiiiiiiiiiiiiiibaiiici`iiiiibiiiii`iiiic`kaiiiiiiiiiiiiiciiiciiiciiciciccicciiiiciiiciccicicccccccciclcccccciiccccaciclclcccciilcccclcclcclcllclilacclcccclccclclcccccclccclclccllcclllllkblllc", +"jjjjjjjjjjjjjjjjjjjjjjjjjjjjjljjljjjljjjjjljljjjjjjjljljjljjljljlllljljljljjjjjljllljcjllllllllllllllllllllccclclabclccccciccccllclclcclcclclccccccccciiaiiicciciiicccccciiiiiiiiiciiiiiicii`i`i``i`iiiii`iiiiiiiiiiiiiiiiiiiiiibiciiiicciiii`iiiiiiiiiie`i``ic`iiiiiiiiiciiciciiciciciciciiiciic`cccclcccccccccciccccccciccciicilcillcccccclciccccclclccclibaili`lillccccciicliccccccclcccllallclliiiclcliilcll", +"jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjljjljjjjjjjjljjljjjljjjjjljjljljlllllljllljlclllllljlllllllllllllllllllllllllcccclccliiccccciccccclclcclccccccclcciccccciacciciiiccci`iiiiciiiiiiiiiiiiiii`i`c``````i``iiiiciiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii`kciiiiiiiiii`c`iciciiiiiiciiiiiiciccicicicciciiiiii`ifcccciccicccccccccccccccclccccccclcclccclccclclclcllilclcclcllclcliilclclclccicccccccccllllcecclclliaacllcllclc", +"jjjjjjjjjjljjjjjjjjjjjjjjjjjjjjjjljljjjljjjjlljjljjjljljjlijjllllllllllllljljajlljlalllllllllllllllllllllccccclllccclclccccccccccclcccccc`clcccccccccccicacicciciciciiiiiiib`iiciiiii`c`iiii``iii``ii``ciiiiiiciiiiciiiii`biii`iiiiciiiiciiicib`iiiiiiiiiiiiiiiiicii```cccciciciciiiiiiiciiiciiccccccccccciicciccccccccccccciccccclccclcccllccclclc`ccclcclcccccclcccllclccclclllcllcliccllclmccclcccl`lclclclll", +"jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjljjjljjjlljjjllljlljjjljljjjljljlcllllljcljjcljlllijllllllllllllllilcllcccccllicllllclcllcclliccccclccclcccccccccccccccc`iciicicciiiaiciciicl`ici`iiiiiiii`ii`i`ii``iiiiiiiiiiiiiii`iiiiiaciiciiiiiiiciiiciiiiiiicici`ciiciiiiciicciiiciiciciiiciiiiiii`cbi`liicicccccccccclccccccccclclccccccclcilccllccccllcclcccclcclclclllllcllllcllllllclcllccccclllcllilllclllclilillccll", +"jjjjjjjljljjjjjjjjjjjjjjjjjjljjjjljljjjjjjjjlljjljlllljllljllljlcljjljljcjlllljcljllllcllllllllllim`lljccllcclcbacllcllclccliclcccclccccccccccccccicciciciiciiciiiiiibiiiib``iiii`i`iiaii`ii`iiiiiciiiiiiiiiiicciiiiiii`iiiiiciiiiciciici`cciiciciiiiib`c`aaicciicicciccccciiiiiiiicciiicciilccccclcccccccccccclccccccclccliccccclclclcillccccllcclclccilcccclclcclcccclclclclllcllllcclllllllclllcllcllclcll`cc", +"jjjjjjjjjjjjjjjjjjjjijljjjjjjjljjljjljjjljjjjjjcjljljlcjjlcljlljkclllllllcllllljllllllljllllllllllliiccccclllllcccllcclcclclclcicccccclcclcccccccicccciicciciiciiiicc`ciii`ciiiiiiiiii``ii`iiiiiiiicii`i`i`iii`iicic`ii``iiiiiiiiiiciciciiiicc`ciicici`cc`iiiciciicicciicicci`iiiiiciciicicccibiccccccclcccccclclcclclcclccicclclcicclikclcllclllcllcllclccccllclclcliclci`cllclllillliccclcllclclbilllclllclcal", +"jjjjjjcbljjcajjjjjjjljjjljljjjjjljjjjjjljljjljjjlljcjllljlilllllaljlljjl`mllljcillllclllllllllllcllclllciiilccclllclclclcclckaclccccccccclccccccccciiciciiciiciiciiiiii`ic`ii`ii`ii`````i`iiiiiiiiciiciiiiiiiiiiic`ibiiciiiiiiiiicicicicccicicicciciccccicccciiicccciccciccciiiiiiiiciccii`cicbicciccciiciclcccccccclcclcccccllcclllliclclcccccclcclcllclcccclcllclclccllc`lllcllcll`llllllcllllllilllllllclcclc", +"jjjjjjjljjjlijjjjjjjjljjjjjjjjljjjjjlljjjjljjljljljajljljlljlljcljjlllllljlljijjlllllllllllllllcjcllllaclclllllcccclccclllccclcccccccccccccccccii``a`cccciciciiiiic`i`baba`iiii`ii```ii`ii`iiiiiiiiicciiccciciiiic`ia`iccii`c`iiciciccccccccbcccccic`iciciiiiccciccicicccccccccciiiiciccccccciccccccccccciicii`a``icccccccilclclciaa`iiccciclllcllclcllcllcccllllclllcllllclclcllllamiccaclllllccllllccllclcllcl", +"ljjjjjjjjljjjjjjjjljljnjjljljljjljllcjljjjljjjlbjllblljljjjljlcljclljlljlljclikllljlllllllllllllcljclccccccccllclllllcccccclcclcccciccciccciabbkakbnaccici`iciiiiiiic`bbnnnnkbaa``iiii`ciiiiicici``ic``ciiiaiiiiiiiciiciciiiiiiicccciciciiccbcciiccccccciccciicicicicccccccccicccicccccccliccicliiccccici```iabkbaccccccccclccclciammnbbbaaicclcclclclclllllllllllclllllclllllllllccijlakillcllllllclllllllcjcll", +"jjljjjjjjljjjjjljjjjjjjljjjjjjljjjjjljjjljjljljjljjijjljljl`liklljljllllllillljlllllllllllllllllllclllccccllccclcccccllcclcclccccccccciii`abnnbknmnmblciiibiiciicik`i`nbkmnmmnmnnk``i`niiiiciiiiciicccicccibciciiiciciccciciiciccicicccccccciccccccicc`ccccicibfcccccccicccccccccccccccclc`cclcclcci`abbbbaii`nnk`ccccccclllc`cciiknnnnbbakbkkicllclllclclllllclclllcllllclllllllllllclccllcllllllllkalllcljclll", +"jljjljjjjjljjjliljjljjjjjcljjjjjjljljljljlljjjljljljlljlljlijblljljlljljllcjllllllliklllllllllcllllclccccccclclcccclccclccclcccclccciiaa`babnmnnmnnmkjiiccacciiiiiiiiakkknmmmmmnmnkkbbaiibciiccciciiccccccccccciciicicciccccccciicccccccccccciiiilicicccccccciiiilcccccci`ailciclcccclcccckbcllclciabbkkb`icianmnkcccclllclccccii`ammmnbabknkkaa`iillclllcjcclllllcllli`lllllllllclclllclllllllllllllljcllclllll", +"jjjljjljlljljjjljjjjjjljcejjlljlljjjjjjjjjjjjlljjljljljljljllkijlllllllcjkllllcllllcallllllllllllclcclilcclclclcllcccllccccccccccc`bk```baabnmnmmmfmklciiciiiiiciiciiakbbknnmnmnnnkbbbbaknicciiiicccciiiccicciccccciicciiccicccccccccccccccccccccicililccccccciiccicccccciiclcclcccclilclliclccli`abbbnkkacciaknmkllllllclllcccii`amnnnnbbakbk`i`aaa`ccicclllcclcljclllclllllllllllllclllccllcllcjcj`alllllllcll", +"jjjjljljljjjjjjjjljljjjjljjjjljjjjlllljlljjlljjlljljljlllllljilljllljlciacjlljb`llllclllcllllcclclllccciccclclcccclcccccclccllc`aabnkii`bbabbnnnnnmnbljiiiciiiiii`i`i`kkkbknmmmnmnnbbknkak`iccccicicccccccccccccicccccibccccccclcciccccccccccccciciicni`ccccccccccccccclcclccclcclacclcclclliiciabbbbbbnb`cc`bkknnlllllclcllccc`iiamnknnnkaaknaiiabbabbkkcccclccjcclllllllllllllllillllllcllcccllllccelllccclicl", +"jljjjjjljjjljljljjjjjjljjjjjljbjljjjjjjljjljjlljjljljlljljjljljlllllljlllclllcjllllllllllllcllllll`ccilicccclclc`illcccccccci`bnbaakk``abbb``knbnmmkbllciii`i`i`i`i``akbbbbkmmnnnnbbkkkabnmnb`icccccccciccccccccccccccc`ccccccccciicccccccccccciccccciilcccccccclcclclclcclcclccclicllcllcc`aiiabbbkkbakacl`bnnknklccllllcclciiii`bmnknmmbaabka``akaaaakkicllclccibclllllllllllllc`lllllllcllcllllllcjlccclcc`ll", +"jjjjljljjjjjjjjjljjljjjljlljjjljljljljljljlljljlljllljlljlcjllllllllllllljcjllmclllljcllllccllllcclcccccclcccccccccclccccciibnmmaaabbbbbbbb``bmbbnmnbljc`ii`ib`iikb``bnkbabbknmmmkbnnkbbbkmmkkaccccccccccccccccccccccclccccclccclcicccclclccclciic`lccciccccccccclclilccclcclcllcllllc`cc`abaliabkkkkkabiciabnmnfnlllllcllllii`i`i`nkbbmmnbbabaakbbba`iknbbbciclcl`llljcllllllllllllllllllllcllllclljclcclllclll", +"jljjjjjjljjljljjjjjjlljjljjljjjljjjljljliljljljljlljlljllllllljljljllllllllcllallllclllllcbkbaclcciillclcccccccclcccccccciaaaknknbai`bbbbbbb`bmnkmnnalliii`i`aiii`ii``bbbbbbnmmnmmbkkkbbbbnmnnnbaiccccccccccccccccclcccillcccclclccllcclcclclccccclciliccclclclcclclcllclcclclcllcilclbaabb`icaakbbknkbaii`abknmnbclllccllllii`iiiibabbbkkkaa`abbbbkbaaknnkmnalclllclclllllllllllljllllllllccllclljlclclllclclll", +"jjjljjjjjjljjljljlljjjljlicjljlllljljli`cccjl`cjljlljlllljllllllllllllllljcjlllllllllllllliclclclcmbclicccccccclccccccci`bkbbbbbbaaaabbkbbbbabnmfnbacljici`iiii`ici`iiiaabbbkmmnmnbbbababbnnmknnkbiclc`acccccccclccccclccclccclcllclccccccclccccccicllciccccccccllcclilccllclclclcjccababbicc`bbbbbkknbac`ababbaicllllllllllcii`i`iiiababbbaaaabbbkabbabnnnmmfna`acclclllllllllllllllllllllllllclcalllllclclllll", +"jjjjjjljjljjjjjl`ailjljjjljjljjljlc`aabkbaba`aiclljllljljcb`ljlllllllllllclllclillllclllllcllclcililclkclcccccccccccccannbabbbbaaaabbbbkkkkbbkmnbiljlllciiiiic`i`i`iiillcakbbknfnkbbnbkbabbkmnnnknnbilccccclccccccccclcaacllcllccclclllcllclccccclclccccccccclllcclclbclclllcllllccl`aaabaicabkkbbkkknka``bkbbilljlllllllllcciiaaijlljcabaaaaaabbbkkkbbknmnnmnnmbillccjlllllllllljlllcllllllllllllllllclllccllll", +"jljljljjljjlljljcjljjljljjlljljc`bbknnkkkkkkkbbbbbcjllljllllllllllllljlllllllllcclllclllllclllcacclcccclcliliclcclcc`mfnnmkbkkbaai`a`aakmkkbikmmlllljllciiii`iiii`iin`iljcbbdbnmnbbbmknnkaaakmkmmnbbbilclclclclcclclk`abilcaclclcllclcclicccccclillcccclilccclclllclllclllcclllcllibbbaaailiakkkkbbnkkk`bbbaballllcllllllcllci`a`lljlllcba`c`a`aakmbkbabmmnnmnnmbacllccllllljllllllllbjlljljllllllclllllllclllll", +"jljjjljljjljjljjljljljjjjljjlc`akkkkbkmmnnmnkbkkbkb`cjjllllllllllllllcllllllclacjcllllflclllclc`cclliiicclccclciaciabkkmnmmkkka`cc`a`akbnkkb`knkjllljlll``iiii`aiiiiicccllakkkkkkbbbnnmnmkaabnmnkbbkkbiccccliacllillilccccllli`llllcllllcccclllcailllllcllclcclcclccllllclllllllliabka`i`clibbkknbbkknkbkkbbbillllllllllllllc```llllljjlb`cci``abbknkbianmnnmmnnnallilllljllllcjllljllllllcllllllllllcllllllijjl", +"ljljjjjjljjljjljljjjjjlljljjibbkmnnkknnfffmnnknnnkbaa`clllllllllllllllllclilllllcccllclclcllccccccclcccccccclcic`cannbbmnnmnbaiiii``akkdknkaabmblljllllciiiabknmniiiiiijljannkkkbbbkkmmnmk``bbkkbbkkkkkaclcclclclclcllclbilcclllillllccllccclclcclcliccll`llilcclllllllclllllllliabba````ccabbbkknbbkkbknkbbbiljcljcljcbnkbabballlljlllc`iii`a`bkbbknbabnnnnmnnnnalcicilllllljllllllljclljljllljljjclllllllla`ll", +"llljljljjljjljljjlj`ljljljlikbbmnfnnmmnfffmnmnmmmkkbkbiiljlllllllllllllciaiclcllllllclcllclccccclcccclcclaclcilc``bknnbkmnnnka`bba`adbkbbkbaabmkcljllllciicbnmnnkiiiiicljcanmnmnkkbbkmnnn`ibbabbbknkabknbclclllclllcllclcllllllcllcclllllilllilllllliclllllcjliccllclllclclllccci`aa`i`aii`bnkbkkkbabaakbnnkkacllllllc`knmkbbbbljjjjjlj``abba``bkkabkaaaknmnmnnnbacli`acllljllllljlllllllllljlbblljllljcllclabll", +"jljljljljjljljjljjl`jjljjcabkkbefmmfnfefefffmffmfmfnkkbaillllljlllllcllll`llllllajiclllclcccccclcclcccccc`lciccakbbbknkbnnnmnnnnbaabbbbkbb`iadmmaclllllcclcaknkmmkiiiiicc`knkmmmbkbnnnnnbi`bkbbkbkbbbaakkaiclcclclllcclllcclllllllllllcll`ill`cllcllcllcikllillc`cccclclllllcciii`aa``iii`akkkkbaaaaiakkbknknkaallllcabkknnkabkallllllibkmka`aaabkbbai`akmmnmnnmballcibbillcljllllljlljljlllljcjlllljlllcjlllljl", +"jlljljjjjljljjljlljljlajl`bkkkkmffffffeffefffmmfffmmnmkbbillllllllllllllcjcllclllilllilclcccccccllclcccccccclcakmnbbbbbkbkmnnmmbabnkbbbkk`cc`bmmmb`ciia`iii`aabnnmaa`c`abkknmnmmbbknmmnkbiababbbaba`ba`aakk`clclllllciccllllcllclllllllllclllllllllclllclllllllliclclcclcclli`aaaaaa`iclc`bbnnkbaiiiibnbnbbknkbb`ccci`knnknnkbbbb`cjjikfmnbabnnbakkk`li`knmnmnnnb`icccaabclilljll`llllllllljllcljlljlljlllllljal", +"ljljjllljljjljljjjljlabliakknmknmfffefmffefefffffffffnmkkailllllllllllialclcllilcllc`jicccccicccccccclcccciccbnnknnkbbkbbknnnmnbbkmmnkbbbiccabnnmmnknkb`ccii`abmnbbbmknnmmnmmmnmkbkkfmnkaa`aabaaa``ia`akbbkkacllccllliillllllllljiaaillclllclllcclllllllllllllclclllllcllcciaaabkbb`iicciabbkkba`iiiaknbmkbbkkbabknbabnknkknmkkbkabbkmnknnabnmmkbbbbiliabnmmnnnnbbaicii`akallllljilljjllllicljjlljljcljljllllcbl", +"jljllllcjjljljljlljlljllbbnnmmffffeffeefeefefeeffmmefmmknkbclllllllclllclllclclccccccicccicccclcccccccccclccbnmnnnnmmnbbbbbmnnkknmnnfnbb`i`aabnmmmmnnnbaiii`abbkkbkkknkmmfkmnmmmnkkknnmnaaabkkbaaiii`bknbkbkbcllclclclblllclllllllllllllclllllllcjllclcllllllllllllllllllliabbaaaaa````a`abbkba`a```abbknnkbbbkknkkk`bnmnmnnknnmkbkbabnmnnbnmknfnka`iiaabnmmmnnnnbaci``aabkaljllljlljcljllljllllljlliljlljlljjll", +"llljljjjljljjljljljjljc`bkbmnfffefeeeefeefeefffeefffmmnnmnkaclllclllclllllclccccccclccccccciccccccliccclbccanmnmmmnknmnbkbbkmnnnnfmmnmnbi`abbaknmnmnnkb``iai`aa`aabknmmnmnnnmnmmmbkbkfnnkbakmnabaabaabnakbbkbbilllllllllllllllllllllllllllllllllllcjallllllllllllllllllllinkbabbba`iaaaa`akbb``````abbbbkfmbabnmmnbakknmmnmnmnnnmkbbbbknnnnnnnmnnmbiiabbakknmmnnkb`````iaa`ailjlljljlljlljlljljlllljljljiclllljl", +"jljljljljljljljljjllljlbknkfnffffefeeeeefeeeeefeeeefffmmnkkbillllllllllclijcclclclccclclccccccccicinacciiibnmmnnnmnnnmnkbkbamnkmnmmnmmnabdaabbbbmmnnnba``iaii``ii`bnknmnnmnmmmmnnkkbbknmmkbknnbkkbbbabnbbkkbbnaclllllllllllllllllllllllclllllllllllcllllccclllllliclllllikfkbaaaaa``aba```baa`a`aaaabbbbkmnnknmnnkbbknnnnmmmnnnnnnnkbbbknnnnmmmnnnabaaakabbnnmnnba`````c``i`iicjlllljllllljllllijjcjlllllcjjjllj", +"lljljjljljljljljlcjjllkbknmfnffffeeefeeeeeeeeeefeeefffffmnkkbclllllcl`llllccccklllclclcclcccclcccccilccccbmmnmmnmnmnnnmmkkbbnnnbknmmnmkkmkaabbbaknnkkbaa```c``iiiabkbmmmmnmnnnnmmmkkkkknmnbnmkbkkkaa`bbbbbkkbnkacllljcllllllllllllllllllllllllllllllallllllllllll`cjlljlabkbab`aaa`iaba``abaaaa`aabkkkkkknnnmmnkbabnnnnnnmnnnmnknmnmkbbbnkkbnnnnnkbnnabbbbbbnnnkkaaiii`iaiciaailjjlll`bialjlljjclljljajjljjlljll", +"jlljjljljjljlljlcjllljanbmmfnffefeefefeeeeeeeeeeeeeeeeffmfnnk`clcllllaclllcclllclcllccciclcccccccccclicc`mmnnnmmnmnnnknmfbbbbdba`abbdbabkaaaabkbbnnnkbaa``ic`iiiaaabbmnbkkbbdbbkbbabkknmnmkmnnabkkbabbkbkbnkkkbb`llcjllllllllllljllllllllllllllllljlllclllljlllljlllcjl`kbbbbbaaaa```a```abaab`ii``aabbabbbbbkkai`bmnnmmmbbkbkmnnnnmka`aaa``aabbbbaknbabbkbbknmkb``a`ii``iiiaaacllijlcklllbljlljljlljijlljla`ljj", +"ljjllljljljljlljljjljibbknffmfeffeeeeeeeeeeeeeeeeeefeffemfmnkbclllcllclcicbcclillccccclcccccccccclcciclinmnnmnmnnnmmnnnnnnkaai``lllllcllllcllc`abknmnac`i`clclliaaaabnalllclclcclcllcc`kmmnnnkbbbkbkknkknkkkbbaa`iccclljlllljllllljllllljllllllllacljljlllllllllljllcliabnnbaaabbaa``````aababllllllcllllcllcciii`bnnnnnncllllnnnnnnnilcllllllcllllciadkbkkbbnnnb`i``iciilc`aaaaclealljllcecllljjjljljjljljjjjll", +"jjljljjjlljljljlljllclbbmnmffeefeeeeeeeeeeeeeeeeeeeeefefffmkkb`lclcllllclicciclccclccllccccccccccicccciknmnnmnnmmnnnmnnnkmnbiia`lllllllllllllllliaknnb`i`aclllli``i`abilllllllljllllllliknnnnkbbbbbbknnnkknkbkaiiaillljlllllllljlljlllllllljllllcjjlllcllllllljlllljlcabbbba`babbba```iaaaakkbllllllllllllllclicadkmnmnknlllllmmmnnnmijlllllllllllllccibbkkkkbknna`i```icli``i`aaclljjljljlljjlllljljlljjllllllj", +"ljljljllljljljlljifccibbmmfffeffeefeeeeeeeeeeeeeeeefefeffffnknaccclccclcccicclcllllclcccccccccccccccccanmnnnknnmnnmnmmmnnnnbi`nilllcllllllllllllliabbkb`aacllll```iiabillllllcllllllllllibnmnnbabbbknnnnnnknbkaiib`ijljcljlljljllllcljcljlllljll`cjlcjjlljllljlllllllibbka``bbbkbba`i``abbbknbcclclllllllclllllladnnnmnnncllllnnnnnnnallllllllllllllllc`bkknbbakbbaaaaaiiii```ciaalllllljljljljjjl`jljllljjjjjjl", +"ljljljl`llljlljljlcclaakmnfffffeeeeeeeeeeeeeeeeeeeeefefefffmnnacccccllccilcclclccci`cclccccccccccccccinknnmkkmmknnnnnmmmmnbaaakicclc``ai````illlllibbaabaalcllc`aai`abilllciada```aicllllannnmkbbbknnkkkkkbnbk````aklllllljlllllljlillijllljlllljlllllcjlljllllljljllbknbaa`kkbbkbai``abbbbbnbilclcccici`icccccllaknnnkkn`lclcknnfnmndlllc`````aaaaccclldbnnbbbabbaaaa`a`ai`aaiibb`jlljljllljljlll`ljljjjjjlljlj", +"jjljjljcjljlljlllllllcbnnmneemefeeeeeeeeeeeeeeeeeeeeefeeffmmnbbiccciccccccclcclcccccccccliclicccccicibknnnnnnnnnmnnnnnnmmkabbbbiliclnmmkkkbbkalcclcbbbbaaallllc`ab``abcllllaknffnnnkalllllnkmnbkbbkkknnkkkkkbb```i`alljllllljlljlllilljlljllljlljlllljllljlljljlllljakbkkkaabnmbababbbbkbbbbkacllccciiii``aablllccnkknnnkillcldnnnmnmblllc`kkkknmmnblcillbnnkbbbbabba```aaaaaaa`aabcjlljljljlljljjljjjljlljjjljj", +"lljlljljlljljlljlllllibnkmnmffefefeeeeeeeeeeeeeeeeeeefffeffmmkkaccccclcillcllclclccccccci`icicccciciakkbknkknnnnnknnnnmnnbadbkkilclcnnmkkbbkkbllllcabbkabblcllcaabaabkilcclakknnnkbkbcilllkbbbbbbbbkbkkbkkbbbaa`iaaaallljjllljljljlclljlllljlllllljljljlbcjllljljjj`nnkbknbbabkbaabkbkkbbbbbbalcllcciabb``bnnilclckkknkkniccccannnnnnalllc`bbbbnnmmnillcldbdnkdabbbbaaaabaabab`aabb`ljlljljljljljljljljjljjljljl", +"jjljllljljllllccjcljlcbmknnnfefeefeeeeeeeeeeeeeeeeeeeefffemmnkk`cclccli`clbcblilccccccccciccccciial`kkkkknkknnnnnkknnmnnbdaabbkclllcknmnkbkmn`cclliaabbbbbcllclabkdaabilllcbkkkmnkakaliilibbbakbbkbkkbbkkbkkba``ibbaailllljlllllllllljlljljlljljlllillllljlljlljllcaknnbbkkbaaa``abkkkkbbabaa`cllcci`abkkabkkclllcbkknkknilllcannnnnk`clcc`bkbabmnnkllccldkkbkb`abbbbbkbbbbbbbbaabknajljlljljljljljljjljljllljll", +"ljlljjjljljljlccjlllccamnnnnfemeefeeeeeeeeeeeeeeeeeeeeffmffmfnbacclclllillil`cclcclccccclccccciia`canbkknnnnmnnnmnnknnmkkiidnbbclccl`aa``i``illclc`abbbkkbcllllbbkb``b`llcl````a`a`illicl`bbbbkkabbbbbabbbbkb``i``aaaalljlljjljjljljllljljlljllljlcalljlljllljlibjcbkmkmkbab``iiabbbkbbkbabbaailllcci``iii`icllcl`kkknnnm`cllcannnnnb`lllli```i`ab`ccllccnfnnkdbabbbbkkbakbabkbaiabnkijjljljljljljljjljljlllljlj", +"lljlljcjlljlljclclljclamnnknnenefeeeeeeeeeeeeeeeeeeeeefemffmmnb`clcllcllcclccclicccccccccccccciiicinnkknknmnnnnnmnmnnnnkbcc`mnklccllllcllllclccll`kkkkbbkkclclcbbkbaabillclcclllclllllllidbbkbnkbkbbkkbkbbkbaii`aiabbklljlllljlljlllljljlljljljlljlcjljllljjjljljlbbannnmba`ii`akbbbbbbbbbkaad`lllclllllllcljlllidmkbnnmn`cllcannnnnb`llccclllllllccllcldkmmnnmkkbbbbkbbbbbbbbbb`babkaljljljljjljljjljllljljljjl", +"jjljlljljllljllljjcc`l`bnmnnkeffefeeeeeeeeeeeeeeeefeeeeemffnnnb`llclccccclccclciclccccccccicccciccknknkkknnkkkbknnnmnmnka``dnkkllclccllllllcllll`kmnkkbkkkclcllbkabbabclllllllllljlllllibkkabbnkknkbbbbabbkbai`aa`abkkbjljljljljljljljljljljljljljjlljljjlljlicjliakkkmnnkkacc`kkkkbbaababnkabalccclllllcllllllcdnnkkmnkkallll`nnnnnballiclllllllllllll`akkkmmnnkkbkkbbbabbabbbabbbbmnclljljljljljjljljljljljjjj", +"alljaklllljlllllllllllibknmnneefefeeeeeeeeeeeeeeeeefeeeffmfnmkbicccllclllclcliibcccccccciciiiiiic`nmnnnknnnbbbbkkknknmnkbbkkkbdccclcccllcijcjlcbnmnmnbbkbklllllbkbabbbilcclclllllcllc``kknnbbbkknmnbkkbabbbaa`aaabbabkncljlljjljllljljljljljlljljljljlllljljljjllkbbaannkknac`bkkkkkbbbbbknkbb`lclllllllllcllcibnmnkkmkkb`ccccannnmkbkllllclllllcllllidkbbknnnnnnkkbkkkbbbbbbbbaabbkmmaljjljjljjljljljljjjjjljjl", +"ljjl`ajljlllljlljllllliinbmnmmefefeeeeeeeeeeeeeeeeeeeeffmnmnnkblclccclccclilillccccccciciciiiicccamnmnknmnkbknnnkbbkkmmknmnmkballclc`aacl`ccibknnmnnmnkbbkclcclkbbbbab`lllc```aaab`iakkkbnmnkbbkkknbbkkbkbaii`babbbbakb`jlaaljllljljljjljljljljljljljljjjlljjljj`nkbbabkknk`cbkkbbkkbbabnkbbbb`lcllcaailllll`bbmmmknnnkkballlcibkkmnnmllclci`iiaaabbkknkbkbnnnnnnnnbbbbbbbbbkabbabkmnmmcljljljjljjljlljljljljjjj", +"lllljljlllbllljllllllllcaknknmffeffeeeeeeeeeeeefeefeefemmfnnnkacclccclclcccccccccccccccccciii`ciabnmmmnnnnbknnmnmmnkkkknnnmkdballcclbmn`llcll`nknmnknkmnbdlcllcbkbbbbk`lcllkkkknnmnkbbknbnknkbkbnkbbbkbakkaiabaabbbbbbabjljcljljlljjljljljljjlljljljljljljjljjclannbbaanbkacikmnkkbbkkbbnnnkbaacclcibbbilcclcaknmnmknmkbbklllccmkkbnkmclclcai``abbnnknnnkbkkknnnnnknkkbbbbbabkbbkbknmmkaljjlljjjlllljjjjjljjajlj", +"jljljccjllljllllljllilll`bbnmmfffefefeeeeeeeeeeeefffefenmfmnkbiclccclcccccccccccccccccccciiiiiii`bbknnnnknbbmnmnnnnnnkkkmnkaad`lcllcbkmk`cllll`knmnmnknnnkllllinbbkmnn`clllbnkknknnnkkkkbknnnkbbkkkbkb`iaba`abbbbbknnbbbllilljllljljljljjljjljljljljljjljjlljia`bnkbb`akab`aaknnnnbkbbaabnnbbbdllliibbbailllclabnnnmkbkkbkclcccmnnkkkniclcl`i`akbbknknknnbbkknnmnkknnkbbbabbkbbnknnnnmnnljljjjljljljljljjjjljjlj", +"klljljjclljlljllllll`cllcakbmmmfefmffeeeeeeeeeeeeefeeffmmfnnbailclccccclccccccccccccccccciiici`iabbbbkkbkkbnmnnknmnnnnnkkkbdab`lcccibknkn`clillakmnnmnkkmkllccinmnknmncjcccknnkkknmmnnbbkbnknnbbbkbabaciaaaabaabaknmnnbbilijljljlljjljjljljjljljjljjljljljjjljjaknkbbaaba``bknnnmnkkbbabbknkbbblllccbbbbailllcc`bkbkkbkbkklclccnnmnnknillcc`c`abbbknnnnnmkbkkknnnnnnnnnkmkbkmnknnmnknnmm`lljjjljjljljjjjljjcjljj", +"ljlllllljlcljcllllllillll`bbkkmmfffffefffeeeeefeeefefffmmmnkb`ccacclcliccclccccccccicciciiciciaibbbkbkbbakbmmbnnnknnnnnnkkkbbaiclllcbnmknncllllldmfknmnknkllllikbknnnniilllknnkkknnnmmnbkbnknnkkabbbaccaaaaabbabknnnnnnkallljjljjljljjljjljjlljljjjjljjljjjljlcbknkkkbbda`aknnnnnmnkbbbbbbbkbbalcclcknkkbaicllil`bkbbbkdmnlllclnknnnnk`llclii`bbabknkkknnbbbkknnnmnnknnnnnnkbkkknnknnmkkbjjjljjjljljljljjjanjjjj", +"llmjjljllllllilljlllllllllikbbnmmmfffffefeeeeffeefffmffmmnkbaicclcccccclccccccccccccccciiiiicc``bbkkknkbakbnnknknnkkknnnmnbbbaclcccibnmnmnncllclldmnnmnnnnllclckkkbkmmilllcknnnnbkknmfnnbkknkknnkabaic`bbbabbbbknmnknnnnkljjljljljjjljjljjljjijljljljljjjlljjj`ikkkbnkbaaadnnnkknmmkbbbbbbbkbballlclbbbbbabclllcidnkbbbbnmlccilnkkkknn`llccciabaabnmnnkmnnbbbbnknmmnkkkknmnkbbkbbnnnmnnnflljjljajljljjjjjljjjjjj", +"illllllllljllclllllllclllll`bbkmnmmfefeffeffefefmeffmffmknkaiclcclclcccccccccccccccicciciicici`aabbbkknkbabknnnkkkknkkkkkknkb`clcllibknnnmkkcllllcdkmfmnnkllllcbbbbabbclcllknnnnkkknnmnbbkkmnknnnkb`c`bbkbbbbbbbknnnnmnknlljljjljjljjljjljjljcjjjjjjjjljljjjllibkkkknnbaabknmnkkkkknkbkkkbbkknklcclcbkbbakdbilllliakkbabkncllllnnnkknkalllliiaaabbbnnnknmnkbbbkbknmmnkkknkbbkbbaabbknnkkniljjjjljjjljljjjjjljjlj", +"lcljlljlllllljlllllllclllillabbnknmmfmfffffffffffmefmnnnkkaicclcilccbcccccccccicciccciciiciiii`babbbbbbkkakkkmnnknkkkkkkknmnda`clllibbbbbakbacllcl`knmnnnklllc`nmb``bbcllclknnnnnnkknnkbbbknnkknnmna`bbbkbbbbbabkknnnnnnncjjjjjjjljjjjjljjljjjljjljljljljjljjj`anknnmnbbabknmmnnkabnnknmkkbaknkcllllbbkbbakaaillclibkbbbbkiclcckkkknkkaclll`bbkkbaabbkabkbbbabbkkbnmmnnkknmmkkkb`abbkkkbkbjjlljjjljljjjjjjjjjljj", +"cbjcjllljlllllllllllcllllllclcbbkkmnmnffffffemmmfnmnmknkkbiccccclccliclcccccccciccciccciiiiciciabaabaaabkbnkknnnkkkkknnnknkdakndbkbabbbbbnbkbbaaa`bkbkmfnmbkkbbnna`ammakaaamnnnkkkkkknnkkakknkkkkmnaabakkbbabbbkknnnnnnmkajjljljjjjljljjjjjjljiljjjjjjjjjljjcccknknknnbbdknnnmmnbbbknmmnnnkkbbbabababbbbbkkkbaaa`aiabakdnkdbdbbkbkkkkkkab``bnnnnbkbbbbbbkbkkbbabbbbnnmknnmknmmm``bnmkbkbknjjjjljjjljljljjljjj`jj", +"lljljlllllllllllllcllllllllllc`abbkknkmfmmfmfknfmmnnnkkba`cclliliccccncccccciicciccciciciiiiii`bbkbaaabbkbnnbkmkkkkkkbkbkkd`bknknnmnkabbnbkkbknbbbbbbbknmnnnnmnbkiannmnnnknnmnnkkkkkkkknnkkknnkknnnbbabbbkbbbbnkbknnmmmmnbcjjjjjjjljjjjlj`jjjlljjjjllljljljlliiknnnnnnkkbkknknfnkknknnnmmnmnmkkbbknkbaabbnknkbbbbaa`bbkbnkbkmnkkkkbbkbkkaabmkknnnnbbakkbkkkkkbakbbbdbmmnmkmnkbbcdnnmnknbkma`ijjjjjjljjjjljjjjljj", +"ljcbaljllllllllllclllllllclcllcci`bbnbkbnknnmkknkkmkkba`ilccilcclcicl`cccciclcliccicicic`icici`nkkkbaabbkbknkbkfnnkkbbkkbbaannknnnnnnbkbkmkknnkkabaaabbbknnnnmfnk`annnmmnnnnnmnnknnknkknnkkknnnkkkkkkbabkkbbbbbkkknmmnmmfkjjljjlljjjlcljjljjjljjljljjjljjlljii`nknnnmmkbbbbnnnmnknknknnnnnmnmnnnkkkkkbaabkmmnbbnbbaabbkbkkkkknkkkkbkkkkdabknknnnnnnbbbkkkbkkkkbaadbbbkknkkmmfkkibnknnnnknmajjjljjljljljjjjjjjjjj", +"lljci`cjlllllllllclllllllllccllllc``bbkkkkknknnkbnkba`icccccc`ccccccclcccccccaciciciciciiiiiiiankkmkbbbbbkbbkbbknnnnnkkkbaaknkknnnmmmkbbbnkbknkkbbabbbbbbkmmnmmmb`kmknnnmnknknnnkknnnnknknnkkknnnnkkmnkbbbbbkbbnnkkmmnnnnmjc`ljjjjjjjljjjjlj`jljjjljljjlljlj`c`nnknnnmkbbaabkbbknmnnknknnnnnmnmmnkbnkbbbkbnmnnknnkbbbbbbbkkbknnnnknkbkk`akkkknknnmnnbbknkbkkkkbaaabbabbknmnnmnk`kkknnnnnnbillljjljjjljjjjjjjjljj", +"jlljcillllllllllclclllllcllllcccclcliiaabbbbbkbabaaiiiiccccccacccclciciccccciaiccicicicici`iiibnnkfnknbbbkaaknkbnnnmnnnkkbknnnkknnnnmkbbbbkbbkkbaaabbbbbbknmnknkbbknnnnnmnnnnnmmnnknknkkkmnnbkknkkkknnkbbbbkknbkkkknnnkknfjjjjjljjlljjjjljjj`jjljljjlljijjjjccaknnkkknnkb`iaabknnmnnnnknnnnnnnnnmnbkkkabkbknmnkkfnkkkbbbabbbbbknnmnnknkaknknnkknnmnnbbbbkabkbbbadaabbaabnmnknkkaknnnnnnnnfkljcjljljljjjjjjjjjjjj", +"llllcjllllllcllllclllclclclclclcccclclcliiiai``icccccccccccibcccccccccccciciiiiciciciciciiiciinmnkmmnmkkbbbbbabbnnnmknnnkkknknnnnnnnnkkbabbbbkka`aabbbbbabnnnnkknnkmnnmmnmnnmmmnmmnnkkkknnnmkbkknnknnnnnkkkkbmmkkkkkkkkkbnjjjljjjljjjljljlljajljjjjljljjjljjjc`kmnnkknnnba```akmnnnnmnnnnknnnnnnmnkkkkbbkkknnnmknmmmnbbbkbbbbbknnmkknnkknknnknnnnnkkkbabbbbkkbiabbbbbbbdnnkkmbknnknnmnnmkmbjinijljljjjjjjjjjjjjj", +"llljllllllllllllccclllcllclclllcllcccccccccclcccccccclcccccc`lccccicciccciccicciciciciiiiii`ickmmnmnmnbbbbbclciicccilcciliiilciccicccccclcclicllllcclcccllciiciciiciiiiicciiiicci`iiclliiiciiccciiiicciiiccccamknkkbkbkkkblljljjljjjjjjjjjjljljjlljjljjjjjjlllinmmnnnknmkaacccciiiciiiiiiiciiiciiiicccclciiicc`cciccillccclclciiciclicliicccliiciccccccclccccllllciccccliiciiiakkknnmmnmnnkciijljjjjjjjjjjjjjjjj", +"ljlcljlllllllllllclllcllllccccccccclccllcccccccccccccccccccclccccccccicccicci`iiciiiicicii`a`ikmnmmmnkbabbijjjjjjjjljljjjjjljjjjjljjjjjjjjljljjjjjjjjjljjjljjjjjjljjljjjjjjjjljjjjljjjjjljjjljjjljjjjjjjjjjjjinnnkkbbbbbkbjjjjjjlljjjjjjjjljjljljjljajjjjjjljccknnnnknnmkbacjjjjjljjjjjljjljjljjjjljjjjjjjjljjljjljjjljjjjjjjjjjjljjljjjljjjjjljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjlikkbknnmnnmkncjljjjljjjjjjjjjjjjjj", +"llllllcllllllllcclclclclccllclclclcclcccccclilccccccccccilicciccicccccciciciibiciciciiciiia``immmmnnmknnkkillljcccjljclljlllccjijljcllljljlljjljljjljlcjlllllllllcllljlcjljjljllljjlclljllilljllclljlcicjclclcknkkkkkabbbkljjjjljjjjjjjjjjjljjljjjjjjjjjjjjjjcianmnnnknmnbacjllclcjcjcjcjllllllllljllllccjlllllljljllcjjllllljlljljjljljjjjlljjjllllllllcjllljllclljjllljljjllabbbbbknknmkn`jjljjjjjjjjjjjjjjjjj", +"lllllljcllcllllccclllclcclclclclcccccccccmkcccilccccccccccccccicccciccccciciiaiiciiiiiiiciii`immmnmnnmmnnkclnmfffffffeeffmmffmmffmfffffmmffffeffemfffffmmmffffffffffffffffmmmffffffmffmmfffffmffffmffmmmmffmmkkmnnkbbnkabkjailjjjjjjjjjjjjjjjjjjjjjjjljjjjjjlcibknmknnnnmkdidkkkmnnnnmmmnkknkkkkkkkknkkkkkknknknnkkkkkkbkbknknnkkknnkkkbkkbbbbbkkbbbbbbbbnkkbbkbkbbkkkabbkbkda`dbbbbbbkbnmnljljljjjj`jljjjjjjjjj", +"jlllllcbccnnclclllklclllllcclcclcllccclcciclclciccccccicccccicaiccccciciicciciciiicicicii`ii`innmmnnnmfnmnilmffffeffffffffffffmffmmffffmmfffffffffffmfmmmmffffefffeffeffmffmmmfffmmmffffffffffffffffffmmfffffnbnnkkbbkkkbaljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjlcibbmmnknnmkka`bnknmmnnnnnnknnnkkkkkbkknnkbkkknknknnkkkkkkbbbkkkkkkkkkkknnkkkkbbbbkbbbbbkbbbkkkbbbkkkkkkbbbbkkbba`bbabbbabaknniljjjjljjjjjjjjjjjjj`", +"c`iljllllliclclclkicllicllccccccccccccccaaiciclcccciclilcicccc`cciciccciciiaiiciiiciciiiii`i``nmmnkknmmmmmilmmmfffffmmffffffmmffmfmmfffmfmmfffffemmffffmmfffffffffffffffmffmmnmffmnmmfmmfeffffffffefffmmfffffkbknnmkbbknkbljjjjjjjjjjllcjjjjjjjjjjjjjjiljjjjliibknmkknnnmnnabkkkmnmnkkknknnkkkkknkkkkknkkkbkknknnkkkkkkbbkkbkkkbkbkkkkkkbkkbbbbkbbbbbkbkkkkkkbkbkbkbkkbbbkbkba`bbbbbbaabkknbjljjjjj`jjjjjjjjijjj", +"lljlcclllllllcccclcllcllccclclcccccclccccccclciccccccciccciccaccccccicicciibiiiciiiiiii`i``i``nmnnnkknmmmnicffffffffmmmmfffmmffmffmmfffffmmmffffffmefefmfffffffnfmmmmmmmmffffffffmmmfffffffffffmefffmmffffffmnbbnnmmkbbbknjjjjjjjjjjjjjjjjjjijjjjjjjjjljjjjjliidbnmnnnknmnnaaknmnnnkkkknknnkkknkkkkbknnknkkbbkknnkkkkkkbbnkknnbbbbkbkkbbbkkkkbkkkbbbbkkkkkbkkbkbkkkbbkbkbkbkkaiabbabkkkbbbbajjjjjjjbljjjjjjjljjj", +"llllllllcjccjlcllcclalccclclaccccccccccccccccccccciccicicccicbcicicicicicic`iciiiiiiii`iii`ii`nnnnnnknmmnmccmffffffmfmfmffffmffmfffmfeffmfmmffffffmfffmmmmfffffmmmmmmmmmmffffefffffmmffffmfffffffffmmfffefffmnkbkkmmnkbbbkjjjjjjjjjjjjjjljjjjjjjjjjjjjjjjjjjci`bbkmmnkknnnn`annnnnnnnkkknkkkknkkkkkkknnknbkbkkkkkkkkkkkkbnkkkkkbkbbbbbbbbkbknnkkbkbkbkbkbbbkbbbkkkbbbkkkkkkkbbibababbkkkkba`ljjjjjjjjjjjjjjjljjj", +"llllllcllclliccclllclccllccik`lc`ccicccccclccccccccciclccicccciciciciciciiccciiiciiiiiiiii`ii`nmnkkkknnmnnlcmmmmffmfmffffffmmffmmfffefffmffmfffmmmnmmmmfmfffffmmmfmmmfmmmfffffmmffffmmfffmmfffffffmmmfffmefmnnkkbbknnnkbabjjjjjjjjjjjjjjijjjjjjjjjjjjjjjjjjjlc`kkkbknnnkmnnaakkknknknnkknnkkknkkkkknmnnkkkkkkkkkbbkbbkkkbkkkkkbkbkbbbbkbbbkbkkkbkbkbkbbbkkbkbbkkkbbbbkbbkkbbba`abbbaabknkkb`ljjjjjjjjjjjjjjjcjjj", +"cllcclllllccccclclclccllcclliccciclcccccciccciccicccicaccciciciiciciciciiciiiiiiiii`i`iiiiiiibnmkkkkkknnnmcifmfmmmmmfmmffffmfffffffeffffmffffefmmfmmffmfmfefmmmmmmfmfmmmnfmmmmnmmffffffefmfffmfffmmmmmmnmfmnmnbkbbbkknnnkbljjcjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjli`bmbbbknmkkkkbannnknkkkkkknnnknnnkkknnnnkkkknknkkkkbkbkkkbkbkkkbbbbkkbkkbbbbbbbbbbbkbkbkkkkbbkkbkbkbbbbbabbkbabb`abbbbaaabkkkbljjjjjjjjjdcjjjjjjjj", +"lccllcilclllccclllclcccccccclcclccccc`biccccccc`ccicicfiiccciiliiciciciiciiciiciiii``iii`iiiibnmmnkkknnnkklcmmmmmmmmmmmmefffffefffffmmffffmfffffnfmfffnfmfffmmmmfffmfmmmffmnmmmmmnmmfffffmfffnmfnmnmnnmmmfnmfnbkkkkkkknnnmljjljjjjjjjjjjjjjjjjjjjjjjjjljjjjjlciamkba`knnnnbb`nknkkkkkkkkknmkknmnnnkkkkkknknknknnkkkkkknkkbknbbbkkbkbbbbbbkkbbbbbbbbbbbkkkbakkbbbbbbabbababbbbb`aba`aaaabbbbbjjjjljjjjjjjjjjjjjjj", +"lclccc``cllccclclccclccclcccccccccccccccbaiccci`cicicciicciciciciciciciiiiaiiii````ii`iiii`i``nmmnnkknnmnklammffmfmmmmmmmmffffmffffffffeffffemmmmffffffmmffmmmmffmffmmmmfffmmnmmnfmmmffffffffffmmmmnmnmmmfffmmnkkkknkbkmnnjjjjjjjjljjjjjjjjjjjjjjjjjjjjjjjjjcccbnbbabbbnnknn`nnknnkkkkkkkkknnnkknnnnknkkknnkkbkbbkkkkkkkkkkbbbbkkbkbkbbbkkkbbbbbbbbbbbkkkkbkkkbbbbabbabbbkbbkbbbnbi`ii`abkbbjjjjeajjjjjjjjjjjjjj", +"ccllllcclclcclcclcllcclccccclcccccccccciciicicccilckciciiciciciciiciiicicii`i`iiii`iiiiii`ii``nnmnnnnnmnnklammfffmfmmmmmmmffmmmmffmfffmfffmffnmmmfmfmfmmnmmmmmmmmmmfmmnmmmmnmmmmmmmnnmmmefffmnmfnnnnmnnmnnffmmkbbkkkbabmnkljljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjl``abkbkbbbknnmm`knknnknkkkkkkknkkkkkkbkkkkknnnknbkbbkkkbbbbbbbkbbbbkkbkkkbbbbbbbbbbbbbbbbbbbkkkbbbkbbbbabbaabbbkbaakbiiii`aabbkcljjjjjjjjjjljjjjdkj", +"clllclclimalccllcclclcccclcccccccccccccccicccciiiciiccicciciciciiciiiiic`iakciiiiiiiiii`ii`iiakmmnnnnnnmnkjanmmfffmfmmmnmmmmmnmmmmmmmmmmfeffmmfmmffmmffmmmmmmmmmmmffmmmmmmmmmmmmmnmmmnnmmfffffmnmnmmmnmnnmffmnnbbbbbbabnmmcjjjj`jjjjjjjjjjjjjjjjjjjjjjjjjcljlii`knkbbbkkbnnn`kknnnnkkkkkbkknkbbkkkkbbkkbknnknkkbkkkkbkkkbbbbkbbbbbbkbkbbbbbbbbbbbbbbbababbkbkbbbbabbbbababbbbb``ka`icc``aabkljjjjjjjjjjjjjjjjjjj", +"lclcllcccclcllcclc`kcclcclccclcacicciliccccccccccicciciciciciciciiiciciiii`i`iiiiiii`iiaiii`iakmnmnmnnnnnblbmmfmfffmmmmmmfmmmmmffmmnmnmfmffmmmmmmfmmmffnfmmmmnmnmmmmmmmmmmmmmmnmmmmmmmnmmmmffmmmmmmmmmnnffmfmnnnbbbkkbbbbbcjjjjiljjjljjjjjjjjjjjjjjjjjjjjljjlc`aknnkkbbkbbbk`knnnnnnnkkkkkkkkkkkkkkkkkbbkbnkkkkkbkkkbkkkkbbkbbbbbbbbbbkbbkbkbbbbbbbbbbbbbkbbbkbbababbbbbbbbbkba`bb``lciaabkncjjjjjjjjjjjjjjjjjjj", +"llllllccccllcclccccciclccclc`iliccclccicicciiicccicciiciciiciiiiciiiiiii`iicii`c`iiiiii`iii``annmmnnnmnnnbjbmffffmfmmmnnmmmmmmmfmmffmmmnmmfmmfmmmmfnmfmmnmnmmmmffmnmnmmmnmmmmmmmmnnmmnmmfmknffmknnmmmnmmffffnmnnnkbbkbbba`ljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjli`annnnnkbbbb`aiknnknknkkkkkkkkkbkknkkbkbkkbkkkkbkkbkkbbbbkbbbbbbbkkkkbbbbbbbbbbbbbbbbbbbbabkbbbkbbbbbabbbakbkbbbb`kbailciankkn`jjjjjjjjjjjljjjjjjj", +"clllccllllccjcilccllnacllicanaclccn`ccikaicccciicci`cciciciciciiii`iiii`ib`iiiciiiii`iiiii`i`knmmmnmnnmmmblkffffmfmmmmmmmnmmmmmmmmmmmmmnfmfnmffmmmmfmmfmmmfnmmffffmnmmmmmnmnmmnmmmnmmmmfnffffmffmmnmnmmfffffmnnnnnkbbakn``jjjjajji`jjjjjjjjjjjjjljjjjjjjjjjjl`i`nnnnnnbka`ciinnnnnknkkkbkbbkkkkkkkbkkbkbkkkbkbbkkbbkkkkbkkkkbbbnknkbbbbbbbbbbbbbbbbbbbbbkbbbbkbbbbbbbabbbkkkkka`kb`clciannkk`jjjjjjjjjjjjjjjjjjj", +"clclcclccclicllclcccacciccciicciicacccli`cccccccicimiiciiiciiiiii`i`i`i`iicii`iii`iiii`ii`ii`knnmnnnmmnmmblkmffmfmmmmnmmnmmmmmmfmnmmnmfffmfmmfmmmmmfmffffffmmffmffmnmmmmmmmmmmmmmmmnmmfmfmmmmmffffmmmnmffmffmmnnmnnkbbknblijjljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjiiannnknkbbi`ciinnnnnkkkkkkkkkkkkkkkkkkkkbkkkkkkkkkbbkkkkkknkkkbkkkkkkbbbkbbbbbbbbbbbbbbbbbbbkkbbbkbkbbbbbbbbkbbbbibbicci`kknnnajjjjjjjjjjjjjjjjjjj", +"llcllclclcjcccclclcclcccbcccccccccicicicccciciiccccicciiciicicii`iii``iiiiiiicii`a`iii`iiiiiinnnnnmnnmnmnbjkmffmmmmmmmmmmmmmmmmmmmffffeffnmmffmmmmmmmnffmffnmffmmmmnnmmmmmmmmmmmmmmnnmmnnmmfmmmmmnmnnmmmmmmmmnmnnmnnkbbba`jijjjjjjjjjjjjjjjjjjjjjjjjjjjjljjjl`iaknmkkb`iiii``nnnkkkkkkkkkkkkkbbkkbbkknnmnkkkkkkkbkbkkbbbkkkkkkknkkkbbbbbkbbbbkbbbbbbbabbbbabkkbabbbbbabakbbbbbb`ab`````nnnkk`jjjjjjjjjjjjjjjjjjj", +"lcllccccccclclcccccccccciccccccccccccicciciccciciiciciciiciciiiiaiia`iiiiiiiiiii```i`iii`iiiikkkbmmmnmmnnalnfmmmnmmnmmmmmmmmnmmnmffmffmffffmmfmnmmmmmnmffmfmffffffmmmnnmnnmmmmmmmmmmnnnmmmmmmmnmmmmmmmnnmnnmmmnnmkmnnkabi`jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjii`nnnka`ic`a``innknkkkkkkbkkkkkkkkbkkkknkkkknkkkkbbkkbkbbbkkkkkbknbkkbbbbbbbbbbbbbbbbbbbababbkbbbbbbabbbbbabbabbbcibbai`akkmkkbjjjjjjjjjjjjjjjjjjj", +"lccllccclclccclccccccccccccicccc`ciliciccccciccccciciciciciiiii`faiii`iiiiii`ii`ii`ii`iiiiiiikmnkbmmnmmnfalkmmfmmffnmnmmmmmmmmfmffffffnmfmfmffmmmmmmmmmfmfffffffmffmmmmmmmmmmnnmnnnnmmmmnmmmmmmmmmmmmnnmnnnmmmmnnmnnnkba`ajjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj`i`nnbbaa`iaaa`inkkkkknkkkkkkkkkbkkkkkknknnbkkkkknkkkbkbbkbkkbbkkkkbkkknbbbbbbbbkbbbbbbabbbbbbbbbbbbbbbbbbabbababa``bba`aabbbnfkjjjjjjjjjjjjjjjjjjj", +"clcllclllclccclcclcccccccccclciccicccccciciiiciiciciciiciiiiii`iicciiiiiiiiiiiiiiiiiii`iiiii`nnmbbkmnmmnk`jnnmmmffmmnmnmmnmmnmfmmmfffffmfmfmffnmmmnmmmmfnfmfmfffffffmnnmmmmnmmnmmmnmnmmmmmmmmmmnmmmmmmmfnnnnnnknnfkkknn``aljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjji``nnnbbbaaabaaikknkknnkbkbkkkkkkbkknkkknnnkkkkkkkbbbbbbbkkbkkkknkknkkkkbbbbbkbbbbbbbbabbbbbbbbbbbbbbbbbbbbbbbabba`aba`abbbkbakkjjjjjjjjjjjjjjjjjjj", +"lclclccccccllccccccccccccciciccclic`cciiiciiiiciiiicicciiiiiiiciii`iiiiiiii`iii`ii`i`iii`ii`akbmnabnnnmnb`jffffmfffmmmnmmnmmmmfmfmmmffffffffffmfnmmnmmmfmffmmfffmmfmmmmmmnnmmmmmmmmnmnmnmmmmmmmnmnnnmfmmfmmmmnknnmnkknkaabjlljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjlic`bkmkbbbabbaainnnknnnkkkkbkkkkkkknkkkkkkknkknkkkkkkkbbbbbbnnkkkbnnkbbbkbbbbbbbbbbkbbbbbbbbbbbbbbbabbbabbbkbbbbbba`baaabkbnbbkbccjjjjjjjjjjjjjjjjj", +"clcccclcall`lcclccccccccccccbiciicicccicccciicciciciciiii`iiiiiiiiccii`iiiiii`ii`iiiiiiiiiciabbkbbbbmmnnn`jffmmfmfmmmmnfmmmfffffffmmmfffmfffffffffmnmnnmfffmmmffffmmmmnnmnmmfmfmnmmmmmmmmnmnnnnnmnnmmmmmmfmmmnnknknkknbbbkljjjjjjjljjjjjjjjjjjjjjjjjjjjjjjjjj`iabknnnkknnkbbinnnnnnnkkkkkkkkknnknnkkkkkkkkkkknnknnkkbkbbbnkkkbbkkkkkkbbbbbbbbkkkbkbbbbbbbbbbbbbabbabbbbbbbbbbbbaabababbbbmnkbljjjjjjjjjjjjjjjjjj", +"clclclcl`lcmcccccccccccccciikiiiii``iiicicciiccicicicii`iiiiiiiii```iiiiii`iiiiii`ii`iiiiiii`bbbbkbbmmnmmilmfnmmmmmmmmmmmmffffffffmmffmmffmmfmffmmmmmmmffmfnmmffffmmmmnnmmmffmmmmnmmmmmmmnmnmnmmmfffnnnnmnnmmnnkkknnkkbkbkljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjji``mnkkknnmmkbbiknnnkkkknnkkkknknnnnnnnkkkkkkknkkkkkkkkbkbkbkbkkbbbkkbkbkbbbbbbkbkkbbbbbbbbbbbbbabbbbbbbbbbbabbabba`b`bkkkkabmmbljjjjjjjjjjjjjjjjjj", +"clcccllclcikcc`cccccccciiciib`iiiiabibiiiiiiciiiiiiiiiiiiiiiiiiiiiiciiiiiiii`i`iiiiiiiiiiiic`kbkbbbbnmnnmicmfffmmmfmfmnmfmmfffffmmmmffmffffmmnmmmmmmffmmmmmnmfffnmmmmfffmffffmnmmmmmmmnnmmnmmmmmmffmmnmmnmmnmnnnkkknkkdbbkljjjjjjjjjjljjjjjjjjjjjjjjjjjjjjjjji``mnkbbkknkkbaiknnnkbkknkkkknkknnknkkkkknnnknkkbkbbbkbkkkkkkkkkbbkkkbbbbkkbkbkkkbbbbbbbbbbbbbbabbkbbbkbbbbabababaaiiibknnkkknnnijjjjjjjjjjjjjjjjjj", +"cclcclcclccclcnicccccciiiiiiciii`ca`iaiciiiciiiiiiiii`iiiiiiiiiiiiii`ic`i`iiiii`iii`iiiiiiii`bknbkkbbnmnnilnfffnmmmmmmmffmfffffmmfnmffffffnmfnmfmfffffmnffmmnfmmmfmmfmmmmffffmmmmmmnmnmmnmmmmmmfmnnnmmnnmnmnnkknkkbnnkbbnbljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjii`kmnkbbkkbbbbiknnnkknkkkkkknkknnnknkbkkkkkkknbkkkkkkkkknnkbkkbbbkbbbkkkbkbbbkknkbbbkbbbbbbbbbbbbkbbbbbbabbbbbabbalilbkkkknnnnmijjjjjjjjjjjjjjjjjj", +"lccclccclcccccccccccciiiiiiiiciiiiii`i`iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii`ii`iiiiiiiiiiciankbbkbbbkkmmccnfffffffmffffmmnmmmmfmmmfffffmmfffmfffmmfffmmffffffnmmfffmmmfmfffmmmnfmnmmmnmnnmffmnnnnnnnnmmnmmnnnkknnkkbkkkknljjjjajjjjjjjjjjjjjjjjjjjjjjjjjjjjjc`iknmnbbbkbbba`bnmnnnnnnnnnnnkkkkbnkbkkknkkkkknnkbkknkkkkkbkknnkkbkbkkkbkbkkbbkkbkbbkbbbbbbababkbbabbaabbbaabbbaaalccankknkbnbkajjjjjjjjjjjjjjjjjj", +"lclliclcccccccccccccciiia`ccciiicickkiiiiiiii`ii`iiiiiiiiiiiiiiiiiiiii`ii`iiii`ai`iiiiii`ii``mnkkbbbabkkklcnnffffffffefffmmnfffmffffmmmmfmfmmnmmffmnmmmffffffmmmmmmmmmffmfffffmmmmnmnnmnmmmmnnnnnnmmmnnkmmmnmnbbknnkbbknnnljjjjjjjjjjjjjjljjjjjjjjjjjjjjjjjjjia`kbnmnbbbbbkaabknnnnmnnnnnnnkkkknkkknkkknkkbkbkkkkknkkkkknnkkkknkkbbkbkbbkkkkkkkkkbbbbbbbbbbbbbbbababbbabbbbbbkbalciakkknnknkkdjjjjjjjjjjjjjjjjjj", +"cclibccaccclcccccccciiicaccciiicic`aai`iiiiiiiiiiiiiiciii`iiiiiii`i`iii`iii`ii`iiiiiiiiciccc`knknkkkbaaa`lifmfmmmfffffffmmnmmffmmfmmmmmmffmfmfffffmfmmmfmfmmnnfnfmmmmnfffffffmmmnmnmmnmmmfmnnmfmfmmfffmmmnmnmnkkbkkkabkknncjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjc``kbknmnbbknnkabnkkbnnnnmnnnnnkkknknnnnkknbknkkkbkkkkkkkkkkbkkkbbbkbkbbbkbbkkkkkbbbbbbbbbabbbbbbbakbkbkkkbabbabbbkci`akknkknkkkajjjjjjjjjjjjjjjjjj", +"cclc`lcccccccccccccciiiccciiicciicac`ii`ii`i`iiiiiiiiiiiiiiiiiii`iiii`ii`iiiiiiiiiiiiiiciiiiakkknnmnba``ij`mmmmmffffmmnmnmfmmffmfffffmmmffmmmmnmnffffmmmmfnmmmfffnmfnnffmmmmmmmmmnmnnmmfmmnnnffffmmmmmmnmnnnmnknkbabkkkbbkljjjjjjjjjjjjjjjjjjljjjjjjjjjjjjjjji`ikkkkkmmnnnfnbbnknknnnnkknkkkkkkknkkkknnnbknnkkkkbkkknknkbkkkkbbbbkkkbkbbkkkkbbbbbbbbbabbbbkkababkbkbbbbbbbbbbabki`abkkkkkknnkbjjjjjjjjjjjjjjjjjj", +"lcllccclcccccccccciiiiiccciicciiciciiiiiiii`iiiiiciiiiiiiiiiiiiiii`iiiiii`bb`iiii`iiiciiiccibnkkbknbba`cijafmmfmfffmmmnmnnmffmffffffffffffmmmmffmffffmmnmfnnmnfmfmmfnnmnmmnnnnmmmnnnmmmmmnnnfmmmnmmfffnnnmmffmknkbabbbkkkkljjjjjjjjjjjjjjjjjjjjjjjjjjjjj`ljjjca`bknkknmnmnnmbannnknkkkkknkbkkkkknnknnnknknkkkbkknkkkkkkkkbbkbbbbbkbbkkbbbbbbbbabbbbbbbbbbkbbabbbbbbbbbkbkbaabkkbaakkkkbbbkknnnjjjjjjjjjjkjjjjjlj", +"cccclcccccccccccccccciiiiciicciccici`ii`i`i`iiiiiiiiiiiiiiiiiii`iiiii`iiiiiicci`iiiiciiiiiciakkkknkaaa`i`jamfmmmmmmfmmnnfnnmffmfmfmfmmffffffffffffmmmfmmmmnmmnfmmmmfmnmnnmmmmmnnmnnmmmmnnnnmfmmnffmmfmmmnnmmmnnnmkbkbbknnbljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjji`ikkknkbkmnnkkbannkkknknnkkbkbkbkknnnnnkkknknnknknkkkkkkkkkbbbkkbbbkkbbkbbabbbbbbbbbbbabbbbbbaabkkbbkkkbkbbbbbbkbbaakkkkkkkbbbknjjjjjjjjjjjjjjjjjj", +"clcccilcccccccciiciciiicccciciicic`iii``ii`iiiiiciiiiiiiii`iii`ii`iiiiiiiiii`iiiiiiiiiiiiiiibkknnkaaaa`abjanmnnfmmmfmmnnmmnmmmmmffmmnnmmffffmmnnfmfmfffmffmffmmmmfmmnmmnmmmmmnmnnmmmfmnnnnmmmmmfmmnnnnmmnmmnmmnmmnkkkkkkkkljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjc``kbkkkbknmnkkbannkknkkkkkbkkkbkkknkkkkkbbkkknnkkkkbkknkkkkknnkkkkbbbkkbbbbbbbbbbbbbbbbbbbbbabbbbkbbbbbbabbbbbbabbaaknknkknkkbkkljjjjjjjjjjjjjjjjk", +"lcccbf`cccccciiaccccciiiiciccciiiiim`iaii`iiiciiiiiiiiiiiii`iiiiiii`i`iii`iciiiiiiii```iiiicabbbkb`iba`abjamfnnmfmmmmmmfnffmmmmnnmmmmnmfmmmmmnnnnfffmmfffnmmmfnmmmmnnnmmmmmmnmnmnnnmmnnnnmfmnmmmnnnnnnnnmmfmffmnnmmnkknbbbljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjl`ibabbkkkbnnkbkakkbkkkkknkkknkkknknkbbkkkbbkkbkkbkbbbknnkkkkkkbkkkbkbbkbbbbkbbkkbbbabbbbbbbbabbkbbakbabbabbbabbkkka`knknnmnnnbnkljjljjjjjjjjjjjjjj", +"k`ii`icclccccciccciicc`ccicicciiciicibniiiiiiiiiiiiiiii`caci`ii`i`iiiiiiiiiiiiciiciiiniiiiic`b`abaiiaaabbjbmmmmmnnnmmmfffffmfmnnmnffmnnnmmmnnnmnnmffmmmffmmffmmmnmfmmmnmmmmnnnmnfffmnnmmffmmmnmnnnnmmnmfnmmfmnnmnmmnnkkknbcjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjci`akkbkkkbbbmkkanknnkkbkkknnkknnknbbbbnknkbkbkkkbbkbbbkkknbkkbbkkkbbbkknkbbbbkbbbbbbbbkkbbabkbbbbbkbbaaabbabbbbbbbaakknnnkbknnkbijjjjjjjjjjjjjjjjj", +"ilcciccciccccccciccccii`iiiiciiciiiiiiai`iiiiiiiiiiii`ic`ii`iiaciiiiiiiiiiiciiiiii`iiaiiiccaabaab`iiaabbblkfmmfmmnmmmfmmfffmmnnmnnmmffmmffffmmmmmmmmmmmnmnmmmnnmmmnmmnnmnnnnmmnmmmnmnnmfnmmfmnnnnnnmmmmmmmmmmnnnmmnmnnnkbk`jjjjjjjjjjajjjjjjjjjjjjjjjjjjjjjjjc`iabnkkkbbbbkkk`knnnnbbkknnnnnmnbkbkkkbkknkkkknkkkbbbbkkkkbbkbkbbkbbbbbbbbbbbbbbbbbbbbbbbabbkkbkbkababbbbbkkbbbbbbb`knnnnkbbkkkkijjjjjjjjjjjjjjjjj", +"cccciciclccicliaccccciliiicciiiiiii`iiiiiiiiiiiiifkiikaiiiiii`c`iiiii`aai`c`iiiiiiiiiciiiac`bb`aacc`bbkkalkmnmfmnnnnmmmnfffnnnnmnmmmmmmmmmnmmmnmmffffmmffmmmmmmmnnnffmnmnnmmfmmmnnmmmnmmnnmnnnnnnnmnffmmnmnnmmnfmnmmnmnnkbljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjli`bbbbkkkkkbkkk`knkkkkkbbkbkbknnkbbkbbbkkkbkkkkkbkkkkkkkkkkkkkkbbkbkkbbbknbbbbbbbbkbbbbkkbbbbbbbbabbbbbbbbbkbbbbabaannnknnbbknkk`jjjjjjjjjjjjjjjjj", +"cciccicccccccciicciciiiiiciiiiiiiiiii`iiiiiiiiiiiic`iicii``ii`iiiiiiiii`iaikiiiiiiiciciiikilab`a`ciakkbk`jnmnmmmmmnmmffmmfmnnmmnnmfmnmmfmmmnmmffmmmfmfmmfmmmmmmfnnmffmnmnnknnnknmmfffmnnnnnnnmmmnmfmnmnmnnnnnnmmnmmnnnnnmkljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjic`bkbbbbkkbbnkk`kkknnnnkbnnnknnkbkbbbkknkbkknkkbkbkkkkkkkkkkkkkbkkbkbbbbkkbbbbabbbbbbbbkkkkbbbaabbbbbbbbbbbbbabbaba`knnnnmkbmmnndjjjjjjjjjjjjjjjjj", +"ccccccciccccciclcicicia`aiiiicciii`iiai`iiiiiiiic`iikb```ii`eic`iiiiiciccnicbiciiccciciciiickai``c`bnkkkajnmmmmmmnmmmfmmmmmnmmmnnmfmmmffmmnnmmfmnmmfmfmfmnmmnmmnnmfmmmfffnnmnnnmmmfffnnnnnnfffmmmmfmnnmnmfmnnnnmmnkknnnnnn`jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjlicibnnnkbbkkbnkk`nknnkkkkknnnkkkkbkbbkbnnkkbkkkkkbkkkkbbbkkkkkbbkkbbbbbbkkbkkkbbbabbabkkkkkbbbbbkkkkkbbbkbbbabbbbbbb`aaknnknkmmnnbjjjjjjjjjjjjjjjjj", +"cclicciiccccccciccciccbib`ciiiiiiiiii`iiiiiiiiii`iiia`ica`iciin`iiii`iii``cinciccicccccciccinic``aaknnkkajnmfmmnnnnnnnnnnmnnmfmmffmfmmmmnmfmmmmnmmmffffmmmmfmnmnnmffmmmnmnnnnnnmmmmmnmnnmffffmmmmfmmmmmmnmmmnmnnmnnkknnnkn`jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjiciibkmnkkkkkkkkk`nmkkbbkbbkbbbbkbbkkkkkkkknkkkkbbkbkkbbbkkkknkbkkkbkkbbbkkkkbkbbbbbbbbkbbkbababkbkbkbbbkkbbbbbbbbbbb`baabnnnkmnnkkjjjjjjjjjjjjjjjjj", +"cclcccciaicccccciic`icacaiciiii`ii`iiiiiiiiiiiiiiiii`ii`i`i`ciaiiiiiiiiciliaf`ilcciccccccicckic`abkknnnnajmmmnnmmmmnmnmnnnnnmfmmnnnmffffmffffmmnnnmmmmmmmnffmmfmnmfffmmnmmfmmmffmmnmnmmffmmmnnmnfmmmfmmmnmmnmnnnnnmkbbknmkijjjjjjjbjjjjjjjjjjjjjjjjjjjjjjjjjlciibbkknnkknbkkbikkkknknkkkkkkkkbbkkknkbkkknnnnkknkkkbbbkkkbkkkkkkbbbkbbbkkbbbbkbbbkbkkbbbbbbkkkbbbbbbbbkbbbkbbbbbbbakkbbknmnmnnnkjjjjjjjjjjjjjjjjj", +"ccccciciiiicciccccciiciiii`iiiiiiiiiii`iiiiiiiiiiii```ii`iiiiiiiiiiiiii`cicia`aiicicccccciciaca`aknkknnn`jfmmnnmmnmmmnmmnnnnmnnmmmnnmnmffffffnnnnmmmfmfmnmmfmmmmfmmmmmnmnmffmmmnnnmmmmmfnnnnmfmnmmmfmmnmmnnnnnkknmnkabkknnijjjijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjci`akkkkknnbknkkannbnkkkkkkkkkbkbknbkbkbkbbkbkkkknkbbbbbbbbkkkkbbbnkkbkknkkkbkbkkkkbbbbbbbkkbbbabbbbbbbbkkkbbbbbabbb`bnnbbknmmnnkbjjjjjjjjjjjjjjjjj", +"cccccciiicccccicicicciiiii``biiii`ii`a`iiiiiiiiiiii`iiiia`ii``iciccici`ciicci`icbicccccccici`i`aknknnnnn`jffnnfmmnmnmmmnnnmmmmmnfmmmnmmmnmmffnmnnnmnnnnfnmmfmmmfmnmmmnnnmnnnmmmmmnmmfmmfnnnnmfmmmmmnnmmfnmnnmnmkknnkbbbbkkcjjjjjjjjjjjjjjjjjjjjjjjljcljjjjjjjci`abkkkknkmbnkn`nkkkkkkkkkkknkbkkkbkkknkkbkkkkbbkmkkbbbbbbbbkbbbknkbkkbbbkbkbbbbbbkkkbakkbkkkbbaabbkbkbabbbbkbbbbbbaannnkbbnnmnnnjjjjjjjjjjjjjjjjj", +"ccccccciicicicciciaaiccc`iii`iiiiiiiii`iiiiiiiii``iiiii`aiiiaa``ciiiiiiccciciiicilcclcccccciaabkkknnnnnn`jfmnnmnmmnnmmnnnnmmmmfmnnmmfnmfnmmffmmmmnmnnnmmnnnmmnnmmmmmmfffmnmmmmmmmnmmfmmmmnnnnmmnmnnnnmnnnnnmnmmnbnnbbkkbakijjjjcljjjjjjjjjjjjjjbljcjjljjjjjjcjiaakbkkbnknnnmm`nkkkkkkkkkkkbbbkkkkkkkkbknbkkkkbbkkkkkbkbbbbbkbbbkbbbbkbkkbkbkbbbbbbbkbbbkbbkkbkabkbkbbbbabbbbabbbaabnnnnbbbknmnnljjjjjjjjjjjjjjjj", +"lciccciiciciccicciiiiiciii```i``i`iiiiiiiiiiii`iii`ii``b`iiiiiicicicciiiciccccccccicccccccciabkkknnnnnnnilnnnmnmnnnnnnnmnffmmmmmnmmfmnmffmmmfmfmnmmmnnnmmmmmnmmnnnnmnmmmnnmmmnmmmmmmmmnnmmmmfffmmmmnnmmnmmnnnnnnbkbbbkbbabcjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj``iabkbkbkkknknn`kkkkkkkkbkbkbkkknkknkkbkknbkknkkknkknbbkkbbbbbkbbbbbbbbbbkbbkkbbbkbkkbkkkbkbbabkbkbbbbbbaabkbbbbbbaaannnmnbbbkknmcjjjjjjjjjjjjjjjj", +"iiiccciiiiciciccicicccci``iiii`ii`iiiiiiiiii`iii`i`iiii`iiiiiciiiciciiiiciicccccci`ilccccccaabkknnnnnnnnclmnnmnnnnnnnnmnmfmmmnnmmmmmmnmmmmmmfmmmnnmnmnnnmmmnnmmmnnnnnnnnmnnnffmnmnmmmnnnfmmnmmmmmmmnmmffmmnmnkkknkbkkbabbbcjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjli`abkbkbkkknkkkckkbkkbkbkbkbkkknkkkkbbknkkkbkkkkknkkkbbbkbbbbbkbkkbkkbbbbbbbbbbbbbbkkbbbkbkabbkkbbbknkbkkkbbkkbbbabaamnnnnkbbabbncjjjjj`ljjjjjjjjj", +"ciicciiiiiiiciicccciiiamb`i`i````iiiiiiiii`iii`iiii`iiciiiiiiiiiiciiiiiciiiccccccciccclccli`kkmmknknknnnccmnnfnnnnnnnnmfnmfnmnnnmmmmmmnnmnmmmmmmnnnmnnnnnnnnmmmmfmnnnnnmnnnmffmmmmmmnnnnnnnnnnmmnfmmnmmfmnnnnnkkkbbkkbabbbcjjjjjbjjjjjjjjjjjjjjjjjcjjjjjjjjjjcci`bbkbbkbkkkbkckkkkkkbbbbbkkkknkkbbbbnnkkkkbkkbbkkkkkbbbbbbbbbbbbbbkkbbbbbbbbbabkkbbbbbbkbabbbbababbbbbbbabkkbbaababnnmnmnbbbbab`jjjjjijjjjjjjjjj", +"ccccciiciiiiiiiiiiciiccaiii`iiii`iiiiiiiiiii`i`i`iii`i`iiiiiiicciiciii`iiiiiciccclcclccccccaknmmmmnnnkknlcmnnmnnnnnnnnmfmfmmmnnnfmmmffmmmmnnnmnfnmnnmnmnnnnnnmmfnnnmmmnnnmmmnmmmmfmmnknnnnnnmmmfmmmnnmmmmknnnnkbabbbabaakaljjjjjjjjjjjjjjjjjjcjjjjjjjjjjjj`jjli``bkbbbkbkknkkckkkkkbkbkbbkknnknnkbbkkkkknkkkkkbbbbbkkbbbkbbbbabbbkbkbbbbbbbbbbbbkkkkkkkkbdbaabbbkbbbkkbbbbbbbabbabakmnnnkkbkkbbijjjjjjjljjjjjjjj", +"cccciciiiiiiiiiiciiab`icci`a`ic`i`iii`ii`iiiii`i`iiiicciciiicciiiccicibiiiccccccicccccclcccanmnmmmmnkkkklimnnmnnnnnnnmfffffmnnnnfnnnmffffnmnnmnmmmnmnnnmnnnmmnmmnnmffmmnmmmnnnmmfmnmmnmmmmmnnnnnmmnmmmnmnnnnknkbabkbbbabbaljjjjjjjjjjjbjjjjjjjjjjjjjjjjjjjjijliiabbkbbkkbkkkb`kkkkkkbbkbbknnnnkkkbkbkbbkknkkkkkbbbbkkbkbbbbbbbbbbbbkbbbbkbbbbbbbbbbkbkbbbbbkkbbbbbbbbbbbbbbbbabbba`bnnnnknnbkbb`jjjjjjjjjjjjjjjj", +"ccccccciiiiiiiiii`iiiiii``iiiiciiiiiii`iiiiii`i`iiiiiiiiiiiciiicciiaicaicciiccccclcclcclllcafmnfnmnnnnnnlcmfnmnmnnnnnmmfmmnnnnnnnnnnmmmmmnmnmfnnfmnnnnnnnnnmnknnnnnnnnnmmnnnnmfmmnnnnmmmmnmnnnmfnnmmmnnmnknkknbbbbbkbaaaaaljjjjjjjjjjjljjji`jjjjjjjjjjjcljjjjj`iabkkkbkkkkkmaaknkkkkbkbbkknnkkkkbbbbnbbbkkkkkbkbnkkbkkkbbbbbbbbkbbbbbabbbbbbbbbbbbbkkbbbbbkbbbbbabbkbabkbbbbbbaaaa`aknnnmnkknbbajjjjjjjjjjjjjjjj", +"icccci`cciciiiiiii`iiiiiii``iiiiii`iiiii`i```iii``ci`ciiiiiccicicccciciiicicccccccclccccclikmmnmnmnnnnnklammnnknnnnnnnnnmmmnnknmnnnnnnmmmmmmfnnmnmmmmnmnmnnnmmnnnnnnnnnnnnmmmmmfnnnnnfnmmnnnnnkmmnnnmmnnmnmnnkbbabbba`aaailjjcjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjliiakbknkkkbknnk`nkkbbkkbkbbbkknkkbbkbkbkbbbkkkkbknbnbbbkbnkbbbkbkbbbbbbbbbabbbbbbbkbbbbbbbabkkkbbbbbbbbbabbbabbbbbaaibbbbknmmknkabjjjjjjjjjjjjjjjj", +"icciccccciicci`bi``i`iii`i``ciiiciiiiiiiiiiiii`aci`iiiciiiiiiiccciicccccccciciccccccccclclcbnnmmnnnnnnnklaffmnnmnnnnnnmmmmmnnnmmnnknmmmmnnmmfnnnnnmmnmnnnmnnmnmnknmnnmmnmmfmmnnnnnnmmfmmnnnnnnnmmmmmnnnkmnnnnkbababaa`aaicjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjliiakkabkkkkknnnannkkbbkbbkbkkkknkkkbbnbbbbbbkkkkkkbkkbbbkkkkbbbbbbbbbbbabbbbbbbkkkbbbbbabbbkbbbbabbbabkkbbabbabbbabb`abbbkknmmmkbb`ljjjjjjjjjjjjjj", +"macciiiicicciii`iii`i`i`i`knai`c`iii`iii`ii`ii`aaciiafiiiciiiciacciccccciciiccclccclccllclcaknnmmnnmnnnnjbmffmnnmnnnnnmmmfnmnnmfmnknmmmnmnmnnnmnmmnmmmnnnnnnnnnnnmmmnmmnnmmnnnnnnnnnnnnnnnmnnnmnnnmnnnknnnnnnkabaaaai```iiljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjiiakbaakkknnnmnankmnkkkkkkbbkkkkkkkbbnkkbbnkkkkbbbbbkbkbnkkkbbbbabbbbbbbkkkkbbbbbbbbbbbbbbabbbbabbabbbbabkabababbbbb`abbbbbknmmnbbljjjjjjjjjjjjjjj", +"biccclcciicciccii`iiii`iii``ci`ia`iiiii`iii`iii`c`iiii`ciiicccibccciciciiiiiiicccccclccclclabkkkmnnmmnmklanmmnnnmnnnnnnmmfmnnnnmmnknmmnnmnmnnmfmmnmmmmmnnknknnnnmmmmmmnnmnnmmmmmmnmknmmmnmmmmmnnnnnmnnnnknnnmkabbaa```a`iiljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjlii`kkbabkbkknmnakknkkbkkkkbbkknkkkkbbnkkbbkkbbbkkkbbknkbkbbkkbabbbbbbbbbkkbbbbbkbbbbbbbbbbbbbbkbbbbkbbbabbabbababbbb`abbbbbabknkkajjjjjjjjjjjjjjjj", +"cciiiiiicciiccib`iii`ii`i`````ic`ii`iii`i`i`iiiiiiiciiciicciiciiiccciiiciiciccilcclclcllcll``aaknmmnmnmblbnnmnnmmnmnnnnmmmmmnknnmnnnnnnnnnmnmnfnknnnnknnnnnnnnnnnnmmnmnmnmnnmmmmmnfnfmmnnnnmmmmnnnnknnnknnkknkabbaaaabba``cjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjii`baaaabakkbknakkkkbkkkkkkbbkknkkkbbbkkkbbbbbbbkkbbkkbbbbbbbbbbbbbbbkbkbbbkbkbbbkbbkkbbbbbkbbbbbbkkbbabaabaaaabaaaa`i```aabaknnbacjjjjjjjjjjjjjjl", +"icccciccicciic`b```iiiiii``iiiiiiiii`iii`iiii`iiicii`cicciiciicccccccicciicicciclcclclcllcli``akkmmmnmnbjbnmmnmnmmmmnnnnmmmmnnnkmnnnnnnnkknnnnnnnnnnnknnmnnnnmmmnmmnnnnnnknknnnmmnmnnnnnnnknmmnnkkkknnkknnnknkabbaaabbkabaijjjjjjjjjjjjjjjjjjjjjjjjjjjljjjjjjjcci`ii`abbkkbkkabnkknknknknkbbkknnkkbbbkkbbkkbbbbbkkbkbbbbbbbabbbbbbkbkkkkbbkbbababbbbkbbbbbbabbabbkbabaababbbbbbabaiciii`aabbnnkacjjjjjjjjjjjjjjj", +"liiicciiiicciiii`i`iiiii``ii``iii`iiii`i`iiiiiiiki`cciciciiccccicccccccccicciiaicccllcllclcaaabknmmnmnnbjkmmfnnnmmfmmnnknmmfmnmnnnnnnnnnnnnnnnnmnnnnnnnnnnnnnnnmmmmnnmmknnnknnmmnnknnmmfmnnmmmnmnnnnnmmnnnnkkbabaaaabkkbnaijjjjjjjjljjjjjjjjjjjjjjjjjjjjjjjjjjilcic``bkbkkkkbaankkkbkkkkkkkbbkknnkkbkbkbbbkkbbbkkbbbbkbbbbabbbbbabbbbbkbbbbbbbbababbkbbabbkkkbbbbkkkbbbbbabbbbabaaalccciabbbkkkbijjjjjjjjjjjjjjj", +"icciciccciiciiiiii`iiiiiii`iii`iiiii`i`iii`iiiiiiic`ciiiiicciicccciccccccilcclilclclclccllcbbbbmmmmmmnnbjkmmmnknnmmnmmmnmfmfmmmfnnmmmmnnknmnmnnmnnnnnnnnnnnnnnnnmmmmmmmmnnnnnnnmnnnmnmnnnnknnmmnmnnnnnnnnnnnnkbb`i`aabnnkaijjjjjjjjljjjjjjjjjjjjjjjjjjjjjjjjjjcllcc`abbbabbkbaannkbbbkkkkkkkkkkknknnkbkbkkkbbbbkbbkbnbbbbbbbbbbbbbbbbkkkkkkkbbbbbabbbababbbabbabbbbbbbbabbbbabbbab`lllciibbabbbbijjjjjjjjjjjjjjj", +"ccciciicciiciii``c`i`cii``iiiii`ikbn`iiii`iiiiiiiciiiiiccakaiccccccccccciccccclccllcllclllcbbbnmmmmmmnnajmmmnnnnnnmmnnnmnmmmmmmmmnnnnmmnnnmnmmmknmmnknmnnknknnmnmnmmmnnnmnknnnnnnkkmmmnnmnmnnnnknkknmmmnmnmkkkaaii``bkkkbaijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjicllccaakbbbann`bnnkbbkkknkkkkbkknnkknkkbbbbkkbbbbbkkbbbkbbbbbbbbabbbbkkbbbkbbbbbabbabbbabbkkbbbbbbabbbaaabbbbbbbbaaalccc`abkbbbabajjjjjjjjjjjjjjj", +"ciiil`ciciciciiii`iiiii`ii```iiii`ia`i`iic`ci`iiiiiicciiiciccccciccccccccccllcclcccllclclccbbbnnnnnmmnn`lnmnknnnnnnmmnmnnmfmmmmmmknkknnknnmnmmmnmnnmmnnnnnnnmnnnnknnnnmmnnknnnnnnnnmmnnnmnnnnnnknnnknmnnknnnmka`i``abbknaaijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjicjcii`bkbkkknmaankbkbkbbknkkkkbknnnknkbbbbbbbbbkkbkkkbbbkkbbbbbbbbbkkbabbbbbbkbbabbbbbbbbbbbbbbbbabbbabbaabbbbaabbbblli``bkbbbbaaajjjjjjjjjjjjjjj", +"ccciina`iicicii`iaiiiiiii``i`iiii`i``ii`i`a`iic`iciciiccciicciccccccclcccccccclclclccllclciabkmnnnnmmnm`jnnnnknnkknmmmmknmfmmnmfmnnnnnmnnmmnnmmmmmmmmnknnnnnmmmnnnnnmmmfkknnkknnmmmmnnnnmnmnnnnknkkknnnmnnnnmna````bbknbaaijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjljjcila`i`bkbknnnnaabbkkkbbbbnkkkbbkkkkkkknkbbbkkbbbkbkbnkkkkbbbbbbbbbbkkbbabbkbkkbaabababbbbbbbabbkbbbaaabababbbbbbabbbllababkbbbbbbbjjjjjjjjjjjjjjj", +"iiccik`iiciacii`ibiiii`iii```i`ii`i`iciiiiiiiciciiiiiiiiiccciccccccccccccclccllcieillclllciabknnnnnnnnnilknnnnnnnnmmnmmnnmmmmmmmnnkknmmmmnnnnnmmnfmmnmmknnnnnmmnnnmmmmmmnnknnknnmnnmnnnnnmmnnknnknknkmmmmnkknkaaa`abakkaab`jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjicca`iibbbknnnnb`bkbkbbkkkkkknkkknknnkkkbbbbbkkkbbbbbbkkkkbkkkbbbbbkbbbbkbkkkbkbabbbabbbbkbbbabbbbbbabbaabbabbbbbbaablcabbbkkbbbbbbjjjjjjjjjjjjjjj", +"ciccccicciibiiiiiaiiiiiiiii`i`i``iii```iiiiiiiiiciiiccciciccccicilclcicccilclclclccclclcll`kknnnnmnnnnn`jnknnnnkmmmmnmmmnmmmmmmmmnnnknnnnnknnnnmnnmnnfmmmmnnmnnnmmnnnmmnnnnnknknnmnmmnnknmnnknknnnmnnmmnnnnkkkabaaabbaaibk`jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjliccb`iibbbbknknk`kkkkbknknkbnnkbkkknkkkkkbbbkkkkbkbakkkbbkbbkkkbbbkbbbbbkbbbbbkbbbababbbbbbbkbabbbbaabbabbbbbbbbaaabbcibbabbkbbaabbljjjjjjjjjjjjjj", +"ciciiciicii`iii`i`ii`iiiii`iii``i``iaaai`iici`ciiicc`iccciiiccclccicccciiaillcclcjlallllll`knnnmnmmnnnn`lnnnnnnnmnnnnmmnnnnnnmnnmfmnmmnnnnknnmmmnnmmmmnmmmnmknkkmmnnnmmmnnkknnnnmmmnmmnknnnknnknnnmmnmmnnnmnnkbbb`abba`abkijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjiicnk`cakbbknknkabkbkbkkkbkbkkkbbbbkbkkkkkkkbkkbbbbkbkkkbbkkkkkkkkbbbabbkkdkkbkkbabbbbbbbbbkbbabbbabbabbbbbbbbbbabbbaiiabbabkbabbbbjjjjjjjjjjjjjjj", +"icciiciciicccii`iiiiiiiiiii`i````iiii`iikiiiabiiiiccaa`ibicbbicicc`iccc`ibcclclllacjclllll`bkknmmmnnnnnilnnnnknnnnnnnmmknnknnnnnnmnmmmnnnnnmnmnnmmmmnknnnnknnkknmmmmmmmmknknnmmmmnmnmnnnnnnknnknnnnnnmnnnnmnknkaiiiab`abbk`jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjji`cnnic`bbkbknkk`bkkbbkkbkkkknkkbkkkkbkbkkkkkkkbbbkbbnbnbbkbbbbbbbbbbbabkkkkkkkbbababbbkbkbbbbbabbabbbabbbbabbbbabbab`ibbabbbbbbbkbljjjjjjjjjjjjjj", +"cciiciciciiii`iiii`iii`i`i`iiii`````iiiiiiciiiicciii`iccciccccicccilccccc`lclllcclcllcllll`bbkbknmnnnnnicnnnnknmnnnnnnnnnnnnnnnnkmmmmmnnknnmnmnnnmmnknnnnnnmnnknknmmmnmnnnknnnmnnnmnnnnnnmnknmnnnnnknnnkkbnmnmbilcci``abkkijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjic`kb``akmbakkknakkbbbbkbknbbkbbbbbbbkbbbkkkkbbbbkkkkbbbkkbbbabbbbkbbbbbbbkkbkkbabbbbkkbkbkbbbbbbkbabbbaababbbaaabbbb`ibkabbbbkbbabljjjjjjjjjjjjjj", +"iciciiiiiccci`i`iiiiiiiiii``i``i``iiiiiiiiiiciciiacciilccccciicciccccccclclclcllllllllllcl`abbbknmmnmnnlcnnkknnnnmnknnnnknnnnnnmmmnmmknnnffmmmnnnmnkknnnknnknnnnnkknnnnnkknnnmmnnmmnnnmnnnnmmmnknknnmnnnnkmnnnii`ciccikkbbijjjjjjjljjjjjjjjjjjjjjjjjjjjjjjjjjjic`bb``bkknbbbnnakkbbkkkkkbbbkkbbkbkbbbknkbkkbbbbnkkkbbbkkbabbbbbbbbbbbbababbbbababbbbbbbbbbbkbbakbbbbbbbabkbbbaabbbb``bbkaknbbkkakijjjajjjjjjjjjj", +"cicciccia``ii``i`i`iiiii`i```i```i`iiiiiciiiiiiic`ciccaiciicciicicccccccclclcllclllllllcjcabbbknnmnmnnnlinnnnknmnnnknnnnnmnmmnmnmmnmnkknknmnmnnmknnnknnnknnnkknknnnknnknnnnmmmmmnmnnnnnmnnmnmnnnnnnmmmnnnnnknk`c`iiciiabbbijjjjjjjjjjjjjjjjcjjjjjjjjjjjjjjjjjjci`bb``bkkkkbbkkakbkbbkkkkbbbkkkbkkkkkkkkkkkkbbbbkkkkkkbbbbbbbabbbbababbbbabbbabbbbkbkkbkbbbabbbbbbbbbbbabbbbbbbabbab``babbbkkbbkkbijjjljjjjjjjjjj", +"cciciiiciiciii``i`i`i`i`ii`````i`iiiiiii`iicicccciciicb`ciiicicicicccccclcllclllllllllllclakknmnmnnmnmmlinknkknmmnnmnkkmnnnmnmnnmnkmmnnmnmmnmmnmmnnmmkknnnnkknknnnnnnnnknnknnnnnnnnnnknmnmmmnnknknmmnnnnkknkkkiciiclcc`ank`jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjic`kb`bbbkkkkbbk`bkbbkkknkkkkkbknbbknkkbkkkkbbbbbkbkkkkkbkbbbbbbbbbbbabbbbbkabbbbbbbbbbkbbbbaabbbkkbbbababbbbbbabaaabaibabbbbkkbbnkajjjjjjjjjjjjjj", +"ciciciciiciiiiiiii`i`i``a`i```i`iiiiiiiiicic`iiiiccccci`iicccciccicciclccllclllcllcllcll`c`bbbmfmnnmmmnl`nknnkkmnnnmmnnmmnknnnnknnnkkkkknmmmnmnnmmnmnnkknnnnkknknnnnnmnnnmnnnmnnnnnnnknnnnmmnnknknnnnnnkkknknk`iicclcciakkajjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjlli`bbbknkkkkkkbbibbkbbbkkkbnkkkkkbbbbbbbkbbbbbbbbkkkkbbbbkbkbbbabkkbbbbbbbbbbbbbbbbbbbbbabbbbbabbkbkbbbabbbbbbabaabakaikaabkbkkbbkkajjjjjjjjjjjjjj", +"cciciciciiiiiiiiiii````ibaiiiii`iiiiiiiiiciabiiliccciiiiccccccccccciclcllclllcllllllllllcjbnkbbknkmmmnmj`nnnnnknnnnnmmnmnnkknnnnknnkknnnnmmnnnkknnnnnnnnnnnnnknkknnkknnnnmmnmmnmknmnknnnmmnnnnknnnnknnkkknnnmkaiiccici`abbbjjjjjjjjjljjjcajjjjjjjjjjjjjjjjjjjjcciabbknkkkkkkkb`kkkkbbkkbkkkkkkkbbbbbbbbbbbbbbbkkkbbbbbbbkbbbbbbkbbababbbbbabbbkkbbbbbbbbbbbabbbbbbbbaabbbbabaaabbaba`nbabbkkkkbbkkjjjjjnljjjjjjj", +"iiciciciiciiiii`iiiiiii`a`iiiiiiiiiiiiiib`iciciiiciiiibiccccccccccccclcllllclllllccllllllcbbbkkbkkkmnmnlannmnknnknknnmmnmnkknnnmnknnmmnfmnnnknnnknknnmmnknnnnnknknkkknnnmmmnnnnknnmkknnnmnnnnnnknnkkknkkknknnb`icc`ai`a`aa`jjjjjjjjjljjjjjjjjjjjjjjjjjjjjjjjjjlci`abbknkkkknnk`kkkkkbkbbbbkkkkkkbbbbkkkbbbbkbkkkbbbbbbbbabkkkbbaabbbbabaababbbbkbbkbbabbbbabbbbbbbbbabbbaaaabaabaabbikkbakkbbnkbbbljjjjajjjjjjjj", +"iiciciiiiiiiiiiiiiiii`iiiii`i`iiiiiiiiii`ccciiciiiiiccalcccccccccclclc`lcllllllllcclllllllbbbnbabbbknmkjannmnnnknnknnmmmmnnnnknmfnmnnnkkmnnnnnnnkkkkknnkknknnnnkknknknknnnmnnnnknnnnknmmmnnnknnnnkkkkkkknnnnnk`cc`ab`a`cii`jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjlciaabbkknkkknnkakkkkkkbbkbbkkkkkkbbbbkkkkkkkkbbkbbkbbbbbabbbbbbbbbbbbbbababbabbbbbbbbbbbbbabakbkbbbabbbabaaabaabbabbaiakbabbbbbkankijjjjjjjjjjjjj", +"iiicciciciiiiiiiiii`iii`ii`iii`iiiiiiiiciiiiciiiicciccliccciicclcllclcaclcllclllllclllllllbabbdkdddbnnklannnknnkknknnnnmmnnnkknmmmmnnfnnnknnnnnknnknnnnnkknnnnnkkkknkknnnnnnnnmknnnnmnnnmnnkkknnkkkkkkkknnnknb`c`bkbba`i``ijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjcibbbkkbknknkkn`kkbkkbbbbbkkbkkkbkkbbbknkkbkkbbbbbbbbbbbbbbbbbbbbbkbbbbbbabababbakbbbkabbbbkbbbkkbababbbaabaaaabbkaaa`bnabbkkbabbbkcjjjjjjjjjjjjj", +"ciiiiciiiiciiiiiiiiii``i`iiiiiii`iiiiiiiciiciiicicccicccililccccclccllllllclllllllllbllllikkabbbbbkbkmblanmnknnknnnkknnnnnnnmmnmmnnnnnnnnnnnknnnnknnnnnnnnnknnnknnnkknnnkkkknnknknmnkknnnnknknnbkkkkkkkknmkkkb`ibknnkbaa``cjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjli`akkbbkbknnnnnibkbbbbkbkbbbkkbkkkkkkknkkbkbbbbbbbbbbbbbbbbbbbbbabbbbbabbbbbbbbbababbbabbbkabbbbababbbaaabbaaaakbbaaa`bnbbbbnkkbbbbljjjjjjjjjjjjj", +"icciccicicii`c`ii`i``cc`ii`iii`ai`iic`iiciiciiiiccccccccclcccclcllciilclllllllllllllcjcllannkbbbkkbaknajknnkkkkkknnknmnnnnnnknnmnnnnnnnknnkkkkkkkknkknkkkknnnnkkmnnkkkkknkkknnnnnknnnknknkknknnnkkkkkkkknnmnnk`aknknknkb`d`jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjl``aknkbbkknnnkkikkbbbbbbbbkbbbkbbbbbbbkkkbbbbkbbbbbbbbbbbbbabbabbbbbbbabkbbaaaabaaababbbabbaabababbaabbbaaaaababbkbbb`ankabbknkbbkbijjjljjjjjjjjj", +"iccici`c`ciii`kiiiiiiiai`iiiiii`ii`iiiccicciiicccciccccc`mlclclclccccllcllllclllllllllail`bkkbaknkbabkijnnkknknnkkkkknnmnnkkknnmkkkknnnnnknknnkknnnnnkknknnnknkkmmmnnnnkkkknnnnnkkknknkknkkkknnkknnnnnnnnmmnkbaknnnknfnbbnbjjjjjljjjjlcjjjjjjjjjjjjjjjjjjjjjjjl``bnnknkkbkknkk`kbkbkbbbkbkbbkkkbbbbbbkbbbbbbbbbbbbbabbbbbbbbbbbbbbbbbbbkkbbbbbbbbbbbkbbbbabbaabbbabbbaaabbdbbbbbbbaa`amkbbbknknkbbijjjjjjjjjjjjj", +"ciiiiia`ci`bna`iii`iibfiii``i`iiii`iiiiiiiciiicccccicccclccl`cilcllllllcclllccllllllll``liabbabkkkkbbbilknkknnknnnkkknnnknnnkknnkkknknknknknknknnnnnnknknnnkknnmmnnkkkkknknknnnmknmnkknnnnnmmmnkkknknkknknnkkbbnnnknmmkdakbjjjjjjjjjjjljjjjjjjjjjjjjjjjjjjjjjjli`bnknnnkkbbkkmabbbkbkbbkbbbbbkkbkbbbbbbbbbbkbbbbbbbbbbbbbbbbbbbbbababbbkbbbabaabababbbbabbabbbbabbbbabbababbbaabaabaaamnabbkkkkkkkijjjjjjjjjjjjj", +"c`icciiciiciiiii`ii`ian`i```iiiaiciiciibiciiiicccccccccccccinlclclcccccllllclclllljcljlilibbbbbbaabkkb`jbkkknkknknkkknnnkknkkkkknkknnkkkkkknknnknnnnkkknknnkknnmmmnnkkknnnnnnnkknnnmnknnkkknnnkbkknnkkkkkkknnkbkkknmnkbbknkjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjl`i`bknknmkkbbbk`bbbbbbkbbkbbbkbbbbbbbbbbbbbbbbbbbbbabbbbbbbbbababbbabbbkkknbababkkbkbbbbkabbabbbabbbbbbaaabbaaabaababa`nkbabbkkkknbaljjjjjjjjjjjj", +"ibaiiiiiik`ciai`iiiiii`iii`iiii`iciiiciaiiciiccicccccccccllililcclllcclllllllllllclllllllibkbkndaabnkb`jknnkkkknkknnnnkkknknkkkknnnnnknkknkknnnnkkknknknknnnnnnnknnnnkkknmnnnnnnnnkkknnnnnnknmnmknnnkkkkkkkknnbnnknmnbbnnnncjjjjjjjjjjjjjjjjjjl`jjjjjjjjjjjjjjl``abkkkknmkbbbbibbbbbkbbbkbbkbbbkbbbbbbbbbbbbbbbabbbbbbbbbbbabbbabbbbbbbbbkbbbabbbbbbbabbbabbabbabbabbbbabbbaabbaaabaaikbbbabbkkbbbbjjjjjjjjjjjjj", +"c`iciiiii`i`iiii`a`ii`iiii`iiiiciiiiicciiiiicccccccccccclicjillccllcllcllllllllljlljllljlanmnnnbabnnnbclknnnnnnnkkknnkkkknknknnnnkknkkknnknnknnnknknnnnnknnnnnnnnnnnnnmmnnmnnnnnnkbkknnknnkkknnnnnnnkkkkkkbkkkbnknnkbbkmmnkjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjl`iakkkmnkknkkbbibkkkkkkbbbbbbbbbbbbkbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbkbbbbbkbbbbbkbkbbbbbaababbbbbaabbbbbbabaaaababaaaikbababbbkkkkbjjjjjjjjji`lj", +"iiiiiciii`iiiiiiiii`iii``i`ii`i`iiicciiciiicicccccccccicc`ciiilallccllcllllllllllllllllllannmnkbbmkkfkljknnmfnnknkkkkkknkkknnnnnknkkkkkknnkknkknkkkknnnnkknnnmmmnnknkknmmmmmmnnnbknnkkmnnnkknnnnnnkkkkkkkknnkkbnknnbbakmnmbjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjl`iiaknnnnknnmnkcakknkbkbkbbbbbbbbbbbbkbbbbbbbabbbbbbbbbbababbbkbabbbbkkkbbbbbabkkbkbkbbaabaaabbbbbbaabbbbbbbaabaaabbabikbbbbaabbknbkjjjjjjjjjjjjj", +"iiiiiiiiiiiiiiiii`i````ii```ii`iiicicici`iicccccccccccclcclclcclclclllllcllllbllljcbcljllannnnbaknnmnncjnmnnnkkkkkknnkkknnnnnkkkkkkkknnnnknnknkknknnnkkkknmnnnnnmmnnnnnnnnnkkkkkkkkkkkkknnnkknnnnknnnkkknkknnb`knkkbdbnmnmbjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjlii`abbkkknnkkmk`kknkkbbbbbbkbbbbbbbkkbbbbbabbbbbbbbbabbbbbbbbbbbbakkbbbbkkbbbkbkbkbbabaababbaaababbabakbbabbbaabbbababcanbaabbabkknkjjjjjjjjjjjjj", +"ciciiiiiiiiiii`i`i```i`i`icc``i`iiiiiiiiicciciccccclccccccclcccllllllclllllllijllllijllllaknkkabkkknmnclmnknknkbnknnnnkkkkkknnknkkkknknknnkknkkkkknnkkkkkknnkknfnmnnknnnnnkkkkknkkkkkkkbkknmnnnkkkknkkkkknkkkbabnkkkbknnfnmjijjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjlii`akdbbbbkmmk`cabbbbbbbbbkkkbbbbbbbbbbbabbbbbbbbbbbbbabbbbbbbaabbbbabbbkbbbbbbbbbbaaabbbaaaabaaabbbkbbaaaaabbbaadababiabbbabaaabbkbljjjjjjjjjjjj", +"iiiiiiiiiiiii`i````iiiiiiii`baiiiiiiiicccccccccccccccccclclclcclclllcccllllllllllllljlljlbknkbankabknncckknknnnmnnnnmnkkknknkkkkkkknnnkknkknkkknknnnnnnnkkkkkknmknnnkkknknnnnnnknkkkkkkknkknnnnnnnnnnnknkkkkkkbknkkkknnnmnajjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjiciakbkbkkkbbbaiakbkkkkbkkbkkkbbbbbbbbbbbbbbbbbbbbbbbbbababkbbbbbabbaabkbbbbaaabababbbbababbbabababbbkbbbbbbbbabbabaabc`aaaaaaaabkknijjjjjjjjjjjj", +"iiiiiiii``i`ii`i``i`i`iii`cciiia`i`i`iiiiiccccccccclccccccclccccclcllilllllllllllllllllllkmkkkknbdabkklcknmmnnnnnkknnnkkkkkknknkkkknknnkkkkkkkkkkknnkknknkkkkkkmkkkkkkknnnnnnkkkknnkknnnnkkkknmnnnkkkbkkknkkbkbnmnnnkknmnnajjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjliiibbbbbbkka`caabkkbkkkkbkbbbkbbbbbbbbbbbbbbbbbbbabababbabbbbbbbbbababbbbaabbabbbbbbkbbaabbabbbbbbbbaabbbbaaaabaababaacc`iaaaa`aabkkijjjjjjjjjjjj", +"lllllllllllllllllllljlllllllllllllllllljlljlljljlljljljljjljjljljjljjljjljjjljjjljjjljjjjknknmnnbbbbkklcnnnnnnkknkknnnkbkkknkkkknknknkknkkkkkkknnnmnnnmnnnnnknnnkkkkkknnmnnkkkkkkknknkmmnknkknnkkbkkkkkkkkbkkbbnnmmkkkkmmnkjljjjjjjljljjjjjjljljjjjjjjjjjjjjjjli``bbbbbbbaiiiaaakbkbbkbkbbbkbbabbbbbbbbbbbbkbbbbbbbbbbbbbbbbbbkbkbbbbbkbbababbbkbbbaaabbbbabbbbbbbabbbbaaaaaaababaaaaiccii`ii``aaab`jjjjjjjjjjjj", +"ljljljljljljjljlljljlljljjljjjljjjjjjjljljlljljljjjjljljlljljljjljlllllljllljllljlljljjljbbknmmnkbbbbblinnnnnnnnknkknnnnkkkkknknknkkknkkkkkkknkknknnkknknnmnnnmnkkkkkknnnnkkkkknkkkknnnnknnknnnkkkknnnkkkbkkbbakmmkbbbbknnkjjjlljlljljllljljjljlllllllljlljljll`cibabaaa`cliaba`kkkkkbbkbbbbbkbbbbbbbbbbbbbbbbbbbababbbbbkkbbbbbkkbbbkbbbaababbbkbaabaabaabbbbbbababbkababbbbbbaaaaaaiciiicci```aad`ljllllllljlj", +"ljlljlljljljljljlllljljljljllljllllhllllljljljjjlllljllllllljljljjljjljljlljjjljllllllljlddknmmnkbkbbbj`mmmnkknnnknkknnnkkkkkkkknkkkkkkkkkknkknknknnnnnnnnnnnnnnknkkbkknnkkknkkkkkbkknnknnkkkknkkknnkkbkkkbkkkaknnbbbbbbknnjljljljllllljllllljlljljljljlllllljl```bbaa`cjlcabbakknkkbkkkbbkbbkkbbbbbbbbbbbbbbbababbbbbbbbbbbbbbbbbkbkbbbbbaaabbabbbbbbaaaaabbbbbbbbaabaababbaaaaaaaab`c``icci`aaaa`iljjjljjljljl", +"jlljlljlllhllhlhlljhlllljlljlljllhjljhjllhlllllhljljllhjllllhllhlhllhjllljhjlhjlhjjljlljlbkmmmmnmbkbkbj`knknnnnnnnknkknnkkkkkknkkkkkkkkkkkkknnknkkbnnnmnnnknkkkkknnnkknmmkkbkkkbkkkbknnnkkknkbkkkkkkkbkkknkknnbkmnkbbbabbadllllllhlllljhjhjljlljlllllllhjlllllc```bba`clliakkbabbbkbbbkkbkkbbbkbbbbbbbbbbbbbbbbbbbbbbbbbbabbbkkbbbbbbbabbbbbabbbbaaaabababaaabbababaaabaaaaaaaaababbaaiaa``i`a`add`cljhljlljljll", +"lljhjhlhjllllllllhlljlljhjlljllllllhlllhjllhllljlllljljlljljlllllllllhlllhllljljlllllljljnknmnmmmnkkbal`kkknnnkkkkknkknmkkkkkkkkmnkkkkkkkknmnkknnkkbkkkkkkknknknknnnknnnnkkkkbkkkkkkkbkkkkkkknkbkkkkkknnnmnkknnknmnbbbkbbbbljljljjljljhjljlhlhllhjhlllllljljllli``kkaiclc`bbkkkbbbbkkkkbbbbkbbkkbbbbabbbkbbababbabbkkbabbbaabbabbabbbbbbbbkbabbbbbbaaabaabaaabbbaababaaababaabbbbbbabacbbaaa`i`abb`iljlllljhjljj", +"llllljljlhllhlllhjllhjhllhlllllljhjljhjlllhjllhlhjhlhlhlhlhlhjhjlljhjljlljlllhlhllhllhllhkknmknmmnkkbbj`nnnnnnnnkkkknnkmnnmnkkkkkkkkkkkkkknnkkkkkkkkkkknkkkkkkkkknmnnnnnkkkkkkkkkkkkbkknkknnnkkknknknnnnknkknmnnnnnbbbbbdbdjlljhlhlhlhlllhlllllljljjhjllllllljhiiiba``ic`bnkbbkbbbkbkkbkbbbkbbbkkkkbbbbbababbbbabbbbbabbbbabbbbbbbbabaabbbkbbbkbbbaabaabaaabaaababbbbbbbabbbbbbbbbababiababba``add`iljhjllljhjhl", +"llhllhjhjllljhjhjlhjllllllllhjhlhllhlllhjljhljljllljlljljljhlllhlhllhlhlhlhlljllljljlllllkbnmkknmmnkkalakknnkkkknknnkkkkmnnnnnnkkkbkkkknkknnkkkkkkkkkknkkkkkkkkknnmnnnnnkkbkbkbkbkbkkbkkkknnkkkkbkknnkkkknknknbkbkbbbabbbkbhllhllljljljhjjljlljhllhlllhlllhjhlli`i````a`abnnkbb`bkkkbbbbbkbbbbbbkkbbkbbbbabababbbbbkbbbaaabaaaabbaababbbbbkbbkbbaaaaaabaabaaabababbabaaaaabbbbaabaabbbibabnnk`iaaa``llljhjhllllj", +"lllllhlllhllhlllhlllhlhlhjhjlllljlljlhjlllllllhlhlhlhlhlhlhlllllljlljljljlljlhjhjhjhllllckbbkkbknfmkbalannnnkkbknkkknkkknkbknnnkkkkkkknnnnnnnnkkkknnkkkkkkkkkkkkkknnnnnkbkkkkkkkkkkkkkknkkkkkbbkkkkkbkkbkkknnnbbbbbbabbbbbbllllllhlhlhljhlllllhjljljhjljhlllllhiiciiiaaabbnnmnk`kkkkbbbakbbbkbbbbbbbbkbbbbababbkbbkbbbbbbbbbbbabababbabaabbbbbbbaababaaaaabbababbabaaaaaaaaaaaaaabbbbbiabannnb``addahlllllljljll", +"jhjhjllhlllhllhlllhllllllllhjhjlllllljhjhjhjhljlllllllhlllllhlhllhlhlhlhlllhljhlllllllllhbbbbbkbknkkb`jamnnnnkkkkkkknnnnnkkkkknkkkkkkkknnnnnnkkkknnnnkkkkkkkkkkkkkkkkkkkkkkkkkkkbkkkknnknnkbkkkkkbkbkkbkbkbnnnkkkkkbbbbkbbdljhjhjljljlllllhlllllhlhllhlhljhlllli`lli`aabbkmmnnmakkkkbbbbbbbbkkkkbbbbbkbbbbbbbbbbbbkbbbkabbkbbbbbababbbaabababaaaababaabaabaabbbbbbaabababaaaababaaabbaibbaknmka`abbbillllllllllj", +"llljhjhjlllllllllhlllhlhlhllllhlhlhlhllhjllljlllljhjhljljllllllhllllhllllhlllhljlhllllllibdbbbbknkabkajbnnnnnnnkkbkknnnmkkkkkkknkkbkbkknnknmnnnnknnnnkkkkkkkkkkkkkkkkkkbkbkkbkbkbbkkkkknnkbkkkkbkkkkkkkkkkknnkbknkkkkbbbbkdlllllllhlhlhlhlljllllllllljljllllllliilc`abaabbknnnn`kkkkkkkkbabbbkkkbbbbbbbbbbababbbkbbkbkkbbbbbbbabababaabbabaaababaababaaaaaabababbbaaababaabbabaaaaaabb`abknkkka`abbbcljlljljllll", +"lllhjllllljhjhllljhllllllllhllllllllllllhlhlhlhlhlllljhlhllllljllllljlhjhjllllhlhllhllllibdkbabknnbbkalknnnnmmnnnkkkkknnkbbkknnknkkkkkkkkknnnnnnknnnkkkkkkkkkkkkkkbkkkkkkkkkkkkkbkkbknnknkkkkkkbkkkkkkkbbkbbkkbkkkkkbkbbkkkllhjhllljljljlllhlllhllhlhlhlhlllllhiic`aabbbbbbnmmn`kkbkkkkbbbbbbbbbbbbbbbbbkbbabbbbbbkbbkbbbbkbkbbbbbbaabbabababababaaabababaaabbbbbabaaaaaaaaabaaabaaaab`annnkbka`abbdilllllhllllh", +"lhlllhlhlhllllhjhlljljllllllllllhjhjhjhllllllllllllhlhllllhllhlhlhlhlhjllhjhlhllllllllll`ddbddaknmkkb`jnmnnknnkkkkkbkknnkknnkknnnkkkkkkknkknkbkknnnnnnnknnnkbkkkkkkkkkkkkkbkbkbkkkkknnnnnnkkbbbkkkkkkkkkkkbkbkbbkkbbbkkbkkbhllllhlllhlhlhllllllljljljlllljhjlll`ciakakbbkbbbknnakkkbkkkbbbkabbbkaabbbbkkbbbbbbbbbbbbbabbbkbbbkbabbbbababbabababbbbababaababbbbbbbbbbaaaababaaaabaaab`aibnmnkbnb`abbb`ljhlllllhll", +"lllhllllhllhlhlllllhlhlhlhllllllllllllllllhlhllhjlljllllllllhllhlhlhlhhhlhhlhlhhhhhhhhhlodddddddknmkdglknknnnnkkkkkkkkkkkkkkknnmkkkknkkbnkkknkknmnnnnnnknkkkkknbkkkkkknnknkkkkkkkkbnnknnnknnnnkbkbkbbbkbkkkbbbbbbkkbbkkkbkkljhlljlhlllllljhjhlllhlhlhlhllhllhlh`i`ababkbbkmbknmakkkbbkbbbbbbbbbabbbbabbbkbbbbbbabbbbbbbbbbbkbbbbbbbbbaabbababbbbbbbabaabbaabbbabbbabbbbaaaaaaaaabaaaa``annnnkbb`bbad`llllhlljlll", +"hlhllhlhllhlllhlhllllllllllllllhjhlllhjhlljhjhjhlhlhlhlhlhhhlhhhhhhhhhlhhllhhhhhhhhhhhhhhhhhhhhhghghhhhggghhghhhhhhgg`g`g`o`dddbddbbkkkkkkknnnkmnnmnnnkbnnnkbbbkbkbknkkbnknkkkknnkkkkkknnnnnmnkkkbkbkkkkbkkbkkbbbbkkkknnknklljhjhlljljhjllllljllljlllllhllhllllii`dbbbbbkbnnbkncbbbknkbabbkbbabbbbbbbbbbkbbbbabbbababbbbbbkkbkbbbbbbbabaababbbabababababbababbbbkbbbbbbaaaaaaabaaaabaa``mnmkkbb`bbdddllhllhlhlhl", +"ljllllllhllhlhllhlhhlhhlhhhhhhhlhlhhhlhhlhhlhhhhhhhhhhhhhhhhgghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghghhghghhhhhhhhhhhhhhhhhhhhhhhchhhco`oddkknnmnnkknnnkknkkbbkkkkkkbkkkkkkkknmnnnnnnnnnkkbkbkbkbbkkbkkkkbbbkknkbknkkhlllhllhlhllhlhlhlhllhlhlllllllljhjlii`abbbbakbmnkkkibbbbkbbbbbkbbbabbbbbbakbkbbbkbabaabbabbkbbkbbkbbbbbbbbbbbaaaaabaaababaabbaabbbbbbbbbbbbabaaadaaaaaaabaa`knnkbdaadd`ddhlhlhlhlllh", +"lhlhlhlhlhllhlhlhhlhhlhhhlhhlhhhhhhhhhhhhhhhhhhhhhhhgghhggggogoogggghhhhhhhhggggggghhhhhhhhhhhhhhhhhhlghhhhhhhhhgghghhhhlhhhhhghghhhhhhhhhhhhhhhhhhgho`oknknmnnmnkkkbkkkkkkkkkkkkknnnkknnnnnnnkbkbbbkbkbkkkbkkbbkkknnkkkkkblllhllllhlllhlllllllhllllhlhlhjhlllh`i`abbabbbknnnkn`bbbabbbbknkkkbkkbbbbbbbkbbbkkbdbbbbbbbbbbbbkbbkbbabbbbbbbbbaabaabbaabababbbbbbdabbbbbbddadddddddddddddd`kmkdd`higio`ghhhhhhhhhhh", +"lhlllhllhlhlhlhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhgggghgggggggggggggghghhhhhhhhhhhhhhhhlljhlhhhhhhhhhhhhhhhhhhgggghhhhghggghghhhhhgghhhhhhhgghhhhghhhlhlhhhhhh`oddnnnnkkkkbkkkkkkkkkbkkknnnnnnnnkbkkkbbkkkbkbkbkbbbbbkkkkbkdblhlllllljhlljhlllllllllllljllllljhlli``aaabbanbnnknncaabbbbbbbbbbabbbbbkkbkbbbbbkkdbbdabbbbabbbbbbbkbabbbbbbbkkbbbbbababbbababaaabdbbkbkkbkdddd`oig`og`ghhhhhhhghhhhghhhhhhhhghhhgghh", +"hhhhhhhhhhhhhhhhghgggggggggggggggggggghghghggggghghghggggogggggogggggghhhhhhggoggggghhghhghggggghhhhhhhhhghghhhhgggggghghhhhgggggggggggghhhhhgghhhhghhhhllhhhhhglhgiodddnknnnnnkkkkkknnnkknnkkbbbbbkkbbkbkkkkkkbbbbbbbbdbbdlljhjhjhlljhllllllllllllllhlhjlllljli`i`baabbbbnnkkblbkkkbbbbkbbbbbbbbbbkbbbbbbbkbdabbdddabbbbbbbabbbbbbbabbabbbkbabbbbabbbbbbbdddddkddd`oihhlhhhhghgggghhhhhhhhhghhhhhhhghghghghgggg", +"hhhhhhhhhhhhhhghggggghghgghghghgggggggghgggggggggghhhhhhggggggggggggggggggggghhhghghhhhhhhhhhhhhgggghhhhghgggghghggggggggggggggggggghhhhhhghghhhhhhhgghhhhhhhhhhhhlhlhhhhhh`ddkkddbbkkkkkknkkkbkkkkbkkkbbbkbbkknnnnnkbbbkkkllhlllhllhlllhlhlhlhllhllhlllhlhlhlhiii`abbbbakkbba`ibbbbkbbkbbbababbkbbabbkkbbkbdbdbbabbbbbkkbkbbbkbbbbbbbbbabbkkbbbkbkbbdbbddd``o`ohhhhhhhhhhhhhhhlhhhhghggghhhhgghhhggggggggghgggg", +"gggggggogggggggggggggggggggggggggggghgggggggggggghghgghhhggggghgggggghhhhhggghhghhhhhhhhhhhhhgggghgggggghhhhhghghhhhghhhghghhhhhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhlhhghhhhhhhhhhhhhhhcg`bknnnnnnnnnnnknnnbbbbbbabkknnnnbbbkmnklllllllllllhllljllljlllllljhjllljlll`i`abababkaa`ii````aababbkkkkkkknnkbbbbbbbkbbabbnbkmnnmknknkkbkkkbbbbbkkkkbbkkddkkddd`gcglhhhhhhhhhhhhhhhhghghhhghhhgggggghghhhhhghhhgggghhhhhhhh", +"ggoggogogogoggggoggogoggggggghggggggghhgggggggggggggghghgggggggggggghghhhhhhhghhgghghhhhghgggggggggggghghgggghghhhhhhhhhhhhhhhghghhhhhghhhhhhhhlhhhhhhhhhhhhhhhhlhhhhhhlhhhhhhhlhlhhh`ddknnnknnnkknbnnnkabbbbbknnmnnnnnknnnhlllhjhjhjljlllhlllhllllllllllllhljhi`idkkbbabaiciiiccciabbabbknbbkkkkkbabbbbbbbbaabnnkkkmkknnnnkbbknkbdkkkknkkddo`ooggghhhghhhhhggggghghgghhhhhhhgghgggggggggghgggghggogghggghhhhggg", +"ggogoggoggggggoggggggggggggghggghgggggggggggggggghhgghgggggggggghhhhhhhhhhhhhhhhhhhlhhhhhhhhhhhhhhhhhhhhhghhghghhhhhhhhghghhhghgggghhhhhhhhhhhhhhhhhhgghhhhhhhhhhhhhhhhhhhhhhhhhhhhlhhhhhgddknnkkknknnkbbkkbbbkmnnnnnnnnnnncjhjlllllhlhlllljllljhjllllllllljllli`ibkkbbba`i`aaiccc`aka``abbkbkkkknnbkbaaabkbabbnnkbkknnnknnnkdddmkddo`gghhhhhhhchghhghhhghggggghgghhhhggghhhhhhhhhhggggghgggogogggghhhhhhhghgggg", +"hghghghghghhhhhhhghhhggghhghgggggogggggggggogggghghhgghgggggggggggghhhhhhhhhhghhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhghhhhhhhhggghhhhhhhhhhhhhhhhghghhhhhghhhhhhhhhhghghghhhhhhhhhhhhhhlhhhhhgddbkmmmnkakkkbbbkbbbbbbnnmmnnhlllhjhljlljhjhlhlllhllhjhlllllhlhjhi`idbnkkkb```aa`ii``i```i`abbbbknbnkkbaaabbbbbabkmnkbbnnnmnkddo`oghhhhhgghhghhhhgghggghghgggggggggggghghgggghhhhhgogogggggghggggggghgghhghhhhhhhg", +"hhhghhhhhhhhhhhhhhhhghhghgggggggggggoggogoggggggghgghhgghggggggggghhhhhhhhhhghhghhhhhhhhhhhhhhghhhhghggghhhhhhhhhhgggggghhhhhgghghghhghhhhhhhhhhgghhhghhhhhhhhhhggggggggggghhhhhhhhhlhhhhlhhhhhhhhgdddbbbbbabkkkkbbaabkknmnllhllhllhlhllhllllhllllllllhlhllllhli`iabkknkbaaaa`aa```aa`icl`akkkkkkkkka`abaabbbbbbkndddndkd`oghhhhhhhhhhhhhghghhhghggggggghgggggoggggooggghhgogggghghhhgggggggggghhghghgghgghghggh", +"ggghghhhhhhhlhhhhgggggghgggghghghggggggoggggggggggghhghhhgggggghhhhhhhhhhghhhhghghhhhhhlllhhhhhhhhhhhhhhhhhhhhhhgghggggggghgggggggggggggggghgggghhhhggghghghhhhhgghghhhhhgghghhhhlhhhhhlhhhhlhhhlhlhhhhi`dkdddbbknkkkkkknnmlllhlllhlllhllhlhllhlhlhlhllllhlhlll````bbbbbabbaaabka`akkbicliannkkkbkkba`abbbdkkkbdkkdo`ghhhhhhhhhggghghhggggghggggghhgghghhggggoggghhhhghhhhhhhghgghhhhggohghhhhhgggogogggggggghgh", +"hghghghhhhhhhhhhhhgggggggghghghggggghggggggggggggggggggghhhhghghhhhhhhhgghggggggggghhhhhhhhhhhhhhhhhhhhhhhhhhhhhghggggggghghhhghggghghghhhhhhhhhhhhhhhhhhghhhhhhlhhhgggghhhhhhhhhhhhhhhhhhhhhhhlhhlhllhhhhh`dkkdkbbbbbbbkknlhlchlhllhllhlllllhlllllhllhlhlllhlhi`i`bbbbbbbbbabbbbaakkaiiliaknkkbkbbaddbddddddddohhhhhhhhhhhhhhhhggggggggggghhhhhggghghhhhgggoggggggggggghgggggggghghhhhhhhhhghggggggggggggghhhhh", +"gggggghghhhhhhhhggggggghhhghhhghhhgggggggggggggggogggggghgghgggggggggghhhhhhggggggggghhhhhhhhhhhgggghggghhhhhhhghgggggghhhhhhghghhhhhhhhhhhhhhhghhhghhhhhhhhhhhhhhhlhhhhgghgghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhgdnmnnnkbbbkblllllhlchlchlchlhllhlhchlchllchcllcliiiabakbbkbaaaaabaaakaaicciabknbbkbaddbddo`gggghhhhhhhhggggggghhgggggoggggggggogggggghghhhhghgggghhhhghhhhhggggggggggggggggggggggogoogggggggggggg", +"ghhhhhhhhhhhhghggggggghhhhhhhhhhgggggggggggggoggggggggghggggghghhhhhhhhhhhggghggghgghghghhhhhhhhhhhhhhhhhhhhhghggggggggghghghhghggghhhhllllhhhhgghgggghgghghhhhhhlhhhhhhhgghhhhhhhhhhhhhhhhhhhhhhhhhlhhhhlhlhhlhh`dknmkkbbdlllhlchllhllchllchlchllclllchlllhchlgciabbkbbbbabbbabbabbaailcc`abkkbd`iiihhhhhhhhgghghghgggggggggghhghggggoggogggggggghhhhghgggggggggggghggggghhgggggghggggghggggogogogggggggggghhhh", +"hhhhhhggggggghghhhhhhhhhhhhhhhhhhhhhhhhhhggggggohggggggggghhhhhhhhhhhhggggggggghghghghhhhhhhhhhhlhlhlhhhhhhgggggggggghghghhghhhhhhhhhhhlhhhhhhhggghhhhhhhhhhghghhhhhhhgggghhhhhhhhhhhhhhhhhhhhlllhhhhhhhhhhhlhhhllhlgakmkdglhlllllclcclllchllchlchlhchllhcllllccciabbabbbbbbababbaaaiiiiii`ddd`dgghhghhggghhhghhgggggggggggggggggggggogggggghhhhhhgggggggghhhhhhgghgggggggggggoggggghghggggggggggggggggghhghgggg", +"hhgggggggggghhhhhhhhhhlhhhhhhhhhhlhhhhhhgghghhhhhhhhhgggghghhhhhhhhhhhgggggggghgggggggggggggghhhhhhhhhhhhgggggggggggggggghhhhhhhhhghhhhhhlhhhhhhgghhhhjljllhhgggghghhhhghghgghhhhhhlhhhhhhhhhhhhlhlhhhhhhhhhhhhhhhhhhhhg`gchllhlhlljjjjljjljljllllllllllllhllhllhidbbaabaabbkkbbbbaa````igioihhhhghghhhghhgggggggggghhhhgggggggghhhgghgggggghghhgghhhhggggggogggggggggggghggggggoggggggoggghhhhhhhhhhhhhgggggggg", +"ggggggogggghghhhhhhhhhhhhhhhhhhhhhhhhggghghhhghhhhhhghghgghghhhhhhhhhgggggggggghgggggggggggghghhhhhhhhhgggggggggggghgggghhhghhhhhghghhhhhhhhhhhhhgghhlhjhjhhhhgghhhhhhhhhhghghghhhhhhhhhhhhhlllhhhhhhhhhhhhhhhhhhhhhhjhlhlhlhlhjjjjjjjjjjjjjjjjjjjjjjjjjjljllllhiiidbababbabbbknnkkdido`hhhhhhhhhhghgghghggghhgghgggggggggoggggoggggogggggoggggghgggggghggggggghgggggghhghggggogogghhggggggggggghhhggggggghggggg", +"ogogoggggggggggghghggggghhhghggghghghggggghghhhghghghhgggggggggghhhhghgggggggggggggggggggghgggggggghggggggggggggggghghhhhghhhhhhggghhhhhhhhhhhhhhgghhhhhhlhjhhhhhhhhghhhhhhhhghhhhhhhhhhhhhhhhhlhhhhhhhhhhhhlhhhhhhhjhhhlhlhlhllljjjjjjjjjjjjjjjjjjjjjjjjjjjjjjc`iibbbbbaaakbdkkkddighhhhhhhhhghgggggggghgghhhhghgggggggggggggggggogggggoggggggggghggggggggggggggogogghghhgggggggghhhhhhhhgghghhghghghhhgggggogo", +"ggogogogggggghhhhhhhhhhhhhghgghhghhhghhhgggggghhghgggghggggghhhhhhhghhhhgggggggggggggggghhghgggggghghghhghhhhgggggghghhghhhhhhggghghhhhhhhhhhhhhgghghhljhjhhhhhhhhghghgghhhhhhhghhhhhhhhlhhhhhhhhhhhhhghhhhhhhhhhhhhhhllhhhhlhlllljjjjjjjjjjjjjjjjjjjjjjjjjjjjlli``bababbddddddogggghhhhhghghgghgggggggghggghggggggggggoggoggggggggggggggggghgggggggggggggggggogggggghghghgggggogghhhhhhggggggggggggogogggoggogo", +"oogogogogogghgghhhhhhhhhhhhhhhhhhhhhhhgggggggggghghhhghghghhhhhhhhghgghghhhghhhhhhhhhhhhhghggggghgghghgghgghghhhgghghhghghhhhhhghhhhhhhhhhhhhhhhghghhhhhlhhhhhhhghhhhghhhhhhhhhhhhhhhhhhlhhlhhhhhhhhgghhhghhhhhhhhhhhhhhlhhhhhhhhlhlljjjjjjjjjjjjjjjjjjjjjjjjjjjiiibabbdbd`oghhhhghhghhohhhgggggghghgggghgggggggggggggogggggggogoggggggggogghhggggogoogggggogggggogggggggggggggggggghhgggggggggggggggggggogoogoo", +"ggogoggggggggghhhhhhhhhhhhhhhhhhhhgggggghhghhhhhhhhhhhhhhhhhhhhhgghggggggghhghhhhhhghggggggghggghghghghgghhhhhghhhghhghghggggggghhhhhhhhhghgggggghhhhhhhhhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhghhhlhhhhhlhhhhhlhlhlhhhlhjljjjjjjjjjjjjjjjjjjjjjjjjl```kbbd`ggihhhhgggghhghhghhghhhhggggggghgggggghhghggggggoogggggggggggggggoggggggggghhggogggggoggghhhhhhhgggggghgghghgggggggogogggggggggggggggogg", +"ggggggogggggghhhhhhhhlllhlhhhhhhgghhhhhhghhhhhhhhhhhhhhhhhhhhhhhhghghghghhhhhhhhhhhhhghggghghghghhhhhhghhhhhhhhhhhhhhhhgghhggghhghghhhhgghgggggggghhhhhhhhhhhghghhhhhhhhhhhhhhhhllhhhhhhhhhhhhhhhhhhhhgghhhhhhhhhhhhhhhlhhhhlhhhhhhhlhlhjjjjjjjjjjjjjjjjjjjjjjlhi``ddihhhhhhhghhhghhhghhghhhhhhggggggggggggghhghgghgggggggogghhhghhgooogggogggggggggggggogoggggggogggggoggghghhhghhggogggghhhhghgggggggggggogggg", +"gggggggghhhhhhhhhlhhhhhhhhhhhhghghhghghhhghghhhhhhhhhhhhhhhhhhgghgggghghhghhhhhghgggggggghgggggggggggghhhhhhhhhhhhhhhghhhggggggggggghghghghggggghhhhhhlhhhhhhhghhhhhhhhhhhhghghhhhhhhhhhhhghhhhghhhhhhhhhhhhhhhhllhhhhhhhhhhlhhhhhhhlhlhlhjjjjjjjjjjjjjjjjjjhlhcgggghghhhhhgghghgghgghgggggghhhhgggggghggggghhhgghhgggggogoggggghggghhgoogogoogggooogogogoggogogogogoggghhgggghhhhhghhgoghghhghhhhhhhgggoogggggh", +"ghghhhhhhhhhlhhhhhhhhhhhghhhhghhghghhghghhghggghhhhhhhhhhhhhghhhgghghghggghghghghghhghhghggghghgggggggghhhhhlhlhhhhhhhghhhhghggggggghghghgghgggggghhhhhhhhhghhhhhhhhhghhgghgggghhhhhhhhhghhhhhghhhhhhhhhhhhhhhhhhhllhhhhhhhhhhhhhhhhhhhlhlllljjjjjjjjjjjjljlhllhhghhghghhghgggghgghggggghhhhhhhhhghggggghgggggggghhggggogggogogggggggggggggggoggogggggggggggogoggghggggggghggggogggggggggoggggggoggggggggggggggg", +"hhhhhhhlhhhhhhhhhhhhhhhhhhghghghghghggggggggggggghhhhhhhhghghggggghghhghhhhhhhhghggghgghghhggggggggggggghhhhhhhhhhhhhhhhghgggghghgghghhghghgghggghhhhhhhhgggghghghghgghghghghhhhhhhhhlhhhhhghhghhhhhhhhhhhhhhlhhhhhhhhhhhhhhhhhlhhhhhlhhhlhhhhjljjjjjjllhhhhhhhhhhhggggogghhghhhggggggggggggghhhhhgghggghgggggggghhhhgggggggogoggggggggggggogogoggggggggggggggggggggggogggggggggogggggggoggggggghggghggggggggggg", +"hhhhhhhhhhhhhhhhhhhhhhhhhghhggggggggggggggggoggggggghghhghghghgghgghghhhhhhhhhhhghghgggggghghhhghggggghghhhhhhhhhhhhhhghhghhhghghgggghhghghghhhhhhghhhhghghgggggghggghghhhhhhhhhhhhhhhhhhhgggghhhhhhhhllhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhlhhlhlhhhlljjhjhlhlhhhhhhggggggggggggggggggggooggggggggggggggghghggggoggghgghhggggggggogogggooogggggoggogogogoggghghghhggggggggggooghhhhhgogggooggggogggghhhggggggghghghg", +"hhhhhhhghhhhhhhhhhhhhhhhghggggggggghhhghgggggggggghhghhhgghghghghghghhhhhhhhhgggggggghhghghghgghgggggggggggghhhhhhhhhhhhhhhhhhhggggghhhhhhhhghhhhhhhhhhgghghhhhghgghgghghghghhhhhhlhlhlhhhhhhhghhhhhhhhhhhhhhhhlhhhhhhghghhhhhhhhhhhhhlhhlhlhhlhhlhlhlhhhhhghhggggogggogggggghggggggghhggggggghgggggggggghggogggghghhggogggoggggoogggggggoggggggoggggggggggggggggggggggogggghhhghgggggggogoggggggggggggoggghhhhh", +"hhhhhhhhhhhhhhhhhhhhhhhggggggggggghghhhghhgggggggggghhghhhhghghggghhhhhhhhhhhghgggggggggghghghgggggogggggghhhghggghgghghhhhhhhhghgghghhhhhhhghghhhhhhghggghghhhhhhghghhghhghhhhhhhhlhjhlhhhhhhghhhhhhhhhhhhhhhhhhhhhhghhghghhhhhhhhhhhhlhlhhhhhhhhhlhhhgghggggggggghggghggghghhggoggghhhggggggggggghhgggghggggggghhhhgggogoggogoggggggggggghghgggggoggggogoogggggogggoggggghggggggoogogggggggghghghggogogogoggog", +"hhhhhhhhhhhhhggggggggggggggggghghghhhhhhgggggogggghgghhhhhhggggghghhhhhhhhhhghgggggggggghghhghgggogogggghhhhhggghggghghghhhhgggggghhhhhhhhhghggghhhhhhhghgghhhhhhhhhhhhhhhhhghhhhhhhhhhhhhhhhgghhghhhhhhghhhhhhhhhhhhgghhhhghhhlhhhhhhhhhhhhhhhhllhhlhhhhggggggoghghggoggoggggggggggghhgggggghggghghgggggggggggghhhhhgoogoggoggggooggghggggggggghggogoggggggggggggoggggggghghhhhggggggoggghgggggggggooooogogoggg", +"hghhhhhhhhhhggggggggggghhhhhhhhhhhhhhhhgghgggggggghghhhhhghghghhhhhhhhhhhhhggggggggggghhhhghhggggggggghghghgghhghghgggggghggghghgghhhhhhhhhhgggggghhhhhhhhhhgghghhhhhhhhhhhhhhhhlhhhhhhhhhhhhggghhhhhhhgghghhhhhhghghhhghghhhhhhhhhhhhhhhlhlhlhhhhlhhhhhgggggggggghgggggoggggggggggghhhggghggggggggggggggoogggghhhhgoggggggggggggogghhhggggogghhghggghggghgggggggggogooogghhhghhhhhggggghhgggogogogoogogoogogogg", +"ghghhhhhgggggggghhhhhhhhhhhhhhhhhhhhhhgghgggghghghghghgggggghhhhhhhhhhhhhhggggggggghghghggggghghgghhhhhhhhhhggggggggggggggghgghggghghhhhhhhgghghhhhghhhhhhhhhhhhhhhghhhhhhhhhhllhlhhhhhhhhhhhhghghhgggghhhhhhhhhhhhghghhghhhghhhhhhhhhhlhhhlhlhhlhhhhhhlghhggoggggggogghggogggggggghhghghggghgghggoggogggggggoogggggggggogoggogogggogghhggogghhhhhggggghhggggoooooooogggoggggghhghhhgghggggggogoghgghgggggoggggg", +"ghghggggggggggggghghhhhhhhhhlhhhhhhhhhhhgghggghggggggggghghhghghhhhhhhghhggggggggggggggggggggggghhghghhhhhhghgghghggggogggggggggggghhhhhhggggghghhhhghhhhhhhhhhhggghhhhhlhlhlhhlhhhhhhhhhhhhhghghghhhghhgghhhhlhlhhhghghhhghhhhhhhhhhhhhhhhlhhhhhhhlhhhhhlhhhggoggggggooggggoggggggghhhhggggghgggggggggggggogogghgggggghhggggggghhgggggogoggggggggggggggggggggogogoggooggggggggggggggogoggggoggggggggghggggogggg", +"hgggggghghggghghgghghhhhhhhhhhlhhhhhhhhghghhhghgggggghhhghghghhhhhhghghgghghhgggoogogogggghghhgghgghghghghghgghgggggggggggghggggggggghhggggghghhhhghghggghghhhhhhhghhhhhhlhlhlhhhhhhghhhlhhhhhgghhhhhhgghhhhhhhhhhhhhhhghghhhhhhhhhhhghhhhhhhhhhlhhhhhhhlhhhhhhhgggggghhggooggggggoggggggggghghhgooggggogogggggggggghhhhhhgggoghhhggogooggggggggggggogghhggogogoggoggggogggggggggggogogggooogoggoggggggggoggoggg", +"ghghghhghhhhhghgggggghhhhhhhlhhhlhhhhhghghghhghggggggghhgggghgggggghhhhhhhhggggggggoggggghghhhhghgggggggggggggggggggggoggghghghgggggggghggggggggghhhhghghgghhhhhhhghhlhhlhhlhlhhhhhghhhlhllhhhhhhhhhhhhhhhhhhhhhhhhhhhgggghhhhhhhhlhhhhhhhlhlhhhlhhhhhhhhlhhhhhhhhggggggogoggggggggggggggghggghgggoogogoggoogogggggghhhhhhgggggggggggogggggggooggogoggghgggoogoogoggogogoggghgggggggggggghggggggggggggggoggogogg", +"hhhhhhhhhghghggggggghhhhhhhhhhhhhhhhhhgggggggggggggghgggghgggghghghhhhhhhhgggggggoggggghhhhhhhhhghgghghhggggggggggggggggggggggggggghghghgghghgghhhhghghgghhhhhhhhggghhlhlhlhlhlhhhghhhhhlhlhhhhhhhhhhhhhhhhhhhhhhhhhhgggghhhhhhhlhhlhlhhlhhlhhhhhhhllhhhhlhhhhhhhhggggghggghggghgghhgggghhggggghggggoggggoggggggggogggghhhgghggggghgggggghgggggggggggggggooggogggggogogoggggghggggoooogoggggggggggggggggggoggggg", +"hhhhhhhhghggggggggghghhhhhhhhhhhhhhhhggggggggggggggggggggggghghghhhhhhhggggggggoggggghhhhhhhhhhhhghgghggggggghghggggogggogggggghgghggghghghgggggggghghhhhhhhlllhhhghhhhhlhhlhlhhhhhghhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhghhhhhgghhjljhlhhlhlhhlhhhhhhlhhhhlhjhhlhhjhhhhhggghhhoghhgggggghhggggogggghhggggggggoggggggggggggggoggghgggggghhggogggghgggggogggggoggggghghghhhgggggggggggggoggggggggggggogggoggggggogogggg", +"hhhhggggggggggggggghhhhhhhhhhhhhhhhggggggggggggghhhghghghghgghgghhhghgggghgggggggggghhhhhhhhhhhhghghggghgghhhhhghgggggggggggghggghgghgghhhgghgghghhgghghhhlllhlhhhhhhhhhhhhhhhhhhhgghhhhhhhhhhhhlllhlhhhhhhhhhghhhhhhhhhhhhhhhlhjhlhhlhhhhhhhhhlhlhhhhllhhlhjhllhhlhlhggggogooggggggggogggggoggggggooggogggggggggggggggggggghggggggggogoggggggooogogggggggggghghhhhhhhhhhhhggggggggoggghhhhhggggogggghggggoooogg", +"gggggghggggggggggghgghhhhhhhhhhghgghghggggggggghggggghghggghggghghggghghhhghgggghghhghhhhhhhhhhghhhghggggggghhghghgggggogoggggghgghghghhghghgghghhhghghhhhlhhlhlhhhhhhhhhhhhhhhhhhhghhhhhhhgghhhhlhjhlhlhhhhhhhhhhhhhhhhhhhhhhhhlljlhhhlhhhhhhhhhhlhjhhhjhlhhhgjhhhhhhhhoggoogggoogghggghgggggggggoggggogoggoogggggghgghggghggggggogogogoooggghggoggggggggghhhhhhhhhhhhhhhhggghgggogoggghhhhhggogoghhhhhhgggggog" +}; diff --git a/sys/amiga/ifchange b/sys/amiga/ifchange new file mode 100644 index 0000000..db3f4ea --- /dev/null +++ b/sys/amiga/ifchange @@ -0,0 +1,56 @@ +.KEY oper/a,tmp/a,real/a,f1,f2,f3,f4,f5 + +. ; miscellaneous script functions for the Amiga +. ; SCCS Id: @(#)ifchange 3.2 96/02/04 +. ; Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1992, 1993, 1996. +. ; NetHack may be freely redistributed. See license for details. + +FAILAT 6 +IF EQ "MOVE" + IF EXISTS + diff >T:mic -c + search from T:mic SEARCH "---" QUIET + IF WARN + echo "MOVE: no change" + delete + ELSE + echo "MOVE: copy" + copy clone + delete + ENDIF + ELSE + echo "MOVE: copy2" + copy clone + delete + ENDIF + QUIT +ENDIF + +IF EQ "TOUCH" + IF EXISTS + diff >T:mic -c + search from T:mic SEARCH "---" QUIET + IF NOT WARN + echo "TOUCH: touch" + IF NOT EQ "@" + setdate + ENDIF + IF NOT EQ "@" + setdate + ENDIF + IF NOT EQ "@" + setdate + ENDIF + IF NOT EQ "@" + setdate + ENDIF + IF NOT EQ "@" + setdate + ENDIF + ENDIF + ENDIF + QUIT +ENDIF + +echo "ifchange: '' not recognized" +quit 10 diff --git a/sys/amiga/mkdmake b/sys/amiga/mkdmake new file mode 100644 index 0000000..2d80c85 --- /dev/null +++ b/sys/amiga/mkdmake @@ -0,0 +1,14 @@ +GE/$@/%(left)/ +GE/$ + +#include "config.h" +#include "tile.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef _DCC +# include +# include +# include +#endif + +void panic(const char *); +void map_colors(void); +int BestMatch(int, int, int); + +extern pixval ColorMap[3][MAXCOLORMAPSIZE]; +extern int colorsinmap; + +/* + * WARNING: + * This program carries forth the assumption that the colormaps in all + * of the .txt files are the same. This is a bug. + */ + +struct { + int Height; + int Width; +} IFFScreen; + +/* + * We are using a hybrid form of our own design which we call a BMAP (for + * bitmap) form. It is an ILBM with the bitmaps already deinterleaved, + * completely uncompressed. + * This speeds the loading of the images from the games point of view because it + * does not have to deinterleave and uncompress them. + */ +#define ID_BMAP MAKE_ID( 'B', 'M', 'A', 'P' ) /* instead of ILBM */ +#define ID_BMHD MAKE_ID( 'B', 'M', 'H', 'D' ) /* Same as ILBM */ +#define ID_CAMG MAKE_ID( 'C', 'A', 'M', 'G' ) /* Same as ILBM */ +#define ID_CMAP MAKE_ID( 'C', 'M', 'A', 'P' ) /* Same as ILBM */ +#define ID_PDAT MAKE_ID( 'P', 'D', 'A', 'T' ) /* Extra data describing plane + * size due to graphics.library + * rounding requirements. + */ +#define ID_PLNE MAKE_ID( 'P', 'L', 'N', 'E' ) /* The planes of the image */ + + +#ifndef _DCC +extern +#endif +struct Library *IFFParseBase; + +int nplanes; + + +/* BMHD from IFF documentation */ +typedef struct { + UWORD w, h; + WORD x, y; + UBYTE nPlanes; + UBYTE masking; + UBYTE compression; + UBYTE reserved1; + UWORD transparentColor; + UBYTE xAspect, yAspect; + WORD pageWidth, pageHeight; +} BitMapHeader; + +typedef struct { + UBYTE r, g, b; +} AmiColorMap; + +pixel pixels[TILE_Y][TILE_X]; +AmiColorMap *cmap; + + +int findcolor( register pixel *pix ); +void packwritebody( pixel (*tile)[TILE_X], char **planes, int tileno ); + + +void +error( char *str ) +{ + fprintf( stderr, "ERROR: %s\n", str ); +} + +/* + * This array maps the image colors to the amiga's first 16 colors. The colors + * are reordered to help with maintaining dripen settings. + */ +int colrmap[] = { 0, 6, 9, 15, 4, 10, 2, 3, 5, 11, 7, 13, 8, 1, 14, 12 }; + +/* How many tiles fit across and down. */ + +#define COLS 20 +#define ROWS ((tiles + COLS-1) / COLS) + +main( int argc, char **argv ) +{ + int colors; + struct { + long nplanes; + long pbytes; + long across; + long down; + long npics; + long xsize; + long ysize; + } pdat; + long pbytes; /* Bytes of data in a plane */ + int i, cnt; + BitMapHeader bmhd; + struct IFFHandle *iff; + long camg = HIRES|LACE; + int tiles=0; + char **planes; + + if(argc != 3){ + fprintf(stderr, "Usage: %s source destination\n", argv[0]); + exit(1); + } + +#if defined(_DCC) || defined(__GNUC__) + IFFParseBase = OpenLibrary( "iffparse.library", 0 ); + if( !IFFParseBase ) { + error( "unable to open iffparse.library" ); + exit( 1 ); + } +#endif + + /* First, count the files in the file */ + if( fopen_text_file( argv[1], "r" ) != TRUE ) + { + perror( argv[1] ); + return( 1 ); + } + + nplanes = 0; + i = colorsinmap-1; /*IFFScreen.Colors - 1; */ + while( i != 0 ) + { + nplanes++; + i >>= 1; + } + + planes = malloc( nplanes * sizeof( char * ) ); + if( planes == 0 ) + { + error( "can not allocate planes pointer" ); + exit( 1 ); + } + + while( read_text_tile( pixels ) == TRUE ) + ++tiles; + fclose_text_file(); + + IFFScreen.Width = COLS * TILE_X; + IFFScreen.Height = ROWS * TILE_Y; + + pbytes = (COLS * ROWS * TILE_X + 15) / 16 * 2 * TILE_Y; + + for( i = 0; i < nplanes; ++i ) + { + planes[ i ] = calloc( 1, pbytes ); + if( planes[ i ] == 0 ) + { + error( "can not allocate planes pointer" ); + exit( 1 ); + } + } + + /* Now, process it */ + if( fopen_text_file( argv[1], "r" ) != TRUE ) + { + perror( argv[1] ); + return( 1 ); + } + + iff = AllocIFF(); + if( !iff ) + { + error( "Can not allocate IFFHandle" ); + return( 1 ); + } + + iff->iff_Stream = Open( argv[2], MODE_NEWFILE ); + if( !iff->iff_Stream ) + { + error( "Can not open output file" ); + return( 1 ); + } + + InitIFFasDOS( iff ); + OpenIFF( iff, IFFF_WRITE ); + + PushChunk( iff, ID_BMAP, ID_FORM, IFFSIZE_UNKNOWN ); + + bmhd.w = IFFScreen.Width; + bmhd.h = IFFScreen.Height; + bmhd.x = 0; + bmhd.y = 0; + bmhd.nPlanes = nplanes; + bmhd.masking = 0; + bmhd.compression = 0; + bmhd.reserved1 = 0; + bmhd.transparentColor = 0; + bmhd.xAspect = 100; + bmhd.yAspect = 100; + bmhd.pageWidth = TILE_X; + bmhd.pageHeight = TILE_Y; + + PushChunk( iff, ID_BMAP, ID_BMHD, sizeof( bmhd ) ); + WriteChunkBytes( iff, &bmhd, sizeof( bmhd ) ); + PopChunk( iff ); + + PushChunk( iff, ID_BMAP, ID_CAMG, sizeof( camg ) ); + WriteChunkBytes( iff, &camg, sizeof( camg ) ); + PopChunk( iff ); + + /* We need to reorder the colors to get reasonable default pens but + * we also need to know where some of the colors are - so go find out. + */ + map_colors(); + + cmap = malloc( (colors = (1L<iff_Stream ); + FreeIFF( iff ); + + printf( "\n%d tiles converted\n", cnt ); + +#if defined(_DCC) || defined(__GNUC__) + CloseLibrary( IFFParseBase ); +#endif + exit( 0 ); +} + +findcolor( register pixel *pix ) +{ + register int i; + + for( i = 0; i < MAXCOLORMAPSIZE; ++i ) + { + if( (pix->r == ColorMap[ CM_RED ][i] ) && + (pix->g == ColorMap[ CM_GREEN ][i] ) && + (pix->b == ColorMap[ CM_BLUE ][i] ) ) + { + return( i ); + } + } + return( -1 ); +} + +void +packwritebody( pixel (*tile)[TILE_X], char **planes, int tileno ) +{ + register int i, j, k, col; + register char *buf; + register int across, rowbytes, xoff, yoff; + + /* how many tiles fit across? */ + across = COLS; + + /* How many bytes per pixel row */ + rowbytes = ((IFFScreen.Width + 15)/16)*2; + + /* How many bytes to account for y distance in planes */ + yoff = ((tileno / across) * TILE_Y) * rowbytes; + + /* How many bytes to account for x distance in planes */ + xoff = (tileno % across) * (TILE_X/8); + + /* For each row... */ + for( i = 0; i < TILE_Y; ++i ) + { + /* For each bitplane... */ + for( k = 0; k < nplanes; ++k ) + { + const int mask = 1l< rate){ + bestrate = rate; + bestslot = x; + } + } +#ifdef DBG + printf("map (%d,%d,%d) -> %d (error=%d)\n",r,g,b,bestslot,bestrate); +#endif + return bestslot; +} + + +long * +alloc( unsigned int n ) +{ + long *ret = malloc( n ); + if(!ret){ + error("Can't allocate memory"); + exit(1); + } + return( ret ); +} + +void +panic(const char *msg){ + fprintf(stderr,"PANIC: %s\n",msg); + exit(1); +} diff --git a/sys/amiga/winami.c b/sys/amiga/winami.c new file mode 100644 index 0000000..2f214b4 --- /dev/null +++ b/sys/amiga/winami.c @@ -0,0 +1,1723 @@ +/* SCCS Id: @(#)winami.c 3.2 2000/01/12 */ +/* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993,1996. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "NH:sys/amiga/windefs.h" +#include "NH:sys/amiga/winext.h" +#include "NH:sys/amiga/winproto.h" +#include "dlb.h" + +#ifdef AMIGA_INTUITION + +static int FDECL( put_ext_cmd, ( char *, int, struct amii_WinDesc *, int ) ); + +struct amii_DisplayDesc *amiIDisplay; /* the Amiga Intuition descriptor */ +struct Rectangle lastinvent, lastmsg; +int clipping = 0; +int clipx=0; +int clipy=0; +int clipxmax=0; +int clipymax=0; +int scrollmsg = 1; +int alwaysinvent = 0; +int amii_numcolors; +long amii_scrnmode; + +/* Interface definition, for use by windows.c and winprocs.h to provide + * the intuition interface for the amiga... + */ +struct window_procs amii_procs = +{ + "amii", + WC_COLOR|WC_HILITE_PET|WC_INVERSE, + amii_init_nhwindows, + amii_player_selection, + amii_askname, + amii_get_nh_event, + amii_exit_nhwindows, + amii_suspend_nhwindows, + amii_resume_nhwindows, + amii_create_nhwindow, + amii_clear_nhwindow, + amii_display_nhwindow, + amii_destroy_nhwindow, + amii_curs, + amii_putstr, + amii_display_file, + amii_start_menu, + amii_add_menu, + amii_end_menu, + amii_select_menu, + genl_message_menu, + amii_update_inventory, + amii_mark_synch, + amii_wait_synch, +#ifdef CLIPPING + amii_cliparound, +#endif +#ifdef POSITIONBAR + donull, +#endif + amii_print_glyph, + amii_raw_print, + amii_raw_print_bold, + amii_nhgetch, + amii_nh_poskey, + amii_bell, + amii_doprev_message, + amii_yn_function, + amii_getlin, + amii_get_ext_cmd, + amii_number_pad, + amii_delay_output, +#ifdef CHANGE_COLOR /* only a Mac option currently */ + amii_change_color, + amii_get_color_string, +#endif + /* other defs that really should go away (they're tty specific) */ + amii_delay_output, + amii_delay_output, + amii_outrip, + genl_preference_update +}; + +/* The view window layout uses the same function names so we can use + * a shared library to allow the executable to be smaller. + */ +struct window_procs amiv_procs = +{ + "amitile", + WC_COLOR|WC_HILITE_PET|WC_INVERSE, + amii_init_nhwindows, + amii_player_selection, + amii_askname, + amii_get_nh_event, + amii_exit_nhwindows, + amii_suspend_nhwindows, + amii_resume_nhwindows, + amii_create_nhwindow, + amii_clear_nhwindow, + amii_display_nhwindow, + amii_destroy_nhwindow, + amii_curs, + amii_putstr, + amii_display_file, + amii_start_menu, + amii_add_menu, + amii_end_menu, + amii_select_menu, + genl_message_menu, + amii_update_inventory, + amii_mark_synch, + amii_wait_synch, +#ifdef CLIPPING + amii_cliparound, +#endif +#ifdef POSITIONBAR + donull, +#endif + amii_print_glyph, + amii_raw_print, + amii_raw_print_bold, + amii_nhgetch, + amii_nh_poskey, + amii_bell, + amii_doprev_message, + amii_yn_function, + amii_getlin, + amii_get_ext_cmd, + amii_number_pad, + amii_delay_output, +#ifdef CHANGE_COLOR /* only a Mac option currently */ + amii_change_color, + amii_get_color_string, +#endif + /* other defs that really should go away (they're tty specific) */ + amii_delay_output, + amii_delay_output, + amii_outrip, + genl_preference_update +}; + +unsigned short amii_initmap[ AMII_MAXCOLORS ]; +/* Default pens used unless user overides in nethack.cnf. */ +unsigned short amii_init_map[ AMII_MAXCOLORS ] = +{ + 0x0000, /* color #0 C_BLACK */ + 0x0FFF, /* color #1 C_WHITE */ + 0x0830, /* color #2 C_BROWN */ + 0x07ac, /* color #3 C_CYAN */ + 0x0181, /* color #4 C_GREEN */ + 0x0C06, /* color #5 C_MAGENTA */ + 0x023E, /* color #6 C_BLUE */ + 0x0c00, /* color #7 C_RED */ +}; + +unsigned short amiv_init_map[ AMII_MAXCOLORS ] = +{ + 0x0000, /* color #0 C_BLACK */ + 0x0fff, /* color #1 C_WHITE */ + 0x00bf, /* color #2 C_CYAN */ + 0x0f60, /* color #3 C_ORANGE */ + 0x000f, /* color #4 C_BLUE */ + 0x0090, /* color #5 C_GREEN */ + 0x069b, /* color #6 C_GREY */ + 0x0f00, /* color #7 C_RED */ + 0x06f0, /* color #8 C_LTGREEN */ + 0x0ff0, /* color #9 C_YELLOW */ + 0x0f0f, /* color #10 C_MAGENTA */ + 0x0940, /* color #11 C_BROWN */ + 0x0466, /* color #12 C_GREYBLUE */ + 0x0c40, /* color #13 C_LTBROWN */ + 0x0ddb, /* color #14 C_LTGREY */ + 0x0fb9, /* color #15 C_PEACH */ + + /* Pens for dripens etc under AA or better */ + 0x0222, /* color #16 */ + 0x0fdc, /* color #17 */ + 0x0000, /* color #18 */ + 0x0ccc, /* color #19 */ + 0x0bbb, /* color #20 */ + 0x0BA9, /* color #21 */ + 0x0999, /* color #22 */ + 0x0987, /* color #23 */ + 0x0765, /* color #24 */ + 0x0666, /* color #25 */ + 0x0555, /* color #26 */ + 0x0533, /* color #27 */ + 0x0333, /* color #28 */ + 0x018f, /* color #29 */ + 0x0f81, /* color #30 */ + 0x0fff, /* color #31 */ +}; + +#if !defined( TTY_GRAPHICS ) || defined( SHAREDLIB ) /* this should be shared better */ +char morc; /* the character typed in response to a --more-- prompt */ +#endif +char spaces[ 76 ] = +" "; + +winid WIN_BASE = WIN_ERR; +winid WIN_OVER = WIN_ERR; +winid amii_rawprwin = WIN_ERR; + +/* Changed later during window/screen opens... */ +int txwidth = FONTWIDTH, txheight = FONTHEIGHT, txbaseline = FONTBASELINE; + +/* If a 240 or more row screen is in front when we start, this will be + * set to 1, and the windows will be given borders to allow them to be + * arranged differently. The Message window may eventually get a scroller... + */ +int bigscreen = 0; + +/* This gadget data is replicated for menu/text windows... */ +struct PropInfo PropScroll = { AUTOKNOB|FREEVERT, + 0xffff,0xffff, 0xffff,0xffff, }; +struct Image Image1 = { 0,0, 7,102, 0, NULL, 0x0000,0x0000, NULL }; +struct Gadget MenuScroll = { + NULL, -15,10, 15,-19, GRELRIGHT|GRELHEIGHT, + RELVERIFY|FOLLOWMOUSE|RIGHTBORDER|GADGIMMEDIATE|RELVERIFY, + PROPGADGET, (APTR)&Image1, NULL, NULL, NULL, (APTR)&PropScroll, + 1, NULL +}; + +/* This gadget is for the message window... */ +struct PropInfo MsgPropScroll = { AUTOKNOB|FREEVERT, + 0xffff,0xffff, 0xffff,0xffff, }; +struct Image MsgImage1 = { 0,0, 7,102, 0, NULL, 0x0000,0x0000, NULL }; +struct Gadget MsgScroll = { + NULL, -15,10, 14,-19, GRELRIGHT|GRELHEIGHT, + RELVERIFY|FOLLOWMOUSE|RIGHTBORDER|GADGIMMEDIATE|RELVERIFY, + PROPGADGET, (APTR)&MsgImage1, NULL, NULL, NULL, (APTR)&MsgPropScroll, + 1, NULL +}; + +int wincnt=0; /* # of nh windows opened */ + +/* We advertise a public screen to allow some people to do other things + * while they are playing... like compiling... + */ + +#ifdef INTUI_NEW_LOOK +extern struct Hook fillhook; +struct TagItem tags[] = +{ + { WA_BackFill, (ULONG)&fillhook }, + { WA_PubScreenName, (ULONG)"NetHack" }, + { TAG_DONE, 0 }, +}; +#endif + +/* + * The default dimensions and status values for each window type. The + * data here is generally changed in create_nhwindow(), so beware that + * what you see here may not be exactly what you get. + */ +struct win_setup new_wins[] = +{ + + /* First entry not used, types are based at 1 */ + {{0}}, + + /* NHW_MESSAGE */ + {{0,1,640,11, + 0xff,0xff, + NEWSIZE|GADGETUP|GADGETDOWN|MOUSEMOVE|MOUSEBUTTONS|RAWKEY, + BORDERLESS|ACTIVATE|SMART_REFRESH +#ifdef INTUI_NEW_LOOK + |WFLG_NW_EXTENDED +#endif + , + NULL,NULL,(UBYTE*)"Messages",NULL,NULL,320,40,0xffff,0xffff, +#ifdef INTUI_NEW_LOOK + PUBLICSCREEN,tags +#else + CUSTOMSCREEN +#endif + }, + 0,0,1,1,80,80}, + + /* NHW_STATUS */ + {{0,181,640,24, + 0xff,0xff, + RAWKEY|MENUPICK|DISKINSERTED, + BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP +#ifdef INTUI_NEW_LOOK + |WFLG_NW_EXTENDED +#endif + , + NULL,NULL,(UBYTE*)"Game Status",NULL,NULL,0,0,0xffff,0xffff, +#ifdef INTUI_NEW_LOOK + PUBLICSCREEN,tags +#else + CUSTOMSCREEN +#endif + }, + 0,0,2,2,78,78}, + + /* NHW_MAP */ + {{0,0,WIDTH,WINDOWHEIGHT, + 0xff,0xff, + RAWKEY|MENUPICK|MOUSEBUTTONS|ACTIVEWINDOW|MOUSEMOVE, + BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP +#ifdef INTUI_NEW_LOOK + |WFLG_NW_EXTENDED +#endif + , + NULL,NULL,(UBYTE*)"Dungeon Map",NULL,NULL,64,64,0xffff,0xffff, +#ifdef INTUI_NEW_LOOK + PUBLICSCREEN,tags +#else + CUSTOMSCREEN +#endif + }, + 0,0,22,22,80,80}, + + /* NHW_MENU */ + {{400,10,10,10, + 0xff,0xff, + RAWKEY|MENUPICK|DISKINSERTED|MOUSEMOVE|MOUSEBUTTONS| + GADGETUP|GADGETDOWN|CLOSEWINDOW|VANILLAKEY|NEWSIZE|INACTIVEWINDOW, + WINDOWSIZING|WINDOWCLOSE|WINDOWDRAG|ACTIVATE|SMART_REFRESH +#ifdef INTUI_NEW_LOOK + |WFLG_NW_EXTENDED +#endif + , + &MenuScroll,NULL,NULL,NULL,NULL,64,32,0xffff,0xffff, +#ifdef INTUI_NEW_LOOK + PUBLICSCREEN,tags +#else + CUSTOMSCREEN +#endif + }, + 0,0,1,1,22,78}, + + /* NHW_TEXT */ + {{0,0,640,200, + 0xff,0xff, + RAWKEY|MENUPICK|DISKINSERTED|MOUSEMOVE| + GADGETUP|CLOSEWINDOW|VANILLAKEY|NEWSIZE, + WINDOWSIZING|WINDOWCLOSE|WINDOWDRAG|ACTIVATE|SMART_REFRESH +#ifdef INTUI_NEW_LOOK + |WFLG_NW_EXTENDED +#endif + , + &MenuScroll,NULL,(UBYTE*)NULL,NULL,NULL,100,32,0xffff,0xffff, +#ifdef INTUI_NEW_LOOK + PUBLICSCREEN,tags +#else + CUSTOMSCREEN +#endif + }, + 0,0,1,1,22,78}, + + /* NHW_BASE */ + {{0,0,WIDTH,WINDOWHEIGHT, + 0xff,0xff, + RAWKEY|MENUPICK|MOUSEBUTTONS, + BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP +#ifdef INTUI_NEW_LOOK + |WFLG_NW_EXTENDED +#endif + , + NULL,NULL,(UBYTE*)NULL,NULL,NULL,-1,-1,0xffff,0xffff, +#ifdef INTUI_NEW_LOOK + PUBLICSCREEN,tags +#else + CUSTOMSCREEN +#endif + }, + 0,0,22,22,80,80}, + + /* NHW_OVER */ + {{320,20,319,179, + 0xff,0xff, + RAWKEY|MENUPICK|MOUSEBUTTONS, + BORDERLESS|ACTIVATE|SMART_REFRESH|BACKDROP +#ifdef INTUI_NEW_LOOK + |WFLG_NW_EXTENDED +#endif + , + NULL,NULL,(UBYTE*)NULL,NULL,NULL,64,32,0xffff,0xffff, +#ifdef INTUI_NEW_LOOK + PUBLICSCREEN,tags +#else + CUSTOMSCREEN +#endif + }, + 0,0,22,22,80,80}, +}; + +const char winpanicstr[] = "Bad winid %d in %s()"; + +/* The opened windows information */ +struct amii_WinDesc *amii_wins[ MAXWIN + 1 ]; + +#ifdef INTUI_NEW_LOOK +/* + * NUMDRIPENS varies based on headers, so don't use it + * here, its value is used elsewhere. + */ +UWORD amii_defpens[ 20 ]; + +struct TagItem scrntags[] = +{ + { SA_PubName, (ULONG)"NetHack" }, + { SA_Overscan, OSCAN_TEXT }, + { SA_AutoScroll, TRUE }, +#if LIBRARY_VERSION >= 39 + { SA_Interleaved, TRUE }, +#endif + { SA_Pens, (ULONG)0 }, + { SA_DisplayID, 0 }, + { TAG_DONE, 0 }, +}; + +#endif + +struct NewScreen NewHackScreen = +{ + 0, 0, WIDTH, SCREENHEIGHT, 3, + 0, 1, /* DetailPen, BlockPen */ + HIRES, + CUSTOMSCREEN +#ifdef INTUI_NEW_LOOK + |NS_EXTENDED +#endif + , + &Hack80, /* Font */ + NULL, /*(UBYTE *)" NetHack X.Y.Z" */ + NULL, /* Gadgets */ + NULL, /* CustomBitmap */ +#ifdef INTUI_NEW_LOOK + scrntags +#endif +}; + +/* + * plname is filled either by an option (-u Player or -uPlayer) or + * explicitly (by being the wizard) or by askname. + * It may still contain a suffix denoting pl_character. + * Always called after init_nhwindows() and before display_gamewindows(). + */ +void +amii_askname() +{ + char plnametmp[300]; /* From winreq.c: sizeof(StrStringSIBuff) */ + *plnametmp = 0; + do { + amii_getlin( "Who are you?", plnametmp ); + } while( strlen( plnametmp ) == 0 ); + + strncpy(plname, plnametmp, PL_NSIZ-1); /* Avoid overflowing plname[] */ + plname[PL_NSIZ-1] = 0; + + if( *plname == '\33' ) + { + clearlocks(); + exit_nhwindows(NULL); + terminate(0); + } +} + +/* Discarded ... -jhsa +#include "NH:sys/amiga/char.c" +*/ + +/* Get the player selection character */ + +#if 0 /* New function at the bottom */ +void +amii_player_selection() +{ + register struct Window *cwin; + register struct IntuiMessage *imsg; + register int aredone = 0; + register struct Gadget *gd; + static int once = 0; + long class, code; + + amii_clear_nhwindow( WIN_BASE ); + if (validrole(flags.initrole)) + return; + else { + flags.initrole=randrole(); + return; + } +#if 0 /* Don't query the user ... instead give random character -jhsa */ + +#if 0 /* OBSOLETE */ + if( *pl_character ){ + pl_character[ 0 ] = toupper( pl_character[ 0 ] ); + if( index( pl_classes, pl_character[ 0 ] ) ) + return; + } +#endif + + if( !once ){ + if( bigscreen ){ + Type_NewWindowStructure1.TopEdge = + (HackScreen->Height/2) - (Type_NewWindowStructure1.Height/2); + } + for( gd = Type_NewWindowStructure1.FirstGadget; gd; + gd = gd->NextGadget ) + { + if( gd->GadgetID != 0 ) + SetBorder( gd ); + } + once = 1; + } + + if( WINVERS_AMIV ) + { +# ifdef INTUI_NEW_LOOK + Type_NewWindowStructure1.Extension = wintags; + Type_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED; + fillhook.h_Entry = (ULONG(*)())LayerFillHook; + fillhook.h_Data = (void *)-2; + fillhook.h_SubEntry = 0; +#endif + } + + Type_NewWindowStructure1.Screen = HackScreen; + if( ( cwin = OpenShWindow( (void *)&Type_NewWindowStructure1 ) ) == NULL ) + { + return; + } +#if 0 + WindowToFront( cwin ); +#endif + + while( !aredone ) + { + WaitPort( cwin->UserPort ); + while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL ) + { + class = imsg->Class; + code = imsg->Code; + gd = (struct Gadget *)imsg->IAddress; + ReplyMsg( (struct Message *)imsg ); + + switch( class ) + { + case VANILLAKEY: + if( index( pl_classes, toupper( code ) ) ) + { + pl_character[0] = toupper( code ); + aredone = 1; + } + else if( code == ' ' || code == '\n' || code == '\r' ) + { + flags.initrole = randrole(); +#if 0 /* OBSOLETE */ +#ifdef TOURIST + strcpy( pl_character, roles[ rnd( 11 ) ] ); +#else + strcpy( pl_character, roles[ rnd( 10 ) ] ); +#endif +#endif + aredone = 1; + amii_clear_nhwindow( WIN_BASE ); + CloseShWindow( cwin ); + RandomWindow( pl_character ); + return; + } + else if( code == 'q' || code == 'Q' ) + { + CloseShWindow( cwin ); + clearlocks(); + exit_nhwindows(NULL); + terminate(0); + } + else + DisplayBeep( NULL ); + break; + + case GADGETUP: + switch( gd->GadgetID ) + { + case 1: /* Random Character */ + flags.initrole = randrole(); +#if 0 /* OBSOLETE */ +#ifdef TOURIST + strcpy( pl_character, roles[ rnd( 11 ) ] ); +#else + strcpy( pl_character, roles[ rnd( 10 ) ] ); +#endif +#endif + amii_clear_nhwindow( WIN_BASE ); + CloseShWindow( cwin ); + RandomWindow( pl_character ); + return; + + default: + pl_character[0] = gd->GadgetID; + break; + } + aredone = 1; + break; + + case CLOSEWINDOW: + CloseShWindow( cwin ); + clearlocks(); + exit_nhwindows(NULL); + terminate(0); + break; + } + } + } + amii_clear_nhwindow( WIN_BASE ); + CloseShWindow( cwin ); +#endif /* Do not query user ... -jhsa */ +} +#endif /* Function elsewhere */ + +#if 0 /* Unused ... -jhsa */ + +#include "NH:sys/amiga/randwin.c" + +void +RandomWindow( name ) + char *name; +{ + struct MsgPort *tport; + struct timerequest *trq; + static int once = 0; + struct Gadget *gd; + struct Window *w; + struct IntuiMessage *imsg; + int ticks = 0, aredone = 0, timerdone = 0; + long mask, got; + + tport = CreateMsgPort(); + trq = (struct timerequest *)CreateIORequest( tport, sizeof( *trq ) ); + if( tport == NULL || trq == NULL ) + { +allocerr: + if( tport ) DeleteMsgPort( tport ); + if( trq ) DeleteIORequest( (struct IORequest *)trq ); + Delay( 8 * 50 ); + return; + } + + if( OpenDevice( TIMERNAME, UNIT_VBLANK, (struct IORequest *)trq, 0L ) != 0 ) + goto allocerr; + + trq->tr_node.io_Command = TR_ADDREQUEST; + trq->tr_time.tv_secs = 8; + trq->tr_time.tv_micro = 0; + + SendIO( (struct IORequest *)trq ); + + /* Place the name in the center of the screen */ + Rnd_IText5.IText = name; + Rnd_IText6.LeftEdge = Rnd_IText4.LeftEdge + + (strlen(Rnd_IText4.IText)+1)*8; + Rnd_NewWindowStructure1.Width = ( + (strlen( Rnd_IText2.IText )+1) * 8 ) + + HackScreen->WBorLeft + HackScreen->WBorRight; + Rnd_IText5.LeftEdge = (Rnd_NewWindowStructure1.Width - + (strlen(name)*8))/2; + + gd = Rnd_NewWindowStructure1.FirstGadget; + gd->LeftEdge = (Rnd_NewWindowStructure1.Width - gd->Width)/2; + /* Chose correct modifier */ + Rnd_IText6.IText = "a"; + switch( *name ) + { + case 'a': case 'e': case 'i': case 'o': + case 'u': case 'A': case 'E': case 'I': + case 'O': case 'U': + Rnd_IText6.IText = "an"; + break; + } + + if( !once ) + { + if( bigscreen ) + { + Rnd_NewWindowStructure1.TopEdge = + (HackScreen->Height/2) - (Rnd_NewWindowStructure1.Height/2); + } + for( gd = Rnd_NewWindowStructure1.FirstGadget; gd; gd = gd->NextGadget ) + { + if( gd->GadgetID != 0 ) + SetBorder( gd ); + } + Rnd_NewWindowStructure1.IDCMPFlags |= VANILLAKEY; + + once = 1; + } + + if( WINVERS_AMIV ) + { +#ifdef INTUI_NEW_LOOK + Rnd_NewWindowStructure1.Extension = wintags; + Rnd_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED; + fillhook.h_Entry = (ULONG(*)())LayerFillHook; + fillhook.h_Data = (void *)-2; + fillhook.h_SubEntry = 0; +#endif + } + + Rnd_NewWindowStructure1.Screen = HackScreen; + if( ( w = OpenShWindow( (void *)&Rnd_NewWindowStructure1 ) ) == NULL ) + { + AbortIO( (struct IORequest *)trq ); + WaitIO( (struct IORequest *)trq ); + CloseDevice( (struct IORequest *)trq ); + DeleteIORequest( (struct IORequest *) trq ); + DeleteMsgPort( tport ); + Delay( 50 * 8 ); + return; + } + + PrintIText( w->RPort, &Rnd_IntuiTextList1, 0, 0 ); + + mask = (1L << tport->mp_SigBit)|(1L << w->UserPort->mp_SigBit); + while( !aredone ) + { + got = Wait( mask ); + if( got & (1L << tport->mp_SigBit ) ) + { + aredone = 1; + timerdone = 1; + GetMsg( tport ); + } + while( w && ( imsg = (struct IntuiMessage *) GetMsg( w->UserPort ) ) ) + { + switch( (long)imsg->Class ) + { + /* Must be up for a little while... */ + case INACTIVEWINDOW: + if( ticks >= 40 ) + aredone = 1; + break; + + case INTUITICKS: + ++ticks; + break; + + case GADGETUP: + aredone = 1; + break; + + case VANILLAKEY: + if(imsg->Code=='\n' || imsg->Code==' ' || imsg->Code=='\r') + aredone = 1; + break; + } + ReplyMsg( (struct Message *)imsg ); + } + } + + if( !timerdone ) + { + AbortIO( (struct IORequest *)trq ); + WaitIO( (struct IORequest *)trq ); + } + + CloseDevice( (struct IORequest *)trq ); + DeleteIORequest( (struct IORequest *) trq ); + DeleteMsgPort( tport ); + if(w) CloseShWindow( w ); +} +#endif /* Discarded randwin ... -jhsa */ + +/* this should probably not be needed (or be renamed) +void +flush_output(){} */ + +/* Read in an extended command - doing command line completion for + * when enough characters have been entered to make a unique command. + */ +int +amii_get_ext_cmd( void ) +{ + menu_item *mip; + anything id; + struct amii_WinDesc *cw; +#ifdef EXTMENU + winid win; + int i; + char buf[256]; +#endif + int colx; + int bottom = 0; + struct Window *w; + char obufp[ 100 ]; + register char *bufp = obufp; + register int c; + int com_index, oindex; + int did_comp=0; /* did successful completion? */ + int sel = -1; + + if( WIN_MESSAGE == WIN_ERR || ( cw = amii_wins[ WIN_MESSAGE ] ) == NULL ) + panic(winpanicstr, WIN_MESSAGE, "get_ext_cmd"); + w = cw->win; + bottom = amii_msgborder( w ); + colx = 3; + +#ifdef EXTMENU + if (iflags.extmenu) { + win = amii_create_nhwindow( NHW_MENU ); + amii_start_menu( win ); + pline("#"); + amii_putstr( WIN_MESSAGE, -1, " " ); + + for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i ) + { + id.a_char = *extcmdlist[ i ].ef_txt; + sprintf( buf, "%-10s - %s ", + extcmdlist[ i ].ef_txt, + extcmdlist[ i ].ef_desc ); + amii_add_menu( win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0, 0, buf, MENU_UNSELECTED); + } + + amii_end_menu( win, (char*)0 ); + sel = amii_select_menu( win, PICK_ONE, &mip ); + amii_destroy_nhwindow( win ); + + if( sel == 1 ) + { + sel = mip->item.a_char; + for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i ) + { + if( sel == extcmdlist[i].ef_txt[0] ) + break; + } + + /* copy in the text */ + if( extcmdlist[ i ].ef_txt != NULL ) + { + amii_clear_nhwindow( WIN_MESSAGE ); + (void) put_ext_cmd( (char *)extcmdlist[i].ef_txt, 0, cw, bottom ); + return( i ); + } + else + DisplayBeep( NULL ); + } + + return( -1 ); + } else { +#else + + amii_clear_nhwindow( WIN_MESSAGE ); /* Was NHW_MESSAGE */ + if( scrollmsg ) + { + pline("#"); + amii_addtopl(" "); + } + else + { + pline("# "); + } + + sel = -1; + while((c = WindowGetchar()) != EOF) + { + amii_curs( WIN_MESSAGE, colx, bottom ); + if(c == '?' ) + { + int win, i; + char buf[ 100 ]; + + if(did_comp){ + while(bufp!=obufp) + { + bufp--; + amii_curs(WIN_MESSAGE, --colx, bottom); + Text(w->RPort,spaces,1); + amii_curs(WIN_MESSAGE,colx,bottom); + did_comp=0; + } + } + + win = amii_create_nhwindow( NHW_MENU ); + amii_start_menu( win ); + + for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i ) + { + id.a_char = extcmdlist[i].ef_txt[0]; + sprintf( buf, "%-10s - %s ", + extcmdlist[ i ].ef_txt, + extcmdlist[ i ].ef_desc ); + amii_add_menu( win, NO_GLYPH, &id, extcmdlist[i].ef_txt[0], 0, + 0, buf, MENU_UNSELECTED); + } + + amii_end_menu( win, (char*)0 ); + sel = amii_select_menu( win, PICK_ONE, &mip ); + amii_destroy_nhwindow( win ); + + if( sel == 0 ) + { + return( -1 ); + } + else + { + sel = mip->item.a_char; + for( i = 0; extcmdlist[ i ].ef_txt != NULL; ++i ) + { + if( sel == extcmdlist[i].ef_txt[0] ) + break; + } + + /* copy in the text */ + if( extcmdlist[ i ].ef_txt != NULL ) + { + amii_clear_nhwindow( WIN_MESSAGE ); + strcpy( bufp = obufp, extcmdlist[ i ].ef_txt ); + (void) put_ext_cmd( obufp, colx, cw, bottom ); + return( i ); + } + else + DisplayBeep( NULL ); + } + } + else if(c == '\033') + { + return( -1 ); + } + else if(c == '\b') + { + if(did_comp){ + while(bufp!=obufp){ + bufp--; + amii_curs(WIN_MESSAGE, --colx, bottom); + Text(w->RPort,spaces,1); + amii_curs(WIN_MESSAGE,colx,bottom); + did_comp=0; + sel = -1; + } + } + else if(bufp != obufp) + { + sel = -1; + bufp--; + amii_curs( WIN_MESSAGE, --colx, bottom); + Text( w->RPort, spaces, 1 ); + amii_curs( WIN_MESSAGE, colx, bottom); + } + else + DisplayBeep( NULL ); + } + else if( c == '\n' || c == '\r' ) + { + return(sel); + } + else if( c >= ' ' && c < '\177') + { + /* avoid isprint() - some people don't have it + ' ' is not always a printing char */ + *bufp = c; + bufp[1] = 0; + oindex = 0; + com_index = -1; + + while(extcmdlist[oindex].ef_txt != NULL) + { + if(!strnicmp(obufp, (char *)extcmdlist[oindex].ef_txt, strlen(obufp))) + { + if(com_index == -1) /* No matches yet*/ + com_index = oindex; + else /* More than 1 match */ + com_index = -2; + } + oindex++; + } + + if(com_index >= 0 && *obufp ) + { + Strcpy(obufp, extcmdlist[com_index].ef_txt); + /* finish printing our string */ + colx = put_ext_cmd( obufp, colx, cw, bottom ); + bufp = obufp; /* reset it */ + if(strlen(obufp) < BUFSZ-1 && strlen(obufp) < COLNO) + bufp += strlen(obufp); + did_comp=1; + sel = com_index; + } + else + { + colx = put_ext_cmd( obufp, colx, cw, bottom ); + if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO) + bufp++; + } + } + else if(c == ('X'-64) || c == '\177') + { + colx = 0; + amii_clear_nhwindow( WIN_MESSAGE ); + pline( "# " ); + bufp = obufp; + } else + DisplayBeep( NULL ); + } + return(-1); +#endif +} + +static int +put_ext_cmd( obufp, colx, cw, bottom ) + char *obufp; + int colx, bottom; + struct amii_WinDesc *cw; +{ + struct Window *w = cw->win; + char *t; + + t = (char *)alloc( strlen( obufp ) + 7 ); + if( t != NULL ) + { + if( scrollmsg ) + { + sprintf( t, "xxx%s", obufp ); + t[0] = 1; + t[1] = 1; + t[2] = '#'; + amii_curs( WIN_MESSAGE, 0, bottom); + SetAPen( w->RPort, C_WHITE ); + Text(w->RPort, "># ", 3 ); + /* SetAPen( w->RPort, C_BLACK ); */ /* Black text on black screen doesn't look too well ... -jhsa */ + Text(w->RPort, t+3, strlen( t ) - 3 ); + } + else + { + sprintf( t, "# %s", obufp ); + amii_curs( WIN_MESSAGE, 0, bottom); + SetAPen( w->RPort, C_WHITE ); + Text(w->RPort, t, strlen( t ) ); + } + if( scrollmsg ) + SetAPen( w->RPort, C_WHITE ); + if( cw->data[ cw->maxrow - 1 ] ) + free( cw->data[ cw->maxrow - 1 ] ); + cw->data[ cw->maxrow - 1 ] = t; + } + else + { + amii_curs( WIN_MESSAGE, 0, bottom); + SetAPen( w->RPort, C_WHITE ); + Text(w->RPort, "# ", 2 ); + /* SetAPen( w->RPort, C_BLACK ); */ /* Black on black ... -jhsa */ + Text(w->RPort, obufp, strlen( obufp ) ); + SetAPen( w->RPort, C_WHITE ); + } + amii_curs( WIN_MESSAGE, colx = strlen( obufp ) + 3 + ( scrollmsg != 0 ), bottom); + return( colx ); +} + +/* Ask a question and get a response */ + +char amii_yn_function(query, resp, def) +const char *query,*resp; +char def; +/* + * Generic yes/no function. 'def' is the default (returned by space or + * return; 'esc' returns 'q', or 'n', or the default, depending on + * what's in the string. The 'query' string is printed before the user + * is asked about the string. + * If resp is NULL, any single character is accepted and returned. + * If not-NULL, only characters in it are allowed (exceptions: the + * quitchars are always allowed, and if it contains '#' then digits + * are allowed); if it includes an , anything beyond that won't + * be shown in the prompt to the user but will be acceptable as input. + */ +{ + register char q; + char rtmp[40]; + boolean digit_ok, allow_num; + char prompt[QBUFSZ]; + register struct amii_WinDesc *cw; + + if( cw = amii_wins[ WIN_MESSAGE ] ) + cw->disprows = 0; + if (resp) { + char *rb, respbuf[QBUFSZ]; + + allow_num = (index(resp, '#') != 0); + Strcpy(respbuf, resp); + /* any acceptable responses that follow aren't displayed */ + if ((rb = index(respbuf, '\033')) != 0) *rb = '\0'; + Sprintf(prompt, "%s [%s] ", query, respbuf); + if (def) Sprintf(eos(prompt), "(%c) ", def); + pline("%s", prompt); + } else { + amii_putstr(WIN_MESSAGE, 0, query); + cursor_on(WIN_MESSAGE); + q = WindowGetchar(); + cursor_off(WIN_MESSAGE); + *rtmp = q; + rtmp[ 1 ] = 0; + amii_addtopl(rtmp); + goto clean_up; + } + + do { /* loop until we get valid input */ + cursor_on(WIN_MESSAGE); + q = lowc(WindowGetchar()); + cursor_off(WIN_MESSAGE); +#if 0 +/* fix for PL2 */ + if (q == '\020') { /* ctrl-P */ + if(!doprev) (void) tty_doprev_message(); /* need two initially */ + (void) tty_doprev_message(); + q = (char)0; + doprev = 1; + continue; + } else if(doprev) { + tty_clear_nhwindow(WIN_MESSAGE); + cw->maxcol = cw->maxrow; + doprev = 0; + amii_addtopl(prompt); + continue; + } +#endif + digit_ok = allow_num && isdigit(q); + if (q == '\033') { + if (index(resp, 'q')) + q = 'q'; + else if (index(resp, 'n')) + q = 'n'; + else + q = def; + break; + } else if (index(quitchars, q)) { + q = def; + break; + } + if (!index(resp, q) && !digit_ok) { + amii_bell(); + q = (char)0; + } else if (q == '#' || digit_ok) { + char z, digit_string[2]; + int n_len = 0; + long value = 0; + amii_addtopl("#"), n_len++; + digit_string[1] = '\0'; + if (q != '#') { + digit_string[0] = q; + amii_addtopl(digit_string), n_len++; + value = q - '0'; + q = '#'; + } + do { /* loop until we get a non-digit */ + cursor_on(WIN_MESSAGE); + z = lowc(WindowGetchar()); + cursor_off(WIN_MESSAGE); + if (isdigit(z)) { + value = (10 * value) + (z - '0'); + if (value < 0) break; /* overflow: try again */ + digit_string[0] = z; + amii_addtopl(digit_string), n_len++; + } else if (z == 'y' || index(quitchars, z)) { + if (z == '\033') value = -1; /* abort */ + z = '\n'; /* break */ + } else if ( z == '\b') { + if (n_len <= 1) { value = -1; break; } + else { value /= 10; removetopl(1), n_len--; } + } else { + value = -1; /* abort */ + amii_bell(); + break; + } + } while (z != '\n'); + if (value > 0) yn_number = value; + else if (value == 0) q = 'n'; /* 0 => "no" */ + else { /* remove number from top line, then try again */ + removetopl(n_len), n_len = 0; + q = '\0'; + } + } + } while(!q); + + if (q != '#' && q != '\033') { + Sprintf(rtmp, "%c", q); + amii_addtopl(rtmp); + } + clean_up: + cursor_off(WIN_MESSAGE); + clear_nhwindow(WIN_MESSAGE); + return q; +} + +void +amii_display_file(fn, complain) +const char *fn; +boolean complain; +{ + register struct amii_WinDesc *cw; + register int win; + register dlb *fp; + register char *t; + register char buf[ 200 ]; + + if( fn == NULL ) + panic("NULL file name in display_file()"); + + if( ( fp = dlb_fopen( fn, RDTMODE ) ) == (dlb *)NULL ) + { + if (complain) { + sprintf( buf, "Can't display %s: %s", fn, +#if defined(_DCC) || defined(__GNUC__) + strerror(errno) +#else +# ifdef __SASC_60 + __sys_errlist[ errno ] +# else + sys_errlist[ errno ] +# endif +#endif + ); + amii_addtopl( buf ); + } + return; + } + win = amii_create_nhwindow( NHW_TEXT ); + + /* Set window title to file name */ + if( cw = amii_wins[ win ] ) + cw->morestr = (char *)fn; + + while( dlb_fgets( buf, sizeof( buf ), fp ) != NULL ) + { + if( t = index( buf, '\n' ) ) + *t = 0; + amii_putstr( win, 0, buf ); + } + dlb_fclose( fp ); + + /* If there were lines in the file, display those lines */ + + if( amii_wins[ win ]->cury > 0 ) + amii_display_nhwindow( win, TRUE ); + + amii_wins[win]->morestr = NULL; /* don't free title string */ + amii_destroy_nhwindow( win ); +} + +/* Put a 3-D motif border around the gadget. String gadgets or those + * which do not have highlighting are rendered down. Boolean gadgets + * are rendered in the up position by default. + */ + +void +SetBorder( gd ) + register struct Gadget *gd; +{ + register struct Border *bp; + register short *sp; + register int i, inc = -1, dec = -1; + int borders = 6; + int hipen = flags.amii_dripens[ SHINEPEN ], shadowpen = flags.amii_dripens[ SHADOWPEN ]; +#ifdef INTUI_NEW_LOOK + struct DrawInfo *dip; +#endif + +#ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + { + if( dip = GetScreenDrawInfo( HackScreen ) ) + { + hipen = dip->dri_Pens[ SHINEPEN ]; + shadowpen = dip->dri_Pens[ SHADOWPEN ]; + FreeScreenDrawInfo( HackScreen, dip ); + } + } +#endif + /* Allocate two border structures one for up image and one for down + * image, plus vector arrays for the border lines. + */ + + if( gd->GadgetType == STRGADGET ) + borders = 12; + + if( ( bp = (struct Border *)alloc( ( ( sizeof( struct Border ) * 2 ) + + ( sizeof( short ) * borders ) ) * 2 ) ) == NULL ) + { + return; + } + + /* For a string gadget, we expand the border beyond the area where + * the text will be entered. + */ + + /* Remove any special rendering flags to avoid confusing intuition + */ + + gd->Flags &= ~(GADGHIGHBITS|GADGIMAGE); + + sp = (short *)(bp + 4); + if( gd->GadgetType == STRGADGET || ( gd->GadgetType == BOOLGADGET && + ( gd->Flags & GADGHIGHBITS ) == GADGHNONE ) ) + { + sp[0] = -1; + sp[1] = gd->Height - 1; + sp[2] = -1; + sp[3] = -1; + sp[4] = gd->Width - 1; + sp[5] = -1; + + sp[6] = gd->Width + 1; + sp[7] = -2; + sp[8] = gd->Width + 1; + sp[9] = gd->Height + 1; + sp[10] = -2; + sp[11] = gd->Height + 1; + + sp[12] = -2; + sp[13] = gd->Height; + sp[14] = -2; + sp[15] = -2; + sp[16] = gd->Width; + sp[17] = -2; + sp[18] = gd->Width; + sp[19] = gd->Height; + sp[20] = -2; + sp[21] = gd->Height; + + for( i = 0; i < 3; ++i ) + { + bp[ i ].LeftEdge = bp[ i ].TopEdge = -1; + bp[ i ].FrontPen = ( i == 0 || i == 1 ) ? shadowpen : hipen; + + /* Have to use JAM2 so that the old colors disappear. */ + bp[ i ].BackPen = C_BLACK; + bp[ i ].DrawMode = JAM2; + bp[ i ].Count = ( i == 0 || i == 1 ) ? 3 : 5; + bp[ i ].XY = &sp[ i*6 ]; + bp[ i ].NextBorder = ( i == 2 ) ? NULL : &bp[ i + 1 ]; + } + + /* bp[0] and bp[1] two pieces for the up image */ + gd->GadgetRender = (APTR) bp; + + /* No image change for select */ + gd->SelectRender = (APTR) bp; + + gd->LeftEdge++; + gd->TopEdge++; + gd->Flags |= GADGHCOMP; + } + else + { + /* Create the border vector values for up and left side, and + * also the lower and right side. + */ + + sp[0] = dec; + sp[1] = gd->Height + inc; + sp[2] = dec; + sp[3] = dec; + sp[4] = gd->Width + inc; + sp[5] = dec; + + sp[6] = gd->Width + inc; + sp[7] = dec; + sp[8] = gd->Width + inc; + sp[9] = gd->Height + inc; + sp[10] = dec; + sp[11] = gd->Height + inc; + + /* We are creating 4 sets of borders, the two sides of the + * rectangle share the border vectors with the opposite image, + * but specify different colors. + */ + + for( i = 0; i < 4; ++i ) + { + bp[ i ].TopEdge = bp[ i ].LeftEdge = 0; + + /* A GADGHNONE is always down */ + + if( gd->GadgetType == BOOLGADGET && + ( gd->Flags & GADGHIGHBITS ) != GADGHNONE ) + { + bp[ i ].FrontPen = + ( i == 1 || i == 2 ) ? shadowpen : hipen; + } + else + { + bp[ i ].FrontPen = + ( i == 1 || i == 3 ) ? hipen : shadowpen; + } + + /* Have to use JAM2 so that the old colors disappear. */ + bp[ i ].BackPen = C_BLACK; + bp[ i ].DrawMode = JAM2; + bp[ i ].Count = 3; + bp[ i ].XY = &sp[ 6 * ((i &1) != 0) ]; + bp[ i ].NextBorder = + ( i == 1 || i == 3 ) ? NULL : &bp[ i + 1 ]; + } + + /* bp[0] and bp[1] two pieces for the up image */ + gd->GadgetRender = (APTR) bp; + + /* bp[2] and bp[3] two pieces for the down image */ + gd->SelectRender = (APTR) (bp + 2); + gd->Flags |= GADGHIMAGE; + } +} + +/* Following function copied from wintty.c */ +/* Modified slightly to fit amiga needs */ + +void +amii_player_selection() +{ + int i, k, n; + char pick4u = 'n', thisch, lastch = 0; + char pbuf[QBUFSZ], plbuf[QBUFSZ], rolenamebuf[QBUFSZ]; + winid win; + anything any; + menu_item *selected = 0; + + rigid_role_checks(); + + /* Should we randomly pick for the player? */ + if (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE || + flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE) { + char *prompt = build_plselection_prompt(pbuf, QBUFSZ, flags.initrole, + flags.initrace, flags.initgend, flags.initalign); + pline("%s", prompt); + do { /* loop until we get valid input */ + cursor_on(WIN_MESSAGE); + pick4u = lowc(WindowGetchar()); + cursor_off(WIN_MESSAGE); + if (index(quitchars, pick4u)) pick4u = 'y'; + } while(!index(ynqchars, pick4u)); + pbuf[0] = pick4u; + pbuf[1] = 0; + amii_addtopl(pbuf); + + if (pick4u != 'y' && pick4u != 'n') { +give_up: /* Quit */ + if (selected) free((genericptr_t) selected); + clearlocks(); + exit_nhwindows(NULL); + terminate(0); + /*NOTREACHED*/ + return; + } + } + + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); + + /* Select a role, if necessary */ + /* we'll try to be compatible with pre-selected race/gender/alignment, + * but may not succeed */ + if (flags.initrole < 0) { + /* Process the choice */ + if (pick4u == 'y' || flags.initrole == ROLE_RANDOM || flags.randomall) { + /* Pick a random role */ + flags.initrole = pick_role(flags.initrace, flags.initgend, + flags.initalign, PICK_RANDOM); + if (flags.initrole < 0) { + amii_putstr(WIN_MESSAGE, 0, "Incompatible role!"); + flags.initrole = randrole(); + } + } else { + /* Prompt for a role */ + win = create_nhwindow(NHW_MENU); + start_menu(win); + any.a_void = 0; /* zero out all bits */ + for (i = 0; roles[i].name.m; i++) { + if (ok_role(i, flags.initrace, flags.initgend, + flags.initalign)) { + any.a_int = i+1; /* must be non-zero */ + thisch = lowc(roles[i].name.m[0]); + if (thisch == lastch) thisch = highc(thisch); + if (flags.initgend != ROLE_NONE && flags.initgend != ROLE_RANDOM) { + if (flags.initgend == 1 && roles[i].name.f) + Strcpy(rolenamebuf, roles[i].name.f); + else + Strcpy(rolenamebuf, roles[i].name.m); + } else { + if (roles[i].name.f) { + Strcpy(rolenamebuf, roles[i].name.m); + Strcat(rolenamebuf, "/"); + Strcat(rolenamebuf, roles[i].name.f); + } else + Strcpy(rolenamebuf, roles[i].name.m); + } + add_menu(win, NO_GLYPH, &any, thisch, + 0, ATR_NONE, an(rolenamebuf), MENU_UNSELECTED); + lastch = thisch; + } + } + any.a_int = pick_role(flags.initrace, flags.initgend, + flags.initalign, PICK_RANDOM)+1; + if (any.a_int == 0) /* must be non-zero */ + any.a_int = randrole()+1; + add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, + "Random", MENU_UNSELECTED); + any.a_int = i+1; /* must be non-zero */ + add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE, + "Quit", MENU_UNSELECTED); + Sprintf(pbuf, "Pick a role for your %s", plbuf); + end_menu(win, pbuf); + n = select_menu(win, PICK_ONE, &selected); + destroy_nhwindow(win); + + /* Process the choice */ + if (n != 1 || selected[0].item.a_int == any.a_int) + goto give_up; /* Selected quit */ + + flags.initrole = selected[0].item.a_int - 1; + free((genericptr_t) selected), selected = 0; + } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); + } + + /* Select a race, if necessary */ + /* force compatibility with role, try for compatibility with + * pre-selected gender/alignment */ + if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) { + /* pre-selected race not valid */ + if (pick4u == 'y' || flags.initrace == ROLE_RANDOM || flags.randomall) { + flags.initrace = pick_race(flags.initrole, flags.initgend, + flags.initalign, PICK_RANDOM); + if (flags.initrace < 0) { + amii_putstr(WIN_MESSAGE, 0, "Incompatible race!"); + flags.initrace = randrace(flags.initrole); + } + } else { /* pick4u == 'n' */ + /* Count the number of valid races */ + n = 0; /* number valid */ + k = 0; /* valid race */ + for (i = 0; races[i].noun; i++) { + if (ok_race(flags.initrole, i, flags.initgend, + flags.initalign)) { + n++; + k = i; + } + } + if (n == 0) { + for (i = 0; races[i].noun; i++) { + if (validrace(flags.initrole, i)) { + n++; + k = i; + } + } + } + + /* Permit the user to pick, if there is more than one */ + if (n > 1) { + win = create_nhwindow(NHW_MENU); + start_menu(win); + any.a_void = 0; /* zero out all bits */ + for (i = 0; races[i].noun; i++) + if (ok_race(flags.initrole, i, flags.initgend, + flags.initalign)) { + any.a_int = i+1; /* must be non-zero */ + add_menu(win, NO_GLYPH, &any, races[i].noun[0], + 0, ATR_NONE, races[i].noun, MENU_UNSELECTED); + } + any.a_int = pick_race(flags.initrole, flags.initgend, + flags.initalign, PICK_RANDOM)+1; + if (any.a_int == 0) /* must be non-zero */ + any.a_int = randrace(flags.initrole)+1; + add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, + "Random", MENU_UNSELECTED); + any.a_int = i+1; /* must be non-zero */ + add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE, + "Quit", MENU_UNSELECTED); + Sprintf(pbuf, "Pick the race of your %s", plbuf); + end_menu(win, pbuf); + n = select_menu(win, PICK_ONE, &selected); + destroy_nhwindow(win); + if (n != 1 || selected[0].item.a_int == any.a_int) + goto give_up; /* Selected quit */ + + k = selected[0].item.a_int - 1; + free((genericptr_t) selected), selected = 0; + } + flags.initrace = k; + } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); + } + + /* Select a gender, if necessary */ + /* force compatibility with role/race, try for compatibility with + * pre-selected alignment */ + if (flags.initgend < 0 || !validgend(flags.initrole, flags.initrace, + flags.initgend)) { + /* pre-selected gender not valid */ + if (pick4u == 'y' || flags.initgend == ROLE_RANDOM || flags.randomall) { + flags.initgend = pick_gend(flags.initrole, flags.initrace, + flags.initalign, PICK_RANDOM); + if (flags.initgend < 0) { + amii_putstr(WIN_MESSAGE, 0, "Incompatible gender!"); + flags.initgend = randgend(flags.initrole, flags.initrace); + } + } else { /* pick4u == 'n' */ + /* Count the number of valid genders */ + n = 0; /* number valid */ + k = 0; /* valid gender */ + for (i = 0; i < ROLE_GENDERS; i++) { + if (ok_gend(flags.initrole, flags.initrace, i, + flags.initalign)) { + n++; + k = i; + } + } + if (n == 0) { + for (i = 0; i < ROLE_GENDERS; i++) { + if (validgend(flags.initrole, flags.initrace, i)) { + n++; + k = i; + } + } + } + + /* Permit the user to pick, if there is more than one */ + if (n > 1) { + win = create_nhwindow(NHW_MENU); + start_menu(win); + any.a_void = 0; /* zero out all bits */ + for (i = 0; i < ROLE_GENDERS; i++) + if (ok_gend(flags.initrole, flags.initrace, i, + flags.initalign)) { + any.a_int = i+1; + add_menu(win, NO_GLYPH, &any, genders[i].adj[0], + 0, ATR_NONE, genders[i].adj, MENU_UNSELECTED); + } + any.a_int = pick_gend(flags.initrole, flags.initrace, + flags.initalign, PICK_RANDOM)+1; + if (any.a_int == 0) /* must be non-zero */ + any.a_int = randgend(flags.initrole, flags.initrace)+1; + add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, + "Random", MENU_UNSELECTED); + any.a_int = i+1; /* must be non-zero */ + add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE, + "Quit", MENU_UNSELECTED); + Sprintf(pbuf, "Pick the gender of your %s", plbuf); + end_menu(win, pbuf); + n = select_menu(win, PICK_ONE, &selected); + destroy_nhwindow(win); + if (n != 1 || selected[0].item.a_int == any.a_int) + goto give_up; /* Selected quit */ + + k = selected[0].item.a_int - 1; + free((genericptr_t) selected), selected = 0; + } + flags.initgend = k; + } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); + } + + /* Select an alignment, if necessary */ + /* force compatibility with role/race/gender */ + if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace, + flags.initalign)) { + /* pre-selected alignment not valid */ + if (pick4u == 'y' || flags.initalign == ROLE_RANDOM || flags.randomall) { + flags.initalign = pick_align(flags.initrole, flags.initrace, + flags.initgend, PICK_RANDOM); + if (flags.initalign < 0) { + amii_putstr(WIN_MESSAGE, 0, "Incompatible alignment!"); + flags.initalign = randalign(flags.initrole, flags.initrace); + } + } else { /* pick4u == 'n' */ + /* Count the number of valid alignments */ + n = 0; /* number valid */ + k = 0; /* valid alignment */ + for (i = 0; i < ROLE_ALIGNS; i++) { + if (ok_align(flags.initrole, flags.initrace, flags.initgend, + i)) { + n++; + k = i; + } + } + if (n == 0) { + for (i = 0; i < ROLE_ALIGNS; i++) { + if (validalign(flags.initrole, flags.initrace, i)) { + n++; + k = i; + } + } + } + + /* Permit the user to pick, if there is more than one */ + if (n > 1) { + win = create_nhwindow(NHW_MENU); + start_menu(win); + any.a_void = 0; /* zero out all bits */ + for (i = 0; i < ROLE_ALIGNS; i++) + if (ok_align(flags.initrole, flags.initrace, + flags.initgend, i)) { + any.a_int = i+1; + add_menu(win, NO_GLYPH, &any, aligns[i].adj[0], + 0, ATR_NONE, aligns[i].adj, MENU_UNSELECTED); + } + any.a_int = pick_align(flags.initrole, flags.initrace, + flags.initgend, PICK_RANDOM)+1; + if (any.a_int == 0) /* must be non-zero */ + any.a_int = randalign(flags.initrole, flags.initrace)+1; + add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, + "Random", MENU_UNSELECTED); + any.a_int = i+1; /* must be non-zero */ + add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE, + "Quit", MENU_UNSELECTED); + Sprintf(pbuf, "Pick the alignment of your %s", plbuf); + end_menu(win, pbuf); + n = select_menu(win, PICK_ONE, &selected); + destroy_nhwindow(win); + if (n != 1 || selected[0].item.a_int == any.a_int) + goto give_up; /* Selected quit */ + + k = selected[0].item.a_int - 1; + free((genericptr_t) selected), selected = 0; + } + flags.initalign = k; + } + } + /* Success! */ +} +#endif /* AMIGA_INTUITION */ diff --git a/sys/amiga/winami.p b/sys/amiga/winami.p new file mode 100644 index 0000000..b34f8e5 --- /dev/null +++ b/sys/amiga/winami.p @@ -0,0 +1,57 @@ +/* SCCS Id: @(#)winami.p 3.1 93/01/08 */ +/* Copyright (c) Gregg Wonderly, Naperville, IL, 1992, 1993 */ +/* NetHack may be freely redistributed. See license for details. */ +/* winami.c */ +void FDECL(amii_raw_print, (const char *)); +void FDECL(amii_raw_print_bold, (const char *)); +void FDECL(amii_start_menu, (winid )); +void FDECL(amii_add_menu, (winid , char , int , const char *)); +void FDECL(amii_end_menu, (winid , char , const char * , const char *)); +char FDECL(amii_select_menu, (winid )); +void NDECL(amii_update_inventory ); +void NDECL(amii_mark_synch ); +void NDECL(amii_wait_synch ); +void NDECL(amii_setclipped ); +void FDECL(amii_cliparound, (int , int )); +void NDECL(amii_askname ); +void NDECL(amii_player_selection ); +void NDECL(flush_output ); +void FDECL(amii_destroy_nhwindow, (winid )); +int FDECL(amii_create_nhwindow, (int )); +void NDECL(amii_init_nhwindows ); +int NDECL(amii_get_ext_cmd); +char FDECL(amii_yn_function, (const char * , const char * , char )); +void FDECL(amii_addtopl, (const char *)); +void FDECL(TextSpaces, (struct RastPort * , int )); +void FDECL(amii_putstr, (winid , int , const char *)); +void FDECL(amii_putsym, (winid , int , int , CHAR_P )); +void FDECL(amii_clear_nhwindow, (winid )); +void FDECL(amii_exit_nhwindows, (const char *)); +int FDECL(amii_nh_poskey, (int * , int * , int *)); +int NDECL(amii_nhgetch ); +void NDECL(amii_get_nh_event ); +void NDECL(amii_remember_topl ); +int NDECL(amii_doprev_message ); +void FDECL(amii_display_nhwindow, (winid , boolean )); +void FDECL(amii_display_file, (const char * , boolean )); +void FDECL(amii_curs, (winid , int , int )); +void FDECL(amii_print_glyph, (winid , xchar , xchar , int )); +void FDECL(DoMenuScroll, (int , int )); +void FDECL(DisplayData, (int , int , int )); +void FDECL(SetPropInfo, (struct Window * , struct Gadget * , long , long , long )); +void FDECL(kill_nhwindows, (int )); +void FDECL(amii_cl_end, (struct amii_WinDesc * , int )); +void FDECL(cursor_off, (winid )); +void FDECL(cursor_on, (winid )); +void NDECL(amii_getret ); +void FDECL(amii_getlin, (const char * , char *)); +void FDECL(getlind, (const char * , char * , const char *)); +void FDECL(amii_suspend_nhwindows, (char * )); +void NDECL(amii_resume_nhwindows); +void NDECL(amii_bell); +void NDECL(EditColor); +void FDECL(DrawCol, ( struct Window *, int, UWORD * ) ); +void FDECL( DispCol, ( struct Window *w, int idx, UWORD * ) ); +void FDECL( SetBorder, (struct Gadget *) ); +void NDECL( port_help ); +void FDECL( dismiss_nhwindow, (winid) ); diff --git a/sys/amiga/winchar.c b/sys/amiga/winchar.c new file mode 100644 index 0000000..2f6e721 --- /dev/null +++ b/sys/amiga/winchar.c @@ -0,0 +1,1246 @@ +/* SCCS Id: @(#)winchar.c 3.1 93/07/22 */ +/* Copyright (c) Olaf Seibert (KosmoSoft), 1989, 1992 */ +/* Copyright (c) Kenneth Lorber, Bethesda, Maryland 1993 */ +/* Copyright (c) Gregg Wonderly, Naperville Illinois, 1994. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include +#include +#include +#ifndef _DCC +#include +#endif + +#ifdef TESTING +# include "hack.h" +#else +# include "NH:src/tile.c" +#endif + +#include "NH:win/share/tile.h" + +#include "NH:sys/amiga/windefs.h" +#include "NH:sys/amiga/winext.h" +#include "NH:sys/amiga/winproto.h" + +#ifdef OPT_DISPMAP +# define DISPMAP /* use display_map() from dispmap.s */ +#endif + +/* NH:sys/amiga/winvchar.c */ +int main ( int , char ** ); +struct BitMap *MyAllocBitMap ( int , int , int , long ); +void MyFreeBitMap ( struct BitMap * ); +void FreeImageFiles ( char **, struct BitMap ** ); +void amiv_flush_glyph_buffer ( struct Window * ); +void amiv_lprint_glyph ( winid , int , int ); +void amii_lprint_glyph ( winid , int , int ); +void amiv_start_glyphout ( winid ); +void amii_end_glyphout ( winid ); +void SetMazeType ( MazeType ); +int GlyphToIcon ( int ); +void amii_start_glyphout ( winid ); +void amii_end_glyphout ( winid ); +void amii_flush_glyph_buffer( struct Window * ); + +int amii_extraplanes = 0; +extern int reclip; + +struct BitMap *MyAllocBitMap( int xsize, int ysize, int depth, long mflags ); +void MyFreeBitMap( struct BitMap *bmp ); + +#ifdef DISPMAP +extern void display_map( struct Window * ); +#endif + +/* + * These values will be available from tile.c source + * + * #define MAXMONTILE 335 + * #define MAXOBJTILE 722 + * #define MAXOTHTILE 841 + */ + +#define IMGROWS 12 +#define IMGCOLUMNS 20 +#define IMGPAGESIZE (IMGROWS*IMGCOLUMNS) + +#define ID_BMAP MAKE_ID('B','M','A','P') /* The type of form we use */ +#define ID_BMHD MAKE_ID('B','M','H','D') /* The ILBM bitmap header */ +#define ID_CAMG MAKE_ID('C','A','M','G') /* The ILBM camg (ignored) */ +#define ID_CMAP MAKE_ID('C','M','A','P') /* Standard ILBM color map */ +#define ID_PLNE MAKE_ID('P','L','N','E') /* The plane data */ +#define ID_PDAT MAKE_ID('P','D','A','T') /* The PDAT structure below */ + +struct PDAT pictdata; + +#define NUMTILEIMAGES 3 +char *tileimages[] = +{ +#define TBLMONTILE 0 + "NetHack:tiles/monsters.iff", +#define TBLOBJTILE 1 + "NetHack:tiles/objects.iff", +#define TBLOTHTILE 2 + "NetHack:tiles/other.iff", + 0, +}; + +struct BitMap *ifftimg[ NUMTILEIMAGES ], *tile; + +#ifdef TESTING +short pens[NUMDRIPENS] = { 8, 3, 15, 0, 15, 7, 7, 8, 0 }; +main( int argc, char **argv ) +{ + BitMapHeader bmhd; + struct IntuiMessage *imsg; + long code, class; + char buf[100]; + int i, x, y, tbl, done = 0, num; + struct Window *w; + struct Screen *scr; + + bmhd = ReadTileImageFiles( ); + + scr = OpenScreenTags( NULL, + SA_Depth, pictdata.nplanes + amii_extraplanes, + SA_DisplayID, DBLNTSC_MONITOR_ID|HIRESLACE_KEY, + SA_Overscan, OSCAN_TEXT, + SA_Top, 0, + SA_Left, 0, + SA_Width, STDSCREENWIDTH, + SA_Height, STDSCREENHEIGHT, + SA_Type, CUSTOMSCREEN, + SA_DetailPen, 0, + SA_BlockPen, 1, + SA_Title, "NetHack Chars", + SA_Pens, pens, + TAG_DONE + ); + if( scr == NULL ) + { + printf( "no screen\n" ); +#undef exit + exit( 1 ); + } + + w = OpenWindowTags( 0, + WA_CustomScreen, scr, + WA_Flags, WFLG_DRAGBAR|WFLG_SIZEGADGET|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET, + WA_IDCMP, IDCMP_CLOSEWINDOW|IDCMP_NEWSIZE|IDCMP_MOUSEBUTTONS, + WA_Left, 0, + WA_Top, scr->WBorTop + 1 + 13, + WA_MinWidth, 100, + WA_MinHeight, 100, + WA_MaxWidth, 700, + WA_MaxHeight, 1000, + WA_Width, 640, + WA_Height, 340, + WA_SmartRefresh, TRUE, + TAG_DONE ); + if( w ) + { + while( !done ) + { + for( i = 0; i < NUMTILEIMAGES * IMGPAGESIZE; ++i ) + { + int dx, dy; + tbl = i/IMGPAGESIZE; + x = i % IMGPAGESIZE; + y = x / IMGCOLUMNS; + x = x % IMGCOLUMNS; + dx = i % (IMGCOLUMNS*2); + dy = i / (IMGCOLUMNS*2); + BltBitMapRastPort( ifftimg[ tbl ], + x * pictdata.xsize, y * pictdata.ysize, + w->RPort, + w->BorderLeft + 1 + dx*pictdata.xsize, + w->BorderTop + 1 + dy*pictdata.ysize, + pictdata.xsize, pictdata.ysize, 0xc0 ); + } + WaitPort( w->UserPort ); + while( imsg = (struct IntuiMessage *)GetMsg( w->UserPort ) ) + { + class = imsg->Class; + code = imsg->Code; + ReplyMsg( (struct Message *)imsg ); + switch( class ) + { + case IDCMP_MOUSEBUTTONS: + { + x = imsg->MouseX - w->BorderLeft; + y = imsg->MouseY - w->BorderTop; + num = ((y/pictdata.ysize)*IMGCOLUMNS*2)+(x/pictdata.xsize); + sprintf( buf, "Char #%d", num ); + SetWindowTitles( w, buf, buf ); + } + break; + case IDCMP_CLOSEWINDOW: + done = 1; + break; + } + } + } + CloseWindow( w ); + CloseScreen( scr ); + } + + FreeImageFiles(tileimages, ifftimg ); + + return(0); +} +#endif + +BitMapHeader +ReadTileImageFiles(){ + char *errstr = NULL; + BitMapHeader ret = ReadImageFiles(tileimages, ifftimg, &errstr); + if(errstr){ + panic(errstr); + } + return ret; +} + +BitMapHeader +ReadImageFiles(char **filenames, struct BitMap **iffimg, char **errstrp ) +{ + BitMapHeader *bmhd = NULL, bmhds; + unsigned char *cmap; + extern int errno; + register int i, j; + struct IFFHandle *iff; + struct StoredProperty *prop; + + IFFParseBase = OpenLibrary( "iffparse.library", 0L ); + if( !IFFParseBase ) + { + *errstrp = "No iffparse.library"; + return bmhds; + } + +/* + for( i = 0; filenames[i]; ++i ) + memset( iffimg[i], 0, sizeof( struct BitMap ) ); +*/ + for( i = 0; filenames[i]; ++i ) + { + iff = AllocIFF(); + if( !iff ) + { + FreeImageFiles(filenames, iffimg ); + *errstrp = "can't start IFF processing"; + return bmhds; + } + iff->iff_Stream = Open( filenames[i], MODE_OLDFILE ); + if( iff->iff_Stream == 0 ) + { + char *buf = malloc(100+strlen(filenames[i])); + FreeImageFiles( filenames, iffimg ); + sprintf(buf, "Can't open %s: %s", filenames[i], strerror( errno )); + *errstrp = buf; + return bmhds; + } + InitIFFasDOS( iff ); + OpenIFF( iff, IFFF_READ ); + PropChunk( iff, ID_BMAP, ID_BMHD ); + PropChunk( iff, ID_BMAP, ID_CMAP ); + PropChunk( iff, ID_BMAP, ID_CAMG ); + PropChunk( iff, ID_BMAP, ID_PDAT ); + StopChunk( iff, ID_BMAP, ID_PLNE ); + if( ( j = ParseIFF( iff, IFFPARSE_SCAN ) ) != 0 ) + { + char *buf = malloc(100); + FreeImageFiles( filenames, iffimg ); + sprintf(buf,"ParseIFF failed for image %d, failure code: %d",i,j); + *errstrp = buf; + return bmhds; + } + + if( prop = FindProp( iff, ID_BMAP, ID_BMHD ) ) + { + bmhd = (BitMapHeader *)prop->sp_Data; + } + else + { + FreeImageFiles(filenames, iffimg); + CloseIFF( iff ); + Close( iff->iff_Stream ); + FreeIFF( iff ); + *errstrp = "No BMHD CHUNK in file"; + return bmhds; + } + + if( prop = FindProp( iff, ID_BMAP, ID_CMAP ) ) + { + cmap = prop->sp_Data; + for( j = 0; j < (1L << bmhd->nPlanes)*3; j+=3 ) + { +#if 0 + /* Some day we will want to use the larger palette + * resolution available under v39 and later. i.e. + * 32 instead of 12 bits of color. Ususally this + * just means shifting the color left by 16-20 bits + * depending on what intensity looks best. Experience + * says that the higher values are better intensities. + * + * For now though we won't do this. The color table + * structure is incompatible with earlier versions of + * intuition. We would have to do some funny things + * to make 3*AMII_MAXCOLORS longs work like 3*AMII_MAXCOLORS + * UWORD's at run time... A union would help, but... + */ + if( IntuitionBase->LibNode.lib_Version >= 39 ) + { + /* 8 bits of color, so shift to left end. */ + amiv_init_map[ j+0 ] = cmap[j+0]<<24; + amiv_init_map[ j+1 ] = cmap[j+1]<<24; + amiv_init_map[ j+2 ] = cmap[j+2]<<24; + } + else +#endif + { + /* We can only use 4 bits of the 8 that are stored in the + * cmap, so mask them and then shift them into position + * for the UWORD value to store. + */ +#ifndef TESTING + amii_initmap[ j/3 ] = + amiv_init_map[ j/3 ] = + ((cmap[j+0]>>4)<<8)| + ((cmap[j+1]>>4)<<4)| + (cmap[j+2]>>4); +#endif + } + } + } + else + { + FreeImageFiles(filenames, iffimg); + CloseIFF( iff ); + Close( iff->iff_Stream ); + FreeIFF( iff ); + *errstrp = "No CMAP CHUNK in file"; + return bmhds; + } + + if( prop = FindProp( iff, ID_BMAP, ID_PDAT ) ) + { + struct PDAT *pp; + + pp = (struct PDAT *)prop->sp_Data; + pictdata = *pp; + } + else + { + FreeImageFiles(filenames, iffimg); + CloseIFF( iff ); + Close( iff->iff_Stream ); + FreeIFF( iff ); + *errstrp = "No PDAT CHUNK in file"; + return bmhds; + } + + iffimg[ i ] = MyAllocBitMap( bmhd->w, bmhd->h, + pictdata.nplanes + amii_extraplanes, MEMF_CHIP|MEMF_CLEAR ); + if( iffimg[ i ] == NULL ) + { + char *buf = malloc(80); + FreeImageFiles(filenames, iffimg); + sprintf(buf, "Can't allocate bitmap for image %d\n", i ); + *errstrp = buf; + return bmhds; + } + for( j = 0; j < pictdata.nplanes + amii_extraplanes; ++j ) + { + ReadChunkBytes( iff, iffimg[i]->Planes[j], RASSIZE( bmhd->w, bmhd->h ) ); + } + bmhds = *bmhd; + CloseIFF( iff ); + Close( iff->iff_Stream ); + FreeIFF( iff ); + } + CloseLibrary( IFFParseBase ); + + tile = MyAllocBitMap( pictdata.xsize, pictdata.ysize, + pictdata.nplanes + amii_extraplanes, MEMF_CHIP|MEMF_CLEAR ); + if( tile == NULL ) + { + FreeImageFiles(filenames, iffimg); + *errstrp = "Can't allocate tile bitmap for scaling"; + } + return( bmhds ); +} + +struct MyBitMap +{ + struct BitMap bm; + long mflags; + USHORT xsize, ysize; +}; + +struct BitMap * +MyAllocBitMap( int xsize, int ysize, int depth, long mflags ) +{ + int j; + struct MyBitMap *bm; + + bm = (struct MyBitMap *)alloc( sizeof( *bm ) ); + if( !bm ) + return( NULL ); + + bm->xsize = xsize; + bm->ysize = ysize; + InitBitMap( &bm->bm, depth, xsize, ysize ); + for( j = 0; j < depth; ++j ) + { + if( mflags & MEMF_CHIP ) + bm->bm.Planes[ j ] = AllocRaster( xsize, ysize ); + else + bm->bm.Planes[ j ] = AllocMem( RASSIZE( xsize, ysize ), mflags ); + + if( bm->bm.Planes[ j ] == 0 ) + { + MyFreeBitMap( &bm->bm ); + return( NULL ); + } + if( mflags & MEMF_CLEAR ) + memset( bm->bm.Planes[ j ], 0, RASSIZE( xsize, ysize ) ); + } + return( &bm->bm ); +} + +void +MyFreeBitMap( struct BitMap *bmp ) +{ + int j; + struct MyBitMap *bm = (struct MyBitMap *)bmp; + + for( j = 0; j < bm->bm.Depth; ++j ) + { + if( bm->bm.Planes[j] ) + { + if( bm->mflags & MEMF_CHIP ) + FreeRaster( bm->bm.Planes[j], bm->xsize, bm->ysize ); + else + FreeMem( bm->bm.Planes[j], RASSIZE( bm->xsize, bm->ysize ) ); + } + } + free( bm ); +} + +#ifdef TESTING +void +panic(s,a1,a2,a3,a4) + char *s; +{ + printf( s, a1, a2, a3, a4 ); + putchar('\n'); +} +long * +alloc(unsigned int x){ + long *p = (long *)malloc(x); + if(!p){panic("malloc failed"); exit(1);} + return p; +} +#endif + +void +FreeTileImageFiles(){ + FreeImageFiles(tileimages,ifftimg); +} + +void +FreeImageFiles(char **filenames, struct BitMap **img ) +{ + register int i; + + for( i = 0; filenames[i]; ++i ) + { + if( img[ i ] ) + MyFreeBitMap( img[ i ] ); + } + + /* REALLY ugly hack alert! */ + if( tile && img==ifftimg) + MyFreeBitMap( tile ); +} + +#ifndef TESTING +/* + * Define some stuff for our special glyph drawing routines + */ +unsigned short glyph_node_index, glyph_buffer_index; +#define NUMBER_GLYPH_NODES 80 +#define GLYPH_BUFFER_SIZE 512 +struct amiv_glyph_node { + short odstx, odsty; + short srcx, srcy, dstx, dsty; + struct BitMap *bitmap; +}; +struct amiv_glyph_node amiv_g_nodes[NUMBER_GLYPH_NODES]; +static char amiv_glyph_buffer[GLYPH_BUFFER_SIZE]; + +void +flush_glyph_buffer( vw ) + struct Window *vw; +{ + if( WINVERS_AMIV ) + amiv_flush_glyph_buffer ( vw ); + else + amii_flush_glyph_buffer ( vw ); +} + +/* + * Routine to flush whatever is buffered + */ +void +amiv_flush_glyph_buffer( vw ) + struct Window *vw; +{ +#if !defined(DISPMAP) || defined(OPT_DISPMAP) + int xsize, ysize, x, y; + struct BitScaleArgs bsa; + struct BitScaleArgs bsm; + struct RastPort rast; + struct Window *w = NULL; + struct BitMap *imgbm = 0, *bm = 0; + int i, k; + int scaling_needed; + register struct RastPort *rp = vw->RPort; +#endif + + /* If nothing is buffered, return before we do anything */ + if(glyph_node_index == 0) + return; + + cursor_off( WIN_MAP ); + amiv_start_glyphout( WIN_MAP ); + +#ifdef OPT_DISPMAP + if(flags.fast_map){ +#endif +#ifdef DISPMAP + display_map( vw ); +#endif +#ifdef OPT_DISPMAP + } else { +#endif +#if !defined(DISPMAP) || defined(OPT_DISPMAP) +/* XXX fix indent */ + /* This is a dynamic value based on this relationship. */ + scaling_needed = ( pictdata.xsize != mxsize || pictdata.ysize != mysize ); + + /* If overview window is up, set up to render the correct scale there */ + if( WIN_OVER != WIN_ERR && ( w = amii_wins[ WIN_OVER ]->win ) != NULL ) + { + InitRastPort( &rast ); + + /* Calculate the x and y size of each tile for a ROWNO by COLNO map */ + xsize = (w->Width - w->BorderLeft - w->BorderRight) / COLNO; + ysize = (w->Height - w->BorderTop - w->BorderBottom) / ROWNO; + + /* Get a chip memory bitmap to blit out of */ + bm = MyAllocBitMap( pictdata.xsize, pictdata.ysize, + pictdata.nplanes + amii_extraplanes, MEMF_CLEAR|MEMF_CHIP ); + if( bm == NULL ) + { + amii_putstr( WIN_MESSAGE, 0, "Can't allocate bitmap for scaling overview window" ); + } + + rast.BitMap = bm; + + memset( &bsa, 0, sizeof( bsa ) ); + bsa.bsa_SrcX = bsa.bsa_SrcY = 0; + bsa.bsa_SrcBitMap = tile; + bsa.bsa_SrcWidth = pictdata.xsize; + bsa.bsa_SrcHeight = pictdata.ysize; + bsa.bsa_XSrcFactor = pictdata.xsize; + bsa.bsa_YSrcFactor = pictdata.ysize; + bsa.bsa_DestX = 0; + bsa.bsa_DestY = 0; + bsa.bsa_DestWidth = xsize; + bsa.bsa_DestHeight = ysize; + bsa.bsa_XDestFactor = xsize; + bsa.bsa_YDestFactor = ysize; + bsa.bsa_DestBitMap = bm; + } + + if( scaling_needed ) + { + /* Fill in scaling data for map rendering */ + memset( &bsm, 0, sizeof( bsm ) ); + bsm.bsa_SrcX = bsm.bsa_SrcY = 0; + bsm.bsa_SrcBitMap = tile; + + bsm.bsa_SrcWidth = pictdata.xsize; + bsm.bsa_SrcHeight = pictdata.ysize; + + bsm.bsa_XSrcFactor = pictdata.xsize; + bsm.bsa_YSrcFactor = pictdata.ysize; + + bsm.bsa_DestWidth = mxsize; + bsm.bsa_DestHeight = mysize; + + bsm.bsa_XDestFactor = mxsize; + bsm.bsa_YDestFactor = mysize; + bsm.bsa_DestBitMap = rp->BitMap; + bsm.bsa_DestY = bsm.bsa_DestX = 0; + + imgbm = MyAllocBitMap( mxsize, mysize, + pictdata.nplanes + amii_extraplanes, MEMF_CLEAR|MEMF_CHIP ); + if( imgbm == NULL ) + { + amii_putstr( WIN_MESSAGE, 0, + "Can't allocate scaling bitmap for map window" ); + } + else + bsm.bsa_DestBitMap = imgbm; + } + + /* Go ahead and start dumping the stuff */ + for( i=0; iBytesPerRow; + for( j = 0; j < pictdata.nplanes + amii_extraplanes; ++j ) + { + for( k = 0; k < pictdata.ysize; ++k ) + { + + /* For a 16x16 tile, this could just be short assignments, but + * this code is generalized to handle any size tile image... + */ + memcpy( tile->Planes[ j ] + ( ( k * pictdata.ysize ) / 8 ), + nodebm->Planes[ j ] + offx + offy + ( nodebm->BytesPerRow * k ), + pictdata.ysize/8 ); + } + } + + if( !clipping || + ( x >= clipx && y >= clipy && + x < clipxmax && y < clipymax ) ) + { + /* scaling is needed, do it */ + if( scaling_needed ) + { + BitMapScale( &bsm ); + BltBitMapRastPort( imgbm, 0, 0, + rp, amiv_g_nodes[ i ].dstx, amiv_g_nodes[ i ].dsty, + mxsize, mysize, 0xc0 ); + } + else + { + BltBitMapRastPort( tile, 0, 0, + rp, amiv_g_nodes[ i ].dstx, amiv_g_nodes[ i ].dsty, + pictdata.xsize, pictdata.ysize, 0xc0 ); + } + } + /* Draw the overview window unless we are scrolling the map raster around */ + if( bm && w && reclip != 2 ) + { + BitMapScale( &bsa ); + BltBitMapRastPort( rast.BitMap, 0, 0, + w->RPort, + w->BorderLeft + amiv_g_nodes[ i ].odstx*xsize, + w->BorderTop + amiv_g_nodes[ i ].odsty*ysize, + xsize, ysize, 0xc0 ); + } + } + + if( imgbm ) MyFreeBitMap( imgbm ); + if( bm ) MyFreeBitMap( bm ); +#endif /* DISPMAP */ +#ifdef OPT_DISPMAP + } +#endif + + amii_end_glyphout( WIN_MAP ); + + /* Clean up */ + glyph_node_index = glyph_buffer_index = 0; +} + +/* + * Glyph buffering routine. Called instead of WindowPuts(). + */ +void +amiv_lprint_glyph(window,color_index, glyph) + winid window; + int color_index, glyph; +{ + int base; + struct amii_WinDesc *cw; + struct Window *w; + int curx; + int cury; + int tbl, icon; + register int xoff, yoff; + + /* Get the real icon index */ + if( glyph != NO_GLYPH ) + icon = GlyphToIcon( glyph ); + + if( ( cw=amii_wins[window] ) == (struct amii_WinDesc *)NULL ) + panic("bad winid in amiv_lprint_glyph: %d", window ); + + w = cw->win; + + if( glyph != NO_GLYPH && glyph < 10000) + { + /* decide on which image has the needed picture */ + if( icon <= MAXMONTILE ) + { + tbl = TBLMONTILE; + base = 0; + } + else if( icon <= MAXOBJTILE ) + { + tbl = TBLOBJTILE; + base = MAXMONTILE+1; + } + else if( icon <= MAXOTHTILE ) + { + tbl = TBLOTHTILE; + base = MAXOBJTILE+1; + } + else + panic( "Bad icon #%d, glyph #%d, only %d icons known\n", icon, glyph, MAXOTHTILE ); + + /* Get the relative offset in the page */ + + /* How many pixels to account for y distance down */ + yoff = ((icon-base) / pictdata.across) * pictdata.ysize; + + /* How many pixels to account for x distance across */ + xoff = ((icon-base) % pictdata.across) * pictdata.xsize; + } + + if(glyph >= 10000){ + /* Run a single ASCII character out to the rastport right now */ + char c= glyph-10000; + int xxx,xxy; + struct RastPort *rp = w->RPort; + + Move(rp, xxx=(((cw->curx-clipx)*rp->TxWidth) + w->BorderLeft), + xxy=(w->BorderTop + (((cw->cury-clipy)+1)* rp->TxHeight)+1)); + Text(rp,&c,1); + /* XXX this shouldn't be necessary: */ + if(cw->cursx == xxx && cw->cursy == xxy){ + cw->wflags &= ~FLMAP_CURSUP; + } + cw->curx += rp->TxWidth; /* keep things in sync */ + return; + } + + if( cw->type == NHW_MAP ) + { + curx = cw->curx - clipx; + cury = cw->cury - clipy; + + /* See if we're out of glyph nodes */ + if(glyph_node_index >= NUMBER_GLYPH_NODES) + amiv_flush_glyph_buffer( w ); + + /* Fill in the node. */ + amiv_g_nodes[glyph_node_index].dsty = min( w->BorderTop + (cury * mysize), + w->Height - 1 ); + +#ifdef OPT_DISPMAP + if(flags.fast_map){ +#endif /* keni */ +#ifdef DISPMAP + /* display_map() needs byte-aligned destinations, and we don't want to + * overwrite the window border. + */ + amiv_g_nodes[glyph_node_index].dstx = + (w->BorderLeft + 8 + (curx * mxsize)) & -8; +#endif +#ifdef OPT_DISPMAP +} else { +#endif +#if !defined(DISPMAP) || defined(OPT_DISPMAP) + amiv_g_nodes[glyph_node_index].dstx = min( w->BorderLeft + (curx * mxsize), + w->Width - 1 ); +#endif +#ifdef OPT_DISPMAP +} +#endif + amiv_g_nodes[glyph_node_index].odsty = cw->cury; + amiv_g_nodes[glyph_node_index].odstx = cw->curx; + amiv_g_nodes[glyph_node_index].srcx = xoff; + amiv_g_nodes[glyph_node_index].srcy = yoff; + amiv_g_nodes[glyph_node_index].bitmap = ifftimg[ tbl ]; + ++glyph_node_index; + } + else + { + /* Do it */ + register int j, k, x, y, apen; + struct RastPort *rp = w->RPort; + x = rp->cp_x - pictdata.xsize - 3; +#ifdef OPT_DISPMAP + if(flags.fast_map){ +#endif +#ifdef DISPMAP + x &= -8; + if(x==0) x = 8; +#endif +#ifdef OPT_DISPMAP + } +#endif + + y = rp->cp_y - pictdata.ysize + 1; + + if( glyph != NO_GLYPH ) + { + struct BitMap *bm = ifftimg[ tbl ]; + + /* 8 bits per byte */ + xoff /= 8; + yoff *= bm->BytesPerRow; + for( j = 0; j < pictdata.nplanes; ++j ) + { + for( k = 0; k < pictdata.ysize; ++k ) + { + memcpy( tile->Planes[ j ] + ( ( k * pictdata.ysize ) / 8 ), + bm->Planes[ j ] + xoff + yoff + ( bm->BytesPerRow * k ), + pictdata.ysize/8 ); + } + } + + BltBitMapRastPort( tile, 0, 0, + rp, x, y, + pictdata.xsize, pictdata.ysize, 0xc0 ); + + apen = rp->FgPen; + SetAPen( rp, flags.amii_dripens[ SHINEPEN ] ); + Move( rp, x-1, y + pictdata.ysize ); + Draw( rp, x-1, y - 1 ); + Draw( rp, x + pictdata.xsize, y - 1 ); + SetAPen( rp, flags.amii_dripens[ SHADOWPEN ] ); + Move( rp, x + pictdata.xsize, y ); + Draw( rp, x + pictdata.xsize, y + pictdata.ysize ); + Draw( rp, x, y + pictdata.ysize ); + SetAPen( rp, apen ); + } + else if( x > w->BorderLeft ) + { + int apen, bpen; + apen = rp->FgPen; + bpen = rp->BgPen; + SetAPen( rp, amii_menuBPen ); + SetBPen( rp, amii_menuBPen ); + RectFill( rp, x-1, y-1, x + pictdata.xsize, y + pictdata.ysize ); + SetAPen( rp, apen ); + SetBPen( rp, bpen ); + } + } +} + +/* + * Define some variables which will be used to save context when toggling + * back and forth between low level text and console I/O. + */ +static long xsave, ysave, modesave, apensave, bpensave; +static int usecolor; + +/* + * The function is called before any glyphs are driven to the screen. It + * removes the cursor, saves internal state of the window, then returns. + */ + +void +amiv_start_glyphout(window) + winid window; +{ + struct amii_WinDesc *cw; + struct Window *w; + + if( ( cw=amii_wins[window] ) == (struct amii_WinDesc *)NULL ) + panic( "bad winid %d in start_glyphout()", window ); + + if( cw->wflags & FLMAP_INGLYPH ) + return; + + if( !(w = cw->win ) ) + panic( "bad winid %d, no window ptr set", window ); + + /* + * Save the context of the window + */ + xsave = w->RPort->cp_x; + ysave = w->RPort->cp_y; + modesave = w->RPort->DrawMode; + apensave = w->RPort->FgPen; + bpensave = w->RPort->BgPen; + + /* + * Set the mode, and be done with it + */ + usecolor = iflags.use_color; + iflags.use_color = FALSE; + cw->wflags |= FLMAP_INGLYPH; +} + +/* + * General cleanup routine -- flushes and restores cursor + */ +void +amii_end_glyphout(window) + winid window; +{ + struct amii_WinDesc *cw; + struct Window *w; + + if( ( cw = amii_wins[ window ] ) == (struct amii_WinDesc *)NULL ) + panic("bad window id %d in amii_end_glyphout()", window ); + + if( ( cw->wflags & FLMAP_INGLYPH ) == 0 ) + return; + cw->wflags &= ~(FLMAP_INGLYPH); + + if( !(w = cw->win ) ) + panic( "bad winid %d, no window ptr set", window ); + + /* + * Clean up whatever is left in the buffer + */ + iflags.use_color = usecolor; + + /* + * Reset internal data structs + */ + SetAPen(w->RPort, apensave); + SetBPen(w->RPort, bpensave); + SetDrMd(w->RPort, modesave); + + Move(w->RPort, xsave, ysave); +} + +static maze_type=COL_MAZE_BRICK; + +void SetMazeType(MazeType t) +{ + maze_type=t; +} + +int GlyphToIcon(int glyph) +{ + if(glyph>10000)return glyph; + return( glyph2tile[glyph] ); +} +#endif + +#ifdef AMII_GRAPHICS +# ifdef TESTING +/* + * Define some stuff for our special glyph drawing routines + */ +static unsigned short glyph_node_index, glyph_buffer_index; +# define NUMBER_GLYPH_NODES 80 +# define GLYPH_BUFFER_SIZE 512 +# endif /* TESTING */ + +struct amii_glyph_node { + short x; + short y; + short len; + unsigned char bg_color; + unsigned char fg_color; + char *buffer; +}; +static struct amii_glyph_node amii_g_nodes[NUMBER_GLYPH_NODES]; +static char amii_glyph_buffer[GLYPH_BUFFER_SIZE]; + +#ifdef TEXTCOLOR +/* + * Map our amiga-specific colormap into the colormap specified in color.h. + * See winami.c for the amiga specific colormap. + */ + +int foreg[AMII_MAXCOLORS] = { 0, 7, 4, 2, 6, 5, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0 }; +int backg[AMII_MAXCOLORS] = { 1, 0, 0, 0, 0, 0, 0, 0, 0, 7, 4, 1, 6, 5, 3, 1 }; +#if 0 + #define CLR_BLACK 0 + #define CLR_RED 1 + #define CLR_GREEN 2 + #define CLR_BROWN 3 /* on IBM, low-intensity yellow is brown */ + #define CLR_BLUE 4 + #define CLR_MAGENTA 5 + #define CLR_CYAN 6 + #define CLR_GRAY 7 /* low-intensity white */ + #define NO_COLOR 8 + #define CLR_ORANGE 9 + #define CLR_BRIGHT_GREEN 10 + #define CLR_YELLOW 11 + #define CLR_BRIGHT_BLUE 12 + #define CLR_BRIGHT_MAGENTA 13 + #define CLR_BRIGHT_CYAN 14 + #define CLR_WHITE 15 + #define CLR_MAX 16 +#endif +#endif + +#ifndef TESTING +/* + * Begin Revamped Text display routines + * + * Up until version 3.1, the only method for displaying text on the playing + * field was by using the console.device. This was nice for a number of + * reasons, the most signifigant of which was a lot of the nuts and bolts was + * done for you via escape sequences interpreted by said device. This did + * not come without a price however. And that price was speed. It has now + * come to a point where the speed has now been deemed unacceptable. + * + * The following series of routines are designed to drop into the current + * nethack display code, using hooks provided for such a measure. It works + * on similar principals as the WindowPuts(), buffering I/O internally + * until either an explicit flush or internal buffering is exceeded, thereby + * forcing the flush. The output (or glyphs) does not go to the + * console.device, however. It is driven directly to the rasterport of the + * nethack window via the low-level Text() calls, increasing the speed by + * a very signifigant factor. + */ +/* + * Routine to simply flush whatever is buffered + */ +void +amii_flush_glyph_buffer( w ) + struct Window *w; +{ + short i, x, y; + register struct RastPort *rp = w->RPort; + + /* If nothing is buffered, return before we do anything */ + if(glyph_node_index == 0) + return; + + cursor_off( WIN_MAP ); + amii_start_glyphout( WIN_MAP ); + + /* Set up the drawing mode */ + SetDrMd( rp, JAM2); + + /* Go ahead and start dumping the stuff */ + for(i=0; iBorderTop + (amii_g_nodes[i].y-2) * rp->TxHeight + + rp->TxBaseline + 1; + x = amii_g_nodes[i].x * rp->TxWidth + w->BorderLeft; + + /* Move pens to correct location */ + Move( rp, (long)x, (long)y); + + /* Setup the colors */ + SetAPen( rp, (long)amii_g_nodes[i].fg_color); + SetBPen( rp, (long)amii_g_nodes[i].bg_color); + + /* Do it */ + Text( rp, amii_g_nodes[i].buffer, amii_g_nodes[i].len); + } + + amii_end_glyphout( WIN_MAP ); + /* Clean up */ + glyph_node_index = glyph_buffer_index = 0; +} +void +amiga_print_glyph(window,color_index, glyph) + winid window; + int color_index, glyph; +{ + if( WINVERS_AMIV ) + amiv_lprint_glyph(window,color_index, glyph); + else + amii_lprint_glyph(window,color_index, glyph); +} + +/* + * Glyph buffering routine. Called instead of WindowPuts(). + */ +void +amii_lprint_glyph(window,color_index, glyph) + winid window; + int color_index, glyph; +{ + int fg_color, bg_color; + struct amii_WinDesc *cw; + struct Window *w; + int curx; + int cury; + + if( ( cw=amii_wins[window] ) == (struct amii_WinDesc *)NULL ) + panic("bad winid in amii_lprint_glyph: %d", window ); + + w = cw->win; + curx=cw->curx; + cury=cw->cury; + +#ifdef TEXTCOLOR + fg_color = foreg[color_index]; + bg_color = backg[color_index]; +#else + fg_color = 1; + bg_color = 0; +#endif /* TEXTCOLOR */ + + /* See if we have enough character buffer space... */ + if(glyph_buffer_index >= GLYPH_BUFFER_SIZE) + amii_flush_glyph_buffer( w ); + + /* + * See if we can append it to the current active node of glyph buffer. It + * must satisfy the following conditions: + * + * * background colors are the same, AND + * * foreground colors are the same, AND + * * they are precisely side by side + */ + if((glyph_buffer_index != 0) && + (fg_color == amii_g_nodes[glyph_node_index-1].fg_color) && + (bg_color == amii_g_nodes[glyph_node_index-1].bg_color) && + (amii_g_nodes[glyph_node_index-1].x+ + amii_g_nodes[glyph_node_index-1].len == curx) && + (amii_g_nodes[glyph_node_index-1].y == cury)) { + /* + * Add it to the end of the buffer + */ + amii_glyph_buffer[glyph_buffer_index++] = glyph; + amii_g_nodes[glyph_node_index-1].len ++; + } else { + /* See if we're out of glyph nodes */ + if(glyph_node_index >= NUMBER_GLYPH_NODES) + amii_flush_glyph_buffer( w ); + amii_g_nodes[glyph_node_index].len = 1; + amii_g_nodes[glyph_node_index].x = curx; + amii_g_nodes[glyph_node_index].y = cury; + amii_g_nodes[glyph_node_index].fg_color = fg_color; + amii_g_nodes[glyph_node_index].bg_color = bg_color; + amii_g_nodes[glyph_node_index].buffer = &amii_glyph_buffer[glyph_buffer_index]; + amii_glyph_buffer[glyph_buffer_index] = glyph; + ++glyph_buffer_index; + ++glyph_node_index; + } +} +#endif /* !TESTING */ + +#ifdef TESTING +/* + * Define some variables which will be used to save context when toggling + * back and forth between low level text and console I/O. + */ +static long xsave, ysave, modesave, apensave, bpensave; +static int usecolor; +#endif /* TESTING */ + +#ifndef TESTING +/* + * The function is called before any glyphs are driven to the screen. It + * removes the cursor, saves internal state of the window, then returns. + */ + +void +amii_start_glyphout(window) + winid window; +{ + struct amii_WinDesc *cw; + struct Window *w; + + if( ( cw=amii_wins[window] ) == (struct amii_WinDesc *)NULL ) + panic( "bad winid %d in start_glyphout()", window ); + + if( cw->wflags & FLMAP_INGLYPH ) + return; + + if( !(w = cw->win ) ) + panic( "bad winid %d, no window ptr set", window ); + + /* + * Save the context of the window + */ + xsave = w->RPort->cp_x; + ysave = w->RPort->cp_y; + modesave = w->RPort->DrawMode; + apensave = w->RPort->FgPen; + bpensave = w->RPort->BgPen; + + /* + * Set the mode, and be done with it + */ + usecolor = iflags.use_color; + iflags.use_color = FALSE; + cw->wflags |= FLMAP_INGLYPH; +} +#endif /* !TESTING */ + +# if 0 +/* + * General cleanup routine -- flushes and restores cursor + */ +void +amii_end_glyphout(window) + winid window; +{ + struct amii_WinDesc *cw; + struct Window *w; + + if( ( cw = amii_wins[ window ] ) == (struct amii_WinDesc *)NULL ) + panic("bad window id %d in amii_end_glyphout()", window ); + + if( ( cw->wflags & FLMAP_INGLYPH ) == 0 ) + return; + cw->wflags &= ~(FLMAP_INGLYPH); + + if( !(w = cw->win ) ) + panic( "bad winid %d, no window ptr set", window ); + + /* + * Clean up whatever is left in the buffer + */ + iflags.use_color = usecolor; + + /* + * Reset internal data structs + */ + SetAPen(w->RPort, apensave); + SetBPen(w->RPort, bpensave); + SetDrMd(w->RPort, modesave); + + Move(w->RPort, xsave, ysave); +} +# endif +#endif + +#ifndef TESTING +# ifdef OPT_DISPMAP +/* don't use dispmap unless x & y are 8,16,24,32,48 and equal */ +void +dispmap_sanity(){ + if( + mxsize != mysize || + dispmap_sanity1(mxsize) || + dispmap_sanity1(mysize)){ + flags.fast_map = 0; + } +} +int +dispmap_sanity1(x) + int x; +{ + static unsigned char valid[] = {8,16,24,32,48,0}; + return !!strchr(valid,x); +} +# endif /* OPT_DISPMAP */ +#endif /* TESTING */ diff --git a/sys/amiga/windefs.h b/sys/amiga/windefs.h new file mode 100644 index 0000000..af017be --- /dev/null +++ b/sys/amiga/windefs.h @@ -0,0 +1,203 @@ +/* SCCS Id: @(#)windefs.h 3.1 93/04/02 */ +/* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include +#include +#include +#if !defined(_DCC) && !defined(__GNUC__) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* stddef.h is included in the precompiled version of hack.h . If we include + * it here normally (through string.h) we'll get an "illegal typedef" later + * on. This is the easiest way I can think of to fix it without messing + * around with the rest of the #includes. --AMC + */ +#if defined(_DCC) && !defined(HACK_H) +# define ptrdiff_t ptrdiff_t_ +# define size_t size_t_ +# define wchar_t wchar_t_ +#endif +#include +#undef strcmpi +#include +#include +#if defined(_DCC) && !defined(HACK_H) +# undef ptrdiff_t +# undef size_t +# undef wchar_T +#endif + +#ifdef IDCMP_CLOSEWINDOW +# ifndef INTUI_NEW_LOOK +# define INTUI_NEW_LOOK +# endif +#endif + +#ifndef HACK_H +#include "hack.h" +#endif +#include "wintype.h" +#include "winami.h" +#include "func_tab.h" + +#ifndef CLIPPING +CLIPPING must be defined for the AMIGA version +#endif + +#undef LI +#undef CO + +/*#define TOPL_GETLINE /* Don't use a window for getlin() */ +/*#define WINDOW_YN /* Use a window for y/n questions */ + +#ifdef AZTEC_C +#include +#else +#ifdef _DCC +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#endif + +/* kludge - see amirip for why */ +# undef red +# undef green +# undef blue +#ifdef _DCC +# include +#else +# include +#endif + +#ifdef _DCC +# define __asm /* DICE doesn't like __asm */ +#endif + +#ifndef __SASC_60 +#undef index +# define index strchr +#endif + +#ifdef _DCC +#include +#else +#include +#endif +#endif + +#ifdef SHAREDLIB +#include "NH:sys/amiga/lib/libmacs.h" +#endif + +#ifdef INTUI_NEW_LOOK +#include +#endif + +#define WINVERS_AMII (strcmp("amii",windowprocs.name)==0) +#define WINVERS_AMIV (strcmp("amitile",windowprocs.name)==0) +#define WINVERS_AMIT (strcmp("amitty",windowprocs.name)==0) + +/* cw->data[x] contains 2 characters worth of special information. These + * characters are stored at the offsets as described here. + */ +#define VATTR 0 /* Video attribute is in this slot */ +#define SEL_ITEM 1 /* If this is a select item, slot is 1 else 0 */ +#define SOFF 2 /* The string starts here. */ + +#undef NULL +#define NULL 0L + +/* + * Versions we need of various libraries. We can't use LIBRARY_VERSION + * as defined in because some of the libraries we need + * don't have that version number in the 1.2 ROM. + */ + +#define LIBRARY_FONT_VERSION 34L +#define LIBRARY_TILE_VERSION 37L + +/* These values are just sorta suggestions in use, but are minimum requirements + * in reality... + */ +#define WINDOWHEIGHT 192 +#define SCREENHEIGHT 200 +#define WIDTH 640 + +/* This character is a solid block (cursor) in Hack.font */ +#define CURSOR_CHAR 0x90 + +#define FONTHEIGHT 8 +#define FONTWIDTH 8 +#define FONTBASELINE 8 + +#define MAPFTWIDTH 8 +#define MAPFTHEIGHT 8 +#define MAPFTBASELN 6 + +/* If Compiling with the "New Look", redefine these now */ +#ifdef INTUI_NEW_LOOK +#define NewWindow ExtNewWindow +#define NewScreen ExtNewScreen +#endif + +#define SIZEOF_DISKNAME 8 + +#define CSI '\x9b' +#define NO_CHAR -1 +#define RAWHELP 0x5F /* Rawkey code of the HELP key */ + + +#define C_BLACK 0 +#define C_WHITE 1 +#define C_BROWN (WINVERS_AMIV ? 11 : 2) +#define C_CYAN (WINVERS_AMIV ? 2 : 3) +#define C_GREEN (WINVERS_AMIV ? 5 : 4) +#define C_MAGENTA (WINVERS_AMIV ? 10 : 5) +#define C_BLUE (WINVERS_AMIV ? 4 : 6) +#define C_RED 7 +#define C_ORANGE 3 +#define C_GREY 6 +#define C_LTGREEN 8 +#define C_YELLOW 9 +#define C_GREYBLUE 12 +#define C_LTBROWN 13 +#define C_LTGREY 14 +#define C_PEACH 15 + +/* Structure describing tile files */ +struct PDAT +{ + long nplanes; /* Depth of images */ + long pbytes; /* Bytes in a plane of data */ + long across; /* Number of tiles across */ + long down; /* Number of tiles down */ + long npics; /* Number of pictures in this file */ + long xsize; /* X-size of a tile */ + long ysize; /* Y-size of a-tile */ +}; + +#undef MAXCOLORS +#define MAXCOLORS 256 diff --git a/sys/amiga/winext.h b/sys/amiga/winext.h new file mode 100644 index 0000000..28e423c --- /dev/null +++ b/sys/amiga/winext.h @@ -0,0 +1,144 @@ +/* SCCS Id: @(#)winext.h 3.1 2000/01/12 */ +/* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993. */ +/* NetHack may be freely redistributed. See license for details. */ + +extern int reclip; + +#ifdef CLIPPING +extern int clipping; +extern int clipx; +extern int clipy; +extern int clipxmax; +extern int clipymax; +extern int xclipbord, yclipbord; +#endif + +extern int CO; +extern int LI; +extern int scrollmsg; +extern int alwaysinvent; + +#ifndef SHAREDLIB +extern unsigned short amii_defpens[ 20 ]; +extern struct amii_DisplayDesc *amiIDisplay; /* the Amiga Intuition descriptor */ +extern struct window_procs amii_procs; +extern struct window_procs amiv_procs; +extern unsigned short amii_initmap[ AMII_MAXCOLORS ]; +extern unsigned short amiv_init_map[ AMII_MAXCOLORS ]; +extern unsigned short amii_init_map[ AMII_MAXCOLORS ]; +extern int bigscreen; +extern int amii_numcolors; +extern long amii_scrnmode; +extern winid amii_rawprwin; +extern struct Screen *HackScreen; +extern char Initialized; +/* These have already been defined elsewhere (and some are conflicting) + * ... going ... going once ... going twice .... + * extern const char *roles[]; + * extern struct Library *ConsoleDevice; + * extern char toplines[ TBUFSZ ]; + * extern NEARDATA winid WIN_MESSAGE; + * extern NEARDATA winid WIN_MAP; + * extern NEARDATA winid WIN_STATUS; + * extern NEARDATA winid WIN_INVEN; + * extern winid WIN_OVER; + * extern struct GfxBase *GfxBase; + * extern struct Library *DiskfontBase; + * extern struct IntuitionBase *IntuitionBase; + * extern struct Library *LayersBase; + */ +extern int amii_msgAPen; +extern int amii_msgBPen; +extern int amii_statAPen; +extern int amii_statBPen; +extern int amii_menuAPen; +extern int amii_menuBPen; +extern int amii_textAPen; +extern int amii_textBPen; +extern int amii_otherAPen; +extern int amii_otherBPen; +#else +extern WinamiBASE *WinamiBase; +#endif +/* All kinds of shared stuff */ +extern struct TextAttr Hack160; +extern struct TextAttr Hack40; +extern struct TextAttr Hack80; +extern struct TextAttr TextsFont13; +extern struct Window *pr_WindowPtr; +extern struct Menu HackMenu[]; +extern struct Menu *MenuStrip; +extern struct NewMenu GTHackMenu[]; +extern APTR *VisualInfo; +extern unsigned char KbdBuffered; +extern struct TextFont *TextsFont; +extern struct TextFont *HackFont; +extern struct IOStdReq ConsoleIO; +extern struct MsgPort *HackPort; + +extern int txwidth, txheight, txbaseline; +#ifdef SUPERBITMAP_MAP +extern struct BitMap amii_vbm; +#endif + +/* This gadget data is replicated for menu/text windows... */ +extern struct PropInfo PropScroll; +extern struct Image Image1; +extern struct Gadget MenuScroll; + +/* This gadget is for the message window... */ +extern struct PropInfo MsgPropScroll; +extern struct Image MsgImage1; +extern struct Gadget MsgScroll; + +extern struct TagItem tags[]; + +extern struct win_setup +{ + struct NewWindow newwin; + UWORD offx,offy,maxrow,rows,maxcol,cols; /* CHECK TYPES */ +} new_wins[]; + +extern UWORD scrnpens[]; +/* The last Window event is stored here for reference. */ +extern WEVENT lastevent; +extern const char winpanicstr[]; +extern struct TagItem scrntags[]; +extern struct NewScreen NewHackScreen; + +extern int topl_addspace; +extern char spaces[ 76 ]; +extern int wincnt; /* # of nh windows opened */ +extern struct Rectangle lastinvent, lastmsg; + +typedef struct { + UWORD w, h; + WORD x, y; + UBYTE nPlanes; + UBYTE masking; + UBYTE compression; + UBYTE reserved1; + UWORD transparentColor; + UBYTE xAspect, yAspect; + WORD pageWidth, pageHeight; +} BitMapHeader; + +typedef enum {COL_MAZE_BRICK,COL_MAZE_STONE,COL_MAZE_HEAT,COL_MAZE_WOOD} MazeType; +extern struct PDAT pictdata; +extern struct Hook fillhook; +extern struct TagItem wintags[]; +#ifndef SHAREDLIB +#ifndef __GNUC__ +void __asm LayerFillHook( + register __a0 struct Hook *hk, + register __a2 struct RastPort *rp, + register __a1 struct FillParams *fp ); +#else +#ifdef __PPC__ +struct EmulLibEntry LayerFillHook; +#else +void LayerFillHook(void); +#endif +#endif +#endif +extern int mxsize, mysize; diff --git a/sys/amiga/winfuncs.c b/sys/amiga/winfuncs.c new file mode 100644 index 0000000..81bca7a --- /dev/null +++ b/sys/amiga/winfuncs.c @@ -0,0 +1,2451 @@ +/* SCCS Id: @(#)winfuncs.c 3.1 2000/01/12 */ +/* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993,1996. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "NH:sys/amiga/windefs.h" +#include "NH:sys/amiga/winext.h" +#include "NH:sys/amiga/winproto.h" +#include "patchlevel.h" + +extern struct TagItem scrntags[]; + +static BitMapHeader amii_bmhd; +static void cursor_common(struct RastPort *, int, int); + +#ifdef CLIPPING +int CO, LI; + +/* Changing clipping region, skip clear of screen in overview window. */ +int reclip; + +/* Must be set to at least two or you will get stuck! */ +int xclipbord = 4, yclipbord = 2; +#endif + +int mxsize, mysize; +struct Rectangle amii_oldover; +struct Rectangle amii_oldmsg; + +extern struct TextFont *RogueFont; + +int amii_msgAPen; +int amii_msgBPen; +int amii_statAPen; +int amii_statBPen; +int amii_menuAPen; +int amii_menuBPen; +int amii_textAPen; +int amii_textBPen; +int amii_otherAPen; +int amii_otherBPen; +long amii_libvers = LIBRARY_FONT_VERSION; + +void +ami_wininit_data( void ) +{ + extern unsigned short amii_init_map[ AMII_MAXCOLORS ]; + extern unsigned short amiv_init_map[ AMII_MAXCOLORS ]; + if( !WINVERS_AMIV ) + { +# ifdef TEXTCOLOR + amii_numcolors = 8; +# else + amii_numcolors = 4; +# endif + amii_defpens[ 0 ] = C_BLACK; /* DETAILPEN */ + amii_defpens[ 1 ] = C_BLUE; /* BLOCKPEN */ + amii_defpens[ 2 ] = C_BROWN; /* TEXTPEN */ + amii_defpens[ 3 ] = C_WHITE; /* SHINEPEN */ + amii_defpens[ 4 ] = C_BLUE; /* SHADOWPEN */ + amii_defpens[ 5 ] = C_CYAN; /* FILLPEN */ + amii_defpens[ 6 ] = C_WHITE; /* FILLTEXTPEN */ + amii_defpens[ 7 ] = C_CYAN; /* BACKGROUNDPEN */ + amii_defpens[ 8 ] = C_RED; /* HIGHLIGHTTEXTPEN */ + amii_defpens[ 9 ] = C_WHITE; /* BARDETAILPEN */ + amii_defpens[ 10 ] = C_CYAN; /* BARBLOCKPEN */ + amii_defpens[ 11 ] = C_BLUE; /* BARTRIMPEN */ + amii_defpens[ 12 ] = (unsigned short) ~0; + + amii_msgAPen = C_WHITE; + amii_msgBPen = C_BLACK; + amii_statAPen = C_WHITE; + amii_statBPen = C_BLACK; + amii_menuAPen = C_WHITE; + amii_menuBPen = C_BLACK; + amii_textAPen = C_WHITE; + amii_textBPen = C_BLACK; + amii_otherAPen = C_RED; + amii_otherBPen = C_BLACK; + + mxsize = 8; + mysize = 8; + + amii_libvers = LIBRARY_FONT_VERSION; + memcpy( amii_initmap, amii_init_map, sizeof( amii_initmap ) ); + } + else + { + mxsize = 16; + mysize = 16; + + amii_numcolors = 16; + + amii_defpens[ 0 ] = C_BLACK; /* DETAILPEN */ + amii_defpens[ 1 ] = C_WHITE; /* BLOCKPEN */ + amii_defpens[ 2 ] = C_BLACK; /* TEXTPEN */ + amii_defpens[ 3 ] = C_CYAN; /* SHINEPEN */ + amii_defpens[ 4 ] = C_BLUE; /* SHADOWPEN */ + amii_defpens[ 5 ] = C_GREYBLUE; /* FILLPEN */ + amii_defpens[ 6 ] = C_LTGREY; /* FILLTEXTPEN */ + amii_defpens[ 7 ] = C_GREYBLUE; /* BACKGROUNDPEN */ + amii_defpens[ 8 ] = C_RED; /* HIGHLIGHTTEXTPEN */ + amii_defpens[ 9 ] = C_WHITE; /* BARDETAILPEN */ + amii_defpens[ 10] = C_GREYBLUE; /* BARBLOCKPEN */ + amii_defpens[ 11] = C_BLUE; /* BARTRIMPEN */ + amii_defpens[ 12] = (unsigned short) ~0; + + amii_msgAPen = C_WHITE; + amii_msgBPen = C_GREYBLUE; + amii_statAPen = C_WHITE; + amii_statBPen = C_GREYBLUE; + amii_menuAPen = C_BLACK; + amii_menuBPen = C_LTGREY; + amii_textAPen = C_BLACK; + amii_textBPen = C_LTGREY; + amii_otherAPen = C_RED; + amii_otherBPen = C_BLACK; + amii_libvers = LIBRARY_TILE_VERSION; + + memcpy( amii_initmap, amiv_init_map, sizeof( amii_initmap ) ); + } +#ifdef OPT_DISPMAP + dispmap_sanity(); +#endif + memcpy(flags.amii_dripens,amii_defpens,sizeof(flags.amii_dripens)); +} + +# ifdef INTUI_NEW_LOOK +struct Hook SM_FilterHook; +struct Hook fillhook; +struct TagItem wintags[] = +{ + { WA_BackFill, (ULONG)&fillhook }, + { WA_PubScreenName, (ULONG)"NetHack" }, + { TAG_END, 0 }, +}; +# endif + +void +amii_destroy_nhwindow(win) /* just hide */ + register winid win; +{ + int i; + int type; + register struct amii_WinDesc *cw; + + if( win == WIN_ERR || ( cw = amii_wins[win] ) == NULL ) + { + panic(winpanicstr,win,"destroy_nhwindow"); + } + + if( WINVERS_AMIV ) + { + if( cw->type == NHW_MAP ) + { + /* If inventory is up, close it now, it will be freed later */ + if( alwaysinvent && WIN_INVEN != WIN_ERR && + amii_wins[ WIN_INVEN ] && + amii_wins[ WIN_INVEN ]->win ) + { + dismiss_nhwindow( WIN_INVEN ); + } + + /* Tear down overview window if it is up */ + if( WIN_OVER != WIN_ERR ) + { + amii_destroy_nhwindow( WIN_OVER ); + WIN_OVER = WIN_ERR; + } + } + else if( cw->type == NHW_OVER ) + { + struct Window *w = amii_wins[ WIN_OVER ]->win; + amii_oldover.MinX = w->LeftEdge; + amii_oldover.MinY = w->TopEdge; + amii_oldover.MaxX = w->Width; + amii_oldover.MaxY = w->Height; + + if( WIN_MESSAGE != WIN_ERR && amii_wins[ WIN_MESSAGE ] ) + { + w = amii_wins[ WIN_MESSAGE ]->win; + amii_oldmsg.MinX = w->LeftEdge; + amii_oldmsg.MinY = w->TopEdge; + amii_oldmsg.MaxX = w->Width; + amii_oldmsg.MaxY = w->Height; + SizeWindow( amii_wins[ WIN_MESSAGE ]->win, + (amiIDisplay->xpix - + amii_wins[ WIN_MESSAGE ]->win->LeftEdge) - + amii_wins[ WIN_MESSAGE ]->win->Width, + 0 ); + } + } + } + + /* Tear down the Intuition stuff */ + dismiss_nhwindow(win); + type = cw->type; + + if( cw->resp ) { + free( cw->resp ); + cw->resp = NULL; + } + if( cw->canresp ) { + free( cw->canresp ); + cw->canresp = NULL; + } + if( cw->morestr ) { + free( cw->morestr ); + cw->morestr = NULL; + } + if( cw->hook ) { + free( cw->hook ); + cw->hook = NULL; + } + + if( cw->data && ( cw->type == NHW_MESSAGE || + cw->type == NHW_MENU || cw->type == NHW_TEXT ) ) + { + for( i = 0; i < cw->maxrow; ++i ) + { + if( cw->data[ i ] ) + free( cw->data[ i ] ); + } + free( cw->data ); + } + + free( cw ); + amii_wins[win] = NULL; + + /* Set globals to WIN_ERR for known one-of-a-kind windows. */ + if( win == WIN_MAP) WIN_MAP = WIN_ERR; + else if( win == WIN_STATUS) WIN_STATUS = WIN_ERR; + else if( win == WIN_MESSAGE) WIN_MESSAGE = WIN_ERR; + else if( win == WIN_INVEN) WIN_INVEN = WIN_ERR; + +} + +#ifdef INTUI_NEW_LOOK +struct FillParams +{ + struct Layer *layer; + struct Rectangle bounds; + WORD offsetx; + WORD offsety; +}; + +#ifdef __GNUC__ +#ifdef __PPC__ +void PPC_LayerFillHook(void); +struct EmulLibEntry LayerFillHook = {TRAP_LIB, 0, (void (*)(void)) PPC_LayerFillHook}; +void PPC_LayerFillHook(void) { + struct Hook *hk = (struct Hook*)REG_A0; + struct RastPort *rp = (struct RastPort *)REG_A2; + struct FillParams *fp = (struct FillParams*)REG_A1; +#else +void LayerFillHook(void) { + register struct Hook *hk asm("a0"); + register struct RastPort *rp asm("a2"); + register struct FillParams *fp asm("a1"); +#endif +#else +void +#ifndef _DCC +__interrupt +#endif +__saveds __asm LayerFillHook( + register __a0 struct Hook *hk, + register __a2 struct RastPort *rp, + register __a1 struct FillParams *fp ) +{ +#endif + + register long x, y, xmax, ymax; + register int apen; + struct RastPort rptmp; + + memcpy(&rptmp, rp, sizeof(struct RastPort)); + rptmp.Layer = NULL; + + switch( (int)hk->h_Data ) + { + case NHW_STATUS: + apen = amii_statBPen; + break; + case NHW_MESSAGE: + apen = amii_msgBPen; + break; + case NHW_TEXT: + apen = amii_textBPen; + break; + case NHW_MENU: + apen = amii_menuBPen; + break; + case -2: + apen = amii_otherBPen; + break; + case NHW_BASE: + case NHW_MAP: + case NHW_OVER: + default: + apen = C_BLACK; + break; + } + + x = fp->bounds.MinX; + y = fp->bounds.MinY; + xmax = fp->bounds.MaxX; + ymax = fp->bounds.MaxY; + + SetAPen(&rptmp, apen); + SetBPen(&rptmp, apen); + SetDrMd(&rptmp, JAM2); + RectFill(&rptmp, x, y, xmax, ymax); +} +#endif + + +amii_create_nhwindow(type) + register int type; +{ + register struct Window *w = NULL; + register struct NewWindow *nw = NULL; + register struct amii_WinDesc *wd = NULL; + struct Window *mapwin = NULL, *stwin = NULL, *msgwin = NULL; + register int newid; + int maph, stath, scrfontysize; + + scrfontysize = HackScreen->Font->ta_YSize; + + /* + * Initial mapwindow height, this might change later in tilemode + * and low screen + */ + maph = ( 21 * mxsize ) + 2 + (bigscreen ? + HackScreen->WBorTop + HackScreen->WBorBottom + scrfontysize + 1 : 0); + + /* Status window height, avoids having to calculate many times */ + stath = txheight * 2 + 2 + (WINVERS_AMIV || bigscreen ? + HackScreen->WBorTop + HackScreen->WBorBottom + + ( bigscreen ? scrfontysize + 1 : 0 ) : 0); + + if( WIN_STATUS != WIN_ERR && amii_wins[ WIN_STATUS ] ) + stwin = amii_wins[ WIN_STATUS ]->win; + + if( WIN_MESSAGE != WIN_ERR && amii_wins[ WIN_MESSAGE ] ) + msgwin = amii_wins[ WIN_MESSAGE ]->win; + + if( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] ) + mapwin = amii_wins[ WIN_MAP ]->win; + + /* Create Port anytime that we need it */ + + if( HackPort == NULL ) + { + HackPort = CreateMsgPort(); + if( !HackPort ) + panic( "no memory for msg port" ); + } + + nw = &new_wins[ type ].newwin; + nw->Width = amiIDisplay->xpix; + nw->Screen = HackScreen; + + if( WINVERS_AMIV ) + { + nw->DetailPen = C_WHITE; + nw->BlockPen = C_GREYBLUE; + } + else + { + nw->DetailPen = C_WHITE; + nw->BlockPen = C_BLACK; + } + + if ( type == NHW_BASE ) { + nw->LeftEdge = 0; + nw->TopEdge = HackScreen->BarHeight+1; + nw->Width = HackScreen->Width; + nw->Height = HackScreen->Height - nw->TopEdge; + } else if( !WINVERS_AMIV && type == NHW_MAP ) { + nw->LeftEdge = 0; + nw->Height = maph; + + if( msgwin && stwin ) { + nw->TopEdge = stwin->TopEdge - maph; + } else { + panic( "msgwin and stwin must open before map" ); + } + if (nw->TopEdge < 0) + panic( "Too small screen to fit map" ); + } + else if( type == NHW_MAP && WINVERS_AMIV ) + { + struct Window *w; + + w = amii_wins[ WIN_MESSAGE ]->win; + nw->LeftEdge = 0; + nw->TopEdge = w->TopEdge + w->Height; + nw->Width = amiIDisplay->xpix - nw->LeftEdge; + + w = amii_wins[ WIN_STATUS ]->win; + nw->Height = w->TopEdge - nw->TopEdge; + nw->MaxHeight = 0xffff; + nw->MaxWidth = 0xffff; + + if( nw->TopEdge + nw->Height > amiIDisplay->ypix - 1 ) + nw->Height = amiIDisplay->ypix - nw->TopEdge - 1; + } + else if( type == NHW_STATUS ) + { + if( !WINVERS_AMIV && ( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] ) ) + w = amii_wins[ WIN_MAP ]->win; + else if( WIN_BASE != WIN_ERR && amii_wins[ WIN_BASE ] ) + w = amii_wins[ WIN_BASE ]->win; + else + panic( "No window to base STATUS location from" ); + + nw->Height = stath; + nw->TopEdge = amiIDisplay->ypix - nw->Height; + nw->LeftEdge = w->LeftEdge; + + if( nw->LeftEdge + nw->Width >= amiIDisplay->xpix ) + nw->LeftEdge = 0; + + if( nw->Width >= amiIDisplay->xpix - nw->LeftEdge ) + nw->Width = amiIDisplay->xpix - nw->LeftEdge; + } + else if( WINVERS_AMIV && type == NHW_OVER ) + { + nw->Flags |= WINDOWSIZING|WINDOWDRAG|WINDOWCLOSE; + nw->IDCMPFlags |= CLOSEWINDOW; + /* Bring up window as half the width of the message window, and make + * the message window change to one half the width... + */ + if( amii_oldover.MaxX != 0 ) + { + nw->LeftEdge = amii_oldover.MinX; + nw->TopEdge = amii_oldover.MinY; + nw->Width = amii_oldover.MaxX; + nw->Height = amii_oldover.MaxY; + ChangeWindowBox( amii_wins[ WIN_MESSAGE ]->win, + amii_oldmsg.MinX, amii_oldmsg.MinY, + amii_oldmsg.MaxX, amii_oldmsg.MaxY ); + } + else + { + nw->LeftEdge = (amii_wins[ WIN_MESSAGE ]->win->Width*4)/9; + nw->TopEdge = amii_wins[ WIN_MESSAGE ]->win->TopEdge; + nw->Width = amiIDisplay->xpix - nw->LeftEdge; + nw->Height = amii_wins[ WIN_MESSAGE ]->win->Height; + SizeWindow( amii_wins[ WIN_MESSAGE ]->win, + nw->LeftEdge - amii_wins[ WIN_MESSAGE ]->win->Width, 0 ); + } + } + else if( type == NHW_MESSAGE ) + { + if( !WINVERS_AMIV && ( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] ) ) + w = amii_wins[ WIN_MAP ]->win; + else if( WIN_BASE != WIN_ERR && amii_wins[ WIN_BASE ] ) + w = amii_wins[ WIN_BASE ]->win; + else + panic( "No window to base STATUS location from" ); + + nw->TopEdge = bigscreen ? HackScreen->BarHeight+1 : 0; + + /* Assume highest possible message window */ + nw->Height = HackScreen->Height - nw->TopEdge - maph - stath; + + /* In tilemode we can cope with this */ + if (WINVERS_AMIV && nw->Height < 0) + nw->Height = 0; + + /* If in fontmode messagewindow is too small, open it with 3 lines + and overlap it with map */ + if (nw->Height < txheight+2) { + nw->Height = txheight*4 + 3 + HackScreen->WBorTop + HackScreen->WBorBottom; + } + + if ((nw->Height-2)/txheight < 3) { + scrollmsg = 0; + nw->Title = 0; + } else { + nw->FirstGadget = &MsgScroll; + nw->Flags |= WINDOWSIZING|WINDOWDRAG; + nw->Flags &= ~BORDERLESS; + + if( WINVERS_AMIV || nw->Height == 0) { + if( WINVERS_AMIV ) { + nw->Height = TextsFont->tf_YSize + HackScreen->WBorTop + 3 + + HackScreen->WBorBottom; + if( bigscreen ) + nw->Height += ( txheight * 6 ); + else + nw->Height += ( txheight * 3 ); + } + else + { + nw->Height = HackScreen->Height - nw->TopEdge - stath - maph; + } + } + } + + /* Do we have room for larger message window ? + * This is possible if we can show full height map in tile + * mode with default scaling. + */ + if (nw->Height + stath + maph < HackScreen->Height - nw->TopEdge ) + nw->Height = HackScreen->Height - nw->TopEdge - 1 - maph - stath; + +#ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + { + MsgPropScroll.Flags |= PROPNEWLOOK; + PropScroll.Flags |= PROPNEWLOOK; + } +#endif + } + + nw->IDCMPFlags |= MENUPICK; + + /* Check if there is "Room" for all this stuff... */ + if( ( WINVERS_AMIV || bigscreen ) && + type != NHW_BASE ) + { + nw->Flags &= ~( BORDERLESS | BACKDROP ); + + if( WINVERS_AMIV ) + { + if( type == NHW_STATUS ) + { + nw->Flags &= ~( WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT | WINDOWSIZING ); + nw->IDCMPFlags &= ~NEWSIZE; + } + else + { + nw->Flags |= ( WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT | WINDOWSIZING ); + nw->IDCMPFlags |= NEWSIZE; + } + } + else + { + if( HackScreen->Width < 657 ) + { + nw->Flags |= ( WINDOWDRAG | WINDOWDEPTH ); + } + else + { + nw->Flags |= ( WINDOWDRAG | WINDOWDEPTH | SIZEBRIGHT ); + } + } + } + + if ( WINVERS_AMII && type == NHW_MAP ) + nw->Flags &= ~WINDOWSIZING; + + if ( type == NHW_MESSAGE && scrollmsg ) { + nw->Flags |= WINDOWDRAG|WINDOWDEPTH|SIZEBRIGHT|WINDOWSIZING; + nw->Flags &= ~BORDERLESS; + } + + /* No titles on a hires only screen except for messagewindow */ + if( !(WINVERS_AMIV && type == NHW_MAP) && !bigscreen && type != NHW_MESSAGE ) + nw->Title = 0; + + wd = (struct amii_WinDesc *)alloc(sizeof(struct amii_WinDesc)); + memset( wd, 0, sizeof( struct amii_WinDesc ) ); + + /* Both, since user may have changed the pen settings so respect those */ + if( WINVERS_AMII || WINVERS_AMIV ) + { + /* Special backfill for these types of layers */ + switch( type ) + { + case NHW_MESSAGE: + case NHW_STATUS: + case NHW_TEXT: + case NHW_MENU: + case NHW_BASE: + case NHW_OVER: + case NHW_MAP: + if( wd ) + { +#ifdef __GNUC__ + fillhook.h_Entry = (void *)&LayerFillHook; +#else + fillhook.h_Entry = (ULONG(*)())LayerFillHook; +#endif + fillhook.h_Data = (void *)type; + fillhook.h_SubEntry = 0; + wd->hook = alloc( sizeof( fillhook ) ); + memcpy( wd->hook, &fillhook, sizeof( fillhook ) ); + memcpy( wd->wintags, wintags, sizeof( wd->wintags) ); + wd->wintags[0].ti_Data = (long)wd->hook; + nw->Extension = (void *)wd->wintags; + } + break; + } + } + + /* Don't open MENU or TEXT windows yet */ + + if( type == NHW_MENU || type == NHW_TEXT ) + w = NULL; + else + w=OpenShWindow( (void *)nw ); + + if( w == NULL && type != NHW_MENU && type != NHW_TEXT ) + { + char buf[ 100 ]; + + sprintf( buf, "nw type (%d) dims l: %d, t: %d, w: %d, h: %d", + type, + nw->LeftEdge, nw->TopEdge, + nw->Width, nw->Height ); + raw_print( buf ); + panic("bad openwin %d",type); + } + + /* Check for an empty slot */ + + for(newid = 0; newid wincnt ) + wincnt = newid; + + /* Do common initialization */ + + amii_wins[newid] = wd; + + wd->newwin = NULL; + wd->win = w; + wd->type = type; + wd->wflags = 0; + wd->active = FALSE; + wd->curx=wd->cury = 0; + wd->resp = wd->canresp = wd->morestr = 0; /* CHECK THESE */ + wd->maxrow = new_wins[type].maxrow; + wd->maxcol = new_wins[type].maxcol; + + if( type != NHW_TEXT && type != NHW_MENU ) + { + if( TextsFont && ( type == NHW_MESSAGE || type == NHW_STATUS ) ) + { + SetFont(w->RPort, TextsFont); + txheight = w->RPort->TxHeight; + txwidth = w->RPort->TxWidth; + txbaseline = w->RPort->TxBaseline; + if( type == NHW_MESSAGE ) + { + if (scrollmsg ) + { + if( WINVERS_AMIV ) + { + WindowLimits( w, 100, w->BorderTop + + w->BorderBottom + + ((txheight+1)*2) + 1, 0, 0 ); + } + else + { + WindowLimits( w, w->Width, w->BorderTop + + w->BorderBottom + + ((txheight+1)*2) + 1, 0, 0 ); + } + } + else + { + WindowLimits( w, w->Width, w->BorderTop + + w->BorderBottom + + txheight + 2, 0, 0 ); + } + } + } + if ( type != NHW_MAP) { + SetFont(w->RPort, TextsFont); + } +#ifdef HACKFONT + else if( HackFont ) + SetFont(w->RPort, HackFont); +#endif + } + + /* Text and menu windows are not opened yet */ + if( w ) + { + wd->rows = ( w->Height - w->BorderTop - + w->BorderBottom - 2 ) / w->RPort->TxHeight; + wd->cols = ( w->Width - w->BorderLeft - + w->BorderRight - 2 ) / w->RPort->TxWidth; + } + + /* Okay, now do the individual type initialization */ + + switch(type) + { + /* History lines for MESSAGE windows are stored in cw->data[?]. + * maxcol and maxrow are used as cursors. maxrow is the count + * of the number of history lines stored. maxcol is the cursor + * to the last line that was displayed by ^P. + */ + case NHW_MESSAGE: + SetMenuStrip(w, MenuStrip); + MsgScroll.TopEdge = HackScreen->WBorTop + scrfontysize + 1; + iflags.msg_history = wd->rows*10; + if (iflags.msg_history < 40) + iflags.msg_history = 40; + if (iflags.msg_history > 400) + iflags.msg_history = 400; + iflags.window_inited=TRUE; + wd->data = (char **)alloc( iflags.msg_history*sizeof( char * ) ); + memset( wd->data, 0, iflags.msg_history * sizeof( char * ) ); + wd->maxrow = wd->maxcol = 0; + /* Indicate that we have not positioned the cursor yet */ + wd->curx = -1; + break; + + /* A MENU contains a list of lines in wd->data[?]. These + * lines are created in amii_putstr() by reallocating the size + * of wd->data to hold enough (char *)'s. wd->rows is the + * number of (char *)'s allocated. wd->maxrow is the number + * used. wd->maxcol is used to track how wide the menu needs + * to be. wd->resp[x] contains the characters that correspond + * to selecting wd->data[x]. wd->resp[x] corresponds to + * wd->data[x] for any x. Elements of wd->data[?] that are not + * valid selections have the corresponding element of + * wd->resp[] set to a value of '\01'; i.e. a ^A which is + * not currently a valid keystroke for responding to any + * MENU or TEXT window. + */ + case NHW_MENU: + MenuScroll.TopEdge = HackScreen->WBorTop + scrfontysize + 1; + wd->resp=(char*)alloc(256); + wd->resp[0]=0; + wd->rows = wd->maxrow = 0; + wd->cols = wd->maxcol = 0; + wd->data = NULL; + break; + + /* See the explanation of MENU above. Except, wd->resp[] is not + * used for TEXT windows since there is no selection of a + * a line performed/allowed. The window is always full + * screen width. + */ + case NHW_TEXT: + MenuScroll.TopEdge = HackScreen->WBorTop + scrfontysize + 1; + wd->rows = wd->maxrow = 0; + wd->cols = wd->maxcol = amiIDisplay->cols; + wd->data = NULL; + wd->morestr = NULL; + break; + + /* The status window has only two lines. These are stored in + * wd->data[], and here we allocate the space for them. + */ + case NHW_STATUS: + SetMenuStrip(w, MenuStrip); + /* wd->cols is the number of characters which fit across the + * screen. + */ + wd->data=(char **)alloc(3*sizeof(char *)); + wd->data[0] = (char *)alloc(wd->cols + 10); + wd->data[1] = (char *)alloc(wd->cols + 10); + wd->data[2] = NULL; + break; + + /* NHW_OVER does not use wd->data[] or the other text + * manipulating members of the amii_WinDesc structure. + */ + case NHW_OVER: + SetMenuStrip(w, MenuStrip); + break; + + /* NHW_MAP does not use wd->data[] or the other text + * manipulating members of the amii_WinDesc structure. + */ + case NHW_MAP: + SetMenuStrip(w, MenuStrip); + if( WINVERS_AMIV ) + { + CO = (w->Width-w->BorderLeft-w->BorderRight)/mxsize; + LI = (w->Height-w->BorderTop-w->BorderBottom)/mysize; + amii_setclipped(); + SetFont( w->RPort, RogueFont); + SetAPen( w->RPort, C_WHITE); /* XXX not sufficient */ + SetBPen( w->RPort, C_BLACK); + SetDrMd( w->RPort, JAM2); + } + else + { + if( HackFont ) + SetFont( w->RPort, HackFont ); + } + break; + + /* The base window must exist until CleanUp() deletes it. */ + case NHW_BASE: + SetMenuStrip(w, MenuStrip); + /* Make our requesters come to our screen */ + { + register struct Process *myProcess = + (struct Process *) FindTask(NULL); + pr_WindowPtr = (struct Window *)(myProcess->pr_WindowPtr); + myProcess->pr_WindowPtr = (APTR) w; + } + + /* Need this for RawKeyConvert() */ + + ConsoleIO.io_Data = (APTR) w; + ConsoleIO.io_Length = sizeof( struct Window ); + ConsoleIO.io_Message.mn_ReplyPort = CreateMsgPort(); + if( OpenDevice("console.device", -1L, + (struct IORequest *) &ConsoleIO, 0L) != 0) + { + Abort(AG_OpenDev | AO_ConsoleDev); + } + + ConsoleDevice = (struct Library *) ConsoleIO.io_Device; + + KbdBuffered = 0; + +#ifdef HACKFONT + if( TextsFont ) + SetFont( w->RPort, TextsFont ); + else if( HackFont ) + SetFont( w->RPort, HackFont ); +#endif + txwidth = w->RPort->TxWidth; + txheight = w->RPort->TxHeight; + txbaseline = w->RPort->TxBaseline; + break; + + default: + panic("bad create_nhwindow( %d )\n",type); + return WIN_ERR; + } + + return( newid ); +} + +#ifdef __GNUC__ +#ifdef __PPC__ +int PPC_SM_Filter(void); +struct EmulLibEntry SM_Filter = {TRAP_LIB, 0, (int (*)(void)) PPC_SM_Filter}; +int PPC_SM_Filter(void) { + struct Hook *hk = (struct Hook*)REG_A0; + ULONG modeID = (ULONG)REG_A1; + struct ScreenModeRequester *smr = (struct ScreenModeRequester *)REG_A2; +#else +int SM_Filter(void) { + register struct Hook *hk asm("a0"); + register ULONG modeID asm("a1"); + register struct ScreenModeRequester *smr asm("a2"); +#endif +#else +int +#ifndef _DCC +__interrupt +#endif +__saveds __asm SM_Filter( + register __a0 struct Hook *hk, + register __a1 ULONG modeID, + register __a2 struct ScreenModeRequester *smr) +{ +#endif + struct DimensionInfo dims; + struct DisplayInfo disp; + DisplayInfoHandle handle; + handle = FindDisplayInfo(modeID); + if (handle) { + GetDisplayInfoData(handle, (char *)&dims, sizeof(dims), DTAG_DIMS, modeID); + GetDisplayInfoData(handle, (char *)&disp, sizeof(disp), DTAG_DISP, modeID); + if (!disp.NotAvailable && + dims.MaxDepth <= 8 && + dims.StdOScan.MaxX >= WIDTH-1 && + dims.StdOScan.MaxY >= SCREENHEIGHT-1) { + return 1; + } + } + return 0; +} + +/* Initialize the windowing environment */ + +void +amii_init_nhwindows(argcp,argv) + int *argcp; + char **argv; +{ + int i; + struct Screen *wbscr; + int forcenobig = 0; + + if( HackScreen ) + panic( "init_nhwindows() called twice", 0 ); + + /* run args & set bigscreen from -L(1)/-l(-1) */ + { + int lclargc = *argcp; + int t; + char **argv_in = argv; + char **argv_out = argv; + + for(t=1;t<=lclargc;t++){ + if(!strcmp("-L",*argv_in) || !strcmp("-l",*argv_in)){ + bigscreen = (*argv_in[1]=='l') ? -1 : 1; + /* and eat the flag */ + (*argcp)--; + } else { + *argv_out = *argv_in; /* keep the flag */ + argv_out++; + } + argv_in++; + } + *argv_out = 0; + } + + WIN_MESSAGE = WIN_ERR; + WIN_MAP = WIN_ERR; + WIN_STATUS = WIN_ERR; + WIN_INVEN = WIN_ERR; + WIN_BASE = WIN_ERR; + WIN_OVER = WIN_ERR; + + if ( (IntuitionBase = (struct IntuitionBase *) + OpenLibrary("intuition.library", amii_libvers )) == NULL) + { + Abort(AG_OpenLib | AO_Intuition); + } + + if ( (GfxBase = (struct GfxBase *) + OpenLibrary("graphics.library", amii_libvers )) == NULL) + { + Abort(AG_OpenLib | AO_GraphicsLib); + } + + if( (LayersBase = (struct Library *) + OpenLibrary("layers.library", amii_libvers )) == NULL) + { + Abort(AG_OpenLib | AO_LayersLib); + } + + if ((GadToolsBase = OpenLibrary("gadtools.library", amii_libvers)) == NULL) { + Abort(AG_OpenLib | AO_GadTools); + } + + if ((AslBase = OpenLibrary("asl.library", amii_libvers)) == NULL) { + Abort(AG_OpenLib); + } + + amiIDisplay=(struct amii_DisplayDesc *)alloc(sizeof(struct amii_DisplayDesc)); + memset( amiIDisplay, 0, sizeof( struct amii_DisplayDesc ) ); + + /* Use Intuition sizes for overscan screens... */ + + amiIDisplay->xpix = 0; +#ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + { + if( wbscr = LockPubScreen( "Workbench" ) ) + { + amiIDisplay->xpix = wbscr->Width; + amiIDisplay->ypix = wbscr->Height; + UnlockPubScreen( NULL, wbscr ); + } + } +#endif + if( amiIDisplay->xpix == 0 ) + { + amiIDisplay->ypix = GfxBase->NormalDisplayRows; + amiIDisplay->xpix = GfxBase->NormalDisplayColumns; + } + + amiIDisplay->cols = amiIDisplay->xpix / FONTWIDTH; + + amiIDisplay->toplin=0; + amiIDisplay->rawprint=0; + amiIDisplay->lastwin=0; + + if( bigscreen == 0 ) + { + if( ( GfxBase->ActiView->ViewPort->Modes & LACE ) == LACE ) + { + amiIDisplay->ypix *= 2; + NewHackScreen.ViewModes |= LACE; + bigscreen = 1; + } + else if( GfxBase->NormalDisplayRows >= 300 || + amiIDisplay->ypix >= 300 ) + { + bigscreen = 1; + } + } + else if( bigscreen == -1 ) + { + bigscreen = 0; + forcenobig = 1; + } + else if( bigscreen ) + { + /* If bigscreen requested and we don't have enough rows in + * noninterlaced mode, switch to interlaced... + */ + if( GfxBase->NormalDisplayRows < 300 ) + { + amiIDisplay->ypix *= 2; + NewHackScreen.ViewModes |= LACE; + } + } + + if( !bigscreen ) + { + alwaysinvent = 0; + } + amiIDisplay->rows = amiIDisplay->ypix / FONTHEIGHT; + +#ifdef HACKFONT + /* + * Load the fonts that we need. + */ + + if( DiskfontBase = + OpenLibrary( "diskfont.library", amii_libvers ) ) + { + Hack80.ta_Name -= SIZEOF_DISKNAME; + HackFont = OpenDiskFont( &Hack80 ); + Hack80.ta_Name += SIZEOF_DISKNAME; + + /* Textsfont13 is filled in with "FONT=" settings. The default is + * courier/13. + */ + TextsFont = NULL; + if( bigscreen ) + TextsFont = OpenDiskFont( &TextsFont13 ); + + /* Try hack/8 for texts if no user specified font */ + if( TextsFont == NULL ) + { + Hack80.ta_Name -= SIZEOF_DISKNAME; + TextsFont = OpenDiskFont( &Hack80 ); + Hack80.ta_Name += SIZEOF_DISKNAME; + } + + /* If no fonts, make everything topaz 8 for non-view windows. + */ + Hack80.ta_Name = "topaz.font"; + RogueFont = OpenFont( &Hack80 ); + if(!RogueFont) panic("Can't get topaz:8"); + if( !HackFont || !TextsFont ) + { + if( !HackFont ) + { + HackFont = OpenFont( &Hack80 ); + if( !HackFont ) + panic( "Can't get a map font, topaz:8" ); + } + + if( !TextsFont ) + { + TextsFont = OpenFont( &Hack80 ); + if( !TextsFont ) + panic( "Can't open text font" ); + } + } + CloseLibrary(DiskfontBase); + DiskfontBase = NULL; + } +#endif + + /* Adjust getlin window size to font */ + + if (TextsFont) { + extern SHORT BorderVectors1[]; + extern SHORT BorderVectors2[]; + extern struct Gadget Gadget2; + extern struct Gadget String; + extern struct NewWindow StrWindow; + BorderVectors1[2] += (TextsFont->tf_XSize-8)*6; /* strlen("Cancel") == 6 */ + BorderVectors1[4] += (TextsFont->tf_XSize-8)*6; + BorderVectors1[5] += TextsFont->tf_YSize-8; + BorderVectors1[7] += TextsFont->tf_YSize-8; + BorderVectors2[2] += (TextsFont->tf_XSize-8)*6; + BorderVectors2[4] += (TextsFont->tf_XSize-8)*6; + BorderVectors2[5] += TextsFont->tf_YSize-8; + BorderVectors2[7] += TextsFont->tf_YSize-8; + Gadget2.TopEdge += TextsFont->tf_YSize-8; + Gadget2.Width += (TextsFont->tf_XSize-8)*6; + Gadget2.Height += TextsFont->tf_YSize-8; + String.LeftEdge += (TextsFont->tf_XSize-8)*6; + String.TopEdge += TextsFont->tf_YSize-8; + String.Width += TextsFont->tf_XSize-8; + String.Height += TextsFont->tf_YSize-8; + StrWindow.Width += (TextsFont->tf_XSize-8)*7; + StrWindow.Height += (TextsFont->tf_YSize-8)*2; /* Titlebar + 1 row of gadgets */ + } + + /* This is the size screen we want to open, within reason... */ + + NewHackScreen.Width = max( WIDTH, amiIDisplay->xpix ); + NewHackScreen.Height = max( SCREENHEIGHT, amiIDisplay->ypix ); + { + static char fname[18]; + sprintf(fname,"NetHack %d.%d.%d", VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL); + NewHackScreen.DefaultTitle=fname; + } +#if 0 + NewHackScreen.BlockPen = C_BLACK; + NewHackScreen.DetailPen = C_WHITE; +#endif +#ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + { + int i; + struct DimensionInfo dims; + DisplayInfoHandle handle; + struct DisplayInfo disp; + ULONG modeid = DEFAULT_MONITOR_ID|HIRES_KEY; + + NewHackScreen.Width = STDSCREENWIDTH; + NewHackScreen.Height = STDSCREENHEIGHT; + +#ifdef HACKFONT + if (TextsFont) { + NewHackScreen.Font = &TextsFont13; + } +#endif + + if ( amii_scrnmode == 0xffffffff ) { + struct ScreenModeRequester *SMR; +#ifdef __GNUC__ + SM_FilterHook.h_Entry = (void *)&SM_Filter; +#else + SM_FilterHook.h_Entry = (ULONG(*)())SM_Filter; +#endif + SM_FilterHook.h_Data = 0; + SM_FilterHook.h_SubEntry = 0; + SMR = AllocAslRequest(ASL_ScreenModeRequest,NULL); + if (AslRequestTags(SMR, + ASLSM_FilterFunc, (ULONG)&SM_FilterHook, + TAG_END)) + amii_scrnmode = SMR->sm_DisplayID; + else + amii_scrnmode = 0; + FreeAslRequest(SMR); + } + + if( forcenobig == 0 ) + { + if( ( wbscr = LockPubScreen( "Workbench" ) ) != NULL || + ( wbscr = LockPubScreen( NULL ) ) != NULL ) + { + /* Get the default pub screen's size */ + modeid = GetVPModeID( &wbscr->ViewPort ); + if( modeid == INVALID_ID || + ModeNotAvailable( modeid ) || + ( handle = FindDisplayInfo( modeid ) ) == NULL || + GetDisplayInfoData( handle, (char *)&dims, sizeof( dims ), + DTAG_DIMS, modeid ) <= 0 || + GetDisplayInfoData( handle, (char *)&disp, sizeof( disp ), + DTAG_DISP, modeid ) <= 0 ) + { + modeid = DEFAULT_MONITOR_ID|HIRES_KEY; + /* If the display database seems to not work, use the screen + * dimensions + */ + NewHackScreen.Height = wbscr->Height; + NewHackScreen.Width = wbscr->Width; + + /* + * Request LACE if it looks laced. For 2.1/3.0, we will get + * promoted to the users choice of modes (if promotion is allowed) + * If the user is using a dragable screen, things will get hosed + * but that is life... + */ + if( wbscr->ViewPort.Modes & LACE ) + NewHackScreen.ViewModes |= LACE; + modeid = -1; + } + else + { + /* Use the display database to get the correct information */ + if( disp.PropertyFlags & DIPF_IS_LACE ) + NewHackScreen.ViewModes |= LACE; + NewHackScreen.Height = dims.StdOScan.MaxY+1; + NewHackScreen.Width = dims.StdOScan.MaxX+1; + } + NewHackScreen.TopEdge = 0; + NewHackScreen.LeftEdge = 0; + + UnlockPubScreen( NULL, wbscr ); + } + } + + for( i = 0; scrntags[i].ti_Tag != TAG_DONE; ++i ) + { + switch( scrntags[i].ti_Tag ) + { + case SA_DisplayID: + if( !amii_scrnmode || ModeNotAvailable( amii_scrnmode ) ) + { + if( ModeNotAvailable( modeid ) ) + { + scrntags[i].ti_Tag = TAG_IGNORE; + break; + } + else + scrntags[i].ti_Data = (long)modeid; + } + else + modeid = scrntags[i].ti_Data = (long)amii_scrnmode; + if( ( handle = FindDisplayInfo( modeid ) ) != NULL && + GetDisplayInfoData( handle, (char *)&dims, sizeof( dims ), + DTAG_DIMS, modeid ) > 0 && + GetDisplayInfoData( handle, (char *)&disp, sizeof( disp ), + DTAG_DISP, modeid ) > 0 ) + { + if( disp.PropertyFlags & DIPF_IS_LACE ) + NewHackScreen.ViewModes |= LACE; + NewHackScreen.Height = dims.StdOScan.MaxY+1; + NewHackScreen.Width = dims.StdOScan.MaxX+1; + } + break; + + case SA_Pens: + scrntags[i].ti_Data = (long)flags.amii_dripens; + break; + } + } + } +#endif + + if( WINVERS_AMIV ) + amii_bmhd = ReadTileImageFiles( ); + else + memcpy( amii_initmap, amii_init_map, sizeof( amii_initmap ) ); + memcpy(flags.amii_curmap,amii_initmap,sizeof(flags.amii_curmap)); + + /* Find out how deep the screen needs to be, 32 planes is enough! */ + for( i = 0; i < 32; ++i ) + { + if( ( 1L << i ) >= amii_numcolors ) + break; + } + + NewHackScreen.Depth = i; + + /* If for some reason Height/Width became smaller than the required, + have the required one */ + if (NewHackScreen.Height < SCREENHEIGHT) + NewHackScreen.Height = SCREENHEIGHT; + if (NewHackScreen.Width < WIDTH) + NewHackScreen.Width = WIDTH; +#ifdef HACKFONT + i = max(TextsFont->tf_XSize, HackFont->tf_XSize); + if (NewHackScreen.Width < 80*i+4) + NewHackScreen.Width = 80*i+4; +#endif + + /* While openscreen fails try fewer colors to see if that is the problem. */ + while( ( HackScreen = OpenScreen( (void *)&NewHackScreen ) ) == NULL ) + { +#ifdef TEXTCOLOR + if( --NewHackScreen.Depth < 3 ) +#else + if( --NewHackScreen.Depth < 2 ) +#endif + Abort( AN_OpenScreen & ~AT_DeadEnd ); + } + amii_numcolors = 1L << NewHackScreen.Depth; + if( HackScreen->Height > 300 && forcenobig == 0 ) + bigscreen = 1; + else + bigscreen = 0; + +#ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + PubScreenStatus( HackScreen, 0 ); +#endif + + amiIDisplay->ypix = HackScreen->Height; + amiIDisplay->xpix = HackScreen->Width; + + LoadRGB4(&HackScreen->ViewPort, flags.amii_curmap, amii_numcolors ); + + VisualInfo = GetVisualInfo(HackScreen, TAG_END); + MenuStrip = CreateMenus(GTHackMenu, TAG_END); + LayoutMenus(MenuStrip, VisualInfo, GTMN_NewLookMenus, TRUE, TAG_END); + + /* Display the copyright etc... */ + + if( WIN_BASE == WIN_ERR ) + WIN_BASE = amii_create_nhwindow( NHW_BASE ); + amii_clear_nhwindow( WIN_BASE ); + amii_putstr( WIN_BASE, 0, "" ); + amii_putstr( WIN_BASE, 0, "" ); + amii_putstr( WIN_BASE, 0, "" ); + amii_putstr( WIN_BASE, 0, COPYRIGHT_BANNER_A); + amii_putstr( WIN_BASE, 0, COPYRIGHT_BANNER_B); + amii_putstr( WIN_BASE, 0, COPYRIGHT_BANNER_C); + amii_putstr( WIN_BASE, 0, ""); + + Initialized = 1; +} + +void +amii_sethipens( struct Window *w, int type, int attr ) +{ + switch( type ) + { + default: + SetAPen( w->RPort, attr ? C_RED : amii_otherAPen ); + SetBPen( w->RPort, C_BLACK ); + break; + case NHW_STATUS: + SetAPen( w->RPort, attr ? C_WHITE : amii_statAPen ); + SetBPen( w->RPort, amii_statBPen ); + break; + case NHW_MESSAGE: + SetAPen( w->RPort, attr ? C_WHITE : amii_msgAPen ); + SetBPen( w->RPort, amii_msgBPen ); + break; + case NHW_MENU: + SetAPen( w->RPort, attr ? C_BLACK : amii_menuAPen ); + SetBPen( w->RPort, amii_menuBPen ); + break; + case NHW_TEXT: + SetAPen( w->RPort, attr ? C_BLACK : amii_textAPen ); + SetBPen( w->RPort, amii_textBPen ); + case -2: + SetBPen( w->RPort, amii_otherBPen ); + SetAPen( w->RPort, attr ? C_RED : amii_otherAPen ); + break; + } +} + +void +amii_setfillpens( struct Window *w, int type ) +{ + switch( type ) + { + case NHW_MESSAGE: + SetAPen( w->RPort, amii_msgBPen ); + SetBPen( w->RPort, amii_msgBPen ); + break; + case NHW_STATUS: + SetAPen( w->RPort, amii_statBPen ); + SetBPen( w->RPort, amii_statBPen ); + break; + case NHW_MENU: + SetAPen( w->RPort, amii_menuBPen ); + SetBPen( w->RPort, amii_menuBPen ); + break; + case NHW_TEXT: + SetAPen( w->RPort, amii_textBPen ); + SetBPen( w->RPort, amii_textBPen ); + break; + case NHW_MAP: + case NHW_BASE: + case NHW_OVER: + default: + SetAPen( w->RPort, C_BLACK ); + SetBPen( w->RPort, C_BLACK ); + break; + case -2: + SetAPen( w->RPort, amii_otherBPen ); + SetBPen( w->RPort, amii_otherBPen ); + break; + } +} + +void +amii_setdrawpens( struct Window *w, int type ) +{ + switch( type ) + { + case NHW_MESSAGE: + SetAPen( w->RPort, amii_msgAPen ); + SetBPen( w->RPort, amii_msgBPen ); + break; + case NHW_STATUS: + SetAPen( w->RPort, amii_statAPen ); + SetBPen( w->RPort, amii_statBPen ); + break; + case NHW_MENU: + SetAPen( w->RPort, amii_menuAPen ); + SetBPen( w->RPort, amii_menuBPen ); + break; + case NHW_TEXT: + SetAPen( w->RPort, amii_textAPen ); + SetBPen( w->RPort, amii_textBPen ); + break; + case NHW_MAP: + case NHW_BASE: + case NHW_OVER: + SetAPen( w->RPort, C_WHITE ); + SetBPen( w->RPort, C_BLACK ); + break; + default: + SetAPen( w->RPort, amii_otherAPen ); + SetBPen( w->RPort, amii_otherBPen ); + break; + } +} + +/* Clear the indicated window */ + +void +amii_clear_nhwindow(win) + register winid win; +{ + register struct amii_WinDesc *cw; + register struct Window *w; + + if( reclip == 2 ) return; + + if( win == WIN_ERR || ( cw = amii_wins[win] ) == NULL ) + panic( winpanicstr, win, "clear_nhwindow" ); + + /* Clear the overview window too if it is displayed */ + if( WINVERS_AMIV && ( cw->type == WIN_MAP && WIN_OVER != WIN_ERR && reclip == 0 ) ) + { + amii_clear_nhwindow( WIN_OVER ); + } + + if( w = cw->win ) + SetDrMd( w->RPort, JAM2); + else + return; + + if( (cw->wflags & FLMAP_CURSUP ) ) + { + if( cw->type != NHW_MAP ) + cursor_off( win ); + else + cw->wflags &= ~FLMAP_CURSUP; + } + + amii_setfillpens( w, cw->type ); + SetDrMd( w->RPort, JAM2 ); + + if( cw->type == NHW_MENU || cw->type == NHW_TEXT ) + { + RectFill( w->RPort, w->BorderLeft, w->BorderTop, + w->Width - w->BorderRight-1, + w->Height - w->BorderBottom-1 ); + } + else + { + if( cw->type == NHW_MESSAGE ) + { + amii_curs( win, 1, 0 ); + if( !scrollmsg ) + TextSpaces( w->RPort, cw->cols ); + } + else + { + RectFill( w->RPort, w->BorderLeft, w->BorderTop, + w->Width - w->BorderRight-1, + w->Height - w->BorderBottom-1 ); + } + } + + cw->cury = 0; + cw->curx = 0; + amii_curs( win, 1, 0 ); +} + +/* Dismiss the window from the screen */ + +void +dismiss_nhwindow(win) + register winid win; +{ + register struct Window *w; + register struct amii_WinDesc *cw; + + if( win == WIN_ERR || ( cw = amii_wins[win] ) == NULL ) + { + panic(winpanicstr,win, "dismiss_nhwindow"); + } + + w = cw->win; + + if( w ) + { + /* All windows have this stuff attached to them. */ + if( cw->type == NHW_MAP || + cw->type == NHW_OVER || + cw->type == NHW_BASE || + cw->type == NHW_MESSAGE || + cw->type == NHW_STATUS ) + { + ClearMenuStrip( w ); + } + + /* Save where user like inventory to appear */ + if( win == WIN_INVEN ) + { + lastinvent.MinX = w->LeftEdge; + lastinvent.MinY = w->TopEdge; + lastinvent.MaxX = w->Width; + lastinvent.MaxY = w->Height; + } + + /* Close the window */ + CloseShWindow( w ); + cw->win = NULL; + + /* Free copy of NewWindow structure for TEXT/MENU windows. */ + if( cw->newwin ) + FreeNewWindow( (void *)cw->newwin ); + cw->newwin = NULL; + } +} + +void +amii_exit_nhwindows(str) + const char *str; +{ + /* Seems strange to have to do this... but we need the BASE window + * left behind... + */ + kill_nhwindows( 0 ); + if( WINVERS_AMIV ) + FreeTileImageFiles( ); + + if( str ) + { + raw_print( "" ); /* be sure we're not under the top margin */ + raw_print( str ); + } +} + +void +amii_display_nhwindow(win,blocking) + winid win; + boolean blocking; +{ + menu_item *mip; + int cnt; + static int lastwin = -1; + struct amii_WinDesc *cw; + + if( !Initialized ) + return; + lastwin = win; + + if( win == WIN_ERR || ( cw = amii_wins[win] ) == NULL ) + panic(winpanicstr,win,"display_nhwindow"); + + if( cw->type == NHW_MESSAGE ) + cw->wflags &= ~FLMAP_SKIP; + + if( cw->type == NHW_MESSAGE || cw->type == NHW_STATUS ) + return; + + if( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] ) + { + flush_glyph_buffer( amii_wins[ WIN_MAP ]->win ); + } + + if( cw->type == NHW_MENU || cw->type == NHW_TEXT ) + { + cnt = DoMenuScroll( win, blocking, PICK_ONE, &mip ); + } + else if( cw->type==NHW_MAP ) + { + amii_end_glyphout( win ); + /* Do more if it is time... */ + if( blocking == TRUE && amii_wins[ WIN_MESSAGE ]->curx ) + { + outmore( amii_wins[ WIN_MESSAGE ] ); + } + } +} + +void +amii_curs(window, x, y) +winid window; +register int x, y; /* not xchar: perhaps xchar is unsigned and + curx-x would be unsigned as well */ +{ + register struct amii_WinDesc *cw; + register struct Window *w; + register struct RastPort *rp; + + if( window == WIN_ERR || ( cw = amii_wins[window] ) == NULL ) + panic(winpanicstr, window, "curs"); + if( (w = cw->win) == NULL ) + { + if( cw->type == NHW_MENU || cw->type == NHW_TEXT ) + return; + else + panic( "No window open yet in curs() for winid %d\n", window ); + } + amiIDisplay->lastwin = window; + + /* Make sure x is within bounds */ + if( x > 0 ) + --x; /* column 0 is never used */ + else + x = 0; + + cw->curx = x; + cw->cury = y; + +#ifdef DEBUG + if( x<0 || y<0 || y >= cw->rows || x >= cw->cols ) + { + char *s = "[unknown type]"; + switch(cw->type) + { + case NHW_MESSAGE: s = "[topl window]"; break; + case NHW_STATUS: s = "[status window]"; break; + case NHW_MAP: s = "[map window]"; break; + case NHW_MENU: s = "[menu window]"; break; + case NHW_TEXT: s = "[text window]"; break; + case NHW_BASE: s = "[base window]"; break; + case NHW_OVER: s = "[overview window]"; break; + } + impossible("bad curs positioning win %d %s (%d,%d)", window, s, x, y); + return; + } +#endif + +#ifdef CLIPPING + if(clipping && cw->type == NHW_MAP) + { + x -= clipx; + y -= clipy; + } +#endif + + /* Output all saved output before doing cursor movements for MAP */ + + if( cw->type == NHW_MAP ) + { + flush_glyph_buffer( w ); + } + + /* Actually do it */ + + rp = w->RPort; + if( cw->type == NHW_MENU ) + { + if( WINVERS_AMIV ) + { + if( window == WIN_INVEN ) + { + Move( rp, (x * rp->TxWidth) + w->BorderLeft + 1 + pictdata.xsize + 4, + (y * max(rp->TxHeight,pictdata.ysize + 3) ) + + rp->TxBaseline + pictdata.ysize - rp->TxHeight + w->BorderTop + 4 ); + } + else + { + Move( rp, (x * rp->TxWidth) + w->BorderLeft + 1, + (y * rp->TxHeight) + rp->TxBaseline + w->BorderTop + 1 ); + } + } + else + { + Move( rp, (x * rp->TxWidth) + w->BorderLeft + 1, + (y*rp->TxHeight ) + rp->TxBaseline + w->BorderTop + 1 ); + } + } + else if( cw->type == NHW_TEXT ) + { + Move( rp, (x * rp->TxWidth) + w->BorderLeft + 1, + (y*rp->TxHeight ) + rp->TxBaseline + w->BorderTop + 1 ); + } + else if( cw->type == NHW_MAP || cw->type == NHW_BASE ) + { + /* These coordinate calculations must be synced with those + * in flush_glyph_buffer() in winchar.c. curs_on_u() will + * use this code, all other drawing occurs through the glyph + * code. In order for the cursor to appear on top of the hero, + * the code must compute X,Y in the same manner relative to + * the RastPort coordinates. + * + * y = w->BorderTop + (g_nodes[i].y-2) * rp->TxHeight + + * rp->TxBaseline + 1; + * x = g_nodes[i].x * rp->TxWidth + w->BorderLeft; + */ + + if( WINVERS_AMIV ) + { + if( cw->type == NHW_MAP ) + { + if(Is_rogue_level(&u.uz)){ +#if 0 +int qqx= (x * w->RPort->TxWidth) + w->BorderLeft; +int qqy= w->BorderTop + ( (y+1) * w->RPort->TxHeight ) + 1; +printf("pos: (%d,%d)->(%d,%d)\n",x,y,qqx,qqy); +#endif + SetAPen(w->RPort,C_WHITE); /* XXX should be elsewhere (was 4)*/ + Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft, + w->BorderTop + ( (y+1) * w->RPort->TxHeight ) + 1 ); + } else { + Move( rp, (x * mxsize) + w->BorderLeft, + w->BorderTop + ( (y+1) * mysize ) + 1 ); + } + } + else + { + Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft, + w->BorderTop + ( (y + 1) * w->RPort->TxHeight ) + + w->RPort->TxBaseline + 1 ); + } + } + else + { + Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft, + w->BorderTop + ( y * w->RPort->TxHeight ) + + w->RPort->TxBaseline + 1 ); + } + } + else if( WINVERS_AMIV && cw->type == NHW_OVER ) + { + Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2, + w->BorderTop + w->RPort->TxBaseline + 3 ); + } + else if( cw->type == NHW_MESSAGE && !scrollmsg ) + { + Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2, + w->BorderTop + w->RPort->TxBaseline + 3 ); + } + else if( cw->type == NHW_STATUS ) + { + Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2, + (y*(w->RPort->TxHeight+1)) + w->BorderTop + + w->RPort->TxBaseline + 1 ); + } + else + { + Move( rp, (x * w->RPort->TxWidth) + w->BorderLeft + 2, + (y*w->RPort->TxHeight) + w->BorderTop + + w->RPort->TxBaseline + 1 ); + } +} + +void +amii_set_text_font( name, size ) + char *name; + int size; +{ + register int i; + register struct amii_WinDesc *cw; + int osize = TextsFont13.ta_YSize; + static char nname[ 100 ]; + + strncpy( nname, name, sizeof( nname ) - 1 ); + nname[ sizeof( nname ) - 1 ] = 0; + + TextsFont13.ta_Name = nname; + TextsFont13.ta_YSize = size; + + /* No alternate text font allowed for 640x269 or smaller */ + if( !HackScreen || !bigscreen ) + return; + + /* Look for windows to set, and change them */ + + if( DiskfontBase = + OpenLibrary( "diskfont.library", amii_libvers ) ) + { + TextsFont = OpenDiskFont( &TextsFont13 ); + for( i = 0; TextsFont && i < MAXWIN; ++i ) + { + if( (cw = amii_wins[ i ]) && cw->win != NULL ) + { + switch( cw->type ) + { + case NHW_STATUS: + MoveWindow( cw->win, 0, -( size - osize ) * 2 ); + SizeWindow( cw->win, 0, ( size - osize ) * 2 ); + SetFont( cw->win->RPort, TextsFont ); + break; + case NHW_MESSAGE: + case NHW_MAP: + case NHW_BASE: + case NHW_OVER: + SetFont( cw->win->RPort, TextsFont ); + break; + } + } + } + } + CloseLibrary(DiskfontBase); + DiskfontBase = NULL; +} + +void +kill_nhwindows( all ) + register int all; +{ + register int i; + register struct amii_WinDesc *cw; + + /* Foreach open window in all of amii_wins[], CloseShWindow, free memory */ + + for( i = 0; i < MAXWIN; ++i ) + { + if( (cw = amii_wins[ i ]) && (cw->type != NHW_BASE || all) ) + { + amii_destroy_nhwindow( i ); + } + } +} + +void +amii_cl_end( cw, curs_pos ) + register struct amii_WinDesc *cw; + register int curs_pos; +{ + register struct Window *w = cw->win; + register int oy, ox; + + if( !w ) + panic("NULL window pointer in amii_cl_end()"); + + oy = w->RPort->cp_y; + ox = w->RPort->cp_x; + + TextSpaces( w->RPort, cw->cols - curs_pos ); + + Move( w->RPort, ox, oy ); +} + +void +cursor_off( window ) + winid window; +{ + register struct amii_WinDesc *cw; + register struct Window *w; + register struct RastPort *rp; + int curx, cury; + int x, y; + long dmode; + short apen, bpen; + unsigned char ch; + + if( window == WIN_ERR || ( cw = amii_wins[window] ) == NULL ) + { + iflags.window_inited=0; + panic(winpanicstr,window, "cursor_off"); + } + + if( !(cw->wflags & FLMAP_CURSUP ) ) + return; + + w = cw->win; + + if( !w ) + return; + + cw->wflags &= ~FLMAP_CURSUP; + rp = w->RPort; + + /* Save the current information */ + curx = rp->cp_x; + cury = rp->cp_y; + x = cw->cursx; + y = cw->cursy; + dmode = rp->DrawMode; + apen = rp->FgPen; + bpen = rp->BgPen; + SetAPen( rp, cw->curs_apen ); + SetBPen( rp, cw->curs_bpen ); + SetDrMd( rp, COMPLEMENT ); +/*printf("CURSOR OFF: %d %d\n",x,y);*/ + + if( WINVERS_AMIV && cw->type == NHW_MAP) + { + cursor_common(rp, x, y); + if(Is_rogue_level(&u.uz)) + Move(rp,curx,cury); + } + else + { + ch = CURSOR_CHAR; + Move( rp, x, y ); + Text( rp, &ch, 1 ); + + /* Put back the other stuff */ + + Move( rp, curx, cury ); + } + SetDrMd( rp, dmode ); + SetAPen( rp, apen ); + SetBPen( rp, bpen ); +} + +void +cursor_on( window ) + winid window; +{ + int x, y; + register struct amii_WinDesc *cw; + register struct Window *w; + register struct RastPort *rp; + unsigned char ch; + long dmode; + short apen, bpen; + + if( window == WIN_ERR || ( cw = amii_wins[window] ) == NULL ) + { + /* tty does this differently - is this OK? */ + iflags.window_inited=0; + panic(winpanicstr,window, "cursor_on"); + } + +/*printf("CURSOR ON: %d %d\n",cw->win->RPort->cp_x, cw->win->RPort->cp_y);*/ + if( (cw->wflags & FLMAP_CURSUP ) ) + cursor_off( window ); + + w = cw->win; + + if( !w ) + return; + + cw->wflags |= FLMAP_CURSUP; + rp = w->RPort; + + /* Save the current information */ + +#ifdef DISPMAP + if( WINVERS_AMIV && cw->type == NHW_MAP && !Is_rogue_level(&u.uz)) + x = cw->cursx = (rp->cp_x & -8) + 8; + else +#endif + x = cw->cursx = rp->cp_x; + y = cw->cursy = rp->cp_y; + apen = rp->FgPen; + bpen = rp->BgPen; + dmode = rp->DrawMode; + + /* Draw in complement mode. The cursor body will be C_WHITE */ + + cw->curs_apen = 0xff; /* Last color/all planes, regardless of depth */ + cw->curs_bpen = 0xff; + SetAPen( rp, cw->curs_apen ); + SetBPen( rp, cw->curs_bpen ); + SetDrMd( rp, COMPLEMENT ); + if( WINVERS_AMIV && cw->type == NHW_MAP) + { + cursor_common(rp, x, y); + } + else + { + Move( rp, x, y ); + ch = CURSOR_CHAR; + Text( rp, &ch, 1 ); + Move( rp, x, y ); + } + + SetDrMd( rp, dmode ); + SetAPen( rp, apen ); + SetBPen( rp, bpen ); +} + +static void +cursor_common(rp, x, y) + struct RastPort *rp; + int x,y; +{ + int x1,x2,y1,y2; + + if(Is_rogue_level(&u.uz)){ + x1 = x-2; y1 = y-rp->TxHeight; + x2 = x+rp->TxWidth+1; y2 = y+3; +/*printf("COMM: (%d %d) (%d %d) (%d %d) (%d %d)\n",x1,y1,x2,y2,x1+2,y1+2,x2-2,y2-2);*/ + } else { + x1 = x; y1 = y-mysize-1; + x2 = x+mxsize-1; y2 = y-2; + RectFill(rp, x1, y1, x2, y2); + } + + RectFill(rp, x1+2, y1+2, x2-2, y2-2); +} + +void amii_suspend_nhwindows( str ) + const char *str; +{ + if( HackScreen ) + ScreenToBack( HackScreen ); +} + +void amii_resume_nhwindows() +{ + if( HackScreen ) + ScreenToFront( HackScreen ); +} + +void amii_bell() +{ + DisplayBeep( NULL ); +} + +void +removetopl(cnt) + int cnt; +{ + struct amii_WinDesc *cw=amii_wins[WIN_MESSAGE]; + /* NB - this is sufficient for + * yn_function, but that's it + */ + if(cw->curx < cnt)cw->curx=0; + else cw->curx -= cnt; + + amii_curs(WIN_MESSAGE, cw->curx+1, cw->cury); + amii_cl_end(cw, cw->curx); +} +/*#endif /* AMIGA_INTUITION */ + +#ifdef PORT_HELP +void +port_help() +{ + display_file( PORT_HELP, 1 ); +} +#endif + +/* + * print_glyph + * + * Print the glyph to the output device. Don't flush the output device. + * + * Since this is only called from show_glyph(), it is assumed that the + * position and glyph are always correct (checked there)! + */ + +void +amii_print_glyph(win,x,y,glyph) + winid win; + xchar x,y; + int glyph; +{ + struct amii_WinDesc *cw; + uchar ch; + int color, och; + extern const int zapcolors[]; + unsigned special; + + /* In order for the overview window to work, we can not clip here */ + if( !WINVERS_AMIV ) + { +#ifdef CLIPPING + /* If point not in visible part of window just skip it */ + if( clipping ) + { + if( x <= clipx || y < clipy || x >= clipxmax || y >= clipymax ) + return; + } +#endif + } + + if( win == WIN_ERR || (cw=amii_wins[win]) == NULL || cw->type != NHW_MAP) + { + panic(winpanicstr,win,"amii_print_glyph"); + } + +#if 0 +{ +static int x=-1; +if(u.uz.dlevel != x){ + fprintf(stderr,"lvlchg: %d (%d)\n",u.uz.dlevel,Is_rogue_level(&u.uz)); + x = u.uz.dlevel; +} +} +#endif + if( + WINVERS_AMIV +#ifdef REINCARNATION + && !Is_rogue_level(&u.uz) +#endif + ) + { + amii_curs(win,x,y); + amiga_print_glyph(win,0,glyph); + } + else /* AMII, or Rogue level in either version */ + { + /* map glyph to character and color */ + mapglyph(glyph, &och, &color, &special, x, y); + /* XXX next if should be ifdef REINCARNATION */ + ch = (uchar)och; + if( WINVERS_AMIV ){ /* implies Rogue level here */ + amii_curs(win,x,y); + amiga_print_glyph(win,NO_COLOR,ch + 10000); + } else { + /* Move the cursor. */ + amii_curs(win,x,y+2); + +#ifdef TEXTCOLOR + /* Turn off color if rogue level. */ +# ifdef REINCARNATION + if (Is_rogue_level(&u.uz)) + color = NO_COLOR; +# endif + + amiga_print_glyph(win,color,ch); +#else + g_putch(ch); /* print the character */ +#endif + cw->curx++; /* one character over */ + } + } +} + +/* Make sure the user sees a text string when no windowing is available */ + +void +amii_raw_print(s) + register const char *s; +{ + int argc = 0; + + if( !s ) + return; + if(amiIDisplay) + amiIDisplay->rawprint++; + + if (!Initialized) { /* Not yet screen open ... */ + puts(s); + fflush(stdout); + return; + } + + if( Initialized == 0 && WIN_BASE == WIN_ERR ) + init_nhwindows(&argc, (char **)0); + + if( amii_rawprwin != WIN_ERR ) + amii_putstr( amii_rawprwin, 0, s ); + else if( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] ) + amii_putstr( WIN_MAP, 0, s ); + else if( WIN_BASE != WIN_ERR && amii_wins[ WIN_BASE ] ) + amii_putstr( WIN_BASE, 0, s ); + else + { + puts( s); + fflush(stdout); + } +} + +/* Make sure the user sees a bold text string when no windowing + * is available + */ + +void +amii_raw_print_bold(s) + register const char *s; +{ + int argc = 0; + + if( !s ) + return; + + if(amiIDisplay) + amiIDisplay->rawprint++; + + if (!Initialized) { /* Not yet screen open ... */ + puts(s); + fflush(stdout); + return; + } + + if( Initialized == 0 && WIN_BASE == WIN_ERR ) + init_nhwindows(&argc, (char **)0); + + if( amii_rawprwin != WIN_ERR ) + amii_putstr( amii_rawprwin, 1, s ); + else if( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] ) + amii_putstr( WIN_MAP, 1, s ); + else if( WIN_BASE != WIN_ERR && amii_wins[ WIN_BASE ] ) + amii_putstr( WIN_BASE, 1, s ); + else + { + printf("\33[1m%s\33[0m\n",s); + fflush(stdout); + } +} + +/* Rebuild/update the inventory if the window is up. + */ +void +amii_update_inventory() +{ + register struct amii_WinDesc *cw; + + if( WIN_INVEN != WIN_ERR && ( cw = amii_wins[ WIN_INVEN ] ) && + cw->type == NHW_MENU && cw->win ) + { + display_inventory( NULL, FALSE ); + } +} + +/* Humm, doesn't really do anything useful */ + +void +amii_mark_synch() +{ + if(!amiIDisplay) + fflush(stderr); +/* anything else? do we need this much? */ +} + +/* Wait for everything to sync. Nothing is asynchronous, so we just + * ask for a key to be pressed. + */ +void +amii_wait_synch() +{ + if(!amiIDisplay || amiIDisplay->rawprint) + { + if(amiIDisplay) amiIDisplay->rawprint=0; + } + else + { + if( WIN_MAP != WIN_ERR ) + { + display_nhwindow(WIN_MAP,TRUE); + flush_glyph_buffer( amii_wins[ WIN_MAP ]->win ); + } + } +} + +void +amii_setclipped() +{ +#ifdef CLIPPING + clipping = TRUE; + clipx=clipy=0; + clipxmax=CO; + clipymax=LI; +/* some of this is now redundant with top of amii_cliparound XXX */ +#endif +} + +/* XXX still to do: suppress scrolling if we violate the boundary but the + * edge of the map is already displayed + */ +void +amii_cliparound(x,y) + register int x,y; +{ + extern boolean restoring; +#ifdef CLIPPING + int oldx = clipx, oldy = clipy; + int oldxmax = clipxmax, oldymax = clipymax; + int COx, LIx; +#define SCROLLCNT 1 /* Get there in 3 moves... */ + int scrollcnt = SCROLLCNT; /* ...or 1 if we changed level */ + if (!clipping) /* And 1 in anycase, cleaner, simpler, quicker */ + return; + + if(Is_rogue_level(&u.uz)){ + struct Window *w = amii_wins[WIN_MAP]->win; + struct RastPort *rp = w->RPort; + + COx = (w->Width-w->BorderLeft-w->BorderRight)/rp->TxWidth; + LIx = (w->Height-w->BorderTop-w->BorderBottom)/rp->TxHeight; + }else{ + COx = CO; + LIx = LI; + } + /* + * On a level change, move the clipping region so that for a + * reasonablely large window extra motion is avoided; for + * the rogue level hopefully this means no motion at all. + */ + { + static d_level saved_level = {127,127}; /* XXX */ + + if(!on_level(&u.uz, &saved_level)){ + scrollcnt = 1; /* jump with blanking */ + clipx=clipy=0; + clipxmax = COx; clipymax = LIx; + saved_level = u.uz; /* save as new current level */ + } + } + + if (x <= clipx + xclipbord ) { + clipx = max(0, x - (clipxmax - clipx)/2 ); + clipxmax = clipx + COx; + } + else if (x > clipxmax - xclipbord ) { + clipxmax = min(COLNO, x + (clipxmax - clipx)/2 ); + clipx = clipxmax - COx; + } + + if (y <= clipy + yclipbord ) { + clipy = max(0, y - (clipymax - clipy) / 2); + clipymax = clipy + LIx; + } + else if (y > clipymax - yclipbord ) { + clipymax = min(ROWNO, y + (clipymax - clipy) / 2); + clipy = clipymax - LIx; + } + + reclip = 1; + if (clipx != oldx || clipy != oldy || clipxmax != oldxmax || clipymax != oldymax ) + { +#ifndef NOSCROLLRASTER + struct Window *w = amii_wins[ WIN_MAP ]->win; + struct RastPort *rp = w->RPort; + int xdelta, ydelta, xmod, ymod, i; + int incx, incy, mincx, mincy; + int savex, savey, savexmax, saveymax; + int scrx, scry; + + if(Is_rogue_level(&u.uz)){ + scrx = rp->TxWidth; + scry = rp->TxHeight; + } else { + scrx = mxsize; + scry = mysize; + } + + /* Ask that the glyph routines not draw the overview window */ + reclip = 2; + cursor_off( WIN_MAP ); + + /* Compute how far we are moving in terms of tiles */ + mincx = clipx - oldx ; + mincy = clipy - oldy ; + + /* How many tiles to get there in SCROLLCNT moves */ + incx = ( clipx - oldx )/scrollcnt; + incy = ( clipy - oldy )/scrollcnt; + + /* If less than SCROLLCNT tiles, then move by 1 tile if moving at all */ + if( incx == 0 ) incx = (mincx != 0); + if( incy == 0 ) incy = (mincy != 0); + + /* Get count of pixels to move each iteration and final pixel count */ + xdelta = ((clipx-oldx )*scrx) / scrollcnt; + xmod = ((clipx-oldx )*scrx) % scrollcnt; + ydelta = ((clipy-oldy )*scry) / scrollcnt; + ymod = ((clipy-oldy )*scry) % scrollcnt; + + /* Preserve the final move location */ + savex = clipx; + savey = clipy; + saveymax = clipymax; + savexmax = clipxmax; + + /* + * Set clipping rectangle to be just the region that will be exposed so + * that drawing will be faster + */ +#if 0 /* Doesn't seem to work quite the way it should */ + /* In some cases hero is 'centered' offscreen */ + if( xdelta < 0 ) + { + clipx = oldx; + clipxmax = clipx + incx; + } + else if( xdelta > 0 ) + { + clipxmax = oldxmax; + clipx = clipxmax - incx; + } + else + { + clipx = oldx; + clipxmax = oldxmax; + } + + if( ydelta < 0 ) + { + clipy = oldy; + clipymax = clipy + incy; + } + else if( ydelta > 0 ) + { + clipymax = oldymax; + clipy = clipymax - incy; + } + else + { + clipy = oldy; + clipymax = oldymax; + } +#endif + /* Now, in scrollcnt moves, move the picture toward the final view */ + for( i = 0; i < scrollcnt; ++i ) + { +#ifdef DISPMAP + if( i == scrollcnt - 1 && (xmod != 0 || ymod != 0) && + (xdelta != 0 || ydelta != 0) ) + { + incx += (clipx - oldx)%scrollcnt; + incy += (clipy - oldy)%scrollcnt; + xdelta += xmod; + ydelta += ymod; + } +#endif + /* Scroll the raster if we are scrolling */ + if( xdelta != 0 || ydelta != 0 ) + { + ScrollRaster( rp, xdelta, ydelta, + w->BorderLeft, w->BorderTop, + w->Width - w->BorderRight - 1, + w->Height - w->BorderBottom - 1 ); + + if( mincx == 0 ) incx = 0; + else mincx -= incx; + + clipx += incx; + clipxmax += incx; + + if( mincy == 0 ) incy = 0; + else mincy -= incy; + + clipy += incy; + clipymax += incy; + + /* Draw the exposed portion */ + if (on_level(&u.uz0, &u.uz) && !restoring) + (void) doredraw(); + flush_glyph_buffer( amii_wins[ WIN_MAP ]->win ); + } + } + + clipx = savex; + clipy = savey; + clipymax = saveymax; + clipxmax = savexmax; +#endif + if (on_level(&u.uz0, &u.uz) && !restoring && moves > 1) + (void) doredraw(); + flush_glyph_buffer( amii_wins[ WIN_MAP ]->win ); + } + reclip = 0; +#endif +} + +void +flushIDCMP( port ) + struct MsgPort *port; +{ + struct Message *msg; + while( msg = GetMsg( port ) ) + ReplyMsg( msg ); +} diff --git a/sys/amiga/winkey.c b/sys/amiga/winkey.c new file mode 100644 index 0000000..7f79864 --- /dev/null +++ b/sys/amiga/winkey.c @@ -0,0 +1,106 @@ +/* SCCS Id: @(#)winkey.c 3.1 93/04/02 */ +/* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "NH:sys/amiga/windefs.h" +#include "NH:sys/amiga/winext.h" +#include "NH:sys/amiga/winproto.h" + +amii_nh_poskey(x, y, mod) + int*x, *y, *mod; +{ + struct amii_WinDesc *cw; + WETYPE type; + struct RastPort *rp; + struct Window *w; + + if( cw = amii_wins[WIN_MESSAGE] ) + { + cw->wflags &= ~FLMAP_SKIP; + if( scrollmsg ) + cw->wflags |= FLMSG_FIRST; + cw->disprows = 0; + } + + if( WIN_MAP != WIN_ERR && (cw = amii_wins[ WIN_MAP ]) && ( w = cw->win ) ) + { + cursor_on( WIN_MAP ); + } + else + panic( "no MAP window opened for nh_poskey\n" ); + + rp = w->RPort; + + while( 1 ) + { + type = WindowGetevent( ); + if( type == WEMOUSE ) + { + *mod = CLICK_1; + if( lastevent.un.mouse.qual ) + *mod = 0; + + /* X coordinates are 1 based, Y are 1 based. */ + *x = ( (lastevent.un.mouse.x - w->BorderLeft) / mxsize ) + 1; + *y = ( ( lastevent.un.mouse.y - w->BorderTop - MAPFTBASELN ) / + mysize ) + 1; +#ifdef CLIPPING + if( clipping ) + { + *x += clipx; + *y += clipy; + } +#endif + return( 0 ); + } + else if( type == WEKEY ) + { + lastevent.type = WEUNK; + return( lastevent.un.key ); + } + } +} + +int +amii_nhgetch() +{ + int ch; + struct amii_WinDesc *cw=amii_wins[WIN_MESSAGE]; + + if( WIN_MAP != WIN_ERR && amii_wins[ WIN_MAP ] ) + { + cursor_on( WIN_MAP ); + } + if(cw) + cw->wflags &= ~FLMAP_SKIP; + + ch = WindowGetchar(); + return( ch ); +} + +void +amii_get_nh_event() +{ + /* nothing now - later I have no idea. Is this just a Mac hook? */ +} + +void +amii_getret() +{ + register int c; + + raw_print( "" ); + raw_print( "Press Return..." ); + + c = 0; + + while( c != '\n' && c != '\r' ) + { + if( HackPort ) + c = WindowGetchar(); + else + c = getchar(); + } + return; +} + diff --git a/sys/amiga/winmenu.c b/sys/amiga/winmenu.c new file mode 100644 index 0000000..b2cf1cf --- /dev/null +++ b/sys/amiga/winmenu.c @@ -0,0 +1,1597 @@ +/* SCCS Id: @(#)winmenu.c 3.2 96/02/17 */ +/* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993,1996. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "NH:sys/amiga/windefs.h" +#include "NH:sys/amiga/winext.h" +#include "NH:sys/amiga/winproto.h" + +/* Start building the text for a menu */ +void +amii_start_menu(window) + register winid window; +{ + register int i; + register struct amii_WinDesc *cw; + register amii_menu_item *mip; + + if(window == WIN_ERR || (cw = amii_wins[window]) == NULL || cw->type != NHW_MENU) + panic(winpanicstr,window, "start_menu"); + + amii_clear_nhwindow(window); + + if( cw->data && ( cw->type == NHW_MESSAGE || + cw->type == NHW_MENU || cw->type == NHW_TEXT ) ) + { + for( i = 0; i < cw->maxrow; ++i ) + { + if( cw->data[ i ] ) + free( cw->data[ i ] ); + } + free( cw->data ); + cw->data = NULL; + } + + for( mip = cw->menu.items, i = 0; (mip = cw->menu.items) && i < cw->menu.count; ++i ) + { + cw->menu.items = mip->next; + free( mip ); + } + + cw->menu.items = 0; + cw->menu.count = 0; + cw->menu.chr = 'a'; + + if( cw->morestr ) free( cw->morestr ); + cw->morestr = NULL; + + if( window == WIN_INVEN && cw->win != NULL ) + { + if( alwaysinvent ) + cw->wasup = 1; + } + cw->cury = cw->rows = cw->maxrow = cw->maxcol = 0; + return; +} + +/* Add a string to a menu */ +void +amii_add_menu(window,glyph, id, ch, gch, attr, str, preselected) + register winid window; + register int glyph; + register const anything *id; + register char ch; + register char gch; + register int attr; + register const char *str; + register BOOLEAN_P preselected; +{ + register struct amii_WinDesc *cw; + amii_menu_item *mip; + char buf[ 4+BUFSZ ]; + + if(str == NULL)return; + + if(window == WIN_ERR || (cw = amii_wins[window]) == NULL || cw->type != NHW_MENU) + panic(winpanicstr,window, "add_menu"); + + mip = (amii_menu_item *)alloc( sizeof( *mip ) ); + mip->identifier = *id; + mip->selected = preselected; + mip->attr = attr; + mip->glyph = Is_rogue_level(&u.uz) ? NO_GLYPH : glyph; + mip->selector = 0; + mip->gselector = gch; + mip->count = -1; + + if (id->a_void && !ch && cw->menu.chr != 0) + { + ch = cw->menu.chr++; + if( ch == 'z' ) + cw->menu.chr = 'A'; + if( ch == 'Z' ) + cw->menu.chr = 0; + } + + mip->canselect = ( id->a_void != 0 ); + + if( id->a_void && ch != '\0') + { + Sprintf( buf, "%c - %s", ch, str ); + str = buf; + mip->canselect = 1; + } + + mip->selector = ch; + + amii_putstr( window, attr, str ); + + mip->str = cw->data[ cw->cury - 1 ]; + cw->menu.count++; + + mip->next = NULL; + + if( cw->menu.items == 0 ) + cw->menu.last = cw->menu.items = mip; + else + { + cw->menu.last->next = mip; + cw->menu.last = mip; + } +} + +/* Done building a menu. */ + +void +amii_end_menu(window,morestr) + register winid window; + register const char *morestr; +{ + register struct amii_WinDesc *cw; + + if(window == WIN_ERR || (cw=amii_wins[window]) == NULL + || cw->type != NHW_MENU ) + panic(winpanicstr,window, "end_menu"); + + if( morestr && *morestr ) + { + anything any; +#define PROMPTFIRST /* Define this to have prompt first */ +#ifdef PROMPTFIRST + amii_menu_item *mip; + int i; + char *t; + mip = cw->menu.last; +#endif + any.a_void = 0; + amii_add_menu( window, NO_GLYPH, &any, 0, 0, ATR_NONE, morestr, + MENU_UNSELECTED); +#ifdef PROMPTFIRST /* Do some shuffling. Last first, push others one forward */ + mip->next = NULL; + cw->menu.last->next = cw->menu.items; + cw->menu.items = cw->menu.last; + cw->menu.last = mip; + t = cw->data[cw->cury-1]; + for (i=cw->cury-1; i>0; i--) { + cw->data[i] = cw->data[i-1]; + } + cw->data[0] = t; +#endif + } + + /* If prompt first, don't put same string in title where in most cases + it's not entirely visible anyway */ +#ifndef PROMPTFIRST + if( morestr ) + cw->morestr = strdup( morestr ); +#endif +} + +/* Select something from the menu. */ + +int +amii_select_menu(window, how, mip ) + register winid window; + register int how; + register menu_item **mip; +{ + int cnt; + register struct amii_WinDesc *cw; + + if( window == WIN_ERR || ( cw=amii_wins[window] ) == NULL || + cw->type != NHW_MENU ) + panic(winpanicstr,window, "select_menu"); + + cnt = DoMenuScroll( window, 1, how, mip ); + + /* This would allow the inventory window to stay open. */ + if( !alwaysinvent || window != WIN_INVEN ) + dismiss_nhwindow(window); /* Now tear it down */ + return cnt; +} + +amii_menu_item * +find_menu_item( register struct amii_WinDesc *cw, int idx ) +{ + amii_menu_item *mip; + for( mip = cw->menu.items; idx > 0 && mip; mip = mip->next ) + --idx; + + return( mip ); +} + +int +make_menu_items( register struct amii_WinDesc *cw, register menu_item **rmip ) +{ + register int idx = 0; + register amii_menu_item *mip; + register menu_item *mmip; + + for( mip = cw->menu.items; mip; mip = mip->next ) + { + if( mip->selected ) + ++idx; + } + + if( idx ) + { + mmip = *rmip = (menu_item *)alloc( idx * sizeof( *mip ) ); + for( mip = cw->menu.items; mip; mip = mip->next ) + { + if( mip->selected ) + { + mmip->item = mip->identifier; + mmip->count = mip->count; + mmip++; + } + } + + cw->mi = *rmip; + } + return( idx ); +} + +int +DoMenuScroll( win, blocking, how, retmip ) + int win, blocking, how; + menu_item **retmip; +{ + amii_menu_item *amip; + register struct Window *w; + register struct NewWindow *nw; + struct PropInfo *pip; + register struct amii_WinDesc *cw; + struct IntuiMessage *imsg; + struct Gadget *gd; + register int wheight, xsize, ysize, aredone = 0; + register int txwd, txh; + long mics, secs, class, code; + long oldmics = 0, oldsecs = 0; + int aidx, oidx, topidx, hidden; + int totalvis; + SHORT mx, my; + static char title[ 100 ]; + int dosize = 1; + struct Screen *scrn = HackScreen; + int x1,x2,y1,y2; + long counting = FALSE, count = 0, reset_counting = FALSE; + char countString[32]; + + if( win == WIN_ERR || ( cw = amii_wins[ win ] ) == NULL ) + panic(winpanicstr,win,"DoMenuScroll"); + + /* Initial guess at window sizing values */ + txwd = txwidth; + if( WINVERS_AMIV ) + { + if( win == WIN_INVEN ) + txh = max( txheight, pictdata.ysize + 3 ); /* interline space */ + else + txh = txheight; /* interline space */ + } + else + txh = txheight; /* interline space */ + + /* Check to see if we should open the window, should need to for + * TEXT and MENU but not MESSAGE. + */ + + w = cw->win; + topidx = 0; + + if( w == NULL ) + { + +#ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + { + PropScroll.Flags |= PROPNEWLOOK; + } +#endif + nw = (void *)DupNewWindow( (void *)(&new_wins[ cw->type ].newwin) ); + if( !alwaysinvent || win != WIN_INVEN ) + { + xsize = scrn->WBorLeft + scrn->WBorRight + MenuScroll.Width + 1 + + (txwd * cw->maxcol); + if( WINVERS_AMIV ) + { + if( win == WIN_INVEN ) + xsize += pictdata.xsize + 4; + } + if( xsize > amiIDisplay->xpix ) + xsize = amiIDisplay->xpix; + + /* If next row not off window, use it, else use the bottom */ + + ysize = ( txh * cw->maxrow ) + /* The text space */ + HackScreen->WBorTop + txheight + 1 + /* Top border */ + HackScreen->WBorBottom + 3; /* The bottom border */ + if( ysize > amiIDisplay->ypix ) + ysize = amiIDisplay->ypix; + + /* Adjust the size of the menu scroll gadget */ + + nw->TopEdge = 0; + if( cw->type == NHW_TEXT && ysize < amiIDisplay->ypix ) + nw->TopEdge += ( amiIDisplay->ypix - ysize ) / 2; + nw->LeftEdge = amiIDisplay->xpix - xsize; + if( cw->type == NHW_MENU ) + { + if( nw->LeftEdge > 10 ) + nw->LeftEdge -= 10; + else + nw->LeftEdge = 0; + if( amiIDisplay->ypix - nw->Height > 10 ) + nw->TopEdge += 10; + else + nw->TopEdge = amiIDisplay->ypix - nw->Height - 1; + } + if( cw->type == NHW_TEXT && xsize < amiIDisplay->xpix ) + nw->LeftEdge -= ( amiIDisplay->xpix - xsize ) / 2; + } + else if( win == WIN_INVEN ) + { + struct Window *mw = amii_wins[ WIN_MAP ]->win; + struct Window *sw = amii_wins[ WIN_STATUS ]->win; + + xsize = scrn->WBorLeft + scrn->WBorRight + MenuScroll.Width + 1 + + (txwd * cw->maxcol); + + /* Make space for the glyph to appear at the left of the description */ + if( WINVERS_AMIV ) + xsize += pictdata.xsize + 4; + + if( xsize > amiIDisplay->xpix ) + xsize = amiIDisplay->xpix; + + /* If next row not off window, use it, else use the bottom */ + + ysize = sw->TopEdge - (mw->TopEdge + mw->Height) - 1; + if( ysize > amiIDisplay->ypix ) + ysize = amiIDisplay->ypix; + + /* Adjust the size of the menu scroll gadget */ + + nw->TopEdge = mw->TopEdge + mw->Height; + nw->LeftEdge = 0; + } + cw->newwin = (void *)nw; + if( nw == NULL ) + panic("No NewWindow Allocated" ); + + nw->Screen = HackScreen; + + if( win == WIN_INVEN ) + { + sprintf( title, "%s the %s's Inventory", plname, pl_character ); + nw->Title = title; + if( lastinvent.MaxX != 0 ) + { + nw->LeftEdge = lastinvent.MinX; + nw->TopEdge = lastinvent.MinY; + nw->Width = lastinvent.MaxX; + nw->Height = lastinvent.MaxY; + } + } + else if( cw->morestr ) + nw->Title = cw->morestr; + + /* Adjust the window coordinates and size now that we know + * how many items are to be displayed. + */ + + if( ( xsize > amiIDisplay->xpix - nw->LeftEdge ) && + ( xsize < amiIDisplay->xpix ) ) + { + nw->LeftEdge = amiIDisplay->xpix - xsize; + nw->Width = xsize; + } + else + { + nw->Width = min( xsize, amiIDisplay->xpix - nw->LeftEdge ); + } + nw->Height = min( ysize, amiIDisplay->ypix - nw->TopEdge ); + + if( WINVERS_AMIV || WINVERS_AMII ) + { + /* Make sure we are using the correct hook structure */ + nw->Extension = cw->wintags; + } + + /* Now, open the window */ + w = cw->win = OpenShWindow( (void *)nw ); + + if( w == NULL ) + { + char buf[ 130 ]; + + sprintf( buf, "No Window Opened For Menu (%d,%d,%d-%d,%d-%d)", + nw->LeftEdge, nw->TopEdge, nw->Width, amiIDisplay->xpix, + nw->Height, amiIDisplay->ypix ); + panic( buf ); + } + +#ifdef HACKFONT + if( TextsFont ) + SetFont(w->RPort, TextsFont ); + else if( HackFont ) + SetFont(w->RPort, HackFont ); +#endif + txwd = w->RPort->TxWidth; + if( WINVERS_AMIV ) + { + if( win == WIN_INVEN ) + txh = max( w->RPort->TxHeight, pictdata.ysize + 3 ); /* interline space */ + else + txh = w->RPort->TxHeight; /* interline space */ + } + else + txh = w->RPort->TxHeight; /* interline space */ + + /* subtract 2 to account for spacing away from border (1 on each side) */ + wheight = ( w->Height - w->BorderTop - w->BorderBottom - 2 ) / txh; + if( WINVERS_AMIV ) + { + if( win == WIN_INVEN ) + { + cw->cols = ( w->Width - w->BorderLeft - + w->BorderRight - 4 - pictdata.xsize - 3 ) / txwd; + } + else + { + cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd; + } + } + else + { + cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd; + } + totalvis = CountLines( win ); + } + else + { + txwd = w->RPort->TxWidth; + if( WINVERS_AMIV ) + { + if( win == WIN_INVEN ) + txh = max( w->RPort->TxHeight, pictdata.ysize + 3 ); /* interline space */ + else + txh = w->RPort->TxHeight; /* interline space */ + } + else + { + txh = w->RPort->TxHeight; /* interline space */ + } + + /* subtract 2 to account for spacing away from border (1 on each side) */ + wheight = ( w->Height - w->BorderTop - w->BorderBottom - 2 ) / txh; + if( WINVERS_AMIV ) + { + if( win == WIN_INVEN ) + { + cw->cols = ( w->Width - w->BorderLeft - + w->BorderRight - 4 - pictdata.xsize - 3) / txwd; + } + else + cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd; + } + else + { + cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd; + } + + totalvis = CountLines( win ); + + for( gd = w->FirstGadget; gd && gd->GadgetID != 1; ) + gd = gd->NextGadget; + + if( gd ) + { + pip = (struct PropInfo *)gd->SpecialInfo; + hidden = max( totalvis - wheight, 0 ); + topidx = (((ULONG)hidden * pip->VertPot) + (MAXPOT/2)) >> 16; + } + } + + for( gd = w->FirstGadget; gd && gd->GadgetID != 1; ) + gd = gd->NextGadget; + + if( !gd ) panic("Can't find scroll gadget" ); + + morc = 0; + oidx = -1; + +#if 0 + /* Make sure there are no selections left over from last time. */ +/* XXX potential problem for preselection if this is really needed */ + for( amip = cw->menu.items; amip; amip = amip->next ) + amip->selected = 0; +#endif + + DisplayData( win, topidx ); + + /* Make the prop gadget the right size and place */ + + SetPropInfo( w, gd, wheight, totalvis, topidx ); + oldsecs = oldmics = 0; + + /* If window already up, don't stop to process events */ + if( cw->wasup ) + { + aredone = 1; + cw->wasup = 0; + } + + while( !aredone ) + { + /* Process window messages */ + + WaitPort( w->UserPort ); + while( imsg = (struct IntuiMessage * ) GetMsg( w->UserPort ) ) + { + class = imsg->Class; + code = imsg->Code; + mics = imsg->Micros; + secs = imsg->Seconds; + gd = (struct Gadget *) imsg->IAddress; + mx = imsg->MouseX; + my = imsg->MouseY; + + /* Only do our window or VANILLAKEY from other windows */ + + if( imsg->IDCMPWindow != w && class != VANILLAKEY && + class != RAWKEY ) + { + ReplyMsg( (struct Message *) imsg ); + continue; + } + + /* Do DeadKeyConvert() stuff if RAWKEY... */ + if( class == RAWKEY ) + { + class = VANILLAKEY; + code = ConvertKey( imsg ); + } + ReplyMsg( (struct Message *) imsg ); + + switch( class ) + { + case NEWSIZE: + + /* + * Ignore every other newsize, no action needed, + * except RefreshWindowFrame() in case borders got overwritten + * for some reason. It should not happen, but ... + */ + + if( !dosize ) + { + RefreshWindowFrame(w); + dosize = 1; + break; + } + + if( win == WIN_INVEN ) + { + lastinvent.MinX = w->LeftEdge; + lastinvent.MinY = w->TopEdge; + lastinvent.MaxX = w->Width; + lastinvent.MaxY = w->Height; + } + else if( win == WIN_MESSAGE ) + { + lastmsg.MinX = w->LeftEdge; + lastmsg.MinY = w->TopEdge; + lastmsg.MaxX = w->Width; + lastmsg.MaxY = w->Height; + } + + /* Find the gadget */ + + for( gd = w->FirstGadget; gd && gd->GadgetID != 1; ) + gd = gd->NextGadget; + + if( !gd ) + panic("Can't find scroll gadget" ); + + totalvis = CountLines( win ); + wheight = ( w->Height - w->BorderTop - + w->BorderBottom - 2) / txh; + if( WINVERS_AMIV ) + { + if( win == WIN_INVEN ) + { + cw->cols = ( w->Width - w->BorderLeft - + w->BorderRight - 4 - pictdata.xsize - 3) / txwd; + } + else + cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd; + } + else + { + cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd; + } + + if( wheight < 2 ) + wheight = 2; + + /* + * Clear the right side & bottom. Parts of letters are not erased by + * amii_cl_end if window shrinks and columns decrease. + */ + + if ( WINVERS_AMII || WINVERS_AMIV ) { + amii_setfillpens(w, cw->type); + SetDrMd(w->RPort, JAM2); + x2 = w->Width - w->BorderRight; + y2 = w->Height - w->BorderBottom; + x1 = x2 - w->IFont->tf_XSize - w->IFont->tf_XSize; + y1 = w->BorderTop; + if (x1 < w->BorderLeft) + x1 = w->BorderLeft; + RectFill(w->RPort, x1, y1, x2, y2); + x1 = w->BorderLeft; + y1 = y1 - w->IFont->tf_YSize; + RectFill(w->RPort, x1, y1, x2, y2); + RefreshWindowFrame(w); + } + + /* Make the prop gadget the right size and place */ + + DisplayData( win, topidx ); + SetPropInfo( w, gd, wheight, totalvis, topidx ); + + /* Force the window to a text line boundary <= to + * what the user dragged it to. This eliminates + * having to clean things up on the bottom edge. + */ + + SizeWindow( w, 0, ( wheight * txh) + + w->BorderTop + w->BorderBottom + 2 - w->Height ); + + /* Don't do next NEWSIZE, we caused it */ + dosize = 0; + oldsecs = oldmics = 0; + break; + + case VANILLAKEY: +#define CTRL(x) ((x)-'@') + morc = code = map_menu_cmd(code); + if (code == MENU_SELECT_ALL) { + if (how == PICK_ANY) { + amip = cw->menu.items; + while (amip) { + if (amip->canselect && amip->selector) { + /* + * Select those yet unselected + * and apply count if necessary + */ + if (!amip->selected) { + amip->selected = TRUE; + if (counting) { + amip->count = count; + reset_counting = TRUE; + /* + * This makes the assumption that + * the string is in format "X - foo" + * with additional selecting and formatting + * data in front (size SOFF) + */ + amip->str[SOFF+2] = '#'; + } else { + amip->count = -1; + amip->str[SOFF+2] = '-'; + } + } + } + amip=amip->next; + } + DisplayData(win, topidx); + } + } else if (code == MENU_UNSELECT_ALL) { + if (how == PICK_ANY) { + amip = cw->menu.items; + while (amip) { + if (amip->selected) { + amip->selected = FALSE; + amip->count = -1; + amip->str[SOFF+2] = '-'; + } + amip=amip->next; + } + DisplayData(win, topidx); + } + } else if (code == MENU_INVERT_ALL) { + if (how == PICK_ANY) { + amip = cw->menu.items; + while (amip) { + if (amip->canselect && amip->selector) { + amip->selected = !amip->selected; + if (counting && amip->selected) { + amip->count = count; + amip->str[SOFF+2] = '#'; + reset_counting = TRUE; + } else { + amip->count = -1; + amip->str[SOFF+2] = '-'; + } + } + amip=amip->next; + } + DisplayData(win, topidx); + } + } else if (code == MENU_SELECT_PAGE) { + if (how == PICK_ANY) { + int i = 0; + amip = cw->menu.items; + while (amip && i++ < topidx) + amip = amip->next; + for (i=0;i < wheight && amip; i++, amip=amip->next) { + if (amip->canselect && amip->selector) { + if (!amip->selected) { + if (counting) { + amip->count = count; + reset_counting = TRUE; + amip->str[SOFF+2] = '#'; + } else { + amip->count = -1; + amip->str[SOFF+2] = '-'; + } + } + amip->selected = TRUE; + } + } + DisplayData(win, topidx); + } + } else if (code == MENU_UNSELECT_PAGE) { + if (how == PICK_ANY) { + int i = 0; + amip = cw->menu.items; + while (amip && i++ < topidx) + amip = amip->next; + for (i=0;i < wheight && amip; i++, amip=amip->next) { + if (amip->selected) { + amip->selected = FALSE; + amip->count = -1; + amip->str[SOFF+2] = '-'; + } + } + DisplayData(win, topidx); + } + } else if (code == MENU_INVERT_PAGE) { + if (how == PICK_ANY) { + int i = 0; + amip = cw->menu.items; + while (amip && i++ < topidx) + amip = amip->next; + for (i=0;i < wheight && amip; i++, amip=amip->next) { + if (amip->canselect && amip->selector) { + amip->selected = !amip->selected; + if (counting && amip->selected) { + amip->count = count; + amip->str[SOFF+2] = '#'; + reset_counting = TRUE; + } else { + amip->count = -1; + amip->str[SOFF+2] = '-'; + } + } + } + DisplayData(win, topidx); + } + } else if (code == MENU_SEARCH && cw->type == NHW_MENU) { + if (how == PICK_ONE || how == PICK_ANY) { + char buf[BUFSZ]; + amip = cw->menu.items; + amii_getlin("Search for:", buf); + if (!*buf || *buf == '\033') + break; + while (amip) { + if (amip->canselect && amip->selector && amip->str && + strstri(&amip->str[SOFF], buf)) { + if (how == PICK_ONE) { + amip->selected = TRUE; + aredone = 1; + break; + } + amip->selected = !amip->selected; + if (counting && amip->selected) { + amip->count = count; + reset_counting = TRUE; + amip->str[SOFF+2] = '#'; + } else { + amip->count = -1; + reset_counting = TRUE; + amip->str[SOFF+2] = '-'; + } + } + amip = amip->next; + } + } + DisplayData(win, topidx); + } else if (how == PICK_ANY && isdigit(code) && + (counting || (!counting && code !='0'))) { + if (count < LARGEST_INT) { + count = count*10 + (long)(code-'0'); + if (count > LARGEST_INT) + count = LARGEST_INT; + if (count > 0) { + counting = TRUE; + reset_counting = FALSE; + } else { + reset_counting = TRUE; + } + sprintf(countString, "Count: %d", count); + pline(countString); + } + } else if( code == CTRL('D') || code == CTRL('U') || + code == MENU_NEXT_PAGE || code == MENU_PREVIOUS_PAGE || + code == MENU_FIRST_PAGE || code == MENU_LAST_PAGE ) + { + int endcnt, i; + + for( gd = w->FirstGadget; gd && gd->GadgetID != 1; ) + gd = gd->NextGadget; + + if( !gd ) + panic("Can't find scroll gadget" ); + + endcnt = wheight; /* /2; */ + if( endcnt == 0 ) + endcnt = 1; + + if (code == MENU_FIRST_PAGE) { + topidx = 0; + } else if (code == MENU_LAST_PAGE) { + topidx = cw->maxrow - wheight; + } else for( i = 0; i < endcnt; ++i ) + { + if (code == CTRL('D') || code == MENU_NEXT_PAGE) + { + if( topidx + wheight < cw->maxrow ) + ++topidx; + else + break; + } + else if (code = CTRL('U') || code == MENU_PREVIOUS_PAGE) + { + if( topidx > 0 ) + --topidx; + else + break; + } + } + /* Make prop gadget the right size and place */ + + DisplayData( win, topidx ); + SetPropInfo( w,gd, wheight, totalvis, topidx ); + oldsecs = oldmics = 0; + } + else if( code == '\b' ) + { + for( gd = w->FirstGadget; gd && gd->GadgetID != 1; ) + gd = gd->NextGadget; + + if( !gd ) + panic("Can't find scroll gadget" ); + + if( topidx - wheight - 2 < 0 ) + { + topidx = 0; + } + else + { + topidx -= wheight - 2; + } + DisplayData( win, topidx ); + SetPropInfo( w, gd, wheight, totalvis, topidx ); + oldsecs = oldmics = 0; + } + else if( code == ' ' ) + { + for( gd = w->FirstGadget; gd && gd->GadgetID != 1; ) + gd = gd->NextGadget; + + if( !gd ) + panic("Can't find scroll gadget" ); + + if( topidx + wheight >= cw->maxrow ) + { + morc = 0; + aredone = 1; + } + else + { + /* If there are still lines to be seen */ + + if( cw->maxrow > topidx + wheight ) + { + if( wheight > 2 ) + topidx += wheight - 2; + else + ++topidx; + DisplayData( win, topidx ); + SetPropInfo( w, gd, wheight, + totalvis, topidx ); + } + oldsecs = oldmics = 0; + } + } + else if( code == '\n' || code == '\r' ) + { + for( gd = w->FirstGadget; gd && gd->GadgetID != 1; ) + gd = gd->NextGadget; + + if( !gd ) + panic("Can't find scroll gadget" ); + + /* If all line displayed, we are done */ + + if( topidx + wheight >= cw->maxrow ) + { + morc = 0; + aredone = 1; + } + else + { + /* If there are still lines to be seen */ + + if( cw->maxrow > topidx + 1 ) + { + ++topidx; + DisplayData( win, topidx ); + SetPropInfo( w, gd, wheight, + totalvis, topidx ); + } + oldsecs = oldmics = 0; + } + } + else if( code == '\33' ) + { + if (counting) { + reset_counting = TRUE; + } else { + aredone = 1; + } + } + else + { + int selected = FALSE; + for( amip = cw->menu.items; amip; amip = amip->next ) + { + if( amip->selector == code ) + { + if( how == PICK_ONE ) + aredone = 1; + amip->selected = !amip->selected; + if (counting && amip->selected) { + amip->count = count; + reset_counting = TRUE; + amip->str[SOFF+2] = '#'; + } else { + amip->count = -1; + reset_counting = TRUE; + amip->str[SOFF+2] = '-'; + } + selected = TRUE; + } else if (amip->gselector == code ) + { + amip->selected = !amip->selected; + if (counting) { + amip->count = count; + reset_counting = TRUE; + amip->str[SOFF+2] = '#'; + } else { + amip->count = -1; + reset_counting = TRUE; + amip->str[SOFF+2] = '-'; + } + selected = TRUE; + } + } + if (selected) + DisplayData( win, topidx ); + } + break; + + case CLOSEWINDOW: + if( win == WIN_INVEN ) + { + lastinvent.MinX = w->LeftEdge; + lastinvent.MinY = w->TopEdge; + lastinvent.MaxX = w->Width; + lastinvent.MaxY = w->Height; + } + else if( win == WIN_MESSAGE ) + { + lastmsg.MinX = w->LeftEdge; + lastmsg.MinY = w->TopEdge; + lastmsg.MaxX = w->Width; + lastmsg.MaxY = w->Height; + } + aredone = 1; + morc = '\33'; + break; + + case GADGETUP: + if( win == WIN_MESSAGE ) + aredone = 1; + for( gd = w->FirstGadget; gd && gd->GadgetID != 1; ) + gd = gd->NextGadget; + + pip = (struct PropInfo *)gd->SpecialInfo; + totalvis = CountLines( win ); + hidden = max( totalvis - wheight, 0 ); + aidx = (((ULONG)hidden * pip->VertPot) + (MAXPOT/2)) >> 16; + if( aidx != topidx ) + DisplayData( win, topidx = aidx ); + break; + + case MOUSEMOVE: + for( gd = w->FirstGadget; gd && gd->GadgetID != 1; ) + gd = gd->NextGadget; + + pip = (struct PropInfo *)gd->SpecialInfo; + totalvis = CountLines( win ); + hidden = max( totalvis - wheight, 0 ); + aidx = (((ULONG)hidden * pip->VertPot) + (MAXPOT/2)) >> 16; + if( aidx != topidx ) + DisplayData( win, topidx = aidx ); + break; + + case INACTIVEWINDOW: + if( win == WIN_MESSAGE || ( win == WIN_INVEN && alwaysinvent ) ) + aredone = 1; + break; + + case MOUSEBUTTONS: + if( ( code == SELECTUP || code == SELECTDOWN ) && + cw->type == NHW_MENU && how != PICK_NONE ) + { + /* Which one is the mouse pointing at? */ + + aidx = ( ( my - w->BorderTop - 1 ) / txh ) + topidx; + + /* If different lines, don't select double click */ + + if( aidx != oidx ) + { + oldsecs = 0; + oldmics = 0; + } + + /* If releasing, check for double click */ + + if( code == SELECTUP ) + { + amip = find_menu_item( cw, aidx ); + if( aidx == oidx ) + { + if( DoubleClick( oldsecs, + oldmics, secs, mics ) ) + { + aredone = 1; + } + oldsecs = secs; + oldmics = mics; + } + else + { + amip = find_menu_item( cw, oidx ); + amip->selected = 0; + amip->count = -1; + reset_counting = TRUE; + if (amip->canselect && amip->selector) + amip->str[SOFF+2] = '-'; + } + if (counting && amip->selected && amip->canselect && amip->selector) { + amip->count = count; + reset_counting = TRUE; + amip->str[SOFF+2] = '#'; + } + DisplayData( win, topidx ); + } + else if( aidx - topidx < wheight && + aidx < cw->maxrow && code == SELECTDOWN ) + { + /* Remove old highlighting if visible */ + + amip = find_menu_item( cw, oidx ); + if( amip && oidx != aidx && + ( oidx > topidx && oidx - topidx < wheight ) ) + { + if( how != PICK_ANY ) { + amip->selected = 0; + amip->count = -1; + reset_counting = TRUE; + if (amip->canselect && amip->selector) + amip->str[SOFF+2] = '-'; + } + oidx = -1; + } + amip = find_menu_item( cw, aidx ); + + if( amip && amip->canselect && amip->selector && how != PICK_NONE ) + { + oidx = aidx; + if( !DoubleClick( oldsecs, + oldmics, secs, mics ) ) + { + amip->selected = !amip->selected; + if (counting && amip->selected) { + amip->count = count; + reset_counting = TRUE; + amip->str[SOFF+2] = '#'; + } else { + amip->count = -1; + reset_counting = TRUE; + if (amip->canselect && amip->selector) + amip->str[SOFF+2] = '-'; + } + } + } + else + { + DisplayBeep( NULL ); + oldsecs = 0; + oldmics = 0; + } + DisplayData( win, topidx ); + } + } + else + { + DisplayBeep( NULL ); + } + break; + } + if (!counting && morc == '\33') { + amip = cw->menu.items; + while (amip) { + if (amip->canselect && amip->selector) { + amip->selected = FALSE; + amip->count = -1; + amip->str[SOFF+2] = '-'; + } + amip=amip->next; + } + } + if (reset_counting) { + count = 0; + if (counting) + pline("Count: 0"); + counting = FALSE; + } + } + } + /* Force a cursor reposition before next message output */ + if( win == WIN_MESSAGE ) + cw->curx = -1; + return( make_menu_items( cw, retmip ) ); +} + +void +ReDisplayData( win ) + winid win; +{ + int totalvis; + register struct amii_WinDesc *cw; + register struct Window *w; + register struct Gadget *gd; + unsigned long hidden, aidx, wheight; + struct PropInfo *pip; + + if( win == WIN_ERR || !(cw = amii_wins[win]) || !( w = cw->win ) ) + return; + + for( gd = w->FirstGadget; gd && gd->GadgetID != 1; ) + gd = gd->NextGadget; + + if( !gd ) + return; + + wheight = (w->Height - w->BorderTop - w->BorderBottom-2)/w->RPort->TxHeight; + + pip = (struct PropInfo *)gd->SpecialInfo; + totalvis = CountLines( win ); + hidden = max( totalvis - wheight, 0 ); + aidx = (((ULONG)hidden * pip->VertPot) + (MAXPOT/2)) >> 16; + clear_nhwindow( win ); + DisplayData( win, aidx ); +} + +long +FindLine( win, line ) + winid win; + int line; +{ + int txwd; + register char *t; + register struct amii_WinDesc *cw; + register struct Window *w; + register int i, disprow, len; + int col = -1; + + if( win == WIN_ERR || !(cw = amii_wins[win]) || !( w = cw->win ) ) + { + panic( winpanicstr, win, "No Window in FindLine" ); + } + txwd = w->RPort->TxWidth; + if( WINVERS_AMIV ) + { + if( win == WIN_INVEN ) + { + cw->cols = ( w->Width - w->BorderLeft - + w->BorderRight - 4 - pictdata.xsize - 3) / txwd; + } + else + cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd; + } + else + { + cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd; + } + + disprow = 0; + for( col = i = 0; line > disprow && i < cw->maxrow; ++i ) + { + t = cw->data[ i ] + SOFF; + if( cw->data[i][1] >= 0 ) + { + ++disprow; + col = 0; + } + + while( *t ) + { + len = strlen( t ); + if( col + len > cw->cols ) + len = cw->cols - col; + while( len > 0 ) + { + if( !t[len] || t[len] == ' ' ) + break; + --len; + } + if( len == 0 ) { + while ( *t && *t != ' ') { + t++; col++; + } + } else { + t += len; + col += len; + } + if( *t ) + { + while( *t == ' ' ) + ++t; + col = 0; + ++disprow; + } + } + } + return( i ); +} + +long +CountLines( win ) + winid win; +{ + int txwd; + amii_menu_item *mip; + register char *t; + register struct amii_WinDesc *cw; + register struct Window *w; + register int i, disprow, len; + int col = -1; + + if( win == WIN_ERR || !(cw = amii_wins[win]) || !( w = cw->win ) ) + { + panic( winpanicstr, win, "No Window in CountLines" ); + } + + txwd = w->RPort->TxWidth; + if( WINVERS_AMIV ) + { + if( win == WIN_INVEN ) + { + cw->cols = ( w->Width - w->BorderLeft - + w->BorderRight - 4 - pictdata.xsize - 3) / txwd; + } + else + cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd; + } + else + { + cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd; + } + + disprow = cw->maxrow; + mip = cw->menu.items; + for( col = i = 0; i < cw->maxrow; ++i ) + { + t = cw->data[ i ] + SOFF; + if( cw->type == NHW_MESSAGE && cw->data[ i ][ SEL_ITEM ] < 0 ) + --disprow; + else + col = 0; + while( *t ) + { + len = strlen( t ); + if( col + len > cw->cols ) + len = cw->cols - col; + while( len > 0 ) + { + if( !t[len] || t[len] == ' ' ) + break; + --len; + } + if( len == 0 ) { + while ( *t && *t != ' ') { + t++; col++; + } + } else { + t += len; + col += len; + } + if( *t ) + { + while( *t == ' ' ) + ++t; + col = 0; + ++disprow; + } + } + } + return( disprow ); +} + +void +DisplayData( win, start ) + winid win; + int start; +{ + int txwd; + amii_menu_item *mip; + register char *t; + register struct amii_WinDesc *cw; + register struct Window *w; + register struct RastPort *rp; + register int i, disprow, len, wheight; + int whichcolor = -1; + int col; + + if( win == WIN_ERR || !(cw = amii_wins[win]) || !( w = cw->win ) ) + { + panic( winpanicstr, win, "No Window in DisplayData" ); + } + + rp = w->RPort; + SetDrMd( rp, JAM2 ); + if( WINVERS_AMIV && win == WIN_INVEN ) + { + wheight = ( w->Height - w->BorderTop - w->BorderBottom - 2 ) / + max( rp->TxHeight, pictdata.ysize + 3 ); + } + else + { + wheight = ( w->Height - w->BorderTop - w->BorderBottom - 2 ) / + rp->TxHeight; + } + + cw->rows = wheight; + txwd = rp->TxWidth; + if( WINVERS_AMIV ) + { + if( win == WIN_INVEN ) + { + cw->cols = ( w->Width - w->BorderLeft - + w->BorderRight - 4 - pictdata.xsize - 3) / txwd; + } + else + cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd; + } + else + { + cw->cols = ( w->Width - w->BorderLeft - w->BorderRight - 4 ) / txwd; + } + + /* Get the real line to display at */ + start = FindLine( win, start ); + + mip = cw->menu.items; + for( i = 0; mip && i < start; ++i ) + { + mip = mip->next; + } + + /* Skip any initial response to a previous line */ + if( cw->type == NHW_MESSAGE && mip && mip->selected < 0 ) + ++start; + if( WINVERS_AMIV && cw->type == NHW_MESSAGE ) + SetAPen( rp, amii_msgAPen ); + + for( disprow = i = start; disprow < wheight + start; i++ ) + { + /* Just erase unused lines in the window */ + if( i >= cw->maxrow ) + { + if (WINVERS_AMIV && win == WIN_INVEN) { + amii_curs( win, 0, disprow - start ); + amiga_print_glyph( win, 0, NO_GLYPH); + } + amii_curs( win, 1, disprow - start ); + amii_cl_end( cw, 0 ); + ++disprow; + continue; + } + + /* Any string with a highlighted attribute goes + * onto the end of the current line in the message window. + */ + if( cw->type == NHW_MESSAGE ) + SetAPen( rp, cw->data[ i ][ SEL_ITEM ] < 0 ? C_RED : amii_msgAPen ); + + /* Selected text in the message window goes onto the end of the current line */ + if( cw->type != NHW_MESSAGE || cw->data[ i ][ SEL_ITEM ] >= 0 ) + { + amii_curs( win, 1, disprow - start ); + if( WINVERS_AMIV && win == WIN_INVEN ) + { + if( mip ) + amiga_print_glyph( win, 0, mip->glyph ); + amii_curs( win, 1, disprow - start ); + } + col = 0; + } + + /* If this entry is to be highlighted, do so */ + if( mip && mip->selected != 0 ) + { + if( whichcolor != 1 ) + { + SetDrMd( rp, JAM2 ); + if( WINVERS_AMIV ) + { + SetAPen( rp, amii_menuBPen ); + SetBPen( rp, C_BLUE ); + } + else + { + SetAPen( rp, C_BLUE ); + SetBPen( rp, amii_menuAPen ); + } + whichcolor = 1; + } + } + else if( whichcolor != 2 ) + { + SetDrMd( rp, JAM2 ); + if( cw->type == NHW_MESSAGE ) + { + SetAPen( rp, amii_msgAPen ); + SetBPen( rp, amii_msgBPen ); + } + else if( cw->type == NHW_MENU ) + { + SetAPen( rp, amii_menuAPen ); + SetBPen( rp, amii_menuBPen ); + } + else if( cw->type == NHW_TEXT ) + { + SetAPen( rp, amii_textAPen ); + SetBPen( rp, amii_textBPen ); + } + whichcolor = 2; + } + + /* Next line out, wrap if too long */ + + t = cw->data[ i ] + SOFF; + ++disprow; + col = 0; + while( *t ) + { + len = strlen( t ); + if( len > (cw->cols - col) ) + len = cw->cols - col; + while( len > 0 ) + { + if( !t[len] || t[len] == ' ' ) + break; + --len; + } + if( len == 0 ) { + Text( rp, t, cw->cols - col ); + while ( *t && *t != ' ') { + t++; col++; + } + } else { + Text( rp, t, len ); + t += len; + col += len; + } + amii_cl_end( cw, col ); + if( *t ) + { + ++disprow; + /* Stop at the bottom of the window */ + if( disprow > wheight + start ) + break; + while( *t == ' ' ) + ++t; + amii_curs( win, 1, disprow - start - 1 ); + if( mip && win == WIN_INVEN && WINVERS_AMIV ) + { + /* Erase any previous glyph drawn here. */ + amiga_print_glyph( win, 0, NO_GLYPH ); + amii_curs( win, 1, disprow - start - 1 ); + } + Text( rp, "+", 1 ); + col = 1; + } + } + + if( cw->type == NHW_MESSAGE ) + { + SetAPen( rp, amii_msgBPen ); + SetBPen( rp, amii_msgBPen ); + } + else if( cw->type == NHW_MENU ) + { + SetAPen( rp, amii_menuBPen ); + SetBPen( rp, amii_menuBPen ); + } + else if( cw->type == NHW_TEXT ) + { + SetAPen( rp, amii_textBPen ); + SetBPen( rp, amii_textBPen ); + } + amii_cl_end( cw, col ); + whichcolor = -1; + if( mip ) mip = mip->next; + } + RefreshWindowFrame(w); + return; +} + +void SetPropInfo( win, gad, vis, total, top ) + register struct Window *win; + register struct Gadget *gad; + register long vis, total, top; +{ + long mflags; + register long hidden; + register int body, pot; + + hidden = max( total-vis, 0 ); + + /* Force the last section to be just to the bottom */ + + if( top > hidden ) + top = hidden; + + /* Scale the body position. */ + /* 2 lines overlap */ + + if( hidden > 0 && total > 2) + body = (ULONG) ((vis - 2) * MAXBODY) / (total - 2); + else + body = MAXBODY; + + if( hidden > 0 ) + pot = (ULONG) (top * MAXPOT) / hidden; + else + pot = 0; + + mflags = AUTOKNOB|FREEVERT; +#ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + { + mflags |= PROPNEWLOOK; + } +#endif + + NewModifyProp( gad, win, NULL, + mflags, 0, pot, MAXBODY, body, 1 ); +} diff --git a/sys/amiga/winproto.h b/sys/amiga/winproto.h new file mode 100644 index 0000000..d0106a0 --- /dev/null +++ b/sys/amiga/winproto.h @@ -0,0 +1,151 @@ +/* SCCS Id: @(#)winproto.h 3.2 96/01/15 */ +/* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993. */ +/* NetHack may be freely redistributed. See license for details. */ + +/* winreq.c */ +void EditColor ( void ); +void EditClipping( void ); +void DrawCol ( struct Window *w , int idx , UWORD *colors ); +void DispCol ( struct Window *w , int idx , UWORD *colors ); +void amii_change_color( int, long, int ); +char *amii_get_color_string( ); +void amii_getlin ( const char *prompt , char *bufp ); +void getlind ( const char *prompt , char *bufp , const char *dflt ); +char *amii_get_color_string( void ); +int filecopy( char *from, char *to ); +char *basename( char *str ); +char *dirname( char *str ); + +/* winstr.c */ +void amii_putstr ( winid window , int attr , const char *str ); +void outmore ( struct amii_WinDesc *cw ); +void outsubstr ( struct amii_WinDesc *cw , char *str , int len, int fudge ); +void amii_putsym ( winid st , int i , int y , CHAR_P c ); +void amii_addtopl ( const char *s ); +void TextSpaces ( struct RastPort *rp , int nr ); +void amii_remember_topl ( void ); +long CountLines( winid ); +long FindLine( winid, int ); +int amii_doprev_message ( void ); +void flushIDCMP( struct MsgPort * ); +int amii_msgborder( struct Window * ); +void amii_scrollmsg( register struct Window *w, register struct amii_WinDesc *cw ); + +/* winkey.c */ +int amii_nh_poskey ( int *x , int *y , int *mod ); +int amii_nhgetch ( void ); +void amii_get_nh_event ( void ); +void amii_getret ( void ); + +/* winmenu.c */ +void amii_start_menu ( winid window ); +void FDECL(amii_add_menu, (winid,int,const anything *,CHAR_P,CHAR_P,int,const char *,BOOLEAN_P)); +void FDECL(amii_end_menu, (winid, const char *)); +int FDECL(amii_select_menu, (winid, int, menu_item **)); +int DoMenuScroll ( int win , int blocking, int how, menu_item ** ); +void ReDisplayData ( winid win ); +void DisplayData ( winid win , int start ); +void SetPropInfo ( struct Window *win , struct Gadget *gad , long vis , long total , long top ); + +/* amiwind.c */ +struct Window *OpenShWindow ( struct NewWindow *nw ); +void CloseShWindow ( struct Window *win ); +int ConvertKey ( struct IntuiMessage *message ); +int kbhit ( void ); +int kbhit ( void ); +int amikbhit ( void ); +int WindowGetchar ( void ); +WETYPE WindowGetevent ( void ); +void amii_cleanup ( void ); +#ifndef SHAREDLIB +void Abort ( long rc ); +#endif +void CleanUp ( void ); +void flush_glyph_buffer ( struct Window *w ); +void amiga_print_glyph ( winid window , int color_index , int glyph ); +void start_glyphout ( winid window ); +void amii_end_glyphout ( winid window ); +struct NewWindow *DupNewWindow ( struct NewWindow *win ); +void FreeNewWindow ( struct NewWindow *win ); +void bell ( void ); +void amii_delay_output ( void ); +void amii_number_pad ( int state ); +#ifndef SHAREDLIB +void amiv_loadlib ( void ); +void amii_loadlib ( void ); +#endif +void preserve_icon( void ); +void clear_icon( void ); + +/* winfuncs.c */ +void amii_destroy_nhwindow ( winid win ); +int amii_create_nhwindow ( int type ); +void amii_init_nhwindows ( int *, char ** ); +void amii_setdrawpens( struct Window *, int type ); +void amii_sethipens( struct Window *, int type, int attr ); +void amii_setfillpens( struct Window *, int type ); +void amii_clear_nhwindow ( winid win ); +void dismiss_nhwindow ( winid win ); +void amii_exit_nhwindows ( const char *str ); +void amii_display_nhwindow ( winid win , boolean blocking ); +void amii_curs ( winid window , int x , int y ); +void kill_nhwindows ( int all ); +void amii_cl_end ( struct amii_WinDesc *cw , int i ); +void cursor_off ( winid window ); +void cursor_on ( winid window ); +void amii_suspend_nhwindows ( const char *str ); +void amii_resume_nhwindows ( void ); +void amii_bell ( void ); +void removetopl ( int cnt ); +void port_help ( void ); +void amii_print_glyph ( winid win , xchar x , xchar y , int glyph ); +void amii_raw_print ( const char *s ); +void amii_raw_print_bold ( const char *s ); +void amii_update_inventory ( void ); +void amii_mark_synch ( void ); +void amii_wait_synch ( void ); +void amii_setclipped ( void ); +void amii_cliparound ( int x , int y ); +void amii_set_text_font( char *font, int size ); +BitMapHeader ReadImageFiles( char **, struct BitMap **, char ** ); +BitMapHeader ReadTileImageFiles(void); +void FreeImageFiles( char **, struct BitMap ** ); +void FreeTileImageFiles(); + +/* winami.c */ +#ifdef SHAREDLIB +int __UserLibInit ( void ); +void __UserLibCleanup ( void ); +#endif +void amii_askname ( void ); +void amii_player_selection ( void ); +void RandomWindow ( char *name ); +int amii_get_ext_cmd ( void ); +char amii_yn_function ( const char *prompt , const char *resp , char def ); +char amii_yn_function ( const char *query , const char *resp , char def ); +void amii_display_file ( const char *fn , boolean complain ); +void SetBorder ( struct Gadget *gd ); +void *malloc ( register unsigned size ); +void free ( void *q ); + +#ifdef SHAREDLIB +/* amilib.c */ +void amii_loadlib ( void ); +void amiv_loadlib ( void ); +void CleanUp ( void ); +void setup_librefs ( WinamiBASE *base ); +#else +void Abort ( long rc ); +#endif + +/* amirip.c */ +void FDECL(amii_outrip, ( winid tmpwin, int how )); + +/* winchar.c */ +void SetMazeType(MazeType); +int GlyphToIcon(int glyph); +#ifdef OPT_DISPMAP +void dispmap_sanity(void); +int dispmap_sanity1(int); +#endif +void FreeTileImageFiles(void); diff --git a/sys/amiga/winreq.c b/sys/amiga/winreq.c new file mode 100644 index 0000000..fac7ee6 --- /dev/null +++ b/sys/amiga/winreq.c @@ -0,0 +1,1177 @@ +/* SCCS Id: @(#)winreq.c 3.1 93/04/02 */ +/* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "NH:sys/amiga/windefs.h" +#include "NH:sys/amiga/winext.h" +#include "NH:sys/amiga/winproto.h" + +#define GADBLUEPEN 2 +#define GADREDPEN 3 +#define GADGREENPEN 4 +#define GADCOLOKAY 5 +#define GADCOLCANCEL 6 +#define GADCOLSAVE 7 + +UBYTE UNDOBUFFER[300]; +SHORT BorderVectors1[] = { 0,0, 57,0, 57,11, 0,11, 0,0 }; +struct Border Border1 = { -1,-1, 3,0,JAM1, 5, BorderVectors1, NULL }; +struct IntuiText IText1 = { 3,0,JAM1, 4,1, NULL, (UBYTE *)"Cancel", NULL }; +struct Gadget Gadget2 = { + NULL, 9,15, 56,10, NULL, RELVERIFY, BOOLGADGET, (APTR)&Border1, + NULL, &IText1, NULL, NULL, 1, NULL +}; +UBYTE StrStringSIBuff[300]; +struct StringInfo StrStringSInfo = { + StrStringSIBuff, UNDOBUFFER, 0, 300, 0, 0,0,0,0,0, 0, 0, NULL +}; +SHORT BorderVectors2[] = { 0,0, 439,0, 439,11, 0,11, 0,0 }; +struct Border Border2 = { -1,-1, 3,0,JAM1, 5, BorderVectors2, NULL }; +struct Gadget String = { + &Gadget2, 77,15, 438,10, NULL, RELVERIFY+STRINGCENTER, STRGADGET, + (APTR)&Border2, NULL, NULL, NULL, (APTR)&StrStringSInfo, 2, NULL +}; + +#define StrString \ + ((char *)(((struct StringInfo *)(String.SpecialInfo))->Buffer)) + +struct NewWindow StrWindow = { + 57,74, 526,31, 0,1, GADGETUP+CLOSEWINDOW+ACTIVEWINDOW+VANILLAKEY, + WINDOWDRAG+WINDOWDEPTH+WINDOWCLOSE+ACTIVATE+NOCAREREFRESH, + &String, NULL, NULL, NULL, NULL, 5,5, 0xffff,0xffff, CUSTOMSCREEN +}; + +#include "NH:sys/amiga/colorwin.c" + +#define XSIZE 2 +#define YSIZE 3 +#define XCLIP 4 +#define YCLIP 5 +#define GADOKAY 6 +#define GADCANCEL 7 + +#include "NH:sys/amiga/clipwin.c" + +void ClearCol( struct Window *w ); + +void +EditColor( ) +{ + extern const char *configfile; + int i, done = 0, okay = 0; + long code, qual, class; + register struct Gadget *gd, *dgad; + register struct Window *nw; + register struct IntuiMessage *imsg; + register struct PropInfo *pip; + register struct Screen *scrn; + long aidx; + int msx, msy; + int curcol = 0, drag = 0; + int bxorx, bxory, bxxlen, bxylen; + static UWORD colors[ AMII_MAXCOLORS ]; + static UWORD svcolors[ AMII_MAXCOLORS ]; + static int once = 0; + scrn = HackScreen; + + if( !once ) + { + if( WINVERS_AMIV ) + { + Col_NewWindowStructure1.Width += 300; + Col_NewWindowStructure1.Height += 20; + Col_NewWindowStructure1.LeftEdge -= 150; + Col_BluePen.Width += 300; + Col_RedPen.Width += 300; + Col_GreenPen.Width += 300; + Col_Cancel.LeftEdge += 300; + Col_Okay.LeftEdge += 150; + Col_Cancel.TopEdge += 20; + Col_Save.TopEdge += 20; + Col_Okay.TopEdge += 20; + } + SetBorder( &Col_Okay ); + SetBorder( &Col_Cancel ); + SetBorder( &Col_Save ); + once = 1; + } + + bxylen = Col_NewWindowStructure1.Height - + ( Col_BluePen.TopEdge + Col_BluePen.Height + 6 ); + bxxlen = Col_BluePen.Width; + bxorx = Col_BluePen.LeftEdge; + bxory = Col_BluePen.TopEdge + Col_BluePen.Height + 2; + + /* Save the current colors */ + for( i = 0; i < amii_numcolors; ++i ) + svcolors[ i ] = colors[ i ] = GetRGB4( scrn->ViewPort.ColorMap, i ); + + Col_NewWindowStructure1.Screen = scrn; +#ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + { + ((struct PropInfo *)Col_BluePen.SpecialInfo)->Flags |= PROPNEWLOOK; + ((struct PropInfo *)Col_RedPen.SpecialInfo)->Flags |= PROPNEWLOOK; + ((struct PropInfo *)Col_GreenPen.SpecialInfo)->Flags |= PROPNEWLOOK; + } +#endif + if( WINVERS_AMIV || WINVERS_AMII ) + { +#ifdef INTUI_NEW_LOOK + Col_NewWindowStructure1.Extension = wintags; + Col_NewWindowStructure1.Flags |= WFLG_NW_EXTENDED; +# ifdef __GNUC__ + fillhook.h_Entry = (void *)&LayerFillHook; +# else + fillhook.h_Entry = (ULONG(*)())LayerFillHook; +# endif + fillhook.h_Data = (void *)-2; + fillhook.h_SubEntry = 0; +#endif + } + + nw = OpenWindow( (void *)&Col_NewWindowStructure1 ); + + if( nw == NULL ) + { + DisplayBeep( NULL ); + return; + } + + PrintIText( nw->RPort, &Col_IntuiTextList1, 0, 0 ); + + ClearCol( nw ); + DrawCol( nw, curcol, colors ); + while( !done ) + { + WaitPort( nw->UserPort ); + + while( imsg = (struct IntuiMessage * )GetMsg( nw->UserPort ) ) + { + gd = (struct Gadget *)imsg->IAddress; + code = imsg->Code; + class = imsg->Class; + qual = imsg->Qualifier; + msx = imsg->MouseX; + msy = imsg->MouseY; + + ReplyMsg( (struct Message *)imsg ); + + switch( class ) + { + case VANILLAKEY: + if( code == 'v' && qual == AMIGALEFT ) + okay = done = 1; + else if( code == 'b' && qual == AMIGALEFT ) + okay = 0, done = 1; + else if( code == 'o' || code == 'O' ) + okay = done = 1; + else if( code == 'c' || code == 'C' ) + okay = 0, done = 1; + break; + + case CLOSEWINDOW: + done = 1; + break; + + case GADGETUP: + drag = 0; + if( gd->GadgetID == GADREDPEN || + gd->GadgetID == GADBLUEPEN || + gd->GadgetID == GADGREENPEN ) + { + pip = (struct PropInfo *)gd->SpecialInfo; + aidx = pip->HorizPot / (MAXPOT/15); + if( gd->GadgetID == GADREDPEN ) + { + colors[ curcol ] = + ( colors[ curcol ] & ~0xf00 ) | (aidx << 8); + LoadRGB4( &scrn->ViewPort, colors, amii_numcolors ); + } + else if( gd->GadgetID == GADBLUEPEN ) + { + colors[ curcol ] = + ( colors[ curcol ] & ~0xf ) | aidx; + LoadRGB4( &scrn->ViewPort, colors, amii_numcolors ); + } + else if( gd->GadgetID == GADGREENPEN ) + { + colors[ curcol ] = ( colors[ curcol ] & ~0x0f0 ) | (aidx << 4); + LoadRGB4( &scrn->ViewPort, colors, amii_numcolors ); + } + DispCol( nw, curcol, colors ); + } + else if( gd->GadgetID == GADCOLOKAY ) + { + done = 1; + okay = 1; + } + else if( gd->GadgetID == GADCOLSAVE ) + { + FILE *fp, *nfp; + char buf[ 300 ], nname[ 300 ], oname[ 300 ]; + int once = 0; + + fp = fopen( configfile, "r" ); + if( !fp ) + { + pline( "can't find NetHack.cnf" ); + break; + } + + strcpy( oname, dirname( (char *)configfile ) ); + if( oname[ strlen(oname)-1 ] != ':' ) + { + sprintf( nname, "%s/New_NetHack.cnf", oname ); + strcat( oname, "/" ); + strcat( oname, "Old_NetHack.cnf" ); + } + else + { + sprintf( nname, "%sNew_NetHack.cnf", oname ); + strcat( oname, "Old_NetHack.cnf" ); + } + + nfp = fopen( nname, "w" ); + if( !nfp ) + { + pline( "can't write to New_NetHack.cnf" ); + fclose( fp ); + break; + } + while( fgets( buf, sizeof( buf ), fp ) ) + { + if( strncmp( buf, "PENS=", 5 ) == 0 ) + { + once = 1; + fputs( "PENS=", nfp ); + for( i = 0; i < amii_numcolors; ++i ) + { + fprintf( nfp, "%03x", colors[i] ); + if(( i + 1 ) < amii_numcolors) + putc( '/', nfp ); + } + putc( '\n', nfp ); + } + else + { + fputs( buf, nfp ); + } + } + + /* If none in the file yet, now write it */ + if( !once ) + { + fputs( "PENS=", nfp ); + for( i = 0; i < amii_numcolors; ++i ) + { + fprintf( nfp, "%03x", colors[i] ); + if(( i + 1 ) < amii_numcolors) + putc( ',', nfp ); + } + putc( '\n', nfp ); + } + fclose( fp ); + fclose( nfp ); + unlink( oname ); + if( filecopy( (char *)configfile, oname ) == 0 ) + if( filecopy( nname, (char *)configfile ) == 0 ) + unlink( nname ); + done = 1; + okay = 1; + } + else if( gd->GadgetID == GADCOLCANCEL ) + { + done = 1; + okay = 0; + } + break; + + case GADGETDOWN: + drag = 1; + dgad = gd; + break; + + case MOUSEMOVE: + if( !drag ) + break; + pip = (struct PropInfo *)dgad->SpecialInfo; + aidx = pip->HorizPot / (MAXPOT/15); + if( dgad->GadgetID == GADREDPEN ) + { + colors[ curcol ] = + ( colors[ curcol ] & ~0xf00 ) | (aidx << 8); + LoadRGB4( &scrn->ViewPort, colors, amii_numcolors ); + } + else if( dgad->GadgetID == GADBLUEPEN ) + { + colors[ curcol ] = ( colors[ curcol ] & ~0xf ) | aidx; + LoadRGB4( &scrn->ViewPort, colors, amii_numcolors ); + } + else if( dgad->GadgetID == GADGREENPEN ) + { + colors[ curcol ] = + ( colors[ curcol ] & ~0x0f0 ) | (aidx << 4); + LoadRGB4( &scrn->ViewPort, colors, amii_numcolors ); + } + DispCol( nw, curcol, colors ); + break; + + case MOUSEBUTTONS: + if( code == SELECTDOWN ) + { + if( msy > bxory && msy < bxory + bxylen - 1 && + msx > bxorx && msx < bxorx + bxxlen - 1 ) + { + curcol = ( msx - bxorx )/(bxxlen / amii_numcolors); + if( curcol >= 0 && curcol < amii_numcolors ) + DrawCol( nw, curcol, colors ); + } + } + break; + } + } + } + + if( okay ) + { + for( i = 0; i < ( amii_numcolors ); ++i ) + flags.amii_curmap[ i ] = colors[ i ]; + LoadRGB4( &scrn->ViewPort, flags.amii_curmap, amii_numcolors ); + } + else + LoadRGB4( &scrn->ViewPort, svcolors, amii_numcolors ); + CloseWindow( nw ); +} + +void +ShowClipValues( struct Window *nw ) +{ + char buf[ 50 ]; + struct Gadget *gd; + + SetAPen( nw->RPort, 5 ); + SetBPen( nw->RPort, amii_otherBPen ); + SetDrMd( nw->RPort, JAM2 ); + + sprintf( buf, "%d ", mxsize ); + gd = &ClipXSIZE; + Move( nw->RPort, gd->LeftEdge + (nw->Width + gd->Width) + 8, + gd->TopEdge + nw->RPort->TxBaseline ); + Text( nw->RPort, buf, strlen( buf ) ); + + sprintf( buf, "%d ", mysize ); + gd = &ClipYSIZE; + Move( nw->RPort, gd->LeftEdge + (nw->Width + gd->Width) + 8, + gd->TopEdge + nw->RPort->TxBaseline ); + Text( nw->RPort, buf, strlen( buf ) ); + + sprintf( buf, "%d ", xclipbord ); + gd = &ClipXCLIP; + Move( nw->RPort, gd->LeftEdge + (nw->Width + gd->Width) + 8, + gd->TopEdge + nw->RPort->TxBaseline ); + Text( nw->RPort, buf, strlen( buf ) ); + + sprintf( buf, "%d ", yclipbord ); + gd = &ClipYCLIP; + Move( nw->RPort, gd->LeftEdge + (nw->Width + gd->Width) + 8, + gd->TopEdge + nw->RPort->TxBaseline ); + Text( nw->RPort, buf, strlen( buf ) ); +} + +void +EditClipping( void ) +{ + int i; + long mflags; + static int sizes[] = { 8, 16, 20, 24, 28, 32, 36 }; + char buf[ 40 ]; + int done = 0, okay = 0; + long code, qual, class; + register struct Gadget *gd, *dgad; + register struct Window *nw; + register struct IntuiMessage *imsg; + register struct PropInfo *pip; + register struct Screen *scrn; + long aidx; + int lmxsize = mxsize, lmysize = mysize; + int lxclipbord = xclipbord, lyclipbord = yclipbord; + int msx, msy; + int drag = 0; + static int once = 0; + + scrn = HackScreen; + + if( !once ) + { + SetBorder( &ClipOkay ); + SetBorder( &ClipCancel ); + once = 1; + } + ClipNewWindowStructure1.Screen = scrn; +#ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + { + ((struct PropInfo *)ClipXSIZE.SpecialInfo)->Flags |= PROPNEWLOOK; + ((struct PropInfo *)ClipYSIZE.SpecialInfo)->Flags |= PROPNEWLOOK; + ((struct PropInfo *)ClipXCLIP.SpecialInfo)->Flags |= PROPNEWLOOK; + ((struct PropInfo *)ClipYCLIP.SpecialInfo)->Flags |= PROPNEWLOOK; + } +#endif + if( WINVERS_AMIV || WINVERS_AMII ) + { +# ifdef INTUI_NEW_LOOK + ClipNewWindowStructure1.Extension = wintags; + ClipNewWindowStructure1.Flags |= WFLG_NW_EXTENDED; +# ifdef __GNUC__ + fillhook.h_Entry = (void *)&LayerFillHook; +# else + fillhook.h_Entry = (ULONG(*)())LayerFillHook; +# endif + fillhook.h_Data = (void *)-2; + fillhook.h_SubEntry = 0; +# endif + } + + nw = OpenWindow( (void *)&ClipNewWindowStructure1 ); + + if( nw == NULL ) + { + DisplayBeep( NULL ); + return; + } + + ShowClipValues( nw ); + mflags = AUTOKNOB|FREEHORIZ; +#ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + { + mflags |= PROPNEWLOOK; + } +#endif + + for( i = 0; i < 7; ++i ) + { + if( mxsize <= sizes[ i ] ) + break; + } + NewModifyProp( &ClipXSIZE, nw, NULL, mflags, (i * MAXPOT ) / 6, 0, + MAXPOT/6, 0, 1 ); + for( i = 0; i < 7; ++i ) + { + if( mysize <= sizes[ i ] ) + break; + } + NewModifyProp( &ClipYSIZE, nw, NULL, mflags, (i * MAXPOT ) / 6, 0, + MAXPOT/6, 0, 1 ); + + NewModifyProp( &ClipXCLIP, nw, NULL, mflags, ((xclipbord-2) * MAXPOT ) / 6, 0, + MAXPOT/6, 0, 1 ); + NewModifyProp( &ClipYCLIP, nw, NULL, mflags, ((yclipbord-2) * MAXPOT ) / 6, 0, + MAXPOT/6, 0, 1 ); + + while( !done ) + { + WaitPort( nw->UserPort ); + + while( imsg = (struct IntuiMessage * )GetMsg( nw->UserPort ) ) + { + gd = (struct Gadget *)imsg->IAddress; + code = imsg->Code; + class = imsg->Class; + qual = imsg->Qualifier; + msx = imsg->MouseX; + msy = imsg->MouseY; + + ReplyMsg( (struct Message *)imsg ); + + switch( class ) + { + case VANILLAKEY: + if( code == '\33' ) + okay = 0, done = 1; + else if( code == 'v' && qual == AMIGALEFT ) + okay = done = 1; + else if( code == 'b' && qual == AMIGALEFT ) + okay = 0, done = 1; + else if( code == 'o' || code == 'O' ) + okay = done = 1; + else if( code == 'c' || code == 'C' ) + okay = 0, done = 1; + break; + + case CLOSEWINDOW: + done = 1; + break; + + case GADGETUP: + drag = 0; + if( gd->GadgetID == XSIZE || gd->GadgetID == YSIZE || + gd->GadgetID == XCLIP || gd->GadgetID == YCLIP ) + { + pip = (struct PropInfo *)gd->SpecialInfo; + aidx = pip->HorizPot / (MAXPOT/6); + if( gd->GadgetID == XSIZE ) + { + mxsize = sizes[ aidx ]; + } + else if( gd->GadgetID == YSIZE ) + { + mysize = sizes[ aidx ]; + } + else if( gd->GadgetID == XCLIP ) + { + xclipbord = aidx + 2; + } + else if( gd->GadgetID == YCLIP ) + { + yclipbord = aidx + 2; + } + ShowClipValues( nw ); +#ifdef OPT_DISPMAP + dispmap_sanity(); +#endif + } + else if( gd->GadgetID == GADOKAY ) + { + done = 1; + okay = 1; + } + else if( gd->GadgetID == GADCANCEL ) + { + done = 1; + okay = 0; + } + ReportMouse( 0, nw ); + reclip = 2; + doredraw(); + flush_glyph_buffer( amii_wins[ WIN_MAP ]->win ); + reclip = 0; + break; + + case GADGETDOWN: + drag = 1; + dgad = gd; + ReportMouse( 1, nw ); + break; + + case MOUSEMOVE: + if( !drag ) + break; + pip = (struct PropInfo *)dgad->SpecialInfo; + aidx = pip->HorizPot / (MAXPOT/6); + Move( nw->RPort, dgad->LeftEdge + (nw->Width + dgad->Width) + 8, + dgad->TopEdge + nw->RPort->TxBaseline ); + if( dgad->GadgetID == XSIZE ) + { + mxsize = sizes[ aidx ]; + sprintf( buf, "%d ",lmxsize ); + } + else if( dgad->GadgetID == YSIZE ) + { + mysize = sizes[ aidx ]; + sprintf( buf, "%d ", mysize ); + } + else if( dgad->GadgetID == XCLIP ) + { + xclipbord = aidx + 2; + sprintf( buf, "%d ", xclipbord ); + } + else if( dgad->GadgetID == YCLIP ) + { + yclipbord = aidx + 2; + sprintf( buf, "%d ", yclipbord ); + } + SetAPen( nw->RPort, 5 ); + SetBPen( nw->RPort, amii_otherBPen ); + SetDrMd( nw->RPort, JAM2 ); + Text( nw->RPort, buf, strlen( buf ) ); +#ifdef OPT_DISPMAP + dispmap_sanity(); +#endif + break; + } + } + } + + CloseWindow( nw ); + + /* Restore oldvalues if cancelled. */ + if( !okay ) + { + mxsize = lmxsize; + mysize = lmysize; + xclipbord = lxclipbord; + yclipbord = lyclipbord; + } +} + +char *dirname( str ) + char *str; +{ + char *t, c; + static char dir[ 300 ]; + + t = strrchr( str, '/' ); + if( !t ) + t = strrchr( str, ':' ); + if( !t ) + t = str; + else + { + c = *t; + *t = 0; + strcpy( dir, str ); + *t = c; + } + return( dir ); +} + +char *basename( str ) + char *str; +{ + char *t; + + t = strrchr( str, '/' ); + if( !t ) + t = strrchr( str, ':' ); + if( !t ) + t = str; + else + ++t; + return( t ); +} + +filecopy( from, to ) + char *from, *to; +{ + char *buf; + int i = 0; + + buf = (char *)alloc( strlen(to) + strlen(from) + 20 ); + if( buf ) + { + sprintf( buf, "c:copy \"%s\" \"%s\" clone", from, to ); + + /* Check SysBase instead? Shouldn't matter */ +#ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + i = System( buf, NULL ); + else +#endif + Execute( buf, NULL, NULL ); + free( buf ); + } + else + { + return( -1 ); + } + return( i ); +} + +/* The colornames, and the default values for the pens */ +static struct COLDEF +{ + char *name, *defval; +}; +struct COLDEF amii_colnames[ AMII_MAXCOLORS ] = +{ + "Black","(000)", + "White","(fff)", + "Brown","(830)", + "Cyan","(7ac)", + "Green","(181)", + "Magenta","(c06)", + "Blue","(23e)", + "Red","(c00)", +}; + +struct COLDEF amiv_colnames[ AMII_MAXCOLORS ] = +{ + "Black","(000)", + "White","(fff)", + "Cyan","(0bf)", + "Orange","(f60)", + "Blue","(00f)", + "Green","(090)", + "Grey","(69b)", + "Red","(f00)", + "Light Green","(6f0)", + "Yellow","(ff0)", + "Magenta","(f0f)", + "Brown","(940)", + "Grey Blue","(466)", + "Light Brown","(c40)", + "Light Grey","(ddb)", + "Peach","(fb9)", + "Col 16","(222)", + "Col 17","(eee)", + "Col 18","(000)", + "Col 19","(ccc)", + "Col 20","(bbb)", + "Col 21","(aaa)", + "Col 22","(999)", + "Col 23","(888)", + "Col 24","(777)", + "Col 25","(666)", + "Col 26","(555)", + "Col 27","(444)", + "Col 28","(333)", + "Col 29","(18f)", + "Col 30","(f81)", + "Col 31","(fff)", +}; + +void +ClearCol( struct Window *w ) +{ + int bxorx, bxory, bxxlen, bxylen; + int incx, incy; + + bxylen = Col_Okay.TopEdge - ( Col_BluePen.TopEdge + Col_BluePen.Height ) - 1 + - txheight - 3; + bxxlen = Col_BluePen.Width - 2; + bxorx = Col_BluePen.LeftEdge + 1; + bxory = Col_BluePen.TopEdge + Col_BluePen.Height + 2; + + incx = bxxlen / amii_numcolors; + incy = bxylen - 2; + + bxxlen /= incx; + bxxlen *= incx; + bxxlen += 2; + + SetAPen( w->RPort, C_WHITE ); + SetDrMd( w->RPort, JAM1 ); + RectFill( w->RPort, bxorx, bxory, bxorx + bxxlen + 1, bxory + bxylen ); + + SetAPen( w->RPort, C_BLACK ); + RectFill( w->RPort, bxorx+1, bxory+1, + bxorx + bxxlen, bxory + bxylen - 1); +} + +void +DrawCol( w, idx, colors ) + struct Window *w; + int idx; + UWORD *colors; +{ + int bxorx, bxory, bxxlen, bxylen; + int i, incx, incy, r, g, b; + long mflags; + + bxylen = Col_Okay.TopEdge - ( Col_BluePen.TopEdge + Col_BluePen.Height ) - 1 + - txheight - 3; + bxxlen = Col_BluePen.Width - 2; + bxorx = Col_BluePen.LeftEdge + 1; + bxory = Col_BluePen.TopEdge + Col_BluePen.Height + 2; + + incx = bxxlen / amii_numcolors; + incy = bxylen - 2; + + bxxlen /= incx; + bxxlen *= incx; + bxxlen += 2; + + for( i = 0; i < amii_numcolors; ++i ) + { + int x, y; + x = bxorx + 2 + (i*incx); + y = bxory + 2; + + if( i == idx ) + { + SetAPen( w->RPort, flags.amii_dripens[ SHADOWPEN ] ); + Move( w->RPort, x, y+bxylen-4 ); + Draw( w->RPort, x, y ); + Draw( w->RPort, x+incx-1, y ); + + Move( w->RPort, x+1, y+bxylen-5 ); + Draw( w->RPort, x+1, y+1 ); + Draw( w->RPort, x+incx-2, y+1 ); + + SetAPen( w->RPort, flags.amii_dripens[ SHINEPEN ] ); + Move( w->RPort, x+incx-1, y+1 ); + Draw( w->RPort, x+incx-1, y+bxylen-4 ); + Draw( w->RPort, x, y+bxylen-4 ); + + Move( w->RPort, x+incx-2, y+2 ); + Draw( w->RPort, x+incx-2, y+bxylen-5 ); + Draw( w->RPort, x+1, y+bxylen-5 ); + } + else + { + SetAPen( w->RPort, C_BLACK ); + Move( w->RPort, x, y ); + Draw( w->RPort, x +incx-1, y ); + Draw( w->RPort, x +incx-1, y +bxylen - 4 ); + Draw( w->RPort, x, y + bxylen - 4 ); + Draw( w->RPort, x, y ); + SetAPen( w->RPort, C_BLACK ); + Move( w->RPort, x+1, y+1 ); + Draw( w->RPort, x +incx-2, y+1 ); + Draw( w->RPort, x +incx-2, y +bxylen - 6 ); + Draw( w->RPort, x+1, y + bxylen - 6 ); + Draw( w->RPort, x+1, y+1 ); + } + + SetAPen( w->RPort, i ); + RectFill( w->RPort, x + 3, y + 3, x + incx - 4, y + bxylen - 6 ); + } + + DispCol( w, idx, colors ); + + r = (colors[ idx ] & 0xf00) >> 8; + g = (colors[ idx ] & 0x0f0) >> 4; + b = colors[ idx ] & 0x00f; + + mflags = AUTOKNOB|FREEHORIZ; +#ifdef INTUI_NEW_LOOK + if( IntuitionBase->LibNode.lib_Version >= 37 ) + { + mflags |= PROPNEWLOOK; + } +#endif + NewModifyProp( &Col_RedPen, w, NULL, mflags, (r * MAXPOT ) / 15, 0, + MAXPOT/15, 0, 1 ); + NewModifyProp( &Col_GreenPen, w, NULL, mflags, (g * MAXPOT ) / 15, 0, + MAXPOT/15, 0, 1 ); + NewModifyProp( &Col_BluePen, w, NULL, mflags, (b * MAXPOT ) / 15, 0, + MAXPOT/15, 0, 1 ); +} + +void +DispCol( w, idx, colors ) + struct Window *w; + int idx; + UWORD *colors; +{ + char buf[ 50 ]; + char *colname, *defval; + + if( WINVERS_AMIV ) + { + colname = amiv_colnames[idx].name; + defval = amiv_colnames[idx].defval; + } + else + { + colname = amii_colnames[idx].name; + defval = amii_colnames[idx].defval; + } + + if( colname == NULL ) + { + colname = "unknown"; + defval = "unknown"; + } + Move( w->RPort, Col_Save.LeftEdge, + Col_Save.TopEdge - 7 ); + sprintf( buf, "%s=%03x default=%s%s", colname, colors[idx], defval, + " "+strlen(colname)+1 ); + SetAPen( w->RPort, C_RED ); + SetBPen( w->RPort, amii_otherBPen ); + SetDrMd( w->RPort, JAM2 ); + Text( w->RPort, buf, strlen( buf ) ); +} + +void +amii_setpens( int count ) +{ +#ifdef INTUI_NEW_LOOK + struct EasyStruct ea = { + sizeof( struct EasyStruct ), + 0l, + "NetHack Request", + "Number of pens requested(%ld) not correct", + "Use default pens|Use requested pens" + }; + struct EasyStruct ea2 = { + sizeof( struct EasyStruct ), + 0l, + "NetHack Request", + "Number of pens requested(%ld) not\ncompatible with game configuration(%ld)", + "Use default pens|Use requested pens" + }; +#endif + /* If the pens in amii_curmap are + * more pens than in amii_numcolors, then we choose to ignore + * those pens. + */ +#ifdef INTUI_NEW_LOOK + if( IntuitionBase && IntuitionBase->LibNode.lib_Version >= 39 ) + { + if( count != amii_numcolors ) + { + long args[2]; + args[0] = count; + args[1] = amii_numcolors; + if( EasyRequest( NULL, &ea2, NULL, args ) == 1 ) + { + memcpy( flags.amii_curmap, amii_initmap, + amii_numcolors*sizeof(amii_initmap[0])); + } + } + } + else if( IntuitionBase && IntuitionBase->LibNode.lib_Version >= 37 ) + { + if( count != amii_numcolors ) + { + if( EasyRequest( NULL, &ea, NULL, NULL ) == 1 ) + { + memcpy( flags.amii_curmap, amii_initmap, + amii_numcolors*sizeof(amii_initmap[0])); + } + } + } + else +#endif + if( count != amii_numcolors ) + { + memcpy( flags.amii_curmap, amii_initmap, + amii_numcolors*sizeof(amii_initmap[0])); + } + + /* If the pens are set in NetHack.cnf, we can get called before + * HackScreen has been opened. + */ + if( HackScreen != NULL ) + { + LoadRGB4( &HackScreen->ViewPort, flags.amii_curmap, amii_numcolors ); + } +} + +/* Generate a requester for a string value. */ + +void amii_getlin(prompt,bufp) + const char *prompt; + char *bufp; +{ + getlind(prompt,bufp,0); +} + +/* and with default */ +void getlind(prompt,bufp, dflt) + const char *prompt; + char *bufp; + const char *dflt; +{ +#ifndef TOPL_GETLINE + register struct Window *cwin; + register struct IntuiMessage *imsg; + register long class, code, qual; + register int aredone = 0; + register struct Gadget *gd; + static int once; + + *StrString = 0; + if( dflt ) + strcpy( StrString, dflt ); + StrWindow.Title = (UBYTE *)prompt; + StrWindow.Screen = HackScreen; + + if( !once ) + { + if( bigscreen ) { + StrWindow.LeftEdge = (HackScreen->Width/2) - (StrWindow.Width/2); + if (amii_wins[WIN_MAP]) { + StrWindow.TopEdge = amii_wins[WIN_MAP]->win->TopEdge; + } else { + StrWindow.TopEdge = (HackScreen->Height/2) - (StrWindow.Height/2); + } + } + SetBorder( &String ); + SetBorder( &Gadget2 ); + once = 1; + } + + if( WINVERS_AMIV || WINVERS_AMII ) + { +#ifdef INTUI_NEW_LOOK + StrWindow.Extension = wintags; + StrWindow.Flags |= WFLG_NW_EXTENDED; +# ifdef __GNUC__ + fillhook.h_Entry = (void *)&LayerFillHook; +# else + fillhook.h_Entry = (ULONG(*)())LayerFillHook; +# endif + fillhook.h_Data = (void *)-2; + fillhook.h_SubEntry = 0; +#endif + } + + if( ( cwin = OpenWindow( (void *)&StrWindow ) ) == NULL ) + { + return; + } + + while( !aredone ) + { + WaitPort( cwin->UserPort ); + while( ( imsg = (void *) GetMsg( cwin->UserPort ) ) != NULL ) + { + class = imsg->Class; + code = imsg->Code; + qual = imsg->Qualifier; + gd = (struct Gadget *) imsg->IAddress; + + switch( class ) + { + case VANILLAKEY: + if( code == '\033' && (qual & + (IEQUALIFIER_LALT|IEQUALIFIER_RALT| + IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND) ) == 0 ) + { + if( bufp ) + { + bufp[0]='\033'; + bufp[1]=0; + } + aredone = 1; + } + else + { + ActivateGadget( &String, cwin, NULL ); + } + break; + + case ACTIVEWINDOW: + ActivateGadget( &String, cwin, NULL ); + break; + + case GADGETUP: + switch( gd->GadgetID ) + { + case 2: + aredone = 1; + if( bufp ) + strcpy( bufp, StrString ); + break; + + case 1: + if( bufp ) + { + bufp[0]='\033'; + bufp[1]=0; + } + aredone = 1; + break; + } + break; + + case CLOSEWINDOW: + if( bufp ) + { + bufp[0]='\033'; + bufp[1]=0; + } + aredone = 1; + break; + } + ReplyMsg( (struct Message *) imsg ); + } + } + + CloseWindow( cwin ); +#else + struct amii_WinDesc *cw; + struct Window *w; + int colx, ocolx, c; + char *obufp; + + amii_clear_nhwindow( WIN_MESSAGE ); + amii_putstr( WIN_MESSAGE, 0, prompt ); + cw = amii_wins[ WIN_MESSAGE ]; + w = cw->win; + ocolx = colx = strlen( prompt ) + 1; + + obufp = bufp; + cursor_on(WIN_MESSAGE); + while((c = WindowGetchar()) != EOF) + { + cursor_off(WIN_MESSAGE); + amii_curs( WIN_MESSAGE, colx, 0 ); + if(c == '\033') + { + *obufp = c; + obufp[1] = 0; + return; + } + else if(c == '\b') + { + if(bufp != obufp) + { + bufp--; + amii_curs( WIN_MESSAGE, --colx, 0); + Text( w->RPort, "\177 ", 2 ); + amii_curs( WIN_MESSAGE, colx, 0); + } + else + DisplayBeep( NULL ); + } + else if( c == '\n' || c == '\r' ) + { + *bufp = 0; + amii_addtopl( obufp ); + return; + } + else if(' ' <= c && c < '\177') + { + /* avoid isprint() - some people don't have it + ' ' is not always a printing char */ + *bufp = c; + bufp[1] = 0; + + Text( w->RPort, bufp, 1 ); + Text( w->RPort, "\177", 1 ); + if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO) + { + colx++; + bufp++; + } + } + else if(c == ('X'-64) || c == '\177') + { + amii_curs( WIN_MESSAGE, ocolx, 0 ); + Text( w->RPort, + " ", + colx - ocolx ); + amii_curs( WIN_MESSAGE, colx = ocolx, 0 ); + } else + DisplayBeep( NULL ); + cursor_on(WIN_MESSAGE); + } + cursor_off(WIN_MESSAGE); + *bufp = 0; +#endif +} + +void amii_change_color( pen, val, rev ) + int pen, rev; + long val; +{ + if( rev ) + flags.amii_curmap[ pen ] = ~val; + else + flags.amii_curmap[ pen ] = val; + + if( HackScreen ) + LoadRGB4( &HackScreen->ViewPort, flags.amii_curmap, amii_numcolors ); +} + +char * +amii_get_color_string( ) +{ + int i; + char s[ 10 ]; + static char buf[ BUFSZ ]; + + *buf = 0; + for( i = 0; i < min(32,amii_numcolors); ++i ) + { + sprintf( s, "%s%03lx", i ? "/" : "", (long)flags.amii_curmap[ i ] ); + strcat( buf, s ); + } + + return( buf ); +} diff --git a/sys/amiga/winstr.c b/sys/amiga/winstr.c new file mode 100644 index 0000000..0ff2f7d --- /dev/null +++ b/sys/amiga/winstr.c @@ -0,0 +1,522 @@ +/* SCCS Id: @(#)winstr.c 3.1 93/04/02 */ +/* Copyright (c) Gregg Wonderly, Naperville, Illinois, 1991,1992,1993. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "NH:sys/amiga/windefs.h" +#include "NH:sys/amiga/winext.h" +#include "NH:sys/amiga/winproto.h" + +/* Put a string into the indicated window using the indicated attribute */ + +void +amii_putstr(window,attr,str) + winid window; + int attr; + const char *str; +{ + int fudge; + int len; + struct Window *w; + register struct amii_WinDesc *cw; + char *ob; + int i, j, n0, bottom, totalvis, wheight; + static int wrapping = 0; + + /* Always try to avoid a panic when there is no window */ + if( window == WIN_ERR ) + { + window = WIN_BASE; + if( window == WIN_ERR ) + window = WIN_BASE = amii_create_nhwindow( NHW_BASE ); + } + + if( window == WIN_ERR || ( cw = amii_wins[window] ) == NULL ) + { + iflags.window_inited=0; + panic(winpanicstr,window, "putstr"); + } + + w = cw->win; + + if(!str) return; + amiIDisplay->lastwin = window; /* do we care??? */ + + /* NHW_MENU windows are not opened immediately, so check if we + * have the window pointer yet + */ + + if( w ) + { + /* Set the drawing mode and pen colors */ + SetDrMd( w->RPort, JAM2 ); + amii_sethipens( w, cw->type, attr ); + } + else if( cw->type != NHW_MENU && cw->type != NHW_TEXT ) + { + panic( "NULL window pointer in putstr 2: %d", window ); + } + + /* Okay now do the work for each type */ + + switch(cw->type) + { + case NHW_MESSAGE: + if( WINVERS_AMIV ) + fudge = 2; + else + { + /* 8 for --more--, 1 for preceeding sp, 1 for putstr pad */ + fudge = 10; + } + + /* There is a one pixel border at the borders, so subtract two */ + bottom = amii_msgborder( w ); + + wheight = ( w->Height - w->BorderTop - + w->BorderBottom - 3 ) / w->RPort->TxHeight; + + if (scrollmsg || wheight > 1) + fudge = 0; + + amii_scrollmsg( w, cw ); + + while (isspace(*str)) str++; + strncpy( toplines, str, TBUFSZ ); + toplines[ TBUFSZ - 1 ] = 0; + + /* For initial message to be visible, we need to explicitly position the + * cursor. This flag, cw->curx == -1 is set elsewhere to force the + * cursor to be repositioned to the "bottom". + */ + if( cw->curx == -1 ) + { + amii_curs( WIN_MESSAGE, 1, bottom ); + cw->curx = 0; + } + + /* If used all of history lines, move them down */ + if( cw->maxrow >= iflags.msg_history ) + { + if( cw->data[ 0 ] ) + free( cw->data[ 0 ] ); + memcpy( cw->data, &cw->data[ 1 ], + ( iflags.msg_history - 1 ) * sizeof( char * ) ); + cw->data[ iflags.msg_history - 1 ] = + (char *) alloc( strlen( toplines ) + 5 ); + strcpy( cw->data[ i = iflags.msg_history - 1 ] + + SOFF + (scrollmsg!=0), toplines ); + } + else + { + /* Otherwise, allocate a new one and copy the line in */ + cw->data[ cw->maxrow ] = (char *) + alloc( strlen( toplines ) + 5 ); + strcpy( cw->data[ i = cw->maxrow++ ] + + SOFF + (scrollmsg!=0), toplines ); + } + cw->data[ i ][ SEL_ITEM ] = 1; + cw->data[ i ][ VATTR ] = attr+1; + + if( scrollmsg ) + { + cw->curx = 0; + cw->data[ i ][2] = (cw->wflags & FLMSG_FIRST ) ? '>' : ' '; + } + + str = cw->data[i] + SOFF; + if( cw->curx + strlen(str) >= (cw->cols-fudge) ) + { + int i; + char *ostr = (char *)str; + char *p; + + while( cw->curx + strlen( str ) >= (cw->cols-fudge) ) + { + for(p=((char *)&str[ cw->cols-1 - cw->curx ])-fudge; !isspace(*p) && p > str;) + --p; + if (p < str) p = (char *)str; + + if( p == str ) { + /* p = (char *)&str[ cw->cols ]; */ + outmore(cw); + continue; + } + + i = (long)p-(long)str; + outsubstr( cw, (char *)str, i, fudge ); + cw->curx += i; + + while(isspace(*p)) p++; + str = p; + +#if 0 + if( str != ostr ) { + outsubstr( cw, "+", 1, fudge ); + cw->curx+=2; + } +#endif + if(*str) + amii_scrollmsg( w, cw ); + amii_cl_end( cw, cw->curx ); + } + + if( *str ) + { + if( str != ostr ) + { + outsubstr( cw, "+", 1, fudge ); + cw->curx+=2; + } + while ( isspace( *str ) ) + ++str; + outsubstr( cw, (char *)str, i = strlen( (char *)str ), fudge ); + cw->curx += i; + amii_cl_end( cw, cw->curx ); + } + } + else + { + outsubstr( cw, (char *)str, i = strlen( (char *)str ), fudge ); + cw->curx += i; + amii_cl_end( cw, cw->curx ); + } + cw->wflags &= ~FLMSG_FIRST; + len = 0; + if( scrollmsg ) + { + totalvis = CountLines( window ); + SetPropInfo( w, &MsgScroll, + ( w->Height-w->BorderTop-w->BorderBottom ) / w->RPort->TxHeight, + totalvis, totalvis ); + } + i = strlen( toplines + SOFF ); + cw->maxcol = max( cw->maxcol, i ); + cw->vwy = cw->maxrow; + break; + + case NHW_STATUS: + if( cw->data[ cw->cury ] == NULL ) + panic( "NULL pointer for status window" ); + ob = &cw->data[cw->cury][j = cw->curx]; + if(flags.botlx) *ob = 0; + + /* Display when beam at top to avoid flicker... */ + WaitTOF(); + Text(w->RPort,(char *)str,strlen((char *)str)); + if( cw->cols > strlen( str ) ) + TextSpaces( w->RPort, cw->cols - strlen( str ) ); + + (void) strncpy(cw->data[cw->cury], str, cw->cols ); + cw->data[cw->cury][cw->cols-1] = '\0'; /* null terminate */ + cw->cury = (cw->cury+1) % 2; + cw->curx = 0; + break; + + case NHW_MAP: + case NHW_BASE: + if (cw->type == NHW_BASE && wrapping) { + amii_curs(window, cw->curx+1, cw->cury); + TextSpaces(w->RPort, cw->cols); + if (cw->cury < cw->rows) { + amii_curs(window, cw->curx+1, cw->cury+1); + TextSpaces(w->RPort, cw->cols); + cw->cury--; + } + } + amii_curs(window, cw->curx+1, cw->cury); + Text(w->RPort,(char *)str,strlen((char *)str)); + cw->curx = 0; + /* CR-LF is automatic in these windows */ + cw->cury++; + if (cw->type == NHW_BASE && cw->cury >= cw->rows) { + cw->cury = 0; + wrapping = 1; + } + break; + + case NHW_MENU: + case NHW_TEXT: + + /* always grows one at a time, but alloc 12 at a time */ + + if( cw->cury >= cw->rows || !cw->data ) + { + char **tmp; + + /* Allocate 12 more rows */ + cw->rows += 12; + tmp = (char**) alloc(sizeof(char*) * cw->rows); + + /* Copy the old lines */ + for(i=0; icury; i++) + tmp[i] = cw->data[i]; + + if( cw->data ) { + free( cw->data ); + cw->data = NULL; + } + + cw->data = tmp; + + /* Null out the unused entries. */ + for(i=cw->cury; irows; i++) + cw->data[i] = 0; + } + + if( !cw->data ) + panic("no data storage"); + + /* Shouldn't need to do this, but... */ + + if( cw->data && cw->data[cw->cury] ) { + free( cw->data[cw->cury] ); + cw->data[cw->cury] = NULL; + } + + n0 = strlen(str)+1; + cw->data[cw->cury] = (char*) alloc(n0+SOFF); + + /* avoid nuls, for convenience */ + cw->data[cw->cury][VATTR] = attr+1; + cw->data[cw->cury][SEL_ITEM] = 0; + Strcpy( cw->data[cw->cury] + SOFF, str); + + if(n0 > cw->maxcol) cw->maxcol = n0; + if(++cw->cury > cw->maxrow) cw->maxrow = cw->cury; + break; + + default: + panic("Invalid or unset window type in putstr()"); + } +} + +void +amii_scrollmsg( w, cw ) + register struct Window *w; + register struct amii_WinDesc *cw; +{ + int bottom, wheight; + + bottom = amii_msgborder( w ); + + wheight = ( w->Height - w->BorderTop - + w->BorderBottom - 3 ) / w->RPort->TxHeight; + + if( scrollmsg ) + { + if( ++cw->disprows > wheight ) + { + outmore( cw ); + cw->disprows = 1; /* count this line... */ + } + else + { + ScrollRaster( w->RPort, 0, w->RPort->TxHeight, + w->BorderLeft, w->BorderTop + 1, + w->Width - w->BorderRight-1, + w->Height - w->BorderBottom - 1 ); + } + amii_curs( WIN_MESSAGE, 1, bottom ); + } +} + +int +amii_msgborder( w ) + struct Window *w; +{ + register int bottom; + + /* There is a one pixel border at the borders, so subtract two */ + bottom = w->Height - w->BorderTop - w->BorderBottom - 2; + bottom /= w->RPort->TxHeight; + if( bottom > 0 ) + --bottom; + return( bottom ); +} + +void +outmore( cw ) + register struct amii_WinDesc *cw; +{ + struct Window *w = cw->win; + + if((cw->wflags & FLMAP_SKIP) == 0) + { + if( scrollmsg ) + { + int bottom; + + bottom = amii_msgborder( w ); + + ScrollRaster( w->RPort, 0, w->RPort->TxHeight, + w->BorderLeft, w->BorderTop+1, + w->Width - w->BorderRight-1, + w->Height - w->BorderBottom - 1 ); + amii_curs( WIN_MESSAGE, 1, bottom ); /* -1 for inner border */ + Text( w->RPort, "--more--", 8 ); + } + else + Text( w->RPort, " --more--", 9 ); + + /* Make sure there are no events in the queue */ + flushIDCMP( HackPort ); + + /* Allow mouse clicks to clear --more-- */ + WindowGetchar(); + if( lastevent.type == WEKEY && lastevent.un.key == '\33' ) + cw->wflags |= FLMAP_SKIP; + } + if( !scrollmsg ) + { + amii_curs( WIN_MESSAGE, 1, 0 ); + amii_cl_end( cw, cw->curx ); + } +} + +void +outsubstr( cw, str, len, fudge ) + register struct amii_WinDesc *cw; + char *str; + int len; + int fudge; +{ + struct Window *w = cw->win; + + if( cw->curx ) + { + /* Check if this string and --more-- fit, if not, + * then put out --more-- and wait for a key. + */ + if( (len + fudge ) + cw->curx >= cw->cols ) + { + if( !scrollmsg ) + outmore( cw ); + } + else + { + /* Otherwise, move and put out a blank separator */ + Text( w->RPort, spaces, 1 ); + cw->curx += 1; + } + } + + Text(w->RPort,str,len); +} + +/* Put a graphics character onto the screen */ + +void +amii_putsym( st, i, y, c ) + winid st; + int i, y; + CHAR_P c; +{ + amii_curs( st, i, y ); + Text(amii_wins[st]->win->RPort, &c, 1); +} + +/* Add to the last line in the message window */ + +void +amii_addtopl(s) + const char *s; +{ + register struct amii_WinDesc *cw = amii_wins[WIN_MESSAGE]; + + while(*s) { + if(cw->curx == cw->cols - 1) + amii_putstr(WIN_MESSAGE, 0, ""); + amii_putsym(WIN_MESSAGE, cw->curx + 1, amii_msgborder(cw->win), *s++); + cw->curx++; + } +} + +void +TextSpaces( rp, nr ) + struct RastPort *rp; + int nr; +{ + if( nr < 1 ) + return; + + while (nr > sizeof(spaces) - 1) + { + Text(rp, spaces, (long)sizeof(spaces) - 1); + nr -= sizeof(spaces) - 1; + } + if (nr > 0) + Text(rp, spaces, (long)nr); +} + +void +amii_remember_topl() +{ + /* ignore for now. I think this will be done automatically by + * the code writing to the message window, but I could be wrong. + */ +} + +int +amii_doprev_message() +{ + struct amii_WinDesc *cw; + struct Window *w; + char *str; + + if( WIN_MESSAGE == WIN_ERR || + ( cw = amii_wins[ WIN_MESSAGE ] ) == NULL || ( w = cw->win ) == NULL ) + { + panic(winpanicstr,WIN_MESSAGE, "doprev_message"); + } + + /* When an interlaced/tall screen is in use, the scroll bar will be there */ + /* Or in some other cases as well */ + if( scrollmsg ) + { + struct Gadget *gd; + struct PropInfo *pip; + int hidden, topidx, i, total, wheight; + + for( gd = w->FirstGadget; gd && gd->GadgetID != 1; ) + gd = gd->NextGadget; + + if( gd ) + { + pip = (struct PropInfo *)gd->SpecialInfo; + wheight = ( w->Height - w->BorderTop - + w->BorderBottom - 2 ) / w->RPort->TxHeight; + hidden = max( cw->maxrow - wheight, 0 ); + topidx = (((ULONG)hidden * pip->VertPot) + (MAXPOT/2)) >> 16; + for( total = i = 0; i < cw->maxrow; ++i ) + { + if( cw->data[i][1] != 0 ) + ++total; + } + + i = 0; + topidx -= wheight/4 + 1; + if (topidx < 0) + topidx = 0; + SetPropInfo( w, &MsgScroll, wheight, total, topidx ); + DisplayData( WIN_MESSAGE, topidx ); + } + return(0); + } + + if( --cw->vwy < 0 ) + { + cw->maxcol = 0; + DisplayBeep( NULL ); + str = "\0\0No more history saved..."; + } + else + str = cw->data[ cw->vwy ]; + + amii_cl_end(cw, 0); + amii_curs( WIN_MESSAGE, 1, 0 ); + amii_setdrawpens( amii_wins[WIN_MESSAGE]->win, NHW_MESSAGE ); + Text(w->RPort,str+SOFF,strlen(str+SOFF)); + cw->curx = cw->cols + 1; + + return( 0 ); +} diff --git a/sys/amiga/xpm2iff.c b/sys/amiga/xpm2iff.c new file mode 100644 index 0000000..82bbb01 --- /dev/null +++ b/sys/amiga/xpm2iff.c @@ -0,0 +1,353 @@ +/* SCCS Id: @(#)xpm2iff.c 3.2 95/08/04 */ +/* Copyright (c) 1995 by Gregg Wonderly, Naperville, Illinois */ +/* NetHack may be freely redistributed. See license for details. */ + +#include + +#include "config.h" +#include "tile.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef _DCC +# include +# include +# include +#endif + +struct xpmscreen { + int Width; + int Height; + int Colors; + int ColorResolution; + int Background; + int AspectRatio; + int Interlace; + int BytesPerRow; +} XpmScreen; + +/* translation table from xpm characters to RGB and colormap slots */ +struct Ttable { + char flag; + char r,g,b; + int slot; /* output colortable index */ +}ttable[256]; + +pixval ColorMap[3][MAXCOLORMAPSIZE]; +int colorsinmap; + +/* + * We are using a hybrid form of our own design which we call a BMAP (for + * bitmap) form. It is an ILBM with the bitmaps already deinterleaved, + * completely uncompressed. + * This speeds the loading of the images from the games point of view because it + * does not have to deinterleave and uncompress them. + */ +#define ID_BMAP MAKE_ID( 'B', 'M', 'A', 'P' ) /* instead of ILBM */ +#define ID_BMHD MAKE_ID( 'B', 'M', 'H', 'D' ) /* Same as ILBM */ +#define ID_CAMG MAKE_ID( 'C', 'A', 'M', 'G' ) /* Same as ILBM */ +#define ID_CMAP MAKE_ID( 'C', 'M', 'A', 'P' ) /* Same as ILBM */ +#define ID_PDAT MAKE_ID( 'P', 'D', 'A', 'T' ) /* Extra data describing plane + * size due to graphics.library + * rounding requirements. + */ +#define ID_PLNE MAKE_ID( 'P', 'L', 'N', 'E' ) /* The planes of the image */ + +int nplanes; + +/* BMHD from IFF documentation */ +typedef struct { + UWORD w, h; + WORD x, y; + UBYTE nPlanes; + UBYTE masking; + UBYTE compression; + UBYTE reserved1; + UWORD transparentColor; + UBYTE xAspect, yAspect; + WORD pageWidth, pageHeight; +} BitMapHeader; + +typedef struct { + UBYTE r, g, b; +} AmiColorMap; + +pixel pixels[TILE_Y][TILE_X]; +AmiColorMap *cmap; + +void +error( char *str ) +{ + fprintf( stderr, "ERROR: %s\n", str ); +} + +char **planes; + +main( int argc, char **argv ) +{ + int colors; + struct { + long nplanes; + long pbytes; + long across; + long down; + long npics; + long xsize; + long ysize; + } pdat; + long pbytes; /* Bytes of data in a plane */ + int i, cnt; + BitMapHeader bmhd; + struct IFFHandle *iff; + long camg = HIRES|LACE; + int tiles=0; + int index; + +#if defined(_DCC) || defined (__GNUC__) + IFFParseBase = OpenLibrary( "iffparse.library", 0 ); + if( !IFFParseBase ) { + error( "unable to open iffparse.library" ); + exit( 1 ); + } +#endif + + if( fopen_xpm_file( argv[1], "r" ) != TRUE ) + { + perror( argv[1] ); + return( 1 ); + } + + nplanes = 0; + i = XpmScreen.Colors - 1; + while( i != 0 ) + { + nplanes++; + i >>= 1; + } + + planes = malloc( nplanes * sizeof( char * ) ); + if( planes == 0 ) + { + error( "can not allocate planes pointer" ); + exit( 1 ); + } + + XpmScreen.BytesPerRow = ((XpmScreen.Width + 15)/16)*2; + pbytes = XpmScreen.BytesPerRow * XpmScreen.Height; + for( i = 0; i < nplanes; ++i ) + { + planes[ i ] = malloc( pbytes ); + if( planes[ i ] == 0 ) + { + error( "can not allocate planes pointer" ); + exit( 1 ); + } + memset( planes[i], 0, pbytes ); + } + + iff = AllocIFF(); + if( !iff ) + { + error( "Can not allocate IFFHandle" ); + return( 1 ); + } + + iff->iff_Stream = Open( argv[2], MODE_NEWFILE ); + if( !iff->iff_Stream ) + { + error( "Can not open output file" ); + return( 1 ); + } + + InitIFFasDOS( iff ); + OpenIFF( iff, IFFF_WRITE ); + + PushChunk( iff, ID_BMAP, ID_FORM, IFFSIZE_UNKNOWN ); + + bmhd.w = XpmScreen.Width; + bmhd.h = XpmScreen.Height; + bmhd.x = 0; + bmhd.y = 0; + bmhd.nPlanes = nplanes; + bmhd.masking = 0; + bmhd.compression = 0; + bmhd.reserved1 = 0; + bmhd.transparentColor = 0; + bmhd.xAspect = 100; + bmhd.yAspect = 100; + bmhd.pageWidth = 0; /* not needed for this program */ + bmhd.pageHeight = 0; /* not needed for this program */ + + PushChunk( iff, ID_BMAP, ID_BMHD, sizeof( bmhd ) ); + WriteChunkBytes( iff, &bmhd, sizeof( bmhd ) ); + PopChunk( iff ); + + PushChunk( iff, ID_BMAP, ID_CAMG, sizeof( camg ) ); + WriteChunkBytes( iff, &camg, sizeof( camg ) ); + PopChunk( iff ); + +#define SCALE(x) (x) + cmap = malloc( (colors = (1L<iff_Stream ); + FreeIFF( iff ); + +#if defined(_DCC) || defined (__GNUC__) + CloseLibrary( IFFParseBase ); +#endif + exit( 0 ); +} + +#define SETBIT(Plane, Plane_offset, Col, Value) \ + if(Value){ \ + planes[Plane][Plane_offset + (Col/8)] |= 1<<(7-(Col & 7)); \ + } + +conv_image(){ + int row, col, planeno; + + for(row = 0;row if any */ + for(bp = buf;*bp;bp++); + bp--; + while(isspace(*bp))bp--; + if(*bp==',')bp--; + if(*bp=='"')bp--; + bp++; + *bp = '\0'; + + return &buf[1]; +} diff --git a/sys/atari/Install.tos b/sys/atari/Install.tos index 25b6b80..76d1084 100644 --- a/sys/atari/Install.tos +++ b/sys/atari/Install.tos @@ -1,7 +1,7 @@ - Instructions for compiling and installing NetHack 3.3 + Instructions for compiling and installing NetHack 3.4 on a TOS system ===================================================== - (or, How to make ST NetHack 3.3) + (or, How to make ST NetHack 3.4) Last revision: 2 February 2000 1. Make sure all the NetHack files are in the appropriate directory structure. @@ -115,7 +115,7 @@ Notes ----- 1) Save files and bones files from previous versions will not work with - NetHack 3.3. Don't bother trying to keep them. + NetHack 3.4. Don't bother trying to keep them. 2) To install an update of NetHack after changing something, enter "make" from the src directory. If you add, delete, or reorder monsters or diff --git a/sys/be/bemain.c b/sys/be/bemain.c index 46b52f2..acebb15 100644 --- a/sys/be/bemain.c +++ b/sys/be/bemain.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)bemain.c 3.3 98/07/15 */ +/* SCCS Id: @(#)bemain.c 3.4 1998/07/15 */ /* Copyright (c) Dean Luick, 1996. */ /* NetHack may be freely redistributed. See license for details. */ @@ -213,6 +213,9 @@ static void process_options(int argc, char **argv) flags.initrace = i; } break; + case '@': + flags.randomall = 1; + break; default: raw_printf("Unknown option: %s", *argv); break; diff --git a/sys/mac/Files.r b/sys/mac/Files.r index fa7837f..b381328 100644 --- a/sys/mac/Files.r +++ b/sys/mac/Files.r @@ -1,3 +1,19 @@ +#include +#include "date.h" +#include "patchlevel.h" + +resource 'vers' (1, purgeable) { + VERSION_MAJOR, (VERSION_MINOR<<4) | PATCHLEVEL, final, EDITLEVEL, verUS, + VERSION_STRING, + VERSION_STRING +}; + +resource 'vers' (2, purgeable) { + VERSION_MAJOR, (VERSION_MINOR<<4) | PATCHLEVEL, final, EDITLEVEL, verUS, + VERSION_STRING, + "devteam@nethack.org" +}; + read 'File' (1000,"cmdhelp") ":dat:cmdhelp"; read 'File' (1001,"help") ":dat:help"; read 'File' (1002,"hh") ":dat:hh"; @@ -30,31 +46,38 @@ read 'File' (1028,"medusa-2.lev") ":lib:medusa-2.lev"; read 'File' (1029,"minefill.lev") ":lib:minefill.lev"; read 'File' (1030,"minend-1.lev") ":lib:minend-1.lev"; read 'File' (1031,"minend-2.lev") ":lib:minend-2.lev"; -read 'File' (1032,"minetn-1.lev") ":lib:minetn-1.lev"; -read 'File' (1033,"minetn-2.lev") ":lib:minetn-2.lev"; -read 'File' (1034,"options") ":lib:options"; -read 'File' (1035,"oracle.lev") ":lib:oracle.lev"; -read 'File' (1036,"oracles") ":lib:oracles"; -read 'File' (1037,"orcus.lev") ":lib:orcus.lev"; -read 'File' (1038,"quest.dat") ":lib:quest.dat"; -read 'File' (1039,"rumors") ":lib:rumors"; -read 'File' (1040,"sanctum.lev") ":lib:sanctum.lev"; -read 'File' (1041,"soko1-1.lev") ":lib:soko1-1.lev"; -read 'File' (1042,"soko1-2.lev") ":lib:soko1-2.lev"; -read 'File' (1043,"soko2-1.lev") ":lib:soko2-1.lev"; -read 'File' (1044,"soko2-2.lev") ":lib:soko2-2.lev"; -read 'File' (1045,"soko3-1.lev") ":lib:soko3-1.lev"; -read 'File' (1046,"soko3-2.lev") ":lib:soko3-2.lev"; -read 'File' (1047,"soko4-1.lev") ":lib:soko4-1.lev"; -read 'File' (1048,"soko4-2.lev") ":lib:soko4-2.lev"; -read 'File' (1049,"tower1.lev") ":lib:tower1.lev"; -read 'File' (1050,"tower2.lev") ":lib:tower2.lev"; -read 'File' (1051,"tower3.lev") ":lib:tower3.lev"; -read 'File' (1052,"valley.lev") ":lib:valley.lev"; -read 'File' (1053,"water.lev") ":lib:water.lev"; -read 'File' (1054,"wizard1.lev") ":lib:wizard1.lev"; -read 'File' (1055,"wizard2.lev") ":lib:wizard2.lev"; -read 'File' (1056,"wizard3.lev") ":lib:wizard3.lev"; +read 'File' (1032,"minend-3.lev") ":lib:minend-3.lev"; +read 'File' (1033,"minend-4.lev") ":lib:minend-4.lev"; +read 'File' (1034,"minetn-1.lev") ":lib:minetn-1.lev"; +read 'File' (1035,"minetn-2.lev") ":lib:minetn-2.lev"; +read 'File' (1036,"minetn-3.lev") ":lib:minetn-3.lev"; +read 'File' (1037,"minetn-4.lev") ":lib:minetn-4.lev"; +read 'File' (1038,"minetn-5.lev") ":lib:minetn-5.lev"; +read 'File' (1039,"minetn-6.lev") ":lib:minetn-6.lev"; +read 'File' (1040,"minetn-7.lev") ":lib:minetn-7.lev"; +read 'File' (1041,"options") ":lib:options"; +read 'File' (1042,"oracle.lev") ":lib:oracle.lev"; +read 'File' (1043,"oracles") ":lib:oracles"; +read 'File' (1044,"orcus.lev") ":lib:orcus.lev"; +read 'File' (1045,"quest.dat") ":lib:quest.dat"; +read 'File' (1046,"rumors") ":lib:rumors"; +read 'File' (1047,"sanctum.lev") ":lib:sanctum.lev"; +read 'File' (1048,"soko1-1.lev") ":lib:soko1-1.lev"; +read 'File' (1049,"soko1-2.lev") ":lib:soko1-2.lev"; +read 'File' (1050,"soko2-1.lev") ":lib:soko2-1.lev"; +read 'File' (1051,"soko2-2.lev") ":lib:soko2-2.lev"; +read 'File' (1052,"soko3-1.lev") ":lib:soko3-1.lev"; +read 'File' (1053,"soko3-2.lev") ":lib:soko3-2.lev"; +read 'File' (1054,"soko4-1.lev") ":lib:soko4-1.lev"; +read 'File' (1055,"soko4-2.lev") ":lib:soko4-2.lev"; +read 'File' (1056,"tower1.lev") ":lib:tower1.lev"; +read 'File' (1057,"tower2.lev") ":lib:tower2.lev"; +read 'File' (1058,"tower3.lev") ":lib:tower3.lev"; +read 'File' (1059,"valley.lev") ":lib:valley.lev"; +read 'File' (1060,"water.lev") ":lib:water.lev"; +read 'File' (1061,"wizard1.lev") ":lib:wizard1.lev"; +read 'File' (1062,"wizard2.lev") ":lib:wizard2.lev"; +read 'File' (1063,"wizard3.lev") ":lib:wizard3.lev"; read 'File' (1100,"Arc-fila.lev") ":lib:Arc-fila.lev"; read 'File' (1101,"Arc-filb.lev") ":lib:Arc-filb.lev"; read 'File' (1102,"Arc-goal.lev") ":lib:Arc-goal.lev"; diff --git a/sys/mac/Install.mw b/sys/mac/Install.mw index d31b738..51580cf 100644 --- a/sys/mac/Install.mw +++ b/sys/mac/Install.mw @@ -1,4 +1,4 @@ -Building a PPC NetHack 3.3 with the Metrowerks compilers +Building a PPC NetHack 3.4 with the Metrowerks compilers You must be familiar with the Metrowerks compiler and know how to construct diff --git a/sys/mac/MacHelp b/sys/mac/MacHelp index e8b1aa3..3197aed 100644 --- a/sys/mac/MacHelp +++ b/sys/mac/MacHelp @@ -1,11 +1,11 @@ - Macintosh-specific help file for NetHack 3.3 + Macintosh-specific help file for NetHack 3.4 The following are options, features, or concerns specific to the -Macintosh port of NetHack 3.3. Bug reports, suggestions, comments, +MacOS Classic port of NetHack. Bug reports, suggestions, comments, and so on, should be addressed to: To: nethack-bugs@nethack.org - Subject: Mac NetHack 3.3 + Subject: Mac NetHack 3.4 or you can use our on-line bug reporting form at @@ -17,10 +17,10 @@ and so on). === Configuration of a playground - NetHack 3.3 is packaged in a Dungeon Folder which includes: + NetHack is packaged in a Dungeon Folder which includes: NetHack - the application file itself. NetHack Defaults - text file for default option settings. - license - licensing terms for nethack. + License - licensing terms for nethack. Guidebook - description of the game in long format. Recover - the application to restore save files from crashed games. Previous versions had a large number of data files in the Dungeon @@ -50,6 +50,7 @@ and so on). and answer the "Who are you?" dialog with the player name of the saved game in the Dungeon Folder. + === Windows The Dungeon Map and Message windows are the essential windows used during window-mode play. During tty-mode play there is only one @@ -68,23 +69,13 @@ and so on). window positions are saved in a file labelled "NetHack Windows" in the appropriate preferences folder. + === Default options The following options are specific to the Macintosh port: background: - black or white MACgraphics - use enhanced dungeon map symbols [TRUE] - large_font - use 12 point font instead of 9 point font [FALSE] - popup_dialog - use real dialogs for question prompts [FALSE] page_wait - display --MORE-- after messages [TRUE] - use_stone:# - use a background pattern for the dungeon. - - large_font is currently a pre-game option and has no effect - after the Dungeon Map window is created. - use_stone is also a pre-game option. The number parameter - specifies which pattern to use. If the number is 0 or - greater than the number of available patterns, it has no - effect. - Default options may be set by editing the NetHack Defaults text file (using SimpleText or your favorite editor). The following notation is used: diff --git a/sys/mac/NHDeflts b/sys/mac/NHDeflts index be8dd2a..12a9c3d 100644 --- a/sys/mac/NHDeflts +++ b/sys/mac/NHDeflts @@ -1,23 +1,35 @@ -# SCCS Id: @(#)NetHack Defaults 3.3 99/11/20 -# Copyright (c) 1999 by Dean Luick, Mark Modrall, and Kevin Hugo +# SCCS Id: @(#)NetHack Defaults 3.4 2002/03/15 +# Copyright (c) 2002 by Dean Luick, Mark Modrall, and Kevin Hugo # NetHack may be freely redistributed. See license for details. # # Default settings for the Macintosh port of NetHack. -# Comment lines begin with a `#' character. +# Lines beginning with a `#' character are "comments" and are +# ignored all the way to the end of the line. Using this +# method, some of the lines below have been disabled so you +# can see an example without having those options actually +# set. Remove the `#' character to "uncomment" the line and +# allow those options to take effect. ### Display ### # Uncomment for the traditional single-window tty interface #OPTIONS=win:tty -# Font size and style (use HackFont or NewHackFont) -OPTIONS=!large,fontmap:NewHackFont +# Boulder symbol +#OPTIONS=boulder:0 -# Color and background -OPTIONS=color,background:white,use_stone:1 +# Color +OPTIONS=color -# Obsolete way to obtain reverse video; use background:black instead -#OPTIONS=palette:000/c22/2c2/ca0/22c/a2a/2aa/ccc/999/f00/0f0/dd0/00f/d0d/0dd/fff/999/444/622/62c/-222 +# Fonts +#OPTIONS=font_map:NewHackFont,font_size_map:9 +#OPTIONS=font_menu:geneva,font_size_menu:9 +#OPTIONS=font_message:PSHackFont,font_size_message:9 +#OPTIONS=font_status:monaco,font_size_status:9 +#OPTIONS=font_text:geneva,font_size_text:9 + +# Don't make dark corridors look like lit corridors +OPTIONS=!lit_corridor # Enable sound and beeps OPTIONS=sound,!silent @@ -30,33 +42,48 @@ OPTIONS=sound,!silent # Save game state periodically in case of crashes (recommended) OPTIONS=checkpoint +# How to prompt for things after death +#OPTIONS=disclose:+i na -v yg nc + # Show tombstone and top scores at death OPTIONS=tombstone,scores:10t/3a/o +# Show top ten list in its own window +#OPTIONS=toptenwin + ### User input and feedback ### # Choose between menus or text prompts # (traditional, combination, partial, or full) OPTIONS=menustyle:full -# Display a little more information with some commands -OPTIONS=verbose +# Extended (`#') commands by menu +#OPTIONS=extmenu + +# Increase the number of message lines remembered +#OPTIONS=msghistory:60 + +# Enable the number pad keys +OPTIONS=number_pad # Pause for --more-- and make it boldface OPTIONS=page_wait,standout +# Ask for confirmation with the #pray command +OPTIONS=prayconfirm + # Allow spacebar as rest command #OPTIONS=rest_on_space -# Enable the number pad keys -OPTIONS=number_pad - # Display experience, score, and time on status line OPTIONS=showexp,showscore,time -# Use popup windows for yes/no questions -# This is likely to go away in future releases -#OPTIONS=popup_dialog +# Turn off animations +#OPTIONS=!sparkle + +# Display a little more information with some commands +#OPTIONS=suppress_alert:3.3.0 +OPTIONS=verbose ### Character ### @@ -76,18 +103,59 @@ OPTIONS=showexp,showscore,time ### Inventory ### +# Automatically dig if wielding a pick +#OPTIONS=autodig + # Disable autopickup (toggle it with the `@' command) -#OPTIONS=!autopickup +#OPTIONS=!autopickup,pickup_types:$* + +# Automatically fill the quiver +#OPTIONS=autoquiver # Don't use fixed inventory letters OPTIONS=!fixinv,perm_invent,sortpack +# What you want to call slime molds +#OPTIONS=fruit:grape + +# Desired inventory display order +#OPTIONS=packorder:)[( + +# How much you're willing to carry without confirmation +#OPTIONS=pickup_burden:B + +# Put weapon in secondary slot when wielding another +#OPTIONS=pushweapon + ### Pets ### # What to call your starting pet, and its type -OPTIONS=dogname:Quinn,catname:Vladimir,horsename:Silver,pettype:dog +#OPTIONS=dogname:Quinn,catname:Vladimir,horsename:Silver,pettype:dog # Don't intentionally attack your pets OPTIONS=confirm,!hilite_pet,safe_pet + +### Unused options ### + +# Now obsolete +# +# background, large_font, popup_dialog, use_stone + +# Obsolete way to obtain reverse video; use at your own risk +#OPTIONS=palette:000/c22/2c2/ca0/22c/a2a/2aa/ccc/999/f00/0f0/dd0/00f/d0d/0dd/fff/999/444/622/62c/-222 + +# Options used in tty window mode, but not mac window mode +# +# menu_..., msg_window, timed_delay, use_inverse, vary_msgcount + +# Options used by other ports but not Macintosh: +# +# align_message, align_status, ascii_map, BIOS, checkspace, +# decgraphics, eight_bit_tty, ibmgraphics, ignintr, mail, +# map_mode, null, player_selection, preload_tiles, rawio, +# splash_screen, tiled_map, tile_..., videocolors, videoshades, +# windowcolors + + # End-of-file diff --git a/sys/mac/NHrsrc.hqx b/sys/mac/NHrsrc.hqx index 1470973..cc3db83 100644 --- a/sys/mac/NHrsrc.hqx +++ b/sys/mac/NHrsrc.hqx @@ -1,1017 +1,991 @@ (This file must be converted with BinHex 4.0) -:$%jPG%KKBfXZFR0bB`"58e*$8P0&4!#3#0IqDb)!N!3"!*!$cV`!!-fm!!!*3J# -3"!d!%!!Y!$#J!J#S!*!&&J!i!#F!iBJB8h4[$%jPG%KKBfXZFR0bBfTcEA0bBf9 -ZG(-VBe"-Fh"`Ef-!!&*68N058d9%!3!!8`%3!*!5XdZMjJ#3"Q-E!!$)!6!!!3# -3#!Zj!*!%&3#3"HB"A!!"!*!)#lJ!N!39!&!!EJ$k!EJ!!3#3#!I8!*!%&3"3!'i -!qJ'i!!%!N!J(d`#3""8!8!"Z!2S"Z!!"!*!)"p)!N!39!&!!EJ$k!EJ!N!-F!3J -!#!&+!2!!N!S(6@9cFf&RC6J+!*!$(!%Z!!3"8J(+!*!+"P0dBA4eFfXi#J#3!aB -!I!$D!2J"LJ#3"!%!N!C01!S!N!-D!,i!"J&3!6)!N!3"!*!&"%PZCQmJ1!S!N!- -L!#J!+!#-!+)!N!3"!*!&$8jeE'`J9fPZC'ph)#%i#J#3!c`16R9YBQ9b)'pQ)'Y -PHA023dj8"5U3"8a69%-(5f9jBfpNC8K#@93%3fKKFN0)39)&+T!&6&0843#3!b! -!+!!S!8S"lJ#3#JY%G@jRC@pZ)%eKF$J+!*!$)!!S!#J!V!(-!*!%!3#3"3Y%D@& -REQpcG'PMFcJ+!*!$&J!"%deKBb"1CA4)B@0V)%KPE($*,cm!N!1!!*!,$rm!N!6 -r!2%"m!#3!r[`$a!I!*!$$lm2!3(`!*!$qrm3%2!!!2!2[rram!!2$rrlm!m!!!m -3%2qr!*!$$`%"m2[`!*!$m"$`$lm!N!-2!3m!qr!!N!2rm!!2[`#3"r[`!*!'$lm -!N!Ir!*!$J!$rN!6`!*!$m!#3!rm!N!2`!*!$r2!!!2!!N!2rr`!!m!#3"!m!!2! -2m!!!$`!!m2rr!!!2!!$`rrm2r`m!!2!2m!!!$`!!m!#3"!m!!2!2m!!!$`!!m2! -2$r!2!!$`m!m!!!m!!2!2m!!!$`!!m!#3"!m!!2q3"J#3"%!!!!(!-L!j%"d)$`J -Rk&q3!%2!3Z!LF"%i$K`!$J!(!!-!!!(!-q!jm"hi$rJRq(q3!(r!IZ!qF"mi$K` -!$J!(!!-!N!0!2q!J-#!S)$`J"#B%,`3[G#B%)!3Q"#PN+33Q"#!%2r`ri$r`2rJ -rr$rm2r`rr$rm2r`rr$rm2r`rr$rm2r`rr!!!!3#3"Jq!!!!`B!!3)"!!("!)!!i -3#!!2%!3!"j!!"!!$m!3!!H!%!!$`"!!`qq3!6ciB!%!H!!"!$`!!3!q!!%!6`!" -!%H!!)"$`!#!3H!!3#$`!$"JH!!2J$`#3!`H!!!!$`!!!!H!!N!2`!*!$H!#3!c` -!N!-H!*!$$J#3!`3!N!82J!!!2q!!%$r`!"`Iq!!1(rJ!$arm!!HIr!!$rr`!!Ir -m!!$rr!!`rr`!IriB!(rq!!"rr`!!Irq!!(rc`!"rmH!!2r$`!$r`H!!Iq$`!$rJ -H!!2J$`#3!`H!!!!$`!!!!H!!N!2`!*!$H!#3!c`!N!-H!*!$$J#3!`3!!!%!$rr -m!!J!"J!)$J8!#C%%J!R)K%!)k%3J#(K(m!Nr3"!+r)!3#Ki!%!SA!"!*%i!3#)R -!%!K`i"!)!(!3#!!i%!J!'"!)B!!3#*!!!"!*D!!3#@Rq%!L3!!!3#'!!%!J!!"! -)B!!3#*!!!"!*#!!3#3QrN!!)N!!!%!KJ!"!)!!!3$rrrm!rrr!!2rri!$rrr!!r -rri!2rrr!$rrri!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!r +:$%jPG%KKBfXZFR0bB`"58e*$8P0&4!%!N!I4j"fk!*!%!3#3!mRS!!$)k!!!"r` +!N!30!"!!,3!`S!)!U!#3"4B!1!!R!1')'&0dE`a1CA4)B@0V,R*cFQ0UFfecFQ0 +PER4c+f036(0`F'pM!!"58e*$8P0&4!%!!&-"%!#3%V0,SqB!N!CM'`!!b!%`!!% +!N!J,Z3#3""8!N!AQ!9`!!3#3#!Zi!*!%&3"3!'i!qJ'i!!%!N!J(e!#3""8!8!" +Z!2S"Z!!"!*!)"p-!N!39!&!!EJ$k!EJ!!3#3#!I5!*!%&3"3!'i!qJ'i!*!$(!% +)!!J"5J$`!*!+"dePFh0KCf8i#J#3!a`",J!%!9)"bJ#3#JC6G'&dGA0V1!S!N!- +@!(`!fJ$i!BS!N!3"!*!'66J+!*!$'J#q!!B"8!%b!*!%!3#3"34*EQC[)$J+!*! +$)J!S!#J!M!#L!*!%!3#3"3e1G@aX)>EQ4[Gb!K1!S!N!-m$NjeE@*PFL"[CL" +VCAPc6d019!8UN!9-8e4$"dYPH@0[C'9)3PP8"%0SBA*$5%&5"5U3"8a69%8!N!- +J!#J!+!&+!Hi!N!S,4(9ZCf9[EL"0BA!i#J#3!b!!+!!S!+`"c!#3"!%!N!8,4'P +KCfj[Fh4TBh-i#J#3!aB!!400B@-J6Q9d5'&MDb")C@a`b5mr!*!$J!#3#`rr!*! +%r`$a!I!!N!2lm!m3(`#3!`qr$`%"m!#3!r[r%"$`!!$`$lrrmI!!$`rrqr!2!!! +2%"$r[`#3!`m"!I$lm!#3!r!3m!qr!*!$$`%2!2[`!*!$rr!!$lm!N!Ilm!#3"Jq +r!*!(r`#3!i!!rj!%m!#3!r!!N!2r!*!$m!#3!rc`!!$`!*!$rrm!!2!!N!32!!$ +`$r!!!!m!!2$rr`!!$`!!m2rr$rm2!!$`$r!!!!m!!2!!N!32!!$`$r!!!!m!!2$ +`$`r`$`!!m2!2!!!2!!$`$r!!!!m!!2!!N!32!!$rN!B!N!4!!!!"`$)J14!G#!m +)*qKIN!"$`%,J)R!41!iF!!i!"`!$!!!"`$2J1I!Gq!ri*rKrN!"r`(lJ2R!I1!i +F!!i!"`!$!*!$3$rJ)$!J+#!m)!3Q"#m%,h3Q"#!%*J3TC#N%*J3J"$rm2q!rm$r +i2r`rr$rm2r`rr$rm2r`rr$rm2r`rr$rm2r`!!!%!N!B2J!!!-'!!%#!3!"`3#!! +1%!J!$a!%!!H3!!3!!r!%!!(J"!!!m!3!-2[N!%mq'!"!(J!!3!m!!%!2J!"!%m! +!3"(J!#!3m!!J%(J!%!Jm!!`B(J!$i!m!N!-(J!!!!m!!!!(J!*!$m!#3!hJ!N!- +m!*!$(J#3!`i!N!-%!*!&$i!!!$rJ!"!rm!!F(rJ!$Kri!!mIr!!(Rr`!!rrm!!( +rr!!!rr`!-2rm!(rq'!"rrJ!!Irm!!(rrJ!"rmm!!Ir(J!$r`m!!rm(J!(rJm!!r +i(J!$i!m!N!-(J!!!!m!!!!(J!*!$m!#3!hJ!N!-m!*!$(J#3!`i!N!-%!!!"!!r +rr!!)!!B!#!i&!!Q4")!*b)4!#1K%)!Ki4r!*2d!3#[b!%!SH!"!+&`!3#41!%!L +*`"!)F1!3#!"`%!J!1"!)!"J3#'!!%!L3!!!3#@J!%!PTrK!)N!!!%!KJ!"!)!!! +3#'!!%!L3!!!3#3J!%!N*[j!!#*!!!"!)B!!3#!!!%!rrrr!2rr`!$rrq!!rrr`! +2rrq!$rrr`!rrrq!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr! +2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr! +2rrr`$rrrm!rrrr!2rrr`$rrrm!!!!J#3&rrrm!#3$2m3%"r`!*!($`#3!r%"N!- +2!*!($rm!!!m3N!6`!*!(qr!!$`'3"2!!N!Il[`!2%*!%(`#3"`qlm!m"N!32!*! +)qlrr%*!%(`#3#!qlm3'3"!m!N!Rl[a#3""m!N!Er!!$rZr(rrr%2!*!&$a$rra$ +l[r!!$r!!N!82!C!%$l[`!*!)$a#3"IZr!*!)$`'3"Iqlm!#3"`m3N!3I!2Zr!*! +($`'3"!m!$l[`!*!(m"#3!am!!2Zr!*!(m3'3!`m!!!qlm!#3"Jm3N!6`!!$l[`# +3"rm"!3r`!!!2Zr!!N!Irrr!!N!6l[`#3$Jqlm!#3$[Zr!*!1$l[`!*!1qlm!N!i +2Zr!!N!ll[`#3$Jqlm!#3$[[`!*!1$`#3!`)!N!2rN!N!N!I`!*!($r!!N!E`!*! +$rr!!!!r2!*!'m!r`$a!I!!!2c2!!N!A`$lm!m3(`!!r-c`#3"I!!qr$`%"m!$mc +-m!#3"2!!$lra!3m!$rq3!`#3"2!2!2[rram!N!32!*!%m2$rrlm!m!#3"!m!N!6 +`m3%2qr!!N!82!*!%m2!3(`qr!*!&$`#3"2!2!3m!qr!!N!32!*!%m!$`%2!2[`# +3"!m!N!6`!!rr!!$lm!#3!`m!N!6`!*!&$lm!N!-2!*!%m!#3"[[`!!!2!*!%m!# +3"Jr`!!!2!*!%m!!2m!#3"`m!N!6`!2!2!*!($`#3"2!2$r$`!*!'$`#3"2!2$r$ +`$rq3!r!!$`#3"2!!m!m!N!F2!*!%m!!2m!#3"`m!N!6`!*!+$`#3"2!!$r!!N!F +2!*!%m!$`$`#3"`m!N!6`$`!!m!#3"Jm!N!6`$`!!m!r`rj!$m!m!N!6`!2!2!*! +($`#3"2!!$r!!N!F2!*!%m!#3#Jm!N!6rN!`!N!8-!&S!EJ$Z!C)!J84%!*!$6!! +#!*!&H!$'!)S"%!3#6dX!N!8+!%B!F`%3L"a$Eh9XC#"ZEh3JAM)JBQ9MBA9cC5" +H-#iJ)&ia!*!&#J!8!#S!0+!#!*!%!3!2rr`!#!!'!!J1"3!*N35!#FL%3!MS4#! +)H%I`#6p!%!VmJ"!+(J!3#KF!%!N6J"!)LF!3#($J%!J!F"!)!$J3#!!B%!Q8aP! ++95P3#P8T8!T9+9!+95P3#C6'8!J!!"!+C6'3!!U95P!+P8T3#T9+8!U95P!+C6' +3!!J!!"!2rrr`$rrm!!rrrJ!2rrm!$rrrJ!rrrm!2rrrJ$rrrm!rrrr!2rrr`$rr +rm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rr +rm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!!N!0!2q! +J-#!S)$`J"#5N+U3UT#5N)!3T*#UN+U3T*#!%2r`ri$r`2rJrr$rm2r`rr$rm2r` +rr$rm2r`rr$rm2r`rr!!!!J#3!rq3#3#3"r!!N!F2m!#3"[!!N!2rm!!!$mm!N!E +`$r!2%"m!!!r-m!#3"I!2[`$a!I!!$mc2!*!&m!$lm2!3(`!2c-c`!*!%m!!2[r% +"$`!2rj!$!*!%m!m!qrrr(`#3"!m!N!6`m2rr[`$`!*!%$`#3"2$a!3rlm!#3"3m +!N!6`m"!I$lm!N!82!*!%m!m"$`$lm!#3"!m!N!6`!2!3m!qr!*!%$`#3"2!!$rm +!!2[`!*!$$`#3"2!!N!82[`#3!`m!N!6`!*!'qr!!!!m!N!6`!*!'$r!!!!m!N!6 +`$r!2$`$r!!r`$`m!N!6`m!q3"!$`m!q3!`#3"2$`$j!%!2$`$j!$!*!%m2!2N!3 +!m2!2N!-!N!6`m!q3"!$`m!q3!`#3"2!2m!m2!2m!$r!2$`#3"2!!N!S2!*!%m2! +2m!m2!2m!$r!2!*!%m*!$$j!%!2$`$`m!N!6`N!-2N!3!m2!2$`#3"2#3!`q3"!$ +`m!m2!*!%m*!$$j!%!2$`$`m!N!6`m!r`$`m!r`!2m!m!N!6`!*!+$`#3"2q3$!# +3"5)!!3#3"9!"4!"N!Ai%!Np,!*!&"J!i!%B"I)J#AM!!N!1!!2q3"2!!N!2`!*! +$r`#3!r!!N!2mm!!!m!#3!rrr!!$`!*!%$`!!m!m!m2!2!!$`N!82!!$`N!82!!$ +`$`$`m!m!!2!!N!32!!$`m!m!m!m!!2#3"3m!!2#3"3m!!2$`$`$`$`!!m!#3"!m +!!2q3"J#3!`Q)N!!!N!6q!!B!!2rh!!B!#`1l!!N!!J#3!cm!N$2B!*!'&%%!N!8 +T3!!!-!!!'J!!!KK!"@YBL8!(i$P%))"!"*A!F"`"`K3!&3!8))r!rr!"q!#3!h1 +!)!#3"5!!!!jJ!3!3!*![F!"3L!)B"!%#J+)!"!))J!!!B!"")K0X!!!#+)!!!IL +*3!@J+83JJ%!%P8"3&!&#&!!9!"3JMm$rm!d)!*!$*%"3![2!!!3J!`!*N!!'e6R +X6#!!"FZF,l[ZF!!1Flc[Iqk2$'%BZmlc[aM'-ImD!J3!%"JK--!!N!-#!*!%UDl +j&+%N#P#YA1q"kP%846SJP(a#4#@Ll%!#55!&DeL*3!@J+83JJ%!%P8"3&!&#&!! +9!"3JMm$rm"-!2J!fG&a!"I`J%KSJ")!*)26IeV+5U3!'2'*S3$'))*'-BaM#%BS +-SEc'-Ba*'-94$3d""!!3)#!33!#3!`)!N!5UdIJ!!"J!N!-M'!+!!*!$4L5#SN! +!!$-b!!+U!!!"q)P!"D!T4##!3!593&!8!8)8!"8!&##2`2r`)`!5!!QXBL!pr$q +4+L3-Z$P!PB95e#&a!!TS3Upi-BeI3HaM#-)3LJdK@XBaM!NBa*%8L!"rR2Gcr6* +pChRfImBeM(kS%&1Hplh1Fj*M'$U1Fk-BaLlRiZI1MDXb3!&9B!9V@2P"rErTI## +!3!6eIprhrhq9q"Ai&IL2`2rhC3I)r)L[iZh,r#"mb#"cI#RqPiqj5#'[ciUSM5$ +%6SL!)Urp#2[6qJiK'FI4miNBa)SNL!#-BaLNBc4VQ-BjJNBe9%8%%&4M'-BaM&* +rreI4M'-BaM@"2%M4MQEXMriCDC!!!Iq2IM'aMmIrN!5A-``c$#"q"rmRrLIrN!2 +iT3+&&)LXBaV,r$q4+$q)I%!1N!#&&E8K)3!6+32`a*&iAd6dB`M#%BU0)4M'%BK +*'05%4%J!M'%IT'-mDaM'-(*'054)U""hiaM'(rr5BaKqNBaM'-BdKq4)dBaL!3J +%)I*0DeMj5rfpq$a!!N!%pIIrGrprJIP"r4Ai6rrm#+-#L45)G'-Gdr`J%KJJF(p +!$T!!!&Db%J%!%LSL+-54###!K'-B`K'+M+%BaK'-549Y4)4)!*aK'#4M-QXBaM! ++69988+J4*#FjcK#%%Q-B8T'-CcM'0BNZ5G'FBrmB"%"b5!(iL8SPT3!!3!*!"*3 +8!93"3!!K3#88)%rrr!LM!T-8L#49%&2m2i!)*)!iJ!#3!)!k63`!%'(2h#FiMR8 +!"(4mlhi1Mh4r',S1LiML4L6q12a[R[HMic&V&hR`mE5+LrkS$L2DeVA[Hp*M(pl +ZFjVAZFla*%E1E')!i!"`DC9V@)P+*D8!!%!#3!58&!&8!8!!)8!P&#"2rr`(E3+ +qjdKcYZ!pr#"rq5!!!)!!m!!3!*!$%#!!N!8"!*!-!3#3"L!!N!9!)!!!3#!!N!4 +!F!*`!*!$J!#3#B!%!!C!!*!*!IL*5L@P!!"!!N!%P"3"9!&!!#&!*43J6rrm!#! +!!!3!N!3Krq!!#5!!N!SJ!*!'!J#3'!1!`!!!3#!!N!-$J!!%!*!$!3#3#3F!N!- +"J!#3#!9V@)P+*qF!!%!#3!58(!(F!F!!)8!P&#"2rr`!N!3%!*!%3!#3!`M!!*" ++!3!%!!N!$J!6!"J!'J!G!#!!*3!U!#`!-3!b!$B!1`!p!%)!4`"-!&%!9J"E!'! +!C3"Q!'J!D`"`!(-!H!"p!))!K`#-!*%!PJ#E!+!!T3#S!+d!XJ#h!,`!`3$'!-X +!d!$9!0S!h`$N!1N!lJ$c!2J!r3$r!3-""3%)!3i"%!%9!4S"(`%N!5N",3%b!6F +"1!%l!8!"3J&(!8`"83&@!9X"B!&P!@N"EJ&c!AJ"I3'#!BF"LJ',!Bi"N`'6!CJ +"R3'L!DF"V!'a!EB"Z`(!!F8"bJ(0!G!"dJ(A!G`"i3(Q!HX"m!(e!IS"r`)%!JN +#$J)6!KJ#(3)L!LF#,!)a!M-#1!)p!N)#4`*,!Nm#9!*C!Pi#C!*U!QX#F!*e!RS +#I`+%!S8#L3+0!T)#P`+E!U!#S`+S!Ud#XJ+f!VS#[3,$!XN#c!,5!YJ#f`,I!Z- +#j`,Y![-#p`,p!j!$#3-2!a8$'`-I!b)$*3-T!bm$03-j!c`$3J0)!dX$6J08!eS +$A`0P!fS$E`0e!hS$J!1&!iS$M`18!jN$R`1P!kX$X31f!lN$[!1r!m-$b!20!p% +$eJ2A!p`$i!2N!qF$l3!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B +!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!D3!`)'!3B!"J!'!!B!"J)'!3B +#"J!'!!B""J!'!JB""J!'!JB!"J!'!!B!"J!'!!B!"J!'!JB""J%'!!B""J!'!!B +!"J!'!!B!"J!'!!B!"J!'!3B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B +!"J!'!JB""J)'!3B!"J%'!!B!"J!'!!B!"J%'!!B!"J)'!!B!"J%'!!B!"J!'!!B +!"J!'!!B""J!'!!B!"J!'!!B!"J)'!JB""J!'!*!$"J!'!!B!"J!'!!B!"J!'!!B +!"J!'!3B""J%'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B +#"J!'!!B!"J!'!3B""J!'!!B!"J!'!!B$"J!'!!B!"J!'!!B$"J!'!!B!"J!'!!B +!"J)'!!B!"J!'!!B!"J-'!!B!"J-'!!B!"J-'!JB#"J)'!!B!"J)'!!B!"J!'!!B +!"J!'!JB$"J-'!JB!"J!'!!B$"J!'!!B!"J-'!!B!"J!'!!B!"J!'!!B!"J!'!!B +!"J!'!!B!"J!'!!B!"J!'!!B""J%'!`B!"J!'!!B""J!'!JB!"J!'!!B""J!'rrm +!!![HN!!!N!6r!!F!!2rp!!F!$`6P!!`!!`#3!d)!N$`i!*!-"S!!N!99UeBL8!( +i$P%)%!)!#)T`"`"`!F%&!!#N!!S)%2i$rrJ!N!dJ!*"!"84!!*!%#P!!!!`!!!X +!N!-JJ!!!!IiL8!&S#P%)%!)!#)T3"3"3!8%&!!#N!!S)%2i$rrJ!N!N$`!!!)!! +!#Q!!!"!!$!#3(("`!*!3(!#3"!B!N!4%J!#3#"!!N!BJJ!"9UeBL8!&S#P%)%!) +!#)T3"3"3!8%&!!#N!!S)%2i$rrJ!N!8i!"J!p#!!!#!!!!f3!!$915a5)!!#jFi +AcIFi!!(!1mlhrZM`aK',[1mlmBaM(mJ5!)%!"!B)6!#3#5TVJ#)!L3%!J+Fli(X +!JL!1L!dI%%L%f,h%!#++!!!"rL*3!@J+83J3!J!)LP!&!&!"338!!+3!#JJ3rJ2 +rq!li2J!!%FiJ!I`J!#!J!`!j)(hIeV*5U!!$(M%d%"M%##)J4M'-)4LJbKZ-BaM +%NBaM%-J9!%%!"!J)6$!!N!5!!*!$+V4845K*!T4,@-B!T*4&%9')%+L3!*%*D-B +N!#55!&@V9L*3!@J+83J3!J!)LP!&!&!"338!!+3!#JJ3rJ2rq"&))J!ENM%J"I` +J"%`J")!T6d698Y*KF3!&&#&8)"M%%"![4M'-)3LJdKA-BaM!NBaM%-3BJ!%!"!J +)""!!N!5!!*!$+J4!!!!'!*!$#-B!S!#3!a'*%IL3!!!!$-BJ!!JJ!!!"rL*3!@J ++83J3!J!)LP!&!&!"338!!+3!#JJ3rJ2rqh&!%!!N1M%3"I`r)T)N")!Trd5&-G3 +KF3!&0#DA[#G'TmK3ap#-)3LJiK'XBaM!NBa9%833!"rR2Gcr6*pjhRfGdBeM(kS +%)ZHplh1Fj*M'$U1Fk-BaLj!!5,RcSfV'*!!@5PT9UeBq8(p[qPm)%!)!#2TIrIr +IrhrP2i#Rq!Tr%2i$rrb54mMm4%BaH"hm)#&5)%Xi)!p%MjL))Dr!#94"q'*)aX! +%P[i`MldrS-)4R(dI1*'-5+*#%!!M'-BT'-dDaM'1BT'094&*"#-BaM'-Ba5BapA +mBaM'-Bejra)dBjQpa2rTQU8!!IrMhiaXBr(rN!@,aM"JaJ`3(m"rr%IrL2q3"2b +53S8N4%IaMZ[m2rS`2l"m)!p%K498)5%2LC5"%'*)[#I)PXB`M#%BS1)4M'%BK*' +-9%4#%!!M'%IT'-iDaM'-A*'054)U"#2iaM'(rr5IrKHNBaM'-Bd35")dBaL!#)" +"+d,9UeBq8[p[IJm3!#)!#2Tqrr[IrhrJ2j3(r3Tr#2rrr!0a3SNN4%BaM@[m)#3 +4)%Kq)!p%!"@bS3%!%48"%'*)K"!3&mB`M#%BU0)4M'%BK*'0BNK"%!!M'%B*'-d +DaM'-!T'0543U"#-)aM'%)35BaK5NBaM'-Bd554)dBaMrm)"#Id+!!IiL8SPT3!! +3!#)!#)S#J!T3!8!!""3!43S)#2rrr!!43T%N4%BUMZ[m2b$a*,"pS!p%J&Da%J! +384B4&'*)LSJJN!"'-B`K'+M+%BaK'-549Z*)34!!*aM'+4M-QXBaM#+6998B+J4 +R'FjcM'%8Q-B9T'-CcM'08NZ5G'FBJ"%!"!UP9DY@)P+*D8!!%!!L!!L+!S!+8!& +!!!38!%8+#!Mrrr`!%8+M*-3k+SJVr#!(%-!!1'!!4)!k6T)!%'$RlK1F4c+!!)p +(c[IJk2G(mBZJk,L1*'*2`*!!Ia[R2FMic&V&hR`FE5+LrkS$QZDeVA1Hj*M(lVZ +FjVAZFla*%E1E')!1!!m+@J!"rL*5L@P!!"!!)J!)LJ+!#P!"3!!%&!"&#JJ)rrr +m!"C#[XG#%GY`(IrJq"!!N!-J!(d!%!!-!"!J!*!'J!#3$%!!N!9`m!#3"4!)!!! +3#!#3""!F!3#3"#!!N!NJ!3!"%!#3#9@V9L*5L@P!!"!!)J!)LJ+!#P!"3!!%&!" +&#JJ)rrrm!"!!!!3!%!!!%IJ!!"!!N!XJ!*!'!3#3$5!!N!X"%!J!!"!)!*!$!4! +!!3#3"#!!N!NJ!!!"i!#3#J(q)P+*D8!!%!!L!!L+!S!+8!&!!!38!%8+#!Mrrr` +!N!3%!$J!!"!!N!-3!*!Yi$!!N!MJ!!)!N!4!!*!)!F!!N!e9UeBL8SRj`!!3!#) +!#)S$J!j`!F!!""3!43S)#2rrr!#3$4!!N%X"!!3!#3!1!"-!'3!D!"d!)!!P!#S +!,!!a!$)!0`!m!$i!3`")!%d!8J"A!&`!B3"Q!'F!D3"Y!()!GJ"l!)%!KJ#,!*! +!!*8!QJ#I!+3!U3#X!,%!YJ#l!-!!a3$+!-m!e!$C!0i!i`$S!1d!mJ$h!2`"N!- +%!3N"$!%4!4J"'J%I!53"+3%Z!6-"0`%m!8%"3J&&!8S"6!&4!9B"@`&J!@8"DJ& +[!A-"H!&p!B)"K`'-!C%"P!'9!CJ"R3'G!D)"T`'X!E%"YJ'l!F!"a3(+!Fm"e!( +A!GS"h!(K!HB"k`(`!I8"qJ(r!J3##3)1!K-#'!)G!L)#*`)X!M%#0J)l!Md#3J* +(!N`#83*@!PX#B!*P!QS#F!*f!RF#I!+"!SJ#M`+@!TF#Q`+I!U3#U3+Y!V)#Y3+ +k!Vm#a!,)!X`#d!,A!Yi#iJ,T![!#p!,j![i$N!-+!a%$&J-G!b3$+`-b!cN$3!0 +&!dN$6305!eN$B!0N!fJ$E`0f!hS$IJ1&!iX$N!!$P31D!jm$T31U!l%$YJ1l!m! +$a32+!mm$e32E!q!$j32S!qX$l`2c!rJ$r33""!B%"`3-""!%&!3B""J%(`!(!!F +!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F +!"`!(!!F!"`!(!!F!"`-(!JF""`%(!3F!"`-(!JF#"`%(!3F#"`%(!`F""`%(!JF +""`%(!3F""`%(!3F""`%(!`F#"`%(!3F#"`%(!!F""`%(!3F""`%(!3F""`%(!JF +""`%(!3F""`%(!3F""`%(!3F""`%(!3F""`%(!3F""`%(!JF""`)(!3F!"`-(!3F +""`%(!3F""`)(!3F""`-(!3F""`)(!3F""`%(!3F""`%(!3F""`%(!3F""`%(!3F +""`)(!`F#"`%(!!!""`%(!3F""`%(!3F""`%(!3F""`%(!JF#"`)(!3F""`%(!3F +""`%(!3F""`%(!3F""`%(!3F""`%(!3F""`%(!3F$"`%(!3F""`%(!3F""`%(!3F +""`%(!3F$"`%(!3F!"`!(!!F$"`!(!!F!"`!(!!F!"`)(!!F!"`!(!!F!"`-(!!F +!"`-(!!F!"`-(!JF#"`)(!!F!"`)(!!F!"`!(!!F!"`!(!JF$"`-(!JF!"`!(!!F +$"`!(!!F!"`-(!!F""`%(!3F""`%(!3F""`!(!3F""`%(!3F""`%(!3F""`%(!3F +#"`)(!`F!"`%(!3F""`%(!`F""`!(!!F""`!"!!Irr`#3!d)!m!#A!*![!3!"!!N +!!%Z*!!`!!%Z-!*!$&J!+@APEDeae9QKAEeKX8f*8DP9Z8L`!N!-@!!TC@9Y,A&9 +@5&G[@%a63P4+98j5,!#3!d*J!!#B!*![!3!"!!N!!$J*!!`!!$J-!!!)`T!!!*! +%l`!+!!$rpJ!+!!`$C`!+!!)!N!-d!*!a!i"0!*!G(i(!!*!'F"`(!(!!N$T83*C +5J!!"J!#3%J+J!*!%&S&!!*!%J!"3&!8!8!#3#383!-$!!!#!!*!A!FB!N!i$J!1 +!!!!*#"C!N3'3!&*%"54!6!!i!!(Ki!#3#4D"6J#3!`d!!&!8"3"3!!&93!!!$c` +!hlRp*58!!,PhaI0pcJ!"MK21jrZM$')1AHGjhiaJaMp#J))!3-)6'!#3!`3!N!- +&65%GqA43P@Q"#UCYT#UD3URb3d32FK)ALd!qGU!!L$2rP[P4!!#J#3!!9j3&!&! +!!TC!)N!I`rM99NP'%K!"4iL0"!Ba""*4%M'84'--SajM'-BNM'$')b0!3J""!J% +)!*!$"!#3!`9@)5-CM%!!N!Y5j%(9MFc+h!43L!3N9)NTGXpJJ$3!%35!A2B&JGJ +!!UU)8!qI``L2dP##(j!!!88*&HJ+-D[SCUS`M%3M$5+YBaM'")a9+88L!"ZCfjq +h,fjZHhmaJaRe3(+K&BaGhGhCQC[fjQCQQCP09$[eM5d+U$j3QU4#r*5*4ZaJ[NL +J%lL%cF2mr`YJ!*!$LM"I``L&1EP5%Rcb441N(`R2%!5UUp#2G2m1)NeMk2R%LT8 +3L4)!"QCP*P0-QCQFK5T8U5JJFU(9M'D3"@95QC!&38j(pEA0#SJ)r+JIJ55N5AD +[i-PC2k&&5Aer$F2FN!!!!$m'-2r$#)!8CL)9%!*&)(iBNL%,k5Vq-)a%BidL$1- +)d#5+LLL4%J!HBRdQ8ibCQCKP+P4*48$ri41-CT!$Brrp8TQ3"3&81qq0,-J!2T! +!bU4#r+5*&UJ46fSLS6P5"3(GIP6rr!!!LM"r``J!9+C5%"!%484&'*)L""!R4M' +84'1-SJcM#XSNL3T%N3S!*QCK*P0-QCQB&53SUB9!M'-6M'D3"#)K8TQ3"3$NKF@ ++%K!!%4#)"#3NT5N@U!T)5Q*"3LN&!&8!9)!!!!K5,jr$#)!j'BNJ!3`jqi6R%Fb +J!4"(cZI$Sh4q$&d(4F4a#N5I#MmIQGNH8bbCERMLj#NAp8#-AI&cRGhGfGQG8TC +QCRGh!%p%"E(Ki!!"(h+rrbGEk4Di'ckaS%%$j)F!93"6i!#3!b(SRm2i!"!!!-! +"!*!()!!1!*!*!3#3"3''!*!%"!)!!!J3!*!$!31!!!J!N!8)!*!+1!#3#J3!!"q +!!*!%!3#3"&F!F!#3"5!IrJ#3"J)!N!G!!*!A'!`!!!J3!*!$"J#3!a!!N!83!*! +9"!#3#!)!N!4`!*!'!F!!N%J"!!3!#3!1!"B!(3!H!#%!*!!T!#i!-!!d!$8!13! +q!%!!43"+!%m!9!"C!&i!B`"S!'N!D`"Z!(-!GJ"k!)%!KJ#,!*!!!*8!Q3#G!+) +!T`#S!+d!XJ#f!,d!`J$(!-`!d3$@!0X!i!$P!1S!m3$f!2X!r`'3!`8""`%+!4! +"%J%@!4S"(J%L!5B"+J%Z!6)"0!%h!6X"23&%!8J"6!&3!93"@!&F!9m"B`&S!@m +"G!&i!A`"I`'!!B-"L!')!Bd"NJ'A!CX"S!'P!DS"VJ'b!EB"ZJ'q!F)"aJ(+!Fi +"dJ(@!GJ"fJ(G!H!"j!(S!H`"m!(d!IJ"r!)!!J3##!),!Jm#&!)C!Ki#)`)S!Ld +#03)p!N8#4`*+!Nm#9`*H!Q-#D!*X!R!#G3*k!Ri#J`+*!Si#N3+9!TS#S3+S!Ui +#XJ+c!VF#[J,"!XB#b`,4!Y8#f3,I!Z8#k3,[![8#r!-!!`B$#J-1!a!$%J-A!ai +$)`-V!bX$+`-V!bX$+`-V!bX$+`-V!bX$+`-V!bX$+`-V!bX$+`-V!bX$+`-a!cF +$2J#3$2q3"JB'rj!'!!$rN"`!"rq3"J-$!3-""3%(!!B!#3!)!3-!"!!%!3F!"J% +%!!8"!`%'!!B""J!'!!B!"J!'!!B!"J!'!!B#"!%%!38!"J%&!3B!#!%(!!B!"J! +'!!8!"3!'!!B"!`!'!!B!"3!)!!B!"J!'!!B!"J!'!!B!"J!'!!J!"J!'!!8""!% +'!33!"!!'!!-!"3!&!!8!"3!&!!3!"3!&!!-!"!!&!!-!#!!&!!8!"3!&!!8!"3! +%!!8!"J!)!!B!"J!&!!3!!J!%!!B!N!-'!3F!"J!&!!B!"J!'!!8!"3!&!!8!"3! +&!!8!"3!&!!8!"3!$!!-!"!!%!!8!"3!&!!8!"3!&!!8!"3!&!!8!"!!&!!B!"J! +'!!B!"J!'!!N!#3!*!33!"!!'!!N!"`%+!!B!"3!&!!B!"J!&!!B!"`-)!J8""3! +&!!J"#3!'!3B"!`!&!!J""3!'!3F!#!!)!3J!"J!(!`F!"J!*!!J!"3!(!3F#"`% +%!33!"J!)!!B!#Iq3+!!'!!B!"`#3"!XQN!!!N!6[!!m!!2rd!!m!$`5C!!`!!`! +"!$i!N$Y`!6)!N!3'!*!@!93!N!8IJ1!!N!S1!$J!N!X&!*!k+)J#6**!!!!*!*! +G&S#J!*!($RcJ#J!S!*!)m!!!"3!%!!!`!!!%!*!G"``!N"%(!!#)!*!$"#%!f3# +))"N'L33$4))"!*!,!93!N!8@r+!!N!3-!!!+4+!+!#J!!!P+J!!$!I[!!!A46Rj +K55!!"-6[`Ajhlc`!!2!!MjlcrhSB--)1,hchchq'$!Bar38!3)!#!`36$!#3"!) +!N!3+Q4"alq,d+"+9CJ%%8UEE%)T9L%8VX!ai!mi!!(4D!(jk!!!4!-rrPX5RJ!! +%J!L!!!TFS!S!+!!!%Nb!"%B"r#r`"GIeNT&)`!!*,4#$3)!``J!"#H#)BBS3KKJ +a3ai`````L)B-"M%-KS!JJ!)%"!%%!*!%!J#3"!UQ%#)BB``J!*!0!8N5K!94(Ki +Qi!#JK93!#J!N84EdU%!!N!-4!#!+8+!+!#J!!"+9!%!-!I`S%!@#P*5JKr)!#KB +4"8%!8-)%%3S45'#'%))B-N+Y-----!L'$%94&)3!$[1HlRfh&XeRHIGh4M%BaqU +!+&))8``ZFjcR1FjcT5XjcR1M'-9,N!#"k9%K)59!!+#-!)5I4")4&T5`,Z1NJ"% +!)!T3TrS!+1i!N!-3T&rer#J3"Br-D%#%`J!5&"-*II"23dJ)&1P2S)B3JKJd3Nd +`````#)8558S84!!4M'-8MP-R-jM'1)T'-4M%+S!S8JK6$$'-BaM'-BaP,-BaM'- +Ba693HrP5A-bN3"%JP95)4%4a%ADAX$%84)!MXP!+8+3EJ1m4!*!$!44rrI`S%!@ +&"K#JK5qI%K3JN3-)N!$#%q3P+LKJKpkIq$K#$,$p$mm)K4+SLL4%!!q-)a5-8dB +M'-B`JNBUT8453%5+$dX-,h[Hpm)aM'8SaM'-BaM%"6L(q9&5d)!"qIbN!r!r4*! +!N8D@-#m8b2`K6&#Edlpiri-4!*!$IJarqI`S%!@!"5d8K!)!)K4!B3-)N!#q)!* +&+LKJKK#''$4#$,$"$3#)K++T4%3N!"'-)r5-8iBM'-B`FN9+SN5+J%5+#%X--Ba +M'-2rrq8SaM'-BaM%"4#(p9$Fd)!!)L$&9)K%44%4GTIS8I93KN%!L5M5#8["lar +ri!!#$%2jr#J3"B!&8`L%!J!L&)"rJ`N3JK!%42IiB)B3KK`b3Ja``3b!L)5K%84 +%*!!4M#-%M&0')aM'-!T&4%9&#S$rrJK($$'-BaM#%)3P+-BaM'-Ba!83Hr23dXb +!!%)JK!#%K%85%4D8#&%'8B9"-ST2mrP+IbN3!*!$%44'(r`S%!8!&C-85!!!358 +)J8-*%)3,k!)%'''+%)BF-8)-F-%X8)L%34)NK"3!%BaM&)a6*L-BaM#+6)4)aJU +!J`BB4``aM'-BaM'-C5M'-BaR1F`&83AK85%K!!(m)B98!!4&*&%@R!54&&'!J8d +&)!!"5J!T%3#3"+4)!I`S%!@!$ScL5!!J`-Ih!6ca$cP%%%(%(jlcm(SEd2i-,d$ +d,`Ki34)Nr"4rMr1Hj(a6&L-AHI"aY)4)[qU!J`A[`[22HplhZFjcT5LjcR1DeV3 +$[S3"GKiH!!#%2RJ$rq4kcp%@J!c1kik!J3(mN!!!!8S!+1i!N!4$`!(m,r!&!!3 +!!$!!)!#3#%!!N!i)!*!'"J`!N!8)!J#3!d!J!*!%"!F!N!0!!*!'%!#3#J%!H!# +3#!&8!!"!!!!@J!#3"3%!N!3"5J!S!*!'3!!(i!!&!*!'3!#3#)!!N"b)!J#3!d! +J!*!%4!#3"#!!N!BJ!*!CJ!!!&S!!N!8"!*!%!FS!+!#3"34!!*!%"3#3,(!-!*! +*1!#3"%!!N"`"9!#3"4q!!*!&!J#3"3i!1!#3"31!!*!%"3#343%!"!!,!"!!&`! +I!#!!)`!Q!#`!-3!c!$J!13!q!%3!4J"-!&)!@3"I!'8!D`"a!(F!H!"k!(i!J`# +(!)d!P3#F!+)!U!#Z!,-!Z!#q!-3!a3$,!0%!eJ$G!1-!k3$[!28!q`'3!`J"$J% +9!4i")`%S!5d",`%d!6B"13&"!8-"5!&0!9)"9`&F!@!"C3&U!@`"E`&d!AB"I`' +%!BN"MJ'6!CJ"R3'K!DB"U`'d!EN"[J($!FB"a`(+!G!"d!(A!Gi"j!(T!Hm"p3( +l!J!#"3)+!Jm#&!)C!Ki#)`)S!Ld#-J)d!MB#13)m!N%#4J*,!P!#93*D!Pm#C!* +T!Qi#F3*e!RS#J!+'!S`#NJ+C!U%#U3+b!V3#Y`+p!XF#c`,@!YX#h`,M!ZJ#l`, +d![S$!3-'!`N$$J-6!aX$*!-V!c!$-3-f!ci$330(!di$9!0C!ei$C30X!h%$H!0 +r!iJ$M!16!jJ$R31I!k%$TJ1Y!l)$[`1r!lm$[`1r!lm$[`1r!lm$[`1r!lm$[`1 +r!lm$[`1r!lm$[`1r!lm$a32,!p8!!2rr!*!)rj!'#!MrN!B!!2q3*!3%!3-""3% +*!3F"#3!*!3-""3%&!3J""`%%!3F"!`%(!3J$#!%)!3J"#!%)!3J"#!%)!3J"!`% +%!3B""`%'!3J"#J%*!3J"#!%)!3F""`%)!3J#"3!(!3J""`%*!3J"#!%)!3J"#!% +)!!J"#!%*!3X""`%(!3F""!%(!33""!!)!33""`%(!3F""`%(!3B""`%(!38""J% +(!38"#`%(!3F""`%(!3B""`%'!3F""`%,!3F""`%(!38"!`%&!3J!!!%*!3N"#!% +(!3J"#!%)!3F""`%(!3F""`%(!3F""`%(!3F""`)&!38""3%&!3F""`%(!3F""`% +(!3F""`%(!3F""3%'!3F"#!%)!3J"#!%*!3S"#J%,!33""3%)!3`!#!!,!3F""J% +'!3F"#3%(!3J"#3)+!38!"J!'!3S"#`!(!3J#"!%(!3S""3%)!3N"#!%)!JS!#!% +*!JN"#!--!3X""J%*!3F""`%%!33""`%*!3J"$rq3+!)*!JN!#VEE!*!$4!#3#3J +!$!"k!%%!HJ!-!!J!N"-)!!`!IJ"r!(i!$!!)!*!,"`!*!*!$4!#3%J(!!8!"3!G +`!L!"3!#!!*!5!F!"`!(!"r!$i!(!!)!!#3!)!*!$4!#3#K!!-!"H!))!AJ!`!"! +!N"-3!$!!IJ$q!(i!-!!3!*!+#!!'!*!$4!#3&4!!+3!A!!N!#3!I!*!9%!!j!"m +!$`!2!"m!#`!,!*!$4!#3&!J!P!$S!*!!!*!!!2J!N"8)!*`!q!$`!2!!q!!!#`! +%!*!$42J!N!!!N!!!k!#8!!J!N"Ai!2!!m!$i!*`!#!#3&J3!"!#3!d3!N!32m!J +3#"!)%!J3#"!)%!J3#"!)%!r`!*!)$r!Iq"L3%Kri$r!!N!8(!!F!N!0%!3!#J!4 +!$Z!#J!+!!i!!N")"!!1!"m!2i!1!!i!$J!#3%`B!"`#3!d3!(`!*!!N!&`!T!"! +!N"8I!!m!$`!I!$N!%!#3&33!#`#3!b!!-!!3!8)"l3!%!*!)#d4eEQGPEfiJ6@& +`+!S!N!-f0DP6G'PMD(4TEQFJ6@&dD'9YBA4TFf0S)%0PER4bG@dX)%&YFh4PFQ4 +KE5`J-6Ni0G!a1C!$!*!$J!$rN!6`!*!$m!#3!rm!N!2`!*!$r2!!!2!!N!2rr`! +!m!#3"!m!!2!!N!32!!$`!2rr!!m!!2!2!3(`$`!!m2!Im"m2!!$`mI%2N!-!!2# +3!amI$`!!m2%2rr!2!!$`$a#3!`m!!2!!rrr`$`!!m!#3"!m!!2q3"J#3")!!rj! +%m!#3!r!!N!2r!*!$m!#3!rc`!!$`!*!$rrm!!2!!N!32!!$`!2rr!!m!!2!2%"$ +`$`!!m2(a$j!$!!$`N!-I(`m!!2$a!3%2$`!!m!m3%2!2!!$`$`ram!m!!2!2%"$ +`$`!!m!$rr`!2!!$`!*!%$`!!rj!'!*!%3$rJ)$!J+#!m)!3J"#2%*#3TP#T8+P3 +Tj#3%)q3J"$rm2q!rm$ri2r`rr$rm2r`rr$rm2r`rr$rm2r`rr$rm2r`!N!0!2q! +J-#!S)$`J"#2%*#3U9#T8+"3N*#@N*#3Ma#!%2r`ri$r`2rJrr$rm2r`rr$rm2r` +rr$rm2r`rr$rm2r`rr!!!!3!2rr`!#!!'!!J1"3!*N35!#FL%3!MS4#!)H%I`#6p +!%!VmJ"!+(J!3#KF!%!N6J"!)LF!3#($J%!J!F"!)!$J3#!!B%!J!!"!)!!!3#!! +!%!J$`"!)"#!3#!Q3!"!)#P!3#!T3%!J*i"!)"!!3#!2J%!J!!"!)!!!3#!!!%!r +rrr!2rr`!$rrq!!rrr`!2rrq!$rrr`!rrrq!2rrr`$rrrm!rrrr!2rrr`$rrrm!r rrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!r -rrr!2rrr`$rrrm!rrrr!2rrr`!!!#!*!Arrr`!*!-ra!3(r!!N!F2!*!$m3'3!`m -!N!F2r`!!$a#3"2!!N!Ilm!!2!C!%m!#3"rZr!!m3N!3I!*!($l[`$`'3"!m!N!M -l[rm3N!3I!*!)$l[a!C!%$`#3#IZr%*!%(`#3"[m!!2qlmIrrm3m!N!82%2rr%2Z -rm!!2m!#3"3m"N!32Zr!!N!J2%*!&qlm!N!J2!C!&rl[`!*!($a#3""m!qlm!N!F -2!C!%$`!2Zr!!N!I`%*!$(`!!qlm!N!Ia!C!$$`!!$l[`!*!'$a#3"2!!!2Zr!*! -(r`%"$r!!!!qlm!#3"rrrm!#3"2Zr!*!1$l[`!*!1qlm!N!i2Zr!!N!ll[`#3$Jq -lm!#3$[Zr!*!1$l[`!*!1qr!!N!i2!*!$!J#3!rq3#3#3"r!!N!F2m!#3"[!!N!2 -rm!!!$mm!N!E`$r!2%"m!!!r-m!#3"I!2[`$a!I!!$mc2!*!&m!$lm2!3(`!2c-c -`!*!%m!!2[r%"$`!2rj!$!*!%m!m!qrrr(`#3"!m!N!6`m2rr[`$`!*!%$`#3"2$ -a!3rlm!#3"3m!N!6`m"!I$lm!N!82!*!%m!m"$`$lm!#3"!m!N!6`!2!3m!qr!*! -%$`#3"2!!$rm!!2[`!*!$$`#3"2!!N!82[`#3!`m!N!6`!*!'qr!!!!m!N!6`!*! -'$r!!!!m!N!6`!!r`!*!($`#3"2!!m!m!N!F2!*!%m!m2m2!!N!B2!*!%m!m2m2! -2rj!$m!!2!*!%m!$`$`#3"`m!N!6`!!r`!*!($`#3"2!!N!S2!*!%m!!2m!#3"`m -!N!6`!2!2!*!($`#3"2!2!!$`!*!'$`#3"2!2!!$`$r$rN!2`$`#3"2!!m!m!N!F -2!*!%m!!2m!#3"`m!N!6`!*!+$`#3"2q3$!#3"3`!@J"Z!1i"NJ#"4%3!N!0-!!) -!N!9i!-B!LJ%3"!*25`#3"3S!4J"c!4#)(%0[G@aN)'j[G#"H-L"LC@0KGA0P)&i -`,L!JAM%!N!8+!"3!+J!dS!)!N!3"!!rrr!!)!!B!#!i&!!Q4")!*b)4!#1K%)!K -i4r!*2d!3#[b!%!SH!"!+&`!3#41!%!L*`"!)F1!3#!"`%!J!1"!)!"J3#C6'8!T -9+9!+95P3#P8T8!T9+9!*P-C3#!!!%!TP-C!!#T9+8!U95P!+P8T3#T9+8!TP-C! -!#!!!%!rrrr!2rr`!$rrq!!rrr`!2rrq!$rrr`!rrrq!2rrr`$rrrm!rrrr!2rrr -`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr -`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!#3!d!ri#! -`)#JJ2#!%*+3UT#UN*+3J"#NN+U3UT#NN)!3rr$rJ2r!rq$rm2r`rr$rm2r`rr$r -m2r`rr$rm2r`rr$rm!!!#!*!$rj!*!*!(m!#3"`r`!*!'m!#3!rr`!!!2c`#3"[! -2m!m3(`!!$mc`!*!&m!qr!2%"m!!2c-m!N!A`!2[`m"!I!!r-c2!!N!6`!!qrm3% -2!!rrN!-!N!6`$`$lrrmI!*!%$`#3"2$`rrqr!2!!N!32!*!%m2%"$r[`!*!&$`# -3"2$`%"m2[`#3"3m!N!6`$`%2!2[`!*!%$`#3"2!!m"$`$lm!N!32!*!%m!!2r`! -!qr!!N!-2!*!%m!#3"3qr!*!$$`#3"2!!N!Elm!!!$`#3"2!!N!B2m!!!$`#3"2! -2m!m2!2m!$r!2$`#3"2$`$j!%!2$`$j!$!*!%m2!2N!3!m2!2N!-!N!6`m!q3"!$ -`m!q3!`#3"2$`$j!%!2$`$j!$!*!%m!r`$`m!r`!2m!m2!*!%m!#3#Jm!N!6`m!r -`$`m!r`!2m!m!N!6`N!-2N!3!m2!2$`#3"2#3!`q3"!$`m!m2!*!%m*!$$j!%!2$ -`$`m!N!6`N!-2N!3!m2!2$`#3"2$`$r!2$`$r!!r`$`#3"2!!N!S2!*!%rj!-!*! -&)J!"!*!&8!&%!'3"IJ3#6dX!N!8'!$J!4J&mL!*H-!#3!aJ!@J"H!1J"T`!&!*! -*JJ!"F!S!N!-B!%)!A!$$!GF!"3#3#BF!!(!+!*!$'!"#!&`!``(A!!8!N!Q'!!" -`#J#3!aJ!3J"F!--"e`!&!*!*K3!!F!S!N!05!!3!N!9M!5d!G`&R"!0CCA-!N!C -M!1F!G`%K"!*1E`#3"3X!6!"8!@D)!Pi`!*!&$!!8!#`!0+!#!!%!N!9G!5J!I3& -)J!#3"'3!"3#3"@-",3"h!@F%!ePPF`#3"Q-!j`"h!5%%!Nj[!*!&B`#K!(F!f`3 -%8A9TG!#3"3X!6!"8!@D)!Pi`!*!&$!!8!#`!0+!#!!%!N!9G!5J!I3&)J!#3"(B -!"J#3"@-",3"h!@F%!ePPF`#3"Q-!j`"h!5%%!Nj[!*!&B`#K!(F!f`3$3@aX!*! -'B`"E!(F!P33%8A9TG!#3"3X!6!"8!@D)!Pi`!*!&$!!8!#`!0+!#!!%!N!9I!5N -!I`&*J!#3""J!3J"F!--"e`!&!*!*L!!!F!S!N!1%!!F!N!9M!5d!G`&R"!0CCA- -!N!CM!1F!G`%K"!*1E`#3"@-!S3"h!0Z3!!#3"Q-!@`"h!*8%!d&XE(3!N!9M!"8 -!G`"2"!44G@Pd!*!&#`"-!&3"CSJ#AM!!N!8-!"3!,!!dS!)!!3#3"9i"+!"q!8L -!!*!%BJ!&!*!&DJ$j!(i"-`3#6dX!N!9U!+8!IJ$I"!C$B@jMC@`!N!8+!&8!1J% -lL!*H-!#3"83!9`"8!6B3!*!'#J!F!#S!2+!#!!%!N!9N!23!K!%8J!#3""J![!# -D!4X"F`!&!*!*L3!!D!S!N!0X!!8!N!9#!%d!9J#("!*25`#3"8)!#`"@!%8%"N0 -KEQ0PE!#3"3F!0!!h!05)!Pi`!*!&4!#B!&3!c"!*4@4TG#"8CAKd!*!'#!!+!#J -!+U!#!!%!N!8p!%N!A3"TJ!#3")!!rj!%m!#3!r!!N!2r!*!$m!#3!rc`!!$`!*! -$rrm!!2!!N!32!!$`$`$`m!m!!2#3"3m!!2#3"3m!!2!2!2$`$`!!m!#3"!m!!2$ -`$`$`$`!!m*!&$`!!m*!&$`!!m2!2!2!2!!$`!*!%$`!!rj!'!*!$#BL3!!#3"2i -!"J!!rrF!"J!,!lX!#3!#!*!$2`#3-pJ!N!B833#3"5P!!!!`!!!D!!!#'%!&DeL -*3!IJ183JJ%!%PF"`(!(#&!!9!"3JMm$rm!(i!*!$Fi!J!*!&)!!!$Q!"!"!!N#p -`!&#)!KJ%!3+!SJ!%!JL!!!"J!%%L%f`!!!)SJ!!"q)P!"D!T4##!3!593&!8!8) -8!"8!&##2`2r`$3J!N!-N3&!#mm!!"#!$!!Q3!!E91Ha-)!!&bj`[Zqj`!!jc[1p -rlSm-B4Llc[1r'-BaraS#"!!3'#%``!#3!`)!N!5TV[N8S53+8+eFli(U844&1L# -8I%*%*D,X3!**)!9V@)P!"D!T4##!3!593&!8!8)8!"8!&##2`2r`%`!q!$CdA%! -&r#!5'L!%J!NJp0r@XT+T!!BmBQK!-BJJNBaM'-)4LJbK[-BaM%NBa9%0$3%%!"! -J)""!!*!$!J#3"+V4q!!!'!#3!b-B!S!!N!0'*)+L3!!!-c)!!US!!!(iL8!&S#P -%))"!"*9!8"3"3K3!&3!8))r!rr!M!")!#DaL)$hm2j%U*!bi18#9K9,8)A%!#QK -#VhJaM9p"l'-)`K#+$5&DaM'-#4M%N45)!(qFph2p-ReRHICraM@-IUJ38jlh[Fj -cNQ-B1SjcSaM',ZILjmk0Uc*!!99J"@YBq8(p[qPm))"!"29rhrIrIjAi&IJ9q)r -!rrGP"mMmL+rLlF[m)(c))(0m+IkAMlP))Dr2LUL0)-41L)!LVrd)qp2k$L%Cap( -cL4M%LL5)!)aM'+4M0'ZBaMQ#4M9843339'-BaM'-8Rrr9p'-BaM'0B%m50'1CZb -2rKPTN!!"ripq-E'2arq3"*Fc$$--)(i(rbIq*rq3!rLP!S88L+aM'X[m2j%S2iK -m3!k3!)89Y5%K!"-T!r$%NAKI424M#-)4LSdK'-B4L%NBe)4%5!#-B4qNBcaV'-B -`FNBe*%LS%(IM'-BIrp*M'(k4M'-BaM5(j%M4M')"#!3KmNeV@2P,rEhi2%!#3!6 -eprphrhq"q8(p&IK2rr`)S`+*&)KdBah6r#!5'#"`Id!1N!!!9V)5!3!5+L)Sa*% -)))#%BaM#%BU-S4M'%Ba*&@e%K%J!R'%B*'-bDaM'-!T09943U"%N*cR1%)35BaK -5NBaR1-BeL5j*dCaMraJ%3(*)!IL*5L@P!!"!!N!%P"3"9!&!!#&!*43J6rrm#+- -#Na5)*&838r`rJ!JNJ$L!!*!!J$T0$!!3BFrF*cL1G3!%G(c[IJk2G(mBZJk,L1* -'*2iir'qHpk2M-@XAHI$aY)U,rUJ1)pV@YHpldQ-IhZjcQYHjc[%N4XjXBJ$J!(" -TP@YBL8SPT3!!3!*!"*38!93"3!!K3#88)%rrr!GY!VlR5(1fi$hm)(rj)!!!J!$ -`!"!!N!-3)!#3"3%!N!`"!*!')!#3"8!J!!"!)!#3"%"`!R!!N!1!!*!*J!3!"N! -!N!N"q)P+*D8!!%!#3!58&!&8!8!!)8!P&#"2rr`!)!!!"!#3"#(ri!!*)!#3#L! -!N!B#!*!B!i$!!!"!)!#3!`1!!!3!N!-"!*!*"`#3!`'!!*!)"@YBL8SRj`!!3!* -!"*3F!G`"`!!K3#88)%rrr!#3"!3!N!4!!*!$#-!!N%S"!!3!#3!1!"-!'!!D!"d -!)!!P!#S!,!!a!$)!0J!l!$d!3J"(!%`!83"@!&X!B!"P!'B!D!"V!(!!F`"i!(d -!JJ#(!)`!N3#@!*X!S!#P!+J!V3#b!,F![!$"!-B!b`$3!08!fJ$I!13!k3$Z!2- -!q!$p!2m"!`%&!3J"$J%3!48"'J%I!53"+3%Y!6)"0`%i!6X"3!&#!8F"6!&4!9B -"@`&J!@8"D3&Z!A-"H!&p!B)"K`'+!BX"MJ'6!C-"Q!'G!D)"T`'X!E%"YJ'l!F! -"a3(+!Fd"d!(5!GF"h!(K!HB"k`(`!I8"qJ(r!J3##3)1!K-#'!)G!L)#*`)X!M% -#-`)i!Md#3J*(!NX#6`*8!PN#AJ*N!QS#D`*`!R8#HJ*r!S3#K3+*!Sd#NJ+A!TX -#S!+M!UJ#V3+b!VB#ZJ+p!X-#b3,-!Y)#f!,E!Ym#i`,R!Zd#m`,h![d$N!-*!`m -$&3-E!am$)J-P!bN$,`-e!cN$2!0#!dJ$5`01!e3$@J0I!f8$DJ0[!h8$HJ1!!i8 -$LJ12!j3$Q31I!k8$U`1a!lB$Z31m!lm$``2)!md$d32@!pF$h!2J!q3$j`2Y!!B -!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B -!"J!'!!B!"J!'!!B!"T!$!JB""J!'!!B!"J!'!JB""J)'!!B!"J%'!!B#"J%'!!B -#"J!'!!B!"J!'!!B!"J!'!!B#"J%'!3B!"J%'!!B!"J!'!!B!"J!'!!B!"J!'!!B -""J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B#"J%'!JB""J!'!3B -!"J!'!!B!"J!'!3B!"J!'!JB!"J!'!3B!"J!'!!B!"J!'!!B!"J%'!!B!"J!'!!B -!"J!'!JB#"J%'!!B!N!-'!!B!"J!'!!B!"J!'!!B!"J!'!!B""J%'!3B!"J!'!!B -!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J)'!!B!"J!'!!B""J%'!!B -!"J!'!!B!"J-'!!B!"J!'!!B!"J-'!!B!"J!'!!B!"J!'!JB!"J!'!!B!"J!'!`B -!"J!'!`B!"J!'!`B#"J)'!JB!"J!'!JB!"J!'!!B!"J!'!!B#"J-'!`B#"J!'!!B -!"J-'!!B!"J!'!`B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B -!"J%'!3B$"J!'!!B!"J%'!!B#"J!'!!B!"J%'!!Err`!!#pk3!!#3"2m!"`!!rrd -!"`!2"18!$!!$!*!$3J#32$J!N!`'J!#3"9@V9L*3!IJ183J3!J!)LR!(!(!"`38 -!!+3!#JJ3rJ2rq!#3$5!!N%!&4%!!N!3+8!!!$!!!#`#3!b#!!!!"rL*3!@J+83J -3!J!)LP!&!&!"338!!+3!#JJ3rJ2rq!#3#32!!!!J!!!+B!!!%!!-!*!FF(!!N"! -F!*!%"J#3"%5!!*!)%!#3"L#!!&@V9L*3!@J+83J3!J!)LP!&!&!"338!!+3!#JJ -3rJ2rq!#3"6J!'!$d)!!!)!!!$C!!!08j,&)J!!,PcKI0pcJ!!F!lc[Iqk2$'%BZ -mlc[aM'-Ib")!J3!%"JK-!*!*+QZ!)J#*!3#!Tc[JH`##)!k)$4m35)6B[F3!)SS -!!!(q)P!"D!T4#"!#!!L+8!8!8!&""3!!T!!+#"$q!rri$[Jq!!!4cL!"r#!!)#! -$!$NJIGr@XP+S!!-H-633'-3))L"'-B`K'+$+'iaM'-54M'-3b"8!33!%#!K--!# -3")!!N!-UY&4&+%N#P%YBaJ#NP%848BJ3U*!!N3PSaL3!**)!9DY@)P!"D!T4#"! -#!!L+8!8!8!&""3!!T!!+#"$q!rri%8JL!"Z5-5!&r#!%6#!%J#P24095dQ&a!!8 -8)93J'-33%#p'-B`K#+$5&FaM'-#4M'-3a"L!!3!%#!J%%!#3")!!N!-U"%!!!!B -!N!-)aJ#J!*!$%BN4q*!!!!!-aL!!##!!!!(q)P!"D!T4#"!#!!L+8!8!8!&""3! -!T!!+#"$q!rrlF8!3!#3k-4!&r$mLNL3%J#Rr4)8ae#&a!!8d*THm*dDRb&$(d)` -K#+$L%DaM'-#4M&844"!!(qFph2p-RhRHICh4M@-IUJ3Ljlh[FjcNQ-B1SjcSaM' -,N!")ZI1MDXBN!"C+@P@V9Mj3IfrkA`J3!J!)qPrprprrIq8rJ+Ii#Rm3rJ2rr** -(b2a%4M&i(I`J)9)J5cJJ$d52Q)JKVm!*9%(iBNM'`!5@rM#2[6qJ`K'FI4miNBa -)SN)3!#-BaLNBc4V'-BjLNBe9%8N%)aM'-BaM&*M(eIaM'-BaMARr%M4MQEh%rqQ -DT3!"rq2IM'aMmIq3"B['-'$'$"!I`(rm4rq)rj!%r**#K54%4r'1kr`rqM!rX(` -J$d5&&93K)3q*P)%3BNLm*mL@aM#-)4LJiK'-B4L%NBa84%)3!#-B4qNBcKV'-Ba -FNBe*%LS%)rM'-BIrp*rq&k4M'-BaM4")%M4M')!)J%%V3Y@V9Mj5rfpq$a!!)J! -)qRlrqprrIq!rP!Ip#Rm)rrrm!h&#L54%4M'0Dr`J*"%J5(iJ$d3!&E+K!3!4&3% -3BNL%%"!AaM#-)4LSdK'-B4L%NBeL5%%3!#-B4JNBc4V'-B`#NBe*&#S%)`M'-B3 -K"*M'&+4M'-BaM4**%M4M'2r`J%*r3S!"rL*5L@P!!"!!)J!)LJ+!#P!"3!!%&!" -&#JJ)rrrm!"&#N54%4LU1kr`r)2%NX(fJ$d5!9V%5!""4&K%8BNL+L##3!%BaM#% -BU-S4M'%Ba*&@iNK"%!!R'-BT'-bDaM'-)T0994JU"'FCcR1-B45BaK@NBaR1-Be -55j*dCaL!%3!%#U99UeBL8SPT3!!3!#)!#)S#J!T3!8!!""3!43S)#2rrr!!43U- -Na$SUL#[m)!F3`!!iB!"%J$T1NJ!3B1IZ%ja(-S!!MdI1pq$SpdIaLk$SZ)iNBNr -!N!"r'qFpb2M-@XAHI"aY)U,rUJ1DjV@YFjlNQ-IZZjcQYHjc[%N4XjXBJ!i!$`T -D!!(q)P+*D8!!%!!L!!L+!S!+8!&!!!38!%8+#!Mrrr`!&N+qad)4fh!Grq$i%!# -3!b!!I3!3!!`!%#!!N!D!!*!-3!#3"A$`!*!&%!J!!"!)!*!%%"`"!*!%)!#3#5! -"!!%3!*!*9DY@)P+*D8!!%!!L!!L+!S!+8!&!!!38!%8+#!Mrrr`!%!!!"!!3!!! -4q!!!%!#3#b!!N!B"!*!0)!#3#`%3#!!!%!J!N!-"%!!"!*!%)!#3#5!!!!(J!*! -+!IiL8SPT3!!3!#)!#)S#J!T3!8!!""3!43S)#2rrr!#3"!3!1!!!%!#3!a!!N#h -J-!#3#1!!!J#3"%!!N!J"`!#3$9@V9L*5LIR!!"!!)J!)LJ1!$R!"`!!%&!"&#JJ -)rrrm!*!0%!#35`%!"!!*!!i!%`!C!"S!(3!J!#8!+J!X!$%!-J!h!$`!2J"$!%J -!63"5!&F!A!"K!'B!C`"T!'d!FJ"f!(X!J3#'!)X!N!!!P3#D!*m!T!#T!+`!X3# -f!,X!`!$&!-S!c`$8!0N!hJ$M!1J!l3$b!2F!r!'3!`3"#3%-!4%"'!%D!4m"*!% -T!5i"-`%h!6`"33&#!88"5J&-!9%"9J&E!@!"C3&U!@m"F`&i!Ad"JJ'(!B`"N3' -8!C8"Q!'G!Cd"SJ'R!D`"X3'f!EX"`!(&!FS"c`(8!GF"fJ(F!H%"jJ(V!I!"p3( -k!Im#"!)*!Ji#%`)B!Kd#)J)R!L`#-3)f!MX#23*#!NF#6!*4!PB#@`*J!Q8#DJ* -`!RB#G`*m!S%#L!+2!TB#P`+E!Tm#T!+T!Ud#XJ+e!VS#[`,%!XJ#c!,3!YF#hJ, -L!ZN#m!,d![N#rJ13!`S$%3-@!ad$*!-V!c)$130!!d8$5300!e)$@30J!f3$D!0 -[!hB$HJ0q!i8$L`13!!19!jS$R`1P!kS$X31f!lX$`!2&!mS$c`29!pX$i!2P!qJ -$k`2[!r-$q!2p"!%%"J3("!`%%!38""J%'!3I!!F!"`!(!!F!"`!(!!F!"`!(!!F -!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!`F -#"`%(!3F""`!(!`F#"`)(!3F""`)(!3F$"`%(!3F#"`%(!3F""`%(!3F""`%(!3F -$"`)(!3F""`)(!3F!"`%(!3F""`%(!3F""`%(!3F#"`%(!3F""`%(!3F""`%(!3F -""`%(!3F""`%(!3F""`%(!3F#"`%(!JF""`!(!`F""`%(!3F""`%(!JF""`%(!`F -""`%(!JF""`%(!3F""`%(!3F""`%(!3F""`%(!3F""`%(!JF$"`)(!3F!!!%(!3F -""`%(!3F""`%(!3F""`%(!3F#"`)(!JF""`%(!3F""`%(!3F""`%(!3F""`%(!3F -""`%(!3F""`%(!3F""`-(!3F""`%(!3F""`%(!3F""`%(!3F""`-(!3F""`!(!!F -!"`-(!!F!"`!(!!F!"`!(!JF!"`!(!!F!"`!(!`F!"`!(!`F!"`!(!`F#"`)(!JF -!"`!(!JF!"`!(!!F!"`!(!!F#"`-(!`F#"`!(!!F!"`-(!!F!"`!(!`F!"`%(!3F -""`%(!3F""`%(!!F""`%(!3F""`%(!3F""`%(!3F""`)(!JF$"`!(!3F""`%(!3F -$"`%(!!F!"`%(!!%!"rrr!*!$3J$`!*F!N#m"!!%!#3!!5iN!$!!!5i`!N!-@!!T -CH9YVA(9@D&G[@'a6BP4U9@j5,!#3!aB!#PPC@dYF99C)9fpB6&0#9%T96P)X!*! -$3Q!!!*J!N#m"!!%!#3!!1!N!$!!!1!`!!!M#N!!!N!6[!!S!!2rf!!S!$!0R!!S -!!J#3!c3!N$%$J%d!N"dIJF!!N!C`(!F!F!#31P4!PP+!!!'!!*!5!U!!N!3@J8! -!N!5!!&!8"3"3!*!*"4!!`-!!!)!!N"F"aJ#3$J1!!i!!!!N)&N#4!C!!8N3&*%" --!$J!!H(J!*!*&S&1!*!$$3!!8"3&!&!!!99!!!!22!$IZIdP*3!!ZAI&mhh1!!' -1%mlRqk--BJjGjhRIM'$'2d+!JJ"!`K-B!*!$"!#3!`90)4hjG DB%+TQfN+TT -#UI*$4!pb%KH,3$jfS!#)-rq@q9%!!+!*!!"AP!8!8!!#PN!L3"r$q09@58B5%!& -(L)d%"M%%%P%5-C4%B`bM(Q-BaL5-B-BM)d"#!%%#!3J!N!-%!*!$"9BK)aQ-3!# -3#e,N3G@0c-VF"&#)"#48L5Pfcf#!0!!4")"FpJ@"f!!#USK3$jr$#)r58))IN!! -"43N9k!SaUqKQUM#-4#-0)UeM'-B%M&8T45)!'jRERlF[EQjlIc'$'I9!FU%9M&h -GhGQCQrEQCQDCQ8e81r@0,3US2P#DT%,mP)P'l'#q5+!6Z)60`rcr#f!!N!1+-&r -$#)8jZ9)5I2*&%k3I#Fm3"+UVd)pdr`iL6@2SqF5+P4#*%J!'CQ8Q8dbCQCb&+P5 -T+#"bSG@-CT!&C9+CN!9"6NIeYFd+L!MmU"q"*+4*GUrJb9NrS89*IAm0`pb3!!! -!2`B`rm-)J"4Q)K83!N8JIKL5)3[T+[i`M%4MM5)-i`M3*)U++*%5!"jLI5C6M*Q -CQ'8U9%P&32rK%iaQN!0Mrre5QC!&!93llidXb!!qN!$+T%,mT)N@U"&2DL+K19) -&!Geq92rm!!#+-(r$#!"8TP)3%!4&4%8BNL)%%#G'-C4%BibL$1-+bL5*#N54#J! -QCQ%Q8dbCQCJ9*#LTK8#-Ba1-CT!%)L&5QC!&!15&aBS5%!!4%)J%*#5P+4DS#NK -+BN&#+38!93"8J!!!#&)[Rm-)J$NCL5!"$$RlK1F4c+!"%%I1jm1MG(i-A3G&a(% -+4*m+2aqCf4j6,*PZH1,N+4Ie3)aGmA1GhGhCfCe5PQCQGhF!6d3&XH(J!!%IFVr -r*e[T&VJE2V'J332NK`"9!&2J!*!$)HLI`rJ!%!!!`!%!N!FJ!!i!N!N"!*!&!BB -!N!3%!J!!#"!!N!-"!i!!#!#3"3J!N!Si!*!+"!!!(i!!N!3"!*!%9`"`!*!&)"r -q!*!'!J#3"d!!N"FB$!!!#"!!N!-'!*!$%!#3"4!!N"8%!*!)!J#3"(!!N!B"`!# -35!%!"!!*!!i!&J!G!"i!)3!N!#N!,J!`!$3!03!j!$i!3!"&!%S!6`"8!&N!AJ" -M!'J!D3"V!'i!F`"f!(S!J3#'!)X!N!!!P3#C!*d!SJ#R!+J!V3#b!,B![3$#!-F -!c!$4!0B!f`$J!18!kJ$a!2B!q`$r!C!$"3%(!3S"%!%5!4B"'J%H!5)"*J%U!5i -"-J%d!6F"1`%p!83"5!&-!9!"9!&B!9`"A`&M!@J"E`&d!AJ"I!&r!B!"J`')!BJ -"M3'5!CF"Q`'J!D8"UJ'Z!E)"YJ'k!Ei"`J('!FS"cJ(5!GB"f!(D!Gd"i!(N!HJ -"l!(`!I3"q!(m!J!#"!))!JX#$`)8!KN#(J)M!LJ#,3)e!Md#43*(!NS#6`*A!Pi -#B`*S!Q`#F!*e!RS#IJ+$!SN#MJ+4!T8#QJ+K!UJ#VJ+b!V-#Y`+q!X%#aJ,,!Y% -#e3,C!Ym#j3,T!Zm#p3,m!`!$"J-+!`i$%!-5!aF$(J-M!bX$+`-V!bX$+`-V!bX -$+`-V!bX$+`-V!bX$+`-V!bX$+`-V!bX$+`-V!c%$0`-q!*!-rj!'"JErN!B!!2q -3(!!(rj!'!`-"!`%&!3F!"J!*!!J"!`!%!!3""`!'!33!"3%$!3B!"J%'!!B!"J! -'!!B!"J!'!!B!"J)%!33""3!'!38""J!)!3F!"J!'!!B!"3!&!!B!"J%$!!B!"J! -&!!J!"J!'!!B!"J!'!!B!"J!'!!B!#!!'!!B!"3%%!3B""!!%!!B!!`!&!!8!"3! -&!!8!"!!&!!8!!`!%!!8!!`!)!!8!"3!&!!8!"3!&!!3!"3!'!!J!"J!'!!8!"!! -#!!3!"J#3!`B""`!'!!8!"J!'!!B!"3!&!!8!"3!&!!8!"3!&!!8!"3!&!!-!!`! -%!!3!"3!&!!8!"3!&!!8!"3!&!!8!"3!%!!8!"J!'!!B!"J!'!!B!#3!*!!N""!! -%!!B!#3!(!3S!"J!&!!8!"J!'!!8!"J!(!`J#"3%&!!8!#!%*!!B""J%$!!8!#!% -&!!B""`!)!!J"#!!'!!F$"`!'!!N!#!!&!!F""`)(!33""!!'!!J!"J!*rj!S!!B -!"J!(!*!%#bD3!!#3"1m!$`!!rr3!$`!2"*N!$!!$!!%!2J#31h!"-J#3"!B!N"B -"9!#3"4q!i!#3#Ji!1!#3#`8!N$SSL!*-NN!!!!N!N"d@J+!!N!F1I1!+!#J!N!M -`!!!&!!3!!$!!!!3!N"d($!#3%3F!!)J!N!-%)3$C!)JJ'3D*"!0%JJ%!N!X"9!# -3"4EmS!#3"!`!!!T%S!S!+!!!#8U!!!-"qm!!"G&1IQ&*)!!%a1r"IRI[2!!!m!# -2R[2rHKJ``Ji[I2I2IiB-"M(p"3"!J!)$""--!*!%!J#3"!UC%(([i[3S%T9Q!34 -5TYX3LP@)45Z`$(J$cJ!!G&S!IRS!!"%!crq@a+H!!!5!#)!!#PbJ#J!S!!!56)! -%4J(m,r!&er@5N8M!!!NY%)0!J$$#!!%*i)KKLK#''$&$(M$$$$#)KJ`'-3b'J## -!!J3%!33!N!3#!*!%#UB3)KKM$#!!N!d"54+%"9%H(LEJ!+#&9!!+!#44&[5S3!# -3!a%!)!T3S!S!+!!!%T8!3!`"r#J3"B+8P+#(mJ!+&K%&33"3`J34#K&)B)B3JKJ -b3Ud`````#)B-49%8K!!1mjlZIEF@c@GjphG'-4M(kS!S8JK6$#jcR1FjcR1P+cR -1Fk-Ba8Z3!)(T85%K*8!!S)`!K*p%%K%@P,!Zik5!%3!J#P#RqJ!SlJ#3!a#NArA -m+"!&MmaS3)6#!")8%`Ppm%p$5!J8k8qJKK##'$4#66$$$$!)K4**5K4%!"'-Ba5 -18bFcQ-BiLNBa'-3UJ#K5#&---BaM'-BaM'8XaM'-BaM&09"lq9*Fc+4!%5#99)K -%4(%4GTH`-44%J#1b8!T3T"Z!la%!N!-"&(rpr#J3"B8'%+#&,jm5&##4!`L3!-) -6j#8U+'#(hTri1%)-X2d2c`L&%UL+*%3!$i`M&)a64L-BaM##4LUP4&*!4)S25`` -[Hplh`M'-C5M'-BaM'-3&1)Ij89,3J!(jr+3$m$p%N!#44TB`,a6)r#&-8*[6[hM -rJa%!N!0q$(rjr#J3"B!&,45%!J!L&%"K!`L3!,iJ!N8U+'#'%)BB0%)-X-%0!)L -%SUP%4#3!%B`Mp)a6KL-BaM"b48UL4)U!4)S)5``aM'-B`rrrj5M'-BaM'-3&%)I -e80c3J!!L)-98L%4&%4&fPqK4p9#'33#*+0)*5m([(rrJ!!)-3rRm+"!&J!96#)3 -#!#)8J(q$#4##%!4%prKJKK#'($*#$($"$)#)K+%44%3N!"'-)`5-8dBM'-B`#N9 -%488+J2rq#%F--BaM'-)3K#8SaM'-BaM%"4"lmp$5c)!!3L#%!)5%44)4&T3)83C -4K8%bLNrcq8Tr+4!!N!-4&%BIr#J3"3!9Na4)!!""*3L"3`N3K![S!J3BBBS3KK` -a3Ja``5a3L)4"%L5%&!!4M'-8M&-Q)aM'-)T-K%M'#S#$"KK($$'-BaM'-BaP+-B -aM'Fjc!94"H&4)5%!!I`KK93!"%8N84DF"*%88B#"638J!!&+!#N4!*!%T%J"r#J -3"B!1M1*)!#$!arF"22%218333F3IR[2`HK[3rJ`[323[#(K"%L6m&(q2mjlNI&- -@)aGjm('dK%LrkS#$"Hr#mmplh[HjcR1P+,R1FjV@Y!1qK!&f(Ki!!)3qH!2rj(V -2d4D!$-lVMS#"!Ib3!!!"5J!SlJ#3"%2!!I`[m!8!"!!!-!!J!*!)3!#3$JJ!N!B -'$!#3"3J#!*!$3#!!N!3%"`#3!d!!N!B3!*!+!3"i!*!)!93!!%!!!"D!!*!&!3# -3"!&+!#J!N!C!!!IJ!!8!N!C!!*!)J!#3()J#!*!$3#!!N!4%!*!%)!#3"L!!N"Q -!!!!@J!#3"3%!N!3"bJ!S!*!&"%!!N!3&!*!XF!`!N!Ni!*!%3!#3(!&8!*!&(i! -!N!8#!*!&$J!i!*!&!i!!N!3&!*"&!3!%!!X!%!!A!"m!)!!M!#B!,!!a!$-!1!! -j!$i!4!"'!%`!8J"C!&m!C3"V!(%!G`"i!(S!IJ#$!)F!M3#9!*`!SJ#S!+i!X`# -i!,i!a!$&!-X!d3$@!0d!i`$T!1m!p3$l!C!$#!%1!48"(J%M!5J",3%[!63"0J% -j!8%"3`&)!8d"8J&A!9`"B!&P!@S"E!&[!A3"GJ&r!B3"L3'1!C-"Q!'G!D%"TJ' -V!E3"Z3'q!F-"aJ((!FS"d!(3!GF"hJ(N!HN"l`(e!IX#!!)&!JS#$`)8!KN#(J) -M!LJ#,3)b!M3#0J)j!M`#33*'!NX#8!*9!PS#A`*N!QN#EJ*a!R8#HJ+!!SB#M!+ -5!TN#S3+T!V)#Y!+h!Vd#a`,2!YB#f`,I!Z-#k!,[![3#qJ-"!`B$#3-1!a-$'`- -N!bX$-!-a!cB$2J0"!dF$6J08!eN$AJ0P!f`$F30i!hm$L!1-!j-$Q!1G!jm$S31 -Q!kd$XJ1r!lm$[`1r!lm$[`1r!lm$[`1r!lm$[`1r!lm$[`1r!lm$[`1r!lm$[`2 -&!mX$e3!!rrm!N!MrN!B)#2q3"J!!rj!N"!3"!`%&!3N""`%*!!N"!`%&!38"#!% -(!33""`%$!3F"#!-)!3J"#!%)!3J"#!%)!3J"#!%$!33""J%(!3B"#!%+!3N"#!% -)!3J""`%(!3J"#!)&!!F"#!%(!3N"#!%)!3J"#!%)!3J!#!%)!3N"#`%(!3F""`% -%!3F""!%%!!J""!%(!3F""`%(!3F""J%(!3F""3%'!3F""3%,!3F""`%(!3F""J% -(!3B""`%(!3X""`%(!3F""3%$!38"#!!!!3N"#3%)!3F"#!%)!3J""`%(!3F""`% -(!3F""`%(!3F""`%(!J8""3%&!38""`%(!3F""`%(!3F""`%(!3F""`%&!3B""`% -)!3J"#!%)!3N"#J%+!3X""!%&!3J"$!!)!!X""`%'!3B""`%*!3F"#!%*!JS""3! -'!!B"#J%,!!F"#!)%!3F"#J%&!3J"#3%)!3J##J!)!3N##3%)!``"#`%'!3N""`% -(!33""!%(!3N"#!%2rj!S!JN##3!+YYX!N!0%!*!*#!!-!(S!33"k!!`!#!#3%`J -!$!"q!(m!IJ!-!!J!N!X(!!N!N!0%!*!5!F!"3!&!"h!#)!&!!)!!N")"`!(!!F! -(m!2J!F!!J!!*!!J!N!0%!*!+%!!`!&i!JJ"H!$!!%!#3%a!!-!"q!2i!IJ!`!"! -!N!S)!!B!N!0%!*!9%!!T!"F!#3!*!"m!N"83!$N!(`!2!!m!(`!,!!X!N!0%!*! -8#!#8!1J!N!!!N!!!q!#3&3J!R!$i!2!!m!$i!!!,!!3!N!0%q!#3!!#3!!$S!*3 -!#!#3&IJ!m!$`!2J!R!!)!*!@"!!%!*!$4!#3"!r`#"!)%!J3#"!)%!J3#"!)%!J -3$r!!N!J2m"ri'*!5(rJ2m!#3"3F!"`#3!d3"!!+!"%!1i!+!!S!$J!#3%J%!!i! -(`!rJ!i!$J!1!!*!6"J!(!*!$4!!I!!N!#3!A!#N!%!#3&4m!$`!2!"m!13!3!*! -9"!!,!*!$)!!`!"!"3J(Y!!3!N!J,4(9ZCf9[EL"0BA!S#J#3!cBeU90dD@0SG'P -ZCb"0BA4SC@eKG'PcBfJJ3f9ZG(*eE5`J3@ecG'9bC'&Y,#!a16Jed$%jN!-!N!1 -!!2q3"2!!N!2`!*!$r`#3!r!!N!2mm!!!m!#3!rrr!!$`!*!%$`!!m!#3"!m!!2! -!rrm!$`!!m!m"!I!2!!$`m"r`(`m!!2$am3q3!`!!m*!$(am2!!$`m3rrm!m!!2! -2%*!$$`!!m!$rrr!2!!$`!*!%$`!!rj!'!*!%J!$rN!6`!*!$m!#3!rm!N!2`!*! -$r2!!!2!!N!2rr`!!m!#3"!m!!2!!rrm!$`!!m!m3%2!2!!$`mI%2N!-!!2#3!am -I$`!!m2%"!3m2!!$`$a!3m!m!!2!2$r(`$`!!m!m3%2!2!!$`!2rr!!m!!2!!N!3 -2!!$rN!B!N!4!2q!J-#!S)$`J"#!%)m3N*#Q8+P3U9#RN*!3Mj#!%2r`ri$r`2rJ -rr$rm2r`rr$rm2r`rr$rm2r`rr$rm2r`rr!#3!d!ri#!`)#JJ2#!%)m3N*#T8+P3 -SN*D3N*#2%)!3rr$rJ2r!rq$rm2r`rr$rm2r`rr$rm2r`rr$rm2r`rr$rm!!! -"!!rrr!!)!!B!#!i&!!Q4")!*b)4!#1K%)!Ki4r!*2d!3#[b!%!SH!"!+&`!3#41 -!%!L*`"!)F1!3#!"`%!J!1"!)!"J3#!!!%!J!!"!)!!!3#!2!%!J%)"!)#C!!%!J -+8"!)#P!3#!RJ%!J%!"!)!q!3#!!!%!J!!"!)!!!3$rrrm!rrr!!2rri!$rrr!!r -rri!2rrr!$rrri!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!r +rrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!!!!3!2rr`!#!!'!!J +1"3!*N35!#FL%3!MS4#!)H%I`#6p!%!VmJ"!+(J!3#KF!%!N6J"!)LF!3#($J%!J +!F"!)!$J3#!!B%!L(`K!*@$83#@!0%!SXD*!!#Y+@N!!*8T83#%aN%!NJ#4!+d"D +3!!SAd*!!#5JT%!P)*4!)amB3#!!!%!rrrr!2rr`!$rrq!!rrr`!2rrq!$rrr`!r +rrq!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!r rrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!r -rrr!2rrr`$rrrm!rrrr!2rrr`!!!"!!rrr!!)!!B!#!i&!!Q4")!*b)4!#1K%)!K -i4r!*2d!3#[b!%!SH!"!+&`!3#41!%!L*`"!)F1!3#!"`%!J!1"!)!"J3#)I#%!P -B04!*B!d3#LaSN!!+dTD3!!P5P4!)6'33#5!*%!V3&T!!#KI3N!!*+#N3#8JP%!M -(aK!)!!!3$rrrm!rrr!!2rri!$rrr!!rrri!2rrr!$rrri!rrrr!2rrr`$rrrm!r -rrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!r -rrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`$rrrm!rrrr!2rrr`!!!#!*! -$rj!*!*!(m!#3"`r`!*!'m!#3!rr`!!!2c`#3"[!2m!m3(`!!$mc`!*!&m!qr!2% -"m!!2c-m!N!A`!2[`m"!I!!r-c2!!N!6`!!qrm3%2!!rrN!-!N!6`$`$lrrmI!*! -%$`#3"2$`rrqr!2!!N!32!*!%m2%"$r[`!*!&$`#3"2$`%"m2[`#3"3m!N!6`$`% -2!2[`!*!%$`#3"2!!m"$`$lm!N!32!*!%m!!2r`!!qr!!N!-2!*!%m!#3"3qr!*! -$$`#3"2!!N!Elm!!!$`#3"2!!N!B2m!!!$`#3"2!!N!S2!*!%m!#3#Jm!N!6`!*! -+$`#3"2!!N!6rr`#3"!m!N!6`!*!$$`%"m!#3!`m!N!6`!*!$m"r`(`#3!`m!N!6 -`!*!$mI%2$`#3!`m!N!6`!*!$m2!I(`#3!`m!N!6`!*!$m3rrm!#3!`m!N!6`!*! -$$a#3!`#3!`m!N!6`!*!%rrr`!*!$$`#3"2!!N!S2!*!%m!#3#Jm!N!6`!*!+$`# -3"2q3$!#3"!)!N!2rN!N!N!I`!*!($r!!N!E`!*!$rr!!!!r2!*!'m!r`$a!I!!! -2c2!!N!A`$lm!m3(`!!r-c`#3"I!!qr$`%"m!$mc-m!#3"2!!$lra!3m!$rq3!`# -3"2!2!2[rram!N!32!*!%m2$rrlm!m!#3"!m!N!6`m3%2qr!!N!82!*!%m2!3(`q -r!*!&$`#3"2!2!3m!qr!!N!32!*!%m!$`%2!2[`#3"!m!N!6`!!rr!!$lm!#3!`m -!N!6`!*!&$lm!N!-2!*!%m!#3"[[`!!!2!*!%m!#3"Jr`!!!2!*!%m!$`!!rrr`! -!m!!2!*!%m!mI$r!3%2m2(`!2!*!%m!m2m3'3"2m2!!m!N!6`m"$`ra!Im2!3m!m -!N!6`mIm2c2(mc`ram!m!N!6`$`mIc2$mcam2!!m!N!6`!!m"r`%2m3m!!!m!N!6 -`$`$`%*!%m!m!$`#3"2$ar`m"N!-2$r(`$`#3"2$`%"mIrrmI%"$`$`#3"2!2!I$ -a!3(`m3m!$`#3"2!2(`$`%"$`$am!$`#3"2!!r`!2rrm!$r!!$`#3"2!!N!S2!*! -%rj!-!*!&"d&38%`!N!B(8&*&4J!"!*!%"d4"9%%!!J#3"!G639C&!!-!N!3(3Np -143!%!*!%2'jS-c%!N!-"4P*&4J!%!*!$J!!"!)%!!J##!!-!J`!%!)4*3diM!!3 -!!!2S!!%$k3!#!qS!!`2V!!3$l!#3!`i!2J"1!,S"XK1*!!3`#J#3!i8!J3#3#2r -rr8m%4QPXC3T5C@4bBAFJ6@&`!&)4!!a3FQ9fD@peFb"0FfF!8"%!#P*PF'pcDA4 -TEfi!6J!!!5d!N!3(8Q9RG@aKFJ!Eb!!04@jdCA)J4AK`E'pbC3!!@!!",3#3"!4 -6BACP!&06!!%Y!*!%"&&eDA3!89%!N!9)!))!N!MrN!2l"%9NDA3%9@jNE`"D!!! -",3#3"!0$GA3!@!!!"%0[F(N!3`!!"9"KFh4P!&B!!!9$E'9KFJ#3#+`!J`#3#2r -rrIm$5f*N$%0[ER4bEf`J5f9jF`!Eb3!,8(9ZBh4eBA4TEfi!'mS!#%*bB@0VCA4 -c!"[,!!9K)#dJE3!Ec!!&EL!Y)(S!'md!"8%J,5"0!"[1!!91)#dJ@J!Ec`!&-#! -Y)$N!'p!!!5d!N!3)+'9cBf&`C5N!N!3(+(0`B@0P+3#3"!JSC'9XCA4P+3#3"!J -SFQ9dGA*Z+3#3#(-!K!#3#2q3!pX%5'9XF!G2F(4TEfjc!!"2!!%Y!*!%"%KPE(! -!!$m!$%4PFf0bD@*P)%YPH3!!*J!",3#3"!G@CA*cD@pZ!!"f!!G)DA0dEh*j!!" -@!""@CA*cD@pZ)%CPBA4eFQ9c!!!M!*!&+J#!!*!)rj!$q`%8$N&LEh9d)%jPG%K -KBf[*!*!%!5d!N!M'!)8!N!Mrrrh["%PZCQm05@jfC@jdEh*j)%&XE!!!D3!35@j -fC@jdEh*j)&0PE'9MG!!!53!'3@4UGA0d!!!M!!%Y!*!%#8a[EfXJ4'phEJ!!1J! --4'9cBh*TBQ8J6fjP!!!l!!e%CA0MFQPLC5"0B@jj!!![!!e%CA0MFQPLC5"8FQ& -`!!"H!!%Y!*!%$%0KE'`J6@pZFh4PFJ!!3`!,6Q&YC5"2BQTPBh3!!#-!#d4TFf0 -[GQ9bD@9c!!"F!*!&Z3#)!*!)rrrlh`90B@GTB`P%FQp`)%PdC@d!!'3!#d4bEh! -J8f9XC@0d!!"%!!C3D@0VGA!!!#`!$94[CfGXC5"`D@0VGA!!!%!!!5d!N!3$4@& -d!!"P!!45C@&N!!"b!!94G@&QCJ!!F3!$4'P`!!!M!!%Y!*!%#daTFh3J8h"PE'a -c!!!V!!T$BA0d)&0`C@aX!!"D!!0DBA!!!(S!"NPZGQpVC3!!)`!$8R9L!!!M!*! -&Y`#*!*!)rrql[`4#DA4c"P0PBA*MD!!!F`!+3fa[Ff8J4'p[FJ!!B`!*6h"PEL" -%Efpb!!"[!!9"F("XH3!!B3!%5fPMD`"%%3!",3#3"!C9ER4bBA!!!#-!"8C[FQ0 -P!!!M!!4-Efpd!!!M!!%Y!*!%"d9ZCh*KGQ8!!%8!!d4TF!!!)`!$8fPd!!!M!!% -Y!!!M!JK$E'PYF#"9F!!!2!!+3faTE@)J4'phEJ!!2J#3"BX!bJ#3#2q3"!Y`G@j -MG(9KG'P[EJ)J,J#3"!)J,!#3"!)J1`#3"!)J1J#3"!)J)3#3"!)J2`#3"!)J+`# -3"!)J,3#3"!)J23#3"!)J)`#3"!)J*!#3"!)J3!#3"!)J*J#3"!)J+J#3"!)JIJ# -3"!)JA`#3#(J!b`#3#2q3"!KLFQ&MDf9dF`&E!*!%!9d!N!3"+!#3"!%T!*!%!AX -!N!3"I3#3"!%m!*!%!6i!N!3"AJ#3"!&J!*!%!5F!N!3")J#3"!&F!*!%!5m!N!3 -"I!#3"!%P!*!)B`$-!*!)rj!%"@%J,5"Y!@%!N!3"BJ#3"!&M!*!%!@3!N!3"C3# -3"!&Q!*!%!@F!N!3"D!#3"!&T!*!%!@S!N!3"D`#3"!&X!*!%!@d!N!KM!-d!N!M -rN!3&EL!Y)(S"EJ#3"!&[!*!%!A!!N!3"F3#3"!&b!*!%!A-!N!3"G!#3"!&e!*! -%!AB!N!3"G`#3"!&i!*!%!AN!N!3"HJ#3#'-!cJ#3#2q3"!9")#dJ63&"!*!%!8) -!N!3"3`#3"!&%!*!%!88!N!3"4J#3"!&(!*!%!8J!N!3"53#3"!&+!*!%!8X!N!3 -"6!#3"!&0!*!)B`$2!*!)rj!%"8iJ,5"D!8i!N!3"6`#3"!&3!*!%!9%!N!3"8J# -3"!&6!*!%!93!N!3"93#3"!&@!*!%!9F!N!3"@!#3"!&C!*!%!9S!N!KU!-N!N!M -rrrhr$'0[ER4bEf`JDf9jF`&L!$%!!!&U!$)!!!&Z!$-!!!&S!$3!!!&X!$B!!!& -j!$F!!!&V!$J!!!&e!$N!!!%Y!*!%!@3!4!!!!A!!8!!!!A)!8J!!!A3!9!#3"P% -!d!#3#2q3"!8`)#dJ13%`!*!%!6%!N!3"-J#3"!%c!*!%!63!N!3"03#3"!%f!*! -%!6F!N!3"1!#3"!%j!*!)N3$)!*!)rj!%"RGTHQ&bC!T"G(4bD@*eG'9c!!"i!!e -%CA4PBh3J9@jcC@9Z!!"P!!P'E'p[FL"0BA!!!'B!%%GPEQ9bBA4P)%e[ER0dCA) -!!'F!#%PNC@jdD@Cj!!"T!!P-Ef0KG'P[ER-!!'m!$NaPGQ9X)&4PE'9`Eh*d!!" -f!!4ADA0S!!"h!*!&A`$4!*!)rj!%"f0eFR*PER3'9f9KF'pZ!!!T!!9"FQe[FJ! -!@`!&8QPZCh-!!$d!"N&YG@aPG!!!)J!&9'p[E(-!!#J!"%G[E'3!!#3!"P0`C@a -XF`!!+`#3"5`!J!!+!)!!N!1"!*!$JJ#3!i-!N!1%!*!$K3#3!iB!N!1(!*!$L!# -3!iN!N!8X!-J!#J$)!*!$b3#3!mS!N!2,!*!$c!#3!md!N!21!*!$c`#3!p!!N!2 -4!*!&N!!!$4'P-M!a)%0[ER4bEf`J5f9jFa#P-M!b)&"eEQ0dG@&dD@pZ$D8b-$- -J3R*KBfYPG(-+T6)`0#"K)#dJE3UP-M!e)'iJ,5"k#U8b-$BJ35!Y)%d+T6)`0b" -1)#dJ@JUP-M!i)$!J,5!j!U8Y#"ZPCA0MBA"P"b#PFh"KBf8)#+9NC@aPG'8)$D9 -bCA4eFQi!N!0P!!d(!U9MG'`YBJF+T@0dE#eU"`kPBh4X,@i(#+9MG'`YD!F-T@0 -dE#eX"aQPBh4X,AN(#k9MG'`YD`F9T@0dE#ee!U8Y"`5PBh4X,@3(%+9MG'`YF!F -5T@0dE#eb"a5PBh4X,A3!N!-L!"!",J%X!6X"1J%K!6m"+`%Y!6d")`%N!8!"*J% -U!Ai"A`#3!b)!%!&E!9d"+!%T!AX"I3%m!6i"AJ&J!5F")J&F!5m"I!%P!*!$(!! -0!@%"BJ&M!@3"C3&Q!@F"D!&T!@S"D`&X!@d!N!-F!!d"EJ&[!A!"F3&b!A-"G!& -e!AB"G`&i!AN"HJ#3!a`!$3&"!8)"3`&%!88"4J&(!8J"53&+!8X"6!&0!*!$(!! -0!8i"6`&3!9%"8J&6!93"93&@!9F"@!&C!9S!N!-@!!S"-!%a!6)"-`%d!68"0J% -h!6J"13#3!d)!#!FBT@0dE#ei"`@PBh4X,@8("U9MG'`YCJF(T@0dE#eR"`QPBh4 -X,@N($k9MG'`YE`F@T@0dE#ef"aHPBh4X,AF!N!-3!!F"+3&E!6d")J%S!53"+`# -3!dX,-A0d)'ePER8J584%9e*%#L-JEfBJ68919A023dj8"5U3"8a69%-'8Q9c)%P -%4&G54!K5CA0PFRCPC%CA8N3&+T!&6&0843#3!aX!#!&2!U8Y!6m"*J+P,3&f!9B -))hCPFR0TEfi!N!-Q!!`"D3&*"b0KC'TeFh3#T5d"1J%l!5m"AJ+P,3&$"50ZB@e -P!9`!N!-d!!)!N!9R!33!H`&8"!*25`#3"3X!83"B!@#)"&i`AM%!N!8+!"J!+J! -iS!)!!3#3!d3!!`#3"9d"$J"a!8S%!Nj[!*!&A3"G!(%!Q33$@@9c!*!'#J"2!&! -"8iJ#AM!!N!8+!"B!+J!fS!)!N!81!%3!4!#b!G8!J%4%-!S!N!-1!%S!DJ$6!GF -6L!!%-!S!N!0!!"!"F`&M!@m"B3F%T@0dE#eN!U8Y"b0eER4bBA!')fC[FQ0P"50 -XEfpd!U8Y!88%)f4TF!3MFfPd!U8Y!6`"2J#3!a366Q9d5'&MDb"3FQ9QCA*PEQ0 -PF`#3!bX$-)!!N!-&-bic,M!H-bic,M!JU6%j1$8Y-6Q3!b"0,L"6G'9`D'9ZFfp -Z!*!$+`-`J!#3!`8c,M-Z-"j6G'PMD(4TEQFJ6@&dD'9YBA4TFf0S)%0PER4bG@d -!N!06!!m",J+P,3J8T5"MG'`YG!8MDR9YF!JME@pZFh4PFJ8MGfP`C3+P,3&K!A! -("+9MG'`YC!8MBfKKG!BMEfCQCA)&)h"bBAN&)h*TC'8&)h4eFQi!N!1F!)F!N!M -rN!0l!d&MG!4AB@Pd!!!Z!!%Y!*!%#&4PE'9`Eh*d!&34!!4+G@e`!!!M!!G0Efj -cG'9b!!!M!!4ADA"P!!!M!!%Y!*!%"8&`F'aj!!"K!!03BAN!!(!!"%YTBfX!4"% -!"%0SBA3!!#-!"8pQCQ9b!!!M!!43FQ&j!!!M!!45D@4P!!!M!!48GA*Z!!!M!*! -&,J!2!@3"4!%X!8!#T5d"C3&b!A%%)f4TF!+P,3%V!9S"HJFMD@jfEfYP"#0bG@) -!N!0#!"%-T6)`15"$GA*bC@jd!U8Y!AF"H!&4!@B"G!&K##0PEQKKEQ0P#L0dGfp -hC@&`Efi#T5d"9`&8!8%#T5d"8!&5!*!$m3#'!*!)rrphq`9&FA9TF!G$GA*bC@j -d!"[4!!%Y!*!%$>C@aN)&GPBA"[EJ!!G`!24AKMD'&ZCf8J9f9KF'pZ!!"i!!e -6C@aPBh3J8A9TGQ9b!!"4!!Y'DA*P)&&eDACPFJ!!CJ!&9'KbEhF!!(3!"8&`F'a -j!!"K!!G&EQKKEQ0P!!!M!"&8GfmJ9f9KF'pZ)%0[E@*KG!!!)`!",3#3"!TAC@& -b)%&bE@pb!!"A!!K8B@YP)%pQCJ!!9!!+3A0V)&*PE@pfC3!!33!",3#3"!C3GA3 -J6fi!!&!!"P*PE@pfC3!!8J#3"6!!N!F%!!$GN!B!!3#3"`)!N!F$!*!("2q3"J# -3!bS!3J!Z!1)"XJ!&!3#3"aG`%P0PE'9MG#"K)%0SBA*KBh4PFMB`#J#3!e3!N#! -J!!"!!*!Srj!'!*!%!5i!%!#3"5J"%J!m!@)%"&"XBAN!N!91!4)!BJ&L"!44G@P -d!*!&*!%1!%!"CS!!N!C3!%J!B3"k!*!(8!#k!'%!lJ#3"hJ!5!#*!(S!N!Gi!,` -!L3$Z!*!(H!%q!)N"B3#3"bN!5J!j!2!3"%jKE@8!N!8B!"3!1!!dS!)!!3#3"9! -!*!"J!%L)"9*[E'8k!*!'8!#@!'!!ZSJ&8Q&MC6TP!*!&H!!8!)J!5)J(4f9ZC'9 -b1J#3"RJ!PJ#)!,b)"N&XD@GZ1J#3"AJ"%J#)!6k)"8e[C'8kD!#3"4-!5!!N!2+ -)$&GSEb"KFQ8JH@pe2`#3$!%%!!%AF!#3!c!!N!F%!!$GN!B!!3#3"`)!N!F$!*! -("2q3"J#3!c!!N!F%!!$GN!B!!3#3"`)!N!F$!*!("2q3"J#3!c!!N!F%!!$GN!B -!!3#3"`)!N!F$!*!("2q3"J#3!c!!N!F%!!$GN!B!!3#3"`)!N!F$!*!("2q3"J# -3!c!!N!F%!!$GN!B!!3#3"`)!N!F$!*!("2q3"J#3!c!!N!F%!!$GN!B!!3#3"`) -!N!F$!*!("2q3"J#3!c!!N!F%!!$GN!B!!3#3"`)!N!F$!*!("2q3"J#3!c!!N!F +rrr!2rrr`$rrrm!!!!J#3!rq3#3#3"r!!N!F2m!#3"[!!N!2rm!!!$mm!N!E`$r! +2%"m!!!r-m!#3"I!2[`$a!I!!$mc2!*!&m!$lm2!3(`!2c-c`!*!%m!!2[r%"$`! +2rj!$!*!%m!m!qrrr(`#3"!m!N!6`m2rr[`$`!*!%$`#3"2$a!3rlm!#3"3m!N!6 +`m"!I$lm!N!82!*!%m!m"$`$lm!#3"!m!N!6`!2!3m!qr!*!%$`#3"2!!$rm!!2[ +`!*!$$`#3"2!!N!82[`#3!`m!N!6`!*!'qr!!!!m!N!6`!*!'$r!!!!m!N!6`!*! ++$`#3"2!!N!S2!*!%m!#3#Jm!N!6`!*!%rrm!N!32!*!%m!#3!`m"!I!!N!-2!*! +%m!#3!r!Im"m!N!-2!*!%m!#3!r(a$`m!N!-2!*!%m!#3!r$`(am!N!-2!*!%m!# +3!r%2rr!!N!-2!*!%m!#3!`m3N!-!N!-2!*!%m!#3"2rrm!#3!`m!N!6`!*!+$`# +3"2!!N!S2!*!%m!#3#Jm!N!6rN!`!N!3#!*!$rj!*!*!(m!#3"`r`!*!'m!#3!rr +`!!!2c`#3"[!2m!m3(`!!$mc`!*!&m!qr!2%"m!!2c-m!N!A`!2[`m"!I!!r-c2! +!N!6`!!qrm3%2!!rrN!-!N!6`$`$lrrmI!*!%$`#3"2$`rrqr!2!!N!32!*!%m2% +"$r[`!*!&$`#3"2$`%"m2[`#3"3m!N!6`$`%2!2[`!*!%$`#3"2!!m"$`$lm!N!3 +2!*!%m!!2r`!!qr!!N!-2!*!%m!#3"3qr!*!$$`#3"2!!N!Elm!!!$`#3"2!!N!B +2m!!!$`#3"2!!m!!2rrm!!2!!$`#3"2!2(`r`%"$r$am!$`#3"2!2$r%"N!6r$`! +2!*!%m2!3m2m3(r$`%2!2!*!%m2(r$mcar-m2mI!2!*!%m!m2(mc`r-mI$`!2!*! +%m!!2!Im"$r%2!!!2!*!%m!m!m"#3"2!2!!m!N!6`mIm2!C!$$`ram!m!N!6`m"! +I(rrr(a!3m!m!N!6`$`(`m3%"m2%2!!m!N!6`$am!m"!3m!mI!!m!N!6`!2m!$rr +r!!r`!!m!N!6`!*!+$`#3"2q3$!#3"3G"8&"-!*!'"e"548B!!3#3"!G%394"!!) +!N!3(8d&@43!$!*!%"d*26N8!"!#3"$aZD$-a!*!$!8C548B!"!#3!i!!!3#"!!) +!JJ!$!)-!"!#%5801)`!%!!!$k!!"!qN!!J2U!!-$k`!%!q`!N!-1!$i!6J#k!E) +6L3!%-!S!N!1&!)%!N!Mrrre2"%CTE'8+8Q9NFQ&h)%eKF!"5%3!-8(*PGQP[GA- +J6A0R!&!4!!T5CA"[FfPdD@pZ!%i!!!%Y!*!%"e*PCh9XBA)!'mJ!$89ZG'9b)%9 +iF'a[FQ8!!&J!!5d!N!3%8f&fC3"68`!",3#3"!44G@Pd!&&4!*!&5!##!*!)rj! +$q`4&C'Pd"&9ZC'm!@J!!!5d!N!3$3h9d!&J!!!4$Eh"j!%-!!!93BA0dC3"@!!! +&3faPBA)!N!LX!)-!N!Mrrrhr!dYLC!a$EfjdFQpX)%YPHA-!'mN!#e"eEQ0dG@& +dD@pZ!"[+!!K#FQ&MDf9dF`!Eb`!&B5!Y)'d!'m`!"@iJ,5"k!"[0!!9")#dJ63! +EcJ!&6L!Y)&S!'mm!"6!J,5!j!"[3!!%Y!*!%##KPFf0KF'8T!*!%"bKcF'&MC5N +!N!3)+'4PE'9dC5N!N!3)+(*PG(9bELN!N!Kc!)3!N!MrN!2E"%KPE(!(6h"dD@p +ZF`!!6`!",3#3"!4)C@a`!!!r!!a%CA0MFQPLC5",CAN!!#B!!5d!N!3(9Q9bFfP +[EJ!!GJ!(5'PcG'pbH3!!9J!39Q9bFfP[EL"'C@&dGA*PF`!!)`#3"5S!J!#3#2q +3!rX"&!j"BQpeG#"1CA4)B@0Vb3#3"!%Y!*!)aJ#&!*!)rrrpl`4*EQC[$8PZGQ9 +ZG'pbH5""E'`!!'N!%%PZGQ9ZG'pbH5"6C@aPBh3!!%N!"N&NDR9cG!!!)`!",3# +3"!P-EfpV)%4[Gfi!!$S!$%4PFf0bD@*P)%pZC3!!1`!04'9cBh*TBQ8J6@&ZH3! +!,`!04'9cBh*TBQ8J9(*KF!!!AJ!",3#3"!a$B@aX)%e[ER0dCA)!!%-!#djKE@8 +J6f*UC@0d!!!M!!Y%DA0MEhCPFQPPF`!!A!#3"EN!L!#3#2rrqpm&6@&RD@-*4(* +[F#"*G'9Y!!"N!!Y%FQp`)&0PE'9MG!!!4!!'8'PMDh9`!!!X!!e8EfGRE'8JF'P +MDh9`!!"!!!%Y!*!%!d9KG!!!C3!%8Q9KC!!!FJ!&8A9KCQB!!(%!!d4TF!!!)`! +",3#3"!Y-DA0d)&0`C@aXF`!!+`!+3f&cG#"6F'9XE!!!@J!$@Q&`!!"k!!C*ERC +[Df8!!#-!!e*eBJ!!)`#3"EF!L3#3#2rrZlm%3QPdF`C6C@&bBfJ!!(-!#N0XEh0 +P)%4[Eh)!!'-!#8p`C@iJ4'p[FJ!!E`!&3A"`E(N!!'%!"%YTBfX!4"%!!5d!N!3 +'9@jdFQ&`!!!M!!9'Eh*MC3!!)`!%6'p[G!!!)`!",3#3"!G&EQGbBACP!!"&!!0 +%DA!!!#-!!e0TG!!!)`!",3!!)`))3faTEA!J9A!!!$`!#N0XD@eL)%4[Gfi!!$i +!N!@,!-S!N!MrN!3,F(9ZBh4eBA4TEfi#)#i!N!3#)#`!N!3#)$X!N!3#)$S!N!3 +#)#%!N!3#)$m!N!3#)#X!N!3#)#d!N!3#)$d!N!3#)#-!N!3#)#3!N!3#)%!!N!3 +#)#B!N!3#)#S!N!3#)(i!N!3#)&m!N!Ki!-X!N!MrN!3)BR*KBfYPG(-"@`#3"!& +G!*!%!5J!N!3"+3#3"!&l!*!%!Ad!N!3"2!#3"!%q!*!%!9i!N!3"B!#3"!%R!*! +%!5)!N!3"A!#3"!%[!*!%!A`!N!3"*3#3#'-!c!#3#2q3"!9K)#dJE3&K!*!%!@) +!N!3"B`#3"!&N!*!%!@8!N!3"CJ#3"!&R!*!%!@J!N!3"D3#3"!&U!*!%!@X!N!3 +"E!#3"!&Y!*!)B`$0!*!)rj!%"@iJ,5"k!@i!N!3"E`#3"!&`!*!%!A%!N!3"FJ# +3"!&c!*!%!A3!N!3"G3#3"!&f!*!%!AF!N!3"H!#3"!&j!*!%!AS!N!KM!-i!N!M +rN!3&35!Y)%d"33#3"!&#!*!%!8-!N!3"4!#3"!&&!*!%!8B!N!3"4`#3"!&)!*! +%!8N!N!3"5J#3"!&,!*!%!8`!N!3"63#3#'-!c`#3#2q3"!91)#dJ@J&1!*!%!8m +!N!3"8!#3"!&4!*!%!9)!N!3"8`#3"!&8!*!%!98!N!3"9J#3"!&A!*!%!9J!N!3 +"@3#3"!&D!*!)DJ$*!*!)rrrpr`aMEfjdFQpX)'YPHA-"BJ!a!!!"DJ!b!!!"EJ! +c!!!"D!!d!!!"E!!f!!!"H3!h!!!"D`!i!!!"G3!j!!!",3#3"!&N!%3!!!&`!&! +!!!&b!&)!!!&d!&3!N!C4!0!!N!MrN!3&-#!Y)$N"-!#3"!%a!*!%!6)!N!3"-`# +3"!%d!*!%!68!N!3"0J#3"!%h!*!%!6J!N!3"13#3#*%!b!#3#2q3"!ChDATKFQ3 ++3A4dFQPLGA4PF`!!H!!04'9dC@0d)&9ZFf9PEJ!!C3!*4Qa[Eh)J6@&`!!"Q!"" +(C@jPFQ&dC5"0EfjcG'9b!!"R!!K*C'9ZG'PQH3!!D3!*6'pMBA4TEfjc!!"[!!j +-CACPE#"8C@aPF'pbG!!!GJ!%9fPcD!!!G`#3"9m!d3#3#2q3"!GMGA*bC@jd"PG +PBA"[EJ!!+3!&3A*YEh)!!&X!"9*TEQGc!!!p!!C"EA9XCA3!!#)!"94[Efac!!! +S!!4(EfaN!!!N!!C6F'9XE(-!!#X!N!8X!)!!#J#!!*!$J3#3!i)!N!1$!*!$K!# +3!i8!N!1'!*!$K`#3!iJ!N!1*!*!&,!$)!!S!b!#3!mN!N!2+!*!$b`#3!m`!N!2 +0!*!$cJ#3!mm!N!23!*!$d3#3"C!!!!d4T6)`-5"$EfjdFQpX)%YPHA-3T6)`-L" +3G@jMG(9KG'P[EJfP-M!c)%*bB@0VCA4c#U8b-$3JB5!Y)'d+T6)`05"Z)#dJHJU +P-M!f)%%J,5"0#U8b-$FJ6L!Y)&S+T6)`1#!`)#dJ13+P,3JET@9cBf&`C3FJTA0 +`B@0P#!LPC'9XCA4P#!fPFQ9dGA*Z!*!$C3!0"`+PBh4X,@)(#U9MG'`YDJF1T@0 +dE#eZ"`LPBh4X,@J($+9MG'`YE!FCT@0dE#ej"`ZPBh4X,@X(&D9MG'`YG3+P,3F +%T@0dE#eN"a#PBh4X,A!(%U9MG'`YFJF8T@0dE#ed!*!$)J!3!5i",!%l!6S")3% +r!5X",3%p!5-"*!&!!5B"+J&q!9m!N!-L!"!"@`&G!5J"+3&l!Ad"2!%q!9i"B!% +R!5)"A!%[!A`"*3#3!a`!$3&K!@)"B`&N!@8"CJ&R!@J"D3&U!@X"E!&Y!*!$(!! +0!@i"E`&`!A%"FJ&c!A3"G3&f!AF"H!&j!AS!N!-F!!d"33&#!8-"4!&&!8B"4`& +)!8N"5J&,!8`"63#3!a`!$3&1!8m"8!&4!9)"8`&8!98"9J&A!9J"@3&D!*!$&J! ++!6!"-3%b!6-"0!%e!6B"0`%i!6N!N!0#!!J('+9MG'`YH!F&T@0dE#eP"`DPBh4 +X,@B("k9MG'`YC`F*T@0dE#eT"`qPBh4X,@m(&U9MG'`YGJFAT@0dE#eh!*!$%!! +(!5N"@`%p!5)"+!%N!5X!N!0,#c&cG#"YC@je)%P%4&G54!SM)'pQ)%e&6P9c6d0 +19!8UN!9-8e4$"P*PFb"*4%4A8N3)8Q9cCA*fC@4'9e*%"5U3"8a69%8!N!-E!!J +"6`+P,3%r!5B#T5d"GJ&@##0fCA*cD@pZ!*!$*J!-!@N"53FMB@4UGA0d!U8Y!6S +"1`%[!9i#T5d"3`8MEQ&YC3&F!*!$0!!#!*!&C`%%!(X"9!3#6dX!N!8,!&%!@!& +JL!4H-&ia!*!&#J!B!#S!1+!#!!%!N!0%!!-!N!9G!3i!F3&+"!*1E`#3"9d!A3" +a!*N%!ePPF`#3"JS!6`"3!91)!Pi`!*!&#J!@!#S!0U!#!*!&$J"%!%3!XJ(9!)" +%4$!+!*!$$J"+!'S!d`(A%iJ!"$!+!*!$3!!3!A-"B`&[!@%("+9MG'`YC!+P,3F +MG@jdFQ&`"L0QEh*MC38ME'p[G!+P,3&&"#0NDA!%)h0TG!+P,3%m!6i!N!-8%dj +PG%KKBfXJ8(*PCQ9bC@jMCA-!N!06!!m",J+P,3J8T5"MG'`YG!8MDR9YF!JME@p +ZFh4PFJ8MGfP`C3+P,3&K!A!("+9MG'`YC!8MBfKKG!BMEfCQCA)&)h"bBAN&)h* +TC'8&)h4eFQi!N!1F!)F!N!MrN!0l!d&MG!4AB@Pd!!!Z!!%Y!*!%#&4PE'9`Eh* +d!&34!!4+G@e`!!!M!!G0EfjcG'9b!!!M!!4ADA"P!!!M!!%Y!*!%"8&`F'aj!!" +K!!03BAN!!(!!"%YTBfX!4"%!"%0SBA3!!#-!"8pQCQ9b!!!M!!43FQ&j!!!M!!4 +5D@4P!!!M!!48GA*Z!!!M!*!&,J!2!@3"4!%X!8!#T5d"C3&b!A%%)f4TF!+P,3% +V!9S"HJFMD@jfEfYP"#0bG@)!N!0#!"%-T6)`15"$GA*bC@jd!U8Y!AF"H!&4!@B +"G!&K##0PEQKKEQ0P#L0dGfphC@&`Efi#T5d"9`&8!8%#T5d"8!&5!*!$m3#'!*! +)rrphq`9&FA9TF!G$GA*bC@jd!"[4!!%Y!*!%$>C@aN)&GPBA"[EJ!!G`!24AK +MD'&ZCf8J9f9KF'pZ!!"i!!e6C@aPBh3J8A9TGQ9b!!"4!!Y'DA*P)&&eDACPFJ! +!CJ!&9'KbEhF!!(3!"8&`F'aj!!"K!!G&EQKKEQ0P!!!M!"&8GfmJ9f9KF'pZ)%0 +[E@*KG!!!)`!",3#3"!TAC@&b)%&bE@pb!!"A!!K8B@YP)%pQCJ!!9!!+3A0V)&* +PE@pfC3!!33!",3#3"!C3GA3J6fi!!&!!"P*PE@pfC3!!8J#3"6!!N!F%!!$GN!B +!!3#3"`)!N!F$!*!("2q3"J#3!bS!3J!Z!1)"XJ!&!3#3"aG`%P0PE'9MG#"K)%0 +SBA*KBh4PFMB`#J#3!e3!N#!J!!"!!*!Srj!'!*!%!5i!%!#3"5J"%J!m!@)%"&" +XBAN!N!91!4)!BJ&L"!44G@Pd!*!&*!%1!%!"CS!!N!C3!%J!B3"k!*!(8!#k!'% +!lJ#3"hJ!5!#*!(S!N!Gi!,`!L3$Z!*!(H!%q!)N"B3#3"bN!5J!j!2!3"%jKE@8 +!N!8B!"3!1!!dS!)!!3#3"9!!*!"J!%L)"9*[E'8k!*!'8!#@!'!!ZSJ&8Q&MC6T +P!*!&H!!8!)J!5)J(4f9ZC'9b1J#3"RJ!PJ#)!,b)"N&XD@GZ1J#3"AJ"%J#)!6k +)"8e[C'8kD!#3"4-!5!!N!2+)$&GSEb"KFQ8JH@pe2`#3$!%%!!%AF!#3!c!!N!F %!!$GN!B!!3#3"`)!N!F$!*!("2q3"J#3!c!!N!F%!!$GN!B!!3#3"`)!N!F$!*! -("2q3"J#3!c!!N!F%!!$GN!B!!3#3"`)!N!F$!*!("2q3"J!!#-i!!3#3!a`!N!0 -1!*!%rrm!N"#!)!#3"8!!3!#3#8J!N!0)!*!&"!!"!!3!N!B)6J#3"#)c-L+3"5- -L%4)L)MYiXL+3"K)M-bY$1l-LN!-c-L+3"5-L)K)5[(h$)T!')5)M-b9$)eXb)L) -c)T!*)eHA8b+3#50$1d-bZd)L)L3b)T!$-L)M0,CpRFXL)b)L)b+3"M1l3c)PBb) -L)l-cZfc'E(ICU[fb)e-M-b+3#E4$-b1mXd0,HCQCUT!$rkUBa6-L*M-c)T!()b1 -d3c-b*'amb0aP9EZlE'9EY&Dc-L46-c)K)c)5)lY8+l4$-M-b*FCXZd-L)K&,4%Z -dYV-c-eXc-L)MZj!$3V3VY$13"E-L@d-b)L'lN!0%4E3c4,8c)LYPXb+3!bXl4$0 -%-dZl-c1l-c-L)9ZlY%3cY%4%1l-MCM)LN!3N*83d0%5l3c-b46-c)L*8Zl4%3lY -%4$0EA&-b)T!&*84$0%5d-c)L*6-c-L0EZl4%3cY%5c*FDc-LN!BQZd0$Y%3c-L) -V3c-L+l5lZdXc+d4%-V@d-L+3"%)L0E4%-c4$-c)L)d3c)L@dZd4%3cY$0$)f4$) -LN!3b)PY$-c3cN!3L)N-b)LC,Zd4%-b3d4$)QY$)LN!4#)V4$-c3l-j!$)L)c-L+ -eZlZd4$-MY8-b*N-b)T!%3b+l4$0$-j!$0$)L)M)LDlZlY%3c+eDd-MBc-b+3"$3 -LY%-c0$13"$)L)M-PDlZd4%-c1eCPXN8c-b+3!a%V)N3cN!BM)T!$-caEZl4$-c0 -,9E99Zc-b)T!$%4Xb0$13!c)M-b)L)5)b9EZ3!c-L1l9EZl[--b+3""%E3c3c-c) -L)c)LN!3c@lZ3!d-M5e9EZl4ADc)LN!-4%e-l-b-b)M)b)T!$)$C9@lZlXcZe@lZ -lY,aQY$)L)K%5`c3b-c)L-M)LN!-Vc&@lZl3c4E9EZlY$YV[&Y#)K%4,,*$-M-L- -LN!3V8la9ZlZc0&YEZj!$-f@e9QGfZlYSfc4$)M)LN!3VC6-m9EZdY,@lN!5d3f@ -lZeA-amc-M$3c)T!&1maE3c9VZlY9DlZ3!l4$1f@l4,Z3"$0V4$)L)L-L)XaV4$- -cbe9QCEZ3!d4%-c9EXc-d4$13!eZlN!1e9V9F@l-c-b*P9P@lN!0%3d-c0VY$-j! -&0'Xc-l0&E-c'3c-c)L+m9PZlZl4$0$-c0VY%-j!&ZlXb-cAF@lY%3c-b)L%X99Y -%4%-cN!3fY$13"#)NY$1c)heEZl4%3b-L)c*'9E3cN!3b)c1fXc13"#)VXc06@0@ -l4*!$-L)L098d@l-b)T!%)c+l3c13!c)L+d-bE0GEZlY%-c-L)VZlXeZc)T!'-VX -d4$-c-L)NXc*&@lY%4$-c)L+l-c0#Zl3LN!BbZd-cN!-b)L08-d5d4%-c-b-L+d- -L)M0&Y$)cN!-L-c0E3c13!c)L)QZl-l-c3c-b)L*$-L)L-c5l3c-c-L)M-fXc-c4 -%-L%Pbc)N8c1d-b)L1l-b)L)c-l4$-cZdY%4EZj!$99Xb*'@c)M1c0&@c)L-l-c- -b)MZlN!1d3c-b)VY%Zl-cYEYQ4$)L-N)VaV-K%83L)c-b0%4%3c)dY$-L@d53!c5 -l9V)N3b)c0$5e-L%5Xc13!c)VZl5d-dY$-L+l-c0%-c5l-L+d-c-N4,Zd-L)b)c0 -%-LZlY%-cN!-M)VXcN!BL)MY$-c1lZc3c5c)M-c-b+d3c-c)L-b)L5c-M-j!%)L) -MYEZ3!c-L-cXb)c0$-L4%0$)L)b+3!cXb)c-c-L)M)T!$)c13!c)L*E-cN!-b*%X -c-L-c)T!$06-M-j!$)L)b)L)c-b-c3b*#1c13!c)N5d-cN!-LN!-Q3b-cN!-LN!8 -M-L)L-c3L)d-c-c)MZd-cN!-b)L)QXc-d-c-L-c)L)M)b)L)M3L)L)d3c-b1l-j! -&)L)PY$13!d-LN!NM-L+3!c@c-cZd-j!&-M)PY$13"#+3"6-b)T!&-b)lY8)eZd3 -cN!3L)LZc-j!%)T!+)b-c)L-d99@l4,-c3c-L)LYL-j!%)T!$-L+3"M-M-c)L-c) -L-j!$3d-c)L)MBc-L)M-LN!Jl@d-cN!-L-L+3!b-lY$-c)L)MDc)cY@Xb)T!'+eZ -l@c0$3c-LN!-c-N1d-c1c)L+mZl9EY$)L)M)LN!-VZl3c0#-c3c0%-b)N-N4$-c5 -l3dI'@d4%-c-L)L-L)MZlY$)LN!8M-L1c-d4$-b)L1l@d1c-c0%-b-c-b)VZ3!c- -LN!BVZl)b-c-b)T!$5l-N3c-dZd1lZl4$@lZl-b)L-j!&YN)L)c)LN!3M-L+dYEZ -lY9Zl4,9EY%Y$)L-c-b)L)cXb)T!*)f@d-d4,3c13!l0$0%)L)c-LN!-b)l)LN!- -K)T!&Zd-b)M-c-M3c4%-c0E)L)L-LN!-K%V)LN!F4*&3c)K)K)L)l4$1c-d8b)T! -%)5)L)E3LN!BK%5Bd-L+3"6Zl3d-d9$)LN!FK+c)LN!-M)L%4YM-LN!3K)NZl3dZ -l3c)LN!-M)L)5)4-b%4)L)b)K%FXLN!84)N5lY,Zc-b)K%M)LN!853b%4)M)L)5Y -c)T!(-d3lZlXc)L)!N!F1!!$ZN!B!!Gf3"J!#c*!'!!1lN!B!"+U3"J!&L*!'!!C -hN!B!"e@3"J!)4*!'!!NLN!B!#K'3"J!,QC!'!!aQN!B!$613"J!2!*!*3J$`!*N -!N#m"!!%!#3!!6)N!$!!!6)`!!!Q)N!!!N!6q!!B!!2rh!!B!#`1l!!N!!J#3!cm -!N!H!!*!("!#3%#!!N"!"!!E!!*!'SJJ!N!3"5J!!!B!!!0!!!"$#!#YDa%S!ri2 -P%))"!"*AKm(Jq)8!"8!&##2`2r`!IJ#3!acJ#!#3"5!!!!jJ!!!3!*!&J!#3"`i -!N"!J!*!3!i!#K%!3`#!)&!83!#!34!!!!`!##4#EB!!!%83!&!r%5J#ZqU83JJ% -!%P@pIlqSK3!&3!8))r!rr!0#!*!$#4!8!,R!!!3J!`!*N!!!e6RX6#!!!6PcKIG -pcJ!"a(HGlrh4iB`M&hRHGq-BaMr3d"!J!)$"#BB!N!33!*!$"8ehb+8*)&+&DZG -m$e+)SLR4"+2L%L%Y&f)!%NN!+eV%5J$Glf83JJ%!%PEZkh[BK3!&3!8))r!rr!6 -!$i!0R4F3!8IJ%KSJ")!*)2(IeV+5U3!"4ia0#!Ba"")ZM'-B3M&"P$HBaM'*)aL -U)C!!D!JJ!)%"!))!N!33!*!$"9D2`!!!`!!!!4M!&!#3!`)a*"85!!!"QC!!!"9 -3!"32a%S!VYDP%))"!"*9hAHeU)8!"8!&##2`2r`)`!5!!QXBL!p(rj%U*!bi18# -4K9,8)A%!!Nd)9Hm'-D[S2iaK'%)43D3V@-BaJ5-BNL+)3!2mjlZIkC2V1mqcrM' -XBr9!JTch[HjcR*-B`G4cR4M'-AFr&cjdE9Q5!!UV!#YDamS2hHpPm))"!"2@lZY -lhq9q"Ai&IL2`2rhC3I)r)L[iZh,(i(c))(0m+Ik9MlP))Dr2`P84T"L*d4!%9Iq -K(hTr3F3M12SqF5-BN85)3!4M'-8M'D0FaM(-%M'USLNJJU-BaM'-BT2rqVk-BaM -'-D`*iND-FcGNIr$,6*32r([aVYDr(rq3!rjGhAHeU"q"rmRrLIq3!riT3+&&)LX -BaV,(rj%S2iKm3!k9K4@e)5%!"'8JIKL5,`[SPBaK'%)a8D3M'-)a#5-DN!#)K%! -%B`Mp)aRM@-BaJj)aU5*&3)1r'-B`rrk6'-2dM'-BaM'N2b*'M'-3#%!K$j*V@XI -+Aph[B2%!#3!6eZlVHprJIP"r4Ai6rrm#+-#L45)G'-Gdaq!5'#"`Id!1P3"@XK) -"!!4&4%8BNL%%%!k-BaK#-9'8)aM#-BNLVDL3!)4!"1-)`5-CNeM'-B"5DUULK8# -*)6R1F)3JNaM#P)aM1FBaV%Pb6ScM(rM!)J159!r%5P'ZeU!"!!N!%PAGGl@S!!K -3#88)%rrr!LM!T-8L#49%&-IrJ!JNJ$L!!*'!1Nd-!"!S1IZ%ja(1S!#+Mjh[`G( -ZMq-A3G&a(%M%Rm,(ihch[4mCLeLlciH0T&4Ip8"a(YDeVh[HNaMqph1FeVh1GiN -L0R0M%!F!!i0-UeV%5P(Glf!"!!N!%PEZkh[B!!K3#88)%rrr!GY!VlR5(1fi$dI -JIrNJ!!#!!2%!%!#3!a!)!*!')!!+!*!+)!#3"3)!N!8#!3!!!J%!N!3#!i!6J!! -!"!#3#33!)!!b!*!*&!r%5P(rrm!"!!N!%P2rN!2i!!K3#88)%rrr!!J!!!%!N!3 -)Iq!!#5!!N!SJ%!#3"N!!'`#3%!%!N!8F"J!!!J%!N!3F!3!J!*!$#!#3#6J!N!- --!*!*!9V%5P%!N!-"!!N!%P!!N!8)8!P&#"2rr`#3"!%!N!33!*!$#-!!N%S"!!3 -!#3!1!"-!'!!D!"d!)!!P!#S!,!!b!$-!13!q!%!!43"+!%m!9!"C!&i!B`"S!'N -!D`"Z!(-!GJ"l!)!!K3#+!)m!P!#C!*i!S`#S!+X!X!#e!,S![`$%!-N!cJ$6!0J -!h3$L!1F!l!$a!2B!q`%!!3)"#!%+!3d"%`%9!4S"(`%N!5N",J%b!6F"2!%p!8! -"43&(!8`"83&@!9X"B!&P!@S"EJ&c!AJ"I3'#!BF"M!'2!C!!!C-"Q!'B!Cd"SJ' -R!D`"X3'f!EX"`!(&!FS"c`(5!G8"e`(F!H%"jJ(V!I!"p3(k!Im#"!)*!Ji#%`) -B!Kd#)J)R!L`#-3)f!MJ#23*#!NF#6!*3!P3#@3*H!Q-#D3*[!R!#G3*k!Rm#K!+ -*!SS#MJ+5!TF#R!+J!U8#U3+Z!V-#Z!+m!X!#``,*!Xm#dJ,B!Yi#i3,P!ZN#l3, -b![F#q`-!!`8$#`-4!aF$(3-K!b3$*`-V!c%$0`-l!ci$4!0+!dd$8!0@!e`$B30 -R!f`$F30h!h`$JJ1(!i`$N31@!jX$S31Q!kX$X31f!lN$[!1r!m-$b!20!p%$eJ2 -A!p`$i!2N!qF$l3!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J! -'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!D3!`)'!3B!"J!'!!B!"J)'!3B#"J! -'!!B""J!'!JB!"J!'!JB!"J!'!!B!"J!'!!B!"J!'!JB""J%'!!B""J!'!!B!"J! -'!!B!"J!'!!B!"J!'!3B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J! -'!JB!"J)'!3B!"J%'!!B!"J!'!!B!"J%'!!B!"J)'!!B!"J%'!!B!"J!'!!B!"J! -'!!B""J!'!!B!"J!'!!B!"J)'!JB""J!'!*!$"J!'!!B!"J!'!!B!"J!'!!B!"J! -'!3B""J%'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B#"J! -'!!B!"J!'!3B""J!'!!B!"J!'!!B$"J!'!!B!"J!'!!B$"J!'!!B!"J!'!!B!"J% -'!!B!"J!'!!B!"J-'!!B!"J-'!!B!"J-'!JB""J%'!!B!"J%'!!B!"J!'!!B!"J! -'!JB$"J-'!JB!"J!'!!B$"J!'!!B!"J-'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J! -'!!B!"J!'!!B!"J!'!!B""J%'!`B!"J!'!!B""J!'!JB!"J!'!!B""J!'rrm!!![ -mN!!!N!6r!!F!!2rp!!F!$`6d!!`!!`#3!d-!N$0!!*!)!F!!N!`d!*!&!UUeBL8 -!Ir!r+)3)!3!%46i2`2JIL#J!"5!!8%#(m"rr`!#3#!Fi!!!%!*!'!`#3"b!!N!K -!!*!2!3#3%N!!N!JU)J#3"9+!!!"J!!"B!!!""!!"8"rL*3"A[l8SK!J"!!4&+[V -rVr@)+!!&)!"33)I`(rr!!*!)#2`!!!3!!!&-!!!$!"!!$!#3!b!!N!MJ!*!2$`1 -!!*!3i!#3"$!!N!-#*!#3#B!!N!8""!!#UV9L*3"V@ZXSK!J"!!4&0leVhAU)+!! -&)!"33)I`(rr!!*!%!F!!`!Mm!!!%!!!"XJ!!!p8j,&)J!!"1A1&mhh1!!"a(HGl -rh4iB`M&hRHGq-BaMq)#3!!3)!#!`3Q!!N!J"8e`"%!4)#!3&1Gm$f!34!(4!D2L -#4#E&lL!"&&!"8"rL*3"A[A8SK!J"!!4&+eVeVV@)+!!&)!"33)I`(rr!Gm(`!!# -1F3!)r!!%"!"J"b32J!2IeV*5U!!!8H-633'-3))Lk-BaK#-8'80aM'-BNM'-BKL -!U!))!#"!3Q'!!*!$"!#3!`&9SU)T3NJ8SPV'-!8NSLL+M%#&4)5)5dBa)!%NN!! -#UV9L*3"V@ZXSK!J"!!4&0leVhAU)+!!&)!"33)I`(rr!LN%3!0b4L3!Sr!#*K!# -3!!8Tk)!$e9,5BA%!!*&#&8)"M%%"!rM'-B3K&"T#ZBaM'")aM')B3-3!#!!J3%! -JJ!#3!`3!N!-"8#)!N!-`!*!$4M!&!*!%M%L2a)!!!'Ba!!""!!&3(q)P!&HpG5L -%#!%!"%8V@[@ZYBJS!!8J!&"!Kr!IrpZ+!)!")G')J#Mrj&*%J*!!"6rSJ!1&-G3 -KF3!!Nd*THm*dDRb&@2S4K#%8(%)eM'-B%M'+SLK!J!$r1HlRqQ6lc[2XlSaV'2e -3)4FplhZFjb6'-(8FjdBaM&b#4FqG'eBa)!#b8Y+UY@2P"qYDkbq%#!%!"(dh[@[ -GH[mTr!8r`&2iKr!Irq552NIL)M',`1Mm"#T%#@F%!HL!!iqBL#'[`!%94"q'*)a -X!%PIaK(hTr3B3M12SqF5-BN85##!!4M'-8M'D0BaM(-8M'USLNJK'-BaM'-BT-B -qVq-BaM'-DmriND-FcHiRrdc9+9!IrMhieleeq2q3"FAV@[@ZYB$q!rrL2ra(rj! -%j*)8+5)L2iah@2rr4JIf$i3"k)!$K498)5%2i4P)%3BNLm*mL9M'%B3M&"a#-B` -M%*)aLSL)))!"'-)r5-C`eM'-BZ5-DNL48#%IaM'-2rqNrr#p)aM'-BaSJN#4SaM -%!%3##9S@UV9Mj5rV@ZX(L!!4!!4p0leVhAVr!IbJ2qK6q%Irrq!ELK4*)L)aM'Y -Br!5#*!N2a!(SJ!-!&E+K!3!#%9!4"L5)33%!5-B4K#-9'N)aM#-3NM'X53J3J!% -B`M")aQM@-BaJ&)aU5+&3)4K'-B`K##6'-+8M'-BaM'L55*'M'-IrK!)6qK93(q) -P+0HpG3!)!"%!"%8V@[@ZYB!!)+!#+&"!4rrri!#+&)NL)M&8GeMrj"iNPJqd!HL -!!i"@X4)!%")4B4&'*)LSJJMSaM'%)a8C3M'-)aL5+Ya*#"#!!6M'-8M'C0BaM'% -8QUUS`9!M1-jcR'-)T-B`V5-BcR'-DT*FNk-ia!#)!#"9+UUeBL8SkeVV!!J!%3! -%46HpDpekJ!!JS!)S8%"(rrrJ!)S9'5BKd94"@2`!iKJ!"``!#)!$J$T1NJ!3&!j -qi6R%FbJ!#+Mjh[`G(ZMq-A3G&a(%M%Ri#)2ihcRZ4mCLeLlci10T&4Ip8"cA0De -VR2FNaMpeh1FeVh1GiNL0R0M%!(!!H&,48"rL*5MA[A8!#!!4!!4&+eVeVV@!!## -J!LK33%Irrq!!XKAf1K#1fi$Sr"m#!*!$"!!2J!-!%!!-!"!%!*!'#!!!S!#3#3J -!N!81#i!!N!@!3!!!J%!!N!5!i!J!N!-"!*!*!3!)!!L!!*!)!UUeBL8SkeVV!!J -!%3!%46HpDpekJ!!JS!)S8%"(rrrJ!)!!!#!!J!!!L2`!!J#3"`-!N!8J#!#3"K! -!!+!!N!N%!*!'"!#3"3L!3!!!J%!!N!-)J%!)!*!$!3#3#3%!N!-2!*!*!9!IiL8 -Srrrq!!J!%3!%44rrN!5!!##J!LK33%Irrq!!N!3J!F!!!)rm!!)!N!F$!*!'#!# -3#!'`!*!3"!#3"3F"J!#3"`F!3"!!N!-#!*!*$J#3$JUeBL8SJ!#3!`J!%3!%43# -3"b#J!LK33%Irrq!!N!`#!*!(!`#343%!"!!*!!i!%`!C!"S!(3!J!#8!+J!X!$- -!0!!l!%!!3J"(!%`!83"@!&X!B!"P!'S!D`"Y!(%!GJ"k!(m!K!#*!)i!N`#B!*d -!SJ#R!+`!V`#d!,N![J$$!-J!c3$5!0F!h!$K!1B!k`$`!28!qJ$r!33""`%1!4% -"&J%G!4m"*!%T!5i"-`%i!6`"33&'!8F"5J&2!9%"9J&E!@!"C3&U!@m"G!&i!Ad -"JJ'(!B`"N3'@!CN"QJ'G!D)"SJ'R!D`"X3'f!EX"`!(&!FS"c`(8!GN"h!(I!H% -"jJ(V!I!"p3(k!Im#"!)*!Ji#%`)B!Kd#)J)R!L`#-3)f!MX#3!*#!NF#6!*4!PB -#@`*J!Q8#DJ*[!R8#H`*m!S%#KJ+-!T-#QJ+E!Tm#S`+S!Ud#X3+h!V`#`J,)!Xd -#d3,9!YN#i!,R!ZX#mJ,j![d$!J-(!``$%J-B!ad$)`-T!c!$0`-q!d8$5J01!e) -$9`0H!f8$D30Y!h3$H`0r!i-$LJ13!!19!jS$R`1N!kS$V`1f!lX$`!2&!mS$c`2 -8!pN$hJ2M!qJ$k`2Z!r)$pJ2l"!!%N!-*"!S%$`36""F%'`3E"#)!"`!(!!F!"`! -(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`! -(!!F!"`!(!!F$"`)(!3F""`%(!!F$"`)(!JF""`%(!JF!"`-(!!F""`)(!3F""`% -(!3F""`%(!3F""`-(!JF""`%(!JF""`%(!3F""`%(!3F""`%(!3F""`)(!3F""`% -(!3F""`%(!3F""`%(!3F""`%(!3F""`%(!3F""`)(!!F#"`%(!!F$"`%(!3F""`% -(!3F#"`%(!3F$"`%(!3F#"`%(!3F""`%(!3F""`%(!3F""`%(!3F""`%(!3F#"`- -(!JF""`!!!3F""`%(!3F""`%(!3F""`%(!3F""`)(!JF#"`%(!3F""`%(!3F""`% -(!3F""`%(!3F""`%(!3F""`%(!3F""`%(!`F""`%(!3F""`%(!3F""`%(!3F""`% -(!`F""`%(!!F!"`!(!`F!"`!(!!F!"`!(!!F""`!(!!F!"`!(!!F$"`!(!!F$"`! -(!!F$"`)(!3F""`!(!!F""`!(!!F!"`!(!!F!"`)(!`F$"`)(!!F!"`!(!`F!"`! -(!!F$"`!(!3F""`%(!3F""`%(!3F!"`%(!3F""`%(!3F""`%(!3F""`%(!JF#"`- -(!!F""`%(!3F""`-(!3F!"`!(!3F!!3!(rrm!!"%Q!!%!N!-F!*!$6J#3"2rr!*! -3J%!!N!9!!%!!N!P)!*!$5!#3"3J!!3!)!*!'%%i!N!3%N!-&"*!,"C!%!J%#!33 -&"33%"3F4%JS&N!`#!J@3!`F("!N("3H3"!8&"*!%"`8&"*!,"C!$"*!$!3)""3F -,%483"`@3$3)#"38(N!-%#3F&"3F*"`8&"*!%"353%`8&#a%A%3X("C!)"!@3"!3 -&!3)&"!3'N!-*"`F&"3F*"`8&"*!%"`53"`8%N!8&"j!$#a%@&a)2#33&N!B%"38 -%"33&"33%"33&"!3'"!H3"!8&"!X,"`8&"!3&"`F&N!-(#JX4$!X,$4%5%KFB'4N -5#J3%"`N("C!'"!8%N!J&"*!H3!`@3!`B($3N&"`8("a%A&K3B&"L3"4Q3""J -8%K%*"`8%"!8,"`@3"!53#`8&"!F%"!N(N!-&N!3%"`X0%!d4%4-3#j!%#T!%#a! -,N!-+"`F,#`F("33%"JN("C!%"!%%"!8%!33%"3F(#3F%"j!&"33&N!-%"!X0$!X -,"JF("353"!%""j!*#`H3!`3'"!N("C!&"!3(#3N("`N("`3("`3*"j!&"!8&"`D -3"33%#`F("C!&"!%(N!N*"j!(#`F&N!3,N!-("33&N!-%"38("!N(N!B&"`F'#3N -'"*!$"j!$"C!%"!3"#3H3#!B*"j!'#3F&"!8,#`F&N!B%N!-&"`3*"j!*"T!$"35 -3!`F*"`F&"33&"!3*"j!3"3X(#a!,"`8%"353"J@3!`3,"j!$"JH3#!8%N!3*"j! -$"C!$"!3,"j!*"!H3"J8,%!X("`8&"*!-#`H3#J8&"!3&"!3(N!-&N!-%"!F*"j! -*"!H3"J3'#`F("C!$"*!("`53!`B,"j!+"C!$"*!%"j!%"C!$"!X(N!S%"`B(N!3 -%"JX("`8&"*!)"C!%#`N(N!S&N!3%N!3(N!-&N!-%#`H3#33%"`B(N!3%"!X(N!- -&"*!)"`8%"!H3#`@3"!F%N!3'"C!&"`X(N!N%"!B'#3F("J3%#`F("C!$"*!("`8 -&"!H3#33(N!-&"3F&"353"!@3!`30#3H3#!8%"!B,#`F("*!$#`F&N!3%N!F("`3 -%"j!%"3H3"38("`@3"353"!8&"!X,"j!*"T!%#3d0#3B%"JX&N!8%N!8"!33("38 -(N!3&"`F&N!8("33&N!-%N!3&"3B0#3H3"`B%"T!$"`Q3"!X*#3F&N!8%N!8"!33 -*"38(N!-&N!i%"!%%"!8%#3X(N!F'"!3'#!B,#3N(N!33$3F&N!-%"33&"!3"N!- -("`8(N!-&N!3%"C!&"*!$"353"3F'#`F*"`N(N!3'"!D3!`X,#3H3"!B*%!X("C! -$"*!%!C!%"`X&"!F("C!%"!3&N!F%N!8!"JX*N!3(N!B%"`B,#`N(N!F0#`X*"`8 -%N!8"N!-%$38&"`F&N!X%N!3&"!3'$3d,#C!$"j!&"JB*"JX*#3H3"JN,#3N0#3N -("*!$!C!%""!("!F("C!+"*!%"38(#`B($3X*"j!&"T!$#`B*#3F*"j!&"!X,"`N -*#`d4%!X(N!-+#a)@"`8("`@3"33&N!-%N!3&"`X,"`8($3N*"j!$"T!$"`X*#3H -3#3B0#3H3"!N,$C!$%!f3""%0"!F("C!$"!8%"C!%"!F($3d*"j!$"3X,#3N("`N -*#`X*N!-(N!S,#3H3$JX*"`F&N!-%"33%"33&N!-4$3X(N!3&N!-0"`N*#`d,#`F -*"j!+"JN,"j!+"38%"!8,#3H3"3Q3"!X*#3X1#3H3"3@3!`3,N!--#`N*"`N(N!S -&"!X*"j!'"3F&N!8("`X*"C!$"`F&"`X,$C!%#`H3"3@3!`3%"`d,$!N*"j!0"3B -,"j!("C!'"`F*"j!$"C!%#a%0#`N(N!J&"353"3d,#`N(N!J&N!F'$3H3!`8("`8 -("C!&"j!$"3F("38(%"8,"j!)"C!%"!3("!3'#`X*#3F("38("C!'"!@3!`F,"j! -$"C!$"`F&N!3%"j!$"38,"3X5%`X(N!J&N!8%"!N,#`B'#`H3!`8&"!8%"C!%"*! -$"38(#3H3"!8(N!-&"33&"!F("C!$#`d9%3X(N!N&N!-%N!-(#3H3"!X(N!-&"!8 -%N!J&N!-*"j!'"38("38%N!-(N!-&"3F,#3H3#3@3!`53!`H3!`8%"!F%#3N,"`5 -3"J8&"*!$"38%#3H3!`@3"`53"!8*"`F&"`B*"j!("C!%"*!$"`F&"33&"3F("JN -("`8&"!3("C!$"*!$"38%#`H3!`@3"`53"3X("`B%"JN'"j!%"C!("!F'"38%N!3 -'"!B'#3F("38("C!%"*!&"JX(N!-&"3H3"!8%N!3,$3F'"!3'#`B%"j!%"38%N!- -'N!3&"33&"!3("!3'"JH3$3X(N!F*#`N'"J3%"`X,"JB%N!-'#3B%"``*"`8%N!3 -'"`F&N!F(N!3*#3H3"`8("C!$#3H3#JQ3!`X,"T!$"*!$"J3'!`3($3d("*!$!3% -'"`@3#!3(N!F&N!-(N!-&N!3,"j!,#`X*"!3("`53!`F%"!B%"`N*"`53!`%%#3@ -3"!H3!`8%"!H3"`8&"j!%"C!%#3H3$38%"33(N!-%"`3%"JB(N!-'N!-%N!-&N!3 -(N!3&"!3(N!F&N!N%"JF("C!$"j!%"C!&"!3&"3N("JF&"!3(N!3'N!8("C!&"j! -$"33%"JH3"3@3#J3'"`@3"!F("C!("*!$"33(#3F*N!-("`B%N!-'"!B("`@3"!H -3!`8&"!B(N!8&N!S%"JN&N!i%N!J&N!-("3F("*!%#`F&N!B("38%"JH3"3@3#`3 -,"`@3$J53"3@3"33&"`F%N!-'"!F("C!)"!B(N!3&N!`%#`F&N!3(N!-&N!3%N!- -&"*!&"C!+"`3&N!-("`8("C!$"*!$"j!%"3F&"3F("C!&"!3,"`@3"!H3"!@3"J5 -3!`8%"C!'"!8%"3F%"!@3!`3(N!3&"`3%"JN(N!-&N!3("`@3"33%#`N("C!$"j! -%"C!&"*!("33&"*!*"38%N!-(#`F'N!3*#3H3!`8%"j!$"3F&N!3%"!N*"`8("C! -)"*!&"33&N!3%N!3&"!3&N!N("`N'"!B,"j!)"C!&"*!%#3N'"3F&N!F%N!B&N!8 -%N!J&N!S("`N*#`X(#3H3"38("C!&"*!$"`X%"C!&"!8&"*!'"C!%"*!+"C!&"`@ -3#!3%"J3%"JB(N!8&N!B%"!d%N!J&N!-%N!3&"353#!F*#`N("`@3!`F&N!J%N!F -(N!B&N!8%"!X'"*!%"`X,#38&"*!&"353"`F*"j!$#3F&"3H3!`@3#!3%"38%"JB -(N!3&"j!$"353!`F0"`F,N!-(N!-&N!3%"C!&"*!H3"38("`8&"j!*"38%"!F -%"!H3"J3(N!3%"a!0#`X(N!B&"`53"!8%"C!$"*!$"`F*"`F&N!N%"!8%"!F&"!8 -("C!$"j!&"C!$"!3("`N*"`B'"`3'"j!&"JB%N!-&N!3%"!H3"J@3"!3%"38%"38 -%"!8&"`F*"`@3#33&"!8%"!H3!`B%"JB%"JH3!`N*"JB,#3N(N!8,"j!'"C!$"!@ -3#`F,"`@3$J3&"3F%N!-*"JF,"j!%#3X,"`N*"j!$#`X(N!B&N!i(N!3&N"%%N!- -'#j!$"`8(N!B&"`F&"3H3!`B(N!-'"J@3$!3("!8&"`@3#!%&N!-%"C!%"!3'N!- -%"C!$"!3'"J8&"!H3"`B("33*"J@3#J)&"!3#!J8("C!+"!@3"!)#"!B*"JB&N!- -""!3""!8&"!H3#!8&"`X&N!X""38#"3)#"`F&N!-%N!B&N!3"!3)&#`B("`@3"!5 -3"!@3!`H3#!8(#3F&N!S%"C!$!T!%"3F&N!-""*!&"`8%"3)#!3F,"C!*!38#"38 -(N!J*#3F&N!8%"!8&"!8&"*!$!38&!J%("`8"N!-%"!@3"J)"!JX("C!+!J%&"3H -3"`N(N!-&N!3""!3&"353"`8%!J%%"`8#!C!$"!3&"33%"3%&#K%&N!`#"C!$"j! -$"!F*"j!%"C!%"!#3"aN!!2q3"*QC!!(rN!4QCJ!#rj!%-c-!!rrrc-bCQ3!%rrr --c'CQ!!Arrmc--c-!"[rrQCPQCJ!(rrqCQ6-c!!MrrfD3"!!*rrpQCM-c!!V-c*Q -C-c-!#mc-CQBc-`!-c-aQCJ#3!`h-c$13"!!1c-`c-`#3!`qCQ@CQ-c-!%*QC-j! -%!"'CQ6-c!*!$%QCQ-c-!N!-6CQB!N!88-c-!N!89GhF!N!8@998!N!8A4%3!N!8 -B)L)!N!8C%4%!N!B)[J!"!*!$(!#3!di!N!6rr`#3%)!J!*!&3!"!!*!*5!#3!dJ -!N!8%!!%!"!#3"JK1!*!%E-CXc-c'Gfc-c'c'TRT'c-E-aQE-c+CR%A4(DQc-E-a -QUNGQChHU4Xc'c-c'aUE-N!2'E-c-5RUUGUCk4QCXE(DNCXCN&X4-c*!$aNChT-E -'c-aXE-4QGk&(4NC-afTXT+TRDNT-a(E-N!4UV'DQc-CXc-aQaRTkGNCfGdCQc'G -QCdG+UNG'aXc'aQI-ChCQc*!%C+Ch4NCf&QCdCXaUc%DQ4'4'4QGXc-aQI'aRc'a -QCRTRC(4RDKCfUQ4QCmaQ4+HU&NCR4(CQc+GQaRE'c'TdCU5K4dGRCdGQG'TfE-c -'UNTf5RC'5QE'GkGXCmE-CU6-HRTf4(S@G%HQ4kCQc-aXC"URCRCk3@c'HQc-CXb -3"'G'4RB@C%CQC'Td4-b3"'HUCRGQGQChaQCQC'a%CRDNCfS@Gk4N4NCf4XCXc*! -%TR4'GNGXCmaXCfc'CQE+CdGRCdGhGRGfC'6-aXb3!m6'ThCk4UahChc*aRafaN& -kG(SATf4R4fD3"-b3"-I-akGfGfGhc%GNCkCmCXCfTNCNC'GKC'CUC-b3"XCmGj! -$CQCR6%V+4'I'4NGfCkCfS@GUGT!$E-b3"'c'I+CQGk4dG%4d5RCQDXCfCQChGRC -dGQHNCQc-N!4Xc(c"GhDQ4RB@C'4'GdTfCQI+TRbKCd4kaQE-E-b3!dE"c'E'CRG -U&RHNC%CRTdaR5Q4fGQG%CQC%E-E-CXc'CRc'N!2%GfGR4hGfGQ4NI'bKa%HKCaC -%C'c-c-E-I-CXaXaXChGdHKHRC'GNC(E'E-a(B@C%CXGhc-c'GhE(Cmb3"AGf4Q4 -NChThCf4fGQV-ChT'4'aNE-c%GhCfE-I-c-E-a'CRTRDRC'5NE%G-b'CQGhGRHQV -'c-CRN!0%E-E-N!0XaQChGK5NUNG(CfG#I(V'4R4mE-CXI'Gda%V-I-b3!f6(CRC -dTkDUGN4k&R4'&TGXGm&Uc-E(FDaQUXb3"FI(4'Tm3@4f4RB@C%CU"T4QDNHXE-a -Q5Nc+'XD3!mb3!fCXaXI%DQDNTRHNC'GX&mUKG(E'E%akUQ'NE-b3"@ahCdV%Cfa -hCQCdE'I(N!#N5N4Qc'c'c%'K&Qc-c'E-c-E'4%GNG(CNCRGhc(Cf&KP+T'CXE-c -'a"&Qc-c'CXc-E'CNT(4NGR4h4RCQCXI'G"CdI-c'E'E-a-b3!fE-N!6(4RC%aRD -QT(GhTQE(DQ&"c'b3!mc-aXc-E-CQE-c-E'I-ChGU`AHRGQ4fTU4'4%5Qc-E-CXC -XE-aXE'4'c-c'C%SDG(&fGNC+5UU3!k&+4d&XCXE-CXE-N!4UTmaXE'5N%8Tk38T -+UU4"SDT+GfCNTQc-CQE-E-aXCU'UGQc'C%T%C'T+HQTUUX4'4Xb3!fc*TXE'E(c -'CQCf%4UNGXCRHUT%G+3@4dG'aQI-N!2'aQbTE'c%c-E-E'CN%D&faXGd5QT"a%U -U5USAE-c'aQE-N!1@E'I-c'aXaXE"URE(E'G+UNTU5NUUUNI-CXCQaXaQE&PQGma -QCQGQCmG"GQCRT+5USD&+S8UUa'c-c(aXE-c-aaT+DUCQI(GQE('XE-ad4(&"4%T -%T%4NaXc'aQCXN!3CN4UQ4mE-aXCN4QbNG%TdE-E(5NUK5@aQaQaQCXc-aKT8NCS -DE(aXN!9mBDT'aXaK4*!%GQCNE'D3!fc-SA%4N!-Fc*!$aXCXCXCfV-E'bNT+DQT -XE-aXN!6-CUT"4"%4('CXE'D3!fGUa%V+CQUUT+T'Gmc'N!6-CQ`4&"4%%4GQCmI -+bNUUCRUQc-c%UNC+4(4Qc'CRCfE-aNT+4+UK&dGQN!0N&(TfBD(-E'aUT''THRa -QE'GXafc'&+CU%4&"5RCfG(T%F8TaS4UU&QURDNUKTQaQafCXc'`D4Q3D4+4hGXa -RCkC(G%SD&"5R5RT"3DUNTQb3"-CQUUUKUUUKCh('N!0RCQDRHN53!a4%3D&"T"& --E'E-akC"UUSDT%4fGfaRCfT+&dT+4%5N4'UNS8UK34C'E-c'TK5NDUTQYQE'CRC -'T+UK3A&"UT!$5U'K5U38UQC%CQC(UU%AUN4kUQE-c'C%UR4h4(4%G%6%5N&"UUS -DUUG+CN4(4(5N58CkI'aXTa&"S@&kHNSDS8UKT*!$C'UN5RCa5RCRTkC+GNGQ4XC -m`DT"4+5N4%TdT%T+DUTmCU'3!a%4aQ4QaQI'Gfamc-c'TQGUHT!$UNUUT+HUSDc -%UN4d5NV-SDUKV'D3"-c-C%4U4NUUUNUU&-E(ah4mc+GXbUUUaUSD3@E'UXamc'a -+5Q4KG%T+UNT(E'c(C+c'N!5T%@GUT%CQCQQQCQCf38&%4NDUTU&"GXc'aQ3@c'c -'CN5U%CURDUC'Ci&XC%U3!d5NTUDU'U&%GfE(a+E-aQC+DK3@4QS@E-aX4'aQT%T -RTNTh4mC"3Ac(E-aXUXc-bRTd4%UNG-6'CN&Qc'HUUNT'5N4fc-DNTXE-E-bUV-c --CQa+3Dc-5XaXa+4QDUU3!dCK5Rc-CK%AaXCQCUSAaQCXaQT%4Xc'aXb3"'UUDN& -kHUTmE-bR4XaXc'GfCQc-N!4Qc-c'c*!&aNTkGRGUG"E-CNCXN!0QUUT"GXE'c-b -RE-aXI-c-CXc'F84aGd5UNfaQ4Qc'DT!$GQT%c*!&CXE+aXCQCXaQG'4fI-4Q4'5 -UI-4Q5UUU3A&a4QE'c!#3"``!!*Q3"J!"CT!'!!*QCM-cCQB!!c-cCT!%!!3c-fC -Q-c-!"613"'CQ!!BcN!B!"`!!998!N!-)UT!'!!PhN!B!#P@3"J!,4*!'!!`LN!B -!!"%@!!%!N!-F!*!$6J#3"2rr!*!3J%!!N!9!!%!!N!P)!*!$5!#3"3J!!3!)!*! -'%%i!N!36"a)*"`S5%`J#!`)4%K86#3B(!`)$!K)4!`F5!`)4!`B#!K!#!`8#N!3 -"!T!$"J-3!`8'N!-#!K!$!K%$"K)(%a-)%JB#!K!4%JN)%JJ("`B'!K!#%`)#%3F -#%3-'%JF5%JF'!K%3!a!$%3-#N!84!J-(!J-4"K%(%JB(%`S6%J+3!`-4!`B(%4% -6%4)4!`B(%a-'!J-'"J)(%3B(!`-'%JJ9#48(%j!$"K)5%"!("JN6"K%'"a-(#3B -*N!-#!`)#%J-3!J)(!`)(!J)$!T!$%K)(!`B'"`-4!J-#!a%#!J-#%3F$%a3(N!- -*"a)("K)("a-("a13!a)+"a%$"a%#"J)#%3B5!`)'!K!#!3)'%JF'!`8'"`B#!a! -'"a!#!K-8&3F$!JB#!K%$!K!$%JJ(%K)#"J-*"a)#!K%(%4!'%JB'%K-(%K-6"J- -$%JB6#3N)%K%%%JJ$"JF6N!-(%a3*#3B$%a-(%JB#"JB$!J-#%`F'!a%(%3-4!`) -3!J)(!J)$"JF(%JF$"JF'#K-0#JJ5"`-4%a)4!K)*#K-'%K-*#3F(&!F6"`B3!JB -#"a)4#4)3!J-5#!B(!JB$%T!$!`B6"JF'"K-#"a%'%T!$"`-5"`-4"`F4!`S6%J- -#%3J6#K%$"J)$"J)$"`d6#4)#"a-$!`B4!K%(%3B$%4)(%a%("JF'"`J(%K)(N!- -'"`-'%3)'"`N'"`F6"JF4%`J("a%#N!-'%`B'%K-5"`F*$480%`S6"`d("J-4%4- -6#!)'"`F*&!N5"J-'"K)(!K%#"JF5%JF$"K)6"`-4"`F5%3)'!`B*%`F$"a-6#3B -5"`-5!`F5"a30&4-(N!-+%J)4"a)$"J)#"`B(!J-$%!-("K)("J-4%3-'%J)("T! -$!J)'%4%(!`-5#K-*"`)(%J)4!K!#!K%$!J-#%JB*!`)$"J-#"`-'"K!#!K!$"3- -5%4-(%3-(%JH3!`)$%K)("`B'!JF(#3N@"a%#!J%5!J-'%J+3!`-'"a'3!`-'!`) -4!K%5%`B(%JF5N!-("K)(%JF5!J-'%3)4"K)5%`F5!`B'#"-0#4)+%a%'!`B(!`) -4%3)3%a)6#JB5!`F'"`B5"JJ5"`N6N!-'"`F5"a)(#4-*"a)(%3)$!`)$!J-$!K% -#!JF6"a)("J)$!JB$%3-#"JF$%`F'"a)(%JF5"JS'!a%("K-)"`F$!K%#"K)$%JF -#!`)$%3)'%j!$!JB#!K!#!a-4!a%#%3)4!J-#%3F'%JF'"`B'#")(%J+3!a-#%3F -(%j!$%3B4!a)$%JF#%3B#%3)4%3B6#K-'!K)5%`B#!`B$"`F'!K%#!`B5"`N'"JF -5&3d8"a-5!`)3%K)(!`B'%JF(!T!%!`B(%`B5!`)$%JF5%3F(%`F(#3N(!`)5%K- -5%J)5%JB$"J)("J-#"a-("JN$%JF5"`B8#")'!J)(!a)5%!)5"JF5!`+3!`B'%J- -#!`F6%`)3!J)$!K%5"`N+#3B'"`F$"J)5"JF4!a)$!JB#!`F'!a%(%JF6"`N*%JB -$!K)("JB6!K)'!`B(N!-5%a-5!`)3!J-5!4!#!K%5!`-'#JB5"a%(%JF'%3B#%4- -("K)'"3-'N!-5!J-#!`B("a)$%K-("JF'!K)6%K-5%JF'"`B4!`F5%3B(%K38"a% -5"`B$!J-4!`-'!JF'"`B$!J-("JF'!T!%%!)3"`-'%3)(%`F5!`B#%a-("a-)"`B -#!a%$%K)'"`B$%JF(!`S6%J-#%3)$#3F'!`)$!`B(%4)4!J-2!K%$"J-#!`)3!`) -$%JB$"J)'%JJ("JF'%3-4"a-(%JF(%J)'"a+3!a-'!JB#!JB$"`8'%3F5%K-(!`B -("J)#"K)(%`F5"K)5"`B#"JJ6%`B'"a%#!a)6""%4"T!$%JF5"a%)#4-(%a-(!a) -#%3-6#3N6"`B(%3F("JB("J-5#3F)#3F'%JF+#4-(#3S6"`-("`B6%JN+"J8$"j! -%%a-5!`B("a-9#3F'!T!$%4-(%a)(%JJ'"K%$%4))"K-("K-5"`B(!`B'"`-6#3N -'!JB'!a))"a-'!a+3!a36%JF#!`F5%`N(%J)'!`B'%JS6"a)#!J-#!JB(%JF6%3F -(!`F$!K%$%3F(%JF5%`J(!a%$%3F("JB(!a%(!a%$%3N6%K-'"`B'!J-$%3)'"a3 -6"a)$%3)'"K-+%`F5"`-'!a%3!JB#"JB5%JF5"a)5%4%#!K%5"a%$!3+3!`F(%`F -$!J)$%JF$"JF5"`-'!`B#!a!("JF5#JN8%`F5%a)'"a%#!K)(%JH3!`B'!J-'!J- -#"K-(%J)(%3)5N!-'%J)3!J)'%JF'"JF*"a)&"a%5"a%6"`-'N!-)#3F'"`B#"J- -#%JN8%a-(%JB$!J-3!T!$!a%$"J-5%`F5#K)(%J-#"J)5"`B#!K)6"JB#%J-(#3F -5"`)5!`F'"`)3!a)$"`B#%JJ6"`)$!`B'!`B'!`F'%3F("JF(%JB#!j!$%J-'%J- -5%J-#%4-(!`)#%!-'%`)'"a)5"K%'!`)3!K%4%JF'"a)4!`)'"JF$!J)4"a-'N!- -5%JF'"J+3!a%&"J)#"3-4"`B#"JF(%K%'!JB("JF5"K)$"JH3!a)5&"3,"a%$!3) -$"a%4!T!$%3B'"a)("`J("JF5!`B#!`B'!J-'%K-(%a)'"a-5%J-#%3-9%JF$"JN -(!JF'%`N,%a)("JF6"`B("K%#!`)$%!-'"a-5%`D3!`-'%4%$!a)6"a)6"`F6"a- -("a)(&!F'!JB6"`B$!JB$!K)'"J-4!J)'"`B5!J-'%JF("K%'%`F*"a)(&3J4!J- -("J)$"4%(!J-6"`B5!`F5%J-'"J)4!JN)"`)4!K)("J-#!J-(%4%(%J-'!J%4"a) -6%JF(%JF6#4-'#!F#!K%("J)$!JB(!`B(!`-("JB5!T!$%3-3!K)(%4-)%a)5!J% -#!a)(%3F6N!-(!`)(%a)(!J-5%`S*#JB("`B3%!)4!`F'%4%("K)(%K-5%J-(!K% -4!J-#"K-(!a-#"`-("`B#%4%'!`B'"a%$!K!#"K%$"T!$!`)3!a!(#!B'!J-)%K) -'!`F'"`J(%a-(%`F4!`%$"JF5%`F#%"%#!`)"%3)#%`J("a)(#a-$!J)3!K)(%JF -'"a%("J)4%J)'"`D3!`F5!JB'#"-'%K-(%JB#%4%("a)'"a)#"J)#%"!$"J)3!`B -##3N+%`F#%")6%JJ5"`N(%JB(%JF9#K-6#!B("a)("K)6"`N'"`S6%JF'!JF(%K- -(#!B#"J)$%JF6%3F5&K8("JB5N!-$"JF4!`F9#!N'!`)$"JJ8%JS6"`B$!J-$"a% -$%3B$"a)6%JF$!a-5%JF'%J)$%JB$%K)@&3X6%`F4"K3+%`-#!JF'"JF5"`B("J) -4%4-6!`B'!`-#%4%'"J)$%`F(%JB'!J)$%3F'!`F$"J)$%J)(#3S+#3)(%3F5!`) -'N!-4"JB"!J)'%a))!`)$"a8+%JF6"`B#%3F5"a)'%JB5"JF("K)5"a)'!`)4!J- -6$"-*%T!$%`B6"J-4N!-+%J3#N!-$%K-("`B("3)3%4-("K)5"`D3!`F5"a)("a- -("a-("J-#"K!#N!-5"K-0#")("a-)%JF#%3-8"`F5"a%5%`B'%JF5#3N(%J-3"`F -5"`B$!K!#!K%$%JB(%3-#%a))%JF'"a)(%JB'!a%6"JF'"J-(%3B$!`)'!J)3"`- -'!`)##!F4!`-#%3-#!JB'#")'!T!$!a!#N!-$%JB6#4)(%a)(&!F5!a%$"a-(#!F -$!J)5%JB%!K)(%J)3!J-#N!-3%J-3!a%#%!-#%!-4%`B#!K!'%J)#%!-4"`-(%JF -$"K%$"J-#!J-#"K)4!`8$!K%'"`F5%")5"`B$"a-5%K!5"`-#N!-5%`S5!`8(&3S -("J-'"a)$%K%("K%4"`)$"J-#!J-#%"!#"JN("`N5!K%(%K)#!`B(!`B#"K-6!`F -("T!%%JF6%K)#"JJ0#3B$"a-)%J8$"K)*#JF)"K)'"a%#"K!#%3F*$3F5#3B#"K- -(#3F*%`F'%3)$%JF#"a-5%JF#"a)9&3F#!3F6%JF$%4!#!J-#"J)("a-'%JF)%`) -#%JF(%K)(%J)$"J)#"JF5"a)'"`)$!JB$%a-(%K-#!a%(&4-,%`F'"JS6"J)#%!F -'%K)#!K))&43'"`D3!`)$%K-5"JB)!`)4!J)3"JB5!`B$"J)4%3-4"3-#%3B$%K% -("JJ6%JB'!`F5"a-6%J-#!a%("JN(&!N6"a)("J)'%3F5!`)4!K!(!`B4!`F$"`F -*%JF'"a%5"a-6#!B(!J)(%`N(%3)#!`8$!a!#N!34"a%$"K)("J)"%!)#!`-#"a) -$!J-#!`B3!K%#"a)(%K)#"`B(%`F6%JF'!JF5%JJ*N!-'"J)(%3)'%4%$%!-4%JJ -5!T!$%3)$!`B#%3+3!a3*%`F3%3F4!a-(%K-5"a)$"J-#!`)5!JF'!a-8"JF5%J- -#!J-'"J-("JF(%K-("JF'!K)5%`N5"a)4"a+3!a3(!J%#"a%'"a-6%JS5"a)4"a) -'"J-#!`B'!K-)%3B("`B("K%$!J-'"a)(%`F'"JJ6"J-'"`N)%a%$!K)(#3N+"J) -#%3)2!a%4!a)("K)("a%'!JF'%`B$!JB("J)$%!)#"J-(%`S6%JB$%JB$"JF6"`F -6"a)(!`)#"JJ5%JF'%J)'%`B5&3S(#T!$%J)$%K)*"a)(%4)#"`B(!`%"!J)6%JB -'"a)5"J)("JF'"a-(%J)$"K)+&K-'"J)5"`J(%J-5%J)$#K38&3N5%`-6#4-)"a% -("K-#"JB(%`F#%a-9&!F(%JF5!JB(%`N(%JB$"J-5%`F6%`)$%3F5%JF'%`F$!a% -(%a)$"`B$%J-'%3F#!J%#%!)#!`F'%`-#%Jd,#4-6#3S6"J-#!a%$%3-4"a-5%`F -6#"%#N!-$#4)6"`)3%3)$"K)(%JB#N!-4"`F$%!)!%J)$%3)$"a%#%!X6%JB(!a) -3!J)3!JB'!T!$"JF$!J-'"JF$"T!$%`F(%a)6%`F*#4-+"a%5!K)'!JB$%4)5$3S -6&"%5!a%$%K81%3B#!J-#!J%"!J-5"`B5#3F'!K%'!`F4!J)$%JS*&!-(%3-5"a) -6"a!#!K!#!`N("JF'!`)"!J%#%3F5"a-(%!-("J-"N!-#%JJ8%JB(#4-*"JF5!`F -5!`B'%JF5!`)'!a%(%`)'!K!#%3-5%K-("JB$!J)4!J-4"`-'!a-("J)#!3+3!`B -(%`N6"`F5#!F(!a%5"a3*"K%4!a%5!K%$!J)6"`)$!K!#%JF0&`J6"J)("JB*!`B -#"JN+$489%`-5%JF4%3-5&!S6%a)6"a)4!`B("a-6"`)("a)+%a)(%4%'"K!3%4) -5#"-6#K%(#3F)%J)'!JB+&!d0#3B'"`F4#3F6%JF6%`F$!J)$!`B'"`N(%K%$!K! -#!`B(%JF5!K)("`)#!`#3"aF!!2rrc*!%!!(-N!B!!Xb3"*QC!!2-c*Q3"!!%c-b -CQ@CQ!!@CQFc-QCN!"TQ3"J!(QC!%CQB!#*QCCT!%!!PQN!B!#QD3"$-c!!YQCM1 -3"!!--c0QCM-c!!dcN!B!$J!!)L)!N!-2hC!'!"#lN!B!%DU3"J!5L*!'!"0hN!B -!&&@3"J!94*!'!"BLN!B!&a'3"J!!#)B!!3#3!a`!N!01!*!%rrm!N"#!)!#3"8! -!3!#3#8J!N!0)!*!&"!!"!!3!N!B)6J#3"%4!0%3c-%0$4$-c3c4%!$-`-%4%-c3 -d-d%d4%3d-$13!d0$-$-d&%4%-j!$4$-$4!"%&$3c3d%4%c-d-$-c3c4%-c-$-d4 -%3d-!-!4%-$-c0$&%-d4"%84%-c3cN!4"3c0$3c0$-c3d-c0$0#-cN!0"0$4%384 -$-d4$-c-d4"4%-6"!4$!`3d-`-c!`-c0!-a4%3d4%0$4%3d-$0%4%3c-c!c383d- -c-`!c0$4%3d3d0$13!d-c!d3`!c4$4$-d-d4$4"-c-$-`!$3d383c-d4%0$3c-`- -d3c-%4$!80%-c3c0$!c-d0$-$3d53!c"$4%4$3c0$-d3c-d0%0$4$-`-c3d-d-$0 -$3$53!a-c!d0%4$4$!c!d0$13"8%$!c13"%0%-d4$384"-c0$0$3c4%3$0%3cN!3 -d4%-`4$"%-c0%-d4%-$4%4$4"-a0%4$3cN!0%-c!c-a3c3c-a-d4$3d3c"$-c&%3 -dN!-c0%-84$-c3d-$0%3c4*!$-a3c4$4$-c0$-c-80"4$0$4%4$0%0$0%-!3c3d- -44%0%4$4%0%4%3c3c0%3c3$0%3d4$4"4%3d-$4$0%3a4%0%4%3d0"-c-`4$-c3c3 -$"%3c3d0"4%4$!$0$0%3c3d-d3d&%-c3d4$-`!c0%3d0%3c4$3d4$3`3c-a3c4%4 -"%838&%-c&$3d!$-c"$0$3d4$4$3c4%-`4$0%4$4"-49"0%4"0%3c4$13"%-c0$4 -"3a-$-d-d0%!`-d-c4%380$-84%3c3`-d!c3c3%13!d4%-$-a0%&$-`4$3$4%4%0 -%0%4"-c0$4%3c-`-$4!0%0$-$343c3d0%0!-d4$-44%%d4$-c-%0%N!0$-%0$0%0 -$!c4$&$4$-c-d0$-d4*!%3d3d0%4"4%-c-d4%3838&%0%N!0$4$3c-d53""&%4%0 -%4%-c%84$-c"%3d4%&%3d-d363c4%0$4!0%4%%8-84*!$0$383c!c-"3d4%4"3d4 -%38&%0!4%4$380%343d&$4%3`0%4$-j!$3d-84"%c4$0%4$3c3d-d4%0"384$&"4 -%N!-8363c0%4%3d4$4$0$3d34-c3d-d3d3a384*!$0$4%-a4"-`"%4%0%-d4$3d3 -d%83c4%0%36-c4%0%0%-d4%3c&%0!-%3d-d-c0%-d4"4%3`-c0%36-d&%0%4%0%4 -$4$4$0$!c4$0$3`-$4$4%&"3cN!0%4$-d4%0%4$4$&%53!c3c!d53!c-d3d%d!d- -c-$-c0"3c3c4$0%4%0%4%3d3c4%3d-c3c3d9%4%13!d!!4$0"3d3$4$-c3c!d-d% -c4%-c!c0%0%-d4%0%0%-d!c0%-d-$3`0%4$3`0%0"&$0%3c-d0$0%3c4"3a4$-d- -%-d-c0$3c0%3c4$4%4%%63d3cN!-`-d-c&%&$0$4$0%4%3c0$-j!$3c-c4%38%63 -d4$-c0$-$4$4%4%0$4%0%4%-c0$0$-j!%4%0"&%0%4"&$-d3c3a-c&$-d3c-$3d- -c-d4%0%4$4$4%-43d4"&"363c0%4$3d%d4%-c-d53!c-c4%0%3d0%4%0"4*!$383 -83c0%0$0"4$-d0%-c0$0$-c4$4$3c"$0%-d3d4%36360%N!0$-d&"3d4$-d4%-c- -%0$0$3c"%0%4$4$4%N!Bc-c"%3c-c4$3d-%3$-d3c4%%c0%3dN!0$4%-d4$3c3`3 -c0$4%-c4$0%3d0!4$3d4%&$3c4%3c4*!$0$3c0$!c4$3c3c!d3`0%-c0%-c0$3d% -d0%0%0$36-d4$4*!%0$0$N!-c4%!$0$3%4$0%-c0%%8-`&%0"-%%d-d4%&%3c4$! -d3`4$!d4%0$4$-c4%-83d0$-40%-c4$0$&%4%0%4$N!3c3c4$3c%c3c4$4*!$36- -d&%4$0"-c3d4%0%%$3`-c4%0"3c0"4$4%-c4$3c0$4$0"3d-c3c4%0"0%-6-!-d4 -%384$-d53!d0$-d-c-c3d3a0$3c3d4%0%0%0%0$4$0$-c0$-d&$3d-`0$-c!`0$3 -c4$3d-$0$-c0$4%3d4!0%3c3d-%3c4%-c4!-c-c53!c-dN!-$0$-d4*!$3d!c3c3 -d3c3d4%&%0%-c4$3c4$4$&%0%-`0%4%0%N!3c-c!a4$0%4"4%4$3`0%-c&%!8360 -$-c!d&%&%&$3cN!4%3c-d3d3dN!0$0"-d0%0%3d53"!4$4$4%N!0$4$-d-d4$-85 -3!c4%3d3d3d4%-d4"-83d0%-8384$0$3`0%13!c0"4$0%-d4%0$-c0%4%0"0$3c- -d3c3c-d4$-c3c0$!c-d3d4%%d4$-d3c3d3c!8-c3`-c%!4$13!c3c3$-d-c3c4%4 -$&%4%-c4%N!-c-d-d3c0$3c36-c3d3c-d-d0%4%0%3d53"N0%3c-c3d4%0!-d-j! -$0%4%0%-c3c!c-d%d0!4$"$-d4$13"%3c3j!$&%3d4%4$-c"%-`!d0!4%4$0%-d0 -$4%-cN!-a3d4%3d4%-%4$N!-c-d%c!%4%0%3d4"4%4%-d3c-d0%3$4%-c4$-%4*! -$3d3d3`!c-d-d4$4"3d3d-%-d-c3d4$4%-c0%3c4%4%0$4%0%3$4%N!0$4%3c&%- -d3d0%3a4$4*!%3c0%4%"!-d3d4$"%4%0%N!0$0%4%-c0%0%38-d4$384$3a%8-$- -c4%%8!%3d-d4$4%4$4$3c%a4%-d3c36&%0!-84$-c4$&%N!-!N!F&!!"QN!B!!61 -3"J!#Gj!'!!09N!B!"%53"J!&)T!'!!!)IJ!"!*!$(!#3!di!N!6rr`#3%)!J!*! -&3!"!!*!*5!#3!dJ!N!8%!!%!"!#3"JK1!*!%%c!#-`#3""-$!`)J-!!b!$#3!c) -b-$!J)!#3!a!L)K!c!!"!!!!`!!!J!J!!-!!K%J#3!b)5)J#3"#!#!!%3!%!`!$! -%!!)`%#)J!$-!!J)J!`!")5%!)3-#!L)!!!)J!3!c!J!`)!!4)!)$-$!!)*!$!L) -4!3!5)J!L)J!J!")J%!!c!!)!!!)5)c!c-#!$)3!L)K%J)J!!!5)!)3!#)"%!%!! -`!J#3!b%"*!!!-J)"!J)!N!3J!J!b!c!#%#-J)5!!-3)!!$!`)#!!!#%`%K%K)J# -3!a)L!!!J!#!#!L)4)L!!!J!#!`!4)J!`)$!L)3!!!L!L%3)J!#-#)#-J%4%")!! -3)J)J)"!3)!-#!L!")J-L!4!K!K!!!#3%!J!K)4%!)!%5)J!`%3!#3$-!!M%K)"! -!)J)5)!)!%J!J)#)K%!%J)T!$)!)4)!!`!b!3)J!`!L)")L!!!!)J)J!!)K)5!!) -$3J)J)!!5-!-b!L!L!!"#)3)3%6!!%K!#!`!!)J!`!5)!)5!#-J-!-#!#-#%#!L) -$)K)30!)#)#!c!b!L!#!L)!)!)5!J!$)#)!)5%L!L%J!"!M)K!!)J!!0!)K%J!!) -$!J%!)6)#!`!L)J%!!K)J!#%!!L%!)!!"-a!#%L-J)J!!!`!"!`-#N!-!)J)K!3! -!!L)5%#)5)3%5!L!L!3!`!!)L)J#3!`)J)!!b)J!L)3)!-L#3!b)#%3-3!J"!!!! -#)"!!3!3#!!!3!#)5!J%J!5%L!#!#%J)L)!)!N!-")J!#N!-5!!)L!"%#!L)J!J) -L)K)J%#)5)5!K%J%J%K%3-`!!!K)$!L)#!5!#%!)4!J!#%K)J)!!!!L)5)M-5)L- -c)!!3!$-`!#)!)!)L!L%3)J!L!L!K%!%L)3!#!!)"!J)J!5!J!!)$%3)%%K-!%3! -#!!!#)J!3!*!$-#!!%3!4)L)J!J!!)4!`!L!!)L!4)!#3!a!"!#!J)M-#!#)5)4) -L)#)J-!%K!#!$)`!!)#)#!!-J!L!J)J)$!#!J!!)`)L)6)!)!!L)$)!)3)#)d!J! -#!b%K!J!J!J%!!J)J!J)L)L-d)`!K!5-6)!)L!L!!!!)L!6)4)!!M!!!J!"!#!K! -#%b!J)L!K)L)M)b)J!L!!%5!#N!-3-!%`!!-!%!!!%3%$!3!!-J)5)J)4)5!!!3! -3%%)K%L!!N!B#!#%#!!!%)3)!%L)K!5)J)!!K!J)!!"!!!!)!!J!!!j!$!L!K-#) -5)L)4%L)J)!)M)4%5)b!!)J)#-!!!!b-N)!-J-J)!-5!J%"%J)J%4!K!#%L%b-#! -!)3!M"#)!!!)!!#%$)!!"!$)L)5)!)5!3%#%L!M)#!J#3!b!J!$-#!#)b!5-M3#! -L!K)4)T!%%4!!)!-!)$!!!`)!!L"$)$)b!`)`)`)#)L%5!K!L)K%M)!)!)!)!!J- -b-5!5!!&!)*!$!$#3!b!M)L!4)K)#)K)!)#)c-3)J-`!c)J!3)$)!-J!#)`-`%b! -!)5%c)L!L%#!#)J!$-!#3!c!a!L!J%K)c!!!b!`-5!!)K!M-!%"!J3J!!)$3!N!- -#!!)L%3)L)$!$!!!$!`!b%!)!N!-L)J-#!J!#)J)#!!-!!L!!!5)J!`-`-$)`%J! -L)J!c-#)J-d!!-!!!%5!!-`)!!J)K%5)J!`%J!`!L!!)`"$"!)M!!!!)#!")K)J- -J-`!#-J%5)L!!)$-!)#!!N!N#)!!L!"%33L%#)J)!)K)`!J!4!!!5!J!J!`!!)!! -!-J)J)!%!!K!#)J&!)5!L)M!#)#)!!a!#!#!#-$)J)$0!)!)b)#!#)!!5!J!L%L% -3!#)`)#!#)#)J)b!#!L)$"!)b)L!L!*!$-#)#)!)#!!)!)4-J-c!#!!!`!L!`!$! -d-!)$)#-J-!)!)3-!!!)`)J%3)#-$"$-!-!)!N!3#!d0!)")J"$!c!*!$!L!J!#) -J!J!b!$"$3!0#)$3!!!3d3`-!%L!%!`3J!$-!!J"!!#!J!`!J)#)c!!!d!b-#!%! -c)c)$!3!!%`!J!#)L!*!$-!-`-#!L!b!!)!-!-!-!!`!#-!)")#%!)#)J)#)#!!! -b-"!!%#!J!J-!-!!M!!)!3%!#!")J%!-!!!)4)33#!b%#-M)M-#-$!$!c-`!`)*! -$-!-#)!)#!#!!)5!J!`)$!5!#-`)`3c!!!#-$!!!L!!!3)!!L)6)J!`%#)#-!!K3 -!!!-d-$-!-$!!!#33)J!a!#!#!`!!!`-!!3*!!!)L!$!$!`!J!#!M-%!!N!-L!#) -#)!)$!`!`!M-#)!#3!a%c"$!%!b!!"!!`-#!!)$!M!J!5)`!!-$!L)!!"!!3J!#- -`)!-`!J!!)J"!-L)!N!-$)#!L!L!"-#*!-!0$!!)J-!)!-`!!!J!M-!!#!`#3"#) -`)3!L)$!%!$!#%`!J!$!")!!b!J!J)!!b)#)#)L!#%J!J!!!$-$!$!$!#!#!!!!% -J)c!!N!-#)#-5*!)%%#)K!3!J!c3$)#-!3`-!!#!#)!)`0$!L!J-!!J!L)!!$!K) -#)L)`)`!J-!!!-c!J-#!#)%0!4$!!N!-M)*!$!!!M-J-b)J!$!!!#)J!`!j!$)$) -c)`3!!b!!)%!L-M!L!J#3""!J!!*!)"%"!!!d-J-#!!-!!$!!)#)!N!-c-!)#!$) -#!`!J!$)#)b)!)!3!-#!!-c-$-$-J!J%!-*!$!`-!3J-`)J#3!a!3)!!J!`#3"`3 -!!*Q3"J!"Zj!'!!+UN!B!!iL3"J!%Gj!'!!!)PJ!"!*!$(!#3!di!N!6rr`#3%)! -J!*!&3!"!!*!*5!#3!dJ!N!8%!!%!"!#3"JK1!*!%35)R)RBR&L%aFR)L*aG"&8F -@%4)LF84(%4%5*b4%&4%Q%L*eBRB8%LBK*fBQ%Q&b)@%4CfGfGK*fCAFR&P%4&@F -Q*b4#*Q8QBKChGfB5*N8L%KBLCb)5CfBACK*K)5&K*fBP9d*fCL4@*")A&a)N38& -b&L)RFRFR)RGdB5&Q&b*Q%A)4GR)RB8BP&eF5G(Bf!L%5Gb*L%@GK*bB4%KFR%5F -K%LCh)KCQC"%Q)4CK3LCR)R%Q*h*L)4&K)K*'Gb%4*K&K)@)Q&QB9&a*fCb35%d- -4%R)RB5GK%@&a0N4b)L%L)K)N3@&KBK%Q4K)ACL48&8CeFR*RFK349RB54"*LGf) -bGRB8CaBK&b)b*R*LC@08-(C5GbBA*K)9BQ%d&h)5&eC"%5)d)4%KCK*LBA)93"9 -6GQ*L&aFL%A3LGP3R)LC5%L%8%8F5BR*f*b*L*Q)RFL&Q&"*K*b94BL*hN!0Q)K) -A*L*48L*LBLBQ)L*#&(Ca34&N&a*L&K9$*b*h&hFL%4*bFKFPGb*LB4)QB5GRGK4 -K%RCh)K*K%8%LGbFL*R*RFKFL)5BL*Q*LF4%84RBR%5Ca4hFK&a&PCb*QCRF5FQC -KF@B@GLFQ)QF@34-@BL%9)A&"&hCLB4%KFR)8*f89CL)L3NF4GfCQB484%4)Q*Q9 -K*%%5)L)K*'Gb)Q%R&")Q9(*A)4%4*QCR%4&#FPGKCK*a%83A&a0N4b)N)K4%-5& -K%N)K8K&LBQGa34&"&5&KCbC'*NGhB54"*P3P99&#)Q*L)5GKB8*LCh)R)dC"FR) -RGa%43RBQ%d&h&eB@99*a%53MGh%4&bFLF5)LC8%L&hGb%4%@)LGP3R*e&PC8Ch0 -"BQ84Ca&h*a&b%L)Q3A0%4hF@&K4L*hH3!aGa3988)9-5GeBQ%L*&348KFRC#4&3 -@)K&4%b*b*h%R)LG84f*K4P%QB@)N%@&"GL%4%RBN4"*fF4&#)LGbFL)R)QBLF4G -b)5)L*R3A)QCL%4&a)Q*K%K%K&N*L)Q)LCQGL*L%L%C!$*R*b)5BR)5F@&K4b)A) -44hB8FR&44'BAFRBLGh)4%@35*L*K&LFLFL%5%R)L*"*A*bGR&&-@&d4LFLG"BKB -K%4FQ9aF83")QCL*h*bFL&Q)Q%KCA&44'&K*LF@3A)5%@&a8K)5)@3KB8)@%LF8* -L*Q%@&h&&-@%Q*aCfCb)L)4*#*MGK%4*LCQ95GRC"35*LB5)L%L%aFLBA)A&b&@G -h)4*5)4F44"GKCPFL*f&hFQB4&R&Q%LBK*hF5GLBK&b&R)LB5*534FACKF@GfFK) -LF9BN)4%QBKBL&h*fCK8LBRFKCK)K3@Gd*f*9*fCKGb)KBL%K%54@*#CK&bGb*@) -RFKCRBL*b)K34)P)QB9FR)Q%A*hGa&8)R)Q)8*LFL)4GKGb)RC5*K*Q*K)Q)5%M4 -LF5Gd3R9N*h)QN!4KB5%5*hCf)6F89f*4)@*hF5%M84FLGb-QFR*e99%LB5CRB4* -f%NGN8K9#Gf&h*RF5%@BN*Q)L4"C')K&84")MBQ%5!5)@)L)R%@)K%R%ABQFRCA9 -(*8-4FK4b&9*8B5%L*#CdF535)4%R*h&")R&K*h&a)LFP-4Ca9#GQ9$33FLFR%f) -5%L%@%4)RCd%5)AGa8KB9BL4%-435BK45&`%9BR*M4NGh)4%8%K)@44BA)L)5%4& -R&&38FK%A)QCQF94#*9944a%L&K%4CR34CaC@*R%4BLF5GK*LF@%A)R*f9R8!84F -4)8)Q%5CbCR)Q)4G&4bGK%LBL3R)4&&)LGQGb%e4aFAF4"'BRBA%L%5BK&e&KCa% -@CK%@)4%84b*PGbG%4#*Q*#*%4'F4)5CaCQBLF4*"FA35)4%KBA8@&RFQ&P8%Gf& -R&R3"FLGb&hFK%K864#*Q)Q%R%5*K%5%4GLB598B4)Q)4*f)R*LBLBLB54P0%GL* -aF4-LFKB4N!-KB4%M4"%5BR%54#GaB4G@GQ)L88!5GbC"Ch&QFL)4G#9"44%Q&h* -bB4)8Cb&K&f4hCL)L85)KF8)Q%RBKCh)8)K35FL)LFLBLF50L*QB4FQ)L4#*a&b* -aCRCR%4BAF4!AFL*L%5&%4#85FRGf%@*RChBN%8)ACf*b*KCbBL*aC%GbGLB4)83 -d%d&4*L*LFM%Q8K&#G(FQ*Q)R)A&LCLC4!QGbGR)L384N4K*%*N&"&a%N&%*N3Q% -QBQ)QC(FR)435)d)Q&Q*d%A%5ChG"FL4bFQ)4Cf)@*L*4*%B93Q%Q&%)P"hCQCLF -LC6)R)44"%6*b%N%hB@Ga!K3K%9%A&(BQCR*L"N)P84)N&KB4&%3N45FL-8CQCL9 -")5*P%@%LCK)R45%8&#C8%KGQGK8434*"*')4BKCQ%NBL3A&8)LCQ&dF53Q*@3K- -bGK*4GK9(-4BAB5GfCT!$*QCLC%*K*QCA%L4(*QC%)R)@F63b*LBa%4)@B5CQCe% -QBQBK)K&RBP*L*KGb)K-P"aF4*4)5*b&%GQD3!f)KB4)QGf*b%5*LF5&K*RCR3"% -Q%90P38GRBN*QCP*Q&fBL4LGa)L*hGf)KCb)5CK%@Gf*R&L&#%83L*bCK*#)5B"* -&B4&R)L)R*e&#Cb*(3K*#GK%L%a)P%aF43L%8%K3K*4853QGa*hFQC4&N)Q&L&R* -KF4BL*fBd&L8$8Q*c%!&f%a%L)N)P3LCL)5C'F83%4#F8*Q%KF488C4&"*f493(* -f)8%5G4*$%4&fCKC`4!#3"`F!!2q3"J!"QC!'!!*QN!B!!pf3"J!%Zj!'!!@UN!B -!"RH3"J!(4*!'!!!4$J!"!*!$(!#3!di!N!6rr`#3%)"!!*!&3!"!!*!*5!#3!dJ -!N!8)!!%!#!#3"K"1!*!%#439&!Q3"43-#438%38&%4%&N!36&Im1r`lr$JN&%C! -'"4)*$!i,$!@3!a)'%`N8#a85"4-*N!F8#C!'&"@3!`8'%C!&"C!$%K)6"`N8ra8 -(""'3"!84"4)*&Im-$4%&N!-5%`N9&3i*%K)*N!B8#C!(&!`1r`88%C!'"385%a) -6#485"385%a'3"!8&%a39r`i9%K%&"4)6&"6r&3N&%K-*N!89#3N8#C!%&!crra) -,%C!'"385%a-8&!@3"")*"4%4"385#431$K81&"%4"3B*#3`2&"+3"!Q3"")8#C! -(&"Arr`B8"4%&N!85%K-*#K%&N!8'#4%&N!-6&"81#a8-%`88"4)*&3i9%T!$"JN -6%`8&%K3*N!F9&Im,#43*%385"4)5%`N8&384N!3&"4)*%J85#439$K8-$48("!N -$"3S1&!@3!`B6&383%386&!N*%a-*N!-9$!`8$!N&N!35%JN*&!`&%3-4%3@3""- -8&"81&488&"8-&!B!%K!&&!i&N!85&"3%"388&")6#3J*#439$Im9#4%&%JB6%a3 -9#3F5%C!("3B6&3crN!-&"4)'#43%""%$"438"3B&N!35&436#4Ar%JB*N!-8#C! -$&3i&N!-5"K-(%`N9#`N4%"!4N!-&N!-5&3i-rrm&"4)6#3N8"J-3"3N8%4-&N!3 -'#Im,#4Ar&!F*N!-(%J8&"K35%385%JB5%JN8&Im8%3-4N!3&"3N9N!-1r`8&%K) -(#3N'!a!X&%J@3"3N-"4%*rj!$&3N5"K'3!`86#4%&%38&%K)6#46r$K33%"' -3!`8@3"2m&N!-'%K)*&"!$"431"C!$%3@3!`F8"4%*$[m-#3N&"4'3!`8'#4' -3!`@3!a)5#439r``&%C!%"38*$"@3!`i5"385N!-6&!83"48,"4%&N!85#384#Im -9%`B&"4%3%"%&"3S&%C!%"C!$%JN8r`i0%4!4"386$!i8%aAr#38'"3B5%JN*%3B -9&!83"C!&%K3&%3N8"33&&2m&%"%3%388#4'3"!8&%JN*&"Ar&3N4%385&3i*"K) -9ra35%J85"K)(&"%5#a8&%3@3!`B5#435"4-&%C!$%`i-"3-3"388ra)4N!-&N!- -(#439$[m1%`8&"`N5"38($!i9%`B&"4)'#3`&"`N5"K)&N!-5"JN8%J85#384""% -8$"33%4%5&2m9"C!&%K-8&3m9$[m*"385N!88$[m1&4)&"3B5#Im*"C!$%K-,#38 -%"`N8"C!%%a)4%3B,$4)4"3B0r``8"C!%%JN8&C!$$!N4"C!%%T!%&2q3!a8&%38 -5$434"C!%"JN9!33-#4%&N!35#4%4"3N9$K-ǡ&38&#"3)%a-9&3N*&"%&%38 -&%K)'%K)*&Im-#4%4"385&"3&N!35#3X"""34%3@3"")*"4%4#3i-&4-8$JX&N!- -'#K8&%C!$"3B5%"%&"4)'%T!%%a6r$K34N!-&"3B9&!@3!a)6&")*"4%&N!B*"4% -&&!`9&3d9ra)4"385#3N4N!3&%`83%3@3!a+3!`B6%a39&434%4!&N!-*$4)'%K) -6&!S&%384"C!%%K-6%388$[m9r``9%4%&"4)*#4%%%4%%3%4%&%T!&"K)8$`i -*%C!$"385%K39%K)6#438%"%&N!B5%`N4"KArN!-1$")4%!8&%JF*%C!$"3B8%C! -$"385N!3'%JN*&3i6%4%$%4%&%JN1&!B6#485%4%&N!85%JN*"46r$Jcrr`N3%4% -&N!-*#K)4%3B+#a'3!`8&"K+3""-*&!i-"4'3"!8&%JN0&3J5#434N!-&N!85%JQ -3!`lrN!--#4'3"!@3!`N8"`85#3`-"4%4"385N!-6%JN*&2m9%3-4""'3!`86&C! -$%K36%"%&N!85"3B8#439$[rr%a!$""'3"!8*&485#48-#4'3!`8&%T!$%a)6#48 --#4!4%384%38&%K39&43+%!34"C!&%K)(&!84%Jcr&!85%K'3"!8+-#4)$#3N -&%4%&"4)5%a)6#4Ar&")3%"'3!`@3!`B8r`i-#4!$"C!(%K3*"386&2q3!a3*&!8 -4%38ǩ%`8$"3S5%4%&"4)5%a-*#Im1&4'3"`8&%K6r$K8*%"%&N!B5%`N4%38 -6&3X8%J@3!`B8&!N5#489%J-%"4)*%J8&%T!$%`N*&3i-&!-4N!B&"4)9&4-'#3N -4%3@3"4)*"4%4%a6r#3@3"4)5&"@3"!8#"4'3!`8'#488#4-6#481$[m8""!3%C! -%"386&435N!-*#4%&N!3'#4-4%4-9&"%4"C!&%JB(&"@3!`3$%4!3%4%&"K-8$"8 -8&Im9#C!%%C!&"385#3i5"4)5%a8)"38'%JN6%38*ra)3%3@3"a)5#"6r&433%!- -3N!-4"38*&"81rrm9#3J(#3N4N!8&%K3*"C!$%K)*&4)&"4-*"JN9ra3#%"%&N!- -5"C!%%K)*&480%K%3N!84"38*&Iq3!``8#3N6#434N!-&"K3*"C!%%K)*ra85#43 -5%`N*$!N#!a%&N!-5"4)&%T!$%a39&3N4%3-3%4!4%38&&"Ar$J`9&43(%a6r&"- -*&"-4%3@3"")6#`i8%a)&"4)5&"3#%"%&N!J'%K)*&3lr"4'3"`85#46r$J`9N!- -6%`N1rrm6%`N4%3@3"4-9&4)5"C!%%K-8!K!3"C!'%T!@3!a3&%38&%C!$"3B -*&3i-&C!$$JB6#Im8"385&!N4"384"385&"35"4%&"4)&%JN4%"%4"C!&%J85N!- -6&3`8#4)'%J8&%38&%K39r`i-&48*%a-8#38&%K)6&"34"4%&"4)9%`84"385N!3 -6#4!$%4%&N!B5%JB*$43&N!35%K-&"4)*&2rr$J`8#")6%`N&"4+3!`J*&4-4"4% -&%K35%4%&"4+3"!B8%K!4%3@3"4)5"K)*&4)4N!3%"38*&!N8$!lr&")'%a)6%K% -&N!-5N!-6#484%38N&%4%&"4)5"JB5#484%"%&%3@3""+3!`N9%K!4%"%$%!8 -&#Irr$J`1&!85N!-*"4%&N!-5"K)6#436"38'&!8&%4%&"4+3!`B6#488!a%4"C! -&%K)*&!i&%C!%%"!4%JIr$!i9&3i*%K)6#4%4"C!$%T!$"JN8&3N5&384"384"38 -5"K)6%JN9$")4N!3&%J85"a6rr`84%334%"!&"3F9r`i9#481%a)(%a!4"C!$%T! -$"K-*$2m-$K%&N!-4"385N!-6%JN9$K85%3@3"")6&2m1ra)4!a%3%"%&"3N9&3i -*"JVrra38#4%&N!-5"4+3!a-8r`lr$!N&%3@3""+3!a-6#43-&3`9%J8&%a-*#43 -9$!N%%C!&"4)*&Im*"4)*&3lrra33%3@3""+3!a-*$[m1&48&N!B5"K)5#3N9$K8 -1rj!$&!@3!a)*&"31"4'3!`34"4)+ra8&"4)*$"89$"83%3@3"4)5%`Rr$K3)#43 -&N!85%JF)#439$K8-$J`*"384"3B*#439#4'3"!8'#489"4%&"JN9$K88r`84%38 -&%JB5%K-*&3i*%`N8%a%&%T!%%`N*&"@3!rm1%`84%38'%K-*#4Ar"J@3!`B*$"3 -4"!8&%JN1$!N6#`N4N!-&"4)5%a-8$K85%K-*&!85%K-5%`Q3!a89$K89%K'3"!8 -5N!-6#489&!B&"JN9&4)4%38&%K3-&")'&2m5%3@3!a)5%`N8&3N5N!-6#486%K1 -3!a)'"4)8&!i&N!-4"C!$"K)5%`N*"4%&%T!$"JN8$K)&"3Ir$385%JN9ra)4"38 -5%JN*&43&%T!%#43-%a-8#4%4"3B*$!d4%3@3"")'%JB6%K%4"3B&"4)'%`N8$4) -5&2m*"C!$%``1$JN&"3B6#"89"C!&"K)*&38&%K%&"JN8$2m8%"!4%38'%T!&%4% -&N!35N!-'"JN9&3Rrr`@3!a)5&!i9"`8&%a3-%K%4"4%&N!-'"a34"C!&%K)*&"3 -3%4%&"4)5%a-'"4!4"4%&N!-5N!-6%`RrN!35"C!$%K6r%K!4"4)*&"84N!-&N!3 -5#43&%3@3"4)'%a3'%4%&%K-*#4-'%4!4"C!'%JB5%JN9rrm1#3@3!a)*&!-3"C! -$%JN8&"%4"4%&"3B(&"-&N!F'%K-8#38&"JN8#3F6!a!3%3@3"K)'%JN9rj!$$!@ -3!`B8"4!3%38&"K-8&384"384"4)6&!i&"4%4"C!$%J85%K8*"3B8&!N6%`)$%"% -&N!-5"C!$%K)*&!i9%K-8&"-5#3-3%4%&"4)(#438%3@3"!B*$!`5"C!$%4%&N!3 -'#3`*#438#3S*!K!4%3@3"JB&"JN8$"3&"4-8&C!$%"!4"C!$%K-*&"8'"C!%%K3 -*&")&%C!'"385#3i-&488#`N5!K!4%3@3!a)&"K+3!`N8$K-&N!-6&481#3-4%38 -&"K)6&"Ar#385%a-5#3N6%C!("385#480$"89#4)&!J)$%3@3!a)&%T!$#3N,$J8 -4"38'#3lr$!84"C!$%K)*&"6r&4)5"K13!`Q3!a%&"4%4"C!$%JN9&3lr&3@3!`- -!%"%%"385"4)5%`J*&484%3@3!a-8ra88%38&"K)5%`N8r`N5%K-6#C!%&4)4N!- -&%38&%a3-&3`9%K%&"4%!!J-4%3@3!a+3!a-8&434N!-&"4)8r``9%`8&%JB5#!N -8&4+3!a13!`Q3!a38%C!%"385#4@3!`i5%4%&%38!!K%3%3@3!a)5%`N8$!N4N!3 -&"JN1&488"C!$%K)6#43-%J8'%`Q3"439%4%%%385#3X1#a36!K%&N!34!J-3!`8 -4"3B6#439&384%"%4"4)*r``9&4)&"4)5%`N8&4)&%K-*N!B9"4%4"JN8$!i9#43 -3%"%4"4%4%K)3!`-4N!-&%`N9$JN4%4!4%385#3`9N!-'"385%K-*#485"4)6#C! -&&"35%3B*#439&385"K3&N!34"385#4%$%3-4"3B8&3N4N!8&"4)6$!i9&4-&"4) -'%`N8&!8&%K)6#C!&&43&#C!%&!`*"3N1%a%&N!B5&43'"38(&3i1%a'3"J8` -9N!-'"C!$%JF*&"3+"4)5#C!&!*!(&J!!c-bCN!3!!Fc-QCPQCJ!#QC!'!!1CN!4 -QCJ!%QCPQN!3!"@D3"J!'CT!%-c-!"fCQ-j!%!!Jc-fCQ-c-!#613"J!+-j!%!*! -$#b)L!*!&$"%4!*!&$3!!)L)!N!-1!!!4%3#3!`m!N!34%3!3L*!'!"&hN!B!%P@ -3"J!64*!'!"3LN!B!&4'3"J$r!*!)!3#3!mkm!!$0[!!!#8)$@EbN'i`!N!-F"ii -!'&G*6N3!"`$+9%e36!!"!5T1G@e`!!%"3N&-8P3!!`&D4%P86!!+!BT69&)M!"% -#$QPMFc3!"!,QD@0c)`!%!b**3diM!!3$AQPME$3!"!1D4%a24`!'!pC'6dj8!!8 -%+NC26N3!!J4b3e958`!)"*CZD$-a!!!&!NC548B!"!813Nj%6!!!"8T048j9!"- -&9Ne195-!!3C'GQ9bF`!""Pj69&)J!!!'GQ4MG')!"JD#D@0dBJ!!"YCKBh4L!!- -'iR"`BA3!"`F5!)!!,3#3!hJ!N!@"!*!,JJ!)!*!$)!#3"B-!$`#3!pi!N!@%!"F -!N!0!!*!&K3!F!*!$@J#3"BB!)3!!!3)!N!@(!+S!!$dD!*!&J!!b!*!$RJ#3"B% -"-3!!83`!N!@!!$F!!#BS!*!&J3""!!!Q3J#3"B(rrb!!#1!!N!@!rrm!!&)N!*! -%%iJ"@3!!8MB!N!36L3&P!!"&M`#3"B(rrb!!#2!!N!@!rrm!!!b-!*!&J[rr!!! -1rJ#3"BMrr`!!$RB!N!@&rrm!!!dL!*!&K[rr!!!0H!#3"BIrr`!!$H!!N!@*rrm -!!!q!!*!%%iMrr`!!8D3!N!36LIrr!!"4h!#3""G`rrm!!&BJ!*!&J!#F)!!"*J# -3"B-!a3!!6Xm!N!@%!-N!!&&E!*!&K3$1!!"4HJ#3"BB"43!!9#X!N!@(!0-!!&- -#!*!&L!$A!!"6q3#3"BN!h3!!8NJ!N!A*!1)!!%pM!*!&bJ$[!!"2c!#3"FX!q`! -!6r)!N!A-!33!!&!B!*!&c3%+!!"31!#3"Fi"%!!!8&J!N!A2!4B!!&"i!*!&d!% -F!!"3Q!#3"FJ")J!!8,)!N!A4!5N!!&$i!*!%!qMrr`!!!8!!N!3$kIrr!!!"a!# -3"!2Urrm!!!r`!*!%!q[rrb!!2AJ!N!3$l2rr)!!pr!#3"!2Srrm!!!*)!*!%!qR -rr`!!!S`!N!3$k[rr!!!+4!#3"!2VrrmJ!$k!!*!%!qcrrb!!2X3!N!3$k2rr!!! -#d!#3"!2Trrm!!!28!*!%!qVrr`!!#8!!N!3$krrr)!!r#!#3"!2XrrmJ!%!-!*! -%!qMrr`!!"0J!N!3$kIrr!!!'h!#3"!2Urrm!!!U)!*!%!q[rrb!!34!!N!3$l2r -r)!"$&!#3"BJ!53!!$PS!N!@(!&B!!!c1!*!&KJ"5!!!-kJ#3"B8!6`!!$3B!N!@ -*!&X!!!pN!*!&JJ"T!!!-XJ#3""G`!8X!!&@D!*!%5iRrrb!!%(3$@E[%5icrr`! -!'J!$@E[!6!N!K#!!*U)$@EZm6!`!N5!!,fJ$@EZi6)Rrrb!!BR)$@EZd6)crr`! -!Dri$@EZ`!*F!F!3!*H)$@EZX!*J!H33!*P`$@EZS!*N"U!3!BL`$@EZN!J$rrb! -!2%)!N!3#!rrr)!!mLJ#3"!)%rrmJ!$c5!*!%!JArrb!!1T)!N!3#"rrr)!!kfJ# -3"!)"rrmJ!$XL!*!%!JErrb!!1fS!N!3##2rr)!!lXJ#3"!)#rrmJ!$[k!*!'rrm -J!$dq!*!&J2rr)!"&'!#3"B(rrb!!45-!N!@#rrmJ!%8Z!*!&Jrrr)!"&13#3"B6 -rrb!!483!N!@!rrmJ!%92!*!&JIrr!!"&S30CZS`!J[rr!!"'+J0CZT!!!)2rr`! -!4RB$@EU8!)6rr`!!4bB$@EUB!)$rr`!!4jd$@EUF!)Arr`!!4mX$@EUJ!)Err`! -!9(%$@EUN!)Irr`!!8eN$@EUS!)Mrr`!!5*8$@EUX!)Rrr`!!59)$@EU`!-Vrr`! -!5Jd$@EUd!-[rr`!!5T`$@EUi!-crr`!!5aJ$@EUm!-hrr`!!5hm$@EV!!-lrr`! -!5qB$@EV%!-rrr`!!6%d$@EV)!-Rrr`!!6,3$@EV-!0$rr`!!65)$@EV3!-Mrr`! -!6AF$@EV8!0(rr`!!6J`$@EVB!)!!Y43!6Qm$@EX)!)%![43!6Tm$@EYN!!(rrb! -!8U3!N!8#rrmJ!&,6!*!&J!%f!!"5M!#3""G`!9-!!&9Q!*!&JJ'"!!"AZJ#3"BN -"L!!!9qi!N!@)!CB!!&JL!*!&K`'F!!"B9J#3"BB"S3!!@)S!N!@&!D8!!&Lq!*! -%&h$rr`!!9FJ!N!36L!&Y!!"A8J#3""1*!AN!!&H'!*!&J2rr!!"BmJ#3"B(rr`! -!@5B!N!@!rrm!!&PD!*!&J[rr!!"hrJ#3"B(rr`!!L5J!N!@$rrm!!*(U!*!&K2r -r!!#M"!#3"BArr`!!Uii!N!@'rrm!!,33!*!&Krrr!!#mUJ#3"!G0CA0cB@GP"P0 -dBA4eF`G%G@jRC@pZ"%ePER8%9'9iG!Y%D@&REQpcG'PMF`4198a-"%jeEA!*9@j -cD'PQG'9N"e0SD@CdC@3&H@j1BA%#H@i$H@ja"(PZBA%08feKE'`J4f9dE'PZC3C -3FQpYF(3)5'&MDdC[ER3+8&0)B@0V4QpZG!a38dKKBfY'Efjd)$N+8&0)B@0V4Qp -ZG!e0DA0M,L"6G(*TEQGc#P48@5"AD@jNEhF(E@9ZG@*KFJGcG@*YC@je!dYLC!4 -)C@a`"%PZCQm$3@0d"8eKCfPM"%*TG(--BfpZG(*[E#"VCAPc#h"eEQ0dG@&dD@p -Z#'*bB@0VCA4c"@%J,5"Y"@iJ,5"k"8%J,5"0"8iJ,5"D"6!J,5!j"RGTHQ&bC!G -MGA*bC@jd"%e195-18(*PCL"'D@aP)%jKE@8&4A&eDA!(BA0VEQ&YC396G'&bG!Y -"BQpeG#pPFR*[FJG$EfjQDA*Y#d&LEh9d,f9bFQpb"d0[EQCTFQd'8(*[EA"d$90 -YB@aX)%GPG'aTEQ8&H@j1BA%%H@jKF30jER%#H@i,6Q9h5'&MDdC[ER3-r!: +("2q3"J#3!c!!N!F%!!$GN!B!!3#3"`)!N!F$!*!("2q3"J#3!c!!N!F%!!$GN!B +!!3#3"`)!N!F$!*!("2q3"J!!#-i!!3#3!a`!N!01!*!%rrm!N"#!)!#3"8!!3!# +3#8J!N!0)!*!&"!!"!!3!N!B)6J#3"#)c-L+3"5-L%4)L)MYiXL+3"K)M-bY$1l- +LN!-c-L+3"5-L)K)5[(h$)T!')5)M-b9$)eXb)L)c)T!*)eHA8b+3#50$1d-bZd) +L)L3b)T!$-L)M0,CpRFXL)b)L)b+3"M1l3c)PBb)L)l-cZfc'E(ICU[fb)e-M-b+ +3#E4$-b1mXd0,HCQCUT!$rkUBa6-L*M-c)T!()b1d3c-b*'amb0aP9EZlE'9EY&D +c-L46-c)K)c)5)lY8+l4$-M-b*FCXZd-L)K&,4%ZdYV-c-eXc-L)MZj!$3V3VY$1 +3"E-L@d-b)L'lN!0%4E3c4,8c)LYPXb+3!bXl4$0%-dZl-c1l-c-L)9ZlY%3cY%4 +%1l-MCM)LN!3N*83d0%5l3c-b46-c)L*8Zl4%3lY%4$0EA&-b)T!&*84$0%5d-c) +L*6-c-L0EZl4%3cY%5c*FDc-LN!BQZd0$Y%3c-L)V3c-L+l5lZdXc+d4%-V@d-L+ +3"%)L0E4%-c4$-c)L)d3c)L@dZd4%3cY$0$)f4$)LN!3b)PY$-c3cN!3L)N-b)LC +,Zd4%-b3d4$)QY$)LN!4#)V4$-c3l-j!$)L)c-L+eZlZd4$-MY8-b*N-b)T!%3b+ +l4$0$-j!$0$)L)M)LDlZlY%3c+eDd-MBc-b+3"$3LY%-c0$13"$)L)M-PDlZd4%- +c1eCPXN8c-b+3!a%V)N3cN!BM)T!$-caEZl4$-c0,9E99Zc-b)T!$%4Xb0$13!c) +M-b)L)5)b9EZ3!c-L1l9EZl[--b+3""%E3c3c-c)L)c)LN!3c@lZ3!d-M5e9EZl4 +ADc)LN!-4%e-l-b-b)M)b)T!$)$C9@lZlXcZe@lZlY,aQY$)L)K%5`c3b-c)L-M) +LN!-Vc&@lZl3c4E9EZlY$YV[&Y#)K%4,,*$-M-L-LN!3V8la9ZlZc0&YEZj!$-f@ +e9QGfZlYSfc4$)M)LN!3VC6-m9EZdY,@lN!5d3f@lZeA-amc-M$3c)T!&1maE3c9 +VZlY9DlZ3!l4$1f@l4,Z3"$0V4$)L)L-L)XaV4$-cbe9QCEZ3!d4%-c9EXc-d4$1 +3!eZlN!1e9V9F@l-c-b*P9P@lN!0%3d-c0VY$-j!&0'Xc-l0&E-c'3c-c)L+m9PZ +lZl4$0$-c0VY%-j!&ZlXb-cAF@lY%3c-b)L%X99Y%4%-cN!3fY$13"#)NY$1c)he +EZl4%3b-L)c*'9E3cN!3b)c1fXc13"#)VXc06@0@l4*!$-L)L098d@l-b)T!%)c+ +l3c13!c)L+d-bE0GEZlY%-c-L)VZlXeZc)T!'-VXd4$-c-L)NXc*&@lY%4$-c)L+ +l-c0#Zl3LN!BbZd-cN!-b)L08-d5d4%-c-b-L+d-L)M0&Y$)cN!-L-c0E3c13!c) +L)QZl-l-c3c-b)L*$-L)L-c5l3c-c-L)M-fXc-c4%-L%Pbc)N8c1d-b)L1l-b)L) +c-l4$-cZdY%4EZj!$99Xb*'@c)M1c0&@c)L-l-c-b)MZlN!1d3c-b)VY%Zl-cYEY +Q4$)L-N)VaV-K%83L)c-b0%4%3c)dY$-L@d53!c5l9V)N3b)c0$5e-L%5Xc13!c) +VZl5d-dY$-L+l-c0%-c5l-L+d-c-N4,Zd-L)b)c0%-LZlY%-cN!-M)VXcN!BL)MY +$-c1lZc3c5c)M-c-b+d3c-c)L-b)L5c-M-j!%)L)MYEZ3!c-L-cXb)c0$-L4%0$) +L)b+3!cXb)c-c-L)M)T!$)c13!c)L*E-cN!-b*%Xc-L-c)T!$06-M-j!$)L)b)L) +c-b-c3b*#1c13!c)N5d-cN!-LN!-Q3b-cN!-LN!8M-L)L-c3L)d-c-c)MZd-cN!- +b)L)QXc-d-c-L-c)L)M)b)L)M3L)L)d3c-b1l-j!&)L)PY$13!d-LN!NM-L+3!c@ +c-cZd-j!&-M)PY$13"#+3"6-b)T!&-b)lY8)eZd3cN!3L)LZc-j!%)T!+)b-c)L- +d99@l4,-c3c-L)LYL-j!%)T!$-L+3"M-M-c)L-c)L-j!$3d-c)L)MBc-L)M-LN!J +l@d-cN!-L-L+3!b-lY$-c)L)MDc)cY@Xb)T!'+eZl@c0$3c-LN!-c-N1d-c1c)L+ +mZl9EY$)L)M)LN!-VZl3c0#-c3c0%-b)N-N4$-c5l3dI'@d4%-c-L)L-L)MZlY$) +LN!8M-L1c-d4$-b)L1l@d1c-c0%-b-c-b)VZ3!c-LN!BVZl)b-c-b)T!$5l-N3c- +dZd1lZl4$@lZl-b)L-j!&YN)L)c)LN!3M-L+dYEZlY9Zl4,9EY%Y$)L-c-b)L)cX +b)T!*)f@d-d4,3c13!l0$0%)L)c-LN!-b)l)LN!-K)T!&Zd-b)M-c-M3c4%-c0E) +L)L-LN!-K%V)LN!F4*&3c)K)K)L)l4$1c-d8b)T!%)5)L)E3LN!BK%5Bd-L+3"6Z +l3d-d9$)LN!FK+c)LN!-M)L%4YM-LN!3K)NZl3dZl3c)LN!-M)L)5)4-b%4)L)b) +K%FXLN!84)N5lY,Zc-b)K%M)LN!853b%4)M)L)5Yc)T!(-d3lZlXc)L)!N!F1!!$ +ZN!B!!Gf3"J!#c*!'!!1lN!B!"+U3"J!&L*!'!!ChN!B!"e@3"J!)4*!'!!NLN!B +!#K'3"J!,QC!'!!aQN!B!$613"J!2!*!*3J$`!*N!N#m"!!%!#3!!6)N!$!!!6)` +!!!Q)N!!!N!6q!!B!!2rh!!B!#`1l!!N!!J#3!cm!N!H!!*!("!#3%#!!N"!"!!E +!!*!'SJJ!N!3"5J!!!B!!!0!!!"$#!#YDa%S!ri2P%))"!"*AKm(Jq)8!"8!&##2 +`2r`!IJ#3!acJ#!#3"5!!!!jJ!!!3!*!&J!#3"`i!N"!J!*!3!i!#K%!3`#!)&!8 +3!#!34!!!!`!##4#EB!!!%83!&!r%5J#ZqU83JJ%!%P@pIlqSK3!&3!8))r!rr!0 +#!*!$#4!8!,R!!!3J!`!*N!!!e6RX6#!!!6PcKIGpcJ!"a(HGlrh4iB`M&hRHGq- +BaMr3d"!J!)$"#BB!N!33!*!$"8ehb+8*)&+&DZGm$e+)SLR4"+2L%L%Y&f)!%NN +!+eV%5J$Glf83JJ%!%PEZkh[BK3!&3!8))r!rr!6!$i!0R4F3!8IJ%KSJ")!*)2( +IeV+5U3!"4ia0#!Ba"")ZM'-B3M&"P$HBaM'*)aLU)C!!D!JJ!)%"!))!N!33!*! +$"9D2`!!!`!!!!4M!&!#3!`)a*"85!!!"QC!!!"93!"32a%S!VYDP%))"!"*9hAH +eU)8!"8!&##2`2r`)`!5!!QXBL!p(rj%U*!bi18#4K9,8)A%!!Nd)9Hm'-D[S2ia +K'%)43D3V@-BaJ5-BNL+)3!2mjlZIkC2V1mqcrM'XBr9!JTch[HjcR*-B`G4cR4M +'-AFr&cjdE9Q5!!UV!#YDamS2hHpPm))"!"2@lZYlhq9q"Ai&IL2`2rhC3I)r)L[ +iZh,(i(c))(0m+Ik9MlP))Dr2`P84T"L*d4!%9IqK(hTr3F3M12SqF5-BN85)3!4 +M'-8M'D0FaM(-%M'USLNJJU-BaM'-BT2rqVk-BaM'-D`*iND-FcGNIr$,6*32r([ +aVYDr(rq3!rjGhAHeU"q"rmRrLIq3!riT3+&&)LXBaV,(rj%S2iKm3!k9K4@e)5% +!"'8JIKL5,`[SPBaK'%)a8D3M'-)a#5-DN!#)K%!%B`Mp)aRM@-BaJj)aU5*&3)1 +r'-B`rrk6'-2dM'-BaM'N2b*'M'-3#%!K$j*V@XI+Aph[B2%!#3!6eZlVHprJIP" +r4Ai6rrm#+-#L45)G'-Gdaq!5'#"`Id!1P3"@XK)"!!4&4%8BNL%%%!k-BaK#-9' +8)aM#-BNLVDL3!)4!"1-)`5-CNeM'-B"5DUULK8#*)6R1F)3JNaM#P)aM1FBaV%P +b6ScM(rM!)J159!r%5P'ZeU!"!!N!%PAGGl@S!!K3#88)%rrr!LM!T-8L#49%&-I +rJ!JNJ$L!!*'!1Nd-!"!S1IZ%ja(1S!#+Mjh[`G(ZMq-A3G&a(%M%Rm,(ihch[4m +CLeLlciH0T&4Ip8"a(YDeVh[HNaMqph1FeVh1GiNL0R0M%!F!!i0-UeV%5P(Glf! +"!!N!%PEZkh[B!!K3#88)%rrr!GY!VlR5(1fi$dIJIrNJ!!#!!2%!%!#3!a!)!*! +')!!+!*!+)!#3"3)!N!8#!3!!!J%!N!3#!i!6J!!!"!#3#33!)!!b!*!*&!r%5P( +rrm!"!!N!%P2rN!2i!!K3#88)%rrr!!J!!!%!N!3)Iq!!#5!!N!SJ%!#3"N!!'`# +3%!%!N!8F"J!!!J%!N!3F!3!J!*!$#!#3#6J!N!--!*!*!9V%5P%!N!-"!!N!%P! +!N!8)8!P&#"2rr`#3"!%!N!33!*!$#-!!N%S"!!3!#3!1!"-!'!!D!"d!)!!P!#S +!,!!b!$-!13!q!%!!43"+!%m!9!"C!&i!B`"S!'N!D`"Z!(-!GJ"l!)!!K3#+!)m +!P!#C!*i!S`#S!+X!X!#e!,S![`$%!-N!cJ$6!0J!h3$L!1F!l!$a!2B!q`%!!3) +"#!%+!3d"%`%9!4S"(`%N!5N",J%b!6F"2!%p!8!"43&(!8`"83&@!9X"B!&P!@S +"EJ&c!AJ"I3'#!BF"M!'2!C!!!C-"Q!'B!Cd"SJ'R!D`"X3'f!EX"`!(&!FS"c`( +5!G8"e`(F!H%"jJ(V!I!"p3(k!Im#"!)*!Ji#%`)B!Kd#)J)R!L`#-3)f!MJ#23* +#!NF#6!*3!P3#@3*H!Q-#D3*[!R!#G3*k!Rm#K!+*!SS#MJ+5!TF#R!+J!U8#U3+ +Z!V-#Z!+m!X!#``,*!Xm#dJ,B!Yi#i3,P!ZN#l3,b![F#q`-!!`8$#`-4!aF$(3- +K!b3$*`-V!c%$0`-l!ci$4!0+!dd$8!0@!e`$B30R!f`$F30h!h`$JJ1(!i`$N31 +@!jX$S31Q!kX$X31f!lN$[!1r!m-$b!20!p%$eJ2A!p`$i!2N!qF$l3!'!!B!"J! +'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J! +'!!B!"J!'!!D3!`)'!3B!"J!'!!B!"J)'!3B#"J!'!!B""J!'!JB!"J!'!JB!"J! +'!!B!"J!'!!B!"J!'!JB""J%'!!B""J!'!!B!"J!'!!B!"J!'!!B!"J!'!3B!"J! +'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!JB!"J)'!3B!"J%'!!B!"J! +'!!B!"J%'!!B!"J)'!!B!"J%'!!B!"J!'!!B!"J!'!!B""J!'!!B!"J!'!!B!"J) +'!JB""J!'!*!$"J!'!!B!"J!'!!B!"J!'!!B!"J!'!3B""J%'!!B!"J!'!!B!"J! +'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B#"J!'!!B!"J!'!3B""J!'!!B!"J! +'!!B$"J!'!!B!"J!'!!B$"J!'!!B!"J!'!!B!"J%'!!B!"J!'!!B!"J-'!!B!"J- +'!!B!"J-'!JB""J%'!!B!"J%'!!B!"J!'!!B!"J!'!JB$"J-'!JB!"J!'!!B$"J! +'!!B!"J-'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B!"J!'!!B""J% +'!`B!"J!'!!B""J!'!JB!"J!'!!B""J!'rrm!!![mN!!!N!6r!!F!!2rp!!F!$`6 +d!!`!!`#3!d-!N$0!!*!)!F!!N!`d!*!&!UUeBL8!Ir!r+)3)!3!%46i2`2JIL#J +!"5!!8%#(m"rr`!#3#!Fi!!!%!*!'!`#3"b!!N!K!!*!2!3#3%N!!N!JU)J#3"9+ +!!!"J!!"B!!!""!!"8"rL*3"A[l8SK!J"!!4&+[VrVr@)+!!&)!"33)I`(rr!!*! +)#2`!!!3!!!&-!!!$!"!!$!#3!b!!N!MJ!*!2$`1!!*!3i!#3"$!!N!-#*!#3#B! +!N!8""!!#UV9L*3"V@ZXSK!J"!!4&0leVhAU)+!!&)!"33)I`(rr!!*!%!F!!`!M +m!!!%!!!"XJ!!!p8j,&)J!!"1A1&mhh1!!"a(HGlrh4iB`M&hRHGq-BaMq)#3!!3 +)!#!`3Q!!N!J"8e`"%!4)#!3&1Gm$f!34!(4!D2L#4#E&lL!"&&!"8"rL*3"A[A8 +SK!J"!!4&+eVeVV@)+!!&)!"33)I`(rr!Gm(`!!#1F3!)r!!%"!"J"b32J!2IeV* +5U!!!8H-633'-3))Lk-BaK#-8'80aM'-BNM'-BKL!U!))!#"!3Q'!!*!$"!#3!`& +9SU)T3NJ8SPV'-!8NSLL+M%#&4)5)5dBa)!%NN!!#UV9L*3"V@ZXSK!J"!!4&0le +VhAU)+!!&)!"33)I`(rr!LN%3!0b4L3!Sr!#*K!#3!!8Tk)!$e9,5BA%!!*&#&8) +"M%%"!rM'-B3K&"T#ZBaM'")aM')B3-3!#!!J3%!JJ!#3!`3!N!-"8#)!N!-`!*! +$4M!&!*!%M%L2a)!!!'Ba!!""!!&3(q)P!&HpG5L%#!%!"%8V@[@ZYBJS!!8J!&" +!Kr!IrpZ+!)!")G')J#Mrj&*%J*!!"6rSJ!1&-G3KF3!!Nd*THm*dDRb&@2S4K#% +8(%)eM'-B%M'+SLK!J!$r1HlRqQ6lc[2XlSaV'2e3)4FplhZFjb6'-(8FjdBaM&b +#4FqG'eBa)!#b8Y+UY@2P"qYDkbq%#!%!"(dh[@[GH[mTr!8r`&2iKr!Irq552NI +L)M',`1Mm"#T%#@F%!HL!!iqBL#'[`!%94"q'*)aX!%PIaK(hTr3B3M12SqF5-BN +85##!!4M'-8M'D0BaM(-8M'USLNJK'-BaM'-BT-BqVq-BaM'-DmriND-FcHiRrdc +9+9!IrMhieleeq2q3"FAV@[@ZYB$q!rrL2ra(rj!%j*)8+5)L2iah@2rr4JIf$i3 +"k)!$K498)5%2i4P)%3BNLm*mL9M'%B3M&"a#-B`M%*)aLSL)))!"'-)r5-C`eM' +-BZ5-DNL48#%IaM'-2rqNrr#p)aM'-BaSJN#4SaM%!%3##9S@UV9Mj5rV@ZX(L!! +4!!4p0leVhAVr!IbJ2qK6q%Irrq!ELK4*)L)aM'YBr!5#*!N2a!(SJ!-!&E+K!3! +#%9!4"L5)33%!5-B4K#-9'N)aM#-3NM'X53J3J!%B`M")aQM@-BaJ&)aU5+&3)4K +'-B`K##6'-+8M'-BaM'L55*'M'-IrK!)6qK93(q)P+0HpG3!)!"%!"%8V@[@ZYB! +!)+!#+&"!4rrri!#+&)NL)M&8GeMrj"iNPJqd!HL!!i"@X4)!%")4B4&'*)LSJJM +SaM'%)a8C3M'-)aL5+Ya*#"#!!6M'-8M'C0BaM'%8QUUS`9!M1-jcR'-)T-B`V5- +BcR'-DT*FNk-ia!#)!#"9+UUeBL8SkeVV!!J!%3!%46HpDpekJ!!JS!)S8%"(rrr +J!)S9'5BKd94"@2`!iKJ!"``!#)!$J$T1NJ!3&!jqi6R%FbJ!#+Mjh[`G(ZMq-A3 +G&a(%M%Ri#)2ihcRZ4mCLeLlci10T&4Ip8"cA0DeVR2FNaMpeh1FeVh1GiNL0R0M +%!(!!H&,48"rL*5MA[A8!#!!4!!4&+eVeVV@!!##J!LK33%Irrq!!XKAf1K#1fi$ +Sr"m#!*!$"!!2J!-!%!!-!"!%!*!'#!!!S!#3#3J!N!81#i!!N!@!3!!!J%!!N!5 +!i!J!N!-"!*!*!3!)!!L!!*!)!UUeBL8SkeVV!!J!%3!%46HpDpekJ!!JS!)S8%" +(rrrJ!)!!!#!!J!!!L2`!!J#3"`-!N!8J#!#3"K!!!+!!N!N%!*!'"!#3"3L!3!! +!J%!!N!-)J%!)!*!$!3#3#3%!N!-2!*!*!9!IiL8Srrrq!!J!%3!%44rrN!5!!## +J!LK33%Irrq!!N!3J!F!!!)rm!!)!N!F$!*!'#!#3#!'`!*!3"!#3"3F"J!#3"`F +!3"!!N!-#!*!*$J#3$JUeBL8SJ!#3!`J!%3!%43#3"b#J!LK33%Irrq!!N!`#!*! +(!`#343%!"!!*!!i!%`!C!"S!(3!J!#8!+J!X!$-!0!!l!%!!3J"(!%`!83"@!&X +!B!"P!'S!D`"Y!(%!GJ"k!(m!K!#*!)i!N`#B!*d!SJ#R!+`!V`#d!,N![J$$!-J +!c3$5!0F!h!$K!1B!k`$`!28!qJ$r!33""`%1!4%"&J%G!4m"*!%T!5i"-`%i!6` +"33&'!8F"5J&2!9%"9J&E!@!"C3&U!@m"G!&i!Ad"JJ'(!B`"N3'@!CN"QJ'G!D) +"SJ'R!D`"X3'f!EX"`!(&!FS"c`(8!GN"h!(I!H%"jJ(V!I!"p3(k!Im#"!)*!Ji +#%`)B!Kd#)J)R!L`#-3)f!MX#3!*#!NF#6!*4!PB#@`*J!Q8#DJ*[!R8#H`*m!S% +#KJ+-!T-#QJ+E!Tm#S`+S!Ud#X3+h!V`#`J,)!Xd#d3,9!YN#i!,R!ZX#mJ,j![d +$!J-(!``$%J-B!ad$)`-T!c!$0`-q!d8$5J01!e)$9`0H!f8$D30Y!h3$H`0r!i- +$LJ13!!19!jS$R`1N!kS$V`1f!lX$`!2&!mS$c`28!pN$hJ2M!qJ$k`2Z!r)$pJ2 +l"!!%N!-*"!S%$`36""F%'`3E"#)!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`! +(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F!"`!(!!F$"`)(!3F""`% +(!!F$"`)(!JF""`%(!JF!"`-(!!F""`)(!3F""`%(!3F""`%(!3F""`-(!JF""`% +(!JF""`%(!3F""`%(!3F""`%(!3F""`)(!3F""`%(!3F""`%(!3F""`%(!3F""`% +(!3F""`%(!3F""`)(!!F#"`%(!!F$"`%(!3F""`%(!3F#"`%(!3F$"`%(!3F#"`% +(!3F""`%(!3F""`%(!3F""`%(!3F""`%(!3F#"`-(!JF""`!!!3F""`%(!3F""`% +(!3F""`%(!3F""`)(!JF#"`%(!3F""`%(!3F""`%(!3F""`%(!3F""`%(!3F""`% +(!3F""`%(!`F""`%(!3F""`%(!3F""`%(!3F""`%(!`F""`%(!!F!"`!(!`F!"`! +(!!F!"`!(!!F""`!(!!F!"`!(!!F$"`!(!!F$"`!(!!F$"`)(!3F""`!(!!F""`! +(!!F!"`!(!!F!"`)(!`F$"`)(!!F!"`!(!`F!"`!(!!F$"`!(!3F""`%(!3F""`% +(!3F!"`%(!3F""`%(!3F""`%(!3F""`%(!JF#"`-(!!F""`%(!3F""`-(!3F!"`! +(!3F!!3!(rrm!!"%Q!!%!N!-F!*!$6J#3"2rr!*!3J%!!N!9!!%!!N!P)!*!$5!# +3"3J!!3!)!*!'%%i!N!3%N!-&"*!,"C!%!J%#!33&"33%"3F4%JS&N!`#!J@3!`F +("!N("3H3"!8&"*!%"`8&"*!,"C!$"*!$!3)""3F,%483"`@3$3)#"38(N!-%#3F +&"3F*"`8&"*!%"353%`8&#a%A%3X("C!)"!@3"!3&!3)&"!3'N!-*"`F&"3F*"`8 +&"*!%"`53"`8%N!8&"j!$#a%@&a)2#33&N!B%"38%"33&"33%"33&"!3'"!H3"!8 +&"!X,"`8&"!3&"`F&N!-(#JX4$!X,$4%5%KFB'4N5#J3%"`N("C!'"!8%N!J&"*! +H3!`@3!`B($3N&"`8("a%A&K3B&"L3"4Q3""J8%K%*"`8%"!8,"`@3"!53#`8 +&"!F%"!N(N!-&N!3%"`X0%!d4%4-3#j!%#T!%#a!,N!-+"`F,#`F("33%"JN("C! +%"!%%"!8%!33%"3F(#3F%"j!&"33&N!-%"!X0$!X,"JF("353"!%""j!*#`H3!`3 +'"!N("C!&"!3(#3N("`N("`3("`3*"j!&"!8&"`D3"33%#`F("C!&"!%(N!N*"j! +(#`F&N!3,N!-("33&N!-%"38("!N(N!B&"`F'#3N'"*!$"j!$"C!%"!3"#3H3#!B +*"j!'#3F&"!8,#`F&N!B%N!-&"`3*"j!*"T!$"353!`F*"`F&"33&"!3*"j!3"3X +(#a!,"`8%"353"J@3!`3,"j!$"JH3#!8%N!3*"j!$"C!$"!3,"j!*"!H3"J8,%!X +("`8&"*!-#`H3#J8&"!3&"!3(N!-&N!-%"!F*"j!*"!H3"J3'#`F("C!$"*!("`5 +3!`B,"j!+"C!$"*!%"j!%"C!$"!X(N!S%"`B(N!3%"JX("`8&"*!)"C!%#`N(N!S +&N!3%N!3(N!-&N!-%#`H3#33%"`B(N!3%"!X(N!-&"*!)"`8%"!H3#`@3"!F%N!3 +'"C!&"`X(N!N%"!B'#3F("J3%#`F("C!$"*!("`8&"!H3#33(N!-&"3F&"353"!@ +3!`30#3H3#!8%"!B,#`F("*!$#`F&N!3%N!F("`3%"j!%"3H3"38("`@3"353"!8 +&"!X,"j!*"T!%#3d0#3B%"JX&N!8%N!8"!33("38(N!3&"`F&N!8("33&N!-%N!3 +&"3B0#3H3"`B%"T!$"`Q3"!X*#3F&N!8%N!8"!33*"38(N!-&N!i%"!%%"!8%#3X +(N!F'"!3'#!B,#3N(N!33$3F&N!-%"33&"!3"N!-("`8(N!-&N!3%"C!&"*!$"35 +3"3F'#`F*"`N(N!3'"!D3!`X,#3H3"!B*%!X("C!$"*!%!C!%"`X&"!F("C!%"!3 +&N!F%N!8!"JX*N!3(N!B%"`B,#`N(N!F0#`X*"`8%N!8"N!-%$38&"`F&N!X%N!3 +&"!3'$3d,#C!$"j!&"JB*"JX*#3H3"JN,#3N0#3N("*!$!C!%""!("!F("C!+"*! +%"38(#`B($3X*"j!&"T!$#`B*#3F*"j!&"!X,"`N*#`d4%!X(N!-+#a)@"`8("`@ +3"33&N!-%N!3&"`X,"`8($3N*"j!$"T!$"`X*#3H3#3B0#3H3"!N,$C!$%!f3""% +0"!F("C!$"!8%"C!%"!F($3d*"j!$"3X,#3N("`N*#`X*N!-(N!S,#3H3$JX*"`F +&N!-%"33%"33&N!-4$3X(N!3&N!-0"`N*#`d,#`F*"j!+"JN,"j!+"38%"!8,#3H +3"3Q3"!X*#3X1#3H3"3@3!`3,N!--#`N*"`N(N!S&"!X*"j!'"3F&N!8("`X*"C! +$"`F&"`X,$C!%#`H3"3@3!`3%"`d,$!N*"j!0"3B,"j!("C!'"`F*"j!$"C!%#a% +0#`N(N!J&"353"3d,#`N(N!J&N!F'$3H3!`8("`8("C!&"j!$"3F("38(%"8,"j! +)"C!%"!3("!3'#`X*#3F("38("C!'"!@3!`F,"j!$"C!$"`F&N!3%"j!$"38,"3X +5%`X(N!J&N!8%"!N,#`B'#`H3!`8&"!8%"C!%"*!$"38(#3H3"!8(N!-&"33&"!F +("C!$#`d9%3X(N!N&N!-%N!-(#3H3"!X(N!-&"!8%N!J&N!-*"j!'"38("38%N!- +(N!-&"3F,#3H3#3@3!`53!`H3!`8%"!F%#3N,"`53"J8&"*!$"38%#3H3!`@3"`5 +3"!8*"`F&"`B*"j!("C!%"*!$"`F&"33&"3F("JN("`8&"!3("C!$"*!$"38%#`H +3!`@3"`53"3X("`B%"JN'"j!%"C!("!F'"38%N!3'"!B'#3F("38("C!%"*!&"JX +(N!-&"3H3"!8%N!3,$3F'"!3'#`B%"j!%"38%N!-'N!3&"33&"!3("!3'"JH3$3X +(N!F*#`N'"J3%"`X,"JB%N!-'#3B%"``*"`8%N!3'"`F&N!F(N!3*#3H3"`8("C! +$#3H3#JQ3!`X,"T!$"*!$"J3'!`3($3d("*!$!3%'"`@3#!3(N!F&N!-(N!-&N!3 +,"j!,#`X*"!3("`53!`F%"!B%"`N*"`53!`%%#3@3"!H3!`8%"!H3"`8&"j!%"C! +%#3H3$38%"33(N!-%"`3%"JB(N!-'N!-%N!-&N!3(N!3&"!3(N!F&N!N%"JF("C! +$"j!%"C!&"!3&"3N("JF&"!3(N!3'N!8("C!&"j!$"33%"JH3"3@3#J3'"`@3"!F +("C!("*!$"33(#3F*N!-("`B%N!-'"!B("`@3"!H3!`8&"!B(N!8&N!S%"JN&N!i +%N!J&N!-("3F("*!%#`F&N!B("38%"JH3"3@3#`3,"`@3$J53"3@3"33&"`F%N!- +'"!F("C!)"!B(N!3&N!`%#`F&N!3(N!-&N!3%N!-&"*!&"C!+"`3&N!-("`8("C! +$"*!$"j!%"3F&"3F("C!&"!3,"`@3"!H3"!@3"J53!`8%"C!'"!8%"3F%"!@3!`3 +(N!3&"`3%"JN(N!-&N!3("`@3"33%#`N("C!$"j!%"C!&"*!("33&"*!*"38%N!- +(#`F'N!3*#3H3!`8%"j!$"3F&N!3%"!N*"`8("C!)"*!&"33&N!3%N!3&"!3&N!N +("`N'"!B,"j!)"C!&"*!%#3N'"3F&N!F%N!B&N!8%N!J&N!S("`N*#`X(#3H3"38 +("C!&"*!$"`X%"C!&"!8&"*!'"C!%"*!+"C!&"`@3#!3%"J3%"JB(N!8&N!B%"!d +%N!J&N!-%N!3&"353#!F*#`N("`@3!`F&N!J%N!F(N!B&N!8%"!X'"*!%"`X,#38 +&"*!&"353"`F*"j!$#3F&"3H3!`@3#!3%"38%"JB(N!3&"j!$"353!`F0"`F,N!- +(N!-&N!3%"C!&"*!H3"38("`8&"j!*"38%"!F%"!H3"J3(N!3%"a!0#`X(N!B +&"`53"!8%"C!$"*!$"`F*"`F&N!N%"!8%"!F&"!8("C!$"j!&"C!$"!3("`N*"`B +'"`3'"j!&"JB%N!-&N!3%"!H3"J@3"!3%"38%"38%"!8&"`F*"`@3#33&"!8%"!H +3!`B%"JB%"JH3!`N*"JB,#3N(N!8,"j!'"C!$"!@3#`F,"`@3$J3&"3F%N!-*"JF +,"j!%#3X,"`N*"j!$#`X(N!B&N!i(N!3&N"%%N!-'#j!$"`8(N!B&"`F&"3H3!`B +(N!-'"J@3$!3("!8&"`@3#!%&N!-%"C!%"!3'N!-%"C!$"!3'"J8&"!H3"`B("33 +*"J@3#J)&"!3#!J8("C!+"!@3"!)#"!B*"JB&N!-""!3""!8&"!H3#!8&"`X&N!X +""38#"3)#"`F&N!-%N!B&N!3"!3)&#`B("`@3"!53"!@3!`H3#!8(#3F&N!S%"C! +$!T!%"3F&N!-""*!&"`8%"3)#!3F,"C!*!38#"38(N!J*#3F&N!8%"!8&"!8&"*! +$!38&!J%("`8"N!-%"!@3"J)"!JX("C!+!J%&"3H3"`N(N!-&N!3""!3&"353"`8 +%!J%%"`8#!C!$"!3&"33%"3%&#K%&N!`#"C!$"j!$"!F*"j!%"C!%"!#3"aN!!2q +3"*QC!!(rN!4QCJ!#rj!%-c-!!rrrc-bCQ3!%rrr-c'CQ!!Arrmc--c-!"[rrQCP +QCJ!(rrqCQ6-c!!MrrfD3"!!*rrpQCM-c!!V-c*QC-c-!#mc-CQBc-`!-c-aQCJ# +3!`h-c$13"!!1c-`c-`#3!`qCQ@CQ-c-!%*QC-j!%!"'CQ6-c!*!$%QCQ-c-!N!- +6CQB!N!88-c-!N!89GhF!N!8@998!N!8A4%3!N!8B)L)!N!8C%4%!N!B)[J!"!*! +$(!#3!di!N!6rr`#3%)!J!*!&3!"!!*!*5!#3!dJ!N!8%!!%!"!#3"JK1!*!%E-C +Xc-c'Gfc-c'c'TRT'c-E-aQE-c+CR%A4(DQc-E-aQUNGQChHU4Xc'c-c'aUE-N!2 +'E-c-5RUUGUCk4QCXE(DNCXCN&X4-c*!$aNChT-E'c-aXE-4QGk&(4NC-afTXT+T +RDNT-a(E-N!4UV'DQc-CXc-aQaRTkGNCfGdCQc'GQCdG+UNG'aXc'aQI-ChCQc*! +%C+Ch4NCf&QCdCXaUc%DQ4'4'4QGXc-aQI'aRc'aQCRTRC(4RDKCfUQ4QCmaQ4+H +U&NCR4(CQc+GQaRE'c'TdCU5K4dGRCdGQG'TfE-c'UNTf5RC'5QE'GkGXCmE-CU6 +-HRTf4(S@G%HQ4kCQc-aXC"URCRCk3@c'HQc-CXb3"'G'4RB@C%CQC'Td4-b3"'H +UCRGQGQChaQCQC'a%CRDNCfS@Gk4N4NCf4XCXc*!%TR4'GNGXCmaXCfc'CQE+CdG +RCdGhGRGfC'6-aXb3!m6'ThCk4UahChc*aRafaN&kG(SATf4R4fD3"-b3"-I-akG +fGfGhc%GNCkCmCXCfTNCNC'GKC'CUC-b3"XCmGj!$CQCR6%V+4'I'4NGfCkCfS@G +UGT!$E-b3"'c'I+CQGk4dG%4d5RCQDXCfCQChGRCdGQHNCQc-N!4Xc(c"GhDQ4RB +@C'4'GdTfCQI+TRbKCd4kaQE-E-b3!dE"c'E'CRGU&RHNC%CRTdaR5Q4fGQG%CQC +%E-E-CXc'CRc'N!2%GfGR4hGfGQ4NI'bKa%HKCaC%C'c-c-E-I-CXaXaXChGdHKH +RC'GNC(E'E-a(B@C%CXGhc-c'GhE(Cmb3"AGf4Q4NChThCf4fGQV-ChT'4'aNE-c +%GhCfE-I-c-E-a'CRTRDRC'5NE%G-b'CQGhGRHQV'c-CRN!0%E-E-N!0XaQChGK5 +NUNG(CfG#I(V'4R4mE-CXI'Gda%V-I-b3!f6(CRCdTkDUGN4k&R4'&TGXGm&Uc-E +(FDaQUXb3"FI(4'Tm3@4f4RB@C%CU"T4QDNHXE-aQ5Nc+'XD3!mb3!fCXaXI%DQD +NTRHNC'GX&mUKG(E'E%akUQ'NE-b3"@ahCdV%CfahCQCdE'I(N!#N5N4Qc'c'c%' +K&Qc-c'E-c-E'4%GNG(CNCRGhc(Cf&KP+T'CXE-c'a"&Qc-c'CXc-E'CNT(4NGR4 +h4RCQCXI'G"CdI-c'E'E-a-b3!fE-N!6(4RC%aRDQT(GhTQE(DQ&"c'b3!mc-aXc +-E-CQE-c-E'I-ChGU`AHRGQ4fTU4'4%5Qc-E-CXCXE-aXE'4'c-c'C%SDG(&fGNC ++5UU3!k&+4d&XCXE-CXE-N!4UTmaXE'5N%8Tk38T+UU4"SDT+GfCNTQc-CQE-E-a +XCU'UGQc'C%T%C'T+HQTUUX4'4Xb3!fc*TXE'E(c'CQCf%4UNGXCRHUT%G+3@4dG +'aQI-N!2'aQbTE'c%c-E-E'CN%D&faXGd5QT"a%UU5USAE-c'aQE-N!1@E'I-c'a +XaXE"URE(E'G+UNTU5NUUUNI-CXCQaXaQE&PQGmaQCQGQCmG"GQCRT+5USD&+S8U +Ua'c-c(aXE-c-aaT+DUCQI(GQE('XE-ad4(&"4%T%T%4NaXc'aQCXN!3CN4UQ4mE +-aXCN4QbNG%TdE-E(5NUK5@aQaQaQCXc-aKT8NCSDE(aXN!9mBDT'aXaK4*!%GQC +NE'D3!fc-SA%4N!-Fc*!$aXCXCXCfV-E'bNT+DQTXE-aXN!6-CUT"4"%4('CXE'D +3!fGUa%V+CQUUT+T'Gmc'N!6-CQ`4&"4%%4GQCmI+bNUUCRUQc-c%UNC+4(4Qc'C +RCfE-aNT+4+UK&dGQN!0N&(TfBD(-E'aUT''THRaQE'GXafc'&+CU%4&"5RCfG(T +%F8TaS4UU&QURDNUKTQaQafCXc'`D4Q3D4+4hGXaRCkC(G%SD&"5R5RT"3DUNTQb +3"-CQUUUKUUUKCh('N!0RCQDRHN53!a4%3D&"T"&-E'E-akC"UUSDT%4fGfaRCfT ++&dT+4%5N4'UNS8UK34C'E-c'TK5NDUTQYQE'CRC'T+UK3A&"UT!$5U'K5U38UQC +%CQC(UU%AUN4kUQE-c'C%UR4h4(4%G%6%5N&"UUSDUUG+CN4(4(5N58CkI'aXTa& +"S@&kHNSDS8UKT*!$C'UN5RCa5RCRTkC+GNGQ4XCm`DT"4+5N4%TdT%T+DUTmCU' +3!a%4aQ4QaQI'Gfamc-c'TQGUHT!$UNUUT+HUSDc%UN4d5NV-SDUKV'D3"-c-C%4 +U4NUUUNUU&-E(ah4mc+GXbUUUaUSD3@E'UXamc'a+5Q4KG%T+UNT(E'c(C+c'N!5 +T%@GUT%CQCQQQCQCf38&%4NDUTU&"GXc'aQ3@c'c'CN5U%CURDUC'Ci&XC%U3!d5 +NTUDU'U&%GfE(a+E-aQC+DK3@4QS@E-aX4'aQT%TRTNTh4mC"3Ac(E-aXUXc-bRT +d4%UNG-6'CN&Qc'HUUNT'5N4fc-DNTXE-E-bUV-c-CQa+3Dc-5XaXa+4QDUU3!dC +K5Rc-CK%AaXCQCUSAaQCXaQT%4Xc'aXb3"'UUDN&kHUTmE-bR4XaXc'GfCQc-N!4 +Qc-c'c*!&aNTkGRGUG"E-CNCXN!0QUUT"GXE'c-bRE-aXI-c-CXc'F84aGd5UNfa +Q4Qc'DT!$GQT%c*!&CXE+aXCQCXaQG'4fI-4Q4'5UI-4Q5UUU3A&a4QE'c!#3"`` +!!*Q3"J!"CT!'!!*QCM-cCQB!!c-cCT!%!!3c-fCQ-c-!"613"'CQ!!BcN!B!"`! +!998!N!-)UT!'!!PhN!B!#P@3"J!,4*!'!!`LN!B!!"%@!!%!N!-F!*!$6J#3"2r +r!*!3J%!!N!9!!%!!N!P)!*!$5!#3"3J!!3!)!*!'%%i!N!36"a)*"`S5%`J#!`) +4%K86#3B(!`)$!K)4!`F5!`)4!`B#!K!#!`8#N!3"!T!$"J-3!`8'N!-#!K!$!K% +$"K)(%a-)%JB#!K!4%JN)%JJ("`B'!K!#%`)#%3F#%3-'%JF5%JF'!K%3!a!$%3- +#N!84!J-(!J-4"K%(%JB(%`S6%J+3!`-4!`B(%4%6%4)4!`B(%a-'!J-'"J)(%3B +(!`-'%JJ9#48(%j!$"K)5%"!("JN6"K%'"a-(#3B*N!-#!`)#%J-3!J)(!`)(!J) +$!T!$%K)(!`B'"`-4!J-#!a%#!J-#%3F$%a3(N!-*"a)("K)("a-("a13!a)+"a% +$"a%#"J)#%3B5!`)'!K!#!3)'%JF'!`8'"`B#!a!'"a!#!K-8&3F$!JB#!K%$!K! +$%JJ(%K)#"J-*"a)#!K%(%4!'%JB'%K-(%K-6"J-$%JB6#3N)%K%%%JJ$"JF6N!- +(%a3*#3B$%a-(%JB#"JB$!J-#%`F'!a%(%3-4!`)3!J)(!J)$"JF(%JF$"JF'#K- +0#JJ5"`-4%a)4!K)*#K-'%K-*#3F(&!F6"`B3!JB#"a)4#4)3!J-5#!B(!JB$%T! +$!`B6"JF'"K-#"a%'%T!$"`-5"`-4"`F4!`S6%J-#%3J6#K%$"J)$"J)$"`d6#4) +#"a-$!`B4!K%(%3B$%4)(%a%("JF'"`J(%K)(N!-'"`-'%3)'"`N'"`F6"JF4%`J +("a%#N!-'%`B'%K-5"`F*$480%`S6"`d("J-4%4-6#!)'"`F*&!N5"J-'"K)(!K% +#"JF5%JF$"K)6"`-4"`F5%3)'!`B*%`F$"a-6#3B5"`-5!`F5"a30&4-(N!-+%J) +4"a)$"J)#"`B(!J-$%!-("K)("J-4%3-'%J)("T!$!J)'%4%(!`-5#K-*"`)(%J) +4!K!#!K%$!J-#%JB*!`)$"J-#"`-'"K!#!K!$"3-5%4-(%3-(%JH3!`)$%K)("`B +'!JF(#3N@"a%#!J%5!J-'%J+3!`-'"a'3!`-'!`)4!K%5%`B(%JF5N!-("K)(%JF +5!J-'%3)4"K)5%`F5!`B'#"-0#4)+%a%'!`B(!`)4%3)3%a)6#JB5!`F'"`B5"JJ +5"`N6N!-'"`F5"a)(#4-*"a)(%3)$!`)$!J-$!K%#!JF6"a)("J)$!JB$%3-#"JF +$%`F'"a)(%JF5"JS'!a%("K-)"`F$!K%#"K)$%JF#!`)$%3)'%j!$!JB#!K!#!a- +4!a%#%3)4!J-#%3F'%JF'"`B'#")(%J+3!a-#%3F(%j!$%3B4!a)$%JF#%3B#%3) +4%3B6#K-'!K)5%`B#!`B$"`F'!K%#!`B5"`N'"JF5&3d8"a-5!`)3%K)(!`B'%JF +(!T!%!`B(%`B5!`)$%JF5%3F(%`F(#3N(!`)5%K-5%J)5%JB$"J)("J-#"a-("JN +$%JF5"`B8#")'!J)(!a)5%!)5"JF5!`+3!`B'%J-#!`F6%`)3!J)$!K%5"`N+#3B +'"`F$"J)5"JF4!a)$!JB#!`F'!a%(%JF6"`N*%JB$!K)("JB6!K)'!`B(N!-5%a- +5!`)3!J-5!4!#!K%5!`-'#JB5"a%(%JF'%3B#%4-("K)'"3-'N!-5!J-#!`B("a) +$%K-("JF'!K)6%K-5%JF'"`B4!`F5%3B(%K38"a%5"`B$!J-4!`-'!JF'"`B$!J- +("JF'!T!%%!)3"`-'%3)(%`F5!`B#%a-("a-)"`B#!a%$%K)'"`B$%JF(!`S6%J- +#%3)$#3F'!`)$!`B(%4)4!J-2!K%$"J-#!`)3!`)$%JB$"J)'%JJ("JF'%3-4"a- +(%JF(%J)'"a+3!a-'!JB#!JB$"`8'%3F5%K-(!`B("J)#"K)(%`F5"K)5"`B#"JJ +6%`B'"a%#!a)6""%4"T!$%JF5"a%)#4-(%a-(!a)#%3-6#3N6"`B(%3F("JB("J- +5#3F)#3F'%JF+#4-(#3S6"`-("`B6%JN+"J8$"j!%%a-5!`B("a-9#3F'!T!$%4- +(%a)(%JJ'"K%$%4))"K-("K-5"`B(!`B'"`-6#3N'!JB'!a))"a-'!a+3!a36%JF +#!`F5%`N(%J)'!`B'%JS6"a)#!J-#!JB(%JF6%3F(!`F$!K%$%3F(%JF5%`J(!a% +$%3F("JB(!a%(!a%$%3N6%K-'"`B'!J-$%3)'"a36"a)$%3)'"K-+%`F5"`-'!a% +3!JB#"JB5%JF5"a)5%4%#!K%5"a%$!3+3!`F(%`F$!J)$%JF$"JF5"`-'!`B#!a! +("JF5#JN8%`F5%a)'"a%#!K)(%JH3!`B'!J-'!J-#"K-(%J)(%3)5N!-'%J)3!J) +'%JF'"JF*"a)&"a%5"a%6"`-'N!-)#3F'"`B#"J-#%JN8%a-(%JB$!J-3!T!$!a% +$"J-5%`F5#K)(%J-#"J)5"`B#!K)6"JB#%J-(#3F5"`)5!`F'"`)3!a)$"`B#%JJ +6"`)$!`B'!`B'!`F'%3F("JF(%JB#!j!$%J-'%J-5%J-#%4-(!`)#%!-'%`)'"a) +5"K%'!`)3!K%4%JF'"a)4!`)'"JF$!J)4"a-'N!-5%JF'"J+3!a%&"J)#"3-4"`B +#"JF(%K%'!JB("JF5"K)$"JH3!a)5&"3,"a%$!3)$"a%4!T!$%3B'"a)("`J("JF +5!`B#!`B'!J-'%K-(%a)'"a-5%J-#%3-9%JF$"JN(!JF'%`N,%a)("JF6"`B("K% +#!`)$%!-'"a-5%`D3!`-'%4%$!a)6"a)6"`F6"a-("a)(&!F'!JB6"`B$!JB$!K) +'"J-4!J)'"`B5!J-'%JF("K%'%`F*"a)(&3J4!J-("J)$"4%(!J-6"`B5!`F5%J- +'"J)4!JN)"`)4!K)("J-#!J-(%4%(%J-'!J%4"a)6%JF(%JF6#4-'#!F#!K%("J) +$!JB(!`B(!`-("JB5!T!$%3-3!K)(%4-)%a)5!J%#!a)(%3F6N!-(!`)(%a)(!J- +5%`S*#JB("`B3%!)4!`F'%4%("K)(%K-5%J-(!K%4!J-#"K-(!a-#"`-("`B#%4% +'!`B'"a%$!K!#"K%$"T!$!`)3!a!(#!B'!J-)%K)'!`F'"`J(%a-(%`F4!`%$"JF +5%`F#%"%#!`)"%3)#%`J("a)(#a-$!J)3!K)(%JF'"a%("J)4%J)'"`D3!`F5!JB +'#"-'%K-(%JB#%4%("a)'"a)#"J)#%"!$"J)3!`B##3N+%`F#%")6%JJ5"`N(%JB +(%JF9#K-6#!B("a)("K)6"`N'"`S6%JF'!JF(%K-(#!B#"J)$%JF6%3F5&K8("JB +5N!-$"JF4!`F9#!N'!`)$"JJ8%JS6"`B$!J-$"a%$%3B$"a)6%JF$!a-5%JF'%J) +$%JB$%K)@&3X6%`F4"K3+%`-#!JF'"JF5"`B("J)4%4-6!`B'!`-#%4%'"J)$%`F +(%JB'!J)$%3F'!`F$"J)$%J)(#3S+#3)(%3F5!`)'N!-4"JB"!J)'%a))!`)$"a8 ++%JF6"`B#%3F5"a)'%JB5"JF("K)5"a)'!`)4!J-6$"-*%T!$%`B6"J-4N!-+%J3 +#N!-$%K-("`B("3)3%4-("K)5"`D3!`F5"a)("a-("a-("J-#"K!#N!-5"K-0#") +("a-)%JF#%3-8"`F5"a%5%`B'%JF5#3N(%J-3"`F5"`B$!K!#!K%$%JB(%3-#%a) +)%JF'"a)(%JB'!a%6"JF'"J-(%3B$!`)'!J)3"`-'!`)##!F4!`-#%3-#!JB'#") +'!T!$!a!#N!-$%JB6#4)(%a)(&!F5!a%$"a-(#!F$!J)5%JB%!K)(%J)3!J-#N!- +3%J-3!a%#%!-#%!-4%`B#!K!'%J)#%!-4"`-(%JF$"K%$"J-#!J-#"K)4!`8$!K% +'"`F5%")5"`B$"a-5%K!5"`-#N!-5%`S5!`8(&3S("J-'"a)$%K%("K%4"`)$"J- +#!J-#%"!#"JN("`N5!K%(%K)#!`B(!`B#"K-6!`F("T!%%JF6%K)#"JJ0#3B$"a- +)%J8$"K)*#JF)"K)'"a%#"K!#%3F*$3F5#3B#"K-(#3F*%`F'%3)$%JF#"a-5%JF +#"a)9&3F#!3F6%JF$%4!#!J-#"J)("a-'%JF)%`)#%JF(%K)(%J)$"J)#"JF5"a) +'"`)$!JB$%a-(%K-#!a%(&4-,%`F'"JS6"J)#%!F'%K)#!K))&43'"`D3!`)$%K- +5"JB)!`)4!J)3"JB5!`B$"J)4%3-4"3-#%3B$%K%("JJ6%JB'!`F5"a-6%J-#!a% +("JN(&!N6"a)("J)'%3F5!`)4!K!(!`B4!`F$"`F*%JF'"a%5"a-6#!B(!J)(%`N +(%3)#!`8$!a!#N!34"a%$"K)("J)"%!)#!`-#"a)$!J-#!`B3!K%#"a)(%K)#"`B +(%`F6%JF'!JF5%JJ*N!-'"J)(%3)'%4%$%!-4%JJ5!T!$%3)$!`B#%3+3!a3*%`F +3%3F4!a-(%K-5"a)$"J-#!`)5!JF'!a-8"JF5%J-#!J-'"J-("JF(%K-("JF'!K) +5%`N5"a)4"a+3!a3(!J%#"a%'"a-6%JS5"a)4"a)'"J-#!`B'!K-)%3B("`B("K% +$!J-'"a)(%`F'"JJ6"J-'"`N)%a%$!K)(#3N+"J)#%3)2!a%4!a)("K)("a%'!JF +'%`B$!JB("J)$%!)#"J-(%`S6%JB$%JB$"JF6"`F6"a)(!`)#"JJ5%JF'%J)'%`B +5&3S(#T!$%J)$%K)*"a)(%4)#"`B(!`%"!J)6%JB'"a)5"J)("JF'"a-(%J)$"K) ++&K-'"J)5"`J(%J-5%J)$#K38&3N5%`-6#4-)"a%("K-#"JB(%`F#%a-9&!F(%JF +5!JB(%`N(%JB$"J-5%`F6%`)$%3F5%JF'%`F$!a%(%a)$"`B$%J-'%3F#!J%#%!) +#!`F'%`-#%Jd,#4-6#3S6"J-#!a%$%3-4"a-5%`F6#"%#N!-$#4)6"`)3%3)$"K) +(%JB#N!-4"`F$%!)!%J)$%3)$"a%#%!X6%JB(!a)3!J)3!JB'!T!$"JF$!J-'"JF +$"T!$%`F(%a)6%`F*#4-+"a%5!K)'!JB$%4)5$3S6&"%5!a%$%K81%3B#!J-#!J% +"!J-5"`B5#3F'!K%'!`F4!J)$%JS*&!-(%3-5"a)6"a!#!K!#!`N("JF'!`)"!J% +#%3F5"a-(%!-("J-"N!-#%JJ8%JB(#4-*"JF5!`F5!`B'%JF5!`)'!a%(%`)'!K! +#%3-5%K-("JB$!J)4!J-4"`-'!a-("J)#!3+3!`B(%`N6"`F5#!F(!a%5"a3*"K% +4!a%5!K%$!J)6"`)$!K!#%JF0&`J6"J)("JB*!`B#"JN+$489%`-5%JF4%3-5&!S +6%a)6"a)4!`B("a-6"`)("a)+%a)(%4%'"K!3%4)5#"-6#K%(#3F)%J)'!JB+&!d +0#3B'"`F4#3F6%JF6%`F$!J)$!`B'"`N(%K%$!K!#!`B(%JF5!K)("`)#!`#3"aF +!!2rrc*!%!!(-N!B!!Xb3"*QC!!2-c*Q3"!!%c-bCQ@CQ!!@CQFc-QCN!"TQ3"J! +(QC!%CQB!#*QCCT!%!!PQN!B!#QD3"$-c!!YQCM13"!!--c0QCM-c!!dcN!B!$J! +!)L)!N!-2hC!'!"#lN!B!%DU3"J!5L*!'!"0hN!B!&&@3"J!94*!'!"BLN!B!&a' +3"J!!#)B!!3#3!a`!N!01!*!%rrm!N"#!)!#3"8!!3!#3#8J!N!0)!*!&"!!"!!3 +!N!B)6J#3"%4!0%3c-%0$4$-c3c4%!$-`-%4%-c3d-d%d4%3d-$13!d0$-$-d&%4 +%-j!$4$-$4!"%&$3c3d%4%c-d-$-c3c4%-c-$-d4%3d-!-!4%-$-c0$&%-d4"%84 +%-c3cN!4"3c0$3c0$-c3d-c0$0#-cN!0"0$4%384$-d4$-c-d4"4%-6"!4$!`3d- +`-c!`-c0!-a4%3d4%0$4%3d-$0%4%3c-c!c383d-c-`!c0$4%3d3d0$13!d-c!d3 +`!c4$4$-d-d4$4"-c-$-`!$3d383c-d4%0$3c-`-d3c-%4$!80%-c3c0$!c-d0$- +$3d53!c"$4%4$3c0$-d3c-d0%0$4$-`-c3d-d-$0$3$53!a-c!d0%4$4$!c!d0$1 +3"8%$!c13"%0%-d4$384"-c0$0$3c4%3$0%3cN!3d4%-`4$"%-c0%-d4%-$4%4$4 +"-a0%4$3cN!0%-c!c-a3c3c-a-d4$3d3c"$-c&%3dN!-c0%-84$-c3d-$0%3c4*! +$-a3c4$4$-c0$-c-80"4$0$4%4$0%0$0%-!3c3d-44%0%4$4%0%4%3c3c0%3c3$0 +%3d4$4"4%3d-$4$0%3a4%0%4%3d0"-c-`4$-c3c3$"%3c3d0"4%4$!$0$0%3c3d- +d3d&%-c3d4$-`!c0%3d0%3c4$3d4$3`3c-a3c4%4"%838&%-c&$3d!$-c"$0$3d4 +$4$3c4%-`4$0%4$4"-49"0%4"0%3c4$13"%-c0$4"3a-$-d-d0%!`-d-c4%380$- +84%3c3`-d!c3c3%13!d4%-$-a0%&$-`4$3$4%4%0%0%4"-c0$4%3c-`-$4!0%0$- +$343c3d0%0!-d4$-44%%d4$-c-%0%N!0$-%0$0%0$!c4$&$4$-c-d0$-d4*!%3d3 +d0%4"4%-c-d4%3838&%0%N!0$4$3c-d53""&%4%0%4%-c%84$-c"%3d4%&%3d-d3 +63c4%0$4!0%4%%8-84*!$0$383c!c-"3d4%4"3d4%38&%0!4%4$380%343d&$4%3 +`0%4$-j!$3d-84"%c4$0%4$3c3d-d4%0"384$&"4%N!-8363c0%4%3d4$4$0$3d3 +4-c3d-d3d3a384*!$0$4%-a4"-`"%4%0%-d4$3d3d%83c4%0%36-c4%0%0%-d4%3 +c&%0!-%3d-d-c0%-d4"4%3`-c0%36-d&%0%4%0%4$4$4$0$!c4$0$3`-$4$4%&"3 +cN!0%4$-d4%0%4$4$&%53!c3c!d53!c-d3d%d!d-c-$-c0"3c3c4$0%4%0%4%3d3 +c4%3d-c3c3d9%4%13!d!!4$0"3d3$4$-c3c!d-d%c4%-c!c0%0%-d4%0%0%-d!c0 +%-d-$3`0%4$3`0%0"&$0%3c-d0$0%3c4"3a4$-d-%-d-c0$3c0%3c4$4%4%%63d3 +cN!-`-d-c&%&$0$4$0%4%3c0$-j!$3c-c4%38%63d4$-c0$-$4$4%4%0$4%0%4%- +c0$0$-j!%4%0"&%0%4"&$-d3c3a-c&$-d3c-$3d-c-d4%0%4$4$4%-43d4"&"363 +c0%4$3d%d4%-c-d53!c-c4%0%3d0%4%0"4*!$38383c0%0$0"4$-d0%-c0$0$-c4 +$4$3c"$0%-d3d4%36360%N!0$-d&"3d4$-d4%-c-%0$0$3c"%0%4$4$4%N!Bc-c" +%3c-c4$3d-%3$-d3c4%%c0%3dN!0$4%-d4$3c3`3c0$4%-c4$0%3d0!4$3d4%&$3 +c4%3c4*!$0$3c0$!c4$3c3c!d3`0%-c0%-c0$3d%d0%0%0$36-d4$4*!%0$0$N!- +c4%!$0$3%4$0%-c0%%8-`&%0"-%%d-d4%&%3c4$!d3`4$!d4%0$4$-c4%-83d0$- +40%-c4$0$&%4%0%4$N!3c3c4$3c%c3c4$4*!$36-d&%4$0"-c3d4%0%%$3`-c4%0 +"3c0"4$4%-c4$3c0$4$0"3d-c3c4%0"0%-6-!-d4%384$-d53!d0$-d-c-c3d3a0 +$3c3d4%0%0%0%0$4$0$-c0$-d&$3d-`0$-c!`0$3c4$3d-$0$-c0$4%3d4!0%3c3 +d-%3c4%-c4!-c-c53!c-dN!-$0$-d4*!$3d!c3c3d3c3d4%&%0%-c4$3c4$4$&%0 +%-`0%4%0%N!3c-c!a4$0%4"4%4$3`0%-c&%!8360$-c!d&%&%&$3cN!4%3c-d3d3 +dN!0$0"-d0%0%3d53"!4$4$4%N!0$4$-d-d4$-853!c4%3d3d3d4%-d4"-83d0%- +8384$0$3`0%13!c0"4$0%-d4%0$-c0%4%0"0$3c-d3c3c-d4$-c3c0$!c-d3d4%% +d4$-d3c3d3c!8-c3`-c%!4$13!c3c3$-d-c3c4%4$&%4%-c4%N!-c-d-d3c0$3c3 +6-c3d3c-d-d0%4%0%3d53"N0%3c-c3d4%0!-d-j!$0%4%0%-c3c!c-d%d0!4$"$- +d4$13"%3c3j!$&%3d4%4$-c"%-`!d0!4%4$0%-d0$4%-cN!-a3d4%3d4%-%4$N!- +c-d%c!%4%0%3d4"4%4%-d3c-d0%3$4%-c4$-%4*!$3d3d3`!c-d-d4$4"3d3d-%- +d-c3d4$4%-c0%3c4%4%0$4%0%3$4%N!0$4%3c&%-d3d0%3a4$4*!%3c0%4%"!-d3 +d4$"%4%0%N!0$0%4%-c0%0%38-d4$384$3a%8-$-c4%%8!%3d-d4$4%4$4$3c%a4 +%-d3c36&%0!-84$-c4$&%N!-!N!F&!!"QN!B!!613"J!#Gj!'!!09N!B!"%53"J! +&)T!'!!!)IJ!"!*!$(!#3!di!N!6rr`#3%)!J!*!&3!"!!*!*5!#3!dJ!N!8%!!% +!"!#3"JK1!*!%%c!#-`#3""-$!`)J-!!b!$#3!c)b-$!J)!#3!a!L)K!c!!"!!!! +`!!!J!J!!-!!K%J#3!b)5)J#3"#!#!!%3!%!`!$!%!!)`%#)J!$-!!J)J!`!")5% +!)3-#!L)!!!)J!3!c!J!`)!!4)!)$-$!!)*!$!L)4!3!5)J!L)J!J!")J%!!c!!) +!!!)5)c!c-#!$)3!L)K%J)J!!!5)!)3!#)"%!%!!`!J#3!b%"*!!!-J)"!J)!N!3 +J!J!b!c!#%#-J)5!!-3)!!$!`)#!!!#%`%K%K)J#3!a)L!!!J!#!#!L)4)L!!!J! +#!`!4)J!`)$!L)3!!!L!L%3)J!#-#)#-J%4%")!!3)J)J)"!3)!-#!L!")J-L!4! +K!K!!!#3%!J!K)4%!)!%5)J!`%3!#3$-!!M%K)"!!)J)5)!)!%J!J)#)K%!%J)T! +$)!)4)!!`!b!3)J!`!L)")L!!!!)J)J!!)K)5!!)$3J)J)!!5-!-b!L!L!!"#)3) +3%6!!%K!#!`!!)J!`!5)!)5!#-J-!-#!#-#%#!L)$)K)30!)#)#!c!b!L!#!L)!) +!)5!J!$)#)!)5%L!L%J!"!M)K!!)J!!0!)K%J!!)$!J%!)6)#!`!L)J%!!K)J!#% +!!L%!)!!"-a!#%L-J)J!!!`!"!`-#N!-!)J)K!3!!!L)5%#)5)3%5!L!L!3!`!!) +L)J#3!`)J)!!b)J!L)3)!-L#3!b)#%3-3!J"!!!!#)"!!3!3#!!!3!#)5!J%J!5% +L!#!#%J)L)!)!N!-")J!#N!-5!!)L!"%#!L)J!J)L)K)J%#)5)5!K%J%J%K%3-`! +!!K)$!L)#!5!#%!)4!J!#%K)J)!!!!L)5)M-5)L-c)!!3!$-`!#)!)!)L!L%3)J! +L!L!K%!%L)3!#!!)"!J)J!5!J!!)$%3)%%K-!%3!#!!!#)J!3!*!$-#!!%3!4)L) +J!J!!)4!`!L!!)L!4)!#3!a!"!#!J)M-#!#)5)4)L)#)J-!%K!#!$)`!!)#)#!!- +J!L!J)J)$!#!J!!)`)L)6)!)!!L)$)!)3)#)d!J!#!b%K!J!J!J%!!J)J!J)L)L- +d)`!K!5-6)!)L!L!!!!)L!6)4)!!M!!!J!"!#!K!#%b!J)L!K)L)M)b)J!L!!%5! +#N!-3-!%`!!-!%!!!%3%$!3!!-J)5)J)4)5!!!3!3%%)K%L!!N!B#!#%#!!!%)3) +!%L)K!5)J)!!K!J)!!"!!!!)!!J!!!j!$!L!K-#)5)L)4%L)J)!)M)4%5)b!!)J) +#-!!!!b-N)!-J-J)!-5!J%"%J)J%4!K!#%L%b-#!!)3!M"#)!!!)!!#%$)!!"!$) +L)5)!)5!3%#%L!M)#!J#3!b!J!$-#!#)b!5-M3#!L!K)4)T!%%4!!)!-!)$!!!`) +!!L"$)$)b!`)`)`)#)L%5!K!L)K%M)!)!)!)!!J-b-5!5!!&!)*!$!$#3!b!M)L! +4)K)#)K)!)#)c-3)J-`!c)J!3)$)!-J!#)`-`%b!!)5%c)L!L%#!#)J!$-!#3!c! +a!L!J%K)c!!!b!`-5!!)K!M-!%"!J3J!!)$3!N!-#!!)L%3)L)$!$!!!$!`!b%!) +!N!-L)J-#!J!#)J)#!!-!!L!!!5)J!`-`-$)`%J!L)J!c-#)J-d!!-!!!%5!!-`) +!!J)K%5)J!`%J!`!L!!)`"$"!)M!!!!)#!")K)J-J-`!#-J%5)L!!)$-!)#!!N!N +#)!!L!"%33L%#)J)!)K)`!J!4!!!5!J!J!`!!)!!!-J)J)!%!!K!#)J&!)5!L)M! +#)#)!!a!#!#!#-$)J)$0!)!)b)#!#)!!5!J!L%L%3!#)`)#!#)#)J)b!#!L)$"!) +b)L!L!*!$-#)#)!)#!!)!)4-J-c!#!!!`!L!`!$!d-!)$)#-J-!)!)3-!!!)`)J% +3)#-$"$-!-!)!N!3#!d0!)")J"$!c!*!$!L!J!#)J!J!b!$"$3!0#)$3!!!3d3`- +!%L!%!`3J!$-!!J"!!#!J!`!J)#)c!!!d!b-#!%!c)c)$!3!!%`!J!#)L!*!$-!- +`-#!L!b!!)!-!-!-!!`!#-!)")#%!)#)J)#)#!!!b-"!!%#!J!J-!-!!M!!)!3%! +#!")J%!-!!!)4)33#!b%#-M)M-#-$!$!c-`!`)*!$-!-#)!)#!#!!)5!J!`)$!5! +#-`)`3c!!!#-$!!!L!!!3)!!L)6)J!`%#)#-!!K3!!!-d-$-!-$!!!#33)J!a!#! +#!`!!!`-!!3*!!!)L!$!$!`!J!#!M-%!!N!-L!#)#)!)$!`!`!M-#)!#3!a%c"$! +%!b!!"!!`-#!!)$!M!J!5)`!!-$!L)!!"!!3J!#-`)!-`!J!!)J"!-L)!N!-$)#! +L!L!"-#*!-!0$!!)J-!)!-`!!!J!M-!!#!`#3"#)`)3!L)$!%!$!#%`!J!$!")!! +b!J!J)!!b)#)#)L!#%J!J!!!$-$!$!$!#!#!!!!%J)c!!N!-#)#-5*!)%%#)K!3! +J!c3$)#-!3`-!!#!#)!)`0$!L!J-!!J!L)!!$!K)#)L)`)`!J-!!!-c!J-#!#)%0 +!4$!!N!-M)*!$!!!M-J-b)J!$!!!#)J!`!j!$)$)c)`3!!b!!)%!L-M!L!J#3""! +J!!*!)"%"!!!d-J-#!!-!!$!!)#)!N!-c-!)#!$)#!`!J!$)#)b)!)!3!-#!!-c- +$-$-J!J%!-*!$!`-!3J-`)J#3!a!3)!!J!`#3"`3!!*Q3"J!"Zj!'!!+UN!B!!iL +3"J!%Gj!'!!!)PJ!"!*!$(!#3!di!N!6rr`#3%)!J!*!&3!"!!*!*5!#3!dJ!N!8 +%!!%!"!#3"JK1!*!%35)R)RBR&L%aFR)L*aG"&8F@%4)LF84(%4%5*b4%&4%Q%L* +eBRB8%LBK*fBQ%Q&b)@%4CfGfGK*fCAFR&P%4&@FQ*b4#*Q8QBKChGfB5*N8L%KB +LCb)5CfBACK*K)5&K*fBP9d*fCL4@*")A&a)N38&b&L)RFRFR)RGdB5&Q&b*Q%A) +4GR)RB8BP&eF5G(Bf!L%5Gb*L%@GK*bB4%KFR%5FK%LCh)KCQC"%Q)4CK3LCR)R% +Q*h*L)4&K)K*'Gb%4*K&K)@)Q&QB9&a*fCb35%d-4%R)RB5GK%@&a0N4b)L%L)K) +N3@&KBK%Q4K)ACL48&8CeFR*RFK349RB54"*LGf)bGRB8CaBK&b)b*R*LC@08-(C +5GbBA*K)9BQ%d&h)5&eC"%5)d)4%KCK*LBA)93"96GQ*L&aFL%A3LGP3R)LC5%L% +8%8F5BR*f*b*L*Q)RFL&Q&"*K*b94BL*hN!0Q)K)A*L*48L*LBLBQ)L*#&(Ca34& +N&a*L&K9$*b*h&hFL%4*bFKFPGb*LB4)QB5GRGK4K%RCh)K*K%8%LGbFL*R*RFKF +L)5BL*Q*LF4%84RBR%5Ca4hFK&a&PCb*QCRF5FQCKF@B@GLFQ)QF@34-@BL%9)A& +"&hCLB4%KFR)8*f89CL)L3NF4GfCQB484%4)Q*Q9K*%%5)L)K*'Gb)Q%R&")Q9(* +A)4%4*QCR%4&#FPGKCK*a%83A&a0N4b)N)K4%-5&K%N)K8K&LBQGa34&"&5&KCbC +'*NGhB54"*P3P99&#)Q*L)5GKB8*LCh)R)dC"FR)RGa%43RBQ%d&h&eB@99*a%53 +MGh%4&bFLF5)LC8%L&hGb%4%@)LGP3R*e&PC8Ch0"BQ84Ca&h*a&b%L)Q3A0%4hF +@&K4L*hH3!aGa3988)9-5GeBQ%L*&348KFRC#4&3@)K&4%b*b*h%R)LG84f*K4P% +QB@)N%@&"GL%4%RBN4"*fF4&#)LGbFL)R)QBLF4Gb)5)L*R3A)QCL%4&a)Q*K%K% +K&N*L)Q)LCQGL*L%L%C!$*R*b)5BR)5F@&K4b)A)44hB8FR&44'BAFRBLGh)4%@3 +5*L*K&LFLFL%5%R)L*"*A*bGR&&-@&d4LFLG"BKBK%4FQ9aF83")QCL*h*bFL&Q) +Q%KCA&44'&K*LF@3A)5%@&a8K)5)@3KB8)@%LF8*L*Q%@&h&&-@%Q*aCfCb)L)4* +#*MGK%4*LCQ95GRC"35*LB5)L%L%aFLBA)A&b&@Gh)4*5)4F44"GKCPFL*f&hFQB +4&R&Q%LBK*hF5GLBK&b&R)LB5*534FACKF@GfFK)LF9BN)4%QBKBL&h*fCK8LBRF +KCK)K3@Gd*f*9*fCKGb)KBL%K%54@*#CK&bGb*@)RFKCRBL*b)K34)P)QB9FR)Q% +A*hGa&8)R)Q)8*LFL)4GKGb)RC5*K*Q*K)Q)5%M4LF5Gd3R9N*h)QN!4KB5%5*hC +f)6F89f*4)@*hF5%M84FLGb-QFR*e99%LB5CRB4*f%NGN8K9#Gf&h*RF5%@BN*Q) +L4"C')K&84")MBQ%5!5)@)L)R%@)K%R%ABQFRCA9(*8-4FK4b&9*8B5%L*#CdF53 +5)4%R*h&")R&K*h&a)LFP-4Ca9#GQ9$33FLFR%f)5%L%@%4)RCd%5)AGa8KB9BL4 +%-435BK45&`%9BR*M4NGh)4%8%K)@44BA)L)5%4&R&&38FK%A)QCQF94#*9944a% +L&K%4CR34CaC@*R%4BLF5GK*LF@%A)R*f9R8!84F4)8)Q%5CbCR)Q)4G&4bGK%LB +L3R)4&&)LGQGb%e4aFAF4"'BRBA%L%5BK&e&KCa%@CK%@)4%84b*PGbG%4#*Q*#* +%4'F4)5CaCQBLF4*"FA35)4%KBA8@&RFQ&P8%Gf&R&R3"FLGb&hFK%K864#*Q)Q% +R%5*K%5%4GLB598B4)Q)4*f)R*LBLBLB54P0%GL*aF4-LFKB4N!-KB4%M4"%5BR% +54#GaB4G@GQ)L88!5GbC"Ch&QFL)4G#9"44%Q&h*bB4)8Cb&K&f4hCL)L85)KF8) +Q%RBKCh)8)K35FL)LFLBLF50L*QB4FQ)L4#*a&b*aCRCR%4BAF4!AFL*L%5&%4#8 +5FRGf%@*RChBN%8)ACf*b*KCbBL*aC%GbGLB4)83d%d&4*L*LFM%Q8K&#G(FQ*Q) +R)A&LCLC4!QGbGR)L384N4K*%*N&"&a%N&%*N3Q%QBQ)QC(FR)435)d)Q&Q*d%A% +5ChG"FL4bFQ)4Cf)@*L*4*%B93Q%Q&%)P"hCQCLFLC6)R)44"%6*b%N%hB@Ga!K3 +K%9%A&(BQCR*L"N)P84)N&KB4&%3N45FL-8CQCL9")5*P%@%LCK)R45%8&#C8%KG +QGK8434*"*')4BKCQ%NBL3A&8)LCQ&dF53Q*@3K-bGK*4GK9(-4BAB5GfCT!$*QC +LC%*K*QCA%L4(*QC%)R)@F63b*LBa%4)@B5CQCe%QBQBK)K&RBP*L*KGb)K-P"aF +4*4)5*b&%GQD3!f)KB4)QGf*b%5*LF5&K*RCR3"%Q%90P38GRBN*QCP*Q&fBL4LG +a)L*hGf)KCb)5CK%@Gf*R&L&#%83L*bCK*#)5B"*&B4&R)L)R*e&#Cb*(3K*#GK% +L%a)P%aF43L%8%K3K*4853QGa*hFQC4&N)Q&L&R*KF4BL*fBd&L8$8Q*c%!&f%a% +L)N)P3LCL)5C'F83%4#F8*Q%KF488C4&"*f493(*f)8%5G4*$%4&fCKC`4!#3"`F +!!2q3"J!"QC!'!!*QN!B!!pf3"J!%Zj!'!!@UN!B!"RH3"J!(4*!'!!!4$J!"!*! +$(!#3!di!N!6rr`#3%)"!!*!&3!"!!*!*5!#3!dJ!N!8)!!%!#!#3"K"1!*!%#43 +9&!Q3"43-#438%38&%4%&N!36&Im1r`lr$JN&%C!'"4)*$!i,$!@3!a)'%`N8#a8 +5"4-*N!F8#C!'&"@3!`8'%C!&"C!$%K)6"`N8ra8(""'3"!84"4)*&Im-$4%&N!- +5%`N9&3i*%K)*N!B8#C!(&!`1r`88%C!'"385%a)6#485"385%a'3"!8&%a39r`i +9%K%&"4)6&"6r&3N&%K-*N!89#3N8#C!%&!crra),%C!'"385%a-8&!@3"")*"4% +4"385#431$K81&"%4"3B*#3`2&"+3"!Q3"")8#C!(&"Arr`B8"4%&N!85%K-*#K% +&N!8'#4%&N!-6&"81#a8-%`88"4)*&3i9%T!$"JN6%`8&%K3*N!F9&Im,#43*%38 +5"4)5%`N8&384N!3&"4)*%J85#439$K8-$48("!N$"3S1&!@3!`B6&383%386&!N +*%a-*N!-9$!`8$!N&N!35%JN*&!`&%3-4%3@3""-8&"81&488&"8-&!B!%K!&&!i +&N!85&"3%"388&")6#3J*#439$Im9#4%&%JB6%a39#3F5%C!("3B6&3crN!-&"4) +'#43%""%$"438"3B&N!35&436#4Ar%JB*N!-8#C!$&3i&N!-5"K-(%`N9#`N4%"! +4N!-&N!-5&3i-rrm&"4)6#3N8"J-3"3N8%4-&N!3'#Im,#4Ar&!F*N!-(%J8&"K3 +5%385%JB5%JN8&Im8%3-4N!3&"3N9N!-1r`8&%K)(#3N'!a!X&%J@3"3N-"4% +*rj!$&3N5"K'3!`86#4%&%38&%K)6#46r$K33%"'3!`8@3"2m&N!-'%K)*&"! +$"431"C!$%3@3!`F8"4%*$[m-#3N&"4'3!`8'#4'3!`@3!a)5#439r``&%C!%"38 +*$"@3!`i5"385N!-6&!83"48,"4%&N!85#384#Im9%`B&"4%3%"%&"3S&%C!%"C! +$%JN8r`i0%4!4"386$!i8%aAr#38'"3B5%JN*%3B9&!83"C!&%K3&%3N8"33&&2m +&%"%3%388#4'3"!8&%JN*&"Ar&3N4%385&3i*"K)9ra35%J85"K)(&"%5#a8&%3@ +3!`B5#435"4-&%C!$%`i-"3-3"388ra)4N!-&N!-(#439$[m1%`8&"`N5"38($!i +9%`B&"4)'#3`&"`N5"K)&N!-5"JN8%J85#384""%8$"33%4%5&2m9"C!&%K-8&3m +9$[m*"385N!88$[m1&4)&"3B5#Im*"C!$%K-,#38%"`N8"C!%%a)4%3B,$4)4"3B +0r``8"C!%%JN8&C!$$!N4"C!%%T!%&2q3!a8&%385$434"C!%"JN9!33-#4%&N!3 +5#4%4"3N9$K-ǡ&38&#"3)%a-9&3N*&"%&%38&%K)'%K)*&Im-#4%4"385&"3 +&N!35#3X"""34%3@3"")*"4%4#3i-&4-8$JX&N!-'#K8&%C!$"3B5%"%&"4)'%T! +%%a6r$K34N!-&"3B9&!@3!a)6&")*"4%&N!B*"4%&&!`9&3d9ra)4"385#3N4N!3 +&%`83%3@3!a+3!`B6%a39&434%4!&N!-*$4)'%K)6&!S&%384"C!%%K-6%388$[m +9r``9%4%&"4)*#4%%%4%%3%4%&%T!&"K)8$`i*%C!$"385%K39%K)6#438%"% +&N!B5%`N4"KArN!-1$")4%!8&%JF*%C!$"3B8%C!$"385N!3'%JN*&3i6%4%$%4% +&%JN1&!B6#485%4%&N!85%JN*"46r$Jcrr`N3%4%&N!-*#K)4%3B+#a'3!`8&"K+ +3""-*&!i-"4'3"!8&%JN0&3J5#434N!-&N!85%JQ3!`lrN!--#4'3"!@3!`N8"`8 +5#3`-"4%4"385N!-6%JN*&2m9%3-4""'3!`86&C!$%K36%"%&N!85"3B8#439$[r +r%a!$""'3"!8*&485#48-#4'3!`8&%T!$%a)6#48-#4!4%384%38&%K39&43+%!3 +4"C!&%K)(&!84%Jcr&!85%K'3"!8+-#4)$#3N&%4%&"4)5%a)6#4Ar&")3%"' +3!`@3!`B8r`i-#4!$"C!(%K3*"386&2q3!a3*&!84%38ǩ%`8$"3S5%4%&"4) +5%a-*#Im1&4'3"`8&%K6r$K8*%"%&N!B5%`N4%386&3X8%J@3!`B8&!N5#489%J- +%"4)*%J8&%T!$%`N*&3i-&!-4N!B&"4)9&4-'#3N4%3@3"4)*"4%4%a6r#3@3"4) +5&"@3"!8#"4'3!`8'#488#4-6#481$[m8""!3%C!%"386&435N!-*#4%&N!3'#4- +4%4-9&"%4"C!&%JB(&"@3!`3$%4!3%4%&"K-8$"88&Im9#C!%%C!&"385#3i5"4) +5%a8)"38'%JN6%38*ra)3%3@3"a)5#"6r&433%!-3N!-4"38*&"81rrm9#3J(#3N +4N!8&%K3*"C!$%K)*&4)&"4-*"JN9ra3#%"%&N!-5"C!%%K)*&480%K%3N!84"38 +*&Iq3!``8#3N6#434N!-&"K3*"C!%%K)*ra85#435%`N*$!N#!a%&N!-5"4)&%T! +$%a39&3N4%3-3%4!4%38&&"Ar$J`9&43(%a6r&"-*&"-4%3@3"")6#`i8%a)&"4) +5&"3#%"%&N!J'%K)*&3lr"4'3"`85#46r$J`9N!-6%`N1rrm6%`N4%3@3"4-9&4) +5"C!%%K-8!K!3"C!'%T!@3!a3&%38&%C!$"3B*&3i-&C!$$JB6#Im8"385&!N +4"384"385&"35"4%&"4)&%JN4%"%4"C!&%J85N!-6&3`8#4)'%J8&%38&%K39r`i +-&48*%a-8#38&%K)6&"34"4%&"4)9%`84"385N!36#4!$%4%&N!B5%JB*$43&N!3 +5%K-&"4)*&2rr$J`8#")6%`N&"4+3!`J*&4-4"4%&%K35%4%&"4+3"!B8%K!4%3@ +3"4)5"K)*&4)4N!3%"38*&!N8$!lr&")'%a)6%K%&N!-5N!-6#484%38N&%4% +&"4)5"JB5#484%"%&%3@3""+3!`N9%K!4%"%$%!8&#Irr$J`1&!85N!-*"4%&N!- +5"K)6#436"38'&!8&%4%&"4+3!`B6#488!a%4"C!&%K)*&!i&%C!%%"!4%JIr$!i +9&3i*%K)6#4%4"C!$%T!$"JN8&3N5&384"384"385"K)6%JN9$")4N!3&%J85"a6 +rr`84%334%"!&"3F9r`i9#481%a)(%a!4"C!$%T!$"K-*$2m-$K%&N!-4"385N!- +6%JN9$K85%3@3"")6&2m1ra)4!a%3%"%&"3N9&3i*"JVrra38#4%&N!-5"4+3!a- +8r`lr$!N&%3@3""+3!a-6#43-&3`9%J8&%a-*#439$!N%%C!&"4)*&Im*"4)*&3l +rra33%3@3""+3!a-*$[m1&48&N!B5"K)5#3N9$K81rj!$&!@3!a)*&"31"4'3!`3 +4"4)+ra8&"4)*$"89$"83%3@3"4)5%`Rr$K3)#43&N!85%JF)#439$K8-$J`*"38 +4"3B*#439#4'3"!8'#489"4%&"JN9$K88r`84%38&%JB5%K-*&3i*%`N8%a%&%T! +%%`N*&"@3!rm1%`84%38'%K-*#4Ar"J@3!`B*$"34"!8&%JN1$!N6#`N4N!-&"4) +5%a-8$K85%K-*&!85%K-5%`Q3!a89$K89%K'3"!85N!-6#489&!B&"JN9&4)4%38 +&%K3-&")'&2m5%3@3!a)5%`N8&3N5N!-6#486%K13!a)'"4)8&!i&N!-4"C!$"K) +5%`N*"4%&%T!$"JN8$K)&"3Ir$385%JN9ra)4"385%JN*&43&%T!%#43-%a-8#4% +4"3B*$!d4%3@3"")'%JB6%K%4"3B&"4)'%`N8$4)5&2m*"C!$%``1$JN&"3B6#"8 +9"C!&"K)*&38&%K%&"JN8$2m8%"!4%38'%T!&%4%&N!35N!-'"JN9&3Rrr`@3!a) +5&!i9"`8&%a3-%K%4"4%&N!-'"a34"C!&%K)*&"33%4%&"4)5%a-'"4!4"4%&N!- +5N!-6%`RrN!35"C!$%K6r%K!4"4)*&"84N!-&N!35#43&%3@3"4)'%a3'%4%&%K- +*#4-'%4!4"C!'%JB5%JN9rrm1#3@3!a)*&!-3"C!$%JN8&"%4"4%&"3B(&"-&N!F +'%K-8#38&"JN8#3F6!a!3%3@3"K)'%JN9rj!$$!@3!`B8"4!3%38&"K-8&384"38 +4"4)6&!i&"4%4"C!$%J85%K8*"3B8&!N6%`)$%"%&N!-5"C!$%K)*&!i9%K-8&"- +5#3-3%4%&"4)(#438%3@3"!B*$!`5"C!$%4%&N!3'#3`*#438#3S*!K!4%3@3"JB +&"JN8$"3&"4-8&C!$%"!4"C!$%K-*&"8'"C!%%K3*&")&%C!'"385#3i-&488#`N +5!K!4%3@3!a)&"K+3!`N8$K-&N!-6&481#3-4%38&"K)6&"Ar#385%a-5#3N6%C! +("385#480$"89#4)&!J)$%3@3!a)&%T!$#3N,$J84"38'#3lr$!84"C!$%K)*&"6 +r&4)5"K13!`Q3!a%&"4%4"C!$%JN9&3lr&3@3!`-!%"%%"385"4)5%`J*&484%3@ +3!a-8ra88%38&"K)5%`N8r`N5%K-6#C!%&4)4N!-&%38&%a3-&3`9%K%&"4%!!J- +4%3@3!a+3!a-8&434N!-&"4)8r``9%`8&%JB5#!N8&4+3!a13!`Q3!a38%C!%"38 +5#4@3!`i5%4%&%38!!K%3%3@3!a)5%`N8$!N4N!3&"JN1&488"C!$%K)6#43-%J8 +'%`Q3"439%4%%%385#3X1#a36!K%&N!34!J-3!`84"3B6#439&384%"%4"4)*r`` +9&4)&"4)5%`N8&4)&%K-*N!B9"4%4"JN8$!i9#433%"%4"4%4%K)3!`-4N!-&%`N +9$JN4%4!4%385#3`9N!-'"385%K-*#485"4)6#C!&&"35%3B*#439&385"K3&N!3 +4"385#4%$%3-4"3B8&3N4N!8&"4)6$!i9&4-&"4)'%`N8&!8&%K)6#C!&&43&#C! +%&!`*"3N1%a%&N!B5&43'"38(&3i1%a'3"J8`9N!-'"C!$%JF*&"3+"4)5#C! +&!*!(&J!!c-bCN!3!!Fc-QCPQCJ!#QC!'!!1CN!4QCJ!%QCPQN!3!"@D3"J!'CT! +%-c-!"fCQ-j!%!!Jc-fCQ-c-!#613"J!+-j!%!*!$#b)L!*!&$"%4!*!&$3!!)L) +!N!-1!!!4%3#3!`m!N!34%3!3L*!'!"&hN!B!%P@3"J!64*!'!"3LN!B!&4'3"J$ +r!*!)!3#3!mRS!!$)k!!!"r`$XkJd!hS!N!-F"TB!&eG*6N3!"`$#9%e36!!"!5* +1G@e`!!%"1N&-8P3!!`&54%P86!!%!B*69&)M!"%"[QPMFc3!"!+@D@0c)`!%!Y* +*3diM!!3$$QPME$3!"!0+4%a24`!!!iC'6dj8!!8$NNC26N3!!J2D3e958`!)!rj +ZD$-a!!!%DNC548B!"!4f3Nj%6!!!",*048j9!"-%[Ne195-!!3@Z8e45)!!!"FC +NBh4L!!!&dQPMG')!!!AHB@0dBJ!$"HT`F'&d!!F''J#!!#d!N!0i!*!&J3#3#i) +!#!#3!b!!N!@$!!m!N!2H!*!&K!!A!*!$3!#3"B8!(!#3!eS!N!@'!#%!!!%#!*! +&K`"f!!!jh!#3"B!!-J#3!ji!N!@"!2d!!%h1!*!&J!!h!!!LkJ#3"B%!33!!)`3 +!N!@"rrmJ!!MJ!l1Qf!#!rrm!!%lQ!l1PV"1)!58!!%li!l1Q%"1*!6%!!%*4!l1 +Pm!#"rrmJ!!M`!l1PK!#!rrm!!!b-!l1QB"1)rrm!!%jQ!l1QL"1*rrm!!%kH!l1 +PZ"G`rrm!!&+%!l1P[!#!!'JJ!!%Q!l1Q,!#$!*%!!%Z4!l1P(!#%!*8!!%iG!l1 +Pi!#&!*S!!%im!l1Pr!#'!4%!!!l1Pj!#(!*m!!%pQ!l1Pf!#)!+-!!&"G!l1 +PJ!#*!+N!!%m+!l1Q0!$*!+i!!%`P!l1QR!$+!,X!!%b1!l1Rk!$,!-F!!%bd!l1 +PM!$-!0!!!%cD!l1Q2!$0!0B!!%ck!l1PX!$1!0`!!%dD!l1PD!$2!1)!!%dk!l1 +Q"!$3!1J!!%eD!l1PT!$)!1i!!%ed!l14Y!$4!28!!%fk!l1Q)!2Srrm!!!&!!*! +%!qRrr`!!!F3!N!3$k[rr!!!-XJ#3"!2VrrmJ!$Sk!*!%!qcrrb!!1Vi!N!3$k2r +r!!!#5!#3"!2Trrm!!!+-!*!%!qVrr`!!#N3!N!3$krrr)!!l3J#3"!2XrrmJ!$Z +'!*!%!qMrr`!!!Y!!N!3$kIrr!!!$e!#3"!2Urrm!!!P!!*!%!q[rrb!!1mS!N!3 +$l2rr)!!mcJ#3"!2Srrm!!!6B!*!%!qRrr`!!"Y`!N!3$k[rr!!!+L!#3"!2Vrrm +J!$h5!*!%!qcrrb!!2pB!N!3AF!%A!!"4rJ1cT0",LIrr)!!00J1cTe4,M2rr!!! +@`J1cTe"-$!"G)!!X+J1cTda-LIrr)!"GRJ1cTdK-M2rr!!"R+J1cTd4-#3&C)!! +MC!1cTd!!P`"*"!!LT!1cTc`!Q!"5"!!M(J1cTcJ!Q3&0"!"G@!1cTc3#!2rr)!! +j"!#3"!)$rrmJ!$P-!*!%!J6rrb!!1C3!N!3#"Irr)!!h9!#3"!)(rrmJ!$HF!*! +%!J(rrb!!0q3!N!3#"[rr)!!i,!#3"!))rrmJ!$Kd!*!%!J,rrb!!1,`!N!Errb! +!1J#3"S$rrb!!3GS!N!@"rrmJ!%(P!*!&J[rr)!""m!#3"B2rrb!!3IX!N!@%rrm +J!%)'!*!&J2rr)!"#%3#3"B(rr`!!3Q-!N!@#rrm!!%,X!*!&Jrrr!!"$1!#3"B6 +rr`!!3qJ!N!@!rrm!!%4I!*!&KIrr!!"%M3#3"BErr`!!808!N!@(rrm!!%qp!*! +&L2rr!!"&9`#3"BRrr`!!4K3!N!A+rrm!!%E2!*!&brrr!!"(AJ#3"Fcrr`!!4pS +!N!A0rrm!!%K"!*!&c[rr!!")U!#3"Frrr`!!53m!N!A*rrm!!%Pf!*!&d2rr!!" +*j!#3"FMrr`!!5MN!N!A4rrm!!%V1!*!&J!#"&!",-31cT0J!J3#*&!",B31cT53 +!J!%#!!"26J1cT5`AF!%I!!"4bJ1cTG!AF2rr!!"5,!#3""1)!6N!!&1f!l1QG"1 +*!88!!&2U!l1Qa!#!rrm!!&3H!l1Ph!#"rrm!!&45!l1N%!#!rrm!!&5'!*!&J[r +r!!"c+J#3"B(rr`!!K&3!N!@$rrm!!)d@!*!&K2rr!!#H-!#3"BArr`!!TVS!N!@ +'rrm!!+mm!*!&Krrr!!#heJ#3"!G0CA0cB@GP"P0dBA4eF`G%G@jRC@pZ"%ePER8 +%9'9iG!Y%D@&REQpcG'PMF`4198a-"%jeEA!*9@jcD'PQG'9N"e0SD@CdC@3)5'& +MDdC[ER3+8&0)B@0V4QpZG!T38dKKBfY'Efjd$8eTFf-Z)&0dFQPZCh-+9&4C)&G +TEQ4[G`GYC@jeBQ&b"h0eBQePER8$5f*N"%KPE(!%5@jQE`0"Bh3&6@&RD@-%3QP +dF`aMEfjdFQpX)'YPHA-,F(9ZBh4eBA4TEfi)BR*KBfYPG(-&B5!Y)'d&EL!Y)(S +&35!Y)%d&6L!Y)&S&-#!Y)$N'GfPkBA*N"f0eFR*PER3%68j9)`j3FQ9Q)%CTE'8 +J6Q&YC39&FA9TF!GKFfYZB@eP"90dBA*d#d&LEh9d,f9bFQpb"d0[EQCTFQd,3@* +[GA3[CA*bEh)(3fpZCQPbE3Y1CAG)B@0V4QpZG!a38dKKBfY'Efjd)$Q6)`: diff --git a/sys/mac/News b/sys/mac/News index ec2917c..ddbc48d 100644 --- a/sys/mac/News +++ b/sys/mac/News @@ -1,4 +1,6 @@ -Welcome to NetHack 3.3 for the Macintosh +Welcome to NetHack 3.4 for MacOS 7.0 - 9.x + +Unfortunately, the 68k version is no longer supported. This game is brought to you by Dean Luick, Kevin Hugo, and Mark Modrall. diff --git a/sys/mac/README b/sys/mac/README index 7c4d2fb..dae2192 100644 --- a/sys/mac/README +++ b/sys/mac/README @@ -1,3 +1,14 @@ +Jan 2002 + +The MPW compilers are now supported again. + +Support for 68k has been discontinued due to a lack of a debugging +system for 68k binaries. + +Note that the tiled MacOS X port uses the Qt windowport and the UNIX +build system, not this windowport code. + + 26 Nov, 1999 NetHack 3.3.0 was built with Metrowerk's Pro 4 compiler on a PPC diff --git a/sys/mac/macerrs.c b/sys/mac/macerrs.c index b863e32..c154d99 100644 --- a/sys/mac/macerrs.c +++ b/sys/mac/macerrs.c @@ -2,7 +2,8 @@ /* Copyright (c) Michael Hamel, 1991 */ /* NetHack may be freely redistributed. See license for details. */ -#ifdef applec /* This needs to be resident always */ +#if defined(macintosh) && defined(__SC__) && !defined(__FAR_CODE__) +/* this needs to be resident always */ #pragma segment Main #endif @@ -12,6 +13,25 @@ #include #include + +void error(const char *format,...) +{ + Str255 buf; + va_list ap; + + va_start(ap, format); + vsprintf((char *)buf, format, ap); + va_end(ap); + + C2P((char *)buf, buf); + ParamText(buf, (StringPtr)"", (StringPtr)"", (StringPtr)""); + Alert(128, (ModalFilterUPP) NULL); + ExitToShell(); +} + + +#if 0 /* Remainder of file is obsolete and will be removed */ + #define stackDepth 1 #define errAlertID 129 #define stdIOErrID 1999 @@ -33,7 +53,6 @@ void showerror(char * errdesc, const char * errcomment) itemHit = Alert(errAlertID, (ModalFilterUPP)nil); } - Boolean itworked(short errcode) /* Return TRUE if it worked, do an error message and return false if it didn't. Error strings for native C errors are in STR#1999, Mac errs in STR 2000-errcode, e.g @@ -111,13 +130,13 @@ error VA_DECL(const char *, line) showerror("of an internal error",line); } + void attemptingto(char * activity) /* Say what we are trying to do for subsequent error-handling: will appear as x in an alert in the form "Could not x because y" */ { C2P(activity,gActivities[gTopactivity]); } -#if 0 /* Apparently unused */ void comment(char *s, long n) { Str255 paserr; @@ -145,4 +164,5 @@ void popattempt(void) if (gTopactivity > 1) --gTopactivity; else error("activity stack underflow"); } -#endif /* Apparently unused */ + +#endif /* Obsolete */ diff --git a/sys/mac/macfile.c b/sys/mac/macfile.c index aeaa813..9ec8f0d 100644 --- a/sys/mac/macfile.c +++ b/sys/mac/macfile.c @@ -66,7 +66,6 @@ static int OpenHandleFile (const unsigned char *name, long fileType) { int i; - OSErr err; Handle h; Str255 s; @@ -74,15 +73,11 @@ OpenHandleFile (const unsigned char *name, long fileType) if (theHandleFiles[i].data == 0L) break; } - if (i >= MAX_HF) { - error("Ran out of HandleFiles"); + if (i >= MAX_HF) return -1; - } h = GetNamedResource (fileType, name); - err = ResError(); - if (err == resNotFound) return -1; /* Don't complain, this might be normal */ - if (!itworked(err)) return -1; + if (!h) return (-1); theHandleFiles[i].data = h; theHandleFiles[i].size = GetHandleSize (h); @@ -97,7 +92,6 @@ static int CloseHandleFile (int fd) { if (!IsHandleFile (fd)) { - error("CloseHandleFile: isn't a handle"); return -1; } fd -= FIRST_HF; @@ -218,7 +212,7 @@ macopen (const char *name, int flags, long fileType) C2P (name, s); if (flags & O_CREAT) { if (HCreate (theDirs.dataRefNum, theDirs.dataDirID, s , - MAC_CREATOR, fileType) && (flags & O_EXCL)) { + TEXT_CREATOR, fileType) && (flags & O_EXCL)) { return -1; } @@ -298,26 +292,15 @@ macread (int fd, void *ptr, unsigned len) long amt = len; if (IsHandleFile (fd)) { - return ReadHandleFile (fd, ptr, amt); } else { - short err = FSRead (fd, &amt, ptr); - if (err == eofErr && len) { - - return amt; - } - if (itworked (err)) { - - return (amt); - } else { - - return -1; - } + return ((err == noErr) || (err == eofErr && len)) ? amt : -1; } } + #if 0 /* this function isn't used, if you use it, uncomment prototype in macwin.h */ char * macgets (int fd, char *ptr, unsigned len) @@ -344,9 +327,10 @@ macwrite (int fd, void *ptr, unsigned len) long amt = len; if (IsHandleFile (fd)) return -1; - - if (itworked(FSWrite (fd, &amt, ptr))) return(amt); - else return(-1); + if (FSWrite(fd, &amt, ptr) == noErr) + return (amt); + else + return (-1); } @@ -372,12 +356,13 @@ macseek (int fd, long where, short whence) break; } - if (itworked(SetFPos (fd, posMode, where)) && itworked(GetFPos (fd, &curPos))) - return(curPos); - - return(-1); + if (SetFPos(fd, posMode, where) == noErr && GetFPos(fd, &curPos) == noErr) + return (curPos); + else + return(-1); } + /* ---------------------------------------------------------------------- */ boolean rsrc_dlb_init(void) { @@ -388,7 +373,7 @@ void rsrc_dlb_cleanup(void) { } boolean rsrc_dlb_fopen(dlb *dp, const char *name, const char *mode) { -#if defined(applec) || defined(__MWERKS__) +#if defined(__SC__) || defined(__MRC__) # pragma unused(mode) #endif Str255 pname; diff --git a/sys/mac/macmain.c b/sys/mac/macmain.c index 15d71d6..c407aa6 100644 --- a/sys/mac/macmain.c +++ b/sys/mac/macmain.c @@ -12,27 +12,23 @@ #include #include #include -#ifdef MAC_MPW32 -#include -#include -#endif #include #include #include #include -#ifdef applec -#include -#endif #include #ifndef O_RDONLY #include #endif -static void -finder_file_request(void); +static void finder_file_request(void); +int main(void); + +#if __SC__ || __MRC__ +QDGlobals qd; +#endif -int NDECL(main); int main (void) diff --git a/sys/mac/macmenu.c b/sys/mac/macmenu.c index e003697..17fa74f 100644 --- a/sys/mac/macmenu.c +++ b/sys/mac/macmenu.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)macmenu.c 3.3 99/11/24 */ +/* SCCS Id: @(#)macmenu.c 3.4 1999/11/24 */ /* Copyright (c) Macintosh NetHack Port Team, 1993. */ /* NetHack may be freely redistributed. See license for details. */ @@ -288,11 +288,11 @@ ask_enable (WindowPtr wind, short item, int enable) /* Enable or disable the appropriate item */ - GetDItem(wind, item, &type, &handle, &rect); + GetDialogItem(wind, item, &type, &handle, &rect); if (enable) type &= ~itemDisable; else type |= itemDisable; HiliteControl((ControlHandle)handle, enable ? 0 : 255); - SetDItem(wind, item, type, handle, &rect); + SetDialogItem(wind, item, type, handle, &rect); return; } @@ -303,11 +303,11 @@ ask_redraw (WindowPtr wind, DialogItemIndex item) short type; Handle handle; Rect rect; - static char *modechar = " XD"; + static char *modechar = "NED"; /* Which item shall we redraw? */ - GetDItem(wind, item, &type, &handle, &rect); + GetDialogItem(wind, item, &type, &handle, &rect); switch (item) { case RSRC_ASK_DEFAULT: PenSize(3, 3); @@ -451,6 +451,25 @@ ask_filter (WindowPtr wind, EventRecord *event, DialogItemIndex *item) *item = 0; return (TRUE); } + /* Handle equivalents for Normal/Explore/Debug */ + if ((event->modifiers & cmdKey) && (ch == 'n')) { + currmode = 0; + ask_redraw(wind, RSRC_ASK_MODE); + *item = RSRC_ASK_MODE; + return (TRUE); + } + if ((event->modifiers & cmdKey) && (ch == 'e')) { + currmode = 1; + ask_redraw(wind, RSRC_ASK_MODE); + *item = RSRC_ASK_MODE; + return (TRUE); + } + if ((event->modifiers & cmdKey) && (ch == 'd')) { + currmode = 2; + ask_redraw(wind, RSRC_ASK_MODE); + *item = RSRC_ASK_MODE; + return (TRUE); + } /* Handle equivalents for Cancel and Quit */ if ((ch == CH_ESCAPE) || (key == KEY_ESCAPE) || ((event->modifiers & cmdKey) && (ch == 'q')) || @@ -491,8 +510,8 @@ void mac_askname () /* Initialize the name text item */ ask_restring(plname, str); if (plname[0]) { - GetDItem(askdialog, RSRC_ASK_NAME, &type, &handle, &rect); - SetIText(handle, str); + GetDialogItem(askdialog, RSRC_ASK_NAME, &type, &handle, &rect); + SetDialogItemText(handle, str); } #if 0 { @@ -515,8 +534,8 @@ void mac_askname () } } if (pName [0]) { - GetDItem(askdialog, RSRC_ASK_NAME, &type, &handle, &rect); - SetIText(handle, pName); + GetDialogItem(askdialog, RSRC_ASK_NAME, &type, &handle, &rect); + SetDialogItemText(handle, pName); if (pName [0] > 2 && pName [pName [0] - 1] == '-') { short role = (*pANR).anMenu[anRole]; char suffix = (char) pName[pName[0]], @@ -531,7 +550,7 @@ void mac_askname () } } #endif - SelIText(askdialog, RSRC_ASK_NAME, 0, 32767); + SelectDialogItemText(askdialog, RSRC_ASK_NAME, 0, 32767); /* Initialize the role popup menu */ if (!(askmenu[RSRC_ASK_ROLE] = NewMenu(RSRC_ASK_ROLE, "\p"))) @@ -601,8 +620,8 @@ void mac_askname () /* Set the redraw procedures */ for (item = RSRC_ASK_DEFAULT; item <= RSRC_ASK_MODE; item++) { - GetDItem(askdialog, item, &type, &handle, &rect); - SetDItem(askdialog, item, type, (Handle)redraw, &rect); + GetDialogItem(askdialog, item, &type, &handle, &rect); + SetDialogItem(askdialog, item, type, (Handle)redraw, &rect); } /* Handle dialog events */ @@ -627,7 +646,7 @@ void mac_askname () if (!races[++j].noun) j = 0; } while (i != j); if (currrace != i) { - GetDItem(askdialog, RSRC_ASK_RACE, &type, &handle, &rect); + GetDialogItem(askdialog, RSRC_ASK_RACE, &type, &handle, &rect); InvalRect(&rect); } @@ -647,7 +666,7 @@ void mac_askname () if (++j >= ROLE_GENDERS) j = 0; } while (i != j); if (currgend != i) { - GetDItem(askdialog, RSRC_ASK_GEND, &type, &handle, &rect); + GetDialogItem(askdialog, RSRC_ASK_GEND, &type, &handle, &rect); InvalRect(&rect); } @@ -667,7 +686,7 @@ void mac_askname () if (++j >= ROLE_ALIGNS) j = 0; } while (i != j); if (curralign != i) { - GetDItem(askdialog, RSRC_ASK_ALIGN, &type, &handle, &rect); + GetDialogItem(askdialog, RSRC_ASK_ALIGN, &type, &handle, &rect); InvalRect(&rect); } @@ -675,7 +694,7 @@ void mac_askname () for (i = 0; roles[i].name.m; i++) { ask_restring((currgend && roles[i].name.f) ? roles[i].name.f : roles[i].name.m, str); - SetItem(askmenu[RSRC_ASK_ROLE], i+1, str); + SetMenuItemText(askmenu[RSRC_ASK_ROLE], i+1, str); CheckItem(askmenu[RSRC_ASK_ROLE], i+1, currrole == i); } @@ -699,7 +718,7 @@ void mac_askname () case RSRC_ASK_ALIGN: case RSRC_ASK_GEND: case RSRC_ASK_MODE: - GetDItem(askdialog, item, &type, &handle, &rect); + GetDialogItem(askdialog, item, &type, &handle, &rect); pt = *(Point *)▭ LocalToGlobal(&pt); if (!!(i = PopUpMenuSelect(askmenu[item], pt.v, pt.h, @@ -730,8 +749,8 @@ void mac_askname () } while ((item != RSRC_ASK_PLAY) && (item != RSRC_ASK_QUIT)); /* Process the name */ - GetDItem(askdialog, RSRC_ASK_NAME, &type, &handle, &rect); - GetIText(handle, str); + GetDialogItem(askdialog, RSRC_ASK_NAME, &type, &handle, &rect); + GetDialogItemText(handle, str); if (str[0] > PL_NSIZ-1) str[0] = PL_NSIZ-1; BlockMove(&str[1], plname, str[0]); plname[str[0]] = '\0'; @@ -1072,7 +1091,7 @@ aboutNetHack() { if (theMenubar >= mbarRegular) { (void) doversion(); /* is this necessary? */ } else { - unsigned char aboutStr[32] = "\pNetHack 3.3."; + unsigned char aboutStr[32] = "\pNetHack 3.4."; if (PATCHLEVEL > 10) { aboutStr[++aboutStr[0]] = '0'+PATCHLEVEL/10; @@ -1132,7 +1151,7 @@ askQuit() ParamText("\pReally Quit?", "\p", "\p", "\p"); itemHit = Alert(alrtMenu_NY, (ModalFilterUPP) 0L); - ResetAlrtStage(); + ResetAlertStage(); if (itemHit != bttnMenuAlertYes) { doQuit = 0; diff --git a/sys/mac/macsnd.c b/sys/mac/macsnd.c index 1e2588e..e09a489 100644 --- a/sys/mac/macsnd.c +++ b/sys/mac/macsnd.c @@ -55,9 +55,8 @@ mac_speaker (struct obj *instr, char *melody) { /* * Set up the synth */ - if (itworked (SndNewChannel (&theChannel, sampledSynth, initMono + - initNoInterp, (void *) 0))) { - + if (SndNewChannel(&theChannel, sampledSynth, initMono + + initNoInterp, (void *) 0) == noErr) { char midi_note [] = {57, 59, 60, 62, 64, 65, 67}; short err; @@ -89,8 +88,6 @@ mac_speaker (struct obj *instr, char *melody) { } SndDisposeChannel (theChannel, false); /* Sync wait for completion */ ReleaseResource (theSound); - - mustwork (err); } } diff --git a/sys/mac/mactopl.c b/sys/mac/mactopl.c index 4cf845d..b9979e3 100644 --- a/sys/mac/mactopl.c +++ b/sys/mac/mactopl.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mactopl.c 3.1 91/07/23 +/* SCCS Id: @(#)mactopl.c 3.1 91/07/23 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -59,12 +59,7 @@ char def; * If resp is NULL, any single character is accepted and returned. */ { -#if ENABLE_MAC_POPUP - if (iflags.popup_dialog) - return popup_yn_function(query, resp, def); - else -#endif return topl_yn_function(query, resp, def); } -/*topl.c*/ +/* mactopl.c */ diff --git a/sys/mac/mactty.c b/sys/mac/mactty.c index c7cc562..d69c0e1 100644 --- a/sys/mac/mactty.c +++ b/sys/mac/mactty.c @@ -1021,7 +1021,7 @@ short blink_cursor (WindowPtr window, long when) { */ short image_tty (EventRecord *theEvent, WindowPtr window) { -#if defined(applec) || defined(__MWERKS__) +#if defined(__SC__) || defined(__MRC__) # pragma unused(theEvent) #endif RECORD_EXISTS (record); diff --git a/sys/mac/macunix.c b/sys/mac/macunix.c index e4c6900..aedcc0e 100644 --- a/sys/mac/macunix.c +++ b/sys/mac/macunix.c @@ -6,22 +6,6 @@ #include "hack.h" -#ifndef __MWERKS__ -#include -#endif - - -#if 0 -int -uptodate(int fd) -#if defined(applec) || defined(__MWERKS__) -# pragma unused(fd) -#endif - return(1); -} -#endif - - void regularize(char *s) { @@ -33,12 +17,11 @@ regularize(char *s) } } - void getlock(void) { int fd; - int pid = getpid(); /* Process Serial Number ? */ + int pid = getpid(); /* Process ID */ set_levelfile_name (lock, 0); diff --git a/sys/mac/macwin.c b/sys/mac/macwin.c index ac10cbc..76983ef 100644 --- a/sys/mac/macwin.c +++ b/sys/mac/macwin.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)macwin.c 3.3 96/01/15 */ +/* SCCS Id: @(#)macwin.c 3.4 1996/01/15 */ /* Copyright (c) Jon W{tte, Hao-Yang Wang, Jonathan Handler 1992. */ /* NetHack may be freely redistributed. See license for details. */ @@ -8,32 +8,15 @@ #include "mactty.h" #include "wintty.h" -#if defined(applec) -#include -#else #include -#endif #include #include #include #include +#include NhWindow *theWindows = (NhWindow *) 0; -#ifndef USESROUTINEDESCRIPTORS /* not using universal headers */ - /* Cast everything in terms of the new Low Memory function calls. */ -# if defined(applec) -# define LMGetCurStackBase() (*(long *) CurStackBase) -# define LMGetDefltStack() (*(long *) DefltStack) -# elif defined(THINK_C) -# define LMGetCurStackBase() CurStackBase -# define LMGetDefltStack() (*(long *) DefltStack) -# elif defined(__MWERKS__) -# else -# error /* need to define LM functions for this compiler */ -# endif -#endif /* !USEROUTINEDESCRIPTORS (universal headers) */ - /* Borrowed from the Mac tty port */ extern WindowPtr _mt_window; @@ -217,7 +200,7 @@ Boolean CheckNhWin (WindowPtr mac_win) { static pascal OSErr AppleEventHandler (const AppleEvent* inAppleEvent, AppleEvent* outAEReply, long inRefCon) { -#if defined(applec) || defined(__MWERKS__) +#if defined(__SC__) || defined(__MRC__) # pragma unused(outAEReply,inRefCon) #endif Size actualSize; @@ -355,13 +338,13 @@ InitMac(void) { /* set up base fonts for all window types */ GetFNum ("\pHackFont", &i); if (i == 0) - i = monaco; + i = kFontIDMonaco; win_fonts [NHW_BASE] = win_fonts [NHW_MAP] = win_fonts [NHW_STATUS] = i; GetFNum ("\pPSHackFont", &i); if (i == 0) - i = geneva; + i = kFontIDGeneva; win_fonts [NHW_MESSAGE] = i; - win_fonts [NHW_TEXT] = geneva; + win_fonts [NHW_TEXT] = kFontIDGeneva; macFlags.hasAE = 0; if(!Gestalt(gestaltAppleEventsAttr, &l) && (l & (1L << gestaltAppleEventsPresent))){ @@ -643,9 +626,12 @@ got1 : if (kind == NHW_MESSAGE) { aWin->font_number = win_fonts [NHW_MESSAGE]; - aWin->font_size = iflags.large_font ? 12 : 9; + aWin->font_size = iflags.wc_fontsiz_message? iflags.wc_fontsiz_message : + iflags.large_font ? 12 : 9; if (!top_line) { const Rect out_of_scr = {10000, 10000, 10100, 10100}; + TextFont(aWin->font_number); + TextSize(aWin->font_size); TextFace(bold); top_line = TENew(&out_of_scr, &out_of_scr); TEActivate(top_line); @@ -653,7 +639,7 @@ got1 : } } else { aWin->font_number = win_fonts [NHW_TEXT]; - aWin->font_size = 9; + aWin->font_size = iflags.wc_fontsiz_text ? iflags.wc_fontsiz_text : 9; } TextFont (aWin->font_number); @@ -685,7 +671,8 @@ mac_init_nhwindows (int *argcp, char **argv) { InitMenuRes (); theWindows = (NhWindow *) NewPtrClear (NUM_MACWINDOWS * sizeof (NhWindow)); - mustwork(MemError()); + if (MemError()) + error("mac_init_nhwindows: Couldn't allocate memory for windows."); DimMenuBar (); @@ -808,7 +795,7 @@ topl_resp_rect(int resp_idx, Rect *r) { void enter_topl_mode(char *query) { if (in_topl_mode()) - Debugger(); + return; putstr(WIN_MESSAGE, ATR_BOLD, query); @@ -832,7 +819,11 @@ leave_topl_mode(char *answer) { NhWindow *aWin = theWindows + WIN_MESSAGE; if (!in_topl_mode()) - Debugger(); + return; + + /* Cap length of reply */ + if (ans_len >= BUFSZ) + ans_len = BUFSZ-1; /* remove unprintables from the answer */ for (ap = *(*top_line)->hText + topl_query_len, bp = answer; ans_len > 0; ans_len--, ap++) { @@ -1147,7 +1138,7 @@ mac_destroy_nhwindow (winid win) { if (iflags.window_inited) { if (flags.tombstone && killer) { /* Prepare for the coming of the tombstone window. */ - win_fonts [NHW_TEXT] = monaco; + win_fonts [NHW_TEXT] = kFontIDMonaco; } return; } @@ -1160,7 +1151,7 @@ mac_destroy_nhwindow (winid win) { if ((!((WindowPeek) theWindow)->visible || (kind != NHW_MENU && kind != NHW_TEXT))) { DisposeWindow (theWindow); if (aWin->windowText) { - DisposHandle (aWin->windowText); + DisposeHandle (aWin->windowText); } aWin->its_window = (WindowPtr) 0; aWin->windowText = (Handle) 0; @@ -1176,7 +1167,7 @@ mac_number_pad (int pad) { void trans_num_keys(EventRecord *theEvent) { -#if defined(applec) || defined(__MWERKS__) +#if defined(__SC__) || defined(__MRC__) # pragma unused(theEvent) #endif /* KMH -- Removed this translation. @@ -1208,7 +1199,7 @@ trans_num_keys(EventRecord *theEvent) { */ static void GeneralKey (EventRecord *theEvent, WindowPtr theWindow) { -#if defined(applec) || defined(__MWERKS__) +#if defined(__SC__) || defined(__MRC__) # pragma unused(theWindow) #endif #if 0 @@ -1477,7 +1468,7 @@ macClickTerm (EventRecord *theEvent, WindowPtr theWindow) { where.v = where.v / nhw->row_height; clicked_mod = (theEvent->modifiers & shiftKey) ? CLICK_2 : CLICK_1; - if (strchr(topl_resp, click_to_cmd(where.h, where.v, clicked_mod))) + if (strchr(topl_resp, *click_to_cmd(where.h, where.v, clicked_mod))) nhbell(); else { if (cursor_locked) @@ -1595,8 +1586,6 @@ mac_doprev_message(void) { static short macDoNull (EventRecord *theEvent, WindowPtr theWindow) { - if (!theEvent || !theWindow) - Debugger (); return 0; } @@ -1626,9 +1615,8 @@ macUpdateMessage (EventRecord *theEvent, WindowPtr theWindow) { NhWindow *aWin = GetNhWin (theWindow); int l; - if (!theEvent) { - Debugger (); - } + if (!theEvent) + return 0; GetClip(org_clip); @@ -1666,7 +1654,7 @@ macUpdateMessage (EventRecord *theEvent, WindowPtr theWindow) { name = tmp; break; } - TextFont(geneva); + TextFont(kFontIDGeneva); TextSize(9); GetFontInfo(&font); MoveTo ((frame.left + frame.right - StringWidth(name)) / 2, @@ -1770,9 +1758,8 @@ GeneralUpdate (EventRecord *theEvent, WindowPtr theWindow) { RgnHandle h; Boolean vis; - if (!theEvent) { - Debugger (); - } + if (!theEvent) + return 0; r2.left = r2.right - SBARWIDTH; r2.right += 1; @@ -1829,7 +1816,7 @@ macCursorTerm (EventRecord *theEvent, WindowPtr theWindow, RgnHandle mouseRgn) { GlobalToLocal (&where); dir_bas = iflags.num_pad ? (char *) ndir : (char *) sdir; - dir = strchr (dir_bas, click_to_cmd (where.h / nhw->char_width + 1 , + dir = strchr (dir_bas, *click_to_cmd (where.h / nhw->char_width + 1 , where.v / nhw->row_height, CLICK_1)); } ch = GetCursor (dir ? dir - dir_bas + 513 : 512); @@ -1849,7 +1836,7 @@ macCursorTerm (EventRecord *theEvent, WindowPtr theWindow, RgnHandle mouseRgn) { static void GeneralCursor (EventRecord *theEvent, WindowPtr theWindow, RgnHandle mouseRgn) { -#if defined(applec) || defined(__MWERKS__) +#if defined(__SC__) || defined(__MRC__) # pragma unused(theWindow) #endif Rect r = {-1, -1, 2, 2}; @@ -2132,7 +2119,7 @@ mac_delay_output(void) { #ifdef CLIPPING static void mac_cliparound (int x, int y) { -#if defined(applec) || defined(__MWERKS__) +#if defined(__SC__) || defined(__MRC__) # pragma unused(x,y) #endif /* TODO */ @@ -2294,7 +2281,7 @@ mac_start_menu (winid win) { void mac_add_menu (winid win, int glyph, const anything *any, CHAR_P menuChar, CHAR_P groupAcc, int attr, const char *inStr, int preselected) { -#if defined(applec) || defined(__MWERKS__) +#if defined(__SC__) || defined(__MRC__) # pragma unused(glyph) #endif NhWindow *aWin = &theWindows [win]; @@ -2478,7 +2465,7 @@ mac_unimplemented (void) { static void mac_suspend_nhwindows (const char *foo) { -#if defined(applec) || defined(__MWERKS__) +#if defined(__SC__) || defined(__MRC__) # pragma unused(foo) #endif /* Can't really do that :-) */ @@ -2504,6 +2491,10 @@ try_key_queue (char *bufp) { /* Interface definition, for windows.c */ struct window_procs mac_procs = { "mac", + WC_COLOR | WC_HILITE_PET | + WC_LARGE_FONT | /* obsolete */ + WC_FONT_MAP | WC_FONT_MENU | WC_FONT_MESSAGE | WC_FONT_STATUS | WC_FONT_TEXT | + WC_FONTSIZ_MAP | WC_FONTSIZ_MENU | WC_FONTSIZ_MESSAGE | WC_FONTSIZ_STATUS | WC_FONTSIZ_TEXT, mac_init_nhwindows, mac_unimplemented, /* see macmenu.c:mac_askname() for player selection */ mac_askname, @@ -2554,6 +2545,7 @@ struct window_procs mac_procs = { 0, // mac_start_screen, 0, // mac_end_screen, genl_outrip, + genl_preference_update, }; /*macwin.c*/ diff --git a/sys/mac/mgetline.c b/sys/mac/mgetline.c index 3e25e3a..06c9b5c 100644 --- a/sys/mac/mgetline.c +++ b/sys/mac/mgetline.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)getline.c 3.1 90/22/02 +/* SCCS Id: @(#)getline.c 3.1 90/22/02 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -8,6 +8,8 @@ #include "macpopup.h" #include "func_tab.h" +extern int NDECL(extcmd_via_menu); /* cmd.c */ + typedef Boolean FDECL ((* key_func), (unsigned char)); int @@ -48,13 +50,7 @@ topl_getlin(const char *query, char *bufp, Boolean ext) { */ void mac_getlin(const char *query, char *bufp) { - -#if ENABLE_MAC_POPUP - if (iflags.popup_dialog) - popup_getlin (query, bufp); - else -#endif - topl_getlin (query, bufp, false); + topl_getlin (query, bufp, false); } @@ -67,6 +63,7 @@ mac_get_ext_cmd() { char bufp[BUFSZ]; int i; + if (iflags.extmenu) return extcmd_via_menu(); topl_getlin("# ", bufp, true); for (i = 0; extcmdlist[i].ef_txt != (char *)0; i++) if (!strcmp(bufp, extcmdlist[i].ef_txt)) break; diff --git a/sys/mac/mmodal.c b/sys/mac/mmodal.c index 33d6b75..35e00e3 100644 --- a/sys/mac/mmodal.c +++ b/sys/mac/mmodal.c @@ -3,11 +3,8 @@ /* NetHack may be freely redistributed. See license for details. */ #include -#if ENABLE_MAC_POPUP -#include "hack.h" -#include "mactty.h" -#endif #include "macpopup.h" +#include /* Flash a dialog button when its accelerator key is pressed */ void @@ -18,7 +15,7 @@ FlashButton (WindowPtr wind, short item) { unsigned long ticks; /* Apple recommends 8 ticks */ - GetDItem(wind, item, &type, &handle, &rect); + GetDialogItem(wind, item, &type, &handle, &rect); HiliteControl((ControlHandle)handle, kControlButtonPart); Delay(8, &ticks); HiliteControl((ControlHandle)handle, 0); @@ -26,637 +23,3 @@ FlashButton (WindowPtr wind, short item) { } -#if ENABLE_MAC_POPUP -static void mv_handle_click (EventRecord *theEvent); - -#define MAX_MV_DIALOGS 20 -static int old_dialog_count = 0; -static struct { - short id; - Boolean init_visible; - DialogPtr dialog; -} old_dialog[MAX_MV_DIALOGS]; - - -static short frame_corner; -static pascal void FrameItem(DialogPtr dlog, short item); -static UserItemUPP FrameItemUPP = NULL; - -static pascal void -FrameItem (DialogPtr dlog, short item) { - short k; - Handle h; - Rect r; - - GetDItem (dlog, item, &k, &h, &r); - PenSize (3, 3); - FrameRoundRect (&r, frame_corner, frame_corner); - PenNormal (); -} - - -static void -SetFrameItem (DialogPtr dlog, short frame, short item) { - Rect r, r2; - short kind; - Handle h; - - if (!FrameItemUPP) /* initialize handler routine */ - FrameItemUPP = NewUserItemProc(FrameItem); - - GetDItem (dlog, item, &kind, &h, &r); - InsetRect (&r, -4, -4); - r2 = r; - GetDItem (dlog, frame, &kind, &h, &r); - SetDItem (dlog, frame, kind, (Handle) FrameItemUPP, &r2); - frame_corner = 16; -} - - -/* Instead of calling GetNewDialog everytime, just call - SelectWindow/ShowWindow for the old dialog to remember its location. -*/ -/* - * Unfortunately, this does not work, as it doesn't handle old text - * in edit text boxes, and not ParamText parameters either. - * - */ -static DialogPtr -mv_get_new_dialog(short dialogID) { - DialogPtr dialog; - int d_idx = old_dialog_count; - Rect oldRect; - Boolean hadOld = 0; - - old_dialog[0].id = dialogID; - while (old_dialog[d_idx].id != dialogID) - --d_idx; - -/* - * This routine modified so that the old dialog is - * disposed, and the new one read in after we remember - * the old dialog's position. - * - * This takes care of strange default strings and ParamTexts - * - */ - - if (d_idx) { - dialog = old_dialog [d_idx] . dialog; - oldRect = dialog->portBits . bounds; - DisposeDialog (dialog); - old_dialog [d_idx] . dialog = (DialogPtr) 0; - hadOld = 1; - - } else { - d_idx = ++ old_dialog_count; - } - - dialog = GetNewDialog(dialogID, nil, (WindowPtr)-1); - if (dialog) { - if (hadOld) { - MoveWindow (dialog, - oldRect . left, - oldRect . top, FALSE); - } - old_dialog[d_idx].id = dialogID; - old_dialog[d_idx].init_visible - = ((WindowPeek)dialog)->visible; - old_dialog[d_idx].dialog = dialog; - } - return dialog; -} - -/* Instead of actually closing the dialog, just hide it so its location - is remembered. */ -static void mv_close_dialog(DialogPtr dialog) { - HideWindow(dialog); -} - -/* This routine is stolen/borrowed from HandleClick (macwin.c). See the - comments in mv_modal_dialog for more information. */ -static void -mv_handle_click (EventRecord *theEvent) { - int code; - WindowPtr theWindow; - Rect r = (*GetGrayRgn ())->rgnBBox; - - InsetRect (&r, 4, 4); - InitCursor (); - - code = FindWindow (theEvent->where, &theWindow); - - switch (code) { - case inContent : - if (theWindow != FrontWindow ()) { - nhbell (); - } - break; - case inDrag : - SetCursor(&qd.arrow); - DragWindow (theWindow, theEvent->where, &r); - SaveWindowPos (theWindow); - break; - default : - HandleEvent (theEvent); - } -} - -static void -mv_modal_dialog(ModalFilterProcPtr filterProc, short *itemHit) { - GrafPtr org_port; - GetPort(&org_port); - - for (;;) { - DialogPtr dialog = FrontWindow(); - EventRecord evt; - - WaitNextEvent(everyEvent, &evt, GetCaretTime(), (RgnHandle) nil); - - if (evt.what == keyDown) - if (evt.modifiers &cmdKey) { - if ((evt.message & charCodeMask) == '.') { - /* 0x351b is the key code and character code of the esc key. */ - evt.message = 0x351b; - evt.modifiers &= ~cmdKey; - } - } else - trans_num_keys(&evt); - - if (filterProc) { - if ((*filterProc)(dialog, &evt, itemHit)) - break; - } else if (evt.what == keyDown) { - char ch = evt.message & charCodeMask; - if (ch == CHAR_CR || ch == CHAR_ENTER) { - *itemHit = ok; - FlashButton(dialog, ok); - break; - } - } - - if (IsDialogEvent(&evt)) { - DialogPtr dont_care; - if (DialogSelect(&evt, &dont_care, itemHit)) - break; - - /* The following part is problemmatic: (1) Calling HandleEvent - here may cause some re-entrance problem (seems ok, but I am - not sure). (2) It is ugly to treat mouseDown events as a - special case. If we can just say "else HandleEvent(&evt);" - here it will be better. */ - } else if (evt.what == mouseDown) - mv_handle_click(&evt); - else - HandleEvent(&evt); - - SetPort(org_port); - } -} - -/********************************************************************************* - * mactopl routines using dialogs - *********************************************************************************/ - -#define YN_DLOG 133 -#define YNQ_DLOG 134 -#define YNAQ_DLOG 135 -#define YNNAQ_DLOG 136 - -static int yn_user_item [] = {5, 6, 7, 8}; -static short gEnterItem, gEscItem; -static const char *gRespStr = (const char *)0; -static char gDef = 0; -static short dlogID; - - -static void -SetEnterItem (DialogPtr dp, const short newEnterItem) { - short kind; - Handle item; - Rect r, r2; - - if (gEnterItem != newEnterItem) { - GetDItem (dp, gEnterItem, &kind, &item, &r2); - InsetRect (&r2, - 4, - 4); - EraseRect (&r2); - InvalRect (&r2); - - gEnterItem = newEnterItem; - - GetDItem (dp, newEnterItem, &kind, &item, &r2); - frame_corner = kind == ctrlItem + btnCtrl ? 16 : 0; - InsetRect (&r2, - 4, - 4); - InvalRect (&r2); - r = r2; - GetDItem (dp, yn_user_item [dlogID - YN_DLOG], &kind, &item, &r2); - SetDItem (dp, yn_user_item [dlogID - YN_DLOG], kind, item, &r); - } -} - - -static void -do_tabbing (DialogPtr dp) { - SetEnterItem(dp, gEnterItem == 1 ? strlen(gRespStr) : gEnterItem - 1); -} - - -static void -set_yn_number(DialogPtr dp) { - if (gRespStr && gRespStr[gEnterItem-1] == '#') { - short k; - Handle h; - Rect r; - Str255 s; - GetDItem(dp, gEnterItem, &k, &h, &r); - GetIText(h, s); - if (s[0]) - StringToNum(s, &yn_number); - } -} - - -static pascal Boolean -YNAQFilter (DialogPtr dp, EventRecord *ev, short *itemHit) { - unsigned char code; - char ch; - char *re = (char *) gRespStr; - - if (ev->what != keyDown) { - - return 0; - } - code = (ev->message & 0xff00) >> 8; - ch = ev->message & 0xff; - - switch (code) { - case 0x24 : - case 0x4c : - set_yn_number (dp); - *itemHit = gEnterItem; - FlashButton (dp, *itemHit); - return 1; - case 0x35 : - case 0x47 : - *itemHit = gEscItem; - FlashButton (dp, *itemHit); - return 1; - case 0x30 : - do_tabbing (dp); - return 0; - } - switch (ch) { - case '\r' : - case '\n' : - case ' ' : - case 3 : - set_yn_number (dp); - *itemHit = gEnterItem; - FlashButton (dp, *itemHit); - return 1; - - case 9 : - do_tabbing (dp); - return 0; - - case 27 : - *itemHit = gEscItem; - FlashButton (dp, *itemHit); - return 1; - - case CHAR_BS : - case 28 : case 29 : case 30 : case 31 : /* the four arrow keys */ - case '0' : case '1' : case '2' : case '3' : case '4' : - case '5' : case '6' : case '7' : case '8' : case '9' : { - char *loc = strchr (gRespStr, '#'); - if (loc) { - SetEnterItem(dp, loc - gRespStr + 1); - return 0; /* Dialog Manager will then put this key into the text field. */ - } - } - } - - while (*re) { - if (*re == ch) { - *itemHit = (re - gRespStr) + 1; - FlashButton (dp, *itemHit); - return 1; - } - re ++; - } - - nhbell (); - ev->what = nullEvent; - return 0; -} - - -static char -do_question_dialog (char *query, int dlog, int defbut, char *resp) { - Str255 p; - DialogPtr dp; - short item; - - char c = queued_resp ((char *) resp); - if (c) - return c; - - dlogID = dlog; - C2P (query, p); - ParamText ((char *)p, (uchar *) 0, (uchar *) 0, (uchar *) 0); - dp = mv_get_new_dialog (dlog); - if (! dp) { - return 0; - } - SetPort (dp); - ShowWindow (dp); - - gEscItem = strlen (resp); - gEnterItem = defbut; - gRespStr = resp; - - SetFrameItem (dp, yn_user_item [dlogID - YN_DLOG], gEnterItem); - - InitCursor (); - mv_modal_dialog (YNAQFilter, &item); - mv_close_dialog (dp); - return resp [item - 1]; -} - - -static pascal Boolean -OneCharDLOGFilter (DialogPtr dp, EventRecord *ev, short *item) { - char ch; - short k; - Handle h; - Rect r; - unsigned char com [2]; - - if (ev->what != keyDown) { - return 0; - } - ch = ev->message & 0xff; - - com [0] = 1; - com [1] = ch; - - if (ch == 27) { - GetDItem (dp, 4, &k, &h, &r); - SetIText (h, com); - *item = 2; - FlashButton (dp, 2); - return 1; - } - if (! gRespStr || strchr (gRespStr, ch)) { - GetDItem (dp, 4, &k, &h, &r); - SetIText (h, com); - *item = 1; - FlashButton (dp, 1); - return 1; - } - if (ch == 10 || ch == 13 || ch == 3 || ch == 32) { - com [1] = gDef; - GetDItem (dp, 4, &k, &h, &r); - SetIText (h, com); - *item = 1; - FlashButton (dp, 1); - return 1; - } - if (ch > 32 && ch < 127) { - GetDItem (dp, 4, &k, &h, &r); - SetIText (h, com); - *item = 1; - FlashButton (dp, 1); - return 1; - } - nhbell (); - ev->what = nullEvent; - return 1; -} - - -static char -generic_yn_function (query, resp, def) -const char *query, *resp; -char def; -{ - DialogPtr dp; - short k, item; - Handle h; - Rect r; - unsigned char com [32] = {1, 27}; // margin for getitext - Str255 pQuery; - - char c = queued_resp ((char *) resp); - if (c) - return c; - - dp = mv_get_new_dialog (137); - if (! dp) { - return 0; - } - SetPort (dp); - ShowWindow (dp); - InitCursor (); - SetFrameItem (dp, 6, 1); - if (def) { - com [1] = def; - } - strcpy ((char *) &pQuery[1], query); - if (resp && *resp) { - strcat ((char *) &pQuery[1], " ("); - strcat ((char *) &pQuery[1], resp); - strcat ((char *) &pQuery[1], ")"); - } - pQuery[0] = strlen (&pQuery[1]); - ParamText ((char *) pQuery, (uchar *) 0, (uchar *) 0, (uchar *) 0); - GetDItem (dp, 4, &k, &h, &r); - SetIText (h, com); - SelIText (dp, 4, 0, 0x7fff); - InitCursor (); - SetFrameItem (dp, 6, 1); - gRespStr = resp; - gDef = def; - do { - mv_modal_dialog (OneCharDLOGFilter, &item); - - } while (item != 1 && item != 2); - GetIText (h, com); - - mv_close_dialog (dp); - if (item == 2 || ! com [0]) { - return 27; // escape - } - return com [1]; -} - - -static char -ynaq_dialog (query, resp, def) -const char *query, *resp; -char def; -{ - int dia = 0; - - if (resp) { - if (! strcmp (resp, ynchars)) { - dia = YN_DLOG; - } - if (! strcmp (resp, ynqchars)) { - dia = YNQ_DLOG; - } - if (! strcmp (resp, ynaqchars)) { - dia = YNAQ_DLOG; - } - if (! strcmp (resp, ynNaqchars)) { - dia = YNNAQ_DLOG; - } - } - if (! dia) { - return generic_yn_function (query, resp, def); - } - - return do_question_dialog ((char *) query, dia , - (strchr (resp, def) - resp) + 1, (char *) resp); -} - - -char -popup_yn_function(const char *query, const char *resp, char def) { - char ch; - - if (ch = ynaq_dialog (query, resp, def)) - return ch; - - return topl_yn_function(query, resp, def); -} - - -/********************************************************************************* - * mgetline routines using dialogs - *********************************************************************************/ - -static pascal Boolean -getlinFilter (DialogPtr dp, EventRecord *ev, short *itemHit) { - if (ev->what == keyDown) { - int key = ev->message & keyCodeMask, - ch = ev->message & charCodeMask; - - if (ch == 0x1b || key == 0x3500 || key == 0x4700) { - *itemHit = 2; - FlashButton(dp, 2); - return true; - } else if (ch == CHAR_CR || ch == CHAR_ENTER) { - *itemHit = 1; - FlashButton(dp, 1); - return true; - } - } - return false; -} - - - -static Boolean -ExtendedCommandDialogFilter (DialogPtr dp, EventRecord *ev, short *item) { - int ix; - Handle h; - Rect r; - short k; - Str255 s; - unsigned char com [2]; - - if (ev->what != keyDown) { - return 0; - } - com [0] = 1; - com [1] = ev->message & 0xff; - - if (com [1] == 10 || com [1] == 13 || com [1] == 32 || - com [1] == 3) { // various "OK" - *item = 1; - FlashButton (dp, 1); - return 1; - } - if (com [1] == 27 || (ev->message & 0xff00 == 0x3500)) { // escape - *item = 2; - FlashButton (dp, 2); - return 1; - } - for (ix = 3; ix; ix ++) { - h = (Handle) 0; - k = 0; - GetDItem (dp, ix, &k, &h, &r); - if (! k || ! h) { - return 0; - } - if (k == 6) { // Radio Button Item - GetCTitle ((ControlHandle) h, s); - s [0] = 1; - if (! IUEqualString (com, s)) { - *item = ix; - return 1; - } - } - } -/*NOTREACHED*/ - return 0; -} - - -void -popup_getlin (const char *query, char *bufp) { - ControlHandle ctrl; - DialogPtr promptDialog; - short itemHit, type; - Rect box; - Str255 pasStr; - - if (get_line_from_key_queue (bufp)) - return; - - /* - ** Make a copy of the prompt string and convert the copy to a Pascal string. - */ - - C2P(query, pasStr); - - /* - ** Set the query line as parameter text. - */ - - ParamText(pasStr, "\p", "\p", "\p"); - - promptDialog = mv_get_new_dialog(130); - ShowWindow(promptDialog); - - InitCursor (); - SetFrameItem (promptDialog, 6, 1); - do { - mv_modal_dialog(&getlinFilter, &itemHit); - } while ((itemHit != 1) && (itemHit != 2)); - - if (itemHit != 2) { - /* - ** Get the text from the text edit item. - */ - - GetDItem(promptDialog, 4, &type, (Handle *) &ctrl, &box); - GetIText((Handle) ctrl, pasStr); - - /* - ** Convert it to a 'C' string and copy it into the return value. - */ - - P2C (pasStr, bufp); - } else { - /* - ** Return a null-terminated string consisting of a single . - */ - - bufp[0] = '\033'; - bufp[1] = '\0'; - } - - mv_close_dialog(promptDialog); -} - -#endif /* ENABLE_MAC_POPUP */ diff --git a/sys/mac/mrecover.c b/sys/mac/mrecover.c index 6929e77..8a76d93 100644 --- a/sys/mac/mrecover.c +++ b/sys/mac/mrecover.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mrecover.c 3.3 96/07/24 */ +/* SCCS Id: @(#)mrecover.c 3.4 1996/07/24 */ /* Copyright (c) David Hairston, 1993. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/mac/mttymain.c b/sys/mac/mttymain.c index fc3e28e..07b882a 100644 --- a/sys/mac/mttymain.c +++ b/sys/mac/mttymain.c @@ -225,17 +225,21 @@ short hor, vert; } } - mustwork (create_tty (&_mt_window, WIN_BASE_KIND + NHW_MAP, _mt_in_color)); + if (create_tty (&_mt_window, WIN_BASE_KIND + NHW_MAP, _mt_in_color) != noErr) + error("_mt_init_stuff: Couldn't create tty."); ((WindowPeek) _mt_window)->windowKind = (WIN_BASE_KIND + NHW_MAP); SelectWindow (_mt_window); SetPort (_mt_window); SetOrigin (-1, -1); - font_size = (iflags.large_font && !small_screen) ? 12 : 9; - mustwork (init_tty_number (_mt_window, win_fonts [NHW_MAP], font_size, CO, LI)); + font_size = iflags.wc_fontsiz_map ? iflags.wc_fontsiz_map : + (iflags.large_font && !small_screen) ? 12 : 9; + if (init_tty_number (_mt_window, win_fonts [NHW_MAP], font_size, CO, LI) != noErr) + error("_mt_init_stuff: Couldn't init tty."); - mustwork (get_tty_metrics (_mt_window, &num_cols, &num_rows, &win_width , - &win_height, &font_num, &font_size, &char_width, &row_height)); + if (get_tty_metrics (_mt_window, &num_cols, &num_rows, &win_width , + &win_height, &font_num, &font_size, &char_width, &row_height)) + error("_mt_init_stuff: Couldn't get tty metrics."); SizeWindow (_mt_window, win_width + 2, win_height + 2, 1); if (RetrievePosition (kMapWindow, &vert, &hor)) { @@ -245,17 +249,17 @@ short hor, vert; ShowWindow (_mt_window); /* Start in raw, always flushing mode */ - mustwork (get_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, &flag)); + get_tty_attrib(_mt_window, TTY_ATTRIB_FLAGS, &flag); flag |= TA_ALWAYS_REFRESH | TA_WRAP_AROUND; - mustwork (set_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, flag)); + set_tty_attrib(_mt_window, TTY_ATTRIB_FLAGS, flag); - mustwork (get_tty_attrib (_mt_window, TTY_ATTRIB_CURSOR, &flag)); + get_tty_attrib(_mt_window, TTY_ATTRIB_CURSOR, &flag); flag |= (TA_BLINKING_CURSOR | TA_NL_ADD_CR); - mustwork (set_tty_attrib (_mt_window, TTY_ATTRIB_CURSOR, flag)); + set_tty_attrib(_mt_window, TTY_ATTRIB_CURSOR, flag); - mustwork (set_tty_attrib (_mt_window, TTY_ATTRIB_FOREGROUND, _mt_colors [NO_COLOR] [0])); - mustwork (set_tty_attrib (_mt_window, TTY_ATTRIB_BACKGROUND, _mt_colors [NO_COLOR] [1])); - clear_tty (_mt_window);// + set_tty_attrib(_mt_window, TTY_ATTRIB_FOREGROUND, _mt_colors[NO_COLOR][0]); + set_tty_attrib(_mt_window, TTY_ATTRIB_BACKGROUND, _mt_colors[NO_COLOR][1]); + clear_tty (_mt_window); InitMenuRes (); } @@ -293,7 +297,7 @@ getreturn (char *str) { int has_color (int color) { -#if defined(applec) || defined(__MWERKS__) +#if defined(__SC__) || defined(__MRC__) # pragma unused(color) #endif Rect r; @@ -361,7 +365,7 @@ short err; void term_end_attr (int attr) { -#if defined(applec) || defined(__MWERKS__) +#if defined(__SC__) || defined(__MRC__) # pragma unused (attr) #endif _mt_set_colors (_mt_attrs [0]); @@ -481,15 +485,15 @@ term_start_color (int color) { void -setftty (void) { -long flag; +setftty (void) +{ + long flag; - mustwork (get_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, &flag)); -/* Buffered output in the game */ + /* Buffered output for the game */ + get_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, &flag); flag &= ~ TA_ALWAYS_REFRESH; flag |= TA_INHIBIT_VERT_SCROLL; /* don't scroll */ - mustwork (set_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, flag)); - + set_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, flag); iflags.cbreak = 1; } @@ -508,16 +512,17 @@ gettty (void) { void -settty (const char *str) { -long flag; +settty (const char *str) +{ + long flag; update_tty (_mt_window); - mustwork (get_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, &flag)); -/* Buffered output in the game, raw in "raw" mode */ + /* Buffered output for the game, raw in "raw" mode */ + get_tty_attrib(_mt_window, TTY_ATTRIB_FLAGS, &flag); flag &= ~ TA_INHIBIT_VERT_SCROLL; /* scroll */ flag |= TA_ALWAYS_REFRESH; - mustwork (set_tty_attrib (_mt_window, TTY_ATTRIB_FLAGS, flag)); + set_tty_attrib(_mt_window, TTY_ATTRIB_FLAGS, flag); tty_raw_print ("\n"); if (str) { @@ -528,7 +533,7 @@ long flag; void tty_number_pad (int arg) { -#if defined(applec) || defined(__MWERKS__) +#if defined(__SC__) || defined(__MRC__) # pragma unused(arg) #endif } diff --git a/sys/msdos/Install.dos b/sys/msdos/Install.dos index 6045574..a4ecda7 100644 --- a/sys/msdos/Install.dos +++ b/sys/msdos/Install.dos @@ -1,15 +1,15 @@ - SCCS Id: @(#)Install.dos 3.3 2000/08/02 + SCCS Id: @(#)Install.dos 3.4 2000/08/02 Copyright (c) NetHack PC Development Team 1990-2000. NetHack may be freely redistributed. See license for details. ============================================================== Instructions for compiling and installing - NetHack 3.3 on a DOS system + NetHack 3.4 on a DOS system ====================================================== - (or, How to make PC NetHack 3.3) + (or, How to make PC NetHack 3.4) Last revision: August 2, 2000 -Credit for a runnable full PC NetHack 3.3 goes to the PC Development team +Credit for a runnable full PC NetHack 3.4 goes to the PC Development team of Paul Winner, Kevin Smolkowski, Michael Allison, Yitzhak Sapir, Bill Dyer, Timo Hakulinen, Yamamoto Keizo, Mike Threepoint, Mike Stephenson, Stephen White, Ken Washikita and Janet Walz. The present port is based diff --git a/sys/msdos/Makefile.BC b/sys/msdos/Makefile.BC index 6bd12be..7008160 100644 --- a/sys/msdos/Makefile.BC +++ b/sys/msdos/Makefile.BC @@ -1,9 +1,9 @@ -# SCCS Id: @(#)Makefile.BC 3.3 1999/11/06 -# Copyright (c) Yitzhak Sapir, 1999. +# SCCS Id: @(#)Makefile.BC 3.4 2002/03/17 +# Copyright (c) Yitzhak Sapir, 1999-2002. # NetHack may be freely distributed. See license for details. # -# PC NetHack 3.3 Makefile for Borland C++ 3.1 and 4.5. +# PC NetHack 3.4 Makefile for Borland C++ 3.1 and 4.5. # # Nota Bene: Before you get to here you should have already read # the Install.dos file located in the sys/msdos directory. @@ -23,7 +23,7 @@ # GAME = NetHack -GAMEDIR = c:\games\nethack +GAMEDIR = ..\binary # # @@ -764,7 +764,7 @@ DLBOBJS = $(O)dlb_main.o $(O)dlb.o $(O)alloc.o $(O)panic.o # OBJ01 = $(O)alloc.o $(RANDOM) $(O)decl.o $(O)objects.o \ - $(O)muse.o $(O)display.o $(O)vision.o \ + $(O)muse.o $(O)display.o $(O)vision.o $(O)mapglyph.o \ $(O)rect.o $(O)vis_tab.o $(O)monst.o $(O)wintty.o \ $(O)files.o $(O)sys.o $(O)monstr.o $(O)minion.o \ $(O)worm.o $(O)detect.o $(O)exper.o $(O)mplayer.o \ @@ -1823,6 +1823,7 @@ $(O)exper.o: $(PCHO) $(SRC)\exper.c $(HACK_H) $(O)extralev.o: $(PCHO) $(SRC)\extralev.c $(HACK_H) $(O)files.o: $(PCHO) $(SRC)\files.c $(HACK_H) $(DLB_H) $(O)fountain.o: $(PCHO) $(SRC)\fountain.c $(HACK_H) +$(O)mapglyph.o: $(PCHO) $(SRC)\mapglyph.c $(HACK_H) $(O)minion.o: $(PCHO) $(SRC)\minion.c $(HACK_H) $(EMIN_H) $(EPRI_H) $(O)mklev.o: $(PCHO) $(SRC)\mklev.c $(HACK_H) $(O)mkmap.o: $(PCHO) $(SRC)\mkmap.c $(HACK_H) $(SP_LEV_H) diff --git a/sys/msdos/Makefile.GCC b/sys/msdos/Makefile.GCC index 177e59b..0b1b126 100644 --- a/sys/msdos/Makefile.GCC +++ b/sys/msdos/Makefile.GCC @@ -1,9 +1,9 @@ -# SCCS Id: @(#)Makefile.GCC 3.3 1999/11/06 -# Copyright (c) NetHack PC Development Team 1996. -# PC NetHack 3.3 Makefile for djgpp V2 +# SCCS Id: @(#)Makefile.GCC 3.4 2002/03/17 +# Copyright (c) NetHack PC Development Team 1996-2002. +# PC NetHack 3.4 Makefile for djgpp V2 # # Gnu gcc compiler for msdos (djgpp) -# Requires Gnu Make utility (V3.73 or greater) supplied with djgpp V2 +# Requires Gnu Make utility (V3.79 or greater) supplied with djgpp # # For questions or comments: devteam@nethack.org # @@ -23,7 +23,7 @@ GAME = nethack # The GNU Make has a problem if you include a drive spec below (unfortunately). -GAMEDIR = \games\nethackd +GAMEDIR =..\binary # # Directories, gcc likes unix style directory specs @@ -225,7 +225,7 @@ VOBJ04 = do_wear.o dog.o dogmove.o dokick.o dothrow.o VOBJ05 = drawing.o dungeon.o eat.o end.o engrave.o VOBJ06 = exper.o explode.o extralev.o files.o fountain.o VOBJ07 = getline.o hack.o hacklib.o invent.o lock.o -VOBJ08 = mail.o main.o makemon.o mcastu.o mhitm.o +VOBJ08 = mail.o main.o makemon.o mapglyph.o mcastu.o mhitm.o VOBJ09 = mhitu.o minion.o mkmap.o mklev.o mkmaze.o VOBJ10 = mkobj.o mkroom.o mon.o mondata.o monmove.o VOBJ11 = monst.o monstr.o mplayer.o mthrowu.o muse.o @@ -1069,6 +1069,7 @@ lock.o: $(HACK_H) mail.o: $(HACK_H) $(INCL)\mail.h makemon.o: $(HACK_H) $(EPRI_H) $(EMIN_H) $(INCL)\edog.h mcastu.o: $(HACK_H) +mapglyph.o: $(HACK_H) mhitm.o: $(HACK_H) $(INCL)\artifact.h $(INCL)\edog.h mhitu.o: $(HACK_H) $(INCL)\artifact.h $(INCL)\edog.h minion.o: $(HACK_H) $(EMIN_H) $(EPRI_H) diff --git a/sys/msdos/Makefile.MSC b/sys/msdos/Makefile.MSC index a886bd6..37a6ea3 100644 --- a/sys/msdos/Makefile.MSC +++ b/sys/msdos/Makefile.MSC @@ -1,6 +1,6 @@ -# SCCS Id: @(#)Makefile.MSC 3.3 2000/08/02 -# Copyright (c) NetHack PC Development Team 1997, 2000. -# PC NetHack 3.3 Makefile for MSC +# SCCS Id: @(#)Makefile.MSC 3.4 2002/03/17 +# Copyright (c) NetHack PC Development Team 1997 - 2002. +# PC NetHack 3.4 Makefile for MSC # # For questions or comments: nethack-bugs@nethack.org # @@ -17,7 +17,7 @@ # NOTE: Make sure GAMEDIR exists before make is started. GAME = nethack -GAMEDIR = \games\nethack +GAMEDIR =..\binary # # Directories @@ -64,7 +64,7 @@ LEXYYC = lexyy.c # # Uncomment this line if you want to include support for ALT-numeric # sequences, such as ALT-2 for toggling #twoweapon mode. -# Note that this code did not get a thorough testing prior to 3.3.1 +# Note that this code did not get a thorough testing prior to 3.4.0 #NEWALT=/DNEW_ALT ############################################################################# @@ -205,7 +205,7 @@ VOBJ04 = do_wear.o dog.o dogmove.o dokick.o dothrow.o VOBJ05 = drawing.o dungeon.o eat.o end.o engrave.o VOBJ06 = exper.o explode.o extralev.o files.o fountain.o VOBJ07 = getline.o hack.o hacklib.o invent.o lock.o -VOBJ08 = mail.o main.o makemon.o mcastu.o mhitm.o +VOBJ08 = mail.o main.o makemon.o mapglyph.o mcastu.o mhitm.o VOBJ09 = mhitu.o minion.o mkmap.o mklev.o mkmaze.o VOBJ10 = mkobj.o mkroom.o mon.o mondata.o monmove.o VOBJ11 = monst.o monstr.o mplayer.o mthrowu.o muse.o @@ -471,7 +471,7 @@ envchk: $(GAMEFILE) : $(LNKOPT) $(ALLOBJ) @echo Linking.... - $(LINK) $(LFLAGS) /SE:1000 /DYNAMIC:2120 /NOE /ST:6000 @<<$(GAME).lnk + $(LINK) $(LFLAGS) /SE:1000 /DYNAMIC:2135 /NOE /ST:6000 @<<$(GAME).lnk $(ALLOBJ:^ =+^ ) $(GAMEFILE) @@ -1035,6 +1035,7 @@ lock.o: lock.c $(HACK_H) mail.o: mail.c $(HACK_H) $(INCL)\mail.h makemon.o: makemon.c $(HACK_H) $(INCL)\epri.h $(INCL)\emin.h \ $(INCL)\edog.h +mapglyph.o: mapglyph.c $(HACK_H) mcastu.o: mcastu.c $(HACK_H) mhitm.o: mhitm.c $(HACK_H) $(INCL)\artifact.h $(INCL)\edog.h mhitu.o: mhitu.c $(HACK_H) $(INCL)\artifact.h $(INCL)\edog.h diff --git a/sys/msdos/Makefile.SC b/sys/msdos/Makefile.SC index f83c234..9b1c364 100644 --- a/sys/msdos/Makefile.SC +++ b/sys/msdos/Makefile.SC @@ -1,10 +1,10 @@ -# SCCS Id : @(#)Makefile.SC 3.3 96/10/14 +# SCCS Id : @(#)Makefile.SC 3.4 1996/10/14 # Copyright (c) NetHack Development Team 1996. # # Symantec C compiler V7.2 # Written for Symantec SMAKE utility # -# NOTE: This Makefile has not been tested for NetHack 3.3.0 +# NOTE: This Makefile has not been tested for NetHack 3.4.0 # # For questions or comments : nethack-bugs@linc.cis.upenn.edu # diff --git a/sys/msdos/NHAccess.nh b/sys/msdos/NHAccess.nh index d807563..2fb6731 100644 --- a/sys/msdos/NHAccess.nh +++ b/sys/msdos/NHAccess.nh @@ -1,4 +1,4 @@ -# SCSS Id: @(#)NHAccess.nh 3.3 1999/11/28 +# SCSS Id: @(#)NHAccess.nh 3.4 1999/11/28 # Copyright (c) NetHack PC Development Team 1993, 1996, 1999 # NetHack may be freely redistributed. See license for details. # diff --git a/sys/msdos/compwarn.lst b/sys/msdos/compwarn.lst new file mode 100644 index 0000000..d505213 --- /dev/null +++ b/sys/msdos/compwarn.lst @@ -0,0 +1,16 @@ +/* SCSS Id: @(#)compwarn.lst 3.4 1992/10/08 */ +/* Copyright (c) Paul Winner, 1992 */ +/* NetHack may be freely redistributed. See license for details. */ + +This file contains a list of compiler warnings generated by Microsoft +C version 7.0, compiled with the /W4 switch, and any known reasons for +the warning. You can safely ignore any warning your compile gives if +it appears on this list. + +C4127 (4): Conditional expression is constant + The While(1) statements used in the code cause this warning. + For the sake of making more easily readable code, this is the + preferred construct for NetHack. +C4131 (4): function: uses old-style declarator + In order to make the code as portable as possible, all func- + tions in NetHack use the old-style declarator. diff --git a/sys/msdos/def2mak.c b/sys/msdos/def2mak.c new file mode 100644 index 0000000..1c16ec9 --- /dev/null +++ b/sys/msdos/def2mak.c @@ -0,0 +1,383 @@ +/* SCCS Id: @(#)def2mak.c 3.4 1995/03/19 */ +/* Copyright (c) NetHack PC Development Team, 1994. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "config.h" +#include +#include +#ifndef _MSC_VER +#include +#else +int __cdecl _strcmpi(const char *, const char *); +int __cdecl _stricmp(const char *, const char *); +int __cdecl _strnicmp(const char *, const char *,size_t); +#endif + +#define MALLOC(type) (type *)malloc(sizeof(type)) + +#define MACROID_SIZ 50 +#define MACROVAL_SIZ 300 + +typedef unsigned char bool; + +struct MacroNode * FDECL(AddMacro, (struct MacroNode *, char *, char *)); +char * FDECL(ApplyMacros, (char *, struct MacroNode *)); +struct MacroNode * FDECL(DelMacro, (struct MacroNode *)); +struct MacroNode * FDECL(DelMacroList, (struct MacroNode *)); +void FDECL(COMPILER, (bool, char *, char *, FILE *)); +void FDECL(SaveNewLine, (char *, char *)); +struct ListItem * FDECL(AddItem, (struct ListItem *, char *)); +struct ListItem * FDECL(ReadList, (FILE *, int)); +void FDECL(LINKLIST, (bool, struct ListItem *, char *, char *)); +struct ListTable * FDECL(AddList, (struct ListTable *, struct ListItem *, + char *)); +struct ListItem * FDECL(DelTableList, (struct ListItem *)); +struct ListTable * FDECL(DelTable, (struct ListTable *)); +struct ListItem * FDECL(FindList, (struct ListTable *, char *)); + +#ifdef strcmpi +# undef strcmpi /* don't want to drag in hacklib.c */ +#endif + +#ifdef _MSC_VER +#define stricmp _strcmpi +#define strnicmp _strnicmp +#endif + +int +strcmpi(s1, s2) +char *s1, *s2; +{ + char t1, t2; + + while (*s1 || *s2) { + if (!*s2) return 1; /* s1 > s2 */ + else if (!*s1) return -1; /* s1 < s2 */ + if (isupper(*s1)) t1 = tolower(*s1); else t1 = *s1; + if (isupper(*s2)) t2 = tolower(*s2); else t2 = *s2; + if (t1 != t2) return (t1 > t2) ? 1 : -1; + s1++; s2++; + } + return 0; /* s1 == s2 */ +} + +struct MacroNode { + char Name[MACROID_SIZ]; + char Val[MACROVAL_SIZ]; + struct MacroNode *Next; +}; + +struct MacroNode * +AddMacro (List, MID, MVal) +struct MacroNode *List; +char *MID; +char *MVal; +{ + struct MacroNode *Tmp; + Tmp = MALLOC (struct MacroNode); + strncpy (Tmp->Name, MID, MACROID_SIZ); + strncpy (Tmp->Val, MVal, MACROVAL_SIZ); + Tmp->Next = List; + return Tmp; +} + +char * +ApplyMacros (Line, List) +char *Line; +struct MacroNode *List; +{ + static char TotalLine[MACROVAL_SIZ + 100]; + char TmpLine[MACROVAL_SIZ + 100]; + int AfterLine; + char MacroName[MACROID_SIZ]; + struct MacroNode *TmpList; + + strcpy (TotalLine, ""); + strcpy (TmpLine, Line); + if (sscanf (TmpLine, "%[^?]?[%[^]]]%n", TotalLine, MacroName, + &AfterLine) <= 1) return Line; + for (TmpList = List; TmpList; TmpList = TmpList->Next) + if (!strcmp(TmpList->Name, MacroName)) { + strcat (TotalLine, TmpList->Val); + break; + } + strcat (TotalLine, TmpLine + AfterLine); + return TotalLine; +} + +struct MacroNode * +DelMacro (List) +struct MacroNode *List; +{ + struct MacroNode *tmp; + + tmp = List->Next; + free (List); + return tmp; +} + +struct MacroNode * +DelMacroList (List) +struct MacroNode *List; +{ + while (List != NULL) + List = DelMacro (List); + return List; +} + +void +COMPILER (display, SavedNewLine, EndString, input) +bool display; +char *SavedNewLine; +char *EndString; +FILE *input; +{ + char buffer[100]; + + fgets (buffer, 100, input); + while (strnicmp(buffer, EndString, strlen(EndString))) { + if (display) + SaveNewLine(buffer, SavedNewLine); + fgets (buffer, 100, input); + }; +} + +void +SaveNewLine (Line, NewLine) +char *Line; +char *NewLine; +{ + char tempNewLine[2]; + + strcpy (tempNewLine, ""); + if (Line[strlen(Line)-1] == '\n') { + Line[strlen(Line)-1] = '\0'; + strcpy (tempNewLine, "\n"); + }; + printf ("%s%s", NewLine, Line); + strcpy (NewLine, tempNewLine); +} + +struct ListItem { + char Item[40]; + struct ListItem *next; +}; + +struct ListTable { + char name[40]; + struct ListItem *List; + struct ListTable *next; +}; + +struct ListItem * +AddItem (List, Item) +struct ListItem *List; +char Item[40]; +{ + struct ListItem *temp; + + temp = MALLOC(struct ListItem); + temp->next = List; + strncpy (temp->Item, Item, 39); + return temp; +} + +struct ListItem * +ReadList (input, LinePos) +FILE *input; +int LinePos; +{ + char Item[40]; + char buffer[100]; + struct ListItem *List; + + List = NULL; + fscanf (input, "%39s", Item); + while (strncmp(Item, "?ENDLIST?", 9)) { + if (LinePos > 60) { + LinePos = 18; + printf ("\\\n\t\t"); + } + List = AddItem(List, Item); + printf ("%s ", Item); + LinePos += 1 + strlen(Item); + fscanf (input, "%39s", Item); + } + printf ("\n"); + fgets (buffer, 100, input); + return List; +} + +void +LINKLIST (BC, List, Listname, SavedNewLine) +bool BC; +struct ListItem *List; +char *Listname; +char *SavedNewLine; +{ + int LinePos; + + printf ("%s\t\t", SavedNewLine); + strcpy (SavedNewLine, ""); + + if (!BC) { + printf ("$(%s:^\t=+^\n\t\t)\n", Listname); + return; + }; + + if (List == NULL) return; + + LinePos = 18; + while (List != NULL) { + if (LinePos > 60) { + LinePos = 18; + printf ("+\n\t\t"); + } + printf ("%s ", List->Item); + LinePos += 1 + strlen(List->Item); + List = List->next; + } + printf ("\n"); +} + +struct ListTable * +AddList (Table, List, Name) +struct ListTable *Table; +struct ListItem *List; +char *Name; +{ + struct ListTable *temp; + temp = MALLOC (struct ListTable); + temp->next = Table; + temp->List = List; + strncpy (temp->name, Name, 39); + return temp; +} + +struct ListItem * +DelTableList (List) +struct ListItem *List; +{ + struct ListItem *temp; + + while (List != NULL) { + temp = List->next; + free (List); + List = temp; + }; + return List; +} + +struct ListTable * +DelTable (Table) +struct ListTable *Table; +{ + struct ListTable *temp; + + while (Table != NULL) { + temp = Table->next; + Table->List = DelTableList(Table->List); + free(Table); + Table=temp; + }; + return Table; +} + +struct ListItem * +FindList (Table, Item) +struct ListTable *Table; +char *Item; +{ + while (Table != NULL) { + if (!stricmp(Table->name, Item)) return Table->List; + Table = Table->next; + } + return NULL; +} + +int +main (argc, argv) +int argc; +char *argv[]; +{ + FILE *makfile; + char buffer[100]; + char SavedNewLine[2]; + char Listname[40]; + struct ListTable *Table; + time_t timer; + bool MSC, BC; + struct MacroNode *MacroList = NULL; + char MacroName[MACROID_SIZ]; + char MacroVal[MACROVAL_SIZ]; + + if (argc < 3) { + printf ("Too few arguments. Correct usage is:\n"); + printf ("\t%s {/MSC || /BC} template\n\n", "def2mak"); + printf ("\t{/MSC || /BC} indicate the compiler to use.\n"); + printf ("\ttemplate is the template file to process.\n\n"); + printf ("The output makefile goes to standard output.\n"); + return 1; + }; + Table = NULL; + if (!strcmpi(argv[1], "/MSC") || !strcmpi(argv[1], "-MSC")) { + MSC = TRUE; + BC = FALSE; + } else if (!strcmpi(argv[1], "/BC") || !strcmpi(argv[1], "-BC")) { + MSC = FALSE; + BC = TRUE; + } else { + fprintf (stderr, "Unknown compiler format: %s\n", argv[1]); + return 1; + }; + + strcpy (SavedNewLine, ""); + if ((makfile = fopen (argv[2], "r")) == NULL) + return 2; + COMPILER (0, SavedNewLine, "?BEGIN?", makfile); + while (!feof(makfile)) { + if (fgets(buffer, 100, makfile) == NULL) + break; + if (!strnicmp(buffer, "?SCCS?", 6)) { + time (&timer); + printf ("%s#\tSCCS Id: @(#)Makefile.%s\t3.4\t%02d/%02d/%02d\n", + SavedNewLine, + MSC ? "MSC" : BC ? "BC" : "???", + localtime(&timer)->tm_year, + localtime(&timer)->tm_mon + 1, + localtime(&timer)->tm_mday); + printf ("# Copyright (c) %s, %d.\n", + BC ? "Yitzhak Sapir" : "NetHack PC Development Team", + localtime(&timer)->tm_year + 1900); + printf ("# NetHack may be freely distributed. "); + printf ("See license for details.\n#\n\n"); + strcpy (SavedNewLine, ""); + } else if (MSC ? sscanf (buffer, "?MSCMACRO:%[^=]=%[^?]?", + MacroName, MacroVal) : + BC ? sscanf (buffer, "?BCMACRO:%[^=]=%[^?]?", + MacroName, MacroVal) : 0) + MacroList = AddMacro(MacroList, MacroName, MacroVal); + else if (!strnicmp(buffer, "?BC?", 4)) + COMPILER(BC, SavedNewLine, "?ENDBC?", makfile); + else if (!strnicmp(buffer, "?MSC?", 5)) + COMPILER(MSC, SavedNewLine, "?ENDMSC?", makfile); + else if (!strnicmp(buffer, "?COMMENT?", 9)) + COMPILER(FALSE, SavedNewLine, "?ENDCOMMENT?", makfile); + else if (sscanf(buffer, "?LIST:%[^?]?", Listname) + == 1) { + printf ("%s%s\t=", SavedNewLine, Listname); + Table = AddList (Table, ReadList (makfile, 18), Listname); + strcpy (SavedNewLine, ""); + } else if (sscanf(buffer, "?LINKLIST:%[^?]?", Listname) + == 1) + LINKLIST (BC, FindList(Table, Listname), Listname, + SavedNewLine); + else if (buffer[0] != '?') + SaveNewLine(ApplyMacros(buffer, MacroList), SavedNewLine); + }; + printf ("%s", SavedNewLine); + fclose (makfile); + Table = DelTable(Table); + MacroList = DelMacroList (MacroList); + return 0; +} diff --git a/sys/msdos/genschem.l b/sys/msdos/genschem.l new file mode 100644 index 0000000..75f14b1 --- /dev/null +++ b/sys/msdos/genschem.l @@ -0,0 +1,326 @@ +%{ + +#include "config.h" +#include +#include + +#define MALLOC(type) (type *)malloc(sizeof(type)) + +typedef unsigned char bool; + +struct OvlNode { + char FileName[13]; + char Comment[80]; + int OvlNumber; + struct OvlNode *Next; +}; + +int linenumber = 1; +int OvlNum = -1; +FILE *outf = NULL; +char *ovldesc = NULL; +struct OvlNode *List = NULL; +char *CommentTemplate; + +struct OvlNode * FDECL(AddNode, (struct OvlNode *, struct OvlNode *)); +struct OvlNode * FDECL(DelNode, (struct OvlNode *)); +struct OvlNode * FDECL(ReverseList, (struct OvlNode *)); +struct OvlNode * FDECL(SortList, (struct OvlNode *)); +int NDECL (yylex); + +#ifndef yywrap +int NDECL (yywrap); +#endif + +#ifdef exit +#undef exit +#endif + +%} + +FILECH [A-Za-z0-9_] +FILE {FILECH}{1,8}("."{FILECH}{0,3})? +SCCS [Ss][Cc][Cc][Ss].*\n +COPYR [Cc][Oo][Pp][Yy][Rr][Ii][Gg][Hh][Tt].*\n + +%% + +{SCCS} { linenumber ++; } +{COPYR} { linenumber ++; } +^#.*\n { + if (OvlNum < 0) { + yytext[yyleng - 1] = 0; + fprintf (outf, CommentTemplate, yytext+1); + } + linenumber ++; + } +\n { linenumber ++; } +[ \t]+ ; /* skip trailing tabs & spaces */ +\[.*\] { + yytext[yyleng-1] = 0; /* Discard the trailing \] */ + if (ovldesc) free (ovldesc); + ovldesc = (char *) malloc(strlen(yytext+1)+1); + strcpy(ovldesc, yytext+1); /* Discard the first \[ */ + OvlNum++; + } +{FILE} { + struct OvlNode *Tmp; + + Tmp = MALLOC (struct OvlNode); + strcpy (Tmp->FileName, yytext); + Tmp->OvlNumber = OvlNum; + strncpy (Tmp->Comment, ovldesc, 80); + List = AddNode (List, Tmp); + } +. { + printf ("Line %d: Received character '%c' (%02x)\n", + linenumber, *yytext, *yytext); + } + + +%% + +#ifndef yywrap +int +yywrap() +{ + return 1; +} +#endif + +#if defined(UNIX) || defined(_MSC_VER) +char * +strlwr(s) +char *s; +{ + char *p; + for (p = s; *p; p++) + if (isupper(*p)) *p = tolower(*p); + return s; +} + +char * +strupr(s) +char *s; +{ + char *p; + for (p = s; *p; p++) + if (islower(*p)) *p = toupper(*p); + return s; +} +#endif + +struct OvlNode * +SortList (List) +struct OvlNode *List; +{ + struct OvlNode *List1 = NULL; + struct OvlNode *List2 = NULL; + struct OvlNode *Tmp; + + if (List == NULL) return NULL; + if (List->Next == NULL) return List; + + while (List != NULL) { + if (List != NULL) { + Tmp = List->Next; + List1 = AddNode (List1, List); + List = Tmp; + } + if (List != NULL) { + Tmp = List->Next; + List2 = AddNode (List2, List); + List = Tmp; + } + } + + List1 = SortList (List1); + List2 = SortList (List2); + + while (List1 != NULL || List2 != NULL) { + while (List1 != NULL && List2 == NULL) { + Tmp = List1->Next; + List = AddNode (List, List1); + List1 = Tmp; + } + while (List1 != NULL && + strcmp(List1->FileName, List2->FileName) <= 0) { + Tmp = List1->Next; + List = AddNode (List, List1); + List1 = Tmp; + } + while (List2 != NULL && List1 == NULL) { + Tmp = List2->Next; + List = AddNode (List, List2); + List2 = Tmp; + } + while (List2 != NULL && + strcmp(List1->FileName, List2->FileName) >= 0) { + Tmp = List2->Next; + List = AddNode (List, List2); + List2 = Tmp; + } + } + + return ReverseList (List); +} + +struct OvlNode * +AddNode (List, ToAdd) +struct OvlNode *List; +struct OvlNode *ToAdd; +{ + ToAdd->Next = List; + return ToAdd; +} + +struct OvlNode * +DelNode (List) +struct OvlNode *List; +{ + struct OvlNode *tmp; + + tmp = List->Next; + free (List); + return tmp; +} + +struct OvlNode * +DelOvlList (List) +struct OvlNode *List; +{ + while (List != NULL) + List = DelNode (List); + return List; +} + +struct OvlNode * +ReverseList (List) +struct OvlNode *List; +{ + struct OvlNode *Temp, *Last; + + Last = NULL; Temp = List; + while (Temp) { + Temp = List->Next; + List->Next = Last; + Last = List; + List = Temp; + } + return Last; +} + +/* + * Deletes all nodes with filename equal to that of the first node, except + * for the first node, itself, which it keeps. + */ + +void +DelFile (List) +struct OvlNode *List; +{ + struct OvlNode *tmp; + + tmp = List; + while (tmp->Next != NULL) { + if (!stricmp(List->FileName, tmp->Next->FileName)) + tmp->Next = DelNode (tmp->Next); + else + tmp = tmp->Next; + }; +} + +int +InList (List, ToFind) +struct OvlNode *List; +struct OvlNode *ToFind; +{ + while (List != NULL) { + if (!stricmp(List->FileName, ToFind->FileName)) + return 1; + List = List->Next; + }; + return 0; +} + +int +main (argc, argv) +int argc; +char *argv[]; +{ + bool MSC, BC; + char *Header, *Header2, *Header3, *RootLine, *OvlLine; + char *c; + char FileName[9]; + time_t timer; + struct tm *curtim; + + if (argc < 3) { + + printf ("Too few arguments. Correct usage is:\n"); + printf ("\t%s {/MSC || /BC} schemafile deffile\n\n", "genschem"); + printf ("\t{/MSC || /BC} indicate the compiler to use.\n"); + printf ("\tschemafile is the schema file to process.\n"); + printf ("\tdeffile is the definition file to produce.\n"); + printf ("\t\tif deffile is missing, stdout is assumed.\n\n"); + return 1; + }; + if (!stricmp(argv[1], "/MSC") || !stricmp(argv[1], "-MSC")) { + MSC = TRUE; + BC = FALSE; + } else if (!stricmp(argv[1], "/BC") || !stricmp(argv[1], "-BC")) { + MSC = FALSE; + BC = TRUE; + } else { + fprintf (stderr, "Unknown compiler format: %s\n", argv[1]); + return 1; + }; + + Header = BC ? "/* SCCS Id: @(#)%s\t3.4\t %02d/%02d/%02d */\n" : + "; SCCS Id: @(#)%s\t3.4\t %02d/%02d/%02d\n"; + Header2 = BC ? "/* Copyright (c) Yitzhak Sapir, %d */\n" : + "; Copyright (c) NetHack PC Development Team, %d\n"; + Header3 = BC ? "\n\n" : ";\n\nSEGMENTS\n\n"; + RootLine = BC ? "-zC%s\n" : + "\"%s\" OVL:0\n"; + OvlLine = BC ? + "-zC%s -zAOVLY -zCOVL%d\n" : + "\"%s\" OVL:%d\n"; + CommentTemplate = BC ? "/* %s */\n" : ";%s\n"; + + yyin = fopen (argv[2], "r"); + + if (yyin == NULL) { + fprintf (stderr, "Error: Input file incorrect\n"); + exit (1); + } + + outf = fopen (argv[3], "w"); + + if (outf == NULL) + if (argc == 4) { + fprintf (stderr, "Error: Output file incorrect\n"); + exit (1); + } else outf = stdout; + + time (&timer); + curtim = localtime(&timer); + fprintf (outf, Header, argv[3], curtim->tm_year, curtim->tm_mon + 1, + curtim->tm_mday); + fprintf (outf, Header2, curtim->tm_year +1900); + yylex(); + + fprintf (outf, Header3); + + for (List = SortList (List); List != NULL; List = DelNode (List)) { + if (BC) { + for (c = strlwr(List->FileName); *c; c++) + if (*c == '.') *c = '_'; + } else strupr(List->FileName); + if (List->OvlNumber) + fprintf (outf, OvlLine, List->FileName, List->OvlNumber); + else fprintf (outf, RootLine, List->FileName, List->FileName); + } + fclose (outf); + +} diff --git a/sys/msdos/msdos.c b/sys/msdos/msdos.c index 0ed9eab..c43af3b 100644 --- a/sys/msdos/msdos.c +++ b/sys/msdos/msdos.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)msdos.c 3.3 2000/07/30 */ +/* SCCS Id: @(#)msdos.c 3.4 2000/07/30 */ /* Copyright (c) NetHack PC Development Team 1990, 1991, 1992, 1993, 1994 */ /* NetHack may be freely redistributed. See license for details. */ @@ -43,7 +43,7 @@ */ #define READCHAR 0x00 /* Read Character from Keyboard */ #define GETKEYFLAGS 0x02 /* Get Keyboard Flags */ -/*#define KEY_DEBUG /* print values of unexpected key codes - devel*/ +/*#define KEY_DEBUG */ /* print values of unexpected key codes - devel*/ void FDECL(get_cursor,(int *, int *)); @@ -53,7 +53,9 @@ void FDECL(get_cursor,(int *, int *)); static char NDECL(DOSgetch); static char NDECL(BIOSgetch); +#ifndef __GO32__ static char * NDECL(getdta); +#endif static unsigned int FDECL(dos_ioctl, (int,int,unsigned)); #ifdef USE_TILES extern boolean FDECL(pckeys,(unsigned char, unsigned char)); /* pckeys.c */ diff --git a/sys/msdos/msdoshlp.txt b/sys/msdos/msdoshlp.txt index 4a36b94..ee94464 100644 --- a/sys/msdos/msdoshlp.txt +++ b/sys/msdos/msdoshlp.txt @@ -1,4 +1,4 @@ - MSDOS specific help file for NetHack 3.3.0 + MSDOS specific help file for NetHack 3.4.0 (Last Revision: December 4, 1999) Copyright (c) NetHack PC Development Team 1993-1999. diff --git a/sys/msdos/ovlinit.c b/sys/msdos/ovlinit.c index 0350764..fc0ff22 100644 --- a/sys/msdos/ovlinit.c +++ b/sys/msdos/ovlinit.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)ovlinit.c 3.3 94/03/20 */ +/* SCCS Id: @(#)ovlinit.c 3.4 1994/03/20 */ /* Copyright (c) NetHack PC Development Team 1995 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/msdos/pckeys.c b/sys/msdos/pckeys.c index d9c8c70..d2783b4 100644 --- a/sys/msdos/pckeys.c +++ b/sys/msdos/pckeys.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pckeys.c 3.3 96/05/11 */ +/* SCCS Id: @(#)pckeys.c 3.4 1996/05/11 */ /* Copyright (c) NetHack PC Development Team 1996 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/msdos/pctiles.c b/sys/msdos/pctiles.c index 8604201..66a6587 100644 --- a/sys/msdos/pctiles.c +++ b/sys/msdos/pctiles.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pctiles.c 3.3 95/07/31 */ +/* SCCS Id: @(#)pctiles.c 3.4 1995/07/31 */ /* Copyright (c) NetHack PC Development Team 1993, 1994 */ /* NetHack may be freely redistributed. See license for details. */ /* */ @@ -90,7 +90,6 @@ OpenTileFile(tilefilename, filestyle) char *tilefilename; boolean filestyle; { - FILE *x; #ifdef TILES_IN_RAM int k; #endif diff --git a/sys/msdos/pctiles.h b/sys/msdos/pctiles.h index 3b97a2d..1750592 100644 --- a/sys/msdos/pctiles.h +++ b/sys/msdos/pctiles.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pctiles.h 3.3 94/04/04 */ +/* SCCS Id: @(#)pctiles.h 3.4 1994/04/04 */ /* Copyright (c) NetHack PC Development Team 1993, 1994 */ /* NetHack may be freely redistributed. See license for details. */ /* */ diff --git a/sys/msdos/pcvideo.h b/sys/msdos/pcvideo.h index dcb08c2..41d3061 100644 --- a/sys/msdos/pcvideo.h +++ b/sys/msdos/pcvideo.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pcvideo.h 3.3 94/06/07 */ +/* SCCS Id: @(#)pcvideo.h 3.4 1994/06/07 */ /* Copyright (c) NetHack PC Development Team 1993, 1994 */ /* NetHack may be freely redistributed. See license for details. */ /* */ @@ -269,7 +269,7 @@ E void FDECL(vga_WriteChar, (int, int, int, int)); E void FDECL(vga_WriteStr, (char *, int, int, int, int)); E void FDECL(vga_xputs, (const char *, int, int)); E void FDECL(vga_xputc, (CHAR_P, int)); -E void FDECL(vga_xputg, (int, int)); +E void FDECL(vga_xputg, (int, int, unsigned)); E void FDECL(vga_userpan, (BOOLEAN_P)); E void FDECL(vga_overview, (BOOLEAN_P)); E void FDECL(vga_traditional, (BOOLEAN_P)); diff --git a/sys/msdos/portio.h b/sys/msdos/portio.h index 5435656..c1d64de 100644 --- a/sys/msdos/portio.h +++ b/sys/msdos/portio.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)portio.h 3.3 95/08/05 */ +/* SCCS Id: @(#)portio.h 3.4 1995/08/05 */ /* Copyright (c) NetHack PC Development Team 1995 */ /* NetHack may be freely redistributed. See license for details. */ /* */ diff --git a/sys/msdos/prebuild.mak b/sys/msdos/prebuild.mak new file mode 100644 index 0000000..2433bdc --- /dev/null +++ b/sys/msdos/prebuild.mak @@ -0,0 +1,67 @@ +# SCCS Id: @(#)prebuild.mak 3.4 1997/09/28 +# +# Makefile for building the genschem utility, the .def files and +# the Makefiles for distribution. +# + +NHINCL =..\..\include + +! IF "$(MAKE)"=="NMAKE" +CC =cl +MODEL =L +CEXENAM =/Fe # name the .EXE file +CFLAGS =/A$(MODEL) /Zp1 /nologo /F 1400 /D__STDC__ /I$(NHINCL) +! ELSE # Assume Borland +CC =bcc # TARGSTRING +MODEL =h +BCTOP =c:\borlandc # main Borland C directory +BCINCL =$(BCTOP)\include # include directory for main BC headers +CEXENAM =-e # name the .EXE file +CFLAGS =-I$(BCINCL) -I$(NHINCL) -m$(MODEL) -DSTRNCMPI +! ENDIF + +LEX = flex +#LEX = flex -Sc:\tools16\flex.ske +# LEX = lex + +# these are the names of the output files from LEX. Under MS-DOS +# and similar systems, they may differ +LEXYYC = lex.yy.c +#LEXYYC = lexyy.c + + +SCHEMAS = schema1.BC schema2.BC +MAKES = Makefile.BC + +all: $(SCHEMAS) + +genschem.exe: genschem.c + $(CC) $(CFLAGS) $(CEXENAM)$@ genschem.c + +genschem.c: genschem.l + $(LEX) $(FLEXSKEL) genschem.l + copy $(LEXYYC) $@ + @del $(LEXYYC) + +schema1.BC: genschem.exe schema1 + genschem /BC schema1 schema1.BC +schema2.BC: genschem.exe schema2 + genschem /BC schema2 schema2.BC +# +# NOTE: MSC no longer uses these overlay definitions +# since switching to the use of packaged functions +# +#schema1.MSC: genschem.exe schema1 +# genschem /MSC schema1 schema1.MSC +#schema2.MSC: genschem.exe schema2 +# genschem /MSC schema2 schema2.MSC +#schema3.MSC: genschem.exe schema3 +# genschem /MSC schema3 schema3.MSC + +def2mak.exe: def2mak.c + $(CC) $(CFLAGS) $(CEXENAM)$@ def2mak.c + +#Makefile.BC: def2mak.exe template.mak +# def2mak /BC template.mak >Makefile.BC +#Makefile.MSC: def2mak.exe template.mak +# def2mak /MSC template.mak >Makefile.MSC diff --git a/sys/msdos/schema1 b/sys/msdos/schema1 new file mode 100644 index 0000000..cafe18f --- /dev/null +++ b/sys/msdos/schema1 @@ -0,0 +1,606 @@ +SCCS Id: @(#)schema1 3.3 95/10/25 +Copyright (c) NetHack PC Development Team 1993, 1994, 1995 +# +# NetHack Overlay Schema +# Minimal extended memory available, lots of 640K base RAM free +# Overlay buffer size will be (20 + 20 + 19) = 59K (sum of 3 largest overlays). +# Requires about 490K (for exe load plus overlay buffer), but +# an additional 70K free (minimum) will be needed for malloc calls, +# bringing the total requirement to about 560K. +# Optimized for minimal overlay turns. +# + +[ root ] +pcmain.0 sound.o tile.o pctiles.0 pctiles.b +vidvga.1 vidvga.0 vidvga.b video.0 video.1 video.b +hack.3 vidtxt.0 vidtxt.b botl.0 monmove.0 display.o +dungeon.0 hacklib.0 wintty.o trap.0 attrib.0 detect.o +mon.0 cmd.0 vision.o hack.1 msdos.0 pckeys.o +random.o rnd.0 alloc.o ovlinit.o +dbridge.0 monmove.1 engrave.0 invent.0 +monmove.2 mondata.0 +hacklib.1 hacklib.2 +dogmove.b + +[ ] +allmain.0 + +[ ] +allmain.1 + +[ ] +allmain.b + +[ ] +apply.0 + +[ ] +apply.1 + +[ ] +apply.b + +[ ] +artifact.0 + +[ ] +artifact.1 + +[ ] +artifact.b + +[ ] +attrib.1 + +[ ] +attrib.2 + +[ ] +attrib.b + +[ ] +ball.o + +[ ] +bones.o + +[ ] +botl.1 + +[ ] +botl.b + +[ ] +cmd.1 + +[ ] +cmd.b + +[ ] +dbridge.1 + +[ ] +dbridge.b + +[ ] +decl.o + +[ ] +dig.o + +[ ] +dlb.o + +[ ] +do.0 + +[ ] +do.1 + +[ ] +do.2 + +[ ] +do.3 + +[ ] +do.b + +[ ] +do_name.0 + +[ ] +do_name.2 + +[ ] +do_name.b + +[ ] +do_wear.0 + +[ ] +do_wear.1 + +[ ] +do_wear.2 + +[ ] +do_wear.b + +[ ] +dog.1 + +[ ] +dog.2 + +[ ] +dog.b + +[ ] +dogmove.0 + +[ ] +dokick.o + +[ ] +dothrow.o + +[ ] +drawing.o + +[ ] +dungeon.1 + +[ ] +eat.0 + +[ ] +eat.1 + +[ ] +eat.b + +[ ] +end.o + +[ ] +engrave.1 + +[ ] +engrave.2 + +[ ] +engrave.b + +[ ] +exper.o + +[ ] +explode.0 + +[ ] +explode.1 + +[ ] +extralev.o + +[ ] +files.o + +[ ] +fountain.o + +[ ] +getline.1 + +[ ] +getline.2 + +[ ] +hack.2 + +[ ] +hack.b + +[ ] +hacklib.b + +[ ] +invent.1 + +[ ] +invent.2 + +[ ] +invent.3 + +[ ] +invent.b + +[ ] +light.3 + +[ ] +lock.0 + +[ ] +lock.b mail.0 + +[ ] +mail.b + +[ ] +makemon.0 + +[ ] +makemon.1 + +[ ] +makemon.2 + +[ ] +makemon.b + +[ ] +mcastu.0 + +[ ] +mcastu.b + +[ ] +mhitm.0 + +[ ] +mhitm.b + +[ ] +mhitu.0 + +[ ] +mhitu.1 + +[ ] +mhitu.b + +[ ] +minion.o + +[ ] +mklev.o + +[ ] +mkmap.o + +[ ] +mkmaze.o + +[ ] +mkobj.0 + +[ ] +mkobj.1 + +[ ] +mkobj.b + +[ ] +mkroom.0 + +[ ] +mkroom.b + +[ ] +mon.1 + +[ ] +mon.2 + +[ ] +mon.b + +[ ] +mondata.1 + +[ ] +mondata.2 + +[ ] +mondata.b + +[ ] +monmove.b + +[ ] +monst.o + +[ ] +monstr.o + +[ ] +mplayer.o + +[ ] +msdos.b + +[ ] +mthrowu.0 + +[ ] +mthrowu.1 + +[ ] +mthrowu.b + +[ ] +muse.o + +[ ] +music.o + +[ ] +o_init.o + +[ ] +objects.o + +[ ] +objnam.0 + +[ ] +objnam.1 + +[ ] +objnam.b + +[ ] +options.o + +[ ] +pager.o + +[ ] +pcmain.1 role.o + +[ ] +pcmain.b + +[ ] +pcunix.b + +[ ] +pickup.o + +[ ] +pline.b + +[ ] +polyself.0 + +[ ] +polyself.1 + +[ ] +polyself.b + +[ ] +potion.b + +[ ] +pray.o + +[ ] +priest.0 + +[ ] +priest.b + +[ ] +quest.o + +[ ] +questpgr.o + +[ ] +read.b + +[ ] +rect.o + +[ ] +region.o + +[ ] +restore.o + +[ ] +rip.o + +[ ] +rnd.1 + +[ ] +rnd.b + +[ ] +rumors.o + +[ ] +save.o + +[ ] +shk.0 + +[ ] +shk.1 + +[ ] +shk.2 + +[ ] +shk.3 + +[ ] +shk.b + +[ ] +shknam.0 + +[ ] +shknam.b + +[ ] +sit.o + +[ ] +sounds.0 + +[ ] +sounds.b + +[ ] +sp_lev.o + +[ ] +spell.o + +[ ] +steal.0 + +[ ] +steal.1 + +[ ] +steal.b + +[ ] +sys.o + +[ ] +teleport.o + +[ ] +termcap.0 + +[ ] +termcap.1 + +[ ] +termcap.b + +[ ] +timeout.0 + +[ ] +timeout.1 + +[ ] +timeout.b + +[ ] +topl.1 + +[ ] +topl.2 + +[ ] +topl.b + +[ ] +topten.o + +[ ] +track.0 + +[ ] +track.1 + +[ ] +track.b + +[ ] +trap.1 + +[ ] +trap.2 + +[ ] +trap.3 + +[ ] +trap.b + +[ ] +tty.o + +[ ] +u_init.o + +[ ] +uhitm.o + +[ ] +vault.0 + +[ ] +vault.b + +[ ] +version.o + +[ ] +vidvga.2 + +[ ] +vis_tab.o + +[ ] +weapon.0 + +[ ] +weapon.1 + +[ ] +weapon.b + +[ ] +were.0 + +[ ] +were.b + +[ ] +wield.o + +[ ] +windows.o + +[ ] +wizard.0 + +[ ] +wizard.b + +[ ] +worm.o + +[ ] +steed.o worn.o + +[ ] +write.o + +[ ] +zap.0 + +[ ] +zap.1 + +[ ] +zap.2 + +[ ] +zap.3 + +[ ] +zap.b + diff --git a/sys/msdos/schema1.BC b/sys/msdos/schema1.BC index 66d0e13..3f51531 100644 --- a/sys/msdos/schema1.BC +++ b/sys/msdos/schema1.BC @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)schema1.BC 3.3 99/10/28 */ +/* SCCS Id: @(#)schema1.BC 3.4 1999/10/28 */ /* Copyright (c) Yitzhak Sapir, 1999 */ /* */ /* NetHack Overlay Schema */ diff --git a/sys/msdos/schema2 b/sys/msdos/schema2 new file mode 100644 index 0000000..33616f3 --- /dev/null +++ b/sys/msdos/schema2 @@ -0,0 +1,669 @@ +SCCS Id: @(#)schema2 3.3 95/10/25 +Copyright (c) NetHack PC Development Team 1993, 1994, 1995 +# +# NetHack Overlay Schema +# Small Root footprint, with extended memory available for caching. +# Almost everything is overlaid. +# + +[ root ] +pcmain.0 sound.o tile.o pctiles.0 pctiles.b +vidvga.1 vidvga.0 vidvga.b video.0 video.1 video.b +hack.3 vidtxt.0 vidtxt.b alloc.o ovlinit.o + +[ ] +allmain.0 + +[ ] +allmain.1 + +[ ] +allmain.b + +[ ] +apply.0 + +[ ] +apply.1 + +[ ] +apply.b + +[ ] +artifact.0 + +[ ] +artifact.1 + +[ ] +artifact.b + +[ ] +attrib.0 + +[ ] +attrib.1 + +[ ] +attrib.2 + +[ ] +attrib.b + +[ ] +ball.o + +[ ] +bones.o + +[ ] +botl.0 + +[ ] +botl.1 + +[ ] +botl.b + +[ ] +cmd.0 + +[ ] +cmd.1 + +[ ] +cmd.b + +[ ] +dbridge.0 + +[ ] +dbridge.1 + +[ ] +dbridge.b + +[ ] +decl.o + +[ ] +detect.o + +[ ] +dig.o + +[ ] +display.o + +[ ] +dlb.o + +[ ] +do.0 + +[ ] +do.1 + +[ ] +do.2 + +[ ] +do.3 + +[ ] +do.b + +[ ] +do_name.0 + +[ ] +do_name.2 + +[ ] +do_name.b + +[ ] +do_wear.0 + +[ ] +do_wear.1 + +[ ] +do_wear.2 + +[ ] +do_wear.b + +[ ] +dog.1 + +[ ] +dog.2 + +[ ] +dog.b + +[ ] +dogmove.0 + +[ ] +dogmove.b + +[ ] +dokick.o + +[ ] +dothrow.o + +[ ] +drawing.o + +[ ] +dungeon.0 + +[ ] +dungeon.1 + +[ ] +eat.0 + +[ ] +eat.1 + +[ ] +eat.b + +[ ] +end.o + +[ ] +engrave.0 + +[ ] +engrave.1 + +[ ] +engrave.2 + +[ ] +engrave.b + +[ ] +exper.o + +[ ] +explode.0 + +[ ] +explode.1 + +[ ] +extralev.o + +[ ] +files.o + +[ ] +fountain.o + +[ ] +getline.1 + +[ ] +getline.2 + +[ ] +hack.1 + +[ ] +hack.2 + +[ ] +hack.b + +[ ] +hacklib.0 + +[ ] +hacklib.1 + +[ ] +hacklib.2 + +[ ] +hacklib.b + +[ ] +invent.0 + +[ ] +invent.1 + +[ ] +invent.2 + +[ ] +invent.3 + +[ ] +invent.b + +[ ] +light.3 + +[ ] +lock.0 + +[ ] +lock.b mail.0 + +[ ] +mail.b + +[ ] +makemon.0 + +[ ] +makemon.1 + +[ ] +makemon.2 + +[ ] +makemon.b + +[ ] +mcastu.0 + +[ ] +mcastu.b + +[ ] +mhitm.0 + +[ ] +mhitm.b + +[ ] +mhitu.0 + +[ ] +mhitu.1 + +[ ] +mhitu.b + +[ ] +minion.o + +[ ] +mklev.o + +[ ] +mkmap.o + +[ ] +mkmaze.o + +[ ] +mkobj.0 + +[ ] +mkobj.1 + +[ ] +mkobj.b + +[ ] +mkroom.0 + +[ ] +mkroom.b + +[ ] +mon.0 + +[ ] +mon.1 + +[ ] +mon.2 + +[ ] +mon.b + +[ ] +mondata.0 + +[ ] +mondata.1 + +[ ] +mondata.2 + +[ ] +mondata.b + +[ ] +monmove.0 + +[ ] +monmove.1 + +[ ] +monmove.2 + +[ ] +monmove.b + +[ ] +monst.o + +[ ] +monstr.o + +[ ] +mplayer.o + +[ ] +msdos.0 pckeys.o + +[ ] +msdos.b + +[ ] +mthrowu.0 + +[ ] +mthrowu.1 + +[ ] +mthrowu.b + +[ ] +muse.o + +[ ] +music.o + +[ ] +o_init.o + +[ ] +objects.o + +[ ] +objnam.0 + +[ ] +objnam.1 + +[ ] +objnam.b + +[ ] +options.o + +[ ] +pager.o + +[ ] +pcmain.1 role.o + +[ ] +pcmain.b + +[ ] +pcunix.b + +[ ] +pickup.o + +[ ] +pline.b + +[ ] +polyself.0 + +[ ] +polyself.1 + +[ ] +polyself.b + +[ ] +potion.b + +[ ] +pray.o + +[ ] +priest.0 + +[ ] +priest.b + +[ ] +quest.o + +[ ] +questpgr.o + +[ ] +random.o + +[ ] +read.b + +[ ] +rect.o + +[ ] +region.o + +[ ] +restore.o + +[ ] +rip.o + +[ ] +rnd.0 + +[ ] +rnd.1 + +[ ] +rnd.b + +[ ] +rumors.o + +[ ] +save.o + +[ ] +shk.0 + +[ ] +shk.1 + +[ ] +shk.2 + +[ ] +shk.3 + +[ ] +shk.b + +[ ] +shknam.0 + +[ ] +shknam.b + +[ ] +sit.o + +[ ] +sounds.0 + +[ ] +sounds.b + +[ ] +sp_lev.o + +[ ] +spell.o + +[ ] +steal.0 + +[ ] +steal.1 + +[ ] +steal.b + +[ ] +steed.o worn.o + +[ ] +sys.o + +[ ] +teleport.o + +[ ] +termcap.0 + +[ ] +termcap.1 + +[ ] +termcap.b + +[ ] +timeout.0 + +[ ] +timeout.1 + +[ ] +timeout.b + +[ ] +topl.1 + +[ ] +topl.2 + +[ ] +topl.b + +[ ] +topten.o + +[ ] +track.0 + +[ ] +track.1 + +[ ] +track.b + +[ ] +trap.0 + +[ ] +trap.1 + +[ ] +trap.2 + +[ ] +trap.3 + +[ ] +trap.b + +[ ] +tty.o + +[ ] +u_init.o + +[ ] +uhitm.o + +[ ] +vault.0 + +[ ] +vault.b + +[ ] +version.o + +[ ] +vidvga.2 + +[ ] +vis_tab.o + +[ ] +vision.o + +[ ] +weapon.0 + +[ ] +weapon.1 + +[ ] +weapon.b + +[ ] +were.0 + +[ ] +were.b + +[ ] +wield.o + +[ ] +windows.o + +[ ] +wintty.o + +[ ] +wizard.0 + +[ ] +wizard.b + +[ ] +worm.o + +[ ] +write.o + +[ ] +zap.0 + +[ ] +zap.1 + +[ ] +zap.2 + +[ ] +zap.3 + +[ ] +zap.b diff --git a/sys/msdos/schema2.BC b/sys/msdos/schema2.BC index 5005a5b..3d15f5c 100644 --- a/sys/msdos/schema2.BC +++ b/sys/msdos/schema2.BC @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)schema2.BC 3.3 99/10/28 */ +/* SCCS Id: @(#)schema2.BC 3.4 1999/10/28 */ /* Copyright (c) Yitzhak Sapir, 1999 */ /* */ /* NetHack Overlay Schema */ diff --git a/sys/msdos/schema3 b/sys/msdos/schema3 new file mode 100644 index 0000000..d5254c9 --- /dev/null +++ b/sys/msdos/schema3 @@ -0,0 +1,600 @@ +SCCS Id: @(#)schema3 3.3 95/10/25 +Copyright (c) NetHack PC Development Team 1993, 1994, 1995 +# +# NetHack Overlay Schema +# Minimal extended memory available, lots of 640K base RAM free +# This schema is for use with a patched moveinit.c (see Makefile +# or Install.dos for information. +# + +[ root ] +pcmain.0 sound.o tile.o pctiles.0 pctiles.b +vidvga.1 vidvga.0 vidvga.b video.0 video.1 video.b +hack.3 vidtxt.0 vidtxt.b botl.0 monmove.0 display.o +dungeon.0 hacklib.0 wintty.o trap.0 attrib.0 detect.o +mon.0 cmd.0 vision.o hack.1 msdos.0 +random.o rnd.0 alloc.o +dbridge.0 monmove.1 engrave.0 invent.0 +monmove.2 mondata.0 +hacklib.1 hacklib.2 +dogmove.b + +[ ] +allmain.0 + +[ ] +allmain.1 + +[ ] +allmain.b + +[ ] +apply.0 + +[ ] +apply.1 + +[ ] +apply.b + +[ ] +artifact.0 + +[ ] +artifact.1 + +[ ] +artifact.b + +[ ] +attrib.1 + +[ ] +attrib.2 + +[ ] +attrib.b + +[ ] +ball.o + +[ ] +bones.o + +[ ] +botl.1 + +[ ] +botl.b + +[ ] +cmd.1 + +[ ] +cmd.b + +[ ] +dbridge.1 + +[ ] +dbridge.b + +[ ] +decl.o + +[ ] +dig.o + +[ ] +dlb.o + +[ ] +do.0 + +[ ] +do.1 + +[ ] +do.2 + +[ ] +do.3 + +[ ] +do.b + +[ ] +do_name.0 + +[ ] +do_name.2 + +[ ] +do_name.b + +[ ] +do_wear.0 + +[ ] +do_wear.1 + +[ ] +do_wear.2 + +[ ] +do_wear.b + +[ ] +dog.1 + +[ ] +dog.2 + +[ ] +dog.b + +[ ] +dogmove.0 + +[ ] +dokick.o + +[ ] +dothrow.o + +[ ] +drawing.o + +[ ] +dungeon.1 + +[ ] +eat.0 + +[ ] +eat.1 + +[ ] +eat.b + +[ ] +end.o + +[ ] +engrave.1 + +[ ] +engrave.2 + +[ ] +engrave.b + +[ ] +exper.o + +[ ] +explode.0 + +[ ] +explode.1 + +[ ] +extralev.o + +[ ] +files.o + +[ ] +fountain.o + +[ ] +getline.1 + +[ ] +getline.2 + +[ ] +hack.2 + +[ ] +hack.b + +[ ] +hacklib.b + +[ ] +invent.1 + +[ ] +invent.2 + +[ ] +invent.3 + +[ ] +invent.b + +[ ] +light.3 + +[ ] +lock.0 + +[ ] +lock.b mail.0 + +[ ] +mail.b + +[ ] +makemon.0 + +[ ] +makemon.1 + +[ ] +makemon.2 + +[ ] +makemon.b + +[ ] +mcastu.0 + +[ ] +mcastu.b + +[ ] +mhitm.0 + +[ ] +mhitm.b + +[ ] +mhitu.0 + +[ ] +mhitu.1 + +[ ] +mhitu.b + +[ ] +minion.o + +[ ] +mklev.o + +[ ] +mkmap.o + +[ ] +mkmaze.o + +[ ] +mkobj.0 + +[ ] +mkobj.1 + +[ ] +mkobj.b + +[ ] +mkroom.0 + +[ ] +mkroom.b + +[ ] +mon.1 + +[ ] +mon.2 + +[ ] +mon.b + +[ ] +mondata.1 + +[ ] +mondata.2 + +[ ] +mondata.b + +[ ] +monmove.b + +[ ] +monst.o + +[ ] +monstr.o + +[ ] +mplayer.o + +[ ] +msdos.b + +[ ] +mthrowu.0 + +[ ] +mthrowu.1 + +[ ] +mthrowu.b + +[ ] +muse.o + +[ ] +music.o + +[ ] +o_init.o + +[ ] +objects.o + +[ ] +objnam.0 + +[ ] +objnam.1 + +[ ] +objnam.b + +[ ] +options.o + +[ ] +pager.o + +[ ] +pcmain.1 + +[ ] +pcmain.b + +[ ] +pcunix.b + +[ ] +pickup.o + +[ ] +pline.b + +[ ] +polyself.0 + +[ ] +polyself.1 + +[ ] +polyself.b + +[ ] +potion.b + +[ ] +pray.o + +[ ] +priest.0 + +[ ] +priest.b + +[ ] +quest.o + +[ ] +questpgr.o + +[ ] +read.b + +[ ] +rect.o + +[ ] +restore.o + +[ ] +rip.o + +[ ] +rnd.1 + +[ ] +rnd.b + +[ ] +rumors.o + +[ ] +save.o + +[ ] +shk.0 + +[ ] +shk.1 + +[ ] +shk.2 + +[ ] +shk.3 + +[ ] +shk.b + +[ ] +shknam.0 + +[ ] +shknam.b + +[ ] +sit.o + +[ ] +sounds.0 + +[ ] +sounds.b + +[ ] +sp_lev.o + +[ ] +spell.o + +[ ] +steal.0 + +[ ] +steal.1 + +[ ] +steal.b + +[ ] +sys.o + +[ ] +teleport.o + +[ ] +termcap.0 + +[ ] +termcap.1 + +[ ] +termcap.b + +[ ] +timeout.0 + +[ ] +timeout.1 + +[ ] +timeout.b + +[ ] +topl.1 + +[ ] +topl.2 + +[ ] +topl.b + +[ ] +topten.o + +[ ] +track.0 + +[ ] +track.1 + +[ ] +track.b + +[ ] +trap.1 + +[ ] +trap.2 + +[ ] +trap.3 + +[ ] +trap.b + +[ ] +tty.o + +[ ] +u_init.o + +[ ] +uhitm.o + +[ ] +vault.0 + +[ ] +vault.b + +[ ] +version.o + +[ ] +vidvga.2 + +[ ] +vis_tab.o + +[ ] +weapon.0 + +[ ] +weapon.1 + +[ ] +weapon.b + +[ ] +were.0 + +[ ] +were.b + +[ ] +wield.o + +[ ] +windows.o + +[ ] +wizard.0 + +[ ] +wizard.b + +[ ] +worm.o + +[ ] +worn.o + +[ ] +write.o + +[ ] +zap.0 + +[ ] +zap.1 + +[ ] +zap.2 + +[ ] +zap.3 + +[ ] +zap.b + diff --git a/sys/msdos/schema3.MSC b/sys/msdos/schema3.MSC index a414634..0359bdc 100644 --- a/sys/msdos/schema3.MSC +++ b/sys/msdos/schema3.MSC @@ -1,4 +1,4 @@ -; SCCS Id: @(#)schema3.MSC 3.3 2000/07/31 +; SCCS Id: @(#)schema3.MSC 3.4 2000/07/31 ; Copyright (c) NetHack PC Development Team, 2000 ; ; NetHack Overlay Schema @@ -19,19 +19,20 @@ functions:0 _is_swallow_sym _check_here _check_leash _check_map_spot _check_pos functions:0 _monsndx _m_move _lcase _tty_create_nhwindow _tty_delay_output _tty_destroy_nhwindow functions:0 _tty_dismiss_nhwindow _gender _genl_outrip _get_cost _get_free_room_loc _get_level functions:0 _get_location _get_map _get_mleash +; functions:1 _move_update _movebubbles _movecmd _movemon _moverock _movobj _mpickgold -functions:1 _doaltarobj _doapply _dobreathe _docall _docast -functions:1 _display_artifact_score _display_warning _dlb_fgetc _doattributes _dochug _dochugw -functions:1 _fill_point _fill_room _fill_zoo _fillholetyp _find_ac _find_branch _find_branch_room _find_defensive +functions:1 _doaltarobj _doapply _dobreathe _docall _docast ; functions:2 _do_vicinity_map functions:3 _pcmain +functions:4 _spell_let_to_idx _cursed_book _deadbook _learn _getspell _spelltypemnemonic +functions:5 _dospellmenu _percent_success _throwspell _cast_protection _isqrt ; functions:6 _a_gname _a_gname_at _a_monnam _abon _abuse_dog _accessible _activate_statue_trap functions:7 _add_branch _add_damage _add_debug_extended_commands _add_door _add_id_mapping _add_level functions:8 _add_menu_cmd_alias _add_one_tobill _add_rect _add_room _add_subroom _add_to_billobjs _add_to_buried _add_to_container functions:9 _add_to_migration _add_to_minv _add_valid_menu_class _add_weapon_skill _addinv _addtobill _addtopl _addupbill -functions:10 _Adjmonnam +functions:10 _Adjmonnam functions:11 _align_gname functions:12 _altar_wrath _Amonnam _amulet _Amulet_off _Amulet_on _An _an _angry_guards functions:13 _angry_priest _angry_shk_exists _any_light_source _aobjnam _append_slash _append_str _Armor_gone _Armor_off @@ -82,7 +83,7 @@ functions:57 _do_earthquake _do_entity _do_genocide _do_improvisation _do_light_ functions:57 _vga_xputg _vga_xputs _video_update_positionbar _view_from _view_init _visctrl _vision_init _vision_recalc functions:58 _do_oname _do_osshock _do_play_instrument _do_reset_eat _do_room_or_subroom _do_storms _do_takeoff functions:60 _doclose _doconfuse _doconsult _docorner _docrt _doddoremarm _doddrop _dodip -;functions:61 +functions:61 _adjust_prefix _build_plselection_prompt _duplicate_opt_detection _enter_explore_mode _maybe_wail functions:62 _doextcmd _doextlist _doextversion _dofindgem _dofiretrap _doforce _dog_eat _dog_goal functions:63 _dog_hunger _dog_invent _dog_move _dog_nutrition _dogfood _dogushforth _dohelp _dohide functions:64 _dohistory _doidtrap _doinvbill _doinvoke _dojump _dokick _dolook _doloot @@ -106,7 +107,7 @@ functions:80 _end_engulf functions:82 _exclam _exepath _exerchk _exercise _exerper _exist_artifact _expels _experience functions:83 _explmm _explmu _explode _explum _expulsion _ext_cmd_getlin_hook _extend_spine _extract_nexthere functions:84 _extract_nobj _fall_asleep _fall_through _feel_cockatrice _feel_location _fightm _filesize_nh _fill_pit -;functions:85 +functions:85 _nh_getenv _promptsep _rigid_role_checks _set_duplicate_opt_detection _tool_in_use functions:86 _find_drawbridge _find_hell _find_lev_obj _find_level _find_mac _find_mid _find_misc _find_offensive functions:87 _find_oid _find_roll_to_hit _find_skates _find_unpaid _finddpos _findfirst_file _findgd _findit functions:88 _findnext_file _findone _findpriest _finish_map _finish_paybill _fix_stair_rooms _fix_worst_trouble _fixup_special @@ -116,7 +117,8 @@ functions:91 _fopenp _forcelock _forget_levels _forget_map _forget_objects _forg functions:92 _fprefx _fracture_rock _free_dungeons _free_rooms _free_ttlist _free_window_info _freediskspace _freedynamicdata functions:93 _freefruitchn _freehand _freeinv _friday_13th _fruitadd _fry_by_god _fully_identify_obj _g_at functions:94 _gainstr _gameDiskPrompt _gazemm _gazemu _gd_move _gd_sound _gem_accept -;functions:95 +functions:95 _display_artifact_score _display_warning _dlb_fgetc _doattributes _dochug _dochugw +functions:96 _fill_point _fill_room _fill_zoo _fillholetyp _find_ac _find_branch _find_branch_room _find_defensive functions:96 _get_mon_location _get_mplname _get_obj_location _get_rect _get_rect_ind _get_room_loc _get_scr_size _get_shop_item functions:97 _get_uchars _get_unused_cs _get_valuables _get_wall_for_db _get_wet _get_wormno _getbones _getdir functions:98 _gethungry @@ -143,7 +145,7 @@ functions:119 _itimeout_incr _its_dead _itsstuck _Japanese_item_name _join _join functions:119 _sticks _still_chewing _stock_room _stolen_container _stolen_value _stone_luck _stoned_dialogue _stop_occupation functions:120 _kick_monster _kick_object _kickdmg _kickstr _kill_egg _kill_eggs _kill_genocided_monsters _killed functions:121 _kind_name _known_hitum _kops_gone _l_monnam _lantern_message _launch_obj _lava_effects -functions:122 _ldrname _leader_speaks _leaderless _learn _learn_egg_type _ledger_no _ledger_to_dlev _ledger_to_dnum +functions:122 _ldrname _leader_speaks _leaderless _learn_egg_type _ledger_no _ledger_to_dlev _ledger_to_dnum functions:123 _left_side _lesshungry _let_to_name _letter _lev_by_name _level_difficulty _level_distance _level_range functions:124 _level_tele _level_tele_trap _levl_follower _lifesaved_monster _lift_object _light_cocktail _light_region _lined_up functions:125 _linedup _list_genocided _list_vanquished _litroom _litter _little_to_big _llord _lminion @@ -225,7 +227,7 @@ functions:201 _save_waterlevel _save_worm _savebones _savech _savedamage _saveDi functions:202 _savelev _savelev0 _savelevchn _savelife _savemonchn _savenames _saveobjchn _savestateinlock functions:203 _savetrapchn _scatter _schedule_goto _score_wanted _search_door _search_special _searches_for_item _see_lamp_flicker functions:204 _see_monsters _see_objects _see_traps _see_wsegs _seemimic _seetrap _seffects _select_hwep -functions:205 _select_off _select_rwep _self_pronoun _selftouch _sellobj _sellobj_state _sengr_at _sense_trap +functions:205 _select_off _select_rwep _selftouch _sellobj _sellobj_state _sengr_at _sense_trap functions:206 _set_all_on_page _set_apparxy _set_artifact_intrinsic _set_bc _set_bonesfile_name _set_bonestemp_name _set_corn _set_cost functions:207 _set_crosswall _set_entity _set_item_state _set_itimeout _set_levelfile_name _set_lit _set_lock_and_bones _set_malign functions:208 _set_mimic_blocking _set_mimic_sym _set_mon_data _set_moreluck _set_occupation _set_repo_loc _set_residency _set_savefile_name @@ -417,9 +419,9 @@ functions:380 _use_saddle _uswapwepgone _uwep_skill_type _validalign _validgend functions:381 _validrole _violated_vegetarian _walk_path _warning_opts _wary_dog _welcome functions:382 _write_timer _yyyymmdd _zap_steed functions:383 _getprice _getreturn _getrumor _gettrack -;functions:384 +functions:384 _ini_inv _knows_object _knows_class _restricted_spell_discipline _ready_weapon functions:385 _doname _Doname2 -functions:386 _minwater +functions:386 _minliquid functions:387 _missmm functions:388 _missmu functions:389 _missum diff --git a/sys/msdos/setup.bat b/sys/msdos/setup.bat index 6b5f9b8..33a9182 100644 --- a/sys/msdos/setup.bat +++ b/sys/msdos/setup.bat @@ -1,10 +1,10 @@ @echo off -REM SCCS Id: @(#)setup.bat 97/09/28 -REM Copyright (c) NetHack PC Development Team 1990 - 1997 +REM SCCS Id: @(#)setup.bat 2002/03/17 +REM Copyright (c) NetHack PC Development Team 1990 - 2002 REM NetHack may be freely redistributed. See license for details. echo. -echo Copyright (c) NetHack PC Development Team 1990 - 1997 +echo Copyright (c) NetHack PC Development Team 1990 - 2002 echo NetHack may be freely redistributed. See license for details. echo. REM setup batch file for msdos, see Install.dos for details. @@ -22,6 +22,9 @@ if not exist ..\..\win\tty\wintty.c goto err_dir if not exist ..\share\lev_yacc.c goto err_dir echo Directories OK. +if not exist ..\..\binary\* mkdir ..\..\binary +if NOT exist ..\..\binary\license copy ..\..\dat\license ..\..\binary\license >nul + if exist ..\..\dat\data.bas goto long1ok if exist ..\..\dat\data.base goto long1a if exist ..\..\dat\data~1.bas goto long1b diff --git a/sys/msdos/sound.c b/sys/msdos/sound.c index 847bde2..b283f59 100644 --- a/sys/msdos/sound.c +++ b/sys/msdos/sound.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)sound.c 3.3 96/02/19 */ +/* SCCS Id: @(#)sound.c 3.4 1996/02/19 */ /* Copyright (c) NetHack PC Development Team 1993,1995 */ /* NetHack may be freely redistributed. See license for details. */ /* */ diff --git a/sys/msdos/template.mak b/sys/msdos/template.mak new file mode 100644 index 0000000..b766331 --- /dev/null +++ b/sys/msdos/template.mak @@ -0,0 +1,2232 @@ +# SCCS Id: @(#)template.mak 3.4 1996/10/25 +# Copyright (c) NetHack PC Development Team 1996 +# +?BEGIN? +?SCCS? +?MSC? +# PC NetHack 3.4 Makefile for Microsoft(tm) "C" >= 7.0 and MSVC >= 1.0 +?ENDMSC? +?BC? +# PC NetHack 3.4 Makefile for Borland C++ 3.1. +?ENDBC? +# +# Nota Bene: Before you get to here you should have already read +# the Install.dos file located in the sys/msdos directory. +?BC? +# Additionally, you should run this makefile with the -N +# Microsoft Compatibility option. +# +# This Makefile is for use with Borland C++ version 3.1. +# +# This Makefile is specific to Borland's MAKE which is supplied with the +# compiler. It supports only one overlay management facility - VROOMM. +# (This Makefile won't work with make45l or NDMAKE) +?ENDBC? +?MSC? +# +# This Makefile is for use with Microsoft C version 7 and Microsoft Visual C++ +# Professional Edition (MSVC) version 1.0 or greater. +# +# This Makefile is specific to Microsoft's NMAKE which is supplied with the +# more recent Microsoft C compilers. +# It supports only one overlay management facility - MOVE. +# (This Makefile won't work with make45l or NDMAKE) +# +# In addition to your C compiler, +# +# if you want to change you will need a +# files with suffix workalike for +# .y yacc (such as bison or byacc) +# .l lex (such as flex) +?ENDMSC? + +# +# Game Installation Variables. +# NOTE: Make sure GAMEDIR exists before nmake is started. +# + +GAME = NetHack +GAMEDIR = c:\games\nethack + +# +# +# Directories +# + +DAT = ..\dat +DOC = ..\doc +INCL = ..\include +SRC = ..\src +OBJ = o +MSYS = ..\sys\msdos +SYS = ..\sys\share +UTIL = ..\util +WTTY = ..\win\tty +WSHR = ..\win\share + + +# +# Compiler File Info. +# ($(MAKE) macro is often predefined, so we use $(MAKEBIN) instead.) +# + +?MSC? +CC = cl # Compiler +LINK = link # Linker +ASM = masm # Assembler (not currently needed for MSC 7 and > ) +MAKEBIN = nmake +UUDECODE = uudecode # Unix style uudecoder +?ENDMSC? +?BC? +CC = bcc # Compiler +LINK = tlink # Linker +ASM = tasm # Assembler (not currently needed for BC) +MAKEBIN = make +UUDECODE = uudecode # Unix style uudecoder + +#BCTOP = c:\borlandc # main Borland C++ directory +BCTOP = c:\bc31 +?ENDBC? + +# +# Yacc/Lex ... if you got 'em. +# +# If you have yacc and lex programs (or work-alike such as bison +# and flex), comment out the upper two lines below, and uncomment +# the lower two. +?BC? +# +# On Borland C++, the newest versions of flex and bison provide +# problems when run from MAKE. +?ENDBC? +# + +DO_YACC = YACC_MSG +DO_LEX = LEX_MSG +#DO_YACC = YACC_ACT +#DO_LEX = LEX_ACT + +# +# - Specify your yacc and lex programs (or work-alikes for each) here. +# + +YACC = bison -y +#YACC = yacc +#YACC = byacc + +LEX = flex +#LEX = lex + +# +# - Specify your flex skeleton file (if needed). +# +FLEXSKEL = +#FLEXSKEL = -Sc:\tools16\flex.ske + +# +# - Your yacc (or work-alike) output files +# +YTABC = y_tab.c +YTABH = y_tab.h +#YTABC = ytab.c +#YTABH = ytab.h + +# +# - Your lex (or work-alike) output files +# +LEXYYC = lexyy.c +#LEXYYC = lex.yy.c + +# +# Optional high-quality BSD random number generation routines +# (see pcconf.h). Set to nothing if not used. +# + +RANDOM = $(OBJ)\random.o +#RANDOM = + +# +# If TERMLIB is #defined in the source (in include\pcconf.h), +# comment out the upper line and uncomment the lower. Make sure +# that TERMLIB contains the full pathname to the termcap library. + +TERMLIB = +#TERMLIB = $(SYS)\termcap.lib + +# +# MEMORY USAGE AND OVERLAYING +# +# Overlay Schema 1 +# +# - Minimal extended memory available, lots of 640K base RAM free +# Minimize overlay turns. Requires that a minimum of +?MSC? +# 560K RAM be free as follows: +# 430K Executable load requirement +# 60K Overlay buffer +# 70K for malloc() calls +# 560K Total memory requirement +?ENDMSC? +?BC? +# 607K RAM be free as follows: +# 462K Executable load requirement +# 115K for malloc() calls +# 30K Overlay buffer +# 607K Total memory requirement +?ENDBC? +# +# Overlay Schema 2 +# +# - Favor small load size, requires extended memory for bearable performance. +# If you have very little base 640K RAM available, but lots of extended +# memory for caching overlays, you might try this. (eg. A machine with +# lots of TSR's or network drivers). Do not try to set SCHEMA = 2 +# without a disk cache and extended memory. +?BC? +# 381K Executable load requirement +# 115K for malloc() calls +# 30K Overlay buffer +# 526K Total memory requirement +?ENDBC? +?MSC? +# 360K Executable load requirement +# 60K Overlay buffer +# 70K for malloc() calls +# 419K Total memory requirement +# +# Overlay Schema 3 +# +# - Minimal extended memory available, lots of 640K base RAM free +# Similar to schema1, but the overlay buffer is twice as large, so +# in theory more overlays can be resident at the same time. The cost is +# that the base memory requirement goes up considerably. +# This requires that you obtain the moveinit.c and moveapi.h files from +# your Microsoft C source/move directory, and place them into the src +# directory. Then apply the patch moveinit.pat file found in sys/msdos. +# Requirements: +# 360K Executable load requirement +# 95K Overlay buffer +# 70K for malloc() calls +# 525K Total memory requirement +?ENDMSC? +# +?BC? +# On Borland C++, you have to make a full rebuild of all object modules each +# time you change schemas. +# +?ENDBC? + +SCHEMA = 1 + +# +# OPTIONAL TILE SUPPORT. +# +# This release of NetHack allows you to build a version of NetHack +# that will draw 16x16 color tiles on the display to represent +# NetHack maps, objects, monsters, etc. on machines with appropriate +# display hardware. Currently the only supported video hardware is +# VGA. +# +# Note: You can build NetHack with tile support and then choose +# whether to use it or not at runtime via the defaults.nh file option +# "video". +# + +TILESUPPORT = Y + +# +# C COMPILER AND LINKER SETTINGS +# +# For debugging ability, comment out the upper three +# macros and uncomment the lower three. You can also +# uncomment only either LDFLAGSU or LDFLAGSN if you +# want to include debug information only in the utilities +# or only in the game file. +?BC? + +# On Borland C++, you cannot include debug information for +# all the object modules because the linker cannot handle +# it. +?ENDBC? + +#CDFLAGS = +?MSC? +#LDFLAGSN = +?ENDMSC? +?BC? +LDFLAGSN = +?ENDBC? +#LDFLAGSU = + +?MSC? +CDFLAGS = /Zi # use debug info (compiler) +LDFLAGSN = /CO # use debug info (linker - game) +LDFLAGSU = /CO # use debug info (linker - utilities) +?ENDMSC? +?BC? +CDFLAGS = -v -vi # use debug info (compiler) +#LDFLAGSN = /v # use debug info (linker - game) +LDFLAGSU = /v # use debug info (linker - utilities) +?ENDBC? + +# +?MSC? +# - Force a change in the C warning level for all builds. +# (Its W0 setting in the CL environment variable will take +# precedence if left blank here). +?ENDMSC? +?BC? +# - Don't warn about unreachable code because flex generates a whole bunch +# of unreachable code warnings, which stops the compile process. +?ENDBC? +# + +?MSC? +CW = +#CW =/W3 +?ENDMSC? +?BC? +CW = -w-rch +?ENDBC? + +# +# Select whether to use pre-compiled headers or not. +# Set PRECOMPHEAD to Y to use pre-compiled headers, set it to anything +# else and pre-compiled headers will not be used. +# (Pre-compiled headers speed up compiles, but require a bit more +# disk space during the build. The pre-compiled headers can be deleted +# afterwards via DEL *.PCH if desired). +# + +PRECOMPHEAD = N + +# +# C Compiler Flags +# +?MSC? +# Note: +# +# CL environment variable should already be set to: +# CL= /AL /G2 /Oo /Gs /Gt16 /Zp1 /W0 /I..\include /nologo /DMOVERLAY +# +?ENDMSC? + +?MSC? +CFLAGS = /c +?ENDMSC? +?BC? +CFLAGS = -c +?ENDBC? + +# Uncomment the line below if you want to store all the level files, +# help files, etc. in a single library file (recommended). + +USE_DLB = Y + +# +######################################################################## +######################################################################## +# +# Nothing below here should have to be changed. +# +######################################################################## +######################################################################## +# +# Warning: +# +# Changing anything below here means that you should be *very* +# familiar with your compiler's workings, *very* knowledgeable +# about the overlay structure and mechanics of NetHack, and *very* +# confident in your understanding of Makefiles and Make utilities. +# +######################################################################## +# +# Default Make Procedure +# + +default: $(GAME) + +# +######################################################################## +# Tile preparation +# + +! IF ("$(TILESUPPORT)"=="Y") + +TILEGAME = $(OBJ)\tile.o $(OBJ)\pctiles.0 $(OBJ)\pctiles.b + +# +# - VGA Tile Support, uncomment these three lines. +# + +TILEVGA = $(OBJ)\vidvga.0 $(OBJ)\vidvga.1 $(OBJ)\vidvga.2 $(OBJ)\vidvga.b +PLANAR_TIB = NetHack1.tib +OVERVIEW_TIB = NetHacko.tib + +# +# Leave this line uncommented and unchanged. +TILEUTIL = $(TILEGAME) $(TILEVGA) $(UTIL)\tile2bin.exe $(UTIL)\til2bin2.exe \ + $(PLANAR_TIB) $(OVERVIEW_TIB) + +! ENDIF + +! IF ("$(USE_DLB)"=="Y") +DLB = nhdat +! ELSE +DLB = +! ENDIF + +# +############################################################################# +# +# General Overlay Schema Settings +# + +?MSC? +LNKOPT = schema$(SCHEMA).def +?ENDMSC? +?BC? +!include schema$(SCHEMA).bc +OVLINIT =$(OBJ)\ovlinit.o +?ENDBC? + +?MSC? +# +# - Specific Overlay Schema Settings +# + +! IF ($(SCHEMA)==1) +INTOVL = /DYNAMIC:1250 /NOE +OVLINIT = +! ENDIF + +! IF ($(SCHEMA)==2) +INTOVL = /DYNAMIC:1380 /NOE +OVLINIT = +! ENDIF + +! IF ($(SCHEMA)==3) +INTOVL = /DYNAMIC:1170 +OVLINIT = $(OBJ)\moveinit.o $(OBJ)\ovlinit.o +! ENDIF +?ENDMSC? + +# +############################################################################# +# +# C Compiler and Linker Setup Options +# (To Maintainer; modify only if absolutely necessary) +# + +?BC? +BCINCL = $(BCTOP)\include # include directory for main BC headers +BCLIB = $(BCTOP)\lib # library directory for main BC libraries +BCCFG = nethack.cfg # name of the nethack configuration file +?ENDBC? + +# +# Model +# + +?MSC? +MODEL = L +?ENDMSC? +?BC? +MODEL = h +?ENDBC? + +# +# - Optional C library specifier for those with non-standard +# libraries or a multiple-target library setup. +# + +CLIB = +?MSC? +#CLIB = llibcer /nod +?ENDMSC? + +?BC? +# +# Borland C++ libraries +# + +BCOVL = $(BCLIB)\OVERLAY +BCMDL = $(BCLIB)\C$(MODEL) + +?ENDBC? +# +# Compiler Options +# + +?MSC? +CNOLNK = /c # just generate .OBJ +CPCHUSE = /YuHACK.H # use precompiled headers +CPCHGEN = /YcHACK.H # generate precompiled headers +CPCHNAM = /Fp # set the name of the precompiled header file +CPCHEXT = .PCH # precompiled header extension +CDEFINE = /D # define a macro +CCSNAM = /NT # set the code segment name +COBJNAM = /Fo # name the .OBJ file +CNOOPT = /f- /Od # disable optimizations (must be first in line) + # /f- = don't use the "fast" compiler,its buggy +?ENDMSC? +?MSCMACRO:CSNAMOA= ? +?MSCMACRO:CSNAMOB=$(CCSNAM)$(@F) ? +?MSCMACRO:CSNAM0=$(CCSNAM)$(@F) ? +?MSCMACRO:CSNAM1=$(CCSNAM)$(@F) ? +?MSCMACRO:CSNAM2=$(CCSNAM)$(@F) ? +?MSCMACRO:CSNAM3=$(CCSNAM)$(@F) ? +?MSCMACRO:CSNAMB=$(CCSNAM)$(@F) ? +?BC? +CNOLNK = -c # just generate .OBJ +CPCHUSE = -Hu # use precompiled headers +CPCHGEN = -H # generate precompiled headers +CPCHNAM = -H= # set the name of the precompiled header file +CPCHEXT = .PCH # precompiled header extension +CDEFINE = -D # define a macro +CSTKSZ = -DSTKSIZ= # set stack size +CCSNAM = -zC # set the code segment name +COBJNAM = -o # name the .OBJ file +?ENDBC? +?BCMACRO:CSNAMOA=$$($(@B)_o) ? +?BCMACRO:CSNAMOB=$$($(@B)_o) ? +?BCMACRO:CSNAM0=$$($(@B)_0) ? +?BCMACRO:CSNAM1=$$($(@B)_1) ? +?BCMACRO:CSNAM2=$$($(@B)_2) ? +?BCMACRO:CSNAM3=$$($(@B)_3) ? +?BCMACRO:CSNAMB=$$($(@B)_b) ? + +# +# Linker Options +# + +?MSC? +LWCASE = /NOI # treat case as significant +LMAP = /MAP # create map file +LSTKSZ = /ST: # set stack size +LMAXSEG = /SE:400 # maximum number of segments allowed +LMAXALL = /CPARM:1 # maximum program memory allocation (?) +LINFO = /INFO # display link information while processing +?ENDMSC? +?BC? +LWCASE = /c # treat case as significant +LMAP = /m # create map file +LINIT = $(BCLIB)\C0$(MODEL) # initialization object file +LOVL = /oOVLY # overlay all needed segments +?ENDBC? + +# +# Stack Sizes +# + +STKSUTL = 4096 # Utilities Stack Size +STKSNRM = 5120 # Normal Stack Size + +?MSC? +LUSTACK = $(LSTKSZ)$(STKSUTL) # Utilities Stack Set for Linker +LNSTACK = $(LSTKSZ)$(STKSNRM) # Normal Stack Set for Linker +?ENDMSC? +?BC? +CUSTACK = $(CSTKSZ)$(STKSUTL) # Utilities Stack Set for Compiler +CNSTACK = $(CSTKSZ)$(STKSNRM) # Normal Stack Set for Compiler +?ENDBC? + + +# +######################################################################## +# DLB preparation +# + +! IF ("$(USE_DLB)"=="Y") +DLBFLG = $(CDEFINE)DLB +! ELSE +DLBFLG = +! ENDIF + +# +######################################################################## +# tile preparation +# + +! IF ("$(TILESUPPORT)"=="Y") +TILFLG = $(CDEFINE)USE_TILES +! ELSE +TILFLG = +! ENDIF + +############################################################################# +# +# Overlay switches +# + +COVL0 = $(CDEFINE)OVL0 +COVL1 = $(CDEFINE)OVL1 +COVL2 = $(CDEFINE)OVL2 +COVL3 = $(CDEFINE)OVL3 +COVLB = $(CDEFINE)OVLB + +# +# Flags +# + +FLAGOPT = $(DLBFLG) $(TILFLG) + +# +# Precompiled Header Section +# + +?BC? +#common options (placed in $(BCCFG)) +CFLGTOT = $(CDFLAGS) $(CFLAGS) $(FLAGOPT) $(CW) +#util builds +CFLAGSU = +$(BCCFG) $(CUSTACK) +#normal build, no PCH +CFLAGSN = +$(BCCFG) $(CNSTACK) +?ENDBC? +?MSC? +#util builds +CFLAGSU = $(CDFLAGS) $(CFLAGS) $(CW) $(FLAGOPT) $(CUSTACK) +#normal build, no PCH +CFLAGSN = $(CDFLAGS) $(CFLAGS) $(CW) $(FLAGOPT) $(CNSTACK) +?ENDMSC? +#no optimizations +CFLAGNO = $(CNOOPT) $(CFLAGSN) + +! IF ("$(PRECOMPHEAD)"!="Y") + +CFLAGCO = $(COVLO) +CFLAGUO = $(COVLO) +CFLAGC0 = $(COVL0) +CFLAGU0 = $(COVL0) +CFLAGC1 = $(COVL1) +CFLAGU1 = $(COVL1) +CFLAGC2 = $(COVL2) +CFLAGU2 = $(COVL2) +CFLAGC3 = $(COVL3) +CFLAGU3 = $(COVL3) +CFLAGCB = $(COVLB) +CFLAGUB = $(COVLB) +PCHO = +PCH0 = +PCH1 = +PCH2 = +PCH3 = +PCHB = + +precomp.msg: + @echo Not using precompiled headers... + +! ELSE + +# .o files +CFLAGUO = $(CPCHUSE) $(CPCHNAM)PHO$(CPCHEXT) $(COVLO) +CFLAGCO = $(CPCHGEN) $(CPCHNAM)PHO$(CPCHEXT) $(COVLO) +PCHO = PHO$(CPCHEXT) +# .0 files +CFLAGU0 = $(CPCHUSE) $(CPCHNAM)PH0$(CPCHEXT) $(COVL0) +CFLAGC0 = $(CPCHGEN) $(CPCHNAM)PH0$(CPCHEXT) $(COVL0) +PCH0 = PH0$(CPCHEXT) +# .1 files +CFLAGU1 = $(CPCHUSE) $(CPCHNAM)PH1$(CPCHEXT) $(COVL1) +CFLAGC1 = $(CPCHGEN) $(CPCHNAM)PH1$(CPCHEXT) $(COVL1) +PCH1 = PH1$(CPCHEXT) +# .2 files +CFLAGU2 = $(CPCHUSE) $(CPCHNAM)PH2$(CPCHEXT) $(COVL2) +CFLAGC2 = $(CPCHGEN) $(CPCHNAM)PH2$(CPCHEXT) $(COVL2) +PCH2 = PH2$(CPCHEXT) +# .3 files +CFLAGU3 = $(CPCHUSE) $(CPCHNAM)PH3$(CPCHEXT) $(COVL3) +CFLAGC3 = $(CPCHGEN) $(CPCHNAM)PH3$(CPCHEXT) $(COVL3) +PCH3 = PH3$(CPCHEXT) +# .B files +CFLAGUB = $(CPCHUSE) $(CPCHNAM)PHB$(CPCHEXT) $(COVLB) +CFLAGCB = $(CPCHGEN) $(CPCHNAM)PHB$(CPCHEXT) $(COVLB) +PCHB = PHB$(CPCHEXT) + +precomp.msg: + @echo Using precompiled headers... + +! ENDIF + + +?BC? +FLAGCO = $(CNSTACK) +CFLAGCO.CFG +FLAGUO = $(CNSTACK) +CFLAGUO.CFG +FLAGC0 = $(CNSTACK) +CFLAGC0.CFG +FLAGU0 = $(CNSTACK) +CFLAGU0.CFG +FLAGC1 = $(CNSTACK) +CFLAGC1.CFG +FLAGU1 = $(CNSTACK) +CFLAGU1.CFG +FLAGC2 = $(CNSTACK) +CFLAGC2.CFG +FLAGU2 = $(CNSTACK) +CFLAGU2.CFG +FLAGC3 = $(CNSTACK) +CFLAGC3.CFG +FLAGU3 = $(CNSTACK) +CFLAGU3.CFG +FLAGCB = $(CNSTACK) +CFLAGCB.CFG +FLAGUB = $(CNSTACK) +CFLAGUB.CFG +?ENDBC? +?MSC? +FLAGCO = $(CFLAGSN) $(CFLAGCO) +FLAGUO = $(CFLAGSN) $(CFLAGUO) +FLAGC0 = $(CFLAGSN) $(CFLAGC0) +FLAGU0 = $(CFLAGSN) $(CFLAGU0) +FLAGC1 = $(CFLAGSN) $(CFLAGC1) +FLAGU1 = $(CFLAGSN) $(CFLAGU1) +FLAGC2 = $(CFLAGSN) $(CFLAGC2) +FLAGU2 = $(CFLAGSN) $(CFLAGU2) +FLAGC3 = $(CFLAGSN) $(CFLAGC3) +FLAGU3 = $(CFLAGSN) $(CFLAGU3) +FLAGCB = $(CFLAGSN) $(CFLAGCB) +FLAGUB = $(CFLAGSN) $(CFLAGUB) +?ENDMSC? + +# End of Pre-compiled header section +#=========================================================================== + +?MSC? +# +# Controls whether MOVE tracing is enabled in the executable +# This should be left commented unless you are tinkering with the +# overlay structure of NetHack. The executable runs _very_ +# slowly when the movetr.lib is linked in. +# + +#MOVETR= movetr.lib + +# do not change this +! IF ("$(MOVETR)"!="") +MVTRCL = $(CDEFINE)MOVE_PROF +! ELSE +MVTRCL = +! ENDIF + +?ENDMSC? +# +# Linker options for building various things. +# + +LFLAGSU = $(LDFLAGSU) $(LUSTACK) $(LINIT) +LFLAGSN = $(LDFLAGSN) $(LNSTACK) $(LWCASE) $(LMAXSEG) $(INTOVL) $(LMAXALL) \ + $(LINFO) $(LINIT) $(LOVL) + +# +# Make Roolz dude. +# Due to the inadequacy of some makes these must accord with a +# topological sort of the generated-from relation... output on +# the left, input on the right. Trust me. +# + +.SUFFIXES: .exe .0 .1 .2 .3 .B .o .til .uu .c .y .l + +# +# Rules for files in src +# + + +.c{$(OBJ)}.o: + @$(CC) $(FLAGUO) ?[CSNAMOB]$(COBJNAM)$@ $< + +{$(SRC)}.c{$(OBJ)}.o: + $(CC) $(FLAGUO) ?[CSNAMOB]$(COBJNAM)$@ $< + +{$(SRC)}.c{$(OBJ)}.0: + $(CC) $(FLAGU0) ?[CSNAM0]$(COBJNAM)$@ $< + +{$(SRC)}.c{$(OBJ)}.1: + $(CC) $(FLAGU1) ?[CSNAM1]$(COBJNAM)$@ $< + +{$(SRC)}.c{$(OBJ)}.2: + $(CC) $(FLAGU2) ?[CSNAM2]$(COBJNAM)$@ $< + +{$(SRC)}.c{$(OBJ)}.3: + $(CC) $(FLAGU3) ?[CSNAM3]$(COBJNAM)$@ $< + +{$(SRC)}.c{$(OBJ)}.B: + $(CC) $(FLAGUB) ?[CSNAMB]$(COBJNAM)$@ $< + +# +# Rules for files in sys\share +# + +{$(SYS)}.c{$(OBJ)}.o: + $(CC) $(FLAGUO) ?[CSNAMOA]$(COBJNAM)$@ $< + +{$(SYS)}.c{$(OBJ)}.0: + $(CC) $(FLAGU0) ?[CSNAM0]$(COBJNAM)$@ $< + +{$(SYS)}.c{$(OBJ)}.1: + $(CC) $(FLAGU1) ?[CSNAM1]$(COBJNAM)$@ $< + +{$(SYS)}.c{$(OBJ)}.2: + $(CC) $(FLAGU2) ?[CSNAM2]$(COBJNAM)$@ $< + +{$(SYS)}.c{$(OBJ)}.3: + $(CC) $(FLAGU3) ?[CSNAM3]$(COBJNAM)$@ $< + +{$(SYS)}.c{$(OBJ)}.B: + $(CC) $(FLAGUB) ?[CSNAMB]$(COBJNAM)$@ $< + +# +# Rules for files in sys\msdos +# + +{$(MSYS)}.c{$(OBJ)}.o: + $(CC) $(FLAGUO) ?[CSNAMOA]$(COBJNAM)$@ $< + +{$(MSYS)}.c{$(OBJ)}.0: + $(CC) $(FLAGU0) ?[CSNAM0]$(COBJNAM)$@ $< + +{$(MSYS)}.c{$(OBJ)}.1: + $(CC) $(FLAGU1) ?[CSNAM1]$(COBJNAM)$@ $< + +{$(MSYS)}.c{$(OBJ)}.2: + $(CC) $(FLAGU2) ?[CSNAM2]$(COBJNAM)$@ $< + +{$(MSYS)}.c{$(OBJ)}.3: + $(CC) $(FLAGU3) ?[CSNAM3]$(COBJNAM)$@ $< + +{$(MSYS)}.c{$(OBJ)}.B: + $(CC) $(FLAGUB) ?[CSNAMB]$(COBJNAM)$@ $< + +{$(MSYS)}.h{$(INCL)}.h: + @copy $< $@ + +# +# Rules for files in util +# + +{$(UTIL)}.c{$(OBJ)}.o: + $(CC) $(CFLAGSU) ?[CSNAMOB]$(COBJNAM)$@ $< + +# +# Rules for files in win\share +# + +{$(WSHR)}.c.o: + @$(CC) $(FLAGUO) ?[CSNAMOA]$(COBJNAM)$@ $< + +{$(WSHR)}.c{$(OBJ)}.o: + @$(CC) $(FLAGUO) ?[CSNAMOA]$(COBJNAM)$@ $< + +{$(WSHR)}.h{$(INCL)}.h: + @copy $< $@ + +{$(WSHR)}.txt{$(DAT)}.txt: + @copy $< $@ + +# +# Rules for files in win\tty +# + +{$(WTTY)}.c{$(OBJ)}.o: + $(CC) $(FLAGUO) ?[CSNAMOA]$(COBJNAM)$@ $< + +{$(WTTY)}.c{$(OBJ)}.0: + $(CC) $(FLAGU0) ?[CSNAM0]$(COBJNAM)$@ $< + +{$(WTTY)}.c{$(OBJ)}.1: + $(CC) $(FLAGU1) ?[CSNAM1]$(COBJNAM)$@ $< + +{$(WTTY)}.c{$(OBJ)}.2: + $(CC) $(FLAGU2) ?[CSNAM2]$(COBJNAM)$@ $< + +{$(WTTY)}.c{$(OBJ)}.3: + $(CC) $(FLAGU3) ?[CSNAM3]$(COBJNAM)$@ $< + +{$(WTTY)}.c{$(OBJ)}.B: + $(CC) $(FLAGUB) ?[CSNAMB]$(COBJNAM)$@ $< + +# +# NETHACK OBJECTS +# +# This section creates shorthand macros for many objects +# referenced later on in the Makefile. +# + +# +# Shorten up the location for some files +# + +O = $(OBJ)\ # comment so \ isn't last char + +U = $(UTIL)\ # comment so \ isn't last char + +# +# Utility Objects. +# + +MAKESRC = $(U)makedefs.c + +SPLEVSRC = $(U)lev_yacc.c $(U)lev_$(LEX).c $(U)lev_main.c $(U)panic.c + +DGNCOMPSRC = $(U)dgn_yacc.c $(U)dgn_$(LEX).c $(U)dgn_main.c + +MAKEOBJS = $(O)makedefs.o $(O)monst.o $(O)objects.o + +?LIST:SPLEVOBJS? + $(O)lev_yacc.o $(O)lev_$(LEX).o $(O)lev_main.o + $(O)alloc.o $(O)decl.o $(O)drawing.o + $(O)monst.o $(O)objects.o $(O)panic.o $(O)stubvid.o +?ENDLIST? + +?LIST:DGNCOMPOBJS? + $(O)dgn_yacc.o $(O)dgn_$(LEX).o $(O)dgn_main.o + $(O)alloc.o $(O)panic.o +?ENDLIST? + +RECOVOBJS = $(O)recover.o + +?LIST:GIFREADERS? + $(O)gifread.o $(O)alloc.o $(O)panic.o +?ENDLIST? + +?LIST:TEXT_IO? + $(O)tiletext.o $(O)tiletxt.o $(O)drawing.o + $(O)decl.o $(O)monst.o $(O)objects.o + $(O)stubvid.o +?ENDLIST? + +PPMWRITERS = $(O)ppmwrite.o $(O)alloc.o $(O)panic.o + +?LIST:GIFREAD2? + $(O)gifread2.o $(O)alloc.o $(O)panic.o +?ENDLIST? + +?LIST:TEXT_IO2? + $(O)tiletex2.o $(O)tiletxt2.o $(O)drawing.o + $(O)decl.o $(O)monst.o $(O)objects.o + $(O)stubvid.o +?ENDLIST? + +PPMWRIT2 = $(O)ppmwrit2.o $(O)alloc.o $(O)panic.o + +TILEFILES = $(WSHR)\monsters.txt $(WSHR)\objects.txt $(WSHR)\other.txt + +TILEFILES2 = $(WSHR)\monthin.txt $(WSHR)\objthin.txt $(WSHR)\oththin.txt + +DLBOBJS = $(O)dlb_main.o $(O)dlb.o $(O)alloc.o $(O)panic.o + +# +# Object files for the game itself. +# + +OBJ01 = $(O)alloc.o $(RANDOM) $(O)decl.o $(O)objects.o \ + $(O)muse.o $(O)display.o $(O)vision.o \ + $(O)rect.o $(O)vis_tab.o $(O)monst.o $(O)wintty.o \ + $(O)files.o $(O)sys.o $(O)monstr.o $(O)minion.o \ + $(O)worm.o $(O)detect.o $(O)exper.o $(O)mplayer.o \ + $(O)uhitm.o $(O)pager.o $(O)windows.o $(O)quest.o \ + $(O)questpgr.o $(O)write.o $(O)drawing.o $(O)dokick.o \ + $(O)dothrow.o $(O)pickup.o $(O)pray.o $(O)spell.o \ + $(O)ball.o $(O)wield.o $(O)worn.o $(O)fountain.o \ + $(O)music.o $(O)rumors.o $(O)dlb.o $(O)sit.o \ + $(O)bones.o $(O)mklev.o $(O)save.o $(O)restore.o \ + $(O)mkmaze.o $(O)mkmap.o $(O)end.o $(O)o_init.o \ + $(O)options.o $(O)rip.o $(O)sound.o $(O)teleport.o \ + $(O)topten.o $(O)tty.o $(O)u_init.o $(O)extralev.o \ + $(O)sp_lev.o $(O)dig.o $(O)pckeys.o $(O)role.o \ + $(O)steed.o $(O)region.o + +OVL0 = $(O)allmain.0 $(O)apply.0 $(O)artifact.0 $(O)attrib.0 \ + $(O)botl.0 $(O)cmd.0 $(O)dbridge.0 $(O)do.0 \ + $(O)do_name.0 $(O)do_wear.0 $(O)dogmove.0 $(O)dungeon.0 \ + $(O)eat.0 $(O)engrave.0 $(O)hacklib.0 $(O)invent.0 \ + $(O)lock.0 $(O)pcmain.0 $(O)mail.0 $(O)makemon.0 \ + $(O)mcastu.0 $(O)mhitm.0 $(O)mhitu.0 $(O)mkobj.0 \ + $(O)mkroom.0 $(O)mon.0 $(O)mondata.0 $(O)monmove.0 \ + $(O)mthrowu.0 $(O)objnam.0 $(O)polyself.0 $(O)priest.0 \ + $(O)rnd.0 $(O)shknam.0 $(O)sounds.0 $(O)steal.0 \ + $(O)timeout.0 $(O)track.0 $(O)trap.0 $(O)vault.0 \ + $(O)weapon.0 $(O)were.0 $(O)wizard.0 $(O)msdos.0 \ + $(O)termcap.0 $(O)video.0 $(O)vidtxt.0 $(O)zap.0 \ + $(O)explode.0 $(O)shk.0 + +OVL1 = $(O)allmain.1 $(O)apply.1 $(O)artifact.1 $(O)attrib.1 \ + $(O)botl.1 $(O)cmd.1 $(O)dbridge.1 $(O)do.1 \ + $(O)do_wear.1 $(O)dog.1 $(O)dungeon.1 $(O)eat.1 \ + $(O)engrave.1 $(O)hack.1 $(O)hacklib.1 $(O)invent.1 \ + $(O)makemon.1 $(O)mhitu.1 $(O)mkobj.1 $(O)mon.1 \ + $(O)mondata.1 $(O)monmove.1 $(O)mthrowu.1 $(O)objnam.1 \ + $(O)pcmain.1 $(O)polyself.1 $(O)rnd.1 $(O)shk.1 \ + $(O)steal.1 $(O)timeout.1 $(O)track.1 $(O)trap.1 \ + $(O)weapon.1 $(O)getline.1 $(O)termcap.1 $(O)topl.1 \ + $(O)video.1 $(O)zap.1 $(O)explode.1 + +OVL2 = $(O)attrib.2 $(O)do.2 $(O)do_name.2 $(O)do_wear.2 \ + $(O)dog.2 $(O)engrave.2 $(O)hack.2 $(O)hacklib.2 \ + $(O)invent.2 $(O)makemon.2 $(O)mon.2 $(O)mondata.2 \ + $(O)monmove.2 $(O)getline.2 $(O)shk.2 $(O)topl.2 \ + $(O)trap.2 $(O)zap.2 + +OVL3 = $(O)do.3 $(O)hack.3 $(O)invent.3 $(O)light.3 \ + $(O)shk.3 $(O)trap.3 $(O)zap.3 + + +OVLB = $(O)allmain.B $(O)apply.B $(O)artifact.B $(O)attrib.B \ + $(O)botl.B $(O)cmd.B $(O)dbridge.B $(O)do.B \ + $(O)do_name.B $(O)do_wear.B $(O)dog.B $(O)dogmove.B \ + $(O)eat.B $(O)engrave.B $(O)hack.B $(O)hacklib.B \ + $(O)invent.B $(O)lock.B $(O)mail.B $(O)makemon.B \ + $(O)mcastu.B $(O)mhitm.B $(O)mhitu.B $(O)mkobj.B \ + $(O)mkroom.B $(O)mon.B $(O)mondata.B $(O)monmove.B \ + $(O)mthrowu.B $(O)objnam.B $(O)pcmain.B $(O)pline.B \ + $(O)polyself.B $(O)potion.B $(O)priest.B $(O)read.B \ + $(O)rnd.B $(O)shk.B $(O)shknam.B $(O)sounds.B \ + $(O)steal.B $(O)timeout.B $(O)track.B $(O)trap.B \ + $(O)vault.B $(O)weapon.B $(O)were.B $(O)wizard.B \ + $(O)msdos.B $(O)pcunix.B $(O)termcap.B $(O)topl.B \ + $(O)video.B $(O)vidtxt.B $(O)zap.B + +TILOBJ = $(TILEGAME) $(TILEVGA) + +VVOBJ = $(O)version.o + +NVOBJ = $(OBJ01) $(OVL0) $(OVL1) $(OVL2) \ + $(OVL3) $(OVLB) $(TILOBJ) + +ALLOBJ= $(NVOBJ) $(VVOBJ) $(OVLINIT) + +# +# Header objects +# + +# This comment copied from sys/unix/Makefile.src, +# extern.h is ignored, even though its declared function types may affect the +# compilation of all the .c files, since extern.h changes every time the +# type of an external function does, and we would spend all our time recompiling +# if we did not ignore it. +#EXTERN_H = $(INCL)\extern.h +EXTERN_H = +PCCONF_H = $(INCL)\pcconf.h $(INCL)\micro.h $(INCL)\system.h +PERMONST_H = $(INCL)\monattk.h $(INCL)\monflag.h $(INCL)\align.h +YOUPROP_H = $(INCL)\prop.h $(PERMONST_H) $(INCL)\pm.h $(INCL)\youprop.h \ + $(INCL)\mondata.h +YOU_H = $(INCL)\attrib.h $(INCL)\monst.h $(YOUPROP_H) $(INCL)\align.h +DECL_H = $(INCL)\quest.h $(INCL)\spell.h $(INCL)\color.h \ + $(INCL)\obj.h $(YOU_H) $(INCL)\onames.h $(INCL)\pm.h + +CONFIG_H = $(INCL)\tradstdc.h $(INCL)\coord.h $(PCCONF_H) $(INCL)\config.h +HACK_H = $(CONFIG_H) $(INCL)\dungeon.h $(INCL)\align.h $(INCL)\monsym.h \ + $(INCL)\mkroom.h $(INCL)\objclass.h $(DECL_H) \ + $(INCL)\timeout.h $(INCL)\trap.h $(INCL)\flag.h $(INCL)\rm.h \ + $(INCL)\vision.h $(INCL)\mondata.h $(INCL)\wintype.h \ + $(INCL)\engrave.h $(INCL)\rect.h $(EXTERN_H) \ + $(INCL)\winprocs.h $(INCL)\trampoli.h $(INCL)\display.h +TILE_H = $(INCL)\tile.h $(INCL)\pctiles.h +PCVIDEO_H = $(INCL)\portio.h $(INCL)\pcvideo.h +ALIGN_H = $(INCL)\align.h +ARTIFACT_H = $(INCL)\artifact.h +ARTILIST_H = $(INCL)\artilist.h +COLOR_H = $(INCL)\color.h +DATE_H = $(INCL)\date.h +DGN_FILE_H = $(INCL)\dgn_file.h +DLB_H = $(INCL)\dlb.h +EMIN_H = $(INCL)\emin.h +EPRI_H = $(INCL)\epri.h +ESHK_H = $(INCL)\eshk.h +EDOG_H = $(INCL)\edog.h +FUNC_TAB_H = $(INCL)\func_tab.h +LEV_H = $(INCL)\lev.h +LEV_COMP_H = $(INCL)\lev_comp.h +MAIL_H = $(INCL)\mail.h +MFNDPOS_H = $(INCL)\mfndpos.h +MONSYM_H = $(INCL)\monsym.h +OBJ_H = $(INCL)\obj.h +OBJCLASS_H = $(INCL)\objclass.h +OBJECTS_H = $(INCL)\objects.h +PROP_H = $(INCL)\prop.h +QTEXT_H = $(INCL)\qtext.h +QUEST_H = $(INCL)\quest.h +SP_LEV_H = $(INCL)\sp_lev.h +TERMCAP_H = $(INCL)\tcap.h +VAULT_H = $(INCL)\vault.h +VIS_TAB_H = $(INCL)\vis_tab.h +WINTTY_H = $(INCL)\wintty.h + +# +# In the unix distribution this file is patchlevel.h, make it 8.3 here +# to avoid an nmake warning under dos. +# + +PATCHLEVEL_H = $(INCL)\patchlev.h + + +# +# The name of the game. +# + +GAMEFILE = $(GAMEDIR)\$(GAME).exe + +# +# make data.base an 8.3 filename to prevent an nmake warning +# + +DATABASE = $(DAT)\data.bas + +####################################################################### +# +# TARGETS + +# +# The main target. +# + +$(GAME): obj.tag envchk $(U)utility.tag $(GAMEFILE) + @echo $(GAME) is up to date. + +# +# Everything +# + +all : install + +install: $(GAME) install.tag + @echo Done. + + +install.tag: $(DAT)\data $(DAT)\rumors $(DAT)\dungeon \ + $(DAT)\oracles $(DAT)\quest.dat $(DAT)\sp_lev.tag $(DLB) +! IF ("$(USE_DLB)"=="Y") + copy nhdat $(GAMEDIR) + copy $(DAT)\license $(GAMEDIR) +! ELSE + copy $(DAT)\*. $(GAMEDIR) + copy $(DAT)\*.dat $(GAMEDIR) + copy $(DAT)\*.lev $(GAMEDIR) + copy $(MSYS)\msdoshlp.txt $(GAMEDIR) + if exist $(GAMEDIR)\makefile del $(GAMEDIR)\makefile +! ENDIF + copy $(SYS)\termcap $(GAMEDIR) + if exist $(DOC)\guideb*.txt copy $(DOC)\guideb*.txt $(GAMEDIR) + if exist $(DOC)\nethack.txt copy $(DOC)\nethack.txt $(GAMEDIR)\NetHack.txt + if exist $(DOC)\recover.txt copy $(DOC)\recover.txt $(GAMEDIR) + copy $(SYS)\nethack.cnf $(GAMEDIR)\defaults.nh + copy $(U)recover.exe $(GAMEDIR) + if exist *.tib copy *.tib $(GAMEDIR) + echo install done > $@ + +$(DAT)\sp_lev.tag: $(U)utility.tag $(DAT)\bigroom.des $(DAT)\castle.des \ + $(DAT)\endgame.des $(DAT)\gehennom.des $(DAT)\knox.des \ + $(DAT)\medusa.des $(DAT)\oracle.des $(DAT)\tower.des \ + $(DAT)\yendor.des $(DAT)\arch.des $(DAT)\barb.des \ + $(DAT)\caveman.des $(DAT)\elf.des $(DAT)\healer.des \ + $(DAT)\knight.des $(DAT)\priest.des $(DAT)\rogue.des \ + $(DAT)\samurai.des $(DAT)\tourist.des $(DAT)\valkyrie.des \ + $(DAT)\wizard.des + cd $(DAT) + $(U)lev_comp bigroom.des + $(U)lev_comp castle.des + $(U)lev_comp endgame.des + $(U)lev_comp gehennom.des + $(U)lev_comp knox.des + $(U)lev_comp mines.des + $(U)lev_comp medusa.des + $(U)lev_comp oracle.des + $(U)lev_comp tower.des + $(U)lev_comp yendor.des + $(U)lev_comp arch.des + $(U)lev_comp barb.des + $(U)lev_comp caveman.des + $(U)lev_comp elf.des + $(U)lev_comp healer.des + $(U)lev_comp knight.des + $(U)lev_comp priest.des + $(U)lev_comp rogue.des + $(U)lev_comp samurai.des + $(U)lev_comp tourist.des + $(U)lev_comp valkyrie.des + $(U)lev_comp wizard.des + cd $(SRC) + echo sp_levs done > $(DAT)\sp_lev.tag + +$(U)utility.tag: envchk $(INCL)\date.h $(INCL)\onames.h \ + $(INCL)\pm.h $(SRC)\monstr.c $(SRC)\vis_tab.c \ + $(U)lev_comp.exe $(VIS_TAB_H) $(U)dgn_comp.exe \ + $(U)recover.exe $(TILEUTIL) + @echo utilities made >$@ + @echo utilities made. + +tileutil: $(U)gif2txt.exe $(U)txt2ppm.exe + @echo Optional tile development utilities are up to date. + +?MSC? +# The section for linking the NetHack image looks a little strange at +# first, especially if you are used to UNIX makes, or NDMAKE. It is +# Microsoft nmake specific, and it gets around the problem of the link +# command line being too long for the linker. An "in-line" linker +# response file is generated temporarily. +# +# It takes advantage of the following features of nmake: +?ENDMSC? +# +# Inline files : +# Specifying the "<<" means to start an inline file. +# Another "<<" at the start of a line closes the +# inline file. +# +?MSC? +# Substitution within Macros: +# $(mymacro:string1=string2) replaces every +# occurrence of string1 with string2 in the +# macro mymacro. Special ascii key codes may be +# used in the substitution text by preceding it +# with ^ as we have done below. Every occurrence +# of a in $(ALLOBJ) is replaced by +# <+>. +# +?ENDMSC? +# DO NOT INDENT THE << below! +# + +?MSC? +$(GAMEFILE) : $(LNKOPT) $(ALLOBJ) +?ENDMSC? +?BC? +$(GAMEFILE) : $(ALLOBJ) +?ENDBC? + @echo Linking.... + $(LINK) $(LFLAGSN) @<<$(GAME).lnk +?BC? + $(ALLOBJ) +?ENDBC? +?MSC? + $(ALLOBJ:^ =+^ + ) +?ENDMSC? + $(GAMEFILE) + $(GAME) + $(TERMLIB) $(MOVETR) $(CLIB) $(BCOVL) $(BCMDL) +?MSC? + $(LNKOPT); +?ENDMSC? +<< + @if exist $(GAMEDIR)\$(GAME).bak del $(GAMEDIR)\$(GAME).bak + +# +# Makedefs Stuff +# + +$(U)makedefs.exe: $(MAKEOBJS) + @$(LINK) $(LFLAGSU) $(MAKEOBJS), $@,, $(CLIB) $(BCMDL); + +$(O)makedefs.o: $(CONFIG_H) $(PERMONST_H) $(OBJCLASS_H) \ + $(MONSYM_H) $(QTEXT_H) $(PATCHLEVEL_H) \ + $(U)makedefs.c + @$(CC) $(CFLAGSU) $(COBJNAM)$@ $(U)makedefs.c + +# +# date.h should be remade every time any of the source or include +# files is modified. +# + +$(INCL)\date.h : $(U)makedefs.exe + $(U)makedefs -v + @echo A new $@ has been created. + +$(INCL)\onames.h : $(U)makedefs.exe + $(U)makedefs -o + +$(INCL)\pm.h : $(U)makedefs.exe + $(U)makedefs -p + +#$(INCL)\trap.h : $(U)makedefs.exe +# $(U)makedefs -t + +$(SRC)\monstr.c: $(U)makedefs.exe + $(U)makedefs -m + +$(INCL)\vis_tab.h: $(U)makedefs.exe + $(U)makedefs -z + +$(SRC)\vis_tab.c: $(U)makedefs.exe + $(U)makedefs -z + +# +# Level Compiler Stuff +# + +$(U)lev_comp.exe: $(SPLEVOBJS) + @echo Linking $@... +?MSC? + $(LINK) $(LFLAGSU) @<<$(@B).lnk +?ENDMSC? +?BC? + $(LINK) $(LFLAGSU) @&&! +?ENDBC? +?LINKLIST:SPLEVOBJS? + $@ + $(@B) + $(BCMDL); +?MSC? +<< +?ENDMSC? +?BC? +! +?ENDBC? + +$(O)lev_yacc.o: $(HACK_H) $(SP_LEV_H) $(INCL)\lev_comp.h $(U)lev_yacc.c + @$(CC) $(CFLAGSU) $(COBJNAM)$@ $(U)lev_yacc.c + +$(O)lev_$(LEX).o: $(HACK_H) $(INCL)\lev_comp.h $(SP_LEV_H) \ + $(U)lev_$(LEX).c + $(CC) $(CFLAGSU) $(COBJNAM)$@ $(U)lev_$(LEX).c + +$(O)lev_main.o: $(U)lev_main.c $(HACK_H) $(SP_LEV_H) + @$(CC) $(CFLAGSU) $(COBJNAM)$@ $(U)lev_main.c + +$(U)lev_yacc.c $(INCL)\lev_comp.h : $(U)lev_comp.y +! IF "$(DO_YACC)"=="YACC_ACT" + $(YACC) -d -l $(U)lev_comp.y + copy $(YTABC) $(U)lev_yacc.c + copy $(YTABH) $(INCL)\lev_comp.h + @del $(YTABC) + @del $(YTABH) +! ELSE + @echo. + @echo $(U)lev_comp.y has changed. + @echo To update $(U)lev_yacc.c and $(INCL)\lev_comp.h run $(YACC). + @echo. + @echo For now, we will copy the prebuilt lev_yacc.c + @echo from $(SYS) to $(U)lev_yacc.c, and copy the prebuilt + @echo lev_comp.h from $(SYS) to $(UTIL)\lev_comp.h + @echo and use those. + @echo. + copy $(SYS)\lev_yacc.c $@ >nul + touch $@ + copy $(SYS)\lev_comp.h $(INCL)\lev_comp.h >nul + touch $(INCL)\lev_comp.h +! ENDIF + +$(U)lev_$(LEX).c: $(U)lev_comp.l +! IF "$(DO_LEX)"=="LEX_ACT" + $(LEX) $(FLEXSKEL) $(U)lev_comp.l + copy $(LEXYYC) $@ + @del $(LEXYYC) +! ELSE + @echo. + @echo $(U)lev_comp.l has changed. To update $@ run $(LEX). + @echo. + @echo For now, we will copy a prebuilt lev_lex.c + @echo from $(SYS) to $@ and use it. + @echo. + copy $(SYS)\lev_lex.c $@ >nul + touch $@ +! ENDIF + +# +# Dungeon Stuff +# + +$(U)dgn_comp.exe: $(DGNCOMPOBJS) + @echo Linking $@... +?MSC? + $(LINK) $(LFLAGSU) @<<$(@B).lnk +?ENDMSC? +?BC? + $(LINK) $(LFLAGSU) @&&! +?ENDBC? +?LINKLIST:DGNCOMPOBJS? + $@ + $(@B) + $(BCMDL); +?MSC? +<< +?ENDMSC? +?BC? +! +?ENDBC? + +$(O)dgn_yacc.o: $(HACK_H) $(DGN_FILE_H) $(INCL)\dgn_comp.h \ + $(U)dgn_yacc.c + @$(CC) $(CFLAGSU) $(COBJNAM)$@ $(U)dgn_yacc.c + +$(O)dgn_$(LEX).o: $(HACK_H) $(DGN_FILE_H) $(INCL)\dgn_comp.h \ + $(U)dgn_$(LEX).c + @$(CC) $(CFLAGSU) $(COBJNAM)$@ $(U)dgn_$(LEX).c + +$(O)dgn_main.o: $(HACK_H) $(U)dgn_main.c + @$(CC) $(CFLAGSU) $(COBJNAM)$@ $(U)dgn_main.c + +$(U)dgn_yacc.c $(INCL)\dgn_comp.h : $(U)dgn_comp.y +! IF "$(DO_YACC)"=="YACC_ACT" + $(YACC) -d -l $(U)dgn_comp.y + copy $(YTABC) $(U)dgn_yacc.c + copy $(YTABH) $(INCL)\dgn_comp.h + @del $(YTABC) + @del $(YTABH) +! ELSE + @echo. + @echo $(U)dgn_comp.y has changed. To update $@ and + @echo $(INCL)\dgn_comp.h run $(YACC). + @echo. + @echo For now, we will copy the prebuilt dgn_yacc.c from + @echo $(SYS) to $(U)dgn_yacc.c, and copy the prebuilt + @echo dgn_comp.h from $(SYS) to $(INCL)\dgn_comp.h + @echo and use those. + @echo. + copy $(SYS)\dgn_yacc.c $@ >nul + touch $@ + copy $(SYS)\dgn_comp.h $(INCL)\dgn_comp.h >nul + touch $(INCL)\dgn_comp.h +! ENDIF + +$(U)dgn_$(LEX).c: $(U)dgn_comp.l +! IF "$(DO_LEX)"=="LEX_ACT" + $(LEX) $(FLEXSKEL) $(U)dgn_comp.l + copy $(LEXYYC) $@ + @del $(LEXYYC) +! ELSE + @echo. + @echo $(U)dgn_comp.l has changed. To update $@ run $(LEX). + @echo. + @echo For now, we will copy a prebuilt dgn_lex.c + @echo from $(SYS) to $@ and use it. + @echo. + copy $(SYS)\dgn_lex.c $@ >nul + touch $@ +! ENDIF + + +obj.tag: + @if not exist $(O)*.* mkdir $(OBJ) + @echo directory $(OBJ) created + @echo directory $(OBJ) created >$@ + +?MSC? +# +# The correct switches for the C compiler depend on the CL environment +# variable being set correctly. This will check that it is. +# The correct setting needs to be: +# CL= /AL /G2 /Oo /Gs /Gt16 /Zp1 /W0 /I..\include /nologo /DMOVERLAY +# + +?ENDMSC? +envchk: precomp.msg +?MSC? +! IF ("$(CL)"=="") +! MESSAGE The CL environment variable is not defined! +! MESSAGE You must CD $(MSYS) and execute the SETUP.BAT procedure +! MESSAGE ie. setup MSC +! MESSAGE +! ERROR +! ELSE + @echo CL Environment variable is defined: + @echo CL=$(CL) +! ENDIF +?ENDMSC? +?COMMENT? +# CL= /AL /G2 /Oo /Gs /Gt16 /Zp1 /W0 /I..\include /nologo /DMOVERLAY +?ENDCOMMENT? +?BC? +# +# Borland Configuration File Section +# + @echo Making Borland configuration files... + @echo -Y -O -Z -Oe -Ob -Os -Ff -I$(BCINCL);$(INCL) > $(BCCFG) + @echo -m$(MODEL) -D__IO_H $(CFLGTOT) -DSTRNCMPI >> $(BCCFG) + @type $(BCCFG) > CFLAGCO.CFG + @type $(BCCFG) > CFLAGUO.CFG + @type $(BCCFG) > CFLAGC0.CFG + @type $(BCCFG) > CFLAGU0.CFG + @type $(BCCFG) > CFLAGC1.CFG + @type $(BCCFG) > CFLAGU1.CFG + @type $(BCCFG) > CFLAGC2.CFG + @type $(BCCFG) > CFLAGU2.CFG + @type $(BCCFG) > CFLAGC3.CFG + @type $(BCCFG) > CFLAGU3.CFG + @type $(BCCFG) > CFLAGCB.CFG + @type $(BCCFG) > CFLAGUB.CFG + @echo -Y $(CFLAGCO) >> CFLAGCO.CFG + @echo -Y $(CFLAGUO) >> CFLAGUO.CFG + @echo -Y $(CFLAGC0) >> CFLAGC0.CFG + @echo -Y $(CFLAGU0) >> CFLAGU0.CFG + @echo -Y $(CFLAGC1) >> CFLAGC1.CFG + @echo -Y $(CFLAGU1) >> CFLAGU1.CFG + @echo -Y $(CFLAGC2) >> CFLAGC2.CFG + @echo -Y $(CFLAGU2) >> CFLAGU2.CFG + @echo -Y $(CFLAGC3) >> CFLAGC3.CFG + @echo -Y $(CFLAGU3) >> CFLAGU3.CFG + @echo -Y $(CFLAGCB) >> CFLAGCB.CFG + @echo -Y $(CFLAGUB) >> CFLAGUB.CFG +?ENDBC? +! IF "$(TILEGAME)"=="" + @echo. + @echo NOTE: This build will NOT include tile support. + @echo. +! ELSE + @echo. + @echo This build includes tile support. + @echo. +! ENDIF + +# +# SECONDARY TARGETS +# + +# +# Header files NOT distributed in ..\include +# + +$(INCL)\tile.h: $(WSHR)\tile.h + copy $(WSHR)\tile.h $@ + +$(INCL)\pctiles.h: $(MSYS)\pctiles.h + copy $(MSYS)\pctiles.h $@ + +$(INCL)\pcvideo.h: $(MSYS)\pcvideo.h + copy $(MSYS)\pcvideo.h $@ + +$(INCL)\portio.h: $(MSYS)\portio.h + copy $(MSYS)\portio.h $@ + +# +# Recover Utility +# + +$(U)recover.exe: $(RECOVOBJS) + @$(LINK) $(LFLAGSU) $(RECOVOBJS),$@,, $(CLIB) $(BCMDL); + +# +# Tile Mapping +# + +$(SRC)\tile.c: $(U)tilemap.exe + @echo A new $@ is being created. + @$(U)tilemap + +$(U)tilemap.exe: $(O)tilemap.o + @$(LINK) $(LFLAGSU) $(O)tilemap.o,$@,, $(CLIB) $(BCMDL); + +$(O)tilemap.o: $(WSHR)\tilemap.c $(HACK_H) + $(CC) $(CFLAGSU) $(COBJNAM)$@ $(WSHR)\tilemap.c + + +# +# Tile Utilities +# + +# +# Optional (for development) +# + + + +# + +$(U)gif2txt.exe: $(GIFREADERS) $(TEXT_IO) + @$(LINK) $(LFLAGSU) $(GIFREADERS) $(TEXT_IO),$@,, \ + $(CLIB) $(BCMDL); + +$(U)txt2ppm.exe: $(PPMWRITERS) $(TEXT_IO) + @$(LINK) $(LFLAGSU) $(PPMWRITERS) $(TEXT_IO),$@,, \ + $(CLIB) $(BCMDL); + +$(U)gif2txt2.exe: $(GIFREAD2) $(TEXT_IO2) + @$(LINK) $(LFLAGSU) $(GIFREAD2) $(TEXT_IO2),$@,, \ + $(CLIB) $(BCMDL); + +$(U)txt2ppm2.exe: $(PPMWRIT2) $(TEXT_IO2) + @$(LINK) $(LFLAGSU) $(PPMWRIT2) $(TEXT_IO2),$@,, \ + $(CLIB) $(BCMDL); + +# +# Required for tile support +# + +NetHack1.tib: $(TILEFILES) $(U)tile2bin.exe + @echo Creating binary tile files (this may take some time) + @$(U)tile2bin + +NetHackO.tib: thintile.tag $(TILEFILES2) $(U)til2bin2.exe + @echo Creating overview binary tile files (this may take some time) + @$(U)til2bin2 + +thintile.tag: $(U)thintile.exe $(TILEFILES) + $(U)thintile + @echo thintiles created >thintile.tag + +$(U)tile2bin.exe: $(O)tile2bin.o $(TEXT_IO) + @echo Linking $@... +?MSC? + $(LINK) $(LFLAGSU) @<<$(@B).lnk +?ENDMSC? +?BC? + $(LINK) $(LFLAGSU) @&&! +?ENDBC? + $(O)tile2bin.o+ +?LINKLIST:TEXT_IO? + $@ + $(@B) + $(BCMDL); +?MSC? +<< +?ENDMSC? +?BC? +! +?ENDBC? + +$(U)til2bin2.exe: $(O)til2bin2.o $(TEXT_IO2) + @echo Linking $@... +?MSC? + $(LINK) $(LFLAGSU) @<<$(@B).lnk +?ENDMSC? +?BC? + $(LINK) $(LFLAGSU) @&&! +?ENDBC? + $(O)til2bin2.o+ +?LINKLIST:TEXT_IO2? + $@ + $(@B) + $(BCMDL); +?MSC? +<< +?ENDMSC? +?BC? +! +?ENDBC? + + +$(U)thintile.exe: $(O)thintile.o + @$(LINK) $(LFLAGSU) $(O)thintile.o,$@,, $(CLIB) $(BCMDL); + +$(O)thintile.o: $(HACK_H) $(INCL)\tile.h $(WSHR)\thintile.c + $(CC) $(CFLAGSU) $(COBJNAM)$@ $(WSHR)\thintile.c + +$(O)tile2bin.o: $(HACK_H) $(TILE_H) $(PCVIDEO_H) + $(CC) $(CFLAGSU) $(COBJNAM)$@ $(MSYS)\tile2bin.c + +$(O)til2bin2.o: $(HACK_H) $(TILE_H) $(PCVIDEO_H) + $(CC) $(CFLAGSU) $(CDEFINE)TILE_X=8 $(CDEFINE)OVERVIEW_FILE \ + $(COBJNAM)$@ $(MSYS)\tile2bin.c + +?COMMENT? +$(U)tile2btb.exe: $(O)tile2btb.o $(GIFREADERS) + @echo Linking $@... + $(LINK) $(LFLAGSU) @&&! + $(O)tile2btb.o+ +?LINKLIST:GIFREADERS? + $@ + $(@B) + $(BCMDL) $(BGI_LIB); +! + +$(O)tile2btb.o: $(HACK_H) $(TILE_H) $(PCVIDEO_H) $(MSYS)\tile2btb.c + $(CC) -DBGI_FILE $(CFLAGSU) $(COBJNAM)$@ $(MSYS)\tile2btb.c +?ENDCOMMENT? + +# +# DLB stuff +# + +nhdat: $(U)dlb_main.exe + @copy $(MSYS)\msdoshlp.txt $(DAT) + @cd $(DAT) + @echo data >dlb.lst + @echo oracles >>dlb.lst + @echo options >>dlb.lst + @echo quest.dat >>dlb.lst + @echo rumors >>dlb.lst + @echo help >>dlb.lst + @echo hh >>dlb.lst + @echo cmdhelp >>dlb.lst + @echo history >>dlb.lst + @echo opthelp >>dlb.lst + @echo wizhelp >>dlb.lst + @echo dungeon >>dlb.lst + @echo license >>dlb.lst + @echo msdoshlp.txt >>dlb.lst + @for %%N in (*.lev) do echo %%N >>dlb.lst + $(U)dlb_main cvIf dlb.lst $(SRC)\nhdat + @cd $(SRC) + +$(U)dlb_main.exe: $(DLBOBJS) + @$(LINK) $(LFLAGSU) $(DLBOBJS),$@,, $(CLIB) $(BCMDL); + +$(O)dlb_main.o: $(U)dlb_main.c $(INCL)\config.h $(DLB_H) + $(CC) $(CFLAGSU) $(COBJNAM)$@ $(U)dlb_main.c + +# +# Housekeeping +# + +spotless: clean + rmdir $(OBJ) + if exist $(DATE_H) del $(DATE_H) + if exist $(INCL)\onames.h del $(INCL)\onames.h + if exist $(INCL)\pm.h del $(INCL)\pm.h + if exist $(VIS_TAB_H) del $(VIS_TAB_H) + if exist $(SRC)\vis_tab.c del $(SRC)\vis_tab.c + if exist $(SRC)\tile.c del $(SRC)\tile.c + if exist $(DAT)\rumors del $(DAT)\rumors + if exist $(DAT)\data del $(DAT)\data + if exist $(DAT)\dungeon del $(DAT)\dungeon + if exist $(DAT)\dungeon.pdf del $(DAT)\dungeon.pdf + if exist $(DAT)\options del $(DAT)\options + if exist $(DAT)\oracles del $(DAT)\oracles + if exist $(DAT)\rumors del $(DAT)\rumors + if exist $(DAT)\quest.dat del $(DAT)\quest.dat + if exist $(DAT)\*.lev del $(DAT)\*.lev + if exist $(DAT)\sp_lev.tag del $(DAT)\sp_lev.tag + if exist $(SRC)\monstr.c del $(SRC)\monstr.c + if exist $(SRC)\vis_tab.c del $(SRC)\vis_tab.c + if exist $(SRC)\$(PLANAR_TIB) del $(SRC)\$(PLANAR_TIB) + if exist $(SRC)\$(OVERVIEW_TIB) del $(SRC)\$(OVERVIEW_TIB) + if exist $(U)recover.exe del $(U)recover.exe + +clean: + if exist $(O)*.o del $(O)*.o + if exist $(O)*.0 del $(O)*.0 + if exist $(O)*.1 del $(O)*.1 + if exist $(O)*.2 del $(O)*.2 + if exist $(O)*.3 del $(O)*.3 + if exist $(O)*.b del $(O)*.b + if exist $(U)utility.tag del $(U)utility.tag + if exist $(U)makedefs.exe del $(U)makedefs.exe + if exist $(U)lev_comp.exe del $(U)lev_comp.exe + if exist $(U)dgn_comp.exe del $(U)dgn_comp.exe + if exist $(U)dlb_main.exe del $(U)dlb_main.exe + if exist $(SRC)\*.lnk del $(SRC)\*.lnk + if exist $(SRC)\*.map del $(SRC)\*.map + if exist $(SRC)\*$(CPCHEXT) del $(SRC)\*$(CPCHEXT) +?BC? + if exist $(SRC)\*.cfg del $(SRC)\*.cfg +?ENDBC? + if exist $(DAT)\dlb.lst del $(DAT)\dlb.lst + +pch.c: $(HACK_H) + @echo ^#include "hack.h" > $@ + @echo main(int argc, char *argv[]) >> $@ + @echo { >> $@ + @echo } >> $@ + @echo. >> $@ + +# +# OTHER DEPENDENCIES +# + +# +# Precompiled Header dependencies +# (We need to force the generation of these at the beginning) +# + +PHO$(CPCHEXT): $(HACK_H) pch.c + @echo Generating new precompiled header for .O files + @$(CC) $(FLAGCO) pch.c +PH0$(CPCHEXT): $(HACK_H) pch.c + @echo Generating new precompiled header for .0 files + @$(CC) $(FLAGC0) pch.c +PH1$(CPCHEXT): $(HACK_H) pch.c + @echo Generating new precompiled header for .1 files + @$(CC) $(FLAGC1) pch.c +PH2$(CPCHEXT): $(HACK_H) pch.c + @echo Generating new precompiled header for .2 files + @$(CC) $(FLAGC2) pch.c +PH3$(CPCHEXT): $(HACK_H) pch.c + @echo Generating new precompiled header for .3 files + @$(CC) $(FLAGC3) pch.c +PHB$(CPCHEXT): $(HACK_H) pch.c + @echo Generating new precompiled header for .B files + @$(CC) $(FLAGCB) pch.c + +?MSC? +# +# Compiler supplied, manually moved file - MOVEINIT.C. +# - This is only compiled if you selected the alternate overlay +# schema3. (MOVEAPI.H must reside in your include search list, +# and MOVEINIT.C must be in your src directory). The patch +# in sys/msdos/moveinit.pat must be applied to moveinit.c +# MS will not allow us to distribute an already patched version. + +$(O)moveinit.o: $(SRC)\moveinit.c + $(CC) $(CFLAGSN) $(COBJNAM)$@ $(MVTRCL) $(SRC)\moveinit.c + +$(SRC)\moveinit.c: + @echo. + @echo * CANNOT COMPLETE THE BUILD * + @echo You must manually copy moveinit.c and moveinit.h + @echo from your Microsoft C Compiler directory tree + @echo source/move directory and apply the sys/msdos/moveinit.pat + @echo patch to moveinit.c after doing so. + @echo. +?ENDMSC? + +?BC? +# Overlay initialization routines used by pcmain() at startup to +# determine EMS/XMS memory usage. + +# Comment out the following line if you don't want Borland C++ to check for +# extended memory. +RECOGNIZE_XMS = $(CDEFINE)RECOGNIZE_XMS + +?ENDBC? +?MSC? +# Overlay initialization routines used by MOVEINIT.C +?ENDMSC? + +$(O)ovlinit.o: $(MSYS)\ovlinit.c $(HACK_H) + $(CC) $(CFLAGSN) $(RECOGNIZE_XMS) $(COBJNAM)$@ $(MSYS)\ovlinit.c + +# +# dat dependencies +# + +$(DAT)\data: $(U)utility.tag $(DATABASE) + $(U)makedefs -d + +$(DAT)\rumors: $(U)utility.tag $(DAT)\rumors.tru $(DAT)\rumors.fal + $(U)makedefs -r + +$(DAT)\quest.dat: $(U)utility.tag $(DAT)\quest.txt + $(U)makedefs -q + +$(DAT)\oracles: $(U)utility.tag $(DAT)\oracles.txt + $(U)makedefs -h + +$(DAT)\dungeon: $(U)utility.tag $(DAT)\dungeon.def + $(U)makedefs -e + cd $(DAT) + $(U)dgn_comp dungeon.pdf + cd $(SRC) + +# +# Util Dependencies. +# + +$(O)panic.o: $(U)panic.c $(CONFIG_H) + $(CC) $(CFLAGSU) $(COBJNAM)$@ $(U)panic.c + +$(O)recover.o: $(CONFIG_H) $(U)recover.c + $(CC) $(CFLAGSU) $(COBJNAM)$@ $(U)recover.c + +# +# from win\share +# + +$(O)tiletxt.o: $(WSHR)\tilemap.c $(HACK_H) + $(CC) $(CFLAGSU) $(CDEFINE)TILETEXT $(COBJNAM)$@ $(WSHR)\tilemap.c + +$(O)tiletxt2.o: $(WSHR)\tilemap.c $(HACK_H) + $(CC) $(CFLAGSU) $(CDEFINE)TILETEXT \ + $(CDEFINE)TILE_X=8 $(COBJNAM)$@ $(WSHR)\tilemap.c + +$(O)gifread.o: $(WSHR)\gifread.c $(CONFIG_H) $(INCL)\tile.h + $(CC) $(CFLAGSU) $(COBJNAM)$@ $(WSHR)\gifread.c + +$(O)gifread2.o: $(WSHR)\gifread.c $(CONFIG_H) $(INCL)\tile.h + $(CC) $(CFLAGSU) $(COBJNAM)$@ $(CDEFINE)TILE_X=8 $(WSHR)\gifread.c + +$(O)ppmwrite.o: $(WSHR)\ppmwrite.c $(CONFIG_H) $(INCL)\tile.h + $(CC) $(CFLAGSU) $(COBJNAM)$@ $(WSHR)\ppmwrite.c + +$(O)ppmwrit2.o: $(WSHR)\ppmwrite.c $(CONFIG_H) $(INCL)\tile.h + $(CC) $(CFLAGSU) $(COBJNAM)$@ $(CDEFINE)TILE_X=8 $(WSHR)\ppmwrite.c + +$(O)tiletext.o: $(WSHR)\tiletext.c $(CONFIG_H) $(INCL)\tile.h + $(CC) $(CFLAGSU) $(COBJNAM)$@ $(WSHR)\tiletext.c + +$(O)tiletex2.o: $(WSHR)\tiletext.c $(CONFIG_H) $(INCL)\tile.h + $(CC) $(CFLAGSU) $(CDEFINE)TILE_X=8 $(COBJNAM)$@ $(WSHR)\tiletext.c + +# +# from win\tty +# + +$(O)getline.1: $(PCH1) $(WTTY)\getline.c $(HACK_H) $(WINTTY_H) $(FUNC_TAB_H) + $(CC) $(FLAGU1) ?[CSNAM1]$(COBJNAM)$@ $(WTTY)\getline.c + +$(O)getline.2: $(PCH2) $(WTTY)\getline.c $(HACK_H) $(WINTTY_H) $(FUNC_TAB_H) + $(CC) $(FLAGU2) ?[CSNAM2]$(COBJNAM)$@ $(WTTY)\getline.c + +$(O)termcap.0: $(PCH0) $(WTTY)\termcap.c $(HACK_H) $(WINTTY_H) $(TERMCAP_H) + $(CC) $(FLAGU0) ?[CSNAM0]$(COBJNAM)$@ $(WTTY)\termcap.c + +$(O)termcap.1: $(PCH1) $(WTTY)\termcap.c $(HACK_H) $(WINTTY_H) $(TERMCAP_H) + $(CC) $(FLAGU1) ?[CSNAM1]$(COBJNAM)$@ $(WTTY)\termcap.c + +$(O)termcap.B: $(PCHB) $(WTTY)\termcap.c $(HACK_H) $(WINTTY_H) $(TERMCAP_H) + $(CC) $(FLAGUB) ?[CSNAMB]$(COBJNAM)$@ $(WTTY)\termcap.c + +$(O)topl.1: $(PCH1) $(WTTY)\topl.c $(HACK_H) $(TERMCAP_H) $(WINTTY_H) + $(CC) $(FLAGU1) ?[CSNAM1]$(COBJNAM)$@ $(WTTY)\topl.c + +$(O)topl.2: $(PCH2) $(WTTY)\topl.c $(HACK_H) $(TERMCAP_H) $(WINTTY_H) + $(CC) $(FLAGU2) ?[CSNAM2]$(COBJNAM)$@ $(WTTY)\topl.c + +$(O)topl.B: $(PCHB) $(WTTY)\topl.c $(HACK_H) $(TERMCAP_H) $(WINTTY_H) + $(CC) $(FLAGUB) ?[CSNAMB]$(COBJNAM)$@ $(WTTY)\topl.c + +$(O)wintty.o: $(PCHO) $(CONFIG_H) $(WTTY)\wintty.c $(PATCHLEVEL_H) + $(CC) $(FLAGUO) ?[CSNAMOB]$(COBJNAM)$@ $(WTTY)\wintty.c + +# +# from sys\share +# + +$(O)pcmain.0: $(PCH0) $(HACK_H) $(SYS)\pcmain.c + $(CC) $(FLAGU0) ?[CSNAM0]$(COBJNAM)$@ $(SYS)\pcmain.c + +$(O)pcmain.1: $(PCH1) $(HACK_H) $(SYS)\pcmain.c + $(CC) $(FLAGU1) ?[CSNAM1]$(COBJNAM)$@ $(SYS)\pcmain.c + +$(O)pcmain.B: $(PCHB) $(HACK_H) $(SYS)\pcmain.c + $(CC) $(FLAGUB) ?[CSNAMB]$(COBJNAM)$@ $(SYS)\pcmain.c + +$(O)pcunix.B: $(PCHB) $(SYS)\pcunix.c $(HACK_H) + $(CC) $(FLAGUB) ?[CSNAMB]$(COBJNAM)$@ $(SYS)\pcunix.c + +$(O)tty.o: $(HACK_H) $(WINTTY_H) $(SYS)\pctty.c + $(CC) $(CFLAGSN) ?[CSNAMOB]$(COBJNAM)$@ $(SYS)\pctty.c + +$(O)sys.o: $(HACK_H) $(SYS)\pcsys.c + $(CC) $(CFLAGSN) ?[CSNAMOB]$(COBJNAM)$@ $(SYS)\pcsys.c + +$(O)random.o: $(PCHO) $(HACK_H) $(SYS)\random.c + $(CC) $(FLAGUO) ?[CSNAMOB]$(COBJNAM)$@ $(SYS)\random.c + +# +# from sys\msdos +# + +$(O)msdos.0: $(MSYS)\msdos.c $(HACK_H) $(PCVIDEO_H) +?BC? + $(CC) $(CFLAGSN) $(COVL0) $$($(@B)_0) $(COBJNAM)$@ $(MSYS)\msdos.c +?ENDBC? +?MSC? + $(CC) $(FLAGU0) $(CCSNAM)$(@F) $(COBJNAM)$@ $(MSYS)\msdos.c +?ENDMSC? +?COMMENT? + $(CC) $(CFLAGSN) $(COVL0) ?[CSNAM0]$(COBJNAM)$@ $(MSYS)\vidtxt.c +?ENDCOMMENT? + +$(O)msdos.B: $(MSYS)\msdos.c $(HACK_H) $(PCVIDEO_H) +?BC? + $(CC) $(CFLAGSN) $(COVLB) $$($(@B)_b) $(COBJNAM)$@ $(MSYS)\msdos.c +?ENDBC? +?MSC? + $(CC) $(FLAGUB) $(CCSNAM)$(@F) $(COBJNAM)$@ $(MSYS)\msdos.c +?ENDMSC? +?COMMENT? + $(CC) $(CFLAGSN) $(COVLB) ?[CSNAMB]$(COBJNAM)$@ $(MSYS)\vidtxt.c +?ENDCOMMENT? + +$(O)pctiles.0: $(PCH0) $(MSYS)\pctiles.c $(HACK_H) $(TILE_H) $(PCVIDEO_H) + $(CC) $(FLAGU0) ?[CSNAM0]$(COBJNAM)$@ $(MSYS)\pctiles.c + +$(O)pctiles.B: $(PCHB) $(MSYS)\pctiles.c $(HACK_H) $(TILE_H) $(PCVIDEO_H) + $(CC) $(FLAGUB) ?[CSNAMB]$(COBJNAM)$@ $(MSYS)\pctiles.c + +$(O)sound.o: $(PCH0) $(MSYS)\sound.c $(HACK_H) $(INCL)\portio.h + $(CC) $(FLAGUO) ?[CSNAMOB]$(COBJNAM)$@ $(MSYS)\sound.c + +$(O)pckeys.o: $(PCHO) $(MSYS)\pckeys.c $(HACK_H) $(PCVIDEO_H) + $(CC) $(FLAGUO) ?[CSNAMOB]$(COBJNAM)$@ $(MSYS)\pckeys.c + +$(O)stubvid.o : $(MSYS)\video.c $(HACK_H) + $(CC) $(FLAGUO) $(CDEFINE)STUBVIDEO ?[CSNAMOB]$(COBJNAM)$@ $(MSYS)\video.c + +$(O)video.0: $(PCH0) $(MSYS)\video.c $(HACK_H) $(WINTTY_H) $(PCVIDEO_H) \ + $(TILE_H) + $(CC) $(FLAGU0) ?[CSNAM0]$(COBJNAM)$@ $(MSYS)\video.c + +$(O)video.1: $(PCH1) $(MSYS)\video.c $(HACK_H) $(WINTTY_H) $(PCVIDEO_H) \ + $(TILE_H) + $(CC) $(FLAGU1) ?[CSNAM1]$(COBJNAM)$@ $(MSYS)\video.c + +$(O)video.B: $(PCHB) $(MSYS)\video.c $(HACK_H) $(WINTTY_H) $(PCVIDEO_H) \ + $(TILE_H) + $(CC) $(FLAGUB) ?[CSNAMB]$(COBJNAM)$@ $(MSYS)\video.c + +$(O)vidtxt.0: $(MSYS)\vidtxt.c $(HACK_H) $(WINTTY_H) $(PCVIDEO_H) +?BC? + $(CC) $(CFLAGSN) $(COVL0) $$($(@B)_0) $(COBJNAM)$@ $(MSYS)\vidtxt.c +?ENDBC? +?MSC? + $(CC) $(FLAGU0) $(CCSNAM)$(@F) $(COBJNAM)$@ $(MSYS)\vidtxt.c +?ENDMSC? +?COMMENT? + $(CC) $(CFLAGSN) $(COVL0) ?[CSNAM0]$(COBJNAM)$@ $(MSYS)\vidtxt.c +?ENDCOMMENT? + +$(O)vidtxt.B: $(MSYS)\vidtxt.c $(HACK_H) $(WINTTY_H) $(PCVIDEO_H) +?BC? + $(CC) $(CFLAGSN) $(COVLB) $$($(@B)_b) $(COBJNAM)$@ $(MSYS)\vidtxt.c +?ENDBC? +?MSC? + $(CC) $(FLAGUB) $(CCSNAM)$(@F) $(COBJNAM)$@ $(MSYS)\vidtxt.c +?ENDMSC? +?COMMENT? + $(CC) $(CFLAGSN) $(COVLB) ?[CSNAMB]$(COBJNAM)$@ $(MSYS)\vidtxt.c +?ENDCOMMENT? + +$(O)vidvga.0: $(PCH0) $(MSYS)\vidvga.c $(HACK_H) $(WINTTY_H) $(PCVIDEO_H) \ + $(TILE_H) + $(CC) $(FLAGU0) ?[CSNAM0]$(COBJNAM)$@ $(MSYS)\vidvga.c + +$(O)vidvga.1: $(PCH1) $(MSYS)\vidvga.c $(HACK_H) $(WINTTY_H) $(PCVIDEO_H) \ + $(TILE_H) + $(CC) $(FLAGU1) ?[CSNAM0]$(COBJNAM)$@ $(MSYS)\vidvga.c + +$(O)vidvga.2: $(PCH2) $(MSYS)\vidvga.c $(HACK_H) $(WINTTY_H) $(PCVIDEO_H) \ + $(TILE_H) + $(CC) $(FLAGU2) ?[CSNAM0]$(COBJNAM)$@ $(MSYS)\vidvga.c + +$(O)vidvga.B: $(PCHB) $(MSYS)\vidvga.c $(HACK_H) $(WINTTY_H) $(PCVIDEO_H) \ + $(TILE_H) + $(CC) $(FLAGUB) ?[CSNAMB]$(COBJNAM)$@ $(MSYS)\vidvga.c + +# +# from src +# + +$(O)alloc.o: $(SRC)\alloc.c $(CONFIG_H) + $(CC) $(CFLAGSN) ?[CSNAMOB]$(COBJNAM)$@ $(SRC)\alloc.c +$(O)ball.o: $(PCHO) $(SRC)\ball.c $(HACK_H) +$(O)bones.o: $(PCHO) $(SRC)\bones.c $(HACK_H) $(LEV_H) +$(O)decl.o: $(PCHO) $(SRC)\decl.c $(HACK_H) $(QUEST_H) +$(O)detect.o: $(PCHO) $(SRC)\detect.c $(HACK_H) $(ARTIFACT_H) +$(O)dig.o: $(PCHO) $(SRC)\dig.c $(HACK_H) $(EDOG_H) # check dep +$(O)display.o: $(PCHO) $(SRC)\display.c $(HACK_H) +$(O)dlb.o: $(SRC)\dlb.c $(DLB_H) $(HACK_H) + $(CC) $(CFLAGSN) ?[CSNAMOB]$(COBJNAM)$@ $(SRC)\dlb.c +$(O)dokick.o: $(PCHO) $(SRC)\dokick.c $(HACK_H) $(ESHK_H) +$(O)dothrow.o: $(PCHO) $(SRC)\dothrow.c $(HACK_H) +$(O)drawing.o: $(SRC)\drawing.c $(HACK_H) $(TERMCAP_H) + $(CC) $(CFLAGSN) ?[CSNAMOB]$(COBJNAM)$@ $(SRC)\drawing.c +$(O)end.o: $(SRC)\end.c $(HACK_H) $(ESHK_H) $(DLB_H) + $(CC) $(CFLAGSN) ?[CSNAMOB]$(COBJNAM)$@ $(SRC)\end.c +$(O)exper.o: $(PCHO) $(SRC)\exper.c $(HACK_H) +$(O)extralev.o: $(PCHO) $(SRC)\extralev.c $(HACK_H) +$(O)files.o: $(PCHO) $(SRC)\files.c $(HACK_H) $(DLB_H) +$(O)fountain.o: $(PCHO) $(SRC)\fountain.c $(HACK_H) +$(O)minion.o: $(PCHO) $(SRC)\minion.c $(HACK_H) $(EMIN_H) $(EPRI_H) +$(O)mklev.o: $(PCHO) $(SRC)\mklev.c $(HACK_H) +$(O)mkmap.o: $(PCHO) $(SRC)\mkmap.c $(HACK_H) $(SP_LEV_H) +$(O)mkmaze.o: $(PCHO) $(SRC)\mkmaze.c $(HACK_H) $(SP_LEV_H) $(LEV_H) +$(O)monst.o: $(SRC)\monst.c $(CONFIG_H) $(PERMONST_H) $(MONSYM_H) \ + $(ESHK_H) $(EPRI_H) $(COLOR_H) $(ALIGN_H) + $(CC) $(CFLAGSN) ?[CSNAMOB]$(COBJNAM)$@ $(SRC)\monst.c +$(O)monstr.o: $(SRC)\monstr.c $(CONFIG_H) + $(CC) $(CFLAGSN) ?[CSNAMOB]$(COBJNAM)$@ $(SRC)\monstr.c +$(O)mplayer.o: $(PCHO) $(SRC)\mplayer.c $(HACK_H) +$(O)muse.o: $(PCHO) $(SRC)\muse.c $(HACK_H) +$(O)music.o: $(PCHO) $(SRC)\music.c $(HACK_H) +$(O)o_init.o: $(PCHO) $(SRC)\o_init.c $(HACK_H) $(LEV_H) +$(O)objects.o: $(SRC)\objects.c $(CONFIG_H) $(OBJ_H) $(OBJCLASS_H) \ + $(PROP_H) $(COLOR_H) + $(CC) $(CFLAGSN) ?[CSNAMOB]$(COBJNAM)$@ $(SRC)\objects.c +$(O)options.o: $(SRC)\options.c $(HACK_H) $(TERMCAP_H) $(OBJCLASS_H) + $(CC) $(CFLAGSN) ?[CSNAMOB]$(COBJNAM)$@ $(SRC)\options.c +$(O)pager.o: $(SRC)\pager.c $(HACK_H) $(DLB_H) + $(CC) $(CFLAGNO) $(COBJNAM)$@ ?[CSNAMOA]$(SRC)\pager.c +$(O)pickup.o: $(PCHO) $(SRC)\pickup.c $(HACK_H) +$(O)pray.o: $(PCHO) $(SRC)\pray.c $(HACK_H) $(EPRI_H) +$(O)quest.o: $(PCHO) $(SRC)\quest.c $(HACK_H) $(QUEST_H) $(QTEXT_H) +$(O)questpgr.o: $(PCHO) $(SRC)\questpgr.c $(HACK_H) $(QTEXT_H) $(DLB_H) +$(O)rect.o: $(PCHO) $(SRC)\rect.c $(HACK_H) +$(O)region.o: $(PCHO) $(SRC)\region.c $(HACK_H) +$(O)restore.o: $(PCHO) $(SRC)\restore.c $(HACK_H) $(LEV_H) $(TERMCAP_H) \ + $(QUEST_H) +$(O)rip.o: $(PCHO) $(SRC)\rip.c $(HACK_H) +$(O)role.o: $(PCHO) $(SRC)\role.c $(HACK_H) +$(O)rumors.o: $(PCHO) $(SRC)\rumors.c $(HACK_H) $(DLB_H) +$(O)save.o: $(PCHO) $(SRC)\save.c $(HACK_H) $(LEV_H) $(QUEST_H) +$(O)sit.o: $(PCHO) $(SRC)\sit.c $(HACK_H) $(ARTIFACT_H) +$(O)steed.o: $(PCHO) $(SRC)\steed.c $(HACK_H) +$(O)sp_lev.o: $(PCHO) $(SRC)\sp_lev.c $(HACK_H) $(SP_LEV_H) $(DLB_H) +$(O)spell.o: $(PCHO) $(SRC)\spell.c $(HACK_H) +$(O)teleport.o: $(PCHO) $(SRC)\teleport.c $(HACK_H) # check dep +$(O)tile.o: $(PCHO) $(SRC)\tile.c $(HACK_H) +$(O)topten.o: $(PCHO) $(SRC)\topten.c $(HACK_H) $(DLB_H) $(PATCHLEVEL_H) +$(O)u_init.o: $(PCHO) $(SRC)\u_init.c $(HACK_H) +$(O)uhitm.o: $(PCHO) $(SRC)\uhitm.c $(HACK_H) +$(O)version.o: $(PCHO) $(SRC)\version.c $(HACK_H) $(PATCHLEVEL_H) +$(O)vision.o: $(PCHO) $(SRC)\vision.c $(HACK_H) $(VIS_TAB_H) +$(O)vis_tab.o: $(SRC)\vis_tab.c $(HACK_H) $(VIS_TAB_H) + $(CC) $(CFLAGSN) ?[CSNAMOB]$(COBJNAM)$@ $(SRC)\vis_tab.c +$(O)wield.o: $(PCHO) $(SRC)\wield.c $(HACK_H) +$(O)windows.o: $(PCHO) $(SRC)\windows.c $(HACK_H) $(WINTTY_H) +$(O)worm.o: $(PCHO) $(SRC)\worm.c $(HACK_H) $(LEV_H) +$(O)worn.o: $(PCHO) $(SRC)\worn.c $(HACK_H) +$(O)write.o: $(PCHO) $(SRC)\write.c $(HACK_H) + +# +# Overlays +# + +# OVL0 +# + +$(O)allmain.0: $(PCH0) $(SRC)\allmain.c $(HACK_H) +$(O)apply.0: $(PCH0) $(SRC)\apply.c $(HACK_H) $(EDOG_H) +$(O)artifact.0: $(PCH0) $(SRC)\artifact.c $(HACK_H) $(ARTIFACT_H) $(ARTILIST_H) +$(O)attrib.0: $(PCH0) $(SRC)\attrib.c $(HACK_H) +$(O)botl.0: $(PCH0) $(SRC)\botl.c $(HACK_H) +$(O)cmd.0: $(PCH0) $(SRC)\cmd.c $(HACK_H) $(FUNC_TAB_H) +$(O)dbridge.0: $(PCH0) $(SRC)\dbridge.c $(HACK_H) +$(O)do.0: $(PCH0) $(SRC)\do.c $(HACK_H) $(LEV_H) +$(O)do_name.0: $(PCH0) $(SRC)\do_name.c $(HACK_H) +$(O)do_wear.0: $(PCH0) $(SRC)\do_wear.c $(HACK_H) +$(O)dogmove.0: $(PCH0) $(SRC)\dogmove.c $(HACK_H) $(MFNDPOS_H) $(EDOG_H) +$(O)dungeon.0: $(PCH0) $(SRC)\dungeon.c $(HACK_H) $(ALIGN_H) $(DGN_FILE_H) \ + $(DLB_H) +$(O)eat.0: $(PCH0) $(SRC)\eat.c $(HACK_H) +$(O)engrave.0: $(PCH0) $(SRC)\engrave.c $(HACK_H) $(LEV_H) +$(O)explode.0: $(PCH0) $(SRC)\explode.c $(HACK_H) +$(O)hacklib.0: $(PCH0) $(SRC)\hacklib.c $(HACK_H) +$(O)invent.0: $(PCH0) $(SRC)\invent.c $(HACK_H) $(ARTIFACT_H) +$(O)lock.0: $(PCH0) $(SRC)\lock.c $(HACK_H) +$(O)mail.0: $(PCH0) $(SRC)\mail.c $(HACK_H) $(MAIL_H) $(PATCHLEVEL_H) +$(O)makemon.0: $(PCH0) $(SRC)\makemon.c $(HACK_H) $(EPRI_H) $(EMIN_H) +$(O)mcastu.0: $(PCH0) $(SRC)\mcastu.c $(HACK_H) +$(O)mhitm.0: $(PCH0) $(SRC)\mhitm.c $(HACK_H) $(ARTIFACT_H) $(EDOG_H) +$(O)mhitu.0: $(PCH0) $(SRC)\mhitu.c $(HACK_H) $(ARTIFACT_H) $(EDOG_H) +$(O)mkobj.0: $(PCH0) $(SRC)\mkobj.c $(HACK_H) $(ARTIFACT_H) $(PROP_H) +$(O)mkroom.0: $(PCH0) $(SRC)\mkroom.c $(HACK_H) +$(O)mon.0: $(PCH0) $(SRC)\mon.c $(HACK_H) $(MFNDPOS_H) $(EDOG_H) +$(O)mondata.0: $(PCH0) $(SRC)\mondata.c $(HACK_H) $(ESHK_H) $(EPRI_H) +$(O)monmove.0: $(PCH0) $(SRC)\monmove.c $(HACK_H) $(MFNDPOS_H) $(ARTIFACT_H) +$(O)mthrowu.0: $(PCH0) $(SRC)\mthrowu.c $(HACK_H) +$(O)objnam.0: $(PCH0) $(SRC)\objnam.c $(HACK_H) +$(O)polyself.0: $(PCH0) $(SRC)\polyself.c $(HACK_H) +$(O)priest.0: $(PCH0) $(SRC)\priest.c $(HACK_H) $(MFNDPOS_H) $(ESHK_H) \ + $(EPRI_H) $(EMIN_H) +$(O)rnd.0: $(PCH0) $(SRC)\rnd.c $(HACK_H) +$(O)shk.0: $(PCH0) $(SRC)\shk.c $(HACK_H) $(ESHK_H) +$(O)shknam.0: $(PCH0) $(SRC)\shknam.c $(HACK_H) $(ESHK_H) +$(O)sounds.0: $(PCH0) $(SRC)\sounds.c $(HACK_H) $(EDOG_H) +$(O)steal.0: $(PCH0) $(SRC)\steal.c $(HACK_H) +$(O)timeout.0: $(PCH0) $(SRC)\timeout.c $(HACK_H) $(LEV_H) +$(O)track.0: $(PCH0) $(SRC)\track.c $(HACK_H) +$(O)trap.0: $(PCH0) $(SRC)\trap.c $(HACK_H) +$(O)vault.0: $(PCH0) $(SRC)\vault.c $(HACK_H) $(VAULT_H) +$(O)weapon.0: $(PCH0) $(SRC)\weapon.c $(HACK_H) +$(O)were.0: $(PCH0) $(SRC)\were.c $(HACK_H) +$(O)wizard.0: $(PCH0) $(SRC)\wizard.c $(HACK_H) $(QTEXT_H) +$(O)zap.0: $(PCH0) $(SRC)\zap.c $(HACK_H) + +# +# OVL1 +# + +$(O)allmain.1: $(PCH1) $(SRC)\allmain.c $(HACK_H) +$(O)apply.1: $(PCH1) $(SRC)\apply.c $(HACK_H) $(EDOG_H) +$(O)artifact.1: $(PCH1) $(SRC)\artifact.c $(HACK_H) $(ARTIFACT_H) $(ARTILIST_H) +$(O)attrib.1: $(PCH1) $(SRC)\attrib.c $(HACK_H) +$(O)botl.1: $(PCH1) $(SRC)\botl.c $(HACK_H) +$(O)cmd.1: $(PCH1) $(SRC)\cmd.c $(HACK_H) $(FUNC_TAB_H) +$(O)dbridge.1: $(PCH1) $(SRC)\dbridge.c $(HACK_H) +$(O)do.1: $(PCH1) $(SRC)\do.c $(HACK_H) $(LEV_H) +$(O)do_wear.1: $(PCH1) $(SRC)\do_wear.c $(HACK_H) +$(O)dog.1: $(PCH1) $(SRC)\dog.c $(HACK_H) $(EDOG_H) +$(O)dungeon.1: $(PCH1) $(SRC)\dungeon.c $(HACK_H) $(ALIGN_H) $(DGN_FILE_H) $(DLB_H) +$(O)eat.1: $(PCH1) $(SRC)\eat.c $(HACK_H) +$(O)engrave.1: $(PCH1) $(SRC)\engrave.c $(HACK_H) $(LEV_H) +$(O)explode.1: $(PCH1) $(SRC)\explode.c $(HACK_H) +$(O)hack.1: $(PCH1) $(SRC)\hack.c $(HACK_H) +$(O)hacklib.1: $(PCH1) $(SRC)\hacklib.c $(HACK_H) +$(O)invent.1: $(PCH1) $(SRC)\invent.c $(HACK_H) $(ARTIFACT_H) +$(O)makemon.1: $(PCH1) $(SRC)\makemon.c $(HACK_H) $(EPRI_H) $(EMIN_H) +$(O)mhitu.1: $(PCH1) $(SRC)\mhitu.c $(HACK_H) $(ARTIFACT_H) $(EDOG_H) +$(O)mkobj.1: $(PCH1) $(SRC)\mkobj.c $(HACK_H) $(ARTIFACT_H) $(PROP_H) +$(O)mon.1: $(PCH1) $(SRC)\mon.c $(HACK_H) $(MFNDPOS_H) $(EDOG_H) +$(O)mondata.1: $(PCH1) $(SRC)\mondata.c $(HACK_H) $(ESHK_H) $(EPRI_H) +$(O)monmove.1: $(PCH1) $(SRC)\monmove.c $(HACK_H) $(MFNDPOS_H) $(ARTIFACT_H) +$(O)mthrowu.1: $(PCH1) $(SRC)\mthrowu.c $(HACK_H) +$(O)objnam.1: $(PCH1) $(SRC)\objnam.c $(HACK_H) +$(O)polyself.1: $(PCH1) $(SRC)\polyself.c $(HACK_H) +$(O)rnd.1: $(PCH1) $(SRC)\rnd.c $(HACK_H) +$(O)shk.1: $(PCH1) $(SRC)\shk.c $(HACK_H) $(ESHK_H) +$(O)steal.1: $(PCH1) $(SRC)\steal.c $(HACK_H) +$(O)timeout.1: $(PCH1) $(SRC)\timeout.c $(HACK_H) $(LEV_H) +$(O)track.1: $(PCH1) $(SRC)\track.c $(HACK_H) +$(O)trap.1: $(PCH1) $(SRC)\trap.c $(HACK_H) +$(O)weapon.1: $(PCH1) $(SRC)\weapon.c $(HACK_H) +$(O)zap.1: $(PCH1) $(SRC)\zap.c $(HACK_H) + +# +# OVL2 +# + +$(O)attrib.2: $(PCH2) $(SRC)\attrib.c $(HACK_H) +$(O)do.2: $(PCH2) $(SRC)\do.c $(HACK_H) $(LEV_H) +$(O)do_name.2: $(PCH2) $(SRC)\do_name.c $(HACK_H) +$(O)do_wear.2: $(PCH2) $(SRC)\do_wear.c $(HACK_H) +$(O)dog.2: $(PCH2) $(SRC)\dog.c $(HACK_H) $(EDOG_H) +$(O)engrave.2: $(PCH2) $(SRC)\engrave.c $(HACK_H) $(LEV_H) +$(O)hack.2: $(PCH2) $(SRC)\hack.c $(HACK_H) +$(O)hacklib.2: $(PCH2) $(SRC)\hacklib.c $(HACK_H) +$(O)invent.2: $(PCH2) $(SRC)\invent.c $(HACK_H) $(ARTIFACT_H) +$(O)makemon.2: $(PCH2) $(SRC)\makemon.c $(HACK_H) $(EPRI_H) $(EMIN_H) +$(O)mon.2: $(PCH2) $(SRC)\mon.c $(HACK_H) $(MFNDPOS_H) $(EDOG_H) +$(O)mondata.2: $(PCH2) $(SRC)\mondata.c $(HACK_H) $(ESHK_H) $(EPRI_H) +$(O)monmove.2: $(PCH2) $(SRC)\monmove.c $(HACK_H) $(MFNDPOS_H) $(ARTIFACT_H) +$(O)shk.2: $(PCH2) $(SRC)\shk.c $(HACK_H) $(ESHK_H) +$(O)trap.2: $(PCH2) $(SRC)\trap.c $(HACK_H) +$(O)zap.2: $(PCH2) $(SRC)\zap.c $(HACK_H) + +# +# OVL3 +# + +$(O)do.3: $(PCH3) $(SRC)\do.c $(HACK_H) $(LEV_H) +$(O)hack.3: $(PCH3) $(SRC)\hack.c $(HACK_H) +$(O)invent.3: $(PCH3) $(SRC)\invent.c $(HACK_H) $(ARTIFACT_H) +$(O)light.3: $(PCH3) $(SRC)\light.c $(HACK_H) +$(O)shk.3: $(PCH3) $(SRC)\shk.c $(HACK_H) $(ESHK_H) +$(O)trap.3: $(PCH3) $(SRC)\trap.c $(HACK_H) +$(O)zap.3: $(PCH3) $(SRC)\zap.c $(HACK_H) + +# +# OVLB +# + +$(O)allmain.B: $(PCHB) $(SRC)\allmain.c $(HACK_H) +$(O)apply.B: $(PCHB) $(SRC)\apply.c $(HACK_H) $(EDOG_H) +$(O)artifact.B: $(PCHB) $(SRC)\artifact.c $(HACK_H) $(ARTIFACT_H) $(ARTILIST_H) +$(O)attrib.B: $(PCHB) $(SRC)\attrib.c $(HACK_H) +$(O)botl.B: $(PCHB) $(SRC)\botl.c $(HACK_H) +$(O)cmd.B: $(PCHB) $(SRC)\cmd.c $(HACK_H) $(FUNC_TAB_H) +$(O)dbridge.B: $(PCHB) $(SRC)\dbridge.c $(HACK_H) +$(O)do.B: $(PCHB) $(SRC)\do.c $(HACK_H) $(LEV_H) +$(O)do_name.B: $(PCHB) $(SRC)\do_name.c $(HACK_H) +$(O)do_wear.B: $(PCHB) $(SRC)\do_wear.c $(HACK_H) +$(O)dog.B: $(PCHB) $(SRC)\dog.c $(HACK_H) $(EDOG_H) +$(O)dogmove.B: $(PCHB) $(SRC)\dogmove.c $(HACK_H) $(MFNDPOS_H) $(EDOG_H) +$(O)eat.B: $(PCHB) $(SRC)\eat.c $(HACK_H) +$(O)engrave.B: $(PCHB) $(SRC)\engrave.c $(HACK_H) $(LEV_H) +$(O)hack.B: $(PCHB) $(SRC)\hack.c $(HACK_H) +$(O)hacklib.B: $(PCHB) $(SRC)\hacklib.c $(HACK_H) +$(O)invent.B: $(PCHB) $(SRC)\invent.c $(HACK_H) $(ARTIFACT_H) +$(O)lock.B: $(PCHB) $(SRC)\lock.c $(HACK_H) +$(O)mail.B: $(PCHB) $(SRC)\mail.c $(HACK_H) $(MAIL_H) $(PATCHLEVEL_H) +$(O)makemon.B: $(PCHB) $(SRC)\makemon.c $(HACK_H) $(EPRI_H) $(EMIN_H) +$(O)mcastu.B: $(PCHB) $(SRC)\mcastu.c $(HACK_H) +$(O)mhitm.B: $(PCHB) $(SRC)\mhitm.c $(HACK_H) $(ARTIFACT_H) $(EDOG_H) +$(O)mhitu.B: $(PCHB) $(SRC)\mhitu.c $(HACK_H) $(ARTIFACT_H) $(EDOG_H) +$(O)mkobj.B: $(PCHB) $(SRC)\mkobj.c $(HACK_H) $(ARTIFACT_H) $(PROP_H) +$(O)mkroom.B: $(PCHB) $(SRC)\mkroom.c $(HACK_H) +$(O)mon.B: $(PCHB) $(SRC)\mon.c $(HACK_H) $(MFNDPOS_H) $(EDOG_H) +$(O)mondata.B: $(PCHB) $(SRC)\mondata.c $(HACK_H) $(ESHK_H) $(EPRI_H) +$(O)monmove.B: $(PCHB) $(SRC)\monmove.c $(HACK_H) $(MFNDPOS_H) $(ARTIFACT_H) +$(O)mthrowu.B: $(PCHB) $(SRC)\mthrowu.c $(HACK_H) +$(O)objnam.B: $(PCHB) $(SRC)\objnam.c $(HACK_H) +$(O)pline.B: $(SRC)\pline.c $(HACK_H) $(EPRI_H) + $(CC) $(CFLAGSN) ?[CSNAMB]$(COBJNAM)$@ $(SRC)\pline.c +$(O)polyself.B: $(PCHB) $(SRC)\polyself.c $(HACK_H) +$(O)potion.B: $(PCHB) $(SRC)\potion.c $(HACK_H) +$(O)priest.B: $(PCHB) $(SRC)\priest.c $(HACK_H) $(MFNDPOS_H) $(ESHK_H) \ + $(EPRI_H) $(EMIN_H) +$(O)read.B: $(PCHB) $(SRC)\read.c $(HACK_H) +$(O)rnd.B: $(PCHB) $(SRC)\rnd.c $(HACK_H) +$(O)shk.B: $(PCHB) $(SRC)\shk.c $(HACK_H) $(ESHK_H) +$(O)shknam.B: $(PCHB) $(SRC)\shknam.c $(HACK_H) $(ESHK_H) +$(O)sounds.B: $(PCHB) $(SRC)\sounds.c $(HACK_H) $(EDOG_H) +$(O)steal.B: $(PCHB) $(SRC)\steal.c $(HACK_H) +$(O)timeout.B: $(PCHB) $(SRC)\timeout.c $(HACK_H) $(LEV_H) +$(O)track.B: $(PCHB) $(SRC)\track.c $(HACK_H) +$(O)trap.B: $(PCHB) $(SRC)\trap.c $(HACK_H) +$(O)vault.B: $(PCHB) $(SRC)\vault.c $(HACK_H) $(VAULT_H) +$(O)weapon.B: $(PCHB) $(SRC)\weapon.c $(HACK_H) +$(O)were.B: $(PCHB) $(SRC)\were.c $(HACK_H) +$(O)wizard.B: $(PCHB) $(SRC)\wizard.c $(HACK_H) $(QTEXT_H) +$(O)zap.B: $(PCHB) $(SRC)\zap.c $(HACK_H) + +# end of file diff --git a/sys/msdos/tile2bin.c b/sys/msdos/tile2bin.c index 10049a8..ee4e894 100644 --- a/sys/msdos/tile2bin.c +++ b/sys/msdos/tile2bin.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)tile2bin.c 3.3 95/01/26 */ +/* SCCS Id: @(#)tile2bin.c 3.4 1995/01/26 */ /* Copyright (c) NetHack PC Development Team 1993, 1994, 1995 */ /* NetHack may be freely redistributed. See license for details. */ @@ -169,7 +169,7 @@ char *argv[]; # endif strncpy(tibheader.ident, - "NetHack 3.3 MSDOS Port binary tile file", 80); + "NetHack 3.4 MSDOS Port binary tile file", 80); strncpy(tibheader.timestamp, asctime(newtime), 24); tibheader.timestamp[25] = '\0'; tibheader.tilecount = tilecount; diff --git a/sys/msdos/video.c b/sys/msdos/video.c index e898a43..48460bb 100644 --- a/sys/msdos/video.c +++ b/sys/msdos/video.c @@ -1,15 +1,16 @@ -/* SCCS Id: @(#)video.c 3.3 95/08/05 */ -/* Copyright (c) NetHack PC Development Team 1993, 1994 */ +/* SCCS Id: @(#)video.c 3.4 2001/04/07 */ +/* Copyright (c) NetHack PC Development Team 1993, 1994, 2001 */ /* NetHack may be freely redistributed. See license for details. */ /* */ /* * video.c - Hardware video support front-ends * *Edit History: - * Initial Creation M. Allison 93/04/04 - * Add djgpp support K. Smolkowski 93/04/26 - * Add txt/graphics mode support M. Allison 93/10/30 - * Add graphics mode cursor sim. M. Allison 94/02/19 + * Initial Creation M. Allison 1993/04/04 + * Add djgpp support K. Smolkowski 1993/04/26 + * Add txt/graphics mode support M. Allison 1993/10/30 + * Add graphics mode cursor sim. M. Allison 1994/02/19 + * Add hooks for decals on vga M. Allison 2001/04/07 */ #include "hack.h" @@ -585,15 +586,16 @@ char ch; } void -xputg(glyphnum,ch) /* write out a glyph picture at current location */ +xputg(glyphnum,ch,special) /* write out a glyph picture at current location */ int glyphnum; int ch; +unsigned special; { if (!iflags.grmode || !iflags.tile_view) { xputc((char)ch); # ifdef SCREEN_VGA } else { - vga_xputg(glyphnum, ch); + vga_xputg(glyphnum, ch, special); # endif } } @@ -748,7 +750,7 @@ int assign_videoshades(char *choiceptr) { char choices[120]; char *cptr, *cvalue[3]; - int i,icolor; + int i,icolor = CLR_WHITE; strcpy(choices,choiceptr); cvalue[0] = choices; @@ -895,12 +897,8 @@ char *sopt; * getch(); */ iflags.grmode = 0; - iflags.hasvesa = 0; iflags.hasvga = 0; - iflags.has8514 = 0; - iflags.usevesa = 0; iflags.usevga = 0; - iflags.use8514 = 0; if (strncmpi(sopt,"def",3) == 0) { /* default */ /* do nothing - default */ @@ -937,11 +935,9 @@ char *sopt; # endif /* * Auto-detect Priorities (arbitrary for now): - * VESA, 8514, VGA + * VGA */ - if (iflags.hasvesa) iflags.usevesa = 1; - else if (iflags.has8514) iflags.use8514 = 1; - else if (iflags.hasvga) { + if (iflags.hasvga) { iflags.usevga = 1; /* VGA depends on BIOS to enable function keys*/ iflags.BIOS = 1; diff --git a/sys/msdos/vidtxt.c b/sys/msdos/vidtxt.c index 170c342..a41fd58 100644 --- a/sys/msdos/vidtxt.c +++ b/sys/msdos/vidtxt.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)vidtxt.c 3.3 94/04/04 */ +/* SCCS Id: @(#)vidtxt.c 3.4 1994/04/04 */ /* Copyright (c) NetHack PC Development Team 1993 */ /* NetHack may be freely redistributed. See license for details. */ /* */ @@ -31,9 +31,8 @@ # endif #endif -/* void FDECL(txt_xputc,(char, int)); /* write out character (and attribute) */ +/* void FDECL(txt_xputc,(char, int)); */ /* write out character (and attribute) */ -STATIC_VAR char buf[BUFSZ]; extern int attrib_text_normal; /* text mode normal attribute */ extern int attrib_gr_normal; /* graphics mode normal attribute */ extern int attrib_text_intense; /* text mode intense attribute */ diff --git a/sys/msdos/vidvga.c b/sys/msdos/vidvga.c index c17c550..caa997b 100644 --- a/sys/msdos/vidvga.c +++ b/sys/msdos/vidvga.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)vidvga.c 3.3 96/02/16 */ +/* SCCS Id: @(#)vidvga.c 3.4 1996/02/16 */ /* Copyright (c) NetHack PC Development Team 1995 */ /* NetHack may be freely redistributed. See license for details. */ /* @@ -108,7 +108,7 @@ # include # endif -/* STATIC_DCL void FDECL(vga_NoBorder, (int)); /* */ +/* STATIC_DCL void FDECL(vga_NoBorder, (int)); */ void FDECL(vga_gotoloc, (int,int)); /* This should be made a macro */ void NDECL(vga_backsp); #ifdef SCROLLMAP @@ -116,6 +116,7 @@ STATIC_DCL void FDECL(vga_scrollmap,(BOOLEAN_P)); #endif STATIC_DCL void FDECL(vga_redrawmap,(BOOLEAN_P)); void FDECL(vga_cliparound,(int, int)); +STATIC_OVL void FDECL(decal_planar,(struct planar_cell_struct *, unsigned)); #ifdef POSITIONBAR STATIC_DCL void NDECL(positionbar); @@ -139,23 +140,25 @@ extern boolean inmap; /* in the map window */ STATIC_VAR unsigned char __far *font; STATIC_VAR char *screentable[SCREENHEIGHT]; -STATIC_VAR char tmp[SCREENWIDTH]; + STATIC_VAR char *paletteptr; STATIC_VAR struct map_struct { int glyph; int ch; int attr; + unsigned special; } map[ROWNO][COLNO]; /* track the glyphs */ # define vga_clearmap() { int x,y; for (y=0; y < ROWNO; ++y) \ for (x=0; x < COLNO; ++x) { map[y][x].glyph = cmap_to_glyph(S_stone); \ - map[y][x].ch = S_stone; map[y][x].attr = 0;} } + map[y][x].ch = S_stone; map[y][x].attr = 0; map[y][x].special = 0;} } # define TOP_MAP_ROW 1 # if defined(OVLB) STATIC_VAR int vgacmap[CLR_MAX] = {0,3,5,9,4,8,12,14,11,2,6,7,1,8,12,13}; STATIC_VAR int viewport_size = 40; -STATIC_VAR char masktable[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; -STATIC_VAR char bittable[8]= {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; +/* STATIC_VAR char masktable[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; */ +/* STATIC_VAR char bittable[8]= {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; */ +#if 0 STATIC_VAR char defpalette[] = { /* Default VGA palette */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, @@ -174,6 +177,8 @@ STATIC_VAR char defpalette[] = { /* Default VGA palette */ 0xff, 0x00, 0xff, 0xff, 0xff, 0xff }; +#endif + # ifndef ALTERNATE_VIDEO_METHOD int vp[SCREENPLANES] = {8,4,2,1}; # endif @@ -195,10 +200,10 @@ STATIC_VAR struct overview_planar_cell_struct *planecell_O; # if defined(USE_TILES) STATIC_VAR struct tibhdr_struct tibheader; -/* extern FILE *tilefile; /* Not needed in here most likely */ +/* extern FILE *tilefile; */ /* Not needed in here most likely */ # endif -/* STATIC_VAR int g_attribute; /* Current attribute to use */ +/* STATIC_VAR int g_attribute; */ /* Current attribute to use */ #ifdef OVLB void @@ -378,29 +383,34 @@ int attr; # if defined(USE_TILES) void -vga_xputg(glyphnum,ch) /* Place tile represent. a glyph at current location */ +vga_xputg(glyphnum,ch, special) /* Place tile represent. a glyph at current location */ int glyphnum; int ch; +unsigned special; /* special feature: corpse, invis, detected, pet, ridden - hack.h */ { int col,row; int attr; + int ry; row = currow; col = curcol; if ((col < 0 || col >= COLNO) || (row < TOP_MAP_ROW || row >= (ROWNO + TOP_MAP_ROW))) return; - map[row - TOP_MAP_ROW][col].glyph = glyphnum; - map[row - TOP_MAP_ROW][col].ch = ch; + ry = row - TOP_MAP_ROW; + map[ry][col].glyph = glyphnum; + map[ry][col].ch = ch; + map[ry][col].special = special; attr = (g_attribute == 0) ? attrib_gr_normal : g_attribute; - map[row - TOP_MAP_ROW][col].attr = attr; + map[ry][col].attr = attr; if (iflags.traditional_view) { vga_WriteChar((unsigned char)ch,col,row,attr); } else if (!iflags.over_view) { if ((col >= clipx) && (col <= clipxmax)) { - if (!ReadPlanarTileFile(glyph2tile[glyphnum], &planecell)) + if (!ReadPlanarTileFile(glyph2tile[glyphnum], &planecell)) { + if (map[ry][col].special) decal_planar(planecell, special); vga_DisplayCell(planecell, col - clipx, row); - else + } else pline("vga_xputg: Error reading tile (%d,%d) from file", glyphnum,glyph2tile[glyphnum]); } @@ -469,7 +479,7 @@ boolean clearfirst; int j,x,y,t; char __far *pch; char volatile a; - + if (clearfirst) { /* y here is in pixel rows */ outportb(0x3ce,5); @@ -508,6 +518,8 @@ boolean clearfirst; if (!iflags.over_view) { if (!ReadPlanarTileFile(glyph2tile[t], &planecell)) { + if (map[y][x].special) + decal_planar(planecell, map[y][x].special); vga_DisplayCell(planecell, x - clipx, y + TOP_MAP_ROW); } else @@ -648,7 +660,8 @@ boolean left; for (y = 0; y < ROWNO; ++y) { for (x = i; x < j; x += 2) { t = map[y][x].glyph; - if (!ReadPlanarTileFile(glyph2tile[t], &planecell)) + if (!ReadPlanarTileFile(glyph2tile[t], &planecell)) + if (map[y][x].special) decal_planar(planecell, map[y][x].special); vga_DisplayCell(planecell, x - clipx, y + TOP_MAP_ROW); else pline("vga_shiftmap: Error reading tile (%d,%d)", @@ -660,6 +673,18 @@ boolean left; # endif /* OVL2 */ # ifdef OVLB +STATIC_OVL void +decal_planar(gp, special) +struct planar_cell_struct *gp; +unsigned special; +{ + if (special & MG_CORPSE) { + } else if (special & MG_INVIS) { + } else if (special & MG_DETECT) { + } else if (special & MG_PET) { + } else if (special & MG_RIDDEN) { + } +} /* * Open tile files, @@ -670,7 +695,7 @@ boolean left; */ void vga_Init(void) { - int i, c; + int i; # ifdef USE_TILES int tilefailure = 0; @@ -692,7 +717,7 @@ void vga_Init(void) iflags.over_view = FALSE; CO = 80; LI = 25; -/* clear_screen() /* not vga_clear_screen() */ +/* clear_screen() */ /* not vga_clear_screen() */ return; } # endif @@ -704,7 +729,7 @@ void vga_Init(void) } vga_SwitchMode(MODE640x480); windowprocs.win_cliparound = vga_cliparound; -/* vga_NoBorder(BACKGROUND_VGA_COLOR); /* Not needed after palette mod */ +/* vga_NoBorder(BACKGROUND_VGA_COLOR); */ /* Not needed after palette mod */ # ifdef USE_TILES paletteptr = tibheader.palette; iflags.tile_view = TRUE; @@ -854,7 +879,7 @@ int chr,col,row,colour; { int i; int x,pixy; - int floc; + char volatile tc; char __far *cp; unsigned char __far *fp = font; @@ -864,7 +889,7 @@ int chr,col,row,colour; x = min(col,(CO-1)); /* min() used protection from callers */ pixy = min(row,(LI-1)) * 16; /* assumes 8 x 16 char set */ -/* if (chr < ' ') chr = ' '; /* assumes ASCII set */ +/* if (chr < ' ') chr = ' '; */ /* assumes ASCII set */ outportb(0x3ce,5); outportb(0x3cf,2); @@ -1013,7 +1038,7 @@ vga_SetPalette(p) } } -/*static unsigned char colorbits[]={0x01,0x02,0x04,0x08}; /* wrong */ +/*static unsigned char colorbits[]={0x01,0x02,0x04,0x08}; */ /* wrong */ static unsigned char colorbits[]={0x08,0x04,0x02,0x01}; #ifdef POSITIONBAR @@ -1042,7 +1067,7 @@ positionbar() int feature, ucol; int k, y, colour, row; char __far *pch; - char bitblock; + int startk, stopk; char volatile a; boolean nowhere = FALSE; @@ -1138,7 +1163,7 @@ void vga_special(chr,col,color) int chr,col,color; { - int i,y,pixx,pixy; + int i,y,pixy; char __far *tmp_d; /* destination pointer */ int vplane; char fnt; diff --git a/sys/os2/Install.os2 b/sys/os2/Install.os2 index e0e7651..aafd0fa 100644 --- a/sys/os2/Install.os2 +++ b/sys/os2/Install.os2 @@ -1,4 +1,4 @@ - Instructions for compiling and installing NetHack 3.3 + Instructions for compiling and installing NetHack 3.4 on an OS/2 system ===================================================== Timo Hakulinen @@ -51,7 +51,7 @@ Note that code compiled for OS/2 versions 1.0-1.3 runs unmodified in OS/2 versions 2.0 and up. In principle it should be possible to cross compile - NetHack 3.3 for OS/2 in DOS using NDMAKE and MSC, but this is not + NetHack 3.4 for OS/2 in DOS using NDMAKE and MSC, but this is not recommended (see note 3). If you're using some other compiler than one listed above, you will have @@ -171,7 +171,7 @@ soko4-2.lev tower1.lev tower2.lev tower3.lev valley.lev water.lev wizard1.lev wizard2.lev wizard3.lev wizhelp - Yes. It's 112 files for a full featured NetHack 3.3. If any of the files + Yes. It's 112 files for a full featured NetHack 3.4. If any of the files are missing, try to rerun make. If that doesn't help, you'll have to try to decipher the makefile to find out how to manually create the missing files. These kinds of troubles shouldn't happen except for two reasons: @@ -181,7 +181,7 @@ If you have old record, logfile, or news files in the game directory, they are not overwritten. Of course, old records from NetHack 3.1 and 3.2 are - not worth keeping with 3.3, since these games are really quite different. + not worth keeping with 3.4, since these games are really quite different. Edit file nethack.cnf in the game directory to reflect your particular setup and personal preferences, following the comments there. More info @@ -199,7 +199,7 @@ The following is a sample program description for OS/2 1.3 desktop, but it's similar for OS/2 2.0: - Program title: NetHack 3.3 + Program title: NetHack 3.4 Path and file name: c:\games\nh33\nethack.cmd Parameters: Working directory: c:\games\nh33 @@ -226,7 +226,7 @@ Notes ----- 1) Save-files and bones-files from previous versions will not work with - NetHack 3.3. Don't bother trying to keep them. + NetHack 3.4. Don't bother trying to keep them. 2) To install an update of NetHack after changing something, enter "make" from the src directory. If you add, delete, or reorder monsters or diff --git a/sys/os2/Makefile.os2 b/sys/os2/Makefile.os2 index 58fda2b..5390662 100644 --- a/sys/os2/Makefile.os2 +++ b/sys/os2/Makefile.os2 @@ -1,12 +1,12 @@ -# SCCS Id: @(#)Makefile.os2 3.3 96/10/29 -# OS/2 NetHack 3.3 Makefile for OS/2 versions 1.x and 2.x +# SCCS Id: @(#)Makefile.os2 3.4 1996/10/29 +# OS/2 NetHack 3.4 Makefile for OS/2 versions 1.x and 2.x # Copyright (C) 1990, 1991, 1992, 1993, 1996 Timo Hakulinen # -# The supported compilers list is mainly from the NetHack 3.1 era. -# There should be newer versions of all these compilers nowadays. +# Several compilers exist for OS/2 but, currently only GCC emx is tested +# and used for releases. make programs other than dmake are not tested +# and the support is left here for historic purposes. # -# Supported compilers: Microsoft C 5.1 and 6.0A, GCC emx 0.8f, -# GCC emx 0.9c, IBM C Set/2 1.00 with Toolkit/2 2.00, IBM CSet++ 2.01. +# Supported compilers: GCC emx 0.9g # # NDMAKE ver 4.5, Microsoft/IBM NMAKE, or Dennis Vadura's DMAKE is # required; old MS-MAKE will not work. To enable the appropriate @@ -25,18 +25,9 @@ # $(SRC). If required, termcap library can be built from termcap # sources using makefile.lib in "sys\share" directory. # -# "MSC" in this makefile refers to Microsoft C 5.1 and 6.0A. -# Whenever the distinction is significant, it is indicated. -# # "GCC" refers to GCC emx only. No other ports of GCC are supported. # Additional credits for honing GCC support for 3.2 go to Ronald -# Van Iwaarden (rrt0136@ibm.net) and Stefan Neis (neis@cs.uni-sb.de). -# -# "CSet/2" refers to both older CSet/2 ver 1 (IBM 32 bit C compiler for -# OS/2 2.0) and newer CSet++ ver 2 (C/C++ compiler). Original CSet/2 -# support courtesy Jeff Urlwin (jurlwin@gandalf.umcs.maine.edu). -# CSet++ support courtesy Helge Hafting (hhafting@intermec.no) and -# Justin Frank (belford-manor@worldnet.att.net). +# Van Iwaarden (ron@vaniwaarden.org) and Stefan Neis (neis@cs.uni-sb.de). # # "OMF" is short for "Object Module Format" and refers to the # standard OS/2 object format, which e.g. link386 uses. MSC and @@ -57,12 +48,41 @@ # Compiler and linker selection. # -#CC = cl # MSC CC = gcc # GCC -#CC = icc # CSet/2 -#LINK = link # MSC -LINK = link386 # GCC OMF, CSet/2 +LINK = gcc +#LINK = link386 # GCC OMF, CSet/2 + +# +# Uncomment the following to compile for X11 and set X11ROOT apropriately +# +#WINX11OBJ01 = $(OBJ)/Window.o +#WINX11OBJ02 = $(OBJ)/dialogs.o +#WINX11OBJ03 = $(OBJ)/winX.o +#WINX11OBJ04 = $(OBJ)/winmap.o +#WINX11OBJ05 = $(OBJ)/winmenu.o +#WINX11OBJ06 = $(OBJ)/winmesg.o +#WINX11OBJ07 = $(OBJ)/winmisc.o +#WINX11OBJ08 = $(OBJ)/winstat.o +#WINX11OBJ09 = $(OBJ)/wintext.o +#WINX11OBJ10 = $(OBJ)/winval.o +#WINX11OBJ11 = $(OBJ)/tile.o +#X11ROOT = e:/xfree86 +#WINX11CFLAGS = -DUSE_XPM -DX11_GRAPHICS \ +# -I$(X11ROOT)/include -Zmtd +#WINX11LIB = -lXaw -lXmu -lXext -lXt -lX11 -lXpm -L$(X11ROOT)/lib -lc_app +#WINX11SRC = ../win/X11/Window.c ../win/X11/dialogs.c ../win/X11/winX.c \ +# ../win/X11/winmap.c ../win/X11/winmenu.c ../win/X11/winmesg.c \ +# ../win/X11/winmisc.c ../win/X11/winstat.c ../win/X11/wintext.c \ +# ../win/X11/winval.c tile.c +#WINX11OBJ = $(WINX11OBJ01) $(WINX11OBJ02) $(WINX11OBJ03) $(WINX11OBJ04) \ +# $(WINX11OBJ05) $(WINX11OBJ06) $(WINX11OBJ07) $(WINX11OBJ08) \ +# $(WINX11OBJ09) $(WINX11OBJ10) $(WINX11OBJ11) +#WINX11VARDAT=x11tiles pet_mark.xbm rip.xpm +#X11ECHO = $(CMD) @echo + + + # # Make syntax peculiarities. @@ -148,7 +168,7 @@ LEXYYC = lexyy.c # Source tree base directory. # -NHSRC = \nethack\3.3.1\uunet +NHSRC = \nethack # # Source directories. Makedefs hardcodes these, don't change them. @@ -160,8 +180,10 @@ DOC = $(NHSRC)\doc # NetHack documentation files UTIL = $(NHSRC)\util # Utility source SRC = $(NHSRC)\src # Main source WIN = $(NHSRC)\win\tty # Window system specific source +WINX11 = $(NHSRC)\win\x11 # Window system specific source SYS = $(NHSRC)\sys\os2 # System specific source SSYS = $(NHSRC)\sys\share # Shared system files +WINSHARE= $(NHSRC)\win\share # Shared system files # # Modifiable directories. Set these according to your setup and @@ -175,53 +197,27 @@ SSYS = $(NHSRC)\sys\share # Shared system files OBJ = \tmp\obj # Object files TEMP = \tmp\bin # Temporary files during make process -GAMEDIR = \games\nh331 # Game directory +GAMEDIR = \games\nh34 # Game directory PLIBP = c:\emx\lib # Protected mode C libraries RLIBP = c:\emx\lib # Possible real mode C libraries -TLIBP = \toolkt20\os2lib # CSet/2 Toolkit libpath (OS2386.LIB) - # # The game name and description. # GAME = nethack -GAMEDES = "NetHack 3.3.1" - -# -# Only if you're using CSet/2. Define the upper line for ver. 1, -# the lower one for ver. 2 (= CSet++). -# - -#CSETVER = /DOS2_CSET2_VER_1 -CSETVER = /DOS2_CSET2_VER_2 +GAMEDES = "NetHack 3.4" # # The uppermost two lines for MSC, the middle two for GCC, and # the lowermost two for CSet/2. # -# MSC: compile only, compiler id, large memory model, optimization level, -# remove stack probes, 80286 instruction set, dedicated datasegment for -# items >= 10 bytes, pack structures on 1 byte boundaries, generate code -# for 8087 coprocessor, compiler warning level, include file path, invoke -# large model compiler, debug flags, ANSI conformance. -# # GCC: compile only, compiler id, object format selection, warnings, # include file path, debug flags, ANSI conformance. # -# CSet/2: compile only, compiler id, migration lib, remove stack probes, -# large 32 bit memory model, fast integer code, optimize (to avoid a -# compiler bug - sometimes it *does* work that way around), don't print -# IBM logo, force optlink linkage on function calls, warning level, -# include file path, debug flags, ANSI conformance. -# -#CFLAGS = /c /DOS2_MSC /AL /O /Gs /G2 /Gt10 /Zp1 /FPi $(WARN) /I$(INCL) $(BIGC) $(CDFLAGS) $(STDC) -#O = /Fo -CFLAGS = -c -DOS2_GCC $(GCCO) $(WARN) -I$(INCL) $(CDFLAGS) $(STDC) +CFLAGS = -c $(GCCO) $(WARN) -I$(INCL) $(CDFLAGS) $(STDC) $(WINX11CFLAGS) O = -s -O -o -#CFLAGS = /c /DOS2_CSET2 $(CSETVER) /Sm /Gs+ /Gt- /Gi+ /O+ /Q+ /Mp $(WARN) /I$(INCL) $(CDFLAGS) $(STDC) -#O = /Fo # # Compiler warning levels. These are really for development, so @@ -229,29 +225,21 @@ O = -s -O -o # from masses of benign warnings. If any problems arise, however, # they may help in finding the trouble. # -# MSC: warning level 3 is highest in 5.1, second highest in 6.0. -# Cries a lot, but for no real cause. Warning level 0 for distribution. -# # GCC: max. reasonable GCC warning levels. Can't use -Wall, because then # it would whine about all the zillions of unused declarations etc. # Even with these switches you'll get a lot of warnings, but they should # all be benign. # -# CSet/2: warning level 3. The second optional parameter gives -# lots of extra warnings. -# -#WARN = /W0 #/W3 # MSC WARN = #-W -Wimplicit -Wreturn-type -Wunused -Wformat -Wswitch -Wshadow -Wcast-qual -Wwrite-strings -DGCC_WARN # GCC -#WARN = #/W3 #/Kbper # CSet/2 # # GCC object format selection. The upper line for standard OS/2 OMF # object format, the lower for Unix style a.out format. # -GCCO = -Zomf -Zsys # GCC OMF -#GCCO = # GCC a.out +#GCCO = -Zomf -Zsys # GCC OMF +GCCO = # GCC a.out # # MSC 5.1 needs the large model first pass of the compiler. @@ -259,7 +247,6 @@ GCCO = -Zomf -Zsys # GCC OMF # BIGC = -#BIGC = /B1 d:\binb\c1l.exe # MSC 5.1 # # Unset CL to avoid troubles with conflicting switches in MSC 6.0. @@ -267,56 +254,31 @@ BIGC = CL = -# -# MSC, CSet/2: don't ignore case in symbols, no default lib search, -# stack 8KB, allow max 1024 segments in program. -# -# GCC: likes a big stack. -# -# CSet/2: give it a bit more stack since we can. -# - -#LFLAGS = /noig /nod /stack:8192 /seg:1024 $(LDFLAGS) # MSC -LFLAGS = /noig /stack:40000 # GCC OMF -#LFLAGS = /noig /nod /stack:32768 /seg:1024 $(LDFLAGS) # CSet/2 - # # Prepare for a debugger. # CDFLAGS = LDFLAGS = -#CDFLAGS = /Zi # CodeView (MSC) -#LDFLAGS = /CO # - " - -#CDFLAGS = -g # GDB (GCC a.out) -#LDFLAGS = -g # - " - -#CDFLAGS = /Ti+ # IPMD (CSet/2) -#LDFLAGS = /CO # - " - +CDFLAGS = -g # GDB (GCC a.out) +LDFLAGS = -g # - " - # # How to produce the most ANSI-like environment. # -#STDC = # MSC 5.1 -STDC = /D__STDC__ # MSC 6.0, CSet/2 STDC = -ansi # GCC # # Possible system object files required during linking. # -#SYSOBJ = # MSC, GCC a.out, CSet/2 -SYSOBJ = $(PLIBP)\crt0.obj $(PLIBP)\end.lib# GCC OMF +SYSOBJ = # MSC, GCC a.out, CSet/2 +#SYSOBJ = $(PLIBP)\crt0.obj $(PLIBP)\end.lib# GCC OMF # # Compiler library selection. Change if necessary. # -# MSC: Protected mode C libraries for 8087 emulator, -# OS/2 API entry points. -# -# GCC emx 0.8 OMF: C standard lib, extra GCC lib, static system lib, -# OS/2 API entry points. -# # GCC emx 0.9 OMF: C single-threaded libs, Unix system call alias lib, # extra GCC lib, single threaded system lib, OS/2 API entry points. # Note that emx changed library naming convention between 0.8 and 0.9. @@ -324,17 +286,9 @@ SYSOBJ = $(PLIBP)\crt0.obj $(PLIBP)\end.lib# GCC OMF # GCC a.out: extra GCC lib, C standard lib, extra GCC lib (again), # OS/2 API entry points. # -# CSet/2: C standard libraries, OS/2 API entry points. -# Note that ver 1 needs lib dde4sbm.lib whereas ver 2 doesn't. -# -#PLIBS = $(PLIBP)\llibcep $(PLIBP)\doscalls # MSC 5.1 -#PLIBS = $(PLIBP)\llibcep $(PLIBP)\os2 # MSC 6.0 -#PLIBS = $(PLIBP)\libc $(PLIBP)\libgcc $(PLIBP)\libsys $(PLIBP)\libos2 # GCC emx 0.8 OMF -PLIBS = $(PLIBP)\st\c $(PLIBP)\st\c_app $(PLIBP)\c_alias $(PLIBP)\gcc $(PLIBP)\st\sys $(PLIBP)\os2 # GCC emx 0.9 OMF -#PLIBS = -lgcc -lc -lgcc -los2 # GCC a.out (defining -lgcc twice is required) -#PLIBS = $(PLIBP)\dde4sbs.lib $(PLIBP)\dde4sbm.lib $(TLIBP)\os2386.lib # CSet/2 ver 1 -#PLIBS = $(PLIBP)\dde4sbs.lib $(TLIBP)\os2386.lib # CSet++ ver 2 +#PLIBS = $(PLIBP)\st\c $(PLIBP)\st\c_app $(PLIBP)\c_alias $(PLIBP)\gcc $(PLIBP)\st\sys $(PLIBP)\os2 # GCC emx 0.9 OMF +PLIBS = -lgcc -lc -lgcc -los2 $(X11LIBS) # GCC a.out # # C libraries used by makedefs, lev_comp and dgn_comp (change if @@ -346,17 +300,6 @@ PLIBS = $(PLIBP)\st\c $(PLIBP)\st\c_app $(PLIBP)\c_alias $(PLIBP)\gcc $(PLIBP)\s #RLIBS = $(RLIBP)\llibcer RLIBS = $(PLIBS) -# -# Default compilation skeletons. The uppermost six are for -# MSC and CSet/2 and the lowermost six for GCC. -# - -#SRCCC = $(CC) $(CFLAGS) $(O)$@ $(SRC)\$(AB) -#UTILCC = $(CC) $(CFLAGS) $(O)$@ $(UTIL)\$(AB) -#SYSCC = $(CC) $(CFLAGS) $(O)$@ $(SYS)\$(AB) -#SSYSCC = $(CC) $(CFLAGS) $(O)$@ $(SSYS)\$(AB) -#PSYSCC = $(CC) $(CFLAGS) $(O)$@ $(SSYS)\pc$(AB) -#WINCC = $(CC) $(CFLAGS) $(O)$@ $(WIN)\$(AB) SRCCC = $(CC) $(CFLAGS) $(O) $@ $(AB) UTILCC = $(B) cd $(UTIL) $(S) $(CC) $(CFLAGS) $(O) $@ $(AB) $(E) SYSCC = $(B) cd $(SYS) $(S) $(CC) $(CFLAGS) $(O) $@ $(AB) $(E) @@ -370,18 +313,18 @@ WINCC = $(B) cd $(WIN) $(S) $(CC) $(CFLAGS) $(O) $@ $(AB) $(E) # the lower six for GCC a.out format. # -GAMELN = $(LINK) @$(TEMP)\$(GAME).rsp -MKDFLN = $(LINK) @$(TEMP)\makedefs.rsp -LEVCLN = $(LINK) @$(TEMP)\lev_comp.rsp -DGNCLN = $(LINK) @$(TEMP)\dgn_comp.rsp -RCVRLN = $(LINK) @$(TEMP)\recover.rsp -DLBRLN = $(LINK) @$(TEMP)\dlb.rsp -#GAMELN = $(CC) $(LDFLAGS) -o $(GAMEDIR)\$(GAME).exe $(TEMP)\$(GAMEDEF) $(SYSOBJ) $(HOBJ) $(PLIBS) $(TERMLIB) -#MKDFLN = $(CC) $(LDFLAGS) -o $(TEMP)\makedefs.exe $(TEMP)\$(MKDFDEF) $(SYSOBJ) $(MAKEOBJS) $(PLIBS) -#LEVCLN = $(CC) $(LDFLAGS) -o $(TEMP)\lev_comp.exe $(TEMP)\$(LEVCDEF) $(SYSOBJ) $(SPLEVOBJS) $(PLIBS) -#DGNCLN = $(CC) $(LDFLAGS) -o $(TEMP)\dgn_comp.exe $(TEMP)\$(DGNCDEF) $(SYSOBJ) $(DGNCOMPOBJS) $(PLIBS) -#RCVRLN = $(CC) $(LDFLAGS) -o $(GAMEDIR)\recover.exe $(TEMP)\$(RCVRDEF) $(SYSOBJ) $(RECOVOBJS) $(PLIBS) -#DLBRLN = $(CC) $(LDFLAGS) -o $(TEMP)\dlb.exe $(TEMP)\$(DLBDEF) $(SYSOBJ) $(DLBOBJS) $(PLIBS) +#GAMELN = $(LINK) @$(TEMP)\$(GAME).rsp +#MKDFLN = $(LINK) @$(TEMP)\makedefs.rsp +#LEVCLN = $(LINK) @$(TEMP)\lev_comp.rsp +#DGNCLN = $(LINK) @$(TEMP)\dgn_comp.rsp +#RCVRLN = $(LINK) @$(TEMP)\recover.rsp +#DLBRLN = $(LINK) @$(TEMP)\dlb.rsp +GAMELN = $(CC) $(LDFLAGS) -o $(GAMEDIR)\$(GAME).exe @$(TEMP)\$(GAME).r $(PLIBS) $(WINX11CFLAGS) $(WINX11LIB) +MKDFLN = $(CC) $(LDFLAGS) -o $(TEMP)\makedefs.exe $(TEMP)\$(MKDFDEF) $(SYSOBJ) $(MAKEOBJS) $(PLIBS) +LEVCLN = $(CC) $(LDFLAGS) -o $(TEMP)\lev_comp.exe $(TEMP)\$(LEVCDEF) $(SYSOBJ) $(SPLEVOBJS) $(PLIBS) +DGNCLN = $(CC) $(LDFLAGS) -o $(TEMP)\dgn_comp.exe $(TEMP)\$(DGNCDEF) $(SYSOBJ) $(DGNCOMPOBJS) $(PLIBS) +RCVRLN = $(CC) $(LDFLAGS) -o $(GAMEDIR)\recover.exe $(TEMP)\$(RCVRDEF) $(SYSOBJ) $(RECOVOBJS) $(PLIBS) +DLBRLN = $(CC) $(LDFLAGS) -o $(TEMP)\dlb.exe $(TEMP)\$(DLBDEF) $(SYSOBJ) $(DLBOBJS) $(PLIBS) # # OS/2 module definition files for NetHack, @@ -454,7 +397,11 @@ GUIDE = # only choice for now. # -WINOBJ = $(OBJ)\getline.o $(OBJ)\termcap.o $(OBJ)\topl.o $(OBJ)\wintty.o +WINOBJ1 = $(OBJ)\getline.o +WINOBJ2 = $(OBJ)\termcap.o +WINOBJ3 = $(OBJ)\topl.o +WINOBJ4 = $(OBJ)\wintty.o +WINOBJ = $(WINOBJ1) $(WINOBJ2) $(WINOBJ3) $(WINOBJ4) $(WINX11OBJ) # # The default make target, so just typing 'make' is useful. @@ -511,11 +458,9 @@ do_cmd : cmd_act # generate nethack.cmd # out the lower line and uncomment the upper. Also, make sure # that DLB is defined in config.h. # -# NOTE: this feature is presently untested under OS/2. -# -#do_dlb : dlb_yup -do_dlb : dlb_nope +do_dlb : dlb_yup +#do_dlb : dlb_nope ###################################################################### # @@ -566,107 +511,205 @@ RECOVOBJS = $(OBJ)\recover.o # Object files for dlb. # -DLBOBJS = $(OBJ)\dlb_main.o $(OBJ)\dlb.o $(OBJ)\alloc.c $(OBJ)\panic.o +DLBOBJS = $(OBJ)\dlb_main.o $(OBJ)\dlb.o $(OBJ)\alloc.o $(OBJ)\panic.o # # Data files for dlb. # DATHELP = \ - $(GAMEDIR)\help $(GAMEDIR)\hh $(GAMEDIR)\cmdhelp $(GAMEDIR)\history \ - $(GAMEDIR)\opthelp $(GAMEDIR)\wizhelp + help hh cmdhelp history opthelp wizhelp + SPEC_LEVS = \ - $(GAMEDIR)\asmodeus.lev $(GAMEDIR)\baalz.lev $(GAMEDIR)\bigrm-1.lev \ - $(GAMEDIR)\bigrm-2.lev $(GAMEDIR)\bigrm-3.lev $(GAMEDIR)\bigrm-4.lev \ - $(GAMEDIR)\castle.lev $(GAMEDIR)\fakewiz1.lev $(GAMEDIR)\fakewiz2.lev \ - $(GAMEDIR)\juiblex.lev $(GAMEDIR)\knox.lev $(GAMEDIR)\medusa-1.lev \ - $(GAMEDIR)\medusa-2.lev $(GAMEDIR)\minend-1.lev $(GAMEDIR)\minend-2.lev \ - $(GAMEDIR)\minefill.lev $(GAMEDIR)\minetn-1.lev $(GAMEDIR)\minetn-2.lev \ - $(GAMEDIR)\oracle.lev $(GAMEDIR)\orcus.lev $(GAMEDIR)\sanctum.lev \ - $(GAMEDIR)\tower1.lev $(GAMEDIR)\tower2.lev $(GAMEDIR)\tower3.lev \ - $(GAMEDIR)\valley.lev $(GAMEDIR)\wizard1.lev $(GAMEDIR)\wizard2.lev \ - $(GAMEDIR)\wizard3.lev $(GAMEDIR)\astral.lev $(GAMEDIR)\air.lev \ - $(GAMEDIR)\earth.lev $(GAMEDIR)\fire.lev $(GAMEDIR)\water.lev \ - $(GAMEDIR)\soko1-1.lev $(GAMEDIR)\soko1-2.lev \ - $(GAMEDIR)\soko2-1.lev $(GAMEDIR)\soko2-2.lev \ - $(GAMEDIR)\soko3-1.lev $(GAMEDIR)\soko3-2.lev \ - $(GAMEDIR)\soko4-1.lev $(GAMEDIR)\soko4-2.lev + asmodeus.lev baalz.lev bigrm-1.lev \ + bigrm-2.lev bigrm-3.lev bigrm-4.lev castle.lev fakewiz1.lev fakewiz2.lev \ + juiblex.lev knox.lev medusa-1.lev medusa-2.lev minend-1.lev minend-2.lev \ + minefill.lev minetn-1.lev minetn-2.lev oracle.lev orcus.lev sanctum.lev \ + tower1.lev tower2.lev tower3.lev valley.lev wizard1.lev wizard2.lev \ + wizard3.lev astral.lev air.lev earth.lev fire.lev water.lev \ + soko1-1.lev soko1-2.lev soko2-1.lev soko2-2.lev \ + soko3-1.lev soko3-2.lev soko4-1.lev soko4-2.lev + QUEST_LEVS = \ - $(GAMEDIR)\Arc-goal.lev $(GAMEDIR)\Arc-fila.lev $(GAMEDIR)\Arc-filb.lev \ - $(GAMEDIR)\Arc-loca.lev $(GAMEDIR)\Arc-strt.lev \ - $(GAMEDIR)\Bar-goal.lev $(GAMEDIR)\Bar-fila.lev $(GAMEDIR)\Bar-filb.lev \ - $(GAMEDIR)\Bar-loca.lev $(GAMEDIR)\Bar-strt.lev \ - $(GAMEDIR)\Cav-goal.lev $(GAMEDIR)\Cav-fila.lev $(GAMEDIR)\Cav-filb.lev \ - $(GAMEDIR)\Cav-loca.lev $(GAMEDIR)\Cav-strt.lev \ - $(GAMEDIR)\Hea-goal.lev $(GAMEDIR)\Hea-fila.lev $(GAMEDIR)\Hea-filb.lev \ - $(GAMEDIR)\Hea-loca.lev $(GAMEDIR)\Hea-strt.lev \ - $(GAMEDIR)\Kni-goal.lev $(GAMEDIR)\Kni-fila.lev $(GAMEDIR)\Kni-filb.lev \ - $(GAMEDIR)\Kni-loca.lev $(GAMEDIR)\Kni-strt.lev \ - $(GAMEDIR)\Mon-goal.lev $(GAMEDIR)\Mon-fila.lev $(GAMEDIR)\Mon-filb.lev \ - $(GAMEDIR)\Mon-loca.lev $(GAMEDIR)\Mon-strt.lev \ - $(GAMEDIR)\Pri-goal.lev $(GAMEDIR)\Pri-fila.lev $(GAMEDIR)\Pri-filb.lev \ - $(GAMEDIR)\Pri-loca.lev $(GAMEDIR)\Pri-strt.lev \ - $(GAMEDIR)\Ran-goal.lev $(GAMEDIR)\Ran-fila.lev $(GAMEDIR)\Ran-filb.lev \ - $(GAMEDIR)\Ran-loca.lev $(GAMEDIR)\Ran-strt.lev \ - $(GAMEDIR)\Rog-goal.lev $(GAMEDIR)\Rog-fila.lev $(GAMEDIR)\Rog-filb.lev \ - $(GAMEDIR)\Rog-loca.lev $(GAMEDIR)\Rog-strt.lev \ - $(GAMEDIR)\Sam-goal.lev $(GAMEDIR)\Sam-fila.lev $(GAMEDIR)\Sam-filb.lev \ - $(GAMEDIR)\Sam-loca.lev $(GAMEDIR)\Sam-strt.lev \ - $(GAMEDIR)\Tou-goal.lev $(GAMEDIR)\Tou-fila.lev $(GAMEDIR)\Tou-filb.lev \ - $(GAMEDIR)\Tou-loca.lev $(GAMEDIR)\Tou-strt.lev \ - $(GAMEDIR)\Val-goal.lev $(GAMEDIR)\Val-fila.lev $(GAMEDIR)\Val-filb.lev \ - $(GAMEDIR)\Val-loca.lev $(GAMEDIR)\Val-strt.lev \ - $(GAMEDIR)\Wiz-goal.lev $(GAMEDIR)\Wiz-fila.lev $(GAMEDIR)\Wiz-filb.lev \ - $(GAMEDIR)\Wiz-loca.lev $(GAMEDIR)\Wiz-strt.lev + Arc-goal.lev Arc-fila.lev Arc-filb.lev Arc-loca.lev Arc-strt.lev \ + Bar-goal.lev Bar-fila.lev Bar-filb.lev Bar-loca.lev Bar-strt.lev \ + Cav-goal.lev Cav-fila.lev Cav-filb.lev Cav-loca.lev Cav-strt.lev \ + Hea-goal.lev Hea-fila.lev Hea-filb.lev Hea-loca.lev Hea-strt.lev \ + Kni-goal.lev Kni-fila.lev Kni-filb.lev Kni-loca.lev Kni-strt.lev \ + Mon-goal.lev Mon-fila.lev Mon-filb.lev Mon-loca.lev Mon-strt.lev \ + Pri-goal.lev Pri-fila.lev Pri-filb.lev Pri-loca.lev Pri-strt.lev \ + Ran-goal.lev Ran-fila.lev Ran-filb.lev Ran-loca.lev Ran-strt.lev \ + Rog-goal.lev Rog-fila.lev Rog-filb.lev Rog-loca.lev Rog-strt.lev \ + Sam-goal.lev Sam-fila.lev Sam-filb.lev Sam-loca.lev Sam-strt.lev \ + Tou-goal.lev Tou-fila.lev Tou-filb.lev Tou-loca.lev Tou-strt.lev \ + Val-goal.lev Val-fila.lev Val-filb.lev Val-loca.lev Val-strt.lev \ + Wiz-goal.lev Wiz-fila.lev Wiz-filb.lev Wiz-loca.lev Wiz-strt.lev VARDATD = \ - $(GAMEDIR)\data $(GAMEDIR)\oracles $(GAMEDIR)\options \ - $(GAMEDIR)\quest.dat $(GAMEDIR)\rumors + data oracles options quest.dat rumors $(WINX11VARDAT) -DATDLB = $(DATHELP) $(GAMEDIR)\dungeon $(SPEC_LEVS) $(QUEST_LEVS) $(VARDATD) +DATDLB = $(DATHELP) dungeon $(SPEC_LEVS) $(QUEST_LEVS) $(VARDATD) \ + $(do_dlb) # # Object files for the game itself. # -VOBJ01 = $(OBJ)\allmain.o $(OBJ)\alloc.o $(OBJ)\apply.o $(OBJ)\artifact.o -VOBJ02 = $(OBJ)\attrib.o $(OBJ)\ball.o $(OBJ)\bones.o $(OBJ)\botl.o -VOBJ03 = $(OBJ)\cmd.o $(OBJ)\dbridge.o $(OBJ)\decl.o $(OBJ)\detect.o -VOBJ04 = $(OBJ)\dig.o $(OBJ)\display.o $(OBJ)\dlb.o $(OBJ)\do.o -VOBJ05 = $(OBJ)\do_name.o $(OBJ)\do_wear.o $(OBJ)\dog.o $(OBJ)\dogmove.o -VOBJ06 = $(OBJ)\dokick.o $(OBJ)\dothrow.o $(OBJ)\drawing.o $(OBJ)\dungeon.o -VOBJ07 = $(OBJ)\eat.o $(OBJ)\end.o $(OBJ)\engrave.o $(OBJ)\exper.o -VOBJ08 = $(OBJ)\explode.o $(OBJ)\extralev.o $(OBJ)\files.o $(OBJ)\fountain.o -VOBJ09 = $(OBJ)\hack.o $(OBJ)\hacklib.o $(OBJ)\invent.o $(OBJ)\light.o -VOBJ10 = $(OBJ)\lock.o $(OBJ)\mail.o $(OBJ)\main.o $(OBJ)\makemon.o -VOBJ11 = $(OBJ)\mcastu.o $(OBJ)\mhitm.o $(OBJ)\mhitu.o $(OBJ)\minion.o -VOBJ12 = $(OBJ)\mklev.o $(OBJ)\mkmap.o $(OBJ)\mkmaze.o $(OBJ)\mkobj.o -VOBJ13 = $(OBJ)\mkroom.o $(OBJ)\mon.o $(OBJ)\mondata.o $(OBJ)\monmove.o -VOBJ14 = $(OBJ)\monst.o $(OBJ)\monstr.o $(OBJ)\mplayer.o $(OBJ)\mthrowu.o -VOBJ15 = $(OBJ)\muse.o $(OBJ)\music.o $(OBJ)\o_init.o $(OBJ)\objects.o -VOBJ16 = $(OBJ)\objnam.o $(OBJ)\options.o $(OBJ)\os2.o $(OBJ)\pager.o -VOBJ17 = $(OBJ)\pcsys.o $(OBJ)\pickup.o $(OBJ)\pline.o $(OBJ)\polyself.o -VOBJ18 = $(OBJ)\potion.o $(OBJ)\pray.o $(OBJ)\priest.o $(OBJ)\quest.o -VOBJ19 = $(OBJ)\questpgr.o $(OBJ)\read.o $(OBJ)\rect.o $(OBJ)\region.o $(OBJ)\restore.o -VOBJ20 = $(OBJ)\rip.o $(OBJ)\rnd.o $(OBJ)\rumors.o $(OBJ)\save.o -VOBJ21 = $(OBJ)\shk.o $(OBJ)\shknam.o $(OBJ)\sit.o $(OBJ)\sounds.o -VOBJ22 = $(OBJ)\sp_lev.o $(OBJ)\spell.o $(OBJ)\steal.o $(OBJ)\teleport.o -VOBJ23 = $(OBJ)\timeout.o $(OBJ)\topten.o $(OBJ)\track.o $(OBJ)\trap.o -VOBJ24 = $(OBJ)\tty.o $(OBJ)\u_init.o $(OBJ)\uhitm.o $(OBJ)\unix.o -VOBJ25 = $(OBJ)\vault.o $(OBJ)\vision.o $(OBJ)\vis_tab.o $(OBJ)\weapon.o -VOBJ26 = $(OBJ)\were.o $(OBJ)\wield.o $(OBJ)\windows.o $(OBJ)\wizard.o -VOBJ27 = $(OBJ)\worm.o $(OBJ)\worn.o $(OBJ)\write.o $(OBJ)\zap.o -VOBJ28 = $(WINOBJ) $(OBJ)\role.o $(OBJ)\steed.o -VOBJ29 = $(RANDOM) +VOBJ011 = $(OBJ)\allmain.o +VOBJ012 = $(OBJ)\alloc.o +VOBJ013 = $(OBJ)\apply.o +VOBJ014 = $(OBJ)\artifact.o +VOBJ021 = $(OBJ)\attrib.o +VOBJ022 = $(OBJ)\ball.o +VOBJ023 = $(OBJ)\bones.o +VOBJ024 = $(OBJ)\botl.o +VOBJ031 = $(OBJ)\cmd.o +VOBJ032 = $(OBJ)\dbridge.o +VOBJ033 = $(OBJ)\decl.o +VOBJ034 = $(OBJ)\detect.o +VOBJ041 = $(OBJ)\dig.o +VOBJ042 = $(OBJ)\display.o +VOBJ043 = $(OBJ)\dlb.o +VOBJ044 = $(OBJ)\do.o +VOBJ051 = $(OBJ)\do_name.o +VOBJ052 = $(OBJ)\do_wear.o +VOBJ053 = $(OBJ)\dog.o +VOBJ054 = $(OBJ)\dogmove.o +VOBJ061 = $(OBJ)\dokick.o +VOBJ062 = $(OBJ)\dothrow.o +VOBJ063 = $(OBJ)\drawing.o +VOBJ064 = $(OBJ)\dungeon.o +VOBJ071 = $(OBJ)\eat.o +VOBJ072 = $(OBJ)\end.o +VOBJ073 = $(OBJ)\engrave.o +VOBJ074 = $(OBJ)\exper.o +VOBJ071 = $(OBJ)\eat.o +VOBJ072 = $(OBJ)\end.o +VOBJ073 = $(OBJ)\engrave.o +VOBJ074 = $(OBJ)\exper.o +VOBJ081 = $(OBJ)\explode.o +VOBJ082 = $(OBJ)\extralev.o +VOBJ083 = $(OBJ)\files.o +VOBJ084 = $(OBJ)\fountain.o +VOBJ091 = $(OBJ)\hack.o +VOBJ092 = $(OBJ)\hacklib.o +VOBJ093 = $(OBJ)\invent.o +VOBJ094 = $(OBJ)\light.o +VOBJ101 = $(OBJ)\lock.o +VOBJ102 = $(OBJ)\mail.o +VOBJ103 = $(OBJ)\main.o +VOBJ104 = $(OBJ)\makemon.o +VOBJ111 = $(OBJ)\mapglyph.o +VOBJ112 = $(OBJ)\mcastu.o +VOBJ113 = $(OBJ)\mhitm.o +VOBJ114 = $(OBJ)\mhitu.o +VOBJ115 = $(OBJ)\minion.o +VOBJ121 = $(OBJ)\mklev.o +VOBJ122 = $(OBJ)\mkmap.o +VOBJ123 = $(OBJ)\mkmaze.o +VOBJ124 = $(OBJ)\mkobj.o +VOBJ131 = $(OBJ)\mkroom.o +VOBJ132 = $(OBJ)\mon.o +VOBJ133 = $(OBJ)\mondata.o +VOBJ134 = $(OBJ)\monmove.o +VOBJ141 = $(OBJ)\monst.o +VOBJ142 = $(OBJ)\monstr.o +VOBJ143 = $(OBJ)\mplayer.o +VOBJ144 = $(OBJ)\mthrowu.o +VOBJ151 = $(OBJ)\muse.o +VOBJ152 = $(OBJ)\music.o +VOBJ153 = $(OBJ)\o_init.o +VOBJ154 = $(OBJ)\objects.o +VOBJ161 = $(OBJ)\objnam.o +VOBJ162 = $(OBJ)\options.o +VOBJ163 = $(OBJ)\os2.o +VOBJ164 = $(OBJ)\pager.o +VOBJ171 = $(OBJ)\pcsys.o +VOBJ172 = $(OBJ)\pickup.o +VOBJ173 = $(OBJ)\pline.o +VOBJ174 = $(OBJ)\polyself.o +VOBJ181 = $(OBJ)\potion.o +VOBJ182 = $(OBJ)\pray.o +VOBJ183 = $(OBJ)\priest.o +VOBJ184 = $(OBJ)\quest.o +VOBJ191 = $(OBJ)\questpgr.o +VOBJ192 = $(OBJ)\read.o +VOBJ193 = $(OBJ)\rect.o +VOBJ194 = $(OBJ)\region.o +VOBJ195 = $(OBJ)\restore.o +VOBJ201 = $(OBJ)\rip.o +VOBJ202 = $(OBJ)\rnd.o +VOBJ203 = $(OBJ)\rumors.o +VOBJ204 = $(OBJ)\save.o +VOBJ211 = $(OBJ)\shk.o +VOBJ212 = $(OBJ)\shknam.o +VOBJ213 = $(OBJ)\sit.o +VOBJ214 = $(OBJ)\sounds.o +VOBJ221 = $(OBJ)\sp_lev.o +VOBJ222 = $(OBJ)\spell.o +VOBJ223 = $(OBJ)\steal.o +VOBJ224 = $(OBJ)\teleport.o +VOBJ231 = $(OBJ)\timeout.o +VOBJ232 = $(OBJ)\topten.o +VOBJ233 = $(OBJ)\track.o +VOBJ234 = $(OBJ)\trap.o +VOBJ241 = $(OBJ)\tty.o +VOBJ242 = $(OBJ)\u_init.o +VOBJ243 = $(OBJ)\uhitm.o +VOBJ244 = $(OBJ)\unix.o +VOBJ251 = $(OBJ)\vault.o +VOBJ252 = $(OBJ)\vision.o +VOBJ253 = $(OBJ)\vis_tab.o +VOBJ254 = $(OBJ)\weapon.o +VOBJ261 = $(OBJ)\were.o +VOBJ262 = $(OBJ)\wield.o +VOBJ263 = $(OBJ)\windows.o +VOBJ264 = $(OBJ)\wizard.o +VOBJ271 = $(OBJ)\worm.o +VOBJ272 = $(OBJ)\worn.o +VOBJ273 = $(OBJ)\write.o +VOBJ274 = $(OBJ)\zap.o +VOBJ281 = $(OBJ)\role.o +VOBJ282 = $(OBJ)\steed.o + +VOBJ01 = $(VOBJ011) $(VOBJ012) $(VOBJ013) $(VOBJ014) +VOBJ02 = $(VOBJ021) $(VOBJ022) $(VOBJ023) $(VOBJ024) +VOBJ03 = $(VOBJ031) $(VOBJ032) $(VOBJ033) $(VOBJ034) +VOBJ04 = $(VOBJ041) $(VOBJ042) $(VOBJ043) $(VOBJ044) +VOBJ05 = $(VOBJ051) $(VOBJ052) $(VOBJ053) $(VOBJ054) +VOBJ06 = $(VOBJ061) $(VOBJ062) $(VOBJ063) $(VOBJ064) +VOBJ07 = $(VOBJ071) $(VOBJ072) $(VOBJ073) $(VOBJ074) +VOBJ08 = $(VOBJ081) $(VOBJ082) $(VOBJ083) $(VOBJ084) +VOBJ09 = $(VOBJ091) $(VOBJ092) $(VOBJ093) $(VOBJ094) +VOBJ10 = $(VOBJ101) $(VOBJ102) $(VOBJ103) $(VOBJ104) +VOBJ11 = $(VOBJ111) $(VOBJ112) $(VOBJ113) $(VOBJ114) $(VOBJ115) +VOBJ12 = $(VOBJ121) $(VOBJ122) $(VOBJ123) $(VOBJ124) +VOBJ13 = $(VOBJ131) $(VOBJ132) $(VOBJ133) $(VOBJ134) +VOBJ14 = $(VOBJ141) $(VOBJ142) $(VOBJ143) $(VOBJ144) +VOBJ15 = $(VOBJ151) $(VOBJ152) $(VOBJ153) $(VOBJ154) +VOBJ16 = $(VOBJ161) $(VOBJ162) $(VOBJ163) $(VOBJ164) +VOBJ17 = $(VOBJ171) $(VOBJ172) $(VOBJ173) $(VOBJ174) +VOBJ18 = $(VOBJ181) $(VOBJ182) $(VOBJ183) $(VOBJ184) +VOBJ19 = $(VOBJ191) $(VOBJ192) $(VOBJ193) $(VOBJ194) $(VOBJ195) +VOBJ20 = $(VOBJ201) $(VOBJ202) $(VOBJ203) $(VOBJ204) +VOBJ21 = $(VOBJ211) $(VOBJ212) $(VOBJ213) $(VOBJ214) +VOBJ22 = $(VOBJ221) $(VOBJ222) $(VOBJ223) $(VOBJ224) +VOBJ23 = $(VOBJ231) $(VOBJ232) $(VOBJ233) $(VOBJ234) +VOBJ24 = $(VOBJ241) $(VOBJ242) $(VOBJ243) $(VOBJ244) +VOBJ25 = $(VOBJ251) $(VOBJ252) $(VOBJ253) $(VOBJ254) +VOBJ26 = $(VOBJ261) $(VOBJ262) $(VOBJ263) $(VOBJ264) +VOBJ27 = $(VOBJ271) $(VOBJ272) $(VOBJ273) $(VOBJ274) +VOBJ28 = $(VOBJ281) $(VOBJ282) +VOBJ29 = $(WINOBJ) $(RANDOM) HHOBJ = $(OBJ)\version.o -VOBJ = $(VOBJ01) $(VOBJ02) $(VOBJ03) $(VOBJ04) $(VOBJ05) $(VOBJ06) $(VOBJ07) \ - $(VOBJ08) $(VOBJ09) $(VOBJ10) $(VOBJ11) $(VOBJ12) $(VOBJ13) $(VOBJ14) \ - $(VOBJ15) $(VOBJ16) $(VOBJ17) $(VOBJ18) $(VOBJ19) $(VOBJ20) $(VOBJ21) \ - $(VOBJ22) $(VOBJ23) $(VOBJ24) $(VOBJ25) $(VOBJ26) $(VOBJ27) $(VOBJ28) \ - $(VOBJ29) -HOBJ = $(VOBJ) $(HHOBJ) +VOBJ = $(VOBJ01) $(VOBJ02) $(VOBJ03) $(VOBJ04) $(VOBJ05) $(VOBJ06) $(VOBJ07) \ + $(VOBJ08) $(VOBJ09) $(VOBJ10) $(VOBJ11) $(VOBJ12) $(VOBJ13) $(VOBJ14) \ + $(VOBJ15) $(VOBJ16) $(VOBJ17) $(VOBJ18) $(VOBJ19) $(VOBJ20) $(VOBJ21) \ + $(VOBJ22) $(VOBJ23) $(VOBJ24) $(VOBJ25) $(VOBJ26) $(VOBJ27) $(VOBJ28) \ + $(VOBJ29) +HOBJ = $(VOBJ) $(HHOBJ) -EXTERN_H = #$(INCL)\extern.h +EXTERN_H = # $(INCL)\extern.h OS2CONF_H = $(INCL)\os2conf.h $(INCL)\micro.h $(INCL)\system.h $(EXTERN_H) GLOBAL_H = $(INCL)\global.h $(INCL)\coord.h $(OS2CONF_H) CONFIG_H = $(INCL)\config.h $(INCL)\config1.h $(INCL)\tradstdc.h $(GLOBAL_H) @@ -704,7 +747,7 @@ $(TEMP)\$(LEVCDEF) : $(TEMP)\$(RCVRDEF) : $(MAKEB) DD_NAME=recover DD_DESC="Recovery utility" DD_TARG=$@ do_def $(TEMP)\$(DLBDEF) : - $(MAKEB) DD_NAME=dld DD_DESC="Archive utility" DD_TARG=$@ do_def + $(MAKEB) DD_NAME=dlb DD_DESC="Archive utility" DD_TARG=$@ do_def do_def : $(ECHO) NAME $(DD_NAME) WINDOWCOMPAT> $(DD_TARG) @@ -718,9 +761,142 @@ do_def : $(GAME) : $(GAMEDIR)\$(GAME).exe $(GAME).exe : $(GAMEDIR)\$(GAME).exe -$(GAMEDIR)\$(GAME).exe : $(TEMP)\$(GAME).rsp +$(GAMEDIR)\$(GAME).exe : $(TEMP)\$(GAME).rsp $(TEMP)\$(GAME).r $(GAMELN) +$(TEMP)\$(GAME).r : $(HOBJ) $(TEMP)\$(GAMEDEF) + $(ECHO) $(VOBJ011) > $@ + $(ECHO) $(VOBJ012) >> $@ + $(ECHO) $(VOBJ013) >> $@ + $(ECHO) $(VOBJ014) >> $@ + $(ECHO) $(VOBJ021) >> $@ + $(ECHO) $(VOBJ022) >> $@ + $(ECHO) $(VOBJ023) >> $@ + $(ECHO) $(VOBJ024) >> $@ + $(ECHO) $(VOBJ031) >> $@ + $(ECHO) $(VOBJ032) >> $@ + $(ECHO) $(VOBJ033) >> $@ + $(ECHO) $(VOBJ034) >> $@ + $(ECHO) $(VOBJ041) >> $@ + $(ECHO) $(VOBJ042) >> $@ + $(ECHO) $(VOBJ043) >> $@ + $(ECHO) $(VOBJ044) >> $@ + $(ECHO) $(VOBJ051) >> $@ + $(ECHO) $(VOBJ052) >> $@ + $(ECHO) $(VOBJ053) >> $@ + $(ECHO) $(VOBJ054) >> $@ + $(ECHO) $(VOBJ061) >> $@ + $(ECHO) $(VOBJ062) >> $@ + $(ECHO) $(VOBJ063) >> $@ + $(ECHO) $(VOBJ064) >> $@ + $(ECHO) $(VOBJ071) >> $@ + $(ECHO) $(VOBJ072) >> $@ + $(ECHO) $(VOBJ073) >> $@ + $(ECHO) $(VOBJ074) >> $@ + $(ECHO) $(VOBJ081) >> $@ + $(ECHO) $(VOBJ082) >> $@ + $(ECHO) $(VOBJ083) >> $@ + $(ECHO) $(VOBJ084) >> $@ + $(ECHO) $(VOBJ091) >> $@ + $(ECHO) $(VOBJ092) >> $@ + $(ECHO) $(VOBJ093) >> $@ + $(ECHO) $(VOBJ094) >> $@ + $(ECHO) $(VOBJ101) >> $@ + $(ECHO) $(VOBJ102) >> $@ + $(ECHO) $(VOBJ103) >> $@ + $(ECHO) $(VOBJ104) >> $@ + $(ECHO) $(VOBJ111) >> $@ + $(ECHO) $(VOBJ112) >> $@ + $(ECHO) $(VOBJ113) >> $@ + $(ECHO) $(VOBJ114) >> $@ + $(ECHO) $(VOBJ115) >> $@ + $(ECHO) $(VOBJ121) >> $@ + $(ECHO) $(VOBJ122) >> $@ + $(ECHO) $(VOBJ123) >> $@ + $(ECHO) $(VOBJ124) >> $@ + $(ECHO) $(VOBJ131) >> $@ + $(ECHO) $(VOBJ132) >> $@ + $(ECHO) $(VOBJ133) >> $@ + $(ECHO) $(VOBJ134) >> $@ + $(ECHO) $(VOBJ141) >> $@ + $(ECHO) $(VOBJ142) >> $@ + $(ECHO) $(VOBJ143) >> $@ + $(ECHO) $(VOBJ144) >> $@ + $(ECHO) $(VOBJ151) >> $@ + $(ECHO) $(VOBJ152) >> $@ + $(ECHO) $(VOBJ153) >> $@ + $(ECHO) $(VOBJ154) >> $@ + $(ECHO) $(VOBJ161) >> $@ + $(ECHO) $(VOBJ162) >> $@ + $(ECHO) $(VOBJ163) >> $@ + $(ECHO) $(VOBJ164) >> $@ + $(ECHO) $(VOBJ171) >> $@ + $(ECHO) $(VOBJ172) >> $@ + $(ECHO) $(VOBJ173) >> $@ + $(ECHO) $(VOBJ174) >> $@ + $(ECHO) $(VOBJ181) >> $@ + $(ECHO) $(VOBJ182) >> $@ + $(ECHO) $(VOBJ183) >> $@ + $(ECHO) $(VOBJ184) >> $@ + $(ECHO) $(VOBJ191) >> $@ + $(ECHO) $(VOBJ192) >> $@ + $(ECHO) $(VOBJ193) >> $@ + $(ECHO) $(VOBJ194) >> $@ + $(ECHO) $(VOBJ195) >> $@ + $(ECHO) $(VOBJ201) >> $@ + $(ECHO) $(VOBJ202) >> $@ + $(ECHO) $(VOBJ203) >> $@ + $(ECHO) $(VOBJ204) >> $@ + $(ECHO) $(VOBJ211) >> $@ + $(ECHO) $(VOBJ212) >> $@ + $(ECHO) $(VOBJ213) >> $@ + $(ECHO) $(VOBJ214) >> $@ + $(ECHO) $(VOBJ221) >> $@ + $(ECHO) $(VOBJ222) >> $@ + $(ECHO) $(VOBJ223) >> $@ + $(ECHO) $(VOBJ224) >> $@ + $(ECHO) $(VOBJ231) >> $@ + $(ECHO) $(VOBJ232) >> $@ + $(ECHO) $(VOBJ233) >> $@ + $(ECHO) $(VOBJ234) >> $@ + $(ECHO) $(VOBJ241) >> $@ + $(ECHO) $(VOBJ242) >> $@ + $(ECHO) $(VOBJ243) >> $@ + $(ECHO) $(VOBJ244) >> $@ + $(ECHO) $(VOBJ251) >> $@ + $(ECHO) $(VOBJ252) >> $@ + $(ECHO) $(VOBJ253) >> $@ + $(ECHO) $(VOBJ254) >> $@ + $(ECHO) $(VOBJ261) >> $@ + $(ECHO) $(VOBJ262) >> $@ + $(ECHO) $(VOBJ263) >> $@ + $(ECHO) $(VOBJ264) >> $@ + $(ECHO) $(VOBJ271) >> $@ + $(ECHO) $(VOBJ272) >> $@ + $(ECHO) $(VOBJ273) >> $@ + $(ECHO) $(VOBJ274) >> $@ + $(ECHO) $(VOBJ281) >> $@ + $(ECHO) $(VOBJ282) >> $@ + $(ECHO) $(WINOBJ1) >> $@ + $(ECHO) $(WINOBJ2) >> $@ + $(ECHO) $(WINOBJ3) >> $@ + $(ECHO) $(WINOBJ4) >> $@ + $(ECHO) $(HHOBJ) >> $@ + $(ECHO) $(RANDOM) >> $@ + $(X11ECHO) $(WINX11OBJ01) >> $@ + $(X11ECHO) $(WINX11OBJ02) >> $@ + $(X11ECHO) $(WINX11OBJ03) >> $@ + $(X11ECHO) $(WINX11OBJ04) >> $@ + $(X11ECHO) $(WINX11OBJ05) >> $@ + $(X11ECHO) $(WINX11OBJ06) >> $@ + $(X11ECHO) $(WINX11OBJ07) >> $@ + $(X11ECHO) $(WINX11OBJ08) >> $@ + $(X11ECHO) $(WINX11OBJ09) >> $@ + $(X11ECHO) $(WINX11OBJ10) >> $@ + $(X11ECHO) $(WINX11OBJ11) >> $@ + + + $(TEMP)\$(GAME).rsp : $(HOBJ) $(TEMP)\$(GAMEDEF) $(ECHO) $(SYSOBJ) $(VOBJ01) +> $@ $(ECHO) $(VOBJ02) +>> $@ @@ -751,6 +927,7 @@ $(TEMP)\$(GAME).rsp : $(HOBJ) $(TEMP)\$(GAMEDEF) $(ECHO) $(VOBJ27) +>> $@ $(ECHO) $(VOBJ28) +>> $@ $(ECHO) $(VOBJ29) +>> $@ + $(ECHO) $(VOBJ30) +>> $@ $(ECHO) $(HHOBJ)>> $@ $(ECHO) $(GAMEDIR)\$(GAME).exe>> $@ $(ECHO) $(TEMP)\$(GAME)>> $@ @@ -908,7 +1085,7 @@ $(OBJ)\recover.o : $(UTIL)\$(CB) $(CONFIG_H) dlb : $(TEMP)\dlb.exe $(TEMP)\dlb.exe : $(TEMP)\dlb.rsp - $(RCVRLN) + $(DLBRLN) $(TEMP)\dlb.rsp : $(DLBOBJS) $(TEMP)\$(DLBDEF) $(ECHO) $(SYSOBJ) $(DLBOBJS)> $@ @@ -920,11 +1097,11 @@ $(TEMP)\dlb.rsp : $(DLBOBJS) $(TEMP)\$(DLBDEF) $(OBJ)\dlb_main.o : $(UTIL)\$(CB) $(CONFIG_H) $(INCL)\dlb.h $(UTILCC) -$(GAMEDIR)\nhdat : +$(GAMEDIR)\nhdat : $(WINX11VARDAT) $(MAKEB) do_dlb dlb_yup : dlb - $(TEMP)\dlb cf $(GAMEDIR)\nhdat $(DATDLB) + $(TEMP)\dlb cCf $(GAMEDIR) $(GAMEDIR)\nhdat $(DATDLB) -$(RM) $(GAMEDIR)\help -$(RM) $(GAMEDIR)\hh -$(RM) $(GAMEDIR)\cmdhelp @@ -962,6 +1139,10 @@ dlb_yup : dlb -$(RM) $(GAMEDIR)\options -$(RM) $(GAMEDIR)\quest.dat -$(RM) $(GAMEDIR)\rumors + -$(RM) $(GAMEDIR)\dungeon + -$(RM) $(GAMEDIR)\soko?-?.lev +# -$(RM) $(GAMEDIR)\pet_mark.xbm +# -$(RM) $(GAMEDIR)\rip.xpm dlb_nope : $(ECHO) DLB not requested. @@ -1067,7 +1248,8 @@ $(OBJ)\wintty.o : $(WIN)\$(CB) $(HACK_H) $(INCL)\tcap.h dat : spec_lev help_fil $(GAMEDIR)\dungeon $(GAMEDIR)\data $(GAMEDIR)\rumors \ $(GAMEDIR)\oracles $(GAMEDIR)\quest.dat $(GAMEDIR)\$(GAME).ico \ - $(GAMEDIR)\$(GAME).cmd $(GAMEDIR)\nethack.cnf $(GAMEDIR)\nhdat + $(GAMEDIR)\$(GAME).cmd $(GAMEDIR)\nethack.cnf $(GAMEDIR)\nhdat \ + $(WINX11VARDAT) help_fil : $(GAMEDIR)\cmdhelp $(GAMEDIR)\help $(GAMEDIR)\hh $(GAMEDIR)\history \ $(GAMEDIR)\license $(GAMEDIR)\opthelp $(GAMEDIR)\wizhelp @@ -1399,6 +1581,8 @@ $(OBJ)\mail.o : $(SRC)\$(CB) $(HACK_H) $(INCL)\mail.h $(SRCCC) $(OBJ)\makemon.o : $(SRC)\$(CB) $(HACK_H) $(INCL)\epri.h $(INCL)\emin.h $(SRCCC) +$(OBJ)\mapglyph.o : $(SRC)\$(CB) $(HACK_H) + $(SRCCC) $(OBJ)\mcastu.o : $(SRC)\$(CB) $(HACK_H) $(SRCCC) $(OBJ)\mhitm.o : $(SRC)\$(CB) $(HACK_H) $(INCL)\artifact.h $(INCL)\edog.h @@ -1531,3 +1715,70 @@ $(OBJ)\write.o : $(SRC)\$(CB) $(HACK_H) $(SRCCC) $(OBJ)\zap.o : $(SRC)\$(CB) $(HACK_H) $(SRCCC) + +$(OBJ)/Window.o: $(WINX11)\Window.c $(INCL)\xwindowp.h $(INCL)\xwindow.h \ + $(CONFIG_H) + $(CC) -o$(OBJ)\Window.o $(CFLAGS) -c $(WINX11)\Window.c +$(OBJ)/dialogs.o: $(WINX11)\dialogs.c $(CONFIG_H) + $(CC) -o$(OBJ)\dialogs.o $(CFLAGS) -c $(WINX11)\dialogs.c +$(OBJ)/winX.o: $(WINX11)\winX.c $(HACK_H) $(INCL)\winX.h $(INCL)\dlb.h \ + $(INCL)\patchlevel.h $(WINX11)\nh72icon \ + $(WINX11)\nh56icon $(WINX11)\nh32icon + $(CC) $(CFLAGS) -c $(WINX11)\winX.c -o$(OBJ)\winX.o +$(OBJ)/winmap.o: $(WINX11)\winmap.c $(INCL)\xwindow.h $(HACK_H) $(INCL)\dlb.h \ + $(INCL)\winX.h $(INCL)\tile2x11.h + $(CC) $(CFLAGS) -c $(WINX11)\winmap.c -o $(OBJ)\winmap.o +$(OBJ)/winmenu.o: $(WINX11)\winmenu.c $(HACK_H) $(INCL)\winX.h + $(CC) $(CFLAGS) -c $(WINX11)\winmenu.c -o $(OBJ)\winmenu.o +$(OBJ)/winmesg.o: $(WINX11)\winmesg.c $(INCL)\xwindow.h $(HACK_H) $(INCL)\winX.h + $(CC) $(CFLAGS) -c $(WINX11)\winmesg.c -o$(OBJ)\winmesg.o +$(OBJ)/winmisc.o: $(WINX11)\winmisc.c $(HACK_H) $(INCL)\func_tab.h \ + $(INCL)\winX.h + $(CC) $(CFLAGS) -c $(WINX11)\winmisc.c -o$(OBJ)\winmisc.o +$(OBJ)/winstat.o: $(WINX11)\winstat.c $(HACK_H) $(INCL)\winX.h + $(CC) $(CFLAGS) -c $(WINX11)\winstat.c -o$(OBJ)\winstat.o +$(OBJ)/wintext.o: $(WINX11)\wintext.c $(HACK_H) $(INCL)\winX.h $(INCL)\xwindow.h + $(CC) $(CFLAGS) -c $(WINX11)\wintext.c -o$(OBJ)\wintext.o +$(OBJ)/winval.o: $(WINX11)\winval.c $(HACK_H) $(INCL)\winX.h + $(CC) $(CFLAGS) -c $(WINX11)\winval.c -o$(OBJ)\winval.o + +$(OBJ)/tile.o: $(NHSRC)\src\tile.c $(HACK_H) + $(CC) $(CFLAGS) -c $(NHSRC)\src\tile.c -o$(OBJ)\tile.o + +$(TEMP)\tilemap.exe: ..\win\share\tilemap.c $(HACK_H) + $(CC) $(GCCO) $(WARN) -I$(INCL) $(CDFLAGS) $(STDC) $(WINX11CFLAGS) $(LFLAGS) -o $(TEMP)\tilemap.exe ..\win\share\tilemap.c $(LIBS) +$(NHSRC)\src\tile.c: $(TEMP)\tilemap.exe + $(TEMP)\tilemap + +x11tiles: $(TEMP)\tile2x11.exe $(WINSHARE)\monsters.txt \ + $(WINSHARE)\objects.txt \ + $(WINSHARE)\other.txt + $(TEMP)\tile2x11.exe $(WINSHARE)\monsters.txt $(WINSHARE)\objects.txt \ + $(WINSHARE)\other.txt + cp x11tiles $(GAMEDIR)\x11tiles + +TEXT_IO = $(OBJ)\tiletext.o \ + $(OBJ)\tiletxt.o \ + $(OBJ)\drawing.o \ + $(OBJ)\decl.o \ + $(OBJ)\monst.o \ + $(OBJ)\objects.o + +$(OBJ)\tiletext.o: ../win/share/tiletext.c $(CONFIG_H) $(WINSHARE)\tile.h + $(CC) $(CFLAGS) -c $(WINSHARE)\tiletext.c -o$(OBJ)\tiletext.o +$(OBJ)\tiletxt.o: $(WINSHARE)\tilemap.c $(HACK_H) + $(CC) $(CFLAGS) -c -DTILETEXT $(WINSHARE)\tilemap.c -o$(OBJ)\tiletxt.o + +$(TEMP)\tile2x11.exe: $(OBJ)\tile2x11.o $(TEXT_IO) + $(CC) $(LFLAGS) -o $(TEMP)\tile2x11.exe $(OBJ)\tile2x11.o $(TEXT_IO) $(LIBS) + +pet_mark.xbm: $(WINX11)\pet_mark.xbm + cp $(WINX11)\pet_mark.xbm $(GAMEDIR)\pet_mark.xbm + +rip.xpm: $(WINX11)\rip.xpm + cp $(WINX11)\rip.xpm $(GAMEDIR)\rip.xpm + +$(OBJ)\tile2x11.o : $(WINX11)\tile2x11.c $(INCL)\tile2x11.h + $(CC) $(CFLAGS) -o$(OBJ)\tile2x11.o -c $(WINX11)\tile2x11.c \ + -I$(WINSHARE) + diff --git a/sys/os2/os2.c b/sys/os2/os2.c index 5cf68d8..cf37dc7 100644 --- a/sys/os2/os2.c +++ b/sys/os2/os2.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)os2.c 3.3 96/02/29 */ +/* SCCS Id: @(#)os2.c 3.4 1996/02/29 */ /* Copyright (c) Timo Hakulinen, 1990, 1991, 1992, 1993, 1996. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/share/Makefile.lib b/sys/share/Makefile.lib index 1d62ef3..dbf9705 100644 --- a/sys/share/Makefile.lib +++ b/sys/share/Makefile.lib @@ -1,4 +1,4 @@ -# SCCS Id: @(#)Makefile.lib 3.3 90/22/02 +# SCCS Id: @(#)Makefile.lib 3.4 1990/22/02 # Nethack makefile for Fred fish termlib -- Norman Meluch # CC = cl /c diff --git a/sys/share/NetHack.cnf b/sys/share/NetHack.cnf index 7cff678..f8703df 100644 --- a/sys/share/NetHack.cnf +++ b/sys/share/NetHack.cnf @@ -49,6 +49,8 @@ OPTIONS=rawio,BIOS,IBMgraphics #OPTIONS=nolegacy,noverbose #OPTIONS=menustyle:traditional +# If you wish to change the symbol used to display boulders use: +OPTIONS=boulder:0 # # General options. You might also set "silent" so as not to attract # the boss's attention. @@ -58,7 +60,6 @@ OPTIONS=time,noshowexp,number_pad,lit_corridor,rest_on_space # If you want to get rid of "use #quit to quit..." use: #OPTIONS=suppress_alert:3.3.1 # - # #HACKDIR=c:\games\nethack # @@ -82,21 +83,12 @@ OPTIONS=time,noshowexp,number_pad,lit_corridor,rest_on_space # processing. # # ================================================ -# An example using the IBM graphics character set: -#DUNGEON= 032 179 196 218 191 192 217 197 193 194 \ -# 180 195 249 239 239 254 254 240 241 249 \ -# 177 177 060 062 060 062 220 124 190 035 \ -# 244 247 249 247 042 042 186 205 046 035 \ -# 247 -# -#TRAPS= 094 094 094 094 094 094 094 094 094 094 \ -# 094 094 094 094 232 232 232 157 094 094 \ -# 094 094 -# -#EFFECTS= 179 196 092 047 042 033 041 040 \ -# 048 035 064 042 \ -# 047 045 092 058 058 092 045 047 \ -# 047 045 092 058 032 058 092 045 047 +# The defaults using the IBM graphics character set: +#DUNGEON = 032 179 196 218 191 192 217 197 193 194 \ +# 180 195 250 254 254 043 043 240 241 250 \ +# 176 177 243 242 060 062 095 124 092 035 \ +# 244 247 250 247 250 250 035 035 032 035 \ +# 247 # # ================================================ # Some alternatives: diff --git a/sys/share/dgn_lex.c b/sys/share/dgn_lex.c index 19c8111..0850e44 100644 --- a/sys/share/dgn_lex.c +++ b/sys/share/dgn_lex.c @@ -406,7 +406,7 @@ static char *yy_last_accepting_cpos; #define YY_MORE_ADJ 0 char *yytext; #define INITIAL 0 -/* SCCS Id: @(#)dgn_lex.c 3.3 96/03/02 */ +/* SCCS Id: @(#)dgn_lex.c 3.4 1996/03/02 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* Copyright (c) 1990 by M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ @@ -481,33 +481,6 @@ void FDECL(init_yyout, (FILE *)); extern YYSTYPE yylval; int line_number = 1; -/* - * This is a hack required by Michael Hamel to get things - * working on the Mac. - */ -#if defined(applec) && !defined(FLEX_SCANNER) && !defined(FLEXHACK_SCANNER) -#undef input -#undef unput -#define unput(c) { yytchar = (c); if (yytchar == 10) yylineno--; *yysptr++ = yytchar; } -# ifndef YYNEWLINE -# define YYNEWLINE 10 -# endif - -char -input() /* Under MPW \n is chr(13)! Compensate for this. */ -{ - if (yysptr > yysbuf) return(*--yysptr); - else { - yytchar = getc(yyin); - if (yytchar == '\n') { - yylineno++; - return(YYNEWLINE); - } - if (yytchar == EOF) return(0); - else return(yytchar); - } -} -#endif /* applec && !FLEX_SCANNER && !FLEXHACK_SCANNER */ /* Macros after this point can all be overridden by user definitions in diff --git a/sys/share/dgn_yacc.c b/sys/share/dgn_yacc.c index ea40212..fe5657b 100644 --- a/sys/share/dgn_yacc.c +++ b/sys/share/dgn_yacc.c @@ -8,7 +8,7 @@ static char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93"; #define yyerrok (yyerrflag=0) #define YYRECOVERING (yyerrflag!=0) #define YYPREFIX "yy" -/* SCCS Id: @(#)dgn_comp.c 3.3 96/06/22 */ +/* SCCS Id: @(#)dgn_comp.c 3.4 1996/06/22 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* Copyright (c) 1990 by M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/share/ioctl.c b/sys/share/ioctl.c index 61c5e1e..8349281 100644 --- a/sys/share/ioctl.c +++ b/sys/share/ioctl.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)ioctl.c 3.3 90/22/02 */ +/* SCCS Id: @(#)ioctl.c 3.4 1990/22/02 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/share/lev_lex.c b/sys/share/lev_lex.c index 381eee8..cf8886d 100644 --- a/sys/share/lev_lex.c +++ b/sys/share/lev_lex.c @@ -208,18 +208,18 @@ static void FDECL(yy_fatal_error, (const char *)); *yy_cp = '\0'; \ yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 111 -#define YY_END_OF_BUFFER 112 -static yyconst short int yy_accept[627] = +#define YY_NUM_RULES 112 +#define YY_END_OF_BUFFER 113 +static yyconst short int yy_accept[633] = { 0, - 0, 0, 0, 0, 112, 110, 108, 107, 110, 110, - 110, 105, 4, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 2, 108, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, 110, 110, 110, 110, 108, 0, 106, 0, - 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 113, 111, 108, 107, 111, 111, + 111, 105, 4, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, + 2, 108, 111, 111, 105, 111, 111, 111, 111, 111, + 111, 111, 111, 111, 111, 111, 111, 108, 0, 106, + 0, 0, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -227,60 +227,61 @@ static yyconst short int yy_accept[627] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 87, 0, 0, 3, 0, - 2, 108, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2, 0, 109, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 87, 0, 0, + 3, 0, 2, 108, 0, 105, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, 110, 0, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 72, 0, 0, 67, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 72, 0, 0, + 67, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, + 0, 0, 0, 0, 65, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 109, 0, 0, + 0, 0, 0, 17, 0, 0, 0, 0, 0, 40, + 0, 0, 0, 6, 0, 0, 42, 0, 0, 0, + 33, 0, 0, 0, 36, 32, 0, 0, 0, 16, + + 0, 0, 104, 0, 0, 0, 0, 0, 0, 0, + 0, 93, 0, 0, 0, 0, 0, 0, 88, 91, + 51, 0, 0, 0, 0, 0, 0, 60, 0, 0, + 0, 0, 0, 94, 0, 0, 0, 0, 0, 0, + 55, 0, 0, 0, 45, 0, 0, 0, 0, 0, + 0, 0, 0, 90, 0, 0, 0, 53, 12, 0, + 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 0, 8, 0, 0, 0, 7, + 0, 0, 0, 0, 0, 0, 27, 0, 0, 0, + 59, 86, 0, 0, 80, 0, 0, 0, 0, 74, + + 0, 0, 0, 0, 0, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, - 0, 0, 0, 40, 0, 0, 0, 6, 0, 0, - 42, 0, 0, 0, 33, 0, 0, 0, 36, 32, - 0, 0, 0, 16, 0, 0, 104, 0, 0, 0, - - 0, 0, 0, 0, 0, 93, 0, 0, 0, 0, - 0, 0, 88, 91, 51, 0, 0, 0, 0, 0, - 0, 60, 0, 0, 0, 0, 0, 94, 0, 0, - 0, 0, 0, 0, 55, 0, 0, 0, 45, 0, - 0, 0, 0, 0, 0, 0, 0, 90, 0, 0, - 0, 53, 12, 0, 0, 0, 0, 25, 0, 0, - 0, 0, 0, 0, 10, 0, 0, 0, 0, 8, - 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, - 27, 0, 0, 0, 59, 86, 0, 0, 80, 0, - 0, 0, 0, 74, 0, 0, 0, 0, 0, 89, - - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 50, 0, 0, 0, 58, - 0, 64, 0, 0, 0, 52, 0, 0, 68, 0, - 0, 30, 43, 0, 0, 0, 0, 0, 0, 0, - 26, 0, 0, 0, 0, 0, 13, 28, 0, 21, - 0, 0, 0, 0, 79, 0, 66, 49, 62, 46, - 0, 0, 97, 0, 69, 0, 0, 0, 0, 0, - 47, 0, 0, 0, 0, 0, 0, 48, 101, 0, - 0, 56, 0, 54, 0, 0, 85, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, - - 15, 0, 0, 0, 37, 0, 20, 0, 95, 0, - 0, 92, 0, 0, 0, 78, 0, 0, 0, 0, - 57, 73, 71, 0, 0, 0, 84, 0, 0, 0, - 0, 39, 0, 0, 31, 11, 9, 19, 0, 0, - 0, 0, 0, 0, 0, 102, 0, 0, 0, 0, - 0, 0, 0, 0, 83, 0, 0, 77, 0, 96, - 70, 14, 0, 41, 0, 0, 0, 0, 0, 0, - 0, 75, 98, 61, 0, 100, 44, 81, 82, 0, - 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, - 63, 0, 99, 0, 0, 0, 0, 0, 0, 0, - - 0, 0, 0, 34, 35, 0, 0, 0, 0, 0, - 76, 103, 0, 0, 0, 24, 0, 0, 0, 22, - 0, 0, 23, 29, 38, 0 + 0, 50, 0, 0, 0, 58, 0, 64, 0, 0, + 0, 52, 0, 0, 68, 0, 0, 30, 43, 0, + 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, + 0, 0, 13, 28, 0, 21, 0, 0, 0, 0, + 79, 0, 66, 49, 62, 46, 0, 0, 97, 0, + 69, 0, 0, 0, 0, 0, 47, 0, 0, 0, + 0, 0, 0, 48, 101, 0, 0, 56, 0, 54, + 0, 0, 85, 0, 0, 1, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 5, 15, 0, 0, 0, + 37, 0, 20, 0, 95, 0, 0, 92, 0, 0, + 0, 78, 0, 0, 0, 0, 57, 73, 71, 0, + 0, 0, 84, 0, 0, 0, 0, 39, 0, 0, + 31, 11, 9, 19, 0, 0, 0, 0, 0, 0, + 0, 102, 0, 0, 0, 0, 0, 0, 0, 0, + 83, 0, 0, 77, 0, 96, 70, 14, 0, 41, + 0, 0, 0, 0, 0, 0, 0, 75, 98, 61, + 0, 100, 44, 81, 82, 0, 0, 0, 18, 0, + 0, 0, 0, 0, 0, 0, 63, 0, 99, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, + 35, 0, 0, 0, 0, 0, 76, 103, 0, 0, + 0, 24, 0, 0, 0, 22, 0, 0, 23, 29, + 38, 0 } ; static yyconst int yy_ec[256] = @@ -294,10 +295,10 @@ static yyconst int yy_ec[256] = 1, 1, 1, 1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 1, 30, 31, 32, 33, 34, 35, 1, 36, 37, - 38, 11, 39, 1, 40, 1, 41, 42, 43, 44, + 38, 39, 40, 1, 41, 1, 42, 43, 44, 45, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 1, 57, 58, 59, 60, 61, 62, 1, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 1, 58, 59, 60, 61, 62, 63, 1, 1, 1, 11, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -315,258 +316,263 @@ static yyconst int yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst int yy_meta[63] = +static yyconst int yy_meta[64] = { 0, 1, 2, 3, 2, 1, 2, 1, 1, 2, 2, - 2, 1, 1, 2, 2, 2, 1, 1, 2, 1, + 2, 2, 1, 2, 2, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1, 1, 1, 2, 1, - 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, + 2, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1 + 1, 1, 1 } ; -static yyconst short int yy_base[631] = +static yyconst short int yy_base[638] = { 0, - 0, 57, 81, 60, 756, 757, 63, 757, 750, 0, - 742, 741, 757, 727, 721, 43, 40, 723, 44, 60, - 722, 59, 61, 66, 733, 719, 90, 87, 63, 732, - 70, 65, 69, 80, 76, 57, 66, 89, 92, 98, - 97, 92, 98, 105, 108, 100, 104, 700, 741, 147, - 757, 164, 167, 169, 171, 174, 177, 716, 157, 162, - 173, 165, 178, 189, 170, 217, 160, 737, 757, 733, - 728, 707, 724, 723, 165, 708, 721, 714, 719, 699, - 703, 705, 707, 711, 693, 689, 694, 697, 697, 182, - 699, 184, 694, 700, 691, 691, 703, 701, 690, 700, - - 688, 147, 190, 166, 670, 659, 669, 664, 649, 652, - 649, 651, 663, 648, 60, 645, 639, 642, 641, 651, - 645, 644, 161, 637, 632, 176, 634, 649, 198, 634, - 636, 629, 206, 638, 642, 645, 644, 630, 636, 628, - 188, 621, 624, 619, 212, 757, 620, 674, 757, 187, - 757, 264, 227, 254, 255, 254, 258, 261, 263, 266, - 269, 757, 0, 757, 662, 648, 647, 641, 642, 641, - 635, 639, 648, 640, 640, 648, 632, 646, 644, 643, - 629, 628, 640, 643, 616, 637, 629, 621, 635, 629, - 624, 625, 626, 617, 628, 616, 619, 231, 596, 601, - - 586, 595, 588, 580, 578, 585, 581, 575, 578, 574, - 579, 571, 571, 574, 568, 567, 568, 566, 571, 576, - 577, 561, 757, 560, 561, 757, 566, 571, 560, 572, - 562, 554, 552, 558, 554, 555, 246, 548, 561, 560, - 550, 560, 559, 557, 552, 556, 541, 548, 537, 757, - 550, 534, 544, 543, 532, 587, 274, 279, 563, 281, - 282, 284, 558, 571, 570, 571, 562, 757, 568, 568, - 550, 548, 561, 757, 538, 559, 551, 540, 560, 541, - 757, 543, 286, 555, 757, 556, 541, 540, 757, 757, - 537, 538, 536, 757, 542, 278, 757, 509, 505, 504, - - 515, 514, 500, 502, 511, 757, 510, 496, 508, 503, - 510, 505, 757, 757, 757, 508, 503, 502, 536, 499, - 495, 757, 498, 497, 500, 486, 489, 757, 479, 480, - 487, 480, 493, 478, 757, 484, 479, 487, 757, 484, - 483, 472, 467, 466, 465, 469, 474, 757, 464, 468, - 460, 757, 757, 293, 504, 294, 296, 757, 496, 498, - 493, 497, 483, 478, 757, 497, 478, 483, 478, 757, - 493, 486, 487, 757, 482, 489, 470, 476, 474, 472, - 757, 470, 469, 477, 757, 757, 450, 438, 757, 448, - 439, 437, 433, 757, 445, 441, 438, 442, 424, 757, - - 440, 264, 431, 430, 434, 436, 420, 420, 432, 431, - 434, 427, 416, 416, 430, 757, 425, 410, 422, 757, - 414, 757, 406, 407, 419, 757, 405, 410, 757, 432, - 308, 757, 757, 433, 431, 436, 435, 434, 425, 440, - 757, 428, 434, 421, 430, 418, 757, 757, 408, 757, - 421, 416, 409, 403, 757, 399, 757, 757, 757, 757, - 388, 387, 757, 395, 757, 394, 389, 382, 391, 386, - 757, 374, 374, 389, 374, 378, 375, 757, 757, 376, - 371, 757, 366, 757, 372, 375, 757, 378, 377, 757, - 311, 403, 390, 402, 391, 390, 380, 386, 390, 757, - - 757, 393, 381, 304, 757, 379, 757, 358, 757, 364, - 363, 757, 361, 359, 350, 757, 349, 346, 357, 342, - 757, 757, 757, 351, 344, 346, 757, 350, 352, 351, - 364, 757, 373, 372, 757, 757, 757, 757, 377, 355, - 361, 360, 372, 361, 345, 757, 340, 339, 323, 333, - 323, 325, 333, 320, 757, 329, 318, 757, 326, 757, - 757, 757, 355, 757, 357, 357, 340, 342, 345, 353, - 336, 757, 757, 757, 306, 757, 757, 757, 757, 310, - 304, 303, 757, 336, 335, 329, 327, 328, 329, 326, - 757, 298, 757, 297, 323, 315, 317, 306, 321, 318, - - 315, 290, 287, 757, 757, 311, 301, 281, 274, 263, - 757, 757, 234, 231, 223, 757, 212, 204, 186, 757, - 118, 45, 757, 757, 757, 757, 347, 350, 352, 354 + 0, 58, 82, 61, 781, 782, 64, 782, 775, 740, + 766, 765, 782, 751, 745, 44, 41, 747, 45, 61, + 746, 60, 62, 67, 757, 743, 91, 90, 90, 756, + 71, 71, 75, 86, 21, 60, 68, 84, 95, 102, + 92, 103, 103, 111, 108, 69, 97, 723, 765, 141, + 782, 163, 160, 168, 170, 172, 174, 181, 740, 183, + 176, 187, 185, 190, 196, 192, 224, 213, 761, 782, + 757, 756, 751, 730, 747, 746, 180, 731, 744, 737, + 742, 722, 726, 728, 730, 734, 716, 712, 717, 720, + 720, 192, 722, 201, 717, 723, 714, 714, 726, 724, + + 713, 723, 711, 212, 184, 182, 692, 681, 691, 686, + 671, 674, 671, 673, 685, 670, 126, 667, 661, 664, + 663, 673, 667, 666, 167, 659, 654, 190, 656, 671, + 204, 656, 658, 651, 212, 660, 664, 667, 666, 652, + 658, 650, 206, 643, 646, 641, 197, 782, 642, 697, + 782, 232, 782, 271, 274, 276, 278, 280, 248, 282, + 284, 287, 289, 295, 782, 0, 782, 691, 690, 683, + 669, 668, 662, 663, 662, 656, 660, 669, 661, 661, + 669, 653, 667, 665, 664, 650, 649, 661, 664, 636, + 658, 650, 642, 656, 650, 645, 646, 647, 638, 649, + + 637, 640, 267, 616, 621, 606, 615, 608, 600, 598, + 605, 601, 595, 598, 594, 599, 591, 591, 594, 588, + 587, 588, 586, 591, 596, 597, 581, 782, 580, 581, + 782, 586, 591, 580, 592, 582, 574, 572, 578, 574, + 575, 249, 568, 581, 580, 570, 580, 579, 577, 572, + 576, 561, 568, 557, 782, 570, 554, 564, 563, 552, + 608, 297, 302, 584, 306, 310, 313, 782, 579, 592, + 591, 592, 583, 782, 589, 589, 571, 569, 582, 782, + 558, 580, 572, 561, 581, 562, 782, 564, 289, 576, + 782, 577, 562, 561, 782, 782, 558, 559, 557, 782, + + 563, 313, 782, 529, 525, 524, 535, 534, 520, 522, + 531, 782, 530, 516, 528, 523, 530, 525, 782, 782, + 782, 528, 523, 522, 557, 519, 515, 782, 518, 517, + 520, 506, 509, 782, 499, 500, 507, 500, 513, 498, + 782, 504, 499, 507, 782, 504, 503, 492, 487, 486, + 485, 489, 494, 782, 484, 488, 480, 782, 782, 319, + 525, 321, 325, 782, 517, 519, 514, 518, 504, 499, + 782, 518, 499, 504, 499, 782, 514, 507, 508, 782, + 503, 510, 491, 497, 495, 493, 782, 491, 490, 498, + 782, 782, 470, 458, 782, 468, 459, 457, 453, 782, + + 465, 461, 458, 462, 444, 782, 460, 272, 451, 450, + 454, 456, 440, 440, 452, 451, 454, 447, 436, 436, + 450, 782, 445, 430, 442, 782, 434, 782, 426, 427, + 439, 782, 425, 430, 782, 453, 331, 782, 782, 454, + 452, 457, 456, 455, 446, 461, 782, 449, 455, 442, + 451, 439, 782, 782, 428, 782, 442, 437, 430, 423, + 782, 419, 782, 782, 782, 782, 408, 407, 782, 415, + 782, 414, 409, 402, 411, 406, 782, 394, 394, 409, + 394, 398, 395, 782, 782, 396, 391, 782, 386, 782, + 392, 395, 782, 398, 397, 782, 333, 424, 411, 423, + + 412, 411, 401, 407, 411, 782, 782, 414, 402, 315, + 782, 400, 782, 378, 782, 384, 383, 782, 381, 379, + 370, 782, 369, 366, 377, 362, 782, 782, 782, 371, + 364, 366, 782, 370, 372, 371, 385, 782, 394, 393, + 782, 782, 782, 782, 398, 376, 382, 381, 393, 382, + 365, 782, 360, 359, 343, 353, 343, 345, 353, 340, + 782, 349, 338, 782, 346, 782, 782, 782, 376, 782, + 378, 378, 361, 363, 366, 374, 357, 782, 782, 782, + 326, 782, 782, 782, 782, 330, 324, 323, 782, 357, + 343, 337, 335, 347, 348, 345, 782, 316, 782, 315, + + 342, 334, 336, 325, 340, 337, 334, 307, 303, 782, + 782, 329, 327, 310, 309, 317, 782, 782, 309, 289, + 271, 782, 219, 191, 169, 782, 89, 68, 782, 782, + 782, 782, 369, 372, 374, 376, 379 } ; -static yyconst short int yy_def[631] = +static yyconst short int yy_def[638] = { 0, - 626, 1, 1, 3, 626, 626, 626, 626, 627, 628, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 629, 626, - 626, 630, 630, 630, 630, 630, 630, 626, 57, 57, - 57, 57, 57, 61, 61, 629, 626, 627, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 629, 626, 626, - 626, 630, 630, 630, 61, 626, 61, 61, 61, 61, - 61, 626, 66, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 61, 61, 626, 61, - 61, 61, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 61, 626, 61, 61, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 61, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 61, 626, 626, 626, 626, 626, 626, 626, 626, 626, - - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 0, 626, 626, 626, 626 + 632, 1, 1, 3, 632, 632, 632, 632, 633, 634, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 635, 632, + 632, 636, 636, 636, 636, 636, 636, 636, 632, 636, + 636, 636, 636, 636, 636, 636, 635, 632, 633, 632, + 632, 637, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 635, + 632, 632, 632, 636, 636, 636, 636, 636, 632, 636, + 636, 636, 636, 636, 632, 67, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 636, 636, 632, 636, 636, 636, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 636, + 632, 636, 636, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 636, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 636, 632, 632, 632, + + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 0, 632, 632, 632, 632, 632 } ; -static yyconst short int yy_nxt[820] = +static yyconst short int yy_nxt[846] = { 0, 6, 7, 8, 7, 9, 6, 6, 10, 11, 11, 6, 12, 13, 14, 15, 16, 17, 18, 19, 20, 6, 21, 6, 6, 22, 23, 24, 25, 26, 27, 28, 29, 6, 6, 30, 6, 6, 31, 6, 6, - 32, 33, 34, 35, 36, 37, 6, 38, 6, 6, - 6, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 6, 48, 49, 74, 67, 66, 67, 76, 79, 77, - 75, 80, 84, 102, 86, 625, 85, 81, 87, 89, - 99, 103, 50, 51, 52, 50, 53, 82, 88, 54, - 54, 53, 100, 90, 55, 56, 57, 119, 58, 59, - - 211, 53, 60, 93, 53, 61, 121, 94, 96, 62, - 120, 63, 64, 212, 122, 65, 104, 95, 97, 98, - 108, 105, 106, 109, 112, 110, 107, 113, 111, 123, - 117, 114, 125, 134, 115, 118, 126, 129, 130, 116, - 127, 132, 136, 124, 624, 138, 128, 135, 140, 137, - 102, 133, 131, 139, 143, 141, 144, 145, 103, 146, - 150, 67, 142, 67, 87, 67, 151, 152, 626, 151, - 626, 151, 626, 151, 88, 626, 151, 153, 626, 151, - 71, 157, 153, 161, 80, 153, 158, 626, 83, 626, - 85, 168, 92, 153, 169, 154, 198, 155, 153, 159, - - 626, 103, 153, 73, 75, 626, 99, 184, 185, 160, - 98, 187, 220, 188, 199, 256, 623, 221, 100, 162, - 163, 224, 163, 180, 200, 163, 163, 163, 626, 151, - 163, 163, 163, 622, 296, 163, 225, 163, 163, 621, - 163, 163, 247, 228, 248, 163, 234, 163, 163, 235, - 229, 163, 230, 620, 252, 626, 151, 253, 236, 237, - 619, 618, 238, 254, 239, 67, 151, 152, 258, 297, - 259, 260, 626, 172, 153, 626, 153, 178, 626, 261, - 626, 296, 153, 626, 617, 257, 626, 354, 334, 192, - 335, 626, 153, 262, 153, 153, 626, 153, 626, 626, - - 271, 626, 375, 356, 616, 265, 153, 153, 357, 153, - 626, 626, 615, 626, 376, 466, 297, 431, 614, 541, - 467, 153, 358, 381, 153, 626, 491, 613, 626, 542, - 612, 543, 544, 611, 610, 609, 608, 607, 606, 605, - 604, 603, 602, 601, 600, 599, 507, 68, 68, 68, - 70, 70, 148, 148, 148, 153, 153, 598, 597, 596, - 595, 594, 593, 592, 591, 590, 589, 588, 587, 586, - 585, 584, 583, 582, 581, 580, 579, 578, 577, 576, - 575, 574, 573, 572, 571, 570, 569, 568, 567, 566, - 565, 564, 563, 562, 561, 560, 559, 558, 557, 556, - - 555, 554, 553, 552, 551, 550, 549, 548, 547, 546, - 545, 540, 539, 538, 537, 536, 535, 534, 533, 532, - 531, 530, 529, 528, 527, 526, 525, 524, 523, 522, - 521, 520, 519, 518, 517, 516, 515, 514, 513, 512, - 511, 510, 509, 508, 507, 506, 505, 504, 503, 502, - 501, 500, 499, 498, 497, 496, 495, 494, 493, 492, - 490, 489, 488, 487, 486, 485, 484, 483, 482, 481, - 480, 479, 478, 477, 476, 475, 474, 473, 472, 471, - 470, 469, 468, 465, 464, 463, 462, 461, 460, 459, - 458, 457, 456, 455, 454, 453, 452, 451, 450, 449, - - 448, 447, 446, 445, 444, 443, 442, 441, 440, 439, - 438, 437, 436, 435, 434, 433, 432, 430, 429, 428, - 427, 426, 425, 424, 423, 422, 421, 420, 419, 418, - 417, 416, 415, 414, 413, 412, 411, 410, 409, 408, - 407, 406, 405, 404, 403, 402, 401, 400, 399, 398, - 397, 396, 395, 394, 393, 392, 391, 390, 389, 388, - 387, 386, 385, 384, 383, 382, 381, 380, 379, 378, - 377, 374, 373, 372, 371, 370, 369, 368, 367, 366, - 365, 364, 363, 362, 361, 360, 359, 358, 355, 353, - 352, 351, 350, 349, 348, 347, 346, 345, 344, 343, - - 342, 341, 340, 339, 338, 337, 336, 333, 332, 331, - 330, 329, 328, 327, 326, 325, 324, 323, 322, 321, - 320, 319, 318, 317, 316, 315, 314, 313, 312, 311, - 310, 309, 308, 307, 306, 305, 304, 303, 302, 301, - 300, 299, 298, 295, 294, 293, 292, 291, 290, 289, - 288, 287, 286, 285, 284, 283, 282, 281, 280, 279, - 278, 277, 276, 275, 274, 273, 272, 271, 270, 269, - 268, 267, 266, 265, 264, 263, 149, 255, 251, 250, - 249, 246, 245, 244, 243, 242, 241, 240, 233, 232, - 231, 227, 226, 223, 222, 219, 218, 217, 216, 215, - - 214, 213, 210, 209, 208, 207, 206, 205, 204, 203, - 202, 201, 197, 196, 195, 194, 193, 192, 191, 190, - 189, 186, 183, 182, 181, 180, 179, 178, 177, 176, - 175, 174, 173, 172, 171, 170, 167, 166, 165, 71, - 164, 69, 156, 149, 147, 101, 92, 91, 83, 78, - 73, 72, 71, 71, 69, 626, 5, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626 + 6, 32, 33, 34, 35, 36, 37, 6, 38, 6, + 6, 6, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 6, 48, 49, 76, 68, 67, 68, 78, 81, + 79, 77, 82, 86, 104, 88, 119, 87, 83, 89, + 91, 120, 105, 50, 51, 52, 50, 53, 84, 90, + 54, 54, 53, 55, 92, 56, 57, 58, 631, 59, + + 60, 121, 53, 61, 95, 53, 62, 101, 96, 123, + 63, 98, 64, 65, 122, 630, 66, 124, 97, 102, + 53, 99, 100, 106, 145, 125, 146, 110, 107, 108, + 111, 114, 112, 109, 115, 113, 127, 134, 116, 126, + 128, 117, 131, 132, 129, 136, 118, 135, 138, 142, + 130, 147, 140, 148, 152, 139, 143, 133, 89, 137, + 141, 632, 153, 144, 68, 153, 154, 216, 90, 632, + 153, 632, 153, 632, 153, 632, 153, 632, 153, 156, + 217, 156, 632, 153, 632, 153, 632, 153, 632, 153, + 203, 632, 153, 632, 153, 105, 157, 632, 153, 629, + + 161, 158, 85, 75, 87, 164, 173, 160, 77, 174, + 82, 162, 94, 101, 68, 104, 68, 189, 190, 225, + 628, 163, 100, 105, 226, 102, 165, 166, 192, 166, + 193, 204, 166, 166, 166, 166, 229, 166, 166, 166, + 257, 205, 166, 258, 166, 166, 627, 166, 166, 259, + 233, 230, 166, 239, 166, 166, 240, 234, 166, 235, + 261, 252, 166, 253, 264, 241, 242, 177, 185, 243, + 302, 244, 68, 153, 154, 632, 153, 632, 153, 632, + 153, 632, 153, 632, 153, 632, 153, 156, 632, 153, + 632, 153, 340, 263, 341, 265, 632, 153, 632, 153, + + 183, 626, 266, 632, 153, 381, 303, 632, 153, 262, + 360, 632, 153, 197, 632, 153, 302, 382, 625, 267, + 632, 153, 632, 153, 472, 277, 632, 153, 271, 473, + 547, 362, 632, 153, 632, 153, 624, 363, 623, 622, + 548, 621, 549, 550, 620, 619, 437, 618, 364, 497, + 387, 617, 303, 616, 615, 614, 613, 612, 611, 610, + 609, 608, 607, 606, 605, 604, 603, 602, 513, 69, + 69, 69, 71, 71, 150, 150, 150, 155, 155, 168, + 168, 601, 600, 599, 598, 597, 596, 595, 594, 593, + 592, 591, 590, 589, 588, 587, 586, 585, 584, 583, + + 582, 581, 580, 579, 578, 577, 576, 575, 574, 573, + 572, 571, 570, 569, 568, 567, 566, 565, 564, 563, + 562, 561, 560, 559, 558, 557, 556, 555, 554, 553, + 552, 551, 546, 545, 544, 543, 542, 541, 540, 539, + 538, 537, 536, 535, 534, 533, 532, 531, 530, 529, + 528, 527, 526, 525, 524, 523, 522, 521, 520, 519, + 518, 517, 516, 515, 514, 513, 512, 511, 510, 509, + 508, 507, 506, 505, 504, 503, 502, 501, 500, 499, + 498, 496, 495, 494, 493, 492, 491, 490, 489, 488, + 487, 486, 485, 484, 483, 482, 481, 480, 479, 478, + + 477, 476, 475, 474, 471, 470, 469, 468, 467, 466, + 465, 464, 463, 462, 461, 460, 459, 458, 457, 456, + 455, 454, 453, 452, 451, 450, 449, 448, 447, 446, + 445, 444, 443, 442, 441, 440, 439, 438, 436, 435, + 434, 433, 432, 431, 430, 429, 428, 427, 426, 425, + 424, 423, 422, 421, 420, 419, 418, 417, 416, 415, + 414, 413, 412, 411, 410, 409, 408, 407, 406, 405, + 404, 403, 402, 401, 400, 399, 398, 397, 396, 395, + 394, 393, 392, 391, 390, 389, 388, 387, 386, 385, + 384, 383, 380, 379, 378, 377, 376, 375, 374, 373, + + 372, 371, 370, 369, 368, 367, 366, 365, 364, 361, + 359, 358, 357, 356, 355, 354, 353, 352, 351, 350, + 349, 348, 347, 346, 345, 344, 343, 342, 339, 338, + 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, + 327, 326, 325, 324, 323, 322, 321, 320, 319, 318, + 317, 316, 315, 314, 313, 312, 311, 310, 309, 308, + 307, 306, 305, 304, 301, 300, 299, 298, 297, 296, + 295, 294, 293, 292, 291, 290, 289, 288, 287, 286, + 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, + 275, 274, 273, 272, 271, 270, 269, 268, 268, 151, + + 260, 256, 255, 254, 251, 250, 249, 248, 247, 246, + 245, 238, 237, 236, 232, 231, 228, 227, 224, 223, + 222, 221, 220, 219, 218, 215, 214, 213, 212, 211, + 210, 209, 208, 207, 206, 202, 201, 200, 199, 198, + 197, 196, 195, 194, 191, 188, 187, 186, 185, 184, + 183, 182, 181, 180, 179, 178, 177, 176, 175, 172, + 171, 170, 73, 169, 167, 70, 159, 151, 149, 103, + 94, 93, 85, 80, 75, 74, 73, 73, 72, 70, + 632, 5, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632 } ; -static yyconst short int yy_chk[820] = +static yyconst short int yy_chk[846] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -574,90 +580,93 @@ static yyconst short int yy_chk[820] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 16, 7, 4, 7, 17, 19, 17, - 16, 19, 22, 31, 23, 622, 22, 20, 23, 24, - 29, 31, 2, 3, 3, 4, 3, 20, 23, 3, - 3, 3, 29, 24, 3, 3, 3, 36, 3, 3, - - 115, 3, 3, 27, 3, 3, 37, 27, 28, 3, - 36, 3, 3, 115, 37, 3, 32, 27, 28, 28, - 33, 32, 32, 33, 34, 33, 32, 34, 33, 38, - 35, 34, 39, 42, 34, 35, 39, 40, 40, 34, - 39, 41, 43, 38, 621, 44, 39, 42, 45, 43, - 102, 41, 40, 44, 46, 45, 46, 47, 102, 47, - 50, 67, 45, 67, 50, 52, 52, 52, 53, 53, - 54, 54, 55, 55, 50, 56, 56, 59, 57, 57, - 54, 59, 60, 65, 59, 62, 61, 65, 60, 60, - 61, 75, 62, 61, 75, 55, 103, 57, 63, 63, - - 61, 103, 64, 56, 57, 63, 64, 90, 90, 63, - 63, 92, 123, 92, 104, 150, 619, 123, 64, 66, - 66, 126, 66, 150, 104, 66, 66, 66, 153, 153, - 66, 66, 66, 618, 198, 66, 126, 66, 66, 617, - 66, 66, 141, 129, 141, 66, 133, 66, 66, 133, - 129, 66, 129, 615, 145, 154, 154, 145, 133, 133, - 614, 613, 133, 145, 133, 152, 152, 152, 155, 198, - 156, 157, 155, 156, 158, 157, 159, 158, 158, 160, - 159, 296, 161, 160, 610, 154, 161, 257, 237, 159, - 237, 257, 258, 161, 260, 261, 258, 262, 260, 261, - - 260, 262, 283, 261, 609, 258, 354, 356, 262, 357, - 354, 356, 608, 357, 283, 402, 296, 357, 607, 504, - 402, 431, 354, 356, 491, 431, 431, 606, 491, 504, - 603, 504, 504, 602, 601, 600, 599, 598, 597, 596, - 595, 594, 592, 590, 589, 588, 491, 627, 627, 627, - 628, 628, 629, 629, 629, 630, 630, 587, 586, 585, - 584, 582, 581, 580, 575, 571, 570, 569, 568, 567, - 566, 565, 563, 559, 557, 556, 554, 553, 552, 551, - 550, 549, 548, 547, 545, 544, 543, 542, 541, 540, - 539, 534, 533, 531, 530, 529, 528, 526, 525, 524, - - 520, 519, 518, 517, 515, 514, 513, 511, 510, 508, - 506, 503, 502, 499, 498, 497, 496, 495, 494, 493, - 492, 489, 488, 486, 485, 483, 481, 480, 477, 476, - 475, 474, 473, 472, 470, 469, 468, 467, 466, 464, - 462, 461, 456, 454, 453, 452, 451, 449, 446, 445, - 444, 443, 442, 440, 439, 438, 437, 436, 435, 434, - 430, 428, 427, 425, 424, 423, 421, 419, 418, 417, - 415, 414, 413, 412, 411, 410, 409, 408, 407, 406, - 405, 404, 403, 401, 399, 398, 397, 396, 395, 393, - 392, 391, 390, 388, 387, 384, 383, 382, 380, 379, - - 378, 377, 376, 375, 373, 372, 371, 369, 368, 367, - 366, 364, 363, 362, 361, 360, 359, 355, 351, 350, - 349, 347, 346, 345, 344, 343, 342, 341, 340, 338, - 337, 336, 334, 333, 332, 331, 330, 329, 327, 326, - 325, 324, 323, 321, 320, 319, 318, 317, 316, 312, - 311, 310, 309, 308, 307, 305, 304, 303, 302, 301, - 300, 299, 298, 295, 293, 292, 291, 288, 287, 286, - 284, 282, 280, 279, 278, 277, 276, 275, 273, 272, - 271, 270, 269, 267, 266, 265, 264, 263, 259, 256, - 255, 254, 253, 252, 251, 249, 248, 247, 246, 245, - - 244, 243, 242, 241, 240, 239, 238, 236, 235, 234, - 233, 232, 231, 230, 229, 228, 227, 225, 224, 222, - 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, - 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, - 201, 200, 199, 197, 196, 195, 194, 193, 192, 191, - 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, - 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, - 170, 169, 168, 167, 166, 165, 148, 147, 144, 143, - 142, 140, 139, 138, 137, 136, 135, 134, 132, 131, - 130, 128, 127, 125, 124, 122, 121, 120, 119, 118, - - 117, 116, 114, 113, 112, 111, 110, 109, 108, 107, - 106, 105, 101, 100, 99, 98, 97, 96, 95, 94, - 93, 91, 89, 88, 87, 86, 85, 84, 83, 82, - 81, 80, 79, 78, 77, 76, 74, 73, 72, 71, - 70, 68, 58, 49, 48, 30, 26, 25, 21, 18, - 15, 14, 12, 11, 9, 5, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - - 626, 626, 626, 626, 626, 626, 626, 626, 626, 626, - 626, 626, 626, 626, 626, 626, 626, 626, 626 + 1, 1, 1, 2, 16, 7, 4, 7, 17, 19, + 17, 16, 19, 22, 31, 23, 35, 22, 20, 23, + 24, 35, 31, 2, 3, 3, 4, 3, 20, 23, + 3, 3, 3, 3, 24, 3, 3, 3, 628, 3, + + 3, 36, 3, 3, 27, 3, 3, 29, 27, 37, + 3, 28, 3, 3, 36, 627, 3, 37, 27, 29, + 3, 28, 28, 32, 46, 38, 46, 33, 32, 32, + 33, 34, 33, 32, 34, 33, 39, 41, 34, 38, + 39, 34, 40, 40, 39, 42, 34, 41, 43, 45, + 39, 47, 44, 47, 50, 43, 45, 40, 50, 42, + 44, 53, 53, 45, 52, 52, 52, 117, 50, 54, + 54, 55, 55, 56, 56, 57, 57, 61, 61, 54, + 117, 55, 58, 58, 60, 60, 63, 63, 62, 62, + 105, 64, 64, 66, 66, 105, 56, 65, 65, 625, + + 62, 58, 61, 57, 62, 66, 77, 60, 58, 77, + 60, 64, 63, 65, 68, 104, 68, 92, 92, 125, + 624, 64, 64, 104, 125, 65, 67, 67, 94, 67, + 94, 106, 67, 67, 67, 67, 128, 67, 67, 67, + 147, 106, 67, 147, 67, 67, 623, 67, 67, 147, + 131, 128, 67, 135, 67, 67, 135, 131, 67, 131, + 152, 143, 67, 143, 159, 135, 135, 159, 152, 135, + 203, 135, 154, 154, 154, 155, 155, 156, 156, 157, + 157, 158, 158, 160, 160, 161, 161, 156, 162, 162, + 163, 163, 242, 158, 242, 160, 164, 164, 262, 262, + + 161, 621, 163, 263, 263, 289, 203, 265, 265, 157, + 262, 266, 266, 162, 267, 267, 302, 289, 620, 164, + 360, 360, 362, 362, 408, 265, 363, 363, 263, 408, + 510, 266, 437, 437, 497, 497, 619, 267, 616, 615, + 510, 614, 510, 510, 613, 612, 363, 609, 360, 437, + 362, 608, 302, 607, 606, 605, 604, 603, 602, 601, + 600, 598, 596, 595, 594, 593, 592, 591, 497, 633, + 633, 633, 634, 634, 635, 635, 635, 636, 636, 637, + 637, 590, 588, 587, 586, 581, 577, 576, 575, 574, + 573, 572, 571, 569, 565, 563, 562, 560, 559, 558, + + 557, 556, 555, 554, 553, 551, 550, 549, 548, 547, + 546, 545, 540, 539, 537, 536, 535, 534, 532, 531, + 530, 526, 525, 524, 523, 521, 520, 519, 517, 516, + 514, 512, 509, 508, 505, 504, 503, 502, 501, 500, + 499, 498, 495, 494, 492, 491, 489, 487, 486, 483, + 482, 481, 480, 479, 478, 476, 475, 474, 473, 472, + 470, 468, 467, 462, 460, 459, 458, 457, 455, 452, + 451, 450, 449, 448, 446, 445, 444, 443, 442, 441, + 440, 436, 434, 433, 431, 430, 429, 427, 425, 424, + 423, 421, 420, 419, 418, 417, 416, 415, 414, 413, + + 412, 411, 410, 409, 407, 405, 404, 403, 402, 401, + 399, 398, 397, 396, 394, 393, 390, 389, 388, 386, + 385, 384, 383, 382, 381, 379, 378, 377, 375, 374, + 373, 372, 370, 369, 368, 367, 366, 365, 361, 357, + 356, 355, 353, 352, 351, 350, 349, 348, 347, 346, + 344, 343, 342, 340, 339, 338, 337, 336, 335, 333, + 332, 331, 330, 329, 327, 326, 325, 324, 323, 322, + 318, 317, 316, 315, 314, 313, 311, 310, 309, 308, + 307, 306, 305, 304, 301, 299, 298, 297, 294, 293, + 292, 290, 288, 286, 285, 284, 283, 282, 281, 279, + + 278, 277, 276, 275, 273, 272, 271, 270, 269, 264, + 261, 260, 259, 258, 257, 256, 254, 253, 252, 251, + 250, 249, 248, 247, 246, 245, 244, 243, 241, 240, + 239, 238, 237, 236, 235, 234, 233, 232, 230, 229, + 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, + 217, 216, 215, 214, 213, 212, 211, 210, 209, 208, + 207, 206, 205, 204, 202, 201, 200, 199, 198, 197, + 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, + 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, + 176, 175, 174, 173, 172, 171, 170, 169, 168, 150, + + 149, 146, 145, 144, 142, 141, 140, 139, 138, 137, + 136, 134, 133, 132, 130, 129, 127, 126, 124, 123, + 122, 121, 120, 119, 118, 116, 115, 114, 113, 112, + 111, 110, 109, 108, 107, 103, 102, 101, 100, 99, + 98, 97, 96, 95, 93, 91, 90, 89, 88, 87, + 86, 85, 84, 83, 82, 81, 80, 79, 78, 76, + 75, 74, 73, 72, 71, 69, 59, 49, 48, 30, + 26, 25, 21, 18, 15, 14, 12, 11, 10, 9, + 5, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632, 632, 632, 632, 632, 632, + 632, 632, 632, 632, 632 } ; static yy_state_type yy_last_accepting_state; @@ -671,7 +680,7 @@ static char *yy_last_accepting_cpos; #define YY_MORE_ADJ 0 char *yytext; #define INITIAL 0 -/* SCCS Id: @(#)lev_lex.c 3.3 96/05/16 */ +/* SCCS Id: @(#)lev_lex.c 3.4 2000/12/22 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -746,34 +755,6 @@ int line_number = 1, colon_line_number = 1; static char map[4096]; static int map_cnt = 0; -/* - * This is a hack required by Michael Hamel to get things - * working on the Mac. - */ -#if defined(applec) && !defined(FLEX_SCANNER) && !defined(FLEXHACK_SCANNER) -#undef input -#undef unput -#define unput(c) { yytchar = (c); if (yytchar == 10) yylineno--; *yysptr++ = yytchar; } -# ifndef YYNEWLINE -# define YYNEWLINE 10 -# endif - -char -input() /* Under MPW \n is chr(13)! Compensate for this. */ -{ - if (yysptr > yysbuf) return(*--yysptr); - else { - yytchar = getc(yyin); - if (yytchar == '\n') { - yylineno++; - return(YYNEWLINE); - } - if (yytchar == EOF) return(0); - else return(yytchar); - } -} -#endif /* applec && !FLEX_SCANNER && !FLEXHACK_SCANNER */ - #define MAPC 1 @@ -928,13 +909,13 @@ int yylex() while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 627 ) + if ( yy_current_state >= 633 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 757 ); + while ( yy_base[yy_current_state] != 782 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -1409,14 +1390,18 @@ YY_RULE_SETUP YY_BREAK case 109: YY_RULE_SETUP -{ yylval.i = yytext[1]; return CHAR; } +{ yylval.i = yytext[2]; return CHAR; } YY_BREAK case 110: YY_RULE_SETUP -{ return yytext[0]; } +{ yylval.i = yytext[1]; return CHAR; } YY_BREAK case 111: YY_RULE_SETUP +{ return yytext[0]; } + YY_BREAK +case 112: +YY_RULE_SETUP ECHO; YY_BREAK case YY_STATE_EOF(INITIAL): @@ -1710,7 +1695,7 @@ static yy_state_type yy_get_previous_state() while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 627 ) + if ( yy_current_state >= 633 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -1741,11 +1726,11 @@ yy_state_type yy_current_state; while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 627 ) + if ( yy_current_state >= 633 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 626); + yy_is_jam = (yy_current_state == 632); return yy_is_jam ? 0 : yy_current_state; } diff --git a/sys/share/lev_yacc.c b/sys/share/lev_yacc.c index 0d37799..e34cccf 100644 --- a/sys/share/lev_yacc.c +++ b/sys/share/lev_yacc.c @@ -8,7 +8,7 @@ static char yysccsid[] = "@(#)yaccpar 1.9 (Berkeley) 02/21/93"; #define yyerrok (yyerrflag=0) #define YYRECOVERING (yyerrflag!=0) #define YYPREFIX "yy" -/* SCCS Id: @(#)lev_yacc.c 3.3 2000/01/17 */ +/* SCCS Id: @(#)lev_yacc.c 3.4 2000/01/17 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/share/nhlan.c b/sys/share/nhlan.c index 9d3d161..27b1783 100644 --- a/sys/share/nhlan.c +++ b/sys/share/nhlan.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)nhlan.c 3.3 99/11/21 */ +/* SCCS Id: @(#)nhlan.c 3.4 1999/11/21 */ /* Copyright (c) Michael Allison, 1997 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/share/pcmain.c b/sys/share/pcmain.c index ec6ea55..77a2df0 100644 --- a/sys/share/pcmain.c +++ b/sys/share/pcmain.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pcmain.c 3.3 97/01/22 */ +/* SCCS Id: @(#)pcmain.c 3.4 1997/01/22 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -70,7 +70,7 @@ int FDECL(main, (int,char **)); extern void FDECL(pcmain, (int,char **)); -#ifdef __BORLANDC__ +#if defined(__BORLANDC__) && !defined(_WIN32) void NDECL( startup ); # ifdef OVLB unsigned _stklen = STKSIZ; @@ -106,7 +106,7 @@ char *argv[]; register int fd; register char *dir; -#ifdef __BORLANDC__ +#if defined(__BORLANDC__) && !defined(_WIN32) startup(); #endif @@ -167,13 +167,9 @@ char *argv[]; if(argc == 0) chdirx(HACKDIR, 1); # endif - ami_argset(&argc, argv); ami_wininit_data(); #endif initoptions(); -#ifdef AMIGA - ami_mkargline(&argc, &argv); -#endif #if defined(TOS) && defined(TEXTCOLOR) if (iflags.BIOS && iflags.use_color) @@ -235,8 +231,7 @@ char *argv[]; u.ux = 0; /* prevent flush_screen() */ /* chdir shouldn't be called before this point to keep the - * code parallel to other ports which call gethdate just - * before here. + * code parallel to other ports. */ #ifdef CHDIR chdirx(hackdir,1); @@ -382,10 +377,6 @@ char *argv[]; if(yn("Do you want to keep the save file?") == 'n'){ (void) delete_savefile(); } -# ifdef AMIGA - else - preserve_icon(); -# endif } flags.move = 0; @@ -427,6 +418,17 @@ char *argv[]; argv++; argc--; switch(argv[0][1]){ + case 'a': + if (argv[0][2]) { + if ((i = str2align(&argv[0][2])) >= 0) + flags.initalign = i; + } else if (argc > 1) { + argc--; + argv++; + if ((i = str2align(argv[0])) >= 0) + flags.initalign = i; + } + break; case 'D': #ifdef WIZARD /* If they don't have a valid wizard name, it'll be @@ -467,6 +469,17 @@ char *argv[]; switch_graphics(DEC_GRAPHICS); break; #endif + case 'g': + if (argv[0][2]) { + if ((i = str2gend(&argv[0][2])) >= 0) + flags.initgend = i; + } else if (argc > 1) { + argc--; + argv++; + if ((i = str2gend(argv[0])) >= 0) + flags.initgend = i; + } + break; case 'p': /* profession (role) */ if (argv[0][2]) { if ((i = str2role(&argv[0][2])) >= 0) @@ -507,6 +520,9 @@ char *argv[]; bigscreen = -1; break; #endif + case '@': + flags.randomall = 1; + break; default: if ((i = str2role(&argv[0][1])) >= 0) { flags.initrole = i; @@ -621,7 +637,15 @@ char *str; # ifndef WIN32 Strcpy (tmp, str); # else - *(tmp + GetModuleFileName((HANDLE)0, tmp, bsize)) = '\0'; + #ifdef UNICODE + { + TCHAR wbuf[BUFSZ]; + GetModuleFileName((HANDLE)0, wbuf, BUFSZ); + WideCharToMultiByte(CP_ACP, 0, wbuf, -1, tmp, bsize, NULL, NULL); + } + #else + *(tmp + GetModuleFileName((HANDLE)0, tmp, bsize)) = '\0'; + #endif # endif tmp2 = strrchr(tmp, PATH_SEPARATOR); if (tmp2) *tmp2 = '\0'; diff --git a/sys/share/pcsys.c b/sys/share/pcsys.c index cc8b5d9..fc252c9 100644 --- a/sys/share/pcsys.c +++ b/sys/share/pcsys.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pcsys.c 3.3 1999/12/10 +/* SCCS Id: @(#)pcsys.c 3.4 2002/01/22 */ /* NetHack may be freely redistributed. See license for details. */ /* @@ -11,7 +11,7 @@ #include #include -#ifndef MSDOS /* already done */ +#if !defined(MSDOS) && !defined(WIN_CE) /* already done */ #include #endif #ifdef __GO32__ @@ -45,9 +45,11 @@ extern unsigned short __far __cdecl _movefpaused; #define __MOVE_PAUSE_CACHE 4 /* Represents the cache memory */ #endif /* MOVERLAY */ +#ifdef MFLOPPY STATIC_DCL boolean NDECL(record_exists); -#ifndef TOS +# ifndef TOS STATIC_DCL boolean NDECL(comspec_exists); +# endif #endif #ifdef WIN32CON @@ -78,11 +80,13 @@ dosh() { extern char orgdir[]; char *comspec; +# ifndef __GO32__ int spawnstat; +# endif #if defined(MSDOS) && defined(NO_TERMS) - int grmode; + int grmode = iflags.grmode; #endif - if (comspec = getcomspec()) { + if ((comspec = getcomspec())) { # ifndef TOS /* TOS has a variety of shells */ suspend_nhwindows("To return to NetHack, enter \"exit\" at the system prompt.\n"); # else @@ -297,8 +301,6 @@ int start; return 1; } -# endif /* MFLOPPY */ - /* Return 1 if the record file was found */ STATIC_OVL boolean record_exists() @@ -312,10 +314,12 @@ record_exists() } return FALSE; } +#endif /* MFLOPPY */ # ifdef TOS #define comspec_exists() 1 # else +# ifdef MFLOPPY /* Return 1 if the comspec was found */ STATIC_OVL boolean comspec_exists() @@ -323,15 +327,17 @@ comspec_exists() int fd; char *comspec; - if (comspec = getcomspec()) + if ((comspec = getcomspec())) if ((fd = open(comspec, O_RDONLY)) >= 0) { (void) close(fd); return TRUE; } return FALSE; } +# endif /* MFLOPPY */ # endif + # ifdef MFLOPPY /* Prompt for game disk, then check for record file. */ @@ -429,7 +435,7 @@ const char *name, *mode; */ (void) strncpy(buf, name, BUFSIZ - 1); buf[BUFSIZ-1] = '\0'; - if (fp = fopen(buf, mode)) + if ((fp = fopen(buf, mode))) return fp; else { int ccnt = 0; @@ -445,8 +451,8 @@ const char *name, *mode; ccnt++; } (void) strncpy(bp, name, (BUFSIZ - ccnt) - 2); - bp[BUFSIZ-1] = '\0'; - if (fp = fopen(buf, mode)) + bp[BUFSIZ - ccnt - 1] = '\0'; + if ((fp = fopen(buf, mode))) return fp; if (*pp) pp++; diff --git a/sys/share/pctty.c b/sys/share/pctty.c index 491e215..5dd3d00 100644 --- a/sys/share/pctty.c +++ b/sys/share/pctty.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pctty.c 3.3 90/22/02 +/* SCCS Id: @(#)pctty.c 3.4 1990/22/02 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/share/pcunix.c b/sys/share/pcunix.c index 1561a35..0064e33 100644 --- a/sys/share/pcunix.c +++ b/sys/share/pcunix.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)pcunix.c 3.3 94/11/07 */ +/* SCCS Id: @(#)pcunix.c 3.4 1994/11/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -21,65 +21,17 @@ extern void NDECL(clear_screen); #ifdef OVLB +#if 0 static struct stat buf; +#endif + # ifdef WANT_GETHDATE static struct stat hbuf; # endif -void -gethdate(name) -char *name; -{ -# ifdef WANT_GETHDATE -/* old version - for people short of space */ -/* -/* register char *np; -/* if(stat(name, &hbuf)) -/* error("Cannot get status of %s.", -/* (np = rindex(name, '/')) ? np+1 : name); -/* -/* version using PATH from: seismo!gregc@ucsf-cgl.ARPA (Greg Couch) */ - -/* - * The problem with #include is that this include file - * does not exist on all systems, and moreover, that it sometimes includes - * again, so that the compiler sees these typedefs twice. - */ -#define MAXPATHLEN 1024 - - register char *np, *path; - char filename[MAXPATHLEN+1], *getenv(); - int pathlen; - - if (index(name, '/') != (char *)0 || (path = getenv("PATH")) == (char *)0) - path = ""; - - for (;;) { - if ((np = index(path, ':')) == (char *)0) - np = path + strlen(path); /* point to end str */ - pathlen = np - path; - if (pathlen > MAXPATHLEN) - pathlen = MAXPATHLEN; - if (pathlen <= 1) { /* %% */ - (void) strncpy(filename, name, MAXPATHLEN); - } else { - (void) strncpy(filename, path, pathlen); - filename[pathlen] = '/'; - (void) strncpy(filename + pathlen + 1, name, - (MAXPATHLEN - 1) - pathlen); - } - filename[MAXPATHLEN] = '\0'; - if (stat(filename, &hbuf) == 0) - return; - if (*np == '\0') - path = ""; - path = np + 1; - } - if (strlen(name) > BUFSZ/2) - name = name + strlen(name) - BUFSZ/2; - error("Cannot get status of %s.", (np = rindex(name, '/')) ? np+1 : name); -# endif /* WANT_GETHDATE */ -} +#ifdef PC_LOCKING +static int NDECL(eraseoldlocks); +#endif #if 0 int @@ -144,11 +96,11 @@ eraseoldlocks() void getlock() { - register int i = 0, fd, c, ci, ct; + register int fd, c, ci, ct; char tbuf[BUFSZ]; const char *fq_lock; # if defined(MSDOS) && defined(NO_TERMS) - int grmode; + int grmode = iflags.grmode; # endif /* we ignore QUIT and INT at this point */ diff --git a/sys/share/sounds/README b/sys/share/sounds/README index 19d9964..74bddea 100644 --- a/sys/share/sounds/README +++ b/sys/share/sounds/README @@ -29,6 +29,6 @@ for the available hardware. Any comment on the sounds or their use is welcome: - h+@nada.kth.se Jon W{tte Mac Team + nethack-bugs@nethack.org diff --git a/sys/share/tclib.c b/sys/share/tclib.c index 4cd1a39..0ccfcb3 100644 --- a/sys/share/tclib.c +++ b/sys/share/tclib.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)tclib.c 3.3 96/02/25 */ +/* SCCS Id: @(#)tclib.c 3.4 1996/02/25 */ /* Copyright (c) Robert Patrick Rankin, 1995 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/share/unixtty.c b/sys/share/unixtty.c index d198d69..05b76b4 100644 --- a/sys/share/unixtty.c +++ b/sys/share/unixtty.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)unixtty.c 3.3 90/22/02 */ +/* SCCS Id: @(#)unixtty.c 3.4 1990/22/02 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -35,6 +35,11 @@ # define termstruct termio # endif # endif /* POSIX_TYPES */ +# ifdef LINUX +# include +# undef delay_output /* curses redefines this */ +# include +# endif # define kill_sym c_cc[VKILL] # define erase_sym c_cc[VERASE] # define intr_sym c_cc[VINTR] diff --git a/sys/share/uudecode.c b/sys/share/uudecode.c new file mode 100644 index 0000000..75e86f9 --- /dev/null +++ b/sys/share/uudecode.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 1983 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +/* + * Modified 12 April 1990 by Mark Adler for use on MSDOS systems with + * Microsoft C and Turbo C. + * + * Modifed 13 February 1991 by Greg Roelofs for use on VMS systems. As + * with the MS-DOS version, the setting of the file mode has been disabled. + * Compile and link normally (but note that the shared-image link option + * produces a binary only 6 blocks long, as opposed to the 137-block one + * produced by an ordinary link). To set up the VMS symbol to run the + * program ("run uudecode filename" won't work), do: + * uudecode :== "$disk:[directory]uudecode.exe" + * and don't forget the leading "$" or it still won't work. The binaries + * produced by this program are in VMS "stream-LF" format; this makes no + * difference to VMS when running decoded executables, nor to VMS unzip, + * but other programs such as zoo or arc may or may not require the file + * to be "BILFed" (or "unBILFed" or whatever). Also, unlike the other + * flavors, VMS files don't get overwritten (a higher version is created). + * + * Modified 13 April 1991 by Gary Mussar to be forgiving of systems that + * appear to be stripping trailing blanks. + * + * Modified 28 February 2002 for use on WIN32 systems with Microsoft C. + */ + +#ifndef lint +static char sccsid[] = "@(#)uudecode.c 5.5 (Berkeley) 7/6/88"; +#endif /* not lint */ + +#ifdef __MSDOS__ /* For Turbo C */ +#define MSDOS 1 +#endif + +#ifdef _WIN32 +#undef MSDOS +#undef __MSDOS__ +#ifndef WIN32 +#define WIN32 +#endif +#endif + +/* + * uudecode [input] + * + * create the specified file, decoding as you go. + * used with uuencode. + */ +#include + +#ifdef VMS +# include +# include +#else +# if !defined(MSDOS) && !defined(WIN32) +# include +# endif +# include /* MSDOS, WIN32, or UNIX */ +# include +# include +# include +#endif + +static void decode(FILE *, FILE *); +static void outdec(char *, FILE *, int); + +/* single-character decode */ +#define DEC(c) (((c) - ' ') & 077) + +int main(argc, argv) +int argc; +char **argv; +{ + FILE *in, *out; + int mode; + char dest[128]; + char buf[80]; + + /* optional input arg */ + if (argc > 1) { + if ((in = fopen(argv[1], "r")) == NULL) { + perror(argv[1]); + exit(1); + } + argv++; argc--; + } else + in = stdin; + + if (argc != 1) { + printf("Usage: uudecode [infile]\n"); + exit(2); + } + + /* search for header line */ + for (;;) { + if (fgets(buf, sizeof buf, in) == NULL) { + fprintf(stderr, "No begin line\n"); + exit(3); + } + if (strncmp(buf, "begin ", 6) == 0) + break; + } + (void)sscanf(buf, "begin %o %s", &mode, dest); + +#if !defined(MSDOS) && !defined(VMS) && !defined(WIN32) + /* handle ~user/file format */ + if (dest[0] == '~') { + char *sl; + struct passwd *getpwnam(); + struct passwd *user; + char dnbuf[100], *index(), *strcat(), *strcpy(); + + sl = index(dest, '/'); + if (sl == NULL) { + fprintf(stderr, "Illegal ~user\n"); + exit(3); + } + *sl++ = 0; + user = getpwnam(dest+1); + if (user == NULL) { + fprintf(stderr, "No such user as %s\n", dest); + exit(4); + } + strcpy(dnbuf, user->pw_dir); + strcat(dnbuf, "/"); + strcat(dnbuf, sl); + strcpy(dest, dnbuf); + } +#endif /* !defined(MSDOS) && !defined(VMS) */ + + /* create output file */ +#if defined(MSDOS) || defined(WIN32) + out = fopen(dest, "wb"); /* Binary file */ +#else + out = fopen(dest, "w"); +#endif + if (out == NULL) { + perror(dest); + exit(4); + } +#if !defined(MSDOS) && !defined(VMS) && !defined(WIN32) /* i.e., UNIX */ + chmod(dest, mode); +#endif + + decode(in, out); + + if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) { + fprintf(stderr, "No end line\n"); + exit(5); + } + exit(0); +} + +/* + * copy from in to out, decoding as you go along. + */ +void +decode(in, out) +FILE *in; +FILE *out; +{ + char buf[80]; + char *bp; + int n, i, expected; + + for (;;) { + /* for each input line */ + if (fgets(buf, sizeof buf, in) == NULL) { + printf("Short file\n"); + exit(10); + } + n = DEC(buf[0]); + if ((n <= 0) || (buf[0] == '\n')) + break; + + /* Calculate expected # of chars and pad if necessary */ + expected = ((n+2)/3)<<2; + for (i = strlen(buf)-1; i <= expected; i++) buf[i] = ' '; + + bp = &buf[1]; + while (n > 0) { + outdec(bp, out, n); + bp += 4; + n -= 3; + } + } +} + +/* + * output a group of 3 bytes (4 input characters). + * the input chars are pointed to by p, they are to + * be output to file f. n is used to tell us not to + * output all of them at the end of the file. + */ +void +outdec(p, f, n) +char *p; +FILE *f; +int n; +{ + int c1, c2, c3; + + c1 = DEC(*p) << 2 | DEC(p[1]) >> 4; + c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2; + c3 = DEC(p[2]) << 6 | DEC(p[3]); + if (n >= 1) + putc(c1, f); + if (n >= 2) + putc(c2, f); + if (n >= 3) + putc(c3, f); +} + +#if !defined(MSDOS) && !defined(VMS) && !defined(WIN32) +/* + * Return the ptr in sp at which the character c appears; + * NULL if not found + */ + +#ifndef NULL +#define NULL 0 +#endif + +char * +index(sp, c) +register char *sp, c; +{ + do { + if (*sp == c) + return(sp); + } while (*sp++); + return(NULL); +} +#endif + diff --git a/sys/unix/Install.unx b/sys/unix/Install.unx index f95025a..0668084 100644 --- a/sys/unix/Install.unx +++ b/sys/unix/Install.unx @@ -1,4 +1,4 @@ - Instructions for installing NetHack 3.3 + Instructions for installing NetHack 3.4 on a UNIX system ======================================= @@ -25,8 +25,8 @@ in Files, which should be in the top directory.) 2. Your Makefiles may still be in sys/unix with tags on the end of them. - If so, run setup.sh in that directory to distribute the Makefiles to - places they can do their work. (If later official patches change + If so, run "sh setup.sh" in that directory to distribute the Makefiles + to places they can do their work. (If later official patches change these Makefiles, setup.sh should be rerun to make sure you use the current copies.) @@ -85,7 +85,7 @@ Notes: 1. Save files and bones files from previous versions will not work with - NetHack 3.3. Don't bother trying to keep them. + NetHack 3.4. Don't bother trying to keep them. 2. To install an update of this version of NetHack after changing something, type 'make update' from the main directory. If you created the new diff --git a/sys/unix/Makefile.dat b/sys/unix/Makefile.dat index 8ed6f54..a691fce 100644 --- a/sys/unix/Makefile.dat +++ b/sys/unix/Makefile.dat @@ -1,5 +1,5 @@ # NetHack Makefile. -# SCCS Id: @(#)Makefile.dat 3.3 92/09/18 +# SCCS Id: @(#)Makefile.dat 3.4 1992/09/18 # for Atari # SHELL=E:/GEMINI2/MUPFEL.TTP @@ -43,13 +43,20 @@ rip.xpm: ../win/X11/rip.xpm mapbg.xpm: ../win/gnome/mapbg.xpm cp ../win/gnome/mapbg.xpm mapbg.xpm +nhsplash.xpm: ../win/Qt/nhsplash.xpm + cp ../win/Qt/nhsplash.xpm nhsplash.xpm + ../util/tile2img.ttp: (cd ../util ; make tile2img.ttp) +../util/xpm2img.ttp: + (cd ../util ; make xpm2img.ttp) nh16.img: ../util/tile2img.ttp ../win/share/monsters.txt \ ../win/share/objects.txt ../win/share/other.txt ../util/tile2img.ttp nh16.img +rip.img: ../util/xpm2img.ttp + ../util/xpm2img.ttp ../win/X11/rip.xpm rip.img title.img: # cp ../win/gem/title.img title.img $(UUDECODE) ../win/gem/title.uu @@ -118,3 +125,4 @@ dungeon: dungeon.def ../util/makedefs ../util/dgn_comp spotless: -rm -f spec_levs quest_levs *.lev $(VARDAT) dungeon dungeon.pdf -rm -f nhdat x11tiles beostiles pet_mark.xbm rip.xpm mapbg.xpm + -rm -f rip.img GEM_RSC.RSC title.img nh16.img diff --git a/sys/unix/Makefile.doc b/sys/unix/Makefile.doc index 1d68a41..076b2ba 100644 --- a/sys/unix/Makefile.doc +++ b/sys/unix/Makefile.doc @@ -1,5 +1,5 @@ # NetHack Makefile. -# SCCS Id: @(#)Makefile.doc 3.3 96/03/23 +# SCCS Id: @(#)Makefile.doc 3.4 1996/03/23 # for Atari # SHELL=E:/GEMINI2/MUPFEL.TTP @@ -14,6 +14,10 @@ GUIDEBOOK = Guidebook # regular ASCII file COLCMD = col -bx #COLCMD = col -b +# The command to use to generate a PostScript file +# PSCMD = ditroff | psdit +PSCMD = groff + # Use the "cat" GUIDECMD if nroff and/or tbl and/or col are not installed # GUIDECMD = cat Guidebook.txt GUIDECMD = tbl tmac.n Guidebook.mn | nroff | $(COLCMD) @@ -24,7 +28,7 @@ Guidebook: Guidebook.mn # Fancier output for those with ditroff, psdit and a PostScript printer. Guidebook.ps: Guidebook.mn - tbl tmac.n Guidebook.mn | ditroff | psdit > Guidebook.ps + tbl tmac.n Guidebook.mn | $(PSCMD) > Guidebook.ps # Guidebook.tex is the same as Guidebook.mn but formatted with LaTeX. # - The invocation command for LaTeX may vary in different installations. diff --git a/sys/unix/Makefile.src b/sys/unix/Makefile.src index 948f70b..cdd0ff3 100644 --- a/sys/unix/Makefile.src +++ b/sys/unix/Makefile.src @@ -1,5 +1,5 @@ # NetHack Makefile. -# SCCS Id: @(#)Makefile.src 3.3 97/04/17 +# SCCS Id: @(#)Makefile.src 3.4 2002/03/02 # newer makes predefine $(MAKE) to 'make' and do smarter processing of # recursive make calls if $(MAKE) is used @@ -40,8 +40,8 @@ SHELL=/bin/sh # # for UNIX systems SYSSRC = ../sys/share/ioctl.c ../sys/share/unixtty.c ../sys/unix/unixmain.c \ - ../sys/unix/unixunix.c -SYSOBJ = ioctl.o unixmain.o unixtty.o unixunix.o + ../sys/unix/unixunix.c ../sys/unix/unixres.c +SYSOBJ = ioctl.o unixmain.o unixtty.o unixunix.o unixres.o # # for Systos # SYSSRC = ../sys/atari/tos.c ../sys/share/pcmain.c ../sys/share/pcsys.c \ @@ -117,11 +117,11 @@ SYSOBJ = ioctl.o unixmain.o unixtty.o unixunix.o # flags for Linux # compile normally -# CFLAGS = -O2 -fomit-frame-pointer -I../include -I/usr/X11/include -# LFLAGS = -L/usr/X11/lib +# CFLAGS = -O2 -fomit-frame-pointer -I../include +# LFLAGS = -L/usr/X11R6/lib # OR compile backwards compatible a.out format -# CFLAGS = -O2 -b i486-linuxaout -fomit-frame-pointer -I../include -I/usr/X11/include -# LFLAGS = -b i486-linuxaout -L/usr/X11/lib +# CFLAGS = -O2 -b i486-linuxaout -fomit-frame-pointer -I../include +# LFLAGS = -b i486-linuxaout -L/usr/X11R6/lib # flags for BeOS # on a Mac/BeBox: @@ -175,8 +175,8 @@ WINX11OBJ = Window.o dialogs.o winX.o winmap.o winmenu.o winmesg.o \ # # Files for a Qt port # -WINQTSRC = ../win/Qt/qt_win.cpp ../win/Qt/qt_clust.cpp -WINQTOBJ = qt_win.o qt_clust.o tile.o +WINQTSRC = ../win/Qt/qt_win.cpp ../win/Qt/qt_clust.cpp ../win/Qt/qttableview.cpp +WINQTOBJ = qt_win.o qt_clust.o qttableview.o tile.o # # Files for a Gnome port # @@ -191,8 +191,8 @@ WINGNOMEOBJ = gnaskstr.o gnbind.o gnglyph.o gnmain.o gnmap.o gnmenu.o \ # # Files for a Gem port WINGEMSRC = ../win/gem/wingem.c ../win/gem/wingem1.c ../win/gem/load_img.c \ - tile.c -WINGEMOBJ = wingem.o wingem1.o load_img.o tile.o + ../win/gem/gr_rect.c tile.c +WINGEMOBJ = wingem.o wingem1.o load_img.o gr_rect.o tile.o # # Files for a BeOS InterfaceKit port -- not ready for prime time WINBESRC = @@ -212,7 +212,7 @@ WINOBJ = $(WINTTYOBJ) # Systos needs -lcurses16 if you use -mshort # AIX 3.1 on RS/6000 likes -lcurses if TERMINFO defined in unixconf.h # and -ltermcap otherwise -# Linux uses -ltermcap or -lncurses +# Linux uses -lncurses (newer) or -ltermcap (older) # Be uses -ltermcap # # libraries for tty ports @@ -305,8 +305,9 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \ botl.c cmd.c dbridge.c decl.c detect.c dig.c display.c dlb.c do.c \ do_name.c do_wear.c dog.c dogmove.c dokick.c dothrow.c drawing.c \ dungeon.c eat.c end.c engrave.c exper.c explode.c extralev.c \ - files.c fountain.c hack.c hacklib.c invent.c light.c lock.c mail.c \ - makemon.c mcastu.c mhitm.c mhitu.c minion.c mklev.c mkmap.c \ + files.c fountain.c hack.c hacklib.c invent.c light.c lock.c \ + mail.c makemon.c mapglyph.c mcastu.c mhitm.c mhitu.c minion.c \ + mklev.c mkmap.c \ mkmaze.c mkobj.c mkroom.c mon.c mondata.c monmove.c monst.c \ mplayer.c mthrowu.c muse.c music.c o_init.c objects.c objnam.c \ options.c pager.c pickup.c pline.c polyself.c potion.c pray.c \ @@ -320,7 +321,10 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \ SYSCSRC = ../sys/atari/tos.c ../sys/share/pcmain.c ../sys/share/pcsys.c \ ../sys/share/pctty.c ../sys/share/pcunix.c ../sys/share/random.c \ ../sys/share/ioctl.c ../sys/share/unixtty.c ../sys/unix/unixmain.c \ - ../sys/unix/unixunix.c ../sys/be/bemain.c + ../sys/unix/unixunix.c ../sys/unix/unixres.c ../sys/be/bemain.c + +# generated source files (tile.c is handled separately via WINxxxSRC) +GENCSRC = monstr.c vis_tab.c #tile.c # all windowing-system-dependent .c (for dependencies and such) WINCSRC = $(WINTTYSRC) $(WINX11SRC) $(WINGNOMESRC) $(WINGEMSRC) @@ -328,10 +332,10 @@ WINCSRC = $(WINTTYSRC) $(WINX11SRC) $(WINGNOMESRC) $(WINGEMSRC) WINCXXSRC = $(WINQTSRC) $(WINBESRC) # .c files for this version (for date.h) -VERSOURCES = $(HACKCSRC) $(SYSSRC) $(WINSRC) monstr.c vis_tab.c +VERSOURCES = $(HACKCSRC) $(SYSSRC) $(WINSRC) $(GENCSRC) # .c files for all versions using this Makefile (for lint and tags) -CSOURCES = $(HACKCSRC) $(SYSSRC) $(WINCSRC) monstr.c vis_tab.c +CSOURCES = $(HACKCSRC) $(SYSSRC) $(WINCSRC) $(GENCSRC) # all .h files except date.h, onames.h, pm.h, and vis_tab.h which would @@ -358,8 +362,9 @@ HOBJ = $(FIRSTOBJ) allmain.o alloc.o apply.o artifact.o attrib.o ball.o \ bones.o botl.o cmd.o dbridge.o decl.o detect.o dig.o display.o dlb.o \ do.o do_name.o do_wear.o dog.o dogmove.o dokick.o dothrow.o \ drawing.o dungeon.o eat.o end.o engrave.o exper.o explode.o \ - extralev.o files.o fountain.o hack.o hacklib.o invent.o light.o lock.o \ - mail.o makemon.o mcastu.o mhitm.o mhitu.o minion.o mklev.o mkmap.o \ + extralev.o files.o fountain.o hack.o hacklib.o invent.o light.o \ + lock.o mail.o makemon.o mapglyph.o mcastu.o mhitm.o mhitu.o \ + minion.o mklev.o mkmap.o \ mkmaze.o mkobj.o mkroom.o mon.o mondata.o monmove.o monstr.o \ mplayer.o mthrowu.o muse.o music.o o_init.o objnam.o options.o \ pager.o pickup.o pline.o polyself.o potion.o pray.o priest.o \ @@ -450,6 +455,9 @@ qt_kde0.moc: ../include/qt_kde0.h qt_win.moc: ../include/qt_win.h $(QTDIR)/bin/moc ../include/qt_win.h > qt_win.moc +qttableview.moc: ../include/qttableview.h + $(QTDIR)/bin/moc ../include/qttableview.h > qttableview.moc + $(MAKEDEFS): ../util/makedefs.c $(CONFIG_H) ../include/permonst.h \ ../include/objclass.h ../include/monsym.h \ ../include/artilist.h ../include/dungeon.h ../include/obj.h \ @@ -465,8 +473,8 @@ monstr.c: $(MAKEDEFS) @( cd ../util ; $(MAKE) ../src/monstr.c ) ../include/vis_tab.h: $(MAKEDEFS) @( cd ../util ; $(MAKE) ../include/vis_tab.h ) -vis_tab.c: $(MAKEDEFS) - @( cd ../util ; $(MAKE) ../src/vis_tab.c ) +# makedefs -z makes both vis_tab.h and vis_tab.c, but writes the .h first +vis_tab.c: ../include/vis_tab.h tile.c: ../win/share/tilemap.c $(HACK_H) @( cd ../util ; $(MAKE) ../src/tile.c ) @@ -510,8 +518,10 @@ spotless: clean -rm -f ../win/gnome/gn_rip.h -depend: ../sys/unix/depend.awk $(SYSCSRC) $(WINCSRC) $(WINCXXSRC) $(HACKCSRC) - $(AWK) -f ../sys/unix/depend.awk ../include/*.h $(SYSCSRC) $(WINCSRC) $(WINCXXSRC) $(HACKCSRC) >makedep +depend: ../sys/unix/depend.awk \ + $(SYSCSRC) $(WINCSRC) $(WINCXXSRC) $(GENCSRC) $(HACKCSRC) + $(AWK) -f ../sys/unix/depend.awk ../include/*.h \ + $(SYSCSRC) $(WINCSRC) $(WINCXXSRC) $(GENCSRC) $(HACKCSRC) >makedep @echo '/^# DO NOT DELETE THIS LINE OR CHANGE ANYTHING BEYOND IT/+2,$$d' >eddep @echo '$$r makedep' >>eddep @echo 'w' >>eddep @@ -571,6 +581,8 @@ unixmain.o: ../sys/unix/unixmain.c $(HACK_H) ../include/dlb.h $(CC) $(CFLAGS) -c ../sys/unix/unixmain.c unixunix.o: ../sys/unix/unixunix.c $(HACK_H) $(CC) $(CFLAGS) -c ../sys/unix/unixunix.c +unixres.o: ../sys/unix/unixres.c $(CONFIG_H) + $(CC) $(CFLAGS) -c ../sys/unix/unixres.c bemain.o: ../sys/be/bemain.c $(HACK_H) ../include/dlb.h $(CC) $(CFLAGS) -c ../sys/be/bemain.c getline.o: ../win/tty/getline.c $(HACK_H) ../include/func_tab.h @@ -614,7 +626,7 @@ gnaskstr.o: ../win/gnome/gnaskstr.c ../win/gnome/gnaskstr.h \ gnbind.o: ../win/gnome/gnbind.c ../win/gnome/gnbind.h ../win/gnome/gnmain.h \ ../win/gnome/gnaskstr.h ../win/gnome/gnyesno.h $(CC) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnbind.c -gnglyph.o: ../win/gnome/gnglyph.c ../win/gnome/gnglyph.h +gnglyph.o: ../win/gnome/gnglyph.c ../win/gnome/gnglyph.h ../include/tile2x11.h $(CC) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnglyph.c gnmain.o: ../win/gnome/gnmain.c ../win/gnome/gnmain.h ../win/gnome/gnsignal.h \ ../win/gnome/gnbind.h ../win/gnome/gnopts.h $(HACK_H) \ @@ -654,14 +666,20 @@ wingem1.o: ../win/gem/wingem1.c ../include/gem_rsc.h ../include/load_img.h \ $(CC) $(CFLAGS) -c ../win/gem/wingem1.c load_img.o: ../win/gem/load_img.c ../include/load_img.h $(CC) $(CFLAGS) -c ../win/gem/load_img.c +gr_rect.o: ../win/gem/gr_rect.c + $(CC) $(CFLAGS) -c ../win/gem/gr_rect.c tile.o: tile.c $(HACK_H) qt_win.o: ../win/Qt/qt_win.cpp $(HACK_H) ../include/func_tab.h \ - ../include/dlb.h ../include/patchlevel.h ../include/qt_win.h \ - ../include/qt_clust.h ../include/qt_kde0.h \ - ../include/qt_xpms.h qt_win.moc qt_kde0.moc + ../include/dlb.h ../include/patchlevel.h ../include/tile2x11.h \ + ../include/qt_win.h ../include/qt_clust.h ../include/qt_kde0.h \ + ../include/qt_xpms.h qt_win.moc qt_kde0.moc qttableview.moc $(CXX) $(CXXFLAGS) -c ../win/Qt/qt_win.cpp qt_clust.o: ../win/Qt/qt_clust.cpp ../include/qt_clust.h $(CXX) $(CXXFLAGS) -c ../win/Qt/qt_clust.cpp +qttableview.o: ../win/Qt/qttableview.cpp ../include/qttableview.h + $(CXX) $(CXXFLAGS) -c ../win/Qt/qttableview.cpp +monstr.o: monstr.c $(CONFIG_H) +vis_tab.o: vis_tab.c $(CONFIG_H) ../include/vis_tab.h allmain.o: allmain.c $(HACK_H) alloc.o: alloc.c $(CONFIG_H) apply.o: apply.c $(HACK_H) ../include/edog.h @@ -702,6 +720,7 @@ lock.o: lock.c $(HACK_H) mail.o: mail.c $(HACK_H) ../include/mail.h makemon.o: makemon.c $(HACK_H) ../include/epri.h ../include/emin.h \ ../include/edog.h +mapglyph.o: mapglyph.c $(HACK_H) mcastu.o: mcastu.c $(HACK_H) mhitm.o: mhitm.c $(HACK_H) ../include/artifact.h ../include/edog.h mhitu.o: mhitu.c $(HACK_H) ../include/artifact.h ../include/edog.h @@ -730,7 +749,7 @@ options.o: options.c $(CONFIG_H) ../include/objclass.h ../include/flag.h \ $(HACK_H) ../include/tcap.h pager.o: pager.c $(HACK_H) ../include/dlb.h pickup.o: pickup.c $(HACK_H) -pline.o: pline.c $(HACK_H) ../include/epri.h +pline.o: pline.c $(HACK_H) ../include/epri.h ../include/edog.h polyself.o: polyself.c $(HACK_H) potion.o: potion.c $(HACK_H) pray.o: pray.c $(HACK_H) ../include/epri.h @@ -740,7 +759,7 @@ quest.o: quest.c $(HACK_H) ../include/qtext.h questpgr.o: questpgr.c $(HACK_H) ../include/dlb.h ../include/qtext.h read.o: read.c $(HACK_H) rect.o: rect.c $(HACK_H) -region.o: region.c $(HACK_H) +region.o: region.c $(HACK_H) ../include/lev.h restore.o: restore.c $(HACK_H) ../include/lev.h ../include/tcap.h rip.o: rip.c $(HACK_H) rnd.o: rnd.c $(HACK_H) diff --git a/sys/unix/Makefile.top b/sys/unix/Makefile.top index c701b80..fafd71a 100644 --- a/sys/unix/Makefile.top +++ b/sys/unix/Makefile.top @@ -1,5 +1,5 @@ # NetHack Makefile. -# SCCS Id: @(#)Makefile.top 3.3 95/01/05 +# SCCS Id: @(#)Makefile.top 3.4 1995/01/05 # newer makes predefine $(MAKE) to 'make' and do smarter processing of # recursive make calls if $(MAKE) is used @@ -44,7 +44,7 @@ VARDATND = # VARDATND = x11tiles pet_mark.xbm # VARDATND = x11tiles pet_mark.xbm rip.xpm # for Atari/Gem -# VARDATND = nh16.img title.img GEM_RSC.RSC +# VARDATND = nh16.img title.img GEM_RSC.RSC rip.img # for BeOS # VARDATND = beostiles # for Gnome @@ -90,42 +90,45 @@ $(GAME): all: $(GAME) Guidebook $(VARDAT) dungeon spec_levs check-dlb @echo "Done." +# Note: many of the dependencies below are here to allow parallel make +# to generate valid output + Guidebook: ( cd doc ; $(MAKE) Guidebook ) manpages: ( cd doc ; $(MAKE) manpages ) -data: +data: $(GAME) ( cd dat ; $(MAKE) data ) -rumors: +rumors: $(GAME) ( cd dat ; $(MAKE) rumors ) -oracles: +oracles: $(GAME) ( cd dat ; $(MAKE) oracles ) # Note: options should have already been made with make, but... -options: +options: $(GAME) ( cd dat ; $(MAKE) options ) -quest.dat: +quest.dat: $(GAME) ( cd dat ; $(MAKE) quest.dat ) -spec_levs: +spec_levs: dungeon ( cd util ; $(MAKE) lev_comp ) ( cd dat ; $(MAKE) spec_levs ) ( cd dat ; $(MAKE) quest_levs ) -dungeon: +dungeon: $(GAME) ( cd util ; $(MAKE) dgn_comp ) ( cd dat ; $(MAKE) dungeon ) -x11tiles: +x11tiles: $(GAME) ( cd util ; $(MAKE) tile2x11 ) ( cd dat ; $(MAKE) x11tiles ) -beostiles: +beostiles: $(GAME) ( cd util ; $(MAKE) tile2beos ) ( cd dat ; $(MAKE) beostiles ) @@ -138,18 +141,23 @@ rip.xpm: mapbg.xpm: (cd dat ; $(MAKE) mapbg.xpm ) -nh16.img: +nhsplash.xpm: + ( cd dat ; $(MAKE) nhsplash.xpm ) + +nh16.img: $(GAME) ( cd util ; $(MAKE) tile2img.ttp ) ( cd dat ; $(MAKE) nh16.img ) +rip.img: + ( cd util ; $(MAKE) xpm2img.ttp ) + ( cd dat ; $(MAKE) rip.img ) GEM_RSC.RSC: ( cd dat ; $(MAKE) GEM_RSC.RSC ) title.img: ( cd dat ; $(MAKE) title.img ) -check-dlb: - ( cd dat; $(MAKE) options ) +check-dlb: options @if egrep -s librarian dat/options ; then $(MAKE) dlb ; else true ; fi dlb: diff --git a/sys/unix/Makefile.utl b/sys/unix/Makefile.utl index e754357..ec560b6 100644 --- a/sys/unix/Makefile.utl +++ b/sys/unix/Makefile.utl @@ -1,5 +1,5 @@ # Makefile for NetHack's utility programs. -# SCCS Id: @(#)Makefile.utl 3.3 97/04/19 +# SCCS Id: @(#)Makefile.utl 3.4 1997/04/19 # newer makes predefine $(MAKE) to 'make' and do smarter processing of # recursive make calls if $(MAKE) is used @@ -72,11 +72,11 @@ # flags for Linux # compile normally -# CFLAGS = -O2 -fomit-frame-pointer -I../include -I/usr/X11/include -# LFLAGS = -L/usr/X11/lib +# CFLAGS = -O2 -fomit-frame-pointer -I../include +# LFLAGS = -L/usr/X11R6/lib # OR compile backwards compatible a.out format -# CFLAGS = -O2 -b i486-linuxaout -fomit-frame-pointer -I../include -I/usr/X11/include -# LFLAGS = -b i486-linuxaout -L/usr/X11/lib +# CFLAGS = -O2 -b i486-linuxaout -fomit-frame-pointer -I../include +# LFLAGS = -b i486-linuxaout -L/usr/X11R6/lib # flags for BeOS using the command line # remember to uncomment flex and bison below @@ -187,8 +187,8 @@ makedefs.o: makedefs.c $(CONFIG_H) ../include/permonst.h \ ./makedefs -m ../include/vis_tab.h: makedefs ./makedefs -z -../src/vis_tab.c: makedefs - ./makedefs -z +# makedefs -z makes both vis_tab.h and vis_tab.c, but writes the .h first +../src/vis_tab.c: ../include/vis_tab.h lintdefs: @lint -axbh -I../include -DLINT $(MAKESRC) $(CMONOBJ) | sed '/_flsbuf/d' @@ -304,6 +304,8 @@ tile2x11: tile2x11.o $(TEXT_IO) tile2img.ttp: tile2img.o bitmfile.o $(TEXT_IO) $(CC) $(LFLAGS) -o tile2img.ttp tile2img.o bitmfile.o $(TEXT_IO) $(LIBS) +xpm2img.ttp: xpm2img.o bitmfile.o + $(CC) $(LFLAGS) -o xpm2img.ttp xpm2img.o bitmfile.o $(LIBS) tile2beos: tile2beos.o $(TEXT_IO) $(CC) $(LFLAGS) -o tile2beos tile2beos.o $(TEXT_IO) -lbe @@ -332,6 +334,8 @@ tile2x11.o: ../win/X11/tile2x11.c $(HACK_H) ../include/tile.h \ tile2img.o: ../win/gem/tile2img.c $(HACK_H) ../include/tile.h \ ../include/bitmfile.h $(CC) $(CFLAGS) -c ../win/gem/tile2img.c +xpm2img.o: ../win/gem/xpm2img.c $(HACK_H) ../include/bitmfile.h + $(CC) $(CFLAGS) -c ../win/gem/xpm2img.c bitmfile.o: ../win/gem/bitmfile.c ../include/bitmfile.h $(CC) $(CFLAGS) -c ../win/gem/bitmfile.c @@ -381,4 +385,4 @@ spotless: clean -rm -f ../include/lev_comp.h ../include/dgn_comp.h -rm -f ../include/tile.h -rm -f makedefs lev_comp dgn_comp recover dlb - -rm -f gif2txt txt2ppm tile2x11 tile2img.ttp tilemap + -rm -f gif2txt txt2ppm tile2x11 tile2img.ttp xpm2img.ttp tilemap diff --git a/sys/unix/README.linux b/sys/unix/README.linux new file mode 100644 index 0000000..e817941 --- /dev/null +++ b/sys/unix/README.linux @@ -0,0 +1,89 @@ +NetHack 3.4.0 Linux Elf + +This README provides the instructions for using the official Linux binary, +system platform requirements, as well as steps used to create that binary. +The same steps can be used from the source distribution to create a similar +binary. + +The official Linux binary has support for tty and X11 windowing systems, but +not Qt. This means you will need to have X11 libraries installed on your +system to run this binary, even in its tty flavor. + + +The Linux binary package assumes that you have a user and a group named +"games" on your system. If you do not, you can simplify installation by +creating them first. + +gunzip and untar the package, preserving permissions, from / to put the +NetHack files in /usr/games/nethack and /usr/games/lib/nethackdir. + +(If you have old record and logfile entries from a previous NetHack +version, you might want to save copies before they get overwritten by the +new empty files; old saved games and bones files won't work with 3.4.0). + +In addition to data files for running the game, you will find other useful +things in /usr/games/lib/nethackdir (such as a copy of this README :-). + +The general documentation Guidebook.txt and the processed man pages +nethack.txt and recover.txt should provide an introduction to the game. + +The sample config file called dot.nethackrc can be used by copying +it to your home directory as .nethackrc and modifying it to your liking. + +If you are running X11 copy the nh10.pcf and ibm.pcf font files from +/usr/games/lib/nethackdir to a X11 fonts directory (such as +/usr/X11/lib/X11/fonts/misc) and run "mkfontdir", then restart X +windows to load them. Also consider putting NetHack.ad in +/usr/X11/lib/X11/app-defaults or its contents in your .Xdefaults or +.Xresources. + + +The official Linux binary is set up to run setgid games, which allows +multiple users on your system to play the game and prevents cheating by +unprivileged users. The usual default for NetHack is setuid games, but +this causes problems with accessing .nethackrc on distributions with +restrictive default security on home directories and users who don't know +the tradeoffs of various permission settings. + + +If you have problems, send us some email. + +nethack-bugs@nethack.org + + + +Steps used to build this binary release + +System: egcs-1.1.2, XFree86-3.3.6, ncurses-5.0, glibc-2.1.3 + +0. Makefile.top: GAMEGRP = games + GAMEPERM = 02775 + FILEPERM = 0664 + EXEPERM = 0775 + DIRPERM = 0775 + VARDATND = x11tiles pet_mark.xbm rip.xpm + +1. Makefile.src: define LINUX and linux options throughout + WINSRC = $(WINTTYSRC) $(WINX11SRC) + WINOBJ = $(WINTTYOBJ) $(WINX11OBJ) + WINTTYLIB = /usr/lib/libncurses.a + Include Xpm libs in WINX11LIB + WINLIB = $(WINTTYLIB) $(WINX11LIB) + +2. Makefile.utl: define LINUX and linux options throughout + Use bison/flex instead of yacc/lex + +3. config.h: define X11 window support, XPM support. + define COMPRESS as /bin/gzip as that is where it + seems to reside on newer Linux's. + define COMPRESS_EXTENSION as ".gz" + define DLB + +4. unixconf.h: define LINUX + define TIMED_DELAY + +5. make all; (cd util; make recover); su; make install; + cp util/recover /usr/games/lib/nethackdir/recover + +6. Convert nh10.bdf and ibm.bdf to proper font files and place in + font path. diff --git a/sys/unix/depend.awk b/sys/unix/depend.awk index 195b8eb..26a9489 100644 --- a/sys/unix/depend.awk +++ b/sys/unix/depend.awk @@ -35,7 +35,7 @@ FNR == 1 { output_dep() #finish previous file } /^\#[ \t]*include[ \t]+\"/ { #find `#include "X"' incl = $2; - #[3.3.1: gnomehack headers currently aren't in include] + #[3.4.0: gnomehack headers currently aren't in include] if (incl ~ /\.h$/) { if (incl ~ /^gn/) # gnomehack special case incl = "../win/gnome/" incl diff --git a/sys/unix/nethack.sh b/sys/unix/nethack.sh index 32dd8a4..3491e8d 100644 --- a/sys/unix/nethack.sh +++ b/sys/unix/nethack.sh @@ -1,5 +1,5 @@ #!/bin/sh -# SCCS Id: @(#)nethack.sh 3.3 90/02/26 +# SCCS Id: @(#)nethack.sh 3.4 1990/02/26 HACKDIR=/usr/games/lib/nethackdir export HACKDIR diff --git a/sys/unix/setup.sh b/sys/unix/setup.sh old mode 100755 new mode 100644 diff --git a/sys/unix/unixmain.c b/sys/unix/unixmain.c index 7587b2f..a88507b 100644 --- a/sys/unix/unixmain.c +++ b/sys/unix/unixmain.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)unixmain.c 3.3 97/01/22 */ +/* SCCS Id: @(#)unixmain.c 3.4 1997/01/22 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -55,6 +55,35 @@ char *argv[]; #endif boolean exact_username; +#if defined(__APPLE__) + /* special hack to change working directory to a resource fork when + running from finder --sam */ +#define MAC_PATH_VALUE ".app/Contents/MacOS/" + char mac_cwd[1024], *mac_exe = argv[0], *mac_tmp; + int arg0_len = strlen(mac_exe), mac_tmp_len, mac_lhs_len=0; + getcwd(mac_cwd, 1024); + if(mac_exe[0] == '/' && !strcmp(mac_cwd, "/")) { + if((mac_exe = strrchr(mac_exe, '/'))) + mac_exe++; + else + mac_exe = argv[0]; + mac_tmp_len = (strlen(mac_exe) * 2) + strlen(MAC_PATH_VALUE); + if(mac_tmp_len <= arg0_len) { + mac_tmp = malloc(mac_tmp_len + 1); + sprintf(mac_tmp, "%s%s%s", mac_exe, MAC_PATH_VALUE, mac_exe); + if(!strcmp(argv[0] + (arg0_len - mac_tmp_len), mac_tmp)) { + mac_lhs_len = (arg0_len - mac_tmp_len) + strlen(mac_exe) + 5; + if(mac_lhs_len > mac_tmp_len - 1) + mac_tmp = realloc(mac_tmp, mac_lhs_len); + strncpy(mac_tmp, argv[0], mac_lhs_len); + mac_tmp[mac_lhs_len] = '\0'; + chdir(mac_tmp); + } + free(mac_tmp); + } + } +#endif + hname = argv[0]; hackpid = getpid(); (void) umask(0777 & ~FCMASK); @@ -107,13 +136,6 @@ char *argv[]; } /* - * Find the creation date of this game, - * so as to avoid restoring outdated savefiles. - */ - gethdate(hname); - - /* - * We cannot do chdir earlier, otherwise gethdate will fail. * Change directories before we initialize the window system so * we can find the tile file. */ @@ -363,6 +385,9 @@ char *argv[]; flags.initrace = i; } break; + case '@': + flags.randomall = 1; + break; default: if ((i = str2role(&argv[0][1])) >= 0) { flags.initrole = i; @@ -491,4 +516,25 @@ wd_message() if (discover) You("are in non-scoring discovery mode."); } + +/* + * Add a slash to any name not ending in /. There must + * be room for the / + */ +void +append_slash(name) +char *name; +{ + char *ptr; + + if (!*name) + return; + ptr = name + (strlen(name) - 1); + if (*ptr != '/') { + *++ptr = '/'; + *++ptr = '\0'; + } + return; +} + /*unixmain.c*/ diff --git a/sys/unix/unixres.c b/sys/unix/unixres.c new file mode 100644 index 0000000..390cc85 --- /dev/null +++ b/sys/unix/unixres.c @@ -0,0 +1,213 @@ +/* SCCS Id: @(#)unixres.c 3.4 2001/07/08 */ +/* Copyright (c) Slash'EM development team, 2001. */ +/* NetHack may be freely redistributed. See license for details. */ + +/* [ALI] This module defines nh_xxx functions to replace getuid etc which + * will hide privileges from the caller if so desired. + * + * Currently supported UNIX variants: + * Linux version 2.1.44 and above + * FreeBSD (versions unknown) + * + * Note: SunOS and Solaris have no mechanism for retrieving the saved id, + * so temporarily dropping privileges on these systems is sufficient to + * hide them. + */ + +#include "config.h" + +#ifdef GETRES_SUPPORT + +# if defined(LINUX) + +static _syscall3(int, getresuid, unsigned short *, ruid, \ + unsigned short *, euid, unsigned short *, suid) +static _syscall3(int, getresgid, unsigned short *, rgid, \ + unsigned short *, egid, unsigned short *, sgid) + +static int +real_getresuid(ruid, euid, suid) +uid_t *ruid, *euid, *suid; +{ + int retval; + unsigned short r, e, s; + retval = getresuid(&r, &e, &s); + if (!retval) { + *ruid = r; + *euid = e; + *suid = s; + } + return retval; +} + +static int +real_getresgid(rgid, egid, sgid) +gid_t *rgid, *egid, *sgid; +{ + int retval; + unsigned short r, e, s; + retval = getresgid(&r, &e, &s); + if (!retval) { + *rgid = r; + *egid = e; + *sgid = s; + } + return retval; +} + +# else +# if defined(BSD) || defined(SVR4) + +# ifdef SYS_getresuid + +static int +real_getresuid(ruid, euid, suid) +uid_t *ruid, *euid, *suid; +{ + return syscall(SYS_getresuid, ruid, euid, suid); +} + +# else /* SYS_getresuid */ + +static int +real_getresuid(ruid, euid, suid) +uid_t *ruid, *euid, *suid; +{ + int retval; + int pfd[2]; + struct stat st; + if (pipe(pfd)) + return -1; + retval = fstat(pfd[0], &st); + close(pfd[0]); + close(pfd[1]); + if (!retval) { + *euid = st.st_uid; + *ruid = syscall(SYS_getuid); + *suid = *ruid; /* Not supported under SVR4 */ + } + return retval; +} + +# endif /* SYS_getresuid */ + +# ifdef SYS_getresgid + +static int +real_getresgid(rgid, egid, sgid) +gid_t *rgid, *egid, *sgid; +{ + return syscall(SYS_getresgid, rgid, egid, sgid); +} + +# else /* SYS_getresgid */ + +static int +real_getresgid(rgid, egid, sgid) +gid_t *rgid, *egid, *sgid; +{ + int retval; + int pfd[2]; + struct stat st; + if (pipe(pfd)) + return -1; + retval = fstat(pfd[0], &st); + close(pfd[0]); + close(pfd[1]); + if (!retval) { + *egid = st.st_gid; + *rgid = syscall(SYS_getgid); + *sgid = *rgid; /* Not supported under SVR4 */ + } + return retval; +} + +# endif /* SYS_getresgid */ +# endif /* BSD || SVR4 */ +# endif /* LINUX */ + +static unsigned int hiding_privileges = 0; + +/* + * Note: returns the value _after_ action. + */ + +int +hide_privileges(flag) +boolean flag; +{ + if (flag) + hiding_privileges++; + else if (hiding_privileges) + hiding_privileges--; + return hiding_privileges; +} + +int +nh_getresuid(ruid, euid, suid) +uid_t *ruid, *euid, *suid; +{ + int retval = real_getresuid(ruid, euid, suid); + if (!retval && hiding_privileges) + *euid = *suid = *ruid; + return retval; +} + +uid_t +nh_getuid() +{ + uid_t ruid, euid, suid; + (void) real_getresuid(&ruid, &euid, &suid); + return ruid; +} + +uid_t +nh_geteuid() +{ + uid_t ruid, euid, suid; + (void) real_getresuid(&ruid, &euid, &suid); + if (hiding_privileges) + euid = ruid; + return euid; +} + +int +nh_getresgid(rgid, egid, sgid) +gid_t *rgid, *egid, *sgid; +{ + int retval = real_getresgid(rgid, egid, sgid); + if (!retval && hiding_privileges) + *egid = *sgid = *rgid; + return retval; +} + +gid_t +nh_getgid() +{ + gid_t rgid, egid, sgid; + (void) real_getresgid(&rgid, &egid, &sgid); + return rgid; +} + +gid_t +nh_getegid() +{ + gid_t rgid, egid, sgid; + (void) real_getresgid(&rgid, &egid, &sgid); + if (hiding_privileges) + egid = rgid; + return egid; +} + +#else /* GETRES_SUPPORT */ + +# ifdef GNOME_GRAPHICS +int +hide_privileges(flag) +boolean flag; +{ + return 0; +} +# endif + +#endif /* GETRES_SUPPORT */ diff --git a/sys/unix/unixunix.c b/sys/unix/unixunix.c index 48d453c..bb45f36 100644 --- a/sys/unix/unixunix.c +++ b/sys/unix/unixunix.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)unixunix.c 3.3 94/11/07 */ +/* SCCS Id: @(#)unixunix.c 3.4 1994/11/07 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -22,91 +22,7 @@ extern void NDECL(linux_mapon); extern void NDECL(linux_mapoff); #endif -static struct stat buf, hbuf; - -void -gethdate(name) - const char *name; -{ -/* old version - for people short of space - * - * register char *np; - * if(stat(name, &hbuf)) - * error("Cannot get status of %s.", - * (np = rindex(name, '/')) ? np+1 : name); - */ -/* version using PATH from: seismo!gregc@ucsf-cgl.ARPA (Greg Couch) */ - -/* - * The problem with #include is that this include file - * does not exist on all systems, and moreover, that it sometimes includes - * again, so that the compiler sees these typedefs twice. - */ -#define MAXPATHLEN 1024 - - register const char *np, *path; - char filename[MAXPATHLEN+1]; - int pathlen; - - if (index(name, '/') != (char *)0 || - (path = getenv("PATH")) == (char *)0) - path = ""; - - for (;;) { - if ((np = index(path, ':')) == (char *)0) - np = path + strlen(path); /* point to end str */ - pathlen = np - path; - if (pathlen > MAXPATHLEN) - pathlen = MAXPATHLEN; - if (pathlen <= 1) { /* %% */ - (void) strncpy(filename, name, MAXPATHLEN); - } else { - (void) strncpy(filename, path, pathlen); - filename[pathlen] = '/'; - (void) strncpy(filename + pathlen + 1, name, - (MAXPATHLEN - 1) - pathlen); - } - filename[MAXPATHLEN] = '\0'; - if (stat(filename, &hbuf) == 0) - return; - if (*np == '\0') - break; - path = np + 1; - } - if (strlen(name) > BUFSZ/2) - name = name + strlen(name) - BUFSZ/2; -#if defined(BOS) && defined(NHSTDC) -/* - * This one is really **STUPID**. I don't know why it's happening - * as similar constructs work elsewhere, but... - */ - if((np = rindex(name, '/'))) - error("Cannot get status of %s.", np+1); - else error("Cannot get status of %s.", name); -#else - error("Cannot get status of %s.", - (np = rindex(name, '/')) ? np+1 : name); -#endif -} - -#if 0 -int -uptodate(fd) -int fd; -{ - if(fstat(fd, &buf)) { - pline("Cannot get status of saved level? "); - wait_synch(); - return(0); - } - if(buf.st_mtime < hbuf.st_mtime) { - pline("Saved level is out of date. "); - wait_synch(); - return(0); - } - return(1); -} -#endif +static struct stat buf; /* see whether we should throw away this xlock file */ static int @@ -368,3 +284,52 @@ int wt; return(0); } #endif + +#ifdef GETRES_SUPPORT + +extern int FDECL(nh_getresuid, (uid_t *, uid_t *, uid_t *)); +extern uid_t NDECL(nh_getuid); +extern uid_t NDECL(nh_geteuid); +extern int FDECL(nh_getresgid, (gid_t *, gid_t *, gid_t *)); +extern gid_t NDECL(nh_getgid); +extern gid_t NDECL(nh_getegid); + +int +(getresuid)(ruid, euid, suid) +uid_t *ruid, *euid, *suid; +{ + return nh_getresuid(ruid, euid, suid); +} + +uid_t +(getuid)() +{ + return nh_getuid(); +} + +uid_t +(geteuid)() +{ + return nh_geteuid(); +} + +int +(getresgid)(rgid, egid, sgid) +gid_t *rgid, *egid, *sgid; +{ + return nh_getresgid(rgid, egid, sgid); +} + +gid_t +(getgid)() +{ + return nh_getgid(); +} + +gid_t +(getegid)() +{ + return nh_getegid(); +} + +#endif /* GETRES_SUPPORT */ diff --git a/sys/vms/Install.vms b/sys/vms/Install.vms index f7568ae..3b54e19 100644 --- a/sys/vms/Install.vms +++ b/sys/vms/Install.vms @@ -1,21 +1,22 @@ - Instructions for Installing NetHack 3.3.1 + Instructions for Installing NetHack 3.4.0 on a VMS system ========================================= 0. Please read this entire file before trying to build or install NetHack, then read it again! -1. Building NetHack requires a C compiler (either VAX C, DEC C, or GNU C) - and VMS version V4.6 or later (but see note #9). This release has been - tested on VAX/VMS V5.5-2 and V6.2, and Alpha/VMS V6.2 and V7.1. The - build procedure (vmsbuild.com) should not need to be modified; it accepts +1. Building NetHack requires a C compiler (either Compaq C, DEC C, + VAX C, or GNU C) and VMS version V4.6 or later (but see note #9). + This release has been tested with Compaq C V6.4 on Alpha/VMS V7.1 + and with VAX C V3.2 and GNU C 2.7.1 on VAX/VMS V5.5-2. The build + procedure (vmsbuild.com) should not need to be modified; it accepts an option for selecting the compiler, and it can detect different versions which might require specific command qualifiers. Versions of VAXC earlier than V2.3 will produce many warning messages (about 200 per source file; over to 25,000 total!), but NetHack has been verified to compile, link, and execute correctly when built with VAXC - V2.2 using vmsbuild.com. There is also a set of Makefiles suitable - for use with MMS; they may or may not work with other make utilities. + V2.2 using vmsbuild.com. There is also a set of Makefiles suitable for + use with MMS or MMK; they may or may not work with other make utilities. 2. Make sure all the NetHack files are in the appropriate directory structure. You should set up a directory--referred to as "top" below @@ -35,13 +36,10 @@ The following subdirectories may be present, but are not useful for building NetHack on VMS and are not required: [.sys .amiga] -- AmigaDOS - [.sys .amiga .splitter] [.sys .atari] -- Atari TOS [.sys .be] -- BeBox BeOS [.sys .mac] -- Macintosh - [.sys .mac .old] [.sys .msdos] -- MSDOS for IBM PCs and compatibles - [.sys .msdos .old] [.sys .os2] -- OS/2 [.sys .share .sounds] -- AIFF format audio files [.sys .unix] -- guess :-) @@ -139,7 +137,7 @@ Notes: 1. Save files and bones files from earlier versions will not work with - 3.3.1. The scoreboard file (RECORD) from 3.3.0 will work; one from + 3.4.0. The scoreboard file (RECORD) from 3.3.x will work; one from version 3.2.x is slightly different format but should be compatible. 2. To specify user-preference options in your environment, define the @@ -155,7 +153,7 @@ Notes: tradeoff for enabling checkpoint is that using it makes level changes do more I/O and take longer. The "menustyle" option controls some aspects of the user interface, and can be set to "menustyle:traditional" - to make 3.3.1 or 3.2.x behave more like 3.1.3. + to make nethack behave more like older versions. If logical name or DCL symbol NETHACKOPTIONS is not defined, NetHack will try HACKOPTIONS instead. Regardless of whether or not either diff --git a/sys/vms/Makefile.dat b/sys/vms/Makefile.dat index 363fb7c..d2ee9a3 100644 --- a/sys/vms/Makefile.dat +++ b/sys/vms/Makefile.dat @@ -1,5 +1,5 @@ # NetHack Makefile (VMS) - data files: special levels and other data. -# SCCS Id: @(#)Makefile.dat 3.3 1999/03/19 +# SCCS Id: @(#)Makefile.dat 3.4 2002/03/02 # Copy this file to [.dat]Makefile.; no editing needed. @@ -20,6 +20,7 @@ LEVCOMP = $(UTL)lev_comp.exe; DGNCOMP = $(UTL)dgn_comp.exe; DLB = $(UTL)dlb.exe; TILE2X11 = $(UTL)tile2x11.exe; +UTILMARKER = $(UTL)util.timestamp; # note: filespecs have enough punctuation to satisfy DELETE MARKERS = spec_levs.timestamp;,quest_levs.timestamp; @@ -56,27 +57,27 @@ options : options.; x11tiles : $(X11TILES) @ $(NOOP) -$(MAKEDEFS) : +$(MAKEDEFS) : $(UTILMARKER) $(CD) $(UTL) $(MAKE)$(MAKEFLAGS) $(MAKEDEFS) @ $(CD) $(DAT) -$(DGNCOMP) : +$(DGNCOMP) : $(UTILMARKER) $(CD) $(UTL) $(MAKE)$(MAKEFLAGS) $(DGNCOMP) @ $(CD) $(DAT) -$(LEVCOMP) : +$(LEVCOMP) : $(UTILMARKER) $(CD) $(UTL) $(MAKE)$(MAKEFLAGS) $(LEVCOMP) @ $(CD) $(DAT) -$(DLB) : +$(DLB) : $(UTILMARKER) $(CD) $(UTL) $(MAKE)$(MAKEFLAGS) $(DLB) @ $(CD) $(DAT) -$(TILE2X11) : +$(TILE2X11) : $(UTILMARKER) $(CD) $(UTL) $(MAKE)$(MAKEFLAGS) $(TILE2X11) @ $(CD) $(DAT) diff --git a/sys/vms/Makefile.doc b/sys/vms/Makefile.doc index a45aaee..1de8642 100644 --- a/sys/vms/Makefile.doc +++ b/sys/vms/Makefile.doc @@ -1,5 +1,5 @@ # NetHack Makefile (VMS) - for the [Unix] documentation. -# SCCS Id: @(#)Makefile.doc 3.3 1993/01/06 +# SCCS Id: @(#)Makefile.doc 3.4 1993/01/06 # Copy this file to [.doc]Makefile. and edit it if needed. diff --git a/sys/vms/Makefile.src b/sys/vms/Makefile.src index 953836f..6b305cc 100644 --- a/sys/vms/Makefile.src +++ b/sys/vms/Makefile.src @@ -1,7 +1,8 @@ # NetHack Makefile (VMS) - for building nethack itself. -# SCCS Id: @(#)Makefile.src 3.3 2000/08/05 +# SCCS Id: @(#)Makefile.src 3.4 2002/03/02 # Copy this file to [.src]Makefile. and then edit it as needed. +# The default configuration is for building with DEC C (aka Compaq C). # If you changed CC or CFLAGS, make similar changes in [.util]Makefile. # # Note: modifying this Makefile will cause crtl.opt to be rebuilt, @@ -32,16 +33,15 @@ MAKEFILE= $(SRC)Makefile. # set option flags for C compiler and linker # -#CFLAGS = /Debug/noOptimize/Include=$(INC) -CFLAGS = /Include=$(INC)/noList # VAXC or GNUC -#CFLAGS = /Prefix=All/Incl=$(INC)/noList # DECC in native mode +CFLAGS = /Prefix=All/Incl=$(INC)/noList # DECC in native mode +#CFLAGS = /Include=$(INC)/noList # VAXC or GNUC #LFLAGS = /Debug/Map/Cross_Ref # for development #LFLAGS = /noTraceback/noMap # for installing w/ privs LFLAGS = /noMap LINK = link -LIBS = sys$share:vaxcrtl.exe/Shareable -#LIBS = # blank for DECC +LIBS = # blank for DECC +#LIBS = sys$share:vaxcrtl.exe/Shareable # VAX C or GNU C MORELIBS = # GCC needs an extra library #MORELIBS = gnu_cc:[000000]gcclib.olb/Library @@ -91,7 +91,7 @@ RANDOBJ = random.obj # and config.h # note: no trailing whitespace (or comment) after version or patchlevel numbers -VERSION =3.3 +VERSION =3.4 PATCHLVL =0 MAKEDEFS = $(UTL)makedefs.exe; @@ -107,7 +107,7 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \ do_name.c do_wear.c dog.c dogmove.c dokick.c dothrow.c drawing.c \ dungeon.c eat.c end.c engrave.c exper.c explode.c extralev.c \ files.c fountain.c hack.c hacklib.c invent.c light.c lock.c mail.c \ - makemon.c mcastu.c mhitm.c mhitu.c minion.c mklev.c mkmap.c \ + makemon.c mapglyph.c mcastu.c mhitm.c mhitu.c minion.c mklev.c mkmap.c \ mkmaze.c mkobj.c mkroom.c mon.c mondata.c monmove.c monst.c \ mplayer.c mthrowu.c muse.c music.c o_init.c objects.c objnam.c \ options.c pager.c pickup.c pline.c polyself.c potion.c pray.c \ @@ -117,8 +117,11 @@ HACKCSRC = allmain.c alloc.c apply.c artifact.c attrib.c ball.c bones.c \ uhitm.c vault.c version.c vision.c weapon.c were.c wield.c \ windows.c wizard.c worm.c worn.c write.c zap.c +# generated source files (tile.c is handled separately via WINxxxSRC) +GENCSRC = monstr.c vis_tab.c #tile.c + # .c files for this version (for date.h) -VERSOURCES = $(HACKCSRC) $(SYSSRC) $(WINSRC) $(RANDSRC) monstr.c vis_tab.c +VERSOURCES = $(HACKCSRC) $(SYSSRC) $(WINSRC) $(RANDSRC) $(GENCSRC) # all .h files except date.h, onames.h, pm.h, and vis_tab.h which would # cause dependency loops if run through "make depend" @@ -147,10 +150,10 @@ HOBJ1 = allmain.obj,alloc.obj,apply.obj,artifact.obj,attrib.obj, \ HOBJ2 = dog.obj,dogmove.obj,dokick.obj,dothrow.obj,drawing.obj, \ dungeon.obj,eat.obj,end.obj,engrave.obj,exper.obj,explode.obj, \ extralev.obj,files.obj,fountain.obj,hack.obj,hacklib.obj,invent.obj -HOBJ3 = light.obj,lock.obj,mail.obj,makemon.obj,mcastu.obj,mhitm.obj, \ - mhitu.obj,minion.obj,mklev.obj,mkmap.obj,mkmaze.obj,mkobj.obj, \ - mkroom.obj,mon.obj,mondata.obj,monmove.obj,monstr.obj,mplayer.obj -HOBJ4 = mthrowu.obj,muse.obj,music.obj,o_init.obj,objnam.obj, \ +HOBJ3 = light.obj,lock.obj,mail.obj,makemon.obj,mapglyph.obj,mcastu.obj, \ + mhitm.obj,mhitu.obj,minion.obj,mklev.obj,mkmap.obj,mkmaze.obj, \ + mkobj.obj,mkroom.obj,mon.obj,mondata.obj,monmove.obj,monstr.obj +HOBJ4 = mplayer.obj,mthrowu.obj,muse.obj,music.obj,o_init.obj,objnam.obj, \ options.obj,pager.obj,pickup.obj,pline.obj,polyself.obj, \ potion.obj,pray.obj,priest.obj,quest.obj,questpgr.obj,read.obj HOBJ5 = rect.obj,region.obj,restore.obj,rip.obj,rnd.obj,role.obj, \ @@ -312,7 +315,7 @@ $(HACK_H) : $(INC)hack.h $(CONFIG_H) $(INC)align.h \ # VMS-specific code vmsmain.obj : $(VMS)vmsmain.c $(HACK_H) $(INC)dlb.h vmstty.obj : $(VMS)vmstty.c $(HACK_H) $(INC)wintty.h $(INC)tcap.h -vmsunix.obj : $(VMS)vmsunix.c $(HACK_H) $(INC)date.h +vmsunix.obj : $(VMS)vmsunix.c $(HACK_H) vmsmisc.obj : $(VMS)vmsmisc.c $(VMS)oldcrtl.c vmsfiles.obj : $(VMS)vmsfiles.c $(CONFIG_H) vmsmail.obj : $(VMS)vmsmail.c $(CONFIG_H) $(INC)mail.h \ @@ -343,6 +346,8 @@ winstat.obj : $(X11)winstat.c $(HACK_H) $(INC)winX.h wintext.obj : $(X11)wintext.c $(HACK_H) $(INC)winX.h $(INC)xwindow.h winval.obj : $(X11)winval.c $(CONFIG_H) $(INC)winX.h tile.obj : $(SRC)tile.c $(HACK_H) +monstr.obj : monstr.c $(CONFIG_H) +vis_tab.obj : vis_tab.c $(CONFIG_H) $(INC)vis_tab.h # general code allmain.obj : allmain.c $(HACK_H) alloc.obj : alloc.c $(CONFIG_H) @@ -383,6 +388,7 @@ light.obj : light.c $(HACK_H) $(INC)lev.h lock.obj : lock.c $(HACK_H) mail.obj : mail.c $(HACK_H) $(INC)mail.h makemon.obj : makemon.c $(HACK_H) $(INC)epri.h $(INC)emin.h $(INC)edog.h +mapglyph.obj : mapglyph.c $(HACK_H) mcastu.obj : mcastu.c $(HACK_H) mhitm.obj : mhitm.c $(HACK_H) $(INC)artifact.h $(INC)edog.h mhitu.obj : mhitu.c $(HACK_H) $(INC)artifact.h $(INC)edog.h @@ -411,7 +417,7 @@ options.obj : options.c $(CONFIG_H) $(INC)objclass.h $(INC)flag.h \ $(HACK_H) $(INC)tcap.h pager.obj : pager.c $(HACK_H) $(INC)dlb.h pickup.obj : pickup.c $(HACK_H) -pline.obj : pline.c $(HACK_H) $(INC)epri.h +pline.obj : pline.c $(HACK_H) $(INC)epri.h $(INC)edog.h polyself.obj : polyself.c $(HACK_H) potion.obj : potion.c $(HACK_H) pray.obj : pray.c $(HACK_H) $(INC)epri.h @@ -421,7 +427,7 @@ quest.obj : quest.c $(HACK_H) $(INC)qtext.h questpgr.obj : questpgr.c $(HACK_H) $(INC)dlb.h $(INC)qtext.h read.obj : read.c $(HACK_H) rect.obj : rect.c $(HACK_H) -region.obj : region.c $(HACK_H) +region.obj : region.c $(HACK_H) $(INC)lev.h restore.obj : restore.c $(HACK_H) $(INC)lev.h $(INC)tcap.h rip.obj : rip.c $(HACK_H) rnd.obj : rnd.c $(HACK_H) diff --git a/sys/vms/Makefile.top b/sys/vms/Makefile.top index a4523fe..3ed44e7 100644 --- a/sys/vms/Makefile.top +++ b/sys/vms/Makefile.top @@ -1,5 +1,5 @@ # NetHack Makefile (VMS) - top level for making & installing everything. -# SCCS Id: @(#)Makefile.top 3.3 96/03/02 +# SCCS Id: @(#)Makefile.top 3.4 1996/03/02 # Copy this file to Makefile.; edit the appropriate values for # GAMEDIR ("playground" location) and GAMEOWNER (UIC or identifier diff --git a/sys/vms/Makefile.utl b/sys/vms/Makefile.utl index f6db287..bc4e2e6 100644 --- a/sys/vms/Makefile.utl +++ b/sys/vms/Makefile.utl @@ -1,13 +1,14 @@ # NetHack Makefile (VMS) - for utility programs. -# SCCS Id: @(#)Makefile.utl 3.3 2000/08/05 +# SCCS Id: @(#)Makefile.utl 3.4 2002/03/02 # Copy this file to [.util]Makefile. and then edit it as needed. +# The default configuration is for building with DEC C (aka Compaq C). # Settings for CC and CFLAGS ought to match the ones used in [.src]Makefile. MAKE = $(MMS) CD = set default ECHO = write sys$output -MOVE = rename/New # within save device only +MOVE = rename/New # within same device only MUNG = search/Exact/Match=NOR # to strip bogus #module directives NOOP = continue RM = delete/noConfirm @@ -28,13 +29,15 @@ LEVCOMP = $(UTL)lev_comp.exe; DGNCOMP = $(UTL)dgn_comp.exe; DLB = $(UTL)dlb.exe; RECOVER = $(UTL)recover.exe; +# used by $(DAT)Makefile for synchronization +MARKER = $(UTL)util.timestamp; # if you are using gcc as your compiler, # uncomment the CC definition below if it's not in your environment # CC = gcc -CFLAGS = /Include=$(INC)/noList # VAXC or GNUC -#CFLAGS = /Prefix=All/Incl=$(INC)/noList # DECC in native mode +CFLAGS = /Prefix=All/Incl=$(INC)/noList # DECC in native mode +#CFLAGS = /Include=$(INC)/noList # VAXC or GNUC LFLAGS = /noMap LIBS = $(SRC)crtl.opt/Options # run-time library(s) needed LINK = link @@ -153,6 +156,7 @@ $(LIBOPT) : $(SRC)Makefile.; # linker options file # $(MAKEDEFS) : $(MAKEOBJS) $(VMSMAKEOBJS) $(LIBOPT) $(LINK) $(LFLAGS) $(MAKEOBJS),$(VMSMAKEOBJS),$(LIBS) + @ $(TOUCH) $(MARKER) makedefs.obj : makedefs.c \ $(CONFIG_H) $(INC)permonst.h $(INC)objclass.h \ @@ -365,3 +369,4 @@ spotless : clean - if f$search("*.exe").nes."" then \ $(RM) $(MAKEDEFS),$(LEVCOMP),$(DGNCOMP),$(RECOVER),$(DLB) - if f$search("*.exe").nes."" then $(RM) $(TILEUTILS) + - if f$search("$(MARKER)").nes."" then $(RM) $(MARKER) diff --git a/sys/vms/lev_lex.h b/sys/vms/lev_lex.h index 0464fec..f001e57 100644 --- a/sys/vms/lev_lex.h +++ b/sys/vms/lev_lex.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)lev_lex.h 3.3 1999/08/08 */ +/* SCCS Id: @(#)lev_lex.h 3.4 1999/08/08 */ /* "vms/lev_lex.h" copied into "util/stdio.h" for use in *_lex.c only! * This is an awful kludge to allow util/*_lex.c made by SunOS's `lex' * to be compiled as is. (It isn't needed with `flex' or VMS POSIX diff --git a/sys/vms/oldcrtl.c b/sys/vms/oldcrtl.c index 586f697..ee87e5a 100644 --- a/sys/vms/oldcrtl.c +++ b/sys/vms/oldcrtl.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)oldcrtl.c 3.3 1995/06/01 */ +/* SCCS Id: @(#)oldcrtl.c 3.4 1995/06/01 */ /* Pat Rankin May'90 */ /* VMS NetHack support, not needed for vms 4.6,4.7,5.x,or later */ diff --git a/sys/vms/vmsbuild.com b/sys/vms/vmsbuild.com index 4e0358f..1d2beaa 100644 --- a/sys/vms/vmsbuild.com +++ b/sys/vms/vmsbuild.com @@ -1,5 +1,5 @@ -$ ! vms/vmsbuild.com -- compile and link NetHack 3.3.* [pr] -$ version_number = "3.3.0" +$ ! vms/vmsbuild.com -- compile and link NetHack 3.4.* [pr] +$ version_number = "3.4.0" $ ! $ ! usage: $ ! $ set default [.src] !or [-.-.src] if starting from [.sys.vms] @@ -257,9 +257,10 @@ $ c_list = "allmain,apply,artifact,attrib,ball,bones,botl,cmd,dbridge,detect" - + ",dig,display,do,do_name,do_wear,dog,dogmove,dokick,dothrow,drawing" - + ",dungeon,eat,end,engrave,exper,explode,extralev,files,fountain" $ gosub compile_list -$ c_list = "hack,hacklib,invent,light,lock,mail,makemon,mcastu,mhitm,mhitu" - - + ",minion,mklev,mkmap,mkmaze,mkobj,mkroom,mon,mondata,monmove,monstr" - - + ",mplayer,mthrowu,muse,music,o_init,objnam,options,pager,pickup" +$ c_list = "hack,hacklib,invent,light,lock,mail,makemon,mapglyph,mcastu" - + + ",mhitm,mhitu,minion,mklev,mkmap,mkmaze,mkobj,mkroom,mon,mondata" - + + ",monmove,monstr,mplayer,mthrowu,muse,music,o_init,objnam,options" - + + ",pager,pickup" $ gosub compile_list $ c_list = "pline,polyself,potion,pray,priest,quest,questpgr,read" - + ",rect,region,restore,rip,rnd,role,rumors,save,shk,shknam,sit" - diff --git a/sys/vms/vmsfiles.c b/sys/vms/vmsfiles.c index 75c31a3..657c060 100644 --- a/sys/vms/vmsfiles.c +++ b/sys/vms/vmsfiles.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)vmsfiles.c 3.3 1999/08/29 */ +/* SCCS Id: @(#)vmsfiles.c 3.4 1999/08/29 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/vms/vmsmail.c b/sys/vms/vmsmail.c index 9c9ef60..29e0192 100644 --- a/sys/vms/vmsmail.c +++ b/sys/vms/vmsmail.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)vmsmail.c 3.3 1995/06/01 */ +/* SCCS Id: @(#)vmsmail.c 3.4 1995/06/01 */ /* Copyright (c) Robert Patrick Rankin, 1991. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/vms/vmsmain.c b/sys/vms/vmsmain.c index 73b2d1d..f20e665 100644 --- a/sys/vms/vmsmain.c +++ b/sys/vms/vmsmain.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)vmsmain.c 3.3 1997/01/22 */ +/* SCCS Id: @(#)vmsmain.c 3.4 2001/07/27 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ /* main.c - VMS NetHack */ @@ -45,7 +45,6 @@ char *argv[]; atexit(byebye); hname = argv[0]; - gethdate(hname); /* find executable's creation date */ hname = vms_basename(hname); /* name used in 'usage' type messages */ hackpid = getpid(); (void) umask(0); @@ -304,6 +303,9 @@ char *argv[]; flags.initrace = i; } break; + case '@': + flags.randomall = 1; + break; default: if ((i = str2role(&argv[0][1])) >= 0) { flags.initrole = i; diff --git a/sys/vms/vmsmisc.c b/sys/vms/vmsmisc.c index 395091d..573d9c4 100644 --- a/sys/vms/vmsmisc.c +++ b/sys/vms/vmsmisc.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)vmsmisc.c 3.3 1996/03/02 */ +/* SCCS Id: @(#)vmsmisc.c 3.4 1996/03/02 */ /* NetHack may be freely redistributed. See license for details. */ #include diff --git a/sys/vms/vmstty.c b/sys/vms/vmstty.c index 3288e63..e9add76 100644 --- a/sys/vms/vmstty.c +++ b/sys/vms/vmstty.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)vmstty.c 3.3 1995/07/09 */ +/* SCCS Id: @(#)vmstty.c 3.4 1995/07/09 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ /* tty.c - (VMS) version */ diff --git a/sys/vms/vmsunix.c b/sys/vms/vmsunix.c index e366bce..fdaa53c 100644 --- a/sys/vms/vmsunix.c +++ b/sys/vms/vmsunix.c @@ -1,13 +1,10 @@ -/* SCCS Id: @(#)vmsunix.c 3.3 1996/02/17 */ +/* SCCS Id: @(#)vmsunix.c 3.4 2001/07/27 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ /* This file implements things from unixunix.c, plus related stuff */ #include "hack.h" -#if 0 -#include "date.h" /* generated by 'makedefs' */ -#endif #include #include @@ -30,10 +27,6 @@ extern unsigned long lib$getdvi(), lib$getjpi(), lib$spawn(), lib$attach(); extern unsigned long smg$init_term_table_by_type(), smg$del_term_table(); #define vms_ok(sts) ((sts) & 1) /* odd => success */ -#if 0 -static long exe_time = BUILD_TIME; -#endif - static int FDECL(veryold, (int)); static char *NDECL(verify_term); #if defined(SHELL) || defined(SUSPEND) @@ -41,48 +34,6 @@ static void FDECL(hack_escape, (BOOLEAN_P,const char *)); static void FDECL(hack_resume, (BOOLEAN_P)); #endif -/*ARGSUSED*/ -void -gethdate(name) /* get the creation date & time of file 'name' */ -const char *name; /* assumed to be argv[0], full path to nethack.exe */ -{ -#if 0 - struct stat hbuf; - /* - [f]stat() won't work across a DECnet link. Would somebody be - masochistic enough to try ``$ RUN node::NETHACK''? One hopes - not, but don't inadvertently forbid it. If stat() fails, use - the compile time provided by 'makedefs' instead of just quitting. - The playground must be local, otherwise all level files will - fail their status check, but the exe image could be remote. - - Note that we care about the executable's creation time, not - its modification time, since the latter is touched by changing - file protection or renaming, two naive ways someone might use - to disable the program during prime time. - */ - if (stat(name, &hbuf) == 0) exe_time = hbuf.st_ctime; -#endif -} - -#if 0 -boolean -uptodate(fd) -int fd; -{ - struct stat buf; - - if (fstat(fd, &buf) != 0) - pline("Cannot get status of saved level? "); - else if (buf.st_mtime < exe_time) - pline("Saved level is out of date. "); - else - return TRUE; /* passed the test */ - wait_synch(); - return FALSE; /* failed the test */ -} -#endif - static int veryold(fd) int fd; diff --git a/sys/winnt/Install.nt b/sys/winnt/Install.nt index b85e7ab..33516cf 100644 --- a/sys/winnt/Install.nt +++ b/sys/winnt/Install.nt @@ -1,74 +1,148 @@ - Copyright (c) NetHack Development Team 1990-2000 + Copyright (c) NetHack Development Team 1990-2002 NetHack may be freely redistributed. See license for details. ============================================================== Instructions for compiling and installing - NetHack 3.3 on a Windows NT, 2000, or Windows 9x system + NetHack 3.4 on a Windows NT, 2000, or XP system ============================================================== - (or, How to make NetHack 3.3.1 for the WIN32 Console subsystem) - Last revision: August 2, 2000 + Last revision: March 2, 2002 -Credit for the PC versions of NetHack goes to the PC Development team -of Paul Winner, Kevin Smolkowski, Michael Allison, Yitzhak Sapir, Bill -Dyer, Timo Hakulinen, Yamamoto Keizo, Mike Threepoint, Mike Stephenson, -Stephen White, Ken Washikita and Janet Walz. +{TODO: there are some TODO's in the text below to be resolved before release} Credit for the porting of NetHack to the Win32 Console Subsystem goes to the NT Porting Team started by Michael Allison. +Credit for the Win32 Graphical version of NetHack (aka +"NetHack for Windows" or Nethackw) goes to Alex Kompel who initially +developed and contributed the port. + +The PC Windows porting team consisting of Michael Allison, Dave Cohrs, +Alex Kompel, Yitzhak Sapir, and Janet Walz integrated the tty version +and the graphical version into the NetHack 3.4.0 sources. Just as +the release of NetHack 3.4.0 was being prepared, Dion Nicolaas submitted +an entire win32 port of his own to the NetHack Development Team. Dion was +subsequently invited to join the PC Windows porting team where he could +continue to contribute to the win32 port, and that invitation was accepted. + + +You can build either the TTY version of NetHack or the Windows Graphical +version. In either case you can use one of the following build +environments: + + o A copy of Microsoft Visual C V6.0 SP3 or later. Things may work with + an earlier version of the compiler, but the current code has not been + tested with an earlier version. + + OR + + o A copy of Borland C 5.5.1 command line tools. Borland has made a + version of its command line tools available for download after + registration at: + http://www.borland.com/bcppbuilder/freecompiler/. + +Additionally, you can build a TTY version of NetHack with the following +build environment: + + o A copy of MinGW 1.0. MinGW is a collection of header files and import + libraries with which native Windows32 programs can be made; MinGW 1.0 + ships with the GNU Compiler Collection. + You can download MinGW at + http://www.mingw.org/ + + +FIRST STEP: + +The first step in building either version of NetHack is to execute +sys/winnt/nhsetup.bat. + +From the command prompt: + cd sys\winnt + nhsetup + +From a Windows explorer window: + double-click on nhsetup.bat + +A "binary" directory will be created off the top of the NetHack source +tree to house the completed build. + +A build subdirectory will also be created off the top of the NetHack +source tree, and many files appropriate for a graphical build will be +moved there. + +If you wish to build the TTY version, proceed now to "BUILDING TTY VERSION." +If you wish to build the graphical version, proceed now to "BUILDING GRAPHICAL VERSION." + + +------------------------ +| BUILDING TTY VERSION | +------------------------ + This version of NetHack for Win32 is a tty port utilizing the WIN32 Console I/O subsystem. I. Dispelling the Myths: - Compiling NetHack is not as easy as it sounds, nor as hard as it looks, - however it will behoove you to read this entire file through before - beginning the task. + Compiling NetHack for WIN32 TTY is not as easy as it sounds, nor as hard + as it looks, however it will behoove you to read this entire section + through before beginning the task. - We have provided a Makefile for building NetHack using the - following compiler: + We have provided a Makefile for each of the following compilers: - Microsoft Visual C++ V6.0 SP3 or greater + o Microsoft Visual C++ V6.0 SP3 or greater + o Borland C 5.5.1 + o MinGW 1.0 with GCC 2.95.3-6 - The Makefile was created for use with MS NMAKE which is provided with - the Microsoft compiler. + The Microsoft Visual C Makefile was created for use with MS NMAKE + which is provided with the Microsoft compiler. The supplied Makefile + may work with earlier versions of the Microsoft 32-bit compiler, but + that has not been tested. - The supplied Makefile may work with earlier versions of the Microsoft - 32-bit compiler, but that has not been tested. + The Borland C Makefile was created for use with Borland MAKE + which is provided with the Borland compiler. + + The GCC Makefile was created for use with GNU Make version 3.79.1, + which comes with the MinGW package. You may find it useful to obtain copies of lex (flex) and yacc (bison, or byacc). While not strictly necessary to compile nethack, they are required should you desire to make any changes to the level and dungeon compilers. - To use the distributed NetHack icon, a version of uudecode is required. -II. To compile your copy of NetHack on a 32 bit Windows machine (NT or 95): +II. To compile your copy of NetHack on a 32 bit Windows machine (NT or 2000): + (Note: build has not been tested on Windows XP. That isn't to say that + it doesn't work, it just hasn't been tried by us.) Setting Up 1. It almost goes without saying that you should make sure that your tools are set up and running correctly. That includes ensuring that all the - necessary environment variables for the Microsoft compiler environment - are set correctly. ( For example, by executing vcvars32.bat, which - is probably in the bin directory of your compilers directory tree. ) + necessary environment variables for the compiler environment + are set correctly. (Examples: For the Microsoft compiler by + executing vcvars32.bat, which is probably in the bin directory of + your compilers directory tree. For the Borland Makefile, you can + simply invoke the Make utility from the Makefile's directory (For + the standard Borland compiler installation you can just + use the explicit path "c:\borland\bcc55\bin\make /f Makefile.bcc". + For the GCC Makefile, add \bin to your path, where is + your MinGW root directory.) 2. Make sure all the NetHack files are in the appropriate directory structure. You should have a main directory with subdirectories - dat, doc, include, src, sys\share, sys\winnt, util and win\tty. + dat, doc, include, src, sys\share, sys\winnt, util, win\tty, and + binary (The "binary" directory was created by nhsetup.bat earlier + if you followed the steps appropriately). + Other subdirectories may also be included in your distribution, but they are not necessary for building the TTY version for the Win32 - console subsystem. You can delete them to save space. Your distribution - may contain a directory win\win32. This window port variant was a - recent addition and was not ready for the 3.3.0 or 3.3.1 releases. - You may ignore it or contribute to it. + console subsystem. You can delete them to save space. Required Directories for a Win32 Console NetHack: top | - ------------------------------------------------- - | | | | | | | - util dat doc include src sys win + ----------------------------------------------------/ /----- + | | | | | | | | + util dat doc include src sys win binary | | ------ ----- | | | @@ -86,113 +160,338 @@ Setting Up with them, so you may need to convert them. The compiler should not have any problems with them however. -3. Go to the sys\winnt directory and run the nhsetup.bat batch file. - The necessary Makefile movements will be accomplished for you. It - will also verify that your directories are set up properly. It - will also attempt to uudecode the NetHack icon contained in the - file sys/winnt/nhico.uu. You must uudecode this file manually - if the batch file fails to do so. - -4. Now go to the include subdirectory to check a couple of the header +3. Now go to the include subdirectory to check a couple of the header files there. Things *should* work as they are, but since you have probably set up your system in some sort of custom configuration it doesn't hurt to check out the following: First check config.h according to the comments to match your system and - desired set of features. Mostly you need to check the WIZARD option, - make sure the HACKDIR is set properly. - - Also check COMPRESS. - - You may include all or as few of the special game features as you wish. + desired set of features. Mostly you need to check the WIZARD option. -5. Go to the src directory and edit the top of your Makefile. - Change the setting of (GAMEDIR) to reflect the directory where - you want NetHack to be installed. + You may include all or as few of the special game features as you wish + (they are located last in the file). - ie. GAMEDIR = \games\nethackntty +4. Edit your Makefile. - The directory you specify *MUST* exist for all remaining steps to be - successful. Be sure the directory you want the game installed - actually exists. If it doesn't, create it now. + For building the TTY version, ensure that GRAPHICAL is set to "N", + or commented out. (If you aren't building the TTY version, you are + currently reading the wrong section, and following the wrong set of + steps. In that case, you may wish to start reading from the top + again.) - If you elected not to use the high-quality BSD random number routines by - commenting out RANDOM in ntconf.h, comment out (or set equal - to nothing) the RANDOM macro in your Makefile. + Optional step: + If you elected not to use the high-quality BSD random number routines by + commenting out RANDOM in ntconf.h, comment out (or set equal to nothing) + the RANDOM macro in your Makefile. If you are recompiling after patching your sources, or if you got your files from somewhere other than the official distribution, "touch makedefs.c" to ensure that certain files (onames.h and pm.h) are remade, - lest potentially troublesome timestamps fool "nmake". + lest potentially troublesome timestamps fool your make (or nmake) utility. Compiling -6. Now that everything is set up, and with your current directory set - to src, run "nmake install". +5. Now that everything is set up, change your current directory to src. - If you get any errors along the way then something has not been set + For Microsoft compiler: + nmake install + + For Borland compiler: + make /f Makefile.bcc install + + For GCC: + make -f Makefile.gcc install + + If you get any errors along the way then something has not been set up correctly. The time it takes to compile depends on your particular machine of course, but you should be able to go for lunch and return to find everything finished. The less memory, and slower your machine, - the longer the lunch you may take. + the longer the lunch you may take. :-) In any case, it is likely that the command prompt window where you are - doing the compiling will be occupied for a quite a while. If all - goes well, you will get an NetHack executable. + doing the compiling will be occupied for a while. If all goes well, + you will get an NetHack executable. Running NetHack -7. Make sure all of the support files -- Guidebook.txt, license, logfile, - Defaults.nh, NetHack.exe, nhdat, record, and recover.exe - -- were copied to the game directory. If not, move them there yourself. - Defaults.nh is actually distributed in the sources as sys/winnt/winnt.cnf, - but the Makefile should take care of moving it and renaming it correctly. +6. Make sure all of the support files -- Guidebook.txt, license, + Defaults.nh, NetHack.exe, nhdat, and recover.exe -- were copied to the + game directory. If not, move them there yourself. Edit Defaults.nh to reflect your particular setup and personal preferences, by following the comments. As with all releases since - 3.2.1, HACKDIR defaults to the same directory as that where the NetHack.exe - executable resides. You only need to set HACKDIR in Defaults.nh if, - for some reason, you wish to override that. + 3.2.1, HACKDIR defaults to the same directory as that where the NetHack.exe + executable resides. You only need to set HACKDIR in defaults.nh if, + for some reason, you wish to override that (be careful). -8a. Running from the command prompt: +7. Executing the game + + a) Running from the command prompt: If you add the directory containing the NetHack executable to your PATH, you can just type "nethack" or "nethack -umike" to start it up. Alternatively, you can explicitly invoke it with - a command such as "c:\games\nethack\nethack" (specifying whatever + a command such as "c:\nethack\binary\nethack.exe" (specifying whatever drive and directory your NetHack executable resides in) each time. + b) Running from a Windows shortcut. -8b. Running from a Windows shortcut (win95 or NT4.x) + If you will be running it by launching it from a shortcut, just + use the following information when setting up the shortcut. - If you will be running it by launching it from program manager - or from a shortcut, just use the following information when - setting up the icon or shortcut. - - Description : NetHack 3.3.1 - Command Line : C:\GAMES\NETHACK\NETHACK.EXE + Description : NetHack 3.4.0 + Command Line : C:\NETHACK\BINARY\NETHACK.EXE (changing the directory to the appropriate one of course) -9. Play NetHack. If it works, you're done! +8. Play NetHack. If it works, you're done! Notes: -1) To install an update of NetHack after changing something, enter "nmake" - from the src directory. If you add, delete, or reorder monsters or - objects, or you change the format of saved level files, delete any save - and bones files. (Trying to use such files sometimes produces amusing - confusions on the game's part, but usually crashes.) +1) To install an update of NetHack after changing something, change + your current directory to src and issue the appropriate command + for your compiler: + + For Microsoft compiler: + nmake + + For Borland compiler: + make /f Makefile.bcc + + For GCC: + make -f Makefile.gcc + + If you add, delete, or reorder monsters or objects, or you change the + format of saved level files, delete any save and bones files. (Trying + to use such files sometimes produces amusing confusions on the game's + part, but usually crashes.) If you made changes to any of the level compiler software, you may have to delete dgn_flex.c, dgn_yacc.c, lev_flex.c, and lev_yacc.c from the util directory to ensure that they are remade. -2) The executable produced by this port is a 32-bit, flat-address space, - non-overlayed .exe file, which should run on any true Win32 environment. +2) The executable produced by the TTY build is a 32-bit, flat-address space, + non-overlayed .exe file, which should run on any true Win32 environment + with console I/O support. + + +------------------------------ +| BUILDING GRAPHICAL VERSION | +------------------------------ + + +This version of NetHack is a Win32 native port built on the Windows API. + +I. Dispelling the Myths: + + Compiling NetHack for Windows is straightforward, as long as you have + your compiler and tools correctly installed. + + It is also assumed that you already changed your directory to + sys\winnt and executed: + nhsetup + as described at the top of this document. If you didn't, you must + go back and do so before proceeding. + +II. To compile your copy of NetHack for Windows on a + Windows NT/2000/XP machine: -3) If you encounter a bug and wish to report it, please send e-mail to: +Setting Up + +1. It almost goes without saying that you should make sure that your tools + are set up and running correctly. (Examples: For the Microsoft Visual + Studio C compiler it should correctly fire up when you choose it in + your Start | Programs menus, and for Borland make sure that the compiler + is in your PATH, or that you know where the make.exe executable resides.) + +2. Make sure all the NetHack files are in the appropriate directory + structure. You should have a main directory with subdirectories + dat, doc, include, src, sys\share, sys\winnt, util, win\win32, + and at this point you should also have a build directory and a + binary directory (both created by nhsetup.bat executed from + sys\winnt earlier.) + + Other subdirectories may also be included in your distribution, but + they are not necessary for building the graphical version of NetHack + (you can delete them to save space if you wish.) + + Required Directories for a Win32 Graphical NetHack: + + top + | + -----------------------------------------/ /--------------- + | | | | | | | | | + util dat doc include src sys win build binary + | | + ------ ----- + | | | + share winnt win32 + + Those last two (build and binary) are created during the building + process. They are not disributed as part of the NetHack source + distribution. nhsetup.bat creates the build directory and moves + a few files into it, including the Visual C project files. + The "binary" directory will house everything you need to play the + game after building is complete. + + Check the file "Files" in your top level directory for an exact + listing of what file is in which directory. In order for the + build process to work, all the source files must be in the proper + locations. Remember that nhsetup.bat moves/copies many files around + to their intended locations for building NetHack. + + If you downloaded or ftp'd the sources from a UNIX system, the lines + will probably end in UNIX-style newlines, instead of the carriage + return and line feed pairs used by Windows. Visual Studio project + files and workspace files (dsp and dsw files) in particular need to + have their lines end in carriage-return-line-feed or they won't work + properly. + +3. Ready your tool. + Microsoft compiler users, perform step 3a. + Borland compiler users, perform step 3b. + + Note for Microsoft users: It's possible to build a graphical version + using the Makefile. For simplicity's sake, however, only the Visual + C IDE build will be explained. The IDE build has full game + functionality and is the officially released build.s + + a) Microsoft compiler: + Start the Visual C IDE. In the Visual C IDE Menus, choose: + File | Open Workspace + + b) Borland compiler: + Chdir to the NetHack src directory: + chdir ../../src + if your current directory was still sys/winnt, + or: + chdir src + if your current directory was the top of the NetHack tree. + +4. Set up for the build. + Microsoft compiler users, perform step 4a. + Borland compiler users, perform step 4b. + + a) Microsoft compiler only: + o In the Visual C "Open Workspace" dialog box, navigate to the top + of your NetHack source directory. + + In there, highlight "nethack.dsw" and click on Open. + Once the workspace has been opened, you should see the following + list in the Visual C selection window: + + dgncomp files + + dgnstuff files + + dlb_main files + + levcomp files + + levstuff files + + makedefs files + + nethackw files + + recover files + + tile2bmp files + + tilemap files + + uudecode files + + o On the Visual C menus, choose: + Project | Set Active Project | nethackw + + o On the Visual C menus again, choose either: + Build | Set Active Configuration | nethackw - Win32 Release + or + Build | Set Active Configuration | nethackw - Win32 Debug + + The first will create the Release build of NetHackW which does + not contain all the debugging information and is smaller, and + runs quicker. The second will create the Debug build of NetHackW + and will spend a lot of time writing debug information to the disk + as the game is played. Unless you are debugging or enhancing NetHack + for Windows, choose the Release build. + + o For Microsoft compiler build, you may now proceed to step 5. + + b) Borland Compiler only: + + o Edit the Makefile. Ensure the following are set correctly. + GRAPHICAL should be set to "Y" + + o Ensure that all your tools directories are set up properly. + By default, your tools are assumed to be in the same + directory as the MAKE program. + + +Building + +5. Start your build. + Microsoft compiler users, perform step 5a. + Borland compiler users, perform step 5b. + + a) Microsoft Compiler only: + o On the Visual C menus once again, choose: + Build | Build nethackw.exe + This starts the build. It is likely that the IDE message window + where you are doing the compiling will be occupied for a while. + If all goes well, you will get an NetHack executable called + nethackw.exe in the "binary" directory, along with all the support + files that it needs. + + o For Microsoft compiler build, you may now proceed to step 6. + + b) Borland Compiler only: + o With your current directory the NetHack src directory, + issue the following command: + make /f Makefile.bcc install + +6. If all has gone well to this point, you should now have a playable + game of "NetHack for Windows" in the "binary" directory. + + +Running NetHack + +7. Make sure all of the support files -- Guidebook.txt, license, + Defaults.nh, nethackw.exe, nhdat, and recover.exe + -- were copied to the binary directory. + (If not, find them in the tree and move them there yourself if they + exist. If they don't exist, something has gone wrong) + + Edit Defaults.nh to reflect your particular setup and personal + preferences, by following the comments. As with all releases since + 3.2.1, HACKDIR defaults to the same directory as that where the nethackw.exe + executable resides. You only need to set HACKDIR in Defaults.nh if, + for some reason, you wish to override that (be careful). + +8. Executing the game + a) Running from the command prompt: + + If you add the directory containing the NetHack executable + to your PATH, + You can just type "nethackw" to start it up. Alternatively, you + can explicitly invoke it with a command such as + "c:\nethack\binary\nethackw.exe" (specifying whatever drive + and directory your NetHack executable resides in) each time. + + b) Running from a Windows shortcut (win95 or NT4.x) + + If you will be running it by launching it from program manager + or from a shortcut, just use the following information when + setting up the icon or shortcut. + + Description : NetHack 3.4.0 + Command Line : C:\NETHACK\BINARY\NETHACKW.EXE + + (changing the directory in the Command Line to the appropriate one of course) + +9. Play NetHack for Windows. If it works, you're done! + + +PROBLEMS + + If you encounter a bug and wish to report it, please send e-mail to: nethack-bugs@nethack.org If you have any comments or suggestions, feel free to drop us a line c/o: DevTeam@nethack.org + + You may wish to vist the NetHack Development Team's website occasionally + to check for updates or known bugs. The website can be found at: + http://www.nethack.org/ + + Happy NetHacking! diff --git a/sys/winnt/Makefile.bcc b/sys/winnt/Makefile.bcc new file mode 100644 index 0000000..ab3e38c --- /dev/null +++ b/sys/winnt/Makefile.bcc @@ -0,0 +1,1311 @@ +# SCCS Id: @(#)Makefile.bcc 3.4 2002/03/03 +# Copyright (c) NetHack PC Development Team 1993-2002 +# +# NetHack 3.4.x Makefile for Borland C++ V5.5.1 and above and Borland's MAKE +# +# Win32 Compilers Tested: +# - Borland C++ 5.5.1 for Win32 +# +# If you don't have this compiler, you can get it at: +# http://www.borland.com/bcppbuilder/freecompiler/ +# +# This makefile is set up to assume the directories are extracted at the +# root, but this can be changed by modifying the bccroot and related +# variables. +# +# This is used for building a TTY or graphical version of NetHack using +# WIN32 Console I/O and API routines only. +# +# In addition to your C compiler, +# +# if you want to change you will need a +# files with suffix workalike for +# .y yacc (such as bison) +# .l lex (such as flex) +# +# +# If you have any questions read the sys/winnt/Install.nt file included +# with the distribution. +# +# -- +# Yitzhak Sapir +#============================================================================== +# Do not delete the following 3 lines. +# +TARGETOS=BOTH +APPVER=4.0 + +bccbin = $(MAKEDIR) +bccroot = $(MAKEDIR)\.. +bccinc = $(bccroot)\include +bcclib = $(bccroot)\lib + +!IFNDEF APPVER +APPVER = 4.0 +!ENDIF + +# Graphical interface +# Set to Y for a graphical version +# Set to anything else (or undefine) for a tty version + +#GRAPHICAL = Y + +# Debug +# Set to Y for Debug support (to produce full map files, listing files, and debug information) +# Set to anything else (or undefine) for a "release" version + +DEBUG = Y + +!IF "$(APPVER)" == "4.0" +MAKE_WINVER = 0x0400 +!ELSEIF "$(APPVER)" == "5.0" +MAKE_WINVER = 0x0500 +!ENDIF + +cc = $(bccbin)\bcc32 +rc = $(bccbin)\brc32 +link = $(bccbin)\ilink32 +implib = $(bccbin)\tlib + +cflags = -c -D_X86_=1 -DWINVER=$(MAKE_WINVER) -q -I$(bccinc) -w-pia -w-rch -w-par -w-aus +cdebug = -y -v -O2 +cvarsmt = -DWIN32 -D_WIN32 -D_MT +lflags = +!IF "$(DEBUG)" == "Y" +linkdebug = /v /m /s +cdebug = -v -y -Q +!ELSE +linkdebug = /C /Gn +cdebug = +!ENDIF +startobj = $(bcclib)\c0x32.obj +!IF "$(GRAPHICAL)" == "Y" +verlflags = /Gn /Gz /q -L$(bcclib) /c /Tpe /V$(APPVER) +startobjg = $(bcclib)\c0w32.obj +!ELSE +verlflags = /Gn /Gz /q -L$(bcclib) /c /ap /Tpe /V$(APPVER) +startobjg = $(startobj) +!ENDIF +libsmt = $(bcclib)\cw32mt.lib $(bcclib)\import32.lib + +# +# Set the gamedir according to your preference. +# It must be present prior to compilation. + +GAME = NetHack # Game Name +GAMEDIR = ..\binary # Game directory + +# +# Source directories. Makedefs hardcodes these, don't change them. +# + +INCL = ..\include # NetHack include files +DAT = ..\dat # NetHack data files +DOC = ..\doc # NetHack documentation files +UTIL = ..\util # Utility source +SRC = ..\src # Main source +SSYS = ..\sys\share # Shared system files +NTSYS = ..\sys\winnt # NT Win32 specific files +TTY = ..\win\tty # window port files (tty) +WIN32 = ..\win\win32 # window port files (Win32) +WSHR = ..\win\share # Tile support files + +# +# Object directory. +# + +OBJ = o + + +# +#========================================== +# Exe File Info. +#========================================== + +# Yacc/Lex ... if you got 'em. +# +# If you have yacc and lex programs (or work-alike such as bison +# and flex), comment out the upper two macros and uncomment +# the lower two. +# + +DO_YACC = YACC_MSG +DO_LEX = LEX_MSG +#DO_YACC = YACC_ACT +#DO_LEX = LEX_ACT + +# - Specify your yacc and lex programs (or work-alikes) here. + +YACC = bison -y +#YACC = byacc +#YACC = yacc + +#LEX = lex +LEX = flex + +# +# - Specify your flex skeleton file (if needed). +# + +FLEXSKEL = +#FLEXSKEL = -S../tools/flex.ske + +YTABC = y.tab.c +YTABH = y.tab.h +LEXYYC = lex.yy.c + +# +# Optional high-quality BSD random number generation routines +# (see pcconf.h). Set to nothing if not used. +# + +RANDOM = $(OBJ)\random.o +#RANDOM = + +# +# - For debugging ability, comment out the upper two +# macros and uncomment the lower two. +# + +# +# Leave the next two lines uncommented _ONLY_ if you do NOT want any +# debug capability in the object files, or in the NetHack executable. +# Comment them if you want debug capability. + +#cdebug = +#linkdebug = + +# +# Compiler and Linker flags +# + +PRECOMPHEAD = N # set to Y if you want to use precomp. headers + +#=============================================== +#======= End of Modification Section =========== +#=============================================== +################################################ +# # +# Nothing below here should have to be changed.# +# # +################################################ + +!IF "$(GRAPHICAL)" == "Y" +WINPORT = $(O)tile.o $(O)mhaskyn.o $(O)mhdlg.o \ + $(O)mhfont.o $(O)mhinput.o $(O)mhmain.o $(O)mhmap.o \ + $(O)mhmenu.o $(O)mhmsgwnd.o $(O)mhrip.o $(O)mhsplash.o \ + $(O)mhstatus.o $(O)mhtext.o $(O)mswproc.o $(O)winhack.o +WINPFLAG = -DTILES -DMSWIN_GRAPHICS +NHRES = $(O)winhack.res +WINPINC = -I$(WIN32) +WINPHDR = $(WIN32)\mhaskyn.h $(WIN32)\mhdlg.h $(WIN32)\mhfont.h \ + $(WIN32)\mhinput.h $(WIN32)\mhmain.h $(WIN32)\mhmap.h $(WIN32)\mhmenu.h \ + $(WIN32)\mhmsg.h $(WIN32)\mhmsgwnd.h $(WIN32)\mhrip.h $(WIN32)\mhstatus.h \ + $(WIN32)\mhtext.h $(WIN32)\resource.h $(WIN32)\winMS.h +!ELSE +WINPORT = $(O)nttty.o +WINPFLAG = -DWIN32CON +WINPHDR = +NHRES = $(O)console.res +WINPINC = +!ENDIF + +TILEUTIL16 = $(UTIL)\tile2bmp.exe +TILEBMP16 = $(SRC)\tiles.bmp + +TILEUTIL32 = $(UTIL)\til2bm32.exe +TILEBMP32 = $(SRC)\tiles32.bmp + +# These should be left commented in 3.4.x +# + +#SOUND = $(OBJ)\ntsound.o +#SOUND = + +# To store all the level files, +# help files, etc. in a single library file. +# USE_DLB = Y is left uncommented + +USE_DLB = Y + +! IF ("$(USE_DLB)"=="Y") +DLBFLG = -DDLB +! ELSE +DLBFLG = +! ENDIF + +# You can actually build a set of tiles +# with this makefile even though they +# are not used. Use 'nmake o\nhtiles.bmp' +# + +#========================================== +# Setting up the compiler and linker +# macros. All builds include the base ones. +#========================================== + +CFLAGSBASE = -c $(cflags) $(cvarsmt) -I$(INCL) $(WINPINC) -q $(cdebug) -v +LFLAGSBASE = $(linkdebug) $(verlflags) -L$(bcclib) -v + +#========================================== +# Util builds +#========================================== + +CFLAGSU = $(CFLAGSBASE) $(WINPFLAG) +LFLAGSU = $(LFLAGSBASE) + +#========================================== +# - Game build +#========================================== + +LFLAGSBASE = $(linkdebug) $(conflags) +CFLAGS = $(CFLAGSBASE) $(WINPFLAG) $(DLBFLG) +NHLFLAGS1 = /Gn /v /m /s /Gz /q /c +lflags = $(LFLAGSBASE) $(NHLFLAGS1) + +GAMEFILE = $(FDIR)\$(GAME).exe # whole thing + +! IF ("$(USE_DLB)"=="Y") +DLB = nhdat +! ELSE +DLB = +! ENDIF + +#========================================== +#================ RULES ================== +#========================================== + +.SUFFIXES: .exe .o .til .uu .c .y .l + +#========================================== +# Rules for files in src +#========================================== + +.c{$(OBJ)}.o: + @$(cc) $(CFLAGS) -o$@ $< + +{$(SRC)}.c{$(OBJ)}.o: + @$(cc) $(CFLAGS) -o$@ $< + +#========================================== +# Rules for files in sys\share +#========================================== + +{$(SSYS)}.c{$(OBJ)}.o: + @$(cc) $(CFLAGS) -o$@ $< + +#========================================== +# Rules for files in sys\winnt +#========================================== + +{$(NTSYS)}.c{$(OBJ)}.o: + @$(cc) $(CFLAGS) -o$@ $< + +{$(NTSYS)}.h{$(INCL)}.h: + @copy $< $@ + +#========================================== +# Rules for files in util +#========================================== + +{$(UTIL)}.c{$(OBJ)}.o: + @$(cc) $(CFLAGSU) -o$@ $< + +#========================================== +# Rules for files in win\share +#========================================== + +{$(WSHR)}.c{$(OBJ)}.o: + @$(cc) $(CFLAGS) -o$@ $< + +{$(WSHR)}.h{$(INCL)}.h: + @copy $< $@ + +#{$(WSHR)}.txt{$(DAT)}.txt: +# @copy $< $@ + +#========================================== +# Rules for files in win\tty +#========================================== + +{$(TTY)}.c{$(OBJ)}.o: + @$(cc) $(CFLAGS) -o$@ $< + +#========================================== +# Rules for files in win\win32 +#========================================== + +{$(WIN32)}.c{$(OBJ)}.o: + @$(cc) $(CFLAGS) -o$@ $< + +#========================================== +#================ MACROS ================== +#========================================== +# This section creates shorthand macros for many objects +# referenced later on in the Makefile. +# + +DEFFILE = $(NTSYS)\$(GAME).def + +# +# Shorten up the location for some files +# + +O = $(OBJ)^\ + +U = $(UTIL)^\ + +# +# Utility Objects. +# + +MAKESRC = $(U)makedefs.c + +SPLEVSRC = $(U)lev_yacc.c $(U)lev_$(LEX).c $(U)lev_main.c $(U)panic.c + +DGNCOMPSRC = $(U)dgn_yacc.c $(U)dgn_$(LEX).c $(U)dgn_main.c + +MAKEOBJS = $(O)makedefs.o $(O)monst.o $(O)objects.o + +SPLEVOBJS = $(O)lev_yacc.o $(O)lev_$(LEX).o $(O)lev_main.o \ + $(O)alloc.o $(O)decl.o $(O)drawing.o \ + $(O)monst.o $(O)objects.o $(O)panic.o + +DGNCOMPOBJS = $(O)dgn_yacc.o $(O)dgn_$(LEX).o $(O)dgn_main.o \ + $(O)alloc.o $(O)panic.o + +RECOVOBJS = $(O)recover.o + +TILEFILES = $(WSHR)\monsters.txt $(WSHR)\objects.txt $(WSHR)\other.txt + +# +# These are not invoked during a normal game build in 3.4.0 +# +TEXT_IO = $(O)tiletext.o $(O)tiletxt.o $(O)drawing.o \ + $(O)decl.o $(O)monst.o $(O)objects.o + +GIFREADERS = $(O)gifread.o $(O)alloc.o $(O)panic.o + +PPMWRITERS = $(O)ppmwrite.o $(O)alloc.o $(O)panic.o + +# +# Object files for the game itself. +# + +VOBJ01 = $(O)allmain.o $(O)alloc.o $(O)apply.o $(O)artifact.o +VOBJ02 = $(O)attrib.o $(O)ball.o $(O)bones.o $(O)botl.o +VOBJ03 = $(O)cmd.o $(O)dbridge.o $(O)decl.o $(O)detect.o +VOBJ04 = $(O)dig.o $(O)display.o $(O)do.o $(O)do_name.o +VOBJ05 = $(O)do_wear.o $(O)dog.o $(O)dogmove.o $(O)dokick.o +VOBJ06 = $(O)dothrow.o $(O)drawing.o $(O)dungeon.o $(O)eat.o +VOBJ07 = $(O)end.o $(O)engrave.o $(O)exper.o $(O)explode.o +VOBJ08 = $(O)extralev.o $(O)files.o $(O)fountain.o $(O)hack.o +VOBJ09 = $(O)hacklib.o $(O)invent.o $(O)light.o $(O)lock.o +VOBJ10 = $(O)mail.o $(O)makemon.o $(O)mapglyph.o $(O)mcastu.o +VOBJ11 = $(O)mhitm.o $(O)mhitu.o $(O)minion.o $(O)mklev.o +VOBJ12 = $(O)mkmap.o $(O)mkmaze.o $(O)mkobj.o $(O)mkroom.o +VOBJ13 = $(O)mon.o $(O)mondata.o $(O)monmove.o $(O)monst.o +VOBJ14 = $(O)monstr.o $(O)mplayer.o $(O)mthrowu.o $(O)muse.o +VOBJ15 = $(O)music.o $(O)o_init.o $(O)objects.o $(O)objnam.o +VOBJ16 = $(O)options.o $(O)pager.o $(O)pickup.o $(O)pline.o +VOBJ17 = $(O)polyself.o $(O)potion.o $(O)pray.o $(O)priest.o +VOBJ18 = $(O)quest.o $(O)questpgr.o $(RANDOM) $(O)read.o +VOBJ19 = $(O)rect.o $(O)region.o $(O)restore.o $(O)rip.o +VOBJ20 = $(O)rnd.o $(O)role.o $(O)rumors.o $(O)save.o +VOBJ21 = $(O)shk.o $(O)shknam.o $(O)sit.o $(O)sounds.o +VOBJ22 = $(O)sp_lev.o $(O)spell.o $(O)steal.o $(O)steed.o +VOBJ23 = $(O)teleport.o $(O)timeout.o $(O)topten.o $(O)track.o +VOBJ24 = $(O)trap.o $(O)u_init.o $(O)uhitm.o $(O)vault.o +VOBJ25 = $(O)vis_tab.o $(O)vision.o $(O)weapon.o $(O)were.o +VOBJ26 = $(O)wield.o $(O)windows.o $(O)wizard.o $(O)worm.o +VOBJ27 = $(O)worn.o $(O)write.o $(O)zap.o + +DLBOBJ = $(O)dlb.o + +TTYOBJ = $(O)topl.o $(O)getline.o $(O)wintty.o + +SOBJ = $(O)winnt.o $(O)pcsys.o $(O)pcunix.o \ + $(SOUND) $(O)pcmain.o $(O)mapimail.o $(O)nhlan.o + +OBJS = $(VOBJ01) $(VOBJ02) $(VOBJ03) $(VOBJ04) $(VOBJ05) \ + $(VOBJ06) $(VOBJ07) $(VOBJ08) $(VOBJ09) $(VOBJ10) \ + $(VOBJ11) $(VOBJ12) $(VOBJ13) $(VOBJ14) $(VOBJ15) \ + $(VOBJ16) $(VOBJ17) $(VOBJ18) $(VOBJ19) $(VOBJ20) \ + $(VOBJ21) $(VOBJ22) $(VOBJ23) $(VOBJ24) $(VOBJ25) \ + $(VOBJ26) $(VOBJ27) + +TILOBJ = $(WINPORT) + +VVOBJ = $(O)version.o + +ALLOBJ = $(TILOBJ) $(SOBJ) $(DLBOBJ) $(TTYOBJ) $(WOBJ) $(OBJS) $(VVOBJ) + + +!IF "$(GRAPHICAL)" == "Y" +OPTIONS_FILE = $(DAT)\guioptions +!ELSE +OPTIONS_FILE = $(DAT)\ttyoptions +!ENDIF +#========================================== +# Header file macros +#========================================== + +CONFIG_H = $(INCL)\config.h $(INCL)\config1.h $(INCL)\tradstdc.h \ + $(INCL)\global.h $(INCL)\coord.h $(INCL)\vmsconf.h \ + $(INCL)\system.h $(INCL)\unixconf.h $(INCL)\os2conf.h \ + $(INCL)\micro.h $(INCL)\pcconf.h $(INCL)\tosconf.h \ + $(INCL)\amiconf.h $(INCL)\macconf.h $(INCL)\beconf.h \ + $(INCL)\ntconf.h $(INCL)\nhlan.h + +HACK_H = $(INCL)\hack.h $(CONFIG_H) $(INCL)\align.h \ + $(INCL)\dungeon.h $(INCL)\monsym.h $(INCL)\mkroom.h \ + $(INCL)\objclass.h $(INCL)\youprop.h $(INCL)\prop.h \ + $(INCL)\permonst.h $(INCL)\monattk.h \ + $(INCL)\monflag.h $(INCL)\mondata.h $(INCL)\pm.h \ + $(INCL)\wintype.h $(INCL)\decl.h $(INCL)\quest.h \ + $(INCL)\spell.h $(INCL)\color.h $(INCL)\obj.h \ + $(INCL)\you.h $(INCL)\attrib.h $(INCL)\monst.h \ + $(INCL)\skills.h $(INCL)\onames.h $(INCL)\timeout.h \ + $(INCL)\trap.h $(INCL)\flag.h $(INCL)\rm.h \ + $(INCL)\vision.h $(INCL)\display.h $(INCL)\engrave.h \ + $(INCL)\rect.h $(INCL)\region.h $(INCL)\winprocs.h \ + $(INCL)\wintty.h $(INCL)\trampoli.h + +LEV_H = $(INCL)\lev.h +DGN_FILE_H = $(INCL)\dgn_file.h +LEV_COMP_H = $(INCL)\lev_comp.h +SP_LEV_H = $(INCL)\sp_lev.h +TILE_H = ..\win\share\tile.h + +#========================================== +# Miscellaneous +#========================================== + +DATABASE = $(DAT)\data.base + +# +# The name of the game. +# + +GAMEFILE = $(GAMEDIR)\$(GAME).exe + +#========================================== +#=============== TARGETS ================== +#========================================== + +# +# The default make target (so just typing 'nmake' is useful). +# +default : $(GAMEFILE) + +# +# The main target. +# + +$(GAME): $(O)obj.tag $(O)utility.tag graphicschk $(GAMEFILE) + @echo $(GAME) is up to date. + +# +# Everything +# + +all : install + +install: graphicschk $(GAME) $(O)install.tag + @echo Done. + +$(O)install.tag: $(DAT)\data $(DAT)\rumors $(DAT)\dungeon \ + $(DAT)\oracles $(DAT)\quest.dat $(O)sp_lev.tag $(DLB) +! IF ("$(USE_DLB)"=="Y") + copy nhdat $(GAMEDIR) + copy $(DAT)\license $(GAMEDIR) +! ELSE + copy $(DAT)\*. $(GAMEDIR) + copy $(DAT)\*.dat $(GAMEDIR) + copy $(DAT)\*.lev $(GAMEDIR) + if exist $(GAMEDIR)\makefile del $(GAMEDIR)\makefile +! ENDIF + if exist $(DOC)\guidebook.txt copy $(DOC)\guidebook.txt $(GAMEDIR)\Guidebook.txt + if exist $(DOC)\nethack.txt copy $(DOC)\nethack.txt $(GAMEDIR)\NetHack.txt + if exist $(DOC)\recover.txt copy $(DOC)\recover.txt $(GAMEDIR)\recover.txt + @if exist $(SRC)\$(GAME).PDB copy $(SRC)\$(GAME).pdb $(GAMEDIR)\$(GAME).pdb + @if exist $(GAMEDIR)\$(GAME).PDB echo NOTE: You may want to remove $(GAMEDIR)\$(GAME).pdb to conserve space + -copy $(NTSYS)\defaults.nh $(GAMEDIR)\defaults.nh + copy $(U)recover.exe $(GAMEDIR) + echo install done > $@ + +# copy $(NTSYS)\winnt.hlp $(GAMEDIR) + +$(O)sp_lev.tag: $(O)utility.tag $(DAT)\bigroom.des $(DAT)\castle.des \ + $(DAT)\endgame.des $(DAT)\gehennom.des $(DAT)\knox.des \ + $(DAT)\medusa.des $(DAT)\oracle.des $(DAT)\tower.des \ + $(DAT)\yendor.des $(DAT)\arch.des $(DAT)\barb.des \ + $(DAT)\caveman.des $(DAT)\healer.des $(DAT)\knight.des \ + $(DAT)\monk.des $(DAT)\priest.des $(DAT)\ranger.des \ + $(DAT)\rogue.des $(DAT)\samurai.des $(DAT)\sokoban.des \ + $(DAT)\tourist.des $(DAT)\valkyrie.des $(DAT)\wizard.des + cd $(DAT) + $(U)lev_comp bigroom.des + $(U)lev_comp castle.des + $(U)lev_comp endgame.des + $(U)lev_comp gehennom.des + $(U)lev_comp knox.des + $(U)lev_comp mines.des + $(U)lev_comp medusa.des + $(U)lev_comp oracle.des + $(U)lev_comp sokoban.des + $(U)lev_comp tower.des + $(U)lev_comp yendor.des + $(U)lev_comp arch.des + $(U)lev_comp barb.des + $(U)lev_comp caveman.des + $(U)lev_comp healer.des + $(U)lev_comp knight.des + $(U)lev_comp monk.des + $(U)lev_comp priest.des + $(U)lev_comp ranger.des + $(U)lev_comp rogue.des + $(U)lev_comp samurai.des + $(U)lev_comp tourist.des + $(U)lev_comp valkyrie.des + $(U)lev_comp wizard.des + cd $(SRC) + echo sp_levs done > $(O)sp_lev.tag + +$(O)utility.tag: $(INCL)\date.h $(INCL)\onames.h $(INCL)\pm.h \ + $(SRC)\monstr.c $(SRC)\vis_tab.c \ + $(U)lev_comp.exe $(INCL)\vis_tab.h \ + $(U)dgn_comp.exe $(U)recover.exe $(TILEUTIL16) + @echo utilities made >$@ + @echo utilities made. + +tileutil: $(U)gif2txt.exe $(U)txt2ppm.exe + @echo Optional tile development utilities are up to date. + +!IF "$(GRAPHICAL)"=="Y" +$(NHRES): $(TILEBMP16) $(WIN32)\winhack.rc $(WIN32)\mnsel.bmp \ + $(WIN32)\mnselcnt.bmp $(WIN32)\mnunsel.bmp \ + $(WIN32)\petmark.bmp $(WIN32)\NetHack.ico $(WIN32)\rip.bmp \ + $(WIN32)\splash.bmp + @$(rc) -r -fo$@ -i$(WIN32) -i$(bccinc) -dNDEBUG $(WIN32)\winhack.rc +!ELSE +$(NHRES): $(NTSYS)\console.rc $(NTSYS)\NetHack.ico + @$(rc) -r -fo$@ -i$(NTSYS) -i$(bccinc) -dNDEBUG $(NTSYS)\console.rc +!ENDIF + +#========================================== +# The main target. +#========================================== + +$(SRC)\uuid.lib: $(bcclib)\uuid.lib + @copy $(bcclib)\uuid.lib $@ + +$(GAMEFILE) : $(ALLOBJ) $(NHRES) $(SRC)\uuid.lib + @echo Linking.... + @$(link) $(lflags) $(startobjg) $(ALLOBJ), $@, $(GAME).map,$(libsmt),,$(NHRES) + @if exist $(O)install.tag del $(O)install.tag + @if exist $(GAMEDIR)\$(GAME).bak del $(GAMEDIR)\$(GAME).bak + +$(GAME)_.ico : $(NTSYS)\$(GAME).ico + @copy $(NTSYS)\$(GAME).ico $@ + +#========================================== +# Create directory for holding object files +#========================================== + +$(O)obj.tag: + @if not exist $(O)*.* mkdir $(OBJ) + @echo directory $(OBJ) created >$@ + +#========================================== +# Notify of any CL environment variables +# in effect since they change the compiler +# options. +#========================================== + +graphicschk: +! IF "$(GRAPHICAL)"=="Y" + @echo ---- + @echo NOTE: This build will include tile support. + @echo ---- +! ENDIF + @echo graphicschk > graphicschk + +# +# Secondary Targets. +# + +#========================================== +# Makedefs Stuff +#========================================== + +$(U)makedefs.exe: $(O)obj.tag $(MAKEOBJS) $(SRC)\uuid.lib + @$(link) $(LFLAGSU) $(startobj) $(MAKEOBJS), $@,,$(libsmt) + +$(O)makedefs.o: $(CONFIG_H) $(INCL)\monattk.h $(INCL)\monflag.h $(INCL)\objclass.h \ + $(INCL)\monsym.h $(INCL)\qtext.h $(INCL)\patchlevel.h \ + $(U)makedefs.c + @$(cc) $(CFLAGSU) -o$@ $(U)makedefs.c + +# +# date.h should be remade every time any of the source or include +# files is modified. +# + +$(INCL)\date.h $(OPTIONS_FILE) : $(U)makedefs.exe + $(U)makedefs -v + +$(INCL)\onames.h : $(U)makedefs.exe + $(U)makedefs -o + +$(INCL)\pm.h : $(U)makedefs.exe + $(U)makedefs -p + +#$(INCL)\trap.h : $(U)makedefs.exe +# $(U)makedefs -t + +$(SRC)\monstr.c: $(U)makedefs.exe + $(U)makedefs -m + +$(INCL)\vis_tab.h: $(U)makedefs.exe + $(U)makedefs -z + +$(SRC)\vis_tab.c: $(U)makedefs.exe + $(U)makedefs -z + +#========================================== +# uudecode utility and uuencoded targets +#========================================== + +$(U)uudecode.exe: $(O)uudecode.o + @$(link) $(LFLAGSU) $(startobj) $(O)\uudecode.o, $@,,$(libsmt) + +$(O)uudecode.o: $(SSYS)\uudecode.c + +$(NTSYS)\NetHack.ico : $(U)uudecode.exe $(NTSYS)\nhico.uu + chdir $(NTSYS) + ..\..\util\uudecode.exe nhico.uu + chdir ..\..\src + +$(WIN32)\NetHack.ico : $(U)uudecode.exe $(NTSYS)\nhico.uu + chdir $(WIN32) + ..\..\util\uudecode.exe ../../sys/winnt/nhico.uu + chdir ..\..\src + +$(WIN32)\mnsel.bmp: $(U)uudecode.exe $(WIN32)\mnsel.uu + chdir $(WIN32) + ..\..\util\uudecode.exe mnsel.uu + chdir ..\..\src + +$(WIN32)\mnselcnt.bmp: $(U)uudecode.exe $(WIN32)\mnselcnt.uu + chdir $(WIN32) + ..\..\util\uudecode.exe mnselcnt.uu + chdir ..\..\src + +$(WIN32)\mnunsel.bmp: $(U)uudecode.exe $(WIN32)\mnunsel.uu + chdir $(WIN32) + ..\..\util\uudecode.exe mnunsel.uu + chdir ..\..\src + +$(WIN32)\petmark.bmp: $(U)uudecode.exe $(WIN32)\petmark.uu + chdir $(WIN32) + ..\..\util\uudecode.exe petmark.uu + chdir ..\..\src + +$(WIN32)\rip.bmp: $(U)uudecode.exe $(WIN32)\rip.uu + chdir $(WIN32) + ..\..\util\uudecode.exe rip.uu + chdir ..\..\src + +$(WIN32)\splash.bmp: $(U)uudecode.exe $(WIN32)\splash.uu + chdir $(WIN32) + ..\..\util\uudecode.exe splash.uu + chdir ..\..\src + +#========================================== +# Level Compiler Stuff +#========================================== + +LEVCFLAGS=$(cflags) -DWIN32 -D_WIN32 -D_MT -I..\include $(cdebug) -DDLB + +$(U)lev_comp.exe: $(SPLEVOBJS) $(SRC)\uuid.lib + @echo Linking $@... + @$(link) $(LFLAGSU) $(startobj) $(SPLEVOBJS), $@,,$(libsmt) + +$(O)lev_yacc.o: $(HACK_H) $(SP_LEV_H) $(INCL)\lev_comp.h $(U)lev_yacc.c + @$(cc) $(LEVCFLAGS) -o$@ $(U)lev_yacc.c + +$(O)lev_$(LEX).o: $(HACK_H) $(INCL)\lev_comp.h $(SP_LEV_H) \ + $(U)lev_$(LEX).c + @$(cc) $(LEVCFLAGS) -D__IO_H -o$@ $(U)lev_$(LEX).c + +$(O)lev_main.o: $(U)lev_main.c $(HACK_H) $(SP_LEV_H) + @$(cc) $(LEVCFLAGS) -o$@ $(U)lev_main.c + + +$(U)lev_yacc.c $(INCL)\lev_comp.h : $(U)lev_comp.y +! IF "$(DO_YACC)"=="YACC_ACT" + chdir $(UTIL) + $(YACC) -d lev_comp.y + copy $(YTABC) lev_yacc.c + copy $(YTABH) $(INCL)\lev_comp.h + @del $(YTABC) + @del $(YTABH) + chdir $(SRC) +! ELSE + @echo $(U)lev_comp.y has changed. + @echo To update $(U)lev_yacc.c and $(INCL)\lev_comp.h run $(YACC). + @echo --- + @echo For now, we will copy the prebuilt lev_yacc.c and + @echo lev_comp.h from $(SSYS) into $(UTIL) and use them. + @copy $(SSYS)\lev_yacc.c $(U)lev_yacc.c >nul + @copy $(SSYS)\lev_comp.h $(INCL)\lev_comp.h >nul + @echo /**/ >>$(U)lev_yacc.c + @echo /**/ >>$(INCL)\lev_comp.h +! ENDIF + +$(U)lev_$(LEX).c: $(U)lev_comp.l +! IF "$(DO_LEX)"=="LEX_ACT" + chdir $(UTIL) + $(LEX) $(FLEXSKEL) lev_comp.l + copy $(LEXYYC) $@ + @del $(LEXYYC) + chdir $(SRC) +! ELSE + @echo $(U)lev_comp.l has changed. To update $@ run $(LEX). + @echo --- + @echo For now, we will copy the prebuilt lev_lex.c + @echo from $(SSYS) into $(UTIL) and use it. + @copy $(SSYS)\lev_lex.c $@ >nul + @echo /**/ >>$@ +! ENDIF + +#========================================== +# Dungeon Compiler Stuff +#========================================== + +$(U)dgn_comp.exe: $(DGNCOMPOBJS) $(SRC)\uuid.lib + @echo Linking $@... + @$(link) $(LFLAGSU) $(startobj) $(DGNCOMPOBJS), $@,,$(libsmt) + + +$(O)dgn_yacc.o: $(HACK_H) $(DGN_FILE_H) $(INCL)\dgn_comp.h $(U)dgn_yacc.c + @$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_yacc.c + +$(O)dgn_$(LEX).o: $(HACK_H) $(DGN_FILE_H) $(INCL)\dgn_comp.h \ + $(U)dgn_$(LEX).c + @$(cc) $(LEVCFLAGS) -D__IO_H -o$@ $(U)dgn_$(LEX).c + +$(O)dgn_main.o: $(HACK_H) $(U)dgn_main.c + @$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_main.c + +$(U)dgn_yacc.c $(INCL)\dgn_comp.h : $(U)dgn_comp.y +! IF "$(DO_YACC)"=="YACC_ACT" + chdir $(UTIL) + $(YACC) -d dgn_comp.y + copy $(YTABC) dgn_yacc.c + copy $(YTABH) $(INCL)\dgn_comp.h + @del $(YTABC) + @del $(YTABH) + chdir $(SRC) +! ELSE + @echo $(U)dgn_comp.y has changed. To update dgn_yacc.c and + @echo $(INCL)\dgn_comp.h run $(YACC). + @echo --- + @echo For now, we will copy the prebuilt $(U)dgn_yacc.c and + @echo dgn_comp.h from $(SSYS) into $(UTIL) and use them. + @copy $(SSYS)\dgn_yacc.c $(U)dgn_yacc.c >nul + @copy $(SSYS)\dgn_comp.h $(INCL)\dgn_comp.h >nul + @echo /**/ >>$(U)dgn_yacc.c + @echo /**/ >>$(INCL)\dgn_comp.h +! ENDIF + +$(U)dgn_$(LEX).c: $(U)dgn_comp.l +! IF "$(DO_LEX)"=="LEX_ACT" + chdir $(UTIL) + $(LEX) $(FLEXSKEL) dgn_comp.l + copy $(LEXYYC) $@ + @del $(LEXYYC) + chdir $(SRC) +! ELSE + @echo $(U)dgn_comp.l has changed. To update $@ run $(LEX). + @echo --- + @echo For now, we will copy the prebuilt dgn_lex.c + @echo from $(SSYS) into $(UTIL) and use it. + @copy $(SSYS)\dgn_lex.c $@ >nul + @echo /**/ >>$@ +! ENDIF + + +#========================================== +#=========== SECONDARY TARGETS ============ +#========================================== + +#=========================================== +# Header files NOT distributed in ..\include +#=========================================== + +$(INCL)\win32api.h: $(NTSYS)\win32api.h + copy $(NTSYS)\win32api.h $@ + + +#========================================== +# DLB utility and nhdat file creation +#========================================== + +$(U)dlb_main.exe: $(DLBOBJ) $(O)dlb.o $(SRC)\uuid.lib + @$(link) $(LFLAGSU) $(startobj) $(O)dlb_main.o $(O)dlb.o $(O)alloc.o $(O)panic.o, $@,,$(libsmt) + + +$(O)dlb.o: $(O)dlb_main.o $(O)alloc.o $(O)panic.o $(INCL)\dlb.h + @$(cc) $(CFLAGS) -o$@ $(SRC)\dlb.c + +$(O)dlb_main.o: $(UTIL)\dlb_main.c $(INCL)\config.h $(INCL)\dlb.h + @$(cc) $(CFLAGS) -o$@ $(UTIL)\dlb_main.c + +$(DAT)\porthelp: $(NTSYS)\porthelp + @copy $(NTSYS)\porthelp $@ >nul + +nhdat: $(U)dlb_main.exe $(DAT)\data $(DAT)\oracles $(OPTIONS_FILE) \ + $(DAT)\quest.dat $(DAT)\rumors $(DAT)\help $(DAT)\hh $(DAT)\cmdhelp \ + $(DAT)\history $(DAT)\opthelp $(DAT)\wizhelp $(DAT)\dungeon $(DAT)\porthelp \ + $(DAT)\license $(O)sp_lev.tag + cd $(DAT) + echo data >dlb.lst + echo oracles >>dlb.lst + if exist options echo options >>dlb.lst + if exist ttyoptions echo ttyoptions >>dlb.lst + if exist guioptions echo guioptions >>dlb.lst + if exist porthelp echo porthelp >>dlb.lst + echo quest.dat >>dlb.lst + echo rumors >>dlb.lst + echo help >>dlb.lst + echo hh >>dlb.lst + echo cmdhelp >>dlb.lst + echo history >>dlb.lst + echo opthelp >>dlb.lst + echo wizhelp >>dlb.lst + echo dungeon >>dlb.lst + echo license >>dlb.lst + for %N in (*.lev) do echo %N >>dlb.lst + $(U)dlb_main cIf dlb.lst $(SRC)\nhdat + cd $(SRC) + +#========================================== +# Recover Utility +#========================================== + +$(U)recover.exe: $(RECOVOBJS) $(SRC)\uuid.lib + @$(link) $(LFLAGSU) $(startobj) $(RECOVOBJS), $@,,$(libsmt) + + +$(O)recover.o: $(CONFIG_H) $(U)recover.c $(INCL)\win32api.h + @$(cc) $(CFLAGSU) -o$@ $(U)recover.c + +#========================================== +# Tile Mapping +#========================================== + +$(SRC)\tile.c: $(U)tilemap.exe + @echo A new $@ has been created + @$(U)tilemap + +$(U)tilemap.exe: $(O)tilemap.o $(SRC)\uuid.lib + @$(link) $(LFLAGSU) $(startobj) $(O)tilemap.o, $@,,$(libsmt) + + +$(O)tilemap.o: $(WSHR)\tilemap.c $(HACK_H) + @$(cc) $(CFLAGSU) -o$@ $(WSHR)\tilemap.c + +$(O)tiletxt.o: $(WSHR)\tilemap.c $(HACK_H) + @$(cc) $(CFLAGS) /DTILETEXT -o$@ $(WSHR)\tilemap.c + +$(O)gifread.o: $(WSHR)\gifread.c $(CONFIG_H) $(TILE_H) + @$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)\gifread.c + +$(O)ppmwrite.o: $(WSHR)\ppmwrite.c $(CONFIG_H) $(TILE_H) + @$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)\ppmwrite.c + +$(O)tiletext.o: $(WSHR)\tiletext.c $(CONFIG_H) $(TILE_H) + @$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)\tiletext.c + +#========================================== +# Optional Tile Utilities +#========================================== + +$(U)gif2txt.exe: $(GIFREADERS) $(TEXT_IO) $(SRC)\uuid.lib + @echo Linking $@... + @$(link) $(LFLAGSU) $(startobj) $(GIFREADERS) $(TEXT_IO), $@,,$(libsmt) + + +$(U)txt2ppm.exe: $(PPMWRITERS) $(TEXT_IO) $(SRC)\uuid.lib + @echo Linking $@... + @$(link) $(LFLAGSU) $(startobj) $(PPMWRITERS) $(TEXT_IO), $@,,$(libsmt) + + +!IF "$(GRAPHICAL)"=="Y" +$(TILEBMP16): $(TILEUTIL16) $(TILEFILES) + @echo Creating 16x16 binary tile files (this may take some time) + @$(U)tile2bmp $(TILEBMP16) +!ENDIF + +$(U)tile2bmp.exe: $(O)tile2bmp.o $(TEXT_IO) $(SRC)\uuid.lib + @echo Linking $@... + @$(link) $(LFLAGSU) $(startobj) $(O)tile2bmp.o $(TEXT_IO), $@,,$(libsmt) + + +$(O)tile2bmp.o: $(WSHR)\tile2bmp.c $(HACK_H) $(TILE_H) $(INCL)\win32api.h + @$(cc) $(CFLAGS) -I$(WSHR) /DPACKED_FILE -o$@ $(WSHR)\tile2bmp.c + +#========================================== +# Housekeeping +#========================================== + +spotless: clean +! IF ("$(OBJ)"!="") + -rmdir $(OBJ) /s /Q +! ENDIF + if exist $(INCL)\date.h del $(INCL)\date.h + if exist $(INCL)\onames.h del $(INCL)\onames.h + if exist $(INCL)\pm.h del $(INCL)\pm.h + if exist $(INCL)\vis_tab.h del $(INCL)\vis_tab.h + if exist $(SRC)\vis_tab.c del $(SRC)\vis_tab.c + if exist $(SRC)\tile.c del $(SRC)\tile.c + if exist $(U)*.lnk del $(U)*.lnk + if exist $(U)*.map del $(U)*.map + if exist $(DAT)\data del $(DAT)\data + if exist $(DAT)\rumors del $(DAT)\rumors + if exist $(DAT)\???-fil?.lev del $(DAT)\???-fil?.lev + if exist $(DAT)\???-goal.lev del $(DAT)\???-goal.lev + if exist $(DAT)\???-loca.lev del $(DAT)\???-loca.lev + if exist $(DAT)\???-strt.lev del $(DAT)\???-strt.lev + if exist $(DAT)\air.lev del $(DAT)\air.lev + if exist $(DAT)\asmodeus.lev del $(DAT)\asmodeus.lev + if exist $(DAT)\astral.lev del $(DAT)\astral.lev + if exist $(DAT)\baalz.lev del $(DAT)\baalz.lev + if exist $(DAT)\bigroom.lev del $(DAT)\bigroom.lev + if exist $(DAT)\castle.lev del $(DAT)\castle.lev + if exist $(DAT)\data del $(DAT)\data + if exist $(DAT)\dungeon del $(DAT)\dungeon + if exist $(DAT)\dungeon.pdf del $(DAT)\dungeon.pdf + if exist $(DAT)\earth.lev del $(DAT)\earth.lev + if exist $(DAT)\fakewiz?.lev del $(DAT)\fakewiz?.lev + if exist $(DAT)\fire.lev del $(DAT)\fire.lev + if exist $(DAT)\juiblex.lev del $(DAT)\juiblex.lev + if exist $(DAT)\knox.lev del $(DAT)\knox.lev + if exist $(DAT)\medusa-?.lev del $(DAT)\medusa-?.lev + if exist $(DAT)\mine*.lev del $(DAT)\mine*.lev + if exist $(DAT)\options del $(DAT)\options + if exist $(DAT)\ttyoptions del $(DAT)\ttyoptions + if exist $(DAT)\guioptions del $(DAT)\guioptions + if exist $(DAT)\oracle.lev del $(DAT)\oracle.lev + if exist $(DAT)\oracles del $(DAT)\oracles + if exist $(DAT)\orcus.lev del $(DAT)\orcus.lev + if exist $(DAT)\rumors del $(DAT)\rumors + if exist $(DAT)\quest.dat del $(DAT)\quest.dat + if exist $(DAT)\sanctum.lev del $(DAT)\sanctum.lev + if exist $(DAT)\soko?-?.lev del $(DAT)\soko?-?.lev + if exist $(DAT)\tower?.lev del $(DAT)\tower?.lev + if exist $(DAT)\valley.lev del $(DAT)\valley.lev + if exist $(DAT)\water.lev del $(DAT)\water.lev + if exist $(DAT)\wizard?.lev del $(DAT)\wizard?.lev + if exist $(O)sp_lev.tag del $(O)sp_lev.tag + if exist $(SRC)\monstr.c del $(SRC)\monstr.c + if exist $(SRC)\vis_tab.c del $(SRC)\vis_tab.c + if exist $(U)recover.exe del $(U)recover.exe + if exist nhdat. del nhdat. + +clean: + if exist $(O)*.o del $(O)*.o + if exist $(O)utility.tag del $(O)utility.tag + if exist $(U)makedefs.exe del $(U)makedefs.exe + if exist $(U)lev_comp.exe del $(U)lev_comp.exe + if exist $(U)dgn_comp.exe del $(U)dgn_comp.exe + if exist $(SRC)\*.lnk del $(SRC)\*.lnk + if exist $(SRC)\*.map del $(SRC)\*.map + if exist $(TILEBMP16) del $(TILEBMP16) + +#=================================================================== +# OTHER DEPENDENCIES +#=================================================================== + +# +# dat dependencies +# + +$(DAT)\data: $(O)utility.tag $(DATABASE) + $(U)makedefs -d + +$(DAT)\rumors: $(O)utility.tag $(DAT)\rumors.tru $(DAT)\rumors.fal + $(U)makedefs -r + +$(DAT)\quest.dat: $(O)utility.tag $(DAT)\quest.txt + $(U)makedefs -q + +$(DAT)\oracles: $(O)utility.tag $(DAT)\oracles.txt + $(U)makedefs -h + +$(DAT)\dungeon: $(O)utility.tag $(DAT)\dungeon.def + $(U)makedefs -e + cd $(DAT) + $(U)dgn_comp dungeon.pdf + cd $(SRC) + +# +# NT dependencies +# + +$(O)nttty.o: $(HACK_H) $(TILE_H) $(INCL)\win32api.h $(NTSYS)\nttty.c + @$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(NTSYS)\nttty.c +$(O)winnt.o: $(HACK_H) $(INCL)\win32api.h $(NTSYS)\winnt.c + @$(cc) $(CFLAGS) -o$@ $(NTSYS)\winnt.c +$(O)ntsound.o: $(HACK_H) $(NTSYS)\ntsound.c + @$(cc) $(CFLAGS) -o$@ $(NTSYS)\ntsound.c +$(O)mapimail.o: $(HACK_H) $(INCL)\nhlan.h $(NTSYS)\mapimail.c + @$(cc) $(CFLAGS) -DMAPI_VERBOSE -o$@ $(NTSYS)\mapimail.c + +# +# util dependencies +# + +$(O)panic.o: $(U)panic.c $(CONFIG_H) + @$(cc) $(CFLAGS) -o$@ $(U)panic.c + +# +# The rest are stolen from sys/unix/Makefile.src, +# with slashes changed to back-slashes +# and -c (which is included in CFLAGS) substituted +# with -o$@ , but otherwise untouched. That +# means that there is some irrelevant stuff +# in here, but maintenance should be easier. +# +$(O)tos.o: ..\sys\atari\tos.c $(HACK_H) $(INCL)\tcap.h + $(cc) $(CFLAGS) -o$@ ..\sys\atari\tos.c +$(O)pcmain.o: ..\sys\share\pcmain.c $(HACK_H) $(INCL)\dlb.h \ + $(INCL)\win32api.h + $(cc) $(CFLAGS) -o$@ ..\sys\share\pcmain.c +$(O)pcsys.o: ..\sys\share\pcsys.c $(HACK_H) + $(cc) $(CFLAGS) -o$@ ..\sys\share\pcsys.c +$(O)pctty.o: ..\sys\share\pctty.c $(HACK_H) + $(cc) $(CFLAGS) -o$@ ..\sys\share\pctty.c +$(O)pcunix.o: ..\sys\share\pcunix.c $(HACK_H) + $(cc) $(CFLAGS) -o$@ ..\sys\share\pcunix.c +$(O)random.o: ..\sys\share\random.c $(HACK_H) + $(cc) $(CFLAGS) -o$@ ..\sys\share\random.c +$(O)ioctl.o: ..\sys\share\ioctl.c $(HACK_H) $(INCL)\tcap.h + $(cc) $(CFLAGS) -o$@ ..\sys\share\ioctl.c +$(O)unixtty.o: ..\sys\share\unixtty.c $(HACK_H) + $(cc) $(CFLAGS) -o$@ ..\sys\share\unixtty.c +$(O)unixmain.o: ..\sys\unix\unixmain.c $(HACK_H) $(INCL)\dlb.h + $(cc) $(CFLAGS) -o$@ ..\sys\unix\unixmain.c +$(O)unixunix.o: ..\sys\unix\unixunix.c $(HACK_H) + $(cc) $(CFLAGS) -o$@ ..\sys\unix\unixunix.c +$(O)bemain.o: ..\sys\be\bemain.c $(HACK_H) $(INCL)\dlb.h + $(cc) $(CFLAGS) -o$@ ..\sys\be\bemain.c +$(O)getline.o: ..\win\tty\getline.c $(HACK_H) $(INCL)\func_tab.h + $(cc) $(CFLAGS) -o$@ ..\win\tty\getline.c +$(O)termcap.o: ..\win\tty\termcap.c $(HACK_H) $(INCL)\tcap.h + $(cc) $(CFLAGS) -o$@ ..\win\tty\termcap.c +$(O)topl.o: ..\win\tty\topl.c $(HACK_H) $(INCL)\tcap.h + $(cc) $(CFLAGS) -o$@ ..\win\tty\topl.c +$(O)wintty.o: ..\win\tty\wintty.c $(HACK_H) $(INCL)\dlb.h \ + $(INCL)\patchlevel.h $(INCL)\tcap.h + $(cc) $(CFLAGS) -o$@ ..\win\tty\wintty.c +$(O)Window.o: ..\win\X11\Window.c $(INCL)\xwindowp.h $(INCL)\xwindow.h \ + $(CONFIG_H) + $(cc) $(CFLAGS) -o$@ ..\win\X11\Window.c +$(O)dialogs.o: ..\win\X11\dialogs.c $(CONFIG_H) + $(cc) $(CFLAGS) -o$@ ..\win\X11\dialogs.c +$(O)winX.o: ..\win\X11\winX.c $(HACK_H) $(INCL)\winX.h $(INCL)\dlb.h \ + $(INCL)\patchlevel.h ..\win\X11\nh72icon \ + ..\win\X11\nh56icon ..\win\X11\nh32icon + $(cc) $(CFLAGS) -o$@ ..\win\X11\winX.c +$(O)winmap.o: ..\win\X11\winmap.c $(INCL)\xwindow.h $(HACK_H) $(INCL)\dlb.h \ + $(INCL)\winX.h $(INCL)\tile2x11.h + $(cc) $(CFLAGS) -o$@ ..\win\X11\winmap.c +$(O)winmenu.o: ..\win\X11\winmenu.c $(HACK_H) $(INCL)\winX.h + $(cc) $(CFLAGS) -o$@ ..\win\X11\winmenu.c +$(O)winmesg.o: ..\win\X11\winmesg.c $(INCL)\xwindow.h $(HACK_H) $(INCL)\winX.h + $(cc) $(CFLAGS) -o$@ ..\win\X11\winmesg.c +$(O)winmisc.o: ..\win\X11\winmisc.c $(HACK_H) $(INCL)\func_tab.h \ + $(INCL)\winX.h + $(cc) $(CFLAGS) -o$@ ..\win\X11\winmisc.c +$(O)winstat.o: ..\win\X11\winstat.c $(HACK_H) $(INCL)\winX.h + $(cc) $(CFLAGS) -o$@ ..\win\X11\winstat.c +$(O)wintext.o: ..\win\X11\wintext.c $(HACK_H) $(INCL)\winX.h $(INCL)\xwindow.h + $(cc) $(CFLAGS) -o$@ ..\win\X11\wintext.c +$(O)winval.o: ..\win\X11\winval.c $(HACK_H) $(INCL)\winX.h + $(cc) $(CFLAGS) -o$@ ..\win\X11\winval.c +$(O)tile.o: $(SRC)\tile.c $(HACK_H) +$(O)gnaskstr.o: ..\win\gnome\gnaskstr.c ..\win\gnome\gnaskstr.h \ + ..\win\gnome\gnmain.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnaskstr.c +$(O)gnbind.o: ..\win\gnome\gnbind.c ..\win\gnome\gnbind.h ..\win\gnome\gnmain.h \ + ..\win\gnome\gnaskstr.h ..\win\gnome\gnyesno.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnbind.c +$(O)gnglyph.o: ..\win\gnome\gnglyph.c ..\win\gnome\gnglyph.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnglyph.c +$(O)gnmain.o: ..\win\gnome\gnmain.c ..\win\gnome\gnmain.h ..\win\gnome\gnsignal.h \ + ..\win\gnome\gnbind.h ..\win\gnome\gnopts.h $(HACK_H) \ + $(INCL)\date.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnmain.c +$(O)gnmap.o: ..\win\gnome\gnmap.c ..\win\gnome\gnmap.h ..\win\gnome\gnglyph.h \ + ..\win\gnome\gnsignal.h $(HACK_H) + $(cc) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnmap.c +$(O)gnmenu.o: ..\win\gnome\gnmenu.c ..\win\gnome\gnmenu.h ..\win\gnome\gnmain.h \ + ..\win\gnome\gnbind.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnmenu.c +$(O)gnmesg.o: ..\win\gnome\gnmesg.c ..\win\gnome\gnmesg.h ..\win\gnome\gnsignal.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnmesg.c +$(O)gnopts.o: ..\win\gnome\gnopts.c ..\win\gnome\gnopts.h ..\win\gnome\gnglyph.h \ + ..\win\gnome\gnmain.h ..\win\gnome\gnmap.h $(HACK_H) + $(cc) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnopts.c +$(O)gnplayer.o: ..\win\gnome\gnplayer.c ..\win\gnome\gnplayer.h \ + ..\win\gnome\gnmain.h $(HACK_H) + $(cc) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnplayer.c +$(O)gnsignal.o: ..\win\gnome\gnsignal.c ..\win\gnome\gnsignal.h \ + ..\win\gnome\gnmain.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnsignal.c +$(O)gnstatus.o: ..\win\gnome\gnstatus.c ..\win\gnome\gnstatus.h \ + ..\win\gnome\gnsignal.h ..\win\gnome\gn_xpms.h \ + ..\win\gnome\gnomeprv.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnstatus.c +$(O)gntext.o: ..\win\gnome\gntext.c ..\win\gnome\gntext.h ..\win\gnome\gnmain.h \ + ..\win\gnome\gn_rip.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gntext.c +$(O)gnyesno.o: ..\win\gnome\gnyesno.c ..\win\gnome\gnbind.h ..\win\gnome\gnyesno.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnyesno.c +$(O)wingem.o: ..\win\gem\wingem.c $(HACK_H) $(INCL)\func_tab.h $(INCL)\dlb.h \ + $(INCL)\patchlevel.h $(INCL)\wingem.h + $(cc) $(CFLAGS) -o$@ ..\win\gem\wingem.c +$(O)wingem1.o: ..\win\gem\wingem1.c $(INCL)\gem_rsc.h $(INCL)\load_img.h \ + $(INCL)\wintype.h $(INCL)\wingem.h + $(cc) $(CFLAGS) -o$@ ..\win\gem\wingem1.c +$(O)load_img.o: ..\win\gem\load_img.c $(INCL)\load_img.h + $(cc) $(CFLAGS) -o$@ ..\win\gem\load_img.c +$(O)tile.o: tile.c $(HACK_H) +$(O)qt_win.o: ..\win\Qt\qt_win.cpp $(HACK_H) $(INCL)\func_tab.h \ + $(INCL)\dlb.h $(INCL)\patchlevel.h $(INCL)\qt_win.h \ + $(INCL)\qt_clust.h $(INCL)\qt_kde0.h \ + $(INCL)\qt_xpms.h qt_win.moc qt_kde0.moc + $(CXX) $(CXXFLAGS) -c ..\win\Qt\qt_win.cpp +$(O)qt_clust.o: ..\win\Qt\qt_clust.cpp $(INCL)\qt_clust.h + $(CXX) $(CXXFLAGS) -c ..\win\Qt\qt_clust.cpp +$(O)monstr.o: $(SRC)\monstr.c $(CONFIG_H) +$(O)vis_tab.o: $(SRC)\vis_tab.c $(CONFIG_H) $(INCL)\vis_tab.h +$(O)allmain.o: allmain.c $(HACK_H) +$(O)alloc.o: alloc.c $(CONFIG_H) +$(O)apply.o: apply.c $(HACK_H) $(INCL)\edog.h +$(O)artifact.o: artifact.c $(HACK_H) $(INCL)\artifact.h $(INCL)\artilist.h +$(O)attrib.o: attrib.c $(HACK_H) $(INCL)\artifact.h +$(O)ball.o: ball.c $(HACK_H) +$(O)bones.o: bones.c $(HACK_H) $(INCL)\lev.h +$(O)botl.o: botl.c $(HACK_H) +$(O)cmd.o: cmd.c $(HACK_H) $(INCL)\func_tab.h +$(O)dbridge.o: dbridge.c $(HACK_H) +$(O)decl.o: decl.c $(HACK_H) +$(O)detect.o: detect.c $(HACK_H) $(INCL)\artifact.h +$(O)dig.o: dig.c $(HACK_H) $(INCL)\edog.h +$(O)display.o: display.c $(HACK_H) +$(O)dlb.o: dlb.c $(CONFIG_H) $(INCL)\dlb.h +$(O)do.o: do.c $(HACK_H) $(INCL)\lev.h +$(O)do_name.o: do_name.c $(HACK_H) +$(O)do_wear.o: do_wear.c $(HACK_H) +$(O)dog.o: dog.c $(HACK_H) $(INCL)\edog.h +$(O)dogmove.o: dogmove.c $(HACK_H) $(INCL)\mfndpos.h $(INCL)\edog.h +$(O)dokick.o: dokick.c $(HACK_H) $(INCL)\eshk.h +$(O)dothrow.o: dothrow.c $(HACK_H) +$(O)drawing.o: drawing.c $(HACK_H) $(INCL)\tcap.h +$(O)dungeon.o: dungeon.c $(HACK_H) $(INCL)\dgn_file.h $(INCL)\dlb.h +$(O)eat.o: eat.c $(HACK_H) +$(O)end.o: end.c $(HACK_H) $(INCL)\eshk.h $(INCL)\dlb.h +$(O)engrave.o: engrave.c $(HACK_H) $(INCL)\lev.h +$(O)exper.o: exper.c $(HACK_H) +$(O)explode.o: explode.c $(HACK_H) +$(O)extralev.o: extralev.c $(HACK_H) +$(O)files.o: files.c $(HACK_H) $(INCL)\dlb.h +$(O)fountain.o: fountain.c $(HACK_H) +$(O)hack.o: hack.c $(HACK_H) +$(O)hacklib.o: hacklib.c $(HACK_H) +$(O)invent.o: invent.c $(HACK_H) $(INCL)\artifact.h +$(O)light.o: light.c $(HACK_H) $(INCL)\lev.h +$(O)lock.o: lock.c $(HACK_H) +$(O)mail.o: mail.c $(HACK_H) $(INCL)\mail.h +$(O)makemon.o: makemon.c $(HACK_H) $(INCL)\epri.h $(INCL)\emin.h \ + $(INCL)\edog.h +$(O)mapglyph.o: mapglyph.c $(HACK_H) +$(O)mcastu.o: mcastu.c $(HACK_H) +$(O)mhitm.o: mhitm.c $(HACK_H) $(INCL)\artifact.h $(INCL)\edog.h +$(O)mhitu.o: mhitu.c $(HACK_H) $(INCL)\artifact.h $(INCL)\edog.h +$(O)minion.o: minion.c $(HACK_H) $(INCL)\emin.h $(INCL)\epri.h +$(O)mklev.o: mklev.c $(HACK_H) +$(O)mkmap.o: mkmap.c $(HACK_H) $(INCL)\sp_lev.h +$(O)mkmaze.o: mkmaze.c $(HACK_H) $(INCL)\sp_lev.h $(INCL)\lev.h +$(O)mkobj.o: mkobj.c $(HACK_H) $(INCL)\artifact.h +$(O)mkroom.o: mkroom.c $(HACK_H) +$(O)mon.o: mon.c $(HACK_H) $(INCL)\mfndpos.h $(INCL)\edog.h +$(O)mondata.o: mondata.c $(HACK_H) $(INCL)\eshk.h $(INCL)\epri.h +$(O)monmove.o: monmove.c $(HACK_H) $(INCL)\mfndpos.h $(INCL)\artifact.h +$(O)monst.o: monst.c $(CONFIG_H) $(INCL)\permonst.h $(INCL)\align.h \ + $(INCL)\monattk.h $(INCL)\monflag.h $(INCL)\monsym.h \ + $(INCL)\dungeon.h $(INCL)\eshk.h $(INCL)\vault.h \ + $(INCL)\epri.h $(INCL)\color.h +$(O)mplayer.o: mplayer.c $(HACK_H) +$(O)mthrowu.o: mthrowu.c $(HACK_H) +$(O)muse.o: muse.c $(HACK_H) $(INCL)\edog.h +$(O)music.o: music.c $(HACK_H) #interp.c +$(O)o_init.o: o_init.c $(HACK_H) $(INCL)\lev.h +$(O)objects.o: objects.c $(CONFIG_H) $(INCL)\obj.h $(INCL)\objclass.h \ + $(INCL)\prop.h $(INCL)\skills.h $(INCL)\color.h +$(O)objnam.o: objnam.c $(HACK_H) +$(O)options.o: options.c $(CONFIG_H) $(INCL)\objclass.h $(INCL)\flag.h \ + $(HACK_H) $(INCL)\tcap.h +$(O)pager.o: pager.c $(HACK_H) $(INCL)\dlb.h +$(O)pickup.o: pickup.c $(HACK_H) +$(O)pline.o: pline.c $(HACK_H) $(INCL)\epri.h $(INCL)\edog.h +$(O)polyself.o: polyself.c $(HACK_H) +$(O)potion.o: potion.c $(HACK_H) +$(O)pray.o: pray.c $(HACK_H) $(INCL)\epri.h +$(O)priest.o: priest.c $(HACK_H) $(INCL)\mfndpos.h $(INCL)\eshk.h \ + $(INCL)\epri.h $(INCL)\emin.h +$(O)quest.o: quest.c $(HACK_H) $(INCL)\qtext.h +$(O)questpgr.o: questpgr.c $(HACK_H) $(INCL)\dlb.h $(INCL)\qtext.h +$(O)read.o: read.c $(HACK_H) +$(O)rect.o: rect.c $(HACK_H) +$(O)region.o: region.c $(HACK_H) $(INCL)\lev.h +$(O)restore.o: restore.c $(HACK_H) $(INCL)\lev.h $(INCL)\tcap.h +$(O)rip.o: rip.c $(HACK_H) +$(O)rnd.o: rnd.c $(HACK_H) +$(O)role.o: role.c $(HACK_H) +$(O)rumors.o: rumors.c $(HACK_H) $(INCL)\lev.h $(INCL)\dlb.h +$(O)save.o: save.c $(HACK_H) $(INCL)\lev.h +$(O)shk.o: shk.c $(HACK_H) $(INCL)\eshk.h +$(O)shknam.o: shknam.c $(HACK_H) $(INCL)\eshk.h +$(O)sit.o: sit.c $(HACK_H) $(INCL)\artifact.h +$(O)sounds.o: sounds.c $(HACK_H) $(INCL)\edog.h +$(O)sp_lev.o: sp_lev.c $(HACK_H) $(INCL)\dlb.h $(INCL)\sp_lev.h +$(O)spell.o: spell.c $(HACK_H) +$(O)steal.o: steal.c $(HACK_H) +$(O)steed.o: steed.c $(HACK_H) +$(O)teleport.o: teleport.c $(HACK_H) +$(O)timeout.o: timeout.c $(HACK_H) $(INCL)\lev.h +$(O)topten.o: topten.c $(HACK_H) $(INCL)\dlb.h $(INCL)\patchlevel.h +$(O)track.o: track.c $(HACK_H) +$(O)trap.o: trap.c $(HACK_H) +$(O)u_init.o: u_init.c $(HACK_H) +$(O)uhitm.o: uhitm.c $(HACK_H) +$(O)vault.o: vault.c $(HACK_H) $(INCL)\vault.h +$(O)version.o: version.c $(HACK_H) $(INCL)\date.h $(INCL)\patchlevel.h +$(O)vision.o: vision.c $(HACK_H) $(INCL)\vis_tab.h +$(O)weapon.o: weapon.c $(HACK_H) +$(O)were.o: were.c $(HACK_H) +$(O)wield.o: wield.c $(HACK_H) +$(O)windows.o: windows.c $(HACK_H) $(INCL)\wingem.h $(INCL)\winGnome.h +$(O)wizard.o: wizard.c $(HACK_H) $(INCL)\qtext.h +$(O)worm.o: worm.c $(HACK_H) $(INCL)\lev.h +$(O)worn.o: worn.c $(HACK_H) +$(O)write.o: write.c $(HACK_H) +$(O)zap.o: zap.c $(HACK_H) + +# end of file + diff --git a/sys/winnt/Makefile.gcc b/sys/winnt/Makefile.gcc new file mode 100644 index 0000000..493d6b9 --- /dev/null +++ b/sys/winnt/Makefile.gcc @@ -0,0 +1,1309 @@ +# SCCS Id: @(#)Makefile.gcc 3.4 2002/02/04 +# Copyright (c) NetHack PC Development Team 1993-2002 +# +# NetHack 3.4.x Makefile for MinGW +# +# Win32 Compilers Tested: +# - gcc version 2.95.3-6 +# +# If you don't have this compiler, you can get it at: +# http://www.mingw.org/ +# +# This is used for building a TTY version of NetHack using +# WIN32 Console I/O only. +# +# In addition to your C compiler, +# +# if you want to change you will need a +# files with suffix workalike for +# .y yacc (such as bison) +# .l lex (such as flex) +# +# +# If you have any questions read the sys/winnt/Install.nt file included +# with the distribution. +# +# -- +# Dion Nicolaas +#============================================================================== +# Graphical interface +# Don't uncomment this line for 3.4.0 +# Set to Y for a graphical version +# Set to anything else (or undefine) for a tty version + +GRAPHICAL = N + +# Debug +# Set to Y for Debug support (to produce debug information) +# Set to anything else (or undefine) for a "release" version +# You can set your debug options below. + +DEBUG = Y + +cc = gcc +rc = windres +link = gcc + +cflags = +lflags = +ifeq "$(DEBUG)" "Y" +cdebug = -g +linkdebug = -g +else +cdebug = +linkdebug = +endif + +# +# Set the gamedir according to your preference. +# If not present prior to compilation it gets created. + +# Game Name +GAME = NetHack +# Game directory +GAMEDIR = ../binary + +# +# Source directories. Makedefs hardcodes these, don't change them. +# + +# NetHack include files +INCL = ../include +# NetHack data files +DAT = ../dat +# NetHack documentation files +DOC = ../doc +# Utility source +UTIL = ../util +# Main source +SRC = ../src +# Shared system files +SSYS = ../sys/share +# NT Win32 specific files +NTSYS = ../sys/winnt +# window port files (tty) +TTY = ../win/tty +# window port files (Win32) +WIN32 = ../win/win32 +# Tile support files +WSHR = ../win/share + +# +# Object directory. +# + +OBJ = o + + +# +#========================================== +# Exe File Info. +#========================================== + +# Yacc/Lex ... if you got 'em. +# +# If you have yacc and lex programs (or work-alike such as bison +# and flex), comment out the upper two macros and uncomment +# the lower two. +# + +DO_YACC = YACC_MSG +DO_LEX = LEX_MSG +#DO_YACC = YACC_ACT +#DO_LEX = LEX_ACT + +# - Specify your yacc and lex programs (or work-alikes) here. + +#YACC = bison -y +YACC = byacc +#YACC = yacc + +#LEX = lex +LEX = flex + +# +# - Specify your flex skeleton file (if needed). +# + +FLEXSKEL = +#FLEXSKEL = -S../tools/flex.ske + +YTABC = y_tab.c +YTABH = y_tab.h +LEXYYC = lexyy.c + +# +# Optional high-quality BSD random number generation routines +# (see pcconf.h). Set to nothing if not used. +# + +RANDOM = $(OBJ)/random.o +#RANDOM = + +#=============================================== +#======= End of Modification Section =========== +#=============================================== +################################################ +# # +# Nothing below here should have to be changed.# +# # +################################################ + +ifeq "$(GRAPHICAL)" "Y" +WINPORT = $(O)tile.o $(O)mhaskyn.o $(O)mhdlg.o \ + $(O)mhfont.o $(O)mhinput.o $(O)mhmain.o $(O)mhmap.o \ + $(O)mhmenu.o $(O)mhmsgwnd.o $(O)mhrip.o $(O)mhsplash.o \ + $(O)mhstatus.o $(O)mhtext.o $(O)mswproc.o $(O)winhack.o +# WIN32_IE=0x400 is currently unsupported by MinGW +WINPFLAG = -DTILES -DMSWIN_GRAPHICS -D_WIN32_IE=0x0400 +NHRES = $(O)winhack.o +WINPINC = -I$(WIN32) +WINPHDR = $(WIN32)/mhaskyn.h $(WIN32)/mhdlg.h $(WIN32)/mhfont.h \ + $(WIN32)/mhinput.h $(WIN32)/mhmain.h $(WIN32)/mhmap.h \ + $(WIN32)/mhmenu.h $(WIN32)/mhmsg.h $(WIN32)/mhmsgwnd.h \ + $(WIN32)/mhrip.h $(WIN32)/mhstatus.h \ + $(WIN32)/mhtext.h $(WIN32)/resource.h $(WIN32)/winMS.h +else +WINPORT = $(O)nttty.o +WINPFLAG= -DWIN32CON +WINPHDR = +NHRES = $(O)console.o +WINPINC = +endif + +TILEUTIL16 = $(UTIL)/tile2bmp.exe +TILEBMP16 = $(SRC)/tiles.bmp + +TILEUTIL32 = $(UTIL)/til2bm32.exe +TILEBMP32 = $(SRC)/tiles32.bmp + +# These should be left commented in 3.4.x +# + +#SOUND = $(OBJ)/ntsound.o +#SOUND = + +# To store all the level files, +# help files, etc. in a single library file. +# USE_DLB = Y is left uncommented + +USE_DLB = Y + +ifeq "$(USE_DLB)" "Y" +DLBFLG = -DDLB +else +DLBFLG = +endif + +#========================================== +# Setting up the compiler and linker +# macros. All builds include the base ones. +#========================================== + +CFLAGSBASE = -c $(cflags) -I$(INCL) $(WINPINC) $(cdebug) +LFLAGSBASEC = $(linkdebug) +LFLAGSBASEG = $(linkdebug) -mwindows + +#========================================== +# Util builds +#========================================== + +CFLAGSU = $(CFLAGSBASE) $(WINPFLAG) +LFLAGSU = $(LFLAGSBASEC) + +#========================================== +# - Game build +#========================================== + +CFLAGS = $(CFLAGSBASE) $(WINPFLAG) $(DLBFLG) +lflags = $(LFLAGSBASE) +ifeq "$(GRAPHICAL)" "Y" +lflags = $(LFLAGSBASEG) +else +lflags = $(LFLAGSBASEC) +endif + +GAMEFILE = $(GAMEDIR)/$(GAME).exe # whole thing + +ifeq "$(USE_DLB)" "Y" +DLB = nhdat +else +DLB = +endif + +#========================================== +#================ RULES ================== +#========================================== + +.SUFFIXES: .exe .o .til .uu .c .y .l + +#========================================== +# Rules for files in src +#========================================== + +$(OBJ)/%.o : /%.c + @$(cc) $(CFLAGS) -o$@ $< + +$(OBJ)/%.o : $(SRC)/%.c + @$(cc) $(CFLAGS) -o$@ $< + +#========================================== +# Rules for files in sys/share +#========================================== + +$(OBJ)/%.o : $(SSYS)/%.c + @$(cc) $(CFLAGS) -o$@ $< + +#========================================== +# Rules for files in sys/winnt +#========================================== + +$(OBJ)/%.o : $(NTSYS)/%.c + @$(cc) $(CFLAGS) -o$@ $< + +$(INCL)/%.h : $(NTSYS)/%.h + @copy $< $@ + +#========================================== +# Rules for files in util +#========================================== + +$(OBJ)/%.o : $(UTIL)/%.c + @$(cc) $(CFLAGSU) -o$@ $< + +#========================================== +# Rules for files in win/share +#========================================== + +$(OBJ)/%.o : $(WSHR)/%.c + @$(cc) $(CFLAGS) -o$@ $< + +$(INCL)/%.h : $(WSHR)/%.h + @copy $< $@ + +#{$(WSHR)}.txt{$(DAT)}.txt: +# @copy $< $@ + +#========================================== +# Rules for files in win/tty +#========================================== + +$(OBJ)/%.o : $(TTY)/%.c + @$(cc) $(CFLAGS) -o$@ $< + +#========================================== +# Rules for files in win/win32 +#========================================== + +$(OBJ)/%.o : $(WIN32)/%.c + @$(cc) $(CFLAGS) -o$@ $< + +#========================================== +#================ MACROS ================== +#========================================== +# This section creates shorthand macros for many objects +# referenced later on in the Makefile. +# + +DEFFILE = $(NTSYS)/$(GAME).def + +# +# Shorten up the location for some files +# + +O = $(OBJ)/ + +U = $(UTIL)/ + +# +# Utility Objects. +# + +MAKESRC = $(U)makedefs.c + +SPLEVSRC = $(U)lev_yacc.c $(U)lev_$(LEX).c $(U)lev_main.c $(U)panic.c + +DGNCOMPSRC = $(U)dgn_yacc.c $(U)dgn_$(LEX).c $(U)dgn_main.c + +MAKEOBJS = $(O)makedefs.o $(O)monst.o $(O)objects.o + +SPLEVOBJS = $(O)lev_yacc.o $(O)lev_$(LEX).o $(O)lev_main.o \ + $(O)alloc.o $(O)decl.o $(O)drawing.o \ + $(O)monst.o $(O)objects.o $(O)panic.o + +DGNCOMPOBJS = $(O)dgn_yacc.o $(O)dgn_$(LEX).o $(O)dgn_main.o \ + $(O)alloc.o $(O)panic.o + +RECOVOBJS = $(O)recover.o + +TILEFILES = $(WSHR)/monsters.txt $(WSHR)/objects.txt $(WSHR)/other.txt + +# +# These are not invoked during a normal game build in 3.4.0 +# +TEXT_IO = $(O)tiletext.o $(O)tiletxt.o $(O)drawing.o \ + $(O)decl.o $(O)monst.o $(O)objects.o + +TEXT_IO32 = $(O)tilete32.o $(O)tiletx32.o $(O)drawing.o \ + $(O)decl.o $(O)monst.o $(O)objects.o + +GIFREADERS = $(O)gifread.o $(O)alloc.o $(O)panic.o +GIFREADERS32 = $(O)gifrd32.o $(O)alloc.o $(O)panic.o + +PPMWRITERS = $(O)ppmwrite.o $(O)alloc.o $(O)panic.o + +# +# Object files for the game itself. +# + +VOBJ01 = $(O)allmain.o $(O)alloc.o $(O)apply.o $(O)artifact.o +VOBJ02 = $(O)attrib.o $(O)ball.o $(O)bones.o $(O)botl.o +VOBJ03 = $(O)cmd.o $(O)dbridge.o $(O)decl.o $(O)detect.o +VOBJ04 = $(O)dig.o $(O)display.o $(O)do.o $(O)do_name.o +VOBJ05 = $(O)do_wear.o $(O)dog.o $(O)dogmove.o $(O)dokick.o +VOBJ06 = $(O)dothrow.o $(O)drawing.o $(O)dungeon.o $(O)eat.o +VOBJ07 = $(O)end.o $(O)engrave.o $(O)exper.o $(O)explode.o +VOBJ08 = $(O)extralev.o $(O)files.o $(O)fountain.o $(O)hack.o +VOBJ09 = $(O)hacklib.o $(O)invent.o $(O)light.o $(O)lock.o +VOBJ10 = $(O)mail.o $(O)makemon.o $(O)mapglyph.o $(O)mcastu.o +VOBJ11 = $(O)mhitm.o $(O)mhitu.o $(O)minion.o $(O)mklev.o +VOBJ12 = $(O)mkmap.o $(O)mkmaze.o $(O)mkobj.o $(O)mkroom.o +VOBJ13 = $(O)mon.o $(O)mondata.o $(O)monmove.o $(O)monst.o +VOBJ14 = $(O)monstr.o $(O)mplayer.o $(O)mthrowu.o $(O)muse.o +VOBJ15 = $(O)music.o $(O)o_init.o $(O)objects.o $(O)objnam.o +VOBJ16 = $(O)options.o $(O)pager.o $(O)pickup.o $(O)pline.o +VOBJ17 = $(O)polyself.o $(O)potion.o $(O)pray.o $(O)priest.o +VOBJ18 = $(O)quest.o $(O)questpgr.o $(RANDOM) $(O)read.o +VOBJ19 = $(O)rect.o $(O)region.o $(O)restore.o $(O)rip.o +VOBJ20 = $(O)rnd.o $(O)role.o $(O)rumors.o $(O)save.o +VOBJ21 = $(O)shk.o $(O)shknam.o $(O)sit.o $(O)sounds.o +VOBJ22 = $(O)sp_lev.o $(O)spell.o $(O)steal.o $(O)steed.o +VOBJ23 = $(O)teleport.o $(O)timeout.o $(O)topten.o $(O)track.o +VOBJ24 = $(O)trap.o $(O)u_init.o $(O)uhitm.o $(O)vault.o +VOBJ25 = $(O)vis_tab.o $(O)vision.o $(O)weapon.o $(O)were.o +VOBJ26 = $(O)wield.o $(O)windows.o $(O)wizard.o $(O)worm.o +VOBJ27 = $(O)worn.o $(O)write.o $(O)zap.o + +DLBOBJ = $(O)dlb.o + +TTYOBJ = $(O)topl.o $(O)getline.o $(O)wintty.o + +SOBJ = $(O)winnt.o $(O)pcsys.o $(O)pcunix.o \ + $(SOUND) $(O)pcmain.o $(O)mapimail.o $(O)nhlan.o + +OBJS = $(VOBJ01) $(VOBJ02) $(VOBJ03) $(VOBJ04) $(VOBJ05) \ + $(VOBJ06) $(VOBJ07) $(VOBJ08) $(VOBJ09) $(VOBJ10) \ + $(VOBJ11) $(VOBJ12) $(VOBJ13) $(VOBJ14) $(VOBJ15) \ + $(VOBJ16) $(VOBJ17) $(VOBJ18) $(VOBJ19) $(VOBJ20) \ + $(VOBJ21) $(VOBJ22) $(VOBJ23) $(VOBJ24) $(VOBJ25) \ + $(VOBJ26) $(VOBJ27) + +WINPOBJ = $(WINPORT) + +VVOBJ = $(O)version.o + +ALLOBJ = $(WINPOBJ) $(SOBJ) $(DLBOBJ) $(TTYOBJ) $(WOBJ) $(OBJS) $(VVOBJ) + +ifeq "$(GRAPHICAL)" "Y" +OPTIONS_FILE = $(DAT)/guioptions +else +OPTIONS_FILE = $(DAT)/ttyoptions +endif + +#========================================== +# Header file macros +#========================================== + +CONFIG_H = $(INCL)/config.h $(INCL)/config1.h $(INCL)/tradstdc.h \ + $(INCL)/global.h $(INCL)/coord.h $(INCL)/vmsconf.h \ + $(INCL)/system.h $(INCL)/unixconf.h $(INCL)/os2conf.h \ + $(INCL)/micro.h $(INCL)/pcconf.h $(INCL)/tosconf.h \ + $(INCL)/amiconf.h $(INCL)/macconf.h $(INCL)/beconf.h \ + $(INCL)/ntconf.h $(INCL)/nhlan.h + +HACK_H = $(INCL)/hack.h $(CONFIG_H) $(INCL)/align.h \ + $(INCL)/dungeon.h $(INCL)/monsym.h $(INCL)/mkroom.h \ + $(INCL)/objclass.h $(INCL)/youprop.h $(INCL)/prop.h \ + $(INCL)/permonst.h $(INCL)/monattk.h \ + $(INCL)/monflag.h $(INCL)/mondata.h $(INCL)/pm.h \ + $(INCL)/wintype.h $(INCL)/decl.h $(INCL)/quest.h \ + $(INCL)/spell.h $(INCL)/color.h $(INCL)/obj.h \ + $(INCL)/you.h $(INCL)/attrib.h $(INCL)/monst.h \ + $(INCL)/skills.h $(INCL)/onames.h $(INCL)/timeout.h \ + $(INCL)/trap.h $(INCL)/flag.h $(INCL)/rm.h \ + $(INCL)/vision.h $(INCL)/display.h $(INCL)/engrave.h \ + $(INCL)/rect.h $(INCL)/region.h $(INCL)/winprocs.h \ + $(INCL)/wintty.h $(INCL)/trampoli.h + +LEV_H = $(INCL)/lev.h +DGN_FILE_H = $(INCL)/dgn_file.h +LEV_COMP_H = $(INCL)/lev_comp.h +SP_LEV_H = $(INCL)/sp_lev.h +TILE_H = ../win/share/tile.h + +#========================================== +# Miscellaneous +#========================================== + +DATABASE = $(DAT)/data.base + +# +# The name of the game. +# + +GAMEFILE = $(GAMEDIR)/$(GAME).exe + + +#========================================== +#=============== TARGETS ================== +#========================================== + +# Since DOS doesn't allow / as path separator, and GCC doesn't allow \ as +# path separator, we must change all pathnames when performing DOS commands. +# This is done by blindly applying $(subst /,\, ...) on every command. +# Where any command contain / for another reason (switch char, or echoing +# comment lines to lev/dungeon files) a little more care is taken. + +# +# The default make target (so just typing 'nmake' is useful). +# +default : $(GAMEFILE) + +# +# The main target. +# + +$(GAME) : $(O)obj.tag $(O)utility.tag graphicschk $(GAMEFILE) + @echo $(GAME) is up to date. + +# +# Everything +# + +all : install + +install: graphicschk $(GAME) $(O)install.tag + @echo Done. + + +$(O)install.tag: $(DAT)/data $(DAT)/rumors $(DAT)/dungeon \ + $(DAT)/oracles $(DAT)/quest.dat $(O)sp_lev.tag $(DLB) +ifeq "$(USE_DLB)" "Y" + $(subst /,\,copy nhdat $(GAMEDIR)) + $(subst /,\,copy $(DAT)/license $(GAMEDIR)) +else + $(subst /,\,copy $(DAT)/*. $(GAMEDIR)) + $(subst /,\,copy $(DAT)/*.dat $(GAMEDIR)) + $(subst /,\,copy $(DAT)/*.lev $(GAMEDIR)) + $(subst /,\,if exist $(GAMEDIR)/makefile del $(GAMEDIR)/makefile) +endif + $(subst /,\,if exist $(DOC)/guidebook.txt copy $(DOC)/guidebook.txt $(GAMEDIR)/Guidebook.txt) + $(subst /,\,if exist $(DOC)/nethack.txt copy $(DOC)/nethack.txt $(GAMEDIR)/NetHack.txt) + $(subst /,\,if exist $(DOC)/recover.txt copy $(DOC)/recover.txt $(GAMEDIR)/recover.txt) + $(subst /,\,@if exist $(SRC)/$(GAME).PDB copy $(SRC)/$(GAME).pdb $(GAMEDIR)/$(GAME).pdb) + $(subst /,\,@if exist $(GAMEDIR)/$(GAME).PDB echo NOTE: You may want to remove $(GAMEDIR)/$(GAME).pdb to conserve space) + $(subst /,\,-copy $(NTSYS)/defaults.nh $(GAMEDIR)/defaults.nh) + $(subst /,\,copy $(U)recover.exe $(GAMEDIR)) + $(subst /,\,echo install done > $@) + +# copy $(NTSYS)/winnt.hlp $(GAMEDIR) + +$(O)sp_lev.tag: $(O)utility.tag $(DAT)/bigroom.des $(DAT)/castle.des \ + $(DAT)/endgame.des $(DAT)/gehennom.des $(DAT)/knox.des \ + $(DAT)/medusa.des $(DAT)/oracle.des $(DAT)/tower.des \ + $(DAT)/yendor.des $(DAT)/arch.des $(DAT)/barb.des \ + $(DAT)/caveman.des $(DAT)/healer.des $(DAT)/knight.des \ + $(DAT)/monk.des $(DAT)/priest.des $(DAT)/ranger.des \ + $(DAT)/rogue.des $(DAT)/samurai.des $(DAT)/sokoban.des \ + $(DAT)/tourist.des $(DAT)/valkyrie.des $(DAT)/wizard.des + $(subst /,\,cd $(DAT)) & \ + $(subst /,\,$(U)lev_comp bigroom.des) & \ + $(subst /,\,$(U)lev_comp castle.des) & \ + $(subst /,\,$(U)lev_comp endgame.des) & \ + $(subst /,\,$(U)lev_comp gehennom.des) & \ + $(subst /,\,$(U)lev_comp knox.des) & \ + $(subst /,\,$(U)lev_comp mines.des) & \ + $(subst /,\,$(U)lev_comp medusa.des) & \ + $(subst /,\,$(U)lev_comp oracle.des) & \ + $(subst /,\,$(U)lev_comp sokoban.des) & \ + $(subst /,\,$(U)lev_comp tower.des) & \ + $(subst /,\,$(U)lev_comp yendor.des) & \ + $(subst /,\,$(U)lev_comp arch.des) & \ + $(subst /,\,$(U)lev_comp barb.des) & \ + $(subst /,\,$(U)lev_comp caveman.des) & \ + $(subst /,\,$(U)lev_comp healer.des) & \ + $(subst /,\,$(U)lev_comp knight.des) & \ + $(subst /,\,$(U)lev_comp monk.des) & \ + $(subst /,\,$(U)lev_comp priest.des) & \ + $(subst /,\,$(U)lev_comp ranger.des) & \ + $(subst /,\,$(U)lev_comp rogue.des) & \ + $(subst /,\,$(U)lev_comp samurai.des) & \ + $(subst /,\,$(U)lev_comp tourist.des) & \ + $(subst /,\,$(U)lev_comp valkyrie.des) & \ + $(subst /,\,$(U)lev_comp wizard.des) & \ + $(subst /,\,cd $(SRC)) + $(subst /,\,echo sp_levs done > $(O)sp_lev.tag) + +$(O)utility.tag: $(INCL)/date.h $(INCL)/onames.h $(INCL)/pm.h \ + $(SRC)/monstr.c $(SRC)/vis_tab.c \ + $(U)lev_comp.exe $(INCL)/vis_tab.h \ + $(U)dgn_comp.exe $(U)recover.exe $(TILEUTIL16) + $(subst /,\,@echo utilities made >$@) + @echo utilities made. + +tileutil: $(U)gif2txt.exe $(U)gif2tx32.exe $(U)txt2ppm.exe + @echo Optional tile development utilities are up to date. + +ifeq "$(GRAPHICAL)" "Y" +$(NHRES): $(TILEBMP16) $(WIN32)\winhack.rc $(WIN32)\mnsel.bmp \ + $(WIN32)\mnselcnt.bmp $(WIN32)\mnunsel.bmp \ + $(WIN32)\petmark.bmp $(WIN32)\NetHack.ico $(WIN32)\rip.bmp \ + $(WIN32)\splash.bmp + @$(rc) -o$@ --include-dir $(WIN32) -i $(WIN32)/winhack.rc +else +$(NHRES): $(NTSYS)/console.rc $(NTSYS)/NetHack.ico + @$(rc) -o$@ --include-dir $(NTSYS) -i $(NTSYS)/console.rc +endif + +#========================================== +# The main target. +#========================================== + +$(GAMEFILE) : $(ALLOBJ) $(NHRES) + @echo Linking.... + @$(link) $(lflags) -o$@ $(ALLOBJ) $(NHRES) + $(subst /,\,@if exist $(O)install.tag del $(O)install.tag) + +$(GAME)_.ico : $(NTSYS)/$(GAME).ico + $(subst /,\,@copy $(NTSYS)/$(GAME).ico $@) + +#========================================== +# Create directory for holding object files +#========================================== + +graphicschk: +ifeq "$(GRAPHICAL)" "Y" + @echo ---- + @echo NOTE: This build will include tile support. + @echo ---- +endif + $(subst /,\,@echo graphicschk > graphicschk) + +# +# Secondary Targets. +# + +#========================================== +# Makedefs Stuff +#========================================== + +$(U)makedefs.exe: $(MAKEOBJS) + @$(link) $(LFLAGSU) -o$@ $(MAKEOBJS) + +$(O)makedefs.o: $(CONFIG_H) $(INCL)/monattk.h $(INCL)/monflag.h $(INCL)/objclass.h \ + $(INCL)/monsym.h $(INCL)/qtext.h $(INCL)/patchlevel.h \ + $(U)makedefs.c + $(subst /,\,@if not exist $(O)*.* mkdir $(OBJ)) + @$(cc) $(CFLAGSU) -o$@ $(U)makedefs.c + +# +# date.h should be remade every time any of the source or include +# files is modified. +# + +$(INCL)/date.h $(OPTIONS_FILE): $(U)makedefs.exe + $(subst /,\,$(U)makedefs -v) + +#$(OPTIONS_FILE): $(U)makedefs.exe +# $(subst /,\,$(U)makedefs -v) + +$(INCL)/onames.h : $(U)makedefs.exe + $(subst /,\,$(U)makedefs -o) + +$(INCL)/pm.h : $(U)makedefs.exe + $(subst /,\,$(U)makedefs -p) + +#$(INCL)/trap.h : $(U)makedefs.exe +# $(U)makedefs -t + +$(SRC)/monstr.c: $(U)makedefs.exe + $(subst /,\,$(U)makedefs -m) + +$(INCL)/vis_tab.h: $(U)makedefs.exe + $(subst /,\,$(U)makedefs -z) + +$(SRC)/vis_tab.c: $(U)makedefs.exe + $(subst /,\,$(U)makedefs -z) + +#========================================== +# uudecode utility and uuencoded targets +#========================================== + +$(U)uudecode.exe: $(O)uudecode.o + @$(link) $(LFLAGSU) -o$@ $(O)uudecode.o + +$(O)uudecode.o: $(SSYS)/uudecode.c + +$(NTSYS)/NetHack.ico : $(U)uudecode.exe $(NTSYS)/nhico.uu + $(subst /,\,chdir $(NTSYS)) & \ + $(subst /,\,uudecode.exe nhico.uu) & \ + $(subst /,\,chdir ..\..\src) + +$(WIN32)/NetHack.ico : $(U)uudecode.exe $(NTSYS)/nhico.uu + $(subst /,\,chdir $(WIN32)) & \ + $(subst /,\,..\..\util\uudecode.exe ../../sys/winnt/nhico.uu) & \ + $(subst /,\,chdir ..\..\src) + +$(WIN32)/mnsel.bmp: $(U)uudecode.exe $(WIN32)/mnsel.uu + $(subst /,\,chdir $(WIN32)) & \ + $(subst /,\,..\..\util\uudecode.exe mnsel.uu) & \ + $(subst /,\,chdir ..\..\src) + +$(WIN32)/mnselcnt.bmp: $(U)uudecode.exe $(WIN32)/mnselcnt.uu + $(subst /,\,chdir $(WIN32)) & \ + $(subst /,\,..\..\util\uudecode.exe mnselcnt.uu) & \ + $(subst /,\,chdir ..\..\src) + +$(WIN32)/mnunsel.bmp: $(U)uudecode.exe $(WIN32)/mnunsel.uu + $(subst /,\,chdir $(WIN32)) & \ + $(subst /,\,..\..\util\uudecode.exe mnunsel.uu) & \ + $(subst /,\,chdir ..\..\src) + +$(WIN32)/petmark.bmp: $(U)uudecode.exe $(WIN32)/petmark.uu + $(subst /,\,chdir $(WIN32)) & \ + $(subst /,\,..\..\util\uudecode.exe petmark.uu) & \ + $(subst /,\,chdir ..\..\src) + +$(WIN32)/rip.bmp: $(U)uudecode.exe $(WIN32)/rip.uu + $(subst /,\,chdir $(WIN32)) & \ + $(subst /,\,..\..\util\uudecode.exe rip.uu) & \ + $(subst /,\,chdir ..\..\src) + +$(WIN32)/splash.bmp: $(U)uudecode.exe $(WIN32)/splash.uu + $(subst /,\,chdir $(WIN32)) & \ + $(subst /,\,..\..\util\uudecode.exe splash.uu) & \ + $(subst /,\,chdir ..\..\src) + + +#========================================== +# Level Compiler Stuff +#========================================== + +LEVCFLAGS=$(cflags) -c -DWIN32 -D_WIN32 -I../include $(cdebug) -DDLB + +$(U)lev_comp.exe: $(SPLEVOBJS) + @echo Linking $@... + @$(link) $(LFLAGSU) -o$@ $(SPLEVOBJS) + +$(O)lev_yacc.o: $(HACK_H) $(SP_LEV_H) $(INCL)/lev_comp.h $(U)lev_yacc.c + @$(cc) $(LEVCFLAGS) -o$@ $(U)lev_yacc.c + +$(O)lev_$(LEX).o: $(HACK_H) $(INCL)/lev_comp.h $(SP_LEV_H) \ + $(U)lev_$(LEX).c + @$(cc) $(LEVCFLAGS) -o$@ $(U)lev_$(LEX).c + +$(O)lev_main.o: $(U)lev_main.c $(HACK_H) $(SP_LEV_H) + @$(cc) $(LEVCFLAGS) -o$@ $(U)lev_main.c + + +$(U)lev_yacc.c $(INCL)/lev_comp.h : $(U)lev_comp.y +ifeq "$(DO_YACC)" "YACC_ACT" + $(subst /,\,chdir $(UTIL)) & \ + $(subst /,\,$(YACC) -d lev_comp.y) & \ + $(subst /,\,copy $(YTABC) lev_yacc.c) & \ + $(subst /,\,copy $(YTABH) $(INCL)/lev_comp.h) & \ + $(subst /,\,@del $(YTABC)) & \ + $(subst /,\,@del $(YTABH)) & \ + $(subst /,\,chdir $(SRC)) +else + @echo $(U)lev_comp.y has changed. + @echo To update $(U)lev_yacc.c and $(INCL)/lev_comp.h run $(YACC). + @echo --- + @echo For now, we will copy the prebuilt lev_yacc.c and + @echo lev_comp.h from $(SSYS) into $(UTIL) and use them. + $(subst /,\,@copy $(SSYS)/lev_yacc.c $(U)lev_yacc.c >nul) + $(subst /,\,@copy $(SSYS)/lev_comp.h $(INCL)/lev_comp.h >nul) + @echo /**/ $(subst /,\,>>$(U)lev_yacc.c) + @echo /**/ $(subst /,\,>>$(INCL)/lev_comp.h) +endif + +$(U)lev_$(LEX).c: $(U)lev_comp.l +ifeq "$(DO_LEX)" "LEX_ACT" + $(subst /,\,chdir $(UTIL)) & \ + $(subst /,\,$(LEX) $(FLEXSKEL) lev_comp.l) & \ + $(subst /,\,copy $(LEXYYC) $@) & \ + $(subst /,\,@del $(LEXYYC)) & \ + $(subst /,\,chdir $(SRC)) +else + @echo $(U)lev_comp.l has changed. To update $@ run $(LEX). + @echo --- + @echo For now, we will copy the prebuilt lev_lex.c + @echo from $(SSYS) into $(UTIL) and use it. + $(subst /,\,@copy $(SSYS)/lev_lex.c $@ >nul) + @echo /**/ $(subst /,\,>>$@) +endif + +#========================================== +# Dungeon Compiler Stuff +#========================================== + +$(U)dgn_comp.exe: $(DGNCOMPOBJS) + @echo Linking $@... + @$(link) $(LFLAGSU) -o$@ $(DGNCOMPOBJS) + + +$(O)dgn_yacc.o: $(HACK_H) $(DGN_FILE_H) $(INCL)/dgn_comp.h $(U)dgn_yacc.c + @$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_yacc.c + +$(O)dgn_$(LEX).o: $(HACK_H) $(DGN_FILE_H) $(INCL)/dgn_comp.h \ + $(U)dgn_$(LEX).c + @$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_$(LEX).c + +$(O)dgn_main.o: $(HACK_H) $(U)dgn_main.c + @$(cc) $(LEVCFLAGS) -o$@ $(U)dgn_main.c + +$(U)dgn_yacc.c $(INCL)/dgn_comp.h : $(U)dgn_comp.y +ifeq "$(DO_YACC)" "YACC_ACT" + $(subst /,\,chdir $(UTIL)) & \ + $(subst /,\,$(YACC) -d dgn_comp.y) & \ + $(subst /,\,copy $(YTABC) dgn_yacc.c) & \ + $(subst /,\,copy $(YTABH) $(INCL)/dgn_comp.h) & \ + $(subst /,\,@del $(YTABC)) & \ + $(subst /,\,@del $(YTABH)) & \ + $(subst /,\,chdir $(SRC)) +else + @echo $(U)dgn_comp.y has changed. To update dgn_yacc.c and + @echo $(INCL)/dgn_comp.h run $(YACC). + @echo --- + @echo For now, we will copy the prebuilt $(U)dgn_yacc.c and + @echo dgn_comp.h from $(SSYS) into $(UTIL) and use them. + $(subst /,\,@copy $(SSYS)/dgn_yacc.c $(U)dgn_yacc.c >nul) + $(subst /,\,@copy $(SSYS)/dgn_comp.h $(INCL)/dgn_comp.h >nul) + @echo /**/ $(subst /,\,>>$(U)dgn_yacc.c) + @echo /**/ $(subst /,\,>>$(INCL)/dgn_comp.h) +endif + +$(U)dgn_$(LEX).c: $(U)dgn_comp.l +ifeq "$(DO_LEX)" "LEX_ACT" + $(subst /,\,chdir $(UTIL)) & \ + $(subst /,\,$(LEX) $(FLEXSKEL) dgn_comp.l) & \ + $(subst /,\,copy $(LEXYYC) $@) & \ + $(subst /,\,@del $(LEXYYC)) & \ + chdir $(SRC) +else + @echo $(U)dgn_comp.l has changed. To update $@ run $(LEX). + @echo --- + @echo For now, we will copy the prebuilt dgn_lex.c + @echo from $(SSYS) into $(UTIL) and use it. + $(subst /,\,@copy $(SSYS)/dgn_lex.c $@ >nul) + @echo /**/ $(subst /,\,>>$@) +endif + +#========================================== +# Create directory for holding object files +#========================================== + +$(O)obj.tag: + $(subst /,\,@if not exist $(OBJ)/*.* echo creating directory $(OBJ)) + $(subst /,\,@if not exist $(OBJ)/*.* mkdir $(OBJ)) + $(subst /,\,@echo directory created > $@) + + +#========================================== +#=========== SECONDARY TARGETS ============ +#========================================== + +#=========================================== +# Header files NOT distributed in ../include +#=========================================== + +$(INCL)/win32api.h: $(NTSYS)/win32api.h + $(subst /,\,copy $(NTSYS)/win32api.h $@) + + +#========================================== +# DLB utility and nhdat file creation +#========================================== + +$(U)dlb_main.exe: $(DLBOBJ) $(O)dlb.o + @$(link) $(LFLAGSU) -o$@ $(O)dlb_main.o $(O)dlb.o $(O)alloc.o $(O)panic.o + + +$(O)dlb.o: $(O)dlb_main.o $(O)alloc.o $(O)panic.o $(INCL)/dlb.h + @$(cc) $(CFLAGS) -o$@ $(SRC)/dlb.c + +$(O)dlb_main.o: $(UTIL)/dlb_main.c $(INCL)/config.h $(INCL)/dlb.h + @$(cc) $(CFLAGS) -o$@ $(UTIL)/dlb_main.c + +$(DAT)/porthelp: $(NTSYS)/porthelp + $(subst /,\,@copy $(NTSYS)/porthelp $@ >nul) + +nhdat: $(U)dlb_main.exe $(DAT)/data $(DAT)/oracles $(OPTIONS_FILE) \ + $(DAT)/quest.dat $(DAT)/rumors $(DAT)/help $(DAT)/hh $(DAT)/cmdhelp \ + $(DAT)/history $(DAT)/opthelp $(DAT)/wizhelp $(DAT)/dungeon $(DAT)/porthelp \ + $(DAT)/license $(O)sp_lev.tag + $(subst /,\,cd $(DAT)) & \ + echo data >dlb.lst & \ + echo oracles >>dlb.lst & \ + (if exist options echo options >>dlb.lst) & \ + (if exist ttyoptions echo ttyoptions >>dlb.lst) & \ + (if exist guioptions echo guioptions >>dlb.lst) & \ + (if exist porthelp echo porthelp >>dlb.lst) & \ + echo quest.dat >>dlb.lst & \ + echo rumors >>dlb.lst & \ + echo help >>dlb.lst & \ + echo hh >>dlb.lst & \ + echo cmdhelp >>dlb.lst & \ + echo history >>dlb.lst & \ + echo opthelp >>dlb.lst & \ + echo wizhelp >>dlb.lst & \ + echo dungeon >>dlb.lst & \ + echo license >>dlb.lst & \ + (for %%N in (*.lev) do echo %%N >>dlb.lst) & \ + $(subst /,\,$(U)dlb_main cIf dlb.lst $(SRC)/nhdat) & \ + $(subst /,\,cd $(SRC)) + +#========================================== +# Recover Utility +#========================================== + +$(U)recover.exe: $(RECOVOBJS) + @$(link) $(LFLAGSU) -o$@ $(RECOVOBJS) + + +$(O)recover.o: $(CONFIG_H) $(U)recover.c $(INCL)/win32api.h + @$(cc) $(CFLAGSU) -o$@ $(U)recover.c + +#========================================== +# Tile Mapping +#========================================== + +$(SRC)/tile.c: $(U)tilemap.exe + @echo A new $@ has been created + @$(U)tilemap + +$(U)tilemap.exe: $(O)tilemap.o + @$(link) $(LFLAGSU) -o$@ $(O)tilemap.o + +$(O)tilemap.o: $(WSHR)/tilemap.c $(HACK_H) + @$(cc) $(CFLAGSU) -o$@ $(WSHR)/tilemap.c + +$(O)tiletx32.o: $(WSHR)/tilemap.c $(HACK_H) + @$(CC) $(CFLAGS) -DTILETEXT -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)\tilemap.c + +$(O)tiletxt.o: $(WSHR)/tilemap.c $(HACK_H) + @$(cc) $(CFLAGS) -DTILETEXT -o$@ $(WSHR)/tilemap.c + +$(O)gifread.o: $(WSHR)/gifread.c $(CONFIG_H) $(TILE_H) + @$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/gifread.c + +$(O)gifrd32.o: $(WSHR)/gifread.c $(CONFIG_H) $(TILE_H) + @$(CC) $(CFLAGS) -I$(WSHR) -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/gifread.c + +$(O)ppmwrite.o: $(WSHR)/ppmwrite.c $(CONFIG_H) $(TILE_H) + @$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/ppmwrite.c + +$(O)tiletext.o: $(WSHR)/tiletext.c $(CONFIG_H) $(TILE_H) + @$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/tiletext.c + +$(O)tilete32.o: $(WSHR)/tiletext.c $(CONFIG_H) $(TILE_H) + @$(CC) $(CFLAGS) -I$(WSHR) -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/tiletext.c + +#========================================== +# Optional Tile Utilities +#========================================== + +$(U)gif2txt.exe: $(GIFREADERS) $(TEXT_IO) + @echo Linking $@... + @$(link) $(LFLAGSU) -o$@ $(GIFREADERS) $(TEXT_IO) + +$(U)gif2tx32.exe: $(GIFREADERS32) $(TEXT_IO32) + @echo Linking $@... + @$(link) $(LFLAGSU) -o$@ $(GIFREADERS32) $(TEXT_IO32) + + +$(U)txt2ppm.exe: $(PPMWRITERS) $(TEXT_IO) + @echo Linking $@... + @$(link) $(LFLAGSU) -o$@ $(PPMWRITERS) $(TEXT_IO) + + +ifeq "$(GRAPHICAL)" "Y" +$(TILEBMP16): $(TILEUTIL16) $(TILEFILES) + @echo Creating 16x16 binary tile files (this may take some time) + $(subst /,\,@$(U)tile2bmp $(TILEBMP16)) +#$(TILEBMP32): $(TILEUTIL32) $(TILEFILES32) +# @echo Creating 32x32 binary tile files (this may take some time) +# $(subst /,\,@$(U)til2bm32 $(TILEBMP32)) +else +$(TILEBMP16): +$(TILEBMP32): +endif + +$(U)tile2bmp.exe: $(O)tile2bmp.o $(TEXT_IO) + @echo Linking $@... + @$(link) $(LFLAGSU) -o$@ $(O)tile2bmp.o $(TEXT_IO) + +$(U)til2bm32.exe: $(O)til2bm32.o $(TEXT_IO32) + @echo Linking $@... + @$(link) $(LFLAGSU) -o$@ $(O)til2bm32.o $(TEXT_IO32) + +$(O)tile2bmp.o: $(WSHR)/tile2bmp.c $(HACK_H) $(TILE_H) $(INCL)/win32api.h + @$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(WSHR)/tile2bmp.c + +$(O)til2bm32.o: $(WSHR)/til2bm32.c $(HACK_H) $(TILE_H) $(INCL)/win32api.h + @$(cc) $(CFLAGS) -I$(WSHR) -DTILE_X=32 -DTILE_Y=32 -o$@ $(WSHR)/til2bm32.c + +#========================================== +# Housekeeping +#========================================== + +spotless: clean +ifneq "$(OBJ)" "" + -rmdir $(OBJ) /s /Q +endif + $(subst /,\,if exist graphicschk del graphicschk) + $(subst /,\,if exist $(INCL)/date.h del $(INCL)/date.h) + $(subst /,\,if exist $(INCL)/onames.h del $(INCL)/onames.h) + $(subst /,\,if exist $(INCL)/pm.h del $(INCL)/pm.h) + $(subst /,\,if exist $(INCL)/vis_tab.h del $(INCL)/vis_tab.h) + $(subst /,\,if exist $(SRC)/vis_tab.c del $(SRC)/vis_tab.c) + $(subst /,\,if exist $(SRC)/tile.c del $(SRC)/tile.c) + $(subst /,\,if exist $(U)*.lnk del $(U)*.lnk) + $(subst /,\,if exist $(U)*.map del $(U)*.map) + $(subst /,\,if exist $(DAT)/data del $(DAT)/data) + $(subst /,\,if exist $(DAT)/rumors del $(DAT)/rumors) + $(subst /,\,if exist $(DAT)/???-fil?.lev del $(DAT)/???-fil?.lev) + $(subst /,\,if exist $(DAT)/???-goal.lev del $(DAT)/???-goal.lev) + $(subst /,\,if exist $(DAT)/???-loca.lev del $(DAT)/???-loca.lev) + $(subst /,\,if exist $(DAT)/???-strt.lev del $(DAT)/???-strt.lev) + $(subst /,\,if exist $(DAT)/air.lev del $(DAT)/air.lev) + $(subst /,\,if exist $(DAT)/asmodeus.lev del $(DAT)/asmodeus.lev) + $(subst /,\,if exist $(DAT)/astral.lev del $(DAT)/astral.lev) + $(subst /,\,if exist $(DAT)/baalz.lev del $(DAT)/baalz.lev) + $(subst /,\,if exist $(DAT)/bigrm-*.lev del $(DAT)/bigrm-*.lev) + $(subst /,\,if exist $(DAT)/castle.lev del $(DAT)/castle.lev) + $(subst /,\,if exist $(DAT)/data del $(DAT)/data) + $(subst /,\,if exist $(DAT)/dungeon del $(DAT)/dungeon) + $(subst /,\,if exist $(DAT)/dungeon.pdf del $(DAT)/dungeon.pdf) + $(subst /,\,if exist $(DAT)/earth.lev del $(DAT)/earth.lev) + $(subst /,\,if exist $(DAT)/fakewiz?.lev del $(DAT)/fakewiz?.lev) + $(subst /,\,if exist $(DAT)/fire.lev del $(DAT)/fire.lev) + $(subst /,\,if exist $(DAT)/juiblex.lev del $(DAT)/juiblex.lev) + $(subst /,\,if exist $(DAT)/knox.lev del $(DAT)/knox.lev) + $(subst /,\,if exist $(DAT)/medusa-?.lev del $(DAT)/medusa-?.lev) + $(subst /,\,if exist $(DAT)/mine*.lev del $(DAT)/mine*.lev) + $(subst /,\,if exist $(DAT)/options del $(DAT)/options) + $(subst /,\,if exist $(DAT)/ttyoptions del $(DAT)/ttyoptions) + $(subst /,\,if exist $(DAT)/guioptions del $(DAT)/guioptions) + $(subst /,\,if exist $(DAT)/oracle.lev del $(DAT)/oracle.lev) + $(subst /,\,if exist $(DAT)/oracles del $(DAT)/oracles) + $(subst /,\,if exist $(DAT)/orcus.lev del $(DAT)/orcus.lev) + $(subst /,\,if exist $(DAT)/rumors del $(DAT)/rumors) + $(subst /,\,if exist $(DAT)/quest.dat del $(DAT)/quest.dat) + $(subst /,\,if exist $(DAT)/sanctum.lev del $(DAT)/sanctum.lev) + $(subst /,\,if exist $(DAT)/soko?-?.lev del $(DAT)/soko?-?.lev) + $(subst /,\,if exist $(DAT)/tower?.lev del $(DAT)/tower?.lev) + $(subst /,\,if exist $(DAT)/valley.lev del $(DAT)/valley.lev) + $(subst /,\,if exist $(DAT)/water.lev del $(DAT)/water.lev) + $(subst /,\,if exist $(DAT)/wizard?.lev del $(DAT)/wizard?.lev) + $(subst /,\,if exist $(O)sp_lev.tag del $(O)sp_lev.tag) + $(subst /,\,if exist $(SRC)/monstr.c del $(SRC)/monstr.c) + $(subst /,\,if exist $(SRC)/vis_tab.c del $(SRC)/vis_tab.c) + $(subst /,\,if exist $(U)recover.exe del $(U)recover.exe) + $(subst /,\,if exist $(DAT)/dlb.lst del $(DAT)/dlb.lst) + $(subst /,\,if exist nhdat. del nhdat.) + +clean: + $(subst /,\,if exist $(O)*.o del $(O)*.o) + $(subst /,\,if exist $(O)utility.tag del $(O)utility.tag) + $(subst /,\,if exist $(U)makedefs.exe del $(U)makedefs.exe) + $(subst /,\,if exist $(U)lev_comp.exe del $(U)lev_comp.exe) + $(subst /,\,if exist $(U)dgn_comp.exe del $(U)dgn_comp.exe) + $(subst /,\,if exist $(SRC)/*.lnk del $(SRC)/*.lnk) + $(subst /,\,if exist $(SRC)/*.map del $(SRC)/*.map) + $(subst /,\,if exist $(TILEBMP16) del $(TILEBMP16)) + $(subst /,\,if exist $(TILEBMP32) del $(TILEBMP32)) + +#=================================================================== +# OTHER DEPENDENCIES +#=================================================================== + +# +# dat dependencies +# + +$(DAT)/data: $(O)utility.tag $(DATABASE) + $(subst /,\,$(U)makedefs -d) + +$(DAT)/rumors: $(O)utility.tag $(DAT)/rumors.tru $(DAT)/rumors.fal + $(subst /,\,$(U)makedefs -r) + +$(DAT)/quest.dat: $(O)utility.tag $(DAT)/quest.txt + $(subst /,\,$(U)makedefs -q) + +$(DAT)/oracles: $(O)utility.tag $(DAT)/oracles.txt + $(subst /,\,$(U)makedefs -h) + +$(DAT)/dungeon: $(O)utility.tag $(DAT)/dungeon.def + $(subst /,\,$(U)makedefs -e) + $(subst /,\,cd $(DAT)) & \ + $(subst /,\,$(U)dgn_comp dungeon.pdf) & \ + $(subst /,\,cd $(SRC)) + +# +# NT dependencies +# + +$(O)nttty.o: $(HACK_H) $(TILE_H) $(INCL)/win32api.h $(NTSYS)/nttty.c + @$(cc) $(CFLAGS) -I$(WSHR) -o$@ $(NTSYS)/nttty.c +$(O)winnt.o: $(HACK_H) $(INCL)/win32api.h $(NTSYS)/winnt.c + @$(cc) $(CFLAGS) -o$@ $(NTSYS)/winnt.c +$(O)ntsound.o: $(HACK_H) $(NTSYS)/ntsound.c + @$(cc) $(CFLAGS) -o$@ $(NTSYS)/ntsound.c +$(O)mapimail.o: $(HACK_H) $(INCL)/nhlan.h $(NTSYS)/mapimail.c + @$(cc) $(CFLAGS) -DMAPI_VERBOSE -o$@ $(NTSYS)/mapimail.c + +# +# util dependencies +# + +$(O)panic.o: $(U)panic.c $(CONFIG_H) + @$(cc) $(CFLAGS) -o$@ $(U)panic.c + +# +# The rest are stolen from sys/unix/Makefile.src, +# and -c (which is included in CFLAGS) substituted +# with -o$@ , but otherwise untouched. That +# means that there is some irrelevant stuff +# in here, but maintenance should be easier. +# +$(O)tos.o: ../sys/atari/tos.c $(HACK_H) $(INCL)/tcap.h + $(cc) $(CFLAGS) -o$@ ../sys/atari/tos.c +$(O)pcmain.o: ../sys/share/pcmain.c $(HACK_H) $(INCL)/dlb.h \ + $(INCL)/win32api.h + $(cc) $(CFLAGS) -o$@ ../sys/share/pcmain.c +$(O)pcsys.o: ../sys/share/pcsys.c $(HACK_H) + $(cc) $(CFLAGS) -o$@ ../sys/share/pcsys.c +$(O)pctty.o: ../sys/share/pctty.c $(HACK_H) + $(cc) $(CFLAGS) -o$@ ../sys/share/pctty.c +$(O)pcunix.o: ../sys/share/pcunix.c $(HACK_H) + $(cc) $(CFLAGS) -o$@ ../sys/share/pcunix.c +$(O)random.o: ../sys/share/random.c $(HACK_H) + $(cc) $(CFLAGS) -o$@ ../sys/share/random.c +$(O)ioctl.o: ../sys/share/ioctl.c $(HACK_H) $(INCL)/tcap.h + $(cc) $(CFLAGS) -o$@ ../sys/share/ioctl.c +$(O)unixtty.o: ../sys/share/unixtty.c $(HACK_H) + $(cc) $(CFLAGS) -o$@ ../sys/share/unixtty.c +$(O)unixmain.o: ../sys/unix/unixmain.c $(HACK_H) $(INCL)/dlb.h + $(cc) $(CFLAGS) -o$@ ../sys/unix/unixmain.c +$(O)unixunix.o: ../sys/unix/unixunix.c $(HACK_H) + $(cc) $(CFLAGS) -o$@ ../sys/unix/unixunix.c +$(O)bemain.o: ../sys/be/bemain.c $(HACK_H) $(INCL)/dlb.h + $(cc) $(CFLAGS) -o$@ ../sys/be/bemain.c +$(O)getline.o: ../win/tty/getline.c $(HACK_H) $(INCL)/func_tab.h + $(cc) $(CFLAGS) -o$@ ../win/tty/getline.c +$(O)termcap.o: ../win/tty/termcap.c $(HACK_H) $(INCL)/tcap.h + $(cc) $(CFLAGS) -o$@ ../win/tty/termcap.c +$(O)topl.o: ../win/tty/topl.c $(HACK_H) $(INCL)/tcap.h + $(cc) $(CFLAGS) -o$@ ../win/tty/topl.c +$(O)wintty.o: ../win/tty/wintty.c $(HACK_H) $(INCL)/dlb.h \ + $(INCL)/patchlevel.h $(INCL)/tcap.h + $(cc) $(CFLAGS) -o$@ ../win/tty/wintty.c +$(O)Window.o: ../win/X11/Window.c $(INCL)/xwindowp.h $(INCL)/xwindow.h \ + $(CONFIG_H) + $(cc) $(CFLAGS) -o$@ ../win/X11/Window.c +$(O)dialogs.o: ../win/X11/dialogs.c $(CONFIG_H) + $(cc) $(CFLAGS) -o$@ ../win/X11/dialogs.c +$(O)winX.o: ../win/X11/winX.c $(HACK_H) $(INCL)/winX.h $(INCL)/dlb.h \ + $(INCL)/patchlevel.h ../win/X11/nh72icon \ + ../win/X11/nh56icon ../win/X11/nh32icon + $(cc) $(CFLAGS) -o$@ ../win/X11/winX.c +$(O)winmap.o: ../win/X11/winmap.c $(INCL)/xwindow.h $(HACK_H) $(INCL)/dlb.h \ + $(INCL)/winX.h $(INCL)/tile2x11.h + $(cc) $(CFLAGS) -o$@ ../win/X11/winmap.c +$(O)winmenu.o: ../win/X11/winmenu.c $(HACK_H) $(INCL)/winX.h + $(cc) $(CFLAGS) -o$@ ../win/X11/winmenu.c +$(O)winmesg.o: ../win/X11/winmesg.c $(INCL)/xwindow.h $(HACK_H) $(INCL)/winX.h + $(cc) $(CFLAGS) -o$@ ../win/X11/winmesg.c +$(O)winmisc.o: ../win/X11/winmisc.c $(HACK_H) $(INCL)/func_tab.h \ + $(INCL)/winX.h + $(cc) $(CFLAGS) -o$@ ../win/X11/winmisc.c +$(O)winstat.o: ../win/X11/winstat.c $(HACK_H) $(INCL)/winX.h + $(cc) $(CFLAGS) -o$@ ../win/X11/winstat.c +$(O)wintext.o: ../win/X11/wintext.c $(HACK_H) $(INCL)/winX.h $(INCL)/xwindow.h + $(cc) $(CFLAGS) -o$@ ../win/X11/wintext.c +$(O)winval.o: ../win/X11/winval.c $(HACK_H) $(INCL)/winX.h + $(cc) $(CFLAGS) -o$@ ../win/X11/winval.c +$(O)tile.o: $(SRC)/tile.c $(HACK_H) +$(O)gnaskstr.o: ../win/gnome/gnaskstr.c ../win/gnome/gnaskstr.h \ + ../win/gnome/gnmain.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnaskstr.c +$(O)gnbind.o: ../win/gnome/gnbind.c ../win/gnome/gnbind.h ../win/gnome/gnmain.h \ + ../win/gnome/gnaskstr.h ../win/gnome/gnyesno.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnbind.c +$(O)gnglyph.o: ../win/gnome/gnglyph.c ../win/gnome/gnglyph.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnglyph.c +$(O)gnmain.o: ../win/gnome/gnmain.c ../win/gnome/gnmain.h ../win/gnome/gnsignal.h \ + ../win/gnome/gnbind.h ../win/gnome/gnopts.h $(HACK_H) \ + $(INCL)/date.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnmain.c +$(O)gnmap.o: ../win/gnome/gnmap.c ../win/gnome/gnmap.h ../win/gnome/gnglyph.h \ + ../win/gnome/gnsignal.h $(HACK_H) + $(cc) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnmap.c +$(O)gnmenu.o: ../win/gnome/gnmenu.c ../win/gnome/gnmenu.h ../win/gnome/gnmain.h \ + ../win/gnome/gnbind.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnmenu.c +$(O)gnmesg.o: ../win/gnome/gnmesg.c ../win/gnome/gnmesg.h ../win/gnome/gnsignal.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnmesg.c +$(O)gnopts.o: ../win/gnome/gnopts.c ../win/gnome/gnopts.h ../win/gnome/gnglyph.h \ + ../win/gnome/gnmain.h ../win/gnome/gnmap.h $(HACK_H) + $(cc) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnopts.c +$(O)gnplayer.o: ../win/gnome/gnplayer.c ../win/gnome/gnplayer.h \ + ../win/gnome/gnmain.h $(HACK_H) + $(cc) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnplayer.c +$(O)gnsignal.o: ../win/gnome/gnsignal.c ../win/gnome/gnsignal.h \ + ../win/gnome/gnmain.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnsignal.c +$(O)gnstatus.o: ../win/gnome/gnstatus.c ../win/gnome/gnstatus.h \ + ../win/gnome/gnsignal.h ../win/gnome/gn_xpms.h \ + ../win/gnome/gnomeprv.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnstatus.c +$(O)gntext.o: ../win/gnome/gntext.c ../win/gnome/gntext.h ../win/gnome/gnmain.h \ + ../win/gnome/gn_rip.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gntext.c +$(O)gnyesno.o: ../win/gnome/gnyesno.c ../win/gnome/gnbind.h ../win/gnome/gnyesno.h + $(cc) $(CFLAGS) $(GNOMEINC) -c ../win/gnome/gnyesno.c +$(O)wingem.o: ../win/gem/wingem.c $(HACK_H) $(INCL)/func_tab.h $(INCL)/dlb.h \ + $(INCL)/patchlevel.h $(INCL)/wingem.h + $(cc) $(CFLAGS) -o$@ ../win/gem/wingem.c +$(O)wingem1.o: ../win/gem/wingem1.c $(INCL)/gem_rsc.h $(INCL)/load_img.h \ + $(INCL)/wintype.h $(INCL)/wingem.h + $(cc) $(CFLAGS) -o$@ ../win/gem/wingem1.c +$(O)load_img.o: ../win/gem/load_img.c $(INCL)/load_img.h + $(cc) $(CFLAGS) -o$@ ../win/gem/load_img.c +$(O)tile.o: tile.c $(HACK_H) +$(O)qt_win.o: ../win/Qt/qt_win.cpp $(HACK_H) $(INCL)/func_tab.h \ + $(INCL)/dlb.h $(INCL)/patchlevel.h $(INCL)/qt_win.h \ + $(INCL)/qt_clust.h $(INCL)/qt_kde0.h \ + $(INCL)/qt_xpms.h qt_win.moc qt_kde0.moc + $(CXX) $(CXXFLAGS) -c ../win/Qt/qt_win.cpp +$(O)qt_clust.o: ../win/Qt/qt_clust.cpp $(INCL)/qt_clust.h + $(CXX) $(CXXFLAGS) -c ../win/Qt/qt_clust.cpp +$(O)monstr.o: $(SRC)/monstr.c $(CONFIG_H) +$(O)vis_tab.o: $(SRC)/vis_tab.c $(CONFIG_H) $(INCL)/vis_tab.h +$(O)allmain.o: allmain.c $(HACK_H) +$(O)alloc.o: alloc.c $(CONFIG_H) +$(O)apply.o: apply.c $(HACK_H) $(INCL)/edog.h +$(O)artifact.o: artifact.c $(HACK_H) $(INCL)/artifact.h $(INCL)/artilist.h +$(O)attrib.o: attrib.c $(HACK_H) $(INCL)/artifact.h +$(O)ball.o: ball.c $(HACK_H) +$(O)bones.o: bones.c $(HACK_H) $(INCL)/lev.h +$(O)botl.o: botl.c $(HACK_H) +$(O)cmd.o: cmd.c $(HACK_H) $(INCL)/func_tab.h +$(O)dbridge.o: dbridge.c $(HACK_H) +$(O)decl.o: decl.c $(HACK_H) +$(O)detect.o: detect.c $(HACK_H) $(INCL)/artifact.h +$(O)dig.o: dig.c $(HACK_H) $(INCL)/edog.h +$(O)display.o: display.c $(HACK_H) +$(O)dlb.o: dlb.c $(CONFIG_H) $(INCL)/dlb.h +$(O)do.o: do.c $(HACK_H) $(INCL)/lev.h +$(O)do_name.o: do_name.c $(HACK_H) +$(O)do_wear.o: do_wear.c $(HACK_H) +$(O)dog.o: dog.c $(HACK_H) $(INCL)/edog.h +$(O)dogmove.o: dogmove.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/edog.h +$(O)dokick.o: dokick.c $(HACK_H) $(INCL)/eshk.h +$(O)dothrow.o: dothrow.c $(HACK_H) +$(O)drawing.o: drawing.c $(HACK_H) $(INCL)/tcap.h +$(O)dungeon.o: dungeon.c $(HACK_H) $(INCL)/dgn_file.h $(INCL)/dlb.h +$(O)eat.o: eat.c $(HACK_H) +$(O)end.o: end.c $(HACK_H) $(INCL)/eshk.h $(INCL)/dlb.h +$(O)engrave.o: engrave.c $(HACK_H) $(INCL)/lev.h +$(O)exper.o: exper.c $(HACK_H) +$(O)explode.o: explode.c $(HACK_H) +$(O)extralev.o: extralev.c $(HACK_H) +$(O)files.o: files.c $(HACK_H) $(INCL)/dlb.h +$(O)fountain.o: fountain.c $(HACK_H) +$(O)hack.o: hack.c $(HACK_H) +$(O)hacklib.o: hacklib.c $(HACK_H) +$(O)invent.o: invent.c $(HACK_H) $(INCL)/artifact.h +$(O)light.o: light.c $(HACK_H) $(INCL)/lev.h +$(O)lock.o: lock.c $(HACK_H) +$(O)mail.o: mail.c $(HACK_H) $(INCL)/mail.h +$(O)makemon.o: makemon.c $(HACK_H) $(INCL)/epri.h $(INCL)/emin.h \ + $(INCL)/edog.h +$(O)mapglyph.o: mapglyph.c $(HACK_H) +$(O)mcastu.o: mcastu.c $(HACK_H) +$(O)mhitm.o: mhitm.c $(HACK_H) $(INCL)/artifact.h $(INCL)/edog.h +$(O)mhitu.o: mhitu.c $(HACK_H) $(INCL)/artifact.h $(INCL)/edog.h +$(O)minion.o: minion.c $(HACK_H) $(INCL)/emin.h $(INCL)/epri.h +$(O)mklev.o: mklev.c $(HACK_H) +$(O)mkmap.o: mkmap.c $(HACK_H) $(INCL)/sp_lev.h +$(O)mkmaze.o: mkmaze.c $(HACK_H) $(INCL)/sp_lev.h $(INCL)/lev.h +$(O)mkobj.o: mkobj.c $(HACK_H) $(INCL)/artifact.h +$(O)mkroom.o: mkroom.c $(HACK_H) +$(O)mon.o: mon.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/edog.h +$(O)mondata.o: mondata.c $(HACK_H) $(INCL)/eshk.h $(INCL)/epri.h +$(O)monmove.o: monmove.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/artifact.h +$(O)monst.o: monst.c $(CONFIG_H) $(INCL)/permonst.h $(INCL)/align.h \ + $(INCL)/monattk.h $(INCL)/monflag.h $(INCL)/monsym.h \ + $(INCL)/dungeon.h $(INCL)/eshk.h $(INCL)/vault.h \ + $(INCL)/epri.h $(INCL)/color.h +$(O)mplayer.o: mplayer.c $(HACK_H) +$(O)mthrowu.o: mthrowu.c $(HACK_H) +$(O)muse.o: muse.c $(HACK_H) $(INCL)/edog.h +$(O)music.o: music.c $(HACK_H) #interp.c +$(O)o_init.o: o_init.c $(HACK_H) $(INCL)/lev.h +$(O)objects.o: objects.c $(CONFIG_H) $(INCL)/obj.h $(INCL)/objclass.h \ + $(INCL)/prop.h $(INCL)/skills.h $(INCL)/color.h +$(O)objnam.o: objnam.c $(HACK_H) +$(O)options.o: options.c $(CONFIG_H) $(INCL)/objclass.h $(INCL)/flag.h \ + $(HACK_H) $(INCL)/tcap.h +$(O)pager.o: pager.c $(HACK_H) $(INCL)/dlb.h +$(O)pickup.o: pickup.c $(HACK_H) +$(O)pline.o: pline.c $(HACK_H) $(INCL)/epri.h $(INCL)/edog.h +$(O)polyself.o: polyself.c $(HACK_H) +$(O)potion.o: potion.c $(HACK_H) +$(O)pray.o: pray.c $(HACK_H) $(INCL)/epri.h +$(O)priest.o: priest.c $(HACK_H) $(INCL)/mfndpos.h $(INCL)/eshk.h \ + $(INCL)/epri.h $(INCL)/emin.h +$(O)quest.o: quest.c $(HACK_H) $(INCL)/qtext.h +$(O)questpgr.o: questpgr.c $(HACK_H) $(INCL)/dlb.h $(INCL)/qtext.h +$(O)read.o: read.c $(HACK_H) +$(O)rect.o: rect.c $(HACK_H) +$(O)region.o: region.c $(HACK_H) $(INCL)/lev.h +$(O)restore.o: restore.c $(HACK_H) $(INCL)/lev.h $(INCL)/tcap.h +$(O)rip.o: rip.c $(HACK_H) +$(O)rnd.o: rnd.c $(HACK_H) +$(O)role.o: role.c $(HACK_H) +$(O)rumors.o: rumors.c $(HACK_H) $(INCL)/lev.h $(INCL)/dlb.h +$(O)save.o: save.c $(HACK_H) $(INCL)/lev.h +$(O)shk.o: shk.c $(HACK_H) $(INCL)/eshk.h +$(O)shknam.o: shknam.c $(HACK_H) $(INCL)/eshk.h +$(O)sit.o: sit.c $(HACK_H) $(INCL)/artifact.h +$(O)sounds.o: sounds.c $(HACK_H) $(INCL)/edog.h +$(O)sp_lev.o: sp_lev.c $(HACK_H) $(INCL)/dlb.h $(INCL)/sp_lev.h +$(O)spell.o: spell.c $(HACK_H) +$(O)steal.o: steal.c $(HACK_H) +$(O)steed.o: steed.c $(HACK_H) +$(O)teleport.o: teleport.c $(HACK_H) +$(O)timeout.o: timeout.c $(HACK_H) $(INCL)/lev.h +$(O)topten.o: topten.c $(HACK_H) $(INCL)/dlb.h $(INCL)/patchlevel.h +$(O)track.o: track.c $(HACK_H) +$(O)trap.o: trap.c $(HACK_H) +$(O)u_init.o: u_init.c $(HACK_H) +$(O)uhitm.o: uhitm.c $(HACK_H) +$(O)vault.o: vault.c $(HACK_H) $(INCL)/vault.h +$(O)version.o: version.c $(HACK_H) $(INCL)/date.h $(INCL)/patchlevel.h +$(O)vision.o: vision.c $(HACK_H) $(INCL)/vis_tab.h +$(O)weapon.o: weapon.c $(HACK_H) +$(O)were.o: were.c $(HACK_H) +$(O)wield.o: wield.c $(HACK_H) +$(O)windows.o: windows.c $(HACK_H) $(INCL)/wingem.h $(INCL)/winGnome.h +$(O)wizard.o: wizard.c $(HACK_H) $(INCL)/qtext.h +$(O)worm.o: worm.c $(HACK_H) $(INCL)/lev.h +$(O)worn.o: worn.c $(HACK_H) +$(O)write.o: write.c $(HACK_H) +$(O)zap.o: zap.c $(HACK_H) + +# end of file + diff --git a/sys/winnt/Makefile.msc b/sys/winnt/Makefile.msc new file mode 100644 index 0000000..08061cd --- /dev/null +++ b/sys/winnt/Makefile.msc @@ -0,0 +1,1345 @@ +# SCCS Id: @(#)Makefile.nt 3.4 2002/02/28 +# Copyright (c) NetHack PC Development Team 1993-2001 +# +# NetHack 3.4.x Makefile for MS Visual C++ V6.x and above and MS NMAKE +# +# Win32 Compilers Tested: +# - Microsoft 32 bit Visual C++ V4.x +# - Microsoft 32 bit Visual C++ V6.0 SP3, SP4 +# +# This is used for building a TTY version of NetHack using WIN32 Console +# I/O routines only. +# +# In addition to your C compiler, +# +# if you want to change you will need a +# files with suffix workalike for +# .y yacc (such as bison) +# .l lex (such as flex) +# +# +# If you have any questions read the sys/winnt/Install.nt file included +# with the distribution. +# -- +# Michael Allison +#============================================================================== +# Do not delete the following 3 lines. +# +TARGETOS=BOTH +APPVER=4.0 +!include + +# Graphical interface +# Set to Y for a graphical version + +#GRAPHICAL = Y + +# +# Set the gamedir according to your preference. +# If not present prior to compilation it gets created. + +GAME = NetHack # Game Name +GAMEDIR = ..\binary # Game directory + +# +# Source directories. Makedefs hardcodes these, don't change them. +# + +INCL = ..\include # NetHack include files +DAT = ..\dat # NetHack data files +DOC = ..\doc # NetHack documentation files +UTIL = ..\util # Utility source +SRC = ..\src # Main source +SSYS = ..\sys\share # Shared system files +NTSYS = ..\sys\winnt # NT Win32 specific files +TTY = ..\win\tty # window port files (tty) +WIN32 = ..\win\win32 # window port files (Win32) +WSHR = ..\win\share # Tile support files + +# +# Object directory. +# + +OBJ = o + + +# +#========================================== +# Exe File Info. +#========================================== + +# Yacc/Lex ... if you got 'em. +# +# If you have yacc and lex programs (or work-alike such as bison +# and flex), comment out the upper two macros and uncomment +# the lower two. +# + +DO_YACC = YACC_MSG +DO_LEX = LEX_MSG +#DO_YACC = YACC_ACT +#DO_LEX = LEX_ACT + +# - Specify your yacc and lex programs (or work-alikes) here. + +#YACC = bison -y +YACC = byacc +#YACC = yacc + +#LEX = lex +LEX = flex + +# +# - Specify your flex skeleton file (if needed). +# + +FLEXSKEL = +#FLEXSKEL = -S../tools/flex.ske + +YTABC = y_tab.c +YTABH = y_tab.h +LEXYYC = lexyy.c + +# +# Optional high-quality BSD random number generation routines +# (see pcconf.h). Set to nothing if not used. +# + +RANDOM = $(OBJ)\random.o +#RANDOM = + +# +# - For debugging ability, comment out the upper two +# macros and uncomment the lower two. +# + +# +# Leave the next two lines uncommented _ONLY_ if you do NOT want any +# debug capability in the object files, or in the NetHack executable. +# Comment them if you want debug capability. + +#cdebug = +#linkdebug = + +# +# Compiler and Linker flags +# + +PRECOMPHEAD = N # set to Y if you want to use precomp. headers + +#=============================================== +#======= End of Modification Section =========== +#=============================================== +################################################ +# # +# Nothing below here should have to be changed.# +# # +################################################ + +!IF "$(GRAPHICAL)" == "Y" +WINPORT = $(O)tile.o $(O)mhaskyn.o $(O)mhdlg.o \ + $(O)mhfont.o $(O)mhinput.o $(O)mhmain.o $(O)mhmap.o \ + $(O)mhmenu.o $(O)mhmsgwnd.o $(O)mhrip.o $(O)mhsplash.o \ + $(O)mhstatus.o $(O)mhtext.o $(O)mswproc.o $(O)winhack.o +WINPFLAG = -DTILES -DMSWIN_GRAPHICS +NHRES = $(O)winhack.res +WINPINC = -I$(WIN32) +WINPHDR = $(WIN32)\mhaskyn.h $(WIN32)\mhdlg.h $(WIN32)\mhfont.h \ + $(WIN32)\mhinput.h $(WIN32)\mhmain.h $(WIN32)\mhmap.h $(WIN32)\mhmenu.h \ + $(WIN32)\mhmsg.h $(WIN32)\mhmsgwnd.h $(WIN32)\mhrip.h $(WIN32)\mhstatus.h \ + $(WIN32)\mhtext.h $(WIN32)\resource.h $(WIN32)\winMS.h +!ELSE +WINPORT = $(O)nttty.o +WINPFLAG = -DWIN32CON +WINPHDR = +NHRES = $(O)console.res +WINPINC = +!ENDIF + +TILEUTIL16 = $(UTIL)\tile2bmp.exe +TILEBMP16 = $(SRC)\tiles.bmp + +TILEUTIL32 = $(UTIL)\til2bm32.exe +TILEBMP32 = $(SRC)\tiles32.bmp + +#SOUND = $(OBJ)\ntsound.o + +#SOUND = + +# To store all the level files, +# help files, etc. in a single library file. +# USE_DLB = Y is left uncommented + +USE_DLB = Y + +! IF ("$(USE_DLB)"=="Y") +DLBFLG = -DDLB +! ELSE +DLBFLG = +! ENDIF + +#========================================== +# Setting up the compiler and linker +# macros. All builds include the base ones. +#========================================== + +CFLAGSBASE = -c $(cflags) $(cvarsmt) -I$(INCL) -nologo $(cdebug) $(WINPINC) +LFLAGSBASEC = $(linkdebug) /NODEFAULTLIB /INCREMENTAL:NO /RELEASE /NOLOGO -subsystem:console,4.0 $(conlibsmt) +LFLAGSBASEG = $(linkdebug) $(guiflags) $(guilibsmt) comctl32.lib + +#========================================== +# Util builds +#========================================== + +CFLAGSU = $(CFLAGSBASE) $(WINPFLAG) +LFLAGSU = $(LFLAGSBASEC) + +#========================================== +# - Game build +#========================================== +LFLAGSBASE = $(linkdebug) /NODEFAULTLIB /INCREMENTAL:NO /RELEASE /NOLOGO -subsystem:console,4.0 $(conlibsmt) +CFLAGS = $(CFLAGSBASE) $(WINPFLAG) $(DLBFLG) +NHLFLAGS1 = /NODEFAULTLIB /INCREMENTAL:NO /PDB:"$(GAME).PDB" /RELEASE /NOLOGO +NHLFLAGS2 = /MAP:"$(GAME).MAP" /MACHINE:$(CPU) -IGNORE:505 +!IF ("$(GRAPHICAL)"=="Y") +LFLAGS = $(LFLAGSBASEG) $(NHLFLAGS1) $(NHLFLAGS2) +!ELSE +LFLAGS = $(LFLAGSBASEC) $(NHLFLAGS1) $(NHLFLAGS2) +!ENDIF + +GAMEFILE = $(GAMEDIR)\$(GAME).exe # whole thing + +! IF ("$(USE_DLB)"=="Y") +DLB = nhdat +! ELSE +DLB = +! ENDIF + +#========================================== +#================ RULES ================== +#========================================== + +.SUFFIXES: .exe .o .til .uu .c .y .l + +#========================================== +# Rules for files in src +#========================================== + +.c{$(OBJ)}.o: + @$(cc) $(CFLAGS) -Fo$@ $< + +{$(SRC)}.c{$(OBJ)}.o: + @$(CC) $(CFLAGS) -Fo$@ $< + +#========================================== +# Rules for files in sys\share +#========================================== + +{$(SSYS)}.c{$(OBJ)}.o: + @$(CC) $(CFLAGS) -Fo$@ $< + +#========================================== +# Rules for files in sys\winnt +#========================================== + +{$(NTSYS)}.c{$(OBJ)}.o: + @$(CC) $(CFLAGS) -Fo$@ $< + +{$(NTSYS)}.h{$(INCL)}.h: + @copy $< $@ + +#========================================== +# Rules for files in util +#========================================== + +{$(UTIL)}.c{$(OBJ)}.o: + @$(CC) $(CFLAGSU) -Fo$@ $< + +#========================================== +# Rules for files in win\share +#========================================== + +{$(WSHR)}.c{$(OBJ)}.o: + @$(CC) $(CFLAGS) -Fo$@ $< + +{$(WSHR)}.h{$(INCL)}.h: + @copy $< $@ + +#{$(WSHR)}.txt{$(DAT)}.txt: +# @copy $< $@ + +#========================================== +# Rules for files in win\tty +#========================================== + +{$(TTY)}.c{$(OBJ)}.o: + @$(CC) $(CFLAGS) -Fo$@ $< + + +#========================================== +# Rules for files in win\win32 +#========================================== + +{$(WIN32)}.c{$(OBJ)}.o: + @$(cc) $(CFLAGS) -Fo$@ $< + +#========================================== +#================ MACROS ================== +#========================================== +# This section creates shorthand macros for many objects +# referenced later on in the Makefile. +# + +DEFFILE = $(NTSYS)\$(GAME).def + +# +# Shorten up the location for some files +# + +O = $(OBJ)^\ + +U = $(UTIL)^\ + +# +# Utility Objects. +# + +MAKESRC = $(U)makedefs.c + +SPLEVSRC = $(U)lev_yacc.c $(U)lev_$(LEX).c $(U)lev_main.c $(U)panic.c + +DGNCOMPSRC = $(U)dgn_yacc.c $(U)dgn_$(LEX).c $(U)dgn_main.c + +MAKEOBJS = $(O)makedefs.o $(O)monst.o $(O)objects.o + +SPLEVOBJS = $(O)lev_yacc.o $(O)lev_$(LEX).o $(O)lev_main.o \ + $(O)alloc.o $(O)decl.o $(O)drawing.o \ + $(O)monst.o $(O)objects.o $(O)panic.o + +DGNCOMPOBJS = $(O)dgn_yacc.o $(O)dgn_$(LEX).o $(O)dgn_main.o \ + $(O)alloc.o $(O)panic.o + +RECOVOBJS = $(O)recover.o + +TILEFILES = $(WSHR)\monsters.txt $(WSHR)\objects.txt $(WSHR)\other.txt + +# +# These are not invoked during a normal game build in 3.4.0 +# +TEXT_IO = $(O)tiletext.o $(O)tiletxt.o $(O)drawing.o \ + $(O)decl.o $(O)monst.o $(O)objects.o + +TEXT_IO32 = $(O)tilete32.o $(O)tiletx32.o $(O)drawing.o \ + $(O)decl.o $(O)monst.o $(O)objects.o + +GIFREADERS = $(O)gifread.o $(O)alloc.o $(O)panic.o +GIFREADERS32 = $(O)gifrd32.o $(O)alloc.o $(O)panic.o + +PPMWRITERS = $(O)ppmwrite.o $(O)alloc.o $(O)panic.o + +# +# Object files for the game itself. +# + +VOBJ01 = $(O)allmain.o $(O)alloc.o $(O)apply.o $(O)artifact.o +VOBJ02 = $(O)attrib.o $(O)ball.o $(O)bones.o $(O)botl.o +VOBJ03 = $(O)cmd.o $(O)dbridge.o $(O)decl.o $(O)detect.o +VOBJ04 = $(O)dig.o $(O)display.o $(O)do.o $(O)do_name.o +VOBJ05 = $(O)do_wear.o $(O)dog.o $(O)dogmove.o $(O)dokick.o +VOBJ06 = $(O)dothrow.o $(O)drawing.o $(O)dungeon.o $(O)eat.o +VOBJ07 = $(O)end.o $(O)engrave.o $(O)exper.o $(O)explode.o +VOBJ08 = $(O)extralev.o $(O)files.o $(O)fountain.o $(O)hack.o +VOBJ09 = $(O)hacklib.o $(O)invent.o $(O)light.o $(O)lock.o +VOBJ10 = $(O)mail.o $(O)pcmain.o $(O)makemon.o $(O)mapglyph.o $(O)mcastu.o +VOBJ11 = $(O)mhitm.o $(O)mhitu.o $(O)minion.o $(O)mklev.o +VOBJ12 = $(O)mkmap.o $(O)mkmaze.o $(O)mkobj.o $(O)mkroom.o +VOBJ13 = $(O)mon.o $(O)mondata.o $(O)monmove.o $(O)monst.o +VOBJ14 = $(O)monstr.o $(O)mplayer.o $(O)mthrowu.o $(O)muse.o +VOBJ15 = $(O)music.o $(O)o_init.o $(O)objects.o $(O)objnam.o +VOBJ16 = $(O)options.o $(O)pager.o $(O)pickup.o $(O)pline.o +VOBJ17 = $(O)polyself.o $(O)potion.o $(O)pray.o $(O)priest.o +VOBJ18 = $(O)quest.o $(O)questpgr.o $(RANDOM) $(O)read.o +VOBJ19 = $(O)rect.o $(O)region.o $(O)restore.o $(O)rip.o +VOBJ20 = $(O)rnd.o $(O)role.o $(O)rumors.o $(O)save.o +VOBJ21 = $(O)shk.o $(O)shknam.o $(O)sit.o $(O)sounds.o +VOBJ22 = $(O)sp_lev.o $(O)spell.o $(O)steal.o $(O)steed.o +VOBJ23 = $(O)teleport.o $(O)timeout.o $(O)topten.o $(O)track.o +VOBJ24 = $(O)trap.o $(O)u_init.o $(O)uhitm.o $(O)vault.o +VOBJ25 = $(O)vis_tab.o $(O)vision.o $(O)weapon.o $(O)were.o +VOBJ26 = $(O)wield.o $(O)windows.o $(O)wizard.o $(O)worm.o +VOBJ27 = $(O)worn.o $(O)write.o $(O)zap.o + +DLBOBJ = $(O)dlb.o + +TTYOBJ = $(O)topl.o $(O)getline.o $(O)wintty.o + +SOBJ = $(O)winnt.o $(O)pcsys.o $(O)pcunix.o \ + $(SOUND) $(O)mapimail.o $(O)nhlan.o + +OBJS = $(VOBJ01) $(VOBJ02) $(VOBJ03) $(VOBJ04) $(VOBJ05) \ + $(VOBJ06) $(VOBJ07) $(VOBJ08) $(VOBJ09) $(VOBJ10) \ + $(VOBJ11) $(VOBJ12) $(VOBJ13) $(VOBJ14) $(VOBJ15) \ + $(VOBJ16) $(VOBJ17) $(VOBJ18) $(VOBJ19) $(VOBJ20) \ + $(VOBJ21) $(VOBJ22) $(VOBJ23) $(VOBJ24) $(VOBJ25) \ + $(VOBJ26) $(VOBJ27) + +WINPOBJ = $(WINPORT) + +VVOBJ = $(O)version.o + +ALLOBJ = $(WINPOBJ) $(SOBJ) $(DLBOBJ) $(TTYOBJ) $(WOBJ) $(OBJS) $(VVOBJ) + +!IF "$(GRAPHICAL)" == "Y" +OPTIONS_FILE = $(DAT)\guioptions +!ELSE +OPTIONS_FILE = $(DAT)\ttyoptions +!ENDIF +#========================================== +# Header file macros +#========================================== + +CONFIG_H = $(INCL)\config.h $(INCL)\config1.h $(INCL)\tradstdc.h \ + $(INCL)\global.h $(INCL)\coord.h $(INCL)\vmsconf.h \ + $(INCL)\system.h $(INCL)\unixconf.h $(INCL)\os2conf.h \ + $(INCL)\micro.h $(INCL)\pcconf.h $(INCL)\tosconf.h \ + $(INCL)\amiconf.h $(INCL)\macconf.h $(INCL)\beconf.h \ + $(INCL)\ntconf.h $(INCL)\nhlan.h + +HACK_H = $(INCL)\hack.h $(CONFIG_H) $(INCL)\align.h \ + $(INCL)\dungeon.h $(INCL)\monsym.h $(INCL)\mkroom.h \ + $(INCL)\objclass.h $(INCL)\youprop.h $(INCL)\prop.h \ + $(INCL)\permonst.h $(INCL)\monattk.h \ + $(INCL)\monflag.h $(INCL)\mondata.h $(INCL)\pm.h \ + $(INCL)\wintype.h $(INCL)\decl.h $(INCL)\quest.h \ + $(INCL)\spell.h $(INCL)\color.h $(INCL)\obj.h \ + $(INCL)\you.h $(INCL)\attrib.h $(INCL)\monst.h \ + $(INCL)\skills.h $(INCL)\onames.h $(INCL)\timeout.h \ + $(INCL)\trap.h $(INCL)\flag.h $(INCL)\rm.h \ + $(INCL)\vision.h $(INCL)\display.h $(INCL)\engrave.h \ + $(INCL)\rect.h $(INCL)\region.h $(INCL)\winprocs.h \ + $(INCL)\wintty.h $(INCL)\trampoli.h + +LEV_H = $(INCL)\lev.h +DGN_FILE_H = $(INCL)\dgn_file.h +LEV_COMP_H = $(INCL)\lev_comp.h +SP_LEV_H = $(INCL)\sp_lev.h +TILE_H = ..\win\share\tile.h + +#========================================== +# Miscellaneous +#========================================== + +DATABASE = $(DAT)\data.base + +# +# The name of the game. +# + +GAMEFILE = $(GAMEDIR)\$(GAME).exe + +#========================================== +#=============== TARGETS ================== +#========================================== + +# +# The default make target (so just typing 'nmake' is useful). +# +default : $(GAMEFILE) + +# +# The main target. +# + +$(GAME): $(O)obj.tag $(O)utility.tag envchk $(GAMEFILE) + @echo $(GAME) is up to date. + +# +# Everything +# + +all : install + +install: envchk $(GAME) $(O)install.tag + @echo Done. + +$(O)install.tag: $(DAT)\data $(DAT)\rumors $(DAT)\dungeon \ + $(DAT)\oracles $(DAT)\quest.dat $(O)sp_lev.tag $(DLB) +! IF ("$(USE_DLB)"=="Y") + copy nhdat $(GAMEDIR) + copy $(DAT)\license $(GAMEDIR) +! ELSE + copy $(DAT)\*. $(GAMEDIR) + copy $(DAT)\*.dat $(GAMEDIR) + copy $(DAT)\*.lev $(GAMEDIR) + if exist $(GAMEDIR)\makefile del $(GAMEDIR)\makefile +! ENDIF + if exist $(DOC)\guidebook.txt copy $(DOC)\guidebook.txt $(GAMEDIR)\Guidebook.txt + if exist $(DOC)\nethack.txt copy $(DOC)\nethack.txt $(GAMEDIR)\NetHack.txt + if exist $(DOC)\recover.txt copy $(DOC)\recover.txt $(GAMEDIR)\recover.txt + @if exist $(SRC)\$(GAME).PDB copy $(SRC)\$(GAME).pdb $(GAMEDIR)\$(GAME).pdb + @if exist $(GAMEDIR)\$(GAME).PDB echo NOTE: You may want to remove $(GAMEDIR)\$(GAME).pdb to conserve space + -copy $(NTSYS)\defaults.nh $(GAMEDIR)\defaults.nh + copy $(U)recover.exe $(GAMEDIR) + echo install done > $@ + +# copy $(NTSYS)\winnt.hlp $(GAMEDIR) + +$(O)sp_lev.tag: $(O)utility.tag $(DAT)\bigroom.des $(DAT)\castle.des \ + $(DAT)\endgame.des $(DAT)\gehennom.des $(DAT)\knox.des \ + $(DAT)\medusa.des $(DAT)\oracle.des $(DAT)\tower.des \ + $(DAT)\yendor.des $(DAT)\arch.des $(DAT)\barb.des \ + $(DAT)\caveman.des $(DAT)\healer.des $(DAT)\knight.des \ + $(DAT)\monk.des $(DAT)\priest.des $(DAT)\ranger.des \ + $(DAT)\rogue.des $(DAT)\samurai.des $(DAT)\sokoban.des \ + $(DAT)\tourist.des $(DAT)\valkyrie.des $(DAT)\wizard.des + cd $(DAT) + $(U)lev_comp bigroom.des + $(U)lev_comp castle.des + $(U)lev_comp endgame.des + $(U)lev_comp gehennom.des + $(U)lev_comp knox.des + $(U)lev_comp mines.des + $(U)lev_comp medusa.des + $(U)lev_comp oracle.des + $(U)lev_comp sokoban.des + $(U)lev_comp tower.des + $(U)lev_comp yendor.des + $(U)lev_comp arch.des + $(U)lev_comp barb.des + $(U)lev_comp caveman.des + $(U)lev_comp healer.des + $(U)lev_comp knight.des + $(U)lev_comp monk.des + $(U)lev_comp priest.des + $(U)lev_comp ranger.des + $(U)lev_comp rogue.des + $(U)lev_comp samurai.des + $(U)lev_comp tourist.des + $(U)lev_comp valkyrie.des + $(U)lev_comp wizard.des + cd $(SRC) + echo sp_levs done > $(O)sp_lev.tag + +$(O)utility.tag: $(INCL)\date.h $(INCL)\onames.h $(INCL)\pm.h \ + $(SRC)\monstr.c $(SRC)\vis_tab.c \ + $(U)lev_comp.exe $(INCL)\vis_tab.h \ + $(U)dgn_comp.exe $(U)recover.exe + @echo utilities made >$@ + @echo utilities made. + +tileutil: $(U)gif2txt.exe $(U)gif2tx32.exe $(U)txt2ppm.exe + @echo Optional tile development utilities are up to date. + +!IF "$(GRAPHICAL)"=="Y" +$(NHRES): $(TILEBMP16) $(WIN32)\winhack.rc $(WIN32)\mnsel.bmp \ + $(WIN32)\mnselcnt.bmp $(WIN32)\mnunsel.bmp \ + $(WIN32)\petmark.bmp $(WIN32)\NetHack.ico $(WIN32)\rip.bmp \ + $(WIN32)\splash.bmp + @$(rc) -r -fo$@ -i$(WIN32) -dNDEBUG $(WIN32)\winhack.rc +!ELSE +$(NHRES): $(NTSYS)\console.rc $(NTSYS)\NetHack.ico + @$(rc) -r -fo$@ -i$(NTSYS) -dNDEBUG $(NTSYS)\console.rc +!ENDIF + +#========================================== +# The main target. +#========================================== + +# The section for linking the NetHack image looks a little strange at +# first, especially if you are used to UNIX makes, or NDMAKE. It is +# Microsoft nmake specific, and it gets around the problem of the +# link command line being too long for the linker. An "in-line" linker +# response file is generated temporarily. +# +# It takes advantage of the following features of nmake: +# +# Inline files : +# Specifying the "<<" means to start an inline file. +# Another "<<" at the start of a line closes the +# inline file. +# +# Substitution within Macros: +# $(mymacro:string1=string2) replaces every +# occurrence of string1 with string2 in the +# macro mymacro. Special ascii key codes may be +# used in the substitution text by preceding it +# with ^ as we have done below. Every occurence +# of a in $(ALLOBJ) is replaced by +# <+>. +# +# DO NOT INDENT THE << below! +# + +$(GAMEFILE) : $(ALLOBJ) $(NHRES) + @if not exist $(GAMEDIR)\*.* mkdir $(GAMEDIR) + @echo Linking.... + $(link) $(LFLAGS) -out:$@ @<<$(GAME).lnk + $(ALLOBJ:^ =^ + ) $(NHRES) +<< + @if exist $(O)install.tag del $(O)install.tag + @if exist $(GAMEDIR)\$(GAME).bak del $(GAMEDIR)\$(GAME).bak + +# +# Secondary Targets. +# + +#========================================== +# Makedefs Stuff +#========================================== + +$(U)makedefs.exe: $(MAKEOBJS) + @$(link) $(LFLAGSU) -out:$@ $(MAKEOBJS) + +$(O)makedefs.o: $(CONFIG_H) $(INCL)\monattk.h $(INCL)\monflag.h $(INCL)\objclass.h \ + $(INCL)\monsym.h $(INCL)\qtext.h $(INCL)\patchlevel.h \ + $(U)makedefs.c + @if not exist $(OBJ)\*.* echo creating directory $(OBJ) + @if not exist $(OBJ)\*.* mkdir $(OBJ) + @$(CC) $(CFLAGSU) -Fo$@ $(U)makedefs.c + +# +# date.h should be remade every time any of the source or include +# files is modified. +# + +$(INCL)\date.h $(OPTIONS_FILE) : $(U)makedefs.exe + $(U)makedefs -v + +$(INCL)\onames.h : $(U)makedefs.exe + $(U)makedefs -o + +$(INCL)\pm.h : $(U)makedefs.exe + $(U)makedefs -p + +#$(INCL)\trap.h : $(U)makedefs.exe +# $(U)makedefs -t + +$(SRC)\monstr.c: $(U)makedefs.exe + $(U)makedefs -m + +$(INCL)\vis_tab.h: $(U)makedefs.exe + $(U)makedefs -z + +$(SRC)\vis_tab.c: $(U)makedefs.exe + $(U)makedefs -z + +#========================================== +# uudecode utility and uuencoded targets +#========================================== + +$(U)uudecode.exe: $(O)uudecode.o + @$(link) $(LFLAGSU) -out:$@ $(O)\uudecode.o + +$(O)uudecode.o: $(SSYS)\uudecode.c + +$(NTSYS)\NetHack.ico : $(U)uudecode.exe $(NTSYS)\nhico.uu + chdir $(NTSYS) + ..\..\util\uudecode.exe nhico.uu + chdir ..\..\src + +$(WIN32)\NetHack.ico : $(U)uudecode.exe $(NTSYS)\nhico.uu + chdir $(WIN32) + ..\..\util\uudecode.exe ../../sys/winnt/nhico.uu + chdir ..\..\src + +$(WIN32)\mnsel.bmp: $(U)uudecode.exe $(WIN32)\mnsel.uu + chdir $(WIN32) + ..\..\util\uudecode.exe mnsel.uu + chdir ..\..\src + +$(WIN32)\mnselcnt.bmp: $(U)uudecode.exe $(WIN32)\mnselcnt.uu + chdir $(WIN32) + ..\..\util\uudecode.exe mnselcnt.uu + chdir ..\..\src + +$(WIN32)\mnunsel.bmp: $(U)uudecode.exe $(WIN32)\mnunsel.uu + chdir $(WIN32) + ..\..\util\uudecode.exe mnunsel.uu + chdir ..\..\src + +$(WIN32)\petmark.bmp: $(U)uudecode.exe $(WIN32)\petmark.uu + chdir $(WIN32) + ..\..\util\uudecode.exe petmark.uu + chdir ..\..\src + +$(WIN32)\rip.bmp: $(U)uudecode.exe $(WIN32)\rip.uu + chdir $(WIN32) + ..\..\util\uudecode.exe rip.uu + chdir ..\..\src + +$(WIN32)\splash.bmp: $(U)uudecode.exe $(WIN32)\splash.uu + chdir $(WIN32) + ..\..\util\uudecode.exe splash.uu + chdir ..\..\src + +#========================================== +# Level Compiler Stuff +#========================================== + +LEVCFLAGS=-c -nologo -DWINVER=0x0400 -DWIN32 -D_WIN32 \ + -D_MT -MT -I..\include -nologo -Z7 -Od -DDLB + +$(U)lev_comp.exe: $(SPLEVOBJS) + @echo Linking $@... + @$(link) $(LFLAGSU) -out:$@ @<<$(@B).lnk + $(SPLEVOBJS:^ =^ + ) +<< + +$(O)lev_yacc.o: $(HACK_H) $(SP_LEV_H) $(INCL)\lev_comp.h $(U)lev_yacc.c + @$(CC) $(LEVCFLAGS) -W0 -Fo$@ $(U)lev_yacc.c + +$(O)lev_$(LEX).o: $(HACK_H) $(INCL)\lev_comp.h $(SP_LEV_H) \ + $(U)lev_$(LEX).c + @$(CC) $(LEVCFLAGS) -W0 -Fo$@ $(U)lev_$(LEX).c + +$(O)lev_main.o: $(U)lev_main.c $(HACK_H) $(SP_LEV_H) + @$(CC) $(LEVCFLAGS) -W0 -Fo$@ $(U)lev_main.c + + +$(U)lev_yacc.c $(INCL)\lev_comp.h : $(U)lev_comp.y +! IF "$(DO_YACC)"=="YACC_ACT" + chdir $(UTIL) + $(YACC) -d lev_comp.y + copy $(YTABC) lev_yacc.c + copy $(YTABH) $(INCL)\lev_comp.h + @del $(YTABC) + @del $(YTABH) + chdir $(SRC) +! ELSE + @echo $(U)lev_comp.y has changed. + @echo To update $(U)lev_yacc.c and $(INCL)\lev_comp.h run $(YACC). + @echo --- + @echo For now, we will copy the prebuilt lev_yacc.c and + @echo lev_comp.h from $(SSYS) into $(UTIL) and use them. + @copy $(SSYS)\lev_yacc.c $(U)lev_yacc.c >nul + @copy $(SSYS)\lev_comp.h $(INCL)\lev_comp.h >nul + @echo /**/ >>$(U)lev_yacc.c + @echo /**/ >>$(INCL)\lev_comp.h +! ENDIF + +$(U)lev_$(LEX).c: $(U)lev_comp.l +! IF "$(DO_LEX)"=="LEX_ACT" + chdir $(UTIL) + $(LEX) $(FLEXSKEL) lev_comp.l + copy $(LEXYYC) $@ + @del $(LEXYYC) + chdir $(SRC) +! ELSE + @echo $(U)lev_comp.l has changed. To update $@ run $(LEX). + @echo --- + @echo For now, we will copy the prebuilt lev_lex.c + @echo from $(SSYS) into $(UTIL) and use it. + @copy $(SSYS)\lev_lex.c $@ >nul + @echo /**/ >>$@ +! ENDIF + +#========================================== +# Dungeon Compiler Stuff +#========================================== + +$(U)dgn_comp.exe: $(DGNCOMPOBJS) + @echo Linking $@... + @$(link) $(LFLAGSU) -out:$@ @<<$(@B).lnk + $(DGNCOMPOBJS:^ =^ + ) +<< + +$(O)dgn_yacc.o: $(HACK_H) $(DGN_FILE_H) $(INCL)\dgn_comp.h $(U)dgn_yacc.c + @$(CC) $(LEVCFLAGS) -W0 -Fo$@ $(U)dgn_yacc.c + +$(O)dgn_$(LEX).o: $(HACK_H) $(DGN_FILE_H) $(INCL)\dgn_comp.h \ + $(U)dgn_$(LEX).c + @$(CC) $(LEVCFLAGS) -W0 -Fo$@ $(U)dgn_$(LEX).c + +$(O)dgn_main.o: $(HACK_H) $(U)dgn_main.c + @$(CC) $(LEVCFLAGS) -W0 -Fo$@ $(U)dgn_main.c + +$(U)dgn_yacc.c $(INCL)\dgn_comp.h : $(U)dgn_comp.y +! IF "$(DO_YACC)"=="YACC_ACT" + chdir $(UTIL) + $(YACC) -d dgn_comp.y + copy $(YTABC) dgn_yacc.c + copy $(YTABH) $(INCL)\dgn_comp.h + @del $(YTABC) + @del $(YTABH) + chdir $(SRC) +! ELSE + @echo $(U)dgn_comp.y has changed. To update dgn_yacc.c and + @echo $(INCL)\dgn_comp.h run $(YACC). + @echo --- + @echo For now, we will copy the prebuilt $(U)dgn_yacc.c and + @echo dgn_comp.h from $(SSYS) into $(UTIL) and use them. + @copy $(SSYS)\dgn_yacc.c $(U)dgn_yacc.c >nul + @copy $(SSYS)\dgn_comp.h $(INCL)\dgn_comp.h >nul + @echo /**/ >>$(U)dgn_yacc.c + @echo /**/ >>$(INCL)\dgn_comp.h +! ENDIF + +$(U)dgn_$(LEX).c: $(U)dgn_comp.l +! IF "$(DO_LEX)"=="LEX_ACT" + chdir $(UTIL) + $(LEX) $(FLEXSKEL) dgn_comp.l + copy $(LEXYYC) $@ + @del $(LEXYYC) + chdir $(SRC) +! ELSE + @echo $(U)dgn_comp.l has changed. To update $@ run $(LEX). + @echo --- + @echo For now, we will copy the prebuilt dgn_lex.c + @echo from $(SSYS) into $(UTIL) and use it. + @copy $(SSYS)\dgn_lex.c $@ >nul + @echo /**/ >>$@ +! ENDIF + +#========================================== +# Create directory for holding object files +#========================================== + +$(O)obj.tag: + @if not exist $(OBJ)\*.* echo creating directory $(OBJ) + @if not exist $(OBJ)\*.* mkdir $(OBJ) + @echo directory created >$@ + +#========================================== +# Notify of any CL environment variables +# in effect since they change the compiler +# options. +#========================================== + +envchk: +! IF "$(CL)"!="" + @echo Warning, the CL Environment variable is defined: + @echo CL=$(CL) +! ENDIF +! IF "$(GRAPHICAL)"=="Y" + @echo ---- + @echo NOTE: This build will include tile support. + @echo ---- +! ENDIF + +#========================================== +#=========== SECONDARY TARGETS ============ +#========================================== + +#=========================================== +# Header files NOT distributed in ..\include +#=========================================== + +$(INCL)\win32api.h: $(NTSYS)\win32api.h + copy $(NTSYS)\win32api.h $@ + + +#========================================== +# DLB utility and nhdat file creation +#========================================== + +$(U)dlb_main.exe: $(DLBOBJ) $(O)dlb.o + @$(link) $(LFLAGSU) -out:$@ @<<$(@B).lnk + $(O)dlb_main.o + $(O)dlb.o + $(O)alloc.o + $(O)panic.o +<< + +$(O)dlb.o: $(O)dlb_main.o $(O)alloc.o $(O)panic.o $(INCL)\dlb.h + @$(CC) $(CFLAGS) /Fo$@ $(SRC)\dlb.c + +$(O)dlb_main.o: $(UTIL)\dlb_main.c $(INCL)\config.h $(INCL)\dlb.h + @$(CC) $(CFLAGS) /Fo$@ $(UTIL)\dlb_main.c + +$(DAT)\porthelp: $(NTSYS)\porthelp + @copy $(NTSYS)\porthelp $@ >nul + +nhdat: $(U)dlb_main.exe $(DAT)\data $(DAT)\oracles $(OPTIONS_FILE) \ + $(DAT)\quest.dat $(DAT)\rumors $(DAT)\help $(DAT)\hh $(DAT)\cmdhelp \ + $(DAT)\history $(DAT)\opthelp $(DAT)\wizhelp $(DAT)\dungeon $(DAT)\porthelp \ + $(DAT)\license $(O)sp_lev.tag + cd $(DAT) + echo data >dlb.lst + echo oracles >>dlb.lst + if exist options echo options >>dlb.lst + if exist ttyoptions echo ttyoptions >>dlb.lst + if exist guioptions echo guioptions >>dlb.lst + if exist porthelp echo porthelp >>dlb.lst + echo quest.dat >>dlb.lst + echo rumors >>dlb.lst + echo help >>dlb.lst + echo hh >>dlb.lst + echo cmdhelp >>dlb.lst + echo history >>dlb.lst + echo opthelp >>dlb.lst + echo wizhelp >>dlb.lst + echo dungeon >>dlb.lst + echo license >>dlb.lst + for %%N in (*.lev) do echo %%N >>dlb.lst + $(U)dlb_main cIf dlb.lst $(SRC)\nhdat + cd $(SRC) + +#========================================== +# Recover Utility +#========================================== + +$(U)recover.exe: $(RECOVOBJS) + @$(link) $(LFLAGSU) -out:$@ $(RECOVOBJS) + +$(O)recover.o: $(CONFIG_H) $(U)recover.c $(INCL)\win32api.h + @$(CC) $(CFLAGSU) -Fo$@ $(U)recover.c + +#========================================== +# Tile Mapping +#========================================== + +$(SRC)\tile.c: $(U)tilemap.exe + @echo A new $@ has been created + @$(U)tilemap + +$(U)tilemap.exe: $(O)tilemap.o + @$(link) $(LFLAGSU) -out:$@ $(O)tilemap.o + +$(O)tilemap.o: $(WSHR)\tilemap.c $(HACK_H) + @$(CC) $(CFLAGSU) -Fo$@ $(WSHR)\tilemap.c + +$(O)tiletx32.o: $(WSHR)\tilemap.c $(HACK_H) + @$(CC) $(CFLAGS) /DTILETEXT /DTILE_X=32 /DTILE_Y=32 -Fo$@ $(WSHR)\tilemap.c + +$(O)tiletxt.o: $(WSHR)\tilemap.c $(HACK_H) + @$(CC) $(CFLAGS) /DTILETEXT -Fo$@ $(WSHR)\tilemap.c + +$(O)gifread.o: $(WSHR)\gifread.c $(CONFIG_H) $(TILE_H) + @$(CC) $(CFLAGS) -I$(WSHR) -Fo$@ $(WSHR)\gifread.c + +$(O)gifrd32.o: $(WSHR)\gifread.c $(CONFIG_H) $(TILE_H) + @$(CC) $(CFLAGS) -I$(WSHR) /DTILE_X=32 /DTILE_Y=32 -Fo$@ $(WSHR)\gifread.c + +$(O)ppmwrite.o: $(WSHR)\ppmwrite.c $(CONFIG_H) $(TILE_H) + @$(CC) $(CFLAGS) -I$(WSHR) -Fo$@ $(WSHR)\ppmwrite.c + +$(O)tiletext.o: $(WSHR)\tiletext.c $(CONFIG_H) $(TILE_H) + @$(CC) $(CFLAGS) -I$(WSHR) -Fo$@ $(WSHR)\tiletext.c + +$(O)tilete32.o: $(WSHR)\tiletext.c $(CONFIG_H) $(TILE_H) + @$(CC) $(CFLAGS) -I$(WSHR) /DTILE_X=32 /DTILE_Y=32 -Fo$@ $(WSHR)\tiletext.c + +#========================================== +# Optional Tile Utilities +#========================================== + +$(U)gif2txt.exe: $(GIFREADERS) $(TEXT_IO) + @echo Linking $@... + @$(link) $(LFLAGSU) -out:$@ @<<$(@B).lnk + $(GIFREADERS:^ =^ + ) + $(TEXT_IO:^ =^ + ) +<< + +$(U)gif2tx32.exe: $(GIFREADERS32) $(TEXT_IO32) + @echo Linking $@... + @$(link) $(LFLAGSU) -out:$@ @<<$(@B).lnk + $(GIFREADERS32:^ =^ + ) + $(TEXT_IO32:^ =^ + ) +<< + +$(U)txt2ppm.exe: $(PPMWRITERS) $(TEXT_IO) + @echo Linking $@... + @$(link) $(LFLAGSU) -out:$@ @<<$(@B).lnk + $(PPMWRITERS:^ =^ + ) + $(TEXT_IO:^ =^ + ) +<< + +!IF "$(GRAPHICAL)"=="Y" +$(TILEBMP16): $(TILEUTIL16) $(TILEFILES) + @echo Creating 16x16 binary tile files (this may take some time) + @$(U)tile2bmp $(TILEBMP16) +#$(TILEBMP32): $(TILEUTIL32) $(TILEFILES32) +# @echo Creating 32x32 binary tile files (this may take some time) +# @$(U)til2bm32 $(TILEBMP32) + +!ELSE +$(TILEBMP16): +$(TILEBMP32): +!ENDIF + +$(U)tile2bmp.exe: $(O)tile2bmp.o $(TEXT_IO) + @echo Linking $@... + @$(link) $(LFLAGSU) -out:$@ @<<$(@B).lnk + $(O)tile2bmp.o + $(TEXT_IO:^ =^ + ) +<< + +$(U)til2bm32.exe: $(O)til2bm32.o $(TEXT_IO32) + @echo Linking $@... + @$(link) $(LFLAGSU) -out:$@ @<<$(@B).lnk + $(O)til2bm32.o + $(TEXT_IO32:^ =^ + ) +<< + +$(O)tile2bmp.o: $(WSHR)\tile2bmp.c $(HACK_H) $(TILE_H) $(INCL)\win32api.h + @$(CC) $(CFLAGS) -I$(WSHR) /DPACKED_FILE /Fo$@ $(WSHR)\tile2bmp.c + +$(O)til2bm32.o: $(WSHR)\tile2bmp.c $(HACK_H) $(TILE_H) $(INCL)\win32api.h + @$(CC) $(CFLAGS) -I$(WSHR) /DPACKED_FILE /DTILE_X=32 /DTILE_Y=32 /Fo$@ $(WSHR)\tile2bmp.c + +#========================================== +# Housekeeping +#========================================== + +spotless: clean +! IF ("$(OBJ)"!="") + -rmdir $(OBJ) /s /Q +! ENDIF + if exist $(INCL)\date.h del $(INCL)\date.h + if exist $(INCL)\onames.h del $(INCL)\onames.h + if exist $(INCL)\pm.h del $(INCL)\pm.h + if exist $(INCL)\vis_tab.h del $(INCL)\vis_tab.h + if exist $(SRC)\vis_tab.c del $(SRC)\vis_tab.c + if exist $(SRC)\tile.c del $(SRC)\tile.c + if exist $(U)*.lnk del $(U)*.lnk + if exist $(U)*.map del $(U)*.map + if exist $(DAT)\data del $(DAT)\data + if exist $(DAT)\rumors del $(DAT)\rumors + if exist $(DAT)\???-fil?.lev del $(DAT)\???-fil?.lev + if exist $(DAT)\???-goal.lev del $(DAT)\???-goal.lev + if exist $(DAT)\???-loca.lev del $(DAT)\???-loca.lev + if exist $(DAT)\???-strt.lev del $(DAT)\???-strt.lev + if exist $(DAT)\air.lev del $(DAT)\air.lev + if exist $(DAT)\asmodeus.lev del $(DAT)\asmodeus.lev + if exist $(DAT)\astral.lev del $(DAT)\astral.lev + if exist $(DAT)\baalz.lev del $(DAT)\baalz.lev + if exist $(DAT)\bigroom.lev del $(DAT)\bigroom.lev + if exist $(DAT)\castle.lev del $(DAT)\castle.lev + if exist $(DAT)\data del $(DAT)\data + if exist $(DAT)\dungeon del $(DAT)\dungeon + if exist $(DAT)\dungeon.pdf del $(DAT)\dungeon.pdf + if exist $(DAT)\earth.lev del $(DAT)\earth.lev + if exist $(DAT)\fakewiz?.lev del $(DAT)\fakewiz?.lev + if exist $(DAT)\fire.lev del $(DAT)\fire.lev + if exist $(DAT)\juiblex.lev del $(DAT)\juiblex.lev + if exist $(DAT)\knox.lev del $(DAT)\knox.lev + if exist $(DAT)\medusa-?.lev del $(DAT)\medusa-?.lev + if exist $(DAT)\mine*.lev del $(DAT)\mine*.lev + if exist $(DAT)\options del $(DAT)\options + if exist $(DAT)\ttyoptions del $(DAT)\ttyoptions + if exist $(DAT)\guioptions del $(DAT)\guioptions + if exist $(DAT)\oracle.lev del $(DAT)\oracle.lev + if exist $(DAT)\oracles del $(DAT)\oracles + if exist $(DAT)\orcus.lev del $(DAT)\orcus.lev + if exist $(DAT)\rumors del $(DAT)\rumors + if exist $(DAT)\quest.dat del $(DAT)\quest.dat + if exist $(DAT)\sanctum.lev del $(DAT)\sanctum.lev + if exist $(DAT)\soko?-?.lev del $(DAT)\soko?-?.lev + if exist $(DAT)\tower?.lev del $(DAT)\tower?.lev + if exist $(DAT)\valley.lev del $(DAT)\valley.lev + if exist $(DAT)\water.lev del $(DAT)\water.lev + if exist $(DAT)\wizard?.lev del $(DAT)\wizard?.lev + if exist $(O)sp_lev.tag del $(O)sp_lev.tag + if exist $(SRC)\monstr.c del $(SRC)\monstr.c + if exist $(SRC)\vis_tab.c del $(SRC)\vis_tab.c + if exist $(U)recover.exe del $(U)recover.exe + if exist nhdat. del nhdat. + +clean: + if exist $(O)*.o del $(O)*.o + if exist $(O)utility.tag del $(O)utility.tag + if exist $(U)makedefs.exe del $(U)makedefs.exe + if exist $(U)lev_comp.exe del $(U)lev_comp.exe + if exist $(U)dgn_comp.exe del $(U)dgn_comp.exe + if exist $(SRC)\*.lnk del $(SRC)\*.lnk + if exist $(SRC)\*.map del $(SRC)\*.map +! IF ("$(WINPFLAG)"!="") + if exist $(TILEBMP16) del $(TILEBMP16) + if exist $(TILEBMP32) del $(TILEBMP32) +! ENDIF + +#=================================================================== +# OTHER DEPENDENCIES +#=================================================================== + +# +# dat dependencies +# + +$(DAT)\data: $(O)utility.tag $(DATABASE) + $(U)makedefs -d + +$(DAT)\rumors: $(O)utility.tag $(DAT)\rumors.tru $(DAT)\rumors.fal + $(U)makedefs -r + +$(DAT)\quest.dat: $(O)utility.tag $(DAT)\quest.txt + $(U)makedefs -q + +$(DAT)\oracles: $(O)utility.tag $(DAT)\oracles.txt + $(U)makedefs -h + +$(DAT)\dungeon: $(O)utility.tag $(DAT)\dungeon.def + $(U)makedefs -e + cd $(DAT) + $(U)dgn_comp dungeon.pdf + cd $(SRC) + +# +# NT dependencies +# + +$(O)nttty.o: $(HACK_H) $(TILE_H) $(INCL)\win32api.h $(NTSYS)\nttty.c + @$(CC) $(CFLAGS) -I$(WSHR) -Fo$@ $(NTSYS)\nttty.c +$(O)winnt.o: $(HACK_H) $(INCL)\win32api.h $(NTSYS)\winnt.c + @$(CC) $(CFLAGS) -Fo$@ $(NTSYS)\winnt.c +$(O)ntsound.o: $(HACK_H) $(NTSYS)\ntsound.c + @$(CC) $(CFLAGS) -Fo$@ $(NTSYS)\ntsound.c +$(O)mapimail.o: $(HACK_H) $(INCL)\nhlan.h $(NTSYS)\mapimail.c + @$(CC) $(CFLAGS) -DMAPI_VERBOSE -Fo$@ $(NTSYS)\mapimail.c + +# +# util dependencies +# + +$(O)panic.o: $(U)panic.c $(CONFIG_H) + @$(CC) $(CFLAGS) -Fo$@ $(U)panic.c + +# +# The rest are stolen from sys/unix/Makefile.src, +# with slashes changed to back-slashes +# and -c (which is included in CFLAGS) substituted +# with -Fo$@ , but otherwise untouched. That +# means that there is some irrelevant stuff +# in here, but maintenance should be easier. +# +$(O)tos.o: ..\sys\atari\tos.c $(HACK_H) $(INCL)\tcap.h + $(CC) $(CFLAGS) -Fo$@ ..\sys\atari\tos.c +$(O)pcmain.o: ..\sys\share\pcmain.c $(HACK_H) $(INCL)\dlb.h \ + $(INCL)\win32api.h + $(CC) $(CFLAGS) -Fo$@ ..\sys\share\pcmain.c +$(O)pcsys.o: ..\sys\share\pcsys.c $(HACK_H) + $(CC) $(CFLAGS) -Fo$@ ..\sys\share\pcsys.c +$(O)pctty.o: ..\sys\share\pctty.c $(HACK_H) + $(CC) $(CFLAGS) -Fo$@ ..\sys\share\pctty.c +$(O)pcunix.o: ..\sys\share\pcunix.c $(HACK_H) + $(CC) $(CFLAGS) -Fo$@ ..\sys\share\pcunix.c +$(O)random.o: ..\sys\share\random.c $(HACK_H) + $(CC) $(CFLAGS) -Fo$@ ..\sys\share\random.c +$(O)ioctl.o: ..\sys\share\ioctl.c $(HACK_H) $(INCL)\tcap.h + $(CC) $(CFLAGS) -Fo$@ ..\sys\share\ioctl.c +$(O)unixtty.o: ..\sys\share\unixtty.c $(HACK_H) + $(CC) $(CFLAGS) -Fo$@ ..\sys\share\unixtty.c +$(O)unixmain.o: ..\sys\unix\unixmain.c $(HACK_H) $(INCL)\dlb.h + $(CC) $(CFLAGS) -Fo$@ ..\sys\unix\unixmain.c +$(O)unixunix.o: ..\sys\unix\unixunix.c $(HACK_H) + $(CC) $(CFLAGS) -Fo$@ ..\sys\unix\unixunix.c +$(O)bemain.o: ..\sys\be\bemain.c $(HACK_H) $(INCL)\dlb.h + $(CC) $(CFLAGS) -Fo$@ ..\sys\be\bemain.c +$(O)getline.o: ..\win\tty\getline.c $(HACK_H) $(INCL)\func_tab.h + $(CC) $(CFLAGS) -Fo$@ ..\win\tty\getline.c +$(O)termcap.o: ..\win\tty\termcap.c $(HACK_H) $(INCL)\tcap.h + $(CC) $(CFLAGS) -Fo$@ ..\win\tty\termcap.c +$(O)topl.o: ..\win\tty\topl.c $(HACK_H) $(INCL)\tcap.h + $(CC) $(CFLAGS) -Fo$@ ..\win\tty\topl.c +$(O)wintty.o: ..\win\tty\wintty.c $(HACK_H) $(INCL)\dlb.h \ + $(INCL)\patchlevel.h $(INCL)\tcap.h + $(CC) $(CFLAGS) -Fo$@ ..\win\tty\wintty.c +$(O)Window.o: ..\win\X11\Window.c $(INCL)\xwindowp.h $(INCL)\xwindow.h \ + $(CONFIG_H) + $(CC) $(CFLAGS) -Fo$@ ..\win\X11\Window.c +$(O)dialogs.o: ..\win\X11\dialogs.c $(CONFIG_H) + $(CC) $(CFLAGS) -Fo$@ ..\win\X11\dialogs.c +$(O)winX.o: ..\win\X11\winX.c $(HACK_H) $(INCL)\winX.h $(INCL)\dlb.h \ + $(INCL)\patchlevel.h ..\win\X11\nh72icon \ + ..\win\X11\nh56icon ..\win\X11\nh32icon + $(CC) $(CFLAGS) -Fo$@ ..\win\X11\winX.c +$(O)winmap.o: ..\win\X11\winmap.c $(INCL)\xwindow.h $(HACK_H) $(INCL)\dlb.h \ + $(INCL)\winX.h $(INCL)\tile2x11.h + $(CC) $(CFLAGS) -Fo$@ ..\win\X11\winmap.c +$(O)winmenu.o: ..\win\X11\winmenu.c $(HACK_H) $(INCL)\winX.h + $(CC) $(CFLAGS) -Fo$@ ..\win\X11\winmenu.c +$(O)winmesg.o: ..\win\X11\winmesg.c $(INCL)\xwindow.h $(HACK_H) $(INCL)\winX.h + $(CC) $(CFLAGS) -Fo$@ ..\win\X11\winmesg.c +$(O)winmisc.o: ..\win\X11\winmisc.c $(HACK_H) $(INCL)\func_tab.h \ + $(INCL)\winX.h + $(CC) $(CFLAGS) -Fo$@ ..\win\X11\winmisc.c +$(O)winstat.o: ..\win\X11\winstat.c $(HACK_H) $(INCL)\winX.h + $(CC) $(CFLAGS) -Fo$@ ..\win\X11\winstat.c +$(O)wintext.o: ..\win\X11\wintext.c $(HACK_H) $(INCL)\winX.h $(INCL)\xwindow.h + $(CC) $(CFLAGS) -Fo$@ ..\win\X11\wintext.c +$(O)winval.o: ..\win\X11\winval.c $(HACK_H) $(INCL)\winX.h + $(CC) $(CFLAGS) -Fo$@ ..\win\X11\winval.c +$(O)tile.o: $(SRC)\tile.c $(HACK_H) +$(O)gnaskstr.o: ..\win\gnome\gnaskstr.c ..\win\gnome\gnaskstr.h \ + ..\win\gnome\gnmain.h + $(CC) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnaskstr.c +$(O)gnbind.o: ..\win\gnome\gnbind.c ..\win\gnome\gnbind.h ..\win\gnome\gnmain.h \ + ..\win\gnome\gnaskstr.h ..\win\gnome\gnyesno.h + $(CC) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnbind.c +$(O)gnglyph.o: ..\win\gnome\gnglyph.c ..\win\gnome\gnglyph.h + $(CC) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnglyph.c +$(O)gnmain.o: ..\win\gnome\gnmain.c ..\win\gnome\gnmain.h ..\win\gnome\gnsignal.h \ + ..\win\gnome\gnbind.h ..\win\gnome\gnopts.h $(HACK_H) \ + $(INCL)\date.h + $(CC) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnmain.c +$(O)gnmap.o: ..\win\gnome\gnmap.c ..\win\gnome\gnmap.h ..\win\gnome\gnglyph.h \ + ..\win\gnome\gnsignal.h $(HACK_H) + $(CC) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnmap.c +$(O)gnmenu.o: ..\win\gnome\gnmenu.c ..\win\gnome\gnmenu.h ..\win\gnome\gnmain.h \ + ..\win\gnome\gnbind.h + $(CC) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnmenu.c +$(O)gnmesg.o: ..\win\gnome\gnmesg.c ..\win\gnome\gnmesg.h ..\win\gnome\gnsignal.h + $(CC) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnmesg.c +$(O)gnopts.o: ..\win\gnome\gnopts.c ..\win\gnome\gnopts.h ..\win\gnome\gnglyph.h \ + ..\win\gnome\gnmain.h ..\win\gnome\gnmap.h $(HACK_H) + $(CC) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnopts.c +$(O)gnplayer.o: ..\win\gnome\gnplayer.c ..\win\gnome\gnplayer.h \ + ..\win\gnome\gnmain.h $(HACK_H) + $(CC) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnplayer.c +$(O)gnsignal.o: ..\win\gnome\gnsignal.c ..\win\gnome\gnsignal.h \ + ..\win\gnome\gnmain.h + $(CC) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnsignal.c +$(O)gnstatus.o: ..\win\gnome\gnstatus.c ..\win\gnome\gnstatus.h \ + ..\win\gnome\gnsignal.h ..\win\gnome\gn_xpms.h \ + ..\win\gnome\gnomeprv.h + $(CC) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnstatus.c +$(O)gntext.o: ..\win\gnome\gntext.c ..\win\gnome\gntext.h ..\win\gnome\gnmain.h \ + ..\win\gnome\gn_rip.h + $(CC) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gntext.c +$(O)gnyesno.o: ..\win\gnome\gnyesno.c ..\win\gnome\gnbind.h ..\win\gnome\gnyesno.h + $(CC) $(CFLAGS) $(GNOMEINC) -c ..\win\gnome\gnyesno.c +$(O)wingem.o: ..\win\gem\wingem.c $(HACK_H) $(INCL)\func_tab.h $(INCL)\dlb.h \ + $(INCL)\patchlevel.h $(INCL)\wingem.h + $(CC) $(CFLAGS) -Fo$@ ..\win\gem\wingem.c +$(O)wingem1.o: ..\win\gem\wingem1.c $(INCL)\gem_rsc.h $(INCL)\load_img.h \ + $(INCL)\wintype.h $(INCL)\wingem.h + $(CC) $(CFLAGS) -Fo$@ ..\win\gem\wingem1.c +$(O)load_img.o: ..\win\gem\load_img.c $(INCL)\load_img.h + $(CC) $(CFLAGS) -Fo$@ ..\win\gem\load_img.c +$(O)tile.o: tile.c $(HACK_H) +$(O)qt_win.o: ..\win\Qt\qt_win.cpp $(HACK_H) $(INCL)\func_tab.h \ + $(INCL)\dlb.h $(INCL)\patchlevel.h $(INCL)\qt_win.h \ + $(INCL)\qt_clust.h $(INCL)\qt_kde0.h \ + $(INCL)\qt_xpms.h qt_win.moc qt_kde0.moc + $(CXX) $(CXXFLAGS) -c ..\win\Qt\qt_win.cpp +$(O)qt_clust.o: ..\win\Qt\qt_clust.cpp $(INCL)\qt_clust.h + $(CXX) $(CXXFLAGS) -c ..\win\Qt\qt_clust.cpp +$(O)monstr.o: $(SRC)\monstr.c $(CONFIG_H) +$(O)vis_tab.o: $(SRC)\vis_tab.c $(CONFIG_H) $(INCL)\vis_tab.h +$(O)allmain.o: allmain.c $(HACK_H) +$(O)alloc.o: alloc.c $(CONFIG_H) +$(O)apply.o: apply.c $(HACK_H) $(INCL)\edog.h +$(O)artifact.o: artifact.c $(HACK_H) $(INCL)\artifact.h $(INCL)\artilist.h +$(O)attrib.o: attrib.c $(HACK_H) $(INCL)\artifact.h +$(O)ball.o: ball.c $(HACK_H) +$(O)bones.o: bones.c $(HACK_H) $(INCL)\lev.h +$(O)botl.o: botl.c $(HACK_H) +$(O)cmd.o: cmd.c $(HACK_H) $(INCL)\func_tab.h +$(O)dbridge.o: dbridge.c $(HACK_H) +$(O)decl.o: decl.c $(HACK_H) +$(O)detect.o: detect.c $(HACK_H) $(INCL)\artifact.h +$(O)dig.o: dig.c $(HACK_H) $(INCL)\edog.h +$(O)display.o: display.c $(HACK_H) +$(O)dlb.o: dlb.c $(CONFIG_H) $(INCL)\dlb.h +$(O)do.o: do.c $(HACK_H) $(INCL)\lev.h +$(O)do_name.o: do_name.c $(HACK_H) +$(O)do_wear.o: do_wear.c $(HACK_H) +$(O)dog.o: dog.c $(HACK_H) $(INCL)\edog.h +$(O)dogmove.o: dogmove.c $(HACK_H) $(INCL)\mfndpos.h $(INCL)\edog.h +$(O)dokick.o: dokick.c $(HACK_H) $(INCL)\eshk.h +$(O)dothrow.o: dothrow.c $(HACK_H) +$(O)drawing.o: drawing.c $(HACK_H) $(INCL)\tcap.h +$(O)dungeon.o: dungeon.c $(HACK_H) $(INCL)\dgn_file.h $(INCL)\dlb.h +$(O)eat.o: eat.c $(HACK_H) +$(O)end.o: end.c $(HACK_H) $(INCL)\eshk.h $(INCL)\dlb.h +$(O)engrave.o: engrave.c $(HACK_H) $(INCL)\lev.h +$(O)exper.o: exper.c $(HACK_H) +$(O)explode.o: explode.c $(HACK_H) +$(O)extralev.o: extralev.c $(HACK_H) +$(O)files.o: files.c $(HACK_H) $(INCL)\dlb.h +$(O)fountain.o: fountain.c $(HACK_H) +$(O)hack.o: hack.c $(HACK_H) +$(O)hacklib.o: hacklib.c $(HACK_H) +$(O)invent.o: invent.c $(HACK_H) $(INCL)\artifact.h +$(O)light.o: light.c $(HACK_H) $(INCL)\lev.h +$(O)lock.o: lock.c $(HACK_H) +$(O)mail.o: mail.c $(HACK_H) $(INCL)\mail.h +$(O)makemon.o: makemon.c $(HACK_H) $(INCL)\epri.h $(INCL)\emin.h \ + $(INCL)\edog.h +$(O)mapglyph.o: mapglyph.c $(HACK_H) +$(O)mcastu.o: mcastu.c $(HACK_H) +$(O)mhitm.o: mhitm.c $(HACK_H) $(INCL)\artifact.h $(INCL)\edog.h +$(O)mhitu.o: mhitu.c $(HACK_H) $(INCL)\artifact.h $(INCL)\edog.h +$(O)minion.o: minion.c $(HACK_H) $(INCL)\emin.h $(INCL)\epri.h +$(O)mklev.o: mklev.c $(HACK_H) +$(O)mkmap.o: mkmap.c $(HACK_H) $(INCL)\sp_lev.h +$(O)mkmaze.o: mkmaze.c $(HACK_H) $(INCL)\sp_lev.h $(INCL)\lev.h +$(O)mkobj.o: mkobj.c $(HACK_H) $(INCL)\artifact.h +$(O)mkroom.o: mkroom.c $(HACK_H) +$(O)mon.o: mon.c $(HACK_H) $(INCL)\mfndpos.h $(INCL)\edog.h +$(O)mondata.o: mondata.c $(HACK_H) $(INCL)\eshk.h $(INCL)\epri.h +$(O)monmove.o: monmove.c $(HACK_H) $(INCL)\mfndpos.h $(INCL)\artifact.h +$(O)monst.o: monst.c $(CONFIG_H) $(INCL)\permonst.h $(INCL)\align.h \ + $(INCL)\monattk.h $(INCL)\monflag.h $(INCL)\monsym.h \ + $(INCL)\dungeon.h $(INCL)\eshk.h $(INCL)\vault.h \ + $(INCL)\epri.h $(INCL)\color.h +$(O)mplayer.o: mplayer.c $(HACK_H) +$(O)mthrowu.o: mthrowu.c $(HACK_H) +$(O)muse.o: muse.c $(HACK_H) $(INCL)\edog.h +$(O)music.o: music.c $(HACK_H) #interp.c +$(O)o_init.o: o_init.c $(HACK_H) $(INCL)\lev.h +$(O)objects.o: objects.c $(CONFIG_H) $(INCL)\obj.h $(INCL)\objclass.h \ + $(INCL)\prop.h $(INCL)\skills.h $(INCL)\color.h +$(O)objnam.o: objnam.c $(HACK_H) +$(O)options.o: options.c $(CONFIG_H) $(INCL)\objclass.h $(INCL)\flag.h \ + $(HACK_H) $(INCL)\tcap.h +$(O)pager.o: pager.c $(HACK_H) $(INCL)\dlb.h +$(O)pickup.o: pickup.c $(HACK_H) +$(O)pline.o: pline.c $(HACK_H) $(INCL)\epri.h $(INCL)\edog.h +$(O)polyself.o: polyself.c $(HACK_H) +$(O)potion.o: potion.c $(HACK_H) +$(O)pray.o: pray.c $(HACK_H) $(INCL)\epri.h +$(O)priest.o: priest.c $(HACK_H) $(INCL)\mfndpos.h $(INCL)\eshk.h \ + $(INCL)\epri.h $(INCL)\emin.h +$(O)quest.o: quest.c $(HACK_H) $(INCL)\qtext.h +$(O)questpgr.o: questpgr.c $(HACK_H) $(INCL)\dlb.h $(INCL)\qtext.h +$(O)read.o: read.c $(HACK_H) +$(O)rect.o: rect.c $(HACK_H) +$(O)region.o: region.c $(HACK_H) $(INCL)\lev.h +$(O)restore.o: restore.c $(HACK_H) $(INCL)\lev.h $(INCL)\tcap.h +$(O)rip.o: rip.c $(HACK_H) +$(O)rnd.o: rnd.c $(HACK_H) +$(O)role.o: role.c $(HACK_H) +$(O)rumors.o: rumors.c $(HACK_H) $(INCL)\lev.h $(INCL)\dlb.h +$(O)save.o: save.c $(HACK_H) $(INCL)\lev.h +$(O)shk.o: shk.c $(HACK_H) $(INCL)\eshk.h +$(O)shknam.o: shknam.c $(HACK_H) $(INCL)\eshk.h +$(O)sit.o: sit.c $(HACK_H) $(INCL)\artifact.h +$(O)sounds.o: sounds.c $(HACK_H) $(INCL)\edog.h +$(O)sp_lev.o: sp_lev.c $(HACK_H) $(INCL)\dlb.h $(INCL)\sp_lev.h +$(O)spell.o: spell.c $(HACK_H) +$(O)steal.o: steal.c $(HACK_H) +$(O)steed.o: steed.c $(HACK_H) +$(O)teleport.o: teleport.c $(HACK_H) +$(O)timeout.o: timeout.c $(HACK_H) $(INCL)\lev.h +$(O)topten.o: topten.c $(HACK_H) $(INCL)\dlb.h $(INCL)\patchlevel.h +$(O)track.o: track.c $(HACK_H) +$(O)trap.o: trap.c $(HACK_H) +$(O)u_init.o: u_init.c $(HACK_H) +$(O)uhitm.o: uhitm.c $(HACK_H) +$(O)vault.o: vault.c $(HACK_H) $(INCL)\vault.h +$(O)version.o: version.c $(HACK_H) $(INCL)\date.h $(INCL)\patchlevel.h +$(O)vision.o: vision.c $(HACK_H) $(INCL)\vis_tab.h +$(O)weapon.o: weapon.c $(HACK_H) +$(O)were.o: were.c $(HACK_H) +$(O)wield.o: wield.c $(HACK_H) +$(O)windows.o: windows.c $(HACK_H) $(INCL)\wingem.h $(INCL)\winGnome.h +$(O)wizard.o: wizard.c $(HACK_H) $(INCL)\qtext.h +$(O)worm.o: worm.c $(HACK_H) $(INCL)\lev.h +$(O)worn.o: worn.c $(HACK_H) +$(O)write.o: write.c $(HACK_H) +$(O)zap.o: zap.c $(HACK_H) + +# end of file + diff --git a/sys/winnt/console.rc b/sys/winnt/console.rc new file mode 100644 index 0000000..7081488 --- /dev/null +++ b/sys/winnt/console.rc @@ -0,0 +1,11 @@ +/* SCCS Id: @(#)console.rc 3.4 2002/02/14 */ +/* Copyright (c) Yitzhak Sapir, 2002. */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "windows.h" + +1 ICON DISCARDABLE "NetHack.ICO" + + +/*console.rc*/ + diff --git a/sys/winnt/defaults.nh b/sys/winnt/defaults.nh new file mode 100644 index 0000000..32e057c --- /dev/null +++ b/sys/winnt/defaults.nh @@ -0,0 +1,145 @@ +# Sample config file for win32 NetHack +# A '#' at the beginning of a line means the rest of the line is a comment. +# +# Some options MUST be set in this file, other options can be toggled while +# playing. For a list of options available see the file. +# +# To change the configuration, comment out the unwanted lines, and +# uncomment the configuration you want. + +# *** OPTIONS *** +# +# Use the IBM character set rather than just plain ascii characters +# for tty window-port. +OPTIONS=IBMGraphics + +# *** Personal Preferences *** +# Some options to set personal preferences. Uncomment and change these to +# suit your personal preference. If several people are to use the same +# configuration, options like these should not be set. +# +#OPTIONS=name:Janet,role:Valkyrie,race:Human,gender:female,align:lawful +#OPTIONS=dogname:Fido,catname:Morris,fruit:guava +#OPTIONS=horsename:Silver +#OPTIONS=autopickup,pickup_types:$"=/!?+ +#OPTIONS=packorder:")[%?+/=!(*0_` +#OPTIONS=scores:10 top/2 around/own +#OPTIONS=nolegacy,noverbose +#OPTIONS=menustyle:traditional + +# +# General options. You might also set "silent" so as not to attract +# the boss's attention. +# +OPTIONS=time,noshowexp,number_pad,lit_corridor,rest_on_space +# +# If you want to get rid of "use #quit to quit..." use: +#OPTIONS=suppress_alert:3.3.1 +# +# Set some options to control graphical window-port (these will +# be safely and silently ignored by the tty port) +# +# Map window settings +# possible map_mode options include: tiles|ascii4x6|ascii6x8|ascii8x8|ascii16x8| +# ascii7x12|ascii8x12|ascii16x12|ascii12x16| +# ascii10x18|fit_to_screen +OPTIONS=map_mode:tiles,scroll_margin:5 + +# Message window settings +OPTIONS=font_message:Arial,font_size_message:9,align_message:top + +# Menu settings +OPTIONS=font_menu:Arial,font_size_menu:9 + +# Text settings +OPTIONS=font_text:Courier New,font_size_text:9 + +# Status window settings +OPTIONS=font_status:Courier New,font_size_status:10 + +# Other +OPTIONS=hilite_pet,!toptenwin +#OPTIONS=!splash_screen,player_selection:prompts + +# Status/message window colors +# Possible color options include: +# six digit hexadecimal RGB color value ("#8F8F8F"), black, red, green, brown, +# blue, magenta, cyan, gray (or grey), orange, brightgreen, yellow, brightblue, +# brightmagenta, brightcyan, white, trueblack, purple, silver, maroon, fuchsia, +# lime, olive, navy, teal, aqua, activeborder, activecaption, appworkspace, +# background, btnface, btnshadow, btntext, captiontext, graytext, highlight, +# highlighttext, inactiveborder, inactivecaption, menu, menutext, scrollbar, +# window, windowframe, windowtext. +#OPTIONS=windowcolors:status windowtext/window message windowtext/window + +# +#HACKDIR=c:\games\nethack +# +# Note: On Windows HACKDIR defaults to the location +# of the NetHack.exe or NetHackw.exe file. +# Setting HACKDIR above will override that. +# +# LEVELS and SAVE default to HACKDIR +# +#LEVELS=c:\games\nethack\bones +#SAVE=c:\games\nethack\bones + +# *** CHARACTER GRAPHICS *** +# +# See the on-line help or the Guidebook for which symbols are in which +# positions. +# +# If you merely set the IBMgraphics option as above, NetHack will use IBM +# extended ASCII for dungeon characters. If you don't like the selections, +# you can make up your own via these graphics options, but you should still +# set IBMgraphics if you are using IBM graphics characters to get the correct +# processing. +# +# ================================================ +# An example using the IBM graphics character set: +#DUNGEON= 032 179 196 218 191 192 217 197 193 194 \ +# 180 195 249 239 239 254 254 240 241 249 \ +# 177 177 060 062 060 062 220 124 190 035 \ +# 244 247 249 247 042 042 186 205 046 035 \ +# 247 +# +#TRAPS= 094 094 094 094 094 094 094 094 094 094 \ +# 094 094 094 094 232 232 232 157 094 094 \ +# 094 094 +# +#EFFECTS= 179 196 092 047 042 033 041 040 \ +# 048 035 064 042 \ +# 047 045 092 058 058 092 045 047 \ +# 047 045 092 058 032 058 092 045 047 +# +# ================================================ +# Some alternatives: +#DUNGEON= 032 186 205 201 187 200 188 206 202 203 \ +# 185 204 249 239 239 254 254 240 241 249 \ +# 177 177 060 062 060 062 095 124 092 035 \ +# 244 247 249 247 042 042 179 196 046 035 \ +# 247 +# +#TRAPS= 094 094 094 094 094 094 094 094 094 094 \ +# 094 094 094 094 094 034 094 094 094 094 \ +# 094 094 + +# ================================================ +# Here is a recommendation sent in by Michael Feir +# for use by blind NetHack players. +# +#DUNGEON= 032 124 045 124 124 124 124 045 045 045 \ +# 124 124 046 045 124 043 043 046 035 035 \ +# 060 062 060 062 095 092 035 126 126 126 \ +# 126 042 042 035 035 032 035 126 +# +#TRAPS= 094 094 094 094 094 094 094 094 094 094 \ +# 094 094 094 094 094 094 094 094 094 094 \ +# 094 094 +# +#EFFECTS= 124 095 092 047 042 033 041 040 \ +# 048 035 064 042 \ +# 047 045 092 058 058 092 045 047 \ +# 047 045 092 058 032 058 092 045 047 + + diff --git a/sys/winnt/mapimail.c b/sys/winnt/mapimail.c index b991644..95811d3 100644 --- a/sys/winnt/mapimail.c +++ b/sys/winnt/mapimail.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)mapimail.c 3.3 2000/04/25 */ +/* SCCS Id: @(#)mapimail.c 3.4 2000/04/25 */ /* Copyright (c) Michael Allison, 1997 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/winnt/nethack.def b/sys/winnt/nethack.def index ee27ed5..064a85a 100644 --- a/sys/winnt/nethack.def +++ b/sys/winnt/nethack.def @@ -1,5 +1,5 @@ NAME NETHACK -DESCRIPTION 'NetHack 3.3.0 for Windows NT' +DESCRIPTION 'NetHack 3.4.0 for Windows NT' EXETYPE WINDOWS STUB 'WINSTUB.EXE' CODE PRELOAD MOVEABLE DISCARDABLE diff --git a/sys/winnt/nhico.uu b/sys/winnt/nhico.uu index c2cfbef..b420c3c 100644 --- a/sys/winnt/nhico.uu +++ b/sys/winnt/nhico.uu @@ -1,25 +1,27 @@ -section 1 of uuencode 4.13 of file NETHACK.ICO by R.E.M. - -begin 644 NETHACK.ICO -M```!``$`("`0``````#H`@``%@```"@````@````0`````$`!```````@`(`. -M``````````````````````````````"```"`````@(``@````(``@`"`@```6 -M@("``,#`P````/\``/\```#__P#_````_P#_`/__``#___\`]F9F9F9F9F9F* -M9F9F9F9F9O]F9F9F9F9F9F9F9F9F9F;_B(B(B(B(B(B(B(B(B&9F_XB(B(B(D -MB(B(B(B(B(AF9O^(B(B(A555B(B(B(B(9F;_B(B(B`!5!8B(B(B(B&9F_XB(' -MB(@```6(B(B(B(AF9O^(B%554`!56(B(B(B(9F;_B(N[N[`.XU6(B(B(B&9F[ -M_XB[N[L`ONXU6(B(B(AF9O^+N[N[N[ONXUB(B(B(9F;_B[N[N[N[ONY3B(B(N -MB&9F_XN[NYF9F[ONXSB(B(AF9O^+N[F9F9F[ONXSB(B(9F;_B[N9F9F9F[ON? -MXSB(B&9F_XNYF9F9F9F[7NXSB(AF9O^+N9F9F9F9NUCNXSB(9F;_B[F9F9F9J -MF;M8CNXSB&9F_XNYF9F9F9F[6(CNXXAF9O^+N9F9F9F9NUB(CNZ(9F;_B[N9] -MF9F9F[M8B(CNB&9F_XN[N9F9F;N[6(B(B(AF9O^+N[N9F9N[NUB(B(B(9F;_R -MB[N[N[N[N[M8B(B(B&9F_XN[N[N[N[N[B(B(B(AF9O^+NXB(B(B+NXB(B(B(F -M9F;_B[B(B(B(B+N(B(B(B&9F_XB(B(B(B(B(B(B(B(AF9O^(B(B(B(B(B(B(J -MB(B(9F;_B(B(B(B(B(B(B(B(B&9F___________________V9O__________% -M__________\`````````````````````````````````````````````````R -M````````````````````````````````````````````````````````````` -M````````````````````````````````````````````````````````````` -!````` -`` +begin 600 nethack.ico +M```!``(`("`0``````#H`@``)@```!`0$```````*`$```X#```H````(``` +M`$`````!``0``````(`"````````````````````````````````@```@``` +M`("``(````"``(``@(```,#`P`"`@(````#_``#_````__\`_P```/\`_P#_ +M_P``____````````````````````````__=P```````````'=W<`#___=P`` +M````````?_?W<`]W:/=P``#_<```!WB'!G`/8'B'<``/_W<```?VAGAP#P=E +M;W``__]W<``'>`=H\`__=G_P#_!V9_<`!W=H=W``__(:/<`=P=W<` +M``__\`_W=G9GB'<`!W=P````__#_=G=X2&"/<`=W``````_P_\=T=F>(:/<' +M<```````#_9V=V5H8(AO<`````````_W=W1WAXAHA_````````#_9\<&>&!H +M!H9W````````_W=V=6=GAH@(]P``````#_?'9W9T:(!H:&=P``````_V=WQV +M=X=HA@B/<``````/]GQP=G>':(A@AW``````#_<'9\=VAH!HB&=P``````_V +M=G=X9V>&"&"'<``````/]W?'9W1@B(:(9W````^&C_?'9W1WAX:`8(=P`'`/ +M_X_P9W9W:&A@AH:''AH@(AW!W\`=H;_9V=G!H:&"&A@=P +M`(`'B(_P<'!V<&>(:(B'<`"`#_\/______=W=W=W=W!W<`__#_____?_?W=W +M=W=P=W`/``__#___]W=W=W!W<`!P```/\`#_]_]_=W<`!W``````#P```/_W +M=W<```!P```````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````H````$````"`````!``0``````,`````````` +M````````````````````````@```@````("``(````"``(``@(```,#`P`"` +M@(````#_``#_````__\`_P```/\`_P#__P``____`````````````/<````` +M=P`/_W`/<`=W<`#_\/8'!W<```\/9F!P<````/9F!@<`````]F9@9P````]F +M9@8&<```#V9F8&!P```/9F8&!G````]F9F!@<``/?V9F!@9P<`]_9F9@8'!P +M#P___W=W<'``#P__=W!P```````````````````````````````````````` +K```````````````````````````````````````````````````````````` +` end -sum -r/size 23881/1107 section (from "begin" to "end") -sum -r/size 55184/766 entire input file diff --git a/sys/winnt/nhsetup.bat b/sys/winnt/nhsetup.bat index 8e2f0e8..55c82fd 100644 --- a/sys/winnt/nhsetup.bat +++ b/sys/winnt/nhsetup.bat @@ -1,64 +1,114 @@ -@REM SCCS Id: @(#)nhsetup.bat 96/10/30 -@REM Copyright (c) NetHack PC Development Team 1993, 1996 +@REM SCCS Id: @(#)nhsetup.bat 2002/03/07 +@REM Copyright (c) NetHack PC Development Team 1993, 1996, 2002 @REM NetHack may be freely redistributed. See license for details. @REM Win32 setup batch file, see Install.nt for details @REM @echo off + +set _pause= + +:nxtcheck echo Checking to see if directories are set up properly -if not exist ..\..\include\hack.h goto err_dir -if not exist ..\..\src\hack.c goto err_dir -if not exist ..\..\dat\wizard.des goto err_dir -if not exist ..\..\util\makedefs.c goto err_dir -if not exist ..\..\sys\winnt\winnt.c goto err_dir +if not exist ..\..\include\hack.h goto :err_dir +if not exist ..\..\src\hack.c goto :err_dir +if not exist ..\..\dat\wizard.des goto :err_dir +if not exist ..\..\util\makedefs.c goto :err_dir +if not exist ..\..\sys\winnt\winnt.c goto :err_dir echo Directories look ok. -:do_rest -echo "Copying Makefile.NT to ..\..\src\Makefile" -copy makefile.NT ..\..\src\Makefile >nul -echo Makefile copied ok. -if not exist ..\..\win\win32\NetHack.dsp goto nowin32 -echo "Copying Visual C project files to top level directory" -copy ..\..\win\win32\NetHack.rc ..\.. -copy ..\..\win\win32\resource.h ..\.. -copy ..\..\win\win32\NetHack.dsw ..\.. -copy ..\..\win\win32\NetHack.clw ..\.. -copy ..\..\win\win32\makedefs.dsp ..\.. -copy ..\..\win\win32\NetHack.dsp ..\.. -copy ..\..\win\win32\tile2bmp.dsp ..\.. -copy ..\..\win\win32\dgncomp.dsp ..\.. -copy ..\..\win\win32\levcomp.dsp ..\.. -copy ..\..\win\win32\dlb_main.dsp ..\.. -copy ..\..\win\win32\tilemap.dsp ..\.. -copy ..\..\win\win32\recover.dsp ..\.. +:do_tty +if NOT exist ..\..\binary\*.* mkdir ..\..\binary +if NOT exist ..\..\binary\license copy ..\..\dat\license ..\..\binary\license >nul +echo Copying Microsoft Makefile - Makefile.msc to ..\..\src\Makefile. +if NOT exist ..\..\src\Makefile goto :domsc +copy ..\..\src\Makefile ..\..\src\Makefile-orig >nul +echo Your existing +echo ..\..\src\Makefile +echo has been renamed to +echo ..\..\src\Makefile-orig +:domsc +copy Makefile.msc ..\..\src\Makefile >nul +echo Microsoft Makefile copied ok. -:nowin32 +echo Copying Borland Makefile - Makefile.bcc to ..\..\src\Makefile.bcc +if NOT exist ..\..\src\Makefile.bcc goto :dobor +copy ..\..\src\Makefile.bcc ..\..\src\Makefile.bcc-orig >nul +echo Your existing +echo ..\..\src\Makefile.bcc +echo has been renamed to +echo ..\..\src\Makefile.bcc-orig +:dobor +copy Makefile.bcc ..\..\src\Makefile.bcc >nul +echo Borland Makefile copied ok. -if exist .\nethack.ico goto hasicon -if exist .\nhico.uu uudecode nhico.uu >nul -if NOT exist .\nethack.ico goto err_nouu -:hasicon -echo NetHack icon exists ok. -echo done! -echo. -echo Proceed with the next step documented in Install.nt +echo Copying MinGW Makefile - Makefile.gcc to ..\..\src\Makefile.gcc +if NOT exist ..\..\src\Makefile.gcc goto :dogcc +copy ..\..\src\Makefile.gcc ..\..\src\Makefile.gcc-orig >nul +echo Your existing +echo ..\..\src\Makefile.gcc +echo has been renamed to +echo ..\..\src\Makefile.gcc-orig +:dogcc +copy Makefile.gcc ..\..\src\Makefile.gcc >nul +echo MinGW Makefile copied ok. + +:do_win +if not exist ..\..\win\win32\nethack.dsw goto :err_win echo. -goto done -:err_nouu -echo Apparently you have no UUDECODE utility in your path. You need a UUDECODE -echo utility in order to turn "nhico.uu" into "nethack.ico". -echo Check "Install.nt" for a list of the steps required to build NetHack. -goto done -:err_plev -echo A required file ..\..\include\patchlev.h seems to be missing. -echo Check "Files." in the root directory for your NetHack distribution -echo and make sure that all required files exist. -goto done +echo Copying Visual C project files to ..\..\build directory +echo Copying ..\..\win\win32\nethack.dsw ..\..\nethack.dsw +copy ..\..\win\win32\nethack.dsw ..\.. >nul +if NOT exist ..\..\binary\*.* echo Creating ..\..\binary directory +if NOT exist ..\..\binary\*.* mkdir ..\..\binary +if NOT exist ..\..\binary\license copy ..\..\dat\license ..\..\binary\license >nul +if NOT exist ..\..\build\*.* echo Creating ..\..\build directory +if NOT exist ..\..\build\*.* mkdir ..\..\build +copy ..\..\win\win32\dgncomp.dsp ..\..\build >nul +copy ..\..\win\win32\dgnstuff.dsp ..\..\build >nul +copy ..\..\win\win32\dgnstuff.mak ..\..\build >nul +copy ..\..\win\win32\dlb_main.dsp ..\..\build >nul +copy ..\..\win\win32\levcomp.dsp ..\..\build >nul +copy ..\..\win\win32\levstuff.dsp ..\..\build >nul +copy ..\..\win\win32\levstuff.mak ..\..\build >nul +copy ..\..\win\win32\makedefs.dsp ..\..\build >nul +copy ..\..\win\win32\recover.dsp ..\..\build >nul +copy ..\..\win\win32\tile2bmp.dsp ..\..\build >nul +copy ..\..\win\win32\tiles.dsp ..\..\build >nul +copy ..\..\win\win32\tiles.mak ..\..\build >nul +copy ..\..\win\win32\tilemap.dsp ..\..\build >nul +copy ..\..\win\win32\uudecode.dsp ..\..\build >nul +copy ..\..\win\win32\nethackw.dsp ..\..\build >nul + +goto :done + +:err_win +echo Some of the files needed to build graphical NetHack +echo for Windows are not in the expected places. +echo Check "Install.nt" for a list of the steps required +echo to build NetHack. +goto :fini + :err_data echo A required file ..\..\dat\data.bas seems to be missing. echo Check "Files." in the root directory for your NetHack distribution echo and make sure that all required files exist. -goto done +goto :fini + :err_dir echo Your directories are not set up properly, please re-read the -echo documentation. +echo documentation and sys/winnt/Install.nt. +goto :fini + :done +echo done! +echo. +echo Proceed with the next step documented in Install.nt +echo. + +:fini +:end +set _pause=Y +if "%0"=="nhsetup" set _pause=N +if "%0"=="NHSETUP" set _pause=N +if "%_pause%"=="Y" pause +set _pause= diff --git a/sys/winnt/ntsound.c b/sys/winnt/ntsound.c index 0e6d6f2..52d09a2 100644 --- a/sys/winnt/ntsound.c +++ b/sys/winnt/ntsound.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)ntsound.c 3.3 95/09/06 */ +/* SCCS Id: @(#)ntsound.c 3.4 1995/09/06 */ /* Copyright (c) NetHack PC Development Team 1993 */ /* NetHack may be freely redistributed. See license for details. */ /* */ diff --git a/sys/winnt/nttty.c b/sys/winnt/nttty.c index 1679139..c76a92a 100644 --- a/sys/winnt/nttty.c +++ b/sys/winnt/nttty.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)nttty.c 3.3 2000/08/02 +/* SCCS Id: @(#)nttty.c 3.4 2000/08/02 /* Copyright (c) NetHack PC Development Team 1993 */ /* NetHack may be freely redistributed. See license for details. */ @@ -39,7 +39,7 @@ HANDLE hConIn; HANDLE hConOut; /* Win32 Screen buffer,coordinate,console I/O information */ -CONSOLE_SCREEN_BUFFER_INFO csbi; +CONSOLE_SCREEN_BUFFER_INFO csbi, origcsbi; COORD ntcoord; INPUT_RECORD ir; @@ -52,15 +52,30 @@ INPUT_RECORD ir; */ int GUILaunched; static BOOL FDECL(CtrlHandler, (DWORD)); - -# ifdef TEXTCOLOR + +#ifndef CLR_MAX +#define CLR_MAX 16 +#endif int ttycolors[CLR_MAX]; +# ifdef TEXTCOLOR static void NDECL(init_ttycolor); # endif +#define DEFTEXTCOLOR ttycolors[7] +#ifdef TEXTCOLOR +#define DEFGLYPHBGRND (0) +#else +#define DEFGLYPHBGRND (0) +#endif + static char nullstr[] = ""; char erase_char,kill_char; +static char currentcolor = FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_BLUE; +static char currenthilite = 0; +static char currentbackground = 0; +static boolean colorchange = TRUE; + #define LEFTBUTTON FROM_LEFT_1ST_BUTTON_PRESSED #define RIGHTBUTTON RIGHTMOST_BUTTON_PRESSED #define MIDBUTTON FROM_LEFT_2ND_BUTTON_PRESSED @@ -70,13 +85,19 @@ char erase_char,kill_char; * Called after returning from ! or ^Z */ void -gettty(){ - +gettty() +{ +#ifndef TEXTCOLOR + int k; +#endif erase_char = '\b'; kill_char = 21; /* cntl-U */ iflags.cbreak = TRUE; #ifdef TEXTCOLOR init_ttycolor(); +#else + for(k=0; k < CLR_MAX; ++k) + ttycolors[k] = 7; #endif } @@ -96,6 +117,51 @@ setftty() start_screen(); } +void +tty_startup(wid, hgt) +int *wid, *hgt; +{ +/* int twid = origcsbi.dwSize.X; */ + int twid = origcsbi.srWindow.Right - origcsbi.srWindow.Left; + + if (twid > 80) twid = 80; + *wid = twid; + *hgt = origcsbi.srWindow.Bottom - origcsbi.srWindow.Top; +} + +void +tty_number_pad(state) +int state; +{ +} + +void +tty_start_screen() +{ + if (iflags.num_pad) tty_number_pad(1); /* make keypad send digits */ +} + +void +tty_end_screen() +{ + clear_screen(); + if (GetConsoleScreenBufferInfo(hConOut,&csbi)) + { + DWORD ccnt; + COORD newcoord; + + newcoord.X = 0; + newcoord.Y = 0; + FillConsoleOutputAttribute(hConOut, + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, + csbi.dwSize.X * csbi.dwSize.Y, + newcoord, &ccnt); + FillConsoleOutputCharacter(hConOut,' ', + csbi.dwSize.X * csbi.dwSize.Y, + newcoord, &ccnt); + } +} + static BOOL CtrlHandler(ctrltype) DWORD ctrltype; { @@ -107,13 +173,12 @@ DWORD ctrltype; case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: #ifndef NOSAVEONHANGUP - if (program_state.something_worth_saving) { - program_state.exiting++; - (void) dosave0(); - } + hangup(0); #endif +#if 0 clearlocks(); terminate(EXIT_FAILURE); +#endif default: return FALSE; } @@ -124,7 +189,7 @@ void nttty_open() { HANDLE hStdOut; - long cmode; + DWORD cmode; long mask; /* Initialize the function pointer that points to @@ -140,10 +205,10 @@ nttty_open() * the NT program manager. M. Allison */ hStdOut = GetStdHandle( STD_OUTPUT_HANDLE ); - GetConsoleScreenBufferInfo( hStdOut, &csbi); - GUILaunched = ((csbi.dwCursorPosition.X == 0) && - (csbi.dwCursorPosition.Y == 0)); - if ((csbi.dwSize.X <= 0) || (csbi.dwSize.Y <= 0)) + GetConsoleScreenBufferInfo( hStdOut, &origcsbi); + GUILaunched = ((origcsbi.dwCursorPosition.X == 0) && + (origcsbi.dwCursorPosition.Y == 0)); + if ((origcsbi.dwSize.X <= 0) || (origcsbi.dwSize.Y <= 0)) GUILaunched = 0; hConIn = GetStdHandle(STD_INPUT_HANDLE); hConOut = GetStdHandle(STD_OUTPUT_HANDLE); @@ -156,7 +221,7 @@ nttty_open() hConOut = CreateFile("CONOUT$", GENERIC_READ |GENERIC_WRITE, FILE_SHARE_READ |FILE_SHARE_WRITE, - 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0); + 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0); #endif GetConsoleMode(hConIn,&cmode); #ifndef NO_MOUSE_ALLOWED @@ -177,6 +242,28 @@ nttty_open() get_scr_size(); } +void +get_scr_size() +{ + GetConsoleScreenBufferInfo(hConOut, &csbi); + + LI = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + CO = csbi.srWindow.Right - csbi.srWindow.Left + 1; + + if ( (LI < 25) || (CO < 80) ) { + COORD newcoord; + + LI = 25; + CO = 80; + + newcoord.Y = LI; + newcoord.X = CO; + + SetConsoleScreenBufferSize( hConOut, newcoord ); + } +} + + /* * Keyboard translation tables. * (Adopted from the MSDOS port) @@ -202,9 +289,9 @@ static const struct pad { {'u', 'U', C('u')}, /* 9 */ {'m', C('p'), C('p')}, /* - */ {'h', 'H', C('h')}, /* 4 */ - {'g', 'g', 'g'}, /* 5 */ + {'g', 'G', 'g'}, /* 5 */ {'l', 'L', C('l')}, /* 6 */ - {'p', 'P', C('p')}, /* + */ + {'+', 'P', C('p')}, /* + */ {'b', 'B', C('b')}, /* 1 */ {'j', 'J', C('j')}, /* 2 */ {'n', 'N', C('n')}, /* 3 */ @@ -218,7 +305,7 @@ static const struct pad { {'4', M('4'), '4'}, /* 4 */ {'g', 'G', 'g'}, /* 5 */ {'6', M('6'), '6'}, /* 6 */ - {'p', 'P', C('p')}, /* + */ + {'+', 'P', C('p')}, /* + */ {'1', M('1'), '1'}, /* 1 */ {'2', M('2'), '2'}, /* 2 */ {'3', M('3'), '3'}, /* 3 */ @@ -245,6 +332,8 @@ static const char *extendedlist = "acdefijlmnopqrstuvw?2"; #define inmap(x) (SCANLO <= (x) && (x) < SCANLO + SIZE(scanmap)) +int FDECL(process_keystroke, (INPUT_RECORD *ir, boolean *valid)); + int process_keystroke(ir, valid) INPUT_RECORD *ir; boolean *valid; @@ -302,8 +391,8 @@ boolean *valid; int tgetch() { - int count; - int valid = 0; + DWORD count; + boolean valid = 0; int ch; valid = 0; while (!valid) @@ -319,13 +408,13 @@ int ntposkey(x, y, mod) int *x, *y, *mod; { - int count; + DWORD count; unsigned short int scan; unsigned char ch; unsigned long shiftstate; int altseq; int done = 0; - int valid = 0; + boolean valid = 0; while (!done) { count = 0; @@ -341,10 +430,6 @@ int *x, *y, *mod; return process_keystroke(&ir, &valid); } else if ((ir.EventType == MOUSE_EVENT && (ir.Event.MouseEvent.dwButtonState & MOUSEMASK))) { -#if 0 - *x = ir.Event.MouseEvent.dwMousePosition.X - csbi.srWindow.Left; - *y = ir.Event.MouseEvent.dwMousePosition.Y - csbi.srWindow.Top; -#endif *x = ir.Event.MouseEvent.dwMousePosition.X + 1; *y = ir.Event.MouseEvent.dwMousePosition.Y - 1; @@ -370,7 +455,7 @@ nttty_kbhit() { int done = 0; /* true = "stop searching" */ int retval; /* true = "we had a match" */ - int count; + DWORD count; unsigned short int scan; unsigned char ch; unsigned long shiftstate; @@ -408,75 +493,6 @@ nttty_kbhit() return retval; } -void -get_scr_size() -{ - if (GetConsoleScreenBufferInfo(hConOut,&csbi)) - { - int tmpx, tmpy, ccnt; - COORD newcoord; - - newcoord.X = 0; - newcoord.Y = 0; - FillConsoleOutputCharacter(hConOut,' ', - csbi.dwSize.X * csbi.dwSize.Y, - newcoord, &ccnt); - - tmpy = csbi.dwSize.Y; - tmpx = csbi.dwSize.X; - if ((tmpy < 25) || (tmpx < 80)) { - newcoord.Y = 25; - newcoord.X = 80; - SetConsoleScreenBufferSize(hConOut, newcoord); - } - } - LI = 25; - CO = 80; -} - - -void -tty_startup(wid, hgt) - int *wid, *hgt; -{ - - *wid = CO; - *hgt = LI; -} - -void -tty_number_pad(state) -int state; -{ -} - -void -tty_start_screen() -{ - if (iflags.num_pad) tty_number_pad(1); /* make keypad send digits */ -} - -void -tty_end_screen() -{ - clear_screen(); - if (GetConsoleScreenBufferInfo(hConOut,&csbi)) - { - int ccnt; - COORD newcoord; - - newcoord.X = 0; - newcoord.Y = 0; - FillConsoleOutputAttribute(hConOut, - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, - csbi.dwSize.X * csbi.dwSize.Y, - newcoord, &ccnt); - FillConsoleOutputCharacter(hConOut,' ', - csbi.dwSize.X * csbi.dwSize.Y, - newcoord, &ccnt); - } -} - void nocmov(x, y) int x,y; @@ -501,8 +517,13 @@ void xputc(c) char c; { - int count; + DWORD count; + if (colorchange) { + SetConsoleTextAttribute(hConOut, + (currentcolor | currenthilite | currentbackground)); + colorchange = FALSE; + } WriteConsole(hConOut,&c,1,&count,0); } @@ -510,34 +531,76 @@ void xputs(s) const char *s; { - int count; - + DWORD count; + if (colorchange) { + SetConsoleTextAttribute(hConOut, + (currentcolor | currenthilite | currentbackground)); + colorchange = FALSE; + } WriteConsole(hConOut,s,strlen(s),&count,0); } +/* + * Overrides winntty.c function of the same name + * for win32. It is used for glyphs only, not text. + */ +void +g_putch(in_ch) +int in_ch; +{ + char ch = (char)in_ch; + DWORD count = 1; + int tcolor; + int bckgnd = currentbackground; + + if (colorchange) { + tcolor = currentcolor | bckgnd | currenthilite; + SetConsoleTextAttribute(hConOut, tcolor); + } + WriteConsole(hConOut,&ch,1,&count,0); + colorchange = TRUE; /* force next output back to current nethack values */ + return; +} + void cl_end() { - int count; + DWORD count; + ntcoord.X = ttyDisplay->curx; + ntcoord.Y = ttyDisplay->cury; + FillConsoleOutputAttribute(hConOut, DEFTEXTCOLOR, + CO - ntcoord.X,ntcoord, &count); ntcoord.X = ttyDisplay->curx; ntcoord.Y = ttyDisplay->cury; FillConsoleOutputCharacter(hConOut,' ', CO - ntcoord.X,ntcoord,&count); tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+1, (int)ttyDisplay->cury); + colorchange = TRUE; } void clear_screen() { - int count; - - ntcoord.X = 0; - ntcoord.Y = 0; - FillConsoleOutputCharacter(hConOut,' ',CO * LI, - ntcoord, &count); + if (GetConsoleScreenBufferInfo(hConOut,&csbi)) { + DWORD ccnt; + COORD newcoord; + + newcoord.X = 0; + newcoord.Y = 0; + FillConsoleOutputAttribute(hConOut, + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, + csbi.dwSize.X * csbi.dwSize.Y, + newcoord, &ccnt); + newcoord.X = 0; + newcoord.Y = 0; + FillConsoleOutputCharacter(hConOut,' ', + csbi.dwSize.X * csbi.dwSize.Y, + newcoord, &ccnt); + } + colorchange = TRUE; home(); } @@ -559,7 +622,13 @@ backsp() if (csbi.dwCursorPosition.X > 0) ntcoord.X = csbi.dwCursorPosition.X-1; ntcoord.Y = csbi.dwCursorPosition.Y; - SetConsoleCursorPosition(hConOut,ntcoord); + SetConsoleCursorPosition(hConOut,ntcoord); + /* colorchange shouldn't ever happen here but.. */ + if (colorchange) { + SetConsoleTextAttribute(hConOut, + (currentcolor|currenthilite|currentbackground)); + colorchange = FALSE; + } WriteConsole(hConOut," ",1,&count,0); SetConsoleCursorPosition(hConOut,ntcoord); } @@ -571,30 +640,51 @@ tty_nhbell() Beep(8000,500); } +volatile int junk; /* prevent optimizer from eliminating loop below */ void tty_delay_output() { /* delay 50 ms - uses ANSI C clock() function now */ clock_t goal; + int k; goal = 50 + clock(); while (goal > clock()) { - /* Do nothing */ + k = junk; /* Do nothing */ } } void cl_eos() { - - register int cy = ttyDisplay->cury+1; + register int cy = ttyDisplay->cury+1; +#if 0 while(cy <= LI-2) { cl_end(); xputc('\n'); cy++; } cl_end(); +#else + if (GetConsoleScreenBufferInfo(hConOut,&csbi)) { + int ccnt; + COORD newcoord; + + newcoord.X = 0; + newcoord.Y = ttyDisplay->cury; + FillConsoleOutputAttribute(hConOut, + FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, + csbi.dwSize.X * csbi.dwSize.Y - cy, + newcoord, &ccnt); + newcoord.X = 0; + newcoord.Y = ttyDisplay->cury; + FillConsoleOutputCharacter(hConOut,' ', + csbi.dwSize.X * csbi.dwSize.Y - cy, + newcoord, &ccnt); + } + colorchange = TRUE; +#endif tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+1, (int)ttyDisplay->cury); } @@ -646,7 +736,6 @@ init_ttycolor() ttycolors[CLR_WHITE] = FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED|\ FOREGROUND_INTENSITY; } - # endif /* TEXTCOLOR */ int @@ -655,17 +744,39 @@ has_color(int color) # ifdef TEXTCOLOR return 1; # else - return 0; + if (color == CLR_BLACK) + return 1; + else if (color == CLR_WHITE) + return 1; + else + return 0; # endif } void term_end_attr(int attr) { - /* Mix all three colors for white on NT console */ - SetConsoleTextAttribute(hConOut, - FOREGROUND_RED|FOREGROUND_BLUE| - FOREGROUND_GREEN); + switch(attr){ + + case ATR_ULINE: + case ATR_BOLD: + case ATR_BLINK: + standoutend(); + break; + case ATR_INVERSE: + if (currentcolor == 0) + currentcolor = FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED; + currentbackground = 0; + colorchange = TRUE; + break; + default: + standoutend(); + if (currentcolor == 0) + currentcolor = FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED; + currentbackground = 0; + currenthilite = 0; + break; + } } void @@ -675,15 +786,19 @@ term_start_attr(int attr) case ATR_ULINE: case ATR_BOLD: - /* Mix all three colors for white on NT console */ - SetConsoleTextAttribute(hConOut, - FOREGROUND_RED|FOREGROUND_BLUE| - FOREGROUND_GREEN|FOREGROUND_INTENSITY ); - break; case ATR_BLINK: + standoutbeg(); + break; case ATR_INVERSE: + /* Suggestion by Lee Berger */ + if ((currentcolor & (FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED)) == + (FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED)) + currentcolor = 0; + currentbackground = (BACKGROUND_RED|BACKGROUND_BLUE|BACKGROUND_GREEN); + colorchange = TRUE; + break; default: - term_end_attr(0); + standoutend(); break; } } @@ -704,11 +819,9 @@ void term_start_color(int color) { # ifdef TEXTCOLOR - WORD attr; - if (color >= 0 && color < CLR_MAX) { - attr = (WORD)ttycolors[color]; - SetConsoleTextAttribute(hConOut,attr); + currentcolor = ttycolors[color]; + colorchange = TRUE; } # endif } @@ -717,30 +830,25 @@ void term_end_color(void) { # ifdef TEXTCOLOR - SetConsoleTextAttribute(hConOut, - FOREGROUND_RED|FOREGROUND_BLUE| - FOREGROUND_GREEN); -# endif + currentcolor = DEFTEXTCOLOR; + colorchange = TRUE; +# endif } void standoutbeg() { - /* Mix all three colors for white on NT console */ - SetConsoleTextAttribute(hConOut, - FOREGROUND_RED|FOREGROUND_BLUE| - FOREGROUND_GREEN|FOREGROUND_INTENSITY ); + currenthilite = FOREGROUND_INTENSITY; + colorchange = TRUE; } void standoutend() { - /* Mix all three colors for white on NT console */ - SetConsoleTextAttribute(hConOut, - FOREGROUND_RED|FOREGROUND_BLUE| - FOREGROUND_GREEN); + currenthilite = 0; + colorchange = TRUE; } #endif /* WIN32CON */ diff --git a/sys/winnt/porthelp b/sys/winnt/porthelp new file mode 100644 index 0000000..fe3cc26 --- /dev/null +++ b/sys/winnt/porthelp @@ -0,0 +1,300 @@ + Microsoft Windows specific help file for NetHack 3.4.0 + Copyright (c) NetHack PC Development Team 1993-2002. + NetHack may be freely distributed. See license for details. + (Last Revision: March 16, 2002) + +This file details specifics for NetHack built for Windows 95, 98, NT, +Me, 2000, and XP. Users of really early 16-bit Windows versions should +use the MSDOS NetHack. + +Please note that "NetHack for Windows - Graphical Interface" requires +an installation of Internet Explorer 4 or an installation of +version 4.71 of the common controls. See the following internet page: + http://www.nethack.org/v340/ports/download-win.html#cc +for more information. If the game runs for you, you are not affected. + +New players should be sure to read GuideBook.txt which contains +essential information about playing NetHack. It can be found in the +same directory as your NetHack executable. + +The NetHack for Windows port supports some additional or enhanced +commands as well as some defaults.nh file options specific to +configuration choices used during the building of NetHack for +Windows. Listed below are those commands and defaults.nh file +options. + +Some options are applicable only to the "Graphical Interface." +These are discussed separately in their own section. + +Contents +1. ALT Key Combinations +2. Boolean options - Option that you can toggle on or off +3. Graphical Interface - Options you can assign a value to +4. Graphical Interface - Additional/Enhanced Commands +5. Graphical Interface - Menus +6. Numeric Keypad (for number_pad mode) + + +1. ALT Key Combinations +---------------------------------------------- +The non-graphical (tty) interface always operates in "NetHack mode", +while the "NetHack for Windows - Graphical Interface" lets you +toggle the mode. In non-NetHack mode, all ALT-key combinations +are sent to the Windows itself, rather than to NetHack. + +While playing in NetHack mode you can press the ALT key in +combination with another key to execute an extended command +as an alternative method to pressing a # key sequence. +The available commands are: + + Alt-2 #twoweapon - toggle two-weapon combat (unavailable + if number_pad mode is set) + Alt-a #adjust - adjust inventory letters. + Alt-c #chat - talk to someone or something. + Alt-d #dip - dip an object into something. + Alt-e #enhance - enhance your skill with a weapon. + Alt-f #force - force a lock. + Alt-i #invoke - invoke an object's powers. + Alt-j #jump - jump to a location. + Alt-l #loot - loot a box on the floor. + Alt-m #monster - use a monster's special ability. + Alt-n #name - name an item or type of object. + Alt-o #offer - offer a sacrifice to the gods. + Alt-p #pray - pray to the gods for help. + Alt-q #quit - quit the game. (Same as #quit) + Alt-r #rub - rub a lamp. + Alt-s #sit - sit down. + Alt-t #turn - turn undead. + Alt-u #untrap - untrap something. + Alt-v #version - list compile time options for this version of + NetHack. + Alt-w #wipe - wipe off your face. + Alt-? #? - display list of extended menu commands + +2. Boolean Options (Options that can be toggled on or off) +---------------------------------------------------------- + +Listed here are any options not discussed in the main help, options +which may be slightly different from the main help file, and options +which may need a slightly more explanatory note: + + color Use color when displaying non-tiled maps. Tiled + maps (available in the graphical port) are always + rendered in color. Default: [TRUE] + + hilite_pet Using tiled graphics, displays a small heart symbol + next to your pet. Using ascii graphics, the pet is + hilited in a white background. + Default: [TRUE] + + IBMgraphics Use IBM extended characters for the dungeon + Default: [TRUE] + + msg_window When ^P is pressed, it shows menu in a full window. + Available only in the non-graphical (tty) version. + Default: [FALSE] + + toptenwin Write top ten list to a window, as opposed to stdout. + Default in tty interface: [FALSE] + Default in graphical interface: [TRUE] (and cannot be changed) + +3. Options that you assign a value to (Graphical Interface only) +---------------------------------------------------------------- + +"NetHack for Windows - Graphical Interface" recognizes the following +additional options, which the non-graphical (tty) version will +silently ignore. These are options that specify attributes of various +windows. The windows that you can tailor include menu windows (such +as the inventory list), text windows (such as "It is written in the +book of ..." screens), the message window (where events of the game are +displayed), the status window (where your character name +and attributes are displayed), and the map window (where the map +is drawn). + +Window Alignment options: + + align_message Specifies at which side of the NetHack screen the + message window is aligned. This option can be used + to align the window to "top" or "bottom". + Default: [TOP] + + align_status Specifies at which side of the NetHack screen the + status window is aligned. This option can be used + to align the window to "top" or "bottom". + Default: [BOTTOM] + +Map Window options: + + map_mode Specifies which map mode to use. + The following map modes are available: + tiles (display things on the map with colored tiles), + ascii4x6, ascii6x8, ascii8x8, ascii16x8, ascii7x12, + ascii8x12, ascii16x12, ascii12x16, ascii10x18 + (which use that size font to display things on + the map), or fit_to_screen (an ascii mode which + forces things to fit on a single screen). + Default: [tiles] + + scroll_margin Specifies the number of map cells from the edge + of the map window where scrolling will take place. + Default: [5] + + tile_file An alternative file containing bitmap to use for + tiles. This file should be a .bmp file and should + be organized as 40 rectangular tiles wide. It is + beyond the scope of this document to describe the + exact contents of each tile in the .bmp, which must + match the object lists used when building NetHack. + + tile_height Used with tile_file to specify the height of each + tile in pixels. This option may only be specified + in the defaults.nh config file. + Default: [16] + + tile_width Used with tile_file to specify the width of each + tile in pixels. This option may only be specified + in the defaults.nh config file. + Default: [16] + +Other Window options: + + windowcolors Specifies the colors for various windows + This option may only be specified in the + defaults.nh config file and has the following + format: + window-type foreground/background + Notes: + - Both foreground and background colors are + required, and a slash must separate them. + - "window-type" is either "message" or "status" + (Short forms are: "msg" or "sts"). + - "foreground" and "background" may be specified as + a color name (such as "blue"), or by a six + digit hexadecimal RGB color value (such as + "#8F8F8F") + - The following color names are available: + black, red, green, brown, blue, magenta, + cyan, gray (or grey), orange, brightgreen, + yellow, brightblue, brightmagenta, brightcyan, + white, trueblack, purple, silver, maroon, fuchsia, + lime, olive, navy, teal, aqua. In addition, you + can use the following names to refer to default + Windows settings: activeborder, activecaption, + appworkspace, background, btnface, btnshadow, btntext, + captiontext, graytext, highlight, highlighttext, + inactiveborder, inactivecaption, menu, menutext, + scrollbar, window, windowframe, windowtext. + + Example: + OPTIONS=windowcolors:sts #00FF80/blue msg menutext/menu + + font_menu Specifies the name of the menu font. + font_message Specifies the name of the message font. + font_status Specifies the name of the status font. + font_text Specifies the name of the text font. + + font_size_menu Specifies the size of the menu font. + + font_size_message + Specifies the size of the message font. + + font_size_status + Specifies the size of the status font. + + font_size_text Specifies the size of the text font. + +Miscellaneous options: + + vary_msgcount Number of lines to display in message window. + + +4. NetHack for Windows - Graphical Interface, Additional/Enhanced Commands +------------------------------------------------------------------------- + +The following function keys are active in +the "NetHack for Windows - Graphical Interface": + + F4 Toggle level overview mode on/off + This key will toggle the map between a view that + is mapped to fit exactly to the window, and the + view that shows the various symbols in their + normal size. This is useful for getting an idea + of where you are in a level. + + F5 Toggle tiled display on/off. + This key switches between the tiled and the + traditional ASCII display. This is equivalent to + using the "map_mode" option. + + F10 Activate menu bar. + This key will activate the menu bar, allowing you + to select between the menus: File, Map, + Window Settings, and Help. + +5. Graphical Port Menus +----------------------- + +File + Save - Allows you to save and exit the game + Quit - Allows you to quit the game + +Map - Provides for selection of map mode. Equivalent to using +the map_mode option. + +Window Settings - Changes your logged-on user's settings for NetHack. +In 3.4.0, only one setting is available: NetHack mode, which can be +checked or unchecked. NetHack mode allows you to use the ALT key for +game key commands [see list above]. You can use F10 to access the +menu bar while in NetHack mode. You can also clear your logged-on +user's settings for NetHack. Settings in this window are saved in +your logged-on user's registry. + +Help - Provides help about various portions of NetHack. + + +6. Numeric Keypad (for "OPTION=number_pad" mode) +------------------------------------------------ + +The numeric keypad and surrounding characters act as macros for different +commands in NetHack. The Num Lock should be toggled to "on" to make the +most of these keys: + + Key Normal Shift-Key + ---------- ---------- ------------- + 1, 2, 3, 4 Move In Run In + 6, 7, 8, 9 Direction Direction + + 0 (Ins) Inventory Categorized + Inventory + + . (Del) Wait Turn : - Look Here + + + Spell List P - Put on an + accessory + + - m - Move Previous + Only Message + + NetHack for Windows - tty Interface Specific Behavior: + ------------------------------------------------------ + + In the non-graphical (tty) interface, when you use the Ctrl key with a + directional key (1, 2, 3, 4, 6, 7, 8, 9) it means "go in specified + direction until you hit a wall or run into something interesting." + + NetHack for Windows - Graphical Interface Specific Behavior: + ------------------------------------------------------------ + + It is possible to scroll or pan the map in a specific direction: + + Ctrl-Shift-Left (4) Scroll (Pan) map left + Ctrl-Shift-Right (6) Scroll (Pan) map right + Ctrl-Shift-Up (8) Scroll (Pan) map up + Ctrl-Shift-Down (2) Scroll (Pan) map down + Ctrl-Shift-Home (7) Scroll (Pan) map left to leftmost corner + Ctrl-Shift-End (1) Scroll (Pan) map left to rightmost corner + Ctrl-Shift-PgUp (9) Scroll (Pan) map left to uppermost corner + Ctrl-Shift-PgDn (3) Scroll (Pan) map left to lowermost corner + + + diff --git a/sys/winnt/win32api.h b/sys/winnt/win32api.h index fa5a11a..c6400db 100644 --- a/sys/winnt/win32api.h +++ b/sys/winnt/win32api.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)win32api.h 3.3 96/02/15 */ +/* SCCS Id: @(#)win32api.h 3.4 1996/02/15 */ /* Copyright (c) NetHack PC Development Team 1996 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/sys/winnt/winnt.c b/sys/winnt/winnt.c index 4cd0969..5c7ebb5 100644 --- a/sys/winnt/winnt.c +++ b/sys/winnt/winnt.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)winnt.c 3.3 97/04/12 */ +/* SCCS Id: @(#)winnt.c 3.4 1997/04/12 */ /* Copyright (c) NetHack PC Development Team 1993, 1994 */ /* NetHack may be freely redistributed. See license for details. */ @@ -12,7 +12,9 @@ #define NEED_VARARGS #include "hack.h" #include +#ifndef __BORLANDC__ #include +#endif #include #include "win32api.h" @@ -159,7 +161,7 @@ void nt_regularize(s) /* normalize file name */ register char *s; { - register char *lp; + register unsigned char *lp; for (lp = s; *lp; lp++) if ( *lp == '?' || *lp == '"' || *lp == '\\' || @@ -174,11 +176,10 @@ register char *s; char *get_username(lan_username_size) int *lan_username_size; { - static char username_buffer[BUFSZ]; + static TCHAR username_buffer[BUFSZ]; unsigned int status; - int i = 0; + DWORD i = BUFSZ - 1; - i = BUFSZ - 1; /* i gets updated with actual size */ status = GetUserName(username_buffer, &i); if (status) username_buffer[i] = '\0'; diff --git a/util/dgn_comp.l b/util/dgn_comp.l index 6cefdd2..429e8b8 100644 --- a/util/dgn_comp.l +++ b/util/dgn_comp.l @@ -1,5 +1,5 @@ %{ -/* SCCS Id: @(#)dgn_lex.c 3.3 96/03/02 */ +/* SCCS Id: @(#)dgn_lex.c 3.4 1996/03/02 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* Copyright (c) 1990 by M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ @@ -74,33 +74,6 @@ void FDECL(init_yyout, (FILE *)); extern YYSTYPE yylval; int line_number = 1; -/* - * This is a hack required by Michael Hamel to get things - * working on the Mac. - */ -#if defined(applec) && !defined(FLEX_SCANNER) && !defined(FLEXHACK_SCANNER) -#undef input -#undef unput -#define unput(c) { yytchar = (c); if (yytchar == 10) yylineno--; *yysptr++ = yytchar; } -# ifndef YYNEWLINE -# define YYNEWLINE 10 -# endif - -char -input() /* Under MPW \n is chr(13)! Compensate for this. */ -{ - if (yysptr > yysbuf) return(*--yysptr); - else { - yytchar = getc(yyin); - if (yytchar == '\n') { - yylineno++; - return(YYNEWLINE); - } - if (yytchar == EOF) return(0); - else return(yytchar); - } -} -#endif /* applec && !FLEX_SCANNER && !FLEXHACK_SCANNER */ %} %% diff --git a/util/dgn_comp.y b/util/dgn_comp.y index cf1ff83..9b355cb 100644 --- a/util/dgn_comp.y +++ b/util/dgn_comp.y @@ -1,5 +1,5 @@ %{ -/* SCCS Id: @(#)dgn_comp.c 3.3 96/06/22 */ +/* SCCS Id: @(#)dgn_comp.c 3.4 1996/06/22 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* Copyright (c) 1990 by M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/util/dgn_main.c b/util/dgn_main.c index 5926757..421aa82 100644 --- a/util/dgn_main.c +++ b/util/dgn_main.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dgn_main.c 3.3 94/09/23 */ +/* SCCS Id: @(#)dgn_main.c 3.4 1994/09/23 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* Copyright (c) 1990 by M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ @@ -12,7 +12,7 @@ #include "dlb.h" #ifdef MAC -# ifdef applec +# if defined(__SC__) || defined(__MRC__) # define MPWTOOL #include # else @@ -44,7 +44,7 @@ FILE *FDECL (freopen, (char *,char *,FILE *)); #endif #define Fprintf (void)fprintf -#ifdef __BORLANDC__ +#if defined(__BORLANDC__) && !defined(_WIN32) extern unsigned _stklen = STKSIZ; #endif int diff --git a/util/dlb_main.c b/util/dlb_main.c index d161fea..a943a92 100644 --- a/util/dlb_main.c +++ b/util/dlb_main.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)dlb_main.c 3.3 98/08/16 */ +/* SCCS Id: @(#)dlb_main.c 3.4 1998/08/16 */ /* Copyright (c) Kenneth Lorber, Bethesda, Maryland, 1993. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/util/lev_comp.l b/util/lev_comp.l index fbf4731..c4e47a4 100644 --- a/util/lev_comp.l +++ b/util/lev_comp.l @@ -1,5 +1,5 @@ %{ -/* SCCS Id: @(#)lev_lex.c 3.3 96/05/16 */ +/* SCCS Id: @(#)lev_lex.c 3.4 2000/12/22 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -74,34 +74,6 @@ int line_number = 1, colon_line_number = 1; static char map[4096]; static int map_cnt = 0; -/* - * This is a hack required by Michael Hamel to get things - * working on the Mac. - */ -#if defined(applec) && !defined(FLEX_SCANNER) && !defined(FLEXHACK_SCANNER) -#undef input -#undef unput -#define unput(c) { yytchar = (c); if (yytchar == 10) yylineno--; *yysptr++ = yytchar; } -# ifndef YYNEWLINE -# define YYNEWLINE 10 -# endif - -char -input() /* Under MPW \n is chr(13)! Compensate for this. */ -{ - if (yysptr > yysbuf) return(*--yysptr); - else { - yytchar = getc(yyin); - if (yytchar == '\n') { - yylineno++; - return(YYNEWLINE); - } - if (yytchar == EOF) return(0); - else return(yytchar); - } -} -#endif /* applec && !FLEX_SCANNER && !FLEXHACK_SCANNER */ - %} %e 1500 %p 5000 @@ -116,7 +88,7 @@ input() /* Under MPW \n is chr(13)! Compensate for this. */ map_cnt = 0; return MAP_ID; } -[-|}{+ABCISHKPLWTF\\#. ]*\n { +[-|}{+ABCISHKPLWTF\\#. 0123456789]*\n { line_number++; (void) strncpy(map + map_cnt, yytext, yyleng); map_cnt += yyleng; @@ -231,6 +203,7 @@ shortsighted { yylval.i=SHORTSIGHTED; return FLAG_TYPE; } return STRING; } \n { line_number++; } [ \t]+ ; +'\\.' { yylval.i = yytext[2]; return CHAR; } '.' { yylval.i = yytext[1]; return CHAR; } . { return yytext[0]; } %% diff --git a/util/lev_comp.y b/util/lev_comp.y index bdd7471..2e872b8 100644 --- a/util/lev_comp.y +++ b/util/lev_comp.y @@ -1,5 +1,5 @@ %{ -/* SCCS Id: @(#)lev_yacc.c 3.3 2000/01/17 */ +/* SCCS Id: @(#)lev_yacc.c 3.4 2000/01/17 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/util/lev_main.c b/util/lev_main.c index e39e14e..1b9e780 100644 --- a/util/lev_main.c +++ b/util/lev_main.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)lev_main.c 3.3 2000/08/01 */ +/* SCCS Id: @(#)lev_main.c 3.4 2000/08/01 */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -6,6 +6,8 @@ * This file contains the main function for the parser * and some useful functions needed by yacc */ +#define SPEC_LEV /* for MPW */ +/* although, why don't we move those special defines here.. and in dgn_main? */ #include "hack.h" #include "date.h" @@ -15,7 +17,7 @@ #endif #ifdef MAC -# ifdef applec +# if defined(__SC__) || defined(__MRC__) # define MPWTOOL #include # else @@ -23,6 +25,10 @@ # endif #endif +#ifdef WIN_CE +#define PREFIX "\\nethack\\dat\\" +#endif + #ifndef MPWTOOL # define SpinCursor(x) #endif @@ -47,7 +53,7 @@ # define OMASK 0644 #endif -#define NEWLINE 10 /* under Mac MPW C '\n' is 13 so don't use it. */ +#define NEWLINE '\n' /* changes to 13 for MPW */ #define ERR (-1) @@ -55,7 +61,7 @@ #define Free(ptr) if(ptr) free((genericptr_t) (ptr)) #define Write(fd, item, size) if (write(fd, (genericptr_t)(item), size) != size) return FALSE; -#ifdef __BORLANDC__ +#if defined(__BORLANDC__) && !defined(_WIN32) extern unsigned _stklen = STKSIZ; #endif #define MAX_ERRORS 25 @@ -142,6 +148,9 @@ static struct { { "zoo", ZOO }, { "delphi", DELPHI }, { "temple", TEMPLE }, + { "anthole", ANTHOLE }, + { "cocknest", COCKNEST }, + { "leprehall", LEPREHALL }, { "shop", SHOPBASE }, { "armor shop", ARMORSHOP }, { "scroll shop", SCROLLSHOP }, @@ -507,8 +516,13 @@ char *map; int max_hig = 0; char msg[256]; - /* First : find the max width of the map */ + /* First, strip out digits 0-9 (line numbering) */ + for (s1 = s2 = map; *s1; s1++) + if (*s1 < '0' || *s1 > '9') + *s2++ = *s1; + *s2 = '\0'; + /* Second, find the max width of the map */ s1 = map; while (s1 && *s1) { s2 = index(s1, NEWLINE); @@ -523,7 +537,6 @@ char *map; } /* Then parse it now */ - while (map && *map) { tmpmap[max_hig] = (char *) alloc(max_len); s1 = index(map, NEWLINE); @@ -1105,7 +1118,11 @@ specialmaze *maze_level; Strcat(lbuf, filename); Strcat(lbuf, LEV_EXT); +#if defined(MAC) && (defined(__SC__) || defined(__MRC__)) + fout = open(lbuf, O_WRONLY|O_CREAT|O_BINARY); +#else fout = open(lbuf, O_WRONLY|O_CREAT|O_BINARY, OMASK); +#endif if (fout < 0) return FALSE; if (room_level) { @@ -1150,8 +1167,19 @@ specialmaze *maze; Write(fd, &(pt->ysize), sizeof(pt->ysize)); for(j=0;jysize;j++) { if(!maze->init_lev.init_present || - pt->xsize > 1 || pt->ysize > 1) - Write(fd, pt->map[j], pt->xsize * sizeof *pt->map[j]); + pt->xsize > 1 || pt->ysize > 1) { +#if !defined(_MSC_VER) && !defined(__BORLANDC__) + Write(fd, pt->map[j], pt->xsize * sizeof *pt->map[j]); +#else + /* + * On MSVC and Borland C compilers the Write macro above caused: + * warning '!=' : signed/unsigned mismatch + */ + unsigned reslt, sz = pt->xsize * sizeof *pt->map[j]; + reslt = write(fd, (genericptr_t)(pt->map[j]), sz); + if (reslt != sz) return FALSE; +#endif + } Free(pt->map[j]); } Free(pt->map); @@ -1300,7 +1328,7 @@ specialmaze *maze; return FALSE; /* The gold piles */ - Write(fd, &(pt->ngold), sizeof(pt->naltar)); + Write(fd, &(pt->ngold), sizeof(pt->ngold)); for(j=0;jngold;j++) { Write(fd, pt->golds[j], sizeof(gold)); Free(pt->golds[j]); diff --git a/util/makedefs.c b/util/makedefs.c index 3159246..34978d4 100644 --- a/util/makedefs.c +++ b/util/makedefs.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)makedefs.c 3.3 1999/08/16 */ +/* SCCS Id: @(#)makedefs.c 3.4 2002/03/03 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) M. Stephenson, 1990, 1991. */ /* Copyright (c) Dean Luick, 1990. */ @@ -27,7 +27,7 @@ #endif #ifdef MAC -# ifdef applec /* Means the MPW compiler, I hope */ +# if defined(__SC__) || defined(__MRC__) /* MPW compilers */ # define MPWTOOL #include #include @@ -49,14 +49,16 @@ #endif #if defined(UNIX) && !defined(LINT) && !defined(GCC_WARN) -static const char SCCS_Id[] = "@(#)makedefs.c\t3.3\t1999/08/16"; +static const char SCCS_Id[] = "@(#)makedefs.c\t3.4\t2002/02/03"; #endif /* names of files to be generated */ #define DATE_FILE "date.h" #define MONST_FILE "pm.h" #define ONAME_FILE "onames.h" +#ifndef OPTIONS_FILE #define OPTIONS_FILE "options" +#endif #define ORACLE_FILE "oracles" #define DATA_FILE "data" #define RUMOR_FILE "rumors" @@ -75,29 +77,33 @@ static const char SCCS_Id[] = "@(#)makedefs.c\t3.3\t1999/08/16"; # define DGN_TEMPLATE "NH:dat/%s" /* where dungeon.pdf file goes */ # define DATA_TEMPLATE "NH:slib/%s" # define DATA_IN_TEMPLATE "NH:dat/%s" -#else +#else /* not AMIGA */ # ifdef MAC # define INCLUDE_TEMPLATE ":include:%s" # define SOURCE_TEMPLATE ":src:%s" # define DGN_TEMPLATE ":dat:%s" /* where dungeon.pdf file goes */ +# if __SC__ || __MRC__ +# define DATA_TEMPLATE ":Dungeon:%s" +# else # define DATA_TEMPLATE ":lib:%s" +# endif /* __SC__ || __MRC__ */ # define DATA_IN_TEMPLATE ":dat:%s" -# else /* MAC */ +# else /* neither AMIGA nor MAC */ # ifdef OS2 # define INCLUDE_TEMPLATE "..\\include\\%s" # define SOURCE_TEMPLATE "..\\src\\%s" # define DGN_TEMPLATE "..\\dat\\%s" /* where dungeon.pdf file goes */ # define DATA_TEMPLATE "..\\dat\\%s" # define DATA_IN_TEMPLATE "..\\dat\\%s" -# else /* OS2 */ +# else /* not AMIGA, MAC, or OS2 */ # define INCLUDE_TEMPLATE "../include/%s" # define SOURCE_TEMPLATE "../src/%s" # define DGN_TEMPLATE "../dat/%s" /* where dungeon.pdf file goes */ # define DATA_TEMPLATE "../dat/%s" # define DATA_IN_TEMPLATE "../dat/%s" -# endif /* OS2 */ -# endif /* MAC */ -#endif /* AMIGA */ +# endif /* else !OS2 */ +# endif /* else !MAC */ +#endif /* else !AMIGA */ static const char *Dont_Edit_Code = @@ -191,7 +197,7 @@ static char *FDECL(eos, (char *)); /* input, output, tmp */ static FILE *ifp, *ofp, *tfp; -#ifdef __BORLANDC__ +#if defined(__BORLANDC__) && !defined(_WIN32) extern unsigned _stklen = STKSIZ; #endif @@ -440,6 +446,9 @@ make_version() #endif #ifdef STEED | (1L << 11) +#endif +#ifdef GOLDOBJ + | (1L << 12) #endif /* flag bits and/or other global variables (15..26) */ #ifdef TEXTCOLOR @@ -536,7 +545,7 @@ do_date() perror(filename); exit(EXIT_FAILURE); } - Fprintf(ofp,"/*\tSCCS Id: @(#)date.h\t3.3\t1996/05/17 */\n\n"); + Fprintf(ofp,"/*\tSCCS Id: @(#)date.h\t3.4\t2002/02/03 */\n\n"); Fprintf(ofp,Dont_Edit_Code); #ifdef KR1ED @@ -575,7 +584,7 @@ do_date() Fprintf(ofp,"#define AMIGA_VERSION_STRING "); Fprintf(ofp,"\"\\0$VER: NetHack %d.%d.%d (%d.%d.%d)\"\n", VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL, - tm->tm_mday, tm->tm_mon+1, tm->tm_year); + tm->tm_mday, tm->tm_mon+1, tm->tm_year+1900); } #endif Fclose(ofp); @@ -613,6 +622,9 @@ static const char *build_opts[] = { #ifdef MFLOPPY "floppy drive support", #endif +#ifdef GOLDOBJ + "gold object in inventories", +#endif #ifdef INSURANCE "insurance files for recovering from crashes", #endif @@ -661,23 +673,19 @@ static const char *build_opts[] = { # ifdef MAC "screen control via mactty", # endif -# ifdef SCREEN_8514 - "screen control via 8514/A graphics", -# endif # ifdef SCREEN_BIOS "screen control via BIOS", # endif # ifdef SCREEN_DJGPPFAST "screen control via DJGPP fast", # endif -# ifdef SCREEN_VESA - "screen control via VESA graphics", -# endif # ifdef SCREEN_VGA "screen control via VGA graphics", # endif -# ifdef WIN32CON +# ifndef MSWIN_GRAPHICS +# ifdef WIN32CON "screen control via WIN32 console I/O", +# endif # endif #endif #ifdef SEDUCE @@ -742,8 +750,8 @@ static const char *window_opts[] = { #ifdef GEM_GRAPHICS "Gem", #endif -#ifdef WIN32_GRAPHICS - "Win32", +#ifdef MSWIN_GRAPHICS + "mswin", #endif #ifdef BEOS_GRAPHICS "BeOS InterfaceKit", @@ -1332,7 +1340,7 @@ do_permonst() perror(filename); exit(EXIT_FAILURE); } - Fprintf(ofp,"/*\tSCCS Id: @(#)pm.h\t3.3\t1994/09/10 */\n\n"); + Fprintf(ofp,"/*\tSCCS Id: @(#)pm.h\t3.4\t2002/02/03 */\n\n"); Fprintf(ofp,Dont_Edit_Code); Fprintf(ofp,"#ifndef PM_H\n#define PM_H\n"); @@ -1645,7 +1653,7 @@ do_objs() perror(filename); exit(EXIT_FAILURE); } - Fprintf(ofp,"/*\tSCCS Id: @(#)onames.h\t3.3\t1994/09/10 */\n\n"); + Fprintf(ofp,"/*\tSCCS Id: @(#)onames.h\t3.4\t2002/02/03 */\n\n"); Fprintf(ofp,Dont_Edit_Code); Fprintf(ofp,"#ifndef ONAMES_H\n#define ONAMES_H\n\n"); diff --git a/util/panic.c b/util/panic.c index 930311c..5a5c41d 100644 --- a/util/panic.c +++ b/util/panic.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)panic.c 3.3 94/03/02 */ +/* SCCS Id: @(#)panic.c 3.4 1994/03/02 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/util/recover.c b/util/recover.c index 780cfc8..1c47fc5 100644 --- a/util/recover.c +++ b/util/recover.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)recover.c 3.3 99/10/23 */ +/* SCCS Id: @(#)recover.c 3.4 1999/10/23 */ /* Copyright (c) Janet Walz, 1992. */ /* NetHack may be freely redistributed. See license for details. */ @@ -26,7 +26,13 @@ int FDECL(open_levelfile, (int)); int NDECL(create_savefile); void FDECL(copy_bytes, (int,int)); +#ifndef WIN_CE #define Fprintf (void)fprintf +#else +#define Fprintf (void)nhce_message +static void nhce_message(FILE*, const char*, ...); +#endif + #define Close (void)close #ifdef UNIX @@ -47,7 +53,7 @@ void FDECL(copy_bytes, (int,int)); char *FDECL(exepath, (char *)); #endif -#ifdef __BORLANDC__ +#if defined(__BORLANDC__) && !defined(_WIN32) extern unsigned _stklen = STKSIZ; #endif char savename[SAVESIZE]; /* holds relative path of save file from playground */ @@ -340,11 +346,19 @@ char *str; if (!str) return (char *)0; bsize = EXEPATHBUFSZ; tmp = exepathbuf; -# ifndef WIN32 +#if !defined(WIN32) strcpy (tmp, str); +#else +# if defined(WIN_CE) + { + TCHAR wbuf[EXEPATHBUFSZ]; + GetModuleFileName((HANDLE)0, wbuf, EXEPATHBUFSZ); + NH_W2A(wbuf, tmp, bsize); + } # else *(tmp + GetModuleFileName((HANDLE)0, tmp, bsize)) = '\0'; # endif +#endif tmp2 = strrchr(tmp, PATH_SEPARATOR); if (tmp2) *tmp2 = '\0'; return tmp; @@ -356,4 +370,19 @@ char *str; const char amiga_version_string[] = AMIGA_VERSION_STRING; #endif +#ifdef WIN_CE +void nhce_message(FILE* f, const char* str, ...) +{ + va_list ap; + TCHAR wbuf[NHSTR_BUFSIZE]; + char buf[NHSTR_BUFSIZE]; + + va_start(ap, str); + vsprintf(buf, str, ap); + va_end(ap); + + MessageBox(NULL, NH_A2W(buf, wbuf, NHSTR_BUFSIZE), TEXT("Recover"), MB_OK); +} +#endif + /*recover.c*/ diff --git a/win/Qt/Install.Qt b/win/Qt/Install.Qt index fc2f4be..194a6bc 100644 --- a/win/Qt/Install.Qt +++ b/win/Qt/Install.Qt @@ -2,12 +2,12 @@ Installing NetHack with a Qt or KDE interface --------------------------------------------- This document describes the installation of NetHack with a Qt interface -on X11. The Qt interface is an alternative to the Athena-widgets interface -found in ../X11. You can download Qt for UNIX from http://www.troll.no. -You need Qt 2.0 or later to use this code. +on UNIX/X11 or Mac OS X. This code should also work with Qt/Windows, but +support for that is not currently official. -There are no explicit UNIX dependencies in this code, but we only regularly -test it under UNIX. If you have Qt for Windows, that should also work. +You can download Qt for UNIX and Qt for Windows from http://www.trolltech.com. +Qt for Mac OS X is currently only available commercially. You need Qt 2.0 or +later to use this code. To use this code: @@ -36,8 +36,10 @@ To use this code: 4. ../../Makefile (the top-level makefile) - change the VARDATND setting to contain the files "x11tiles" - and "rip.xpm". + change the VARDATND setting to contain the files "x11tiles", + "rip.xpm", and "nhsplash.xpm": + + VARDATND = x11tiles rip.xpm nhsplash.xpm 5. Follow all the instructions in ../../sys/unix/Install.unx for the remainder of the installation process. @@ -46,7 +48,7 @@ To use this code: likely to give the best interface for this window port: OPTIONS=name:player,number_pad,menustyle:partial,!time,showexp - OPTIONS=hilite_pet,toptenwin,msghistory:200 + OPTIONS=hilite_pet,toptenwin,msghistory:200,windowtype:Qt If you are using KDE, you may want to also try the KDE version. It just diff --git a/win/Qt/nhsplash.xpm b/win/Qt/nhsplash.xpm new file mode 100644 index 0000000..7850725 --- /dev/null +++ b/win/Qt/nhsplash.xpm @@ -0,0 +1,374 @@ +/* XPM */ +static char *noname[] = { +/* width height ncolors chars_per_pixel */ +"196 111 256 2", +/* colors */ +" ` c None", +" c #A094A7", +" . c #761C1B", +" X c #751A1A", +" o c #361414", +" O c #18181E", +" + c #CF0909", +" @ c #F4F2E2", +" # c #AD110F", +" $ c #AB0D0D", +" % c #C9BEC5", +" & c #CF977F", +" * c #627EB9", +" = c #512A21", +" - c #5F201B", +" ; c #A45841", +" : c #D3281D", +" > c #661B18", +" , c #78443A", +" < c #721110", +" 1 c #61332A", +" 2 c #7C231D", +" 3 c #533226", +" 4 c #978A8D", +" 5 c #AF0A0A", +" 6 c #841111", +" 7 c #783226", +" 8 c #B80D0C", +" 9 c #981514", +" 0 c #DDDACE", +" q c #881918", +" w c #B0A5B9", +" e c #74352F", +" r c #CCA799", +" t c #ADA8AC", +" y c #9B9897", +" u c #651413", +" i c #712C22", +" p c #710C0B", +" a c #8E1817", +" s c #861B19", +" d c #E4100C", +" f c #9B1010", +" g c #B49795", +" h c #EB0909", +" j c #3E302B", +" k c #8F5D53", +" l c #9E0909", +" z c #701717", +" x c #D1CBCF", +" c c #846E69", +" v c #9987A2", +" b c #291413", +" n c #281212", +" m c #691110", +" M c #BA0A0A", +" N c #DED4D5", +" B c #71291B", +" V c #918E90", +" C c #721F1C", +" Z c #664231", +" A c #7D1313", +" S c #C2B5C0", +" D c #6B332C", +" F c #D40909", +" G c #66625F", +" H c #460A0B", +" J c #446CCF", +" K c #CB0A0A", +" L c #BB100E", +" P c #867A85", +" I c #C64529", +" U c #273FA2", +" Y c #B70A0A", +" T c #A19AA6", +" R c #811B1A", +" E c #441916", +" W c #A50C0C", +" Q c #521110", +" ! c #C2BDC3", +" ~ c #580C0C", +" ^ c #0E0E0F", +" / c #481210", +" ( c #751818", +" ) c #E0DCDD", +" _ c #C90C0B", +" ' c #B5B2C0", +" ] c #A898B0", +" [ c #722522", +" { c #8F1B17", +" } c #78201E", +" | c #8D1515", +". c #7C1918", +".. c #831615", +".X c #E20909", +".o c #950909", +".O c #7D100F", +".+ c #9D7E7A", +".@ c #792C22", +".# c #878382", +".$ c #BC897E", +".% c #2C2622", +".& c #D7D4D7", +".* c #F30909", +".= c #693D33", +".- c #CDCBD7", +".; c #510C0B", +".: c #0E0B0B", +".> c #ABA3AF", +"., c #AE1914", +".< c #6B1414", +".1 c #CB0909", +".2 c #5B513C", +".3 c #65463C", +".4 c #1E2856", +".5 c #6A0909", +".6 c #8A3425", +".7 c #381913", +".8 c #930D0D", +".9 c #D5D099", +".0 c #774E3D", +".q c #403F35", +".w c #3F231D", +".e c #7B0909", +".r c #211110", +".t c #655A56", +".y c #171010", +".u c #BC6F59", +".i c #AB0A0A", +".p c #51423F", +".a c #931110", +".s c #D2C4AD", +".d c #7E6F7F", +".f c #7B1616", +".g c #BC1914", +".h c #602519", +".j c #DAD5C2", +".k c #B7AAA3", +".l c #9C231C", +".z c #67382D", +".x c #D90909", +".c c #BAB4BD", +".v c #A48997", +".b c #D2C4C4", +".n c #AF2B1E", +".m c #EBEAE3", +".M c #A30F0F", +".N c #7D1C1B", +".B c #841918", +".V c #931313", +".C c #8B1615", +".Z c #1A0D0C", +".A c #640909", +".S c #635A43", +".D c #C07D63", +".F c #8B0B0B", +".G c #651817", +".H c #C20909", +".J c #591715", +".K c #A21111", +".L c #9C3122", +".P c #6A241F", +".I c #9E0D0D", +".U c #775B53", +".Y c #A11513", +".T c #C7C3C9", +".R c #280D0C", +".E c #720909", +".W c #8D4941", +".Q c #5B5655", +".! c #8B1111", +".~ c #A54427", +".^ c #E1E0DF", +"./ c #8D4037", +".( c #A11B16", +".) c #727072", +"._ c #7C0C0C", +".` c #310E0E", +".' c #621110", +".] c #5A1212", +".[ c #B30A0A", +".{ c #532318", +".} c #521F17", +".| c #792623", +"X c #A7A29F", +"X. c #B6ABBB", +"XX c #7D1F1D", +"Xo c #908099", +"XO c #7B1B1B", +"X+ c #90878F", +"X@ c #C5B698", +"X# c #E90A0A", +"X$ c #100F0E", +"X% c #A50909", +"X& c #580909", +"X* c #2A1717", +"X= c #65503D", +"X- c #3D0C0C", +"X; c #B00E0D", +"X: c #807B7F", +"X> c #7A1D1D", +"X, c #781D1B", +"X< c #5A0F0E", +"X1 c #EF0909", +"X2 c #696765", +"X3 c #605B45", +"X4 c #CD130F", +"X5 c #D20A0A", +"X6 c #4C0A0A", +"X7 c #533E2B", +"X8 c #850A0A", +"X9 c #3C59B3", +"X0 c #C00C0C", +"Xq c #C70909", +"Xw c #971915", +"Xe c #7E1A1A", +"Xr c #7E7580", +"Xt c #5E0C0B", +"Xy c #5D0A0A", +"Xu c #520909", +"Xi c #8B2520", +"Xp c #C85C48", +"Xa c #CEC5CB", +"Xs c #6C2A1F", +"Xd c #642B21", +"Xf c #9B1212", +"Xg c #706A68", +"Xh c #841919", +"Xj c #A7999E", +"Xk c #69201C", +"Xl c #E7E0E0", +"Xz c #9C6F65", +"Xx c #C3B9C0", +"Xc c #826D48", +"Xv c #AFADA9", +"Xb c #8A2B22", +"Xn c #741413", +"Xm c #9A929B", +"XM c #CBB5B4", +"XN c #8F5341", +"XB c #783C31", +"XV c #73211F", +"XC c #911515", +"XZ c #630D0C", +"XA c #881616", +"XS c #E5E4E1", +"XD c #6E1B1A", +"XF c #DC0A09", +"XG c #741616", +"XH c #8E7F85", +"XJ c #591B19", +"XK c #8A201B", +"XL c #BE0909", +"XP c #4E1A18", +"XI c #FEFDF6", +"XU c #6A0C0C", +/* pixels */ +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XIXI.m ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XIXIXIXI.j ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XIXIXIXI.$Xl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.b.s N.D.$ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ).S.~.~.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.c kXp N ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` g I.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xx.~ & ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^ ;.uXl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.+Xp.j ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `X ; r ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.T ; & ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^XzXp N ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` g.~.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XlXMXMXM r &XMXM N ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xx.~ & ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xl rXp : :X#.X h hX#.X :.X.X.X.x.x :Xp.u &.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^XN.uXl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.b & :X#X1.*.* : dX5.x F _ K.,.nX0 _X5 _ FXFX4X4.x.xXp.D r N ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.+Xp.j ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.s :X# hX1 h.XX5 8 L.LXw 9 9Xh q.|XB 2 qXCXC |.VXi.6X; # _ _.x.X :.D r ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `X Xp r ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` NXpX#.*.* :X4 _X;.KXhXh.=.| X X.< i 1 1 1.P i.G u.<.=.zX>XhXh.V | #X;.n KX4Xp rXl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.T ; & `Xl r.$XpXpXpXp.$.$XM N ` ` ` ` ` ` ` `XIXI 0 ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XlXpX#.*X1.*X5.,.6 2XhXO z D.=.3.3 GX2.).d.dXrXrXrXo P PXrXg.3 , DXk zXO [ , {.KX0 _ KXp rXl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^ ;XpX0 8 # | a. RXhXe qXf.L.u rXl ` ` `XIXIXI @.k ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` 0 & :.*.*X#X0.K R.=XDXd.=.t GX2X2.).d P P P P PXoXoXoXo ] ] v ] vX+.# V.d.U.3.P.NXhXC.VX0X0 _.DXM ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XlXpXF.!.~ { XXD.< > D u.'.XOXCXK.L _ : &Xl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` 0.uXFX0XCXD.~.L.U P P PX+ P P.d.U.3Xd -XJ.f ; @ 0 0.+ g ) ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.SXcXcXN.6.|X,.'XJ.Q G G G P PXo PXrXo vXo v v v ] vX+Xo vXo v ] ] ] ] wXmXm T.>XmXm c.U 1.z q.KX0 +Xp.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `X@ IX# 8.! [XrXB kXj v v vXoXoXo v vXoX+.U D , @.j @ c.m.m ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` eX7XcXcXzXb.V f.8 pXd.t.d.d.d.) P.d P P ]Xo PXo vXo vX+ v vXo v v ] wXmXm TXm T.> w w ' w.d.W C RXC #X0 I rXS ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.+X0 h.* 8 f { k.3Xz.b v vXo v v v v v vXoXo.k g @.s c.s r ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.WXz.mXS.j i.N aXC.V 6.O.6.d.d.)Xr P P.dXr PXo P PXoXoX+ PX+ vXm ]XmXmXmXm T T w.>.> w.>.> wX..> c ,XGXh.K 8.n &Xl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `X@.NX0.*.*Xq $ $Xp.sXzXzXoXoXo v vXoXo vXoXo P.s @X@.q o (./XM ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.WXz.mXS.D .X>.NXh qXb 2.o.8 ,.).dXo P P P v PXoXoX+ PXo vX+ vXm VXmXm Xm ] ] ].> w T.>.> w.> w.> tX..c wXz e i , #.g &Xl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.jXMXi 8.*.*X5 $.,.p.yXs.uXo v vXoXo v vXo ].kX3 O.yX2.U 3 A ;XM ` ` ` ` ` ` `.-XS ` ` ` ` `.WXz.mXSXbX> <.fX, }.= 7 |.M.oXC.0Xr.)Xr P P PXo PX: PXHXoX+ v V V XmXm ] ] ] w w w w wX. TX. w wX. S.cX..cXj c C |.K.g &Xl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ).^ 0.b.| W.*.* + 5.F.yX$ 3.~ k v v v v v T .%.j 0.4 J.4.4X9 U.d.-.-XS.- * J J J J.- ` ` `.W ;.m.j.P X iXdXZ > i [.NXhXf.! { A.U P PXo P P PXoX+Xo vXoX+X+XmXm VXmXmXm ]Xm ] T wX. w.>X. w wX. tX.X.X..c SXx t c [XhX; 8.u N ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XS 0 ` `.bXiX0X1.*.x 8X0X-.% k.~.n.WXo v v ] ] ].) 4XI.- J J J J U U U U U U UX9 U U J J JX9 * w ,.W @X@Xd.< [.|.< Q.=.P zX>.N s ,XC.8.l kXoXr P vXoXo v X+X+ VXmXm ]XmXmXmXm ] T T T w.>.>.>.>X. t tX. ' S S.c.c.c.c !.+ iXh 9 8.DXl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xx.m ` ` `.bXbX;X1.*XF.I.[.Z.% j.~ & @ 0Xm ] N !.d &X9X9.- `Xl.Q O.4.4.4.4 O O O O.Q.4 U U U * J.= i @.u ( mXnX>X>.'.p G.t.z C D.=.| a.V.oXb cXoXo PX+X+X+ vXmXmXmXmXm ] wXm T T.> w.>.>.>X..> tX..c t.c.c !.c S !.T.T.T.TXj k. ./.n &Xl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` 0 ` ` ` ` `.bXi L.*.*.X.I lXtX* j B.D.s gXIXIXI J.Q 0XIXIXIXIXIX+.4.4 U U.p.4.Q.% O.q.)X2X9 J J /.G 0.uX, - 1XnX, iXP.QX2X2X2.3 D X.NXeXA s.C.6 cX+X+X+ w v ]Xm V ] wXm T T w wX. w wX.X. tX.X.X..cX..c.T !.T.TXa.-.T.-Xa ! c [.K.g r ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.bXi M.X.*X#X;.!.i l =.w.~.$.m @ ` J.-XIXIXI @ 0 0 gXoXo ] .) j.4Xo.- ` `.>X9.]XnX@Xb.N - G.=.P DXkXJX2X2X2XgXg G.= CX>.= 7.V W.6.dX+X+XmX+XmXmX+ Xm T T TX. w w.>X..>X..> tX..c SXv S ! !Xx !Xa.T.T.-.T.TXa.c kXO.M :XM ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.bXi 8 h.* h.[XD <.i./.3Xp.uXl ' J *XIXIXI.sX3X@.sXo v ] T T .U./.b ` ` `.^.J }.U i.P - G GXd z.N.<.pX2X2XgXg.).).) G.3 [.N a f |./ P vXmXm V VXm ] T T ] T T T w.>.> wX.X.X.X.X..c.c !XaX.Xx ! ! !XaXaXaXaXaXa.&.& S.WXA.KXpXM ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.bXi.,.X.*.*X0 eXVX;.,.UXp & J J J `XI @.s.q.+ @.s ] ] ] T wX. 4 e.$ ` ` ` zXD D DXVXJ G G GXdXGXV 3.QX2XgXg.).).).).).) ,.PXe.@ 7.I.WX+Xm ] Xm TXm TXm.>.>.>.> T.>X.X. tX. tX..c.c S.T ! !.T !.T.TXa.TXa.-Xa x.&.& xXj.W a #.u ) ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.m ) ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` xXi M h.*.* _.W.UXOX%./ ;.W J J J @ @X@.%Xg @.jXj ] ] ] ].>X. w ! ) g.W N.bX6Xn.f . (Xk G GX2X2 1.z DXJXgXg.).).).).).).)XrXr.U.S D R f.Y.WX+XmXm ]Xm T T T T T.>.>.> t w.c t tX..c S.c.c ! % ! !.T.T x x !Xa.& x.&.&.&.&.&.k.WXi ; & ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XS.9.q y ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.bXiX;XFX1 h K.6Xo ,.OX U.6 J JXl 0.t j O.+.s c ] ] ] ]X.X. ! ` ` ` NXlXM.G zX>X> .XJ G GX2X2 GXD. XD.pXg.).).).).).).)XrXrX:X:Xg ,.|XhXi.@.W.v ] T TXm T w.>X..>.> w w tX..c.c S.c.c.c ! ! !.T.T.T xXaXa x.&Xa x.& x.&.& ) ).c.U a IXM ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XM.k.9.qX$ t ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.bXi.( F.*.* F.LXHXo y ^.4.L.dX9Xx.q.q.4.% c g k.v ] w.cX. x ` ` ` ` `.k Q .XVXV C.{ G GX2X2X2 G > C 3.t.).).).).).).)XrXrX:X:X:X:X:.U.U e.C 9.WXm T T TX..>.>.>X. wX.X.X. S.c.c.c.cXx.T.T !.T.T.TXa.T.-.- x.& x.&.& ).& ) ) ).&.v 2Xf.uXl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` `XS.jX@X X .c ` ` ` ` ` ` ` ` ` ` ` ` ` ` r.g.H./X@.qX$ O.^ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XMXh 8X#.*.*X5.l P.4 J O ^.h rXI 0 ' *X+ @ 0.+ c.W gX.X. x ` ` ` ` `.+.'XV D D [.J GX2X2X2X2Xg GXd D -.).).).).).)XrXrX:X:X:X:X:.#.#.#Xr , }.CXb kXm T.>.>.>.>.> w wX..c !X..c.c.c.c.T ! !.TXa.T.T.T.T x x x.& x.&.& ).& ) ) ).^ !Xz |., & ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` `.m 0.s.kX cXcX3X3X3X3Xv r.D.$.+.kXS ` ` ` ` ` rX5.xX5 = O.yX$X$X: ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` rXh 8XFX#.*.XX;X2 J J U ^.+ @ @ 0.t.+.s.+ 4 ] kXz.v ! ` ` ` ` ` cX6Xn.f .XGXJ GX2X2X2XgXg.).t X.<.p.).).).)Xg.)XrX:X:X:X:.3Xg.#.#.#.#.#.U.U.@Xw ;Xm.> w.> t w tX..cX..c.c.c %Xx.T !.T.-Xa !.- x.TXa x x x.& x ) ) ) ) )XSXSXS.&Xx kXfXp.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` `.m.jX@ cXcXcX3X3X3.p.q.2.q.. I ;.~Xi.@ ,XM ` ` ` NX4X1.* FXPX$X$X$X$ O ` ` ` ` ` ` ` ` `Xl N ` ` ` ` ` ` ` r |.,X5 h.* h.l J J J J.4.2 =.p.4 O O O.% wX.X. %XMXz g ` ` ` `.0 < XXOX,XnXP GX2X2X2XgXg.).).U.PX7 G.).).) =.w.)X:X:X:.q o j.#.#.#.#X+X+ V c ,..XwXzXjX.X. S '.cX.X..c.cX..cXx !.T.TXa.T.T.TXa x x.- x.&.& )XS.m.m ` ` ` ` ` ` ` `XM./.K.$ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` `.j.+ c.2.q.q j j j j.q.q.q.h ; &.u.~ #Xh RX> r ` `Xp h.*.*.oXZ.yX$X$X$X$.T ` ` `Xl k.^ ` `.D j.^ ` ` ` g ` ` `.k q 8.xX#.* d J J J J.4 ^ ^ BXs O ^ O ^X9X..k.& ` ` N ` ` x `XJ.] }XV C C =X2X2X2.Q.w G.).).) 3 i -.).).Q oX*.w.)X:.3.r o b G.#.#Xr.tX+ V V VXH k.U { k T S.cX..c.c.c.c.cXxXx.c !.TXa.T.T x xXa x )XS ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` gXM ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` `.+.% O O O.y.y.y O O O.%.% |.D &.D.(.K.VXC R.f g rXq.x.1 MX8X6 QX$X$X$X$ y ` ` ` g o.Q ` x E n.Q ` ` r E.# ` ` ` r q 8X5 hX1 J J J.4X9X9 U ^ 1.~.4 ^.y.4 * 2.3.^ ` ` ` !.:X: HXt i [ [XD 1X2X2 G.w oX*.t.)X2X* QX>.3.) oX* o n.w.Q b b o n.%X:.p o o.# V V V V V y c.6 {XzX..c.c.c.c S !XxXxXx !.T.TXa.T x.^ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` `.T.c.c.c yX:.).pX$X$X$ OX*Xb ; ; :.i W.MXf.YX;Xq M.M fXUXyXuXu q QX$X$X$.% ! ` `.W.Z.r y.D n n.Z t ` 1 b n.T ` ` `.$ a.,Xq & * J U J U U J U O.4.~ U U UX9.pXP.p.^ `.^.%.:.r HX<.f. .NXn.7.QX2.q b o bX*.t j.r o =X7 = nX* o n nX* bX* o n b.w n o o.t V V V VXm y y yXH c.6XzX..c.cXa !.T !.T !Xa x.^ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` `.^ y.pX$.r._.M.a.FX%XL K.1 L.a M.xX;.!X6X-X- H R zX-X$.y.Z.p ` x.7.Z.ZX* j.r n.ZX* g o b.r j ` ` ` `Xz.L.jXI.- J.4 J J J U U O O.4.6 U U U U.q.7.U `.+ oXJ o H < (Xn ..'.`X*.Q o b o n bX* b b o n.J Q nX* o.r.r b b o b n o bX* o b.q V V VXg.w V y y y y 4 kXiXz.c ! ! !Xx.T x.m ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` `.z.F $.. R.! W $XF F.F $ K.[ f Q Q.J Q.G z.f <.` o.ZX$ y.v.r.Z.r.y.y.r n.y.Z.7 n b.r.r.t.$.$ rXz.~ 2XK.~.QX9 J.- @.s.q.4.4 ^ UX9 UX9X9 U.4X*.U E EXJ /.' XXV [XV.<.` b b b b o n b b n b o b nXJ.w b b.r.rX* n o n.r o b o o bX* VX+.pX* o.t y y y y T TX .+XN.u S.T xXS ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` `Xz M.[ f.C.C K +.MXA.F.oX#.*.1X8 u u -. EXk.{XP.{.{ - (XJ >._.]XPX.SXV u./Xc.(.O.].h.JXy.`.R /.h B B.h.uXI.m./.n.nXK.7.}.Z.RXU.i l f {.l.' ~.'.B.f X zXtX- HX-XuXuX6X&X&X6XyXuX&.AX6X&XuX mXu.]XV 3 -X7 1 j = 3XP 1 =Xd =.6X= DXf a.3.~XG.aXw.h.!X&Xu.R.}.h B.~.h 0.mX7 I.n.LXK.h /X-X6XuX& j.q.pX6.A.' XXD }XO.; / ~X&X6.AX&.E.E ~.E.A ~.E.A.5.5.A < < <.hXs.hXU.o l M.M.K {._ B 3.! z.J /XkXP.}XD E.}.k.=.} C.U ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` `Xl.V m 8.* WXh 6 W W.8 ~ >.J j.D.9.h.~.~X7 OXG z Q.]XPXV 3XJ =.P j.P 1 - 1.PXd 3.N ,.|...6./.K #.I.!.F.E.e HX-.h B B.h.z @.%.n.n.n.L B.}X<. >XkXJ.3 jX6.AXU q.f X <.;X- Q ~Xy.E.E.5.eXU.E.eXUX8.EXt.E.5 p (.< 6 Z.~., K., LX0 8.M |._Xd 7X;., W.O.G.<.}XP E - E -Xk.}.^ ` ` N ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` 7 I $.* _.VX;.FX;.VXi.| u.v &.D.~.6.6X7 O /XDXb.J E = C =.PXJXkXdXX - -XJ.PXJ.PXK D.! R.=Xb 9 f.V.Y.8.o.e H.}.h B B.7.m.%XK { 2XK B.{ /.! 6 [ iXA mX&.5Xt AXn (XZ ~ ~Xt.;.;.5.e.E.e.e.EX8.o.F 5.o 5X%X% l (.,.u.u.~.g.H +.,.l.(.(Xw.8XKXw M $.[.aXb.!.'XP EXJXDXPXP.k N cX>Xx ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` `.j.~ $ YXq.[.o l.a #XhXKXXXC.u.9.D I.h 7.q O o Q. } Q -.]XJ.].J z u.]XPXXy.EXU uXnXG C p.' Q QXt.;.E.eX8 YXq _.x +.x.x.1 K FX;X5 K _ : I IX4.g.n.g.n.YXw.LXK p.8 K M M $X0 $.i 7.h.X-.`.R.r j cX@.sX@ qX8.o.E.A.'.eX8XU < A.fXU QX7X=X3X3.2 D R.N 7 e e 7XXXhXh q a.K.MX; 8X4.D.D.u.u.DXcXcXc ;.L., #.M.!.8 MX; LX;X0.L F.HX0X5Xq +X0 8.@XkXJXJ - }XP.b ` ` `.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` rXL.1.X +.XX#.H 8 f f.V 6 p.] R 9 # LX0.( z.<.G Q.]X&XZ.A.A.A.AX&XyXZ.A.AXyXUXZ p.E p A aXGXh..XAXAXh. . |Xh q 9.KXf.! z i <.'.;.R.:X$X*.q 3X@XNXK.o.e.E.5.E.EX8.F AXZ uX> } DX=X3 D i.= Z.SX=.=.|X>X>X>X>X>X>X>.|X=.SXc.0.6./XcXcXc.~.,.( # 9.M.O lX; W Y.[ _Xq.1X0.g K.HXqXq.g.~.~ A. .}.}.+ g.U.PXB ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` `.b.g FXF F F +.x W.[.[.M f 9...fXh.N RXOX<.|XkXD (.'XZXU ~X& ~.A ~XZXt.AXZ.AXU.AXZ.5.A p.f.fX>. Xe X. XwXA | qXe s.f.fXeXh.(.| 6.V |.F B.`.R.R.R b.z.u.sXw.EX8XU.EX8.!.FXZ XX>X>X> [ D.=.=.SX3X3.SX=.6XC.V | | |Xh.|.SX3.S.2.3Xd 1.2.3 Z eXf.I W $.a fX8 #.M M $X0 MXq.H K _.1 KX5Xq _X0.H.l 7 u - E -XX.}.^ `.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` I _ F.X.X F.H.[.oX% $.K..Xf q.NXeXeXO.N.'.<.P m ~.'XZXZXuX&XZXZX.N RXV D.SX3X3X3X3.S { W.M.M $ f.6XcXcXc , 7XiXK 7XB.zXs z z. .! W.a.a.IX; 8X; W.[ MX0XqXL K _ _ F KX5 +.g.~XNXw. -.}.+.W.l.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` &XL l FX1.X + F.M.Y.C.V mXh qXh z mX>.'.f u u.JXGXuXZX& Q Q.' u u.]X<.J.G -Xk.G.PXD CXD ..fXG.fXhX,.NX> X R.N. .Xw a |XCXhXCXD q A A.BXn.{ 7 /X6 ~XD / 3 &.j 6 9 ( W.[.a | 6 6XGXO.V.MXf s 7.SX3X3X3.S.3XV.NXh | f #./XcXc.L.,.( _.Y.lXw.M l.! . C (.!.!.F f.K.MX0X;X; 8.[X0.[.HXF.1 F + +.x.x + _Xq { u [XJXbXiXz ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` `.$.xXLX0XqX5.H.H.H 5 $.V. .< zXhXh R..} 7XD f 6.Y.B EXz.9XwXiXb L.x hX5XL.[.f.. W f.K $.M./XcXc.UXcX3.=X>X>X>X> R qXb.6.K M $ M 5.[ WX%.i l.8 qXe XXG.F._.K.a f f #.M _., _X; K _X0.H F FX5.x F K ; ;.6 s.l.} e `XMXp.$ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` `.$ _ F.1X0.H +.X h FXL f |.fXG XXh R. XG m z.'XyX&.'.]X<.G ~XJ.z.=XB 7 DXs 7 i -Xk.h = 1 ZX=X=.= D D D [XVX> .Xh.NX>Xh.N aXe {XeXV {.CXh 9Xf.{.}XbXiXA..Xf.C.N.P -.(XbXw _.x.xXF Y M. | K fXCX; 9.(XcXcXcXzXc.~ WXf.YXh.NX>X,X>XAXf.K f f 9.iX%X%X%X%.a sXA.fXn.e. .I |.( a.M #.( #.H 8.nX0Xq KX5X5X5 +XF.g :X4 _X; XXJ e.P.n.P N ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` NX5X#XF FXq.x F.X + +XL.KXCXh.<.<.G.< 2XX A aXe a.N.N q RXeXhXC.N q /.} e.NXA | a.C | [.= eXi #Xq.x.HXFX;XL..XC $ #.V.K L #./ ;XcXcXc.g $X; 8X; _XfXCXC. }XVXkXsXdXkXnXn A.8.8.BXA A A.O.O...KXKXC 6.VXK 9.IX0.( # W.[.g L +.x.xXF +XF.x :.~.Y.fXb.lXVXz ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` `.$XqX%.x F.[X5XLX&X6.`._ qXhXn.<.; mX>X,XnXZ pXU.< uX& ~.G Q.J N ` ` ` ` ` ` ` ` ` ` ` `Xl gXN CXd.= D } i.z C.=.= [XX.NXG |XO ..| RXCXh s.NXC.` = eXw | a.Y.Y qXX.S.=.,., _ F.H.1 FXFXf 9Xf.MX0XCXfX0 f.Y.nXNXc.L.gX0 9.( L.VXf 8.K |XwXKXi.6.,.Y 8 f.aX,.PXV. A.O._ a.BXK s f a { {.VXf.(.(.KX0.,., # MX5 _ FX5.X :.u I.g 8.B iXV.b.$.L.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` k <.;.RX8 $.x.F.5 H.RX-.|.| XXZ p <.N X u.5XUX6XtX& ~ ~XD ~.+ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` N.$ e uX>XV D.=.3 i } e.| zXnXi.P X...NX> a.C u.` CXC aXhXhXhXh { eX= D RXF.x hXqXLXLX0X;Xf 9Xf 9.V.V $.M f.(.L.n.6.6.,.lXb.l L 9.MX0.(Xw.@.L 7.(X; # LX;.(.(XiXs.z C.O < s 7Xi..XwXiXK f.V.(XK a.M.(.L., M L.~X4 +.XX4XFXF.XX4.g.IXKXDXbXb.W ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` k m.;.R.R f.I.F.F.F.A.e [ e [.< pX,. X,XG u.`.:.; ~ ~.G -XV ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XMXz.JXJ -.|X> C i [ [ 2 ZXkXhXn |.NXn.C.7 /XhXe.BXCXh.NXh.@.U.U 7 9 F.HXqXF.[X;.MXLX5.K a a # #.VX;.(Xb.L.n./.6.l.LXb {.VX;Xf.V.Y 9XX.l eXwXwXi L.,.l.l.l.@ iXd.< p i.@.B R i e R R {.|XA #.Y {XbXK LX;.L.L LX5 IX4.x d.u.D I + A.l.|Xs.+ ` ` `Xl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` `.+.J.. 6._.! AX8X8 YX#.X 7.= iXOXnX>X, X.<.`.:.:X-.J ~ .XyXz ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xl.v e z u zX>.| DX= [.N ..f qXG 6.J.Z.<. Xf A..XA 9XX e Z.@.,.x 8XLX; FX; $ fX;Xf 8 aXhXA.MXA.V.n./.0.W./.6Xb.lX0XC.C.M.. 2.l L q.(XV i ZX=.~.6.(XK.6 7XK 2Xk.G uX> } i.|X>..XK 2 2.NXA {Xb {.Y.K f.l./X4X0.L.gXF :Xp : dX#.X M a.P.6 NXx k.z ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` N i.L I :XK.|.'X8.H +.(.= DXk XX>X>X>.G.R.:.:.: E Q.' } ~XM ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XM k u u C i }X>X>XG }.f.O u.Z EXe.fXn. .! 6Xe.6 6.Y F.1.1.1 + $XLX; +Xf 9 |X;X0 a A 9 |.C {XB ,XB.6.n.6XKXf 9 |.K # 2XX {.C } D.P 1.z.6Xi.YX% {XbXw 6 2 C.JXD.@ i 2.N } i }X>Xh s s.| RXh a |XiXb.M 8.g.~X0X4 IX4.*X1 I :.XX; s 1 E > EXM ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` `.s ;.~.6 D [ R < z i [ C }XG XX>X>.J.:.:.:X$.: EXP.P.' i ` ` ` ` ` ` ` ` ` ` ` `XM N ` ` ` ` ` ` ` ` ` ` ` ` ` ` 3.`.].'X> CX>XGXGXD >.r.R.f z A.B 6._ 9. .I.*.X h.1.HXLXF.[ $ $X0 8.V | f qXCXG |.K., s.6.~XBXBXb.L s.C.Y #XA aXi iXK {.zXXXn >XkXD 6 l Y Y q 7.NXD X C.hX=.S i }.=.3 [X, R [ 2X>.N RXC 2 2 |.YXf.Y ; MX;.n : h IXp IX1.X _XX>XD >.R.:.:X$X$X$.:XP.} 1 uXz ` ` ` ` ` ` ` ` ` N.DXp.~Xi.uXM ` ` ` ` ` ` ` ` ` ` ` g =.w.Z.r.R.`.R.;.. /X$ oXnXnXG.f.f._ p 6 #.1.*.x.* h.HXL.[Xq W.MXfX; | qXAXeXC |XhXA.MXh s./ ,XB 7XB.,XhXh.( [XB.0.0 7.6 , > u.].hXJ z.I.F Y.8 i B...B < mXH g.+ cX:.0 i i.=X= DX>.NXX.N sX>XOXhXhXK.(.KXf.L.n.x d I.*.*.*X1.X.I E E i ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` `.+.=.@.N. .N.N.NX> .X-.`.: ^X$X$.:X$X$.:X- = - Q N ` ` ` ` ` ` `XS 0Xp d & d I.l 6 p <.U ! ` ` ` ` ` ` ` c = - - /.R.r.R.7 n o >X> X.N XX,.f <.E.I.H.H F.XXq hX0.H.i.H fXf a 8 L.Y.f.N f 9 R R 9 aXhXBXN.6 2.@Xi. .| 2./ , Z.UX=Xs.z - ~ m ~.J.G .N RXeXh 9Xi.YX;.g I h d : :.* h K.J.W.&.+XP.& ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` `XM.W.NX>X>XD.J.`.r O ^X$X$X$X$.:X$.:.: QXd u k ` ` ` ` ` ` `.m 0.j &X@.j : ;.n..X&.J =X7 c.^ ` ` ` `.^ =XJ.GX< ~XZ.'. -.O.[.IXq K.H.xXL.x.1X5 MX% $X;Xh 9XA 9XC ..f.V.CXe q.(.6XB.@ {.| 7 7Xb i i Z DXG.0.0Xd Z.h Q.}X7.{.{.G m 6Xn.PXsXn p.O.E ~.b ` ` ` ` ` ` ` ` ` ` ` ` % g.+.U.= [.NX>.N R.N.YXf 9., MX4 :.*.*.*X#.H ; 3 E o.v ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` `.^.%.y.yX$ ^ OX* OX$ OX$X$X$.:X$.:.y.J -.]XM ` ` ` ` `.m.m.m.mXS.sXzXBXi {XCXe / BX7.wXZ DXM ` ` `.k.}.}.' H ~X&Xy.<.; E.{ -.G u u z . { K.I.C L + 8X#Xq _.1XLXq.I f $XA q RXAXf.N.f A.Y a. .|.6 i.| 2.6 1 Z 1 , 1.2.z.{.h.3.{ 3 3 ZX7.2.2.2X= 1.h.G >XD.. 6 p pXt ..b ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XlXM 4 k D }Xh.NXh a |.K #.,XLXF d h.X F / E o = ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` `.T.% j.p G.Q.q 4.%.qX$.%.:.:.:X$.R.P.J.W ` ` ` ` ` ` ` ` ` ` ` ` g./ D , k -.w jX7X7 /X-X-.p.+.k.U.{.J HX& ~.;X& m u E EX7X= Z 1Xd X A 6.8.B.YX5.K dXF 8.H MXL _.I.a.! R.NXhXh.. z (. XhXOXX 7XB.=.=XB Z.3.2.S 3 - e.{.{ 1 =X7 3.S.2X3X3Xv `XS 4Xd QXX> X a.! f 8X; +XFXF FX<.7 EXM ` `.& ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` `.bXg GX:.Q.q.t j.%.y j.:X$.:X$.`.h.< % ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` g 3 j jX7 j j.7.7.%.w.w.w QX-.; /.;Xt.< k.U =.2 Z.SX3X3Xd ..B.aXA $.[.Y.K.XX;X5XL Y.i.H.!.8 9XO.NXe {XnXO.N aXCXOX,XK i e.=.0.2 1.2 1 3 1 3X7.PX=.2 [ Z.SX3Xv ` ` ` ` NXz.J ~XUXZXt.A.E.eXw.+ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XMXz.@ }X> {.. f.OX8XLXq.x.H.O.JXM x.p.3 ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ).#.) V.% O.%.Q.y.y.yX$.:X$ b E.' k ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xv.t j j.w.w.7.7.wX*.7X- / /X6 ~.' g ` %.3.3 Z.SX3X3X=Xh.C.K.V.aX%.I.(X5 LX#.X M.i.i.I 6 < 6.NXO.N R.NXOX> (.NX> a a C.=XcX7X7 ZX=.2.3X7.2X7.S i .X= c x ` ` ` ` ` ` `.kXJX6 HX6.A.5X%.1XL.LXl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XS.k.WX>.NXe.C 6X%.I M.1Xq K.~X* n o N ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` `Xv G x.qX$X$ G OX$X$X$X$ ^ =XJ.P.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xx 1 /.w j.w E / HX- /X6Xt.' g ` ` `.+.= [ ZX3.S.S i CXV C. X% $XwX;X;XLX#.i.[X% l._Xy < 9X>XO.N qX> X.N a.N.N 2Xs.3.S.SX3.2X7X3X7.SX3 Z [.|.0Xj ` ` ` ` ` ` ` ` ` N.J / H HX&.5.X h.x 5.W ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XM k iXeXO.K 6.8 YXq 8.8.Z.r.r r ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` x.Q `.)X$.:.q.%X$X$X$X$ b D u.+ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^.2 E.;.;.; Q Q.w /.;XD g ` ` ` ` `.W } i.SX3.SX= zXV.P.P.!.i {Xw #.i + + MX% l.[XZXZ.NXhX>X>Xh R [ [XK.| i.3.S.2.S.2X3X3.SX3X3 Z.= }XzXv ` ` ` ` ` ` ` ` ` ` ` `XB.]X< ~Xu.e F.x.*XqX8.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` N kX> } X 6 W l W.[XU.y.r g ` ` yXM ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` `XSXg ! t.q.q.%.q.yX$X$ O - i ,XS ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^ kXuXu.; QXP.w Q >.b ` ` ` ` ` `Xl.WX>.|X=.S.S =.G C.P.B 8XKXw # 5XL.H.H Y.o.O p.'.NXhX> XX>.|.| [.|.@X=.SX3X3X3X3X3.SX3X3X3.0.$Xl ` ` ` ` ` ` ` ` ` ` ` ` ` ` gXy.5.5.E.e.8 l.i lX8 g ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` %.U.N. Xn.O.F.I $._ Q.nXMX X$.+ ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` !X `.Q.#.q.%.%X$ ^.'X>Xs.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.vXuXuXP j = >.b ` ` ` ` ` ` ` `Xl.WX> }.0X3.S ZXd [.|X,. 2.[ W.HXL 5Xq.F } m uX,.N 2 [ D.=.= D [ iXB ZX=X3X3X3X3X3X3 cXv ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^X&Xy.E.E u =X8.E.E.A.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` g 7 i X.O <.F $ f 6.C =X$X= ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xv ` c c.p j c ^ n s. .v ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.b ,.w Q ,.b ` ` ` ` ` ` ` ` ` `XlXz [ D.S.S.2 3 1.z 1 C C W.[.i Y Y 5.C 7 -.'X> } C.| [ }XX }XV D.=.=.=.3X=.2 3 3 /.& ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` kX&.E.eXU =X<.5Xy.P ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` N.+ DX, iXn A.O.F.a ~ ~XP.+ 4 cXB r ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.v k.W.W.n.7.G.BXz ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XM ,.3X3X3X=.zX7Xs z.O.o 5X% M.i.i.YXNXd ~X> } }X>X>XD C.P - -.G Q / HX-.7X6X6 k ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` NX&.AX8.o.~ B.E.A k ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` % kX=.@ R Z.fXV.P < D 1 ZX3 c ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` g.xX#XF _.Y.N.WXS ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xl.$XB.3.3.= i > z.O l 5.o 5X;X% W.6 BXt k g.$.$.kXxXM.3XuXuX6 H HX6X6X6Xu e.^ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` e.E.o l.6.n M.e.+ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.b.+ i.S e.zX3.zX3X3.S c ) ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` NX0.*.*.KXXXzXl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` r.+XBXVXV >.< p._.F.o # l l.CXB.]XM ` ` ` ` `.b -XuXuX6X6XuXuXuXu.J.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.+Xy.e {.l YX%.e.$ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XS.k.# k.S.S c cXv ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.$X5 9./.k ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` NXM r./.'.5X8._ 8 l.i l 2 6 g ` ` ` ` ` k -X6Xu ~.;XuXuXu.J.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XM ~.{X=.n.1X%.eXM ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` N.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xl./X&.e.E l M FXL.Y.e.+ ` ` ` ` `.|XdX,.'XD.J u u k N ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^X7X7 Z.~X4 5.oXM ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^XB.5.F 5XF.*.X f.o.W ` ` ` ` ` DXD D > D >XD.PXM ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^.w.hXKXpX4 Y.o.$ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ;.i.i.1X#.xXF $.o.G ` ` ` ` `.= } Z z Z DXDXVXl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `X .w u. .~X0Xq l k ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.$.i Y.[Xq + + 8.a.E , ` ` ` ` `.2 [X=Xd.3.S ZXz ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` 1XU p B.6 L Y.iXb ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.k ;.[Xq.1.iX;.i._ p.e.E.+ ` ` ` ` `.p.=.SX7.P.z ,Xl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.kX&.EX8.iX0Xq YX%. .b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `X e l.1.XXF.H.C.f.FXU.AXy , ` ` ` ` ` `.pXP i 3.y.yXl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^.GXy.E l.i M.[Xq 5X8.+ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` k 2.Y.X hX1Xq.8 1 mXt QXd g ` ` ` ` ` ` `.).p n o.% O ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xz.A p.F l.i M + Y lX8Xz ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.+ 6 YX5.*X1 5.F m.{ Q.U.k ` ` ` ` ` ` ` ` `.cX:X$.p.).p ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` NXu.A.5 l Y.xX1 +.H 5X8.W ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` 1 l.1.*.xX; >.}.UX XS ` ` ` ` ` ` ` ` ` ` ` ` tX$X:.c.p ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `XMXy.5 p.o Y.*.*.x.1XL l > ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xl k.<.iXL.X.i 3X7Xx ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^X$ y ` G ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xz /.A p.[X5X#X1.XXLX%.o [ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xl.gX0 B.i F.[.GX3.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.q.c `.^ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.$ lX8 ~.5X8.oXL.x.i.iX8X8.+ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.D IX0., + F._.t.^ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` y.c ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xi 8 IXtX&.E.E lX%.F.E.A e ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xp., :X4 :X5.!.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.b.B.6.l.IXF.8.[.*.*X0 q.+ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xz.g I.~ d.gXX N ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.b.|./ 6 8 :.V.g.D d.g ; ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.D.~.n ; ;.l k ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` NXB 7.V.,.u |.~ d.X., k ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` gXN.0.(XNXB.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `./X, aXN.gXA./ ;.g.Y g ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` gXi 1.s.D N ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.k 1XiXN ; 7 ,XcXcXBXl ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.T.sXz.s 0 ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` y.q ,.0XcXd {.L.0XM ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xv.s.j.sXS ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `X .p [Xb.6.w.$.D r ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.&.s.^.b ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.# y.+./ 7 k.k.sXS ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.s ` x ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` VXa.#.s.s.m V.s ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.T ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.&XS V.s.s `X .s ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.^ ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.c.j 0 `Xv 0 ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `X ) ` `.^ y ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `.TXv ` ` `.& ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `Xg ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `", +" ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` x ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` ` `" +}; diff --git a/win/Qt/qt_clust.cpp b/win/Qt/qt_clust.cpp index 024d2c2..e5952c5 100644 --- a/win/Qt/qt_clust.cpp +++ b/win/Qt/qt_clust.cpp @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)qt_clust.cpp 3.3 1999/11/19 */ +/* SCCS Id: @(#)qt_clust.cpp 3.4 1999/11/19 */ /* Copyright (c) Warwick Allison, 1999. */ /* NetHack may be freely redistributed. See license for details. */ #include "qt_clust.h" diff --git a/win/Qt/qt_win.cpp b/win/Qt/qt_win.cpp index 001967a..23096a3 100644 --- a/win/Qt/qt_win.cpp +++ b/win/Qt/qt_win.cpp @@ -1,14 +1,10 @@ -// SCCS Id: @(#)qt_win.cpp 3.3 1999/11/19 +// SCCS Id: @(#)qt_win.cpp 3.4 1999/11/19 // Copyright (c) Warwick Allison, 1999. // NetHack may be freely redistributed. See license for details. -#define VERSION_QT_MAJOR 2 -#define VERSION_QT_MINOR 0 -#define VERSION_QT_PATCH 0 - -// Qt Binding for NetHack 3.3 +// Qt Binding for NetHack 3.4 // -// Copyright (C) 1996,1997 by Warwick W. Allison (warwick@troll.no) +// Copyright (C) 1996-2001 by Warwick W. Allison (warwick@troll.no) // // Contributors: // Michael Hohmuth @@ -51,6 +47,8 @@ extern "C" { // enough, and we undefine NetHack macros which conflict with Qt // identifiers. +#define alloc hide_alloc // avoid treading on STL symbol +#define lock hide_lock // avoid treading on STL symbol #ifdef _MSC_VER #define NHSTDC #endif @@ -58,6 +56,7 @@ extern "C" { #include "func_tab.h" #include "dlb.h" #include "patchlevel.h" +#include "tile2x11.h" #undef Warning #undef red #undef green @@ -68,11 +67,15 @@ extern "C" { #undef FALSE #undef min #undef max +#undef alloc +#undef lock } #include "qt_win.h" +#include #include +#include #include #include #include @@ -80,9 +83,14 @@ extern "C" { #include #include #include +#include +#include #include #include +#include +#include #include +#include //#include //#include @@ -91,15 +99,31 @@ extern "C" { #include "qt_clust.h" #include "qt_xpms.h" -#include +#include +#ifdef Q_WS_MACX +# include +#else +# include +#endif #ifdef _WS_X11_ // For userid control #include #endif +// Some distributors released Qt 2.1.0beta4 +#if QT_VERSION < 220 +# define nh_WX11BypassWM 0x01000000 +#else +# define nh_WX11BypassWM WX11BypassWM +#endif + #ifdef USER_SOUNDS -#include +# if QT_VERSION < 220 +# undef USER_SOUNDS +# else +# include +# endif #endif @@ -110,18 +134,21 @@ extern "C" void play_sound_for_message(const char* str); // Warwick prefers it this way... #define QT_CHOOSE_RACE_FIRST +static const char nh_attribution[] = "
NetHack" + "
by the NetHack DevTeam
"; + static QString aboutMsg() { QString msg; msg.sprintf( - "Qt NetHack is a version of NetHack built using\n" + "Qt NetHack is a version of NetHack built\n" #ifdef KDE - "KDE and the Qt GUI toolkit for the user interface.\n" + "using KDE and the Qt GUI toolkit.\n" #else - "the Qt GUI toolkit for the user interface.\n" + "using the Qt GUI toolkit.\n" #endif - "This is version %d.%d.%d.%d.%d.%d\n\n" + "This is version %d.%d.%d\n\n" "Homepage:\n http://trolls.troll.no/warwick/nethack/\n\n" #ifdef KDE "KDE:\n http://www.kde.org\n" @@ -129,10 +156,7 @@ aboutMsg() "Qt:\n http://www.troll.no", VERSION_MAJOR, VERSION_MINOR, - PATCHLEVEL, - VERSION_QT_MAJOR, - VERSION_QT_MINOR, - VERSION_QT_PATCH); + PATCHLEVEL); return msg; } @@ -140,6 +164,7 @@ static void centerOnMain( QWidget* w ) { QWidget* m = qApp->mainWidget(); + if (!m) m = qApp->desktop(); QPoint p = m->mapToGlobal(QPoint(0,0)); w->move( p.x() + m->width()/2 - w->width()/2, p.y() + m->height()/2 - w->height()/2 ); @@ -166,6 +191,7 @@ extern "C" { char *qt_tilewidth=NULL; char *qt_tileheight=NULL; char *qt_fontsize=NULL; +int qt_compact_mode = 0; extern const char *enc_stat[]; /* from botl.c */ extern const char *hu_stat[]; /* from eat.c */ extern const char *killed_by_prefix[]; @@ -177,8 +203,8 @@ extern short glyph2tile[]; // from tile.c #define TILEWBASE 16 #define TILEHBASE 16 -#define TILEWMIN 4 -#define TILEHMIN 4 +#define TILEWMIN 1 +#define TILEHMIN 1 /* XPM */ @@ -230,6 +256,339 @@ static const char * nh_icon[] = { " ", " ", " "}; +/* XPM */ +static const char * nh_icon_small[] = { +/* width height ncolors chars_per_pixel */ +"16 16 16 1", +/* colors */ +" c #587070", +". c #D1D5C9", +"X c #8B8C84", +"o c #2A2A28", +"O c #9AABA9", +"+ c #6A8FB2", +"@ c #C4CAC4", +"# c #B6BEB6", +"$ c None", +"% c #54564E", +"& c #476C6C", +"* c #ADB2AB", +"= c #ABABA2", +"- c #5E8295", +"; c #8B988F", +": c #E8EAE7", +/* pixels */ +"$$$$$$$$$$$$$$$$", +"$$$.$#::.#==*$$$", +"$.*:::::....#*=$", +"$@#:..@#*==#;XX;", +"$@O:+++- &&; X%X", +"$#%.+++- &&;% oX", +"$$o.++-- &&;%%X$", +"$$$:++-- &&;%%$$", +"$$$.O++- &&=o $$", +"$$$=:++- & XoX$$", +"$$*:@O-- ;%Xo$$", +"$*:O#$+--;oOOX $", +"$:+ =o::=oo=-;%X", +"$::.%o$*;X;##@%$", +"$$@# ;$$$$$=*;X$", +"$$$$$$$$$$$$$$$$" +}; + +/* XPM */ +static const char * map_xpm[] = { +"12 13 4 1", +". c None", +" c #000000000000", +"X c #0000B6DAFFFF", +"o c #69A69248B6DA", +" .", +" XXXXX ooo ", +" XoooX o ", +" XoooX o o ", +" XoooX ooo ", +" XXoXX o ", +" oooooXXX ", +" oo o oooX ", +" o XooX ", +" oooo XooX ", +" o o XXXX ", +" ", +". "}; +/* XPM */ +static const char * msg_xpm[] = { +"12 13 4 1", +". c None", +" c #FFFFFFFFFFFF", +"X c #69A69248B6DA", +"o c #000000000000", +" .", +" XXX XXX X o", +" o", +" XXXXX XX o", +" o", +" XX XXXXX o", +" o", +" XXXXXX o", +" o", +" XX XXX XX o", +" o", +" o", +".ooooooooooo"}; +/* XPM */ +static const char * stat_xpm[] = { +"12 13 5 1", +" c None", +". c #FFFF00000000", +"X c #000000000000", +"o c #FFFFFFFF0000", +"O c #69A6FFFF0000", +" ", +" ", +"... ", +"...X ", +"...X ... ", +"oooX oooX", +"oooXooo oooX", +"OOOXOOOXOOOX", +"OOOXOOOXOOOX", +"OOOXOOOXOOOX", +"OOOXOOOXOOOX", +"OOOXOOOXOOOX", +" XXXXXXXXXXX"}; +/* XPM */ +static const char * info_xpm[] = { +"12 13 4 1", +" c None", +". c #00000000FFFF", +"X c #FFFFFFFFFFFF", +"o c #000000000000", +" ... ", +" ....... ", +" ...XXX... ", +" .........o ", +"...XXXX.... ", +"....XXX....o", +"....XXX....o", +"....XXX....o", +" ...XXX...oo", +" ..XXXXX..o ", +" .......oo ", +" o...ooo ", +" ooo "}; + + +/* XPM */ +static const char * again_xpm[] = { +"12 13 2 1", +" c None", +". c #000000000000", +" .. ", +" .. ", +" ..... ", +" ....... ", +"... .. .. ", +".. .. .. ", +".. ..", +".. ..", +".. ..", +" .. .. ", +" .......... ", +" ...... ", +" "}; +/* XPM */ +static const char * kick_xpm[] = { +"12 13 3 1", +" c None", +". c #000000000000", +"X c #FFFF6DB60000", +" ", +" ", +" . . . ", +" ... . . ", +" ... . ", +" ... . ", +" ... ", +"XXX ... ", +"XXX. ... ", +"XXX. ... ", +"XXX. .. ", +" ... ", +" "}; +/* XPM */ +static const char * throw_xpm[] = { +"12 13 3 1", +" c None", +". c #FFFF6DB60000", +"X c #000000000000", +" ", +" ", +" ", +" ", +".... X ", +"....X X ", +"....X XXXXXX", +"....X X ", +" XXXX X ", +" ", +" ", +" ", +" "}; +/* XPM */ +static const char * fire_xpm[] = { +"12 13 5 1", +" c None", +". c #B6DA45140000", +"X c #FFFFB6DA9658", +"o c #000000000000", +"O c #FFFF6DB60000", +" . ", +" X. ", +" X . ", +" X .o ", +" X . o ", +" X .o o ", +"OOOOOOOOoooo", +" X .o o ", +" X . o o ", +" X .o ", +" X. o ", +" . o ", +" o "}; +/* XPM */ +static const char * get_xpm[] = { +"12 13 3 1", +" c None", +". c #000000000000", +"X c #FFFF6DB60000", +" ", +" . ", +" ... ", +" . . . ", +" . ", +" . ", +" ", +" XXXXX ", +" XXXXX. ", +" XXXXX. ", +" XXXXX. ", +" ..... ", +" "}; +/* XPM */ +static const char * drop_xpm[] = { +"12 13 3 1", +" c None", +". c #FFFF6DB60000", +"X c #000000000000", +" ", +" ..... ", +" .....X ", +" .....X ", +" .....X ", +" XXXXX ", +" ", +" X ", +" X ", +" X X X ", +" XXX ", +" X ", +" "}; +/* XPM */ +static const char * eat_xpm[] = { +"12 13 4 1", +" c None", +". c #000000000000", +"X c #FFFFB6DA9658", +"o c #FFFF6DB60000", +" .X. .. ", +" .X. .. ", +" .X. .. ", +" .X. .. ", +" ... .. ", +" .. .. ", +" .. .. ", +" oo oo ", +" oo oo ", +" oo oo ", +" oo oo ", +" oo oo ", +" oo oo "}; +/* XPM */ +static const char * rest_xpm[] = { +"12 13 2 1", +" c None", +". c #000000000000", +" ..... ", +" . ", +" . ", +" . ....", +" ..... . ", +" . ", +" ....", +" ", +" .... ", +" . ", +" . ", +" .... ", +" "}; +/* XPM */ +static const char * cast_a_xpm[] = { +"12 13 3 1", +" c None", +". c #FFFF6DB60000", +"X c #000000000000", +" . ", +" . ", +" .. ", +" .. ", +" .. . ", +" .. . ", +" ...... ", +" .. .. XX ", +" .. X X ", +" .. X X ", +" .. XXXX ", +" . X X ", +" . X X "}; +/* XPM */ +static const char * cast_b_xpm[] = { +"12 13 3 1", +" c None", +". c #FFFF6DB60000", +"X c #000000000000", +" . ", +" . ", +" .. ", +" .. ", +" .. . ", +" .. . ", +" ...... ", +" .. .. XXX ", +" .. X X ", +" .. XXX ", +" .. X X ", +" . X X ", +" . XXX "}; +/* XPM */ +static const char * cast_c_xpm[] = { +"12 13 3 1", +" c None", +". c #FFFF6DB60000", +"X c #000000000000", +" . ", +" . ", +" .. ", +" .. ", +" .. . ", +" .. . ", +" ...... ", +" .. .. XX ", +" .. X X ", +" .. X ", +" .. X ", +" . X X ", +" . XX "}; NetHackQtSettings::NetHackQtSettings(int w, int h) : tilewidth(TILEWMIN,32,1,this), @@ -241,7 +600,7 @@ NetHackQtSettings::NetHackQtSettings(int w, int h) : #ifdef WS_WIN normalfixed("courier new"), #else - normalfixed("fixed"), + normalfixed("helvetica"), // ################# normally fixed, just testing #endif large("times"), theglyphs(0) @@ -249,7 +608,12 @@ NetHackQtSettings::NetHackQtSettings(int w, int h) : { int default_fontsize; - if (w<=700) { + if (w<=300) { + // ~240x320 + default_fontsize=4; + tilewidth.setValue(8); + tileheight.setValue(12); + } else if (w<=700) { // ~640x480 default_fontsize=3; tilewidth.setValue(8); @@ -291,6 +655,7 @@ NetHackQtSettings::NetHackQtSettings(int w, int h) : case 'l': default_fontsize = 1; break; case 'm': default_fontsize = 2; break; case 's': default_fontsize = 3; break; + case 't': default_fontsize = 4; break; } free(qt_fontsize); } @@ -305,6 +670,7 @@ NetHackQtSettings::NetHackQtSettings(int w, int h) : fontsize.insertItem("Large"); fontsize.insertItem("Medium"); fontsize.insertItem("Small"); + fontsize.insertItem("Tiny"); fontsize.setCurrentItem(default_fontsize); connect(&fontsize,SIGNAL(activated(int)),this,SIGNAL(fontChanged())); @@ -341,29 +707,28 @@ void NetHackQtSettings::resizeTiles() const QFont& NetHackQtSettings::normalFont() { - static int size[]={ 18, 14, 12, 10 }; + static int size[]={ 18, 14, 12, 10, 8 }; normal.setPointSize(size[fontsize.currentItem()]); return normal; } const QFont& NetHackQtSettings::normalFixedFont() { - static int size[]={ 18, 14, 13, 10 }; + static int size[]={ 18, 14, 13, 10, 8 }; normalfixed.setPointSize(size[fontsize.currentItem()]); return normalfixed; } const QFont& NetHackQtSettings::largeFont() { - static int size[]={ 24, 18, 14, 12 }; + static int size[]={ 24, 18, 14, 12, 10 }; large.setPointSize(size[fontsize.currentItem()]); return large; } bool NetHackQtSettings::ynInMessages() { - // XXX Two out of two users prefer True. - return TRUE; + return !qt_compact_mode; } @@ -387,9 +752,14 @@ void NetHackQtKeyBuffer::Put(int k, int a, int state) in=(in+1)%maxkey; } +void NetHackQtKeyBuffer::Put(char a) +{ + Put(0,a,0); +} + void NetHackQtKeyBuffer::Put(const char* str) { - while (*str) Put(0,*str++,0); + while (*str) Put(*str++); } int NetHackQtKeyBuffer::GetKey() @@ -559,10 +929,15 @@ class NhPSListView : public QListView { int selectedItemNumber() const { int i=0; - QListViewItem* c=firstChild(); - while (c && c != selectedItem()) - i++,c = c->nextSibling(); - return i; + QListViewItem* c = firstChild(); + while (c) { + if (c == selectedItem()) { + return i; + } + i++; + c = c->nextSibling(); + } + return -1; } void setSelectedItemNumber(int i) @@ -576,7 +951,8 @@ class NhPSListView : public QListView { NetHackQtPlayerSelector::NetHackQtPlayerSelector(NetHackQtKeyBuffer& ks) : QDialog(0,"plsel",TRUE), - keysource(ks) + keysource(ks), + fully_specified_role(TRUE) { /* 0 1 2 @@ -614,11 +990,15 @@ NetHackQtPlayerSelector::NetHackQtPlayerSelector(NetHackQtKeyBuffer& ks) : race = new NhPSListView(this); role->addColumn("Role"); race->addColumn("Race"); - QButtonGroup* genderbox = new QButtonGroup(1,Horizontal,"Sex",this); - QButtonGroup* alignbox = new QButtonGroup(1,Horizontal,"Alignment",this); - - QLabel* logo = new QLabel("Qt NetHack" - "
by Warwick Allison
and the NetHack DevTeam", this); + QButtonGroup* genderbox = new QButtonGroup("Sex",this); + QButtonGroup* alignbox = new QButtonGroup("Alignment",this); + QVBoxLayout* vbgb = new QVBoxLayout(genderbox,3,1); + vbgb->setAutoAdd(TRUE); + vbgb->addSpacing(fontMetrics().height()*3/4); + QVBoxLayout* vbab = new QVBoxLayout(alignbox,3,1); + vbab->setAutoAdd(TRUE); + vbab->addSpacing(fontMetrics().height()); + QLabel* logo = new QLabel(nh_attribution, this); l->addMultiCellWidget( namebox, 0,0,0,2 ); #ifdef QT_CHOOSE_RACE_FIRST @@ -672,29 +1052,60 @@ NetHackQtPlayerSelector::NetHackQtPlayerSelector(NetHackQtKeyBuffer& ks) : l->addWidget( cancel, 5, 2 ); connect( cancel, SIGNAL(clicked()), this, SLOT(reject()) ); - // Randomize - int ro = rn2(nrole); - int ra = rn2(nrace); + // Randomize race and role, unless specified in config + int ro = flags.initrole; + if (ro == -1) { + ro = rn2(nrole); + fully_specified_role = FALSE; + } + int ra = flags.initrace; + if (ra == -1) { + ra = rn2(nrace); + fully_specified_role = FALSE; + } + // make sure we have a valid combination, honoring + // the users request if possible. + bool choose_race_first; #ifdef QT_CHOOSE_RACE_FIRST - while (!validrace(ro,ra)) - ro = rn2(nrole); + choose_race_first = TRUE; + if (flags.initrole != -1 && flags.initrace == -1) { + choose_race_first = FALSE; + } #else - while (!validrace(ro,ra)) - ra = rn2(nrace); + choose_race_first = FALSE; + if (flags.initrace != -1 && flags.initrole == -1) { + choose_race_first = TRUE; + } #endif + while (!validrace(ro,ra)) { + fully_specified_role = FALSE; + if (choose_race_first) { + ro = rn2(nrole); + } else { + ra = rn2(nrace); + } + } - int g; - do { + int g = flags.initgend; + if (g == -1) { g = rn2(ROLE_GENDERS); - } while (!validgend(ro,ra,g)); + fully_specified_role = FALSE; + } + while (!validgend(ro,ra,g)) { + g = rn2(ROLE_GENDERS); + } gender[g]->setChecked(TRUE); selectGender(g); - int a; - do { + int a = flags.initalign; + if (a == -1) { + a = rn2(ROLE_ALIGNS); + fully_specified_role = FALSE; + } + while (!validalign(ro,ra,a)) { a = rn2(ROLE_ALIGNS); - } while (!validalign(ro,ra,a)); + } alignment[a]->setChecked(TRUE); selectAlignment(g); @@ -717,6 +1128,10 @@ void NetHackQtPlayerSelector::selectName(const QString& n) void NetHackQtPlayerSelector::selectRole() { + int ra = race->selectedItemNumber(); + int ro = role->selectedItemNumber(); + if (ra == -1 || ro == -1) return; + #ifndef QT_CHOOSE_RACE_FIRST selectRace(); #else @@ -725,7 +1140,6 @@ void NetHackQtPlayerSelector::selectRole() int j; NhPSListViewItem* item; item = (NhPSListViewItem*)role->firstChild(); - int ra = race->selectedItemNumber(); for (j=0; roles[j].name.m; j++) { bool v = validrace(j,ra); item->setSelectable(TRUE); @@ -750,16 +1164,18 @@ void NetHackQtPlayerSelector::selectRole() void NetHackQtPlayerSelector::selectRace() { + int ra = race->selectedItemNumber(); + int ro = role->selectedItemNumber(); + if (ra == -1 || ro == -1) return; + #ifdef QT_CHOOSE_RACE_FIRST selectRole(); - flags.initrace = race->selectedItemNumber(); #else QListViewItem* i=race->currentItem(); QListViewItem* valid=0; int j; NhPSListViewItem* item; item = (NhPSListViewItem*)race->firstChild(); - int ro = role->selectedItemNumber(); for (j=0; races[j].noun; j++) { bool v = validrace(ro,j); item->setSelectable(TRUE); @@ -851,11 +1267,23 @@ void NetHackQtPlayerSelector::Random() bool NetHackQtPlayerSelector::Choose() { - centerOnMain(this); + if (fully_specified_role) return TRUE; + +#if defined(QWS) // probably safe with Qt 3, too (where show!=exec in QDialog). + if ( qt_compact_mode ) { + showMaximized(); + } else +#endif + { + adjustSize(); + centerOnMain(this); + } + if ( exec() ) { return TRUE; - } else + } else { return FALSE; + } } @@ -871,6 +1299,7 @@ NetHackQtStringRequestor::NetHackQtStringRequestor(NetHackQtKeyBuffer& ks, const okay=new QPushButton("Okay",this); connect(okay,SIGNAL(clicked()),this,SLOT(accept())); connect(&input,SIGNAL(returnPressed()),this,SLOT(accept())); + okay->setDefault(TRUE); setFocusPolicy(StrongFocus); } @@ -994,18 +1423,45 @@ NetHackQtMapWindow::NetHackQtMapWindow(NetHackQtClickBuffer& click_sink) : setBackgroundColor(black); viewport.setBackgroundColor(black); - pet_annotation = QPixmap(pet_mark_xpm); + pet_annotation = QPixmap(qt_compact_mode ? pet_mark_small_xpm : pet_mark_xpm); cursor.setX(0); cursor.setY(0); Clear(); connect(qt_settings,SIGNAL(tilesChanged()),this,SLOT(updateTiles())); + connect(&viewport, SIGNAL(contentsMoving(int,int)), this, + SLOT(moveMessages(int,int))); updateTiles(); //setFocusPolicy(StrongFocus); } +void NetHackQtMapWindow::moveMessages(int x, int y) +{ + QRect u = messages_rect; + messages_rect.moveTopLeft(QPoint(x,y)); + u |= messages_rect; + update(u); +} + +void NetHackQtMapWindow::clearMessages() +{ + messages = ""; + update(messages_rect); + messages_rect = QRect(); +} + +void NetHackQtMapWindow::putMessage(int attr, const char* text) +{ + if ( !messages.isEmpty() ) + messages += "\n"; + messages += text; + QFontMetrics fm = fontMetrics(); + messages_rect = fm.boundingRect(viewport.contentsX(),viewport.contentsY(),viewport.width(),0, WordBreak|AlignTop|AlignLeft|DontClip, messages); + update(messages_rect); +} + void NetHackQtMapWindow::updateTiles() { NetHackQtGlyphs& glyphs = qt_settings->glyphs(); @@ -1016,10 +1472,12 @@ void NetHackQtMapWindow::updateTiles() viewport.verticalScrollBar()->setSteps(gh,gh); viewport.horizontalScrollBar()->setSteps(gw,gw); + /* viewport.setMaximumSize( gw*COLNO + viewport.verticalScrollBar()->width(), gh*ROWNO + viewport.horizontalScrollBar()->height() ); + */ viewport.updateScrollBars(); change.clear(); @@ -1152,66 +1610,13 @@ void NetHackQtMapWindow::paintEvent(QPaintEvent* event) for (int i=garea.left(); i<=garea.right(); i++) { unsigned short g=Glyph(i,j); uchar ch; - - /* (from wintty, naturally) - * - * Map the glyph back to a character. - * - * Warning: For speed, this makes an assumption on the order of - * offsets. The order is set in display.h. - */ - + int color, och; + unsigned special; -#ifdef TEXTCOLOR - int color; - -#define zap_color(n) color = iflags.use_color ? zapcolors[n] : NO_COLOR -#define cmap_color(n) color = iflags.use_color ? defsyms[n].color : NO_COLOR -#define obj_color(n) color = iflags.use_color ? objects[n].oc_color : NO_COLOR -#define mon_color(n) color = iflags.use_color ? mons[n].mcolor : NO_COLOR -#define pet_color(n) color = iflags.use_color ? mons[n].mcolor : NO_COLOR -#define warn_color(n) color = iflags.use_color ? def_warnsyms[n].color : NO_COLOR - -# else /* no text color */ - -#define zap_color(n) -#define cmap_color(n) -#define obj_color(n) -#define mon_color(n) -#define pet_color(c) -#define warn_color(c) painter.setPen( green ); -#endif - - if ((offset = (g - GLYPH_WARNING_OFF)) >= 0) { /* a warning flash */ - ch = warnsyms[offset]; - warn_color(offset); - } else if ((offset = (g - GLYPH_SWALLOW_OFF)) >= 0) { /* swallow */ - /* see swallow_to_glyph() in display.c */ - ch = (uchar) showsyms[S_sw_tl + (offset & 0x7)]; - mon_color(offset >> 3); - } else if ((offset = (g - GLYPH_ZAP_OFF)) >= 0) { /* zap beam */ - /* see zapdir_to_glyph() in display.c */ - ch = showsyms[S_vbeam + (offset & 0x3)]; - zap_color((offset >> 2)); - } else if ((offset = (g - GLYPH_CMAP_OFF)) >= 0) { /* cmap */ - ch = showsyms[offset]; - cmap_color(offset); - } else if ((offset = (g - GLYPH_OBJ_OFF)) >= 0) { /* object */ - ch = oc_syms[(int)objects[offset].oc_class]; - obj_color(offset); - } else if ((offset = (g - GLYPH_BODY_OFF)) >= 0) { /* a corpse */ - ch = oc_syms[(int)objects[CORPSE].oc_class]; - mon_color(offset); - } else if ((offset = (g - GLYPH_PET_OFF)) >= 0) { /* a pet */ - ch = monsyms[(int)mons[offset].mlet]; - pet_color(offset); - } else { /* a monster */ - ch = monsyms[(int)mons[g].mlet]; - mon_color(g); - } - // end of wintty code - + /* map glyph to character and color */ + mapglyph(g, &och, &color, &special, i, j); + ch = (uchar)och; #ifdef TEXTCOLOR painter.setPen( nhcolor_to_pen(color) ); #endif @@ -1232,6 +1637,8 @@ void NetHackQtMapWindow::paintEvent(QPaintEvent* event) } } } + + painter.setFont(font()); } else #endif { @@ -1280,6 +1687,15 @@ void NetHackQtMapWindow::paintEvent(QPaintEvent* event) qt_settings->glyphs().width(),qt_settings->glyphs().height()); } + if (area.intersects(messages_rect)) { + painter.setPen(black); + painter.drawText(viewport.contentsX()+1,viewport.contentsY()+1, + viewport.width(),0, WordBreak|AlignTop|AlignLeft|DontClip, messages); + painter.setPen(white); + painter.drawText(viewport.contentsX(),viewport.contentsY(), + viewport.width(),0, WordBreak|AlignTop|AlignLeft|DontClip, messages); + } + painter.end(); } @@ -1485,6 +1901,7 @@ NetHackQtMessageWindow::NetHackQtMessageWindow() : list(new NetHackQtScrollText(::iflags.msg_history)) { ::iflags.window_inited = 1; + map = 0; connect(qt_settings,SIGNAL(fontChanged()),this,SLOT(updateFont())); updateFont(); } @@ -1497,9 +1914,17 @@ NetHackQtMessageWindow::~NetHackQtMessageWindow() QWidget* NetHackQtMessageWindow::Widget() { return list; } +void NetHackQtMessageWindow::setMap(NetHackQtMapWindow* m) +{ + map = m; + updateFont(); +} + void NetHackQtMessageWindow::updateFont() { list->setFont(qt_settings->normalFont()); + if ( map ) + map->setFont(qt_settings->normalFont()); } void NetHackQtMessageWindow::Scroll(int dx, int dy) @@ -1509,6 +1934,8 @@ void NetHackQtMessageWindow::Scroll(int dx, int dy) void NetHackQtMessageWindow::Clear() { + if ( map ) + map->clearMessages(); if (list->uncleared) { list->uncleared=0; changed=TRUE; @@ -1536,6 +1963,9 @@ void NetHackQtMessageWindow::PutStr(int attr, const char* text) // Force scrollbar to bottom // XXX list->setTopItem(list->count()); + + if ( map ) + map->putMessage(attr, text); } @@ -1616,7 +2046,12 @@ void NetHackQtLabelledIcon::setFont(const QFont& f) } void NetHackQtLabelledIcon::show() { - if (!isVisible()) highlight(hl_bad); +#if QT_VERSION >= 300 + if (isHidden()) +#else + if (!isVisible()) +#endif + highlight(hl_bad); QWidget::show(); } void NetHackQtLabelledIcon::highlightWhenChanging() @@ -1965,7 +2400,7 @@ void NetHackQtStatusWindow::fadeHighlighting() */ void NetHackQtStatusWindow::updateStats() { - if (!isVisible()) return; + if (!parentWidget()) return; char buf[BUFSZ]; @@ -2051,7 +2486,11 @@ void NetHackQtStatusWindow::updateStats() dlevel.setLabel(buf,(long)depth(&u.uz)); } - gold.setLabel("Au:",(long)u.ugold); +#ifndef GOLDOBJ + gold.setLabel("Au:", u.ugold); +#else + gold.setLabel("Au:", money_cnt(invent)); +#endif if (u.mtimedone) { // You're a monster! @@ -2357,20 +2796,27 @@ int NetHackQtMenuWindow::SelectMenu(int h, MENU_ITEM_P **menu_list) invert->setEnabled(how==PICK_ANY); search->setEnabled(how!=PICK_NONE); + dialog->SetResult(-1); + // 20 allows for scrollbar or spacing // 4 for frame borders int mh = QApplication::desktop()->height()*3/5; - dialog->resize(totalWidth()+20, - QMIN(totalHeight(), mh)+buth+4+(prompt.text().isNull() ? 0 : buth)); + if ( qt_compact_mode && totalHeight() > mh ) { + // big, so make it fill + dialog->showMaximized(); + } else { + dialog->resize(totalWidth()+20, + QMIN(totalHeight(), mh)+buth+4+(prompt.text().isNull() ? 0 : buth)); + if ( dialog->width() > QApplication::desktop()->width() ) + dialog->resize(QApplication::desktop()->width(),dialog->height()+16); + centerOnMain(dialog); + dialog->show(); + } - dialog->SetResult(-1); - centerOnMain(dialog); - dialog->show(); setFocus(); while (dialog->result()<0) { - qApp->enter_loop(); // changed the defaults below to the values in wintype.h 000119 - azy - if (dialog->result()<0 && !keysource.Empty()) { + if (!keysource.Empty()) { char k=keysource.GetAscii(); k=map_menu_cmd(k); /* added 000119 - azy */ if (k=='\033') @@ -2392,6 +2838,8 @@ int NetHackQtMenuWindow::SelectMenu(int h, MENU_ITEM_P **menu_list) } } } + if (dialog->result()<0) + qApp->enter_loop(); } dialog->hide(); int result=dialog->result(); @@ -2516,7 +2964,7 @@ void NetHackQtMenuWindow::paintCell(QPainter* painter, int row, int col) AlignHCenter|AlignVCenter,text); } break; case 1: - if (i.ch>=0) { + if ((signed char)i.ch >= 0) { char text[2]={i.ch,0}; painter->drawText(0,0,cellWidth(col),cellHeight(), AlignHCenter|AlignVCenter,text); @@ -2669,6 +3117,11 @@ void NetHackQtRIP::setLines(char** l, int n) riplines=n; } +QSize NetHackQtRIP::sizeHint() const +{ + return pixmap->size(); +} + void NetHackQtRIP::paintEvent(QPaintEvent* event) { if ( riplines ) { @@ -2704,8 +3157,14 @@ NetHackQtTextWindow::NetHackQtTextWindow(NetHackQtKeyBuffer& ks) : ok.setDefault(TRUE); connect(&ok,SIGNAL(clicked()),this,SLOT(accept())); connect(&search,SIGNAL(clicked()),this,SLOT(Search())); - connect(qt_settings,SIGNAL(fontChanged()),this,SLOT(doUpdate())); + + QVBoxLayout* vb = new QVBoxLayout(this); + vb->addWidget(&rip); + QHBoxLayout* hb = new QHBoxLayout(vb); + hb->addWidget(&ok); + hb->addWidget(&search); + vb->addWidget(lines); } void NetHackQtTextWindow::doUpdate() @@ -2756,7 +3215,11 @@ static char** rip_line=0; Sprintf(rip_line[NAME_LINE], "%s", plname); /* Put $ on stone */ +#ifndef GOLDOBJ Sprintf(rip_line[GOLD_LINE], "%ld Au", u.ugold); +#else + Sprintf(rip_line[GOLD_LINE], "%ld Au", done_money); +#endif /* Put together death description */ switch (killer_format) { @@ -2813,21 +3276,33 @@ void NetHackQtTextWindow::Display(bool block) { if (str_fixed) { lines->setFont(qt_settings->normalFixedFont()); + } else { + lines->setFont(qt_settings->normalFont()); } - int h=ok.height()*2; + int h=0; if (use_rip) { h+=rip.height(); + ok.hide(); + search.hide(); rip.show(); } else { + h+=ok.height()*2; + ok.show(); + search.show(); rip.hide(); } int mh = QApplication::desktop()->height()*3/5; - resize(QMAX(use_rip ? rip.width() : 200, - lines->TotalWidth()+24), - QMIN(mh, lines->TotalHeight()+h)); - centerOnMain(this); - show(); + if ( qt_compact_mode && lines->TotalHeight() > mh || use_rip ) { + // big, so make it fill + showMaximized(); + } else { + resize(QMAX(use_rip ? rip.width() : 200, + lines->TotalWidth()+24), + QMIN(mh, lines->TotalHeight()+h)); + centerOnMain(this); + show(); + } if (block) { setResult(-1); while (result()==-1) { @@ -2857,23 +3332,6 @@ void NetHackQtTextWindow::done(int i) qApp->exit_loop(); } -void NetHackQtTextWindow::resizeEvent(QResizeEvent*) -{ - const int margin=8; - const int gutter=8; - const int butw = (width()-margin*2-gutter)/2; - const int buth=fontMetrics().height()*2; - int y=0; - if (use_rip) { - rip.setGeometry(0,0,width(),rip.height()); - y+=rip.height(); - } - y+=margin; - ok.setGeometry(margin, y, butw, buth); - search.setGeometry(margin+butw+gutter, y, butw, buth); - y+=buth+margin; - lines->setGeometry(0,y,width(),height()-y); -} void NetHackQtTextWindow::keyPressEvent(QKeyEvent* e) { if ( e->ascii() != '\r' && e->ascii() != '\n' && e->ascii() != '\033' ) @@ -2891,8 +3349,8 @@ void NetHackQtTextWindow::Search() int current=lines->currentItem(); for (int i=1; icount(); i++) { int lnum=(i+current)%lines->count(); - const char* str=lines->text(lnum); - if (strstr(str,line)) { + QString str=lines->text(lnum); + if (str.contains(line)) { lines->setCurrentItem(lnum); lines->centerCurrentItem(); return; @@ -2982,132 +3440,162 @@ void NetHackQtInvUsageWindow::paintEvent(QPaintEvent*) painter.end(); } +class SmallToolButton : public QToolButton { +public: + SmallToolButton(const QPixmap & pm, const QString &textLabel, + const QString& grouptext, + QObject * receiver, const char* slot, + QToolBar * parent) : + QToolButton(pm, textLabel, +#if QT_VERSION < 210 + QString::null, +#else + grouptext, +#endif + receiver, slot, parent) + { + } + + QSize sizeHint() const + { + // get just a couple more pixels for the map + return QToolButton::sizeHint()-QSize(0,2); + } +}; NetHackQtMainWindow::NetHackQtMainWindow(NetHackQtKeyBuffer& ks) : - message(0), map(0), status(0), invusage(this), -#ifdef KDE - menubar(new KMenuBar(this)), -#else - menubar(new QMenuBar(this)), -#endif + message(0), map(0), status(0), invusage(0), keysink(ks) { - setCaption("Qt NetHack"); - setIcon(QPixmap(nh_icon)); - - setBackgroundColor(black); -#ifndef KDE - menubar->setSeparator(QMenuBar::InWindowsStyle); + QToolBar* toolbar = new QToolBar(this); +#if QT_VERSION >= 210 + setToolBarsMovable(FALSE); + toolbar->setHorizontalStretchable(TRUE); + toolbar->setVerticalStretchable(TRUE); #endif + addToolBar(toolbar); + menubar = menuBar(); + + setCaption("Qt NetHack"); + if ( qt_compact_mode ) + setIcon(QPixmap(nh_icon_small)); + else + setIcon(QPixmap(nh_icon)); QPopupMenu* game=new QPopupMenu; QPopupMenu* apparel=new QPopupMenu; - QPopupMenu* action=new QPopupMenu; + QPopupMenu* act1=new QPopupMenu; + QPopupMenu* act2 = qt_compact_mode ? new QPopupMenu : act1; QPopupMenu* magic=new QPopupMenu; - QPopupMenu* nonaction=new QPopupMenu; + QPopupMenu* info=new QPopupMenu; + + QPopupMenu *help; #ifdef KDE - QPopupMenu *help = kapp->getHelpMenu( TRUE, "" ); + help = kapp->getHelpMenu( TRUE, "" ); help->insertSeparator(); #else - QPopupMenu* help = new QPopupMenu; + help = qt_compact_mode ? info : new QPopupMenu; #endif + enum { OnDesktop=1, OnHandhelds=2 }; struct Macro { QPopupMenu* menu; const char* name; const char* action; + int flags; } item[] = { - { game, 0, 0 }, - { game, "Version\tv", "v" }, - { game, "Compilation\tAlt-V", "\366" }, - { game, "History\tShift-V", "V" }, - { game, "Redraw\tCtrl-R", "\022" }, - { game, "Options\tShift-O", "O" }, - { game, "Explore mode\tShift-X", "X" }, - { game, 0, 0 }, - { game, "Save\tShift-S", "S" }, - { game, "Quit\tAlt-Q", "\361" }, - - { apparel, "Apparel off\tShift-A", "A" }, - { apparel, 0, 0 }, - { apparel, "Wield weapon\tw", "w" }, - { apparel, "Exchange weapons\tx", "x" }, - { apparel, "Two weapon combat\t#two", "#tw" }, - { apparel, 0, 0 }, - { apparel, "Wear armour\tShift-W", "W" }, - { apparel, "Take off armour\tShift-T", "T" }, - { apparel, 0, 0 }, - { apparel, "Put on non-armour\tShift-P", "P" }, - { apparel, "Remove non-armour\tShift-R", "R" }, - - { action, "Again\tCtrl-A", "\001" }, - { action, 0, 0 }, - { action, "Get\t,", "," }, - { action, "Loot\tAlt-L", "\354" }, - { action, "Sit\tAlt-S", "\363" }, - { action, "Force\tAlt-F", "\346" }, - { action, "Kick\tCtrl-D", "\004" }, - { action, "Jump\tAlt-J", "\352" }, - { action, "Wipe face\tAlt-W", "\367" }, - { action, "Throw\tt", "t" }, - { action, "Load quiver\tQ", "Q" }, - { action, "Fire from quiver\tf", "f" }, - { action, "Fight\tF", "F" }, - { action, "Open door\to", "o" }, - { action, "Close door\tc", "c" }, - { action, "Drop\td?", "d?" }, - { action, "Drop many\tShift-D", "D" }, - { action, "Eat\te?", "e?" }, - { action, "Engrave\tShift-E", "E" }, - { action, "Apply\ta?", "a?" }, - { action, 0, 0 }, - { action, "Ride\t#ri", "#ri" }, - { action, "Up\t<", "<" }, - { action, "Down\t>", ">" }, - { action, "Rest\t.", "." }, - { action, "Search\ts", "s" }, - { action, 0, 0 }, - { action, "Chat\tAlt-C", "\343" }, - { action, "Pay\tp", "p" }, - - { magic, "Quaff potion\tq", "q?" }, - { magic, "Read scroll/book\tr?", "r?" }, - { magic, "Zap wand\tz?", "z?" }, - { magic, "Zap spell\tShift-Z?", "Z?" }, - { magic, "Dip\tAlt-D", "\344" }, - { magic, "Rub\tAlt-R", "\362" }, - { magic, "Invoke\tAlt-I", "\351" }, - { magic, 0, 0 }, - { magic, "Offer\tAlt-O", "\357" }, - { magic, "Pray\tAlt-P", "\360" }, - { magic, 0, 0 }, - { magic, "Teleport\tCtrl-T", "\024" }, - { magic, "Monster action\tAlt-M", "\355" }, - { magic, "Turn undead\tAlt-T", "\364" }, - - { nonaction, "Inventory\ti", "i" }, + { game, 0, 0, 3}, + { game, "Version\tv", "v", 3}, + { game, "Compilation\tAlt+V", "\366", 3}, + { game, "History\tShift+V", "V", 3}, + { game, "Redraw\tCtrl+R", "\022", 0}, // useless + { game, "Options\tShift+O", "O", 3}, + { game, "Explore mode\tShift+X", "X", 3}, + { game, 0, 0, 3}, + { game, "Save\tShift+S", "Sy", 3}, + { game, "Quit\tAlt+Q", "\361", 3}, + + { apparel, "Apparel off\tShift+A", "A", 2}, + { apparel, "Remove many\tShift+A", "A", 1}, + { apparel, 0, 0, 3}, + { apparel, "Wield weapon\tw", "w", 3}, + { apparel, "Exchange weapons\tx", "x", 3}, + { apparel, "Two weapon combat\t#two", "#tw", 3}, + { apparel, "Load quiver\tQ", "Q", 3}, + { apparel, 0, 0, 3}, + { apparel, "Wear armour\tShift+W", "W", 3}, + { apparel, "Take off armour\tShift+T", "T", 3}, + { apparel, 0, 0, 3}, + { apparel, "Put on non-armour\tShift+P", "P", 3}, + { apparel, "Remove non-armour\tShift+R", "R", 3}, + + { act1, "Again\tCtrl+A", "\001", 2}, + { act1, 0, 0, 3}, + { act1, "Apply\ta?", "a?", 3}, + { act1, "Chat\tAlt+C", "\343", 3}, + { act1, "Close door\tc", "c", 3}, + { act1, "Down\t>", ">", 3}, + { act1, "Drop many\tShift+D", "D", 2}, + { act1, "Drop\td?", "d?", 2}, + { act1, "Eat\te?", "e?", 2}, + { act1, "Engrave\tShift+E", "E", 3}, + { act1, "Fight\tF", "F", 3}, + { act1, "Fire from quiver\tf", "f", 2}, + { act1, "Force\tAlt+F", "\346", 3}, + { act1, "Get\t,", ",", 2}, + { act1, "Jump\tAlt+J", "\352", 3}, + { act2, "Kick\tCtrl+D", "\004", 2}, + { act2, "Loot\tAlt+L", "\354", 3}, + { act2, "Open door\to", "o", 3}, + { act2, "Pay\tp", "p", 3}, + { act2, "Rest\t.", ".", 2}, + { act2, "Ride\t#ri", "#ri", 3}, + { act2, "Search\ts", "s", 3}, + { act2, "Sit\tAlt+S", "\363", 3}, + { act2, "Throw\tt", "t", 2}, + { act2, "Up\t<", "<", 3}, + { act2, "Wipe face\tAlt+W", "\367", 3}, + + { magic, "Quaff potion\tq", "q?", 3}, + { magic, "Read scroll/book\tr?", "r?", 3}, + { magic, "Zap wand\tz?", "z?", 3}, + { magic, "Zap spell\tShift+Z", "Z", 3}, + { magic, "Dip\tAlt+D", "\344", 3}, + { magic, "Rub\tAlt+R", "\362", 3}, + { magic, "Invoke\tAlt+I", "\351", 3}, + { magic, 0, 0, 3}, + { magic, "Offer\tAlt+O", "\357", 3}, + { magic, "Pray\tAlt+P", "\360", 3}, + { magic, 0, 0, 3}, + { magic, "Teleport\tCtrl+T", "\024", 3}, + { magic, "Monster action\tAlt+M", "\355", 3}, + { magic, "Turn undead\tAlt+T", "\364", 3}, + + { help, "Help\t?", "?", 3}, + { help, 0, 0, 3}, + { help, "What is here\t:", ":", 3}, + { help, "What is there\t;", ";", 3}, + { help, "What is...\t/", "/y", 2}, + { help, 0, 0, 1}, + + { info, "Inventory\ti", "i", 3}, #ifdef SLASHEM - { nonaction, "Angbandish inventory\t*", "*" }, + { info, "Angbandish inventory\t*", "*", 3}, #endif - { nonaction, "Conduct\t#co", "#co" }, - { nonaction, "Discoveries\t\\", "\\" }, - { nonaction, "List/reorder spells\t+", "+" }, - { nonaction, "Adjust letters\tAlt-A", "\341" }, - { nonaction, 0, 0 }, - { nonaction, "Name objects\tAlt-N", "\356" }, - { nonaction, "Name creature\tShift-C", "C" }, - { nonaction, 0, 0 }, - { nonaction, "Qualifications\tAlt-E", "\345" }, - - { help, "Help\t?", "?" }, - { help, 0, 0 }, - { help, "What is here\t:", ":" }, - { help, "What is that\t;", ";" }, - { help, "What is...\t/", "/y" }, - - { 0, 0, 0 } + { info, "Conduct\t#co", "#co", 3}, + { info, "Discoveries\t\\", "\\", 3}, + { info, "List/reorder spells\t+", "+", 3}, + { info, "Adjust letters\tAlt+A", "\341", 2}, + { info, 0, 0, 3}, + { info, "Name object\tAlt+N", "\356y?", 3}, + { info, "Name object type\tAlt+N", "\356n?", 3}, + { info, "Name creature\tShift+C", "C", 3}, + { info, 0, 0, 3}, + { info, "Qualifications\tAlt+E", "\345", 3}, + + { 0, 0, 0, 0 } }; int i; @@ -3119,24 +3607,73 @@ NetHackQtMainWindow::NetHackQtMainWindow(NetHackQtKeyBuffer& ks) : game->insertItem("Qt settings...",1000); help->insertItem("About Qt NetHack...",2000); + //help->insertItem("NetHack Guidebook...",3000); + help->insertSeparator(); count=0; for (i=0; item[i].menu; i++) { - if (item[i].name) { - item[i].menu->insertItem(item[i].name,count); - macro[count++]=item[i].action; - } else { - item[i].menu->insertSeparator(); + if ( item[i].flags & (qt_compact_mode ? 1 : 2) ) { + if (item[i].name) { + QString name = item[i].name; + if ( qt_compact_mode ) // accelerators aren't + name.replace(QRegExp("\t.*"),""); + item[i].menu->insertItem(name,count); + macro[count++]=item[i].action; + } else { + item[i].menu->insertSeparator(); + } } } menubar->insertItem("Game",game); - menubar->insertItem("Apparel",apparel); - menubar->insertItem("Action",action); - menubar->insertItem("Magic",magic); - menubar->insertItem("Non-action",nonaction); - menubar->insertSeparator(); - menubar->insertItem("Help",help); + menubar->insertItem("Gear",apparel); + + if ( qt_compact_mode ) { + menubar->insertItem("A-J",act1); + menubar->insertItem("K-Z",act2); + menubar->insertItem("Magic",magic); + menubar->insertItem(QPixmap(info_xpm),info); + menubar->insertItem(QPixmap(map_xpm), this, SLOT(raiseMap())); + menubar->insertItem(QPixmap(msg_xpm), this, SLOT(raiseMessages())); + menubar->insertItem(QPixmap(stat_xpm), this, SLOT(raiseStatus())); + } else { + menubar->insertItem("Action",act1); + menubar->insertItem("Magic",magic); + menubar->insertItem("Info",info); + menubar->insertSeparator(); + menubar->insertItem("Help",help); + } + + QSignalMapper* sm = new QSignalMapper(this); + connect(sm, SIGNAL(mapped(const QString&)), this, SLOT(doKeys(const QString&))); + QToolButton* tb; + tb = new SmallToolButton( QPixmap(again_xpm),"Again","Action", sm, SLOT(map()), toolbar ); + sm->setMapping(tb, "\001" ); + tb = new SmallToolButton( QPixmap(get_xpm),"Get","Action", sm, SLOT(map()), toolbar ); + sm->setMapping(tb, "," ); + tb = new SmallToolButton( QPixmap(kick_xpm),"Kick","Action", sm, SLOT(map()), toolbar ); + sm->setMapping(tb, "\004" ); + tb = new SmallToolButton( QPixmap(throw_xpm),"Throw","Action", sm, SLOT(map()), toolbar ); + sm->setMapping(tb, "t" ); + tb = new SmallToolButton( QPixmap(fire_xpm),"Fire","Action", sm, SLOT(map()), toolbar ); + sm->setMapping(tb, "f" ); + tb = new SmallToolButton( QPixmap(drop_xpm),"Drop","Action", sm, SLOT(map()), toolbar ); + sm->setMapping(tb, "D" ); + tb = new SmallToolButton( QPixmap(eat_xpm),"Eat","Action", sm, SLOT(map()), toolbar ); + sm->setMapping(tb, "e" ); + tb = new SmallToolButton( QPixmap(rest_xpm),"Rest","Action", sm, SLOT(map()), toolbar ); + sm->setMapping(tb, "." ); + tb = new SmallToolButton( QPixmap(cast_a_xpm),"Cast A","Magic", sm, SLOT(map()), toolbar ); + sm->setMapping(tb, "Za" ); + tb = new SmallToolButton( QPixmap(cast_b_xpm),"Cast B","Magic", sm, SLOT(map()), toolbar ); + sm->setMapping(tb, "Zb" ); + tb = new SmallToolButton( QPixmap(cast_c_xpm),"Cast C","Magic", sm, SLOT(map()), toolbar ); + sm->setMapping(tb, "Zc" ); + if ( !qt_compact_mode ) { + QWidget* filler = new QWidget(toolbar); + filler->setBackgroundMode(PaletteButton); + toolbar->setStretchableWidget(filler); + } connect(menubar,SIGNAL(activated(int)),this,SLOT(doMenuItem(int))); @@ -3172,7 +3709,60 @@ NetHackQtMainWindow::NetHackQtMainWindow(NetHackQtKeyBuffer& ks) : } setGeometry(x,y,w,h); + + if ( qt_compact_mode ) { + stack = new QWidgetStack(this); + setCentralWidget(stack); + } else { + setCentralWidget(new QWidget(this)); + invusage = new NetHackQtInvUsageWindow(centralWidget()); + } +} + +void NetHackQtMainWindow::raiseMap() +{ + stack->raiseWidget(0); +} + +void NetHackQtMainWindow::raiseMessages() +{ + stack->raiseWidget(1); } + +void NetHackQtMainWindow::raiseStatus() +{ + stack->raiseWidget(2); +} + +class NetHackMimeSourceFactory : public QMimeSourceFactory { +public: + const QMimeSource* data(const QString& abs_name) const + { + const QMimeSource* r = 0; + if ( (NetHackMimeSourceFactory*)this == QMimeSourceFactory::defaultFactory() ) + r = QMimeSourceFactory::data(abs_name); + else + r = QMimeSourceFactory::defaultFactory()->data(abs_name); + if ( !r ) { + int sl = abs_name.length(); + do { + sl = abs_name.findRev('/',sl-1); + QString name = sl>=0 ? abs_name.mid(sl+1) : abs_name; + int dot = name.findRev('.'); + if ( dot >= 0 ) + name = name.left(dot); + if ( name == "map" ) + r = new QImageDrag(QImage(map_xpm)); + else if ( name == "msg" ) + r = new QImageDrag(QImage(msg_xpm)); + else if ( name == "stat" ) + r = new QImageDrag(QImage(stat_xpm)); + } while (!r && sl>0); + } + return r; + } +}; + void NetHackQtMainWindow::doMenuItem(int id) { switch (id) { @@ -3180,15 +3770,33 @@ void NetHackQtMainWindow::doMenuItem(int id) centerOnMain(qt_settings); qt_settings->show(); break; - case 2000: { - QMessageBox::about(this, "About Qt NetHack", aboutMsg()); - } break; + case 2000: + QMessageBox::about(this, "About Qt NetHack", aboutMsg()); + break; + case 3000: { + QDialog dlg(this,0,TRUE); + (new QVBoxLayout(&dlg))->setAutoAdd(TRUE); + QTextBrowser browser(&dlg); + NetHackMimeSourceFactory ms; + browser.setMimeSourceFactory(&ms); + browser.setSource(QDir::currentDirPath()+"/Guidebook.html"); + if ( qt_compact_mode ) + dlg.showMaximized(); + dlg.exec(); + } + break; default: - keysink.Put(macro[id]); - qApp->exit_loop(); + if ( id >= 0 ) + doKeys(macro[id]); } } +void NetHackQtMainWindow::doKeys(const QString& k) +{ + keysink.Put(k); + qApp->exit_loop(); +} + void NetHackQtMainWindow::AddMessageWindow(NetHackQtMessageWindow* window) { message=window; @@ -3224,7 +3832,8 @@ void NetHackQtMainWindow::RemoveWindow(NetHackQtWindow* window) void NetHackQtMainWindow::updateInventory() { - invusage.repaint(FALSE); + if ( invusage ) + invusage->repaint(FALSE); } void NetHackQtMainWindow::fadeHighlighting() @@ -3236,21 +3845,23 @@ void NetHackQtMainWindow::fadeHighlighting() void NetHackQtMainWindow::layout() { + if ( qt_compact_mode ) + return; if (message && map && status) { QSize maxs=map->Widget()->maximumSize(); int maph=QMIN(height()*2/3,maxs.height()); - int y=menubar->height(); - int h=height()-y; + QWidget* c = centralWidget(); + int h=c->height(); int toph=h-maph; int iuw=3*qt_settings->glyphs().width(); - int topw=(width()-iuw)/2; + int topw=(c->width()-iuw)/2; - message->Widget()->setGeometry(0,y,topw,toph); - invusage.setGeometry(topw,y,iuw,toph); - status->Widget()->setGeometry(topw+iuw,y,topw,toph); - map->Widget()->setGeometry(QMAX(0,(width()-maxs.width())/2), - y+toph,width(),maph); + message->Widget()->setGeometry(0,0,topw,toph); + invusage->setGeometry(topw,0,iuw,toph); + status->Widget()->setGeometry(topw+iuw,0,topw,toph); + map->Widget()->setGeometry(QMAX(0,(c->width()-maxs.width())/2), + toph,c->width(),maph); } } @@ -3266,15 +3877,32 @@ void NetHackQtMainWindow::keyPressEvent(QKeyEvent* event) { // Global key controls + // For desktop, arrow keys scroll map, since we don't want players + // to think that's the way to move. For handhelds, the normal way is to + // click-to-travel, so we allow the cursor keys for fine movements. + + const char* d = iflags.num_pad ? ndir : sdir; switch (event->key()) { case Key_Up: - if (map) map->Scroll(0,-1); + if (qt_compact_mode) + keysink.Put(d[2]); + else + if (map) map->Scroll(0,-1); break; case Key_Down: - if (map) map->Scroll(0,+1); + if (qt_compact_mode) + keysink.Put(d[6]); + else + if (map) map->Scroll(0,+1); break; case Key_Left: - if (map) map->Scroll(-1,0); + if (qt_compact_mode) + keysink.Put(d[0]); + else + if (map) map->Scroll(-1,0); break; case Key_Right: - if (map) map->Scroll(+1,0); + if (qt_compact_mode) + keysink.Put(d[4]); + else + if (map) map->Scroll(+1,0); break; case Key_Prior: if (message) message->Scroll(0,-1); break; case Key_Next: @@ -3289,20 +3917,17 @@ void NetHackQtMainWindow::closeEvent(QCloseEvent* e) if ( program_state.something_worth_saving ) { switch ( QMessageBox::information( this, "NetHack", "This will end your NetHack session", - "&Save", "&Quit", "&Cancel", 0, 2 ) ) + "&Save", "&Cancel", 0, 1 ) ) { case 0: // See dosave() function if (dosave0()) { u.uhp = -1; + NetHackQtBind::qt_exit_nhwindows(0); terminate(EXIT_SUCCESS); } break; case 1: - u.uhp = -1; - terminate(EXIT_SUCCESS); - break; - case 2: break; // ignore the event } } else { @@ -3314,12 +3939,20 @@ void NetHackQtMainWindow::ShowIfReady() { if (message && map && status) { QPoint pos(0,0); - message->Widget()->recreate(this,0,pos); - map->Widget()->recreate(this,0,pos); - status->Widget()->recreate(this,0,pos); - - layout(); - show(); + QWidget* p = qt_compact_mode ? stack : centralWidget(); + message->Widget()->recreate(p,0,pos); + map->Widget()->recreate(p,0,pos); + status->Widget()->recreate(p,0,pos); + if ( qt_compact_mode ) { + message->setMap(map); + stack->addWidget(map->Widget(), 0); + stack->addWidget(message->Widget(), 1); + stack->addWidget(status->Widget(), 2); + raiseMap(); + } else { + layout(); + } + showMaximized(); } else if (isVisible()) { hide(); } @@ -3336,12 +3969,82 @@ NetHackQtYnDialog::NetHackQtYnDialog(NetHackQtKeyBuffer& keysrc,const char* q,co char NetHackQtYnDialog::Exec() { - if (choices) { - QButtonGroup group(question, this); + QString ch(choices); + int ch_per_line=6; + QString qlabel; + QString enable; + if ( qt_compact_mode && !choices ) { + // expand choices from prompt + // ##### why isn't choices set properly??? + const char* c=question; + while ( *c && *c != '[' ) + c++; + qlabel = QString(question).left(c-question); + if ( *c ) { + c++; + if ( *c == '-' ) + ch.append(*c++); + char from=0; + while ( *c && *c != ']' && *c != ' ' ) { + if ( *c == '-' ) { + from = c[-1]; + } else if ( from ) { + for (char f=from+1; f<=*c; f++) + ch.append(f); + from = 0; + } else { + ch.append(*c); + from = 0; + } + c++; + } + if ( *c == ' ' ) { + while ( *c && *c != ']' ) { + if ( *c == '*' || *c == '?' ) + ch.append(*c); + c++; + } + } + } + if ( strstr(question, "what direction") ) { + // We replace this regardless, since sometimes you get choices. + const char* d = iflags.num_pad ? ndir : sdir; + enable=ch; + ch=""; + ch.append(d[1]); + ch.append(d[2]); + ch.append(d[3]); + ch.append(d[0]); + ch.append('.'); + ch.append(d[4]); + ch.append(d[7]); + ch.append(d[6]); + ch.append(d[5]); + ch.append(d[8]); + ch.append(d[9]); + ch_per_line = 3; + def = ' '; + } else { + // Hmm... they'll have to use a virtual keyboard + } + } else { + qlabel = question; + } + if (!ch.isNull()) { + QVBoxLayout vb(this); + vb.setAutoAdd(TRUE); + bool bigq = qlabel.length()>40; + if ( bigq ) { + QLabel* q = new QLabel(qlabel,this); + q->setAlignment(AlignLeft|WordBreak); + q->setMargin(4); + } + QButtonGroup group(ch_per_line, Horizontal, + bigq ? QString::null : qlabel, this); - int nchoices=strlen(choices); + int nchoices=ch.length(); - bool allow_count=strchr(choices,'#')!=0; + bool allow_count=ch.contains('#'); const int margin=8; const int gutter=8; @@ -3351,11 +4054,14 @@ char NetHackQtYnDialog::Exec() int butsize=fontMetrics().height()*2+5; QPushButton* button; - for (int i=0; isetGeometry(x,y,butsize,butsize); // Square - if (choices[i]==def) button->setDefault(TRUE); + for (int i=0; isetEnabled(FALSE); + } + button->setFixedSize(butsize,butsize); // Square + if (ch[i]==def) button->setDefault(TRUE); if (i%10==9) { // last in row x=margin; @@ -3365,47 +4071,50 @@ char NetHackQtYnDialog::Exec() } } - group.resize(margin*2+(gutter+button->width())*10, - extra+margin*2+(gutter+button->height())*(nchoices/10+1)); - connect(&group,SIGNAL(clicked(int)),this,SLOT(done(int))); + connect(&group,SIGNAL(clicked(int)),this,SLOT(doneItem(int))); QLabel* lb=0; QLineEdit* le=0; if (allow_count) { - lb=new QLabel("Count: ",this); - le=new QLineEdit(this); - lb->setGeometry(margin,group.height()+margin,group.width()*1/3,le->height()); - le->setGeometry(lb->geometry().right()+margin,lb->geometry().top(), - group.width()*2/3,le->height()); + QHBox *hb = new QHBox(this); + lb=new QLabel("Count: ",hb); + le=new QLineEdit(hb); } + adjustSize(); centerOnMain(this); show(); char choice=0; + char ch_esc=0; + for (int i=0; i= 1000 ) { + choice = ch[result() - 1000].latin1(); } - qApp->enter_loop(); + if ( !choice ) + qApp->enter_loop(); } hide(); if (allow_count && !le->text().isEmpty()) { @@ -3414,16 +4123,17 @@ char NetHackQtYnDialog::Exec() } return choice; } else { - QLabel label(question,this); + QLabel label(qlabel,this); QPushButton cancel("Dismiss",this); label.setFrameStyle(QFrame::Box|QFrame::Sunken); label.setAlignment(AlignCenter); - label.resize(fontMetrics().width(question)+60,30+fontMetrics().height()); + label.resize(fontMetrics().width(qlabel)+60,30+fontMetrics().height()); cancel.move(width()/2-cancel.width()/2,label.geometry().bottom()+8); connect(&cancel,SIGNAL(clicked()),this,SLOT(reject())); centerOnMain(this); + setResult(-1); show(); - while (!result() && keysource.Empty()) { + while (result()<0 && keysource.Empty()) { qApp->enter_loop(); } hide(); @@ -3440,9 +4150,14 @@ void NetHackQtYnDialog::keyPressEvent(QKeyEvent* event) event->ignore(); } +void NetHackQtYnDialog::doneItem(int i) +{ + done(i+1000); +} + void NetHackQtYnDialog::done(int i) { - setResult(i+1000); + setResult(i); qApp->exit_loop(); } @@ -3464,10 +4179,10 @@ NetHackQtGlyphs::NetHackQtGlyphs() tiles_per_row = 40; } } else { - tiles_per_row = 1; - if (img.height()%total_tiles_used) { - impossible("Tile file \"%s\" has %d lines, not multiple of glyph count (%d)", - tile_file, img.height(), total_tiles_used); + tiles_per_row = TILES_PER_ROW; + if (img.width()%tiles_per_row) { + impossible("Tile file \"%s\" has %d columns, not multiple of row count (%d)", + tile_file, img.width(), tiles_per_row); } } int rows = ((total_tiles_used+tiles_per_row-1) / tiles_per_row); @@ -3604,12 +4319,53 @@ struct { NetHackQtBind::NetHackQtBind(int& argc, char** argv) : #ifdef KDE KApplication(argc,argv) +#elif defined(QWS) // not quite the right condition + QPEApplication(argc,argv) #else QApplication(argc,argv) #endif { + QPixmap pm("nhsplash.xpm"); + if ( !pm.isNull() ) { + QVBox *vb = new QVBox(0,0, + WStyle_Customize | WStyle_NoBorder | nh_WX11BypassWM | WStyle_StaysOnTop ); + splash = vb; + QLabel *lsplash = new QLabel(vb); + lsplash->setAlignment(AlignCenter); + lsplash->setPixmap(pm); + QLabel* capt = new QLabel("Loading...",vb); + capt->setAlignment(AlignCenter); + if ( pm.mask() ) { + lsplash->setFixedSize(pm.size()); + lsplash->setMask(*pm.mask()); + } + splash->move((QApplication::desktop()->width()-pm.width())/2, + (QApplication::desktop()->height()-pm.height())/2); + //splash->setGeometry(0,0,100,100); + if ( qt_compact_mode ) { + splash->showMaximized(); + } else { + vb->setFrameStyle(QFrame::WinPanel|QFrame::Raised); + vb->setMargin(10); + splash->adjustSize(); + splash->show(); + } + + // force content refresh outside event loop + splash->repaint(FALSE); + lsplash->repaint(FALSE); + capt->repaint(FALSE); + qApp->flushX(); + + } else { + splash = 0; + } main = new NetHackQtMainWindow(keybuffer); +#if defined(QWS) // not quite the right condition + showMainWidget(main); +#else setMainWidget(main); +#endif qt_settings=new NetHackQtSettings(main->width(),main->height()); } @@ -3656,29 +4412,146 @@ void NetHackQtBind::qt_player_selection() qt_askname(); } +NetHackQtSavedGameSelector::NetHackQtSavedGameSelector(const char** saved) : + QDialog(0,"sgsel",TRUE) +{ + QVBoxLayout *vbl = new QVBoxLayout(this,6); + QHBox* hb; + + QLabel* logo = new QLabel(this); vbl->addWidget(logo); + logo->setAlignment(AlignCenter); + logo->setPixmap(QPixmap("nhsplash.xpm")); + QLabel* attr = new QLabel("by the NetHack DevTeam",this); + attr->setAlignment(AlignCenter); + vbl->addWidget(attr); + vbl->addStretch(2); + /* + QLabel* logo = new QLabel(hb); + hb = new QHBox(this); + vbl->addWidget(hb, AlignCenter); + logo->setPixmap(QPixmap(nh_icon)); + logo->setAlignment(AlignRight|AlignVCenter); + new QLabel(nh_attribution,hb); + */ + + hb = new QHBox(this); + vbl->addWidget(hb, AlignCenter); + QPushButton* q = new QPushButton("Quit",hb); + connect(q, SIGNAL(clicked()), this, SLOT(reject())); + QPushButton* c = new QPushButton("New Game",hb); + connect(c, SIGNAL(clicked()), this, SLOT(accept())); + c->setDefault(TRUE); + + QButtonGroup* bg = new QButtonGroup(3, Horizontal, "Saved Characters",this); + vbl->addWidget(bg); + connect(bg, SIGNAL(clicked(int)), this, SLOT(done(int))); + for (int i=0; saved[i]; i++) { + QPushButton* b = new QPushButton(saved[i],bg); + bg->insert(b, i+2); + } +} + +int NetHackQtSavedGameSelector::choose() +{ +#if defined(QWS) // probably safe with Qt 3, too (where show!=exec in QDialog). + if ( qt_compact_mode ) + showMaximized(); +#endif + return exec()-2; +} + +static char** get_saved_names() +{ + int myuid=getuid(); + struct dirent **namelist; + int n = scandir("save", &namelist, 0, alphasort);; + if ( n > 0 ) { + int i,j=0; + char** result = (char**)malloc((n+1)*sizeof(char*)); /* at most */ + for (i=0; id_name, "%d%s", &uid, name ) == 2 ) { + if ( uid == myuid ) { + char* end = strstr(name,".gz"); + if ( !end ) end = strstr(name,".Z"); + if ( end ) *end = 0; + result[j++] = strdup(name); + } + } + } + result[j++] = 0; + return result; + } else { + return 0; + } +} + +static void free_saved_names(char** saved) +{ + if ( saved ) { + int i=0; + while (saved[i]) free(saved[i++]); + free(saved); + } +} + void NetHackQtBind::qt_askname() { have_asked = TRUE; // We do it all here, and nothing in askname - NetHackQtPlayerSelector selector(keybuffer); - - if (selector.Choose()) { - // ... - } else { - clearlocks(); - qt_exit_nhwindows(0); - terminate(0); + char** saved = get_saved_names(); + int ch = -1; + if ( saved && *saved ) { + if ( splash ) splash->hide(); + NetHackQtSavedGameSelector sgsel((const char**)saved); + ch = sgsel.choose(); + if ( ch >= 0 ) + strcpy(plname,saved[ch]); + } + free_saved_names(saved); + + switch (ch) { + case -1: + if ( splash ) splash->hide(); + if (NetHackQtPlayerSelector(keybuffer).Choose()) + return; + case -2: + break; + default: + return; } + + // Quit + clearlocks(); + qt_exit_nhwindows(0); + terminate(0); } void NetHackQtBind::qt_get_nh_event() { } +#if defined(QWS) +// Kludge to access lastWindowClosed() signal. +class TApp : public QApplication { +public: + TApp(int& c, char**v) : QApplication(c,v) {} + void lwc() { emit lastWindowClosed(); } +}; +#endif + void NetHackQtBind::qt_exit_nhwindows(const char *) { +#if defined(QWS) + // Avoids bug in SHARP SL5500 + ((TApp*)qApp)->lwc(); + qApp->quit(); +#endif + + delete instance; // ie. qApp } void NetHackQtBind::qt_suspend_nhwindows(const char *) @@ -3722,6 +4595,19 @@ winid NetHackQtBind::qt_create_nhwindow(int type) window=new NetHackQtTextWindow(keybuffer); } + // Note: use of isHidden does not work with Qt 2.1 + if ( splash +#if QT_VERSION >= 300 + && !main->isHidden() +#else + && main->isVisible() +#endif + ) + { + delete splash; + splash = 0; + } + id_to_window[id] = window; return id; } @@ -3955,7 +4841,7 @@ char NetHackQtBind::qt_yn_function(const char *question, const char *choices, CH #ifdef USE_POPUPS // Improve some special-cases (DIRKS 08/02/23) if (strcmp (choices,"ynq") == 0) { - switch (QMessageBox::information (0,"NetHack",question,"&Yes","&No","&Quit",0,2)) + switch (QMessageBox::information (qApp->mainWidget(),"NetHack",question,"&Yes","&No","&Quit",0,2)) { case 0: return 'y'; case 1: return 'n'; @@ -3964,7 +4850,7 @@ char NetHackQtBind::qt_yn_function(const char *question, const char *choices, CH } if (strcmp (choices,"yn") == 0) { - switch (QMessageBox::information(0,"NetHack",question,"&Yes", "&No",0,1)) + switch (QMessageBox::information(qApp->mainWidget(),"NetHack",question,"&Yes", "&No",0,1)) { case 0: return 'y'; case 1: return 'n'; @@ -4141,6 +5027,11 @@ void NetHackQtBind::qt_outrip(winid wid, int how) bool NetHackQtBind::notify(QObject *receiver, QEvent *event) { + // Ignore Alt-key navigation to menubar, it's annoying when you + // use Alt-Direction to move around. + if ( main && event->type()==QEvent::KeyRelease && main==receiver ) + return TRUE; + bool result=QApplication::notify(receiver,event); if (event->type()==QEvent::KeyPress) { QKeyEvent* key_event=(QKeyEvent*)event; @@ -4179,12 +5070,14 @@ NetHackQtBind* NetHackQtBind::instance=0; NetHackQtKeyBuffer NetHackQtBind::keybuffer; NetHackQtClickBuffer NetHackQtBind::clickbuffer; NetHackQtMainWindow* NetHackQtBind::main=0; +QWidget* NetHackQtBind::splash=0; extern "C" struct window_procs Qt_procs; struct window_procs Qt_procs = { "Qt", + WC_COLOR|WC_HILITE_PET, NetHackQtBind::qt_init_nhwindows, NetHackQtBind::qt_player_selection, NetHackQtBind::qt_askname, @@ -4238,13 +5131,15 @@ struct window_procs Qt_procs = { #else genl_outrip, #endif + genl_preference_update, }; extern "C" void play_usersound(const char* filename, int volume) { #ifdef USER_SOUNDS - // Qt 2.2 has sound - //QSound::play(filename,volume); +#ifndef QT_NO_SOUND + QSound::play(filename); +#endif #endif } @@ -4252,3 +5147,6 @@ extern "C" void play_usersound(const char* filename, int volume) #ifndef KDE #include "qt_kde0.moc" #endif +#if QT_VERSION >= 300 +#include "qttableview.moc" +#endif diff --git a/win/Qt/qttableview.cpp b/win/Qt/qttableview.cpp new file mode 100644 index 0000000..abeda15 --- /dev/null +++ b/win/Qt/qttableview.cpp @@ -0,0 +1,2275 @@ +/********************************************************************** +** $Id: qttableview.cpp,v 1.2 2002/03/09 03:13:15 jwalz Exp $ +** +** Implementation of QtTableView class +** +** Created : 941115 +** +** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. +** +** This file contains a class moved out of the Qt GUI Toolkit API. It +** may be used, distributed and modified without limitation. +** +**********************************************************************/ + +#include "qttableview.h" +#if QT_VERSION >= 300 +#ifndef QT_NO_QTTABLEVIEW +#include +#include +#include +#include + +enum ScrollBarDirtyFlags { + verGeometry = 0x01, + verSteps = 0x02, + verRange = 0x04, + verValue = 0x08, + horGeometry = 0x10, + horSteps = 0x20, + horRange = 0x40, + horValue = 0x80, + verMask = 0x0F, + horMask = 0xF0 +}; + + +#define HSBEXT horizontalScrollBar()->sizeHint().height() +#define VSBEXT verticalScrollBar()->sizeHint().width() + + +class QCornerSquare : public QWidget // internal class +{ +public: + QCornerSquare( QWidget *, const char* = 0 ); + void paintEvent( QPaintEvent * ); +}; + +QCornerSquare::QCornerSquare( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ +} + +void QCornerSquare::paintEvent( QPaintEvent * ) +{ +} + + +// NOT REVISED +/*! + \class QtTableView qttableview.h + \brief The QtTableView class provides an abstract base for tables. + + \obsolete + + A table view consists of a number of abstract cells organized in rows + and columns, and a visible part called a view. The cells are identified + with a row index and a column index. The top-left cell is in row 0, + column 0. + + The behavior of the widget can be finely tuned using + setTableFlags(); a typical subclass will consist of little more than a + call to setTableFlags(), some table content manipulation and an + implementation of paintCell(). Subclasses that need cells with + variable width or height must reimplement cellHeight() and/or + cellWidth(). Use updateTableSize() to tell QtTableView when the + width or height has changed. + + When you read this documentation, it is important to understand the + distinctions among the four pixel coordinate systems involved. + + \list 1 + \i The \e cell coordinates. (0,0) is the top-left corner of a cell. + Cell coordinates are used by functions such as paintCell(). + + \i The \e table coordinates. (0,0) is the top-left corner of the cell at + row 0 and column 0. These coordinates are absolute; that is, they are + independent of what part of the table is visible at the moment. They are + used by functions such as setXOffset() or maxYOffset(). + + \i The \e widget coordinates. (0,0) is the top-left corner of the widget, + \e including the frame. They are used by functions such as repaint(). + + \i The \e view coordinates. (0,0) is the top-left corner of the view, \e + excluding the frame. This is the least-used coordinate system; it is used by + functions such as viewWidth(). \endlist + + It is rather unfortunate that we have to use four different + coordinate systems, but there was no alternative to provide a flexible and + powerful base class. + + Note: The row,column indices are always given in that order, + i.e., first the vertical (row), then the horizontal (column). This is + the opposite order of all pixel operations, which take first the + horizontal (x) and then the vertical (y). + + + + \warning the functions setNumRows(), setNumCols(), setCellHeight(), + setCellWidth(), setTableFlags() and clearTableFlags() may cause + virtual functions such as cellWidth() and cellHeight() to be called, + even if autoUpdate() is FALSE. This may cause errors if relevant + state variables are not initialized. + + \warning Experience has shown that use of this widget tends to cause + more bugs than expected and our analysis indicates that the widget's + very flexibility is the problem. If QScrollView or QListBox can + easily be made to do the job you need, we recommend subclassing + those widgets rather than QtTableView. In addition, QScrollView makes + it easy to have child widgets inside tables, which QtTableView + doesn't support at all. + + \sa QScrollView + \link guibooks.html#fowler GUI Design Handbook: Table\endlink +*/ + + +/*! + Constructs a table view. The \a parent, \a name and \f arguments + are passed to the QFrame constructor. + + The \link setTableFlags() table flags\endlink are all cleared (set to 0). + Set \c Tbl_autoVScrollBar or \c Tbl_autoHScrollBar to get automatic scroll + bars and \c Tbl_clipCellPainting to get safe clipping. + + The \link setCellHeight() cell height\endlink and \link setCellWidth() + cell width\endlink are set to 0. + + Frame line shapes (QFrame::HLink and QFrame::VLine) are disallowed; + see QFrame::setFrameStyle(). + + Note that the \a f argument is \e not \link setTableFlags() table + flags \endlink but rather \link QWidget::QWidget() widget + flags. \endlink + +*/ + +QtTableView::QtTableView( QWidget *parent, const char *name, WFlags f ) + : QFrame( parent, name, f ) +{ + nRows = nCols = 0; // zero rows/cols + xCellOffs = yCellOffs = 0; // zero offset + xCellDelta = yCellDelta = 0; // zero cell offset + xOffs = yOffs = 0; // zero total pixel offset + cellH = cellW = 0; // user defined cell size + tFlags = 0; + vScrollBar = hScrollBar = 0; // no scroll bars + cornerSquare = 0; + sbDirty = 0; + eraseInPaint = FALSE; + verSliding = FALSE; + verSnappingOff = FALSE; + horSliding = FALSE; + horSnappingOff = FALSE; + coveringCornerSquare = FALSE; + inSbUpdate = FALSE; +} + +/*! + Destroys the table view. +*/ + +QtTableView::~QtTableView() +{ + delete vScrollBar; + delete hScrollBar; + delete cornerSquare; +} + + +/*! + \internal + Reimplements QWidget::setBackgroundColor() for binary compatibility. + \sa setPalette() +*/ + +void QtTableView::setBackgroundColor( const QColor &c ) +{ + QWidget::setBackgroundColor( c ); +} + +/*!\reimp +*/ + +void QtTableView::setPalette( const QPalette &p ) +{ + QWidget::setPalette( p ); +} + +/*!\reimp +*/ + +void QtTableView::show() +{ + showOrHideScrollBars(); + QWidget::show(); +} + + +/*! + \overload void QtTableView::repaint( bool erase ) + Repaints the entire view. +*/ + +/*! + Repaints the table view directly by calling paintEvent() directly + unless updates are disabled. + + Erases the view area \a (x,y,w,h) if \a erase is TRUE. Parameters \a + (x,y) are in \e widget coordinates. + + If \a w is negative, it is replaced with width() - x. + If \a h is negative, it is replaced with height() - y. + + Doing a repaint() usually is faster than doing an update(), but + calling update() many times in a row will generate a single paint + event. + + At present, QtTableView is the only widget that reimplements \link + QWidget::repaint() repaint()\endlink. It does this because by + clearing and then repainting one cell at at time, it can make the + screen flicker less than it would otherwise. */ + +void QtTableView::repaint( int x, int y, int w, int h, bool erase ) +{ + if ( !isVisible() || testWState(WState_BlockUpdates) ) + return; + if ( w < 0 ) + w = width() - x; + if ( h < 0 ) + h = height() - y; + QRect r( x, y, w, h ); + if ( r.isEmpty() ) + return; // nothing to do + QPaintEvent e( r ); + if ( erase && backgroundMode() != NoBackground ) + eraseInPaint = TRUE; // erase when painting + paintEvent( &e ); + eraseInPaint = FALSE; +} + +/*! + \overload void QtTableView::repaint( const QRect &r, bool erase ) + Replaints rectangle \a r. If \a erase is TRUE draws the background + using the palette's background. +*/ + + +/*! + \fn int QtTableView::numRows() const + Returns the number of rows in the table. + \sa numCols(), setNumRows() +*/ + +/*! + Sets the number of rows of the table to \a rows (must be non-negative). + Does not change topCell(). + + The table repaints itself automatically if autoUpdate() is set. + + \sa numCols(), setNumCols(), numRows() +*/ + +void QtTableView::setNumRows( int rows ) +{ + if ( rows < 0 ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QtTableView::setNumRows: (%s) Negative argument %d.", + name( "unnamed" ), rows ); +#endif + return; + } + if ( nRows == rows ) + return; + + if ( autoUpdate() && isVisible() ) { + int oldLastVisible = lastRowVisible(); + int oldTopCell = topCell(); + nRows = rows; + if ( autoUpdate() && isVisible() && + ( oldLastVisible != lastRowVisible() || oldTopCell != topCell() ) ) + repaint( oldTopCell != topCell() ); + } else { + // Be more careful - if destructing, bad things might happen. + nRows = rows; + } + updateScrollBars( verRange ); + updateFrameSize(); +} + +/*! + \fn int QtTableView::numCols() const + Returns the number of columns in the table. + \sa numRows(), setNumCols() +*/ + +/*! + Sets the number of columns of the table to \a cols (must be non-negative). + Does not change leftCell(). + + The table repaints itself automatically if autoUpdate() is set. + + \sa numCols(), numRows(), setNumRows() +*/ + +void QtTableView::setNumCols( int cols ) +{ + if ( cols < 0 ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QtTableView::setNumCols: (%s) Negative argument %d.", + name( "unnamed" ), cols ); +#endif + return; + } + if ( nCols == cols ) + return; + int oldCols = nCols; + nCols = cols; + if ( autoUpdate() && isVisible() ) { + int maxCol = lastColVisible(); + if ( maxCol >= oldCols || maxCol >= nCols ) + repaint(); + } + updateScrollBars( horRange ); + updateFrameSize(); +} + + +/*! + \fn int QtTableView::topCell() const + Returns the index of the first row in the table that is visible in + the view. The index of the first row is 0. + \sa leftCell(), setTopCell() +*/ + +/*! + Scrolls the table so that \a row becomes the top row. + The index of the very first row is 0. + \sa setYOffset(), setTopLeftCell(), setLeftCell() +*/ + +void QtTableView::setTopCell( int row ) +{ + setTopLeftCell( row, -1 ); + return; +} + +/*! + \fn int QtTableView::leftCell() const + Returns the index of the first column in the table that is visible in + the view. The index of the very leftmost column is 0. + \sa topCell(), setLeftCell() +*/ + +/*! + Scrolls the table so that \a col becomes the leftmost + column. The index of the leftmost column is 0. + \sa setXOffset(), setTopLeftCell(), setTopCell() +*/ + +void QtTableView::setLeftCell( int col ) +{ + setTopLeftCell( -1, col ); + return; +} + +/*! + Scrolls the table so that the cell at row \a row and colum \a + col becomes the top-left cell in the view. The cell at the extreme + top left of the table is at position (0,0). + \sa setLeftCell(), setTopCell(), setOffset() +*/ + +void QtTableView::setTopLeftCell( int row, int col ) +{ + int newX = xOffs; + int newY = yOffs; + + if ( col >= 0 ) { + if ( cellW ) { + newX = col*cellW; + if ( newX > maxXOffset() ) + newX = maxXOffset(); + } else { + newX = 0; + while ( col ) + newX += cellWidth( --col ); // optimize using current! ### + } + } + if ( row >= 0 ) { + if ( cellH ) { + newY = row*cellH; + if ( newY > maxYOffset() ) + newY = maxYOffset(); + } else { + newY = 0; + while ( row ) + newY += cellHeight( --row ); // optimize using current! ### + } + } + setOffset( newX, newY ); +} + + +/*! + \fn int QtTableView::xOffset() const + + Returns the x coordinate in \e table coordinates of the pixel that is + currently on the left edge of the view. + + \sa setXOffset(), yOffset(), leftCell() */ + +/*! + Scrolls the table so that \a x becomes the leftmost pixel in the view. + The \a x parameter is in \e table coordinates. + + The interaction with \link setTableFlags() Tbl_snapToHGrid + \endlink is tricky. + + \sa xOffset(), setYOffset(), setOffset(), setLeftCell() +*/ + +void QtTableView::setXOffset( int x ) +{ + setOffset( x, yOffset() ); +} + +/*! + \fn int QtTableView::yOffset() const + + Returns the y coordinate in \e table coordinates of the pixel that is + currently on the top edge of the view. + + \sa setYOffset(), xOffset(), topCell() +*/ + + +/*! + Scrolls the table so that \a y becomes the top pixel in the view. + The \a y parameter is in \e table coordinates. + + The interaction with \link setTableFlags() Tbl_snapToVGrid + \endlink is tricky. + + \sa yOffset(), setXOffset(), setOffset(), setTopCell() +*/ + +void QtTableView::setYOffset( int y ) +{ + setOffset( xOffset(), y ); +} + +/*! + Scrolls the table so that \a (x,y) becomes the top-left pixel + in the view. Parameters \a (x,y) are in \e table coordinates. + + The interaction with \link setTableFlags() Tbl_snapTo*Grid \endlink + is tricky. If \a updateScrBars is TRUE, the scroll bars are + updated. + + \sa xOffset(), yOffset(), setXOffset(), setYOffset(), setTopLeftCell() +*/ + +void QtTableView::setOffset( int x, int y, bool updateScrBars ) +{ + if ( (!testTableFlags(Tbl_snapToHGrid) || xCellDelta == 0) && + (!testTableFlags(Tbl_snapToVGrid) || yCellDelta == 0) && + (x == xOffs && y == yOffs) ) + return; + + if ( x < 0 ) + x = 0; + if ( y < 0 ) + y = 0; + + if ( cellW ) { + if ( x > maxXOffset() ) + x = maxXOffset(); + xCellOffs = x / cellW; + if ( !testTableFlags(Tbl_snapToHGrid) ) { + xCellDelta = (short)(x % cellW); + } else { + x = xCellOffs*cellW; + xCellDelta = 0; + } + } else { + int xn=0, xcd=0, col = 0; + while ( col < nCols-1 && x >= xn+(xcd=cellWidth(col)) ) { + xn += xcd; + col++; + } + xCellOffs = col; + if ( testTableFlags(Tbl_snapToHGrid) ) { + xCellDelta = 0; + x = xn; + } else { + xCellDelta = (short)(x-xn); + } + } + if ( cellH ) { + if ( y > maxYOffset() ) + y = maxYOffset(); + yCellOffs = y / cellH; + if ( !testTableFlags(Tbl_snapToVGrid) ) { + yCellDelta = (short)(y % cellH); + } else { + y = yCellOffs*cellH; + yCellDelta = 0; + } + } else { + int yn=0, yrd=0, row=0; + while ( row < nRows-1 && y >= yn+(yrd=cellHeight(row)) ) { + yn += yrd; + row++; + } + yCellOffs = row; + if ( testTableFlags(Tbl_snapToVGrid) ) { + yCellDelta = 0; + y = yn; + } else { + yCellDelta = (short)(y-yn); + } + } + int dx = (x - xOffs); + int dy = (y - yOffs); + xOffs = x; + yOffs = y; + if ( autoUpdate() && isVisible() ) + scroll( dx, dy ); + if ( updateScrBars ) + updateScrollBars( verValue | horValue ); +} + + +/*! + \overload int QtTableView::cellWidth() const + + Returns the column width in pixels. Returns 0 if the columns have + variable widths. + + \sa setCellWidth(), cellHeight() +*/ + +/*! + Returns the width of column \a col in pixels. + + This function is virtual and must be reimplemented by subclasses that + have variable cell widths. Note that if the total table width + changes, updateTableSize() must be called. + + \sa setCellWidth(), cellHeight(), totalWidth(), updateTableSize() +*/ + +int QtTableView::cellWidth( int ) +{ + return cellW; +} + + +/*! + Sets the width in pixels of the table cells to \a cellWidth. + + Setting it to 0 means that the column width is variable. When + set to 0 (this is the default) QtTableView calls the virtual function + cellWidth() to get the width. + + \sa cellWidth(), setCellHeight(), totalWidth(), numCols() +*/ + +void QtTableView::setCellWidth( int cellWidth ) +{ + if ( cellW == cellWidth ) + return; +#if defined(QT_CHECK_RANGE) + if ( cellWidth < 0 || cellWidth > SHRT_MAX ) { + qWarning( "QtTableView::setCellWidth: (%s) Argument out of range (%d)", + name( "unnamed" ), cellWidth ); + return; + } +#endif + cellW = (short)cellWidth; + + updateScrollBars( horSteps | horRange ); + if ( autoUpdate() && isVisible() ) + repaint(); + +} + +/*! + \overload int QtTableView::cellHeight() const + + Returns the row height, in pixels. Returns 0 if the rows have + variable heights. + + \sa setCellHeight(), cellWidth() +*/ + + +/*! + Returns the height of row \a row in pixels. + + This function is virtual and must be reimplemented by subclasses that + have variable cell heights. Note that if the total table height + changes, updateTableSize() must be called. + + \sa setCellHeight(), cellWidth(), totalHeight() +*/ + +int QtTableView::cellHeight( int ) +{ + return cellH; +} + +/*! + Sets the height in pixels of the table cells to \a cellHeight. + + Setting it to 0 means that the row height is variable. When set + to 0 (this is the default), QtTableView calls the virtual function + cellHeight() to get the height. + + \sa cellHeight(), setCellWidth(), totalHeight(), numRows() +*/ + +void QtTableView::setCellHeight( int cellHeight ) +{ + if ( cellH == cellHeight ) + return; +#if defined(QT_CHECK_RANGE) + if ( cellHeight < 0 || cellHeight > SHRT_MAX ) { + qWarning( "QtTableView::setCellHeight: (%s) Argument out of range (%d)", + name( "unnamed" ), cellHeight ); + return; + } +#endif + cellH = (short)cellHeight; + if ( autoUpdate() && isVisible() ) + repaint(); + updateScrollBars( verSteps | verRange ); +} + + +/*! + Returns the total width of the table in pixels. + + This function is virtual and should be reimplemented by subclasses that + have variable cell widths and a non-trivial cellWidth() function, or a + large number of columns in the table. + + The default implementation may be slow for very wide tables. + + \sa cellWidth(), totalHeight() */ + +int QtTableView::totalWidth() +{ + if ( cellW ) { + return cellW*nCols; + } else { + int tw = 0; + for( int i = 0 ; i < nCols ; i++ ) + tw += cellWidth( i ); + return tw; + } +} + +/*! + Returns the total height of the table in pixels. + + This function is virtual and should be reimplemented by subclasses that + have variable cell heights and a non-trivial cellHeight() function, or a + large number of rows in the table. + + The default implementation may be slow for very tall tables. + + \sa cellHeight(), totalWidth() +*/ + +int QtTableView::totalHeight() +{ + if ( cellH ) { + return cellH*nRows; + } else { + int th = 0; + for( int i = 0 ; i < nRows ; i++ ) + th += cellHeight( i ); + return th; + } +} + + +/*! + \fn uint QtTableView::tableFlags() const + + Returns the union of the table flags that are currently set. + + \sa setTableFlags(), clearTableFlags(), testTableFlags() +*/ + +/*! + \fn bool QtTableView::testTableFlags( uint f ) const + + Returns TRUE if any of the table flags in \a f are currently set, + otherwise FALSE. + + \sa setTableFlags(), clearTableFlags(), tableFlags() +*/ + +/*! + Sets the table flags to \a f. + + If a flag setting changes the appearance of the table, the table is + repainted if - and only if - autoUpdate() is TRUE. + + The table flags are mostly single bits, though there are some multibit + flags for convenience. Here is a complete list: + +
+
Tbl_vScrollBar
- The table has a vertical scroll bar. +
Tbl_hScrollBar
- The table has a horizontal scroll bar. +
Tbl_autoVScrollBar
- The table has a vertical scroll bar if + - and only if - the table is taller than the view. +
Tbl_autoHScrollBar
The table has a horizontal scroll bar if + - and only if - the table is wider than the view. +
Tbl_autoScrollBars
- The union of the previous two flags. +
Tbl_clipCellPainting
- The table uses QPainter::setClipRect() to + make sure that paintCell() will not draw outside the cell + boundaries. +
Tbl_cutCellsV
- The table will never show part of a + cell at the bottom of the table; if there is not space for all of + a cell, the space is left blank. +
Tbl_cutCellsH
- The table will never show part of a + cell at the right side of the table; if there is not space for all of + a cell, the space is left blank. +
Tbl_cutCells
- The union of the previous two flags. +
Tbl_scrollLastHCell
- When the user scrolls horizontally, + let him/her scroll the last cell left until it is at the left + edge of the view. If this flag is not set, the user can only scroll + to the point where the last cell is completely visible. +
Tbl_scrollLastVCell
- When the user scrolls vertically, let + him/her scroll the last cell up until it is at the top edge of + the view. If this flag is not set, the user can only scroll to the + point where the last cell is completely visible. +
Tbl_scrollLastCell
- The union of the previous two flags. +
Tbl_smoothHScrolling
- The table scrolls as smoothly as + possible when the user scrolls horizontally. When this flag is not + set, scrolling is done one cell at a time. +
Tbl_smoothVScrolling
- The table scrolls as smoothly as + possible when scrolling vertically. When this flag is not set, + scrolling is done one cell at a time. +
Tbl_smoothScrolling
- The union of the previous two flags. +
Tbl_snapToHGrid
- Except when the user is actually scrolling, + the leftmost column shown snaps to the leftmost edge of the view. +
Tbl_snapToVGrid
- Except when the user is actually + scrolling, the top row snaps to the top edge of the view. +
Tbl_snapToGrid
- The union of the previous two flags. +
+ + You can specify more than one flag at a time using bitwise OR. + + Example: + \code + setTableFlags( Tbl_smoothScrolling | Tbl_autoScrollBars ); + \endcode + + \warning The cutCells options (\c Tbl_cutCells, \c Tbl_cutCellsH and + Tbl_cutCellsV) may cause painting problems when scrollbars are + enabled. Do not combine cutCells and scrollbars. + + + \sa clearTableFlags(), testTableFlags(), tableFlags() +*/ + +void QtTableView::setTableFlags( uint f ) +{ + f = (f ^ tFlags) & f; // clear flags already set + tFlags |= f; + + bool updateOn = autoUpdate(); + setAutoUpdate( FALSE ); + + uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH; + + if ( f & Tbl_vScrollBar ) { + setVerScrollBar( TRUE ); + } + if ( f & Tbl_hScrollBar ) { + setHorScrollBar( TRUE ); + } + if ( f & Tbl_autoVScrollBar ) { + updateScrollBars( verRange ); + } + if ( f & Tbl_autoHScrollBar ) { + updateScrollBars( horRange ); + } + if ( f & Tbl_scrollLastHCell ) { + updateScrollBars( horRange ); + } + if ( f & Tbl_scrollLastVCell ) { + updateScrollBars( verRange ); + } + if ( f & Tbl_snapToHGrid ) { + updateScrollBars( horRange ); + } + if ( f & Tbl_snapToVGrid ) { + updateScrollBars( verRange ); + } + if ( f & Tbl_snapToGrid ) { // Note: checks for 2 flags + if ( (f & Tbl_snapToHGrid) != 0 && xCellDelta != 0 || //have to scroll? + (f & Tbl_snapToVGrid) != 0 && yCellDelta != 0 ) { + snapToGrid( (f & Tbl_snapToHGrid) != 0, // do snapping + (f & Tbl_snapToVGrid) != 0 ); + repaintMask |= Tbl_snapToGrid; // repaint table + } + } + + if ( updateOn ) { + setAutoUpdate( TRUE ); + updateScrollBars(); + if ( isVisible() && (f & repaintMask) ) + repaint(); + } + +} + +/*! + Clears the \link setTableFlags() table flags\endlink that are set + in \a f. + + Example (clears a single flag): + \code + clearTableFlags( Tbl_snapToGrid ); + \endcode + + The default argument clears all flags. + + \sa setTableFlags(), testTableFlags(), tableFlags() +*/ + +void QtTableView::clearTableFlags( uint f ) +{ + f = (f ^ ~tFlags) & f; // clear flags that are already 0 + tFlags &= ~f; + + bool updateOn = autoUpdate(); + setAutoUpdate( FALSE ); + + uint repaintMask = Tbl_cutCellsV | Tbl_cutCellsH; + + if ( f & Tbl_vScrollBar ) { + setVerScrollBar( FALSE ); + } + if ( f & Tbl_hScrollBar ) { + setHorScrollBar( FALSE ); + } + if ( f & Tbl_scrollLastHCell ) { + int maxX = maxXOffset(); + if ( xOffs > maxX ) { + setOffset( maxX, yOffs ); + repaintMask |= Tbl_scrollLastHCell; + } + updateScrollBars( horRange ); + } + if ( f & Tbl_scrollLastVCell ) { + int maxY = maxYOffset(); + if ( yOffs > maxY ) { + setOffset( xOffs, maxY ); + repaintMask |= Tbl_scrollLastVCell; + } + updateScrollBars( verRange ); + } + if ( f & Tbl_smoothScrolling ) { // Note: checks for 2 flags + if ((f & Tbl_smoothHScrolling) != 0 && xCellDelta != 0 ||//must scroll? + (f & Tbl_smoothVScrolling) != 0 && yCellDelta != 0 ) { + snapToGrid( (f & Tbl_smoothHScrolling) != 0, // do snapping + (f & Tbl_smoothVScrolling) != 0 ); + repaintMask |= Tbl_smoothScrolling; // repaint table + } + } + if ( f & Tbl_snapToHGrid ) { + updateScrollBars( horRange ); + } + if ( f & Tbl_snapToVGrid ) { + updateScrollBars( verRange ); + } + if ( updateOn ) { + setAutoUpdate( TRUE ); + updateScrollBars(); // returns immediately if nothing to do + if ( isVisible() && (f & repaintMask) ) + repaint(); + } + +} + + +/*! + \fn bool QtTableView::autoUpdate() const + + Returns TRUE if the view updates itself automatically whenever it + is changed in some way. + + \sa setAutoUpdate() +*/ + +/*! + Sets the auto-update option of the table view to \a enable. + + If \a enable is TRUE (this is the default), the view updates itself + automatically whenever it has changed in some way (for example, when a + \link setTableFlags() flag\endlink is changed). + + If \a enable is FALSE, the view does NOT repaint itself or update + its internal state variables when it is changed. This can be + useful to avoid flicker during large changes and is singularly + useless otherwise. Disable auto-update, do the changes, re-enable + auto-update and call repaint(). + + \warning Do not leave the view in this state for a long time + (i.e., between events). If, for example, the user interacts with the + view when auto-update is off, strange things can happen. + + Setting auto-update to TRUE does not repaint the view; you must call + repaint() to do this. + + \sa autoUpdate(), repaint() +*/ + +void QtTableView::setAutoUpdate( bool enable ) +{ + if ( isUpdatesEnabled() == enable ) + return; + setUpdatesEnabled( enable ); + if ( enable ) { + showOrHideScrollBars(); + updateScrollBars(); + } +} + + +/*! + Repaints the cell at row \a row, column \a col if it is inside the view. + + If \a erase is TRUE, the relevant part of the view is cleared to the + background color/pixmap before the contents are repainted. + + \sa isVisible() +*/ + +void QtTableView::updateCell( int row, int col, bool erase ) +{ + int xPos, yPos; + if ( !colXPos( col, &xPos ) ) + return; + if ( !rowYPos( row, &yPos ) ) + return; + QRect uR = QRect( xPos, yPos, + cellW ? cellW : cellWidth(col), + cellH ? cellH : cellHeight(row) ); + repaint( uR.intersect(viewRect()), erase ); +} + + +/*! + \fn QRect QtTableView::cellUpdateRect() const + + This function should be called only from the paintCell() function in + subclasses. It returns the portion of a cell that actually needs to be + updated in \e cell coordinates. This is useful only for non-trivial + paintCell(). + +*/ + +/*! + Returns the rectangle that is the actual table, excluding any + frame, in \e widget coordinates. +*/ + +QRect QtTableView::viewRect() const +{ + return QRect( frameWidth(), frameWidth(), viewWidth(), viewHeight() ); +} + + +/*! + Returns the index of the last (bottom) row in the view. + The index of the first row is 0. + + If no rows are visible it returns -1. This can happen if the + view is too small for the first row and Tbl_cutCellsV is set. + + \sa lastColVisible() +*/ + +int QtTableView::lastRowVisible() const +{ + int cellMaxY; + int row = findRawRow( maxViewY(), &cellMaxY ); + if ( row == -1 || row >= nRows ) { // maxViewY() past end? + row = nRows - 1; // yes: return last row + } else { + if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() ) { + if ( row == yCellOffs ) // cut by right margin? + return -1; // yes, nothing in the view + else + row = row - 1; // cut by margin, one back + } + } + return row; +} + +/*! + Returns the index of the last (right) column in the view. + The index of the first column is 0. + + If no columns are visible it returns -1. This can happen if the + view is too narrow for the first column and Tbl_cutCellsH is set. + + \sa lastRowVisible() +*/ + +int QtTableView::lastColVisible() const +{ + int cellMaxX; + int col = findRawCol( maxViewX(), &cellMaxX ); + if ( col == -1 || col >= nCols ) { // maxViewX() past end? + col = nCols - 1; // yes: return last col + } else { + if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() ) { + if ( col == xCellOffs ) // cut by bottom margin? + return -1; // yes, nothing in the view + else + col = col - 1; // cell by margin, one back + } + } + return col; +} + +/*! + Returns TRUE if \a row is at least partially visible. + \sa colIsVisible() +*/ + +bool QtTableView::rowIsVisible( int row ) const +{ + return rowYPos( row, 0 ); +} + +/*! + Returns TRUE if \a col is at least partially visible. + \sa rowIsVisible() +*/ + +bool QtTableView::colIsVisible( int col ) const +{ + return colXPos( col, 0 ); +} + + +/*! + \internal + Called when both scroll bars are active at the same time. Covers the + bottom left corner between the two scroll bars with an empty widget. +*/ + +void QtTableView::coverCornerSquare( bool enable ) +{ + coveringCornerSquare = enable; + if ( !cornerSquare && enable ) { + cornerSquare = new QCornerSquare( this ); + Q_CHECK_PTR( cornerSquare ); + cornerSquare->setGeometry( maxViewX() + frameWidth() + 1, + maxViewY() + frameWidth() + 1, + VSBEXT, + HSBEXT); + } + if ( autoUpdate() && cornerSquare ) { + if ( enable ) + cornerSquare->show(); + else + cornerSquare->hide(); + } +} + + +/*! + \internal + Scroll the view to a position such that: + + If \a horizontal is TRUE, the leftmost column shown fits snugly + with the left edge of the view. + + If \a vertical is TRUE, the top row shown fits snugly with the top + of the view. + + You can achieve the same effect automatically by setting any of the + \link setTableFlags() Tbl_snapTo*Grid \endlink table flags. +*/ + +void QtTableView::snapToGrid( bool horizontal, bool vertical ) +{ + int newXCell = -1; + int newYCell = -1; + if ( horizontal && xCellDelta != 0 ) { + int w = cellW ? cellW : cellWidth( xCellOffs ); + if ( xCellDelta >= w/2 ) + newXCell = xCellOffs + 1; + else + newXCell = xCellOffs; + } + if ( vertical && yCellDelta != 0 ) { + int h = cellH ? cellH : cellHeight( yCellOffs ); + if ( yCellDelta >= h/2 ) + newYCell = yCellOffs + 1; + else + newYCell = yCellOffs; + } + setTopLeftCell( newYCell, newXCell ); //row,column +} + +/*! + \internal + This internal slot is connected to the horizontal scroll bar's + QScrollBar::valueChanged() signal. + + Moves the table horizontally to offset \a val without updating the + scroll bar. +*/ + +void QtTableView::horSbValue( int val ) +{ + if ( horSliding ) { + horSliding = FALSE; + if ( horSnappingOff ) { + horSnappingOff = FALSE; + tFlags |= Tbl_snapToHGrid; + } + } + setOffset( val, yOffs, FALSE ); +} + +/*! + \internal + This internal slot is connected to the horizontal scroll bar's + QScrollBar::sliderMoved() signal. + + Scrolls the table smoothly horizontally even if \c Tbl_snapToHGrid is set. +*/ + +void QtTableView::horSbSliding( int val ) +{ + if ( testTableFlags(Tbl_snapToHGrid) && + testTableFlags(Tbl_smoothHScrolling) ) { + tFlags &= ~Tbl_snapToHGrid; // turn off snapping while sliding + setOffset( val, yOffs, FALSE ); + tFlags |= Tbl_snapToHGrid; // turn on snapping again + } else { + setOffset( val, yOffs, FALSE ); + } +} + +/*! + \internal + This internal slot is connected to the horizontal scroll bar's + QScrollBar::sliderReleased() signal. +*/ + +void QtTableView::horSbSlidingDone( ) +{ + if ( testTableFlags(Tbl_snapToHGrid) && + testTableFlags(Tbl_smoothHScrolling) ) + snapToGrid( TRUE, FALSE ); +} + +/*! + \internal + This internal slot is connected to the vertical scroll bar's + QScrollBar::valueChanged() signal. + + Moves the table vertically to offset \a val without updating the + scroll bar. +*/ + +void QtTableView::verSbValue( int val ) +{ + if ( verSliding ) { + verSliding = FALSE; + if ( verSnappingOff ) { + verSnappingOff = FALSE; + tFlags |= Tbl_snapToVGrid; + } + } + setOffset( xOffs, val, FALSE ); +} + +/*! + \internal + This internal slot is connected to the vertical scroll bar's + QScrollBar::sliderMoved() signal. + + Scrolls the table smoothly vertically even if \c Tbl_snapToVGrid is set. +*/ + +void QtTableView::verSbSliding( int val ) +{ + if ( testTableFlags(Tbl_snapToVGrid) && + testTableFlags(Tbl_smoothVScrolling) ) { + tFlags &= ~Tbl_snapToVGrid; // turn off snapping while sliding + setOffset( xOffs, val, FALSE ); + tFlags |= Tbl_snapToVGrid; // turn on snapping again + } else { + setOffset( xOffs, val, FALSE ); + } +} + +/*! + \internal + This internal slot is connected to the vertical scroll bar's + QScrollBar::sliderReleased() signal. +*/ + +void QtTableView::verSbSlidingDone( ) +{ + if ( testTableFlags(Tbl_snapToVGrid) && + testTableFlags(Tbl_smoothVScrolling) ) + snapToGrid( FALSE, TRUE ); +} + + +/*! + This virtual function is called before painting of table cells + is started. It can be reimplemented by subclasses that want to + to set up the painter in a special way and that do not want to + do so for each cell. +*/ + +void QtTableView::setupPainter( QPainter * ) +{ +} + +/*! + \fn void QtTableView::paintCell( QPainter *p, int row, int col ) + + This pure virtual function is called to paint the single cell at \a + (row,col) using \a p, which is open when paintCell() is called and + must remain open. + + The coordinate system is \link QPainter::translate() translated \endlink + so that the origin is at the top-left corner of the cell to be + painted, i.e. \e cell coordinates. Do not scale or shear the coordinate + system (or if you do, restore the transformation matrix before you + return). + + The painter is not clipped by default and for maximum efficiency. For safety, + call setTableFlags(Tbl_clipCellPainting) to enable clipping. + + \sa paintEvent(), setTableFlags() */ + + +/*! + Handles paint events, \a e, for the table view. + + Calls paintCell() for the cells that needs to be repainted. +*/ + +void QtTableView::paintEvent( QPaintEvent *e ) +{ + QRect updateR = e->rect(); // update rectangle + if ( sbDirty ) { + bool e = eraseInPaint; + updateScrollBars(); + eraseInPaint = e; + } + + QPainter paint( this ); + + if ( !contentsRect().contains( updateR, TRUE ) ) {// update frame ? + drawFrame( &paint ); + if ( updateR.left() < frameWidth() ) //### + updateR.setLeft( frameWidth() ); + if ( updateR.top() < frameWidth() ) + updateR.setTop( frameWidth() ); + } + + int maxWX = maxViewX(); + int maxWY = maxViewY(); + if ( updateR.right() > maxWX ) + updateR.setRight( maxWX ); + if ( updateR.bottom() > maxWY ) + updateR.setBottom( maxWY ); + + setupPainter( &paint ); // prepare for painting table + + int firstRow = findRow( updateR.y() ); + int firstCol = findCol( updateR.x() ); + int xStart, yStart; + if ( !colXPos( firstCol, &xStart ) || !rowYPos( firstRow, &yStart ) ) { + paint.eraseRect( updateR ); // erase area outside cells but in view + return; + } + int maxX = updateR.right(); + int maxY = updateR.bottom(); + int row = firstRow; + int col; + int yPos = yStart; + int xPos = maxX+1; // in case the while() is empty + int nextX; + int nextY; + QRect winR = viewRect(); + QRect cellR; + QRect cellUR; +#ifndef QT_NO_TRANSFORMATIONS + QWMatrix matrix; +#endif + + while ( yPos <= maxY && row < nRows ) { + nextY = yPos + (cellH ? cellH : cellHeight( row )); + if ( testTableFlags( Tbl_cutCellsV ) && nextY > ( maxWY + 1 ) ) + break; + col = firstCol; + xPos = xStart; + while ( xPos <= maxX && col < nCols ) { + nextX = xPos + (cellW ? cellW : cellWidth( col )); + if ( testTableFlags( Tbl_cutCellsH ) && nextX > ( maxWX + 1 ) ) + break; + + cellR.setRect( xPos, yPos, cellW ? cellW : cellWidth(col), + cellH ? cellH : cellHeight(row) ); + cellUR = cellR.intersect( updateR ); + if ( cellUR.isValid() ) { + cellUpdateR = cellUR; + cellUpdateR.moveBy( -xPos, -yPos ); // cell coordinates + if ( eraseInPaint ) + paint.eraseRect( cellUR ); + +#ifndef QT_NO_TRANSFORMATIONS + matrix.translate( xPos, yPos ); + paint.setWorldMatrix( matrix ); + if ( testTableFlags(Tbl_clipCellPainting) || + frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt + paint.setClipRect( cellUR ); + paintCell( &paint, row, col ); + paint.setClipping( FALSE ); + } else { + paintCell( &paint, row, col ); + } + matrix.reset(); + paint.setWorldMatrix( matrix ); +#else + paint.translate( xPos, yPos ); + if ( testTableFlags(Tbl_clipCellPainting) || + frameWidth() > 0 && !winR.contains( cellR ) ) { //##arnt + paint.setClipRect( cellUR ); + paintCell( &paint, row, col ); + paint.setClipping( FALSE ); + } else { + paintCell( &paint, row, col ); + } + paint.translate( -xPos, -yPos ); +#endif + } + col++; + xPos = nextX; + } + row++; + yPos = nextY; + } + + // while painting we have to erase any areas in the view that + // are not covered by cells but are covered by the paint event + // rectangle these must be erased. We know that xPos is the last + // x pixel updated + 1 and that yPos is the last y pixel updated + 1. + + // Note that this needs to be done regardless whether we do + // eraseInPaint or not. Reason: a subclass may implement + // flicker-freeness and encourage the use of repaint(FALSE). + // The subclass, however, cannot draw all pixels, just those + // inside the cells. So QtTableView is reponsible for all pixels + // outside the cells. + + QRect viewR = viewRect(); + const QColorGroup g = colorGroup(); + + if ( xPos <= maxX ) { + QRect r = viewR; + r.setLeft( xPos ); + r.setBottom( yPossetCursor( arrowCursor ); +#endif + sb->resize( sb->sizeHint() ); // height is irrelevant + Q_CHECK_PTR(sb); + sb->setTracking( FALSE ); + sb->setFocusPolicy( NoFocus ); + connect( sb, SIGNAL(valueChanged(int)), + SLOT(verSbValue(int))); + connect( sb, SIGNAL(sliderMoved(int)), + SLOT(verSbSliding(int))); + connect( sb, SIGNAL(sliderReleased()), + SLOT(verSbSlidingDone())); + sb->hide(); + that->vScrollBar = sb; + return sb; + } + return vScrollBar; +} + +/*! + Returns a pointer to the horizontal scroll bar mainly so you can + connect() to its signals. Note that the scroll bar works in pixel + values; use findCol() to translate to cell numbers. +*/ + +QScrollBar *QtTableView::horizontalScrollBar() const +{ + QtTableView *that = (QtTableView*)this; // semantic const + if ( !hScrollBar ) { + QScrollBar *sb = new QScrollBar( QScrollBar::Horizontal, that ); +#ifndef QT_NO_CURSOR + sb->setCursor( arrowCursor ); +#endif + sb->resize( sb->sizeHint() ); // width is irrelevant + sb->setFocusPolicy( NoFocus ); + Q_CHECK_PTR(sb); + sb->setTracking( FALSE ); + connect( sb, SIGNAL(valueChanged(int)), + SLOT(horSbValue(int))); + connect( sb, SIGNAL(sliderMoved(int)), + SLOT(horSbSliding(int))); + connect( sb, SIGNAL(sliderReleased()), + SLOT(horSbSlidingDone())); + sb->hide(); + that->hScrollBar = sb; + return sb; + } + return hScrollBar; +} + +/*! + Enables or disables the horizontal scroll bar, as required by + setAutoUpdate() and the \link setTableFlags() table flags\endlink. +*/ + +void QtTableView::setHorScrollBar( bool on, bool update ) +{ + if ( on ) { + tFlags |= Tbl_hScrollBar; + horizontalScrollBar(); // created + if ( update ) + updateScrollBars( horMask | verMask ); + else + sbDirty = sbDirty | (horMask | verMask); + if ( testTableFlags( Tbl_vScrollBar ) ) + coverCornerSquare( TRUE ); + if ( autoUpdate() ) + sbDirty = sbDirty | horMask; + } else { + tFlags &= ~Tbl_hScrollBar; + if ( !hScrollBar ) + return; + coverCornerSquare( FALSE ); + bool hideScrollBar = autoUpdate() && hScrollBar->isVisible(); + if ( hideScrollBar ) + hScrollBar->hide(); + if ( update ) + updateScrollBars( verMask ); + else + sbDirty = sbDirty | verMask; + if ( hideScrollBar && isVisible() ) + repaint( hScrollBar->x(), hScrollBar->y(), + width() - hScrollBar->x(), hScrollBar->height() ); + } + if ( update ) + updateFrameSize(); +} + + +/*! + Enables or disables the vertical scroll bar, as required by + setAutoUpdate() and the \link setTableFlags() table flags\endlink. +*/ + +void QtTableView::setVerScrollBar( bool on, bool update ) +{ + if ( on ) { + tFlags |= Tbl_vScrollBar; + verticalScrollBar(); // created + if ( update ) + updateScrollBars( verMask | horMask ); + else + sbDirty = sbDirty | (horMask | verMask); + if ( testTableFlags( Tbl_hScrollBar ) ) + coverCornerSquare( TRUE ); + if ( autoUpdate() ) + sbDirty = sbDirty | verMask; + } else { + tFlags &= ~Tbl_vScrollBar; + if ( !vScrollBar ) + return; + coverCornerSquare( FALSE ); + bool hideScrollBar = autoUpdate() && vScrollBar->isVisible(); + if ( hideScrollBar ) + vScrollBar->hide(); + if ( update ) + updateScrollBars( horMask ); + else + sbDirty = sbDirty | horMask; + if ( hideScrollBar && isVisible() ) + repaint( vScrollBar->x(), vScrollBar->y(), + vScrollBar->width(), height() - vScrollBar->y() ); + } + if ( update ) + updateFrameSize(); +} + + + + +int QtTableView::findRawRow( int yPos, int *cellMaxY, int *cellMinY, + bool goOutsideView ) const +{ + int r = -1; + if ( nRows == 0 ) + return r; + if ( goOutsideView || yPos >= minViewY() && yPos <= maxViewY() ) { + if ( yPos < minViewY() ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QtTableView::findRawRow: (%s) internal error: " + "yPos < minViewY() && goOutsideView " + "not supported. (%d,%d)", + name( "unnamed" ), yPos, yOffs ); +#endif + return -1; + } + if ( cellH ) { // uniform cell height + r = (yPos - minViewY() + yCellDelta)/cellH; // cell offs from top + if ( cellMaxY ) + *cellMaxY = (r + 1)*cellH + minViewY() - yCellDelta - 1; + if ( cellMinY ) + *cellMinY = r*cellH + minViewY() - yCellDelta; + r += yCellOffs; // absolute cell index + } else { // variable cell height + QtTableView *tw = (QtTableView *)this; + r = yCellOffs; + int h = minViewY() - yCellDelta; //##arnt3 + int oldH = h; + Q_ASSERT( r < nRows ); + while ( r < nRows ) { + oldH = h; + h += tw->cellHeight( r ); // Start of next cell + if ( yPos < h ) + break; + r++; + } + if ( cellMaxY ) + *cellMaxY = h - 1; + if ( cellMinY ) + *cellMinY = oldH; + } + } + return r; + +} + + +int QtTableView::findRawCol( int xPos, int *cellMaxX, int *cellMinX , + bool goOutsideView ) const +{ + int c = -1; + if ( nCols == 0 ) + return c; + if ( goOutsideView || xPos >= minViewX() && xPos <= maxViewX() ) { + if ( xPos < minViewX() ) { +#if defined(QT_CHECK_RANGE) + qWarning( "QtTableView::findRawCol: (%s) internal error: " + "xPos < minViewX() && goOutsideView " + "not supported. (%d,%d)", + name( "unnamed" ), xPos, xOffs ); +#endif + return -1; + } + if ( cellW ) { // uniform cell width + c = (xPos - minViewX() + xCellDelta)/cellW; //cell offs from left + if ( cellMaxX ) + *cellMaxX = (c + 1)*cellW + minViewX() - xCellDelta - 1; + if ( cellMinX ) + *cellMinX = c*cellW + minViewX() - xCellDelta; + c += xCellOffs; // absolute cell index + } else { // variable cell width + QtTableView *tw = (QtTableView *)this; + c = xCellOffs; + int w = minViewX() - xCellDelta; //##arnt3 + int oldW = w; + Q_ASSERT( c < nCols ); + while ( c < nCols ) { + oldW = w; + w += tw->cellWidth( c ); // Start of next cell + if ( xPos < w ) + break; + c++; + } + if ( cellMaxX ) + *cellMaxX = w - 1; + if ( cellMinX ) + *cellMinX = oldW; + } + } + return c; +} + + +/*! + Returns the index of the row at position \a yPos, where \a yPos is in + \e widget coordinates. Returns -1 if \a yPos is outside the valid + range. + + \sa findCol(), rowYPos() +*/ + +int QtTableView::findRow( int yPos ) const +{ + int cellMaxY; + int row = findRawRow( yPos, &cellMaxY ); + if ( testTableFlags(Tbl_cutCellsV) && cellMaxY > maxViewY() ) + row = - 1; // cell cut by bottom margin + if ( row >= nRows ) + row = -1; + return row; +} + + +/*! + Returns the index of the column at position \a xPos, where \a xPos is + in \e widget coordinates. Returns -1 if \a xPos is outside the valid + range. + + \sa findRow(), colXPos() +*/ + +int QtTableView::findCol( int xPos ) const +{ + int cellMaxX; + int col = findRawCol( xPos, &cellMaxX ); + if ( testTableFlags(Tbl_cutCellsH) && cellMaxX > maxViewX() ) + col = - 1; // cell cut by right margin + if ( col >= nCols ) + col = -1; + return col; +} + + +/*! + Computes the position in the widget of row \a row. + + Returns TRUE and stores the result in \a *yPos (in \e widget + coordinates) if the row is visible. Returns FALSE and does not modify + \a *yPos if \a row is invisible or invalid. + + \sa colXPos(), findRow() +*/ + +bool QtTableView::rowYPos( int row, int *yPos ) const +{ + int y; + if ( row >= yCellOffs ) { + if ( cellH ) { + int lastVisible = lastRowVisible(); + if ( row > lastVisible || lastVisible == -1 ) + return FALSE; + y = (row - yCellOffs)*cellH + minViewY() - yCellDelta; + } else { + //##arnt3 + y = minViewY() - yCellDelta; // y of leftmost cell in view + int r = yCellOffs; + QtTableView *tw = (QtTableView *)this; + int maxY = maxViewY(); + while ( r < row && y <= maxY ) + y += tw->cellHeight( r++ ); + if ( y > maxY ) + return FALSE; + + } + } else { + return FALSE; + } + if ( yPos ) + *yPos = y; + return TRUE; +} + + +/*! + Computes the position in the widget of column \a col. + + Returns TRUE and stores the result in \a *xPos (in \e widget + coordinates) if the column is visible. Returns FALSE and does not + modify \a *xPos if \a col is invisible or invalid. + + \sa rowYPos(), findCol() +*/ + +bool QtTableView::colXPos( int col, int *xPos ) const +{ + int x; + if ( col >= xCellOffs ) { + if ( cellW ) { + int lastVisible = lastColVisible(); + if ( col > lastVisible || lastVisible == -1 ) + return FALSE; + x = (col - xCellOffs)*cellW + minViewX() - xCellDelta; + } else { + //##arnt3 + x = minViewX() - xCellDelta; // x of uppermost cell in view + int c = xCellOffs; + QtTableView *tw = (QtTableView *)this; + int maxX = maxViewX(); + while ( c < col && x <= maxX ) + x += tw->cellWidth( c++ ); + if ( x > maxX ) + return FALSE; + } + } else { + return FALSE; + } + if ( xPos ) + *xPos = x; + return TRUE; +} + + +/*! + Moves the visible area of the table right by \a xPixels and + down by \a yPixels pixels. Both may be negative. + + \warning You might find that QScrollView offers a higher-level of + functionality than using QtTableView and this function. + + This function is \e not the same as QWidget::scroll(); in particular, + the signs of \a xPixels and \a yPixels have the reverse semantics. + + \sa setXOffset(), setYOffset(), setOffset(), setTopCell(), + setLeftCell() +*/ + +void QtTableView::scroll( int xPixels, int yPixels ) +{ + QWidget::scroll( -xPixels, -yPixels, contentsRect() ); +} + + +/*! + Returns the leftmost pixel of the table view in \e view + coordinates. This excludes the frame and any header. + + \sa maxViewY(), viewWidth(), contentsRect() +*/ + +int QtTableView::minViewX() const +{ + return frameWidth(); +} + + +/*! + Returns the top pixel of the table view in \e view + coordinates. This excludes the frame and any header. + + \sa maxViewX(), viewHeight(), contentsRect() +*/ + +int QtTableView::minViewY() const +{ + return frameWidth(); +} + + +/*! + Returns the rightmost pixel of the table view in \e view + coordinates. This excludes the frame and any scroll bar, but + includes blank pixels to the right of the visible table data. + + \sa maxViewY(), viewWidth(), contentsRect() +*/ + +int QtTableView::maxViewX() const +{ + return width() - 1 - frameWidth() + - (tFlags & Tbl_vScrollBar ? VSBEXT + : 0); +} + + +/*! + Returns the bottom pixel of the table view in \e view + coordinates. This excludes the frame and any scroll bar, but + includes blank pixels below the visible table data. + + \sa maxViewX(), viewHeight(), contentsRect() +*/ + +int QtTableView::maxViewY() const +{ + return height() - 1 - frameWidth() + - (tFlags & Tbl_hScrollBar ? HSBEXT + : 0); +} + + +/*! + Returns the width of the table view, as such, in \e view + coordinates. This does not include any header, scroll bar or frame, + but it does include background pixels to the right of the table data. + + \sa minViewX() maxViewX(), viewHeight(), contentsRect() viewRect() +*/ + +int QtTableView::viewWidth() const +{ + return maxViewX() - minViewX() + 1; +} + + +/*! + Returns the height of the table view, as such, in \e view + coordinates. This does not include any header, scroll bar or frame, + but it does include background pixels below the table data. + + \sa minViewY() maxViewY() viewWidth() contentsRect() viewRect() +*/ + +int QtTableView::viewHeight() const +{ + return maxViewY() - minViewY() + 1; +} + + +void QtTableView::doAutoScrollBars() +{ + int viewW = width() - frameWidth() - minViewX(); + int viewH = height() - frameWidth() - minViewY(); + bool vScrollOn = testTableFlags(Tbl_vScrollBar); + bool hScrollOn = testTableFlags(Tbl_hScrollBar); + int w = 0; + int h = 0; + int i; + + if ( testTableFlags(Tbl_autoHScrollBar) ) { + if ( cellW ) { + w = cellW*nCols; + } else { + i = 0; + while ( i < nCols && w <= viewW ) + w += cellWidth( i++ ); + } + if ( w > viewW ) + hScrollOn = TRUE; + else + hScrollOn = FALSE; + } + + if ( testTableFlags(Tbl_autoVScrollBar) ) { + if ( cellH ) { + h = cellH*nRows; + } else { + i = 0; + while ( i < nRows && h <= viewH ) + h += cellHeight( i++ ); + } + + if ( h > viewH ) + vScrollOn = TRUE; + else + vScrollOn = FALSE; + } + + if ( testTableFlags(Tbl_autoHScrollBar) && vScrollOn && !hScrollOn ) + if ( w > viewW - VSBEXT ) + hScrollOn = TRUE; + + if ( testTableFlags(Tbl_autoVScrollBar) && hScrollOn && !vScrollOn ) + if ( h > viewH - HSBEXT ) + vScrollOn = TRUE; + + setHorScrollBar( hScrollOn, FALSE ); + setVerScrollBar( vScrollOn, FALSE ); + updateFrameSize(); +} + + +/*! + \fn void QtTableView::updateScrollBars() + + Updates the scroll bars' contents and presence to match the table's + state. Generally, you should not need to call this. + + \sa setTableFlags() +*/ + +/*! + Updates the scroll bars' contents and presence to match the table's + state \c or \a f. + + \sa setTableFlags() +*/ + +void QtTableView::updateScrollBars( uint f ) +{ + sbDirty = sbDirty | f; + if ( inSbUpdate ) + return; + inSbUpdate = TRUE; + + if ( testTableFlags(Tbl_autoHScrollBar) && (sbDirty & horRange) || + testTableFlags(Tbl_autoVScrollBar) && (sbDirty & verRange) ) + // if range change and auto + doAutoScrollBars(); // turn scroll bars on/off if needed + + if ( !autoUpdate() ) { + inSbUpdate = FALSE; + return; + } + if ( yOffset() > 0 && testTableFlags( Tbl_autoVScrollBar ) && + !testTableFlags( Tbl_vScrollBar ) ) { + setYOffset( 0 ); + } + if ( xOffset() > 0 && testTableFlags( Tbl_autoHScrollBar ) && + !testTableFlags( Tbl_hScrollBar ) ) { + setXOffset( 0 ); + } + if ( !isVisible() ) { + inSbUpdate = FALSE; + return; + } + + if ( testTableFlags(Tbl_hScrollBar) && (sbDirty & horMask) != 0 ) { + if ( sbDirty & horGeometry ) + hScrollBar->setGeometry( 0,height() - HSBEXT, + viewWidth() + frameWidth()*2, + HSBEXT); + + if ( sbDirty & horSteps ) { + if ( cellW ) + hScrollBar->setSteps( QMIN(cellW,viewWidth()/2), viewWidth() ); + else + hScrollBar->setSteps( 16, viewWidth() ); + } + + if ( sbDirty & horRange ) + hScrollBar->setRange( 0, maxXOffset() ); + + if ( sbDirty & horValue ) + hScrollBar->setValue( xOffs ); + + // show scrollbar only when it has a sane geometry + if ( !hScrollBar->isVisible() ) + hScrollBar->show(); + } + + if ( testTableFlags(Tbl_vScrollBar) && (sbDirty & verMask) != 0 ) { + if ( sbDirty & verGeometry ) + vScrollBar->setGeometry( width() - VSBEXT, 0, + VSBEXT, + viewHeight() + frameWidth()*2 ); + + if ( sbDirty & verSteps ) { + if ( cellH ) + vScrollBar->setSteps( QMIN(cellH,viewHeight()/2), viewHeight() ); + else + vScrollBar->setSteps( 16, viewHeight() ); // fttb! ### + } + + if ( sbDirty & verRange ) + vScrollBar->setRange( 0, maxYOffset() ); + + if ( sbDirty & verValue ) + vScrollBar->setValue( yOffs ); + + // show scrollbar only when it has a sane geometry + if ( !vScrollBar->isVisible() ) + vScrollBar->show(); + } + if ( coveringCornerSquare && + ( (sbDirty & verGeometry ) || (sbDirty & horGeometry)) ) + cornerSquare->move( maxViewX() + frameWidth() + 1, + maxViewY() + frameWidth() + 1 ); + + sbDirty = 0; + inSbUpdate = FALSE; +} + + +void QtTableView::updateFrameSize() +{ + int rw = width() - ( testTableFlags(Tbl_vScrollBar) ? + VSBEXT : 0 ); + int rh = height() - ( testTableFlags(Tbl_hScrollBar) ? + HSBEXT : 0 ); + if ( rw < 0 ) + rw = 0; + if ( rh < 0 ) + rh = 0; + + if ( autoUpdate() ) { + int fh = frameRect().height(); + int fw = frameRect().width(); + setFrameRect( QRect(0,0,rw,rh) ); + + if ( rw != fw ) + update( QMIN(fw,rw) - frameWidth() - 2, 0, frameWidth()+4, rh ); + if ( rh != fh ) + update( 0, QMIN(fh,rh) - frameWidth() - 2, rw, frameWidth()+4 ); + } +} + + +/*! + Returns the maximum horizontal offset within the table of the + view's left edge in \e table coordinates. + + This is used mainly to set the horizontal scroll bar's range. + + \sa maxColOffset(), maxYOffset(), totalWidth() +*/ + +int QtTableView::maxXOffset() +{ + int tw = totalWidth(); + int maxOffs; + if ( testTableFlags(Tbl_scrollLastHCell) ) { + if ( nCols != 1) + maxOffs = tw - ( cellW ? cellW : cellWidth( nCols - 1 ) ); + else + maxOffs = tw - viewWidth(); + } else { + if ( testTableFlags(Tbl_snapToHGrid) ) { + if ( cellW ) { + maxOffs = tw - (viewWidth()/cellW)*cellW; + } else { + int goal = tw - viewWidth(); + int pos = tw; + int nextCol = nCols - 1; + int nextCellWidth = cellWidth( nextCol ); + while( nextCol > 0 && pos > goal + nextCellWidth ) { + pos -= nextCellWidth; + nextCellWidth = cellWidth( --nextCol ); + } + if ( goal + nextCellWidth == pos ) + maxOffs = goal; + else if ( goal < pos ) + maxOffs = pos; + else + maxOffs = 0; + } + } else { + maxOffs = tw - viewWidth(); + } + } + return maxOffs > 0 ? maxOffs : 0; +} + + +/*! + Returns the maximum vertical offset within the table of the + view's top edge in \e table coordinates. + + This is used mainly to set the vertical scroll bar's range. + + \sa maxRowOffset(), maxXOffset(), totalHeight() +*/ + +int QtTableView::maxYOffset() +{ + int th = totalHeight(); + int maxOffs; + if ( testTableFlags(Tbl_scrollLastVCell) ) { + if ( nRows != 1) + maxOffs = th - ( cellH ? cellH : cellHeight( nRows - 1 ) ); + else + maxOffs = th - viewHeight(); + } else { + if ( testTableFlags(Tbl_snapToVGrid) ) { + if ( cellH ) { + maxOffs = th - (viewHeight()/cellH)*cellH; + } else { + int goal = th - viewHeight(); + int pos = th; + int nextRow = nRows - 1; + int nextCellHeight = cellHeight( nextRow ); + while( nextRow > 0 && pos > goal + nextCellHeight ) { + pos -= nextCellHeight; + nextCellHeight = cellHeight( --nextRow ); + } + if ( goal + nextCellHeight == pos ) + maxOffs = goal; + else if ( goal < pos ) + maxOffs = pos; + else + maxOffs = 0; + } + } else { + maxOffs = th - viewHeight(); + } + } + return maxOffs > 0 ? maxOffs : 0; +} + + +/*! + Returns the index of the last column, which may be at the left edge + of the view. + + Depending on the \link setTableFlags() Tbl_scrollLastHCell\endlink flag, + this may or may not be the last column. + + \sa maxXOffset(), maxRowOffset() +*/ + +int QtTableView::maxColOffset() +{ + int mx = maxXOffset(); + if ( cellW ) + return mx/cellW; + else { + int xcd=0, col=0; + while ( col < nCols && mx > (xcd=cellWidth(col)) ) { + mx -= xcd; + col++; + } + return col; + } +} + + +/*! + Returns the index of the last row, which may be at the top edge of + the view. + + Depending on the \link setTableFlags() Tbl_scrollLastVCell\endlink flag, + this may or may not be the last row. + + \sa maxYOffset(), maxColOffset() +*/ + +int QtTableView::maxRowOffset() +{ + int my = maxYOffset(); + if ( cellH ) + return my/cellH; + else { + int ycd=0, row=0; + while ( row < nRows && my > (ycd=cellHeight(row)) ) { + my -= ycd; + row++; + } + return row; + } +} + + +void QtTableView::showOrHideScrollBars() +{ + if ( !autoUpdate() ) + return; + if ( vScrollBar ) { + if ( testTableFlags(Tbl_vScrollBar) ) { + if ( !vScrollBar->isVisible() ) + sbDirty = sbDirty | verMask; + } else { + if ( vScrollBar->isVisible() ) + vScrollBar->hide(); + } + } + if ( hScrollBar ) { + if ( testTableFlags(Tbl_hScrollBar) ) { + if ( !hScrollBar->isVisible() ) + sbDirty = sbDirty | horMask; + } else { + if ( hScrollBar->isVisible() ) + hScrollBar->hide(); + } + } + if ( cornerSquare ) { + if ( testTableFlags(Tbl_hScrollBar) && + testTableFlags(Tbl_vScrollBar) ) { + if ( !cornerSquare->isVisible() ) + cornerSquare->show(); + } else { + if ( cornerSquare->isVisible() ) + cornerSquare->hide(); + } + } +} + + +/*! + Updates the scroll bars and internal state. + + Call this function when the table view's total size is changed; + typically because the result of cellHeight() or cellWidth() have changed. + + This function does not repaint the widget. +*/ + +void QtTableView::updateTableSize() +{ + bool updateOn = autoUpdate(); + setAutoUpdate( FALSE ); + int xofs = xOffset(); + xOffs++; //so that setOffset will not return immediately + setOffset(xofs,yOffset(),FALSE); //to calculate internal state correctly + setAutoUpdate(updateOn); + + updateScrollBars( horSteps | horRange | + verSteps | verRange ); + showOrHideScrollBars(); +} + + +#endif +#endif diff --git a/win/Qt/tileedit.cpp b/win/Qt/tileedit.cpp index a594d3a..faee82f 100644 --- a/win/Qt/tileedit.cpp +++ b/win/Qt/tileedit.cpp @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)tileedit.cpp 3.3 1999/11/19 */ +/* SCCS Id: @(#)tileedit.cpp 3.4 1999/11/19 */ /* Copyright (c) Warwick Allison, 1999. */ /* NetHack may be freely redistributed. See license for details. */ /* @@ -180,7 +180,7 @@ void TrivialTileEditor::setColor( QRgb rgb ) { pen = rgb; for (penpixel = 0; - penpixelpos()); + if ( !img.rect().contains(p) ) + return; uchar& pixel = img.scanLine(p.y())[p.x()]; if ( e->button() == LeftButton ) { pixel = penpixel; @@ -226,7 +228,8 @@ void TrivialTileEditor::mousePressEvent(QMouseEvent* e) emit pick( img.color(pixel) ); } else if ( e->button() == MidButton ) { QPainter painter(this); - fill(painter,p,pixel); + if ( pixel != penpixel ) + fill(painter,p,pixel); } } @@ -253,6 +256,8 @@ void TrivialTileEditor::mouseReleaseEvent(QMouseEvent* e) void TrivialTileEditor::mouseMoveEvent(QMouseEvent* e) { QPoint p = imagePoint(e->pos()); + if ( !img.rect().contains(p) ) + return; uchar& pixel = img.scanLine(p.y())[p.x()]; pixel = penpixel; QPainter painter(this); diff --git a/win/Qt/tileedit.h b/win/Qt/tileedit.h index e3cbf9b..8d2d2cd 100644 --- a/win/Qt/tileedit.h +++ b/win/Qt/tileedit.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)tileedit.h 3.3 1999/11/19 */ +/* SCCS Id: @(#)tileedit.h 3.4 1999/11/19 */ /* Copyright (c) Warwick Allison, 1999. */ /* NetHack may be freely redistributed. See license for details. */ #ifndef QNHTILEEDIT_H diff --git a/win/X11/Install.X11 b/win/X11/Install.X11 index 201d3f1..7a0ffcd 100644 --- a/win/X11/Install.X11 +++ b/win/X11/Install.X11 @@ -40,6 +40,12 @@ replacement font), you will need to have the win/share files and change the VARDATND setting in the top Makefile to contain the tile files before you do your 'make all'. +If you get a linker error referring to `substitute_tiles' then most +likely you have overlooked the WINSRC, WINOBJ, WINLIB step above. +Alternatively, you are building with more than one non-tty interface +specified but haven't followed the direction in src/Makefile to remove +all but one instance of tile.o from the WINxxxOBJ values used for WINOBJ. + When using tiles, you have the option of defining USE_XPM in config.h. This causes NetHack to use the XPM file format for the "x11tiles" file rather than a custom format. Since the XPM format can be processed by diff --git a/win/X11/NetHack.ad b/win/X11/NetHack.ad index dc1ab17..df01745 100644 --- a/win/X11/NetHack.ad +++ b/win/X11/NetHack.ad @@ -59,10 +59,10 @@ NetHack*message*translations: : input() ! It is not guaranteed that the window manager will honor the icon selection. !NetHack*icon: nh56 ! -! If True, a popup for single character prompts such as y/n questions is _not_ -! used. -!NetHack*slow: True -! +! If True, the default, a popup for single character prompts such as y/n +! questions is _not_ used. +NetHack*slow: True + ! The number of lines the message window will show without scrolling. !NetHack*message_lines: 12 ! diff --git a/win/X11/Window.c b/win/X11/Window.c index 92e7e7d..c21c8f2 100644 --- a/win/X11/Window.c +++ b/win/X11/Window.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)Window.c 3.3 93/02/02 */ +/* SCCS Id: @(#)Window.c 3.4 1993/02/02 */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/X11/nh32icon b/win/X11/nh32icon index aeded5a..47fd0b9 100644 --- a/win/X11/nh32icon +++ b/win/X11/nh32icon @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)nh32icon 3.3 95/07/19 */ +/* SCCS Id: @(#)nh32icon 3.4 2002/02/12 */ /* Copyright (C) 1993,1995 by Robert Patrick Rankin */ /* NetHack may be freely redistributed. See license for details. */ @@ -10,9 +10,9 @@ static unsigned char nh32icon_bits[] = { 0xff, 0x7f, 0xfe, 0xff, 0x01, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x40, 0x82, 0x21, 0x25, 0xc0, 0x83, 0x61, 0x25, 0x80, 0x81, 0xe1, 0x3d, 0x80, 0x81, 0xa1, 0x25, 0x80, 0x81, 0x21, 0x25, 0x80, 0x81, 0x01, 0x00, 0xe0, 0x87, - 0x71, 0x38, 0x90, 0x89, 0x81, 0x40, 0x80, 0x81, 0x61, 0x30, 0x80, 0x81, - 0x81, 0x40, 0x80, 0x81, 0x71, 0x3a, 0x84, 0x81, 0x03, 0x00, 0x8a, 0xc1, - 0x02, 0x00, 0x84, 0x41, 0x32, 0x73, 0x80, 0x41, 0xf3, 0x7f, 0x80, 0xc1, + 0x71, 0x48, 0x90, 0x89, 0x81, 0x48, 0x80, 0x81, 0x61, 0x78, 0x80, 0x81, + 0x81, 0x40, 0x80, 0x81, 0x71, 0x42, 0x84, 0x81, 0x03, 0x00, 0x8a, 0xc1, + 0x02, 0x00, 0x84, 0x41, 0x32, 0x67, 0x80, 0x41, 0xf3, 0x7f, 0x80, 0xc1, 0xf1, 0x7f, 0x84, 0x81, 0x71, 0x77, 0x8a, 0x81, 0xb1, 0x68, 0x84, 0x81, 0x71, 0x77, 0x80, 0x81, 0x71, 0x77, 0x80, 0x81, 0xb1, 0x68, 0x84, 0x81, 0x71, 0x77, 0x8a, 0x81, 0xf1, 0x7f, 0x84, 0x81, 0xe1, 0x3f, 0x80, 0x81, diff --git a/win/X11/nh56icon b/win/X11/nh56icon index 2e4605c..b58a605 100644 --- a/win/X11/nh56icon +++ b/win/X11/nh56icon @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)nh56icon 3.3 95/07/19 */ +/* SCCS Id: @(#)nh56icon 3.4 2002/02/12 */ /* Copyright (c) 1993,1995 by M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ @@ -25,12 +25,12 @@ static unsigned char nh56icon_bits[] = { 0x00, 0xc0, 0x03, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x38, 0x00, 0x00, - 0xc0, 0x43, 0x10, 0x21, 0x38, 0x70, 0x80, 0xc3, 0xc3, 0x10, 0x21, 0x38, - 0x88, 0x40, 0xc4, 0xc3, 0x10, 0x21, 0x38, 0x80, 0x00, 0xc4, 0x43, 0x11, - 0x21, 0x38, 0x80, 0x00, 0xc4, 0x43, 0x12, 0x3f, 0x38, 0x70, 0x80, 0xc3, - 0x43, 0x12, 0x21, 0x38, 0x80, 0x00, 0xc4, 0x43, 0x14, 0x21, 0x38, 0x80, - 0x00, 0xc4, 0x43, 0x18, 0x21, 0x38, 0x80, 0x00, 0xc4, 0x43, 0x18, 0x21, - 0x38, 0x88, 0x4c, 0xc4, 0x43, 0x10, 0x21, 0x38, 0x70, 0x8c, 0xc3, 0x03, + 0xc0, 0x43, 0x10, 0x21, 0x38, 0x70, 0x20, 0xc2, 0xc3, 0x10, 0x21, 0x38, + 0x88, 0x20, 0xc2, 0xc3, 0x10, 0x21, 0x38, 0x80, 0x20, 0xc2, 0x43, 0x11, + 0x21, 0x38, 0x80, 0x20, 0xc2, 0x43, 0x12, 0x3f, 0x38, 0x70, 0xe0, 0xc3, + 0x43, 0x12, 0x21, 0x38, 0x80, 0x00, 0xc2, 0x43, 0x14, 0x21, 0x38, 0x80, + 0x00, 0xc2, 0x43, 0x18, 0x21, 0x38, 0x80, 0x00, 0xc2, 0x43, 0x18, 0x21, + 0x38, 0x88, 0x0c, 0xc2, 0x43, 0x10, 0x21, 0x38, 0x70, 0x0c, 0xc2, 0x03, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc0, 0xfb, 0xff, 0xff, 0x39, 0xff, 0xff, 0xdf, 0x0b, 0x00, 0x80, 0x7c, 0x02, 0x00, 0xd0, 0x0b, 0x00, 0x80, 0xee, 0x02, 0x00, 0xd0, 0xfb, 0xff, diff --git a/win/X11/nh72icon b/win/X11/nh72icon index e78959d..75dfe84 100644 --- a/win/X11/nh72icon +++ b/win/X11/nh72icon @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)nh72icon 3.3 93/01/21 */ +/* SCCS Id: @(#)nh72icon 3.4 1993/01/21 */ /* Copyright (c) 1993 by M. Stephenson */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/X11/tile2x11.c b/win/X11/tile2x11.c index 746001d..a254213 100644 --- a/win/X11/tile2x11.c +++ b/win/X11/tile2x11.c @@ -15,7 +15,7 @@ x11_header header; -unsigned char tile_bytes[TILE_X*TILE_Y*MAX_GLYPH]; +unsigned char tile_bytes[TILE_X*TILE_Y*(MAX_GLYPH+TILES_PER_ROW)]; unsigned char *curr_tb = tile_bytes; unsigned char x11_colormap[MAXCOLORMAPSIZE][3]; @@ -44,8 +44,9 @@ pix_to_colormap(pix) /* Convert the tiles in the file to our format of bytes. */ static unsigned long -convert_tiles(tb_ptr) +convert_tiles(tb_ptr, total) unsigned char **tb_ptr; /* pointer to a tile byte pointer */ + unsigned long total; /* total tiles so far */ { unsigned char *tb = *tb_ptr; unsigned long count = 0; @@ -54,12 +55,20 @@ convert_tiles(tb_ptr) while (read_text_tile(tile)) { count++; - for (y = 0; y < TILE_Y; y++) + total++; + for (y = 0; y < TILE_Y; y++) { for (x = 0; x < TILE_X; x++) - *tb++ = pix_to_colormap(tile[y][x]); + tb[x] = pix_to_colormap(tile[y][x]); + tb += TILE_X * header.per_row; + } + + /* repoint at the upper-left corner of the next tile */ + *tb_ptr += TILE_X; + if (header.per_row == 1 || (total % header.per_row) == 0) + *tb_ptr += TILE_X * (TILE_Y - 1) * header.per_row; + tb = *tb_ptr; } - *tb_ptr = tb; /* update return val */ return count; } @@ -108,9 +117,9 @@ process_file(fname) if (!fopen_text_file(fname, RDTMODE)) { Fprintf(stderr, "can't open file \"%s\"\n", fname); exit(1); - } + } merge_text_colormap(); - count = convert_tiles(&curr_tb); + count = convert_tiles(&curr_tb, header.ntiles); Fprintf(stderr, "%s: %lu tiles\n", fname, count); header.ntiles += count; fclose_text_file(); @@ -122,7 +131,7 @@ static int xpm_write(fp) FILE *fp; { - int i,j,n; + int i, j, n; if (header.ncolors > 64) { Fprintf(stderr, "Sorry, only configured for up to 64 colors\n"); @@ -130,34 +139,32 @@ FILE *fp; /* All you need to do is add more char per color - below */ } - fprintf(fp, "/* XPM */\n"); - fprintf(fp, "static char* nhtiles[] = {\n"); - fprintf(fp, "\"%lu %lu %lu %d\",\n", - header.tile_width, - header.tile_height*header.ntiles, + Fprintf(fp, "/* XPM */\n"); + Fprintf(fp, "static char* nhtiles[] = {\n"); + Fprintf(fp, "\"%lu %lu %lu %d\",\n", + header.tile_width*header.per_row, + (header.tile_height*header.ntiles)/header.per_row, header.ncolors, 1 /* char per color */); for (i = 0; i < header.ncolors; i++) - fprintf(fp, "\"%c c #%02x%02x%02x\",\n", + Fprintf(fp, "\"%c c #%02x%02x%02x\",\n", i+'0', /* just one char per color */ x11_colormap[i][0], x11_colormap[i][1], x11_colormap[i][2]); - n=0; - for (i = 0; i < header.tile_height*header.ntiles; i++) { - fprintf(fp, "\""); - for (j = 0; j < header.tile_width; j++) { + n = 0; + for (i = 0; i < (header.tile_height*header.ntiles)/header.per_row; i++) { + Fprintf(fp, "\""); + for (j = 0; j < header.tile_width*header.per_row; j++) { /* just one char per color */ fputc(tile_bytes[n++]+'0', fp); } - if (j==header.tile_width-1) - fprintf(fp, "\"\n"); - else - fprintf(fp, "\",\n"); + + Fprintf(fp, "\",\n"); } - return fprintf(fp, "};\n")>=0; + return fprintf(fp, "};\n") >= 0; } #endif /* USE_XPM */ @@ -169,11 +176,12 @@ main(argc, argv) FILE *fp; int i; - header.version = 1; + header.version = 2; /* version 1 had no per_row field */ header.ncolors = 0; header.tile_width = TILE_X; header.tile_height = TILE_Y; header.ntiles = 0; /* updated as we read in files */ + header.per_row = TILES_PER_ROW; if (argc == 1) { Fprintf(stderr, "usage: %s txt_file1 [txt_file2 ...]\n", argv[0]); @@ -184,12 +192,20 @@ main(argc, argv) if (!fp) { Fprintf(stderr, "can't open output file\n"); exit(1); - } + } + + /* don't leave garbage at end of partial row */ + (void) memset((genericptr_t)tile_bytes, 0, sizeof(tile_bytes)); for (i = 1; i < argc; i++) process_file(argv[i]); Fprintf(stderr, "Total tiles: %ld\n", header.ntiles); + /* round size up to the end of the row */ + if ((header.ntiles % header.per_row) != 0) { + header.ntiles += header.per_row - (header.ntiles % header.per_row); + } + #ifdef USE_XPM if (xpm_write(fp) == 0) { Fprintf(stderr, "can't write XPM file\n"); @@ -199,7 +215,7 @@ main(argc, argv) if (fwrite((char *)&header, sizeof(x11_header), 1, fp) == 0) { Fprintf(stderr, "can't open output header\n"); exit(1); - } + } if (fwrite((char *)x11_colormap, 1, header.ncolors*3, fp) == 0) { Fprintf(stderr, "can't write output colormap\n"); diff --git a/win/X11/winX.c b/win/X11/winX.c index 4a68982..2e48138 100644 --- a/win/X11/winX.c +++ b/win/X11/winX.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)winX.c 3.3 1999/12/21 */ +/* SCCS Id: @(#)winX.c 3.4 1999/12/21 */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -92,6 +92,7 @@ int updated_inventory; /* Interface definition, for windows.c */ struct window_procs X11_procs = { "X11", + WC_COLOR|WC_HILITE_PET, X11_init_nhwindows, X11_player_selection, X11_askname, @@ -144,6 +145,7 @@ struct window_procs X11_procs = { #else genl_outrip, #endif + genl_preference_update, }; /* @@ -265,7 +267,7 @@ XColor *color; /* the X color structure; changed only if successful */ long cdiff = 16777216; /* 2^24; hopefully our map is smaller */ XColor tmp; static XColor *table = 0; - register i, j; + register int i, j; register long tdiff; /* if the screen doesn't have a big colormap, don't waste our time */ @@ -450,6 +452,38 @@ Cardinal *num_args; } } +/* [ALI] Utility function to ask Xaw for font height, since the previous + * assumption of ascent + descent is not always valid. + */ +Dimension +nhFontHeight(w) +Widget w; +#ifdef _XawTextSink_h +{ + Widget sink; + XawTextPosition pos = 0; + int resWidth, resHeight; + Arg args[1]; + + XtSetArg(args[0], XtNtextSink, &sink); + XtGetValues(w, args, 1); + + XawTextSinkFindPosition(sink, pos, 0, 0, 0, &pos, &resWidth, &resHeight); + return resHeight; +} +#else +{ + XFontStruct *fs; + Arg args[1]; + + XtSetArg(args[0], XtNfont, &fs); + XtGetValues(w, args, 1); + + /* Assume font height is ascent + descent. */ + return = fs->ascent + fs->descent; +} +#endif + /* Global Functions ======================================================== */ void X11_raw_print(str) @@ -870,7 +904,7 @@ static XtActionsRec actions[] = { static XtResource resources[] = { { "slow", "Slow", XtRBoolean, sizeof(Boolean), - XtOffset(AppResources *,slow), XtRString, "False" }, + XtOffset(AppResources *,slow), XtRString, "True" }, { "autofocus", "AutoFocus", XtRBoolean, sizeof(Boolean), XtOffset(AppResources *,autofocus), XtRString, "False" }, { "message_line", "Message_line", XtRBoolean, sizeof(Boolean), @@ -1178,12 +1212,20 @@ done_button(w, client_data, call_data) XtPointer client_data; XtPointer call_data; { + int len; char *s; Widget dialog = (Widget) client_data; s = (char *) GetDialogResponse(dialog); - Strcpy(getline_input, s); + len = strlen(s); + + /* Truncate input if necessary */ + if (len >= BUFSZ) len = BUFSZ - 1; + + (void) strncpy(getline_input, s, len); + getline_input[len] = '\0'; XtFree(s); + nh_XtPopdown(XtParent(dialog)); exit_x_event = TRUE; } @@ -1389,12 +1431,10 @@ X11_display_file(str, complain) XtGetValues(dispfile, args, num_args); /* - * Font height is ascent + descent. - * * The data files are currently set up assuming an 80 char wide window * and a fixed width font. Soo.. */ - new_height = num_lines * (fs->ascent + fs->descent) + + new_height = num_lines * nhFontHeight(dispfile) + top_margin + bottom_margin; new_width = 80 * fs->max_bounds.width + left_margin + right_margin; diff --git a/win/X11/winmap.c b/win/X11/winmap.c index 73ea1e5..dda4685 100644 --- a/win/X11/winmap.c +++ b/win/X11/winmap.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)winmap.c 3.3 96/04/05 */ +/* SCCS Id: @(#)winmap.c 3.4 1996/04/05 */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -100,75 +100,16 @@ X11_print_glyph(window, x, y, glyph) } else { uchar ch; - register int offset; register unsigned char *ch_ptr; + int color,och; + unsigned special; #ifdef TEXTCOLOR - int color; register unsigned char *co_ptr; - -#define zap_color(n) color = zapcolors[n] -#define cmap_color(n) color = defsyms[n].color -#define obj_color(n) color = objects[n].oc_color -#define mon_color(n) color = mons[n].mcolor -#define invis_color(n) color = NO_COLOR -#define pet_color(n) color = mons[n].mcolor -#define warn_color(n) color = iflags.use_color ? def_warnsyms[n].color : NO_COLOR -# else /* no text color */ - -#define zap_color(n) -#define cmap_color(n) -#define obj_color(n) -#define mon_color(n) -#define invis_color(n) -#define pet_color(n) -#define warn_color(n) - #endif - - /* - * Map the glyph back to a character. - * - * Warning: For speed, this makes an assumption on the order of - * offsets. The order is set in display.h. - */ - if ((offset = (glyph - GLYPH_WARNING_OFF)) >= 0) { /* a warning flash */ - ch = warnsyms[offset]; - warn_color(offset); - } else if ((offset = (glyph - GLYPH_SWALLOW_OFF)) >= 0) { /* swallow */ - /* see swallow_to_glyph() in display.c */ - ch = (uchar) showsyms[S_sw_tl + (offset & 0x7)]; - mon_color(offset >> 3); - } else if ((offset = (glyph - GLYPH_ZAP_OFF)) >= 0) { /* zap beam */ - /* see zapdir_to_glyph() in display.c */ - ch = showsyms[S_vbeam + (offset & 0x3)]; - zap_color((offset >> 2)); - } else if ((offset = (glyph - GLYPH_CMAP_OFF)) >= 0) { /* cmap */ - ch = showsyms[offset]; - cmap_color(offset); - } else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) { /* object */ - ch = oc_syms[(int) objects[offset].oc_class]; - obj_color(offset); - } else if ((offset = (glyph - GLYPH_RIDDEN_OFF)) >= 0) {/* ridden mon */ - ch = monsyms[(int) mons[offset].mlet]; - mon_color(offset); - } else if ((offset = (glyph - GLYPH_BODY_OFF)) >= 0) { /* a corpse */ - ch = oc_syms[(int) objects[CORPSE].oc_class]; - mon_color(offset); - } else if ((offset = (glyph - GLYPH_DETECT_OFF)) >= 0) { - /* monster detection; should really be inverse */ - ch = monsyms[(int) mons[offset].mlet]; - mon_color(offset); - } else if ((offset = (glyph - GLYPH_INVIS_OFF)) >= 0) { /* invisible */ - ch = DEF_INVISIBLE; - invis_color(offset); - } else if ((offset = (glyph - GLYPH_PET_OFF)) >= 0) { /* a pet */ - ch = monsyms[(int) mons[offset].mlet]; - pet_color(offset); - } else { /* a monster */ - ch = monsyms[(int) mons[glyph].mlet]; - mon_color(glyph); - } - + /* map glyph to character and color */ + mapglyph(glyph, &och, &color, &special, x, y); + ch = (uchar)och; + /* Only update if we need to. */ ch_ptr = &map_info->mtype.text_map->text[y][x]; @@ -186,12 +127,6 @@ X11_print_glyph(window, x, y, glyph) update_bbox = TRUE; } else update_bbox = FALSE; - -#undef zap_color -#undef cmap_color -#undef obj_color -#undef mon_color -#undef pet_color } if (update_bbox) { /* update row bbox */ @@ -271,11 +206,11 @@ post_process_tiles() Display *dpy = XtDisplay(toplevel); unsigned int width, height; - height = tile_height * tile_count; - width = tile_width; - if (tile_image == 0) return; /* no tiles */ + height = tile_image->height; + width = tile_image->width; + tile_pixmap = XCreatePixmap(dpy, XtWindow(toplevel), width, height, @@ -304,7 +239,10 @@ static boolean init_tiles(wp) struct xwindow *wp; { -#ifndef USE_XPM +#ifdef USE_XPM + XpmAttributes attributes; + int errorcode; +#else FILE *fp = (FILE *)0; x11_header header; unsigned char *cp, *colormap = (unsigned char *)0; @@ -313,13 +251,14 @@ init_tiles(wp) XColor *colors = (XColor *)0; int i, x, y; int bitmap_pad; - unsigned int image_height, image_width; int ddepth; #endif + char buf[BUFSZ]; Display *dpy = XtDisplay(toplevel); Screen *screen = DefaultScreenOfDisplay(dpy); struct map_info_t *map_info = (struct map_info_t *)0; struct tile_map_info_t *tile_info = (struct tile_map_info_t *)0; + unsigned int image_height = 0, image_width = 0; boolean result = TRUE; XGCValues values; XtGCMask mask; @@ -334,54 +273,63 @@ init_tiles(wp) sizeof(struct tile_map_info_t)); #ifdef USE_XPM - { - char buf[BUFSZ]; - XpmAttributes attributes; - int errorcode; + attributes.valuemask = XpmCloseness; + attributes.closeness = 25000; - attributes.valuemask = XpmCloseness; - attributes.closeness = 25000; + errorcode = XpmReadFileToImage(dpy, appResources.tile_file, + &tile_image, 0, &attributes); - errorcode=XpmReadFileToImage(dpy,appResources.tile_file,&tile_image,0,&attributes); + if (errorcode == XpmColorFailed) { + Sprintf(buf, "Insufficient colors available to load %s.", + appResources.tile_file); + X11_raw_print(buf); + X11_raw_print("Try closing other colorful applications and restart."); + X11_raw_print("Attempting to load with inferior colors."); + attributes.closeness = 50000; + errorcode = XpmReadFileToImage(dpy, appResources.tile_file, + &tile_image, 0, &attributes); + } + if (errorcode != XpmSuccess) { if (errorcode == XpmColorFailed) { - Sprintf(buf, "Insufficient colors available to load %s.",appResources.tile_file); + Sprintf(buf, "Insufficient colors available to load %s.", + appResources.tile_file); + X11_raw_print(buf); + } else { + Sprintf(buf, "Failed to load %s: %s", appResources.tile_file, + XpmGetErrorString(errorcode)); X11_raw_print(buf); - X11_raw_print("Try closing other colorful applications and restart."); - X11_raw_print("Attempting to load with inferior colors."); - attributes.closeness = 50000; - errorcode=XpmReadFileToImage(dpy,appResources.tile_file,&tile_image,0,&attributes); } + result = FALSE; + X11_raw_print("Switching to text-based mode."); + goto tiledone; + } - if (errorcode!=XpmSuccess) { - if (errorcode == XpmColorFailed) { - Sprintf(buf, "Insufficient colors available to load %s.",appResources.tile_file); - X11_raw_print(buf); - } else { - Sprintf(buf, "Failed to load %s: %s",appResources.tile_file, - XpmGetErrorString(errorcode)); - X11_raw_print(buf); - } - result = FALSE; - X11_raw_print("Switching to text-based mode."); - goto tiledone; - } + /* assume a fixed number of tiles per row */ + if (tile_image->width % TILES_PER_ROW != 0) { + Sprintf(buf, + "%s is not a multiple of %d (number of tiles/row) pixels wide", + appResources.tile_file, TILES_PER_ROW); + X11_raw_print(buf); + XDestroyImage(tile_image); + tile_image = 0; + result = FALSE; + goto tiledone; + } - if (tile_image->height%total_tiles_used != 0) { - Sprintf(buf, - "%s is not a multiple of %d (the number of tiles) pixels high", - appResources.tile_file, total_tiles_used); - X11_raw_print(buf); - XDestroyImage(tile_image); - tile_image = 0; - result = FALSE; - goto tiledone; - } + /* infer tile dimensions from image size, assume square tiles */ + image_width = tile_image->width; + image_height = tile_image->height; + tile_width = image_width / TILES_PER_ROW; + tile_height = tile_width; + tile_count = (image_width * image_height) / (tile_width * tile_height); - /* infer tile dimensions from image size */ - tile_count=total_tiles_used; - tile_width=tile_image->width; - tile_height=tile_image->height/tile_count; + if (tile_count < total_tiles_used) { + Sprintf(buf, "%s incomplete, expecting %d tiles, found %d", + appResources.tile_file, total_tiles_used, tile_count); + X11_raw_print(buf); + result = FALSE; + goto tiledone; } #else /* any less than 16 colours makes tiles useless */ @@ -405,12 +353,21 @@ init_tiles(wp) goto tiledone; } + if (header.version != 2) { + Sprintf(buf, "Wrong tile file version, expected 2, got %lu", + header.version); + X11_raw_print(buf); + result = FALSE; + goto tiledone; + } + # ifdef VERBOSE - fprintf(stderr, "X11 tile file:\n version %ld\n ncolors %ld\n tile width %ld\n tile height %ld\n ntiles %ld\n", + fprintf(stderr, "X11 tile file:\n version %ld\n ncolors %ld\n tile width %ld\n tile height %ld\n per row %ld\n ntiles %ld\n", header.version, header.ncolors, header.tile_width, header.tile_height, + header.per_row, header.ntiles); # endif @@ -439,9 +396,8 @@ init_tiles(wp) if (!XAllocColor(dpy, DefaultColormapOfScreen(screen), &colors[i]) && !nhApproxColor(screen, DefaultColormapOfScreen(screen), (char *)0, &colors[i])) { - char buf[BUFSZ]; Sprintf(buf, "%dth out of %ld color allocation failed", - i, header.ncolors); + i, header.ncolors); X11_raw_print(buf); result = FALSE; goto tiledone; @@ -453,8 +409,11 @@ init_tiles(wp) * This alloc() and the one below require 32-bit ints, since tile_bytes * is currently ~200k and alloc() takes an int */ - tile_bytes = (unsigned char *) alloc((unsigned)header.ntiles*size); tile_count = header.ntiles; + if ((tile_count % header.per_row) != 0) { + tile_count += header.per_row - (tile_count % header.per_row); + } + tile_bytes = (unsigned char *) alloc((unsigned)tile_count*size); if (fread((char *) tile_bytes, size, tile_count, fp) != tile_count) { X11_raw_print("read of tile bytes failed"); result = FALSE; @@ -462,7 +421,6 @@ init_tiles(wp) } if (header.ntiles < total_tiles_used) { - char buf[BUFSZ]; Sprintf(buf, "tile file incomplete, expecting %d tiles, found %lu", total_tiles_used, header.ntiles); X11_raw_print(buf); @@ -479,8 +437,8 @@ init_tiles(wp) tile_height = header.tile_height; } - image_height = tile_height * tile_count; - image_width = tile_width; + image_height = tile_height * tile_count / header.per_row; + image_width = tile_width * header.per_row; /* calculate bitmap_pad */ if (ddepth > 16) @@ -509,19 +467,19 @@ init_tiles(wp) if (appResources.double_tile_size) { unsigned long *expanded_row = - (unsigned long *)alloc(sizeof(unsigned long)*(unsigned)tile_width); + (unsigned long *)alloc(sizeof(unsigned long)*(unsigned)image_width); tb = tile_bytes; for (y = 0; y < image_height; y++) { - for (x = 0; x < header.tile_width; x++) + for (x = 0; x < image_width/2; x++) expanded_row[2*x] = expanded_row[(2*x)+1] = colors[*tb++].pixel; - for (x = 0; x < tile_width; x++) + for (x = 0; x < image_width; x++) XPutPixel(tile_image, x, y, expanded_row[x]); y++; /* duplicate row */ - for (x = 0; x < tile_width; x++) + for (x = 0; x < image_width; x++) XPutPixel(tile_image, x, y, expanded_row[x]); } free((genericptr_t)expanded_row); @@ -554,12 +512,8 @@ init_tiles(wp) */ mask = GCFunction | GCForeground | GCGraphicsExposures; values.graphics_exposures = False; -#if 1 values.foreground = WhitePixelOfScreen(screen) ^ XGetPixel(tile_image, 0, tile_height*glyph2tile[cmap_to_glyph(S_corr)]); -#else - values.foreground = ~((unsigned long) 0); -#endif values.function = GXxor; tile_info->white_gc = XtGetGC(wp->w, mask, &values); @@ -567,7 +521,7 @@ init_tiles(wp) values.function = GXCopy; values.graphics_exposures = False; tile_info->black_gc = XtGetGC(wp->w, mask, &values); -#endif +#endif /* USE_WHITE */ tiledone: #ifndef USE_XPM @@ -582,6 +536,8 @@ init_tiles(wp) map_info->square_width = tile_width; map_info->square_ascent = 0; map_info->square_lbearing = 0; + tile_info->image_width = image_width; + tile_info->image_height = image_height; } else { if (tile_info) free((genericptr_t)tile_info); tile_info = 0; @@ -623,7 +579,9 @@ check_cursor_visibility(wp) XtSetArg(arg[1], XtNtopOfThumb, &top); XtGetValues(horiz_sb, arg, TWO); - cursor_middle = (((float) wp->cursx) + 0.5) / (float) COLNO; + /* [ALI] Don't assume map widget is the same size as actual map */ + cursor_middle = (wp->cursx + 0.5) * wp->map_information->square_width / + wp->pixel_width; do_call = True; #ifdef VERBOSE @@ -669,7 +627,8 @@ check_cursor_visibility(wp) XtSetArg(arg[1], XtNtopOfThumb, &top); XtGetValues(vert_sb, arg, TWO); - cursor_middle = (((float) wp->cursy) + 0.5) / (float) ROWNO; + cursor_middle = (wp->cursy + 0.5) * wp->map_information->square_height / + wp->pixel_height; do_call = True; #ifdef VERBOSE @@ -743,11 +702,30 @@ map_check_size_change(wp) /* Only do cursor check if new size is smaller. */ if (new_width < map_info->viewport_width || new_height < map_info->viewport_height) { + /* [ALI] If the viewport was larger than the map (and so the map + * widget was contrained to be larger than the actual map) then we + * may be able to shrink the map widget as the viewport shrinks. + */ + wp->pixel_width = map_info->square_width * COLNO; + if (wp->pixel_width < new_width) + wp->pixel_width = new_width; + wp->pixel_height = map_info->square_height * ROWNO; + if (wp->pixel_height < new_height) + wp->pixel_height = new_height; + XtSetArg(arg[0], XtNwidth, wp->pixel_width); + XtSetArg(arg[1], XtNheight, wp->pixel_height); + XtSetValues(wp->w, arg, TWO); + check_cursor_visibility(wp); } map_info->viewport_width = new_width; map_info->viewport_height = new_height; + + /* [ALI] These may have changed if the user has re-sized the viewport */ + XtSetArg(arg[0], XtNwidth, &wp->pixel_width); + XtSetArg(arg[1], XtNheight, &wp->pixel_height); + XtGetValues(wp->w, arg, TWO); } /* @@ -948,7 +926,7 @@ get_char_info(wp) #ifdef VERBOSE printf("Font information:\n"); - printf("fid = %d, direction = %d\n", fs->fid, fs->direction); + printf("fid = %ld, direction = %d\n", fs->fid, fs->direction); printf("first = %d, last = %d\n", fs->min_char_or_byte2, fs->max_char_or_byte2); printf("all chars exist? %s\n", fs->all_chars_exist?"yes":"no"); @@ -960,7 +938,7 @@ get_char_info(wp) fs->max_bounds.lbearing, fs->max_bounds.rbearing, fs->max_bounds.width, fs->max_bounds.ascent, fs->max_bounds.descent, fs->max_bounds.attributes); - printf("per_char = 0x%x\n", fs->per_char); + printf("per_char = 0x%lx\n", (unsigned long) fs->per_char); printf("Text: (max) width = %d, height = %d\n", map_info->square_width, map_info->square_height); #endif @@ -1217,28 +1195,26 @@ map_update(wp, start_row, stop_row, start_col, stop_col, inverted) if (map_info->is_tile) { struct tile_map_info_t *tile_map = map_info->mtype.tile_map; int cur_col; - Display* dpy=XtDisplay(wp->w); - Screen* screen=DefaultScreenOfDisplay(dpy); + Display* dpy = XtDisplay(wp->w); + Screen* screen = DefaultScreenOfDisplay(dpy); for (row = start_row; row <= stop_row; row++) { for (cur_col = start_col; cur_col <= stop_col; cur_col++) { int glyph = tile_map->glyphs[row][cur_col]; int tile = glyph2tile[glyph]; + int src_x, src_y; int dest_x = cur_col * map_info->square_width; int dest_y = row * map_info->square_height; + src_x = (tile % TILES_PER_ROW) * tile_width; + src_y = (tile / TILES_PER_ROW) * tile_height; XCopyArea(dpy, tile_pixmap, XtWindow(wp->w), - tile_map->black_gc, /* no grapics_expose */ - 0, - tile * map_info->square_height, - tile_width, tile_height, - dest_x,dest_y); + tile_map->black_gc, /* no grapics_expose */ + src_x, src_y, + tile_width, tile_height, + dest_x, dest_y); - if (glyph_is_pet(glyph) -#ifdef TEXTCOLOR - && iflags.hilite_pet -#endif - ) { + if (glyph_is_pet(glyph) && iflags.hilite_pet) { /* draw pet annotation (a heart) */ XSetForeground(dpy, tile_map->black_gc, pet_annotation.foreground); XSetClipOrigin(dpy, tile_map->black_gc, dest_x, dest_y); diff --git a/win/X11/winmenu.c b/win/X11/winmenu.c index 2912fb1..d6f80e9 100644 --- a/win/X11/winmenu.c +++ b/win/X11/winmenu.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)winmenu.c 3.3 96/08/15 */ +/* SCCS Id: @(#)winmenu.c 3.4 1996/08/15 */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/X11/winmesg.c b/win/X11/winmesg.c index da5e359..63dac96 100644 --- a/win/X11/winmesg.c +++ b/win/X11/winmesg.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)winmesg.c 3.3 96/04/05 */ +/* SCCS Id: @(#)winmesg.c 3.4 1996/04/05 */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/X11/winmisc.c b/win/X11/winmisc.c index b8bfebb..d6720fe 100644 --- a/win/X11/winmisc.c +++ b/win/X11/winmisc.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)winmisc.c 3.3 2000/05/21 */ +/* SCCS Id: @(#)winmisc.c 3.4 2000/05/21 */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -265,15 +265,21 @@ X11_player_selection() i, availcount, availindex; Widget popup, player_form; const char **choices; - const char *namep; - char qbuf[QBUFSZ]; + char qbuf[QBUFSZ], plbuf[QBUFSZ]; + + /* avoid unnecessary prompts further down */ + rigid_role_checks(); + + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); while (flags.initrole < 0) { - if (flags.initrole == ROLE_RANDOM) { + if (flags.initrole == ROLE_RANDOM || flags.randomall) { flags.initrole = pick_role(flags.initrace, - flags.initgend, flags.initalign); + flags.initgend, flags.initalign, PICK_RANDOM); break; } + /* select a role */ for (num_roles = 0; roles[num_roles].name.m; ++num_roles) continue; choices = (const char **)alloc(sizeof(char *) * num_roles); @@ -295,7 +301,8 @@ X11_player_selection() else if (flags.initrace >= 0) flags.initrace = -1; else panic("no available ROLE+race+gender+alignment combinations"); } - popup = make_menu("player_selection", "Choose a Role", + Sprintf(qbuf, "Choose your %s Role", s_suffix(plbuf)); + popup = make_menu("player_selection", qbuf, player_select_translations, "quit", ps_quit, "random", ps_random, @@ -325,10 +332,13 @@ X11_player_selection() } } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); + while (!validrace(flags.initrole, flags.initrace)) { - if (flags.initrace == ROLE_RANDOM) { + if (flags.initrace == ROLE_RANDOM || flags.randomall) { flags.initrace = pick_race(flags.initrole, - flags.initgend, flags.initalign); + flags.initgend, flags.initalign, PICK_RANDOM); break; } /* select a race */ @@ -355,11 +365,7 @@ X11_player_selection() flags.initrace = availindex; free((genericptr_t)choices), choices = 0; } else { - namep = roles[flags.initrole].name.m; - if (flags.initgend >= 0 && flags.female && - roles[flags.initrole].name.f) - namep = roles[flags.initrole].name.f; - Sprintf(qbuf, "Pick your %s race", s_suffix(namep)); + Sprintf(qbuf, "Pick your %s race", s_suffix(plbuf)); popup = make_menu("race_selection", qbuf, race_select_translations, "quit", ps_quit, @@ -392,10 +398,13 @@ X11_player_selection() } /* more than one race choice available */ } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); + while (!validgend(flags.initrole, flags.initrace, flags.initgend)) { - if (flags.initgend == ROLE_RANDOM) { + if (flags.initgend == ROLE_RANDOM || flags.randomall) { flags.initgend = pick_gend(flags.initrole, flags.initrace, - flags.initalign); + flags.initalign, PICK_RANDOM); break; } /* select a gender */ @@ -421,12 +430,7 @@ X11_player_selection() flags.initgend = availindex; free((genericptr_t)choices), choices = 0; } else { - namep = roles[flags.initrole].name.m; - if (flags.initgend >= 0 && flags.female && - roles[flags.initrole].name.f) - namep = roles[flags.initrole].name.f; - Sprintf(qbuf, "Your %s %s gender?", - races[flags.initrace].adj, s_suffix(namep)); + Sprintf(qbuf, "Your %s gender?", s_suffix(plbuf)); popup = make_menu("gender_selection", qbuf, gend_select_translations, "quit", ps_quit, @@ -459,10 +463,13 @@ X11_player_selection() } /* more than one gender choice available */ } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); + while (!validalign(flags.initrole, flags.initrace, flags.initalign)) { - if (flags.initalign == ROLE_RANDOM) { + if (flags.initalign == ROLE_RANDOM || flags.randomall) { flags.initalign = pick_align(flags.initrole, flags.initrace, - flags.initgend); + flags.initgend, PICK_RANDOM); break; } /* select an alignment */ @@ -487,14 +494,7 @@ X11_player_selection() flags.initalign = availindex; free((genericptr_t)choices), choices = 0; } else { - namep = roles[flags.initrole].name.m; - if (flags.initgend >= 0 && flags.female && - roles[flags.initrole].name.f) - namep = roles[flags.initrole].name.f; - Sprintf(qbuf, "%s %s %s alignment?", - genders[flags.initgend].adj, - races[flags.initrace].adj, s_suffix(namep)); - qbuf[0] = highc(qbuf[0]); + Sprintf(qbuf, "Your %s alignment?", s_suffix(plbuf)); popup = make_menu("alignment_selection", qbuf, algn_select_translations, "quit", ps_quit, diff --git a/win/X11/winstat.c b/win/X11/winstat.c index 4092ca8..d9bd7ad 100644 --- a/win/X11/winstat.c +++ b/win/X11/winstat.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)winstat.c 3.3 96/04/05 */ +/* SCCS Id: @(#)winstat.c 3.4 1996/04/05 */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -111,9 +111,7 @@ create_status_window(wp, create_popup, parent) XtSetArg(args[num_args], XtNrightMargin, &right_margin); num_args++; XtGetValues(wp->w, args, num_args); - /* font height is ascent + descent */ - wp->pixel_height = 2 * (fs->ascent + fs->descent) + - top_margin + bottom_margin; + wp->pixel_height = 2 * nhFontHeight(wp->w) + top_margin + bottom_margin; wp->pixel_width = COLNO * fs->max_bounds.width + left_margin + right_margin; @@ -600,7 +598,11 @@ update_fancy_status(wp) case F_NAME: val = (long) 0L; break; /* special */ case F_DLEVEL: val = (long) 0L; break; /* special */ +#ifndef GOLDOBJ case F_GOLD: val = (long) u.ugold; break; +#else + case F_GOLD: val = money_cnt(invent); break; +#endif case F_HP: val = (long) (u.mtimedone ? (u.mh > 0 ? u.mh : 0): (u.uhp > 0 ? u.uhp : 0)); break; diff --git a/win/X11/wintext.c b/win/X11/wintext.c index b55941e..84cafe6 100644 --- a/win/X11/wintext.c +++ b/win/X11/wintext.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)wintext.c 3.3 96/04/05 */ +/* SCCS Id: @(#)wintext.c 3.4 1996/04/05 */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ @@ -156,13 +156,14 @@ display_text_window(wp, blocking) struct text_info_t *text_info; Arg args[8]; Cardinal num_args; - Dimension width, height; + Dimension width, height, font_height; int nlines; text_info = wp->text_information; width = text_info->max_width + text_info->extra_width; text_info->blocked = blocking; text_info->destroy_on_ack = FALSE; + font_height = nhFontHeight(wp->w); /* * Calculate the number of lines to use. First, find the number of @@ -172,17 +173,14 @@ display_text_window(wp, blocking) * _some_ lines. Finally, use the number of lines in the text if * there are fewer than the max. */ - nlines = (XtScreen(wp->w)->height - text_info->extra_height) / - (text_info->fs->ascent + text_info->fs->descent); + nlines = (XtScreen(wp->w)->height - text_info->extra_height) / font_height; nlines -= 4; if (nlines > text_info->text.num_lines) nlines = text_info->text.num_lines; if (nlines <= 0) nlines = 1; - /* Font height is ascent + descent. */ - height = (nlines * (text_info->fs->ascent + text_info->fs->descent)) - + text_info->extra_height; + height = nlines * font_height + text_info->extra_height; num_args = 0; @@ -469,8 +467,12 @@ calculate_rip_text(int how) Sprintf(rip_line[NAME_LINE], "%s", plname); /* Put $ on stone */ - Sprintf(rip_line[GOLD_LINE], "%ld Au", u.ugold); - + Sprintf(rip_line[GOLD_LINE], "%ld Au", +#ifndef GOLDOBJ + u.ugold); +#else + done_money); +#endif /* Put together death description */ switch (killer_format) { default: impossible("bad killer format?"); diff --git a/win/X11/winval.c b/win/X11/winval.c index 42cfa60..3f2307e 100644 --- a/win/X11/winval.c +++ b/win/X11/winval.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)winval.c 3.3 92/3/7 */ +/* SCCS Id: @(#)winval.c 3.4 1992/3/7 */ /* Copyright (c) Dean Luick, 1992 */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gem/Install.gem b/win/gem/Install.gem index 6bd4f9a..97b7697 100644 --- a/win/gem/Install.gem +++ b/win/gem/Install.gem @@ -1,6 +1,6 @@ Hi, -This is nethack3.3.1 for Atari Gem and tty +This is nethack3.4.0 for Atari Gem and tty Windowing System. It is by far not complete or perfect. diff --git a/win/gem/gr_rect.c b/win/gem/gr_rect.c new file mode 100644 index 0000000..0dbe49a --- /dev/null +++ b/win/gem/gr_rect.c @@ -0,0 +1,181 @@ +/* SCCS Id: @(#)gr_rect.c 3.4 2001/12/10 */ +/* Copyright (c) Christian Bressler, 2001 */ +/* NetHack may be freely redistributed. See license for details. */ +/* This is an almost exact copy of qt_clust.cpp */ +/* gr_rect.c */ +#include +#include +#include +#include "gr_rect.h" +dirty_rect *new_dirty_rect(int size){ + dirty_rect *new=NULL; + if(size>0){ + new=(dirty_rect *)calloc(1L,sizeof(dirty_rect)); + if(new){ + new->rects=(GRECT *)calloc((long)size,sizeof(GRECT)); + if(new->rects==NULL){ + free(new); + return(NULL); + } + new->max=size; + } + } + return(new); +} +void delete_dirty_rect(dirty_rect *this){ + if(this==NULL) + return; + if(this->rects) + free(this->rects); + /* In case the Pointer is reused wrongly */ + this->rects=NULL; + this->max=0; + this->used=0; + free(this); +} +static int gc_inside(GRECT *frame,GRECT *test); +static int gc_touch(GRECT *frame,GRECT *test); +static void gc_combine(GRECT *frame,GRECT *test); +static long gc_area(GRECT *area); +int add_dirty_rect(dirty_rect *dr,GRECT *area){ + int cursor; + long lowestcost=9999999L; + int cheapest=-1; + int cheapestmerge1=-1; + int cheapestmerge2=-1; + int merge1; + int merge2; + for (cursor=0; cursorused; cursor++) { + if (gc_inside(&dr->rects[cursor],area)) { + /* Wholly contained already. */ + return(TRUE); + } + } + for (cursor=0; cursorused; cursor++) { + if (gc_touch(&dr->rects[cursor],area)) { + GRECT larger=dr->rects[cursor]; + long cost; + gc_combine(&larger,area); + cost=gc_area(&larger)-gc_area(&dr->rects[cursor]); + if (cost < lowestcost) { + int bad=FALSE,c; + for (c=0; cused && !bad; c++) { + bad=gc_touch(&dr->rects[c],&larger) && c!=cursor; + } + if (!bad) { + cheapest=cursor; + lowestcost=cost; + } + } + } + } + if (cheapest>=0) { + gc_combine(&dr->rects[cheapest],area); + return(TRUE); + } + if (dr->used < dr->max) { + dr->rects[dr->used++]=*area; + return(TRUE); + } + // Do cheapest of: + // add to closest cluster + // do cheapest cluster merge, add to new cluster + lowestcost=9999999L; + cheapest=-1; + for (cursor=0; cursorused; cursor++) { + GRECT larger=dr->rects[cursor]; + long cost; + gc_combine(&larger,area); + cost=gc_area(&larger)-gc_area(&dr->rects[cursor]); + if (cost < lowestcost) { + int bad=FALSE, c; + for (c=0; cused && !bad; c++) { + bad=gc_touch(&dr->rects[c],&larger) && c!=cursor; + } + if (!bad) { + cheapest=cursor; + lowestcost=cost; + } + } + } + // XXX could make an heuristic guess as to whether we + // XXX need to bother looking for a cheap merge. + for (merge1=0; merge1used; merge1++) { + for (merge2=0; merge2used; merge2++) { + if (merge1!=merge2) { + GRECT larger=dr->rects[merge1]; + long cost; + gc_combine(&larger,&dr->rects[merge2]); + cost=gc_area(&larger)-gc_area(&dr->rects[merge1])-gc_area(&dr->rects[merge2]); + if (cost < lowestcost) { + int bad=FALSE, c; + for (c=0; cused && !bad; c++) { + bad=gc_touch(&dr->rects[c],&larger) && c!=cursor; + } + if (!bad) { + cheapestmerge1=merge1; + cheapestmerge2=merge2; + lowestcost=cost; + } + } + } + } + } + if (cheapestmerge1>=0) { + gc_combine(&dr->rects[cheapestmerge1],&dr->rects[cheapestmerge2]); + dr->rects[cheapestmerge2]=dr->rects[dr->used-1]; + dr->rects[dr->used-1]=*area; + } else { + gc_combine(&dr->rects[cheapest],area); + } + // NB: clusters do not intersect (or intersection will + // overwrite). This is a result of the above algorithm, + // given the assumption that (x,y) are ordered topleft + // to bottomright. + return(TRUE); +} +int get_dirty_rect(dirty_rect* dr,GRECT *area){ + if(dr==NULL || area==NULL || dr->rects==NULL || dr->used<=0 || dr->max<=0) + return(FALSE); + *area=dr->rects[--dr->used]; + return(TRUE); +} +int clear_dirty_rect(dirty_rect *dr){ + if(dr) + dr->used=0; + return(TRUE); +} +int resize_dirty_rect(dirty_rect *dr,int new_size){ + return(FALSE); +} +static int gc_inside(GRECT *frame,GRECT *test){ + if(frame && test && frame->g_x<=test->g_x && frame->g_y<=test->g_y && + frame->g_x+frame->g_w>=test->g_x+test->g_w && + frame->g_y+frame->g_h>=test->g_y+test->g_h + ) + return(TRUE); + return(FALSE); +} +static int gc_touch(GRECT *frame,GRECT *test){ + GRECT tmp={test->g_x-1,test->g_y-1,test->g_w+2,test->g_h+2}; + return(rc_intersect(frame,&tmp)); +} +static void gc_combine(GRECT *frame,GRECT *test){ + if(!frame || !test) + return; + if(frame->g_x>test->g_x){ + frame->g_w+=frame->g_x-test->g_x; + frame->g_x=test->g_x; + } + if(frame->g_y>test->g_y){ + frame->g_h+=frame->g_y-test->g_y; + frame->g_y=test->g_y; + } + if(frame->g_x+frame->g_wg_x+test->g_w) + frame->g_w=test->g_x+test->g_w-frame->g_x; + if(frame->g_y+frame->g_hg_y+test->g_h) + frame->g_h=test->g_y+test->g_h-frame->g_y; +} +static long gc_area(GRECT *area){ + return((long)area->g_h*(long)area->g_w); +} diff --git a/win/gem/gr_rect.h b/win/gem/gr_rect.h new file mode 100644 index 0000000..0e4a0bd --- /dev/null +++ b/win/gem/gr_rect.h @@ -0,0 +1,14 @@ +/* gr_rect.h */ +#include +/********** structs **********/ +typedef struct { + GRECT *rects; + int max,used; +} dirty_rect; +/********* functions ************/ +dirty_rect *new_dirty_rect(int size); +void delete_dirty_rect(dirty_rect *this); +int add_dirty_rect(dirty_rect *dr,GRECT *area); +int get_dirty_rect(dirty_rect* dr,GRECT *area); +int clear_dirty_rect(dirty_rect *dr); +int resize_dirty_rect(dirty_rect *dr,int new_size); diff --git a/win/gem/load_img.c b/win/gem/load_img.c index 5386d2a..16d8fe8 100644 --- a/win/gem/load_img.c +++ b/win/gem/load_img.c @@ -37,7 +37,7 @@ void get_colors(int handle, short *palette, int col){ if(i<16) idx=vdi2dev4[i]; else - idx=i; + idx= i==255 ? 1 : i; } vq_color(handle, i, 0, (int *)palette + idx * 3); } @@ -49,7 +49,7 @@ void img_set_colors(int handle, short *palette, int col){ /* set color palette */ end=min(1< pic->img_h) scan_repeat = pic->img_h - line; - /* copy line to image buffer */ if(scan_repeat>1){ /* calculate address of a current line in a current bitplane */ diff --git a/win/gem/wingem.c b/win/gem/wingem.c index de13d33..415086a 100644 --- a/win/gem/wingem.c +++ b/win/gem/wingem.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)wingem.c 3.3 1999/12/10 */ +/* SCCS Id: @(#)wingem.c 3.4 1999/12/10 */ /* Copyright (c) Christian Bressler, 1999 */ /* NetHack may be freely redistributed. See license for details. */ @@ -21,12 +21,28 @@ static int curr_status_line; static char *FDECL(copy_of, (const char *)); static void FDECL(bail, (const char *)); /* __attribute__((noreturn)) */ +extern int mar_set_tile_mode(int); +extern void mar_set_font(int,const char*,int); +extern void mar_set_margin(int); +extern void mar_set_msg_visible(int); +extern void mar_set_status_align(int); +extern void mar_set_msg_align(int); +extern void mar_set_tilefile(char *); +extern void mar_set_tilex(int); +extern void mar_set_tiley(int); extern short glyph2tile[MAX_GLYPH]; /* from tile.c */ extern void mar_display_nhwindow(winid); /* from wingem1.c */ +void Gem_outrip(winid,int); +void Gem_preference_update(const char *); /* Interface definition, for windows.c */ struct window_procs Gem_procs = { "Gem", + WC_COLOR|WC_HILITE_PET|WC_ALIGN_MESSAGE|WC_ALIGN_STATUS| + WC_INVERSE|WC_SCROLL_MARGIN| + WC_FONT_MESSAGE|WC_FONT_STATUS|WC_FONT_MENU|WC_FONT_TEXT|WC_FONT_MAP| + WC_FONTSIZ_MESSAGE|WC_FONTSIZ_STATUS|WC_FONTSIZ_MENU|WC_FONTSIZ_TEXT|WC_FONTSIZ_MAP| + WC_TILE_WIDTH|WC_TILE_HEIGHT|WC_TILE_FILE|WC_VARY_MSGCOUNT|WC_ASCII_MAP, Gem_init_nhwindows, Gem_player_selection, Gem_askname, @@ -79,7 +95,8 @@ struct window_procs Gem_procs = { /* other defs that really should go away (they're tty specific) */ Gem_start_screen, Gem_end_screen, - genl_outrip + Gem_outrip, + Gem_preference_update }; #ifdef MAC @@ -115,6 +132,11 @@ mar_get_msg_history() return(iflags.msg_history); } +int +mar_get_msg_visible() +{ + return(iflags.wc_vary_msgcount); +} /* clean up and quit */ static void bail(mesg) @@ -126,6 +148,17 @@ const char *mesg; /*NOTREACHED*/ } +/*$$$*/ +#define DEF_CLIPAROUND_MARGIN -1 +#ifndef TILE_X +#define TILE_X 16 +#endif +#define TILE_Y 16 +#define TILES_PER_LINE 20 +#define NHFONT_DEFAULT_SIZE 10 +#define NHFONT_SIZE_MIN 3 +#define NHFONT_SIZE_MAX 20 +/*$$$*/ /*ARGSUSED*/ void Gem_init_nhwindows(argcp,argv) @@ -135,6 +168,42 @@ char** argv; argv=argv, argcp=argcp; colors_changed=TRUE; + set_wc_option_mod_status( + WC_ALIGN_MESSAGE | + WC_ALIGN_STATUS | + WC_TILE_WIDTH | + WC_TILE_HEIGHT | + WC_TILE_FILE, + DISP_IN_GAME); + set_wc_option_mod_status( + WC_HILITE_PET | + WC_SCROLL_MARGIN | + WC_FONT_MESSAGE | + WC_FONT_MAP | + WC_FONT_STATUS | + WC_FONT_MENU | + WC_FONT_TEXT | + WC_FONTSIZ_MESSAGE | + WC_FONTSIZ_MAP | + WC_FONTSIZ_STATUS | + WC_FONTSIZ_MENU | + WC_FONTSIZ_TEXT | + WC_VARY_MSGCOUNT, + SET_IN_GAME + ); + if( iflags.wc_align_message==0 ) iflags.wc_align_message = ALIGN_TOP; + if( iflags.wc_align_status==0 ) iflags.wc_align_status = ALIGN_BOTTOM; + if( iflags.wc_scroll_margin==0 ) iflags.wc_scroll_margin = DEF_CLIPAROUND_MARGIN; + if( iflags.wc_tile_width==0 ) iflags.wc_tile_width = TILE_X; + if( iflags.wc_tile_height==0 ) iflags.wc_tile_height = TILE_Y; + if(iflags.wc_tile_file && *iflags.wc_tile_file) + mar_set_tilefile(iflags.wc_tile_file); + if( iflags.wc_vary_msgcount==0 ) iflags.wc_vary_msgcount = 3; + mar_set_tile_mode(!iflags.wc_ascii_map); /* MAR -- 17.Mar 2002 True is tiles */ + mar_set_tilex(iflags.wc_tile_width); + mar_set_tiley(iflags.wc_tile_height); + mar_set_msg_align(iflags.wc_align_message-ALIGN_BOTTOM); + mar_set_status_align(iflags.wc_align_status-ALIGN_BOTTOM); if(mar_gem_init()==0){ bail((char *)0); /*NOTREACHED*/ @@ -157,10 +226,19 @@ Gem_player_selection() anything any; menu_item *selected=NULL; + /* avoid unnecessary prompts further down */ + rigid_role_checks(); + /* Should we randomly pick for the player? */ - if (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE || - flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE) { - pick4u = yn_function("Shall I pick a character for you? [ynq]",ynqchars,'n'); + if (!flags.randomall && + (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE || + flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE)) { +/* pick4u = yn_function("Shall I pick a character for you? [ynq]",ynqchars,'n');*/ + pick4u = yn_function( + build_plselection_prompt(pbuf, QBUFSZ, flags.initrole,flags.initrace, + flags.initgend, flags.initalign) + ,ynqchars,'n' + ); if(pick4u=='q'){ give_up: /* Just quit */ if (selected) free((genericptr_t) selected); @@ -174,10 +252,10 @@ Gem_player_selection() if (flags.initrole < 0) { /* Process the choice */ - if(pick4u=='y' || flags.initrole == ROLE_RANDOM) { + if(pick4u=='y' || flags.initrole == ROLE_RANDOM || flags.randomall) { /* Pick a random role */ flags.initrole = pick_role(flags.initrace, flags.initgend, - flags.initalign); + flags.initalign, PICK_RANDOM); if (flags.initrole < 0) { mar_add_message("Incompatible role!"); mar_display_nhwindow(WIN_MESSAGE); @@ -201,7 +279,7 @@ Gem_player_selection() } } any.a_int = pick_role(flags.initrace, flags.initgend, - flags.initalign)+1; + flags.initalign, PICK_RANDOM)+1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randrole()+1; add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, @@ -227,9 +305,9 @@ Gem_player_selection() * pre-selected gender/alignment */ if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) { /* pre-selected race not valid */ - if (pick4u == 'y' || flags.initrace == ROLE_RANDOM) { + if (pick4u == 'y' || flags.initrace == ROLE_RANDOM || flags.randomall) { flags.initrace = pick_race(flags.initrole, flags.initgend, - flags.initalign); + flags.initalign, PICK_RANDOM); if (flags.initrace < 0) { mar_add_message("Incompatible race!"); mar_display_nhwindow(WIN_MESSAGE); @@ -254,7 +332,6 @@ Gem_player_selection() } } } - /* Permit the user to pick, if there is more than one */ if (n > 1) { win = create_nhwindow(NHW_MENU); @@ -268,7 +345,7 @@ Gem_player_selection() 0, ATR_NONE, races[i].noun, MENU_UNSELECTED); } any.a_int = pick_race(flags.initrole, flags.initgend, - flags.initalign)+1; + flags.initalign, PICK_RANDOM)+1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randrace(flags.initrole)+1; add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, @@ -283,7 +360,6 @@ Gem_player_selection() destroy_nhwindow(win); if (n != 1 || selected[0].item.a_int == any.a_int) goto give_up; /* Selected quit */ - k = selected[0].item.a_int - 1; free((genericptr_t) selected), selected = 0; } @@ -297,9 +373,9 @@ Gem_player_selection() if (flags.initgend < 0 || !validgend(flags.initrole, flags.initrace, flags.initgend)) { /* pre-selected gender not valid */ - if (pick4u == 'y' || flags.initgend == ROLE_RANDOM) { + if (pick4u == 'y' || flags.initgend == ROLE_RANDOM || flags.randomall) { flags.initgend = pick_gend(flags.initrole, flags.initrace, - flags.initalign); + flags.initalign, PICK_RANDOM); if (flags.initgend < 0) { mar_add_message("Incompatible gender!"); mar_display_nhwindow(WIN_MESSAGE); @@ -324,7 +400,6 @@ Gem_player_selection() } } } - /* Permit the user to pick, if there is more than one */ if (n > 1) { win = create_nhwindow(NHW_MENU); @@ -338,7 +413,7 @@ Gem_player_selection() 0, ATR_NONE, genders[i].adj, MENU_UNSELECTED); } any.a_int = pick_gend(flags.initrole, flags.initrace, - flags.initalign)+1; + flags.initalign, PICK_RANDOM)+1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randgend(flags.initrole, flags.initrace)+1; add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, @@ -354,7 +429,6 @@ Gem_player_selection() destroy_nhwindow(win); if (n != 1 || selected[0].item.a_int == any.a_int) goto give_up; /* Selected quit */ - k = selected[0].item.a_int - 1; free((genericptr_t) selected), selected = 0; } @@ -367,9 +441,9 @@ Gem_player_selection() if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace, flags.initalign)) { /* pre-selected alignment not valid */ - if (pick4u == 'y' || flags.initalign == ROLE_RANDOM) { + if (pick4u == 'y' || flags.initalign == ROLE_RANDOM || flags.randomall) { flags.initalign = pick_align(flags.initrole, flags.initrace, - flags.initgend); + flags.initgend, PICK_RANDOM); if (flags.initalign < 0) { mar_add_message("Incompatible alignment!"); mar_display_nhwindow(WIN_MESSAGE); @@ -394,7 +468,6 @@ Gem_player_selection() } } } - /* Permit the user to pick, if there is more than one */ if (n > 1) { win = create_nhwindow(NHW_MENU); @@ -408,7 +481,7 @@ Gem_player_selection() 0, ATR_NONE, aligns[i].adj, MENU_UNSELECTED); } any.a_int = pick_align(flags.initrole, flags.initrace, - flags.initgend)+1; + flags.initgend, PICK_RANDOM)+1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randalign(flags.initrole, flags.initrace)+1; add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, @@ -427,7 +500,6 @@ Gem_player_selection() destroy_nhwindow(win); if (n != 1 || selected[0].item.a_int == any.a_int) goto give_up; /* Selected quit */ - k = selected[0].item.a_int - 1; free((genericptr_t) selected), selected = 0; } @@ -643,6 +715,8 @@ Gem_putstr(window, attr, str) Gem_putstr(WIN_MESSAGE,0,str); else mar_map_curs_weiter(); + mar_display_nhwindow(WIN_MESSAGE); + mar_display_nhwindow(WIN_STATUS); break; case NHW_MENU: @@ -827,7 +901,6 @@ extern int mar_set_rogue(int); #endif extern void mar_add_pet_sign(winid,int,int); -extern int mar_set_tile_mode(int); void Gem_print_glyph(window, x, y, glyph) @@ -845,10 +918,11 @@ Gem_print_glyph(window, x, y, glyph) x--; /* MAR -- because x ranges from 1 to COLNO */ if(mar_set_tile_mode(-1)){ mar_print_glyph(window,x,y,glyph2tile[glyph]); - if(glyph_is_pet(glyph) + if( #ifdef TEXTCOLOR - && iflags.hilite_pet + iflags.hilite_pet && #endif + glyph_is_pet(glyph) ) mar_add_pet_sign(window,x,y); }else @@ -862,78 +936,12 @@ void mar_print_gl_char(window, x, y, glyph) xchar x, y; int glyph; { - uchar ch; - register int offset; -#ifdef TEXTCOLOR + int ch; int color; + unsigned special; -#define zap_color(n) color = iflags.use_color ? zapcolors[n] : NO_COLOR -#define cmap_color(n) color = iflags.use_color ? defsyms[n].color : NO_COLOR -#define obj_color(n) color = iflags.use_color ? objects[n].oc_color : NO_COLOR -#define mon_color(n) color = iflags.use_color ? mons[n].mcolor : NO_COLOR -#define invis_color(n) color = NO_COLOR -#define pet_color(n) color = iflags.use_color ? mons[n].mcolor : \ - /* If no color, try to hilite pets; black */ \ - /* should be HI */ \ - ((iflags.hilite_pet) ? CLR_BLACK : NO_COLOR) -#define warn_color(n) color = iflags.use_color ? def_warnsyms[n].color : NO_COLOR - -# else /* no text color */ - -#define zap_color(n) -#define cmap_color(n) -#define obj_color(n) -#define mon_color(n) -#define invis_color(n) -#define pet_color(c) -#define warn_color(c) -#endif /* no text color */ - - /* - * Map the glyph back to a character. - * - * Warning: For speed, this makes an assumption on the order of - * offsets. The order is set in display.h. - */ - if ((offset = (glyph - GLYPH_WARNING_OFF)) >= 0) { /* a warning flash */ - ch = warnsyms[offset]; - warn_color(offset); - } else - if ((offset = (glyph - GLYPH_SWALLOW_OFF)) >= 0) { /* swallow */ - /* see swallow_to_glyph() in display.c */ - ch = (uchar) showsyms[S_sw_tl + (offset & 0x7)]; - mon_color(offset >> 3); - } else if ((offset = (glyph - GLYPH_ZAP_OFF)) >= 0) { /* zap beam */ - /* see zapdir_to_glyph() in display.c */ - ch = showsyms[S_vbeam + (offset & 0x3)]; - zap_color((offset >> 2)); - } else if ((offset = (glyph - GLYPH_CMAP_OFF)) >= 0) { /* cmap */ - ch = showsyms[offset]; - cmap_color(offset); - } else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) { /* object */ - ch = oc_syms[(int)objects[offset].oc_class]; - obj_color(offset); - } else if ((offset = (glyph - GLYPH_RIDDEN_OFF)) >= 0) { /* mon ridden */ - ch = monsyms[(int)mons[offset].mlet]; - mon_color(offset); - } else if ((offset = (glyph - GLYPH_BODY_OFF)) >= 0) { /* a corpse */ - ch = oc_syms[(int)objects[CORPSE].oc_class]; - mon_color(offset); - } else if ((offset = (glyph - GLYPH_DETECT_OFF)) >= 0) { /* mon detect */ - ch = monsyms[(int)mons[offset].mlet]; - mon_color(offset); - /* Disabled for now; anyone want to get reverse video to work? */ - /* is_reverse = TRUE; */ - } else if ((offset = (glyph - GLYPH_INVIS_OFF)) >= 0) { /* invisible */ - ch = DEF_INVISIBLE; - invis_color(offset); - } else if ((offset = (glyph - GLYPH_PET_OFF)) >= 0) { /* a pet */ - ch = monsyms[(int)mons[offset].mlet]; - pet_color(offset); - } else { /* a monster */ - ch = monsyms[(int)mons[glyph].mlet]; - mon_color(glyph); - } + /* map glyph to character and color */ + mapglyph(glyph, &ch, &color, &special, x, y); #ifdef TEXTCOLOR /* Turn off color if rogue level. */ @@ -1038,6 +1046,182 @@ char *posbar; {} #endif +/** Gem_outrip **/ +void mar_set_text_to_rip(winid); +char** rip_line=0; +extern const char *killed_by_prefix[]; +void +Gem_outrip(w, how) +winid w; +int how; +{ +/* Code from X11 windowport */ +#define STONE_LINE_LEN 15 /* # chars that fit on one line */ +#define NAME_LINE 0 /* line # for player name */ +#define GOLD_LINE 1 /* line # for amount of gold */ +#define DEATH_LINE 2 /* line # for death description */ +#define YEAR_LINE 6 /* line # for year */ + char buf[BUFSZ]; + char *dpx; + int line; + if (!rip_line) { + int i; + rip_line= (char **)malloc((YEAR_LINE+1)*sizeof(char *)); + for (i=0; i STONE_LINE_LEN) { + for(i = STONE_LINE_LEN; + ((i0 > STONE_LINE_LEN) && i); i--) + if(dpx[i] == ' ') i0 = i; + if(!i) i0 = STONE_LINE_LEN; + } + tmpchar = dpx[i0]; + dpx[i0] = 0; + strcpy(rip_line[line], dpx); + if (tmpchar != ' ') { + dpx[i0] = tmpchar; + dpx= &dpx[i0]; + } else dpx= &dpx[i0+1]; + } + /* Put year on stone */ + Sprintf(rip_line[YEAR_LINE], "%4d", getyear()); + mar_set_text_to_rip(w); + for(line=0;line<13;line++) + putstr(w, 0, ""); +} +void +mar_get_font(type,p_fname,psize) +int type; +char **p_fname; +int *psize; +{ + switch(type){ + case NHW_MESSAGE: + *p_fname=iflags.wc_font_message; + *psize=iflags.wc_fontsiz_message; + break; + case NHW_MAP: + *p_fname=iflags.wc_font_map; + *psize=iflags.wc_fontsiz_map; + break; + case NHW_STATUS: + *p_fname=iflags.wc_font_status; + *psize=iflags.wc_fontsiz_status; + break; + case NHW_MENU: + *p_fname=iflags.wc_font_menu; + *psize=iflags.wc_fontsiz_menu; + break; + case NHW_TEXT: + *p_fname=iflags.wc_font_text; + *psize=iflags.wc_fontsiz_text; + break; + default: + break; + } +} +void +Gem_preference_update(pref) +const char *pref; +{ + if( stricmp( pref, "font_message")==0 || + stricmp( pref, "font_size_message")==0 ) { + if( iflags.wc_fontsiz_messageNHFONT_SIZE_MAX ) + iflags.wc_fontsiz_message = NHFONT_DEFAULT_SIZE; + mar_set_font(NHW_MESSAGE,iflags.wc_font_message,iflags.wc_fontsiz_message); + return; + } + if( stricmp( pref, "font_map")==0 || + stricmp( pref, "font_size_map")==0 ) { + if( iflags.wc_fontsiz_mapNHFONT_SIZE_MAX ) + iflags.wc_fontsiz_map = NHFONT_DEFAULT_SIZE; + mar_set_font(NHW_MAP,iflags.wc_font_map,iflags.wc_fontsiz_map); + return; + } + if( stricmp( pref, "font_status")==0 || + stricmp( pref, "font_size_status")==0 ) { + if( iflags.wc_fontsiz_statusNHFONT_SIZE_MAX ) + iflags.wc_fontsiz_status = NHFONT_DEFAULT_SIZE; + mar_set_font(NHW_STATUS,iflags.wc_font_status,iflags.wc_fontsiz_status); + return; + } + if( stricmp( pref, "font_menu")==0 || + stricmp( pref, "font_size_menu")==0 ) { + if( iflags.wc_fontsiz_menuNHFONT_SIZE_MAX ) + iflags.wc_fontsiz_menu = NHFONT_DEFAULT_SIZE; + mar_set_font(NHW_MENU,iflags.wc_font_menu,iflags.wc_fontsiz_menu); + return; + } + if( stricmp( pref, "font_text")==0 || + stricmp( pref, "font_size_text")==0 ) { + if( iflags.wc_fontsiz_textNHFONT_SIZE_MAX ) + iflags.wc_fontsiz_text = NHFONT_DEFAULT_SIZE; + mar_set_font(NHW_TEXT,iflags.wc_font_text,iflags.wc_fontsiz_text); + return; + } + if( stricmp( pref, "scroll_margin")==0 ) { + mar_set_margin(iflags.wc_scroll_margin); + Gem_cliparound(u.ux, u.uy); + return; + } + if( stricmp( pref, "ascii_map")==0 ) { + mar_set_tile_mode(!iflags.wc_ascii_map); + doredraw(); + return; + } + if( stricmp( pref, "hilite_pet")==0 ){ + /* MAR -- works without doing something here. */ + return; + } + if( stricmp( pref, "align_message")==0){ + mar_set_msg_align(iflags.wc_align_message-ALIGN_BOTTOM); + return; + } + if(stricmp( pref, "align_status")==0 ){ + mar_set_status_align(iflags.wc_align_status-ALIGN_BOTTOM); + return; + } + if( stricmp( pref, "vary_msgcount")==0 ){ + mar_set_msg_visible(iflags.wc_vary_msgcount); + return; + } +} /* * Allocate a copy of the given string. If null, return a string of * zero length. diff --git a/win/gem/wingem1.c b/win/gem/wingem1.c index fb2e833..d93be8b 100644 --- a/win/gem/wingem1.c +++ b/win/gem/wingem1.c @@ -1,10 +1,11 @@ -/* SCCS Id: @(#)wingem1.c 3.3 1999/12/10 */ +/* SCCS Id: @(#)wingem1.c 3.4 1999/12/10 */ /* Copyright (c) Christian Bressler 1999 */ /* NetHack may be freely redistributed. See license for details. */ #define __TCC_COMPAT__ #include +#include #include #include #include @@ -13,6 +14,7 @@ #include "gem_rsc.h" #include "load_img.h" +#include "gr_rect.h" #define genericptr_t void * #include "wintype.h" @@ -39,13 +41,14 @@ typedef signed char xchar; #undef NDECL #undef FDECL -static char nullstr[]="", md[]="NetHack 3.3.1", strCancel[]="Cancel", strOk[]="Ok", strText[]="Text"; +static char nullstr[]="", md[]="NetHack 3.4.0", strCancel[]="Cancel", strOk[]="Ok", strText[]="Text"; extern winid WIN_MESSAGE, WIN_MAP, WIN_STATUS, WIN_INVEN; #define MAXWIN 20 #define ROWNO 21 #define COLNO 80 +#define MSGLEN 100 #define MAP_GADGETS NAME|MOVER|CLOSER|FULLER|LFARROW|RTARROW|UPARROW|DNARROW|VSLIDE|HSLIDE|SIZER|SMALLER #define DIALOG_MODE AUTO_DIAL|MODAL|NO_ICONIFY @@ -116,11 +119,19 @@ extern int mar_iflags_numpad(void); /* from wingem.c */ extern void Gem_raw_print(const char *); /* from wingem.c */ extern int mar_hp_query(void); /* from wingem.c */ extern int mar_get_msg_history(void); /* from wingem.c */ +extern int mar_get_msg_visible(void); /* from wingem.c */ +extern void mar_get_font(int,char **,int *);/* from wingem.c */ extern int vdi2dev4[]; /* from load_img.c */ +void recalc_msg_win(GRECT*); +void recalc_status_win(GRECT*); +void calc_std_winplace(int, GRECT *); +int (*v_mtext)(int,int,int,char*); static int no_glyph; /* the int indicating there is no glyph */ IMG_header tile_image, titel_image, rip_image; -MFDB Tile_bilder, Map_bild, Titel_bild, Rip_bild, Black_bild, Pet_Mark; +MFDB Tile_bilder, Map_bild, Titel_bild, Rip_bild, Black_bild, Pet_Mark, FontCol_Bild; +static int Tile_width=16, Tile_heigth=16, Tiles_per_line=20; +char *Tilefile=NULL; /* pet_mark Design by Warwick Allison warwick@troll.no */ static int pet_mark_data[]={0x0000,0x3600,0x7F00,0x7F00,0x3E00,0x1C00,0x0800}; static short *normal_palette=NULL; @@ -131,19 +142,28 @@ static struct gw{ GRECT gw_place; } Gem_nhwindow[MAXWIN]; -int Fcw, Fch; +typedef struct { + int id; + int size; + int cw, ch; + int prop; +} NHGEM_FONT; /*struct gemmapdata {*/ - GRECT dirty_map_area={COLNO,ROWNO,0,0}; + GRECT dirty_map_area={COLNO-1,ROWNO,0,0}; int map_cursx=0, map_cursy=0, curs_col=WHITE; - int draw_cursor=TRUE, map_cell_width=16; + int draw_cursor=TRUE, scroll_margin=-1; + NHGEM_FONT map_font; SCROLL scroll_map; char **map_glyphs=NULL; + dirty_rect *dr_map; /*};*/ /*struct gemstatusdata{*/ char **status_line; - int Anz_status_lines, status_w, StFch, StFcw; + int Anz_status_lines, status_w, status_align=FALSE; + NHGEM_FONT status_font; + dirty_rect *dr_stat; /*};*/ /*struct gemmessagedata{*/ @@ -152,19 +172,25 @@ int Fcw, Fch; int messages_pro_zug=0; char **message_line; int *message_age; - int msg_pos=0, msg_max=0, msg_anz=0, msg_width=0; + int msg_pos=0, msg_max=0, msg_anz=0, msg_width=0, msg_vis=3, msg_align=TRUE; + NHGEM_FONT msg_font; + dirty_rect *dr_msg; /*};*/ /*struct geminvdata {*/ SCROLL scroll_menu; Gem_menu_item *invent_list; int Anz_inv_lines=0, Inv_breite=16; + NHGEM_FONT menu_font; int Inv_how; /*};*/ /*struct gemtextdata{*/ char **text_lines; int Anz_text_lines=0, text_width; + NHGEM_FONT text_font; + int use_rip=FALSE; + extern char** rip_line; /*};*/ static OBJECT *zz_oblist[NHICON+1]; @@ -222,6 +248,35 @@ void mar_clear_messagewin(void){ mar_display_nhwindow(WIN_MESSAGE); } +void clipbrd_save(void *data,int cnt,boolean append,boolean is_inv){ + char path[MAX_PATH],*text,*crlf="\r\n"; + long handle; + int i; + + if (data && cnt>0 && scrp_path(path,"scrap.txt") && (handle = append ? Fopen(path,1) : Fcreate(path,0))>0){ + if (append) + Fseek(0L,(int) handle,SEEK_END); + if(is_inv){ + Gem_menu_item *it=(Gem_menu_item *)data; + + for(;it;it=it->Gmi_next){ + text=it->Gmi_str; + Fwrite((int) handle,strlen(text),text); + Fwrite((int) handle,2L,crlf); + } + }else{ + for(i=0;i2){ + if(msg_pos>msg_vis-1){ msg_pos--; Gem_nhwindow[WIN_MESSAGE].gw_dirty=TRUE; mar_display_nhwindow(WIN_MESSAGE); @@ -281,8 +336,191 @@ int ng; no_glyph=ng; } +void +mar_set_tilefile(name) +char* name; +{ + Tilefile=name; +} +void +mar_set_tilex(value) +int value; +{ + Min(&value,32); + Max(&value,1); + Tile_width=value; +} +void +mar_set_tiley(value) +int value; +{ + Min(&value,32); + Max(&value,1); + Tile_heigth=value; +} /****************************** userdef_draw *************************************/ +void rearrange_windows(void); +void mar_set_status_align(int sa){ + if(status_align!=sa){ + status_align=sa; + rearrange_windows(); + } +} +void mar_set_msg_align(int ma){ + if(msg_align!=ma){ + msg_align=ma; + rearrange_windows(); + } +} +void mar_set_msg_visible(int mv){ + if(mv!=msg_vis){ + Max(&mv,1); + Min(&mv,min(msg_anz,20)); + Min(&mv,desk.g_h/msg_font.ch/2); + msg_vis=mv; + rearrange_windows(); + } +} +/* size<0 cellheight; size>0 points */ +void mar_set_fontbyid(int type, int id, int size){ + int chardim[4]; + if(id<=0) + id=ibm_font_id; + if((size>-3 && size<3) || size<-20 || size>20) + size=-ibm_font; + /* MAR -- 17.Mar 2002 For now allow FNT_PROP only with NHW_TEXT */ + if(type!=NHW_TEXT && (FontInfo(id)->type & (FNT_PROP|FNT_ASCII))) + id=ibm_font_id; + switch(type){ + case NHW_MESSAGE: + if(msg_font.size==-size && msg_font.id==id) + break; + msg_font.size=-size; + msg_font.id=id; + msg_font.prop=FontInfo(id)->type & (FNT_PROP|FNT_ASCII); + v_set_text(msg_font.id,msg_font.size,BLACK,0,0,chardim); + msg_font.ch=chardim[3] ? chardim[3] : 1; + msg_font.cw=chardim[2] ? chardim[2] : 1; + msg_width=min(max_w/msg_font.cw-3,MSGLEN); + rearrange_windows(); + break; + case NHW_MAP: + if(map_font.size!=-size || map_font.id!=id){ + MFDB mtmp; + map_font.size=-size; + map_font.id=id; + map_font.prop=FontInfo(id)->type & (FNT_PROP|FNT_ASCII); + v_set_text(map_font.id,map_font.size,BLACK,0,0,chardim); + map_font.ch=chardim[3] ? chardim[3] : 1; + map_font.cw=chardim[2] ? chardim[2] : 1; + mfdb(&mtmp,NULL,(COLNO-1)*map_font.cw, ROWNO*map_font.ch, 0, planes); + if(mfdb_size(&mtmp)>mfdb_size(&FontCol_Bild) && mfdb_size(&mtmp)>mfdb_size(&Map_bild)){ + FontCol_Bild.fd_addr=Map_bild.fd_addr=(int *)realloc(Map_bild.fd_addr,mfdb_size(&mtmp)); + if(!Map_bild.fd_addr) /* FIXME -- Not really neccessary since the former space is still valid */ + panic("Not enough Space for the map."); + } + mfdb(&FontCol_Bild,FontCol_Bild.fd_addr,(COLNO-1)*map_font.cw, ROWNO*map_font.ch, 0, planes); + rearrange_windows(); + } + break; + case NHW_STATUS: + if(status_font.size==-size && status_font.id==id) + break; + status_font.size=-size; + status_font.id=id; + status_font.prop=FontInfo(id)->type & (FNT_PROP|FNT_ASCII); + v_set_text(status_font.id,status_font.size,BLACK,0,0,chardim); + status_font.ch=chardim[3] ? chardim[3] : 1; + status_font.cw=chardim[2] ? chardim[2] : 1; + rearrange_windows(); + break; + case NHW_MENU: + if(menu_font.size==-size && menu_font.id==id) + break; + menu_font.size=-size; + menu_font.id=id; + menu_font.prop=FontInfo(id)->type & (FNT_PROP|FNT_ASCII); + v_set_text(menu_font.id,menu_font.size,BLACK,0,0,chardim); + menu_font.ch=chardim[3] ? chardim[3] : 1; + menu_font.cw=chardim[2] ? chardim[2] : 1; + break; + case NHW_TEXT: + if(text_font.size==-size && text_font.id==id) + break; + text_font.size=-size; + text_font.id=id; + text_font.prop=FontInfo(id)->type & (FNT_PROP|FNT_ASCII); + v_set_text(text_font.id,text_font.size,BLACK,0,0,chardim); + text_font.ch=chardim[3] ? chardim[3] : 1; + text_font.cw=chardim[2] ? chardim[2] : 1; + break; + default: + break; + } +} +void mar_set_font(int type, const char *font_name, int size){ + int id=0; + /* MAR -- 17.Mar 2002 usual Gem behavior, use the Font-ID */ + if(font_name && *font_name){ + id=atoi(font_name); + if(id<=0){ + int i, tid; + char name[32]; + for(i=fonts_loaded;--i>=0;){ + tid=vqt_name(x_handle,i,name); + if(!stricmp(name,font_name)){ + id=tid; + break; + } + } + } + } + mar_set_fontbyid(type,id,size); +} +void rearrange_windows(void){ + GRECT area; + int todo=TRUE; + if(WIN_MAP != WIN_ERR && Gem_nhwindow[WIN_MAP].gw_window){ + scroll_map.px_hline=mar_set_tile_mode(FAIL)?Tile_width:map_font.cw; + scroll_map.px_vline=mar_set_tile_mode(FAIL)?Tile_heigth:map_font.ch; + if(todo){ + calc_std_winplace(FAIL,&area); + todo=FALSE; + } + calc_std_winplace(NHW_MAP,&area); + Gem_nhwindow[WIN_MAP].gw_window->max.g_w=area.g_w; + Gem_nhwindow[WIN_MAP].gw_window->max.g_h=area.g_h; + Gem_nhwindow[WIN_MAP].gw_window->max.g_w=area.g_w; + window_reinit(Gem_nhwindow[WIN_MAP].gw_window,md,md,NULL,FALSE,FALSE); + { + int buf[8]; + buf[3]=K_CTRL; + buf[4]=C('L'); + AvSendMsg(ap_id,AV_SENDKEY,buf); + } + } + if(WIN_MESSAGE != WIN_ERR && Gem_nhwindow[WIN_MESSAGE].gw_window){ + if(todo){ + calc_std_winplace(FAIL,&area); + todo=FALSE; + } + calc_std_winplace(NHW_MESSAGE,&area); + Gem_nhwindow[WIN_MESSAGE].gw_window->min_h=area.g_h; + window_size(Gem_nhwindow[WIN_MESSAGE].gw_window,&area); + redraw_window(Gem_nhwindow[WIN_MESSAGE].gw_window,NULL); + } + if(WIN_STATUS != WIN_ERR && Gem_nhwindow[WIN_STATUS].gw_window){ + if(todo){ + calc_std_winplace(FAIL,&area); + todo=FALSE; + } + calc_std_winplace(NHW_STATUS,&area); + Gem_nhwindow[WIN_STATUS].gw_window->min_h=area.g_h; + window_size(Gem_nhwindow[WIN_STATUS].gw_window,&area); + redraw_window(Gem_nhwindow[WIN_STATUS].gw_window,NULL); + } +} void my_color_area(GRECT *area, int col){ int pxy[4]; @@ -299,41 +537,42 @@ int mar_set_tile_mode(int); static void win_draw_map(int first, WIN *win, GRECT *area){ int pla[8], w=area->g_w-1, h=area->g_h-1; - int i, x, y, mode, mch; + int i, x, y; GRECT back=*area; first=first; - v_set_mode(MD_REPLACE); - mode=S_ONLY; if(!mar_set_tile_mode(FAIL)){ - v_set_text(ibm_font_id,ibm_font,WHITE,0,0,NULL); + int start=(area->g_x-win->work.g_x)/map_font.cw+scroll_map.hpos; + int stop=(area->g_x+area->g_w+map_font.cw-1-win->work.g_x)/map_font.cw+scroll_map.hpos; + int starty=(area->g_y-win->work.g_y)/map_font.ch+scroll_map.vpos; + int stopy=min((area->g_y+area->g_h+map_font.ch-1-win->work.g_y)/map_font.ch+scroll_map.vpos,ROWNO); + char tmp; + v_set_text(map_font.id,map_font.size,WHITE,0,0,NULL); v_set_mode(MD_TRANS); - mode=S_OR_D; - mch=Fch-1; - x=win->work.g_x-scroll_map.px_hpos; - y=win->work.g_y-scroll_map.px_vpos; - pla[2]=pla[0]=area->g_x-x; - pla[3]=pla[1]=0; + x=win->work.g_x-scroll_map.px_hpos+start*map_font.cw; + y=win->work.g_y-scroll_map.px_vpos+starty*map_font.ch; + pla[2]=pla[0]=scroll_map.px_hpos+area->g_x-win->work.g_x; + pla[3]=pla[1]=starty*map_font.ch; pla[2]+=w; - pla[3]+=mch; /* MAR -- was 16 */ + pla[3]+=map_font.ch-1; pla[6]=pla[4]=area->g_x; /* x_wert to */ pla[7]=pla[5]=y; /* y_wert to */ pla[6]+=w; - pla[7]+=mch; /* MAR -- was 16 */ - Vsync(); - back.g_h=Fch; /* MAR -- was 16 */ - for(i=0;ig_x-win->work.g_x; pla[3]=pla[1]=scroll_map.px_vpos+area->g_y-win->work.g_y; pla[2]+=w; @@ -342,15 +581,15 @@ static void win_draw_map(int first, WIN *win, GRECT *area){ pla[7]=pla[5]=area->g_y; /* y_wert to */ pla[6]+=w; pla[7]+=h; - vro_cpyfm(x_handle, mode, pla, &Map_bild, screen); + vro_cpyfm(x_handle, S_ONLY, pla, &Map_bild, screen); } if(draw_cursor){ v_set_line(curs_col,1,1,0,0); pla[0]=pla[2]=win->work.g_x+scroll_map.px_hline*(map_cursx-scroll_map.hpos); pla[1]=pla[3]=win->work.g_y+scroll_map.px_vline*(map_cursy-scroll_map.vpos); - pla[2]+=map_cell_width-1; - pla[3]+=mch; + pla[2]+=scroll_map.px_hline-1; + pla[3]+=scroll_map.px_vline-1; v_rect(pla[0],pla[1],pla[2],pla[3]); } } @@ -379,32 +618,78 @@ static int draw_lines(PARMBLK *pb){ if(rc_intersect((GRECT *)&pb->pb_xc,&area)){ char **ptr; - int x=pb->pb_x,y=pb->pb_y,start_line=(area.g_y-y), chardim[4]; + int x=pb->pb_x,y=pb->pb_y,start_line=(area.g_y-y); - v_set_mode(MD_REPLACE); + v_set_mode((text_font.cw&7)==0 && text_font.prop==0 ? MD_REPLACE : MD_TRANS); /* void v_set_text(int font,int height,int color,int effect,int rotate,int out[4]) */ - v_set_text(ibm_font_id,ibm_font,BLACK,0,0,chardim); + v_set_text(text_font.id,text_font.size,BLACK,0,0,NULL); + start_line /= text_font.ch; + y+=start_line*text_font.ch; + x-=(int)scroll_menu.px_hpos; + ptr=&text_lines[start_line+=scroll_menu.vpos]; + start_line = min((area.g_y-y+area.g_h+text_font.ch-1)/text_font.ch,Anz_text_lines-start_line); + area.g_h=text_font.ch; + Vsync(); +/* x=(x+7) & ~7;*/ + for(;--start_line>=0;y+=text_font.ch){ + area.g_y=y; + my_clear_area(&area); + if(**ptr-1){ + v_set_text(FAIL,0,BLUE,0x01,0,NULL); + (*v_mtext)(x_handle,x,y,(*ptr++)+1); + v_set_text(FAIL,0,BLACK,0x00,0,NULL); + }else + (*v_mtext)(x_handle,x,y,(*ptr++)+1); + } + } + return(0); +} - Fch= chardim[3] ? chardim[3] : 1; - start_line /= Fch; - y+=start_line*Fch; +static int draw_rip(PARMBLK *pb){ + GRECT area=*(GRECT *) &pb->pb_x; + if(rc_intersect((GRECT *)&pb->pb_xc,&area)){ + char **ptr; + int x=pb->pb_x,y=pb->pb_y,start_line=(area.g_y-y), chardim[4], pla[8],i; + v_set_mode(MD_REPLACE); +/* void v_set_text(int font,int height,int color,int effect,int rotate,int out[4]) */ + v_set_text(text_font.id,text_font.size,BLACK,0,0,chardim); + start_line /= text_font.ch; + y+=start_line*text_font.ch; x-=scroll_menu.px_hpos; ptr=&text_lines[start_line+=scroll_menu.vpos]; - start_line = min((area.g_y-y+area.g_h+Fch-1)/Fch,Anz_text_lines-start_line); - area.g_h=Fch; + start_line = min((area.g_y-y+area.g_h+text_font.ch-1)/text_font.ch,Anz_text_lines-start_line); + area.g_h=text_font.ch; Vsync(); - for(;--start_line>=0;y+=Fch){ + x=(x+7) & ~7; + for(;--start_line>=0;y+=text_font.ch){ area.g_y=y; my_clear_area(&area); if(**ptr-1){ v_set_text(FAIL,0,BLUE,0x01,0,NULL); - v_gtext(x_handle,x,y,(*ptr++)+1); + (*v_mtext)(x_handle,x,y,(*ptr++)+1); v_set_text(FAIL,0,BLACK,0x00,0,NULL); }else - v_gtext(x_handle,x,y,(*ptr++)+1); - + (*v_mtext)(x_handle,x,y,(*ptr++)+1); + } + pla[0]=pla[1]=0; + pla[2]=min(pb->pb_w-1,Rip_bild.fd_w-1); + pla[3]=min(pb->pb_h-1,Rip_bild.fd_h-1); + pla[6]=pla[4]=pb->pb_x+(pb->pb_w-Rip_bild.fd_w)/2; /* x_wert to */ + pla[7]=pla[5]=pb->pb_y; /* y_wert to */ + pla[6]+=pla[2]; + pla[7]+=pla[3]; + vro_cpyfm(x_handle, S_ONLY, pla, &Rip_bild, screen); + v_set_mode(MD_TRANS); + vst_alignment(x_handle,1,5,&i,&i); + pla[5]+=64; + for(i=0;i<7;i++,pla[5]+=chardim[3]){ + v_set_text(text_font.id,(i==0 || i==6) ? text_font.size : 12,WHITE,1,0,chardim); + (*v_mtext)(x_handle,pla[4]+157,pla[5],rip_line[i]); + v_set_text(text_font.id,(i==0 || i==6) ? text_font.size : 12,BLACK,0,0,chardim); + (*v_mtext)(x_handle,pla[4]+157,pla[5],rip_line[i]); } + vst_alignment(x_handle,0,5,&i,&i); } return(0); } @@ -413,27 +698,32 @@ static int draw_msgline(PARMBLK *pb){ GRECT area=*(GRECT *) &pb->pb_x; if(rc_intersect((GRECT *)&pb->pb_xc,&area)){ - int x=pb->pb_x, y=pb->pb_y+2*Fch, foo, i; - char **ptr=&message_line[msg_pos]; + int x=pb->pb_x, y=pb->pb_y+(msg_vis-1)*msg_font.ch, foo, i; + char **ptr=&message_line[msg_pos], tmp; + int startx, stopx, starty, stopy; x=(x+7) & ~7; /* Byte alignment speeds output up */ v_set_mode(MD_REPLACE); /* void v_set_text(int font,int height,int color,int effect,int rotate,int out[4]) */ - v_set_text(ibm_font_id,ibm_font,FAIL, FAIL,0,NULL); + v_set_text(msg_font.id,msg_font.size,FAIL, FAIL,0,NULL); vst_alignment(x_handle,0,5,&foo,&foo); - foo=min(msg_pos,3); -/* area.g_h=Fch;*/ - Vsync(); - for(i=0;ipb_x; + area.g_x+=2*status_font.cw-2; + area.g_w-=2*status_font.cw-2; if(rc_intersect((GRECT *)&pb->pb_xc,&area)){ - char **ptr=status_line; - int x=pb->pb_x, y=pb->pb_y, chardim[4], h; + int x=pb->pb_x, y=pb->pb_y, startx, stopx, starty, stopy, i; + char tmp; /* void v_set_text(int font,int height,int color,int effect,int rotate,int out[4]) */ v_set_mode(MD_REPLACE); - if(max_w/Fcw>=COLNO-1) - v_set_text(ibm_font_id,ibm_font,BLACK,0,0,chardim); - else - v_set_text(small_font_id,small_font,BLACK,0,0,chardim); - h=chardim[3] ? chardim[3] : 1; - x+=2*chardim[2]; - - Vsync(); + v_set_text(status_font.id,status_font.size,BLACK,0,0,NULL); + x = (x+2*status_font.cw+6) & ~7; + + startx=(area.g_x-x)/status_font.cw; + starty=(area.g_y-y)/status_font.ch; + stopx=(area.g_x+area.g_w+status_font.ch-1-x)/status_font.cw; + stopy=(area.g_y+area.g_h+status_font.ch-1-y)/status_font.ch; + Max(&startx,0); /* MAR -- Hmm, area.g_x could end up 1 below x */ + Max(&stopx,0); + x+=startx*status_font.cw; + y+=starty*status_font.ch; +/* Vsync();*/ + area.g_h=status_font.ch; + for(i=starty;i=0 && it; it=it->Gmi_next); - i = min((area.g_y-y+area.g_h+Fch-1)/Fch,Anz_inv_lines-start_line); + i = min((area.g_y-y+area.g_h+menu_font.ch-1)/menu_font.ch,Anz_inv_lines-start_line); Vsync(); - area.g_h=Fch; + area.g_h=menu_font.ch; - for(;(--i>=0) && it;it=it->Gmi_next,y+=Fch){ + for(;(--i>=0) && it;it=it->Gmi_next,y+=menu_font.ch){ if(it->Gmi_attr) v_set_text(FAIL,FALSE,BLUE,1,FAIL,NULL); /* Bold */ else @@ -494,22 +795,22 @@ static int draw_inventory(PARMBLK *pb){ area.g_y=y; my_clear_area(&area); if((gl=it->Gmi_glyph) != no_glyph){ - int pla[8], h=min(Fch,16)-1; + int pla[8], h=min(menu_font.ch,Tile_heigth)-1; - pla[0]=pla[2]=(gl%20)*16; /* x_wert from */ - pla[1]=pla[3]=(gl/20)*16; /* y_wert from */ + pla[0]=pla[2]=(gl%Tiles_per_line)*Tile_width; /* x_wert from */ + pla[1]=pla[3]=(gl/Tiles_per_line)*Tile_heigth; /* y_wert from */ pla[4]=pla[6]=x; /* x_wert to */ pla[5]=pla[7]=y; /* y_wert to */ - pla[2]+=15; + pla[2]+=Tile_width-1; pla[3]+=h; - pla[6]+=15; + pla[6]+=Tile_heigth-1; pla[7]+=h; vro_cpyfm(x_handle,S_ONLY,pla,&Tile_bilder,screen); } if(it->Gmi_identifier) it->Gmi_str[2]=it->Gmi_selected ? (it->Gmi_count == -1L ? '+' : '#') : '-'; - v_gtext(x_handle,x+16,y,it->Gmi_str); + (*v_mtext)(x_handle,(x+23) & ~7,y,it->Gmi_str); } } return(0); @@ -520,23 +821,22 @@ static int draw_prompt(PARMBLK *pb){ if(rc_intersect((GRECT *)&pb->pb_xc,&area)){ char **ptr=(char **)pb->pb_parm; - int x=pb->pb_x, y=pb->pb_y, chardim[4], h; + int x=pb->pb_x, y=pb->pb_y, chardim[4]; /* void v_set_text(int font,int height,int color,int effect,int rotate,int out[4]) */ v_set_mode(MD_TRANS); - v_set_text(ibm_font_id,ibm_font,WHITE,0,0,NULL); + v_set_text(ibm_font_id,ibm_font,WHITE,0,0,chardim); Vsync(); if(planes<4){ int pxy[4]; - v_set_fill(BLACK,2,4,0); rc_grect_to_array(&area,pxy); v_bar(x_handle,pxy); }else my_color_area(&area,LWHITE); - v_gtext(x_handle,x,y,*(ptr++)); + (*v_mtext)(x_handle,x,y,*(ptr++)); if(*ptr) - v_gtext(x_handle,x,y+Fch,*ptr); + (*v_mtext)(x_handle,x,y+chardim[3],*ptr); } return(0); } @@ -606,7 +906,6 @@ mar_set_dir_keys() if(mi_numpad!=mar_iflags_numpad()){ OBJECT *z_ob=zz_oblist[DIRECTION]; int i; - mi_numpad=mar_iflags_numpad(); ob_set_hotkey(z_ob,DIRDOWN,'>'); ob_set_hotkey(z_ob,DIRUP,'<'); @@ -619,7 +918,8 @@ mar_set_dir_keys() int mar_gem_init() { - int i, bild_fehler=FALSE, chardim[4]; + int i, bild_fehler=FALSE, fsize; + char *fname; static MITEM wish_workaround= {FAIL,key(0,'J'),K_CTRL,W_CYCLE,FAIL}; OBJECT *z_ob; @@ -637,6 +937,8 @@ mar_gem_init() } MouseBee(); + /* MAR -- 17.Mar 2002 NVDI 3.0 or better uses v_ftext */ + v_mtext= speedo==3 ? &v_ftext : &v_gtext; for(i=0;i=COLNO-1){ - status_w=msg_width; - StFch=Fch; - StFcw=Fcw; - }else{ - v_set_text(small_font_id,small_font,BLACK,0,0,chardim); - StFch=chardim[3] ? chardim[3] : 1; - StFcw=chardim[2] ? chardim[2] : 1; - status_w=min(max_w/StFcw-3,100); - } + mar_set_msg_visible(mar_get_msg_visible()); + msg_width=min(max_w/msg_font.cw-3,MSGLEN); + if(max_w/status_font.cw0 && planes<9) normal_palette=(short *)m_alloc(3*colors*sizeof(short)); get_colors(x_handle,normal_palette, colors); if(planes<4){ - bild_fehler=depack_img("NH2.IMG",&tile_image); + bild_fehler=depack_img(Tilefile?Tilefile:"NH2.IMG",&tile_image); }else{ - bild_fehler=depack_img("NH16.IMG",&tile_image); + bild_fehler=depack_img(Tilefile?Tilefile:"NH16.IMG",&tile_image); if(!bild_fehler) - img_set_colors(x_handle, tile_image.palette, tile_image.planes); + if(tile_image.planes>1) + img_set_colors(x_handle, tile_image.palette, tile_image.planes); +#if 0 + else{ + int mypalette[]={}; + img_set_colors(x_handle, mypalette, 4); + } +#endif } if(bild_fehler ){ @@ -682,13 +992,15 @@ mar_gem_init() mfdb(&Tile_bilder, (int *)tile_image.addr, tile_image.img_w, tile_image.img_h, 1, tile_image.planes); transform_img(&Tile_bilder); - mfdb(&Map_bild,NULL,COLNO*16, ROWNO*16, 0, planes); - Map_bild.fd_addr=(int *)m_alloc(mfdb_size(&Map_bild)); + mfdb(&Map_bild,NULL,(COLNO-1)*Tile_width, ROWNO*Tile_heigth, 0, planes); + mfdb(&FontCol_Bild,NULL,(COLNO-1)*map_font.cw, ROWNO*map_font.ch, 0, planes); + Map_bild.fd_addr=(int *)m_alloc(mfdb_size(&Map_bild)>mfdb_size(&FontCol_Bild)?mfdb_size(&Map_bild):mfdb_size(&FontCol_Bild)); + FontCol_Bild.fd_addr=Map_bild.fd_addr; mfdb(&Pet_Mark,pet_mark_data,8, 7, 1, 1); vr_trnfm(x_handle,&Pet_Mark,&Pet_Mark); - mfdb(&Black_bild,NULL,8, 16, 1, 1); + mfdb(&Black_bild,NULL,16, 32, 1, 1); /* MAR -- 17.Mar 2002 that should cover the biggest map-font */ Black_bild.fd_addr=(int *)m_alloc(mfdb_size(&Black_bild)); memset(Black_bild.fd_addr,255,mfdb_size(&Black_bild)); vr_trnfm(x_handle,&Black_bild,&Black_bild); @@ -702,20 +1014,20 @@ mar_gem_init() memset(&scroll_menu,0,sizeof(scroll_menu)); scroll_menu.scroll=AUTO_SCROLL; scroll_menu.obj=LINESLIST; - scroll_menu.px_hline=Fcw; - scroll_menu.px_vline=Fch; + scroll_menu.px_hline=menu_font.cw; + scroll_menu.px_vline=menu_font.ch; scroll_menu.hscroll= scroll_menu.vscroll=1; - scroll_menu.tbar_d=2*Fch-2; + scroll_menu.tbar_d=2*gr_ch-2; mar_set_dir_keys(); memset(&scroll_map,0,sizeof(scroll_map)); scroll_map.scroll=AUTO_SCROLL; scroll_map.obj=ROOT; - scroll_map.px_hline=16; /* width of Cell 8 char or 16 tile */ - scroll_map.px_vline=16; /* height of Cell always 16 */ - scroll_map.hsize=COLNO; + scroll_map.px_hline=mar_set_tile_mode(FAIL)?Tile_width:map_font.cw; + scroll_map.px_vline=mar_set_tile_mode(FAIL)?Tile_heigth:map_font.ch; + scroll_map.hsize=COLNO-1; scroll_map.vsize=ROWNO; scroll_map.hpage=8; scroll_map.vpage=8; @@ -760,7 +1072,7 @@ mar_exit_nhwindows() mar_destroy_nhwindow(i); if(normal_palette){ - img_set_colors(x_handle,normal_palette,planes); + img_set_colors(x_handle,normal_palette,tile_image.planes); null_free(normal_palette); } test_free(tile_image.palette); @@ -791,9 +1103,11 @@ int x, y; Gem_nhwindow[WIN_MAP].gw_dirty=TRUE; } +void mar_cliparound(void); void mar_map_curs_weiter(void) { mar_curs(map_cursx+1,map_cursy); + mar_cliparound(); } /************************* about *******************************/ @@ -921,7 +1235,7 @@ mar_more() dial_colors(7,RED,BLACK,RED,RED,BLACK,BLACK,BLACK,BLACK,WHITE,WHITE,WHITE,WHITE,TRUE,TRUE); if(WIN_MESSAGE!=WIN_ERR && (p_w=Gem_nhwindow[WIN_MESSAGE].gw_window)){ z_ob->ob_x=p_w->work.g_x; - z_ob->ob_y=p_w->curr.g_y+p_w->curr.g_h+Fch; + z_ob->ob_y=p_w->curr.g_y+p_w->curr.g_h+gr_ch; } xdialog(z_ob,NULL, NULL, NULL, DIA_LASTPOS, FALSE, DIALOG_MODE); Event_Timer(0,0,TRUE); @@ -988,7 +1302,10 @@ mar_set_accelerators() Gem_menu_item *curr; for(curr=invent_list;curr;curr=curr->Gmi_next){ - Max(&Inv_breite,Fcw*(strlen(curr->Gmi_str)+1)+16); + int extent[8]; + v_set_text(menu_font.id,menu_font.size,BLACK,0,0,NULL); + vqt_extent(x_handle,curr->Gmi_str,extent); + Max(&Inv_breite,extent[4]+Tile_width+menu_font.cw); if(ch && curr->Gmi_accelerator==0 && curr->Gmi_identifier){ curr->Gmi_accelerator=ch; curr->Gmi_str[0]=ch; @@ -1009,6 +1326,9 @@ mar_hol_inv() void mar_raw_print(const char *); +void mar_set_text_to_rip(winid w){ + use_rip=TRUE; +} void mar_putstr_text(winid window, int attr, const char *str) { @@ -1027,6 +1347,7 @@ mar_putstr_text(winid window, int attr, const char *str) } if(!text_lines){ mar_raw_print("No room for Text"); + return; } if(str) @@ -1047,24 +1368,25 @@ int Anzahl, Breite; OBJECT *z_ob=zz_oblist[LINES]; int retval=WIN_DIAL|MODAL|NO_ICONIFY; - scroll_menu.vpage= (desk.g_h-3*Fch)/Fch; + scroll_menu.hsize=0; + scroll_menu.vpage= (desk.g_h-3*gr_ch)/scroll_menu.px_vline; if(Anzahl>scroll_menu.vpage){ retval |= WD_VSLIDER; - if(Breite>max_w-3*Fcw){ + if(Breite>max_w-3*scroll_menu.px_hline){ retval|=WD_HSLIDER; - scroll_menu.hpage=(max_w-3*Fcw)/Fcw; + scroll_menu.hpage=(max_w-3*scroll_menu.px_hline)/scroll_menu.px_hline; scroll_menu.hpos=0; - scroll_menu.hsize=Breite/Fcw; - scroll_menu.vpage=(desk.g_h-4*Fch-1)/Fch; + scroll_menu.hsize=Breite/scroll_menu.px_hline; + scroll_menu.vpage=(desk.g_h-4*gr_ch-1)/scroll_menu.px_vline; } Anzahl=scroll_menu.vpage; }else{ - if(Breite>max_w-Fcw){ + if(Breite>max_w-scroll_menu.px_hline){ retval|=WD_HSLIDER; - scroll_menu.hpage=(max_w-Fcw)/Fcw; + scroll_menu.hpage=(max_w-scroll_menu.px_hline)/scroll_menu.px_hline; scroll_menu.hpos=0; - scroll_menu.hsize=Breite/Fcw; - scroll_menu.vpage= (desk.g_h-4*Fch-1)/Fch; + scroll_menu.hsize=Breite/scroll_menu.px_hline; + scroll_menu.vpage= (desk.g_h-4*gr_ch-1)/scroll_menu.px_vline; if(Anzahl>scroll_menu.vpage){ retval |= WD_VSLIDER; Anzahl=scroll_menu.vpage; @@ -1077,14 +1399,14 @@ int Anzahl, Breite; if((scroll_menu.vmax=scroll_menu.vsize-scroll_menu.vpage)<0) scroll_menu.vmax=0; - /* left/right/up 2 pixel border down 2Fch toolbar */ + /* left/right/up 2 pixel border down 2gr_ch toolbar */ z_ob[ROOT].ob_width=z_ob[LINESLIST].ob_width=Breite; z_ob[ROOT].ob_height= z_ob[QLINE].ob_y= - z_ob[LINESLIST].ob_height=Fch*Anzahl; - z_ob[QLINE].ob_y+=Fch/2; + z_ob[LINESLIST].ob_height=scroll_menu.px_vline*Anzahl; + z_ob[QLINE].ob_y+=gr_ch/2; z_ob[ROOT].ob_width+=4; - z_ob[ROOT].ob_height+=2*Fch+2; + z_ob[ROOT].ob_height+=2*gr_ch+2; return(retval); } @@ -1096,9 +1418,6 @@ mar_status_dirty() { int ccol; - if(WIN_STATUS != WIN_ERR) - Gem_nhwindow[WIN_STATUS].gw_dirty=TRUE; - ccol=mar_hp_query(); if(ccol<2) curs_col=WHITE; /* 50-100% : 0 */ @@ -1155,7 +1474,7 @@ const char *str; rest=strcpy(buf,toplines+pos); }else{ message_age[msg_max]=TRUE; - strcpy(message_line[msg_max],toplines); + strncpy(message_line[msg_max],toplines,msg_width); rest=0; } @@ -1176,8 +1495,29 @@ mar_add_status_str(str,line) const char *str; int line; { - strncpy(status_line[line],str,status_w-1); - status_line[line][status_w-1]='\0'; + int i,last_diff=-1; + GRECT area={0,line*status_font.ch,status_font.cw,status_font.ch}; + for(i=0;(i=0){ + add_dirty_rect(dr_stat,&area); + last_diff=-1; + area.g_w=status_font.cw; + } + for(;i=0) + add_dirty_rect(dr_stat,&area); } /************************* mar_set_menu_title *******************************/ @@ -1288,7 +1628,7 @@ int scroll_top_dialog(char ch){ return(FALSE); } -#define Text_Init K_Init +#define Text_Init KM_Init int Text_Handler(xev) @@ -1296,6 +1636,15 @@ XEVENT *xev; { int ev=xev->ev_mwich; + if(ev&MU_MESAG){ + int *buf=xev->ev_mmgpbuf, y_wo, i; + if(*buf==FONT_CHANGED){ + if(buf[3]>=0){ + mar_set_fontbyid(NHW_TEXT,buf[4],buf[5]); + FontAck(buf[1],1); + } + } + } if(ev&MU_KEYBD){ char ch=(char)(xev->ev_mkreturn&0x00FF); @@ -1304,6 +1653,9 @@ XEVENT *xev; case '\033': send_return(); /* just closes the textwin */ break; + case C('c'): + clipbrd_save(text_lines,Anz_text_lines,xev->ev_mmokstate&K_SHIFT,FALSE); + break; default: ev &= ~MU_KEYBD; /* unknown key */ break; @@ -1314,6 +1666,7 @@ XEVENT *xev; #define Inv_Init KM_Init +static long count=0; int Inv_Handler(xev) XEVENT *xev; @@ -1321,30 +1674,35 @@ XEVENT *xev; int ev=xev->ev_mwich; Gem_menu_item *it; GRECT area; - static long count=0; OBJECT *z_ob=zz_oblist[LINES]; ob_pos(z_ob,LINESLIST,&area); - if(ev&MU_MESAG){ int *buf=xev->ev_mmgpbuf, y_wo, i; + if(*buf==FONT_CHANGED){ + if(buf[3]>=0){ + mar_set_fontbyid(NHW_MENU,buf[4],buf[5]); + FontAck(buf[1],1); + } + }else if(*buf==OBJC_CHANGED && buf[3]==LINESLIST){ ob_undostate(z_ob,LINESLIST,SELECTED); mouse(NULL,&y_wo); - y_wo=(y_wo-area.g_y)/Fch+scroll_menu.vpos; + y_wo=(y_wo-area.g_y)/menu_font.ch+scroll_menu.vpos; for(it=invent_list,i=0;iGmi_next,i++); if(it->Gmi_identifier){ it->Gmi_selected=!it->Gmi_selected; it->Gmi_count= count==0L ? -1L : count; count = 0L; - if(Inv_how!=PICK_ANY) - my_close_dialog(Inv_dialog,TRUE); - else{ - area.g_x+=16+2*Fcw; - area.g_w=Fcw; - area.g_h=Fch; - area.g_y+=(y_wo-scroll_menu.vpos)*Fch; + if(Inv_how!=PICK_ANY){ + /*my_close_dialog(Inv_dialog,TRUE);*/ + send_return(); + }else{ + area.g_x=(area.g_x+23+2*menu_font.cw) & ~7; + area.g_w=menu_font.cw; + area.g_h=menu_font.ch; + area.g_y+=(y_wo-scroll_menu.vpos)*menu_font.ch; ob_draw_chg(Inv_dialog,LINESLIST,&area,FAIL); } /* how != PICK_ANY */ } /* identifier */ @@ -1412,7 +1770,6 @@ XEVENT *xev; case MENU_SEARCH: if(Inv_how!=PICK_NONE){ char buf[BUFSZ]; - Gem_getlin("Search for:",buf); if(!*buf || buf[0]=='\033') break; @@ -1427,24 +1784,28 @@ XEVENT *xev; } } break; + case C('c'): + clipbrd_save(invent_list,Anz_inv_lines,xev->ev_mmokstate&K_SHIFT,TRUE); + break; default: find_acc: if(Inv_how==PICK_NONE) my_close_dialog(Inv_dialog,TRUE); - for(it=invent_list;it;it=it->Gmi_next){ - if(it->Gmi_identifier && (it->Gmi_accelerator==ch || it->Gmi_groupacc==ch)){ - it->Gmi_selected=!it->Gmi_selected; - it->Gmi_count= count==0L ? -1L : count; - count = 0L; - if(Inv_how!=PICK_ANY) - my_close_dialog(Inv_dialog,TRUE); + else + for(it=invent_list;it;it=it->Gmi_next){ + if(it->Gmi_identifier && (it->Gmi_accelerator==ch || it->Gmi_groupacc==ch)){ + it->Gmi_selected=!it->Gmi_selected; + it->Gmi_count= count==0L ? -1L : count; + count = 0L; + if(Inv_how!=PICK_ANY) + my_close_dialog(Inv_dialog,TRUE); + } } - } break; } /* end switch(ch) */ if(Inv_how==PICK_ANY){ - area.g_x+=16+2*Fcw; - area.g_w=Fcw; + area.g_x=(area.g_x+23+2*menu_font.cw) & ~7; + area.g_w=menu_font.cw; ob_draw_chg(Inv_dialog,LINESLIST,&area,FAIL); } } /* !scroll_Inv_dialog */ @@ -1485,6 +1846,11 @@ GRECT *area; /************************* mar_display_nhwindow *******************************/ +void redraw_winwork(WIN *w,GRECT *area){ + area->g_x+=w->work.g_x; + area->g_y+=w->work.g_y; + redraw_window(w,area); +} void mar_menu_set_slider(WIN *p_win){ if(p_win){ SCROLL *sc=p_win->scroll; @@ -1513,45 +1879,73 @@ void mar_menu_set_slider(WIN *p_win){ } } +void recalc_msg_win(GRECT *area){ + OBJECT *z_ob; + z_ob=zz_oblist[MSGWIN]; + z_ob[MSGLINES].ob_spec.userblk=&ub_msg; + z_ob[MSGLINES].ob_width= + z_ob[ROOT].ob_width= (msg_width+3)*msg_font.cw; + z_ob[MSGLINES].ob_width-=z_ob[UPMSG].ob_width; + z_ob[ROOT].ob_height= + z_ob[GRABMSGWIN].ob_height= + z_ob[MSGLINES].ob_height=msg_vis*msg_font.ch; + z_ob[DNMSG].ob_y=z_ob[GRABMSGWIN].ob_height-z_ob[DNMSG].ob_height; + window_border(0,0,0,z_ob->ob_width,z_ob->ob_height, area); +} +void recalc_status_win(GRECT *area){ + OBJECT *z_ob; + z_ob=zz_oblist[STATUSLINE]; + z_ob[ROOT].ob_type=G_USERDEF; + z_ob[ROOT].ob_spec.userblk=&ub_status; + z_ob[ROOT].ob_width=(status_w+2)*status_font.cw; + z_ob[ROOT].ob_height= + z_ob[GRABSTATUS].ob_height=2*status_font.ch; + z_ob[GRABSTATUS].ob_width=2*status_font.cw-2; + window_border(0,0,0,z_ob->ob_width,z_ob->ob_height,area); +} void calc_std_winplace(int which, GRECT *place){ static int todo=TRUE; static GRECT me, ma, st; - if(todo){ + if(todo || which<0){ OBJECT *z_ob; int map_h_off, foo; /* First the messagewin */ - z_ob=zz_oblist[MSGWIN]; - z_ob[MSGLINES].ob_spec.userblk=&ub_msg; - z_ob[MSGLINES].ob_width= - z_ob[ROOT].ob_width= (msg_width+3)*Fcw; - z_ob[MSGLINES].ob_width-=z_ob[UPMSG].ob_width; - window_border(0,0,0,z_ob->ob_width,z_ob->ob_height, &me); + recalc_msg_win(&me); /* Now the map */ - wind_calc(WC_BORDER,MAP_GADGETS,0,0,16*COLNO,16*ROWNO,&foo,&foo,&foo,&map_h_off); - map_h_off-=16*ROWNO; - window_border(MAP_GADGETS,0,0,16*COLNO,16*ROWNO, &ma); - ma.g_y=desk.g_y+me.g_h; + wind_calc(WC_BORDER,MAP_GADGETS,0,0,scroll_map.px_hline*(COLNO-1),scroll_map.px_vline*ROWNO,&foo,&foo,&foo,&map_h_off); + map_h_off-=scroll_map.px_vline*ROWNO; + window_border(MAP_GADGETS,0,0,scroll_map.px_hline*(COLNO-1),scroll_map.px_vline*ROWNO, &ma); /* Next the statuswin */ - z_ob=zz_oblist[STATUSLINE]; - z_ob[ROOT].ob_type=G_USERDEF; - z_ob[ROOT].ob_spec.userblk=&ub_status; - z_ob[ROOT].ob_width=(status_w+2)*StFcw; - z_ob[ROOT].ob_height= - z_ob[GRABSTATUS].ob_height=2*StFch; - z_ob[GRABSTATUS].ob_width=2*StFcw-2; - window_border(0,0,0,z_ob->ob_width,z_ob->ob_height,&st); + recalc_status_win(&st); /* And last but not least a final test */ - ma.g_h=map_h_off+16*ROWNO; + ma.g_h=map_h_off+scroll_map.px_vline*ROWNO; while(me.g_h+ma.g_h+st.g_h>=desk.g_h) - ma.g_h-=16; - st.g_y=desk.g_y+me.g_h+ma.g_h; + ma.g_h-=scroll_map.px_vline; + /* stack the windows */ + ma.g_y=me.g_y=st.g_y=desk.g_y; + if(status_align){ + ma.g_y+=st.g_h; + if(msg_align){ + st.g_y+=me.g_h; + ma.g_y+=me.g_h; + }else{ + me.g_y+=st.g_h+ma.g_h; + } + }else{ + if(msg_align){ + ma.g_y+=me.g_h; + }else{ + me.g_y+=ma.g_h; + } + st.g_y+=me.g_h+ma.g_h; + } - todo=FALSE; + if(which) todo=FALSE; } switch(which){ case NHW_MESSAGE: @@ -1589,14 +1983,28 @@ winid wind; z_ob=zz_oblist[LINES]; scroll_menu.vsize=Anz_text_lines; scroll_menu.vpos=0; + if(use_rip){ + if(!depack_img(planes<4 ? "RIP2.IMG" : "RIP.IMG", &rip_image)){ + mfdb(&Rip_bild, (int *)rip_image.addr, rip_image.img_w, rip_image.img_h, 1, rip_image.planes); + transform_img(&Rip_bild); + } + ub_lines.ub_code=draw_rip; + }else + ub_lines.ub_code=draw_lines; z_ob[LINESLIST].ob_spec.userblk=&ub_lines; breite=16; - for(i=0;idi_win; @@ -1621,11 +2029,13 @@ winid wind; scroll_menu.vpos=0; z_ob[LINESLIST].ob_spec.userblk=&ub_inventory; if((Menu_title)&&(wind!=WIN_INVEN)) /* because I sets no Menu_title */ - Max(&Inv_breite,Fcw*strlen(Menu_title)+16); - mar_di_mode=mar_set_inv_win(Anz_inv_lines, Inv_breite); + Max(&Inv_breite,gr_cw*strlen(Menu_title)+16); + scroll_menu.px_vline=menu_font.ch; + scroll_menu.px_hline=menu_font.cw; + mar_di_mode=mar_set_inv_win(Anz_inv_lines, Inv_breite, NHW_MENU); tmp_button=ob_get_text(z_ob,QLINE,0); ob_set_text(z_ob,QLINE,Inv_how!=PICK_NONE ? strCancel : strOk ); - ob_doflag(z_ob,LINESLIST,SELECTABLE); + ob_doflag(z_ob,LINESLIST,TOUCHEXIT); Event_Handler(Inv_Init, Inv_Handler); if((Inv_dialog=open_dialog(z_ob,(wind==WIN_INVEN) ? "Inventory" : (Menu_title ? Menu_title : "Staun"), NULL, NULL, mar_ob_mapcenter(z_ob), FALSE, mar_di_mode, FAIL, NULL, NULL))!=NULL){ WIN *ptr_win=Inv_dialog->di_win; @@ -1633,7 +2043,43 @@ winid wind; ptr_win->scroll=&scroll_menu; mar_menu_set_slider(ptr_win); WindowItems(ptr_win,SCROLL_KEYS,scroll_keys); - if((d_exit=X_Form_Do(NULL))!=W_ABANDON){ + do{ + int y_wo,x_wo,ru_w=1,ru_h=1; + GRECT oarea; + Gem_menu_item *it; + d_exit=X_Form_Do(NULL); + if((d_exit&NO_CLICK)==LINESLIST){ + ob_pos(z_ob,LINESLIST,&oarea); + if(mouse(&x_wo,&y_wo) && Inv_how==PICK_ANY){ + graf_rt_rubberbox(FALSE,x_wo,y_wo,FAIL,FAIL,&oarea,&ru_w,&ru_h,NULL); + invert_all_on_page((int)((y_wo-oarea.g_y)/menu_font.ch+scroll_menu.vpos),(ru_h+menu_font.ch-1)/menu_font.ch,0); + }else{ + for(it=invent_list,i=0;i<((y_wo-oarea.g_y)/menu_font.ch+scroll_menu.vpos) && it;it=it->Gmi_next,i++); + if(it && it->Gmi_identifier){ + it->Gmi_selected=!it->Gmi_selected; + it->Gmi_count= count==0L ? -1L : count; + count = 0L; + if(Inv_how!=PICK_ANY) + break; + } /* identifier */ + } + oarea.g_x=(oarea.g_x+23+2*menu_font.cw) & ~7; + oarea.g_y=y_wo-(y_wo-oarea.g_y)%menu_font.ch; + oarea.g_w=menu_font.cw; + oarea.g_h=((ru_h+menu_font.ch-1)/menu_font.ch)*menu_font.ch; + ob_draw_chg(Inv_dialog,LINESLIST,&oarea,FAIL); + } + if(Inv_how==PICK_ANY){ + ob_set_text(Inv_dialog->di_tree,QLINE,strCancel); + for(it=invent_list;it;it=it->Gmi_next) + if(it->Gmi_identifier && it->Gmi_selected){ + ob_set_text(Inv_dialog->di_tree,QLINE,strOk); + break; + } + ob_draw_chg(Inv_dialog,QLINE,NULL,FAIL); + } + }while((d_exit&NO_CLICK)==LINESLIST); + if(d_exit!=W_ABANDON){ my_close_dialog(Inv_dialog,FALSE); if(d_exit!=W_CLOSED) ob_undostate(z_ob,d_exit&NO_CLICK,SELECTED); @@ -1645,7 +2091,7 @@ winid wind; case NHW_MAP: if(p_Gw->gw_window==NULL){ calc_std_winplace(NHW_MAP,&p_Gw->gw_place); - window_border(MAP_GADGETS,0,0,16*COLNO,16*ROWNO, &g_mapmax); + window_border(MAP_GADGETS,0,0,Tile_width*(COLNO-1),Tile_heigth*ROWNO, &g_mapmax); p_Gw->gw_window=open_window(md, md, NULL, zz_oblist[NHICON], MAP_GADGETS, TRUE, 128, 128, &g_mapmax, &p_Gw->gw_place, &scroll_map, win_draw_map, NULL, XM_TOP|XM_BOTTOM|XM_SIZE); WindowItems(p_Gw->gw_window,SCROLL_KEYS-1,scroll_keys); /* ClrHome centers on u */ mar_clear_map(); @@ -1658,7 +2104,7 @@ winid wind; redraw_window(p_Gw->gw_window,&area); - dirty_map_area.g_x=COLNO; + dirty_map_area.g_x=COLNO-1; dirty_map_area.g_y=ROWNO; dirty_map_area.g_w= dirty_map_area.g_h=0; @@ -1672,19 +2118,21 @@ winid wind; p_Gw->gw_window=open_window(NULL, NULL, NULL, NULL, 0, 0, 0, 0, NULL, &p_Gw->gw_place, NULL, mar_draw_window, z_ob, XM_TOP|XM_BOTTOM|XM_SIZE); magx=tmp_magx; window_size(p_Gw->gw_window,&p_Gw->gw_window->curr); + p_Gw->gw_dirty=TRUE; } if(p_Gw->gw_dirty){ + ob_pos(zz_oblist[MSGWIN],MSGLINES,&area); while(messages_pro_zug>3){ messages_pro_zug-=3; msg_pos+=3; - redraw_window(p_Gw->gw_window,NULL); + redraw_window(p_Gw->gw_window,&area); mar_more(); } msg_pos+=messages_pro_zug; messages_pro_zug=0; if(msg_pos>msg_max) msg_pos=msg_max; - redraw_window(p_Gw->gw_window,NULL); + redraw_window(p_Gw->gw_window,&area); mar_message_pause=FALSE; } break; @@ -1695,11 +2143,17 @@ winid wind; magx=0; /* MAR -- Fake E_GEM to remove Backdropper */ p_Gw->gw_window=open_window(NULL, NULL, NULL, NULL, 0, FALSE, 0, 0, NULL, &p_Gw->gw_place, NULL, mar_draw_window, z_ob, XM_TOP|XM_BOTTOM|XM_SIZE); magx=tmp_magx; - /* Because 2*StFch is smaller then e_gem expects the minimum win_height */ + /* Because 2*status_font.ch is smaller then e_gem expects the minimum win_height */ p_Gw->gw_window->min_h=z_ob[ROOT].ob_height; window_size(p_Gw->gw_window,&p_Gw->gw_place); + p_Gw->gw_dirty=TRUE; + } + while(get_dirty_rect(dr_stat,&area)){ + area.g_x=(area.g_x+p_Gw->gw_window->work.g_x+2*status_font.cw+6)&~7; + area.g_y+=p_Gw->gw_window->work.g_y; + redraw_window(p_Gw->gw_window,&area); } - /* Fall thru */ + break; default: if(p_Gw->gw_dirty) redraw_window(p_Gw->gw_window,NULL); @@ -1732,23 +2186,29 @@ int type; message_age=(int *)m_alloc(msg_anz*sizeof(int)); for(i=0;i0 ? scroll_margin : max(scroll_map.hpage/4,1), + hoehe=scroll_margin>0 ? scroll_margin : max(scroll_map.vpage/4,1), + adjust_needed; adjust_needed=FALSE; if ((map_cursx < scroll_map.hpos + breite) || (map_cursx >= scroll_map.hpos + scroll_map.hpage - breite)){ - scroll_map.hpos=map_cursx - 2*breite; + scroll_map.hpos=map_cursx - scroll_map.hpage/2; adjust_needed=TRUE; } - if ((map_cursy < scroll_map.vpos + hoehe) || (map_cursy >= scroll_map.vpos + scroll_map.vpage - hoehe)){ - scroll_map.vpos=map_cursy - 2*hoehe; + scroll_map.vpos=map_cursy - scroll_map.vpage/2; adjust_needed=TRUE; } - if(adjust_needed) scroll_window(Gem_nhwindow[WIN_MAP].gw_window,WIN_SCROLL,NULL); } @@ -1874,6 +2341,9 @@ mar_update_value() mar_display_nhwindow(WIN_MESSAGE); } + if(WIN_MAP!=WIN_ERR) + mar_cliparound(); + if(WIN_STATUS!=WIN_ERR){ mar_check_hilight_status(); mar_display_nhwindow(WIN_STATUS); @@ -1922,9 +2392,14 @@ mar_nh_poskey(x, y, mod) kpad = mar_iflags_numpad()==1 ? numpad : keypad; if (shift & K_SHIFT) ch = kpad[scan - KEYPADLO].shift; - else if (shift & K_CTRL) + else if (shift & K_CTRL){ + if(scan>=0x67 && scan<=0x6f && scan!=0x6b){ + send_key(kpad[scan - KEYPADLO].normal); + ch = 'g'; + }else{ ch = kpad[scan - KEYPADLO].cntrl; - else + } + }else ch = kpad[scan - KEYPADLO].normal; } if(scan==SCANHOME) @@ -1938,6 +2413,10 @@ mar_nh_poskey(x, y, mod) draw_cursor=!draw_cursor; mar_curs(map_cursx,map_cursy); mar_display_nhwindow(WIN_MAP); + }else if(scan == SCANF4){ /* Font-Selector */ + if(!CallFontSelector(0,FAIL,FAIL,FAIL,FAIL)){ + xalert(1,1,X_ICN_ALERT,NULL,SYS_MODAL,BUTTONS_RIGHT,TRUE,"Hello","Fontselector not available!",NULL); + } }else if(!ch && shift&K_CTRL && scan==-57){ /* MAR -- nothing ignore Ctrl-Alt-Clr/Home == MagiC's restore screen */ }else{ @@ -1954,7 +2433,7 @@ mar_nh_poskey(x, y, mod) WIN *akt_win=window_find(ex,ey); if(WIN_MAP != WIN_ERR && akt_win==Gem_nhwindow[WIN_MAP].gw_window){ - *x=max(min((ex-akt_win->work.g_x)/scroll_map.px_hline+scroll_map.hpos,COLNO),0)+1; + *x=max(min((ex-akt_win->work.g_x)/scroll_map.px_hline+scroll_map.hpos,COLNO-1),0)+1; *y=max(min((ey-akt_win->work.g_y)/scroll_map.px_vline+scroll_map.vpos,ROWNO),0); *mod=xev.ev_mmobutton; retval=0; @@ -1997,8 +2476,8 @@ mar_nh_poskey(x, y, mod) break; case '3': draw_cursor=!draw_cursor; - if(WIN_MAP != WIN_ERR && Gem_nhwindow[WIN_MAP].gw_window) - redraw_window(Gem_nhwindow[WIN_MAP].gw_window,NULL); + mar_curs(map_cursx,map_cursy); + mar_display_nhwindow(WIN_MAP); break; default: } @@ -2011,6 +2490,24 @@ mar_nh_poskey(x, y, mod) case WM_CLOSED: WindowHandler(W_ICONIFYALL,NULL,NULL); break; + case AP_TERM: + retval='S'; + break; + case FONT_CHANGED: + if(buf[3]>=0){ + if(buf[3]==Gem_nhwindow[WIN_MESSAGE].gw_window->handle){ + mar_set_fontbyid(NHW_MESSAGE,buf[4],buf[5]); + mar_display_nhwindow(WIN_MESSAGE); + }else if(buf[3]==Gem_nhwindow[WIN_MAP].gw_window->handle){ + mar_set_fontbyid(NHW_MAP,buf[4],buf[5]); + mar_display_nhwindow(WIN_MAP); + }else if(buf[3]==Gem_nhwindow[WIN_STATUS].gw_window->handle){ + mar_set_fontbyid(NHW_STATUS,buf[4],buf[5]); + mar_display_nhwindow(WIN_STATUS); + } + FontAck(buf[1],1); + } + break; default: break; } @@ -2039,10 +2536,12 @@ Gem_delay_output() int Gem_doprev_message() { - if(msg_pos>2) msg_pos--; + if(msg_pos>2){ + msg_pos--; if(WIN_MESSAGE != WIN_ERR) Gem_nhwindow[WIN_MESSAGE].gw_dirty=TRUE; mar_display_nhwindow(WIN_MESSAGE); + } return(0); } @@ -2056,21 +2555,23 @@ int tiles; { static int tile_mode=TRUE; static GRECT prev; - WIN *z_w=Gem_nhwindow[WIN_MAP].gw_window; + WIN *z_w=WIN_MAP!=WIN_ERR ? Gem_nhwindow[WIN_MAP].gw_window : NULL; - if(tiles<0) return(tile_mode); + if(tiles<0) + return(tile_mode); + else if(!z_w) + tile_mode=tiles; + else if(tile_mode==tiles || (mar_set_rogue(FAIL) && tiles)) + return(FAIL); else{ GRECT tmp; - if(tile_mode==tiles || (mar_set_rogue(FAIL) && tiles) || !z_w) - return(FAIL); - tile_mode=tiles; - map_cell_width= tiles ? 16 : Fcw; - scroll_map.px_hline=map_cell_width; - scroll_map.px_vline=tiles ? 16 : Fch; - window_border(MAP_GADGETS,0,0,map_cell_width*COLNO,16*ROWNO, &tmp); + scroll_map.px_hline= tiles ? Tile_width : map_font.cw; + scroll_map.px_vline= tiles ? Tile_heigth : map_font.ch; + window_border(MAP_GADGETS,0,0,scroll_map.px_hline*(COLNO-1),scroll_map.px_vline*ROWNO, &tmp); z_w->max.g_w=tmp.g_w; + z_w->max.g_h=tmp.g_h; if(tiles) z_w->curr=prev; else @@ -2120,33 +2621,26 @@ mar_print_glyph(window, x, y, gl) winid window; int x, y, gl; { + if(window != WIN_ERR && window==WIN_MAP){ static int pla[8]; - if(window != WIN_ERR && window==WIN_MAP){ - Min(&dirty_map_area.g_x,x); - Min(&dirty_map_area.g_y,y); - Max(&dirty_map_area.g_w,x); - Max(&dirty_map_area.g_h,y); - Gem_nhwindow[window].gw_dirty=TRUE; - if(mar_set_tile_mode(FAIL)){ - pla[2]=pla[0]=(gl%20)*16; - pla[3]=pla[1]=(gl/20)*16; - pla[2]+=15; - pla[3]+=15; - pla[6]=pla[4]=16*x; /* x_wert to */ - pla[7]=pla[5]=16*y; /* y_wert to */ - pla[6]+=15; - pla[7]+=15; + pla[2]=pla[0]=(gl%Tiles_per_line)*Tile_width; + pla[3]=pla[1]=(gl/Tiles_per_line)*Tile_heigth; + pla[2]+=Tile_width-1; + pla[3]+=Tile_heigth-1; + pla[6]=pla[4]=Tile_width*x; /* x_wert to */ + pla[7]=pla[5]=Tile_heigth*y; /* y_wert to */ + pla[6]+=Tile_width-1; + pla[7]+=Tile_heigth-1; vro_cpyfm(x_handle, gl!=-1 ? S_ONLY : ALL_BLACK, pla, &Tile_bilder, &Map_bild); } } -} void mar_print_char(window, x, y, ch, col) winid window; -int x, y; +int x, y; char ch; int col; { @@ -2158,15 +2652,15 @@ int col; pla[0]= pla[1]=0; - pla[2]=Fcw-1; - pla[3]=Fch-1; - pla[6]=pla[4]=Fcw*x; - pla[7]=pla[5]=Fch*y; - pla[6]+=Fcw-1; - pla[7]+=Fch-1; + pla[2]=map_font.cw-1; + pla[3]=map_font.ch-1; + pla[6]=pla[4]=map_font.cw*x; + pla[7]=pla[5]=map_font.ch*y; + pla[6]+=map_font.cw-1; + pla[7]+=map_font.ch-1; colindex[0]=gem_color[col]; colindex[1]=WHITE; - vrt_cpyfm(x_handle,MD_REPLACE,pla,&Black_bild,&Map_bild,colindex); + vrt_cpyfm(x_handle,MD_REPLACE,pla,&Black_bild,&FontCol_Bild,colindex); } } @@ -2186,9 +2680,9 @@ char *input; z_ob[LGPROMPT].ob_type=G_USERDEF; z_ob[LGPROMPT].ob_spec.userblk=&ub_prompt; - z_ob[LGPROMPT].ob_height=2*Fch; + z_ob[LGPROMPT].ob_height=2*gr_ch; - length=z_ob[LGPROMPT].ob_width/Fcw; + length=z_ob[LGPROMPT].ob_width/gr_cw; if(strlen(ques)>length){ tmp=ques+length; while(*tmp!=' ' && tmp>=ques){ @@ -2361,9 +2855,9 @@ char def; if(strstr(query,"irect")) return(mar_ask_direction()); - len=min(strlen(query),(max_w-8*Fcw)/Fcw); - z_ob[ROOT].ob_width=(len+8)*Fcw; - z_ob[YNPROMPT].ob_width=Fcw*len+8; + len=min(strlen(query),(max_w-8*gr_cw)/gr_cw); + z_ob[ROOT].ob_width=(len+8)*gr_cw; + z_ob[YNPROMPT].ob_width=gr_cw*len+8; tmp=ob_get_text(z_ob,YNPROMPT,0); ob_set_text(z_ob,YNPROMPT,mar_copy_of(query)); @@ -2397,11 +2891,11 @@ char def; } z_ob[SOMECHARS].ob_width=z_ob[YN1+i].ob_x+8; - z_ob[SOMECHARS].ob_height=z_ob[YN1+i].ob_y+Fch+Fch/2; - Max((int *)&z_ob[ROOT].ob_width,z_ob[SOMECHARS].ob_width+4*Fcw); - z_ob[ROOT].ob_height=z_ob[SOMECHARS].ob_height+4*Fch; + z_ob[SOMECHARS].ob_height=z_ob[YN1+i].ob_y+gr_ch+gr_ch/2; + Max((int *)&z_ob[ROOT].ob_width,z_ob[SOMECHARS].ob_width+4*gr_cw); + z_ob[ROOT].ob_height=z_ob[SOMECHARS].ob_height+4*gr_ch; if(strchr(resp,'#')) - z_ob[ROOT].ob_height=z_ob[YNOK].ob_y+2*Fch; + z_ob[ROOT].ob_height=z_ob[YNOK].ob_y+2*gr_ch; for(i+=YN1;i<(YNN+1);i+=2){ ob_hide(z_ob,i,TRUE); @@ -2412,11 +2906,11 @@ char def; ob_hide(z_ob,ANYCHAR,FALSE); ob_hide(z_ob,YNOK,TRUE); ob_hide(z_ob,COUNT,TRUE); - z_ob[ANYCHAR].ob_height=2*Fch; + z_ob[ANYCHAR].ob_height=2*gr_ch; z_ob[CHOSENCH].ob_y= - z_ob[CHOSENCH+1].ob_y=Fch/2; - z_ob[ROOT].ob_width=max(z_ob[YNPROMPT].ob_width+z_ob[YNPROMPT].ob_x,z_ob[ANYCHAR].ob_width+z_ob[ANYCHAR].ob_x)+2*Fcw; - z_ob[ROOT].ob_height=z_ob[ANYCHAR].ob_height+z_ob[ANYCHAR].ob_y+Fch/2; + z_ob[CHOSENCH+1].ob_y=gr_ch/2; + z_ob[ROOT].ob_width=max(z_ob[YNPROMPT].ob_width+z_ob[YNPROMPT].ob_x,z_ob[ANYCHAR].ob_width+z_ob[ANYCHAR].ob_x)+2*gr_cw; + z_ob[ROOT].ob_height=z_ob[ANYCHAR].ob_height+z_ob[ANYCHAR].ob_y+gr_ch/2; *ob_get_text(z_ob,CHOSENCH,0)='?'; Event_Handler(any_init,any_handler); } diff --git a/win/gem/xpm2img.c b/win/gem/xpm2img.c new file mode 100644 index 0000000..605d5db --- /dev/null +++ b/win/gem/xpm2img.c @@ -0,0 +1,164 @@ +/* SCCS Id: @(#)xpm2img.c 3.4 2002/03/17 */ +/* Copyright (c) Christian Bressler 2002 */ +/* NetHack may be freely redistributed. See license for details. */ +/* This is mainly a reworked tile2bmp.c + xpm2iff.c -- Marvin */ +#include +#include +#include +#include "bitmfile.h" +#define TRUE 1 +#define FALSE 0 +void get_color(unsigned int colind, struct RGB *rgb); +void get_pixel(int x, int y, unsigned int *colind); +char *xpmgetline(); +unsigned int **Bild_daten; +/* translation table from xpm characters to RGB and colormap slots */ +struct Ttable { + char flag; + struct RGB col; + int slot; /* output colortable index */ +}ttable[256]; +struct RGB *ColorMap; +int num_colors = 0; +int width=0, height=0; +int initflag; +FILE *fp; +int +main(argc, argv) +int argc; +char *argv[]; +{ + int i; + int row, col, planeno; + int farben, planes; + if (argc != 3) { + fprintf(stderr, "usage: tile2img infile.xpm outfile.img\n"); + exit(EXIT_FAILURE); + } + initflag = 0; + fp = fopen(argv[2],"wb"); + if (!fp) { + printf("Error creating IMG-file %s, aborting.\n",argv[2]); + exit(EXIT_FAILURE); + } + fclose(fp); + if(fopen_xpm_file(argv[1],"r")!=TRUE){ + printf("Error reading xpm-file %s, aborting.\n",argv[1]); + exit(EXIT_FAILURE); + } + Bild_daten=(unsigned int **)malloc((long)height*sizeof(unsigned int *)); + for(i=0;i256){ + fprintf(stderr,"ERROR: zuviele Farben\n"); + exit(EXIT_FAILURE); + }else if(num_colors>16){ + farben=256; + planes=8; + }else if(num_colors>2){ + farben=16; + planes=4; + }else{ + farben=2; + planes=1; + } + bitmap_to_file(XIMG, width, height, 372, 372, planes, farben, argv[2], get_color, get_pixel ); + exit(EXIT_SUCCESS); + /*NOTREACHED*/ + return 0; +} +void get_color(unsigned int colind, struct RGB *rgb){ + rgb->r=(1000L*(long)ColorMap[colind].r)/0xFF; + rgb->g=(1000L*(long)ColorMap[colind].g)/0xFF; + rgb->b=(1000L*(long)ColorMap[colind].b)/0xFF; +} +void get_pixel(int x, int y, unsigned int *colind){ + *colind=Bild_daten[y][x]; +} +FILE *xpmfh = 0; +char initbuf[200]; +char *xpmbuf = initbuf; +/* version 1. Reads the raw xpm file, NOT the compiled version. This is + * not a particularly good idea but I don't have time to do the right thing + * at this point, even if I was absolutely sure what that was. */ +fopen_xpm_file(const char *fn, const char *mode){ + int temp; + char *xb; + if(strcmp(mode, "r"))return FALSE; /* no choice now */ + if(xpmfh)return FALSE; /* one file at a time */ + xpmfh = fopen(fn, mode); + if(!xpmfh)return FALSE; /* I'm hard to please */ + /* read the header */ + xb = xpmgetline(); + if(xb == 0)return FALSE; + if(4 != sscanf(xb,"%d %d %d %d", + &width, &height,&num_colors, &temp)) + return FALSE; /* bad header */ + /* replace the original buffer with one big enough for + * the real data + */ +/* XXX */ + xpmbuf = malloc(width * 2); + if(!xpmbuf){ + fprintf(stderr,"ERROR: Can't allocate line buffer\n"); + exit(1); + } + if(temp != 1)return FALSE; /* limitation of this code */ + { + /* read the colormap and translation table */ + int ccount = -1; + ColorMap = (struct RGB *)malloc((long)num_colors*sizeof(struct RGB)); + while(ccount++ < (num_colors-1)){ + char index; + int r, g, b; + xb = xpmgetline(); + if(xb==0)return FALSE; + if(4 != sscanf(xb,"%c c #%2x%2x%2x",&index,&r,&g,&b)){ + fprintf(stderr,"Bad color entry: %s\n",xb); + return FALSE; + } + ttable[index].flag = 1; /* this color is valid */ + ttable[index].col.r = r; + ttable[index].col.g = g; + ttable[index].col.b = b; + ttable[index].slot = ccount; + ColorMap[ccount].r=r; + ColorMap[ccount].g=g; + ColorMap[ccount].b=b; + } + } + return TRUE; +} +/* This deserves better. Don't read it too closely - you'll get ill. */ +#define bufsz 2048 +char buf[bufsz]; +char * +xpmgetline(){ + char *bp; + do { + if(fgets(buf, bufsz, xpmfh) == 0)return 0; + } while(buf[0] != '"'); + /* strip off the trailing <",> if any */ + for(bp = buf;*bp;bp++); + bp--; + while(isspace(*bp))bp--; + if(*bp==',')bp--; + if(*bp=='"')bp--; + bp++; + *bp = '\0'; + return &buf[1]; +} diff --git a/win/gnome/gn_xpms.h b/win/gnome/gn_xpms.h index 547aaa9..28408a0 100644 --- a/win/gnome/gn_xpms.h +++ b/win/gnome/gn_xpms.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnxpms.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnxpms.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ /* These XPMs are the artwork of Warwick Allison diff --git a/win/gnome/gnaskstr.c b/win/gnome/gnaskstr.c index e5443a3..b982896 100644 --- a/win/gnome/gnaskstr.c +++ b/win/gnome/gnaskstr.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnaskstr.c 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnaskstr.c 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnaskstr.h b/win/gnome/gnaskstr.h index cfa80c6..9cde69b 100644 --- a/win/gnome/gnaskstr.h +++ b/win/gnome/gnaskstr.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnaskstr.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnaskstr.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnbind.c b/win/gnome/gnbind.c index 762ee1d..9695746 100644 --- a/win/gnome/gnbind.c +++ b/win/gnome/gnbind.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnbind.c 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnbind.c 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ @@ -21,6 +21,7 @@ extern void tty_raw_print_bold(const char *); /* Interface definition, for windows.c */ struct window_procs Gnome_procs = { "Gnome", + WC_COLOR|WC_HILITE_PET|WC_INVERSE, gnome_init_nhwindows, gnome_player_selection, gnome_askname, @@ -69,6 +70,7 @@ struct window_procs Gnome_procs = { gnome_start_screen, gnome_end_screen, gnome_outrip, + genl_preference_update, }; /* @@ -110,49 +112,222 @@ void gnome_init_nhwindows(int* argc, char** argv) offers a Quit option, it is its responsibility to clean up and terminate the process. You need to fill in pl_character[0]. */ -void gnome_player_selection() -{ - int num_roles, availcount, i, nRole; - const char** choices; - - /* select a role */ - for (num_roles = 0; roles[num_roles].name.m; ++num_roles) continue; - choices = (const char **)alloc(sizeof(char *) * (num_roles+1)); - for (;;) { - availcount = 0; - for (i = 0; i < num_roles; i++) { - choices[i] = 0; - if (ok_role(i, flags.initrace, - flags.initgend, flags.initalign)) { - choices[i] = roles[i].name.m; - if (flags.initgend >= 0 && flags.female && roles[i].name.f) - choices[i] = roles[i].name.f; - ++availcount; - } - } - if (availcount > 0) break; - else if (flags.initalign >= 0) flags.initalign = -1; /* reset */ - else if (flags.initgend >= 0) flags.initgend = -1; - else if (flags.initrace >= 0) flags.initrace = -1; - else panic("no available ROLE+race+gender+alignment combinations"); - } - choices[num_roles] = (const char *) 0; - nRole=ghack_player_sel_dialog(choices); +void +gnome_player_selection() +{ + int n, i, sel; + const char** choices; + int* pickmap; + + /* prevent an unnecessary prompt */ + rigid_role_checks(); + + if (!flags.randomall && flags.initrole < 0) { + + /* select a role */ + for (n = 0; roles[n].name.m; n++) continue; + choices = (const char **)alloc(sizeof(char *) * (n+1)); + pickmap = (int*)alloc(sizeof(int) * (n+1)); + for (;;) { + for (n = 0, i = 0; roles[i].name.m; i++) { + if (ok_role(i, flags.initrace, + flags.initgend, flags.initalign)) { + if (flags.initgend >= 0 && flags.female && roles[i].name.f) + choices[n] = roles[i].name.f; + else + choices[n] = roles[i].name.m; + pickmap[n++] = i; + } + } + if (n > 0) break; + else if (flags.initalign >= 0) flags.initalign = -1; /* reset */ + else if (flags.initgend >= 0) flags.initgend = -1; + else if (flags.initrace >= 0) flags.initrace = -1; + else panic("no available ROLE+race+gender+alignment combinations"); + } + choices[n] = (const char *) 0; + if (n > 1) + sel = ghack_player_sel_dialog(choices, + _("Player selection"), _("Choose one of the following roles:")); + else sel = 0; + if (sel >= 0) sel = pickmap[sel]; + else if (sel == ROLE_NONE) { /* Quit */ + clearlocks(); + gnome_exit_nhwindows(0); + } + free(choices); + free(pickmap); + } else if (flags.initrole < 0) sel = ROLE_RANDOM; + else sel = flags.initrole; - /* Quit */ - if ( nRole == -1 ) - { - clearlocks(); - gnome_exit_nhwindows(0); + if (sel == ROLE_RANDOM) { /* Random role */ + sel = pick_role(flags.initrace, flags.initgend, + flags.initalign, PICK_RANDOM); + if (sel < 0) sel = randrole(); } - /* Random role */ - if ( nRole == -2) - { - nRole = rn2(num_roles); - pline("This game you will be %s", an(choices[nRole])); + + flags.initrole = sel; + + /* Select a race, if necessary */ + /* force compatibility with role, try for compatibility with + * pre-selected gender/alignment */ + if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) { + if (flags.initrace == ROLE_RANDOM || flags.randomall) { + flags.initrace = pick_race(flags.initrole, flags.initgend, + flags.initalign, PICK_RANDOM); + if (flags.initrace < 0) flags.initrace = randrace(flags.initrole); + } else { + /* Count the number of valid races */ + n = 0; /* number valid */ + for (i = 0; races[i].noun; i++) { + if (ok_race(flags.initrole, i, flags.initgend, flags.initalign)) + n++; + } + if (n == 0) { + for (i = 0; races[i].noun; i++) { + if (validrace(flags.initrole, i)) n++; + } + } + + choices = (const char **)alloc(sizeof(char *) * (n+1)); + pickmap = (int*)alloc(sizeof(int) * (n + 1)); + for (n = 0, i = 0; races[i].noun; i++) { + if (ok_race(flags.initrole, i, flags.initgend, + flags.initalign)) { + choices[n] = races[i].noun; + pickmap[n++] = i; + } + } + choices[n] = (const char *) 0; + /* Permit the user to pick, if there is more than one */ + if (n > 1) + sel = ghack_player_sel_dialog(choices, _("Race selection"), + _("Choose one of the following races:")); + else sel = 0; + if (sel >= 0) sel = pickmap[sel]; + else if (sel == ROLE_NONE) { /* Quit */ + clearlocks(); + gnome_exit_nhwindows(0); + } + flags.initrace = sel; + free(choices); + free(pickmap); + } + if (flags.initrace == ROLE_RANDOM) { /* Random role */ + sel = pick_race(flags.initrole, flags.initgend, + flags.initalign, PICK_RANDOM); + if (sel < 0) sel = randrace(flags.initrole); + flags.initrace = sel; + } + } + + /* Select a gender, if necessary */ + /* force compatibility with role/race, try for compatibility with + * pre-selected alignment */ + if (flags.initgend < 0 || + !validgend(flags.initrole, flags.initrace, flags.initgend)) { + if (flags.initgend == ROLE_RANDOM || flags.randomall) { + flags.initgend = pick_gend(flags.initrole, flags.initrace, + flags.initalign, PICK_RANDOM); + if (flags.initgend < 0) + flags.initgend = randgend(flags.initrole, flags.initrace); + } else { + /* Count the number of valid genders */ + n = 0; /* number valid */ + for (i = 0; i < ROLE_GENDERS; i++) { + if (ok_gend(flags.initrole, flags.initrace, i, flags.initalign)) + n++; + } + if (n == 0) { + for (i = 0; i < ROLE_GENDERS; i++) { + if (validgend(flags.initrole, flags.initrace, i)) n++; + } + } + + choices = (const char **)alloc(sizeof(char *) * (n+1)); + pickmap = (int*)alloc(sizeof(int) * (n + 1)); + for (n = 0, i = 0; i < ROLE_GENDERS; i++) { + if (ok_gend(flags.initrole, flags.initrace, i, + flags.initalign)) { + choices[n] = genders[i].adj; + pickmap[n++] = i; + } + } + choices[n] = (const char *) 0; + /* Permit the user to pick, if there is more than one */ + if (n > 1) + sel = ghack_player_sel_dialog(choices, _("Gender selection"), + _("Choose one of the following genders:")); + else sel = 0; + if (sel >= 0) sel = pickmap[sel]; + else if (sel == ROLE_NONE) { /* Quit */ + clearlocks(); + gnome_exit_nhwindows(0); + } + flags.initgend = sel; + free(choices); + free(pickmap); + } + if (flags.initgend == ROLE_RANDOM) { /* Random gender */ + sel = pick_gend(flags.initrole, flags.initrace, + flags.initalign, PICK_RANDOM); + if (sel < 0) sel = randgend(flags.initrole, flags.initrace); + flags.initgend = sel; + } + } + + /* Select an alignment, if necessary */ + /* force compatibility with role/race/gender */ + if (flags.initalign < 0 || + !validalign(flags.initrole, flags.initrace, flags.initalign)) { + if (flags.initalign == ROLE_RANDOM || flags.randomall) { + flags.initalign = pick_align(flags.initrole, flags.initrace, + flags.initgend, PICK_RANDOM); + if (flags.initalign < 0) + flags.initalign = randalign(flags.initrole, flags.initrace); + } else { + /* Count the number of valid alignments */ + n = 0; /* number valid */ + for (i = 0; i < ROLE_ALIGNS; i++) { + if (ok_align(flags.initrole, flags.initrace, flags.initgend, i)) + n++; + } + if (n == 0) { + for (i = 0; i < ROLE_ALIGNS; i++) + if (validalign(flags.initrole, flags.initrace, i)) n++; + } + + choices = (const char **)alloc(sizeof(char *) * (n+1)); + pickmap = (int*)alloc(sizeof(int) * (n + 1)); + for (n = 0, i = 0; i < ROLE_ALIGNS; i++) { + if (ok_align(flags.initrole, + flags.initrace, flags.initgend, i)) { + choices[n] = aligns[i].adj; + pickmap[n++] = i; + } + } + choices[n] = (const char *) 0; + /* Permit the user to pick, if there is more than one */ + if (n > 1) + sel = ghack_player_sel_dialog(choices, _("Alignment selection"), + _("Choose one of the following alignments:")); + else sel = 0; + if (sel >= 0) sel = pickmap[sel]; + else if (sel == ROLE_NONE) { /* Quit */ + clearlocks(); + gnome_exit_nhwindows(0); + } + flags.initalign = sel; + free(choices); + free(pickmap); + } + if (flags.initalign == ROLE_RANDOM) { + sel = pick_align(flags.initrole, flags.initrace, + flags.initgend, PICK_RANDOM); + if (sel < 0) sel = randalign(flags.initrole, flags.initrace); + flags.initalign = sel; + } } - - flags.initrole = nRole; } @@ -973,7 +1148,12 @@ void gnome_outrip(winid wid, int how) Strcat(ripString, buf); /* Put $ on stone */ - Sprintf(buf, "%ld Au\n", u.ugold); + Sprintf(buf, "%ld Au\n", +#ifndef GOLDOBJ + u.ugold); +#else + done_money); +#endif Strcat(ripString, buf); /* Put together death description */ @@ -1001,6 +1181,3 @@ void gnome_outrip(winid wid, int how) ghack_text_window_rip_string( ripString); } - - - diff --git a/win/gnome/gnbind.h b/win/gnome/gnbind.h index 3a2c3c1..17a5452 100644 --- a/win/gnome/gnbind.h +++ b/win/gnome/gnbind.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnbind.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnbind.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnglyph.c b/win/gnome/gnglyph.c index 7453e1c..702617a 100644 --- a/win/gnome/gnglyph.c +++ b/win/gnome/gnglyph.c @@ -1,8 +1,9 @@ -/* SCCS Id: @(#)gnglyph.c 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnglyph.c 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ #include "gnglyph.h" +#include "tile2x11.h" static GHackGlyphs ghack_glyphs; static GdkImlibImage** ghack_tiles = NULL; @@ -28,8 +29,9 @@ static GdkImlibImage** ghack_tiles = NULL; * NOTES: * The glyphs (tiles) must be in the image in a certain way: the * glyphs must be stacked such that the resultant image is - * TILE_X wide, and TILE_Y * (number of glyphs) high. In this - * sense, TILE_X == TILE_Y, and can be any reasonable integer-- + * TILE_X * TILES_PER_ROW wide, and + * TILE_Y * (number of glyphs) / TILES_PER_ROW high (rounded up). + * In this sense, TILE_X == TILE_Y, and can be any reasonable integer * say, 16 <= TILE_X <= 64. Because the glyph number is tightly * coupled to the Nethack object it represents, the order of the * glyphs in the image is imporant: Glyph 1 is at the top of the @@ -55,12 +57,19 @@ ghack_init_glyphs( const char *xpmFile) gdk_imlib_render(ghack_glyphs.im, ghack_glyphs.im->rgb_width, ghack_glyphs.im->rgb_height); - ghack_glyphs.count = ghack_glyphs.im->rgb_height / ghack_glyphs.im->rgb_width; - ghack_glyphs.width = ghack_glyphs.im->rgb_width; - ghack_glyphs.height = ghack_glyphs.im->rgb_height / ghack_glyphs.count; + if (ghack_glyphs.im->rgb_width % TILES_PER_ROW) { + g_error("%s is not a multiple of %d (number of tiles/row) pixels wide", + xpmFile, TILES_PER_ROW); + return -1; + } + ghack_glyphs.width = ghack_glyphs.im->rgb_width / TILES_PER_ROW; + ghack_glyphs.height = ghack_glyphs.width; + ghack_glyphs.count = + (ghack_glyphs.im->rgb_height * ghack_glyphs.im->rgb_width) / + (ghack_glyphs.width * ghack_glyphs.height); - /* Assume the tiles are stacked vertically. + /* Assume the tiles are organized in rows of TILES_PER_ROW * Further, assume that the tiles are SQUARE */ ghack_tiles = g_new0( GdkImlibImage*, ghack_glyphs.count ); @@ -186,8 +195,8 @@ ghack_image_from_glyph( int glyph, gboolean force ) (force==TRUE)? "TRUE" : "FALSE"); } - if (!ghack_tiles[tile] || force) - { + if (!ghack_tiles[tile] || force) { + int src_x, src_y; #if 0 fprintf( stderr, "crop_and_clone: glyph=%d, tile=%d, ptr=%p, x=%d, y=%d, w=%d, h=%d\n", glyph, tile, (void*)&(ghack_tiles[tile]), 0, @@ -197,8 +206,10 @@ ghack_image_from_glyph( int glyph, gboolean force ) #endif if (ghack_glyphs.im->pixmap == NULL) g_warning( "Aiiee! ghack_glyphs.im->pixmap==NULL!!!!\n"); - ghack_tiles[tile] = gdk_imlib_crop_and_clone_image(ghack_glyphs.im, 0, - tile * ghack_glyphs.width, + src_x = (tile % TILES_PER_ROW) * ghack_glyphs.width; + src_y = (tile / TILES_PER_ROW) * ghack_glyphs.height; + ghack_tiles[tile] = gdk_imlib_crop_and_clone_image(ghack_glyphs.im, + src_x, src_y, ghack_glyphs.height, ghack_glyphs.width); } @@ -216,4 +227,3 @@ ghack_image_from_glyph( int glyph, gboolean force ) return ghack_tiles[tile]; } - diff --git a/win/gnome/gnglyph.h b/win/gnome/gnglyph.h index c1631df..e2b30da 100644 --- a/win/gnome/gnglyph.h +++ b/win/gnome/gnglyph.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnglyph.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnglyph.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnmain.c b/win/gnome/gnmain.c index f5e6435..1ca8f03 100644 --- a/win/gnome/gnmain.c +++ b/win/gnome/gnmain.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnmain.c 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnmain.c 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ @@ -11,6 +11,7 @@ #include #include #include +#include #include "hack.h" #include "date.h" @@ -137,7 +138,8 @@ ghack_about_cb(GtkWidget *widget, gpointer data) _("\nSend comments and bug reports to: nethack-bugs@nethack.org\n" "This game is free software. See License for details.")); about = gnome_about_new(_("Nethack"), - buf1, "(C) 1985-2000 Mike Stephenson", (const char **)authors, buf, + buf1, "Copyright (C) 1985-2002 Mike Stephenson", + (const char **)authors, buf, NULL); gtk_signal_connect (GTK_OBJECT (about), "destroy", @@ -651,9 +653,55 @@ parse_args (int argc, char *argv[]) return; } +/* + * [ALI] Gnome installs its own handler(s) for SIGBUS, SIGFPE and SIGSEGV. + * These handlers will fork and exec a helper program. When that helper + * comes to initialize GTK+, it may fail if setuid/setgid. We solve this + * by dropping privileges before passing the signal along the chain. + * Note: We don't need to either drop or mask the saved ID since this + * will be reset when the child process performs the execve() anyway. + */ + +static struct { + int signum; + void (*handler)(int); +} ghack_chain[] = { + {SIGBUS}, + {SIGFPE}, + {SIGSEGV}, + {SIGILL} /* Not currently handled by Gnome */ +}; + +static void ghack_sig_handler(int signum) +{ + int i; + uid_t uid, euid; + gid_t gid, egid; + uid = getuid(); + euid = geteuid(); + gid = getgid(); + egid = getegid(); + if (gid != egid) + setgid(gid); + if (uid != euid) + setuid(uid); + for(i = SIZE(ghack_chain) - 1; i >= 0; i--) + if (ghack_chain[i].signum == signum) { + ghack_chain[i].handler(signum); + break; + } + if (i < 0) + impossible("Unhandled ghack signal"); + if (uid != euid) + setuid(euid); + if (gid != egid) + setgid(egid); +} + /* initialize gnome and fir up the main window */ void ghack_init_main_window( int argc, char** argv) { + int i; struct timeval tv; uid_t uid, euid; @@ -672,7 +720,10 @@ void ghack_init_main_window( int argc, char** argv) euid = geteuid(); if (uid != euid) setuid(uid); + hide_privileges(TRUE); + /* XXX gnome_init must print nethack options for --help, but does not */ gnome_init ("nethack", VERSION_STRING, argc, argv); + hide_privileges(FALSE); parse_args (argc, argv); /* Initialize the i18n stuff (not that gnomehack supperts it yet...) */ @@ -712,6 +763,9 @@ void ghack_init_main_window( int argc, char** argv) * has already been shown */ if (uid != euid) setuid(euid); + for(i = 0; i < SIZE(ghack_chain); i++) + ghack_chain[i].handler = + signal(ghack_chain[i].signum, ghack_sig_handler); } void ghack_main_window_add_map_window(GtkWidget* win) @@ -769,4 +823,3 @@ ghack_get_main_window() { return( GTK_WIDGET(mainWindow) ); } - diff --git a/win/gnome/gnmain.h b/win/gnome/gnmain.h index e759582..36aaf7f 100644 --- a/win/gnome/gnmain.h +++ b/win/gnome/gnmain.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnmain.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnmain.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnmap.c b/win/gnome/gnmap.c index 4aa4f7f..3d0882e 100644 --- a/win/gnome/gnmap.c +++ b/win/gnome/gnmap.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnmap.c 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnmap.c 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* Copyright (C) 1998 by Anthony Taylor */ /* NetHack may be freely redistributed. See license for details. */ @@ -180,12 +180,13 @@ ghack_init_map_window ( ) /* Tile the map background with a pretty image */ background = gdk_imlib_load_image((char *) "mapbg.xpm"); - gdk_imlib_render( background, background->rgb_width, - background->rgb_height); if (background == NULL) { g_warning("Bummer! Failed to load the map background image (mapbg.xpm)!"); } else { + gdk_imlib_render(background, background->rgb_width, + background->rgb_height); + /* Tile the map background */ for (y = 0; y < height+background->rgb_height; y+=background->rgb_height) { @@ -229,15 +230,16 @@ ghack_init_map_window ( ) /* Set up the pet mark image */ petmark = gdk_imlib_create_image_from_xpm_data( pet_mark_xpm); - gdk_imlib_render( petmark, petmark->rgb_width, - petmark->rgb_height); if (petmark == NULL) { g_warning("Bummer! Failed to load the pet_mark image!"); } else { + gdk_imlib_render(petmark, petmark->rgb_width, + petmark->rgb_height); + /* ghack_map.overlay is an array of canvas images used to * overlay tile images... - */ + */ for (i=0, y = 0; y < height; y+=ghack_glyph_height()) { for (x = 0; x < width; x+=ghack_glyph_width()) diff --git a/win/gnome/gnmap.h b/win/gnome/gnmap.h index 8dd41f9..83bc849 100644 --- a/win/gnome/gnmap.h +++ b/win/gnome/gnmap.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnmap.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnmap.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnmenu.c b/win/gnome/gnmenu.c index 133c96a..4536401 100644 --- a/win/gnome/gnmenu.c +++ b/win/gnome/gnmenu.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnmenu.c 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnmenu.c 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnmenu.h b/win/gnome/gnmenu.h index 41cb86e..2864cc7 100644 --- a/win/gnome/gnmenu.h +++ b/win/gnome/gnmenu.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnmenu.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnmenu.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnmesg.c b/win/gnome/gnmesg.c index 498c006..337a21b 100644 --- a/win/gnome/gnmesg.c +++ b/win/gnome/gnmesg.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnmesg.c 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnmesg.c 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnmesg.h b/win/gnome/gnmesg.h index c464fea..139e63a 100644 --- a/win/gnome/gnmesg.h +++ b/win/gnome/gnmesg.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnmesg.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnmesg.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnomeprv.h b/win/gnome/gnomeprv.h index fcff9a9..60fe4c8 100644 --- a/win/gnome/gnomeprv.h +++ b/win/gnome/gnomeprv.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnomeprv.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnomeprv.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnopts.c b/win/gnome/gnopts.c index 1fb0e0d..b4845b9 100644 --- a/win/gnome/gnopts.c +++ b/win/gnome/gnopts.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnopts.c 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnopts.c 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnopts.h b/win/gnome/gnopts.h index 53b16ad..83ff37b 100644 --- a/win/gnome/gnopts.h +++ b/win/gnome/gnopts.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnopts.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnopts.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnplayer.c b/win/gnome/gnplayer.c index b1ad878..f34fa50 100644 --- a/win/gnome/gnplayer.c +++ b/win/gnome/gnplayer.c @@ -1,11 +1,11 @@ -/* SCCS Id: @(#)gnplayer.c 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnplayer.c 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ -#include "gnplayer.h" -#include "gnmain.h" #include #include +#include "gnplayer.h" +#include "gnmain.h" #include "hack.h" static gint role_number; @@ -13,15 +13,15 @@ static GtkWidget* clist; static void player_sel_key_hit (GtkWidget *widget, GdkEventKey *event, gpointer data) -{ - const char** roles = data; - int i; - for (i = 0; roles[i] != 0; ++i) { - if (roles[i][0] == toupper(event->keyval)) { - role_number = i; - gtk_clist_select_row( GTK_CLIST (clist), i, 0); - } - } +{ + const char** roles = data; + int i; + for (i = 0; roles[i] != 0; ++i) { + if (roles[i][0] == toupper(event->keyval)) { + role_number = i; + gtk_clist_select_row( GTK_CLIST (clist), i, 0); + } + } } static void @@ -31,23 +31,25 @@ player_sel_row_selected (GtkCList *clist, int row, int col, GdkEvent *event) } int -ghack_player_sel_dialog( const char** roles) +ghack_player_sel_dialog(const char** choices, + const gchar* title, + const gchar* prompt) { int i; static GtkWidget* dialog; static GtkWidget* swin; static GtkWidget* frame1; - dialog = gnome_dialog_new (_("Player selection"), + dialog = gnome_dialog_new(title, GNOME_STOCK_BUTTON_OK, - _("Random role"), + _("Random"), GNOME_STOCK_BUTTON_CANCEL, NULL); gnome_dialog_close_hides (GNOME_DIALOG (dialog), FALSE); gtk_signal_connect (GTK_OBJECT (dialog), "key_press_event", - GTK_SIGNAL_FUNC (player_sel_key_hit), roles ); + GTK_SIGNAL_FUNC (player_sel_key_hit), choices ); - frame1 = gtk_frame_new (_("Choose one of the following roles:")); + frame1 = gtk_frame_new(prompt); gtk_object_set_data (GTK_OBJECT (dialog), "frame1", frame1); gtk_widget_show (frame1); gtk_container_border_width (GTK_CONTAINER (frame1), 3); @@ -67,10 +69,10 @@ ghack_player_sel_dialog( const char** roles) gtk_box_pack_start_defaults (GTK_BOX (GNOME_DIALOG (dialog)->vbox), frame1); /* Add the roles into the list here... */ - for (i=0; roles[i]; i++) { + for (i=0; choices[i]; i++) { gchar accelBuf[BUFSZ]; - const char *text[3]={accelBuf, roles[i],NULL}; - sprintf( accelBuf, "%c ", tolower(roles[i][0])); + const char *text[3]={accelBuf, choices[i],NULL}; + sprintf( accelBuf, "%c ", tolower(choices[i][0])); gtk_clist_insert (GTK_CLIST (clist), i, (char**)text); } @@ -89,11 +91,11 @@ ghack_player_sel_dialog( const char** roles) /* Quit on button 2 or error */ if (i < 0 || i > 1) { - return( -1); + return(ROLE_NONE); } /* Random is button 1*/ if (i == 1 ) { - return( -2); + return(ROLE_RANDOM); } return ( role_number); } diff --git a/win/gnome/gnplayer.h b/win/gnome/gnplayer.h index cc3ad4a..73929de 100644 --- a/win/gnome/gnplayer.h +++ b/win/gnome/gnplayer.h @@ -1,13 +1,10 @@ -/* SCCS Id: @(#)gnplayer.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnplayer.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ #ifndef GnomeHackPlayerSelDialog_h #define GnomeHackPlayerSelDialog_h - -int ghack_player_sel_dialog(const char **); - +int ghack_player_sel_dialog(const char **, const gchar*, const gchar*); #endif /* GnomeHackPlayerSelDialog_h */ - diff --git a/win/gnome/gnsignal.c b/win/gnome/gnsignal.c index 12275fa..0387975 100644 --- a/win/gnome/gnsignal.c +++ b/win/gnome/gnsignal.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnsignal.c 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnsignal.c 3.4 2000/07/16 */ /* Copyright (C) 1998 by Anthony Taylor */ /* NetHack may be freely redistributed. See license for details. */ @@ -248,193 +248,194 @@ ghack_handle_button_press(GtkWidget *widget, GdkEventButton *event, void ghack_handle_key_press(GtkWidget *widget, GdkEventKey *event, gpointer data) { - int key=0; - int ctl=GDK_CONTROL_MASK; - int alt=GDK_MOD1_MASK; + static int was_pound = 0; + int key = 0; + int ctl = GDK_CONTROL_MASK; + int alt = GDK_MOD1_MASK; -/* Turn this on to debug key events */ + /* Turn this on to debug key events */ #if 0 - g_message("I got a \"%s\" key (%d) %s%s", - gdk_keyval_name (event->keyval), event->keyval, - (event->state&ctl)? "+CONTROL":"", (event->state&alt)? "+ALT":""); + g_message("I got a \"%s\" key (%d) %s%s", + gdk_keyval_name (event->keyval), event->keyval, + (event->state&ctl)? "+CONTROL":"", (event->state&alt)? "+ALT":""); #endif - switch (event->keyval) { - /* special keys to do stuff with */ - - /* Set up the direction keys */ - - /* First handle the arrow keys -- these always mean move */ - case GDK_Right: - case GDK_rightarrow: - if (iflags.num_pad) key='6'; else key='l'; break; - case GDK_Left: - case GDK_leftarrow: - if (iflags.num_pad) key='4'; else key='h'; break; - case GDK_Up: - case GDK_uparrow: - if (iflags.num_pad) key='8'; else key='k'; break; - case GDK_Down: - case GDK_downarrow: - if (iflags.num_pad) key='2'; else key='j'; break; - case GDK_Home: - if (iflags.num_pad) key='7'; else key='y'; break; - case GDK_End: - if (iflags.num_pad) key='1'; else key='b'; break; - case GDK_Page_Down: - if (iflags.num_pad) key='3'; else key='n'; break; - case GDK_Page_Up: - if (iflags.num_pad) key='9'; else key='u'; break; - case ' ': key='.'; break; - - /* Now, handle the numberpad (move or numbers) */ - case GDK_KP_Right: - case GDK_KP_6: - if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) - key = GDK_KP_6; - else - key='6'; - break; - - case GDK_KP_Left: - case GDK_KP_4: - if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) - key = GDK_KP_4; - else - key='4'; - break; - - case GDK_KP_Up: - case GDK_KP_8: - if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) - key = GDK_KP_8; - else - key='8'; - break; - - case GDK_KP_Down: - case GDK_KP_2: - if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) - key = GDK_KP_2; - else - key='2'; - break; - - /* Move Top-Left */ - case GDK_KP_Home: - case GDK_KP_7: - if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) - key = GDK_KP_7; - else - key='7'; - break; - - case GDK_KP_Page_Up: - case GDK_KP_9: - if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) - key = GDK_KP_9; - else - key='9'; - break; - - case GDK_KP_End: - case GDK_KP_1: - if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) - key = GDK_KP_1; - else - key='1'; - break; - - case GDK_KP_Page_Down: - case GDK_KP_3: - if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) - key = GDK_KP_3; - else - key='3'; - break; + switch (event->keyval) { + /* special keys to do stuff with */ + + /* Set up the direction keys */ + + /* First handle the arrow keys -- these always mean move */ + case GDK_Right: + case GDK_rightarrow: + if (iflags.num_pad) key='6'; else key='l'; break; + case GDK_Left: + case GDK_leftarrow: + if (iflags.num_pad) key='4'; else key='h'; break; + case GDK_Up: + case GDK_uparrow: + if (iflags.num_pad) key='8'; else key='k'; break; + case GDK_Down: + case GDK_downarrow: + if (iflags.num_pad) key='2'; else key='j'; break; + case GDK_Home: + if (iflags.num_pad) key='7'; else key='y'; break; + case GDK_End: + if (iflags.num_pad) key='1'; else key='b'; break; + case GDK_Page_Down: + if (iflags.num_pad) key='3'; else key='n'; break; + case GDK_Page_Up: + if (iflags.num_pad) key='9'; else key='u'; break; + case ' ': key='.'; break; + + /* Now, handle the numberpad (move or numbers) */ + case GDK_KP_Right: + case GDK_KP_6: + if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) + key = GDK_KP_6; + else + key='6'; + break; + + case GDK_KP_Left: + case GDK_KP_4: + if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) + key = GDK_KP_4; + else + key='4'; + break; + + case GDK_KP_Up: + case GDK_KP_8: + if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) + key = GDK_KP_8; + else + key='8'; + break; + + case GDK_KP_Down: + case GDK_KP_2: + if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) + key = GDK_KP_2; + else + key='2'; + break; + + /* Move Top-Left */ + case GDK_KP_Home: + case GDK_KP_7: + if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) + key = GDK_KP_7; + else + key='7'; + break; + + case GDK_KP_Page_Up: + case GDK_KP_9: + if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) + key = GDK_KP_9; + else + key='9'; + break; + + case GDK_KP_End: + case GDK_KP_1: + if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) + key = GDK_KP_1; + else + key='1'; + break; + + case GDK_KP_Page_Down: + case GDK_KP_3: + if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) + key = GDK_KP_3; + else + key='3'; + break; - case GDK_KP_5: - if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) - key = GDK_KP_5; - else - key='5'; - break; - - case GDK_KP_Delete: - case GDK_KP_Decimal: - key='.'; - break; - - /* We don't bother using the "#" key for extended commands. Instead, - * we will just use the ALT key.*/ - case GDK_numbersign: - break; - - /* We will probably want to do something with these later... */ - case GDK_KP_Begin: - case GDK_KP_F1: - case GDK_F1: - case GDK_KP_F2: - case GDK_F2: - case GDK_KP_F3: - case GDK_F3: - case GDK_KP_F4: - case GDK_F4: - case GDK_F5: - case GDK_F6: - case GDK_F7: - case GDK_F8: - case GDK_F9: - case GDK_F10: - case GDK_F11: - case GDK_F12: - break; - /* various keys to ignore */ - case GDK_KP_Insert: - case GDK_Insert: - case GDK_Delete: - case GDK_Print: - case GDK_BackSpace: - case GDK_Pause: - case GDK_Scroll_Lock: - case GDK_Shift_Lock: - case GDK_Num_Lock: - case GDK_Caps_Lock: - case GDK_Control_L: - case GDK_Control_R: - case GDK_Shift_L: - case GDK_Shift_R: - case GDK_Alt_L: - case GDK_Alt_R: - case GDK_Meta_L: - case GDK_Meta_R: - case GDK_Mode_switch: - case GDK_Multi_key: - return; - - default: - key = event->keyval; - } - - if (event->state & alt) { + case GDK_KP_5: + if (event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK) && iflags.num_pad) + key = GDK_KP_5; + else + key='5'; + break; + + case GDK_KP_Delete: + case GDK_KP_Decimal: + key='.'; + break; + + /* can't just ignore "#", it's a core feature */ + case GDK_numbersign: + was_pound = 1; + return; + + /* We will probably want to do something with these later... */ + case GDK_KP_Begin: + case GDK_KP_F1: + case GDK_F1: + case GDK_KP_F2: + case GDK_F2: + case GDK_KP_F3: + case GDK_F3: + case GDK_KP_F4: + case GDK_F4: + case GDK_F5: + case GDK_F6: + case GDK_F7: + case GDK_F8: + case GDK_F9: + case GDK_F10: + case GDK_F11: + case GDK_F12: + break; + /* various keys to ignore */ + case GDK_KP_Insert: + case GDK_Insert: + case GDK_Delete: + case GDK_Print: + case GDK_BackSpace: + case GDK_Pause: + case GDK_Scroll_Lock: + case GDK_Shift_Lock: + case GDK_Num_Lock: + case GDK_Caps_Lock: + case GDK_Control_L: + case GDK_Control_R: + case GDK_Shift_L: + case GDK_Shift_R: + case GDK_Alt_L: + case GDK_Alt_R: + case GDK_Meta_L: + case GDK_Meta_R: + case GDK_Mode_switch: + case GDK_Multi_key: + return; + + default: + key = event->keyval; + } + + if ((event->state & alt) || was_pound) { key=M(event->keyval); - } - else if (event->state & ctl) { + } else if (event->state & ctl) { key=C(event->keyval); - } + } + if (was_pound) { + was_pound = 0; + } - /* Ok, here is where we do clever stuff to overide the default - * game behavior */ - if (g_askingQuestion==0) { - - if (key == 'S' || key == M('S') || key == C('S')) { - ghack_save_game_cb( NULL, NULL); - return; - } - } + /* Ok, here is where we do clever stuff to overide the default + * game behavior */ + if (g_askingQuestion == 0) { + + if (key == 'S' || key == M('S') || key == C('S')) { + ghack_save_game_cb( NULL, NULL); + return; + } + } g_keyBuffer = g_list_prepend (g_keyBuffer, GINT_TO_POINTER( key)); g_numKeys++; } - - diff --git a/win/gnome/gnsignal.h b/win/gnome/gnsignal.h index ad43e98..52fa299 100644 --- a/win/gnome/gnsignal.h +++ b/win/gnome/gnsignal.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnsignal.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnsignal.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Anthony Taylor */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnstatus.c b/win/gnome/gnstatus.c index bfd6e55..bc3e912 100644 --- a/win/gnome/gnstatus.c +++ b/win/gnome/gnstatus.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnstatus.c 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnstatus.c 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ @@ -432,6 +432,9 @@ void ghack_status_window_update_stats() const char* hung; const char* enc; static int firstTime=TRUE; +#ifdef GOLDOBJ + long umoney; +#endif /* First, fill in the player name and the dungeon level */ strcpy(buf, plname); @@ -560,16 +563,30 @@ void ghack_status_window_update_stats() gtk_label_set( GTK_LABEL( chaLabel), buf); /* Now do the non-pixmaped stats (gold and such) */ +#ifndef GOLDOBJ sprintf(buf,"Au:%ld", u.ugold); if (lastAu < u.ugold && firstTime==FALSE) { +#else + umoney = money_cnt(invent); + sprintf(buf,"Au:%ld", umouney); + if (lastAu < umoney && firstTime==FALSE) { +#endif /* Ok, this changed so add it to the highlighing list */ ghack_highlight_widget( goldLabel, normalStyle, greenStyle); } +#ifndef GOLDOBJ else if (lastAu > u.ugold && firstTime==FALSE) { +#else + else if (lastAu > umoney && firstTime==FALSE) { +#endif /* Ok, this changed so add it to the highlighing list */ ghack_highlight_widget( goldLabel, normalStyle, redStyle); } +#ifndef GOLDOBJ lastAu = u.ugold; +#else + lastAu = umoney; +#endif gtk_label_set( GTK_LABEL( goldLabel), buf); if (u.mtimedone) { diff --git a/win/gnome/gnstatus.h b/win/gnome/gnstatus.h index 3275657..d5008a5 100644 --- a/win/gnome/gnstatus.h +++ b/win/gnome/gnstatus.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnstatus.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnstatus.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gntext.c b/win/gnome/gntext.c index ece5f77..275a4a1 100644 --- a/win/gnome/gntext.c +++ b/win/gnome/gntext.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gntext.c 3.3 2000/07/16 */ +/* SCCS Id: @(#)gntext.c 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ @@ -40,6 +40,7 @@ void ghack_text_window_clear(GtkWidget *widget, gpointer data) void ghack_text_window_destroy() { + TW_window = NULL; } void ghack_text_window_display(GtkWidget *widget, boolean block, @@ -50,6 +51,8 @@ void ghack_text_window_display(GtkWidget *widget, boolean block, gtk_window_set_title(GTK_WINDOW( TW_window), "Rest In Peace"); } + gtk_signal_connect (GTK_OBJECT (TW_window), "destroy", + (GtkSignalFunc) ghack_text_window_destroy, NULL); if (block) gnome_dialog_run(GNOME_DIALOG(TW_window)); else diff --git a/win/gnome/gntext.h b/win/gnome/gntext.h index 86883cf..c957dc2 100644 --- a/win/gnome/gntext.h +++ b/win/gnome/gntext.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gntext.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gntext.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnyesno.c b/win/gnome/gnyesno.c index 07fb310..ecf3bad 100644 --- a/win/gnome/gnyesno.c +++ b/win/gnome/gnyesno.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnyesno.c 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnyesno.c 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/gnome/gnyesno.h b/win/gnome/gnyesno.h index 8450f18..dd0728f 100644 --- a/win/gnome/gnyesno.h +++ b/win/gnome/gnyesno.h @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)gnyesno.h 3.3 2000/07/16 */ +/* SCCS Id: @(#)gnyesno.h 3.4 2000/07/16 */ /* Copyright (C) 1998 by Erik Andersen */ /* NetHack may be freely redistributed. See license for details. */ diff --git a/win/share/monsters.txt b/win/share/monsters.txt index 9cb2cbd..eea8b3e 100644 --- a/win/share/monsters.txt +++ b/win/share/monsters.txt @@ -2241,20 +2241,20 @@ P = (108, 145, 182) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM - MMMMMMMMMMGGMMMM - MMMMMMMMMGOGGMMM - MMMMMMMMMGGGGMMM - MMMMMGGMMGGGMMMM - MMMGGMMGGMMMAAAM - MMMMMGOGGGMAAAAM - MMMMGOGGMMGAAAAM - NNNGOGGMGAAAAAMM - NANGGGGMAGAAMMMM - NNNGGNNNAAAMAMMM - MMGGGNANAAMAMAMM - MGGGANNNAAMMAMMM - MMGMMAAAAAAMMMMM - MMMMMMAAMAMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMDMMMMNHCNMMDMM + MDMDMMNHDNCNDEDM + DMDMDMNNHCNDMDED + MDMMMDMNNHDNDMMM + MDDDMMENNGMDMDEM + MMDDDDEEEEGDMMDE + DMMMMMDEHEEMDMMM + MDMMMMMMMHMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM } # tile 118 (xan) { @@ -6930,21 +6930,21 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 364 (Wizard of Balance) +# tile 364 (Neferet the Green) { - MMMMMMMMMBPMMMMM - MMMMMMBBBPEMMMMM - MMMMMBPPPEAMMMMM - MMMMMBAAAEAMMMMM - MMMHMPAAAEAMMMMM - MMMHBPLLLEAMMMMM - MHHHHHPLLEMMMMMM - MCMLMCBAAEAMAAAM - PCPHPCPBBEEAAAAM - CHCHCHCPPEEEAAMM - MMMHMEEPPEALAAMM - MMHHHEPPPEAAAAMM - MMMMMBPPPEAAMAMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMGGGMMMMMMM + MMMMMGFFFGMMMMMM + MMMMGFEFEGMMMMMM + MMMMGFFFFEGMMMMM + MNMGPEFFFEEMMMMM + MIMMBBEAAEAMAAMM + MIMBBPPBBEEAAAAM + MIGBPPPPPEEEAAMM + MIMPPMEPEAAGAAMM + MIMMMBPPPAAAAAMM + MNMMMBPPPEAAMAMM MMMMBPPPPPEAMMMM MMMBPPPPPPPEMMMM MMMMMMMMMMMMMMMM diff --git a/win/share/objects.txt b/win/share/objects.txt index ae0c522..4592352 100644 --- a/win/share/objects.txt +++ b/win/share/objects.txt @@ -2408,7 +2408,26 @@ P = (108, 145, 182) MMMMMNNNNNAAMMMM MMMMMMAAAAAMMMMM } -# tile 126 (tattered cape / cloak of protection) +# tile 126 (leather cloak) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMKJJMJJKMMMMM + MMMMMKJJJKAAMMMM + MMMMMMKJKAAMMMMM + MMMMMKKAKJAMMMMM + MMMMKKKAKJJAMMMM + MMMKKKAAKJJJAMMM + MMKKKKAAKJJJJAMM + MMKKKAAJJKJJJAMM + MMKKKAAJJKJJJAMM + MMMKKAJJJJKJAMMM + MMMMAAAAAAAAMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 127 (tattered cape / cloak of protection) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2427,7 +2446,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 127 (opera cloak / cloak of invisibility) +# tile 128 (opera cloak / cloak of invisibility) { MMMMMMMMMMMMMMMM MMMMMMNNNMMMMMMM @@ -2446,7 +2465,7 @@ P = (108, 145, 182) MMAANNNNNNAOOAAM MMMMAAAAAAAAAAMM } -# tile 128 (ornamental cope / cloak of magic resistance) +# tile 129 (ornamental cope / cloak of magic resistance) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2465,7 +2484,7 @@ P = (108, 145, 182) MMAAAAAAAAAAAPMM MMMPPPPPPPPPPPMM } -# tile 129 (piece of cloth / cloak of displacement) +# tile 130 (piece of cloth / cloak of displacement) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2484,7 +2503,7 @@ P = (108, 145, 182) MMMMMPPPPPAAMMMM MMMMMMMPPAAMMMMM } -# tile 130 (small shield) +# tile 131 (small shield) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2503,7 +2522,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 131 (blue and green shield / elven shield) +# tile 132 (blue and green shield / elven shield) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2522,7 +2541,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 132 (white-handed shield / Uruk-hai shield) +# tile 133 (white-handed shield / Uruk-hai shield) { MMMMMMMMMMMMMMMM MMMKMKKKJJJMJMMM @@ -2541,7 +2560,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 133 (red-eyed shield / orcish shield) +# tile 134 (red-eyed shield / orcish shield) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2560,7 +2579,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 134 (large shield) +# tile 135 (large shield) { MMMMMMMMMMMMMMMM MMMNMNNNOOOMOMMM @@ -2579,7 +2598,7 @@ P = (108, 145, 182) MMMMMMMMAAMMMMMM MMMMMMMMMMMMMMMM } -# tile 135 (large round shield / dwarvish roundshield) +# tile 136 (large round shield / dwarvish roundshield) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2598,7 +2617,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 136 (polished silver shield / shield of reflection) +# tile 137 (polished silver shield / shield of reflection) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2617,7 +2636,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 137 (old gloves / leather gloves) +# tile 138 (old gloves / leather gloves) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2636,7 +2655,7 @@ P = (108, 145, 182) MMMMMMMMMAAAMMMM MMMMMMMMMMMMMMMM } -# tile 138 (padded gloves / gauntlets of fumbling) +# tile 139 (padded gloves / gauntlets of fumbling) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2655,7 +2674,7 @@ P = (108, 145, 182) MMMMMMMMMAAAMMMM MMMMMMMMMMMMMMMM } -# tile 139 (riding gloves / gauntlets of power) +# tile 140 (riding gloves / gauntlets of power) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2674,7 +2693,7 @@ P = (108, 145, 182) MMMMMMMMMAAAMMMM MMMMMMMMMMMMMMMM } -# tile 140 (fencing gloves / gauntlets of dexterity) +# tile 141 (fencing gloves / gauntlets of dexterity) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2693,7 +2712,7 @@ P = (108, 145, 182) MMMMMMMMMAAAMMMM MMMMMMMMMMMMMMMM } -# tile 141 (walking shoes / low boots) +# tile 142 (walking shoes / low boots) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2712,7 +2731,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 142 (hard shoes / iron shoes) +# tile 143 (hard shoes / iron shoes) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2731,7 +2750,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 143 (jackboots / high boots) +# tile 144 (jackboots / high boots) { MMMMMMMCCKKKKMMM MMMMMMCKAAAAJJMM @@ -2750,7 +2769,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 144 (combat boots / speed boots) +# tile 145 (combat boots / speed boots) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2769,7 +2788,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 145 (jungle boots / water walking boots) +# tile 146 (jungle boots / water walking boots) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2788,7 +2807,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 146 (hiking boots / jumping boots) +# tile 147 (hiking boots / jumping boots) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2807,7 +2826,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 147 (mud boots / elven boots) +# tile 148 (mud boots / elven boots) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2826,7 +2845,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 148 (buckled boots / kicking boots) +# tile 149 (buckled boots / kicking boots) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2845,7 +2864,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 149 (riding boots / fumble boots) +# tile 150 (riding boots / fumble boots) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2864,7 +2883,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 150 (snow boots / levitation boots) +# tile 151 (snow boots / levitation boots) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2883,7 +2902,7 @@ P = (108, 145, 182) MMMAMAMAMAMAMAMM MMMMMMMMMMMMMMMM } -# tile 151 (wooden / adornment) +# tile 152 (wooden / adornment) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2902,7 +2921,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 152 (granite / gain strength) +# tile 153 (granite / gain strength) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2921,7 +2940,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 153 (opal / gain constitution) +# tile 154 (opal / gain constitution) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2940,7 +2959,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 154 (clay / increase accuracy) +# tile 155 (clay / increase accuracy) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2959,7 +2978,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 155 (coral / increase damage) +# tile 156 (coral / increase damage) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2978,7 +2997,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 156 (black onyx / protection) +# tile 157 (black onyx / protection) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2997,7 +3016,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 157 (moonstone / regeneration) +# tile 158 (moonstone / regeneration) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3016,7 +3035,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 158 (tiger eye / searching) +# tile 159 (tiger eye / searching) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3035,7 +3054,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 159 (jade / stealth) +# tile 160 (jade / stealth) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3054,7 +3073,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 160 (bronze / sustain ability) +# tile 161 (bronze / sustain ability) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3073,7 +3092,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 161 (agate / levitation) +# tile 162 (agate / levitation) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3092,7 +3111,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 162 (topaz / hunger) +# tile 163 (topaz / hunger) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3111,7 +3130,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 163 (sapphire / aggravate monster) +# tile 164 (sapphire / aggravate monster) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3130,7 +3149,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 164 (ruby / conflict) +# tile 165 (ruby / conflict) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3149,7 +3168,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 165 (diamond / warning) +# tile 166 (diamond / warning) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3168,7 +3187,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 166 (pearl / poison resistance) +# tile 167 (pearl / poison resistance) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3187,7 +3206,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 167 (iron / fire resistance) +# tile 168 (iron / fire resistance) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3206,7 +3225,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 168 (brass / cold resistance) +# tile 169 (brass / cold resistance) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3225,7 +3244,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 169 (copper / shock resistance) +# tile 170 (copper / shock resistance) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3244,7 +3263,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 170 (twisted / free action) +# tile 171 (twisted / free action) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3263,7 +3282,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 171 (steel / slow digestion) +# tile 172 (steel / slow digestion) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3282,7 +3301,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 172 (silver / teleportation) +# tile 173 (silver / teleportation) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3301,7 +3320,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 173 (gold / teleport control) +# tile 174 (gold / teleport control) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3320,7 +3339,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 174 (ivory / polymorph) +# tile 175 (ivory / polymorph) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3339,7 +3358,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 175 (emerald / polymorph control) +# tile 176 (emerald / polymorph control) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3358,7 +3377,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 176 (wire / invisibility) +# tile 177 (wire / invisibility) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3377,7 +3396,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 177 (engagement / see invisible) +# tile 178 (engagement / see invisible) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3396,7 +3415,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 178 (shiny / protection from shape changers) +# tile 179 (shiny / protection from shape changers) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3415,7 +3434,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 179 (circular / amulet of ESP) +# tile 180 (circular / amulet of ESP) { MMMMMMMMMMMMMMMM MMMMMMLLLLLAAMMM @@ -3434,7 +3453,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 180 (spherical / amulet of life saving) +# tile 181 (spherical / amulet of life saving) { MMMMMMMMMMMMMMMM MMMMMMLLLLLAAMMM @@ -3453,7 +3472,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 181 (oval / amulet of strangulation) +# tile 182 (oval / amulet of strangulation) { MMMMMMMMMMMMMMMM MMMMMMLLLLLLAAMM @@ -3472,7 +3491,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 182 (triangular / amulet of restful sleep) +# tile 183 (triangular / amulet of restful sleep) { MMMMMMMMMMMMMMMM MMMMMMLLLLLAAMMM @@ -3491,7 +3510,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 183 (pyramidal / amulet versus poison) +# tile 184 (pyramidal / amulet versus poison) { MMMMMMMMMMMMMMMM MMMMMMLLLLLAAMMM @@ -3510,7 +3529,7 @@ P = (108, 145, 182) MMMMKJJJJJJJJAMM MMMMMMMAAAAAAAMM } -# tile 184 (square / amulet of change) +# tile 185 (square / amulet of change) { MMMMMMMMMMMMMMMM MMMMMMLLLLLAAMMM @@ -3529,7 +3548,7 @@ P = (108, 145, 182) MMMMMMMAAAAAMMMM MMMMMMMMMMMMMMMM } -# tile 185 (concave / amulet of unchanging) +# tile 186 (concave / amulet of unchanging) { MMMMMMMMMMMMMMMM MMMMMMLLLLLAAMMM @@ -3548,7 +3567,7 @@ P = (108, 145, 182) MMMMMMMKCCAAMMMM MMMMMMMMAAAMMMMM } -# tile 186 (hexagonal / amulet of reflection) +# tile 187 (hexagonal / amulet of reflection) { MMMMMMMMMMMMMMMM MMMMMMLLLLLAAMMM @@ -3567,7 +3586,7 @@ P = (108, 145, 182) MMMMMMMMAAAMMMMM MMMMMMMMMMMMMMMM } -# tile 187 (octagonal / amulet of magical breathing) +# tile 188 (octagonal / amulet of magical breathing) { MMMMMMMMMMMMMMMM MMMMMMLLLLLAAMMM @@ -3586,7 +3605,7 @@ P = (108, 145, 182) MMMMMMMKKKAAMMMM MMMMMMMMAAAMMMMM } -# tile 188 (Amulet of Yendor / cheap plastic imitation of the Amulet of Yendor) +# tile 189 (Amulet of Yendor / cheap plastic imitation of the Amulet of Yendor) { MMMMMMMMMMMMMMMM MMMMMMHHHHHAAMMM @@ -3605,7 +3624,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 189 (Amulet of Yendor / Amulet of Yendor) +# tile 190 (Amulet of Yendor / Amulet of Yendor) { MMMMMMMMMMMMMMMM MMMMMMHHHHHAAMMM @@ -3624,7 +3643,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 190 (large box) +# tile 191 (large box) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3643,7 +3662,7 @@ P = (108, 145, 182) CKKKKKKKKKKJAAMM MAAAAAAAAAAAAMMM } -# tile 191 (chest) +# tile 192 (chest) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3662,7 +3681,7 @@ P = (108, 145, 182) CKKKKKKKKKKJAAMM MAAAAAAAAAAAAMMM } -# tile 192 (ice box) +# tile 193 (ice box) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3681,7 +3700,7 @@ P = (108, 145, 182) NBBBBBBBBBBPAAMM MAAAAAAAAAAAAMMM } -# tile 193 (bag / sack) +# tile 194 (bag / sack) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3700,7 +3719,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 194 (bag / oilskin sack) +# tile 195 (bag / oilskin sack) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3719,7 +3738,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 195 (bag / bag of holding) +# tile 196 (bag / bag of holding) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3738,7 +3757,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 196 (bag / bag of tricks) +# tile 197 (bag / bag of tricks) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3757,7 +3776,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 197 (key / skeleton key) +# tile 198 (key / skeleton key) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3776,7 +3795,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 198 (lock pick) +# tile 199 (lock pick) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3795,7 +3814,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 199 (credit card) +# tile 200 (credit card) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3814,7 +3833,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 200 (candle / tallow candle) +# tile 201 (candle / tallow candle) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3833,7 +3852,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 201 (candle / wax candle) +# tile 202 (candle / wax candle) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3852,7 +3871,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 202 (brass lantern) +# tile 203 (brass lantern) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3871,7 +3890,7 @@ P = (108, 145, 182) MMMMMAAAAAAAMMMM MMMMMMMMMMMMMMMM } -# tile 203 (lamp / oil lamp) +# tile 204 (lamp / oil lamp) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3890,7 +3909,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 204 (lamp / magic lamp) +# tile 205 (lamp / magic lamp) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3909,7 +3928,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 205 (expensive camera) +# tile 206 (expensive camera) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3928,7 +3947,7 @@ P = (108, 145, 182) MMMPPPPPPPPPPPPM MMMMMMMMMMMMMMMM } -# tile 206 (looking glass / mirror) +# tile 207 (looking glass / mirror) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3947,7 +3966,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 207 (glass orb / crystal ball) +# tile 208 (glass orb / crystal ball) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3966,7 +3985,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 208 (lenses) +# tile 209 (lenses) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -3985,7 +4004,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 209 (blindfold) +# tile 210 (blindfold) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4004,7 +4023,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 210 (towel) +# tile 211 (towel) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4023,7 +4042,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 211 (saddle) +# tile 212 (saddle) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4042,7 +4061,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 212 (leash) +# tile 213 (leash) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4061,7 +4080,7 @@ P = (108, 145, 182) MMMMMAAAAMMMMMMM MMMMMMMMMMMMMMMM } -# tile 213 (stethoscope) +# tile 214 (stethoscope) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4080,7 +4099,7 @@ P = (108, 145, 182) MMMMMMMMAAAMMMMM MMMMMMMMMMMMMMMM } -# tile 214 (tinning kit) +# tile 215 (tinning kit) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4099,7 +4118,7 @@ P = (108, 145, 182) MMMMMMAAAMMMMMMM MMMMMMMMMMMMMMMM } -# tile 215 (tin opener) +# tile 216 (tin opener) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4118,7 +4137,7 @@ P = (108, 145, 182) MMMMMMMMAAMMMMMM MMMMMMMMMMMMMMMM } -# tile 216 (can of grease) +# tile 217 (can of grease) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4137,7 +4156,7 @@ P = (108, 145, 182) MMMMMMMAAAAMMMMM MMMMMMMMMMMMMMMM } -# tile 217 (figurine) +# tile 218 (figurine) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4156,7 +4175,7 @@ P = (108, 145, 182) MMMMMJJJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 218 (magic marker) +# tile 219 (magic marker) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4175,7 +4194,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 219 (land mine) +# tile 220 (land mine) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4194,7 +4213,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 220 (beartrap) +# tile 221 (beartrap) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4213,7 +4232,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 221 (whistle / tin whistle) +# tile 222 (whistle / tin whistle) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4232,7 +4251,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 222 (whistle / magic whistle) +# tile 223 (whistle / magic whistle) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4251,7 +4270,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 223 (flute / wooden flute) +# tile 224 (flute / wooden flute) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4270,7 +4289,7 @@ P = (108, 145, 182) MMAMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 224 (flute / magic flute) +# tile 225 (flute / magic flute) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4289,7 +4308,7 @@ P = (108, 145, 182) MMAMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 225 (horn / tooled horn) +# tile 226 (horn / tooled horn) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4308,7 +4327,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 226 (horn / frost horn) +# tile 227 (horn / frost horn) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4327,7 +4346,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 227 (horn / fire horn) +# tile 228 (horn / fire horn) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4346,7 +4365,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 228 (horn / horn of plenty) +# tile 229 (horn / horn of plenty) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4365,7 +4384,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 229 (harp / wooden harp) +# tile 230 (harp / wooden harp) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4384,7 +4403,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 230 (harp / magic harp) +# tile 231 (harp / magic harp) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4403,7 +4422,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 231 (bell) +# tile 232 (bell) { MMMMMMMMMMMMMMMM MMMMMMMKAMMMMMMM @@ -4422,7 +4441,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 232 (bugle) +# tile 233 (bugle) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4441,7 +4460,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 233 (drum / leather drum) +# tile 234 (drum / leather drum) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4460,7 +4479,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 234 (drum / drum of earthquake) +# tile 235 (drum / drum of earthquake) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4479,7 +4498,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 235 (pick-axe) +# tile 236 (pick-axe) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4498,7 +4517,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 236 (iron hook / grappling hook) +# tile 237 (iron hook / grappling hook) { MMMMMMMMMMMMMNMM MMMMMMMMMMMMMMPM @@ -4517,7 +4536,7 @@ P = (108, 145, 182) MMOOAMMOOOAMMMMM MMMMOOOAAMMMMMMM } -# tile 237 (unicorn horn) +# tile 238 (unicorn horn) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4536,7 +4555,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 238 (candelabrum / Candelabrum of Invocation) +# tile 239 (candelabrum / Candelabrum of Invocation) { MMMMMMMNMMMMMMMM MMMMMMMDMMMMMMMM @@ -4555,7 +4574,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 239 (silver bell / Bell of Opening) +# tile 240 (silver bell / Bell of Opening) { MMMMMMMMMMMMMMMM MMMMMMMOAMMMMMMM @@ -4574,7 +4593,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 240 (tripe ration) +# tile 241 (tripe ration) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4593,7 +4612,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 241 (corpse) +# tile 242 (corpse) { MMMMMMMMMMMMMMMM MMMMMDMDPLNMMMMM @@ -4612,7 +4631,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 242 (egg) +# tile 243 (egg) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4631,7 +4650,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 243 (meatball) +# tile 244 (meatball) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4650,7 +4669,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 244 (meat stick) +# tile 245 (meat stick) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4669,7 +4688,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 245 (huge chunk of meat) +# tile 246 (huge chunk of meat) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4688,7 +4707,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 246 (meat ring) +# tile 247 (meat ring) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4707,7 +4726,7 @@ P = (108, 145, 182) MMMMMMAAAAAMMMMM MMMMMMMMMMMMMMMM } -# tile 247 (kelp frond) +# tile 248 (kelp frond) { MMMMFAMMMMMMMMMM MMMMFFAMMMMMMMMM @@ -4726,7 +4745,7 @@ P = (108, 145, 182) MMMMMFFFFAMMMMMM MMMMMMFFFFAMMMMM } -# tile 248 (eucalyptus leaf) +# tile 249 (eucalyptus leaf) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4745,7 +4764,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 249 (apple) +# tile 250 (apple) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4764,7 +4783,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 250 (orange) +# tile 251 (orange) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4783,7 +4802,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 251 (pear) +# tile 252 (pear) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4802,7 +4821,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 252 (melon) +# tile 253 (melon) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4821,7 +4840,7 @@ P = (108, 145, 182) MMMMMMAAAMMMMMMM MMMMMMMMMMMMMMMM } -# tile 253 (banana) +# tile 254 (banana) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4840,7 +4859,7 @@ P = (108, 145, 182) MMMMMAAAAAMMMMMM MMMMMMMMMMMMMMMM } -# tile 254 (carrot) +# tile 255 (carrot) { MMMMMMMMMMMMMMMM MMMMMMMMMMFMMFMM @@ -4859,7 +4878,7 @@ P = (108, 145, 182) MMMAMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 255 (sprig of wolfsbane) +# tile 256 (sprig of wolfsbane) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4878,7 +4897,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 256 (clove of garlic) +# tile 257 (clove of garlic) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4897,7 +4916,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 257 (slime mold) +# tile 258 (slime mold) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4916,7 +4935,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 258 (lump of royal jelly) +# tile 259 (lump of royal jelly) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4935,7 +4954,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 259 (cream pie) +# tile 260 (cream pie) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4954,7 +4973,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 260 (candy bar) +# tile 261 (candy bar) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4973,7 +4992,7 @@ P = (108, 145, 182) MMMMAMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 261 (fortune cookie) +# tile 262 (fortune cookie) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -4992,7 +5011,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 262 (pancake) +# tile 263 (pancake) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5011,7 +5030,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 263 (lembas wafer) +# tile 264 (lembas wafer) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5030,7 +5049,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 264 (cram ration) +# tile 265 (cram ration) { MMMMMMMMMMMMMMMM MMMJKAMMMMMMMMMM @@ -5049,7 +5068,7 @@ P = (108, 145, 182) MMMMMAAAAAAMMMMM MMMMMMMMMMMMMMMM } -# tile 265 (food ration) +# tile 266 (food ration) { MMMJJAMMMMMMMMMM MMMBPAMMMMMMMMMM @@ -5068,7 +5087,7 @@ P = (108, 145, 182) MMMMKKKKKKKKKAMM MMMMMAAAAAAAAMMM } -# tile 266 (K-ration) +# tile 267 (K-ration) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5087,7 +5106,7 @@ P = (108, 145, 182) MMMMKKKKKKKKKAMM MMMMMAAAAAAAAMMM } -# tile 267 (C-ration) +# tile 268 (C-ration) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5106,7 +5125,7 @@ P = (108, 145, 182) MMMMKKKKKKKKKAMM MMMMMAAAAAAAAMMM } -# tile 268 (tin) +# tile 269 (tin) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5125,7 +5144,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 269 (ruby / gain ability) +# tile 270 (ruby / gain ability) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5144,7 +5163,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 270 (pink / restore ability) +# tile 271 (pink / restore ability) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5163,7 +5182,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 271 (orange / confusion) +# tile 272 (orange / confusion) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5182,7 +5201,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 272 (yellow / blindness) +# tile 273 (yellow / blindness) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5201,7 +5220,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 273 (emerald / paralysis) +# tile 274 (emerald / paralysis) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5220,7 +5239,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 274 (dark green / speed) +# tile 275 (dark green / speed) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5239,7 +5258,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 275 (cyan / levitation) +# tile 276 (cyan / levitation) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5258,7 +5277,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 276 (sky blue / hallucination) +# tile 277 (sky blue / hallucination) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5277,7 +5296,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 277 (brilliant blue / invisibility) +# tile 278 (brilliant blue / invisibility) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5296,7 +5315,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 278 (magenta / see invisible) +# tile 279 (magenta / see invisible) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5315,7 +5334,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 279 (purple-red / healing) +# tile 280 (purple-red / healing) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5334,7 +5353,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 280 (puce / extra healing) +# tile 281 (puce / extra healing) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5353,7 +5372,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 281 (milky / gain level) +# tile 282 (milky / gain level) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5372,7 +5391,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 282 (swirly / enlightenment) +# tile 283 (swirly / enlightenment) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5391,7 +5410,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 283 (bubbly / monster detection) +# tile 284 (bubbly / monster detection) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5410,7 +5429,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 284 (smoky / object detection) +# tile 285 (smoky / object detection) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5429,7 +5448,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 285 (cloudy / gain energy) +# tile 286 (cloudy / gain energy) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5448,7 +5467,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 286 (effervescent / sleeping) +# tile 287 (effervescent / sleeping) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5467,7 +5486,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 287 (black / full healing) +# tile 288 (black / full healing) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5486,7 +5505,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 288 (golden / polymorph) +# tile 289 (golden / polymorph) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5505,7 +5524,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 289 (brown / booze) +# tile 290 (brown / booze) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5524,7 +5543,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 290 (fizzy / sickness) +# tile 291 (fizzy / sickness) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5543,7 +5562,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 291 (dark / fruit juice) +# tile 292 (dark / fruit juice) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5562,7 +5581,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 292 (white / acid) +# tile 293 (white / acid) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5581,7 +5600,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 293 (murky / oil) +# tile 294 (murky / oil) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5600,7 +5619,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 294 (clear / water) +# tile 295 (clear / water) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5619,7 +5638,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 295 (ZELGO MER / enchant armor) +# tile 296 (ZELGO MER / enchant armor) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5638,7 +5657,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 296 (JUYED AWK YACC / destroy armor) +# tile 297 (JUYED AWK YACC / destroy armor) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5657,7 +5676,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 297 (NR 9 / confuse monster) +# tile 298 (NR 9 / confuse monster) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5676,7 +5695,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 298 (XIXAXA XOXAXA XUXAXA / scare monster) +# tile 299 (XIXAXA XOXAXA XUXAXA / scare monster) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5695,7 +5714,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 299 (PRATYAVAYAH / remove curse) +# tile 300 (PRATYAVAYAH / remove curse) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5714,7 +5733,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 300 (DAIYEN FOOELS / enchant weapon) +# tile 301 (DAIYEN FOOELS / enchant weapon) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5733,7 +5752,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 301 (LEP GEX VEN ZEA / create monster) +# tile 302 (LEP GEX VEN ZEA / create monster) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5752,7 +5771,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 302 (PRIRUTSENIE / taming) +# tile 303 (PRIRUTSENIE / taming) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5771,7 +5790,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 303 (ELBIB YLOH / genocide) +# tile 304 (ELBIB YLOH / genocide) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5790,7 +5809,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 304 (VERR YED HORRE / light) +# tile 305 (VERR YED HORRE / light) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5809,7 +5828,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 305 (VENZAR BORGAVVE / teleportation) +# tile 306 (VENZAR BORGAVVE / teleportation) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5828,7 +5847,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 306 (THARR / gold detection) +# tile 307 (THARR / gold detection) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5847,7 +5866,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 307 (YUM YUM / food detection) +# tile 308 (YUM YUM / food detection) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5866,7 +5885,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 308 (KERNOD WEL / identify) +# tile 309 (KERNOD WEL / identify) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5885,7 +5904,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 309 (ELAM EBOW / magic mapping) +# tile 310 (ELAM EBOW / magic mapping) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5904,7 +5923,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 310 (DUAM XNAHT / amnesia) +# tile 311 (DUAM XNAHT / amnesia) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5923,7 +5942,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 311 (ANDOVA BEGARIN / fire) +# tile 312 (ANDOVA BEGARIN / fire) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5942,7 +5961,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 312 (KIRJE / earth) +# tile 313 (KIRJE / earth) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5961,7 +5980,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 313 (VE FORBRYDERNE / punishment) +# tile 314 (VE FORBRYDERNE / punishment) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5980,7 +5999,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 314 (HACKEM MUCHE / charging) +# tile 315 (HACKEM MUCHE / charging) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -5999,7 +6018,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 315 (VELOX NEB / stinking cloud) +# tile 316 (VELOX NEB / stinking cloud) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6018,7 +6037,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 316 (FOOBIE BLETCH) +# tile 317 (FOOBIE BLETCH) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6037,7 +6056,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 317 (TEMOV) +# tile 318 (TEMOV) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6056,7 +6075,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 318 (GARVEN DEH) +# tile 319 (GARVEN DEH) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6075,7 +6094,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 319 (READ ME) +# tile 320 (READ ME) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6094,7 +6113,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 320 (stamped / mail) +# tile 321 (stamped / mail) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6113,7 +6132,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 321 (unlabeled / blank paper) +# tile 322 (unlabeled / blank paper) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6132,7 +6151,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 322 (parchment / dig) +# tile 323 (parchment / dig) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6151,7 +6170,7 @@ P = (108, 145, 182) MMMMMMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 323 (vellum / magic missile) +# tile 324 (vellum / magic missile) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6170,7 +6189,7 @@ P = (108, 145, 182) MMMMMMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 324 (ragged / fireball) +# tile 325 (ragged / fireball) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6189,7 +6208,7 @@ P = (108, 145, 182) MMMMMMOOJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 325 (dog eared / cone of cold) +# tile 326 (dog eared / cone of cold) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6208,7 +6227,7 @@ P = (108, 145, 182) MMMMMMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 326 (mottled / sleep) +# tile 327 (mottled / sleep) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6227,7 +6246,7 @@ P = (108, 145, 182) MMMMMMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 327 (stained / finger of death) +# tile 328 (stained / finger of death) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6246,7 +6265,7 @@ P = (108, 145, 182) MMMMMMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 328 (cloth / light) +# tile 329 (cloth / light) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6265,7 +6284,7 @@ P = (108, 145, 182) MMMMMMMPPPAAMMMM MMMMMMMMMMMMMMMM } -# tile 329 (leather / detect monsters) +# tile 330 (leather / detect monsters) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6284,7 +6303,7 @@ P = (108, 145, 182) MMMMMMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 330 (white / healing) +# tile 331 (white / healing) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6303,7 +6322,7 @@ P = (108, 145, 182) MMMMMMMPNNAAMMMM MMMMMMMMMMMMMMMM } -# tile 331 (pink / knock) +# tile 332 (pink / knock) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6322,7 +6341,7 @@ P = (108, 145, 182) MMMMMMMIIIAAMMMM MMMMMMMMMMMMMMMM } -# tile 332 (red / force bolt) +# tile 333 (red / force bolt) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6341,7 +6360,7 @@ P = (108, 145, 182) MMMMMMMDDDAAMMMM MMMMMMMMMMMMMMMM } -# tile 333 (orange / confuse monster) +# tile 334 (orange / confuse monster) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6360,7 +6379,7 @@ P = (108, 145, 182) MMMMMMMCCCAAMMMM MMMMMMMMMMMMMMMM } -# tile 334 (yellow / cure blindness) +# tile 335 (yellow / cure blindness) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6379,7 +6398,7 @@ P = (108, 145, 182) MMMMMMMHHHAAMMMM MMMMMMMMMMMMMMMM } -# tile 335 (velvet / drain life) +# tile 336 (velvet / drain life) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6398,7 +6417,7 @@ P = (108, 145, 182) MMMMMMMEEEAAMMMM MMMMMMMMMMMMMMMM } -# tile 336 (light green / slow monster) +# tile 337 (light green / slow monster) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6417,7 +6436,7 @@ P = (108, 145, 182) MMMMMMMGGGAAMMMM MMMMMMMMMMMMMMMM } -# tile 337 (dark green / wizard lock) +# tile 338 (dark green / wizard lock) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6436,7 +6455,7 @@ P = (108, 145, 182) MMMMMMMFFFAAMMMM MMMMMMMMMMMMMMMM } -# tile 338 (turquoise / create monster) +# tile 339 (turquoise / create monster) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6455,7 +6474,7 @@ P = (108, 145, 182) MMMMMMMFBBAAMMMM MMMMMMMMMMMMMMMM } -# tile 339 (cyan / detect food) +# tile 340 (cyan / detect food) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6474,7 +6493,7 @@ P = (108, 145, 182) MMMMMMMBBBAAMMMM MMMMMMMMMMMMMMMM } -# tile 340 (light blue / cause fear) +# tile 341 (light blue / cause fear) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6493,7 +6512,7 @@ P = (108, 145, 182) MMMMMMMBBBAAMMMM MMMMMMMMMMMMMMMM } -# tile 341 (dark blue / clairvoyance) +# tile 342 (dark blue / clairvoyance) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6512,7 +6531,7 @@ P = (108, 145, 182) MMMMMMMEEEAAMMMM MMMMMMMMMMMMMMMM } -# tile 342 (indigo / cure sickness) +# tile 343 (indigo / cure sickness) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6531,7 +6550,7 @@ P = (108, 145, 182) MMMMMMMEEEAAMMMM MMMMMMMMMMMMMMMM } -# tile 343 (magenta / charm monster) +# tile 344 (magenta / charm monster) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6550,7 +6569,7 @@ P = (108, 145, 182) MMMMMMMIIIAAMMMM MMMMMMMMMMMMMMMM } -# tile 344 (purple / haste self) +# tile 345 (purple / haste self) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6569,7 +6588,7 @@ P = (108, 145, 182) MMMMMMMIIIAAMMMM MMMMMMMMMMMMMMMM } -# tile 345 (violet / detect unseen) +# tile 346 (violet / detect unseen) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6588,7 +6607,7 @@ P = (108, 145, 182) MMMMMMMIIIAAMMMM MMMMMMMMMMMMMMMM } -# tile 346 (tan / levitation) +# tile 347 (tan / levitation) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6607,7 +6626,7 @@ P = (108, 145, 182) MMMMMMMKKKAAMMMM MMMMMMMMMMMMMMMM } -# tile 347 (plaid / extra healing) +# tile 348 (plaid / extra healing) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6626,7 +6645,7 @@ P = (108, 145, 182) MMMMMMMEFDAAMMMM MMMMMMMMMMMMMMMM } -# tile 348 (light brown / restore ability) +# tile 349 (light brown / restore ability) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6645,7 +6664,7 @@ P = (108, 145, 182) MMMMMMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 349 (dark brown / invisibility) +# tile 350 (dark brown / invisibility) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6664,7 +6683,7 @@ P = (108, 145, 182) MMMMMMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 350 (gray / detect treasure) +# tile 351 (gray / detect treasure) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6683,7 +6702,7 @@ P = (108, 145, 182) MMMMMMMPPPAAMMMM MMMMMMMMMMMMMMMM } -# tile 351 (wrinkled / remove curse) +# tile 352 (wrinkled / remove curse) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6702,7 +6721,7 @@ P = (108, 145, 182) MMMMMMJJKKAAMMMM MMMMMMMMMMMMMMMM } -# tile 352 (dusty / magic mapping) +# tile 353 (dusty / magic mapping) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6721,7 +6740,7 @@ P = (108, 145, 182) MKAKAMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 353 (bronze / identify) +# tile 354 (bronze / identify) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6740,7 +6759,7 @@ P = (108, 145, 182) MMMMMMMCCCAAMMMM MMMMMMMMMMMMMMMM } -# tile 354 (copper / turn undead) +# tile 355 (copper / turn undead) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6759,7 +6778,7 @@ P = (108, 145, 182) MMMMMMMJCJAAMMMM MMMMMMMMMMMMMMMM } -# tile 355 (silver / polymorph) +# tile 356 (silver / polymorph) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6778,7 +6797,7 @@ P = (108, 145, 182) MMMMMMMPPPAAMMMM MMMMMMMMMMMMMMMM } -# tile 356 (gold / teleport away) +# tile 357 (gold / teleport away) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6797,7 +6816,7 @@ P = (108, 145, 182) MMMMMMMHHHAAMMMM MMMMMMMMMMMMMMMM } -# tile 357 (glittering / create familiar) +# tile 358 (glittering / create familiar) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6816,7 +6835,7 @@ P = (108, 145, 182) MMMMMMMPPPANMMMM MMMMMMMNMMMMMMMM } -# tile 358 (shining / cancellation) +# tile 359 (shining / cancellation) { MMMMNMMMMMMMMMMM MMMMMMMNMMMMMMMM @@ -6835,7 +6854,7 @@ P = (108, 145, 182) MMMMMMMPPPAAMMMM MMMMMMMMMMMMMMMM } -# tile 359 (dull / protection) +# tile 360 (dull / protection) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6854,7 +6873,7 @@ P = (108, 145, 182) MMMMMMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 360 (thin / jumping) +# tile 361 (thin / jumping) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6873,7 +6892,7 @@ P = (108, 145, 182) MMMMMMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 361 (thick / stone to flesh) +# tile 362 (thick / stone to flesh) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6892,7 +6911,7 @@ P = (108, 145, 182) MMMMMMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 362 (plain / blank paper) +# tile 363 (plain / blank paper) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6911,7 +6930,7 @@ P = (108, 145, 182) MMMMMMMJJJAAMMMM MMMMMMMMMMMMMMMM } -# tile 363 (papyrus / Book of the Dead) +# tile 364 (papyrus / Book of the Dead) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6930,7 +6949,7 @@ P = (108, 145, 182) MMMMMMMAAAMMMMMM MMMMMMMMMMMMMMMM } -# tile 364 (glass / light) +# tile 365 (glass / light) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6949,7 +6968,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 365 (balsa / secret door detection) +# tile 366 (balsa / secret door detection) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6968,7 +6987,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 366 (crystal / enlightenment) +# tile 367 (crystal / enlightenment) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -6987,7 +7006,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 367 (maple / create monster) +# tile 368 (maple / create monster) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7006,7 +7025,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 368 (pine / wishing) +# tile 369 (pine / wishing) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7025,7 +7044,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 369 (oak / nothing) +# tile 370 (oak / nothing) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7044,7 +7063,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 370 (ebony / striking) +# tile 371 (ebony / striking) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7063,7 +7082,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 371 (marble / make invisible) +# tile 372 (marble / make invisible) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7082,7 +7101,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 372 (tin / slow monster) +# tile 373 (tin / slow monster) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7101,7 +7120,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 373 (brass / speed monster) +# tile 374 (brass / speed monster) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7120,7 +7139,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 374 (copper / undead turning) +# tile 375 (copper / undead turning) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7139,7 +7158,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 375 (silver / polymorph) +# tile 376 (silver / polymorph) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7158,7 +7177,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 376 (platinum / cancellation) +# tile 377 (platinum / cancellation) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7177,7 +7196,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 377 (iridium / teleportation) +# tile 378 (iridium / teleportation) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7196,7 +7215,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 378 (zinc / opening) +# tile 379 (zinc / opening) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7215,7 +7234,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 379 (aluminum / locking) +# tile 380 (aluminum / locking) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7234,7 +7253,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 380 (uranium / probing) +# tile 381 (uranium / probing) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7253,7 +7272,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 381 (iron / digging) +# tile 382 (iron / digging) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7272,7 +7291,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 382 (steel / magic missile) +# tile 383 (steel / magic missile) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7291,7 +7310,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 383 (hexagonal / fire) +# tile 384 (hexagonal / fire) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7310,7 +7329,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 384 (short / cold) +# tile 385 (short / cold) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7329,7 +7348,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 385 (runed / sleep) +# tile 386 (runed / sleep) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7348,7 +7367,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 386 (long / death) +# tile 387 (long / death) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMNOM @@ -7367,7 +7386,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 387 (curved / lightning) +# tile 388 (curved / lightning) { MMMMMMMMMMMMMMMM MMMMMMMNOMMMMMMM @@ -7386,7 +7405,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 388 (forked) +# tile 389 (forked) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7405,7 +7424,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 389 (spiked) +# tile 390 (spiked) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7424,7 +7443,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 390 (jeweled) +# tile 391 (jeweled) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7443,7 +7462,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 391 (gold piece) +# tile 392 (gold piece) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7462,7 +7481,7 @@ P = (108, 145, 182) MMMMMMMMMHAMMMMM MMMMMMMMMMMHAMMM } -# tile 392 (white / dilithium crystal) +# tile 393 (white / dilithium crystal) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7481,7 +7500,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 393 (white / diamond) +# tile 394 (white / diamond) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7500,7 +7519,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 394 (red / ruby) +# tile 395 (red / ruby) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7519,7 +7538,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 395 (orange / jacinth) +# tile 396 (orange / jacinth) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7538,7 +7557,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 396 (blue / sapphire) +# tile 397 (blue / sapphire) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7557,7 +7576,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 397 (black / black opal) +# tile 398 (black / black opal) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7576,7 +7595,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 398 (green / emerald) +# tile 399 (green / emerald) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7595,7 +7614,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 399 (green / turquoise) +# tile 400 (green / turquoise) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7614,7 +7633,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 400 (yellow / citrine) +# tile 401 (yellow / citrine) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7633,7 +7652,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 401 (green / aquamarine) +# tile 402 (green / aquamarine) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7652,7 +7671,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 402 (yellowish brown / amber) +# tile 403 (yellowish brown / amber) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7671,7 +7690,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 403 (yellowish brown / topaz) +# tile 404 (yellowish brown / topaz) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7690,7 +7709,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 404 (black / jet) +# tile 405 (black / jet) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7709,7 +7728,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 405 (white / opal) +# tile 406 (white / opal) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7728,7 +7747,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 406 (yellow / chrysoberyl) +# tile 407 (yellow / chrysoberyl) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7747,7 +7766,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 407 (red / garnet) +# tile 408 (red / garnet) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7766,7 +7785,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 408 (violet / amethyst) +# tile 409 (violet / amethyst) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7785,7 +7804,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 409 (red / jasper) +# tile 410 (red / jasper) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7804,7 +7823,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 410 (violet / fluorite) +# tile 411 (violet / fluorite) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7823,7 +7842,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 411 (black / obsidian) +# tile 412 (black / obsidian) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7842,7 +7861,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 412 (orange / agate) +# tile 413 (orange / agate) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7861,7 +7880,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 413 (green / jade) +# tile 414 (green / jade) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7880,7 +7899,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 414 (white / worthless piece of white glass) +# tile 415 (white / worthless piece of white glass) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7899,7 +7918,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 415 (blue / worthless piece of blue glass) +# tile 416 (blue / worthless piece of blue glass) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7918,7 +7937,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 416 (red / worthless piece of red glass) +# tile 417 (red / worthless piece of red glass) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7937,7 +7956,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 417 (yellowish brown / worthless piece of yellowish brown glass) +# tile 418 (yellowish brown / worthless piece of yellowish brown glass) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7956,7 +7975,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 418 (orange / worthless piece of orange glass) +# tile 419 (orange / worthless piece of orange glass) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7975,7 +7994,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 419 (yellow / worthless piece of yellow glass) +# tile 420 (yellow / worthless piece of yellow glass) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -7994,7 +8013,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 420 (black / worthless piece of black glass) +# tile 421 (black / worthless piece of black glass) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -8013,7 +8032,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 421 (green / worthless piece of green glass) +# tile 422 (green / worthless piece of green glass) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -8032,7 +8051,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 422 (violet / worthless piece of violet glass) +# tile 423 (violet / worthless piece of violet glass) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -8051,7 +8070,26 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 423 (gray / luckstone) +# tile 424 (gray / luckstone) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMPPPPPMMMMMM + MMMMPNPPPPPMMMMM + MMMPNPPPPPPPAMMM + MMPPPPPPPPPPPAAM + MMPPPPPPPPPPPAAA + MMMPPPPPPPPPAAAM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 425 (gray / loadstone) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -8070,7 +8108,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 424 (gray / loadstone) +# tile 426 (gray / touchstone) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -8089,7 +8127,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 425 (gray / flint) +# tile 427 (gray / flint) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -8108,7 +8146,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 426 (rock) +# tile 428 (rock) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -8127,7 +8165,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 427 (boulder) +# tile 429 (boulder) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -8146,7 +8184,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 428 (statue) +# tile 430 (statue) { MMMMMMMMMMMMMMMM MMMMMMMMJJMMMMMM @@ -8165,7 +8203,7 @@ P = (108, 145, 182) MMMMMJJJJJJAAMMM MMMMMMMMMMMMMMMM } -# tile 429 (heavy iron ball) +# tile 431 (heavy iron ball) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -8184,7 +8222,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 430 (iron chain) +# tile 432 (iron chain) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -8203,7 +8241,7 @@ P = (108, 145, 182) MMMMMMMMMMMPPMPA MMMMMMMMMMMMAAMM } -# tile 431 (splash of venom / blinding venom) +# tile 433 (splash of venom / blinding venom) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -8222,7 +8260,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 432 (splash of venom / acid venom) +# tile 434 (splash of venom / acid venom) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM diff --git a/win/share/other.txt b/win/share/other.txt index f3c99bc..14ec940 100644 --- a/win/share/other.txt +++ b/win/share/other.txt @@ -1173,7 +1173,7 @@ P = (108, 145, 182) MMMMMMAAAAAMMMMM MMMMMMMMMMMMMMMM } -# tile 61 (anti-magic trap field) +# tile 61 (anti-magic field) { MMMMMMMMMMMMMMMM MMMMMMDDDDDMMMMM @@ -1591,7 +1591,862 @@ P = (108, 145, 182) DDAAAAAAAAAAAAAA AAAAAAAAAAAAAAAA } -# tile 83 (cmap 83) +# tile 83 (explosion dark 0) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMAAA + MMMMMMAMMMAAAAAA + MMMMMMMMMAAAAAAA + MMMMMMMMMAAAAAAM + MMMMMMMMAAAAMMMA + MMMAAAMAAAAMMMAA + MAMMMAAAAAAMAAAA + MMMMMAAAAAAMAAAA + MMMMAAAAAAAMAAAA + MMMMMMMMAAMMAAMM + MMMMAAAAAAAAAAMM + MMMAAAAMMAAAMMMM + MMAAAAMMAAAAMMMM + MMAAAMMAAAAAMMMM +} +# tile 84 (explosion dark 1) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + AMMMMMMMMAAAAAAM + AAAAAAMAAAAAAAAM + AAAAAAMMMMMAAAAA + MMMAAAMAAAAAAAAA + AAAAAAMAAAAAAAAA + AAAAAAMAAAAAAAAM + AAMMMMMMMMMMMAMM + MMAAAMAMMMMMAAAA + MAMAMAMMMAMMMAAA + MPPAMMMAAMMMMMAA + MAMMMMMAMMMMAAAA + MMMMMAMMAMMMPAAA + MMMMMMMMAMAMAPAA + MPAMMMAPAAAAAAAA +} +# tile 85 (explosion dark 2) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMAMMMAMMM + AAAAAMMMMMMMMMMM + AAAAAAMMMAMMAMMM + AAAAAAAMMMMMMMMM + MMMMMMAAAAMMMMMM + AAAAAMMAAAAMMMMM + MMAAAAAAAAAAMMMM + AAMAAMMMMAAAMMMM + AAMAAAAAMAAAMMMM + AAPAAMAAAAAAMAMM + AAAMMMMMAAAAMMMM + AAMAMMAMAAAAMMMM + AMAAMMAMAAAAAMMM +} +# tile 86 (explosion dark 3) +{ + MMAAAMAMAAAMMMMM + MMAAAMAAAAAMAPMM + MMMAAMAAMMMMMMMA + MMMAAAAAAMMMMPPM + MMAAAMAAMMAMMPAP + MAAAMMMAMMMMPMAP + MAAAMAAAMAMMPMMP + MAAAMAAAMMMAAAAP + MAAAMAAAMMMMPAAA + MAAAMMAAMMMMPPAA + MMAAAMMAAMMMPAAP + MMMAAAMMMAPMPPPP + MMMMAAAMMMPMMPMA + MMMMMAAMMMMMAAAM + MMAMAMMMAAPMMMPA + MMMMAMMMMMMMMMPA +} +# tile 87 (explosion dark 4) +{ + APAAAMMPPAPAAAAA + MAPAMMAMAAAPAAAM + AAPMPAAMMAAAAAAM + PAPPPAAAMMAAPAMM + AAAPPAAAAPAAPMMA + AAPPMPPPAAAAAMMA + AAPAAAAAAAAAAAMM + APPAAAAAAAAAAAMM + AAAAAAAAAAAAPAAA + AAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAA + AAAAAAAAAAAAAMAA + AAAAAAAAAAAMHHMM +} +# tile 88 (explosion dark 5) +{ + MMAAAMAMAMAAAAMM + MMAAAAAMAMAAAAMM + MMAAAAAMAMAAAAMM + PMAAAAAMMMAAAAMM + PMAAPAPAAMAAAAMM + PMMMPMMAMMAAAMMM + MMMAPMMAAAAAAMMM + MPAAPAAAAAAAAMMM + AAPMMMPAAAAAMMMM + MMAAMPPAAMAMMMAM + AMMMPPMMMMMMMMMM + MAAAAPPAAMMMAMMM + MMAAMPPMAAAMMMMM + AMMMMMMAAAAAMMMM + AAAMMMAAAAAAAMMM + MMMMPPAAAAAAAAMM +} +# tile 89 (explosion dark 6) +{ + MMMMAMMMMMMMAMMP + MMMMAMMMMMMMAAMM + MAMMAAMMMPMMAMAM + MMMAAAMAMMPMMAAP + MMMAAAAMMAAPMMAM + MMMAAAAMMMMPMMMA + MMMAAAAMMAMMAMMA + MMMAAAAAMAAAMMMM + MMMAAAAAMMAAMMMM + MMMMAAAAAAAAAMMM + MMMMMAAAAAAAAAAA + MMMAMMAAAAAAAAAA + MMMMMMMMAAMAAAAA + MMMAMMMMMMMMAAAA + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 90 (explosion dark 7) +{ + PPPAAAAAPAAAMAMM + AAPPAAPPPPAMAMMM + PPPPPPPPPPAMMAPP + MPPAAMAAMAPAAMMM + MMAAAAMAMMAAAPAA + APPAPAPMAMAMPAAM + AMMPPAAAMMMMMMMP + AAMMMMMMMAMMMMMM + PAPAMAAAAAAAAAAP + AAMAPAAAAMMMMMMA + AAAMAMPPMMMAAAAA + AAAAAAMAMMAAAAAA + AAAAAAAAAAAAAAAA + AAAAMMMMMMMMMMAA + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 91 (explosion dark 8) +{ + MMMMPMMAAAAAAAMM + MMAMMAMAAMAMAAMM + PPMMAMMAAMAMAAMM + MMMAAAMAAMAMAAMM + MAAAAAMAAAMMAAMM + MMPAAMMAAAMAAAMM + MAAAMMAAAMMAAAMM + MAMAAMAAAAAAAAMM + AAMAAAAAAMAAAAMM + MMMAAAAAAAAAAAMM + MAAAAAAAAMAAAMMM + AAAAAAAAMMMMMMMM + AAAAAAMMMMAMMMMM + AAAMMMAMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 92 (explosion noxious 0) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMFFF + MMMMMMFMMMFFFFFF + MMMMMMMMMFFFFFFF + MMMMMMMMMFFFFFFM + MMMMMMMMFFFFMMMF + MMMFFFMFFFFMMMFF + MFMMMFFFFFFMFFFF + MMMMMFFFFFFMFFFF + MMMMFFFFFFFMFFFF + MMMMMMMMFFMMFFMM + MMMMFFFFFFFFFFMM + MMMFFFFMMFFFMMMM + MMFFFFMMFFFFMMMM + MMFFFMMFFFFFMMMM +} +# tile 93 (explosion noxious 1) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + FMMMMMMMMFFFFFFM + FFFFFFMFFFFFFFFM + FFFFFFMMMMMFFFFF + MMMFFFMFFFFFFFFF + FFFFFFMFFFFFFFFF + FFFFFFMFFFFFFFFM + FFMMMMMMMMMMMFMM + MMFFFMFMMMMMFFFF + MHMFMFMMMFMMMFFF + MGGFMMMFFMMMMMFF + MHMMMMMFMMMMFFFF + MMMMMFMMFMMMGFFF + MMMMMMMMFMFMFGFF + MGHMMMHGHHFFFFFF +} +# tile 94 (explosion noxious 2) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMFMMMFMMM + FFFFFMMMMMMMMMMM + FFFFFFMMMFMMFMMM + FFFFFFFMMMMMMMMM + MMMMMMFFFFMMMMMM + FFFFFMMFFFFMMMMM + MMFFFFFFFFFFMMMM + FFMFFMMMMFFFMMMM + FFMFFFFFMFFFMMMM + FFGFFMFFFFFFMFMM + FFFMMMMMFFFFMMMM + FFMFMMFMFFFFMMMM + FMFFMMFMFFFFFMMM +} +# tile 95 (explosion noxious 3) +{ + MMFFFMFMFFFMMMMM + MMFFFMFFFFFMFGMM + MMMFFMFFMMMMMMMF + MMMFFFFFFMMMMGGM + MMFFFMFFMMFMMGFG + MFFFMMMFMMMMGMFG + MFFFMFFFMHMMGMMG + MFFFMFFFMMMFFFFG + MFFFMFFFMMMMGFHH + MFFFMMFFMMMMGGHH + MMFFFMMFFMMMGHHG + MMMFFFMMMFGMGGGG + MMMMFFFMMMGMMGMH + MMMMMFFMMMMMHHFM + MMFMFMMMFHGMMMGH + MMMMFMMMMMMMMMGH +} +# tile 96 (explosion noxious 4) +{ + FGHFFMMGGFGHFFFF + MHGHMMFMFFHGFHFM + HFGMGHFMMHHHFFHM + GFGGGHHHMMHHGFMM + HHHGGHHHHGHHGMMF + HHGGMGGGHHHHFMMF + HHGHHHHHHHHHHFMM + HGGHHHHHHHHHHHMM + HHHHHHNNNNHHGHNH + GHHHHHHHNHHHHHNH + GHHGHGNNNNHHHHGF + GGNHNHNNNNHHHGGF + HHHHNHNNNHHHGGGG + HGGNGHNNNHHHGGGF + HHHHNHNHNMGGGMGF + GGGGNHHHGGGMHHMM +} +# tile 97 (explosion noxious 5) +{ + MMFFFMFMFMFFFFMM + MMFFFFFMFMFFFFMM + MMFFFFFMFMFFFFMM + GMFFFFFMMMFFFFMM + GMFFGFGFFMFFFFMM + GMMMGMGFMMFFFMMM + MMMFGMMFFFFFFMMM + MGFFFFFFFFFFFMMM + FFGMMMGFFFFFMMMM + MMFFMGGFFMFMMMFM + FMMMGGMMMMMMMMMM + MFFFFGGFFMMMFMMM + MMHFMGGMFFFMMMMM + HMMMMMMFFFFFMMMM + HFHMMMFFFFFFFMMM + MMMMGGFFFFFFFFMM +} +# tile 98 (explosion noxious 6) +{ + MMMMFMMMMMMMHMMG + MMMMFMMMMMMMFHMM + MFMMFFMMMGMMFMHM + MMMFFFMFMMGMMFFG + MMMFFFFMMFFGMMFM + MMMFFFFMMMMGMMMF + MMMFFFFMMFMMHMMF + MMMFFFFFMFFFMMMM + MMMFFFFFMMFFMMMM + MMMMFFFFFFFFFMMM + MMMMMFFFHFFFFFFF + MMMFMMFFFFFFFFFF + MMMMMMMMFFMFFFFF + MMMFMMMMMMMMFFFF + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 99 (explosion noxious 7) +{ + GGGHHHHHGHHHMHMM + HHGGHHGGGGHMFMMM + GGGGGGGGGGFMMFGG + MGGHFMFFMHGFFMMM + MMHHHHMFMMFFHGHF + HGGFGFGMHMHMGFFM + FMMGGFFHMMMMMMMG + HFMMMMMMMFMMMMMM + GHGFMFFFFFFFFFFG + HFMHGHFFFMMMMMMF + FFFMFMGGMMMFFFFF + FFFFFFMFMMFFFFFF + FFFFFFFFFFFFFFFF + FFFFMMMMMMMMMMFF + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 100 (explosion noxious 8) +{ + MMMMGMMFFFFFFFMM + MMFMMFMFFMFMFFMM + GGMMFMMFFMFMFFMM + MMMFFFMFFMFMFFMM + MFFFFFMFFFMMFFMM + MMGFFMMFFFMFFFMM + MFFFMMFFFMMFFFMM + MFMFFMFFFFFFFFMM + FFMFFFFFFMFFFFMM + MMMFFFFFFFFFFFMM + MFFFFFFFFMFFFMMM + FFFFFFFFMMMMMMMM + FFFFFFMMMMFMMMMM + FFFMMMFMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 101 (explosion muddy 0) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMJJJ + MMMMMMJMMMJJJJJJ + MMMMMMMMMJJJJJJJ + MMMMMMMMMJJJJJJK + MMMMMMMMJJJJKKKJ + MMMJJJMJJJJKKKJJ + MJMMMJJJJJJKJJJJ + MMMMMJJJJJJKJJJJ + MMMMJJJJJJJKJJJJ + MMMMMMMKJJKKJJKK + MMMMJJJJJJJJJJKK + MMMJJJJKKJJJKKKK + MMJJJJKKJJJJKKKK + MMJJJKKJJJJJKKKK +} +# tile 102 (explosion muddy 1) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + JMMMMMMMMJJJJJJM + JJJJJJKJJJJJJJJM + JJJJJJKKKKKJJJJJ + KKKJJJKJJJJJJJJJ + JJJJJJKJJJJJJJJJ + JJJJJJKJJJJJJJJK + JJKKKKKKKKKKKJKK + KKJJJKJKKKKKJJJJ + KLKJKJKKKJKKKJJJ + KCCJKKKJJKKKKKJJ + KLKKKKKJKKKKJJJJ + KKKKKJKKJKKKCJJJ + KKKKKKKKJKJKJCJJ + KCLKKKLCLLJJJJJJ +} +# tile 103 (explosion muddy 2) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMJMMMJMMM + JJJJJMMMMMMMMMMM + JJJJJJMMMJMMJMMM + JJJJJJJMMMMMMMMM + KKKKKKJJJJMMMMMM + JJJJJKKJJJJMMMMM + KKJJJJJJJJJJMMMM + JJKJJKKKKJJJMMMM + JJKJJJJJKJJJMMMM + JJCJJKJJJJJJMJMM + JJJKKKKKJJJJMMMM + JJKJKKJKJJJJMMMM + JKJJKKJKJJJJJMMM +} +# tile 104 (explosion muddy 3) +{ + MMJJJKJKJJJKKKKK + MMJJJKJJJJJKJCKK + MMMJJKJJKKKKKKKJ + MMMJJJJJJKKKKCCK + MMJJJKJJKKJKKCJC + MJJJKKKJKKKKCKJC + MJJJKJJJKLKKCKKC + MJJJKJJJKKKJJJJC + MJJJKJJJKKKKCJLL + MJJJKKJJKKKKCCLL + MMJJJKKJJKKKCLLC + MMMJJJKKKJCKCCCC + MMMMJJJKKKCKKCKL + MMMMMJJKKKKKLLJK + MMJMJKKKJLCKKKCL + MMMMJKKKKKKKKKCL +} +# tile 105 (explosion muddy 4) +{ + JCLJJKKCCJCLJJJJ + KLCLKKJKJJLCJLJK + LJCKCLJKKLLLJJLK + CJCCCLLLKKLLCJKK + LLLCCLLLLCLLCKKJ + LLCCKCCCLLLLJKKJ + LLCLLLLLLLLLLJKK + LCCLLLLLLLLLLLKK + LLLLLLCCCCLLCLCL + CLLLLLLLCLLLLLCL + CLLCLCCCCCLLLLCJ + CCCLCLCCCCLLLCCJ + LLLLCLCCCLLLCCCC + LCCCCLCCCLLLCCCJ + LLLLCLCLCKCCCKCJ + CCCCCLLLCCCKLLKK +} +# tile 106 (explosion muddy 5) +{ + KKJJJKJKJKJJJJMM + KKJJJJJKJKJJJJMM + KKJJJJJKJKJJJJMM + CKJJJJJKKKJJJJMM + CKJJCJCJJKJJJJMM + CKKKCKKJKKJJJMMM + KKKJCKKJJJJJJMMM + KCJJCJJJJJJJJMMM + JJCKKKCJJJJJMMMM + KKJJKCCJJKJMMMJM + JKKKCCKKKKMMMMMM + KJJJJCCJJKMMJMMM + KKLJKCCKJJJMMMMM + LKKKKKKJJJJJMMMM + LJLKKKJJJJJJJMMM + KKKKCCJJJJJJJJMM +} +# tile 107 (explosion muddy 6) +{ + MMMMJKKKKKKKLKKC + MMMMJKKKKKKKJLKK + MJMMJJKKKCKKJKLK + MMMJJJKJKKCKKJJC + MMMJJJJKKJJCKKJK + MMMJJJJKKKKCKKKJ + MMMJJJJKKJKKLKKJ + MMMJJJJJKJJJKKKK + MMMJJJJJKKJJKKKK + MMMMJJJJJJJJJKKK + MMMMMJJJLJJJJJJJ + MMMJMMJJJJJJJJJJ + MMMMMMMMJJMJJJJJ + MMMJMMMMMMMMJJJJ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 108 (explosion muddy 7) +{ + CCCLLLLLCLLLKLKK + LLCCLLCCCCLKJKKK + CCCCCCCCCCJKKJCC + KCCLJKJJKLCJJKKK + KKLLLLKJKKJJLCLJ + LCCJCJCKLKLKCJJK + JKKCCJJLKKKKKKKC + LJKKKKKKKJKKKKKK + CLCJKJJJJJJJJJJC + LJKLCLJJJKKKKKKJ + JJJKJKCCKKKJJJJJ + JJJJJJKJKKJJJJJJ + JJJJJJJJJJJJJJJJ + JJJJMMMMMMMMMMJJ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 109 (explosion muddy 8) +{ + KKKKCKKJJJJJJJMM + KKJKKJKJJKJKJJMM + CCKKJKKJJKJKJJMM + KKKJJJKJJKJKJJMM + KJJJJJKJJJKKJJMM + KKCJJKKJJJKJJJMM + KJJJKKJJJKKJJJMM + KJKJJKJJJJJJJJMM + JJKJJJJJJKJJJJMM + KKKJJJJJJJJJJJMM + KJJJJJJJJMJJJMMM + JJJJJJJJMMMMMMMM + JJJJJJMMMMJMMMMM + JJJMMMJMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 110 (explosion wet 0) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMEEE + MMMMMMEMMMEEEEEE + MMMMMMMMMEEEEEEE + MMMMMMMMMEEEEEEP + MMMMMMMMEEEEPPPE + MMMEEEMEEEEPPPEE + MEMMMEEEEEEPEEEE + MMMMMEEEEEEPEEEE + MMMMEEEEEEEPEEEE + MMMMMMMPEEPPEEPP + MMMMEEEEEEEEEEPP + MMMEEEEPPEEEPPPP + MMEEEEPPEEEEPPPP + MMEEEPPEEEEEPPPP +} +# tile 111 (explosion wet 1) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + EMMMMMMMMEEEEEEM + EEEEEEPEEEEEEEEM + EEEEEEPPPPPEEEEE + PPPEEEPEEEEEEEEE + EEEEEEPEEEEEEEEE + EEEEEEPEEEEEEEEP + EEPPPPPPPPPPPEPP + PPEEEPEPPPPPEEEE + PNPEPEPPPEPPPEEE + PBBEPPPEEPPPPPEE + PNPPPPPEPPPPEEEE + PPPPPEPPEPPPBEEE + PPPPPPPPEPEPEBEE + PBNPPPNBEEEEEEEE +} +# tile 112 (explosion wet 2) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMEMMMEMMM + EEEEEMMMMMMMMMMM + EEEEEEMMMEMMEMMM + EEEEEEEMMMMMMMMM + PPPPPPEEEEMMMMMM + EEEEEPPEEEEMMMMM + PPEEEEEEEEEEMMMM + EEPEEPPPPEEEMMMM + EEPEEEEEPEEEMMMM + EEBEEPEEEEEEMEMM + EEEPPPPPEEEEMMMM + EEPEPPEPEEEEMMMM + EPEEPPEPEEEEEMMM +} +# tile 113 (explosion wet 3) +{ + MMEEEPEPEEEPPPPP + MMEEEPEEEEEPEBPP + MMMEEPEEPPPPPPPE + MMMEEEEEEPPPPBBP + MMEEEPEEPPEPPBEB + MEEEPPPEPPPPBPEB + MEEEPEEEPNPPBPPB + MEEEPEEEPPPEEEEB + MEEEPEEEPPPPBEEE + MEEEPPEEPPPPBBEE + MMEEEPPEEPPPBEEB + MMMEEEPPPEBPBBBB + MMMMEEEPPPBPPBPN + MMMMMEEPPPPPNNEP + MMEMEPPPENBPPPBE + MMMMEPPPPPPPPPBE +} +# tile 114 (explosion wet 4) +{ + EBNEEPPBBEBNEEEE + PNBNPPEPEEEBENEP + NEBPBEEPPEEEEENP + BEBBBEEEPPEEBEPP + EEEBBEEEEBEEBPPE + EEBBPBBBEEEEEPPE + EEBEEEEEEEEEEEPP + EBBEEEEEEEEEEEPP + EEEEEEEEEEEEBEEE + BEEEEEEEEEEEEEEE + BEEBEBEEEEEEEEBE + BBEEEEEEEEEEEBBE + EEEEEEEEEEEEBBBB + EBBEBEEEEEEEBBBE + EEEEEEEEEPBBBPBE + BBBBEEEEBBBPNNPP +} +# tile 115 (explosion wet 5) +{ + PPEEEPEPEPEEEEMM + PPEEEEEPEPEEEEMM + PPEEEEEPEPEEEEMM + BPEEEEEPPPEEEEMM + BPEEBEBEEPEEEEMM + BPPPBPPEPPEEEMMM + PPPEBPPEEEEEEMMM + PBEEBEEEEEEEEMMM + EEBPPPBEEEEEMMMM + PPEEPBBEEPEMMMEM + EPPPBBPPPPMMMMMM + PEEEEBBEEPMMEMMM + PPNEPBBPEEEMMMMM + NPPPPPPEEEEEMMMM + NENPPPEEEEEEEMMM + PPPPBBEEEEEEEEMM +} +# tile 116 (explosion wet 6) +{ + MMMMEPPPPPPPNPPB + MMMMEPPPPPPPENPP + MEMMEEPPPBPPEPNP + MMMEEEPEPPBPPEEB + MMMEEEEPPEEBPPEP + MMMEEEEPPPPBPPPE + MMMEEEEPPEPPNPPE + MMMEEEEEPEEEPPPP + MMMEEEEEPPEEPPPP + MMMMEEEEEEEEEPPP + MMMMMEEENEEEEEEE + MMMEMMEEEEEEEEEE + MMMMMMMMEEMEEEEE + MMMEMMMMMMMMEEEE + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 117 (explosion wet 7) +{ + BBBEEEEEBEEEPEPP + EEBBEEBBBBEPEPPP + BBBBBBBBBBEPPEBB + PBBEEPEEPNBEEPPP + PPEEEEPEPPEENBNE + NBBEBEBPNPNPBEEP + EPPBBEENPPPPPPPB + NEPPPPPPPEPPPPPP + BNBEPEEEEEEEEEEB + NEPNBNEEEPPPPPPE + EEEPEPBBPPPEEEEE + EEEEEEPEPPEEEEEE + EEEEEEEEEEEEEEEE + EEEEMMMMMMMMMMEE + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 118 (explosion wet 8) +{ + PPPPBPPEEEEEEEMM + PPEPPEPEEPEPEEMM + BBPPEPPEEPEPEEMM + PPPEEEPEEPEPEEMM + PEEEEEPEEEPPEEMM + PPBEEPPEEEPEEEMM + PEEEPPEEEPPEEEMM + PEPEEPEEEEEEEEMM + EEPEEEEEEPEEEEMM + PPPEEEEEEEEEEEMM + PEEEEEEEEMEEEMMM + EEEEEEEEMMMMMMMM + EEEEEEMMMMEMMMMM + EEEMMMEMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 119 (explosion magical 0) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMEEE + MMMMMMEMMMEEEEEE + MMMMMMMMMEEEEEEE + MMMMMMMMMEEEEEEC + MMMMMMMMEEEEIIIE + MMMEEEMEEEEIIIEE + MEMMMEEEEEEIEEEE + MMMMMEEEEEEIEEEE + MMMMEEEEEEEIEEEE + MMMMMMMIEEIIEEII + MMMMEEEEEEEEEEII + MMMEEEEIIEEEIIII + MMEEEEIIEEEEIIII + MMEEEIIEEEEEIIII +} +# tile 120 (explosion magical 1) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + EMMMMMMMMEEEEEEM + EEEEEEIEEEEEEEEM + EEEEEEIIIIIEEEEE + IIIEEEIEEEEEEEEE + EEEEEEIEEEEEEEEE + EEEEEEIEEEEEEEEI + EEIIIIIIIIIIIEII + IIEEEIEIIIIIEEEE + IHIEIEIIIEIIIEEE + ILLEIIIEEIIIIIEE + IHIIIIIEIIIIEEEE + IIIIIEIIEIIILEEE + IIIIIIIIEIEIELEE + ILHIIIHLHHEEEEEE +} +# tile 121 (explosion magical 2) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMEMMMEMMM + EEEEEMMMMMMMMMMM + EEEEEEMMMEMMEMMM + EEEEEEEMMMMMMMMM + IIIIIIEEEEMMMMMM + EEEEEIIEEEEMMMMM + IIEEEEEEEEEEMMMM + EEIEEIIIIEEEMMMM + EEIEEEEEIEEEMMMM + EELEEIEEEEEEMEMM + EEEIIIIIEEEEMMMM + EEIEIIEIEEEEMMMM + EIEEIIEIEEEEEMMM +} +# tile 122 (explosion magical 3) +{ + MMEEEIEIEEEIIIII + MMEEEIEEEEEIEIII + MMMEEIEEIIIIIIIE + MMMEEEEEEIIIIIII + MMEEEIEEIIEIIIEI + MEEEIIIEIIIIIIEI + MEEEIEEEINIIIIII + MEEEIEEEIIIEEEEI + MEEEIEEEIIIIIENN + MEEEIIEEIIIIIINN + MMEEEIIEEIIIINNI + MMMEEEIIIEIIIIII + MMMMEEEIIIIIIIIN + MMMMMEEIIIIINNEI + MMEMEIIIENIIIIIN + MMMMEIIIIIIIIIIN +} +# tile 123 (explosion magical 4) +{ + EINEEIIIIEINEEEE + ININIIEIEENIENEI + NEIIINEIINNNEENI + IEIIINNNIINNIEII + NNNIINNNNINNIIIE + NNIIIIIINNNNEIIE + NNINNNNNNNNNNEII + NIINNNNNNNNNNNII + NNNNNNNNNNNNINNN + INNNNNNNNNNNNNNN + INNININNNNNNNNIE + IINNNNNNNNNNNIIE + NNNNNNNNNNNNIIII + NIININNNNNNNIIIE + NNNNNNNNNIIIIIIE + IIIINNNNIIIINNII +} +# tile 124 (explosion magical 5) +{ + IIEEEIEIEIEEEEMM + IIEEEEEIEIEEEEMM + IIEEEEEIEIEEEEMM + IIEEEEEIIIEEEEMM + IIEEIEIEEIEEEEMM + IIIIIIIEIIEEEMMM + IIIEIIIEEEEEEMMM + IIEEIEEEEEEEEMMM + EEIIIIIEEEEEMMMM + IIEEIIIEEIEMMMEM + EIIIIIIIIIMMMMMM + IEEEEIIEEIMMEMMM + IINEIIIIEEEMMMMM + NIIIIIIEEEEEMMMM + NENIIIEEEEEEEMMM + IIIIIIEEEEEEEEMM +} +# tile 125 (explosion magical 6) +{ + MMMMEIIIIIIIHIII + MMMMEIIIIIIIEHII + MEMMEEIIIIIIEIHI + MMMEEEIEIIIIIEEI + MMMEEEEIIEEIIIEI + MMMEEEEIIIIIIIIE + MMMEEEEIIEIIHIIE + MMMEEEEEIEEEIIII + MMMEEEEEIIEEIIII + MMMMEEEEEEEEEIII + MMMMMEEEHEEEEEEE + MMMEMMEEEEEEEEEE + MMMMMMMMEEMEEEEE + MMMEMMMMMMMMEEEE + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 126 (explosion magical 7) +{ + IIINNNNNINNNINII + NNIINNIIIINIEIII + IIIIIIIIIIEIIEII + IIINEIEEINIEEIII + IINNNNIEIIEENINE + NIIEIEIININIIEEI + EIIIIEENIIIIIIII + NEIIIIIIIEIIIIII + INIEIEEEEEEEEEEI + NEININEEEIIIIIIE + EEEIEIIIIIIEEEEE + EEEEEEIEIIEEEEEE + EEEEEEEEEEEEEEEE + EEEEMMMMMMMMMMEE + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 127 (explosion magical 8) +{ + IIIIIIIEEEEEEEMM + IIEIIEIEEIEIEEMM + IIIIEIIEEIEIEEMM + IIIEEEIEEIEIEEMM + IEEEEEIEEEIIEEMM + IIIEEIIEEEIEEEMM + IEEEIIEEEIIEEEMM + IEIEEIEEEEEEEEMM + EEIEEEEEEIEEEEMM + IIIEEEEEEEEEEEMM + IEEEEEEEEMEEEMMM + EEEEEEEEMMMMMMMM + EEEEEEMMMMEMMMMM + EEEMMMEMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 128 (explosion fiery 0) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -1610,7 +2465,7 @@ P = (108, 145, 182) MMDDDDCCDDDDCCCC MMDDDCCDDDDDCCCC } -# tile 84 (cmap 84) +# tile 129 (explosion fiery 1) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -1629,7 +2484,7 @@ P = (108, 145, 182) CCCCCCCCDCDCDLDD CLHCCCHLHHDDDDDD } -# tile 85 (cmap 85) +# tile 130 (explosion fiery 2) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -1648,7 +2503,7 @@ P = (108, 145, 182) DDCDCCDCDDDDMMMM DCDDCCDCDDDDDMMM } -# tile 86 (cmap 86) +# tile 131 (explosion fiery 3) { MMDDDCDCDDDCCCCC MMDDDCDDDDDCDLCC @@ -1667,7 +2522,7 @@ P = (108, 145, 182) MMDMDCCCDHLCCCLH MMMMDCCCCCCCCCLH } -# tile 87 (cmap 87) +# tile 132 (explosion fiery 4) { DLHDDCCLLDLHDDDD CHLHCCDCDDHLDHDC @@ -1686,7 +2541,7 @@ P = (108, 145, 182) HHHHNHNHNCLLLCLD LLLLNHHHLLLCHHCC } -# tile 88 (cmap 88) +# tile 133 (explosion fiery 5) { CCDDDCDCDCDDDDMM CCDDDDDCDCDDDDMM @@ -1705,7 +2560,7 @@ P = (108, 145, 182) HDHCCCDDDDDDDMMM CCCCLLDDDDDDDDMM } -# tile 89 (cmap 89) +# tile 134 (explosion fiery 6) { MMMMDCCCCCCCHCCL MMMMDCCCCCCCDHCC @@ -1724,7 +2579,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 90 (cmap 90) +# tile 135 (explosion fiery 7) { LLLHHHHHLHHHCHCC HHLLHHLLLLHCDCCC @@ -1743,7 +2598,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 91 (cmap 91) +# tile 136 (explosion fiery 8) { CCCCLCCDDDDDDDMM CCDCCDCDDCDCDDMM @@ -1762,7 +2617,178 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 92 (zap 0 0) +# tile 137 (explosion frosty 0) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMEEE + MMMMMNEMMMEEEEEE + MMNMMMNMMENBEEEE + MNMNMNMMMEEEEEEP + MMMMNMMMEEEEPPPE + MMMNENMNEEEPPPEE + MENMMENEEEEPNBEE + MMMNMEEEEEEPEEEE + MMMMEENBEEEPEEEE + MMMMMMMPEEPPEEPP + MMMMEEEEEEEEEEPP + MMMEEEEPPEEEPPPP + MMEEEEPPNBEEPPPP + MMEEEPPEEEEEPPPP +} +# tile 138 (explosion frosty 1) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + EMMMMMMMMEEEEEEM + ENBEENPEEEENBEEM + EEEEEENPNPNEEEEE + PPBEEEPENEEEEEEE + EEEEEENNNNNEEEEE + EEEEEEPENEEENBEP + EEPPPPNPNPNPPPPP + PPEEENEPPPPNEEEE + PNPEPEPPPEPPPEEE + PBBEPPPEEPPNBPEE + PNPPPPPEPPPPEEEE + PPPPPEPPEPPPBEEE + PPPPPPPPEPEPEBEE + PBNPPPNBNNEEEEEE +} +# tile 139 (explosion frosty 2) +{ + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM + MMMMMMMMEMMMEMMM + EEEEEMMMMMMMMMMM + EEEEEEMMMEMMNMMM + EEEEEEENMMNNMMMM + PPPPPPENENMMMMMM + EEEEEPPENENMNMMM + PPEEEEEEEEENMNMM + EEPEEPPPPNNEMNMM + EEPEEEEENEEEMMMM + EEBEEPEEEEEEMEMM + EEEPPPPPEEEEMMMM + EEPEPPEPEEEEMMMM + EPEEPPEPEEEEEMMM +} +# tile 140 (explosion frosty 3) +{ + MMEEEPEPEEEPPPPP + MMEEEPEEEEEPEBPP + MMMEEPEEPPPPPPPE + MMMENENEEPPPPBBP + MMEEENEEPPEPPBEB + MEEENENEPPPPBPEB + MEEEPEEEPNPPBPPB + MEEEPEEEPPPEEEEB + MEEEPEEEPPPPBENN + MEEEPPEEPPPPBBNN + MMEEEPNEEPPPBNNB + MMMEENNNPEBPBBBB + MMMMEENPPPBPPBPN + MMMMMEEPPPPPNNEP + MMEMEPPPENBPPPBN + MMMMEPPPPPPPPPBN +} +# tile 141 (explosion frosty 4) +{ + EBNEEPPBBEBNEEEE + PNBNPPEPEENBENEP + NEBPBNEPPNNNEENP + BEBBBNNNPPNNBEPP + NNNBBNNNNBNNBPPE + NNBBPBBBNNNNEPPE + NNBNNNNNNNNNNEPP + NBBNNNNNNNNNNNPP + NNNNNNNNNNNNBNNN + BNNNNNNNNNNNNNNN + BNNBNBNNNNNNNNBE + BBNNNNNNNNNNNBBE + NNNNNNNNNNNNBBBB + NBBNBNNNNNNNBBBE + NNNNNNNNNPBBBPBE + BBBBNNNNBBBPNNPP +} +# tile 142 (explosion frosty 5) +{ + PPEEEPEPEPEEEEMM + PPEEEEEPEPEEEEMM + PPEEEEEPEPEEEEMM + BPEEEEEPPPEEEEMM + BPEEBEBEEPEEEEMM + BPPPBPPEPPEEEMMM + PPPEBPPENEEENMMM + PBEEBEEEENENEMMM + EEBPPPBNNNNNNNMM + PPEEPBBEENENMMEM + EPPPBBPPNPMMNMMM + PEEEEBBEEPMMEMMM + PPNEPBBPEEEMMMMM + NPPPPPPEEEEEMMMM + NENPPPEEEEEEEMMM + PPPPBBEEEEEEEEMM +} +# tile 143 (explosion frosty 6) +{ + MMMMEPPPPPPPNPPB + MMMMEPPPPPPPENPP + MEMMEEPPPBPPEPNP + MMMEEEPEPPBPPEEB + MMMEENEPPEEBPPEP + MMMNEEENPPPBPPPE + MMNENPNPNEPPNPPE + MMMNNENNPEEEPPPP + MNMPEEEPPNEEPPPP + MMMNNENNEEEEEPPP + MMNMNPNENEEEEEEE + MMMNMMENEEEEEEEE + MMMMMNMMEEMEEEEE + MMMEMMMMMMMMEEEE + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 144 (explosion frosty 7) +{ + BBBNNNNNBNNNPNPP + NNBBNNBBBBNPEPPP + BBBBBBBBBBEPPEBB + PBBNEPEEPNBEEPPP + PPNNNNPEPPEENBNE + NBBEBEBPNPNPBEEP + EPPBBEENPPPPPPPB + NEPPPPPPPEPPPPPP + BNBEPEEEEEEEEEEB + NEPNBNEEEPNENPPE + EEEPEPBBPPPNEEEE + EEEEEEPEPNNNNNEE + EEEEEEEEEEENEEEE + EEEEMMMMMMNMNMEE + MMMMMMMMMMMMMMMM + MMMMMMMMMMMMMMMM +} +# tile 145 (explosion frosty 8) +{ + PPPPBPPEEEEEEEMM + PPEPPEPEEPEPEEMM + BBPPEPPEEPEPNENM + PPPEEEPEEPEPENMM + PEEEEEPEEEPPNENM + PPBEEPNENEPEEEMM + PEEEPPENEPPEEEMM + PEPEENNNNNEEEEMM + EEPEEEENEPEEEEMM + PPPEEENENEEEEEMM + PEEEEEEEEMEEEMMM + EEEEEEEEMMMMMMMM + EEEEEEMMMMENMMMM + EEEMMMEMMMNMNMMM + MMMMMMMMMMMNMMMM + MMMMMMMMMMMMMMMM +} +# tile 146 (zap 0 0) { MMMMMMMIIMMMMMMM MMMMMMIIIIMMMMMM @@ -1781,7 +2807,7 @@ P = (108, 145, 182) MMMMMMIIIIMMMMMM MMMMMMMIIMMMMMMM } -# tile 93 (zap 0 1) +# tile 147 (zap 0 1) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -1800,7 +2826,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 94 (zap 0 2) +# tile 148 (zap 0 2) { IIIMMMMMMMMMMMMM IIIIMMMMMMMMMMMM @@ -1819,7 +2845,7 @@ P = (108, 145, 182) MMMMMMMMMMMMIIII MMMMMMMMMMMMMIII } -# tile 95 (zap 0 3) +# tile 149 (zap 0 3) { MMMMMMMMMMMMMIII MMMMMMMMMMMMIIII @@ -1838,7 +2864,7 @@ P = (108, 145, 182) IIIIMMMMMMMMMMMM IIIMMMMMMMMMMMMM } -# tile 96 (zap 1 0) +# tile 150 (zap 1 0) { MMMMMMMCCMMMMMMM MMMMMMCCCCMMMMMM @@ -1857,7 +2883,7 @@ P = (108, 145, 182) MMMMMMCCCCMMMMMM MMMMMMMCCMMMMMMM } -# tile 97 (zap 1 1) +# tile 151 (zap 1 1) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -1876,7 +2902,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 98 (zap 1 2) +# tile 152 (zap 1 2) { CCCMMMMMMMMMMMMM CCCCMMMMMMMMMMMM @@ -1895,7 +2921,7 @@ P = (108, 145, 182) MMMMMMMMMMMMCCCC MMMMMMMMMMMMMCCC } -# tile 99 (zap 1 3) +# tile 153 (zap 1 3) { MMMMMMMMMMMMMCCC MMMMMMMMMMMMCCCC @@ -1914,7 +2940,7 @@ P = (108, 145, 182) CCCCMMMMMMMMMMMM CCCMMMMMMMMMMMMM } -# tile 100 (zap 2 0) +# tile 154 (zap 2 0) { MMMMMMMNNMMMMMMM MMMMMMNNNNMMMMMM @@ -1933,7 +2959,7 @@ P = (108, 145, 182) MMMMMMNNNNMMMMMM MMMMMMMNNMMMMMMM } -# tile 101 (zap 2 1) +# tile 155 (zap 2 1) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -1952,7 +2978,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 102 (zap 2 2) +# tile 156 (zap 2 2) { NNNMMMMMMMMMMMMM NNNNMMMMMMMMMMMM @@ -1971,7 +2997,7 @@ P = (108, 145, 182) MMMMMMMMMMMMNNNN MMMMMMMMMMMMMNNN } -# tile 103 (zap 2 3) +# tile 157 (zap 2 3) { MMMMMMMMMMMMMNNN MMMMMMMMMMMMNNNN @@ -1990,7 +3016,7 @@ P = (108, 145, 182) NNNNMMMMMMMMMMMM NNNMMMMMMMMMMMMM } -# tile 104 (zap 3 0) +# tile 158 (zap 3 0) { MMMMMMMBBMMMMMMM MMMMMMBBBBMMMMMM @@ -2009,7 +3035,7 @@ P = (108, 145, 182) MMMMMMBBBBMMMMMM MMMMMMMBBMMMMMMM } -# tile 105 (zap 3 1) +# tile 159 (zap 3 1) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2028,7 +3054,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 106 (zap 3 2) +# tile 160 (zap 3 2) { BBBMMMMMMMMMMMMM BBBBMMMMMMMMMMMM @@ -2047,7 +3073,7 @@ P = (108, 145, 182) MMMMMMMMMMMMBBBB MMMMMMMMMMMMMBBB } -# tile 107 (zap 3 3) +# tile 161 (zap 3 3) { MMMMMMMMMMMMMBBB MMMMMMMMMMMMBBBB @@ -2066,7 +3092,7 @@ P = (108, 145, 182) BBBBMMMMMMMMMMMM BBBMMMMMMMMMMMMM } -# tile 108 (zap 4 0) +# tile 162 (zap 4 0) { MMMMMMMAAMMMMMMM MMMMMMAAAAMMMMMM @@ -2085,7 +3111,7 @@ P = (108, 145, 182) MMMMMMAAAAMMMMMM MMMMMMMAAMMMMMMM } -# tile 109 (zap 4 1) +# tile 163 (zap 4 1) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2104,7 +3130,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 110 (zap 4 2) +# tile 164 (zap 4 2) { AAAMMMMMMMMMMMMM AAAAMMMMMMMMMMMM @@ -2123,7 +3149,7 @@ P = (108, 145, 182) MMMMMMMMMMMMAAAA MMMMMMMMMMMMMAAA } -# tile 111 (zap 4 3) +# tile 165 (zap 4 3) { MMMMMMMMMMMMMAAA MMMMMMMMMMMMAAAA @@ -2142,7 +3168,7 @@ P = (108, 145, 182) AAAAMMMMMMMMMMMM AAAMMMMMMMMMMMMM } -# tile 112 (zap 5 0) +# tile 166 (zap 5 0) { MMMMMMMNNMMMMMMM MMMMMMNNNNMMMMMM @@ -2161,7 +3187,7 @@ P = (108, 145, 182) MMMMMMNNNNMMMMMM MMMMMMMNNMMMMMMM } -# tile 113 (zap 5 1) +# tile 167 (zap 5 1) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2180,7 +3206,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 114 (zap 5 2) +# tile 168 (zap 5 2) { NNNMMMMMMMMMMMMM NNNNMMMMMMMMMMMM @@ -2199,7 +3225,7 @@ P = (108, 145, 182) MMMMMMMMMMMMNNNN MMMMMMMMMMMMMNNN } -# tile 115 (zap 5 3) +# tile 169 (zap 5 3) { MMMMMMMMMMMMMNNN MMMMMMMMMMMMNNNN @@ -2218,7 +3244,7 @@ P = (108, 145, 182) NNNNMMMMMMMMMMMM NNNMMMMMMMMMMMMM } -# tile 116 (zap 6 0) +# tile 170 (zap 6 0) { MMMMMMMFFMMMMMMM MMMMMMFFFFMMMMMM @@ -2237,7 +3263,7 @@ P = (108, 145, 182) MMMMMMFFFFMMMMMM MMMMMMMFFMMMMMMM } -# tile 117 (zap 6 1) +# tile 171 (zap 6 1) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2256,7 +3282,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 118 (zap 6 2) +# tile 172 (zap 6 2) { FFFMMMMMMMMMMMMM FFFFMMMMMMMMMMMM @@ -2275,7 +3301,7 @@ P = (108, 145, 182) MMMMMMMMMMMMFFFF MMMMMMMMMMMMMFFF } -# tile 119 (zap 6 3) +# tile 173 (zap 6 3) { MMMMMMMMMMMMMFFF MMMMMMMMMMMMFFFF @@ -2294,7 +3320,7 @@ P = (108, 145, 182) FFFFMMMMMMMMMMMM FFFMMMMMMMMMMMMM } -# tile 120 (zap 7 0) +# tile 174 (zap 7 0) { MMMMMMMGGMMMMMMM MMMMMMGGGGMMMMMM @@ -2313,7 +3339,7 @@ P = (108, 145, 182) MMMMMMGGGGMMMMMM MMMMMMMGGMMMMMMM } -# tile 121 (zap 7 1) +# tile 175 (zap 7 1) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2332,7 +3358,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM } -# tile 122 (zap 7 2) +# tile 176 (zap 7 2) { GGGMMMMMMMMMMMMM GGGGMMMMMMMMMMMM @@ -2351,7 +3377,7 @@ P = (108, 145, 182) MMMMMMMMMMMMGGGG MMMMMMMMMMMMMGGG } -# tile 123 (zap 7 3) +# tile 177 (zap 7 3) { MMMMMMMMMMMMMGGG MMMMMMMMMMMMGGGG @@ -2370,7 +3396,7 @@ P = (108, 145, 182) GGGGMMMMMMMMMMMM GGGMMMMMMMMMMMMM } -# tile 124 (warning 0) +# tile 178 (warning 0) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2389,7 +3415,7 @@ P = (108, 145, 182) MMMMMMMAAMMMMMMM MMMMMMMMMMMMMMMM } -# tile 125 (warning 1) +# tile 179 (warning 1) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2408,7 +3434,7 @@ P = (108, 145, 182) MMMMMMMAAMMMMMMM MMMMMMMMMMMMMMMM } -# tile 126 (warning 2) +# tile 180 (warning 2) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2427,7 +3453,7 @@ P = (108, 145, 182) MMMMMMMAAMMMMMMM MMMMMMMMMMMMMMMM } -# tile 127 (warning 3) +# tile 181 (warning 3) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2446,7 +3472,7 @@ P = (108, 145, 182) MMMMMMMAAMMMMMMM MMMMMMMMMMMMMMMM } -# tile 128 (warning 4) +# tile 182 (warning 4) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2465,7 +3491,7 @@ P = (108, 145, 182) MMMMMMMAAMMMMMMM MMMMMMMMMMMMMMMM } -# tile 129 (warning 5) +# tile 183 (warning 5) { MMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMM @@ -2484,216 +3510,216 @@ P = (108, 145, 182) MMMMMMMAAMMMMMMM MMMMMMMMMMMMMMMM } -# tile 130 (sub mine walls 0) -{ - ANNLAJKKKKKJNNLA - ALLLAJKJKKJJLLLA - ALLLAJKKKKKJLLLA - ALLLAJKKKKKJLLLA - ALLLAJJKKKKJLLLA - AJAAAJJKKKKJJAJA - AJJJAJJKKKKJJJJA - ALKKAJJKKJKJLKJA - ANNLAJKKKKKJNNLA - ALLLAJKKKKKJLLLA - ALLLAJKKKKKJLLLA - ALLLAJKKKKKJLLLA - ALLLAJJKJKJJLLLA - AJAAAJJKKKKJJAJA - AJJJAJJKKKKJJJJA - ALKKAJJKKKKJLKJA -} -# tile 131 (sub mine walls 1) -{ - AAANLLAAAAANLLAA - LLLNLLAJLLLNLLAJ - KLLJJJAJKLLJJJAJ +# tile 184 (sub mine walls 0) +{ + AJJKKKACJAAJJJAA + AJKKKACLJJAJJJJA + AJKKACLCKJJAJJJA + AAKACLCKJJJJAAAA + AAACLLKKJJJJJJAA + AACLLKKKAAJJJJJA + ACKKKKKACJAJJJJA + AKKKKKACLJJAJJJA + AAKKKACLKJJJAJAA + AAKKACLKKJJJJJAA + AACCCKKAAJJJJJJA + ACCKKKACJAJJJJJA + ACKKKACLJJAJJJJA + AAKKACLCKJJAJJAA + AAJACKCKKJJJAJAA + AAJCKKJAAAJJJJJA +} +# tile 185 (sub mine walls 1) +{ + AJAAAAAAJJAAAJAA + JJJAAAJJJJJAAAAJ + JJJACJAJJJACCJAJ + AAACLJJAJACCLJJA + AACLCKJJACCLCKJJ + ACKCKKJJJCKCKKJA + CJKKKKJJCKCKJJAC + KJJKCJJCKKKJJJCK + KJKKKJJKJKJJJJKK + JJJKCJKKJKJJJCKJ + JJJJJJKJKKJJJKKJ + JJJJJKJJJJJJJJJJ JJJJJJJJJJJJJJJJ - KKJJJKKKKKJJJKKK - KKNLLKKKKKNLLKKK - LLNLLAJLLLNLLAJL - LLJJJAJKLLJJJAJK JJJJJJJJJJJJJJJJ - KKJLKKKKJLKKKJLK - KKJKKKKKJKKKKJKK - JJJJJJJJJJJJJJJJ - JLKKKKJLKKKKJLKK - JKKKKKJKKKKKJKKK JJJJJJJJJJJJJJJJ AAAAAAAAAAAAAAAA } -# tile 132 (sub mine walls 2) -{ - AAANNNNLLLLLLAAA - NNNNAAJJKKKKLJJJ - LLLNAJJKKKCCLJJJ - LLLLLLLLLLLLLJJJ - LLLKKKKKKKKKKJJJ - LLLKKKKKKKKKKJJJ - LLKKKKKKKKKKKKJJ - LKKKKKKKKKKKKKKJ - JJJJJJJJJJJJJJJJ - AKKJJJJJJJJJKKKJ - ALLLAAAAAAAALLLA - ALLLAJKKKKKJLLLA - ALLLAJKKKKKJLLLA - AJAAAJJKKKKJJAJA - AJJJAJJKKKKJJJJA - ALKKAJJKKKKJLKJA -} -# tile 133 (sub mine walls 3) -{ - AAANNNNLLLLLLAAA - NNNNAAJJKKKKLJJJ - LLLNAJJKKKCCLJJJ - LLLLLLLLLLLLLJJJ - LLLKKKKKKKKKKJJJ - LLLKKKKKKKKKKJJJ - LLKKKKKKKKKKKKJJ - LKKKKKKKKKKKKKKJ - JJJJJJJJJJJJJJJJ - AKKJJJJJJJJJKKKJ - ALLLAAAAAAAALLLA - ALLLAJKKKKKJLLLA - ALLLAJKKKKKJLLLA - AJAAAJJKKKKJJAJA - AJJJAJJKKKKJJJJA - ALKKAJJKKKKJLKJA -} -# tile 134 (sub mine walls 4) -{ - AAANNNNLLLLLLAAA - NNNNAAJJKKKKLJJJ - LLLNAJJKKKCCLJJJ - LLLLLLLLLLLLLJJJ - LLLKKKKKKKKKKJJJ - LLLKKKKKKKKKKJJJ - LLKKKKKKKKKKKKJJ - LKKKKKKKKKKKKKKJ - JJJJJJJJJJJJJJJJ - KKJLKKKKJLKKKJLK - KKJKKKKKJKKKKJKK - JJJJJJJJJJJJJJJJ - JLKKKKJLKKKKJLKK - JKKKKKJKKKKKJKKK - JJJJJJJJJJJJJJJJ +# tile 186 (sub mine walls 2) +{ + AAAAAAKCCKKJAAAA + AAAAKKCLCJKJJAAA + AAKKKCLCKJJJKKAA + AKKKCLCKJJJJJJKA + AKKCLLKKJJJJJJJA + AKCLLKKKAAJJJJJJ + ACKKKKKACJAJJJJJ + AKKKKKACLJJAAJJJ + AAKKKCLLKJJJAJAJ + AAKKCCCKKJJJAJAA + AACCKKKAAJJJJJJA + ACCKKKACJAJJJJJA + ACKKKACLJJAJJJJA + AAKKACLCKJJAJJAA + AAJACKCKKJJJAJAA + AAJCKKJAAAJJJJJA +} +# tile 187 (sub mine walls 3) +{ + AAAAAAKCCKKJAAAA + AAAAKKCLCJKJJAAA + AAKKKCLCKJJJKKAA + AKKCCLCKJJJJJJKA + KKCCLLKKJJJJJJJA + KKCLKKKKAAJJJJJA + KCLKKKKACJAJJJJA + CKKKKKACLJJAAJJA + KAKKKCLLKJJJAJAA + AKKKCCCKKJJJAJAA + AACCKKKAAJJJJJJA + ACCKKKACJAJJJJJA + ACKKKACLJJAJJJJA + AKKKACLCKJJAJJAA + AAJACKCKKJJJAJAA + AAJCKKJAAAJJJJJA +} +# tile 188 (sub mine walls 4) +{ + AKKKAAKKKKAAJJJA + AKKAAKCCCJJJAAJA + AKKAALLJJJACCJAA + AKAACLJJJACCLJJA + AAACCKJJACLLCKJJ + AAACLKJJJCKCKKJA + AACLKKJJCKCKJJAC + AAKKCJJCKKKJJJCK + ACKKKJJKJKJJJJKK + ACKKCJKKJKJJJCKJ + AKKKJJKJKKJJJKKJ + ACKJJKJJJJJJJJJJ + AKJJJJJJJJJJJJJJ + AKJJJJJJJJJJJJJJ + AJJJJJJJJJJJJJJJ AAAAAAAAAAAAAAAA } -# tile 135 (sub mine walls 5) -{ - AAANNNNLLLLLLAAA - NNNNAAJJKKKKLJJJ - LLLNAJJKKKCCLJJJ - LLLLLLLLLLLLLJJJ - LLLKKKKKKKKKKJJJ - LLLKKKKKKKKKKJJJ - LLKKKKKKKKKKKKJJ - LKKKKKKKKKKKKKKJ - JJJJJJJJJJJJJJJJ - KKJLKKKKJLKKKJLK - KKJKKKKKJKKKKJKK - JJJJJJJJJJJJJJJJ - JLKKKKJLKKKKJLKK - JKKKKKJKKKKKJKKK - JJJJJJJJJJJJJJJJ +# tile 189 (sub mine walls 5) +{ + AKKAAAKKAAAAJJJA + AKAAKKLCKAAAAAJA + AAKKCLCJJACCAJJA + AKKCLJJJACCCLAJA + AKCKKKJACCCLCAAA + ACKKKKJACCKCKKAA + CJKKKKACCKCKJJAA + KJJKCJJCKKKJJJAA + KJKKKJJKJKJJJJJA + JJJKCJKKJKJJJJJA + JJJJJJKJKKJJJJJA + JJJJJKJJJJJJJJJA + JJJJJJJJJJJJJJJA + JJJJJJJJJJJJJJJA + JJJJJJJJJJJJJJJA AAAAAAAAAAAAAAAA } -# tile 136 (sub mine walls 6) -{ - AAANNNNLLLLLLAAA - NNNNAAJJKKKKLJJJ - LLLNAJJKKKCCLJJJ - LLLLLLLLLLLLLJJJ - LLLKKKKKKKKKKJJJ - LLLKKKKKKKKKKJJJ - LLKKKKKKKKKKKKJJ - LKKKKKKKKKKKKKKJ +# tile 190 (sub mine walls 6) +{ + AAAAAAKCCKKJAAAA + AAAAKCCLCJKJJAAA + AAKKCCLCKJJJKKAA + AKKKCLCKJJJJJJKA + KKKCLKKKJJJJJJJA + KKCLKKKKAAJJJJJJ + KCKLKKKACJAJJJJJ + CKKKKKACLJJAAJJJ + KAKKKCLLKJJJAJAJ + AKKKCCCKKJJJAJAA + AACCKKKAAJJJJJJA + ACCKKKACJAJJJJJA + ACKKKACLJJAJJJJA + AKKKACLCKJJAJJAA + AAJACKCKKJJJAJAA + AAJCKKJAAAJJJJJA +} +# tile 191 (sub mine walls 7) +{ + AKKAAAKKKKAAJJJA + AKAAKKLCCJJJAAJA + AAKKCLCJJJACCJAA + AKKCLJJJJACCLJJA + AKCLCKJJACCLCKJJ + ACKCKKJJJCKCKKJA + CJKKKKJJCKCKJJAC + KJJKCJJCKKKJJJCK + KJKKKJJKJKJJJJKK + JJJKCJKKJKJJJCKJ + JJJJJJKJKKJJJKKJ + JJJJJKJJJJJJJJJJ JJJJJJJJJJJJJJJJ - AKKJJJJJJJJJKKKJ - ALLLAAAAAAAALLLA - ALLLAJKKKKKJLLLA - ALLLAJKKKKKJLLLA - AJAAAJJKKKKJJAJA - AJJJAJJKKKKJJJJA - ALKKAJJKKKKJLKJA -} -# tile 137 (sub mine walls 7) -{ - AAANNNNLLLLLLAAA - NNNNAAJJKKKKLJJJ - LLLNAJJKKKCCLJJJ - LLLLLLLLLLLLLJJJ - LLLKKKKKKKKKKJJJ - LLLKKKKKKKKKKJJJ - LLKKKKKKKKKKKKJJ - LKKKKKKKKKKKKKKJ JJJJJJJJJJJJJJJJ - KKJLKKKKJLKKKJLK - KKJKKKKKJKKKKJKK - JJJJJJJJJJJJJJJJ - JLKKKKJLKKKKJLKK - JKKKKKJKKKKKJKKK JJJJJJJJJJJJJJJJ AAAAAAAAAAAAAAAA } -# tile 138 (sub mine walls 8) -{ - AAANNNNLLLLLLAAA - NNNNAAJJKKKKLJJJ - LLLNAJJKKKCCLJJJ - LLLLLLLLLLLLLJJJ - LLLKKKKKKKKKKJJJ - LLLKKKKKKKKKKJJJ - LLKKKKKKKKKKKKJJ - LKKKKKKKKKKKKKKJ - JJJJJJJJJJJJJJJJ - AKKJJJJJJJJJKKKJ - ALLLAAAAAAAALLLA - ALLLAJKKKKKJLLLA - ALLLAJKKKKKJLLLA - AJAAAJJKKKKJJAJA - AJJJAJJKKKKJJJJA - ALKKAJJKKKKJLKJA -} -# tile 139 (sub mine walls 9) -{ - AAANNNNLLLLLLAAA - NNNNAAJJKKKKLJJJ - LLLNAJJKKKCCLJJJ - LLLLLLLLLLLLLJJJ - LLLKKKKKKKKKKJJJ - LLLKKKKKKKKKKJJJ - LLKKKKKKKKKKKKJJ - LKKKKKKKKKKKKKKJ - JJJJJJJJJJJJJJJJ - AKKJJJJJJJJJKKKJ - ALLLAAAAAAAALLLA - ALLLAJKKKKKJLLLA - ALLLAJKKKKKJLLLA - AJAAAJJKKKKJJAJA - AJJJAJJKKKKJJJJA - ALKKAJJKKKKJLKJA -} -# tile 140 (sub mine walls 10) -{ - AAANNNNLLLLLLAAA - NNNNAAJJKKKKLJJJ - LLLNAJJKKKCCLJJJ - LLLLLLLLLLLLLJJJ - LLLKKKKKKKKKKJJJ - LLLKKKKKKKKKKJJJ - LLKKKKKKKKKKKKJJ - LKKKKKKKKKKKKKKJ - JJJJJJJJJJJJJJJJ - AKKJJJJJJJJJKKKJ - ALLLAAAAAAAALLLA - ALLLAJKKKKKJLLLA - ALLLAJKKKKKJLLLA - AJAAAJJKKKKJJAJA - AJJJAJJKKKKJJJJA - ALKKAJJKKKKJLKJA -} -# tile 141 (sub gehennom walls 0) +# tile 192 (sub mine walls 8) +{ + AAAAAAKCCKKJAAAA + AAAAKCCLCJKJJAAA + AAKKKCLCKJJJKKAA + AKKKCLCKJJJJJJKA + KKCCLLKKJJJJJJJA + KKCLLKKKAAJJJJJJ + KCLLKKKACJAJJJJJ + CKLKKKACLJJAAJJJ + KAKKKCLLKJJJAJAJ + AKKKCCCKKJJJAJAA + AACCKKKAAJJJJJJA + ACCKKKACJAJJJJJA + ACKKKACLJJAJJJJA + AKKKACLCKJJAJJAA + AAJACKCKKJJJAJAA + AAJCKKJAAAJJJJJA +} +# tile 193 (sub mine walls 9) +{ + AKKAACKCCKKJAJJA + AKACKKKLLJKJJAJA + AAKKKCCCKJJJKKAA + AKKKCCLKJJJJJJKA + AKKCLLKKJJJJJJJA + AKCLLKKKAAJJJJJJ + ACLKKKKACJAJJJJJ + AKKKKKACLJJAAJJJ + AAKKKCLLKJJJAJAJ + AAKKCCCKKJJJAJAA + AACCKKKAAJJJJJJA + ACCKKKACJAJJJJJA + ACKKKACLJJAJJJJA + AAKKACLCKJJAJJAA + AAJACKCKKJJJAJAA + AAJCKKJAAAJJJJJA +} +# tile 194 (sub mine walls 10) +{ + AKKAACKCCKKJAJJA + AKACKKCLCJKJJAJA + AAKKCCLCKJJJKKAA + AKKCLLCKJJJJJJKA + KKCCLLKKJJJJJJJA + KCKLLKKKAAJJJJJA + CCKKKKKACJAJJJJA + CKKKKKACLJJAAJJA + KAKKKCLLKJJJAJAA + AKKKCCCKKJJJAJAA + AACCKKKAAJJJJJJA + ACCKKKACJAJJJJJA + ACKKKACLJJAJJJJA + AKKKACLCKJJAJJAA + AAJACKCKKJJJAJAA + AAJCKKJAAAJJJJJA +} +# tile 195 (sub gehennom walls 0) { ALLDAJMMMMMJLLDA ADDDAJMJMMJJDDDA @@ -2712,7 +3738,7 @@ P = (108, 145, 182) AJJJAJJMMMMJJJJA ADMMAJJMMMMJDMJA } -# tile 142 (sub gehennom walls 1) +# tile 196 (sub gehennom walls 1) { AAALDDAAAAALDDAA DDDLDDAJDDDLDDAJ @@ -2731,7 +3757,7 @@ P = (108, 145, 182) JJJJJJJJJJJJJJJJ AAAAAAAAAAAAAAAA } -# tile 143 (sub gehennom walls 2) +# tile 197 (sub gehennom walls 2) { AAALLLLDDDDDDAAA LLLLAAJJMMMMDJJJ @@ -2750,7 +3776,7 @@ P = (108, 145, 182) AJJJAJJMMMMJJJJA ADMMAJJMMMMJDMJA } -# tile 144 (sub gehennom walls 3) +# tile 198 (sub gehennom walls 3) { AAALLLLDDDDDDAAA LLLLAAJJMMMMDJJJ @@ -2769,7 +3795,7 @@ P = (108, 145, 182) AJJJAJJMMMMJJJJA ADMMAJJMMMMJDMJA } -# tile 145 (sub gehennom walls 4) +# tile 199 (sub gehennom walls 4) { AAALLLLDDDDDDAAA LLLLAAJJMMMMDJJJ @@ -2788,7 +3814,7 @@ P = (108, 145, 182) JJJJJJJJJJJJJJJJ AAAAAAAAAAAAAAAA } -# tile 146 (sub gehennom walls 5) +# tile 200 (sub gehennom walls 5) { AAALLLLDDDDDDAAA LLLLAAJJMMMMDJJJ @@ -2807,7 +3833,7 @@ P = (108, 145, 182) JJJJJJJJJJJJJJJJ AAAAAAAAAAAAAAAA } -# tile 147 (sub gehennom walls 6) +# tile 201 (sub gehennom walls 6) { AAALLLLDDDDDDAAA LLLLAAJJMMMMDJJJ @@ -2826,7 +3852,7 @@ P = (108, 145, 182) AJJJAJJMMMMJJJJA ADMMAJJMMMMJDMJA } -# tile 148 (sub gehennom walls 7) +# tile 202 (sub gehennom walls 7) { AAALLLLDDDDDDAAA LLLLAAJJMMMMDJJJ @@ -2845,7 +3871,7 @@ P = (108, 145, 182) JJJJJJJJJJJJJJJJ AAAAAAAAAAAAAAAA } -# tile 149 (sub gehennom walls 8) +# tile 203 (sub gehennom walls 8) { AAALLLLDDDDDDAAA LLLLAAJJMMMMDJJJ @@ -2864,7 +3890,7 @@ P = (108, 145, 182) AJJJAJJMMMMJJJJA ADMMAJJMMMMJDMJA } -# tile 150 (sub gehennom walls 9) +# tile 204 (sub gehennom walls 9) { AAALLLLDDDDDDAAA LLLLAAJJMMMMDJJJ @@ -2883,7 +3909,7 @@ P = (108, 145, 182) AJJJAJJMMMMJJJJA ADMMAJJMMMMJDMJA } -# tile 151 (sub gehennom walls 10) +# tile 205 (sub gehennom walls 10) { AAALLLLDDDDDDAAA LLLLAAJJMMMMDJJJ @@ -2902,7 +3928,7 @@ P = (108, 145, 182) AJJJAJJMMMMJJJJA ADMMAJJMMMMJDMJA } -# tile 152 (sub knox walls 0) +# tile 206 (sub knox walls 0) { AJJJAAACJAAAJJJA AJJJAACLJJAAJJJA @@ -2921,7 +3947,7 @@ P = (108, 145, 182) AAJAAACKKJAAAJAA ACJJAAAAAAAACJJA } -# tile 153 (sub knox walls 1) +# tile 207 (sub knox walls 1) { AJAAAJAAAJAAAJAA JJJAAAJAJJJAAAJA @@ -2940,7 +3966,7 @@ P = (108, 145, 182) KJJACJJAKJJACJJA AAAAAAAAAAAAAAAA } -# tile 154 (sub knox walls 2) +# tile 208 (sub knox walls 2) { AAAAAAKCJKAAAAAA AAAAKKCLKJKKAAAA @@ -2959,7 +3985,7 @@ P = (108, 145, 182) AAJAAACKKJAAAJAA ACJJAAAAAAAACJJA } -# tile 155 (sub knox walls 3) +# tile 209 (sub knox walls 3) { AAAAAAKCJKAAAAAA AAAAKKCLKJKKAAAA @@ -2978,7 +4004,7 @@ P = (108, 145, 182) AAJAAACKKJAAAJAA ACJJAAAAAAAACJJA } -# tile 156 (sub knox walls 4) +# tile 210 (sub knox walls 4) { AAAAAAKCJKAAAAAA AAAAKKCLKJKKAAAA @@ -2997,7 +4023,7 @@ P = (108, 145, 182) KJJACJJAKJJACJJA AAAAAAAAAAAAAAAA } -# tile 157 (sub knox walls 5) +# tile 211 (sub knox walls 5) { AAAAAAKCJKAAAAAA AAAAKKCLKJKKAAAA @@ -3016,7 +4042,7 @@ P = (108, 145, 182) KJJACJJAKJJACJJA AAAAAAAAAAAAAAAA } -# tile 158 (sub knox walls 6) +# tile 212 (sub knox walls 6) { AAAAAAKCJKAAAAAA AAAAKKCLKJKKAAAA @@ -3035,7 +4061,7 @@ P = (108, 145, 182) AAJAAACKKJAAAJAA ACJJAAAAAAAACJJA } -# tile 159 (sub knox walls 7) +# tile 213 (sub knox walls 7) { AAAAAAKCJKAAAAAA AAAAKKCLKJKKAAAA @@ -3054,7 +4080,7 @@ P = (108, 145, 182) KJJACJJAKJJACJJA AAAAAAAAAAAAAAAA } -# tile 160 (sub knox walls 8) +# tile 214 (sub knox walls 8) { AAAAAAKCJKAAAAAA AAAAKKCLKJKKAAAA @@ -3073,7 +4099,7 @@ P = (108, 145, 182) AAJAAACKKJAAAJAA ACJJAAAAAAAACJJA } -# tile 161 (sub knox walls 9) +# tile 215 (sub knox walls 9) { AAAAAAKCJKAAAAAA AAAAKKCLKJKKAAAA @@ -3092,7 +4118,7 @@ P = (108, 145, 182) AAJAAACKKJAAAJAA ACJJAAAAAAAACJJA } -# tile 162 (sub knox walls 10) +# tile 216 (sub knox walls 10) { AAAAAAKCJKAAAAAA AAAAKKCLKJKKAAAA @@ -3111,7 +4137,7 @@ P = (108, 145, 182) AAJAAACKKJAAAJAA ACJJAAAAAAAACJJA } -# tile 163 (sub sokoban walls 0) +# tile 217 (sub sokoban walls 0) { ANNBAMEEEEEMNNBA ABBBAMEMEEMMBBBA @@ -3130,7 +4156,7 @@ P = (108, 145, 182) AMMMAMMEEEEMMMMA ABEEAMMEEEEMBEMA } -# tile 164 (sub sokoban walls 1) +# tile 218 (sub sokoban walls 1) { AAANBBAAAAANBBAA BBBNBBAMBBBNBBAM @@ -3149,7 +4175,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM AAAAAAAAAAAAAAAA } -# tile 165 (sub sokoban walls 2) +# tile 219 (sub sokoban walls 2) { AAANNNNBBBBBBAAA NNNNAAMMEEEEBMMM @@ -3168,7 +4194,7 @@ P = (108, 145, 182) AMMMAMMEEEEMMMMA ABEEAMMEEEEMBEMA } -# tile 166 (sub sokoban walls 3) +# tile 220 (sub sokoban walls 3) { AAANNNNBBBBBBAAA NNNNAAMMEEEEBMMM @@ -3187,7 +4213,7 @@ P = (108, 145, 182) AMMMAMMEEEEMMMMA ABEEAMMEEEEMBEMA } -# tile 167 (sub sokoban walls 4) +# tile 221 (sub sokoban walls 4) { AAANNNNBBBBBBAAA NNNNAAMMEEEEBMMM @@ -3206,7 +4232,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM AAAAAAAAAAAAAAAA } -# tile 168 (sub sokoban walls 5) +# tile 222 (sub sokoban walls 5) { AAANNNNBBBBBBAAA NNNNAAMMEEEEBMMM @@ -3225,7 +4251,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM AAAAAAAAAAAAAAAA } -# tile 169 (sub sokoban walls 6) +# tile 223 (sub sokoban walls 6) { AAANNNNBBBBBBAAA NNNNAAMMEEEEBMMM @@ -3244,7 +4270,7 @@ P = (108, 145, 182) AMMMAMMEEEEMMMMA ABEEAMMEEEEMBEMA } -# tile 170 (sub sokoban walls 7) +# tile 224 (sub sokoban walls 7) { AAANNNNBBBBBBAAA NNNNAAMMEEEEBMMM @@ -3263,7 +4289,7 @@ P = (108, 145, 182) MMMMMMMMMMMMMMMM AAAAAAAAAAAAAAAA } -# tile 171 (sub sokoban walls 8) +# tile 225 (sub sokoban walls 8) { AAANNNNBBBBBBAAA NNNNAAMMEEEEBMMM @@ -3282,7 +4308,7 @@ P = (108, 145, 182) AMMMAMMEEEEMMMMA ABEEAMMEEEEMBEMA } -# tile 172 (sub sokoban walls 9) +# tile 226 (sub sokoban walls 9) { AAANNNNBBBBBBAAA NNNNAAMMEEEEBMMM @@ -3301,7 +4327,7 @@ P = (108, 145, 182) AMMMAMMEEEEMMMMA ABEEAMMEEEEMBEMA } -# tile 173 (sub sokoban walls 10) +# tile 227 (sub sokoban walls 10) { AAANNNNBBBBBBAAA NNNNAAMMEEEEBMMM diff --git a/win/share/thintile.c b/win/share/thintile.c index 9276af4..9e4dc33 100644 --- a/win/share/thintile.c +++ b/win/share/thintile.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)thintile.c 3.3 95/11/26 */ +/* SCCS Id: @(#)thintile.c 3.4 1995/11/26 */ /* Copyright (c) NetHack Development Team 1995 */ /* NetHack may be freely redistributed. See license for details. */ @@ -29,7 +29,7 @@ static char comment[BUFSZ]; static void copy_colormap() { - int i, r, g, b; + int r, g, b; char c[2]; while (fscanf(infile, "%[A-Za-z0-9] = (%d, %d, %d) ", c, &r, &g, &b) @@ -41,13 +41,14 @@ copy_colormap() static boolean read_txttile() { - int i, j, k; + int i, j; char buf[BUFSZ]; - const char *p; + char buf2[BUFSZ]; + char c[2]; - if (fscanf(infile, "# tile %d (%[^)])", &i, buf) <= 0) + if (fscanf(infile, "# %s %d (%[^)])", buf2, &i, buf) <= 0) return FALSE; Sprintf(comment,"# tile %d (%s)", i, buf); @@ -84,8 +85,7 @@ read_txttile() static void write_thintile() { - const char *p; - int i, j, k; + int i, j; Fprintf(outfile, "%s\n", comment); @@ -104,8 +104,6 @@ main(argc, argv) int argc; char *argv[]; { - boolean x; - while (filenum < 3) { tilecount_per_file = 0; infile = fopen(tilefiles[filenum], RDTMODE); diff --git a/win/share/tile.h b/win/share/tile.h index eadc997..4bfbe7f 100644 --- a/win/share/tile.h +++ b/win/share/tile.h @@ -23,7 +23,9 @@ extern int colorsinmainmap; #ifndef TILE_X #define TILE_X 16 #endif +#ifndef TILE_Y #define TILE_Y 16 +#endif #define Fprintf (void) fprintf diff --git a/win/share/tile2bmp.c b/win/share/tile2bmp.c index 2214516..c10142e 100644 --- a/win/share/tile2bmp.c +++ b/win/share/tile2bmp.c @@ -1,11 +1,11 @@ -/* SCCS Id: @(#)tile2bmp.c 3.3 1999/08/29 */ +/* SCCS Id: @(#)tile2bmp.c 3.4 2002/03/14 */ /* Copyright (c) NetHack PC Development Team 1995 */ /* NetHack may be freely redistributed. See license for details. */ /* * Edit History: * - * Initial Creation M.Allison 94/01/11 + * Initial Creation M.Allison 1994/01/11 * */ @@ -13,12 +13,16 @@ #include "hack.h" #include "tile.h" -#ifndef __DJGPP__ +#ifndef __GNUC__ #include "win32api.h" #endif /* #define COLORS_IN_USE MAXCOLORMAPSIZE /* 256 colors */ +#if (TILE_X==32) +#define COLORS_IN_USE 256 +#else #define COLORS_IN_USE 16 /* 16 colors */ +#endif #define BITCOUNT 8 @@ -26,10 +30,16 @@ extern char *FDECL(tilename, (int, int)); #if BITCOUNT==4 #define MAX_X 320 /* 2 per byte, 4 bits per pixel */ +#define MAX_Y 480 #else +# if (TILE_X==32) +#define MAX_X (32 * 40) +#define MAX_Y 960 +# else #define MAX_X 640 /* 1 per byte, 8 bits per pixel */ -#endif #define MAX_Y 480 +# endif +#endif /* GCC fix by Paolo Bonzini 1999/03/28 */ #ifdef __GNUC__ @@ -38,7 +48,7 @@ extern char *FDECL(tilename, (int, int)); #define PACK #endif -#if defined(__DJGPP__) +#ifdef __GNUC__ typedef struct tagBMIH { unsigned long biSize; long biWidth; @@ -75,7 +85,7 @@ typedef struct tagRGBQ { #define BI_RLE8 1L #define BI_RLE4 2L #define BI_BITFIELDS 3L -#endif /* defined(__DJGPP__) */ +#endif /* __GNUC__ */ #pragma pack(1) struct tagBMP{ @@ -85,13 +95,18 @@ struct tagBMP{ #define RGBQUAD_COUNT 16 RGBQUAD bmaColors[RGBQUAD_COUNT]; #else +#if (TILE_X==32) +#define RGBQUAD_COUNT 256 +#else #define RGBQUAD_COUNT 16 +#endif RGBQUAD bmaColors[RGBQUAD_COUNT]; #endif -#if COLORS_IN_USE==16 +#if (COLORS_IN_USE==16) uchar packtile[MAX_Y][MAX_X]; #else - uchar packtile[TILE_Y][TILE_X]; + uchar packtile[MAX_Y][MAX_X]; +/* uchar packtile[TILE_Y][TILE_X]; */ #endif } PACK bmp; #pragma pack() @@ -106,9 +121,17 @@ static void FDECL(build_bmfh,(BITMAPFILEHEADER *)); static void FDECL(build_bmih,(BITMAPINFOHEADER *)); static void FDECL(build_bmptile,(pixel (*)[TILE_X])); -char *tilefiles[] = { "../win/share/monsters.txt", - "../win/share/objects.txt", - "../win/share/other.txt"}; +char *tilefiles[] = { +#if (TILE_X == 32) + "../win/share/mon32.txt", + "../win/share/obj32.txt", + "../win/share/oth32.txt" +#else + "../win/share/monsters.txt", + "../win/share/objects.txt", + "../win/share/other.txt" +#endif +}; int num_colors = 0; int tilecount; @@ -125,10 +148,10 @@ main(argc, argv) int argc; char *argv[]; { - int i; + int i, j; if (argc != 2) { - Fprintf(stderr, "usage: tile2bmp outfile.bmp\n"); + Fprintf(stderr, "usage: %s outfile.bmp\n", argv[0]); exit(EXIT_FAILURE); } else strcpy(bmpname, argv[1]); @@ -151,7 +174,7 @@ char *argv[]; printf("Error creating tile file %s, aborting.\n",bmpname); exit(1); } - while (filenum < 3) { + while (filenum < (sizeof(tilefiles) / sizeof(char *))) { if (!fopen_text_file(tilefiles[filenum], RDTMODE)) { Fprintf(stderr, "usage: tile2bmp (from the util directory)\n"); @@ -165,8 +188,9 @@ char *argv[]; if (!initflag) { build_bmfh(&bmp.bmfh); build_bmih(&bmp.bmih); - memset(&bmp.packtile,0, - (MAX_X * MAX_Y * sizeof(uchar))); + for (i = 0; i < MAX_Y; ++i) + for (j = 0; j < MAX_X; ++j) + bmp.packtile[i][j] = (uchar)0; for (i = 0; i < num_colors; i++) { bmp.bmaColors[i].rgbRed = ColorMap[CM_RED][i]; bmp.bmaColors[i].rgbGreen = ColorMap[CM_GREEN][i]; @@ -219,6 +243,7 @@ static void build_bmih(pbmih) BITMAPINFOHEADER *pbmih; { + WORD cClrBits; pbmih->biSize = (DWORD) sizeof(bmp.bmih); #if BITCOUNT==4 pbmih->biWidth = (LONG) MAX_X * 2; @@ -232,12 +257,35 @@ BITMAPINFOHEADER *pbmih; #else pbmih->biBitCount = (WORD) 8; #endif + cClrBits = (WORD)(pbmih->biPlanes * pbmih->biBitCount); + if (cClrBits == 1) + cClrBits = 1; + else if (cClrBits <= 4) + cClrBits = 4; + else if (cClrBits <= 8) + cClrBits = 8; + else if (cClrBits <= 16) + cClrBits = 16; + else if (cClrBits <= 24) + cClrBits = 24; + else cClrBits = 32; pbmih->biCompression = (DWORD) BI_RGB; - pbmih->biSizeImage = (DWORD)0; pbmih->biXPelsPerMeter = (LONG)0; pbmih->biYPelsPerMeter = (LONG)0; - pbmih->biClrUsed = (DWORD)RGBQUAD_COUNT; - pbmih->biClrImportant = (DWORD)0; +#if (TILE_X==32) + if (cClrBits < 24) + pbmih->biClrUsed = (1<biClrUsed = (DWORD)RGBQUAD_COUNT; +#endif + +#if (TILE_X==16) + pbmih->biSizeImage = 0; +#else + pbmih->biSizeImage = ((pbmih->biWidth * cClrBits +31) & ~31) /8 + * pbmih->biHeight; +#endif + pbmih->biClrImportant = (DWORD)0; } static void diff --git a/win/share/tilemap.c b/win/share/tilemap.c index dc8f6d6..a8bbfcc 100644 --- a/win/share/tilemap.c +++ b/win/share/tilemap.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)tilemap.c 3.3 2000/06/04 */ +/* SCCS Id: @(#)tilemap.c 3.4 2000/06/04 */ /* NetHack may be freely redistributed. See license for details. */ /* @@ -180,7 +180,7 @@ int set, entry; } tilenum = 0; /* set-relative number */ - for (i = 0; i < MAXPCHARS; i++) { + for (i = 0; i < (MAXPCHARS - MAXEXPCHARS); i++) { if (set == OTH_GLYPH && tilenum == entry) { if (*defsyms[i].explanation) return defsyms[i].explanation; @@ -211,7 +211,22 @@ int set, entry; tilenum++; } } - + /* explosions */ + tilenum = MAXPCHARS - MAXEXPCHARS; + i = entry - tilenum; + if (i < (MAXEXPCHARS * EXPL_MAX)) { + if (set == OTH_GLYPH) { + static char *explosion_types[] = { /* hack.h */ + "dark", "noxious", "muddy", "wet", + "magical", "fiery", "frosty" + }; + Sprintf(buf, "explosion %s %d", + explosion_types[i / MAXEXPCHARS], i % MAXEXPCHARS); + return buf; + } + } + tilenum += (MAXEXPCHARS * EXPL_MAX); + i = entry - tilenum; if (i < (NUM_ZAP << 2)) { if (set == OTH_GLYPH) { @@ -345,7 +360,7 @@ init_tilemap() } lastobjtile = tilenum - 1; - for (i = 0; i < MAXPCHARS; i++) { + for (i = 0; i < (MAXPCHARS - MAXEXPCHARS); i++) { tilemap[GLYPH_CMAP_OFF+i] = tilenum; tilenum++; while (conditionals[condnum].sequence == OTH_GLYPH && @@ -355,11 +370,21 @@ init_tilemap() } } + for (i = 0; i < (MAXEXPCHARS * EXPL_MAX); i++) { + tilemap[GLYPH_EXPLODE_OFF+i] = tilenum; + tilenum++; + while (conditionals[condnum].sequence == OTH_GLYPH && + conditionals[condnum].predecessor == (i + MAXPCHARS)) { + condnum++; + tilenum++; + } + } + for (i = 0; i < NUM_ZAP << 2; i++) { tilemap[GLYPH_ZAP_OFF+i] = tilenum; tilenum++; while (conditionals[condnum].sequence == OTH_GLYPH && - conditionals[condnum].predecessor == (i + MAXPCHARS)) { + conditionals[condnum].predecessor == (i + MAXEXPCHARS)) { condnum++; tilenum++; } diff --git a/win/share/tiletext.c b/win/share/tiletext.c index 2a22df4..8ac8abe 100644 --- a/win/share/tiletext.c +++ b/win/share/tiletext.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)tiletext.c 3.3 1999/10/24 */ +/* SCCS Id: @(#)tiletext.c 3.4 1999/10/24 */ /* NetHack may be freely redistributed. See license for details. */ #include "config.h" diff --git a/win/tty/getline.c b/win/tty/getline.c index 1d9a725..4be8b6b 100644 --- a/win/tty/getline.c +++ b/win/tty/getline.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)getline.c 3.3 96/01/27 */ +/* SCCS Id: @(#)getline.c 3.4 1996/01/27 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -72,12 +72,25 @@ getlin_hook_proc hook; *bufp = 0; } if(c == '\020') { /* ctrl-P */ - if(!doprev) - (void) tty_doprev_message(); /* need two initially */ - (void) tty_doprev_message(); - doprev = 1; - continue; - } else if(doprev) { + if (iflags.prevmsg_window) { + int sav = ttyDisplay->inread; + ttyDisplay->inread = 0; + (void) tty_doprev_message(); + ttyDisplay->inread = sav; + tty_clear_nhwindow(WIN_MESSAGE); + cw->maxcol = cw->maxrow; + addtopl(query); + addtopl(" "); + *bufp = 0; + addtopl(obufp); + } else { + if (!doprev) + (void) tty_doprev_message();/* need two initially */ + (void) tty_doprev_message(); + doprev = 1; + continue; + } + } else if (doprev && !iflags.prevmsg_window) { tty_clear_nhwindow(WIN_MESSAGE); cw->maxcol = cw->maxrow; doprev = 0; diff --git a/win/tty/termcap.c b/win/tty/termcap.c index 591e2ec..cb89f94 100644 --- a/win/tty/termcap.c +++ b/win/tty/termcap.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)termcap.c 3.3 2000/07/10 */ +/* SCCS Id: @(#)termcap.c 3.4 2000/07/10 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1151,6 +1151,20 @@ int has_color(color) int color; { +#ifdef X11_GRAPHICS + /* XXX has_color() should be added to windowprocs */ + if (windowprocs.name != NULL && + !strcmpi(windowprocs.name, "X11")) return TRUE; +#endif +#ifdef GEM_GRAPHICS + /* XXX has_color() should be added to windowprocs */ + if (windowprocs.name != NULL && + !strcmpi(windowprocs.name, "Gem")) return TRUE; +#endif +#ifdef AMII_GRAPHICS + /* hilites[] not used */ + return iflags.use_color; +#endif return hilites[color] != (char *)0; } diff --git a/win/tty/topl.c b/win/tty/topl.c index 98d4248..ec38d6a 100644 --- a/win/tty/topl.c +++ b/win/tty/topl.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)topl.c 3.3 96/10/24 */ +/* SCCS Id: @(#)topl.c 3.4 1996/10/24 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -26,19 +26,37 @@ tty_doprev_message() { register struct WinDesc *cw = wins[WIN_MESSAGE]; - ttyDisplay->dismiss_more = C('p'); /* allowed at --More-- */ - do { - morc = 0; - if (cw->maxcol == cw->maxrow) - redotoplin(toplines); - else if (cw->data[cw->maxcol]) - redotoplin(cw->data[cw->maxcol]); - cw->maxcol--; - if (cw->maxcol < 0) cw->maxcol = cw->rows-1; - if (!cw->data[cw->maxcol]) - cw->maxcol = cw->maxrow; - } while (morc == C('p')); - ttyDisplay->dismiss_more = 0; + winid prevmsg_win; + int i; + + if (iflags.prevmsg_window && !ttyDisplay->inread) { + prevmsg_win = create_nhwindow(NHW_MENU); + putstr(prevmsg_win, 0, "Message History"); + putstr(prevmsg_win, 0, ""); + i = cw->maxcol; + do { + if(cw->data[i] && strcmp(cw->data[i], "") ) + putstr(prevmsg_win, 0, cw->data[i]); + i = (i + 1) % cw->rows; + } while (i != cw->maxcol); + putstr(prevmsg_win, 0, toplines); + display_nhwindow(prevmsg_win, TRUE); + destroy_nhwindow(prevmsg_win); + } else { + ttyDisplay->dismiss_more = C('p'); /* allowed at --More-- */ + do { + morc = 0; + if (cw->maxcol == cw->maxrow) + redotoplin(toplines); + else if (cw->data[cw->maxcol]) + redotoplin(cw->data[cw->maxcol]); + cw->maxcol--; + if (cw->maxcol < 0) cw->maxcol = cw->rows-1; + if (!cw->data[cw->maxcol]) + cw->maxcol = cw->maxrow; + } while (morc == C('p')); + ttyDisplay->dismiss_more = 0; + } return 0; } @@ -147,7 +165,9 @@ update_topl(bp) /* If there is room on the line, print message on same line */ /* But messages like "You die..." deserve their own line */ n0 = strlen(bp); - if(ttyDisplay->toplin == 1 && cw->cury == 0 && + if( (ttyDisplay->toplin == 1 || + (cw->flags & WIN_STOP && iflags.prevmsg_window)) && + cw->cury == 0 && n0 + (int)strlen(toplines) + 3 < CO-8 && /* room for --More-- */ (notdied = strncmp(bp, "You die", 7))) { Strcat(toplines, " "); @@ -156,7 +176,7 @@ update_topl(bp) if(!(cw->flags & WIN_STOP)) addtopl(bp); return; - } else if(!(cw->flags & WIN_STOP)) { + } else if (!(cw->flags & WIN_STOP && !iflags.prevmsg_window)) { if(ttyDisplay->toplin == 1) more(); else if(cw->cury) { /* for when flags.toplin == 2 && cury > 1 */ docorner(1, cw->cury+1); /* reset cury = 0 if redraw screen */ @@ -279,9 +299,20 @@ char def; do { /* loop until we get valid input */ q = lowc(readchar()); if (q == '\020') { /* ctrl-P */ - if(!doprev) (void) tty_doprev_message(); /* need two initially */ - (void) tty_doprev_message(); - doprev = 1; + if (iflags.prevmsg_window) { + int sav = ttyDisplay->inread; + ttyDisplay->inread = 0; + (void) tty_doprev_message(); + ttyDisplay->inread = sav; + tty_clear_nhwindow(WIN_MESSAGE); + cw->maxcol = cw->maxrow; + addtopl(prompt); + } else { + if(!doprev) + (void) tty_doprev_message(); /* need two initially */ + (void) tty_doprev_message(); + doprev = 1; + } q = '\0'; /* force another loop iteration */ continue; } else if (doprev) { diff --git a/win/tty/wintty.c b/win/tty/wintty.c index 142ecb1..4d2d4df 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)wintty.c 3.3 2000/06/27 */ +/* SCCS Id: @(#)wintty.c 3.4 2002/02/05 */ /* Copyright (c) David Cohrs, 1991 */ /* NetHack may be freely redistributed. See license for details. */ @@ -45,6 +45,10 @@ extern char mapped_menu_cmds[]; /* from options.c */ /* Interface definition, for windows.c */ struct window_procs tty_procs = { "tty", +#ifdef MSDOS + WC_TILED_MAP|WC_ASCII_MAP| +#endif + WC_COLOR|WC_HILITE_PET|WC_INVERSE|WC_EIGHT_BIT_IN, tty_init_nhwindows, tty_player_selection, tty_askname, @@ -97,7 +101,8 @@ struct window_procs tty_procs = { /* other defs that really should go away (they're tty specific) */ tty_start_screen, tty_end_screen, - genl_outrip + genl_outrip, + genl_preference_update, }; static int maxwin = 0; /* number of windows in use */ @@ -308,16 +313,21 @@ tty_player_selection() { int i, k, n; char pick4u = 'n', thisch, lastch = 0; - char pbuf[QBUFSZ]; + char pbuf[QBUFSZ], plbuf[QBUFSZ]; winid win; anything any; menu_item *selected = 0; + /* prevent an unnecessary prompt */ + rigid_role_checks(); + /* Should we randomly pick for the player? */ - if (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE || - flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE) { - const char *prompt = "Shall I pick a character for you? [ynq] "; + if (!flags.randomall && + (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE || + flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE)) { int echoline; + char *prompt = build_plselection_prompt(pbuf, QBUFSZ, flags.initrole, + flags.initrace, flags.initgend, flags.initalign); tty_putstr(BASE_WINDOW, 0, ""); echoline = wins[BASE_WINDOW]->cury; @@ -347,20 +357,26 @@ tty_player_selection() } } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); + /* Select a role, if necessary */ /* we'll try to be compatible with pre-selected race/gender/alignment, * but may not succeed */ if (flags.initrole < 0) { + char rolenamebuf[QBUFSZ]; /* Process the choice */ - if (pick4u == 'y' || flags.initrole == ROLE_RANDOM) { + if (pick4u == 'y' || flags.initrole == ROLE_RANDOM || flags.randomall) { /* Pick a random role */ flags.initrole = pick_role(flags.initrace, flags.initgend, - flags.initalign); + flags.initalign, PICK_RANDOM); if (flags.initrole < 0) { tty_putstr(BASE_WINDOW, 0, "Incompatible role!"); flags.initrole = randrole(); } - } else { + } else { + tty_clear_nhwindow(BASE_WINDOW); + tty_putstr(BASE_WINDOW, 0, "Choosing Character's Role"); /* Prompt for a role */ win = create_nhwindow(NHW_MENU); start_menu(win); @@ -371,13 +387,26 @@ tty_player_selection() any.a_int = i+1; /* must be non-zero */ thisch = lowc(roles[i].name.m[0]); if (thisch == lastch) thisch = highc(thisch); + if (flags.initgend != ROLE_NONE && flags.initgend != ROLE_RANDOM) { + if (flags.initgend == 1 && roles[i].name.f) + Strcpy(rolenamebuf, roles[i].name.f); + else + Strcpy(rolenamebuf, roles[i].name.m); + } else { + if (roles[i].name.f) { + Strcpy(rolenamebuf, roles[i].name.m); + Strcat(rolenamebuf, "/"); + Strcat(rolenamebuf, roles[i].name.f); + } else + Strcpy(rolenamebuf, roles[i].name.m); + } add_menu(win, NO_GLYPH, &any, thisch, - 0, ATR_NONE, an(roles[i].name.m), MENU_UNSELECTED); + 0, ATR_NONE, an(rolenamebuf), MENU_UNSELECTED); lastch = thisch; } } any.a_int = pick_role(flags.initrace, flags.initgend, - flags.initalign)+1; + flags.initalign, PICK_RANDOM)+1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randrole()+1; add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, @@ -385,7 +414,8 @@ tty_player_selection() any.a_int = i+1; /* must be non-zero */ add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE, "Quit", MENU_UNSELECTED); - end_menu(win, "Pick a role"); + Sprintf(pbuf, "Pick a role for your %s", plbuf); + end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); destroy_nhwindow(win); @@ -396,16 +426,18 @@ tty_player_selection() flags.initrole = selected[0].item.a_int - 1; free((genericptr_t) selected), selected = 0; } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); } - + /* Select a race, if necessary */ /* force compatibility with role, try for compatibility with * pre-selected gender/alignment */ if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) { /* pre-selected race not valid */ - if (pick4u == 'y' || flags.initrace == ROLE_RANDOM) { + if (pick4u == 'y' || flags.initrace == ROLE_RANDOM || flags.randomall) { flags.initrace = pick_race(flags.initrole, flags.initgend, - flags.initalign); + flags.initalign, PICK_RANDOM); if (flags.initrace < 0) { tty_putstr(BASE_WINDOW, 0, "Incompatible race!"); flags.initrace = randrace(flags.initrole); @@ -432,6 +464,8 @@ tty_player_selection() /* Permit the user to pick, if there is more than one */ if (n > 1) { + tty_clear_nhwindow(BASE_WINDOW); + tty_putstr(BASE_WINDOW, 0, "Choosing Race"); win = create_nhwindow(NHW_MENU); start_menu(win); any.a_void = 0; /* zero out all bits */ @@ -443,7 +477,7 @@ tty_player_selection() 0, ATR_NONE, races[i].noun, MENU_UNSELECTED); } any.a_int = pick_race(flags.initrole, flags.initgend, - flags.initalign)+1; + flags.initalign, PICK_RANDOM)+1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randrace(flags.initrole)+1; add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, @@ -451,8 +485,7 @@ tty_player_selection() any.a_int = i+1; /* must be non-zero */ add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE, "Quit", MENU_UNSELECTED); - Sprintf(pbuf, "Pick the race of your %s", - roles[flags.initrole].name.m); + Sprintf(pbuf, "Pick the race of your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); destroy_nhwindow(win); @@ -464,6 +497,8 @@ tty_player_selection() } flags.initrace = k; } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); } /* Select a gender, if necessary */ @@ -472,9 +507,9 @@ tty_player_selection() if (flags.initgend < 0 || !validgend(flags.initrole, flags.initrace, flags.initgend)) { /* pre-selected gender not valid */ - if (pick4u == 'y' || flags.initgend == ROLE_RANDOM) { + if (pick4u == 'y' || flags.initgend == ROLE_RANDOM || flags.randomall) { flags.initgend = pick_gend(flags.initrole, flags.initrace, - flags.initalign); + flags.initalign, PICK_RANDOM); if (flags.initgend < 0) { tty_putstr(BASE_WINDOW, 0, "Incompatible gender!"); flags.initgend = randgend(flags.initrole, flags.initrace); @@ -501,6 +536,8 @@ tty_player_selection() /* Permit the user to pick, if there is more than one */ if (n > 1) { + tty_clear_nhwindow(BASE_WINDOW); + tty_putstr(BASE_WINDOW, 0, "Choosing Gender"); win = create_nhwindow(NHW_MENU); start_menu(win); any.a_void = 0; /* zero out all bits */ @@ -512,7 +549,7 @@ tty_player_selection() 0, ATR_NONE, genders[i].adj, MENU_UNSELECTED); } any.a_int = pick_gend(flags.initrole, flags.initrace, - flags.initalign)+1; + flags.initalign, PICK_RANDOM)+1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randgend(flags.initrole, flags.initrace)+1; add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, @@ -520,9 +557,7 @@ tty_player_selection() any.a_int = i+1; /* must be non-zero */ add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE, "Quit", MENU_UNSELECTED); - Sprintf(pbuf, "Pick the gender of your %s %s", - races[flags.initrace].adj, - roles[flags.initrole].name.m); + Sprintf(pbuf, "Pick the gender of your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); destroy_nhwindow(win); @@ -534,6 +569,8 @@ tty_player_selection() } flags.initgend = k; } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); } /* Select an alignment, if necessary */ @@ -541,9 +578,9 @@ tty_player_selection() if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace, flags.initalign)) { /* pre-selected alignment not valid */ - if (pick4u == 'y' || flags.initalign == ROLE_RANDOM) { + if (pick4u == 'y' || flags.initalign == ROLE_RANDOM || flags.randomall) { flags.initalign = pick_align(flags.initrole, flags.initrace, - flags.initgend); + flags.initgend, PICK_RANDOM); if (flags.initalign < 0) { tty_putstr(BASE_WINDOW, 0, "Incompatible alignment!"); flags.initalign = randalign(flags.initrole, flags.initrace); @@ -570,6 +607,8 @@ tty_player_selection() /* Permit the user to pick, if there is more than one */ if (n > 1) { + tty_clear_nhwindow(BASE_WINDOW); + tty_putstr(BASE_WINDOW, 0, "Choosing Alignment"); win = create_nhwindow(NHW_MENU); start_menu(win); any.a_void = 0; /* zero out all bits */ @@ -581,7 +620,7 @@ tty_player_selection() 0, ATR_NONE, aligns[i].adj, MENU_UNSELECTED); } any.a_int = pick_align(flags.initrole, flags.initrace, - flags.initgend)+1; + flags.initgend, PICK_RANDOM)+1; if (any.a_int == 0) /* must be non-zero */ any.a_int = randalign(flags.initrole, flags.initrace)+1; add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, @@ -589,12 +628,7 @@ tty_player_selection() any.a_int = i+1; /* must be non-zero */ add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE, "Quit", MENU_UNSELECTED); - Sprintf(pbuf, "Pick the alignment of your %s %s %s", - genders[flags.initgend].adj, - races[flags.initrace].adj, - (flags.initgend && roles[flags.initrole].name.f) ? - roles[flags.initrole].name.f : - roles[flags.initrole].name.m); + Sprintf(pbuf, "Pick the alignment of your %s", plbuf); end_menu(win, pbuf); n = select_menu(win, PICK_ONE, &selected); destroy_nhwindow(win); @@ -1209,8 +1243,10 @@ struct WinDesc *cw; if (cw->npages > 1) Sprintf(cw->morestr, "(%d of %d)", curr_page + 1, (int) cw->npages); - else + else if (msave) Strcpy(cw->morestr, msave); + else + Strcpy(cw->morestr, defmorestr); tty_curs(window, 1, page_lines); cl_end(); @@ -1483,7 +1519,7 @@ tty_display_nhwindow(window, blocking) } else tty_clear_nhwindow(WIN_MESSAGE); - if (cw->data) + if (cw->data || !cw->maxrow) process_text_window(window, cw); else process_menu_window(window, cw); @@ -1576,7 +1612,7 @@ register int x, y; /* not xchar: perhaps xchar is unsigned and cw->curx = --x; /* column 0 is never used */ cw->cury = y; #ifdef DEBUG - if(x<0 || y<0 || y >= cw->rows || x >= cw->cols) { + if(x<0 || y<0 || y >= cw->rows || x > cw->cols) { const char *s = "[unknown type]"; switch(cw->type) { case NHW_MESSAGE: s = "[topl window]"; break; @@ -1703,7 +1739,9 @@ tty_putstr(window, attr, str) return; } - if(str == (const char*)0 || (cw->flags & WIN_CANCELLED)) + if(str == (const char*)0 || + ( (cw->flags & WIN_CANCELLED) && + (cw->type != NHW_MESSAGE || !iflags.prevmsg_window) )) return; if(cw->type != NHW_MESSAGE) str = compress_str(str); @@ -1815,7 +1853,7 @@ tty_putstr(window, attr, str) cw->maxrow = cw->cury; if(n0 > CO) { /* attempt to break the line */ - for(i = CO-1; i && str[i] != ' ';) + for(i = CO-1; i && str[i] != ' ' && str[i] != '\n';) i--; if(i) { cw->data[cw->cury-1][++i] = '\0'; @@ -1874,6 +1912,8 @@ boolean complain; } else if(u.ux) docrt(); } else { winid datawin = tty_create_nhwindow(NHW_TEXT); + boolean empty = TRUE; + if(complain #ifndef NO_TERMS && nh_CD @@ -1890,11 +1930,12 @@ boolean complain; if ((cr = index(buf, '\r')) != 0) *cr = 0; #endif if (index(buf, '\t') != 0) (void) tabexpand(buf); + empty = FALSE; tty_putstr(datawin, 0, buf); if(wins[datawin]->flags & WIN_CANCELLED) break; } - tty_display_nhwindow(datawin, FALSE); + if (!empty) tty_display_nhwindow(datawin, FALSE); tty_destroy_nhwindow(datawin); (void) dlb_fclose(f); } @@ -2144,8 +2185,11 @@ const char *mesg; response to a prompt, we'll assume that the display is up to date */ tty_putstr(WIN_MESSAGE, 0, mesg); /* if `mesg' didn't wrap (triggering --More--), force --More-- now */ - if (ttyDisplay->toplin == 1) + if (ttyDisplay->toplin == 1) { more(); + ttyDisplay->toplin = 1; /* more resets this */ + tty_clear_nhwindow(WIN_MESSAGE); + } /* normally means skip further messages, but in this case it means cancel the current prompt; any other messages should continue to be output normally */ @@ -2179,7 +2223,7 @@ tty_wait_synch() if(ttyDisplay->inmore) { addtopl("--More--"); (void) fflush(stdout); - } else if(ttyDisplay->inread) { + } else if(ttyDisplay->inread > program_state.gameover) { /* this can only happen if we were reading and got interrupted */ ttyDisplay->toplin = 3; /* do this twice; 1st time gets the Quit? message again */ @@ -2249,6 +2293,7 @@ end_glyphout() #endif } +#ifndef WIN32 void g_putch(in_ch) int in_ch; @@ -2280,6 +2325,7 @@ int in_ch; return; } +#endif /* !WIN32 */ #ifdef CLIPPING void @@ -2331,178 +2377,26 @@ int x, y; * Since this is only called from show_glyph(), it is assumed that the * position and glyph are always correct (checked there)! */ + void tty_print_glyph(window, x, y, glyph) winid window; xchar x, y; int glyph; { - uchar ch; - register int offset; - boolean is_reverse = FALSE; -#ifdef TEXTCOLOR + int ch; + boolean reverse_on = FALSE; int color; - -#define zap_color(n) color = iflags.use_color ? zapcolors[n] : NO_COLOR -#define cmap_color(n) color = iflags.use_color ? defsyms[n].color : NO_COLOR -#define obj_color(n) color = iflags.use_color ? objects[n].oc_color : NO_COLOR -#define mon_color(n) color = iflags.use_color ? mons[n].mcolor : NO_COLOR -#define invis_color(n) color = NO_COLOR -#define pet_color(n) color = iflags.use_color ? mons[n].mcolor : \ - /* If no color, try to hilite pets; black */ \ - /* should be nh_HI */ \ - ((iflags.hilite_pet && has_color(CLR_BLACK)) ? \ - CLR_BLACK : NO_COLOR) -#define warn_color(n) color = iflags.use_color ? def_warnsyms[n].color : NO_COLOR -# if defined(REINCARNATION) && defined(ASCIIGRAPH) -# define ROGUE_COLOR -# endif - -#else /* no text color */ - -#define zap_color(n) -#define cmap_color(n) -#define obj_color(n) -#define mon_color(n) -#define invis_color(n) -#define pet_color(c) -#define warn_color(n) -#endif - -#ifdef ROGUE_COLOR -# if defined(USE_TILES) && defined(MSDOS) -#define HAS_ROGUE_IBM_GRAPHICS (iflags.IBMgraphics && !iflags.grmode && \ - Is_rogue_level(&u.uz)) -# else -#define HAS_ROGUE_IBM_GRAPHICS (iflags.IBMgraphics && Is_rogue_level(&u.uz)) -# endif -#endif - + unsigned special; + #ifdef CLIPPING if(clipping) { if(x <= clipx || y < clipy || x >= clipxmax || y >= clipymax) return; } #endif - /* - * Map the glyph back to a character. - * - * Warning: For speed, this makes an assumption on the order of - * offsets. The order is set in display.h. - */ - if ((offset = (glyph - GLYPH_WARNING_OFF)) >= 0) { /* a warning flash */ - ch = warnsyms[offset]; -# ifdef ROGUE_COLOR - if (HAS_ROGUE_IBM_GRAPHICS) - color = NO_COLOR; - else -# endif - warn_color(offset); - } else if ((offset = (glyph - GLYPH_SWALLOW_OFF)) >= 0) { /* swallow */ - /* see swallow_to_glyph() in display.c */ - ch = (uchar) showsyms[S_sw_tl + (offset & 0x7)]; -#ifdef ROGUE_COLOR - if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) - color = NO_COLOR; - else -#endif - mon_color(offset >> 3); - } else if ((offset = (glyph - GLYPH_ZAP_OFF)) >= 0) { /* zap beam */ - /* see zapdir_to_glyph() in display.c */ - ch = showsyms[S_vbeam + (offset & 0x3)]; -#ifdef ROGUE_COLOR - if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) - color = NO_COLOR; - else -#endif - zap_color((offset >> 2)); - } else if ((offset = (glyph - GLYPH_CMAP_OFF)) >= 0) { /* cmap */ - ch = showsyms[offset]; -#ifdef ROGUE_COLOR - if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) { - if (offset >= S_vwall && offset <= S_hcdoor) - color = CLR_BROWN; - else if (offset >= S_arrow_trap && offset <= S_polymorph_trap) - color = CLR_MAGENTA; - else if (offset == S_corr || offset == S_litcorr) - color = CLR_GRAY; - else if (offset >= S_room && offset <= S_water) - color = CLR_GREEN; - else - color = NO_COLOR; - } else -#endif - cmap_color(offset); - } else if ((offset = (glyph - GLYPH_OBJ_OFF)) >= 0) { /* object */ - ch = oc_syms[(int)objects[offset].oc_class]; -#ifdef ROGUE_COLOR - if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) { - switch(objects[offset].oc_class) { - case GOLD_CLASS: color = CLR_YELLOW; break; - case FOOD_CLASS: color = CLR_RED; break; - default: color = CLR_BRIGHT_BLUE; break; - } - } else -#endif - obj_color(offset); - } else if ((offset = (glyph - GLYPH_RIDDEN_OFF)) >= 0) { /* mon ridden */ - ch = monsyms[(int)mons[offset].mlet]; -#ifdef ROGUE_COLOR - if (HAS_ROGUE_IBM_GRAPHICS) - /* This currently implies that the hero is here -- monsters */ - /* don't ride (yet...). Should we set it to yellow like in */ - /* the monster case below? There is no equivalent in rogue. */ - color = NO_COLOR; /* no need to check iflags.use_color */ - else -#endif - mon_color(offset); - } else if ((offset = (glyph - GLYPH_BODY_OFF)) >= 0) { /* a corpse */ - ch = oc_syms[(int)objects[CORPSE].oc_class]; -#ifdef ROGUE_COLOR - if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) - color = CLR_RED; - else -#endif - mon_color(offset); - } else if ((offset = (glyph - GLYPH_DETECT_OFF)) >= 0) { /* mon detect */ - ch = monsyms[(int)mons[offset].mlet]; -#ifdef ROGUE_COLOR - if (HAS_ROGUE_IBM_GRAPHICS) - color = NO_COLOR; /* no need to check iflags.use_color */ - else -#endif - mon_color(offset); - /* Disabled for now; anyone want to get reverse video to work? */ - /* is_reverse = TRUE; */ - } else if ((offset = (glyph - GLYPH_INVIS_OFF)) >= 0) { /* invisible */ - ch = DEF_INVISIBLE; -#ifdef ROGUE_COLOR - if (HAS_ROGUE_IBM_GRAPHICS) - color = NO_COLOR; /* no need to check iflags.use_color */ - else -#endif - invis_color(offset); - } else if ((offset = (glyph - GLYPH_PET_OFF)) >= 0) { /* a pet */ - ch = monsyms[(int)mons[offset].mlet]; -#ifdef ROGUE_COLOR - if (HAS_ROGUE_IBM_GRAPHICS) - color = NO_COLOR; /* no need to check iflags.use_color */ - else -#endif - pet_color(offset); - } else { /* a monster */ - ch = monsyms[(int)mons[glyph].mlet]; -#ifdef ROGUE_COLOR - if (HAS_ROGUE_IBM_GRAPHICS && iflags.use_color) { - if (x == u.ux && y == u.uy) - /* actually player should be yellow-on-gray if in a corridor */ - color = CLR_YELLOW; - else - color = NO_COLOR; - } else -#endif - mon_color(glyph); - } + /* map glyph to character and color */ + mapglyph(glyph, &ch, &color, &special, x, y); /* Move the cursor. */ tty_curs(window, x,y); @@ -2515,18 +2409,6 @@ tty_print_glyph(window, x, y, glyph) #endif #ifdef TEXTCOLOR - /* Turn off color if no color defined, or rogue level w/o PC graphics. */ -# ifdef REINCARNATION -# ifdef ASCIIGRAPH - if (!has_color(color) || (Is_rogue_level(&u.uz) && !HAS_ROGUE_IBM_GRAPHICS)) -# else - if (!has_color(color) || Is_rogue_level(&u.uz)) -# endif -# else - if (!has_color(color)) -# endif - color = NO_COLOR; - if (color != ttyDisplay->color) { if(ttyDisplay->color != NO_COLOR) term_end_color(); @@ -2535,17 +2417,24 @@ tty_print_glyph(window, x, y, glyph) term_start_color(color); } #endif /* TEXTCOLOR */ + + /* must be after color check; term_end_color may turn off inverse too */ + if (((special & MG_PET) && iflags.hilite_pet) || + ((special & MG_DETECT) && iflags.use_inverse)) { + term_start_attr(ATR_INVERSE); + reverse_on = TRUE; + } + #if defined(USE_TILES) && defined(MSDOS) if (iflags.grmode && iflags.tile_view) - xputg(glyph,(int)ch); + xputg(glyph,ch,special); else #endif - if (is_reverse) { /* not currently working */ - term_start_attr(ATR_INVERSE); - g_putch((int)ch); /* print the character */ - term_end_attr(ATR_INVERSE); - } else - g_putch((int)ch); /* print the character */ + g_putch(ch); /* print the character */ + + if (reverse_on) + term_end_attr(ATR_INVERSE); + wins[window]->curx++; /* one character over */ ttyDisplay->curx++; /* the real cursor moved too */ } diff --git a/win/win32/dgncomp.dsp b/win/win32/dgncomp.dsp new file mode 100644 index 0000000..815384c --- /dev/null +++ b/win/win32/dgncomp.dsp @@ -0,0 +1,297 @@ +# Microsoft Developer Studio Project File - Name="dgncomp" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=dgncomp - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "dgncomp.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "dgncomp.mak" CFG="dgncomp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "dgncomp - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "dgncomp - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "dgncomp - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "..\util" +# PROP BASE Intermediate_Dir "dgncomp___Win32_Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\util" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\sys\winnt" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32CON" /D "DLB" /D "MSWIN_GRAPHICS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x1009 /d "NDEBUG" +# ADD RSC /l 0x1009 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\util\dgn_comp.exe" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=dgncomp +PostBuild_Cmds=echo Building dungeon echo chdir ..\dat chdir ..\dat echo ..\util\dgn_comp.exe dungeon.pdf ..\util\dgn_comp.exe dungeon.pdf echo chdir ..\build chdir ..\build +# End Special Build Tool + +!ELSEIF "$(CFG)" == "dgncomp - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "dgncomp___Win32_Debug" +# PROP BASE Intermediate_Dir "dgncomp___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\util" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\sys\winnt" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32CON" /D "DLB" /D "MSWIN_GRAPHICS" /FD /GZ /c +# ADD BASE RSC /l 0x1009 /d "_DEBUG" +# ADD RSC /l 0x1009 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"..\util\dgn_comp.exe" /pdbtype:sept +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=dgncomp +PostBuild_Cmds=echo Building dungeon echo chdir ..\dat chdir ..\dat echo ..\util\dgn_comp.exe dungeon.pdf ..\util\dgn_comp.exe dungeon.pdf echo chdir ..\build chdir ..\build +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "dgncomp - Win32 Release" +# Name "dgncomp - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\src\alloc.c +# End Source File +# Begin Source File + +SOURCE=..\util\dgn_lex.c +# End Source File +# Begin Source File + +SOURCE=..\util\dgn_main.c +# End Source File +# Begin Source File + +SOURCE=..\util\dgn_yacc.c +# End Source File +# Begin Source File + +SOURCE=..\util\panic.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\include\align.h +# End Source File +# Begin Source File + +SOURCE=..\include\attrib.h +# End Source File +# Begin Source File + +SOURCE=..\include\color.h +# End Source File +# Begin Source File + +SOURCE=..\include\config.h +# End Source File +# Begin Source File + +SOURCE=..\include\config1.h +# End Source File +# Begin Source File + +SOURCE=..\include\coord.h +# End Source File +# Begin Source File + +SOURCE=..\include\decl.h +# End Source File +# Begin Source File + +SOURCE=..\include\dgn_comp.h +# End Source File +# Begin Source File + +SOURCE=..\include\dgn_file.h +# End Source File +# Begin Source File + +SOURCE=..\include\display.h +# End Source File +# Begin Source File + +SOURCE=..\include\dungeon.h +# End Source File +# Begin Source File + +SOURCE=..\include\engrave.h +# End Source File +# Begin Source File + +SOURCE=..\include\flag.h +# End Source File +# Begin Source File + +SOURCE=..\include\global.h +# End Source File +# Begin Source File + +SOURCE=..\include\mkroom.h +# End Source File +# Begin Source File + +SOURCE=..\include\monattk.h +# End Source File +# Begin Source File + +SOURCE=..\include\monst.h +# End Source File +# Begin Source File + +SOURCE=..\include\monsym.h +# End Source File +# Begin Source File + +SOURCE=..\include\nhlan.h +# End Source File +# Begin Source File + +SOURCE=..\include\ntconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\obj.h +# End Source File +# Begin Source File + +SOURCE=..\include\objclass.h +# End Source File +# Begin Source File + +SOURCE=..\include\onames.h +# End Source File +# Begin Source File + +SOURCE=..\include\permonst.h +# End Source File +# Begin Source File + +SOURCE=..\include\pm.h +# End Source File +# Begin Source File + +SOURCE=..\include\prop.h +# End Source File +# Begin Source File + +SOURCE=..\include\quest.h +# End Source File +# Begin Source File + +SOURCE=..\include\rect.h +# End Source File +# Begin Source File + +SOURCE=..\include\region.h +# End Source File +# Begin Source File + +SOURCE=..\include\rm.h +# End Source File +# Begin Source File + +SOURCE=..\include\skills.h +# End Source File +# Begin Source File + +SOURCE=..\include\spell.h +# End Source File +# Begin Source File + +SOURCE=..\include\timeout.h +# End Source File +# Begin Source File + +SOURCE=..\include\tradstdc.h +# End Source File +# Begin Source File + +SOURCE=..\include\trampoli.h +# End Source File +# Begin Source File + +SOURCE=..\include\trap.h +# End Source File +# Begin Source File + +SOURCE=..\include\vision.h +# End Source File +# Begin Source File + +SOURCE=..\include\winprocs.h +# End Source File +# Begin Source File + +SOURCE=..\include\wintty.h +# End Source File +# Begin Source File + +SOURCE=..\include\wintype.h +# End Source File +# Begin Source File + +SOURCE=..\include\you.h +# End Source File +# Begin Source File + +SOURCE=..\include\youprop.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/win/win32/dgnstuff.dsp b/win/win32/dgnstuff.dsp new file mode 100644 index 0000000..ab1e95a --- /dev/null +++ b/win/win32/dgnstuff.dsp @@ -0,0 +1,97 @@ +# Microsoft Developer Studio Project File - Name="dgnstuff" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) External Target" 0x0106 + +CFG=dgnstuff - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "dgnstuff.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "dgnstuff.mak" CFG="dgnstuff - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "dgnstuff - Win32 Release" (based on "Win32 (x86) External Target") +!MESSAGE "dgnstuff - Win32 Debug" (based on "Win32 (x86) External Target") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "dgnstuff - Win32 Release" + +# PROP BASE Use_MFC +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Cmd_Line "NMAKE /f dgnstuff.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "dgnstuff.exe" +# PROP BASE Bsc_Name "dgnstuff.bsc" +# PROP BASE Target_Dir "" +# PROP Use_MFC +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Cmd_Line "nmake /f "dgnstuff.mak"" +# PROP Rebuild_Opt "/a" +# PROP Target_File "..\util\dgncomp.exe" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "dgnstuff - Win32 Debug" + +# PROP BASE Use_MFC +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Cmd_Line "NMAKE /f dgnstuff.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "dgnstuff.exe" +# PROP BASE Bsc_Name "dgnstuff.bsc" +# PROP BASE Target_Dir "" +# PROP Use_MFC +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "dgnstuff___Win32_Debug" +# PROP Intermediate_Dir "Debug" +# PROP Cmd_Line "nmake /f "dgnstuff.mak"" +# PROP Rebuild_Opt "/a" +# PROP Target_File "..\util\dgncomp.exe" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "dgnstuff - Win32 Release" +# Name "dgnstuff - Win32 Debug" + +!IF "$(CFG)" == "dgnstuff - Win32 Release" + +!ELSEIF "$(CFG)" == "dgnstuff - Win32 Debug" + +!ENDIF + +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/win/win32/dgnstuff.mak b/win/win32/dgnstuff.mak new file mode 100644 index 0000000..8e5aa81 --- /dev/null +++ b/win/win32/dgnstuff.mak @@ -0,0 +1,59 @@ +#Set all of these or none of them +#YACC = byacc.exe +#LEX = flex.exe +#YTABC = y_tab.c +#YTABH = y_tab.h +#LEXYYC = lexyy.c + +!IF "$(YACC)"!="" +@echo Yacc-alike set to $(YACC) +@echo YTABC set to $(YTABC) +@echo YTABH set to $(YTABH) +!ENDIF + +!IF "$(LEX)"!="" +@echo Lex-alike set to $(LEX) +@echo LEXYYC set to $(LEXYYC) +!ENDIF + +default: all + +all: ..\util\dgn_yacc.c ..\util\dgn_lex.c + +rebuild: clean all + +clean: + -del ..\util\dgn_lex.c + -del ..\util\dgn_yacc.c + -del ..\include\dgn_comp.h + +#========================================== +# Dungeon Compiler Stuff +#========================================== + +..\util\dgn_yacc.c ..\include\dgn_comp.h : ..\util\dgn_comp.y +!IF "$(YACC)"=="" + @echo Using pre-built dgn_yacc.c and dgn_comp.h + @copy ..\sys\share\dgn_yacc.c ..\util\dgn_yacc.c + @copy ..\sys\share\dgn_comp.h ..\include\dgn_comp.h +!ELSE + chdir ..\util + $(YACC) -d dgn_comp.y + copy $(YTABC) $@ + copy $(YTABH) ..\include\dgn_comp.h + @del $(YTABC) + @del $(YTABH) + chdir ..\build +!ENDIF + +..\util\dgn_lex.c: ..\util\dgn_comp.l +!IF "$(LEX)"=="" + @echo Using pre-built dgn_lex.c + @copy ..\sys\share\dgn_lex.c $@ +!ELSE + chdir ..\util + $(LEX) dgn_comp.l + copy $(LEXYYC) $@ + @del $(LEXYYC) + chdir ..\build +!ENDIF diff --git a/win/win32/dlb_main.dsp b/win/win32/dlb_main.dsp new file mode 100644 index 0000000..8dff70f --- /dev/null +++ b/win/win32/dlb_main.dsp @@ -0,0 +1,179 @@ +# Microsoft Developer Studio Project File - Name="dlb_main" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=dlb_main - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "dlb_main.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "dlb_main.mak" CFG="dlb_main - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "dlb_main - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "dlb_main - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "dlb_main - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\sys\winnt" /I "..\win\share" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "DLB" /D "WIN32CON" /D "MSWIN_GRAPHICS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x1009 /d "NDEBUG" +# ADD RSC /l 0x1009 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\util\dlb_main.exe" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Packaging via DLB +PostBuild_Cmds=echo chdir ..\dat \ +chdir ..\dat \ +chdir \ + echo data >dlb.lst \ + echo oracles >>dlb.lst \ + if exist options echo options >>dlb.lst \ + if exist ttyoptions echo ttyoptions >>dlb.lst \ + if exist guioptions echo guioptions >>dlb.lst \ + if NOT exist porthelp copy ..\sys\winnt\porthelp porthelp \ + if exist porthelp echo porthelp >>dlb.lst \ + echo quest.dat >>dlb.lst \ + echo rumors >>dlb.lst \ + echo help >>dlb.lst \ + echo hh >>dlb.lst \ + echo cmdhelp >>dlb.lst \ + echo history >>dlb.lst \ + echo opthelp >>dlb.lst \ + echo wizhelp >>dlb.lst \ + echo dungeon >>dlb.lst \ + echo license >>dlb.lst \ + for %%N in (*.lev) do echo %%N >>dlb.lst \ + ..\util\dlb_main.exe cIf dlb.lst nhdat \ + echo chdir ..\build \ +chdir ..\build \ +echo if NOT exist ..\binary\*.* mkdir ..\binary \ + if NOT exist ..\binary\*.* mkdir ..\binary +# End Special Build Tool + +!ELSEIF "$(CFG)" == "dlb_main - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\sys\winnt" /I "..\win\share" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "DLB" /D "WIN32CON" /D "MSWIN_GRAPHICS" /FD /GZ /c +# ADD BASE RSC /l 0x1009 /d "_DEBUG" +# ADD RSC /l 0x1009 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"..\util\dlb_main.exe" /pdbtype:sept +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Packaging via dlb +PostBuild_Cmds=echo chdir ..\dat \ +chdir ..\dat \ +chdir \ + echo data >dlb.lst \ + echo oracles >>dlb.lst \ + if exist options echo options >>dlb.lst \ + if exist ttyoptions echo ttyoptions >>dlb.lst \ + if exist guioptions echo guioptions >>dlb.lst \ + if NOT exist porthelp copy ..\sys\winnt\porthelp porthelp \ + if exist porthelp echo porthelp >>dlb.lst \ + echo quest.dat >>dlb.lst \ + echo rumors >>dlb.lst \ + echo help >>dlb.lst \ + echo hh >>dlb.lst \ + echo cmdhelp >>dlb.lst \ + echo history >>dlb.lst \ + echo opthelp >>dlb.lst \ + echo wizhelp >>dlb.lst \ + echo dungeon >>dlb.lst \ + echo license >>dlb.lst \ + for %%N in (*.lev) do echo %%N >>dlb.lst \ + ..\util\dlb_main.exe cIf dlb.lst nhdat \ +echo chdir ..\build \ +chdir ..\build \ +echo if NOT exist ..\binary\*.* mkdir ..\binary \ +if NOT exist ..\binary\*.* mkdir ..\binary +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "dlb_main - Win32 Release" +# Name "dlb_main - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\src\alloc.c +# End Source File +# Begin Source File + +SOURCE=..\src\dlb.c +# End Source File +# Begin Source File + +SOURCE=..\util\dlb_main.c +# End Source File +# Begin Source File + +SOURCE=..\util\panic.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\include\dlb.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/win/win32/levcomp.dsp b/win/win32/levcomp.dsp new file mode 100644 index 0000000..7c1486e --- /dev/null +++ b/win/win32/levcomp.dsp @@ -0,0 +1,198 @@ +# Microsoft Developer Studio Project File - Name="levcomp" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=levcomp - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "levcomp.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "levcomp.mak" CFG="levcomp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "levcomp - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "levcomp - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "levcomp - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\util" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\sys\winnt" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32CON" /D "DLB" /D "MSWIN_GRAPHICS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x1009 /d "NDEBUG" +# ADD RSC /l 0x1009 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=levcomp +PostBuild_Cmds=echo Building special levels echo chdir ..\dat chdir ..\dat \ +echo arch.des ..\util\levcomp.exe arch.des \ +echo barb.des ..\util\levcomp.exe barb.des \ +echo bigroom.des ..\util\levcomp.exe bigroom.des \ +echo castle.des ..\util\levcomp.exe castle.des \ +echo caveman.des ..\util\levcomp.exe caveman.des \ +echo endgame.des ..\util\levcomp.exe endgame.des \ +echo gehennom.des ..\util\levcomp.exe gehennom.des \ +echo healer.des ..\util\levcomp.exe healer.des \ +echo knight.des ..\util\levcomp.exe knight.des \ +echo knox.des ..\util\levcomp.exe knox.des \ +echo medusa.des ..\util\levcomp.exe medusa.des \ +echo mines.des ..\util\levcomp.exe mines.des \ +echo monk.des ..\util\levcomp.exe monk.des \ +echo oracle.des ..\util\levcomp.exe oracle.des \ +echo priest.des ..\util\levcomp.exe priest.des \ +echo ranger.des ..\util\levcomp.exe ranger.des \ +echo rogue.des ..\util\levcomp.exe rogue.des \ +echo samurai.des ..\util\levcomp.exe samurai.des \ +echo sokoban.des ..\util\levcomp.exe sokoban.des \ +echo tourist.des ..\util\levcomp.exe tourist.des \ +echo tower.des ..\util\levcomp.exe tower.des \ +echo valkyrie.des ..\util\levcomp.exe valkyrie.des \ +echo wizard .des ..\util\levcomp.exe wizard.des \ +echo yendor.des ..\util\levcomp.exe yendor.des \ +echo chdir ..\build chdir ..\build +# End Special Build Tool + +!ELSEIF "$(CFG)" == "levcomp - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\util" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\sys\winnt" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32CON" /D "DLB" /D "MSWIN_GRAPHICS" /FD /GZ /c +# ADD BASE RSC /l 0x1009 /d "_DEBUG" +# ADD RSC /l 0x1009 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /pdbtype:sept +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=levcomp +PostBuild_Cmds=echo Building special levels echo chdir ..\dat chdir ..\dat \ +echo arch.des ..\util\levcomp.exe arch.des \ +echo barb.des ..\util\levcomp.exe barb.des \ +echo bigroom.des ..\util\levcomp.exe bigroom.des \ +echo castle.des ..\util\levcomp.exe castle.des \ +echo caveman.des ..\util\levcomp.exe caveman.des \ +echo endgame.des ..\util\levcomp.exe endgame.des \ +echo gehennom.des ..\util\levcomp.exe gehennom.des \ +echo healer.des ..\util\levcomp.exe healer.des \ +echo knight.des ..\util\levcomp.exe knight.des \ +echo knox.des ..\util\levcomp.exe knox.des \ +echo medusa.des ..\util\levcomp.exe medusa.des \ +echo mines.des ..\util\levcomp.exe mines.des \ +echo monk.des ..\util\levcomp.exe monk.des \ +echo oracle.des ..\util\levcomp.exe oracle.des \ +echo priest.des ..\util\levcomp.exe priest.des \ +echo ranger.des ..\util\levcomp.exe ranger.des \ +echo rogue.des ..\util\levcomp.exe rogue.des \ +echo samurai.des ..\util\levcomp.exe samurai.des \ +echo sokoban.des ..\util\levcomp.exe sokoban.des \ +echo tourist.des ..\util\levcomp.exe tourist.des \ +echo tower.des ..\util\levcomp.exe tower.des \ +echo valkyrie.des ..\util\levcomp.exe valkyrie.des \ +echo wizard .des ..\util\levcomp.exe wizard.des \ +echo yendor.des ..\util\levcomp.exe yendor.des \ +echo chdir ..\build chdir ..\build +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "levcomp - Win32 Release" +# Name "levcomp - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\src\alloc.c +# End Source File +# Begin Source File + +SOURCE=..\src\decl.c +# End Source File +# Begin Source File + +SOURCE=..\src\drawing.c +# End Source File +# Begin Source File + +SOURCE=..\util\lev_lex.c +# End Source File +# Begin Source File + +SOURCE=..\util\lev_main.c +# End Source File +# Begin Source File + +SOURCE=..\util\lev_yacc.c +# End Source File +# Begin Source File + +SOURCE=..\src\monst.c +# End Source File +# Begin Source File + +SOURCE=..\src\objects.c +# End Source File +# Begin Source File + +SOURCE=..\util\panic.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\include\lev_comp.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/win/win32/levstuff.dsp b/win/win32/levstuff.dsp new file mode 100644 index 0000000..276ad81 --- /dev/null +++ b/win/win32/levstuff.dsp @@ -0,0 +1,97 @@ +# Microsoft Developer Studio Project File - Name="levstuff" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) External Target" 0x0106 + +CFG=levstuff - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "levstuff.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "levstuff.mak" CFG="levstuff - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "levstuff - Win32 Release" (based on "Win32 (x86) External Target") +!MESSAGE "levstuff - Win32 Debug" (based on "Win32 (x86) External Target") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "levstuff - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Cmd_Line "NMAKE /f levstuff.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "levstuff.exe" +# PROP BASE Bsc_Name "levstuff.bsc" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Cmd_Line "nmake /f "levstuff.mak"" +# PROP Rebuild_Opt "/a" +# PROP Target_File "..\util\lev_lex.c" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "levstuff - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "levstuff___Win32_Debug0" +# PROP BASE Intermediate_Dir "levstuff___Win32_Debug0" +# PROP BASE Cmd_Line "NMAKE /f levstuff.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "levstuff.exe" +# PROP BASE Bsc_Name "levstuff.bsc" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "levstuff___Win32_Debug0" +# PROP Intermediate_Dir "levstuff___Win32_Debug0" +# PROP Cmd_Line "nmake /f "levstuff.mak"" +# PROP Rebuild_Opt "/a" +# PROP Target_File "..\util\lev_lex.c" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "levstuff - Win32 Release" +# Name "levstuff - Win32 Debug" + +!IF "$(CFG)" == "levstuff - Win32 Release" + +!ELSEIF "$(CFG)" == "levstuff - Win32 Debug" + +!ENDIF + +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/win/win32/levstuff.mak b/win/win32/levstuff.mak new file mode 100644 index 0000000..c7540c4 --- /dev/null +++ b/win/win32/levstuff.mak @@ -0,0 +1,59 @@ +#YACC = byacc.exe +#LEX = flex.exe +#YTABC = y_tab.c +#YTABH = y_tab.h +#LEXYYC = lexyy.c + +!IF "$(YACC)"!="" +@echo Yacc-alike set to $(YACC) +@echo YTABC set to $(YTABC) +@echo YTABH set to $(YTABH) +!ENDIF + +!IF "$(LEX)"!="" +@echo Lex-alike set to $(LEX) +@echo LEXYYC set to $(LEXYYC) +!ENDIF + + +default: all + +all: ..\util\lev_yacc.c ..\util\lev_lex.c + +rebuild: clean all + +clean: + -del ..\util\lev_lex.c + -del ..\util\lev_yacc.c + -del ..\include\lev_comp.h + +#========================================== +# Level Compiler Stuff +#========================================== +..\util\lev_yacc.c ..\include\lev_comp.h: ..\util\lev_comp.y +!IF "$(YACC)"=="" + @echo Using pre-built lev_yacc.c and lev_comp.h + @copy ..\sys\share\lev_yacc.c ..\util\lev_yacc.c + @copy ..\sys\share\lev_comp.h ..\include\lev_comp.h +!ELSE + chdir ..\util + $(YACC) -d lev_comp.y + copy $(YTABC) $@ + copy $(YTABH) ..\include\lev_comp.h + @del $(YTABC) + @del $(YTABH) + chdir ..\build +!ENDIF + +..\util\lev_lex.c: ..\util\lev_comp.l +!IF "$(LEX)"=="" + @echo Using pre-built lev_lex.c + @copy ..\sys\share\lev_lex.c $@ +!ELSE + chdir ..\util + $(LEX) lev_comp.l + copy $(LEXYYC) $@ + @del $(LEXYYC) + chdir ..\build +!ENDIF + diff --git a/win/win32/makedefs.dsp b/win/win32/makedefs.dsp new file mode 100644 index 0000000..5ecdc88 --- /dev/null +++ b/win/win32/makedefs.dsp @@ -0,0 +1,198 @@ +# Microsoft Developer Studio Project File - Name="makedefs" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=makedefs - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "makedefs.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "makedefs.mak" CFG="makedefs - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "makedefs - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "makedefs - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "makedefs - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "..\util" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "." /I "..\include" /I "..\sys\winnt" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32CON" /D "DLB" /D "MSWIN_GRAPHICS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Running makedefs +PostBuild_Cmds=echo chdir ..\util chdir ..\util chdir \ +echo makedefs.exe -v makedefs.exe -v \ +echo makedefs.exe -o makedefs.exe -o \ +echo makedefs.exe -p makedefs.exe -p \ +echo makedefs.exe -m makedefs.exe -m \ +echo makedefs.exe -z makedefs.exe -z \ +echo chdir ..\dat chdir ..\dat chdir \ +echo Generating NetHack database echo ..\util\makedefs.exe -d ..\util\makedefs.exe -d \ +echo Generating rumors echo ..\util\makedefs.exe -r ..\util\makedefs.exe -r \ +echo Generating quests echo ..\util\makedefs.exe -q ..\util\makedefs.exe -q \ +echo Generating oracles echo ..\util\makedefs.exe -h ..\util\makedefs.exe -h \ +echo Generating dungeon.pdf echo ..\util\makedefs.exe -e ..\util\makedefs.exe -e \ +echo chdir ..\build chdir ..\build \ +copy ..\win\share\tilemap.c ..\win\share\tiletxt.c +# End Special Build Tool + +!ELSEIF "$(CFG)" == "makedefs - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "..\util" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "." /I "..\include" /I "..\sys\winnt" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32CON" /D "DLB" /D "MSWIN_GRAPHICS" /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /pdbtype:sept +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Running makedefs +PostBuild_Cmds=echo chdir ..\util chdir ..\util chdir \ +echo makedefs.exe -v makedefs.exe -v \ +echo makedefs.exe -o makedefs.exe -o \ +echo makedefs.exe -p makedefs.exe -p \ +echo makedefs.exe -m makedefs.exe -m \ +echo makedefs.exe -z makedefs.exe -z \ +echo chdir ..\dat chdir ..\dat chdir \ +echo Generating NetHack database echo ..\util\makedefs.exe -d ..\util\makedefs.exe -d \ +echo Generating rumors echo ..\util\makedefs.exe -r ..\util\makedefs.exe -r \ +echo Generating quests echo ..\util\makedefs.exe -q ..\util\makedefs.exe -q \ +echo Generating oracles echo ..\util\makedefs.exe -h ..\util\makedefs.exe -h \ +echo Generating dungeon.pdf echo ..\util\makedefs.exe -e ..\util\makedefs.exe -e \ +echo chdir ..\build chdir ..\build \ +copy ..\win\share\tilemap.c ..\win\share\tiletxt.c +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "makedefs - Win32 Release" +# Name "makedefs - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\util\makedefs.c +# End Source File +# Begin Source File + +SOURCE=..\src\monst.c +# End Source File +# Begin Source File + +SOURCE=..\src\objects.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\include\config.h +# End Source File +# Begin Source File + +SOURCE=..\include\config1.h +# End Source File +# Begin Source File + +SOURCE=..\include\coord.h +# End Source File +# Begin Source File + +SOURCE=..\include\global.h +# End Source File +# Begin Source File + +SOURCE=..\include\monattk.h +# End Source File +# Begin Source File + +SOURCE=..\include\monflag.h +# End Source File +# Begin Source File + +SOURCE=..\include\monsym.h +# End Source File +# Begin Source File + +SOURCE=..\include\nhlan.h +# End Source File +# Begin Source File + +SOURCE=..\include\ntconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\objclass.h +# End Source File +# Begin Source File + +SOURCE=..\include\patchlevel.h +# End Source File +# Begin Source File + +SOURCE=..\include\qtext.h +# End Source File +# Begin Source File + +SOURCE=..\include\tradstdc.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/win/win32/mhaskyn.c b/win/win32/mhaskyn.c new file mode 100644 index 0000000..8553d9d --- /dev/null +++ b/win/win32/mhaskyn.c @@ -0,0 +1,11 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#include +#include "winMS.h" +#include "mhaskyn.h" + +int mswin_yes_no_dialog( const char *question, const char *choices, int def) +{ + return '\032'; +} \ No newline at end of file diff --git a/win/win32/mhaskyn.h b/win/win32/mhaskyn.h new file mode 100644 index 0000000..a386b09 --- /dev/null +++ b/win/win32/mhaskyn.h @@ -0,0 +1,11 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef MSWINAskYesNO_h +#define MSWINAskYesNO_h + +#include "winMS.h" + +int mswin_yes_no_dialog( const char *question, const char *choices, int def); + +#endif /* MSWINAskYesNO_h */ diff --git a/win/win32/mhdlg.c b/win/win32/mhdlg.c new file mode 100644 index 0000000..6849e68 --- /dev/null +++ b/win/win32/mhdlg.c @@ -0,0 +1,729 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +/* various dialog boxes are defined here */ + +#include "winMS.h" +#include "hack.h" +#include "func_tab.h" +#include "resource.h" +#include "mhdlg.h" + +/*---------------------------------------------------------------*/ +/* data for getlin dialog */ +struct getlin_data { + const char* question; + char* result; + size_t result_size; +}; + +BOOL CALLBACK GetlinDlgProc(HWND, UINT, WPARAM, LPARAM); + +int mswin_getlin_window ( + const char *question, + char *result, + size_t result_size +) +{ + int ret; + struct getlin_data data; + + /* initilize dialog data */ + ZeroMemory(&data, sizeof(data)); + data.question = question; + data.result = result; + data.result_size = result_size; + + /* create modal dialog window */ + ret = DialogBoxParam( + GetNHApp()->hApp, + MAKEINTRESOURCE(IDD_GETLIN), + GetNHApp()->hMainWnd, + GetlinDlgProc, + (LPARAM)&data + ); + if( ret==-1 ) panic("Cannot create getlin window"); + + return ret; +} + +BOOL CALLBACK GetlinDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + struct getlin_data* data; + RECT main_rt, dlg_rt; + SIZE dlg_sz; + TCHAR wbuf[BUFSZ]; + HDC WindowDC; + HWND ControlHWND; + SIZE WindowExtents; + SIZE ViewPortExtents; + RECT ControlRect; + RECT ClientRect; + LONG Division; + LONG ButtonOffset; + + switch (message) + { + case WM_INITDIALOG: + data = (struct getlin_data*)lParam; + SetWindowText(hWnd, NH_A2W(data->question, wbuf, sizeof(wbuf))); + SetWindowLong(hWnd, GWL_USERDATA, lParam); + + /* center dialog in the main window */ + GetWindowRect(hWnd, &dlg_rt); + GetWindowRect(GetNHApp()->hMainWnd, &main_rt); + WindowDC = GetWindowDC(hWnd); + + if (!GetWindowExtEx(WindowDC, &WindowExtents) || + !GetViewportExtEx(WindowDC, &ViewPortExtents) || + !GetTextExtentPoint32(GetWindowDC (hWnd), wbuf, _tcslen(wbuf), &dlg_sz)) + { + dlg_sz.cx = 0; + } + else + { + /* I think we need to do the following scaling */ + dlg_sz.cx *= ViewPortExtents.cx; dlg_sz.cx /= WindowExtents.cx; + /* Add the size of the various items in the caption bar */ + dlg_sz.cx += GetSystemMetrics(SM_CXSIZE) + + 2 * (GetSystemMetrics (SM_CXBORDER) + GetSystemMetrics(SM_CXFRAME)); + } + + if (dlg_sz.cx < dlg_rt.right - dlg_rt.left) + dlg_sz.cx = dlg_rt.right - dlg_rt.left; + dlg_sz.cy = dlg_rt.bottom - dlg_rt.top; + dlg_rt.left = (main_rt.left+main_rt.right-dlg_sz.cx)/2; + dlg_rt.right = dlg_rt.left + dlg_sz.cx; + dlg_rt.top = (main_rt.top+main_rt.bottom-dlg_sz.cy)/2; + dlg_rt.bottom = dlg_rt.top + dlg_sz.cy; + MoveWindow( hWnd, + (main_rt.left+main_rt.right-dlg_sz.cx)/2, + (main_rt.top+main_rt.bottom-dlg_sz.cy)/2, + dlg_sz.cx, + dlg_sz.cy, + TRUE ); + + /* set focus and size of the edit control */ + ControlHWND = GetDlgItem(hWnd, IDC_GETLIN_EDIT); + SetFocus(ControlHWND); + GetClientRect (hWnd, &ClientRect); + GetWindowRect (ControlHWND, &ControlRect); + MoveWindow (ControlHWND, 0, 0, + ClientRect.right - ClientRect.left, + ControlRect.bottom - ControlRect.top, TRUE); + ButtonOffset = ControlRect.bottom - ControlRect.top; + + /* Now get the OK and CANCEL buttons */ + ControlHWND = GetDlgItem(hWnd, IDOK); + GetWindowRect (ControlHWND, &ControlRect); + Division = ((ClientRect.right - ClientRect.left) - + 2 * (ControlRect.right - ControlRect.left)) / 3; + MoveWindow (ControlHWND, Division, + ButtonOffset, + ControlRect.right - ControlRect.left, + ControlRect.bottom - ControlRect.top, TRUE); + ControlHWND = GetDlgItem(hWnd, IDCANCEL); + MoveWindow (ControlHWND, + Division * 2 + ControlRect.right - ControlRect.left, + ButtonOffset, + ControlRect.right - ControlRect.left, + ControlRect.bottom - ControlRect.top, TRUE); + + /* tell windows that we've set the focus */ + return FALSE; + break; + + case WM_COMMAND: + { + TCHAR wbuf[BUFSZ]; + + switch (LOWORD(wParam)) + { + /* OK button was pressed */ + case IDOK: + data = (struct getlin_data*)GetWindowLong(hWnd, GWL_USERDATA); + SendDlgItemMessage(hWnd, IDC_GETLIN_EDIT, WM_GETTEXT, (WPARAM)sizeof(wbuf), (LPARAM)wbuf ); + NH_W2A(wbuf, data->result, data->result_size); + + /* Fall through. */ + + /* cancel button was pressed */ + case IDCANCEL: + EndDialog(hWnd, wParam); + return TRUE; + } + } break; + + } /* end switch (message) */ + return FALSE; +} + + +/*---------------------------------------------------------------*/ +/* dialog data for the list of extended commands */ +struct extcmd_data { + int* selection; +}; + +BOOL CALLBACK ExtCmdDlgProc(HWND, UINT, WPARAM, LPARAM); + +int mswin_ext_cmd_window (int* selection) +{ + int ret; + struct extcmd_data data; + + /* init dialog data */ + ZeroMemory(&data, sizeof(data)); + *selection = -1; + data.selection = selection; + + /* create modal dialog window */ + ret = DialogBoxParam( + GetNHApp()->hApp, + MAKEINTRESOURCE(IDD_EXTCMD), + GetNHApp()->hMainWnd, + ExtCmdDlgProc, + (LPARAM)&data + ); + if( ret==-1 ) panic("Cannot create extcmd window"); + return ret; +} + +BOOL CALLBACK ExtCmdDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + struct extcmd_data* data; + RECT main_rt, dlg_rt; + SIZE dlg_sz; + int i; + const char *ptr; + TCHAR wbuf[255]; + + switch (message) + { + case WM_INITDIALOG: + data = (struct extcmd_data*)lParam; + SetWindowLong(hWnd, GWL_USERDATA, lParam); + + /* center dialog in the main window */ + GetWindowRect(GetNHApp()->hMainWnd, &main_rt); + GetWindowRect(hWnd, &dlg_rt); + dlg_sz.cx = dlg_rt.right - dlg_rt.left; + dlg_sz.cy = dlg_rt.bottom - dlg_rt.top; + + dlg_rt.left = (main_rt.left+main_rt.right-dlg_sz.cx)/2; + dlg_rt.right = dlg_rt.left + dlg_sz.cx; + dlg_rt.top = (main_rt.top+main_rt.bottom-dlg_sz.cy)/2; + dlg_rt.bottom = dlg_rt.top + dlg_sz.cy; + MoveWindow( hWnd, + (main_rt.left+main_rt.right-dlg_sz.cx)/2, + (main_rt.top+main_rt.bottom-dlg_sz.cy)/2, + dlg_sz.cx, + dlg_sz.cy, + TRUE ); + + /* fill combobox with extended commands */ + for(i=0; (ptr=extcmdlist[i].ef_txt); i++) { + SendDlgItemMessage(hWnd, IDC_EXTCMD_LIST, LB_ADDSTRING, (WPARAM)0, (LPARAM)NH_A2W(ptr, wbuf, sizeof(wbuf)) ); + } + + /* set focus to the list control */ + SetFocus(GetDlgItem(hWnd, IDC_EXTCMD_LIST)); + + /* tell windows we set the focus */ + return FALSE; + break; + + case WM_COMMAND: + data = (struct extcmd_data*)GetWindowLong(hWnd, GWL_USERDATA); + switch (LOWORD(wParam)) + { + /* OK button ws clicked */ + case IDOK: + *data->selection = SendDlgItemMessage(hWnd, IDC_EXTCMD_LIST, LB_GETCURSEL, (WPARAM)0, (LPARAM)0 ); + if( *data->selection==LB_ERR ) + *data->selection = -1; + /* Fall through. */ + + /* CANCEL button ws clicked */ + case IDCANCEL: + EndDialog(hWnd, wParam); + return TRUE; + + /* list control events */ + case IDC_EXTCMD_LIST: + switch(HIWORD(wParam)) { + + case LBN_DBLCLK: + /* double click within the list + wParam + The low-order word is the list box identifier. + The high-order word is the notification message. + lParam + Handle to the list box + */ + *data->selection = SendMessage((HWND)lParam, LB_GETCURSEL, (WPARAM)0, (LPARAM)0); + if( *data->selection==LB_ERR ) + *data->selection = -1; + EndDialog(hWnd, IDOK); + return TRUE; + } + break; + } + } + return FALSE; +} + +/*---------------------------------------------------------------*/ +/* player selector dialog data */ +struct plsel_data { + int* selection; +}; + +BOOL CALLBACK PlayerSelectorDlgProc(HWND, UINT, WPARAM, LPARAM); +static void plselInitDialog(HWND hWnd); +static void plselAdjustLists(HWND hWnd, int changed_opt); +static int plselFinalSelection(HWND hWnd, int* selection); + +int mswin_player_selection_window ( int* selection ) +{ + int ret; + struct plsel_data data; + + /* init dialog data */ + ZeroMemory(&data, sizeof(data)); + data.selection = selection; + + /* create modal dialog */ + ret = DialogBoxParam( + GetNHApp()->hApp, + MAKEINTRESOURCE(IDD_PLAYER_SELECTOR), + GetNHApp()->hMainWnd, + PlayerSelectorDlgProc, + (LPARAM)&data + ); + if( ret==-1 ) panic("Cannot create getlin window"); + + return ret; +} + +BOOL CALLBACK PlayerSelectorDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + struct plsel_data* data; + RECT main_rt, dlg_rt; + SIZE dlg_sz; + + switch (message) + { + case WM_INITDIALOG: + data = (struct plsel_data*)lParam; + SetWindowLong(hWnd, GWL_USERDATA, lParam); + + /* center dialog in the main window */ + GetWindowRect(GetNHApp()->hMainWnd, &main_rt); + GetWindowRect(hWnd, &dlg_rt); + dlg_sz.cx = dlg_rt.right - dlg_rt.left; + dlg_sz.cy = dlg_rt.bottom - dlg_rt.top; + + dlg_rt.left = (main_rt.left+main_rt.right-dlg_sz.cx)/2; + dlg_rt.right = dlg_rt.left + dlg_sz.cx; + dlg_rt.top = (main_rt.top+main_rt.bottom-dlg_sz.cy)/2; + dlg_rt.bottom = dlg_rt.top + dlg_sz.cy; + MoveWindow( hWnd, + (main_rt.left+main_rt.right-dlg_sz.cx)/2, + (main_rt.top+main_rt.bottom-dlg_sz.cy)/2, + dlg_sz.cx, + dlg_sz.cy, + TRUE ); + + /* init dialog */ + plselInitDialog(hWnd); + + /* set focus on the role checkbox (random) field */ + SetFocus(GetDlgItem(hWnd, IDC_PLSEL_ROLE_RANDOM)); + + /* tell windows we set the focus */ + return FALSE; + break; + + case WM_COMMAND: + data = (struct plsel_data*)GetWindowLong(hWnd, GWL_USERDATA); + switch (LOWORD(wParam)) { + + /* OK button was clicked */ + case IDOK: + if( plselFinalSelection(hWnd, data->selection) ) { + EndDialog(hWnd, wParam); + } else { + MessageBox(hWnd, TEXT("Cannot match this role. Try something else."), TEXT("STOP"), MB_OK ); + } + return TRUE; + + /* CANCEL button was clicked */ + case IDCANCEL: + *data->selection = -1; + EndDialog(hWnd, wParam); + return TRUE; + + /* following are events from dialog controls: + "random" checkboxes send BN_CLICKED messages; + role/race/... combo-boxes send CBN_SELENDOK + if something was selected; + */ + case IDC_PLSEL_ROLE_RANDOM: + if( HIWORD(wParam)==BN_CLICKED ) { + /* enable corresponding list window if "random" + checkbox was "unchecked" */ + EnableWindow( + GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST), + SendMessage((HWND)lParam, BM_GETCHECK, 0, 0)==BST_UNCHECKED + ); + } + break; + + case IDC_PLSEL_RACE_RANDOM: + if( HIWORD(wParam)==BN_CLICKED ) { + EnableWindow( + GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST), + SendMessage((HWND)lParam, BM_GETCHECK, 0, 0)==BST_UNCHECKED + ); + } + break; + + case IDC_PLSEL_GENDER_RANDOM: + if( HIWORD(wParam)==BN_CLICKED ) { + EnableWindow( + GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST), + SendMessage((HWND)lParam, BM_GETCHECK, 0, 0)==BST_UNCHECKED + ); + } + break; + + case IDC_PLSEL_ALIGN_RANDOM: + if( HIWORD(wParam)==BN_CLICKED ) { + EnableWindow( + GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST), + SendMessage((HWND)lParam, BM_GETCHECK, 0, 0)==BST_UNCHECKED + ); + } + break; + + case IDC_PLSEL_ROLE_LIST: + if( HIWORD(wParam)==CBN_SELENDOK ) { + /* filter out invalid options if + the selection was made */ + plselAdjustLists( hWnd, LOWORD(wParam) ); + } + break; + + case IDC_PLSEL_RACE_LIST: + if( HIWORD(wParam)==CBN_SELENDOK ) { + plselAdjustLists( hWnd, LOWORD(wParam) ); + } + break; + + case IDC_PLSEL_GENDER_LIST: + if( HIWORD(wParam)==CBN_SELENDOK ) { + plselAdjustLists( hWnd, LOWORD(wParam) ); + } + break; + + case IDC_PLSEL_ALIGN_LIST: + if( HIWORD(wParam)==CBN_SELENDOK ) { + plselAdjustLists( hWnd, LOWORD(wParam) ); + } + break; + } + break; + } + return FALSE; +} + +/* initialize player selector dialog */ +void plselInitDialog(HWND hWnd) +{ + TCHAR wbuf[BUFSZ]; + + /* set player name */ + SetDlgItemText(hWnd, IDC_PLSEL_NAME, NH_A2W(plname, wbuf, sizeof(wbuf))); + + plselAdjustLists(hWnd, -1); + + /* intialize roles list */ + if( flags.initrole<0 || !ok_role(flags.initrole, ROLE_NONE, ROLE_NONE, ROLE_NONE)) { + CheckDlgButton(hWnd, IDC_PLSEL_ROLE_RANDOM, BST_CHECKED); + EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST), FALSE); + } else { + CheckDlgButton(hWnd, IDC_PLSEL_ROLE_RANDOM, BST_UNCHECKED); + EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST), TRUE); + SendDlgItemMessage(hWnd, IDC_PLSEL_ROLE_LIST, CB_SETCURSEL, (WPARAM)flags.initrole, 0); + } + + /* intialize races list */ + if( flags.initrace<0 || !ok_race(flags.initrole, flags.initrace, ROLE_NONE, ROLE_NONE) ) { + CheckDlgButton(hWnd, IDC_PLSEL_RACE_RANDOM, BST_CHECKED); + EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST), FALSE); + } else { + CheckDlgButton(hWnd, IDC_PLSEL_RACE_RANDOM, BST_UNCHECKED); + EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST), TRUE); + SendDlgItemMessage(hWnd, IDC_PLSEL_RACE_LIST, CB_SETCURSEL, (WPARAM)flags.initrace, 0); + } + + /* intialize genders list */ + if( flags.initgend<0 || !ok_gend(flags.initrole, flags.initrace, flags.initgend, ROLE_NONE)) { + CheckDlgButton(hWnd, IDC_PLSEL_GENDER_RANDOM, BST_CHECKED); + EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST), FALSE); + } else { + CheckDlgButton(hWnd, IDC_PLSEL_GENDER_RANDOM, BST_UNCHECKED); + EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST), TRUE); + SendDlgItemMessage(hWnd, IDC_PLSEL_GENDER_LIST, CB_SETCURSEL, (WPARAM)flags.initgend, 0); + } + + /* intialize alignments list */ + if( flags.initalign<0 || !ok_align(flags.initrole, flags.initrace, flags.initgend, flags.initalign) ) { + CheckDlgButton(hWnd, IDC_PLSEL_ALIGN_RANDOM, BST_CHECKED); + EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST), FALSE); + } else { + CheckDlgButton(hWnd, IDC_PLSEL_ALIGN_RANDOM, BST_UNCHECKED); + EnableWindow(GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST), TRUE); + SendDlgItemMessage(hWnd, IDC_PLSEL_ALIGN_LIST, CB_SETCURSEL, (WPARAM)flags.initalign, 0); + } +} + +/* adjust role/race/alignment/gender list - filter out + invalid combinations + changed_sel points to the list where selection occured + (-1 if unknown) +*/ +void plselAdjustLists(HWND hWnd, int changed_sel) +{ + HWND control_role, control_race, control_gender, control_align; + int initrole, initrace, initgend, initalign; + int i; + int ind; + int valid_opt; + TCHAR wbuf[255]; + + /* get control handles */ + control_role = GetDlgItem(hWnd, IDC_PLSEL_ROLE_LIST); + control_race = GetDlgItem(hWnd, IDC_PLSEL_RACE_LIST); + control_gender = GetDlgItem(hWnd, IDC_PLSEL_GENDER_LIST); + control_align = GetDlgItem(hWnd, IDC_PLSEL_ALIGN_LIST); + + /* get current selections */ + ind = SendMessage(control_role, CB_GETCURSEL, 0, 0); + initrole = (ind==LB_ERR)? ROLE_NONE : SendMessage(control_role, CB_GETITEMDATA, ind, 0); + + ind = SendMessage(control_race, CB_GETCURSEL, 0, 0); + initrace = (ind==LB_ERR)? ROLE_NONE : SendMessage(control_race, CB_GETITEMDATA, ind, 0); + + ind = SendMessage(control_gender, CB_GETCURSEL, 0, 0); + initgend = (ind==LB_ERR)? ROLE_NONE : SendMessage(control_gender, CB_GETITEMDATA, ind, 0); + + ind = SendMessage(control_align, CB_GETCURSEL, 0, 0); + initalign = (ind==LB_ERR)? ROLE_NONE : SendMessage(control_align, CB_GETITEMDATA, ind, 0); + + /* intialize roles list */ + if( changed_sel==-1 ) { + valid_opt = 0; + + /* reset content and populate the list */ + SendMessage(control_role, CB_RESETCONTENT, 0, 0); + for (i = 0; roles[i].name.m; i++) { + if (ok_role(i, initrace, initgend, initalign)) { + if (initgend>=0 && flags.female && roles[i].name.f) + ind = SendMessage(control_role, CB_ADDSTRING, (WPARAM)0, (LPARAM)NH_A2W(roles[i].name.f, wbuf, sizeof(wbuf)) ); + else + ind = SendMessage(control_role, CB_ADDSTRING, (WPARAM)0, (LPARAM)NH_A2W(roles[i].name.m, wbuf, sizeof(wbuf)) ); + + SendMessage(control_role, CB_SETITEMDATA, (WPARAM)ind, (LPARAM)i ); + if( i==initrole ) { + SendMessage(control_role, CB_SETCURSEL, (WPARAM)ind, (LPARAM)0 ); + valid_opt = 1; + } + } + } + + /* set selection to the previously selected role + if it is still valid */ + if( !valid_opt ) { + initrole = ROLE_NONE; + initrace = ROLE_NONE; + initgend = ROLE_NONE; + initalign = ROLE_NONE; + SendMessage(control_role, CB_SETCURSEL, (WPARAM)-1, (LPARAM)0 ); + } + + /* trigger change of the races list */ + changed_sel=IDC_PLSEL_ROLE_LIST; + } + + /* intialize races list */ + if( changed_sel==IDC_PLSEL_ROLE_LIST ) { + valid_opt = 0; + + /* reset content and populate the list */ + SendMessage(control_race, CB_RESETCONTENT, 0, 0); + for (i = 0; races[i].noun; i++) + if (ok_race(initrole, i, ROLE_NONE, ROLE_NONE)) { + ind = SendMessage(control_race, CB_ADDSTRING, (WPARAM)0, (LPARAM)NH_A2W(races[i].noun, wbuf, sizeof(wbuf)) ); + SendMessage(control_race, CB_SETITEMDATA, (WPARAM)ind, (LPARAM)i ); + if( i==initrace ) { + SendMessage(control_race, CB_SETCURSEL, (WPARAM)ind, (LPARAM)0 ); + valid_opt = 1; + } + } + + /* set selection to the previously selected race + if it is still valid */ + if( !valid_opt ) { + initrace = ROLE_NONE; + initgend = ROLE_NONE; + initalign = ROLE_NONE; + SendMessage(control_race, CB_SETCURSEL, (WPARAM)-1, (LPARAM)0 ); + } + + /* trigger change of the genders list */ + changed_sel=IDC_PLSEL_RACE_LIST; + } + + /* intialize genders list */ + if( changed_sel==IDC_PLSEL_RACE_LIST ) { + valid_opt = 0; + + /* reset content and populate the list */ + SendMessage(control_gender, CB_RESETCONTENT, 0, 0); + for (i = 0; i < ROLE_GENDERS; i++) + if (ok_gend(initrole, initrace, i, ROLE_NONE)) { + ind = SendMessage(control_gender, CB_ADDSTRING, (WPARAM)0, (LPARAM)NH_A2W(genders[i].adj, wbuf, sizeof(wbuf)) ); + SendMessage(control_gender, CB_SETITEMDATA, (WPARAM)ind, (LPARAM)i ); + if( i==initgend ) { + SendMessage(control_gender, CB_SETCURSEL, (WPARAM)ind, (LPARAM)0 ); + } + } + + /* set selection to the previously selected gender + if it is still valid */ + if( !valid_opt ) { + initgend = ROLE_NONE; + initalign = ROLE_NONE; + SendMessage(control_gender, CB_SETCURSEL, (WPARAM)-1, (LPARAM)0 ); + } + + /* trigger change of the alignments list */ + changed_sel=IDC_PLSEL_GENDER_LIST; + } + + /* intialize alignments list */ + if( changed_sel==IDC_PLSEL_GENDER_LIST ) { + valid_opt = 0; + + /* reset content and populate the list */ + SendMessage(control_align, CB_RESETCONTENT, 0, 0); + for (i = 0; i < ROLE_ALIGNS; i++) + if (ok_align(initrole, initrace, initgend, i)) { + ind = SendMessage(control_align, CB_ADDSTRING, (WPARAM)0, (LPARAM)NH_A2W(aligns[i].adj, wbuf, sizeof(wbuf)) ); + SendMessage(control_align, CB_SETITEMDATA, (WPARAM)ind, (LPARAM)i ); + if( i==initalign ) { + SendMessage(control_align, CB_SETCURSEL, (WPARAM)ind, (LPARAM)0 ); + valid_opt = 1; + } + } + + /* set selection to the previously selected alignment + if it is still valid */ + if( !valid_opt ) { + initalign = ROLE_NONE; + SendMessage(control_align, CB_SETCURSEL, (WPARAM)-1, (LPARAM)0 ); + } + } +} + +/* player made up his mind - get final selection here */ +int plselFinalSelection(HWND hWnd, int* selection) +{ + int ind; + + /* get current selections */ + if( SendDlgItemMessage(hWnd, IDC_PLSEL_ROLE_RANDOM, BM_GETCHECK, 0, 0)==BST_CHECKED ) { + flags.initrole = ROLE_RANDOM; + } else { + ind = SendDlgItemMessage(hWnd, IDC_PLSEL_ROLE_LIST, CB_GETCURSEL, 0, 0); + flags.initrole = (ind==LB_ERR)? ROLE_RANDOM : SendDlgItemMessage(hWnd, IDC_PLSEL_ROLE_LIST, CB_GETITEMDATA, ind, 0); + } + + if( SendDlgItemMessage(hWnd, IDC_PLSEL_RACE_RANDOM, BM_GETCHECK, 0, 0)==BST_CHECKED ) { + flags.initrace = ROLE_RANDOM; + } else { + ind = SendDlgItemMessage(hWnd, IDC_PLSEL_RACE_LIST, CB_GETCURSEL, 0, 0); + flags.initrace = (ind==LB_ERR)? ROLE_RANDOM : SendDlgItemMessage(hWnd, IDC_PLSEL_RACE_LIST, CB_GETITEMDATA, ind, 0); + } + + if( SendDlgItemMessage(hWnd, IDC_PLSEL_GENDER_RANDOM, BM_GETCHECK, 0, 0)==BST_CHECKED ) { + flags.initgend = ROLE_RANDOM; + } else { + ind = SendDlgItemMessage(hWnd, IDC_PLSEL_GENDER_LIST, CB_GETCURSEL, 0, 0); + flags.initgend = (ind==LB_ERR)? ROLE_RANDOM : SendDlgItemMessage(hWnd, IDC_PLSEL_GENDER_LIST, CB_GETITEMDATA, ind, 0); + } + + if( SendDlgItemMessage(hWnd, IDC_PLSEL_ALIGN_RANDOM, BM_GETCHECK, 0, 0)==BST_CHECKED ) { + flags.initalign = ROLE_RANDOM; + } else { + ind = SendDlgItemMessage(hWnd, IDC_PLSEL_ALIGN_LIST, CB_GETCURSEL, 0, 0); + flags.initalign = (ind==LB_ERR)? ROLE_RANDOM : SendDlgItemMessage(hWnd, IDC_PLSEL_ALIGN_LIST, CB_GETITEMDATA, ind, 0); + } + + + /* check the role */ + if( flags.initrole==ROLE_RANDOM ) { + flags.initrole = pick_role(flags.initrace, flags.initgend, flags.initalign, PICK_RANDOM); + if (flags.initrole < 0) { + MessageBox(hWnd, TEXT("Incompatible role!"), TEXT("STOP"), MB_OK); + return FALSE; + } + } + + /* Select a race, if necessary */ + /* force compatibility with role */ + if (flags.initrace==ROLE_RANDOM || !validrace(flags.initrole, flags.initrace)) { + /* pre-selected race not valid */ + if (flags.initrace == ROLE_RANDOM) { + flags.initrace = pick_race(flags.initrole, flags.initgend, flags.initalign, PICK_RANDOM); + } + + if (flags.initrace < 0) { + MessageBox(hWnd, TEXT("Incompatible race!"), TEXT("STOP"), MB_OK); + return FALSE; + } + } + + /* Select a gender, if necessary */ + /* force compatibility with role/race, try for compatibility with + * pre-selected alignment */ + if (flags.initgend < 0 || + !validgend(flags.initrole, flags.initrace, flags.initgend)) { + /* pre-selected gender not valid */ + if (flags.initgend == ROLE_RANDOM) { + flags.initgend = pick_gend(flags.initrole, flags.initrace, flags.initalign, PICK_RANDOM); + } + + if (flags.initgend < 0) { + MessageBox(hWnd, TEXT("Incompatible gender!"), TEXT("STOP"), MB_OK); + return FALSE; + } + } + + /* Select an alignment, if necessary */ + /* force compatibility with role/race/gender */ + if (flags.initalign < 0 || + !validalign(flags.initrole, flags.initrace, flags.initalign)) { + /* pre-selected alignment not valid */ + if (flags.initalign == ROLE_RANDOM) { + flags.initalign = pick_align(flags.initrole, flags.initrace, flags.initgend, PICK_RANDOM); + } else { + MessageBox(hWnd, TEXT("Incompatible alignment!"), TEXT("STOP"), MB_OK); + return FALSE; + } + } + + return TRUE; +} \ No newline at end of file diff --git a/win/win32/mhdlg.h b/win/win32/mhdlg.h new file mode 100644 index 0000000..b964838 --- /dev/null +++ b/win/win32/mhdlg.h @@ -0,0 +1,15 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef MSWINDlgWindow_h +#define MSWINDlgWindow_h + +#include "winMS.h" +#include "config.h" +#include "global.h" + +int mswin_getlin_window (const char *question, char *result, size_t result_size); +int mswin_ext_cmd_window (int* selection); +int mswin_player_selection_window(int* selection); + +#endif /* MSWINDlgWindow_h */ diff --git a/win/win32/mhfont.c b/win/win32/mhfont.c new file mode 100644 index 0000000..003c562 --- /dev/null +++ b/win/win32/mhfont.c @@ -0,0 +1,194 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +/* font management and such */ + +#include "mhfont.h" + +#define MAXFONTS 64 + +/* font table - 64 fonts ought to be enough */ +static struct font_table_entry { + int code; + HFONT hFont; +} font_table[MAXFONTS] ; +static int font_table_size = 0; +HFONT version_splash_font; +HFONT extrainfo_splash_font; + +#define NHFONT_CODE(win, attr) (((attr&0xFF)<<8)|(win_type&0xFF)) + +static void __cdecl font_table_cleanup(void); + +void mswin_init_splashfonts(HWND hWnd) +{ + HDC hdc = GetDC(hWnd); + HFONT fnt = NULL; + LOGFONT lgfnt; + ZeroMemory( &lgfnt, sizeof(lgfnt) ); + lgfnt.lfHeight = -80; // height of font + lgfnt.lfWidth = 0; // average character width + lgfnt.lfEscapement = 0; // angle of escapement + lgfnt.lfOrientation = 0; // base-line orientation angle + lgfnt.lfWeight = FW_BOLD; // font weight + lgfnt.lfItalic = FALSE; // italic attribute option + lgfnt.lfUnderline = FALSE; // underline attribute option + lgfnt.lfStrikeOut = FALSE; // strikeout attribute option + lgfnt.lfCharSet = OEM_CHARSET; // character set identifier + lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS; // output precision + lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision + lgfnt.lfQuality = DEFAULT_QUALITY; // output quality + lgfnt.lfPitchAndFamily = DEFAULT_PITCH; // pitch and family + NH_A2W( "Times New Roman", lgfnt.lfFaceName, LF_FACESIZE); + version_splash_font = CreateFontIndirect(&lgfnt); + lgfnt.lfHeight = -16; // height of font + extrainfo_splash_font = CreateFontIndirect(&lgfnt); + ReleaseDC(hWnd, hdc); +} + +void mswin_destroy_splashfonts() +{ + DeleteObject (version_splash_font); + DeleteObject (extrainfo_splash_font); +} + +/* create font based on window type, charater attributes and + window device context */ +HGDIOBJ mswin_get_font(int win_type, int attr, HDC hdc, BOOL replace) +{ + HFONT fnt = NULL; + LOGFONT lgfnt; + int font_size; + int font_index; + static BOOL once = FALSE; + + if( !once ) { + once = TRUE; + atexit(font_table_cleanup); + } + + ZeroMemory( &lgfnt, sizeof(lgfnt) ); + + /* try find font in the table */ + for(font_index=0; font_index=MAXFONTS ) panic( "font table overflow!" ); + font_table_size++; + } else { + DeleteObject(font_table[font_index].hFont); + } + + font_table[font_index].code = NHFONT_CODE(win_type, attr); + font_table[font_index].hFont = fnt; + return fnt; +} + +void __cdecl font_table_cleanup(void) +{ + int i; + for(i=0; i */ +/* NetHack may be freely redistributed. See license for details. */ + +/* font management functions */ + +#ifndef MSWINFont_h +#define MSWINFont_h + +#include "winMS.h" + +HGDIOBJ mswin_get_font(int win_type, int attr, HDC hdc, BOOL replace); +void mswin_init_splashfonts(HWND hWnd); +void mswin_destroy_splashfonts(void); + +#endif /* MSWINFont_h */ diff --git a/win/win32/mhinput.c b/win/win32/mhinput.c new file mode 100644 index 0000000..7b6594d --- /dev/null +++ b/win/win32/mhinput.c @@ -0,0 +1,85 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#include +#include "winMS.h" +#include "mhinput.h" + +/* nethack input queue functions */ + +#define NH_INPUT_BUFFER_SIZE 64 + +/* as it stands right now we need only one slot + since events are processed almost the same time as + they occur but I like large round numbers */ + +static MSNHEvent nhi_input_buffer[NH_INPUT_BUFFER_SIZE]; +static int nhi_init_input = 0; +static int nhi_read_pos = 0; +static int nhi_write_pos = 0; + +/* initialize input queue */ +void mswin_nh_input_init(void) +{ + if( !nhi_init_input ) { + nhi_init_input = 1; + + ZeroMemory( nhi_input_buffer, sizeof(nhi_input_buffer) ); + nhi_read_pos = 0; + nhi_write_pos = 0; + } +} + +/* check for input */ +int mswin_have_input() +{ + return (nhi_read_pos!=nhi_write_pos); +} + +/* add event to the queue */ +void mswin_input_push(PMSNHEvent event) +{ + int new_write_pos; + + if( !nhi_init_input ) mswin_nh_input_init(); + + new_write_pos = (nhi_write_pos+1) % NH_INPUT_BUFFER_SIZE; + + if(new_write_pos!=nhi_read_pos) { + memcpy(nhi_input_buffer+nhi_write_pos, event, sizeof(*event)); + nhi_write_pos = new_write_pos; + } + +} + +/* get event from the queue and delete it */ +PMSNHEvent mswin_input_pop() +{ + PMSNHEvent retval; + + if( !nhi_init_input ) mswin_nh_input_init(); + + if( nhi_read_pos!=nhi_write_pos ) { + retval = &nhi_input_buffer[nhi_read_pos]; + nhi_read_pos = (nhi_read_pos+1) % NH_INPUT_BUFFER_SIZE; + } else { + retval = NULL; + } + + return retval; +} + +/* get event from the queue but leave it there */ +PMSNHEvent mswin_input_peek() +{ + PMSNHEvent retval; + + if( !nhi_init_input ) mswin_nh_input_init(); + + if( nhi_read_pos!=nhi_write_pos ) { + retval = &nhi_input_buffer[nhi_read_pos]; + } else { + retval = NULL; + } + return retval; +} \ No newline at end of file diff --git a/win/win32/mhinput.h b/win/win32/mhinput.h new file mode 100644 index 0000000..23ed41b --- /dev/null +++ b/win/win32/mhinput.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef MSWINInput_h +#define MSWINInput_h + +/* nethack input queue - store/extract input events */ +#include "winMS.h" + +#define NHEVENT_CHAR 1 +#define NHEVENT_MOUSE 2 +typedef struct mswin_event { + int type; + union { + struct { + int ch; + } kbd; + + struct { + int mod; + int x, y; + } ms; + }; +} MSNHEvent, *PMSNHEvent; + +#define NHEVENT_KBD(c) { MSNHEvent e; e.type=NHEVENT_CHAR; e.kbd.ch=(c); mswin_input_push(&e); } +#define NHEVENT_MS(_mod, _x, _y) { MSNHEvent e; e.type=NHEVENT_MOUSE; e.ms.mod = (_mod); e.ms.x=(_x); e.ms.y=(_y); mswin_input_push(&e); } + +void mswin_nh_input_init(void); +int mswin_have_input(void); +void mswin_input_push(PMSNHEvent event); +PMSNHEvent mswin_input_pop(void); +PMSNHEvent mswin_input_peek(void); + +#endif /* MSWINInput_h */ diff --git a/win/win32/mhmain.c b/win/win32/mhmain.c new file mode 100644 index 0000000..6b4a39b --- /dev/null +++ b/win/win32/mhmain.c @@ -0,0 +1,915 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "winMS.h" +#include "patchlevel.h" +#include "resource.h" +#include "mhmsg.h" +#include "mhinput.h" +#include "mhmain.h" +#include "mhmenu.h" +#include "mhstatus.h" +#include "mhmsgwnd.h" +#include "mhmap.h" + +typedef struct mswin_nethack_main_window { + int mapAcsiiModeSave; +} NHMainWindow, *PNHMainWindow; + +static TCHAR szMainWindowClass[] = TEXT("MSNHMainWndClass"); +static TCHAR szTitle[MAX_LOADSTRING]; + +LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); +static LRESULT onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam); +static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam); +static void register_main_window_class(void); +static int menuid2mapmode(int menuid); +static int mapmode2menuid(int map_mode); + +HWND mswin_init_main_window () { + static int run_once = 0; + HWND ret; + + /* register window class */ + if( !run_once ) { + LoadString(GetNHApp()->hApp, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); + register_main_window_class( ); + run_once = 1; + } + + /* create the main window */ + ret = CreateWindow( + szMainWindowClass, /* registered class name */ + szTitle, /* window name */ + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, /* window style */ + CW_USEDEFAULT, /* horizontal position of window */ + CW_USEDEFAULT, /* vertical position of window */ + CW_USEDEFAULT, /* window width */ + CW_USEDEFAULT, /* window height */ + NULL, /* handle to parent or owner window */ + NULL, /* menu handle or child identifier */ + GetNHApp()->hApp, /* handle to application instance */ + NULL /* window-creation data */ + ); + + if( !ret ) panic("Cannot create main window"); + + return ret; +} + +void register_main_window_class() +{ + WNDCLASS wcex; + + ZeroMemory(&wcex, sizeof(wcex)); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = (WNDPROC)MainWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = GetNHApp()->hApp; + wcex.hIcon = LoadIcon(GetNHApp()->hApp, (LPCTSTR)IDI_NETHACKW); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); + wcex.lpszMenuName = (TCHAR*)IDC_NETHACKW; + wcex.lpszClassName = szMainWindowClass; + + RegisterClass(&wcex); +} + +/* + * Keypad keys are translated to the normal values below. + * Shifted keypad keys are translated to the + * shift values below. + */ + +enum KEY_INDEXES { +KEY_NW, KEY_N, KEY_NE, KEY_MINUS, +KEY_W, KEY_GOINTERESTING, KEY_E, KEY_PLUS, +KEY_SW, KEY_S, KEY_SE, +KEY_INV, KEY_WAITLOOK, +KEY_LAST}; + +static const unsigned char +/* normal, shift, control */ +keypad[KEY_LAST][3] = { + {'y', 'Y', C('y')}, /* 7 */ + {'k', 'K', C('k')}, /* 8 */ + {'u', 'U', C('u')}, /* 9 */ + {'m', C('p'), C('p')}, /* - */ + {'h', 'H', C('h')}, /* 4 */ + {'g', 'G', 'g'}, /* 5 */ + {'l', 'L', C('l')}, /* 6 */ + {'+', 'P', C('p')}, /* + */ + {'b', 'B', C('b')}, /* 1 */ + {'j', 'J', C('j')}, /* 2 */ + {'n', 'N', C('n')}, /* 3 */ + {'i', 'I', C('i')}, /* Ins */ + {'.', ':', ':'} /* Del */ +}, +numpad[KEY_LAST][3] = { + {'7', M('7'), '7'}, /* 7 */ + {'8', M('8'), '8'}, /* 8 */ + {'9', M('9'), '9'}, /* 9 */ + {'m', C('p'), C('p')}, /* - */ + {'4', M('4'), '4'}, /* 4 */ + {'g', 'G', 'g'}, /* 5 */ + {'6', M('6'), '6'}, /* 6 */ + {'+', 'P', C('p')}, /* + */ + {'1', M('1'), '1'}, /* 1 */ + {'2', M('2'), '2'}, /* 2 */ + {'3', M('3'), '3'}, /* 3 */ + {'i', 'I', C('i')}, /* Ins */ + {'.', ':', ':'} /* Del */ +}; + +#define STATEON(x) ((GetKeyState(x) & 0xFFFE) != 0) +#define KEYTABLE_REGULAR(x) ((iflags.num_pad ? numpad : keypad)[x][0]) +#define KEYTABLE_SHIFT(x) ((iflags.num_pad ? numpad : keypad)[x][1]) +#define KEYTABLE(x) (STATEON(VK_SHIFT) ? KEYTABLE_SHIFT(x) : KEYTABLE_REGULAR(x)) + +/* map mode macros */ +#define IS_MAP_FIT_TO_SCREEN(mode) ((mode)==MAP_MODE_ASCII_FIT_TO_SCREEN || \ + (mode)==MAP_MODE_TILES_FIT_TO_SCREEN ) + +#define IS_MAP_ASCII(mode) ((mode)!=MAP_MODE_TILES && (mode)!=MAP_MODE_TILES_FIT_TO_SCREEN) + +static const char *extendedlist = "acdefijlmnopqrstuvw?2"; + +#define SCANLO 0x02 +static const char scanmap[] = { /* ... */ + '1','2','3','4','5','6','7','8','9','0',0,0,0,0, + 'q','w','e','r','t','y','u','i','o','p','[',']', '\n', + 0, 'a','s','d','f','g','h','j','k','l',';','\'', '`', + 0, '\\', 'z','x','c','v','b','n','m',',','.','?' /* ... */ +}; + +/* +// FUNCTION: WndProc(HWND, unsigned, WORD, LONG) +// +// PURPOSE: Processes messages for the main window. +*/ +LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + PNHMainWindow data; + + switch (message) + { + case WM_CREATE: + /* set window data */ + data = (PNHMainWindow)malloc(sizeof(NHMainWindow)); + if( !data ) panic("out of memory"); + ZeroMemory(data, sizeof(NHMainWindow)); + data->mapAcsiiModeSave = MAP_MODE_ASCII12x16; + SetWindowLong(hWnd, GWL_USERDATA, (LONG)data); + + GetNHApp()->hMainWnd = hWnd; + break; + + case WM_MSNH_COMMAND: + onMSNHCommand(hWnd, wParam, lParam); + break; + + case WM_KEYDOWN: + { + data = (PNHMainWindow)GetWindowLong(hWnd, GWL_USERDATA); + + /* translate arrow keys into nethack commands */ + switch (wParam) + { + case VK_LEFT: + if( STATEON(VK_CONTROL) ) { + /* scroll map window one line left */ + SendMessage( + mswin_hwnd_from_winid(WIN_MAP), + WM_HSCROLL, + MAKEWPARAM(SB_LINEUP, 0), + (LPARAM)NULL + ); + } else { + NHEVENT_KBD(KEYTABLE(KEY_W)); + } + return 0; + + case VK_RIGHT: + if( STATEON(VK_CONTROL) ) { + /* scroll map window one line right */ + SendMessage( + mswin_hwnd_from_winid(WIN_MAP), + WM_HSCROLL, + MAKEWPARAM(SB_LINEDOWN, 0), + (LPARAM)NULL + ); + } else { + NHEVENT_KBD(KEYTABLE(KEY_E)); + } + return 0; + + case VK_UP: + if( STATEON(VK_CONTROL) ) { + /* scroll map window one line up */ + SendMessage( + mswin_hwnd_from_winid(WIN_MAP), + WM_VSCROLL, + MAKEWPARAM(SB_LINEUP, 0), + (LPARAM)NULL + ); + } else { + NHEVENT_KBD(KEYTABLE(KEY_N)); + } + return 0; + + case VK_DOWN: + if( STATEON(VK_CONTROL) ) { + /* scroll map window one line down */ + SendMessage( + mswin_hwnd_from_winid(WIN_MAP), + WM_VSCROLL, + MAKEWPARAM(SB_LINEDOWN, 0), + (LPARAM)NULL + ); + } else { + NHEVENT_KBD(KEYTABLE(KEY_S)); + } + return 0; + + case VK_HOME: + if( STATEON(VK_CONTROL) ) { + /* scroll map window to upper left corner */ + SendMessage( + mswin_hwnd_from_winid(WIN_MAP), + WM_VSCROLL, + MAKEWPARAM(SB_THUMBTRACK, 0), + (LPARAM)NULL + ); + + SendMessage( + mswin_hwnd_from_winid(WIN_MAP), + WM_HSCROLL, + MAKEWPARAM(SB_THUMBTRACK, 0), + (LPARAM)NULL + ); + } else { + NHEVENT_KBD(KEYTABLE(KEY_NW)); + } + return 0; + + case VK_END: + if( STATEON(VK_CONTROL) ) { + /* scroll map window to lower right corner */ + SendMessage( + mswin_hwnd_from_winid(WIN_MAP), + WM_VSCROLL, + MAKEWPARAM(SB_THUMBTRACK, ROWNO), + (LPARAM)NULL + ); + + SendMessage( + mswin_hwnd_from_winid(WIN_MAP), + WM_HSCROLL, + MAKEWPARAM(SB_THUMBTRACK, COLNO), + (LPARAM)NULL + ); + } else { + NHEVENT_KBD(KEYTABLE(KEY_SW)); + } + return 0; + + case VK_PRIOR: + if( STATEON(VK_CONTROL) ) { + /* scroll map window one page up */ + SendMessage( + mswin_hwnd_from_winid(WIN_MAP), + WM_VSCROLL, + MAKEWPARAM(SB_PAGEUP, 0), + (LPARAM)NULL + ); + } else { + NHEVENT_KBD(KEYTABLE(KEY_NE)); + } + return 0; + + case VK_NEXT: + if( STATEON(VK_CONTROL) ) { + /* scroll map window one page down */ + SendMessage( + mswin_hwnd_from_winid(WIN_MAP), + WM_VSCROLL, + MAKEWPARAM(SB_PAGEDOWN, 0), + (LPARAM)NULL + ); + } else { + NHEVENT_KBD(KEYTABLE(KEY_SE)); + } + return 0; + + case VK_DECIMAL: + case VK_DELETE: + NHEVENT_KBD(KEYTABLE(KEY_WAITLOOK)); + return 0; + + case VK_INSERT: + NHEVENT_KBD(KEYTABLE(KEY_INV)); + return 0; + + case VK_SUBTRACT: + NHEVENT_KBD(KEYTABLE(KEY_MINUS)); + return 0; + + case VK_ADD: + NHEVENT_KBD(KEYTABLE(KEY_PLUS)); + return 0; + + case VK_CLEAR: /* This is the '5' key */ + NHEVENT_KBD(KEYTABLE(KEY_GOINTERESTING)); + return 0; + + case VK_F4: + if( IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode) ) { + mswin_select_map_mode( + IS_MAP_ASCII(iflags.wc_map_mode)? + data->mapAcsiiModeSave : + MAP_MODE_TILES + ); + } else { + mswin_select_map_mode( + IS_MAP_ASCII(iflags.wc_map_mode)? + MAP_MODE_ASCII_FIT_TO_SCREEN : + MAP_MODE_TILES_FIT_TO_SCREEN + ); + } + return 0; + + case VK_F5: + if( IS_MAP_ASCII(iflags.wc_map_mode) ) { + if( IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode) ) { + mswin_select_map_mode(MAP_MODE_TILES_FIT_TO_SCREEN); + } else { + mswin_select_map_mode(MAP_MODE_TILES); + } + } else { + if( IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode) ) { + mswin_select_map_mode(MAP_MODE_ASCII_FIT_TO_SCREEN); + } else { + mswin_select_map_mode(data->mapAcsiiModeSave); + } + } + return 0; + + default: { + WORD c; + BYTE kbd_state[256]; + + c = 0; + ZeroMemory(kbd_state, sizeof(kbd_state)); + GetKeyboardState(kbd_state); + + if( ToAscii( wParam, (lParam>>16)&0xFF, kbd_state, &c, 0) ) { + NHEVENT_KBD( c&0xFF ); + return 0; + } else { + return 1; + } + } + + } /* end switch */ + } break; + + case WM_SYSCHAR: /* Alt-char pressed */ + { + /* + If not nethackmode, don't handle Alt-keys here. + If no Alt-key pressed it can never be an extended command + */ + if (GetNHApp()->regNetHackMode && ((lParam & 1<<29) != 0)) + { + unsigned char c = (unsigned char)(wParam & 0xFF); + unsigned char scancode = (lParam >> 16) & 0xFF; + if (index(extendedlist, tolower(c)) != 0) + { + NHEVENT_KBD(M(tolower(c))); + } else if (scancode == (SCANLO + SIZE(scanmap)) - 1) { + NHEVENT_KBD(M('?')); + } + return 0; + } + return DefWindowProc(hWnd, message, wParam, lParam); + } + break; + + case WM_COMMAND: + /* process commands - menu commands mostly */ + if( onWMCommand(hWnd, wParam, lParam) ) + return DefWindowProc(hWnd, message, wParam, lParam); + else + return 0; + + case WM_MOVE: + case WM_SIZE: + mswin_layout_main_window(NULL); + break; + + case WM_SETFOCUS: + /* if there is a menu window out there - + transfer input focus to it */ + if( IsWindow( GetNHApp()->hPopupWnd ) ) { + SetFocus( GetNHApp()->hPopupWnd ); + } + break; + + case WM_CLOSE: + { + /* exit gracefully */ + if (program_state.gameover) + { + /* assume the user really meant this, as the game is already over... */ + /* to make sure we still save bones, just set stop printing flag */ + program_state.stopprint++; + NHEVENT_KBD('\033'); /* and send keyboard input as if user pressed ESC */ + /* additional code for this is done in menu and rip windows */ + } + else + { + switch(MessageBox(hWnd, TEXT("Save?"), TEXT("NetHack for Windows"), MB_YESNOCANCEL | MB_ICONQUESTION)) { + case IDYES: NHEVENT_KBD('y'); dosave(); break; + case IDNO: NHEVENT_KBD('q'); done(QUIT); break; + case IDCANCEL: break; + } + } + } return 0; + + case WM_DESTROY: + /* apparently we never get here + TODO: work on exit routines - need to send + WM_QUIT somehow */ + + /* clean up */ + free( (PNHMainWindow)GetWindowLong(hWnd, GWL_USERDATA) ); + SetWindowLong(hWnd, GWL_USERDATA, (LONG)0); + + // PostQuitMessage(0); + exit(1); + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + switch(wParam) { + + /* new window was just added */ + case MSNH_MSG_ADDWND: { + PMSNHMsgAddWnd msg_param = (PMSNHMsgAddWnd)lParam; + HWND child; + + if( GetNHApp()->windowlist[msg_param->wid].type == NHW_MAP ) + mswin_select_map_mode(iflags.wc_map_mode); + + child = GetNHApp()->windowlist[msg_param->wid].win; + if( child ) mswin_layout_main_window(child); + } break; + + } +} + +/* adjust windows to fit main window layout + --------------------------- + | Status | + +-------------------------+ + | | + | | + | MAP | + | | + | | + +-------------------------+ + | Messages | + --------------------------- +*/ +void mswin_layout_main_window(HWND changed_child) +{ + winid i; + POINT pt; + RECT client_rt, wnd_rect; + SIZE menu_size; + POINT status_org; + SIZE status_size; + POINT msg_org; + SIZE msg_size; + POINT map_org; + SIZE map_size; + HWND wnd_status, wnd_msg; + PNHMainWindow data; + + GetClientRect(GetNHApp()->hMainWnd, &client_rt); + data = (PNHMainWindow)GetWindowLong(GetNHApp()->hMainWnd, GWL_USERDATA); + + /* get sizes of child windows */ + wnd_status = mswin_hwnd_from_winid(WIN_STATUS); + if( IsWindow(wnd_status) ) { + mswin_status_window_size(wnd_status, &status_size); + } else { + status_size.cx = status_size.cy = 0; + } + + wnd_msg = mswin_hwnd_from_winid(WIN_MESSAGE); + if( IsWindow(wnd_msg) ) { + mswin_message_window_size(wnd_msg, &msg_size); + } else { + msg_size.cx = msg_size.cy = 0; + } + + /* set window positions */ + SetRect(&wnd_rect, client_rt.left, client_rt.top, client_rt.right, client_rt.bottom); + switch(iflags.wc_align_status) { + case ALIGN_LEFT: + status_size.cx = (wnd_rect.right-wnd_rect.left)/4; + status_size.cy = (wnd_rect.bottom-wnd_rect.top); // that won't look good + status_org.x = wnd_rect.left; + status_org.y = wnd_rect.top; + wnd_rect.left += status_size.cx; + break; + + case ALIGN_RIGHT: + status_size.cx = (wnd_rect.right-wnd_rect.left)/4; + status_size.cy = (wnd_rect.bottom-wnd_rect.top); // that won't look good + status_org.x = wnd_rect.right - status_size.cx; + status_org.y = wnd_rect.top; + wnd_rect.right -= status_size.cx; + break; + + case ALIGN_TOP: + status_size.cx = (wnd_rect.right-wnd_rect.left); + status_org.x = wnd_rect.left; + status_org.y = wnd_rect.top; + wnd_rect.top += status_size.cy; + break; + + case ALIGN_BOTTOM: + default: + status_size.cx = (wnd_rect.right-wnd_rect.left); + status_org.x = wnd_rect.left; + status_org.y = wnd_rect.bottom - status_size.cy; + wnd_rect.bottom -= status_size.cy; + break; + } + + switch(iflags.wc_align_message) { + case ALIGN_LEFT: + msg_size.cx = (wnd_rect.right-wnd_rect.left)/4; + msg_size.cy = (wnd_rect.bottom-wnd_rect.top); + msg_org.x = wnd_rect.left; + msg_org.y = wnd_rect.top; + wnd_rect.left += msg_size.cx; + break; + + case ALIGN_RIGHT: + msg_size.cx = (wnd_rect.right-wnd_rect.left)/4; + msg_size.cy = (wnd_rect.bottom-wnd_rect.top); + msg_org.x = wnd_rect.right - msg_size.cx; + msg_org.y = wnd_rect.top; + wnd_rect.right -= msg_size.cx; + break; + + case ALIGN_TOP: + msg_size.cx = (wnd_rect.right-wnd_rect.left); + msg_org.x = wnd_rect.left; + msg_org.y = wnd_rect.top; + wnd_rect.top += msg_size.cy; + break; + + case ALIGN_BOTTOM: + default: + msg_size.cx = (wnd_rect.right-wnd_rect.left); + msg_org.x = wnd_rect.left; + msg_org.y = wnd_rect.bottom - msg_size.cy; + wnd_rect.bottom -= msg_size.cy; + break; + } + + map_org.x = wnd_rect.left; + map_org.y = wnd_rect.top; + map_size.cx = wnd_rect.right - wnd_rect.left; + map_size.cy = wnd_rect.bottom - wnd_rect.top; + + /* go through the windows list and adjust sizes */ + for( i=0; iwindowlist[i].win && !GetNHApp()->windowlist[i].dead) { + switch( GetNHApp()->windowlist[i].type ) { + case NHW_STATUS: + MoveWindow(GetNHApp()->windowlist[i].win, + status_org.x, + status_org.y, + status_size.cx, + status_size.cy, + TRUE ); + break; + + case NHW_MAP: + MoveWindow(GetNHApp()->windowlist[i].win, + map_org.x, + map_org.y, + map_size.cx, + map_size.cy, + TRUE ); + break; + + case NHW_MESSAGE: + MoveWindow(GetNHApp()->windowlist[i].win, + msg_org.x, + msg_org.y, + msg_size.cx, + msg_size.cy, + TRUE ); + break; + + case NHW_MENU: + mswin_menu_window_size(GetNHApp()->windowlist[i].win, &menu_size); + menu_size.cx = min(menu_size.cx, (client_rt.right-client_rt.left)); + + pt.x = map_org.x + max(0, (int)(map_size.cx-menu_size.cx)); + pt.y = map_org.y; + ClientToScreen(GetNHApp()->hMainWnd, &pt); + MoveWindow(GetNHApp()->windowlist[i].win, + pt.x, + pt.y, + min(menu_size.cx, map_size.cx), + map_size.cy, + TRUE ); + break; + } + ShowWindow(GetNHApp()->windowlist[i].win, SW_SHOW); + } + } +} + +LRESULT onWMCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + int wmId, wmEvent; + PNHMainWindow data; + + data = (PNHMainWindow)GetWindowLong(hWnd, GWL_USERDATA); + wmId = LOWORD(wParam); + wmEvent = HIWORD(wParam); + + // Parse the menu selections: + switch (wmId) + { + case IDM_ABOUT: + DialogBox(GetNHApp()->hApp, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); + break; + + case IDM_EXIT: + done2(); + break; + + case IDM_SAVE: + dosave(); + break; + + case IDM_MAP_TILES: + case IDM_MAP_ASCII4X6: + case IDM_MAP_ASCII6X8: + case IDM_MAP_ASCII8X8: + case IDM_MAP_ASCII16X8: + case IDM_MAP_ASCII7X12: + case IDM_MAP_ASCII8X12: + case IDM_MAP_ASCII12X16: + case IDM_MAP_ASCII16X12: + case IDM_MAP_ASCII10X18: + mswin_select_map_mode(menuid2mapmode(wmId)); + break; + + case IDM_MAP_FIT_TO_SCREEN: + if( IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode) ) { + mswin_select_map_mode( + IS_MAP_ASCII(iflags.wc_map_mode)? + data->mapAcsiiModeSave : + MAP_MODE_TILES + ); + } else { + mswin_select_map_mode( + IS_MAP_ASCII(iflags.wc_map_mode)? + MAP_MODE_ASCII_FIT_TO_SCREEN : + MAP_MODE_TILES_FIT_TO_SCREEN + ); + } + break; + + case IDM_NHMODE: + { + GetNHApp()->regNetHackMode = GetNHApp()->regNetHackMode ? 0 : 1; + mswin_menu_check_intf_mode(); + break; + } + case IDM_CLEARSETTINGS: + { + mswin_destroy_reg(); + /* Notify the user that windows settings will not be saved this time. */ + MessageBox(GetNHApp()->hMainWnd, + "Your Windows Settings will not be stored when you exit this time.", + "NetHack", MB_OK | MB_ICONINFORMATION); + break; + } + case IDM_HELP_LONG: + display_file(HELP, TRUE); + break; + + case IDM_HELP_COMMANDS: + display_file(SHELP, TRUE); + break; + + case IDM_HELP_HISTORY: + (void) dohistory(); + break; + + case IDM_HELP_INFO_CHAR: + (void) dowhatis(); + break; + + case IDM_HELP_INFO_KEY: + (void) dowhatdoes(); + break; + + case IDM_HELP_OPTIONS: + option_help(); + break; + + case IDM_HELP_OPTIONS_LONG: + display_file(OPTIONFILE, TRUE); + break; + + case IDM_HELP_EXTCMD: + (void) doextlist(); + break; + + case IDM_HELP_LICENSE: + display_file(LICENSE, TRUE); + break; + + case IDM_HELP_PORTHELP: + display_file(PORT_HELP, TRUE); + break; + + default: + return 1; + } + return 0; +} + +// Mesage handler for about box. +LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +{ + char buf[BUFSZ]; + TCHAR wbuf[BUFSZ]; + RECT main_rt, dlg_rt; + SIZE dlg_sz; + + switch (message) + { + case WM_INITDIALOG: + getversionstring(buf); + SetDlgItemText(hDlg, IDC_ABOUT_VERSION, NH_A2W(buf, wbuf, sizeof(wbuf))); + + SetDlgItemText(hDlg, IDC_ABOUT_COPYRIGHT, + NH_A2W( + COPYRIGHT_BANNER_A "\n" + COPYRIGHT_BANNER_B "\n" + COPYRIGHT_BANNER_C, + wbuf, + BUFSZ + ) ); + + + /* center dialog in the main window */ + GetWindowRect(GetNHApp()->hMainWnd, &main_rt); + GetWindowRect(hDlg, &dlg_rt); + dlg_sz.cx = dlg_rt.right - dlg_rt.left; + dlg_sz.cy = dlg_rt.bottom - dlg_rt.top; + + dlg_rt.left = (main_rt.left+main_rt.right-dlg_sz.cx)/2; + dlg_rt.right = dlg_rt.left + dlg_sz.cx; + dlg_rt.top = (main_rt.top+main_rt.bottom-dlg_sz.cy)/2; + dlg_rt.bottom = dlg_rt.top + dlg_sz.cy; + MoveWindow( hDlg, + (main_rt.left+main_rt.right-dlg_sz.cx)/2, + (main_rt.top+main_rt.bottom-dlg_sz.cy)/2, + dlg_sz.cx, + dlg_sz.cy, + TRUE ); + + return TRUE; + + case WM_COMMAND: + if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) + { + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + } + break; + } + return FALSE; +} + +void mswin_menu_check_intf_mode() +{ + HMENU hMenu = GetMenu(GetNHApp()->hMainWnd); + + if (GetNHApp()->regNetHackMode) + CheckMenuItem(hMenu, IDM_NHMODE, MF_CHECKED); + else + CheckMenuItem(hMenu, IDM_NHMODE, MF_UNCHECKED); + +} + +void mswin_select_map_mode(int mode) +{ + PNHMainWindow data; + winid map_id; + + map_id = WIN_MAP; + data = (PNHMainWindow)GetWindowLong(GetNHApp()->hMainWnd, GWL_USERDATA); + + /* override for Rogue level */ +#ifdef REINCARNATION + if( Is_rogue_level(&u.uz) && !IS_MAP_ASCII(mode) ) return; +#endif + + /* set map mode menu mark */ + if( IS_MAP_ASCII(mode) ) { + CheckMenuRadioItem( + GetMenu(GetNHApp()->hMainWnd), + IDM_MAP_TILES, + IDM_MAP_ASCII10X18, + mapmode2menuid( IS_MAP_FIT_TO_SCREEN(mode)? data->mapAcsiiModeSave : mode ), + MF_BYCOMMAND); + } else { + CheckMenuRadioItem( + GetMenu(GetNHApp()->hMainWnd), + IDM_MAP_TILES, + IDM_MAP_ASCII10X18, + mapmode2menuid( MAP_MODE_TILES ), + MF_BYCOMMAND); + } + + /* set fit-to-screen mode mark */ + CheckMenuItem( + GetMenu(GetNHApp()->hMainWnd), + IDM_MAP_FIT_TO_SCREEN, + MF_BYCOMMAND | + (IS_MAP_FIT_TO_SCREEN(mode)? MF_CHECKED : MF_UNCHECKED) + ); + + if( IS_MAP_ASCII(iflags.wc_map_mode) && !IS_MAP_FIT_TO_SCREEN(iflags.wc_map_mode)) { + data->mapAcsiiModeSave = iflags.wc_map_mode; + } + + iflags.wc_map_mode = mode; + + /* + ** first, check if WIN_MAP has been inialized. + ** If not - attempt to retrieve it by type, then check it again + */ + if( map_id==WIN_ERR ) + map_id = mswin_winid_from_type(NHW_MAP); + if( map_id!=WIN_ERR ) + mswin_map_mode(mswin_hwnd_from_winid(map_id), mode); +} + +static struct t_menu2mapmode { + int menuID; + int mapMode; +} _menu2mapmode[] = +{ + { IDM_MAP_TILES, MAP_MODE_TILES }, + { IDM_MAP_ASCII4X6, MAP_MODE_ASCII4x6 }, + { IDM_MAP_ASCII6X8, MAP_MODE_ASCII6x8 }, + { IDM_MAP_ASCII8X8, MAP_MODE_ASCII8x8 }, + { IDM_MAP_ASCII16X8, MAP_MODE_ASCII16x8 }, + { IDM_MAP_ASCII7X12, MAP_MODE_ASCII7x12 }, + { IDM_MAP_ASCII8X12, MAP_MODE_ASCII8x12 }, + { IDM_MAP_ASCII12X16, MAP_MODE_ASCII12x16 }, + { IDM_MAP_ASCII16X12, MAP_MODE_ASCII16x12 }, + { IDM_MAP_ASCII10X18, MAP_MODE_ASCII10x18 }, + { IDM_MAP_FIT_TO_SCREEN, MAP_MODE_ASCII_FIT_TO_SCREEN }, + { -1, -1 } +}; + +int menuid2mapmode(int menuid) +{ + struct t_menu2mapmode* p; + for( p = _menu2mapmode; p->mapMode!=-1; p++ ) + if(p->menuID==menuid ) return p->mapMode; + return -1; +} + +int mapmode2menuid(int map_mode) +{ + struct t_menu2mapmode* p; + for( p = _menu2mapmode; p->mapMode!=-1; p++ ) + if(p->mapMode==map_mode ) return p->menuID; + return -1; +} diff --git a/win/win32/mhmain.h b/win/win32/mhmain.h new file mode 100644 index 0000000..3f40714 --- /dev/null +++ b/win/win32/mhmain.h @@ -0,0 +1,16 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef MSWINMainWindow_h +#define MSWINMainWindow_h + +/* this is a main appliation window */ + +#include "winMS.h" + +HWND mswin_init_main_window (void); +void mswin_layout_main_window(HWND changed_child); +void mswin_select_map_mode(int map_mode); +void mswin_menu_check_intf_mode(void); + +#endif /* MSWINMainWindow_h */ diff --git a/win/win32/mhmap.c b/win/win32/mhmap.c new file mode 100644 index 0000000..2790bb3 --- /dev/null +++ b/win/win32/mhmap.c @@ -0,0 +1,954 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "winMS.h" +#include "resource.h" +#include "mhmap.h" +#include "mhmsg.h" +#include "mhinput.h" + +#include "patchlevel.h" + +#define NHMAP_FONT_NAME TEXT("Terminal") +#define MAXWINDOWTEXT 255 + +extern short glyph2tile[]; + +/* map window data */ +typedef struct mswin_nethack_map_window { + int map[COLNO][ROWNO]; /* glyph map */ + + int mapMode; /* current map mode */ + boolean bAsciiMode; /* switch ASCII/tiled mode */ + boolean bFitToScreenMode; /* switch Fit map to screen mode on/off */ + int xPos, yPos; /* scroll position */ + int xPageSize, yPageSize; /* scroll page size */ + int xCur, yCur; /* position of the cursor */ + int xScrTile, yScrTile; /* size of display tile */ + POINT map_orig; /* map origin point */ + + HFONT hMapFont; /* font for ASCII mode */ +} NHMapWindow, *PNHMapWindow; + +static TCHAR szNHMapWindowClass[] = TEXT("MSNethackMapWndClass"); +LRESULT CALLBACK MapWndProc(HWND, UINT, WPARAM, LPARAM); +static void register_map_window_class(void); +static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam); +static void onMSNH_VScroll(HWND hWnd, WPARAM wParam, LPARAM lParam); +static void onMSNH_HScroll(HWND hWnd, WPARAM wParam, LPARAM lParam); +static void onPaint(HWND hWnd); +static void onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam); +static void nhcoord2display(PNHMapWindow data, int x, int y, LPRECT lpOut); +#if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2) +static void nhglyph2charcolor(short glyph, uchar* ch, int* color); +#endif +static COLORREF nhcolor_to_RGB(int c); + +HWND mswin_init_map_window () { + static int run_once = 0; + HWND ret; + + if( !run_once ) { + register_map_window_class(); + run_once = 1; + } + + ret = CreateWindow( + szNHMapWindowClass, /* registered class name */ + NULL, /* window name */ + WS_CHILD | WS_HSCROLL | WS_VSCROLL | WS_CLIPSIBLINGS, /* window style */ + 0, /* horizontal position of window - set it later */ + 0, /* vertical position of window - set it later */ + 0, /* window width - set it later */ + 0, /* window height - set it later*/ + GetNHApp()->hMainWnd, /* handle to parent or owner window */ + NULL, /* menu handle or child identifier */ + GetNHApp()->hApp, /* handle to application instance */ + NULL ); /* window-creation data */ + if( !ret ) { + panic("Cannot create map window"); + } + return ret; +} + +void mswin_map_stretch(HWND hWnd, LPSIZE lpsz, BOOL redraw) +{ + PNHMapWindow data; + RECT client_rt; + SCROLLINFO si; + SIZE wnd_size; + LOGFONT lgfnt; + + /* check arguments */ + if( !IsWindow(hWnd) || + !lpsz || + lpsz->cx<=0 || + lpsz->cy<=0 ) return; + + /* calculate window size */ + GetClientRect(hWnd, &client_rt); + wnd_size.cx = client_rt.right - client_rt.left; + wnd_size.cy = client_rt.bottom - client_rt.top; + + /* set new screen tile size */ + data = (PNHMapWindow)GetWindowLong(hWnd, GWL_USERDATA); + data->xScrTile = (data->bFitToScreenMode? wnd_size.cx : lpsz->cx) / COLNO; + data->yScrTile = (data->bFitToScreenMode? wnd_size.cy : lpsz->cy) / ROWNO; + + /* set map origin point */ + data->map_orig.x = max(0, client_rt.left + (wnd_size.cx - data->xScrTile*COLNO)/2 ); + data->map_orig.y = max(0, client_rt.top + (wnd_size.cy - data->yScrTile*ROWNO)/2 ); + + data->map_orig.x -= data->map_orig.x % data->xScrTile; + data->map_orig.y -= data->map_orig.y % data->yScrTile; + + /* adjust horizontal scroll bar */ + if( data->bFitToScreenMode ) + data->xPageSize = COLNO+1; /* disable scroll bar */ + else + data->xPageSize = wnd_size.cx/data->xScrTile; + + if( data->xPageSize >= COLNO ) { + data->xPos = 0; + GetNHApp()->bNoHScroll = TRUE; + } else { + GetNHApp()->bNoHScroll = FALSE; + data->xPos = max(0, min(COLNO-data->xPageSize+1, u.ux - data->xPageSize/2)); + } + + si.cbSize = sizeof(si); + si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; + si.nMin = 0; + si.nMax = COLNO; + si.nPage = data->xPageSize; + si.nPos = data->xPos; + SetScrollInfo(hWnd, SB_HORZ, &si, TRUE); + + /* adjust vertical scroll bar */ + if( data->bFitToScreenMode ) + data->yPageSize = ROWNO+1; /* disable scroll bar */ + else + data->yPageSize = wnd_size.cy/data->yScrTile; + + if( data->yPageSize >= ROWNO ) { + data->yPos = 0; + GetNHApp()->bNoVScroll = TRUE; + } else { + GetNHApp()->bNoVScroll = FALSE; + data->yPos = max(0, min(ROWNO-data->yPageSize+1, u.uy - data->yPageSize/2)); + } + + si.cbSize = sizeof(si); + si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; + si.nMin = 0; + si.nMax = ROWNO; + si.nPage = data->yPageSize; + si.nPos = data->yPos; + SetScrollInfo(hWnd, SB_VERT, &si, TRUE); + + /* create font */ + if( data->hMapFont ) DeleteObject(data->hMapFont); + ZeroMemory(&lgfnt, sizeof(lgfnt)); + lgfnt.lfHeight = -data->yScrTile; // height of font + lgfnt.lfWidth = -data->xScrTile; // average character width + lgfnt.lfEscapement = 0; // angle of escapement + lgfnt.lfOrientation = 0; // base-line orientation angle + lgfnt.lfWeight = FW_NORMAL; // font weight + lgfnt.lfItalic = FALSE; // italic attribute option + lgfnt.lfUnderline = FALSE; // underline attribute option + lgfnt.lfStrikeOut = FALSE; // strikeout attribute option + lgfnt.lfCharSet = OEM_CHARSET; // character set identifier + lgfnt.lfOutPrecision = OUT_DEFAULT_PRECIS; // output precision + lgfnt.lfClipPrecision = CLIP_DEFAULT_PRECIS; // clipping precision + lgfnt.lfQuality = DEFAULT_QUALITY; // output quality + lgfnt.lfPitchAndFamily = FIXED_PITCH; // pitch and family + _tcscpy(lgfnt.lfFaceName, NHMAP_FONT_NAME); + data->hMapFont = CreateFontIndirect(&lgfnt); + + mswin_cliparound(data->xCur, data->yCur); + + if(redraw) InvalidateRect(hWnd, NULL, TRUE); +} + +/* set map mode */ +int mswin_map_mode(HWND hWnd, int mode) +{ + PNHMapWindow data; + int oldMode; + SIZE mapSize; + + data = (PNHMapWindow)GetWindowLong(hWnd, GWL_USERDATA); + if( mode == data->mapMode ) return mode; + + oldMode = data->mapMode; + data->mapMode = mode; + + switch( data->mapMode ) { + + case MAP_MODE_ASCII4x6: + data->bAsciiMode = TRUE; + data->bFitToScreenMode = FALSE; + mapSize.cx = 4*COLNO; + mapSize.cy = 6*ROWNO; + break; + + case MAP_MODE_ASCII6x8: + data->bAsciiMode = TRUE; + data->bFitToScreenMode = FALSE; + mapSize.cx = 6*COLNO; + mapSize.cy = 8*ROWNO; + break; + + case MAP_MODE_ASCII8x8: + data->bAsciiMode = TRUE; + data->bFitToScreenMode = FALSE; + mapSize.cx = 8*COLNO; + mapSize.cy = 8*ROWNO; + break; + + case MAP_MODE_ASCII16x8: + data->bAsciiMode = TRUE; + data->bFitToScreenMode = FALSE; + mapSize.cx = 16*COLNO; + mapSize.cy = 8*ROWNO; + break; + + case MAP_MODE_ASCII7x12: + data->bAsciiMode = TRUE; + data->bFitToScreenMode = FALSE; + mapSize.cx = 7*COLNO; + mapSize.cy = 12*ROWNO; + break; + + case MAP_MODE_ASCII8x12: + data->bAsciiMode = TRUE; + data->bFitToScreenMode = FALSE; + mapSize.cx = 8*COLNO; + mapSize.cy = 12*ROWNO; + break; + + case MAP_MODE_ASCII16x12: + data->bAsciiMode = TRUE; + data->bFitToScreenMode = FALSE; + mapSize.cx = 16*COLNO; + mapSize.cy = 12*ROWNO; + break; + + case MAP_MODE_ASCII12x16: + data->bAsciiMode = TRUE; + data->bFitToScreenMode = FALSE; + mapSize.cx = 12*COLNO; + mapSize.cy = 16*ROWNO; + break; + + case MAP_MODE_ASCII10x18: + data->bAsciiMode = TRUE; + data->bFitToScreenMode = FALSE; + mapSize.cx = 10*COLNO; + mapSize.cy = 18*ROWNO; + break; + + case MAP_MODE_ASCII_FIT_TO_SCREEN: { + RECT client_rt; + GetClientRect(hWnd, &client_rt); + mapSize.cx = client_rt.right - client_rt.left; + mapSize.cy = client_rt.bottom - client_rt.top; + + data->bAsciiMode = TRUE; + data->bFitToScreenMode = TRUE; + } break; + + case MAP_MODE_TILES_FIT_TO_SCREEN: { + RECT client_rt; + GetClientRect(hWnd, &client_rt); + mapSize.cx = client_rt.right - client_rt.left; + mapSize.cy = client_rt.bottom - client_rt.top; + + data->bAsciiMode = FALSE; + data->bFitToScreenMode = TRUE; + } break; + + case MAP_MODE_TILES: + default: + data->bAsciiMode = FALSE; + data->bFitToScreenMode = FALSE; + mapSize.cx = GetNHApp()->mapTile_X*COLNO; + mapSize.cy = GetNHApp()->mapTile_Y*ROWNO; + break; + } + + mswin_map_stretch(hWnd, &mapSize, TRUE); + + return oldMode; +} + +/* register window class for map window */ +void register_map_window_class() +{ + WNDCLASS wcex; + ZeroMemory( &wcex, sizeof(wcex)); + + /* window class */ + wcex.style = CS_NOCLOSE | CS_DBLCLKS; + wcex.lpfnWndProc = (WNDPROC)MapWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = GetNHApp()->hApp; + wcex.hIcon = NULL; + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = CreateSolidBrush(RGB(0, 0, 0)); /* set backgroup here */ + wcex.lpszMenuName = NULL; + wcex.lpszClassName = szNHMapWindowClass; + + if( !RegisterClass(&wcex) ) { + panic("cannot register Map window class"); + } +} + +/* map window procedure */ +LRESULT CALLBACK MapWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + PNHMapWindow data; + + data = (PNHMapWindow)GetWindowLong(hWnd, GWL_USERDATA); + switch (message) + { + case WM_CREATE: + onCreate( hWnd, wParam, lParam ); + break; + + case WM_MSNH_COMMAND: + onMSNHCommand(hWnd, wParam, lParam); + break; + + case WM_PAINT: + onPaint(hWnd); + break; + + case WM_SETFOCUS: + /* transfer focus back to the main window */ + SetFocus(GetNHApp()->hMainWnd); + break; + + case WM_HSCROLL: + onMSNH_HScroll(hWnd, wParam, lParam); + break; + + case WM_VSCROLL: + onMSNH_VScroll(hWnd, wParam, lParam); + break; + + case WM_SIZE: + { + SIZE size; + + if( data->bFitToScreenMode ) { + size.cx = LOWORD(lParam); + size.cy = HIWORD(lParam); + } else { + /* mapping factor is unchaged we just need to adjust scroll bars */ + size.cx = data->xScrTile*COLNO; + size.cy = data->yScrTile*ROWNO; + } + mswin_map_stretch(hWnd, &size, TRUE); + } + break; + + case WM_LBUTTONDOWN: + NHEVENT_MS( + CLICK_1, + max(0, min(COLNO, data->xPos + (LOWORD(lParam)-data->map_orig.x)/data->xScrTile)), + max(0, min(ROWNO, data->yPos + (HIWORD(lParam)-data->map_orig.y)/data->yScrTile)) + ); + return 0; + + case WM_LBUTTONDBLCLK : + NHEVENT_MS( + CLICK_2, + max(0, min(COLNO, data->xPos + (LOWORD(lParam)-data->map_orig.x)/data->xScrTile)), + max(0, min(ROWNO, data->yPos + (HIWORD(lParam)-data->map_orig.y)/data->yScrTile)) + ); + return 0; + + case WM_DESTROY: + if( data->hMapFont ) DeleteObject(data->hMapFont); + free(data); + SetWindowLong(hWnd, GWL_USERDATA, (LONG)0); + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +/* on WM_COMMAND */ +void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + PNHMapWindow data; + RECT rt; + + data = (PNHMapWindow)GetWindowLong(hWnd, GWL_USERDATA); + switch(wParam) { + case MSNH_MSG_PRINT_GLYPH: + { + PMSNHMsgPrintGlyph msg_data = (PMSNHMsgPrintGlyph)lParam; + data->map[msg_data->x][msg_data->y] = msg_data->glyph; + + /* invalidate the update area */ + nhcoord2display(data, msg_data->x, msg_data->y, &rt); + InvalidateRect(hWnd, &rt, TRUE); + } + break; + + case MSNH_MSG_CLIPAROUND: + { + PMSNHMsgClipAround msg_data = (PMSNHMsgClipAround)lParam; + int x, y; + BOOL scroll_x, scroll_y; + int mcam = iflags.wc_scroll_margin; + + /* calculate if you should clip around */ + scroll_x = + !GetNHApp()->bNoHScroll && + ( msg_data->x<(data->xPos+mcam) || + msg_data->x>(data->xPos+data->xPageSize-mcam) ); + scroll_y = + !GetNHApp()->bNoVScroll && + ( msg_data->y<(data->yPos+mcam) || + msg_data->y>(data->yPos+data->yPageSize-mcam) ); + + /* get page size and center horizontally on x-position */ + if( scroll_x ) { + if( data->xPageSize<=2*mcam ) { + x = max(0, min(COLNO, msg_data->x - data->xPageSize/2)); + } else if( msg_data->x < data->xPos+data->xPageSize/2 ) { + x = max(0, min(COLNO, msg_data->x - mcam)); + } else { + x = max(0, min(COLNO, msg_data->x - data->xPageSize + mcam)); + } + SendMessage( hWnd, WM_HSCROLL, (WPARAM)MAKELONG(SB_THUMBTRACK, x), (LPARAM)NULL ); + } + + /* get page size and center vertically on y-position */ + if( scroll_y ) { + if( data->yPageSize<=2*mcam ) { + y = max(0, min(ROWNO, msg_data->y - data->yPageSize/2)); + } else if( msg_data->y < data->yPos+data->yPageSize/2 ) { + y = max(0, min(ROWNO, msg_data->y - mcam)); + } else { + y = max(0, min(ROWNO, msg_data->y - data->yPageSize + mcam)); + } + SendMessage( hWnd, WM_VSCROLL, (WPARAM)MAKELONG(SB_THUMBTRACK, y), (LPARAM)NULL ); + } + } + break; + + case MSNH_MSG_CLEAR_WINDOW: + { + int i, j; + for(i=0; imap[i][j] = -1; + } + InvalidateRect(hWnd, NULL, TRUE); + } break; + + case MSNH_MSG_CURSOR: + { + PMSNHMsgCursor msg_data = (PMSNHMsgCursor)lParam; + HDC hdc; + RECT rt; + + /* move focus rectangle at the cursor postion */ + hdc = GetDC(hWnd); + + nhcoord2display(data, data->xCur, data->yCur, &rt); + if( data->bAsciiMode ) { + PatBlt(hdc, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, DSTINVERT); + } else { + DrawFocusRect(hdc, &rt); + } + + data->xCur = msg_data->x; + data->yCur = msg_data->y; + + nhcoord2display(data, data->xCur, data->yCur, &rt); + if( data->bAsciiMode ) { + PatBlt(hdc, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, DSTINVERT); + } else { + DrawFocusRect(hdc, &rt); + } + + ReleaseDC(hWnd, hdc); + } break; + } +} + +/* on WM_CREATE */ +void onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + PNHMapWindow data; + int i,j; + + /* set window data */ + data = (PNHMapWindow)malloc(sizeof(NHMapWindow)); + if( !data ) panic("out of memory"); + + ZeroMemory(data, sizeof(NHMapWindow)); + for(i=0; imap[i][j] = -1; + } + + data->bAsciiMode = FALSE; + + data->xScrTile = GetNHApp()->mapTile_X; + data->yScrTile = GetNHApp()->mapTile_Y; + + SetWindowLong(hWnd, GWL_USERDATA, (LONG)data); +} + +/* on WM_PAINT */ +void onPaint(HWND hWnd) +{ + PNHMapWindow data; + PAINTSTRUCT ps; + HDC hDC; + HDC tileDC; + HGDIOBJ saveBmp; + RECT paint_rt; + int i, j; + + /* get window data */ + data = (PNHMapWindow)GetWindowLong(hWnd, GWL_USERDATA); + + hDC = BeginPaint(hWnd, &ps); + + /* calculate paint rectangle */ + if( !IsRectEmpty(&ps.rcPaint) ) { + /* calculate paint rectangle */ + paint_rt.left = max(data->xPos + (ps.rcPaint.left - data->map_orig.x)/data->xScrTile, 0); + paint_rt.top = max(data->yPos + (ps.rcPaint.top - data->map_orig.y)/data->yScrTile, 0); + paint_rt.right = min(data->xPos + (ps.rcPaint.right - data->map_orig.x)/data->xScrTile+1, COLNO); + paint_rt.bottom = min(data->yPos + (ps.rcPaint.bottom - data->map_orig.y)/data->yScrTile+1, ROWNO); + + if( data->bAsciiMode +#ifdef REINCARNATION + || Is_rogue_level(&u.uz) + /* You enter a VERY primitive world! */ +#endif + ) { + HGDIOBJ oldFont; + + oldFont = SelectObject(hDC, data->hMapFont); + SetBkMode(hDC, TRANSPARENT); + + /* draw the map */ + for(i=paint_rt.left; imap[i][j]>=0) { + char ch; + TCHAR wch; + RECT glyph_rect; + int color; + unsigned special; + int mgch; + HBRUSH back_brush; + + nhcoord2display(data, i, j, &glyph_rect); + +#if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2) + nhglyph2charcolor(data->map[i][j], &ch, &color); + SetTextColor (hDC, nhcolor_to_RGB(color) ); +#else + /* rely on NetHack core helper routine */ + mapglyph(data->map[i][j], &mgch, &color, + &special, i, j); + ch = (char)mgch; + if (((special & MG_PET) && iflags.hilite_pet) || + ((special & MG_DETECT) && iflags.use_inverse)) { + back_brush = CreateSolidBrush(RGB(192, 192, 192)); + FillRect (hDC, &glyph_rect, back_brush); + DeleteObject (back_brush); + SetTextColor( hDC, RGB(0, 0, 0) ); + } else + { + SetTextColor (hDC, nhcolor_to_RGB(color) ); + } +#endif + + DrawText(hDC, + NH_A2W(&ch, &wch, 1), + 1, + &glyph_rect, + DT_CENTER | DT_VCENTER | DT_NOPREFIX + ); + } + SelectObject(hDC, oldFont); + } else { + /* prepare tiles DC for mapping */ + tileDC = CreateCompatibleDC(hDC); + saveBmp = SelectObject(tileDC, GetNHApp()->bmpMapTiles); + + /* draw the map */ + for(i=paint_rt.left; imap[i][j]>=0) { + short ntile; + int t_x, t_y; + RECT glyph_rect; + + ntile = glyph2tile[ data->map[i][j] ]; + t_x = (ntile % GetNHApp()->mapTilesPerLine)*GetNHApp()->mapTile_X; + t_y = (ntile / GetNHApp()->mapTilesPerLine)*GetNHApp()->mapTile_Y; + + nhcoord2display(data, i, j, &glyph_rect); + + StretchBlt( + hDC, + glyph_rect.left, + glyph_rect.top, + data->xScrTile, + data->yScrTile, + tileDC, + t_x, + t_y, + GetNHApp()->mapTile_X, + GetNHApp()->mapTile_Y, + SRCCOPY + ); + if( glyph_is_pet(data->map[i][j]) && iflags.wc_hilite_pet ) { + /* apply pet mark transparently over + pet image */ + HDC hdcPetMark; + HBITMAP bmPetMarkOld; + + /* this is DC for petmark bitmap */ + hdcPetMark = CreateCompatibleDC(hDC); + bmPetMarkOld = SelectObject(hdcPetMark, GetNHApp()->bmpPetMark); + + nhapply_image_transparent( + hDC, + glyph_rect.left, + glyph_rect.top, + data->xScrTile, + data->yScrTile, + hdcPetMark, + 0, + 0, + TILE_X, + TILE_Y, + TILE_BK_COLOR + ); + SelectObject(hdcPetMark, bmPetMarkOld); + DeleteDC(hdcPetMark); + } + } + SelectObject(tileDC, saveBmp); + DeleteDC(tileDC); + } + + /* draw focus rect */ + nhcoord2display(data, data->xCur, data->yCur, &paint_rt); + if( data->bAsciiMode ) { + PatBlt( hDC, + paint_rt.left, paint_rt.top, + paint_rt.right-paint_rt.left, paint_rt.bottom-paint_rt.top, + DSTINVERT ); + } else { + DrawFocusRect(hDC, &paint_rt); + } + } + EndPaint(hWnd, &ps); +} + +/* on WM_VSCROLL */ +void onMSNH_VScroll(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + PNHMapWindow data; + SCROLLINFO si; + int yNewPos; + int yDelta; + + /* get window data */ + data = (PNHMapWindow)GetWindowLong(hWnd, GWL_USERDATA); + + switch(LOWORD (wParam)) + { + /* User clicked shaft left of the scroll box. */ + case SB_PAGEUP: + yNewPos = data->yPos-data->yPageSize; + break; + + /* User clicked shaft right of the scroll box. */ + case SB_PAGEDOWN: + yNewPos = data->yPos+data->yPageSize; + break; + + /* User clicked the left arrow. */ + case SB_LINEUP: + yNewPos = data->yPos-1; + break; + + /* User clicked the right arrow. */ + case SB_LINEDOWN: + yNewPos = data->yPos+1; + break; + + /* User dragged the scroll box. */ + case SB_THUMBTRACK: + yNewPos = HIWORD(wParam); + break; + + default: + yNewPos = data->yPos; + } + + yNewPos = max(0, min(ROWNO-data->yPageSize+1, yNewPos)); + if( yNewPos == data->yPos ) return; + + yDelta = yNewPos - data->yPos; + data->yPos = yNewPos; + + ScrollWindowEx (hWnd, 0, -data->yScrTile * yDelta, + (CONST RECT *) NULL, (CONST RECT *) NULL, + (HRGN) NULL, (LPRECT) NULL, SW_INVALIDATE | SW_ERASE); + + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = data->yPos; + SetScrollInfo(hWnd, SB_VERT, &si, TRUE); +} + +/* on WM_HSCROLL */ +void onMSNH_HScroll(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + PNHMapWindow data; + SCROLLINFO si; + int xNewPos; + int xDelta; + + /* get window data */ + data = (PNHMapWindow)GetWindowLong(hWnd, GWL_USERDATA); + + switch(LOWORD (wParam)) + { + /* User clicked shaft left of the scroll box. */ + case SB_PAGEUP: + xNewPos = data->xPos-data->xPageSize; + break; + + /* User clicked shaft right of the scroll box. */ + case SB_PAGEDOWN: + xNewPos = data->xPos+data->xPageSize; + break; + + /* User clicked the left arrow. */ + case SB_LINEUP: + xNewPos = data->xPos-1; + break; + + /* User clicked the right arrow. */ + case SB_LINEDOWN: + xNewPos = data->xPos+1; + break; + + /* User dragged the scroll box. */ + case SB_THUMBTRACK: + xNewPos = HIWORD(wParam); + break; + + default: + xNewPos = data->xPos; + } + + xNewPos = max(0, min(COLNO-data->xPageSize+1, xNewPos)); + if( xNewPos == data->xPos ) return; + + xDelta = xNewPos - data->xPos; + data->xPos = xNewPos; + + ScrollWindowEx (hWnd, -data->xScrTile * xDelta, 0, + (CONST RECT *) NULL, (CONST RECT *) NULL, + (HRGN) NULL, (LPRECT) NULL, SW_INVALIDATE | SW_ERASE); + + + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = data->xPos; + SetScrollInfo(hWnd, SB_HORZ, &si, TRUE); +} + +/* map nethack map coordinates to the screen location */ +void nhcoord2display(PNHMapWindow data, int x, int y, LPRECT lpOut) +{ + lpOut->left = (x - data->xPos)*data->xScrTile + data->map_orig.x; + lpOut->top = (y - data->yPos)*data->yScrTile + data->map_orig.y; + lpOut->right = lpOut->left + data->xScrTile; + lpOut->bottom = lpOut->top + data->yScrTile; +} + +#if (VERSION_MAJOR < 4) && (VERSION_MINOR < 4) && (PATCHLEVEL < 2) +/* map glyph to character/color combination */ +void nhglyph2charcolor(short g, uchar* ch, int* color) +{ + int offset; +#ifdef TEXTCOLOR + +#define zap_color(n) *color = iflags.use_color ? zapcolors[n] : NO_COLOR +#define cmap_color(n) *color = iflags.use_color ? defsyms[n].color : NO_COLOR +#define obj_color(n) *color = iflags.use_color ? objects[n].oc_color : NO_COLOR +#define mon_color(n) *color = iflags.use_color ? mons[n].mcolor : NO_COLOR +#define pet_color(n) *color = iflags.use_color ? mons[n].mcolor : NO_COLOR +#define warn_color(n) *color = iflags.use_color ? def_warnsyms[n].color : NO_COLOR + +# else /* no text color */ + +#define zap_color(n) +#define cmap_color(n) +#define obj_color(n) +#define mon_color(n) +#define pet_color(c) +#define warn_color(c) + *color = CLR_WHITE; +#endif + + if ((offset = (g - GLYPH_WARNING_OFF)) >= 0) { /* a warning flash */ + *ch = warnsyms[offset]; + warn_color(offset); + } else if ((offset = (g - GLYPH_SWALLOW_OFF)) >= 0) { /* swallow */ + /* see swallow_to_glyph() in display.c */ + *ch = (uchar) showsyms[S_sw_tl + (offset & 0x7)]; + mon_color(offset >> 3); + } else if ((offset = (g - GLYPH_ZAP_OFF)) >= 0) { /* zap beam */ + /* see zapdir_to_glyph() in display.c */ + *ch = showsyms[S_vbeam + (offset & 0x3)]; + zap_color((offset >> 2)); + } else if ((offset = (g - GLYPH_CMAP_OFF)) >= 0) { /* cmap */ + *ch = showsyms[offset]; + cmap_color(offset); + } else if ((offset = (g - GLYPH_OBJ_OFF)) >= 0) { /* object */ + *ch = oc_syms[(int)objects[offset].oc_class]; + obj_color(offset); + } else if ((offset = (g - GLYPH_BODY_OFF)) >= 0) { /* a corpse */ + *ch = oc_syms[(int)objects[CORPSE].oc_class]; + mon_color(offset); + } else if ((offset = (g - GLYPH_PET_OFF)) >= 0) { /* a pet */ + *ch = monsyms[(int)mons[offset].mlet]; + pet_color(offset); + } else { /* a monster */ + *ch = monsyms[(int)mons[g].mlet]; + mon_color(g); + } + // end of wintty code +} +#endif + +/* map nethack color to RGB */ +COLORREF nhcolor_to_RGB(int c) +{ + switch(c) { + case CLR_BLACK: return RGB(0x55, 0x55, 0x55); + case CLR_RED: return RGB(0xFF, 0x00, 0x00); + case CLR_GREEN: return RGB(0x00, 0x80, 0x00); + case CLR_BROWN: return RGB(0xA5, 0x2A, 0x2A); + case CLR_BLUE: return RGB(0x00, 0x00, 0xFF); + case CLR_MAGENTA: return RGB(0xFF, 0x00, 0xFF); + case CLR_CYAN: return RGB(0x00, 0xFF, 0xFF); + case CLR_GRAY: return RGB(0xC0, 0xC0, 0xC0); + case NO_COLOR: return RGB(0xFF, 0xFF, 0xFF); + case CLR_ORANGE: return RGB(0xFF, 0xA5, 0x00); + case CLR_BRIGHT_GREEN: return RGB(0x00, 0xFF, 0x00); + case CLR_YELLOW: return RGB(0xFF, 0xFF, 0x00); + case CLR_BRIGHT_BLUE: return RGB(0x00, 0xC0, 0xFF); + case CLR_BRIGHT_MAGENTA: return RGB(0xFF, 0x80, 0xFF); + case CLR_BRIGHT_CYAN: return RGB(0x80, 0xFF, 0xFF); /* something close to aquamarine */ + case CLR_WHITE: return RGB(0xFF, 0xFF, 0xFF); + default: return RGB(0x00, 0x00, 0x00); /* black */ + } +} + +/* apply bitmap pointed by sourceDc transparently over + bitmap pointed by hDC */ +void nhapply_image_transparent( + HDC hDC, int x, int y, int width, int height, + HDC sourceDC, int s_x, int s_y, int s_width, int s_height, + COLORREF cTransparent +) +{ + HDC hdcMem, hdcBack, hdcObject, hdcSave; + COLORREF cColor; + HBITMAP bmAndBack, bmAndObject, bmAndMem, bmSave; + HBITMAP bmBackOld, bmObjectOld, bmMemOld, bmSaveOld; + + /* Create some DCs to hold temporary data. */ + hdcBack = CreateCompatibleDC(hDC); + hdcObject = CreateCompatibleDC(hDC); + hdcMem = CreateCompatibleDC(hDC); + hdcSave = CreateCompatibleDC(hDC); + + /* this is bitmap for our pet image */ + bmSave = CreateCompatibleBitmap(hDC, s_width, s_height); + + /* Monochrome DC */ + bmAndBack = CreateBitmap(s_width, s_height, 1, 1, NULL); + bmAndObject = CreateBitmap(s_width, s_height, 1, 1, NULL); + + /* resulting bitmap */ + bmAndMem = CreateCompatibleBitmap(hDC, s_width, s_height); + + /* Each DC must select a bitmap object to store pixel data. */ + bmBackOld = SelectObject(hdcBack, bmAndBack); + bmObjectOld = SelectObject(hdcObject, bmAndObject); + bmMemOld = SelectObject(hdcMem, bmAndMem); + bmSaveOld = SelectObject(hdcSave, bmSave); + + /* copy source image because it is going to be overwritten */ + BitBlt(hdcSave, 0, 0, s_width, s_height, sourceDC, s_x, s_y, SRCCOPY); + + /* Set the background color of the source DC to the color. + contained in the parts of the bitmap that should be transparent */ + cColor = SetBkColor(hdcSave, cTransparent); + + /* Create the object mask for the bitmap by performing a BitBlt + from the source bitmap to a monochrome bitmap. */ + BitBlt(hdcObject, 0, 0, s_width, s_height, hdcSave, 0, 0, SRCCOPY); + + /* Set the background color of the source DC back to the original + color. */ + SetBkColor(hdcSave, cColor); + + /* Create the inverse of the object mask. */ + BitBlt(hdcBack, 0, 0, s_width, s_height, hdcObject, 0, 0, NOTSRCCOPY); + + /* Copy background to the resulting image */ + StretchBlt(hdcMem, 0, 0, s_width, s_height, hDC, x, y, width, height, SRCCOPY); + + /* Mask out the places where the source image will be placed. */ + BitBlt(hdcMem, 0, 0, s_width, s_height, hdcObject, 0, 0, SRCAND); + + /* Mask out the transparent colored pixels on the source image. */ + BitBlt(hdcSave, 0, 0, s_width, s_height, hdcBack, 0, 0, SRCAND); + + /* XOR the source image with the beckground. */ + BitBlt(hdcMem, 0, 0, s_width, s_height, hdcSave, 0, 0, SRCPAINT); + + /* blt resulting image to the screen */ + StretchBlt( + hDC, + x, y, width, height, hdcMem, + 0, 0, s_width, s_height, SRCCOPY + ); + + /* cleanup */ + DeleteObject(SelectObject(hdcBack, bmBackOld)); + DeleteObject(SelectObject(hdcObject, bmObjectOld)); + DeleteObject(SelectObject(hdcMem, bmMemOld)); + DeleteObject(SelectObject(hdcSave, bmSaveOld)); + + DeleteDC(hdcMem); + DeleteDC(hdcBack); + DeleteDC(hdcObject); + DeleteDC(hdcSave); +} diff --git a/win/win32/mhmap.h b/win/win32/mhmap.h new file mode 100644 index 0000000..c7d7d3a --- /dev/null +++ b/win/win32/mhmap.h @@ -0,0 +1,20 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef MSWINMapWindow_h +#define MSWINMapWindow_h + +#include "winMS.h" +#include "config.h" +#include "global.h" + + +HWND mswin_init_map_window (void); +void mswin_map_stretch(HWND hWnd, LPSIZE lpsz, BOOL redraw); +int mswin_map_mode(HWND hWnd, int mode); + +#define ROGUE_LEVEL_MAP_MODE MAP_MODE_ASCII12x16 + +#define DEF_CLIPAROUND_MARGIN 5 + +#endif /* MSWINMapWindow_h */ diff --git a/win/win32/mhmenu.c b/win/win32/mhmenu.c new file mode 100644 index 0000000..67eb976 --- /dev/null +++ b/win/win32/mhmenu.c @@ -0,0 +1,1367 @@ +/* SCCS Id: @(#)mhmenu.c 3.4 2002/03/06 */ +/* Copyright (c) Alex Kompel, 2002 */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "winMS.h" +#include +#include "resource.h" +#include "mhmenu.h" +#include "mhmain.h" +#include "mhmsg.h" +#include "mhfont.h" + +#define MENU_MARGIN 0 +#define NHMENU_STR_SIZE BUFSZ +#define MIN_TABSTOP_SIZE 8 + +typedef struct mswin_menu_item { + int glyph; + ANY_P identifier; + CHAR_P accelerator; + CHAR_P group_accel; + int attr; + char str[NHMENU_STR_SIZE]; + BOOLEAN_P presel; + int count; + BOOL has_focus; +} NHMenuItem, *PNHMenuItem; + +typedef struct mswin_nethack_menu_window { + int type; /* MENU_TYPE_TEXT or MENU_TYPE_MENU */ + int how; /* for menus: PICK_NONE, PICK_ONE, PICK_ANY */ + + union { + struct menu_list { + int size; /* number of items in items[] */ + int allocated; /* number of allocated slots in items[] */ + PNHMenuItem items; /* menu items */ + char gacc[QBUFSZ]; /* group accelerators */ + BOOL counting; /* counting flag */ + char prompt[QBUFSZ]; /* menu prompt */ + int tab_stop_size; /* for options menu we use tabstops to align option values */ + } menu; + + struct menu_text { + TCHAR* text; + } text; + }; + int result; + int done; + + HBITMAP bmpChecked; + HBITMAP bmpCheckedCount; + HBITMAP bmpNotChecked; +} NHMenuWindow, *PNHMenuWindow; + +extern short glyph2tile[]; + +static WNDPROC wndProcListViewOrig = NULL; +static WNDPROC editControlWndProc = NULL; + +#define NHMENU_IS_SELECTABLE(item) ((item).identifier.a_obj!=NULL) +#define NHMENU_IS_SELECTED(item) ((item).count!=0) + +BOOL CALLBACK MenuWndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK NHMenuListWndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK NHMenuTextWndProc(HWND, UINT, WPARAM, LPARAM); +static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam); +static BOOL onMeasureItem(HWND hWnd, WPARAM wParam, LPARAM lParam); +static BOOL onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam); +static void LayoutMenu(HWND hwnd); +static void SetMenuType(HWND hwnd, int type); +static void SetMenuListType(HWND hwnd, int now); +static HWND GetMenuControl(HWND hwnd); +static void SelectMenuItem(HWND hwndList, PNHMenuWindow data, int item, int count); +static void reset_menu_count(HWND hwndList, PNHMenuWindow data); +static BOOL onListChar(HWND hWnd, HWND hwndList, WORD ch); + +/*-----------------------------------------------------------------------------*/ +HWND mswin_init_menu_window (int type) { + HWND ret; + + ret = CreateDialog( + GetNHApp()->hApp, + MAKEINTRESOURCE(IDD_MENU), + GetNHApp()->hMainWnd, + MenuWndProc + ); + if( !ret ) { + panic("Cannot create menu window"); + } + + SetMenuType(ret, type); + return ret; +} +/*-----------------------------------------------------------------------------*/ +int mswin_menu_window_select_menu (HWND hWnd, int how, MENU_ITEM_P ** _selected) +{ + MSG msg; + PNHMenuWindow data; + int ret_val; + MENU_ITEM_P *selected = NULL; + int i; + char* ap; + + assert( _selected!=NULL ); + *_selected = NULL; + ret_val = -1; + + data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); + + /* set menu type */ + SetMenuListType(hWnd, how); + + /* Ok, now give items a unique accelerators */ + if( data->type == MENU_TYPE_MENU ) { + char next_char = 'a'; + + data->menu.gacc[0] = '\0'; + ap = data->menu.gacc; + for( i=0; imenu.size; i++) { + if( data->menu.items[i].accelerator!=0 ) { + next_char = (char)(data->menu.items[i].accelerator+1); + } else if( NHMENU_IS_SELECTABLE(data->menu.items[i]) ) { + if ( (next_char>='a' && next_char<='z') || + (next_char>='A' && next_char<='Z') ) { + data->menu.items[i].accelerator = next_char; + } else { + if( next_char > 'z' ) next_char = 'A'; + else if ( next_char > 'Z' ) break; + + data->menu.items[i].accelerator = next_char; + } + + next_char ++; + } + + /* collect group accelerators */ + if( data->how != PICK_NONE ) { + if( data->menu.items[i].group_accel && + !strchr(data->menu.gacc, data->menu.items[i].group_accel) ) { + *ap++ = data->menu.items[i].group_accel; + *ap = '\x0'; + } + } + } + + reset_menu_count(NULL, data); + } + + /* activate the menu window */ + GetNHApp()->hPopupWnd = hWnd; + + mswin_layout_main_window(hWnd); + + /* disable game windows */ + EnableWindow(mswin_hwnd_from_winid(WIN_MAP), FALSE); + EnableWindow(mswin_hwnd_from_winid(WIN_MESSAGE), FALSE); + EnableWindow(mswin_hwnd_from_winid(WIN_STATUS), FALSE); + + /* bring menu window on top */ + SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); + + /* go into message loop */ + while( IsWindow(hWnd) && + !data->done && + GetMessage(&msg, NULL, 0, 0)!=0 ) { + if( !IsDialogMessage(hWnd, &msg) ) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + /* get the result */ + if( data->result != -1 ) { + if(how==PICK_NONE) { + if(data->result>=0) ret_val=0; + else ret_val=-1; + } else if(how==PICK_ONE || how==PICK_ANY) { + /* count selected items */ + ret_val = 0; + for(i=0; imenu.size; i++ ) { + if( NHMENU_IS_SELECTABLE(data->menu.items[i]) && + NHMENU_IS_SELECTED(data->menu.items[i]) ) { + ret_val++; + } + } + if( ret_val > 0 ) { + int sel_ind; + + selected = (MENU_ITEM_P*)malloc(ret_val*sizeof(MENU_ITEM_P)); + if( !selected ) panic("out of memory"); + + sel_ind = 0; + for(i=0; imenu.size; i++ ) { + if( NHMENU_IS_SELECTABLE(data->menu.items[i]) && + NHMENU_IS_SELECTED(data->menu.items[i]) ) { + selected[sel_ind].item = data->menu.items[i].identifier; + selected[sel_ind].count = data->menu.items[i].count; + sel_ind++; + } + } + ret_val = sel_ind; + *_selected = selected; + } + } + } + + /* restore window state */ + EnableWindow(mswin_hwnd_from_winid(WIN_MAP), TRUE); + EnableWindow(mswin_hwnd_from_winid(WIN_MESSAGE), TRUE); + EnableWindow(mswin_hwnd_from_winid(WIN_STATUS), TRUE); + + SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_HIDEWINDOW); + GetNHApp()->hPopupWnd = NULL; + mswin_window_mark_dead( mswin_winid_from_handle(hWnd) ); + DestroyWindow(hWnd); + + mswin_layout_main_window(hWnd); + + SetFocus(GetNHApp()->hMainWnd ); + + return ret_val; +} +/*-----------------------------------------------------------------------------*/ +BOOL CALLBACK MenuWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + PNHMenuWindow data; + HWND control; + HDC hdc; + TCHAR title[MAX_LOADSTRING]; + + + data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); + switch (message) + { + case WM_INITDIALOG: + data = (PNHMenuWindow)malloc(sizeof(NHMenuWindow)); + ZeroMemory(data, sizeof(NHMenuWindow)); + data->type = MENU_TYPE_TEXT; + data->how = PICK_NONE; + data->result = 0; + data->done = 0; + data->bmpChecked = LoadBitmap(GetNHApp()->hApp, MAKEINTRESOURCE(IDB_MENU_SEL)); + data->bmpCheckedCount = LoadBitmap(GetNHApp()->hApp, MAKEINTRESOURCE(IDB_MENU_SEL_COUNT)); + data->bmpNotChecked = LoadBitmap(GetNHApp()->hApp, MAKEINTRESOURCE(IDB_MENU_UNSEL)); + SetWindowLong(hWnd, GWL_USERDATA, (LONG)data); + + /* set font for the text cotrol */ + control = GetDlgItem(hWnd, IDC_MENU_TEXT); + hdc = GetDC(control); + SendMessage(control, WM_SETFONT, (WPARAM)mswin_get_font(NHW_MENU, ATR_NONE, hdc, FALSE), (LPARAM)0); + ReleaseDC(control, hdc); + + /* subclass edit control */ + editControlWndProc = (WNDPROC)GetWindowLong(control, GWL_WNDPROC); + SetWindowLong(control, GWL_WNDPROC, (LONG)NHMenuTextWndProc); + + /* Even though the dialog has no caption, you can still set the title + which shows on Alt-Tab */ + LoadString(GetNHApp()->hApp, IDS_APP_TITLE, title, MAX_LOADSTRING); + SetWindowText(hWnd, title); + break; + + case WM_MSNH_COMMAND: + onMSNHCommand(hWnd, wParam, lParam); + break; + + case WM_SIZE: + LayoutMenu(hWnd); + return FALSE; + + case WM_CLOSE: + if (program_state.gameover) { + data->result = -1; + data->done = 1; + program_state.stopprint++; + return TRUE; + } else + return FALSE; + + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDCANCEL: + if( data->type == MENU_TYPE_MENU && + (data->how==PICK_ONE || data->how==PICK_ANY) && + data->menu.counting) { + HWND list; + int i; + + /* reset counter if counting is in progress */ + list = GetMenuControl(hWnd); + i = ListView_GetNextItem(list, -1, LVNI_FOCUSED); + if( i>=0 ) { + SelectMenuItem(list, data, i, 0); + } + return TRUE; + } else { + data->result = -1; + data->done = 1; + } + return TRUE; + + case IDOK: + data->done = 1; + data->result = 0; + return TRUE; + + case IDC_MENU_TEXT: + switch (HIWORD(wParam)) + { + case EN_SETFOCUS: + HideCaret((HWND)lParam); + return TRUE; + } + } + } break; + + case WM_NOTIFY: + { + LPNMHDR lpnmhdr = (LPNMHDR)lParam; + switch (LOWORD(wParam)) { + case IDC_MENU_LIST: + { + if( !data || data->type!=MENU_TYPE_MENU ) break; + + switch(lpnmhdr->code) { + case LVN_ITEMACTIVATE: + { + LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lParam; + if(data->how==PICK_ONE) { + if( lpnmlv->iItem>=0 && + lpnmlv->iItemmenu.size && + NHMENU_IS_SELECTABLE(data->menu.items[lpnmlv->iItem]) ) { + SelectMenuItem( + lpnmlv->hdr.hwndFrom, + data, + lpnmlv->iItem, + -1 + ); + data->done = 1; + data->result = 0; + return TRUE; + } + } + } break; + + case NM_CLICK: { + LPNMLISTVIEW lpnmitem = (LPNMLISTVIEW) lParam; + if( lpnmitem->iItem==-1 ) return 0; + if( data->how==PICK_ANY ) { + SelectMenuItem( + lpnmitem->hdr.hwndFrom, + data, + lpnmitem->iItem, + NHMENU_IS_SELECTED(data->menu.items[lpnmitem->iItem])? 0 : -1 + ); + } + } break; + + case LVN_ITEMCHANGED: + { + LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lParam; + if( lpnmlv->iItem==-1 ) return 0; + if( !(lpnmlv->uChanged & LVIF_STATE) ) return 0; + + if( data->how==PICK_ONE || data->how==PICK_ANY ) { + data->menu.items[lpnmlv->iItem].has_focus = !!(lpnmlv->uNewState & LVIS_FOCUSED); + ListView_RedrawItems(lpnmlv->hdr.hwndFrom, lpnmlv->iItem, lpnmlv->iItem); + } + + /* update count for single-selection menu (follow the listview selection) */ + if( data->how==PICK_ONE ) { + if( lpnmlv->uNewState & LVIS_SELECTED ) { + SelectMenuItem( + lpnmlv->hdr.hwndFrom, + data, + lpnmlv->iItem, + -1 + ); + } + } + + /* check item focus */ + if( data->how==PICK_ONE || data->how==PICK_ANY ) { + data->menu.items[lpnmlv->iItem].has_focus = !!(lpnmlv->uNewState & LVIS_FOCUSED); + ListView_RedrawItems(lpnmlv->hdr.hwndFrom, lpnmlv->iItem, lpnmlv->iItem); + } + } break; + + case NM_KILLFOCUS: + reset_menu_count(lpnmhdr->hwndFrom, data); + break; + + } + } break; + } + } break; + + case WM_SETFOCUS: + if( hWnd!=GetNHApp()->hPopupWnd ) { + SetFocus(GetNHApp()->hPopupWnd ); + } + break; + + case WM_MEASUREITEM: + if( wParam==IDC_MENU_LIST ) + return onMeasureItem(hWnd, wParam, lParam); + else + return FALSE; + + case WM_DRAWITEM: + if( wParam==IDC_MENU_LIST ) + return onDrawItem(hWnd, wParam, lParam); + else + return FALSE; + + case WM_DESTROY: + if( data ) { + DeleteObject(data->bmpChecked); + DeleteObject(data->bmpCheckedCount); + DeleteObject(data->bmpNotChecked); + if( data->type == MENU_TYPE_TEXT ) { + if( data->text.text ) free(data->text.text); + } + free(data); + SetWindowLong(hWnd, GWL_USERDATA, (LONG)0); + } + return TRUE; + } + return FALSE; +} +/*-----------------------------------------------------------------------------*/ +void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + PNHMenuWindow data; + + data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); + switch( wParam ) { + case MSNH_MSG_PUTSTR: + { + PMSNHMsgPutstr msg_data = (PMSNHMsgPutstr)lParam; + HWND text_view; + TCHAR wbuf[BUFSZ]; + size_t text_size; + + if( data->type!=MENU_TYPE_TEXT ) + SetMenuType(hWnd, MENU_TYPE_TEXT); + + if( !data->text.text ) { + text_size = strlen(msg_data->text) + 4; + data->text.text = (TCHAR*)malloc(text_size*sizeof(data->text.text[0])); + ZeroMemory(data->text.text, text_size*sizeof(data->text.text[0])); + } else { + text_size = _tcslen(data->text.text) + strlen(msg_data->text) + 4; + data->text.text = (TCHAR*)realloc(data->text.text, text_size*sizeof(data->text.text[0])); + } + if( !data->text.text ) break; + + _tcscat(data->text.text, NH_A2W(msg_data->text, wbuf, BUFSZ)); + _tcscat(data->text.text, TEXT("\r\n")); + + text_view = GetDlgItem(hWnd, IDC_MENU_TEXT); + if( !text_view ) panic("cannot get text view window"); + SetWindowText(text_view, data->text.text); + } break; + + case MSNH_MSG_STARTMENU: + if( data->type!=MENU_TYPE_MENU ) + SetMenuType(hWnd, MENU_TYPE_MENU); + + if( data->menu.items ) free(data->menu.items); + data->how = PICK_NONE; + data->menu.items = NULL; + data->menu.size = 0; + data->menu.allocated = 0; + data->done = 0; + data->result = 0; + data->menu.tab_stop_size = MIN_TABSTOP_SIZE; + break; + + case MSNH_MSG_ADDMENU: + { + PMSNHMsgAddMenu msg_data = (PMSNHMsgAddMenu)lParam; + char *p, *p1; + int new_item; + + if( data->type!=MENU_TYPE_MENU ) break; + if( strlen(msg_data->str)==0 ) break; + + if( data->menu.size==data->menu.allocated ) { + data->menu.allocated += 10; + data->menu.items = (PNHMenuItem)realloc(data->menu.items, data->menu.allocated*sizeof(NHMenuItem)); + } + + new_item = data->menu.size; + ZeroMemory( &data->menu.items[new_item], sizeof(data->menu.items[new_item])); + data->menu.items[new_item].glyph = msg_data->glyph; + data->menu.items[new_item].identifier = *msg_data->identifier; + data->menu.items[new_item].accelerator = msg_data->accelerator; + data->menu.items[new_item].group_accel = msg_data->group_accel; + data->menu.items[new_item].attr = msg_data->attr; + strncpy(data->menu.items[new_item].str, msg_data->str, NHMENU_STR_SIZE); + data->menu.items[new_item].presel = msg_data->presel; + + /* calculate tabstop size */ + p1 = data->menu.items[new_item].str; + p = strchr(data->menu.items[new_item].str, '\t'); + while( p ) { + data->menu.tab_stop_size = + max( data->menu.tab_stop_size, p - p1 + 1 ); + p1 = p; + p = strchr(p+1, '\t'); + } + + /* increment size */ + data->menu.size++; + } break; + + case MSNH_MSG_ENDMENU: + { + PMSNHMsgEndMenu msg_data = (PMSNHMsgEndMenu)lParam; + if( msg_data->text ) { + strncpy( data->menu.prompt, msg_data->text, sizeof(data->menu.prompt)-1 ); + } else { + ZeroMemory(data->menu.prompt, sizeof(data->menu.prompt)); + } + } break; + + } +} +/*-----------------------------------------------------------------------------*/ +void LayoutMenu(HWND hWnd) +{ + PNHMenuWindow data; + HWND menu_ok; + HWND menu_cancel; + RECT clrt, rt; + POINT pt_elem, pt_ok, pt_cancel; + SIZE sz_elem, sz_ok, sz_cancel; + + data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); + menu_ok = GetDlgItem(hWnd, IDOK); + menu_cancel = GetDlgItem(hWnd, IDCANCEL); + + /* get window coordinates */ + GetClientRect(hWnd, &clrt ); + + /* set window placements */ + GetWindowRect(menu_ok, &rt); + sz_ok.cx = (clrt.right - clrt.left)/2 - 2*MENU_MARGIN; + sz_ok.cy = rt.bottom-rt.top; + pt_ok.x = clrt.left + MENU_MARGIN; + pt_ok.y = clrt.bottom - MENU_MARGIN - sz_ok.cy; + + GetWindowRect(menu_cancel, &rt); + sz_cancel.cx = (clrt.right - clrt.left)/2 - 2*MENU_MARGIN; + sz_cancel.cy = rt.bottom-rt.top; + pt_cancel.x = (clrt.left + clrt.right)/2 + MENU_MARGIN; + pt_cancel.y = clrt.bottom - MENU_MARGIN - sz_cancel.cy; + + pt_elem.x = clrt.left + MENU_MARGIN; + pt_elem.y = clrt.top + MENU_MARGIN; + sz_elem.cx = (clrt.right - clrt.left) - 2*MENU_MARGIN; + sz_elem.cy = min(pt_cancel.y, pt_ok.y) - 2*MENU_MARGIN; + + MoveWindow(GetMenuControl(hWnd), pt_elem.x, pt_elem.y, sz_elem.cx, sz_elem.cy, TRUE ); + MoveWindow(menu_ok, pt_ok.x, pt_ok.y, sz_ok.cx, sz_ok.cy, TRUE ); + MoveWindow(menu_cancel, pt_cancel.x, pt_cancel.y, sz_cancel.cx, sz_cancel.cy, TRUE ); +} +/*-----------------------------------------------------------------------------*/ +void SetMenuType(HWND hWnd, int type) +{ + PNHMenuWindow data; + HWND list, text; + + data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); + + data->type = type; + + text = GetDlgItem(hWnd, IDC_MENU_TEXT); + list = GetDlgItem(hWnd, IDC_MENU_LIST); + if(data->type==MENU_TYPE_TEXT) { + ShowWindow(list, SW_HIDE); + EnableWindow(list, FALSE); + EnableWindow(text, TRUE); + ShowWindow(text, SW_SHOW); + SetFocus(text); + } else { + ShowWindow(text, SW_HIDE); + EnableWindow(text, FALSE); + EnableWindow(list, TRUE); + ShowWindow(list, SW_SHOW); + SetFocus(list); + } + LayoutMenu(hWnd); +} +/*-----------------------------------------------------------------------------*/ +void SetMenuListType(HWND hWnd, int how) +{ + PNHMenuWindow data; + RECT rt; + DWORD dwStyles; + char buf[BUFSZ]; + TCHAR wbuf[BUFSZ]; + int nItem; + int i; + HWND control; + LVCOLUMN lvcol; + LRESULT fnt; + + data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); + if( data->type != MENU_TYPE_MENU ) return; + + data->how = how; + + switch(how) { + case PICK_NONE: + dwStyles = WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_CHILD + | WS_VSCROLL | WS_HSCROLL | LVS_REPORT + | LVS_OWNERDRAWFIXED | LVS_SINGLESEL; + break; + case PICK_ONE: + dwStyles = WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_CHILD + | WS_VSCROLL | WS_HSCROLL | LVS_REPORT + | LVS_OWNERDRAWFIXED | LVS_SINGLESEL; + break; + case PICK_ANY: + dwStyles = WS_VISIBLE | WS_TABSTOP | WS_BORDER | WS_CHILD + | WS_VSCROLL | WS_HSCROLL | LVS_REPORT + | LVS_OWNERDRAWFIXED | LVS_SINGLESEL; + break; + default: panic("how should be one of PICK_NONE, PICK_ONE or PICK_ANY"); + }; + + if( strlen(data->menu.prompt)==0 ) { + dwStyles |= LVS_NOCOLUMNHEADER ; + } + + GetWindowRect(GetDlgItem(hWnd, IDC_MENU_LIST), &rt); + DestroyWindow(GetDlgItem(hWnd, IDC_MENU_LIST)); + control = CreateWindow(WC_LISTVIEW, NULL, + dwStyles, + rt.left, + rt.top, + rt.right - rt.left, + rt.bottom - rt.top, + hWnd, + (HMENU)IDC_MENU_LIST, + GetNHApp()->hApp, + NULL ); + if( !control ) panic( "cannot create menu control" ); + + /* install the hook for the control window procedure */ + wndProcListViewOrig = (WNDPROC)GetWindowLong(control, GWL_WNDPROC); + SetWindowLong(control, GWL_WNDPROC, (LONG)NHMenuListWndProc); + + /* set control font */ + fnt = SendMessage(hWnd, WM_GETFONT, (WPARAM)0, (LPARAM)0); + SendMessage(control, WM_SETFONT, (WPARAM)fnt, (LPARAM)0); + + /* add column to the list view */ + ZeroMemory(&lvcol, sizeof(lvcol)); + lvcol.mask = LVCF_WIDTH | LVCF_TEXT; + lvcol.cx = GetSystemMetrics(SM_CXFULLSCREEN); + lvcol.pszText = NH_A2W(data->menu.prompt, wbuf, BUFSZ); + ListView_InsertColumn(control, 0, &lvcol); + + /* add items to the list view */ + for(i=0; imenu.size; i++ ) { + LVITEM lvitem; + ZeroMemory( &lvitem, sizeof(lvitem) ); + sprintf(buf, "%c - %s", max(data->menu.items[i].accelerator, ' '), data->menu.items[i].str ); + + lvitem.mask = LVIF_PARAM | LVIF_STATE | LVIF_TEXT; + lvitem.iItem = i; + lvitem.iSubItem = 0; + lvitem.state = data->menu.items[i].presel? LVIS_SELECTED : 0; + lvitem.pszText = NH_A2W(buf, wbuf, BUFSZ); + lvitem.lParam = (LPARAM)&data->menu.items[i]; + nItem = SendMessage(control, LB_ADDSTRING, (WPARAM)0, (LPARAM) buf); + if( ListView_InsertItem(control, &lvitem)==-1 ) { + panic("cannot insert menu item"); + } + } + SetFocus(control); +} +/*-----------------------------------------------------------------------------*/ +HWND GetMenuControl(HWND hWnd) +{ + PNHMenuWindow data; + + data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); + + if(data->type==MENU_TYPE_TEXT) { + return GetDlgItem(hWnd, IDC_MENU_TEXT); + } else { + return GetDlgItem(hWnd, IDC_MENU_LIST); + } +} +/*-----------------------------------------------------------------------------*/ +BOOL onMeasureItem(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + LPMEASUREITEMSTRUCT lpmis; + TEXTMETRIC tm; + HGDIOBJ saveFont; + HDC hdc; + PNHMenuWindow data; + RECT list_rect; + + lpmis = (LPMEASUREITEMSTRUCT) lParam; + data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); + GetClientRect(GetMenuControl(hWnd), &list_rect); + + hdc = GetDC(GetMenuControl(hWnd)); + saveFont = SelectObject(hdc, mswin_get_font(NHW_MENU, ATR_INVERSE, hdc, FALSE)); + GetTextMetrics(hdc, &tm); + + /* Set the height of the list box items. */ + lpmis->itemHeight = max(tm.tmHeight, TILE_Y)+2; + lpmis->itemWidth = list_rect.right - list_rect.left; + + SelectObject(hdc, saveFont); + ReleaseDC(GetMenuControl(hWnd), hdc); + return TRUE; +} +/*-----------------------------------------------------------------------------*/ +BOOL onDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + LPDRAWITEMSTRUCT lpdis; + PNHMenuItem item; + PNHMenuWindow data; + TEXTMETRIC tm; + HGDIOBJ saveFont; + HDC tileDC; + short ntile; + int t_x, t_y; + int x, y; + TCHAR wbuf[BUFSZ]; + RECT drawRect; + DRAWTEXTPARAMS dtp; + + lpdis = (LPDRAWITEMSTRUCT) lParam; + + /* If there are no list box items, skip this message. */ + if (lpdis->itemID == -1) return FALSE; + + data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); + + item = &data->menu.items[lpdis->itemID]; + + tileDC = CreateCompatibleDC(lpdis->hDC); + saveFont = SelectObject(lpdis->hDC, mswin_get_font(NHW_MENU, item->attr, lpdis->hDC, FALSE)); + GetTextMetrics(lpdis->hDC, &tm); + + x = lpdis->rcItem.left + 1; + + /* print check mark */ + if( NHMENU_IS_SELECTABLE(*item) ) { + HGDIOBJ saveBmp; + char buf[2]; + + switch(item->count) { + case -1: saveBmp = SelectObject(tileDC, data->bmpChecked); break; + case 0: saveBmp = SelectObject(tileDC, data->bmpNotChecked); break; + default: saveBmp = SelectObject(tileDC, data->bmpCheckedCount); break; + } + + y = (lpdis->rcItem.bottom + lpdis->rcItem.top - TILE_Y) / 2; + BitBlt(lpdis->hDC, x, y, TILE_X, TILE_Y, tileDC, 0, 0, SRCCOPY ); + + x += TILE_X + 5; + + if(item->accelerator!=0) { + buf[0] = item->accelerator; + buf[1] = '\x0'; + + SetRect( &drawRect, x, lpdis->rcItem.top, lpdis->rcItem.right, lpdis->rcItem.bottom ); + DrawText(lpdis->hDC, NH_A2W(buf, wbuf, 2), 1, &drawRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX); + } + x += tm.tmAveCharWidth + tm.tmOverhang + 5; + SelectObject(tileDC, saveBmp); + } else { + x += TILE_X + tm.tmAveCharWidth + tm.tmOverhang + 10; + } + + /* print glyph if present */ + if( item->glyph != NO_GLYPH ) { + HGDIOBJ saveBmp; + + saveBmp = SelectObject(tileDC, GetNHApp()->bmpTiles); + ntile = glyph2tile[ item->glyph ]; + t_x = (ntile % TILES_PER_LINE)*TILE_X; + t_y = (ntile / TILES_PER_LINE)*TILE_Y; + + y = (lpdis->rcItem.bottom + lpdis->rcItem.top - TILE_Y) / 2; + + nhapply_image_transparent( + lpdis->hDC, x, y, TILE_X, TILE_Y, + tileDC, t_x, t_y, TILE_X, TILE_Y, TILE_BK_COLOR ); + SelectObject(tileDC, saveBmp); + } + + x += TILE_X + 5; + + /* draw item text */ + SetRect( &drawRect, x, lpdis->rcItem.top, lpdis->rcItem.right, lpdis->rcItem.bottom ); + + ZeroMemory(&dtp, sizeof(dtp)); + dtp.cbSize = sizeof(dtp); + dtp.iTabLength = max(MIN_TABSTOP_SIZE, data->menu.tab_stop_size); + DrawTextEx(lpdis->hDC, + NH_A2W(item->str, wbuf, BUFSZ), + strlen(item->str), + &drawRect, + DT_LEFT | DT_VCENTER | DT_EXPANDTABS | DT_SINGLELINE | DT_TABSTOP, + &dtp + ); + + /* draw focused item */ + if( item->has_focus ) { + RECT client_rt; + + GetClientRect(lpdis->hwndItem, &client_rt); + if( NHMENU_IS_SELECTABLE(*item) && + data->menu.items[lpdis->itemID].count!=0 && + item->glyph != NO_GLYPH ) { + if( data->menu.items[lpdis->itemID].count==-1 ) { + _stprintf(wbuf, TEXT("Count: All") ); + } else { + _stprintf(wbuf, TEXT("Count: %d"), data->menu.items[lpdis->itemID].count ); + } + + SelectObject(lpdis->hDC, mswin_get_font(NHW_MENU, ATR_BLINK, lpdis->hDC, FALSE)); + + /* calculate text rectangle */ + SetRect( &drawRect, client_rt.left, lpdis->rcItem.top, client_rt.right, lpdis->rcItem.bottom ); + DrawText(lpdis->hDC, wbuf, _tcslen(wbuf), &drawRect, + DT_CALCRECT | DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX ); + + /* erase text rectangle */ + drawRect.left = max(client_rt.left+1, client_rt.right - (drawRect.right - drawRect.left) - 10); + drawRect.right = client_rt.right-1; + drawRect.top = lpdis->rcItem.top; + drawRect.bottom = lpdis->rcItem.bottom; + FillRect(lpdis->hDC, &drawRect, (HBRUSH)GetClassLong(lpdis->hwndItem, GCL_HBRBACKGROUND) ); + + /* draw text */ + DrawText(lpdis->hDC, wbuf, _tcslen(wbuf), &drawRect, + DT_RIGHT | DT_VCENTER | DT_SINGLELINE | DT_NOPREFIX ); + } + + /* draw focus rect */ + SetRect( &drawRect, client_rt.left, lpdis->rcItem.top, client_rt.right, lpdis->rcItem.bottom ); + DrawFocusRect(lpdis->hDC, &drawRect); + } + + SelectObject(lpdis->hDC, saveFont); + DeleteDC(tileDC); + return TRUE; +} +/*-----------------------------------------------------------------------------*/ +BOOL onListChar(HWND hWnd, HWND hwndList, WORD ch) +{ + int i = 0; + PNHMenuWindow data; + int curIndex, topIndex, pageSize; + boolean is_accelerator = FALSE; + + data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); + + switch( ch ) { + case MENU_FIRST_PAGE: + i = 0; + ListView_SetItemState(hwndList, i, LVIS_FOCUSED, LVIS_FOCUSED); + ListView_EnsureVisible(hwndList, i, FALSE); + return -2; + + case MENU_LAST_PAGE: + i = max(0, data->menu.size-1); + ListView_SetItemState(hwndList, i, LVIS_FOCUSED, LVIS_FOCUSED); + ListView_EnsureVisible(hwndList, i, FALSE); + return -2; + + case MENU_NEXT_PAGE: + topIndex = ListView_GetTopIndex( hwndList ); + pageSize = ListView_GetCountPerPage( hwndList ); + curIndex = ListView_GetNextItem(hwndList, -1, LVNI_FOCUSED); + /* Focus down one page */ + i = min(curIndex+pageSize, data->menu.size-1); + ListView_SetItemState(hwndList, i, LVIS_FOCUSED, LVIS_FOCUSED); + /* Scrollpos down one page */ + i = min(topIndex+(2*pageSize - 1), data->menu.size-1); + ListView_EnsureVisible(hwndList, i, FALSE); + return -2; + + case MENU_PREVIOUS_PAGE: + topIndex = ListView_GetTopIndex( hwndList ); + pageSize = ListView_GetCountPerPage( hwndList ); + curIndex = ListView_GetNextItem(hwndList, -1, LVNI_FOCUSED); + /* Focus up one page */ + i = max(curIndex-pageSize, 0); + ListView_SetItemState(hwndList, i, LVIS_FOCUSED, LVIS_FOCUSED); + /* Scrollpos up one page */ + i = max(topIndex-pageSize, 0); + ListView_EnsureVisible(hwndList, i, FALSE); + break; + + case MENU_SELECT_ALL: + if( data->how == PICK_ANY ) { + reset_menu_count(hwndList, data); + for(i=0; imenu.size; i++ ) { + SelectMenuItem(hwndList, data, i, -1); + } + return -2; + } + break; + + case MENU_UNSELECT_ALL: + if( data->how == PICK_ANY ) { + reset_menu_count(hwndList, data); + for(i=0; imenu.size; i++ ) { + SelectMenuItem(hwndList, data, i, 0); + } + return -2; + } + break; + + case MENU_INVERT_ALL: + if( data->how == PICK_ANY ) { + reset_menu_count(hwndList, data); + for(i=0; imenu.size; i++ ) { + SelectMenuItem( + hwndList, + data, + i, + NHMENU_IS_SELECTED(data->menu.items[i])? 0 : -1 + ); + } + return -2; + } + break; + + case MENU_SELECT_PAGE: + if( data->how == PICK_ANY ) { + int from, to; + reset_menu_count(hwndList, data); + topIndex = ListView_GetTopIndex( hwndList ); + pageSize = ListView_GetCountPerPage( hwndList ); + from = max(0, topIndex); + to = min(data->menu.size, from+pageSize); + for(i=from; ihow == PICK_ANY ) { + int from, to; + reset_menu_count(hwndList, data); + topIndex = ListView_GetTopIndex( hwndList ); + pageSize = ListView_GetCountPerPage( hwndList ); + from = max(0, topIndex); + to = min(data->menu.size, from+pageSize); + for(i=from; ihow == PICK_ANY ) { + int from, to; + reset_menu_count(hwndList, data); + topIndex = ListView_GetTopIndex( hwndList ); + pageSize = ListView_GetCountPerPage( hwndList ); + from = max(0, topIndex); + to = min(data->menu.size, from+pageSize); + for(i=from; imenu.items[i])? 0 : -1 + ); + } + return -2; + } + break; + + case MENU_SEARCH: + if( data->how==PICK_ANY || data->how==PICK_ONE ) { + char buf[BUFSZ]; + + reset_menu_count(hwndList, data); + mswin_getlin("Search for:", buf); + if (!*buf || *buf == '\033') return -2; + for(i=0; imenu.size; i++ ) { + if( NHMENU_IS_SELECTABLE(data->menu.items[i]) + && strstr(data->menu.items[i].str, buf) ) { + if (data->how == PICK_ANY) { + SelectMenuItem( + hwndList, + data, + i, + NHMENU_IS_SELECTED(data->menu.items[i])? 0 : -1 + ); + } else if( data->how == PICK_ONE ) { + SelectMenuItem( + hwndList, + data, + i, + -1 + ); + ListView_SetItemState(hwndList, i, LVIS_FOCUSED, LVIS_FOCUSED); + ListView_EnsureVisible(hwndList, i, FALSE); + break; + } + } + } + } else { + mswin_nhbell(); + } + return -2; + + case ' ': + { + if (GetNHApp()->regNetHackMode) { + /* NetHack mode: Scroll down one page, + ends menu when on last page. */ + SCROLLINFO si; + + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE; + GetScrollInfo(hwndList, SB_VERT, &si); + if ((si.nPos + (int)si.nPage) > (si.nMax - si.nMin)) { + /* We're at the bottom: dismiss. */ + data->done = 1; + data->result = 0; + return -2; + } + /* We're not at the bottom: page down. */ + topIndex = ListView_GetTopIndex( hwndList ); + pageSize = ListView_GetCountPerPage( hwndList ); + curIndex = ListView_GetNextItem(hwndList, -1, LVNI_FOCUSED); + /* Focus down one page */ + i = min(curIndex+pageSize, data->menu.size-1); + ListView_SetItemState(hwndList, i, LVIS_FOCUSED, LVIS_FOCUSED); + /* Scrollpos down one page */ + i = min(topIndex+(2*pageSize - 1), data->menu.size-1); + ListView_EnsureVisible(hwndList, i, FALSE); + + return -2; + } else { + /* Windows mode: ends menu for PICK_ONE/PICK_NONE + select item for PICK_ANY */ + if( data->how==PICK_ONE || data->how==PICK_NONE ) { + data->done = 1; + data->result = 0; + return -2; + } else if( data->how==PICK_ANY ) { + i = ListView_GetNextItem(hwndList, -1, LVNI_FOCUSED); + if( i>=0 ) { + SelectMenuItem( + hwndList, + data, + i, + NHMENU_IS_SELECTED(data->menu.items[i])? 0 : -1 + ); + } + } + } + } + break; + + default: + if( strchr(data->menu.gacc, ch) && + !(ch=='0' && data->menu.counting) ) { + /* matched a group accelerator */ + if (data->how == PICK_ANY || data->how == PICK_ONE) { + reset_menu_count(hwndList, data); + for(i=0; imenu.size; i++ ) { + if( NHMENU_IS_SELECTABLE(data->menu.items[i]) && + data->menu.items[i].group_accel == ch ) { + if( data->how == PICK_ANY ) { + SelectMenuItem( + hwndList, + data, + i, + NHMENU_IS_SELECTED(data->menu.items[i])? 0 : -1 + ); + } else if( data->how == PICK_ONE ) { + SelectMenuItem( + hwndList, + data, + i, + -1 + ); + data->result = 0; + data->done = 1; + return -2; + } + } + } + return -2; + } else { + mswin_nhbell(); + return -2; + } + } + + if (isdigit(ch)) { + int count; + i = ListView_GetNextItem(hwndList, -1, LVNI_FOCUSED); + if( i>=0 ) { + count = data->menu.items[i].count; + if( count==-1 ) count=0; + count *= 10L; + count += (int)(ch - '0'); + if (count != 0) /* ignore leading zeros */ { + data->menu.counting = TRUE; + data->menu.items[i].count = min(100000, count); + ListView_RedrawItems( hwndList, i, i ); /* update count mark */ + } + } + return -2; + } + + is_accelerator = FALSE; + for(i=0; imenu.size; i++) { + if( data->menu.items[i].accelerator == ch ) { + is_accelerator = TRUE; + break; + } + } + + if( (ch>='a' && ch<='z') || + (ch>='A' && ch<='Z') || is_accelerator) { + if (data->how == PICK_ANY || data->how == PICK_ONE) { + for(i=0; imenu.size; i++ ) { + if( data->menu.items[i].accelerator == ch ) { + if( data->how == PICK_ANY ) { + SelectMenuItem( + hwndList, + data, + i, + NHMENU_IS_SELECTED(data->menu.items[i])? 0 : -1 + ); + ListView_SetItemState(hwndList, i, LVIS_FOCUSED, LVIS_FOCUSED); + ListView_EnsureVisible(hwndList, i, FALSE); + return -2; + } else if( data->how == PICK_ONE ) { + SelectMenuItem( + hwndList, + data, + i, + -1 + ); + data->result = 0; + data->done = 1; + return -2; + } + } + } + } + } + break; + } + + reset_menu_count(hwndList, data); + return -1; +} +/*-----------------------------------------------------------------------------*/ +void mswin_menu_window_size (HWND hWnd, LPSIZE sz) +{ + TEXTMETRIC tm; + HWND control; + HGDIOBJ saveFont; + HDC hdc; + PNHMenuWindow data; + int i; + RECT rt; + TCHAR wbuf[BUFSZ]; + + GetClientRect(hWnd, &rt); + sz->cx = rt.right - rt.left; + sz->cy = rt.bottom - rt.top; + + data = (PNHMenuWindow)GetWindowLong(hWnd, GWL_USERDATA); + if(data) { + control = GetMenuControl(hWnd); + hdc = GetDC(control); + + if( data->type==MENU_TYPE_MENU ) { + /* Calculate the width of the list box. */ + saveFont = SelectObject(hdc, mswin_get_font(NHW_MENU, ATR_NONE, hdc, FALSE)); + GetTextMetrics(hdc, &tm); + for(i=0; imenu.size; i++ ) { + DRAWTEXTPARAMS dtp; + RECT drawRect; + + SetRect(&drawRect, 0, 0, 1, 1); + ZeroMemory(&dtp, sizeof(dtp)); + dtp.cbSize = sizeof(dtp); + dtp.iTabLength = max(MIN_TABSTOP_SIZE, data->menu.tab_stop_size); + DrawTextEx(hdc, + NH_A2W(data->menu.items[i].str, wbuf, BUFSZ), + strlen(data->menu.items[i].str), + &drawRect, + DT_CALCRECT | DT_LEFT | DT_VCENTER | DT_EXPANDTABS | DT_SINGLELINE | DT_TABSTOP, + &dtp + ); + + sz->cx = max(sz->cx, + (LONG)(2*TILE_X + (drawRect.right - drawRect.left) + tm.tmAveCharWidth*12 + tm.tmOverhang)); + } + SelectObject(hdc, saveFont); + } else { + /* Calculate the width of the text box. */ + RECT text_rt; + saveFont = SelectObject(hdc, mswin_get_font(NHW_MENU, ATR_NONE, hdc, FALSE)); + GetTextMetrics(hdc, &tm); + SetRect(&text_rt, 0, 0, sz->cx, sz->cy); + DrawText(hdc, data->text.text, _tcslen(data->text.text), &text_rt, DT_CALCRECT | DT_TOP | DT_LEFT | DT_NOPREFIX); + sz->cx = max(sz->cx, text_rt.right - text_rt.left + 5*tm.tmAveCharWidth + tm.tmOverhang); + SelectObject(hdc, saveFont); + } + sz->cx += GetSystemMetrics(SM_CXVSCROLL) + 2*GetSystemMetrics(SM_CXSIZEFRAME); + + ReleaseDC(control, hdc); + } +} +/*-----------------------------------------------------------------------------*/ +void SelectMenuItem(HWND hwndList, PNHMenuWindow data, int item, int count) +{ + int i; + + if( item<0 || item>=data->menu.size ) return; + + if( data->how==PICK_ONE && count!=0 ) { + for(i=0; imenu.size; i++) + if( item!=i && data->menu.items[i].count!=0 ) { + data->menu.items[i].count = 0; + ListView_RedrawItems( hwndList, i, i ); + }; + } + + data->menu.items[item].count = count; + ListView_RedrawItems( hwndList, item, item ); + reset_menu_count(hwndList, data); +} +/*-----------------------------------------------------------------------------*/ +void reset_menu_count(HWND hwndList, PNHMenuWindow data) +{ + int i; + data->menu.counting = FALSE; + if( IsWindow(hwndList) ) { + i = ListView_GetNextItem((hwndList), -1, LVNI_FOCUSED); + if( i>=0 ) ListView_RedrawItems( hwndList, i, i ); + } +} +/*-----------------------------------------------------------------------------*/ +/* List window Proc */ +LRESULT CALLBACK NHMenuListWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + BOOL bUpdateFocusItem; + + bUpdateFocusItem = FALSE; + + switch(message) { + + /* filter keyboard input for the control */ + case WM_KEYDOWN: + case WM_KEYUP: { + MSG msg; + BOOL processed; + + processed = FALSE; + if( PeekMessage(&msg, hWnd, WM_CHAR, WM_CHAR, PM_REMOVE) ) { + if( onListChar(GetParent(hWnd), hWnd, (char)msg.wParam)==-2 ) { + processed = TRUE; + } + } + if( processed ) return 0; + + if( wParam==VK_LEFT || wParam==VK_RIGHT ) + bUpdateFocusItem = TRUE; + } break; + + case WM_SIZE: + case WM_HSCROLL: + bUpdateFocusItem = TRUE; + break; + + } + + if( bUpdateFocusItem ) { + int i; + RECT rt; + + /* invalidate the focus rectangle */ + i = ListView_GetNextItem(hWnd, -1, LVNI_FOCUSED); + if( i!=-1 ) { + ListView_GetItemRect(hWnd, i, &rt, LVIR_BOUNDS); + InvalidateRect(hWnd, &rt, TRUE); + } + } + + if( wndProcListViewOrig ) + return CallWindowProc(wndProcListViewOrig, hWnd, message, wParam, lParam); + else + return 0; +} +/*-----------------------------------------------------------------------------*/ +/* Text control window proc - implements scrolling without a cursor */ +LRESULT CALLBACK NHMenuTextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) { + + case WM_KEYDOWN: + switch (wParam) + { + /* close on space in Windows mode + page down on space in NetHack mode */ + case VK_SPACE: + { + SCROLLINFO si; + + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE; + GetScrollInfo(hWnd, SB_VERT, &si); + /* If nethackmode and not at the end of the list */ + if (GetNHApp()->regNetHackMode && + (si.nPos + (int)si.nPage) <= (si.nMax - si.nMin)) + SendMessage(hWnd, EM_SCROLL, SB_PAGEDOWN, 0); + else + PostMessage(GetParent(hWnd), WM_COMMAND, MAKELONG(IDOK, 0), 0); + return 0; + } + case VK_NEXT: + SendMessage(hWnd, EM_SCROLL, SB_PAGEDOWN, 0); + return 0; + case VK_PRIOR: + SendMessage(hWnd, EM_SCROLL, SB_PAGEUP, 0); + return 0; + case VK_UP: + SendMessage(hWnd, EM_SCROLL, SB_LINEUP, 0); + return 0; + case VK_DOWN: + SendMessage(hWnd, EM_SCROLL, SB_LINEDOWN, 0); + return 0; + + } + break; + + } + + if( editControlWndProc ) + return CallWindowProc(editControlWndProc, hWnd, message, wParam, lParam); + else + return 0; +} +/*-----------------------------------------------------------------------------*/ diff --git a/win/win32/mhmenu.h b/win/win32/mhmenu.h new file mode 100644 index 0000000..aa9a90d --- /dev/null +++ b/win/win32/mhmenu.h @@ -0,0 +1,18 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef MSWINMenuWindow_h +#define MSWINMenuWindow_h + +#include "winMS.h" +#include "config.h" +#include "global.h" + +#define MENU_TYPE_TEXT 1 +#define MENU_TYPE_MENU 2 + +HWND mswin_init_menu_window ( int type ); +int mswin_menu_window_select_menu (HWND hwnd, int how, MENU_ITEM_P **); +void mswin_menu_window_size (HWND hwnd, LPSIZE sz); + +#endif /* MSWINTextWindow_h */ diff --git a/win/win32/mhmsg.h b/win/win32/mhmsg.h new file mode 100644 index 0000000..1d08b89 --- /dev/null +++ b/win/win32/mhmsg.h @@ -0,0 +1,61 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef MHNethackMessages_H +#define MHNethackMessages_H + +/* nethack messages */ +#define WM_MSNH_COMMAND (WM_APP+1) + +#define MSNH_MSG_ADDWND 100 +#define MSNH_MSG_PUTSTR 101 +#define MSNH_MSG_PRINT_GLYPH 102 +#define MSNH_MSG_CLEAR_WINDOW 103 +#define MSNH_MSG_CLIPAROUND 104 +#define MSNH_MSG_STARTMENU 105 +#define MSNH_MSG_ADDMENU 106 +#define MSNH_MSG_CURSOR 107 +#define MSNH_MSG_ENDMENU 108 +#define MSNH_MSG_DIED 109 + +typedef struct mswin_nhmsg_add_wnd { + winid wid; +} MSNHMsgAddWnd, *PMSNHMsgAddWnd; + +typedef struct mswin_nhmsg_putstr { + int attr; + const char* text; + boolean append; +} MSNHMsgPutstr, *PMSNHMsgPutstr; + +typedef struct mswin_nhmsg_print_glyph { + XCHAR_P x; + XCHAR_P y; + int glyph; +} MSNHMsgPrintGlyph, *PMSNHMsgPrintGlyph; + +typedef struct mswin_nhmsg_cliparound { + int x; + int y; +} MSNHMsgClipAround, *PMSNHMsgClipAround; + +typedef struct mswin_nhmsg_add_menu { + int glyph; + const ANY_P* identifier; + CHAR_P accelerator; + CHAR_P group_accel; + int attr; + const char * str; + BOOLEAN_P presel; +} MSNHMsgAddMenu, *PMSNHMsgAddMenu; + +typedef struct mswin_nhmsg_cursor { + int x; + int y; +} MSNHMsgCursor, *PMSNHMsgCursor; + +typedef struct mswin_nhmsg_end_menu { + const char* text; +} MSNHMsgEndMenu, *PMSNHMsgEndMenu; + +#endif diff --git a/win/win32/mhmsgwnd.c b/win/win32/mhmsgwnd.c new file mode 100644 index 0000000..6c397ad --- /dev/null +++ b/win/win32/mhmsgwnd.c @@ -0,0 +1,540 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "winMS.h" +#include "mhmsgwnd.h" +#include "mhmsg.h" +#include "mhfont.h" + +#define MSG_WRAP_TEXT + +#define MSG_VISIBLE_LINES max(iflags.wc_vary_msgcount, 2) +#define MAX_MSG_LINES 32 +#define MSG_LINES (int)min(iflags.msg_history, MAX_MSG_LINES) +#define MAXWINDOWTEXT 200 + +#define DEFAULT_COLOR_BG_MSG COLOR_WINDOW +#define DEFAULT_COLOR_FG_MSG COLOR_WINDOWTEXT + +struct window_line { + int attr; + char text[MAXWINDOWTEXT]; +}; + +typedef struct mswin_nethack_message_window { + size_t max_text; + struct window_line window_text[MAX_MSG_LINES]; + + int xChar; /* horizontal scrolling unit */ + int yChar; /* vertical scrolling unit */ + int xUpper; /* average width of uppercase letters */ + int xPos; /* current horizontal scrolling position */ + int yPos; /* current vertical scrolling position */ + int xMax; /* maximum horizontal scrolling position */ + int yMax; /* maximum vertical scrolling position */ + int xPage; /* page size of horizontal scroll bar */ + } NHMessageWindow, *PNHMessageWindow; + +static TCHAR szMessageWindowClass[] = TEXT("MSNHMessageWndClass"); +LRESULT CALLBACK NHMessageWndProc(HWND, UINT, WPARAM, LPARAM); +static void register_message_window_class(void); +static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam); +static void onMSNH_VScroll(HWND hWnd, WPARAM wParam, LPARAM lParam); +#ifndef MSG_WRAP_TEXT +static void onMSNH_HScroll(HWND hWnd, WPARAM wParam, LPARAM lParam); +#endif +static void onPaint(HWND hWnd); +static void onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam); +static HDC prepareDC( HDC hdc ); + +HWND mswin_init_message_window () { + static int run_once = 0; + HWND ret; + DWORD style; + + if( !run_once ) { + register_message_window_class( ); + run_once = 1; + } + +#ifdef MSG_WRAP_TEXT + style = WS_CHILD | WS_CLIPSIBLINGS | WS_VSCROLL; +#else + style = WS_CHILD | WS_CLIPSIBLINGS | WS_VSCROLL | WS_HSCROLL; +#endif + + ret = CreateWindowEx( + WS_EX_CLIENTEDGE, + szMessageWindowClass, /* registered class name */ + NULL, /* window name */ + style, /* window style */ + 0, /* horizontal position of window */ + 0, /* vertical position of window */ + 0, /* window width */ + 0, /* window height - set it later */ + GetNHApp()->hMainWnd, /* handle to parent or owner window */ + NULL, /* menu handle or child identifier */ + GetNHApp()->hApp, /* handle to application instance */ + NULL ); /* window-creation data */ + + if( !ret ) panic("Cannot create message window"); + + return ret; +} + +void register_message_window_class() +{ + WNDCLASS wcex; + ZeroMemory( &wcex, sizeof(wcex)); + + wcex.style = CS_NOCLOSE; + wcex.lpfnWndProc = (WNDPROC)NHMessageWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = GetNHApp()->hApp; + wcex.hIcon = NULL; + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = message_bg_brush ? message_bg_brush : SYSCLR_TO_BRUSH(DEFAULT_COLOR_BG_MSG); + wcex.lpszMenuName = NULL; + wcex.lpszClassName = szMessageWindowClass; + + RegisterClass(&wcex); +} + +LRESULT CALLBACK NHMessageWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_CREATE: + onCreate( hWnd, wParam, lParam ); + break; + + case WM_MSNH_COMMAND: + onMSNHCommand(hWnd, wParam, lParam); + break; + + case WM_PAINT: + onPaint(hWnd); + break; + + case WM_SETFOCUS: + SetFocus(GetNHApp()->hMainWnd); + break; + +#ifndef MSG_WRAP_TEXT + case WM_HSCROLL: + onMSNH_HScroll(hWnd, wParam, lParam); + break; +#endif + + case WM_VSCROLL: + onMSNH_VScroll(hWnd, wParam, lParam); + break; + + case WM_DESTROY: + { + PNHMessageWindow data; + data = (PNHMessageWindow)GetWindowLong(hWnd, GWL_USERDATA); + free(data); + SetWindowLong(hWnd, GWL_USERDATA, (LONG)0); + } break; + + case WM_SIZE: + { + SCROLLINFO si; + int xNewSize; + int yNewSize; + PNHMessageWindow data; + + data = (PNHMessageWindow)GetWindowLong(hWnd, GWL_USERDATA); + + xNewSize = LOWORD(lParam); + yNewSize = HIWORD(lParam); + + if( xNewSize>0 || yNewSize>0 ) { + +#ifndef MSG_WRAP_TEXT + data->xPage = xNewSize/data->xChar; + data->xMax = max(0, (int)(1 + data->max_text - data->xPage)); + data->xPos = min(data->xPos, data->xMax); + + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; + si.nMin = 0; + si.nMax = data->max_text; + si.nPage = data->xPage; + si.nPos = data->xPos; + SetScrollInfo(hWnd, SB_HORZ, &si, TRUE); +#endif + + data->yMax = MSG_LINES - MSG_VISIBLE_LINES - 1; + data->yPos = min(data->yPos, data->yMax); + + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS; + si.nMin = 0; + si.nMax = MSG_LINES; + si.nPage = MSG_VISIBLE_LINES; + si.nPos = data->yPos; + SetScrollInfo(hWnd, SB_VERT, &si, TRUE); + } + } + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + PNHMessageWindow data; + + data = (PNHMessageWindow)GetWindowLong(hWnd, GWL_USERDATA); + switch( wParam ) { + case MSNH_MSG_PUTSTR: + { + PMSNHMsgPutstr msg_data = (PMSNHMsgPutstr)lParam; + SCROLLINFO si; + char* p; + + if( msg_data->append ) { + strncat(data->window_text[MSG_LINES-1].text, msg_data->text, + MAXWINDOWTEXT - strlen(data->window_text[MSG_LINES-1].text)); + } else { + /* check if the string is empty */ + for(p = data->window_text[MSG_LINES-1].text; *p && isspace(*p); p++); + + if( *p ) { + /* last string is not empty - scroll up */ + memmove(&data->window_text[0], + &data->window_text[1], + (MSG_LINES-1)*sizeof(data->window_text[0])); + } + + /* append new text to the end of the array */ + data->window_text[MSG_LINES-1].attr = msg_data->attr; + strncpy(data->window_text[MSG_LINES-1].text, msg_data->text, MAXWINDOWTEXT); + } + + /* reset V-scroll position to display new text */ + data->yPos = data->yMax; + + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = data->yPos; + SetScrollInfo(hWnd, SB_VERT, &si, TRUE); + + /* update window content */ + InvalidateRect(hWnd, NULL, TRUE); + } + break; + + case MSNH_MSG_CLEAR_WINDOW: + { + MSNHMsgPutstr data; + + /* append an empty line to the message window (send message to itself) */ + data.attr = ATR_NONE; + data.text = " "; + onMSNHCommand(hWnd, (WPARAM)MSNH_MSG_PUTSTR, (LPARAM)&data); + + InvalidateRect(hWnd, NULL, TRUE); + break; + } + } +} + +void onMSNH_VScroll(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + PNHMessageWindow data; + SCROLLINFO si; + int yInc; + + /* get window data */ + data = (PNHMessageWindow)GetWindowLong(hWnd, GWL_USERDATA); + + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_POS; + GetScrollInfo(hWnd, SB_VERT, &si); + + switch(LOWORD (wParam)) + { + // User clicked the shaft above the scroll box. + + case SB_PAGEUP: + yInc = -(int)si.nPage; + break; + + // User clicked the shaft below the scroll box. + + case SB_PAGEDOWN: + yInc = si.nPage; + break; + + // User clicked the top arrow. + + case SB_LINEUP: + yInc = -1; + break; + + // User clicked the bottom arrow. + + case SB_LINEDOWN: + yInc = 1; + break; + + // User dragged the scroll box. + + case SB_THUMBTRACK: + yInc = HIWORD(wParam) - data->yPos; + break; + + default: + yInc = 0; + } + + // If applying the vertical scrolling increment does not + // take the scrolling position out of the scrolling range, + // increment the scrolling position, adjust the position + // of the scroll box, and update the window. UpdateWindow + // sends the WM_PAINT message. + + if (yInc = max(-data->yPos, min(yInc, data->yMax - data->yPos))) + { + data->yPos += yInc; + /* ScrollWindowEx(hWnd, 0, -data->yChar * yInc, + (CONST RECT *) NULL, (CONST RECT *) NULL, + (HRGN) NULL, (LPRECT) NULL, SW_INVALIDATE | SW_ERASE); + */ + InvalidateRect(hWnd, NULL, TRUE); + + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = data->yPos; + SetScrollInfo(hWnd, SB_VERT, &si, TRUE); + + UpdateWindow (hWnd); + } +} + +#ifndef MSG_WRAP_TEXT +void onMSNH_HScroll(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + PNHMessageWindow data; + SCROLLINFO si; + int xInc; + + /* get window data */ + data = (PNHMessageWindow)GetWindowLong(hWnd, GWL_USERDATA); + + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE; + GetScrollInfo(hWnd, SB_HORZ, &si); + + switch(LOWORD (wParam)) + { + // User clicked shaft left of the scroll box. + + case SB_PAGEUP: + xInc = - (int)si.nPage; + break; + + // User clicked shaft right of the scroll box. + + case SB_PAGEDOWN: + xInc = si.nPage; + break; + + // User clicked the left arrow. + + case SB_LINEUP: + xInc = -1; + break; + + // User clicked the right arrow. + + case SB_LINEDOWN: + xInc = 1; + break; + + // User dragged the scroll box. + + case SB_THUMBTRACK: + xInc = HIWORD(wParam) - data->xPos; + break; + + default: + xInc = 0; + + } + + + // If applying the horizontal scrolling increment does not + // take the scrolling position out of the scrolling range, + // increment the scrolling position, adjust the position + // of the scroll box, and update the window. + + if (xInc = max (-data->xPos, min (xInc, data->xMax - data->xPos))) + { + data->xPos += xInc; + ScrollWindowEx (hWnd, -data->xChar * xInc, 0, + (CONST RECT *) NULL, (CONST RECT *) NULL, + (HRGN) NULL, (LPRECT) NULL, SW_INVALIDATE | SW_ERASE); + + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = data->xPos; + SetScrollInfo(hWnd, SB_HORZ, &si, TRUE); + UpdateWindow (hWnd); + } +} +#endif // MSG_WRAP_TEXT + +void onPaint(HWND hWnd) +{ + PAINTSTRUCT ps; + HDC hdc; + PNHMessageWindow data; + RECT client_rt, draw_rt; + int FirstLine, LastLine; + int i, x, y; + HGDIOBJ oldFont; + TCHAR wbuf[MAXWINDOWTEXT+2]; + size_t wlen; + COLORREF OldBg, OldFg; + + hdc = BeginPaint(hWnd, &ps); + + OldBg = SetBkColor(hdc, message_bg_brush ? message_bg_color : (COLORREF)GetSysColor(DEFAULT_COLOR_BG_MSG)); + OldFg = SetTextColor(hdc, message_fg_brush ? message_fg_color : (COLORREF)GetSysColor(DEFAULT_COLOR_FG_MSG)); + + data = (PNHMessageWindow)GetWindowLong(hWnd, GWL_USERDATA); + + GetClientRect(hWnd, &client_rt); + + if( !IsRectEmpty(&ps.rcPaint) ) { + FirstLine = max (0, data->yPos + ps.rcPaint.top/data->yChar - 1); + LastLine = min (MSG_LINES-1, data->yPos + ps.rcPaint.bottom/data->yChar); + y = min( ps.rcPaint.bottom, client_rt.bottom - 2); + for (i=LastLine; i>=FirstLine; i--) { + if( i==MSG_LINES-1 ) { + x = data->xChar * (2 - data->xPos); + } else { + x = data->xChar * (4 - data->xPos); + } + + if( strlen(data->window_text[i].text)>0 ) { + /* convert to UNICODE */ + NH_A2W(data->window_text[i].text, wbuf, sizeof(wbuf)); + wlen = _tcslen(wbuf); + + /* calculate text height */ + draw_rt.left = x; + draw_rt.right = client_rt.right; + draw_rt.top = y - data->yChar; + draw_rt.bottom = y; + + oldFont = SelectObject(hdc, mswin_get_font(NHW_MESSAGE, data->window_text[i].attr, hdc, FALSE)); + +#ifdef MSG_WRAP_TEXT + DrawText(hdc, wbuf, wlen, &draw_rt, DT_NOPREFIX | DT_WORDBREAK | DT_CALCRECT); + draw_rt.top = y - (draw_rt.bottom - draw_rt.top); + draw_rt.bottom = y; + DrawText(hdc, wbuf, wlen, &draw_rt, DT_NOPREFIX | DT_WORDBREAK); +#else + DrawText(hdc, wbuf, wlen, &draw_rt, DT_NOPREFIX ); +#endif + SelectObject(hdc, oldFont); + + y -= draw_rt.bottom - draw_rt.top; + } else { + y -= data->yChar; + } + + /* highligh the last line */ + if( i==MSG_LINES-1 ) { + draw_rt.left = client_rt.left; + draw_rt.right = draw_rt.left + 2*data->xChar; + DrawText(hdc, TEXT("> "), 2, &draw_rt, DT_NOPREFIX ); + + y -= 2; + draw_rt.left = client_rt.left; + draw_rt.right = client_rt.right; + draw_rt.top -= 2; + draw_rt.bottom = client_rt.bottom; + DrawEdge(hdc, &draw_rt, EDGE_SUNKEN, BF_TOP | BF_ADJUST); + DrawEdge(hdc, &draw_rt, EDGE_SUNKEN, BF_BOTTOM | BF_ADJUST); + } + } + } + + SetTextColor (hdc, OldFg); + SetBkColor (hdc, OldBg); + EndPaint(hWnd, &ps); +} + +void onCreate(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + HDC hdc; + TEXTMETRIC tm; + PNHMessageWindow data; + HGDIOBJ saveFont; + + /* set window data */ + data = (PNHMessageWindow)malloc(sizeof(NHMessageWindow)); + if( !data ) panic("out of memory"); + ZeroMemory(data, sizeof(NHMessageWindow)); + data->max_text = MAXWINDOWTEXT; + SetWindowLong(hWnd, GWL_USERDATA, (LONG)data); + + /* Get the handle to the client area's device context. */ + hdc = prepareDC( GetDC(hWnd) ); + saveFont = SelectObject(hdc, mswin_get_font(NHW_MESSAGE, ATR_NONE, hdc, FALSE)); + + /* Extract font dimensions from the text metrics. */ + GetTextMetrics (hdc, &tm); + data->xChar = tm.tmAveCharWidth; + data->xUpper = (tm.tmPitchAndFamily & 1 ? 3 : 2) * data->xChar/2; + data->yChar = tm.tmHeight + tm.tmExternalLeading; + data->xPage = 1; + + /* Free the device context. */ + SelectObject(hdc, saveFont); + ReleaseDC (hWnd, hdc); +} + +HDC prepareDC( HDC hdc ) +{ + // set font here + return hdc; +} + + +void mswin_message_window_size (HWND hWnd, LPSIZE sz) +{ + PNHMessageWindow data; + RECT rt, client_rt; + + GetWindowRect(hWnd, &rt); + + sz->cx = rt.right - rt.left; + sz->cy = rt.bottom - rt.top; + + data = (PNHMessageWindow)GetWindowLong(hWnd, GWL_USERDATA); + if(data) { + /* set size to accomodate MSG_VISIBLE_LINES, highligh rectangle and + horizontal scroll bar (difference between window rect and client rect */ + GetClientRect(hWnd, &client_rt); + sz->cy = sz->cy-(client_rt.bottom - client_rt.top) + + data->yChar * MSG_VISIBLE_LINES + 4; + } +} \ No newline at end of file diff --git a/win/win32/mhmsgwnd.h b/win/win32/mhmsgwnd.h new file mode 100644 index 0000000..a4f6736 --- /dev/null +++ b/win/win32/mhmsgwnd.h @@ -0,0 +1,15 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef MSWINMessageWindow_h +#define MSWINMessageWindow_h + +#include "winMS.h" +#include "config.h" +#include "global.h" + +HWND mswin_init_message_window (void); +void mswin_message_window_size (HWND hWnd, LPSIZE sz); + + +#endif /* MSWINMessageWindow_h */ diff --git a/win/win32/mhrip.c b/win/win32/mhrip.c new file mode 100644 index 0000000..69f4916 --- /dev/null +++ b/win/win32/mhrip.c @@ -0,0 +1,265 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "winMS.h" +#include "resource.h" +#include "mhrip.h" +#include "mhmsg.h" +#include "mhfont.h" + +#define RIP_WIDTH 400 +#define RIP_HEIGHT 200 + +#define RIP_GRAVE_HEIGHT 120 +#define RIP_GRAVE_WIDTH 115 +#define RIP_GRAVE_X 90 +#define RIP_GRAVE_Y 60 + +#define RIP_OFFSET_X 10 +#define RIP_OFFSET_Y 10 + +PNHWinApp GetNHApp(void); + +typedef struct mswin_nethack_text_window { + HANDLE rip_bmp; + TCHAR* window_text; + TCHAR* rip_text; +} NHRIPWindow, *PNHRIPWindow; + +BOOL CALLBACK NHRIPWndProc(HWND, UINT, WPARAM, LPARAM); +static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam); + +HWND mswin_init_RIP_window () { + HWND ret; + PNHRIPWindow data; + + ret = CreateDialog( + GetNHApp()->hApp, + MAKEINTRESOURCE(IDD_NHRIP), + GetNHApp()->hMainWnd, + NHRIPWndProc + ); + if( !ret ) panic("Cannot create rip window"); + + data = (PNHRIPWindow)malloc(sizeof(NHRIPWindow)); + if( !data ) panic("out of memory"); + + ZeroMemory(data, sizeof(NHRIPWindow)); + SetWindowLong(ret, GWL_USERDATA, (LONG)data); + return ret; +} + +void mswin_display_RIP_window (HWND hWnd) +{ + MSG msg; + RECT rt; + PNHRIPWindow data; + HWND mapWnd; + RECT riprt; + RECT clientrect; + RECT textrect; + HDC hdc; + HFONT OldFont; + + data = (PNHRIPWindow)GetWindowLong(hWnd, GWL_USERDATA); + + GetNHApp()->hPopupWnd = hWnd; + mapWnd = mswin_hwnd_from_winid(WIN_MAP); + if( !IsWindow(mapWnd) ) mapWnd = GetNHApp()->hMainWnd; + GetWindowRect(mapWnd, &rt); + GetWindowRect(hWnd, &riprt); + GetClientRect (hWnd, &clientrect); + textrect = clientrect; + textrect.top += RIP_OFFSET_Y; + textrect.left += RIP_OFFSET_X; + textrect.right -= RIP_OFFSET_X; + if (data->window_text) + { + hdc = GetDC (hWnd); + OldFont = SelectObject (hdc, mswin_get_font(NHW_TEXT, 0, hdc, FALSE)); + DrawText (hdc, data->window_text, strlen(data->window_text), &textrect, + DT_LEFT | DT_NOPREFIX | DT_CALCRECT); + SelectObject (hdc, OldFont); + ReleaseDC(hWnd, hdc); + } + if (textrect.right - textrect.left > RIP_WIDTH) + clientrect.right = textrect.right + RIP_OFFSET_X - clientrect.right; + else + clientrect.right = textrect.left + 2 * RIP_OFFSET_X + RIP_WIDTH - clientrect.right; + clientrect.bottom = textrect.bottom + RIP_HEIGHT + RIP_OFFSET_Y - clientrect.bottom; + GetWindowRect (GetDlgItem(hWnd, IDOK), &textrect); + textrect.right -= textrect.left; + textrect.bottom -= textrect.top; + clientrect.bottom += textrect.bottom + RIP_OFFSET_Y; + riprt.right -= riprt.left; + riprt.bottom -= riprt.top; + riprt.right += clientrect.right; + riprt.bottom += clientrect.bottom; + rt.left += (rt.right - rt.left - riprt.right) / 2; + rt.top += (rt.bottom - rt.top - riprt.bottom) / 2; + + MoveWindow(hWnd, rt.left, rt.top, riprt.right, riprt.bottom, TRUE); + GetClientRect (hWnd, &clientrect); + MoveWindow (GetDlgItem(hWnd, IDOK), + (clientrect.right - clientrect.left - textrect.right) / 2, + clientrect.bottom - textrect.bottom - RIP_OFFSET_Y, textrect.right, textrect.bottom, TRUE); + ShowWindow(hWnd, SW_SHOW); + + while( IsWindow(hWnd) && + GetMessage(&msg, NULL, 0, 0)!=0 ) { + if( !IsDialogMessage(hWnd, &msg) ) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + GetNHApp()->hPopupWnd = NULL; +} + +BOOL CALLBACK NHRIPWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + HDC hdc; + PNHRIPWindow data; + + data = (PNHRIPWindow)GetWindowLong(hWnd, GWL_USERDATA); + switch (message) + { + case WM_INITDIALOG: + /* set text control font */ + hdc = GetDC(hWnd); + SendMessage(hWnd, WM_SETFONT, + (WPARAM)mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE), 0); + ReleaseDC(hWnd, hdc); + + SetFocus(GetDlgItem(hWnd, IDOK)); + return FALSE; + + case WM_MSNH_COMMAND: + onMSNHCommand(hWnd, wParam, lParam); + break; + + case WM_PAINT: + { + int bitmap_offset; + RECT clientrect; + RECT textrect; + HDC hdcBitmap; + HANDLE OldBitmap; + PAINTSTRUCT ps; + HFONT OldFont; + + hdc = BeginPaint (hWnd, &ps); + OldFont = SelectObject (hdc, mswin_get_font(NHW_TEXT, 0, hdc, FALSE)); + hdcBitmap = CreateCompatibleDC(hdc); + SetBkMode (hdc, TRANSPARENT); + GetClientRect (hWnd, &clientrect); + textrect = clientrect; + textrect.top += RIP_OFFSET_Y; + textrect.left += RIP_OFFSET_X; + textrect.right -= RIP_OFFSET_X; + if (data->window_text) + { + DrawText (hdc, data->window_text, strlen(data->window_text), &textrect, + DT_LEFT | DT_NOPREFIX | DT_CALCRECT); + DrawText (hdc, data->window_text, strlen(data->window_text), &textrect, + DT_LEFT | DT_NOPREFIX); + } + OldBitmap = SelectObject(hdcBitmap, GetNHApp()->bmpRip); + SetBkMode (hdc, OPAQUE); + bitmap_offset = (textrect.right - textrect.left - RIP_WIDTH) / 2; + BitBlt (hdc, textrect.left + bitmap_offset, textrect.bottom, RIP_WIDTH, + RIP_HEIGHT, hdcBitmap, 0, 0, SRCCOPY); + SetBkMode (hdc, TRANSPARENT); + if (data->rip_text) + { + textrect.left += RIP_GRAVE_X + bitmap_offset; + textrect.top = textrect.bottom + RIP_GRAVE_Y; + textrect.right = textrect.left + RIP_GRAVE_WIDTH; + textrect.bottom = textrect.top + RIP_GRAVE_HEIGHT; + DrawText (hdc, data->rip_text, strlen(data->rip_text), &textrect, + DT_CENTER | DT_VCENTER | DT_NOPREFIX | DT_WORDBREAK); + } + SelectObject (hdcBitmap, OldBitmap); + SelectObject (hdc, OldFont); + DeleteDC (hdcBitmap); + EndPaint (hWnd, &ps); + } + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + mswin_window_mark_dead(mswin_winid_from_handle(hWnd)); + if( GetNHApp()->hMainWnd==hWnd ) + GetNHApp()->hMainWnd=NULL; + DestroyWindow(hWnd); + SetFocus(GetNHApp()->hMainWnd); + return TRUE; + } + break; + + case WM_CLOSE: + /* if we get this here, we saved the bones so we can just force a quit */ + + mswin_window_mark_dead(mswin_winid_from_handle(hWnd)); + if( GetNHApp()->hMainWnd==hWnd ) + GetNHApp()->hMainWnd=NULL; + DestroyWindow(hWnd); + SetFocus(GetNHApp()->hMainWnd); + program_state.stopprint++; + return TRUE; + + case WM_DESTROY: + if( data ) { + if( data->window_text ) free(data->window_text); + if( data->rip_text ) free(data->rip_text); + if (data->rip_bmp != NULL) DeleteObject(data->rip_bmp); + free(data); + SetWindowLong(hWnd, GWL_USERDATA, (LONG)0); + } + break; + + } + return FALSE; +} + +void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + PNHRIPWindow data; + static int InRipText = 1; + data = (PNHRIPWindow)GetWindowLong(hWnd, GWL_USERDATA); + switch( wParam ) { + case MSNH_MSG_PUTSTR: { + PMSNHMsgPutstr msg_data = (PMSNHMsgPutstr)lParam; + TCHAR wbuf[BUFSZ]; + size_t text_size; + + if( !data->window_text ) { + text_size = strlen(msg_data->text) + 4; + data->window_text = (TCHAR*)malloc(text_size*sizeof(data->window_text[0])); + ZeroMemory(data->window_text, text_size*sizeof(data->window_text[0])); + } else { + text_size = _tcslen(data->window_text) + strlen(msg_data->text) + 4; + data->window_text = (TCHAR*)realloc(data->window_text, text_size*sizeof(data->window_text[0])); + } + if( !data->window_text ) break; + + _tcscat(data->window_text, NH_A2W(msg_data->text, wbuf, BUFSZ)); + _tcscat(data->window_text, TEXT("\r\n")); + break; + } + case MSNH_MSG_DIED: + { + data->rip_text = data->window_text; + data->window_text = NULL; + break; + } + + } +} + +void mswin_finish_rip_text(winid wid) +{ + SendMessage (mswin_hwnd_from_winid(wid), WM_MSNH_COMMAND, MSNH_MSG_DIED, 0); +} diff --git a/win/win32/mhrip.h b/win/win32/mhrip.h new file mode 100644 index 0000000..cc49355 --- /dev/null +++ b/win/win32/mhrip.h @@ -0,0 +1,15 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef MSWINRIPWindow_h +#define MSWINRIPWindow_h + +#include "winMS.h" +#include "config.h" +#include "global.h" + +void mswin_finish_rip_text(winid wid); +HWND mswin_init_RIP_window (void); +void mswin_display_RIP_window (HWND hwnd); + +#endif /* MSWINRIPWindow_h */ diff --git a/win/win32/mhsplash.c b/win/win32/mhsplash.c new file mode 100644 index 0000000..dba08ac --- /dev/null +++ b/win/win32/mhsplash.c @@ -0,0 +1,169 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "winMS.h" +#include "resource.h" +#include "mhsplash.h" +#include "mhmsg.h" +#include "mhfont.h" +#include "patchlevel.h" + +PNHWinApp GetNHApp(void); + +BOOL CALLBACK NHSplashWndProc(HWND, UINT, WPARAM, LPARAM); + +#define SPLASH_WIDTH 440 +#define SPLASH_HEIGHT 240 +#define SPLASH_VERSION_X 290 +#define SPLASH_VERSION_Y 10 +#define SPLASH_EXTRA_X_BEGIN 15 +#define SPLASH_EXTRA_X_END 415 +#define SPLASH_EXTRA_Y 150 +#define SPLASH_OFFSET_X 10 +#define SPLASH_OFFSET_Y 10 + +extern HFONT version_splash_font; +extern HFONT extrainfo_splash_font; + +void mswin_display_splash_window () +{ + MSG msg; + RECT rt; + HWND mapWnd; + RECT splashrt; + RECT clientrt; + RECT controlrt; + HWND hWnd; + + hWnd = CreateDialog(GetNHApp()->hApp, MAKEINTRESOURCE(IDD_SPLASH), + GetNHApp()->hMainWnd, NHSplashWndProc); + if( !hWnd ) panic("Cannot create Splash window"); + mswin_init_splashfonts(hWnd); + GetNHApp()->hPopupWnd = hWnd; + mapWnd = mswin_hwnd_from_winid(WIN_MAP); + if( !IsWindow(mapWnd) ) mapWnd = GetNHApp()->hMainWnd; + /* Get control size */ + GetWindowRect (GetDlgItem(hWnd, IDOK), &controlrt); + controlrt.right -= controlrt.left; + controlrt.bottom -= controlrt.top; + /* Get current client area */ + GetClientRect (hWnd, &clientrt); + /* Get window size */ + GetWindowRect(hWnd, &splashrt); + splashrt.right -= splashrt.left; + splashrt.bottom -= splashrt.top; + /* Get difference between requested client area and current value */ + splashrt.right += SPLASH_WIDTH + SPLASH_OFFSET_X * 2 - clientrt.right; + splashrt.bottom += SPLASH_HEIGHT + controlrt.bottom + SPLASH_OFFSET_Y * 3 - clientrt.bottom; + /* Place the window centered */ + GetWindowRect(mapWnd, &rt); + rt.left += (rt.right - rt.left - splashrt.right) / 2; + rt.top += (rt.bottom - rt.top - splashrt.bottom) / 2; + MoveWindow(hWnd, rt.left, rt.top, splashrt.right, splashrt.bottom, TRUE); + /* Place the control */ + GetClientRect (hWnd, &clientrt); + MoveWindow (GetDlgItem(hWnd, IDOK), + (clientrt.right - clientrt.left - controlrt.right) / 2, + clientrt.bottom - controlrt.bottom - SPLASH_OFFSET_Y, + controlrt.right, controlrt.bottom, TRUE); + ShowWindow(hWnd, SW_SHOW); + + while( IsWindow(hWnd) && + GetMessage(&msg, NULL, 0, 0)!=0 ) { + if( !IsDialogMessage(hWnd, &msg) ) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + GetNHApp()->hPopupWnd = NULL; + mswin_destroy_splashfonts(); +} + +BOOL CALLBACK NHSplashWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + HDC hdc; + switch (message) + { + case WM_INITDIALOG: + /* set text control font */ + hdc = GetDC(hWnd); + hdc = GetDC(hWnd); + SendMessage(hWnd, WM_SETFONT, + (WPARAM)mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE), 0); + ReleaseDC(hWnd, hdc); + + ReleaseDC(hWnd, hdc); + + SetFocus(GetDlgItem(hWnd, IDOK)); + return FALSE; + + case WM_PAINT: + { + char VersionString[BUFSZ]; + char InfoString[BUFSZ]; + RECT rt; + HDC hdcBitmap; + HANDLE OldBitmap; + HANDLE OldFont; + PAINTSTRUCT ps; + + hdc = BeginPaint (hWnd, &ps); + /* Show splash graphic */ + + hdcBitmap = CreateCompatibleDC(hdc); + SetBkMode (hdc, OPAQUE); + OldBitmap = SelectObject(hdcBitmap, GetNHApp()->bmpSplash); + BitBlt (hdc, SPLASH_OFFSET_X, SPLASH_OFFSET_Y, SPLASH_WIDTH, + SPLASH_HEIGHT, hdcBitmap, 0, 0, SRCCOPY); + SelectObject (hdcBitmap, OldBitmap); + DeleteDC (hdcBitmap); + + SetBkMode (hdc, TRANSPARENT); + /* Print version number */ + + SetTextColor (hdc, RGB(0, 0, 0)); + rt.right = rt.left = SPLASH_VERSION_X; + rt.bottom = rt.top = SPLASH_VERSION_Y; + Sprintf (VersionString, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, + PATCHLEVEL); + OldFont = SelectObject(hdc, version_splash_font); + DrawText (hdc, VersionString, strlen(VersionString), &rt, + DT_LEFT | DT_NOPREFIX | DT_CALCRECT); + DrawText (hdc, VersionString, strlen(VersionString), &rt, + DT_LEFT | DT_NOPREFIX); + + /* Print copyright banner */ + + SetTextColor (hdc, RGB(255, 255, 255)); + Sprintf (InfoString, "%s\n%s\n%s\n", COPYRIGHT_BANNER_A, COPYRIGHT_BANNER_B, + COPYRIGHT_BANNER_C); + SelectObject(hdc, extrainfo_splash_font); + rt.left = SPLASH_EXTRA_X_BEGIN; + rt.right = SPLASH_EXTRA_X_END; + rt.bottom = rt.top = SPLASH_EXTRA_Y; + DrawText (hdc, InfoString, strlen(InfoString), &rt, + DT_LEFT | DT_NOPREFIX | DT_LEFT | DT_VCENTER | DT_CALCRECT); + DrawText (hdc, InfoString, strlen(InfoString), &rt, + DT_LEFT | DT_NOPREFIX | DT_LEFT | DT_VCENTER); + + SelectObject(hdc, OldFont); + EndPaint (hWnd, &ps); + } + break; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + mswin_window_mark_dead(mswin_winid_from_handle(hWnd)); + if( GetNHApp()->hMainWnd==hWnd ) + GetNHApp()->hMainWnd=NULL; + DestroyWindow(hWnd); + SetFocus(GetNHApp()->hMainWnd); + return TRUE; + } + break; + } + return FALSE; +} diff --git a/win/win32/mhsplash.h b/win/win32/mhsplash.h new file mode 100644 index 0000000..47c7696 --- /dev/null +++ b/win/win32/mhsplash.h @@ -0,0 +1,13 @@ +/* Copyright (C) 2002 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef MSWINSplashWindow_h +#define MSWINSplashWindow_h + +#include "winMS.h" +#include "config.h" +#include "global.h" + +void mswin_display_splash_window (void); + +#endif /* MSWINSplashWindow_h */ diff --git a/win/win32/mhstatus.c b/win/win32/mhstatus.c new file mode 100644 index 0000000..1647858 --- /dev/null +++ b/win/win32/mhstatus.c @@ -0,0 +1,176 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "winMS.h" +#include "mhstatus.h" +#include "mhmsg.h" +#include "mhfont.h" + +#define NHSW_LINES 2 +#define MAXWINDOWTEXT 80 + +typedef struct mswin_nethack_status_window { + int index; + char window_text[NHSW_LINES][MAXWINDOWTEXT]; +} NHStatusWindow, *PNHStatusWindow; + +static TCHAR szStatusWindowClass[] = TEXT("MSNHStatusWndClass"); +LRESULT CALLBACK StatusWndProc(HWND, UINT, WPARAM, LPARAM); +static void register_status_window_class(void); + +#define DEFAULT_COLOR_BG_STATUS COLOR_WINDOW +#define DEFAULT_COLOR_FG_STATUS COLOR_WINDOWTEXT + +HWND mswin_init_status_window () { + static int run_once = 0; + HWND ret; + NHStatusWindow* data; + + if( !run_once ) { + register_status_window_class( ); + run_once = 1; + } + + ret = CreateWindow( + szStatusWindowClass, + NULL, + WS_CHILD | WS_DISABLED | WS_CLIPSIBLINGS, + 0, /* x position */ + 0, /* y position */ + 0, /* x-size - we will set it later */ + 0, /* y-size - we will set it later */ + GetNHApp()->hMainWnd, + NULL, + GetNHApp()->hApp, + NULL ); + if( !ret ) panic("Cannot create status window"); + + EnableWindow(ret, FALSE); + + data = (PNHStatusWindow)malloc(sizeof(NHStatusWindow)); + if( !data ) panic("out of memory"); + + ZeroMemory(data, sizeof(NHStatusWindow)); + SetWindowLong(ret, GWL_USERDATA, (LONG)data); + return ret; +} + +void register_status_window_class() +{ + WNDCLASS wcex; + ZeroMemory( &wcex, sizeof(wcex)); + + wcex.style = CS_NOCLOSE; + wcex.lpfnWndProc = (WNDPROC)StatusWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = GetNHApp()->hApp; + wcex.hIcon = NULL; + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.hbrBackground = status_bg_brush + ? status_bg_brush : SYSCLR_TO_BRUSH(DEFAULT_COLOR_BG_STATUS); + wcex.lpszMenuName = NULL; + wcex.lpszClassName = szStatusWindowClass; + + RegisterClass(&wcex); +} + + +LRESULT CALLBACK StatusWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + RECT rt; + PAINTSTRUCT ps; + HDC hdc; + PNHStatusWindow data; + + data = (PNHStatusWindow)GetWindowLong(hWnd, GWL_USERDATA); + switch (message) + { + case WM_MSNH_COMMAND: { + switch( wParam ) { + case MSNH_MSG_PUTSTR: { + PMSNHMsgPutstr msg_data = (PMSNHMsgPutstr)lParam; + strncpy(data->window_text[data->index], msg_data->text, + MAXWINDOWTEXT); + strncat(data->window_text[data->index], "\n", + MAXWINDOWTEXT-strlen(data->window_text[data->index])); + data->index = (data->index+1) % NHSW_LINES; + InvalidateRect(hWnd, NULL, TRUE); + break; + } + case MSNH_MSG_CLEAR_WINDOW: + data->index = 0; + ZeroMemory(data->window_text, sizeof(data->window_text)); + InvalidateRect(hWnd, NULL, TRUE); + break; + } + } break; + + case WM_PAINT: { + int i; + SIZE sz; + HGDIOBJ oldFont; + TCHAR wbuf[BUFSZ]; + COLORREF OldBg, OldFg; + + hdc = BeginPaint(hWnd, &ps); + GetClientRect(hWnd, &rt); + + oldFont = SelectObject(hdc, mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE)); + + OldBg = SetBkColor(hdc, status_bg_brush + ? status_bg_color : (COLORREF)GetSysColor(DEFAULT_COLOR_BG_STATUS)); + OldFg = SetTextColor(hdc, status_fg_brush + ? status_fg_color : (COLORREF)GetSysColor(DEFAULT_COLOR_FG_STATUS)); + + for(i=0; iwindow_text[i], wbuf, sizeof(wbuf)), strlen(data->window_text[i]), &sz); + NH_A2W(data->window_text[i], wbuf, BUFSZ); + DrawText(hdc, wbuf, strlen(data->window_text[i]), &rt, DT_LEFT | DT_END_ELLIPSIS); + rt.top += sz.cy; + } + + SelectObject(hdc, oldFont); + SetTextColor (hdc, OldFg); + SetBkColor (hdc, OldBg); + EndPaint(hWnd, &ps); + } break; + + case WM_DESTROY: + free(data); + SetWindowLong(hWnd, GWL_USERDATA, (LONG)0); + break; + + case WM_SETFOCUS: + SetFocus(GetNHApp()->hMainWnd); + break; + + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + return 0; +} + +void mswin_status_window_size (HWND hWnd, LPSIZE sz) +{ + TEXTMETRIC tm; + HGDIOBJ saveFont; + HDC hdc; + PNHStatusWindow data; + RECT rt; + GetWindowRect(hWnd, &rt); + sz->cx = rt.right - rt.left; + sz->cy = rt.bottom - rt.top; + + data = (PNHStatusWindow)GetWindowLong(hWnd, GWL_USERDATA); + if(data) { + hdc = GetDC(hWnd); + saveFont = SelectObject(hdc, mswin_get_font(NHW_STATUS, ATR_NONE, hdc, FALSE)); + GetTextMetrics(hdc, &tm); + + sz->cy = tm.tmHeight * NHSW_LINES; + + SelectObject(hdc, saveFont); + ReleaseDC(hWnd, hdc); + } +} \ No newline at end of file diff --git a/win/win32/mhstatus.h b/win/win32/mhstatus.h new file mode 100644 index 0000000..e073a80 --- /dev/null +++ b/win/win32/mhstatus.h @@ -0,0 +1,14 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef MSWINStatusWindow_h +#define MSWINStatusWindow_h + +#include "winMS.h" +#include "config.h" +#include "global.h" + +HWND mswin_init_status_window (void); +void mswin_status_window_size (HWND hWnd, LPSIZE sz); + +#endif /* MSWINStatusWindow_h */ diff --git a/win/win32/mhtext.c b/win/win32/mhtext.c new file mode 100644 index 0000000..11c5ed2 --- /dev/null +++ b/win/win32/mhtext.c @@ -0,0 +1,254 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#include "winMS.h" +#include "resource.h" +#include "mhtext.h" +#include "mhmsg.h" +#include "mhfont.h" + +PNHWinApp GetNHApp(void); + +typedef struct mswin_nethack_text_window { + TCHAR* window_text; +} NHTextWindow, *PNHTextWindow; + +static WNDPROC editControlWndProc = 0; + +BOOL CALLBACK NHTextWndProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK NHEditHookWndProc(HWND, UINT, WPARAM, LPARAM); +static void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam); +static void LayoutText(HWND hwnd); + +HWND mswin_init_text_window () { + HWND ret; + PNHTextWindow data; + + ret = CreateDialog( + GetNHApp()->hApp, + MAKEINTRESOURCE(IDD_NHTEXT), + GetNHApp()->hMainWnd, + NHTextWndProc + ); + if( !ret ) panic("Cannot create text window"); + + data = (PNHTextWindow)malloc(sizeof(NHTextWindow)); + if( !data ) panic("out of memory"); + + ZeroMemory(data, sizeof(NHTextWindow)); + SetWindowLong(ret, GWL_USERDATA, (LONG)data); + return ret; +} + +void mswin_display_text_window (HWND hWnd) +{ + MSG msg; + RECT rt; + PNHTextWindow data; + HWND mapWnd; + + data = (PNHTextWindow)GetWindowLong(hWnd, GWL_USERDATA); + if( data && data->window_text ) { + HWND control; + control = GetDlgItem(hWnd, IDC_TEXT_CONTROL); + SendMessage(control, EM_FMTLINES, 1, 0 ); + SetWindowText(GetDlgItem(hWnd, IDC_TEXT_CONTROL), data->window_text); + } + + GetNHApp()->hPopupWnd = hWnd; + mapWnd = mswin_hwnd_from_winid(WIN_MAP); + if( !IsWindow(mapWnd) ) mapWnd = GetNHApp()->hMainWnd; + GetWindowRect(mapWnd, &rt); + MoveWindow(hWnd, rt.left, rt.top, rt.right-rt.left, rt.bottom-rt.top, TRUE); + ShowWindow(hWnd, SW_SHOW); + + while( IsWindow(hWnd) && + GetMessage(&msg, NULL, 0, 0)!=0 ) { + if( !IsDialogMessage(hWnd, &msg) ) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + GetNHApp()->hPopupWnd = NULL; +} + +BOOL CALLBACK NHTextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + HWND control; + HDC hdc; + PNHTextWindow data; + TCHAR title[MAX_LOADSTRING]; + + data = (PNHTextWindow)GetWindowLong(hWnd, GWL_USERDATA); + switch (message) + { + case WM_INITDIALOG: + /* set text control font */ + control = GetDlgItem(hWnd, IDC_TEXT_CONTROL); + if( !control ) { + panic("cannot get text view window"); + } + + hdc = GetDC(control); + SendMessage(control, WM_SETFONT, (WPARAM)mswin_get_font(NHW_TEXT, ATR_NONE, hdc, FALSE), 0); + ReleaseDC(control, hdc); + + /* subclass edit control */ + editControlWndProc = (WNDPROC)GetWindowLong(control, GWL_WNDPROC); + SetWindowLong(control, GWL_WNDPROC, (LONG)NHEditHookWndProc); + + SetFocus(control); + + /* Even though the dialog has no caption, you can still set the title + which shows on Alt-Tab */ + LoadString(GetNHApp()->hApp, IDS_APP_TITLE, title, MAX_LOADSTRING); + SetWindowText(hWnd, title); + return FALSE; + + case WM_MSNH_COMMAND: + onMSNHCommand(hWnd, wParam, lParam); + break; + + case WM_SIZE: + LayoutText(hWnd); + return FALSE; + + case WM_COMMAND: + switch (LOWORD(wParam)) + { + case IDOK: + case IDCANCEL: + mswin_window_mark_dead(mswin_winid_from_handle(hWnd)); + if( GetNHApp()->hMainWnd==hWnd ) + GetNHApp()->hMainWnd=NULL; + DestroyWindow(hWnd); + SetFocus(GetNHApp()->hMainWnd); + return TRUE; + case IDC_TEXT_CONTROL: + switch (HIWORD(wParam)) + { + case EN_SETFOCUS: + HideCaret((HWND)lParam); + return TRUE; + } + } + break; + + case WM_DESTROY: + if( data ) { + if( data->window_text ) free(data->window_text); + free(data); + SetWindowLong(hWnd, GWL_USERDATA, (LONG)0); + } + break; + + } + return FALSE; +} + +void onMSNHCommand(HWND hWnd, WPARAM wParam, LPARAM lParam) +{ + PNHTextWindow data; + + data = (PNHTextWindow)GetWindowLong(hWnd, GWL_USERDATA); + switch( wParam ) { + case MSNH_MSG_PUTSTR: { + PMSNHMsgPutstr msg_data = (PMSNHMsgPutstr)lParam; + TCHAR wbuf[BUFSZ]; + size_t text_size; + + if( !data->window_text ) { + text_size = strlen(msg_data->text) + 4; + data->window_text = (TCHAR*)malloc(text_size*sizeof(data->window_text[0])); + ZeroMemory(data->window_text, text_size*sizeof(data->window_text[0])); + } else { + text_size = _tcslen(data->window_text) + strlen(msg_data->text) + 4; + data->window_text = (TCHAR*)realloc(data->window_text, text_size*sizeof(data->window_text[0])); + } + if( !data->window_text ) break; + + _tcscat(data->window_text, NH_A2W(msg_data->text, wbuf, BUFSZ)); + _tcscat(data->window_text, TEXT("\r\n")); + break; + } + } +} + +void LayoutText(HWND hWnd) +{ + HWND btn_ok; + HWND text; + RECT clrt, rt; + POINT pt_elem, pt_ok; + SIZE sz_elem, sz_ok; + + text = GetDlgItem(hWnd, IDC_TEXT_CONTROL); + btn_ok = GetDlgItem(hWnd, IDOK); + + /* get window coordinates */ + GetClientRect(hWnd, &clrt ); + + /* set window placements */ + GetWindowRect(btn_ok, &rt); + sz_ok.cx = clrt.right - clrt.left; + sz_ok.cy = rt.bottom-rt.top; + pt_ok.x = clrt.left; + pt_ok.y = clrt.bottom - sz_ok.cy; + + pt_elem.x = clrt.left; + pt_elem.y = clrt.top; + sz_elem.cx = clrt.right - clrt.left; + sz_elem.cy = pt_ok.y; + + MoveWindow(text, pt_elem.x, pt_elem.y, sz_elem.cx, sz_elem.cy, TRUE ); + MoveWindow(btn_ok, pt_ok.x, pt_ok.y, sz_ok.cx, sz_ok.cy, TRUE ); +} + +/* Edit box hook */ +LRESULT CALLBACK NHEditHookWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch(message) { + + case WM_KEYDOWN: + switch (wParam) + { + /* close on space in Windows mode + page down on space in NetHack mode */ + case VK_SPACE: + { + SCROLLINFO si; + + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_POS | SIF_RANGE | SIF_PAGE; + GetScrollInfo(hWnd, SB_VERT, &si); + /* If nethackmode and not at the end of the list */ + if (GetNHApp()->regNetHackMode && + (si.nPos + (int)si.nPage) <= (si.nMax - si.nMin)) + SendMessage(hWnd, EM_SCROLL, SB_PAGEDOWN, 0); + else + PostMessage(GetParent(hWnd), WM_COMMAND, MAKELONG(IDOK, 0), 0); + return 0; + } + case VK_NEXT: + SendMessage(hWnd, EM_SCROLL, SB_PAGEDOWN, 0); + return 0; + case VK_PRIOR: + SendMessage(hWnd, EM_SCROLL, SB_PAGEUP, 0); + return 0; + case VK_UP: + SendMessage(hWnd, EM_SCROLL, SB_LINEUP, 0); + return 0; + case VK_DOWN: + SendMessage(hWnd, EM_SCROLL, SB_LINEDOWN, 0); + return 0; + + } + break; + } + + if( editControlWndProc ) + return CallWindowProc(editControlWndProc, hWnd, message, wParam, lParam); + else + return 0; +} diff --git a/win/win32/mhtext.h b/win/win32/mhtext.h new file mode 100644 index 0000000..64be03d --- /dev/null +++ b/win/win32/mhtext.h @@ -0,0 +1,14 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef MSWINTextWindow_h +#define MSWINTextWindow_h + +#include "winMS.h" +#include "config.h" +#include "global.h" + +HWND mswin_init_text_window (void); +void mswin_display_text_window (HWND hwnd); + +#endif /* MSWINTextWindow_h */ diff --git a/win/win32/mnsel.uu b/win/win32/mnsel.uu new file mode 100644 index 0000000..0433654 --- /dev/null +++ b/win/win32/mnsel.uu @@ -0,0 +1,9 @@ +begin 600 mnsel.bmp +M0DWV`````````'8````H````$````!`````!``0``````(`````````````` +M````````````````````@```@````("``(````"``(``@(```,#`P`"`@(`` +M``#_``#_````__\`_P```/\`_P#__P``____```````````````````````` +M________``#_"/____\``/@`C____P``\`@(____``#P#X"/__\``/`/^`C_ +M_P``\`__@(__``#XC__X"/\``/____^`CP``______@/``#_______\``/__ +5_____P`````````````````````` +` +end diff --git a/win/win32/mnselcnt.uu b/win/win32/mnselcnt.uu new file mode 100644 index 0000000..72273d7 --- /dev/null +++ b/win/win32/mnselcnt.uu @@ -0,0 +1,9 @@ +begin 600 mnselcnt.bmp +M0DWV`````````'8````H````$````!`````!``0``````(`````````````` +M````````````````````@```@````("``(````"``(``@(```,#`P`"`@(`` +M``#_``#_````__\`_P```/\`_P#__P``____```````````````````````` +M________``#_______\``/_P__\/_P``_P````#_``#_\/__#_\``/_P__\/ +M_P``__#__P__``#_\/__#_\``/\`````_P``__#__P__``#_______\``/__ +5_____P`````````````````````` +` +end diff --git a/win/win32/mnunsel.uu b/win/win32/mnunsel.uu new file mode 100644 index 0000000..4133094 --- /dev/null +++ b/win/win32/mnunsel.uu @@ -0,0 +1,9 @@ +begin 600 mnunsel.bmp +M0DWV`````````'8````H````$````!`````!``0``````(`````````````` +M````````````````````@```@````("``(````"``(``@(```,#`P`"`@(`` +M``#_``#_````__\`_P```/\`_P#__P``____```````````````````````` +M________``#_______\``/_______P``________``#_______\``/______ +M_P``________``#_______\``/_______P``________``#_______\``/__ +5_____P`````````````````````` +` +end diff --git a/win/win32/mswproc.c b/win/win32/mswproc.c new file mode 100644 index 0000000..5e82201 --- /dev/null +++ b/win/win32/mswproc.c @@ -0,0 +1,2017 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +/* + * This file implements the interface between the window port specific + * code in the mswin port and the rest of the nethack game engine. +*/ + +#include "hack.h" +#include "dlb.h" +#include "winMS.h" +#include "mhmap.h" +#include "mhstatus.h" +#include "mhtext.h" +#include "mhmsgwnd.h" +#include "mhmenu.h" +#include "mhsplash.h" +#include "mhmsg.h" +#include "mhinput.h" +#include "mhaskyn.h" +#include "mhdlg.h" +#include "mhrip.h" +#include "mhmain.h" +#include "mhfont.h" + +#define LLEN 128 + +extern const char *killed_by_prefix[]; + +#ifdef _DEBUG +extern void logDebug(const char *fmt, ...); +#else +void logDebug(const char *fmt, ...) { } +#endif + +static void mswin_main_loop(void); +static BOOL initMapTiles(void); +static void mswin_color_from_string(char *colorstring, HBRUSH* brushptr, COLORREF *colorptr); +static void prompt_for_player_selection(void); + +#define TOTAL_BRUSHES 10 +HBRUSH brush_table[TOTAL_BRUSHES]; +int max_brush = 0; + +HBRUSH menu_bg_brush = NULL; +HBRUSH menu_fg_brush = NULL; +HBRUSH text_bg_brush = NULL; +HBRUSH text_fg_brush = NULL; +HBRUSH status_bg_brush = NULL; +HBRUSH status_fg_brush = NULL; +HBRUSH message_bg_brush = NULL; +HBRUSH message_fg_brush = NULL; + +COLORREF menu_bg_color = RGB(0, 0, 0); +COLORREF menu_fg_color = RGB(0xFF, 0xFF, 0xFF); +COLORREF text_bg_color = RGB(0, 0, 0); +COLORREF text_fg_color = RGB(0xFF, 0xFF, 0xFF); +COLORREF status_bg_color = RGB(0, 0, 0); +COLORREF status_fg_color = RGB(0xFF, 0xFF, 0xFF); +COLORREF message_bg_color = RGB(0, 0, 0); +COLORREF message_fg_color = RGB(0xFF, 0xFF, 0xFF); + +/* Interface definition, for windows.c */ +struct window_procs mswin_procs = { + "MSWIN", + WC_COLOR|WC_HILITE_PET|WC_ALIGN_MESSAGE|WC_ALIGN_STATUS| + WC_INVERSE|WC_SCROLL_MARGIN|WC_MAP_MODE| + WC_FONT_MESSAGE|WC_FONT_STATUS|WC_FONT_MENU|WC_FONT_TEXT| + WC_FONTSIZ_MESSAGE|WC_FONTSIZ_STATUS|WC_FONTSIZ_MENU|WC_FONTSIZ_TEXT| + WC_TILE_WIDTH|WC_TILE_HEIGHT|WC_TILE_FILE|WC_VARY_MSGCOUNT| + WC_WINDOWCOLORS|WC_PLAYER_SELECTION|WC_SPLASH_SCREEN, + mswin_init_nhwindows, + mswin_player_selection, + mswin_askname, + mswin_get_nh_event, + mswin_exit_nhwindows, + mswin_suspend_nhwindows, + mswin_resume_nhwindows, + mswin_create_nhwindow, + mswin_clear_nhwindow, + mswin_display_nhwindow, + mswin_destroy_nhwindow, + mswin_curs, + mswin_putstr, + mswin_display_file, + mswin_start_menu, + mswin_add_menu, + mswin_end_menu, + mswin_select_menu, + genl_message_menu, /* no need for X-specific handling */ + mswin_update_inventory, + mswin_mark_synch, + mswin_wait_synch, +#ifdef CLIPPING + mswin_cliparound, +#endif +#ifdef POSITIONBAR + donull, +#endif + mswin_print_glyph, + mswin_raw_print, + mswin_raw_print_bold, + mswin_nhgetch, + mswin_nh_poskey, + mswin_nhbell, + mswin_doprev_message, + mswin_yn_function, + mswin_getlin, + mswin_get_ext_cmd, + mswin_number_pad, + mswin_delay_output, +#ifdef CHANGE_COLOR /* only a Mac option currently */ + mswin, + mswin_change_background, +#endif + /* other defs that really should go away (they're tty specific) */ + mswin_start_screen, + mswin_end_screen, + mswin_outrip, + mswin_preference_update, +}; + + +/* +init_nhwindows(int* argcp, char** argv) + -- Initialize the windows used by NetHack. This can also + create the standard windows listed at the top, but does + not display them. + -- Any commandline arguments relevant to the windowport + should be interpreted, and *argcp and *argv should + be changed to remove those arguments. + -- When the message window is created, the variable + iflags.window_inited needs to be set to TRUE. Otherwise + all plines() will be done via raw_print(). + ** Why not have init_nhwindows() create all of the "standard" + ** windows? Or at least all but WIN_INFO? -dean +*/ +void mswin_init_nhwindows(int* argc, char** argv) +{ + logDebug("mswin_init_nhwindows()\n"); + +#ifdef _DEBUG + { + /* truncate trace file */ + FILE *dfp = fopen("nhtrace.log", "w"); + fclose(dfp); + } +#endif + mswin_nh_input_init(); + + /* set it to WIN_ERR so we can detect attempts to + use this ID before it is inialized */ + WIN_MAP = WIN_ERR; + + /* Read Windows settings from the reqistry */ + mswin_read_reg(); + /* Set menu check mark for interface mode */ + mswin_menu_check_intf_mode(); + + /* check default values */ + if( iflags.wc_fontsiz_statusNHFONT_SIZE_MAX ) + iflags.wc_fontsiz_status = NHFONT_DEFAULT_SIZE; + + if( iflags.wc_fontsiz_messageNHFONT_SIZE_MAX ) + iflags.wc_fontsiz_message = NHFONT_DEFAULT_SIZE; + + if( iflags.wc_fontsiz_textNHFONT_SIZE_MAX ) + iflags.wc_fontsiz_text = NHFONT_DEFAULT_SIZE; + + if( iflags.wc_fontsiz_menuNHFONT_SIZE_MAX ) + iflags.wc_fontsiz_menu = NHFONT_DEFAULT_SIZE; + + if( iflags.wc_align_message==0 ) iflags.wc_align_message = ALIGN_TOP; + if( iflags.wc_align_status==0 ) iflags.wc_align_status = ALIGN_BOTTOM; + if( iflags.wc_scroll_margin==0 ) iflags.wc_scroll_margin = DEF_CLIPAROUND_MARGIN; + if( iflags.wc_tile_width==0 ) iflags.wc_tile_width = TILE_X; + if( iflags.wc_tile_height==0 ) iflags.wc_tile_height = TILE_Y; + + if( iflags.wc_vary_msgcount==0 ) iflags.wc_vary_msgcount = 4; + + /* force tabs in menus */ + iflags.menu_tab_sep = 1; + + /* force toptenwin to be true. toptenwin is the option that decides whether to + * write output to a window or stdout. stdout doesn't make sense on Windows + * non-console applications + */ + flags.toptenwin = 1; + set_option_mod_status("toptenwin", SET_IN_FILE); + + /* initialize map tiles bitmap */ + initMapTiles(); + + /* set tile-related options to readonly */ + set_wc_option_mod_status( + WC_TILE_WIDTH|WC_TILE_HEIGHT|WC_TILE_FILE, + DISP_IN_GAME); + + /* set font-related options to change in the game */ + set_wc_option_mod_status( + WC_HILITE_PET | + WC_ALIGN_MESSAGE | + WC_ALIGN_STATUS | + WC_SCROLL_MARGIN | + WC_MAP_MODE | + WC_FONT_MESSAGE | + WC_FONT_STATUS | + WC_FONT_MENU | + WC_FONT_TEXT | + WC_FONTSIZ_MESSAGE | + WC_FONTSIZ_STATUS | + WC_FONTSIZ_MENU | + WC_FONTSIZ_TEXT | + WC_VARY_MSGCOUNT, + SET_IN_GAME + ); + + mswin_color_from_string(iflags.wc_foregrnd_menu, &menu_fg_brush, &menu_fg_color); + mswin_color_from_string(iflags.wc_foregrnd_message, &message_fg_brush, &message_fg_color); + mswin_color_from_string(iflags.wc_foregrnd_status, &status_fg_brush, &status_fg_color); + mswin_color_from_string(iflags.wc_foregrnd_text, &text_fg_brush, &text_fg_color); + mswin_color_from_string(iflags.wc_backgrnd_menu, &menu_bg_brush, &menu_bg_color); + mswin_color_from_string(iflags.wc_backgrnd_message, &message_bg_brush, &message_bg_color); + mswin_color_from_string(iflags.wc_backgrnd_status, &status_bg_brush, &status_bg_color); + mswin_color_from_string(iflags.wc_backgrnd_text, &text_bg_brush, &text_bg_color); + + if (iflags.wc_splash_screen) mswin_display_splash_window(); + iflags.window_inited = TRUE; +} + + +/* Do a window-port specific player type selection. If player_selection() + offers a Quit option, it is its responsibility to clean up and terminate + the process. You need to fill in pl_character[0]. +*/ +void mswin_player_selection(void) +{ + int nRole; + + logDebug("mswin_player_selection()\n"); + + if (iflags.wc_player_selection == VIA_DIALOG) { + /* pick player type randomly (use pre-selected role/race/gender/alignment) */ + if( flags.randomall ) { + if (flags.initrole < 0) { + flags.initrole = pick_role(flags.initrace, flags.initgend, + flags.initalign, PICK_RANDOM); + if (flags.initrole < 0) { + raw_print("Incompatible role!"); + flags.initrole = randrole(); + } + } + + if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) { + flags.initrace = pick_race(flags.initrole, flags.initgend, + flags.initalign, PICK_RANDOM); + if (flags.initrace < 0) { + raw_print("Incompatible race!"); + flags.initrace = randrace(flags.initrole); + } + } + + if (flags.initgend < 0 || !validgend(flags.initrole, flags.initrace, + flags.initgend)) { + flags.initgend = pick_gend(flags.initrole, flags.initrace, + flags.initalign, PICK_RANDOM); + if (flags.initgend < 0) { + raw_print("Incompatible gender!"); + flags.initgend = randgend(flags.initrole, flags.initrace); + } + } + + if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace, + flags.initalign)) { + flags.initalign = pick_align(flags.initrole, flags.initrace, + flags.initgend, PICK_RANDOM); + if (flags.initalign < 0) { + raw_print("Incompatible alignment!"); + flags.initalign = randalign(flags.initrole, flags.initrace); + } + } + } else { + /* select a role */ + if( mswin_player_selection_window( &nRole ) == IDCANCEL ) { + bail(0); + } + } + } else { /* iflags.wc_player_selection == VIA_PROMPTS */ + prompt_for_player_selection(); + } +} + +void prompt_for_player_selection(void) +{ + int i, k, n; + char pick4u = 'n', thisch, lastch = 0; + char pbuf[QBUFSZ], plbuf[QBUFSZ]; + winid win; + anything any; + menu_item *selected = 0; + DWORD box_result; + + logDebug("prompt_for_player_selection()\n"); + + /* prevent an unnecessary prompt */ + rigid_role_checks(); + + /* Should we randomly pick for the player? */ + if (!flags.randomall && + (flags.initrole == ROLE_NONE || flags.initrace == ROLE_NONE || + flags.initgend == ROLE_NONE || flags.initalign == ROLE_NONE)) { + /* int echoline; */ + char *prompt = build_plselection_prompt(pbuf, QBUFSZ, flags.initrole, + flags.initrace, flags.initgend, flags.initalign); + + /* tty_putstr(BASE_WINDOW, 0, ""); */ + /* echoline = wins[BASE_WINDOW]->cury; */ + box_result = MessageBox(NULL, prompt, TEXT("NetHack for Windows"), + MB_YESNOCANCEL | MB_DEFBUTTON1); + pick4u = (box_result == IDYES) ? 'y' : (box_result == IDNO) ? 'n' : '\033'; + /* tty_putstr(BASE_WINDOW, 0, prompt); */ + do { + /* pick4u = lowc(readchar()); */ + if (index(quitchars, pick4u)) pick4u = 'y'; + } while(!index(ynqchars, pick4u)); + if ((int)strlen(prompt) + 1 < CO) { + /* Echo choice and move back down line */ + /* tty_putsym(BASE_WINDOW, (int)strlen(prompt)+1, echoline, pick4u); */ + /* tty_putstr(BASE_WINDOW, 0, ""); */ + } else + /* Otherwise it's hard to tell where to echo, and things are + * wrapping a bit messily anyway, so (try to) make sure the next + * question shows up well and doesn't get wrapped at the + * bottom of the window. + */ + /* tty_clear_nhwindow(BASE_WINDOW) */ ; + + if (pick4u != 'y' && pick4u != 'n') { +give_up: /* Quit */ + if (selected) free((genericptr_t) selected); + bail((char *)0); + /*NOTREACHED*/ + return; + } + } + + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); + + /* Select a role, if necessary */ + /* we'll try to be compatible with pre-selected race/gender/alignment, + * but may not succeed */ + if (flags.initrole < 0) { + char rolenamebuf[QBUFSZ]; + /* Process the choice */ + if (pick4u == 'y' || flags.initrole == ROLE_RANDOM || flags.randomall) { + /* Pick a random role */ + flags.initrole = pick_role(flags.initrace, flags.initgend, + flags.initalign, PICK_RANDOM); + if (flags.initrole < 0) { + /* tty_putstr(BASE_WINDOW, 0, "Incompatible role!"); */ + flags.initrole = randrole(); + } + } else { + /* tty_clear_nhwindow(BASE_WINDOW); */ + /* tty_putstr(BASE_WINDOW, 0, "Choosing Character's Role"); */ + /* Prompt for a role */ + win = create_nhwindow(NHW_MENU); + start_menu(win); + any.a_void = 0; /* zero out all bits */ + for (i = 0; roles[i].name.m; i++) { + if (ok_role(i, flags.initrace, flags.initgend, + flags.initalign)) { + any.a_int = i+1; /* must be non-zero */ + thisch = lowc(roles[i].name.m[0]); + if (thisch == lastch) thisch = highc(thisch); + if (flags.initgend != ROLE_NONE && flags.initgend != ROLE_RANDOM) { + if (flags.initgend == 1 && roles[i].name.f) + Strcpy(rolenamebuf, roles[i].name.f); + else + Strcpy(rolenamebuf, roles[i].name.m); + } else { + if (roles[i].name.f) { + Strcpy(rolenamebuf, roles[i].name.m); + Strcat(rolenamebuf, "/"); + Strcat(rolenamebuf, roles[i].name.f); + } else + Strcpy(rolenamebuf, roles[i].name.m); + } + add_menu(win, NO_GLYPH, &any, thisch, + 0, ATR_NONE, an(rolenamebuf), MENU_UNSELECTED); + lastch = thisch; + } + } + any.a_int = pick_role(flags.initrace, flags.initgend, + flags.initalign, PICK_RANDOM)+1; + if (any.a_int == 0) /* must be non-zero */ + any.a_int = randrole()+1; + add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, + "Random", MENU_UNSELECTED); + any.a_int = i+1; /* must be non-zero */ + add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE, + "Quit", MENU_UNSELECTED); + Sprintf(pbuf, "Pick a role for your %s", plbuf); + end_menu(win, pbuf); + n = select_menu(win, PICK_ONE, &selected); + destroy_nhwindow(win); + + /* Process the choice */ + if (n != 1 || selected[0].item.a_int == any.a_int) + goto give_up; /* Selected quit */ + + flags.initrole = selected[0].item.a_int - 1; + free((genericptr_t) selected), selected = 0; + } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); + } + + /* Select a race, if necessary */ + /* force compatibility with role, try for compatibility with + * pre-selected gender/alignment */ + if (flags.initrace < 0 || !validrace(flags.initrole, flags.initrace)) { + /* pre-selected race not valid */ + if (pick4u == 'y' || flags.initrace == ROLE_RANDOM || flags.randomall) { + flags.initrace = pick_race(flags.initrole, flags.initgend, + flags.initalign, PICK_RANDOM); + if (flags.initrace < 0) { + /* tty_putstr(BASE_WINDOW, 0, "Incompatible race!"); */ + flags.initrace = randrace(flags.initrole); + } + } else { /* pick4u == 'n' */ + /* Count the number of valid races */ + n = 0; /* number valid */ + k = 0; /* valid race */ + for (i = 0; races[i].noun; i++) { + if (ok_race(flags.initrole, i, flags.initgend, + flags.initalign)) { + n++; + k = i; + } + } + if (n == 0) { + for (i = 0; races[i].noun; i++) { + if (validrace(flags.initrole, i)) { + n++; + k = i; + } + } + } + + /* Permit the user to pick, if there is more than one */ + if (n > 1) { + /* tty_clear_nhwindow(BASE_WINDOW); */ + /* tty_putstr(BASE_WINDOW, 0, "Choosing Race"); */ + win = create_nhwindow(NHW_MENU); + start_menu(win); + any.a_void = 0; /* zero out all bits */ + for (i = 0; races[i].noun; i++) + if (ok_race(flags.initrole, i, flags.initgend, + flags.initalign)) { + any.a_int = i+1; /* must be non-zero */ + add_menu(win, NO_GLYPH, &any, races[i].noun[0], + 0, ATR_NONE, races[i].noun, MENU_UNSELECTED); + } + any.a_int = pick_race(flags.initrole, flags.initgend, + flags.initalign, PICK_RANDOM)+1; + if (any.a_int == 0) /* must be non-zero */ + any.a_int = randrace(flags.initrole)+1; + add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, + "Random", MENU_UNSELECTED); + any.a_int = i+1; /* must be non-zero */ + add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE, + "Quit", MENU_UNSELECTED); + Sprintf(pbuf, "Pick the race of your %s", plbuf); + end_menu(win, pbuf); + n = select_menu(win, PICK_ONE, &selected); + destroy_nhwindow(win); + if (n != 1 || selected[0].item.a_int == any.a_int) + goto give_up; /* Selected quit */ + + k = selected[0].item.a_int - 1; + free((genericptr_t) selected), selected = 0; + } + flags.initrace = k; + } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); + } + + /* Select a gender, if necessary */ + /* force compatibility with role/race, try for compatibility with + * pre-selected alignment */ + if (flags.initgend < 0 || !validgend(flags.initrole, flags.initrace, + flags.initgend)) { + /* pre-selected gender not valid */ + if (pick4u == 'y' || flags.initgend == ROLE_RANDOM || flags.randomall) { + flags.initgend = pick_gend(flags.initrole, flags.initrace, + flags.initalign, PICK_RANDOM); + if (flags.initgend < 0) { + /* tty_putstr(BASE_WINDOW, 0, "Incompatible gender!"); */ + flags.initgend = randgend(flags.initrole, flags.initrace); + } + } else { /* pick4u == 'n' */ + /* Count the number of valid genders */ + n = 0; /* number valid */ + k = 0; /* valid gender */ + for (i = 0; i < ROLE_GENDERS; i++) { + if (ok_gend(flags.initrole, flags.initrace, i, + flags.initalign)) { + n++; + k = i; + } + } + if (n == 0) { + for (i = 0; i < ROLE_GENDERS; i++) { + if (validgend(flags.initrole, flags.initrace, i)) { + n++; + k = i; + } + } + } + + /* Permit the user to pick, if there is more than one */ + if (n > 1) { + /* tty_clear_nhwindow(BASE_WINDOW); */ + /* tty_putstr(BASE_WINDOW, 0, "Choosing Gender"); */ + win = create_nhwindow(NHW_MENU); + start_menu(win); + any.a_void = 0; /* zero out all bits */ + for (i = 0; i < ROLE_GENDERS; i++) + if (ok_gend(flags.initrole, flags.initrace, i, + flags.initalign)) { + any.a_int = i+1; + add_menu(win, NO_GLYPH, &any, genders[i].adj[0], + 0, ATR_NONE, genders[i].adj, MENU_UNSELECTED); + } + any.a_int = pick_gend(flags.initrole, flags.initrace, + flags.initalign, PICK_RANDOM)+1; + if (any.a_int == 0) /* must be non-zero */ + any.a_int = randgend(flags.initrole, flags.initrace)+1; + add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, + "Random", MENU_UNSELECTED); + any.a_int = i+1; /* must be non-zero */ + add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE, + "Quit", MENU_UNSELECTED); + Sprintf(pbuf, "Pick the gender of your %s", plbuf); + end_menu(win, pbuf); + n = select_menu(win, PICK_ONE, &selected); + destroy_nhwindow(win); + if (n != 1 || selected[0].item.a_int == any.a_int) + goto give_up; /* Selected quit */ + + k = selected[0].item.a_int - 1; + free((genericptr_t) selected), selected = 0; + } + flags.initgend = k; + } + (void) root_plselection_prompt(plbuf, QBUFSZ - 1, + flags.initrole, flags.initrace, flags.initgend, flags.initalign); + } + + /* Select an alignment, if necessary */ + /* force compatibility with role/race/gender */ + if (flags.initalign < 0 || !validalign(flags.initrole, flags.initrace, + flags.initalign)) { + /* pre-selected alignment not valid */ + if (pick4u == 'y' || flags.initalign == ROLE_RANDOM || flags.randomall) { + flags.initalign = pick_align(flags.initrole, flags.initrace, + flags.initgend, PICK_RANDOM); + if (flags.initalign < 0) { + /* tty_putstr(BASE_WINDOW, 0, "Incompatible alignment!"); */ + flags.initalign = randalign(flags.initrole, flags.initrace); + } + } else { /* pick4u == 'n' */ + /* Count the number of valid alignments */ + n = 0; /* number valid */ + k = 0; /* valid alignment */ + for (i = 0; i < ROLE_ALIGNS; i++) { + if (ok_align(flags.initrole, flags.initrace, flags.initgend, + i)) { + n++; + k = i; + } + } + if (n == 0) { + for (i = 0; i < ROLE_ALIGNS; i++) { + if (validalign(flags.initrole, flags.initrace, i)) { + n++; + k = i; + } + } + } + + /* Permit the user to pick, if there is more than one */ + if (n > 1) { + /* tty_clear_nhwindow(BASE_WINDOW); */ + /* tty_putstr(BASE_WINDOW, 0, "Choosing Alignment"); */ + win = create_nhwindow(NHW_MENU); + start_menu(win); + any.a_void = 0; /* zero out all bits */ + for (i = 0; i < ROLE_ALIGNS; i++) + if (ok_align(flags.initrole, flags.initrace, + flags.initgend, i)) { + any.a_int = i+1; + add_menu(win, NO_GLYPH, &any, aligns[i].adj[0], + 0, ATR_NONE, aligns[i].adj, MENU_UNSELECTED); + } + any.a_int = pick_align(flags.initrole, flags.initrace, + flags.initgend, PICK_RANDOM)+1; + if (any.a_int == 0) /* must be non-zero */ + any.a_int = randalign(flags.initrole, flags.initrace)+1; + add_menu(win, NO_GLYPH, &any , '*', 0, ATR_NONE, + "Random", MENU_UNSELECTED); + any.a_int = i+1; /* must be non-zero */ + add_menu(win, NO_GLYPH, &any , 'q', 0, ATR_NONE, + "Quit", MENU_UNSELECTED); + Sprintf(pbuf, "Pick the alignment of your %s", plbuf); + end_menu(win, pbuf); + n = select_menu(win, PICK_ONE, &selected); + destroy_nhwindow(win); + if (n != 1 || selected[0].item.a_int == any.a_int) + goto give_up; /* Selected quit */ + + k = selected[0].item.a_int - 1; + free((genericptr_t) selected), selected = 0; + } + flags.initalign = k; + } + } + /* Success! */ + /* tty_display_nhwindow(BASE_WINDOW, FALSE); */ +} + +/* Ask the user for a player name. */ +void mswin_askname(void) +{ + logDebug("mswin_askname()\n"); + + if( mswin_getlin_window("Who are you?", plname, PL_NSIZ)==IDCANCEL ) { + bail("bye-bye"); + /* not reached */ + } +} + + +/* Does window event processing (e.g. exposure events). + A noop for the tty and X window-ports. +*/ +void mswin_get_nh_event(void) +{ + logDebug("mswin_get_nh_event()\n"); + return; +} + +/* Exits the window system. This should dismiss all windows, + except the "window" used for raw_print(). str is printed if possible. +*/ +void mswin_exit_nhwindows(const char *str) +{ + logDebug("mswin_exit_nhwindows(%s)\n", str); + /* Write Window settings to the registry */ + mswin_write_reg(); + while (max_brush) + DeleteObject(brush_table[--max_brush]); +} + +/* Prepare the window to be suspended. */ +void mswin_suspend_nhwindows(const char *str) +{ + logDebug("mswin_suspend_nhwindows(%s)\n", str); + return; +} + + +/* Restore the windows after being suspended. */ +void mswin_resume_nhwindows() +{ + logDebug("mswin_resume_nhwindows()\n"); + return; +} + +/* Create a window of type "type" which can be + NHW_MESSAGE (top line) + NHW_STATUS (bottom lines) + NHW_MAP (main dungeon) + NHW_MENU (inventory or other "corner" windows) + NHW_TEXT (help/text, full screen paged window) +*/ +winid +mswin_create_nhwindow(int type) +{ + winid i = 0; + MSNHMsgAddWnd data; + + logDebug("mswin_create_nhwindow(%d)\n", type); + + /* Return the next available winid + */ + + for (i=1; iwindowlist[i].win == NULL && + !GetNHApp()->windowlist[i].dead) + break; + if (i == MAXWINDOWS) + panic ("ERROR: No windows available...\n"); + + switch (type) { + case NHW_MAP: + { + GetNHApp()->windowlist[i].win = mswin_init_map_window(); + GetNHApp()->windowlist[i].type = type; + GetNHApp()->windowlist[i].dead = 0; + break; + } + case NHW_MESSAGE: + { + GetNHApp()->windowlist[i].win = mswin_init_message_window(); + GetNHApp()->windowlist[i].type = type; + GetNHApp()->windowlist[i].dead = 0; + break; + } + case NHW_STATUS: + { + GetNHApp()->windowlist[i].win = mswin_init_status_window(); + GetNHApp()->windowlist[i].type = type; + GetNHApp()->windowlist[i].dead = 0; + break; + } + case NHW_MENU: + { + GetNHApp()->windowlist[i].win = NULL; //will create later + GetNHApp()->windowlist[i].type = type; + GetNHApp()->windowlist[i].dead = 1; + break; + } + case NHW_TEXT: + { + GetNHApp()->windowlist[i].win = mswin_init_text_window(); + GetNHApp()->windowlist[i].type = type; + GetNHApp()->windowlist[i].dead = 0; + break; + } + } + + ZeroMemory(&data, sizeof(data) ); + data.wid = i; + SendMessage( GetNHApp()->hMainWnd, + WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_ADDWND, (LPARAM)&data ); + return i; +} + +/* Clear the given window, when asked to. */ +void mswin_clear_nhwindow(winid wid) +{ + logDebug("mswin_clear_nhwindow(%d)\n", wid); + + if ((wid >= 0) && + (wid < MAXWINDOWS) && + (GetNHApp()->windowlist[wid].win != NULL)) + { +#ifdef REINCARNATION + if( GetNHApp()->windowlist[wid].type == NHW_MAP ) { + if( Is_rogue_level(&u.uz) ) + mswin_map_mode(mswin_hwnd_from_winid(WIN_MAP), ROGUE_LEVEL_MAP_MODE); + else + mswin_map_mode(mswin_hwnd_from_winid(WIN_MAP), iflags.wc_map_mode); + } +#endif + + SendMessage( + GetNHApp()->windowlist[wid].win, + WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_CLEAR_WINDOW, (LPARAM)NULL ); + } +} + +/* -- Display the window on the screen. If there is data + pending for output in that window, it should be sent. + If blocking is TRUE, display_nhwindow() will not + return until the data has been displayed on the screen, + and acknowledged by the user where appropriate. + -- All calls are blocking in the tty window-port. + -- Calling display_nhwindow(WIN_MESSAGE,???) will do a + --more--, if necessary, in the tty window-port. +*/ +void mswin_display_nhwindow(winid wid, BOOLEAN_P block) +{ + logDebug("mswin_display_nhwindow(%d, %d)\n", wid, block); + if (GetNHApp()->windowlist[wid].win != NULL) + { + if (GetNHApp()->windowlist[wid].type == NHW_MENU) { + MENU_ITEM_P* p; + mswin_menu_window_select_menu(GetNHApp()->windowlist[wid].win, PICK_NONE, &p); + } if (GetNHApp()->windowlist[wid].type == NHW_TEXT) { + mswin_display_text_window(GetNHApp()->windowlist[wid].win); + } if (GetNHApp()->windowlist[wid].type == NHW_RIP) { + mswin_display_RIP_window(GetNHApp()->windowlist[wid].win); + } else { + if( !block ) { + UpdateWindow(GetNHApp()->windowlist[wid].win); + } else { + if ( GetNHApp()->windowlist[wid].type == NHW_MAP ) { + (void) mswin_nhgetch(); + } + } + } + SetFocus(GetNHApp()->hMainWnd); + } +} + + +HWND mswin_hwnd_from_winid(winid wid) +{ + if( wid>=0 && widwindowlist[wid].win; + } else { + return NULL; + } +} + +winid mswin_winid_from_handle(HWND hWnd) +{ + winid i = 0; + + for (i=1; iwindowlist[i].win == hWnd) + return i; + return -1; +} + +winid mswin_winid_from_type(int type) +{ + winid i = 0; + + for (i=1; iwindowlist[i].type == type) + return i; + return -1; +} + +void mswin_window_mark_dead(winid wid) +{ + if( wid>=0 && widwindowlist[wid].win = NULL; + GetNHApp()->windowlist[wid].dead = 1; + } +} + +/* Destroy will dismiss the window if the window has not + * already been dismissed. +*/ +void mswin_destroy_nhwindow(winid wid) +{ + logDebug("mswin_destroy_nhwindow(%d)\n", wid); + + if ((GetNHApp()->windowlist[wid].type == NHW_MAP) || + (GetNHApp()->windowlist[wid].type == NHW_MESSAGE) || + (GetNHApp()->windowlist[wid].type == NHW_STATUS)) { + /* main windows is going to take care of those */ + return; + } + + if (GetNHApp()->windowlist[wid].type == NHW_TEXT) { + /* this type takes care of themself */ + return; + } + + if (wid != -1) { + if( !GetNHApp()->windowlist[wid].dead && + GetNHApp()->windowlist[wid].win != NULL ) + DestroyWindow(GetNHApp()->windowlist[wid].win); + GetNHApp()->windowlist[wid].win = NULL; + GetNHApp()->windowlist[wid].type = 0; + GetNHApp()->windowlist[wid].dead = 0; + } +} + +/* Next output to window will start at (x,y), also moves + displayable cursor to (x,y). For backward compatibility, + 1 <= x < cols, 0 <= y < rows, where cols and rows are + the size of window. +*/ +void mswin_curs(winid wid, int x, int y) +{ + logDebug("mswin_curs(%d, %d, %d)\n", wid, x, y); + + if ((wid >= 0) && + (wid < MAXWINDOWS) && + (GetNHApp()->windowlist[wid].win != NULL)) + { + MSNHMsgCursor data; + data.x = x; + data.y = y; + SendMessage( + GetNHApp()->windowlist[wid].win, + WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_CURSOR, (LPARAM)&data ); + } +} + +/* +putstr(window, attr, str) + -- Print str on the window with the given attribute. Only + printable ASCII characters (040-0126) must be supported. + Multiple putstr()s are output on separate lines. +Attributes + can be one of + ATR_NONE (or 0) + ATR_ULINE + ATR_BOLD + ATR_BLINK + ATR_INVERSE + If a window-port does not support all of these, it may map + unsupported attributes to a supported one (e.g. map them + all to ATR_INVERSE). putstr() may compress spaces out of + str, break str, or truncate str, if necessary for the + display. Where putstr() breaks a line, it has to clear + to end-of-line. + -- putstr should be implemented such that if two putstr()s + are done consecutively the user will see the first and + then the second. In the tty port, pline() achieves this + by calling more() or displaying both on the same line. +*/ +void mswin_putstr(winid wid, int attr, const char *text) +{ + logDebug("mswin_putstr(%d, %d, %s)\n", wid, attr, text); + + mswin_putstr_ex(wid, attr, text, 0); +} + +void mswin_putstr_ex(winid wid, int attr, const char *text, boolean app) +{ + if( (wid >= 0) && + (wid < MAXWINDOWS) ) + { + if( GetNHApp()->windowlist[wid].win==NULL && + GetNHApp()->windowlist[wid].type==NHW_MENU ) { + GetNHApp()->windowlist[wid].win = mswin_init_menu_window(MENU_TYPE_TEXT); + GetNHApp()->windowlist[wid].dead = 0; + } + + if (GetNHApp()->windowlist[wid].win != NULL) + { + MSNHMsgPutstr data; + ZeroMemory(&data, sizeof(data)); + data.attr = attr; + data.text = text; + data.append = app; + SendMessage( + GetNHApp()->windowlist[wid].win, + WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_PUTSTR, (LPARAM)&data ); + } + } + else + { + // build text to display later in message box + GetNHApp()->saved_text = realloc(GetNHApp()->saved_text, strlen(text) + + strlen(GetNHApp()->saved_text) + 1); + strcat(GetNHApp()->saved_text, text); + } +} + +/* Display the file named str. Complain about missing files + iff complain is TRUE. +*/ +void mswin_display_file(const char *filename,BOOLEAN_P must_exist) +{ + dlb *f; + TCHAR wbuf[BUFSZ]; + + logDebug("mswin_display_file(%s, %d)\n", filename, must_exist); + + f = dlb_fopen(filename, RDTMODE); + if (!f) { + if (must_exist) { + TCHAR message[90]; + _stprintf(message, TEXT("Warning! Could not find file: %s\n"), NH_A2W(filename, wbuf, sizeof(wbuf))); + MessageBox(GetNHApp()->hMainWnd, message, TEXT("ERROR"), MB_OK | MB_ICONERROR ); + } + } else { + HWND hwnd; + char line[LLEN]; + + hwnd = mswin_init_text_window(); + + while (dlb_fgets(line, LLEN, f)) { + MSNHMsgPutstr data; + size_t len; + + len = strlen(line); + if( line[len-1]=='\n' ) line[len-1]='\x0'; + data.attr = 0; + data.text = line; + SendMessage( hwnd, WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_PUTSTR, (LPARAM)&data ); + } + (void) dlb_fclose(f); + + mswin_display_text_window(hwnd); + } +} + +/* Start using window as a menu. You must call start_menu() + before add_menu(). After calling start_menu() you may not + putstr() to the window. Only windows of type NHW_MENU may + be used for menus. +*/ +void mswin_start_menu(winid wid) +{ + logDebug("mswin_start_menu(%d)\n", wid); + if( (wid >= 0) && + (wid < MAXWINDOWS) ) { + if( GetNHApp()->windowlist[wid].win==NULL && + GetNHApp()->windowlist[wid].type==NHW_MENU ) { + GetNHApp()->windowlist[wid].win = mswin_init_menu_window(MENU_TYPE_MENU); + GetNHApp()->windowlist[wid].dead = 0; + } + + if(GetNHApp()->windowlist[wid].win != NULL) { + SendMessage( + GetNHApp()->windowlist[wid].win, + WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_STARTMENU, (LPARAM)NULL + ); + } + } +} + +/* +add_menu(windid window, int glyph, const anything identifier, + char accelerator, char groupacc, + int attr, char *str, boolean preselected) + -- Add a text line str to the given menu window. If identifier + is 0, then the line cannot be selected (e.g. a title). + Otherwise, identifier is the value returned if the line is + selected. Accelerator is a keyboard key that can be used + to select the line. If the accelerator of a selectable + item is 0, the window system is free to select its own + accelerator. It is up to the window-port to make the + accelerator visible to the user (e.g. put "a - " in front + of str). The value attr is the same as in putstr(). + Glyph is an optional glyph to accompany the line. If + window port cannot or does not want to display it, this + is OK. If there is no glyph applicable, then this + value will be NO_GLYPH. + -- All accelerators should be in the range [A-Za-z]. + -- It is expected that callers do not mix accelerator + choices. Either all selectable items have an accelerator + or let the window system pick them. Don't do both. + -- Groupacc is a group accelerator. It may be any character + outside of the standard accelerator (see above) or a + number. If 0, the item is unaffected by any group + accelerator. If this accelerator conflicts with + the menu command (or their user defined alises), it loses. + The menu commands and aliases take care not to interfere + with the default object class symbols. + -- If you want this choice to be preselected when the + menu is displayed, set preselected to TRUE. +*/ +void mswin_add_menu(winid wid, int glyph, const ANY_P * identifier, + CHAR_P accelerator, CHAR_P group_accel, int attr, + const char *str, BOOLEAN_P presel) +{ + logDebug("mswin_add_menu(%d, %d, %p, %c, %c, %d, %s, %d)\n", + wid, glyph, identifier, (char)accelerator, (char)group_accel, + attr, str, presel); + if ((wid >= 0) && + (wid < MAXWINDOWS) && + (GetNHApp()->windowlist[wid].win != NULL)) + { + MSNHMsgAddMenu data; + ZeroMemory(&data, sizeof(data)); + data.glyph = glyph; + data.identifier = identifier; + data.accelerator = accelerator; + data.group_accel = group_accel; + data.attr = attr; + data.str = str; + data.presel = presel; + + SendMessage( + GetNHApp()->windowlist[wid].win, + WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_ADDMENU, (LPARAM)&data + ); + } +} + +/* +end_menu(window, prompt) + -- Stop adding entries to the menu and flushes the window + to the screen (brings to front?). Prompt is a prompt + to give the user. If prompt is NULL, no prompt will + be printed. + ** This probably shouldn't flush the window any more (if + ** it ever did). That should be select_menu's job. -dean +*/ +void mswin_end_menu(winid wid, const char *prompt) +{ + logDebug("mswin_end_menu(%d, %s)\n", wid, prompt); + if ((wid >= 0) && + (wid < MAXWINDOWS) && + (GetNHApp()->windowlist[wid].win != NULL)) + { + MSNHMsgEndMenu data; + ZeroMemory(&data, sizeof(data)); + data.text = prompt; + + SendMessage( + GetNHApp()->windowlist[wid].win, + WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_ENDMENU, (LPARAM)&data + ); + } +} + +/* +int select_menu(windid window, int how, menu_item **selected) + -- Return the number of items selected; 0 if none were chosen, + -1 when explicitly cancelled. If items were selected, then + selected is filled in with an allocated array of menu_item + structures, one for each selected line. The caller must + free this array when done with it. The "count" field + of selected is a user supplied count. If the user did + not supply a count, then the count field is filled with + -1 (meaning all). A count of zero is equivalent to not + being selected and should not be in the list. If no items + were selected, then selected is NULL'ed out. How is the + mode of the menu. Three valid values are PICK_NONE, + PICK_ONE, and PICK_N, meaning: nothing is selectable, + only one thing is selectable, and any number valid items + may selected. If how is PICK_NONE, this function should + never return anything but 0 or -1. + -- You may call select_menu() on a window multiple times -- + the menu is saved until start_menu() or destroy_nhwindow() + is called on the window. + -- Note that NHW_MENU windows need not have select_menu() + called for them. There is no way of knowing whether + select_menu() will be called for the window at + create_nhwindow() time. +*/ +int mswin_select_menu(winid wid, int how, MENU_ITEM_P **selected) +{ + int nReturned = -1; + + logDebug("mswin_select_menu(%d, %d)\n", wid, how); + + if ((wid >= 0) && + (wid < MAXWINDOWS) && + (GetNHApp()->windowlist[wid].win != NULL)) + { + nReturned = mswin_menu_window_select_menu(GetNHApp()->windowlist[wid].win, how, selected); + } + return nReturned; +} + +/* + -- Indicate to the window port that the inventory has been changed. + -- Merely calls display_inventory() for window-ports that leave the + window up, otherwise empty. +*/ +void mswin_update_inventory() +{ + logDebug("mswin_update_inventory()\n"); +} + +/* +mark_synch() -- Don't go beyond this point in I/O on any channel until + all channels are caught up to here. Can be an empty call + for the moment +*/ +void mswin_mark_synch() +{ + logDebug("mswin_mark_synch()\n"); +} + +/* +wait_synch() -- Wait until all pending output is complete (*flush*() for + streams goes here). + -- May also deal with exposure events etc. so that the + display is OK when return from wait_synch(). +*/ +void mswin_wait_synch() +{ + logDebug("mswin_wait_synch()\n"); +} + +/* +cliparound(x, y)-- Make sure that the user is more-or-less centered on the + screen if the playing area is larger than the screen. + -- This function is only defined if CLIPPING is defined. +*/ +void mswin_cliparound(int x, int y) +{ + winid wid = WIN_MAP; + + logDebug("mswin_cliparound(%d, %d)\n", x, y); + + if ((wid >= 0) && + (wid < MAXWINDOWS) && + (GetNHApp()->windowlist[wid].win != NULL)) + { + MSNHMsgClipAround data; + data.x = x; + data.y = y; + SendMessage( + GetNHApp()->windowlist[wid].win, + WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_CLIPAROUND, (LPARAM)&data ); + } +} + +/* +print_glyph(window, x, y, glyph) + -- Print the glyph at (x,y) on the given window. Glyphs are + integers at the interface, mapped to whatever the window- + port wants (symbol, font, color, attributes, ...there's + a 1-1 map between glyphs and distinct things on the map). +*/ +void mswin_print_glyph(winid wid,XCHAR_P x,XCHAR_P y,int glyph) +{ + logDebug("mswin_print_glyph(%d, %d, %d, %d)\n", wid, x, y, glyph); + + if ((wid >= 0) && + (wid < MAXWINDOWS) && + (GetNHApp()->windowlist[wid].win != NULL)) + { + MSNHMsgPrintGlyph data; + + ZeroMemory(&data, sizeof(data) ); + data.x = x; + data.y = y; + data.glyph = glyph; + SendMessage( GetNHApp()->windowlist[wid].win, + WM_MSNH_COMMAND, (WPARAM)MSNH_MSG_PRINT_GLYPH, (LPARAM)&data ); + } +} + +/* +raw_print(str) -- Print directly to a screen, or otherwise guarantee that + the user sees str. raw_print() appends a newline to str. + It need not recognize ASCII control characters. This is + used during startup (before windowing system initialization + -- maybe this means only error startup messages are raw), + for error messages, and maybe other "msg" uses. E.g. + updating status for micros (i.e, "saving"). +*/ +void mswin_raw_print(const char *str) +{ + TCHAR wbuf[255]; + logDebug("mswin_raw_print(%s)\n", str); + if( str && *str ) + MessageBox(GetNHApp()->hMainWnd, NH_A2W(str, wbuf, sizeof(wbuf)), TEXT("NetHack"), MB_OK ); +} + +/* +raw_print_bold(str) + -- Like raw_print(), but prints in bold/standout (if +possible). +*/ +void mswin_raw_print_bold(const char *str) +{ + TCHAR wbuf[255]; + logDebug("mswin_raw_print_bold(%s)\n", str); + if( str && *str ) + MessageBox(GetNHApp()->hMainWnd, NH_A2W(str, wbuf, sizeof(wbuf)), TEXT("NetHack"), MB_OK ); +} + +/* +int nhgetch() -- Returns a single character input from the user. + -- In the tty window-port, nhgetch() assumes that tgetch() + will be the routine the OS provides to read a character. + Returned character _must_ be non-zero. +*/ +int mswin_nhgetch() +{ + PMSNHEvent event; + int key = 0; + + logDebug("mswin_nhgetch()\n"); + + + while( (event = mswin_input_pop()) == NULL || + event->type != NHEVENT_CHAR ) + mswin_main_loop(); + + key = event->kbd.ch; + return (key); +} + +/* +int nh_poskey(int *x, int *y, int *mod) + -- Returns a single character input from the user or a + a positioning event (perhaps from a mouse). If the + return value is non-zero, a character was typed, else, + a position in the MAP window is returned in x, y and mod. + mod may be one of + + CLICK_1 -- mouse click type 1 + CLICK_2 -- mouse click type 2 + + The different click types can map to whatever the + hardware supports. If no mouse is supported, this + routine always returns a non-zero character. +*/ +int mswin_nh_poskey(int *x, int *y, int *mod) +{ + PMSNHEvent event; + int key; + + logDebug("mswin_nh_poskey()\n"); + + while( (event = mswin_input_pop())==NULL ) mswin_main_loop(); + + if( event->type==NHEVENT_MOUSE ) { + *mod = event->ms.mod; + *x = event->ms.x; + *y = event->ms.y; + key = 0; + } else { + key = event->kbd.ch; + } + return (key); +} + +/* +nhbell() -- Beep at user. [This will exist at least until sounds are + redone, since sounds aren't attributable to windows anyway.] +*/ +void mswin_nhbell() +{ + logDebug("mswin_nhbell()\n"); +} + +/* +doprev_message() + -- Display previous messages. Used by the ^P command. + -- On the tty-port this scrolls WIN_MESSAGE back one line. +*/ +int mswin_doprev_message() +{ + logDebug("mswin_doprev_message()\n"); + return 0; +} + +/* +char yn_function(const char *ques, const char *choices, char default) + -- Print a prompt made up of ques, choices and default. + Read a single character response that is contained in + choices or default. If choices is NULL, all possible + inputs are accepted and returned. This overrides + everything else. The choices are expected to be in + lower case. Entering ESC always maps to 'q', or 'n', + in that order, if present in choices, otherwise it maps + to default. Entering any other quit character (SPACE, + RETURN, NEWLINE) maps to default. + -- If the choices string contains ESC, then anything after + it is an acceptable response, but the ESC and whatever + follows is not included in the prompt. + -- If the choices string contains a '#' then accept a count. + Place this value in the global "yn_number" and return '#'. + -- This uses the top line in the tty window-port, other + ports might use a popup. +*/ +char mswin_yn_function(const char *question, const char *choices, + CHAR_P def) +{ + int result=-1; + char ch; + char yn_esc_map='\033'; + char message[BUFSZ]; + char res_ch[2]; + + logDebug("mswin_yn_function(%s, %s, %d)\n", question, choices, def); + + if (WIN_MESSAGE == WIN_ERR && choices == ynchars) { + char *text = realloc(strdup(GetNHApp()->saved_text), strlen(question) + + strlen(GetNHApp()->saved_text) + 1); + DWORD box_result; + strcat(text, question); + box_result = MessageBox(NULL, + NH_W2A(text, message, sizeof(message)), + TEXT("NetHack for Windows"), + MB_YESNOCANCEL | + ((def == 'y') ? MB_DEFBUTTON1 : + (def == 'n') ? MB_DEFBUTTON2 : MB_DEFBUTTON3)); + free(text); + GetNHApp()->saved_text = strdup(""); + return box_result == IDYES ? 'y' : box_result == IDNO ? 'n' : '\033'; + } + + if (choices) { + char *cb, choicebuf[QBUFSZ]; + Strcpy(choicebuf, choices); + if ((cb = index(choicebuf, '\033')) != 0) { + /* anything beyond is hidden */ + *cb = '\0'; + } + sprintf(message, "%s [%s] ", question, choicebuf); + if (def) sprintf(eos(message), "(%c) ", def); + /* escape maps to 'q' or 'n' or default, in that order */ + yn_esc_map = (index(choices, 'q') ? 'q' : + (index(choices, 'n') ? 'n' : def)); + } else { + Strcpy(message, question); + Strcat(message, " "); + } + + mswin_putstr(WIN_MESSAGE, ATR_BOLD, message); + + /* Only here if main window is not present */ + while (result<0) { + ch=mswin_nhgetch(); + if (ch=='\033') { + result=yn_esc_map; + } else if (choices && !index(choices,ch)) { + /* FYI: ch==-115 is for KP_ENTER */ + if (def && (ch==' ' || ch=='\r' || ch=='\n' || ch==-115)) { + result=def; + } else { + mswin_nhbell(); + /* and try again... */ + } + } else { + result=ch; + } + } + + /* display selection in the message window */ + if( isprint(ch) ) { + res_ch[0] = ch; + res_ch[1] = '\x0'; + mswin_putstr_ex(WIN_MESSAGE, ATR_BOLD, res_ch, 1); + } + + return result; +} + +/* +getlin(const char *ques, char *input) + -- Prints ques as a prompt and reads a single line of text, + up to a newline. The string entered is returned without the + newline. ESC is used to cancel, in which case the string + "\033\000" is returned. + -- getlin() must call flush_screen(1) before doing anything. + -- This uses the top line in the tty window-port, other + ports might use a popup. +*/ +void mswin_getlin(const char *question, char *input) +{ + logDebug("mswin_getlin(%s, %p)\n", question, input); + if( mswin_getlin_window(question, input, BUFSZ)==IDCANCEL ) { + strcpy(input, "\033"); + } +} + +/* +int get_ext_cmd(void) + -- Get an extended command in a window-port specific way. + An index into extcmdlist[] is returned on a successful + selection, -1 otherwise. +*/ +int mswin_get_ext_cmd() +{ + int ret; + logDebug("mswin_get_ext_cmd()\n"); + + if(mswin_ext_cmd_window (&ret) == IDCANCEL) + return -1; + else + return ret; +} + + +/* +number_pad(state) + -- Initialize the number pad to the given state. +*/ +void mswin_number_pad(int state) +{ + /* Do Nothing */ + logDebug("mswin_number_pad(%d)\n", state); +} + +/* +delay_output() -- Causes a visible delay of 50ms in the output. + Conceptually, this is similar to wait_synch() followed + by a nap(50ms), but allows asynchronous operation. +*/ +void mswin_delay_output() +{ + logDebug("mswin_delay_output()\n"); + Sleep(50); +} + +void mswin_change_color() +{ + logDebug("mswin_change_color()\n"); +} + +char *mswin_get_color_string() +{ + logDebug("mswin_get_color_string()\n"); + return( "" ); +} + +/* +start_screen() -- Only used on Unix tty ports, but must be declared for + completeness. Sets up the tty to work in full-screen + graphics mode. Look at win/tty/termcap.c for an + example. If your window-port does not need this function + just declare an empty function. +*/ +void mswin_start_screen() +{ + /* Do Nothing */ + logDebug("mswin_start_screen()\n"); +} + +/* +end_screen() -- Only used on Unix tty ports, but must be declared for + completeness. The complement of start_screen(). +*/ +void mswin_end_screen() +{ + /* Do Nothing */ + logDebug("mswin_end_screen()\n"); +} + +/* +outrip(winid, int) + -- The tombstone code. If you want the traditional code use + genl_outrip for the value and check the #if in rip.c. +*/ +#define STONE_LINE_LEN 16 +void mswin_outrip(winid wid, int how) +{ + char buf[BUFSZ]; + + logDebug("mswin_outrip(%d)\n", wid, how); + if ((wid >= 0) && (wid < MAXWINDOWS) ) { + DestroyWindow(GetNHApp()->windowlist[wid].win); + GetNHApp()->windowlist[wid].win = mswin_init_RIP_window(); + GetNHApp()->windowlist[wid].type = NHW_RIP; + GetNHApp()->windowlist[wid].dead = 0; + } + + /* Put name on stone */ + Sprintf(buf, "%s", plname); + buf[STONE_LINE_LEN] = 0; + putstr(wid, 0, buf); + + /* Put $ on stone */ +#ifndef GOLDOBJ + Sprintf(buf, "%ld Au", u.ugold); +#else + Sprintf(buf, "%ld Au", done_money); +#endif + buf[STONE_LINE_LEN] = 0; /* It could be a *lot* of gold :-) */ + putstr(wid, 0, buf); + + /* Put together death description */ + switch (killer_format) { + default: impossible("bad killer format?"); + case KILLED_BY_AN: + Strcpy(buf, killed_by_prefix[how]); + Strcat(buf, an(killer)); + break; + case KILLED_BY: + Strcpy(buf, killed_by_prefix[how]); + Strcat(buf, killer); + break; + case NO_KILLER_PREFIX: + Strcpy(buf, killer); + break; + } + + /* Put death type on stone */ + putstr(wid, 0, buf); + + /* Put year on stone */ + Sprintf(buf, "%4d", getyear()); + putstr(wid, 0, buf); + mswin_finish_rip_text(wid); +} + +/* handle options updates here */ +void mswin_preference_update(const char *pref) +{ + HDC hdc; + + if( stricmp( pref, "font_menu")==0 || + stricmp( pref, "font_size_menu")==0 ) { + if( iflags.wc_fontsiz_menuNHFONT_SIZE_MAX ) + iflags.wc_fontsiz_menu = NHFONT_DEFAULT_SIZE; + + hdc = GetDC(GetNHApp()->hMainWnd); + mswin_get_font(NHW_MENU, ATR_NONE, hdc, TRUE); + mswin_get_font(NHW_MENU, ATR_BOLD, hdc, TRUE); + mswin_get_font(NHW_MENU, ATR_DIM, hdc, TRUE); + mswin_get_font(NHW_MENU, ATR_ULINE, hdc, TRUE); + mswin_get_font(NHW_MENU, ATR_BLINK, hdc, TRUE); + mswin_get_font(NHW_MENU, ATR_INVERSE, hdc, TRUE); + ReleaseDC(GetNHApp()->hMainWnd, hdc); + + mswin_layout_main_window(NULL); + return; + } + + if( stricmp( pref, "font_status")==0 || + stricmp( pref, "font_size_status")==0 ) { + + if( iflags.wc_fontsiz_statusNHFONT_SIZE_MAX ) + iflags.wc_fontsiz_status = NHFONT_DEFAULT_SIZE; + + hdc = GetDC(GetNHApp()->hMainWnd); + mswin_get_font(NHW_STATUS, ATR_NONE, hdc, TRUE); + mswin_get_font(NHW_STATUS, ATR_BOLD, hdc, TRUE); + mswin_get_font(NHW_STATUS, ATR_DIM, hdc, TRUE); + mswin_get_font(NHW_STATUS, ATR_ULINE, hdc, TRUE); + mswin_get_font(NHW_STATUS, ATR_BLINK, hdc, TRUE); + mswin_get_font(NHW_STATUS, ATR_INVERSE, hdc, TRUE); + ReleaseDC(GetNHApp()->hMainWnd, hdc); + + mswin_layout_main_window(NULL); + return; + } + + if( stricmp( pref, "font_message")==0 || + stricmp( pref, "font_size_message")==0 ) { + + if( iflags.wc_fontsiz_messageNHFONT_SIZE_MAX ) + iflags.wc_fontsiz_message = NHFONT_DEFAULT_SIZE; + + hdc = GetDC(GetNHApp()->hMainWnd); + mswin_get_font(NHW_MESSAGE, ATR_NONE, hdc, TRUE); + mswin_get_font(NHW_MESSAGE, ATR_BOLD, hdc, TRUE); + mswin_get_font(NHW_MESSAGE, ATR_DIM, hdc, TRUE); + mswin_get_font(NHW_MESSAGE, ATR_ULINE, hdc, TRUE); + mswin_get_font(NHW_MESSAGE, ATR_BLINK, hdc, TRUE); + mswin_get_font(NHW_MESSAGE, ATR_INVERSE, hdc, TRUE); + ReleaseDC(GetNHApp()->hMainWnd, hdc); + + mswin_layout_main_window(NULL); + return; + } + + if( stricmp( pref, "font_text")==0 || + stricmp( pref, "font_size_text")==0 ) { + + if( iflags.wc_fontsiz_textNHFONT_SIZE_MAX ) + iflags.wc_fontsiz_text = NHFONT_DEFAULT_SIZE; + + hdc = GetDC(GetNHApp()->hMainWnd); + mswin_get_font(NHW_TEXT, ATR_NONE, hdc, TRUE); + mswin_get_font(NHW_TEXT, ATR_BOLD, hdc, TRUE); + mswin_get_font(NHW_TEXT, ATR_DIM, hdc, TRUE); + mswin_get_font(NHW_TEXT, ATR_ULINE, hdc, TRUE); + mswin_get_font(NHW_TEXT, ATR_BLINK, hdc, TRUE); + mswin_get_font(NHW_TEXT, ATR_INVERSE, hdc, TRUE); + ReleaseDC(GetNHApp()->hMainWnd, hdc); + + mswin_layout_main_window(NULL); + return; + } + + if( stricmp( pref, "scroll_margin")==0 ) { + mswin_cliparound(u.ux, u.uy); + return; + } + + if( stricmp( pref, "map_mode")==0 ) { + mswin_select_map_mode( iflags.wc_map_mode ); + return; + } + + if( stricmp( pref, "hilite_pet")==0 ) { + InvalidateRect(mswin_hwnd_from_winid(WIN_MAP), NULL, TRUE); + return; + } + + if( stricmp( pref, "align_message")==0 || + stricmp( pref, "align_status")==0 ) { + mswin_layout_main_window(NULL); + return; + } + + if( stricmp( pref, "vary_msgcount")==0 ) { + InvalidateRect(mswin_hwnd_from_winid(WIN_MESSAGE), NULL, TRUE); + mswin_layout_main_window(NULL); + return; + } + +} + + +void mswin_main_loop() +{ + MSG msg; + + while( !mswin_have_input() && + GetMessage(&msg, NULL, 0, 0)!=0 ) { + if (GetNHApp()->regNetHackMode || + !TranslateAccelerator(msg.hwnd, GetNHApp()->hAccelTable, &msg)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +} + +/* clean up and quit */ +void bail(const char *mesg) +{ + clearlocks(); + mswin_exit_nhwindows(mesg); + terminate(EXIT_SUCCESS); + /*NOTREACHED*/ +} + +BOOL initMapTiles(void) +{ + HBITMAP hBmp; + BITMAP bm; + TCHAR wbuf[MAX_PATH]; + int tl_num; + SIZE map_size; + extern int total_tiles_used; + + /* no file - no tile */ + if( !(iflags.wc_tile_file && *iflags.wc_tile_file) ) + return TRUE; + + /* load bitmap */ + hBmp = LoadImage( + GetNHApp()->hApp, + NH_A2W(iflags.wc_tile_file, wbuf, MAX_PATH), + IMAGE_BITMAP, + 0, + 0, + LR_LOADFROMFILE | LR_DEFAULTSIZE + ); + if( hBmp==NULL ) { + raw_print("Cannot load tiles from the file. Reverting back to default."); + return FALSE; + } + + /* calculate tile dimensions */ + GetObject(hBmp, sizeof(BITMAP), (LPVOID)&bm); + if( bm.bmWidth%iflags.wc_tile_width || + bm.bmHeight%iflags.wc_tile_height ) { + DeleteObject(hBmp); + raw_print("Tiles bitmap does not match tile_width and tile_height options. Reverting back to default."); + return FALSE; + } + + tl_num = (bm.bmWidth/iflags.wc_tile_width)* + (bm.bmHeight/iflags.wc_tile_height); + if( tl_numbmpMapTiles!=GetNHApp()->bmpTiles ) { + DeleteObject(GetNHApp()->bmpMapTiles); + } + + GetNHApp()->bmpMapTiles = hBmp; + GetNHApp()->mapTile_X = iflags.wc_tile_width; + GetNHApp()->mapTile_Y = iflags.wc_tile_height; + GetNHApp()->mapTilesPerLine = bm.bmWidth / iflags.wc_tile_width; + + map_size.cx = GetNHApp()->mapTile_X * COLNO; + map_size.cy = GetNHApp()->mapTile_Y * ROWNO; + mswin_map_stretch( + mswin_hwnd_from_winid(WIN_MAP), + &map_size, + TRUE + ); + return TRUE; +} + +#ifdef _DEBUG +#include + +void +logDebug(const char *fmt, ...) +{ + FILE *dfp = fopen("nhtrace.log", "a"); + + if (dfp) { + va_list args; + + va_start(args, fmt); + vfprintf(dfp, fmt, args); + va_end(args); + fclose(dfp); + } +} + +#endif + + +/* Reading and writing settings from the registry. */ +#define CATEGORYKEY "Software" +#define COMPANYKEY "NetHack" +#define PRODUCTKEY "NetHack 3.4.0" +#define SETTINGSKEY "Settings" + +/* #define all the subkeys here */ +#define INTFKEY "Interface" + +void +mswin_read_reg() +{ + HKEY key; + DWORD size; + char keystring[MAX_PATH]; + + sprintf(keystring, "%s\\%s\\%s\\%s", + CATEGORYKEY, COMPANYKEY, PRODUCTKEY, SETTINGSKEY); + + /* Set the defaults here. The very first time the app is started, nothing is + read from the registry, so these defaults apply. */ + GetNHApp()->saveRegistrySettings = 1; /* Normally, we always save */ + GetNHApp()->regNetHackMode = 0; + + if (RegOpenKeyEx(HKEY_CURRENT_USER, keystring, 0, KEY_READ, &key) + != ERROR_SUCCESS) + return; + + /* Read the keys here. */ + size = sizeof(DWORD); + RegQueryValueEx(key, INTFKEY, 0, NULL, + (unsigned char *)(&(GetNHApp()->regNetHackMode)), &size); + + RegCloseKey(key); +} + +void +mswin_write_reg() +{ + HKEY key; + DWORD disposition; + + if (GetNHApp()->saveRegistrySettings) + { + char keystring[MAX_PATH]; + + sprintf(keystring, "%s\\%s\\%s\\%s", + CATEGORYKEY, COMPANYKEY, PRODUCTKEY, SETTINGSKEY); + + if (RegOpenKeyEx(HKEY_CURRENT_USER, keystring, 0, KEY_WRITE, &key) != ERROR_SUCCESS) + { + RegCreateKeyEx(HKEY_CURRENT_USER, keystring, 0, "", + REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &key, &disposition); + } + + /* Write the keys here */ + RegSetValueEx(key, INTFKEY, 0, REG_DWORD, (unsigned char *)(&(GetNHApp()->regNetHackMode)), sizeof(DWORD)); + + RegCloseKey(key); + } +} + +void +mswin_destroy_reg() +{ + char keystring[MAX_PATH]; + HKEY key; + DWORD nrsubkeys; + + /* Delete keys one by one, as NT does not delete trees */ + sprintf(keystring, "%s\\%s\\%s\\%s", + CATEGORYKEY, COMPANYKEY, PRODUCTKEY, SETTINGSKEY); + RegDeleteKey(HKEY_CURRENT_USER, keystring); + sprintf(keystring, "%s\\%s\\%s", + CATEGORYKEY, COMPANYKEY, PRODUCTKEY); + RegDeleteKey(HKEY_CURRENT_USER, keystring); + /* The company key will also contain information about newer versions + of nethack (e.g. a subkey called NetHack 4.0), so only delete that + if it's empty now. */ + sprintf(keystring, "%s\\%s", CATEGORYKEY, COMPANYKEY); + /* If we cannot open it, we probably cannot delete it either... Just + go on and see what happens. */ + RegOpenKeyEx(HKEY_CURRENT_USER, keystring, 0, KEY_READ, &key); + nrsubkeys = 0; + RegQueryInfoKey(key, NULL, NULL, NULL, &nrsubkeys, NULL, NULL, NULL, + NULL, NULL, NULL, NULL); + RegCloseKey(key); + if (nrsubkeys == 0) + RegDeleteKey(HKEY_CURRENT_USER, keystring); + + /* Prevent saving on exit */ + GetNHApp()->saveRegistrySettings = 0; +} + +typedef struct ctv +{ + const char *colorstring; + COLORREF colorvalue; +} color_table_value; + +/* + * The color list here is a combination of: + * NetHack colors. (See mhmap.c) + * HTML colors. (See http://www.w3.org/TR/REC-html40/types.html#h-6.5 ) + */ + +static color_table_value color_table[] = { +/* NetHack colors */ + { "black", RGB(0x55, 0x55, 0x55)}, + { "red", RGB(0xFF, 0x00, 0x00)}, + { "green", RGB(0x00, 0x80, 0x00)}, + { "brown", RGB(0xA5, 0x2A, 0x2A)}, + { "blue", RGB(0x00, 0x00, 0xFF)}, + { "magenta", RGB(0xFF, 0x00, 0xFF)}, + { "cyan", RGB(0x00, 0xFF, 0xFF)}, + { "orange", RGB(0xFF, 0xA5, 0x00)}, + { "brightgreen", RGB(0x00, 0xFF, 0x00)}, + { "yellow", RGB(0xFF, 0xFF, 0x00)}, + { "brightblue", RGB(0x00, 0xC0, 0xFF)}, + { "brightmagenta", RGB(0xFF, 0x80, 0xFF)}, + { "brightcyan", RGB(0x80, 0xFF, 0xFF)}, + { "white", RGB(0xFF, 0xFF, 0xFF)}, +/* Remaining HTML colors */ + { "trueblack", RGB(0x00, 0x00, 0x00)}, + { "gray", RGB(0x80, 0x80, 0x80)}, + { "grey", RGB(0x80, 0x80, 0x80)}, + { "purple", RGB(0x80, 0x00, 0x80)}, + { "silver", RGB(0xC0, 0xC0, 0xC0)}, + { "maroon", RGB(0x80, 0x00, 0x00)}, + { "fuchsia", RGB(0xFF, 0x00, 0xFF)}, /* = NetHack magenta */ + { "lime", RGB(0x00, 0xFF, 0x00)}, /* = NetHack bright green */ + { "olive", RGB(0x80, 0x80, 0x00)}, + { "navy", RGB(0x00, 0x00, 0x80)}, + { "teal", RGB(0x00, 0x80, 0x80)}, + { "aqua", RGB(0x00, 0xFF, 0xFF)}, /* = NetHack cyan */ + { "", RGB(0x00, 0x00, 0x00)}, +}; + +typedef struct ctbv +{ + char *colorstring; + int syscolorvalue; +} color_table_brush_value; + +static color_table_brush_value color_table_brush[] = { + { "activeborder", COLOR_ACTIVEBORDER }, + { "activecaption", COLOR_ACTIVECAPTION }, + { "appworkspace", COLOR_APPWORKSPACE }, + { "background", COLOR_BACKGROUND }, + { "btnface", COLOR_BTNFACE }, + { "btnshadow", COLOR_BTNSHADOW }, + { "btntext", COLOR_BTNTEXT }, + { "captiontext", COLOR_CAPTIONTEXT }, + { "graytext", COLOR_GRAYTEXT }, + { "greytext", COLOR_GRAYTEXT }, + { "highlight", COLOR_HIGHLIGHT }, + { "highlighttext", COLOR_HIGHLIGHTTEXT }, + { "inactiveborder", COLOR_INACTIVEBORDER }, + { "inactivecaption", COLOR_INACTIVECAPTION }, + { "menu", COLOR_MENU }, + { "menutext", COLOR_MENUTEXT }, + { "scrollbar", COLOR_SCROLLBAR }, + { "window", COLOR_WINDOW }, + { "windowframe", COLOR_WINDOWFRAME }, + { "windowtext", COLOR_WINDOWTEXT }, + { "", -1 }, +}; + +static void mswin_color_from_string(char *colorstring, HBRUSH* brushptr, COLORREF *colorptr) +{ + color_table_value *ctv_ptr = color_table; + color_table_brush_value *ctbv_ptr = color_table_brush; + int red_value, blue_value, green_value; + static char *hexadecimals = "0123456789abcdef"; + + if (colorstring == NULL) return; + if (*colorstring == '#') { + if (strlen(++colorstring) != 6) return; + + red_value = index(hexadecimals, tolower(*colorstring++)) - hexadecimals; + red_value *= 16; + red_value += index(hexadecimals, tolower(*colorstring++)) - hexadecimals; + + green_value = index(hexadecimals, tolower(*colorstring++)) - hexadecimals; + green_value *= 16; + green_value += index(hexadecimals, tolower(*colorstring++)) - hexadecimals; + + blue_value = index(hexadecimals, tolower(*colorstring++)) - hexadecimals; + blue_value *= 16; + blue_value += index(hexadecimals, tolower(*colorstring++)) - hexadecimals; + + *colorptr = RGB(red_value, blue_value, green_value); + } else { + while (*ctv_ptr->colorstring && stricmp(ctv_ptr->colorstring, colorstring)) + ++ctv_ptr; + if (*ctv_ptr->colorstring) { + *colorptr = ctv_ptr->colorvalue; + } else { + while (*ctbv_ptr->colorstring && stricmp(ctbv_ptr->colorstring, colorstring)) + ++ctbv_ptr; + if (*ctbv_ptr->colorstring) { + *brushptr = SYSCLR_TO_BRUSH(ctbv_ptr->syscolorvalue); + *colorptr = GetSysColor(ctbv_ptr->syscolorvalue); + } + } + } + if (max_brush > TOTAL_BRUSHES) panic("Too many colors!"); + *brushptr = CreateSolidBrush(*colorptr); + brush_table[max_brush++] = *brushptr; +} diff --git a/win/win32/nethack.dsw b/win/win32/nethack.dsw new file mode 100644 index 0000000..d773e0a --- /dev/null +++ b/win/win32/nethack.dsw @@ -0,0 +1,215 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "dgncomp"=.\build\dgncomp.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name dgnstuff + End Project Dependency +}}} + +############################################################################### + +Project: "dgnstuff"=.\build\dgnstuff.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name makedefs + End Project Dependency +}}} + +############################################################################### + +Project: "dlb_main"=.\build\dlb_main.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name dgncomp + End Project Dependency + Begin Project Dependency + Project_Dep_Name levcomp + End Project Dependency + Begin Project Dependency + Project_Dep_Name makedefs + End Project Dependency +}}} + +############################################################################### + +Project: "levcomp"=.\build\levcomp.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name levstuff + End Project Dependency +}}} + +############################################################################### + +Project: "levstuff"=.\build\levstuff.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name makedefs + End Project Dependency +}}} + +############################################################################### + +Project: "makedefs"=.\build\makedefs.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "nethackw"=.\build\nethackw.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name dgncomp + End Project Dependency + Begin Project Dependency + Project_Dep_Name dlb_main + End Project Dependency + Begin Project Dependency + Project_Dep_Name levcomp + End Project Dependency + Begin Project Dependency + Project_Dep_Name makedefs + End Project Dependency + Begin Project Dependency + Project_Dep_Name recover + End Project Dependency + Begin Project Dependency + Project_Dep_Name tilemap + End Project Dependency + Begin Project Dependency + Project_Dep_Name tiles + End Project Dependency + Begin Project Dependency + Project_Dep_Name uudecode + End Project Dependency +}}} + +############################################################################### + +Project: "recover"=.\build\recover.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name makedefs + End Project Dependency + Begin Project Dependency + Project_Dep_Name dlb_main + End Project Dependency +}}} + +############################################################################### + +Project: "tile2bmp"=.\build\tile2bmp.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "tilemap"=.\build\tilemap.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "tiles"=.\build\tiles.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name tile2bmp + End Project Dependency +}}} + +############################################################################### + +Project: "uudecode"=.\build\uudecode.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/win/win32/nethackw.dsp b/win/win32/nethackw.dsp new file mode 100644 index 0000000..e501da6 --- /dev/null +++ b/win/win32/nethackw.dsp @@ -0,0 +1,1108 @@ +# Microsoft Developer Studio Project File - Name="nethackw" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=nethackw - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "nethackw.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "nethackw.mak" CFG="nethackw - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "nethackw - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "nethackw - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "nethackw - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /Og /Oy /Ob1 /Gs /Gf /Gy /Oi- /Ot /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /W3 /GX /Og /Oy /Ob1 /Gs /Gf /Gy /Oi- /Ot /I "..\win\win32" /I "..\include" /I "..\sys\winnt" /I "..\sys\share" /I "..\win\share" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "DLB" /D "MSWIN_GRAPHICS" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /machine:I386 +# Begin Special Build Tool +OutDir=.\Release +SOURCE="$(InputPath)" +PostBuild_Desc=Install exe +PostBuild_Cmds=copy $(OutDir)\nethackw.exe ..\binary \ +copy ..\dat\nhdat ..\binary \ +copy ..\dat\license ..\binary \ +if exist tiles.bmp copy tiles.bmp ..\binary \ +if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt \ +if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt \ +if exist ..\doc\recover.txt copy ..\doc\recover.txt ..\binary\recover.txt \ +copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh +# End Special Build Tool + +!ELSEIF "$(CFG)" == "nethackw - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\win\win32" /I "..\include" /I "..\sys\winnt" /I "..\sys\share" /I "..\win\share" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "DLB" /D "MSWIN_GRAPHICS" /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# Begin Special Build Tool +OutDir=.\Debug +SOURCE="$(InputPath)" +PostBuild_Desc=Install exe +PostBuild_Cmds=if NOT exist ..\binary\*.* mkdir ..\binary \ +copy $(OutDir)\nethackw.exe ..\binary \ +copy ..\dat\nhdat ..\binary \ +copy ..\dat\license ..\binary \ +if exist tiles.bmp copy tiles.bmp ..\binary \ +if exist ..\doc\Guidebook.txt copy ..\doc\Guidebook.txt ..\binary\Guidebook.txt \ +if exist ..\doc\nethack.txt copy ..\doc\nethack.txt ..\binary\NetHack.txt \ +if exist ..\doc\recover.txt copy ..\doc\recover.txt ..\binary\recover.txt \ +copy ..\sys\winnt\defaults.nh ..\binary\defaults.nh +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "nethackw - Win32 Release" +# Name "nethackw - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\src\allmain.c +# End Source File +# Begin Source File + +SOURCE=..\src\alloc.c +# End Source File +# Begin Source File + +SOURCE=..\src\apply.c +# End Source File +# Begin Source File + +SOURCE=..\src\artifact.c +# End Source File +# Begin Source File + +SOURCE=..\src\attrib.c +# End Source File +# Begin Source File + +SOURCE=..\src\ball.c +# End Source File +# Begin Source File + +SOURCE=..\src\bones.c +# End Source File +# Begin Source File + +SOURCE=..\src\botl.c +# End Source File +# Begin Source File + +SOURCE=..\src\cmd.c +# End Source File +# Begin Source File + +SOURCE=..\src\dbridge.c +# End Source File +# Begin Source File + +SOURCE=..\src\decl.c +# End Source File +# Begin Source File + +SOURCE=..\src\detect.c +# End Source File +# Begin Source File + +SOURCE=..\src\dig.c +# End Source File +# Begin Source File + +SOURCE=..\src\display.c +# End Source File +# Begin Source File + +SOURCE=..\src\dlb.c +# End Source File +# Begin Source File + +SOURCE=..\src\do.c +# End Source File +# Begin Source File + +SOURCE=..\src\do_name.c +# End Source File +# Begin Source File + +SOURCE=..\src\do_wear.c +# End Source File +# Begin Source File + +SOURCE=..\src\dog.c +# End Source File +# Begin Source File + +SOURCE=..\src\dogmove.c +# End Source File +# Begin Source File + +SOURCE=..\src\dokick.c +# End Source File +# Begin Source File + +SOURCE=..\src\dothrow.c +# End Source File +# Begin Source File + +SOURCE=..\src\drawing.c +# End Source File +# Begin Source File + +SOURCE=..\src\dungeon.c +# End Source File +# Begin Source File + +SOURCE=..\src\eat.c +# End Source File +# Begin Source File + +SOURCE=..\src\end.c +# End Source File +# Begin Source File + +SOURCE=..\src\engrave.c +# End Source File +# Begin Source File + +SOURCE=..\src\exper.c +# End Source File +# Begin Source File + +SOURCE=..\src\explode.c +# End Source File +# Begin Source File + +SOURCE=..\src\extralev.c +# End Source File +# Begin Source File + +SOURCE=..\src\files.c +# End Source File +# Begin Source File + +SOURCE=..\src\fountain.c +# End Source File +# Begin Source File + +SOURCE=..\win\tty\getline.c +# End Source File +# Begin Source File + +SOURCE=..\src\hack.c +# End Source File +# Begin Source File + +SOURCE=..\src\hacklib.c +# End Source File +# Begin Source File + +SOURCE=..\src\invent.c +# End Source File +# Begin Source File + +SOURCE=..\src\light.c +# End Source File +# Begin Source File + +SOURCE=..\src\lock.c +# End Source File +# Begin Source File + +SOURCE=..\src\mail.c +# End Source File +# Begin Source File + +SOURCE=..\src\makemon.c +# End Source File +# Begin Source File + +SOURCE=..\src\mapglyph.c +# End Source File +# Begin Source File + +SOURCE=..\src\mcastu.c +# End Source File +# Begin Source File + +SOURCE=..\src\mhitm.c +# End Source File +# Begin Source File + +SOURCE=..\src\mhitu.c +# End Source File +# Begin Source File + +SOURCE=..\src\minion.c +# End Source File +# Begin Source File + +SOURCE=..\src\mklev.c +# End Source File +# Begin Source File + +SOURCE=..\src\mkmap.c +# End Source File +# Begin Source File + +SOURCE=..\src\mkmaze.c +# End Source File +# Begin Source File + +SOURCE=..\src\mkobj.c +# End Source File +# Begin Source File + +SOURCE=..\src\mkroom.c +# End Source File +# Begin Source File + +SOURCE=..\src\mon.c +# End Source File +# Begin Source File + +SOURCE=..\src\mondata.c +# End Source File +# Begin Source File + +SOURCE=..\src\monmove.c +# End Source File +# Begin Source File + +SOURCE=..\src\monst.c +# End Source File +# Begin Source File + +SOURCE=..\src\monstr.c +# End Source File +# Begin Source File + +SOURCE=..\src\mplayer.c +# End Source File +# Begin Source File + +SOURCE=..\src\mthrowu.c +# End Source File +# Begin Source File + +SOURCE=..\src\muse.c +# End Source File +# Begin Source File + +SOURCE=..\src\music.c +# End Source File +# Begin Source File + +SOURCE=..\src\o_init.c +# End Source File +# Begin Source File + +SOURCE=..\src\objects.c +# End Source File +# Begin Source File + +SOURCE=..\src\objnam.c +# End Source File +# Begin Source File + +SOURCE=..\src\options.c +# End Source File +# Begin Source File + +SOURCE=..\src\pager.c +# End Source File +# Begin Source File + +SOURCE=..\sys\share\pcmain.c +# End Source File +# Begin Source File + +SOURCE=..\sys\share\pcsys.c +# End Source File +# Begin Source File + +SOURCE=..\sys\share\pcunix.c +# End Source File +# Begin Source File + +SOURCE=..\src\pickup.c +# End Source File +# Begin Source File + +SOURCE=..\src\pline.c +# End Source File +# Begin Source File + +SOURCE=..\src\polyself.c +# End Source File +# Begin Source File + +SOURCE=..\src\potion.c +# End Source File +# Begin Source File + +SOURCE=..\src\pray.c +# End Source File +# Begin Source File + +SOURCE=..\src\priest.c +# End Source File +# Begin Source File + +SOURCE=..\src\quest.c +# End Source File +# Begin Source File + +SOURCE=..\src\questpgr.c +# End Source File +# Begin Source File + +SOURCE=..\sys\share\random.c +# End Source File +# Begin Source File + +SOURCE=..\src\read.c +# End Source File +# Begin Source File + +SOURCE=..\src\rect.c +# End Source File +# Begin Source File + +SOURCE=..\src\region.c +# End Source File +# Begin Source File + +SOURCE=..\src\restore.c +# End Source File +# Begin Source File + +SOURCE=..\src\rip.c +# End Source File +# Begin Source File + +SOURCE=..\src\rnd.c +# End Source File +# Begin Source File + +SOURCE=..\src\role.c +# End Source File +# Begin Source File + +SOURCE=..\src\rumors.c +# End Source File +# Begin Source File + +SOURCE=..\src\save.c +# End Source File +# Begin Source File + +SOURCE=..\src\shk.c +# End Source File +# Begin Source File + +SOURCE=..\src\shknam.c +# End Source File +# Begin Source File + +SOURCE=..\src\sit.c +# End Source File +# Begin Source File + +SOURCE=..\src\sounds.c +# End Source File +# Begin Source File + +SOURCE=..\src\sp_lev.c +# End Source File +# Begin Source File + +SOURCE=..\src\spell.c +# End Source File +# Begin Source File + +SOURCE=..\src\steal.c +# End Source File +# Begin Source File + +SOURCE=..\src\steed.c +# End Source File +# Begin Source File + +SOURCE=..\src\teleport.c +# End Source File +# Begin Source File + +SOURCE=..\src\tile.c +# End Source File +# Begin Source File + +SOURCE=..\src\timeout.c +# End Source File +# Begin Source File + +SOURCE=..\src\topten.c +# End Source File +# Begin Source File + +SOURCE=..\src\track.c +# End Source File +# Begin Source File + +SOURCE=..\src\trap.c +# End Source File +# Begin Source File + +SOURCE=..\src\u_init.c +# End Source File +# Begin Source File + +SOURCE=..\src\uhitm.c +# End Source File +# Begin Source File + +SOURCE=..\src\vault.c +# End Source File +# Begin Source File + +SOURCE=..\src\version.c +# End Source File +# Begin Source File + +SOURCE=..\src\vision.c +# End Source File +# Begin Source File + +SOURCE=..\src\weapon.c +# End Source File +# Begin Source File + +SOURCE=..\src\were.c +# End Source File +# Begin Source File + +SOURCE=..\src\wield.c +# End Source File +# Begin Source File + +SOURCE=..\src\windows.c +# End Source File +# Begin Source File + +SOURCE=..\sys\winnt\winnt.c +# End Source File +# Begin Source File + +SOURCE=..\win\tty\wintty.c +# End Source File +# Begin Source File + +SOURCE=..\src\wizard.c +# End Source File +# Begin Source File + +SOURCE=..\src\worm.c +# End Source File +# Begin Source File + +SOURCE=..\src\worn.c +# End Source File +# Begin Source File + +SOURCE=..\src\write.c +# End Source File +# Begin Source File + +SOURCE=..\src\zap.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\include\align.h +# End Source File +# Begin Source File + +SOURCE=..\include\amiconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\artifact.h +# End Source File +# Begin Source File + +SOURCE=..\include\artilist.h +# End Source File +# Begin Source File + +SOURCE=..\include\attrib.h +# End Source File +# Begin Source File + +SOURCE=..\include\beconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\bitmfile.h +# End Source File +# Begin Source File + +SOURCE=..\include\color.h +# End Source File +# Begin Source File + +SOURCE=..\include\config.h +# End Source File +# Begin Source File + +SOURCE=..\include\config1.h +# End Source File +# Begin Source File + +SOURCE=..\include\coord.h +# End Source File +# Begin Source File + +SOURCE=..\include\decl.h +# End Source File +# Begin Source File + +SOURCE=..\include\def_os2.h +# End Source File +# Begin Source File + +SOURCE=..\include\dgn_file.h +# End Source File +# Begin Source File + +SOURCE=..\include\display.h +# End Source File +# Begin Source File + +SOURCE=..\include\dlb.h +# End Source File +# Begin Source File + +SOURCE=..\include\dungeon.h +# End Source File +# Begin Source File + +SOURCE=..\include\edog.h +# End Source File +# Begin Source File + +SOURCE=..\include\emin.h +# End Source File +# Begin Source File + +SOURCE=..\include\engrave.h +# End Source File +# Begin Source File + +SOURCE=..\include\epri.h +# End Source File +# Begin Source File + +SOURCE=..\include\eshk.h +# End Source File +# Begin Source File + +SOURCE=..\include\extern.h +# End Source File +# Begin Source File + +SOURCE=..\include\flag.h +# End Source File +# Begin Source File + +SOURCE=..\include\func_tab.h +# End Source File +# Begin Source File + +SOURCE=..\include\gem_rsc.h +# End Source File +# Begin Source File + +SOURCE=..\include\global.h +# End Source File +# Begin Source File + +SOURCE=..\include\hack.h +# End Source File +# Begin Source File + +SOURCE=..\include\lev.h +# End Source File +# Begin Source File + +SOURCE=..\include\load_img.h +# End Source File +# Begin Source File + +SOURCE=..\include\macconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\macpopup.h +# End Source File +# Begin Source File + +SOURCE=..\include\mactty.h +# End Source File +# Begin Source File + +SOURCE=..\include\macwin.h +# End Source File +# Begin Source File + +SOURCE=..\include\mail.h +# End Source File +# Begin Source File + +SOURCE=..\include\mfndpos.h +# End Source File +# Begin Source File + +SOURCE=..\include\micro.h +# End Source File +# Begin Source File + +SOURCE=..\include\mkroom.h +# End Source File +# Begin Source File + +SOURCE=..\include\monattk.h +# End Source File +# Begin Source File + +SOURCE=..\include\mondata.h +# End Source File +# Begin Source File + +SOURCE=..\include\monflag.h +# End Source File +# Begin Source File + +SOURCE=..\include\monst.h +# End Source File +# Begin Source File + +SOURCE=..\include\monsym.h +# End Source File +# Begin Source File + +SOURCE=..\include\mttypriv.h +# End Source File +# Begin Source File + +SOURCE=..\include\nhlan.h +# End Source File +# Begin Source File + +SOURCE=..\include\ntconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\obj.h +# End Source File +# Begin Source File + +SOURCE=..\include\objclass.h +# End Source File +# Begin Source File + +SOURCE=..\include\os2conf.h +# End Source File +# Begin Source File + +SOURCE=..\include\patchlevel.h +# End Source File +# Begin Source File + +SOURCE=..\include\pcconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\permonst.h +# End Source File +# Begin Source File + +SOURCE=..\include\prop.h +# End Source File +# Begin Source File + +SOURCE=..\include\qt_clust.h +# End Source File +# Begin Source File + +SOURCE=..\include\qt_kde0.h +# End Source File +# Begin Source File + +SOURCE=..\include\qt_win.h +# End Source File +# Begin Source File + +SOURCE=..\include\qt_xpms.h +# End Source File +# Begin Source File + +SOURCE=..\include\qtext.h +# End Source File +# Begin Source File + +SOURCE=..\include\quest.h +# End Source File +# Begin Source File + +SOURCE=..\include\rect.h +# End Source File +# Begin Source File + +SOURCE=..\include\region.h +# End Source File +# Begin Source File + +SOURCE=..\include\rm.h +# End Source File +# Begin Source File + +SOURCE=..\include\skills.h +# End Source File +# Begin Source File + +SOURCE=..\include\sp_lev.h +# End Source File +# Begin Source File + +SOURCE=..\include\spell.h +# End Source File +# Begin Source File + +SOURCE=..\include\system.h +# End Source File +# Begin Source File + +SOURCE=..\include\tcap.h +# End Source File +# Begin Source File + +SOURCE=..\include\tile2x11.h +# End Source File +# Begin Source File + +SOURCE=..\include\timeout.h +# End Source File +# Begin Source File + +SOURCE=..\include\tosconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\tradstdc.h +# End Source File +# Begin Source File + +SOURCE=..\include\trampoli.h +# End Source File +# Begin Source File + +SOURCE=..\include\trap.h +# End Source File +# Begin Source File + +SOURCE=..\include\unixconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\vault.h +# End Source File +# Begin Source File + +SOURCE=..\include\vision.h +# End Source File +# Begin Source File + +SOURCE=..\include\vmsconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\winami.h +# End Source File +# Begin Source File + +SOURCE=..\include\wingem.h +# End Source File +# Begin Source File + +SOURCE=..\include\winGnome.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\winhack.h +# End Source File +# Begin Source File + +SOURCE=..\include\winprocs.h +# End Source File +# Begin Source File + +SOURCE=..\include\wintty.h +# End Source File +# Begin Source File + +SOURCE=..\include\wintype.h +# End Source File +# Begin Source File + +SOURCE=..\include\winX.h +# End Source File +# Begin Source File + +SOURCE=..\include\xwindow.h +# End Source File +# Begin Source File + +SOURCE=..\include\xwindowp.h +# End Source File +# Begin Source File + +SOURCE=..\include\you.h +# End Source File +# Begin Source File + +SOURCE=..\include\youprop.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=..\win\win32\bitmap1.bmp +# End Source File +# Begin Source File + +SOURCE=..\win\win32\bitmap2.bmp +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mnsel.bmp +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mnunsel.bmp +# End Source File +# Begin Source File + +SOURCE=..\win\win32\NETHACK.ICO +# End Source File +# Begin Source File + +SOURCE=..\win\win32\small.ico +# End Source File +# Begin Source File + +SOURCE=..\win\win32\tiles.bmp +# End Source File +# Begin Source File + +SOURCE=..\win\win32\winhack.ico +# End Source File +# End Group +# Begin Group "wnd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\win\win32\mhaskyn.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhaskyn.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhdlg.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhdlg.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhfont.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhfont.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhinput.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhinput.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhmain.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhmain.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhmap.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhmap.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhmenu.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhmenu.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhmsg.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhmsgwnd.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhmsgwnd.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhsplash.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhrip.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhsplash.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhrip.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhstatus.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhstatus.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhtext.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mhtext.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\mswproc.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\resource.h +# End Source File +# Begin Source File + +SOURCE=..\win\win32\winhack.c +# End Source File +# Begin Source File + +SOURCE=..\win\win32\winhack.rc +# End Source File +# Begin Source File + +SOURCE=..\win\win32\winMS.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\win\win32\ReadMe.txt +# End Source File +# End Target +# End Project diff --git a/win/win32/petmark.uu b/win/win32/petmark.uu new file mode 100644 index 0000000..deace34 --- /dev/null +++ b/win/win32/petmark.uu @@ -0,0 +1,9 @@ +begin 600 petmark.bmp +M0DWV`````````'8````H````$````!`````!``0``````(`````````````` +M````````````;&Q'````_P```````("``(````"``(``@(```,#`P`#`W,`` +M\,JF``0$!``("`@`#`P,`!$1$0`6%A8`'!P<```````````````````````` +M```````````````````````````````````````````````````````````` +M``````````````````````````````````````````````````````$````` +5````$1````````$1$0```````!`0 +` +end diff --git a/win/win32/recover.dsp b/win/win32/recover.dsp new file mode 100644 index 0000000..39dca3c --- /dev/null +++ b/win/win32/recover.dsp @@ -0,0 +1,146 @@ +# Microsoft Developer Studio Project File - Name="recover" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=recover - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "recover.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "recover.mak" CFG="recover - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "recover - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "recover - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "recover - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\sys\winnt" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32CON" /D "DLB" /D "MSWIN_GRAPHICS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x1009 /d "NDEBUG" +# ADD RSC /l 0x1009 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# Begin Special Build Tool +OutDir=.\Release +SOURCE="$(InputPath)" +PostBuild_Cmds=copy $(OutDir)\recover.exe ..\binary +# End Special Build Tool + +!ELSEIF "$(CFG)" == "recover - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /I "..\sys\winnt" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32CON" /D "DLB" /D "MSWIN_GRAPHICS" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x1009 /d "_DEBUG" +# ADD RSC /l 0x1009 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# Begin Special Build Tool +OutDir=.\Debug +SOURCE="$(InputPath)" +PostBuild_Desc=install exe +PostBuild_Cmds=copy $(OutDir)\recover.exe ..\binary +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "recover - Win32 Release" +# Name "recover - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\util\recover.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\include\config.h +# End Source File +# Begin Source File + +SOURCE=..\include\config1.h +# End Source File +# Begin Source File + +SOURCE=..\include\coord.h +# End Source File +# Begin Source File + +SOURCE=..\include\global.h +# End Source File +# Begin Source File + +SOURCE=..\include\nhlan.h +# End Source File +# Begin Source File + +SOURCE=..\include\ntconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\tradstdc.h +# End Source File +# Begin Source File + +SOURCE=..\sys\winnt\win32api.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/win/win32/resource.h b/win/win32/resource.h new file mode 100644 index 0000000..7fa83bf --- /dev/null +++ b/win/win32/resource.h @@ -0,0 +1,149 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by winhack.rc +// +#define IDC_MYICON 2 +#define IDD_WINHACK_DIALOG 102 +#define IDD_ABOUTBOX 103 +#define IDS_APP_TITLE 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDS_HELLO 106 +#define IDI_NETHACKW 107 +#define IDC_NETHACKW 109 +#define IDR_MAINFRAME 128 +#define IDB_TILES 129 +#define IDD_TEXT 130 +#define IDD_NHTEXT 130 +#define IDD_MENU 132 +#define IDB_MENU_SEL 133 +#define IDB_MENU_UNSEL 134 +#define IDD_COMMANDS 136 +#define IDD_GETLIN 138 +#define IDD_EXTCMD 139 +#define IDD_PLAYER_SELECTOR 141 +#define IDB_PETMARK 143 +#define IDB_MENU_SEL_COUNT 144 +#define IDD_NHRIP 145 +#define IDB_SPLASH 146 +#define IDB_RIP 147 +#define IDD_SPLASH 148 +#define IDC_TEXT_VIEW 1000 +#define IDC_TEXT_CONTROL 1000 +#define IDC_CMD_MOVE_NW 1001 +#define IDC_CMD_MOVE_N 1002 +#define IDC_MENU_LIST 1003 +#define IDC_CMD_MOVE_NE 1003 +#define IDC_MENU_TEXT 1004 +#define IDC_CMD_MOVE_W 1004 +#define IDC_CMD_MOVE_SELF 1005 +#define IDC_CMD_MOVE_E 1006 +#define IDC_CMD_MOVE_SW 1007 +#define IDC_CMD_MOVE_S 1008 +#define IDC_CMD_MOVE_SE 1009 +#define IDC_CMD_MOVE_UP 1010 +#define IDC_CMD_MOVE_DOWN 1011 +#define IDC_CMD_5 1012 +#define IDC_CMD_A 1013 +#define IDC_CMD_B 1014 +#define IDC_CMD_C 1015 +#define IDC_CMD_D 1016 +#define IDC_CMD_E 1017 +#define IDC_CMD_F 1018 +#define IDC_CMD_G 1019 +#define IDC_CMD_H 1020 +#define IDC_CMD_I 1021 +#define IDC_CMD_J 1022 +#define IDC_CMD_K 1023 +#define IDC_CMD_L 1024 +#define IDC_CMD_M 1025 +#define IDC_CMD_N 1026 +#define IDC_CMD_O 1027 +#define IDC_CMD_P 1028 +#define IDC_CMD_Q 1029 +#define IDC_CMD_R 1030 +#define IDC_CMD_S 1031 +#define IDC_CMD_T 1032 +#define IDC_CMD_U 1033 +#define IDC_CMD_V 1034 +#define IDC_CMD_W 1035 +#define IDC_CMD_X 1036 +#define IDC_CMD_Y 1037 +#define IDC_CMD_Z 1038 +#define IDC_CMD_AA 1039 +#define IDC_CMD_BB 1040 +#define IDC_CMD_CC 1041 +#define IDC_CMD_DD 1042 +#define IDC_CMD_EE 1043 +#define IDC_CMD_FF 1044 +#define IDC_CMD_GG 1045 +#define IDC_CMD_HH 1046 +#define IDC_CMD_II 1047 +#define IDC_CMD_JJ 1048 +#define IDC_CMD_KK 1049 +#define IDC_CMD_LL 1050 +#define IDC_CMD_MM 1051 +#define IDC_CMD_NN 1052 +#define IDC_CMD_OO 1053 +#define IDC_CMD_PP 1054 +#define IDC_CMD_QQ 1055 +#define IDC_CMD_RR 1056 +#define IDC_CMD_SS 1057 +#define IDC_CMD_TT 1058 +#define IDC_CMD_UU 1059 +#define IDC_CMD_VV 1060 +#define IDC_CMD_WW 1061 +#define IDC_CMD_XX 1062 +#define IDC_CMD_YY 1063 +#define IDC_CMD_ZZ 1064 +#define IDC_CMD_FIRST 1100 +#define IDC_CMD_LAST 1300 +#define IDC_GETLIN_EDIT 1309 +#define IDC_EXTCMD_LIST 1310 +#define IDC_PLSEL_NAME 1314 +#define IDC_PLSEL_ROLE_RANDOM 1315 +#define IDC_PLSEL_RACE_RANDOM 1318 +#define IDC_PLSEL_GENDER_RANDOM 1319 +#define IDC_PLSEL_ALIGN_RANDOM 1320 +#define IDC_PLSEL_ROLE_LIST 1323 +#define IDC_PLSEL_RACE_LIST 1324 +#define IDC_PLSEL_ALIGN_LIST 1325 +#define IDC_PLSEL_GENDER_LIST 1326 +#define IDC_ABOUT_VERSION 1327 +#define IDC_ABOUT_COPYRIGHT 1328 +#define IDM_SAVE 32771 +#define IDM_HELP_LONG 32772 +#define IDM_HELP_COMMANDS 32773 +#define IDM_HELP_HISTORY 32774 +#define IDM_HELP_INFO_CHAR 32775 +#define IDM_HELP_INFO_KEY 32776 +#define IDM_HELP_OPTIONS 32777 +#define IDM_HELP_OPTIONS_LONG 32778 +#define IDM_HELP_EXTCMD 32779 +#define IDM_HELP_LICENSE 32780 +#define IDM_HELP_PORTHELP 32781 +#define IDM_MAP_TILES 32782 +#define IDM_MAP_ASCII4X6 32783 +#define IDM_MAP_ASCII6X8 32784 +#define IDM_MAP_ASCII8X8 32785 +#define IDM_MAP_ASCII16X8 32786 +#define IDM_MAP_ASCII7X12 32787 +#define IDM_MAP_ASCII8X12 32788 +#define IDM_MAP_ASCII16X12 32789 +#define IDM_MAP_ASCII12X16 32790 +#define IDM_MAP_ASCII10X18 32791 +#define IDM_MAP_FIT_TO_SCREEN 32792 +#define IDM_NHMODE 32794 +#define IDM_CLEARSETTINGS 32795 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 145 +#define _APS_NEXT_COMMAND_VALUE 32796 +#define _APS_NEXT_CONTROL_VALUE 1331 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/win/win32/rip.uu b/win/win32/rip.uu new file mode 100644 index 0000000..c1da8e6 --- /dev/null +++ b/win/win32/rip.uu @@ -0,0 +1,1805 @@ +begin 600 rip.bmp +M0DVV/`$``````#8$```H````D`$``,@````!``@``````(`X`0`2"P``$@L` +M```!`````0``+C8V`$9!00`Q+R\`(S4U``)'`P`*+A4`'C$P`"LI*0`1-2,` +M&B(B`**FI@`X.CH`:W1U`!0:&0!X?G\`#1(2`!,G'P`*,Q8``3X#`!88&``! +M.@,``C@$`!06%@!-1D8`)20D``H,#``,%14`145%`#=+2P`/,!\`#RX?`#\_ +M/P`]/3T`%1L;``TN&@"#AX@`+2TM`"DI*0![?X``$R\G`#0Q,0!634T`#A@8 +M`+&TM`"2F)@`(28E`(J0D``8'!P`?8*#`&1L;0`?("``EYB;+3AGEYB; +MS\O1P+7"*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``*S`^S\O1P+*U*S`^@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``$QDXEYB;P+*UF=#5EYB;F:?, +MF=#5S\O1J:VO0UICF8"0F=#5S\O1-3]`@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``*S`^P+7"F=#5*S`^+3AG*S`^@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@8 +MP+*UU=3>S\O1EYB;N7YBF=#5F=#5P+7"96=IEYB;F:?,F:?,+3AG@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``559;P+*U +MF=#5GZ=P+7"S\O1>GZ=EYB;F:?,S\O1F=#5P+*UF:?, +MP+*UF=#596=I$QDX'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``*S`^F=#5F=#5S\O1S\O1S\O1F=#5%!0V@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@896=IEYB;P+*UEYB;EYB; +M96^<05BD05BDF8"0F=#5F=#5S\O1S\O1>GZ=$QDX@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``*S`^S\O1U=3>F=#5X^KKU=3>P+*U559; +M'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#`P] +MF8"0EYB;F8"096^<96^<(C&<%!68+3AG(C&S\O1S\O1F=#5*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``'A@8>GZ=EYB;559;0UIC&25@(C&<+3AG)T2E+3AGEYB; +MEYB;?Y?/F:?,EYB;5B@>@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``*S`^F=#5S\O1F=#5EYB;F:?,U=3>SMK=5B@>@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``%!0VEYB;J:VO0UIC+3AG04F- +M(C&<05BD0UIC+3AG'".<(C&<(C&<96=I96^GZ=F:?,0UIC'".<(C&<96^<05BD(C&<+3AG(C&< +M96=I05BD0UIC05BD05BDF:?,EYB;%!0V@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``+3AGEYB;04F-+3AG04F-05BD2%S(05BD05BD96^'A@8@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``-3]`EYB;96^<+3AG+3AG'".<"0F5'2C32%S(96^<'".<(C&< +M*47&*47&"0GS"0GS#Q/-96^<05BD@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``%!0V05BD(C&<'2C3(C&<05BD*47&'2C3#Q/-'".<(C&EYB;05BD&25@(C&<'".<%!68 +M(C&<*47&*47&"0G+'2C3(C&<2%S(*47&'2C3"0G+05BD04F-#@\0@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``*S`^96^<(C&<'2C3*47&(C&<(C&<"0GS +M"0G+(C&<(C&GZ=L)BH96=I*S`^@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``%!0V>GZ=L)BHF:?,5B@>#@\0*S`^'A@8@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#`P] +M05BD(C&<'2C3*47&(C&<+3AG&25@+3AG"0F5"0ED"0F5%!68"0G+"0G+'".< +M"0ED"0F5&25@+3AG+3AG+3AG'A@8@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^F:?,66^\ +M*47&'".<+3AG"0ED"0G+#Q/-"0G+"0G+'".<+3AG0UICEYB;EYB;5B@>#`P] +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``$QDX+3AG96=IF=#5*S`^*S`^N7YB*S`^ +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``'A@896^<66^\(C&<'".<'".<"0ED"0ED"0ED%QAE'".< +M'".<"0G+'2C3#Q/-"0F5"0G+%!68"0F5"0F5(C&<96=I$QDX@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``#`P]0UICP+7"F:?,2%S('".<+3AG'2C3"0F5"0G+"0G+%!68'".< +M+3AG0UIC96=IEYB;*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``5B@>>GZ=*S`^5B@> +M>GZ=*S`^*S`^96^<'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``$QDX-3]`05BD+3AG"0ED +M+3AG"0ED"0ED"0G+"0G+#Q/-"0G+"0GS"0GS#Q/-'2C3"0F5"0G+"0F5%!68 +M+3AG%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``'A@8EYB;L)BH05BD+3AG%QAE"0F5 +M"0G+'2C3"0GS"0G+"0F5&25@*S`^0UICF8"0559;'A@8*S`^*S`^*S`^#`P] +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``-3]`EYB;559;*S`^N7YB559;0UIC559;%!0V@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``*S`^>GZ=+3AG"0ED"0ED%!68&25@#Q/-'2C3"0GS"0GS"0GS"0GS"0GS +M"0G+"0G+'".<"0F5"0F5%QAE@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#@\0$QDX +M*S`^$QDX*S`^(C&<(C&<"0G+"0G+"0GS"0GS#Q/-"0G+%!68%QAE+3AG05BD +M0UICF8"0F=#5EYB;*S`^%!0V'A@8%!0V@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``*S`^559;EYB;+3AG%!0VGZ=EYB;+3AG%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``559;F=#5+3AG%!0V +M"0ED"0ED%QAE"0F5"0G+"0F5"0GS"0GS'2C3"0GS"0G+#Q/-'".<"0ED'".< +M+3AG$QDX@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``%!0V96=I96^<(C&< +M"0F5"0G+#Q/-"0GS"0GS"0GS"0GS%!68"0F5"0F5+3AG"0ED$QDX%QAE05BD +MF:?,EYB;*S`^*S`^*S`^#@\0@(``@(``@(``@(``@(``@(``@(``@(``*S`^ +MP+7"S\O1N7YB$QDX#`P]*S`^559;96=I0UIC'A@8@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``*S`^F8"096=I&25@&25@%QAE'".<"0F5#Q/-"0G+"0GS"0GS"0G+"0G+ +M'2C3"0G+"0G+"0F5'".<04F-%!0V@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``#`P]*S`^04F-05BD(C&<%!68"0G+"0GS'2C3"0GS"0G+"0G+'".< +M"0F5%!68&25@&25@%QAE+3AG%QAE+3AGF8"0>GZ=*S`^@(``@(``@(``@(`` +M@(``@(``@(``@(``#`P]GZ=+3AG*S`^%!0V*S`^$QDX'A@8*S`^*S`^ +M$QDX@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``'A@8*S`^GZ=EYB;(C&<(C&<*47&'2C3"0GS#Q/-"0GS"0G+'2C3"0F5'".<%!68'".< +M%QAE"0ED"0ED"0ED%QAE+3AG+3AG*S`^@(``@(``@(``@(``@(``@(``@(`` +M-3]`+3AG&25@(C&<0UIC+3AG%!0V$QDX+3AGEYB;F=#5559;#@\0@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``'A@8EYB;F=#596=I&25@"0ED"0ED(C&<"0F5(C&<"0G+"0F5"0G+ +M"0G+"0G+"0G+"0F5+3AGF8"0*S`^@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``'A@8'A@8*S`^EYB;?Y?/04F-(C&<'2C3"0G+"0G+ +M#Q/-"0F5#Q/-(C&<"0G+"0F5&25@%!68"0ED'".<%!6896^<96^<%!0V@(`` +M@(``@(``@(``@(``@(``559;96=I+3AG0UIC96=I0UIC+3AG+3AG+3AG0UIC +M96^GZ=*S`^@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#`P] +M*S`^+3AG%QAE+3AG"0F5%!68&25@(C&<%!68'2C3"0G+"0G+%!68'".<(C&< +M*S`^'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``$QDX96^<>GZ=*47&'".<#Q/-"0G+*47&"0G+"0G+ +M"0GS'2C3"0G+"0G+"0F5%!68(C&<,4)F'A@8@(``@(``@(``@(``@(``@(`` +M-3]`559;(C&<0UIC559;&25@+3AG0UIC0UIC0UIC+3AG05BD559;*S`^@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``%!0V0UIC(C&<&25@%QAE&25@'".<0UIC(C&<"0F5 +M'2C3"0G+(C&<(C&<+3AG%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#`P]559;0UIC(C&<'".< +M"0G+'".<"0G+#Q/-"0G+"0GS#Q/-"0G+(C&<'".<"0ED'".<*S`^#`P]@(`` +M@(``@(``@(``@(``'A@8+3AG05BD+3AG+3AG(C&<+3AG(C&<0UIC+3AG%QAE +M'".<(C&GZ=EYB;+3AG"0ED +M%!68'".<(C&<*47&#Q/-"0G+"0G+(C&<2%S(96=I#@\0@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M'A@8EYB;F:?,96=I%!68"0ED"0F5"0G+"0G+'2C3"0GS"0GS"0GS"0G+%!68 +M'".<(C&<+3AG%!0V@(``@(``@(``@(``@(``#`P]+3AG+3AG+3AG05BD+3AG +M+3AG+3AG+3AG&25@+3AG%QAE05BDF=#5F=#5$QDX@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M*S`^P+7"P+*U+3AG&25@+3AG(C&<96^<2%S(#Q/-"0G+(C&<"0F566^\66^\ +M%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@8*S`^559;*S`^#@\0 +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``#`P]559;F:?,F:?,+3AG&25@"0ED%QAE'".<"0G+"0GS +M"0G+"0GS*47&"0F5%!68"0F596^<05BD#`P]@(``@(``@(``@(``@(``#`P] +M+3AG(C&<+3AG+3AG+3AG%!68+3AG+3AG'".<"0ED+3AG(C&GZ=$QDX@(``@(``@(``@(``@(``#`P]04F-05BD+3AG+3AG"0ED +M"0ED*S`^&25@"0ED*S`^"0ED"0ED&25@+3AG0UICEYB;EYB;$QDX@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M%!0VS\O1P+7"+3AG+3AG*S`^+3AG05BD"0G+*47&"0G+'".<(C&GZ=(C&<"0ED"0ED"0F5"0F5%!68"0F5"0F5#Q/-'".< +M%!68"0F5'".<(C&<'".<+3AGF:?,EYB;$QDX@(``@(``@(``@(``@(``#@\0 +M96=I96^<%QAE"0ED%!0V"0ED"0ED"0ED%QAE"0ED"0ED#`P]#`P]"0ED&25@ +MF:?,F:?,559;%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``'A@8P+7"F:?,+3AG&25@+3AG0UIC(C&<'2C3"0G+ +M"0F5"0F5%!68F=#5EYB;*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#`P] +M*S`^559;+3AG*S`^%!0V%!0V#`P]'A@8$QDX*S`^'A@8$QDX5B@>%!0V#`P] +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``5B@>EYB;2%S( +M*47&*47&"0GS#Q/-"0G+(C&<(C&<96^GZ=%!0V@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``%!0V*S`^+3AGF8"0J:VOEYB;96=I>GZ=96=I559;0UIC+3AG96^< +M96^<GZ= +MF:?,5B@>@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M'A@8EYB;P+7">GZ=0UIC(C&<96^<05BD05BD0UIC+3AG&25@%QAE"0ED'".< +M"0F5"0F5%!68"0F5"0F5"0F5#Q/-"0F5"0G+%!68'2C3"0F5'".<+3AG(C&< +M+3AG>GZ=?Y?/EYB;>GZ=66^\F8"0>GZ=P+*UP+7"XO+TF=#596=I&25@"0ED +M"0ED%QAE"0ED%QAE"0ED$QDX%!0V&25@%!0V#`P]"0ED*S`^05BDF:?,EYB; +M$QDX@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``559;(C&<%!68"0ED"0F5#Q/-(C&<(C&<'2C3'2C3"0G+'".<66^\96^< +M$QDX@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``$QDXEYB;P+*U>GZ=96^<05BD96=I04F-559; +M05BD96=I0UIC96=I0UIC05BD96=I96^<GZ=?V]^'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``'A@8*S`^*S`^0UICEYB;F=#596^< +M+3AG"0ED+3AG&25@+3AG(C&<0UIC(C&<+3AG0UIC-3]`0UIC96=I0UIC96^< +MS\O1J:VO%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@8@(``*S`^>GZ=>GZ= +M04F-05BD559;(C&<(C&<&25@&25@%QAE"0F5(C&<96^<+3AG%!0V@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#`P]'A@8'A@8 +M@(``@(``@(``#`P]$QDX*S`^$QDX@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``#`P]'A@8$QDX-3]`EYB;96^<(C&<96=I0UIC +M0UIC96=I0UIC+3AG+3AG+3AG0UIC(C&<%QAE"0F5%QAE(C&<"0F5#Q/-"0F5 +M'".<#Q/-"0F5%!68"0G+"0F5%!6805BD+3AG%QAE&25@&25@%!68(C&<(C&< +M(C&<(C&<+3AG(C&<(C&<+3AG+3AG&25@+3AG"0ED%QAE&25@&25@%QAE"0ED +M%!0V%!0V&25@*S`^$QDX#`P]&25@*S`^05BD96^<*S`^#`P]@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``+3AG>GZ=+3AG%!0V"0ED&25@ +M"0F5'".<*47&05BD+3AG"0ED%QAE&25@05BD04F-#`P]@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#`P]%!0V*S`^-3]`EYB; +MEYB;96^<0UIC04F-+3AG"0F5'".<+3AG'".<"0F5+3AG+3AG&25@+3AG+3AG +M(C&<0UIC+3AG+3AG96=I>GZ=96^<*S`^#`P]@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^ +M>GZ=*S`^%!0V?V]^96^<96=I+3AG+3AG0UIC96^<*S`^'A@8$QDX'".<'".< +M(C&GZ=05BD+3AG$QDX#`P]*S`^+3AGEYB;EYB;%!0V@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^EYB;F8"096=I +M(C&<(C&<+3AG+3AG96=I96=I0UIC+3AG+3AG0UIC+3AG+3AG+3AG+3AG'".< +M'".<"0F5"0F5"0F5"0F5"0G+"0F5'2C3"0G+(C&<"0G+'".<(C&<+3AG&25@ +M%QAE'".<'".<+3AG%!68&25@'".<%!68+3AG"0F5%QAE'".<+3AG'".<+3AG +M+3AG+3AG+3AG+3AG+3AG+3AG0UIC+3AG+3AG-3]`+3AG&25@%QAE%QAE0UIC +MN7YB*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``%!0V +M96=I(C&<"0ED"0ED"0F5%QAE"0F5+3AG+3AG%QAE&25@"0ED&25@+3AG+3AG +M#`P]@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M$QDXN7YBF:?,>GZ=96=I(C&<05BD(C&<&25@&25@+3AG%QAE+3AG'".<%!68 +M'".<"0ED"0ED"0ED&25@+3AGF8"0EYB;>GZ=GZ=F8"00UIC*S`^*S`^96=I +M%!0V'A@8#`P]%QAE%!68+3AG?Y?/EYB;0UIC'A@8@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``'A@8*S`^559;EYB;96^<+3AG*S`^%QAE&25@(C&< +MF=#5F:?,+3AG'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#@\0 +M*S`^96^GZ=F8"096=I +M&25@96=I>GZ=*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``'A@8+3AGEYB;P+*UF=#5559;*S`^96=IN7YB +M>GZ=*S`^*S`^*S`^*S`^$QDX````'A@8"0ED'".<%!68+3AG04F-F8"00UIC +M$QDX#`P]@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``#`P]%!0V'A@8+3AG96^<>GZ=0UIC%QAE +M"0ED&25@*S`^+3AG*S`^+3AG96=IEYB;0UIC%!0V#`P]@(``@(``@(``@(`` +M@(``@(``@(``#`P]*S`^EYB;F:?,96^<(C&<(C&<+3AG05BD559;0UIC96=I +M0UIC0UIC+3AG&25@(C&<+3AG(C&<'".<+3AG%!68'".<#Q/-"0F5"0G+"0G+ +M'2C3"0G+"0G+"0F5"0G+"0F5%!68'".<+3AG"0ED%QAE&25@%!68'".<'".< +M+3AG(C&<+3AG(C&<+3AG+3AG+3AG0UIC+3AG&25@+3AG+3AG0UIC559;05BD +M0UIC96=I0UIC96=I0UIC96=I0UIC96=I0UIC96=IGZ=*S`^$QDX +M%!0V$QDX#@\0@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``$QDXL)BHF:?,+3AG%!0V&25@%QAE"0F5 +M"0ED+3AG&25@+3AG"0F5"0F5%QAE&25@"0ED0UICEYB;0UIC@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``'A@8$QDX%!0V+3AGF8"005BD(C&<(C&<&25@ +M'".<%!68"0ED'".<%!68"0G+"0F5%!68%QAE(C&<'".<+3AG+3AG%!0V0UIC +M+3AG%!0V$QDX'A@8'A@8#`P]#`P]%!0V@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``-3]`EYB;>GZ=EYB; +MS\O1J:VON7YB0UIC96=I+3AG*S`^*S`^-3]`#`P]````'A@8#`P]#@\0%!0V +M&25@%!68,4)F96^EYB;66^\96^<(C&<%QAE'".< +M0UIC05BD0UIC0UIC+3AG+3AG%QAE+3AG%QAE+3AG'".<%!68%!68"0F5&25@ +M%!68'".<"0G+'2C3%!68"0G+%!68'2C3"0G+(C&<"0F5'".<"0F5+3AG"0F5 +M%QAE'".<%QAE+3AG%!68&25@%!68+3AG+3AG+3AG(C&<+3AG%!68+3AG(C&< +M+3AG(C&<0UIC96=I0UIC559;0UIC0UIC559;0UIC0UIC96=I96=I0UIC96=I +M0UIC96=I@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^EYB;96=I0UIC +M(C&<'".<&25@+3AG%QAE"0F5"0F5&25@"0F5"0F5'".<%!68&25@"0F5*47& +MF:?,F=#5N7YB*S`^GZ=(C&<+3AG%!68+3AG"0F5'".<"0F5(C&<"0G+%!68"0F5 +M"0F5%QAE$QDX(C&<66^\L)BHF:?,>GZ=96=IEYB;EYB;%!0V@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``*S`^P+*U96^<559;0UIC96=I96=I$QDX```` +M#`P]*S`^*S`^*S`^$QDX#@\0````'A@8#@\0````$QDX+3AG+3AG+3AG>GZ= +M96^<*S`^'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``%!0V0UICF:?,GZ=559;$QDX@(``@(`` +M@(``@(``$QDX*S`^(C&<(C&<&25@+3AG96=I05BD559;0UIC0UIC0UIC&25@ +M+3AG"0F5+3AG%QAE&25@'".<'".<"0F5%!68'".<(C&<'2C3%!68"0G+"0G+ +M'2C3"0G+"0F5#Q/-"0F5"0G+"0G+"0F5+3AG%QAE"0ED&25@+3AG'".<'".< +M+3AG%!68'".<&25@+3AG&25@+3AG(C&<&25@(C&<%!68+3AG&25@0UIC559; +M0UIC559;96=I0UIC0UIC0UIC96=I0UIC96^<0UIC0UIC0UIC559;0UIC96=I +M+3AG(C&<96^<>GZ=F8"0*S`^%!0V#@\0$QDX@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``#`P]$QDX+3AG0UIC"0ED%QAE&25@#`P]"0ED +M"0ED"0ED"0G+"0G+"0GS"0G+"0GS'".<"0F504F-EYB;*S`^@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M'A@8$QDX%!0V*S`^>GZ=96^<0UIC(C&<(C&<%!68&25@"0F5'".<%!68"0F5 +M(C&<"0F5"0G+(C&<&25@%!0V#`P]%QAE>GZ=?Y?/*S`^%!0V-3]`F8"0F=#5 +M>GZ='A@8@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``-3]`F:?,96^<GZ=N7YB%!0V@(``@(``#@\096^<>GZ=+3AG+3AG'".<0UIC0UIC0UIC +M96=I0UIC96=I(C&<+3AG%!68&25@+3AG+3AG'".<%!68"0G+"0F5"0G+'".< +M#Q/-"0G+"0F5'2C3"0GS#Q/-"0G+'2C3"0G+'".<%!68'".<%!68&25@"0ED +M&25@"0F5%!68%!68+3AG%QAE'".<+3AG%!68%!68'".<%!68+3AG%!68'".< +M+3AG'".<&25@(C&<+3AG+3AG0UIC0UIC559;96=I96=I0UIC0UIC+3AG+3AG +M0UIC+3AG0UIC+3AG05BD96=I+3AG(C&<(C&<96^<+3AG0UICN7YB*S`^@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^>GZ=96=I"0ED +M&25@$QDX"0ED*S`^"0ED&25@%!68'2C3"0GS#Q/-"0GS#Q/-"0G+(C&<(C&< +M*S`^%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``*S`^EYB;GZ=04F-&25@"0ED#`P]&25@"0ED*S`^ +M"0ED%QAE"0F5(C&<"0G+*47&'2C3(C&GZ=96=IF8"0 +M>GZ=96=I0UIC*S`^0UIC559;+3AG*S`^%!0V#@\0*S`^*S`^%!0V'A@8#`P] +M'A@8#@\0#`P]#`P]+3AG+3AG(C&GZ=%!0V@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``'A@8F8"0>GZ=+3AG0UIC559;+3AG*S`^0UIC*S`^*S`^+3AG +M%!0V$QDX#`P]$QDX*S`^%QAE$QDX*S`^*S`^"0ED"0ED"0ED%!0V"0ED%QAE +M"0ED"0ED&25@+3AG05BD96^<96^<+3AG*S`^+3AG+3AG0UIC0UIC0UIC96=I +M96=I0UIC+3AG'".<%!68'".<%!68"0F5%!68#Q/-"0F5#Q/-%!68#Q/-%!68 +M"0GS#Q/-'".<"0GS"0G+'2C3%!68'2C3%!68'2C3"0F5&25@%!68'".<'".< +M+3AG'".<%QAE'".<+3AG%!68%QAE'".<+3AG+3AG%!68'".<'".<%!68'".< +M+3AG%!68(C&<'".<+3AG+3AG0UIC96=I05BD559;+3AG+3AG0UIC+3AG+3AG +M+3AG+3AG+3AG*S`^0UIC0UIC(C&<0UIC96=I96=I&25@%!68(C&<96=I96=I +M96^GZ=96=I(C&<04F-(C&<+3AG%!68'".<%QAE'".<%!68"0F5"0ED'2C3#Q/- +M"0G+"0GS"0G+'2C3"0F5'".<+3AG?HF\F=#5EYB;96=I+3AG+3AG+3AG*S`^ +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@80UIC +ML)BHF:?,96^<96=I96=I96=I96=I559;-3]`96=I96=I-3]`$QDX*S`^$QDX +M+3AG*S`^#@\0#@\0````````'A@8````*S`^%QAE'".<+3AGF:?,EYB;%!0V +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``*S`^#`P]$QDX$QDX#`P]$QDX*S`^?Y?/EYB;+3AG$QDX*S`^*S`^ +M+3AG+3AG*S`^+3AG*S`^$QDX%!0V%QAE*S`^+3AG0UIC*S`^&25@%QAE*S`^ +M#`P]%!0V&25@%!0V$QDX"0ED&25@%QAE'".<04F-96^<0UIC%QAE&25@-3]` +M0UIC559;+3AG96=I0UIC559;+3AG+3AG%!68&25@%!68%!68&25@'".<"0F5 +M'2C3#Q/-'".<'".<'2C3"0G+"0G+(C&<"0G+%!68"0G+"0G+"0F5"0G+'".< +M%!68'".<"0F5%!68%!68%QAE'".<+3AG%!68'".<'".<"0F5+3AG%!68'".< +M(C&<%!68+3AG'".<&25@'".<'".<(C&<(C&<+3AG(C&<0UIC(C&<0UIC0UIC +M96=I(C&<559;+3AG+3AG+3AG+3AG+3AG+3AG*S`^+3AG+3AG559;0UIC+3AG +M+3AG+3AG96=I0UIC559;0UICF:?,J:VO559;$QDX%!0V5B@>*S`^559;F:?, +MEYB;05BD%QAE"0ED%QAE&25@%QAE"0ED%QAE"0ED"0ED"0ED%!68&25@05BD +M96^<GZ= +M>GZ=*S`^+3AG*S`^'A@8$QDX$QDX%!0V````%!0V````#`P]````$QDX&25@ +M+3AG&25@04F-96=I*S`^#`P]@(``@(``@(``@(``@(``@(``@(``*S`^$QDX +M*S`^*S`^*S`^'A@8*S`^$QDX+3AGEYB;04F-+3AG(C&<+3AG(C&<0UIC+3AG +M(C&<*S`^&25@+3AG*S`^0UIC+3AG"0ED#`P]%QAE*S`^+3AG96=I96^GZ=EYB;559;#`P]'A@8#`P]%!0V#@\0 +M%!0V%!0V*S`^*S`^-3]`*S`^#`P]*S`^$QDX````%!0V#@\0'A@8$QDX'A@8 +M#@\0%!0V````'A@8%QAE+3AG%QAE&25@+3AGEYB;*S`^@(``@(``@(``@(`` +M@(``@(``*S`^P+7"P+*UP+7"P+7"S\O1S\O1P+7"P+*UF:?,>GZ=0UIC(C&< +M'".<+3AG'".<(C&<'".<&25@"0ED+3AG+3AG+3AG*S`^*S`^&25@$QDX+3AG +MEYB;+3AG$QDX*S`^-3]`559;EYB;+3AG$QDX%QAE&25@&25@%!0V"0ED%QAE +M&25@"0ED&25@"0F5%QAE"0ED*S`^%QAE&25@*S`^%QAE&25@+3AG"0ED%QAE +M&25@%!68%!68%!68"0G+'".<#Q/-"0F5(C&<"0G+"0G+#Q/-'".<#Q/-"0GS +M#Q/-'2C3#Q/-"0G+%!68"0G+"0G+"0G+'".<"0F5'".<'".<%!68%!68+3AG +M%!68&25@%!68'".<%!68+3AG%!68%!68"0F5"0F5%!68(C&<"0F5&25@+3AG +M(C&<&25@+3AG'".<+3AG'".<'".<+3AG+3AG+3AG+3AG0UIC96=I0UIC+3AG +M0UIC+3AG+3AG&25@&25@+3AG+3AG*S`^&25@*S`^+3AG+3AG0UIC0UIC+3AG +M559;0UIC0UICGZ=96^<96^<&25@&25@+3AG +M'".<%QAE'".<+3AG%!68"0F5(C&<"0F5'".<#Q/-'".<'".<#Q/-'2C3"0GS +M"0G+'2C3"0GS"0GS"0G+'2C3%QAE$QDX*S`^%!0V%!0V+3AG$QDX@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#@\0 +M559;EYB;66^\05BD%!68&25@+3AG+3AG&25@%QAE%!0V"0ED$QDX*S`^$QDX +M#`P]#@\0'A@8#@\0#`P]'A@8$QDX````'A@8````'A@8#`P]'A@8#@\0"0ED +M%QAE&25@&25@+3AG96^<+3AG'A@8@(``@(``@(``@(``@(``%!0V'A@8*S`^ +M0UICP+*UX.#GU=3>S\O1F:?,?Y?/F=#5F=#5F:?,*47&05BD*47&'".<%!68 +M&25@"0ED%QAE&25@+3AG+3AG0UIC96=IF:?,EYB;+3AG@(``@(``@(``@(`` +M*S`^EYB;96=I"0ED"0ED+3AG+3AG&25@%QAE%QAE&25@&25@%QAE"0ED%QAE +M"0ED%QAE+3AG%!68&25@"0F5&25@+3AG+3AG&25@%QAE+3AG%QAE&25@&25@ +M'".<"0G+'".<%!68"0G+"0G+#Q/-'2C3"0G+#Q/-"0G+#Q/-"0GS#Q/-'2C3 +M"0G+"0G+'2C3"0F5(C&<"0F5'".<%QAE(C&<'".<%!68'".<%!68%!68+3AG +M%!68"0F5%QAE%!68"0F5+3AG"0F5'".<(C&<'2C3(C&<(C&<+3AG(C&<'".< +M%!68+3AG(C&<+3AG(C&<(C&<%!68+3AG+3AG(C&<0UIC(C&<+3AG'".<0UIC +M05BD+3AG+3AG+3AG+3AG+3AG*S`^+3AG&25@%QAE+3AG*S`^&25@+3AG%QAE +M+3AG&25@"0F5+3AG%!68&25@(C&<&25@+3AG&25@&25@"0F5%QAE"0F5&25@ +M+3AG>GZ=0UIC$QDX@(``@(``@(``@(``@(``@(``'A@8*S`^%!0V$QDX'A@8 +M$QDX#`P]#`P]$QDX*S`^EYB;P+7">GZ=96^<96=I05BD559;05BD+3AG%!68 +M+3AG(C&<&25@+3AG%!68%!68(C&<"0G+'".<(C&<'2C3%!68"0G+"0G+"0G+ +M'2C3'2C3'2C3"0GS"0GS"0GS"0GS"0GS'2C3(C&<*47&0UIC+3AG$QDX&25@ +M*S`^96^<*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``$QDX96^<>GZ=05BD(C&<+3AG+3AG%!68"0F5%!68'".<+3AG +M'".<%QAE+3AG"0ED%QAE'A@8$QDX#`P]'A@8#`P]#@\0````%!0V#`P]#@\0 +M$QDX#@\0#@\0%!0V#`P]*S`^+3AG%QAE&25@0UICF:?,EYB;%!0V@(``@(`` +M@(``@(``@(``@(``@(``%!0V96=IS\O1XO+TSMK=66^\*47&2%S(F:?,F=#5 +M*47&'2C305BD'".<%!68&25@"0F5%QAE'".<96^GZ=F8"096=I96=I559;+3AG05BD96^<04F-(C&<(C&< +M'".<(C&<+3AG&25@'".<&25@+3AG%!68'".<'".<'".<+3AG"0F5%!68%!68 +M'".<2%S(*47&"0G+*47&"0GS*47&'2C3"0GS"0GS"0GS"0GS"0G+%!68'".< +M96^@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``'A@8*S`^5B@>*S`^>GZ=?HF\0UIC(C&<'".<'".< +M+3AG'".<+3AG'".<%QAE'".<+3AG'".<+3AG&25@%!0V"0ED#`P]%!0V```` +M%!0V#@\0#@\0````'A@8#`P]'A@8'A@8````$QDX"0ED+3AG&25@+3AG%QAE +MP+*UF:?,*S`^@(``@(``@(``@(``@(``@(``@(``@(``'A@8F8"0S\O1F=#5 +MF:?,2%S(2%S(?Y?/?Y?/'2C3'2C3*47&05BD(C&<(C&<%QAE&25@%QAE96=I +MEYB;EYB;%!0V@(``@(``@(``@(``@(``@(``@(``@(``'A@8F8"0>GZ=+3AG +M&25@+3AG*S`^%!0V%!0V$QDX'A@8#`P]'A@8%!0V$QDX%QAE*S`^%QAE&25@ +M'".<+3AG&25@+3AG'".<%QAE'".<%QAE'".<&25@&25@%QAE"0F5"0F5"0G+ +M"0G+"0G+'2C3"0G+"0G+#Q/-"0GS#Q/-"0G+"0G+'".<"0G+"0G+'2C3%!68 +M"0F5(C&<%!68"0F5"0G+(C&<"0G+%!68%!68&25@%!68'".<"0F5%!68%QAE +M'".<+3AG'".<'".<%!68'".<(C&<05BD(C&<05BD+3AG'".<+3AG+3AG%!68 +M+3AG"0ED'".<%!68+3AG04F-05BD0UIC0UIC96=I96=I0UIC+3AG+3AG+3AG +M+3AG&25@%QAE"0ED%QAE"0ED&25@%!0V&25@+3AG%!68"0F5#Q/-"0F5"0F5 +M&25@(C&<+3AG&25@%QAE'".<"0F5'".<%QAE>GZ=GZ=&25@+3AGEYB;*S`^@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^F:?,F:?,GZ=$QDX@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``$QDX'A@8559;F:?,P+7">GZ=66^\96^<05BD05BD(C&<66^\L)BH +MF8"0$QDX#`P]@(``#`P]%!0V'A@8@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``%!0VGZ=>GZ=GZ=96=I+3AG(C&<96=I(C&<96=I0UIC05BD +M(C&<%!68(C&<+3AG%!68+3AG"0F5'".<+3AG'".<+3AG'".<'".<+3AG%QAE +M'".<(C&<'2C3%!68'2C3(C&<(C&<'2C3#Q/-"0G+"0GS2%S(2%S(*47&"0GS +M"0GS*47&"0GS"0GS"0G+"0F5"0F5%QAE*S`^%QAE(C&<+3AG'A@8%!0V#@\0 +M#`P]'A@8#`P]@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^ +MEYB;?Y?/96^<66^\0UIC+3AG(C&<%QAE'".<+3AG&25@%!68%QAE+3AG&25@ +M&25@%QAE+3AG%!68+3AG%!68+3AG'".<%QAE'".<%QAE*S`^#`P]````#@\0 +M#`P]%!0V#@\0'A@8$QDX%QAE$QDX+3AG'".<%QAE(C&<+3AG#`P]@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@8*S`^-3]`+3AG$QDX559; +MF:?,F=#5F:?,+3AG+3AG*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``*S`^*S`^+3AG$QDX%!0V$QDX%QAE&25@ +M+3AG+3AG&25@&25@%!68+3AG+3AG%!68%QAE&25@'A@8#@\0%QAE"0ED+3AG +M'".<"0ED"0F5(C&<%!68&25@%!68%!68'".<%!68"0F5"0G+'2C3"0GS"0GS +M"0G+"0GS#Q/-"0G+"0F5'2C3"0G+'2C3"0G+'2C3%!68"0G+"0G+"0G+"0F5 +M"0F5%!68'".<"0F5%!68'".<%!68&25@%QAE"0F5(C&<"0F5'2C3%!68'".< +M(C&<*47&05BD(C&<(C&<(C&<+3AG(C&<(C&<%!68'".<+3AG'2C3%!68'".< +M(C&<"0F5(C&<+3AG(C&<+3AG(C&<'".<'".<+3AG%QAE'".<%QAE&25@%QAE +M&25@+3AG%QAE'".<"0F5#Q/-"0F5%!68"0G+%!68'".<+3AG&25@%!68%QAE +M+3AG'".<&25@+3AG96=I96^<96=I04F-+3AG(C&<559;05BD+3AG+3AG'".< +M%!68+3AG%!68+3AG+3AG+3AG'".<%QAE&25@%!68'".<%!68'".<%!68'".< +M%!68"0F5%!68'".<"0F5%!6805BD#Q/-'".<"0F5'2C3(C&<*47&"0GS"0GS +M'2C366^\2%S(2%S("0GS"0GS"0GS'2C3"0G++3AG%QAE&25@*S`^&25@*S`^ +M0UIC*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``*S`^96=I?Y?/66^\*47&(C&<*47&(C&<+3AG+3AG+3AG"0F5 +M+3AG"0F5'".<'".<+3AG%!68+3AG&25@'".<&25@"0F5%!68&25@%!68+3AG +M'".<"0ED'A@8#@\0#`P]'A@8````#`P]````%QAE$QDX%QAE&25@+3AG"0ED +M+3AG+3AG-3]`#`P]@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``*S`^EYB;P+7"EYB;%!0V@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#@\0*S`^*S`^$QDX*S`^ +M&25@#`P]&25@%QAE"0F5%!68'".<(C&<'".<%QAE'".<%QAE&25@&25@+3AG +M#`P]'A@8#`P]&25@"0F5+3AG%!68+3AG"0F5'".<&25@"0F5%!68'".<"0F5 +M+3AG'2C3"0G+#Q/-'2C3"0GS#Q/-"0G+"0G+"0G+#Q/-"0G+#Q/-"0F5"0F5 +M"0G+(C&<"0G+(C&<"0G+(C&<+3AG%!68(C&<%!68%!68'".<%QAE'".<%!68 +M'".<"0G+%!68+3AG'".<05BD(C&<(C&<0UIC+3AG+3AG'".<(C&<'2C3'".< +M+3AG%!68"0F5'".<"0G+%!68'".<'".<(C&<+3AG'".<&25@%!68%!68+3AG +M+3AG'".<%QAE&25@+3AG+3AG%QAE'".<%!68"0F5%!68'2C3"0G+'".<'".< +M+3AG(C&<+3AG'".<&25@"0F5+3AG%!68+3AG+3AG0UIC0UIC'".<%!68&25@ +M+3AG0UIC05BD(C&<+3AG&25@"0F5+3AG&25@%!68+3AG%!68+3AG%!68'".< +M(C&<"0F5+3AG+3AG+3AG'".<(C&<'".<%!68(C&<(C&<(C&<'".<"0F5'2C3 +M*47&05BD"0GS"0GS*47&'2C32%S(66^\*47&*47&"0GS"0G+"0G+%!68&25@ +M"0ED*S`^%QAE"0ED+3AG96^<*S`^@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``$QDXEYB;F=#5(C&<(C&<05BD*47&'2C3 +M'2C3+3AG(C&<%QAE'".<%!68"0F5(C&<"0G+"0G+'".<(C&<+3AG+3AG(C&< +M+3AG&25@+3AG%!68+3AG+3AG%QAE+3AG$QDX%!0V#@\0$QDX'A@8#@\0#`P] +M*S`^&25@*S`^"0ED+3AG&25@(C&<>GZ=*S`^@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@8$QDX*S`^'A@8$QDX@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@8'A@8$QDX%!0V'A@8 +M*S`^EYB;96=I0UIC%QAE"0ED+3AG%QAE'".<+3AG'".<%QAE+3AG+3AG%!68 +M"0ED'".<+3AG"0F5%QAE'".<%QAE#`P]*S`^+3AG%!68&25@"0F5+3AG"0ED +M%!68&25@'".<+3AG%!68+3AG(C&<%!68(C&<'".<#Q/-'2C3'2C3#Q/-'2C3 +M"0G+"0G+'2C3(C&<"0G+%!68'2C3"0G+'".<%!68'".<"0F5'".<"0G+'2C3 +M'2C3%!68'".<"0F5(C&<'".<%!68'".<"0F5(C&<(C&<05BD96=I+3AG05BD +M(C&<(C&<(C&<(C&<%!68"0F5'".<%!68(C&<"0F5'2C3%!68"0F5'".<%!68 +M+3AG%!68'".<+3AG'".<+3AG(C&<+3AG+3AG+3AG0UIC(C&<(C&<+3AG'".< +M"0F5"0F5'2C3(C&<(C&<%!68'".<%!68&25@+3AG+3AG"0ED&25@"0F5+3AG +M+3AG(C&<+3AG&25@+3AG%!68+3AG+3AG%QAE+3AG'".<%!68+3AG'".<%!68 +M'".<'".<+3AG'".<+3AG"0F5(C&<'".<%!68'".<%!68'".<"0G+"0G+"0G+ +M'2C3*47&#Q/-'2C3"0G+2%S(*47&*47&"0GS"0GS'2C3*47&*47&*47&"0G+ +M"0GS"0G+%!68(C&<0UIC+3AG&25@+3AG"0ED96=IEYB;+3AG@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``$QDXF8"0EYB; +M+3AG%!68(C&<'2C3(C&<"0F5%!68'".<+3AG"0ED&25@"0F5"0G+"0GS"0GS +M*47&(C&<+3AG0UIC+3AG&25@%!68"0F5&25@%!68&25@%!68'".<"0ED%QAE +M#`P]````#`P]````*S`^"0ED"0ED"0ED%QAE&25@"0ED+3AG96^<*S`^@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M$QDXEYB;P+*U>GZ=0UIC'".<(C&<(C&<'".<+3AG"0F5'".<+3AG+3AG+3AG +M+3AG+3AG%!68+3AG'".<+3AG%!68%QAE'".<+3AG"0F5&25@%QAE#`P]#`P] +M&25@+3AG%!68"0F5+3AG%!68'".<%!68"0F5'".<(C&<+3AG(C&<0UIC(C&< +M(C&<"0G+'2C3"0GS"0F5(C&<"0G+"0F5"0G+"0G+'2C3"0F5#Q/-"0F5'".< +M%!68%!68(C&<"0G+%!68(C&<%!68+3AG"0F5"0F5"0F5+3AG'".<%!68*47& +M0UIC559;0UIC(C&<05BD04F-)T2E+3AG(C&<'".<"0G+'".<%!68'".<"0ED +M(C&<"0F5%!68+3AG'".<(C&<"0G+'".<%!68"0F5+3AG+3AG&25@+3AG0UIC +M559;(C&<05BD(C&<(C&<'2C3+3AG(C&<+3AG)T2E+3AG'".<+3AG(C&<%!68 +M%QAE&25@+3AG%!68'".<+3AG+3AG&25@%!68"0F5'".<%!68'".<%!68'".< +M%!68%QAE'".<&25@%!68&25@(C&<%!68"0F5'2C3%!68'".<"0F5%!68(C&< +M05BD#Q/-#Q/-(C&<#Q/-(C&<(C&<"0G+#Q/-'2C3*47&2%S(*47&"0GS"0GS +M"0GS'2C3#Q/-'2C3"0G+'".<%!68'".<04F-P+7"S\O1F:?,96^<+3AG&25@ +M*S`^'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``$QDX96^<96^<+3AG'".<"0F5"0ED"0ED+3AG"0F5'".<"0F5"0F5 +M%!68'".<%!68"0G+#Q/-"0G+(C&<0UIC(C&<+3AG'".<+3AG&25@%QAE%!68 +M'".<+3AG+3AG+3AG'".<*S`^%!0V#@\0%!0V"0ED&25@+3AG%QAE&25@%QAE +M"0ED+3AG04F-$QDX@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``$QDX*S`^+3AG-3]`EYB;F=#5?HF\04F-+3AG"0F5&25@+3AG'".< +M%QAE+3AG%!68+3AG(C&<0UIC0UIC'".<'".<%QAE"0F5+3AG'".<'".<%!68 +M'".<%!68&25@%!0V$QDX%QAE'".<"0F5(C&<"0F5&25@'".<%QAE'".<(C&< +M%!68'".<559;0UIC96=I05BD(C&<#Q/-'2C3#Q/-"0G+"0G+(C&<#Q/-'2C3 +M%!68"0G+'".<%!68"0G+'2C3'".<"0F5'2C3'".<'".<%!68'".<(C&<(C&< +M'".<%!68%!68'".<'2C3(C&<05BD+3AG(C&<559;05BD(C&<'".<(C&<(C&< +M#Q/-"0G+%!68'".<%!68"0G++3AG"0F5&25@*47&%!68(C&<%!68&25@(C&< +M(C&<%QAE+3AG(C&<0UIC(C&<)T2E05BD'2C3'".<%!68(C&<(C&<(C&<(C&< +M%!68'".<(C&<&25@+3AG&25@%QAE'".<%QAE+3AG'".<+3AG(C&<+3AG+3AG +M+3AG%!68'".<+3AG+3AG+3AG'".<+3AG%!68'".<%!68(C&<'".<(C&<%!68 +M'".<%!68"0G+(C&<(C&<*47&'2C3'2C3"0G+'".<(C&<'2C3"0G+"0GS*47& +M96^<2%S(*47&*47&'2C3"0GS#Q/-"0G+"0F5%!68+3AG&25@(C&<05BDF:?, +MP+*UP+7"96^<96^<05BD%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``'A@896=I96^<"0ED"0ED%!0V*S`^$QDX +M#`P]"0F5%!68%!68'".<%QAE"0F5&25@"0F5"0ED&25@%!68+3AG+3AG(C&< +M+3AG%QAE"0F5"0F5&25@+3AG'".<%!68&25@"0ED"0ED#`P]#`P]#@\0%!0V +M"0ED"0ED#`P]"0ED%QAE"0ED+3AG+3AG%!0V'A@8@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``'A@8$QDX'A@8*S`^>GZ=L)BH96^<559;+3AG+3AG&25@ +M+3AG&25@%QAE%!68&25@+3AG(C&<&25@+3AG+3AG+3AG+3AG+3AG+3AG+3AG +M'".<"0ED"0F5%!68+3AG&25@%QAE'".<$QDX%QAE&25@+3AG%!68'".<%!68 +M%!68'".<%!68%!68'".<&25@+3AG(C&<04F-0UIC0UIC(C&<+3AG"0G+'2C3 +M#Q/-"0G+"0G+"0G+"0GS#Q/-"0G+(C&<"0F5%!68"0F5#Q/-"0G+#Q/-%!68 +M%!68'".<"0F5"0G+"0F5%!68'".<"0G+%!68(C&<(C&<(C&<'".<(C&<2%S( +M(C&<+3AG(C&<*47&'".<(C&<'".<(C&<"0F5'".<%!68'2C3%!68(C&<'".< +M"0G+'".<'".<(C&<%!68(C&<+3AG%!68'".<(C&<(C&<(C&<"0G+%!68(C&< +M(C&<'".<'".<(C&<+3AG+3AG+3AG+3AG&25@&25@%!68'".<+3AG(C&<'".< +M%!68%!68+3AG+3AG(C&<'".<&25@(C&<'".<%!68'".<"0F5%!68"0F5"0G+ +M(C&<+3AG'".<%!68'".<'2C3#Q/-"0G+(C&<(C&<(C&<(C&<#Q/-'2C3*47& +M*47&#Q/-"0G+"0G+"0GS*47&66^\?Y?/2%S(*47&'2C3"0F5+3AG'".<+3AG +M'".<(C&<96^<GZ=96=I +M%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``*S`^EYB;EYB;96^<559;(C&<(C&< +M+3AG'".<%!68+3AG+3AG(C&<0UIC(C&<+3AG&25@(C&<+3AG(C&<%QAE%!68 +M'".<(C&<+3AG&25@'".<%!68+3AG%!68'".<'".<%!68'".<%!68%QAE"0ED +M*S`^%QAE'".<(C&<'".<+3AG"0F5+3AG'".<%QAE%!68%!68'".<+3AG(C&< +M96=I0UIC(C&<+3AG"0G+"0GS'2C3#Q/-"0GS"0G+'2C3"0F5"0G+"0G+'2C3 +M'".<#Q/-"0F5(C&<'".<'".<%!68(C&<"0F5(C&<"0G+'".<%!68'".<"0F5 +M%!68(C&<'".<*47&(C&<(C&<(C&<#Q/-'2C3(C&<(C&<(C&<%!68(C&<"0G+ +M%!68'".<"0G+"0G+(C&<(C&<"0F5+3AG(C&<(C&<&25@(C&<'".<'2C3"0G+ +M#Q/-'2C3"0G+'".<'2C3'2C3%!68(C&<%!68'".<(C&<+3AG'".<%QAE%!68 +M"0ED+3AG%!68'".<+3AG'".<+3AG"0F5+3AG'".<(C&<%!68%!68'".<%!68 +M%!68(C&<'".<%!68'".<"0F5#Q/-05BD(C&<'2C3"0G+'2C3'".<*47&05BD +M'2C3'2C3"0G+"0G+*47&'2C3"0GS"0GS*47&"0GS*47&*47&*47&#Q/-'".< +M"0F5%QAE"0ED'".<(C&<(C&<(C&<+3AG%!0V#@\0@(``@(``'A@8*S`^*S`^ +M#`P]@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``#`P]0UIC96^<'".<%!68"0ED*S`^"0F5"0G+'2C3"0G+"0G+"0F5 +M+3AG"0ED$QDX'A@8#`P]"0ED+3AG(C&<%!68'".<+3AG%!68"0ED&25@"0ED +M+3AG+3AG'".<&25@%QAE"0ED+3AG"0ED%QAE%QAE"0ED%QAE#`P]"0ED%!0V +M"0F5+3AG%QAE96^GZ=2%S(*47&"0F5(C&<"0G+"0G+ +M*47&"0G+#Q/-"0GS"0G+"0ED"0ED#`P]"0ED$QDX%QAE'".<(C&<+3AG"0F5 +M"0ED&25@%QAE"0ED%QAE'".<%!68+3AG'".<%QAE"0ED"0ED"0F5&25@&25@ +M%!68&25@%QAE"0ED%QAE&25@&25@$QDX"0ED05BDEYB;*S`^%!0V$QDX*S`^ +M*S`^%!0V#@\0@(``@(``@(``@(``@(``@(``@(``'A@8%!0V$QDX*S`^F8"0 +MF=#5>GZ=96^<96=I05BD+3AG+3AG(C&<+3AG+3AG+3AG+3AG'".<+3AG(C&< +M'".<+3AG+3AG(C&<+3AG%!68'".<'".<+3AG"0ED"0F5+3AG'".<+3AG'".< +M(C&<+3AG"0F5%QAE%!68'".<&25@%!68(C&<"0F5$QDX%!0V&25@0UIC+3AG +M"0F5%!68'".<%!68"0G+%!68'".<%!68%QAE(C&<559;0UIC(C&<#Q/-'2C3 +M'".<"0G+'2C3#Q/-"0G+"0G+"0G+'2C3'2C3"0G+'2C3(C&<"0F5%!68'2C3 +M%!68'2C3"0F5(C&<"0G+*47&"0G+'".<(C&<#Q/-(C&<96^<04F-05BD(C&< +M#Q/-'2C3'2C3"0G+(C&<'".<"0F5'2C3#Q/-"0F5"0F5'".<#Q/-'2C3%!68 +M'".<'".<"0F5+3AG'".<+3AG(C&<'".<'2C3(C&<"0F5"0G+%!68"0F5+3AG +M'".<'".<+3AG%!68+3AG%!68'".<&25@%!68"0ED"0F5(C&<%!68'".<(C&< +M+3AG"0F5%!68'".<%!68'".<%!68'".<"0G+%!68'2C3%!68'2C3"0F5"0G+ +M'2C3'".<#Q/-'".<#Q/-"0G+"0G+"0G+'2C3'2C3"0G+"0GS#Q/-"0G+"0GS +M2%S(66^\2%S(*47&*47&"0G+(C&<"0F5&25@+3AG(C&GZ=F8"0EYB;EYB;P+*UL)BHL)BH*S`^@(``@(``@(``@(``@(``@(``-3]` +MEYB;EYB;?Y?/96^<96=I04F-559;(C&<+3AG(C&<+3AG+3AG0UIC0UIC559; +M(C&<+3AG(C&<0UIC+3AG+3AG+3AG(C&<+3AG+3AG'".<%QAE%!68%!68+3AG +M'".<%!68&25@%!68+3AG%!68"0F5+3AG'".<'".<%!68%!68%!68+3AG%!68 +M"0ED*S`^+3AG(C&<'".<%!68'".<%!68'".<(C&<'".<%!68'".<%!68+3AG +M+3AG96=I+3AG(C&<%!68"0G+#Q/-"0G+"0G+"0G+"0GS"0G+#Q/-"0G+#Q/- +M"0F5'".<%!68'".<"0F5(C&<"0F5%!68%!68"0G+"0F5%!68(C&<04F-05BD +M96=I05BD96^<05BD'2C3%!68#Q/-%!68"0G+"0G+#Q/-%!68"0G+(C&<'".< +M%!68'2C3"0F5%!68&25@%QAE+3AG+3AG(C&<+3AG+3AG&25@+3AG"0ED%!68 +M+3AG'".<%!68&25@"0F5&25@%!68"0F5+3AG'".<'".<%QAE%!68"0F5&25@ +M%!68"0F5(C&<"0F5%!68'".<%!68'".<%!68(C&<(C&<'".<%!68'2C3"0G+ +M(C&<"0F5(C&<"0F5(C&<%!68"0G+#Q/-"0F5"0G+"0G+"0GS"0G+#Q/-"0GS +M"0G+"0G+"0GS"0G+'2C3'2C305BD(C&<%!68+3AG'".<(C&<(C&<'".<+3AG +M05BD559;0UIC*S`^#`P]$QDX*S`^%!0V@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``$QDXEYB;P+7"2%S("0GS"0GS#Q/-'2C3"0GS'2C3"0G+"0GS"0G+ +M"0GS"0GS#Q/-"0G+"0GS'2C3"0F5%!68'".<+3AG'".<%QAE'".<%QAE+3AG +M"0ED%QAE&25@%!68"0F5&25@"0ED"0F5"0ED"0ED&25@"0F5+3AG"0ED%QAE +M#`P]+3AG&25@&25@%QAE96=I?Y?/P+*UF:?,P+7"S\O1F=#5-3]`%!0V#`P] +M#@\0#`P]$QDX#`P]+3AGEYB;EYB;EYB;96^<&25@$QDX&25@+3AG+3AG(C&< +M0UIC+3AG(C&<+3AG0UIC+3AG0UIC(C&<+3AG%!68'".<%QAE'".<&25@'".< +M%!68+3AG'".<'".<&25@%!68'".<%!68'".<(C&<'".<%!68'".<%!68%!68 +M&25@'".<'".<%!68'".<"0ED*S`^+3AG+3AG&25@+3AG'".<%QAE'".<%!68 +M+3AG"0F5+3AG&25@+3AG(C&<+3AG(C&<%!68'".<'".<'2C3"0GS*47&"0G+ +M#Q/-"0G+'".<"0G+'".<%!68+3AG"0F5(C&<"0G+%!68'".<'2C3'".<#Q/- +M"0G+'".<(C&<05BD96^<96^<96^<96=I96^<*47&'2C3'".<"0F5(C&<"0F5 +M"0G+'".<"0G+"0G+"0F5+3AG%!68+3AG"0F5+3AG%!68'".<%QAE&25@&25@ +M+3AG%QAE+3AG'".<"0F5&25@%!68'".<"0F5'2C3%!68'".<%!68'".<%QAE +M%!68&25@'".<'".<%QAE'".<"0G+(C&<'".<%!68'".<%QAE'".<%!68'".< +M%!68"0F5"0G+"0F5"0G+#Q/-"0G+'".<"0G+"0G+"0G+'".<'2C3"0G+*47& +M"0GS#Q/-"0G+'2C3"0GS'2C3#Q/-"0G+"0G+*47&*47&(C&<'".<'".<+3AG +M(C&<'".<'".<%QAE05BD96^<+3AG@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``%!0V-3]`66^\66^\#Q/-"0G+"0G+ +M#Q/-"0G+#Q/-"0G+*47&"0G+"0G+"0GS'2C3"0G+#Q/-"0F5(C&<%!68"0F5 +M+3AG"0F5&25@%QAE'".<+3AG%!68'".<+3AG"0ED%QAE&25@%QAE&25@%QAE +M%QAE"0ED"0ED&25@%QAE&25@"0ED%QAE"0ED&25@&25@(C&<559;05BD0UIC +M96=I+3AG+3AG+3AG+3AG(C&<+3AG+3AG&25@%QAE(C&<(C&<+3AG+3AG+3AG +M+3AG+3AG05BD+3AG0UIC+3AG+3AG0UIC+3AG+3AG(C&<+3AG(C&<&25@'".< +M+3AG'".<%QAE%!68+3AG'".<%!68"0F5+3AG%!68+3AG'".<+3AG"0F5"0F5 +M+3AG+3AG'".<+3AG"0F5+3AG%!68%!68"0F5+3AG%QAE%QAE&25@+3AG%!68 +M'".<(C&<"0F5'".<%!68'".<+3AG%!68'".<+3AG+3AG%!68'".<(C&<'".< +M#Q/-#Q/-"0G+"0G+"0G+"0GS"0GS"0G+#Q/-"0G+'".<"0F5"0G+#Q/-'2C3 +M"0F5(C&<"0F5#Q/-'".<%!68*47&05BDGZ=96^<05BD*47& +M(C&<"0G+%!68'2C3%!68'".<%!68'".<+3AG%!68'".<'".<&25@%!68'".< +M"0F5'".<'2C3%!68%!68%!68'2C3%!68"0G+(C&<"0G+'".<"0G+(C&<"0F5 +M"0F5+3AG%QAE"0F5+3AG"0F5+3AG"0F5%QAE'".<'".<%!68%!68'".<(C&< +M%!68"0G+%!68"0G+'".<%!68'2C3'".<#Q/-'2C3(C&<"0F5#Q/-'2C3#Q/- +M'2C3#Q/-#Q/-"0G+"0G+"0G+"0G+"0GS"0G+*47&*47&'2C3"0G+"0G+#Q/- +M'2C3+3AG+3AG%QAE+3AG+3AG(C&<*47&+3AG96=IEYB;*S`^@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#`P] +M*S`^66^\F:?,#Q/-'2C3"0G+"0G+'2C3"0G+"0G+"0G+"0G+#Q/-"0G+'2C3 +M"0G+"0F5'2C3'".<%!68&25@%QAE+3AG"0F5%!68'".<"0F5+3AG"0ED'".< +M&25@%!68&25@%QAE"0ED&25@"0ED+3AG%!68"0ED&25@%QAE&25@"0ED%QAE +M$QDX+3AG"0ED&25@%QAE&25@&25@+3AG&25@0UIC&25@+3AG+3AG&25@*S`^ +M*S`^+3AG-3]`*S`^+3AG0UIC559;+3AG+3AG&25@(C&<+3AG'".<+3AG+3AG +M%!68+3AG%!68+3AG%!68%QAE%!68&25@'".<%!68'".<+3AG+3AG"0F5'".< +M"0F5+3AG"0F5+3AG%QAE'".<'".<%!68'".<"0F5'".<%!68'".<%!68"0F5 +M+3AG&25@&25@'".<+3AG%!68'".<%!68+3AG"0G+%!68'".<&25@96=I96^< +M?Y?/(C&<"0F5(C&<(C&<'".<'".<"0GS'2C3"0GS"0G+"0G+#Q/-'2C3"0G+ +M%QAE+3AG(C&<"0F5'".<#Q/-'".<"0G+"0F5'2C3(C&<(C&<96^<96^<05BD +M96=I96^<05BD0UIC0UIC+3AG'".<%!68%!68+3AG&25@%!68+3AG'".<%QAE +M+3AG(C&<(C&<%!68'".<"0G+%!68"0G+"0F5'2C3"0G+'".<"0F5"0F5"0F5 +M"0F5"0G+"0F5"0F5(C&<%!68'".<'".<%!68'".<"0F5"0F5%!68'".<%!68 +M"0F5'".<'".<"0F5'2C3'".<%!68'2C3"0G+(C&<"0G+"0G+"0G+"0G+"0G+ +M"0G+'2C3"0G+"0G+"0G+"0G+"0G+'2C3"0GS'2C3"0GS"0G+'2C304F-05BD +M2%S((C&<(C&<(C&<%!68'".<%QAE&25@+3AG*S`^F:?,S\O12%S(66^\?HF\ +M+3AG#@\0@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``%!0V>GZ=EYB;'2C3#Q/-"0G+#Q/-'2C3"0G+#Q/- +M'2C3"0G+'".<"0G+#Q/-"0F5#Q/-%!68(C&<"0F5+3AG"0F5&25@%!68+3AG +M+3AG"0F5+3AG%!68%QAE+3AG%QAE'".<%QAE%!68&25@%QAE"0ED'".<"0ED +M"0ED&25@%!68#`P]&25@"0ED"0ED"0ED%!0V+3AG"0ED+3AG+3AG+3AG%QAE +M&25@*S`^&25@*S`^+3AG0UIC+3AG+3AG&25@0UIC(C&<+3AG&25@'".<%QAE +M+3AG+3AG%!68'".<'".<%!68+3AG'".<%QAE'".<'".<'".<%!68+3AG&25@ +M%!68%!68'".<%!68+3AG'".<%!68'".<+3AG"0F5+3AG%!68%QAE+3AG%!68 +M+3AG'".<"0F5(C&<'".<%QAE*S`^%QAE+3AG+3AG"0F5+3AG"0F5&25@%!68 +M+3AG&25@"0ED96^GZ=#@\0@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@8%!0V+3AG66^\*47& +M'2C3"0G+"0G+'2C3"0GS"0GS#Q/-"0G+"0G+"0G+(C&<'".<'".<"0F5'".< +M%!68"0F5+3AG"0F5'".<%!68+3AG'".<&25@&25@'".<"0ED"0ED&25@%QAE +M&25@'".<%QAE&25@%QAE&25@"0ED&25@%QAE"0ED&25@%!0V&25@%QAE&25@ +M%QAE"0ED&25@%QAE&25@%QAE&25@%QAE%QAE&25@&25@+3AG%QAE+3AG+3AG +M%QAE'".<+3AG%QAE+3AG'".<%!68&25@+3AG%!68'".<%QAE'".<%!68+3AG +M%!68+3AG'".<%!68%!68'".<&25@+3AG'".<%!68'".<(C&<"0F5"0F5%!68 +M'".<'".<'".<&25@'".<"0F5"0F5+3AG"0F5+3AG"0F5+3AG&25@+3AG%QAE +M&25@"0ED"0ED+3AG"0F5&25@%QAE0UIC?Y?/F=#5F=#505BD"0F5"0F5&25@ +M%!68'".<'2C3%!68"0F5%!68(C&<"0F5'".<%!68%QAE&25@+3AG'".<%!68 +M'2C3%!68"0F5'".<(C&<0UIC96=I05BD96=I96=I0UIC0UIC96=I+3AG+3AG +M+3AG%!68'".<%!68%!68'".<"0G+%!68(C&<0UIC96^<05BD96^<(C&<#Q/- +M'".<%!68%!68'2C3"0G+(C&<'".<'".<"0F5"0G+"0F5"0F5+3AG%!68&25@ +M%!68&25@'".<"0F5"0F5'".<"0F5"0G+%!68"0G+(C&<"0G+*47&'2C3"0F5 +M"0G+'2C3"0G+"0G+(C&<"0G+"0G+#Q/-'2C3"0G+"0G+"0G+'2C3"0G+"0G+ +M'2C3"0G+'2C3"0GS#Q/-"0G+#Q/-'".<'".<+3AG%QAE+3AG+3AG+3AG'".< +M(C&<'".<96^<96^<$QDX%!0V$QDX%!0V$QDX%!0V@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``'A@8&25@*47&*47&'2C3#Q/-"0G+#Q/-'2C3"0GS'2C3"0G+'".< +M"0F5"0G+%!68'2C3%!68'2C3'".<"0F5+3AG'".<"0F5'".<%QAE%!68%!68 +M%!68+3AG+3AG"0F5%QAE%QAE+3AG&25@+3AG"0F5"0ED%!0V"0ED&25@"0ED +M%QAE&25@"0ED"0ED&25@%QAE&25@"0ED+3AG"0ED%!0V"0ED"0ED&25@#`P] +M+3AG"0ED"0ED%QAE'".<"0ED"0ED%!68&25@&25@%QAE'".<%QAE"0F5+3AG +M&25@+3AG'".<%!68+3AG'".<%!68(C&<"0F5+3AG%!68(C&<"0F5%!68&25@ +M'".<%!68"0F5(C&<'".<%!68%QAE'".<%!68%!68%!68'".<%!68'".<%!68 +M+3AG&25@(C&<%QAE&25@%!0V$QDX#`P]#`P]*S`^0UICF8"0F=#5S\O1F:?, +M66^\%!68%QAE+3AG"0ED%QAE%!68"0F5"0F5&25@"0F5"0ED%QAE%QAE&25@ +M'".<%!68+3AG"0F5%!68'".<+3AG+3AG+3AG96=I0UIC96=I0UIC0UIC0UIC +M559;96=I05BD(C&<%!68'2C3"0F5"0F5#Q/-'".<"0F5%!68(C&<96^<96^< +MGZ=96=I559;05BDF:?,EYB;$QDX +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``$QDXF8"0 +MF:?,2%S("0G+"0G+#Q/-"0G+'2C3"0G+"0G+"0G+*47&"0G+%!68"0G+%!68 +M'2C3"0G+"0F5'".<"0F5+3AG'".<%QAE%!68'".<'".<%!68%!68+3AG"0F5 +M%QAE'".<&25@%QAE'".<+3AG+3AG"0ED"0ED%QAE%QAE"0ED"0ED"0ED&25@ +M+3AG"0ED%!0V"0ED+3AG"0ED"0ED"0ED&25@"0ED'".<"0ED%QAE"0ED"0ED +M+3AG"0ED"0ED+3AG"0F5"0F5+3AG%QAE%!68+3AG&25@'".<"0F5+3AG'".< +M+3AG'".<%!68%!68%!68"0F5&25@%QAE'".<'".<'".<'".<"0F5+3AG'".< +M%!68'".<'".<(C&<"0F5(C&<%!68'".<"0F5'".<+3AG*S`^#`P]%!0V$QDX +M%!0V$QDX&25@$QDX0UIC2%S(F:?,F:?,04F-%!68"0F5"0F5%!68"0ED%QAE +M"0F5%QAE'".<"0F5%!68"0F5&25@+3AG'".<+3AG%!68+3AG'".<+3AG(C&< +M0UIC0UIC+3AG559;+3AG96=I96=I+3AG0UIC96=I0UIC05BD+3AG%!68"0F5 +M'".<+3AG"0F5"0F5(C&<'".<%!68+3AG+3AG96=I96=I0UIC0UIC+3AG96=I +M+3AG+3AG+3AG(C&<+3AG96=I+3AG0UIC+3AG'".<"0F5'".<"0F5"0F5'".< +M"0F5%!68'".<'".<"0F5"0F5(C&<#Q/-'2C3"0G+'2C3"0F5*47&"0G+#Q/- +M"0G+#Q/-'2C3"0G+"0G+'2C3"0G+*47&"0G+"0G+#Q/-"0G+'2C3#Q/-"0G+ +M%!68#Q/-+3AG)T2E&25@+3AG+3AG+3AG+3AG+3AG+3AG%QAE559;F:?,+3AG +M+3AG>GZ=559;%!0V'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``'A@8+3AG96=IF:?,'2C3"0F5'2C3"0GS#Q/-"0GS'2C3"0GS +M"0G+"0G+'".<"0F5"0G+"0F5(C&<%!68'".<%!68"0F5"0F5&25@+3AG%!68 +M+3AG"0F5(C&<'2C3'".<"0G+(C&<%!68&25@%QAE"0ED"0ED%QAE&25@&25@ +M"0ED&25@&25@%QAE"0ED"0ED"0F5&25@"0ED"0ED"0ED+3AG"0F5%QAE"0ED +M%QAE"0ED"0ED+3AG"0ED"0ED&25@"0F5"0ED&25@+3AG"0F5'".<&25@"0F5 +M+3AG%!68%QAE'".<%!68%!68&25@%!68&25@'".<%!68(C&<%!68%!68(C&< +M%!68#Q/-(C&<"0F5(C&<"0F5+3AG+3AG%!68+3AG&25@"0F5%QAE"0ED$QDX +M#`P]````#`P]#@\0*S`^*S`^+3AGEYB;F:?,05BD(C&<(C&<*47&'".<&25@ +M"0F5"0ED"0ED&25@"0ED&25@"0F5%QAE"0F5&25@%QAE"0ED"0F5%QAE'".< +M'".<+3AG0UIC0UIC96=I+3AG+3AG(C&<,4)F+3AG0UIC+3AG96=I05BD559; +M+3AG+3AG+3AG'".<+3AG"0ED%!68+3AG%!68+3AG'".<+3AG%!68'".<0UIC +M+3AG-3]`96=I96=I0UIC+3AG(C&<+3AG559;2&V"05BD96^<96=I(C&<*47& +M(C&<%!68#Q/-(C&<"0G+(C&<"0G++3AG"0ED"0G+%!68'".<"0G+%!68"0G+ +M'".<"0G+"0G+"0G+'2C3"0G+"0G+"0G+(C&<#Q/-'2C3"0G+"0G+"0G+"0G+ +M'2C3*47&(C&<(C&<(C&<'".<&25@+3AG*S`^%QAE96=IF8"0?Y?/96^<559; +M(C&<&25@+3AG-3]`#@\0'A@8*S`^@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^?Y?/66^\*47&"0G+ +M"0G+'2C3#Q/-"0G+#Q/-"0GS#Q/-"0G+'2C3%!68'".<%!68'".<"0F5+3AG +M&25@+3AG%QAE"0F5'".<#Q/-'2C3"0G+"0G+#Q/-"0G+'".<"0F5+3AG'".< +M+3AG&25@+3AG%QAE#`P]"0ED%QAE"0ED"0ED&25@%QAE"0ED%QAE+3AG"0ED +M&25@"0ED"0ED&25@"0ED&25@%QAE&25@"0ED&25@%QAE"0ED'".<%QAE"0F5 +M%QAE'".<+3AG%!68"0F5+3AG'".<'".<%!68'".<+3AG"0F5'".<%!68'".< +M+3AG"0F5'".<'".<"0F5'".<'".<"0F5'".<%!68"0ED%QAE'".<&25@&25@ +M"0ED#`P]$QDX%!0V````'A@8%!0V*S`^+3AG0UIC96=I0UICF:?,F:?,05BD +M+3AG'".<"0ED%QAE"0F5&25@%!68&25@"0F5"0F5%QAE"0F5'".<"0F5+3AG +M"0ED&25@"0ED+3AG(C&<+3AG(C&<559;0UIC96=I0UIC+3AG+3AG%!68+3AG +M+3AG0UIC0UIC0UIC0UIC+3AG+3AG%!68&25@%!68'".<+3AG%!68'".<+3AG +M%!68%QAE'".<+3AG(C&<(C&<96=I0UIC2&V"96^<05BD05BD(C&<05BD96^< +M2&V"GZ=F:?,F:?, +MF:?,?Y?/2%S(+3AG'".<"0F5"0F5"0F5"0ED&25@"0ED"0ED"0F5%QAE"0ED +M&25@"0F5%QAE%!68"0F5"0ED%!68&25@+3AG+3AG0UIC96=I0UIC0UIC+3AG +M0UIC'".<+3AG%!68%!68'".<(C&<+3AG(C&<(C&<+3AG%!68+3AG"0F5+3AG +M'".<"0F5(C&<"0F5#Q/-'".<#Q/-'".<"0G+"0G+(C&<2%S(66^\96^<>GZ= +M66^\?Y?/66^\>GZ=96^<96^<05BD96^<96^<(C&<05BD#Q/-"0G+#Q/-'".< +M%!68'".<(C&<"0F5#Q/-"0F5'".<#Q/-'".<"0F5'2C3'2C3(C&<'2C3#Q/- +M"0G+"0G+"0G+"0GS"0G+'2C3#Q/-"0G+"0G+'2C3+3AG&25@+3AG%QAE+3AG +M+3AG+3AG%!68+3AG+3AGF:?,EYB;559;$QDX#`P]*S`^>GZ=EYB;'A@8@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``#@\0$QDX96^GZ=96^<#`P]@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^?HF\ +M96^<#Q/-'2C3"0G+"0F5"0G+#Q/-'2C3"0G+%!68'".<"0F5'".<%!68&25@ +M'".<"0F5"0ED"0F5(C&<'".<"0G+'2C3?Y?/P+*UF=#5?Y?/96^<96^<+3AG +M&25@*S`^#`P]*S`^"0ED&25@*S`^%QAE&25@"0ED"0ED*S`^"0ED"0ED%QAE +M$QDX%QAE"0ED&25@%QAE"0ED&25@%QAE"0ED"0ED+3AG"0ED"0ED%!68"0ED +M%!68+3AG"0ED%!68'".<"0F5+3AG%!68'".<%!68'".<%QAE'".<"0F5%!68 +M"0F5%!68+3AG%!68'".<"0F5"0ED%QAE#`P]*S`^$QDX#`P]#`P]'A@8'A@8 +M%!0V*S`^96=IF=#5U=3>SMK=U=3>X.#GF=#566^\96^<'".<"0ED"0ED%!68 +M"0ED'".<"0F5"0ED"0ED+3AG&25@"0ED'".<"0ED+3AG"0ED'".<%QAE%!68 +M"0F5"0F5*S`^*S`^-3]`+3AG0UIC0UIC96^<05BD(C&<"0G+'".<"0G+"0G+ +M"0GS'2C3#Q/-#Q/-'2C3#Q/-"0GS'2C3#Q/-"0G+"0GS*47&"0GS"0G+"0GS +M"0G+"0G+*47&"0G+"0GS'2C3"0GS'2C3*47&2%S(66^\?Y?/?Y?/?Y?/96^< +M96^<96^<96^<05BD2%S('".<'".<'".<#Q/-"0F5(C&<&25@"0G+"0G+#Q/- +M'".<"0G+'".<#Q/-'2C3"0G+'2C3"0G+#Q/-'2C3"0G+%!68'2C3"0G+'".< +M04F-0UIC&25@"0ED"0ED%QAE*S`^&25@+3AG05BD96^<96=I(C&<05BD559; +M%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``*S`^?Y?/F:?,(C&<"0F5+3AG"0G+'2C3"0F5"0G+%!68 +M"0F5#Q/-'".<"0F5"0F5%!68%QAE+3AG'".<'".<%!68#Q/-66^\F:?,F:?, +M?Y?/66^\(C&<&25@0UIC*S`^+3AG%!0V$QDX%!0V+3AG"0F5+3AG&25@+3AG +M"0ED+3AG"0ED#`P]&25@"0ED"0ED"0ED&25@"0ED$QDX#`P]"0ED$QDX&25@ +M"0ED%!0V"0ED%!0V&25@"0ED"0ED'".<%!68%QAE'".<%!68"0F5+3AG&25@ +M%!68&25@%!68"0ED&25@&25@+3AG(C&<+3AG%!68"0F5'".<"0ED"0ED#`P] +M#`P]'A@8#`P]%!0V0UICEYB;F:?,EYB;S\O1U=3>X^KKU=3>S\O1>GZ=(C&< +M%QAE"0ED%QAE&25@"0F5"0F5%!68%QAE*S`^&25@&25@"0ED"0F5%QAE"0ED +M"0F5"0F5%QAE"0F5&25@+3AG"0ED%QAE+3AG0UIC*S`^*S`^&25@+3AG&25@ +M(C&<"0G+#Q/-"0G+"0G+'2C3"0G+"0GS"0G+"0G+"0GS"0G+"0G+"0G+'2C3 +M"0G+"0G+%!68"0G+#Q/-'2C3"0G+"0G+"0GS"0G+"0G+"0GS"0GS"0GS(C&< +M(C&<2%S(05BD2%S(0UIC2&V"05BD96^<*47&(C&<#Q/-(C&<'".<%!68'".< +M"0F5"0F5%!68"0G+"0G+"0G+*47&"0G+#Q/-"0G+"0G+*47&"0G+(C&<'".< +M"0G+%!68"0F5%!68&25@%QAE&25@%QAE*S`^*S`^&25@&25@+3AG04F-*S`^ +M+3AG?HF\?Y?/96^<96^<$QDX@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^F=#5U=3>2%S(#Q/-"0F5 +M"0G+"0G+#Q/-"0G+'".<"0F5(C&<"0F5(C&<'2C3+3AG%!68'".<%!68%!68 +M(C&<05BD?Y?/F=#5F:?,?Y?/*47&+3AG'".<+3AG+3AG-3]`$QDX#`P]&25@ +M"0ED&25@"0F5%!68#`P]&25@"0ED&25@%QAE%QAE%!0V&25@%QAE"0ED+3AG +M%QAE"0ED+3AG%QAE#`P]"0ED&25@&25@"0ED&25@%!68%QAE'".<"0F5'".< +M+3AG"0F5"0ED%!68%QAE+3AG%!68"0F5'".<#Q/-%!68'".<%!68"0F5'".< +M"0ED%!68&25@%!0V$QDX*S`^&25@*S`^$QDX5B@>P+7"S\O1F:?,F=#5Q,32 +M?Y?/66^\(C&<%QAE&25@$QDX#`P]'A@8#`P]%QAE'".<&25@"0ED&25@%!0V +M%QAE&25@"0ED"0ED&25@%QAE+3AG"0ED+3AG"0F5%QAE'".<&25@&25@"0ED +M&25@"0ED&25@"0ED"0ED"0ED'".<"0F5"0F5%!68"0G+#Q/-'2C3#Q/-"0GS +M*47&"0G+"0GS"0G+"0GS"0G+"0GS'2C3'2C3"0G+'".<"0G+#Q/-'2C3"0G+ +M"0G+*47&#Q/-*47&*47&*47&*47&#Q/-'2C3(C&<*47&*47&'2C3%!68'".< +M'".<(C&<*47&&25@%QAE'".<%!68'2C3#Q/-'2C3%!68"0G+'2C3"0G+'2C3 +M#Q/-"0G+"0F5'".<%QAE'".<+3AG"0ED+3AG%!0V*S`^&25@+3AG"0ED&25@ +M"0ED%QAE+3AG96=I$QDX#@\0*S`^*S`^*S`^*S`^#`P]@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@8 +MF8"0EYB;(C&<(C&<'".<(C&<"0G+'2C3%!68"0F5"0F5"0G+'".<"0G+%!68 +M"0F5+3AG'".<+3AG&25@'".<66^\F:?,F=#5?Y?/2%S(*47&+3AG&25@+3AG +M0UIC*S`^%!0V%!0V%!0V"0ED+3AG+3AG&25@%QAE$QDX%QAE+3AG"0ED&25@ +M%QAE"0ED&25@+3AG"0F5&25@+3AG&25@"0ED&25@+3AG%QAE"0F5+3AG&25@ +M+3AG'".<+3AG&25@%!68"0ED"0F5'".<+3AG'".<&25@"0G+"0F5%!68'".< +M(C&<%!68'".<%!68"0F5"0F5"0ED"0ED%!0V"0ED*S`^"0ED*S`^#`P]*S`^ +MP+*UU\O-96=I66^\66^\05BD(C&<"0F5&25@%!0V"0ED*S`^#`P]$QDX"0F5 +M%!68"0F5+3AG&25@*S`^&25@"0ED"0ED%QAE"0F5&25@"0F5"0ED%QAE'".< +M%QAE+3AG"0ED%QAE%QAE"0ED"0ED%QAE*S`^$QDX%QAE"0ED%!68"0ED"0F5 +M'".<#Q/-"0F5'2C3"0F5"0G+'2C3#Q/-'2C3"0G+'2C3#Q/-"0G+"0G+#Q/- +M'2C3%!68"0G+(C&<"0F5#Q/-*47&'2C32%S(2%S(*47&'2C3"0G+'".<#Q/- +M'2C3(C&<(C&<'2C3%!68#Q/-(C&<'".<%!68%QAE"0F5"0F5"0G+"0G+"0G+ +M"0G+'".<#Q/-'".<#Q/-"0F5"0F5(C&<(C&<&25@*S`^"0ED+3AG&25@&25@ +M"0ED%QAE05BD96=I(C&<+3AG&25@(C&GZ=EYB;F=#5?Y?/ +M66^\2%S(+3AG(C&<(C&<0UIC+3AG'A@8&25@$QDX+3AG'".<'".<%QAE$QDX +M*S`^+3AG+3AG+3AG&25@+3AG+3AG&25@%QAE+3AG&25@(C&<%!68+3AG+3AG +M%QAE&25@+3AG+3AG"0ED+3AG&25@%!68+3AG+3AG'".<%QAE+3AG0UIC(C&< +M(C&<%!68'2C3"0F5"0G+"0F5'".<%!68"0F5"0F5%QAE&25@#`P]&25@+3AG +M&25@%QAE'".<*S`^+3AGF=#5S\O1559;+3AG'".<%!68'".<+3AG'".<'".< +M%!68&25@%!0V"0ED"0ED(C&<'".<%QAE+3AG(C&<'".<+3AG&25@"0ED&25@ +M"0ED%QAE'".<+3AG&25@"0F5+3AG"0F5&25@"0ED$QDX%QAE"0ED"0ED"0ED +M"0ED&25@"0F5&25@%QAE"0F5"0F5"0ED"0F5%!68"0F5"0F5"0F5"0F5%!68 +M"0G+"0F5'".<"0F5%!68"0G+'".<"0F5%!68"0F5(C&<2%S(96^<96^<05BD +M*47&%!68"0G+'2C3"0G+"0G+"0G+'".<#Q/-'".<'".<(C&<'".<%!68'".< +M(C&<'".<#Q/-"0G+'".<#Q/-"0F5%!68(C&<(C&<'".<"0F5&25@*S`^"0ED +M&25@%QAE&25@%QAE%QAE#`P]+3AGF:?,P+7"EYB;96^<(C&<96^GZ=*S`^@(``%!0VEYB;EYB;%!0V@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``'A@8>GZ=EYB;#Q/-(C&<"0G+'2C3#Q/-'2C3#Q/-%!68 +M'".<"0F5&25@'".<"0F5"0F5"0F5"0F5"0G+(C&<%QAE%!0V$QDX+3AG(C&< +M*47&&25@2%S(66^\*47&559;+3AG%!0V%!68+3AG%!68&25@"0ED"0ED'".< +M+3AG+3AG*S`^&25@+3AG+3AG+3AG+3AG*S`^+3AG&25@*S`^&25@+3AG+3AG +M&25@+3AG&25@+3AG+3AG05BD0UIC+3AG(C&<"0F5%!68+3AG0UIC(C&<'".< +M%!68"0F5(C&<+3AG+3AG'".<%!68"0ED"0ED%!0V$QDX&25@+3AG+3AG%!68 +M+3AG)T2E%QAE0UICQ,32]OW^F=#596=I*47&2%S(*47&'2C3(C&<'".<(C&< +M%QAE&25@#`P]$QDX&25@"0ED"0ED"0ED+3AG+3AG-3]`+3AG*S`^&25@%QAE +M"0ED%!68&25@%!68+3AG%!68%!68"0F5%QAE%QAE$QDX%QAE&25@"0ED"0ED +M&25@"0ED"0ED#`P]"0ED%!68"0ED"0ED"0ED&25@%QAE"0ED&25@"0F5%QAE +M"0ED&25@"0ED&25@"0ED%QAE'".<&25@%QAE%QAE&25@+3AG+3AG&25@%QAE +M"0ED%!68"0F5"0F5(C&<%!68"0F5%!68(C&<"0F5+3AG&25@&25@+3AG+3AG +M%!68%QAE&25@%QAE&25@%!68+3AG&25@*S`^"0ED+3AG%QAE&25@+3AG>GZ= +MF:?,+3AG+3AG&25@+3AG05BD96=I*S`^@(``@(``@(``'A@8%!0V'A@8@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``#`P]2%S(2%S("0G+"0G+#Q/- +M"0G+"0F5'2C3"0F5'".<"0F5#Q/-"0G+%!68"0G+"0F5(C&<"0G+*47&"0G+ +M"0F5&25@%QAE&25@'".<'".<+3AG(C&<2%S(05BD-3]`*S`^+3AG&25@'".< +M&25@"0ED+3AG%QAE+3AG+3AG&25@+3AG*S`^+3AG+3AG+3AG+3AG+3AG%QAE +M+3AG+3AG+3AG0UIC+3AG+3AG0UIC+3AG%QAE&25@+3AG96=I'".<&25@'".< +M(C&<05BD*47&'2C3 +M(C&<*47&+3AG&25@*S`^&25@#`P]%!0V"0ED%QAE"0G+"0F5(C&<"0F5(C&< +M%!68(C&<'".<%QAE"0ED&25@"0ED+3AG"0F5'".<&25@+3AG&25@"0ED&25@ +M"0ED#`P]"0ED*S`^"0ED%QAE"0ED&25@%QAE&25@"0ED+3AG"0ED%QAE"0ED +M"0ED"0ED%QAE"0ED$QDX"0ED#`P]&25@%QAE%QAE&25@%QAE%QAE&25@*S`^ +M+3AG+3AG+3AG"0ED"0ED+3AG"0ED&25@"0ED'".<"0F5+3AG&25@"0ED&25@ +M"0ED+3AG+3AG&25@"0F5&25@&25@"0ED*S`^&25@0UIC(C&<+3AG#`P]"0ED +M&25@*S`^+3AG96=I0UIC*S`^*S`^96^<96^<(C&GZ=96^< +MEYB;EYB;559;@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``'A@8?Y?/F:?,2%S("0G+*47&"0G+(C&<"0F5'".<'".< +M"0F5"0GS'2C3#Q/-"0F5%!68"0ED'".<(C&<"0G+"0GS"0G+#Q/-"0F5'".< +M%!68"0ED&25@%QAE*S`^"0ED"0ED&25@+3AG%!68&25@"0ED+3AG"0ED&25@ +M%QAE*S`^"0ED%QAE'".<%QAE+3AG"0ED&25@+3AG%QAE*S`^"0ED*S`^%QAE +M&25@+3AG%QAE&25@%QAE+3AG+3AG"0ED&25@&25@*S`^%QAE%QAE&25@%QAE +M+3AG"0ED*S`^#`P]#`P]$QDX$QDX$QDX"0ED+3AG'".<+3AG&25@"0F5&25@ +M+3AG05BDF=#5X.#G]OW^X^KKF=#5+3AG$QDX#`P]*S`^#`P]'A@8#@\0$QDX +M$QDX````%QAE*S`^%!0V#`P]%QAE#`P]$QDX'A@8#`P]%!0V#`P]*S`^#`P] +M"0ED"0ED"0ED'".<%!68&25@'".<"0ED&25@&25@*S`^$QDX#`P]*S`^#`P] +M$QDX%QAE$QDX#`P]%!0V"0ED#`P]*S`^"0ED"0ED%!0V#`P]#`P]"0ED*S`^ +M#`P]$QDX#`P]%QAE&25@%QAE"0ED*S`^*S`^&25@&25@%QAE"0F5"0ED&25@ +M"0ED+3AG"0ED*S`^#`P]%!0V$QDX$QDX$QDX#`P]*S`^&25@*S`^$QDX"0ED +M&25@+3AG&25@#`P]%QAEF:?,SMK=F=#5F8"096^<+3AG+3AG(C&F:?,*S`^```````` +M#`P]````#`P]'A@8````%!0V#`P]*S`^*S`^5B@>*S`^'A@8%!0V#`P]'A@8 +M#@\0'A@8$QDX%!0V$QDX"0ED&25@%QAE&25@%QAE&25@%QAE+3AG%!68"0ED +M*S`^%!0V#@\0%!0V#`P]%!0V$QDX%!0V"0ED#@\0$QDX%!0V$QDX#`P]$QDX +M%!0V$QDX%!0V#`P]#@\0#`P]%!0V&25@"0ED%!0V&25@#`P]#`P]%QAE$QDX +M%QAE$QDX&25@%!0V&25@#`P]#`P]%QAE$QDX#`P]*S`^#`P]%!0V*S`^#`P] +M%!0V0UIC+3AG%!0V#`P]*S`^%!0V"0ED*S`^*S`^L)BHU\O-U=3>U\O-S\O1 +MF:?,66^\+3AG+3AG'A@8````````````*S`^F:?,>GZ=05BD>GZ=*S`^@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``*S`^04F-(C&<%!68'".<'".<%!68'".<+3AG'".<(C&<"0G+#Q/-"0G+ +M%!68'".<"0F5"0F5"0F5"0GS"0GS"0G+"0G+%!68%QAE&25@%QAE&25@%QAE +M&25@+3AG"0F5%!68'".<%QAE"0F5"0F5$QDX#`P]#`P]'A@8$QDX%!0V+3AG +M0UIC0UIC%QAE````#`P]````#`P]$QDX%!0V#@\0%!0V````$QDX'A@8'A@8 +M#`P]'A@8#`P]$QDX%!0V````'A@8#`P]%!0V0UIC(C&<0UIC05BD04F-0UIC +M'".<'".<+3AG'".<+3AG'".<+3AG&25@(C&<+3AG96^ +MJ:VO>GZ=*S`^%!0V#@\0'A@8'A@8*S`^'A@8*S`^5B@>*S`^5B@>5B@>HC\G +M5B@>5B@>'A@8*S`^*S`^#`P]#`P]%!0V#`P]"0ED%!0V%QAE'".<%!68+3AG +M(C&<'".<+3AG"0F5%QAE$QDX'A@8%!0V$QDX'A@8#`P]$QDX%!0V$QDX%!0V +M%!0V$QDX#`P]%!0V#@\0#`P]*S`^#`P]$QDX%!0V$QDX%!0V+3AG&25@%!0V +M%!0V#`P]'A@8#`P]$QDX%QAE#`P]%!0V#`P]"0ED*S`^#`P]*S`^$QDX%!0V +M$QDX$QDX#`P]'A@8$QDX*S`^96=IGZ=EYB;96^<*S`^````%!0V#@\0%!0V#@\0'A@8#`P] +M$QDX%!0V#`P]#@\0#`P]*S`^*S`^%!0V*S`^#`P]$QDX#`P]*S`^96=I96^< +M?Y?/66^\F:?,?Y?/96^<05BD(C&<(C&<(C&<(C&<*47&96=I96=IHC\GSVQ$ +MN7YBS\O1U=3>U\O-S\O196=I*S`^*S`^5B@>*S`^'A@8HC\GHC\GLUD\HC\G +MHC\GHC\GLUD\LUD\HC\G5B@>5B@>$QDX+3AG559;&25@*S`^$QDX*S`^$QDX +M"0ED&25@%QAE+3AG'".<%QAE+3AG&25@&25@%QAE$QDX#`P]'A@8%!0V#`P] +M$QDX%!0V$QDX"0ED#`P]$QDX'A@8#`P]*S`^#`P]%!0V$QDX%QAE$QDX'A@8 +M"0ED&25@*S`^%QAE$QDX#`P]%!0V$QDX%!0V*S`^#`P]$QDX#`P]%!0V*S`^ +M%!0V#`P]#`P]%!0V#`P]%!0V*S`^#`P]%!0V$QDX%!0V96^GZ=559; +M*S`^*S`^#`P]%QAE96=IEYB;EYB;EYB;EYB;L)BHF:?,EYB;P+7"EYB;EYB; +MEYB;96^<04F-66^\?Y?/F:?,P+*US\O1F=#5P+7"L)BH0UIC*S`^$QDX'A@8 +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``*S`^EYB;L)BH>GZ=+3AG%!0V'A@8 +M#`P]"0ED"0F5(C&<"0F5(C&<"0F5%!68'".<"0G+#Q/-'2C3"0G+'2C3#Q/- +M"0F5"0G+"0G+"0G+"0G+(C&<"0F5&25@"0ED#`P]&25@#`P]%QAE&25@'".< +M%!68&25@"0ED'A@8%!0V#@\0#`P]*S`^*S`^559;P+7"P+*U*S`^#@\0#`P] +M#@\0#`P]$QDX%!0V'A@8#`P]'A@8$QDX'A@8$QDXF8"0>GZ=%QAE'A@8#`P] +M%!0V*S`^$QDX$QDX*S`^*S`^$QDX*S`^0UIC96^<*47&05BDF=#5U=3>S\O1 +MF=#5N7YBLUD\HC\GN7YBSVQ$N7YBSVQ$N7YBLUD\HC\GHC\G*S`^%!0V'A@8 +M5B@>(C&<559;LUD\LUD\HC\GSVQ$LUD\HC\G559;*S`^%!0V0UIC*S`^+3AG +M04F-*S`^"0ED%QAE%QAE#`P]*S`^"0F5&25@"0F5+3AG'".<%QAE%QAE$QDX +M#`P]%!0V$QDX+3AG*S`^%!0V$QDX%!0V*S`^#`P]*S`^#`P]*S`^#`P]$QDX +M#`P]*S`^#`P]$QDX"0ED*S`^"0ED*S`^$QDX%!0V$QDX%!0V$QDX#`P]'A@8 +M#`P]%!0V*S`^$QDX#`P]$QDX'A@8$QDX*S`^$QDX'A@8$QDX*S`^#`P]%!0V +M*S`^>GZ=L)BHEYB;N7YB>GZ=559;$QDX*S`^>GZ=EYB;F:?,EYB;F=#5EYB; +MEYB;P+*UEYB;96^<04F-96^<96^SVQ$SVQ$SVQ$HC\GSVQ$HC\G +MLUD\HC\G'A@8'A@8'A@8+3AG(C&<559;LUD\HC\GHC\GHC\GHC\G559;+3AG +M$QDX*S`^96^<*S`^*S`^96^<*S`^#`P]$QDX*S`^#`P]%!0V"0ED%!68%QAE +M&25@%!68'".<'".<"0ED$QDX%!0V*S`^559;*S`^"0ED#`P]%!0V$QDX#`P] +M*S`^#`P]$QDX#`P]'A@8%!0V$QDX%!0V%!0V+3AG&25@%QAE$QDX#`P]*S`^ +M*S`^#`P]'A@8#`P]#`P]%!0V$QDX%!0V#`P]%!0V%!0V#`P]#`P]"0ED$QDX +M%!0V$QDX%!0V#`P]$QDX0UICEYB;F:?,EYB;EYB;EYB;96=I*S`^559;EYB; +MEYB;J:VOEYB;EYB;EYB;EYB;96^<>GZ=96^<05BD(C&*S`^'A@8@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``5B@>F:?,L)BHEYB;EYB;L)BHEYB;N7YB>GZ= +M?V]^96=I+3AG559;*S`^*S`^$QDX#`P]%!0V%!0V*S`^%!68(C&<66^\05BD +M96^<*47&(C&<"0F5(C&<'2C3"0F5"0F5'2C3%!68(C&<'2C3*47&'2C3'2C3 +M"0F5'2C3"0ED&25@"0ED#`P]%QAE#`P]'".<%!68&25@#`P]$QDX'A@8#@\0 +M'A@8*S`^F:?,EYB;%!0V'A@8*S`^559;$QDX````*S`^96^GZ=+3AG +M````'A@8#`P]-3]`96^<-3]`$QDX+3AG$QDX'A@8-3]`>GZ=N7YB'A@8```` +M#@\0*S`^EYB;66^\(C&<"0F5(C&<2%S(2%S(F:?,N7YBN7YBSVQ$HC\GSVQ$ +M?V]^HC\GLUD\HC\GN7YBHC\G5B@>*S`^*S`^559;04F-HC\GHC\GHC\GHC\G +MLUD\SVQ$559;*S`^+3AG5B@>*S`^#`P]$QDX"0ED&25@*S`^ +M+3AG+3AG%!0V#`P]$QDX"0ED$QDX$QDX%!0V$QDX*S`^$QDX#`P]*S`^$QDX +M$QDX*S`^%!0V*S`^+3AG$QDX#`P]*S`^%!0V%QAE559;N7YBEYB;EYB;EYB; +MN7YBEYB;EYB;EYB;EYB;F:?,EYB;EYB;>GZ=96^<96^<04F-96^<96^'A@8*S`^>GZ=+3AG%QAE +MGZ=05BD'".<"0G+%!68"0GS"0GS'2C32%S( +MN7YBN7YBSVQ$LUD\5B@>5B@>HC\G?V]^SVQ$LUD\5B@>%!0V*S`^05BD05BD +M5B@>*S`^%!0V5B@>5B@>559;?V]^+3AG%QAE+3AGEYB;P+7"-3]`'A@8%!0V +M0UICF:?,EYB;5B@>96=I96^<*S`^"0ED&25@+3AG(C&<+3AG%!68&25@+3AG +M+3AG96=I?V]^0UICGZ=EYB;EYB;EYB;EYB;F8"0EYB;EYB;EYB;EYB;>GZ=96^<04F-(C&<(C&< +M96^LUD\LUD\HC\GHC\G +M*S`^$QDX+3AG(C&<(C&<*S`^````````#`P]5B@>5B@>N7YB(C&<(C&<>GZ= +MP+7"EYB;*S`^*S`^+3AG'A@8EYB;EYB;96=I>GZ=96=I*S`^"0ED%QAE+3AG +M'".<+3AG+3AG'".<%!680UIC96=I96=I96^<96^<96=I+3AG%!0V#`P]+3AG +M96=I#`P]%!0V +M$QDX$QDX#`P]*S`^+3AG96=I*S`^%!0V$QDX$QDX#`P]%!0V*S`^559;?V]^ +M96=I559;+3AG%!0V+3AGN7YBEYB;EYB;EYB;EYB;EYB;EYB;EYB;EYB;F8"0 +M96^<05BD'".<+3AG04F-66^\F=#5S\O1P+7"F=#5P+7"S\O1P+*UF:?,S\O1 +MF=#5P+7"S\O1P+7"S\O1F=#5P+*UP+7"S\O1S\O1S\O1S\O1U\O-U=3>U\O- +MX^KKS\O196=I5B@>0UIC559;559;*S`^@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``$QDX*S`^+3AG*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``*S`^EYB;EYB;>GZ=96^<96=I0UIC*S`^+3AG +M*S`^+3AG+3AG*S`^*S`^+3AG*S`^0UIC-3]`+3AG-3]`&25@+3AG96^GZ=559;$QDX*S`^2%S( +M2%S("0G+"0GS"0G+"0GS"0F5+3AG"0ED#`P]````$QDX'A@8#@\0'A@8#@\0 +M*S`^EYB;*S`^@(``@(``@(``*S`^EYB;96^<05BDEYB;*S`^'A@8*S`^96^< +M?Y?/559;J:VOEYB;$QDX@(``#@\0*S`^F8"0>GZ=*S`^````````+3AGEYB; +M>GZ=(C&<'".<"0G+"0GS"0GS"0GS"0GS"0GS2%S(N7YBN7YBSVQ$SVQ$SVQ$ +M?V]^5B@>%!0V*S`^'A@8+3AG(C&<+3AG&25@'A@8%!0V'A@8#`P]'A@8HC\G +MN7YBP+7"J:VOL)BHP+7"96=I*S`^+3AGL)BHEYB;*S`^$QDX559;>GZ=5B@> +M$QDX&25@"0ED&25@+3AG%QAE&25@+3AG%!68+3AG+3AG0UIC?V]^96=I96=I +MGZ=F8"0>GZ=?V]^96=I96=IF8"0EYB;EYB;N7YB>GZ= +MEYB;96^<96^<96^<05BD559;(C&<96^*S`^ +M*S`^'A@8$QDX*S`^'A@8$QDX'A@8#`P]@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``$QDX'A@8*S`^F8"0F=#5EYB;%!0V@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``%!0V559;F=#5U=3> +MS\O1F:?,?Y?/96=I0UIC05BD0UIC0UIC0UIC+3AG-3]`0UIC*S`^5B@>0UIC +M+3AG-3]`+3AG+3AG2%S(05BD2%S(05BD'".<(C&<"0F5+3AG(C&P+*U96=I*S`^$QDX@(``@(``@(``*S`^*S`^ +M'A@8````*S`^F8"096^<(C&<(C&<#Q/-"0G+"0G+"0GS"0G+"0GS"0F5*47& +MN7YBSVQ$SVQ$N7YBSVQ$SVQ$*S`^*S`^$QDX$QDX%QAE*S`^*S`^'A@8'A@8 +M````````'A@8*S`^N7YBP+*UP+*UP+7"S\O1S\O1S\O1?HF\>GZ=F:?,F:?, +M%!0V````'A@8%!0V````%!0V0UIC%!68"0F5+3AG'".<%!68"0F5&25@&25@ +M%QAE96=IGZ=N7YBEYB;N7YBF8"0N7YB +MEYB;EYB;EYB;F8"096^<559;(C&<'".<(C&<96^<>GZ=?HF\J:VOF=#5L)BH +MP+*UF=#5P+7"P+*UP+7"P+*UF=#5P+*UP+7"F=#5P+7"P+*UP+7"S\O1P+7" +MF=#5P+7"S\O1S\O1P+7"S\O1P+7"S\O1P+7"S\O1S\O1U=3>S\O1U=3>S\O1 +MSMK=X.#GS\O1P+*UP+7"P+7"P+7"P+7"S\O1S\O1S\O1EYB;$QDX@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``*S`^EYB;04F-(C&<05BDF:?,EYB; +M%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``%!0VEYB;P+*UF=#5F=#5S\O1?Y?/EYB;>GZ=96^<96^<*S`^+3AG*S`^*S`^$QDX+3AGF:?,S\O1P+7"EYB;P+7"S\O1 +MF=#5P+7"EYB;F8"0>GZ='A@8````````````````$QDX+3AG+3AG&25@%QAE +M%QAE+3AG+3AG%!68%QAE+3AG96=I96^<96=I96=IGZ=96=IN7YB96=I04F-&25@&25@-3]`96=I96^GZ=F8"0N7YBF8"00UIC&25@*S`^0UIC>GZ=EYB;>GZ= +MF8"0EYB;>GZ=EYB;EYB;EYB;N7YB>GZ=96=I0UIC'".<+3AG(C&<04F-?HF\ +MJ:VOP+7"S\O1P+7"F=#5P+7"P+7"P+*UF=#5P+7"P+7"L)BHP+7"F=#5P+7" +MP+*UF=#5P+7"P+*UP+7"S\O1S\O1S\O1S\O1S\O1S\O1S\O1S\O1S\O1S\O1 +MS\O1S\O1S\O1S\O1S\O1U\O-S\O1S\O1U=3>SMK=XO+TX^KKXO+TX^KKXO+T +MX.#GS\O196=I559;*S`^559;-3]`+3AG559;-3]`+3AG*S`^*S`^+3AGEYB; +M66^\96^<2%S(66^\F:?,S\O1F=#5F:?, +MF:?,F:?,F:?,EYB;>GZ=96^<96=I96=I96=I96=I05BD559;96=I?Y?/F=#5 +MEYB;>GZ=>GZ=66^\F8"0EYB;F:?,EYB;0UIC*S`^@(``@(``@(``@(``%!0V +M0UICEYB;2%S(#Q/-"0GS"0GS'2C3&25@*S`^*S`^$QDX%!0V#@\0%!0VF8"0 +M96=I%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#@\0$QDX +M*S`^%!0V@(``@(``@(``@(``@(``@(``@(``#`P]*S`^>GZ=EYB;05BD"0F5 +M"0G+#Q/-"0GS"0GS#Q/-'2C3"0GS(C&<(C&S\O1SMK=P+7"?V]^96=IF8"0P+*U?Y?/F8"0EYB;F:?, +MF=#5EYB;>GZ=96^<66^\EYB;L)BHF=#55B@>$QDX```````````````````` +M%!0V96^<+3AG&25@"0ED'".<'".<'".<"0ED'".<%QAE0UIC?V]^96=I96=I +MF8"096=IF8"0GZ=>GZ=N7YB96=I +M+3AG96=IN7YBF8"0F8"0N7YB>GZ=F8"0>GZ=96^<96^<05BD559;(C&<(C&< +M(C&<*47&F8"0EYB;F:?,L)BHF=#5P+7"L)BHJ:VOL)BHP+*UF:?,P+7"P+*U +MF=#5F=#5L)BHS\O1P+*UP+7"P+7"S\O1F=#5S\O1S\O1S\O1P+7"S\O1S\O1 +MS\O1S\O1S\O1P+*US\O1S\O1S\O1U=3>S\O1S\O1U=3>S\O1SMK=X.#GSMK= +MS\O1X.#GS\O1X.#GSMK=U\O-S\O1S\O1S\O1S\O1SMK=U=3>U\O-U=3>F=#5 +MP+*UF:?,96^<(C&<05BD2%S(66^\?Y?/0UIC%!0V@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``5B@>*S`^5B@>-3]`*S`^96=IP+7"X.#GS\O1F=#5F=#5F:?,F:?,F:?, +MJ:VO0UIC*S`^5B@>*S`^*S`^&25@*S`^*S`^$QDX*S`^-3]`5B@>#@\0@(`` +M@(``@(``@(``@(``@(``@(``+3AGF:?,F:?,*47&"0G+(C&<(C&GZ= +M+3AG$QDX````$QDXEYB;F=#5*S`^@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^ +MEYB;96^<(C&<"0F5"0GS"0GS"0G+"0GS"0GS"0GS"0G+(C&<96^<5B@>5B@> +MSVQ$5B@>5B@>'A@8%!0V,4)FF:?,XO+TX.#GX.#GS\O1P+*UEYB;EYB;F:?, +MU=3>SMK=F=#5EYB;F8"096^<04F-?Y?/F:?,L)BHF=#5P+7"S\O15B@>```` +M````````````````````*S`^96^<%QAE%QAE%!68+3AG+3AG+3AG%!68+3AG +M&25@559;96=I96=I>GZ=96=IGZ=N7YBF8"0N7YBF8"0>GZ= +MF8"0N7YBF8"0F8"096=IF8"0>GZ=N7YB>GZ=EYB;>GZ=F8"096=I(C&<+3AG +M+3AG'".<(C&<96^<96^S\O1S\O1U=3>S\O1SMK=U=3>S\O1X.#GSMK=U=3>XO+TS\O1 +MX.#GXO+TX^KKU\O-J:VO66^\04F-'".<05BD?HF\05BD*S`^*S`^'A@8@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``%!0VEYB;F=#5F=#5 +MF:?,>GZ=EYB;EYB;EYB;L)BH*S`^@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#`P]EYB;?Y?/(C&< +M*47&*47&66^\F=#5F:?,559;````%!0V0UICEYB;EYB;%!0V@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``*S`^$QDX"0ED+3AG04F-F:?,X.#GSMK=F=#5 +MJ:VOL)BH?V]^?V]^N7YBS\O1U\O-U=3>>GZ=?V]^96^<96^GZ=N7YBF8"0EYB;N7YB>GZ=F8"0?V]^ +M96^<96=I(C&<&25@"0F5%!68(C&<559;>GZ=F:?,L)BHL)BHF:?,P+7"L)BH +MF=#5J:VOP+7"EYB;L)BHP+*UP+7"L)BHP+7"F=#5P+*US\O1P+*UF=#5P+7" +MS\O1P+7"P+*UP+7"S\O1S\O1S\O1S\O1S\O1S\O1S\O1P+7"S\O1S\O1S\O1 +MS\O1S\O1S\O1S\O1X.#GS\O1S\O1U\O-S\O1U\O-S\O1U\O-U\O-S\O1X^KK +MU=3>SMK=U\O-X.#GSMK=X^KKU=3>S\O1F:?,96^<05BD(C&<(C&<66^\>GZ= +M*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``$QDX*S`^'A@8%!0V'A@8$QDX'A@8*S`^$QDX@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``%!0V$QDX%QAEEYB;F=#5F=#5S\O1F=#5+3AG*S`^-3]`F8"0559; +M$QDX#`P]@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``0UICF8"0?Y?/04F-(C&<%!68'2C3"0GS +M"0GS"0GS"0GS'2C32%S(96^GZ=EYB;>GZ=5B@>5B@>+#-K+3AG96^< +M?V]^N7YBP+7"F=#596=I559;+3AG5B@>*S`^-3]`F8"0F=#5EYB;96^GZ=?V]^96=I>GZ=N7YB96^<>GZ=F8"0>GZ=?V]^N7YBF8"0GZ=96^<96=I05BD96=I04F-+3AG%!68'".<(C&<05BDF8"0EYB;L)BHEYB; +MF=#5EYB;P+*UP+7"F=#5L)BHL)BHF:?,P+*UF:?,P+*UP+7"F=#5P+*UP+7" +ML)BHF=#5P+7"P+*UP+*UP+7"F=#5P+*UP+7"F=#5S\O1P+7"S\O1S\O1S\O1 +MS\O1S\O1S\O1S\O1U=3>S\O1P+7"S\O1S\O1SMK=S\O1U=3>S\O1U=3>SMK= +MU=3>S\O1XO+TU=3>S\O1SMK=U\O-S\O1XO+TU=3>S\O1P+7">GZ=05BD*47& +M05BD2%S(F:?,?Y?/*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@8*S`^F8"0S\O1F=#5F:?, +M-3]`F8"0EYB;559;$QDX@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^EYB;96^<(C&< +M%!68'2C3"0GS"0GS"0G+"0GS'2C3'2C3(C&```` +M````````*S`^EYB;S\O1S\O1F:?,(C&<&25@%QAE+3AG&25@%!68%QAE'".< +M%QAE96=I96=I96=I?V]^GZ=F8"0>GZ=96^<04F-559;05BD+3AG'".<%!68+3AG'".<0UIC96^U\O-S\O1S\O1S\O1U\O-SMK=U\O-S\O1X^KKX.#GXO+TX.#GU\O-P+7" +MGZ=F8"0>GZ='A@8@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M*S`^96=IF:?,(C&<"0F5"0F5"0GS"0G+"0GS"0GS"0G+#Q/-(C&<0UICF8"0 +M0UIC%!68+3AGEYB;F8"0?V]^96=I04F-SVQ$SVQ$N7YBSMK=X^KKS\O1?V]^ +M+3AG*S`^+3AG>GZ=F:?,S\O1>GZ=>GZ=L)BHEYB;L)BHP+*UL)BHF:?,L)BH +MP+7"P+*UP+7"96=I*S`^*S`^+3AG559;F=#5X.#GXO+TS\O105BD"0ED&25@ +M%!68'".<+3AG'".<+3AG+3AG0UIC96=I96=I96=I96=IGZ=GZ=96=IN7YB96^< +MSMK=S\O1S\O1F:?,>GZ=96=I05BD(C&<*47&EYB;EYB;$QDX@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``#`P]5B@>J:VOU=3>EYB;5B@>%!0V@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``'A@8+3AGEYB;F:?,(C&<'2C3#Q/-"0G+"0GS"0GS"0GS"0G+ +M(C&<(C&<96=I05BD(C&<(C&<'".<05BD2%S(2&V"04F-?V]^N7YBSVQ$SVQ$ +MN7YBU\O-XO+TU=3>F=#5*S`^$QDX96=IS\O1X^KKF=#5P+*UEYB;L)BHF:?, +MP+7"F:?,P+7"EYB;P+*UF=#5F=#5P+*UL)BHF=#5P+*UEYB;?Y?/96^GZ=96=I?V]^96^<96=IF8"0?V]^96^<559;96=I0UIC(C&<'".< +M'".<(C&<"0F5(C&<05BD96^S\O1U\O-U=3> +MS\O1X.#GS\O1S\O1S\O1P+7"?HF\96^<04F-05BD96^<66^\96^<$QDX%!0V +M%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^+3AG +M*S`^$QDX@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``*S`^F8"096^<(C&<%!68'2C3"0GS +M"0GS"0GS'2C3#Q/-(C&<(C&<&25@%!68"0G+(C&<(C&<96^<66^\?Y?/F8"0 +MSVQ$N7YBSVQ$N7YB5B@>LUD\XO+T]OW^X^KKF=#5+3AG*S`^>GZ=XO+TX.#G +MU=3>P+7"L)BHF:?,L)BHEYB;EYB;L)BHL)BHF:?,L)BHP+7"P+7"F=#5EYB; +M96^GZ=96=I96^GZ=04F->GZ=96^<$QDX````'A@85B@>%QAE'".<+3AG +M+3AG559;+3AG(C&<%QAE+3AG559;96=I96=I96=I0UIC+3AG%!68&25@&25@ +M+3AG559;96=I96=I?V]^96=I96=I96=I96^<96=I>GZ=N7YBS\O1S\O1S\O1S\O1EYB;96^<(C&< +M'".<(C&<2%S(2%S(96^U\O-P+*UN7YBN7YBN7YBP+7" +MS\O1]OW^]OW^SMK=S\O196^<9EYB;F:?, +ML)BHJ:VOEYB;EYB;EYB;EYB;EYB;96^<(C&<96^EYB;+3AG"0ED%!6805BD0UIC+3AG&25@%QAE+3AG0UIC?V]^05BD+3AG +M+3AG'".<"0F5+3AG%!68-3]`0UIC96=IGZ=F8"0EYB;EYB;EYB;EYB;EYB;EYB;EYB;L)BHL)BHJ:VOL)BHF:?,EYB; +MP+7"EYB;L)BHEYB;EYB;P+*UP+7"F=#5EYB;F=#5F:?,P+7"P+*UP+7"P+*U +MP+7"P+7"F=#5L)BHP+7"P+7"F=#5S\O1S\O1S\O1P+7"S\O1S\O1S\O1P+7" +MP+7"S\O1S\O1S\O1S\O1S\O1S\O1S\O1S\O1S\O1U\O-S\O1S\O1S\O1F=#5 +MF:?,04F-(C&<'".<(C&<*47&>GZ=?Y?/*S`^*S`^$QDX@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``*S`^>GZ=96^<(C&<'2C3"0GS#Q/-"0GS"0GS"0GS +M'2C3%!68'".<"0F5%!68"0F5+3AG%!0V*S`^(C&<66^\F:?,S\O1XO+TS\O1 +M?V]^SVQ$SVQ$S\O1]OW^]OW^]OW^]OW^XO+TU=3>F=#5S\O1U=3>J:VOF:?, +MEYB;EYB;F:?,P+*UF:?,L)BHF:?,L)BHF:?,N7YB0UIC+3AG5B@>>GZ=L)BH +MF=#5559;````'A@8>GZ=EYB;N7YB+3AG"0ED+3AGF:?,EYB;(C&<'".<+3AG +M&25@96=I96=I0UIC+3AG+3AG+3AG%!68+3AG&25@96=I96=I96=I96^<96=I +MGZ=EYB;N7YBEYB;EYB;F8"0EYB;F:?,EYB;F8"0EYB;EYB; +MEYB;P+7"EYB;L)BHJ:VOEYB;F=#5EYB;P+7"F=#5P+7"J:VOL)BHP+7"P+*U +MP+7"J:VOF:?,F:?,P+*UF:?,P+*UF:?,P+*US\O1P+*US\O1P+7"P+7"S\O1 +MP+*UF=#5P+7"P+7"P+*US\O1S\O1P+7"S\O1S\O1S\O1U=3>S\O1S\O1S\O1 +MS\O1U=3>S\O1F8"096=I(C&<(C&<'2C32%S(F:?,+3AG*S`^*S`^'A@8@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@8 +M+3AG*S`^@(``@(``@(``@(``@(``@(``@(``*S`^96=IF:?,(C&<"0F5%!68 +M"0GS"0G+"0GS"0GS"0G+"0G+&25@%!68'".<"0F5'".<*S`^&25@+3AG2%S( +M>GZ=F=#5X^KK]OW^S\O196=ISVQ$N7YBP+*UX.#GXO+T]OW^]OW^]OW^X^KK +MX.#GSMK=U=3>P+7"EYB;F8"0?V]^EYB;HH>9N7YBL)BHF8"0EYB;F8"096=I +M+3AG*S`^5B@>96=IEYB;F=#5559;$QDX*S`^L)BHP+*USVQ$*S`^"0ED&25@ +MS\O1F=#505BD%!68&25@%QAE559;96=I(C&<&25@%!68+3AG+3AG%QAE+3AG +M96=I>GZ=96=I96=I?V]^96^<96=I96=I0UIC+3AG+3AG+3AG%!68&25@(C&< +M+3AG'".<'".<%!68'2C396=I96^EYB; +M?HF\05BD%!68'2C3"0GS"0GS"0GS'2C3%!68"0F5'".<%QAE"0ED&25@*S`^ +M+3AG(C&<66^\?Y?/F:?,F:?,F:?,U\O-XO+T]OW^U\O-N7YBSVQ$96=IF=#5 +MX^KKU\O-XO+T]OW^S\O1XO+TX.#GS\O1EYB;>GZ=5B@>*S`^5B@>HC\GLUD\ +M96=I559;*S`^5B@>559;*S`^$QDX%!0V-3]`559;96=I96^%QAE&25@P+7"SMK=66^\+3AG"0F5&25@+3AG+3AG%QAE+3AG +M+3AG+3AG&25@*S`^559;96=I96=IGZ=F8"0EYB;F:?, +ML)BHEYB;EYB;F:?,EYB;EYB;EYB;EYB;EYB;EYB;EYB;L)BHL)BHP+*UEYB; +MF:?,P+*UL)BHEYB;F:?,F:?,F:?,P+7"P+*UF:?,F=#5P+*UF=#5L)BHP+7" +MJ:VOF=#5P+7"F=#5P+7"P+*US\O1F=#5P+7"S\O1P+7"S\O1P+7"S\O1S\O1 +MP+7"U\O-S\O1S\O1P+7"S\O1S\O1P+*UF=#5P+*U96^<05BD'".<(C&<#Q/- +M66^\>GZ=+3AG#`P]'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@8EYB;U=3>EYB;*S`^@(`` +M@(``@(``*S`^EYB;96^<05BD%!68"0G+#Q/-"0GS"0GS"0G+%!68'2C3"0G+ +M%QAE*S`^$QDX*S`^0UIC*47&?Y?/S\O1XO+TU=3>J:VOEYB;F=#5X^KKX.#G +MS\O1EYB;>GZ=EYB;?V]^SVQ$N7YBU\O-U=3>N7YBSMK=U\O-*S`^5B@>5B@>5B@>5B@>'A@8#`P]#@\0%!0V$QDX$QDX5B@>*S`^*S`^ +MLUD\LUD\HC\GLUD\N7YBN7YBN7YB+3AG&25@+3AGS\O1X.#G66^\%!68"0ED +M%QAE%QAE'".<'".<%!68'".<%QAE+3AG559;96=IGZ=F8"0EYB; +MF8"0EYB;EYB;EYB;EYB;EYB;P+7"EYB;L)BHEYB;F:?,EYB;EYB;EYB;EYB; +MF:?,EYB;F:?,F=#5L)BHEYB;EYB;F:?,EYB;P+7"P+*UP+*UL)BHP+*UP+7" +MP+*UP+7"F:?,P+*UJ:VOP+7"L)BHP+*UF:?,EYB;P+7"F=#5P+7"P+7"P+*U +MF=#5S\O1F=#5S\O1S\O1S\O1S\O1U=3>S\O1S\O1P+*UEYB;?HF\(C&<(C&< +M(C&<%!68(C&S\O1S\O1 +ML)BHEYB;L)BHS\O1S\O1P+7"96^5B@>HC\G5B@>5B@>5B@>5B@>'A@8%!0V'A@8%!0V +M'A@85B@>96=I559;HC\GLUD\HC\GLUD\HC\GSVQ$N7YBN7YB559;'".<04F- +MF=#5U=3>F:?,+3AG%!68&25@%!68&25@%!68+3AG+3AG"0ED-3]`96=I05BD +M559;96=I+3AG&25@&25@(C&<(C&<0UIC%!68"0F5(C&<"0F5%!68'".<05BD +MF8"0N7YBEYB;F8"0EYB;N7YBEYB;EYB;F8"0EYB;EYB;EYB;EYB;F8"0EYB; +MEYB;EYB;EYB;L)BHEYB;EYB;L)BHEYB;P+7"EYB;EYB;F:?,L)BHEYB;P+*U +MP+7"F:?,P+7"F:?,EYB;L)BHP+7"L)BHP+7"F:?,P+*UP+7"F=#5P+7"P+*U +MP+7"P+*UP+*US\O1S\O1P+7"P+*UP+7"S\O1P+7"S\O1S\O1S\O1P+7"F:?, +MF:?,>GZ=(C&<+3AG&25@*47&2%S(2%S(?Y?/P+7"EYB;'A@8@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``'A@8F=#5]OW^U=3>559;*S`^*S`^>GZ=F:?,04F-'2C3 +M"0G+'2C3"0GS"0GS"0GS"0G+'2C3%!68"0ED#`P]+3AG96=I96^<(C&<*47& +M2%S(96^GZ=P+7" +MU=3>P+*UN7YB?V]^SVQ$SVQ$SVQ$SVQ$LUD\HC\GLUD\LUD\HC\GSVQ$HC\G +MSVQ$HC\GLUD\?V]^HC\GHC\GHC\GHC\GSVQ$N7YBSVQ$N7YBSVQ$?V]^?V]^ +MEYB;EYB;05BD+3AG96^GZ=EYB;L)BHEYB;F8"0F8"0L)BHEYB;F8"0 +MF:?,F8"0EYB;N7YBEYB;L)BHF:?,EYB;EYB;P+7"EYB;F:?,EYB;EYB;F:?, +MEYB;F:?,P+*UEYB;F:?,L)BHEYB;P+*UL)BHF=#5L)BHF=#5J:VOP+7"P+*U +MF:?,P+*UF:?,L)BHF=#5P+7"F=#5P+7"P+7"P+*UP+7"F=#5S\O1L)BHF=#5 +MP+7"F=#5EYB;>GZ=+3AG(C&<%!68(C&<*47&*47&96^9EYB;EYB;EYB;EYB;P+7"EYB;EYB; +ML)BHF:?,96^<96=IS\O1]OW^S\O1LUD\HC\GSVQ$HC\GHC\G5B@>HC\GSVQ$ +MHC\G?V]^F8"0P+*US\O1U\O-U\O-S\O1U\O-N7YBSVQ$SVQ$SVQ$SVQ$N7YB +MSVQ$U\O-J:VO5B@>'A@85B@>*S`^04F-05BD66^\U=3>X^KKQ,32+3AG&25@ +M%!68&25@+3AG(C&<&25@%QAE&25@&25@(C&<&25@%!68+3AG%!68'".<%!68 +M'".<(C&<%!68%QAE0UIC04F-96^GZ=EYB; +ML)BHEYB;F8"0EYB;EYB;L)BHEYB;>GZ=F8"0EYB;EYB;EYB;EYB;EYB;EYB; +MEYB;L)BHEYB;EYB;L)BHEYB;L)BHEYB;P+7"EYB;L)BHF:?,P+7"L)BHP+7" +ML)BHP+7"L)BHP+7"P+*UP+7"P+7"EYB;F=#5L)BHS\O1P+*UP+*US\O1S\O1 +MF=#5P+7"S\O1F=#5EYB;N7YB04F-+3AG%!68"0F5"0G+'2C3?Y?/Q,32F:?, +M0UIC+3AG*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@8 +MEYB;S\O1SMK=X.#GU=3>P+7"(C&<"0F5"0G+"0GS"0GS"0GS"0G+#Q/-"0G+ +M&25@+3AG#`P]#`P]#`P](C&<05BD05BD96^9 +ML)BHEYB;EYB;L)BHEYB;L)BHJ:VOF8"00UICEYB;F=#5EYB;5B@>559;SVQ$ +M5B@>'A@8*S`^LUD\?V]^?V]^96=IEYB;F:?,P+7"F=#5S\O1P+7"F=#5?V]^ +MN7YBSVQ$N7YBN7YBSVQ$SVQ$L)BHN7YB$QDX@(``@(``@(``(C&<2%S(96^< +MS\O1]OW^S\O196=I"0ED+3AG+3AG%!68+3AG"0ED"0ED+3AG%!68+3AG(C&< +M+3AG'".<%!68'".<"0F5"0F5+3AG'".<+3AG05BDF8"0>GZ=F8"096^GZ=N7YBEYB;F8"0F8"0F8"0EYB;EYB;EYB;EYB;EYB;F8"0EYB;EYB;EYB; +MF8"0EYB;EYB;EYB;EYB;EYB;EYB;EYB;L)BHF:?,P+*UEYB;L)BHL)BHF=#5 +ML)BHF:?,P+*UF=#5P+7"J:VOF:?,P+7"P+*UF:?,P+7"J:VOP+7"P+7"S\O1 +MP+7"P+7"P+7"F=#5P+7"P+*UP+*UF:?,EYB;96^<+3AG'".<"0ED"0F5'2C3 +M2%S(2%S(66^\F=#5N7YB$QDX@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``%!0V96=IS\O1S\O1?Y?/(C&<'".<"0G+'2C3"0G+ +M"0G+#Q/-'".<"0F5%!6805BD+3AG*S`^&25@+3AG>GZ=?HF\F8"0EYB;L)BH +MEYB;F8"0EYB;N7YBEYB;EYB;F8"0EYB;EYB;F:?,L)BHF=#5EYB;96=I0UIC +M0UIC559;0UIC96=I96=I0UIC+3AG+3AG96^X^KKU=3>2%S(&25@%!68"0F5&25@+3AG%!68 +M&25@'".<0UIC+3AG(C&<&25@%!68"0G+'".<%!68'".<(C&<96=I96^GZ=?V]^EYB;F8"0F8"0N7YB +MHH>9EYB;EYB;EYB;EYB;EYB;EYB;F:?,EYB;EYB;F:?,L)BHF:?,L)BHL)BH +MEYB;F:?,P+*UF:?,F:?,L)BHP+*UP+7"L)BHL)BHP+7"J:VOP+7"F=#5L)BH +MP+*UF:?,P+*UP+7"S\O1F=#5F=#5P+*UF:?,L)BHF:?,>GZ=96^<+3AG%!68 +M(C&<#Q/-*47&96^GZ=EYB;EYB;F8"0EYB;EYB;EYB;HH>9F8"0EYB;L)BHEYB;EYB;EYB;F8"0 +MEYB;P+*UF=#5S\O1F:?,GZ=U=3>]OW^S\O1F:?,05BD +M+3AG"0F5+3AG%!68'".<%QAE+3AG(C&<'".<+3AG"0F5'".<"0F5(C&<(C&< +M96=IF8"096=IF8"0F8"0>GZ=F8"0F8"0F8"0EYB;F8"0EYB;F8"0EYB;EYB; +MF8"0>GZ=?V]^EYB;F8"0EYB;EYB;EYB;HH>9EYB;>GZ=EYB;EYB;EYB;EYB; +MEYB;EYB;L)BHF:?,P+7"L)BHL)BHF:?,L)BHP+*UP+7"F:?,L)BHF:?,F:?, +MP+*UF:?,L)BHF=#5P+7"P+7"J:VOP+7"S\O1S\O1P+*UP+7"EYB;05BD96=I +M0UIC05BD96=I"0F5"0G+(C&9EYB;EYB;EYB;EYB; +MEYB;EYB;EYB;EYB;F8"0EYB;F:?,S\O1XO+TS\O1F=#596=I0UIC+3AG+3AG +M(C&<96^GZ= +MU=3>]OW^XO+TF:?,66^\+3AG%!68+3AG%!68'".<%!68'".<(C&<+3AG'".< +M"0F5%!68(C&<05BD96=IGZ=N7YBF8"0EYB; +MF8"0N7YBEYB;F8"0N7YBF8"0N7YBEYB;EYB;EYB;EYB;F8"0EYB;F:?,EYB; +MEYB;EYB;EYB;F:?,EYB;L)BHEYB;EYB;L)BHEYB;L)BHF=#5L)BHF=#5P+7" +MEYB;EYB;L)BHF=#5L)BHF=#5P+7"P+*UL)BHF:?,P+*UEYB;L)BHF=#5EYB; +MF:?,EYB;96^<+3AG'".<%!68+3AG(C&<*47&66^\2%S(F:?,F=#5>GZ='A@8 +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``*S`^96^<*47&#Q/-"0GS#Q/-"0GS"0G+"0F5 +M"0G++3AG04F-96=I05BD96^9EYB;HH>9EYB;L)BH +MEYB;L)BHEYB;F8"0EYB;F8"0EYB;F8"0N7YB>GZ=F:?,J:VOF:?,U=3>S\O1 +MF:?,>GZ=EYB;F=#5F:?,-3]`#`P]$QDX@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``'A@80UIC04F-?HF\S\O1X.#GSMK=S\O1EYB;(C&<+3AG'".<"0F5+3AG +M"0F5%!68'".<"0F5'".<+3AG(C&GZ=N7YBF8"096^< +MN7YB96^GZ=F8"0EYB;F8"0N7YBF8"0>GZ= +MF8"0EYB;L)BHEYB;F8"0EYB;EYB;L)BHL)BHEYB;EYB;F:?,EYB;EYB;F:?, +MEYB;EYB;F:?,L)BHJ:VOP+7"P+*UP+7"F:?,L)BHP+7"EYB;P+7"F:?,L)BH +MP+7"EYB;F8"096=I96=I(C&<+3AG%!68(C&<'".<'2C305BD*47&?Y?/F:?, +MEYB;+3AG*S`^'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``+3AGEYB;2%S(*47& +M"0G+"0G+%!68"0F5+3AG04F-96^<05BD(C&<04F-EYB;F:?,L)BHL)BHEYB; +MEYB;F8"0EYB;EYB;EYB;EYB;EYB;L)BHL)BHEYB;L)BHEYB;96^<(C&<96=I +M96^GZ=U=3>]OW^U=3>-3]`@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``#`P]+3AG(C&<0UIC>GZ=>GZ=>GZ=EYB;?Y?/ +M(C&<+3AG%!68%!68"0F5'".<"0ED+3AG+3AG559;96=IF8"096^GZ= +M?V]^?V]^F8"0?V]^F8"0EYB;F8"0F8"0F:?,F8"0F8"0N7YBF8"0L)BHEYB; +MEYB;EYB;EYB;EYB;EYB;EYB;EYB;EYB;?HF\L)BHEYB;L)BHF:?,L)BHF:?, +MEYB;EYB;EYB;EYB;L)BHL)BHL)BHEYB;L)BHEYB;P+7"J:VOP+7"P+*UP+7" +MP+*US\O1P+*UF8"0>GZ=96^<0UIC(C&<+3AG'".<#Q/-"0F5"0G+'2C32%S( +MF:?,F=#5P+7"0UIC+3AG*S`^'A@8@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``-3]`F=#52%S('2C3*47&'2C3"0F5+3AG'".<+3AG>GZ=559;0UIC96^< +MEYB;EYB;EYB;EYB;HH>9EYB;F8"0EYB;F8"0N7YBF8"0F8"0EYB;96^EYB;S\O1XO+TS\O1 +M559;@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``&25@+3AG+3AG +M05BD0UIC96=I96^<96^<(C&<"0F5'".<"0F5%!68'".<%!680UIC+3AG0UIC +MF8"0GZ=96^GZ=EYB;EYB;EYB;HH>9EYB;HH>9EYB;?HF\L)BHF8"0F8"0EYB;EYB; +MEYB;EYB;L)BHF:?,P+*UEYB;EYB;L)BHF:?,EYB;F:?,F:?,EYB;EYB;EYB; +MEYB;L)BHF:?,EYB;F=#5EYB;L)BHF8"0?V]^(C&<+3AG%!68&25@"0F5(C&< +M'2C3(C&<*47&*47&2%S(EYB;F=#5EYB;%!0V@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``5B@>F:?,EYB;2%S(#Q/-"0G+#Q/-(C&<%QAE +M+3AG(C&<(C&<)T2E04F-96^GZ=96=I(C&<96=I+3AG%!68+3AG%QAE+3AG(C&<96^ +MS\O1F8"0?Y?/P+7"S\O1+3AG@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``#`P]0UIC96^<2&V"96^<05BD05BD(C&<'".<+3AG%!68+3AG'".<+3AG +M+3AG+3AG559;96=I96=I96=I96=IF8"0F8"0N7YBF8"0F8"096^9EYB;HH>9F:?,L)BHP+7"L)BHEYB;EYB;EYB;EYB;EYB; +MEYB;EYB;L)BHEYB;L)BHP+7"P+7"L)BHL)BHL)BHF:?,L)BHJ:VOL)BHEYB; +MEYB;L)BHEYB;F:?,L)BHEYB;EYB;EYB;96^<96^<96=I04F-+3AG+3AG'".< +M"0F5(C&<"0G+'2C3*47&2%S(66^\?HF\0UIC@(``'A@8*S`^$QDX@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#@\0559;F=#5F=#5 +M2%S('2C3"0G+"0F5(C&<*47&'".<%!68&25@+3AG+3AG+3AG+3AG05BD96=I +M(C&<&25@%QAE+3AG+3AG+3AG%QAE'".<%QAE&25@"0ED'".<8WW`F:?,Q,32 +MS\O1U=3>XO+TX.#G]OW^XO+TF:?,96=I96=IP+7"5B@>@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``$QDXF8"0EYB;05BDEYB;?HF\*47&(C&<"0G+ +M'".<"0F5%QAE%QAE%QAE+3AG0UIC559;96=I96=I?V]^96=I96=I?V]^96=I +MN7YBEYB;EYB;N7YB96^GZ=F8"0EYB;L)BHEYB;F8"0EYB;EYB; +ML)BHF8"0EYB;F8"0F8"0EYB;F8"0F8"0EYB;F8"0EYB;EYB;EYB;F=#5EYB; +MP+7"EYB;P+7"F:?,L)BHP+*UEYB;EYB;EYB;96=I(C&<04F-+3AG+3AG+3AG +M'".<%!68'".<(C&<#Q/-"0G+'2C366^\F=#5F:?,96=I&25@5B@>'A@8@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``$QDXEYB;F:?,?HF\*47&#Q/-'".<05BD(C&<'".<%QAE+3AG"0F5 +M%QAE"0ED"0ED%QAE&25@"0ED&25@"0ED%QAE'".<"0F5+3AG(C&<(C&<(C&< +M96^<2%S(96^XO+T]OW^X.#GS\O196^<96^9F8"0F8"096^GZ=N7YBEYB; +MEYB;EYB;>GZ=F8"0F8"0EYB;F8"0N7YBEYB;EYB;F:?,EYB;L)BHEYB;L)BH +MF:?,L)BHP+7"L)BHEYB;EYB;EYB;L)BHEYB;EYB;EYB;F8"0GZ=?HF\F:?,>GZ=*S`^#`P]$QDX559;F:?,X^KKX^KK]OW^ +M]OW^XO+TF:?,F8"0-3]`'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``'A@8F:?,S\O1F:?,2%S(*47&"0GS"0G+"0GS"0G+#Q/-(C&<'".<%!68 +M+3AG0UIC(C&<+3AG+3AG+3AG(C&<559;96=I96=I96=I96=I96=IGZ=F8"0?V]^F8"0F8"0>GZ=F8"0F8"0EYB;F8"0EYB;EYB;EYB;EYB;HH>9 +MEYB;L)BHEYB;F8"0EYB;F8"0F8"0>GZ=N7YB96^<>GZ=F8"096^<96=I96=I +M0UIC+3AG'".<(C&<%!68'".<%!68(C&<"0G+(C&<#Q/-*47&*47&?Y?/F:?, +M?Y?/*S`^$QDX*S`^%!0V#@\0@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``'A@8EYB;F:?, +M66^\?Y?/?HF\(C&+3AG@(``@(``@(`` +M#@\0*S`^96=IX.#G]OW^]OW^U=3>?V]^*S`^#`P]@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``'A@8*S`^96=IF=#566^\'2C3"0GS"0GS"0GS +M"0G+"0GS"0GS"0G+'".<'".<(C&<+3AG&25@'".<+3AG%QAE&25@559;+3AG +M(C&<+3AG05BD559;96=I?V]^?V]^>GZ=N7YB96^EYB;F=#5EYB;?Y?/>GZ=96^< +M2%S(2%S(66^\05BD96^GZ=EYB;F:?,F=#5EYB;$QDX@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``*S`^J:VOP+*US\O1F=#5-3]`@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^EYB; +M66^\2%S('2C3*47&"0GS"0GS"0GS"0GS*47&#Q/-'2C3'".<%!68+3AG"0F5 +M%!68"0F5+3AG'".<+3AG+3AG559;+3AG+3AG96=I0UIC96^<96=I96^GZ=96^<96=I0UIC+3AG +M+3AG+3AG+3AG%QAE'".<"0ED%!68"0F5'".<05BD559;'".<'2C3(C&<"0GS +M*47&*47&2%S(2%S(66^\EYB;P+7"EYB;'A@8@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``#`P]'A@8+3AG96^GZ=+3AG*S`^#`P]'A@8 +M*S`^%!0V$QDX$QDX#`P]#@\0#`P]$QDX#`P]$QDX*S`^%!0V%!0V*S`^*S`^ +M%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``%!0V*S`^ +M*S`^%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``%!0V$QDX*S`^?Y?/66^\2%S(*47&"0GS"0G+"0G+"0GS +M*47&*47&"0G+"0G+(C&<"0G+(C&<%!68"0F5%!68(C&<+3AG(C&<+3AG%!68 +M+3AG+3AG(C&<+3AG+3AG(C&<+3AG+3AG+3AG%!68&25@+3AG%QAE%!68+3AG +M+3AG559;+3AG(C&<&25@%!68'".<%!68"0F5%!68"0F5'".<(C&<%!68*47& +M05BD*47&#Q/-"0G+2%S(EYB;F=#5?HF\*S`^$QDX*S`^%!0V$QDX@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``#@\096=I>GZ=96^@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``%!0V*S`^*S`^+3AG +MF:?,2%S("0GS"0GS"0GS*47&"0GS"0GS"0GS"0G+"0G+"0G+'".<%!68'".< +M(C&<+3AG'".<%!68'".<'".<+3AG'".<+3AG+3AG+3AG0UIC(C&<'".<%!68 +M&25@%!68"0F5&25@'".<%!68&25@05BD+3AG'".<"0F5%!68"0F5'2C3"0G+ +M"0G+"0GS"0GS"0GS66^\?HF\?Y?/+3AG#`P]&25@*S`^*S`^*S`^'A@8@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#@\0*S`^-3]`+3AG +M>GZ=?HF\66^\P+7"EYB;*S`^@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``*S`^EYB;2%S((C&<66^\'2C3"0GS"0GS'2C3"0G+"0GS +M"0GS"0G+#Q/-"0G+#Q/-"0G+#Q/-'2C3%!68"0F5%!68"0F5'".<%!68'".< +M+3AG(C&<+3AG'".<%!68"0F5"0F5(C&<%!68"0F5"0F5(C&<'".<(C&<'".< +M#Q/-'2C3"0GS*47&#Q/-2%S(66^\*47&05BD2%S(>GZ=>GZ=*S`^@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M'A@8*S`^?HF\F:?,96^<66^\?Y?/F:?,559;$QDX@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``#@\0$QDX%!0V+3AGF:?,F:?, +M66^\*47&"0GS"0GS'2C3"0GS"0GS"0GS"0GS*47&"0GS"0G+#Q/-"0GS'2C3 +M'2C3"0G+"0G+"0G+(C&<*47&'2C3'2C3"0G+'2C3"0GS"0G+"0G+"0GS"0GS +M*47&"0G+#Q/-*47&"0GS#Q/-'".<*47&96^<96^GZ=P+7"F:?,F=#5 +MF:?,F:?,?Y?/?Y?/F:?,?Y?/P+7"F:?,F=#5EYB;"0ED#`P]@(``#`P]*S`^ +M#`P]$QDX*S`^$QDX%!0V@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M$QDXEYB;F:?,96^<2%S(?Y?/F:?,96^<*S`^'A@8@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M#`P]*S`^559;*S`^5B@>+3AG*S`^559;*S`^+3AG-3]`5B@>*S`^5B@>*S`^ +M#@\0@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``#@\00UICL)BHF=#5>GZ=2%S(04F->GZ=5B@>@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``'A@85B@>?Y?/>GZ=66^\>GZ=+3AG +M#`P]'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#@\0>GZ=EYB; +M66^\F:?,?Y?/+3AG@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``'A@8*S`^EYB;F:?,>GZ=F:?,>GZ=%!0V@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``#`P]$QDX%!0V*S`^96^<66^\?HF\?Y?/559;$QDX@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````````````````` +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``5B@>EYB;05BD(C&GZ=66^\?Y?/EYB; +M+3AG@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``#`P]'A@8@(``*S`^EYB;96^< +M05BD66^\F:?,EYB;*S`^'A@8@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``*S`^ +MEYB;0UIC+3AG05BD*47&96^S\O1U\O-F=#566^\?Y?/ +M?Y?/-3]`@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``+3AGP+7"XO+T]OW^ +MX.#G]OW^U=3>F:?,S\O1F:?,%!0V@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``-3]`U\O-]OW^]OW^]OW^]OW^SMK=F:?,P+7"EYB;'A@8@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``*S`^F=#5X^KKX.#G]OW^]OW^XO+TP+7"559; +M$QDX#`P]@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``#`P]96=IU=3>]OW^ +M]OW^]OW^S\O10UIC#@\0@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``%!0VN7YBF=#5P+*UP+7"EYB;'A@8@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``%!0V%!0V*S`^*S`^%!0V@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````____````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YB```` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YB````````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````````````N7YBN7YB +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````N7YB````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YB +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YB````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````````N7YBN7YB +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YB````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````N7YB````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````````````N7YB````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````N7YB````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````N7YBN7YB````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````````` +MN7YBN7YBN7YBN7YB````````````````````````````````````````N7YB +MN7YBN7YBN7YBN7YBN7YBN7YB````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(`````` +M````````N7YBN7YBN7YBN7YB````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``````````````N7YB +MN7YBN7YBN7YB````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````____```` +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````````` +M````N7YBN7YBN7YBN7YBN7YB````````@(``@(``@(``@(``@(``@(``@(`` +M@(``````N7YB````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````@(``@(``@(``@(``@(`` +M@(``````@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YBN7YB +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(`` +M@(``@(``@(``@(``````````N7YBN7YBN7YB````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````N7YBN7YBN7YB````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````````````N7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB +MN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YB +MN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``````@(`` +M@(``@(``@(``````````N7YBN7YBN7YBN7YBN7YBN7YBN7YB```````````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(`````` +M````````N7YBN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````````````N7YBN7YB```````````````````````````````````` +M````````````N7YBN7YBN7YBN7YBN7YBN7YBN7YB````````````````@(`` +M@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````````@(``@(``````N7YBN7YBN7YBN7YB +MN7YB````````@(``@(``@(``@(``@(``````````N7YBN7YBN7YBN7YBN7YB +M````@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``````````N7YB +MN7YBN7YBN7YBN7YBN7YBN7YB````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````@(``@(``````````N7YBN7YBN7YBN7YB```` +M````@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB```````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````````N7YBN7YBN7YB +MN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB +MN7YB````````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````````````@(``@(`` +M@(``@(``@(``@(``````````````````````N7YBN7YBN7YBN7YBN7YBN7YB +M````````````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````````````````````N7YBN7YBN7YBN7YBN7YB```````````````` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````````````N7YBN7YBN7YBN7YBN7YB +MN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB```````` +M````````````````````````@(``@(``@(``@(``@(``````N7YBN7YBN7YB +MN7YB````````````````````@(``@(``@(``@(``@(``@(`````````````` +MN7YBN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``````N7YB +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(`````````` +M````````````N7YBN7YBN7YBN7YBN7YBN7YB```````````````````````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````````````N7YB +MN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``````N7YB +MN7YBN7YB````````````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````````````````N7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB +MN7YBN7YBN7YBN7YB````````````````````````@(``````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB```````````````` +M````@(``@(``````````@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB +MN7YBN7YBN7YB````````````````````````@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YBN7YBN7YB +M````````````````````````@(``````````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````````N7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB +MN7YB````````````````````````````@(``@(``````````@(``@(``@(`` +M@(``````N7YBN7YBN7YBN7YB````````````````````@(``@(``@(``@(`` +M@(``@(``@(``````````N7YBN7YBN7YBN7YB```````````````````````` +M````@(``@(``````N7YBN7YBN7YBN7YB````````````````````````@(`` +M@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YBN7YBN7YB```````````` +M````````````@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````````N7YBN7YBN7YBN7YB````````````````````````@(``@(`` +M@(``@(``````````N7YBN7YBN7YB````````````````@(``````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````````````````````````N7YBN7YBN7YB +MN7YBN7YBN7YBN7YBN7YBN7YB````````````````````````````@(``@(`` +M@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB +MN7YB````````````````@(``@(``@(``@(``````````@(``@(``@(``@(`` +M@(``````N7YBN7YBN7YBN7YBN7YB````````````````````````@(``@(`` +M@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````````@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````````````````````````N7YBN7YBN7YBN7YB +MN7YBN7YB````````````````````````````````````@(``@(``@(``@(`` +M@(``````````@(``@(``@(``````N7YBN7YBN7YBN7YB````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````````@(``````@(``@(``````N7YBN7YBN7YB```````````` +M````````@(``````````@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB +MN7YB````````````````````````@(``@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``````@(``@(``@(``````N7YBN7YBN7YB```````````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````` +M```````````````````````````````````````````````````````````` +M````@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(`` +M````````N7YBN7YBN7YB````````````````````@(``@(``@(``@(``@(`` +M@(``````@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````````` +M````````````````````````````````````````````````````````@(`` +M@(``@(``@(``@(``@(``@(``````````@(``@(``@(``````N7YBN7YBN7YB +MN7YB````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``````N7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````N7YBN7YBN7YB````````````````````@(``@(``@(``@(``@(`` +M@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(`````````````````````````````````````````` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(`````````````````````````````````````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(`` +M@(``````N7YBN7YBN7YBN7YB````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB````````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``````N7YBN7YBN7YB````````````````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````` +M````````````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````````@(``@(``@(``````N7YBN7YBN7YBN7YB````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB +M````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``````N7YBN7YBN7YB````````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````````@(``@(``@(``````N7YBN7YBN7YB +MN7YB````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``````N7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``@(``@(``````N7YBN7YBN7YB```` +M````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YB````````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````N7YB````````@(``@(``@(``@(``@(``@(`` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(`` +M@(``````N7YBN7YBN7YBN7YB````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB````````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M````N7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB```` +M````@(``@(``@(``@(``````````N7YB````````@(``@(``@(``@(``@(`` +M@(``````````@(``@(``@(``````N7YBN7YBN7YBN7YB````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB +M````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YB +MN7YBN7YB````````````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````N7YBN7YBN7YB````````@(``@(``@(``@(``````````N7YBN7YB```` +M````````@(``@(``@(``@(``````````````````````````N7YBN7YBN7YB +MN7YB````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``````N7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``@(``````N7YBN7YBN7YB```````` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(``@(`` +M````````N7YBN7YB````````````@(``@(``@(``@(``````````@(``@(`` +M@(``````N7YBN7YBN7YBN7YB````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB````````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(`````` +MN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````````` +M````@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YB````````````````````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB```` +M````````@(``@(``@(``````````N7YBN7YB````````````````@(``@(`` +M@(``````````@(``@(``@(``````N7YBN7YBN7YBN7YB````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB +M````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````````````````N7YBN7YBN7YB````````````````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YB +MN7YB````````````````@(``@(``````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````````` +M@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````N7YBN7YBN7YB````````````@(``@(``@(``````````N7YBN7YB```` +M````````````@(``@(``@(``````````@(``@(``@(``````N7YBN7YBN7YB +MN7YB````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``````@(``@(``````N7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``````````N7YBN7YB```````````` +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````N7YBN7YBN7YB````````````````````@(``@(``````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YB````````````````@(``@(``@(``````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(``@(`` +M````````N7YBN7YB````````````````@(``@(``@(``````````@(``@(`` +M@(``````N7YBN7YBN7YBN7YB````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M````@(``@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB````````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(`````` +M````````````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````````N7YBN7YBN7YB````````````````@(`` +M@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(`````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB```` +M````````@(``@(``@(``````````N7YBN7YB````````````````@(``@(`` +M@(``````````@(``@(``@(``````N7YBN7YBN7YBN7YB````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````@(``@(``````@(``@(``````N7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB +M````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``````````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``````````````````N7YBN7YBN7YB```` +M````````````````@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````````` +M@(``@(``@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````N7YBN7YBN7YB````````````@(``@(``@(``````````N7YBN7YB```` +M````````````@(``@(``@(``````````@(``@(``@(``````N7YBN7YBN7YB +MN7YB````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``````@(``@(``````N7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(`````````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``````````````````````````````````````@(``@(`` +M````N7YBN7YBN7YB````````````````@(``@(``@(``@(``````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YB````````````````@(``@(``@(``@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(``@(`` +M````````N7YBN7YB````````````````@(``@(``@(`````````````````` +M````````N7YBN7YBN7YBN7YB````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````````````````````````````````````````@(``@(`` +M````@(``@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB````````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(``@(`` +M@(``````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB```` +M````````@(``@(``@(``````````N7YBN7YB````````````````@(``@(`` +M@(``````````@(``@(``@(``````N7YBN7YBN7YBN7YB````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````````````@(``````@(``@(``@(``````N7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB +M````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````` +M````````@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````````` +M@(``@(``@(``@(``@(``@(``````N7YBN7YB````````@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````N7YBN7YBN7YB````````````@(``@(``@(``````````N7YBN7YB```` +M````````````@(``@(``@(``````````@(``@(``@(``````N7YBN7YBN7YB +MN7YB````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``````N7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YB````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YB +MN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YB````````````````@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB +M````````@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(``@(`` +M````````N7YBN7YB````````````````@(``@(``@(``````````@(``@(`` +M@(``````N7YBN7YBN7YBN7YB````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(`` +M@(``@(``@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB````````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YB````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````N7YBN7YBN7YB````````````````````@(``@(``@(`` +M@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````````@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB```` +M````````@(``@(``@(``````````N7YBN7YB````````````````@(``@(`` +M@(``````````@(``@(``@(``````N7YBN7YBN7YBN7YB````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````````@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB +M````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````` +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````````` +M@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````````@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````N7YBN7YBN7YB````````````@(``@(``@(``````````N7YBN7YB```` +M````````````@(``@(``@(``````````@(``@(``@(``````N7YBN7YBN7YB +MN7YB````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````````@(``@(``@(``@(``@(``@(``````N7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````N7YBN7YBN7YB````````````````@(``@(``@(`````````````` +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``````````N7YB +MN7YBN7YB````````````````````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YB````````````````````@(``@(``@(``@(``@(``@(``````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YB````````````````@(``@(``````N7YBN7YBN7YBN7YBN7YB```````` +M````````````````@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(``@(``@(`` +M@(``@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(``@(`` +M````````N7YBN7YB````````````````@(``@(``@(``````````@(``@(`` +M@(``````N7YBN7YBN7YBN7YB````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(``@(``@(``@(`` +M@(``@(``@(``````N7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB````````````````@(`` +M````````N7YBN7YBN7YBN7YBN7YB````````@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(`` +M@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YB````````````````````````N7YBN7YBN7YB +MN7YBN7YB````````````````````@(`````````````````````````````` +MN7YBN7YBN7YBN7YB````````````````````````````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YB````````````@(``@(``@(``@(``@(``````````N7YBN7YBN7YB```` +M````````@(``@(``@(``````````N7YBN7YB````````````````@(``@(`` +M@(``````````@(``@(``@(``````N7YBN7YBN7YBN7YB````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````````` +M````@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB +M````````````````@(``````N7YBN7YBN7YBN7YBN7YBN7YBN7YB```````` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M____````````````@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````````````` +M@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````````` +M````N7YBN7YBN7YBN7YBN7YB````````````````````@(``@(``````N7YB +MN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB +MN7YB````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````````````````` +M````N7YBN7YBN7YB````````````@(``@(``@(``````````N7YBN7YB```` +M````````````@(``@(``@(``````````@(``@(``@(``````N7YBN7YBN7YB +MN7YBN7YB````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````````N7YBN7YBN7YBN7YB````````@(``@(``@(``@(``````````N7YB +MN7YBN7YBN7YBN7YB````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````N7YBN7YBN7YB````````````````````N7YBN7YBN7YBN7YBN7YB +MN7YB````````````````````@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````````@(``@(``@(``@(``````N7YBN7YBN7YB +M````````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````N7YBN7YBN7YB```````````````````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB +M````````````````@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````````````` +M````````````````````N7YBN7YBN7YBN7YBN7YB```````````````````` +M@(``@(``@(``````````N7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB +MN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YBN7YB +MN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB````````````@(``@(``@(`` +M````````N7YBN7YB````````````````@(``@(``@(`````````````````` +M````N7YBN7YBN7YB````````````````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``````````N7YBN7YBN7YBN7YBN7YBN7YB````````@(`` +M@(``````````N7YBN7YBN7YBN7YB````````````````````@(``@(``@(`` +M@(``@(``@(``@(``@(``````````````````````````````````````N7YB +MN7YBN7YBN7YBN7YB````````````````````````````````@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``````````@(`` +M````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB +MN7YBN7YBN7YBN7YBN7YB````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````N7YBN7YBN7YB````````````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````````````N7YBN7YBN7YBN7YBN7YB```` +M````````````````@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YBN7YB +MN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````````N7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB```` +M````````@(``@(``@(``````````N7YBN7YB````````````````@(``@(`` +M@(``````````````````````N7YBN7YB````````````````````````@(`` +M@(``````````@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YBN7YB```` +M````````````````````````N7YBN7YBN7YBN7YB```````````````````` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````````````````N7YBN7YBN7YBN7YB```````````````````````````` +M````````@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``````````````N7YBN7YBN7YB````````````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````````````````N7YBN7YBN7YBN7YBN7YBN7YB````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````N7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````````N7YBN7YB````````````````````@(``@(``@(``@(``@(`````` +M````````N7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB +MN7YBN7YBN7YBN7YBN7YB````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````````````````````````````````N7YBN7YB +MN7YBN7YBN7YBN7YB````````````@(``@(``@(``````````N7YBN7YB```` +M````````````@(``@(``@(``````````@(``@(`````````````````````` +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YB````````````````````````@(``@(``````````N7YBN7YB```` +M````````````````````@(``@(``@(``````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YB```````````` +M````````````````````@(``````````@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``@(``@(``````````N7YB```````` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(`````````````````````````````````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````````````````````````````@(``@(`` +M@(``@(``@(``@(``@(``````````````````````N7YBN7YBN7YBN7YB```` +M````````````````````````````````````````____````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````````````` +M````````````````````````N7YBN7YBN7YB````````````@(``@(``@(`` +M````````N7YBN7YB````````````````@(``@(``@(``````````@(``@(`` +M@(``````````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````````````````````````````@(``@(``@(`` +M@(``@(``````````````````````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````````````````````````````@(``@(``@(``@(``````@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``````````````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````````` +M````````````````````````@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````` +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(`````````````````` +MN7YBN7YBN7YBN7YB```````````````````````````````````````````` +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````````````````````````````````N7YBN7YBN7YB```` +M````````@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(`` +M@(``````````@(``@(``@(``@(``@(``````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````````` +M````@(``@(``@(``@(``@(``@(``@(``````````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````````````````````@(``@(``@(`` +M@(``@(``````````@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``````````````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````````````````````````@(``@(``@(``@(`` +M@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````````````N7YBN7YBN7YBN7YB```````````````````````` +M````````````````````````````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````N7YBN7YBN7YB````````````@(``@(``@(``````````N7YBN7YBN7YB +M````````````@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```````````` +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(``@(`` +M````````N7YBN7YBN7YB````````````@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB```` +M````````@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(`` +M@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YB````````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````N7YBN7YBN7YB````````````@(``@(``@(``````````N7YBN7YBN7YB +M````````````@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(``@(`` +M````````N7YBN7YBN7YB````````````@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``````N7YBN7YBN7YB +M````````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB```` +M````````@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(`` +M@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(`` +M````````N7YBN7YBN7YB````````````````@(``@(`````````````````` +M````````````````````@(``@(``````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````````N7YBN7YBN7YBN7YB````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````N7YBN7YBN7YB````````````@(``@(``@(``````````N7YBN7YBN7YB +M````````````@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``````N7YBN7YBN7YB```````````````````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YB```` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(``@(`` +M````````N7YBN7YBN7YB````````````@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``@(``@(``@(``````N7YBN7YBN7YB```` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````````````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB```` +M````````@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(`` +M@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(`````` +MN7YBN7YBN7YB````````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````N7YBN7YBN7YB````````````@(``@(``@(``````````N7YBN7YBN7YB +M````````````@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``````N7YBN7YBN7YB````````````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(``@(`` +M````````N7YBN7YBN7YB````````````@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``@(``````N7YBN7YBN7YBN7YB```````` +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB```` +M````````@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(`` +M@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``````N7YB +MN7YBN7YB````````````````````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````N7YBN7YBN7YB````````````@(``@(``@(``````````N7YBN7YBN7YB +M````````````@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````````N7YBN7YB````````````@(``@(``@(`` +M````````N7YBN7YBN7YB````````````@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``````N7YBN7YBN7YB```````````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(`` +M@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YB```` +M````````@(``@(``@(``````````N7YBN7YBN7YB````````````@(``@(`` +M@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YB```````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB +MN7YB````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````````````````````@(``@(``@(``````````N7YBN7YBN7YB +M````````````@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````````````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````````N7YBN7YBN7YB````````````````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````````````@(``@(`` +M@(``````N7YBN7YBN7YB````````````@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB````````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YB````````````@(``@(`` +M@(``````````@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB```` +M````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````````````N7YBN7YBN7YBN7YBN7YBN7YB````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````````````````````````@(``@(``@(``@(``@(``````N7YBN7YB +M````````````@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(`` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +MN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``````@(``@(``@(``````````N7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB +MN7YBN7YB````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````````````````N7YBN7YBN7YBN7YBN7YB```````````` +M@(``@(``@(``````````````````````@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``````N7YBN7YBN7YB````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````````N7YBN7YBN7YB````````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````````````````N7YBN7YBN7YBN7YB +MN7YBN7YBN7YB````````````````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YBN7YBN7YBN7YB +MN7YBN7YBN7YBN7YBN7YB````````@(``@(``@(``````````````@(``@(`` +M@(``````````@(``@(``@(``@(``@(``````````N7YBN7YBN7YBN7YB```` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````` +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````` +MN7YBN7YBN7YBN7YBN7YBN7YB```````````````````````````````````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YB +MN7YBN7YBN7YBN7YB````````````````````````````````````@(``@(`` +M@(``@(``@(``````@(``@(``````````@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YBN7YBN7YB````````````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````N7YB +MN7YBN7YB````````````````````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````````N7YBN7YBN7YB```````````````````` +M@(``@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````N7YBN7YBN7YBN7YBN7YBN7YB````````````````````````````@(`` +M@(``````````````@(``@(``@(``@(``@(``@(``@(`````````````````` +M````````N7YBN7YBN7YBN7YBN7YBN7YB````````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````````````` +M````````````````@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````````````N7YBN7YBN7YBN7YBN7YB```````````````````` +M````````@(``@(``@(``@(``@(``@(``````````@(``@(``@(``@(``@(`` +M@(``@(``````N7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB```````````` +M````````@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB```````````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``````````````````````````@(``@(``@(``@(``@(``@(``@(`` +M````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``````````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````````N7YBN7YBN7YBN7YBN7YB```````` +M````````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````@(``@(``@(``@(``@(``@(``````````````N7YBN7YBN7YBN7YBN7YB +M````````````````````````@(``@(``@(``````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````____````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YBN7YBN7YB +M````````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``````````````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``````````````N7YBN7YBN7YB +MN7YBN7YB````````````````````````@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(`````````` +M````````````````````````````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M````____````````@(``@(``@(``@(``@(``@(``@(``@(``@(`````````` +MN7YBN7YBN7YBN7YBN7YB````````````````@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``````````````@(``@(``@(``@(``@(``@(``@(``@(`````````````` +MN7YBN7YBN7YBN7YBN7YB````````````````````````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````````````````````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``````N7YBN7YB````````````@(``@(``@(`` +M````````````N7YBN7YBN7YBN7YBN7YBN7YB````````````````````@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(`````````````````````````````````` +M````````````N7YBN7YBN7YBN7YBN7YBN7YB```````````````````````` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````````````` +M````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````N7YBN7YB +MN7YBN7YB````````````N7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB```````` +M````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````` +MN7YBN7YBN7YB````N7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB```````````` +M````````````````@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````````N7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB +MN7YB````````````````````````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``````````````N7YBN7YBN7YBN7YBN7YBN7YBN7YBN7YB +M````````````````````````````@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``````````````N7YBN7YB +MN7YBN7YBN7YB````````````````````````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`````````````````` +M````````````````````````````````````````@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````````````````````````````````````@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``````````````````````````````````````````@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +M@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(``@(`` +)@(``@(``@(`` +` +end diff --git a/win/win32/tile2bmp.dsp b/win/win32/tile2bmp.dsp new file mode 100644 index 0000000..5a534e2 --- /dev/null +++ b/win/win32/tile2bmp.dsp @@ -0,0 +1,146 @@ +# Microsoft Developer Studio Project File - Name="tile2bmp" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=tile2bmp - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "tile2bmp.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "tile2bmp.mak" CFG="tile2bmp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "tile2bmp - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "tile2bmp - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "tile2bmp - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\sys\winnt" /I "..\win\share" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32CON" /D "DLB" /D "MSWIN_GRAPHICS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x1009 /d "NDEBUG" +# ADD RSC /l 0x1009 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\util\tile2bmp.exe" + +!ELSEIF "$(CFG)" == "tile2bmp - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\sys\winnt" /I "..\win\share" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32CON" /D "DLB" /D "MSWIN_GRAPHICS" /FD /GZ /c +# ADD BASE RSC /l 0x1009 /d "_DEBUG" +# ADD RSC /l 0x1009 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\util\tile2bmp.exe" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "tile2bmp - Win32 Release" +# Name "tile2bmp - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\src\decl.c +# End Source File +# Begin Source File + +SOURCE=..\src\drawing.c +# End Source File +# Begin Source File + +SOURCE=..\src\monst.c +# End Source File +# Begin Source File + +SOURCE=..\src\objects.c +# End Source File +# Begin Source File + +SOURCE=..\win\share\tile2bmp.c + +!IF "$(CFG)" == "tile2bmp - Win32 Release" + +!ELSEIF "$(CFG)" == "tile2bmp - Win32 Debug" + +# ADD CPP /D "PACKED_FILE" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\win\share\tiletext.c + +!IF "$(CFG)" == "tile2bmp - Win32 Release" + +!ELSEIF "$(CFG)" == "tile2bmp - Win32 Debug" + +# ADD CPP /Zi + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\win\share\tiletxt.c +# ADD CPP /D "TILETEXT" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/win/win32/tilemap.dsp b/win/win32/tilemap.dsp new file mode 100644 index 0000000..37d71ef --- /dev/null +++ b/win/win32/tilemap.dsp @@ -0,0 +1,281 @@ +# Microsoft Developer Studio Project File - Name="tilemap" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=tilemap - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "tilemap.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "tilemap.mak" CFG="tilemap - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "tilemap - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "tilemap - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "tilemap - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\sys\winnt\include" /I "..\win\share" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32CON" /D "DLB" /D "MSWIN_GRAPHICS" /FD /c +# SUBTRACT CPP /YX +# ADD BASE RSC /l 0x1009 /d "NDEBUG" +# ADD RSC /l 0x1009 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"..\util\tilemap.exe" +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Generating src\tile.c +PostBuild_Cmds=echo chdir ..\src chdir ..\src ..\util\tilemap.exe echo chdir ..\build chdir ..\build +# End Special Build Tool + +!ELSEIF "$(CFG)" == "tilemap - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /Zi /Od /I "..\include" /I "..\sys\winnt\include" /I "..\win\share" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "WIN32CON" /D "DLB" /D "MSWIN_GRAPHICS" /FD /GZ /c +# ADD BASE RSC /l 0x1009 /d "_DEBUG" +# ADD RSC /l 0x1009 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 /out:"..\util\tilemap.exe" /pdbtype:sept +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Desc=Generating src\tile.c +PostBuild_Cmds=echo chdir ..\src chdir ..\src ..\util\tilemap.exe echo chdir ..\build chdir ..\build +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "tilemap - Win32 Release" +# Name "tilemap - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\win\share\tilemap.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\include\align.h +# End Source File +# Begin Source File + +SOURCE=..\include\attrib.h +# End Source File +# Begin Source File + +SOURCE=..\include\color.h +# End Source File +# Begin Source File + +SOURCE=..\include\config.h +# End Source File +# Begin Source File + +SOURCE=..\include\config1.h +# End Source File +# Begin Source File + +SOURCE=..\include\coord.h +# End Source File +# Begin Source File + +SOURCE=..\include\decl.h +# End Source File +# Begin Source File + +SOURCE=..\include\dgn_comp.h +# End Source File +# Begin Source File + +SOURCE=..\include\dgn_file.h +# End Source File +# Begin Source File + +SOURCE=..\include\display.h +# End Source File +# Begin Source File + +SOURCE=..\include\dungeon.h +# End Source File +# Begin Source File + +SOURCE=..\include\engrave.h +# End Source File +# Begin Source File + +SOURCE=..\include\flag.h +# End Source File +# Begin Source File + +SOURCE=..\include\global.h +# End Source File +# Begin Source File + +SOURCE=..\include\mkroom.h +# End Source File +# Begin Source File + +SOURCE=..\include\monattk.h +# End Source File +# Begin Source File + +SOURCE=..\include\monst.h +# End Source File +# Begin Source File + +SOURCE=..\include\monsym.h +# End Source File +# Begin Source File + +SOURCE=..\include\nhlan.h +# End Source File +# Begin Source File + +SOURCE=..\include\ntconf.h +# End Source File +# Begin Source File + +SOURCE=..\include\obj.h +# End Source File +# Begin Source File + +SOURCE=..\include\objclass.h +# End Source File +# Begin Source File + +SOURCE=..\include\onames.h +# End Source File +# Begin Source File + +SOURCE=..\include\permonst.h +# End Source File +# Begin Source File + +SOURCE=..\include\pm.h +# End Source File +# Begin Source File + +SOURCE=..\include\prop.h +# End Source File +# Begin Source File + +SOURCE=..\include\quest.h +# End Source File +# Begin Source File + +SOURCE=..\include\rect.h +# End Source File +# Begin Source File + +SOURCE=..\include\region.h +# End Source File +# Begin Source File + +SOURCE=..\include\rm.h +# End Source File +# Begin Source File + +SOURCE=..\include\skills.h +# End Source File +# Begin Source File + +SOURCE=..\include\spell.h +# End Source File +# Begin Source File + +SOURCE=..\include\timeout.h +# End Source File +# Begin Source File + +SOURCE=..\include\tradstdc.h +# End Source File +# Begin Source File + +SOURCE=..\include\trampoli.h +# End Source File +# Begin Source File + +SOURCE=..\include\trap.h +# End Source File +# Begin Source File + +SOURCE=..\include\vision.h +# End Source File +# Begin Source File + +SOURCE=..\include\winprocs.h +# End Source File +# Begin Source File + +SOURCE=..\include\wintty.h +# End Source File +# Begin Source File + +SOURCE=..\include\wintype.h +# End Source File +# Begin Source File + +SOURCE=..\include\you.h +# End Source File +# Begin Source File + +SOURCE=..\include\youprop.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/win/win32/tiles.dsp b/win/win32/tiles.dsp new file mode 100644 index 0000000..ab2207a --- /dev/null +++ b/win/win32/tiles.dsp @@ -0,0 +1,97 @@ +# Microsoft Developer Studio Project File - Name="tiles" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) External Target" 0x0106 + +CFG=tiles - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "tiles.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "tiles.mak" CFG="tiles - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "tiles - Win32 Release" (based on "Win32 (x86) External Target") +!MESSAGE "tiles - Win32 Debug" (based on "Win32 (x86) External Target") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "tiles - Win32 Release" + +# PROP BASE Use_MFC +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Cmd_Line "NMAKE /f tiles.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "tiles.exe" +# PROP BASE Bsc_Name "tiles.bsc" +# PROP BASE Target_Dir "" +# PROP Use_MFC +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Cmd_Line "nmake /f "tiles.mak"" +# PROP Rebuild_Opt "/a" +# PROP Target_File "..\win\win32\tiles.bmp" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "tiles - Win32 Debug" + +# PROP BASE Use_MFC +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Cmd_Line "NMAKE /f tiles.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "tiles.exe" +# PROP BASE Bsc_Name "tiles.bsc" +# PROP BASE Target_Dir "" +# PROP Use_MFC +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Cmd_Line "nmake /f "tiles.mak"" +# PROP Rebuild_Opt "/a" +# PROP Target_File "..\win\win32\tiles.bmp" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "tiles - Win32 Release" +# Name "tiles - Win32 Debug" + +!IF "$(CFG)" == "tiles - Win32 Release" + +!ELSEIF "$(CFG)" == "tiles - Win32 Debug" + +!ENDIF + +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/win/win32/tiles.mak b/win/win32/tiles.mak new file mode 100644 index 0000000..26af1ea --- /dev/null +++ b/win/win32/tiles.mak @@ -0,0 +1,21 @@ +default: all + +all: ..\win\win32\tiles.bmp + +clean: + -del ..\src\win\win32\tiles.bmp + -del ..\win\win32\tiles.bmp + +#========================================== +# Building the tiles file tile.bmp +#========================================== + +..\src\tiles.bmp : ..\win\share\monsters.txt ..\win\share\objects.txt \ + ..\win\share\other.txt + chdir ..\src + ..\util\tile2bmp.exe tiles.bmp + chdir ..\build + +..\win\win32\tiles.bmp: ..\src\tiles.bmp + @copy ..\src\tiles.bmp ..\win\win32\tiles.bmp + diff --git a/win/win32/uudecode.dsp b/win/win32/uudecode.dsp new file mode 100644 index 0000000..a9cf1be --- /dev/null +++ b/win/win32/uudecode.dsp @@ -0,0 +1,146 @@ +# Microsoft Developer Studio Project File - Name="uudecode" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=uudecode - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "uudecode.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "uudecode.mak" CFG="uudecode - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "uudecode - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "uudecode - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "uudecode - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:console /machine:I386 /out:"..\util\uudecode.exe" +# SUBTRACT LINK32 /nodefaultlib +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=echo chdir ..\win\win32 chdir ..\win\win32 \ +echo decoding icon (nhico.uu to NetHack.ico) \ +..\..\util\uudecode.exe ../../sys/winnt/nhico.uu \ +echo decoding mnsel (mnsel.uu to mnsel.bmp) \ +..\..\util\uudecode.exe mnsel.uu \ +echo decoding mnselcnt (mnselcnt.uu to mnselcnt.bmp) \ +..\..\util\uudecode.exe mnselcnt.uu \ +echo decoding mnunsel (mnunsel.uu to mnunsel.bmp) \ +..\..\util\uudecode.exe mnunsel.uu \ +echo decoding petmark (petmark.uu to petmark.bmp) \ +..\..\util\uudecode.exe petmark.uu \ +echo decoding splash (splash.uu to splash.bmp) \ +..\..\util\uudecode.exe splash.uu \ +echo decoding tombstone (rip.uu to rip.bmp) \ +..\..\util\uudecode.exe rip.uu \ +chdir ..\..\binary + +# End Special Build Tool + +!ELSEIF "$(CFG)" == "uudecode - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Yu"stdafx.h" /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /GZ /c +# SUBTRACT CPP /YX /Yc /Yu +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib /nologo /subsystem:console /debug /machine:I386 /out:"..\util\uudecode.exe" /pdbtype:sept +# SUBTRACT LINK32 /nodefaultlib +# Begin Special Build Tool +SOURCE="$(InputPath)" +PostBuild_Cmds=echo chdir ..\win\win32 chdir ..\win\win32 \ +echo decoding icon (nhico.uu to NetHack.ico) \ +..\..\util\uudecode.exe ../../sys/winnt/nhico.uu \ +echo decoding mnsel (mnsel.uu to mnsel.bmp) \ +..\..\util\uudecode.exe mnsel.uu \ +echo decoding mnselcnt (mnselcnt.uu to mnselcnt.bmp) \ +..\..\util\uudecode.exe mnselcnt.uu \ +echo decoding mnunsel (mnunsel.uu to mnunsel.bmp) \ +..\..\util\uudecode.exe mnunsel.uu \ +echo decoding petmark (petmark.uu to petmark.bmp) \ +..\..\util\uudecode.exe petmark.uu \ +echo decoding splash (splash.uu to splash.bmp) \ +..\..\util\uudecode.exe splash.uu \ +echo decoding tombstone (rip.uu to rip.bmp) \ +..\..\util\uudecode.exe rip.uu \ +chdir ..\..\binary + +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "uudecode - Win32 Release" +# Name "uudecode - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\sys\share\uudecode.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/win/win32/winMS.h b/win/win32/winMS.h new file mode 100644 index 0000000..80d09fa --- /dev/null +++ b/win/win32/winMS.h @@ -0,0 +1,187 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +#ifndef WINMS_H +#define WINMS_H + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include "hack.h" + +/* Create an array to keep track of the various windows */ + +#ifndef MAXWINDOWS +#define MAXWINDOWS 15 +#endif + +#define NHW_RIP 32 + +#ifndef TILE_X +#define TILE_X 16 +#endif +#define TILE_Y 16 + +#define TILES_PER_LINE 40 + +/* tile background color */ +#define TILE_BK_COLOR RGB(71, 108, 108) + +/* minimum/maximum font size (in points - 1/72 inch) */ +#define NHFONT_DEFAULT_SIZE 9 +#define NHFONT_SIZE_MIN 3 +#define NHFONT_SIZE_MAX 20 + +#define MAX_LOADSTRING 100 + +typedef struct mswin_nhwindow_data { + HWND win; + int type; + int dead; +} MSNHWinData, *PMSNHWinData; + +typedef struct mswin_nhwindow_app { + HINSTANCE hApp; + HWND hMainWnd; + HACCEL hAccelTable; + HWND hPopupWnd; /* current popup window */ + + MSNHWinData windowlist[MAXWINDOWS]; + + HBITMAP bmpTiles; + HBITMAP bmpPetMark; + HBITMAP bmpMapTiles; /* custom tiles bitmap */ + HBITMAP bmpRip; + HBITMAP bmpSplash; + int mapTile_X; /* tile width */ + int mapTile_Y; /* tile height */ + int mapTilesPerLine; /* number of tile per row in the bitmap */ + + boolean bNoHScroll; /* disable cliparound for horizontal grid (map) */ + boolean bNoVScroll; /* disable cliparound for vertical grid (map) */ + + int mapDisplayModeSave; /* saved map display mode */ + + char* saved_text; + + DWORD saveRegistrySettings; /* Flag if we should save this time */ + DWORD regNetHackMode; /* NetHack mode means no Windows keys in some places */ +} NHWinApp, *PNHWinApp; + +#define E extern + +E PNHWinApp GetNHApp(void); +E struct window_procs mswin_procs; + +#undef E + +/* Some prototypes */ +void mswin_init_nhwindows(int* argc, char** argv); +void mswin_player_selection(void); +void mswin_askname(void); +void mswin_get_nh_event(void); +void mswin_exit_nhwindows(const char *); +void mswin_suspend_nhwindows(const char *); +void mswin_resume_nhwindows(void); +winid mswin_create_nhwindow(int type); +void mswin_clear_nhwindow(winid wid); +void mswin_display_nhwindow(winid wid, BOOLEAN_P block); +void mswin_destroy_nhwindow(winid wid); +void mswin_curs(winid wid, int x, int y); +void mswin_putstr(winid wid, int attr, const char *text); +void mswin_putstr_ex(winid wid, int attr, const char *text, boolean append); +void mswin_display_file(const char *filename,BOOLEAN_P must_exist); +void mswin_start_menu(winid wid); +void mswin_add_menu(winid wid, int glyph, const ANY_P * identifier, + CHAR_P accelerator, CHAR_P group_accel, int attr, + const char *str, BOOLEAN_P presel); +void mswin_end_menu(winid wid, const char *prompt); +int mswin_select_menu(winid wid, int how, MENU_ITEM_P **selected); +void mswin_update_inventory(void); +void mswin_mark_synch(void); +void mswin_wait_synch(void); +void mswin_cliparound(int x, int y); +void mswin_print_glyph(winid wid,XCHAR_P x,XCHAR_P y,int glyph); +void mswin_raw_print(const char *str); +void mswin_raw_print_bold(const char *str); +int mswin_nhgetch(void); +int mswin_nh_poskey(int *x, int *y, int *mod); +void mswin_nhbell(void); +int mswin_doprev_message(void); +char mswin_yn_function(const char *question, const char *choices, + CHAR_P def); +void mswin_getlin(const char *question, char *input); +int mswin_get_ext_cmd(void); +void mswin_number_pad(int state); +void mswin_delay_output(void); +void mswin_change_color(void); +char *mswin_get_color_string(void); +void mswin_start_screen(void); +void mswin_end_screen(void); +void mswin_outrip(winid wid, int how); +void mswin_preference_update(const char *pref); + +/* helper function */ +HWND mswin_hwnd_from_winid(winid wid); +winid mswin_winid_from_type(int type); +winid mswin_winid_from_handle(HWND hWnd); +void mswin_window_mark_dead(winid wid); +void bail(const char *mesg); +void nhapply_image_transparent( + HDC hDC, int x, int y, int width, int height, + HDC sourceDC, int s_x, int s_y, int s_width, int s_height, + COLORREF cTransparent +); + +void mswin_read_reg(void); +void mswin_destroy_reg(void); +void mswin_write_reg(void); + +extern HBRUSH menu_bg_brush; +extern HBRUSH menu_fg_brush; +extern HBRUSH text_bg_brush; +extern HBRUSH text_fg_brush; +extern HBRUSH status_bg_brush; +extern HBRUSH status_fg_brush; +extern HBRUSH message_bg_brush; +extern HBRUSH message_fg_brush; + +extern COLORREF menu_bg_color; +extern COLORREF menu_fg_color; +extern COLORREF text_bg_color; +extern COLORREF text_fg_color; +extern COLORREF status_bg_color; +extern COLORREF status_fg_color; +extern COLORREF message_bg_color; +extern COLORREF message_fg_color; + + +#define SYSCLR_TO_BRUSH(x) ((HBRUSH)((x) + 1)) + +/* unicode stuff */ +#ifdef UNICODE + #define NH_W2A(w, a, cb) ( WideCharToMultiByte( \ + CP_ACP, \ + 0, \ + (w), \ + -1, \ + (a), \ + (cb), \ + NULL, \ + NULL), (a) ) + + #define NH_A2W(a, w, cb) ( MultiByteToWideChar( \ + CP_ACP, \ + 0, \ + (a), \ + -1, \ + (w), \ + (cb)), (w) ) +#else + #define NH_W2A(w, a, cb) (strncpy((a), (w), (cb))) + + #define NH_A2W(a, w, cb) (strncpy((w), (a), (cb))) +#endif + +#endif /* WINmswin_H */ diff --git a/win/win32/winhack.c b/win/win32/winhack.c new file mode 100644 index 0000000..5498967 --- /dev/null +++ b/win/win32/winhack.c @@ -0,0 +1,287 @@ +/* Copyright (C) 2001 by Alex Kompel */ +/* NetHack may be freely redistributed. See license for details. */ + +// winhack.cpp : Defines the entry point for the application. +// + +#include +#include "winMS.h" +#include "hack.h" +#include "dlb.h" +#include "resource.h" +#include "mhmain.h" +#include "mhmap.h" + +#ifndef __BORLANDC__ +#include +#else /* Borland redefines "boolean" in shlwapi.h so just use the little bit we need */ +typedef struct _DLLVERSIONINFO +{ + DWORD cbSize; + DWORD dwMajorVersion; // Major version + DWORD dwMinorVersion; // Minor version + DWORD dwBuildNumber; // Build number + DWORD dwPlatformID; // DLLVER_PLATFORM_* +} DLLVERSIONINFO; + +// +// The caller should always GetProcAddress("DllGetVersion"), not +// implicitly link to it. +// + +typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *); + +#endif + +#ifdef OVL0 +#define SHARED_DCL +#else +#define SHARED_DCL extern +#endif + +/* Minimal common control library version +Version _WIN_32IE Platform/IE +======= ========= =========== +4.00 0x0200 Microsoft(r) Windows 95/Windows NT 4.0 +4.70 0x0300 Microsoft(r) Internet Explorer 3.x +4.71 0x0400 Microsoft(r) Internet Explorer 4.0 +4.72 0x0401 Microsoft(r) Internet Explorer 4.01 +...and probably going on infinitely... +*/ +#define MIN_COMCTLMAJOR 4 +#define MIN_COMCTLMINOR 71 +#define INSTALL_NOTES "http://www.nethack.org/v340/ports/download-win.html#cc" +/*#define COMCTL_URL "http://www.microsoft.com/msdownload/ieplatform/ie/comctrlx86.asp"*/ + +extern void FDECL(nethack_exit,(int)); +static TCHAR* _get_cmd_arg(TCHAR* pCmdLine); +static HRESULT GetComCtlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor); + + +// Global Variables: +NHWinApp _nethack_app; + +#ifdef __BORLANDC__ +#define _stricmp(s1,s2) stricmp(s1,s2) +#define _strdup(s1) strdup(s1) +#endif + +// Foward declarations of functions included in this code module: +BOOL InitInstance(HINSTANCE, int); + +extern void FDECL(pcmain, (int,char **)); +static void __cdecl mswin_moveloop(void *); + +#define MAX_CMDLINE_PARAM 255 + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + INITCOMMONCONTROLSEX InitCtrls; + int argc; + char* argv[MAX_CMDLINE_PARAM]; + size_t len; + TCHAR *p; + TCHAR wbuf[BUFSZ]; + char buf[BUFSZ]; + DWORD major, minor; + + + /* ensure that we don't access violate on a panic() */ + windowprocs.win_raw_print = mswin_raw_print; + windowprocs.win_raw_print_bold = mswin_raw_print_bold; + + /* init applicatio structure */ + _nethack_app.hApp = hInstance; + _nethack_app.hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_NETHACKW); + _nethack_app.hMainWnd = NULL; + _nethack_app.hPopupWnd = NULL; + _nethack_app.bmpTiles = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TILES)); + if( _nethack_app.bmpTiles==NULL ) panic("cannot load tiles bitmap"); + _nethack_app.bmpPetMark = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_PETMARK)); + if( _nethack_app.bmpPetMark==NULL ) panic("cannot load pet mark bitmap"); + _nethack_app.bmpRip = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_RIP)); + if ( _nethack_app.bmpRip == NULL ) panic("cannot load rip bitmap"); + _nethack_app.bmpSplash = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_SPLASH)); + if ( _nethack_app.bmpSplash == NULL ) panic("cannot load splash bitmap"); + _nethack_app.bmpMapTiles = _nethack_app.bmpTiles; + _nethack_app.mapTile_X = TILE_X; + _nethack_app.mapTile_Y = TILE_Y; + _nethack_app.mapTilesPerLine = TILES_PER_LINE; + + _nethack_app.bNoHScroll = FALSE; + _nethack_app.bNoVScroll = FALSE; + _nethack_app.saved_text = strdup(""); + + // init controls + if (FAILED(GetComCtlVersion(&major, &minor))) + { + char buf[TBUFSZ]; + Sprintf(buf, "Cannot load common control library.\n%s\n%s", + "For further information, refer to the installation notes at", + INSTALL_NOTES); + panic(buf); + } + if (major < MIN_COMCTLMAJOR + || (major == MIN_COMCTLMAJOR && minor < MIN_COMCTLMINOR)) + { + char buf[TBUFSZ]; + Sprintf(buf, "Common control library is outdated.\n%s %d.%d\n%s\n%s", + "NetHack requires at least version ", + MIN_COMCTLMAJOR, MIN_COMCTLMINOR, + "For further information, refer to the installation notes at", + INSTALL_NOTES); + panic(buf); + } + ZeroMemory(&InitCtrls, sizeof(InitCtrls)); + InitCtrls.dwSize = sizeof(InitCtrls); + InitCtrls.dwICC = ICC_LISTVIEW_CLASSES; + InitCommonControlsEx(&InitCtrls); + + // Perform application initialization: + if (!InitInstance (hInstance, nCmdShow)) + { + return FALSE; + } + + /* get command line parameters */ + p = _get_cmd_arg(GetCommandLine()); + p = _get_cmd_arg(NULL); /* skip first paramter - command name */ + for( argc = 1; p && argc0 ) { + argv[argc] = _strdup( NH_W2A(p, buf, BUFSZ) ); + } else { + argv[argc] = ""; + } + p = _get_cmd_arg(NULL); + } + GetModuleFileName(NULL, wbuf, BUFSZ); + argv[0] = _strdup(NH_W2A(wbuf, buf, BUFSZ)); + + pcmain(argc,argv); + + moveloop(); + + return 0; +} + + +// +// FUNCTION: InitInstance(HANDLE, int) +// +// PURPOSE: Creates main window +// +// COMMENTS: +// +// In this function, we create and display the main program window. +// +BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) +{ + HWND hWnd; + + hWnd = mswin_init_main_window(); + if (!hWnd) + { + return FALSE; + } + + ShowWindow(hWnd, nCmdShow); + UpdateWindow(hWnd); + + _nethack_app.hMainWnd = hWnd; + + return TRUE; +} + +PNHWinApp GetNHApp() +{ + return &_nethack_app; +} + +TCHAR* _get_cmd_arg(TCHAR* pCmdLine) +{ + static TCHAR* pArgs = NULL; + TCHAR *pRetArg; + BOOL bQuoted; + + if( !pCmdLine && !pArgs ) return NULL; + if( !pArgs ) pArgs = pCmdLine; + + /* skip whitespace */ + for(pRetArg = pArgs; *pRetArg && _istspace(*pRetArg); pRetArg = CharNext(pRetArg)); + if( !*pRetArg ) { + pArgs = NULL; + return NULL; + } + + /* check for quote */ + if( *pRetArg==TEXT('"') ) { + bQuoted = TRUE; + pRetArg = CharNext(pRetArg); + pArgs = _tcschr(pRetArg, TEXT('"')); + } else { + /* skip to whitespace */ + for(pArgs = pRetArg; *pArgs && !_istspace(*pArgs); pArgs = CharNext(pArgs)); + } + + if( pArgs && *pArgs ) { + TCHAR* p; + p = pArgs; + pArgs = CharNext(pArgs); + *p = (TCHAR)0; + } else { + pArgs = NULL; + } + + return pRetArg; +} + +/* Get the version of the Common Control library on this machine. + Copied from the Microsoft SDK + */ +HRESULT GetComCtlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor) +{ + HINSTANCE hComCtl; + HRESULT hr = S_OK; + DLLGETVERSIONPROC pDllGetVersion; + + if(IsBadWritePtr(pdwMajor, sizeof(DWORD)) || + IsBadWritePtr(pdwMinor, sizeof(DWORD))) + return E_INVALIDARG; + //load the DLL + hComCtl = LoadLibrary(TEXT("comctl32.dll")); + if (!hComCtl) return E_FAIL; + + /* + You must get this function explicitly because earlier versions of the DLL + don't implement this function. That makes the lack of implementation of the + function a version marker in itself. + */ + pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hComCtl, TEXT("DllGetVersion")); + if(pDllGetVersion) { + DLLVERSIONINFO dvi; + ZeroMemory(&dvi, sizeof(dvi)); + dvi.cbSize = sizeof(dvi); + hr = (*pDllGetVersion)(&dvi); + if(SUCCEEDED(hr)) { + *pdwMajor = dvi.dwMajorVersion; + *pdwMinor = dvi.dwMinorVersion; + } else { + hr = E_FAIL; + } + } else { + /* + If GetProcAddress failed, then the DLL is a version previous to the one + shipped with IE 3.x. + */ + *pdwMajor = 4; + *pdwMinor = 0; + } + FreeLibrary(hComCtl); + return hr; +} + + diff --git a/win/win32/winhack.h b/win/win32/winhack.h new file mode 100644 index 0000000..bce5d91 --- /dev/null +++ b/win/win32/winhack.h @@ -0,0 +1,18 @@ +/* SCCS Id: @(#)winhack.h 3.4 2002/03/06 */ +/* Copyright (c) Alex Kompel, 2002 */ +/* NetHack may be freely redistributed. See license for details. */ + + +#if !defined(AFX_WINHACK_H__6397C328_BAF8_460C_9465_F12C596C5732__INCLUDED_) +#define AFX_WINHACK_H__6397C328_BAF8_460C_9465_F12C596C5732__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define STRICT +#include +#include "resource.h" + + +#endif // !defined(AFX_WINHACK_H__6397C328_BAF8_460C_9465_F12C596C5732__INCLUDED_) diff --git a/win/win32/winhack.rc b/win/win32/winhack.rc new file mode 100644 index 0000000..7af7663 --- /dev/null +++ b/win/win32/winhack.rc @@ -0,0 +1,332 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#if defined(__BORLANDC__) +LANGUAGE LANG_ENGLISH,SUBLANG_ENGLISH_US +#endif +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_NETHACKW ICON DISCARDABLE "NETHACK.ICO" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDC_NETHACKW MENU DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Save", IDM_SAVE + MENUITEM SEPARATOR + MENUITEM "&Quit", IDM_EXIT + END + POPUP "&Map" + BEGIN + MENUITEM "&0 - Use Tiles", IDM_MAP_TILES + MENUITEM "&1 - ASCII (4x6)", IDM_MAP_ASCII4X6 + MENUITEM "&2 - ASCII (6x8)", IDM_MAP_ASCII6X8 + MENUITEM "&3 - ASCII (8x8)", IDM_MAP_ASCII8X8 + MENUITEM "&4 - ASCII (16x8)", IDM_MAP_ASCII16X8 + MENUITEM "&5 - ASCII (7x12)", IDM_MAP_ASCII7X12 + MENUITEM "&6 - ASCII (8x12)", IDM_MAP_ASCII8X12 + MENUITEM "&7 - ASCII (16x12)", IDM_MAP_ASCII16X12 + MENUITEM "&8 - ASCII (12x16)", IDM_MAP_ASCII12X16 + MENUITEM "&9 - ASCII (10x18)", IDM_MAP_ASCII10X18 + MENUITEM SEPARATOR + MENUITEM "&Fit To Screen ", IDM_MAP_FIT_TO_SCREEN + END + POPUP "Windows &Settings" + BEGIN + MENUITEM "NetHack Mode", IDM_NHMODE + MENUITEM SEPARATOR + MENUITEM "&Clear All Settings", IDM_CLEARSETTINGS + END + POPUP "&Help" + BEGIN + MENUITEM "&About ...", IDM_ABOUT + MENUITEM "&Long description of the game", IDM_HELP_LONG + MENUITEM "List of &commands", IDM_HELP_COMMANDS + MENUITEM "&History of NetHack", IDM_HELP_HISTORY + MENUITEM "&Info on a character", IDM_HELP_INFO_CHAR + MENUITEM "Info on what a given &key does", IDM_HELP_INFO_KEY + MENUITEM "List of game &options", IDM_HELP_OPTIONS + MENUITEM "&Longer list of game options", IDM_HELP_OPTIONS_LONG + MENUITEM "List of e&xtended commands", IDM_HELP_EXTCMD + MENUITEM "The &NetHack license", IDM_HELP_LICENSE + MENUITEM "NetHack for &Windows help", IDM_HELP_PORTHELP + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDC_NETHACKW ACCELERATORS MOVEABLE PURE +BEGIN + "?", IDM_ABOUT, ASCII, ALT + "/", IDM_ABOUT, ASCII, ALT +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 230, 75 +STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU +CAPTION "About" +FONT 8, "System" +BEGIN + LTEXT "NetHack",IDC_ABOUT_VERSION,10,10,170,15,SS_NOPREFIX + LTEXT "Copyright",IDC_ABOUT_COPYRIGHT,10,30,210,40 + DEFPUSHBUTTON "OK",IDOK,195,6,30,11,WS_GROUP +END + +IDD_NHTEXT DIALOGEX 0, 0, 172, 178 +STYLE DS_SETFOREGROUND | WS_POPUP | WS_THICKFRAME +EXSTYLE WS_EX_STATICEDGE +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,54,163,50,14 + EDITTEXT IDC_TEXT_CONTROL,0,0,170,160,ES_MULTILINE | + ES_OEMCONVERT | ES_READONLY | WS_VSCROLL | WS_HSCROLL +END + +IDD_MENU DIALOGEX 0, 0, 187, 153 +STYLE WS_POPUP | WS_CLIPSIBLINGS | WS_THICKFRAME +EXSTYLE WS_EX_CLIENTEDGE | WS_EX_CONTROLPARENT | WS_EX_STATICEDGE +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,7,132,50,14,BS_FLAT + PUSHBUTTON "Cancel",IDCANCEL,130,132,50,14,BS_FLAT + LISTBOX IDC_MENU_LIST,10,10,170,55,LBS_SORT | WS_TABSTOP + EDITTEXT IDC_MENU_TEXT,10,70,170,60,ES_MULTILINE | ES_OEMCONVERT | + ES_READONLY | WS_VSCROLL | WS_HSCROLL +END + +IDD_GETLIN DIALOG DISCARDABLE 0, 0, 131, 29 +STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Question?" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,0,15,65,14 + PUSHBUTTON "Cancel",IDCANCEL,65,15,65,14 + EDITTEXT IDC_GETLIN_EDIT,0,0,130,13,ES_AUTOHSCROLL +END + +IDD_EXTCMD DIALOG DISCARDABLE 0, 0, 137, 117 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Extended Commands" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,80,7,50,14 + PUSHBUTTON "Cancel",IDCANCEL,80,24,50,14 + LISTBOX IDC_EXTCMD_LIST,7,7,65,103,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_TABSTOP +END + +IDD_PLAYER_SELECTOR DIALOG DISCARDABLE 0, 0, 152, 169 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "What are you?" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "Play",IDOK,7,148,66,14 + PUSHBUTTON "Quit",IDCANCEL,79,148,66,14 + LTEXT "Name:",IDC_STATIC,7,8,25,10 + EDITTEXT IDC_PLSEL_NAME,40,7,105,12,ES_AUTOHSCROLL | ES_READONLY | + NOT WS_TABSTOP + GROUPBOX "Role",IDC_STATIC,7,21,138,30 + CONTROL "Random",IDC_PLSEL_ROLE_RANDOM,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,14,34,40,10 + COMBOBOX IDC_PLSEL_ROLE_LIST,63,33,75,50,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + GROUPBOX "Race",IDC_STATIC,7,51,138,30 + CONTROL "Random",IDC_PLSEL_RACE_RANDOM,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,14,63,40,10 + COMBOBOX IDC_PLSEL_RACE_LIST,63,62,75,45,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + GROUPBOX "Gender",IDC_STATIC,7,81,138,30 + CONTROL "Random",IDC_PLSEL_GENDER_RANDOM,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,14,93,40,10 + COMBOBOX IDC_PLSEL_GENDER_LIST,63,92,75,40,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + GROUPBOX "Alignment",IDC_STATIC,7,111,138,30 + CONTROL "Random",IDC_PLSEL_ALIGN_RANDOM,"Button",BS_AUTOCHECKBOX | + WS_TABSTOP,13,123,40,10 + COMBOBOX IDC_PLSEL_ALIGN_LIST,63,122,75,45,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP +END + +IDD_NHRIP DIALOGEX 0, 0, 281, 209 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Here lies..." +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,82,188,50,14 +END + +IDD_SPLASH DIALOGEX 0, 0, 281, 209 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Welcome to NetHack" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,82,188,50,14 +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#if defined(__BORLANDC__)\r\n" + "LANGUAGE LANG_ENGLISH,SUBLANG_ENGLISH_US\r\n" + "#endif\r\n" + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""resource.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_TILES BITMAP DISCARDABLE "tiles.bmp" +IDB_MENU_SEL BITMAP DISCARDABLE "mnsel.bmp" +IDB_MENU_UNSEL BITMAP DISCARDABLE "mnunsel.bmp" +IDB_PETMARK BITMAP DISCARDABLE "petmark.bmp" +IDB_MENU_SEL_COUNT BITMAP DISCARDABLE "mnselcnt.bmp" +IDB_RIP BITMAP DISCARDABLE "rip.bmp" +IDB_SPLASH BITMAP DISCARDABLE "splash.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_NHTEXT, DIALOG + BEGIN + BOTTOMMARGIN, 177 + END + + IDD_MENU, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 180 + TOPMARGIN, 7 + BOTTOMMARGIN, 146 + END + + IDD_GETLIN, DIALOG + BEGIN + BOTTOMMARGIN, 22 + END + + IDD_EXTCMD, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 130 + TOPMARGIN, 7 + BOTTOMMARGIN, 110 + END + + IDD_PLAYER_SELECTOR, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 145 + TOPMARGIN, 7 + BOTTOMMARGIN, 162 + END + + IDD_NHRIP, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 274 + TOPMARGIN, 7 + BOTTOMMARGIN, 202 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_APP_TITLE "NetHack for Windows - Graphical Interface" + IDC_NETHACKW "NETHACKW" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED +