DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T b

⟦508bf720e⟧ TextFile

    Length: 18965 (0x4a15)
    Types: TextFile
    Names: »bandit.c«

Derivation

└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
    └─⟦this⟧ »EUUGD18/General/Bandit/bandit.c« 

TextFile

/*
 *   One-Armed Bandit, v 1.01, by Pete Granger   (December 13, 1988)
 *
 * Abstract:
 *
 *   This is a slot machine simulation which uses curses routines. The
 *  setup and payoffs are described in comments below, and the means of
 *  play can be read in the print_instructions() routine.
 *
 * Notes:
 *
 *  This program has been compiled and run on a VAX running Ultrix 3.0,
 *  and on a Sun-3, Sun-4, and Sun-386i. It will compile on an IBM
 *  AT-compatible, but there are problems with the stty and curses
 *  commands. Fixes for the AT are forthcoming at an undetermined date.
 *
 *  If your machine does not have the random() and srandom() functions,
 *  then set the value of RANDOM to 0, prior to compiling, and rand() and
 *  srand() will be used instead.
 *
 *  In order to compile, the -lcurses and -ltermcap options must be
 *  used.
 *
 * Release:
 *
 *  This program is released to the public domain via usenet on February
 *  15th, 1989. You may redistribute freely, on the condition that no
 *  attempt is made to earn a profit for distributing this software. You
 *  may change the code as necessary to fit the system on which you wish
 *  to run it. The author bears no responsibility for the use or misuse
 *  of this game, or any damages caused thereby.
 *
 * Revision History:
 *
 *  1.0   12/09/88   Pete Granger
 *  First release for public use. Incorporates all basic functions.
 *
 *  1.01  12/13/88   Pete Granger
 *  Added the "refresh" option in play_game().
 *
 */

/*
   This is the configuration and payoff chart for a fair but profitable
   slot machine. It has a 9.54% chance of paying off on each play, and
   (on one-dollar bets) will pay back an average of 91.47% of all bets.

         Wheel 1     Wheel 2     Wheel 3
          -----       -----       -----
    Bars    1           1           1
   Bells    2           1           1
 Oranges    1           5           1
  Lemons    3           1           4
   Plums    3           2           3
Cherries    4           4           4


   Combination     Pays   Frequency   Total Payoff
      -----        ----     -----         -----
      Bar * 3      1000        1          1000
     Bell * 3       100        2           200
   Orange * 3        50        5           250
    Lemon * 3        20       12           240
     Plum * 3        10       18           180
   Cherry * 3         5       64           320
Cherry * 2 + Any      2      160           320
                            _____         _____
                              262         2510
                                          (234 profit)
*/

#include <stdio.h>
#include <curses.h>

#define RANDOM 1

typedef unsigned char   u_8;
typedef char            s_8;
typedef unsigned short u_16;
typedef short          s_16;
typedef unsigned long  u_32;
typedef long           s_32;

#define NUMSYMS    6
#define NAMELEN    8
#define ON_WHEEL  14
#define MIN_ROW    0
#define MAX_ROW   23
#define MIN_COL    0
#define MAX_COL   78
   
#define BAR    0
#define BELL   1
#define ORANGE 2
#define LEMON  3
#define PLUM   4
#define CHERRY 5

#define BAR3      000
#define BELL3     111
#define ORANGE3   222
#define LEMON3    333
#define PLUM3     444
#define CHERRY3   555
#define W_BAR     550
#define W_BELL    551
#define W_ORANGE  552
#define W_LEMON   553
#define W_PLUM    554

#define PAY_BAR     1000
#define PAY_BELL     100
#define PAY_ORANGE    50
#define PAY_LEMON     20
#define PAY_PLUM      10
#define PAY_CHERRY     5
#define PAY_WILD       2
#define BUST           0

#define START_MONEY 100

typedef int wheel[ON_WHEEL];

static wheel w1 = {BAR, PLUM, CHERRY, BELL, LEMON, PLUM, CHERRY,
                   ORANGE, LEMON, PLUM, CHERRY, BELL, LEMON, CHERRY};

static wheel w2 = {ORANGE, BAR, CHERRY, ORANGE, PLUM, ORANGE, CHERRY,
                   BELL, ORANGE, CHERRY, PLUM, LEMON, ORANGE, CHERRY};

static wheel w3 = {BELL, LEMON, CHERRY, ORANGE, PLUM, LEMON, CHERRY,
                   BAR, PLUM, CHERRY, LEMON, PLUM, LEMON, CHERRY};

