[alt.sources] hangperson

amator@homxb.ATT.COM (T.NECEDA) (02/04/89)

if you have curses, rand48(), SYS5, and an ascii word list you can
probably run this game....if not it probably will take about 3 minutes
to port to whatever you do have.
--------cut here--------cut here----------cut here---------cut here---------
#!/bin/sh
# shar:    Shell Archiver  (v1.22)
#
#    Run the following text with /bin/sh to create:
#      README
#      Makefile
#      main.c
#      dogame.c
#
if test -f README; then echo "File README exists"; else
echo "x - extracting README (Text)"
sed 's/^X//' << 'SHAR_EOF' > README &&
XHere is a quick 'hangperson' program based on the ever-so-popular 
Xhangman game we used to relish playing as kids. I have forgotten
Xsome of the rules (in particular - how many wrong guesses you are allowed)
Xso I just guessed on a couple of things.
X
XThis was written on a system running SYSVR3. I make no guarantees that
Xit will run correctly anywhere. I do humbly apologize for some
Xof the poor code, incoherent comments, and lack of a help screen but,
Xwhat the hell, it was quick, easy, and now it's free. Please feel free
Xto hack it to death if you want.
X
XWhat you will have to do:
X    1. Unshar this file (which you may have done already)
X    2. edit main.c and change the define of WORDLIST to the path
X       of your ascii word list ( /usr/dict/words may be a good one ),
X       and change the define of NO_OF_WORDS to the total amount of
X       words in WORDLIST (`wc -l' might help there).
X    3. type make
X
Xenjoy!
XThomas W. Neceda
Xatt!homxb!amator
X       
SHAR_EOF
chmod 0600 README || echo "restore of README fails"
fi
if test -f Makefile; then echo "File Makefile exists"; else
echo "x - extracting Makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X
X# Makefile for 'hangperson'. Edit BIN if you want to install in some other
X# place than /usr/games. 
X#
X# Make sure you edit the main.c file first and redefine WORDLIST and
X# NO_OF_WORDS
X
XBIN= /usr/games
XLDLIBS= -lcurses -ltermcap
XFINAL= hangperson
X
XCFLAGS= -O 
X
XOBJECTS = main.o dogame.o 
X
X$(FINAL): $(OBJECTS)
X	$(CC) -o $(FINAL) $(OBJECTS) $(LDLIBS)
X
Xinstall: $(FINAL)
X	cp $(FINAL) $(BIN)
X	strip $(BIN)/$(FINAL)
X
Xcleanup:
X	rm -f $(OBJECTS) $(FINAL) 
X
SHAR_EOF
chmod 0600 Makefile || echo "restore of Makefile fails"
fi
if test -f main.c; then echo "File main.c exists"; else
echo "x - extracting main.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > main.c &&
X/*****************************************************************************
X a hangperson program written with curses.
X
X    1/30/89 by Thomas W. Neceda
X    please send any comments/fixes/flames/money to 
X    att!homxb!amator
X    This is public domain - You can do absolutely whatever you want with
X    this, but if someone is foolish enough to give you money for this I'd
X    appreciate it if you would buy me a beer sometime.
X******************************************************************************/
X
X/*****************************************************************************
X You will most probably have to redefine these next two. I understand
X that /usr/dict/words is a popular spot to find an ascii word list.
X NO_OF_WORDS is the result of `wc -l /usr/dict/words` or where ever the
X dictionary happens to be.
X******************************************************************************/
X
X#define WORDLIST        "/usr/src/cmd/spell/list" /*location of dictionary*/
X#define NO_OF_WORDS     23739                     /*number of words in dict.*/
X
X#include <ctype.h>
X#include <stdio.h>
X#include <time.h>
X
Xchar word[30];
X
Xmain()
X{
X    char *c, *getaword() ;
X    static int i ;
X
X    do {
X        i = getint();      /* get an integer that will correspond to a line */ 
X        c = getaword(i);   /* get the word on the line from above integer */
X    } while( c == NULL ); 
X
X    do_game(c);            /* do the game */
X    endgame();             /* should never get here */
X}
X
X/* get a random number that falls between 1 and the total number or words in
X   the dictionary file. This number will be used as a line number to get
X   the word on that line. (this whole procedure probably would be more 
X   efficient if using fstat()/fseek() )
X*/
Xgetint() 
X{
X    long int i, time();
X    int j = 1 ;
X
X    srand48( (int)time((long int *)0) ); /* seed with current time */
X    i = lrand48();                       /* get a random long */
X
X    j = i % 10 ;                         /* get a number to divide by */
X
X    /* someone once told me you can't divide by zero...1 is not cool here
X        either.....33 was just picked out of the hat */
X
X    j = ( j > 1) ? j : 33 ;
X
X    while( i > NO_OF_WORDS )        
X        i = i / j ;
X
X    return(i);
X}
X
X/* get a word from the dictionary....the number passed to this function
X   should correspond to a line number in the dictionary file 
X*/
Xchar *
Xgetaword(i)
Xint i;
X{
X    static char c ;
X    extern char word[]; 
X    FILE *fp ;
X
X    if((fp=fopen(WORDLIST, "r")) == NULL ){
X        printf("Can't open file\n");
X        exit(2);
X    }
X
X    for( ; i > 0 ; i-- )
X        fgets(word, 29, fp);
X
X    c = word[0] ;
X
X    if( isupper(c) || isdigit(c) ){        /* we don't want any words that */
X        fclose(fp);                        /* begin with capitals or numbers */
X        return((char *)NULL);
X    }
X    else{
X        fclose(fp);
X        return((char *)word);              /* got a word? well...return * ! */
X    } 
X}
SHAR_EOF
chmod 0600 main.c || echo "restore of main.c fails"
fi
if test -f dogame.c; then echo "File dogame.c exists"; else
echo "x - extracting dogame.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > dogame.c &&
X/*****************************************************************************
X a hangperson program written with curses.
X
X    1/30/89 by Thomas W. Neceda
X    please send any comments/fixes/flames/money to 
X    att!homxb!amator
X    This is public domain - You can do absolutely whatever you want with
X    this, but if someone is foolish enough to give you money for this I'd
X    appreciate it if you would buy me a beer.
X******************************************************************************/
X
X#include <ctype.h>
X#include <curses.h>
X#include <signal.h>
X
Xdo_game(word)
Xchar word[];
X{
X    static char *poorsoul[] = {
X    "  O`\\  ",
X    "  /|_|  ",
X    " ' ||`  ",
X    "   ||   ",
X    "   '`   ",  
X    "        " };
X    static char *snap[] = {
X    "  O    ",
X    " /-`\\/`",
X    " \\ /`  ",
X    " ' | \\ ",
X    "  /   \\",
X    " '    , " };
X                                                                                
X    static char *bottom[] = {"---------------------------"};
X    static char *yardarm[] = {"------------"};
X    static char *side[] = { "|","|","|","|", "|", "|","|","|", "|", "|", "|"};
X    static char *post[] = {"|", "|", "|", "|", "|", "|", "|", "|"};
X    static char *rope[] = {"|", "|"};
X    static char *alpha[] = {"a", "b","c","d","e","f","g","h","i","j","k","l",
X                    "m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
X
X    static char guessed[40];        /* letters already guessed,right or wrong*/
X    static int j = 0;               /* index for guessed[] */
X    static char cur_guess ;         /* the current guess */
X    static int i ;                  /* your basic index'er */
X    static int dupe;                /* if cur_guess in guessed[] */
X    static int total ;              /* amount of characters in word[] */
X    static int toomany ;            /* how many wrong guesses */
X    static int hit;                 /* if cur_guess is a good guess */
X    static int miss;                /* if cur_guess is a bad guess */
X
X    extern int endgame();            /* normal end of game */
X    extern int quickend();           /* abnormal end of game */
X
X    signal(SIGINT, quickend);        /* some basic signal handling here */ 
X    signal(SIGHUP, quickend);
X    signal(SIGQUIT, quickend);
X
X    initscr();
X    clear();
X
X    for( i=0 ; word[i] != '\n' ; i++ )   /* put underscores to indicate */ 
X        mvaddch(LINES / 2 , i, '_' );    /* the word's letters */
X
X    total = i ;
X
X    mvaddstr(1, 0, "Unused Letters:");   /* make a list of unused letters */
X    for(i = 0 ; i < 26 ; i++)            /* (each letter will be deleted as */
X        mvprintw(2, i, "%c", *alpha[i]); /* guessed) */
X
X    mvprintw(LINES-3, 0, "There are %d letters in the word", total ); 
X    mvprintw(LINES-2, 0, "Please enter a letter");
X    refresh();
X
X    while( total > 0 ){            /* haven't guessed all the characters */
X        while( miss != 1 ){     /* do until guess is a character */
X            move(LINES-1, 0);
X            clrtoeol();
X            refresh();
X            cur_guess = tolower(getch()); /* make sure its lower case */
X            if( cur_guess == '\014' ){    /* refresh screen with ^L */
X                clearok(stdscr, TRUE);
X                refresh();
X                miss = 0 ;
X            }
X            else if(isalpha(cur_guess) != 0 ) /*check to see if a letter */
X                miss = 1 ;
X            else{                              /* if not a letter, beep */
X                miss = 0 ;
X                beep();
X                move(LINES-1, 0);
X                clrtoeol();
X                refresh();
X            }
X        }
X        miss = 0 ;   /* reset miss for next guess */
X
X        for( i=0 ; i <= j ; i++ ){      /* go through all guesses to see if */
X            if(guessed[i] == cur_guess) /* previously guessed */
X                dupe = 1 ;
X        }
X        if(dupe == 1 ){                 /* if previously guessed then say so */
X            move(LINES-2, 0 );
X            clrtoeol();
X            printw("Don't be silly!");
X            refresh();
X            beep();
X            dupe = 0;
X        }
X        else{                                    /* otherwise put the */
X            for( i=0 ; word[i] != '\n' ; i++ ){  /* letter in its proper */
X                if(cur_guess == word[i]){        /* place */
X                    move(LINES-2, 0 );
X                    clrtoeol();
X                    printw("HIT");
X                    mvprintw(LINES/2, i, "%c", cur_guess );
X                    hit = 1 ;
X                    total-- ;
X                    if(total == 0){              /* all guessed correctly? */
X                        mvprintw(LINES-2, 0, "We have a WINNER!->%s", word);
X                        refresh();
X                        endgame();
X                    }
X                }
X            }
X            if( hit == 1 )    /* if letter was a good one reset hit for */
X                hit = 0 ;     /* next loop */
X            else{
X                move(LINES-2, 0 ); /* otherwise increment toomany and print */
X                clrtoeol();        /* the appropriate part of the gallows */
X                printw("Sorry");
X                toomany++ ;
X                refresh();
X                switch(toomany)
X                {
X                case 1 :
X                    hanger(bottom, 1, 20, COLS/2 );
X                    break ;
X                case 2 :
X                    hanger(side, 10, 10, COLS/2 );
X                    break ;
X                case 3 :
X                    hanger(side, 10, 10, COLS/2 + 26 );
X                    break ;
X                case 4 :
X                    hanger(bottom, 1, 9, COLS/2 );
X                    break ;
X                case 5 :
X                    hanger(post, 6, 3, COLS/2 + 5 );
X                    break ;
X                case 6 :
X                    hanger(yardarm, 1, 2, COLS/2 + 5 );
X                    break ;
X                case 7 :
X                    hanger(rope, 2, 3, COLS/2 + 17 );
X                    break ;
X                case 8 :
X                    mvprintw(1, COLS/2, "HEY! No more wrong guesses OK????");
X                    hanger(poorsoul, 5, 5, COLS/2 + 14 );
X                    beep();
X                    break ;
X                case 9 :
X                    move(1,0);        /* player is dead meat here */
X                    clrtoeol();
X                    mvprintw(1, 0, "AAAAAAARRRRRGGGGHHHHHHHHHHHH");
X                    mvprintw(LINES-2,0," too many wrong guesses! word was: %s",
X                             word);
X                    refresh();
X                    beep();
X                    for( i = 5 ; i <= 13 ; i++ ){
X                        hanger(poorsoul, 5, i, COLS/2 + 14 );
X                        mvprintw( i , COLS/2 + 16, " | " );
X                    }
X                    hanger(snap, 6, i, COLS/2 +14);
X                    hanger(snap, 6, i, COLS/2 +14);
X                    hanger(poorsoul, 6, i, COLS/2 +14);
X                    endgame();
X                    break ;
X                default :
X                    endgame();
X                }
X            }
X            for(i = 0 ; i < 26 ; i++){        /* delete the letter from */
X                if( cur_guess == *alpha[i] )  /* list of unused letters */
X                    mvaddch(2, i, ' ');
X            }
X            guessed[j++] = cur_guess ;        /* add the guess to list of */
X                                              /* previously guessed letters*/
X            refresh();
X        }
X    }
X    refresh();
X    endgame();
X}
X
X        /* draw a part of the gallows */
Xhanger(pic, length, y, x)
Xchar *pic[];
Xint length, y, x;
X{
X    int i;
X    for ( i=0 ; i < length ; i++ )
X        mvprintw(i+y, x, pic[i]);
X    refresh();
X}
X
X        /* normal end of game */
Xendgame()
X{
X    endwin();
X    exit();
X}
X
X        /* abnormal end of game....just clears the screen too */
Xquickend()
X{
X    clear();
X    refresh();
X    endwin();
X    exit();
X}
SHAR_EOF
chmod 0600 dogame.c || echo "restore of dogame.c fails"
fi
exit 0
-- 
# Thomas W. Neceda                                     (201) 949-3215
# AT&T - Bell Laboratories
# att!{homxb, hopat}!amator