Compare commits

..

23 commits

Author SHA1 Message Date
Eric S. Raymond
d388877c1b Implement -d option. 2023-03-29 16:40:57 -04:00
Eric S. Raymond
286556f885 Make Z a synonym for NOTHI. 2023-03-23 11:28:53 -04:00
Eric S. Raymond
ffa9332ee3 Avoid noise diffs around logging of seed command. 2023-03-23 11:28:53 -04:00
Eric S. Raymond
bed5fb747b Don't loop back on resume file read failure...
...it's inconvenient for testing.
2023-03-23 11:28:53 -04:00
Eric S. Raymond
0a63b5e2d6 Trim resume file names as required. 2023-03-23 11:28:53 -04:00
Eric S. Raymond
c3bb0dae75 Quiet down database compilation. Observe RNG stability.
At this commit, we can tell that the seeded-RNG nehavopr of this 430
branch is identical to that of master because the axebear log - which
includes randomization of dwarf spawning and the reservoir word -
yields the same results in both versions.
2023-03-23 11:28:53 -04:00
Eric S. Raymond
184e981be3 Fix things so seed doesn't cost clock time. 2023-03-23 11:28:53 -04:00
Eric S. Raymond
b80d1779e6 Fix dropped stitch in last commit. 2023-03-23 11:28:53 -04:00
Eric S. Raymond
220cf2c58b Make it possible to pass options to advent from within regression-test loads. 2023-03-23 11:28:53 -04:00
Jason S. Ninneman
c41dd35268 Ensure the ZZZZ magic word is reproducible.
This happens by making the SEED command also regenerate the magic word.
2023-03-23 11:28:53 -04:00
Eric S. Raymond
d39325f963 Fix bug that led to comments not being ignored. 2023-03-23 11:28:53 -04:00
Eric S. Raymond
85cd6b0bd5 Repeatable seeding is working. 2023-03-23 11:28:53 -04:00
Eric S. Raymond
f286c3a327 Implement fallback handler that looks at the raw command buffer. 2023-03-23 11:28:53 -04:00
Jason S. Ninneman
74dc437a7e Stop command-logging from non-stdin sources. 2023-03-23 11:28:53 -04:00
Eric S. Raymond
2fdd509f32 Once again, take srand()/random() out of the initialization chain.
They have exactly the wrong kind of randomness for this job - not
returning consistent sequences across different platforms or C library
versions, and because pseodorandom not really better than sampling
the clock.
2023-03-23 11:28:53 -04:00
Eric S. Raymond
54afefba94 Re-enable skipping of #-led comments. 2023-03-23 11:28:53 -04:00
Jason S. Ninneman
060601da2f Remove a bad use of tv_nsec. 2023-03-23 11:28:53 -04:00
Jason S. Ninneman
5598b7a178 Add seedable PRNG using an adaptation the original LCG algorithm. 2023-03-23 11:28:53 -04:00
Eric S. Raymond
97b00dfb14 Make output from replays easier to interpret by adding prompts. 2023-03-23 11:28:53 -04:00
Eric S. Raymond
63efff14f5 Echo commands to stdout when replaying...
...makes check loads full transcripts abd more readable.
2023-03-23 11:28:53 -04:00
Eric S. Raymond
a416d78a58 Input source is parametrized all the way down.
This means that, potentially, do_command() could be called on any text file
pointer and the right thing would happen.
2023-03-23 11:28:53 -04:00
Eric S. Raymond
baa508a683 Begin factoring out the command interpreter. 2023-03-23 11:28:53 -04:00
Eric S. Raymond
12f909bcc9 Start advent430 branch for correctness testing.
The purpose of this branch is to create a version of the game from
before the bug fixes, refactoring, and logic changes.  We want this so
we can run it against our 100% coverage test suite and see all changes
in behavior.

This branch is forked from the point where the prompt and the oldstyle
option were added.  At this point there had been only two logic
changes:

1. Do initialization of the LCG with gettimeofday(). Note that
this change will not affectt regression testing, since the
initialization done in this way will nbe overridden in the
logs by seed commands.

2. Refactor the input routines to a normal Unixy organization.
This is required for the -l option to work.

This commit just builds the binary at advent430 where it
won't collide with the production version.
2023-03-23 11:28:53 -04:00
270 changed files with 8467 additions and 167991 deletions

16
.gitignore vendored
View file

@ -1,17 +1,3 @@
# SPDX-FileCopyrightText: (C) Eric S. Raymond
# SPDX-License-Identifier: BSD-2-Clause
advent
*.gcda
*.gcno
*.o
*.html
dungeon.h
dungeon.c
advent.6
*.tar.gz
MANIFEST
*.adv
.*~
cheat
advent.info
coverage/*
adventure.data

View file

@ -1,104 +0,0 @@
# SPDX-FileCopyrightText: (C) Eric S. Raymond
# SPDX-License-Identifier: BSD-2-Clause
stages:
- ci-build
- build
- test
- deploy
default:
image: $CI_REGISTRY_IMAGE:ci
# build and push Docker image to be used in subsequent steps
ci-build:
stage: ci-build
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
script:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile.ci --destination $CI_REGISTRY_IMAGE:ci --cache=true
# build advent itself
binary:debug:
stage: build
script:
- make debug
artifacts:
paths:
- advent
- cheat
- "*.o"
- dungeon.c
- dungeon.h
binary:release:
stage: build
script:
- make advent cheat
artifacts:
paths:
- advent
- cheat
- "*.o"
- dungeon.c
- dungeon.h
manpage:
stage: build
script:
- make advent.6
artifacts:
paths:
- advent.6
html:
stage: build
script:
- make html
artifacts:
paths:
- "*.html"
dist:
stage: build
script:
- export VERS=${CI_COMMIT_REF_NAME}
- make dist -e
artifacts:
paths:
- "*.tar.gz"
# run tests using the binary built before
test:debug:
stage: test
script:
- make coverage
artifacts:
paths:
- coverage
dependencies:
- binary:debug
test:release:
stage: test
script:
- cd tests
- make
- cd ..
dependencies:
- binary:release
pages:
stage: deploy
script:
- mkdir public
- mv coverage public
artifacts:
paths:
- public
only:
- master
dependencies:
- test:debug

View file

@ -1,5 +0,0 @@
#SPDX-FileCopyrightText: (C) Eric S. Raymond
#SPDX-License-Identifier: BSD-2-Clause
extralines="""
<p>There is a <a href="http://esr.gitlab.io/open-adventure/coverage/">code coverage analysis</a> and a <a href="http://esr.gitlab.io/open-adventure/coverage/adventure.yaml.html">symbol coverage analysis</p>
"""

View file

@ -1,4 +1,7 @@
BSD 2-Clause LICENSE
BSD LICENSE
Copyright (c) 1977, 2005 by Will Crowther and Don Woods
Copytright (c) 2017 by Eric S. Raymond
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are

View file

@ -1,12 +0,0 @@
# This image is built by the Gitlab CI pipeline to be used in subsequent
# pipeline steps.
# SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
FROM ubuntu
# tell apt not to ask for any user input
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update
RUN apt-get install --yes --no-install-recommends make gcc libedit-dev libasan6 libubsan1 python3 python3-yaml lcov asciidoctor libxslt1.1 pkg-config docbook-xml xsltproc

View file

@ -1,27 +0,0 @@
= Installing Open Adventure =
// SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
// SPDX-License-Identifier: CC-BY-4.0
Installation now requires Python3 due to a security issue
with the YAML library.
1. Install libedit from http://thrysoee.dk/editline/ (aka: editline)
on your system.
+
On Debian and Ubuntu: `apt-get install libedit-dev`.
+
On Fedora: `dnf install libedit-devel`.
+
You can also use pip to install PyYAML: `pip3 install PyYAML`.
2. Change to the top-level directory of the source code (e.g., `cd open-adventure`).
3. Build with `make`.
4. Optionally run a regression test on the code with `make check`.
5. Run `./advent` to play.
6. If you want to buld the documentation you will need asciidoctor.
7. Running the regression tests requires batchspell

167
Makefile
View file

@ -1,161 +1,46 @@
# Makefile for the open-source release of adventure 2.5
# SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
# To build with save/resume disabled, pass CFLAGS="-DADVENT_NOSAVE"
# To build with auto-save/resume enabled, pass CFLAGS="-DADVENT_AUTOSAVE"
VERS=$(shell sed -n <NEWS.adoc '/^[0-9]/s/:.*//p' | head -1)
.PHONY: debug indent release refresh dist linty html clean
.PHONY: check coverage
CC?=gcc
CCFLAGS+=-std=c99 -Wall -Wextra -D_DEFAULT_SOURCE -DVERSION=\"$(VERS)\" -O2 -D_FORTIFY_SOURCE=2 -fstack-protector-all $(CFLAGS) -g $(EXTRA)
LIBS=$(shell pkg-config --libs libedit)
INC+=$(shell pkg-config --cflags libedit)
# LLVM/Clang on macOS seems to need -ledit flag for linking
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
LIBS += -ledit
endif
OBJS=main.o init.o actions.o score.o misc.o saveresume.o
CHEAT_OBJS=cheat.o init.o actions.o score.o misc.o saveresume.o
SOURCES=$(OBJS:.o=.c) advent.h adventure.yaml Makefile control make_dungeon.py templates/*.tpl
OBJS=main.o init.o actions1.o actions2.o score.o misc.o
SOURCES=$(OBJS:.o=.c) COPYING NEWS README TODO advent.text control
.c.o:
$(CC) $(CCFLAGS) $(INC) $(DBX) -c $<
gcc -g $(DBX) -c $<
advent: $(OBJS) dungeon.o
$(CC) $(CCFLAGS) $(DBX) -o advent $(OBJS) dungeon.o $(LDFLAGS) $(LIBS)
advent430: $(OBJS)
gcc -g $(DBX) -o advent430 $(OBJS)
main.o: advent.h dungeon.h
main.o: misc.h funcs.h
init.o: advent.h dungeon.h
init.o: misc.h main.h share.h funcs.h
actions.o: advent.h dungeon.h
actions1.o: misc.h main.h share.h funcs.h
score.o: advent.h dungeon.h
actions2.o: misc.h main.h share.h funcs.h
misc.o: advent.h dungeon.h
score.o: misc.h main.h share.h
cheat.o: advent.h dungeon.h
saveresume.o: advent.h dungeon.h
dungeon.o: dungeon.c dungeon.h
$(CC) $(CCFLAGS) $(DBX) -c dungeon.c
dungeon.c dungeon.h: make_dungeon.py adventure.yaml advent.h templates/*.tpl
./make_dungeon.py
misc.o: misc.h main.h
clean:
rm -f *.o advent cheat *.html *.gcno *.gcda
rm -f dungeon.c dungeon.h
rm -f README advent.6 MANIFEST *.tar.gz
rm -f *~
rm -f .*~
rm -rf coverage advent.info
cd tests; $(MAKE) --quiet clean
rm -f *.o advent.html advent.6
realclean: clean
rm -f adventure.data advent430
cheat: $(CHEAT_OBJS) dungeon.o
$(CC) $(CCFLAGS) $(DBX) -o cheat $(CHEAT_OBJS) dungeon.o $(LDFLAGS) $(LIBS)
# Requires asciidoc and xsltproc/docbook stylesheets.
.asc.6:
a2x --doctype manpage --format manpage $<
.asc.html:
a2x --doctype manpage --format xhtml -D . $<
rm -f docbook-xsl.css
CSUPPRESSIONS = --suppress=missingIncludeSystem --suppress=invalidscanf
cppcheck:
@-cppcheck -I. --quiet --template gcc -UOBJECT_SET_SEEN --enable=all $(CSUPPRESSIONS) *.[ch]
pylint:
@-pylint --score=n *.py */*.py
check: advent cheat pylint cppcheck spellcheck
cd tests; $(MAKE) --quiet
spellcheck:
@batchspell adventure.yaml advent.adoc
reflow:
@clang-format --style="{IndentWidth: 8, UseTab: ForIndentation}" -i $$(find . -name "*.[ch]")
@black --quiet *.py
# Requires gcov, lcov, libasan6, and libubsan1
# The last two are Ubuntu names, might vary on other distributions.
# After this, run your browser on coverage/open-adventure/index.html
# to see coverage results. Browse coverage/adventure.yaml.html
# to see symbol coverage over the YAML file.
coverage: clean debug
cd tests; $(MAKE) coverage --quiet
# Note: to suppress the footers with timestamps being generated in HTML,
# we use "-a nofooter".
# To debug asciidoc problems, you may need to run "xmllint --nonet --noout --valid"
# on the intermediate XML that throws an error.
.SUFFIXES: .html .adoc .6
.adoc.6:
asciidoctor -D. -a nofooter -b manpage $<
.adoc.html:
asciidoctor -D. -a nofooter -a webfonts! $<
html: advent.html history.html hints.html
# README.adoc exists because that filename is magic on GitLab.
DOCS=COPYING NEWS.adoc README.adoc advent.adoc history.adoc notes.adoc hints.adoc advent.6 INSTALL.adoc
TESTFILES=tests/*.log tests/*.chk tests/README tests/decheck tests/Makefile
# Can't use GNU tar's --transform, needs to build under Alpine Linux.
# This is a requirement for testing dist in GitLab's CI pipeline
advent-$(VERS).tar.gz: $(SOURCES) $(DOCS)
@find $(SOURCES) $(DOCS) $(TESTFILES) -print | sed s:^:advent-$(VERS)/: >MANIFEST
@(ln -s . advent-$(VERS))
(tar -T MANIFEST -czvf advent-$(VERS).tar.gz)
@(rm advent-$(VERS))
release: advent-$(VERS).tar.gz advent.html history.html hints.html notes.html
shipper version=$(VERS) | sh -e -x
refresh: advent.html notes.html history.html
shipper -N -w version=$(VERS) | sh -e -x
advent-$(VERS).tar.gz: $(SOURCES) advent.6
tar --transform='s:^:advent-$(VERS)/:' --show-transformed-names -cvzf advent-$(VERS).tar.gz $(SOURCES) advent.6
dist: advent-$(VERS).tar.gz
linty: CCFLAGS += -W
linty: CCFLAGS += -Wall
linty: CCFLAGS += -Wextra
linty: CCGLAGS += -Wpedantic
linty: CCFLAGS += -Wundef
linty: CCFLAGS += -Wstrict-prototypes
linty: CCFLAGS += -Wmissing-prototypes
linty: CCFLAGS += -Wmissing-declarations
linty: CCFLAGS += -Wshadow
linty: CCFLAGS += -Wnull-dereference
linty: CCFLAGS += -Wjump-misses-init
linty: CCFLAGS += -Wfloat-equal
linty: CCFLAGS += -Wcast-align
linty: CCFLAGS += -Wwrite-strings
linty: CCFLAGS += -Waggregate-return
linty: CCFLAGS += -Wcast-qual
linty: CCFLAGS += -Wswitch-enum
linty: CCFLAGS += -Wwrite-strings
linty: CCFLAGS += -Wunreachable-code
linty: CCFLAGS += -Winit-self
linty: CCFLAGS += -Wpointer-arith
linty: advent cheat
# These seem to be more modern options for enabling coverage testing.
# Documenting them here in case a future version bump disables --coverage.
#debug: CCFLAGS += -ftest-coverage
#debug: CCFLAGS += -fprofile-arcs
debug: CCFLAGS += -O0
debug: CCFLAGS += --coverage
debug: CCFLAGS += -ggdb
debug: CCFLAGS += -U_FORTIFY_SOURCE
debug: CCFLAGS += -fsanitize=address
debug: CCFLAGS += -fsanitize=undefined
debug: linty
release: advent-$(VERS).tar.gz advent.html
shipper version=$(VERS) | sh -e -x
refresh: advent.html
shipper -N -w version=$(VERS) | sh -e -x

7
NEWS Normal file
View file

@ -0,0 +1,7 @@
= OpenAdventure project news =
Repository head::
Forward port of Crowther & Woods's 430-point Adventure 2.5.
Added -l option for logging.
Added command prompt; -o suppresses this.

View file

@ -1,90 +0,0 @@
= Open Adventure project news =
// SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
// SPDX-License-Identifier: CC-BY-4.0
1.20: 2024-09-23::
Make oldstyle correctly suppress line editing.
1.19: 2024-06-27::
Ensore that the KNIVES_VANISH message can't issue twice.
1.18: 2024-02-15::
Bring the manual page fully up to date.
1.17: 2024-01-02::
Saying Z'ZZZ at reservoir no longer causes the waters to part and crash.
1.16: 2023-04-15::
Savefiles now have an identifying magic cookie at the front.
Resume detects if a save has incompatible endianness.
1.15: 2023-04-03::
Commands in magic-word sequence now interrupt it, as in original.
Bug fix for bird not starting caged in endgame.
1.14: 2023-03-09::
Added -a option for BBS door systems.
-o reverts to the old message on some failed magic words.
Typo fixes and documentation polishing.
1.13: 2023-02-28::
Fixed slightly buggy emission of end-of-game messages on a win.
1.12: 2023-02-06::
The bug and todo list has been cleared; project declared finished.
Correctness has been systematically tested against the 1995 code.
Typo fixes and documentation polishing.
1.11: 2022-04-14::
Restore 100% test coverage.
Use TAP reporting for tests.
1.10: 2022-04-06::
Fixed a bug that manifested after two "fly rug" commands - third one fails.
Fix some glitches in processing fee fie foe foo.
Correct some object start states and reading-related glitches in the endgame.
1.9: 2020-08-27::
Update the dungeon maker to avoid a deprecation due to security issues
1.8: 2019-04-19::
Minor typo and capitalization glitches in user-visible text fixed & documented.
Save format has changed.
1.7: 2018-12-03::
Python 3 and OS X port fixes.
1.6: 2018-11-15::
Split commands with verbless objects now pick up a preceding verb correctly.
1.5: 2018-11-11::
Fix for a minor bug in inventory handling.
Handle a bare numeric token on the command line a bit more gracefully.
1.4: 2017-08-07::
Repair packaging error (omitted templates.)
Minor improvements in odd grammar cases.
1.3: 2017-08-01::
Split commands with objectless transitive verbs are handled correctly.
Test suite has 100% code coverage.
1.2: 2017-07-11::
Under oldstyle, new-school single-letter command synonyms are ignored.
Switched from linenoise to editline for new-style line input.
The -s option is no longer required to paste command input; it is removed.
1.1: 2017-06-29::
There is a 'version' command.
Include tests directory in generated tarball.
Support command-line editing with arrow keys and Emacs keystrokes.
Save format has changed.
1.0: 2017-06-05::
Forward port of Crowther & Woods's 430-point Adventure 2.5.
Added -l option for logging.
Game logs are now fully reproducible via the "seed" command.
Added regression-test suite using seed, with coverage checking.
Added command prompt; -o suppresses this. Otherwise no gameplay changes.
Fixed bug that caused reservoir word not to be randomized.
Makefile does parallel builds.

16
README Normal file
View file

@ -0,0 +1,16 @@
= README for Open Adventure =
This code is a forward-port of the Crowther/Woods Adventure 2.5 from
1995, last version in the main line of Colossal Cave Adventure
development written by the original authors. The authors have given
permission and encouragement to this release.
The file history.txt contains a more detailed history of this game
and its ancestors.
This project is called "Open Adventure" because it's not at all clear
to number Adventure past 2.5 without misleading or causing collisions
or both. See the history file for discussion. The original 6-character
name on the PDP-10 has been reverted to in order to avoid a collision
with the BSD games port of the ancestral 196 version.

View file

@ -1,41 +0,0 @@
= README for Open Adventure =
// SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
// SPDX-License-Identifier: CC-BY-4.0
If you are reading this anywhere but at http://www.catb.org/~esr/open-adventure
you can go there for tarball downloads and other resources.
This code is a forward-port of the Crowther/Woods Adventure 2.5 from
1995, last version in the main line of Colossal Cave Adventure
development written by the original authors. The authors have given
permission and encouragement for this release; it obsolesces all
the 350-point versions and previous 2.x (430-point) ports.
The file history.adoc contains a more detailed history of this game
and its ancestors. The file notes.adoc is the maintainer's notes,
describing project goals and recent changes.
This project is called "Open Adventure" because it's not at all clear
how to number Adventure past 2.5 without misleading or causing
collisions or both. See the history file for discussion. The
original 6-character name on the PDP-10 has been reverted to for the
executable in order to avoid a collision with the BSD games port of
the ancestral 1977 version.
Please see INSTALL.adoc for build info.
Extreme care has been taken to not silently change gameplay. By
policy, all user-visible changes from 2.5 that are not bugs or typos
are revertible with the -o (oldstyle) command-line option.
If you encounter a bug (not likely; this code is old and well tested)
please try to make a test log that reproduces it, using the -l option,
and ship it to the maintainers.
If you find this code useful or amusing, please
https://www.patreon.com/esr[support me on Patreon.]
// end

16
TODO Normal file
View file

@ -0,0 +1,16 @@
= Open Adventure TODO =
* Update the command parser to accept a PRNG seed value.
* Add command logging and command log replay. Note that the replay log
needs to begin with the random-number seed.
* Use that feature to make regression tests from walkthroughs.
* Add command-line option to disable all extension features. First
extension features: (1) Command prompt, (2) initial resource-allocation
number display suppressed.
* Translate the FORTRANish mess to actual C.
* Inline the database so the code doesn't need an external file.

1659
actions.c

File diff suppressed because it is too large Load diff

586
actions1.c Normal file
View file

@ -0,0 +1,586 @@
#include <stdlib.h>
#include <stdbool.h>
#include "misc.h"
#include "main.h"
#include "share.h"
#include "funcs.h"
/* This stuff was broken off as part of an effort to get the main program
* to compile without running out of memory. We're called with a number
* that says what label the caller wanted to "goto", and we return a
* similar label number for the caller to "goto".
*/
/* Analyse a verb. Remember what it was, go back for object if second word
* unless verb is "say", which snarfs arbitrary second word. */
int action(FILE *input, long STARTAT) {
switch(STARTAT) {
case 4000: goto L4000;
case 4090: goto L4090;
case 5000: goto L5000;
}
BUG(99);
L4000: VERB=K;
SPK=ACTSPK[VERB];
if(WD2 > 0 && VERB != SAY) return(2800);
if(VERB == SAY)OBJ=WD2;
if(OBJ > 0) goto L4090;
/* Analyse an intransitive verb (ie, no object given yet). */
switch (VERB-1) { case 0: goto L8010; case 1: return(8000); case 2:
return(8000); case 3: goto L8040; case 4: return(2009); case 5: goto L8040;
case 6: goto L8070; case 7: goto L8080; case 8: return(8000); case
9: return(8000); case 10: return(2011); case 11: goto L9120; case 12:
goto L9130; case 13: goto L8140; case 14: goto L9150; case 15:
return(8000); case 16: return(8000); case 17: goto L8180; case 18:
return(8000); case 19: goto L8200; case 20: return(8000); case 21:
goto L9220; case 22: goto L9230; case 23: goto L8240; case 24:
goto L8250; case 25: goto L8260; case 26: goto L8270; case 27:
return(8000); case 28: return(8000); case 29: goto L8300; case 30:
goto L8310; case 31: goto L8320; case 32: goto L8330; case 33:
goto L8340; }
/* TAKE DROP SAY OPEN NOTH LOCK ON OFF WAVE CALM
* WALK KILL POUR EAT DRNK RUB TOSS QUIT FIND INVN
* FEED FILL BLST SCOR FOO BRF READ BREK WAKE SUSP
* RESU FLY LSTN ZZZZ */
BUG(23);
/* Analyse a transitive verb. */
L4090: switch (VERB-1) { case 0: goto L9010; case 1: goto L9020; case 2: goto
L9030; case 3: goto L9040; case 4: return(2009); case 5: goto L9040;
case 6: goto L9070; case 7: goto L9080; case 8: goto L9090; case
9: return(2011); case 10: return(2011); case 11: goto L9120; case 12:
goto L9130; case 13: goto L9140; case 14: goto L9150; case 15:
goto L9160; case 16: goto L9170; case 17: return(2011); case 18:
goto L9190; case 19: goto L9190; case 20: goto L9210; case 21:
goto L9220; case 22: goto L9230; case 23: return(2011); case 24:
return(2011); case 25: return(2011); case 26: goto L9270; case 27:
goto L9280; case 28: goto L9290; case 29: return(2011); case 30:
return(2011); case 31: goto L9320; case 32: return(2011); case 33:
goto L8340; }
/* TAKE DROP SAY OPEN NOTH LOCK ON OFF WAVE CALM
* WALK KILL POUR EAT DRNK RUB TOSS QUIT FIND INVN
* FEED FILL BLST SCOR FOO BRF READ BREK WAKE SUSP
* RESU FLY LSTN ZZZZ */
BUG(24);
/* Analyse an object word. See if the thing is here, whether we've got a verb
* yet, and so on. Object must be here unless verb is "find" or "invent(ory)"
* (and no new verb yet to be analysed). Water and oil are also funny, since
* they are never actually dropped at any location, but might be here inside
* the bottle or urn or as a feature of the location. */
L5000: OBJ=K;
if(!HERE(K)) goto L5100;
L5010: if(WD2 > 0) return(2800);
if(VERB != 0) goto L4090;
SETPRM(1,WD1,WD1X);
RSPEAK(255);
return(2600);
L5100: if(K != GRATE) goto L5110;
if(LOC == 1 || LOC == 4 || LOC == 7)K=DPRSSN;
if(LOC > 9 && LOC < 15)K=ENTRNC;
if(K != GRATE) return(8);
L5110: if(K == DWARF && ATDWRF(LOC) > 0) goto L5010;
if((LIQ(0) == K && HERE(BOTTLE)) || K == LIQLOC(LOC)) goto L5010;
if(OBJ != OIL || !HERE(URN) || PROP[URN] == 0) goto L5120;
OBJ=URN;
goto L5010;
L5120: if(OBJ != PLANT || !AT(PLANT2) || PROP[PLANT2] == 0) goto L5130;
OBJ=PLANT2;
goto L5010;
L5130: if(OBJ != KNIFE || KNFLOC != LOC) goto L5140;
KNFLOC= -1;
SPK=116;
return(2011);
L5140: if(OBJ != ROD || !HERE(ROD2)) goto L5190;
OBJ=ROD2;
goto L5010;
L5190: if((VERB == FIND || VERB == INVENT) && WD2 <= 0) goto L5010;
SETPRM(1,WD1,WD1X);
RSPEAK(256);
return(2012);
/* Routines for performing the various action verbs */
/* Statement numbers in this section are 8000 for intransitive verbs, 9000 for
* transitive, plus ten times the verb number. Many intransitive verbs use the
* transitive code, and some verbs use code for other verbs, as noted below. */
/* Carry, no object given yet. OK if only one object present. */
L8010: if(ATLOC[LOC] == 0 || LINK[ATLOC[LOC]] != 0 || ATDWRF(LOC) > 0) return(8000);
OBJ=ATLOC[LOC];
/* Transitive carry/drop are in separate file. */
L9010: return(carry());
L9020: return(discard(false));
/* SAY. Echo WD2 (or WD1 if no WD2 (SAY WHAT?, etc.).) Magic words override. */
L9030: SETPRM(1,WD2,WD2X);
if(WD2 <= 0)SETPRM(1,WD1,WD1X);
if(WD2 > 0)WD1=WD2;
I=VOCAB(WD1,-1);
if(I == 62 || I == 65 || I == 71 || I == 2025 || I == 2034) goto L9035;
RSPEAK(258);
return(2012);
L9035: WD2=0;
OBJ=0;
return(2630);
/* Lock, unlock, no object given. Assume various things if present. */
L8040: SPK=28;
if(HERE(CLAM))OBJ=CLAM;
if(HERE(OYSTER))OBJ=OYSTER;
if(AT(DOOR))OBJ=DOOR;
if(AT(GRATE))OBJ=GRATE;
if(OBJ != 0 && HERE(CHAIN)) return(8000);
if(HERE(CHAIN))OBJ=CHAIN;
if(OBJ == 0) return(2011);
/* Lock, unlock object. Special stuff for opening clam/oyster and for chain. */
L9040: if(OBJ == CLAM || OBJ == OYSTER) goto L9046;
if(OBJ == DOOR)SPK=111;
if(OBJ == DOOR && PROP[DOOR] == 1)SPK=54;
if(OBJ == CAGE)SPK=32;
if(OBJ == KEYS)SPK=55;
if(OBJ == GRATE || OBJ == CHAIN)SPK=31;
if(SPK != 31 || !HERE(KEYS)) return(2011);
if(OBJ == CHAIN) goto L9048;
if(!CLOSNG) goto L9043;
K=130;
if(!PANIC)CLOCK2=15;
PANIC=true;
return(2010);
L9043: K=34+PROP[GRATE];
PROP[GRATE]=1;
if(VERB == LOCK)PROP[GRATE]=0;
K=K+2*PROP[GRATE];
return(2010);
/* Clam/Oyster. */
L9046: K=0;
if(OBJ == OYSTER)K=1;
SPK=124+K;
if(TOTING(OBJ))SPK=120+K;
if(!TOTING(TRIDNT))SPK=122+K;
if(VERB == LOCK)SPK=61;
if(SPK != 124) return(2011);
DSTROY(CLAM);
DROP(OYSTER,LOC);
DROP(PEARL,105);
return(2011);
/* Chain. */
L9048: if(VERB == LOCK) goto L9049;
SPK=171;
if(PROP[BEAR] == 0)SPK=41;
if(PROP[CHAIN] == 0)SPK=37;
if(SPK != 171) return(2011);
PROP[CHAIN]=0;
FIXED[CHAIN]=0;
if(PROP[BEAR] != 3)PROP[BEAR]=2;
FIXED[BEAR]=2-PROP[BEAR];
return(2011);
L9049: SPK=172;
if(PROP[CHAIN] != 0)SPK=34;
if(LOC != PLAC[CHAIN])SPK=173;
if(SPK != 172) return(2011);
PROP[CHAIN]=2;
if(TOTING(CHAIN))DROP(CHAIN,LOC);
FIXED[CHAIN]= -1;
return(2011);
/* Light. Applicable only to lamp and urn. */
L8070: if(HERE(LAMP) && PROP[LAMP] == 0 && LIMIT >= 0)OBJ=LAMP;
if(HERE(URN) && PROP[URN] == 1)OBJ=OBJ*100+URN;
if(OBJ == 0 || OBJ > 100) return(8000);
L9070: if(OBJ == URN) goto L9073;
if(OBJ != LAMP) return(2011);
SPK=184;
if(LIMIT < 0) return(2011);
PROP[LAMP]=1;
RSPEAK(39);
if(WZDARK) return(2000);
return(2012);
L9073: SPK=38;
if(PROP[URN] == 0) return(2011);
SPK=209;
PROP[URN]=2;
return(2011);
/* Extinguish. Lamp, urn, dragon/volcano (nice try). */
L8080: if(HERE(LAMP) && PROP[LAMP] == 1)OBJ=LAMP;
if(HERE(URN) && PROP[URN] == 2)OBJ=OBJ*100+URN;
if(OBJ == 0 || OBJ > 100) return(8000);
L9080: if(OBJ == URN) goto L9083;
if(OBJ == LAMP) goto L9086;
if(OBJ == DRAGON || OBJ == VOLCAN)SPK=146;
return(2011);
L9083: PROP[URN]=PROP[URN]/2;
SPK=210;
return(2011);
L9086: PROP[LAMP]=0;
RSPEAK(40);
if(DARK(0))RSPEAK(16);
return(2012);
/* Wave. No effect unless waving rod at fissure or at bird. */
L9090: if((!TOTING(OBJ)) && (OBJ != ROD || !TOTING(ROD2)))SPK=29;
if(OBJ != ROD || !TOTING(OBJ) || (!HERE(BIRD) && (CLOSNG || !AT(FISSUR))))
return(2011);
if(HERE(BIRD))SPK=206+MOD(PROP[BIRD],2);
if(SPK == 206 && LOC == PLACE[STEPS] && PROP[JADE] < 0) goto L9094;
if(CLOSED) return(18999);
if(CLOSNG || !AT(FISSUR)) return(2011);
if(HERE(BIRD))RSPEAK(SPK);
PROP[FISSUR]=1-PROP[FISSUR];
PSPEAK(FISSUR,2-PROP[FISSUR]);
return(2012);
L9094: DROP(JADE,LOC);
PROP[JADE]=0;
TALLY=TALLY-1;
SPK=208;
return(2011);
/* Attack also moved into separate module. */
L9120: return(attack(input));
/* Pour. If no object, or object is bottle, assume contents of bottle.
* special tests for pouring water or oil on plant or rusty door. */
L9130: if(OBJ == BOTTLE || OBJ == 0)OBJ=LIQ(0);
if(OBJ == 0) return(8000);
if(!TOTING(OBJ)) return(2011);
SPK=78;
if(OBJ != OIL && OBJ != WATER) return(2011);
if(HERE(URN) && PROP[URN] == 0) goto L9134;
PROP[BOTTLE]=1;
PLACE[OBJ]=0;
SPK=77;
if(!(AT(PLANT) || AT(DOOR))) return(2011);
if(AT(DOOR)) goto L9132;
SPK=112;
if(OBJ != WATER) return(2011);
PSPEAK(PLANT,PROP[PLANT]+3);
PROP[PLANT]=MOD(PROP[PLANT]+1,3);
PROP[PLANT2]=PROP[PLANT];
K=NUL;
return(8);
L9132: PROP[DOOR]=0;
if(OBJ == OIL)PROP[DOOR]=1;
SPK=113+PROP[DOOR];
return(2011);
L9134: OBJ=URN;
goto L9220;
/* Eat. Intransitive: assume food if present, else ask what. Transitive: food
* ok, some things lose appetite, rest are ridiculous. */
L8140: if(!HERE(FOOD)) return(8000);
L8142: DSTROY(FOOD);
SPK=72;
return(2011);
L9140: if(OBJ == FOOD) goto L8142;
if(OBJ == BIRD || OBJ == SNAKE || OBJ == CLAM || OBJ == OYSTER || OBJ ==
DWARF || OBJ == DRAGON || OBJ == TROLL || OBJ == BEAR || OBJ ==
OGRE)SPK=71;
return(2011);
/* Drink. If no object, assume water and look for it here. If water is in
* the bottle, drink that, else must be at a water loc, so drink stream. */
L9150: if(OBJ == 0 && LIQLOC(LOC) != WATER && (LIQ(0) != WATER || !HERE(BOTTLE)))
return(8000);
if(OBJ == BLOOD) goto L9153;
if(OBJ != 0 && OBJ != WATER)SPK=110;
if(SPK == 110 || LIQ(0) != WATER || !HERE(BOTTLE)) return(2011);
PROP[BOTTLE]=1;
PLACE[WATER]=0;
SPK=74;
return(2011);
L9153: DSTROY(BLOOD);
PROP[DRAGON]=2;
OBJSND[BIRD]=OBJSND[BIRD]+3;
SPK=240;
return(2011);
/* Rub. Yields various snide remarks except for lit urn. */
L9160: if(OBJ != LAMP)SPK=76;
if(OBJ != URN || PROP[URN] != 2) return(2011);
DSTROY(URN);
DROP(AMBER,LOC);
PROP[AMBER]=1;
TALLY=TALLY-1;
DROP(CAVITY,LOC);
SPK=216;
return(2011);
/* Throw moved into separate module. */
L9170: return(throw(input));
/* Quit. Intransitive only. Verify intent and exit if that's what he wants. */
L8180: if(YES(input,22,54,54)) score(1);
return(2012);
/* Find. Might be carrying it, or it might be here. Else give caveat. */
L9190: if(AT(OBJ) || (LIQ(0) == OBJ && AT(BOTTLE)) || K == LIQLOC(LOC) || (OBJ ==
DWARF && ATDWRF(LOC) > 0))SPK=94;
if(CLOSED)SPK=138;
if(TOTING(OBJ))SPK=24;
return(2011);
/* Inventory. If object, treat same as find. Else report on current burden. */
L8200: SPK=98;
/* 8201 */ for (I=1; I<=100; I++) {
if(I == BEAR || !TOTING(I)) goto L8201;
if(SPK == 98)RSPEAK(99);
BLKLIN=false;
PSPEAK(I,-1);
BLKLIN=true;
SPK=0;
L8201: /*etc*/ ;
} /* end loop */
if(TOTING(BEAR))SPK=141;
return(2011);
/* Feed/fill are in the other module. */
L9210: return(feed());
L9220: return(fill());
/* Blast. No effect unless you've got dynamite, which is a neat trick! */
L9230: if(PROP[ROD2] < 0 || !CLOSED) return(2011);
BONUS=133;
if(LOC == 115)BONUS=134;
if(HERE(ROD2))BONUS=135;
RSPEAK(BONUS);
score(0);
/* Score. Call scoring routine but tell it to return. */
L8240: score(-1);
SETPRM(1,SCORE,MXSCOR);
SETPRM(3,TURNS,TURNS);
RSPEAK(259);
return(2012);
/* FEE FIE FOE FOO (AND FUM). ADVANCE TO NEXT STATE IF GIVEN IN PROPER ORDER.
* LOOK UP WD1 IN SECTION 3 OF VOCAB TO DETERMINE WHICH WORD WE'VE GOT. LAST
* WORD ZIPS THE EGGS BACK TO THE GIANT ROOM (UNLESS ALREADY THERE). */
L8250: K=VOCAB(WD1,3);
SPK=42;
if(FOOBAR == 1-K) goto L8252;
if(FOOBAR != 0)SPK=151;
return(2011);
L8252: FOOBAR=K;
if(K != 4) return(2009);
FOOBAR=0;
if(PLACE[EGGS] == PLAC[EGGS] || (TOTING(EGGS) && LOC == PLAC[EGGS]))
return(2011);
/* Bring back troll if we steal the eggs back from him before crossing. */
if(PLACE[EGGS] == 0 && PLACE[TROLL] == 0 && PROP[TROLL] ==
0)PROP[TROLL]=1;
K=2;
if(HERE(EGGS))K=1;
if(LOC == PLAC[EGGS])K=0;
MOVE(EGGS,PLAC[EGGS]);
PSPEAK(EGGS,K);
return(2012);
/* Brief. Intransitive only. Suppress long descriptions after first time. */
L8260: SPK=156;
ABBNUM=10000;
DETAIL=3;
return(2011);
/* Read. Print stuff based on objtxt. Oyster (?) is special case. */
L8270: for (I=1; I<=100; I++) {
if(HERE(I) && OBJTXT[I] != 0 && PROP[I] >= 0)OBJ=OBJ*100+I;
} /* end loop */
if(OBJ > 100 || OBJ == 0 || DARK(0)) return(8000);
L9270: if(DARK(0)) goto L5190;
if(OBJTXT[OBJ] == 0 || PROP[OBJ] < 0) return(2011);
if(OBJ == OYSTER && !CLSHNT) goto L9275;
PSPEAK(OBJ,OBJTXT[OBJ]+PROP[OBJ]);
return(2012);
L9275: CLSHNT=YES(input,192,193,54);
return(2012);
/* Break. Only works for mirror in repository and, of course, the vase. */
L9280: if(OBJ == MIRROR)SPK=148;
if(OBJ == VASE && PROP[VASE] == 0) goto L9282;
if(OBJ != MIRROR || !CLOSED) return(2011);
SPK=197;
return(18999);
L9282: SPK=198;
if(TOTING(VASE))DROP(VASE,LOC);
PROP[VASE]=2;
FIXED[VASE]= -1;
return(2011);
/* Wake. Only use is to disturb the dwarves. */
L9290: if(OBJ != DWARF || !CLOSED) return(2011);
SPK=199;
return(18999);
/* Suspend. Offer to save things in a file, but charging some points (so
* can't win by using saved games to retry battles or to start over after
* learning zzword). */
L8300: SPK=201;
RSPEAK(260);
if(!YES(input,200,54,54)) return(2012);
SAVED=SAVED+5;
KK= -1;
/* This next part is shared with the "resume" code. The two cases are
* distinguished by the value of kk (-1 for suspend, +1 for resume). */
L8305: DATIME(I,K);
K=I+650*K;
SAVWRD(KK,K);
K=VRSION;
SAVWRD(0,K);
if(K != VRSION) goto L8312;
/* Herewith are all the variables whose values can change during a game,
* omitting a few (such as I, J, ATTACK) whose values between turns are
* irrelevant and some whose values when a game is
* suspended or resumed are guaranteed to match. If unsure whether a value
* needs to be saved, include it. Overkill can't hurt. Pad the last savwds
* with junk variables to bring it up to 7 values. */
SAVWDS(ABBNUM,BLKLIN,BONUS,CLOCK1,CLOCK2,CLOSED,CLOSNG);
SAVWDS(DETAIL,DFLAG,DKILL,DTOTAL,FOOBAR,HOLDNG,IWEST);
SAVWDS(KNFLOC,LIMIT,LL,LMWARN,LOC,NEWLOC,NUMDIE);
SAVWDS(OBJ,OLDLC2,OLDLOC,OLDOBJ,PANIC,SAVED,SETUP);
SAVWDS(SPK,TALLY,THRESH,TRNDEX,TRNLUZ,TURNS,OBJTXT[OYSTER]);
SAVWDS(VERB,WD1,WD1X,WD2,WZDARK,ZZWORD,OBJSND[BIRD]);
SAVWDS(OBJTXT[SIGN],CLSHNT,NOVICE,K,K,K,K);
SAVARR(ABB,LOCSIZ);
SAVARR(ATLOC,LOCSIZ);
SAVARR(DLOC,6);
SAVARR(DSEEN,6);
SAVARR(FIXED,100);
SAVARR(HINTED,HNTSIZ);
SAVARR(HINTLC,HNTSIZ);
SAVARR(LINK,200);
SAVARR(ODLOC,6);
SAVARR(PLACE,100);
SAVARR(PROP,100);
SAVWRD(KK,K);
if(K != 0) goto L8318;
K=NUL;
ZZWORD=RNDVOC(3,ZZWORD-MESH*2)+MESH*2;
if(KK > 0) return(8);
RSPEAK(266);
exit(0);
/* Resume. Read a suspended game back from a file. */
L8310: KK=1;
if(LOC == 1 && ABB[1] == 1) goto L8305;
RSPEAK(268);
if(!YES(input,200,54,54)) return(2012);
goto L8305;
L8312: SETPRM(1,K/10,MOD(K,10));
SETPRM(3,VRSION/10,MOD(VRSION,10));
RSPEAK(269);
return(2000);
L8318: RSPEAK(270);
exit(0);
/* Fly. Snide remarks unless hovering rug is here. */
L8320: if(PROP[RUG] != 2)SPK=224;
if(!HERE(RUG))SPK=225;
if(SPK/2 == 112) return(2011);
OBJ=RUG;
L9320: if(OBJ != RUG) return(2011);
SPK=223;
if(PROP[RUG] != 2) return(2011);
OLDLC2=OLDLOC;
OLDLOC=LOC;
NEWLOC=PLACE[RUG]+FIXED[RUG]-LOC;
SPK=226;
if(PROP[SAPPH] >= 0)SPK=227;
RSPEAK(SPK);
return(2);
/* Listen. Intransitive only. Print stuff based on objsnd/locsnd. */
L8330: SPK=228;
K=LOCSND[LOC];
if(K == 0) goto L8332;
RSPEAK(IABS(K));
if(K < 0) return(2012);
SPK=0;
L8332: SETPRM(1,ZZWORD-MESH*2,0);
/* 8335 */ for (I=1; I<=100; I++) {
if(!HERE(I) || OBJSND[I] == 0 || PROP[I] < 0) goto L8335;
PSPEAK(I,OBJSND[I]+PROP[I]);
SPK=0;
if(I == BIRD && OBJSND[I]+PROP[I] == 8)DSTROY(BIRD);
L8335: /*etc*/ ;
} /* end loop */
return(2011);
/* Z'ZZZ (word gets recomputed at startup; different each game). */
L8340: if(!AT(RESER) && LOC != FIXED[RESER]-1) return(2011);
PSPEAK(RESER,PROP[RESER]+1);
PROP[RESER]=1-PROP[RESER];
if(AT(RESER)) return(2012);
OLDLC2=LOC;
NEWLOC=0;
RSPEAK(241);
return(2);
}