static char symnames[NUMSYMS][NAMELEN+1] = {" *BAR*  ", "  BELL  ",
                                            " ORANGE ", " LEMON  ",
                                            "  PLUM  ", " CHERRY " };

static char winflash[6][35] = { "*    * *** *   * *   * **** **** *",
                                "*    *  *  **  * **  * *    *  * *",
                                "* ** *  *  * * * * * * ***  **** *",
                                "**  **  *  *  ** *  ** *    * *   ",
                                "*    * *** *   * *   * **** *  * *",
                                "                                  " };

#define W1ROW  10
#define W1COL   5
#define W2ROW  10
#define W2COL  17
#define W3ROW  10
#define W3COL  29

#define ODDS_R      6
#define ODDS_C     43
#define QUERY_R    19
#define QUERY_C     6
#define INVALID_R  18
#define INVALID_C   6
#define PAY_R      14
#define PAY_C       6
#define TOTAL_R    15
#define TOTAL_C     6


#define do_wheel1(W1)  {                            \
                         move(W1ROW,W1COL);         \
                         addstr(symnames[w1[W1]]);  \
                         refresh();                 \
                       }

#define do_wheel2(W2)  {                            \
                         move(W2ROW,W2COL);         \
                         addstr(symnames[w2[W2]]);  \
                         refresh();                 \
                       }

#define do_wheel3(W3)  {                            \
                         move(W3ROW,W3COL);         \
                         addstr(symnames[w3[W3]]);  \
                         refresh();                 \
                       }

#define str_out(R,C)   {                     \
                         move((R),(C));      \
                         addstr(outbuf);     \
                         refresh();          \
                       }

#define MIN(A,B) (((A)<(B)) ? (A) : (B))

char replybuf[80];
char outbuf[80];

/*
 *  Initialize the random number generator.
 */

void init_rand()
{
  u_32 z;

  z = time();
#if RANDOM
  srandom(z);
#else
  srand(z);
#endif
}

/*
 *  Returns an integer in the range from min to max, inclusive.
 */

s_16 range(min,max)
u_16 min, max;
{
  u_8 det;
  u_16 dist;
  s_16 return_val, discard;

#if RANDOM
  det = random() % 100 + 1;
#else
  det = rand() % 100 + 1;
#endif
  dist = max - min + 1;
  if (det > 50)
#if RANDOM
    discard = random();
  return_val = random() % dist + min;
#else
    discard = rand();
  return_val = rand() % dist + min;
#endif
  return(return_val);
}

/*
 * Prompt the user at a break in the instructions.
 */

rest()
{
	printf(" -- More --   ");
    while (getchar() != ' ');
}

/*
 * Give the user instructions on the game.
 */

void print_instructions(in_char)
char in_char;
{
system("clear");
if (in_char != 'y' && in_char != 'Y') return;
system("stty cbreak -echo");
printf("                   Instructions for One-Armed Bandit\n");
printf("                                  by\n");
printf("                             Pete Granger\n\n");
printf("OBJECT:   To amass a fortune, of course. Also to have a good time\n");
printf("        playing the slots.\n\n");
printf(" MEANS:   I have designed a slot machine which I consider to be\n");
printf("        fairly honest. By both statistical and empirical means,\n");
printf("        it is calculated to have a payoff rate of about 91 percent.\n");
printf("        The payoffs are as follows:\n\n");
printf("               Combination     Pays   Frequency   Total Payoff\n");
printf("                  -----        ----     -----         -----\n");
printf("                  Bar * 3      1000         1          1000\n");
printf("                 Bell * 3       100         2           200\n");
printf("               Orange * 3        50         5           250\n");
printf("                Lemon * 3        20        12           240\n");
printf("                 Plum * 3        10        18           180\n");
printf("               Cherry * 3         5        64           320\n");
printf("            Cherry * 2 + Any      2       160           320\n");
printf("                                        -----         -----\n");
printf("                                          262          2510\n");
rest();
printf("\n\n\n\n");
printf("          You will be given an initial bankroll of $%d. Not\n",
        START_MONEY);
printf("        bad for a day at the casino, right? On each play, you can\n");
printf("        bet from $1 to $5, and the payoff will be proportional\n");
printf("        to the bet. You may also place a bet of 0, which means you\n");
printf("        want to sit out this round, and watch the wheels spin. The\n");
printf("        catch, of course, is that you don't win anything this way.\n");
printf("        The only other restriction is that your bet can't exceed\n");
printf("        your current bankroll.\n");
printf("\n");
printf("          If you wish to refresh the screen (e.g. after receiving\n");
printf("        system messages) enter a 'r' at the 'Bet?' prompt.\n");
printf("\n");
printf("          If you decide you want to quit, just enter a 'q' at the\n");
printf("        'Bet?' prompt. You can then cash in your winnings and\n");
printf("        leave the casino.\n");
printf("\n");
printf("          Also, if your bankroll reaches 0, you will be asked to\n");
printf("        leave the casino. But don't worry, you can always come\n");
printf("        back later.\n");
printf("\n");
printf("              Good luck, and enjoy One-Armed Bandit!\n");
printf("\n");
rest();
system("stty -cbreak echo");
system("clear");
}

