|
|
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