Compare commits

...

376 commits
1.6 ... master

Author SHA1 Message Date
Eric S. Raymond
7d848c89e1 Add spell-checking to the regression tests. 2025-05-25 11:06:46 -04:00
Eric S. Raymond
7bbf994fce Spellcheck the manual page a well. No errors. 2025-05-25 11:03:34 -04:00
Eric S. Raymond
3e989aec53 Spellcheck the YAML - yielded one trivial fix. 2025-05-25 10:57:34 -04:00
Eric S. Raymond
9df69fe034 Ready to ship 1.20. 2024-09-23 18:48:11 -04:00
Eric S. Raymond
a2bb39dc7e Eliminate a confusing dummy argument in a macro. 2024-09-23 14:22:25 -04:00
Eric S. Raymond
5c90880f0a Comment and macro cleanup. 2024-09-23 06:06:32 -04:00
Eric S. Raymond
92451f1fff Eliminate thew last property inequality outside a macro. 2024-09-23 05:08:11 -04:00
Eric S. Raymond
96ad6c6245 Reflow. 2024-09-23 04:38:24 -04:00
Eric S. Raymond
40742e112b Expand a macro to simplify code. 2024-09-23 04:26:59 -04:00
Eric S. Raymond
a4fd14caf7 Back away from trying for the found member until we make stashed work. 2024-09-23 04:26:59 -04:00
Eric S. Raymond
9a6e4406f5 Confine uses of PROP_STASHIFY() to advent.h
Now it shouyld be possible to manipulate a stashed flag by only
changing macros.
2024-09-23 04:26:59 -04:00
Eric S. Raymond
08f0351817 Introduce OBJECT_STASHIFY. 2024-09-23 04:26:59 -04:00
Eric S. Raymond
0157e58668 Remove an unneeded layer of macro indirection. 2024-09-23 03:35:52 -04:00
Eric S. Raymond
354e56a69b Clean up some comments. 2024-09-23 03:35:52 -04:00
Eric S. Raymond
9c3f4b0c90 Reflow. 2024-09-22 13:08:31 -04:00
Eric S. Raymond
20fd7c589f Typo fix. 2024-09-20 22:19:14 -04:00
Eric S. Raymond
8c553af53e Avoid a GNUism, POSIX strncasecmp() is declarted in strings.h. 2024-09-20 22:05:25 -04:00
Eric S. Raymond
f1cb740c41 Define TRUNCLEN and explain its issues. 2024-09-20 22:04:16 -04:00
Eric S. Raymond
cf4adf8d02 Repair truncation in oldstyle mode.
Sure would be nice to remember while this code had TOKEN + TOKEN
where one would think it should just say TOKEN.
2024-09-20 10:49:44 -04:00
Eric S. Raymond
acdfa96315 Fix a busted comment. 2024-09-20 10:40:22 -04:00
Eric S. Raymond
3d6c689ffa Make oldstyle correctly suppress line editing. 2024-09-20 10:29:37 -04:00
Eric S. Raymond
8dcc6e6641 Correct missing negative. 2024-09-20 10:03:15 -04:00
Eric S. Raymond
e17ff128da Remove obsolete comment part. 2024-06-30 17:20:46 -04:00
Eric S. Raymond
cb293f4aa4 Rename some macos for clarity. 2024-06-30 14:48:44 -04:00
Eric S. Raymond
124e7768b4 Cease relying on C storage starting zeroed. 2024-06-27 19:50:56 -04:00
Eric S. Raymond
63e8579f74 Ready to shp 1.19. 2024-06-27 13:39:27 -04:00
Eric S. Raymond
1080b45d39 Comment typo fix. 2024-06-27 13:29:28 -04:00
Eric S. Raymond
86fe4bd121 Verify that tesrts still match advent430 where expected. 2024-06-27 13:04:33 -04:00
Eric S. Raymond
bd499dc532 Fix GitLab issue #69: repeated knive caveat message 2024-06-25 16:42:14 -04:00
Eric S. Raymond
ae6eced72d Incorporate Ryan Sarson's test for correct knife message. 2024-06-25 13:08:50 -04:00
Eric S. Raymond
7903ac1bb8 More validation, with -Wall and -Wextra. 2024-06-03 21:12:41 -04:00
Eric S. Raymond
b51612131d Typo fix. 2024-04-29 11:43:41 -04:00
Eric S. Raymond
62cd0c78da Reissue 1.18 - same code, corrected metadata. 2024-02-15 12:56:01 -05:00
Eric S. Raymond
bad34acf1e Improve the project summary. 2024-02-05 08:07:31 -05:00
Eric S. Raymond
0fafbe379f Ubuntu-discuss doesn't want to see release notifications. 2024-02-05 07:51:00 -05:00
Eric S. Raymond
fcf6935689 Ready to ship 1.18. 2024-02-05 07:49:07 -05:00
Eric S. Raymond
b610a62685 Documentation polishing. 2024-02-05 07:43:23 -05:00
Eric S. Raymond
6174129116 Add a detail to the installation instructiions. 2024-02-04 16:56:20 -05:00
Eric S. Raymond
a2fa136988 Remove unused production. 2024-02-04 16:16:05 -05:00
Eric S. Raymond
43a08621e4 asciidoc -> asciidoctor. 2024-02-04 15:52:03 -05:00
Eric S. Raymond
f24fcd2971 Perform full code validation on every make check. 2024-02-04 12:48:33 -05:00
Eric S. Raymond
580f409ee6 At this revision, make cppcheck runs clean. 2024-02-04 11:44:04 -05:00
Eric S. Raymond
5b917084b0 Minor repair of savefile validation code. 2024-02-04 11:43:36 -05:00
Eric S. Raymond
1ef39055f3 Make reflow run black. 2024-02-04 10:07:58 -05:00
Eric S. Raymond
0175344caa 1TBS reflow, the bracening. 2024-01-29 12:14:56 -05:00
Eric S. Raymond
be429016af 1TBS reflow with clang-format. 2024-01-28 08:09:39 -05:00
Eric S. Raymond
c11938aed5 Place1TBS mandatory braces. 2024-01-28 07:14:46 -05:00
Eric S. Raymond
258b7703f2 Simplify SPDX copyright lines to the shortest canonical form...
...because if we leave them longer than 80 chars, reflow is going to
mess them up.
2024-01-28 07:14:46 -05:00
Eric S. Raymond
83c6a66887 Typo fix. 2024-01-15 05:10:46 -05:00
Eric S. Raymond
3c09c25cc3 Update tapview and tapdiffer. 2024-01-15 05:03:53 -05:00
Eric S. Raymond
f26514b5dd Fix SPDX headers. 2024-01-15 04:58:21 -05:00
Eric S. Raymond
cf7ea0cd89 Remove debugging debris. 2024-01-15 04:57:47 -05:00
Eric S. Raymond
2db3bed3f1 Fix up copyright notices. SPDX wants only one per file. 2024-01-03 06:30:40 -05:00
Eric S. Raymond
a6ec8a9595 Simplify some dependencies. 2024-01-03 06:15:04 -05:00
Eric S. Raymond
75bc031b46 Reduce include complexity. 2024-01-03 05:55:57 -05:00
Eric S. Raymond
dd65960ec5 Ready to ship 1.17. 2024-01-02 21:58:14 -05:00
Eric S. Raymond
90f96a25da pylint cleanup. 2024-01-02 21:53:23 -05:00
Eric S. Raymond
c10e9694e3 Corrected fix, and test, for #67. 2024-01-02 17:19:42 -05:00
Eric S. Raymond
11d966f349 Add -a option to synopsis. 2024-01-02 16:57:15 -05:00
Eric S. Raymond
e1a17fd442 NEWS update. 2024-01-02 16:38:59 -05:00
Eric S. Raymond
eb63994931 Better explanation of backwards compatibility with 4.30. 2024-01-02 16:34:54 -05:00
Eric S. Raymond
0b82afa5c1 Commit a test script. 2024-01-02 16:03:30 -05:00
Eric S. Raymond
b247359d7f Initialize dwarf locations in YAML, not C.
Minimizes magic numbers.
2024-01-02 12:12:32 -05:00
Eric S. Raymond
1f9f39d789 Address GitLab issue #67: saying Z'ZZZ at the reservoir causes the water to part/crash together 2024-01-02 10:42:11 -05:00
Eric S. Raymond
2582e240bd Fix defective copyright notices. 2024-01-02 09:46:09 -05:00
Eric S. Raymond
9fbd603f8d Typo fix. 2024-01-02 09:28:39 -05:00
Nicola Smaniotto
5016978156
saveresume.c: add missing semicolon
Fixes compilation when ADVENT_NOSAVE is set
2023-11-27 17:41:26 +01:00
Eric S. Raymond
7d4dd78679 Apply black to move Python style to standard form. 2023-09-17 16:17:30 -04:00
Eric S. Raymond
ab4653b89c Comment polishing. 2023-05-10 20:08:10 -04:00
Torbjörn Andersson
b28eb66868 Spelling fixes. 2023-04-18 18:44:08 +02:00
Eric S. Raymond
f0119f8431 Comment rtpo fix. 2023-04-18 08:02:14 -04:00
Eric S. Raymond
5075c63cf4 Add some map tags. 2023-04-18 07:51:55 -04:00
Eric S. Raymond
ebf3e389c0 Add exolanatory comment. 2023-04-17 09:19:26 -04:00
Eric S. Raymond
6cef68cda5 Use fixed-lwength types to make the save format more portable 2023-04-17 07:24:51 -04:00
Eric S. Raymond
234da6b468 Remove unnecessary code duplication. 2023-04-17 07:06:56 -04:00
Eric S. Raymond
adbb5c1204 Ready to ship 1.16. 2023-04-15 14:44:20 -04:00
Eric S. Raymond
869c53d1b1 Comment polishing. 2023-04-15 10:00:23 -04:00
Eric S. Raymond
ef78c36ddb Improve state-macro encapsulation. 2023-04-15 09:29:28 -04:00
Eric S. Raymond
5d3205e1e9 Add explanatory comments. 2023-04-15 06:29:59 -04:00
Eric S. Raymond
a6b41fdb8f Simplify initialization code. All tests pass, 100% coverage. 2023-04-14 08:24:51 -04:00
Eric S. Raymond
9ff036d789 Make build with conditional compilation easier. 2023-04-14 06:16:29 -04:00
Eric S. Raymond
88feaab0c0 Remove a remnant line number. 2023-04-10 19:29:11 -04:00
Eric S. Raymond
4d4e8dce96 Magic-number elimination. 2023-04-10 19:27:07 -04:00
Eric S. Raymond
82c3ae5e65 Condition in alternative state-management macros.
These do not entirely work yet. #define FOUNDBOOL to enable them.