/*
 *  Blank part of a line with curses.
 */

void blank_seg(row,col,length)
u_16 row,col,length;
{
  char locbuf[80];
  u_8 i;

  if (row >= MIN_ROW && row <= MAX_ROW && col >= MIN_COL && col <= MAX_COL)
  {
    if ((col+length-1) > MAX_COL)
      length = MAX_COL - col + 1;
    for (i = 0; i < length; i++)
      locbuf[i] = ' ';
    locbuf[i] = '\0';
    move(row,col);
    addstr(locbuf);
    refresh();
  }
}

/*
 *  Print an odds chart on the screen.
 */

void show_odds()
{
  extern char outbuf[];
  extern char symnames[NUMSYMS][NAMELEN+1];

  sprintf(outbuf,"          Pete Granger's");
  str_out(ODDS_R-5,ODDS_C);
  sprintf(outbuf,"         ONE-ARMED BANDIT");
  str_out(ODDS_R-4,ODDS_C);
  sprintf(outbuf,"        Combination        | Odds");
  str_out(ODDS_R-2,ODDS_C);
  sprintf(outbuf,"---------------------------+------");
  str_out(ODDS_R-1,ODDS_C);
  sprintf(outbuf,"%s %s %s | %4d",
          symnames[BAR],symnames[BAR],symnames[BAR],PAY_BAR);
  str_out(ODDS_R,ODDS_C);
  sprintf(outbuf,"%s %s %s | %4d",
          symnames[BELL],symnames[BELL],symnames[BELL],PAY_BELL);
  str_out(ODDS_R+BELL,ODDS_C);
  sprintf(outbuf,"%s %s %s | %4d",
          symnames[ORANGE],symnames[ORANGE],symnames[ORANGE],PAY_ORANGE);
  str_out(ODDS_R+ORANGE,ODDS_C);
  sprintf(outbuf,"%s %s %s | %4d",
          symnames[LEMON],symnames[LEMON],symnames[LEMON],PAY_LEMON);
  str_out(ODDS_R+LEMON,ODDS_C);
  sprintf(outbuf,"%s %s %s | %4d",
          symnames[PLUM],symnames[PLUM],symnames[PLUM],PAY_PLUM);
  str_out(ODDS_R+PLUM,ODDS_C);
  sprintf(outbuf,"%s %s %s | %4d",
          symnames[CHERRY],symnames[CHERRY],symnames[CHERRY],PAY_CHERRY);
  str_out(ODDS_R+CHERRY,ODDS_C);
  sprintf(outbuf,"%s %s %s | %4d",
          symnames[CHERRY],symnames[CHERRY]," *wild* ",PAY_WILD);
  str_out(ODDS_R+CHERRY+1,ODDS_C);
}


/*
 *  Draw a box with curses, given the top left and bottom right corners.
 */

void draw_box(tlr,tlc,brr,brc)
s_16 tlr,tlc,brr,brc;
{
  u_8 i, j;
  u_16 tmp;

  if (tlc > brc)
  {
    tmp = brc; brc = tlc; tlc = tmp;
  }
  if (tlr > brr)
  {
    tmp = brr; brr = tlr; tlr = tmp;
  }
  if (tlc < 0) tlc = 0;
  else if (tlc > 78) tlc = 78;
  if (brc < 0) brc = 0;
  else if (brc > 78) brc = 78;
  if (tlr < 0) tlr = 0;
  else if (tlr > 23) tlr = 23;
  if (brr < 0) brr = 0;
  else if (brr > 23) brr = 23;
  move(tlr,tlc); addch('+'); refresh();
  move(brr,tlc); addch('+'); refresh();
  for (i = tlc + 1; i < brc; i++)
  {
    move(tlr,i); addch('-'); refresh();
    move(brr,i); addch('-'); refresh();
  }
  move(tlr,brc); addch('+'); refresh();
  move(brr,brc); addch('+'); refresh();
  for (i = tlr + 1; i < brr; i++)
  {
    move(i,tlc); addch('|'); refresh();
    for (j = tlc + 1; j < brr; j++)
    {
      move(i,j); addch(' '); refresh();
    }
    move(i,brc); addch('|'); refresh();
  }
}

