1
/* advdbs.c - adventure database access routines */
3
Copyright (c) 1986, by David Michael Betz
14
/* global variables */
15
int h_init; /* initialization code */
16
int h_update; /* update code */
17
int h_before; /* before handler code */
18
int h_after; /* after handler code */
19
int h_error; /* error handling code */
20
strid_t datafd; /* data file descriptor */
22
/* external variables */
23
extern jmp_buf restart;
25
/* table base addresses */
26
char *wtable; /* word table */
27
char *wtypes; /* word type table */
28
int wcount; /* number of words */
29
char *otable; /* object table */
30
int ocount; /* number of objects */
31
char *atable; /* action table */
32
int acount; /* number of actions */
33
char *vtable; /* variable table */
34
int vcount; /* number of variables */
35
char *data; /* base of data tables */
36
char *base; /* current base address */
37
char *dbase; /* base of the data space */
38
char *cbase; /* base of the code space */
39
glui32 length; /* length of resident data structures */
41
/* data file header */
42
static char hdr[HDR_SIZE];
45
static long saveoff; /* save data file offset */
46
static char *save; /* save area base address */
47
static glui32 slen; /* save area length */
49
/* db_init - read and decode the data file header */
50
void db_init(strid_t realfd)
52
int woff,ooff,aoff,voff,n;
54
/* open the data file */
55
datafd = realfd; // glk_stream_open_file(name, filemode_Read, 0);
57
// if (datafd == NULL)
58
// error("can't open data file");
61
if (glk_get_buffer_stream(datafd,hdr,HDR_SIZE) != HDR_SIZE)
62
error("bad data file");
64
complement(hdr,HDR_SIZE);
67
/* check the magic information */
68
if (strncmp(&hdr[HDR_MAGIC],"ADVSYS",6) != 0)
69
error("not an adventure data file");
71
/* check the version number */
72
if ((n = getword(HDR_VERSION)) < 101 || n > VERSION)
73
error("wrong version number");
75
/* decode the resident data length header field */
76
length = getword(HDR_LENGTH);
78
/* allocate space for the resident data structure */
79
if ((data = malloc(length)) == 0)
80
error("insufficient memory");
82
/* compute the offset to the data */
83
saveoff = (long)getword(HDR_DATBLK) * 512L;
85
/* read the resident data structure */
86
glk_stream_set_position(datafd,saveoff,seekmode_Start);
87
if (glk_get_buffer_stream(datafd,data,length) != length)
88
error("bad data file");
89
complement(data,length);
91
/* get the table base addresses */
92
wtable = data + (woff = getword(HDR_WTABLE));
93
wtypes = data + getword(HDR_WTYPES) - 1;
94
otable = data + (ooff = getword(HDR_OTABLE));
95
atable = data + (aoff = getword(HDR_ATABLE));
96
vtable = data + (voff = getword(HDR_VTABLE));
98
/* get the save data area */
99
saveoff += (long)getword(HDR_SAVE);
100
save = data + getword(HDR_SAVE);
101
slen = getword(HDR_SLEN);
103
/* get the base of the data and code spaces */
104
dbase = data + getword(HDR_DBASE);
105
cbase = data + getword(HDR_CBASE);
107
/* initialize the message routines */
108
msg_init(datafd,getword(HDR_MSGBLK));
110
/* get the code pointers */
111
h_init = getword(HDR_INIT);
112
h_update = getword(HDR_UPDATE);
113
h_before = getword(HDR_BEFORE);
114
h_after = getword(HDR_AFTER);
115
h_error = getword(HDR_ERROR);
117
/* get the table lengths */
119
wcount = getword(woff);
120
ocount = getword(ooff);
121
acount = getword(aoff);
122
vcount = getword(voff);
124
/* setup the base of the resident data */
127
/* set the object count */
128
setvalue(V_OCOUNT,ocount);
130
/* CHANGED FOR GLK */
133
garglk_set_story_name(&hdr[HDR_ANAME]);
141
i = strlen(&hdr[HDR_ANAME]);
143
i += strlen("GLK AdvSys - ");
145
buf = malloc( sizeof(char) * i );
146
wsprintf(buf, "GLK AdvSys - %s", &hdr[HDR_ANAME]);
147
winglk_window_set_title(buf);
152
/* db_save - save the current database */
155
return (advsave(&hdr[HDR_ANAME],20,save,slen) ? T : NIL);
158
/* db_restore - restore a saved database */
161
return (advrestore(&hdr[HDR_ANAME],20,save,slen) ? T : NIL);
164
/* db_restart - restart the current game */
167
glk_stream_set_position(datafd,saveoff,seekmode_Start);
168
if (glk_get_buffer_stream(datafd,save,slen) != slen)
170
complement(save,slen);
171
setvalue(V_OCOUNT,ocount);
176
/* complement - complement a block of memory */
177
void complement(char *adr,int len)
183
/* findword - find a word in the dictionary */
184
int findword(char *word)
186
char sword[WRDSIZE+1];
189
/* shorten the word */
190
strncpy(sword,word,WRDSIZE); sword[WRDSIZE] = 0;
192
/* look up the word */
193
for (i = 1; i <= wcount; i++) {
195
if (strcmp(base+wrd+2,sword) == 0)
196
return (getword(wrd));
201
/* wtype - return the type of a word */
204
return (wtypes[wrd]);
207
/* match - match an object against a name and list of adjectives */
208
int match(int obj,int noun,int *adjs)
212
if (!hasnoun(obj,noun))
214
for (aptr = adjs; *aptr != NIL; aptr++)
215
if (!hasadjective(obj,*aptr))
220
/* checkverb - check to see if this is a valid verb */
221
int checkverb(int *verbs)
225
/* look up the action */
226
for (act = 1; act <= acount; act++)
227
if (hasverb(act,verbs))
232
/* findaction - find an action matching a description */
233
int findaction(int *verbs,int preposition,int flag)
237
/* look up the action */
238
for (act = 1; act <= acount; act++) {
239
if (preposition && !haspreposition(act,preposition))
241
if (!hasverb(act,verbs))
243
mask = ~getabyte(act,A_MASK);
244
if ((flag & mask) == (getabyte(act,A_FLAG) & mask))
250
/* getp - get the value of an object property */
251
int getp(int obj,int prop)
255
for (; obj; obj = getofield(obj,O_CLASS))
256
if (p = findprop(obj,prop))
257
return (getofield(obj,p));
261
/* setp - set the value of an object property */
262
int setp(int obj,int prop,int val)
266
for (; obj; obj = getofield(obj,O_CLASS))
267
if (p = findprop(obj,prop))
268
return (putofield(obj,p,val));
272
/* findprop - find a property */
273
int findprop(int obj,int prop)
277
n = getofield(obj,O_NPROPERTIES);
278
for (i = p = 0; i < n; i++, p += 4)
279
if ((getofield(obj,O_PROPERTIES+p) & ~P_CLASS) == prop)
280
return (O_PROPERTIES+p+2);
284
/* hasnoun - check to see if an object has a specified noun */
285
int hasnoun(int obj,int noun)
288
if (inlist(getofield(obj,O_NOUNS),noun))
290
obj = getofield(obj,O_CLASS);
295
/* hasadjective - check to see if an object has a specified adjective */
296
int hasadjective(int obj,int adjective)
299
if (inlist(getofield(obj,O_ADJECTIVES),adjective))
301
obj = getofield(obj,O_CLASS);
306
/* hasverb - check to see if this action has this verb */
307
int hasverb(int act,int *verbs)
311
/* get the list of verbs */
312
link = getafield(act,A_VERBS);
314
/* look for this verb */
315
while (link != NIL) {
317
word = getword(link+L_DATA);
318
while (*verb != NIL && word != NIL) {
319
if (*verb != getword(word+L_DATA))
322
word = getword(word+L_NEXT);
324
if (*verb == NIL && word == NIL)
326
link = getword(link+L_NEXT);
331
/* haspreposition - check to see if an action has a specified preposition */
332
int haspreposition(int act, int preposition)
334
return (inlist(getafield(act,A_PREPOSITIONS),preposition));
337
/* inlist - check to see if a word is an element of a list */
338
int inlist(int link, int word)
340
while (link != NIL) {
341
if (word == getword(link+L_DATA))
343
link = getword(link+L_NEXT);
348
/* getofield - get a field from an object */
349
int getofield(int obj, int off)
351
return (getword(getoloc(obj)+off));
354
/* putofield - put a field into an object */
355
int putofield(int obj,int off,int val)
357
return (putword(getoloc(obj)+off,val));
360
/* getafield - get a field from an action */
361
int getafield(int act,int off)
363
return (getword(getaloc(act)+off));
366
/* getabyte - get a byte field from an action */
367
int getabyte(int act,int off)
369
return (getbyte(getaloc(act)+off));
372
/* getoloc - get an object from the object table */
375
if (n < 1 || n > ocount)
376
nerror("object number out of range: %d",n);
377
return (getdword(otable+n+n));
380
/* getaloc - get an action from the action table */
383
if (n < 1 || n > acount)
384
nerror("action number out of range: %d",n);
385
return (getdword(atable+n+n));
388
/* getvalue - get the value of a variable from the variable table */
391
if (n < 1 || n > vcount)
392
nerror("variable number out of range: %d",n);
393
return (getdword(vtable+n+n));
396
/* setvalue - set the value of a variable in the variable table */
400
if (n < 1 || n > vcount)
401
nerror("variable number out of range: %d",n);
402
return (putdword(vtable+n+n,v));
405
/* getwloc - get a word from the word table */
408
if (n < 1 || n > wcount)
409
nerror("word number out of range: %d",n);
410
return (getdword(wtable+n+n));
413
/* getword - get a word from the data array */
416
return (getdword(base+n));
419
/* putword - put a word into the data array */
420
int putword(int n,int w)
422
return (putdword(base+n,w));
425
/* getbyte - get a byte from the data array */
428
return (*(base+n) & 0xFF);
431
/* getcbyte - get a code byte */
434
return (*(cbase+n) & 0xFF);
437
/* getcword - get a code word */
440
return (getdword(cbase+n));
443
/* getdword - get a word from the data array */
444
int getdword(char *p)
446
return (((*p & 0xFF) | (*(p+1) << 8))&0xFFFF);
449
/* putdword - put a word into the data array */
450
int putdword(char *p,int w)
452
*p = w; *(p+1) = w >> 8;
456
/* nerror - handle errors with numeric arguments */
457
void nerror(char *fmt,int n)