349
actions2.c Normal file
View file

@ -0,0 +1,349 @@
#include "misc.h"
#include "main.h"
#include "share.h"
#include "funcs.h"
/* Carry an object. Special cases for bird and cage (if bird in cage, can't
* take one without the other). Liquids also special, since they depend on
* status of bottle. Also various side effects, etc. */
int carry(void) {
if(TOTING(OBJ)) return(2011);
SPK=25;
if(OBJ == PLANT && PROP[PLANT] <= 0)SPK=115;
if(OBJ == BEAR && PROP[BEAR] == 1)SPK=169;
if(OBJ == CHAIN && PROP[BEAR] != 0)SPK=170;
if(OBJ == URN)SPK=215;
if(OBJ == CAVITY)SPK=217;
if(OBJ == BLOOD)SPK=239;
if(OBJ == RUG && PROP[RUG] == 2)SPK=222;
if(OBJ == SIGN)SPK=196;
if(OBJ != MESSAG) goto L9011;
SPK=190;
DSTROY(MESSAG);
L9011: if(FIXED[OBJ] != 0) return(2011);
if(OBJ != WATER && OBJ != OIL) goto L9017;
K=OBJ;
OBJ=BOTTLE;
if(HERE(BOTTLE) && LIQ(0) == K) goto L9017;
if(TOTING(BOTTLE) && PROP[BOTTLE] == 1) return(fill());
if(PROP[BOTTLE] != 1)SPK=105;
if(!TOTING(BOTTLE))SPK=104;
return(2011);
L9017: SPK=92;
if(HOLDNG >= 7) return(2011);
if(OBJ != BIRD || PROP[BIRD] == 1 || -1-PROP[BIRD] == 1) goto L9014;
if(PROP[BIRD] == 2) goto L9015;
if(!TOTING(CAGE))SPK=27;
if(TOTING(ROD))SPK=26;
if(SPK/2 == 13) return(2011);
PROP[BIRD]=1;
L9014: if((OBJ == BIRD || OBJ == CAGE) && (PROP[BIRD] == 1 || -1-PROP[BIRD] ==
1))CARRY(BIRD+CAGE-OBJ,LOC);
CARRY(OBJ,LOC);
K=LIQ(0);
if(OBJ == BOTTLE && K != 0)PLACE[K]= -1;
if(!GSTONE(OBJ) || PROP[OBJ] == 0) return(2009);
PROP[OBJ]=0;
PROP[CAVITY]=1;
return(2009);
L9015: SPK=238;
DSTROY(BIRD);
return(2011);
}
/* Discard object. "Throw" also comes here for most objects. Special cases for
* bird (might attack snake or dragon) and cage (might contain bird) and vase.
* Drop coins at vending machine for extra batteries. */
int discard(bool just_do_it) {
if(just_do_it) goto L9021;
if(TOTING(ROD2) && OBJ == ROD && !TOTING(ROD))OBJ=ROD2;
if(!TOTING(OBJ)) return(2011);
if(OBJ != BIRD || !HERE(SNAKE)) goto L9023;
RSPEAK(30);
if(CLOSED) return(19000);
DSTROY(SNAKE);
/* SET PROP FOR USE BY TRAVEL OPTIONS */
PROP[SNAKE]=1;
L9021: K=LIQ(0);
if(K == OBJ)OBJ=BOTTLE;
if(OBJ == BOTTLE && K != 0)PLACE[K]=0;
if(OBJ == CAGE && PROP[BIRD] == 1)DROP(BIRD,LOC);
DROP(OBJ,LOC);
if(OBJ != BIRD) return(2012);
PROP[BIRD]=0;
if(FOREST(LOC))PROP[BIRD]=2;
return(2012);
L9023: if(!(GSTONE(OBJ) && AT(CAVITY) && PROP[CAVITY] != 0)) goto L9024;
RSPEAK(218);
PROP[OBJ]=1;
PROP[CAVITY]=0;
if(!HERE(RUG) || !((OBJ == EMRALD && PROP[RUG] != 2) || (OBJ == RUBY &&
PROP[RUG] == 2))) goto L9021;
SPK=219;
if(TOTING(RUG))SPK=220;
if(OBJ == RUBY)SPK=221;
RSPEAK(SPK);
if(SPK == 220) goto L9021;
K=2-PROP[RUG];
PROP[RUG]=K;
if(K == 2)K=PLAC[SAPPH];
MOVE(RUG+100,K);
goto L9021;
L9024: if(OBJ != COINS || !HERE(VEND)) goto L9025;
DSTROY(COINS);
DROP(BATTER,LOC);
PSPEAK(BATTER,0);
return(2012);
L9025: if(OBJ != BIRD || !AT(DRAGON) || PROP[DRAGON] != 0) goto L9026;
RSPEAK(154);
DSTROY(BIRD);
PROP[BIRD]=0;
return(2012);
L9026: if(OBJ != BEAR || !AT(TROLL)) goto L9027;
RSPEAK(163);
MOVE(TROLL,0);
MOVE(TROLL+100,0);
MOVE(TROLL2,PLAC[TROLL]);
MOVE(TROLL2+100,FIXD[TROLL]);
JUGGLE(CHASM);
PROP[TROLL]=2;
goto L9021;
L9027: if(OBJ == VASE && LOC != PLAC[PILLOW]) goto L9028;
RSPEAK(54);
goto L9021;
L9028: PROP[VASE]=2;
if(AT(PILLOW))PROP[VASE]=0;
PSPEAK(VASE,PROP[VASE]+1);
if(PROP[VASE] != 0)FIXED[VASE]= -1;
goto L9021;
}
/* Attack. Assume target if unambiguous. "Throw" also links here. Attackable
* objects fall into two categories: enemies (snake, dwarf, etc.) and others
* (bird, clam, machine). Ambiguous if 2 enemies, or no enemies but 2 others. */
int attack(FILE *input) {
I=ATDWRF(LOC);
if(OBJ != 0) goto L9124;
if(I > 0)OBJ=DWARF;
if(HERE(SNAKE))OBJ=OBJ*100+SNAKE;
if(AT(DRAGON) && PROP[DRAGON] == 0)OBJ=OBJ*100+DRAGON;
if(AT(TROLL))OBJ=OBJ*100+TROLL;
if(AT(OGRE))OBJ=OBJ*100+OGRE;
if(HERE(BEAR) && PROP[BEAR] == 0)OBJ=OBJ*100+BEAR;
if(OBJ > 100) return(8000);
if(OBJ != 0) goto L9124;
/* CAN'T ATTACK BIRD OR MACHINE BY THROWING AXE. */
if(HERE(BIRD) && VERB != THROW)OBJ=BIRD;
if(HERE(VEND) && VERB != THROW)OBJ=OBJ*100+VEND;
/* CLAM AND OYSTER BOTH TREATED AS CLAM FOR INTRANSITIVE CASE; NO HARM DONE. */
if(HERE(CLAM) || HERE(OYSTER))OBJ=100*OBJ+CLAM;
if(OBJ > 100) return(8000);
L9124: if(OBJ != BIRD) goto L9125;
SPK=137;
if(CLOSED) return(2011);
DSTROY(BIRD);
PROP[BIRD]=0;
SPK=45;
L9125: if(OBJ != VEND) goto L9126;
PSPEAK(VEND,PROP[VEND]+2);
PROP[VEND]=3-PROP[VEND];
return(2012);
L9126: if(OBJ == 0)SPK=44;
if(OBJ == CLAM || OBJ == OYSTER)SPK=150;
if(OBJ == SNAKE)SPK=46;
if(OBJ == DWARF)SPK=49;
if(OBJ == DWARF && CLOSED) return(19000);
if(OBJ == DRAGON)SPK=167;
if(OBJ == TROLL)SPK=157;
if(OBJ == OGRE)SPK=203;
if(OBJ == OGRE && I > 0) goto L9128;
if(OBJ == BEAR)SPK=165+(PROP[BEAR]+1)/2;
if(OBJ != DRAGON || PROP[DRAGON] != 0) return(2011);
/* Fun stuff for dragon. If he insists on attacking it, win! Set PROP to dead,
* move dragon to central loc (still fixed), move rug there (not fixed), and
* move him there, too. Then do a null motion to get new description. */
RSPEAK(49);
VERB=0;
OBJ=0;
GETIN(input,WD1,WD1X,WD2,WD2X);
if(WD1 != MAKEWD(25) && WD1 != MAKEWD(250519)) return(2607);
PSPEAK(DRAGON,3);
PROP[DRAGON]=1;
PROP[RUG]=0;
K=(PLAC[DRAGON]+FIXD[DRAGON])/2;
MOVE(DRAGON+100,-1);
MOVE(RUG+100,0);
MOVE(DRAGON,K);
MOVE(RUG,K);
DROP(BLOOD,K);
for (OBJ=1; OBJ<=100; OBJ++) {
if(PLACE[OBJ] == PLAC[DRAGON] || PLACE[OBJ] == FIXD[DRAGON])MOVE(OBJ,K);
/*etc*/ ;
} /* end loop */
LOC=K;
K=NUL;
return(8);
L9128: RSPEAK(SPK);
RSPEAK(6);
DSTROY(OGRE);
K=0;
/* 9129 */ for (I=1; I<=5; I++) {
if(DLOC[I] != LOC) goto L9129;
K=K+1;
DLOC[I]=61;
DSEEN[I]=false;
L9129: /*etc*/ ;
} /* end loop */
SPK=SPK+1+1/K;
return(2011);
}
/* Throw. Same as discard unless axe. Then same as attack except ignore bird,
* and if dwarf is present then one might be killed. (Only way to do so!)
* Axe also special for dragon, bear, and troll. Treasures special for troll. */
int throw(FILE *cmdin) {
if(TOTING(ROD2) && OBJ == ROD && !TOTING(ROD))OBJ=ROD2;
if(!TOTING(OBJ)) return(2011);
if(OBJ >= 50 && OBJ <= MAXTRS && AT(TROLL)) goto L9178;
if(OBJ == FOOD && HERE(BEAR)) goto L9177;
if(OBJ != AXE) return(discard(false));
I=ATDWRF(LOC);
if(I > 0) goto L9172;
SPK=152;
if(AT(DRAGON) && PROP[DRAGON] == 0) goto L9175;
SPK=158;
if(AT(TROLL)) goto L9175;
SPK=203;
if(AT(OGRE)) goto L9175;
if(HERE(BEAR) && PROP[BEAR] == 0) goto L9176;
OBJ=0;
return(attack(cmdin));
L9172: SPK=48;
if(randrange(7) < DFLAG) goto L9175;
DSEEN[I]=false;
DLOC[I]=0;
SPK=47;
DKILL=DKILL+1;
if(DKILL == 1)SPK=149;
L9175: RSPEAK(SPK);
DROP(AXE,LOC);
K=NUL;
return(8);
/* This'll teach him to throw the axe at the bear! */
L9176: SPK=164;
DROP(AXE,LOC);
FIXED[AXE]= -1;
PROP[AXE]=1;
JUGGLE(BEAR);
return(2011);
/* But throwing food is another story. */
L9177: OBJ=BEAR;
return(feed());
L9178: SPK=159;
/* Snarf a treasure for the troll. */
DROP(OBJ,0);
MOVE(TROLL,0);
MOVE(TROLL+100,0);
DROP(TROLL2,PLAC[TROLL]);
DROP(TROLL2+100,FIXD[TROLL]);
JUGGLE(CHASM);
return(2011);
}
/* Feed. If bird, no seed. Snake, dragon, troll: quip. If dwarf, make him
* mad. Bear, special. */
int feed() {
if(OBJ != BIRD) goto L9212;
SPK=100;
return(2011);
L9212: if(OBJ != SNAKE && OBJ != DRAGON && OBJ != TROLL) goto L9213;
SPK=102;
if(OBJ == DRAGON && PROP[DRAGON] != 0)SPK=110;
if(OBJ == TROLL)SPK=182;
if(OBJ != SNAKE || CLOSED || !HERE(BIRD)) return(2011);
SPK=101;
DSTROY(BIRD);
PROP[BIRD]=0;
return(2011);
L9213: if(OBJ != DWARF) goto L9214;
if(!HERE(FOOD)) return(2011);
SPK=103;
DFLAG=DFLAG+2;
return(2011);
L9214: if(OBJ != BEAR) goto L9215;
if(PROP[BEAR] == 0)SPK=102;
if(PROP[BEAR] == 3)SPK=110;
if(!HERE(FOOD)) return(2011);
DSTROY(FOOD);
PROP[BEAR]=1;
FIXED[AXE]=0;
PROP[AXE]=0;
SPK=168;
return(2011);
L9215: if(OBJ != OGRE) goto L9216;
if(HERE(FOOD))SPK=202;
return(2011);
L9216: SPK=14;
return(2011);
}
/* Fill. Bottle or urn must be empty, and liquid available. (Vase is nasty.) */
int fill() {
if(OBJ == VASE) goto L9222;
if(OBJ == URN) goto L9224;
if(OBJ != 0 && OBJ != BOTTLE) return(2011);
if(OBJ == 0 && !HERE(BOTTLE)) return(8000);
SPK=107;
if(LIQLOC(LOC) == 0)SPK=106;
if(HERE(URN) && PROP[URN] != 0)SPK=214;
if(LIQ(0) != 0)SPK=105;
if(SPK != 107) return(2011);
PROP[BOTTLE]=MOD(COND[LOC],4)/2*2;
K=LIQ(0);
if(TOTING(BOTTLE))PLACE[K]= -1;
if(K == OIL)SPK=108;
return(2011);
L9222: SPK=29;
if(LIQLOC(LOC) == 0)SPK=144;
if(LIQLOC(LOC) == 0 || !TOTING(VASE)) return(2011);
RSPEAK(145);
PROP[VASE]=2;
FIXED[VASE]= -1;
return(discard(true));
L9224: SPK=213;
if(PROP[URN] != 0) return(2011);
SPK=144;
K=LIQ(0);
if(K == 0 || !HERE(BOTTLE)) return(2011);
PLACE[K]=0;
PROP[BOTTLE]=1;
if(K == OIL)PROP[URN]=1;
SPK=211+PROP[URN];
return(2011);
}

View file

@ -1,93 +0,0 @@
= advent(6) =
:doctype: manpage
// SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
// SPDX-License-Identifier: CC-BY-4.0
// batchspell: add advent logfile savefile roleplaying Gillogly PDP Ctrl-D
// batchspell: add EOF autosave endianness wumpus zork nethack
== NAME ==
advent - Colossal Cave Adventure
== SYNOPSIS ==
*advent* [-l logfile] [-o] [-r savefile] [-a savefile] [script...]
== DESCRIPTION ==
The original Colossal Cave Adventure from 1976-1977 was the origin of all
later text adventures, dungeon-crawl (computer) games, and computer-hosted
roleplaying games.
This is the last version released by Crowther & Woods, its original
authors, in 1995. It has been known as "adventure 2.5" and "430-point
adventure". To learn more about the changes since the 350-point
original, type 'news' at the command prompt.
There is an 'adventure' in the BSD games package that is a C port by
Jim Gillogly of the 1977 version. To avoid a name collision, this game
builds as 'advent', reflecting the fact that the PDP-10 on which the
game originally ran limited filenames to 6 characters.
This version is released as open source with the permission and
encouragement of the original authors.
Unlike the original, this version has a command prompt and supports
use of your arrow keys to edit your command line in place. Basic
Emacs keystrokes are supported, and your up/down arrows access a
command history.
Some minor bugs and message typos have been fixed. Otherwise, the
"version" command is almost the only way to tell you're not running
Don's 1977 version until you get to the new cave sections added for
2.5.
To exit the game, type Ctrl-D (EOF).
There have been no gameplay changes.
== OPTIONS ==
-l:: Log commands to specified file.
-r:: Restore game from specified save file
-a:: Load from specified save file and autosave to it on exit or signal.
-o:: Old-style. Reverts some minor cosmetic fixes in game
messages. Restores original interface, no prompt or line editing.
Also ignores new-school one-letter commands l, x, g, z, i. Also
case-smashes and truncates unrecognized text when echoed.
Normally, game input is taken from standard input. If script file
arguments are given, input is taken from them instead. A script file
argument of '-' is taken as a directive to read from standard input.
== BUGS ==
The binary save file format is fragile, dependent on your machine's
endianness, and unlikely to survive through version bumps. There are
version and endianness checks when attempting to restore from a save.
The input parser was the first attempt *ever* at natural-language
parsing in a game and has some known deficiencies. While later text
adventures distinguished between transitive and intransitive verbs,
Adventure's grammar distinguishes only between motion and action
verbs. Motions are always immediate in their behavior, so both ACTION
MOTION and MOTION ACTION (and even MOTION NOUN and MOTION MOTION) are
invariably equivalent to MOTION (thus GO NORTH means NORTH and JUMP
DOWN means JUMP). Whereas, with actions and nouns, the parser collects
words until it's seen one of each, and then dispatches; if it reaches
the end of the command without seeing a noun, it'll dispatch an
"intransitive" action. This makes ACTION1 ACTION2 equivalent to
ACTION2 (thus TAKE INVENTORY means INVENTORY), and NOUN ACTION
equivalent to ACTION NOUN.
Thus you get anomalies like "eat building" interpreted as a command
to move to the building. These should not be reported as bugs; instead,
consider them historical curiosities.
== REPORTING BUGS ==
Report bugs to Eric S. Raymond <esr@thyrsus.com>. The project page is
at http://catb.org/~esr/open-adventure
== SEE ALSO ==
wumpus(6), adventure(6), zork(6), rogue(6), nethack(6).

View file

@ -1,10 +0,0 @@
# SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
[Desktop Entry]
Type=Application
Name=Open Adventure
Comment=Colossal Cave Adventure, the 1995 430-point version
Icon=advent
Exec=advent
Terminal=true
Categories=Game;AdventureGame;ConsoleOnly

359
advent.h
View file

@ -1,359 +0,0 @@
/*
* Dungeon types and macros.
*
* SPDX-FileCopyrightText: (C) 1977, 2005 by Will Crowther and Don Woods
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "dungeon.h"
/* LCG PRNG parameters tested against
* Knuth vol. 2. by the original authors */
#define LCG_A 1093L
#define LCG_C 221587L
#define LCG_M 1048576L
#define LINESIZE 1024
#define TOKLEN 5 // # outputting characters in a token */
#define PIRATE NDWARVES // must be NDWARVES-1 when zero-origin
#define DALTLC LOC_NUGGET // alternate dwarf location
#define INVLIMIT 7 // inventory limit (# of objects)
#define INTRANSITIVE -1 // illegal object number
#define GAMELIMIT 330 // base limit of turns
#define NOVICELIMIT 1000 // limit of turns for novice
#define WARNTIME 30 // late game starts at game.limit-this
#define FLASHTIME 50 // turns from first warning till blinding flash
#define PANICTIME 15 // time left after closing
#define BATTERYLIFE 2500 // turn limit increment from batteries
#define WORD_NOT_FOUND \
-1 // "Word not found" flag value for the vocab hash functions.
#define WORD_EMPTY 0 // "Word empty" flag value for the vocab hash functions
#define PIT_KILL_PROB 35 // Percentage probability of dying from fall in pit.
#define CARRIED -1 // Player is toting it
#define READ_MODE "rb" // b is not needed for POSIX but harmless
#define WRITE_MODE "wb" // b is not needed for POSIX but harmless
/* Special object-state values - integers > 0 are object-specific */
#define STATE_NOTFOUND -1 // 'Not found" state of treasures
#define STATE_FOUND 0 // After discovered, before messed with
#define STATE_IN_CAVITY 1 // State value common to all gemstones
/* Special fixed object-state values - integers > 0 are location */
#define IS_FIXED -1
#define IS_FREE 0
/* (ESR) It is fitting that translation of the original ADVENT should
* have left us a maze of twisty little conditionals that resists all
* understanding. Setting and use of what is now the per-object state
* member (which used to be an array of its own) is our mystery. This
* state tangles together information about whether the object is a
* treasure, whether the player has seen it yet, and its activation
* state.
*
* Things we think we know:
*
* STATE_NOTFOUND is only set on treasures. Non-treasures start the
* game in STATE_FOUND.
*
* PROP_STASHIFY is supposed to map a state property value to a
* negative range, where the object cannot be picked up but the value
* can be recovered later. Various objects get this property when
* the cave starts to close. Only seems to be significant for the bird
* and readable objects, notably the clam/oyster - but the code around
* those tests is difficult to read.
*
* All tests of the prop member are done with either these macros or ==.
*/
#define OBJECT_IS_NOTFOUND(obj) (game.objects[obj].prop == STATE_NOTFOUND)
#define OBJECT_IS_FOUND(obj) (game.objects[obj].prop == STATE_FOUND)
#define OBJECT_SET_FOUND(obj) (game.objects[obj].prop = STATE_FOUND)
#define OBJECT_SET_NOT_FOUND(obj) (game.objects[obj].prop = STATE_NOTFOUND)
#define OBJECT_IS_NOTFOUND2(g, o) (g.objects[o].prop == STATE_NOTFOUND)
#define PROP_IS_INVALID(val) (val < -MAX_STATE - 1 || val > MAX_STATE)
#define PROP_STASHIFY(n) (-1 - (n))
#define OBJECT_STASHIFY(obj, pval) game.objects[obj].prop = PROP_STASHIFY(pval)
#define OBJECT_IS_STASHED(obj) (game.objects[obj].prop < STATE_NOTFOUND)
#define OBJECT_STATE_EQUALS(obj, pval) \
((game.objects[obj].prop == pval) || \
(game.objects[obj].prop == PROP_STASHIFY(pval)))
#define PROMPT "> "
/*
* DESTROY(N) = Get rid of an item by putting it in LOC_NOWHERE
* MOD(N,M) = Arithmetic modulus
* TOTING(OBJ) = true if the OBJ is being carried
* AT(OBJ) = true if on either side of two-placed object
* HERE(OBJ) = true if the OBJ is at "LOC" (or is being carried)
* CNDBIT(L,N) = true if COND(L) has bit n set (bit 0 is units bit)
* LIQUID() = object number of liquid in bottle
* LIQLOC(LOC) = object number of liquid (if any) at LOC
* FORCED(LOC) = true if LOC moves without asking for input (COND=2)
* IS_DARK_HERE() = true if location "LOC" is dark
* PCT(N) = true N% of the time (N integer from 0 to 100)
* GSTONE(OBJ) = true if OBJ is a gemstone
* FOREST(LOC) = true if LOC is part of the forest
* OUTSIDE(LOC) = true if location not in the cave
* INSIDE(LOC) = true if location is in the cave or the building at the
* beginning of the game
* INDEEP(LOC) = true if location is in the Hall of Mists or deeper
* BUG(X) = report bug and exit
*/
#define DESTROY(N) move(N, LOC_NOWHERE)
#define MOD(N, M) ((N) % (M))
#define TOTING(OBJ) (game.objects[OBJ].place == CARRIED)
#define AT(OBJ) \
(game.objects[OBJ].place == game.loc || \
game.objects[OBJ].fixed == game.loc)
#define HERE(OBJ) (AT(OBJ) || TOTING(OBJ))
#define CNDBIT(L, N) (tstbit(conditions[L], N))
#define LIQUID() \
(game.objects[BOTTLE].prop == WATER_BOTTLE ? WATER \
: game.objects[BOTTLE].prop == OIL_BOTTLE ? OIL \
: NO_OBJECT)
#define LIQLOC(LOC) \
(CNDBIT((LOC), COND_FLUID) ? CNDBIT((LOC), COND_OILY) ? OIL : WATER \
: NO_OBJECT)
#define FORCED(LOC) CNDBIT(LOC, COND_FORCED)
#define IS_DARK_HERE() \
(!CNDBIT(game.loc, COND_LIT) && \
(game.objects[LAMP].prop == LAMP_DARK || !HERE(LAMP)))
#define PCT(N) (randrange(100) < (N))
#define GSTONE(OBJ) \
((OBJ) == EMERALD || (OBJ) == RUBY || (OBJ) == AMBER || (OBJ) == SAPPH)
#define FOREST(LOC) CNDBIT(LOC, COND_FOREST)
#define OUTSIDE(LOC) (CNDBIT(LOC, COND_ABOVE) || FOREST(LOC))
#define INSIDE(LOC) (!OUTSIDE(LOC) || LOC == LOC_BUILDING)
#define INDEEP(LOC) CNDBIT((LOC), COND_DEEP)
#define BUG(x) bug(x, #x)
enum bugtype {
SPECIAL_TRAVEL_500_GT_L_GT_300_EXCEEDS_GOTO_LIST,
VOCABULARY_TYPE_N_OVER_1000_NOT_BETWEEN_0_AND_3,
INTRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST,
TRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST,
CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION,
LOCATION_HAS_NO_TRAVEL_ENTRIES,
HINT_NUMBER_EXCEEDS_GOTO_LIST,
SPEECHPART_NOT_TRANSITIVE_OR_INTRANSITIVE_OR_UNKNOWN,
ACTION_RETURNED_PHASE_CODE_BEYOND_END_OF_SWITCH,
};
enum speaktype { touch, look, hear, study, change };
enum termination { endgame, quitgame, scoregame };
enum speechpart { unknown, intransitive, transitive };
typedef enum { NO_WORD_TYPE, MOTION, OBJECT, ACTION, NUMERIC } word_type_t;
typedef enum scorebonus { none, splatter, defeat, victory } score_t;
/* Phase codes for action returns.
* These were at one time FORTRAN line numbers.
*/
typedef enum {
GO_TERMINATE,
GO_MOVE,
GO_TOP,
GO_CLEAROBJ,
GO_CHECKHINT,
GO_WORD2,
GO_UNKNOWN,
GO_DWARFWAKE,
} phase_codes_t;
/* Use fixed-lwength types to make the save format moore portable */
typedef int32_t vocab_t; // index into a vocabulary array */
typedef int32_t verb_t; // index into an actions array */
typedef int32_t obj_t; // index into the object array */
typedef int32_t loc_t; // index into the locations array */
typedef int32_t turn_t; // turn counter or threshold */
typedef int32_t bool32_t; // turn counter or threshold */
struct game_t {
int32_t lcg_x;
int32_t abbnum; // How often to print int descriptions
score_t bonus; // What kind of finishing bonus we are getting
loc_t chloc; // pirate chest location
loc_t chloc2; // pirate chest alternate location
turn_t clock1; // # turns from finding last treasure to close
turn_t clock2; // # turns from warning till blinding flash
bool32_t clshnt; // has player read the clue in the endgame?
bool32_t closed; // whether we're all the way closed
bool32_t closng; // whether it's closing time yet
bool32_t lmwarn; // has player been warned about lamp going dim?
bool32_t novice; // asked for instructions at start-up?
bool32_t panic; // has player found out he's trapped?
bool32_t wzdark; // whether the loc he's leaving was dark
bool32_t blooded; // has player drunk of dragon's blood?
int32_t conds; // min value for cond[loc] if loc has any hints
int32_t detail; // level of detail in descriptions
/* dflag controls the level of activation of dwarves:
* 0 No dwarf stuff yet (wait until reaches Hall Of Mists)
* 1 Reached Hall Of Mists, but hasn't met first dwarf
* 2 Met 1t dwarf, others start moving, no knives thrown yet
* 3 A knife has been thrown (first set always misses) 3+
* Dwarves are mad (increases their accuracy) */
int32_t dflag;
int32_t dkill; // dwarves killed
int32_t dtotal; // total dwarves (including pirate) in loc
int32_t foobar; // progress in saying "FEE FIE FOE FOO".
int32_t holdng; // number of objects being carried
int32_t igo; // # uses of "go" instead of a direction
int32_t iwest; // # times he's said "west" instead of "w"
loc_t knfloc; // knife location; LOC_NOWERE if none, -1 after caveat
turn_t limit; // lifetime of lamp
loc_t loc; // where player is now
loc_t newloc; // where player is going
turn_t numdie; // number of times killed so far
loc_t oldloc; // where player was
loc_t oldlc2; // where player was two moves ago
obj_t oldobj; // last object player handled
int32_t saved; // point penalty for saves
int32_t tally; // count of treasures gained
int32_t thresh; // current threshold for endgame scoring tier
bool32_t seenbigwords; // have we red the graffiti in the Giant's Room?
turn_t trnluz; // # points lost so far due to turns used
turn_t turns; // counts commands given (ignores yes/no)
char zzword[TOKLEN + 1]; // randomly generated magic word from bird
struct {
int32_t abbrev; // has location been seen?
int32_t atloc; // head of object linked list per location
} locs[NLOCATIONS + 1];
struct {
int32_t seen; // true if dwarf has seen him
loc_t loc; // location of dwarves, initially hard-wired in
loc_t oldloc; // prior loc of each dwarf, initially garbage
} dwarves[NDWARVES + 1];
struct {
loc_t fixed; // fixed location of object (if not IS_FREE)
int32_t prop; // object state
loc_t place; // location of object
} objects[NOBJECTS + 1];
struct {
bool32_t used; // hints[i].used = true iff hint i has been used.
int32_t lc; // hints[i].lc = show int at LOC with cond bit i
} hints[NHINTS];
obj_t link[NOBJECTS * 2 + 1]; // object-list links
};
/*
* Game application settings - settings, but not state of the game, per se.
* This data is not saved in a saved game.
*/
struct settings_t {
FILE *logfp;
bool oldstyle;
bool prompt;
char **argv;
int argc;
int optind;
FILE *scriptfp;
int debug;
};
typedef struct {
char raw[LINESIZE];
vocab_t id;
word_type_t type;
} command_word_t;
typedef enum {
EMPTY,
RAW,
TOKENIZED,
GIVEN,
PREPROCESSED,
PROCESSING,
EXECUTED
} command_state_t;
typedef struct {
enum speechpart part;
command_word_t word[2];
verb_t verb;
obj_t obj;
command_state_t state;
} command_t;
/*
* Bump on save format change.
*
* Note: Verify that the tests run clean before bumping this, then rebuild the
* check files afterwards. Otherwise you will get a spurious failure due to the
* old version having been generated into a check file.
*/
#define SAVE_VERSION 31
/*
* Goes at start of file so saves can be identified by file(1) and the like.
*/
#define ADVENT_MAGIC "open-adventure\n"
/*
* If you change the first three members, the resume function may not properly
* reject saves from older versions. Later members can change, but bump the
* version when you do that.
*/
struct save_t {
char magic[sizeof(ADVENT_MAGIC)];
int32_t version;
int32_t canary;
struct game_t game;
};
extern struct game_t game;
extern struct save_t save;
extern struct settings_t settings;
extern char *myreadline(const char *);
extern bool get_command_input(command_t *);
extern void clear_command(command_t *);
extern void speak(const char *, ...);
extern void sspeak(int msg, ...);
extern void pspeak(vocab_t, enum speaktype, bool, int, ...);
extern void rspeak(vocab_t, ...);
extern void echo_input(FILE *, const char *, const char *);
extern bool silent_yes_or_no(void);
extern bool yes_or_no(const char *, const char *, const char *);
extern void juggle(obj_t);
extern void move(obj_t, loc_t);
extern void put(obj_t, loc_t, int);
extern void carry(obj_t, loc_t);
extern void drop(obj_t, loc_t);
extern int atdwrf(loc_t);
extern int setbit(int);
extern bool tstbit(int, int);
extern void set_seed(int32_t);
extern int32_t randrange(int32_t);
extern int score(enum termination);
extern void terminate(enum termination) __attribute__((noreturn));
extern int savefile(FILE *);
#if defined ADVENT_AUTOSAVE
extern void autosave(void);
#endif
extern int suspend(void);
extern int resume(void);
extern int restore(FILE *);
extern int initialise(void);
extern phase_codes_t action(command_t);
extern void state_change(obj_t, int);
extern bool is_valid(struct game_t);
extern void bug(enum bugtype, const char *) __attribute__((__noreturn__));
/* represent an empty command word */
static const command_word_t empty_command_word = {
.raw = "",
.id = WORD_EMPTY,
.type = NO_WORD_TYPE,
};
/* end */

View file

@ -1,106 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!--
SPDX-FileCopyrightText: 2017 Dr. Tobias Quathamer <toddy@debian.org>
SPDX-License-Identifier: BSD-2-Clause
-->
<svg width="128" height="128" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<!-- gradient for the brass body -->
<linearGradient id="brass">
<stop offset="5%" stop-color="#b5a642" />
<stop offset="95%" stop-color="#e7d874" />
</linearGradient>
<!-- body of lamp -->
<path d="m40,118 c-6,0 -8,2 -8,8 h64 c0,-6 -2,-8 -8,-8"
fill="url(#brass)" stroke="black" stroke-width="1" />
<rect x="40" y="98" width="48" height="20"
fill="url(#brass)" stroke="black" stroke-width="1" />
<!-- glass around lamp light -->
<rect x="45" y="78" width="38" height="20"
fill="#ddd" stroke="black" stroke-width="1" />
<!-- gradient for the flame -->
<linearGradient id="flame" gradientTransform="rotate(90)">
<stop offset="20%" stop-color="yellow" />
<stop offset="100%" stop-color="#fa0" />
</linearGradient>
<!-- flame -->
<path d="m59,98 c-2,-4 -2,-6 1,-10 c2,-2.67 2,-3 4,-7 c2,4 2,4.33 4,7 c3,4 3,6 1,10 z"
fill="url(#flame)" stroke="black" stroke-width="1" />
<!-- brass bars around glass -->
<rect x="40" y="78" width="2" height="20"
fill="#b5a642" stroke="black" stroke-width="1" />
<rect x="50" y="78" width="2" height="20"
fill="#bfb04c" stroke="black" stroke-width="1" />
<rect x="76" y="78" width="2" height="20"
fill="#ddce6a" stroke="black" stroke-width="1" />
<rect x="86" y="78" width="2" height="20"
fill="#e7d874" stroke="black" stroke-width="1" />
<!-- top brass plate -->
<rect x="40" y="76" width="48" height="2"
fill="url(#brass)" stroke="black" stroke-width="1" />
<!-- gradient for the metal mesh -->
<linearGradient id="meshcolor">
<stop offset="5%" stop-color="#888" />
<stop offset="95%" stop-color="#aaa" />
</linearGradient>
<!-- two lines of little holes -->
<pattern id="mesh" x="50" y="0" width="28" height="6" patternUnits="userSpaceOnUse">
<!-- rectangle for the metal background -->
<rect x="0" y="0" width="28" height="10" fill="url(#meshcolor)" />
<!-- first line of holes -->
<circle cx="2" cy="2" r="1" fill="white" />
<circle cx="5" cy="2" r="1" fill="white" />
<circle cx="8" cy="2" r="1" fill="white" />
<circle cx="11" cy="2" r="1" fill="white" />
<circle cx="14" cy="2" r="1" fill="white" />
<circle cx="17" cy="2" r="1" fill="white" />
<circle cx="20" cy="2" r="1" fill="white" />
<circle cx="23" cy="2" r="1" fill="white" />
<circle cx="26" cy="2" r="1" fill="white" />
<!-- second line of holes -->
<circle cx="0.5" cy="5" r="1" fill="white" />
<circle cx="3.5" cy="5" r="1" fill="white" />
<circle cx="6.5" cy="5" r="1" fill="white" />
<circle cx="9.5" cy="5" r="1" fill="white" />
<circle cx="12.5" cy="5" r="1" fill="white" />
<circle cx="15.5" cy="5" r="1" fill="white" />
<circle cx="18.5" cy="5" r="1" fill="white" />
<circle cx="21.5" cy="5" r="1" fill="white" />
<circle cx="24.5" cy="5" r="1" fill="white" />
<circle cx="27.5" cy="5" r="1" fill="white" />
</pattern>
<!-- metal mesh -->
<rect x="50" y="24" width="28" height="52"
fill="url(#mesh)" stroke="black" stroke-width="1" />
<!-- brass bars around mesh -->
<path d="m50,24 l-10,52 h2 l10,-52"
fill="#b5a642" stroke="black" stroke-width="1" />
<rect x="63" y="24" width="2" height="52"
fill="#cebf5b" stroke="black" stroke-width="1" />
<path d="m76,24 l10,52 h2 l-10,-52"
fill="#e7d874" stroke="black" stroke-width="1" />
<!-- hook on top, needs to be drawn before the lid -->
<path d="m63,19.5 v-5 a5,5 0 1,0 -5,-5 h-2 a7,7 0 1,1 9,6.7 v3.5"
fill="#cebf5b" stroke="black" stroke-width="1" />
<!-- top brass lid -->
<path d="m50,24 c12,-6 16,-6 28,0 z"
fill="url(#brass)" stroke="black" stroke-width="1" />
</svg>

