jxs7451@ritcv.UUCP (jeff) (04/30/86)
This is the hangman game I was talking about in net.games. I've had a few requests, which said to post, so i did. The game was designed on a 780 running Ultrix 1.1, and on a 785 running 4.2BSD. It seems to work, but if you have any problms please respond either to me or to net.games. Jeff Smith ritcv!jxs7451 "Please help me, I need a coop job!!" +---------------------------------------------------------------------------+ +------------------------------cut here-------------------------------------+ #! /bin/sh # hangman distribuiton file. # to get individual files execute this file. # written by: ritcv!jxs7451 # help from ritcv!jeb1265 with screen.c (from ogre) echo 'start of hangman v3.00(js)' echo x- doargs.c sed 's/X //' > doargs.c << '/' X /* doargs.c X * handles command line arguments X * written by: ritcv!jxs7451 X */ X #include "hangman.h" X #include<stdio.h> X #include<strings.h> X #define OPLEN 7 /* max length of input options string */ X X doargs(argc, argv, debug, hard, length) X int argc; X char *argv[]; X int *debug; X int *hard; X int *length; X { X char *strcpy(); X char buf[OPLEN]; /* holds argv[1] for decoding */ X int i; /* loop counter */ X X if ((argc > 2) || (strlen(argv[1]) > (OPLEN - 1))) /* too many arguments */ X usage(); X if (argc == 2) /* must be an attempted option */ X { X strcpy(buf,argv[1]); X if (buf[0] != '-') X usage(); X for(i=1;buf[i] != '\0';i++) X switch(buf[i]) { X case 'D' : X if (!(*debug)) X if (DBUG == getuid()) X (*debug)++; X else X { X puts("Debug permission denied."); X exit(0); /* terminate program */ X } X else X usage(); X break; X case 'h': X if (!(*hard)) X *hard = 1; X else if (*hard == 2) X twolev(); X else X usage(); X break; X case 'e': X if (!(*hard)) X *hard = 2; X else if (*hard == 1) X twolev(); X else X usage(); X break; X case 'l': X if (!(*length)) X *length = 1; X else if (*length == 2) X twolen(); X else X usage(); X break; X case 'L': X if (!(*length)) X *length = 2; X else if (*length == 1) X twolen(); X else X usage(); X break; X default: X usage(); X break; X } /* switch */ X } X } / echo x- doquit.c sed 's/X //' > doquit.c << '/' X /* doquit.c X * process 'Q' command...ie quit X * written by: ritcv!jxs7451 X */ X #include "hangman.h" X #include<stdio.h> X doquit() X { X int ch; X X clbtm(); X setcur(ERROR,1); X printf("Really quit(y/n)? "); X ch = getchar(); X putchar(ch); X /* eof */ X if ((ch != 'Y') && (ch != 'y')) X { X setcur(ERROR,1); X erasel(0,0); X puts("Not quitting.\n"); X return(0); X } X else /* really quit */ X { X setcur(ERROR,1); X erasel(0,0); X printf("Quitting hangman %s.\n",VERSION); X reset_term(); X exit(0); X } X } X / echo x- getlet.c sed 's/X //' > getlet.c << '/' X /* getlet.c X * gets 1 letter of input. does error stuff also X * written by: ritcv!jxs7451 X */ X #include "hangman.h" X #include<stdio.h> X getlet() X { X int ch; X X ch = getchar(); X putchar(ch); X if ((ch < 'a') || (ch > 'z')) X switch(ch) { X case '!': /* shell escape */ X case 'G': /* string guess */ X case 'Q': /* Quit */ X case '?': /* help command */ X case 18 : /* refresh screen */ X break; X default: X clbtm(); X setcur(ERROR,1); X printf("Illegal command, try again."); X setcur(ERROR - 1,1); X erasel(0,0); X printf(PROMPT); X ch = getlet(); X break; X } X return(ch); X } / echo x- getrand.c sed 's/X //' > getrand.c << '/' X /* getrand.c X * returns a random number that is the # to the word in word list X * written by: ritcv!jxs7451 X */ X #include "hangman.h" X #include<stdio.h> X long getrand() X { X float one = random(),two = random(),tmp; X int goo; X tmp = one / two; X goo = (int) tmp; X tmp -= goo; /* now have a random # between 0 and 1 */ X return((long) (tmp * WORDMAX + 1)); X } / echo x- getwd.c sed 's/X //' > getwd.c << '/' X /* getwd.c X * gets word, and if debug defined prints the word X * written by: ritcv!jxs7451 X */ X #include "hangman.h" X #include<stdio.h> X X getwd(word, length) X char word[]; X int *length; X { X long getrand(); /* random number generator */ X int fd; /* file descriptor */ X int i; /* everyday array counter */ X int flag=0; /* flag==1 if need to get new word */ X char ch; /* 1 character buffer */ X X fd = open(WORDL,0); X lseek(fd,getrand(),0); /* goto offset position */ X for (read(fd,&ch,1);ch != '\n';read(fd,&ch,1)); /* skip to next word */ X for (read(fd,&ch,1),i=0;ch != '\n';read(fd,&ch,1),i++) X word[i] = ch; X close(fd); X word[i] = '\0'; X X for (i=0;word[i] != '\0';i++) /* mapping caps to smalls */ X if ((word[i] >= 'A') && (word[i] <='Z')) X word[i] -= ('A' - 'a'); X if ((i-2) < *length) /* i-2 is length of the word */ X flag++; X X for (i=0;word[i] != '\0';i++) /* checking for non lowercase */ X if ((word[i] < 'a') || (word[i] > 'z')) X { X flag++; /* set flag */ X break; /* exit loop */ X } X X if (flag) /* checking if need to get another word */ X getwd(word, length); X } / echo x- hangman.c sed 's/X //' > hangman.c << '/' X /* hangman.c X * X * hangman game. uses termcap...terminal must be in /etc/termcap X * written by: ritcv!jxs7451 X * help with screen.c from: ritcv!jeb1265 (from ogre i guess) X * X * To run on another system: adjust WORDL and WORDMAX X * X * Program is designed and tested on Ultrix 1.1 and 4.2BSD X */ X #include "hangman.h" X #include<stdio.h> X #include<strings.h> X #include<signal.h> X X main(argc, argv) X int argc; X char *argv[]; X { X int debug = 0; /* 1 if debug permission granted */ X int hard = 0; /* 1 if hard is requested */ X int length = 0; /* minimum length of a word */ X int nl = 0; /* loop counter variable */ X int right = 0; /* 1 if got word right */ X int ch = 0; /* holds users guess */ X int left; /* tries left */ X int att = 0; /* attempts used */ X int flag = 0; /* general flag */ X char word[MAXLINE]; /* string for actuall word */ X char guess[MAXLINE]; /* the string guessed */ X int tried[127]; /* entry 1 if char tried */ X X doargs(argc, argv, &debug, &hard, &length); X switch (length) { X case 1: /* harder */ X length = LMINWORD; X break; X case 2: /* hard */ X length = LLMINWORD; X break; X default: /* normal */ X length = MINWORD; X break; X } X switch (hard) { X case 1: X left = HTRIES; /* hard */ X break; X case 2: X left = ETRIES; /* easy */ X break; X default: X left = TRIES; /* norm */ X break; X } X X /* set so cannot stop or break. term gets messed up if stop abnormally */ X signal(SIGTSTP, SIG_IGN); /* stop signal */ X signal(SIGINT, SIG_IGN); /* interupt */ X signal(SIGQUIT, SIG_IGN); /* quit */ X X initman(left); X srandom(time()); X init_term(); X getwd(word, &length); X cltried(tried); X X for (nl=0;word[nl] != '\0';nl++) /* putting - in guess string */ X guess[nl] = '-'; X drawscrn(); X X while (!right && left) X { X turninfo(guess,att,left,tried,word,debug); X setcur(ERROR - 1,1); X erasel(0,0); X printf(PROMPT); X X while (tried[(ch = getlet())] != 0) X { X switch (ch) { X case '!' : X doshell(); X init_term(); X drawscrn(); X turninfo(guess,att,left,tried,word,debug); X break; X case 'G' : X clbtm(); X setcur(ERROR,1); X puts("Enter the whole word."); X printf("enter the word: "); X nl = wordguess(word); X switch (nl) { X case 1: /* win */ X turninfo(word,att,left,tried,word,debug); X puts("\nSuper guess!! You got it right."); X if (left > 1) X printf("You had %d guesses left.\n",left); X else X puts("You had 1 guess left."); X reset_term(); X exit(0); X break; X case 2: /* lose */ X att++; X killman(); X turninfo(word,att,left,tried,word,debug); X clbtm(); X setcur(ERROR,1); X puts("Nope, thats not it."); X die(att); /* echo hangman */ X reset_term(); X exit(0); /* quit */ X break; X default: /* continue */ X break; X } X turninfo(guess,att,left,tried,word,debug); X break; X case 'Q' : X doquit(); X turninfo(guess,att,left,tried,word,debug); X break; X case '?' : X help(); X turninfo(guess,att,left,tried,word,debug); X break; X case 18 : X drawscrn(); X turninfo(guess,att,left,tried,word,debug); X break; X default: X clbtm(); X setcur(ERROR,1); X puts("You already tried that letter."); X break; X } /* end of switch */ X setcur(ERROR - 1,1); X erasel(0,0); X printf(PROMPT); X } X tried[ch] = 1; /* set tried */ X X for (nl=flag=0;word[nl] != '\0';nl++) /* check if guess in word */ X if (word[nl] == (char) ch) X { X guess[nl] = (char) ch; X flag++; /* set flag */ X } X X if (!flag) /* flag set if gets 1 right */ X { X left--; X incman(); X clbtm(); X setcur(ERROR,1); X printf("nope, no '%c' in the word.\n",ch); X } X else X { X clbtm(); X setcur(ERROR,1); X printf("Good guess!!"); X } X X right = !(strcmp(guess,word)); /* check if done */ X att++; /* increment tries */ X } X X clbtm(); X turninfo(word,att,left,tried,word,debug); X if (right) X if (left > 1) X printf("You got it in %d attempts, with %d misses left.\n",att,left); X else X printf("You got it in %d attempts, with %d miss left.\n",att,left); X else X die(att); X reset_term(); X } / echo x- lib.c sed 's/X //' > lib.c << '/' X /* lib.c X * group of short hangman library routines. X * written by: ritcv!jxs7451 X */ X #include "hangman.h" X #include<stdio.h> X X /* prints out the dead punk */ X die(att) X int att; X { X if (att > 1) X printf("You used %d turns to lose %s.\n\n",att,getlogin()); X else X printf("You used %d turn to lose %s.\n\n",att,getlogin()); X puts("Better luck next time!"); X } X X /* does shell escape to login shell */ X doshell() X { X char *getenv(); X X clbtm(); X setcur(ERROR,1); X printf("sporning a shell. ^D to return to hangman %s\n",VERSION); X reset_term(); X system(getenv("SHELL")); X } X X /* function to print out some quick help info */ X help() X { X setcur(1,1); X epage(); X printf("\nHangman %s help:\n",VERSION); X puts("commands:"); X puts(" 'a' to 'z' : choose that letter"); X puts(" '!' : shell escape to login shell"); X puts(" 'G' : try to guess the whole word"); X puts(" '?' : print help"); X puts(" '^R' : redraw screen (control r)"); X puts(" 'Q' : quit hangman\n"); X puts("- all words contain small letters only."); X printf("- the default minimum word length is %d.\n",MINWORD); X printf("- the -l option sets the minimum word lenth to %d.\n",LMINWORD); X printf("- the -L option sets the minimum word lenth to %d.\n",LLMINWORD); X puts("- the -D option is only for hangman development."); X puts("- the -h option gives you less misses(ie harder)."); X puts("- the -e option gives you more misses(ie easier)."); X printf("- hangman %s is public domain.\n",VERSION); X puts("- written by: ritcv!jxs7451"); X printf("\nHit space to continue."); X while (getchar() != ' ') ; X drawscrn(); X } X X /* prints intro stuff */ X drawscrn() X { X setcur(1,1); X epage(); X printf("Welcome, %s to hangman %s.\n",getlogin(),VERSION); X printf("Hit '?' for help."); X } X X /* prints error msg when use -h and -e at the same time */ X twolev() X { X puts("Cannot use 'e' and 'h' options at the same time."); X exit(0); X } X X /* prints the usage and quits.. */ X usage() X { X puts("usage: hangman [-ehlDL]"); X exit(0); /* terminate program */ X } X X /* function to clear out the tried array */ X cltried(arr) X int arr[]; X { X int i; X for (i = 0; i == 127; i++) X arr[i] = 0; X arr['!'] = 1; /* set so can shell escape */ X arr['G'] = 1; /* set so can guess all word */ X arr['Q'] = 1; /* set so can quit */ X arr['?'] = 1; /* set so can do help */ X arr[18] = 1; /* set so can do ^R */ X } X X /* the options 'l' and 'L' used together */ X twolen() X { X puts("Cannot use 'l' and 'L' options at the same time."); X exit(0); X } X X /* clears the error area */ X clbtm() X { X int i; X for (i = ERROR; i != (ERROR + 4); i++) X erasel(i,1); X } / echo x- screen.c sed 's/X //' > screen.c << '/' X /* screen.c X * hangman screen utilities from ogre with help from ritcv!jeb1265 X * hangman by ritcv!jxs7451 X */ X #define TRUE 1 X #define FALSE 0 X #include <sgtty.h> X X struct sgttyb old_term, new_term; X short ospeed; X X static char *cs_dwn,*BC,*UP,*cs_move; X static char *scn_eeol,*scn_eeos,*scn_dwn; X static backspace; X int putchar(); X X /* X * Set up the curses environment, and set terminal to CBREAK and NOECHO X * These last two are done for single character input with no echo. X * After this routine is called, a normal getchar() will X * fetch the next character on stdin. X */ X init_term() X { X static char bp[1024]; X static char buffer[1024]; X char *area = buffer; X char *getenv(),*tgetstr(); X char *name; X int retcode; X X name = getenv("TERM"); X retcode = tgetent(bp, name); X switch(retcode) { X case -1: X printf("Unable to open termcap file.\n"); X exit(1); X break; X case 0: X printf("No termcap entry for %s.\n",name); X exit(1); X break; X } X backspace = tgetflag("bs"); X scn_eeos = tgetstr("cl",&area); X scn_eeol = tgetstr("ce",&area); X scn_dwn = tgetstr("sr",&area); X BC = tgetstr("bc",&area); X UP = tgetstr("up",&area); X cs_dwn = tgetstr("kd",&area); X cs_move = tgetstr("cm",&area); X X gtty(0, &old_term); X gtty(0, &new_term); X X new_term.sg_flags &= ~(ECHO | XTABS); X new_term.sg_flags |= CBREAK; X X ospeed = new_term.sg_ospeed; X X stty(0, &new_term); X } X X /* X * Reset the terminal to normal mode. This MUST be called when X * you are all done, or boy, are you in trouble. X */ X reset_term() X { X stty(0, &old_term); X } X X /* X * epage() X * Erase the terminal screen from current X * position to the end of the screen X */ X epage() X { X tputs(scn_eeos, 0, putchar); X } X X /* X * erasel() X * If you give the arguments (0,0), current line is erased to X * end. Otherwise position to the given (i,j) and the erase X * the end of line. X */ X erasel(i,j) X int i,j; X { X if (i) X setcur(i,j); X tputs(scn_eeol, 0, putchar); X } X X /* X * Move the cursor to (row,col). Notice the upper left is (1,1) X */ X setcur(row,col) X int row,col; X { X char *tgoto(); X tputs(tgoto(cs_move,--col,--row), 0, putchar); X } / echo x- turninfo.c sed 's/X //' > turninfo.c << '/' X /* turninfo.c X * function to print info for each turn X * written by: ritcv!jxs7451 X */ X #include"hangman.h" X #include<stdio.h> X X static int man; /* holds man parts */ X X turninfo(guess,att,left,tried,word,debug) X int guess; X int att; X int left; X int tried[]; X char word[]; X int debug; X { X int i; /* loop counter */ X X setcur(3,1); X if (debug) X { X printf("the word is '%s'.",word); X } X setcur(5,1); X erasel(0,0); X printf("%s tries = %d misses left = %d\n",guess,att,left); X printf("tried: "); /* printing out the chars already tried */ X for (i=0;i != 127;i++) X if (tried[i] != 0) X switch (i) { X case '!' : X case 'G' : X case 'Q' : X case '?' : X case 18 : X break; X default : X printf("%c ",i); X break; X } X drawman(); X setcur(ERROR - 1,1); X } X X /* initalized the man stuff */ X initman(left) X int left; X { X man = ETRIES - left; X } X X /* incriment the man variable */ X incman() X { X man++; X } X X /* draws man */ X drawman() X { X switch (man) { X case 14 : X setcur(5,68); X printf("_|_"); X case 13 : X setcur(5,69); X putchar('|'); X case 12 : X setcur(4,70); X putchar('\\'); X case 11 : X setcur(4,68); X putchar('/'); X case 10 : X setcur(4,69); X putchar('|'); X case 9 : X setcur(3,69); X putchar('O'); X case 8 : X setcur(2,69); X putchar('|'); X case 7 : X setcur(1,68); X printf("__"); X case 6 : X setcur(1,66); X printf("__"); X case 5 : X setcur(3,64); X putchar('/'); X setcur(2,65); X putchar('/'); X case 4 : X setcur(1,63); X printf("___"); X case 3 : X setcur(2,63); X putchar('|'); X setcur(3,63); X putchar('|'); X setcur(4,63); X putchar('|'); X case 2 : X setcur(5,63); X putchar('|'); X setcur(6,63); X putchar('|'); X setcur(6,62); X putchar('_'); X case 1 : X setcur(6,64); X printf("_________"); X break; X default : X break; X } X } X X /* sets man to 14 for die with G command */ X killman() X { X man = 14; X } / echo x- wordguess.c sed 's/X //' > wordguess.c << '/' X /* wordguess.c X * code to guess the whole word X * written by: ritcv!jxs7451 X */ X #include "hangman.h" X #include<stdio.h> X #include<strings.h> X wordguess(word) X char word[]; X { X char fguess[MAXLINE]; /* holds user guess */ X int i; /* loop counter */ X X reset_term(); X for(i=0;(fguess[i] = getchar()) != '\n';i++) X { X if (i > (MAXLINE - 1)) X { X while (getchar() != '\n') ; /* cl buffer */ X init_term(); X clbtm(); X setcur(ERROR,1); X printf("Guess too long."); X return(0); X } X if (fguess[i] == EOF) X { X printf("\n\nunexpected EOF. Quitting hangman %s.\n",VERSION); X exit(0); X } X } X fguess[i] = '\0'; X init_term(); X clbtm(); X setcur(ERROR,1); X printf("Your guess is '%s'.\n",fguess); X erasel(0,0); X printf("Are you sure(y/n) "); X i = getchar(); X if ((i != 'y') && (i != 'Y')) X { X clbtm(); X setcur(ERROR,1); X puts("The guess was not tried."); X return(0); X } X else /* trying it */ X if (!strcmp(fguess,word)) X return(1); /* win */ X else X return(2); /* lose */ X } / echo x- hangman.h sed 's/X //' > hangman.h << '/' X /* hangman.h X * defines for hangman by ritcv!jxs7451 X */ X #define MAXLINE 30 /* max word length */ X #define WORDMAX 201000 /* number of (bytes-xx) in dictionary */ X /* xx is to insure that dont get EOF */ X #define VERSION "v3.00(js)" /* April 1986 */ X #define DBUG 2315 /* uid with debug permission (-D option) */ X #define PROMPT "guess ? " /* std prompt */ X #define WORDL "/usr/dict/words" /* wordlist */ X #define MINWORD 5 /* min word length */ X #define LMINWORD 8 /* min word with -l option */ X #define LLMINWORD 10 /* min word with -L option */ X #define ERROR 8 /* where error printed */ X X /* changing these will severly mess up the man drawing */ X #define TRIES 10 /* max number of wrong guesses */ X #define HTRIES 6 /* when -h used this is guesses */ X #define ETRIES 14 /* when -e used this is guesses */ / echo x- hangman.6 sed 's/X //' > hangman.6 << '/' X .TH HANGMAN 6 X .UC 4 X .SH NAME X hangman v3.00(js) \- Computer version of the game hangman X .SH SYNTAX X .B hangman [-ehlDL] X .SH DESCRIPTION X In X .I hangman, X the computer picks a word from the on-line word list X and you must try to guess it. X The computer keeps track of which letters have been guessed X and how many wrong guesses you have made in a graphic manner. X The terminal used must be found in the termcap database. X Help is avaliable from X .I hangman X by entering '?'. X X .PP X There are a number of options: X .TP X .B e X Allows for 14 wrong guesses. X Cannot be used with 'h' option. X .TP X .B h X Allows for 6 wrong guesses. X Cannot be used with 'e' option. X .TP X .B l X The minimum word length is set to 8. X Cannot be used with 'L' option. X .TP X .B L X The minimum word length is set to 10. X Cannot be used with 'l' option. X .TP X .B D X For debugging purposes. X Only accessable by the developer X .SH RESTRICTIONS X The arguments must be one grouping as the second argument of the invoking X call. X Any argument can appear only once. X .SH FILES X /usr/dict/words On-line word list X /etc/termcap termcap file / echo x- makefile sed 's/X //' > makefile << '/' X # makefile for hangman game X # written by ritcv!jxs7451 X # X DOTO= lib.o hangman.o doargs.o getwd.o turninfo.o wordguess.o\ X getlet.o getrand.o doquit.o screen.o X X hangman: $(DOTO) X cc $(DOTO) -ltermcap -o hangman X X # .o dependancies X lib.o: lib.c hangman.h X hangman.o: hangman.c lib.o doargs.o getwd.o turninfo.o wordguess.o\ X doquit.o getlet.o hangman.h screen.o X doargs.o: doargs.c hangman.h lib.o screen.o X getwd.o: getwd.c hangman.h getrand.o screen.o lib.o X turninfo.o: turninfo.c hangman.h screen.o lib.o X wordguess.o: wordguess.c hangman.h screen.o lib.o X getlet.o: getlet.c hangman.h screen.o lib.o X getrand.o: getrand.c hangman.c screen.o lib.o X doquit.o: doquit.c hangman.h screen.o lib.o X screen.o: screen.c X X #definition of .c X .c.o: X cc -c -O $*.c X #do nroff for man page X doc: X nroff -man -h hangman.6 | /usr/ucb/more / echo x- mkdist sed 's/X //' > mkdist << '/' X #! /bin/csh X #makes distribution format. ALL files must be in present dir X echo "#! /bin/sh" > hangman.d X echo "# hangman distribuiton file." >> hangman.d X echo "# to get individual files execute this file." >> hangman.d X echo "# written by: ritcv\!jxs7451" >> hangman.d X echo "# help from ritcv\!jeb1265 with screen.c (from ogre)" >> hangman.d X echo "echo 'start of hangman v3.00(js)'" >> hangman.d X foreach j (*.c *.h hangman.6 makefile mkdist) X echo "doing: $j" X echo "echo x- $j" >> hangman.d X echo "sed 's/X //' > $j << '/'" >> hangman.d X cat $j | awk '{print "X",$0}' >> hangman.d X echo '/' >> hangman.d X end X echo "echo 'end of hangman v3.00(js)'" >> hangman.d / echo 'end of hangman v3.00(js)'