All tests pass, 100% coverage.
2023-04-10 19:26:18 -04:00
Eric S. Raymond
1af01ff91f Confine use of STATE_NOTFOUND to macros. 2023-04-08 23:04:34 -04:00
Eric S. Raymond
9e9731d59b Turn an odd test into a macro disjunction.
Was game.objects[i].prop > STATE_NOTFOUND.

This finishes off all the statec comparisons we want to macroize.
2023-04-08 21:17:55 -04:00
Eric S. Raymond
191d3cb043 More nontrivial macro abstraction of state checks.
game.prop < 0 becomes an alternation of macros.
2023-04-08 20:32:04 -04:00
Eric S. Raymond
c82d1214fa First nontrivial replacement of object state test by macro.
Test was game.objects[i].prop >= 0, but we know that state -1
(STATE_NOTFOUND) can't occiur here because the object is in
a lit room.
2023-04-08 20:02:27 -04:00
Eric S. Raymond
02987d0330 Encapsulate object-state state tests and setttings in macros.
This isn't a complete refwctoring, just the part than can be done with
transparetly correct capture of inlinre logic into macros.

No logic changes. Tests pass, 100% coverage.
2023-04-08 19:35:41 -04:00
Eric S. Raymond
9cd7c53d78 Refactor put() function and calls. 2023-04-07 13:19:51 -04:00
Eric S. Raymond
ab2779cd93 Remove unneeded use of put(). 2023-04-07 13:09:57 -04:00
Eric S. Raymond
819aed5c4e Add test for behavior of stashed objects in endgame. 2023-04-07 12:33:52 -04:00
Eric S. Raymond
8d4d64fafb Structurization of hints. 2023-04-07 10:52:16 -04:00
Eric S. Raymond
eebc87f889 Structurize object info. 2023-04-07 10:35:13 -04:00
Eric S. Raymond
8fe07c8bf3 Structurize locatiuon info. 2023-04-07 09:30:33 -04:00
Eric S. Raymond
ff9c73a37d Structurize the informaruin about dwarves. 2023-04-07 09:15:20 -04:00
Eric S. Raymond
195e6e149b Apply loc_t type. 2023-04-07 08:18:50 -04:00
Eric S. Raymond
4369284c75 Boolification. 2023-04-07 07:35:28 -04:00
Torbjörn Andersson
7e21108e95 Spelling fixes. 2023-04-07 10:50:01 +02:00
Eric S. Raymond
829c13d1d5 Fix some screwy formatting of conditionals...
...probably by the original FOTRAN-to-C translator.
2023-04-06 21:29:39 -04:00
Eric S. Raymond
2f60504e07 Comment typo fixes. 2023-04-06 21:01:48 -04:00
Eric S. Raymond
5de3b8ff70 In notes.adoc, update the new-features list and credits. 2023-04-06 20:07:25 -04:00
Eric S. Raymond
520d365f74 Resume now detects if a save has incompatible endianness. 2023-04-06 19:41:22 -04:00
Eric S. Raymond
4b08b726f9 Simplify the signature of savefile(). 2023-04-06 19:26:04 -04:00
Eric S. Raymond
58cf204eba Implement the magic-cookie check and its test. 2023-04-06 19:03:02 -04:00
Eric S. Raymond
d16822a583 Give savefiles an identifting header. SAve format version gets bumped. 2023-04-06 17:54:02 -04:00
Eric S. Raymond
3640e5cb96 Refactoring step - change some visibilities. 2023-04-06 17:44:11 -04:00
Eric S. Raymond
e99cc69de0 Quiet make test down. 2023-04-06 17:28:43 -04:00
Eric S. Raymond
e8991f69e9 Simplify and speed up testing. 2023-04-06 16:38:21 -04:00
Eric S. Raymond
3e72486724 Comment typo fix 2023-04-06 12:13:38 -04:00
Eric S. Raymond
f5ff25f52a Magic-number elimination. 2023-04-06 10:03:24 -04:00
Eric S. Raymond
e1a528a4c5 Move NEWS file to asciidoc. 2023-04-05 21:48:02 -04:00
Eric S. Raymond
9726d8207c Add some SPDX headers. 2023-04-05 21:36:52 -04:00
Eric S. Raymond
fe378b9e13 Improved behavior when magic words are said before they're seen.
Note: there is a tiny risk that this could break savefile
compatibility, as I swiped an unused int member in the game structure
and turned it into a bool. int and bool *should* be the same sixe...
2023-04-05 19:49:38 -04:00
Eric S. Raymond
4ce4de190e Magic number removal. 2023-04-05 18:02:47 -04:00
Eric S. Raymond
9b53140f1c GO_* enums no longer have an order constraint. 2023-04-05 17:48:26 -04:00
Eric S. Raymond
3c6648882d How to set up prerequisites for oldcompare 2023-04-04 19:14:45 -04:00
Eric S. Raymond
00bdc2133a Improve TAP messages slightly. 2023-04-04 09:53:10 -04:00
Eric S. Raymond
20e1b9d930 Update tapdiffer version. 2023-04-04 09:32:18 -04:00
Eric S. Raymond
1ce4fc2ac3 Improve copyright lines. 2023-04-03 17:05:01 -04:00
Eric S. Raymond
642b7e4890 Ready to ship 1.15. 2023-04-03 11:36:39 -04:00
Eric S. Raymond
ec1d99f354 Commenting fix. 2023-04-03 11:36:39 -04:00
Eric S. Raymond
6ebc2bf0e3 Documentation fix. 2023-04-03 11:25:11 -04:00
Eric S. Raymond
25230068fe Partial REUSE cmpliance. 2023-04-03 11:25:11 -04:00
Eric S. Raymond
71abcb4e65 Add explanatory comment. 2023-04-03 09:42:55 -04:00
Eric S. Raymond
2dd1ccc535 Fix for Gitlab issue #65: revisiting "fee fie foe foo" and "fum".
100% coverage, "make oldcompare" passes.
2023-04-03 09:24:21 -04:00
Eric S. Raymond
0a1f5dbb43 Nothing but FOO can start a magic-word sequence,
100% coverage ans oldcompare passes.
2023-04-03 07:14:11 -04:00
Eric S. Raymond
20cb8b9ffb Back out test lines that break compatibility with advent430.
Coverage is still 100% even withthese lines commebted out.
2023-04-02 18:28:45 -04:00
Eric S. Raymond
b86d4afd20 Back out the behavior change to magic words outside the Giant's Room.
There are twi reasons for this. One is to decompolicate verifying
the fix for issue $85: revisiting "fee fie foe foo" and "fum". The
other is because I'm now convinced that the test should notr be
"Are you in the Giant's Room" but :Have you read the grafitti there?
2023-04-02 17:53:09 -04:00
Eric S. Raymond
d9ddf4d805 Consolidate all magicwords tests into one file. 100% coverage. 2023-04-02 17:45:04 -04:00
Eric S. Raymond
9c6219a27d The oldcompare production no longer requires savefiles. 2023-04-02 11:54:37 -04:00
Eric S. Raymond
34516ecf39 Test name change, 2023-04-02 10:42:10 -04:00
Eric S. Raymond
7dc3482c5b Start building a better test load for micwords. 2023-04-02 10:23:07 -04:00
Eric S. Raymond
40a4acb868 Comment typo fixes. 2023-04-02 07:41:49 -04:00
Torbjörn Andersson
54927c33e5 Spelling fixes 2023-04-02 07:32:24 +02:00
Eric S. Raymond
e49fb5f367 Close out oldcompare.
At this revision all test logs either pass checkfile comparison
against advent439 or have a NOCOMPARE comment explaining why they don't
pass, turning into a TAP skip. 100% coverage.
2023-04-01 18:37:08 -04:00
Eric S. Raymond
59a5afb72e Improve advent430 comparisons. 2023-04-01 16:58:52 -04:00
Eric S. Raymond
f95442b310 Test comment typo fixes. 2023-04-01 11:34:46 -04:00
Eric S. Raymond
97a69d8cbd Merge two NOCOMPARE tests. 2023-04-01 11:01:28 -04:00
Eric S. Raymond
0d2332573b Tweak a fuzzed test fotr advent430 compability. 100% coverage. 2023-04-01 10:47:49 -04:00
Eric S. Raymond
7af8492169 Add a warning comment. 2023-04-01 08:46:44 -04:00
Eric S. Raymond
3af590e972 Trim the illformed test. Still 100% coverage. 2023-03-30 20:09:10 -04:00
Eric S. Raymond
2c8aa9668c Add explanatory comments to two tests. 2023-03-30 08:46:35 -04:00
Eric S. Raymond
30a98cc916 Factor out the test of the bare word "seed". 2023-03-30 01:05:32 -04:00
Eric S. Raymond
872b94f927 Factor out most of illformed that doesn't cause advent430 problems. 2023-03-30 00:05:13 -04:00
Eric S. Raymond
74c3158f42 Add more NOCOMPARE exclusions due to version skew. 2023-03-29 22:05:27 -04:00
Eric S. Raymond
ef180a0731 Truncatte bigfail test because the RNG gets confused by resurrection. 2023-03-29 18:25:35 -04:00
Eric S. Raymond
77ac2f1570 Coverage exclusions for -d. 2023-03-29 18:16:43 -04:00
Eric S. Raymond
ff46cf7fac Add -d option 2023-03-29 16:04:36 -04:00
Eric S. Raymond
c80162b467 More test cleanup to converge with advent430 branch. 2023-03-29 14:40:38 -04:00
Eric S. Raymond
65f221e03f Add a more carefully factored test...
...so we can exclude the part advent430 won't pass.
2023-03-29 10:59:42 -04:00
Eric S. Raymond
cbb5572b21 Clean up some tests, adding newlines at EOF where they're missing.
The advent430 command interpreter accidentally accepted input lines with no
trailing newline. Thus, these files produced spurious mismatches.
2023-03-29 10:55:56 -04:00
Eric S. Raymond
a5eeb0b2bc Add a useful warning to the tests makefile 2023-03-29 09:36:58 -04:00
Eric S. Raymond
4eccfa127c Document a bugfix and isolate it in a test. 2023-03-29 09:24:12 -04:00
Eric S. Raymond
dc8b19bcdc Implement NOCOMPARE magic. 2023-03-23 14:58:06 -04:00
Eric S. Raymond
2070db3a2a Test simplification - we don't care about the difference in processing blank lines. 2023-03-22 21:20:24 -04:00
Eric S. Raymond
e3fbac804b Reconciliation with advent430. 2023-03-22 20:39:36 -04:00
Eric S. Raymond
5f7ce87040 Change prompt generation to be more compatible with the advent430 branch. 2023-03-22 17:09:14 -04:00
Eric S. Raymond
1e05134b47 Minor fix to prompt generation. 2023-03-22 17:03:50 -04:00
Eric S. Raymond
1ffb81b70b YAML markup fix. 2023-03-22 14:48:49 -04:00
Eric S. Raymond
fefd2a19fb Remove redundant test. 2023-03-22 14:48:49 -04:00
Eric S. Raymond
4fa3d4d758 Test cleanup and reconvilation with advent430. 2023-03-22 14:48:49 -04:00
Eric S. Raymond
07a0f066ba Quoting fixes in the YAML. 2023-03-22 00:05:58 -04:00
Eric S. Raymond
a006bdd272 TAPify the ancient-diffs report. 2023-03-22 00:05:58 -04:00
Eric S. Raymond
327efd3678 Test cleanup. 2023-03-22 00:05:58 -04:00
Eric S. Raymond
b044e9ab42 Move in the direction of being able to do ancient regression tests. 2023-03-21 17:27:30 -04:00
Eric S. Raymond
8fd3eb8b92 Testing simplification. 2023-03-16 10:18:56 -04:00
Eric S. Raymond
9fdbe73315 Revert "Tapify output of cheat."
There was a better way.
2023-03-16 10:15:47 -04:00
Eric S. Raymond
9758883ea2 More TAPification. 2023-03-16 09:48:16 -04:00
Eric S. Raymond
f5d15ab1f2 Tapify output of cheat. 2023-03-16 08:32:59 -04:00
Eric S. Raymond
f07b3ba2d4 Address GitLab issue #66: Missing couple of ; in saveresume.c 2023-03-16 07:43:17 -04:00
Eric S. Raymond
87855f8124 Avoid a compiler warning. 2023-03-14 14:58:26 -04:00
Eric S. Raymond
786832210e Magic-number elimination. 2023-03-14 14:58:26 -04:00
Eric S. Raymond
9b89dd2829 Experimental test production. 2023-03-14 14:58:26 -04:00
Eric S. Raymond
17840d0e15 Comment polishing. 2023-03-12 17:59:10 -04:00
Eric S. Raymond
5929a68b88 Real test coverage dor SAVE_TAMPERING. 2023-03-12 17:37:58 -04:00
Eric S. Raymond
43af075fa9 Cleann up scratchfile after tesrs. 2023-03-12 17:21:15 -04:00
Eric S. Raymond
47c3d14a11 Comment polishing. 2023-03-12 17:14:18 -04:00
Eric S. Raymond
db8ca5eb26 Documentation polishing. 2023-03-12 12:58:11 -04:00
Eric S. Raymond
ca5b6975dc NEWS update. 2023-03-12 12:41:13 -04:00
Eric S. Raymond
282842c4a9 Whitespace trimming of save and resume names. 2023-03-12 12:10:30 -04:00
Eric S. Raymond
7723f3fc1a Add coverage exception now that SAVE_TAMPERING is back. 2023-03-12 10:11:52 -04:00
Eric S. Raymond
0ffb297801 Relax the savefile validity check a little.
There was a very old bug, probably predating the OpenAdventure port,
that would poke a stashed value of -1 into the snake object if you did
a save in endgame, and then fail the savefile validation on resume.
This was masked for a long time by a bug in put() just fixed a couple
of revisions ago.
2023-03-12 10:03:43 -04:00
Eric S. Raymond
04df0ce64c Add message and bailout on invalid save.
Note: save/resume still fails at saveresume.4
at this revision.
2023-03-12 06:39:57 -04:00
Eric S. Raymond
569a39aa7c Drop an attempt to pacify cppcheck that's no longer needed. 2023-03-11 10:58:38 -05:00
Eric S. Raymond
1652df4540 Add ANSI prototype, 2023-03-11 10:40:01 -05:00
Eric S. Raymond
ba3248224e Add C coverage exclsion required by unbreaking the property setter. 2023-03-11 10:29:38 -05:00
Eric S. Raymond
b7bf85904d Fix a formal-type glitch. 2023-03-11 09:44:51 -05:00
Eric S. Raymond
71f05c4567 Bugfix: bird starts caged in endgame.
Turns out the code of put() had been modified ibcorrectly, but
the bug was masked in all but a few cases, noe of which would be
encountered in normal gameplay.

