From 7c49679666e20063d3e01c3939aa58a8bd7d7868 Mon Sep 17 00:00:00 2001 From: "William F. Jolitz" Date: Wed, 2 May 1990 07:41:27 -0800 Subject: [PATCH] 386BSD 0.1 development Work on file usr/othersrc/games/hack/Makequest Work on file usr/othersrc/games/hack/Original_READ_ME Work on file usr/othersrc/games/hack/READ_ME Work on file usr/othersrc/games/hack/alloc.c Work on file usr/othersrc/games/hack/data Work on file usr/othersrc/games/hack/date.h Work on file usr/othersrc/games/hack/def.edog.h Work on file usr/othersrc/games/hack/def.eshk.h Work on file usr/othersrc/games/hack/def.flag.h Work on file usr/othersrc/games/hack/def.func_tab.h Work on file usr/othersrc/games/hack/def.gen.h Work on file usr/othersrc/games/hack/def.gold.h Work on file usr/othersrc/games/hack/def.mkroom.h Work on file usr/othersrc/games/hack/def.monst.h Work on file usr/othersrc/games/hack/def.obj.h Work on file usr/othersrc/games/hack/def.objclass.h Work on file usr/othersrc/games/hack/def.objects.h Work on file usr/othersrc/games/hack/def.permonst.h Work on file usr/othersrc/games/hack/def.rm.h Work on file usr/othersrc/games/hack/def.trap.h Work on file usr/othersrc/games/hack/def.wseg.h Work on file usr/othersrc/games/hack/hack.Decl.c Work on file usr/othersrc/games/hack/hack.bones.c Work on file usr/othersrc/games/hack/hack.c Work on file usr/othersrc/games/hack/hack.do_name.c Work on file usr/othersrc/games/hack/hack.do_wear.c Work on file usr/othersrc/games/hack/hack.dog.c Work on file usr/othersrc/games/hack/hack.eat.c Work on file usr/othersrc/games/hack/hack.engrave.c Work on file usr/othersrc/games/hack/hack.fight.c Work on file usr/othersrc/games/hack/hack.fix Work on file usr/othersrc/games/hack/hack.invent.c Work on file usr/othersrc/games/hack/hack.ioctl.c Work on file usr/othersrc/games/hack/hack.lev.c Work on file usr/othersrc/games/hack/hack.mfndpos.h Work on file usr/othersrc/games/hack/hack.mhitu.c Work on file usr/othersrc/games/hack/hack.mklev.c Work on file usr/othersrc/games/hack/hack.mkmaze.c Work on file usr/othersrc/games/hack/hack.mkobj.c Work on file usr/othersrc/games/hack/hack.mkshop.c Work on file usr/othersrc/games/hack/hack.monst.c Work on file usr/othersrc/games/hack/hack.o_init.c Work on file usr/othersrc/games/hack/hack.objnam.c Work on file usr/othersrc/games/hack/hack.onames.h Work on file usr/othersrc/games/hack/hack.options.c Work on file usr/othersrc/games/hack/hack.potion.c Work on file usr/othersrc/games/hack/hack.pri.c Work on file usr/othersrc/games/hack/hack.rip.c Work on file usr/othersrc/games/hack/hack.rumors.c Work on file usr/othersrc/games/hack/hack.save.c Work on file usr/othersrc/games/hack/hack.search.c Work on file usr/othersrc/games/hack/hack.sh Work on file usr/othersrc/games/hack/hack.shknam.c Work on file usr/othersrc/games/hack/hack.steal.c Work on file usr/othersrc/games/hack/hack.termcap.c Work on file usr/othersrc/games/hack/hack.timeout.c Work on file usr/othersrc/games/hack/hack.topl.c Work on file usr/othersrc/games/hack/hack.track.c Work on file usr/othersrc/games/hack/hack.trap.c Work on file usr/othersrc/games/hack/hack.u_init.c Work on file usr/othersrc/games/hack/hack.unix.c Work on file usr/othersrc/games/hack/hack.vault.c Work on file usr/othersrc/games/hack/hack.version.c Work on file usr/othersrc/games/hack/hack.wield.c Work on file usr/othersrc/games/hack/hack.wizard.c Work on file usr/othersrc/games/hack/hack.worm.c Work on file usr/othersrc/games/hack/hack.worn.c Work on file usr/othersrc/games/hack/hack.zap.c Work on file usr/othersrc/games/hack/help Work on file usr/othersrc/games/hack/hh Work on file usr/othersrc/games/hack/rnd.c Work on file usr/othersrc/games/hack/rumors Co-Authored-By: Lynne Greer Jolitz Synthesized-from: 386BSD-0.1 --- usr/othersrc/games/hack/Makequest | 196 +++++ usr/othersrc/games/hack/Original_READ_ME | 61 ++ usr/othersrc/games/hack/READ_ME | 92 +++ usr/othersrc/games/hack/alloc.c | 47 ++ usr/othersrc/games/hack/data | 232 ++++++ usr/othersrc/games/hack/date.h | 2 + usr/othersrc/games/hack/def.edog.h | 12 + usr/othersrc/games/hack/def.eshk.h | 24 + usr/othersrc/games/hack/def.flag.h | 42 ++ usr/othersrc/games/hack/def.func_tab.h | 16 + usr/othersrc/games/hack/def.gen.h | 15 + usr/othersrc/games/hack/def.gold.h | 12 + usr/othersrc/games/hack/def.mkroom.h | 26 + usr/othersrc/games/hack/def.monst.h | 60 ++ usr/othersrc/games/hack/def.obj.h | 48 ++ usr/othersrc/games/hack/def.objclass.h | 60 ++ usr/othersrc/games/hack/def.objects.h | 289 ++++++++ usr/othersrc/games/hack/def.permonst.h | 25 + usr/othersrc/games/hack/def.rm.h | 52 ++ usr/othersrc/games/hack/def.trap.h | 27 + usr/othersrc/games/hack/def.wseg.h | 13 + usr/othersrc/games/hack/hack.Decl.c | 43 ++ usr/othersrc/games/hack/hack.bones.c | 95 +++ usr/othersrc/games/hack/hack.c | 798 +++++++++++++++++++++ usr/othersrc/games/hack/hack.do_name.c | 289 ++++++++ usr/othersrc/games/hack/hack.do_wear.c | 336 +++++++++ usr/othersrc/games/hack/hack.dog.c | 413 +++++++++++ usr/othersrc/games/hack/hack.eat.c | 459 ++++++++++++ usr/othersrc/games/hack/hack.engrave.c | 306 ++++++++ usr/othersrc/games/hack/hack.fight.c | 358 ++++++++++ usr/othersrc/games/hack/hack.fix | 113 +++ usr/othersrc/games/hack/hack.invent.c | 863 +++++++++++++++++++++++ usr/othersrc/games/hack/hack.ioctl.c | 53 ++ usr/othersrc/games/hack/hack.lev.c | 285 ++++++++ usr/othersrc/games/hack/hack.mfndpos.h | 12 + usr/othersrc/games/hack/hack.mhitu.c | 363 ++++++++++ usr/othersrc/games/hack/hack.mklev.c | 741 +++++++++++++++++++ usr/othersrc/games/hack/hack.mkmaze.c | 136 ++++ usr/othersrc/games/hack/hack.mkobj.c | 148 ++++ usr/othersrc/games/hack/hack.mkshop.c | 274 +++++++ usr/othersrc/games/hack/hack.monst.c | 79 +++ usr/othersrc/games/hack/hack.o_init.c | 160 +++++ usr/othersrc/games/hack/hack.objnam.c | 547 ++++++++++++++ usr/othersrc/games/hack/hack.onames.h | 227 ++++++ usr/othersrc/games/hack/hack.options.c | 203 ++++++ usr/othersrc/games/hack/hack.potion.c | 386 ++++++++++ usr/othersrc/games/hack/hack.pri.c | 660 +++++++++++++++++ usr/othersrc/games/hack/hack.rip.c | 81 +++ usr/othersrc/games/hack/hack.rumors.c | 63 ++ usr/othersrc/games/hack/hack.save.c | 238 +++++++ usr/othersrc/games/hack/hack.search.c | 133 ++++ usr/othersrc/games/hack/hack.sh | 14 + usr/othersrc/games/hack/hack.shknam.c | 140 ++++ usr/othersrc/games/hack/hack.steal.c | 203 ++++++ usr/othersrc/games/hack/hack.termcap.c | 276 ++++++++ usr/othersrc/games/hack/hack.timeout.c | 62 ++ usr/othersrc/games/hack/hack.topl.c | 192 +++++ usr/othersrc/games/hack/hack.track.c | 38 + usr/othersrc/games/hack/hack.trap.c | 447 ++++++++++++ usr/othersrc/games/hack/hack.u_init.c | 357 ++++++++++ usr/othersrc/games/hack/hack.unix.c | 430 +++++++++++ usr/othersrc/games/hack/hack.vault.c | 259 +++++++ usr/othersrc/games/hack/hack.version.c | 16 + usr/othersrc/games/hack/hack.wield.c | 99 +++ usr/othersrc/games/hack/hack.wizard.c | 189 +++++ usr/othersrc/games/hack/hack.worm.c | 183 +++++ usr/othersrc/games/hack/hack.worn.c | 65 ++ usr/othersrc/games/hack/hack.zap.c | 642 +++++++++++++++++ usr/othersrc/games/hack/help | 132 ++++ usr/othersrc/games/hack/hh | 55 ++ usr/othersrc/games/hack/rnd.c | 30 + usr/othersrc/games/hack/rumors | 505 +++++++++++++ 72 files changed, 14547 insertions(+) create mode 100644 usr/othersrc/games/hack/Makequest create mode 100644 usr/othersrc/games/hack/Original_READ_ME create mode 100644 usr/othersrc/games/hack/READ_ME create mode 100644 usr/othersrc/games/hack/alloc.c create mode 100644 usr/othersrc/games/hack/data create mode 100644 usr/othersrc/games/hack/date.h create mode 100644 usr/othersrc/games/hack/def.edog.h create mode 100644 usr/othersrc/games/hack/def.eshk.h create mode 100644 usr/othersrc/games/hack/def.flag.h create mode 100644 usr/othersrc/games/hack/def.func_tab.h create mode 100644 usr/othersrc/games/hack/def.gen.h create mode 100644 usr/othersrc/games/hack/def.gold.h create mode 100644 usr/othersrc/games/hack/def.mkroom.h create mode 100644 usr/othersrc/games/hack/def.monst.h create mode 100644 usr/othersrc/games/hack/def.obj.h create mode 100644 usr/othersrc/games/hack/def.objclass.h create mode 100644 usr/othersrc/games/hack/def.objects.h create mode 100644 usr/othersrc/games/hack/def.permonst.h create mode 100644 usr/othersrc/games/hack/def.rm.h create mode 100644 usr/othersrc/games/hack/def.trap.h create mode 100644 usr/othersrc/games/hack/def.wseg.h create mode 100644 usr/othersrc/games/hack/hack.Decl.c create mode 100644 usr/othersrc/games/hack/hack.bones.c create mode 100644 usr/othersrc/games/hack/hack.c create mode 100644 usr/othersrc/games/hack/hack.do_name.c create mode 100644 usr/othersrc/games/hack/hack.do_wear.c create mode 100644 usr/othersrc/games/hack/hack.dog.c create mode 100644 usr/othersrc/games/hack/hack.eat.c create mode 100644 usr/othersrc/games/hack/hack.engrave.c create mode 100644 usr/othersrc/games/hack/hack.fight.c create mode 100644 usr/othersrc/games/hack/hack.fix create mode 100644 usr/othersrc/games/hack/hack.invent.c create mode 100644 usr/othersrc/games/hack/hack.ioctl.c create mode 100644 usr/othersrc/games/hack/hack.lev.c create mode 100644 usr/othersrc/games/hack/hack.mfndpos.h create mode 100644 usr/othersrc/games/hack/hack.mhitu.c create mode 100644 usr/othersrc/games/hack/hack.mklev.c create mode 100644 usr/othersrc/games/hack/hack.mkmaze.c create mode 100644 usr/othersrc/games/hack/hack.mkobj.c create mode 100644 usr/othersrc/games/hack/hack.mkshop.c create mode 100644 usr/othersrc/games/hack/hack.monst.c create mode 100644 usr/othersrc/games/hack/hack.o_init.c create mode 100644 usr/othersrc/games/hack/hack.objnam.c create mode 100644 usr/othersrc/games/hack/hack.onames.h create mode 100644 usr/othersrc/games/hack/hack.options.c create mode 100644 usr/othersrc/games/hack/hack.potion.c create mode 100644 usr/othersrc/games/hack/hack.pri.c create mode 100644 usr/othersrc/games/hack/hack.rip.c create mode 100644 usr/othersrc/games/hack/hack.rumors.c create mode 100644 usr/othersrc/games/hack/hack.save.c create mode 100644 usr/othersrc/games/hack/hack.search.c create mode 100644 usr/othersrc/games/hack/hack.sh create mode 100644 usr/othersrc/games/hack/hack.shknam.c create mode 100644 usr/othersrc/games/hack/hack.steal.c create mode 100644 usr/othersrc/games/hack/hack.termcap.c create mode 100644 usr/othersrc/games/hack/hack.timeout.c create mode 100644 usr/othersrc/games/hack/hack.topl.c create mode 100644 usr/othersrc/games/hack/hack.track.c create mode 100644 usr/othersrc/games/hack/hack.trap.c create mode 100644 usr/othersrc/games/hack/hack.u_init.c create mode 100644 usr/othersrc/games/hack/hack.unix.c create mode 100644 usr/othersrc/games/hack/hack.vault.c create mode 100644 usr/othersrc/games/hack/hack.version.c create mode 100644 usr/othersrc/games/hack/hack.wield.c create mode 100644 usr/othersrc/games/hack/hack.wizard.c create mode 100644 usr/othersrc/games/hack/hack.worm.c create mode 100644 usr/othersrc/games/hack/hack.worn.c create mode 100644 usr/othersrc/games/hack/hack.zap.c create mode 100644 usr/othersrc/games/hack/help create mode 100644 usr/othersrc/games/hack/hh create mode 100644 usr/othersrc/games/hack/rnd.c create mode 100644 usr/othersrc/games/hack/rumors diff --git a/usr/othersrc/games/hack/Makequest b/usr/othersrc/games/hack/Makequest new file mode 100644 index 0000000000..9271c2841c --- /dev/null +++ b/usr/othersrc/games/hack/Makequest @@ -0,0 +1,196 @@ +# Hack or Quest Makefile. + +# on some systems the termcap library is in -ltermcap +TERMLIB = -ltermlib + + +# make hack +GAME = quest +GAMEDIR = /usr/games/lib/questdir +CFLAGS = -g -DQUEST +HACKCSRC = hack.Decl.c\ + hack.apply.c hack.bones.c hack.c hack.cmd.c hack.do.c\ + hack.do_name.c hack.do_wear.c hack.dog.c hack.eat.c hack.end.c\ + hack.engrave.c hack.fight.c hack.invent.c hack.ioctl.c\ + hack.lev.c hack.main.c hack.makemon.c hack.mhitu.c\ + hack.mklev.c hack.mkmaze.c hack.mkobj.c hack.mkshop.c\ + hack.mon.c hack.monst.c hack.o_init.c hack.objnam.c\ + hack.options.c hack.pager.c hack.potion.c hack.pri.c\ + hack.read.c hack.rip.c hack.rumors.c hack.save.c\ + hack.search.c hack.shk.c hack.shknam.c hack.steal.c\ + hack.termcap.c hack.timeout.c hack.topl.c\ + hack.track.c hack.trap.c hack.tty.c hack.unix.c\ + hack.u_init.c hack.vault.c\ + hack.wield.c hack.wizard.c hack.worm.c hack.worn.c hack.zap.c\ + hack.version.c rnd.c alloc.c + +CSOURCES = $(HACKCSRC) makedefs.c + +HSOURCES = hack.h hack.mfndpos.h config.h\ + def.edog.h def.eshk.h def.flag.h def.func_tab.h def.gold.h\ + def.mkroom.h\ + def.monst.h def.obj.h def.objclass.h def.objects.h\ + def.permonst.h def.rm.h def.trap.h def.wseg.h + +SOURCES = $(CSOURCES) $(HSOURCES) + +AUX = data help hh rumors hack.6 hack.sh + +DISTR = $(SOURCES) $(AUX) READ_ME Makefile date.h hack.onames.h + +HOBJ = hack.Decl.o hack.apply.o hack.bones.o hack.o hack.cmd.o hack.do.o\ + hack.do_name.o hack.do_wear.o hack.dog.o hack.eat.o hack.end.o\ + hack.engrave.o hack.fight.o hack.invent.o hack.ioctl.o\ + hack.lev.o hack.main.o hack.makemon.o hack.mhitu.o hack.mklev.o\ + hack.mkmaze.o hack.mkobj.o hack.mkshop.o hack.mon.o\ + hack.monst.o hack.o_init.o hack.objnam.o hack.options.o\ + hack.pager.o hack.potion.o hack.pri.o\ + hack.read.o hack.rip.o hack.rumors.o hack.save.o\ + hack.search.o hack.shk.o hack.shknam.o hack.steal.o\ + hack.termcap.o hack.timeout.o hack.topl.o\ + hack.track.o hack.trap.o\ + hack.tty.o hack.unix.o hack.u_init.o hack.vault.o hack.wield.o\ + hack.wizard.o hack.worm.o hack.worn.o hack.zap.o\ + hack.version.o rnd.o alloc.o + +$(GAME): $(HOBJ) Makefile + @echo "Loading ..." + @ld -X -o $(GAME) /lib/crt0.o $(HOBJ) $(TERMLIB) -lc + +all: $(GAME) lint + @echo "Done." + +makedefs: makedefs.c + cc -o makedefs makedefs.c + + +hack.onames.h: makedefs def.objects.h + makedefs > hack.onames.h + +lint: +# lint cannot have -p here because (i) capitals are meaningful: +# [Ww]izard, (ii) identifiers may coincide in the first six places: +# doweararm() versus dowearring(). +# _flsbuf comes from , a bug in the system libraries. + @echo lint -axbh -DLINT ... + @lint -axbh -DLINT $(HACKCSRC) | sed '/_flsbuf/d' + + +diff: + @- for i in $(SOURCES) $(AUX) ; do \ + cmp -s $$i $D/$$i || \ + ( echo diff $D/$$i $$i ; diff $D/$$i $$i ; echo ) ; done + +distribution: Makefile + @- for i in READ_ME $(SOURCES) $(AUX) Makefile date.h hack.onames.h\ + ; do \ + cmp -s $$i $D/$$i || \ + ( echo cp $$i $D ; cp $$i $D ) ; done +# the distribution directory also contains the empty files perm and record. + + +install: + rm -f $(GAMEDIR)/$(GAME) + cp $(GAME) $(GAMEDIR)/$(GAME) + chmod 04511 $(GAMEDIR)/$(GAME) + rm -f $(GAMEDIR)/bones* +# cp hack.6 /usr/man/man6 + +clean: + rm -f *.o + + +depend: +# For the moment we are lazy and disregard /usr/include files because +# the sources contain them conditionally. Perhaps we should use cpp. +# ( /bin/grep '^#[ ]*include' $$i | sed -n \ +# -e 's,<\(.*\)>,"/usr/include/\1",' \ +# + for i in ${CSOURCES}; do \ + ( /bin/grep '^#[ ]*include[ ]*"' $$i | sed -n \ + -e 's/[^"]*"\([^"]*\)".*/\1/' \ + -e H -e '$$g' -e '$$s/\n/ /g' \ + -e '$$s/.*/'$$i': &/' -e '$$s/\.c:/.o:/p' \ + >> makedep); done + for i in ${HSOURCES}; do \ + ( /bin/grep '^#[ ]*include[ ]*"' $$i | sed -n \ + -e 's/[^"]*"\([^"]*\)".*/\1/' \ + -e H -e '$$g' -e '$$s/\n/ /g' \ + -e '$$s/.*/'$$i': &\ + touch '$$i/p \ + >> makedep); done + @echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep + @echo '$$r makedep' >>eddep + @echo 'w' >>eddep + @cp Makefile Makefile.bak + ed - Makefile < eddep + @rm -f eddep makedep + @echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile + @echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile + @echo '# see make depend above' >> Makefile + - diff Makefile Makefile.bak + @rm -f Makefile.bak + +# DO NOT DELETE THIS LINE + +hack.Decl.o: hack.h def.mkroom.h +hack.apply.o: hack.h def.edog.h def.mkroom.h +hack.bones.o: hack.h +hack.o: hack.h +hack.cmd.o: hack.h def.func_tab.h +hack.do.o: hack.h +hack.do_name.o: hack.h +hack.do_wear.o: hack.h +hack.dog.o: hack.h hack.mfndpos.h def.edog.h def.mkroom.h +hack.eat.o: hack.h +hack.end.o: hack.h +hack.engrave.o: hack.h +hack.fight.o: hack.h +hack.invent.o: hack.h def.wseg.h +hack.ioctl.o: config.h +hack.lev.o: hack.h def.mkroom.h def.wseg.h +hack.main.o: hack.h +hack.makemon.o: hack.h +hack.mhitu.o: hack.h +hack.mklev.o: hack.h def.mkroom.h +hack.mkmaze.o: hack.h def.mkroom.h +hack.mkobj.o: hack.h +hack.mkshop.o: hack.h def.mkroom.h def.eshk.h +hack.mon.o: hack.h hack.mfndpos.h +hack.monst.o: hack.h def.eshk.h +hack.o_init.o: config.h def.objects.h hack.onames.h +hack.objnam.o: hack.h +hack.options.o: config.h hack.h +hack.pager.o: hack.h +hack.potion.o: hack.h +hack.pri.o: hack.h def.wseg.h +hack.read.o: hack.h +hack.rip.o: hack.h +hack.rumors.o: hack.h +hack.save.o: hack.h +hack.search.o: hack.h +hack.shk.o: hack.h hack.mfndpos.h def.mkroom.h def.eshk.h +hack.shknam.o: hack.h +hack.steal.o: hack.h +hack.termcap.o: config.h def.flag.h +hack.timeout.o: hack.h +hack.topl.o: hack.h +hack.track.o: hack.h +hack.trap.o: hack.h def.mkroom.h +hack.tty.o: hack.h +hack.unix.o: hack.h def.mkroom.h +hack.u_init.o: hack.h +hack.vault.o: hack.h def.mkroom.h +hack.wield.o: hack.h +hack.wizard.o: hack.h +hack.worm.o: hack.h def.wseg.h +hack.worn.o: hack.h +hack.zap.o: hack.h +hack.version.o: date.h +hack.h: config.h def.objclass.h def.monst.h def.gold.h def.trap.h def.obj.h def.flag.h def.rm.h def.permonst.h hack.onames.h + touch hack.h +def.objects.h: config.h def.objclass.h + touch def.objects.h +# DEPENDENCIES MUST END AT END OF FILE +# IF YOU PUT STUFF HERE IT WILL GO AWAY +# see make depend above diff --git a/usr/othersrc/games/hack/Original_READ_ME b/usr/othersrc/games/hack/Original_READ_ME new file mode 100644 index 0000000000..9d2070be09 --- /dev/null +++ b/usr/othersrc/games/hack/Original_READ_ME @@ -0,0 +1,61 @@ +This is export hack, my first semester programming project. + +To set it up for your system, you will have to do the following: + 1: create a hack uid, to own the top ten list, etc. + 2: create a hack directory "/usr/lib/game/hack" is the default. + 2.5: make the directory 700 mode. /* sav files go in there...*/ + 3: modify hack.main.c to use the new directory. + 4: modify hack.main.c so it uses the new hack gid. Gid accounts can +go into magic mode without the password, can get cores with ^G, etc. +(make sure gid isn't checked anywhere else...) + 5: recompile hack. + 6: put it in games after making it set-uid hack. + 8: fix the bugs I undobtedly left in it. + 9: tell me what you think of it. + + Hack uses the UCB file /etc/termcap to get your terminal escape codes. +If you don't use it, you will have to make extensive changes to hack.pri.c + +If you find any bugs (That you think I don't know about), or have any +awesome new changes (Like a better save (One that works!)), or have ANY +questions, write me + Jay Fenlason + 29 East St. + Sudbury Mass. + 01776 + +or call me at (617) 443-5036. Since I have both a modem and a teen-age +sister, Good Luck. + + +Hack is split (roughly) into several source files that do different things. +I have tried to fit all the procedures having to do with a certain segment +of the game into a single file, but the job is not the best in the world. +The rough splits are: + +hack.c General random stuff and things I never got around to moving. +hack.main.c main() and other random procedures, also the lock file stuff. +hack.mon.c Monsters, moving, attacking, etc. +hack.do.c drink, eat, read, wield, save, etc. +hack.do1.c zap, wear, remove, etc... +hack.pri.c stuff having to do with the screen, most of the terminal + independant stuff is in here. +hack.lev.c temp files and calling of mklev. + +Because of the peculiar restraints on our system, I make mklev (create +a level) a separate procedure execd by hack when needed. The source for +mklev is (Naturaly) mklev.c. You may want to put mklev back into hack. +Good luck. + +Most of hack was written by me, with help from + Kenny Woodland (KW) (general random things including + the original BUZZ()) + Mike Thome (MT) (The original chamelian) + and Jon Payne (JP) (The original lock file kludge and + the massive CURS()) + +This entire program would not have been possible without the SFSU Logo +Workshop. I am eternally grateful to all of our students (Especially K.L.), +without whom I would never have seen Rogue. I am especially grateful to +Mike Clancy, without whose generous help I would never have gotten to play +ROGUE. diff --git a/usr/othersrc/games/hack/READ_ME b/usr/othersrc/games/hack/READ_ME new file mode 100644 index 0000000000..cfe6ca2fe3 --- /dev/null +++ b/usr/othersrc/games/hack/READ_ME @@ -0,0 +1,92 @@ +Hack is a display oriented dungeons & dragons - like game. +Both display and command structure resemble rogue. +(For a game with the same structure but entirely different display - +a real cave instead of dull rectangles - try Quest) + +Hack was originally written by Jay Fenlason (at lincolnsudbury: + 29 East St., Sudbury Mass., 01776) with help from + Kenny Woodland, Mike Thome and Jon Payne. +Basically it was an implementation of Rogue, however, with 52+ instead of 26 + monster types. +The current version is more than thrice as large (with such new features as + the dog, the long worms, the shops, etc.) and almost entirely rewritten + (only the display routines are the original ones - I must rewrite these + too one day; especially when you are blind strange things still happen). + +Files for hack: + hack The actual game + record Top 100 list (just start with an empty file) + news Tells about recent changes in hack, or bugs found ... + (Just start with no news file.) + data Auxiliary file used by hack to give you the names + and sometimes some more information on the + objects and monsters. + help Introductory information (no doubt outdated). + hh Compactified version of help. + perm An empty file used for locking purposes. + rumors Texts for fortune cookies. + (Some of these contain information on the game, + others are just plain stupid. Additional rumors + are appreciated.) + hack.sh A shell script. + (We have hack.sh in /usr/games/hack and + hack in /usr/games/lib/hackdir/hack and all the other + hack stuff in /usr/games/lib/hackdir - perhaps this + will make the script clear. + There is no need for you to use it.) + READ_ME This file. + Original_READ_ME Jay Fenlason's READ_ME + +System files used: + /etc/termcap Used in conjunction with the environment variable + $TERM. + /bin/cat + /usr/ucb/more + /bin/sh Used when $SHELL is undefined. + +How to install hack: +0. Compile the sources. Perhaps you should first look at the file config.h + and define BSD if you are on a BSDtype system, + define STUPID if your C-compiler chokes on complicated expressions. + Make sure schar and uchar represent signed and unsigned types. + If your C compiler doesnt allow initialization of bit fields + change Bitfield. When config.h looks reasonable, say 'make'. + (Perhaps you have to change TERMLIB in the makefile.) +1. If it didnt exist already, introduce a loginname `play' . +2. The program hack resides in a directory so that it is executable + for everybody and is suid play: + ---s--s--x 1 play 206848 Apr 3 00:17 hack + Perhaps you wish to restrict playing to certain hours, or have games + running under nice; in that case you might write a program play.c + such that the program play is suid play and executable for everybody + while all the games in /usr/games are readable or executable for + play only; all the program play does is asking for the name of a game, + checking that time-of-day and system load do not forbid playing, + and then executing the game. Thus: + -r-sr-sr-x 1 play 13312 May 24 12:52 play + ---x------ 1 play 206848 Apr 3 00:17 hack + If you are worried about security you might let play do + chroot("/usr/games") so that no player can get access to the rest + of the system via shell escapes and the likes. + If you #define SECURE in config.h then hack will not setuid(getuid()) + before executing a chdir(). Hack will always do setuid(getuid()) with + a fork. If you do not define UNIX then hack will not fork. +3. The rest of the stuff belonging to hack sits in a subdirectory hackdir + (on our system /usr/games/lib/hackdir) with modes + drwx------ 3 play 1024 Aug 9 09:03 hackdir + Here all the temporary files will be created (with names like xlock.17 + or user.5). +4. If you are not really short on file space, creating a subdirectory + hackdir/save (modes again drwx------) will enable users to save their + unfinished games. + +The program hack is called +$ hack [-d hackdir] [maxnrofplayers] +(for playing) or +$ hack [-d hackdir] -s [listofusers | limit | all] +(for seeing part of the scorelist). +The shell file hack (in this kit called hack.sh) takes care of +calling hack with the right arguments. + +Send complaints, bug reports, suggestions for improvements to +mcvax!aeb - in real life Andries Brouwer. diff --git a/usr/othersrc/games/hack/alloc.c b/usr/othersrc/games/hack/alloc.c new file mode 100644 index 0000000000..d94bf8b903 --- /dev/null +++ b/usr/othersrc/games/hack/alloc.c @@ -0,0 +1,47 @@ +/* alloc.c - version 1.0.2 */ +#ifdef LINT + +/* + a ridiculous definition, suppressing + "possible pointer alignment problem" for (long *) malloc() + "enlarg defined but never used" + "ftell defined (in ) but never used" + from lint +*/ +#include +long * +alloc(n) unsigned n; { +long dummy = ftell(stderr); + if(n) dummy = 0; /* make sure arg is used */ + return(&dummy); +} + +#else + +extern char *malloc(); +extern char *realloc(); + +long * +alloc(lth) +register unsigned lth; +{ + register char *ptr; + + if(!(ptr = malloc(lth))) + panic("Cannot get %d bytes", lth); + return((long *) ptr); +} + +long * +enlarge(ptr,lth) +register char *ptr; +register unsigned lth; +{ + register char *nptr; + + if(!(nptr = realloc(ptr,lth))) + panic("Cannot reallocate %d bytes", lth); + return((long *) nptr); +} + +#endif LINT diff --git a/usr/othersrc/games/hack/data b/usr/othersrc/games/hack/data new file mode 100644 index 0000000000..5d8d509b0f --- /dev/null +++ b/usr/othersrc/games/hack/data @@ -0,0 +1,232 @@ + Hack & Quest data file - version 1.0.3 +@ human (or you) +- a wall +| a wall ++ a door +. the floor of a room + a dark part of a room +# a corridor +} water filled area +< the staircase to the previous level +> the staircase to the next level +^ a trap +$ a pile, pot or chest of gold +%% a piece of food +! a potion +* a gem +? a scroll += a ring +/ a wand +[ a suit of armor +) a weapon +( a useful item (camera, key, rope etc.) +0 an iron ball +_ an iron chain +` an enormous rock +" an amulet +, a trapper +: a chameleon +; a giant eel +' a lurker above +& a demon +A a giant ant +B a giant bat +C a centaur; + Of all the monsters put together by the Greek imagination + the Centaurs (Kentauroi) constituted a class in themselves. + Despite a strong streak of sensuality in their make-up, + their normal behaviour was moral, and they took a kindly + thought of man's welfare. The attempted outrage of Nessos on + Deianeira, and that of the whole tribe of Centaurs on the + Lapith women, are more than offset by the hospitality of + Pholos and by the wisdom of Cheiron, physician, prophet, + lyrist, and the instructor of Achilles. Further, the Cen- + taurs were peculiar in that their nature, which united the + body of a horse with the trunk and head of a man, involved + an unthinkable duplication of vital organs and important + members. So grotesque a combination seems almost un-Greek. + These strange creatures were said to live in the caves and + clefts of the mountains, myths associating them especially + with the hills of Thessaly and the range of Erymanthos. + [Mythology of all races, Vol. 1, pp. 270-271] +D a dragon; + In the West the dragon was the natural enemy of man. Although + preferring to live in bleak and desolate regions, whenever it was + seen among men it left in its wake a trail of destruction and + disease. Yet any attempt to slay this beast was a perilous under- + taking. For the dragon's assailant had to contend not only with + clouds of sulphurous fumes pouring from its fire-breathing nos- + trils, but also with the thrashings of its tail, the most deadly + part of its serpent-like body. + [From: Mythical Beasts by Deirdre Headon (The Leprechaun Library)] +E a floating eye +F a freezing sphere +G a gnome; + ... And then a gnome came by, carrying a bundle, an old fellow + three times as large as an imp and wearing clothes of a sort, + especially a hat. And he was clearly just as frightened as the + imps though he could not go so fast. Ramon Alonzo saw that there + must be some great trouble that was vexing magical things; and, + since gnomes speak the language of men, and will answer if spoken + to gently, he raised his hat, and asked of the gnome his name. + The gnome did not stop his hasty shuffle a moment as he answered + 'Alaraba' and grabbed the rim of his hat but forgot to doff it. + 'What is the trouble, Alaraba?' said Ramon Alonzo. + 'White magic. Run!' said the gnome ... + [From: The Charwoman's Shadow, by Lord Dunsany.] +H a hobgoblin; + Hobgoblin. Used by the Puritans and in later times for + wicked goblin spirits, as in Bunyan's 'Hobgoblin nor foul + friend', but its more correct use is for the friendly spir- + its of the brownie type. In 'A midsummer night's dream' a + fairy says to Shakespeare's Puck: + Those that Hobgoblin call you, and sweet Puck, + You do their work, and they shall have good luck: + Are you not he? + and obviously Puck would not wish to be called a hobgoblin + if that was an ill-omened word. + Hobgoblins are on the whole, good-humoured and ready to be + helpful, but fond of practical joking, and like most of the + fairies rather nasty people to annoy. Boggarts hover on the + verge of hobgoblindom. Bogles are just over the edge. + One Hob mentioned by Henderson, was Hob Headless who haunted + the road between Hurworth and Neasham, but could not cross + the little river Kent, which flowed into the Tess. He was + exorcised and laid under a large stone by the roadside for + ninety-nine years and a day. If anyone was so unwary as to + sit on that stone, he would be unable to quit it for ever. + The ninety-nine years is nearly up, so trouble may soon be + heard of on the road between Hurworth and Neasham. + [Katharine Briggs, A dictionary of Fairies] +I an invisible stalker +J a jackal +K a kobold +L a leprechaun; + The Irish Leprechaun is the Faeries' shoemaker and is known + under various names in different parts of Ireland: Cluri- + caune in Cork, Lurican in Kerry, Lurikeen in Kildare and Lu- + rigadaun in Tipperary. Although he works for the Faeries, + the Leprechaun is not of the same species. He is small, has + dark skin and wears strange clothes. His nature has some- + thing of the manic-depressive about it: first he is quite + happy, whistling merrily as he nails a sole on to a shoe; a + few minutes later, he is sullen and morose, drunk on his + home-made heather ale. The Leprechaun's two great loves are + tobacco and whiskey, and he is a first-rate con-man, impos- + sible to out-fox. No one, no matter how clever, has ever + managed to cheat him out of his hidden pot of gold or his + magic shilling. At the last minute he always thinks of some + way to divert his captor's attention and vanishes in the + twinkling of an eye. + [From: A Field Guide to the Little People + by Nancy Arrowsmith & George Moorse. ] +M a mimic +N a nymph +O an orc +P a purple worm +Q a quasit +R a rust monster +S a snake +T a troll +U an umber hulk +V a vampire +W a wraith +X a xorn +Y a yeti +Z a zombie +a an acid blob +b a giant beetle +c a cockatrice; + Once in a great while, when the positions of the stars are + just right, a seven-year-old rooster will lay an egg. Then, + along will come a snake, to coil around the egg, or a toad, + to squat upon the egg, keeping it warm and helping it to + hatch. When it hatches, out comes a creature called basil- + isk, or cockatrice, the most deadly of all creatures. A sin- + gle glance from its yellow, piercing toad's eyes will kill + both man and beast. Its power of destruction is said to be + so great that sometimes simply to hear its hiss can prove + fatal. Its breath is so venomenous that it causes all vege- + tation to wither. + There is, however, one creature which can withstand the + basilisk's deadly gaze, and this is the weasel. No one knows + why this is so, but although the fierce weasel can slay the + basilisk, it will itself be killed in the struggle. Perhaps + the weasel knows the basilisk's fatal weakness: if it ever + sees its own reflection in a mirror it will perish instant- + ly. But even a dead basilisk is dangerous, for it is said + that merely touching its lifeless body can cause a person to + sicken and die. + [From: Mythical Beasts by Deirdre Headon (The Leprechaun + Library) and other sources. ] +d a dog +e an ettin +f a fog cloud +g a gelatinous cube +h a homunculus +i an imp; + ... imps ... little creatures of two feet high that could + gambol and jump prodigiously; ... + [From: The Charwoman's Shadow, by Lord Dunsany.] + + An 'imp' is an off-shoot or cutting. Thus an 'ymp tree' was + a grafted tree, or one grown from a cutting, not from seed. + 'Imp' properly means a small devil, an off-shoot of Satan, + but the distinction between goblins or bogles and imps from + hell is hard to make, and many in the Celtic countries as + well as the English Puritans regarded all fairies as devils. + The fairies of tradition often hover uneasily between the + ghostly and the diabolic state. + [Katharine Briggs, A dictionary of Fairies] +j a jaguar +k a killer bee +l a leocrotta +m a minotaur +n a nurse +o an owlbear +p a piercer +q a quivering blob +r a giant rat +s a scorpion +t a tengu; + The tengu was the most troublesome creature of Japanese + legend. Part bird and part man, with red beak for a nose + and flashing eyes, the tengu was notorious for stirring up + feuds and prolonging enmity between families. Indeed, the + belligerent tengus were supposed to have been man's first + instructors in the use of arms. + [From: Mythical Beasts by Deirdre Headon + (The Leprechaun Library). ] +u a unicorn; + Men have always sought the elusive unicorn, for the single + twisted horn which projected from its forehead was thought + to be a powerful talisman. It was said that the unicorn had + simply to dip the tip of its horn in a muddy pool for the + water to become pure. Men also believed that to drink from + this horn was a protection against all sickness, and that if + the horn was ground to a powder it would act as an antidote + to all poisons. Less than 200 years ago in France, the horn + of a unicorn was used in a ceremony to test the royal food + for poison. + Although only the size of a small horse, the unicorn is a + very fierce beast, capable of killing an elephant with a + single thrust from its horn. Its fleetness of foot also + makes this solitary creature difficult to capture. However, + it can be tamed and captured by a maiden. Made gentle by the + sight of a virgin, the unicorn can be lured to lay its head + in her lap, and in this docile mood, the maiden may secure + it with a golden rope. + [From: Mythical Beasts by Deirdre Headon + (The Leprechaun Library). ] +v a violet fungi +w a long worm; + From its teeth the crysknife can be manufactured. +~ the tail of a long worm +x a xan; + The xan were animals sent to prick the legs of the Lords of Xibalba. +y a yellow light +z a zruty; + The zruty are wild and gigantic beings, living in the wildernesses + of the Tatra mountains. +1 The wizard of Yendor +2 The mail daemon diff --git a/usr/othersrc/games/hack/date.h b/usr/othersrc/games/hack/date.h new file mode 100644 index 0000000000..9a7ef76888 --- /dev/null +++ b/usr/othersrc/games/hack/date.h @@ -0,0 +1,2 @@ + +char datestring[] = "Tue Jul 23 1985"; diff --git a/usr/othersrc/games/hack/def.edog.h b/usr/othersrc/games/hack/def.edog.h new file mode 100644 index 0000000000..a5c2b4616e --- /dev/null +++ b/usr/othersrc/games/hack/def.edog.h @@ -0,0 +1,12 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.edog.h - version 1.0.2 */ + +struct edog { + long hungrytime; /* at this time dog gets hungry */ + long eattime; /* dog is eating */ + long droptime; /* moment dog dropped object */ + unsigned dropdist; /* dist of drpped obj from @ */ + unsigned apport; /* amount of training */ + long whistletime; /* last time he whistled */ +}; +#define EDOG(mp) ((struct edog *)(&(mp->mextra[0]))) diff --git a/usr/othersrc/games/hack/def.eshk.h b/usr/othersrc/games/hack/def.eshk.h new file mode 100644 index 0000000000..2ebf2804d3 --- /dev/null +++ b/usr/othersrc/games/hack/def.eshk.h @@ -0,0 +1,24 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.eshk.h - version 1.0.2 : added 'following' */ + +#define BILLSZ 200 +struct bill_x { + unsigned bo_id; + unsigned useup:1; + unsigned bquan:7; + unsigned price; /* price per unit */ +}; + +struct eshk { + long int robbed; /* amount stolen by most recent customer */ + boolean following; /* following customer since he owes us sth */ + schar shoproom; /* index in rooms; set by inshop() */ + coord shk; /* usual position shopkeeper */ + coord shd; /* position shop door */ + int shoplevel; /* level of his shop */ + int billct; + struct bill_x bill[BILLSZ]; + int visitct; /* nr of visits by most recent customer */ + char customer[PL_NSIZ]; /* most recent customer */ + char shknam[PL_NSIZ]; +}; diff --git a/usr/othersrc/games/hack/def.flag.h b/usr/othersrc/games/hack/def.flag.h new file mode 100644 index 0000000000..221f33dd91 --- /dev/null +++ b/usr/othersrc/games/hack/def.flag.h @@ -0,0 +1,42 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.flag.h - version 1.0.3 */ + +struct flag { + unsigned ident; /* social security number for each monster */ + unsigned debug:1; /* in debugging mode */ +#define wizard flags.debug + unsigned toplin:2; /* a top line (message) has been printed */ + /* 0: top line empty; 2: no --More-- reqd. */ + unsigned cbreak:1; /* in cbreak mode, rogue format */ + unsigned standout:1; /* use standout for --More-- */ + unsigned nonull:1; /* avoid sending nulls to the terminal */ + unsigned time:1; /* display elapsed 'time' */ + unsigned nonews:1; /* suppress news printing */ + unsigned notombstone:1; + unsigned end_top, end_around; /* describe desired score list */ + unsigned end_own:1; /* idem (list all own scores) */ + unsigned no_rest_on_space:1; /* spaces are ignored */ + unsigned beginner:1; + unsigned female:1; + unsigned invlet_constant:1; /* let objects keep their + inventory symbol */ + unsigned move:1; + unsigned mv:1; + unsigned run:3; /* 0: h (etc), 1: H (etc), 2: fh (etc) */ + /* 3: FH, 4: ff+, 5: ff-, 6: FF+, 7: FF- */ + unsigned nopick:1; /* do not pickup objects */ + unsigned echo:1; /* 1 to echo characters */ + unsigned botl:1; /* partially redo status line */ + unsigned botlx:1; /* print an entirely new bottom line */ + unsigned nscrinh:1; /* inhibit nscr() in pline(); */ + unsigned made_amulet:1; + unsigned no_of_wizards:2;/* 0, 1 or 2 (wizard and his shadow) */ + /* reset from 2 to 1, but never to 0 */ + unsigned moonphase:3; +#define NEW_MOON 0 +#define FULL_MOON 4 + +}; + +extern struct flag flags; + diff --git a/usr/othersrc/games/hack/def.func_tab.h b/usr/othersrc/games/hack/def.func_tab.h new file mode 100644 index 0000000000..63f74d2ef6 --- /dev/null +++ b/usr/othersrc/games/hack/def.func_tab.h @@ -0,0 +1,16 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.func_tab.h - version 1.0.2 */ + +struct func_tab { + char f_char; + int (*f_funct)(); +}; + +extern struct func_tab cmdlist[]; + +struct ext_func_tab { + char *ef_txt; + int (*ef_funct)(); +}; + +extern struct ext_func_tab extcmdlist[]; diff --git a/usr/othersrc/games/hack/def.gen.h b/usr/othersrc/games/hack/def.gen.h new file mode 100644 index 0000000000..f1e44fc989 --- /dev/null +++ b/usr/othersrc/games/hack/def.gen.h @@ -0,0 +1,15 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.gen.h version 1.0.1: added ONCE flag */ + +struct gen { + struct gen *ngen; + xchar gx,gy; + unsigned gflag; /* 037: trap type; 040: SEEN flag */ + /* 0100: ONCE only */ +#define TRAPTYPE 037 +#define SEEN 040 +#define ONCE 0100 +}; +extern struct gen *fgold, *ftrap; +struct gen *g_at(); +#define newgen() (struct gen *) alloc(sizeof(struct gen)) diff --git a/usr/othersrc/games/hack/def.gold.h b/usr/othersrc/games/hack/def.gold.h new file mode 100644 index 0000000000..8088908835 --- /dev/null +++ b/usr/othersrc/games/hack/def.gold.h @@ -0,0 +1,12 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.gold.h - version 1.0.2 */ + +struct gold { + struct gold *ngold; + xchar gx,gy; + long amount; +}; + +extern struct gold *fgold; +struct gold *g_at(); +#define newgold() (struct gold *) alloc(sizeof(struct gold)) diff --git a/usr/othersrc/games/hack/def.mkroom.h b/usr/othersrc/games/hack/def.mkroom.h new file mode 100644 index 0000000000..ddbb62be1b --- /dev/null +++ b/usr/othersrc/games/hack/def.mkroom.h @@ -0,0 +1,26 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.mkroom.h - version 1.0.3 */ + +struct mkroom { + schar lx,hx,ly,hy; /* usually xchar, but hx may be -1 */ + schar rtype,rlit,doorct,fdoor; +}; + +#define MAXNROFROOMS 15 +extern struct mkroom rooms[MAXNROFROOMS+1]; + +#define DOORMAX 100 +extern coord doors[DOORMAX]; + +/* various values of rtype */ +/* 0: ordinary room; 8-15: various shops */ +/* Note: some code assumes that >= 8 means shop, so be careful when adding + new roomtypes */ +#define SWAMP 3 +#define VAULT 4 +#define BEEHIVE 5 +#define MORGUE 6 +#define ZOO 7 +#define SHOPBASE 8 +#define WANDSHOP 9 +#define GENERAL 15 diff --git a/usr/othersrc/games/hack/def.monst.h b/usr/othersrc/games/hack/def.monst.h new file mode 100644 index 0000000000..88836af7ae --- /dev/null +++ b/usr/othersrc/games/hack/def.monst.h @@ -0,0 +1,60 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.monst.h - version 1.0.2 */ + +struct monst { + struct monst *nmon; + struct permonst *data; + unsigned m_id; + xchar mx,my; + xchar mdx,mdy; /* if mdispl then pos where last displayed */ +#define MTSZ 4 + coord mtrack[MTSZ]; /* monster track */ + schar mhp,mhpmax; + char mappearance; /* nonzero for undetected 'M's and for '1's */ + Bitfield(mimic,1); /* undetected mimic */ + Bitfield(mdispl,1); /* mdx,mdy valid */ + Bitfield(minvis,1); /* invisible */ + Bitfield(cham,1); /* shape-changer */ + Bitfield(mhide,1); /* hides beneath objects */ + Bitfield(mundetected,1); /* not seen in present hiding place */ + Bitfield(mspeed,2); + Bitfield(msleep,1); + Bitfield(mfroz,1); + Bitfield(mconf,1); + Bitfield(mflee,1); /* fleeing */ + Bitfield(mfleetim,7); /* timeout for mflee */ + Bitfield(mcan,1); /* has been cancelled */ + Bitfield(mtame,1); /* implies peaceful */ + Bitfield(mpeaceful,1); /* does not attack unprovoked */ + Bitfield(isshk,1); /* is shopkeeper */ + Bitfield(isgd,1); /* is guard */ + Bitfield(mcansee,1); /* cansee 1, temp.blinded 0, blind 0 */ + Bitfield(mblinded,7); /* cansee 0, temp.blinded n, blind 0 */ + Bitfield(mtrapped,1); /* trapped in a pit or bear trap */ + Bitfield(mnamelth,6); /* length of name (following mxlth) */ +#ifndef NOWORM + Bitfield(wormno,5); /* at most 31 worms on any level */ +#endif NOWORM + unsigned mtrapseen; /* bitmap of traps we've been trapped in */ + long mlstmv; /* prevent two moves at once */ + struct obj *minvent; + long mgold; + unsigned mxlth; /* length of following data */ + /* in order to prevent alignment problems mextra should + be (or follow) a long int */ + long mextra[1]; /* monster dependent info */ +}; + +#define newmonst(xl) (struct monst *) alloc((unsigned)(xl) + sizeof(struct monst)) + +extern struct monst *fmon; +extern struct monst *fallen_down; +struct monst *m_at(); + +/* these are in mspeed */ +#define MSLOW 1 /* slow monster */ +#define MFAST 2 /* speeded monster */ + +#define NAME(mtmp) (((char *) mtmp->mextra) + mtmp->mxlth) +#define MREGEN "TVi1" +#define UNDEAD "ZVW " diff --git a/usr/othersrc/games/hack/def.obj.h b/usr/othersrc/games/hack/def.obj.h new file mode 100644 index 0000000000..50b21df1b8 --- /dev/null +++ b/usr/othersrc/games/hack/def.obj.h @@ -0,0 +1,48 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.obj.h - version 1.0.3 */ + +struct obj { + struct obj *nobj; + unsigned o_id; + unsigned o_cnt_id; /* id of container object is in */ + xchar ox,oy; + xchar odx,ody; + uchar otyp; + uchar owt; + uchar quan; /* use oextra for tmp gold objects */ + schar spe; /* quality of weapon, armor or ring (+ or -) + number of charges for wand ( >= -1 ) + special for uball and amulet %% BAH */ + char olet; + char invlet; + Bitfield(oinvis,1); /* not yet implemented */ + Bitfield(odispl,1); + Bitfield(known,1); /* exact nature known */ + Bitfield(dknown,1); /* color or text known */ + Bitfield(cursed,1); + Bitfield(unpaid,1); /* on some bill */ + Bitfield(rustfree,1); + Bitfield(onamelth,6); + long age; /* creation date */ + long owornmask; +#define W_ARM 01L +#define W_ARM2 02L +#define W_ARMH 04L +#define W_ARMS 010L +#define W_ARMG 020L +#define W_ARMOR (W_ARM | W_ARM2 | W_ARMH | W_ARMS | W_ARMG) +#define W_RINGL 010000L /* make W_RINGL = RING_LEFT (see uprop) */ +#define W_RINGR 020000L +#define W_RING (W_RINGL | W_RINGR) +#define W_WEP 01000L +#define W_BALL 02000L +#define W_CHAIN 04000L + long oextra[1]; /* used for name of ordinary objects - length + is flexible; amount for tmp gold objects */ +}; + +extern struct obj *fobj; + +#define newobj(xl) (struct obj *) alloc((unsigned)(xl) + sizeof(struct obj)) +#define ONAME(otmp) ((char *) otmp->oextra) +#define OGOLD(otmp) (otmp->oextra[0]) diff --git a/usr/othersrc/games/hack/def.objclass.h b/usr/othersrc/games/hack/def.objclass.h new file mode 100644 index 0000000000..9e17de237e --- /dev/null +++ b/usr/othersrc/games/hack/def.objclass.h @@ -0,0 +1,60 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.objclass.h - version 1.0.3 */ + +/* definition of a class of objects */ + +struct objclass { + char *oc_name; /* actual name */ + char *oc_descr; /* description when name unknown */ + char *oc_uname; /* called by user */ + Bitfield(oc_name_known,1); + Bitfield(oc_merge,1); /* merge otherwise equal objects */ + char oc_olet; + schar oc_prob; /* probability for mkobj() */ + schar oc_delay; /* delay when using such an object */ + uchar oc_weight; + schar oc_oc1, oc_oc2; + int oc_oi; +#define nutrition oc_oi /* for foods */ +#define a_ac oc_oc1 /* for armors - only used in ARM_BONUS */ +#define ARM_BONUS(obj) ((10 - objects[obj->otyp].a_ac) + obj->spe) +#define a_can oc_oc2 /* for armors */ +#define bits oc_oc1 /* for wands and rings */ + /* wands */ +#define NODIR 1 +#define IMMEDIATE 2 +#define RAY 4 + /* rings */ +#define SPEC 1 /* +n is meaningful */ +#define wldam oc_oc1 /* for weapons and PICK_AXE */ +#define wsdam oc_oc2 /* for weapons and PICK_AXE */ +#define g_val oc_oi /* for gems: value on exit */ +}; + +extern struct objclass objects[]; + +/* definitions of all object-symbols */ + +#define ILLOBJ_SYM '\\' +#define AMULET_SYM '"' +#define FOOD_SYM '%' +#define WEAPON_SYM ')' +#define TOOL_SYM '(' +#define BALL_SYM '0' +#define CHAIN_SYM '_' +#define ROCK_SYM '`' +#define ARMOR_SYM '[' +#define POTION_SYM '!' +#define SCROLL_SYM '?' +#define WAND_SYM '/' +#define RING_SYM '=' +#define GEM_SYM '*' +/* Other places with explicit knowledge of object symbols: + * ....shk.c: char shtypes[] = "=/)%?!["; + * mklev.c: "=/)%?![<>" + * hack.mkobj.c: char mkobjstr[] = "))[[!!!!????%%%%/=**"; + * hack.apply.c: otmp = getobj("0#%", "put in"); + * hack.eat.c: otmp = getobj("%", "eat"); + * hack.invent.c: if(index("!%?[)=*(0/\"", sym)){ + * hack.invent.c: || index("%?!*",otmp->olet))){ + */ diff --git a/usr/othersrc/games/hack/def.objects.h b/usr/othersrc/games/hack/def.objects.h new file mode 100644 index 0000000000..b4400fc4a7 --- /dev/null +++ b/usr/othersrc/games/hack/def.objects.h @@ -0,0 +1,289 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.objects.h - version 1.0.3 */ + +/* objects have letter " % ) ( 0 _ ` [ ! ? / = * */ +#include "config.h" +#include "def.objclass.h" +#define NULL (char *)0 + +struct objclass objects[] = { + + { "strange object", NULL, NULL, 1, 0, + ILLOBJ_SYM, 0, 0, 0, 0, 0, 0 }, + { "amulet of Yendor", NULL, NULL, 1, 0, + AMULET_SYM, 100, 0, 2, 0, 0, 0 }, + +#define FOOD(name,prob,delay,weight,nutrition) { name, NULL, NULL, 1, 1,\ + FOOD_SYM, prob, delay, weight, 0, 0, nutrition } + +/* dog eats foods 0-4 but prefers 1 above 0,2,3,4 */ +/* food 4 can be read */ +/* food 5 improves your vision */ +/* food 6 makes you stronger (like Popeye) */ +/* foods CORPSE up to CORPSE+52 are cadavers */ + + FOOD("food ration", 50, 5, 4, 800), + FOOD("tripe ration", 20, 1, 2, 200), + FOOD("pancake", 3, 1, 1, 200), + FOOD("dead lizard", 3, 0, 1, 40), + FOOD("fortune cookie", 7, 0, 1, 40), + FOOD("carrot", 2, 0, 1, 50), + FOOD("tin", 7, 0, 1, 0), + FOOD("orange", 1, 0, 1, 80), + FOOD("apple", 1, 0, 1, 50), + FOOD("pear", 1, 0, 1, 50), + FOOD("melon", 1, 0, 1, 100), + FOOD("banana", 1, 0, 1, 80), + FOOD("candy bar", 1, 0, 1, 100), + FOOD("egg", 1, 0, 1, 80), + FOOD("clove of garlic", 1, 0, 1, 40), + FOOD("lump of royal jelly", 0, 0, 1, 200), + + FOOD("dead human", 0, 4, 40, 400), + FOOD("dead giant ant", 0, 1, 3, 30), + FOOD("dead giant bat", 0, 1, 3, 30), + FOOD("dead centaur", 0, 5, 50, 500), + FOOD("dead dragon", 0, 15, 150, 1500), + FOOD("dead floating eye", 0, 1, 1, 10), + FOOD("dead freezing sphere", 0, 1, 1, 10), + FOOD("dead gnome", 0, 1, 10, 100), + FOOD("dead hobgoblin", 0, 2, 20, 200), + FOOD("dead stalker", 0, 4, 40, 400), + FOOD("dead jackal", 0, 1, 10, 100), + FOOD("dead kobold", 0, 1, 10, 100), + FOOD("dead leprechaun", 0, 4, 40, 400), + FOOD("dead mimic", 0, 4, 40, 400), + FOOD("dead nymph", 0, 4, 40, 400), + FOOD("dead orc", 0, 2, 20, 200), + FOOD("dead purple worm", 0, 7, 70, 700), + FOOD("dead quasit", 0, 2, 20, 200), + FOOD("dead rust monster", 0, 5, 50, 500), + FOOD("dead snake", 0, 1, 10, 100), + FOOD("dead troll", 0, 4, 40, 400), + FOOD("dead umber hulk", 0, 5, 50, 500), + FOOD("dead vampire", 0, 4, 40, 400), + FOOD("dead wraith", 0, 1, 1, 10), + FOOD("dead xorn", 0, 7, 70, 700), + FOOD("dead yeti", 0, 7, 70, 700), + FOOD("dead zombie", 0, 1, 3, 30), + FOOD("dead acid blob", 0, 1, 3, 30), + FOOD("dead giant beetle", 0, 1, 1, 10), + FOOD("dead cockatrice", 0, 1, 3, 30), + FOOD("dead dog", 0, 2, 20, 200), + FOOD("dead ettin", 0, 1, 3, 30), + FOOD("dead fog cloud", 0, 1, 1, 10), + FOOD("dead gelatinous cube", 0, 1, 10, 100), + FOOD("dead homunculus", 0, 2, 20, 200), + FOOD("dead imp", 0, 1, 1, 10), + FOOD("dead jaguar", 0, 3, 30, 300), + FOOD("dead killer bee", 0, 1, 1, 10), + FOOD("dead leocrotta", 0, 5, 50, 500), + FOOD("dead minotaur", 0, 7, 70, 700), + FOOD("dead nurse", 0, 4, 40, 400), + FOOD("dead owlbear", 0, 7, 70, 700), + FOOD("dead piercer", 0, 2, 20, 200), + FOOD("dead quivering blob", 0, 1, 10, 100), + FOOD("dead giant rat", 0, 1, 3, 30), + FOOD("dead giant scorpion", 0, 1, 10, 100), + FOOD("dead tengu", 0, 3, 30, 300), + FOOD("dead unicorn", 0, 3, 30, 300), + FOOD("dead violet fungi", 0, 1, 10, 100), + FOOD("dead long worm", 0, 5, 50, 500), +/* %% wt of long worm should be proportional to its length */ + FOOD("dead xan", 0, 3, 30, 300), + FOOD("dead yellow light", 0, 1, 1, 10), + FOOD("dead zruty", 0, 6, 60, 600), + +/* weapons ... - ROCK come several at a time */ +/* weapons ... - (ROCK-1) are shot using idem+(BOW-ARROW) */ +/* weapons AXE, SWORD, THSWORD are good for worm-cutting */ +/* weapons (PICK-)AXE, DAGGER, CRYSKNIFE are good for tin-opening */ +#define WEAPON(name,prob,wt,ldam,sdam) { name, NULL, NULL, 1, 0 /*%%*/,\ + WEAPON_SYM, prob, 0, wt, ldam, sdam, 0 } + + WEAPON("arrow", 7, 0, 6, 6), + WEAPON("sling bullet", 7, 0, 4, 6), + WEAPON("crossbow bolt", 7, 0, 4, 6), + WEAPON("dart", 7, 0, 3, 2), + WEAPON("rock", 6, 1, 3, 3), + WEAPON("boomerang", 2, 3, 9, 9), + WEAPON("mace", 9, 3, 6, 7), + WEAPON("axe", 6, 3, 6, 4), + WEAPON("flail", 6, 3, 6, 5), + WEAPON("long sword", 8, 3, 8, 12), + WEAPON("two handed sword", 6, 4, 12, 6), + WEAPON("dagger", 6, 3, 4, 3), + WEAPON("worm tooth", 0, 4, 2, 2), + WEAPON("crysknife", 0, 3, 10, 10), + WEAPON("spear", 6, 3, 6, 8), + WEAPON("bow", 6, 3, 4, 6), + WEAPON("sling", 5, 3, 6, 6), + WEAPON("crossbow", 6, 3, 4, 6), + + { "whistle", "whistle", NULL, 0, 0, + TOOL_SYM, 90, 0, 2, 0, 0, 0 }, + { "magic whistle", "whistle", NULL, 0, 0, + TOOL_SYM, 10, 0, 2, 0, 0, 0 }, + { "expensive camera", NULL, NULL, 1, 1, + TOOL_SYM, 0, 0, 3, 0, 0, 0 }, + { "ice box", "large box", NULL, 0, 0, + TOOL_SYM, 0, 0, 40, 0, 0, 0 }, + { "pick-axe", NULL, NULL, 1, 1, + TOOL_SYM, 0, 0, 5, 6, 3, 0 }, + { "can opener", NULL, NULL, 1, 1, + TOOL_SYM, 0, 0, 1, 0, 0, 0 }, + { "heavy iron ball", NULL, NULL, 1, 0, + BALL_SYM, 100, 0, 20, 0, 0, 0 }, + { "iron chain", NULL, NULL, 1, 0, + CHAIN_SYM, 100, 0, 20, 0, 0, 0 }, + { "enormous rock", NULL, NULL, 1, 0, + ROCK_SYM, 100, 0, 200 /* > MAX_CARR_CAP */, 0, 0, 0 }, + +#define ARMOR(name,prob,delay,ac,can) { name, NULL, NULL, 1, 0,\ + ARMOR_SYM, prob, delay, 8, ac, can, 0 } + ARMOR("helmet", 3, 1, 9, 0), + ARMOR("plate mail", 5, 5, 3, 2), + ARMOR("splint mail", 8, 5, 4, 1), + ARMOR("banded mail", 10, 5, 4, 0), + ARMOR("chain mail", 10, 5, 5, 1), + ARMOR("scale mail", 10, 5, 6, 0), + ARMOR("ring mail", 15, 5, 7, 0), + /* the armors below do not rust */ + ARMOR("studded leather armor", 13, 3, 7, 1), + ARMOR("leather armor", 17, 3, 8, 0), + ARMOR("elven cloak", 5, 0, 9, 3), + ARMOR("shield", 3, 0, 9, 0), + ARMOR("pair of gloves", 1, 1, 9, 0), + +#define POTION(name,color) { name, color, NULL, 0, 1,\ + POTION_SYM, 0, 0, 2, 0, 0, 0 } + + POTION("restore strength", "orange"), + POTION("booze", "bubbly"), + POTION("invisibility", "glowing"), + POTION("fruit juice", "smoky"), + POTION("healing", "pink"), + POTION("paralysis", "puce"), + POTION("monster detection", "purple"), + POTION("object detection", "yellow"), + POTION("sickness", "white"), + POTION("confusion", "swirly"), + POTION("gain strength", "purple-red"), + POTION("speed", "ruby"), + POTION("blindness", "dark green"), + POTION("gain level", "emerald"), + POTION("extra healing", "sky blue"), + POTION("levitation", "brown"), + POTION(NULL, "brilliant blue"), + POTION(NULL, "clear"), + POTION(NULL, "magenta"), + POTION(NULL, "ebony"), + +#define SCROLL(name,text,prob) { name, text, NULL, 0, 1,\ + SCROLL_SYM, prob, 0, 3, 0, 0, 0 } + SCROLL("mail", "KIRJE", 0), + SCROLL("enchant armor", "ZELGO MER", 6), + SCROLL("destroy armor", "JUYED AWK YACC", 5), + SCROLL("confuse monster", "NR 9", 5), + SCROLL("scare monster", "XIXAXA XOXAXA XUXAXA", 4), + SCROLL("blank paper", "READ ME", 3), + SCROLL("remove curse", "PRATYAVAYAH", 6), + SCROLL("enchant weapon", "DAIYEN FOOELS", 6), + SCROLL("damage weapon", "HACKEM MUCHE", 5), + SCROLL("create monster", "LEP GEX VEN ZEA", 5), + SCROLL("taming", "PRIRUTSENIE", 1), + SCROLL("genocide", "ELBIB YLOH",2), + SCROLL("light", "VERR YED HORRE", 10), + SCROLL("teleportation", "VENZAR BORGAVVE", 5), + SCROLL("gold detection", "THARR", 4), + SCROLL("food detection", "YUM YUM", 1), + SCROLL("identify", "KERNOD WEL", 18), + SCROLL("magic mapping", "ELAM EBOW", 5), + SCROLL("amnesia", "DUAM XNAHT", 3), + SCROLL("fire", "ANDOVA BEGARIN", 5), + SCROLL("punishment", "VE FORBRYDERNE", 1), + SCROLL(NULL, "VELOX NEB", 0), + SCROLL(NULL, "FOOBIE BLETCH", 0), + SCROLL(NULL, "TEMOV", 0), + SCROLL(NULL, "GARVEN DEH", 0), + +#define WAND(name,metal,prob,flags) { name, metal, NULL, 0, 0,\ + WAND_SYM, prob, 0, 3, flags, 0, 0 } + + WAND("light", "iridium", 10, NODIR), + WAND("secret door detection", "tin", 5, NODIR), + WAND("create monster", "platinum", 5, NODIR), + WAND("wishing", "glass", 1, NODIR), + WAND("striking", "zinc", 9, IMMEDIATE), + WAND("slow monster", "balsa", 5, IMMEDIATE), + WAND("speed monster", "copper", 5, IMMEDIATE), + WAND("undead turning", "silver", 5, IMMEDIATE), + WAND("polymorph", "brass", 5, IMMEDIATE), + WAND("cancellation", "maple", 5, IMMEDIATE), + WAND("teleportation", "pine", 5, IMMEDIATE), + WAND("make invisible", "marble", 9, IMMEDIATE), + WAND("digging", "iron", 5, RAY), + WAND("magic missile", "aluminium", 10, RAY), + WAND("fire", "steel", 5, RAY), + WAND("sleep", "curved", 5, RAY), + WAND("cold", "short", 5, RAY), + WAND("death", "long", 1, RAY), + WAND(NULL, "oak", 0, 0), + WAND(NULL, "ebony", 0, 0), + WAND(NULL, "runed", 0, 0), + +#define RING(name,stone,spec) { name, stone, NULL, 0, 0,\ + RING_SYM, 0, 0, 1, spec, 0, 0 } + + RING("adornment", "engagement", 0), + RING("teleportation", "wooden", 0), + RING("regeneration", "black onyx", 0), + RING("searching", "topaz", 0), + RING("see invisible", "pearl", 0), + RING("stealth", "sapphire", 0), + RING("levitation", "moonstone", 0), + RING("poison resistance", "agate", 0), + RING("aggravate monster", "tiger eye", 0), + RING("hunger", "shining", 0), + RING("fire resistance", "gold", 0), + RING("cold resistance", "copper", 0), + RING("protection from shape changers", "diamond", 0), + RING("conflict", "jade", 0), + RING("gain strength", "ruby", SPEC), + RING("increase damage", "silver", SPEC), + RING("protection", "granite", SPEC), + RING("warning", "wire", 0), + RING("teleport control", "iron", 0), + RING(NULL, "ivory", 0), + RING(NULL, "blackened", 0), + +/* gems ************************************************************/ +#define GEM(name,color,prob,gval) { name, color, NULL, 0, 1,\ + GEM_SYM, prob, 0, 1, 0, 0, gval } + GEM("diamond", "blue", 1, 4000), + GEM("ruby", "red", 1, 3500), + GEM("sapphire", "blue", 1, 3000), + GEM("emerald", "green", 1, 2500), + GEM("turquoise", "green", 1, 2000), + GEM("aquamarine", "blue", 1, 1500), + GEM("tourmaline", "green", 1, 1000), + GEM("topaz", "yellow", 1, 900), + GEM("opal", "yellow", 1, 800), + GEM("garnet", "dark", 1, 700), + GEM("amethyst", "violet", 2, 650), + GEM("agate", "green", 2, 600), + GEM("onyx", "white", 2, 550), + GEM("jasper", "yellowish brown", 2, 500), + GEM("jade", "green", 2, 450), + GEM("worthless piece of blue glass", "blue", 20, 0), + GEM("worthless piece of red glass", "red", 20, 0), + GEM("worthless piece of yellow glass", "yellow", 20, 0), + GEM("worthless piece of green glass", "green", 20, 0), + { NULL, NULL, NULL, 0, 0, ILLOBJ_SYM, 0, 0, 0, 0, 0, 0 } +}; + +char obj_symbols[] = { + ILLOBJ_SYM, AMULET_SYM, FOOD_SYM, WEAPON_SYM, TOOL_SYM, + BALL_SYM, CHAIN_SYM, ROCK_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM, + WAND_SYM, RING_SYM, GEM_SYM, 0 }; +int bases[sizeof(obj_symbols)]; diff --git a/usr/othersrc/games/hack/def.permonst.h b/usr/othersrc/games/hack/def.permonst.h new file mode 100644 index 0000000000..b19efc6ae4 --- /dev/null +++ b/usr/othersrc/games/hack/def.permonst.h @@ -0,0 +1,25 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.permonst.h - version 1.0.2 */ + +struct permonst { + char *mname,mlet; + schar mlevel,mmove,ac,damn,damd; + unsigned pxlth; +}; + +extern struct permonst mons[]; +#define PM_ACID_BLOB &mons[7] +#define PM_ZOMBIE &mons[13] +#define PM_PIERCER &mons[17] +#define PM_KILLER_BEE &mons[26] +#define PM_WRAITH &mons[33] +#define PM_MIMIC &mons[37] +#define PM_VAMPIRE &mons[43] +#define PM_CHAMELEON &mons[47] +#define PM_DEMON &mons[54] +#define PM_MINOTAUR &mons[55] /* last in mons array */ +#define PM_SHK &mons[56] /* very last */ +#define PM_GHOST &pm_ghost +#define PM_EEL &pm_eel +#define PM_WIZARD &pm_wizard +#define CMNUM 55 /* number of common monsters */ diff --git a/usr/othersrc/games/hack/def.rm.h b/usr/othersrc/games/hack/def.rm.h new file mode 100644 index 0000000000..f84921ca33 --- /dev/null +++ b/usr/othersrc/games/hack/def.rm.h @@ -0,0 +1,52 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.rm.h - version 1.0.2 */ + +/* Level location types */ +#define HWALL 1 +#define VWALL 2 +#define SDOOR 3 +#define SCORR 4 +#define LDOOR 5 +#define POOL 6 /* not yet fully implemented */ + /* this should in fact be a bit like lit */ +#define DOOR 7 +#define CORR 8 +#define ROOM 9 +#define STAIRS 10 + +/* + * Avoid using the level types in inequalities: + * these types are subject to change. + * Instead, use one of the macros below. + */ +#define IS_WALL(typ) ((typ) <= VWALL) +#define IS_ROCK(typ) ((typ) < POOL) /* absolutely nonaccessible */ +#define ACCESSIBLE(typ) ((typ) >= DOOR) /* good position */ +#define IS_ROOM(typ) ((typ) >= ROOM) /* ROOM or STAIRS */ +#define ZAP_POS(typ) ((typ) > DOOR) + +/* + * A few of the associated symbols are not hardwired. + */ +#ifdef QUEST +#define CORR_SYM ':' +#else +#define CORR_SYM '#' +#endif QUEST +#define POOL_SYM '}' + +#define ERRCHAR '{' + +/* + * The structure describing a coordinate position. + * Before adding fields, remember that this will significantly affect + * the size of temporary files and save files. + */ +struct rm { + char scrsym; + unsigned typ:5; + unsigned new:1; + unsigned seen:1; + unsigned lit:1; +}; +extern struct rm levl[COLNO][ROWNO]; diff --git a/usr/othersrc/games/hack/def.trap.h b/usr/othersrc/games/hack/def.trap.h new file mode 100644 index 0000000000..26946add76 --- /dev/null +++ b/usr/othersrc/games/hack/def.trap.h @@ -0,0 +1,27 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.trap.h - version 1.0.2 */ + +struct trap { + struct trap *ntrap; + xchar tx,ty; + unsigned ttyp:5; + unsigned tseen:1; + unsigned once:1; +}; + +extern struct trap *ftrap; +struct trap *t_at(); +#define newtrap() (struct trap *) alloc(sizeof(struct trap)) + +/* various kinds of traps */ +#define BEAR_TRAP 0 +#define ARROW_TRAP 1 +#define DART_TRAP 2 +#define TRAPDOOR 3 +#define TELEP_TRAP 4 +#define PIT 5 +#define SLP_GAS_TRAP 6 +#define PIERC 7 +#define MIMIC 8 /* used only in mklev.c */ +#define TRAPNUM 9 /* if not less than 32, change sizeof(ttyp) */ + /* see also mtrapseen (bit map) */ diff --git a/usr/othersrc/games/hack/def.wseg.h b/usr/othersrc/games/hack/def.wseg.h new file mode 100644 index 0000000000..0a2af7791d --- /dev/null +++ b/usr/othersrc/games/hack/def.wseg.h @@ -0,0 +1,13 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* def.wseg.h - version 1.0.2 */ + +#ifndef NOWORM +/* worm structure */ +struct wseg { + struct wseg *nseg; + xchar wx,wy; + unsigned wdispl:1; +}; + +#define newseg() (struct wseg *) alloc(sizeof(struct wseg)) +#endif NOWORM diff --git a/usr/othersrc/games/hack/hack.Decl.c b/usr/othersrc/games/hack/hack.Decl.c new file mode 100644 index 0000000000..b2855ac936 --- /dev/null +++ b/usr/othersrc/games/hack/hack.Decl.c @@ -0,0 +1,43 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.Decl.c - version 1.0.3 */ + +#include "hack.h" +char nul[40]; /* contains zeros */ +char plname[PL_NSIZ]; /* player name */ +char lock[PL_NSIZ+4] = "1lock"; /* long enough for login name .99 */ + +boolean in_mklev, restoring; + +struct rm levl[COLNO][ROWNO]; /* level map */ +#ifndef QUEST +#include "def.mkroom.h" +struct mkroom rooms[MAXNROFROOMS+1]; +coord doors[DOORMAX]; +#endif QUEST +struct monst *fmon = 0; +struct trap *ftrap = 0; +struct gold *fgold = 0; +struct obj *fobj = 0, *fcobj = 0, *invent = 0, *uwep = 0, *uarm = 0, + *uarm2 = 0, *uarmh = 0, *uarms = 0, *uarmg = 0, *uright = 0, + *uleft = 0, *uchain = 0, *uball = 0; +struct flag flags; +struct you u; +struct monst youmonst; /* dummy; used as return value for boomhit */ + +xchar dlevel = 1; +xchar xupstair, yupstair, xdnstair, ydnstair; +char *save_cm = 0, *killer, *nomovemsg; + +long moves = 1; +long wailmsg = 0; + +int multi = 0; +char genocided[60]; +char fut_geno[60]; + +xchar curx,cury; +xchar seelx, seehx, seely, seehy; /* corners of lit room */ + +coord bhitpos; + +char quitchars[] = " \r\n\033"; diff --git a/usr/othersrc/games/hack/hack.bones.c b/usr/othersrc/games/hack/hack.bones.c new file mode 100644 index 0000000000..d4a05b8222 --- /dev/null +++ b/usr/othersrc/games/hack/hack.bones.c @@ -0,0 +1,95 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.bones.c - version 1.0.3 */ + +#include "hack.h" +extern char plname[PL_NSIZ]; +extern long somegold(); +extern struct monst *makemon(); +extern struct permonst pm_ghost; + +char bones[] = "bones_xx"; + +/* save bones and possessions of a deceased adventurer */ +savebones(){ +register fd; +register struct obj *otmp; +register struct trap *ttmp; +register struct monst *mtmp; + if(dlevel <= 0 || dlevel > MAXLEVEL) return; + if(!rn2(1 + dlevel/2)) return; /* not so many ghosts on low levels */ + bones[6] = '0' + (dlevel/10); + bones[7] = '0' + (dlevel%10); + if((fd = open(bones,0)) >= 0){ + (void) close(fd); + return; + } + /* drop everything; the corpse's possessions are usually cursed */ + otmp = invent; + while(otmp){ + otmp->ox = u.ux; + otmp->oy = u.uy; + otmp->age = 0; /* very long ago */ + otmp->owornmask = 0; + if(rn2(5)) otmp->cursed = 1; + if(!otmp->nobj){ + otmp->nobj = fobj; + fobj = invent; + invent = 0; /* superfluous */ + break; + } + otmp = otmp->nobj; + } + if(!(mtmp = makemon(PM_GHOST, u.ux, u.uy))) return; + mtmp->mx = u.ux; + mtmp->my = u.uy; + mtmp->msleep = 1; + (void) strcpy((char *) mtmp->mextra, plname); + mkgold(somegold() + d(dlevel,30), u.ux, u.uy); + for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){ + mtmp->m_id = 0; + if(mtmp->mtame) { + mtmp->mtame = 0; + mtmp->mpeaceful = 0; + } + mtmp->mlstmv = 0; + if(mtmp->mdispl) unpmon(mtmp); + } + for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) + ttmp->tseen = 0; + for(otmp = fobj; otmp; otmp = otmp->nobj) { + otmp->o_id = 0; + /* otmp->o_cnt_id = 0; - superfluous */ + otmp->onamelth = 0; + otmp->known = 0; + otmp->invlet = 0; + if(otmp->olet == AMULET_SYM && !otmp->spe) { + otmp->spe = -1; /* no longer the actual amulet */ + otmp->cursed = 1; /* flag as gotten from a ghost */ + } + } + if((fd = creat(bones, FMASK)) < 0) return; + savelev(fd,dlevel); + (void) close(fd); +} + +getbones(){ +register fd,x,y,ok; + if(rn2(3)) return(0); /* only once in three times do we find bones */ + bones[6] = '0' + dlevel/10; + bones[7] = '0' + dlevel%10; + if((fd = open(bones, 0)) < 0) return(0); + if((ok = uptodate(fd)) != 0){ + getlev(fd, 0, dlevel); + for(x = 0; x < COLNO; x++) for(y = 0; y < ROWNO; y++) + levl[x][y].seen = levl[x][y].new = 0; + } + (void) close(fd); +#ifdef WIZARD + if(!wizard) /* duvel!frans: don't remove bones while debugging */ +#endif WiZARD + if(unlink(bones) < 0){ + pline("Cannot unlink %s .", bones); + return(0); + } + return(ok); +} diff --git a/usr/othersrc/games/hack/hack.c b/usr/othersrc/games/hack/hack.c new file mode 100644 index 0000000000..5c8288144e --- /dev/null +++ b/usr/othersrc/games/hack/hack.c @@ -0,0 +1,798 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.c - version 1.0.3 */ + +#include "hack.h" +#include + +extern char news0(); +extern char *nomovemsg; +extern char *exclam(); +extern struct obj *addinv(); +extern boolean hmon(); + +/* called on movement: + 1. when throwing ball+chain far away + 2. when teleporting + 3. when walking out of a lit room + */ +unsee() { + register x,y; + register struct rm *lev; + +/* + if(u.udispl){ + u.udispl = 0; + newsym(u.udisx, u.udisy); + } +*/ +#ifndef QUEST + if(seehx){ + seehx = 0; + } else +#endif QUEST + 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; + lev = &levl[x][y]; + if(!lev->lit && lev->scrsym == '.') { + lev->scrsym =' '; + lev->new = 1; + on_scr(x,y); + } + } +} + +/* called: + in hack.eat.c: seeoff(0) - blind after eating rotten food + in hack.mon.c: seeoff(0) - blinded by a yellow light + in hack.mon.c: seeoff(1) - swallowed + in hack.do.c: seeoff(0) - blind after drinking potion + in hack.do.c: seeoff(1) - go up or down the stairs + in hack.trap.c:seeoff(1) - fall through trapdoor + */ +seeoff(mode) /* 1 to redo @, 0 to leave them */ +{ /* 1 means misc movement, 0 means blindness */ + register x,y; + register struct rm *lev; + + if(u.udispl && mode){ + u.udispl = 0; + levl[u.udisx][u.udisy].scrsym = news0(u.udisx,u.udisy); + } +#ifndef QUEST + if(seehx) { + seehx = 0; + } else +#endif QUEST + if(!mode) { + 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; + lev = &levl[x][y]; + if(!lev->lit && lev->scrsym == '.') + lev->seen = 0; + } + } +} + +domove() +{ + xchar oldx,oldy; + register struct monst *mtmp; + register struct rm *tmpr,*ust; + struct trap *trap; + register struct obj *otmp; + + u_wipe_engr(rnd(5)); + + if(inv_weight() > 0){ + pline("You collapse under your load."); + nomul(0); + return; + } + if(u.uswallow) { + u.dx = u.dy = 0; + u.ux = u.ustuck->mx; + u.uy = u.ustuck->my; + } else { + if(Confusion) { + do { + confdir(); + } while(!isok(u.ux+u.dx, u.uy+u.dy) || + IS_ROCK(levl[u.ux+u.dx][u.uy+u.dy].typ)); + } + if(!isok(u.ux+u.dx, u.uy+u.dy)){ + nomul(0); + return; + } + } + + ust = &levl[u.ux][u.uy]; + oldx = u.ux; + oldy = u.uy; + if(!u.uswallow && (trap = t_at(u.ux+u.dx, u.uy+u.dy)) && trap->tseen) + nomul(0); + if(u.ustuck && !u.uswallow && (u.ux+u.dx != u.ustuck->mx || + u.uy+u.dy != u.ustuck->my)) { + if(dist(u.ustuck->mx, u.ustuck->my) > 2){ + /* perhaps it fled (or was teleported or ... ) */ + u.ustuck = 0; + } else { + if(Blind) pline("You cannot escape from it!"); + else pline("You cannot escape from %s!", + monnam(u.ustuck)); + nomul(0); + return; + } + } + if(u.uswallow || (mtmp = m_at(u.ux+u.dx,u.uy+u.dy))) { + /* attack monster */ + + nomul(0); + gethungry(); + if(multi < 0) return; /* we just fainted */ + + /* try to attack; note that it might evade */ + if(attack(u.uswallow ? u.ustuck : mtmp)) + return; + } + /* not attacking an animal, so we try to move */ + if(u.utrap) { + if(u.utraptype == TT_PIT) { + pline("You are still in a pit."); + u.utrap--; + } else { + pline("You are caught in a beartrap."); + if((u.dx && u.dy) || !rn2(5)) u.utrap--; + } + return; + } + tmpr = &levl[u.ux+u.dx][u.uy+u.dy]; + if(IS_ROCK(tmpr->typ) || + (u.dx && u.dy && (tmpr->typ == DOOR || ust->typ == DOOR))){ + flags.move = 0; + nomul(0); + return; + } + while(otmp = sobj_at(ENORMOUS_ROCK, u.ux+u.dx, u.uy+u.dy)) { + register xchar rx = u.ux+2*u.dx, ry = u.uy+2*u.dy; + register struct trap *ttmp; + nomul(0); + if(isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) && + (levl[rx][ry].typ != DOOR || !(u.dx && u.dy)) && + !sobj_at(ENORMOUS_ROCK, rx, ry)) { + if(m_at(rx,ry)) { + pline("You hear a monster behind the rock."); + pline("Perhaps that's why you cannot move it."); + goto cannot_push; + } + if(ttmp = t_at(rx,ry)) + switch(ttmp->ttyp) { + case PIT: + pline("You push the rock into a pit!"); + deltrap(ttmp); + delobj(otmp); + pline("It completely fills the pit!"); + continue; + case TELEP_TRAP: + pline("You push the rock and suddenly it disappears!"); + delobj(otmp); + continue; + } + if(levl[rx][ry].typ == POOL) { + levl[rx][ry].typ = ROOM; + mnewsym(rx,ry); + prl(rx,ry); + pline("You push the rock into the water."); + pline("Now you can cross the water!"); + delobj(otmp); + continue; + } + otmp->ox = rx; + otmp->oy = ry; + /* pobj(otmp); */ + if(cansee(rx,ry)) atl(rx,ry,otmp->olet); + if(Invisible) newsym(u.ux+u.dx, u.uy+u.dy); + + { static long lastmovetime; + /* note: this var contains garbage initially and + after a restore */ + if(moves > lastmovetime+2 || moves < lastmovetime) + pline("With great effort you move the enormous rock."); + lastmovetime = moves; + } + } else { + pline("You try to move the enormous rock, but in vain."); + cannot_push: + if((!invent || inv_weight()+90 <= 0) && + (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][u.uy+u.dy].typ) + && IS_ROCK(levl[u.ux+u.dx][u.uy].typ)))){ + pline("However, you can squeeze yourself into a small opening."); + break; + } else + return; + } + } + if(u.dx && u.dy && IS_ROCK(levl[u.ux][u.uy+u.dy].typ) && + IS_ROCK(levl[u.ux+u.dx][u.uy].typ) && + invent && inv_weight()+40 > 0) { + pline("You are carrying too much to get through."); + nomul(0); + return; + } + if(Punished && + DIST(u.ux+u.dx, u.uy+u.dy, uchain->ox, uchain->oy) > 2){ + if(carried(uball)) { + movobj(uchain, u.ux, u.uy); + goto nodrag; + } + + if(DIST(u.ux+u.dx, u.uy+u.dy, uball->ox, uball->oy) < 3){ + /* leave ball, move chain under/over ball */ + movobj(uchain, uball->ox, uball->oy); + goto nodrag; + } + + if(inv_weight() + (int) uball->owt/2 > 0) { + pline("You cannot %sdrag the heavy iron ball.", + invent ? "carry all that and also " : ""); + nomul(0); + return; + } + + movobj(uball, uchain->ox, uchain->oy); + unpobj(uball); /* BAH %% */ + uchain->ox = u.ux; + uchain->oy = u.uy; + nomul(-2); + nomovemsg = ""; + nodrag: ; + } + u.ux += u.dx; + u.uy += u.dy; + if(flags.run) { + if(tmpr->typ == DOOR || + (xupstair == u.ux && yupstair == u.uy) || + (xdnstair == u.ux && ydnstair == u.uy)) + nomul(0); + } + + if(tmpr->typ == POOL && !Levitation) + drown(); /* not necessarily fatal */ + +/* + if(u.udispl) { + u.udispl = 0; + newsym(oldx,oldy); + } +*/ + if(!Blind) { +#ifdef QUEST + setsee(); +#else + if(ust->lit) { + if(tmpr->lit) { + if(tmpr->typ == DOOR) + prl1(u.ux+u.dx,u.uy+u.dy); + else if(ust->typ == DOOR) + nose1(oldx-u.dx,oldy-u.dy); + } else { + unsee(); + prl1(u.ux+u.dx,u.uy+u.dy); + } + } else { + if(tmpr->lit) setsee(); + else { + prl1(u.ux+u.dx,u.uy+u.dy); + if(tmpr->typ == DOOR) { + if(u.dy) { + prl(u.ux-1,u.uy); + prl(u.ux+1,u.uy); + } else { + prl(u.ux,u.uy-1); + prl(u.ux,u.uy+1); + } + } + } + nose1(oldx-u.dx,oldy-u.dy); + } +#endif QUEST + } else { + pru(); + } + if(!flags.nopick) pickup(1); + if(trap) dotrap(trap); /* fall into pit, arrow trap, etc. */ + (void) inshop(); + if(!Blind) read_engr_at(u.ux,u.uy); +} + +movobj(obj, ox, oy) +register struct obj *obj; +register int ox, oy; +{ + /* Some dirty programming to get display right */ + freeobj(obj); + unpobj(obj); + obj->nobj = fobj; + fobj = obj; + obj->ox = ox; + obj->oy = oy; +} + +dopickup(){ + if(!g_at(u.ux,u.uy) && !o_at(u.ux,u.uy)) { + pline("There is nothing here to pick up."); + return(0); + } + if(Levitation) { + pline("You cannot reach the floor."); + return(1); + } + pickup(0); + return(1); +} + +pickup(all) +{ + register struct gold *gold; + register struct obj *obj, *obj2; + register int wt; + + if(Levitation) return; + while(gold = g_at(u.ux,u.uy)) { + pline("%ld gold piece%s.", gold->amount, plur(gold->amount)); + u.ugold += gold->amount; + flags.botl = 1; + freegold(gold); + if(flags.run) nomul(0); + if(Invisible) newsym(u.ux,u.uy); + } + + /* check for more than one object */ + if(!all) { + register int ct = 0; + + for(obj = fobj; obj; obj = obj->nobj) + if(obj->ox == u.ux && obj->oy == u.uy) + if(!Punished || obj != uchain) + ct++; + if(ct < 2) + all++; + else + pline("There are several objects here."); + } + + for(obj = fobj; obj; obj = obj2) { + obj2 = obj->nobj; /* perhaps obj will be picked up */ + if(obj->ox == u.ux && obj->oy == u.uy) { + if(flags.run) nomul(0); + + /* do not pick up uchain */ + if(Punished && obj == uchain) + continue; + + if(!all) { + char c; + + pline("Pick up %s ? [ynaq]", doname(obj)); + while(!index("ynaq ", (c = readchar()))) + bell(); + if(c == 'q') return; + if(c == 'n') continue; + if(c == 'a') all = 1; + } + + if(obj->otyp == DEAD_COCKATRICE && !uarmg){ + pline("Touching the dead cockatrice is a fatal mistake."); + pline("You turn to stone."); + killer = "cockatrice cadaver"; + done("died"); + } + + if(obj->otyp == SCR_SCARE_MONSTER){ + if(!obj->spe) obj->spe = 1; + else { + /* Note: perhaps the 1st pickup failed: you cannot + carry anymore, and so we never dropped it - + let's assume that treading on it twice also + destroys the scroll */ + pline("The scroll turns to dust as you pick it up."); + delobj(obj); + continue; + } + } + + wt = inv_weight() + obj->owt; + if(wt > 0) { + if(obj->quan > 1) { + /* see how many we can lift */ + extern struct obj *splitobj(); + int savequan = obj->quan; + int iw = inv_weight(); + int qq; + for(qq = 1; qq < savequan; qq++){ + obj->quan = qq; + if(iw + weight(obj) > 0) + break; + } + obj->quan = savequan; + qq--; + /* we can carry qq of them */ + if(!qq) goto too_heavy; + pline("You can only carry %s of the %s lying here.", + (qq == 1) ? "one" : "some", + doname(obj)); + (void) splitobj(obj, qq); + /* note: obj2 is set already, so we'll never + * encounter the other half; if it should be + * otherwise then write + * obj2 = splitobj(obj,qq); + */ + goto lift_some; + } + too_heavy: + pline("There %s %s here, but %s.", + (obj->quan == 1) ? "is" : "are", + doname(obj), + !invent ? "it is too heavy for you to lift" + : "you cannot carry anymore"); + break; + } + lift_some: + if(inv_cnt() >= 52) { + pline("Your knapsack cannot accomodate anymore items."); + break; + } + if(wt > -5) pline("You have a little trouble lifting"); + freeobj(obj); + if(Invisible) newsym(u.ux,u.uy); + addtobill(obj); /* sets obj->unpaid if necessary */ + { int pickquan = obj->quan; + int mergquan; + if(!Blind) obj->dknown = 1; /* this is done by prinv(), + but addinv() needs it already for merging */ + obj = addinv(obj); /* might merge it with other objects */ + mergquan = obj->quan; + obj->quan = pickquan; /* to fool prinv() */ + prinv(obj); + obj->quan = mergquan; + } + } + } +} + +/* stop running if we see something interesting */ +/* turn around a corner if that is the only way we can proceed */ +/* do not turn left or right twice */ +lookaround(){ +register x,y,i,x0,y0,m0,i0 = 9; +register int corrct = 0, noturn = 0; +register struct monst *mtmp; +#ifdef lint + /* suppress "used before set" message */ + x0 = y0 = 0; +#endif lint + if(Blind || flags.run == 0) return; + if(flags.run == 1 && levl[u.ux][u.uy].typ == ROOM) return; +#ifdef QUEST + if(u.ux0 == u.ux+u.dx && u.uy0 == u.uy+u.dy) goto stop; +#endif QUEST + for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++){ + if(x == u.ux && y == u.uy) continue; + if(!levl[x][y].typ) continue; + if((mtmp = m_at(x,y)) && !mtmp->mimic && + (!mtmp->minvis || See_invisible)){ + if(!mtmp->mtame || (x == u.ux+u.dx && y == u.uy+u.dy)) + goto stop; + } else mtmp = 0; /* invisible M cannot influence us */ + if(x == u.ux-u.dx && y == u.uy-u.dy) continue; + switch(levl[x][y].scrsym){ + case '|': + case '-': + case '.': + case ' ': + break; + case '+': + if(x != u.ux && y != u.uy) break; + if(flags.run != 1) goto stop; + /* fall into next case */ + case CORR_SYM: + corr: + if(flags.run == 1 || flags.run == 3) { + i = DIST(x,y,u.ux+u.dx,u.uy+u.dy); + if(i > 2) break; + if(corrct == 1 && DIST(x,y,x0,y0) != 1) + noturn = 1; + if(i < i0) { + i0 = i; + x0 = x; + y0 = y; + m0 = mtmp ? 1 : 0; + } + } + corrct++; + break; + case '^': + if(flags.run == 1) goto corr; /* if you must */ + if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop; + break; + default: /* e.g. objects or trap or stairs */ + if(flags.run == 1) goto corr; + if(mtmp) break; /* d */ + stop: + nomul(0); + return; + } + } +#ifdef QUEST + if(corrct > 0 && (flags.run == 4 || flags.run == 5)) goto stop; +#endif QUEST + if(corrct > 1 && flags.run == 2) goto stop; + if((flags.run == 1 || flags.run == 3) && !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) + i = 2; /* straight turn right */ + else + i = -2; /* straight turn left */ + } else if(u.dx && u.dy) { + if((u.dx == u.dy && y0 == u.uy) || + (u.dx != u.dy && y0 != u.uy)) + i = -1; /* half turn left */ + else + i = 1; /* half turn right */ + } else { + if((x0-u.ux == y0-u.uy && !u.dy) || + (x0-u.ux != y0-u.uy && u.dy)) + i = 1; /* half turn right */ + else + i = -1; /* half turn left */ + } + i += u.last_str_turn; + if(i <= 2 && i >= -2) { + u.last_str_turn = i; + u.dx = x0-u.ux, u.dy = y0-u.uy; + } + } +} + +/* something like lookaround, but we are not running */ +/* react only to monsters that might hit us */ +monster_nearby() { +register int x,y; +register struct monst *mtmp; + if(!Blind) + for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++){ + if(x == u.ux && y == u.uy) continue; + if((mtmp = m_at(x,y)) && !mtmp->mimic && !mtmp->mtame && + !mtmp->mpeaceful && !index("Ea", mtmp->data->mlet) && + !mtmp->mfroz && !mtmp->msleep && /* aplvax!jcn */ + (!mtmp->minvis || See_invisible)) + return(1); + } + return(0); +} + +#ifdef QUEST +cansee(x,y) xchar x,y; { +register int dx,dy,adx,ady,sdx,sdy,dmax,d; + if(Blind) return(0); + if(!isok(x,y)) return(0); + d = dist(x,y); + if(d < 3) return(1); + if(d > u.uhorizon*u.uhorizon) return(0); + if(!levl[x][y].lit) + return(0); + dx = x - u.ux; adx = abs(dx); sdx = sgn(dx); + dy = y - u.uy; ady = abs(dy); sdy = sgn(dy); + if(dx == 0 || dy == 0 || adx == ady){ + dmax = (dx == 0) ? ady : adx; + for(d = 1; d <= dmax; d++) + if(!rroom(sdx*d,sdy*d)) + return(0); + return(1); + } else if(ady > adx){ + for(d = 1; d <= ady; d++){ + if(!rroom(sdx*( (d*adx)/ady ), sdy*d) || + !rroom(sdx*( (d*adx-1)/ady+1 ), sdy*d)) + return(0); + } + return(1); + } else { + for(d = 1; d <= adx; d++){ + if(!rroom(sdx*d, sdy*( (d*ady)/adx )) || + !rroom(sdx*d, sdy*( (d*ady-1)/adx+1 ))) + return(0); + } + return(1); + } +} + +rroom(x,y) register int x,y; { + return(IS_ROOM(levl[u.ux+x][u.uy+y].typ)); +} + +#else + +cansee(x,y) xchar x,y; { + if(Blind || u.uswallow) return(0); + if(dist(x,y) < 3) return(1); + if(levl[x][y].lit && seelx <= x && x <= seehx && seely <= y && + y <= seehy) return(1); + return(0); +} +#endif QUEST + +sgn(a) register int a; { + return((a > 0) ? 1 : (a == 0) ? 0 : -1); +} + +#ifdef QUEST +setsee() +{ + register x,y; + + if(Blind) { + pru(); + return; + } + for(y = u.uy-u.uhorizon; y <= u.uy+u.uhorizon; y++) + for(x = u.ux-u.uhorizon; x <= u.ux+u.uhorizon; x++) { + if(cansee(x,y)) + prl(x,y); + } +} + +#else + +setsee() +{ + register x,y; + + if(Blind) { + pru(); + return; + } + if(!levl[u.ux][u.uy].lit) { + seelx = u.ux-1; + seehx = u.ux+1; + seely = u.uy-1; + seehy = u.uy+1; + } else { + for(seelx = u.ux; levl[seelx-1][u.uy].lit; seelx--); + for(seehx = u.ux; levl[seehx+1][u.uy].lit; seehx++); + for(seely = u.uy; levl[u.ux][seely-1].lit; seely--); + for(seehy = u.uy; levl[u.ux][seehy+1].lit; seehy++); + } + for(y = seely; y <= seehy; y++) + for(x = seelx; x <= seehx; x++) { + prl(x,y); + } + if(!levl[u.ux][u.uy].lit) seehx = 0; /* seems necessary elsewhere */ + else { + if(seely == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seely-1); + if(seehy == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seehy+1); + if(seelx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seelx-1,y); + if(seehx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seehx+1,y); + } +} +#endif QUEST + +nomul(nval) +register nval; +{ + if(multi < 0) return; + multi = nval; + flags.mv = flags.run = 0; +} + +abon() +{ + if(u.ustr == 3) return(-3); + else if(u.ustr < 6) return(-2); + else if(u.ustr < 8) return(-1); + else if(u.ustr < 17) return(0); + else if(u.ustr < 69) return(1); /* up to 18/50 */ + else if(u.ustr < 118) return(2); + else return(3); +} + +dbon() +{ + if(u.ustr < 6) return(-1); + else if(u.ustr < 16) return(0); + else if(u.ustr < 18) return(1); + else if(u.ustr == 18) return(2); /* up to 18 */ + else if(u.ustr < 94) return(3); /* up to 18/75 */ + else if(u.ustr < 109) return(4); /* up to 18/90 */ + else if(u.ustr < 118) return(5); /* up to 18/99 */ + else return(6); +} + +losestr(num) /* may kill you; cause may be poison or monster like 'A' */ +register num; +{ + u.ustr -= num; + while(u.ustr < 3) { + u.ustr++; + u.uhp -= 6; + u.uhpmax -= 6; + } + flags.botl = 1; +} + +losehp(n,knam) +register n; +register char *knam; +{ + u.uhp -= n; + if(u.uhp > u.uhpmax) + u.uhpmax = u.uhp; /* perhaps n was negative */ + flags.botl = 1; + if(u.uhp < 1) { + killer = knam; /* the thing that killed you */ + done("died"); + } +} + +losehp_m(n,mtmp) +register n; +register struct monst *mtmp; +{ + u.uhp -= n; + flags.botl = 1; + if(u.uhp < 1) + done_in_by(mtmp); +} + +losexp() /* hit by V or W */ +{ + register num; + extern long newuexp(); + + if(u.ulevel > 1) + pline("Goodbye level %u.", u.ulevel--); + else + u.uhp = -1; + num = rnd(10); + u.uhp -= num; + u.uhpmax -= num; + u.uexp = newuexp(); + flags.botl = 1; +} + +inv_weight(){ +register struct obj *otmp = invent; +register int wt = (u.ugold + 500)/1000; +register int carrcap; + if(Levitation) /* pugh@cornell */ + carrcap = MAX_CARR_CAP; + else { + carrcap = 5*(((u.ustr > 18) ? 20 : u.ustr) + u.ulevel); + if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP; + if(Wounded_legs & LEFT_SIDE) carrcap -= 10; + if(Wounded_legs & RIGHT_SIDE) carrcap -= 10; + } + while(otmp){ + wt += otmp->owt; + otmp = otmp->nobj; + } + return(wt - carrcap); +} + +inv_cnt(){ +register struct obj *otmp = invent; +register int ct = 0; + while(otmp){ + ct++; + otmp = otmp->nobj; + } + return(ct); +} + +long +newuexp() +{ + return(10*(1L << (u.ulevel-1))); +} diff --git a/usr/othersrc/games/hack/hack.do_name.c b/usr/othersrc/games/hack/hack.do_name.c new file mode 100644 index 0000000000..72ac62c862 --- /dev/null +++ b/usr/othersrc/games/hack/hack.do_name.c @@ -0,0 +1,289 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.do_name.c - version 1.0.3 */ + +#include "hack.h" +#include +extern char plname[]; + +coord +getpos(force,goal) int force; char *goal; { +register cx,cy,i,c; +extern char sdir[]; /* defined in hack.c */ +extern schar xdir[], ydir[]; /* idem */ +extern char *visctrl(); /* see below */ +coord cc; + pline("(For instructions type a ?)"); + cx = u.ux; + cy = u.uy; + curs(cx,cy+2); + while((c = readchar()) != '.'){ + for(i=0; i<8; i++) if(sdir[i] == c){ + if(1 <= cx + xdir[i] && cx + xdir[i] <= COLNO) + cx += xdir[i]; + if(0 <= cy + ydir[i] && cy + ydir[i] <= ROWNO-1) + cy += ydir[i]; + goto nxtc; + } + if(c == '?'){ + pline("Use [hjkl] to move the cursor to %s.", goal); + pline("Type a . when you are at the right place."); + } else { + pline("Unknown direction: '%s' (%s).", + visctrl(c), + force ? "use hjkl or ." : "aborted"); + if(force) goto nxtc; + cc.x = -1; + cc.y = 0; + return(cc); + } + nxtc: ; + curs(cx,cy+2); + } + cc.x = cx; + cc.y = cy; + return(cc); +} + +do_mname(){ +char buf[BUFSZ]; +coord cc; +register int cx,cy,lth,i; +register struct monst *mtmp, *mtmp2; +extern char *lmonnam(); + cc = getpos(0, "the monster you want to name"); + cx = cc.x; + cy = cc.y; + if(cx < 0) return(0); + mtmp = m_at(cx,cy); + if(!mtmp){ + if(cx == u.ux && cy == u.uy) + pline("This ugly monster is called %s and cannot be renamed.", + plname); + else + pline("There is no monster there."); + return(1); + } + if(mtmp->mimic){ + pline("I see no monster there."); + return(1); + } + if(!cansee(cx,cy)) { + pline("I cannot see a monster there."); + return(1); + } + pline("What do you want to call %s? ", lmonnam(mtmp)); + getlin(buf); + clrlin(); + if(!*buf || *buf == '\033') + return(1); + lth = strlen(buf)+1; + if(lth > 63){ + buf[62] = 0; + lth = 63; + } + mtmp2 = newmonst(mtmp->mxlth + lth); + *mtmp2 = *mtmp; + for(i=0; imxlth; i++) + ((char *) mtmp2->mextra)[i] = ((char *) mtmp->mextra)[i]; + mtmp2->mnamelth = lth; + (void) strcpy(NAME(mtmp2), buf); + replmon(mtmp,mtmp2); + return(1); +} + +/* + * This routine changes the address of obj . Be careful not to call it + * when there might be pointers around in unknown places. For now: only + * when obj is in the inventory. + */ +do_oname(obj) register struct obj *obj; { +register struct obj *otmp, *otmp2; +register lth; +char buf[BUFSZ]; + pline("What do you want to name %s? ", doname(obj)); + getlin(buf); + clrlin(); + if(!*buf || *buf == '\033') + return; + lth = strlen(buf)+1; + if(lth > 63){ + buf[62] = 0; + lth = 63; + } + otmp2 = newobj(lth); + *otmp2 = *obj; + otmp2->onamelth = lth; + (void) strcpy(ONAME(otmp2), buf); + + setworn((struct obj *) 0, obj->owornmask); + setworn(otmp2, otmp2->owornmask); + + /* do freeinv(obj); etc. by hand in order to preserve + the position of this object in the inventory */ + if(obj == invent) invent = otmp2; + else for(otmp = invent; ; otmp = otmp->nobj){ + if(!otmp) + panic("Do_oname: cannot find obj."); + if(otmp->nobj == obj){ + otmp->nobj = otmp2; + break; + } + } + /* obfree(obj, otmp2); /* now unnecessary: no pointers on bill */ + free((char *) obj); /* let us hope nobody else saved a pointer */ +} + +ddocall() +{ + register struct obj *obj; + + pline("Do you want to name an individual object? [ny] "); + switch(readchar()) { + case '\033': + break; + case 'y': + obj = getobj("#", "name"); + if(obj) do_oname(obj); + break; + default: + obj = getobj("?!=/", "call"); + if(obj) docall(obj); + } + return(0); +} + +docall(obj) +register struct obj *obj; +{ + char buf[BUFSZ]; + struct obj otemp; + register char **str1; + extern char *xname(); + register char *str; + + otemp = *obj; + otemp.quan = 1; + otemp.onamelth = 0; + str = xname(&otemp); + pline("Call %s %s: ", index(vowels,*str) ? "an" : "a", str); + getlin(buf); + clrlin(); + if(!*buf || *buf == '\033') + return; + str = newstring(strlen(buf)+1); + (void) strcpy(str,buf); + str1 = &(objects[obj->otyp].oc_uname); + if(*str1) free(*str1); + *str1 = str; +} + +char *ghostnames[] = { /* these names should have length < PL_NSIZ */ + "adri", "andries", "andreas", "bert", "david", "dirk", "emile", + "frans", "fred", "greg", "hether", "jay", "john", "jon", "kay", + "kenny", "maud", "michiel", "mike", "peter", "robert", "ron", + "tom", "wilmar" +}; + +char * +xmonnam(mtmp, vb) register struct monst *mtmp; int vb; { +static char buf[BUFSZ]; /* %% */ +extern char *shkname(); + if(mtmp->mnamelth && !vb) { + (void) strcpy(buf, NAME(mtmp)); + return(buf); + } + switch(mtmp->data->mlet) { + case ' ': + { register char *gn = (char *) mtmp->mextra; + if(!*gn) { /* might also look in scorefile */ + gn = ghostnames[rn2(SIZE(ghostnames))]; + if(!rn2(2)) (void) + strcpy((char *) mtmp->mextra, !rn2(5) ? plname : gn); + } + (void) sprintf(buf, "%s's ghost", gn); + } + break; + case '@': + if(mtmp->isshk) { + (void) strcpy(buf, shkname(mtmp)); + break; + } + /* fall into next case */ + default: + (void) sprintf(buf, "the %s%s", + mtmp->minvis ? "invisible " : "", + mtmp->data->mname); + } + if(vb && mtmp->mnamelth) { + (void) strcat(buf, " called "); + (void) strcat(buf, NAME(mtmp)); + } + return(buf); +} + +char * +lmonnam(mtmp) register struct monst *mtmp; { + return(xmonnam(mtmp, 1)); +} + +char * +monnam(mtmp) register struct monst *mtmp; { + return(xmonnam(mtmp, 0)); +} + +char * +Monnam(mtmp) register struct monst *mtmp; { +register char *bp = monnam(mtmp); + if('a' <= *bp && *bp <= 'z') *bp += ('A' - 'a'); + return(bp); +} + +char * +amonnam(mtmp,adj) +register struct monst *mtmp; +register char *adj; +{ + register char *bp = monnam(mtmp); + static char buf[BUFSZ]; /* %% */ + + if(!strncmp(bp, "the ", 4)) bp += 4; + (void) sprintf(buf, "the %s %s", adj, bp); + return(buf); +} + +char * +Amonnam(mtmp, adj) +register struct monst *mtmp; +register char *adj; +{ + register char *bp = amonnam(mtmp,adj); + + *bp = 'T'; + return(bp); +} + +char * +Xmonnam(mtmp) register struct monst *mtmp; { +register char *bp = Monnam(mtmp); + if(!strncmp(bp, "The ", 4)) { + bp += 2; + *bp = 'A'; + } + return(bp); +} + +char * +visctrl(c) +char c; +{ +static char ccc[3]; + if(c < 040) { + ccc[0] = '^'; + ccc[1] = c + 0100; + ccc[2] = 0; + } else { + ccc[0] = c; + ccc[1] = 0; + } + return(ccc); +} diff --git a/usr/othersrc/games/hack/hack.do_wear.c b/usr/othersrc/games/hack/hack.do_wear.c new file mode 100644 index 0000000000..423955d294 --- /dev/null +++ b/usr/othersrc/games/hack/hack.do_wear.c @@ -0,0 +1,336 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.do_wear.c - version 1.0.3 */ + +#include "hack.h" +#include +extern char *nomovemsg; +extern char quitchars[]; +extern char *Doname(); + +off_msg(otmp) register struct obj *otmp; { + pline("You were wearing %s.", doname(otmp)); +} + +doremarm() { + register struct obj *otmp; + if(!uarm && !uarmh && !uarms && !uarmg) { + pline("Not wearing any armor."); + return(0); + } + otmp = (!uarmh && !uarms && !uarmg) ? uarm : + (!uarms && !uarm && !uarmg) ? uarmh : + (!uarmh && !uarm && !uarmg) ? uarms : + (!uarmh && !uarm && !uarms) ? uarmg : + getobj("[", "take off"); + if(!otmp) return(0); + if(!(otmp->owornmask & (W_ARMOR - W_ARM2))) { + pline("You can't take that off."); + return(0); + } + if( otmp == uarmg && uwep && uwep->cursed ) { /* myers@uwmacc */ + pline("You seem not able to take off the gloves while holding your weapon."); + return(0); + } + (void) armoroff(otmp); + return(1); +} + +doremring() { + if(!uleft && !uright){ + pline("Not wearing any ring."); + return(0); + } + if(!uleft) + return(dorr(uright)); + if(!uright) + return(dorr(uleft)); + if(uleft && uright) while(1) { + char answer; + + pline("What ring, Right or Left? [ rl?]"); + if(index(quitchars, (answer = readchar()))) + return(0); + switch(answer) { + case 'l': + case 'L': + return(dorr(uleft)); + case 'r': + case 'R': + return(dorr(uright)); + case '?': + (void) doprring(); + /* might look at morc here %% */ + } + } + /* NOTREACHED */ +#ifdef lint + return(0); +#endif lint +} + +dorr(otmp) register struct obj *otmp; { + if(cursed(otmp)) return(0); + ringoff(otmp); + off_msg(otmp); + return(1); +} + +cursed(otmp) register struct obj *otmp; { + if(otmp->cursed){ + pline("You can't. It appears to be cursed."); + return(1); + } + return(0); +} + +armoroff(otmp) register struct obj *otmp; { +register int delay = -objects[otmp->otyp].oc_delay; + if(cursed(otmp)) return(0); + setworn((struct obj *) 0, otmp->owornmask & W_ARMOR); + if(delay) { + nomul(delay); + switch(otmp->otyp) { + case HELMET: + nomovemsg = "You finished taking off your helmet."; + break; + case PAIR_OF_GLOVES: + nomovemsg = "You finished taking off your gloves"; + break; + default: + nomovemsg = "You finished taking off your suit."; + } + } else { + off_msg(otmp); + } + return(1); +} + +doweararm() { + register struct obj *otmp; + register int delay; + register int err = 0; + long mask = 0; + + otmp = getobj("[", "wear"); + if(!otmp) return(0); + if(otmp->owornmask & W_ARMOR) { + pline("You are already wearing that!"); + return(0); + } + if(otmp->otyp == HELMET){ + if(uarmh) { + pline("You are already wearing a helmet."); + err++; + } else + mask = W_ARMH; + } else if(otmp->otyp == SHIELD){ + if(uarms) pline("You are already wearing a shield."), err++; + if(uwep && uwep->otyp == TWO_HANDED_SWORD) + pline("You cannot wear a shield and wield a two-handed sword."), err++; + if(!err) mask = W_ARMS; + } else if(otmp->otyp == PAIR_OF_GLOVES) { + if(uarmg) { + pline("You are already wearing gloves."); + err++; + } else + if(uwep && uwep->cursed) { + pline("You cannot wear gloves over your weapon."); + err++; + } else + mask = W_ARMG; + } else { + if(uarm) { + if(otmp->otyp != ELVEN_CLOAK || uarm2) { + pline("You are already wearing some armor."); + err++; + } + } + if(!err) mask = W_ARM; + } + if(otmp == uwep && uwep->cursed) { + if(!err++) + pline("%s is welded to your hand.", Doname(uwep)); + } + if(err) return(0); + setworn(otmp, mask); + if(otmp == uwep) + setuwep((struct obj *) 0); + delay = -objects[otmp->otyp].oc_delay; + if(delay){ + nomul(delay); + nomovemsg = "You finished your dressing manoeuvre."; + } + otmp->known = 1; + return(1); +} + +dowearring() { + register struct obj *otmp; + long mask = 0; + long oldprop; + + if(uleft && uright){ + pline("There are no more ring-fingers to fill."); + return(0); + } + otmp = getobj("=", "wear"); + if(!otmp) return(0); + if(otmp->owornmask & W_RING) { + pline("You are already wearing that!"); + return(0); + } + if(otmp == uleft || otmp == uright) { + pline("You are already wearing that."); + return(0); + } + if(otmp == uwep && uwep->cursed) { + pline("%s is welded to your hand.", Doname(uwep)); + return(0); + } + if(uleft) mask = RIGHT_RING; + else if(uright) mask = LEFT_RING; + else do { + char answer; + + pline("What ring-finger, Right or Left? "); + if(index(quitchars, (answer = readchar()))) + return(0); + switch(answer){ + case 'l': + case 'L': + mask = LEFT_RING; + break; + case 'r': + case 'R': + mask = RIGHT_RING; + break; + } + } while(!mask); + setworn(otmp, mask); + if(otmp == uwep) + setuwep((struct obj *) 0); + oldprop = u.uprops[PROP(otmp->otyp)].p_flgs; + u.uprops[PROP(otmp->otyp)].p_flgs |= mask; + switch(otmp->otyp){ + case RIN_LEVITATION: + if(!oldprop) float_up(); + break; + case RIN_PROTECTION_FROM_SHAPE_CHANGERS: + rescham(); + break; + case RIN_GAIN_STRENGTH: + u.ustr += otmp->spe; + u.ustrmax += otmp->spe; + if(u.ustr > 118) u.ustr = 118; + if(u.ustrmax > 118) u.ustrmax = 118; + flags.botl = 1; + break; + case RIN_INCREASE_DAMAGE: + u.udaminc += otmp->spe; + break; + } + prinv(otmp); + return(1); +} + +ringoff(obj) +register struct obj *obj; +{ +register long mask; + mask = obj->owornmask & W_RING; + setworn((struct obj *) 0, obj->owornmask); + if(!(u.uprops[PROP(obj->otyp)].p_flgs & mask)) + impossible("Strange... I didnt know you had that ring."); + u.uprops[PROP(obj->otyp)].p_flgs &= ~mask; + switch(obj->otyp) { + case RIN_FIRE_RESISTANCE: + /* Bad luck if the player is in hell... --jgm */ + if (!Fire_resistance && dlevel >= 30) { + pline("The flames of Hell burn you to a crisp."); + killer = "stupidity in hell"; + done("burned"); + } + break; + case RIN_LEVITATION: + if(!Levitation) { /* no longer floating */ + float_down(); + } + break; + case RIN_GAIN_STRENGTH: + u.ustr -= obj->spe; + u.ustrmax -= obj->spe; + if(u.ustr > 118) u.ustr = 118; + if(u.ustrmax > 118) u.ustrmax = 118; + flags.botl = 1; + break; + case RIN_INCREASE_DAMAGE: + u.udaminc -= obj->spe; + break; + } +} + +find_ac(){ +register int uac = 10; + if(uarm) uac -= ARM_BONUS(uarm); + if(uarm2) uac -= ARM_BONUS(uarm2); + if(uarmh) uac -= ARM_BONUS(uarmh); + if(uarms) uac -= ARM_BONUS(uarms); + if(uarmg) uac -= ARM_BONUS(uarmg); + if(uleft && uleft->otyp == RIN_PROTECTION) uac -= uleft->spe; + if(uright && uright->otyp == RIN_PROTECTION) uac -= uright->spe; + if(uac != u.uac){ + u.uac = uac; + flags.botl = 1; + } +} + +glibr(){ +register struct obj *otmp; +int xfl = 0; + if(!uarmg) if(uleft || uright) { + /* Note: at present also cursed rings fall off */ + pline("Your %s off your fingers.", + (uleft && uright) ? "rings slip" : "ring slips"); + xfl++; + if((otmp = uleft) != Null(obj)){ + ringoff(uleft); + dropx(otmp); + } + if((otmp = uright) != Null(obj)){ + ringoff(uright); + dropx(otmp); + } + } + if((otmp = uwep) != Null(obj)){ + /* Note: at present also cursed weapons fall */ + setuwep((struct obj *) 0); + dropx(otmp); + pline("Your weapon %sslips from your hands.", + xfl ? "also " : ""); + } +} + +struct obj * +some_armor(){ +register struct obj *otmph = uarm; + if(uarmh && (!otmph || !rn2(4))) otmph = uarmh; + if(uarmg && (!otmph || !rn2(4))) otmph = uarmg; + if(uarms && (!otmph || !rn2(4))) otmph = uarms; + return(otmph); +} + +corrode_armor(){ +register struct obj *otmph = some_armor(); + if(otmph){ + if(otmph->rustfree || + otmph->otyp == ELVEN_CLOAK || + otmph->otyp == LEATHER_ARMOR || + otmph->otyp == STUDDED_LEATHER_ARMOR) { + pline("Your %s not affected!", + aobjnam(otmph, "are")); + return; + } + pline("Your %s!", aobjnam(otmph, "corrode")); + otmph->spe--; + } +} diff --git a/usr/othersrc/games/hack/hack.dog.c b/usr/othersrc/games/hack/hack.dog.c new file mode 100644 index 0000000000..aa4387abbe --- /dev/null +++ b/usr/othersrc/games/hack/hack.dog.c @@ -0,0 +1,413 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.dog.c - version 1.0.3 */ + +#include "hack.h" +#include "hack.mfndpos.h" +extern struct monst *makemon(); +#include "def.edog.h" +#include "def.mkroom.h" + +struct permonst li_dog = + { "little dog", 'd',2,18,6,1,6,sizeof(struct edog) }; +struct permonst dog = + { "dog", 'd',4,16,5,1,6,sizeof(struct edog) }; +struct permonst la_dog = + { "large dog", 'd',6,15,4,2,4,sizeof(struct edog) }; + + +makedog(){ +register struct monst *mtmp = makemon(&li_dog,u.ux,u.uy); + if(!mtmp) return; /* dogs were genocided */ + initedog(mtmp); +} + +initedog(mtmp) register struct monst *mtmp; { + mtmp->mtame = mtmp->mpeaceful = 1; + EDOG(mtmp)->hungrytime = 1000 + moves; + EDOG(mtmp)->eattime = 0; + EDOG(mtmp)->droptime = 0; + EDOG(mtmp)->dropdist = 10000; + EDOG(mtmp)->apport = 10; + EDOG(mtmp)->whistletime = 0; +} + +/* attach the monsters that went down (or up) together with @ */ +struct monst *mydogs = 0; +struct monst *fallen_down = 0; /* monsters that fell through a trapdoor */ + /* they will appear on the next level @ goes to, even if he goes up! */ + +losedogs(){ +register struct monst *mtmp; + while(mtmp = mydogs){ + mydogs = mtmp->nmon; + mtmp->nmon = fmon; + fmon = mtmp; + mnexto(mtmp); + } + while(mtmp = fallen_down){ + fallen_down = mtmp->nmon; + mtmp->nmon = fmon; + fmon = mtmp; + rloc(mtmp); + } +} + +keepdogs(){ +register struct monst *mtmp; + for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) + if(dist(mtmp->mx,mtmp->my) < 3 && follower(mtmp) + && !mtmp->msleep && !mtmp->mfroz) { + relmon(mtmp); + mtmp->nmon = mydogs; + mydogs = mtmp; + unpmon(mtmp); + keepdogs(); /* we destroyed the link, so use recursion */ + return; /* (admittedly somewhat primitive) */ + } +} + +fall_down(mtmp) register struct monst *mtmp; { + relmon(mtmp); + mtmp->nmon = fallen_down; + fallen_down = mtmp; + unpmon(mtmp); + mtmp->mtame = 0; +} + +/* return quality of food; the lower the better */ +#define DOGFOOD 0 +#define CADAVER 1 +#define ACCFOOD 2 +#define MANFOOD 3 +#define APPORT 4 +#define POISON 5 +#define UNDEF 6 +dogfood(obj) register struct obj *obj; { + switch(obj->olet) { + case FOOD_SYM: + return( + (obj->otyp == TRIPE_RATION) ? DOGFOOD : + (obj->otyp < CARROT) ? ACCFOOD : + (obj->otyp < CORPSE) ? MANFOOD : + (poisonous(obj) || obj->age + 50 <= moves || + obj->otyp == DEAD_COCKATRICE) + ? POISON : CADAVER + ); + default: + if(!obj->cursed) return(APPORT); + /* fall into next case */ + case BALL_SYM: + case CHAIN_SYM: + case ROCK_SYM: + return(UNDEF); + } +} + +/* return 0 (no move), 1 (move) or 2 (dead) */ +dog_move(mtmp, after) register struct monst *mtmp; { +register int nx,ny,omx,omy,appr,nearer,j; +int udist,chi,i,whappr; +register struct monst *mtmp2; +register struct permonst *mdat = mtmp->data; +register struct edog *edog = EDOG(mtmp); +struct obj *obj; +struct trap *trap; +xchar cnt,chcnt,nix,niy; +schar dogroom,uroom; +xchar gx,gy,gtyp,otyp; /* current goal */ +coord poss[9]; +int info[9]; +#define GDIST(x,y) ((x-gx)*(x-gx) + (y-gy)*(y-gy)) +#define DDIST(x,y) ((x-omx)*(x-omx) + (y-omy)*(y-omy)) + + if(moves <= edog->eattime) return(0); /* dog is still eating */ + omx = mtmp->mx; + omy = mtmp->my; + whappr = (moves - EDOG(mtmp)->whistletime < 5); + if(moves > edog->hungrytime + 500 && !mtmp->mconf){ + mtmp->mconf = 1; + mtmp->mhpmax /= 3; + if(mtmp->mhp > mtmp->mhpmax) + mtmp->mhp = mtmp->mhpmax; + if(cansee(omx,omy)) + pline("%s is confused from hunger.", Monnam(mtmp)); + else pline("You feel worried about %s.", monnam(mtmp)); + } else + if(moves > edog->hungrytime + 750 || mtmp->mhp < 1){ + if(cansee(omx,omy)) + pline("%s dies from hunger.", Monnam(mtmp)); + else + pline("You have a sad feeling for a moment, then it passes."); + mondied(mtmp); + return(2); + } + dogroom = inroom(omx,omy); + uroom = inroom(u.ux,u.uy); + udist = dist(omx,omy); + + /* maybe we tamed him while being swallowed --jgm */ + if(!udist) return(0); + + /* if we are carrying sth then we drop it (perhaps near @) */ + /* Note: if apport == 1 then our behaviour is independent of udist */ + if(mtmp->minvent){ + if(!rn2(udist) || !rn2((int) edog->apport)) + if(rn2(10) < edog->apport){ + relobj(mtmp, (int) mtmp->minvis); + if(edog->apport > 1) edog->apport--; + edog->dropdist = udist; /* hpscdi!jon */ + edog->droptime = moves; + } + } else { + if(obj = o_at(omx,omy)) if(!index("0_", obj->olet)){ + if((otyp = dogfood(obj)) <= CADAVER){ + nix = omx; + niy = omy; + goto eatobj; + } + if(obj->owt < 10*mtmp->data->mlevel) + if(rn2(20) < edog->apport+3) + if(rn2(udist) || !rn2((int) edog->apport)){ + freeobj(obj); + unpobj(obj); + /* if(levl[omx][omy].scrsym == obj->olet) + newsym(omx,omy); */ + mpickobj(mtmp,obj); + } + } + } + + /* first we look for food */ + gtyp = UNDEF; /* no goal as yet */ +#ifdef LINT + gx = gy = 0; /* suppress 'used before set' message */ +#endif LINT + for(obj = fobj; obj; obj = obj->nobj) { + otyp = dogfood(obj); + if(otyp > gtyp || otyp == UNDEF) continue; + if(inroom(obj->ox,obj->oy) != dogroom) continue; + if(otyp < MANFOOD && + (dogroom >= 0 || DDIST(obj->ox,obj->oy) < 10)) { + if(otyp < gtyp || (otyp == gtyp && + DDIST(obj->ox,obj->oy) < DDIST(gx,gy))){ + gx = obj->ox; + gy = obj->oy; + gtyp = otyp; + } + } else + if(gtyp == UNDEF && dogroom >= 0 && + uroom == dogroom && + !mtmp->minvent && edog->apport > rn2(8)){ + gx = obj->ox; + gy = obj->oy; + gtyp = APPORT; + } + } + if(gtyp == UNDEF || + (gtyp != DOGFOOD && gtyp != APPORT && moves < edog->hungrytime)){ + if(dogroom < 0 || dogroom == uroom){ + gx = u.ux; + gy = u.uy; +#ifndef QUEST + } else { + int tmp = rooms[dogroom].fdoor; + cnt = rooms[dogroom].doorct; + + gx = gy = FAR; /* random, far away */ + while(cnt--){ + if(dist(gx,gy) > + dist(doors[tmp].x, doors[tmp].y)){ + gx = doors[tmp].x; + gy = doors[tmp].y; + } + tmp++; + } + /* here gx == FAR e.g. when dog is in a vault */ + if(gx == FAR || (gx == omx && gy == omy)){ + gx = u.ux; + gy = u.uy; + } +#endif QUEST + } + appr = (udist >= 9) ? 1 : (mtmp->mflee) ? -1 : 0; + if(after && udist <= 4 && gx == u.ux && gy == u.uy) + return(0); + if(udist > 1){ + if(!IS_ROOM(levl[u.ux][u.uy].typ) || !rn2(4) || + whappr || + (mtmp->minvent && rn2((int) edog->apport))) + appr = 1; + } + /* if you have dog food he'll follow you more closely */ + if(appr == 0){ + obj = invent; + while(obj){ + if(obj->otyp == TRIPE_RATION){ + appr = 1; + break; + } + obj = obj->nobj; + } + } + } else appr = 1; /* gtyp != UNDEF */ + if(mtmp->mconf) appr = 0; + + if(gx == u.ux && gy == u.uy && (dogroom != uroom || dogroom < 0)){ + extern coord *gettrack(); + register coord *cp; + cp = gettrack(omx,omy); + if(cp){ + gx = cp->x; + gy = cp->y; + } + } + + nix = omx; + niy = omy; + cnt = mfndpos(mtmp,poss,info,ALLOW_M | ALLOW_TRAPS); + chcnt = 0; + chi = -1; + for(i=0; idata->mlevel >= mdat->mlevel+2 || + mtmp2->data->mlet == 'c') + continue; + if(after) return(0); /* hit only once each move */ + + if(hitmm(mtmp, mtmp2) == 1 && rn2(4) && + mtmp2->mlstmv != moves && + hitmm(mtmp2,mtmp) == 2) return(2); + return(0); + } + + /* dog avoids traps */ + /* but perhaps we have to pass a trap in order to follow @ */ + if((info[i] & ALLOW_TRAPS) && (trap = t_at(nx,ny))){ + if(!trap->tseen && rn2(40)) continue; + if(rn2(10)) continue; + } + + /* dog eschewes cursed objects */ + /* but likes dog food */ + obj = fobj; + while(obj){ + if(obj->ox != nx || obj->oy != ny) + goto nextobj; + if(obj->cursed) goto nxti; + if(obj->olet == FOOD_SYM && + (otyp = dogfood(obj)) < MANFOOD && + (otyp < ACCFOOD || edog->hungrytime <= moves)){ + /* Note: our dog likes the food so much that he + might eat it even when it conceals a cursed object */ + nix = nx; + niy = ny; + chi = i; + eatobj: + edog->eattime = + moves + obj->quan * objects[obj->otyp].oc_delay; + if(edog->hungrytime < moves) + edog->hungrytime = moves; + edog->hungrytime += + 5*obj->quan * objects[obj->otyp].nutrition; + mtmp->mconf = 0; + if(cansee(nix,niy)) + pline("%s ate %s.", Monnam(mtmp), doname(obj)); + /* perhaps this was a reward */ + if(otyp != CADAVER) + edog->apport += 200/(edog->dropdist+moves-edog->droptime); + delobj(obj); + goto newdogpos; + } + nextobj: + obj = obj->nobj; + } + + for(j=0; jmtrack[j].x && ny == mtmp->mtrack[j].y) + if(rn2(4*(cnt-j))) goto nxti; + +/* Some stupid C compilers cannot compute the whole expression at once. */ + nearer = GDIST(nx,ny); + nearer -= GDIST(nix,niy); + nearer *= appr; + if((nearer == 0 && !rn2(++chcnt)) || nearer<0 || + (nearer > 0 && !whappr && + ((omx == nix && omy == niy && !rn2(3)) + || !rn2(12)) + )){ + nix = nx; + niy = ny; + if(nearer < 0) chcnt = 0; + chi = i; + } + nxti: ; + } +newdogpos: + if(nix != omx || niy != omy){ + if(info[chi] & ALLOW_U){ + (void) hitu(mtmp, d(mdat->damn, mdat->damd)+1); + return(0); + } + mtmp->mx = nix; + mtmp->my = niy; + for(j=MTSZ-1; j>0; j--) mtmp->mtrack[j] = mtmp->mtrack[j-1]; + mtmp->mtrack[0].x = omx; + mtmp->mtrack[0].y = omy; + } + if(mintrap(mtmp) == 2) /* he died */ + return(2); + pmon(mtmp); + return(1); +} + +/* return roomnumber or -1 */ +inroom(x,y) xchar x,y; { +#ifndef QUEST + register struct mkroom *croom = &rooms[0]; + while(croom->hx >= 0){ + if(croom->hx >= x-1 && croom->lx <= x+1 && + croom->hy >= y-1 && croom->ly <= y+1) + return(croom - rooms); + croom++; + } +#endif QUEST + return(-1); /* not in room or on door */ +} + +tamedog(mtmp, obj) +register struct monst *mtmp; +register struct obj *obj; +{ + register struct monst *mtmp2; + + if(flags.moonphase == FULL_MOON && night() && rn2(6)) + return(0); + + /* If we cannot tame him, at least he's no longer afraid. */ + mtmp->mflee = 0; + mtmp->mfleetim = 0; + if(mtmp->mtame || mtmp->mfroz || +#ifndef NOWORM + mtmp->wormno || +#endif NOWORM + mtmp->isshk || mtmp->isgd || index(" &@12", mtmp->data->mlet)) + return(0); /* no tame long worms? */ + if(obj) { + if(dogfood(obj) >= MANFOOD) return(0); + if(cansee(mtmp->mx,mtmp->my)){ + pline("%s devours the %s.", Monnam(mtmp), + objects[obj->otyp].oc_name); + } + obfree(obj, (struct obj *) 0); + } + mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth); + *mtmp2 = *mtmp; + mtmp2->mxlth = sizeof(struct edog); + if(mtmp->mnamelth) (void) strcpy(NAME(mtmp2), NAME(mtmp)); + initedog(mtmp2); + replmon(mtmp,mtmp2); + return(1); +} diff --git a/usr/othersrc/games/hack/hack.eat.c b/usr/othersrc/games/hack/hack.eat.c new file mode 100644 index 0000000000..f1a767779a --- /dev/null +++ b/usr/othersrc/games/hack/hack.eat.c @@ -0,0 +1,459 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.eat.c - version 1.0.3 */ + +#include "hack.h" +char POISONOUS[] = "ADKSVabhks"; +extern char *nomovemsg; +extern int (*afternmv)(); +extern int (*occupation)(); +extern char *occtxt; +extern struct obj *splitobj(), *addinv(); + +/* hunger texts used on bottom line (each 8 chars long) */ +#define SATIATED 0 +#define NOT_HUNGRY 1 +#define HUNGRY 2 +#define WEAK 3 +#define FAINTING 4 +#define FAINTED 5 +#define STARVED 6 + +char *hu_stat[] = { + "Satiated", + " ", + "Hungry ", + "Weak ", + "Fainting", + "Fainted ", + "Starved " +}; + +init_uhunger(){ + u.uhunger = 900; + u.uhs = NOT_HUNGRY; +} + +#define TTSZ SIZE(tintxts) +struct { char *txt; int nut; } tintxts[] = { + "It contains first quality peaches - what a surprise!", 40, + "It contains salmon - not bad!", 60, + "It contains apple juice - perhaps not what you hoped for.", 20, + "It contains some nondescript substance, tasting awfully.", 500, + "It contains rotten meat. You vomit.", -50, + "It turns out to be empty.", 0 +}; + +static struct { + struct obj *tin; + int usedtime, reqtime; +} tin; + +opentin(){ + register int r; + + if(!carried(tin.tin)) /* perhaps it was stolen? */ + return(0); /* %% probably we should use tinoid */ + if(tin.usedtime++ >= 50) { + pline("You give up your attempt to open the tin."); + return(0); + } + if(tin.usedtime < tin.reqtime) + return(1); /* still busy */ + + pline("You succeed in opening the tin."); + useup(tin.tin); + r = rn2(2*TTSZ); + if(r < TTSZ){ + pline(tintxts[r].txt); + lesshungry(tintxts[r].nut); + if(r == 1) /* SALMON */ { + Glib = rnd(15); + pline("Eating salmon made your fingers very slippery."); + } + } else { + pline("It contains spinach - this makes you feel like Popeye!"); + lesshungry(600); + if(u.ustr < 118) + u.ustr += rnd( ((u.ustr < 17) ? 19 : 118) - u.ustr); + if(u.ustr > u.ustrmax) u.ustrmax = u.ustr; + flags.botl = 1; + } + return(0); +} + +Meatdone(){ + u.usym = '@'; + prme(); +} + +doeat(){ + register struct obj *otmp; + register struct objclass *ftmp; + register tmp; + + /* Is there some food (probably a heavy corpse) here on the ground? */ + if(!Levitation) + for(otmp = fobj; otmp; otmp = otmp->nobj) { + if(otmp->ox == u.ux && otmp->oy == u.uy && + otmp->olet == FOOD_SYM) { + pline("There %s %s here; eat %s? [ny] ", + (otmp->quan == 1) ? "is" : "are", + doname(otmp), + (otmp->quan == 1) ? "it" : "one"); + if(readchar() == 'y') { + if(otmp->quan != 1) + (void) splitobj(otmp, 1); + freeobj(otmp); + otmp = addinv(otmp); + addtobill(otmp); + goto gotit; + } + } + } + otmp = getobj("%", "eat"); + if(!otmp) return(0); +gotit: + if(otmp->otyp == TIN){ + if(uwep) { + switch(uwep->otyp) { + case CAN_OPENER: + tmp = 1; + break; + case DAGGER: + case CRYSKNIFE: + tmp = 3; + break; + case PICK_AXE: + case AXE: + tmp = 6; + break; + default: + goto no_opener; + } + pline("Using your %s you try to open the tin.", + aobjnam(uwep, (char *) 0)); + } else { + no_opener: + pline("It is not so easy to open this tin."); + if(Glib) { + pline("The tin slips out of your hands."); + if(otmp->quan > 1) { + register struct obj *obj; + extern struct obj *splitobj(); + + obj = splitobj(otmp, 1); + if(otmp == uwep) setuwep(obj); + } + dropx(otmp); + return(1); + } + tmp = 10 + rn2(1 + 500/((int)(u.ulevel + u.ustr))); + } + tin.reqtime = tmp; + tin.usedtime = 0; + tin.tin = otmp; + occupation = opentin; + occtxt = "opening the tin"; + return(1); + } + ftmp = &objects[otmp->otyp]; + multi = -ftmp->oc_delay; + if(otmp->otyp >= CORPSE && eatcorpse(otmp)) goto eatx; + if(!rn2(7) && otmp->otyp != FORTUNE_COOKIE) { + pline("Blecch! Rotten food!"); + if(!rn2(4)) { + pline("You feel rather light headed."); + Confusion += d(2,4); + } else if(!rn2(4)&& !Blind) { + pline("Everything suddenly goes dark."); + Blind = d(2,10); + seeoff(0); + } else if(!rn2(3)) { + if(Blind) + pline("The world spins and you slap against the floor."); + else + pline("The world spins and goes dark."); + nomul(-rnd(10)); + nomovemsg = "You are conscious again."; + } + lesshungry(ftmp->nutrition / 4); + } else { + if(u.uhunger >= 1500) { + pline("You choke over your food."); + pline("You die..."); + killer = ftmp->oc_name; + done("choked"); + } + switch(otmp->otyp){ + case FOOD_RATION: + if(u.uhunger <= 200) + pline("That food really hit the spot!"); + else if(u.uhunger <= 700) + pline("That satiated your stomach!"); + else { + pline("You're having a hard time getting all that food down."); + multi -= 2; + } + lesshungry(ftmp->nutrition); + if(multi < 0) nomovemsg = "You finished your meal."; + break; + case TRIPE_RATION: + pline("Yak - dog food!"); + more_experienced(1,0); + flags.botl = 1; + if(rn2(2)){ + pline("You vomit."); + morehungry(20); + if(Sick) { + Sick = 0; /* David Neves */ + pline("What a relief!"); + } + } else lesshungry(ftmp->nutrition); + break; + default: + if(otmp->otyp >= CORPSE) + pline("That %s tasted terrible!",ftmp->oc_name); + else + pline("That %s was delicious!",ftmp->oc_name); + lesshungry(ftmp->nutrition); + if(otmp->otyp == DEAD_LIZARD && (Confusion > 2)) + Confusion = 2; + else +#ifdef QUEST + if(otmp->otyp == CARROT && !Blind){ + u.uhorizon++; + setsee(); + pline("Your vision improves."); + } else +#endif QUEST + if(otmp->otyp == FORTUNE_COOKIE) { + if(Blind) { + pline("This cookie has a scrap of paper inside!"); + pline("What a pity, that you cannot read it!"); + } else + outrumor(); + } else + if(otmp->otyp == LUMP_OF_ROYAL_JELLY) { + /* This stuff seems to be VERY healthy! */ + if(u.ustrmax < 118) u.ustrmax++; + if(u.ustr < u.ustrmax) u.ustr++; + u.uhp += rnd(20); + if(u.uhp > u.uhpmax) { + if(!rn2(17)) u.uhpmax++; + u.uhp = u.uhpmax; + } + heal_legs(); + } + break; + } + } +eatx: + if(multi<0 && !nomovemsg){ + static char msgbuf[BUFSZ]; + (void) sprintf(msgbuf, "You finished eating the %s.", + ftmp->oc_name); + nomovemsg = msgbuf; + } + useup(otmp); + return(1); +} + +/* called in hack.main.c */ +gethungry(){ + --u.uhunger; + if(moves % 2) { + if(Regeneration) u.uhunger--; + if(Hunger) u.uhunger--; + /* a3: if(Hunger & LEFT_RING) u.uhunger--; + if(Hunger & RIGHT_RING) u.uhunger--; + etc. */ + } + if(moves % 20 == 0) { /* jimt@asgb */ + if(uleft) u.uhunger--; + if(uright) u.uhunger--; + } + newuhs(TRUE); +} + +/* called after vomiting and after performing feats of magic */ +morehungry(num) register num; { + u.uhunger -= num; + newuhs(TRUE); +} + +/* called after eating something (and after drinking fruit juice) */ +lesshungry(num) register num; { + u.uhunger += num; + newuhs(FALSE); +} + +unfaint(){ + u.uhs = FAINTING; + flags.botl = 1; +} + +newuhs(incr) boolean incr; { + register int newhs, h = u.uhunger; + + newhs = (h > 1000) ? SATIATED : + (h > 150) ? NOT_HUNGRY : + (h > 50) ? HUNGRY : + (h > 0) ? WEAK : FAINTING; + + if(newhs == FAINTING) { + if(u.uhs == FAINTED) + newhs = FAINTED; + if(u.uhs <= WEAK || rn2(20-u.uhunger/10) >= 19) { + if(u.uhs != FAINTED && multi >= 0 /* %% */) { + pline("You faint from lack of food."); + nomul(-10+(u.uhunger/10)); + nomovemsg = "You regain consciousness."; + afternmv = unfaint; + newhs = FAINTED; + } + } else + if(u.uhunger < -(int)(200 + 25*u.ulevel)) { + u.uhs = STARVED; + flags.botl = 1; + bot(); + pline("You die from starvation."); + done("starved"); + } + } + + if(newhs != u.uhs) { + if(newhs >= WEAK && u.uhs < WEAK) + losestr(1); /* this may kill you -- see below */ + else + if(newhs < WEAK && u.uhs >= WEAK && u.ustr < u.ustrmax) + losestr(-1); + switch(newhs){ + case HUNGRY: + pline((!incr) ? "You only feel hungry now." : + (u.uhunger < 145) ? "You feel hungry." : + "You are beginning to feel hungry."); + break; + case WEAK: + pline((!incr) ? "You feel weak now." : + (u.uhunger < 45) ? "You feel weak." : + "You are beginning to feel weak."); + break; + } + u.uhs = newhs; + flags.botl = 1; + if(u.uhp < 1) { + pline("You die from hunger and exhaustion."); + killer = "exhaustion"; + done("starved"); + } + } +} + +#define CORPSE_I_TO_C(otyp) (char) ((otyp >= DEAD_ACID_BLOB)\ + ? 'a' + (otyp - DEAD_ACID_BLOB)\ + : '@' + (otyp - DEAD_HUMAN)) +poisonous(otmp) +register struct obj *otmp; +{ + return(index(POISONOUS, CORPSE_I_TO_C(otmp->otyp)) != 0); +} + +/* returns 1 if some text was printed */ +eatcorpse(otmp) register struct obj *otmp; { +register char let = CORPSE_I_TO_C(otmp->otyp); +register tp = 0; + if(let != 'a' && moves > otmp->age + 50 + rn2(100)) { + tp++; + pline("Ulch -- that meat was tainted!"); + pline("You get very sick."); + Sick = 10 + rn2(10); + u.usick_cause = objects[otmp->otyp].oc_name; + } else if(index(POISONOUS, let) && rn2(5)){ + tp++; + pline("Ecch -- that must have been poisonous!"); + if(!Poison_resistance){ + losestr(rnd(4)); + losehp(rnd(15), "poisonous corpse"); + } else + pline("You don't seem affected by the poison."); + } else if(index("ELNOPQRUuxz", let) && rn2(5)){ + tp++; + pline("You feel sick."); + losehp(rnd(8), "cadaver"); + } + switch(let) { + case 'L': + case 'N': + case 't': + Teleportation |= INTRINSIC; + break; + case 'W': + pluslvl(); + break; + case 'n': + u.uhp = u.uhpmax; + flags.botl = 1; + /* fall into next case */ + case '@': + pline("You cannibal! You will be sorry for this!"); + /* not tp++; */ + /* fall into next case */ + case 'd': + Aggravate_monster |= INTRINSIC; + break; + case 'I': + if(!Invis) { + Invis = 50+rn2(100); + if(!See_invisible) + newsym(u.ux, u.uy); + } else { + Invis |= INTRINSIC; + See_invisible |= INTRINSIC; + } + /* fall into next case */ + case 'y': +#ifdef QUEST + u.uhorizon++; +#endif QUEST + /* fall into next case */ + case 'B': + Confusion = 50; + break; + case 'D': + Fire_resistance |= INTRINSIC; + break; + case 'E': + Telepat |= INTRINSIC; + break; + case 'F': + case 'Y': + Cold_resistance |= INTRINSIC; + break; + case 'k': + case 's': + Poison_resistance |= INTRINSIC; + break; + case 'c': + pline("You turn to stone."); + killer = "dead cockatrice"; + done("died"); + /* NOTREACHED */ + case 'a': + if(Stoned) { + pline("What a pity - you just destroyed a future piece of art!"); + tp++; + Stoned = 0; + } + break; + case 'M': + pline("You cannot resist the temptation to mimic a treasure chest."); + tp++; + nomul(-30); + afternmv = Meatdone; + nomovemsg = "You now again prefer mimicking a human."; + u.usym = '$'; + prme(); + break; + } + return(tp); +} diff --git a/usr/othersrc/games/hack/hack.engrave.c b/usr/othersrc/games/hack/hack.engrave.c new file mode 100644 index 0000000000..dc16c39f95 --- /dev/null +++ b/usr/othersrc/games/hack/hack.engrave.c @@ -0,0 +1,306 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.engrave.c - version 1.0.3 */ + +#include "hack.h" + +extern char *nomovemsg; +extern char nul[]; +extern struct obj zeroobj; +struct engr { + struct engr *nxt_engr; + char *engr_txt; + xchar engr_x, engr_y; + unsigned engr_lth; /* for save & restore; not length of text */ + long engr_time; /* moment engraving was (will be) finished */ + xchar engr_type; +#define DUST 1 +#define ENGRAVE 2 +#define BURN 3 +} *head_engr; + +struct engr * +engr_at(x,y) register xchar x,y; { +register struct engr *ep = head_engr; + while(ep) { + if(x == ep->engr_x && y == ep->engr_y) + return(ep); + ep = ep->nxt_engr; + } + return((struct engr *) 0); +} + +sengr_at(s,x,y) register char *s; register xchar x,y; { +register struct engr *ep = engr_at(x,y); +register char *t; +register int n; + if(ep && ep->engr_time <= moves) { + t = ep->engr_txt; +/* + if(!strcmp(s,t)) return(1); +*/ + n = strlen(s); + while(*t) { + if(!strncmp(s,t,n)) return(1); + t++; + } + } + return(0); +} + +u_wipe_engr(cnt) +register int cnt; +{ + if(!u.uswallow && !Levitation) + wipe_engr_at(u.ux, u.uy, cnt); +} + +wipe_engr_at(x,y,cnt) register xchar x,y,cnt; { +register struct engr *ep = engr_at(x,y); +register int lth,pos; +char ch; + if(ep){ + if((ep->engr_type != DUST) || Levitation) { + cnt = rn2(1 + 50/(cnt+1)) ? 0 : 1; + } + lth = strlen(ep->engr_txt); + if(lth && cnt > 0 ) { + while(cnt--) { + pos = rn2(lth); + if((ch = ep->engr_txt[pos]) == ' ') + continue; + ep->engr_txt[pos] = (ch != '?') ? '?' : ' '; + } + } + while(lth && ep->engr_txt[lth-1] == ' ') + ep->engr_txt[--lth] = 0; + while(ep->engr_txt[0] == ' ') + ep->engr_txt++; + if(!ep->engr_txt[0]) del_engr(ep); + } +} + +read_engr_at(x,y) register int x,y; { +register struct engr *ep = engr_at(x,y); + if(ep && ep->engr_txt[0]) { + switch(ep->engr_type) { + case DUST: + pline("Something is written here in the dust."); + break; + case ENGRAVE: + pline("Something is engraved here on the floor."); + break; + case BURN: + pline("Some text has been burned here in the floor."); + break; + default: + impossible("Something is written in a very strange way."); + } + pline("You read: \"%s\".", ep->engr_txt); + } +} + +make_engr_at(x,y,s) +register int x,y; +register char *s; +{ + register struct engr *ep; + + if(ep = engr_at(x,y)) + del_engr(ep); + ep = (struct engr *) + alloc((unsigned)(sizeof(struct engr) + strlen(s) + 1)); + ep->nxt_engr = head_engr; + head_engr = ep; + ep->engr_x = x; + ep->engr_y = y; + ep->engr_txt = (char *)(ep + 1); + (void) strcpy(ep->engr_txt, s); + ep->engr_time = 0; + ep->engr_type = DUST; + ep->engr_lth = strlen(s) + 1; +} + +doengrave(){ +register int len; +register char *sp; +register struct engr *ep, *oep = engr_at(u.ux,u.uy); +char buf[BUFSZ]; +xchar type; +int spct; /* number of leading spaces */ +register struct obj *otmp; + multi = 0; + + if(u.uswallow) { + pline("You're joking. Hahaha!"); /* riv05!a3 */ + return(0); + } + + /* one may write with finger, weapon or wand */ + otmp = getobj("#-)/", "write with"); + if(!otmp) return(0); + + if(otmp == &zeroobj) + otmp = 0; + if(otmp && otmp->otyp == WAN_FIRE && otmp->spe) { + type = BURN; + otmp->spe--; + } else { + /* first wield otmp */ + if(otmp != uwep) { + if(uwep && uwep->cursed) { + /* Andreas Bormann */ + pline("Since your weapon is welded to your hand,"); + pline("you use the %s.", aobjnam(uwep, (char *) 0)); + otmp = uwep; + } else { + if(!otmp) + pline("You are now empty-handed."); + else if(otmp->cursed) + pline("The %s %s to your hand!", + aobjnam(otmp, "weld"), + (otmp->quan == 1) ? "itself" : "themselves"); + else + pline("You now wield %s.", doname(otmp)); + setuwep(otmp); + } + } + + if(!otmp) + type = DUST; + else + if(otmp->otyp == DAGGER || otmp->otyp == TWO_HANDED_SWORD || + otmp->otyp == CRYSKNIFE || + otmp->otyp == LONG_SWORD || otmp->otyp == AXE) { + type = ENGRAVE; + if((int)otmp->spe <= -3) { + type = DUST; + pline("Your %s too dull for engraving.", + aobjnam(otmp, "are")); + if(oep && oep->engr_type != DUST) return(1); + } + } else type = DUST; + } + if(Levitation && type != BURN){ /* riv05!a3 */ + pline("You can't reach the floor!"); + return(1); + } + if(oep && oep->engr_type == DUST){ + pline("You wipe out the message that was written here."); + del_engr(oep); + oep = 0; + } + if(type == DUST && oep){ + pline("You cannot wipe out the message that is %s in the rock.", + (oep->engr_type == BURN) ? "burned" : "engraved"); + return(1); + } + + pline("What do you want to %s on the floor here? ", + (type == ENGRAVE) ? "engrave" : (type == BURN) ? "burn" : "write"); + getlin(buf); + clrlin(); + spct = 0; + sp = buf; + while(*sp == ' ') spct++, sp++; + len = strlen(sp); + if(!len || *buf == '\033') { + if(type == BURN) otmp->spe++; + return(0); + } + + switch(type) { + case DUST: + case BURN: + if(len > 15) { + multi = -(len/10); + nomovemsg = "You finished writing."; + } + break; + case ENGRAVE: /* here otmp != 0 */ + { int len2 = (otmp->spe + 3) * 2 + 1; + + pline("Your %s dull.", aobjnam(otmp, "get")); + if(len2 < len) { + len = len2; + sp[len] = 0; + otmp->spe = -3; + nomovemsg = "You cannot engrave more."; + } else { + otmp->spe -= len/2; + nomovemsg = "You finished engraving."; + } + multi = -len; + } + break; + } + if(oep) len += strlen(oep->engr_txt) + spct; + ep = (struct engr *) alloc((unsigned)(sizeof(struct engr) + len + 1)); + ep->nxt_engr = head_engr; + head_engr = ep; + ep->engr_x = u.ux; + ep->engr_y = u.uy; + sp = (char *)(ep + 1); /* (char *)ep + sizeof(struct engr) */ + ep->engr_txt = sp; + if(oep) { + (void) strcpy(sp, oep->engr_txt); + (void) strcat(sp, buf); + del_engr(oep); + } else + (void) strcpy(sp, buf); + ep->engr_lth = len+1; + ep->engr_type = type; + ep->engr_time = moves-multi; + + /* kludge to protect pline against excessively long texts */ + if(len > BUFSZ-20) sp[BUFSZ-20] = 0; + + return(1); +} + +save_engravings(fd) int fd; { +register struct engr *ep = head_engr; + while(ep) { + if(!ep->engr_lth || !ep->engr_txt[0]){ + ep = ep->nxt_engr; + continue; + } + bwrite(fd, (char *) & (ep->engr_lth), sizeof(ep->engr_lth)); + bwrite(fd, (char *) ep, sizeof(struct engr) + ep->engr_lth); + ep = ep->nxt_engr; + } + bwrite(fd, (char *) nul, sizeof(unsigned)); + head_engr = 0; +} + +rest_engravings(fd) int fd; { +register struct engr *ep; +unsigned lth; + head_engr = 0; + while(1) { + mread(fd, (char *) <h, sizeof(unsigned)); + if(lth == 0) return; + ep = (struct engr *) alloc(sizeof(struct engr) + lth); + mread(fd, (char *) ep, sizeof(struct engr) + lth); + ep->nxt_engr = head_engr; + ep->engr_txt = (char *) (ep + 1); /* Andreas Bormann */ + head_engr = ep; + } +} + +del_engr(ep) register struct engr *ep; { +register struct engr *ept; + if(ep == head_engr) + head_engr = ep->nxt_engr; + else { + for(ept = head_engr; ept; ept = ept->nxt_engr) { + if(ept->nxt_engr == ep) { + ept->nxt_engr = ep->nxt_engr; + goto fnd; + } + } + impossible("Error in del_engr?"); + return; + fnd: ; + } + free((char *) ep); +} diff --git a/usr/othersrc/games/hack/hack.fight.c b/usr/othersrc/games/hack/hack.fight.c new file mode 100644 index 0000000000..ede886d169 --- /dev/null +++ b/usr/othersrc/games/hack/hack.fight.c @@ -0,0 +1,358 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.fight.c - version 1.0.3 */ + +#include "hack.h" +extern struct permonst li_dog, dog, la_dog; +extern char *exclam(), *xname(); +extern struct obj *mkobj_at(); + +static boolean far_noise; +static long noisetime; + +/* hitmm returns 0 (miss), 1 (hit), or 2 (kill) */ +hitmm(magr,mdef) register struct monst *magr,*mdef; { +register struct permonst *pa = magr->data, *pd = mdef->data; +int hit; +schar tmp; +boolean vis; + if(index("Eauy", pa->mlet)) return(0); + if(magr->mfroz) return(0); /* riv05!a3 */ + tmp = pd->ac + pa->mlevel; + if(mdef->mconf || mdef->mfroz || mdef->msleep){ + tmp += 4; + if(mdef->msleep) mdef->msleep = 0; + } + hit = (tmp > rnd(20)); + if(hit) mdef->msleep = 0; + vis = (cansee(magr->mx,magr->my) && cansee(mdef->mx,mdef->my)); + if(vis){ + char buf[BUFSZ]; + if(mdef->mimic) seemimic(mdef); + if(magr->mimic) seemimic(magr); + (void) sprintf(buf,"%s %s", Monnam(magr), + hit ? "hits" : "misses"); + pline("%s %s.", buf, monnam(mdef)); + } else { + boolean far = (dist(magr->mx, magr->my) > 15); + if(far != far_noise || moves-noisetime > 10) { + far_noise = far; + noisetime = moves; + pline("You hear some noises%s.", + far ? " in the distance" : ""); + } + } + if(hit){ + if(magr->data->mlet == 'c' && !magr->cham) { + magr->mhpmax += 3; + if(vis) pline("%s is turned to stone!", Monnam(mdef)); + else if(mdef->mtame) + pline("You have a peculiarly sad feeling for a moment, then it passes."); + monstone(mdef); + hit = 2; + } else + if((mdef->mhp -= d(pa->damn,pa->damd)) < 1) { + magr->mhpmax += 1 + rn2(pd->mlevel+1); + if(magr->mtame && magr->mhpmax > 8*pa->mlevel){ + if(pa == &li_dog) magr->data = pa = &dog; + else if(pa == &dog) magr->data = pa = &la_dog; + } + if(vis) pline("%s is killed!", Monnam(mdef)); + else if(mdef->mtame) + pline("You have a sad feeling for a moment, then it passes."); + mondied(mdef); + hit = 2; + } + } + return(hit); +} + +/* drop (perhaps) a cadaver and remove monster */ +mondied(mdef) register struct monst *mdef; { +register struct permonst *pd = mdef->data; + if(letter(pd->mlet) && rn2(3)){ + (void) mkobj_at(pd->mlet,mdef->mx,mdef->my); + if(cansee(mdef->mx,mdef->my)){ + unpmon(mdef); + atl(mdef->mx,mdef->my,fobj->olet); + } + stackobj(fobj); + } + mondead(mdef); +} + +/* drop a rock and remove monster */ +monstone(mdef) register struct monst *mdef; { + extern char mlarge[]; + if(index(mlarge, mdef->data->mlet)) + mksobj_at(ENORMOUS_ROCK, mdef->mx, mdef->my); + else + mksobj_at(ROCK, mdef->mx, mdef->my); + if(cansee(mdef->mx, mdef->my)){ + unpmon(mdef); + atl(mdef->mx,mdef->my,fobj->olet); + } + mondead(mdef); +} + + +fightm(mtmp) register struct monst *mtmp; { +register struct monst *mon; + for(mon = fmon; mon; mon = mon->nmon) if(mon != mtmp) { + if(DIST(mon->mx,mon->my,mtmp->mx,mtmp->my) < 3) + if(rn2(4)) + return(hitmm(mtmp,mon)); + } + return(-1); +} + +/* u is hit by sth, but not a monster */ +thitu(tlev,dam,name) +register tlev,dam; +register char *name; +{ +char buf[BUFSZ]; + setan(name,buf); + if(u.uac + tlev <= rnd(20)) { + if(Blind) pline("It misses."); + else pline("You are almost hit by %s!", buf); + return(0); + } else { + if(Blind) pline("You are hit!"); + else pline("You are hit by %s!", buf); + losehp(dam,name); + return(1); + } +} + +char mlarge[] = "bCDdegIlmnoPSsTUwY',&"; + +boolean +hmon(mon,obj,thrown) /* return TRUE if mon still alive */ +register struct monst *mon; +register struct obj *obj; +register thrown; +{ + register tmp; + boolean hittxt = FALSE; + + if(!obj){ + tmp = rnd(2); /* attack with bare hands */ + if(mon->data->mlet == 'c' && !uarmg){ + pline("You hit the cockatrice with your bare hands."); + pline("You turn to stone ..."); + done_in_by(mon); + } + } else if(obj->olet == WEAPON_SYM || obj->otyp == PICK_AXE) { + if(obj == uwep && (obj->otyp > SPEAR || obj->otyp < BOOMERANG)) + tmp = rnd(2); + else { + if(index(mlarge, mon->data->mlet)) { + tmp = rnd(objects[obj->otyp].wldam); + if(obj->otyp == TWO_HANDED_SWORD) tmp += d(2,6); + else if(obj->otyp == FLAIL) tmp += rnd(4); + } else { + tmp = rnd(objects[obj->otyp].wsdam); + } + tmp += obj->spe; + if(!thrown && obj == uwep && obj->otyp == BOOMERANG + && !rn2(3)){ + pline("As you hit %s, the boomerang breaks into splinters.", + monnam(mon)); + freeinv(obj); + setworn((struct obj *) 0, obj->owornmask); + obfree(obj, (struct obj *) 0); + tmp++; + } + } + if(mon->data->mlet == 'O' && obj->otyp == TWO_HANDED_SWORD && + !strcmp(ONAME(obj), "Orcrist")) + tmp += rnd(10); + } else switch(obj->otyp) { + case HEAVY_IRON_BALL: + tmp = rnd(25); break; + case EXPENSIVE_CAMERA: + pline("You succeed in destroying your camera. Congratulations!"); + freeinv(obj); + if(obj->owornmask) + setworn((struct obj *) 0, obj->owornmask); + obfree(obj, (struct obj *) 0); + return(TRUE); + case DEAD_COCKATRICE: + pline("You hit %s with the cockatrice corpse.", + monnam(mon)); + if(mon->data->mlet == 'c') { + tmp = 1; + hittxt = TRUE; + break; + } + pline("%s is turned to stone!", Monnam(mon)); + killed(mon); + return(FALSE); + case CLOVE_OF_GARLIC: /* no effect against demons */ + if(index(UNDEAD, mon->data->mlet)) + mon->mflee = 1; + tmp = 1; + break; + default: + /* non-weapons can damage because of their weight */ + /* (but not too much) */ + tmp = obj->owt/10; + if(tmp < 1) tmp = 1; + else tmp = rnd(tmp); + if(tmp > 6) tmp = 6; + } + + /****** NOTE: perhaps obj is undefined!! (if !thrown && BOOMERANG) */ + + tmp += u.udaminc + dbon(); + if(u.uswallow) { + if((tmp -= u.uswldtim) <= 0) { + pline("Your arms are no longer able to hit."); + return(TRUE); + } + } + if(tmp < 1) tmp = 1; + mon->mhp -= tmp; + if(mon->mhp < 1) { + killed(mon); + return(FALSE); + } + if(mon->mtame && (!mon->mflee || mon->mfleetim)) { + mon->mflee = 1; /* Rick Richardson */ + mon->mfleetim += 10*rnd(tmp); + } + + if(!hittxt) { + if(thrown) + /* this assumes that we cannot throw plural things */ + hit( xname(obj) /* or: objects[obj->otyp].oc_name */, + mon, exclam(tmp) ); + else if(Blind) + pline("You hit it."); + else + pline("You hit %s%s", monnam(mon), exclam(tmp)); + } + + if(u.umconf && !thrown) { + if(!Blind) { + pline("Your hands stop glowing blue."); + if(!mon->mfroz && !mon->msleep) + pline("%s appears confused.",Monnam(mon)); + } + mon->mconf = 1; + u.umconf = 0; + } + return(TRUE); /* mon still alive */ +} + +/* try to attack; return FALSE if monster evaded */ +/* u.dx and u.dy must be set */ +attack(mtmp) +register struct monst *mtmp; +{ + schar tmp; + boolean malive = TRUE; + register struct permonst *mdat; + mdat = mtmp->data; + + u_wipe_engr(3); /* andrew@orca: prevent unlimited pick-axe attacks */ + + if(mdat->mlet == 'L' && !mtmp->mfroz && !mtmp->msleep && + !mtmp->mconf && mtmp->mcansee && !rn2(7) && + (m_move(mtmp, 0) == 2 /* he died */ || /* he moved: */ + mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) + return(FALSE); + + if(mtmp->mimic){ + if(!u.ustuck && !mtmp->mflee) u.ustuck = mtmp; + switch(levl[u.ux+u.dx][u.uy+u.dy].scrsym){ + case '+': + pline("The door actually was a Mimic."); + break; + case '$': + pline("The chest was a Mimic!"); + break; + default: + pline("Wait! That's a Mimic!"); + } + wakeup(mtmp); /* clears mtmp->mimic */ + return(TRUE); + } + + wakeup(mtmp); + + if(mtmp->mhide && mtmp->mundetected){ + register struct obj *obj; + + mtmp->mundetected = 0; + if((obj = o_at(mtmp->mx,mtmp->my)) && !Blind) + pline("Wait! There's a %s hiding under %s!", + mdat->mname, doname(obj)); + return(TRUE); + } + + tmp = u.uluck + u.ulevel + mdat->ac + abon(); + if(uwep) { + if(uwep->olet == WEAPON_SYM || uwep->otyp == PICK_AXE) + tmp += uwep->spe; + if(uwep->otyp == TWO_HANDED_SWORD) tmp -= 1; + else if(uwep->otyp == DAGGER) tmp += 2; + else if(uwep->otyp == CRYSKNIFE) tmp += 3; + else if(uwep->otyp == SPEAR && + index("XDne", mdat->mlet)) tmp += 2; + } + if(mtmp->msleep) { + mtmp->msleep = 0; + tmp += 2; + } + if(mtmp->mfroz) { + tmp += 4; + if(!rn2(10)) mtmp->mfroz = 0; + } + if(mtmp->mflee) tmp += 2; + if(u.utrap) tmp -= 3; + + /* with a lot of luggage, your agility diminishes */ + tmp -= (inv_weight() + 40)/20; + + if(tmp <= rnd(20) && !u.uswallow){ + if(Blind) pline("You miss it."); + else pline("You miss %s.",monnam(mtmp)); + } else { + /* we hit the monster; be careful: it might die! */ + + if((malive = hmon(mtmp,uwep,0)) == TRUE) { + /* monster still alive */ + if(!rn2(25) && mtmp->mhp < mtmp->mhpmax/2) { + mtmp->mflee = 1; + if(!rn2(3)) mtmp->mfleetim = rnd(100); + if(u.ustuck == mtmp && !u.uswallow) + u.ustuck = 0; + } +#ifndef NOWORM + if(mtmp->wormno) + cutworm(mtmp, u.ux+u.dx, u.uy+u.dy, + uwep ? uwep->otyp : 0); +#endif NOWORM + } + if(mdat->mlet == 'a') { + if(rn2(2)) { + pline("You are splashed by the blob's acid!"); + losehp_m(rnd(6), mtmp); + if(!rn2(30)) corrode_armor(); + } + if(!rn2(6)) corrode_weapon(); + } + } + if(malive && mdat->mlet == 'E' && canseemon(mtmp) + && !mtmp->mcan && rn2(3)) { + if(mtmp->mcansee) { + pline("You are frozen by the floating eye's gaze!"); + nomul((u.ulevel > 6 || rn2(4)) ? rn1(20,-21) : -200); + } else { + pline("The blinded floating eye cannot defend itself."); + if(!rn2(500)) if((int)u.uluck > LUCKMIN) u.uluck--; + } + } + return(TRUE); +} diff --git a/usr/othersrc/games/hack/hack.fix b/usr/othersrc/games/hack/hack.fix new file mode 100644 index 0000000000..01e6460247 --- /dev/null +++ b/usr/othersrc/games/hack/hack.fix @@ -0,0 +1,113 @@ +/***** unido:net.games.hack / ab / 7:23 pm Sep 13, 1985*/ + +Recently hack (1.0.3) crashed with core dumps during some good games. +The crashes occured in the onbill-routine. After investigating the core +dump I found that the shopkeeper's bill was still to be paid. Normaly +if you leave a shop the bill will be cleared and onbill() would not +check it. But under certain conditions you can leave a shop without +clearing the bill. The conditions are: + + 1. You have to rob a shop in order to make the shopkeeper + follow you. + + 2. After leaving the shop being followed by the shopkeeper + you must return to the shop... + + 3. ...and then leave the unguarded shop again. + - The shopkeeper mustn't be present! + +If you climb the stairs to the previous level, chances are that your +bill now contains much more items than allowed. If so the next call to +onbill() will dump the core. + +Following is a context diff to fix the bug. Actually just the last hunk +does the fix [it deletes two lines which have been inserted in 1.0.3], +but I think the other fix was intended by the now deleted lines. + + Andreas + +-- +Andreas Bormann ab@unido.UUCP +University of Dortmund N 51 29' 05" E 07 24' 42" +West Germany + +------ the diff follows: + +*** hack.shk.c.orig Sun Aug 4 12:07:51 1985 +--- hack.shk.c Fri Sep 13 14:29:52 1985 +*************** +*** 133,139 + /* Did we just leave a shop? */ + if(u.uinshop && + (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) { +- u.uinshop = 0; + if(shopkeeper) { + if(ESHK(shopkeeper)->billct) { + pline("Somehow you escaped the shop without paying!"); + +--- 133,138 ----- + /* Did we just leave a shop? */ + if(u.uinshop && + (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) { + if(shopkeeper) { + if(ESHK(shopkeeper)->billct) { + if(inroom(shopkeeper->mx, shopkeeper->my) +*************** +*** 136,142 + u.uinshop = 0; + if(shopkeeper) { + if(ESHK(shopkeeper)->billct) { +! pline("Somehow you escaped the shop without paying!"); + addupbill(); + pline("You stole for a total worth of %ld zorkmids.", + total); + +--- 135,143 ----- + (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) { + if(shopkeeper) { + if(ESHK(shopkeeper)->billct) { +! if(inroom(shopkeeper->mx, shopkeeper->my) +! == u.uinshop - 1) /* ab@unido */ +! pline("Somehow you escaped the shop without paying!"); + addupbill(); + pline("You stole for a total worth of %ld zorkmids.", + total); +*************** +*** 149,154 + shopkeeper = 0; + shlevel = 0; + } + } + + /* Did we just enter a zoo of some kind? */ + +--- 150,156 ----- + shopkeeper = 0; + shlevel = 0; + } ++ u.uinshop = 0; + } + + /* Did we just enter a zoo of some kind? */ +*************** +*** 183,190 + findshk(roomno); + if(!shopkeeper) { + rooms[roomno].rtype = 0; +- u.uinshop = 0; +- } else if(inroom(shopkeeper->mx, shopkeeper->my) != roomno) { + u.uinshop = 0; + } else if(!u.uinshop){ + if(!ESHK(shopkeeper)->visitct || + +--- 185,190 ----- + findshk(roomno); + if(!shopkeeper) { + rooms[roomno].rtype = 0; + u.uinshop = 0; + } else if(!u.uinshop){ + if(!ESHK(shopkeeper)->visitct || +/* ---------- */ + + + diff --git a/usr/othersrc/games/hack/hack.invent.c b/usr/othersrc/games/hack/hack.invent.c new file mode 100644 index 0000000000..c4620ca129 --- /dev/null +++ b/usr/othersrc/games/hack/hack.invent.c @@ -0,0 +1,863 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.invent.c - version 1.0.3 */ + +#include "hack.h" +#include +extern struct obj *splitobj(); +extern struct obj zeroobj; +extern char morc; +extern char quitchars[]; +char *xprname(); + +#ifndef NOWORM +#include "def.wseg.h" +extern struct wseg *wsegs[32]; +#endif NOWORM + +#define NOINVSYM '#' + +static int lastinvnr = 51; /* 0 ... 51 */ +static +assigninvlet(otmp) +register struct obj *otmp; +{ + boolean inuse[52]; + register int i; + register struct obj *obj; + + for(i = 0; i < 52; i++) inuse[i] = FALSE; + for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) { + i = obj->invlet; + if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else + if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE; + if(i == otmp->invlet) otmp->invlet = 0; + } + if((i = otmp->invlet) && + (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z'))) + return; + for(i = lastinvnr+1; i != lastinvnr; i++) { + if(i == 52) { i = -1; continue; } + if(!inuse[i]) break; + } + otmp->invlet = (inuse[i] ? NOINVSYM : + (i < 26) ? ('a'+i) : ('A'+i-26)); + lastinvnr = i; +} + +struct obj * +addinv(obj) +register struct obj *obj; +{ + register struct obj *otmp; + + /* merge or attach to end of chain */ + if(!invent) { + invent = obj; + otmp = 0; + } else + for(otmp = invent; /* otmp */; otmp = otmp->nobj) { + if(merged(otmp, obj, 0)) + return(otmp); + if(!otmp->nobj) { + otmp->nobj = obj; + break; + } + } + obj->nobj = 0; + + if(flags.invlet_constant) { + assigninvlet(obj); + /* + * The ordering of the chain is nowhere significant + * so in case you prefer some other order than the + * historical one, change the code below. + */ + if(otmp) { /* find proper place in chain */ + otmp->nobj = 0; + if((invent->invlet ^ 040) > (obj->invlet ^ 040)) { + obj->nobj = invent; + invent = obj; + } else + for(otmp = invent; ; otmp = otmp->nobj) { + if(!otmp->nobj || + (otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){ + obj->nobj = otmp->nobj; + otmp->nobj = obj; + break; + } + } + } + } + + return(obj); +} + +useup(obj) +register struct obj *obj; +{ + if(obj->quan > 1){ + obj->quan--; + obj->owt = weight(obj); + } else { + setnotworn(obj); + freeinv(obj); + obfree(obj, (struct obj *) 0); + } +} + +freeinv(obj) +register struct obj *obj; +{ + register struct obj *otmp; + + if(obj == invent) + invent = invent->nobj; + else { + for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj) + if(!otmp->nobj) panic("freeinv"); + otmp->nobj = obj->nobj; + } +} + +/* destroy object in fobj chain (if unpaid, it remains on the bill) */ +delobj(obj) register struct obj *obj; { + freeobj(obj); + unpobj(obj); + obfree(obj, (struct obj *) 0); +} + +/* unlink obj from chain starting with fobj */ +freeobj(obj) register struct obj *obj; { + register struct obj *otmp; + + if(obj == fobj) fobj = fobj->nobj; + else { + for(otmp = fobj; otmp->nobj != obj; otmp = otmp->nobj) + if(!otmp) panic("error in freeobj"); + otmp->nobj = obj->nobj; + } +} + +/* Note: freegold throws away its argument! */ +freegold(gold) register struct gold *gold; { + register struct gold *gtmp; + + if(gold == fgold) fgold = gold->ngold; + else { + for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold) + if(!gtmp) panic("error in freegold"); + gtmp->ngold = gold->ngold; + } + free((char *) gold); +} + +deltrap(trap) +register struct trap *trap; +{ + register struct trap *ttmp; + + if(trap == ftrap) + ftrap = ftrap->ntrap; + else { + for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ; + ttmp->ntrap = trap->ntrap; + } + free((char *) trap); +} + +struct wseg *m_atseg; + +struct monst * +m_at(x,y) +register x,y; +{ + register struct monst *mtmp; +#ifndef NOWORM + register struct wseg *wtmp; +#endif NOWORM + + m_atseg = 0; + for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){ + if(mtmp->mx == x && mtmp->my == y) + return(mtmp); +#ifndef NOWORM + if(mtmp->wormno){ + for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg) + if(wtmp->wx == x && wtmp->wy == y){ + m_atseg = wtmp; + return(mtmp); + } + } +#endif NOWORM + } + return(0); +} + +struct obj * +o_at(x,y) +register x,y; +{ + register struct obj *otmp; + + for(otmp = fobj; otmp; otmp = otmp->nobj) + if(otmp->ox == x && otmp->oy == y) return(otmp); + return(0); +} + +struct obj * +sobj_at(n,x,y) +register n,x,y; +{ + register struct obj *otmp; + + for(otmp = fobj; otmp; otmp = otmp->nobj) + if(otmp->ox == x && otmp->oy == y && otmp->otyp == n) + return(otmp); + return(0); +} + +carried(obj) register struct obj *obj; { +register struct obj *otmp; + for(otmp = invent; otmp; otmp = otmp->nobj) + if(otmp == obj) return(1); + return(0); +} + +carrying(type) +register int type; +{ + register struct obj *otmp; + + for(otmp = invent; otmp; otmp = otmp->nobj) + if(otmp->otyp == type) + return(TRUE); + return(FALSE); +} + +struct obj * +o_on(id, objchn) unsigned int id; register struct obj *objchn; { + while(objchn) { + if(objchn->o_id == id) return(objchn); + objchn = objchn->nobj; + } + return((struct obj *) 0); +} + +struct trap * +t_at(x,y) +register x,y; +{ + register struct trap *trap = ftrap; + while(trap) { + if(trap->tx == x && trap->ty == y) return(trap); + trap = trap->ntrap; + } + return(0); +} + +struct gold * +g_at(x,y) +register x,y; +{ + register struct gold *gold = fgold; + while(gold) { + if(gold->gx == x && gold->gy == y) return(gold); + gold = gold->ngold; + } + return(0); +} + +/* make dummy object structure containing gold - for temporary use only */ +struct obj * +mkgoldobj(q) +register long q; +{ + register struct obj *otmp; + + otmp = newobj(0); + /* should set o_id etc. but otmp will be freed soon */ + otmp->olet = '$'; + u.ugold -= q; + OGOLD(otmp) = q; + flags.botl = 1; + return(otmp); +} + +/* + * getobj returns: + * struct obj *xxx: object to do something with. + * (struct obj *) 0 error return: no object. + * &zeroobj explicitly no object (as in w-). + */ +struct obj * +getobj(let,word) +register char *let,*word; +{ + register struct obj *otmp; + register char ilet,ilet1,ilet2; + char buf[BUFSZ]; + char lets[BUFSZ]; + register int foo = 0, foo2; + register char *bp = buf; + xchar allowcnt = 0; /* 0, 1 or 2 */ + boolean allowgold = FALSE; + boolean allowall = FALSE; + boolean allownone = FALSE; + xchar foox = 0; + long cnt; + + if(*let == '0') let++, allowcnt = 1; + if(*let == '$') let++, allowgold = TRUE; + if(*let == '#') let++, allowall = TRUE; + if(*let == '-') let++, allownone = TRUE; + if(allownone) *bp++ = '-'; + if(allowgold) *bp++ = '$'; + if(bp > buf && bp[-1] == '-') *bp++ = ' '; + + ilet = 'a'; + for(otmp = invent; otmp; otmp = otmp->nobj){ + if(!*let || index(let, otmp->olet)) { + bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet; + + /* ugly check: remove inappropriate things */ + if((!strcmp(word, "take off") && + !(otmp->owornmask & (W_ARMOR - W_ARM2))) + || (!strcmp(word, "wear") && + (otmp->owornmask & (W_ARMOR | W_RING))) + || (!strcmp(word, "wield") && + (otmp->owornmask & W_WEP))) { + foo--; + foox++; + } + } + if(ilet == 'z') ilet = 'A'; else ilet++; + } + bp[foo] = 0; + if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0; + (void) strcpy(lets, bp); /* necessary since we destroy buf */ + if(foo > 5) { /* compactify string */ + foo = foo2 = 1; + ilet2 = bp[0]; + ilet1 = bp[1]; + while(ilet = bp[++foo2] = bp[++foo]){ + if(ilet == ilet1+1){ + if(ilet1 == ilet2+1) + bp[foo2 - 1] = ilet1 = '-'; + else if(ilet2 == '-') { + bp[--foo2] = ++ilet1; + continue; + } + } + ilet2 = ilet1; + ilet1 = ilet; + } + } + if(!foo && !allowall && !allowgold && !allownone) { + pline("You don't have anything %sto %s.", + foox ? "else " : "", word); + return(0); + } + for(;;) { + if(!buf[0]) + pline("What do you want to %s [*]? ", word); + else + pline("What do you want to %s [%s or ?*]? ", + word, buf); + + cnt = 0; + ilet = readchar(); + while(digit(ilet) && allowcnt) { + if (cnt < 100000000) + cnt = 10*cnt + (ilet - '0'); + else + cnt = 999999999; + allowcnt = 2; /* signal presence of cnt */ + ilet = readchar(); + } + if(digit(ilet)) { + pline("No count allowed with this command."); + continue; + } + if(index(quitchars,ilet)) + return((struct obj *)0); + if(ilet == '-') { + return(allownone ? &zeroobj : (struct obj *) 0); + } + if(ilet == '$') { + if(!allowgold){ + pline("You cannot %s gold.", word); + continue; + } + if(!(allowcnt == 2 && cnt < u.ugold)) + cnt = u.ugold; + return(mkgoldobj(cnt)); + } + if(ilet == '?') { + doinv(lets); + if(!(ilet = morc)) continue; + /* he typed a letter (not a space) to more() */ + } else if(ilet == '*') { + doinv((char *) 0); + if(!(ilet = morc)) continue; + /* ... */ + } + if(flags.invlet_constant) { + for(otmp = invent; otmp; otmp = otmp->nobj) + if(otmp->invlet == ilet) break; + } else { + if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1; + ilet -= 'a'; + for(otmp = invent; otmp && ilet; + ilet--, otmp = otmp->nobj) ; + } + if(!otmp) { + pline("You don't have that object."); + continue; + } + if(cnt < 0 || otmp->quan < cnt) { + pline("You don't have that many! [You have %u]" + , otmp->quan); + continue; + } + break; + } + if(!allowall && let && !index(let,otmp->olet)) { + pline("That is a silly thing to %s.",word); + return(0); + } + if(allowcnt == 2) { /* cnt given */ + if(cnt == 0) return(0); + if(cnt != otmp->quan) { + register struct obj *obj; + obj = splitobj(otmp, (int) cnt); + if(otmp == uwep) setuwep(obj); + } + } + return(otmp); +} + +ckunpaid(otmp) register struct obj *otmp; { + return( otmp->unpaid ); +} + +/* interactive version of getobj - used for Drop and Identify */ +/* return the number of times fn was called successfully */ +ggetobj(word, fn, max) +char *word; +int (*fn)(), max; +{ +char buf[BUFSZ]; +register char *ip; +register char sym; +register int oletct = 0, iletct = 0; +register boolean allflag = FALSE; +char olets[20], ilets[20]; +int (*ckfn)() = (int (*)()) 0; +xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0; /* BAH */ + if(!invent && !allowgold){ + pline("You have nothing to %s.", word); + return(0); + } else { + register struct obj *otmp = invent; + register int uflg = 0; + + if(allowgold) ilets[iletct++] = '$'; + ilets[iletct] = 0; + while(otmp) { + if(!index(ilets, otmp->olet)){ + ilets[iletct++] = otmp->olet; + ilets[iletct] = 0; + } + if(otmp->unpaid) uflg = 1; + otmp = otmp->nobj; + } + ilets[iletct++] = ' '; + if(uflg) ilets[iletct++] = 'u'; + if(invent) ilets[iletct++] = 'a'; + ilets[iletct] = 0; + } + pline("What kinds of thing do you want to %s? [%s] ", + word, ilets); + getlin(buf); + if(buf[0] == '\033') { + clrlin(); + return(0); + } + ip = buf; + olets[0] = 0; + while(sym = *ip++){ + if(sym == ' ') continue; + if(sym == '$') { + if(allowgold == 1) + (*fn)(mkgoldobj(u.ugold)); + else if(!u.ugold) + pline("You have no gold."); + allowgold = 2; + } else + if(sym == 'a' || sym == 'A') allflag = TRUE; else + if(sym == 'u' || sym == 'U') ckfn = ckunpaid; else + if(index("!%?[()=*/\"0", sym)){ + if(!index(olets, sym)){ + olets[oletct++] = sym; + olets[oletct] = 0; + } + } + else pline("You don't have any %c's.", sym); + } + if(allowgold == 2 && !oletct) + return(1); /* he dropped gold (or at least tried to) */ + else + return(askchain(invent, olets, allflag, fn, ckfn, max)); +} + +/* + * Walk through the chain starting at objchn and ask for all objects + * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL) + * whether the action in question (i.e., fn) has to be performed. + * If allflag then no questions are asked. Max gives the max nr of + * objects to be treated. Return the number of objects treated. + */ +askchain(objchn, olets, allflag, fn, ckfn, max) +struct obj *objchn; +register char *olets; +int allflag; +int (*fn)(), (*ckfn)(); +int max; +{ +register struct obj *otmp, *otmp2; +register char sym, ilet; +register int cnt = 0; + ilet = 'a'-1; + for(otmp = objchn; otmp; otmp = otmp2){ + if(ilet == 'z') ilet = 'A'; else ilet++; + otmp2 = otmp->nobj; + if(olets && *olets && !index(olets, otmp->olet)) continue; + if(ckfn && !(*ckfn)(otmp)) continue; + if(!allflag) { + pline(xprname(otmp, ilet)); + addtopl(" [nyaq]? "); + sym = readchar(); + } + else sym = 'y'; + + switch(sym){ + case 'a': + allflag = 1; + case 'y': + cnt += (*fn)(otmp); + if(--max == 0) goto ret; + case 'n': + default: + break; + case 'q': + goto ret; + } + } + pline(cnt ? "That was all." : "No applicable objects."); +ret: + return(cnt); +} + +obj_to_let(obj) /* should of course only be called for things in invent */ +register struct obj *obj; +{ + register struct obj *otmp; + register char ilet; + + if(flags.invlet_constant) + return(obj->invlet); + ilet = 'a'; + for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj) + if(++ilet > 'z') ilet = 'A'; + return(otmp ? ilet : NOINVSYM); +} + +prinv(obj) +register struct obj *obj; +{ + pline(xprname(obj, obj_to_let(obj))); +} + +static char * +xprname(obj,let) +register struct obj *obj; +register char let; +{ + static char li[BUFSZ]; + + (void) sprintf(li, "%c - %s.", + flags.invlet_constant ? obj->invlet : let, + doname(obj)); + return(li); +} + +ddoinv() +{ + doinv((char *) 0); + return(0); +} + +/* called with 0 or "": all objects in inventory */ +/* otherwise: all objects with (serial) letter in lets */ +doinv(lets) +register char *lets; +{ + register struct obj *otmp; + register char ilet; + int ct = 0; + char any[BUFSZ]; + + morc = 0; /* just to be sure */ + + if(!invent){ + pline("Not carrying anything."); + return; + } + + cornline(0, (char *) 0); + ilet = 'a'; + for(otmp = invent; otmp; otmp = otmp->nobj) { + if(flags.invlet_constant) ilet = otmp->invlet; + if(!lets || !*lets || index(lets, ilet)) { + cornline(1, xprname(otmp, ilet)); + any[ct++] = ilet; + } + if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; + } + any[ct] = 0; + cornline(2, any); +} + +dotypeinv () /* free after Robert Viduya */ +/* Changed to one type only, so he doesnt have to type cr */ +{ + char c, ilet; + char stuff[BUFSZ]; + register int stct; + register struct obj *otmp; + boolean billx = inshop() && doinvbill(0); + boolean unpd = FALSE; + + if (!invent && !u.ugold && !billx) { + pline ("You aren't carrying anything."); + return(0); + } + + stct = 0; + if(u.ugold) stuff[stct++] = '$'; + stuff[stct] = 0; + for(otmp = invent; otmp; otmp = otmp->nobj) { + if (!index (stuff, otmp->olet)) { + stuff[stct++] = otmp->olet; + stuff[stct] = 0; + } + if(otmp->unpaid) + unpd = TRUE; + } + if(unpd) stuff[stct++] = 'u'; + if(billx) stuff[stct++] = 'x'; + stuff[stct] = 0; + + if(stct > 1) { + pline ("What type of object [%s] do you want an inventory of? ", + stuff); + c = readchar(); + if(index(quitchars,c)) return(0); + } else + c = stuff[0]; + + if(c == '$') + return(doprgold()); + + if(c == 'x' || c == 'X') { + if(billx) + (void) doinvbill(1); + else + pline("No used-up objects on the shopping bill."); + return(0); + } + + if((c == 'u' || c == 'U') && !unpd) { + pline("You are not carrying any unpaid objects."); + return(0); + } + + stct = 0; + ilet = 'a'; + for (otmp = invent; otmp; otmp = otmp -> nobj) { + if(flags.invlet_constant) ilet = otmp->invlet; + if (c == otmp -> olet || (c == 'u' && otmp -> unpaid)) + stuff[stct++] = ilet; + if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; + } + stuff[stct] = '\0'; + if(stct == 0) + pline("You have no such objects."); + else + doinv (stuff); + + return(0); +} + +/* look at what is here */ +dolook() { + register struct obj *otmp, *otmp0; + register struct gold *gold; + char *verb = Blind ? "feel" : "see"; + int ct = 0; + + if(!u.uswallow) { + if(Blind) { + pline("You try to feel what is lying here on the floor."); + if(Levitation) { /* ab@unido */ + pline("You cannot reach the floor!"); + return(1); + } + } + otmp0 = o_at(u.ux, u.uy); + gold = g_at(u.ux, u.uy); + } + + if(u.uswallow || (!otmp0 && !gold)) { + pline("You %s no objects here.", verb); + return(!!Blind); + } + + cornline(0, "Things that are here:"); + for(otmp = otmp0; otmp; otmp = otmp->nobj) { + if(otmp->ox == u.ux && otmp->oy == u.uy) { + ct++; + cornline(1, doname(otmp)); + if(Blind && otmp->otyp == DEAD_COCKATRICE && !uarmg) { + pline("Touching the dead cockatrice is a fatal mistake ..."); + pline("You die ..."); + killer = "dead cockatrice"; + done("died"); + } + } + } + + if(gold) { + char gbuf[30]; + + (void) sprintf(gbuf, "%ld gold piece%s", + gold->amount, plur(gold->amount)); + if(!ct++) + pline("You %s here %s.", verb, gbuf); + else + cornline(1, gbuf); + } + + if(ct == 1 && !gold) { + pline("You %s here %s.", verb, doname(otmp0)); + cornline(3, (char *) 0); + } + if(ct > 1) + cornline(2, (char *) 0); + return(!!Blind); +} + +stackobj(obj) register struct obj *obj; { +register struct obj *otmp = fobj; + for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj) + if(otmp->ox == obj->ox && otmp->oy == obj->oy && + merged(obj,otmp,1)) + return; +} + +/* merge obj with otmp and delete obj if types agree */ +merged(otmp,obj,lose) register struct obj *otmp, *obj; { + if(obj->otyp == otmp->otyp && + obj->unpaid == otmp->unpaid && + obj->spe == otmp->spe && + obj->dknown == otmp->dknown && + obj->cursed == otmp->cursed && + (index("%*?!", obj->olet) || + (obj->known == otmp->known && + (obj->olet == WEAPON_SYM && obj->otyp < BOOMERANG)))) { + otmp->quan += obj->quan; + otmp->owt += obj->owt; + if(lose) freeobj(obj); + obfree(obj,otmp); /* free(obj), bill->otmp */ + return(1); + } else return(0); +} + +/* + * Gold is no longer displayed; in fact, when you have a lot of money, + * it may take a while before you have counted it all. + * [Bug: d$ and pickup still tell you how much it was.] + */ +extern int (*occupation)(); +extern char *occtxt; +static long goldcounted; + +countgold(){ + if((goldcounted += 100*(u.ulevel + 1)) >= u.ugold) { + long eps = 0; + if(!rn2(2)) eps = rnd((int) (u.ugold/100 + 1)); + pline("You probably have about %ld gold pieces.", + u.ugold + eps); + return(0); /* done */ + } + return(1); /* continue */ +} + +doprgold(){ + if(!u.ugold) + pline("You do not carry any gold."); + else if(u.ugold <= 500) + pline("You are carrying %ld gold pieces.", u.ugold); + else { + pline("You sit down in order to count your gold pieces."); + goldcounted = 500; + occupation = countgold; + occtxt = "counting your gold"; + } + return(1); +} + +/* --- end of gold counting section --- */ + +doprwep(){ + if(!uwep) pline("You are empty handed."); + else prinv(uwep); + return(0); +} + +doprarm(){ + if(!uarm && !uarmg && !uarms && !uarmh) + pline("You are not wearing any armor."); + else { + char lets[6]; + register int ct = 0; + + if(uarm) lets[ct++] = obj_to_let(uarm); + if(uarm2) lets[ct++] = obj_to_let(uarm2); + if(uarmh) lets[ct++] = obj_to_let(uarmh); + if(uarms) lets[ct++] = obj_to_let(uarms); + if(uarmg) lets[ct++] = obj_to_let(uarmg); + lets[ct] = 0; + doinv(lets); + } + return(0); +} + +doprring(){ + if(!uleft && !uright) + pline("You are not wearing any rings."); + else { + char lets[3]; + register int ct = 0; + + if(uleft) lets[ct++] = obj_to_let(uleft); + if(uright) lets[ct++] = obj_to_let(uright); + lets[ct] = 0; + doinv(lets); + } + return(0); +} + +digit(c) char c; { + return(c >= '0' && c <= '9'); +} diff --git a/usr/othersrc/games/hack/hack.ioctl.c b/usr/othersrc/games/hack/hack.ioctl.c new file mode 100644 index 0000000000..6669ceaba3 --- /dev/null +++ b/usr/othersrc/games/hack/hack.ioctl.c @@ -0,0 +1,53 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.ioctl.c - version 1.0.2 */ + +/* This cannot be part of hack.tty.c (as it was earlier) since on some + systems (e.g. MUNIX) the include files and + define the same constants, and the C preprocessor complains. */ +#include +#include "config.h" +#ifdef BSD +#include +struct ltchars ltchars, ltchars0; +#else +#include /* also includes part of */ +struct termio termio; +#endif BSD + +getioctls() { +#ifdef BSD + (void) ioctl(fileno(stdin), (int) TIOCGLTC, (char *) <chars); + (void) ioctl(fileno(stdin), (int) TIOCSLTC, (char *) <chars0); +#else + (void) ioctl(fileno(stdin), (int) TCGETA, &termio); +#endif BSD +} + +setioctls() { +#ifdef BSD + (void) ioctl(fileno(stdin), (int) TIOCSLTC, (char *) <chars); +#else + (void) ioctl(fileno(stdin), (int) TCSETA, &termio); +#endif BSD +} + +#ifdef SUSPEND /* implies BSD */ +dosuspend() { +#include +#ifdef SIGTSTP + if(signal(SIGTSTP, SIG_IGN) == SIG_DFL) { + settty((char *) 0); + (void) signal(SIGTSTP, SIG_DFL); + (void) kill(0, SIGTSTP); + gettty(); + setftty(); + docrt(); + } else { + pline("I don't think your shell has job control."); + } +#else SIGTSTP + pline("Sorry, it seems we have no SIGTSTP here. Try ! or S."); +#endif SIGTSTP + return(0); +} +#endif SUSPEND diff --git a/usr/othersrc/games/hack/hack.lev.c b/usr/othersrc/games/hack/hack.lev.c new file mode 100644 index 0000000000..f011f675fb --- /dev/null +++ b/usr/othersrc/games/hack/hack.lev.c @@ -0,0 +1,285 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.lev.c - version 1.0.3 */ + +#include "hack.h" +#include "def.mkroom.h" +#include +extern struct monst *restmonchn(); +extern struct obj *restobjchn(); +extern struct obj *billobjs; +extern char *itoa(); +extern char SAVEF[]; +extern int hackpid; +extern xchar dlevel; +extern char nul[]; + +#ifndef NOWORM +#include "def.wseg.h" +extern struct wseg *wsegs[32], *wheads[32]; +extern long wgrowtime[32]; +#endif NOWORM + +boolean level_exists[MAXLEVEL+1]; + +savelev(fd,lev) +int fd; +xchar lev; +{ +#ifndef NOWORM + register struct wseg *wtmp, *wtmp2; + register tmp; +#endif NOWORM + + if(fd < 0) panic("Save on bad file!"); /* impossible */ + if(lev >= 0 && lev <= MAXLEVEL) + level_exists[lev] = TRUE; + + bwrite(fd,(char *) &hackpid,sizeof(hackpid)); + bwrite(fd,(char *) &lev,sizeof(lev)); + bwrite(fd,(char *) levl,sizeof(levl)); + bwrite(fd,(char *) &moves,sizeof(long)); + bwrite(fd,(char *) &xupstair,sizeof(xupstair)); + bwrite(fd,(char *) &yupstair,sizeof(yupstair)); + bwrite(fd,(char *) &xdnstair,sizeof(xdnstair)); + bwrite(fd,(char *) &ydnstair,sizeof(ydnstair)); + savemonchn(fd, fmon); + savegoldchn(fd, fgold); + savetrapchn(fd, ftrap); + saveobjchn(fd, fobj); + saveobjchn(fd, billobjs); + billobjs = 0; + save_engravings(fd); +#ifndef QUEST + bwrite(fd,(char *) rooms,sizeof(rooms)); + bwrite(fd,(char *) doors,sizeof(doors)); +#endif QUEST + fgold = 0; + ftrap = 0; + fmon = 0; + fobj = 0; +#ifndef NOWORM + bwrite(fd,(char *) wsegs,sizeof(wsegs)); + for(tmp=1; tmp<32; tmp++){ + for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2){ + wtmp2 = wtmp->nseg; + bwrite(fd,(char *) wtmp,sizeof(struct wseg)); + } + wsegs[tmp] = 0; + } + bwrite(fd,(char *) wgrowtime,sizeof(wgrowtime)); +#endif NOWORM +} + +bwrite(fd,loc,num) +register fd; +register char *loc; +register unsigned num; +{ +/* lint wants the 3rd arg of write to be an int; lint -p an unsigned */ + if(write(fd, loc, (int) num) != num) + panic("cannot write %u bytes to file #%d", num, fd); +} + +saveobjchn(fd,otmp) +register fd; +register struct obj *otmp; +{ + register struct obj *otmp2; + unsigned xl; + int minusone = -1; + + while(otmp) { + otmp2 = otmp->nobj; + xl = otmp->onamelth; + bwrite(fd, (char *) &xl, sizeof(int)); + bwrite(fd, (char *) otmp, xl + sizeof(struct obj)); + free((char *) otmp); + otmp = otmp2; + } + bwrite(fd, (char *) &minusone, sizeof(int)); +} + +savemonchn(fd,mtmp) +register fd; +register struct monst *mtmp; +{ + register struct monst *mtmp2; + unsigned xl; + int minusone = -1; + struct permonst *monbegin = &mons[0]; + + bwrite(fd, (char *) &monbegin, sizeof(monbegin)); + + while(mtmp) { + mtmp2 = mtmp->nmon; + xl = mtmp->mxlth + mtmp->mnamelth; + bwrite(fd, (char *) &xl, sizeof(int)); + bwrite(fd, (char *) mtmp, xl + sizeof(struct monst)); + if(mtmp->minvent) saveobjchn(fd,mtmp->minvent); + free((char *) mtmp); + mtmp = mtmp2; + } + bwrite(fd, (char *) &minusone, sizeof(int)); +} + +savegoldchn(fd,gold) +register fd; +register struct gold *gold; +{ + register struct gold *gold2; + while(gold) { + gold2 = gold->ngold; + bwrite(fd, (char *) gold, sizeof(struct gold)); + free((char *) gold); + gold = gold2; + } + bwrite(fd, nul, sizeof(struct gold)); +} + +savetrapchn(fd,trap) +register fd; +register struct trap *trap; +{ + register struct trap *trap2; + while(trap) { + trap2 = trap->ntrap; + bwrite(fd, (char *) trap, sizeof(struct trap)); + free((char *) trap); + trap = trap2; + } + bwrite(fd, nul, sizeof(struct trap)); +} + +getlev(fd,pid,lev) +int fd,pid; +xchar lev; +{ + register struct gold *gold; + register struct trap *trap; +#ifndef NOWORM + register struct wseg *wtmp; +#endif NOWORM + register tmp; + long omoves; + int hpid; + xchar dlvl; + + /* First some sanity checks */ + mread(fd, (char *) &hpid, sizeof(hpid)); + mread(fd, (char *) &dlvl, sizeof(dlvl)); + if((pid && pid != hpid) || (lev && dlvl != lev)) { + pline("Strange, this map is not as I remember it."); + pline("Somebody is trying some trickery here ..."); + pline("This game is void ..."); + done("tricked"); + } + + fgold = 0; + ftrap = 0; + mread(fd, (char *) levl, sizeof(levl)); + mread(fd, (char *)&omoves, sizeof(omoves)); + mread(fd, (char *)&xupstair, sizeof(xupstair)); + mread(fd, (char *)&yupstair, sizeof(yupstair)); + mread(fd, (char *)&xdnstair, sizeof(xdnstair)); + mread(fd, (char *)&ydnstair, sizeof(ydnstair)); + + fmon = restmonchn(fd); + + /* regenerate animals while on another level */ + { long tmoves = (moves > omoves) ? moves-omoves : 0; + register struct monst *mtmp, *mtmp2; + extern char genocided[]; + + for(mtmp = fmon; mtmp; mtmp = mtmp2) { + long newhp; /* tmoves may be very large */ + + mtmp2 = mtmp->nmon; + if(index(genocided, mtmp->data->mlet)) { + mondead(mtmp); + continue; + } + + if(mtmp->mtame && tmoves > 250) { + mtmp->mtame = 0; + mtmp->mpeaceful = 0; + } + + newhp = mtmp->mhp + + (index(MREGEN, mtmp->data->mlet) ? tmoves : tmoves/20); + if(newhp > mtmp->mhpmax) + mtmp->mhp = mtmp->mhpmax; + else + mtmp->mhp = newhp; + } + } + + setgd(); + gold = newgold(); + mread(fd, (char *)gold, sizeof(struct gold)); + while(gold->gx) { + gold->ngold = fgold; + fgold = gold; + gold = newgold(); + mread(fd, (char *)gold, sizeof(struct gold)); + } + free((char *) gold); + trap = newtrap(); + mread(fd, (char *)trap, sizeof(struct trap)); + while(trap->tx) { + trap->ntrap = ftrap; + ftrap = trap; + trap = newtrap(); + mread(fd, (char *)trap, sizeof(struct trap)); + } + free((char *) trap); + fobj = restobjchn(fd); + billobjs = restobjchn(fd); + rest_engravings(fd); +#ifndef QUEST + mread(fd, (char *)rooms, sizeof(rooms)); + mread(fd, (char *)doors, sizeof(doors)); +#endif QUEST +#ifndef NOWORM + mread(fd, (char *)wsegs, sizeof(wsegs)); + for(tmp = 1; tmp < 32; tmp++) if(wsegs[tmp]){ + wheads[tmp] = wsegs[tmp] = wtmp = newseg(); + while(1) { + mread(fd, (char *)wtmp, sizeof(struct wseg)); + if(!wtmp->nseg) break; + wheads[tmp]->nseg = wtmp = newseg(); + wheads[tmp] = wtmp; + } + } + mread(fd, (char *)wgrowtime, sizeof(wgrowtime)); +#endif NOWORM +} + +mread(fd, buf, len) +register fd; +register char *buf; +register unsigned len; +{ + register int rlen; + extern boolean restoring; + + rlen = read(fd, buf, (int) len); + if(rlen != len){ + pline("Read %d instead of %u bytes.\n", rlen, len); + if(restoring) { + (void) unlink(SAVEF); + error("Error restoring old game."); + } + panic("Error reading level file."); + } +} + +mklev() +{ + extern boolean in_mklev; + + if(getbones()) return; + + in_mklev = TRUE; + makelevel(); + in_mklev = FALSE; +} diff --git a/usr/othersrc/games/hack/hack.mfndpos.h b/usr/othersrc/games/hack/hack.mfndpos.h new file mode 100644 index 0000000000..f4da529fc7 --- /dev/null +++ b/usr/othersrc/games/hack/hack.mfndpos.h @@ -0,0 +1,12 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.mfndpos.h - version 1.0.2 */ + +#define ALLOW_TRAPS 0777 +#define ALLOW_U 01000 +#define ALLOW_M 02000 +#define ALLOW_TM 04000 +#define ALLOW_ALL (ALLOW_U | ALLOW_M | ALLOW_TM | ALLOW_TRAPS) +#define ALLOW_SSM 010000 +#define ALLOW_ROCK 020000 +#define NOTONL 040000 +#define NOGARLIC 0100000 diff --git a/usr/othersrc/games/hack/hack.mhitu.c b/usr/othersrc/games/hack/hack.mhitu.c new file mode 100644 index 0000000000..ae7d204b17 --- /dev/null +++ b/usr/othersrc/games/hack/hack.mhitu.c @@ -0,0 +1,363 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.mhitu.c - version 1.0.3 */ + +#include "hack.h" +extern struct monst *makemon(); + +/* + * mhitu: monster hits you + * returns 1 if monster dies (e.g. 'y', 'F'), 0 otherwise + */ +mhitu(mtmp) +register struct monst *mtmp; +{ + register struct permonst *mdat = mtmp->data; + register int tmp, ctmp; + + nomul(0); + + /* If swallowed, can only be affected by hissers and by u.ustuck */ + if(u.uswallow) { + if(mtmp != u.ustuck) { + if(mdat->mlet == 'c' && !rn2(13)) { + pline("Outside, you hear %s's hissing!", + monnam(mtmp)); + pline("%s gets turned to stone!", + Monnam(u.ustuck)); + pline("And the same fate befalls you."); + done_in_by(mtmp); + /* "notreached": not return(1); */ + } + return(0); + } + switch(mdat->mlet) { /* now mtmp == u.ustuck */ + case ',': + youswld(mtmp, (u.uac > 0) ? u.uac+4 : 4, + 5, "The trapper"); + break; + case '\'': + youswld(mtmp,rnd(6),7,"The lurker above"); + break; + case 'P': + youswld(mtmp,d(2,4),12,"The purple worm"); + break; + default: + /* This is not impossible! */ + pline("The mysterious monster totally digests you."); + u.uhp = 0; + } + if(u.uhp < 1) done_in_by(mtmp); + return(0); + } + + if(mdat->mlet == 'c' && Stoned) + return(0); + + /* make eels visible the moment they hit/miss us */ + if(mdat->mlet == ';' && mtmp->minvis && cansee(mtmp->mx,mtmp->my)){ + mtmp->minvis = 0; + pmon(mtmp); + } + if(!index("1&DuxynNF",mdat->mlet)) + tmp = hitu(mtmp,d(mdat->damn,mdat->damd)); + else + tmp = 0; + if(index(UNDEAD, mdat->mlet) && midnight()) + tmp += hitu(mtmp,d(mdat->damn,mdat->damd)); + + ctmp = tmp && !mtmp->mcan && + (!uarm || objects[uarm->otyp].a_can < rnd(3) || !rn2(50)); + switch(mdat->mlet) { + case '1': + if(wiz_hit(mtmp)) return(1); /* he disappeared */ + break; + case '&': + if(!mtmp->cham && !mtmp->mcan && !rn2(13)) { + (void) makemon(PM_DEMON,u.ux,u.uy); + } else { + (void) hitu(mtmp,d(2,6)); + (void) hitu(mtmp,d(2,6)); + (void) hitu(mtmp,rnd(3)); + (void) hitu(mtmp,rnd(3)); + (void) hitu(mtmp,rn1(4,2)); + } + break; + case ',': + if(tmp) justswld(mtmp,"The trapper"); + break; + case '\'': + if(tmp) justswld(mtmp, "The lurker above"); + break; + case ';': + if(ctmp) { + if(!u.ustuck && !rn2(10)) { + pline("%s swings itself around you!", + Monnam(mtmp)); + u.ustuck = mtmp; + } else if(u.ustuck == mtmp && + levl[mtmp->mx][mtmp->my].typ == POOL) { + pline("%s drowns you ...", Monnam(mtmp)); + done("drowned"); + } + } + break; + case 'A': + if(ctmp && rn2(2)) { + if(Poison_resistance) + pline("The sting doesn't seem to affect you."); + else { + pline("You feel weaker!"); + losestr(1); + } + } + break; + case 'C': + (void) hitu(mtmp,rnd(6)); + break; + case 'c': + if(!rn2(5)) { + pline("You hear %s's hissing!", monnam(mtmp)); + if(ctmp || !rn2(20) || (flags.moonphase == NEW_MOON + && !carrying(DEAD_LIZARD))) { + Stoned = 5; + /* pline("You get turned to stone!"); */ + /* done_in_by(mtmp); */ + } + } + break; + case 'D': + if(rn2(6) || mtmp->mcan) { + (void) hitu(mtmp,d(3,10)); + (void) hitu(mtmp,rnd(8)); + (void) hitu(mtmp,rnd(8)); + break; + } + kludge("%s breathes fire!","The dragon"); + buzz(-1,mtmp->mx,mtmp->my,u.ux-mtmp->mx,u.uy-mtmp->my); + break; + case 'd': + (void) hitu(mtmp,d(2, (flags.moonphase == FULL_MOON) ? 3 : 4)); + break; + case 'e': + (void) hitu(mtmp,d(3,6)); + break; + case 'F': + if(mtmp->mcan) break; + kludge("%s explodes!","The freezing sphere"); + if(Cold_resistance) pline("You don't seem affected by it."); + else { + xchar dn; + if(17-(u.ulevel/2) > rnd(20)) { + pline("You get blasted!"); + dn = 6; + } else { + pline("You duck the blast..."); + dn = 3; + } + losehp_m(d(dn,6), mtmp); + } + mondead(mtmp); + return(1); + case 'g': + if(ctmp && multi >= 0 && !rn2(3)) { + kludge("You are frozen by %ss juices","the cube'"); + nomul(-rnd(10)); + } + break; + case 'h': + if(ctmp && multi >= 0 && !rn2(5)) { + nomul(-rnd(10)); + kludge("You are put to sleep by %ss bite!", + "the homunculus'"); + } + break; + case 'j': + tmp = hitu(mtmp,rnd(3)); + tmp &= hitu(mtmp,rnd(3)); + if(tmp){ + (void) hitu(mtmp,rnd(4)); + (void) hitu(mtmp,rnd(4)); + } + break; + case 'k': + if((hitu(mtmp,rnd(4)) || !rn2(3)) && ctmp){ + poisoned("bee's sting",mdat->mname); + } + break; + case 'L': + if(tmp) stealgold(mtmp); + break; + case 'N': + if(mtmp->mcan && !Blind) { + pline("%s tries to seduce you, but you seem not interested.", + Amonnam(mtmp, "plain")); + if(rn2(3)) rloc(mtmp); + } else if(steal(mtmp)) { + rloc(mtmp); + mtmp->mflee = 1; + } + break; + case 'n': + if(!uwep && !uarm && !uarmh && !uarms && !uarmg) { + pline("%s hits! (I hope you don't mind)", + Monnam(mtmp)); + u.uhp += rnd(7); + if(!rn2(7)) u.uhpmax++; + if(u.uhp > u.uhpmax) u.uhp = u.uhpmax; + flags.botl = 1; + if(!rn2(50)) rloc(mtmp); + } else { + (void) hitu(mtmp,d(2,6)); + (void) hitu(mtmp,d(2,6)); + } + break; + case 'o': + tmp = hitu(mtmp,rnd(6)); + if(hitu(mtmp,rnd(6)) && tmp && /* hits with both paws */ + !u.ustuck && rn2(2)) { + u.ustuck = mtmp; + kludge("%s has grabbed you!","The owlbear"); + u.uhp -= d(2,8); + } else if(u.ustuck == mtmp) { + u.uhp -= d(2,8); + pline("You are being crushed."); + } + break; + case 'P': + if(ctmp && !rn2(4)) + justswld(mtmp,"The purple worm"); + else + (void) hitu(mtmp,d(2,4)); + break; + case 'Q': + (void) hitu(mtmp,rnd(2)); + (void) hitu(mtmp,rnd(2)); + break; + case 'R': + if(tmp && uarmh && !uarmh->rustfree && + (int) uarmh->spe >= -1) { + pline("Your helmet rusts!"); + uarmh->spe--; + } else + if(ctmp && uarm && !uarm->rustfree && /* Mike Newton */ + uarm->otyp < STUDDED_LEATHER_ARMOR && + (int) uarm->spe >= -1) { + pline("Your armor rusts!"); + uarm->spe--; + } + break; + case 'S': + if(ctmp && !rn2(8)) { + poisoned("snake's bite",mdat->mname); + } + break; + case 's': + if(tmp && !rn2(8)) { + poisoned("scorpion's sting",mdat->mname); + } + (void) hitu(mtmp,rnd(8)); + (void) hitu(mtmp,rnd(8)); + break; + case 'T': + (void) hitu(mtmp,rnd(6)); + (void) hitu(mtmp,rnd(6)); + break; + case 't': + if(!rn2(5)) rloc(mtmp); + break; + case 'u': + mtmp->mflee = 1; + break; + case 'U': + (void) hitu(mtmp,d(3,4)); + (void) hitu(mtmp,d(3,4)); + break; + case 'v': + if(ctmp && !u.ustuck) u.ustuck = mtmp; + break; + case 'V': + if(tmp) u.uhp -= 4; + if(ctmp) losexp(); + break; + case 'W': + if(ctmp) losexp(); + break; +#ifndef NOWORM + case 'w': + if(tmp) wormhit(mtmp); +#endif NOWORM + break; + case 'X': + (void) hitu(mtmp,rnd(5)); + (void) hitu(mtmp,rnd(5)); + (void) hitu(mtmp,rnd(5)); + break; + case 'x': + { register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE; + pline("%s pricks in your %s leg!", + Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left"); + set_wounded_legs(side, rnd(50)); + losehp_m(2, mtmp); + break; + } + case 'y': + if(mtmp->mcan) break; + mondead(mtmp); + if(!Blind) { + pline("You are blinded by a blast of light!"); + Blind = d(4,12); + seeoff(0); + } + return(1); + case 'Y': + (void) hitu(mtmp,rnd(6)); + break; + } + if(u.uhp < 1) done_in_by(mtmp); + return(0); +} + +hitu(mtmp,dam) +register struct monst *mtmp; +register dam; +{ + register tmp, res; + + nomul(0); + if(u.uswallow) return(0); + + if(mtmp->mhide && mtmp->mundetected) { + mtmp->mundetected = 0; + if(!Blind) { + register struct obj *obj; + extern char * Xmonnam(); + if(obj = o_at(mtmp->mx,mtmp->my)) + pline("%s was hidden under %s!", + Xmonnam(mtmp), doname(obj)); + } + } + + tmp = u.uac; + /* give people with Ac = -10 at least some vulnerability */ + if(tmp < 0) { + dam += tmp; /* decrease damage */ + if(dam <= 0) dam = 1; + tmp = -rn2(-tmp); + } + tmp += mtmp->data->mlevel; + if(multi < 0) tmp += 4; + if((Invis && mtmp->data->mlet != 'I') || !mtmp->mcansee) tmp -= 2; + if(mtmp->mtrapped) tmp -= 2; + if(tmp <= rnd(20)) { + if(Blind) pline("It misses."); + else pline("%s misses.",Monnam(mtmp)); + res = 0; + } else { + if(Blind) pline("It hits!"); + else pline("%s hits!",Monnam(mtmp)); + losehp_m(dam, mtmp); + res = 1; + } + stop_occupation(); + return(res); +} diff --git a/usr/othersrc/games/hack/hack.mklev.c b/usr/othersrc/games/hack/hack.mklev.c new file mode 100644 index 0000000000..8904021374 --- /dev/null +++ b/usr/othersrc/games/hack/hack.mklev.c @@ -0,0 +1,741 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.mklev.c - version 1.0.3 */ + +#include "hack.h" + +extern char *getlogin(), *getenv(); +extern struct monst *makemon(); +extern struct obj *mkobj_at(); +extern struct trap *maketrap(); + +#define somex() ((random()%(croom->hx-croom->lx+1))+croom->lx) +#define somey() ((random()%(croom->hy-croom->ly+1))+croom->ly) + +#include "def.mkroom.h" +#define XLIM 4 /* define minimum required space around a room */ +#define YLIM 3 +boolean secret; /* TRUE while making a vault: increase [XY]LIM */ +struct mkroom rooms[MAXNROFROOMS+1]; +int smeq[MAXNROFROOMS+1]; +coord doors[DOORMAX]; +int doorindex; +struct rm zerorm; +int comp(); +schar nxcor; +boolean goldseen; +int nroom; +xchar xdnstair,xupstair,ydnstair,yupstair; + +/* Definitions used by makerooms() and addrs() */ +#define MAXRS 50 /* max lth of temp rectangle table - arbitrary */ +struct rectangle { + xchar rlx,rly,rhx,rhy; +} rs[MAXRS+1]; +int rscnt,rsmax; /* 0..rscnt-1: currently under consideration */ + /* rscnt..rsmax: discarded */ + +makelevel() +{ + register struct mkroom *croom, *troom; + register unsigned tryct; + register x,y; + + nroom = 0; + doorindex = 0; + rooms[0].hx = -1; /* in case we are in a maze */ + + for(x=0; x= rn1(3, 26)) { /* there might be several mazes */ + makemaz(); + return; + } + + /* construct the rooms */ + nroom = 0; + secret = FALSE; + (void) makerooms(); + + /* construct stairs (up and down in different rooms if possible) */ + croom = &rooms[rn2(nroom)]; + xdnstair = somex(); + ydnstair = somey(); + levl[xdnstair][ydnstair].scrsym ='>'; + levl[xdnstair][ydnstair].typ = STAIRS; + if(nroom > 1) { + troom = croom; + croom = &rooms[rn2(nroom-1)]; + if(croom >= troom) croom++; + } + xupstair = somex(); /* %% < and > might be in the same place */ + yupstair = somey(); + levl[xupstair][yupstair].scrsym ='<'; + levl[xupstair][yupstair].typ = STAIRS; + + /* for each room: put things inside */ + for(croom = rooms; croom->hx > 0; croom++) { + + /* put a sleeping monster inside */ + /* Note: monster may be on the stairs. This cannot be + avoided: maybe the player fell through a trapdoor + while a monster was on the stairs. Conclusion: + we have to check for monsters on the stairs anyway. */ + if(!rn2(3)) (void) + makemon((struct permonst *) 0, somex(), somey()); + + /* put traps and mimics inside */ + goldseen = FALSE; + while(!rn2(8-(dlevel/6))) mktrap(0,0,croom); + if(!goldseen && !rn2(3)) mkgold(0L,somex(),somey()); + if(!rn2(3)) { + (void) mkobj_at(0, somex(), somey()); + tryct = 0; + while(!rn2(5)) { + if(++tryct > 100){ + printf("tryct overflow4\n"); + break; + } + (void) mkobj_at(0, somex(), somey()); + } + } + } + + qsort((char *) rooms, nroom, sizeof(struct mkroom), comp); + makecorridors(); + make_niches(); + + /* make a secret treasure vault, not connected to the rest */ + if(nroom <= (2*MAXNROFROOMS/3)) if(rn2(3)) { + troom = &rooms[nroom]; + secret = TRUE; + if(makerooms()) { + troom->rtype = VAULT; /* treasure vault */ + for(x = troom->lx; x <= troom->hx; x++) + for(y = troom->ly; y <= troom->hy; y++) + mkgold((long)(rnd(dlevel*100) + 50), x, y); + if(!rn2(3)) + makevtele(); + } + } + +#ifndef QUEST +#ifdef WIZARD + if(wizard && getenv("SHOPTYPE")) mkshop(); else +#endif WIZARD + if(dlevel > 1 && dlevel < 20 && rn2(dlevel) < 3) mkshop(); + else + if(dlevel > 6 && !rn2(7)) mkzoo(ZOO); + else + if(dlevel > 9 && !rn2(5)) mkzoo(BEEHIVE); + else + if(dlevel > 11 && !rn2(6)) mkzoo(MORGUE); + else + if(dlevel > 18 && !rn2(6)) mkswamp(); +#endif QUEST +} + +makerooms() { +register struct rectangle *rsp; +register int lx, ly, hx, hy, lowx, lowy, hix, hiy, dx, dy; +int tryct = 0, xlim, ylim; + + /* init */ + xlim = XLIM + secret; + ylim = YLIM + secret; + if(nroom == 0) { + rsp = rs; + rsp->rlx = rsp->rly = 0; + rsp->rhx = COLNO-1; + rsp->rhy = ROWNO-1; + rsmax = 1; + } + rscnt = rsmax; + + /* make rooms until satisfied */ + while(rscnt > 0 && nroom < MAXNROFROOMS-1) { + if(!secret && nroom > (MAXNROFROOMS/3) && + !rn2((MAXNROFROOMS-nroom)*(MAXNROFROOMS-nroom))) + return(0); + + /* pick a rectangle */ + rsp = &rs[rn2(rscnt)]; + hx = rsp->rhx; + hy = rsp->rhy; + lx = rsp->rlx; + ly = rsp->rly; + + /* find size of room */ + if(secret) + dx = dy = 1; + else { + dx = 2 + rn2((hx-lx-8 > 20) ? 12 : 8); + dy = 2 + rn2(4); + if(dx*dy > 50) + dy = 50/dx; + } + + /* look whether our room will fit */ + if(hx-lx < dx + dx/2 + 2*xlim || hy-ly < dy + dy/3 + 2*ylim) { + /* no, too small */ + /* maybe we throw this area out */ + if(secret || !rn2(MAXNROFROOMS+1-nroom-tryct)) { + rscnt--; + rs[rsmax] = *rsp; + *rsp = rs[rscnt]; + rs[rscnt] = rs[rsmax]; + tryct = 0; + } else + tryct++; + continue; + } + + lowx = lx + xlim + rn2(hx - lx - dx - 2*xlim + 1); + lowy = ly + ylim + rn2(hy - ly - dy - 2*ylim + 1); + hix = lowx + dx; + hiy = lowy + dy; + + if(maker(lowx, dx, lowy, dy)) { + if(secret) + return(1); + addrs(lowx-1, lowy-1, hix+1, hiy+1); + tryct = 0; + } else + if(tryct++ > 100) + break; + } + return(0); /* failed to make vault - very strange */ +} + +addrs(lowx,lowy,hix,hiy) +register int lowx,lowy,hix,hiy; +{ + register struct rectangle *rsp; + register int lx,ly,hx,hy,xlim,ylim; + boolean discarded; + + xlim = XLIM + secret; + ylim = YLIM + secret; + + /* walk down since rscnt and rsmax change */ + for(rsp = &rs[rsmax-1]; rsp >= rs; rsp--) { + + if((lx = rsp->rlx) > hix || (ly = rsp->rly) > hiy || + (hx = rsp->rhx) < lowx || (hy = rsp->rhy) < lowy) + continue; + if((discarded = (rsp >= &rs[rscnt]))) { + *rsp = rs[--rsmax]; + } else { + rsmax--; + rscnt--; + *rsp = rs[rscnt]; + if(rscnt != rsmax) + rs[rscnt] = rs[rsmax]; + } + if(lowy - ly > 2*ylim + 4) + addrsx(lx,ly,hx,lowy-2,discarded); + if(lowx - lx > 2*xlim + 4) + addrsx(lx,ly,lowx-2,hy,discarded); + if(hy - hiy > 2*ylim + 4) + addrsx(lx,hiy+2,hx,hy,discarded); + if(hx - hix > 2*xlim + 4) + addrsx(hix+2,ly,hx,hy,discarded); + } +} + +addrsx(lx,ly,hx,hy,discarded) +register int lx,ly,hx,hy; +boolean discarded; /* piece of a discarded area */ +{ + register struct rectangle *rsp; + + /* check inclusions */ + for(rsp = rs; rsp < &rs[rsmax]; rsp++) { + if(lx >= rsp->rlx && hx <= rsp->rhx && + ly >= rsp->rly && hy <= rsp->rhy) + return; + } + + /* make a new entry */ + if(rsmax >= MAXRS) { +#ifdef WIZARD + if(wizard) pline("MAXRS may be too small."); +#endif WIZARD + return; + } + rsmax++; + if(!discarded) { + *rsp = rs[rscnt]; + rsp = &rs[rscnt]; + rscnt++; + } + rsp->rlx = lx; + rsp->rly = ly; + rsp->rhx = hx; + rsp->rhy = hy; +} + +comp(x,y) +register struct mkroom *x,*y; +{ + if(x->lx < y->lx) return(-1); + return(x->lx > y->lx); +} + +coord +finddpos(xl,yl,xh,yh) { + coord ff; + register x,y; + + x = (xl == xh) ? xl : (xl + rn2(xh-xl+1)); + y = (yl == yh) ? yl : (yl + rn2(yh-yl+1)); + if(okdoor(x, y)) + goto gotit; + + for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++) + if(okdoor(x, y)) + goto gotit; + + for(x = xl; x <= xh; x++) for(y = yl; y <= yh; y++) + if(levl[x][y].typ == DOOR || levl[x][y].typ == SDOOR) + goto gotit; + /* cannot find something reasonable -- strange */ + x = xl; + y = yh; +gotit: + ff.x = x; + ff.y = y; + return(ff); +} + +/* see whether it is allowable to create a door at [x,y] */ +okdoor(x,y) +register x,y; +{ + if(levl[x-1][y].typ == DOOR || levl[x+1][y].typ == DOOR || + levl[x][y+1].typ == DOOR || levl[x][y-1].typ == DOOR || + levl[x-1][y].typ == SDOOR || levl[x+1][y].typ == SDOOR || + levl[x][y-1].typ == SDOOR || levl[x][y+1].typ == SDOOR || + (levl[x][y].typ != HWALL && levl[x][y].typ != VWALL) || + doorindex >= DOORMAX) + return(0); + return(1); +} + +dodoor(x,y,aroom) +register x,y; +register struct mkroom *aroom; +{ + if(doorindex >= DOORMAX) { + impossible("DOORMAX exceeded?"); + return; + } + if(!okdoor(x,y) && nxcor) + return; + dosdoor(x,y,aroom,rn2(8) ? DOOR : SDOOR); +} + +dosdoor(x,y,aroom,type) +register x,y; +register struct mkroom *aroom; +register type; +{ + register struct mkroom *broom; + register tmp; + + if(!IS_WALL(levl[x][y].typ)) /* avoid SDOORs with '+' as scrsym */ + type = DOOR; + levl[x][y].typ = type; + if(type == DOOR) + levl[x][y].scrsym = '+'; + aroom->doorct++; + broom = aroom+1; + if(broom->hx < 0) tmp = doorindex; else + for(tmp = doorindex; tmp > broom->fdoor; tmp--) + doors[tmp] = doors[tmp-1]; + doorindex++; + doors[tmp].x = x; + doors[tmp].y = y; + for( ; broom->hx >= 0; broom++) broom->fdoor++; +} + +/* Only called from makerooms() */ +maker(lowx,ddx,lowy,ddy) +schar lowx,ddx,lowy,ddy; +{ + register struct mkroom *croom; + register x, y, hix = lowx+ddx, hiy = lowy+ddy; + register xlim = XLIM + secret, ylim = YLIM + secret; + + if(nroom >= MAXNROFROOMS) return(0); + if(lowx < XLIM) lowx = XLIM; + if(lowy < YLIM) lowy = YLIM; + if(hix > COLNO-XLIM-1) hix = COLNO-XLIM-1; + if(hiy > ROWNO-YLIM-1) hiy = ROWNO-YLIM-1; +chk: + if(hix <= lowx || hiy <= lowy) return(0); + + /* check area around room (and make room smaller if necessary) */ + for(x = lowx - xlim; x <= hix + xlim; x++) { + for(y = lowy - ylim; y <= hiy + ylim; y++) { + if(levl[x][y].typ) { +#ifdef WIZARD + if(wizard && !secret) + pline("Strange area [%d,%d] in maker().",x,y); +#endif WIZARD + if(!rn2(3)) return(0); + if(x < lowx) + lowx = x+xlim+1; + else + hix = x-xlim-1; + if(y < lowy) + lowy = y+ylim+1; + else + hiy = y-ylim-1; + goto chk; + } + } + } + + croom = &rooms[nroom]; + + /* on low levels the room is lit (usually) */ + /* secret vaults are always lit */ + if((rnd(dlevel) < 10 && rn2(77)) || (ddx == 1 && ddy == 1)) { + for(x = lowx-1; x <= hix+1; x++) + for(y = lowy-1; y <= hiy+1; y++) + levl[x][y].lit = 1; + croom->rlit = 1; + } else + croom->rlit = 0; + croom->lx = lowx; + croom->hx = hix; + croom->ly = lowy; + croom->hy = hiy; + croom->rtype = croom->doorct = croom->fdoor = 0; + + for(x = lowx-1; x <= hix+1; x++) + for(y = lowy-1; y <= hiy+1; y += (hiy-lowy+2)) { + levl[x][y].scrsym = '-'; + levl[x][y].typ = HWALL; + } + for(x = lowx-1; x <= hix+1; x += (hix-lowx+2)) + for(y = lowy; y <= hiy; y++) { + levl[x][y].scrsym = '|'; + levl[x][y].typ = VWALL; + } + for(x = lowx; x <= hix; x++) + for(y = lowy; y <= hiy; y++) { + levl[x][y].scrsym = '.'; + levl[x][y].typ = ROOM; + } + + smeq[nroom] = nroom; + croom++; + croom->hx = -1; + nroom++; + return(1); +} + +makecorridors() { + register a,b; + + nxcor = 0; + for(a = 0; a < nroom-1; a++) + join(a, a+1); + for(a = 0; a < nroom-2; a++) + if(smeq[a] != smeq[a+2]) + join(a, a+2); + for(a = 0; a < nroom; a++) + for(b = 0; b < nroom; b++) + if(smeq[a] != smeq[b]) + join(a, b); + if(nroom > 2) + for(nxcor = rn2(nroom) + 4; nxcor; nxcor--) { + a = rn2(nroom); + b = rn2(nroom-2); + if(b >= a) b += 2; + join(a, b); + } +} + +join(a,b) +register a,b; +{ + coord cc,tt; + register tx, ty, xx, yy; + register struct rm *crm; + register struct mkroom *croom, *troom; + register dx, dy, dix, diy, cct; + + croom = &rooms[a]; + troom = &rooms[b]; + + /* find positions cc and tt for doors in croom and troom + and direction for a corridor between them */ + + if(troom->hx < 0 || croom->hx < 0 || doorindex >= DOORMAX) return; + if(troom->lx > croom->hx) { + dx = 1; + dy = 0; + xx = croom->hx+1; + tx = troom->lx-1; + cc = finddpos(xx,croom->ly,xx,croom->hy); + tt = finddpos(tx,troom->ly,tx,troom->hy); + } else if(troom->hy < croom->ly) { + dy = -1; + dx = 0; + yy = croom->ly-1; + cc = finddpos(croom->lx,yy,croom->hx,yy); + ty = troom->hy+1; + tt = finddpos(troom->lx,ty,troom->hx,ty); + } else if(troom->hx < croom->lx) { + dx = -1; + dy = 0; + xx = croom->lx-1; + tx = troom->hx+1; + cc = finddpos(xx,croom->ly,xx,croom->hy); + tt = finddpos(tx,troom->ly,tx,troom->hy); + } else { + dy = 1; + dx = 0; + yy = croom->hy+1; + ty = troom->ly-1; + cc = finddpos(croom->lx,yy,croom->hx,yy); + tt = finddpos(troom->lx,ty,troom->hx,ty); + } + xx = cc.x; + yy = cc.y; + tx = tt.x - dx; + ty = tt.y - dy; + if(nxcor && levl[xx+dx][yy+dy].typ) + return; + dodoor(xx,yy,croom); + + cct = 0; + while(xx != tx || yy != ty) { + xx += dx; + yy += dy; + + /* loop: dig corridor at [xx,yy] and find new [xx,yy] */ + if(cct++ > 500 || (nxcor && !rn2(35))) + return; + + if(xx == COLNO-1 || xx == 0 || yy == 0 || yy == ROWNO-1) + return; /* impossible */ + + crm = &levl[xx][yy]; + if(!(crm->typ)) { + if(rn2(100)) { + crm->typ = CORR; + crm->scrsym = CORR_SYM; + if(nxcor && !rn2(50)) + (void) mkobj_at(ROCK_SYM, xx, yy); + } else { + crm->typ = SCORR; + crm->scrsym = ' '; + } + } else + if(crm->typ != CORR && crm->typ != SCORR) { + /* strange ... */ + return; + } + + /* find next corridor position */ + dix = abs(xx-tx); + diy = abs(yy-ty); + + /* do we have to change direction ? */ + if(dy && dix > diy) { + register ddx = (xx > tx) ? -1 : 1; + + crm = &levl[xx+ddx][yy]; + if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) { + dx = ddx; + dy = 0; + continue; + } + } else if(dx && diy > dix) { + register ddy = (yy > ty) ? -1 : 1; + + crm = &levl[xx][yy+ddy]; + if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) { + dy = ddy; + dx = 0; + continue; + } + } + + /* continue straight on? */ + crm = &levl[xx+dx][yy+dy]; + if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) + continue; + + /* no, what must we do now?? */ + if(dx) { + dx = 0; + dy = (ty < yy) ? -1 : 1; + crm = &levl[xx+dx][yy+dy]; + if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) + continue; + dy = -dy; + continue; + } else { + dy = 0; + dx = (tx < xx) ? -1 : 1; + crm = &levl[xx+dx][yy+dy]; + if(!crm->typ || crm->typ == CORR || crm->typ == SCORR) + continue; + dx = -dx; + continue; + } + } + + /* we succeeded in digging the corridor */ + dodoor(tt.x, tt.y, troom); + + if(smeq[a] < smeq[b]) + smeq[b] = smeq[a]; + else + smeq[a] = smeq[b]; +} + +make_niches() +{ + register int ct = rnd(nroom/2 + 1); + while(ct--) makeniche(FALSE); +} + +makevtele() +{ + makeniche(TRUE); +} + +makeniche(with_trap) +boolean with_trap; +{ + register struct mkroom *aroom; + register struct rm *rm; + register int vct = 8; + coord dd; + register dy,xx,yy; + register struct trap *ttmp; + + if(doorindex < DOORMAX) + while(vct--) { + aroom = &rooms[rn2(nroom-1)]; + if(aroom->rtype != 0) continue; /* not an ordinary room */ + if(aroom->doorct == 1 && rn2(5)) continue; + if(rn2(2)) { + dy = 1; + dd = finddpos(aroom->lx,aroom->hy+1,aroom->hx,aroom->hy+1); + } else { + dy = -1; + dd = finddpos(aroom->lx,aroom->ly-1,aroom->hx,aroom->ly-1); + } + xx = dd.x; + yy = dd.y; + if((rm = &levl[xx][yy+dy])->typ) continue; + if(with_trap || !rn2(4)) { + rm->typ = SCORR; + rm->scrsym = ' '; + if(with_trap) { + ttmp = maketrap(xx, yy+dy, TELEP_TRAP); + ttmp->once = 1; + make_engr_at(xx, yy-dy, "ad ae?ar um"); + } + dosdoor(xx, yy, aroom, SDOOR); + } else { + rm->typ = CORR; + rm->scrsym = CORR_SYM; + if(rn2(7)) + dosdoor(xx, yy, aroom, rn2(5) ? SDOOR : DOOR); + else { + mksobj_at(SCR_TELEPORTATION, xx, yy+dy); + if(!rn2(3)) (void) mkobj_at(0, xx, yy+dy); + } + } + return; + } +} + +/* make a trap somewhere (in croom if mazeflag = 0) */ +mktrap(num,mazeflag,croom) +register num,mazeflag; +register struct mkroom *croom; +{ + register struct trap *ttmp; + register int kind,nopierc,nomimic,fakedoor,fakegold,tryct = 0; + register xchar mx,my; + extern char fut_geno[]; + + if(!num || num >= TRAPNUM) { + nopierc = (dlevel < 4) ? 1 : 0; + nomimic = (dlevel < 9 || goldseen ) ? 1 : 0; + if(index(fut_geno, 'M')) nomimic = 1; + kind = rn2(TRAPNUM - nopierc - nomimic); + /* note: PIERC = 7, MIMIC = 8, TRAPNUM = 9 */ + } else kind = num; + + if(kind == MIMIC) { + register struct monst *mtmp; + + fakedoor = (!rn2(3) && !mazeflag); + fakegold = (!fakedoor && !rn2(2)); + if(fakegold) goldseen = TRUE; + do { + if(++tryct > 200) return; + if(fakedoor) { + /* note: fakedoor maybe on actual door */ + if(rn2(2)){ + if(rn2(2)) + mx = croom->hx+1; + else mx = croom->lx-1; + my = somey(); + } else { + if(rn2(2)) + my = croom->hy+1; + else my = croom->ly-1; + mx = somex(); + } + } else if(mazeflag) { + extern coord mazexy(); + coord mm; + mm = mazexy(); + mx = mm.x; + my = mm.y; + } else { + mx = somex(); + my = somey(); + } + } while(m_at(mx,my) || levl[mx][my].typ == STAIRS); + if(mtmp = makemon(PM_MIMIC,mx,my)) { + mtmp->mimic = 1; + mtmp->mappearance = + fakegold ? '$' : fakedoor ? '+' : + (mazeflag && rn2(2)) ? AMULET_SYM : + "=/)%?![<>" [ rn2(9) ]; + } + return; + } + + do { + if(++tryct > 200) + return; + if(mazeflag){ + extern coord mazexy(); + coord mm; + mm = mazexy(); + mx = mm.x; + my = mm.y; + } else { + mx = somex(); + my = somey(); + } + } while(t_at(mx, my) || levl[mx][my].typ == STAIRS); + ttmp = maketrap(mx, my, kind); + if(mazeflag && !rn2(10) && ttmp->ttyp < PIERC) + ttmp->tseen = 1; +} diff --git a/usr/othersrc/games/hack/hack.mkmaze.c b/usr/othersrc/games/hack/hack.mkmaze.c new file mode 100644 index 0000000000..bee24f954c --- /dev/null +++ b/usr/othersrc/games/hack/hack.mkmaze.c @@ -0,0 +1,136 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.mkmaze.c - version 1.0.2 */ + +#include "hack.h" +#include "def.mkroom.h" /* not really used */ +extern struct monst *makemon(); +extern struct permonst pm_wizard; +extern struct obj *mkobj_at(); +extern coord mazexy(); +struct permonst hell_hound = + { "hell hound", 'd', 12, 14, 2, 3, 6, 0 }; + +makemaz() +{ + int x,y; + register zx,zy; + coord mm; + boolean al = (dlevel >= 30 && !flags.made_amulet); + + for(x = 2; x < COLNO-1; x++) + for(y = 2; y < ROWNO-1; y++) + levl[x][y].typ = (x%2 && y%2) ? 0 : HWALL; + if(al) { + register struct monst *mtmp; + + zx = 2*(COLNO/4) - 1; + zy = 2*(ROWNO/4) - 1; + for(x = zx-2; x < zx+4; x++) for(y = zy-2; y <= zy+2; y++) { + levl[x][y].typ = + (y == zy-2 || y == zy+2 || x == zx-2 || x == zx+3) ? POOL : + (y == zy-1 || y == zy+1 || x == zx-1 || x == zx+2) ? HWALL: + ROOM; + } + (void) mkobj_at(AMULET_SYM, zx, zy); + flags.made_amulet = 1; + walkfrom(zx+4, zy); + if(mtmp = makemon(&hell_hound, zx, zy)) + mtmp->msleep = 1; + if(mtmp = makemon(PM_WIZARD, zx+1, zy)) { + mtmp->msleep = 1; + flags.no_of_wizards = 1; + } + } else { + mm = mazexy(); + zx = mm.x; + zy = mm.y; + walkfrom(zx,zy); + (void) mksobj_at(WAN_WISHING, zx, zy); + (void) mkobj_at(ROCK_SYM, zx, zy); /* put a rock on top of it */ + } + + for(x = 2; x < COLNO-1; x++) + for(y = 2; y < ROWNO-1; y++) { + switch(levl[x][y].typ) { + case HWALL: + levl[x][y].scrsym = '-'; + break; + case ROOM: + levl[x][y].scrsym = '.'; + break; + } + } + for(x = rn1(8,11); x; x--) { + mm = mazexy(); + (void) mkobj_at(rn2(2) ? GEM_SYM : 0, mm.x, mm.y); + } + for(x = rn1(10,2); x; x--) { + mm = mazexy(); + (void) mkobj_at(ROCK_SYM, mm.x, mm.y); + } + mm = mazexy(); + (void) makemon(PM_MINOTAUR, mm.x, mm.y); + for(x = rn1(5,7); x; x--) { + mm = mazexy(); + (void) makemon((struct permonst *) 0, mm.x, mm.y); + } + for(x = rn1(6,7); x; x--) { + mm = mazexy(); + mkgold(0L,mm.x,mm.y); + } + for(x = rn1(6,7); x; x--) + mktrap(0,1,(struct mkroom *) 0); + mm = mazexy(); + levl[(xupstair = mm.x)][(yupstair = mm.y)].scrsym = '<'; + levl[xupstair][yupstair].typ = STAIRS; + xdnstair = ydnstair = 0; +} + +walkfrom(x,y) int x,y; { +register int q,a,dir; +int dirs[4]; + levl[x][y].typ = ROOM; + while(1) { + q = 0; + for(a = 0; a < 4; a++) + if(okay(x,y,a)) dirs[q++]= a; + if(!q) return; + dir = dirs[rn2(q)]; + move(&x,&y,dir); + levl[x][y].typ = ROOM; + move(&x,&y,dir); + walkfrom(x,y); + } +} + +move(x,y,dir) +register int *x, *y; +register int dir; +{ + switch(dir){ + case 0: --(*y); break; + case 1: (*x)++; break; + case 2: (*y)++; break; + case 3: --(*x); break; + } +} + +okay(x,y,dir) +int x,y; +register int dir; +{ + move(&x,&y,dir); + move(&x,&y,dir); + if(x<3 || y<3 || x>COLNO-3 || y>ROWNO-3 || levl[x][y].typ != 0) + return(0); + else + return(1); +} + +coord +mazexy(){ + coord mm; + mm.x = 3 + 2*rn2(COLNO/2 - 2); + mm.y = 3 + 2*rn2(ROWNO/2 - 2); + return mm; +} diff --git a/usr/othersrc/games/hack/hack.mkobj.c b/usr/othersrc/games/hack/hack.mkobj.c new file mode 100644 index 0000000000..18a69146d0 --- /dev/null +++ b/usr/othersrc/games/hack/hack.mkobj.c @@ -0,0 +1,148 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.mkobj.c - version 1.0.3 */ + +#include "hack.h" + +char mkobjstr[] = "))[[!!!!????%%%%/=**))[[!!!!????%%%%/=**(%"; +struct obj *mkobj(), *mksobj(); + +struct obj * +mkobj_at(let,x,y) +register let,x,y; +{ + register struct obj *otmp = mkobj(let); + otmp->ox = x; + otmp->oy = y; + otmp->nobj = fobj; + fobj = otmp; + return(otmp); +} + +mksobj_at(otyp,x,y) +register otyp,x,y; +{ + register struct obj *otmp = mksobj(otyp); + otmp->ox = x; + otmp->oy = y; + otmp->nobj = fobj; + fobj = otmp; +} + +struct obj * +mkobj(let) { + if(!let) + let = mkobjstr[rn2(sizeof(mkobjstr) - 1)]; + return( + mksobj( + letter(let) ? + CORPSE + ((let > 'Z') ? (let-'a'+'Z'-'@'+1) : (let-'@')) + : probtype(let) + ) + ); +} + + +struct obj zeroobj; + +struct obj * +mksobj(otyp) +register otyp; +{ + register struct obj *otmp; + char let = objects[otyp].oc_olet; + + otmp = newobj(0); + *otmp = zeroobj; + otmp->age = moves; + otmp->o_id = flags.ident++; + otmp->quan = 1; + otmp->olet = let; + otmp->otyp = otyp; + otmp->dknown = index("/=!?*", let) ? 0 : 1; + switch(let) { + case WEAPON_SYM: + otmp->quan = (otmp->otyp <= ROCK) ? rn1(6,6) : 1; + if(!rn2(11)) otmp->spe = rnd(3); + else if(!rn2(10)) { + otmp->cursed = 1; + otmp->spe = -rnd(3); + } + break; + case FOOD_SYM: + if(otmp->otyp >= CORPSE) break; +#ifdef NOT_YET_IMPLEMENTED + /* if tins are to be identified, need to adapt doname() etc */ + if(otmp->otyp == TIN) + otmp->spe = rnd(...); +#endif NOT_YET_IMPLEMENTED + /* fall into next case */ + case GEM_SYM: + otmp->quan = rn2(6) ? 1 : 2; + case TOOL_SYM: + case CHAIN_SYM: + case BALL_SYM: + case ROCK_SYM: + case POTION_SYM: + case SCROLL_SYM: + case AMULET_SYM: + break; + case ARMOR_SYM: + if(!rn2(8)) otmp->cursed = 1; + if(!rn2(10)) otmp->spe = rnd(3); + else if(!rn2(9)) { + otmp->spe = -rnd(3); + otmp->cursed = 1; + } + break; + case WAND_SYM: + if(otmp->otyp == WAN_WISHING) otmp->spe = 3; else + otmp->spe = rn1(5, + (objects[otmp->otyp].bits & NODIR) ? 11 : 4); + break; + case RING_SYM: + if(objects[otmp->otyp].bits & SPEC) { + if(!rn2(3)) { + otmp->cursed = 1; + otmp->spe = -rnd(2); + } else otmp->spe = rnd(2); + } else if(otmp->otyp == RIN_TELEPORTATION || + otmp->otyp == RIN_AGGRAVATE_MONSTER || + otmp->otyp == RIN_HUNGER || !rn2(9)) + otmp->cursed = 1; + break; + default: + panic("impossible mkobj"); + } + otmp->owt = weight(otmp); + return(otmp); +} + +letter(c) { + return(('@' <= c && c <= 'Z') || ('a' <= c && c <= 'z')); +} + +weight(obj) +register struct obj *obj; +{ +register int wt = objects[obj->otyp].oc_weight; + return(wt ? wt*obj->quan : (obj->quan + 1)/2); +} + +mkgold(num,x,y) +register long num; +{ + register struct gold *gold; + register long amount = (num ? num : 1 + (rnd(dlevel+2) * rnd(30))); + + if(gold = g_at(x,y)) + gold->amount += amount; + else { + gold = newgold(); + gold->ngold = fgold; + gold->gx = x; + gold->gy = y; + gold->amount = amount; + fgold = gold; + /* do sth with display? */ + } +} diff --git a/usr/othersrc/games/hack/hack.mkshop.c b/usr/othersrc/games/hack/hack.mkshop.c new file mode 100644 index 0000000000..9d99a22d2c --- /dev/null +++ b/usr/othersrc/games/hack/hack.mkshop.c @@ -0,0 +1,274 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.mkshop.c - version 1.0.3 */ + +#ifndef QUEST +#include "hack.h" +#include "def.mkroom.h" +#include "def.eshk.h" +#define ESHK ((struct eshk *)(&(shk->mextra[0]))) +extern struct monst *makemon(); +extern struct obj *mkobj_at(); +extern int nroom; +extern char shtypes[]; /* = "=/)%?!["; 8 types: 7 specialized, 1 mixed */ +schar shprobs[] = { 3,3,5,5,10,10,14,50 }; /* their probabilities */ + +mkshop(){ +register struct mkroom *sroom; +register int sh,sx,sy,i = -1; +register char let; +int roomno; +register struct monst *shk; +#ifdef WIZARD + /* first determine shoptype */ + if(wizard){ + extern char *getenv(); + register char *ep = getenv("SHOPTYPE"); + if(ep){ + if(*ep == 'z' || *ep == 'Z'){ + mkzoo(ZOO); + return; + } + if(*ep == 'm' || *ep == 'M'){ + mkzoo(MORGUE); + return; + } + if(*ep == 'b' || *ep == 'B'){ + mkzoo(BEEHIVE); + return; + } + if(*ep == 's' || *ep == 'S'){ + mkswamp(); + return; + } + for(i=0; shtypes[i]; i++) + if(*ep == shtypes[i]) break; + goto gottype; + } + } +gottype: +#endif WIZARD + for(sroom = &rooms[0], roomno = 0; ; sroom++, roomno++){ + if(sroom->hx < 0) return; + if(sroom - rooms >= nroom) { + pline("rooms not closed by -1?"); + return; + } + if(sroom->rtype) continue; + if(!sroom->rlit || has_dnstairs(sroom) || has_upstairs(sroom)) + continue; + if( +#ifdef WIZARD + (wizard && getenv("SHOPTYPE") && sroom->doorct != 0) || +#endif WIZARD + sroom->doorct <= 2 && sroom->doorct > 0) break; + } + + if(i < 0) { /* shoptype not yet determined */ + register int j; + + for(j = rn2(100), i = 0; (j -= shprobs[i])>= 0; i++) + if(!shtypes[i]) break; /* superfluous */ + if(isbig(sroom) && i + SHOPBASE == WANDSHOP) + i = GENERAL-SHOPBASE; + } + sroom->rtype = i + SHOPBASE; + let = shtypes[i]; + sh = sroom->fdoor; + sx = doors[sh].x; + sy = doors[sh].y; + if(sx == sroom->lx-1) sx++; else + if(sx == sroom->hx+1) sx--; else + if(sy == sroom->ly-1) sy++; else + if(sy == sroom->hy+1) sy--; else { +#ifdef WIZARD + /* This is said to happen sometimes, but I've never seen it. */ + if(wizard) { + register int j = sroom->doorct; + extern int doorindex; + + pline("Where is shopdoor?"); + pline("Room at (%d,%d),(%d,%d).", sroom->lx, sroom->ly, + sroom->hx, sroom->hy); + pline("doormax=%d doorct=%d fdoor=%d", + doorindex, sroom->doorct, sh); + while(j--) { + pline("door [%d,%d]", doors[sh].x, doors[sh].y); + sh++; + } + more(); + } +#endif WIZARD + return; + } + if(!(shk = makemon(PM_SHK,sx,sy))) return; + shk->isshk = shk->mpeaceful = 1; + shk->msleep = 0; + shk->mtrapseen = ~0; /* we know all the traps already */ + ESHK->shoproom = roomno; + ESHK->shoplevel = dlevel; + ESHK->shd = doors[sh]; + ESHK->shk.x = sx; + ESHK->shk.y = sy; + ESHK->robbed = 0; + ESHK->visitct = 0; + ESHK->following = 0; + shk->mgold = 1000 + 30*rnd(100); /* initial capital */ + ESHK->billct = 0; + findname(ESHK->shknam, let); + for(sx = sroom->lx; sx <= sroom->hx; sx++) + for(sy = sroom->ly; sy <= sroom->hy; sy++){ + register struct monst *mtmp; + if((sx == sroom->lx && doors[sh].x == sx-1) || + (sx == sroom->hx && doors[sh].x == sx+1) || + (sy == sroom->ly && doors[sh].y == sy-1) || + (sy == sroom->hy && doors[sh].y == sy+1)) continue; + if(rn2(100) < dlevel && !m_at(sx,sy) && + (mtmp = makemon(PM_MIMIC, sx, sy))){ + mtmp->mimic = 1; + mtmp->mappearance = + (let && rn2(10) < dlevel) ? let : ']'; + continue; + } + (void) mkobj_at(let, sx, sy); + } +} + +mkzoo(type) +int type; +{ + register struct mkroom *sroom; + register struct monst *mon; + register int sh,sx,sy,i; + int goldlim = 500 * dlevel; + int moct = 0; + struct permonst *morguemon(); + + i = nroom; + for(sroom = &rooms[rn2(nroom)]; ; sroom++) { + if(sroom == &rooms[nroom]) + sroom = &rooms[0]; + if(!i-- || sroom->hx < 0) + return; + if(sroom->rtype) + continue; + if(type == MORGUE && sroom->rlit) + continue; + if(has_upstairs(sroom) || (has_dnstairs(sroom) && rn2(3))) + continue; + if(sroom->doorct == 1 || !rn2(5)) + break; + } + sroom->rtype = type; + sh = sroom->fdoor; + for(sx = sroom->lx; sx <= sroom->hx; sx++) + for(sy = sroom->ly; sy <= sroom->hy; sy++){ + if((sx == sroom->lx && doors[sh].x == sx-1) || + (sx == sroom->hx && doors[sh].x == sx+1) || + (sy == sroom->ly && doors[sh].y == sy-1) || + (sy == sroom->hy && doors[sh].y == sy+1)) continue; + mon = makemon( + (type == MORGUE) ? morguemon() : + (type == BEEHIVE) ? PM_KILLER_BEE : (struct permonst *) 0, + sx, sy); + if(mon) mon->msleep = 1; + switch(type) { + case ZOO: + i = sq(dist2(sx,sy,doors[sh].x,doors[sh].y)); + if(i >= goldlim) i = 5*dlevel; + goldlim -= i; + mkgold((long)(10 + rn2(i)), sx, sy); + break; + case MORGUE: + /* Usually there is one dead body in the morgue */ + if(!moct && rn2(3)) { + mksobj_at(CORPSE, sx, sy); + moct++; + } + break; + case BEEHIVE: + if(!rn2(3)) mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy); + break; + } + } +} + +struct permonst * +morguemon() +{ + extern struct permonst pm_ghost; + register int i = rn2(100), hd = rn2(dlevel); + + if(hd > 10 && i < 10) return(PM_DEMON); + if(hd > 8 && i > 85) return(PM_VAMPIRE); + return((i < 40) ? PM_GHOST : (i < 60) ? PM_WRAITH : PM_ZOMBIE); +} + +mkswamp() /* Michiel Huisjes & Fred de Wilde */ +{ + register struct mkroom *sroom; + register int sx,sy,i,eelct = 0; + extern struct permonst pm_eel; + + for(i=0; i<5; i++) { /* 5 tries */ + sroom = &rooms[rn2(nroom)]; + if(sroom->hx < 0 || sroom->rtype || + has_upstairs(sroom) || has_dnstairs(sroom)) + continue; + + /* satisfied; make a swamp */ + sroom->rtype = SWAMP; + for(sx = sroom->lx; sx <= sroom->hx; sx++) + for(sy = sroom->ly; sy <= sroom->hy; sy++) + if((sx+sy)%2 && !o_at(sx,sy) && !t_at(sx,sy) + && !m_at(sx,sy) && !nexttodoor(sx,sy)){ + levl[sx][sy].typ = POOL; + levl[sx][sy].scrsym = POOL_SYM; + if(!eelct || !rn2(4)) { + (void) makemon(PM_EEL, sx, sy); + eelct++; + } + } + } +} + +nexttodoor(sx,sy) +register sx,sy; +{ + register dx,dy; + register struct rm *lev; + for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++) + if((lev = &levl[sx+dx][sy+dy])->typ == DOOR || + lev->typ == SDOOR || lev->typ == LDOOR) + return(1); + return(0); +} + +has_dnstairs(sroom) +register struct mkroom *sroom; +{ + return(sroom->lx <= xdnstair && xdnstair <= sroom->hx && + sroom->ly <= ydnstair && ydnstair <= sroom->hy); +} + +has_upstairs(sroom) +register struct mkroom *sroom; +{ + return(sroom->lx <= xupstair && xupstair <= sroom->hx && + sroom->ly <= yupstair && yupstair <= sroom->hy); +} + +isbig(sroom) +register struct mkroom *sroom; +{ + register int area = (sroom->hx - sroom->lx) * (sroom->hy - sroom->ly); + return( area > 20 ); +} + +dist2(x0,y0,x1,y1){ + return((x0-x1)*(x0-x1) + (y0-y1)*(y0-y1)); +} + +sq(a) int a; { + return(a*a); +} +#endif QUEST diff --git a/usr/othersrc/games/hack/hack.monst.c b/usr/othersrc/games/hack/hack.monst.c new file mode 100644 index 0000000000..b682b59de2 --- /dev/null +++ b/usr/othersrc/games/hack/hack.monst.c @@ -0,0 +1,79 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.monst.c - version 1.0.2 */ + +#include "hack.h" +#include "def.eshk.h" +extern char plname[PL_NSIZ]; + +struct permonst mons[CMNUM+2] = { + { "bat", 'B',1,22,8,1,4,0 }, + { "gnome", 'G',1,6,5,1,6,0 }, + { "hobgoblin", 'H',1,9,5,1,8,0 }, + { "jackal", 'J',0,12,7,1,2,0 }, + { "kobold", 'K',1,6,7,1,4,0 }, + { "leprechaun", 'L',5,15,8,1,2,0 }, + { "giant rat", 'r',0,12,7,1,3,0 }, + { "acid blob", 'a',2,3,8,0,0,0 }, + { "floating eye", 'E',2,1,9,0,0,0 }, + { "homunculus", 'h',2,6,6,1,3,0 }, + { "imp", 'i',2,6,2,1,4,0 }, + { "orc", 'O',2,9,6,1,8,0 }, + { "yellow light", 'y',3,15,0,0,0,0 }, + { "zombie", 'Z',2,6,8,1,8,0 }, + { "giant ant", 'A',3,18,3,1,6,0 }, + { "fog cloud", 'f',3,1,0,1,6,0 }, + { "nymph", 'N',6,12,9,1,2,0 }, + { "piercer", 'p',3,1,3,2,6,0 }, + { "quasit", 'Q',3,15,3,1,4,0 }, + { "quivering blob", 'q',3,1,8,1,8,0 }, + { "violet fungi", 'v',3,1,7,1,4,0 }, + { "giant beetle", 'b',4,6,4,3,4,0 }, + { "centaur", 'C',4,18,4,1,6,0 }, + { "cockatrice", 'c',4,6,6,1,3,0 }, + { "gelatinous cube", 'g',4,6,8,2,4,0 }, + { "jaguar", 'j',4,15,6,1,8,0 }, + { "killer bee", 'k',4,14,4,2,4,0 }, + { "snake", 'S',4,15,3,1,6,0 }, + { "freezing sphere", 'F',2,13,4,0,0,0 }, + { "owlbear", 'o',5,12,5,2,6,0 }, + { "rust monster", 'R',10,18,3,0,0,0 }, + { "scorpion", 's',5,15,3,1,4,0 }, + { "tengu", 't',5,13,5,1,7,0 }, + { "wraith", 'W',5,12,5,1,6,0 }, +#ifdef NOWORM + { "wumpus", 'w',8,3,2,3,6,0 }, +#else + { "long worm", 'w',8,3,5,1,4,0 }, +#endif NOWORM + { "large dog", 'd',6,15,4,2,4,0 }, + { "leocrotta", 'l',6,18,4,3,6,0 }, + { "mimic", 'M',7,3,7,3,4,0 }, + { "troll", 'T',7,12,4,2,7,0 }, + { "unicorn", 'u',8,24,5,1,10,0 }, + { "yeti", 'Y',5,15,6,1,6,0 }, + { "stalker", 'I',8,12,3,4,4,0 }, + { "umber hulk", 'U',9,6,2,2,10,0 }, + { "vampire", 'V',8,12,1,1,6,0 }, + { "xorn", 'X',8,9,-2,4,6,0 }, + { "xan", 'x',7,18,-2,2,4,0 }, + { "zruty", 'z',9,8,3,3,6,0 }, + { "chameleon", ':',6,5,6,4,2,0 }, + { "dragon", 'D',10,9,-1,3,8,0 }, + { "ettin", 'e',10,12,3,2,8,0 }, + { "lurker above", '\'',10,3,3,0,0,0 }, + { "nurse", 'n',11,6,0,1,3,0 }, + { "trapper", ',',12,3,3,0,0,0 }, + { "purple worm", 'P',15,9,6,2,8,0 }, + { "demon", '&',10,12,-4,1,4,0 }, + { "minotaur", 'm',15,15,6,4,10,0 }, + { "shopkeeper", '@', 12, 18, 0, 4, 8, sizeof(struct eshk) } +}; + +struct permonst pm_ghost = { "ghost", ' ', 10, 3, -5, 1, 1, sizeof(plname) }; +struct permonst pm_wizard = { + "wizard of Yendor", '1', 15, 12, -2, 1, 12, 0 +}; +#ifdef MAIL +struct permonst pm_mail_daemon = { "mail daemon", '2', 100, 1, 10, 0, 0, 0 }; +#endif MAIL +struct permonst pm_eel = { "giant eel", ';', 15, 6, -3, 3, 6, 0 }; diff --git a/usr/othersrc/games/hack/hack.o_init.c b/usr/othersrc/games/hack/hack.o_init.c new file mode 100644 index 0000000000..37b33aefb0 --- /dev/null +++ b/usr/othersrc/games/hack/hack.o_init.c @@ -0,0 +1,160 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.o_init.c - version 1.0.3 */ + +#include "config.h" /* for typedefs */ +#include "def.objects.h" +#include "hack.onames.h" /* for LAST_GEM */ +extern char *index(); + +int +letindex(let) register char let; { +register int i = 0; +register char ch; + while((ch = obj_symbols[i++]) != 0) + if(ch == let) return(i); + return(0); +} + +init_objects(){ +register int i, j, first, last, sum, end; +register char let, *tmp; + /* init base; if probs given check that they add up to 100, + otherwise compute probs; shuffle descriptions */ + end = SIZE(objects); + first = 0; + while( first < end ) { + let = objects[first].oc_olet; + last = first+1; + while(last < end && objects[last].oc_olet == let + && objects[last].oc_name != NULL) + last++; + i = letindex(let); + if((!i && let != ILLOBJ_SYM) || bases[i] != 0) + error("initialization error"); + bases[i] = first; + + if(let == GEM_SYM) + setgemprobs(); + check: + sum = 0; + for(j = first; j < last; j++) sum += objects[j].oc_prob; + if(sum == 0) { + for(j = first; j < last; j++) + objects[j].oc_prob = (100+j-first)/(last-first); + goto check; + } + if(sum != 100) + error("init-prob error for %c", let); + + if(objects[first].oc_descr != NULL && let != TOOL_SYM){ + /* shuffle, also some additional descriptions */ + while(last < end && objects[last].oc_olet == let) + last++; + j = last; + while(--j > first) { + i = first + rn2(j+1-first); + tmp = objects[j].oc_descr; + objects[j].oc_descr = objects[i].oc_descr; + objects[i].oc_descr = tmp; + } + } + first = last; + } +} + +probtype(let) register char let; { +register int i = bases[letindex(let)]; +register int prob = rn2(100); + while((prob -= objects[i].oc_prob) >= 0) i++; + if(objects[i].oc_olet != let || !objects[i].oc_name) + panic("probtype(%c) error, i=%d", let, i); + return(i); +} + +setgemprobs() +{ + register int j,first; + extern xchar dlevel; + + first = bases[letindex(GEM_SYM)]; + + for(j = 0; j < 9-dlevel/3; j++) + objects[first+j].oc_prob = 0; + first += j; + if(first >= LAST_GEM || first >= SIZE(objects) || + objects[first].oc_olet != GEM_SYM || + objects[first].oc_name == NULL) + printf("Not enough gems? - first=%d j=%d LAST_GEM=%d\n", + first, j, LAST_GEM); + for(j = first; j < LAST_GEM; j++) + objects[j].oc_prob = (20+j-first)/(LAST_GEM-first); +} + +oinit() /* level dependent initialization */ +{ + setgemprobs(); +} + +extern long *alloc(); + +savenames(fd) register fd; { +register int i; +unsigned len; + bwrite(fd, (char *) bases, sizeof bases); + bwrite(fd, (char *) objects, sizeof objects); + /* as long as we use only one version of Hack/Quest we + need not save oc_name and oc_descr, but we must save + oc_uname for all objects */ + for(i=0; i < SIZE(objects); i++) { + if(objects[i].oc_uname) { + len = strlen(objects[i].oc_uname)+1; + bwrite(fd, (char *) &len, sizeof len); + bwrite(fd, objects[i].oc_uname, len); + } + } +} + +restnames(fd) register fd; { +register int i; +unsigned len; + mread(fd, (char *) bases, sizeof bases); + mread(fd, (char *) objects, sizeof objects); + for(i=0; i < SIZE(objects); i++) if(objects[i].oc_uname) { + mread(fd, (char *) &len, sizeof len); + objects[i].oc_uname = (char *) alloc(len); + mread(fd, objects[i].oc_uname, len); + } +} + +dodiscovered() /* free after Robert Viduya */ +{ + extern char *typename(); + register int i, end; + int ct = 0; + + cornline(0, "Discoveries"); + + end = SIZE(objects); + for (i = 0; i < end; i++) { + if (interesting_to_discover (i)) { + ct++; + cornline(1, typename(i)); + } + } + if (ct == 0) { + pline ("You haven't discovered anything yet..."); + cornline(3, (char *) 0); + } else + cornline(2, (char *) 0); + + return(0); +} + +interesting_to_discover(i) +register int i; +{ + return( + objects[i].oc_uname != NULL || + (objects[i].oc_name_known && objects[i].oc_descr != NULL) + ); +} diff --git a/usr/othersrc/games/hack/hack.objnam.c b/usr/othersrc/games/hack/hack.objnam.c new file mode 100644 index 0000000000..a1c966cd91 --- /dev/null +++ b/usr/othersrc/games/hack/hack.objnam.c @@ -0,0 +1,547 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.objnam.c - version 1.0.2 */ + +#include "hack.h" +#define Sprintf (void) sprintf +#define Strcat (void) strcat +#define Strcpy (void) strcpy +#define PREFIX 15 +extern char *eos(); +extern int bases[]; + +char * +strprepend(s,pref) register char *s, *pref; { +register int i = strlen(pref); + if(i > PREFIX) { + pline("WARNING: prefix too short."); + return(s); + } + s -= i; + (void) strncpy(s, pref, i); /* do not copy trailing 0 */ + return(s); +} + +char * +sitoa(a) int a; { +static char buf[13]; + Sprintf(buf, (a < 0) ? "%d" : "+%d", a); + return(buf); +} + +char * +typename(otyp) +register int otyp; +{ +static char buf[BUFSZ]; +register struct objclass *ocl = &objects[otyp]; +register char *an = ocl->oc_name; +register char *dn = ocl->oc_descr; +register char *un = ocl->oc_uname; +register int nn = ocl->oc_name_known; + switch(ocl->oc_olet) { + case POTION_SYM: + Strcpy(buf, "potion"); + break; + case SCROLL_SYM: + Strcpy(buf, "scroll"); + break; + case WAND_SYM: + Strcpy(buf, "wand"); + break; + case RING_SYM: + Strcpy(buf, "ring"); + break; + default: + if(nn) { + Strcpy(buf, an); + if(otyp >= TURQUOISE && otyp <= JADE) + Strcat(buf, " stone"); + if(un) + Sprintf(eos(buf), " called %s", un); + if(dn) + Sprintf(eos(buf), " (%s)", dn); + } else { + Strcpy(buf, dn ? dn : an); + if(ocl->oc_olet == GEM_SYM) + Strcat(buf, " gem"); + if(un) + Sprintf(eos(buf), " called %s", un); + } + return(buf); + } + /* here for ring/scroll/potion/wand */ + if(nn) + Sprintf(eos(buf), " of %s", an); + if(un) + Sprintf(eos(buf), " called %s", un); + if(dn) + Sprintf(eos(buf), " (%s)", dn); + return(buf); +} + +char * +xname(obj) +register struct obj *obj; +{ +static char bufr[BUFSZ]; +register char *buf = &(bufr[PREFIX]); /* leave room for "17 -3 " */ +register int nn = objects[obj->otyp].oc_name_known; +register char *an = objects[obj->otyp].oc_name; +register char *dn = objects[obj->otyp].oc_descr; +register char *un = objects[obj->otyp].oc_uname; +register int pl = (obj->quan != 1); + if(!obj->dknown && !Blind) obj->dknown = 1; /* %% doesnt belong here */ + switch(obj->olet) { + case AMULET_SYM: + Strcpy(buf, (obj->spe < 0 && obj->known) + ? "cheap plastic imitation of the " : ""); + Strcat(buf,"Amulet of Yendor"); + break; + case TOOL_SYM: + if(!nn) { + Strcpy(buf, dn); + break; + } + Strcpy(buf,an); + break; + case FOOD_SYM: + if(obj->otyp == DEAD_HOMUNCULUS && pl) { + pl = 0; + Strcpy(buf, "dead homunculi"); + break; + } + /* fungis ? */ + /* fall into next case */ + case WEAPON_SYM: + if(obj->otyp == WORM_TOOTH && pl) { + pl = 0; + Strcpy(buf, "worm teeth"); + break; + } + if(obj->otyp == CRYSKNIFE && pl) { + pl = 0; + Strcpy(buf, "crysknives"); + break; + } + /* fall into next case */ + case ARMOR_SYM: + case CHAIN_SYM: + case ROCK_SYM: + Strcpy(buf,an); + break; + case BALL_SYM: + Sprintf(buf, "%sheavy iron ball", + (obj->owt > objects[obj->otyp].oc_weight) ? "very " : ""); + break; + case POTION_SYM: + if(nn || un || !obj->dknown) { + Strcpy(buf, "potion"); + if(pl) { + pl = 0; + Strcat(buf, "s"); + } + if(!obj->dknown) break; + if(un) { + Strcat(buf, " called "); + Strcat(buf, un); + } else { + Strcat(buf, " of "); + Strcat(buf, an); + } + } else { + Strcpy(buf, dn); + Strcat(buf, " potion"); + } + break; + case SCROLL_SYM: + Strcpy(buf, "scroll"); + if(pl) { + pl = 0; + Strcat(buf, "s"); + } + if(!obj->dknown) break; + if(nn) { + Strcat(buf, " of "); + Strcat(buf, an); + } else if(un) { + Strcat(buf, " called "); + Strcat(buf, un); + } else { + Strcat(buf, " labeled "); + Strcat(buf, dn); + } + break; + case WAND_SYM: + if(!obj->dknown) + Sprintf(buf, "wand"); + else if(nn) + Sprintf(buf, "wand of %s", an); + else if(un) + Sprintf(buf, "wand called %s", un); + else + Sprintf(buf, "%s wand", dn); + break; + case RING_SYM: + if(!obj->dknown) + Sprintf(buf, "ring"); + else if(nn) + Sprintf(buf, "ring of %s", an); + else if(un) + Sprintf(buf, "ring called %s", un); + else + Sprintf(buf, "%s ring", dn); + break; + case GEM_SYM: + if(!obj->dknown) { + Strcpy(buf, "gem"); + break; + } + if(!nn) { + Sprintf(buf, "%s gem", dn); + break; + } + Strcpy(buf, an); + if(obj->otyp >= TURQUOISE && obj->otyp <= JADE) + Strcat(buf, " stone"); + break; + default: + Sprintf(buf,"glorkum %c (0%o) %u %d", + obj->olet,obj->olet,obj->otyp,obj->spe); + } + if(pl) { + register char *p; + + for(p = buf; *p; p++) { + if(!strncmp(" of ", p, 4)) { + /* pieces of, cloves of, lumps of */ + register int c1, c2 = 's'; + + do { + c1 = c2; c2 = *p; *p++ = c1; + } while(c1); + goto nopl; + } + } + p = eos(buf)-1; + if(*p == 's' || *p == 'z' || *p == 'x' || + (*p == 'h' && p[-1] == 's')) + Strcat(buf, "es"); /* boxes */ + else if(*p == 'y' && !index(vowels, p[-1])) + Strcpy(p, "ies"); /* rubies, zruties */ + else + Strcat(buf, "s"); + } +nopl: + if(obj->onamelth) { + Strcat(buf, " named "); + Strcat(buf, ONAME(obj)); + } + return(buf); +} + +char * +doname(obj) +register struct obj *obj; +{ +char prefix[PREFIX]; +register char *bp = xname(obj); + if(obj->quan != 1) + Sprintf(prefix, "%u ", obj->quan); + else + Strcpy(prefix, "a "); + switch(obj->olet) { + case AMULET_SYM: + if(strncmp(bp, "cheap ", 6)) + Strcpy(prefix, "the "); + break; + case ARMOR_SYM: + if(obj->owornmask & W_ARMOR) + Strcat(bp, " (being worn)"); + /* fall into next case */ + case WEAPON_SYM: + if(obj->known) { + Strcat(prefix, sitoa(obj->spe)); + Strcat(prefix, " "); + } + break; + case WAND_SYM: + if(obj->known) + Sprintf(eos(bp), " (%d)", obj->spe); + break; + case RING_SYM: + if(obj->owornmask & W_RINGR) Strcat(bp, " (on right hand)"); + if(obj->owornmask & W_RINGL) Strcat(bp, " (on left hand)"); + if(obj->known && (objects[obj->otyp].bits & SPEC)) { + Strcat(prefix, sitoa(obj->spe)); + Strcat(prefix, " "); + } + break; + } + if(obj->owornmask & W_WEP) + Strcat(bp, " (weapon in hand)"); + if(obj->unpaid) + Strcat(bp, " (unpaid)"); + if(!strcmp(prefix, "a ") && index(vowels, *bp)) + Strcpy(prefix, "an "); + bp = strprepend(bp, prefix); + return(bp); +} + +/* used only in hack.fight.c (thitu) */ +setan(str,buf) +register char *str,*buf; +{ + if(index(vowels,*str)) + Sprintf(buf, "an %s", str); + else + Sprintf(buf, "a %s", str); +} + +char * +aobjnam(otmp,verb) register struct obj *otmp; register char *verb; { +register char *bp = xname(otmp); +char prefix[PREFIX]; + if(otmp->quan != 1) { + Sprintf(prefix, "%u ", otmp->quan); + bp = strprepend(bp, prefix); + } + + if(verb) { + /* verb is given in plural (i.e., without trailing s) */ + Strcat(bp, " "); + if(otmp->quan != 1) + Strcat(bp, verb); + else if(!strcmp(verb, "are")) + Strcat(bp, "is"); + else { + Strcat(bp, verb); + Strcat(bp, "s"); + } + } + return(bp); +} + +char * +Doname(obj) +register struct obj *obj; +{ + register char *s = doname(obj); + + if('a' <= *s && *s <= 'z') *s -= ('a' - 'A'); + return(s); +} + +char *wrp[] = { "wand", "ring", "potion", "scroll", "gem" }; +char wrpsym[] = { WAND_SYM, RING_SYM, POTION_SYM, SCROLL_SYM, GEM_SYM }; + +struct obj * +readobjnam(bp) register char *bp; { +register char *p; +register int i; +int cnt, spe, spesgn, typ, heavy; +char let; +char *un, *dn, *an; +/* int the = 0; char *oname = 0; */ + cnt = spe = spesgn = typ = heavy = 0; + let = 0; + an = dn = un = 0; + for(p = bp; *p; p++) + if('A' <= *p && *p <= 'Z') *p += 'a'-'A'; + if(!strncmp(bp, "the ", 4)){ +/* the = 1; */ + bp += 4; + } else if(!strncmp(bp, "an ", 3)){ + cnt = 1; + bp += 3; + } else if(!strncmp(bp, "a ", 2)){ + cnt = 1; + bp += 2; + } + if(!cnt && digit(*bp)){ + cnt = atoi(bp); + while(digit(*bp)) bp++; + while(*bp == ' ') bp++; + } + if(!cnt) cnt = 1; /* %% what with "gems" etc. ? */ + + if(*bp == '+' || *bp == '-'){ + spesgn = (*bp++ == '+') ? 1 : -1; + spe = atoi(bp); + while(digit(*bp)) bp++; + while(*bp == ' ') bp++; + } else { + p = rindex(bp, '('); + if(p) { + if(p > bp && p[-1] == ' ') p[-1] = 0; + else *p = 0; + p++; + spe = atoi(p); + while(digit(*p)) p++; + if(strcmp(p, ")")) spe = 0; + else spesgn = 1; + } + } + /* now we have the actual name, as delivered by xname, say + green potions called whisky + scrolls labeled "QWERTY" + egg + dead zruties + fortune cookies + very heavy iron ball named hoei + wand of wishing + elven cloak + */ + for(p = bp; *p; p++) if(!strncmp(p, " named ", 7)) { + *p = 0; +/* oname = p+7; */ + } + for(p = bp; *p; p++) if(!strncmp(p, " called ", 8)) { + *p = 0; + un = p+8; + } + for(p = bp; *p; p++) if(!strncmp(p, " labeled ", 9)) { + *p = 0; + dn = p+9; + } + + /* first change to singular if necessary */ + if(cnt != 1) { + /* find "cloves of garlic", "worthless pieces of blue glass" */ + for(p = bp; *p; p++) if(!strncmp(p, "s of ", 5)){ + while(*p = p[1]) p++; + goto sing; + } + /* remove -s or -es (boxes) or -ies (rubies, zruties) */ + p = eos(bp); + if(p[-1] == 's') { + if(p[-2] == 'e') { + if(p[-3] == 'i') { + if(!strcmp(p-7, "cookies")) + goto mins; + Strcpy(p-3, "y"); + goto sing; + } + + /* note: cloves / knives from clove / knife */ + if(!strcmp(p-6, "knives")) { + Strcpy(p-3, "fe"); + goto sing; + } + + /* note: nurses, axes but boxes */ + if(!strcmp(p-5, "boxes")) { + p[-2] = 0; + goto sing; + } + } + mins: + p[-1] = 0; + } else { + if(!strcmp(p-9, "homunculi")) { + Strcpy(p-1, "us"); /* !! makes string longer */ + goto sing; + } + if(!strcmp(p-5, "teeth")) { + Strcpy(p-5, "tooth"); + goto sing; + } + /* here we cannot find the plural suffix */ + } + } +sing: + if(!strcmp(bp, "amulet of yendor")) { + typ = AMULET_OF_YENDOR; + goto typfnd; + } + p = eos(bp); + if(!strcmp(p-5, " mail")){ /* Note: ring mail is not a ring ! */ + let = ARMOR_SYM; + an = bp; + goto srch; + } + for(i = 0; i < sizeof(wrpsym); i++) { + register int j = strlen(wrp[i]); + if(!strncmp(bp, wrp[i], j)){ + let = wrpsym[i]; + bp += j; + if(!strncmp(bp, " of ", 4)) an = bp+4; + /* else if(*bp) ?? */ + goto srch; + } + if(!strcmp(p-j, wrp[i])){ + let = wrpsym[i]; + p -= j; + *p = 0; + if(p[-1] == ' ') p[-1] = 0; + dn = bp; + goto srch; + } + } + if(!strcmp(p-6, " stone")){ + p[-6] = 0; + let = GEM_SYM; + an = bp; + goto srch; + } + if(!strcmp(bp, "very heavy iron ball")){ + heavy = 1; + typ = HEAVY_IRON_BALL; + goto typfnd; + } + an = bp; +srch: + if(!an && !dn && !un) + goto any; + i = 1; + if(let) i = bases[letindex(let)]; + while(i <= NROFOBJECTS && (!let || objects[i].oc_olet == let)){ + register char *zn = objects[i].oc_name; + + if(!zn) goto nxti; + if(an && strcmp(an, zn)) + goto nxti; + if(dn && (!(zn = objects[i].oc_descr) || strcmp(dn, zn))) + goto nxti; + if(un && (!(zn = objects[i].oc_uname) || strcmp(un, zn))) + goto nxti; + typ = i; + goto typfnd; + nxti: + i++; + } +any: + if(!let) let = wrpsym[rn2(sizeof(wrpsym))]; + typ = probtype(let); +typfnd: + { register struct obj *otmp; + extern struct obj *mksobj(); + let = objects[typ].oc_olet; + otmp = mksobj(typ); + if(heavy) + otmp->owt += 15; + if(cnt > 0 && index("%?!*)", let) && + (cnt < 4 || (let == WEAPON_SYM && typ <= ROCK && cnt < 20))) + otmp->quan = cnt; + + if(spe > 3 && spe > otmp->spe) + spe = 0; + else if(let == WAND_SYM) + spe = otmp->spe; + if(spe == 3 && u.uluck < 0) + spesgn = -1; + if(let != WAND_SYM && spesgn == -1) + spe = -spe; + if(let == BALL_SYM) + spe = 0; + else if(let == AMULET_SYM) + spe = -1; + else if(typ == WAN_WISHING && rn2(10)) + spe = (rn2(10) ? -1 : 0); + otmp->spe = spe; + + if(spesgn == -1) + otmp->cursed = 1; + + return(otmp); + } +} diff --git a/usr/othersrc/games/hack/hack.onames.h b/usr/othersrc/games/hack/hack.onames.h new file mode 100644 index 0000000000..c0fe81eaa6 --- /dev/null +++ b/usr/othersrc/games/hack/hack.onames.h @@ -0,0 +1,227 @@ +#define STRANGE_OBJECT 0 +#define AMULET_OF_YENDOR 1 +#define FOOD_RATION 2 +#define TRIPE_RATION 3 +#define PANCAKE 4 +#define DEAD_LIZARD 5 +#define FORTUNE_COOKIE 6 +#define CARROT 7 +#define TIN 8 +#define ORANGE 9 +#define APPLE 10 +#define PEAR 11 +#define MELON 12 +#define BANANA 13 +#define CANDY_BAR 14 +#define EGG 15 +#define CLOVE_OF_GARLIC 16 +#define LUMP_OF_ROYAL_JELLY 17 +#define DEAD_HUMAN 18 +#define DEAD_GIANT_ANT 19 +#define DEAD_GIANT_BAT 20 +#define DEAD_CENTAUR 21 +#define DEAD_DRAGON 22 +#define DEAD_FLOATING_EYE 23 +#define DEAD_FREEZING_SPHERE 24 +#define DEAD_GNOME 25 +#define DEAD_HOBGOBLIN 26 +#define DEAD_STALKER 27 +#define DEAD_JACKAL 28 +#define DEAD_KOBOLD 29 +#define DEAD_LEPRECHAUN 30 +#define DEAD_MIMIC 31 +#define DEAD_NYMPH 32 +#define DEAD_ORC 33 +#define DEAD_PURPLE_WORM 34 +#define DEAD_QUASIT 35 +#define DEAD_RUST_MONSTER 36 +#define DEAD_SNAKE 37 +#define DEAD_TROLL 38 +#define DEAD_UMBER_HULK 39 +#define DEAD_VAMPIRE 40 +#define DEAD_WRAITH 41 +#define DEAD_XORN 42 +#define DEAD_YETI 43 +#define DEAD_ZOMBIE 44 +#define DEAD_ACID_BLOB 45 +#define DEAD_GIANT_BEETLE 46 +#define DEAD_COCKATRICE 47 +#define DEAD_DOG 48 +#define DEAD_ETTIN 49 +#define DEAD_FOG_CLOUD 50 +#define DEAD_GELATINOUS_CUBE 51 +#define DEAD_HOMUNCULUS 52 +#define DEAD_IMP 53 +#define DEAD_JAGUAR 54 +#define DEAD_KILLER_BEE 55 +#define DEAD_LEOCROTTA 56 +#define DEAD_MINOTAUR 57 +#define DEAD_NURSE 58 +#define DEAD_OWLBEAR 59 +#define DEAD_PIERCER 60 +#define DEAD_QUIVERING_BLOB 61 +#define DEAD_GIANT_RAT 62 +#define DEAD_GIANT_SCORPION 63 +#define DEAD_TENGU 64 +#define DEAD_UNICORN 65 +#define DEAD_VIOLET_FUNGI 66 +#define DEAD_LONG_WORM 67 +#define DEAD_XAN 68 +#define DEAD_YELLOW_LIGHT 69 +#define DEAD_ZRUTY 70 +#define ARROW 71 +#define SLING_BULLET 72 +#define CROSSBOW_BOLT 73 +#define DART 74 +#define ROCK 75 +#define BOOMERANG 76 +#define MACE 77 +#define AXE 78 +#define FLAIL 79 +#define LONG_SWORD 80 +#define TWO_HANDED_SWORD 81 +#define DAGGER 82 +#define WORM_TOOTH 83 +#define CRYSKNIFE 84 +#define SPEAR 85 +#define BOW 86 +#define SLING 87 +#define CROSSBOW 88 +#define WHISTLE 89 +#define MAGIC_WHISTLE 90 +#define EXPENSIVE_CAMERA 91 +#define ICE_BOX 92 +#define PICK_AXE 93 +#define CAN_OPENER 94 +#define HEAVY_IRON_BALL 95 +#define IRON_CHAIN 96 +#define ENORMOUS_ROCK 97 +#define HELMET 98 +#define PLATE_MAIL 99 +#define SPLINT_MAIL 100 +#define BANDED_MAIL 101 +#define CHAIN_MAIL 102 +#define SCALE_MAIL 103 +#define RING_MAIL 104 +#define STUDDED_LEATHER_ARMOR 105 +#define LEATHER_ARMOR 106 +#define ELVEN_CLOAK 107 +#define SHIELD 108 +#define PAIR_OF_GLOVES 109 +#define POT_RESTORE_STRENGTH 110 +#define POT_BOOZE 111 +#define POT_INVISIBILITY 112 +#define POT_FRUIT_JUICE 113 +#define POT_HEALING 114 +#define POT_PARALYSIS 115 +#define POT_MONSTER_DETECTION 116 +#define POT_OBJECT_DETECTION 117 +#define POT_SICKNESS 118 +#define POT_CONFUSION 119 +#define POT_GAIN_STRENGTH 120 +#define POT_SPEED 121 +#define POT_BLINDNESS 122 +#define POT_GAIN_LEVEL 123 +#define POT_EXTRA_HEALING 124 +#define POT_LEVITATION 125 +#define SCR_MAIL 130 +#define SCR_ENCHANT_ARMOR 131 +#define SCR_DESTROY_ARMOR 132 +#define SCR_CONFUSE_MONSTER 133 +#define SCR_SCARE_MONSTER 134 +#define SCR_BLANK_PAPER 135 +#define SCR_REMOVE_CURSE 136 +#define SCR_ENCHANT_WEAPON 137 +#define SCR_DAMAGE_WEAPON 138 +#define SCR_CREATE_MONSTER 139 +#define SCR_TAMING 140 +#define SCR_GENOCIDE 141 +#define SCR_LIGHT 142 +#define SCR_TELEPORTATION 143 +#define SCR_GOLD_DETECTION 144 +#define SCR_FOOD_DETECTION 145 +#define SCR_IDENTIFY 146 +#define SCR_MAGIC_MAPPING 147 +#define SCR_AMNESIA 148 +#define SCR_FIRE 149 +#define SCR_PUNISHMENT 150 +#define WAN_LIGHT 155 +#define WAN_SECRET_DOOR_DETECTION 156 +#define WAN_CREATE_MONSTER 157 +#define WAN_WISHING 158 +#define WAN_STRIKING 159 +#define WAN_SLOW_MONSTER 160 +#define WAN_SPEED_MONSTER 161 +#define WAN_UNDEAD_TURNING 162 +#define WAN_POLYMORPH 163 +#define WAN_CANCELLATION 164 +#define WAN_TELEPORTATION 165 +#define WAN_MAKE_INVISIBLE 166 +#define WAN_DIGGING 167 +#define WAN_MAGIC_MISSILE 168 +#define WAN_FIRE 169 +#define WAN_SLEEP 170 +#define WAN_COLD 171 +#define WAN_DEATH 172 +#define Adornment u.uprops[0].p_flgs +#define RIN_ADORNMENT 176 +#define Teleportation u.uprops[1].p_flgs +#define RIN_TELEPORTATION 177 +#define Regeneration u.uprops[2].p_flgs +#define RIN_REGENERATION 178 +#define Searching u.uprops[3].p_flgs +#define RIN_SEARCHING 179 +#define See_invisible u.uprops[4].p_flgs +#define RIN_SEE_INVISIBLE 180 +#define Stealth u.uprops[5].p_flgs +#define RIN_STEALTH 181 +#define Levitation u.uprops[6].p_flgs +#define RIN_LEVITATION 182 +#define Poison_resistance u.uprops[7].p_flgs +#define RIN_POISON_RESISTANCE 183 +#define Aggravate_monster u.uprops[8].p_flgs +#define RIN_AGGRAVATE_MONSTER 184 +#define Hunger u.uprops[9].p_flgs +#define RIN_HUNGER 185 +#define Fire_resistance u.uprops[10].p_flgs +#define RIN_FIRE_RESISTANCE 186 +#define Cold_resistance u.uprops[11].p_flgs +#define RIN_COLD_RESISTANCE 187 +#define Protection_from_shape_changers u.uprops[12].p_flgs +#define RIN_PROTECTION_FROM_SHAPE_CHANGERS 188 +#define Conflict u.uprops[13].p_flgs +#define RIN_CONFLICT 189 +#define Gain_strength u.uprops[14].p_flgs +#define RIN_GAIN_STRENGTH 190 +#define Increase_damage u.uprops[15].p_flgs +#define RIN_INCREASE_DAMAGE 191 +#define Protection u.uprops[16].p_flgs +#define RIN_PROTECTION 192 +#define Warning u.uprops[17].p_flgs +#define RIN_WARNING 193 +#define Teleport_control u.uprops[18].p_flgs +#define RIN_TELEPORT_CONTROL 194 +#define DIAMOND 197 +#define RUBY 198 +#define SAPPHIRE 199 +#define EMERALD 200 +#define TURQUOISE 201 +#define AQUAMARINE 202 +#define TOURMALINE 203 +#define TOPAZ 204 +#define OPAL 205 +#define GARNET 206 +#define AMETHYST 207 +#define AGATE 208 +#define ONYX 209 +#define JASPER 210 +#define JADE 211 +/* #define WORTHLESS_PIECE_OF_BLUE_GLASS 212 */ +/* #define WORTHLESS_PIECE_OF_RED_GLASS 213 */ +/* #define WORTHLESS_PIECE_OF_YELLOW_GLASS 214 */ +/* #define WORTHLESS_PIECE_OF_GREEN_GLASS 215 */ + +#define CORPSE DEAD_HUMAN +#define LAST_GEM (JADE+1) +#define LAST_RING 19 +#define NROFOBJECTS 215 diff --git a/usr/othersrc/games/hack/hack.options.c b/usr/othersrc/games/hack/hack.options.c new file mode 100644 index 0000000000..ed95de310e --- /dev/null +++ b/usr/othersrc/games/hack/hack.options.c @@ -0,0 +1,203 @@ +/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ +/* hack.options.c - version 1.0.3 */ + +#include "config.h" +#include "hack.h" +extern char *eos(); + +initoptions() +{ + register char *opts; + extern char *getenv(); + + flags.time = flags.nonews = flags.notombstone = flags.end_own = + flags.standout = flags.nonull = FALSE; + flags.no_rest_on_space = TRUE; + flags.invlet_constant = TRUE; + flags.end_top = 5; + flags.end_around = 4; + flags.female = FALSE; /* players are usually male */ + + if(opts = getenv("HACKOPTIONS")) + parseoptions(opts,TRUE); +} + +parseoptions(opts, from_env) +register char *opts; +boolean from_env; +{ + register char *op,*op2; + unsigned num; + boolean negated; + + if(op = index(opts, ',')) { + *op++ = 0; + parseoptions(op, from_env); + } + if(op = index(opts, ' ')) { + op2 = op; + while(*op++) + if(*op != ' ') *op2++ = *op; + } + if(!*opts) return; + negated = FALSE; + while((*opts == '!') || !strncmp(opts, "no", 2)) { + if(*opts == '!') opts++; else opts += 2; + negated = !negated; + } + + if(!strncmp(opts,"standout",8)) { + flags.standout = !negated; + return; + } + + if(!strncmp(opts,"null",3)) { + flags.nonull = negated; + return; + } + + if(!strncmp(opts,"tombstone",4)) { + flags.notombstone = negated; + return; + } + + if(!strncmp(opts,"news",4)) { + flags.nonews = negated; + return; + } + + if(!strncmp(opts,"time",4)) { + flags.time = !negated; + flags.botl = 1; + return; + } + + if(!strncmp(opts,"restonspace",4)) { + flags.no_rest_on_space = negated; + return; + } + + if(!strncmp(opts,"fixinv",4)) { + if(from_env) + flags.invlet_constant = !negated; + else + pline("The fixinvlet option must be in HACKOPTIONS."); + return; + } + + if(!strncmp(opts,"male",4)) { + flags.female = negated; + return; + } + if(!strncmp(opts,"female",6)) { + flags.female = !negated; + return; + } + + /* name:string */ + if(!strncmp(opts,"name",4)) { + extern char plname[PL_NSIZ]; + if(!from_env) { + pline("The playername can be set only from HACKOPTIONS."); + return; + } + op = index(opts,':'); + if(!op) goto bad; + (void) strncpy(plname, op+1, sizeof(plname)-1); + return; + } + + /* endgame:5t[op] 5a[round] o[wn] */ + if(!strncmp(opts,"endgame",3)) { + op = index(opts,':'); + if(!op) goto bad; + op++; + while(*op) { + num = 1; + if(digit(*op)) { + num = atoi(op); + while(digit(*op)) op++; + } else + if(*op == '!') { + negated = !negated; + op++; + } + switch(*op) { + case 't': + flags.end_top = num; + break; + case 'a': + flags.end_around = num; + break; + case 'o': + flags.end_own = !negated; + break; + default: + goto bad; + } + while(letter(*++op)) ; + if(*op == '/') op++; + } + return; + } +bad: + if(!from_env) { + if(!strncmp(opts, "help", 4)) { + pline("%s%s%s", +"To set options use `HACKOPTIONS=\"\"' in your environment, or ", +"give the command 'o' followed by the line `' while playing. ", +"Here is a list of