/*
 *     Jotto.  G. L. Sicherman.  1990.
 *     Translated to C from UNIX f77.
 *     The UNIX f77 was ported from the original CDC FORTRAN IV
 *     and COMPASS, which goes back to around 1975.
 *
 *     You may use this program and modify it as you like,
 *     so long as you leave this message as it is and don't
 *     try to make money off the program.
 */

#include <ctype.h>
#include <stdio.h>
/*
 *     The usual string incompatibility.
 *     In SYSV, index() is an unrelated function in libPW.
 */
#ifdef BSD
#include <strings.h>
#define        strchr index
#else
#include <string.h>
#endif
#include "jotto.h"

#ifndef        DICT
#define        DICT    "jotto.d"
#endif

char   *bad[DICTLEN];                  /* words eliminated by one answer */
int    diagn = 0;
char   dict[DICTLEN][WORDLEN*2+1];     /* all the words */
char   *good[DICTLEN];                 /* words not eliminated */
int    gy[MAXGUESS];
char   *iguess[MAXGUESS];
int    ndict;
int    ngood, nbad;
FILE   *tape4;                         /* Yep - it's CDC FORTRAN, all right */
char   uguess[MAXGUESS][WORDLEN+1];
int    uguessc, iresp[MAXGUESS];

extern char    *getlogin();
extern int     legal();
extern char    *ord();
extern long    time();

main(argc, argv)
int argc;
char **argv;
{
       char    **use;          /* whichever we're using */
       int     num;
       int     igs;
       int     *nuse;
       char    mult[WORDLEN*10+1];
       char    *foundpan;
       int     guess;
       int     ustart;
       char    *login;
       char    *pop;
       int     wins[2];
       int     over;
       char    *you, *getword();
       char    *mine;
       char    *old;
       char    *a;
       long    best;
       int     which;
       int     iguessc;
       int     i, n, i0;

       while (--argc) {
               if ('-'==**++argv) switch(*++*argv) {
               case 'd':               /* undocumented debugging option */
                       diagn = 1;
                       break;
               default:
                       ;
               }
               else break;
       }
       printf(" Jotto 3.0\n");
       for (i=0; i<2; i++) wins[i]=0;
       tape4 = fopen(DICT, "r");
       if (!tape4) {
               printf("\nCannot read dictionary - aborted\n");
               exit(1);
       }
       login = getlogin();
       load();
       srand(time((long *)0));
       ustart = rand(0) >= 16384;
       do {    /* loop over games */
               printf("\n Think of a word of %d different letters.\n",
                       WORDLEN);
/*
 *             Pick a word.
 */
               mine = &dict[which=rand()%ndict][WORDLEN];
               if (diagn) printf("l %5d\n", ndict);
/*
 *             Copy all the words into the good list
 *             while the user is thinking.
 */
               for (i=0; i<ndict; i++) good[i] = dict[i];
               ngood = ndict;
               nbad=0;
               while (!yes(" Ready? ")) ;
/*
 *             Pick a place in the dictionary to start guessing.
 */
               do guess = rand()%ndict;
               while (guess == which); /* don't guess our own word! */
               printf(" Type a carriage-return for a list of my answers.\n");
               iguessc = uguessc = 0;
               foundpan = (char *)NULL;
               for (over=0; !over; ) {
/*
 *                     Loop over turns.
 */
                       if (ustart && uguessc==0) goto getguess;
/*
 *                     our turn to guess.
 */
                       if (foundpan) {
/*
 *                             Multiple anagrams!
 */
                               foundpan += WORDLEN;
                               if (*foundpan) {
                                       old = foundpan;
                                       goto doguess;
                               }
                               /* otherwise we're stuck */
                               goto giveup;
                       }
                       best = -999999;
                       use = good;
                       if (!*(nuse = &ngood)) {
                               if (!*(nuse = &nbad)) goto giveup;
                               use = bad;
                       }
                       if (*nuse == 1) old = &use[0][WORDLEN];
                       else for (igs=0; igs<50; igs++) {
                               if ((guess += 31) >= ndict) guess -= ndict;
       /*
        *                      Get the guess.
        */
                               a = &dict[guess][WORDLEN];
                               if ((i=isis(a,use,*nuse)) >= best) {
                                       best = i;
                                       old = a;
                               }
                               if (diagn && igs<10)
                                       printf(" ?g %s %7d\n", a, i);
                               if (best >= -1) break;
                       }
                       if (diagn && *nuse <= 10) {
                               for (i=0; i<*nuse; i++)
                               printf(" i %.*s\n", WORDLEN, use[i]+WORDLEN);
                       }
                       if (diagn) printf("%dg%d\n", igs, best);
doguess:
                       printf("\n My %d%s guess is: %.*s.\n",
                               iguessc+1, ord(iguessc+1), WORDLEN, old);
                       num = getnum(" How many letters? ");
                       iguess[iguessc] = old;
                       gy[iguessc++] = num;
                       if (num == WORDLEN) {
                               if (yes(" Is that your word? ")) {
                                       printf("\n Your word is: %s\n", old);
                                       printf(" My word was: %s\n", mine);
                                       wins[0]++;
                                       over = 1;
                                       break;
                               }
                               if (!foundpan) {
                                       getmult(old-WORDLEN, mult);
                                       foundpan = mult;
                               }
                       }
                       else revise(old, num);
/*
 *             Time for the user's guess.
 */
getguess:
                       do {
                               printf("\n What is your %d%s guess? ",
                                       uguessc+1, ord(uguessc+1));
                               you = getword();
                               if (strlen(you)==0) {
                                       jsumm();
                                       continue;
                               }
                       } while (!legal(you));
                       strcpy(uguess[uguessc] , you);
                       iresp[uguessc++] = i = inter(mine, you);
                       if (!strcmp(mine, you)) {
                               printf(" ...you win.\n");
                               goto beg;
                       }
                       answer(you, i);
                       continue;
giveup:
                       printf("\n\n I give up.\n");
beg:
                       printf(" What was your word? ");
                       pop = getword();
                       if (!legal(pop)) {
                               printf("\n \"%s\" is not a legal word.\n", pop)
;
                               wins[0]++;
                               over = 1;
                               break;
                       }
/*
 *             Check his answers.
 */
                       for (i0 = 0; i0 < iguessc; i0++) {
                               if (inter(iguess[i0],pop) != gy[i0]) {
                                       printf(
                       "\n You cheated\n You said \"%s\" had %d letters\n",
                                               iguess[i0], gy[i0]);
                                       wins[0]++;
                                       over = 1;
                                       break;
                               }
                               if (!strcmp(iguess[i0],pop)) {
                                       printf(
                               " You cheated\n You said \"%s\" was not your wo
rd\n",
                                               iguess[i0]);
                                       wins[0]++;
                                       over = 1;
                                       break;
                               }
                       }
                       if (over) break;
                       wins[1]++;
                       printf(" My word was: %s\n", mine);
                       over = 1;
               }
       } while (yes(" Another game? "));
       printf("\n Final score\n %-8.8s %2d\n computer %2d\n",
               login, wins[1], wins[0]);
       exit(0);
}

