|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T b
Length: 18965 (0x4a15) Types: TextFile Names: »bandit.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Bandit/bandit.c«
/* * 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(); }