/*
 *  Draw the three windows where the wheels appear.
 */

void draw_windows()
{
  extern void draw_box();

  draw_box(W1ROW-2,W1COL-2,W1ROW+2,W1COL+NAMELEN+1);
  draw_box(W2ROW-2,W2COL-2,W2ROW+2,W2COL+NAMELEN+1);
  draw_box(W3ROW-2,W3COL-2,W3ROW+2,W3COL+NAMELEN+1);
}

/*
 * Convert the three wheel indices into a simple integer.
 */

u_16 wheel_sum(s1,s2,s3)
u_8 s1,s2,s3;
{
  extern wheel w1, w2, w3;

  u_16 return_val;

  return_val = (100 * w1[s1]) + (10 * w2[s2]) + w3[s3];
  return(return_val);
}

/*
 * Determine the payoff odds based on the three wheel indices.
 */

u_16 payoff(s1,s2,s3)
u_8 s1,s2,s3;
{
  extern u_16 wheel_sum();

  u_16 payoff_index, return_val;

  payoff_index = wheel_sum(s1,s2,s3);
  switch (payoff_index)
  {
    case BAR3:     return_val = PAY_BAR;
                   break;
    case BELL3:    return_val = PAY_BELL;
                   break;
    case ORANGE3:  return_val = PAY_ORANGE;
                   break;
    case LEMON3:   return_val = PAY_LEMON;
                   break;
    case PLUM3:    return_val = PAY_PLUM;
                   break;
    case CHERRY3:  return_val = PAY_CHERRY;
                   break;
    case W_BAR:
    case W_BELL:
    case W_ORANGE:
    case W_LEMON:
    case W_PLUM:   return_val = PAY_WILD;
                   break;
    default:       return_val = BUST;
                   break;
  }
  return(return_val);
}

/*
 *  Flash the "WINNER!" box on a jackpot.
 */

void flash_win(payoff)
u_16 payoff;
{
  extern void draw_box();
  extern void blank_seg();
  extern char winflash[6][35];
  extern char outbuf[];

  u_8 i, j, flashes;

  draw_box(1,W1COL-2,W1ROW-3,W3COL+NAMELEN+1);
  if (payoff >= PAY_BAR)
    flashes = 10;
  else if (payoff >= PAY_ORANGE)
    flashes = 6;
  else
    flashes = 3;
  for (i = 0; i < flashes; i++)
  {
    for (j = 0; j < 5; j++)
    {
      sprintf(outbuf,winflash[j]);
      str_out(j+2,W1COL-1);
    }
    if (i == flashes - 1)
      sleep(8);
    else
      for (j = 0; j < 5; j++)
      {
        sprintf(outbuf,winflash[5]);
        str_out(j+2,W1COL-1);
      }
  }
  for (i = 0; i < 7; i++)
    blank_seg(i+1,W1COL-2,36);
}

/*
 *  Refresh the screen at the user's request. Handy if you get mail in
 *  the middle of a game or something.
 */

void refresh_screen(ts,br)
u_32 ts, br;
{
  extern void draw_windows();
  extern void show_odds();
  extern void blank_seg();
  extern char outbuf[];

  initscr();
  draw_windows();
  show_odds();
  if (!ts)
  {
    blank_seg(TOTAL_R,TOTAL_C,78);
    sprintf(outbuf,"Starting bankroll: %d",br);
    str_out(TOTAL_R,TOTAL_C);
  }
  else
  {
    blank_seg(TOTAL_R,TOTAL_C,78);
    sprintf(outbuf,"New total (after %d %s) is %d.",
            ts,((ts != 1) ? "plays" : "play"),br);
    str_out(TOTAL_R,TOTAL_C);
  }
}