A test to ensure this bug does noit recur has been added.
2023-03-11 09:35:26 -05:00
Eric S. Raymond
fe8a82927c Document a bugfix. 2023-03-10 17:17:38 -05:00
Eric S. Raymond
b125fe7b2a Fix interrupted-magic-words cosmetic bug.
C patch by Torbjörn Andersson.
2023-03-10 16:43:27 -05:00
Eric S. Raymond
3971a61ab0 Ready to ship 1.14. 2023-03-09 10:19:53 -05:00
Eric S. Raymond
8f527fb433 Fix whitespace glitch. 2023-03-09 10:19:53 -05:00
Eric S. Raymond
643eab4e9c Use $(advent) rather than advent where needed. 2023-03-09 08:54:20 -05:00
Eric S. Raymond
f53476f826 Complete fix of GitLab issue #64: Coverage summary looks wrong 2023-03-08 22:55:12 -05:00
Eric S. Raymond
83c32598be Partially address Gitlsb issue #64: Coverage summary looks wrong 2023-03-08 21:54:45 -05:00
Torbjörn Andersson
98b95e92ee Another typo fix. 2023-03-08 18:15:51 +01:00
Eric S. Raymond
8d409c6b3b Add a comment to the code that fixes the inventory-count bug. 2023-03-07 08:12:36 -05:00
Eric S. Raymond
e1ce7d6b6a Documentation polishing. 2023-03-07 06:27:08 -05:00
Eric S. Raymond
f911e42453 Eliminate some forwards. 2023-03-06 23:41:07 -05:00
Eric S. Raymond
12d39ef72b Improve Makefile recipe for coverage testing. 2023-03-06 12:55:17 -05:00
Eric S. Raymond
1efd1027f7 Add test for interspersed non-motion command amidst magic words. 2023-03-04 20:26:13 -05:00
Eric S. Raymond
1121bb8aa5 NEWS and notes.adoc update. 2023-03-04 20:16:07 -05:00
Eric S. Raymond
a01c08385c Prevent a spurious coverage error. 2023-03-04 19:58:57 -05:00
Eric S. Raymond
643656fcc3 Complain to user on save/resume.restore when it's disabled. 2023-03-04 19:48:17 -05:00
Eric S. Raymond
ac0c5fc024 Document -a option. 2023-03-03 17:18:00 -05:00
Rob Swindell (on Debian Linux)
dfff80faa8 Add optional auto-save/restore feature using -a <filename> option
To enable use with online Bulletin Board Systems (BBSes) where users
may be disconnected unexpectedly, but would naturally want to resume
playing their same game, added support for an optional save game
path/filename to be specified on the command-line (very similar to
"-r <filename>"), except this save/restore file is:
1. automatically loaded/restored if it exists
2. automatically created when starting a new game
3. automatically updated when exiting a game for any reason
4. cannot be changed to a different path/filename by the user

