~ubuntu-branches/ubuntu/wily/gargoyle-free/wily-proposed

« back to all changes in this revision

Viewing changes to terps/advsys/advexe.c

  • Committer: Bazaar Package Importer
  • Author(s): Sylvain Beucler
  • Date: 2009-09-11 20:09:43 UTC
  • Revision ID: james.westby@ubuntu.com-20090911200943-idgzoyupq6650zpn
Tags: upstream-2009-08-25
ImportĀ upstreamĀ versionĀ 2009-08-25

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/* advexe.c - adventure code executer */
 
3
/*
 
4
        Copyright (c) 1986, by David Michael Betz
 
5
        All rights reserved
 
6
*/
 
7
 
 
8
#include "header.h"
 
9
#include "advint.h"
 
10
#include "advdbs.h"
 
11
 
 
12
/* external variables */
 
13
extern char line[];
 
14
extern int nouns[],*adjectives[];
 
15
 
 
16
/* local variables */
 
17
int pc,opcode,p2,p3,sts;
 
18
int stack[STKSIZE],*sp,*fp,*top;
 
19
long rseed = 1L;
 
20
 
 
21
/* Function Prototypes.  Gosh */
 
22
void exe_one(void);
 
23
int getboperand();
 
24
int getwoperand();
 
25
void print(int msg);
 
26
int vowel(int msg) ;
 
27
void pnumber(int n);
 
28
int getrand(int n);
 
29
void setrand(long n);
 
30
 
 
31
/* execute - execute adventure code */
 
32
int execute(int code)
 
33
{
 
34
    /* setup initial program counter */
 
35
    if ((pc = code) == NIL)
 
36
        return (CHAIN);
 
37
 
 
38
    /* initialize */
 
39
    sp = fp = top = stack + STKSIZE;
 
40
 
 
41
    /* execute the code */
 
42
    for (sts = 0; sts == 0; )
 
43
        exe_one();
 
44
 
 
45
    return (sts);
 
46
}
 
47
 
 
48
/* exe_one - execute one instruction */
 
49
void exe_one()
 