void play_game()
{
  extern s_16 range();
  extern u_16 payoff();
  extern void draw_windows();
  extern void show_odds();
  extern void flash_win();
  extern void refresh_screen();
  extern void blank_seg();
  extern wheel w1, w2, w3;
  extern char symnames[NUMSYMS][NAMELEN+1];
  extern char replybuf[];
  extern char outbuf[];

  u_8  r1, s1, r2, s2, r3, s3, offset;
  u_8  this_bet, maxbet;
  u_16 c1, c2, c3, counter;
  u_32 bankroll, times_spun, payoffs;

  bankroll = START_MONEY;
  this_bet = 0;
  payoffs = times_spun = 0;
  s1 = s2 = s3 = 0;
  initscr();
  draw_windows();
  show_odds();
  while (bankroll)
  {
    if (!times_spun)
    {
      blank_seg(TOTAL_R,TOTAL_C,78);
      sprintf(outbuf,"Starting bankroll: %d",bankroll);
      str_out(TOTAL_R,TOTAL_C);
    }
    maxbet = MIN(5,bankroll);
    sprintf(outbuf,"How much do you wish to bet (0-%d)? ",maxbet);
    blank_seg(QUERY_R,QUERY_C,78);
    str_out(QUERY_R,QUERY_C);
    if (gets(replybuf) == NULL) continue;
    if (replybuf[0] == 'q' || replybuf[0] == 'Q')
      break;
    else if (replybuf[0] == 'r' || replybuf[0] == 'R')
      refresh_screen(times_spun,bankroll);
    else
    {
      if ((this_bet = atoi(replybuf)) > maxbet)
      {
        sprintf(outbuf,"You can't bet that much!");
        str_out(INVALID_R,INVALID_C);
        continue;
      }
      else
        blank_seg(INVALID_R,INVALID_C,30);
      if (this_bet)
        times_spun++;
      r1 = range(5,8);
      r2 = r1 + range(2,4);
      r3 = r2 + range(2,4);
      s1 = (s1 + range(0,ON_WHEEL-1)) % ON_WHEEL;
      s2 = (s2 + range(0,ON_WHEEL-1)) % ON_WHEEL;
      s3 = (s3 + range(0,ON_WHEEL-1)) % ON_WHEEL;
      c1 = ON_WHEEL * r1 + s1;
      c2 = ON_WHEEL * r2 + s2;
      c3 = ON_WHEEL * r3 + s3;
      bankroll -= this_bet;
      for (counter = 0; counter <= c3; counter++)
      {
        offset = counter % ON_WHEEL;
        if (counter <= c1)
          do_wheel1(offset);
        if (counter <= c2)
          do_wheel2(offset);
        do_wheel3(offset);
      }
      if (payoff(s1,s2,s3))
      {
        flash_win(payoff(s1,s2,s3));
        sprintf(outbuf,"The payoff for %d %s is %d.",this_bet,
                ((this_bet != 1) ? "dollars" : "dollar"),
                (this_bet * payoff(s1,s2,s3)));
        bankroll += (this_bet * payoff(s1,s2,s3));
        if (this_bet)
          payoffs++;
      }
      else
        sprintf(outbuf,"No winner.");
      blank_seg(PAY_R,PAY_C,40);
      str_out(PAY_R,PAY_C);
      blank_seg(TOTAL_R,TOTAL_C,78);
      sprintf(outbuf,"New total (after %d %s) is %d.",
              times_spun,((times_spun != 1) ? "plays" : "play"),bankroll);
      str_out(TOTAL_R,TOTAL_C);
    }
  }
  blank_seg(QUERY_R,QUERY_C,78);
  endwin();
  if (!bankroll)
  {
    printf("\nYou are bankrupt after %d %s, %d %s.\n",
            times_spun,((times_spun != 1) ? "plays" : "play"),
            payoffs,((payoffs != 1) ? "payoffs" : "payoff"));
    printf("\nLuck does not seem to be with you. Unfortunately,\n");
    printf("Guido and Vito, the casino's bouncers, are. They grab\n");
    printf("you by the elbows and escort you to the sidewalk.\n\n");
    printf("                      GAME OVER\n\n");
  }
  else
    printf("\nTotal of %d after %d %s, %d %s.\n",bankroll,
            times_spun,((times_spun != 1) ? "plays" : "play"),
            payoffs,((payoffs != 1) ? "payoffs" : "payoff"));
}

void main()
{
  extern void init_rand();
  extern void play_game();
  extern char replybuf[];
  extern void print_instructions();

  system("clear");
  printf("Would you like instructions, y/n [default is n] -> ");
  fflush(stdout);
  while (gets(replybuf) == NULL);
  print_instructions(replybuf[0]);
  init_rand();
  play_game();
}