/* ybcalc.c (c)1988 Ali T. Ozer
** The "stack calculator" and window stuff for YaBoing II.
** Freely distributable.
*/

#include "yb2.h"

extern struct RastPort *rp;  /* The rastport of the YaBoing window */

#define STACKSIZE 4
unsigned long stack[STACKSIZE];
int sp; /* =0 when empty, =STACKSIZE when full */

long stacklocs[STACKSIZE] = {20L,30L,40L,50L};  /* Locations where we write */

unsigned long bestsofar = 0;

#define STRLEN 13
char str[STRLEN];


EraseStackLoc (s) int s; {WriteString (s, "             ", STRLEN);}


DrawStackLoc (s) int s;  {WriteNum (s, stack[s]);}


WriteNum (s, num)
int s;
unsigned long num;
{
  unsigned long mult = 1000000000;   /* 1 billion */
  int zeros = false, curdigit;
  char *tstr = str;
    
  while (mult) {
    curdigit = (int)((num / mult) % 10);
    if (curdigit || mult == 1) zeros = true;  /* End of leading zeros! */
    if (curdigit || zeros) *tstr++ = curdigit + '0'; else *tstr++ = ' ';
    if (mult == 1000000000 || mult == 1000000 || mult == 1000) {
      if (zeros) *tstr++ = ','; else *tstr++ = ' ';
    };
    mult /= 10;
  } 
  WriteString (s, str);       
}


InitMessage ()
{                  
  WriteString (0, " Click  here ");
  WriteString (1, "to start (and");
  WriteString (2, "stop) playing");
  WriteString (3, "--Good luck--");
}

WriteString (s, tstr)
int s;
char *tstr;
{
  Move (rp, 32L, stacklocs[s]); 
  Text (rp, tstr, (long)STRLEN);
}  

ClearStack ()
{
  int cnt;
  sp = 0;
  for (cnt = 0; cnt < STACKSIZE; cnt++) EraseStackLoc (cnt);
}

ShowScore ()
{
  unsigned long score = (sp ? stack[sp-1] : 0L);
  WriteString (0, "SCORE:       "); WriteNum (1, score);  
  WriteString (2, "PREV BEST:   "); WriteNum (3, bestsofar);
  if (score > bestsofar) bestsofar = score;
}

ProcessHit (spr)
struct sprrec *spr;
{
  int cnt; unsigned long tmp;

  if (TYPE == NUMSPRITE || VAL == OPCHK) {
    if (VAL == OPCHK) VAL = 10 + 2 * Rnd(11);
    if (sp == STACKSIZE) {
      for (cnt = 0; cnt < STACKSIZE-1; cnt++) stack[cnt] = stack[cnt+1];
      stack[STACKSIZE-1] = VAL;
      for (cnt = 0; cnt < STACKSIZE; cnt++) DrawStackLoc (cnt);
    } else {
      stack[sp] = (unsigned long)VAL;
      DrawStackLoc (sp++);
    };
    return;
  };

  /* Must be an OPSPRITE, an operator */
  
  if (VAL == OPPOP) {if (sp) EraseStackLoc (--sp);
  } else {
    if (sp < 2) return;
    switch (VAL) {
      case OPADD: stack[sp-2] += stack[sp-1]; break;
      case OPMUL: stack[sp-2] *= stack[sp-1]; break;
      case OPSUB: if (stack[sp-1] > stack[sp-2]) stack[sp-2] = 0;
                  else stack[sp-2] -= stack[sp-1]; 
                  break;
      case OPDIV: if (stack[sp-1] == 0) {ClearStack (); return;};
                  stack[sp-2] /= stack[sp-1]; break;
      case OPSWP: tmp = stack[sp-2]; 
                  stack[sp-2] = stack[sp-1];
                  stack[sp-1] = tmp;
		  DrawStackLoc (sp-2);
		  DrawStackLoc (sp-1);
                  return;
                  break;
      default: return;
    };
    DrawStackLoc (sp-2);
    EraseStackLoc (--sp);
  }
}

 
    
   
    
  
    
      