Before

Width:  |  Height:  |  Size: 4 KiB

42
advent.txt Normal file
View file

@ -0,0 +1,42 @@
= advent(6) =
:doctype: manpage
== NAME ==
advent - Colossal Cave Adventure
== SYNOPSIS ==
*advent*
== DESCRIPTION ==
The original Colossal Cave Adventure from 1976 was the origin of all
text adventures, dungeon-crawl games, and computer-hosted roleplaying
games.
This is the last version released by Crowther & Woods, its original
authors, in 1995. It has been known as "adventure 2.5" and "430-point
adventure".
This game is released as open source with the permission and encouragement of
the authors.
There is an 'adventure' in the BSD games package that is a C
port of the 1976 ancestor of this game. To avoid a name collision,
this game builds as 'advent', reflecting the fact that the PDP-10
on which it originally ran limited filenames to 6 characters.
== OPTIONS ==
-l:: Log commands to specified file.
-o:: Old-style. Restores original interface, no prompt.
== ENVIRONMENT VARIABLES ==
ADVENTURE::
Path to the text database file describing Colossal Cave.
== REPORTING BUGS ==
Report bugs to Eric S. Raymond <esr@thyrsus.com>. The project page is
at http://catb.org/~esr/advent
== SEE ALSO ==
wumpus(6), adventure(6), zork(6), rogue(6), nethack(6).

2296
adventure.text Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

105
cheat.c
View file

@ -1,105 +0,0 @@
/*
* 'cheat' is a tool for generating save game files to test states that ought
* not happen. It leverages chunks of advent, mostly initialize() and
* savefile(), so we know we're always outputting save files that advent
* can import.
*
* SPDX-FileCopyrightText: (C) 1977, 2005 by Will Crowther and Don Woods
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "advent.h"
#include <editline/readline.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int ch;
char *savefilename = NULL;
FILE *fp = NULL;
// Initialize game variables
initialise();
/* we're generating a saved game, so saved once by default,
* unless overridden with command-line options below.
*/
game.saved = 1;
/* Options. */
const char *opts = "d:l:s:t:v:o:";
const char *usage =
"Usage: %s [-d numdie] [-s numsaves] [-v version] -o savefilename "
"\n"
" -d number of deaths. Signed integer.\n"
" -l lifetime of lamp in turns. Signed integer.\n"
" -s number of saves. Signed integer.\n"
" -t number of turns. Signed integer.\n"
" -v version number of save format.\n"
" -o required. File name of save game to write.\n";
while ((ch = getopt(argc, argv, opts)) != EOF) {
switch (ch) {
case 'd':
game.numdie = (turn_t)atoi(optarg);
printf("cheat: game.numdie = %d\n", game.numdie);
break;
case 'l':
game.limit = (turn_t)atoi(optarg);
printf("cheat: game.limit = %d\n", game.limit);
break;
case 's':
game.saved = (int)atoi(optarg);
printf("cheat: game.saved = %d\n", game.saved);
break;
case 't':
game.turns = (turn_t)atoi(optarg);
printf("cheat: game.turns = %d\n", game.turns);
break;
case 'v':
save.version = atoi(optarg);
printf("cheat: version = %d\n", save.version);
break;
case 'o':
savefilename = optarg;
break;
default:
fprintf(stderr, usage, argv[0]);
exit(EXIT_FAILURE);
break;
}
}
// Save filename required; the point of cheat is to generate save file
if (savefilename == NULL) {
fprintf(stderr, usage, argv[0]);
fprintf(stderr, "ERROR: filename required\n");
exit(EXIT_FAILURE);
}
fp = fopen(savefilename, WRITE_MODE);
if (fp == NULL) {
fprintf(stderr, "Can't open file %s. Exiting.\n", savefilename);
exit(EXIT_FAILURE);
}
savefile(fp);
fclose(fp);
printf("cheat: %s created.\n", savefilename);
return EXIT_SUCCESS;
}
// LCOV_EXCL_START
/*
* Ugh...unused, but required for linkage.
* See the actually useful version of this in main.c
*/
char *myreadline(const char *prompt) { return readline(prompt); }
// LCOV_EXCL_STOP
/* end */

25
control
View file

@ -1,29 +1,22 @@
# This is not a real Debian control file
# It's project metadata for the shipper tool
Package: open-adventure
Package: advent
Description: Colossal Cave Adventure, the 1995 430-point version.
This is the last descendant of the original 1976 Colossal Cave Adventure
worked on by the original authors - Crowther & Woods; it is shipped with
their permission and encouragement. It has sometimes been known as
Adventure 2.5. The original PDP-10 name 'advent' is used for the
built program to avoid collision with the BSD Games version.
This is the last descendent of the original 1976 Colossal Cave Adventure
worked on by the original authors - Crowther & Woods. It has sometimes
been known as Adventure 2.5. The original PDP-10 name 'advent' is used
to avoid collision with the BSD Games version.
Homepage: http://www.catb.org/~esr/open-adventure
#XBS-Destinations: freshcode
Homepage: http://www.catb.org/~esr/advent
XBS-HTML-Target: index.html
XBS-Repository-URL: https://gitlab.com/esr/open-adventure
XBS-Debian-Packages: open-adventure
XBS-IRC-Channel: irc://chat.freenode.net/#open-adventure
XBS-Project-Tags: Games/Entertainment
#XBS-Project-Tags: Games/Entertainment
XBS-VC-Tag-Template: %(version)s
XBS-Logo: lamp.png
XBS-Validate: make pylint cppcheck check

45
funcs.h Normal file
View file

@ -0,0 +1,45 @@
#include <stdbool.h>
/* Statement functions
*
* AT(OBJ) = true if on either side of two-placed object
* CNDBIT(L,N) = true if COND(L) has bit n set (bit 0 is units bit)
* DARK(DUMMY) = true if location "LOC" is dark
* FORCED(LOC) = true if LOC moves without asking for input (COND=2)
* FOREST(LOC) = true if LOC is part of the forest
* GSTONE(OBJ) = true if OBJ is a gemstone
* HERE(OBJ) = true if the OBJ is at "LOC" (or is being carried)
* LIQ(DUMMY) = object number of liquid in bottle
* LIQLOC(LOC) = object number of liquid (if any) at LOC
* PCT(N) = true N% of the time (N integer from 0 to 100)
* TOTING(OBJ) = true if the OBJ is being carried */
#define TOTING(OBJ) (PLACE[OBJ] == -1)
#define AT(OBJ) (PLACE[OBJ] == LOC || FIXED[OBJ] == LOC)
#define HERE(OBJ) (AT(OBJ) || TOTING(OBJ))
#define LIQ2(PBOTL) ((1-(PBOTL))*WATER+((PBOTL)/2)*(WATER+OIL))
#define LIQ(DUMMY) (LIQ2(PROP[BOTTLE]<0 ? -1-PROP[BOTTLE] : PROP[BOTTLE]))
#define LIQLOC(LOC) (LIQ2((MOD(COND[LOC]/2*2,8)-5)*MOD(COND[LOC]/4,2)+1))
#define CNDBIT(L,N) (TSTBIT(COND[L],N))
#define FORCED(LOC) (COND[LOC] == 2)
#define DARK(DUMMY) ((!CNDBIT(LOC,0)) && (PROP[LAMP] == 0 || !HERE(LAMP)))
#define PCT(N) (randrange(100) < (N))
#define GSTONE(OBJ) ((OBJ) == EMRALD || (OBJ) == RUBY || (OBJ) == AMBER || (OBJ) == SAPPH)
#define FOREST(LOC) ((LOC) >= 145 && (LOC) <= 166)
#define VOCWRD(LETTRS,SECT) (VOCAB(MAKEWD(LETTRS),SECT))
/* The following two functions were added to fix a bug (CLOCK1 decremented
* while in forest). They should probably be replaced by using another
* "cond" bit. For now, however, a quick fix... OUTSID(LOC) is true if
* LOC is outside, INDEEP(LOC) is true if LOC is "deep" in the cave (hall
* of mists or deeper). Note special kludges for "FOOF" locs. */
#define OUTSID(LOC) ((LOC) <= 8 || FOREST(LOC) || (LOC) == PLAC[SAPPH] || (LOC) == 180 || (LOC) == 182)
#define INDEEP(LOC) ((LOC) >= 15 && !OUTSID(LOC) && (LOC) != 179)
extern int carry(void), discard(bool), attack(FILE *), throw(FILE *), feed(void), fill(void);
void score(long);

View file

@ -1,24 +0,0 @@
= Non-spoiler hints =
// SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
// SPDX-License-Identifier: CC-BY-4.0
Say the words you see. They can have interesting effects.
Reading is fundamental.
Yes, the fissure in the Hall of Mists can be bridged. By magic.
"Free bird": It's more than an epic guitar solo. Do it twice!
There is a legend that if you drink the blood of a dragon, you will
be able to understand the speech of birds.
That vending machine? It would be better off dead.
Ogres laugh at humans, but for some reason dwarves frighten them badly.
When rust is a problem, oil can be helpful.
A lucky rabbit's foot might help you keep your footing.
The troll might go away when you are no longer unbearable.

View file

@ -1,174 +0,0 @@
= A brief history of Colossal Cave Adventure =
by Eric S. Raymond
// SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
// SPDX-License-Identifier: CC-BY-4.0
Adventure is the fons et origo of all later dungeon-crawling computer
games, the granddaddy of interactive fiction, and one of the hallowed
artifacts of hacker folklore.
== Origin and history ==
The very first version was released by Crowther in 1976, in FORTRAN on
the PDP-10 at Bolt, Beranek, and Newman. (Crowther was at the time
writing what we could now call firmware for the earliest ARPANET
routers.) It was a maze game based on the Colossal Cave complex in
Kentucky, including fewer of the D&D-like elements now associated with
the game.
Adventure as we now know it, the ancestor of all later versions, was
released on a PDP-10 at the Stanford AI Lab by Don Woods on June 3rd,
1977 (some sources erroneously say 1976). That version is sometimes
known as 350-point Adventure.
Between 1977 and 1995 Crowther and Woods themselves continued to work
intermittently on the game. This main line of development culminated
in the 1995 release of Adventure 2.5, also known as 430-point Adventure
The earliest port to C was by Jim Gillogly under an early Unix running
at the Rand Corporation in 1977; this version was later, and still is,
included in the BSD Games collection. I have it from Don Woods directly
that "[Jim Gillogly] was one of the first to request and receive a copy
of the source" but that Woods did not actually know of the BSD port
until I briefed him on it in 2017. (This contradicts some implications
in third-party histories.)
Many other people ported and extended the game in various directions.
A notable version was the first game shipped for the IBM Personal
Computer in 1981; neither Crowther nor Woods nor Gillogly were paid
royalties.
The history of these non-mainline versions is complex and
murky. Functional differences were generally marked by changes in the
maximum score as people added puzzles and rooms; however, multiple
ports of some versions existed - some in FORTRAN, some in C,
some in other languages - so the maximum point score is not
completely disambiguating.
Same articles at <<DA>> are a narrative of the history of the game.
There is an in-depth study of its origins at <<SN>>. Many versions
are collected at The Interactive Fiction Archive <<IFA>>; note however
that IFA's historical claims are thinly sourced and its dates for the
earliest releases don't match either comments in the code or the
careful reconstruction in <<SN>>.
== Open Adventure ==
An attempt to untangle and document a lot of the non-mainline history
has been made by Arthur O'Dwyer at <<QUUX>>. For our purposes, it
will suffice to explain the chain of provenance that led from the
original Adventure to the Open Adventure distributed with this
document.
The original 350-point ADVENT on the PDP-10 had been one of my
formative experiences as a fledgling hacker in 1976-77. Forty years
later, in February 2017, while doing some casual research into the
history of text adventure games, I looked through some source code at
<<IFA>> and was delighted to learn of Adventure 2.5, a version of the
Crowther-Woods mainline later than I had ever played.
Adventure 2.5 had been shipped long enough ago that today's conventions of
open-source licensing were not yet fully established. The Makefile
contained a rights reservation by Don Woods and that was it.
I wrote to Don asking permission to release 2.5 under 2-clause BSD;
he replied on 15 May 2017 giving both permission and encouragement.
Here is what Don said about differences between the original Adventure
and 2.5:
............................................................................
> The bulk of the points come from five new 16-point treasures. (I say "bulk"
> because I think at least one of the scores included some padding and I may
> have tweaked those.) Each of the new treasures requires solving a puzzle
> that's definitely at the tricky end of the scale for Adventure. Much of the
> new stuff involves trying new directions and/or finding new uses for stuff
> that already existed; e.g. the forest outside is no longer a small number of
> locations with partially random movement, but is a full-fledged maze, one
> that I hope has a character different from either of the previous two.
>
> As the text itself says, V2.5 is essentially the same as V2, with a few more
> hints. (I think I came up with a better one for the endgame, too.) I don't
> seem to have a copy of the similar text from V2, so I don't know whether/how
> it described itself to new and seasoned players.
>
> The other big change, as I mentioned above, was I added a way of docking
> points at a certain number of turns. This was my second attempt to do what
> the batteries had been for: require being efficient to achieve top score.
> Alas, the batteries led to players deliberately turning the lamp off/on
> whenever they weren't moving or were in a lit area, making the game take
> even longer! I set the requirement at what felt like a hard but fair
> number of turns, then applied several sneaky tricks to shave off another
> twenty.
>
> I hacked up a wrapper around the game (still in Fortran, most likely, but
> I forget) that would try each initializing the RNG using each second of a
> given day, while feeding in a script that either worked or aborted early
> if anything went wrong (such as a dwarf blocking my path). As I recall,
> it took less than a day's worth of RNG seeds to find one that worked.
>
> I verified my script could work given a favorable RNG, and stuck
> that number in the message.
>
> I like how that final puzzle, unlike the game itself, does not readily
> succumb even given access to the game source. You really need to fit
> together not only the goals and the map and use of inventory space, but
> also details like just what _can_ you do in the dark...?
............................................................................
Great care has been taken to preserve 2.5's exact gameplay as intended
by Don. We have added a "version" command.
However, under the hood Open Adventure is rather different from 2.5.
Where 2.5 was written in FORTRAN mechanically translated into
extremely ugly C, Open Adventure has been translated into much more
modern and idiomatic C. The extremely cryptic and opaque format of
the original database of rooms, objects, and strings has been moved to
YAML; this makes the brilliant design of it much easier to comprehend.
== Earlier non-influences ==
There is record of one earlier dungeon-crawling game called "dnd",
written in 1974-75 on the PLATO system at University of Illinois
<<DND>>. This was in some ways similar to later roguelike games but
not to Adventure. The designers of later roguelikes frequently cite
Adventure as an influence, but not dnd; like PLATO itself, dnd seems
not to have become known outside of its own user community until
rediscovered by computer historians many years after Adventure
shipped.
There was also Hunt The Wumpus <<WUMPUS>>, written by Gregory Yob in
1972. There is no evidence that Yob's original (circulated
in BASIC among microcomputer enthusiasts) was known to the ARPANET-
and minicomputer-centered culture Crowther and Woods were part of
until well after Adventure was written.
(I was a developer of the Nethack roguelike early in that game's
history, in the late 1980s; we knew nothing of PLATO dnd. We did know
of Hunt The Wumpus then from its early Unix port, but it didn't
influence us either, nor in any apparent way the designers of other
early roguelikes. After my time the wumpus was included as a monster
in Nethack, but this was done in a spirit of conscious museumization
well after historians rediscovered Yob's game.)
Neither of these games used an attempt at a natural-language parser
even as primitive as Adventure's.
== Sources ==
// asciidoc and asciidoctor both foo up on bare links ending in ')'.
[bibliography]
- [[[IFA]]] http://rickadams.org/adventure/[Colossal Cave Adventure Page]
- [[[DA]]] http://www.filfre.net/sitemap/[The Digital Antiquarian]
- [[[SN]]]
http://www.digitalhumanities.org/dhq/vol/1/2/000009/000009.html[Digital
Humanities Quarterly]
- [[[DND]]] https://en.wikipedia.org/wiki/Dnd_(video_game)[dnd (video game)]
- [[[WUMPUS]]] https://en.wikipedia.org/wiki/Hunt_the_Wumpus[Hunt The Wumpus]
- [[[QUUX]]] https://github.com/Quuxplusone/Advent[Quuxplusone/Advent]

86
history.txt Normal file
View file

