|
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 y
Length: 12059 (0x2f1b) Types: TextFile Names: »yid-slots.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/YidSlots/yid-slots.c«
/* Yid Slots * (c) 1987 by Bob Glickstein * * See the README file for information regarding the legal status of * this software. * * Program simulates a slot machine in which the first of three windows * contains typical Jewish first names; the second window * conatins typical Jewish last-name-prefixes; and the third window * contains typical Jewish last-name-suffixes. A file is read in * to determine the set of name-parts. The file contains payoffs for * certain combinations. In the default file, the biggest * payoff is for the combination "Bob Glick stein". */ /* FORMAT OF DATA FILE CONTAINING NAMES PARTS AND PAYOFFS: * <list-of-first-names-each-separated-by-white-space> * <nl>*<nl> (That is, an asterisk alone on a line) * <list-of-last-name-prefixes-each-separated-by-white-space> * <nl>*<nl> * <list-of-last-name-suffixes-each-separated-by-white-space> * <nl>*<nl> * <a-first-name> <a-prefix> <a-suffix> <a-payoff-number><nl> * (this last line can be repeated as many times as you like, for as * many payoffs as you'd like to have. The payoff-number is the number * of credits to return for every credit that was bet. A "?" in any of the * first name, prefix, or suffix positions matches anything. * * RESTRICTIONS: No single string in the data file may be >= 20 chars * in length. */ #include <stdio.h> #include <curses.h> #include "yid-slots.h" struct namenode *names[3]; /* names[0] points to a linked list of first * names; names[1] to a linked list of * prefixes; names[2] to suffixes */ struct namenode *curnode[3]; /* These pointers hold our current position * within the lists pointed to by names. (By * current position, I mean the nodes * appearing in the CENTER of the window. * These pointers trail behind the printnode * pointers.) */ struct namenode *printnode[3]; /* Points to the nodes being printed in the * windows. When the wheels stop spinning, * these pointers point to nodes in the * BOTTOMS of the windows. Curnode points to * nodes in the CENTERS of the windows (these * are the nodes that win). */ struct payoff *payoffs; /* A linked list of payoffs */ WINDOW *betwin, *textwin, *namewins[3]; /* betwin displays current * money & current bet; * textwin is a dialogue * window; namewins are the * three slot machine windows */ WINDOW *boxwin; /* boxwin displays a box around name windows */ int bankroll; /* Amount of money player has */ main(argc, argv) int argc; char *argv[]; { char *fname; if (argc == 2) fname = argv[1]; else { if (argc == 1) fname = FDEFAULT; else { fprintf(stderr, "Usage: %s [yidnamefile]\n", argv[0]); exit(1); } } initglobals(); if (readnamefile(fname)) { /* if file successfully read */ initdisplay(); signon(); play(); signoff(); cleanup(); } else { cleanup(); fprintf(stderr, "%s: error reading file %s\n", argv[0], fname); exit(1); } } /* advance - given an index into names[], and a pointer to the current * position, advance returns the next position in the linked list * names[i], wrapping around to the head of the list at the end */ struct namenode *advance(i, ptr) int i; struct namenode *ptr; { return ((ptr->next) ? ptr->next : names[i]); } /* My own random-number generator, generates a random number between 0 and * n-1 (the argument). Call this fn. with an arg. of 0 to seed the generator * randomly (will return 0). */ long bgrandom(n) long n; { long time(), random(); if (!n) srandom((int) (time(NULL) & 0377)); else return (random() % n); } initglobals() { bgrandom((long) 0); names[0] = names[1] = names[2] = NULL; payoffs = NULL; curnode[0] = curnode[1] = curnode[2] = NULL; printnode[0] = printnode[1] = printnode[2] = NULL; initscr(); namewins[0] = newwin(WINDOWHEIGHT, WINDOWWIDTH, WINDOW_Y_START, 1); namewins[1] = newwin(WINDOWHEIGHT, WINDOWWIDTH, WINDOW_Y_START, 3 + WINDOWWIDTH); namewins[2] = newwin(WINDOWHEIGHT, WINDOWWIDTH, WINDOW_Y_START, 5 + 2 * WINDOWWIDTH); boxwin = newwin(WINDOWHEIGHT + 2, 7 + 3 * WINDOWWIDTH, WINDOW_Y_START - 1, 0); textwin = newwin(AUX_WINHEIGHT, TEXTWIDTH, WINDOWHEIGHT + WINDOW_Y_START + 2, 0); betwin = newwin(AUX_WINHEIGHT, BETWIDTH, WINDOWHEIGHT + WINDOW_Y_START + 2, TEXTWIDTH + 2); scrollok(namewins[0], TRUE); scrollok(namewins[1], TRUE); scrollok(namewins[2], TRUE); scrollok(textwin, TRUE); bankroll = INIT_BANKROLL; } /* initdisplay() does things like erase the windows, draw the boxes, * fill in non-changing text (like the templates "Amount in wallet:" * and "Amount of bet:" in the betwindow * MOST IMPORTANTLY, this routine fills up the three windows with the first * few name parts and sets all of the pointers correctly (curnode, * printnode). */ /* WARNING: contains lots of hardwired numbers */ initdisplay() { int i, j; werase(textwin); werase(betwin); wprintw(betwin, "You have:\n %d\nAmt. of bet:\n %d", bankroll, 0); wrefresh(textwin); wrefresh(betwin); werase(boxwin); box(boxwin, '.', '.'); for (j = 1; j <= 5; ++j) { wmove(boxwin, j, 23); waddstr(boxwin, ".."); wmove(boxwin, j, 47); waddstr(boxwin, ".."); } wmove(boxwin, 3, 0); waddch(boxwin, '-'); wmove(boxwin, 3, 23); waddstr(boxwin, "--"); wmove(boxwin, 3, 47); waddstr(boxwin, "--"); wmove(boxwin, 3, 72); waddch(boxwin, '-'); wrefresh(boxwin); for (i = 0; i < 3; ++i) { werase(namewins[i]); printnode[i] = names[i]; wprintw(namewins[i], "%s", printnode[i]->name); } for (i = 0; i < 3; ++i) { printnode[i] = advance(i, printnode[i]); wprintw(namewins[i], "\n%s", printnode[i]->name); } for (i = 0; i < 3; ++i) { curnode[i] = printnode[i] = advance(i, printnode[i]); wprintw(namewins[i], "\n%s", printnode[i]->name); } for (j = 1; j <= 2; ++j) for (i = 0; i < 3; ++i) { printnode[i] = advance(i, printnode[i]); wprintw(namewins[i], "\n%s", printnode[i]->name); } for (i = 0; i < 3; ++i) { overwrite(namewins[i], boxwin); wrefresh(namewins[i]); } } cleanup() { endwin(); } int readnamefile(fname) /* Attempts to load names in from a * hopefully correct-format namefile */ char *fname; { FILE *fp; int i, tpay; char buffer[3][BUFLEN], *malloc(); struct namenode *tnode; struct payoff *tpayoff; if (!(fp = fopen(fname, "r"))) return (FALSE); /* No Good */ for (i = 0; i < 3; ++i) { do { fscanf(fp, "%s", buffer[0]); if (buffer[0][0] != DELIM) { tnode = (struct namenode *) malloc(sizeof(struct namenode)); tnode->name = malloc(1 + strlen(buffer[0])); /* * WARNING: These malloc's are not checked for failure */ strcpy(tnode->name, buffer[0]); tnode->next = names[i]; names[i] = tnode; /* Links it into the list */ } } while (buffer[0][0] != DELIM); } while (fscanf(fp, "%s %s %s %d", buffer[0], buffer[1], buffer[2], &tpay) == 4) { tpayoff = (struct payoff *) malloc(sizeof(struct payoff)); for (i = 0; i < 3; ++i) { tpayoff->parts[i] = malloc(1 + strlen(buffer[i])); strcpy(tpayoff->parts[i], buffer[i]); } tpayoff->pay = tpay; tpayoff->next = payoffs; payoffs = tpayoff; /* Links it into the list */ } return (TRUE); } signon() { wprintw(textwin, "Welcome to Yid Slots\n(c) 1987 by Bob Glickstein\n"); wrefresh(textwin); } signoff() { wprintw(textwin, "Thank you for playing Yid Slots\n"); wrefresh(textwin); } /* Main loop of program */ play() { int bet; while (bankroll > 0) { if (!(bet = placebet())) return; /* A bet of zero ends the game */ spin(); bankroll += settle(bet);/* settle() returns -bet if no winning * combinations came up; otherwise, it * returns the number of credits by which to * augment bankroll */ wmove(betwin, 1, 1); wprintw(betwin, "%d", bankroll); wclrtoeol(betwin); wrefresh(betwin); } } /* Dialogue & input of bet amount */ int placebet() { int again = TRUE, bet; wprintw(textwin, "Place your bet (0 ends the game)\n "); wrefresh(textwin); while (again) { wscanw(textwin, "%d", &bet); wrefresh(textwin); if ((bet < 0) || (bet > bankroll)) { wprintw(textwin, "Bet must be non-negative and affordable\n"); wrefresh(textwin); again = TRUE; } else again = FALSE; } wmove(betwin, 3, 1); wprintw(betwin, "%d", bet); wclrtoeol(betwin); wrefresh(betwin); return (bet); } /* Set the wheels a-spin, stopping them one at a time after * a random interval (maximum MAXSPIN ticks per wheel) */ spin() { int counter; long r; for (counter = 0; counter < 3; ++counter) for (r = MAXSPIN; r && bgrandom(r); --r) spinwheels(counter); } /* Advance wheels counter through 2 one tick each */ spinwheels(counter) int counter; { int i; for (i = counter; i < 3; ++i) { printnode[i] = advance(i, printnode[i]); curnode[i] = advance(i, curnode[i]); wprintw(namewins[i], "\n%s", printnode[i]->name); wrefresh(namewins[i]); } } /* Examine what came up on the wheels. Compare against * winning combinations in the payoffs linked list. If there * is a match, return the payoff times the bet placed. If * not, return -bet */ int settle(bet) int bet; { struct payoff *ptr; wmove(betwin, 3, 1); wprintw(betwin, "%d", 0); wclrtoeol(betwin); wrefresh(betwin); for (ptr = payoffs; ptr && !match(ptr); ptr = ptr->next); wprintw(textwin, "%s %s%s - ", curnode[0]->name, curnode[1]->name, curnode[2]->name); if (ptr) { wprintw(textwin, "pays %d:1!\n", ptr->pay); wrefresh(textwin); return (bet * ptr->pay); } else { wprintw(textwin, "does not pay\n"); wrefresh(textwin); return (-bet); } } /* Predicate: do all three curnode[] pointers match the given * payoff pointer? */ int match(ptr) struct payoff *ptr; { int i, matched = TRUE; for (i = 0; (i < 3) && matched; ++i) matched = matched && ((!strcmp(ptr->parts[i], MATCHANY)) || (!strcmp(ptr->parts[i], curnode[i]->name))); return (matched); } #ifdef DEBUG report(str) char *str; { fprintf(stderr, "* %s\n", str); } #endif