Compare commits
376 commits
Author | SHA1 | Date | |
---|---|---|---|
|
7d848c89e1 | ||
|
7bbf994fce | ||
|
3e989aec53 | ||
|
9df69fe034 | ||
|
a2bb39dc7e | ||
|
5c90880f0a | ||
|
92451f1fff | ||
|
96ad6c6245 | ||
|
40742e112b | ||
|
a4fd14caf7 | ||
|
9a6e4406f5 | ||
|
08f0351817 | ||
|
0157e58668 | ||
|
354e56a69b | ||
|
9c3f4b0c90 | ||
|
20fd7c589f | ||
|
8c553af53e | ||
|
f1cb740c41 | ||
|
cf4adf8d02 | ||
|
acdfa96315 | ||
|
3d6c689ffa | ||
|
8dcc6e6641 | ||
|
e17ff128da | ||
|
cb293f4aa4 | ||
|
124e7768b4 | ||
|
63e8579f74 | ||
|
1080b45d39 | ||
|
86fe4bd121 | ||
|
bd499dc532 | ||
|
ae6eced72d | ||
|
7903ac1bb8 | ||
|
b51612131d | ||
|
62cd0c78da | ||
|
bad34acf1e | ||
|
0fafbe379f | ||
|
fcf6935689 | ||
|
b610a62685 | ||
|
6174129116 | ||
|
a2fa136988 | ||
|
43a08621e4 | ||
|
f24fcd2971 | ||
|
580f409ee6 | ||
|
5b917084b0 | ||
|
1ef39055f3 | ||
|
0175344caa | ||
|
be429016af | ||
|
c11938aed5 | ||
|
258b7703f2 | ||
|
83c6a66887 | ||
|
3c09c25cc3 | ||
|
f26514b5dd | ||
|
cf7ea0cd89 | ||
|
2db3bed3f1 | ||
|
a6ec8a9595 | ||
|
75bc031b46 | ||
|
dd65960ec5 | ||
|
90f96a25da | ||
|
c10e9694e3 | ||
|
11d966f349 | ||
|
e1a17fd442 | ||
|
eb63994931 | ||
|
0b82afa5c1 | ||
|
b247359d7f | ||
|
1f9f39d789 | ||
|
2582e240bd | ||
|
9fbd603f8d | ||
|
5016978156 | ||
|
7d4dd78679 | ||
|
ab4653b89c | ||
|
b28eb66868 | ||
|
f0119f8431 | ||
|
5075c63cf4 | ||
|
ebf3e389c0 | ||
|
6cef68cda5 | ||
|
234da6b468 | ||
|
adbb5c1204 | ||
|
869c53d1b1 | ||
|
ef78c36ddb | ||
|
5d3205e1e9 | ||
|
a6b41fdb8f | ||
|
9ff036d789 | ||
|
88feaab0c0 | ||
|
4d4e8dce96 | ||
|
82c3ae5e65 | ||
|
1af01ff91f | ||
|
9e9731d59b | ||
|
191d3cb043 | ||
|
c82d1214fa | ||
|
02987d0330 | ||
|
9cd7c53d78 | ||
|
ab2779cd93 | ||
|
819aed5c4e | ||
|
8d4d64fafb | ||
|
eebc87f889 | ||
|
8fe07c8bf3 | ||
|
ff9c73a37d | ||
|
195e6e149b | ||
|
4369284c75 | ||
|
7e21108e95 | ||
|
829c13d1d5 | ||
|
2f60504e07 | ||
|
5de3b8ff70 | ||
|
520d365f74 | ||
|
4b08b726f9 | ||
|
58cf204eba | ||
|
d16822a583 | ||
|
3640e5cb96 | ||
|
e99cc69de0 | ||
|
e8991f69e9 | ||
|
3e72486724 | ||
|
f5ff25f52a | ||
|
e1a528a4c5 | ||
|
9726d8207c | ||
|
fe378b9e13 | ||
|
4ce4de190e | ||
|
9b53140f1c | ||
|
3c6648882d | ||
|
00bdc2133a | ||
|
20e1b9d930 | ||
|
1ce4fc2ac3 | ||
|
642b7e4890 | ||
|
ec1d99f354 | ||
|
6ebc2bf0e3 | ||
|
25230068fe | ||
|
71abcb4e65 | ||
|
2dd1ccc535 | ||
|
0a1f5dbb43 | ||
|
20cb8b9ffb | ||
|
b86d4afd20 | ||
|
d9ddf4d805 | ||
|
9c6219a27d | ||
|
34516ecf39 | ||
|
7dc3482c5b | ||
|
40a4acb868 | ||
|
54927c33e5 | ||
|
e49fb5f367 | ||
|
59a5afb72e | ||
|
f95442b310 | ||
|
97a69d8cbd | ||
|
0d2332573b | ||
|
7af8492169 | ||
|
3af590e972 | ||
|
2c8aa9668c | ||
|
30a98cc916 | ||
|
872b94f927 | ||
|
74c3158f42 | ||
|
ef180a0731 | ||
|
77ac2f1570 | ||
|
ff46cf7fac | ||
|
c80162b467 | ||
|
65f221e03f | ||
|
cbb5572b21 | ||
|
a5eeb0b2bc | ||
|
4eccfa127c | ||
|
dc8b19bcdc | ||
|
2070db3a2a | ||
|
e3fbac804b | ||
|
5f7ce87040 | ||
|
1e05134b47 | ||
|
1ffb81b70b | ||
|
fefd2a19fb | ||
|
4fa3d4d758 | ||
|
07a0f066ba | ||
|
a006bdd272 | ||
|
327efd3678 | ||
|
b044e9ab42 | ||
|
8fd3eb8b92 | ||
|
9fdbe73315 | ||
|
9758883ea2 | ||
|
f5d15ab1f2 | ||
|
f07b3ba2d4 | ||
|
87855f8124 | ||
|
786832210e | ||
|
9b89dd2829 | ||
|
17840d0e15 | ||
|
5929a68b88 | ||
|
43af075fa9 | ||
|
47c3d14a11 | ||
|
db8ca5eb26 | ||
|
ca5b6975dc | ||
|
282842c4a9 | ||
|
7723f3fc1a | ||
|
0ffb297801 | ||
|
04df0ce64c | ||
|
569a39aa7c | ||
|
1652df4540 | ||
|
ba3248224e | ||
|
b7bf85904d | ||
|
71f05c4567 | ||
|
fe8a82927c | ||
|
b125fe7b2a | ||
|
3971a61ab0 | ||
|
8f527fb433 | ||
|
643eab4e9c | ||
|
f53476f826 | ||
|
83c32598be | ||
|
98b95e92ee | ||
|
8d409c6b3b | ||
|
e1ce7d6b6a | ||
|
f911e42453 | ||
|
12d39ef72b | ||
|
1efd1027f7 | ||
|
1121bb8aa5 | ||
|
a01c08385c | ||
|
643656fcc3 | ||
|
ac0c5fc024 | ||
|
dfff80faa8 | ||
|
426684fec2 | ||
|
162c5abc8a | ||
|
1f644a1d7d | ||
|
17782cab67 | ||
|
94e7cc6505 | ||
|
3f34adad3b | ||
|
17c74326c1 | ||
|
b8c7a6d5ea | ||
|
e5e6dbd741 | ||
|
89266b7c1a | ||
|
9a1b4d021e | ||
|
ff2dd31209 | ||
|
66b8192ae8 | ||
|
23e9931645 | ||
|
20859304c0 | ||
|
aa32e8f4d6 | ||
|
60d7070506 | ||
|
a44ec19753 | ||
|
9812b7a357 | ||
|
d9111efc68 | ||
|
5e2614678b | ||
|
0aead5634e | ||
|
7810888164 | ||
|
aaaf0ac7d2 | ||
|
750cfe36d8 | ||
|
b6c0f5bff0 | ||
|
e5d01c83f0 | ||
|
3dcf8449e5 | ||
|
3f3e114536 | ||
|
baab09e3ab | ||
|
81c7bb6d5b | ||
|
c547f4498b | ||
|
74b1589b57 | ||
|
67a887f432 | ||
|
00c2182d9b | ||
|
9af3ab4ecd | ||
|
017162da6e | ||
|
648deb4770 | ||
|
156b39c34a | ||
|
c71a4dc441 | ||
|
732b581031 | ||
|
86e2e21ef8 | ||
|
3afaabead3 | ||
|
d320212622 | ||
|
f7d6884ded | ||
|
d9d58ea168 | ||
|
846f293e06 | ||
|
70a9edd497 | ||
|
dee8809e30 | ||
|
44017d64bb | ||
|
dd7b664e32 | ||
|
1c2346392e | ||
|
f6fc7f244d | ||
|
18566a349a | ||
|
4069bf210b | ||
|
ceba6482a1 | ||
|
9e6095afa0 | ||
|
ad75cc1eb7 | ||
|
0f5fd82b77 | ||
|
834f6e753c | ||
|
b30059bb72 | ||
|
af7ce31dd9 | ||
|
337377ab57 | ||
|
d235313e97 | ||
|
129136b51e | ||
|
7b3b5d32c0 | ||
|
c78845e05a | ||
|
74dc0d168a | ||
|
829e55f99d | ||
|
10b888f449 | ||
|
f9237d6970 | ||
|
8c80aa183b | ||
|
8b8a3a73c4 | ||
|
865e10e6d0 | ||
|
c5250b5f3f | ||
|
49e2479efa | ||
|
6f7c5743c6 | ||
|
00cbf464b5 | ||
|
2df951ba60 | ||
|
6dd37a6ec3 | ||
|
07f77a8ffd | ||
|
7d2cfa5166 | ||
|
beae508e1d | ||
|
dd5ca23302 | ||
|
db384731a7 | ||
|
a2116b3d79 | ||
|
46e1595cb0 | ||
|
e0b9aeda6e | ||
|
73b49d27f4 | ||
|
bb2b8e0fca | ||
|
8378063198 | ||
|
0799bc2f79 | ||
|
5ab94ce8de | ||
|
5aaa22860a | ||
|
f2f238e9e4 | ||
|
a251e18682 | ||
|
be3457abeb | ||
|
12443b0159 | ||
|
eb27776c99 | ||
|
ba11a8df2e | ||
|
b93d2d396f | ||
|
bfbea454c7 | ||
|
747c42029d | ||
|
8984e48e78 | ||
|
fe1b02f4c0 | ||
|
e879e35a02 | ||
|
90d9ffd85d | ||
|
d9e33a8478 | ||
|
039c06882e | ||
|
baa7800a3f | ||
|
7d0b15ef89 | ||
|
3b714272fb | ||
|
41c0e77684 | ||
|
569e7c5051 | ||
|
b909cc695f | ||
|
1e6b58420e | ||
|
989bdad3ee | ||
|
2ad0fc148b | ||
|
1d54ebb6bd | ||
|
ae02eac051 | ||
|
cf64568f83 | ||
|
9cbea5a5db | ||
|
b817c54245 | ||
|
2ddd091893 | ||
|
b2b4377f71 | ||
|
81af59974b | ||
|
b8c9cf90d8 | ||
|
7de00b0741 | ||
|
58a2de6d75 | ||
|
5c260e3aec | ||
|
a727aebdfa | ||
|
83f432780a | ||
|
0d27a5e03d | ||
|
cd36e91381 | ||
|
894ac28186 | ||
|
64b120c03b | ||
|
8c6593ad0c | ||
|
e7dc3eab5d | ||
|
2a5dac3d8c | ||
|
e3b508536d | ||
|
5f4df123b4 | ||
|
9475552be4 | ||
|
b84a2392a1 | ||
|
673da862b5 | ||
|
ea3b456715 | ||
|
dd1d69ad82 | ||
|
6667ffd1f1 | ||
|
fcf99d56d8 | ||
|
e65f31cac2 | ||
|
524f035e76 | ||
|
f1d3b75561 | ||
|
a437136543 | ||
|
16545a5765 | ||
|
eb49f4d0d2 | ||
|
08f77c692a | ||
|
deb489cd8c | ||
|
9a32aab879 | ||
|
42a42c49ac | ||
|
5fb6e2e1bc | ||
|
c09e36ef8b | ||
|
09cd426443 | ||
|
7991d007ac | ||
|
17e6078122 | ||
|
31d561b470 | ||
|
3ca9613bcd | ||
|
42c66160a7 | ||
|
5ce427b62b | ||
|
79875c8088 | ||
|
ce5b694458 |
248 changed files with 31679 additions and 7623 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
# SPDX-FileCopyrightText: (C) Eric S. Raymond
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
advent
|
||||
*.gcda
|
||||
*.gcno
|
||||
|
|
|
@ -1,15 +1,28 @@
|
|||
image: opensuse:tumbleweed
|
||||
|
||||
# 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
|
||||
before_script:
|
||||
- zypper install -y make gcc libedit-devel libasan5 libubsan1 python python2-PyYAML lcov
|
||||
script:
|
||||
- make debug
|
||||
artifacts:
|
||||
|
@ -22,8 +35,6 @@ binary:debug:
|
|||
|
||||
binary:release:
|
||||
stage: build
|
||||
before_script:
|
||||
- zypper install -y make gcc libedit-devel python python2-PyYAML
|
||||
script:
|
||||
- make advent cheat
|
||||
artifacts:
|
||||
|
@ -36,8 +47,6 @@ binary:release:
|
|||
|
||||
manpage:
|
||||
stage: build
|
||||
before_script:
|
||||
- zypper install -y make asciidoc
|
||||
script:
|
||||
- make advent.6
|
||||
artifacts:
|
||||
|
@ -46,8 +55,6 @@ manpage:
|
|||
|
||||
html:
|
||||
stage: build
|
||||
before_script:
|
||||
- zypper install -y make asciidoc libxslt
|
||||
script:
|
||||
- make html
|
||||
artifacts:
|
||||
|
@ -56,8 +63,6 @@ html:
|
|||
|
||||
dist:
|
||||
stage: build
|
||||
before_script:
|
||||
- zypper install -y make asciidoc tar
|
||||
script:
|
||||
- export VERS=${CI_COMMIT_REF_NAME}
|
||||
- make dist -e
|
||||
|
@ -68,8 +73,6 @@ dist:
|
|||
# run tests using the binary built before
|
||||
test:debug:
|
||||
stage: test
|
||||
before_script:
|
||||
- zypper install -y make gcc libedit-devel libasan5 libubsan1 python python2-PyYAML lcov
|
||||
script:
|
||||
- make coverage
|
||||
artifacts:
|
||||
|
@ -78,17 +81,8 @@ test:debug:
|
|||
dependencies:
|
||||
- binary:debug
|
||||
|
||||
test:debug_clang:
|
||||
stage: test
|
||||
before_script:
|
||||
- zypper install -y make clang libedit-devel python python2-PyYAML lcov
|
||||
script:
|
||||
- CC=clang make debug check
|
||||
|
||||
test:release:
|
||||
stage: test
|
||||
before_script:
|
||||
- zypper install -y make libedit
|
||||
script:
|
||||
- cd tests
|
||||
- make
|
||||
|
|
2
.shipper
2
.shipper
|
@ -1,3 +1,5 @@
|
|||
#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>
|
||||
"""
|
||||
|
|
5
COPYING
5
COPYING
|
@ -1,7 +1,4 @@
|
|||
BSD LICENSE
|
||||
|
||||
Copyright (c) 1977, 2005 by Will Crowther and Don Woods
|
||||
Copyright (c) 2017 by Eric S. Raymond
|
||||
BSD 2-Clause LICENSE
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
|
|
12
Dockerfile.ci
Normal file
12
Dockerfile.ci
Normal file
|
@ -0,0 +1,12 @@
|
|||
# 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
|
38
INSTALL.adoc
38
INSTALL.adoc
|
@ -1,29 +1,27 @@
|
|||
= Installing Open Adventure =
|
||||
// SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
|
||||
// SPDX-License-Identifier: CC-BY-4.0
|
||||
|
||||
The instructions below assume your system uses Python 3 by default,
|
||||
but the actual Python code in Open Adventure is 2/3 agnostic. Adjust
|
||||
the example commands below accordingly.
|
||||
Installation now requires Python3 due to a security issue
|
||||
with the YAML library.
|
||||
|
||||
1. Install PyYAML for Python 3 (which requires Python 3) and libedit
|
||||
from http://thrysoee.dk/editline/ (aka: editline) on your system.
|
||||
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`.
|
||||
|
||||
On Debian and Ubuntu: 'apt-get install python3-yaml libedit-dev'.
|
||||
On Fedora: 'dnf install python3-PyYAML libedit-devel'.
|
||||
2. Change to the top-level directory of the source code (e.g., `cd open-adventure`).
|
||||
|
||||
If you are using MacPorts on OS X: 'port install py3{5,6}-yaml', as
|
||||
appropriate for your Python 3 version.
|
||||
3. Build with `make`.
|
||||
|
||||
You can also use pip to install PyYAML: 'pip3 install PyYAML'.
|
||||
4. Optionally run a regression test on the code with `make check`.
|
||||
|
||||
2. 'make'.
|
||||
5. Run `./advent` to play.
|
||||
|
||||
3. Optionally run a regression test on the code with 'make check'.
|
||||
6. If you want to buld the documentation you will need asciidoctor.
|
||||
|
||||
4. Run the resulting 'advent' binary to play.
|
||||
|
||||
If make returns the following message:
|
||||
|
||||
./make_dungeon.py Traceback (most recent call last): File "./make_dungeon.py", line 10, in import sys, yaml ImportError: No module named yaml
|
||||
|
||||
try editing make_dungeon.py to change #!/usr/bin/env python to read
|
||||
#!/usr/bin/env python3
|
||||
7. Running the regression tests requires batchspell
|
||||
|
|
67
Makefile
67
Makefile
|
@ -1,17 +1,27 @@
|
|||
# Makefile for the open-source release of adventure 2.5
|
||||
|
||||
# To build with save/resume disabled, pass CCFLAGS="-D ADVENT_NOSAVE"
|
||||
# SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
VERS=$(shell sed -n <NEWS '/^[0-9]/s/:.*//p' | head -1)
|
||||
# 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 -D_DEFAULT_SOURCE -DVERSION=\"$(VERS)\" -O2 -D_FORTIFY_SOURCE=2 -fstack-protector-all
|
||||
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
|
||||
|
@ -39,7 +49,7 @@ 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 templates/*.tpl
|
||||
dungeon.c dungeon.h: make_dungeon.py adventure.yaml advent.h templates/*.tpl
|
||||
./make_dungeon.py
|
||||
|
||||
clean:
|
||||
|
@ -55,26 +65,46 @@ clean:
|
|||
cheat: $(CHEAT_OBJS) dungeon.o
|
||||
$(CC) $(CCFLAGS) $(DBX) -o cheat $(CHEAT_OBJS) dungeon.o $(LDFLAGS) $(LIBS)
|
||||
|
||||
check: advent cheat
|
||||
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
|
||||
|
||||
coverage: debug
|
||||
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
|
||||
|
||||
.SUFFIXES: .adoc .html .6
|
||||
# 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
|
||||
|
||||
# Requires asciidoc and xsltproc/docbook stylesheets.
|
||||
.adoc.6:
|
||||
a2x --doctype manpage --format manpage $<
|
||||
asciidoctor -D. -a nofooter -b manpage $<
|
||||
.adoc.html:
|
||||
asciidoc $<
|
||||
.adoc:
|
||||
asciidoc $<
|
||||
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 README.adoc TODO advent.adoc history.adoc notes.adoc hints.adoc advent.6 INSTALL.adoc
|
||||
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.
|
||||
|
@ -85,9 +115,6 @@ advent-$(VERS).tar.gz: $(SOURCES) $(DOCS)
|
|||
(tar -T MANIFEST -czvf advent-$(VERS).tar.gz)
|
||||
@(rm advent-$(VERS))
|
||||
|
||||
indent:
|
||||
astyle -n -A3 --pad-header --min-conditional-indent=1 --pad-oper *.c
|
||||
|
||||
release: advent-$(VERS).tar.gz advent.html history.html hints.html notes.html
|
||||
shipper version=$(VERS) | sh -e -x
|
||||
|
||||
|
@ -119,6 +146,11 @@ 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
|
||||
|
@ -127,6 +159,3 @@ debug: CCFLAGS += -fsanitize=address
|
|||
debug: CCFLAGS += -fsanitize=undefined
|
||||
debug: linty
|
||||
|
||||
CSUPPRESSIONS = --suppress=missingIncludeSystem --suppress=invalidscanf
|
||||
cppcheck:
|
||||
cppcheck -I. --template gcc --enable=all $(CSUPPRESSIONS) *.[ch]
|
||||
|
|
36
NEWS
36
NEWS
|
@ -1,36 +0,0 @@
|
|||
= Open Adventure project news =
|
||||
|
||||
1.6: 2017-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.
|
90
NEWS.adoc
Normal file
90
NEWS.adoc
Normal file
|
@ -0,0 +1,90 @@
|
|||
= 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.
|
|
@ -1,4 +1,6 @@
|
|||
= 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.
|
||||
|
@ -23,13 +25,16 @@ 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 are revertible with the
|
||||
-o (oldstyle) option.
|
||||
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
|
||||
|
||||
|
||||
|
|
19
TODO
19
TODO
|
@ -1,19 +0,0 @@
|
|||
= Open Adventure TODO =
|
||||
|
||||
The FORTRANish mess that once was is now mostly idiomatic C. Some issues
|
||||
remain to be cleaned up:
|
||||
|
||||
* Remaining unstructured gotos in do_command().
|
||||
|
||||
* The program is still pretty much typeless. Some attempt has been
|
||||
made to introduce semantic types, but the job is barely started.
|
||||
|
||||
* More possible vase tests: FILL VASE while it's on the ground next to you;
|
||||
DROP VASE in the Soft Room; DROP VASE in the well house and confirm
|
||||
that you do/don't get points for it; die while carrying the vase and
|
||||
confirm that it doesn't break.
|
||||
|
||||
We are aware that the lamp currently used as the project logo is a
|
||||
hurricane lamp, not a proper miner's lamp. Submissions of potential
|
||||
replacement images would be welcome.
|
||||
|
45
advent.adoc
45
advent.adoc
|
@ -1,14 +1,19 @@
|
|||
= 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] [-s]
|
||||
*advent* [-l logfile] [-o] [-r savefile] [-a savefile] [script...]
|
||||
|
||||
== DESCRIPTION ==
|
||||
The original Colossal Cave Adventure from 1976-77 was the origin of all
|
||||
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.
|
||||
|
||||
|
@ -18,19 +23,22 @@ 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 1976 ancestor of this game. 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.
|
||||
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 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.
|
||||
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.
|
||||
|
||||
Otherwise, the "version" command is about the only way to tell you're not
|
||||
running Don's original.
|
||||
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).
|
||||
|
||||
|
@ -40,17 +48,24 @@ There have been no gameplay changes.
|
|||
|
||||
-l:: Log commands to specified file.
|
||||
|
||||
-r:: Restore game from specified file
|
||||
-r:: Restore game from specified save file
|
||||
|
||||
-o:: Old-style. Restores original interface, no prompt or line editing.
|
||||
-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 word
|
||||
size and endianness, and unlikely to survive through version bumps. There
|
||||
is a version check.
|
||||
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
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# SPDX-FileCopyrightText: (C) Eric S. Raymond <esr@thyrsus.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Open Adventure
|
||||
|
|
448
advent.h
448
advent.h
|
@ -1,8 +1,14 @@
|
|||
/*
|
||||
* 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 <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "dungeon.h"
|
||||
|
||||
|
@ -12,174 +18,231 @@
|
|||
#define LCG_C 221587L
|
||||
#define LCG_M 1048576L
|
||||
|
||||
#define LINESIZE 1024
|
||||
#define TOKLEN 5 // № sigificant characters in a token */
|
||||
#define NDWARVES 6 // number of dwarves
|
||||
#define PIRATE NDWARVES // must be NDWARVES-1 when zero-origin
|
||||
#define DALTLC LOC_NUGGET // alternate dwarf location
|
||||
#define INVLIMIT 7 // inverntory 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 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
|
||||
#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
|
||||
#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
|
||||
|
||||
/* Map a state property value to a negative range, where the object cannot be
|
||||
* picked up but the value can be recovered later. Avoid colliding with -1,
|
||||
* which has its own meaning. */
|
||||
#define STASHED(obj) (-1 - game.prop[obj])
|
||||
/* (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 "> "
|
||||
|
||||
/*
|
||||
* MOD(N,M) = Arithmetic modulus
|
||||
* 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(LOC) = 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)
|
||||
* LIQUID() = 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 DESTROY(N) move(N, LOC_NOWHERE)
|
||||
#define MOD(N,M) ((N) % (M))
|
||||
#define TOTING(OBJ) (game.place[OBJ] == CARRIED)
|
||||
#define AT(OBJ) (game.place[OBJ] == game.loc || game.fixed[OBJ] == game.loc)
|
||||
#define HERE(OBJ) (AT(OBJ) || TOTING(OBJ))
|
||||
#define CNDBIT(L,N) (tstbit(conditions[L],N))
|
||||
#define LIQUID() (game.prop[BOTTLE] == WATER_BOTTLE? WATER : game.prop[BOTTLE] == 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 DARK(DUMMY) (!CNDBIT(game.loc,COND_LIT) && (game.prop[LAMP] == 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 OUTSID(LOC) (CNDBIT(LOC, COND_ABOVE) || FOREST(LOC))
|
||||
#define INSIDE(LOC) (!OUTSID(LOC) || LOC == LOC_BUILDING)
|
||||
#define INDEEP(LOC) ((LOC) >= LOC_MISTHALL && !OUTSID(LOC))
|
||||
#define BUG(x) bug(x, #x)
|
||||
* 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,
|
||||
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 speaktype { touch, look, hear, study, change };
|
||||
|
||||
enum termination {endgame, quitgame, scoregame};
|
||||
enum termination { endgame, quitgame, scoregame };
|
||||
|
||||
enum speechpart {unknown, intransitive, transitive};
|
||||
enum speechpart { unknown, intransitive, transitive };
|
||||
|
||||
typedef enum {NO_WORD_TYPE, MOTION, OBJECT, ACTION, NUMERIC} word_type_t;
|
||||
typedef enum { NO_WORD_TYPE, MOTION, OBJECT, ACTION, NUMERIC } word_type_t;
|
||||
|
||||
typedef enum scorebonus {none, splatter, defeat, victory} score_t;
|
||||
typedef enum scorebonus { none, splatter, defeat, victory } score_t;
|
||||
|
||||
/* Phase codes for action returns.
|
||||
* These were at one time FORTRAN line numbers.
|
||||
* The values don't matter, but perturb their order at your peril.
|
||||
*/
|
||||
enum phase_codes {
|
||||
GO_TERMINATE,
|
||||
GO_MOVE,
|
||||
GO_TOP,
|
||||
GO_CLEAROBJ,
|
||||
GO_CHECKHINT,
|
||||
GO_CHECKFOO,
|
||||
GO_LOOKUP,
|
||||
GO_WORD2,
|
||||
GO_UNKNOWN,
|
||||
GO_DWARFWAKE,
|
||||
};
|
||||
typedef enum {
|
||||
GO_TERMINATE,
|
||||
GO_MOVE,
|
||||
GO_TOP,
|
||||
GO_CLEAROBJ,
|
||||
GO_CHECKHINT,
|
||||
GO_WORD2,
|
||||
GO_UNKNOWN,
|
||||
GO_DWARFWAKE,
|
||||
} phase_codes_t;
|
||||
|
||||
typedef long vocab_t; // index into a vocabulary array */
|
||||
typedef long verb_t; // index into an actions array */
|
||||
typedef long obj_t; // index into the object array */
|
||||
typedef long loc_t; // index into the locations array */
|
||||
typedef long turn_t; // turn counter or threshold */
|
||||
/* 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;
|
||||
long abbnum; // How often to print long 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
|
||||
bool clshnt; // has player read the clue in the endgame?
|
||||
bool closed; // whether we're all the way closed
|
||||
bool closng; // whether it's closing time yet
|
||||
bool lmwarn; // has player been warned about lamp going dim?
|
||||
bool novice; // asked for instructions at start-up?
|
||||
bool panic; // has player found out he's trapped?
|
||||
bool wzdark; // whether the loc he's leaving was dark
|
||||
bool blooded; // has player drunk of dragon's blood?
|
||||
long conds; // min value for cond[loc] if loc has any hints
|
||||
long detail; // level of detail in descriptions
|
||||
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 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) */
|
||||
long dflag;
|
||||
/* 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;
|
||||
|
||||
long dkill; // dwarves killed
|
||||
long dtotal; // total dwarves (including pirate) in loc
|
||||
long foobar; // progress in saying "FEE FIE FOE FOO".
|
||||
long holdng; // number of objects being carried
|
||||
long igo; // # uses of "go" instead of a direction
|
||||
long iwest; // # times he's said "west" instead of "w"
|
||||
long knfloc; // knife location; 0 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
|
||||
long saved; // point penalty for saves
|
||||
long tally; // count of treasures gained
|
||||
long thresh; // current threshold for endgame scoring tier
|
||||
turn_t trndex; // FIXME: not used, remove on next format bump
|
||||
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
|
||||
long abbrev[NLOCATIONS + 1]; // has location been seen?
|
||||
long atloc[NLOCATIONS + 1]; // head of object linked list per location
|
||||
long dseen[NDWARVES + 1]; // true if dwarf has seen him
|
||||
loc_t dloc[NDWARVES + 1]; // location of dwarves, initially hard-wired in
|
||||
loc_t odloc[NDWARVES + 1]; // prior loc of each dwarf, initially garbage
|
||||
loc_t fixed[NOBJECTS + 1]; // fixed location of object (if not IS_FREE)
|
||||
obj_t link[NOBJECTS * 2 + 1]; // object-list links
|
||||
loc_t place[NOBJECTS + 1]; // location of object
|
||||
long hinted[NHINTS]; // hinted[i] = true iff hint i has been used.
|
||||
long hintlc[NHINTS]; // hintlc[i] = how long at LOC with cond bit i
|
||||
long prop[NOBJECTS + 1]; // object state array */
|
||||
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
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -187,57 +250,104 @@ struct game_t {
|
|||
* This data is not saved in a saved game.
|
||||
*/
|
||||
struct settings_t {
|
||||
FILE *logfp;
|
||||
bool oldstyle;
|
||||
bool prompt;
|
||||
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;
|
||||
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;
|
||||
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 speak(const char*, ...);
|
||||
extern void clear_command(command_t *);
|
||||
extern void speak(const char *, ...);
|
||||
extern void sspeak(int msg, ...);
|
||||
extern void pspeak(vocab_t, enum speaktype, int, bool, ...);
|
||||
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(void);
|
||||
extern bool yes(const char*, const char*, const char*);
|
||||
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 loc_t put(obj_t, long, long);
|
||||
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 long setbit(int);
|
||||
extern bool tstbit(long, int);
|
||||
extern int setbit(int);
|
||||
extern bool tstbit(int, int);
|
||||
extern void set_seed(int32_t);
|
||||
extern int32_t randrange(int32_t);
|
||||
extern long score(enum termination);
|
||||
extern int score(enum termination);
|
||||
extern void terminate(enum termination) __attribute__((noreturn));
|
||||
extern int savefile(FILE *, int32_t);
|
||||
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 long initialise(void);
|
||||
extern int action(command_t command);
|
||||
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);
|
||||
|
||||
void bug(enum bugtype, const char *) __attribute__((__noreturn__));
|
||||
extern void bug(enum bugtype, const char *) __attribute__((__noreturn__));
|
||||
|
||||
/* represent an empty command word */
|
||||
static const command_word_t empty_command_word = {
|
||||
|
|
26
advent.svg
26
advent.svg
|
@ -2,30 +2,8 @@
|
|||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!--
|
||||
Copyright © 2017 Dr. Tobias Quathamer <toddy@debian.org>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
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">
|
||||
|
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 4 KiB |
435
adventure.yaml
435
adventure.yaml
File diff suppressed because it is too large
Load diff
165
cheat.c
165
cheat.c
|
@ -1,98 +1,105 @@
|
|||
/*
|
||||
* '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 outputing save files that advent
|
||||
* savefile(), so we know we're always outputting save files that advent
|
||||
* can import.
|
||||
*
|
||||
* Copyright (c) 1977, 2005 by Will Crowther and Don Woods
|
||||
* Copyright (c) 2017 by Eric S. Raymond
|
||||
* SPDX-License-Identifier: BSD-2-clause
|
||||
* SPDX-FileCopyrightText: (C) 1977, 2005 by Will Crowther and Don Woods
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#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;
|
||||
int version = 0;
|
||||
FILE *fp = NULL;
|
||||
int main(int argc, char *argv[]) {
|
||||
int ch;
|
||||
char *savefilename = NULL;
|
||||
FILE *fp = NULL;
|
||||
|
||||
// Initialize game variables
|
||||
initialise();
|
||||
// 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;
|
||||
/* 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";
|
||||
/* 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 = %ld\n", game.numdie);
|
||||
break;
|
||||
case 'l':
|
||||
game.limit = (turn_t)atoi(optarg);
|
||||
printf("cheat: game.limit = %ld\n", game.limit);
|
||||
break;
|
||||
case 's':
|
||||
game.saved = (long)atoi(optarg);
|
||||
printf("cheat: game.saved = %ld\n", game.saved);
|
||||
break;
|
||||
case 't':
|
||||
game.turns = (turn_t)atoi(optarg);
|
||||
printf("cheat: game.turns = %ld\n", game.turns);
|
||||
break;
|
||||
case 'v':
|
||||
version = atoi(optarg);
|
||||
printf("cheat: version = %d\n", version);
|
||||
break;
|
||||
case 'o':
|
||||
savefilename = optarg;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
usage, argv[0]);
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
fp = fopen(savefilename, WRITE_MODE);
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Can't open file %s. Exiting.\n", savefilename);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
savefile(fp, version);
|
||||
savefile(fp);
|
||||
|
||||
fclose(fp);
|
||||
fclose(fp);
|
||||
|
||||
printf("cheat: %s created.\n", savefilename);
|
||||
printf("cheat: %s created.\n", savefilename);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
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 */
|
||||
|
|
15
control
15
control
|
@ -4,12 +4,11 @@
|
|||
Package: open-adventure
|
||||
|
||||
Description: Colossal Cave Adventure, the 1995 430-point 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
|
||||
for the built program to avoid collision with the BSD Games version.
|
||||
|
||||
#XBS-Destinations: freshcode
|
||||
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.
|
||||
|
||||
Homepage: http://www.catb.org/~esr/open-adventure
|
||||
|
||||
|
@ -17,6 +16,8 @@ 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
|
||||
|
@ -25,4 +26,4 @@ XBS-VC-Tag-Template: %(version)s
|
|||
|
||||
XBS-Logo: lamp.png
|
||||
|
||||
XBS-Validate: make check
|
||||
XBS-Validate: make pylint cppcheck check
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
= 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.
|
||||
|
||||
|
|
41
history.adoc
41
history.adoc
|
@ -1,5 +1,7 @@
|
|||
= 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
|
||||
|
@ -15,9 +17,9 @@ 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 in 1977
|
||||
(some sources, apparently erroneously, say 1976). That version is
|
||||
sometimes known as 350-point Adventure.
|
||||
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
|
||||
|
@ -115,19 +117,21 @@ and 2.5:
|
|||
............................................................................
|
||||
|
||||
Great care has been taken to preserve 2.5's exact gameplay as intended
|
||||
by Don. 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.
|
||||
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 site
|
||||
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
|
||||
|
@ -145,23 +149,26 @@ 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
|
||||
after historians rediscovered Yob's game.)
|
||||
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/
|
||||
- [[[IFA]]] http://rickadams.org/adventure/[Colossal Cave Adventure Page]
|
||||
|
||||
- [[[DA]]] http://www.filfre.net/sitemap/
|
||||
- [[[DA]]] http://www.filfre.net/sitemap/[The Digital Antiquarian]
|
||||
|
||||
- [[[SN]]] http://www.digitalhumanities.org/dhq/vol/1/2/000009/000009.html
|
||||
- [[[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]]] https://en.wikipedia.org/wiki/Dnd_(video_game)[dnd (video game)]
|
||||
|
||||
- [[[WUMPUS]]] https://en.wikipedia.org/wiki/Hunt_the_Wumpus
|
||||
- [[[WUMPUS]]] https://en.wikipedia.org/wiki/Hunt_the_Wumpus[Hunt The Wumpus]
|
||||
|
||||
- [[[QUUX]]] https://github.com/Quuxplusone/Advent
|
||||
- [[[QUUX]]] https://github.com/Quuxplusone/Advent[Quuxplusone/Advent]
|
||||
|
|
147
init.c
147
init.c
|
@ -1,101 +1,96 @@
|
|||
/*
|
||||
* Initialisation
|
||||
*
|
||||
* Copyright (c) 1977, 2005 by Will Crowther and Don Woods
|
||||
* Copyright (c) 2017 by Eric S. Raymond
|
||||
* SPDX-License-Identifier: BSD-2-clause
|
||||
* SPDX-FileCopyrightText: (C) 1977, 2005 by Will Crowther and Don Woods
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "advent.h"
|
||||
|
||||
struct settings_t settings = {
|
||||
.logfp = NULL,
|
||||
.oldstyle = false,
|
||||
.prompt = true
|
||||
};
|
||||
struct settings_t settings = {.logfp = NULL, .oldstyle = false, .prompt = true};
|
||||
|
||||
struct game_t game = {
|
||||
.dloc[1] = LOC_KINGHALL,
|
||||
.dloc[2] = LOC_WESTBANK,
|
||||
.dloc[3] = LOC_Y2,
|
||||
.dloc[4] = LOC_ALIKE3,
|
||||
.dloc[5] = LOC_COMPLEX,
|
||||
|
||||
/* Sixth dwarf is special (the pirate). He always starts at his
|
||||
/* 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. */
|
||||
.dloc[6] = LOC_DEADEND12,
|
||||
.chloc = LOC_DEADEND12,
|
||||
.chloc2 = LOC_DEADEND13,
|
||||
.abbnum = 5,
|
||||
.clock1 = WARNTIME,
|
||||
.clock2 = FLASHTIME,
|
||||
.newloc = LOC_START,
|
||||
.loc = LOC_START,
|
||||
.limit = GAMELIMIT,
|
||||
.foobar = WORD_EMPTY,
|
||||
.chloc = LOC_MAZEEND12, .chloc2 = LOC_DEADEND13, .abbnum = 5,
|
||||
.clock1 = WARNTIME, .clock2 = FLASHTIME, .newloc = LOC_START,
|
||||
.loc = LOC_START, .limit = GAMELIMIT, .foobar = WORD_EMPTY,
|
||||
};
|
||||
|
||||
long initialise(void)
|
||||
{
|
||||
if (settings.oldstyle)
|
||||
printf("Initialising...\n");
|
||||
int initialise(void) {
|
||||
if (settings.oldstyle) {
|
||||
printf("Initialising...\n");
|
||||
}
|
||||
|
||||
srand(time(NULL));
|
||||
long seedval = (long)rand();
|
||||
set_seed(seedval);
|
||||
srand(time(NULL));
|
||||
int seedval = (int)rand();
|
||||
set_seed(seedval);
|
||||
|
||||
for (int i = 1; i <= NOBJECTS; i++) {
|
||||
game.place[i] = LOC_NOWHERE;
|
||||
}
|
||||
for (int i = 1; i <= NDWARVES; i++) {
|
||||
game.dwarves[i].loc = dwarflocs[i - 1];
|
||||
}
|
||||
|
||||
for (int i = 1; i <= NLOCATIONS; i++) {
|
||||
if (!(locations[i].description.big == 0 ||
|
||||
tkey[i] == 0)) {
|
||||
int k = tkey[i];
|
||||
if (T_TERMINATE(travel[k]))
|
||||
conditions[i] |= (1 << COND_FORCED);
|
||||
}
|
||||
}
|
||||
for (int i = 1; i <= NOBJECTS; i++) {
|
||||
game.objects[i].place = LOC_NOWHERE;
|
||||
}
|
||||
|
||||
/* Set up the game.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 <= 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 1; i <= NOBJECTS; i++) {
|
||||
int k = NOBJECTS + 1 - i;
|
||||
game.fixed[k] = objects[k].fixd;
|
||||
if (objects[k].plac != 0 && objects[k].fixd <= 0)
|
||||
drop(k, objects[k].plac);
|
||||
}
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* Treasure props are initially -1, and are set to 0 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. */
|
||||
for (int treasure = 1; treasure <= NOBJECTS; treasure++) {
|
||||
if (objects[treasure].is_treasure) {
|
||||
if (objects[treasure].inventory != 0)
|
||||
game.prop[treasure] = STATE_NOTFOUND;
|
||||
game.tally = game.tally - game.prop[treasure];
|
||||
}
|
||||
}
|
||||
game.conds = setbit(11);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
return seedval;
|
||||
/* 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;
|
||||
}
|
||||
|
|
339
make_dungeon.py
339
make_dungeon.py
|
@ -1,14 +1,16 @@
|
|||
#!/usr/bin/env python
|
||||
#!/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.
|
||||
|
||||
# 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().
|
||||
#
|
||||
# Copyright (c) 2017 by Eric S. Raymond
|
||||
# SPDX-License-Identifier: BSD-2-clause
|
||||
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
|
||||
|
||||
|
@ -22,9 +24,10 @@ 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 == None:
|
||||
if string is None:
|
||||
return "NULL"
|
||||
string = string.replace("\n", "\\n")
|
||||
string = string.replace("\t", "\\t")
|
||||
|
@ -33,14 +36,16 @@ def make_c_string(string):
|
|||
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
|
||||
ref_str = ref_str[:-1] # trim trailing newline
|
||||
return ref_str
|
||||
|
||||
|
||||
def get_string_group(strings):
|
||||
template = """{{
|
||||
.strs = {},
|
||||
|
@ -49,20 +54,24 @@ def get_string_group(strings):
|
|||
if strings == []:
|
||||
strs = "NULL"
|
||||
else:
|
||||
strs = "(const char* []) {" + ", ".join([make_c_string(s) for s in strings]) + "}"
|
||||
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
|
||||
arb_str = arb_str[:-1] # trim trailing newline
|
||||
return arb_str
|
||||
|
||||
|
||||
def get_class_messages(cls):
|
||||
template = """ {{
|
||||
.threshold = {},
|
||||
|
@ -74,9 +83,10 @@ def get_class_messages(cls):
|
|||
threshold = item["threshold"]
|
||||
message = make_c_string(item["message"])
|
||||
cls_str += template.format(threshold, message)
|
||||
cls_str = cls_str[:-1] # trim trailing newline
|
||||
cls_str = cls_str[:-1] # trim trailing newline
|
||||
return cls_str
|
||||
|
||||
|
||||
def get_turn_thresholds(trn):
|
||||
template = """ {{
|
||||
.threshold = {},
|
||||
|
@ -90,9 +100,10 @@ def get_turn_thresholds(trn):
|
|||
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
|
||||
trn_str = trn_str[:-1] # trim trailing newline
|
||||
return trn_str
|
||||
|
||||
|
||||
def get_locations(loc):
|
||||
template = """ {{ // {}: {}
|
||||
.description = {{
|
||||
|
@ -110,9 +121,10 @@ def get_locations(loc):
|
|||
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
|
||||
loc_str = loc_str[:-1] # trim trailing newline
|
||||
return loc_str
|
||||
|
||||
|
||||
def get_objects(obj):
|
||||
template = """ {{ // {}: {}
|
||||
.words = {},
|
||||
|
@ -134,6 +146,7 @@ def get_objects(obj):
|
|||
}},
|
||||
}},
|
||||
"""
|
||||
max_state = 0
|
||||
obj_str = ""
|
||||
for (i, item) in enumerate(obj):
|
||||
attr = item[1]
|
||||
|
@ -143,7 +156,7 @@ def get_objects(obj):
|
|||
words_str = get_string_group([])
|
||||
i_msg = make_c_string(attr["inventory"])
|
||||
descriptions_str = ""
|
||||
if attr["descriptions"] == None:
|
||||
if attr["descriptions"] is None:
|
||||
descriptions_str = " " * 12 + "NULL,"
|
||||
else:
|
||||
labels = []
|
||||
|
@ -151,47 +164,62 @@ def get_objects(obj):
|
|||
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
|
||||
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") == None:
|
||||
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
|
||||
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") == None:
|
||||
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
|
||||
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") == None:
|
||||
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
|
||||
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 type(locs) == str:
|
||||
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
|
||||
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 = {},
|
||||
|
@ -203,9 +231,10 @@ def get_obituaries(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
|
||||
obit_str = obit_str[:-1] # trim trailing newline
|
||||
return obit_str
|
||||
|
||||
|
||||
def get_hints(hnt):
|
||||
template = """ {{
|
||||
.number = {},
|
||||
|
@ -224,9 +253,10 @@ def get_hints(hnt):
|
|||
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
|
||||
hnt_str = hnt_str[:-1] # trim trailing newline
|
||||
return hnt_str
|
||||
|
||||
|
||||
def get_condbits(locations):
|
||||
cnd_str = ""
|
||||
for (name, loc) in locations:
|
||||
|
@ -237,7 +267,7 @@ def get_condbits(locations):
|
|||
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])
|
||||
trail = "|".join([("(1<<COND_H%s)" % f["name"]) for f in hints])
|
||||
if trail:
|
||||
line += "|" + trail
|
||||
if line.startswith("|"):
|
||||
|
@ -247,6 +277,7 @@ def get_condbits(locations):
|
|||
cnd_str += " " + line + ",\t// " + name + "\n"
|
||||
return cnd_str
|
||||
|
||||
|
||||
def get_motions(motions):
|
||||
template = """ {{
|
||||
.words = {},
|
||||
|
@ -255,18 +286,19 @@ def get_motions(motions):
|
|||
mot_str = ""
|
||||
for motion in motions:
|
||||
contents = motion[1]
|
||||
if contents["words"] == None:
|
||||
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 contents.get("oldstyle", True) == False:
|
||||
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 = {},
|
||||
|
@ -278,41 +310,43 @@ def get_actions(actions):
|
|||
for action in actions:
|
||||
contents = action[1]
|
||||
|
||||
if contents["words"] == None:
|
||||
if contents["words"] is None:
|
||||
words_str = get_string_group([])
|
||||
else:
|
||||
words_str = get_string_group(contents["words"])
|
||||
|
||||
if contents["message"] == None:
|
||||
if contents["message"] is None:
|
||||
message = "NULL"
|
||||
else:
|
||||
message = make_c_string(contents["message"])
|
||||
|
||||
if contents.get("noaction") == None:
|
||||
if contents.get("noaction") is None:
|
||||
noaction = "false"
|
||||
else:
|
||||
noaction = "true"
|
||||
|
||||
act_str += template.format(words_str, message, noaction)
|
||||
global ignore
|
||||
if contents.get("oldstyle", True) == False:
|
||||
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
|
||||
act_str = act_str[:-1] # trim trailing newline
|
||||
return act_str
|
||||
|
||||
|
||||
def bigdump(arr):
|
||||
out = ""
|
||||
for (i, entry) in enumerate(arr):
|
||||
for (i, _) in enumerate(arr):
|
||||
if i % 10 == 0:
|
||||
if out and out[-1] == ' ':
|
||||
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
|
||||
|
@ -332,31 +366,31 @@ def buildtravel(locs, objs):
|
|||
# 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.
|
||||
# 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 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
|
||||
# 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
|
||||
# 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 = []
|
||||
|
@ -367,27 +401,37 @@ def buildtravel(locs, objs):
|
|||
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))
|
||||
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))
|
||||
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
|
||||
elif cond == ["nodwarves"]:
|
||||
if cond == ["nodwarves"]:
|
||||
return 100
|
||||
elif cond[0] == "pct":
|
||||
return cond[1]
|
||||
|
@ -395,33 +439,45 @@ def buildtravel(locs, objs):
|
|||
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.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 \n" % (cond[1], name))
|
||||
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 type(cond[2]) == int:
|
||||
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 type(stateclause) == list:
|
||||
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);
|
||||
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.stderr.write(
|
||||
"dungeon: unknown object name %s in not clause of %s\n"
|
||||
% (cond[1], name)
|
||||
)
|
||||
sys.exit(1)
|
||||
else:
|
||||
print(cond)
|
||||
|
@ -431,16 +487,18 @@ def buildtravel(locs, objs):
|
|||
if "travel" in loc:
|
||||
for rule in loc["travel"]:
|
||||
tt = [i]
|
||||
dest = dencode(rule["action"], name) + 1000 * cencode(rule.get("cond"), name)
|
||||
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
|
||||
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 wgat used to be the runtime format.
|
||||
# same mapping into what used to be the runtime format.
|
||||
|
||||
travel = [[0, "LOC_NOWHERE", 0, 0, 0, 0, 0, 0, "false", "false"]]
|
||||
tkey = [0]
|
||||
|
@ -451,12 +509,12 @@ def buildtravel(locs, objs):
|
|||
newloc = rule.pop(0)
|
||||
if loc != oldloc:
|
||||
tkey.append(len(travel))
|
||||
oldloc = loc
|
||||
oldloc = loc
|
||||
elif travel:
|
||||
travel[-1][-1] = "false" if travel[-1][-1] == "true" else "true"
|
||||
travel[-1][-1] = "false" if travel[-1][-1] == "true" else "true"
|
||||
while rule:
|
||||
cond = newloc // 1000
|
||||
nodwarves = (cond == 100)
|
||||
nodwarves = cond == 100
|
||||
if cond == 0:
|
||||
condtype = "cond_goto"
|
||||
condarg1 = condarg2 = 0
|
||||
|
@ -479,30 +537,35 @@ def buildtravel(locs, objs):
|
|||
else:
|
||||
condtype = "cond_not"
|
||||
condarg1 = cond % 100
|
||||
condarg2 = (cond - 300) // 100.
|
||||
condarg2 = (cond - 300) // 100.0
|
||||
dest = newloc % 1000
|
||||
if dest <= 300:
|
||||
desttype = "dest_goto";
|
||||
desttype = "dest_goto"
|
||||
destval = locnames[dest]
|
||||
elif dest > 500:
|
||||
desttype = "dest_speak";
|
||||
desttype = "dest_speak"
|
||||
destval = msgnames[dest - 500]
|
||||
else:
|
||||
desttype = "dest_special";
|
||||
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.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 = {},
|
||||
|
@ -518,47 +581,52 @@ def get_travel(travel):
|
|||
out = ""
|
||||
for entry in travel:
|
||||
out += template.format(*entry)
|
||||
out = out[:-1] # trim trailing newline
|
||||
out = out[:-1] # trim trailing newline
|
||||
return out
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
with open(YAML_NAME, "r") as f:
|
||||
db = yaml.load(f)
|
||||
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"])
|
||||
(travel, tkey) = buildtravel(db["locations"], db["objects"])
|
||||
ignore = ""
|
||||
try:
|
||||
with open(H_TEMPLATE_PATH, "r") as htf:
|
||||
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") as ctf:
|
||||
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))
|
||||
exit(-1)
|
||||
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
|
||||
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
|
||||
|
@ -566,29 +634,30 @@ if __name__ == "__main__":
|
|||
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
|
||||
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") as hf:
|
||||
with open(H_NAME, "w", encoding="ascii", errors="surrogateescape") as hf:
|
||||
hf.write(h)
|
||||
|
||||
with open(C_NAME, "w") as cf:
|
||||
with open(C_NAME, "w", encoding="ascii", errors="surrogateescape") as cf:
|
||||
cf.write(c)
|
||||
|
||||
# end
|
||||
|
|
221
make_graph.py
Executable file
221
make_graph.py
Executable file
|
@ -0,0 +1,221 @@
|
|||
#!/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
|
87
notes.adoc
87
notes.adoc
|
@ -1,5 +1,7 @@
|
|||
= 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
|
||||
|
@ -13,7 +15,9 @@ 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.
|
||||
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 ==
|
||||
|
||||
|
@ -41,25 +45,47 @@ 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.
|
||||
|
||||
* Behavior when saying the giant's magic words outside his room wasn't
|
||||
quite correct - the game responded as though the player were in
|
||||
the room ("...can't you read?"). The new message is "Well, that was
|
||||
remarkably pointless."
|
||||
|
||||
* 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
|
||||
say "floor" when it should say "ground" (or "dirt", or something).
|
||||
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,
|
||||
|
@ -76,14 +102,15 @@ Unrecognized words are no longer truncated to 5 characters and
|
|||
uppercased when they are echoed. The "-o" (oldstyle) option restores
|
||||
this behavior.
|
||||
|
||||
Typing a numeric literal to the command prompt no longer triggers a
|
||||
fatal error. This change is reverted by the oldstyle option.
|
||||
|
||||
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
|
||||
|
@ -105,11 +132,28 @@ 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.
|
||||
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.
|
||||
|
@ -131,7 +175,7 @@ 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 (it seems clear from the code that words were originally
|
||||
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.
|
||||
|
@ -146,6 +190,9 @@ 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:
|
||||
|
||||
|
@ -155,10 +202,6 @@ ways:
|
|||
and the choice to refrain will make forward translation into future
|
||||
languages easier.
|
||||
|
||||
* There are a few gotos left that resist restructuring; all are in the
|
||||
principal command interpreter function implementing its state
|
||||
machine.
|
||||
|
||||
* 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
|
||||
|
@ -169,14 +212,18 @@ ways:
|
|||
arrays are a cell larger than they strictly need to be and cell 0 is
|
||||
unused.
|
||||
|
||||
* The code is still mostly typeless, slinging around machine longs
|
||||
like a FORTRAN or BCPL program. Some (incomplete) effort has been made
|
||||
to introduce semantic types.
|
||||
|
||||
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
|
||||
|
|
415
saveresume.c
415
saveresume.c
|
@ -4,245 +4,264 @@
|
|||
* (ESR) This replaces a bunch of particularly nasty FORTRAN-derived code;
|
||||
* see the history.adoc file in the source distribution for discussion.
|
||||
*
|
||||
* Copyright (c) 1977, 2005 by Will Crowther and Don Woods
|
||||
* Copyright (c) 2017 by Eric S. Raymond
|
||||
* SPDX-License-Identifier: BSD-2-clause
|
||||
* 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 <editline/readline.h>
|
||||
#include <time.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "advent.h"
|
||||
#include "dungeon.h"
|
||||
|
||||
#define VRSION 28 /* bump on save format change */
|
||||
|
||||
/*
|
||||
* If you change the first three members, the resume function may not properly
|
||||
* reject saves from older versions. Yes, this glues us to a hardware-
|
||||
* dependent length of long. Later members can change, but bump the version
|
||||
* when you do that.
|
||||
* Use this to detect endianness mismatch. Can't be unchanged by byte-swapping.
|
||||
*/
|
||||
struct save_t {
|
||||
int64_t savetime;
|
||||
int32_t mode; /* not used, must be present for version detection */
|
||||
int32_t version;
|
||||
struct game_t game;
|
||||
};
|
||||
#define ENDIAN_MAGIC 2317
|
||||
|
||||
struct save_t save;
|
||||
|
||||
#define IGNORE(r) do{if (r){}}while(0)
|
||||
#define IGNORE(r) \
|
||||
do { \
|
||||
if (r) { \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
int savefile(FILE *fp, int32_t version)
|
||||
/* Save game to file. No input or output from user. */
|
||||
{
|
||||
save.savetime = time(NULL);
|
||||
save.mode = -1;
|
||||
save.version = (version == 0) ? VRSION : version;
|
||||
|
||||
save.game = game;
|
||||
IGNORE(fwrite(&save, sizeof(struct save_t), 1, fp));
|
||||
return (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 */
|
||||
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, do nothing instead. */
|
||||
|
||||
#ifdef ADVENT_NOSAVE
|
||||
return GO_UNKNOWN;
|
||||
#endif
|
||||
FILE *fp = NULL;
|
||||
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';
|
||||
}
|
||||
|
||||
rspeak(SUSPEND_WARNING);
|
||||
if (!yes(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 = readline("\nFile name: ");
|
||||
if (name == NULL)
|
||||
return GO_TOP;
|
||||
fp = fopen(name, WRITE_MODE);
|
||||
if (fp == NULL)
|
||||
printf("Can't open file %s, try again.\n", name);
|
||||
free(name);
|
||||
}
|
||||
|
||||
savefile(fp, VRSION);
|
||||
fclose(fp);
|
||||
rspeak(RESUME_HELP);
|
||||
exit(EXIT_SUCCESS);
|
||||
return name;
|
||||
}
|
||||
|
||||
int resume(void)
|
||||
{
|
||||
/* Resume. Read a suspended game back from a file.
|
||||
* If ADVENT_NOSAVE is defined, do nothing instead. */
|
||||
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. */
|
||||
|
||||
#ifdef ADVENT_NOSAVE
|
||||
return GO_UNKNOWN;
|
||||
#if defined ADVENT_NOSAVE || defined ADVENT_AUTOSAVE
|
||||
rspeak(SAVERESUME_DISABLED);
|
||||
return GO_TOP;
|
||||
#endif
|
||||
FILE *fp = NULL;
|
||||
FILE *fp = NULL;
|
||||
|
||||
if (game.loc != 1 ||
|
||||
game.abbrev[1] != 1) {
|
||||
rspeak(RESUME_ABANDON);
|
||||
if (!yes(arbitrary_messages[THIS_ACCEPTABLE], arbitrary_messages[OK_MAN], arbitrary_messages[OK_MAN]))
|
||||
return GO_CLEAROBJ;
|
||||
}
|
||||
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 = readline("\nFile name: ");
|
||||
if (name == NULL)
|
||||
return GO_TOP;
|
||||
fp = fopen(name, READ_MODE);
|
||||
if (fp == NULL)
|
||||
printf("Can't open file %s, try again.\n", name);
|
||||
free(name);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
return restore(fp);
|
||||
savefile(fp);
|
||||
fclose(fp);
|
||||
rspeak(RESUME_HELP);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
int restore(FILE* fp)
|
||||
{
|
||||
/* Read and restore game state from file, assuming
|
||||
* sane initial state.
|
||||
* If ADVENT_NOSAVE is defined, do nothing instead. */
|
||||
#ifdef ADVENT_NOSAVE
|
||||
return GO_UNKNOWN;
|
||||
#endif
|
||||
int resume(void) {
|
||||
/* Resume. Read a suspended game back from a file.
|
||||
* If ADVENT_NOSAVE is defined, gripe instead. */
|
||||
|
||||
IGNORE(fread(&save, sizeof(struct save_t), 1, fp));
|
||||
fclose(fp);
|
||||
if (save.version != VRSION) {
|
||||
rspeak(VERSION_SKEW, save.version / 10, MOD(save.version, 10), VRSION / 10, MOD(VRSION, 10));
|
||||
} else if (is_valid(save.game)) {
|
||||
game = save.game;
|
||||
}
|
||||
return GO_TOP;
|
||||
#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);
|
||||
}
|
||||
|
||||
bool is_valid(struct game_t valgame)
|
||||
{
|
||||
/* Save files can be roughly grouped into three groups:
|
||||
* With valid, reaceable state, with valid, but unreachable
|
||||
* state and with invaild state. We check that state is
|
||||
* valid: no states are outside minimal or maximal value
|
||||
*/
|
||||
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
|
||||
|
||||
/* Prevent division by zero */
|
||||
if (valgame.abbnum == 0) {
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* Check for RNG overflow. Truncate */
|
||||
if (valgame.lcg_x >= LCG_M) {
|
||||
valgame.lcg_x %= LCG_M;
|
||||
}
|
||||
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
|
||||
*/
|
||||
|
||||
/* Check for RNG underflow. Transpose */
|
||||
if (valgame.lcg_x < LCG_M) {
|
||||
valgame.lcg_x = LCG_M + (valgame.lcg_x % LCG_M);
|
||||
}
|
||||
/* Prevent division by zero */
|
||||
if (valgame.abbnum == 0) {
|
||||
return false; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/* Bounds check for location arrays */
|
||||
for (int i = 0; i <= NDWARVES; i++) {
|
||||
if (valgame.dloc[i] < -1 || valgame.dloc[i] > NLOCATIONS ||
|
||||
valgame.odloc[i] < -1 || valgame.odloc[i] > NLOCATIONS) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* Check for RNG overflow. Truncate */
|
||||
if (valgame.lcg_x >= LCG_M) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i <= NOBJECTS; i++) {
|
||||
if (valgame.place[i] < -1 || valgame.place[i] > NLOCATIONS ||
|
||||
valgame.fixed[i] < -1 || valgame.fixed[i] > NLOCATIONS) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/* Bounds check for dwarves */
|
||||
if (valgame.dtotal < 0 || valgame.dtotal > NDWARVES ||
|
||||
valgame.dkill < 0 || valgame.dkill > NDWARVES) {
|
||||
return false;
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/* Validate that we didn't die too many times in save */
|
||||
if (valgame.numdie >= NDEATHS) {
|
||||
return false;
|
||||
}
|
||||
/* Bounds check for dwarves */
|
||||
if (valgame.dtotal < 0 || valgame.dtotal > NDWARVES ||
|
||||
valgame.dkill < 0 || valgame.dkill > NDWARVES) {
|
||||
return false; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
/* Recalculate tally, throw the towel if in disagreement */
|
||||
long temp_tally = 0;
|
||||
for (int treasure = 1; treasure <= NOBJECTS; treasure++) {
|
||||
if (objects[treasure].is_treasure) {
|
||||
if (valgame.prop[treasure] == STATE_NOTFOUND) {
|
||||
++temp_tally;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (temp_tally != valgame.tally) {
|
||||
return false;
|
||||
}
|
||||
/* Validate that we didn't die too many times in save */
|
||||
if (valgame.numdie >= NDEATHS) {
|
||||
return false; // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
/* Check that properties of objects aren't beyond expected */
|
||||
for (obj_t obj = 0; obj <= NOBJECTS; obj++) {
|
||||
if (valgame.prop[obj] < STATE_NOTFOUND || valgame.prop[obj] > 1) {
|
||||
switch (obj) {
|
||||
case RUG:
|
||||
case DRAGON:
|
||||
case BIRD:
|
||||
case BOTTLE:
|
||||
case PLANT:
|
||||
case PLANT2:
|
||||
case TROLL:
|
||||
case URN:
|
||||
case EGGS:
|
||||
case VASE:
|
||||
case CHAIN:
|
||||
if (valgame.prop[obj] == 2) // There are multiple different states, but it's convenient to clump them together
|
||||
continue;
|
||||
/* FALLTHRU */
|
||||
case BEAR:
|
||||
if (valgame.prop[BEAR] == CONTENTED_BEAR || valgame.prop[BEAR] == BEAR_DEAD)
|
||||
continue;
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 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 values in linked lists for objects in locations are inside bounds */
|
||||
for (loc_t loc = LOC_NOWHERE; loc <= NLOCATIONS; loc++) {
|
||||
if (valgame.atloc[loc] < NO_OBJECT || valgame.atloc[loc] > NOBJECTS * 2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (obj_t obj = 0; obj <= NOBJECTS * 2; obj++ ) {
|
||||
if (valgame.link[obj] < NO_OBJECT || valgame.link[obj] > NOBJECTS * 2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* 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
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
/* 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 */
|
||||
|
|
257
score.c
257
score.c
|
@ -1,139 +1,162 @@
|
|||
/*
|
||||
* Scoring and wrap-up.
|
||||
*
|
||||
* Copyright (c) 1977, 2005 by Will Crowther and Don Woods
|
||||
* Copyright (c) 2017 by Eric S. Raymond
|
||||
* SPDX-License-Identifier: BSD-2-clause
|
||||
* SPDX-FileCopyrightText: (C) 1977, 2005 by Will Crowther and Don Woods
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include "advent.h"
|
||||
#include "dungeon.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
static int mxscor; /* ugh..the price for having score() not exit. */
|
||||
static int mxscor; /* ugh..the price for having score() not exit. */
|
||||
|
||||
long score(enum termination mode)
|
||||
/* mode is 'scoregame' if scoring, 'quitgame' if quitting, 'endgame' if died
|
||||
* or won */
|
||||
{
|
||||
int score = 0;
|
||||
int score(enum termination mode) {
|
||||
/* mode is 'scoregame' if scoring, 'quitgame' if quitting, 'endgame' if
|
||||
* died or won */
|
||||
int score = 0;
|
||||
|
||||
/* 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 "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. */
|
||||
|
||||
/* 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 (game.prop[i] > STATE_NOTFOUND)
|
||||
score += 2;
|
||||
if (game.place[i] == LOC_BUILDING && game.prop[i] == STATE_FOUND)
|
||||
score += k - 2;
|
||||
mxscor += k;
|
||||
}
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
/* 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;
|
||||
|
||||
/* Did he come to Witt's End as he should? */
|
||||
if (game.place[MAGAZINE] == LOC_WITTSEND)
|
||||
score += 1;
|
||||
mxscor += 1;
|
||||
/* Did he come to Witt's End as he should? */
|
||||
if (game.objects[MAGAZINE].place == LOC_WITTSEND) {
|
||||
score += 1;
|
||||
}
|
||||
mxscor += 1;
|
||||
|
||||
/* Round it off. */
|
||||
score += 2;
|
||||
mxscor += 2;
|
||||
/* Round it off. */
|
||||
score += 2;
|
||||
mxscor += 2;
|
||||
|
||||
/* Deduct for hints/turns/saves. Hints < 4 are special; see database desc. */
|
||||
for (int i = 0; i < NHINTS; i++) {
|
||||
if (game.hinted[i])
|
||||
score = score - hints[i].penalty;
|
||||
}
|
||||
if (game.novice)
|
||||
score -= 5;
|
||||
if (game.clshnt)
|
||||
score -= 10;
|
||||
score = score - game.trnluz - game.saved;
|
||||
/* 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;
|
||||
|
||||
/* Return to score command if that's where we came from. */
|
||||
if (mode == scoregame) {
|
||||
rspeak(GARNERED_POINTS, score, mxscor, game.turns, game.turns);
|
||||
}
|
||||
/* Return to score command if that's where we came from. */
|
||||
if (mode == scoregame) {
|
||||
rspeak(GARNERED_POINTS, score, mxscor, game.turns, game.turns);
|
||||
}
|
||||
|
||||
return score;
|
||||
return score;
|
||||
}
|
||||
|
||||
void terminate(enum termination mode)
|
||||
/* End of game. Let's tell him all about it. */
|
||||
{
|
||||
long points = score(mode);
|
||||
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 <= (long)NCLASSES; i++) {
|
||||
if (classes[i].threshold >= points) {
|
||||
speak(classes[i].message);
|
||||
i = classes[i].threshold + 1 - points;
|
||||
rspeak(NEXT_HIGHER, i, i);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
rspeak(OFF_SCALE);
|
||||
rspeak(NO_HIGHER);
|
||||
exit(EXIT_SUCCESS);
|
||||
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 */
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
<--
|
||||
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>
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
|
||||
SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "{h_file}"
|
||||
|
||||
const char* arbitrary_messages[] = {{
|
||||
|
@ -48,4 +53,7 @@ const travelop_t travel[] = {{
|
|||
|
||||
const char *ignore = "{ignore}";
|
||||
|
||||
/* end */
|
||||
/* Dwarf starting locations */
|
||||
const int dwarflocs[NDWARVES] = {{{dwarflocs}}};
|
||||
|
||||
/* end */
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
|
||||
SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
#ifndef DUNGEON_H
|
||||
#define DUNGEON_H
|
||||
|
||||
|
@ -12,22 +16,27 @@
|
|||
#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
|
||||
#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 */
|
||||
/* Bits past 10 indicate areas of interest to "hint" routines */
|
||||
#define COND_HBASE 10 /* Base for location hint bits */
|
||||
#define COND_HCAVE 11 /* Trying to get into cave */
|
||||
#define COND_HBIRD 12 /* Trying to catch bird */
|
||||
#define COND_HSNAKE 13 /* Trying to deal with snake */
|
||||
#define COND_HMAZE 14 /* Lost in maze */
|
||||
#define COND_HDARK 15 /* Pondering dark room */
|
||||
#define COND_HWITT 16 /* At Witt's End */
|
||||
#define COND_HCLIFF 17 /* Cliff with urn */
|
||||
#define COND_HWOODS 18 /* Lost in forest */
|
||||
#define COND_HOGRE 19 /* Trying to deal with ogre */
|
||||
#define COND_HJADE 20 /* Found all treasures except jade */
|
||||
#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;
|
||||
|
@ -104,13 +113,6 @@ typedef struct {{
|
|||
const bool stop;
|
||||
}} travelop_t;
|
||||
|
||||
/* Abstract out the encoding of words in the travel array. Gives us
|
||||
* some hope of getting to a less cryptic representation than we
|
||||
* inherited from FORTRAN, someday. To understand these, read the
|
||||
* encoding description for travel.
|
||||
*/
|
||||
#define T_TERMINATE(entry) ((entry).motion == 1)
|
||||
|
||||
extern const location_t locations[];
|
||||
extern const object_t objects[];
|
||||
extern const char* arbitrary_messages[];
|
||||
|
@ -162,4 +164,4 @@ enum action_refs {{
|
|||
|
||||
{state_definitions}
|
||||
|
||||
#endif /* end DUNGEON_H */
|
||||
#endif /* end DUNGEON_H */
|
||||
|
|
176
tests/Makefile
176
tests/Makefile
|
@ -1,4 +1,7 @@
|
|||
# Test-suite makefile for reposurgeon
|
||||
# Test-suite makefile for open-adventure
|
||||
|
||||
# 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
|
||||
# scripts from parent directory. Note that using $PWD seems to fail
|
||||
|
@ -13,26 +16,28 @@ advent?=advent
|
|||
# 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 coverage clean testlist listcheck savegames buildregress
|
||||
.PHONY: savecheck regress
|
||||
.PHONY: check clean testlist listcheck savegames savecheck coverage
|
||||
.PHONY: buildchecks multifile-regress tap count
|
||||
|
||||
check: savecheck regress
|
||||
@echo "=== No diff output is good news."
|
||||
@-advent -x 2>/dev/null # Get usage message into coverage tests
|
||||
@-advent -l /dev/null <pitfall.log >/dev/null
|
||||
|
||||
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
|
||||
check: savecheck
|
||||
@make tap | tapview
|
||||
@-advent -x 2>/dev/null || exit 0 # Get usage message into coverage tests
|
||||
|
||||
.SUFFIXES: .chk
|
||||
|
||||
clean:
|
||||
rm -fr *~ adventure.text *.adv scratch.tmp
|
||||
rm -fr *~ *.adv scratch.tmp *.ochk advent430 adventure.data
|
||||
|
||||
# Show summary lines for all tests.
|
||||
testlist:
|
||||
|
@ -43,59 +48,130 @@ listcheck:
|
|||
done
|
||||
|
||||
# Generate bogus savegames.
|
||||
savegames:
|
||||
@$(ECHO) "cheat: Generate save file with -900 deaths"
|
||||
cheat_numdie.adv:
|
||||
@$(PARDIR)/cheat -d -900 -o cheat_numdie.adv > /tmp/cheat_numdie
|
||||
@$(ECHO) "cheat: Generate save file with -1000 deaths"
|
||||
cheat_numdie1000.adv:
|
||||
@$(PARDIR)/cheat -d -1000 -o cheat_numdie1000.adv > /tmp/cheat_numdie1000
|
||||
@$(ECHO) "cheat: Generate save file with version -1337"
|
||||
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
|
||||
@$(ECHO) "cheat: Generate save file 1000 saves"
|
||||
thousand_saves.adv:
|
||||
@$(PARDIR)/cheat -s -1000 -o thousand_saves.adv > /tmp/cheat_1000saves
|
||||
@$(ECHO) "cheat: Generate save file 1000 turns"
|
||||
@$(PARDIR)/cheat -t -1000 -o thousand_saves.adv > /tmp/cheat_1000turns
|
||||
@$(ECHO) "cheat: Generate save file 1000 turns"
|
||||
@$(PARDIR)/cheat -l -1000 -o thousand_lamp.adv > /tmp/cheat_1000lamp
|
||||
@rm -f /tmp/cheat*
|
||||
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
|
||||
buildregress: savegames
|
||||
buildchecks: savegames
|
||||
$(PARDIR)/cheat -s -1000 -o thousand_saves.adv > /tmp/regress1000saves
|
||||
@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
|
||||
|
||||
savecheck: savegames
|
||||
@$(ECHO) "TEST cheat: Bogus option for save file generation"
|
||||
@$(PARDIR)/cheat -QqQ 2> /tmp/coverage_cheat_batopt | true
|
||||
@$(ECHO) "TEST cheat: No save file specified"
|
||||
@$(PARDIR)/cheat 2>/dev/null | true
|
||||
@$(ECHO) "TEST cheat: Fail to save because we omit -o"
|
||||
@$(PARDIR)/cheat -d 1 2> /tmp/coverage_cheat_nooutput | true
|
||||
@$(ECHO) "TEST cheat: Fail to save to invalid path"
|
||||
@$(PARDIR)/cheat -o / 2> /tmp/coverage_cheat_badoutput | true
|
||||
@$(ECHO) "TEST advent: Start with invalid file with -r"
|
||||
@advent -r /badfilename < pitfall.log > /tmp/coverage_advent_readfail 2>&1 || exit 1
|
||||
@$(ECHO) "TEST advent: Start with invalid file with -l"
|
||||
@advent -l / < pitfall.log > /tmp/coverage_advent_logfail 2>&1 || exit 1
|
||||
@$(ECHO) "TEST advent: Test -r with valid input"
|
||||
@advent -r thousand_saves.adv < pitfall.log > /tmp/coverage_advent_readfail 2>&1 || exit 1
|
||||
@rm -f /tmp/coverage*
|
||||
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")
|
||||
|
||||
# General regression testing of commands and output; look at the *.log and
|
||||
# corresponding *.chk files to see which tests this runs.
|
||||
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 \
|
||||
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; \
|
||||
rm -f scratch.tmp /tmp/regress$$$$
|
||||
echo 1..$(words $(shell ls *.log))) | $(TAPFILTER)
|
||||
@rm *.ochk *-new advent430 adventure.data
|
||||
|
||||
# List all NOCOMPARE tests.
|
||||
residuals:
|
||||
@grep -n NOCOMPARE *.log
|
||||
|
||||
# end
|
||||
|
|
17
tests/README
17
tests/README
|
@ -17,27 +17,20 @@ 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 regress".
|
||||
To run the tests, "make check".
|
||||
|
||||
To remake the check files, "make buildregress".
|
||||
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 -s and
|
||||
paste it to the advent command log from the clipboard. If you don't
|
||||
use -s to disable advanced ediiting, the code used for that will consume
|
||||
the first line of the paste and discare the rest. This is almost
|
||||
certainly not what you want.
|
||||
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, have a look at our test coverage
|
||||
report:
|
||||
To see where we can use more tests, "make coverage".
|
||||
|
||||
http://esr.gitlab.io/open-adventure/coverage/
|
||||
|
||||
Improvements in test coverage are always welcome.
|
||||
|
||||
// end
|
||||
|
||||
|
|
|
@ -316,7 +316,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill dragon
|
||||
|
||||
|
@ -329,7 +329,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -487,7 +487,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -532,7 +532,7 @@ There is an emerald here the size of a plover's egg!
|
|||
|
||||
You're in the dark-room. A corridor leading south is the only exit.
|
||||
|
||||
A massive stone tablet imbedded in the wall reads:
|
||||
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!
|
||||
|
@ -808,7 +808,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -931,6 +931,10 @@ You're at west end of Twopit Room.
|
|||
|
||||
The top of a 12-foot-tall beanstalk is poking out of the west pit.
|
||||
|
||||
> eat plant
|
||||
|
||||
Don't be ridiculous!
|
||||
|
||||
> w
|
||||
|
||||
You're in Slab Room.
|
||||
|
@ -1081,6 +1085,10 @@ You're in west pit.
|
|||
|
||||
There is a gigantic beanstalk stretching all the way up to the hole.
|
||||
|
||||
> eat plant
|
||||
|
||||
Don't be ridiculous!
|
||||
|
||||
> u
|
||||
|
||||
You're at west end of Twopit Room.
|
||||
|
@ -1278,7 +1286,7 @@ OK
|
|||
|
||||
There is a threatening little dwarf in the room with you!
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1322,7 +1330,7 @@ going west. There is also a large room above. The air is damp here.
|
|||
> n
|
||||
|
||||
You're in a large room carved out of sedimentary rock. The floor and
|
||||
walls are littered with bits of shells imbedded in the stone. A
|
||||
walls are littered with bits of shells embedded in the stone. A
|
||||
shallow passage proceeds downward, and a somewhat steeper one leads
|
||||
up. A low hands and knees passage enters from the south.
|
||||
|
||||
|
@ -1375,7 +1383,7 @@ There is an enormous ruby here!
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -1600,7 +1608,7 @@ You are inside a barren room. The center of the room is completely
|
|||
empty except for some dust. Marks in the dust lead away toward the
|
||||
far end of the room. The only exit is the way you came in.
|
||||
|
||||
There is a ferocious cave bear eying you from the far end of the room!
|
||||
There is a ferocious cave bear eyeing you from the far end of the room!
|
||||
|
||||
The bear is locked to the wall with a golden chain!
|
||||
|
||||
|
@ -1617,14 +1625,14 @@ You are inside a barren room. The center of the room is completely
|
|||
empty except for some dust. Marks in the dust lead away toward the
|
||||
far end of the room. The only exit is the way you came in.
|
||||
|
||||
There is a ferocious cave bear eying you from the far end of the room!
|
||||
There is a ferocious cave bear eyeing you from the far end of the room!
|
||||
|
||||
There is a little axe lying beside the bear.
|
||||
|
||||
The bear is locked to the wall with a golden chain!
|
||||
|
||||
|
||||
You scored 251 out of a possible 430, using 269 turns.
|
||||
>
|
||||
You scored 251 out of a possible 430, using 271 turns.
|
||||
|
||||
You have reached "Junior Master" status.
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
@ -150,6 +152,7 @@ s
|
|||
d
|
||||
water plant
|
||||
u
|
||||
eat plant
|
||||
w
|
||||
u
|
||||
reservoir
|
||||
|
@ -178,6 +181,7 @@ d
|
|||
s
|
||||
d
|
||||
water plant
|
||||
eat plant
|
||||
u
|
||||
drop appendage
|
||||
e
|
||||
|
|
|
@ -308,7 +308,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> throw axe
|
||||
|
||||
|
@ -320,7 +320,7 @@ There is a little axe here.
|
|||
|
||||
A huge green fierce dragon bars the way!
|
||||
|
||||
The dragon is sprawled out on a persian rug!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> take axe
|
||||
|
||||
|
@ -337,7 +337,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -652,7 +652,7 @@ 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.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
|
22
tests/badmagic.chk
Normal file
22
tests/badmagic.chk
Normal file
|
@ -0,0 +1,22 @@
|
|||
|
||||
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.
|
8
tests/badmagic.log
Normal file
8
tests/badmagic.log
Normal file
|
@ -0,0 +1,8 @@
|
|||
## 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
|
|
@ -255,7 +255,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> drop bird
|
||||
|
||||
|
@ -286,7 +286,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill dragon
|
||||
|
||||
|
@ -299,7 +299,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -307,7 +307,7 @@ The blood-specked body of a huge green dead dragon lies to one side.
|
|||
|
||||
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.
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
## 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
|
||||
|
|
|
@ -316,7 +316,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill dragon
|
||||
|
||||
|
@ -329,7 +329,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -487,7 +487,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -532,7 +532,7 @@ There is an emerald here the size of a plover's egg!
|
|||
|
||||
You're in the dark-room. A corridor leading south is the only exit.
|
||||
|
||||
A massive stone tablet imbedded in the wall reads:
|
||||
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!
|
||||
|
@ -808,7 +808,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -1284,7 +1284,7 @@ It is beyond your power to do that.
|
|||
|
||||
There is a threatening little dwarf in the room with you!
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1324,7 +1324,7 @@ going west. There is also a large room above. The air is damp here.
|
|||
> n
|
||||
|
||||
You're in a large room carved out of sedimentary rock. The floor and
|
||||
walls are littered with bits of shells imbedded in the stone. A
|
||||
walls are littered with bits of shells embedded in the stone. A
|
||||
shallow passage proceeds downward, and a somewhat steeper one leads
|
||||
up. A low hands and knees passage enters from the south.
|
||||
|
||||
|
@ -1334,12 +1334,20 @@ There is an enormous clam here with its shell tightly closed.
|
|||
|
||||
OK
|
||||
|
||||
> unlock clam
|
||||
|
||||
I advise you to put down the clam before opening it. >STRAIN!<
|
||||
|
||||
> s
|
||||
|
||||
You can't fit this five-foot clam through that little passage!
|
||||
|
||||
You're in Shell Room.
|
||||
|
||||
> open clam
|
||||
|
||||
I advise you to put down the clam before opening it. >STRAIN!<
|
||||
|
||||
> drop clam
|
||||
|
||||
OK
|
||||
|
@ -1350,6 +1358,10 @@ A glistening pearl falls out of the clam and rolls away. Goodness,
|
|||
this must really be an oyster. (I never was very good at identifying
|
||||
bivalves.) Whatever it is, it has now snapped shut again.
|
||||
|
||||
> read oyster
|
||||
|
||||
I'm afraid I don't understand.
|
||||
|
||||
> take oyster
|
||||
|
||||
OK
|
||||
|
@ -1407,7 +1419,7 @@ There is an enormous ruby here!
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -1632,7 +1644,7 @@ You are inside a barren room. The center of the room is completely
|
|||
empty except for some dust. Marks in the dust lead away toward the
|
||||
far end of the room. The only exit is the way you came in.
|
||||
|
||||
There is a ferocious cave bear eying you from the far end of the room!
|
||||
There is a ferocious cave bear eyeing you from the far end of the room!
|
||||
|
||||
The bear is locked to the wall with a golden chain!
|
||||
|
||||
|
@ -1663,7 +1675,7 @@ OK
|
|||
|
||||
You're in Barren Room.
|
||||
|
||||
There is a ferocious cave bear eying you from the far end of the room!
|
||||
There is a ferocious cave bear eyeing you from the far end of the room!
|
||||
|
||||
The bear is locked to the wall with a golden chain!
|
||||
|
||||
|
@ -1788,748 +1800,12 @@ 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?
|
||||
|
||||
> yes
|
||||
|
||||
All right. But don't blame me if something goes wr......
|
||||
--- POOF!! ---
|
||||
You are engulfed in a cloud of orange smoke. Coughing and gasping,
|
||||
you emerge from the smoke and find....
|
||||
|
||||
You're inside building.
|
||||
|
||||
There is a richly-carved ebony statuette here!
|
||||
|
||||
There is an emerald here the size of a plover's egg!
|
||||
|
||||
There is a jewel-encrusted trident here!
|
||||
|
||||
There is a platinum pyramid here, 8 inches on a side!
|
||||
|
||||
There are diamonds here!
|
||||
|
||||
There is an enormous ruby here!
|
||||
|
||||
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!
|
||||
|
||||
> inven
|
||||
|
||||
You're not carrying anything.
|
||||
|
||||
> out
|
||||
|
||||
You're in front of building.
|
||||
|
||||
There is a shiny brass lamp nearby.
|
||||
|
||||
> take lamp
|
||||
> n
|
||||
|
||||
OK
|
||||
|
||||
> light lamp
|
||||
|
||||
Your lamp is now on.
|
||||
|
||||
> in
|
||||
|
||||
You're inside building.
|
||||
|
||||
There is a richly-carved ebony statuette here!
|
||||
|
||||
There is an emerald here the size of a plover's egg!
|
||||
|
||||
There is a jewel-encrusted trident here!
|
||||
|
||||
There is a platinum pyramid here, 8 inches on a side!
|
||||
|
||||
There are diamonds here!
|
||||
|
||||
There is an enormous ruby here!
|
||||
|
||||
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!
|
||||
|
||||
> plugh
|
||||
|
||||
>>Foof!<<
|
||||
|
||||
You're at "Y2".
|
||||
|
||||
> s
|
||||
|
||||
You're in n/s passage above e/w passage.
|
||||
|
||||
> d
|
||||
|
||||
You're in dirty passage.
|
||||
|
||||
> bedquilt
|
||||
|
||||
You're in Bedquilt.
|
||||
|
||||
> n
|
||||
|
||||
You're in large low room.
|
||||
|
||||
> sw
|
||||
|
||||
You're in sloping corridor.
|
||||
|
||||
> up
|
||||
|
||||
You're on sw side of chasm.
|
||||
|
||||
There is a little axe here.
|
||||
|
||||
There are many coins here!
|
||||
|
||||
Off to one side lies a glistening pearl!
|
||||
|
||||
There is a golden chain lying in a heap on the floor!
|
||||
|
||||
The wreckage of a bridge (and a dead bear) can be seen at the bottom
|
||||
of the chasm.
|
||||
|
||||
The troll is nowhere to be seen.
|
||||
|
||||
> over
|
||||
|
||||
There is no longer any way across the chasm.
|
||||
|
||||
You're on sw side of chasm.
|
||||
|
||||
There is a little axe here.
|
||||
|
||||
There are many coins here!
|
||||
|
||||
Off to one side lies a glistening pearl!
|
||||
|
||||
There is a golden chain lying in a heap on the floor!
|
||||
|
||||
The wreckage of a bridge (and a dead bear) can be seen at the bottom
|
||||
of the chasm.
|
||||
|
||||
The troll is nowhere to be seen.
|
||||
|
||||
> feed bear
|
||||
|
||||
Don't be ridiculous!
|
||||
|
||||
> attack bear
|
||||
|
||||
For crying out loud, the poor thing is already dead!
|
||||
|
||||
> take coins
|
||||
|
||||
OK
|
||||
|
||||
> take axe
|
||||
|
||||
OK
|
||||
|
||||
> sw
|
||||
|
||||
You're in sloping corridor.
|
||||
|
||||
> d
|
||||
|
||||
You're in large low room.
|
||||
|
||||
> se
|
||||
|
||||
You're in Oriental Room.
|
||||
|
||||
The floor is littered with worthless shards of pottery.
|
||||
|
||||
> se
|
||||
|
||||
You're in Swiss Cheese Room.
|
||||
|
||||
> ne
|
||||
|
||||
You are in Bedquilt, a long east/west passage with holes everywhere.
|
||||
To explore at random select north, south, up, or down.
|
||||
|
||||
> e
|
||||
|
||||
You're at complex junction.
|
||||
|
||||
> up
|
||||
|
||||
You're in dusty rock room.
|
||||
|
||||
> e
|
||||
|
||||
You're in dirty passage.
|
||||
|
||||
> up
|
||||
|
||||
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.
|
||||
|
||||
> up
|
||||
|
||||
You're in Hall of Mists.
|
||||
|
||||
Rough stone steps lead up the dome.
|
||||
|
||||
> 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.
|
||||
|
||||
> take rod
|
||||
|
||||
OK
|
||||
|
||||
> wave rod
|
||||
|
||||
The crystal bridge has vanished!
|
||||
|
||||
> across
|
||||
|
||||
There is no way across the fissure.
|
||||
|
||||
You're on east bank of fissure.
|
||||
|
||||
> wave rod
|
||||
|
||||
A crystal bridge now spans the fissure.
|
||||
|
||||
> across
|
||||
|
||||
You're on west bank of fissure.
|
||||
|
||||
A crystal bridge spans the fissure.
|
||||
|
||||
> 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.
|
||||
|
||||
> s
|
||||
|
||||
You are in a maze of twisting little passages, all different.
|
||||
|
||||
> sw
|
||||
|
||||
You are in a twisting little maze of passages, all different.
|
||||
|
||||
> se
|
||||
|
||||
You are in a twisting maze of little passages, all different.
|
||||
|
||||
> s
|
||||
|
||||
You are in a little maze of twisting passages, all different.
|
||||
|
||||
> s
|
||||
|
||||
Dead end
|
||||
|
||||
There is a massive vending machine here, swung back to reveal a
|
||||
southward passage.
|
||||
|
||||
> drop coins
|
||||
|
||||
There are fresh batteries here.
|
||||
|
||||
> look
|
||||
|
||||
Sorry, but I am not allowed to give more detail. I will repeat the
|
||||
long description of your location.
|
||||
|
||||
Dead end
|
||||
|
||||
There are fresh batteries 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.
|
||||
|
||||
> z
|
||||
|
||||
OK
|
||||
|
||||
> z
|
||||
|
||||
OK
|
||||
|
||||
> z
|
||||
|
||||
Your lamp is getting dim. You'd best go back for those batteries.
|
||||
|
||||
OK
|
||||
|
||||
> z
|
||||
|
||||
OK
|
||||
|
||||
> s
|
||||
|
||||
Tsk! A wizard wouldn't have to take 350 turns. This is going to cost
|
||||
you a couple of points.
|
||||
|
||||
Dead end
|
||||
|
||||
There are fresh batteries here.
|
||||
|
||||
There is a massive vending machine here, swung back to reveal a
|
||||
southward passage.
|
||||
|
||||
> take batteries
|
||||
|
||||
Your lamp is getting dim. I'm taking the liberty of replacing the
|
||||
batteries.
|
||||
|
||||
OK
|
||||
|
||||
> n
|
||||
|
||||
You are in a little maze of twisting passages, all different.
|
||||
|
||||
> back
|
||||
|
||||
Sorry, but the path twisted and turned so much that I can't figure
|
||||
out which way to go to get back.
|
||||
|
||||
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.
|
||||
|
||||
> drink
|
||||
|
||||
Drink what?
|
||||
|
||||
> e
|
||||
|
||||
You're at east end of long hall.
|
||||
|
||||
> e
|
||||
|
||||
You're at west end of Hall of Mists.
|
||||
|
||||
> n
|
||||
|
||||
You have crawled through a very low wide passage parallel to and north
|
||||
of the Hall of Mists.
|
||||
|
||||
You're on west bank of fissure.
|
||||
|
||||
A crystal bridge spans the fissure.
|
||||
|
||||
> w
|
||||
|
||||
You're at west end of Hall of Mists.
|
||||
|
||||
> w
|
||||
|
||||
You're at east end of long hall.
|
||||
|
||||
> n
|
||||
|
||||
You are at a crossover of a high n/s passage and a low e/w one.
|
||||
|
||||
> e
|
||||
|
||||
You're in the west side chamber.
|
||||
|
||||
> d
|
||||
|
||||
There is no way to go that direction.
|
||||
|
||||
You're in the west side chamber.
|
||||
|
||||
> e
|
||||
|
||||
You're in Hall of Mt King.
|
||||
|
||||
> u
|
||||
|
||||
There is a threatening little dwarf in the room with you!
|
||||
|
||||
You're in Hall of Mists.
|
||||
|
||||
Rough stone steps lead up the dome.
|
||||
|
||||
> throw axe
|
||||
|
||||
You killed a little dwarf.
|
||||
|
||||
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.
|
||||
|
||||
There is a little axe here.
|
||||
|
||||
Rough stone steps lead up the dome.
|
||||
|
||||
> d
|
||||
|
||||
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.
|
||||
|
||||
> e
|
||||
|
||||
You are on the brink of a small clean climbable pit. A crawl leads
|
||||
west.
|
||||
|
||||
> d
|
||||
|
||||
You are in the bottom of a small pit with a little stream, which
|
||||
enters and exits through tiny slits.
|
||||
|
||||
> listen
|
||||
|
||||
The stream is gurgling placidly.
|
||||
|
||||
> u
|
||||
|
||||
You're at brink of small pit.
|
||||
|
||||
> w
|
||||
|
||||
You're in dirty passage.
|
||||
|
||||
> bedquilt
|
||||
|
||||
You're in Bedquilt.
|
||||
|
||||
> z
|
||||
|
||||
OK
|
||||
|
||||
> z
|
||||
|
||||
OK
|
||||
|
||||
> z
|
||||
|
||||
OK
|
||||
|
||||
> n
|
||||
|
||||
You have crawled around in some little holes and wound up back in the
|
||||
main passage.
|
||||
|
||||
You're in Bedquilt.
|
||||
|
||||
> n
|
||||
|
||||
You have crawled around in some little holes and wound up back in the
|
||||
main passage.
|
||||
|
||||
You're in Bedquilt.
|
||||
|
||||
> 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 secret canyon at a junction of three canyons, bearing
|
||||
north, south, and se. The north one is as tall as the other two
|
||||
combined.
|
||||
|
||||
> w
|
||||
|
||||
There is no way to go that direction.
|
||||
|
||||
You're at junction of three secret canyons.
|
||||
|
||||
> n
|
||||
|
||||
You're at a low window overlooking a huge pit, which extends up out of
|
||||
sight. A floor is indistinctly visible over 50 feet below. Traces of
|
||||
white mist cover the floor of the pit, becoming thicker to the left.
|
||||
Marks in the dust around the window would seem to indicate that
|
||||
someone has been here recently. Directly across the pit from you and
|
||||
25 feet away there is a similar window looking into a lighted room. A
|
||||
shadowy figure can be seen there peering back at you.
|
||||
|
||||
The shadowy figure seems to be trying to attract your attention.
|
||||
|
||||
> w
|
||||
|
||||
You're at junction of three secret canyons.
|
||||
|
||||
> s
|
||||
|
||||
You are in a secret n/s canyon above a sizable passage.
|
||||
|
||||
> s
|
||||
|
||||
A large stalactite extends from the roof and almost reaches the floor
|
||||
below. You could climb down it, and jump from it to the floor, but
|
||||
having done so you would be unable to reach it to climb back up.
|
||||
|
||||
> n
|
||||
|
||||
You are in a secret n/s canyon above a sizable passage.
|
||||
|
||||
> s
|
||||
|
||||
There are faint rustling noises from the darkness behind you.
|
||||
|
||||
You're at top of stalactite.
|
||||
|
||||
> n
|
||||
|
||||
You are in a secret n/s canyon above a sizable passage.
|
||||
|
||||
> n
|
||||
|
||||
You're at junction of three secret canyons.
|
||||
|
||||
> n
|
||||
|
||||
You're at window on pit.
|
||||
|
||||
The shadowy figure seems to be trying to attract your attention.
|
||||
|
||||
> jump
|
||||
|
||||
You are at the bottom of the pit with a broken neck.
|
||||
|
||||
You clumsy oaf, you've done it again! I don't know how long I can
|
||||
keep this up. Do you want me to try reincarnating you again?
|
||||
|
||||
> y
|
||||
|
||||
Okay, now where did I put my orange smoke?.... >POOF!<
|
||||
Everything disappears in a dense cloud of orange smoke.
|
||||
|
||||
You're inside building.
|
||||
|
||||
There is a richly-carved ebony statuette here!
|
||||
|
||||
There is an emerald here the size of a plover's egg!
|
||||
|
||||
There is a jewel-encrusted trident here!
|
||||
|
||||
There is a platinum pyramid here, 8 inches on a side!
|
||||
|
||||
There are diamonds here!
|
||||
|
||||
There is an enormous ruby here!
|
||||
|
||||
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!
|
||||
|
||||
> out
|
||||
|
||||
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.
|
||||
|
||||
There is a shiny brass lamp nearby.
|
||||
|
||||
> take lamp
|
||||
|
||||
OK
|
||||
|
||||
> in
|
||||
|
||||
You're inside building.
|
||||
|
||||
There is a richly-carved ebony statuette here!
|
||||
|
||||
There is an emerald here the size of a plover's egg!
|
||||
|
||||
There is a jewel-encrusted trident here!
|
||||
|
||||
There is a platinum pyramid here, 8 inches on a side!
|
||||
|
||||
There are diamonds here!
|
||||
|
||||
There is an enormous ruby here!
|
||||
|
||||
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!
|
||||
|
||||
> downstream
|
||||
|
||||
The stream flows out through a pair of 1 foot diameter sewer pipes.
|
||||
It would be advisable to use the exit.
|
||||
|
||||
You are inside a building, a well house for a large spring.
|
||||
|
||||
There is a richly-carved ebony statuette here!
|
||||
|
||||
There is an emerald here the size of a plover's egg!
|
||||
|
||||
There is a jewel-encrusted trident here!
|
||||
|
||||
There is a platinum pyramid here, 8 inches on a side!
|
||||
|
||||
There are diamonds here!
|
||||
|
||||
There is an enormous ruby here!
|
||||
|
||||
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!
|
||||
|
||||
> plugh
|
||||
|
||||
>>Foof!<<
|
||||
|
||||
It is now pitch dark. If you proceed you will likely fall into a pit.
|
||||
|
||||
> on lamp
|
||||
|
||||
Your lamp is now on.
|
||||
|
||||
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.
|
||||
|
||||
> w
|
||||
|
||||
You're at a low window overlooking a huge pit, which extends up out of
|
||||
sight. A floor is indistinctly visible over 50 feet below. Traces of
|
||||
white mist cover the floor of the pit, becoming thicker to the right.
|
||||
Marks in the dust around the window would seem to indicate that
|
||||
someone has been here recently. Directly across the pit from you and
|
||||
25 feet away there is a similar window looking into a lighted room. A
|
||||
shadowy figure can be seen there peering back at you.
|
||||
|
||||
The shadowy figure seems to be trying to attract your attention.
|
||||
|
||||
> e
|
||||
|
||||
You're at "Y2".
|
||||
|
||||
> s
|
||||
|
||||
You're in n/s passage above e/w passage.
|
||||
|
||||
> s
|
||||
|
||||
You're in Hall of Mt King.
|
||||
|
||||
> e
|
||||
|
||||
You're in Hall of Mists.
|
||||
|
||||
There is a little axe here.
|
||||
|
||||
Rough stone steps lead up the dome.
|
||||
|
||||
> take axe
|
||||
|
||||
OK
|
||||
|
||||
> listen
|
||||
|
||||
The wind whistles coldly past your ears.
|
||||
|
||||
> score
|
||||
|
||||
You have garnered 207 out of a possible 430 points, using 410 turns.
|
||||
|
||||
> inven
|
||||
|
||||
You are currently holding the following:
|
||||
Brass lantern
|
||||
Dwarf's axe
|
||||
|
||||
> waste 2443
|
||||
|
||||
Game limit is now 30
|
||||
|
||||
You're in Hall of Mists.
|
||||
|
||||
Rough stone steps lead up the dome.
|
||||
|
||||
> z
|
||||
|
||||
Your lamp is getting dim, and you're out of spare batteries. You'd
|
||||
best start wrapping this up.
|
||||
|
||||
OK
|
||||
|
||||
|
||||
You scored 207 out of a possible 430, using 413 turns.
|
||||
You scored 223 out of a possible 430, using 303 turns.
|
||||
|
||||
You may now consider yourself a "Seasoned Adventurer".
|
||||
|
||||
To achieve the next higher rating, you need 44 more points.
|
||||
To achieve the next higher rating, you need 28 more points.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
@ -226,9 +228,12 @@ 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
|
||||
|
@ -307,141 +312,5 @@ sw
|
|||
free bear
|
||||
take bear
|
||||
sw
|
||||
yes
|
||||
inven
|
||||
out
|
||||
take lamp
|
||||
light lamp
|
||||
in
|
||||
plugh
|
||||
s
|
||||
d
|
||||
bedquilt
|
||||
n
|
||||
sw
|
||||
up
|
||||
over
|
||||
feed bear
|
||||
attack bear
|
||||
# We'll need these when the game times out
|
||||
take coins
|
||||
take axe
|
||||
# Back to fissure to vanish the bridge and then test OVER
|
||||
sw
|
||||
d
|
||||
se
|
||||
se
|
||||
ne
|
||||
e
|
||||
up
|
||||
e
|
||||
up
|
||||
s
|
||||
up
|
||||
w
|
||||
take rod
|
||||
wave rod
|
||||
across
|
||||
# Next, buy batteries but don't take them.
|
||||
wave rod
|
||||
across
|
||||
w
|
||||
w
|
||||
w
|
||||
s
|
||||
s
|
||||
sw
|
||||
se
|
||||
s
|
||||
s
|
||||
drop coins
|
||||
look
|
||||
n
|
||||
z
|
||||
z
|
||||
z
|
||||
z
|
||||
# Battery warning happens here.
|
||||
s
|
||||
take batteries
|
||||
# We now have 2500 more turns of life. Into the maze...
|
||||
n
|
||||
# Show that trying to back up in the maze fails
|
||||
back
|
||||
n
|
||||
nw
|
||||
d
|
||||
# Out of maze. Drink where nothing is eligible.
|
||||
drink
|
||||
e
|
||||
e
|
||||
# PARALLEL1 coverage
|
||||
n
|
||||
# If we go to hall of mists we'll meet a killer dwarf with the drop on us
|
||||
#e
|
||||
#e
|
||||
w
|
||||
w
|
||||
n
|
||||
e
|
||||
d
|
||||
e
|
||||
u
|
||||
throw axe
|
||||
d
|
||||
n
|
||||
d
|
||||
# Coverage of LOC_SMALLPIT and LOC_SMALLPITBRINK
|
||||
e
|
||||
d
|
||||
listen
|
||||
u
|
||||
w
|
||||
# Coverage of LOC_THREEJUNCTION, LOC_WINDOW2, LOC_SECRET2, LOC_TOPSTALACTITE,
|
||||
# LOC_NECKBROKE. Only accessible via stalactite from big maze or by random
|
||||
# exit from Bedquilt.
|
||||
bedquilt
|
||||
z
|
||||
z
|
||||
z
|
||||
n
|
||||
n
|
||||
n
|
||||
n
|
||||
# In secret canyon
|
||||
w
|
||||
n
|
||||
w
|
||||
s
|
||||
# LOC_TOPSTALACTITE
|
||||
s
|
||||
n
|
||||
s
|
||||
n
|
||||
n
|
||||
n
|
||||
jump
|
||||
y
|
||||
# Reincarnation, cover LOC_SEWER
|
||||
out
|
||||
take lamp
|
||||
in
|
||||
downstream
|
||||
plugh
|
||||
on lamp
|
||||
# Cover WINDOW1
|
||||
w
|
||||
e
|
||||
# Retrieve axe
|
||||
s
|
||||
s
|
||||
e
|
||||
take axe
|
||||
listen
|
||||
# At Hall of Mists
|
||||
score
|
||||
inven
|
||||
# Timewarp forward to test exhaustion of replacement batteries
|
||||
waste 2443
|
||||
z
|
||||
# MISSING_BATTERIES is uttered
|
||||
quit
|
||||
|
|
|
@ -316,7 +316,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill dragon
|
||||
|
||||
|
@ -329,7 +329,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -487,7 +487,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -532,7 +532,7 @@ There is an emerald here the size of a plover's egg!
|
|||
|
||||
You're in the dark-room. A corridor leading south is the only exit.
|
||||
|
||||
A massive stone tablet imbedded in the wall reads:
|
||||
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!
|
||||
|
@ -808,7 +808,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -1278,7 +1278,7 @@ OK
|
|||
|
||||
There is a threatening little dwarf in the room with you!
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1326,7 +1326,7 @@ going west. There is also a large room above. The air is damp here.
|
|||
> n
|
||||
|
||||
You're in a large room carved out of sedimentary rock. The floor and
|
||||
walls are littered with bits of shells imbedded in the stone. A
|
||||
walls are littered with bits of shells embedded in the stone. A
|
||||
shallow passage proceeds downward, and a somewhat steeper one leads
|
||||
up. A low hands and knees passage enters from the south.
|
||||
|
||||
|
@ -1379,7 +1379,7 @@ There is an enormous ruby here!
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -1393,6 +1393,10 @@ There are some keys on the ground here.
|
|||
|
||||
There is food here.
|
||||
|
||||
> score
|
||||
|
||||
You have garnered 191 out of a possible 430 points, using 229 turns.
|
||||
|
||||
> drop pillow
|
||||
|
||||
OK
|
||||
|
@ -1401,6 +1405,10 @@ OK
|
|||
|
||||
The vase is now resting, delicately, on a velvet pillow.
|
||||
|
||||
> score
|
||||
|
||||
You have garnered 205 out of a possible 430 points, using 232 turns.
|
||||
|
||||
> drop trident
|
||||
|
||||
OK
|
||||
|
@ -1606,7 +1614,7 @@ You are inside a barren room. The center of the room is completely
|
|||
empty except for some dust. Marks in the dust lead away toward the
|
||||
far end of the room. The only exit is the way you came in.
|
||||
|
||||
There is a ferocious cave bear eying you from the far end of the room!
|
||||
There is a ferocious cave bear eyeing you from the far end of the room!
|
||||
|
||||
The bear is locked to the wall with a golden chain!
|
||||
|
||||
|
@ -1762,7 +1770,7 @@ There is a huge beanstalk growing out of the west pit up to the hole.
|
|||
|
||||
> e
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1906,7 +1914,7 @@ There is an enormous ruby here!
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -2009,11 +2017,11 @@ OK
|
|||
|
||||
The gem fits easily into the cavity.
|
||||
|
||||
The persian rug stiffens and rises a foot or so off the ground.
|
||||
The Persian rug stiffens and rises a foot or so off the ground.
|
||||
|
||||
> fly rug
|
||||
|
||||
You board the persian rug, which promptly whisks you across the chasm.
|
||||
You board the Persian rug, which promptly whisks you across the chasm.
|
||||
You have time for a fleeting glimpse of a two thousand foot drop to a
|
||||
mighty river; then you find yourself on the other side.
|
||||
|
||||
|
@ -2021,7 +2029,7 @@ You are on a small ledge on one face of a sheer cliff. There are no
|
|||
paths away from the ledge. Across the chasm is a small clearing
|
||||
surrounded by forest.
|
||||
|
||||
There is a persian rug here, hovering in mid-air!
|
||||
There is a Persian rug here, hovering in mid-air!
|
||||
|
||||
A brilliant blue star sapphire is here!
|
||||
|
||||
|
@ -2037,7 +2045,7 @@ You're at cliff.
|
|||
|
||||
There is an emerald resting in a small cavity in the rock!
|
||||
|
||||
There is a persian rug here, hovering in mid-air!
|
||||
There is a Persian rug here, hovering in mid-air!
|
||||
|
||||
> take emerald
|
||||
|
||||
|
@ -2047,7 +2055,7 @@ OK
|
|||
|
||||
The gem fits easily into the cavity.
|
||||
|
||||
The persian rug settles gently to the ground.
|
||||
The Persian rug settles gently to the ground.
|
||||
|
||||
> take rug
|
||||
|
||||
|
@ -2115,6 +2123,9 @@ There are many coins here!
|
|||
|
||||
> drop ruby
|
||||
|
||||
Tsk! A wizard wouldn't have to take 350 turns. This is going to cost
|
||||
you a couple of points.
|
||||
|
||||
OK
|
||||
|
||||
> drop sapphire
|
||||
|
@ -2123,9 +2134,6 @@ OK
|
|||
|
||||
> drop amber
|
||||
|
||||
Tsk! A wizard wouldn't have to take 350 turns. This is going to cost
|
||||
you a couple of points.
|
||||
|
||||
OK
|
||||
|
||||
> drop rug
|
||||
|
@ -2139,7 +2147,7 @@ long description of your location.
|
|||
|
||||
You are inside a building, a well house for a large spring.
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a rare amber gemstone here!
|
||||
|
||||
|
@ -2329,7 +2337,7 @@ It is now pitch dark. If you proceed you will likely fall into a pit.
|
|||
|
||||
You're inside building.
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a rare amber gemstone here!
|
||||
|
||||
|
@ -2922,7 +2930,7 @@ OK
|
|||
|
||||
> take bird
|
||||
|
||||
OK
|
||||
You are already carrying it!
|
||||
|
||||
> free bird
|
||||
|
||||
|
@ -2933,7 +2941,7 @@ The resulting ruckus has awakened the dwarves. There are now several
|
|||
threatening little dwarves in the room with you! Most of them throw
|
||||
knives at you! All of them get you!
|
||||
|
||||
You scored 393 out of a possible 430, using 466 turns.
|
||||
You scored 393 out of a possible 430, using 468 turns.
|
||||
|
||||
Your score puts you in Master Adventurer Class B.
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
@ -231,8 +233,12 @@ 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
|
||||
|
|
|
@ -456,7 +456,7 @@ attack. He seems almost amused by your puny effort.
|
|||
|
||||
OK
|
||||
|
||||
|
||||
>
|
||||
You scored 61 out of a possible 430, using 81 turns.
|
||||
|
||||
Your score qualifies you as a novice class adventurer.
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
## 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
|
||||
|
|
|
@ -266,7 +266,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill drago
|
||||
|
||||
|
@ -279,7 +279,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -399,7 +399,7 @@ You're in front of building.
|
|||
|
||||
You're inside building.
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There are some keys on the ground here.
|
||||
|
||||
|
@ -436,7 +436,7 @@ There is an emerald here the size of a plover's egg!
|
|||
|
||||
You're in the dark-room. A corridor leading south is the only exit.
|
||||
|
||||
A massive stone tablet imbedded in the wall reads:
|
||||
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!
|
||||
|
@ -702,7 +702,7 @@ It is now pitch dark. If you proceed you will likely fall into a pit.
|
|||
|
||||
You're inside building.
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There are some keys on the ground here.
|
||||
|
||||
|
@ -984,7 +984,7 @@ There is a huge beanstalk growing out of the west pit up to the hole.
|
|||
You are at the bottom of the eastern pit in the Twopit Room. There is
|
||||
a small pool of oil in one corner of the pit.
|
||||
|
||||
> g oil
|
||||
> get oil
|
||||
|
||||
Your bottle is now full of oil.
|
||||
|
||||
|
@ -1140,7 +1140,7 @@ There is a delicate, precious, ming vase here!
|
|||
|
||||
There is a threatening little dwarf in the room with you!
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1178,7 +1178,7 @@ going west. There is also a large room above. The air is damp here.
|
|||
> n
|
||||
|
||||
You're in a large room carved out of sedimentary rock. The floor and
|
||||
walls are littered with bits of shells imbedded in the stone. A
|
||||
walls are littered with bits of shells embedded in the stone. A
|
||||
shallow passage proceeds downward, and a somewhat steeper one leads
|
||||
up. A low hands and knees passage enters from the south.
|
||||
|
||||
|
@ -1225,7 +1225,7 @@ It is now pitch dark. If you proceed you will likely fall into a pit.
|
|||
|
||||
You are inside a building, a well house for a large spring.
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There are some keys on the ground here.
|
||||
|
||||
|
@ -1351,7 +1351,7 @@ You're in Giant Room.
|
|||
|
||||
There is a large nest here, full of golden eggs!
|
||||
|
||||
> g
|
||||
> get
|
||||
|
||||
OK
|
||||
|
||||
|
@ -1421,7 +1421,7 @@ You are inside a barren room. The center of the room is completely
|
|||
empty except for some dust. Marks in the dust lead away toward the
|
||||
far end of the room. The only exit is the way you came in.
|
||||
|
||||
There is a ferocious cave bear eying you from the far end of the room!
|
||||
There is a ferocious cave bear eyeing you from the far end of the room!
|
||||
|
||||
The bear is locked to the wall with a golden chain!
|
||||
|
||||
|
@ -1479,7 +1479,7 @@ You're in Chamber of Boulders.
|
|||
|
||||
There are rare spices here!
|
||||
|
||||
|
||||
>
|
||||
You scored 119 out of a possible 430, using 238 turns.
|
||||
|
||||
Your score qualifies you as a novice class adventurer.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## Coverage of LOC_BOULDERS2.short
|
||||
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
n
|
||||
seed 1838473132
|
||||
in
|
||||
|
@ -156,7 +158,7 @@ u
|
|||
drop appen
|
||||
e
|
||||
d
|
||||
g oil
|
||||
get oil
|
||||
u
|
||||
w
|
||||
d
|
||||
|
@ -220,7 +222,7 @@ w
|
|||
d
|
||||
climb
|
||||
w
|
||||
g
|
||||
get
|
||||
n
|
||||
take bottl
|
||||
n
|
||||
|
@ -239,4 +241,4 @@ fork
|
|||
ne
|
||||
e
|
||||
out
|
||||
e
|
||||
e
|
||||
|
|
|
@ -316,7 +316,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill dragon
|
||||
|
||||
|
@ -329,7 +329,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -487,7 +487,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -532,7 +532,7 @@ There is an emerald here the size of a plover's egg!
|
|||
|
||||
You're in the dark-room. A corridor leading south is the only exit.
|
||||
|
||||
A massive stone tablet imbedded in the wall reads:
|
||||
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!
|
||||
|
@ -808,7 +808,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -1286,7 +1286,7 @@ OK
|
|||
|
||||
There is a threatening little dwarf in the room with you!
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1334,7 +1334,7 @@ going west. There is also a large room above. The air is damp here.
|
|||
> n
|
||||
|
||||
You're in a large room carved out of sedimentary rock. The floor and
|
||||
walls are littered with bits of shells imbedded in the stone. A
|
||||
walls are littered with bits of shells embedded in the stone. A
|
||||
shallow passage proceeds downward, and a somewhat steeper one leads
|
||||
up. A low hands and knees passage enters from the south.
|
||||
|
||||
|
@ -1387,7 +1387,7 @@ There is an enormous ruby here!
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -1614,7 +1614,7 @@ You are inside a barren room. The center of the room is completely
|
|||
empty except for some dust. Marks in the dust lead away toward the
|
||||
far end of the room. The only exit is the way you came in.
|
||||
|
||||
There is a ferocious cave bear eying you from the far end of the room!
|
||||
There is a ferocious cave bear eyeing you from the far end of the room!
|
||||
|
||||
The bear is locked to the wall with a golden chain!
|
||||
|
||||
|
@ -1774,7 +1774,7 @@ There is a huge beanstalk growing out of the west pit up to the hole.
|
|||
|
||||
> e
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1918,7 +1918,7 @@ There is an enormous ruby here!
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -2021,11 +2021,11 @@ OK
|
|||
|
||||
The gem fits easily into the cavity.
|
||||
|
||||
The persian rug stiffens and rises a foot or so off the ground.
|
||||
The Persian rug stiffens and rises a foot or so off the ground.
|
||||
|
||||
> fly rug
|
||||
|
||||
You board the persian rug, which promptly whisks you across the chasm.
|
||||
You board the Persian rug, which promptly whisks you across the chasm.
|
||||
You have time for a fleeting glimpse of a two thousand foot drop to a
|
||||
mighty river; then you find yourself on the other side.
|
||||
|
||||
|
@ -2033,7 +2033,7 @@ You are on a small ledge on one face of a sheer cliff. There are no
|
|||
paths away from the ledge. Across the chasm is a small clearing
|
||||
surrounded by forest.
|
||||
|
||||
There is a persian rug here, hovering in mid-air!
|
||||
There is a Persian rug here, hovering in mid-air!
|
||||
|
||||
A brilliant blue star sapphire is here!
|
||||
|
||||
|
@ -2049,7 +2049,7 @@ You're at cliff.
|
|||
|
||||
There is an emerald resting in a small cavity in the rock!
|
||||
|
||||
There is a persian rug here, hovering in mid-air!
|
||||
There is a Persian rug here, hovering in mid-air!
|
||||
|
||||
> take emerald
|
||||
|
||||
|
@ -2059,7 +2059,7 @@ OK
|
|||
|
||||
The gem fits easily into the cavity.
|
||||
|
||||
The persian rug settles gently to the ground.
|
||||
The Persian rug settles gently to the ground.
|
||||
|
||||
> take rug
|
||||
|
||||
|
@ -2151,7 +2151,7 @@ long description of your location.
|
|||
|
||||
You are inside a building, a well house for a large spring.
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a rare amber gemstone here!
|
||||
|
||||
|
@ -2341,7 +2341,7 @@ It is now pitch dark. If you proceed you will likely fall into a pit.
|
|||
|
||||
You're inside building.
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a rare amber gemstone here!
|
||||
|
||||
|
@ -2934,14 +2934,14 @@ Huh?
|
|||
|
||||
Huh?
|
||||
|
||||
> unlock oyster
|
||||
|
||||
I advise you to put down the oyster before opening it. >WRENCH!<
|
||||
|
||||
> drop oyster
|
||||
|
||||
OK
|
||||
|
||||
> unlock oyster
|
||||
|
||||
You don't have anything strong enough to open the oyster.
|
||||
|
||||
> take oyster
|
||||
|
||||
OK
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
@ -467,14 +469,16 @@ e
|
|||
e
|
||||
cave
|
||||
e
|
||||
# Everything to here is from endgame428
|
||||
# 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
|
||||
unlock oyster
|
||||
drop oyster
|
||||
unlock oyster
|
||||
take oyster
|
||||
read oyster
|
||||
y
|
||||
|
@ -482,4 +486,3 @@ sw
|
|||
attack bird
|
||||
find bird
|
||||
break mirror
|
||||
|
||||
|
|
|
@ -51,10 +51,6 @@ has scrawled, "MAGIC WORD XYZZY".
|
|||
|
||||
A three foot black rod with a rusty star on an end lies nearby.
|
||||
|
||||
> eat grate
|
||||
|
||||
I see no grate here.
|
||||
|
||||
> w
|
||||
|
||||
You are in an awkward sloping east/west canyon.
|
||||
|
@ -75,8 +71,8 @@ You can catch the bird, but you cannot carry it.
|
|||
|
||||
The little bird is now dead. Its body disappears.
|
||||
|
||||
|
||||
You scored 32 out of a possible 430, using 10 turns.
|
||||
>
|
||||
You scored 32 out of a possible 430, using 9 turns.
|
||||
|
||||
You are obviously a rank amateur. Better luck next time.
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
@ -6,9 +8,8 @@ take lamp
|
|||
rub lamp
|
||||
xyzzy
|
||||
on
|
||||
eat grate
|
||||
w
|
||||
w
|
||||
take bird
|
||||
# test intransitive attack on bird
|
||||
attack
|
||||
attack
|
||||
|
|
|
@ -197,7 +197,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill dragon
|
||||
|
||||
|
@ -210,7 +210,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -327,7 +327,7 @@ 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.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
|
|
@ -13,14 +13,15 @@ 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
|
||||
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 threshhold in fewer than 330 turns.'
|
||||
my knowledge, never achieved this threshold in fewer than 330 turns.
|
||||
|
||||
To achieve the next higher rating, you need 969 more points.
|
||||
To achieve the next higher rating would be a neat trick!
|
||||
Congratulations!!
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
## 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
|
||||
|
|
|
@ -13,12 +13,9 @@ 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!!
|
||||
|
||||
To achieve the next higher rating would be a neat trick!
|
||||
Congratulations!!
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
## 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
|
||||
|
|
4
tests/compare
Executable file
4
tests/compare
Executable file
|
@ -0,0 +1,4 @@
|
|||
#! /bin/sh
|
||||
# Display diff for an individual test
|
||||
test=$1
|
||||
../advent <${test}.log | ./tapdiffer "${test}" "${test}.chk"
|
|
@ -1,181 +1,212 @@
|
|||
#!/usr/bin/env python
|
||||
#!/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.
|
||||
|
||||
# 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 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 yaml
|
||||
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"
|
||||
STDOUT_REPORT_CATEGORY = (
|
||||
" {name:.<19}: {percent:5.1f}% covered ({covered} of {total})\n"
|
||||
)
|
||||
|
||||
HTML_SUMMARY_ROW = '''
|
||||
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 = '''
|
||||
HTML_CATEGORY_SECTION = """
|
||||
<tr id="{id}"></tr>
|
||||
{rows}
|
||||
<tr>
|
||||
<td> </td>
|
||||
</tr>
|
||||
'''
|
||||
"""
|
||||
|
||||
HTML_CATEGORY_HEADER = '''
|
||||
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="{}"> </td>\n'
|
||||
|
||||
HTML_CATEGORY_ROW = '''
|
||||
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 == None or needle == "" or needle == "NO_MESSAGE":
|
||||
|
||||
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", ".*")
|
||||
|
||||
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 i, objouter in enumerate(objects):
|
||||
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["messages"][name] = {"covered": False}
|
||||
report["total"] += 1
|
||||
if report["messages"][name]["covered"] != True and search(desc, text):
|
||||
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 seperately
|
||||
# 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["messages"][name] = {"long": False, "short": False}
|
||||
report["total"] += 2
|
||||
if report["messages"][name]["long"] != True and search(desc["long"], text):
|
||||
if not report["messages"][name]["long"] and search(desc["long"], text):
|
||||
report["messages"][name]["long"] = True
|
||||
report["covered"] += 1
|
||||
if report["messages"][name]["short"] != True and search(desc["short"], text):
|
||||
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 i, hintouter in enumerate(obituaries):
|
||||
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["messages"][name] = {"question": False, "hint": False}
|
||||
report["total"] += 2
|
||||
if report["messages"][name]["question"] != True and search(hint["question"], text):
|
||||
if not report["messages"][name]["question"] and search(hint["question"], text):
|
||||
report["messages"][name]["question"] = True
|
||||
report["covered"] += 1
|
||||
if report["messages"][name]["hint"] != True and search(hint["hint"], text):
|
||||
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["messages"][name] = {"query": False, "yes_response": False}
|
||||
report["total"] += 2
|
||||
if report["messages"][name]["query"] != True and search(obit["query"], text):
|
||||
if not report["messages"][name]["query"] and search(obit["query"], text):
|
||||
report["messages"][name]["query"] = True
|
||||
report["covered"] += 1
|
||||
if report["messages"][name]["yes_response"] != True and search(obit["yes_response"], text):
|
||||
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["messages"][name] = {"covered": False}
|
||||
report["total"] += 1
|
||||
if report["messages"][name]["covered"] != True and search(item["message"], text):
|
||||
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["messages"][name] = {"covered": False}
|
||||
report["total"] += 1
|
||||
if report["messages"][name]["covered"] != True and search(message, text):
|
||||
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["messages"][name] = {"covered": False}
|
||||
report["total"] += 1
|
||||
if report["messages"][name]["covered"] != True and search(item["message"], text):
|
||||
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 catagory, including total items, number of items
|
||||
# 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" : {}
|
||||
"name": name, # convenience for string formatting
|
||||
"total": 0,
|
||||
"covered": 0,
|
||||
"messages": {},
|
||||
}
|
||||
|
||||
# search for each message in ever test check file
|
||||
# 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"])
|
||||
|
@ -188,20 +219,21 @@ def coverage_report(db, check_file_contents):
|
|||
|
||||
return report
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# load DB
|
||||
try:
|
||||
with open(YAML_PATH, "r") as f:
|
||||
db = yaml.load(f)
|
||||
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 {} ({}})'.format(YAML_PATH, e.strerror))
|
||||
exit(-1)
|
||||
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") as f:
|
||||
with open(filename, "r", encoding="ascii", errors="surrogateescape") as f:
|
||||
check_file_contents.append(f.read())
|
||||
|
||||
# run coverage analysis report on dungeon database
|
||||
|
@ -218,20 +250,26 @@ if __name__ == "__main__":
|
|||
category["percent"] = (category["covered"] / float(category["total"])) * 100
|
||||
|
||||
# render section header
|
||||
cat_messages = sorted(category["messages"].items())
|
||||
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)
|
||||
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 value != True else "covered")
|
||||
category_html += HTML_CATEGORY_ROW.format(id=message_id,colspan=colspan, cells=category_html_row)
|
||||
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
|
||||
|
@ -248,16 +286,22 @@ if __name__ == "__main__":
|
|||
|
||||
# render HTML report
|
||||
try:
|
||||
with open(HTML_TEMPLATE_PATH, "r") as f:
|
||||
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))
|
||||
exit(-1)
|
||||
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") as f:
|
||||
f.write(html_template.format(categories=categories_html, summary=summary_html))
|
||||
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))
|
||||
print("ERROR: writing HTML report failed ({})".format(e.strerror))
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
|
|
@ -316,7 +316,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill dragon
|
||||
|
||||
|
@ -329,7 +329,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -487,7 +487,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -532,7 +532,7 @@ There is an emerald here the size of a plover's egg!
|
|||
|
||||
You're in the dark-room. A corridor leading south is the only exit.
|
||||
|
||||
A massive stone tablet imbedded in the wall reads:
|
||||
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!
|
||||
|
@ -813,7 +813,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -1283,7 +1283,7 @@ OK
|
|||
|
||||
There is a threatening little dwarf in the room with you!
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1331,7 +1331,7 @@ going west. There is also a large room above. The air is damp here.
|
|||
> n
|
||||
|
||||
You're in a large room carved out of sedimentary rock. The floor and
|
||||
walls are littered with bits of shells imbedded in the stone. A
|
||||
walls are littered with bits of shells embedded in the stone. A
|
||||
shallow passage proceeds downward, and a somewhat steeper one leads
|
||||
up. A low hands and knees passage enters from the south.
|
||||
|
||||
|
@ -1389,7 +1389,7 @@ There is an enormous ruby here!
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -1616,7 +1616,7 @@ You are inside a barren room. The center of the room is completely
|
|||
empty except for some dust. Marks in the dust lead away toward the
|
||||
far end of the room. The only exit is the way you came in.
|
||||
|
||||
There is a ferocious cave bear eying you from the far end of the room!
|
||||
There is a ferocious cave bear eyeing you from the far end of the room!
|
||||
|
||||
The bear is locked to the wall with a golden chain!
|
||||
|
||||
|
@ -1772,7 +1772,7 @@ There is a huge beanstalk growing out of the west pit up to the hole.
|
|||
|
||||
> e
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1916,7 +1916,7 @@ There is an enormous ruby here!
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -2023,11 +2023,11 @@ The rug does not appear inclined to cooperate.
|
|||
|
||||
The gem fits easily into the cavity.
|
||||
|
||||
The persian rug stiffens and rises a foot or so off the ground.
|
||||
The Persian rug stiffens and rises a foot or so off the ground.
|
||||
|
||||
> fly rug
|
||||
|
||||
You board the persian rug, which promptly whisks you across the chasm.
|
||||
You board the Persian rug, which promptly whisks you across the chasm.
|
||||
You have time for a fleeting glimpse of a two thousand foot drop to a
|
||||
mighty river; then you find yourself on the other side.
|
||||
|
||||
|
@ -2035,7 +2035,7 @@ You are on a small ledge on one face of a sheer cliff. There are no
|
|||
paths away from the ledge. Across the chasm is a small clearing
|
||||
surrounded by forest.
|
||||
|
||||
There is a persian rug here, hovering in mid-air!
|
||||
There is a Persian rug here, hovering in mid-air!
|
||||
|
||||
A brilliant blue star sapphire is here!
|
||||
|
||||
|
@ -2051,7 +2051,7 @@ You're at cliff.
|
|||
|
||||
There is an emerald resting in a small cavity in the rock!
|
||||
|
||||
There is a persian rug here, hovering in mid-air!
|
||||
There is a Persian rug here, hovering in mid-air!
|
||||
|
||||
> take emerald
|
||||
|
||||
|
@ -2061,7 +2061,7 @@ OK
|
|||
|
||||
The gem fits easily into the cavity.
|
||||
|
||||
The persian rug settles gently to the ground.
|
||||
The Persian rug settles gently to the ground.
|
||||
|
||||
> take rug
|
||||
|
||||
|
@ -2079,7 +2079,7 @@ OK
|
|||
|
||||
The gem fits easily into the cavity.
|
||||
|
||||
The persian rug draped over your shoulder seems to wriggle for a
|
||||
The Persian rug draped over your shoulder seems to wriggle for a
|
||||
moment, but then subsides.
|
||||
|
||||
> take emerald
|
||||
|
@ -2164,7 +2164,7 @@ long description of your location.
|
|||
|
||||
You are inside a building, a well house for a large spring.
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a rare amber gemstone here!
|
||||
|
||||
|
@ -2354,7 +2354,7 @@ It is now pitch dark. If you proceed you will likely fall into a pit.
|
|||
|
||||
You're inside building.
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a rare amber gemstone here!
|
||||
|
||||
|
@ -2932,6 +2932,20 @@ OK
|
|||
Interesting. There seems to be something written on the underside of
|
||||
the oyster.
|
||||
|
||||
> read oyster
|
||||
|
||||
Hmmm, this looks like a clue, which means it'll cost you 10 points to
|
||||
read it. Should I go ahead and read it anyway?
|
||||
|
||||
> y
|
||||
|
||||
It says, "There is a way out of this place. Do you need any more
|
||||
information to escape? Sorry, but this initial hint is all you get."
|
||||
|
||||
> read oyster
|
||||
|
||||
It says the same thing it did before. Hm, maybe it's a pun?
|
||||
|
||||
> drop oyster
|
||||
|
||||
OK
|
||||
|
@ -3014,14 +3028,16 @@ There is an enormous oyster here with its shell tightly closed.
|
|||
You can hear the murmuring of the beanstalks and the snoring of the
|
||||
dwarves.
|
||||
|
||||
Even though it's an oyster, the critter's as tight-mouthed as a clam.
|
||||
|
||||
> blast rod
|
||||
|
||||
There is a loud explosion, and a twenty-foot hole appears in the far
|
||||
wall, burying the snakes in the rubble. A river of molten lava pours
|
||||
in through the hole, destroying everything in its path, including you!
|
||||
|
||||
You scored 399 out of a possible 430, using 480 turns.
|
||||
You scored 389 out of a possible 430, using 482 turns.
|
||||
|
||||
Your score puts you in Master Adventurer Class B.
|
||||
|
||||
To achieve the next higher rating, you need 12 more points.
|
||||
To achieve the next higher rating, you need 22 more points.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
@ -472,8 +474,11 @@ e
|
|||
e
|
||||
e
|
||||
e
|
||||
# Expecting failure here
|
||||
take oyster
|
||||
# Test both cases (before and after hint) of reading oyster
|
||||
read oyster
|
||||
y
|
||||
read oyster
|
||||
drop oyster
|
||||
open oyster
|
||||
sw
|
||||
|
|
|
@ -166,7 +166,7 @@ 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.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
|
|
@ -227,7 +227,7 @@ There is a little axe here.
|
|||
|
||||
A huge green fierce dragon bars the way!
|
||||
|
||||
The dragon is sprawled out on a persian rug!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill drago
|
||||
|
||||
|
@ -242,11 +242,11 @@ 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!
|
||||
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.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
|
|
@ -150,7 +150,7 @@ A huge green fierce snake bars the way!
|
|||
|
||||
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.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
@ -25,4 +27,4 @@ take bird
|
|||
drop cage
|
||||
d
|
||||
d
|
||||
feed snake
|
||||
feed snake
|
||||
|
|
|
@ -316,7 +316,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill dragon
|
||||
|
||||
|
@ -329,7 +329,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -491,7 +491,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -536,7 +536,7 @@ There is an emerald here the size of a plover's egg!
|
|||
|
||||
You're in the dark-room. A corridor leading south is the only exit.
|
||||
|
||||
A massive stone tablet imbedded in the wall reads:
|
||||
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!
|
||||
|
@ -812,7 +812,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## In which the dwarf kills you
|
||||
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
n
|
||||
seed 1494912171
|
||||
in
|
||||
|
|
|
@ -58,3 +58,12 @@ 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.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
# Check that dwarf spawns in alternative location (fuzzed)
|
||||
## 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
|
||||
|
@ -8,3 +10,4 @@ w
|
|||
w
|
||||
d
|
||||
d
|
||||
n
|
||||
|
|
|
@ -248,7 +248,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill drago
|
||||
|
||||
|
@ -261,7 +261,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -994,7 +994,7 @@ There is a delicate, precious, ming vase here!
|
|||
|
||||
> se
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1024,7 +1024,7 @@ going west. There is also a large room above. The air is damp here.
|
|||
> n
|
||||
|
||||
You're in a large room carved out of sedimentary rock. The floor and
|
||||
walls are littered with bits of shells imbedded in the stone. A
|
||||
walls are littered with bits of shells embedded in the stone. A
|
||||
shallow passage proceeds downward, and a somewhat steeper one leads
|
||||
up. A low hands and knees passage enters from the south.
|
||||
|
||||
|
@ -1167,7 +1167,7 @@ You're in Giant Room.
|
|||
|
||||
There is a large nest here, full of golden eggs!
|
||||
|
||||
> g egg
|
||||
> take egg
|
||||
|
||||
OK
|
||||
|
||||
|
@ -1223,7 +1223,7 @@ Wicker cage
|
|||
Black rod
|
||||
Small bottle
|
||||
|
||||
|
||||
>
|
||||
You scored 77 out of a possible 430, using 190 turns.
|
||||
|
||||
Your score qualifies you as a novice class adventurer.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
@ -184,11 +186,11 @@ w
|
|||
d
|
||||
climb
|
||||
w
|
||||
g egg
|
||||
take egg
|
||||
n
|
||||
fee
|
||||
fie
|
||||
foe
|
||||
foo
|
||||
look
|
||||
inven
|
||||
inven
|
||||
|
|
|
@ -399,7 +399,7 @@ the west wall is scrawled the inscription, "FEE FIE FOE FOO" [sic].
|
|||
|
||||
There is a large nest here, full of golden eggs!
|
||||
|
||||
> g
|
||||
> take
|
||||
|
||||
OK
|
||||
|
||||
|
@ -435,7 +435,7 @@ There is a large nest here, full of golden eggs!
|
|||
|
||||
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.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
@ -59,7 +61,7 @@ d
|
|||
water plant
|
||||
climb
|
||||
w
|
||||
g
|
||||
take
|
||||
n
|
||||
fee
|
||||
fie
|
||||
|
@ -67,4 +69,4 @@ foe
|
|||
foo
|
||||
# go south, east to arrive at LOC_CAVEIN for coverage
|
||||
s
|
||||
e
|
||||
e
|
||||
|
|
|
@ -316,7 +316,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill dragon
|
||||
|
||||
|
@ -329,7 +329,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -487,7 +487,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -532,7 +532,7 @@ There is an emerald here the size of a plover's egg!
|
|||
|
||||
You're in the dark-room. A corridor leading south is the only exit.
|
||||
|
||||
A massive stone tablet imbedded in the wall reads:
|
||||
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!
|
||||
|
@ -808,7 +808,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -1278,7 +1278,7 @@ OK
|
|||
|
||||
There is a threatening little dwarf in the room with you!
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1326,7 +1326,7 @@ going west. There is also a large room above. The air is damp here.
|
|||
> n
|
||||
|
||||
You're in a large room carved out of sedimentary rock. The floor and
|
||||
walls are littered with bits of shells imbedded in the stone. A
|
||||
walls are littered with bits of shells embedded in the stone. A
|
||||
shallow passage proceeds downward, and a somewhat steeper one leads
|
||||
up. A low hands and knees passage enters from the south.
|
||||
|
||||
|
@ -1379,7 +1379,7 @@ There is an enormous ruby here!
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -1606,7 +1606,7 @@ You are inside a barren room. The center of the room is completely
|
|||
empty except for some dust. Marks in the dust lead away toward the
|
||||
far end of the room. The only exit is the way you came in.
|
||||
|
||||
There is a ferocious cave bear eying you from the far end of the room!
|
||||
There is a ferocious cave bear eyeing you from the far end of the room!
|
||||
|
||||
The bear is locked to the wall with a golden chain!
|
||||
|
||||
|
@ -1762,7 +1762,7 @@ There is a huge beanstalk growing out of the west pit up to the hole.
|
|||
|
||||
> e
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1906,7 +1906,7 @@ There is an enormous ruby here!
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -2009,11 +2009,11 @@ OK
|
|||
|
||||
The gem fits easily into the cavity.
|
||||
|
||||
The persian rug stiffens and rises a foot or so off the ground.
|
||||
The Persian rug stiffens and rises a foot or so off the ground.
|
||||
|
||||
> fly rug
|
||||
|
||||
You board the persian rug, which promptly whisks you across the chasm.
|
||||
You board the Persian rug, which promptly whisks you across the chasm.
|
||||
You have time for a fleeting glimpse of a two thousand foot drop to a
|
||||
mighty river; then you find yourself on the other side.
|
||||
|
||||
|
@ -2021,7 +2021,7 @@ You are on a small ledge on one face of a sheer cliff. There are no
|
|||
paths away from the ledge. Across the chasm is a small clearing
|
||||
surrounded by forest.
|
||||
|
||||
There is a persian rug here, hovering in mid-air!
|
||||
There is a Persian rug here, hovering in mid-air!
|
||||
|
||||
A brilliant blue star sapphire is here!
|
||||
|
||||
|
@ -2037,7 +2037,7 @@ You're at cliff.
|
|||
|
||||
There is an emerald resting in a small cavity in the rock!
|
||||
|
||||
There is a persian rug here, hovering in mid-air!
|
||||
There is a Persian rug here, hovering in mid-air!
|
||||
|
||||
> take emerald
|
||||
|
||||
|
@ -2047,7 +2047,7 @@ OK
|
|||
|
||||
The gem fits easily into the cavity.
|
||||
|
||||
The persian rug settles gently to the ground.
|
||||
The Persian rug settles gently to the ground.
|
||||
|
||||
> take rug
|
||||
|
||||
|
@ -2139,7 +2139,7 @@ long description of your location.
|
|||
|
||||
You are inside a building, a well house for a large spring.
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a rare amber gemstone here!
|
||||
|
||||
|
@ -2329,7 +2329,7 @@ It is now pitch dark. If you proceed you will likely fall into a pit.
|
|||
|
||||
You're inside building.
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a rare amber gemstone here!
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
|
2464
tests/endobjects.chk
Normal file
2464
tests/endobjects.chk
Normal file
File diff suppressed because it is too large
Load diff
430
tests/endobjects.log
Normal file
430
tests/endobjects.log
Normal file
|
@ -0,0 +1,430 @@
|
|||
### 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
|
|
@ -436,7 +436,7 @@ OK
|
|||
|
||||
OK
|
||||
|
||||
|
||||
>
|
||||
You scored 59 out of a possible 430, using 93 turns.
|
||||
|
||||
Your score qualifies you as a novice class adventurer.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## 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
|
||||
|
|
|
@ -244,7 +244,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill drago
|
||||
|
||||
|
@ -257,7 +257,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -1055,7 +1055,7 @@ There is a delicate, precious, ming vase here!
|
|||
|
||||
There is a threatening little dwarf in the room with you!
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1166,7 +1166,7 @@ You're at complex junction.
|
|||
> n
|
||||
|
||||
You're in a large room carved out of sedimentary rock. The floor and
|
||||
walls are littered with bits of shells imbedded in the stone. A
|
||||
walls are littered with bits of shells embedded in the stone. A
|
||||
shallow passage proceeds downward, and a somewhat steeper one leads
|
||||
up. A low hands and knees passage enters from the south.
|
||||
|
||||
|
@ -1271,7 +1271,7 @@ A small velvet pillow lies on the floor.
|
|||
|
||||
> w
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1405,7 +1405,7 @@ You are in a secret n/s canyon above a large room.
|
|||
|
||||
You are in a secret canyon which exits to the north and east.
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -1638,7 +1638,7 @@ OK
|
|||
|
||||
OK
|
||||
|
||||
|
||||
>
|
||||
You scored 77 out of a possible 430, using 263 turns.
|
||||
|
||||
Your score qualifies you as a novice class adventurer.
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
## Qualify for ogre hint but fail due to dwarves dead (fuzzed)
|
||||
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#NOCOMPARE Fails due uninteresting difference in whitespace process.
|
||||
n
|
||||
seed 1838473132
|
||||
in
|
||||
|
|
|
@ -207,7 +207,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill
|
||||
|
||||
|
@ -225,7 +225,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -394,7 +394,7 @@ You are in a large chamber with passages to the west and north.
|
|||
|
||||
A formidable ogre bars the northern exit.
|
||||
|
||||
|
||||
>
|
||||
You scored 63 out of a possible 430, using 56 turns.
|
||||
|
||||
Your score qualifies you as a novice class adventurer.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## Quaify for ogre hint but fail due to nearby dwarf (fuzzed)
|
||||
## Qualify for ogre hint but fail due to nearby dwarf (fuzzed)
|
||||
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
n
|
||||
seed 25508795
|
||||
in
|
||||
|
|
|
@ -109,7 +109,7 @@ OK
|
|||
|
||||
OK
|
||||
|
||||
|
||||
>
|
||||
You scored 32 out of a possible 430, using 25 turns.
|
||||
|
||||
You are obviously a rank amateur. Better luck next time.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## Fail getting wood hint by finding appendage (fuzzed)
|
||||
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
n
|
||||
n
|
||||
z
|
||||
|
@ -24,4 +26,4 @@ z
|
|||
z
|
||||
z
|
||||
z
|
||||
z
|
||||
z
|
||||
|
|
|
@ -57,7 +57,7 @@ You can't fill that.
|
|||
|
||||
Your bottle is already full.
|
||||
|
||||
|
||||
>
|
||||
You scored 32 out of a possible 430, using 10 turns.
|
||||
|
||||
You are obviously a rank amateur. Better luck next time.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## Attempt to fill lamp, attempt to fill bottle with no source
|
||||
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
n
|
||||
in
|
||||
carry lamp
|
||||
|
|
|
@ -316,7 +316,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill dragon
|
||||
|
||||
|
@ -329,7 +329,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -487,7 +487,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -532,7 +532,7 @@ There is an emerald here the size of a plover's egg!
|
|||
|
||||
You're in the dark-room. A corridor leading south is the only exit.
|
||||
|
||||
A massive stone tablet imbedded in the wall reads:
|
||||
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!
|
||||
|
@ -808,7 +808,7 @@ You're inside building.
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -1282,7 +1282,7 @@ There is nothing here with which to fill it.
|
|||
|
||||
There is a threatening little dwarf in the room with you!
|
||||
|
||||
You are in a room whose walls resemble swiss cheese. Obvious passages
|
||||
You are in a room whose walls resemble Swiss cheese. Obvious passages
|
||||
go west, east, ne, and nw. Part of the room is occupied by a large
|
||||
bedrock block.
|
||||
|
||||
|
@ -1330,7 +1330,7 @@ going west. There is also a large room above. The air is damp here.
|
|||
> n
|
||||
|
||||
You're in a large room carved out of sedimentary rock. The floor and
|
||||
walls are littered with bits of shells imbedded in the stone. A
|
||||
walls are littered with bits of shells embedded in the stone. A
|
||||
shallow passage proceeds downward, and a somewhat steeper one leads
|
||||
up. A low hands and knees passage enters from the south.
|
||||
|
||||
|
@ -1383,7 +1383,7 @@ There is an enormous ruby here!
|
|||
|
||||
There are bars of silver here!
|
||||
|
||||
There is a persian rug spread out on the floor!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
There is a large sparkling nugget of gold here!
|
||||
|
||||
|
@ -1463,7 +1463,7 @@ A small velvet pillow lies on the ground.
|
|||
|
||||
You can't be serious!
|
||||
|
||||
|
||||
>
|
||||
You scored 191 out of a possible 430, using 241 turns.
|
||||
|
||||
You may now consider yourself a "Seasoned Adventurer".
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## Fill the vase
|
||||
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
# Arthur O'Dwyer <arthur.j.odwyer@gmail.com> writes:
|
||||
#
|
||||
# (4) Lastly, here's a test case for you! Go get the VASE; then get the
|
||||
|
|
2046
tests/flyback.chk
Normal file
2046
tests/flyback.chk
Normal file
File diff suppressed because it is too large
Load diff
345
tests/flyback.log
Normal file
345
tests/flyback.log
Normal file
|
@ -0,0 +1,345 @@
|
|||
## Test fix for issue 51: rug flying is broken
|
||||
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
#NOCOMPARE Behavior differs due to a bug fix.
|
||||
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
|
||||
fork
|
||||
w
|
||||
w
|
||||
sw
|
||||
free bear
|
||||
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
|
||||
drop keys
|
||||
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
|
||||
fly rug
|
||||
fly rug
|
|
@ -248,7 +248,7 @@ 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!!
|
||||
The dragon is sprawled out on a Persian rug!!
|
||||
|
||||
> kill drago
|
||||
|
||||
|
@ -261,7 +261,7 @@ 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!
|
||||
There is a Persian rug spread out on the floor!
|
||||
|
||||
The blood-specked body of a huge green dead dragon lies to one side.
|
||||
|
||||
|
@ -781,3 +781,24 @@ 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?
|
||||
|
||||
> y
|
||||
|
||||
All right. But don't blame me if something goes wr......
|
||||
--- POOF!! ---
|
||||
You are engulfed in a cloud of orange smoke. Coughing and gasping,
|
||||
you emerge from the smoke and find....
|
||||
|
||||
You are inside a building, a well house for a large spring.
|
||||
|
||||
There are some keys on the ground here.
|
||||
|
||||
There is food here.
|
||||
|
||||
>
|
||||
|
||||
>
|
||||
You scored 61 out of a possible 430, using 121 turns.
|
||||
|
||||
Your score qualifies you as a novice class adventurer.
|
||||
|
||||
To achieve the next higher rating, you need 60 more points.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
## Coverage of LOC_FOOTSLIP
|
||||
# SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
n
|
||||
seed 1838473132
|
||||
in
|
||||
|
@ -122,4 +124,6 @@ u
|
|||
u
|
||||
u
|
||||
u
|
||||
u
|
||||
u
|
||||
y
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue