From: jonathan@CAD.UCLA.EDU (Jonathan Katz)
Newsgroups: soc.culture.jewish
Subject: Chanukah Stuff -- Dreidle Simulator
Date: 23 Dec 92 02:42:23 GMT
Organization: U.C.L.A. Computer Aided Design Laboratory

Hi... Somebody asked me to post this here, so here it goes....

I do not read this group, so if you wish to respond, email would probably
be best...

------------8<------Cut Here------8<----------------

/*  
   Dreidle Sim        Jonathan Katz 921221 
   
   Compile:
      cc dreidle.c -lcurses

   History:
      During the time of King Antiochus (sp?) IV, the Jews were not
allowed to practice Judaism or too study their holy books.  Therefore,
the wise men took to the practice of keeping little spinning tops
on the table along with there holy books.  If, while they were studying
in secret, some of the king's guards came to make sure that the
king's wishes were being followed, the wise men would begin to
play with their tops.  This is the origin of the Dreidle, and the origin of
giving money (or Chanukah gelt) to children so that they may play.
      This program is a little late for the start of Chanukah, but,
still is early enough to be a little fun.  This program simulates a
game of Dreidle.

The modern game is played as follows:
   The spinning top can land on one of four sides; the four sides
are labeled with the following Hebrew letters in counter-clockwise
(from the top) order:  Nun, Gimmel, Hay, Shin.  These letters
form an acronym for the Hebrew sentence "Nes Gadol Ha-ya Sham" which
means "A great miracle happened there.  Dreidles from Israel have
the Shin replaced with a Pay, for the Hebrew word "Po" which means
"here".
   The game is a form of gambling.  Whenever the pot is empty (including
at the start of the game), each player places one penny, or dollar, or
peanut, or candy, or article of clothing, etc. into the pot.  Players
then take turns spinning the Dreidle and performing an action based
on the Hebrew letter on which it lands.
The actions are as follows:
     Nun :  Nothing happens.  Next person spins.
  Gimmel :  The player gets everything in the pot (REMEMBER, the
              pot is now empty again!).  Next person spins.
     Hay :  The player get 1/2 of everything in the pot.
    Shin :  The player must add one penny, or dollar, or peanut, or
               candy, or article of clothing, etc. into the pot.
Play continues until there is only one person left with anything (or
until the kids start crying...).


   USAGE:
      By default, this program plays a standard game of Dreidle with
4 players each starting with $10.  The game spins once every 100ms.

The following run-line options are valid:
   -d NUMBER    (where NUMBER is the number of ms between spins)

   -p NUMBER    (where NUMBER is the number of starting players)

   -m NUMBER    (where NUMBER is the amount each person starts with)

   -s           (do not show the game, only the final stats.  This 
                 option also disables the between spin delay)

   -S           (this option puts a special rule into effect where if
                 a shin is rolled the player must MATCH the current
                 pot, rather than just adding one unit)

   -?
   -h           (provide a short help message on running the game)      

Other Chanukah facts:
   This is the first recorded war fought for religious freedom (165 BCE).

Fun things to do with this program:
   Run it with the -s options 1000 times, then do a statistical
     analysis on the results. 
   Laugh at the bad code.
      
*/

#include <curses.h>
#include <signal.h>


/* define globals and set default values */

int    numplayers = 4;
int    initbankroll = 10;
int    *bankroll;
int    pot;
short  standardshin = 1;
short  doprint = 1;
long   delaytime = 100000;
long   numrounds = 0;
long   numspins = 0;


/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* Called before program exit (also pointed to by signal catcher) */
void exitwell()
{
   int count, winner;

   if (doprint) endwin();
   printf("Rounds: %ld     Spins: %ld     ",numrounds, numspins);
   winner = 1;
   for(count = 2; count <= numplayers; count++)
      if(bankroll[count] > bankroll[winner]) winner = count;
   printf("FinalPot: %d     Winner: %d with $%d\n",pot, winner,bankroll[winner]);
   exit(0);
}

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

void updatescreen(int numplayers, int pot, int bankroll[])
{
   int count;

   for(count=1; count <= numplayers; count++)
      mvprintw(5+( (count - 1) * 2), 20,"%d   ",bankroll[count]);
   mvprintw(3,16, "%d   ",pot);
}

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

