/*																				*/
/*																				*/
/*				File:		  	proces.c										*/
/*				Returns:	  	int											*/
/*				Parameters:	recno - int									*/
/*																				*/
/*																				*/

#include <stdio.h>
#include <process.h>

#include "advm.h"
#include "values.h"
#include "misc.h"
#include "string.h"
#include "defcom.h"

#include "rdbuff.h"
#include "where.h"
#include "ref.h"
#include "isnear.h"
#include "eval.h"
#include "rnd.h"
#include "movobj.h"
#include "setval.h"
#include "setbit.h"
#include "bitval.h"
#include "object.h"
#include "place.h"
#include "say.h"
#include "commnd.h"
#include "svar.h"
#include "execute.h"


int proces(recno)
int recno;

   {
   int calls = 0;
   int dos = 0;
   int i,j,k;
   char zresp[140];

   rec1 = 0;
   rec2 = recno;
label_1000:
   for (;;)               /* label 1000 */
      {
      bp = 0;
label_1100:
      for (;;)            /* label 1100 */
         {
         rdbuff((int *)&rec);
         skpflg = 0;
         negate = FALSE;
         passon = FALSE;
         logicm = 1;
label_1200:
         for (;;)
            {
            array(buffer,bp);
            if ((opcode = buffer[bp++]) > 0)
               {
               switch (opcode)
                  {
                  case 1:                /* keyword */
                     array(buffer, bp);
                     word1 = buffer[bp++];
                     for (i=0; i<lineln; i++)
                        {
                        array(linewd, i);
                        if (word1 == linewd[i])
                           goto label_1200;
                        }
                     goto label_1300;
                  case 2:                  /* have */
                     array(buffer, bp);
                     if (where(ref(word1 = buffer[bp++])) == inhand)
                        goto label_1200;
                     goto label_1300;
                  case 3:                  /* near */
                     array(buffer, bp);
                     word1 = buffer[bp++];
                     j = where(i = ref(word1));
                     if (j == inhand || is_near(i))
                        goto label_1200;
                     goto label_1300;
                  case 4:                     /* at */
                     truth = FALSE;
                     do
                        {
                        array(buffer, bp);
                        word1 = buffer[bp++];
                        truth |= (word1 == eval(here));
                        array(buffer,bp);
                        } while (buffer[bp++] == 4);
                     bp--;
                     if (truth)
                        goto label_1200;
                     goto label_1300;
                  case 5:                  /* anyof */
                      truth = FALSE;
                     do
                        {
                        array(buffer,bp);
                        word1 = buffer[bp++];
                        for (i=0; i<lineln; i++)
                           {
                           array(linewd, i);
                           truth |= (word1 == linewd[i]);
                           }
                        array(buffer,bp);
                        } while (buffer[bp++] == 5);
                     bp--;
                     if (truth)
                        goto label_1200;
                     goto label_1300;
                  case 6:      /* general if processing */
                  case 7:
                  case 8:
                  case 9:
                  case 10:
                  case 29:
                  case 30:
                  case 33:
                  case 39:
                  case 43:
                  case 50:
                     switch (opcode)
                        {
                        case 6:                      /* ifeq */
                           array(buffer, bp);
                           array(buffer, bp+1);
                           word1 = buffer[bp++];
                           word2 = buffer[bp++];
                           if (skpflg <= 0)
                              truth = (eval(word1) == eval(word2));
                           break;
                        case 7:                  /* iflt */
                           array(buffer, bp);
                           array(buffer, bp+1);
                           word1 = buffer[bp++];
                           word2 = buffer[bp++];
                           if (skpflg <= 0)
                              truth = (eval(word1) < eval(word2));
                           break;
                        case 8:                 /* ifgt */
                           array(buffer, bp);
                           array(buffer, bp+1);
                           word1 = buffer[bp++];
                           word2 = buffer[bp++];
                           if (skpflg <= 0)
                              truth = (eval(word1) > eval(word2));
                           trace3("PROCES: IFGT %d %d %s\n",buffer[bp],buffer[bp+1],truth ? "Yes" : "No");
                           break;
                        case 9:                 /* ifat */
                           array(buffer, bp);
                           word1 = buffer[bp++];
                           if (skpflg <= 0)
                              truth = (ref(word1) == eval(here));
                           break;
                        case 10:                /* chance */
                           array(buffer, bp);
                           word1 = buffer[bp++];
                           if (skpflg <= 0)
                              truth = (eval(word1) > rnd(100));
                           break;
                        case 29:               /* ifhave */
                           array(buffer, bp);
                           word1 = buffer[bp++];
                           if (skpflg <= 0)
                              truth = (where(ref(word1)) == inhand);
                           break;
                        case 30:               /* ifnear */
                           array(buffer, bp);
                           word1 = buffer[bp++];
                           if (skpflg <= 0)
                              {
                              i = ref(word1);
                              j = where(i);
                              truth = (j == inhand) || is_near(i);
                              }
                           break;
                        case 33:                           /* bitst */
                           array(buffer, bp);
                           array(buffer, bp+1);
                           word1 = buffer[bp++];
                           word2 = buffer[bp++];
                           if (skpflg <= 0)
                              truth = ((bitval(word1) & bitval(word2)) != 0);
                           break;
                        case 39:                     /* ifloc */
                           array(buffer, bp);
                           array(buffer, bp+1);
                           word1 = buffer[bp++];
                           word2 = buffer[bp++];
                           if (skpflg <= 0)
                              truth = (where(ref(word1)) == ref(word2));
                           break;
                        case 43:                     /* ifkey */
                           array(buffer, bp);
                           word1 = buffer[bp++];
                           if (skpflg <= 0)
                              {
                              truth = FALSE;
                              for (i=0; i<lineln; i++)
                                 {
                                 array(linewd, i);
                                 if (truth |= (word1 == linewd[i]))
                                    break;
                                 }
                              }
                           break;
                        case 50:                        /* query */
                           array(buffer, bp);
                           word1 = buffer[bp++];
                           if (skpflg <= 0)
                              {
                              for (;;)
                                 {
                                 say(ref(word1));
                                 printf(" ");
                                 gets(zresp);
                                 trace3("PROCES: QUERY - zresp '%s' '%c' %02.2X\n",zresp,zresp[0],zresp[0]);
                                 if (zresp[0] == 'Y' || zresp[0] == 'y')
                                    truth = TRUE;
                                 else if (zresp[0] == 'N' || zresp[0] == 'n')
                                    truth = FALSE;
                                 else
                                    {
                                    printf ("Please answer the question.");
                                    continue;
                                    }
                                 break;
                                 }
                              }
                           break;
                        default:
                           assert(FALSE);
                        }
                     trace3("PROCES: IF... truth %s, negate %s, passon %s",
                              truth ? "True" : "False",
                              negate ? "True" : "False",
                              passon ? "True" : "False");
                     trace1(", logicm %d,",logicm);
                     truth ^= negate;
                     switch (logicm)
                        {
                        case 1: truth |= passon; break;
                        case 2: truth &= passon; break;
                        case 3: truth ^= passon; break;
                        }
                     trace2("skpflg = %d, truth = %s",skpflg,truth?"Yes":"No");
                     passon = FALSE;
                     negate = FALSE;
                     for (logicm = 1; logicm <= 3; logicm++)
                        {
                        array(buffer,bp);
                        array(logcls,logicm-1);
                        if (buffer[bp] == logcls[logicm-1])
                           {
                           bp++;
                           passon = truth;
                           trace(" continued ...\n");
                           goto label_1200;
                           }
                        }
                     logicm = 1;
                     if (skpflg != 0)
                        skpflg++;
                     else
                        if (!truth)
                           skpflg=1;
                     trace1(" new skpflg = %d\n",skpflg);
                     goto label_1200;   
                  case 11:                  /* else */
                     trace1("PROCESS: ELSE - skipflg: %d -> ",skpflg);
                     if (skpflg <= 1)
                        skpflg = 1-skpflg;
                     trace1("%d\n",skpflg);
                     goto label_1200;
                  case 12:                  /* fin */
                     trace1("PROCESS: FIN - skipflg: %d -> ",skpflg);
                     skpflg = (skpflg > 0) ? skpflg-1 : 0;
                     trace1("%d\n",skpflg);
                     goto label_1200;
                  case 13:                  /* eof */
                     skpflg = 0;
                     goto label_1200;
                  case 14:                  /* get */
                     array(buffer, bp);
                     word1 = buffer[bp++];
                     if (skpflg <= 0)
                        {
                        movobj(ref(word1), inhand);
                        if ((i = eval(ref(word1))) < 0)
                           setval(ref(word1), -1-i);
                        }
                     goto label_1200;
                  case 15:                  /* drop */
                     array(buffer, bp);
                     word1 = buffer[bp++];
                     if (skpflg <= 0)
                        movobj(ref(word1), eval(here));
                     goto label_1200;
                  case 16:                  /* apport */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        movobj(ref(word1), ref(word2));
                     goto label_1200;
                  case 17:                  /* set */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        setval(word1, eval(word2));
                     goto label_1200;
                  case 18:                  /* add */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        setval(word1,eval(word1)+eval(word2));
                     goto label_1200;
                  case 19:                  /* sub */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        setval(word1,eval(word1)-eval(word2));
                     goto label_1200;
                  case 20:                  /* goto */
                     array(buffer, bp);
                     word1 = buffer[bp++];
                     if (skpflg <= 0)
                        {
                        i = eval(here);
                        j = bitval(here);
                        setval(here, ref(word1));
                        setbit(here, bitval(ref(word1)));
                        setval(there, i);
                        setbit(there, j);
                        setbit(status, bitval(status) | moved);
                        }
                     goto label_1200;
                  case 21:                  /* move */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     array(linewd, 0);
                     array(linewd, 1);
                     if ((skpflg > 0) ||
                        (word1 != linewd[0] && (lineln < 2 ||
                        word1 != linewd[1] || (linewd[0] != explor
                        && linewd[0] != sayxx))))
                        goto label_1200;
                     i = eval(here);
                     j = bitval(here);
                     setval(here, ref(word2));
                     setbit(here, bitval(ref(word2)));
                     setval(there, i);
                     setbit(there, j);
                     setbit(status, bitval(status) | moved);
                     return(1);
                  case 22:                           /* call */
                     array(buffer, bp);
                     word1 = buffer[bp++];
                     if (skpflg > 0)
                        goto label_1200;
                     array(callrc1, calls);
                     array(callrc2, calls);
                     array(callbp, calls);
                     array(calldo, calls);
                     callrc1[calls] = rec1;
                     callrc2[calls] = rec2;
                     callbp[calls] = bp;
                     calldo[calls++] = dos;
                     rec1 = 0;
                     rec2 = ref(word1);
                     if (object(rec2) || place(rec2))
                        rec1 = 500;
                     goto label_1000;
                  case 23:                     /* say */
                     array (buffer, bp);
                     word1 = buffer[bp++];
                     if (skpflg <= 0)
                        say(ref(word1));
                     goto label_1200;
                  case 24:                     /* name */
                     array (buffer, bp);
                     array (buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        {
                        for (i=0; i < 2; i++)
                           {
                           array(argwrd, i);
                           if (word2 == argwrd[i])
                              {
                              saynam(ref(word1), word2);
                              goto label_1200;
                              }
                           }
                        saynam(ref(word1), ref(word2));
                        }
                     goto label_1200;
                  case 25:                        /* value */
                     array (buffer, bp);
                     array (buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        sayval(ref(word1), ref(word2));
                     goto label_1200;
                  case 26:                     /* proceed */
                     if (skpflg > 0)
                        goto label_1200;
                     goto label_1300;
                  case 27:                     /* quit */
                     if (skpflg > 0)
                        goto label_1200;
                     return (1);
                  case 28:                     /* stop */
                     if (skpflg > 0)
                        goto label_1200;
                     exit(0);
                  case 31:               /* or, and, xor */
                  case 51:
                  case 52:
                     printf("Glitch!  Ill-placed logical in record %d.%03d after loc %d\n",
                        rec1,rec2,bp);
                     goto label_1200;
                  case 32:               /* random */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        setval(word1, rnd(eval(word2)));
                     goto label_1200;
                  case 34:                     /* biset */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        setbit(word1, bitval(word1) | bitval(word2));
                     goto label_1200;
                  case 35:                     /* biclear */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        setbit(word1, bitval(word1) & ~bitval(word2));
                     goto label_1200;
                  case 36:                  /* itobj */
                     array(buffer, bp);
                     word1 = buffer[bp++];
                     if (skpflg <= 0)
                        {
                        array(dovar, dos);
                        array(dpoint, dos);
                        array(domode, dos);
                        dovar[dos] = word1;
                        setval(word1, 1000);
                        dpoint[dos] = bp;
                        domode[dos] = 1;
                        }
                     dos++;
                     goto label_1200;
                  case 37:                  /* itplace */
                     array(buffer, bp);
                     word1 = buffer[bp++];
                     if (skpflg <= 0)
                        {
                        array(dovar, dos);
                        array(dpoint, dos);
                        array(domode, dos);
                        dovar[dos] = word1;
                        setval(word1, 2000);
                        dpoint[dos] = bp;
                        domode[dos] = 2;
                        }
                     dos++;
                     goto label_1200;
                  case 38:                  /* eoi */
                     for(;;)
                        {
                        if (skpflg <= 0)
                           {
                           array(dovar, dos-1);
                           i = eval(dovar[dos-1]) + 1;
                           setval(dovar[dos-1], i);
                           array(domode, dos-1); 
                           assert(domode[dos-1] >= 1 && domode[dos-1] <= 3);
                           if (domode[dos-1] == 1)
                              {
                              if (i-1000 == nobj)
                                 break;
                              }
                           else if (domode[dos-1] == 2)
                              {
                              if (i-2000 == nplace)
                                 break;
                              }
                           else
                              {
                              if (i-1000 == nobj)
                                 break;
label_5945:
                              j = where(i);
                              if (!is_near(i) && i-1000 != nobj-1)
                                 continue;
                              }
                           array(dpoint, dos-1);
                           bp = dpoint[dos-1];
                           goto label_1200;
                           }      /* if */
                        else
                           break;
                        }         /* for */
                     dos--;
                     goto label_1200;
                  case 40:                     /* input */
                     if (skpflg <= 0)
                        {
                        defflg = FALSE;
                        commnd();
                        }
                     goto label_1200;
                  case 41:                     /* locate */
                     array (buffer, bp);
                     array (buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        setval(word1, where(ref(word2)));
                     goto label_1200;
                  case 42:                     /* not */
                     if (skpflg <= 0)
                        negate = !negate;
                     goto label_1200;
                   case 44:                     /* lda */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        {
                        setval(word1, word2);
                        for (i=0; i<lineln; i++)
                           {
                           array(argwrd, i);
                           if (word1 == argwrd[i])
                              {
                              array(linewd, i);
                              linewd[i] = word2;
                              break;
                              }
                           }
                        }
                     goto label_1200;
                  case 45:                           /* eval */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        setval(word1, eval(ref(word2)));
                     goto label_1200;
                  case 46:                           /* multiply */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        setval(word1, eval(word1) * eval(word2));
                     goto label_1200;
                  case 47:                           /* divide */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        setval(word1, eval(word1) / eval(word2));
                     goto label_1200;
                  case 48:                           /* svar */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        {
                        i = eval(word2);
                        svar(eval(word1), &i);
                        setval(word2, i);
                        }
                     goto label_1200;
                  case 49:                           /* exec */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        execut();
                     goto label_1200;
                   case 53:                           /* deposit */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     if (skpflg <= 0)
                        setval(ref(word1), eval(word2));
                     goto label_1200;
                    case 54:                              /* itlist */
                     array(buffer, bp);
                     word1 = buffer[bp++];
                     dos++;
                     if (skpflg > 0)
                        goto label_1200;
                     array(dovar, dos-1);
                     dovar[dos-1] = word1;
                     i = 1000;
                     setval(word1, i);
                     array(dpoint, dos-1);
                     dpoint[dos-1] =  bp;
                     array(domode, dos-1);
                     domode[dos-1] = 3;
                     goto label_5945;
                  case 55:                     /* smove */
                     array(buffer, bp);
                     array(buffer, bp+1);
                     array(buffer, bp+2);
                     word1 = buffer[bp++];
                     word2 = buffer[bp++];
                     word3 = buffer[bp++];
                     if (skpflg <= 0)
                        {
                        array(linewd, 0);
                        array(linewd, 1);
                        if (!(word1 != linewd[0] && (lineln < 2 ||
                              word1 != linewd[1] || (linewd[0] != explor
                              && linewd[0] != sayxx))))
                           {
                           i = eval(here);
                           j = bitval(here);
                           setval(here, ref(word2));
                           setbit(here, bitval(ref(word2)));
                           setval(there, i);
                           setbit(there, j);
                           setbit(status, bitval(status) | moved);
                           say(word3);
                           return (1);
                           }
                        }
                     goto label_1200;
                  case 56:                        /* default */
                     array(buffer, bp);
                     word1 = buffer[bp++];
                     if (skpflg <= 0)
                        {
                        k = 0;
                        for (i=1000; i<1000+nobj; i++)
                           {
                           if (!is_near(i) || !(bitval(i) & bitval(word1)))
                              continue;
                           if (k)
                              goto label_1200;
                           k=i;
                           }
                        if (k)
                           {
                           array(argwrd, 1);
                           array(linewd, 1);
                           setval(argwrd[1], k);
                           setbit(argwrd[1], bitval(k));
                           linewd[1] = k;
                           setval(status, 2);
                           lineln = 2;
                           defflg = TRUE;
                           }
                        }
                     goto label_1200;
                  default:
                     printf("Glitch!  Bad opcode: %d - rec = %d.%03d after loc %d\n",
                           opcode, rec2, rec1, bp);
                     goto label_1300;
                  }
               }
            if (bp == 1)
               {
label_1500:
               if (!calls)
                  return(0);
               array(callrc1, calls-1);
               array(callrc2, calls-1);
               array(callbp, calls-1);
               array(calldo, calls-1);
               rec1 = callrc1[--calls];
               rec2 = callrc2[calls];
               bp = callbp[calls];
               dos = calldo[calls];
               goto label_1100;
               }
label_1300:
            rec1++;
            goto label_1000;
            }
         }
      }
   }
