// utility routines (shift, ran, datime, ciao, bug)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "adv_util.h"

int shift(int val, int dist)
{
    // RETURN VAL LEFT-SHIFTED (LOGICALLY) DIST BITS (RIGHT-SHIFT IF DIST<0).
    if(dist < 0)
        return (val >> dist);
    else if (dist == 0) 
        return val;
    else  // if (dist > 0)
        return (val << dist);
}

int ran(int range)
{
// SINCE THE RAN FUNCTION IN LIB40 SEEMS TO BE A REAL LOSE, WE"LL USE ONE OF
// OUR OWN.  IT"S BEEN RUN THROUGH MANY OF THE TESTS IN KNUTH VOL. 2 AND
// SEEMS TO BE QUITE RELIABLE.  RAN RETURNS A VALUE UNIFORMLY SELECTED
// BETWEEN 0 AND RANGE-1.  NOTE RESEMBLANCE TO ALG USED IN WIZARD.

      static int r = 0;
      int d,t;
      
      d=1;
      if (r == 0)   // first time - randomize
      { 
        // call datime(d,t);
        r = 18*t+5;
        d = 1000 + d%1000;
      } 
      for (t=1;t<=d;t++)
        r = (r*1021)%1048576;
      return (range*r)/1048576;
}

void datime(long *d, long *t)
{
// RETURN THE DATE AND TIME IN D AND T.  D IS NUMBER OF DAYS SINCE 01-JAN-77,
// T IS MINUTES PAST MIDNIGHT.  THIS IS HARDER THAN IT SOUNDS, BECAUSE THE
// FINAGLED DEC FUNCTIONS RETURN THE VALUES ONLY AS ASCII STRINGS!
// on a unix/linux system, "time" returns GMT. adjust by TZ_OFFSET (in adventur.h)
  time_t now;

  now = time(NULL);
  *t = (now % 86400) / 60;  // extract seconds since midnight, change to minutes
  // time() returns days since 1970, we need to subtract 7 years for 1977
  // dt = (now/86400) - SEVENYRS;  // extract days since 1977
  *d = (now/86400);  // extract days since 1977

/*    ignore the rest of this junk for now, since it looks like we get a
        more reasonable output from "time" (just segm.conds in a "long") 

      dimension dat(2),months(12),hath(12);
      data months/"-jan-","-feb-","-mar-","-apr-","-may-","-jun-","-jul-","-aug-","-sep-","-oct-","-nov-","-dec-"/;
      data hath/31,28,31,30,31,30,31,31,30,31,30,31/;

// FUNCTION I2 TAKES 2-DIGIT ASCII AND YIELDS DECIMAL VALUE.

      i2(x)=(shift(x,-29) && 15)*10+(shift(x,-22) && 15);

      call date(dat);
      call time(tim);

      year=i2(shift(dat(2),14))-77;
      d=i2(dat(1))-1;
      x=((shift(dat(1),14) | shift(dat(2),-21)) &  ! "1004020001) | "-@@@-";
// ABOVE FUNNY EXPRESSION GUARANTEES (A) UPPER-CASE, AND (B) BOTTOM BIT OKAY.
      do 1 mon=1,12;
      if(x == months(mon))goto 2;
1     d=d+hath(mon);
      call bug(28);

2     d=d+year*365+year/4;
      if(mod(year,4) == 3 && mon > 2)d=d+1;
      t=i2(tim)*60+i2(shift(tim,21));
      return;
*/
}

void ciao(void)
{
  // EXITS, AFTER ISSUING REMINDER TO SAVE NEW CORE IMAGE.  USED WHEN SUSPENDING
  // AND WHEN CREATING NEW VERSION VIA MAGIC MODE.  ON SOME SYSTEMS, THE CORE
  // IMAGE IS LOST ONCE THE PROGRAM EXITS.  IF SO, SET K=31 INSTEAD OF 32.
  // Note that in the context of Linux, "core-image" has no meaning, so we
  //   will skip messages 31 and 32 in favor of something more user-friendly
  // int k = 32;
  // int a, b, c, d;

  // mspeak(k);
  // if (k == 31)
  //     getin(a,b,c,d);
  printf("THANKS FOR PLAYING LINUX ADVENTURE.\n");
  printf("COME BACK SOON.\n");
  exit(0);
}

void bug(int num)
{
// THE FOLLOWING CONDITIONS ARE CURRENTLY CONSIDERED FATAL BUGS.  NUMBERS < 20
// ARE DETECTED WHILE READING THE DATABASE; THE OTHERS OCCUR AT "RUN TIME".
//    0     MESSAGE LINE > 70 CHARACTERS
//    1     NULL LINE IN MESSAGE
//    2     TOO MANY WORDS OF MESSAGES
//    3     TOO MANY TRAVEL OPTIONS
//    4     TOO MANY VOCABULARY WORDS
//    5     REQUIRED VOCABULARY WORD NOT FOUND
//    6     TOO MANY RTEXT OR MTEXT MESSAGES
//    7     TOO MANY HINTS
//    8     LOCATION HAS COND BIT BEING SET TWICE
//    9     INVALID SECTION NUMBER IN DATABASE
//    20    SPECIAL TRAVEL (500>L>300) EXCEEDS GOTO LIST
//    21    RAN OFF END OF VOCABULARY TABLE
//    22    VOCABULARY TYPE (N/1000) NOT BETWEEN 0 AND 3
//    23    INTRANSITIVE ACTION VERB EXCEEDS GOTO LIST
//    24    TRANSITIVE ACTION VERB EXCEEDS GOTO LIST
//    25    CONDITIONAL TRAVEL ENTRY WITH NO ALTERNATIVE
//    26    LOCATION HAS NO TRAVEL ENTRIES
//    27    HINT NUMBER EXCEEDS GOTO LIST
//    28    INVALID MONTH RETURNED BY DATE FUNCTION

      printf("FATAL ERROR, SEE SOURCE CODE FOR INTERPRETATION.\nPROBABLE CAUSE: ERRONEOUS INFO IN DATABASE.\nERROR CODE = %i\n",num);
}

