projects
/
open-adventure.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Another step in de-obscurifying the travel code.
[open-adventure.git]
/
main.c
diff --git
a/main.c
b/main.c
index 0a2ed9a0828b99405a30e8690c36666fdc3e6cb6..86e738a4e9b15593d72293e1bece5d81eb538511 100644
(file)
--- a/
main.c
+++ b/
main.c
@@
-13,28
+13,20
@@
* and for the offensive globals. Applying the Structured Program
* Theorem can be hard.
*/
* and for the offensive globals. Applying the Structured Program
* Theorem can be hard.
*/
-#define DEFINE_GLOBALS_FROM_INCLUDES
+
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <getopt.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <getopt.h>
#include <signal.h>
-#include <time.h>
#include <string.h>
#include "advent.h"
#include <string.h>
#include "advent.h"
-#include "linenoise/linenoise.h"
#include "dungeon.h"
#define DIM(a) (sizeof(a)/sizeof(a[0]))
#include "dungeon.h"
#define DIM(a) (sizeof(a)/sizeof(a[0]))
-struct game_t game;
-
-long LNLENG, LNPOSN;
-char rawbuf[LINESIZE], INLINE[LINESIZE + 1];
-
FILE *logfp = NULL, *rfp = NULL;
bool oldstyle = false;
FILE *logfp = NULL, *rfp = NULL;
bool oldstyle = false;
-bool editline = true;
bool prompt = true;
// LCOV_EXCL_START
bool prompt = true;
// LCOV_EXCL_START
@@
-45,7
+37,7
@@
static void sig_handler(int signo)
if (logfp != NULL)
fflush(logfp);
}
if (logfp != NULL)
fflush(logfp);
}
- exit(
0
);
+ exit(
EXIT_FAILURE
);
}
// LCOV_EXCL_STOP
}
// LCOV_EXCL_STOP
@@
-53,7
+45,6
@@
static void sig_handler(int signo)
* MAIN PROGRAM
*
* Adventure (rev 2: 20 treasures)
* MAIN PROGRAM
*
* Adventure (rev 2: 20 treasures)
-Here's what we think. *
* History: Original idea & 5-treasure version (adventures) by Willie Crowther
* 15-treasure version (adventure) by Don Woods, April-June 1977
* 20-treasure version (rev 2) by Don Woods, August 1978
* History: Original idea & 5-treasure version (adventures) by Willie Crowther
* 15-treasure version (adventure) by Don Woods, April-June 1977
* 20-treasure version (rev 2) by Don Woods, August 1978
@@
-70,11
+61,11
@@
int main(int argc, char *argv[])
/* Options. */
#ifndef ADVENT_NOSAVE
/* Options. */
#ifndef ADVENT_NOSAVE
- const char* opts = "l:or
:s
";
- const char* usage = "Usage: %s [-l logfilename] [-o] [-r restorefilename]
[-s]
\n";
+ const char* opts = "l:or";
+ const char* usage = "Usage: %s [-l logfilename] [-o] [-r restorefilename]\n";
#else
#else
- const char* opts = "l:o
s
";
- const char* usage = "Usage: %s [-l logfilename] [-o]
[-s]
\n";
+ const char* opts = "l:o";
+ const char* usage = "Usage: %s [-l logfilename] [-o]\n";
#endif
while ((ch = getopt(argc, argv, opts)) != EOF) {
switch (ch) {
#endif
while ((ch = getopt(argc, argv, opts)) != EOF) {
switch (ch) {
@@
-88,7
+79,7
@@
int main(int argc, char *argv[])
break;
case 'o':
oldstyle = true;
break;
case 'o':
oldstyle = true;
-
editline =
prompt = false;
+ prompt = false;
break;
#ifndef ADVENT_NOSAVE
case 'r':
break;
#ifndef ADVENT_NOSAVE
case 'r':
@@
-100,9
+91,6
@@
int main(int argc, char *argv[])
signal(SIGINT, sig_handler);
break;
#endif
signal(SIGINT, sig_handler);
break;
#endif
- case 's':
- editline = false;
- break;
default:
fprintf(stderr,
usage, argv[0]);
default:
fprintf(stderr,
usage, argv[0]);
@@
-114,32
+102,18
@@
int main(int argc, char *argv[])
fprintf(stderr,
" -r restore from specified saved game file\n");
#endif
fprintf(stderr,
" -r restore from specified saved game file\n");
#endif
- fprintf(stderr,
- " -s suppress command editing\n");
- exit(-1);
+ exit(EXIT_FAILURE);
break;
}
}
break;
}
}
- linenoiseHistorySetMaxLen(350);
-
- /* Initialize our LCG PRNG with parameters tested against
- * Knuth vol. 2. by the original authors */
- game.lcg_a = 1093;
- game.lcg_c = 221587;
- game.lcg_m = 1048576;
- srand(time(NULL));
- long seedval = (long)rand();
- set_seed(seedval);
-
/* Initialize game variables */
/* Initialize game variables */
- initialise();
+
long seedval =
initialise();
/* Start-up, dwarf stuff */
make_zzword(game.zzword);
/* Start-up, dwarf stuff */
make_zzword(game.zzword);
- game.newloc = LOC_START;
- game.loc = LOC_START;
- game.limit = GAMELIMIT;
+
+#ifndef ADVENT_NOSAVE
if (!rfp) {
game.novice = yes(arbitrary_messages[WELCOME_YOU], arbitrary_messages[CAVE_NEARBY], arbitrary_messages[NO_MESSAGE]);
if (game.novice)
if (!rfp) {
game.novice = yes(arbitrary_messages[WELCOME_YOU], arbitrary_messages[CAVE_NEARBY], arbitrary_messages[NO_MESSAGE]);
if (game.novice)
@@
-147,6
+121,7
@@
int main(int argc, char *argv[])
} else {
restore(rfp);
}
} else {
restore(rfp);
}
+#endif
if (logfp)
fprintf(logfp, "seed %ld\n", seedval);
if (logfp)
fprintf(logfp, "seed %ld\n", seedval);
@@
-374,9
+349,12
@@
static bool dwarfmove(void)
if (PCT(50))
game.dloc[j] = 0;
}
if (PCT(50))
game.dloc[j] = 0;
}
+
+ /* Alternate initial loc for dwarf, in case one of them
+ * starts out on top of the adventurer. */
for (int i = 1; i <= NDWARVES - 1; i++) {
if (game.dloc[i] == game.loc)
for (int i = 1; i <= NDWARVES - 1; i++) {
if (game.dloc[i] == game.loc)
- game.dloc[i] = DALTLC;
+ game.dloc[i] = DALTLC;
//
game.odloc[i] = game.dloc[i];
}
rspeak(DWARF_RAN);
game.odloc[i] = game.dloc[i];
}
rspeak(DWARF_RAN);
@@
-401,7
+379,7
@@
static bool dwarfmove(void)
kk = tkey[game.dloc[i]];
if (kk != 0)
do {
kk = tkey[game.dloc[i]];
if (kk != 0)
do {
- game.newloc =
T_DESTINATION(travel[kk])
;
+ game.newloc =
travel[kk].dest
;
/* Have we avoided a dwarf encounter? */
bool avoided = (SPECIAL(game.newloc) ||
!INDEEP(game.newloc) ||
/* Have we avoided a dwarf encounter? */
bool avoided = (SPECIAL(game.newloc) ||
!INDEEP(game.newloc) ||
@@
-513,6
+491,13
@@
static void croak(void)
}
}
}
}
+static bool traveleq(long a, long b)
+/* Are two travel entries equal for purposes of skip after failed condition? */
+{
+ return (travel[a].cond == travel[b].cond)
+ && (travel[a].dest == travel[b].dest);
+}
+
/* Given the current location in "game.loc", and a motion verb number in
* "motion", put the new location in "game.newloc". The current loc is saved
* in "game.oldloc" in case he wants to retreat. The current
/* Given the current location in "game.loc", and a motion verb number in
* "motion", put the new location in "game.newloc". The current loc is saved
* in "game.oldloc" in case he wants to retreat. The current
@@
-521,7
+506,7
@@
static void croak(void)
* him, so we need game.oldlc2, which is the last place he was
* safe.) */
* him, so we need game.oldlc2, which is the last place he was
* safe.) */
-static bool playermove(
token_t verb,
int motion)
+static bool playermove( int motion)
{
int scratchloc, travel_entry = tkey[game.loc];
game.newloc = game.loc;
{
int scratchloc, travel_entry = tkey[game.loc];
game.newloc = game.loc;
@@
-546,10
+531,10
@@
static bool playermove(token_t verb, int motion)
if (spk == 0) {
int te_tmp = 0;
for (;;) {
if (spk == 0) {
int te_tmp = 0;
for (;;) {
- scratchloc =
T_DESTINATION(travel[travel_entry])
;
+ scratchloc =
travel[travel_entry].dest
;
if (scratchloc != motion) {
if (!SPECIAL(scratchloc)) {
if (scratchloc != motion) {
if (!SPECIAL(scratchloc)) {
- if (FORCED(scratchloc) &&
T_DESTINATION(travel[tkey[scratchloc]])
== motion)
+ if (FORCED(scratchloc) &&
travel[tkey[scratchloc]].dest
== motion)
te_tmp = travel_entry;
}
if (!travel[travel_entry].stop) {
te_tmp = travel_entry;
}
if (!travel[travel_entry].stop) {
@@
-598,23
+583,20
@@
static bool playermove(token_t verb, int motion)
if (T_TERMINATE(travel[travel_entry]) || travel[travel_entry].motion == motion)
break;
if (travel[travel_entry].stop) {
if (T_TERMINATE(travel[travel_entry]) || travel[travel_entry].motion == motion)
break;
if (travel[travel_entry].stop) {
- /* FIXME: Magic numbers! */
/* Couldn't find an entry matching the motion word passed
* in. Various messages depending on word given. */
int spk = CANT_APPLY;
/* Couldn't find an entry matching the motion word passed
* in. Various messages depending on word given. */
int spk = CANT_APPLY;
- if (motion >=
43 && motion <= 50
)
+ if (motion >=
EAST && motion <= NW
)
spk = BAD_DIRECTION;
spk = BAD_DIRECTION;
- if (motion ==
29 || motion == 30
)
+ if (motion ==
UP || motion == DOWN
)
spk = BAD_DIRECTION;
spk = BAD_DIRECTION;
- if (motion ==
7 || motion == 36 || motion == 37
)
+ if (motion ==
FORWARD || motion == LEFT || motion == RIGHT
)
spk = UNSURE_FACING;
spk = UNSURE_FACING;
- if (motion ==
11 || motion == 19
)
+ if (motion ==
OUTSIDE || motion == INSIDE
)
spk = NO_INOUT_HERE;
spk = NO_INOUT_HERE;
- if (verb == FIND || verb == INVENTORY)
- spk = NEARBY;
- if (motion == 62 || motion == 65)
+ if (motion == XYZZY || motion == PLUGH)
spk = NOTHING_HAPPENS;
spk = NOTHING_HAPPENS;
- if (motion ==
17
)
+ if (motion ==
CRAWL
)
spk = WHICH_WAY;
rspeak(spk);
return true;
spk = WHICH_WAY;
rspeak(spk);
return true;
@@
-625,10
+607,11
@@
static bool playermove(token_t verb, int motion)
/* (ESR) We've found a destination that goes with the motion verb.
* Next we need to check any conditional(s) on this destination, and
* possibly on following entries. */
/* (ESR) We've found a destination that goes with the motion verb.
* Next we need to check any conditional(s) on this destination, and
* possibly on following entries. */
+ /* FIXME: Magic numbers related to move opcodes */
do {
for (;;) { /* L12 loop */
for (;;) {
do {
for (;;) { /* L12 loop */
for (;;) {
- long cond =
T_CONDITION(travel[travel_entry])
;
+ long cond =
travel[travel_entry].cond
;
long arg = MOD(cond, 100);
if (!SPECIAL(cond)) {
/* YAML N and [pct N] conditionals */
long arg = MOD(cond, 100);
if (!SPECIAL(cond)) {
/* YAML N and [pct N] conditionals */
@@
-652,12
+635,12
@@
static bool playermove(token_t verb, int motion)
BUG(CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION); // LCOV_EXCL_LINE
++te_tmp;
} while
BUG(CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION); // LCOV_EXCL_LINE
++te_tmp;
} while
-
(T_HIGH(travel[travel_entry]) == T_HIGH(travel[te_tmp]
));
+
(traveleq(travel_entry, te_tmp
));
travel_entry = te_tmp;
}
/* Found an eligible rule, now execute it */
travel_entry = te_tmp;
}
/* Found an eligible rule, now execute it */
- game.newloc =
T_DESTINATION(travel[travel_entry])
;
+ game.newloc =
travel[travel_entry].dest
;
if (!SPECIAL(game.newloc))
return true;
if (!SPECIAL(game.newloc))
return true;
@@
-694,7
+677,7
@@
static bool playermove(token_t verb, int motion)
BUG(CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION); // LCOV_EXCL_LINE
++te_tmp;
} while
BUG(CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION); // LCOV_EXCL_LINE
++te_tmp;
} while
-
(T_HIGH(travel[travel_entry]) == T_HIGH(travel[te_tmp]
));
+
(traveleq(travel_entry, te_tmp
));
travel_entry = te_tmp;
continue; /* goto L12 */
case 3:
travel_entry = te_tmp;
continue; /* goto L12 */
case 3:
@@
-707,8
+690,8
@@
static bool playermove(token_t verb, int motion)
* so step out and block him. (standard travel
* entries check for game.prop(TROLL)=0.) Special
* stuff for bear. */
* so step out and block him. (standard travel
* entries check for game.prop(TROLL)=0.) Special
* stuff for bear. */
- if (game.prop[TROLL] ==
1
) {
- pspeak(TROLL, look,
1
);
+ if (game.prop[TROLL] ==
TROLL_PAIDONCE
) {
+ pspeak(TROLL, look,
TROLL_PAIDONCE
);
game.prop[TROLL] = 0;
move(TROLL2, 0);
move(TROLL2 + NOBJECTS, 0);
game.prop[TROLL] = 0;
move(TROLL2, 0);
move(TROLL2 + NOBJECTS, 0);
@@
-719,13
+702,13
@@
static bool playermove(token_t verb, int motion)
return true;
} else {
game.newloc = objects[TROLL].plac + objects[TROLL].fixd - game.loc;
return true;
} else {
game.newloc = objects[TROLL].plac + objects[TROLL].fixd - game.loc;
- if (game.prop[TROLL] ==
0
)
- game.prop[TROLL] =
1
;
+ if (game.prop[TROLL] ==
TROLL_UNPAID
)
+ game.prop[TROLL] =
TROLL_PAIDONCE
;
if (!TOTING(BEAR))
return true;
rspeak(BRIDGE_COLLAPSE);
if (!TOTING(BEAR))
return true;
rspeak(BRIDGE_COLLAPSE);
- game.prop[CHASM] =
1
;
- game.prop[TROLL] =
2
;
+ game.prop[CHASM] =
BRIDGE_WRECKED
;
+ game.prop[TROLL] =
TROLL_GONE
;
drop(BEAR, game.newloc);
game.fixed[BEAR] = -1;
game.prop[BEAR] = BEAR_DEAD;
drop(BEAR, game.newloc);
game.fixed[BEAR] = -1;
game.prop[BEAR] = BEAR_DEAD;
@@
-781,7
+764,7
@@
static bool closecheck(void)
* have been activated, since we've found chest. */
if (game.clock1 == 0) {
game.prop[GRATE] = GRATE_CLOSED;
* have been activated, since we've found chest. */
if (game.clock1 == 0) {
game.prop[GRATE] = GRATE_CLOSED;
- game.prop[FISSURE] =
0
;
+ game.prop[FISSURE] =
UNBRIDGED
;
for (int i = 1; i <= NDWARVES; i++) {
game.dseen[i] = false;
game.dloc[i] = 0;
for (int i = 1; i <= NDWARVES; i++) {
game.dseen[i] = false;
game.dloc[i] = 0;
@@
-793,8
+776,8
@@
static bool closecheck(void)
juggle(CHASM);
if (game.prop[BEAR] != BEAR_DEAD)
DESTROY(BEAR);
juggle(CHASM);
if (game.prop[BEAR] != BEAR_DEAD)
DESTROY(BEAR);
- game.prop[CHAIN] =
0
;
- game.fixed[CHAIN] =
0
;
+ game.prop[CHAIN] =
CHAIN_HEAP
;
+ game.fixed[CHAIN] =
CHAIN_HEAP
;
game.prop[AXE] = 0;
game.fixed[AXE] = 0;
rspeak(CAVE_CLOSING);
game.prop[AXE] = 0;
game.fixed[AXE] = 0;
rspeak(CAVE_CLOSING);
@@
-896,8
+879,8
@@
static void listobjects(void)
/* Print out descriptions of objects at this location. If
* not closing and property value is negative, tally off
* another treasure. Rug is special case; once seen, its
/* Print out descriptions of objects at this location. If
* not closing and property value is negative, tally off
* another treasure. Rug is special case; once seen, its
- * game.prop is
1
(dragon on it) till dragon is killed.
- * Similarly for chain; game.prop is initially
1
(locked to
+ * game.prop is
RUG_DRAGON
(dragon on it) till dragon is killed.
+ * Similarly for chain; game.prop is initially
CHAINING_BEAR
(locked to
* bear). These hacks are because game.prop=0 is needed to
* get full score. */
{
* bear). These hacks are because game.prop=0 is needed to
* get full score. */
{
@@
-913,8
+896,10
@@
static void listobjects(void)
if (game.closed)
continue;
game.prop[obj] = 0;
if (game.closed)
continue;
game.prop[obj] = 0;
- if (obj == RUG || obj == CHAIN)
- game.prop[obj] = 1;
+ if (obj == RUG)
+ game.prop[RUG] = RUG_DRAGON;
+ if (obj == CHAIN)
+ game.prop[CHAIN] = CHAINING_BEAR;
--game.tally;
/* Note: There used to be a test here to see whether the
* player had blown it so badly that he could never ever see
--game.tally;
/* Note: There used to be a test here to see whether the
* player had blown it so badly that he could never ever see
@@
-998,7
+983,7
@@
static bool do_command()
rspeak(TAME_BEAR);
speak(msg);
if (FORCED(game.loc)) {
rspeak(TAME_BEAR);
speak(msg);
if (FORCED(game.loc)) {
- if (playermove(
command.verb, 1
))
+ if (playermove(
HERE
))
return true;
else
continue; /* back to top of main interpreter loop */
return true;
else
continue; /* back to top of main interpreter loop */
@@
-1035,6
+1020,8
@@
L2600:
/* This is where we get a new command from the user */
char* input;
/* This is where we get a new command from the user */
char* input;
+ char inputbuf[LINESIZE];
+
for (;;) {
input = get_input();
if (input == NULL)
for (;;) {
input = get_input();
if (input == NULL)
@@
-1046,8
+1033,12
@@
L2600:
if (strcmp(input, "") != 0)
break;
}
if (strcmp(input, "") != 0)
break;
}
+
+ strncpy(inputbuf, input, LINESIZE - 1);
+ free(input);
+
long tokens[4];
long tokens[4];
- tokenize(input, tokens);
+ tokenize(input
buf
, tokens);
command.wd1 = tokens[0];
command.wd1x = tokens[1];
command.wd2 = tokens[2];
command.wd1 = tokens[0];
command.wd1x = tokens[1];
command.wd2 = tokens[2];
@@
-1100,13
+1091,13
@@
L2607:
command.wd1x = command.wd2x;
wordclear(&command.wd2);
} else {
command.wd1x = command.wd2x;
wordclear(&command.wd2);
} else {
- /* FIXME: Magic numbers */
- if (!((V1 !=
1000 + WATER && V1 != 1000 + OIL
) ||
- (V2 !=
1000 + PLANT && V2 != 1000 + DOOR
))) {
- if (AT(
V2 - 1000
))
+ /* FIXME: Magic numbers
related to vocabulary
*/
+ if (!((V1 !=
PROMOTE_WORD(WATER) && V1 != PROMOTE_WORD(OIL)
) ||
+ (V2 !=
PROMOTE_WORD(PLANT) && V2 != PROMOTE_WORD(DOOR)
))) {
+ if (AT(
DEMOTE_WORD(V2)
))
command.wd2 = token_to_packed("POUR");
}
command.wd2 = token_to_packed("POUR");
}
- if (V1 ==
1000 + CAGE && V2 == 1000 + BIRD
&& HERE(CAGE) && HERE(BIRD))
+ if (V1 ==
PROMOTE_WORD(CAGE) && V2 == PROMOTE_WORD(BIRD)
&& HERE(CAGE) && HERE(BIRD))
command.wd1 = token_to_packed("CATCH");
}
L2620:
command.wd1 = token_to_packed("CATCH");
}
L2620:
@@
-1124,15
+1115,16
@@
Lookup:
defn = get_vocab_id(word1);
if (defn == -1) {
/* Gee, I don't understand. */
defn = get_vocab_id(word1);
if (defn == -1) {
/* Gee, I don't understand. */
- if (fallback_handler(input))
+ if (fallback_handler(input
buf
))
continue;
rspeak(DONT_KNOW, command.wd1, command.wd1x);
goto L2600;
}
continue;
rspeak(DONT_KNOW, command.wd1, command.wd1x);
goto L2600;
}
+ /* FIXME: magic numbers related to vocabulary */
kmod = MOD(defn, 1000);
switch (defn / 1000) {
case 0:
kmod = MOD(defn, 1000);
switch (defn / 1000) {
case 0:
- if (playermove(
command.verb,
kmod))
+ if (playermove(kmod))
return true;
else
continue; /* back to top of main interpreter loop */
return true;
else
continue; /* back to top of main interpreter loop */
@@
-1145,7
+1137,7
@@
Lookup:
command.verb = kmod;
break;
case 3:
command.verb = kmod;
break;
case 3:
-
r
speak(specials[kmod].message);
+ speak(specials[kmod].message);
goto L2012;
default:
BUG(VOCABULARY_TYPE_N_OVER_1000_NOT_BETWEEN_0_AND_3); // LCOV_EXCL_LINE
goto L2012;
default:
BUG(VOCABULARY_TYPE_N_OVER_1000_NOT_BETWEEN_0_AND_3); // LCOV_EXCL_LINE
@@
-1156,7
+1148,7
@@
Laction:
case GO_TERMINATE:
return true;
case GO_MOVE:
case GO_TERMINATE:
return true;
case GO_MOVE:
- playermove(
command.verb,
NUL);
+ playermove(NUL);
return true;
case GO_TOP:
continue; /* back to top of main interpreter loop */
return true;
case GO_TOP:
continue; /* back to top of main interpreter loop */
@@
-1187,7
+1179,6
@@
Laction:
default:
BUG(ACTION_RETURNED_PHASE_CODE_BEYOND_END_OF_SWITCH); // LCOV_EXCL_LINE
}
default:
BUG(ACTION_RETURNED_PHASE_CODE_BEYOND_END_OF_SWITCH); // LCOV_EXCL_LINE
}
- linenoiseFree(input);
}
}
}
}