@ -0,0 +1,86 @@
= A brief history of Colossal Cave Adventure =
by Eric S. Raymond
Adventure is the fons et origo of all later dungeon-crawling games,
the grandaddy of interactive fiction, and one of the hallowed artifacts
of hacker folklore.
The very first version was released by Crowther in 1976, in FORTRAN on
the PDP-10 at Bolt, Beranek, and Newman. (Crowther was at the time
writing what we could now call firmware for the earliest ARPANET
routers.) It was a maze game based on the Colossal Cave complex in
Kentucky, lacking the D&D-like elements now associated with the game.
Adventure as we now know it, the ancestor of all later versions, was
was released on a PDP-10 at the Stanford AI Lab by Don Woods in 1977
(some sources, apparently erroneously, say 1976). That version is
sometimes known as 350-point Adventure.
Between 1977 and 1995 Crowther and Woods themselves continued to work
intermittently on the game. This main line of development culminated
in the 1995 release of Adventure 2.5, also known as 430-point Adventure
The earliest port to C was by Jim Gillogly under an early Unix running
at the Rand Corporation in 1977; this version was later, and still is,
included in the BSD Games collection. It was blessed by Crowther and
Woods and briefly marketed in 1981 under the name "The Original
Adventure".
Many other people ported and extended the game in various directions.
A notable version was the first game shipped for the IBM Personal
Computer in 1981; this, for which neither Crowther nor Woods nor
Gillogly were paid royalties, what "The Original" was competing
against.
The history of these non-mainline versions is complex and
murky. Functional differences were generally marked by changes in the
maximum score as people added puzzles and rooms; however, multiple
ports of some versions existed - some in FORTRAN, some in C,
some in other languages - so the maximum point score is not
completely disambiguating.
Same articles at <<DA>> are a narrative of the history of the
game. There is an in-depth study of its origins at <<SN>>.
Many versions are collected at The Interactive Fiction Archive
<<IFA>>; note however that its dates for the earliest releases
don't match other comments in the code or the careful reconstruction
in <<SN>>.
Future versions of this document may attempt to untangle some of the
non-mainline history. For now, it will suffice to explain the chain of
provenance that led from the original Adventure to the version
distributed with this document.
The original 350-point ADVENT on the PDP-10 had been one of my
formative experiences as a fledgling hacker in 1976-77. Forty years
later, in February 2017, while doing some casual research into the
history of text adventure games, I looked through some source code at
<<IFA>> and was delighted to learn of Adventure 2.5, a version of the
Crowther-Woods mainline later than I had ever played.
Adventure 2.5 had been shipped long enough ago that today's conventions of
open-source licensing were not yet fully established. The Makefile
contained a rights reservation by Don Woods and that was it.
I wrote to Don asking permission to release 2.5 under 2-clause BSD;
he replied on 15 May giving both permission and encouragement.
== Nomenclature ==
This project is called "Open Adventure" because it's not at all clear
to number Adventure past 2.5 without misleading or causing
collisions. Various of the non-mainline versions have claimed to be
versions 3, 4, 5, 6, 7 and for all I know higher than that. It seems
best just to start a new numbering series while acknowledging the
links back. I have reverted to "Advent" to avoid a name collision
with the BSD Games version.
== Sources ==
[bibliography]
- [[[IFA]]] http://rickadams.org/adventure/
- [[[[DA]]] http://www.filfre.net/sitemap/
- [[[SN]]] http://www.digitalhumanities.org/dhq/vol/1/2/000009/000009.html

790
init.c
View file

@ -1,96 +1,714 @@
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "misc.h"
#include "main.h"
#include "share.h"
#include "funcs.h"
/*
* Initialisation
*
* SPDX-FileCopyrightText: (C) 1977, 2005 by Will Crowther and Don Woods
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
/* Current limits:
* 12500 words of message text (LINES, LINSIZ).
* 885 travel options (TRAVEL, TRVSIZ).
* 330 vocabulary words (KTAB, ATAB, TABSIZ).
* 185 locations (LTEXT, STEXT, KEY, COND, ABB, ATLOC, LOCSND, LOCSIZ).
* 100 objects (PLAC, PLACE, FIXD, FIXED, LINK (TWICE), PTEXT, PROP,
* OBJSND, OBJTXT).
* 35 "action" verbs (ACTSPK, VRBSIZ).
* 277 random messages (RTEXT, RTXSIZ).
* 12 different player classifications (CTEXT, CVAL, CLSMAX).
* 20 hints (HINTLC, HINTED, HINTS, HNTSIZ).
* 5 "# of turns" threshholds (TTEXT, TRNVAL, TRNSIZ).
* There are also limits which cannot be exceeded due to the structure of
* the database. (E.G., The vocabulary uses n/1000 to determine word type,
* so there can't be more than 1000 words.) These upper limits are:
* 1000 non-synonymous vocabulary words
* 300 locations
* 100 objects */
#include "advent.h"
struct settings_t settings = {.logfp = NULL, .oldstyle = false, .prompt = true};
/* Description of the database format
*
*
* The data file contains several sections. Each begins with a line containing
* a number identifying the section, and ends with a line containing "-1".
*
* Section 1: Long form descriptions. Each line contains a location number,
* a tab, and a line of text. The set of (necessarily adjacent) lines
* whose numbers are X form the long description of location X.
* Section 2: Short form descriptions. Same format as long form. Not all
* places have short descriptions.
* Section 3: Travel table. Each line contains a location number (X), a second
* location number (Y), and a list of motion numbers (see section 4).
* each motion represents a verb which will go to Y if currently at X.
* Y, in turn, is interpreted as follows. Let M=Y/1000, N=Y mod 1000.
* If N<=300 it is the location to go to.
* If 300<N<=500 N-300 is used in a computed goto to
* a section of special code.
* If N>500 message N-500 from section 6 is printed,
* and he stays wherever he is.
* Meanwhile, M specifies the conditions on the motion.
* If M=0 it's unconditional.
* If 0<M<100 it is done with M% probability.
* If M=100 unconditional, but forbidden to dwarves.
* If 100<M<=200 he must be carrying object M-100.
* If 200<M<=300 must be carrying or in same room as M-200.
* If 300<M<=400 PROP(M % 100) must *not* be 0.
* If 400<M<=500 PROP(M % 100) must *not* be 1.
* If 500<M<=600 PROP(M % 100) must *not* be 2, etc.
* If the condition (if any) is not met, then the next *different*
* "destination" value is used (unless it fails to meet *its* conditions,
* in which case the next is found, etc.). Typically, the next dest will
* be for one of the same verbs, so that its only use is as the alternate
* destination for those verbs. For instance:
* 15 110022 29 31 34 35 23 43
* 15 14 29
* This says that, from loc 15, any of the verbs 29, 31, etc., will take
* him to 22 if he's carrying object 10, and otherwise will go to 14.
* 11 303008 49
* 11 9 50
* This says that, from 11, 49 takes him to 8 unless PROP(3)=0, in which
* case he goes to 9. Verb 50 takes him to 9 regardless of PROP(3).
* Section 4: Vocabulary. Each line contains a number (n), a tab, and a
* five-letter word. Call M=N/1000. If M=0, then the word is a motion
* verb for use in travelling (see section 3). Else, if M=1, the word is
* an object. Else, if M=2, the word is an action verb (such as "carry"
* or "attack"). Else, if M=3, the word is a special case verb (such as
* "dig") and N % 1000 is an index into section 6. Objects from 50 to
* (currently, anyway) 79 are considered treasures (for pirate, closeout).
* Section 5: Object descriptions. Each line contains a number (N), a tab,
* and a message. If N is from 1 to 100, the message is the "inventory"
* message for object n. Otherwise, N should be 000, 100, 200, etc., and
* the message should be the description of the preceding object when its
* prop value is N/100. The N/100 is used only to distinguish multiple
* messages from multi-line messages; the prop info actually requires all
* messages for an object to be present and consecutive. Properties which
* produce no message should be given the message ">$<".
* Section 6: Arbitrary messages. Same format as sections 1, 2, and 5, except
* the numbers bear no relation to anything (except for special verbs
* in section 4).
* Section 7: Object locations. Each line contains an object number and its
* initial location (zero (or omitted) if none). If the object is
* immovable, the location is followed by a "-1". If it has two locations
* (e.g. the grate) the first location is followed with the second, and
* the object is assumed to be immovable.
* Section 8: Action defaults. Each line contains an "action-verb" number and
* the index (in section 6) of the default message for the verb.
* Section 9: Location attributes. Each line contains a number (n) and up to
* 20 location numbers. Bit N (where 0 is the units bit) is set in
* COND(LOC) for each loc given. The cond bits currently assigned are:
* 0 Light
* 1 If bit 2 is on: on for oil, off for water
* 2 Liquid asset, see bit 1
* 3 Pirate doesn't go here unless following player
* 4 Cannot use "back" to move away
* Bits past 10 indicate areas of interest to "hint" routines:
* 11 Trying to get into cave
* 12 Trying to catch bird
* 13 Trying to deal with snake
* 14 Lost in maze
* 15 Pondering dark room
* 16 At witt's end
* 17 Cliff with urn
* 18 Lost in forest
* 19 Trying to deal with ogre
* 20 Found all treasures except jade
* COND(LOC) is set to 2, overriding all other bits, if loc has forced
* motion.
* Section 10: Class messages. Each line contains a number (n), a tab, and a
* message describing a classification of player. The scoring section
* selects the appropriate message, where each message is considered to
* apply to players whose scores are higher than the previous N but not
* higher than this N. Note that these scores probably change with every
* modification (and particularly expansion) of the program.
* SECTION 11: Hints. Each line contains a hint number (add 10 to get cond
* bit; see section 9), the number of turns he must be at the right loc(s)
* before triggering the hint, the points deducted for taking the hint,
* the message number (section 6) of the question, and the message number
* of the hint. These values are stashed in the "hints" array. HNTMAX is
* set to the max hint number (<= HNTSIZ).
* Section 12: Unused in this version.
* Section 13: Sounds and text. Each line contains either 2 or 3 numbers. If
* 2 (call them N and S), N is a location and message ABS(S) from section
* 6 is the sound heard there. If S<0, the sound there drowns out all
* other noises. If 3 numbers (call them N, S, and T), N is an object
* number and S+PROP(N) is the property message (from section 5) if he
* listens to the object, and T+PROP(N) is the text if he reads it. If
* S or T is -1, the object has no sound or text, respectively. Neither
* S nor T is allowed to be 0.
* Section 14: Turn threshholds. Each line contains a number (N), a tab, and
* a message berating the player for taking so many turns. The messages
* must be in the proper (ascending) order. The message gets printed if
* the player exceeds N % 100000 turns, at which time N/100000 points
* get deducted from his score.
* Section 0: End of database. */
struct game_t game = {
/* Last dwarf is special (the pirate). He always starts at his
* chest's eventual location inside the maze. This loc is saved
* in chloc for ref. The dead end in the other maze has its
* loc stored in chloc2. */
.chloc = LOC_MAZEEND12, .chloc2 = LOC_DEADEND13, .abbnum = 5,
.clock1 = WARNTIME, .clock2 = FLASHTIME, .newloc = LOC_START,
.loc = LOC_START, .limit = GAMELIMIT, .foobar = WORD_EMPTY,
};
/* The various messages (sections 1, 2, 5, 6, etc.) may include certain
* special character sequences to denote that the program must provide
* parameters to insert into a message when the message is printed. These
* sequences are:
* %S = The letter 'S' or nothing (if a given value is exactly 1)
* %W = A word (up to 10 characters)
* %L = A word mapped to lower-case letters
* %U = A word mapped to upper-case letters
* %C = A word mapped to lower-case, first letter capitalised
* %T = Several words of text, ending with a word of -1
* %1 = A 1-digit number
* %2 = A 2-digit number
* ...
* %9 = A 9-digit number
* %B = Variable number of blanks
* %! = The entire message should be suppressed */
int initialise(void) {
if (settings.oldstyle) {
static bool quick_init(void);
static int raw_init(void);
static void report(void);
static void quick_save(void);
static int finish_init(void);
static void quick_io(void);
void initialise(void) {
if (oldstyle)
printf("Initialising...\n");
}
srand(time(NULL));
int seedval = (int)rand();
set_seed(seedval);
for (int i = 1; i <= NDWARVES; i++) {
game.dwarves[i].loc = dwarflocs[i - 1];
}
for (int i = 1; i <= NOBJECTS; i++) {
game.objects[i].place = LOC_NOWHERE;
}
for (int i = 1; i <= NLOCATIONS; i++) {
if (!(locations[i].description.big == 0 || tkey[i] == 0)) {
int k = tkey[i];
if (travel[k].motion == HERE) {
conditions[i] |= (1 << COND_FORCED);
}
}
}
/* Set up the game.locs atloc and game.link arrays.
* We'll use the DROP subroutine, which prefaces new objects on the
* lists. Since we want things in the other order, we'll run the
* loop backwards. If the object is in two locs, we drop it twice.
* Also, since two-placed objects are typically best described
* last, we'll drop them first. */
for (int i = NOBJECTS; i >= 1; i--) {
if (objects[i].fixd > 0) {
drop(i + NOBJECTS, objects[i].fixd);
drop(i, objects[i].plac);
}
}
for (int i = 1; i <= NOBJECTS; i++) {
int k = NOBJECTS + 1 - i;
game.objects[k].fixed = objects[k].fixd;
if (objects[k].plac != 0 && objects[k].fixd <= 0) {
drop(k, objects[k].plac);
}
}
/* Treasure props are initially STATE_NOTFOUND, and are set to
* STATE_FOUND the first time they are described. game.tally
* keeps track of how many are not yet found, so we know when to
* close the cave.
* (ESR) Non-treasures are set to STATE_FOUND explicitly so we
* don't rely on the value of uninitialized storage. This is to
* make translation to future languages easier. */
for (int object = 1; object <= NOBJECTS; object++) {
if (objects[object].is_treasure) {
++game.tally;
if (objects[object].inventory != NULL) {
OBJECT_SET_NOT_FOUND(object);
}
} else {
OBJECT_SET_FOUND(object);
}
}
game.conds = setbit(COND_HBASE);
return seedval;
if(!quick_init()){raw_init(); report(); quick_save();}
finish_init();
}
static int raw_init(void) {
//printf("Couldn't find adventure.data, using adventure.text...\n");
FILE *OPENED=fopen("adventure.text","r" /* NOT binary */);
if(!OPENED){printf("Can't read adventure.text!\n"); exit(0);}
/* Clear out the various text-pointer arrays. All text is stored in array
* lines; each line is preceded by a word pointing to the next pointer (i.e.
* the word following the end of the line). The pointer is negative if this is
* first line of a message. The text-pointer arrays contain indices of
* pointer-words in lines. STEXT(N) is short description of location N.
* LTEXT(N) is long description. PTEXT(N) points to message for PROP(N)=0.
* Successive prop messages are found by chasing pointers. RTEXT contains
* section 6's stuff. CTEXT(N) points to a player-class message. TTEXT is for
* section 14. We also clear COND (see description of section 9 for details). */
/* 1001 */ for (I=1; I<=300; I++) {
if(I <= 100)PTEXT[I]=0;
if(I <= RTXSIZ)RTEXT[I]=0;
if(I <= CLSMAX)CTEXT[I]=0;
if(I <= 100)OBJSND[I]=0;
if(I <= 100)OBJTXT[I]=0;
if(I > LOCSIZ) goto L1001;
STEXT[I]=0;
LTEXT[I]=0;
COND[I]=0;
KEY[I]=0;
LOCSND[I]=0;
L1001: /*etc*/ ;
} /* end loop */
LINUSE=1;
TRVS=1;
CLSSES=0;
TRNVLS=0;
/* Start new data section. Sect is the section number. */
L1002: SECT=GETNUM(OPENED);
OLDLOC= -1;
switch (SECT) { case 0: return(0); case 1: goto L1004; case 2: goto
L1004; case 3: goto L1030; case 4: goto L1040; case 5: goto L1004;
case 6: goto L1004; case 7: goto L1050; case 8: goto L1060; case
9: goto L1070; case 10: goto L1004; case 11: goto L1080; case 12:
break; case 13: goto L1090; case 14: goto L1004; }
/* (0) (1) (2) (3) (4) (5) (6) (7) (8) (9)
* (10) (11) (12) (13) (14) */
BUG(9);
/* Sections 1, 2, 5, 6, 10, 14. Read messages and set up pointers. */
L1004: KK=LINUSE;
L1005: LINUSE=KK;
LOC=GETNUM(OPENED);
if(LNLENG >= LNPOSN+70)BUG(0);
if(LOC == -1) goto L1002;
if(LNLENG < LNPOSN)BUG(1);
L1006: KK=KK+1;
if(KK >= LINSIZ)BUG(2);
LINES[KK]=GETTXT(false,false,false,KK);
if(LINES[KK] != -1) goto L1006;
LINES[LINUSE]=KK;
if(LOC == OLDLOC) goto L1005;
OLDLOC=LOC;
LINES[LINUSE]= -KK;
if(SECT == 14) goto L1014;
if(SECT == 10) goto L1012;
if(SECT == 6) goto L1011;
if(SECT == 5) goto L1010;
if(LOC > LOCSIZ)BUG(10);
if(SECT == 1) goto L1008;
STEXT[LOC]=LINUSE;
goto L1005;
L1008: LTEXT[LOC]=LINUSE;
goto L1005;
L1010: if(LOC > 0 && LOC <= 100)PTEXT[LOC]=LINUSE;
goto L1005;
L1011: if(LOC > RTXSIZ)BUG(6);
RTEXT[LOC]=LINUSE;
goto L1005;
L1012: CLSSES=CLSSES+1;
if(CLSSES > CLSMAX)BUG(11);
CTEXT[CLSSES]=LINUSE;
CVAL[CLSSES]=LOC;
goto L1005;
L1014: TRNVLS=TRNVLS+1;
if(TRNVLS > TRNSIZ)BUG(11);
TTEXT[TRNVLS]=LINUSE;
TRNVAL[TRNVLS]=LOC;
goto L1005;
/* The stuff for section 3 is encoded here. Each "from-location" gets a
* contiguous section of the "TRAVEL" array. Each entry in travel is
* NEWLOC*1000 + KEYWORD (from section 4, motion verbs), and is negated if
* this is the last entry for this location. KEY(N) is the index in travel
* of the first option at location N. */
L1030: LOC=GETNUM(OPENED);
if(LOC == -1) goto L1002;
NEWLOC=GETNUM(NULL);
if(KEY[LOC] != 0) goto L1033;
KEY[LOC]=TRVS;
goto L1035;
L1033: TRVS--; TRAVEL[TRVS]= -TRAVEL[TRVS]; TRVS++;
L1035: L=GETNUM(NULL);
if(L == 0) goto L1039;
TRAVEL[TRVS]=NEWLOC*1000+L;
TRVS=TRVS+1;
if(TRVS == TRVSIZ)BUG(3);
goto L1035;
L1039: TRVS--; TRAVEL[TRVS]= -TRAVEL[TRVS]; TRVS++;
goto L1030;
/* Here we read in the vocabulary. KTAB(N) is the word number, ATAB(N) is
* the corresponding word. The -1 at the end of section 4 is left in KTAB
* as an end-marker. The words are given a minimal hash to make deciphering
* the core-image harder. (We don't use gettxt's hash since that would force
* us to hash each input line to make comparisons work, and that in turn
* would make it harder to detect particular input words.) */
L1040: J=10000;
for (TABNDX=1; TABNDX<=TABSIZ; TABNDX++) {
KTAB[TABNDX]=GETNUM(OPENED);
if(KTAB[TABNDX] == -1) goto L1002;
J=J+7;
ATAB[TABNDX]=GETTXT(true,true,true,0)+J*J;
} /* end loop */
BUG(4);
/* Read in the initial locations for each object. Also the immovability info.
* plac contains initial locations of objects. FIXD is -1 for immovable
* objects (including the snake), or = second loc for two-placed objects. */
L1050: OBJ=GETNUM(OPENED);
if(OBJ == -1) goto L1002;
PLAC[OBJ]=GETNUM(NULL);
FIXD[OBJ]=GETNUM(NULL);
goto L1050;
/* Read default message numbers for action verbs, store in ACTSPK. */
L1060: VERB=GETNUM(OPENED);
if(VERB == -1) goto L1002;
ACTSPK[VERB]=GETNUM(NULL);
goto L1060;
/* Read info about available liquids and other conditions, store in COND. */
L1070: K=GETNUM(OPENED);
if(K == -1) goto L1002;
L1071: LOC=GETNUM(NULL);
if(LOC == 0) goto L1070;
if(CNDBIT(LOC,K)) BUG(8);
COND[LOC]=COND[LOC]+SETBIT(K);
goto L1071;
/* Read data for hints. */
L1080: HNTMAX=0;
L1081: K=GETNUM(OPENED);
if(K == -1) goto L1002;
if(K <= 0 || K > HNTSIZ)BUG(7);
for (I=1; I<=4; I++) {
HINTS[K][I] =GETNUM(NULL);
} /* end loop */
HNTMAX=(HNTMAX>K ? HNTMAX : K);
goto L1081;
/* Read the sound/text info, store in OBJSND, OBJTXT, LOCSND. */
L1090: K=GETNUM(OPENED);
if(K == -1) goto L1002;
KK=GETNUM(NULL);
I=GETNUM(NULL);
if(I == 0) goto L1092;
OBJSND[K]=(KK>0 ? KK : 0);
OBJTXT[K]=(I>0 ? I : 0);
goto L1090;
L1092: LOCSND[K]=KK;
goto L1090;
}
/* Finish constructing internal data format */
/* Having read in the database, certain things are now constructed. PROPS are
* set to zero. We finish setting up COND by checking for forced-motion travel
* entries. The PLAC and FIXD arrays are used to set up ATLOC(N) as the first
* object at location N, and LINK(OBJ) as the next object at the same location
* as OBJ. (OBJ>100 indicates that FIXED(OBJ-100)=LOC; LINK(OBJ) is still the
* correct link to use.) ABB is zeroed; it controls whether the abbreviated
* description is printed. Counts modulo 5 unless "LOOK" is used. */
static int finish_init(void) {
for (I=1; I<=100; I++) {
PLACE[I]=0;
PROP[I]=0;
LINK[I]=0;
{long x = I+100; LINK[x]=0;}
} /* end loop */
/* 1102 */ for (I=1; I<=LOCSIZ; I++) {
ABB[I]=0;
if(LTEXT[I] == 0 || KEY[I] == 0) goto L1102;
K=KEY[I];
if(MOD(IABS(TRAVEL[K]),1000) == 1)COND[I]=2;
L1102: ATLOC[I]=0;
} /* end loop */
/* Set up the ATLOC and LINK arrays as described above. We'll use the DROP
* subroutine, which prefaces new objects on the lists. Since we want things
* in the other order, we'll run the loop backwards. If the object is in two
* locs, we drop it twice. This also sets up "PLACE" and "fixed" as copies of
* "PLAC" and "FIXD". Also, since two-placed objects are typically best
* described last, we'll drop them first. */
/* 1106 */ for (I=1; I<=100; I++) {
K=101-I;
if(FIXD[K] <= 0) goto L1106;
DROP(K+100,FIXD[K]);
DROP(K,PLAC[K]);
L1106: /*etc*/ ;
} /* end loop */
for (I=1; I<=100; I++) {
K=101-I;
FIXED[K]=FIXD[K];
if(PLAC[K] != 0 && FIXD[K] <= 0)DROP(K,PLAC[K]);
} /* end loop */
/* Treasures, as noted earlier, are objects 50 through MAXTRS (CURRENTLY 79).
* Their props are initially -1, and are set to 0 the first time they are
* described. TALLY keeps track of how many are not yet found, so we know
* when to close the cave. */
MAXTRS=79;
TALLY=0;
for (I=50; I<=MAXTRS; I++) {
if(PTEXT[I] != 0)PROP[I]= -1;
TALLY=TALLY-PROP[I];
} /* end loop */
/* Clear the hint stuff. HINTLC(I) is how long he's been at LOC with cond bit
* I. HINTED(I) is true iff hint I has been used. */
for (I=1; I<=HNTMAX; I++) {
HINTED[I]=false;
HINTLC[I]=0;
} /* end loop */
/* Define some handy mnemonics. These correspond to object numbers. */
AXE=VOCWRD(12405,1);
BATTER=VOCWRD(201202005,1);
BEAR=VOCWRD(2050118,1);
BIRD=VOCWRD(2091804,1);
BLOOD=VOCWRD(212151504,1);
BOTTLE=VOCWRD(215202012,1);
CAGE=VOCWRD(3010705,1);
CAVITY=VOCWRD(301220920,1);
CHASM=VOCWRD(308011913,1);
CLAM=VOCWRD(3120113,1);
DOOR=VOCWRD(4151518,1);
DRAGON=VOCWRD(418010715,1);
DWARF=VOCWRD(423011806,1);
FISSUR=VOCWRD(609191921,1);
FOOD=VOCWRD(6151504,1);
GRATE=VOCWRD(718012005,1);
KEYS=VOCWRD(11052519,1);
KNIFE=VOCWRD(1114090605,1);
LAMP=VOCWRD(12011316,1);
MAGZIN=VOCWRD(1301070126,1);
MESSAG=VOCWRD(1305191901,1);
MIRROR=VOCWRD(1309181815,1);
OGRE=VOCWRD(15071805,1);
OIL=VOCWRD(150912,1);
OYSTER=VOCWRD(1525192005,1);
PILLOW=VOCWRD(1609121215,1);
PLANT=VOCWRD(1612011420,1);
PLANT2=PLANT+1;
RESER=VOCWRD(1805190518,1);
ROD=VOCWRD(181504,1);
ROD2=ROD+1;
SIGN=VOCWRD(19090714,1);
SNAKE=VOCWRD(1914011105,1);
STEPS=VOCWRD(1920051619,1);
TROLL=VOCWRD(2018151212,1);
TROLL2=TROLL+1;
URN=VOCWRD(211814,1);
VEND=VOCWRD(1755140409,1);
VOLCAN=VOCWRD(1765120301,1);
WATER=VOCWRD(1851200518,1);
/* Objects from 50 through whatever are treasures. Here are a few. */
AMBER=VOCWRD(113020518,1);
CHAIN=VOCWRD(308010914,1);
CHEST=VOCWRD(308051920,1);
COINS=VOCWRD(315091419,1);
EGGS=VOCWRD(5070719,1);
EMRALD=VOCWRD(513051801,1);
JADE=VOCWRD(10010405,1);
NUGGET=VOCWRD(7151204,1);
PEARL=VOCWRD(1605011812,1);
PYRAM=VOCWRD(1625180113,1);
RUBY=VOCWRD(18210225,1);
RUG=VOCWRD(182107,1);
SAPPH=VOCWRD(1901161608,1);
TRIDNT=VOCWRD(2018090405,1);
VASE=VOCWRD(22011905,1);
/* These are motion-verb numbers. */
BACK=VOCWRD(2010311,0);
CAVE=VOCWRD(3012205,0);
DPRSSN=VOCWRD(405161805,0);
ENTER=VOCWRD(514200518,0);
ENTRNC=VOCWRD(514201801,0);
LOOK=VOCWRD(12151511,0);
NUL=VOCWRD(14211212,0);
STREAM=VOCWRD(1920180501,0);
/* And some action verbs. */
FIND=VOCWRD(6091404,2);
INVENT=VOCWRD(914220514,2);
LOCK=VOCWRD(12150311,2);
SAY=VOCWRD(190125,2);
THROW=VOCWRD(2008181523,2);
/* Initialise the dwarves. DLOC is loc of dwarves, hard-wired in. ODLOC is
* prior loc of each dwarf, initially garbage. DALTLC is alternate initial loc
* for dwarf, in case one of them starts out on top of the adventurer. (No 2
* of the 5 initial locs are adjacent.) DSEEN is true if dwarf has seen him.
* DFLAG controls the level of activation of all this:
* 0 No dwarf stuff yet (wait until reaches Hall Of Mists)
* 1 Reached Hall Of Mists, but hasn't met first dwarf
* 2 Met first dwarf, others start moving, no knives thrown yet
* 3 A knife has been thrown (first set always misses)
* 3+ Dwarves are mad (increases their accuracy)
* Sixth dwarf is special (the pirate). He always starts at his chest's
* eventual location inside the maze. This loc is saved in CHLOC for ref.
* the dead end in the other maze has its loc stored in CHLOC2. */
CHLOC=114;
CHLOC2=140;
for (I=1; I<=6; I++) {
DSEEN[I]=false;
} /* end loop */
DFLAG=0;
DLOC[1]=19;
DLOC[2]=27;
DLOC[3]=33;
DLOC[4]=44;
DLOC[5]=64;
DLOC[6]=CHLOC;
DALTLC=18;
/* Other random flags and counters, as follows:
* ABBNUM How often we should print non-abbreviated descriptions
* BONUS Used to determine amount of bonus if he reaches closing
* CLOCK1 Number of turns from finding last treasure till closing
* CLOCK2 Number of turns from first warning till blinding flash
* CONDS Min value for cond(loc) if loc has any hints
* DETAIL How often we've said "not allowed to give more detail"
* DKILL Number of dwarves killed (unused in scoring, needed for msg)
* FOOBAR Current progress in saying "FEE FIE FOE FOO".
* HOLDNG Number of objects being carried
* IGO How many times he's said "go XXX" instead of "XXX"
* IWEST How many times he's said "west" instead of "w"
* KNFLOC 0 if no knife here, loc if knife here, -1 after caveat
* LIMIT Lifetime of lamp (not set here)
* MAXDIE Number of reincarnation messages available (up to 5)
* NUMDIE Number of times killed so far
* THRESH Next #turns threshhold (-1 if none)
* TRNDEX Index in TRNVAL of next threshhold (section 14 of database)
* TRNLUZ # points lost so far due to number of turns used
* TURNS Tallies how many commands he's given (ignores yes/no)
* Logicals were explained earlier */
TURNS=0;
TRNDEX=1;
THRESH= -1;
if(TRNVLS > 0)THRESH=MOD(TRNVAL[1],100000)+1;
TRNLUZ=0;
LMWARN=false;
IGO=0;
IWEST=0;
KNFLOC=0;
DETAIL=0;
ABBNUM=5;
for (I=0; I<=4; I++) {
{long x = 2*I+81; if(RTEXT[x] != 0)MAXDIE=I+1;}
} /* end loop */
NUMDIE=0;
HOLDNG=0;
DKILL=0;
FOOBAR=0;
BONUS=0;
CLOCK1=30;
CLOCK2=50;
CONDS=SETBIT(11);
SAVED=0;
CLOSNG=false;
PANIC=false;
CLOSED=false;
CLSHNT=false;
NOVICE=false;
SETUP=1;
/* if we can ever think of how, we should save it at this point */
return(0); /* then we won't actually return from initialisation */
}
/* Report on amount of arrays actually used, to permit reductions. */
static void report(void) {
for (K=1; K<=LOCSIZ; K++) {
KK=LOCSIZ+1-K;
if(LTEXT[KK] != 0) goto L1997;
/*etc*/ ;
} /* end loop */
OBJ=0;
L1997: for (K=1; K<=100; K++) {
if(PTEXT[K] != 0)OBJ=OBJ+1;
} /* end loop */
for (K=1; K<=TABNDX; K++) {
if(KTAB[K]/1000 == 2)VERB=KTAB[K]-2000;
} /* end loop */
for (K=1; K<=RTXSIZ; K++) {
J=RTXSIZ+1-K;
if(RTEXT[J] != 0) goto L1993;
/*etc*/ ;
} /* end loop */
L1993: SETPRM(1,LINUSE,LINSIZ);
SETPRM(3,TRVS,TRVSIZ);
SETPRM(5,TABNDX,TABSIZ);
SETPRM(7,KK,LOCSIZ);
SETPRM(9,OBJ,100);
SETPRM(11,VERB,VRBSIZ);
SETPRM(13,J,RTXSIZ);
SETPRM(15,CLSSES,CLSMAX);
SETPRM(17,HNTMAX,HNTSIZ);
SETPRM(19,TRNVLS,TRNSIZ);
//RSPEAK(267);
TYPE0();
}
static long init_reading, init_cksum;
static FILE *f;
static void quick_item(long*);
static void quick_array(long*, long);
static bool quick_init(void) {
extern char *getenv();
char *adv = getenv("ADVENTURE");
f = NULL;
if(adv)f = fopen(adv,READ_MODE);
if(f == NULL)f = fopen("adventure.data",READ_MODE);
if(f == NULL)return(false);
init_reading = true;
init_cksum = 1;
quick_io();
if(fread(&K,sizeof(long),1,f) == 1) init_cksum -= K; else init_cksum = 1;
fclose(f);
if(init_cksum != 0)printf("Checksum error!\n");
return(init_cksum == 0);
}
static void quick_save(void) {
//printf("Writing adventure.data...\n");
f = fopen("adventure.data",WRITE_MODE);
if(f == NULL){printf("Can't open file!\n"); return;}
init_reading = false;
init_cksum = 1;
quick_io();
fwrite(&init_cksum,sizeof(long),1,f);
fclose(f);
}
static void quick_io(void) {
quick_item(&LINUSE);
quick_item(&TRVS);
quick_item(&CLSSES);
quick_item(&TRNVLS);
quick_item(&TABNDX);
quick_item(&HNTMAX);
quick_array(PTEXT,100);
quick_array(RTEXT,RTXSIZ);
quick_array(CTEXT,CLSMAX);
quick_array(OBJSND,100);
quick_array(OBJTXT,100);
quick_array(STEXT,LOCSIZ);
quick_array(LTEXT,LOCSIZ);
quick_array(COND,LOCSIZ);
quick_array(KEY,LOCSIZ);
quick_array(LOCSND,LOCSIZ);
quick_array(LINES,LINSIZ);
quick_array(CVAL,CLSMAX);
quick_array(TTEXT,TRNSIZ);
quick_array(TRNVAL,TRNSIZ);
quick_array(TRAVEL,TRVSIZ);
quick_array(KTAB,TABSIZ);
quick_array(ATAB,TABSIZ);
quick_array(PLAC,100);
quick_array(FIXD,100);
quick_array(ACTSPK,VRBSIZ);
quick_array((long *)HINTS,(HNTMAX+1)*5-1);
}
static void quick_item(W)long *W; {
if(init_reading && fread(W,sizeof(long),1,f) != 1)return;
init_cksum = MOD(init_cksum*13+(*W),60000000);
if(!init_reading)fwrite(W,sizeof(long),1,f);
}
static void quick_array(A,N)long *A, N; { long I;
if(init_reading && fread(A,sizeof(long),N+1,f) != N+1)printf("Read error!\n");
for(I=1;I<=N;I++)init_cksum = MOD(init_cksum*13+A[I],60000000);
if(!init_reading && fwrite(A,sizeof(long),N+1,f)!=N+1)printf("Write error!\n");
}

BIN
lamp.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

2457
main.c

File diff suppressed because it is too large Load diff

17
main.h Normal file
View file

@ -0,0 +1,17 @@
#include <stdbool.h>
#define LINESIZE 100
typedef struct lcg_state
{
unsigned long a, c, m, x;
} lcg_state;
extern long ABB[], ATAB[], ATLOC[], BLKLIN, DFLAG, DLOC[], FIXED[], HOLDNG,
KTAB[], *LINES, LINK[], LNLENG, LNPOSN,
PARMS[], PLACE[], PTEXT[], RTEXT[], TABSIZ;
extern signed char rawbuf[LINESIZE], INLINE[LINESIZE+1], MAP1[], MAP2[];
extern FILE *logfp;
extern bool oldstyle;
extern int debug;
extern lcg_state lcgstate;

View file

@ -1,663 +0,0 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
"""
This is the open-adventure dungeon generator. It consumes a YAML description of
the dungeon and outputs a dungeon.h and dungeon.c pair of C code files.
The nontrivial part of this is the compilation of the YAML for
movement rules to the travel array that's actually used by
playermove().
"""
# pylint: disable=consider-using-f-string,line-too-long,invalid-name,missing-function-docstring,too-many-branches,global-statement,multiple-imports,too-many-locals,too-many-statements,too-many-nested-blocks,no-else-return,raise-missing-from,redefined-outer-name
import sys, yaml
YAML_NAME = "adventure.yaml"
H_NAME = "dungeon.h"
C_NAME = "dungeon.c"
H_TEMPLATE_PATH = "templates/dungeon.h.tpl"
C_TEMPLATE_PATH = "templates/dungeon.c.tpl"
DONOTEDIT_COMMENT = "/* Generated from adventure.yaml - do not hand-hack! */\n\n"
statedefines = ""
def make_c_string(string):
"""Render a Python string into C string literal format."""
if string is None:
return "NULL"
string = string.replace("\n", "\\n")
string = string.replace("\t", "\\t")
string = string.replace('"', '\\"')
string = string.replace("'", "\\'")
string = '"' + string + '"'
return string
def get_refs(l):
reflist = [x[0] for x in l]
ref_str = ""
for ref in reflist:
ref_str += " {},\n".format(ref)
ref_str = ref_str[:-1] # trim trailing newline
return ref_str
def get_string_group(strings):
template = """{{
.strs = {},
.n = {},
}}"""
if strings == []:
strs = "NULL"
else:
strs = (
"(const char* []) {" + ", ".join([make_c_string(s) for s in strings]) + "}"
)
n = len(strings)
sg_str = template.format(strs, n)
return sg_str
def get_arbitrary_messages(arb):
template = """ {},
"""
arb_str = ""
for item in arb:
arb_str += template.format(make_c_string(item[1]))
arb_str = arb_str[:-1] # trim trailing newline
return arb_str
def get_class_messages(cls):
template = """ {{
.threshold = {},
.message = {},
}},
"""
cls_str = ""
for item in cls:
threshold = item["threshold"]
message = make_c_string(item["message"])
cls_str += template.format(threshold, message)
cls_str = cls_str[:-1] # trim trailing newline
return cls_str
def get_turn_thresholds(trn):
template = """ {{
.threshold = {},
.point_loss = {},
.message = {},
}},
"""
trn_str = ""
for item in trn:
threshold = item["threshold"]
point_loss = item["point_loss"]
message = make_c_string(item["message"])
trn_str += template.format(threshold, point_loss, message)
trn_str = trn_str[:-1] # trim trailing newline
return trn_str
def get_locations(loc):
template = """ {{ // {}: {}
.description = {{
.small = {},
.big = {},
}},
.sound = {},
.loud = {},
}},
"""
loc_str = ""
for (i, item) in enumerate(loc):
short_d = make_c_string(item[1]["description"]["short"])
long_d = make_c_string(item[1]["description"]["long"])
sound = item[1].get("sound", "SILENT")
loud = "true" if item[1].get("loud") else "false"
loc_str += template.format(i, item[0], short_d, long_d, sound, loud)
loc_str = loc_str[:-1] # trim trailing newline
return loc_str
def get_objects(obj):
template = """ {{ // {}: {}
.words = {},
.inventory = {},
.plac = {},
.fixd = {},
.is_treasure = {},
.descriptions = (const char* []) {{
{}
}},
.sounds = (const char* []) {{
{}
}},
.texts = (const char* []) {{
{}
}},
.changes = (const char* []) {{
{}
}},
}},
"""
max_state = 0
obj_str = ""
for (i, item) in enumerate(obj):
attr = item[1]
try:
words_str = get_string_group(attr["words"])
except KeyError:
words_str = get_string_group([])
i_msg = make_c_string(attr["inventory"])
descriptions_str = ""
if attr["descriptions"] is None:
descriptions_str = " " * 12 + "NULL,"
else:
labels = []
for l_msg in attr["descriptions"]:
descriptions_str += " " * 12 + make_c_string(l_msg) + ",\n"
for label in attr.get("states", []):
labels.append(label)
descriptions_str = descriptions_str[:-1] # trim trailing newline
if labels:
global statedefines
statedefines += "/* States for %s */\n" % item[0]
for (n, label) in enumerate(labels):
statedefines += "#define %s\t%d\n" % (label, n)
max_state = max(max_state, n)
statedefines += "\n"
sounds_str = ""
if attr.get("sounds") is None:
sounds_str = " " * 12 + "NULL,"
else:
for l_msg in attr["sounds"]:
sounds_str += " " * 12 + make_c_string(l_msg) + ",\n"
sounds_str = sounds_str[:-1] # trim trailing newline
texts_str = ""
if attr.get("texts") is None:
texts_str = " " * 12 + "NULL,"
else:
for l_msg in attr["texts"]:
texts_str += " " * 12 + make_c_string(l_msg) + ",\n"
texts_str = texts_str[:-1] # trim trailing newline
changes_str = ""
if attr.get("changes") is None:
changes_str = " " * 12 + "NULL,"
else:
for l_msg in attr["changes"]:
changes_str += " " * 12 + make_c_string(l_msg) + ",\n"
changes_str = changes_str[:-1] # trim trailing newline
locs = attr.get("locations", ["LOC_NOWHERE", "LOC_NOWHERE"])
immovable = attr.get("immovable", False)
try:
if isinstance(locs, str):
locs = [locs, -1 if immovable else 0]
except IndexError:
sys.stderr.write("dungeon: unknown object location in %s\n" % locs)
sys.exit(1)
treasure = "true" if attr.get("treasure") else "false"
obj_str += template.format(
i,
item[0],
words_str,
i_msg,
locs[0],
locs[1],
treasure,
descriptions_str,
sounds_str,
texts_str,
changes_str,
)
obj_str = obj_str[:-1] # trim trailing newline
statedefines += "/* Maximum state value */\n#define MAX_STATE %d\n" % max_state
return obj_str
def get_obituaries(obit):
template = """ {{
.query = {},
.yes_response = {},
}},
"""
obit_str = ""
for o in obit:
query = make_c_string(o["query"])
yes = make_c_string(o["yes_response"])
obit_str += template.format(query, yes)
obit_str = obit_str[:-1] # trim trailing newline
return obit_str
def get_hints(hnt):
template = """ {{
.number = {},
.penalty = {},
.turns = {},
.question = {},
.hint = {},
}},
"""
hnt_str = ""
for member in hnt:
item = member["hint"]
number = item["number"]
penalty = item["penalty"]
turns = item["turns"]
question = make_c_string(item["question"])
hint = make_c_string(item["hint"])
hnt_str += template.format(number, penalty, turns, question, hint)
hnt_str = hnt_str[:-1] # trim trailing newline
return hnt_str
def get_condbits(locations):
cnd_str = ""
for (name, loc) in locations:
conditions = loc["conditions"]
hints = loc.get("hints") or []
flaglist = []
for flag in conditions:
if conditions[flag]:
flaglist.append(flag)
line = "|".join([("(1<<COND_%s)" % f) for f in flaglist])
trail = "|".join([("(1<<COND_H%s)" % f["name"]) for f in hints])
if trail:
line += "|" + trail
if line.startswith("|"):
line = line[1:]
if not line:
line = "0"
cnd_str += " " + line + ",\t// " + name + "\n"
return cnd_str
def get_motions(motions):
template = """ {{
.words = {},
}},
"""
mot_str = ""
for motion in motions:
contents = motion[1]
if contents["words"] is None:
words_str = get_string_group([])
else:
words_str = get_string_group(contents["words"])
mot_str += template.format(words_str)
global ignore
if not contents.get("oldstyle", True):
for word in contents["words"]:
if len(word) == 1:
ignore += word.upper()
return mot_str
def get_actions(actions):
template = """ {{
.words = {},
.message = {},
.noaction = {},
}},
"""
act_str = ""
for action in actions:
contents = action[1]
if contents["words"] is None:
words_str = get_string_group([])
else:
words_str = get_string_group(contents["words"])
if contents["message"] is None:
message = "NULL"
else:
message = make_c_string(contents["message"])
if contents.get("noaction") is None:
noaction = "false"
else:
noaction = "true"
act_str += template.format(words_str, message, noaction)
global ignore
if not contents.get("oldstyle", True):
for word in contents["words"]:
if len(word) == 1:
ignore += word.upper()
act_str = act_str[:-1] # trim trailing newline
return act_str
def bigdump(arr):
out = ""
for (i, _) in enumerate(arr):
if i % 10 == 0:
if out and out[-1] == " ":
out = out[:-1]
out += "\n "
out += str(arr[i]).lower() + ", "
out = out[:-2] + "\n"
return out
def buildtravel(locs, objs):
assert len(locs) <= 300
assert len(objs) <= 100
# THIS CODE IS WAAAY MORE COMPLEX THAN IT NEEDS TO BE. It's the
# result of a massive refactoring exercise that concentrated all
# the old nastiness in one spot. It hasn't been finally simplified
# because there's no need to do it until one of the assertions
# fails. Hint: if you try cleaning this up, the acceptance test is
# simple - the output dungeon.c must not change.
#
# This function first compiles the YAML to a form identical to the
# data in section 3 of the old adventure.text file, then a second
# stage unpacks that data into the travel array. Here are the
# rules of that intermediate form:
#
# Each row of data contains a location number (X), a second
# location number (Y), and a list of motion numbers (see section 4).
# each motion represents a verb which will go to Y if currently at X.
# Y, in turn, is interpreted as follows. Let M=Y/1000, N=Y mod 1000.
# If N<=300 it is the location to go to.
# If 300<N<=500 N-300 is used in a computed goto to
# a section of special code.
# If N>500 message N-500 from section 6 is printed,
# and he stays wherever he is.
# Meanwhile, M specifies the conditions on the motion.
# If M=0 it's unconditional.
# If 0<M<100 it is done with M% probability.
# If M=100 unconditional, but forbidden to dwarves.
# If 100<M<=200 he must be carrying object M-100.
# If 200<M<=300 must be carrying or in same room as M-200.
# If 300<M<=400 game.prop(M % 100) must *not* be 0.
# If 400<M<=500 game.prop(M % 100) must *not* be 1.
# If 500<M<=600 game.prop(M % 100) must *not* be 2, etc.
# If the condition (if any) is not met, then the next *different*
# "destination" value is used (unless it fails to meet *its* conditions,
# in which case the next is found, etc.). Typically, the next dest will
# be for one of the same verbs, so that its only use is as the alternate
# destination for those verbs. For instance:
# 15 110022 29 31 34 35 23 43
# 15 14 29
# This says that, from loc 15, any of the verbs 29, 31, etc., will take
# him to 22 if he's carrying object 10, and otherwise will go to 14.
# 11 303008 49
# 11 9 50
# This says that, from 11, 49 takes him to 8 unless game.prop[3]=0, in which
# case he goes to 9. Verb 50 takes him to 9 regardless of game.prop[3].
ltravel = []
verbmap = {}
for i, motion in enumerate(db["motions"]):
try:
for word in motion[1]["words"]:
verbmap[word.upper()] = i
except TypeError:
pass
def dencode(action, name):
"Decode a destination number"
if action[0] == "goto":
try:
return locnames.index(action[1])
except ValueError:
sys.stderr.write(
"dungeon: unknown location %s in goto clause of %s\n"
% (action[1], name)
)
raise ValueError
elif action[0] == "special":
return 300 + action[1]
elif action[0] == "speak":
try:
return 500 + msgnames.index(action[1])
except ValueError:
sys.stderr.write(
"dungeon: unknown location %s in carry clause of %s\n"
% (cond[1], name)
)
else:
print(cond)
raise ValueError
return "" # Pacify pylint
def cencode(cond, name):
if cond is None:
return 0
if cond == ["nodwarves"]:
return 100
elif cond[0] == "pct":
return cond[1]
elif cond[0] == "carry":
try:
return 100 + objnames.index(cond[1])
except ValueError:
sys.stderr.write(
"dungeon: unknown object name %s in carry clause of %s\n"
% (cond[1], name)
)
sys.exit(1)
elif cond[0] == "with":
try:
return 200 + objnames.index(cond[1])
except IndexError:
sys.stderr.write(
"dungeon: unknown object name %s in with clause of %s\n"
% (cond[1], name)
)
sys.exit(1)
elif cond[0] == "not":
try:
obj = objnames.index(cond[1])
if isinstance(cond[2], int):
state = cond[2]
elif cond[2] in objs[obj][1].get("states", []):
state = objs[obj][1].get("states").index(cond[2])
else:
for (i, stateclause) in enumerate(objs[obj][1]["descriptions"]):
if isinstance(stateclause, list):
if stateclause[0] == cond[2]:
state = i
break
else:
sys.stderr.write(
"dungeon: unmatched state symbol %s in not clause of %s\n"
% (cond[2], name)
)
sys.exit(0)
return 300 + obj + 100 * state
except ValueError:
sys.stderr.write(
"dungeon: unknown object name %s in not clause of %s\n"
% (cond[1], name)
)
sys.exit(1)
else:
print(cond)
raise ValueError
for (i, (name, loc)) in enumerate(locs):
if "travel" in loc:
for rule in loc["travel"]:
tt = [i]
dest = dencode(rule["action"], name) + 1000 * cencode(
rule.get("cond"), name
)
tt.append(dest)
tt += [motionnames[verbmap[e]].upper() for e in rule["verbs"]]
if not rule["verbs"]:
tt.append(1) # Magic dummy entry for null rules
ltravel.append(tuple(tt))
# At this point the ltravel data is in the Section 3
# representation from the FORTRAN version. Next we perform the
# same mapping into what used to be the runtime format.
travel = [[0, "LOC_NOWHERE", 0, 0, 0, 0, 0, 0, "false", "false"]]
tkey = [0]
oldloc = 0
while ltravel:
rule = list(ltravel.pop(0))
loc = rule.pop(0)
newloc = rule.pop(0)
if loc != oldloc:
tkey.append(len(travel))
oldloc = loc
elif travel:
travel[-1][-1] = "false" if travel[-1][-1] == "true" else "true"
while rule:
cond = newloc // 1000
nodwarves = cond == 100
if cond == 0:
condtype = "cond_goto"
condarg1 = condarg2 = 0
elif cond < 100:
condtype = "cond_pct"
condarg1 = cond
condarg2 = 0
elif cond == 100:
condtype = "cond_goto"
condarg1 = 100
condarg2 = 0
elif cond <= 200:
condtype = "cond_carry"
condarg1 = objnames[cond - 100]
condarg2 = 0
elif cond <= 300:
condtype = "cond_with"
condarg1 = objnames[cond - 200]
condarg2 = 0
else:
condtype = "cond_not"
condarg1 = cond % 100
condarg2 = (cond - 300) // 100.0
dest = newloc % 1000
if dest <= 300:
desttype = "dest_goto"
destval = locnames[dest]
elif dest > 500:
desttype = "dest_speak"
destval = msgnames[dest - 500]
else:
desttype = "dest_special"
destval = locnames[dest - 300]
travel.append(
[
len(tkey) - 1,
locnames[len(tkey) - 1],
rule.pop(0),
condtype,
condarg1,
condarg2,
desttype,
destval,
"true" if nodwarves else "false",
"false",
]
)
travel[-1][-1] = "true"
return (travel, tkey)
def get_travel(travel):
template = """ {{ // from {}: {}
.motion = {},
.condtype = {},
.condarg1 = {},
.condarg2 = {},
.desttype = {},
.destval = {},
.nodwarves = {},
.stop = {},
}},
"""
out = ""
for entry in travel:
out += template.format(*entry)
out = out[:-1] # trim trailing newline
return out
if __name__ == "__main__":
with open(YAML_NAME, "r", encoding="ascii", errors="surrogateescape") as f:
db = yaml.safe_load(f)
locnames = [x[0] for x in db["locations"]]
msgnames = [el[0] for el in db["arbitrary_messages"]]
objnames = [el[0] for el in db["objects"]]
motionnames = [el[0] for el in db["motions"]]
(travel, tkey) = buildtravel(db["locations"], db["objects"])
ignore = ""
try:
with open(
H_TEMPLATE_PATH, "r", encoding="ascii", errors="surrogateescape"
) as htf:
# read in dungeon.h template
h_template = DONOTEDIT_COMMENT + htf.read()
with open(
C_TEMPLATE_PATH, "r", encoding="ascii", errors="surrogateescape"
) as ctf:
# read in dungeon.c template
c_template = DONOTEDIT_COMMENT + ctf.read()
except IOError as e:
print("ERROR: reading template failed ({})".format(e.strerror))
sys.exit(-1)
c = c_template.format(
h_file=H_NAME,
arbitrary_messages=get_arbitrary_messages(db["arbitrary_messages"]),
classes=get_class_messages(db["classes"]),
turn_thresholds=get_turn_thresholds(db["turn_thresholds"]),
locations=get_locations(db["locations"]),
objects=get_objects(db["objects"]),
obituaries=get_obituaries(db["obituaries"]),
hints=get_hints(db["hints"]),
conditions=get_condbits(db["locations"]),
motions=get_motions(db["motions"]),
actions=get_actions(db["actions"]),
tkeys=bigdump(tkey),
travel=get_travel(travel),
ignore=ignore,
dwarflocs=", ".join(db["dwarflocs"]) + ",",
)
# 0-origin index of birds's last song. Bird should
# die after player hears this.
deathbird = len(dict(db["objects"])["BIRD"]["sounds"]) - 1
h = h_template.format(
num_locations=len(db["locations"]) - 1,
num_objects=len(db["objects"]) - 1,
num_hints=len(db["hints"]),
num_classes=len(db["classes"]) - 1,
num_deaths=len(db["obituaries"]),
num_thresholds=len(db["turn_thresholds"]),
num_motions=len(db["motions"]),
num_actions=len(db["actions"]),
num_travel=len(travel),
num_keys=len(tkey),
bird_endstate=deathbird,
arbitrary_messages=get_refs(db["arbitrary_messages"]),
locations=get_refs(db["locations"]),
objects=get_refs(db["objects"]),
motions=get_refs(db["motions"]),
actions=get_refs(db["actions"]),
state_definitions=statedefines,
ndwarflocs=str(len(db["dwarflocs"])),
)
with open(H_NAME, "w", encoding="ascii", errors="surrogateescape") as hf:
hf.write(h)
with open(C_NAME, "w", encoding="ascii", errors="surrogateescape") as cf:
cf.write(c)
# end

View file

@ -1,221 +0,0 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
"""\
usage: make_graph.py [-a] [-d] [-m] [-s] [-v]
Make a DOT graph of Colossal Cave.
-a = emit graph of entire dungeon
-d = emit graph of maze all different
-f = emit graph of forest locations
-m = emit graph of maze all alike
-s = emit graph of non-forest surface locations
-v = include internal symbols in room labels
"""
# pylint: disable=consider-using-f-string,line-too-long,invalid-name,missing-function-docstring,multiple-imports,redefined-outer-name
import sys, getopt, yaml
def allalike(loc):
"Select out loci related to the Maze All Alike"
return location_lookup[loc]["conditions"].get("ALLALIKE")
def alldifferent(loc):
"Select out loci related to the Maze All Alike"
return location_lookup[loc]["conditions"].get("ALLDIFFERENT")
def surface(loc):
"Select out surface locations"
return location_lookup[loc]["conditions"].get("ABOVE")
def forest(loc):
return location_lookup[loc]["conditions"].get("FOREST")
def abbreviate(d):
m = {
"NORTH": "N",
"EAST": "E",
"SOUTH": "S",
"WEST": "W",
"UPWAR": "U",
"DOWN": "D",
}
return m.get(d, d)
def roomlabel(loc):
"Generate a room label from the description, if possible"
loc_descriptions = location_lookup[loc]["description"]
description = ""
if debug:
description = loc[4:]
longd = loc_descriptions["long"]
short = loc_descriptions["maptag"] or loc_descriptions["short"]
if short is None and longd is not None and len(longd) < 20:
short = loc_descriptions["long"]
if short is not None:
if short.startswith("You're "):
short = short[7:]
if short.startswith("You are "):
short = short[8:]
if (
short.startswith("in ")
or short.startswith("at ")
or short.startswith("on ")
):
short = short[3:]
if short.startswith("the "):
short = short[4:]
if short[:3] in {"n/s", "e/w"}:
short = short[:3].upper() + short[3:]
elif short[:2] in {"ne", "sw", "se", "nw"}:
short = short[:2].upper() + short[2:]
else:
short = short[0].upper() + short[1:]
if debug:
description += "\\n"
description += short
if loc in startlocs:
description += "\\n(" + ",".join(startlocs[loc]).lower() + ")"
return description
# A forwarder is a location that you can't actually stop in - when you go there
# it ships some message (which is the point) then shifts you to a next location.
# A forwarder has a zero-length array of notion verbs in its travel section.
#
# Here is an example forwarder declaration:
#
# - LOC_GRUESOME:
# description:
# long: 'There is now one more gruesome aspect to the spectacular vista.'
# short: !!null
# maptag: !!null
# conditions: {DEEP: true}
# travel: [
# {verbs: [], action: [goto, LOC_NOWHERE]},
# ]
def is_forwarder(loc):
"Is a location a forwarder?"
travel = location_lookup[loc]["travel"]
return len(travel) == 1 and len(travel[0]["verbs"]) == 0
def forward(loc):
"Chase a location through forwarding links."
while is_forwarder(loc):
loc = location_lookup[loc]["travel"][0]["action"][1]
return loc
def reveal(objname):
"Should this object be revealed when mapping?"
if "OBJ_" in objname:
return False
if objname == "VEND":
return True
obj = object_lookup[objname]
return not obj.get("immovable")
if __name__ == "__main__":
with open("adventure.yaml", "r", encoding="ascii", errors="surrogateescape") as f:
db = yaml.safe_load(f)
location_lookup = dict(db["locations"])
object_lookup = dict(db["objects"])
try:
(options, arguments) = getopt.getopt(sys.argv[1:], "adfmsv")
except getopt.GetoptError as e:
print(e)
sys.exit(1)
subset = allalike
debug = False
for (switch, val) in options:
if switch == "-a":
# pylint: disable=unnecessary-lambda-assignment
subset = lambda loc: True
elif switch == "-d":
subset = alldifferent
elif switch == "-f":
subset = forest
elif switch == "-m":
subset = allalike
elif switch == "-s":
subset = surface
elif switch == "-v":
debug = True
else:
sys.stderr.write(__doc__)
raise SystemExit(1)
startlocs = {}
for obj in db["objects"]:
objname = obj[0]
location = obj[1].get("locations")
if location != "LOC_NOWHERE" and reveal(objname):
if location in startlocs:
startlocs[location].append(objname)
else:
startlocs[location] = [objname]
# Compute reachability, using forwards.
# Dictionary key is (from, to) iff its a valid link,
# value is corresponding motion verbs.
links = {}
nodes = []
for (loc, attrs) in db["locations"]:
nodes.append(loc)
travel = attrs["travel"]
if len(travel) > 0:
for dest in travel:
verbs = [abbreviate(x) for x in dest["verbs"]]
if len(verbs) == 0:
continue
action = dest["action"]
if action[0] == "goto":
dest = forward(action[1])
if not (subset(loc) or subset(dest)):
continue
links[(loc, dest)] = verbs
neighbors = set()
for loc in nodes:
for (f, t) in links:
if f == "LOC_NOWHERE" or t == "LOC_NOWHERE":
continue
if (f == loc and subset(t)) or (t == loc and subset(f)):
if loc not in neighbors:
neighbors.add(loc)
print("digraph G {")
for loc in nodes:
if not is_forwarder(loc):
node_label = roomlabel(loc)
if subset(loc):
print(' %s [shape=box,label="%s"]' % (loc[4:], node_label))
elif loc in neighbors:
print(' %s [label="%s"]' % (loc[4:], node_label))
# Draw arcs
for (f, t) in links:
arc = "%s -> %s" % (f[4:], t[4:])
label = ",".join(links[(f, t)]).lower()
if len(label) > 0:
arc += ' [label="%s"]' % label
print(" " + arc)
print("}")
# end

1722
misc.c

File diff suppressed because it is too large Load diff

77
misc.h Normal file
View file

@ -0,0 +1,77 @@
#include <time.h>
#include <stdio.h>
/* b is not needed for POSIX but harmless */
#define READ_MODE "rb"
#define WRITE_MODE "wb"
extern void fSPEAK(long);
#define SPEAK(N) fSPEAK(N)
extern void fPSPEAK(long,long);
#define PSPEAK(MSG,SKIP) fPSPEAK(MSG,SKIP)
extern void fRSPEAK(long);
#define RSPEAK(I) fRSPEAK(I)
extern void fSETPRM(long,long,long);
#define SETPRM(FIRST,P1,P2) fSETPRM(FIRST,P1,P2)
extern void fGETIN(FILE *,long*,long*,long*,long*);
#define GETIN(input,WORD1,WORD1X,WORD2,WORD2X) fGETIN(input,&WORD1,&WORD1X,&WORD2,&WORD2X)
extern long fYES(FILE *,long,long,long);
#define YES(input,X,Y,Z) fYES(input,X,Y,Z)
extern long fGETNUM(FILE *);
#define GETNUM(K) fGETNUM(K)
extern long fGETTXT(long,long,long,long);
#define GETTXT(SKIP,ONEWRD,UPPER,HASH) fGETTXT(SKIP,ONEWRD,UPPER,HASH)
extern long fMAKEWD(long);
#define MAKEWD(LETTRS) fMAKEWD(LETTRS)
extern void fPUTTXT(long,long*,long,long);
#define PUTTXT(WORD,STATE,CASE,HASH) fPUTTXT(WORD,&STATE,CASE,HASH)
extern void fSHFTXT(long,long);
#define SHFTXT(FROM,DELTA) fSHFTXT(FROM,DELTA)
extern void fTYPE0();
#define TYPE0() fTYPE0()
extern void fSAVWDS(long*,long*,long*,long*,long*,long*,long*);
#define SAVWDS(W1,W2,W3,W4,W5,W6,W7) fSAVWDS(&W1,&W2,&W3,&W4,&W5,&W6,&W7)
extern void fSAVARR(long*,long);
#define SAVARR(ARR,N) fSAVARR(ARR,N)
extern void fSAVWRD(long,long*);
#define SAVWRD(OP,WORD) fSAVWRD(OP,&WORD)
extern long fVOCAB(long,long);
#define VOCAB(ID,INIT) fVOCAB(ID,INIT)
extern void fDSTROY(long);
#define DSTROY(OBJECT) fDSTROY(OBJECT)
extern void fJUGGLE(long);
#define JUGGLE(OBJECT) fJUGGLE(OBJECT)
extern void fMOVE(long,long);
#define MOVE(OBJECT,WHERE) fMOVE(OBJECT,WHERE)
extern long fPUT(long,long,long);
#define PUT(OBJECT,WHERE,PVAL) fPUT(OBJECT,WHERE,PVAL)
extern void fCARRY(long,long);
#define CARRY(OBJECT,WHERE) fCARRY(OBJECT,WHERE)
extern void fDROP(long,long);
#define DROP(OBJECT,WHERE) fDROP(OBJECT,WHERE)
extern long fATDWRF(long);
#define ATDWRF(WHERE) fATDWRF(WHERE)
extern long fSETBIT(long);
#define SETBIT(BIT) fSETBIT(BIT)
extern long fTSTBIT(long,long);
#define TSTBIT(MASK,BIT) fTSTBIT(MASK,BIT)
extern long fRNDVOC(long,long);
#define RNDVOC(CHAR,FORCE) fRNDVOC(CHAR,FORCE)
extern void fBUG(long);
#define BUG(NUM) fBUG(NUM)
extern void fMAPLIN(FILE *);
#define MAPLIN(FIL) fMAPLIN(FIL)
extern void fTYPE();
#define TYPE() fTYPE()
extern void fMPINIT();
#define MPINIT() fMPINIT()
extern void fSAVEIO(long,long,long*);
#define SAVEIO(OP,IN,ARR) fSAVEIO(OP,IN,ARR)
#define DATIME(D,T) do {struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); D=ts.tv_sec, T=ts.tv_nsec;} while (0)
extern long fIABS(long);
#define IABS(N) fIABS(N)
extern long fMOD(long,long);
#define MOD(N,M) fMOD(N,M)
extern void set_seed(long);
extern unsigned long get_next_lcg_value(void);
extern long randrange(long);

View file

@ -1,229 +0,0 @@
= Open Adventure Maintainer's Notes =
by Eric S. Raymond
// SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
// SPDX-License-Identifier: CC-BY-4.0
In which we explain what has been done to this code since Don Woods
authorized us to ship it under an open-source license. There's a
separate link:history.html[history] describing how it came to us.
== Who we are ==
The principal maintainers of this code are Eric S. Raymond and Jason
Ninneman. Eric received Don Woods's encouragement to update and ship
the game; Jason signed on early in the process to help. The assistance
of Peje Nilsson in restructuring some particularly grotty gotos is
gratefully acknowledged. Petr Voropaev contributed fuzz testing and
code cleanups. Aaron Traas did a lot of painstaking work to improve
test coverage, and factored out the last handful of gotos. Ryan
Sarson nudged us into fixing a longstanding minor bug in the
handling of incorrect magic-word sequences,
== Nomenclature ==
This project is called "Open Adventure" because it's not at all clear
to number Adventure past 2.5 without misleading or causing
collisions. Various of the non-mainline versions have claimed to be
versions 3, 4, 5, 6, 7 and for all I know higher than that. It seems
best just to start a new numbering series while acknowledging the
links back.
We have reverted to "advent" for the binary to avoid a name collision
with the BSD Games version.
== Philosophy ==
Extreme care has been taken not to make changes that would alter the
logic of the game as we received it from Don Woods, except to fix
glitches that were clearly bugs. By policy, all user-visible
changes to gameplay must be revertible with the -o (oldstyle) option.
It is a goal of this project to exactly preserve the *intended
behavior* of 430-point Adventure, but the implementation of it is fair
game for improvement. In particular, we are concerned to move it to a
form that is (a) readable, and (b) friendly to forward translation to
future languages. It has already survived a move from FORTRAN to C; a
future as a Python or Go translation seems possible, even probable.
Compatibility with the 2.5 source we found has been checked by
building a version patched minimally to support the seed command and
running it against the entire test suite, which has 100% code
coverage.
== Functional changes ==
Bug fixes:
* The caged bird used to be counted as two items in your inventory.
* Reading the relocated Witt's End sign in the endgame didn't work right.
* Oyster was readable after first gotten even when not carried.
* Response to an attempt to unlock the oyster while carrying it was incorrect.
* Behavior when saying the giant's magic words before having seen them
wasn't quite correct - the game responded as though the player had
already read them ("...can't you read?"). The new message is "Well,
that was remarkably pointless!" The -o option reverts this change.
* Attempting to extinguish an unlit urn caused it to lose its oil.
* "A crystal bridge now spans the fissure." (progressive present) was
incorrect most places it appeared and has been replaced by "A crystal
bridge spans the fissure." (timeless present).
* A few minor typos have been corrected: absence of capitalization on
"Swiss" and "Persian", inconsistent spelling of "imbedded" vs. "embedded",
"eying" for "eyeing", "thresholds" for "threshholds", "pencilled"
for "penciled".
* Under odd circumstances (dropping rug or vase outdoors) the game could
formerly say "floor" when it should say "ground" (or "dirt", or
something).
* The "knives vanish" message could formerly be emitted when "I see no
knife here." would be appropriate.
Enhancements:
By default, advent issues "> " as a command prompt. This feature
became common in many variants after the original 350-point version,
but was never backported into Crowther & Woods's main line before now.
The "-o" (oldstyle) option reverts the behavior.
There is a set of standard one-letter command aliases conventional in modern
text adventure games; 'l' and 'x'; for 'look' (or 'examine'), 'z' to do nothing
for a turn, 'i' for 'inventory', 'g' for 'get', and 'd' for 'drop'. The 'd'
alias collides with 'd' for 'down', but the others have been implemented.
The "-o" (oldstyle) option disables them.
Unrecognized words are no longer truncated to 5 characters and
uppercased when they are echoed. The "-o" (oldstyle) option restores
this behavior.
A "seed" command has been added. This is not intended for human use
but as a way for game logs to set the PRNG (pseudorandom-number generator) so
that random events (dwarf & pirate appearances, the bird's magic word)
will be reproducible.
A "version" command has been added. This has no effect on gameplay.
The text displayed by the "news" command has been updated.
A -l command-line option has been added. When this is given (with a
file path argument) each command entered will be logged to the
specified file. Additionally, a generated "seed" command will be put
early in the file capturing the randomized start state of the PRNG
so that replays of the log will be reproducible.
Using "seed" and -l, the distribution now includes a regression-test
suite for the game. Any log captured with -l (and thus containing
a "seed" command) will replay reliably, including random events.
The adventure.text file is no longer required at runtime. Instead, an
adventure.yaml file is compiled at build time to a source module
containing C structures, which is then linked to the advent
binary. The YAML is drastically easier to read and edit than
the old ad-hoc format of adventure.txt.
The game-save format has changed. This was done to simplify the
FORTRAN-derived code that formerly implemented the save/restore
functions; without C's fread(3)/fwrite() and structs it was
necessarily pretty ugly by modern standards. Encryption and
checksumming have been discarded - it's pointless to try
tamper-proofing saves when everyone has the source code. However
the game still integrity-checks savefiles on resume, including an
abort if the endianness of the restoring machine does not match that of
the saving machine. There is a magic-cookie header on the saves so
in theory they could be identified by programs like file(1).
Save and resume filenames are stripped of leading and trailing
whitespace before processing.
A -r command-line option has been added. When it is given (with a file
path argument) it is functionally equivalent to a RESTORE command.
An -a command-line option has been added (conditionally on
ADVENT_AUTOSAVE) for use in BBS door systems. When this option is
given, the game roads from the specified filename argument on startup
and saves to it on quit or a received signal. There is a new nmessage
to inform the user about this.
The game can be built in a mode that entirely disables save/resume
(-DADVENT_NOSAVE). If the game had been built this way, a diagnostic is
emitted if you try to save or resume.
== Translation ==
The 2.5 code was a mechanical C translation of a FORTRAN original.
There were gotos everywhere and the code was, though functional,
ugly and quite unreadable.
Jason Ninneman and I have moved it to what is almost, but not quite,
idiomatic modern C. We refactored the right way, checking correctness
against a comprehensive test suite that we built first and verified
with coverage tools (there is effectively 100% code coverage). This is
what you are running when you do "make check".
The move to modern C entailed some structural changes. The most
important was the refactoring of over 350 gotos into if/loop/break
structures. We also abolished almost all shared globals; the main one
left is a struct holding the game's saveable/restorable state.
The original code was greatly complicated by a kind of bit-packing
that was performed because the FORTRAN it was written in had no string
type. Text from the adventure.text file was compiled into sequences
of sixbit code points in a restricted character set, packed 5 to a
32-bit word (and it seems clear from the code that words were originally
*6* chars each packed into a PDP-10 36-bit word). A command noun or
verb was one of these words, and what would be string operations in a
more recent language were all done on sequences of these words.
We have removed all this bit-packing cruft in favor of proper C
strings. C strings may be a weak and leaky abstraction, but this is
one of the rare cases in which they are an obvious improvement over
what they're displacing...
We have also conducted extensive fuzz testing on the game using
afl (American Fuzzy Lop). We've found and fixed some crashers in
our new code (which occasionally uses malloc(3)), but none as yet
in Don's old code (which didn't).
After version 1.11, correctness was carefully checked against the
behavior of a binary from before the big refactoring.
The code falls short of being fully modern C in the following
ways:
* We have not attempted to translate the old code to pointer-based
idioms (as opposed, in particular, to integer-based array indexing).
We don't need whatever minor performance gains this might collect,
and the choice to refrain will make forward translation into future
languages easier.
* Linked lists (for objects at a location) are implemented using an array
of link indices. This is a surviving FORTRANism that is quite unlike
normal practice in C or any more modern language. We have not tried
to fix it because doing so would (a) be quite difficult, and (b)
compromise forward-portability to other languages.
* Much of the code still assumes one-origin array indexing. Thus,
arrays are a cell larger than they strictly need to be and cell 0 is
unused.
We have made exactly one minor architectural change. In addition to the
old code's per-object state-description messages, we now have a per-object
message series for state *changes*. This makes it possible to pull a fair
amount of text out of the arbitrary-messages list and associate those
messages with the objects that conceptually own them.
== Development status ==
We consider this project finished. All issues and TODOs have been
cleared, behavior has been carefully checked against original ADVENT,
no future demand for new features is expected, and the test suite has
100% code coverage. If new bugs appear as the toolchain bit-rots out
from under underneath, we will fix those problems.
// end

View file

@ -1,267 +0,0 @@
/*
* Saving and resuming.
*
* (ESR) This replaces a bunch of particularly nasty FORTRAN-derived code;
* see the history.adoc file in the source distribution for discussion.
*
* SPDX-FileCopyrightText: (C) 1977, 2005 by Will Crowther and Don Woods
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <ctype.h>
#include <inttypes.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "advent.h"
/*
* Use this to detect endianness mismatch. Can't be unchanged by byte-swapping.
*/
#define ENDIAN_MAGIC 2317
struct save_t save;
#define IGNORE(r) \
do { \
if (r) { \
} \
} while (0)
int savefile(FILE *fp) {
/* Save game to file. No input or output from user. */
memcpy(&save.magic, ADVENT_MAGIC, sizeof(ADVENT_MAGIC));
if (save.version == 0) {
save.version = SAVE_VERSION;
}
if (save.canary == 0) {
save.canary = ENDIAN_MAGIC;
}
save.game = game;
IGNORE(fwrite(&save, sizeof(struct save_t), 1, fp));
return (0);
}
/* Suspend and resume */
static char *strip(char *name) {
// Trim leading whitespace
while (isspace((unsigned char)*name)) {
name++; // LCOV_EXCL_LINE
}
if (*name != '\0') {
// Trim trailing whitespace;
// might be left there by autocomplete
char *end = name + strlen(name) - 1;
while (end > name && isspace((unsigned char)*end)) {
end--;
}
// Write new null terminator character
end[1] = '\0';
}
return name;
}
int suspend(void) {
/* Suspend. Offer to save things in a file, but charging
* some points (so can't win by using saved games to retry
* battles or to start over after learning zzword).
* If ADVENT_NOSAVE is defined, gripe instead. */
#if defined ADVENT_NOSAVE || defined ADVENT_AUTOSAVE
rspeak(SAVERESUME_DISABLED);
return GO_TOP;
#endif
FILE *fp = NULL;
rspeak(SUSPEND_WARNING);
if (!yes_or_no(arbitrary_messages[THIS_ACCEPTABLE],
arbitrary_messages[OK_MAN],
arbitrary_messages[OK_MAN])) {
return GO_CLEAROBJ;
}
game.saved = game.saved + 5;
while (fp == NULL) {
char *name = myreadline("\nFile name: ");
if (name == NULL) {
return GO_TOP;
}
name = strip(name);
if (strlen(name) == 0) {
return GO_TOP; // LCOV_EXCL_LINE
}
fp = fopen(strip(name), WRITE_MODE);
if (fp == NULL) {
printf("Can't open file %s, try again.\n", name);
}
free(name);
}
savefile(fp);
fclose(fp);
rspeak(RESUME_HELP);
exit(EXIT_SUCCESS);
}
int resume(void) {
/* Resume. Read a suspended game back from a file.
* If ADVENT_NOSAVE is defined, gripe instead. */
#if defined ADVENT_NOSAVE || defined ADVENT_AUTOSAVE
rspeak(SAVERESUME_DISABLED);
return GO_TOP;
#endif
FILE *fp = NULL;
if (game.loc != LOC_START || game.locs[LOC_START].abbrev != 1) {
rspeak(RESUME_ABANDON);
if (!yes_or_no(arbitrary_messages[THIS_ACCEPTABLE],
arbitrary_messages[OK_MAN],
arbitrary_messages[OK_MAN])) {
return GO_CLEAROBJ;
}
}
while (fp == NULL) {
char *name = myreadline("\nFile name: ");
if (name == NULL) {
return GO_TOP;
}
name = strip(name);
if (strlen(name) == 0) {
return GO_TOP; // LCOV_EXCL_LINE
}
fp = fopen(name, READ_MODE);
if (fp == NULL) {
printf("Can't open file %s, try again.\n", name);
}
free(name);
}
return restore(fp);
}
int restore(FILE *fp) {
/* Read and restore game state from file, assuming
* sane initial state.
* If ADVENT_NOSAVE is defined, gripe instead. */
#ifdef ADVENT_NOSAVE
rspeak(SAVERESUME_DISABLED);
return GO_TOP;
#endif
IGNORE(fread(&save, sizeof(struct save_t), 1, fp));
fclose(fp);
if (memcmp(save.magic, ADVENT_MAGIC, sizeof(ADVENT_MAGIC)) != 0 ||
save.canary != ENDIAN_MAGIC) {
rspeak(BAD_SAVE);
} else if (save.version != SAVE_VERSION) {
rspeak(VERSION_SKEW, save.version / 10, MOD(save.version, 10),
SAVE_VERSION / 10, MOD(SAVE_VERSION, 10));
} else if (!is_valid(save.game)) {
rspeak(SAVE_TAMPERING);
exit(EXIT_SUCCESS);
} else {
game = save.game;
}
return GO_TOP;
}
bool is_valid(struct game_t valgame) {
/* Save files can be roughly grouped into three groups:
* With valid, reachable state, with valid, but unreachable
* state and with invalid state. We check that state is
* valid: no states are outside minimal or maximal value
*/
/* Prevent division by zero */
if (valgame.abbnum == 0) {
return false; // LCOV_EXCL_LINE
}
/* Check for RNG overflow. Truncate */
if (valgame.lcg_x >= LCG_M) {
return false;
}
/* Bounds check for locations */
if (valgame.chloc < -1 || valgame.chloc > NLOCATIONS ||
valgame.chloc2 < -1 || valgame.chloc2 > NLOCATIONS ||
valgame.loc < 0 || valgame.loc > NLOCATIONS || valgame.newloc < 0 ||
valgame.newloc > NLOCATIONS || valgame.oldloc < 0 ||
valgame.oldloc > NLOCATIONS || valgame.oldlc2 < 0 ||
valgame.oldlc2 > NLOCATIONS) {
return false; // LCOV_EXCL_LINE
}
/* Bounds check for location arrays */
for (int i = 0; i <= NDWARVES; i++) {
if (valgame.dwarves[i].loc < -1 ||
valgame.dwarves[i].loc > NLOCATIONS ||
valgame.dwarves[i].oldloc < -1 ||
valgame.dwarves[i].oldloc > NLOCATIONS) {
return false; // LCOV_EXCL_LINE
}
}
for (int i = 0; i <= NOBJECTS; i++) {
if (valgame.objects[i].place < -1 ||
valgame.objects[i].place > NLOCATIONS ||
valgame.objects[i].fixed < -1 ||
valgame.objects[i].fixed > NLOCATIONS) {
return false; // LCOV_EXCL_LINE
}
}
/* Bounds check for dwarves */
if (valgame.dtotal < 0 || valgame.dtotal > NDWARVES ||
valgame.dkill < 0 || valgame.dkill > NDWARVES) {
return false; // LCOV_EXCL_LINE
}
/* Validate that we didn't die too many times in save */
if (valgame.numdie >= NDEATHS) {
return false; // LCOV_EXCL_LINE
}
/* Recalculate tally, throw the towel if in disagreement */
int temp_tally = 0;
for (int treasure = 1; treasure <= NOBJECTS; treasure++) {
if (objects[treasure].is_treasure) {
if (OBJECT_IS_NOTFOUND2(valgame, treasure)) {
++temp_tally;
}
}
}
if (temp_tally != valgame.tally) {
return false; // LCOV_EXCL_LINE
}
/* Check that properties of objects aren't beyond expected */
for (obj_t obj = 0; obj <= NOBJECTS; obj++) {
if (PROP_IS_INVALID(valgame.objects[obj].prop)) {
return false; // LCOV_EXCL_LINE
}
}
/* Check that values in linked lists for objects in locations are inside
* bounds */
for (loc_t loc = LOC_NOWHERE; loc <= NLOCATIONS; loc++) {
if (valgame.locs[loc].atloc < NO_OBJECT ||
valgame.locs[loc].atloc > NOBJECTS * 2) {
return false; // LCOV_EXCL_LINE
}
}
for (obj_t obj = 0; obj <= NOBJECTS * 2; obj++) {
if (valgame.link[obj] < NO_OBJECT ||
valgame.link[obj] > NOBJECTS * 2) {
return false; // LCOV_EXCL_LINE
}
}
return true;
}
/* end */

255
score.c
View file

@ -1,162 +1,117 @@
/*
* Scoring and wrap-up.
*
* SPDX-FileCopyrightText: (C) 1977, 2005 by Will Crowther and Don Woods
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "advent.h"
#include "dungeon.h"
#include <stdlib.h>
#include "misc.h"
#include "main.h"
#include "share.h"
static int mxscor; /* ugh..the price for having score() not exit. */
/*
* scoring and wrap-up
*/
int score(enum termination mode) {
/* mode is 'scoregame' if scoring, 'quitgame' if quitting, 'endgame' if
* died or won */
int score = 0;
void score(long MODE) {
/* <0 if scoring, >0 if quitting, =0 if died or won */
/* The present scoring algorithm is as follows:
* Objective: Points: Present total possible:
* Getting well into cave 25 25
* Each treasure < chest 12 60
* Treasure chest itself 14 14
* Each treasure > chest 16 224
* Surviving (MAX-NUM)*10 30
* Not quitting 4 4
* Reaching "game.closng" 25 25
* "Closed": Quit/Killed 10
* Klutzed 25
* Wrong way 30
* Success 45 45
* Came to Witt's End 1 1
* Round out the total 2 2
* TOTAL: 430
* Points can also be deducted for using hints or too many turns, or
* for saving intermediate positions. */
/* The present scoring algorithm is as follows:
* Objective: Points: Present total possible:
* Getting well into cave 25 25
* Each treasure < chest 12 60
* Treasure chest itself 14 14
* Each treasure > chest 16 224
* Surviving (MAX-NUM)*10 30
* Not quitting 4 4
* Reaching "CLOSNG" 25 25
* "Closed": Quit/Killed 10
* Klutzed 25
* Wrong way 30
* Success 45 45
* Came to Witt's End 1 1
* Round out the total 2 2
* TOTAL: 430
* Points can also be deducted for using hints or too many turns, or for
* saving intermediate positions. */
/* First tally up the treasures. Must be in building and not broken.
* Give the poor guy 2 points just for finding each treasure. */
mxscor = 0;
for (int i = 1; i <= NOBJECTS; i++) {
if (!objects[i].is_treasure) {
continue;
}
if (objects[i].inventory != 0) {
int k = 12;
if (i == CHEST) {
k = 14;
}
if (i > CHEST) {
k = 16;
}
if (!OBJECT_IS_STASHED(i) && !OBJECT_IS_NOTFOUND(i)) {
score += 2;
}
if (game.objects[i].place == LOC_BUILDING &&
OBJECT_IS_FOUND(i)) {
score += k - 2;
}
mxscor += k;
}
}
SCORE=0;
MXSCOR=0;
/* Now look at how he finished and how far he got. NDEATHS and
* game.numdie tell us how well he survived. game.dflag will tell us
* if he ever got suitably deep into the cave. game.closng still
* indicates whether he reached the endgame. And if he got as far as
* "cave closed" (indicated by "game.closed"), then bonus is zero for
* mundane exits or 133, 134, 135 if he blew it (so to speak). */
score += (NDEATHS - game.numdie) * 10;
mxscor += NDEATHS * 10;
if (mode == endgame) {
score += 4;
}
mxscor += 4;
if (game.dflag != 0) {
score += 25;
}
mxscor += 25;
if (game.closng) {
score += 25;
}
mxscor += 25;
if (game.closed) {
if (game.bonus == none) {
score += 10;
}
if (game.bonus == splatter) {
score += 25;
}
if (game.bonus == defeat) {
score += 30;
}
if (game.bonus == victory) {
score += 45;
}
}
mxscor += 45;
/* First tally up the treasures. Must be in building and not broken.
* Give the poor guy 2 points just for finding each treasure. */
/* Did he come to Witt's End as he should? */
if (game.objects[MAGAZINE].place == LOC_WITTSEND) {
score += 1;
}
mxscor += 1;
/* 20010 */ for (I=50; I<=MAXTRS; I++) {
if(PTEXT[I] == 0) goto L20010;
K=12;
if(I == CHEST)K=14;
if(I > CHEST)K=16;
if(PROP[I] >= 0)SCORE=SCORE+2;
if(PLACE[I] == 3 && PROP[I] == 0)SCORE=SCORE+K-2;
MXSCOR=MXSCOR+K;
L20010: /*etc*/ ;
} /* end loop */
/* Round it off. */
score += 2;
mxscor += 2;
/* Now look at how he finished and how far he got. MAXDIE and NUMDIE tell us
* how well he survived. DFLAG will
* tell us if he ever got suitably deep into the cave. CLOSNG still indicates
* whether he reached the endgame. And if he got as far as "cave closed"
* (indicated by "CLOSED"), then bonus is zero for mundane exits or 133, 134,
* 135 if he blew it (so to speak). */
/* Deduct for hints/turns/saves. Hints < 4 are special; see database
* desc. */
for (int i = 0; i < NHINTS; i++) {
if (game.hints[i].used) {
score = score - hints[i].penalty;
}
}
if (game.novice) {
score -= 5;
}
if (game.clshnt) {
score -= 10;
}
score = score - game.trnluz - game.saved;
SCORE=SCORE+(MAXDIE-NUMDIE)*10;
MXSCOR=MXSCOR+MAXDIE*10;
if(MODE == 0)SCORE=SCORE+4;
MXSCOR=MXSCOR+4;
if(DFLAG != 0)SCORE=SCORE+25;
MXSCOR=MXSCOR+25;
if(CLOSNG)SCORE=SCORE+25;
MXSCOR=MXSCOR+25;
if(!CLOSED) goto L20020;
if(BONUS == 0)SCORE=SCORE+10;
if(BONUS == 135)SCORE=SCORE+25;
if(BONUS == 134)SCORE=SCORE+30;
if(BONUS == 133)SCORE=SCORE+45;
L20020: MXSCOR=MXSCOR+45;
/* Return to score command if that's where we came from. */
if (mode == scoregame) {
rspeak(GARNERED_POINTS, score, mxscor, game.turns, game.turns);
}
/* Did he come to Witt's End as he should? */
if(PLACE[MAGZIN] == 108)SCORE=SCORE+1;
MXSCOR=MXSCOR+1;
/* Round it off. */
SCORE=SCORE+2;
MXSCOR=MXSCOR+2;
/* Deduct for hints/turns/saves. Hints < 4 are special; see database desc. */
for (I=1; I<=HNTMAX; I++) {
if(HINTED[I])SCORE=SCORE-HINTS[I][2];
} /* end loop */
if(NOVICE)SCORE=SCORE-5;
if(CLSHNT)SCORE=SCORE-10;
SCORE=SCORE-TRNLUZ-SAVED;
/* Return to score command if that's where we came from. */
if(MODE < 0) return;
/* that should be good enough. Let's tell him all about it. */
if(SCORE+TRNLUZ+1 >= MXSCOR && TRNLUZ != 0)RSPEAK(242);
if(SCORE+SAVED+1 >= MXSCOR && SAVED != 0)RSPEAK(143);
SETPRM(1,SCORE,MXSCOR);
SETPRM(3,TURNS,TURNS);
RSPEAK(262);
for (I=1; I<=CLSSES; I++) {
if(CVAL[I] >= SCORE) goto L20210;
/*etc*/ ;
} /* end loop */
SPK=265;
goto L25000;
L20210: SPEAK(CTEXT[I]);
SPK=264;
if(I >= CLSSES) goto L25000;
I=CVAL[I]+1-SCORE;
SETPRM(1,I,I);
SPK=263;
L25000: RSPEAK(SPK);
exit(0);
return score;
}
void terminate(enum termination mode) {
/* End of game. Let's tell him all about it. */
int points = score(mode);
#if defined ADVENT_AUTOSAVE
autosave();
#endif
if (points + game.trnluz + 1 >= mxscor && game.trnluz != 0) {
rspeak(TOOK_LONG);
}
if (points + game.saved + 1 >= mxscor && game.saved != 0) {
rspeak(WITHOUT_SUSPENDS);
}
rspeak(TOTAL_SCORE, points, mxscor, game.turns, game.turns);
for (int i = 1; i <= (int)NCLASSES; i++) {
if (classes[i].threshold >= points) {
speak(classes[i].message);
if (i < (int)NCLASSES) {
int nxt = classes[i].threshold + 1 - points;
rspeak(NEXT_HIGHER, nxt, nxt);
} else {
rspeak(NO_HIGHER);
}
exit(EXIT_SUCCESS);
}
}
rspeak(OFF_SCALE);
exit(EXIT_SUCCESS);
}
/* end */

24
share.h Normal file
View file

@ -0,0 +1,24 @@
extern void score(long);
extern long ABBNUM, ACTSPK[], AMBER, ATTACK, AXE, BACK, BATTER, BEAR,
BIRD, BLOOD, BONUS,
BOTTLE, CAGE, CAVE, CAVITY, CHAIN, CHASM, CHEST, CHLOC, CHLOC2,
CLAM, CLOCK1, CLOCK2, CLOSED, CLOSNG, CLSHNT, CLSMAX, CLSSES,
COINS, COND[], CONDS, CTEXT[], CVAL[], DALTLC, DETAIL,
DKILL, DOOR, DPRSSN, DRAGON, DSEEN[], DTOTAL, DWARF, EGGS,
EMRALD, ENTER, ENTRNC, FIND, FISSUR, FIXD[], FOOBAR, FOOD,
GRATE, HINT, HINTED[], HINTLC[], HINTS[][5], HNTMAX,
HNTSIZ, I, INVENT, IGO, IWEST, J, JADE, K, K2, KEY[], KEYS, KK,
KNFLOC, KNIFE, KQ, L, LAMP, LIMIT, LINSIZ, LINUSE, LL,
LMWARN, LOC, LOCK, LOCSIZ, LOCSND[], LOOK, LTEXT[],
MAGZIN, MAXDIE, MAXTRS, MESH, MESSAG, MIRROR, MXSCOR,
NEWLOC, NOVICE, NUGGET, NUL, NUMDIE, OBJ, OBJSND[],
OBJTXT[], ODLOC[], OGRE, OIL, OLDLC2, OLDLOC, OLDOBJ, OYSTER,
PANIC, PEARL, PILLOW, PLAC[], PLANT, PLANT2, PROP[], PYRAM,
RESER, ROD, ROD2, RTXSIZ, RUBY, RUG, SAPPH, SAVED, SAY,
SCORE, SECT, SETUP, SIGN, SNAKE, SPK, STEPS, STEXT[], STICK,
STREAM, TABNDX, TALLY, THRESH, THROW, TK[], TRAVEL[], TRIDNT,
TRNDEX, TRNLUZ, TRNSIZ, TRNVAL[], TRNVLS, TROLL, TROLL2, TRVS,
TRVSIZ, TTEXT[], TURNS, URN, V1, V2, VASE, VEND, VERB,
VOLCAN, VRBSIZ, VRSION, WATER, WD1, WD1X, WD2, WD2X,
WZDARK, ZZWORD;

View file

@ -1,87 +0,0 @@
<--
SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
SPDX-License-Identifier: BSD-2-Clause
-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Coverage - adventure.yaml</title>
<link rel="stylesheet" type="text/css" href="gcov.css">
<style>
.covered {{
text-align: center;
background-color: #A7FC9D;
}}
.covered::before {{
content: '\002714';
}}
.uncovered {{
text-align: center;
background-color: #FF0000;
}}
.uncovered::before {{
content: '\002715';
}}
</style>
</head>
<body>
<table width="100%" border=0 cellspacing=0 cellpadding=0>
<tr>
<td class="title" colspan="2">adventure.yaml Coverage report</td>
</tr>
<tr>
<td class="ruler" colspan="2"><img src="glass.png" width=3 height=3 alt=""></td>
</tr>
<tr valign="top">
<td>
<table cellpadding=1 border=0 width="100%">
<tr>
<td width="10%" class="headerItem">Test:</a></td>
<td width="35%" class="headerValue">adventure.yaml</td>
<td width="65%"></td>
</tr>
<tr>
<td class="headerItem">Date:</a></td>
<td class="headerValue">2017-07-07 21:47:56</td>
<td></td>
</tr>
</table>
</td>
<td>
<table cellpadding=1 border=0 width="100%">
<tr>
<td width="55%"></td>
<td width="15%" class="headerCovTableHead">Total</td>
<td width="15%" class="headerCovTableHead">Covered</td>
<td width="15%" class="headerCovTableHead">% Coverage</td>
</tr>
{summary}
</table>
</td>
</tr>
<tr>
<td><img src="glass.png" width=3 height=3 alt=""></td>
</tr>
<tr>
<td class="ruler" colspan="2"><img src="glass.png" width=3 height=3 alt=""></td>
</tr>
</table>
<br>
<center>
<table width="60%" border=0 cellpadding=1 cellspacing=1>
{categories}
</table>
</center>
<br>
<table width="100%" border=0 cellspacing=0 cellpadding=0>
<tr>
<td class="ruler"><img src="glass.png" width=3 height=3 alt=""></td>
</tr>
<tr>
<td class="versionInfo">Generated by: <a href="https://gitlab.com/esr/open-adventure/blob/master/tests/coverage_dungeon.py">Open Adventure Dungeon Coverage Generator</a></td>
</tr>
</table>
<br>
</body>
</html>

View file

@ -1,59 +0,0 @@
/*
SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
SPDX-License-Identifier: BSD-2-Clause
*/
#include "{h_file}"
const char* arbitrary_messages[] = {{
{arbitrary_messages}
}};
const class_t classes[] = {{
{classes}
}};
const turn_threshold_t turn_thresholds[] = {{
{turn_thresholds}
}};
const location_t locations[] = {{
{locations}
}};
const object_t objects[] = {{
{objects}
}};
const obituary_t obituaries[] = {{
{obituaries}
}};
const hint_t hints[] = {{
{hints}
}};
long conditions[] = {{
{conditions}
}};
const motion_t motions[] = {{
{motions}
}};
const action_t actions[] = {{
{actions}
}};
const long tkey[] = {{{tkeys}}};
const travelop_t travel[] = {{
{travel}
}};
const char *ignore = "{ignore}";
/* Dwarf starting locations */
const int dwarflocs[NDWARVES] = {{{dwarflocs}}};
/* end */

View file

@ -1,167 +0,0 @@
/*
SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
SPDX-License-Identifier: BSD-2-Clause
*/
#ifndef DUNGEON_H
#define DUNGEON_H
#include <stdio.h>
#include <stdbool.h>
#define SILENT -1 /* no sound */
/* Symbols for cond bits */
#define COND_LIT 0 /* Light */
#define COND_OILY 1 /* If bit 2 is on: on for oil, off for water */
#define COND_FLUID 2 /* Liquid asset, see bit 1 */
#define COND_NOARRR 3 /* Pirate doesn't go here unless following */
#define COND_NOBACK 4 /* Cannot use "back" to move away */
#define COND_ABOVE 5 /* Aboveground, but not in forest */
#define COND_DEEP 6 /* Deep - e.g where dwarves are active */
#define COND_FOREST 7 /* In the forest */
#define COND_FORCED 8 /* Only one way in or out of here */
#define COND_ALLDIFFERENT 9 /* Room is in maze all different */
#define COND_ALLALIKE 10 /* Room is in maze all alike */
/* Bits past 11 indicate areas of interest to "hint" routines */
#define COND_HBASE 11 /* Base for location hint bits */
#define COND_HCAVE 12 /* Trying to get into cave */
#define COND_HBIRD 13 /* Trying to catch bird */
#define COND_HSNAKE 14 /* Trying to deal with snake */
#define COND_HMAZE 15 /* Lost in maze */
#define COND_HDARK 16 /* Pondering dark room */
#define COND_HWITT 17 /* At Witt's End */
#define COND_HCLIFF 18 /* Cliff with urn */
#define COND_HWOODS 19 /* Lost in forest */
#define COND_HOGRE 20 /* Trying to deal with ogre */
#define COND_HJADE 21 /* Found all treasures except jade */
#define NDWARVES {ndwarflocs} // number of dwarves
extern const int dwarflocs[NDWARVES];
typedef struct {{
const char** strs;
const int n;
}} string_group_t;
typedef struct {{
const string_group_t words;
const char* inventory;
int plac, fixd;
bool is_treasure;
const char** descriptions;
const char** sounds;
const char** texts;
const char** changes;
}} object_t;
typedef struct {{
const char* small;
const char* big;
}} descriptions_t;
typedef struct {{
descriptions_t description;
const long sound;
const bool loud;
}} location_t;
typedef struct {{
const char* query;
const char* yes_response;
}} obituary_t;
typedef struct {{
const int threshold;
const int point_loss;
const char* message;
}} turn_threshold_t;
typedef struct {{
const int threshold;
const char* message;
}} class_t;
typedef struct {{
const int number;
const int turns;
const int penalty;
const char* question;
const char* hint;
}} hint_t;
typedef struct {{
const string_group_t words;
}} motion_t;
typedef struct {{
const string_group_t words;
const char* message;
const bool noaction;
}} action_t;
enum condtype_t {{cond_goto, cond_pct, cond_carry, cond_with, cond_not}};
enum desttype_t {{dest_goto, dest_special, dest_speak}};
typedef struct {{
const long motion;
const long condtype;
const long condarg1;
const long condarg2;
const enum desttype_t desttype;
const long destval;
const bool nodwarves;
const bool stop;
}} travelop_t;
extern const location_t locations[];
extern const object_t objects[];
extern const char* arbitrary_messages[];
extern const class_t classes[];
extern const turn_threshold_t turn_thresholds[];
extern const obituary_t obituaries[];
extern const hint_t hints[];
extern long conditions[];
extern const motion_t motions[];
extern const action_t actions[];
extern const travelop_t travel[];
extern const long tkey[];
extern const char *ignore;
#define NLOCATIONS {num_locations}
#define NOBJECTS {num_objects}
#define NHINTS {num_hints}
#define NCLASSES {num_classes}
#define NDEATHS {num_deaths}
#define NTHRESHOLDS {num_thresholds}
#define NMOTIONS {num_motions}
#define NACTIONS {num_actions}
#define NTRAVEL {num_travel}
#define NKEYS {num_keys}
#define BIRD_ENDSTATE {bird_endstate}
enum arbitrary_messages_refs {{
{arbitrary_messages}
}};
enum locations_refs {{
{locations}
}};
enum object_refs {{
{objects}
}};
enum motion_refs {{
{motions}
}};
enum action_refs {{
{actions}
}};
/* State definitions */
{state_definitions}
#endif /* end DUNGEON_H */

View file

@ -1,43 +1,20 @@
# Test-suite makefile for open-adventure
# Test-suite makefile for reposurgeon
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
# Use absolute path so tests that change working directory still use
# Use absolute path so tests that change working directory still use
# scripts from parent directory. Note that using $PWD seems to fail
# here under Gitlab's CI environment.
PARDIR=$(realpath ..)
PATH := $(PARDIR):$(realpath .):${PATH}
GCOV?=gcov
# Make this overrideable so it's easier to test old versions
advent?=advent
PATH := $(realpath ..):$(realpath .):${PATH}
# Defeat annoying behavior under Mac OS X - builtin echo doesn't do -n
ECHO := /bin/echo
# The TAP filter. Only affects presentation of the test suite messages
TAPCONSUMER=tapview
# Fall back to safety if our declared TAP consumer does not exist.
# This is helpful in the CI environment, where it would be better for
# the logfiles to carry the raw TAP messages.
TAPFILTER=$(shell command -v $(TAPCONSUMER) || echo cat)
# Find all *.log entries to test
TESTLOADS := $(shell ls -1 *.log | sed '/.log/s///' | sort)
.PHONY: check clean testlist listcheck savegames savecheck coverage
.PHONY: buildchecks multifile-regress tap count
check: savecheck
@make tap | tapview
@-advent -x 2>/dev/null || exit 0 # Get usage message into coverage tests
all: regress
@echo "=== No diff output is good news."
.SUFFIXES: .chk
clean:
rm -fr *~ *.adv scratch.tmp *.ochk advent430 adventure.data
rm -fr *~ adventure.text
# Show summary lines for all tests.
testlist:
@ -47,131 +24,23 @@ listcheck:
if ( head -3 $$f | grep -q '^ *##' ); then :; else echo "$$f needs a description"; fi; \
done
# Generate bogus savegames.
cheat_numdie.adv:
@$(PARDIR)/cheat -d -900 -o cheat_numdie.adv > /tmp/cheat_numdie
cheat_numdie1000.adv:
@$(PARDIR)/cheat -d -1000 -o cheat_numdie1000.adv > /tmp/cheat_numdie1000
cheat_savetamper.adv:
@$(PARDIR)/cheat -d 2000 -o cheat_savetamper.adv > /tmp/cheat_savetamper
resume_badversion.adv:
@$(PARDIR)/cheat -v -1337 -o resume_badversion.adv > /tmp/cheat_badversion
thousand_saves.adv:
@$(PARDIR)/cheat -s -1000 -o thousand_saves.adv > /tmp/cheat_1000saves
thousand_turns.adv:
@$(PARDIR)/cheat -t -1000 -o thousand_turns.adv > /tmp/cheat_1000turns
thousand_limit.adv:
@$(PARDIR)/cheat -l -1000 -o thousand_limit.adv > /tmp/cheat_1000limit
SGAMES = cheat_numdie.adv cheat_numdie1000.adv cheat_savetamper.adv resume_badversion.adv \
thousand_saves.adv thousand_turns.adv thousand_limit.adv
# Force coverage of cheat edgecases
scheck1:
@$(PARDIR)/cheat -QqQ 2> /tmp/coverage_cheat_batopt | true
@./outcheck.sh "cheat: bogus option for save file generation"
scheck2:
@$(PARDIR)/cheat 2>/dev/null | true
@./outcheck.sh "cheat: No save file specified"
scheck3:
@$(PARDIR)/cheat -d 1 2> /tmp/coverage_cheat_nooutput | true
@./outcheck.sh "cheat: doesn't save because we omit -o"
scheck4:
@$(PARDIR)/cheat -o / 2> /tmp/coverage_cheat_badoutput | true
@./outcheck.sh "cheat: doesn't save to invalid path"
scheck5:
@$(advent) -r /badfilename < pitfall.log > /tmp/coverage_advent_readfail 2>&1 || exit 1
@./outcheck.sh "cheat: doesn't start with invalid file with -r"
scheck6:
@$(advent) -l / < pitfall.log > /tmp/coverage_advent_logfail 2>&1 || exit 1
@./outcheck.sh "cheat: doesn't start with invalid file passed to -l"
scheck7:
@$(advent) -r thousand_saves.adv < pitfall.log > /tmp/coverage_advent_readfail 2>&1 || exit 1
@./outcheck.sh "test -r with valid input"
SCHECKS = scheck1 scheck2 scheck3 scheck4 scheck5 scheck6 scheck7
# Don't run this from here, you'll get cryptic warnings and no good result
# if the advent binary wasn't built with coverage flags. Do "make clean coverage"
# from the top-level directory.
coverage: check
lcov -t "advent" -o $(PARDIR)/advent.info -c -d $(PARDIR) --gcov-tool=$(GCOV)
genhtml -o $(PARDIR)/coverage/ $(PARDIR)/advent.info
./coverage_dungeon.py
# Rebuild characterizing tests
buildchecks: savegames
$(PARDIR)/cheat -s -1000 -o thousand_saves.adv > /tmp/regress1000saves
# General regression testing of commands and output; look at the *.log and
# corresponding *.chk files to see which tests this runs.
TESTLOADS := $(shell ls -1 *.log | sed '/.log/s///')
buildregress:
@for file in $(TESTLOADS); do \
echo "Remaking $${file}.chk"; \
OPTS=`sed -n /#options:/s///p <$${file}.log`; \
advent $$OPTS <$${file}.log >$${file}.chk 2>&1 || exit 1; \
done; \
echo "inven" | advent issue36.log /dev/stdin >multifile.chk; \
rm -f scratch.tmp
RUN_TARGETS=$(TESTLOADS:%=run-regress-%)
$(RUN_TARGETS): run-regress-%: %.log
@(test=$(<:.log=); legend=$$(sed -n '/^## /s///p' <"$<" 2>/dev/null || echo "(no description)"); \
OPTS=`sed -n /#options:/s///p $<`; \
$(advent) $$OPTS <$< | tapdiffer "$${test}: $${legend}" "$${test}.chk")
multifile-regress:
@(echo "inven" | advent issue36.log /dev/stdin) | tapdiffer "multifile: multiple-file test" multifile.chk
TEST_TARGETS = $(SCHECKS) $(RUN_TARGETS) multifile-regress
tap: count $(SGAMES) $(TEST_TARGETS)
@rm -f scratch.tmp /tmp/coverage* /tmp/cheat*
count:
@echo 1..$(words $(TEST_TARGETS))
# The following machinery tests the game against a binary made from
# the advent430 branch To use it, switch to that branch, build the
# binary, run it once to generate adventure.data, then switch back to
# master leaving advent430 and adventure.data in place (make clean
# does not remove them).
#
# make clean # Clean up object files, laving a bare source tree
# git checkout advent430 # Check out the advent430 branch
# make # Build the advent430 binary
# advent430 # Run it. Answer the novice question and quit
# make clean # Remove .o files
# git checkout master # Go back to master branch
# make # Rebuild advent.
#
# The diff file produced has corrected spellings in it. That's what oldfilter
# is for, to massage out the original spellings and avoid noise diffs.
# Diffs in amount of whitespace and trailing whitespace are ignored
#
# A magic comment of NOCOMPARE in a log file excludes it from this comparison.
# making it a skipped test in the TAP view. First use of this was to avoid a
# spurious mismatch on the news text. Other uses avoid spurious mismatches due
# to bug fixes.
#
# When adding more tests, bear in mind that any game that continues after a
# resurrection will need a NOCOMPARE. At some point in the forward port,
# resurrection was accidentally changed in a way that messed with the LCG chain.
#
# The *.chk files need not be up-to-date for this to work.
#
TAPFILTER=tapview
oldcompare:
@if [ -f ../advent430 ]; then cp ../advent430 ../adventure.data .; else echo "advent430 nonexistent"; exit 1; fi
@-(for x in *.log; do \
stem=$${x%.log}; \
legend=$$(sed -n '/^## /s///p' <$$x 2>/dev/null || echo "(no description)"); \
if grep NOCOMPARE $$x >/dev/null; \
then echo "not ok - $${stem}.ochk: $${legend} # SKIP"; \
else \
./advent430 <$${stem}.log | oldfilter >$${stem}.ochk; \
../advent <$${stem}.log >$${stem}.log-new; \
./newfilter <$${stem}.log-new | tapdiffer -b "$${stem}: $${legend}" $${stem}.ochk; \
fi; \
done; \
echo 1..$(words $(shell ls *.log))) | $(TAPFILTER)
@rm *.ochk *-new advent430 adventure.data
# List all NOCOMPARE tests.
residuals:
@grep -n NOCOMPARE *.log
done
regress:
@for file in $(TESTLOADS); do \
$(ECHO) -n " $${file} "; grep '##' $${file}.log || echo ' ## (no description)'; \
OPTS=`sed -n /#options:/s///p <$${file}.log`; \
if advent $$OPTS < $${file}.log >/tmp/regress$$$$ 2>&1; \
then diff --text -u $${file}.chk /tmp/regress$$$$ || exit 1; \
else echo "*** Nonzero return status on $${file}!"; exit 1; fi \
done
@rm -f /tmp/regress$$$$
# end

View file

@ -1,36 +0,0 @@
= Notes on the test machinery =
== Understanding and running tests ==
A .log extension means it's a game log
A .chk extension means it's expected output from a test
The test files are run in alphabetical order. This allows you to
ensure certain tests are run in a particular order merely by giving
them appropriate names, e.g.: test.1.log, test.2.log, test.3.log. This
is useful for testing save and resume.
In general, a file named foo.chk is the expected output from the game log
foo.log. To add new tests, just drop log files in this directory.
To see summary lines from all tests, 'make testlist'. The summary lines
are those led with ##; you should have one such descriptive line at the
head of each file.
To run the tests, "make check".
To remake the check files, "make buildchecks".
== Composing tests ==
The simplest way to make a test is to simply play a game with the -l
option giving a log path. Commands will be captured to that log.
To re-use a command sequence from an existing log, run advent and
paste it to the advent command log from the clipboard.
To see where we can use more tests, "make coverage".
// end

File diff suppressed because it is too large Load diff

View file

@ -1,278 +0,0 @@
## Observe axe after throwing at bear
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 1838473132
in
take lamp
xyzzy
on
take rod
e
take cage
w
w
w
drop rod
take bird
take rod
w
free bird
wave rod
take necklace
drop rod
take bird
take rod
d
d
free bird
drop rod
drop cage
take cage
take bird
w
take coins
e
s
take jewelry
n
up
s
take gold
n
d
n
n
plugh
extinguish lamp
drop coins
drop jewelry
drop necklace
drop gold
plugh
on
s
take silver
s
sw
take axe
w
kill dragon
yes
drink blood
take rug
e
e
up
d
n
n
off
plugh
inven
drop rug
drop silver
out
s
w
n
take appendage
free bird
drop cage
listen
s
s
n
in
take water
plugh
on
plover
ne
take pyramid
s
plover
s
s
take rod
up
w
wave rod
drop rod
west
take diamonds
w
w
w
s
sw
se
s
kill machine
s
s
kill ogre
n
take ruby
s
w
n
n
n
nw
d
e
e
e
e
e
throw axe
take axe
n
n
n
off
plugh
drop ruby
drop diamonds
drop pyramid
plugh
on
s
s
u
n
n
d
bedquilt
throw axe
take axe
slab
s
d
water plant
u
eat plant
w
u
reservoir
H'CFL
n
n
nw
u
u
u
u
ne
take ebony
sw
d
d
d
d
d
take water
s
s
s
s
d
s
d
water plant
eat plant
u
drop appendage
e
d
get oil
u
w
d
climb
w
n
oil door
drop bottle
n
take trident
w
d
se
n
w
drop trident
drop ebony
drop axe
drop lantern
e
take emerald
w
take lamp
take axe
take ebony
take trident
nw
s
take vase
se
throw axe
take axe
e
take pillow
w
ne
e
n
open clam
s
u
e
u
n
off
plugh
drop pillow
drop vase
drop trident
drop emerald
drop ebony
take keys
take food
plugh
on
s
d
w
d
n
d
d
take pearl
u
u
s
w
w
w
w
d
climb
w
get eggs
n
take bottle
n
w
d
sw
u
toss eggs
ne
ne
barren
in
throw axe
look

View file

@ -1,660 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> seed 1838473132
Seed set to 1838473132
You're in front of building.
> in
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is a bottle of water here.
> take lamp
OK
> xyzzy
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You are in a debris room filled with stuff washed in from the surface.
A low wide passage with cobbles becomes plugged with mud and debris
here, but an awkward canyon leads upward and west. In the mud someone
has scrawled, "MAGIC WORD XYZZY".
A three foot black rod with a rusty star on an end lies nearby.
> take rod
OK
> e
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
There is a small wicker cage discarded nearby.
> take cage
OK
> w
You're in debris room.
> w
You are in an awkward sloping east/west canyon.
> w
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
from east and west sides of the chamber.
A cheerful little bird is sitting here singing.
> drop rod
OK
> cage bird
OK
> take rod
OK
> w
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
Rough stone steps lead down the pit.
> free bird
OK
> wave rod
The bird flies about agitatedly for a moment, then disappears through
the crack. It reappears shortly, carrying in its beak a jade
necklace, which it drops at your feet.
> take necklace
OK
> drop rod
OK
> cage bird
OK
> take rod
OK
> d
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
staircase leads downward. The hall is filled with wisps of white mist
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
Rough stone steps lead up the dome.
> d
You are in the Hall of the Mountain King, with passages off in all
directions.
A huge green fierce snake bars the way!
> free bird
The little bird attacks the green snake, and in an astounding flurry
drives the snake away.
> drop rod
OK
> drop cage
OK
> take cage
OK
> cage bird
OK
> take rod
OK
> w
You are in the west side chamber of the Hall of the Mountain King.
A passage continues west and up here.
There are many coins here!
> e
You're in Hall of Mt King.
> s
You are in the south side chamber.
There is precious jewelry here!
> take jewelry
OK
> n
You're in Hall of Mt King.
> up
You're in Hall of Mists.
Rough stone steps lead up the dome.
> s
This is a low room with a crude note on the wall. The note says,
"You won't get it up the steps".
There is a large sparkling nugget of gold here!
> take gold
OK
> n
You're in Hall of Mists.
> d
You're in Hall of Mt King.
> n
You are in a low n/s passage at a hole in the floor. The hole goes
down to an e/w passage.
There are bars of silver here!
> n
You are in a large room, with a passage to the south, a passage to the
west, and a wall of broken rock to the east. There is a large "Y2" on
a rock in the room's center.
A hollow voice says "PLUGH".
> plugh
>>Foof!<<
You're inside building.
There are some keys on the ground here.
There is food here.
There is a bottle of water here.
> extinguish lamp
Your lamp is now off.
> drop coins
I see no coins here.
> drop jewelry
OK
> drop necklace
OK
> drop gold
OK
> plugh
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You're at "Y2".
> s
You're in n/s passage above e/w passage.
There are bars of silver here!
> take silver
OK
> s
You're in Hall of Mt King.
> sw
A little dwarf just walked around a corner, saw you, threw a little
axe at you which missed, cursed, and ran away.
You are in a secret canyon which here runs e/w. It crosses over a
very tight canyon 15 feet below. If you go down you may not be able
to get back up.
There is a little axe here.
> take axe
OK
> w
You are in a secret canyon which exits to the north and east.
A huge green fierce dragon bars the way!
The dragon is sprawled out on a Persian rug!!
> throw axe
The axe bounces harmlessly off the dragon's thick scales.
You are in a secret canyon which exits to the north and east.
There is a little axe here.
A huge green fierce dragon bars the way!
The dragon is sprawled out on a Persian rug!!
> take axe
OK
> kill dragon
With what? Your bare hands?
> y
Congratulations! You have just vanquished a dragon with your bare
hands! (Unbelievable, isn't it?)
You are in a secret canyon which exits to the north and east.
There is a Persian rug spread out on the floor!
The blood-specked body of a huge green dead dragon lies to one side.
> inven
You are currently holding the following:
Brass lantern
Wicker cage
Black rod
Little bird in cage
Dwarf's axe
Bars of silver
> e
You're in secret e/w canyon above tight canyon.
> e
You are in the Hall of the Mountain King, with passages off in all
directions.
> u
You're in Hall of Mists.
Rough stone steps lead up the dome.
> w
You are on the east bank of a fissure slicing clear across the hall.
The mist is quite thick here, and the fissure is too wide to jump.
> wave rod
The bird flies agitatedly about the cage.
A crystal bridge now spans the fissure.
> w
You are on the west side of the fissure in the Hall of Mists.
There are diamonds here!
A crystal bridge spans the fissure.
> w
You are at the west end of the Hall of Mists. A low wide crawl
continues west and another goes north. To the south is a little
passage 6 feet off the floor.
> w
You are at the east end of a very long hall apparently without side
chambers. To the east a low wide crawl slants up. To the north a
round two foot hole slants down.
> w
You are at the west end of a very long featureless hall. The hall
joins up with a narrow north/south passage.
> s
You are in a maze of twisty little passages, all different.
> sw
You are in a little maze of twisty passages, all different.
> se
You are in a little maze of twisting passages, all different.
> s
Dead end
There is a massive and somewhat battered vending machine here. The
instructions on it read: "Drop coins here to receive fresh batteries."
> throw axe
There is nothing here to attack.
> kill machine
As you strike the vending machine, it pivots backward along with a
section of wall, revealing a dark passage leading south.
> s
You are in a long, rough-hewn, north/south corridor.
> s
You are in a large chamber with passages to the west and north.
A formidable ogre bars the northern exit.
> throw axe
The ogre, who despite his bulk is quite agile, easily dodges your
attack. He seems almost amused by your puny effort.
You are in a large chamber with passages to the west and north.
There is a little axe here.
A formidable ogre bars the northern exit.
> take axe
OK
> w
You are in a long, rough-hewn, north/south corridor.
> n
Dead end
There is a massive vending machine here, swung back to reveal a
southward passage.
> n
You are in a little maze of twisting passages, all different.
> n
You are in a little maze of twisty passages, all different.
> nw
You are in a maze of twisty little passages, all different.
> d
You're at west end of long hall.
> e
You're at east end of long hall.
> e
You're at west end of Hall of Mists.
> e
You're on west bank of fissure.
There are diamonds here!
A crystal bridge spans the fissure.
> e
You're on east bank of fissure.
A crystal bridge spans the fissure.
> e
You're in Hall of Mists.
Rough stone steps lead up the dome.
> n
You're in Hall of Mt King.
> n
There is a threatening little dwarf in the room with you!
One sharp nasty knife is thrown at you!
It misses!
You're in n/s passage above e/w passage.
> take knife
The dwarves' knives vanish as they strike the walls of the cave.
> throw axe
You killed a little dwarf. The body vanishes in a cloud of greasy
black smoke.
You're in n/s passage above e/w passage.
There is a little axe here.
> take axe
OK
> d
You are in a dirty broken passage. To the east is a crawl. To the
west is a large passage. Above you is a hole to another passage.
> w
You are in a large room full of dusty rocks. There is a big hole in
the floor. There are cracks everywhere, and a passage leading east.
> d
You are at a complex junction. A low hands and knees passage from the
north joins a higher crawl from the east to make a walking passage
going west. There is also a large room above. The air is damp here.
> w
You are in Bedquilt, a long east/west passage with holes everywhere.
To explore at random select north, south, up, or down.
> n
You have crawled around in some little holes and wound up back in the
main passage.
There is a threatening little dwarf in the room with you!
You're in Bedquilt.
> feed dwarf
There is nothing here to eat.
> throw axe
You killed a little dwarf.
You're in Bedquilt.
There is a little axe here.
> take axe
OK
> n
You have crawled around in some little holes and wound up back in the
main passage.
You're in Bedquilt.
> n
You are in a large low room. Crawls lead north, se, and sw.
> n
Dead end crawl.
> out
You're in large low room.
> sw
You are in a long winding corridor sloping out of sight in both
directions.
> up
You are on one side of a large, deep chasm. A heavy white mist rising
up from below obscures all view of the far side. A sw path leads away
from the chasm into a winding corridor.
A rickety wooden bridge extends across the chasm, vanishing into the
mist. A notice posted on the bridge reads, "Stop! Pay troll!"
A burly troll stands by the bridge and insists you throw him a
treasure before you may cross.
> throw axe
The troll deftly catches the axe, examines it carefully, and tosses it
back, declaring, "Good workmanship, but it's not valuable enough."
You're on sw side of chasm.
There is a little axe here.
A rickety wooden bridge extends across the chasm, vanishing into the
mist. A notice posted on the bridge reads, "Stop! Pay troll!"
A burly troll stands by the bridge and insists you throw him a
treasure before you may cross.
> jump
I respectfully suggest you go across the bridge instead of jumping.
You're on sw side of chasm.
There is a little axe here.
A rickety wooden bridge extends across the chasm, vanishing into the
mist. A notice posted on the bridge reads, "Stop! Pay troll!"
A burly troll stands by the bridge and insists you throw him a
treasure before you may cross.
>
You scored 105 out of a possible 430, using 109 turns.
Your score qualifies you as a novice class adventurer.
To achieve the next higher rating, you need 16 more points.

View file

@ -1,122 +0,0 @@
## Test throwing axe at non-dwarves.
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
# Added coverage of LOC_DEADCRAWL and CROSS_BRIDGE
n
seed 1838473132
in
take lamp
xyzzy
on
take rod
e
take cage
w
w
w
drop rod
cage bird
take rod
w
free bird
wave rod
take necklace
drop rod
cage bird
take rod
d
d
free bird
drop rod
drop cage
take cage
cage bird
take rod
w
e
s
take jewelry
n
up
s
take gold
n
d
n
n
plugh
extinguish lamp
drop coins
drop jewelry
drop necklace
drop gold
plugh
on
s
take silver
s
sw
take axe
w
throw axe
take axe
kill dragon
y
inven
e
e
u
# Go to vending machine and ogre from Hall of Mists
w
wave rod
w
w
w
w
s
sw
se
s
throw axe
kill machine
s
s
throw axe
take axe
# Return to Hall of Mists
w
n
n
n
# Vending machine
nw
d
e
e
e
e
e
# Hall of Mists
n
n
take knife
throw axe
take axe
d
w
d
w
# Bedquilt
n
feed dwarf
throw axe
take axe
n
n
n
out
sw
up
# Troll bridge
throw axe
jump

View file

@ -1,22 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> resume
Can't open file y, try again.
Oops, that does not look like a valid save file.
You're in front of building.
>
You scored 32 out of a possible 430, using 1 turn.
You are obviously a rank amateur. Better luck next time.
To achieve the next higher rating, you need 14 more points.

View file

@ -1,8 +0,0 @@
## Resume from filename withoy the right magic at the front
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
#NOCOMPARE advent430 doesn't have this test
n
resume
y
../main.o

View file

@ -1,315 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> seed 1635997320
Seed set to 1635997320
You're in front of building.
> in
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is a bottle of water here.
> take lamp
OK
> xyzzy
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> take rod
OK
> e
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
There is a small wicker cage discarded nearby.
> take cage
OK
> w
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You are in a debris room filled with stuff washed in from the surface.
A low wide passage with cobbles becomes plugged with mud and debris
here, but an awkward canyon leads upward and west. In the mud someone
has scrawled, "MAGIC WORD XYZZY".
> w
You are in an awkward sloping east/west canyon.
> w
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
from east and west sides of the chamber.
A cheerful little bird is sitting here singing.
> drop rod
OK
> take bird
OK
> take rod
OK
> w
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
Rough stone steps lead down the pit.
> free bird
OK
> wave rod
The bird flies about agitatedly for a moment, then disappears through
the crack. It reappears shortly, carrying in its beak a jade
necklace, which it drops at your feet.
> drop rod
OK
> take bird
OK
> take jade
OK
> e
You're in bird chamber.
> e
You are in an awkward sloping east/west canyon.
> e
You're in debris room.
> off
Your lamp is now off.
It is now pitch dark. If you proceed you will likely fall into a pit.
> xyzzy
>>Foof!<<
You're inside building.
There are some keys on the ground here.
There is food here.
There is a bottle of water here.
> drop jade
OK
> xyzzy
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You're in debris room.
> w
You are in an awkward sloping east/west canyon.
> w
You're in bird chamber.
> w
You're at top of small pit.
A three foot black rod with a rusty star on an end lies nearby.
Rough stone steps lead down the pit.
> take rod
OK
> d
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
staircase leads downward. The hall is filled with wisps of white mist
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
Rough stone steps lead up the dome.
> w
You are on the east bank of a fissure slicing clear across the hall.
The mist is quite thick here, and the fissure is too wide to jump.
> wave rod
The bird flies agitatedly about the cage.
A crystal bridge now spans the fissure.
> drop rod
OK
> e
You're in Hall of Mists.
Rough stone steps lead up the dome.
> n
You are in the Hall of the Mountain King, with passages off in all
directions.
A huge green fierce snake bars the way!
> free bird
The little bird attacks the green snake, and in an astounding flurry
drives the snake away.
> take bird
OK
> s
You are in the south side chamber.
There is precious jewelry here!
> take jewelry
OK
> n
You're in Hall of Mt King.
> sw
You are in a secret canyon which here runs e/w. It crosses over a
very tight canyon 15 feet below. If you go down you may not be able
to get back up.
> w
You are in a secret canyon which exits to the north and east.
A huge green fierce dragon bars the way!
The dragon is sprawled out on a Persian rug!!
> drop bird
The little bird attacks the green dragon, and in an astounding flurry
gets burnt to a cinder. The ashes blow away.
> extinguish dragon
It is beyond your power to do that.
> kill dragon
With what? Your bare hands?
>
Please answer the question.
> green
Please answer the question.
> n
The dragon looks rather nasty. You'd best not try to get by.
You are in a secret canyon which exits to the north and east.
A huge green fierce dragon bars the way!
The dragon is sprawled out on a Persian rug!!
> kill dragon
With what? Your bare hands?
> y
Congratulations! You have just vanquished a dragon with your bare
hands! (Unbelievable, isn't it?)
You are in a secret canyon which exits to the north and east.
There is a Persian rug spread out on the floor!
The blood-specked body of a huge green dead dragon lies to one side.
> kill dragon
For crying out loud, the poor thing is already dead!
>
You scored 77 out of a possible 430, using 49 turns.
Your score qualifies you as a novice class adventurer.
To achieve the next higher rating, you need 44 more points.

View file

@ -1,60 +0,0 @@
## Get to dragon, refuse to use bare hands
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
#NOCOMPARE Fails due uninteresting difference in whitespace process.
# Based on walkthrough at http://www.ecsoftwareconsulting.com/node/56
n
seed 1635997320
in
take lamp
xyzzy
take rod
e
take cage
w
on
w
w
drop rod
take bird
take rod
w
free bird
wave rod
drop rod
take bird
take jade
e
e
e
off
xyzzy
drop jade
xyzzy
on
w
w
w
take rod
d
w
wave rod
drop rod
e
n
free bird
take bird
s
take jewelry
n
sw
w
drop bird
extinguish dragon
kill dragon
green
n
kill dragon
y
kill dragon

File diff suppressed because it is too large Load diff

View file

@ -1,316 +0,0 @@
## Test many nonlethal failure conditions
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
# See comments in this log
n
seed 1838473132
in
take lamp
xyzzy
on
take rod
e
take cage
w
w
w
drop rod
take bird
take rod
w
free bird
wave rod
take necklace
drop rod
take bird
take rod
d
d
free bird
drop rod
drop cage
take cage
take bird
w
take coins
e
s
take jewelry
n
up
s
take gold
n
d
n
n
plugh
extinguish lamp
drop coins
drop jewelry
drop necklace
drop gold
plugh
on
s
take silver
s
sw
take axe
w
kill dragon
yes
drink blood
take rug
e
e
up
d
n
n
off
plugh
inven
drop rug
drop silver
out
s
w
n
take appendage
free bird
drop cage
listen
s
s
n
in
take water
plugh
on
plover
ne
take pyramid
s
plover
s
s
take rod
up
w
wave rod
drop rod
west
take diamonds
w
w
w
s
sw
se
s
kill machine
s
s
kill ogre
n
take ruby
s
w
n
n
n
nw
d
e
e
e
e
e
throw axe
take axe
n
n
n
off
plugh
drop ruby
drop diamonds
drop pyramid
plugh
on
s
s
u
n
n
d
bedquilt
throw axe
take axe
slab
s
d
water plant
u
w
u
reservoir
H'CFL
n
n
nw
u
u
u
u
ne
take ebony
sw
d
d
d
d
d
take water
s
s
s
s
d
s
d
water plant
u
drop appendage
e
d
get oil
u
w
d
climb
w
n
oil door
drop bottle
n
take trident
w
d
se
n
w
drop trident
drop ebony
drop axe
drop lantern
e
take emerald
w
take lamp
take axe
take ebony
take trident
nw
s
take vase
# Test vase breakage
break vase
break vase
se
throw axe
take axe
e
w
ne
e
n
# Here we are at the Shell Room. Fail to carry out bivalves
take clam
unlock clam
s
open clam
drop clam
open clam
read oyster
take oyster
s
drop oyster
s
# OK, bivalve-carry test is done
u
e
u
n
off
plugh
drop pillow
drop trident
drop emerald
drop ebony
take keys
take food
take coins
plugh
on
s
d
w
d
n
d
d
take pearl
u
u
s
w
w
w
w
d
climb
w
get eggs
n
take bottle
n
w
d
sw
u
toss eggs
ne
ne
# Bear-verb test. Try feeding without food before feeding with
barren
drop food
in
attack
unlock chain
feed bear
out
take food
in
feed bear
carry bear
unlock chain
take chain
attack bear
feed bear
take bear
fork
ne
e
take spices
drop keys
fork
w
w
sw
free bear
take bear
sw
n
quit

File diff suppressed because it is too large Load diff

View file

@ -1,477 +0,0 @@
## Attempt to kill snake with bird in the endgame
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 1838473132
in
take lamp
xyzzy
on
take rod
e
take cage
w
w
w
drop rod
take bird
take rod
w
free bird
wave rod
take necklace
drop rod
take bird
take rod
d
d
free bird
drop rod
drop cage
take cage
take bird
w
take coins
e
s
take jewelry
n
up
s
take gold
n
d
n
n
plugh
extinguish lamp
drop coins
drop jewelry
drop necklace
drop gold
plugh
on
s
take silver
s
sw
take axe
w
kill dragon
yes
drink blood
take rug
e
e
up
d
n
n
off
plugh
inven
drop rug
drop silver
out
s
w
n
take appendage
free bird
drop cage
listen
s
s
n
in
take water
plugh
on
plover
ne
take pyramid
s
plover
s
s
take rod
up
w
wave rod
drop rod
west
take diamonds
w
w
w
s
sw
se
s
kill machine
s
s
kill ogre
n
take ruby
s
w
n
n
n
nw
d
e
e
e
e
e
throw axe
take axe
n
n
n
off
plugh
drop ruby
drop diamonds
drop pyramid
plugh
on
s
s
u
n
n
d
bedquilt
throw axe
take axe
slab
s
d
water plant
u
w
u
reservoir
H'CFL
n
n
nw
u
u
u
u
ne
take ebony
sw
d
d
d
d
d
take water
s
s
s
s
d
s
d
water plant
u
drop appendage
e
d
get oil
u
w
d
climb
w
n
oil door
drop bottle
n
take trident
w
d
se
n
w
drop trident
drop ebony
drop axe
drop lantern
e
take emerald
w
take lamp
take axe
take ebony
take trident
nw
s
take vase
se
throw axe
take axe
e
take pillow
w
drop axe
ne
e
n
open clam
s
u
e
u
n
off
plugh
# The score commands verify that you do indeed score points
# for dropping the vase on the pillow in the building.
score
drop pillow
drop vase
score
drop trident
drop emerald
drop ebony
take keys
take food
plugh
on
s
d
w
d
n
d
d
take pearl
u
u
s
w
w
w
w
d
climb
w
get eggs
n
take bottle
n
w
d
sw
u
toss eggs
ne
ne
barren
in
feed bear
unlock chain
take chain
take bear
fork
ne
e
take spices
drop keys
fork
w
w
sw
free bear
inven
sw
sw
d
se
se
w
d
get oil
up
e
take axe
w
w
d
climb
w
fee
fie
foe
foo
take eggs
s
d
u
w
u
s
e
e
n
n
off
plugh
drop eggs
drop pearl
drop spices
drop chain
take rug
take ruby
take emerald
out
w
n
n
n
inven
fill urn
light urn
rub urn
take amber
drop rug
drop emerald
fly rug
take sapphire
fly rug
take emerald
drop ruby
take rug
drop bottle
take ruby
e
s
e
e
in
drop ruby
drop sapphire
drop amber
drop rug
look
plugh
on
s
s
u
w
w
w
s
e
s
throw axe
take axe
s
s
n
e
e
nw
take emerald
take chest
se
n
d
e
e
off
xyzzy
drop emerald
drop chest
plugh
on
s
d
w
d
e
take magazine
e
drop magazine
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
u
u
e
u
n
plover
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
sw
listen
take cage
take bird
free bird

View file

@ -1,464 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> seed 976729036
Seed set to 976729036
You're in front of building.
> in
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is a bottle of water here.
> take lamp
OK
> take food
OK
> take bottle
OK
> inventory
You are currently holding the following:
Brass lantern
Tasty food
Small bottle
Water in the bottle
> out
You're in front of building.
> s
You are in a valley in the forest beside a stream tumbling along a
rocky bed.
> w
You are wandering aimlessly through the forest.
> n
You are wandering aimlessly through the forest.
Your keen eye spots a severed leporine appendage lying on the ground.
> take appendage
OK
> s
You are wandering aimlessly through the forest.
> s
You're in valley.
> n
You're in front of building.
> in
You're inside building.
There are some keys on the ground here.
> xyzzy
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You are in a debris room filled with stuff washed in from the surface.
A low wide passage with cobbles becomes plugged with mud and debris
here, but an awkward canyon leads upward and west. In the mud someone
has scrawled, "MAGIC WORD XYZZY".
A three foot black rod with a rusty star on an end lies nearby.
> e
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
There is a small wicker cage discarded nearby.
> take cage
OK
> w
You're in debris room.
A three foot black rod with a rusty star on an end lies nearby.
> w
You are in an awkward sloping east/west canyon.
> w
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
from east and west sides of the chamber.
A cheerful little bird is sitting here singing.
> take bird
OK
> e
You are in an awkward sloping east/west canyon.
> e
You're in debris room.
A three foot black rod with a rusty star on an end lies nearby.
> take rod
OK
> w
You are in an awkward sloping east/west canyon.
> w
You're in bird chamber.
> w
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
Rough stone steps lead down the pit.
> d
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
staircase leads downward. The hall is filled with wisps of white mist
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
Rough stone steps lead up the dome.
> inventory
You are currently holding the following:
Brass lantern
Wicker cage
Black rod
Little bird in cage
Tasty food
Small bottle
Water in the bottle
Leporine appendage
> w
You are on the east bank of a fissure slicing clear across the hall.
The mist is quite thick here, and the fissure is too wide to jump.
> wave rod
The bird flies agitatedly about the cage.
A crystal bridge now spans the fissure.
> drop rod
OK
> e
You're in Hall of Mists.
Rough stone steps lead up the dome.
> s
This is a low room with a crude note on the wall. The note says,
"You won't get it up the steps".
There is a large sparkling nugget of gold here!
> take gold
OK
> n
You're in Hall of Mists.
> w
You're on east bank of fissure.
A three foot black rod with a rusty star on an end lies nearby.
A crystal bridge spans the fissure.
> w
You are on the west side of the fissure in the Hall of Mists.
There are diamonds here!
A crystal bridge spans the fissure.
> drop gold
OK
> take diamonds
OK
> w
You are at the west end of the Hall of Mists. A low wide crawl
continues west and another goes north. To the south is a little
passage 6 feet off the floor.
> w
You are at the east end of a very long hall apparently without side
chambers. To the east a low wide crawl slants up. To the north a
round two foot hole slants down.
> w
You are at the west end of a very long featureless hall. The hall
joins up with a narrow north/south passage.
> inventory
You are currently holding the following:
Brass lantern
Wicker cage
Little bird in cage
Tasty food
Small bottle
Water in the bottle
Leporine appendage
Several diamonds
> s
You are in a maze of twisty little passages, all different.
> sw
You are in a little maze of twisty passages, all different.
> se
You are in a little maze of twisting passages, all different.
> s
A little dwarf just walked around a corner, saw you, threw a little
axe at you which missed, cursed, and ran away.
Dead end
There is a little axe here.
There is a massive and somewhat battered vending machine here. The
instructions on it read: "Drop coins here to receive fresh batteries."
> drop food
OK
> drop water
OK
> take axe
OK
> kill machine
As you strike the vending machine, it pivots backward along with a
section of wall, revealing a dark passage leading south.
> s
You are in a long, rough-hewn, north/south corridor.
> s
You are in a large chamber with passages to the west and north.
A formidable ogre bars the northern exit.
> drop diamonds
OK
> w
You are in a long, rough-hewn, north/south corridor.
> w
There is no way to go that direction.
You are in a long, rough-hewn, north/south corridor.
> n
Dead end
There is a bottle of water here.
There is food here.
There is a massive vending machine here, swung back to reveal a
southward passage.
> n
You are in a little maze of twisting passages, all different.
> n
You are in a little maze of twisty passages, all different.
> nw
You are in a maze of twisty little passages, all different.
> d
You're at west end of long hall.
> e
You're at east end of long hall.
> e
You're at west end of Hall of Mists.
> e
You're on west bank of fissure.
There is a large sparkling nugget of gold here!
A crystal bridge spans the fissure.
> take gold
OK
> w
You're at west end of Hall of Mists.
> w
You're at east end of long hall.
> w
You're at west end of long hall.
> s
You are in a maze of twisty little passages, all different.
> sw
You are in a little maze of twisty passages, all different.
> se
You are in a little maze of twisting passages, all different.
> s
Dead end
There is a bottle of water here.
There is food here.
There is a massive vending machine here, swung back to reveal a
southward passage.
> take bottle
OK
> take food
OK
> s
You are in a long, rough-hewn, north/south corridor.
> s
You are in a large chamber with passages to the west and north.
There are diamonds here!
A formidable ogre bars the northern exit.
> throw appendage
OK
> kill ogre
The ogre, who despite his bulk is quite agile, easily dodges your
attack. He seems almost amused by your puny effort.
> take appendage
OK
>
You scored 61 out of a possible 430, using 81 turns.
Your score qualifies you as a novice class adventurer.
To achieve the next higher rating, you need 60 more points.

View file

@ -1,90 +0,0 @@
## Verify that the bird is weightless in inventory
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
# Checks fix for GitLab issue #40
#NOCOMPARE Bird was not weightless in cage in advent430 so this test is invalid.
n
#seed 687800971
seed 976729036
in
take lamp
take food
take bottle
inventory
out
s
w
n
take appendage
s
s
n
in
xyzzy
on
e
take cage
w
w
w
take bird
e
e
take rod
w
w
w
d
inventory
w
wave rod
drop rod
e
s
take gold
n
w
w
drop gold
take diamonds
w
w
w
inventory
s
sw
se
s
drop food
drop water
take axe
kill machine
s
s
drop diamonds
w
w
n
# Back at vending machine
n
n
nw
d
e
e
e
take gold
w
w
w
s
sw
se
s
take bottle
take food
s
s
throw appendage
kill ogre
take appendage

File diff suppressed because it is too large Load diff

View file

@ -1,244 +0,0 @@
## Coverage of LOC_BOULDERS2.short
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 1838473132
in
take lamp
xyzzy
on
take rod
e
take cage
w
w
w
drop rod
take bird
take rod
w
free bird
wave rod
drop rod
take bird
take rod
d
d
free bird
w
e
s
take n
u
s
n
d
n
n
plugh
extin
plugh
on
s
s
sw
take
w
kill drago
y
take rug
e
e
u
d
n
n
off
plugh
drop rug
out
s
w
n
take appen
drop cage
s
s
n
in
take water
plugh
on
plove
ne
s
plove
s
s
u
w
wave rod
drop rod
west
w
w
w
s
sw
se
s
kill machi
s
s
kill ogre
n
s
w
n
n
n
nw
d
e
e
e
e
e
throw axe
take axe
n
n
n
off
plugh
plugh
on
s
s
u
n
n
d
bedqu
throw axe
take
slab
s
d
water plant
u
w
u
reser
H'CFL
n
n
nw
u
u
u
u
ne
sw
d
d
d
d
d
take water
s
s
s
s
d
s
d
water plant
u
drop appen
e
d
get oil
u
w
d
climb
w
n
oil door
drop bottl
n
take tride
w
d
se
n
w
drop tride
drop axe
drop lante
e
take emera
w
take lamp
take axe
take tride
nw
s
se
throw axe
e
w
ne
e
n
open clam
s
u
e
u
n
off
plugh
drop tride
take key
take food
plugh
on
s
d
w
d
n
d
d
u
u
s
w
w
w
w
d
climb
w
get
n
take bottl
n
w
d
sw
u
toss egg
ne
barre
in
feed bear
unloc
take bear
fork
ne
e
out
e

File diff suppressed because it is too large Load diff

View file

@ -1,488 +0,0 @@
## Break the mirror in endgame and die
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 1838473132
in
take lamp
xyzzy
on
take rod
e
take cage
w
w
w
drop rod
take bird
take rod
w
free bird
wave rod
take necklace
drop rod
take bird
take rod
d
d
free bird
drop rod
drop cage
take cage
take bird
w
take coins
e
s
take jewelry
n
up
s
take gold
n
d
n
n
plugh
extinguish lamp
drop coins
drop jewelry
drop necklace
drop gold
plugh
on
s
take silver
s
sw
take axe
w
kill dragon
yes
drink blood
take rug
e
e
up
d
n
n
off
plugh
inven
drop rug
drop silver
out
s
w
n
take appendage
free bird
drop cage
listen
s
s
n
in
take water
plugh
on
plover
ne
take pyramid
s
plover
s
s
take rod
up
w
wave rod
drop rod
west
take diamonds
w
w
w
s
sw
se
s
kill machine
s
s
kill ogre
n
take ruby
s
w
n
n
n
nw
d
e
e
e
e
e
throw axe
take axe
n
n
n
off
plugh
drop ruby
drop diamonds
drop pyramid
plugh
on
s
s
u
n
n
d
bedquilt
throw axe
take axe
slab
s
d
water plant
u
w
u
reservoir
H'CFL
n
n
nw
u
u
u
u
ne
take ebony
sw
d
d
d
d
d
take water
s
s
s
break mirror
s
d
s
d
water plant
u
drop appendage
e
d
get oil
u
w
d
climb
w
n
unlock
oil door
drop bottle
n
take trident
w
d
se
n
w
drop trident
drop ebony
drop axe
drop lantern
e
take emerald
w
take lamp
take axe
take ebony
take trident
nw
s
take vase
se
throw axe
take axe
e
take pillow
w
drop axe
ne
e
n
open clam
s
u
e
u
n
off
plugh
drop pillow
drop vase
drop trident
drop emerald
drop ebony
take keys
take food
plugh
on
s
d
w
d
n
d
d
take pearl
u
u
s
w
w
w
w
d
climb
w
get eggs
n
take bottle
n
w
d
sw
u
toss eggs
ne
ne
barren
in
feed bear
unlock
unlock chain
take chain
take bear
fork
ne
e
take spices
drop keys
fork
w
w
sw
free bear
inven
sw
sw
d
se
se
w
d
get oil
up
e
take axe
w
w
d
climb
w
fee
fie
foe
foo
take eggs
s
d
u
w
u
s
e
e
n
n
off
plugh
drop eggs
drop pearl
drop spices
drop chain
take rug
take ruby
take emerald
out
w
n
n
n
inven
fill urn
light urn
rub urn
take amber
drop rug
drop emerald
fly rug
take sapphire
fly rug
take emerald
drop ruby
take rug
drop bottle
take ruby
e
s
e
e
in
drop ruby
drop sapphire
drop amber
drop rug
look
plugh
on
s
s
u
w
w
w
s
e
s
throw axe
take axe
s
s
n
e
e
nw
take emerald
take chest
se
n
d
e
e
off
xyzzy
drop emerald
drop chest
plugh
on
s
d
w
d
e
take magazine
e
drop magazine
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
u
u
e
u
n
plover
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
cave
e
# Everything to here is from endgame428,
# except we drop the oyster before trying
# to unlock it rather than after.
attack
take oyster
find oyster
lock
lock oyster
drop oyster
unlock oyster
take oyster
read oyster
y
sw
attack bird
find bird
break mirror

View file

@ -1,79 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> seed 1071883378
Seed set to 1071883378
You're in front of building.
> in
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is a bottle of water here.
> take lamp
OK
> rub lamp
Rubbing the electric lamp is not particularly rewarding. Anyway,
nothing exciting happens.
> xyzzy
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You are in a debris room filled with stuff washed in from the surface.
A low wide passage with cobbles becomes plugged with mud and debris
here, but an awkward canyon leads upward and west. In the mud someone
has scrawled, "MAGIC WORD XYZZY".
A three foot black rod with a rusty star on an end lies nearby.
> w
You are in an awkward sloping east/west canyon.
> w
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
from east and west sides of the chamber.
A cheerful little bird is sitting here singing.
> take bird
You can catch the bird, but you cannot carry it.
> attack
The little bird is now dead. Its body disappears.
>
You scored 32 out of a possible 430, using 9 turns.
You are obviously a rank amateur. Better luck next time.
To achieve the next higher rating, you need 14 more points.

View file

@ -1,15 +0,0 @@
## Try to carry bird without cage, then kill bird
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 1071883378
in
take lamp
rub lamp
xyzzy
on
w
w
take bird
# test intransitive attack on bird
attack

View file

@ -1,335 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> seed 1495951709
Seed set to 1495951709
You're in front of building.
> attack
There is nothing here to attack.
> in
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is a bottle of water here.
> take lamp
OK
> on
Your lamp is now on.
> xyzzy
>>Foof!<<
You are in a debris room filled with stuff washed in from the surface.
A low wide passage with cobbles becomes plugged with mud and debris
here, but an awkward canyon leads upward and west. In the mud someone
has scrawled, "MAGIC WORD XYZZY".
A three foot black rod with a rusty star on an end lies nearby.
> take rod
OK
> e
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
There is a small wicker cage discarded nearby.
> take cage
OK
> w
You're in debris room.
> w
You are in an awkward sloping east/west canyon.
> w
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
from east and west sides of the chamber.
A cheerful little bird is sitting here singing.
> drop rod
OK
> take bird
OK
> take rod
OK
> w
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
Rough stone steps lead down the pit.
> free bird
OK
> wave rod
The bird flies about agitatedly for a moment, then disappears through
the crack. It reappears shortly, carrying in its beak a jade
necklace, which it drops at your feet.
> take jade
OK
> drop rod
OK
> take bird
OK
> take rod
OK
> d
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
staircase leads downward. The hall is filled with wisps of white mist
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
Rough stone steps lead up the dome.
> w
You are on the east bank of a fissure slicing clear across the hall.
The mist is quite thick here, and the fissure is too wide to jump.
> wave rod
The bird flies agitatedly about the cage.
A crystal bridge now spans the fissure.
> drop rod
OK
> e
You're in Hall of Mists.
Rough stone steps lead up the dome.
> n
You are in the Hall of the Mountain King, with passages off in all
directions.
A huge green fierce snake bars the way!
> free bird
The little bird attacks the green snake, and in an astounding flurry
drives the snake away.
> take bird
OK
> s
You are in the south side chamber.
There is precious jewelry here!
> take jewelry
OK
> n
You're in Hall of Mt King.
> sw
You are in a secret canyon which here runs e/w. It crosses over a
very tight canyon 15 feet below. If you go down you may not be able
to get back up.
> w
You are in a secret canyon which exits to the north and east.
A huge green fierce dragon bars the way!
The dragon is sprawled out on a Persian rug!!
> kill dragon
With what? Your bare hands?
> yes
Congratulations! You have just vanquished a dragon with your bare
hands! (Unbelievable, isn't it?)
You are in a secret canyon which exits to the north and east.
There is a Persian rug spread out on the floor!
The blood-specked body of a huge green dead dragon lies to one side.
> drink blood
Your head buzzes strangely for a moment.
> take rug
OK
> e
You're in secret e/w canyon above tight canyon.
> e
You're in Hall of Mt King.
> n
You are in a low n/s passage at a hole in the floor. The hole goes
down to an e/w passage.
There are bars of silver here!
> take silver
OK
> n
You are in a large room, with a passage to the south, a passage to the
west, and a wall of broken rock to the east. There is a large "Y2" on
a rock in the room's center.
> plugh
>>Foof!<<
You're inside building.
There are some keys on the ground here.
There is food here.
There is a bottle of water here.
> drop silver
OK
> drop jewelry
OK
> drop jade
OK
> drop rug
OK
> out
You're in front of building.
> s
You are in a valley in the forest beside a stream tumbling along a
rocky bed.
> w
You are wandering aimlessly through the forest.
> n
You are wandering aimlessly through the forest.
Your keen eye spots a severed leporine appendage lying on the ground.
> take appendage
OK
> drop cage
OK
> look
Sorry, but I am not allowed to give more detail. I will repeat the
long description of your location.
You are wandering aimlessly through the forest.
There is a small wicker cage discarded nearby.
There is a little bird in the cage.
> take cage
OK
> free bird
OK
> carry bird
The bird eyes you suspiciously and flutters away. A moment later you
feel something wet land on your head, but upon looking up you can see
no sign of the culprit.
>
You scored 113 out of a possible 430, using 57 turns.
Your score qualifies you as a novice class adventurer.
To achieve the next higher rating, you need 8 more points.

View file

@ -1,63 +0,0 @@
## Try to carry the bird after freeing it instead of listening
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 1495951709
attack
in
take lamp
on
xyzzy
take rod
e
take cage
w
w
w
drop rod
take bird
take rod
w
free bird
wave rod
take jade
drop rod
take bird
take rod
d
w
wave rod
drop rod
e
n
free bird
take bird
s
take jewelry
n
sw
w
kill dragon
yes
drink blood
take rug
e
e
n
take silver
n
plugh
drop silver
drop jewelry
drop jade
drop rug
out
s
w
n
take appendage
drop cage
look
take cage
free bird
carry bird

View file

@ -1,27 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> resume
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
>
Now let's see you do it without suspending in mid-Adventure.
You scored 9031 out of a possible 430, using 0 turns.
Adventuredom stands in awe -- you have now joined the ranks of the
W O R L D C H A M P I O N A D V E N T U R E R S !
It may interest you to know that the Dungeon-Master himself has, to
my knowledge, never achieved this threshold in fewer than 330 turns.
To achieve the next higher rating would be a neat trick!
Congratulations!!

View file

@ -1,7 +0,0 @@
## Resume from absurd save file with numdie = -900
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
#NOCOMPARE Can't compare to advent430 due to version skew
n
resume
cheat_numdie.adv

View file

@ -1,21 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> resume
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
>
Now let's see you do it without suspending in mid-Adventure.
You scored 10031 out of a possible 430, using 0 turns.
You just went off my scale!!

View file

@ -1,8 +0,0 @@
## Resume from absurd save file with numdie = -1000
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
# generating "off my scale" score threshold message
#NOCOMPARE Can't compare to advent430 due to version skew
n
resume
cheat_numdie1000.adv

View file

@ -1,4 +0,0 @@
#! /bin/sh
# Display diff for an individual test
test=$1
../advent <${test}.log | ./tapdiffer "${test}" "${test}.chk"

View file

@ -1,307 +0,0 @@
#!/usr/bin/env python3
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
"""
This is the open-adventure dungeon text coverage report generator. It
consumes a YAML description of the dungeon and determines whether the
various strings contained are present within the test check files.
The default HTML output is appropriate for use with Gitlab CI.
You can override it with a command-line argument.
The DANGLING lists are for actions and messages that should be
considered always found even if the checkfile search doesn't find them.
Typically this will because an action emit a templated message that
can't be regression-tested by equality.
"""
# pylint: disable=consider-using-f-string,line-too-long,invalid-name,missing-function-docstring,redefined-outer-name
import os
import sys
import re
import yaml
TEST_DIR = "."
YAML_PATH = "../adventure.yaml"
HTML_TEMPLATE_PATH = "../templates/coverage_dungeon.html.tpl"
DEFAULT_HTML_OUTPUT_PATH = "../coverage/adventure.yaml.html"
DANGLING_ACTIONS = ["ACT_VERSION"]
DANGLING_MESSAGES = ["SAVERESUME_DISABLED"]
STDOUT_REPORT_CATEGORY = (
" {name:.<19}: {percent:5.1f}% covered ({covered} of {total})\n"
)
HTML_SUMMARY_ROW = """
<tr>
<td class="headerItem"><a href="#{name}">{name}:</a></td>
<td class="headerCovTableEntry">{total}</td>
<td class="headerCovTableEntry">{covered}</td>
<td class="headerCovTableEntry">{percent:.1f}%</td>
</tr>
"""
HTML_CATEGORY_SECTION = """
<tr id="{id}"></tr>
{rows}
<tr>
<td>&nbsp;</td>
</tr>
"""
HTML_CATEGORY_HEADER = """
<tr>
<td class="tableHead" width="60%" colspan="{colspan}">{label}</td>
{cells}
</tr>
"""
HTML_CATEGORY_HEADER_CELL = '<td class="tableHead" width="15%">{}</td>\n'
HTML_CATEGORY_COVERAGE_CELL = '<td class="{}">&nbsp;</td>\n'
HTML_CATEGORY_ROW = """
<tr>
<td class="coverFile" colspan="{colspan}">{id}</td>
{cells}
</tr>
"""
def search(needle, haystack):
# Search for needle in haystack, first escaping needle for regex, then
# replacing %s, %d, etc. with regex wildcards, so the variable messages
# within the dungeon definition will actually match
if needle is None or needle == "" or needle == "NO_MESSAGE":
# if needle is empty, assume we're going to find an empty string
return True
needle_san = (
re.escape(needle)
.replace("\\n", "\n")
.replace("\\t", "\t")
.replace("%S", ".*")
.replace("%s", ".*")
.replace("%d", ".*")
.replace("%V", ".*")
)
return re.search(needle_san, haystack)
def obj_coverage(objects, text, report):
# objects have multiple descriptions based on state
for _, objouter in enumerate(objects):
(obj_name, obj) = objouter
if obj["descriptions"]:
for j, desc in enumerate(obj["descriptions"]):
name = "{}[{}]".format(obj_name, j)
if name not in report["messages"]:
report["messages"][name] = {"covered": False}
report["total"] += 1
if not report["messages"][name]["covered"] and search(desc, text):
report["messages"][name]["covered"] = True
report["covered"] += 1
def loc_coverage(locations, text, report):
# locations have a long and a short description, that each have to
# be checked separately
for name, loc in locations:
desc = loc["description"]
if name not in report["messages"]:
report["messages"][name] = {"long": False, "short": False}
report["total"] += 2
if not report["messages"][name]["long"] and search(desc["long"], text):
report["messages"][name]["long"] = True
report["covered"] += 1
if not report["messages"][name]["short"] and search(desc["short"], text):
report["messages"][name]["short"] = True
report["covered"] += 1
def hint_coverage(obituaries, text, report):
# hints have a "question" where the hint is offered, followed
# by the actual hint if the player requests it
for _, hintouter in enumerate(obituaries):
hint = hintouter["hint"]
name = hint["name"]
if name not in report["messages"]:
report["messages"][name] = {"question": False, "hint": False}
report["total"] += 2
if not report["messages"][name]["question"] and search(hint["question"], text):
report["messages"][name]["question"] = True
report["covered"] += 1
if not report["messages"][name]["hint"] and search(hint["hint"], text):
report["messages"][name]["hint"] = True
report["covered"] += 1
def obit_coverage(obituaries, text, report):
# obituaries have a "query" where it asks the player for a resurrection,
# followed by a snarky comment if the player says yes
for name, obit in enumerate(obituaries):
if name not in report["messages"]:
report["messages"][name] = {"query": False, "yes_response": False}
report["total"] += 2
if not report["messages"][name]["query"] and search(obit["query"], text):
report["messages"][name]["query"] = True
report["covered"] += 1
if not report["messages"][name]["yes_response"] and search(
obit["yes_response"], text
):
report["messages"][name]["yes_response"] = True
report["covered"] += 1
def threshold_coverage(classes, text, report):
# works for class thresholds and turn threshold, which have a "message"
# property
for name, item in enumerate(classes):
if name not in report["messages"]:
report["messages"][name] = {"covered": False}
report["total"] += 1
if not report["messages"][name]["covered"] and search(item["message"], text):
report["messages"][name]["covered"] = True
report["covered"] += 1
def arb_coverage(arb_msgs, text, report):
for name, message in arb_msgs:
if name not in report["messages"]:
report["messages"][name] = {"covered": False}
report["total"] += 1
if not report["messages"][name]["covered"] and (
search(message, text) or name in DANGLING_MESSAGES
):
report["messages"][name]["covered"] = True
report["covered"] += 1
def actions_coverage(items, text, report):
# works for actions
for name, item in items:
if name not in report["messages"]:
report["messages"][name] = {"covered": False}
report["total"] += 1
if not report["messages"][name]["covered"] and (
search(item["message"], text) or name in DANGLING_ACTIONS
):
report["messages"][name]["covered"] = True
report["covered"] += 1
def coverage_report(db, check_file_contents):
# Create report for each category, including total items, number of items
# covered, and a list of the covered messages
report = {}
for name in db.keys():
# initialize each catagory
report[name] = {
"name": name, # convenience for string formatting
"total": 0,
"covered": 0,
"messages": {},
}
# search for each message in every test check file
for chk in check_file_contents:
arb_coverage(db["arbitrary_messages"], chk, report["arbitrary_messages"])
hint_coverage(db["hints"], chk, report["hints"])
loc_coverage(db["locations"], chk, report["locations"])
obit_coverage(db["obituaries"], chk, report["obituaries"])
obj_coverage(db["objects"], chk, report["objects"])
actions_coverage(db["actions"], chk, report["actions"])
threshold_coverage(db["classes"], chk, report["classes"])
threshold_coverage(db["turn_thresholds"], chk, report["turn_thresholds"])
return report
if __name__ == "__main__":
# load DB
try:
with open(YAML_PATH, "r", encoding="ascii", errors="surrogateescape") as f:
db = yaml.safe_load(f)
except IOError as e:
print("ERROR: could not load %s (%s)" % (YAML_PATH, e.strerror))
sys.exit(-1)
# get contents of all the check files
check_file_contents = []
for filename in os.listdir(TEST_DIR):
if filename.endswith(".chk"):
with open(filename, "r", encoding="ascii", errors="surrogateescape") as f:
check_file_contents.append(f.read())
# run coverage analysis report on dungeon database
report = coverage_report(db, check_file_contents)
# render report output
categories_html = ""
summary_html = ""
summary_stdout = "adventure.yaml coverage rate:\n"
for name, category in sorted(report.items()):
# ignore categories with zero entries
if category["total"] > 0:
# Calculate percent coverage
category["percent"] = (category["covered"] / float(category["total"])) * 100
# render section header
cat_messages = list(category["messages"].items())
cat_keys = cat_messages[0][1].keys()
headers_html = ""
colspan = 10 - len(cat_keys)
for key in cat_keys:
headers_html += HTML_CATEGORY_HEADER_CELL.format(key)
category_html = HTML_CATEGORY_HEADER.format(
colspan=colspan, label=category["name"], cells=headers_html
)
# render message coverage row
for message_id, covered in cat_messages:
category_html_row = ""
for key, value in covered.items():
category_html_row += HTML_CATEGORY_COVERAGE_CELL.format(
"uncovered" if not value else "covered"
)
category_html += HTML_CATEGORY_ROW.format(
id=message_id, colspan=colspan, cells=category_html_row
)
categories_html += HTML_CATEGORY_SECTION.format(id=name, rows=category_html)
# render category summaries
summary_stdout += STDOUT_REPORT_CATEGORY.format(**category)
summary_html += HTML_SUMMARY_ROW.format(**category)
# output some quick report stats
print(summary_stdout)
if len(sys.argv) > 1:
html_output_path = sys.argv[1]
else:
html_output_path = DEFAULT_HTML_OUTPUT_PATH
# render HTML report
try:
with open(
HTML_TEMPLATE_PATH, "r", encoding="ascii", errors="surrogateescape"
) as f:
# read in HTML template
html_template = f.read()
except IOError as e:
print("ERROR: reading HTML report template failed ({})".format(e.strerror))
sys.exit(-1)
# parse template with report and write it out
try:
with open(
html_output_path, "w", encoding="ascii", errors="surrogateescape"
) as f:
f.write(
html_template.format(categories=categories_html, summary=summary_html)
)
except IOError as e:
print("ERROR: writing HTML report failed ({})".format(e.strerror))

View file

@ -1,89 +1,76 @@
Welcome to Adventure!! Would you like instructions?
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> seed 1495774850
Seed set to 1495774850
You're in front of building.
You're in front of building.
> in
You are inside a building, a well house for a large spring.
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is food here.
There is a bottle of water here.
There is a bottle of water here.
> take keys
OK
OK
> take lamp
OK
OK
> out
You're in front of building.
You're in front of building.
> s
You are in a valley in the forest beside a stream tumbling along a
You are in a valley in the forest beside a stream tumbling along a
rocky bed.
> s
At your feet all the water of the stream splashes into a 2-inch slit
in the rock. Downstream the streambed is bare rock.
At your feet all the water of the stream splashes into a 2-inch slit
in the rock. Downstream the streambed is bare rock.
> s
You are in a 20-foot depression floored with bare dirt. Set into the
dirt is a strong steel grate mounted in concrete. A dry streambed
leads into the depression.
You are in a 20-foot depression floored with bare dirt. Set into the
dirt is a strong steel grate mounted in concrete. A dry streambed
leads into the depression.
The grate is locked.
> open grate
The grate is now unlocked.
The grate is now unlocked.
> d
You are in a small chamber beneath a 3x3 steel grate to the surface.
A low crawl over cobbles leads inward to the west.
The grate is open.
> u
You're outside grate.
The grate is open.
> d
You're below the grate.
The grate is open.
The grate is open.
> w
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
There is a small wicker cage discarded nearby.
There is a small wicker cage discarded nearby.
> w
@ -94,69 +81,60 @@ It is now pitch dark. If you proceed you will likely fall into a pit.
Your lamp is now on.
You are in a debris room filled with stuff washed in from the surface.
A low wide passage with cobbles becomes plugged with mud and debris
A low wide passage with cobbles becomes plugged with mud and debris
here, but an awkward canyon leads upward and west. In the mud someone
has scrawled, "MAGIC WORD XYZZY".
has scrawled, "MAGIC WORD XYZZY".
A three foot black rod with a rusty star on an end lies nearby.
A three foot black rod with a rusty star on an end lies nearby.
> w
You are in an awkward sloping east/west canyon.
You are in an awkward sloping east/west canyon.
> w
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
from east and west sides of the chamber.
A cheerful little bird is sitting here singing.
A cheerful little bird is sitting here singing.
> w
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
Rough stone steps lead down the pit.
> crack
The crack is far too small for you to follow. At its widest it is
barely wide enough to admit your foot.
You're at top of small pit.
Rough stone steps lead down the pit.
Rough stone steps lead down the pit.
> down
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
staircase leads downward. The hall is filled with wisps of white mist
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
Rough stone steps lead up the dome.
> w
You are on the east bank of a fissure slicing clear across the hall.
The mist is quite thick here, and the fissure is too wide to jump.
You are on the east bank of a fissure slicing clear across the hall.
The mist is quite thick here, and the fissure is too wide to jump.
> jump
You didn't make it.
You didn't make it.
Oh dear, you seem to have gotten yourself killed. I might be able to
help you out, but I've never really done this before. Do you want me
to try to reincarnate you?
Oh dear, you seem to have gotten yourself killed. I might be able to
help you out, but I've never really done this before. Do you want me
to try to reincarnate you?
> n
OK
OK
You scored 51 out of a possible 430, using 21 turns.
You scored 51 out of a possible 430, using 18 turns.
Your score qualifies you as a novice class adventurer.
Your score qualifies you as a novice class adventurer.
To achieve the next higher rating, you need 70 more points.
To achieve the next higher rating, you need 70 more points.

View file

@ -1,29 +0,0 @@
## Jump into a pit and die, refuse reincarnation
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 1495774850
in
take keys
take lamp
out
s
s
s
open grate
d
# go back up and down again because of coverage
u
d
w
w
light lamp
w
w
w
# attempt and fail to traverse the crack because coverage
crack
down
w
jump
n

View file

@ -1,3 +0,0 @@
#!/bin/sh
# Turn a non-oldstyle checkfile on stdin into an equivalent log on stdout.
sed -n -e '/> /s///p'

File diff suppressed because it is too large Load diff

View file

@ -1,497 +0,0 @@
## Last-minute defeat, with lava. Also tests vase drop before pillow.
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
# Based on walkthrough at http://www.ecsoftwareconsulting.com/node/56
n
seed 1838473132
in
take lamp
xyzzy
on
take rod
e
take cage
go west
go west
go west
drop rod
take bird
take rod
go west
free bird
wave rod
take necklace
drop rod
take bird
take rod
d
d
free bird
drop rod
drop cage
take cage
take bird
go west
take coins
e
s
take jewelry
n
up
s
take gold
n
d
n
n
plugh
extinguish lamp
drop coins
drop jewelry
drop necklace
drop gold
plugh
on
s
take silver
s
sw
take axe
go west
kill dragon
yes
drink blood
take rug
e
e
up
d
n
n
off
plugh
inven
drop rug
drop silver
out
s
go west
n
take appendage
free bird
drop cage
listen
s
s
n
in
take water
plugh
on
plover
ne
take pyramid
s
plover
s
s
take rod
up
go west
wave rod
drop rod
west
take diamonds
go west
go west
go west
s
sw
se
s
kill machine
s
s
kill ogre
n
take ruby
s
west
n
n
n
nw
d
e
e
e
e
e
throw axe
take axe
n
n
n
off
plugh
drop ruby
drop diamonds
drop pyramid
plugh
on
s
s
u
n
n
d
bedquilt
throw axe
take axe
slab
s
d
water plant
u
west
u
reservoir
say H'CFL
n
n
nw
u
u
u
u
ne
take ebony
sw
d
d
d
d
d
take water
s
s
s
s
d
s
d
water plant
u
drop appendage
e
d
get oil
u
west
d
climb
west
n
oil door
drop bottle
n
take trident
west
d
se
n
west
drop trident
drop ebony
drop axe
drop lantern
e
take emerald
west
take lamp
take axe
take ebony
take trident
nw
s
take vase
se
throw axe
take axe
e
take pillow
west
drop axe
ne
e
n
open clam
open oyster
s
u
e
u
n
off
plugh
# Invert these so we test the vase-drop code
drop vase
drop pillow
drop trident
drop emerald
drop ebony
take keys
take food
plugh
on
s
d
west
d
n
d
d
take pearl
u
u
s
west
west
west
west
d
climb
west
get eggs
n
take bottle
n
west
d
sw
u
toss eggs
ne
ne
barren
in
feed bear
unlock chain
take chain
take bear
fork
ne
e
take spices
drop keys
fork
west
west
sw
free bear
inven
sw
sw
d
se
se
west
d
get oil
up
e
take axe
west
west
d
climb
west
fee
fie
foe
foo
take eggs
s
d
u
west
u
s
e
e
n
n
off
plugh
drop eggs
drop pearl
drop spices
drop chain
take rug
take ruby
take emerald
out
west
n
n
n
inven
fill urn
light urn
rub urn
take amber
drop rug
# fly rug before dropping emerald, triggering RUG_NOTHING1
fly rug
drop emerald
fly rug
take sapphire
fly
take emerald
drop ruby
take rug
drop bottle
take ruby
drop emerald
take emerald
e
s
e
e
in
drop ruby
drop sapphire
drop amber
drop rug
look
plugh
on
s
s
u
west
west
west
s
e
s
throw axe
take axe
s
s
n
e
e
nw
take emerald
take chest
se
n
d
e
e
off
xyzzy
drop emerald
drop chest
plugh
on
s
d
west
d
e
read sign
take magazine
e
drop magazine
w
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
u
u
e
u
n
plover
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
take oyster
# Test both cases (before and after hint) of reading oyster
read oyster
y
read oyster
drop oyster
open oyster
sw
# We want the xyzzy and plugh words to fail here
xyzzy
plugh
read sign
carry sign
take rod
drop rod
# look to see dropped rod on ground. Different state than
# before we picked it up.
look
ne
listen
blast rod

View file

@ -1,174 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> seed 1838473132
Seed set to 1838473132
You're in front of building.
> in
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is a bottle of water here.
> take lamp
OK
> xyzzy
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You are in a debris room filled with stuff washed in from the surface.
A low wide passage with cobbles becomes plugged with mud and debris
here, but an awkward canyon leads upward and west. In the mud someone
has scrawled, "MAGIC WORD XYZZY".
A three foot black rod with a rusty star on an end lies nearby.
> e
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
There is a small wicker cage discarded nearby.
> take cage
OK
> w
You're in debris room.
A three foot black rod with a rusty star on an end lies nearby.
> w
You are in an awkward sloping east/west canyon.
> w
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
from east and west sides of the chamber.
A cheerful little bird is sitting here singing.
> take
OK
> w
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
Rough stone steps lead down the pit.
> d
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
staircase leads downward. The hall is filled with wisps of white mist
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
Rough stone steps lead up the dome.
> d
You are in the Hall of the Mountain King, with passages off in all
directions.
A huge green fierce snake bars the way!
> free bird
The little bird attacks the green snake, and in an astounding flurry
drives the snake away.
> w
You are in the west side chamber of the Hall of the Mountain King.
A passage continues west and up here.
There are many coins here!
> e
You're in Hall of Mt King.
A cheerful little bird is sitting here singing.
> s
You are in the south side chamber.
There is precious jewelry here!
> n
You're in Hall of Mt King.
A cheerful little bird is sitting here singing.
> u
You're in Hall of Mists.
Rough stone steps lead up the dome.
> s
This is a low room with a crude note on the wall. The note says,
"You won't get it up the steps".
There is a large sparkling nugget of gold here!
> take nugget
OK
> n
You're in Hall of Mists.
> dome
The dome is unclimbable.
You're in Hall of Mists.
> u
The dome is unclimbable.
You're in Hall of Mists.
>
You scored 63 out of a possible 430, using 24 turns.
Your score qualifies you as a novice class adventurer.
To achieve the next higher rating, you need 58 more points.

View file

@ -1,29 +0,0 @@
## Take nugget and fail to climb to the dome
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 1838473132
in
take lamp
xyzzy
on
e
take cage
w
w
w
take
w
d
d
free bird
w
e
s
n
u
s
take nugget
n
dome
u

View file

@ -1,254 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> seed 18084731
Seed set to 18084731
You're in front of building.
> in
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is a bottle of water here.
> take lamp
OK
> xyzzy
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You are in a debris room filled with stuff washed in from the surface.
A low wide passage with cobbles becomes plugged with mud and debris
here, but an awkward canyon leads upward and west. In the mud someone
has scrawled, "MAGIC WORD XYZZY".
A three foot black rod with a rusty star on an end lies nearby.
> e
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
There is a small wicker cage discarded nearby.
> take
OK
> w
You're in debris room.
A three foot black rod with a rusty star on an end lies nearby.
> w
You are in an awkward sloping east/west canyon.
> w
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
from east and west sides of the chamber.
A cheerful little bird is sitting here singing.
> cage bird
OK
> w
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
Rough stone steps lead down the pit.
> d
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
staircase leads downward. The hall is filled with wisps of white mist
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
Rough stone steps lead up the dome.
> d
You are in the Hall of the Mountain King, with passages off in all
directions.
A huge green fierce snake bars the way!
> free bird
The little bird attacks the green snake, and in an astounding flurry
drives the snake away.
> w
You are in the west side chamber of the Hall of the Mountain King.
A passage continues west and up here.
There are many coins here!
> e
You're in Hall of Mt King.
A cheerful little bird is sitting here singing.
> s
You are in the south side chamber.
There is precious jewelry here!
> u
There is no way to go that direction.
You are in the south side chamber.
There is precious jewelry here!
> s
There is no way to go that direction.
You are in the south side chamber.
There is precious jewelry here!
> n
You're in Hall of Mt King.
A cheerful little bird is sitting here singing.
> d
There is no way to go that direction.
You're in Hall of Mt King.
A cheerful little bird is sitting here singing.
> n
You are in a low n/s passage at a hole in the floor. The hole goes
down to an e/w passage.
There are bars of silver here!
> n
You are in a large room, with a passage to the south, a passage to the
west, and a wall of broken rock to the east. There is a large "Y2" on
a rock in the room's center.
> plugh
>>Foof!<<
You're inside building.
There are some keys on the ground here.
There is food here.
There is a bottle of water here.
> extin
Your lamp is now off.
> plugh
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You're at "Y2".
> s
You're in n/s passage above e/w passage.
There are bars of silver here!
> s
You're in Hall of Mt King.
A cheerful little bird is sitting here singing.
> sw
You are in a secret canyon which here runs e/w. It crosses over a
very tight canyon 15 feet below. If you go down you may not be able
to get back up.
> w
A little dwarf just walked around a corner, saw you, threw a little
axe at you which missed, cursed, and ran away.
You are in a secret canyon which exits to the north and east.
There is a little axe here.
A huge green fierce dragon bars the way!
The dragon is sprawled out on a Persian rug!!
> kill drago
With what? Your bare hands?
> y
Congratulations! You have just vanquished a dragon with your bare
hands! (Unbelievable, isn't it?)
You are in a secret canyon which exits to the north and east.
There is a little axe here.
There is a Persian rug spread out on the floor!
The blood-specked body of a huge green dead dragon lies to one side.
>
You scored 65 out of a possible 430, using 32 turns.
Your score qualifies you as a novice class adventurer.
To achieve the next higher rating, you need 56 more points.

View file

@ -1,38 +0,0 @@
## Check that dead dragon actually moves its location (fuzzed)
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 18084731
in
take lamp
xyzzy
on
e
take
w
w
w
cage bird
w
d
d
free bird
w
e
s
u
s
n
d
n
n
plugh
extin
plugh
on
s
s
sw
w
kill drago
y

View file

@ -1,158 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> seed 1495951709
Seed set to 1495951709
You're in front of building.
> in
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is a bottle of water here.
> take lamp
OK
> on
Your lamp is now on.
> xyzzy
>>Foof!<<
You are in a debris room filled with stuff washed in from the surface.
A low wide passage with cobbles becomes plugged with mud and debris
here, but an awkward canyon leads upward and west. In the mud someone
has scrawled, "MAGIC WORD XYZZY".
A three foot black rod with a rusty star on an end lies nearby.
> take rod
OK
> e
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
There is a small wicker cage discarded nearby.
> take cage
OK
> w
You're in debris room.
> w
You are in an awkward sloping east/west canyon.
> w
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
from east and west sides of the chamber.
A cheerful little bird is sitting here singing.
> wave rod
The bird flies about agitatedly for a moment.
> take bird
The bird seemed unafraid at first, but as you approach it becomes
disturbed and you cannot catch it.
> drop rod
OK
> take bird
OK
> take rod
OK
> w
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
Rough stone steps lead down the pit.
> free bird
OK
> wave rod
The bird flies about agitatedly for a moment, then disappears through
the crack. It reappears shortly, carrying in its beak a jade
necklace, which it drops at your feet.
> take jade
OK
> drop rod
OK
> take bird
OK
> drop cage
OK
> d
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
staircase leads downward. The hall is filled with wisps of white mist
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
Rough stone steps lead up the dome.
> d
You are in the Hall of the Mountain King, with passages off in all
directions.
A huge green fierce snake bars the way!
> feed snake
There's nothing here it wants to eat (except perhaps you).
>
You scored 59 out of a possible 430, using 25 turns.
Your score qualifies you as a novice class adventurer.
To achieve the next higher rating, you need 62 more points.

View file

@ -1,30 +0,0 @@
## Try to carry the bird after freeing it instead of listening
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 1495951709
in
take lamp
on
xyzzy
take rod
e
take cage
w
w
w
wave rod
take bird
drop rod
take bird
take rod
w
free bird
wave rod
take jade
drop rod
take bird
drop cage
d
d
feed snake

View file

@ -1,966 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> seed 1838473132
Seed set to 1838473132
You're in front of building.
> in
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is a bottle of water here.
> take lamp
OK
> xyzzy
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You are in a debris room filled with stuff washed in from the surface.
A low wide passage with cobbles becomes plugged with mud and debris
here, but an awkward canyon leads upward and west. In the mud someone
has scrawled, "MAGIC WORD XYZZY".
A three foot black rod with a rusty star on an end lies nearby.
> take rod
OK
> e
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
There is a small wicker cage discarded nearby.
> take cage
OK
> w
You're in debris room.
> w
You are in an awkward sloping east/west canyon.
> w
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
from east and west sides of the chamber.
A cheerful little bird is sitting here singing.
> drop rod
OK
> take bird
OK
> take rod
OK
> w
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
Rough stone steps lead down the pit.
> free bird
OK
> wave rod
The bird flies about agitatedly for a moment, then disappears through
the crack. It reappears shortly, carrying in its beak a jade
necklace, which it drops at your feet.
> take necklace
OK
> drop rod
OK
> take bird
OK
> take rod
OK
> d
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
staircase leads downward. The hall is filled with wisps of white mist
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
Rough stone steps lead up the dome.
> d
You are in the Hall of the Mountain King, with passages off in all
directions.
A huge green fierce snake bars the way!
> free bird
The little bird attacks the green snake, and in an astounding flurry
drives the snake away.
> drop rod
OK
> drop cage
OK
> take cage
OK
> take bird
OK
> w
You are in the west side chamber of the Hall of the Mountain King.
A passage continues west and up here.
There are many coins here!
> take coins
OK
> e
You're in Hall of Mt King.
A three foot black rod with a rusty star on an end lies nearby.
> s
You are in the south side chamber.
There is precious jewelry here!
> take jewelry
OK
> n
You're in Hall of Mt King.
A three foot black rod with a rusty star on an end lies nearby.
> up
You're in Hall of Mists.
Rough stone steps lead up the dome.
> s
This is a low room with a crude note on the wall. The note says,
"You won't get it up the steps".
There is a large sparkling nugget of gold here!
> take gold
OK
> n
You're in Hall of Mists.
> d
You're in Hall of Mt King.
A three foot black rod with a rusty star on an end lies nearby.
> n
You are in a low n/s passage at a hole in the floor. The hole goes
down to an e/w passage.
There are bars of silver here!
> n
You are in a large room, with a passage to the south, a passage to the
west, and a wall of broken rock to the east. There is a large "Y2" on
a rock in the room's center.
A hollow voice says "PLUGH".
> plugh
>>Foof!<<
You're inside building.
There are some keys on the ground here.
There is food here.
There is a bottle of water here.
> extinguish lamp
Your lamp is now off.
> drop coins
OK
> drop jewelry
OK
> drop necklace
OK
> drop gold
OK
> plugh
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You're at "Y2".
> s
You're in n/s passage above e/w passage.
There are bars of silver here!
> take silver
OK
> s
You're in Hall of Mt King.
A three foot black rod with a rusty star on an end lies nearby.
> sw
A little dwarf just walked around a corner, saw you, threw a little
axe at you which missed, cursed, and ran away.
You are in a secret canyon which here runs e/w. It crosses over a
very tight canyon 15 feet below. If you go down you may not be able
to get back up.
There is a little axe here.
> take axe
OK
> w
You are in a secret canyon which exits to the north and east.
A huge green fierce dragon bars the way!
The dragon is sprawled out on a Persian rug!!
> kill dragon
With what? Your bare hands?
> yes
Congratulations! You have just vanquished a dragon with your bare
hands! (Unbelievable, isn't it?)
You are in a secret canyon which exits to the north and east.
There is a Persian rug spread out on the floor!
The blood-specked body of a huge green dead dragon lies to one side.
> feed dragon
Don't be ridiculous!
> drink blood
Your head buzzes strangely for a moment.
> take rug
OK
> e
You're in secret e/w canyon above tight canyon.
> e
You are in the Hall of the Mountain King, with passages off in all
directions.
A three foot black rod with a rusty star on an end lies nearby.
> up
There is a threatening little dwarf in the room with you!
One sharp nasty knife is thrown at you!
It misses!
You're in Hall of Mists.
Rough stone steps lead up the dome.
> d
There is a threatening little dwarf in the room with you!
You're in Hall of Mt King.
A three foot black rod with a rusty star on an end lies nearby.
> n
There is a threatening little dwarf in the room with you!
You're in n/s passage above e/w passage.
> n
There is a threatening little dwarf in the room with you!
You're at "Y2".
A hollow voice says "PLUGH".
> off
Your lamp is now off.
It is now pitch dark. If you proceed you will likely fall into a pit.
> plugh
>>Foof!<<
You're inside building.
There is a large sparkling nugget of gold here!
A precious jade necklace has been dropped here!
There is precious jewelry here!
There are many coins here!
There are some keys on the ground here.
There is food here.
There is a bottle of water here.
> inven
You are currently holding the following:
Brass lantern
Wicker cage
Little bird in cage
Dwarf's axe
Bars of silver
Persian rug
> drop rug
OK
> drop silver
OK
> out
You're in front of building.
> s
You are in a valley in the forest beside a stream tumbling along a
rocky bed.
> w
You are wandering aimlessly through the forest.
> n
You are wandering aimlessly through the forest.
Your keen eye spots a severed leporine appendage lying on the ground.
> take appendage
OK
> free bird
OK
> drop cage
OK
> listen
The bird is singing to you in gratitude for your having returned it to
its home. In return, it informs you of a magic word which it thinks
you may find useful somewhere near the Hall of Mists. The magic word
changes frequently, but for now the bird believes it is "H'CFL". You
thank the bird for this information, and it flies off into the forest.
> s
You are wandering aimlessly through the forest.
> s
You're in valley.
> n
You're in front of building.
> in
You're inside building.
There are bars of silver here!
There is a Persian rug spread out on the floor!
There is a large sparkling nugget of gold here!
A precious jade necklace has been dropped here!
There is precious jewelry here!
There are many coins here!
There are some keys on the ground here.
There is food here.
There is a bottle of water here.
> take water
OK
> plugh
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You're at "Y2".
> plover
>>Foof!<<
You're in a small chamber lit by an eerie green light. An extremely
narrow tunnel exits to the west. A dark corridor leads ne.
There is an emerald here the size of a plover's egg!
> ne
You're in the dark-room. A corridor leading south is the only exit.
A massive stone tablet embedded in the wall reads:
"Congratulations on bringing light into the dark-room!"
There is a platinum pyramid here, 8 inches on a side!
> take pyramid
OK
> s
You're in Plover Room.
There is an emerald here the size of a plover's egg!
> plover
>>Foof!<<
You're at "Y2".
A hollow voice says "PLUGH".
> s
You're in n/s passage above e/w passage.
> s
You're in Hall of Mt King.
A three foot black rod with a rusty star on an end lies nearby.
> take rod
OK
> up
You're in Hall of Mists.
Rough stone steps lead up the dome.
> w
You are on the east bank of a fissure slicing clear across the hall.
The mist is quite thick here, and the fissure is too wide to jump.
> wave rod
A crystal bridge now spans the fissure.
> drop rod
OK
> west
You are on the west side of the fissure in the Hall of Mists.
There are diamonds here!
A crystal bridge spans the fissure.
> take diamonds
OK
> w
There is a threatening little dwarf in the room with you!
One sharp nasty knife is thrown at you!
It misses!
You are at the west end of the Hall of Mists. A low wide crawl
continues west and another goes north. To the south is a little
passage 6 feet off the floor.
> w
There is a threatening little dwarf in the room with you!
You are at the east end of a very long hall apparently without side
chambers. To the east a low wide crawl slants up. To the north a
round two foot hole slants down.
> w
There is a threatening little dwarf in the room with you!
You are at the west end of a very long featureless hall. The hall
joins up with a narrow north/south passage.
> s
There is a threatening little dwarf in the room with you!
You are in a maze of twisty little passages, all different.
> sw
There is a threatening little dwarf in the room with you!
You are in a little maze of twisty passages, all different.
> se
There is a threatening little dwarf in the room with you!
You are in a little maze of twisting passages, all different.
> s
There is a threatening little dwarf in the room with you!
Dead end
There is a massive and somewhat battered vending machine here. The
instructions on it read: "Drop coins here to receive fresh batteries."
> kill machine
As you strike the vending machine, it pivots backward along with a
section of wall, revealing a dark passage leading south.
> s
There is a threatening little dwarf in the room with you!
You are in a long, rough-hewn, north/south corridor.
> s
There is a threatening little dwarf in the room with you!
You are in a large chamber with passages to the west and north.
A formidable ogre bars the northern exit.
> kill ogre
The ogre, who despite his bulk is quite agile, easily dodges your
attack. He seems almost amused by your puny effort.
One sharp nasty knife is thrown at you!
The ogre, distracted by your rush, is struck by the knife. With a
blood-curdling yell he turns and bounds after the dwarf, who flees
in panic. You are left alone in the room.
> n
You are in the ogre's storeroom. The only exit is to the south.
There is an enormous ruby here!
> take ruby
OK
> s
You are in a large chamber with passages to the west and north.
> w
You are in a long, rough-hewn, north/south corridor.
> n
Dead end
There is a massive vending machine here, swung back to reveal a
southward passage.
> n
You are in a little maze of twisting passages, all different.
> n
You are in a little maze of twisty passages, all different.
> nw
You are in a maze of twisty little passages, all different.
> d
You're at west end of long hall.
> e
You're at east end of long hall.
> e
You're at west end of Hall of Mists.
> e
You're on west bank of fissure.
A crystal bridge spans the fissure.
> e
You're on east bank of fissure.
A three foot black rod with a rusty star on an end lies nearby.
A crystal bridge spans the fissure.
> e
There is a threatening little dwarf in the room with you!
One sharp nasty knife is thrown at you!
It misses!
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
staircase leads downward. The hall is filled with wisps of white mist
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
Rough stone steps lead up the dome.
> throw axe
You killed a little dwarf. The body vanishes in a cloud of greasy
black smoke.
You're in Hall of Mists.
There is a little axe here.
Rough stone steps lead up the dome.
> take axe
OK
> n
You're in Hall of Mt King.
> n
You're in n/s passage above e/w passage.
> n
You are in a large room, with a passage to the south, a passage to the
west, and a wall of broken rock to the east. There is a large "Y2" on
a rock in the room's center.
A hollow voice says "PLUGH".
> off
Your lamp is now off.
It is now pitch dark. If you proceed you will likely fall into a pit.
> plugh
>>Foof!<<
You're inside building.
There are bars of silver here!
There is a Persian rug spread out on the floor!
There is a large sparkling nugget of gold here!
A precious jade necklace has been dropped here!
There is precious jewelry here!
There are many coins here!
There are some keys on the ground here.
There is food here.
> drop ruby
OK
> drop diamonds
OK
> drop pyramid
OK
> plugh
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You're at "Y2".
A hollow voice says "PLUGH".
> s
You are in a low n/s passage at a hole in the floor. The hole goes
down to an e/w passage.
> s
You're in Hall of Mt King.
> n
You're in n/s passage above e/w passage.
> d
You are in a dirty broken passage. To the east is a crawl. To the
west is a large passage. Above you is a hole to another passage.
> bedquilt
You are in Bedquilt, a long east/west passage with holes everywhere.
To explore at random select north, south, up, or down.
> slab
You are in a large low circular chamber whose floor is an immense slab
fallen from the ceiling (Slab Room). East and west there once were
large passages, but they are now filled with boulders. Low small
passages go north and south, and the south one quickly bends west
around the boulders.
> s
You are at the west end of the Twopit Room. There is a large hole in
the wall above the pit at this end of the room.
> d
You are at the bottom of the western pit in the Twopit Room. There is
a large hole in the wall about 25 feet above you.
There is a tiny little plant in the pit, murmuring "water, water, ..."
> water plant
The plant spurts into furious growth for a few seconds.
You're in west pit.
There is a 12-foot-tall beanstalk stretching up out of the pit,
bellowing "WATER!! WATER!!"
> H'CFL
Nothing happens.
> u
You're at west end of Twopit Room.
The top of a 12-foot-tall beanstalk is poking out of the west pit.
> w
You're in Slab Room.
> u
You are in a secret n/s canyon above a large room.
> reservoir
You are at the edge of a large underground reservoir. An opaque cloud
of white mist fills the room and rises rapidly upward. The lake is
fed by a stream, which tumbles out of a hole in the wall about 10 feet
overhead and splashes noisily into the water somewhere within the
mist. There is a passage going back toward the south.
> drink
You have taken a drink from the stream. The water tastes strongly of
minerals, but is not unpleasant. It is extremely cold.
> H'CFL
The waters have parted to form a narrow path across the reservoir.
> n
You are walking across the bottom of the reservoir. Walls of water
rear up on either side. The roar of the water cascading past is
nearly deafening, and the mist is so thick you can barely see.
> H'CFL
The waters crash together again.
(Uh, y'know, that wasn't very bright.)
Oh dear, you seem to have gotten yourself killed. I might be able to
help you out, but I've never really done this before. Do you want me
to try to reincarnate you?
> n
OK
You scored 177 out of a possible 430, using 153 turns.
You may now consider yourself a "Seasoned Adventurer".
To achieve the next higher rating, you need 74 more points.

View file

@ -1,161 +0,0 @@
## Speak a magic word at an inopportune time and drown.
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
# Based on walkthrough at http://www.ecsoftwareconsulting.com/node/56
n
seed 1838473132
in
take lamp
xyzzy
on
take rod
e
take cage
w
w
w
drop rod
take bird
take rod
w
free bird
wave rod
take necklace
drop rod
take bird
take rod
d
d
free bird
drop rod
drop cage
take cage
take bird
w
take coins
e
s
take jewelry
n
up
s
take gold
n
d
n
n
plugh
extinguish lamp
drop coins
drop jewelry
drop necklace
drop gold
plugh
on
s
take silver
s
sw
take axe
w
kill dragon
yes
feed dragon
drink blood
take rug
e
e
up
d
n
n
off
plugh
inven
drop rug
drop silver
out
s
w
n
take appendage
free bird
drop cage
listen
s
s
n
in
take water
plugh
on
plover
ne
take pyramid
s
plover
s
s
take rod
up
w
wave rod
drop rod
west
take diamonds
w
w
w
s
sw
se
s
kill machine
s
s
kill ogre
n
take ruby
s
w
n
n
n
nw
d
e
e
e
e
e
throw axe
take axe
n
n
n
off
plugh
drop ruby
drop diamonds
drop pyramid
plugh
on
s
s
n
d
bedquilt
slab
s
d
water plant
H'CFL
u
w
u
reservoir
drink
H'CFL
n
H'CFL
n

View file

@ -1,81 +1,90 @@
Welcome to Adventure!! Would you like instructions?
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
<<<<<<< HEAD
> seed 1495763690
Seed set to 1495763690
You're in front of building.
> seed 1495752222
Seed set to 1495752222
=======
> seed 1494912171
Seed set to 1494912171
>>>>>>> f9eca41 (Ensure the ZZZZ magic word is reproducible.)
You're in front of building.
You're in front of building.
> in
You are inside a building, a well house for a large spring.
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is food here.
There is a bottle of water here.
There is a bottle of water here.
> take keys
OK
OK
> take lamp
OK
OK
> out
You're in front of building.
You're in front of building.
> down
You are in a valley in the forest beside a stream tumbling along a
You are in a valley in the forest beside a stream tumbling along a
rocky bed.
> s
At your feet all the water of the stream splashes into a 2-inch slit
in the rock. Downstream the streambed is bare rock.
At your feet all the water of the stream splashes into a 2-inch slit
in the rock. Downstream the streambed is bare rock.
> s
You are in a 20-foot depression floored with bare dirt. Set into the
dirt is a strong steel grate mounted in concrete. A dry streambed
leads into the depression.
You are in a 20-foot depression floored with bare dirt. Set into the
dirt is a strong steel grate mounted in concrete. A dry streambed
leads into the depression.
The grate is locked.
> open grate
The grate is now unlocked.
The grate is now unlocked.
> down
You are in a small chamber beneath a 3x3 steel grate to the surface.
A low crawl over cobbles leads inward to the west.
The grate is open.
The grate is open.
> west
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
There is a small wicker cage discarded nearby.
There is a small wicker cage discarded nearby.
> take cage
OK
OK
> west
@ -86,302 +95,322 @@ It is now pitch dark. If you proceed you will likely fall into a pit.
Your lamp is now on.
You are in a debris room filled with stuff washed in from the surface.
A low wide passage with cobbles becomes plugged with mud and debris
A low wide passage with cobbles becomes plugged with mud and debris
here, but an awkward canyon leads upward and west. In the mud someone
has scrawled, "MAGIC WORD XYZZY".
has scrawled, "MAGIC WORD XYZZY".
A three foot black rod with a rusty star on an end lies nearby.
A three foot black rod with a rusty star on an end lies nearby.
> take rod
OK
OK
> xyzzy
>>Foof!<<
>>Foof!<<
You're inside building.
You're inside building.
There is food here.
There is food here.
There is a bottle of water here.
There is a bottle of water here.
> xyzzy
>>Foof!<<
>>Foof!<<
You're in debris room.
You're in debris room.
> west
You are in an awkward sloping east/west canyon.
You are in an awkward sloping east/west canyon.
> drop rod
OK
OK
> west
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
from east and west sides of the chamber.
A cheerful little bird is sitting here singing.
A cheerful little bird is sitting here singing.
> take bird
OK
OK
> east
You are in an awkward sloping east/west canyon.
You are in an awkward sloping east/west canyon.
A three foot black rod with a rusty star on an end lies nearby.
A three foot black rod with a rusty star on an end lies nearby.
> take rod
OK
OK
> west
You're in bird chamber.
You're in bird chamber.
> west
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
Rough stone steps lead down the pit.
Rough stone steps lead down the pit.
> down
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
staircase leads downward. The hall is filled with wisps of white mist
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
Rough stone steps lead up the dome.
> south
This is a low room with a crude note on the wall. The note says,
"You won't get it up the steps".
"You won't get it up the steps".
There is a large sparkling nugget of gold here!
There is a large sparkling nugget of gold here!
> take gold
OK
OK
> n
You're in Hall of Mists.
You're in Hall of Mists.
> n
You are in the Hall of the Mountain King, with passages off in all
directions.
You are in the Hall of the Mountain King, with passages off in all
directions.
A huge green fierce snake bars the way!
A huge green fierce snake bars the way!
> drop bird
The little bird attacks the green snake, and in an astounding flurry
drives the snake away.
The little bird attacks the green snake, and in an astounding flurry
drives the snake away.
> west
You are in the west side chamber of the Hall of the Mountain King.
A passage continues west and up here.
You are in the west side chamber of the Hall of the Mountain King.
A passage continues west and up here.
There are many coins here!
There are many coins here!
> take coins
OK
OK
> e
You're in Hall of Mt King.
You're in Hall of Mt King.
A cheerful little bird is sitting here singing.
A cheerful little bird is sitting here singing.
> s
A little dwarf just walked around a corner, saw you, threw a little
axe at you which missed, cursed, and ran away.
A little dwarf just walked around a corner, saw you, threw a little
axe at you which missed, cursed, and ran away.
You are in the south side chamber.
You are in the south side chamber.
There is a little axe here.
There is a little axe here.
There is precious jewelry here!
> drop cage
OK
There is precious jewelry here!
> take jewelry
OK
> take axe
OK
OK
> n
There is a threatening little dwarf in the room with you!
There is a threatening little dwarf in the room with you!
One sharp nasty knife is thrown at you!
One sharp nasty knife is thrown at you!
It misses!
You're in Hall of Mt King.
You're in Hall of Mt King.
A cheerful little bird is sitting here singing.
A cheerful little bird is sitting here singing.
> n
There is a threatening little dwarf in the room with you!
There is a threatening little dwarf in the room with you!
You are in a low n/s passage at a hole in the floor. The hole goes
down to an e/w passage.
You are in a low n/s passage at a hole in the floor. The hole goes
down to an e/w passage.
There are bars of silver here!
> take silver
You can't carry anything more. You'll have to drop something first.
> drop cage
OK
> take silver
OK
> n
There is a threatening little dwarf in the room with you!
There is a threatening little dwarf in the room with you!
You are in a large room, with a passage to the south, a passage to the
west, and a wall of broken rock to the east. There is a large "Y2" on
a rock in the room's center.
west, and a wall of broken rock to the east. There is a large "Y2" on
a rock in the room's center.
> plugh
>>Foof!<<
>>Foof!<<
You're inside building.
You're inside building.
There is food here.
There is food here.
There is a bottle of water here.
There is a bottle of water here.
> inven
You are currently holding the following:
Set of keys
Brass lantern
Black rod
Dwarf's axe
Large gold nugget
Precious jewelry
You are currently holding the following:
Set of keys
Brass lantern
Black rod
Large gold nugget
Bars of silver
Precious jewelry
Rare coins
> drop jewelry
OK
OK
> drop gold
OK
OK
> drop silver
OK
> inven
You are currently holding the following:
Set of keys
Brass lantern
Black rod
Dwarf's axe
You are currently holding the following:
Set of keys
Brass lantern
Black rod
Rare coins
> drop keys
OK
OK
> plugh
>>Foof!<<
>>Foof!<<
There are 2 threatening little dwarves in the room with you.
There are 2 threatening little dwarves in the room with you.
One sharp nasty knife is thrown at you!
One sharp nasty knife is thrown at you!
It misses!
You're at "Y2".
You're at "Y2".
> take knife
The dwarves' knives vanish as they strike the walls of the cave.
> throw axe
I see no axe here.
> s
There are 2 threatening little dwarves in the room with you.
There are 2 threatening little dwarves in the room with you.
You're in n/s passage above e/w passage.
You're in n/s passage above e/w passage.
There are bars of silver here!
There is a small wicker cage discarded nearby.
> s
There are 2 threatening little dwarves in the room with you.
There are 2 threatening little dwarves in the room with you.
You're in Hall of Mt King.
You're in Hall of Mt King.
A cheerful little bird is sitting here singing.
A cheerful little bird is sitting here singing.
> up
There are 2 threatening little dwarves in the room with you.
There are 2 threatening little dwarves in the room with you.
You're in Hall of Mists.
You're in Hall of Mists.
Rough stone steps lead up the dome.
> w
There are 2 threatening little dwarves in the room with you.
There are 2 threatening little dwarves in the room with you.
You are on the east bank of a fissure slicing clear across the hall.
The mist is quite thick here, and the fissure is too wide to jump.
You are on the east bank of a fissure slicing clear across the hall.
The mist is quite thick here, and the fissure is too wide to jump.
> wave rod
A crystal bridge now spans the fissure.
A crystal bridge now spans the fissure.
> w
There are 2 threatening little dwarves in the room with you.
There are 2 threatening little dwarves in the room with you.
You are on the west side of the fissure in the Hall of Mists.
You are on the west side of the fissure in the Hall of Mists.
There are diamonds here!
There are diamonds here!
A crystal bridge spans the fissure.
A crystal bridge now spans the fissure.
> take diamonds
OK
OK
<<<<<<< HEAD
>
You scored 97 out of a possible 430, using 60 turns.
=======
> e
A little dwarf with a big knife blocks your way.
A little dwarf with a big knife blocks your way.
There are 2 threatening little dwarves in the room with you.
There are 2 threatening little dwarves in the room with you.
2 of them throw knives at you!
2 of them throw knives at you!
One of them gets you!
One of them gets you!
Oh dear, you seem to have gotten yourself killed. I might be able to
help you out, but I've never really done this before. Do you want me
to try to reincarnate you?
Oh dear, you seem to have gotten yourself killed. I might be able to
help you out, but I've never really done this before. Do you want me
to try to reincarnate you?
> n
OK
OK
You scored 81 out of a possible 430, using 55 turns.
You scored 81 out of a possible 430, using 55 turns.
>>>>>>> 6a6670e (Fix things so seed doesn't cost clock time.)
Your score qualifies you as a novice class adventurer.
Your score qualifies you as a novice class adventurer.
To achieve the next higher rating, you need 40 more points.
To achieve the next higher rating, you need 24 more points.

View file

@ -1,6 +1,4 @@
## In which the dwarf kills you
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
## Death by dwarf.
n
seed 1494912171
in

View file

@ -1,69 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> seed 383847
Seed set to 383847
You're in front of building.
> in
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is a bottle of water here.
> xyzzy
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> w
It is now pitch dark. If you proceed you will likely fall into a pit.
> w
It is now pitch dark. If you proceed you will likely fall into a pit.
> w
It is now pitch dark. If you proceed you will likely fall into a pit.
> d
It is now pitch dark. If you proceed you will likely fall into a pit.
> d
A little dwarf just walked around a corner, saw you, threw a little
axe at you which missed, cursed, and ran away.
You fell into a pit and broke every bone in your body!
Oh dear, you seem to have gotten yourself killed. I might be able to
help you out, but I've never really done this before. Do you want me
to try to reincarnate you?
> n
OK
You scored 51 out of a possible 430, using 7 turns.
Your score qualifies you as a novice class adventurer.
To achieve the next higher rating, you need 70 more points.

View file

@ -1,13 +0,0 @@
## Check that dwarf spawns in alternative location (fuzzed)
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 383847
in
xyzzy
w
w
w
d
d
n

File diff suppressed because it is too large Load diff

View file

@ -1,196 +0,0 @@
## Be done with Giant Room and eggs (fuzzed)
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 1838473132
in
take lamp
xyzzy
on
take rod
e
take cage
w
w
w
drop rod
take bird
take rod
w
d
d
free bird
w
take coins
e
s
take n
u
s
n
d
n
n
plugh
extin
plugh
on
s
s
sw
take
w
kill drago
y
e
e
u
d
n
n
off
plugh
out
s
w
n
s
s
n
in
take water
plugh
on
plove
s
plove
s
s
u
w
wave rod
west
w
w
w
s
s
e
s
kill machi
s
s
n
s
w
n
n
n
nw
d
e
e
e
e
e
n
n
n
off
plugh
plugh
on
s
s
u
n
n
d
bedqu
throw axe
slab
s
d
water plant
u
w
u
reser
H'CFL
n
n
w
u
u
u
u
w
d
d
d
d
d
take water
s
s
s
s
d
s
d
water plant
u
e
d
get oil
u
w
d
climb
w
n
oil door
d
n
w
d
se
n
w
nw
s
e
se
e
w
ne
e
n
e
u
n
s
d
w
d
n
d
d
u
u
s
w
w
w
w
d
climb
w
take egg
n
fee
fie
foe
foo
look
inven

View file

@ -1,443 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> seed 1838473132
Seed set to 1838473132
You're in front of building.
> in
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is a bottle of water here.
> take lamp
OK
> xyzzy
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You are in a debris room filled with stuff washed in from the surface.
A low wide passage with cobbles becomes plugged with mud and debris
here, but an awkward canyon leads upward and west. In the mud someone
has scrawled, "MAGIC WORD XYZZY".
A three foot black rod with a rusty star on an end lies nearby.
> e
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
There is a small wicker cage discarded nearby.
> take cage
OK
> w
You're in debris room.
A three foot black rod with a rusty star on an end lies nearby.
> w
You are in an awkward sloping east/west canyon.
> w
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
from east and west sides of the chamber.
A cheerful little bird is sitting here singing.
> take
OK
> w
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
Rough stone steps lead down the pit.
> d
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
staircase leads downward. The hall is filled with wisps of white mist
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
Rough stone steps lead up the dome.
> d
You are in the Hall of the Mountain King, with passages off in all
directions.
A huge green fierce snake bars the way!
> free bird
The little bird attacks the green snake, and in an astounding flurry
drives the snake away.
> w
You are in the west side chamber of the Hall of the Mountain King.
A passage continues west and up here.
There are many coins here!
> e
You're in Hall of Mt King.
A cheerful little bird is sitting here singing.
> s
You are in the south side chamber.
There is precious jewelry here!
> n
You're in Hall of Mt King.
A cheerful little bird is sitting here singing.
> u
You're in Hall of Mists.
Rough stone steps lead up the dome.
> s
This is a low room with a crude note on the wall. The note says,
"You won't get it up the steps".
There is a large sparkling nugget of gold here!
> n
You're in Hall of Mists.
Rough stone steps lead up the dome.
> d
You're in Hall of Mt King.
A cheerful little bird is sitting here singing.
> n
You are in a low n/s passage at a hole in the floor. The hole goes
down to an e/w passage.
There are bars of silver here!
> n
You are in a large room, with a passage to the south, a passage to the
west, and a wall of broken rock to the east. There is a large "Y2" on
a rock in the room's center.
A hollow voice says "PLUGH".
> plugh
>>Foof!<<
You're inside building.
There are some keys on the ground here.
There is food here.
There is a bottle of water here.
> extin
Your lamp is now off.
> plugh
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You're at "Y2".
> plugh
>>Foof!<<
You're inside building.
There are some keys on the ground here.
There is food here.
There is a bottle of water here.
> take water
OK
> plugh
>>Foof!<<
You're at "Y2".
> plugh
>>Foof!<<
You're inside building.
There are some keys on the ground here.
There is food here.
> plugh
>>Foof!<<
You're at "Y2".
> s
You're in n/s passage above e/w passage.
There are bars of silver here!
> d
You are in a dirty broken passage. To the east is a crawl. To the
west is a large passage. Above you is a hole to another passage.
> bedqu
You are in Bedquilt, a long east/west passage with holes everywhere.
To explore at random select north, south, up, or down.
> slab
You are in a large low circular chamber whose floor is an immense slab
fallen from the ceiling (Slab Room). East and west there once were
large passages, but they are now filled with boulders. Low small
passages go north and south, and the south one quickly bends west
around the boulders.
> s
You are at the west end of the Twopit Room. There is a large hole in
the wall above the pit at this end of the room.
> d
You are at the bottom of the western pit in the Twopit Room. There is
a large hole in the wall about 25 feet above you.
There is a tiny little plant in the pit, murmuring "water, water, ..."
> water plant
The plant spurts into furious growth for a few seconds.
You're in west pit.
There is a 12-foot-tall beanstalk stretching up out of the pit,
bellowing "WATER!! WATER!!"
> u
You're at west end of Twopit Room.
The top of a 12-foot-tall beanstalk is poking out of the west pit.
> w
You're in Slab Room.
> u
You are in a secret n/s canyon above a large room.
> reser
You are at the edge of a large underground reservoir. An opaque cloud
of white mist fills the room and rises rapidly upward. The lake is
fed by a stream, which tumbles out of a hole in the wall about 10 feet
overhead and splashes noisily into the water somewhere within the
mist. There is a passage going back toward the south.
> H'CFL
The waters have parted to form a narrow path across the reservoir.
> n
You are walking across the bottom of the reservoir. Walls of water
rear up on either side. The roar of the water cascading past is
nearly deafening, and the mist is so thick you can barely see.
> n
You are at the northern edge of the reservoir. A northwest passage
leads sharply up from here.
The waters have parted to form a narrow path across the reservoir.
> take water
Your bottle is now full of water.
> s
You're at bottom of reservoir.
> s
You're at reservoir.
The waters have parted to form a narrow path across the reservoir.
> s
You are in a north/south canyon about 25 feet across. The floor is
covered by white mist seeping in from the north. The walls extend
upward for well over 100 feet. Suspended from some unseen point far
above you, an enormous two-sided mirror is hanging parallel to and
midway between the canyon walls. (The mirror is obviously provided
for the use of the dwarves who, as you know, are extremely vain.) A
small window can be seen in either wall, some fifty feet up.
> s
You are in a secret n/s canyon above a large room.
> d
You're in Slab Room.
> s
You're at west end of Twopit Room.
The top of a 12-foot-tall beanstalk is poking out of the west pit.
> d
A little dwarf just walked around a corner, saw you, threw a little
axe at you which missed, cursed, and ran away.
You're in west pit.
There is a little axe here.
There is a 12-foot-tall beanstalk stretching up out of the pit,
bellowing "WATER!! WATER!!"
> water plant
The plant grows explosively, almost filling the bottom of the pit.
You're in west pit.
There is a little axe here.
There is a gigantic beanstalk stretching all the way up to the hole.
> climb
You clamber up the plant and scurry through the hole at the top.
You are in a long, narrow corridor stretching out of sight to the
west. At the eastern end is a hole through which you can see a
profusion of leaves.
> w
You are in the Giant Room. The ceiling here is too high up for your
lamp to show it. Cavernous passages lead east, north, and south. On
the west wall is scrawled the inscription, "FEE FIE FOE FOO" [sic].
There is a large nest here, full of golden eggs!
> take
OK
> n
You are at one end of an immense north/south passage.
The way north is barred by a massive, rusty, iron door.
> fee
OK
> fie
OK
> foe
OK
> foo
The nest of golden eggs has vanished!
> s
You're in Giant Room.
There is a large nest here, full of golden eggs!
> e
The passage here is blocked by a recent cave-in.
>
You scored 67 out of a possible 430, using 66 turns.
Your score qualifies you as a novice class adventurer.
To achieve the next higher rating, you need 54 more points.

View file

@ -1,72 +0,0 @@
## Vanishing eggs in Giant Room (fuzzed)
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 1838473132
in
take lamp
xyzzy
on
e
take cage
w
w
w
take
w
d
d
free bird
w
e
s
n
u
s
n
d
n
n
plugh
extin
plugh
on
plugh
take water
plugh
plugh
plugh
s
d
bedqu
slab
s
d
water plant
u
w
u
reser
H'CFL
n
n
take water
s
s
s
s
d
s
d
water plant
climb
w
take
n
fee
fie
foe
foo
# go south, east to arrive at LOC_CAVEIN for coverage
s
e

File diff suppressed because it is too large Load diff

View file

@ -1,475 +0,0 @@
## 428-point walkthrough
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
# Based on walkthrough at http://www.ecsoftwareconsulting.com/node/56
n
seed 1838473132
in
take lamp
xyzzy
on
take rod
e
take cage
w
w
w
drop rod
take bird
take rod
w
free bird
wave rod
take necklace
drop rod
take bird
take rod
d
d
free bird
drop rod
drop cage
take cage
take bird
w
take coins
e
s
take jewelry
n
up
s
take gold
n
d
n
n
plugh
extinguish lamp
drop coins
drop jewelry
drop necklace
drop gold
plugh
on
s
take silver
s
sw
take axe
w
kill dragon
yes
drink blood
take rug
e
e
up
d
n
n
off
plugh
inven
drop rug
drop silver
out
s
w
n
take appendage
free bird
drop cage
listen
s
s
n
in
take water
plugh
on
plover
ne
take pyramid
s
plover
s
s
take rod
up
w
wave rod
drop rod
west
take diamonds
w
w
w
s
sw
se
s
kill machine
s
s
kill ogre
n
take ruby
s
w
n
n
n
nw
d
e
e
e
e
e
throw axe
take axe
n
n
n
off
plugh
drop ruby
drop diamonds
drop pyramid
plugh
on
s
s
u
n
n
d
bedquilt
throw axe
take axe
slab
s
d
water plant
u
w
u
reservoir
H'CFL
n
n
nw
u
u
u
u
ne
take ebony
sw
d
d
d
d
d
take water
s
s
s
s
d
s
d
water plant
u
drop appendage
e
d
get oil
u
w
d
climb
w
n
oil door
drop bottle
n
take trident
w
d
se
n
w
drop trident
drop ebony
drop axe
drop lantern
e
take emerald
w
take lamp
take axe
take ebony
take trident
nw
s
take vase
se
throw axe
take axe
e
take pillow
w
drop axe
ne
e
n
open clam
s
u
e
u
n
off
plugh
drop pillow
drop vase
drop trident
drop emerald
drop ebony
take keys
take food
plugh
on
s
d
w
d
n
d
d
take pearl
u
u
s
w
w
w
w
d
climb
w
get eggs
n
take bottle
n
w
d
sw
u
toss eggs
ne
ne
barren
in
feed bear
unlock chain
take chain
take bear
fork
ne
e
take spices
drop keys
fork
w
w
sw
free bear
inven
sw
sw
d
se
se
w
d
get oil
up
e
take axe
w
w
d
climb
w
fee
fie
foe
foo
take eggs
s
d
u
w
u
s
e
e
n
n
off
plugh
drop eggs
drop pearl
drop spices
drop chain
take rug
take ruby
take emerald
out
w
n
n
n
inven
fill urn
light urn
rub urn
take amber
drop rug
drop emerald
fly rug
take sapphire
fly rug
take emerald
drop ruby
take rug
drop bottle
take ruby
e
s
e
e
in
drop ruby
drop sapphire
drop amber
drop rug
look
plugh
on
s
s
u
w
w
w
s
e
s
throw axe
take axe
s
s
n
e
e
nw
take emerald
take chest
se
n
d
e
e
off
xyzzy
drop emerald
drop chest
plugh
on
s
d
w
d
e
take magazine
e
drop magazine
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
u
u
e
u
n
plover
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
e
sw
take rod
ne
drop rod
sw
blast

File diff suppressed because it is too large Load diff

View file

@ -1,430 +0,0 @@
### Check that water is unavailable in endgame
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
# Addresses GitLab issue #55: in endgame, some object starting states are incorrect
#NOCOMPARE Bird was not weightless in cage in advent430, this test depends on that.
no
seed 11247848
no
seed 1516020414
e
plugh
plove
get emerald
w
drop emerald
e
ne
get pyramid
s
plove
plugh
drop pyramid
get lamp
xyzzy
on
get rod
e
get cage
pit
d
w
wave rod
w
get diamonds
e
e
u
drop rod
e
get bird
w
free bird
get rod
wave rod
get necklace
drop rod
get bird
d
s
get gold
n
d
free bird
get bird
s
get jewelry
n
sw
w
kill dragon
yes
drink blood
get rug
e
e
n
n
plugh
drop necklace
drop gold
drop jewelry
drop diamonds
w
s
w
n
get appendage
free bird
drop cage
listen
s
s
n
e
plugh
s
s
sw
w
n
reserv
U'SIM
n
n
u
u
u
u
u
ne
get statuette
sw
d
d
d
d
d
s
s
s
s
s
get axe
e
e
e
w
w
w
w
s
sw
se
s
hit machine
s
s
hit ogre
s
n
get ruby
s
w
n
n
d
d
d
e
e
e
e
e
d
throw axe
get axe
n
get silver
n
plugh
drop silver
drop ebony
drop appendage
get water
plugh
throw axe
get axe
s
d
bedquilt
w
w
w
d
pour water
u
e
d
get oil
u
e
e
get pillow
w
orien
get vase
n
w
get emerald
nw
s
se
ne
slab
u
s
e
e
n
n
plugh
drop pillow
drop vase
drop emerald
xyzzy
pit
d
w
w
w
s
e
s
s
s
n
throw axe
get axe
e
e
nw
get chest
get ruby
get rug
se
se
w
throw axe
s
d
debris
xyzzy
drop chest
get emerald
w
w
n
n
n
fill urn
light urn
rub urn
get amber
drop rug
drop emerald
fly rug
get sapphire
fly rug
get emerald
drop ruby
get rug
get ruby
e
s
e
e
e
drop ruby
drop sapphire
drop amber
drop emerald
drop rug
get water
get keys
get food
plugh
s
s
sw
w
n
d
s
d
pour water
u
e
d
get oil
u
w
d
climb
w
get eggs
n
oil door
n
get trident
w
d
sw
u
toss eggs
cross
barren
e
feed bear
unlock chain
get chain
get bear
fork
ne
e
drop keys
get spices
fork
w
w
cross
free bear
cross
sw
d
bedquilt
w
w
w
d
climb
w
fee
fie
foe
foo
get eggs
s
d
u
e
e
ne
e
n
open clam
d
d
get pearl
shell
s
u
e
u
s
w
drop bottle
get coins
e
n
n
plugh
drop chain
drop spices
drop trident
drop pearl
drop eggs
drop coins
plugh
s
d
w
d
e
get magazine
e
drop magazine
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
no
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
no
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
look
no
look
look
get water
get bottle
inven
sw
get cage
# In the original game, the bird is in the cage at this point
inven
get bird
inven
quit
yes

View file

@ -1,444 +0,0 @@
Welcome to Adventure!! Would you like instructions?
> n
You are standing at the end of a road before a small brick building.
Around you is a forest. A small stream flows out of the building and
down a gully.
> seed 25508795
Seed set to 25508795
You're in front of building.
> in
You are inside a building, a well house for a large spring.
There are some keys on the ground here.
There is a shiny brass lamp nearby.
There is food here.
There is a bottle of water here.
> take lamp
OK
> xyzzy
>>Foof!<<
It is now pitch dark. If you proceed you will likely fall into a pit.
> on
Your lamp is now on.
You are in a debris room filled with stuff washed in from the surface.
A low wide passage with cobbles becomes plugged with mud and debris
here, but an awkward canyon leads upward and west. In the mud someone
has scrawled, "MAGIC WORD XYZZY".
A three foot black rod with a rusty star on an end lies nearby.
> e
You are crawling over cobbles in a low passage. There is a dim light
at the east end of the passage.
There is a small wicker cage discarded nearby.
> take cage
OK
> w
You're in debris room.
A three foot black rod with a rusty star on an end lies nearby.
> w
You are in an awkward sloping east/west canyon.
> w
You are in a splendid chamber thirty feet high. The walls are frozen
rivers of orange stone. An awkward canyon and a good passage exit
from east and west sides of the chamber.
A cheerful little bird is sitting here singing.
> take
OK
> w
At your feet is a small pit breathing traces of white mist. An east
passage ends here except for a small crack leading on.
Rough stone steps lead down the pit.
> d
You are at one end of a vast hall stretching forward out of sight to
the west. There are openings to either side. Nearby, a wide stone
staircase leads downward. The hall is filled with wisps of white mist
swaying to and fro almost as if alive. A cold wind blows up the
staircase. There is a passage at the top of a dome behind you.
Rough stone steps lead up the dome.
> d
You are in the Hall of the Mountain King, with passages off in all
directions.
A huge green fierce snake bars the way!
> free bird
The little bird attacks the green snake, and in an astounding flurry
drives the snake away.
> w
You are in the west side chamber of the Hall of the Mountain King.
A passage continues west and up here.
There are many coins here!
> w
You are at a crossover of a high n/s passage and a low e/w one.
> w
You are at the east end of a very long hall apparently without side
chambers. To the east a low wide crawl slants up. To the north a
round two foot hole slants down.
> e
You are at the west end of the Hall of Mists. A low wide crawl
continues west and another goes north. To the south is a little
passage 6 feet off the floor.
> s
You are in a maze of twisty little passages, all alike.
> s
A little dwarf just walked around a corner, saw you, threw a little
axe at you which missed, cursed, and ran away.
You are in a maze of twisty little passages, all alike.
There is a little axe here.
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
> z
OK
>
You scored 59 out of a possible 430, using 93 turns.
Your score qualifies you as a novice class adventurer.
To achieve the next higher rating, you need 62 more points.

View file

@ -1,98 +0,0 @@
## Fail to get maze hint by being empty-handed (fuzzed)
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
# SPDX-License-Identifier: BSD-2-Clause
n
seed 25508795
in
take lamp
xyzzy
on
e
take cage
w
w
w
take
w
d
d
free bird
w
w
w
e
s
s
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z
z

Some files were not shown because too many files have changed in this diff Show more