Since a BBS server program can be expected to send a SIGHUP or SIGTERM
to the game process upon user disconnection (or timeout), those
signals are caught and a graceful termination will occur which saves
the current game state.

Build with ADVENT_AUTOSAVE defined to enable this option.

BUG:
The 'info' command still reports the save/suspend/pause commands as
valid, though they are not when this build option is used (same is
true of ADVENT_NOSAVE, and that doesn't apparently bother anyone).
2023-03-02 19:44:47 -08:00
Eric S. Raymond
426684fec2 Increase retrigressiveness of oldstyle a bit. 2023-03-01 17:46:13 -05:00
Eric S. Raymond
162c5abc8a Comment typo fix. 2023-03-01 16:03:13 -05:00
Eric S. Raymond
1f644a1d7d Don't crap out on failed diff. 2023-03-01 14:01:44 -05:00
Eric S. Raymond
17782cab67 Another comment typo fix. 2023-03-01 13:52:54 -05:00
Eric S. Raymond
94e7cc6505 Address Gitlab isse #62: Comment typos. 2023-03-01 13:04:53 -05:00
Eric S. Raymond
3f34adad3b Move pylint suppressions inline. 2023-02-28 19:46:50 -05:00
Eric S. Raymond
17c74326c1 Ready to ship 1.13. 2023-02-28 19:02:10 -05:00
Eric S. Raymond
b8c7a6d5ea cppcheck cleanup. 2023-02-28 18:55:12 -05:00
Eric S. Raymond
e5e6dbd741 NEWS update. 2023-02-28 18:40:40 -05:00
Eric S. Raymond
89266b7c1a Documerntation and comment polishing. 2023-02-28 17:05:37 -05:00
Eric S. Raymond
9a1b4d021e Improve message emission when player wins. 2023-02-28 15:10:54 -05:00
Eric S. Raymond
ff2dd31209 Update our tapview copy. 2023-02-28 15:04:42 -05:00
Eric S. Raymond
66b8192ae8 SPDXify generated code. 2023-02-28 14:55:40 -05:00
Eric S. Raymond
23e9931645 Prevent spurious error return. 2023-02-28 14:48:33 -05:00
Eric S. Raymond
20859304c0 Eliminate a bad code smell. 2023-02-28 06:45:24 -05:00
Eric S. Raymond
aa32e8f4d6 Add Ryan Sarson's 430-point win to the test suite. 2023-02-27 23:03:38 -05:00
Eric S. Raymond
60d7070506 Cleanup for current pylint. 2023-02-17 13:45:50 -05:00
Eric S. Raymond
a44ec19753 Documentation polishing. 2023-02-07 05:27:24 -05:00
Eric S. Raymond
9812b7a357 Comment improvements. 2023-02-07 04:55:59 -05:00
Eric S. Raymond
d9111efc68 Ready to ship 1.12 2023-02-06 17:03:34 -05:00
Eric S. Raymond
5e2614678b NEWS update. 2023-02-06 16:52:16 -05:00
Eric S. Raymond
0aead5634e Another typo fix. 2023-02-06 16:46:03 -05:00
Eric S. Raymond
7810888164 Experimental tweak of Docker image to try to fix manpage build. 2023-02-06 16:36:59 -05:00
Eric S. Raymond
aaaf0ac7d2 Typo fixes. 2023-02-06 16:03:38 -05:00
Eric S. Raymond
750cfe36d8 Fix for GitLab issue #59. 2022-10-21 11:21:58 -04:00
Eric S. Raymond
b6c0f5bff0 Add Patreon link. 2022-04-20 11:59:26 -04:00
Eric S. Raymond
e5d01c83f0 Remove ibsoletre constraint comment.
I think it became obsolete when we factored out state-change messages.
2022-04-20 11:32:02 -04:00
Eric S. Raymond
3dcf8449e5 In the grapher,add some room condition bits to clean up code. 2022-04-20 11:09:08 -04:00
Eric S. Raymond
3f3e114536 In the grapher, split forset from surface mode. 2022-04-20 07:15:18 -04:00
Eric S. Raymond
baab09e3ab py;imt cleanup. 2022-04-19 22:41:14 -04:00
Eric S. Raymond
81c7bb6d5b More grapher improvement. 2022-04-19 22:36:28 -04:00
Eric S. Raymond
c547f4498b Add verbose optionm to grapher. 2022-04-19 20:39:54 -04:00
Eric S. Raymond
74b1589b57 Various grapher improvements. 2022-04-19 19:48:35 -04:00
Eric S. Raymond
67a887f432 Magic-number elimination. 2022-04-19 17:07:46 -04:00
Eric S. Raymond
00c2182d9b Code cleanup. 2022-04-19 16:36:20 -04:00
Eric S. Raymond
9af3ab4ecd Improve comments. 2022-04-19 16:36:20 -04:00
Eric S. Raymond
017162da6e Declare the poject finished in the designer's notes. 2022-04-18 16:41:13 -04:00
Eric S. Raymond
648deb4770 Remove the TODo, last iten about lamp image is obsolerte
* 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.
The deleted TODO said:

* 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.

Further research using an image search on the web reveals that there
have been miners' lamps thart visually resemble outr hurricane-lamp
images pretty closely,  so we can keep using it.
2022-04-18 16:18:43 -04:00
Eric S. Raymond
156b39c34a Do full code validation before each release. 2022-04-18 14:47:01 -04:00
Eric S. Raymond
c71a4dc441 NEWS update, 2022-04-18 14:43:55 -04:00
Eric S. Raymond
732b581031 Remove an issue about dropping the vase, the drop code doesn't change state. 2022-04-18 13:57:29 -04:00
Eric S. Raymond
86e2e21ef8 Drop vase on pillow in well house and confirm that you get points for it. 2022-04-18 12:40:09 -04:00
Eric S. Raymond
3afaabead3 NEWS update.
After re-reading the code, I have concluded that the objective of making it
more typeful can be abandoned. The tyings typefulness could give us are
largely achieved.
2022-04-18 12:01:35 -04:00
Eric S. Raymond
d320212622 Indent cleanup. 2022-04-18 10:31:13 -04:00
Eric S. Raymond
f7d6884ded cppcheck cleanup. 2022-04-18 10:24:11 -04:00
Eric S. Raymond
d9d58ea168 Base UNDEEP on the previiously unreferenced DEEP condition bit.
Removes the only dependency on the order of locations left in the macros.
2022-04-18 10:01:14 -04:00
Eric S. Raymond
846f293e06 Typo fix. 2022-04-14 15:49:56 -04:00
Eric S. Raymond
70a9edd497 Ready to ship 1.11 2022-04-14 14:38:50 -04:00
Eric S. Raymond
dee8809e30 pylint cleanup. 2022-04-14 13:54:45 -04:00
Eric S. Raymond
44017d64bb Reorganize and clean up test machinery. 2022-04-14 12:27:15 -04:00
Eric S. Raymond
dd7b664e32 Revert Makefile changes that broke coverage testing for cheat.c 2022-04-14 12:05:03 -04:00
Eric S. Raymond
1c2346392e Grapher simplification. 2022-04-14 11:34:43 -04:00
Eric S. Raymond
f6fc7f244d Graph mode for maze all different. 2022-04-14 07:47:47 -04:00
Eric S. Raymond
18566a349a Add logic for chasing forwarding limks to the graph maker. 2022-04-13 22:31:46 -04:00
Eric S. Raymond
4069bf210b cppcheck cleanup. 2022-04-13 20:55:57 -04:00
Eric S. Raymond
ceba6482a1 Introduce and use matags in the YAML. 2022-04-13 20:31:07 -04:00
Eric S. Raymond
9e6095afa0 Inprove -m mapping. 2022-04-13 15:20:26 -04:00
Eric S. Raymond
ad75cc1eb7 Mapping improvements. 2022-04-13 13:41:57 -04:00
Eric S. Raymond
0f5fd82b77 Add a test of resurrection logic. 2022-04-13 04:38:41 -04:00
Eric S. Raymond
834f6e753c Add test that dropping vase in tghe soft room does not break it. 2022-04-13 04:23:28 -04:00
Eric S. Raymond
b30059bb72 NEWS update. 2022-04-13 04:01:41 -04:00
Eric S. Raymond
af7ce31dd9 Simplify the test machinery. 2022-04-13 03:59:57 -04:00
Eric S. Raymond
337377ab57 savecheck only needs to be run for makiung coverage reports. 2022-04-13 03:45:59 -04:00
Eric S. Raymond
d235313e97 Switch normal regression testing to TAP output. 2022-04-13 03:13:53 -04:00
Eric S. Raymond
129136b51e Integrate multifile test into TAP sequence. 2022-04-13 02:58:02 -04:00
Eric S. Raymond
7b3b5d32c0 More steps towards TAP. 2022-04-13 02:42:25 -04:00
Eric S. Raymond
c78845e05a Update maxhinert for tap from reposurgeon...
...but it doesn't work yet.
2022-04-12 23:23:48 -04:00
Eric S. Raymond
74dc0d168a Take test coverage back to 100% 2022-04-12 22:47:41 -04:00
Eric S. Raymond
829e55f99d Another test coverage improvement. 2022-04-12 21:51:37 -04:00
Eric S. Raymond
10b888f449 Another coverage improvement 2022-04-12 21:24:42 -04:00
Eric S. Raymond
f9237d6970 Improve YAML symbol coverage. 2022-04-12 20:08:45 -04:00
Eric S. Raymond
8c80aa183b Scratch a to-do item. 2022-04-12 19:53:13 -04:00
Eric S. Raymond
8b8a3a73c4 Fix bugs in coverage testing. 2022-04-12 19:45:43 -04:00
Eric S. Raymond
865e10e6d0 Coverage fixups. 2022-04-12 11:27:07 -04:00
Eric S. Raymond
c5250b5f3f Clean up warning and deprecation issues. 2022-04-12 10:53:37 -04:00
Eric S. Raymond
49e2479efa Improve test coverage. 2022-04-07 06:42:20 -04:00
Eric S. Raymond
6f7c5743c6 Add a coverage exclusion. 2022-04-06 22:27:14 -04:00
Eric S. Raymond
00cbf464b5 Ready to ship 1.10. 2022-04-06 20:02:07 -04:00
Eric S. Raymond
2df951ba60 Improve the maze graph. 2022-04-06 19:11:09 -04:00
Eric S. Raymond
6dd37a6ec3 Namespace splittiing to prune the maze graph. No eeffect on gameplay. 2022-04-06 18:59:14 -04:00
Eric S. Raymond
07f77a8ffd Proof of concept for dungeon graph maker. 2022-04-06 17:47:57 -04:00
Eric S. Raymond
7d2cfa5166 Typo fix. 2022-04-06 15:48:06 -04:00
Eric S. Raymond
beae508e1d Add a test for the isolated-foo case 2022-04-06 14:54:43 -04:00
Eric S. Raymond
dd5ca23302 Second part of fix for "fee fie foe foo" and "fum", with test. 2022-04-06 14:41:30 -04:00
Eric S. Raymond
db384731a7 Address GitLab issue #56: handling of "fee fie foe foo" and "fum"
Also add a regression test for this.
2022-04-06 13:43:08 -04:00
Eric S. Raymond
a2116b3d79 Add test for correct listen behavior. 2022-04-06 07:54:20 -04:00
Eric S. Raymond
46e1595cb0 Address Gitlanb issue #54: listen command not showing all sounds 2022-04-06 07:49:42 -04:00
Eric S. Raymond
e0b9aeda6e Resolve Gitlab issue #55: in endgame, some object starting states are incorrect
The uncaged status of the bird in the endagame doesn't seem worth the effort to fix it.
2022-04-05 19:20:21 -04:00
Eric S. Raymond
73b49d27f4 Fix issue #51: rug flying is broken
And add a test for the fix.
2022-04-05 15:18:17 -04:00
Eric S. Raymond
bb2b8e0fca Support execution of command script arguments. 2022-04-05 14:33:29 -04:00
Eric S. Raymond
8378063198 Address GitLab issue #53: inventory limit glitch in original game is not reproduced
It was actually a bit of a philosophical question whether I should try to make
this fix revertible with -o. I decided not to, as it's just something the user
may stumble over rather than being an edifying feature of the origiunal interface.
2022-04-04 18:08:50 -04:00
Eric S. Raymond
0799bc2f79 Address Gitlib issu #57: Resume can't open save file...
...when auto-completed filename is followed by a space character.
2022-04-04 17:51:06 -04:00
Eric S. Raymond
5ab94ce8de Fix bad copypasta. 2021-03-14 20:45:34 -04:00
Eric S. Raymond
5aaa22860a Experimental steps towards TAP and test parallelization. 2021-03-10 16:56:39 -05:00
Eric S. Raymond
f2f238e9e4 Address GitLab issue #55: water should not be available in endgame. 2021-02-15 22:21:26 -05:00
Eric S. Raymond
a251e18682 Address Gitlab issue #52: endgame oyster reading is incorrect 2021-02-15 18:11:57 -05:00
Jason Ninneman
be3457abeb Overhaul CI pipeline to use a custom Ubuntu-based Docker image. 2021-01-12 09:08:56 -07:00
Jason Ninneman
12443b0159 Use Python 3, not 2. 2021-01-11 15:56:05 +00:00
Jason Ninneman
eb27776c99 Change and add packages for tumbleweed. 2021-01-11 15:56:05 +00:00
Eric S. Raymond
ba11a8df2e In the YAML, name the rabbit foot because it has a reference. 2021-01-11 01:06:44 -05:00
Eric S. Raymond
b93d2d396f Tweak for Debian packaging. 2021-01-11 00:27:09 -05:00
Eric S. Raymond
bfbea454c7 Trim a legend to less than 80 lines. 2021-01-11 00:20:03 -05:00
Eric S. Raymond
747c42029d Attempt fix for issue #52: endgame oyster reading is incorrect 2021-01-11 00:14:51 -05:00
Eric S. Raymond
8984e48e78 Attempting fix for issue #50: carried clam can be opened (with trident) 2021-01-10 22:14:11 -05:00
Eric S. Raymond
fe1b02f4c0 Correction to the date of first drop. Also, a thinko fix. 2021-01-10 21:02:30 -05:00
Eric S. Raymond
e879e35a02 We can be precise to the day about the release date...
...because Don's original code drop at SAIL was recovered and
announced on Twitter on 2021-01-01.
2021-01-04 14:40:08 -05:00
Eric S. Raymond
90d9ffd85d Ready to release 1.9. 2020-08-27 20:41:17 -04:00
Eric S. Raymond
d9e33a8478 Deal with the consequences of an entry-point deprecation in Python. 2020-08-27 20:33:44 -04:00
Eric S. Raymond
039c06882e Ready for 1.8 release. 2019-04-19 16:29:15 -04:00
Eric S. Raymond
baa7800a3f Fix markup. 2019-04-19 16:25:59 -04:00
Eric S. Raymond
7d0b15ef89 Fixes for some links in the history section. 2019-04-19 16:19:32 -04:00
Eric S. Raymond
3b714272fb control metadata update. 2019-04-19 16:19:32 -04:00
Eric S. Raymond
41c0e77684 Typo fix. 2019-04-19 16:19:32 -04:00
Robert Oschler
569e7c5051 Update INSTALL.adoc to provide extra help for those getting an error regarding yaml when trying to follow the install instructions. 2019-04-19 18:43:46 +00:00
Jason Ninneman
b909cc695f Install missing CI pipeline dependency. 2019-03-01 11:11:44 -07:00
Jason Ninneman
1e6b58420e Use the new path to the openSUSE Docker image. 2019-03-01 11:03:58 -07:00
Eric S. Raymond
989bdad3ee Add a warning to avoid CI breakage. 2019-02-28 22:42:59 -05:00
Jason Ninneman
2ad0fc148b Bump save version number in a test. 2019-02-28 13:04:12 -07:00
Eric S. Raymond
1d54ebb6bd Note that save format has been bumped. 2019-02-28 13:55:56 -05:00
Eric S. Raymond
ae02eac051 Add a coverage exception. 2019-02-28 13:38:08 -05:00
Eric S. Raymond
cf64568f83 Make dungeon.[ch] depemdent on advent.h in case of save version bump. 2019-02-28 12:48:54 -05:00
Eric S. Raymond
9cbea5a5db Documentation polishing. 2019-02-28 07:26:52 -05:00
Eric S. Raymond
b817c54245 Documentation polishing. 2019-02-28 07:09:57 -05:00
Eric S. Raymond
2ddd091893 Documentation polishing. 2019-02-28 06:21:24 -05:00
Eric S. Raymond
b2b4377f71 Bump the save format number, just in case. 2019-02-28 06:04:57 -05:00
Eric S. Raymond
81af59974b The FORTRAN-derived longs were semantically ints. Make it so.
Note. because we used fixed-length declrations in the right places, this
shouldn't break saves.

(Besides being right, this will someday make a port to Go a touch easier,
if we decide to do that.)
2019-02-28 05:58:16 -05:00
Eric S. Raymond
b8c9cf90d8 Restore eyeball-friendliness of INSTALL.adoc. 2019-02-28 05:38:06 -05:00
Eric S. Raymond
7de00b0741 NEWS update. 2019-02-28 05:30:41 -05:00
Jason Ninneman
58a2de6d75 Drop clang debug test to restore pipeline to working order. 2019-02-28 10:24:14 +00:00
Jason Ninneman
5c260e3aec Apply the recent typo fixes to the tests, so they pass. 2019-02-28 10:24:14 +00:00
Jason Ninneman
a727aebdfa Improve INSTALL.adoc's directions and asciidoc-ness.
View it in the Gitlab web interface to see the intended result.
2019-02-28 10:24:14 +00:00
Eric S. Raymond
83f432780a Remove use of Unicode number sign in comments.
"#" for this use is well established in English.  It's not worth opening the
i18n can of worms here.
2019-02-28 05:18:04 -05:00
Eric S. Raymond
0d27a5e03d Document a user-visible change. 2019-02-28 04:59:44 -05:00
Horst H. von Brand
cd36e91381 A few in-game message typos...
Signed-off-by: Horst H. von Brand <vonbrand@inf.utfsm.cl>
2018-12-10 22:26:39 -03:00
Horst H. von Brand
894ac28186 Another typo
Signed-off-by: Horst H. von Brand <vonbrand@inf.utfsm.cl>
2018-12-10 22:09:22 -03:00
Horst H. von Brand
64b120c03b A couple of "locaiton" in advent.h
Signed-off-by: Horst H. von Brand <vonbrand@inf.utfsm.cl>
2018-12-10 21:38:27 -03:00
Aaron Traas
8c6593ad0c Commenting and cleanups 2018-12-10 10:56:35 -05:00
Aaron Traas
e7dc3eab5d Correct return types for all of the action handling functions in actions, so it's clear we're not just using arbitrary ints 2018-12-07 10:36:42 -05:00
Aaron Traas
2a5dac3d8c Abstracted a chuck of do_command() into seperate function do_move(), moved that call to main loop, so as to narrow the focus of do_command() to getting and processing commands. 2018-12-07 10:35:36 -05:00
Aaron Traas
e3b508536d Fix warning on macOS 2018-12-06 10:01:34 -05:00
Aaron Traas
5f4df123b4 Refactored; added state property to command struct to notate where in the lifecycle of command processing that the command is. 2018-12-05 15:05:55 -05:00
Aaron Traas
9475552be4 Major cleanups. Pre-process loop back in main loop, pre-processing abstracted into a function that makes sense. 2018-12-04 11:03:17 -05:00
Eric S. Raymond
b84a2392a1 Ready for 1.7 release. 2018-12-03 22:23:29 -05:00
Eric S. Raymond
673da862b5 NEWS update. 2018-12-03 21:06:03 -05:00
Aaron Traas
ea3b456715 Makefile fix for macOS 10.14 2018-12-03 13:51:02 -05:00
Aaron Traas
dd1d69ad82 Fix for change in list handling behavior in Python 3 2018-12-03 13:48:00 -05:00
Eric S. Raymond
6667ffd1f1 Address GitLab issue #45: OSX Compile issue 2018-11-30 09:50:25 -05:00
Eric S. Raymond
fcf99d56d8 Resolve GitLab issue #46: -o (oldstyle) clarification. 2018-11-30 09:50:25 -05:00
Eric S. Raymond
e65f31cac2 Documentation fix. 2018-11-30 09:50:25 -05:00
NHOrus
524f035e76 Reindentation, typo fix 2018-11-23 20:41:31 +03:00
Eric S. Raymond
f1d3b75561 Remove comments that are obsolete now that the code is goto-less. 2018-11-20 07:05:23 -05:00
Aaron Traas
a437136543 We are now goto free! 2018-11-19 17:01:31 -05:00
Aaron Traas
16545a5765 Eliminated "Lookup" label 2018-11-19 14:52:13 -05:00
Eric S. Raymond
eb49f4d0d2 Comment polishing. 2018-11-18 16:27:06 -05:00
Eric S. Raymond
08f77c692a Attempting voodoo change to banish GitLab error.
This shouldn't be necessary.
2018-11-18 12:39:04 -05:00
Eric S. Raymond
deb489cd8c Eliminate a label. 2018-11-16 08:30:26 -05:00
Eric S. Raymond
9a32aab879 Explicit preserve logic is no longer needed...
...now that we're not heedlessly nuking the command state.
2018-11-16 07:38:49 -05:00
Eric S. Raymond
42a42c49ac Extend coverage. 2018-11-16 07:20:58 -05:00
Eric S. Raymond
5fb6e2e1bc Magic-number elimination. 2018-11-16 05:19:31 -05:00
Eric S. Raymond
c09e36ef8b Recover 100% test coverage. 2018-11-16 05:04:18 -05:00
Eric S. Raymond
09cd426443 Try to get that last line of coverage. 2018-11-15 19:56:01 -05:00
Eric S. Raymond
7991d007ac Choose a less obscure label name. 2018-11-15 14:03:20 -05:00
Eric S. Raymond
17e6078122 Remove some dead symbols revealed by coverage analysis. 2018-11-15 14:00:37 -05:00
Eric S. Raymond
31d561b470 Coverage improvement. Also, it's rude to die silently. 2018-11-15 13:55:10 -05:00
Eric S. Raymond
3ca9613bcd More coverage tweaks. 2018-11-15 13:33:16 -05:00
Eric S. Raymond
42c66160a7 Another coverage tweak. 2018-11-15 13:23:16 -05:00
Eric S. Raymond
5ce427b62b Another coverage tweak. 2018-11-15 12:40:04 -05:00
Eric S. Raymond
79875c8088 Tweak code-coverage exclusions. 2018-11-15 12:18:27 -05:00
Eric S. Raymond
ce5b694458 Ready for 1.6 release. 2018-11-15 12:18:27 -05:00
248 changed files with 31679 additions and 7623 deletions

2
.gitignore vendored
View file

@ -1,3 +1,5 @@
# SPDX-FileCopyrightText: (C) Eric S. Raymond
# SPDX-License-Identifier: BSD-2-Clause
advent
*.gcda
*.gcno

View file

@ -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

View file

@ -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>
"""

View file

@ -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
View 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

View file

@ -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

View file

@ -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
View file

@ -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
View 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.

View file

@ -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
View file

@ -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.

2994
actions.c

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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
View file

@ -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 = {

View file

@ -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

Before After
Before After

File diff suppressed because it is too large Load diff

165
cheat.c
View file

@ -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
View file

@ -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

View file

@ -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.

View file

@ -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
View file

@ -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;
}

2594
main.c

File diff suppressed because it is too large Load diff

View file

@ -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
View 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

1213
misc.c

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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
View file

@ -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 */

View file

@ -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>

View file

@ -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 */

View file

@ -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 */

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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
View 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
View 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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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!!

View file

@ -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

View file

@ -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!!

View file

@ -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
View file

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

View file

@ -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>&nbsp;</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="{}">&nbsp;</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))

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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!

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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!

View file

@ -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

File diff suppressed because it is too large Load diff

430
tests/endobjects.log Normal file
View 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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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".

View file

@ -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

File diff suppressed because it is too large Load diff

345
tests/flyback.log Normal file
View 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

View file

@ -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.

View file

@ -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