*.o
*.html
database.h
-database.c
advent.6
*.tar.gz
MANIFEST
*.adv
+.*~
newdb.h
newdb.c
#
# To build with save/resume disabled, pass CCFLAGS="-D ADVENT_NOSAVE"
+.PHONY: debug indent release refresh dist linty html clean
+
VERS=1.0
CC?=gcc
dist: advent-$(VERS).tar.gz
-linty: CCFLAGS += -W -Wall -Wextra -Wundef -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshadow -Wfloat-equal -Wcast-align -Wwrite-strings -Waggregate-return -Wcast-qual -Wswitch-enum -Wwrite-strings -Wunreachable-code -Winit-self -Wpointer-arith -O2
+linty: CCFLAGS += -W
+linty: CCFLAGS += -Wall
+linty: CCFLAGS += -Wextra
+linty: CCFLAGS += -Wundef
+linty: CCFLAGS += -Wstrict-prototypes
+linty: CCFLAGS += -Wmissing-prototypes
+linty: CCFLAGS += -Wmissing-declarations
+linty: CCFLAGS += -Wshadow
+linty: CCFLAGS += -Wfloat-equal
+linty: CCFLAGS += -Wcast-align
+linty: CCFLAGS += -Wwrite-strings
+linty: CCFLAGS += -Waggregate-return
+linty: CCFLAGS += -Wcast-qual
+linty: CCFLAGS += -Wswitch-enum
+linty: CCFLAGS += -Wwrite-strings
+linty: CCFLAGS += -Wunreachable-code
+linty: CCFLAGS += -Winit-self
+linty: CCFLAGS += -Wpointer-arith
+linty: CCFLAGS +=-O2
linty: advent
debug: CCFLAGS += -O0 --coverage -g
}
}
-static int quit(FILE *input)
+static int quit(void)
/* Quit. Intransitive only. Verify intent and exit if that's what he wants. */
{
if (YES(REALLY_QUIT, OK_MAN, OK_MAN))
return GO_CLEAROBJ;
}
-static int read(FILE *input, token_t verb, token_t obj)
+static int read(token_t verb, token_t obj)
/* Read. Print stuff based on objtxt. Oyster (?) is special case. */
{
int spk = ACTSPK[verb];
case 16: /* TOSS */
return GO_UNKNOWN;
case 17: /* QUIT */
- return quit(input);
+ return quit();
case 18: /* FIND */
return GO_UNKNOWN;
case 19: /* INVEN */
case 25: /* BRIEF */
return brief();
case 26: /* READ */
- return read(input, verb, INTRANSITIVE);
+ return read(verb, INTRANSITIVE);
case 27: /* BREAK */
return GO_UNKNOWN;
case 28: /* WAKE */
return GO_UNKNOWN;
case 29: /* SUSP */
- return suspend(input);
+ return suspend();
case 30: /* RESU */
- return resume(input);
+ return resume();
case 31: /* FLY */
return fly(verb, INTRANSITIVE);
case 32: /* LISTE */
case 33: /* ZZZZ */
return reservoir();
}
- BUG(23);
+ BUG(INTRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST);
}
/* FALLTHRU */
case transitive:
return GO_CLEAROBJ;
}
case 26: /* READ */
- return read(input, verb, obj);
+ return read(verb, obj);
case 27: /* BREAK */
return vbreak(verb, obj);
case 28: /* WAKE */
case 33: /* ZZZZ */
return reservoir();
}
- BUG(24);
+ BUG(TRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST);
case unknown:
/* Unknown verb, couldn't deduce object - might need hint */
SETPRM(1, WD1, WD1X);
RSPEAK(WHAT_DO);
return GO_CHECKHINT;
default:
- BUG(99);
+ BUG(SPEECHPART_NOT_TRANSITIVE_OR_INTRANSITIVE_OR_UNKNOWN);
}
}
#include <stdio.h>
+#include <stdlib.h>
#include <stdbool.h>
#include "common.h"
extern long SETBIT(long);
extern bool TSTBIT(long,int);
extern long RNDVOC(long,long);
-extern void BUG(long) __attribute__((noreturn));
extern bool MAPLIN(FILE *);
extern void DATIME(long*, long*);
extern long randrange(long);
extern long score(enum termination);
extern void terminate(enum termination) __attribute__((noreturn));
-extern int suspend(FILE *);
-extern int resume(FILE *);
+extern int suspend(void);
+extern int resume(void);
extern int restore(FILE *);
/*
+#include <stdlib.h>
+#include <stdio.h>
#include "common.h"
const char advent_to_ascii[] = {
+#ifndef COMMON_H
+#define COMMON_H
/* maximum size limits shared by dungeon compiler and runtime */
#define LOCSIZ 185
extern const char advent_to_ascii[128];
extern const char ascii_to_advent[128];
+
+enum bug_e {
+ MESSAGE_LINE_GT_70_CHARACTERS, // 0
+ NULL_LINE_IN_MESSAGE, // 1
+ TOO_MANY_WORDS_OF_MESSAGES, // 2
+ TOO_MANY_TRAVEL_OPTIONS, // 3
+ TOO_MANY_VOCABULARY_WORDS, // 4
+ REQUIRED_VOCABULARY_WORD_NOT_FOUND, // 5
+ TOO_MANY_RTEXT_MESSAGES, // 6
+ TOO_MANY_HINTS, // 7
+ LOCATION_HAS_CONDITION_BIT_BEING_SET_TWICE, // 8
+ INVALID_SECTION_NUMBER_IN_DATABASE, // 9
+ TOO_MANY_LOCATIONS, // 10
+ TOO_MANY_CLASS_OR_TURN_MESSAGES, // 11
+ SPECIAL_TRAVEL_500_GT_L_GT_300_EXCEEDS_GOTO_LIST = 20, // 20
+ RAN_OFF_END_OF_VOCABULARY_TABLE, // 21
+ VOCABULARY_TYPE_N_OVER_1000_NOT_BETWEEN_0_AND_3, // 22
+ INTRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST, // 23
+ TRANSITIVE_ACTION_VERB_EXCEEDS_GOTO_LIST, // 24
+ CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION, // 25
+ LOCATION_HAS_NO_TRAVEL_ENTRIES, // 26
+ HINT_NUMBER_EXCEEDS_GOTO_LIST, // 27
+ INVALID_MOTH_RETURNED_BY_DATA_FUNCTION, // 28
+ TOO_MANY_PARAMETERS_GIVEN_TO_SETPRM, // 29
+ SPEECHPART_NOT_TRANSITIVE_OR_INTRANSITIVE_OR_UNKNOWN=99, // 99
+ ACTION_RETURNED_PHASE_CODE_BEYOND_END_OF_SWITCH, // 100
+};
+
+static inline void bug(enum bug_e num, const char *error_string) __attribute__((__noreturn__));
+static inline void bug(enum bug_e num, const char *error_string)
+{
+ fprintf(stderr, "Fatal error %d, %s.\n", num, error_string);
+ exit(EXIT_FAILURE);
+}
+
+#define BUG(x) bug(x, #x)
+
+#endif
* defining (mostly) invariant state. A couple of slots are messed with
* at runtime.
*/
-#include "common.h"
#define LINESIZE 100
#define RTXSIZ 277
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
+#include "common.h"
// Global variables for use in functions below that can gradually disappear as code is cleaned up
static long LNLENG;
return (TEXT);
}
-static void BUG(long NUM)
-{
-
- /* The following conditions are currently considered fatal bugs. Numbers < 20
- * are detected while reading the database; the others occur at "run time".
- * 0 Message line > 70 characters
- * 1 Null line in message
- * 2 Too many words of messages
- * 3 Too many travel options
- * 4 Too many vocabulary words
- * 5 Required vocabulary word not found
- * 6 Too many RTEXT messages
- * 7 Too many hints
- * 8 Location has cond bit being set twice
- * 9 Invalid section number in database
- * 10 Too many locations
- * 11 Too many class or turn messages
- * 20 Special travel (500>L>300) exceeds goto list
- * 21 Ran off end of vocabulary table
- * 22 Vocabulary type (N/1000) not between 0 and 3
- * 23 Intransitive action verb exceeds goto list
- * 24 Transitive action verb exceeds goto list
- * 25 Conditional travel entry with no alternative
- * 26 Location has no travel entries
- * 27 Hint number exceeds goto list
- * 28 Invalid month returned by date function
- * 29 Too many parameters given to SETPRM */
-
- fprintf(stderr, "Fatal error %ld. See source code for interpretation.\n", NUM);
- exit(EXIT_FAILURE);
-}
-
static void MAPLIN(FILE *OPENED)
{
/* Read a line of input, from the specified input source,
long loc;
LINUSE = KK;
loc = GETNUM(database);
- if (LNLENG >= LNPOSN + 70)BUG(0);
+ if (LNLENG >= LNPOSN + 70)
+ BUG(MESSAGE_LINE_GT_70_CHARACTERS);
if (loc == -1) return;
- if (LNLENG < LNPOSN)BUG(1);
+ if (LNLENG < LNPOSN)
+ BUG(NULL_LINE_IN_MESSAGE);
do {
KK = KK + 1;
- if (KK >= LINSIZ)BUG(2);
+ if (KK >= LINSIZ)
+ BUG(TOO_MANY_WORDS_OF_MESSAGES);
LINES[KK] = GETTXT(false, false, false);
} while (LINES[KK] != -1);
LINES[LINUSE] = KK;
LINES[LINUSE] = -KK;
if (sect == 14) {
TRNVLS = TRNVLS + 1;
- if (TRNVLS > TRNSIZ)BUG(11);
+ if (TRNVLS > TRNSIZ)
+ BUG(TOO_MANY_CLASS_OR_TURN_MESSAGES);
TTEXT[TRNVLS] = LINUSE;
TRNVAL[TRNVLS] = loc;
continue;
}
if (sect == 10) {
CLSSES = CLSSES + 1;
- if (CLSSES > CLSMAX)BUG(11);
+ if (CLSSES > CLSMAX)
+ BUG(TOO_MANY_CLASS_OR_TURN_MESSAGES);
CTEXT[CLSSES] = LINUSE;
CVAL[CLSSES] = loc;
continue;
}
if (sect == 6) {
- if (loc > RTXSIZ)BUG(6);
+ if (loc > RTXSIZ)
+ BUG(TOO_MANY_RTEXT_MESSAGES);
RTEXT[loc] = LINUSE;
continue;
}
if (loc > 0 && loc <= NOBJECTS)PTEXT[loc] = LINUSE;
continue;
}
- if (loc > LOCSIZ)BUG(10);
+ if (loc > LOCSIZ)
+ BUG(TOO_MANY_LOCATIONS);
if (sect == 1) {
LTEXT[loc] = LINUSE;
continue;
while ((L = GETNUM(NULL)) != 0) {
TRAVEL[TRVS] = newloc * 1000 + L;
TRVS = TRVS + 1;
- if (TRVS == TRVSIZ)BUG(3);
+ if (TRVS == TRVSIZ)
+ BUG(TOO_MANY_TRAVEL_OPTIONS);
}
TRAVEL[TRVS - 1] = -TRAVEL[TRVS - 1];
}
if (KTAB[TABNDX] == -1) return;
ATAB[TABNDX] = GETTXT(true, true, true);
} /* end loop */
- BUG(4);
+ BUG(TOO_MANY_VOCABULARY_WORDS);
}
/* Read in the initial locations for each object. Also the immovability info.
while ((K = GETNUM(database)) != -1) {
long loc;
while ((loc = GETNUM(NULL)) != 0) {
- if (is_set(COND[loc], K)) BUG(8);
+ if (is_set(COND[loc], K))
+ BUG(LOCATION_HAS_CONDITION_BIT_BEING_SET_TWICE);
COND[loc] = COND[loc] + (1l << K);
}
}
long K;
HNTMAX = 0;
while ((K = GETNUM(database)) != -1) {
- if (K <= 0 || K > HNTSIZ)BUG(7);
+ if (K <= 0 || K > HNTSIZ)
+ BUG(TOO_MANY_HINTS);
for (int I = 1; I <= 4; I++) {
HINTS[K][I] = GETNUM(NULL);
} /* end loop */
read_messages(database, sect);
break;
default:
- BUG(9);
+ BUG(INVALID_SECTION_NUMBER_IN_DATABASE);
}
}
}
* 15-treasure version (adventure) by Don Woods, April-June 1977
* 20-treasure version (rev 2) by Don Woods, August 1978
* Errata fixed: 78/12/25
- * Revived 2017 as Open Advebture.
+ * Revived 2017 as Open Adventure.
*/
static bool do_command(FILE *);
case 's':
editline = false;
break;
+ default:
+ fprintf(stderr,
+ "Usage: %s [-l logfilename] [-o] [-r restorefilename] [-s] \n", argv[0]);
+ fprintf(stderr,
+ " where -l creates a log file of your game named as specified'\n");
+ fprintf(stderr,
+ " -o 'oldstyle' (no prompt, no command editing, displays 'Initialising...')\n");
+ fprintf(stderr,
+ " -r indicates restoring from specified saved game file\n");
+ fprintf(stderr,
+ " -s indicates playing with command editing suppressed\n");
+ exit(-1);
+ break;
}
}
* all come back here eventually to finish the loop. Ignore
* "HINTS" < 4 (special stuff, see database notes).
*/
-static void checkhints(FILE *cmdin)
+static void checkhints(void)
{
if (COND[game.loc] >= game.conds) {
for (int hint = 1; hint <= HNTMAX; hint++) {
game.hintlc[hint] = 0;
return;
default:
- BUG(27);
+ BUG(HINT_NUMBER_EXCEEDS_GOTO_LIST);
break;
}
* without the lamp!). game.oldloc is zapped so he can't just
* "retreat". */
-static void croak(FILE *cmdin)
+static void croak(void)
/* Okay, he's dead. Let's get on with it. */
{
++game.numdie;
* him, so we need game.oldlc2, which is the last place he was
* safe.) */
-static bool playermove(FILE *cmdin, token_t verb, int motion)
+static bool playermove(token_t verb, int motion)
{
int scratchloc, k2, kk = KEY[game.loc];
game.newloc = game.loc;
if (kk == 0)
- BUG(26);
+ BUG(LOCATION_HAS_NO_TRAVEL_ENTRIES);
if (motion == NUL)
return true;
else if (motion == BACK) {
break;
L12:
do {
- if (TRAVEL[kk] < 0)BUG(25);
+ if (TRAVEL[kk] < 0)
+ BUG(CONDITIONAL_TRAVEL_ENTRY_WITH_NO_ALTERATION);
++kk;
game.newloc = labs(TRAVEL[kk]) / 1000;
} while
game.fixed[BEAR] = -1;
game.prop[BEAR] = 3;
game.oldlc2 = game.newloc;
- croak(cmdin);
+ croak();
}
}
- BUG(20);
+ BUG(SPECIAL_TRAVEL_500_GT_L_GT_300_EXCEEDS_GOTO_LIST);
}
} while
(false);
game.loc = game.newloc;
if (!dwarfmove())
- croak(cmdin);
+ croak();
/* Describe the current location and (maybe) get next command. */
for (;;) {
if (game.loc == 0)
- croak(cmdin);
+ croak();
const char* msg = locations[game.loc].description.small;
if (MOD(game.abbrev[game.loc], game.abbnum) == 0 || msg == 0)
msg = locations[game.loc].description.big;
if (game.wzdark && PCT(35)) {
RSPEAK(PIT_FALL);
game.oldlc2 = game.loc;
- croak(cmdin);
+ croak();
continue; /* back to top of main interpreter loop */
}
msg = arbitrary_messages[PITCH_DARK];
if (TOTING(BEAR))RSPEAK(TAME_BEAR);
speak(msg);
if (FORCED(game.loc)) {
- if (playermove(cmdin, verb, 1))
+ if (playermove(verb, 1))
return true;
else
continue; /* back to top of main interpreter loop */
obj = 0;
L2600:
- checkhints(cmdin);
+ checkhints();
/* If closing time, check for any objects being toted with
* game.prop < 0 and set the prop to -1-game.prop. This way
kmod = MOD(defn, 1000);
switch (defn / 1000) {
case 0:
- if (playermove(cmdin, verb, kmod))
+ if (playermove(verb, kmod))
return true;
else
continue; /* back to top of main interpreter loop */
RSPEAK(kmod);
goto L2012;
default:
- BUG(22);
+ BUG(VOCABULARY_TYPE_N_OVER_1000_NOT_BETWEEN_0_AND_3);
}
Laction:
case GO_TERMINATE:
return true;
case GO_MOVE:
- playermove(cmdin, verb, NUL);
+ playermove(verb, NUL);
return true;
case GO_TOP:
continue; /* back to top of main interpreter loop */
RSPEAK(DWARVES_AWAKEN);
terminate(endgame);
default:
- BUG(99);
+ BUG(ACTION_RETURNED_PHASE_CODE_BEYOND_END_OF_SWITCH);
}
}
}
* are stored into PARMS(first) and PARMS(first+1). */
{
if (first >= MAXPARMS)
- BUG(29);
+ BUG(TOO_MANY_PARAMETERS_GIVEN_TO_SETPRM);
else {
PARMS[first] = p1;
PARMS[first + 1] = p2;
size_t n = 0;
if (isatty(0))
printf("%s", input_prompt);
- getline(&input, &n, stdin);
+ IGNORE(getline(&input, &n, stdin));
}
if (input == NULL) // Got EOF; quit.
char* firstword = (char*) xmalloc(strlen(reply));
sscanf(reply, "%s", firstword);
- for (int i = 0; i < strlen(firstword); ++i)
+ for (int i = 0; i < (int)strlen(firstword); ++i)
firstword[i] = tolower(firstword[i]);
int yes = strncmp("yes", firstword, sizeof("yes") - 1);
lexeme = -1;
if (init < 0)
return (lexeme);
- BUG(5);
+ BUG(REQUIRED_VOCABULARY_WORD_NOT_FOUND);
}
if (init >= 0 && KTAB[i] / 1000 != init)
continue;
return (lexeme);
}
}
- BUG(21);
+ BUG(RAN_OFF_END_OF_VOCABULARY_TABLE);
}
void JUGGLE(long object)
}
/* Utility routines (SETBIT, TSTBIT, set_seed, get_next_lcg_value,
- * randrange, RNDVOC, BUG) */
+ * randrange, RNDVOC) */
long SETBIT(long bit)
/* Returns 2**bit for use in constructing bit-masks. */
return rnd;
}
-void BUG(long num)
-/* The following conditions are currently considered fatal bugs. Numbers < 20
- * are detected while reading the database; the others occur at "run time".
- * 0 Message line > 70 characters
- * 1 Null line in message
- * 2 Too many words of messages
- * 3 Too many travel options
- * 4 Too many vocabulary words
- * 5 Required vocabulary word not found
- * 6 Too many RTEXT messages
- * 7 Too many hints
- * 8 Location has cond bit being set twice
- * 9 Invalid section number in database
- * 10 Too many locations
- * 11 Too many class or turn messages
- * 20 Special travel (500>L>300) exceeds goto list
- * 21 Ran off end of vocabulary table
- * 22 Vocabulary type (N/1000) not between 0 and 3
- * 23 Intransitive action verb exceeds goto list
- * 24 Transitive action verb exceeds goto list
- * 25 Conditional travel entry with no alternative
- * 26 Location has no travel entries
- * 27 Hint number exceeds goto list
- * 28 Invalid month returned by date function
- * 29 Too many parameters given to SETPRM */
-{
-
- printf("Fatal error %ld. See source code for interpretation.\n", num);
- exit(0);
-}
/* Machine dependent routines (MAPLIN, SAVEIO) */
struct save_t save;
/* Suspend and resume */
-int suspend(FILE *input)
+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
exit(0);
}
-int resume(FILE *input)
+int resume(void)
{
/* Resume. Read a suspended game back from a file.
* If ADVENT_NOSAVE is defined, do nothing instead. */