void playthegame()
{
   int  count,spin,curplayer,numplayercheck;
   short keepgoing = 1;

   pot = 0;
   curplayer = 0;
   while(keepgoing)
   {
      if (pot == 0)
      {
         for(count = 1; count <= numplayers; count++) 
            if(bankroll[count] >0 )
            {
               bankroll[count]--;
               pot++;
               if(doprint) mvprintw(5+( (count - 1) * 2), 28,"ANTE");
            }
         if(doprint)
         {
            updatescreen(numplayers, pot, bankroll);
            refresh();
            usleep(delaytime);
            for(count = 1; count <= numplayers; count++) 
               mvprintw(5+( (count - 1) * 2), 28,"    ");
         }
         if(pot == 1) keepgoing = 0;
      }
      if(!keepgoing) break;
      curplayer++;
      if(curplayer >numplayers) 
      { 
         curplayer = 1; 
         numrounds++;
      }
      while(bankroll[curplayer] <= 0 && keepgoing)
      {
         curplayer++;
         if(curplayer >numplayers) 
         { 
            curplayer = 1; 
            numrounds++;
         }
      }
      spin = rand()%4; numspins++;
      switch (spin)
      {
         case 0:
                if(doprint) mvprintw(5+( (curplayer - 1) * 2), 28,"Nun");
                break;
         case 1:
                if(doprint) mvprintw(5+( (curplayer - 1) * 2), 28,"Gimmel");
                bankroll[curplayer] += pot;
                pot = 0;
                if(doprint) updatescreen(numplayers, pot, bankroll);
                break;
         case 2:
                if(doprint) mvprintw(5+( (curplayer - 1) * 2), 28,"Hay");
                bankroll[curplayer] += (int)pot/2;
                pot -= (int)pot/2;
                if(doprint) updatescreen(numplayers, pot, bankroll);
                break;
         case 3:
                if(doprint) mvprintw(5+( (curplayer - 1) * 2), 28,"Shin");
                if(standardshin)
                {
                   bankroll[curplayer]--;
                   pot++;
                }
                else
                {
                   bankroll[curplayer] -= pot;
                   pot += pot;
                   if(bankroll[curplayer] < 0)
                   {
                      pot += bankroll[curplayer];
                      bankroll[curplayer] = 0;
                   }
                }
                if(doprint) updatescreen(numplayers, pot, bankroll);
                break;
      }
      if(doprint) 
      {
         refresh();
         usleep(delaytime);
         mvprintw(5+( (curplayer - 1) * 2), 28,"         ");
      }

      numplayercheck = 0;
      for(count = 1; count <= numplayers; count++)
         if(bankroll[count] > 0) numplayercheck++;
      if(numplayercheck <= 1) keepgoing = 0;

   }
}

/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
void usage(char *progname)
{
   printf(
      "%s: [-S] [-s] [-d delay] [-p numplayers] [-m init_money]\n", progname);
   printf("   where '-S' makes shin match the pot rather than add 1 unit\n"); 
   printf("   and '-s' means only print the final stats.\n");
   printf("   'delay' is in ms\n");
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

main(int argc, char *argv[]) {

   int count;


   for(count = 1; count < argc;)
   {
      switch (argv[count][1])
      {
         case 'S' :                                        /*  Shin  */
                   standardshin = 0;
                   count++;
                   break;
         case 's' :                                        /* silent */
                   doprint = 0;
                   count++;
                   break;
         case 'd' :                                     /* set delay */
                   count++;
                   delaytime = 1000 * atoi(argv[count]);
                   count++;
                   break;
         case 'p' :                                 /*set numplayers */
                   count++;
                   numplayers = atoi(argv[count]);
                   count++;
                   break;
         case 'm' :                                   /*set start $$ */
                   count++;
                   initbankroll = atoi(argv[count]);
                   count++;
                   break;
         case 'h' :                                            /*help*/
         case '?' :
                   usage(argv[0]);
                   exit(0);
         default  :
                   usage(argv[0]);
                   exit(1);
      }
   }

   srand(time(0));
   if (doprint) initscr();
   signal(SIGINT, exitwell);

   if (doprint) clear();

   if(doprint)
   mvprintw(1,5, "Game results for $%d and %d players:",
                                         initbankroll,numplayers);

   bankroll = malloc( sizeof(int) * numplayers+1);

   if(doprint) mvprintw(3,10, "Pot:");
   for(count = 1; count <= numplayers; count++)
   {
      bankroll[count] = initbankroll;
      if(doprint) mvprintw(5+( (count - 1) * 2 ), 10,"Player %d",count);
   }
   
   playthegame();

   exitwell();
}

------------8<------Cut Here------8<----------------
-- 
qp HumanNet: Jonathan Katz          |   Computer Aided Design Laboratory     qp
db AT&T-Net: (310)-825-7821         |_________     ---(*)---                 db
qp Internet: jonathan@kanga.cad.ucla.edu      |______Do you read rec.humor?  qp
db SnailNet: 38-138 Engineering IV, UCLA, LA, Ca, 90024|  No, frayed knot... db