50
{
 
51
    /* get the opcode */
 
52
    opcode = getcbyte(pc); pc++;
 
53
 
 
54
    /* execute the instruction */
 
55
    switch (opcode) {
 
56
    case OP_CALL:
 
57
                *--sp = getboperand();
 
58
                *--sp = pc;
 
59
                *--sp = (int)(top - fp);
 
60
                fp = sp;
 
61
                pc = getafield(fp[fp[2]+3],A_CODE);
 
62
                break;
 
63
    case OP_SEND:
 
64
                *--sp = getboperand();
 
65
                *--sp = pc;
 
66
                *--sp = (int)(top - fp);
 
67
                fp = sp;
 
68
                if (p2 = fp[fp[2]+3])
 
69
                    p2 = getofield(p2,O_CLASS);
 
70
                else
 
71
                    p2 = fp[fp[2]+2];
 
72
                if (p2 && (p2 = getp(p2,fp[fp[2]+1]))) {
 
73
                    pc = getafield(p2,A_CODE);
 
74
                    break;
 
75
                }
 
76
                *sp = NIL;
 
77
                /* return NIL if there is no method for this message */
 
78
    case OP_RETURN:
 
79
                if (fp == top)
 
80
                    sts = CHAIN;
 
81
                else {
 
82
                    p2 = *sp;
 
83
                    sp = fp;
 
84
                    fp = top - *sp++;
 
85
                    pc = *sp++;
 
86
                    p3 = *sp++;
 
87
                    sp += p3;
 
88
                    *sp = p2;
 
89
                }
 
90
                break;
 
91
    case OP_TSPACE:
 
92
                sp -= getboperand();
 
93
                break;
 
94
    case OP_TMP:
 
95
                p2 = getboperand();
 
96
                *sp = fp[-p2-1];
 
97
                break;
 
98
    case OP_TSET:
 
99
                p2 = getboperand();
 
100
                fp[-p2-1] = *sp;
 
101
                break;
 
102
    case OP_ARG:
 
103
                p2 = getboperand();
 
104
                if (p2 >= fp[2])
 
105
                    error("too few arguments");
 
106
                *sp = fp[p2+3];
 
107
                break;
 
108
    case OP_ASET:
 
109
                p2 = getboperand();
 
110
                if (p2 >= fp[2])
 
111
                    error("too few arguments");
 
112
                fp[p2+3] = *sp;
 
113
                break;
 
114
    case OP_BRT:
 
115
                pc = (*sp ? getwoperand() : pc+2);
 
116
                break;
 
117
    case OP_BRF:
 
118
                pc = (*sp ? pc+2 : getwoperand());
 
119
                break;
 
120
    case OP_BR:
 
121
                pc = getwoperand();
 
122
                break;
 
123
    case OP_T:
 
124
                *sp = T;
 
125
                break;
 
126
    case OP_NIL:
 
127
                *sp = NIL;
 
128
                break;
 
129
    case OP_PUSH:
 
130
                *--sp = NIL;
 
131
                break;
 
132
    case OP_NOT:
 
133
                *sp = (*sp ? NIL : T);
 
134
                break;
 
135
    case OP_ADD:
 
136
                p2 = *sp++;
 
137
                *sp += p2;
 
138
                break;
 
139
    case OP_SUB:
 
140
                p2 = *sp++;
 
141
                *sp -= p2;
 
142
                break;
 
143
    case OP_MUL:
 
144
                p2 = *sp++;
 
145
                *sp *= p2;
 
146
                break;
 
147
    case OP_DIV:
 
148
                p2 = *sp++;
 
149
                *sp = (p2 == 0 ? 0 : *sp / p2);
 
150
                break;
 
151
    case OP_REM:
 
152
                p2 = *sp++;
 
153
                *sp = (p2 == 0 ? 0 : *sp % p2);
 
154
                break;
 
155
    case OP_BAND:
 
156
                p2 = *sp++;
 
157
                *sp &= p2;
 
158
                break;
 
159
    case OP_BOR:
 
160
                p2 = *sp++;
 
161
                *sp |= p2;
 
162
                break;
 
163
    case OP_BNOT:
 
164
                *sp = ~*sp;
 
165
                break;
 
166
    case OP_LT:
 
167
                p2 = *sp++;
 
168
                *sp = (*sp < p2 ? T : NIL);
 
169
                break;
 
170
    case OP_EQ:
 
171
                p2 = *sp++;
 
172
                *sp = (*sp == p2 ? T : NIL);
 
173
                break;
 
174
    case OP_GT:
 
175
                p2 = *sp++;
 
176
                *sp = (*sp > p2 ? T : NIL);
 
177
                break;
 
178
    case OP_LIT:
 
179
                *sp = getwoperand();
 
180
                break;
 
181
    case OP_SPLIT:
 
182
                *sp = getboperand();
 
183
                break;
 
184
    case OP_SNLIT:
 
185
                *sp = -getboperand();
 
186
                break;
 
187
    case OP_VAR:
 
188
                *sp = getvalue(getwoperand());
 
189
                break;
 
190
    case OP_SVAR:
 
191
                *sp = getvalue(getboperand());
 
192
                break;
 
193
    case OP_SET:
 
194
                setvalue(getwoperand(),*sp);
 
195
                break;
 
196
    case OP_SSET:
 
197
                setvalue(getboperand(),*sp);
 
198
                break;
 
199
    case OP_GETP:
 
200
                p2 = *sp++;
 
201
                *sp = getp(*sp,p2);
 
202
                break;
 
203
    case OP_SETP:
 
204
                p3 = *sp++;
 
205
                p2 = *sp++;
 
206
                *sp = setp(*sp,p2,p3);
 
207
                break;
 
208
    case OP_PRINT:
 
209
                print(*sp);
 
210
                break;
 
211
    case OP_PNUMBER:
 
212
                pnumber(*sp);
 
213
                break;
 
214
    case OP_PNOUN:
 
215
                show_noun(*sp);
 
216
                break;
 
217
    case OP_TERPRI:
 
218
                trm_chr('\n');
 
219
                break;
 
220
    case OP_FINISH:
 
221
                sts = FINISH;
 
222
                break;
 
223
    case OP_CHAIN:
 
224
                sts = CHAIN;
 
225
                break;
 
226
    case OP_ABORT:
 
227
                sts = ABORT;
 
228
                break;
 
229
    case OP_EXIT:
 
230
                trm_done();
 
231
                glk_exit();
 
232
                break;
 
233
    case OP_YORN:
 
234
                trm_get(line);
 
235
                *sp = (line[0] == 'Y' || line[0] == 'y' ? T : NIL);
 
236
                break;
 
237
    case OP_CLASS:
 
238
                *sp = getofield(*sp,O_CLASS);
 
239
                break;
 
240
    case OP_MATCH:
 
241
                p2 = *sp++;
 
242
                *sp = (match(*sp,nouns[p2-1],adjectives[p2-1]) ? T : NIL);
 
243
                break;
 
244
    case OP_SAVE:
 
245
                if ((*sp = db_save()) == NIL)     // VB: added if
 
246
                   trm_str("Sorry, I couldn't save to this file.\n");
 
247
                break;
 
248
    case OP_RESTORE:
 
249
                if ((*sp = db_restore()) == NIL)  // VB: added if
 
250
                   trm_str("Sorry, I couldn't restore from this file.\n");
 
251
                break;
 
252
    case OP_RESTART:
 
253
                *sp = db_restart();
 
254
                break;
 
255
    case OP_RAND:
 
256
                *sp = getrand(*sp);
 
257
                break;
 
258
    case OP_RNDMIZE:
 
259
                setrand(time(0L));
 
260
                *sp = NIL;
 
261
                break;
 
262
    case OP_VOWEL:                 // patch for smart articles by MRP
 
263
                *sp = vowel(*sp);  // patch for smart articles by MRP
 
264
                break;             // patch for smart articles by MRP
 
265
    default:
 
266
            if (opcode >= OP_XVAR && opcode < OP_XSET)
 
267
                *sp = getvalue(opcode - OP_XVAR);
 
268
            else if (opcode >= OP_XSET && opcode < OP_XPLIT)
 
269
                setvalue(opcode - OP_XSET,*sp);
 
270
            else if (opcode >= OP_XPLIT && opcode < OP_XNLIT)
 
271
                *sp = opcode - OP_XPLIT;
 
272
            else if (opcode >= OP_XNLIT && opcode < 256)
 
273
                *sp = OP_XNLIT - opcode;
 
274
            else
 
275
                trm_str("Bad opcode\n");
 
276
            break;
 
277
    }
 
278
}
 
