/* hangman.c - a hangman game similar to one seen on some *nix machines.*
* *
* hangman [wordlist] *
* if wordlist is not specified, reads words in current *
* directory if it exists, else reads dict:words. *
* *
* hangman (C) 1989 by Gary L. Brant *
* *
* :ts=8 */
#include <ctype.h>
#include <stdio.h>
#include <time.h>
#include <stat.h>
char word[30];
char dead_man[][4] = {
" O ",
"/|\\",
" | ",
"/ \\"
};
char guessed[28]; /* letters already guessed */
int count = 0; /* count of letters in guessed */
char blimp[30]; /* string of -'s length of word */
char dictionary[30]; /* file name of dictionary */
float curavg = 0.0;
float overavg = 0.0;
int wordno = 0;
long totalwrong = 0L;
int done = 0;
int raw_mode = 0; /* true if currently in raw mode */
FILE *dict, *fopen ();
struct stat statbuf;
long size;
main (argc, argv)
int argc;
char *argv[];
{
int i;
if (argc > 1) {
if ((dict = fopen (argv[1], "r")) == NULL) {
printf ("can't open %s\n", argv[1]);
exit (20);
} else
strcpy (dictionary, argv[1]);
} else if ((dict = fopen ("words", "r")) == NULL) {
if ((dict = fopen ("dict:words", "r")) == NULL) {
printf ("can't find dictionary\n");
exit (20);
} else
strcpy (dictionary, "dict:words");
} else
strcpy (dictionary, "words");
if ((stat (dictionary, &statbuf)) == -1) {
printf ("can't get info for %s\n", dictionary);
quit (10);
}
size = statbuf.st_size;
srand ((int) time ((long *) 0)); /* use time as random seed */
do { /* loop until user says no more */
getword (); /* get word from dictionary */
set_raw ();
raw_mode = 1;
hangman (); /* play one word game */
newgame ();
set_con ();
raw_mode = 0;
} while (!done);
quit (0);
}
/* get a random number. */
long getran ()
{
long time ();
unsigned long i, j;
i = rand ();
j = rand ();
i += 65536 * j; /* fabricate a random long int */
return (i);
}
/* get a word from the dictionary for use in the game */
getword ()
{
register int i, len;
long num;
long position;
for (;;) {
num = getran (); /* get an random long integer */
position = num % size;
if ((fseek (dict, position, 0)) != 0) {
printf ("can't seek on %s\n", dictionary);
quit (10);
}
fgets (word, 29, dict);
if (fgets (word, 29, dict) == NULL)
continue;
if ((len = strlen (word) - 1) < 4)
continue;
for (i = 0; i < len; i++)
if (word[i] < 'a' || word[i] > 'z')
goto nogood;
word[len] = '\0';
return; /* return word found */
nogood:
continue;
}
}
/* play one word game, return as soon as guesses used up or word guessed.
* Display a congratulatory message before exiting if player guessed the
* word, else display the word.
*/
hangman ()
{
char guess; /* the current guess */
int i;
int togo; /* number of letters still to be guessed */
int wrong = 0; /* number of incorrect guesses */
char getcharacter (); /* get user's input */
nextword ();
redraw ();
togo = strlen (word);
while (togo > 0) { /* haven't guessed all the characters */
int dup = 0; /* if letter was guessed before */
for (;;) { /* do until guess is a character */
scr_curs (12, 8);
scr_eol ();
fflush (stdout);
guess = getcharacter ();
putc (guess, stdout);
if (guess == '\f') /* redraw screen if ^L */
redraw ();
else if (!isalpha (guess)) { /* disallow non-alpha characters */
scr_beep ();
scr_curs (12, 8);
scr_eol ();
scr_curs (13, 0);
fputs ("Not a valid guess, ", stdout);
if (guess < ' ') {
char bad[4];
bad[0] = '^';
bad[1] = guess + 'A' - 1;
bad[2] = '\0';
fputs (bad, stdout);
} else
putc (guess, stdout);
} else
break; /* drop out of loop if alpha */
}
for (i = 0; guessed[i]; i++)
if (guess == guessed[i]) {
dup = 1;
break;
}
scr_curs (13, 0);
scr_eol ();
if (dup) { /* if previously guessed */
printf ("Already guessed %c", guess);
dup = 0;
} else {
int inword = 0; /* if guess in word */
for (i = 0; word[i]; i++) {
if (guess == word[i]) {
inword = 1;
togo--;
blimp[i] = guess;
scr_curs (11, i+8);
putc (guess, stdout); /* place letter in word */
if (togo == 0) { /* if word completed */
insert (guess);
scr_curs (13, 0);
fputs ("You got it!", stdout);
return;
}
}
}
if (!inword) {
wrong++; /* scorekeeping */
totalwrong++;
curavg += 1.0 / ((float) wordno);
scr_curs (6, 49); /* update current average on screen */
printf ("%8.4f", curavg);
switch (wrong) {
case 1: scr_curs (3, 10);
putc ('O', stdout);
dead_man[0][1] = 'O';
break;
case 2: scr_curs (4, 10);
putc ('|', stdout);
dead_man[1][1] = '|';
break;
case 3: scr_curs (5, 10);
putc ('|', stdout);
dead_man[2][1] = '|';
break;
case 4: scr_curs (6, 9);
putc ('/', stdout);
dead_man[3][0] = '/';
break;
case 5: scr_curs (4, 9);
putc ('/', stdout);
dead_man[1][0] = '/';
break;
case 6: scr_curs (4, 11);
putc ('\\', stdout);
dead_man[1][2] = '\\';
break;
case 7: scr_curs (6, 11);
putc ('\\', stdout);
dead_man[3][2] = '\\';
scr_curs (13, 0);
fputs ("The word was: ", stdout);
fputs (word, stdout);
return;
}
}
insert (guess);
}
}
return;
}
/* game over; inquire from player whether to play another */
newgame ()
{
char c;
scr_curs (14, 0);
fputs ("Another word? ", stdout);
for (;;) {
fflush (stdout);
c = getcharacter ();
if (c == 'n') {
done = 1;
return;
} else if (c == 'y')
return;
scr_curs (15, 0);
fputs ("Please type 'y' or 'n'", stdout);
scr_curs (14, 15);
}
}
/* redraw display at beginning of new word or at user request (^L) */
redraw ()
{
int i;
scr_clear ();
scr_curs (1, 5);
fputs ("______", stdout);
scr_curs (2, 5);
fputs ("| |", stdout);
scr_curs (3, 5);
putc ('|', stdout);
scr_curs (3, 10);
putc (dead_man[0][1], stdout);
scr_curs (3, 32);
fputs ("Guessed: ", stdout);
fputs (guessed, stdout);
scr_curs (4, 5);
putc ('|', stdout);
scr_curs (4, 9);
for (i = 0; i < 3; i++)
putc (dead_man[1][i], stdout);
scr_curs (5, 5);
putc ('|', stdout);
scr_curs (5, 9);
for (i = 0; i < 3; i++)
putc (dead_man[2][i], stdout);
scr_curs (5, 32);
printf ("Word #: %d", wordno);
scr_curs (6, 5);
putc ('|', stdout);
scr_curs (6, 9);
for (i = 0; i < 3; i++)
putc (dead_man[3][i], stdout);
scr_curs (6, 32);
printf ("Current Average: %8.4f", curavg);
scr_curs (7, 3);
fputs ("__|_____", stdout);
scr_curs (7, 32);
printf ("Overall Average: %8.4f", overavg);
scr_curs (8, 3);
putc ('|', stdout);
scr_curs (8, 10);
fputs ("|___", stdout);
scr_curs (9, 3);
fputs ("|_________|", stdout);
scr_curs (11, 1);
fputs ("Word: ", stdout);
fputs (blimp, stdout);
scr_curs (12, 0);
fputs ("Guess:", stdout);
fflush (stdout);
}
/* reset stuff for next word */
nextword ()
{
int i, j;
for (i = 0; i < 4; i++)
for (j = 0; j < 3; j++)
dead_man[i][j] = ' ';
for (i = 0; i < strlen (word); i++)
blimp[i] = '-';
blimp[i] = '\0';
for (i = 0; i < 28; i++)
guessed[i] = '\0';
count = 0;
wordno++;
overavg = curavg;
curavg = ((float) totalwrong) / ((float) wordno);
}
/* get user's input */
char getcharacter ()
{
while (!WaitForChar (Input (), 100L) &&
stdin->_bp >= stdin->_bend);
return (tolower (getc (stdin)));
}
/* insert letter just guessed into list of guessed letters; also update list
* on screen for player.
*/
insert (guess)
register char guess;
{
if (count == 0) { /* first guess ? */
guessed[count++] = guess;
scr_curs (3, 42);
putc (guess, stdout);
} else {
register int i, j;
for (i = 0; i < count; i++)
if (guessed[i] > guess)
break;
for (j = count; j > i; j--)
guessed[j] = guessed[j-1];
guessed[i] = guess; /* add the guess to list of */
/* previously guessed letters*/
scr_curs (3, i+42);
fputs (&guessed[i], stdout); /* update list on screen */
count++;
}
}
/* needed, since Manx version apparently doesn't work */
scr_eol ()
{
static char clr[] = {0x9b, 'K', '\0'};
fputs (clr, stdout);
}
/* in order to have a chance at cleaning up & exiting gracefully */
_abort ()
{
puts ("^C");
quit (0);
}
quit (code)
int code;
{
if (dict)
fclose (dict);
set_con ();
exit (code);
}
_wb_parse ()
{
}