int
yes(prompt)
char *prompt;
{
       char *i, xinline[80+1];

       printf(prompt);
       if (!gets(xinline)) {
               printf("ERROR reading your answer\n");
               return 0;
       }
       for (i=xinline; *i && isspace(*i); i++) ;
       return *i == 'y' || *i == 'Y';
}

char *
getword()
{
       static char wline[80];
       char *w, *ww;

       if (!gets(wline)) {
               printf("ERROR reading your answer\n");
               return (char *)0;
       }
       for (w=wline; *w && isspace(*w); w++) ;
       for (ww=w; !isspace(*ww); ww++) ;
       *ww = '\0';
       for (ww=w; *ww; ww++) if (isupper(*ww)) *ww=tolower(*ww);
       return w;
}

int
getnum(pr)
char *pr;
{
       char *n, nline[80+1];
       do {
               printf(pr);
               if (!gets(nline)) return -1;
               if (n = strchr(nline, '\n')) *n = 0;
               for (n=nline; *n && isspace(*n); n++) ;
       } while (!isdigit(*n));
       return atoi(n);
}

getmult(want, hold)
char *want, *hold;
{
       char mline[80+1];
       rewind(tape4);
       while (fgets(mline, 80, tape4)) if (!strncmp(want,mline,WORDLEN)) {
               *(strchr(mline,'\n')) = '\0';
               strcpy(hold, mline+WORDLEN);
               return;
       }
}

revise(word, num)
char *word;
int num;
/*
 *.... revise candidate lists.
 */
{
       int n;

       for (n=0; n<nbad; n++)
               if (inter(bad[n], word) != num)
                       bad[n--] = bad[--nbad];
       for (n=0; n<ngood; n++)
               if (inter(good[n], word) != num) {
                       bad[nbad++] = good[n];
                       good[n--] = good[--ngood];
               }
       if (diagn) printf(" w%5d%5d\n", ngood, nbad);
}