279
 
 
280
/* getboperand - get data byte */
 
281
int getboperand()
 
282
{
 
283
    int data;
 
284
    data = getcbyte(pc); pc += 1;
 
285
    return (data);
 
286
}
 
287
 
 
288
/* getwoperand - get data word */
 
289
int getwoperand()
 
290
{
 
291
    int data;
 
292
    data = getcword(pc); pc += 2;
 
293
    return (data);
 
294
}
 
295
 
 
296
/* print - print a message */
 
297
void print(int msg)
 
298
{
 
299
    int ch;
 
300
 
 
301
    msg_open(msg);
 
302
    while (ch = msg_byte())
 
303
        trm_chr(ch);
 
304
}
 
305
 
 
306
/* vowel - check for vowel */      // patch for smart articles by MRP
 
307
int vowel(int msg)                         // patch for smart articles by MRP
 
308
{                                  // patch for smart articles by MRP
 
309
    int ch,r;                      // patch for smart articles by MRP
 
310
                                   // patch for smart articles by MRP
 
311
    msg_open(msg);                 // patch for smart articles by MRP
 
312
    ch = msg_byte();               // patch for smart articles by MRP
 
313
    if (ch=='a'||ch=='e'||ch=='i'||ch=='o'||ch=='u')  // patch by MRP
 
314
      r = T;                       // patch for smart articles by MRP
 
315
    else                           // patch for smart articles by MRP
 
316
      r = NIL;                     // patch for smart articles by MRP
 
317
    while (ch)                     // patch for smart articles by MRP
 
318
      ch = msg_byte();             // patch for smart articles by MRP
 
319
    return (r);                    // patch for smart articles by MRP
 
320
}                                  // patch for smart articles by MRP
 
321
 
 
322
/* pnumber - print a number */
 
323
void pnumber(int n)
 
324
{
 
325
    char buf[10];
 
326
 
 
327
    sprintf(buf,"%d",n);
 
328
    trm_str(buf);
 
329
}
 
330
 
 
331
/* getrand - get a random number between 0 and n-1 */
 
332
int getrand(int n)
 
333
{
 
334
    long k1;
 
335
 
 
336
    /* make sure we don't get stuck at zero */
 
337
    if (rseed == 0L) rseed = 1L;
 
338
 
 
339
    /* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */
 
340
    k1 = rseed / 127773L;
 
341
    if ((rseed = 16807L * (rseed - k1 * 127773L) - k1 * 2836L) < 0L)
 
342
        rseed += 2147483647L;
 
343
 
 
344
    /* return a random number between 0 and n-1 */
 
345
    return ((int)(rseed % (long)n));
 
346
}
 
347
 
 
348
/* setrand - set the random number seed */
 
349
void setrand(long n)
 
350
{
 
351
    rseed = n;
 
352
}
 
353