home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Interactive Guide / c-cplusplus-interactive-guide.iso / c_ref / csource4 / 251_01 / advexe.c < prev    next >
Text File  |  1987-10-29  |  6KB  |  332 lines

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