/*-
 * Copyright (c) 1991, 1993
 *  The Regents of the University of California.  All rights reserved.
 *
 * The game adventure was originally written in Fortran by Will Crowther
 * and Don Woods.  It was later translated to C and enhanced by Jim
 * Gillogly.  This code is derived from software contributed to Berkeley
 * by Jim Gillogly at The Rand Corporation.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *  This product includes software developed by the University of
 *  California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef lint
static const char copyright[] __attribute__((unused)) =
    "@(#) Copyright (c) 1991, 1993\n\
	The Regents of the University of California.  All rights reserved.\n";
#endif /* not lint */

#ifndef lint
#if 0
static char sccsid[] = "@(#)adventure.c	8.1 (Berkeley) 6/2/93";
#endif
static const char rcsid[] __attribute__((unused)) =
    "$FreeBSD: src/games/adventure/adventure.c,v 1.9.2.1 2001/03/05 11:43:11 kris Exp $";
#endif /* not lint */

/*      Re-coding of advent in C: main program                          */

/* #include <sys/file.h>
#include <errno.h>
#include <sys/types.h>
#include <signal.h> */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "hdr.h"

int
main(int argc, char **argv) {
    int i;
    int rval, ll;
    struct text *kk;

    /* If the user hits start, bail */
    cont_btn_callback(0, CONT_START, (cont_btn_callback_t)arch_exit);

    pvr_init_defaults();
    conio_init(CONIO_TTY_PVR, CONIO_INPUT_LINE);
    // conio_init(CONIO_TTY_SERIAL, CONIO_INPUT_LINE);

#if 0
    /* revoke */
    setgid(getgid());
#endif

    my_init();      /* Initialize everything */
    /* signal(SIGINT,trapdel); */

#if 0

    if(argc > 1) {  /* Restore file specified */
        /* Restart is label 8305 (Fortran) */
        i = restore(argv[1]);       /* See what we've got */

        switch(i) {
            case 0:     /* The restore worked fine */
                yea = Start();
                k = null;
                unlink(argv[1]);/* Don't re-use the save */
                goto l8;        /* Get where we're going */
            case 1:             /* Couldn't open it */
                exit(1);        /* So give up */
            case 2:             /* Oops -- file was altered */
                rspeak(202);    /* You dissolve */
                exit(1);        /* File could be non-adventure */
        }                       /* So don't unlink it. */
    }

#endif

    startup();              /* prepare for a user           */

    for(;;) {                       /* main command loop (label 2)  */
        if(newloc < 9 && newloc != 0 && closng) {
            rspeak(130);    /* if closing leave only by     */
            newloc = loc;   /*      main office             */

            if(!apanic) clock2 = 15;

            apanic = TRUE;
        }

        rval = fdwarf();        /* dwarf stuff                  */

        if(rval == 99) die(99);

    l2000:

        if(loc == 0) die(99);   /* label 2000                   */

        kk = &stext[loc];

        if((abb[loc] % abbnum) == 0 || kk->seekadr == 0)
            kk = &ltext[loc];

        if(!forced(loc) && dark()) {
            if(wzdark && pct(35)) {
                die(90);
                goto l2000;
            }

            kk = &rtext[16];
        }

        if(toting(bear)) rspeak(141);   /* 2001                 */

        speak(kk);
        k = 1;

        if(forced(loc))
            goto l8;

        if(loc == 33 && pct(25) && !closng) rspeak(8);

        if(!dark()) {
            abb[loc]++;

            for(i = atloc[loc]; i != 0; i = linkx[i]) { /*2004  */
                obj = i;

                if(obj > 100) obj -= 100;

                if(obj == steps && toting(nugget)) continue;

                if(prop[obj] < 0) {
                    if(closed) continue;

                    prop[obj] = 0;

                    if(obj == rug || obj == chain)
                        prop[obj] = 1;

                    tally--;

                    if(tally == tally2 && tally != 0)
                        if(limit > 35) limit = 35;
                }

                ll =  prop[obj];   /* 2006         */

                if(obj == steps && loc == fixed[steps])
                    ll = 1;

                pspeak(obj, ll);
            }                                       /* 2008 */

            goto l2012;
        l2009:
            k = 54;                 /* 2009                 */
        l2010:
            spk = k;
        l2011:
            rspeak(spk);
        }

    l2012:
        verb = 0;                       /* 2012                 */
        obj = 0;
    l2600:
        checkhints();                   /* to 2600-2602         */

        if(closed) {
            if(prop[oyster] < 0 && toting(oyster))
                pspeak(oyster, 1);

            for(i = 1; i < 100; i++)
                if(toting(i) && prop[i] < 0)    /*2604  */
                    prop[i] = -1 - prop[i];
        }

        wzdark = dark();                /* 2605                 */

        if(knfloc > 0 && knfloc != loc) knfloc = 1;

        getin(&wd1, &wd2);
#if 0

        if(delhit) {                    /* user typed a DEL     */
            delhit = 0;             /* reset counter        */
            strcpy(wd1, "quit");   /* pretend he's quitting*/
            *wd2 = 0;
        }

#endif
    l2608:

        if((foobar = -foobar) > 0) foobar = 0;  /* 2608         */

        /* should check here for "magic mode"                   */
        turns++;

        if(demo && turns >= SHORT) done(1);     /* to 13000     */

        if(verb == say && *wd2 != 0) verb = 0;

        if(verb == say)
            goto l4090;

        if(tally == 0 && loc >= 15 && loc != 33) clock1--;

        if(clock1 == 0) {
            closing();                      /* to 10000     */
            goto l19999;
        }

        if(clock1 < 0) clock2--;

        if(clock2 == 0) {
            caveclose();            /* to 11000             */
            continue;               /* back to 2            */
        }

        if(prop[lamp] == 1) limit--;

        if(limit <= 30 && here(batter) && prop[batter] == 0
                && here(lamp)) {
            rspeak(188);            /* 12000                */
            prop[batter] = 1;

            if(toting(batter)) drop(batter, loc);

            limit = limit + 2500;
            lmwarn = FALSE;
            goto l19999;
        }

        if(limit == 0) {
            limit = -1;             /* 12400                */
            prop[lamp] = 0;
            rspeak(184);
            goto l19999;
        }

        if(limit < 0 && loc <= 8) {
            rspeak(185);            /* 12600                */
            gaveup = TRUE;
            done(2);                /* to 20000             */
        }

        if(limit <= 30) {
            if(lmwarn || !here(lamp)) goto l19999;  /*12200*/

            lmwarn = TRUE;
            spk = 187;

            if(place[batter] == 0) spk = 183;

            if(prop[batter] == 1) spk = 189;

            rspeak(spk);
        }

    l19999:
        k = 43;

        if(liqloc(loc) == water) k = 70;

        if(!strncmp(wd1, "enter", 5) &&
                (!strncmp(wd2, "strea", 5) || !strncmp(wd2, "water", 5)))
            goto l2010;

        if(!strncmp(wd1, "enter", 5) && *wd2 != 0) goto l2800;

        if((strncmp(wd1, "water", 5) && strncmp(wd1, "oil", 3))
                || (strncmp(wd2, "plant", 5) && strncmp(wd2, "door", 4)))
            goto l2610;

        if(at(vocab(wd2, 1, 0))) strcpy(wd2, "pour");

    l2610:

        if(!strncmp(wd1, "west", 4))
            if(++iwest == 10) rspeak(17);

    l2630:
        i = vocab(wd1, -1, 0);

        if(i == -1) {
            spk = 60;               /* 3000         */

            if(pct(20)) spk = 61;

            if(pct(20)) spk = 13;

            rspeak(spk);
            goto l2600;
        }

        k = i % 1000;
        kq = i / 1000 + 1;

        switch(kq) {
            case 1:
                goto l8;
            case 2:
                goto l5000;
            case 3:
                goto l4000;
            case 4:
                goto l2010;
            default:
                bug(22);
        }

    l8:

        switch(march()) {
            case 2:
                continue;           /* i.e. goto l2         */
            case 99:
                die(99);
                goto l2000;
            default:
                bug(110);
        }

    l2800:
        strcpy(wd1, wd2);
        *wd2 = 0;
        goto l2610;

    l4000:
        verb = k;
        spk = actspk[verb];

        if(*wd2 != 0 && verb != say) goto l2800;

        if(verb == say) obj = *wd2;

        if(obj != 0) goto l4090;

        switch(verb) {
            case 1:                     /* take = 8010          */

                if(atloc[loc] == 0 || linkx[atloc[loc]] != 0) goto l8000;

                for(i = 1; i <= 5; i++)
                    if(dloc[i] == loc && dflag >= 2) goto l8000;

                obj = atloc[loc];
                goto l9010;
            case 2:
            case 3:
            case 9:     /* 8000 : drop,say,wave */
            case 10:
            case 16:
            case 17:  /* calm,rub,toss        */
            case 19:
            case 21:
            case 28:  /* find,feed,break      */
            case 29:                    /* wake                 */
            l8000:
                printf("%s what?\n", wd1);
                obj = 0;
                goto l2600;
            case 4:
            case 6:             /* 8040 open,lock       */
                spk = 28;

                if(here(clam)) obj = clam;

                if(here(oyster)) obj = oyster;

                if(at(door)) obj = door;

                if(at(grate)) obj = grate;

                if(obj != 0 && here(chain)) goto l8000;

                if(here(chain)) obj = chain;

                if(obj == 0) goto l2011;

                goto l9040;
            case 5:
                goto l2009;         /* nothing              */
            case 7:
                goto l9070;         /* on                   */
            case 8:
                goto l9080;         /* off                  */
            case 11:
                goto l8000;        /* walk                 */
            case 12:
                goto l9120;        /* kill                 */
            case 13:
                goto l9130;        /* pour                 */
            case 14:                    /* eat: 8140            */

                if(!here(food)) goto l8000;

            l8142:
                dstroy(food);
                spk = 72;
                goto l2011;
            case 15:
                goto l9150;        /* drink                */
            case 18:                    /* quit: 8180           */
                gaveup = yes(22, 54, 54);

                if(gaveup) done(2);     /* 8185                 */

                goto l2012;
            case 20:                    /* invent=8200          */
                spk = 98;

                for(i = 1; i <= 100; i++) {
                    if(i != bear && toting(i)) {
                        if(spk == 98) rspeak(99);

                        blklin = FALSE;
                        pspeak(i, -1);
                        blklin = TRUE;
                        spk = 0;
                    }
                }

                if(toting(bear)) spk = 141;

                goto l2011;
            case 22:
                goto l9220;        /* fill                 */
            case 23:
                goto l9230;        /* blast                */
            case 24:                    /* score: 8240          */
                scorng = TRUE;
                printf("If you were to quit now, you would score");
                printf(" %d out of a possible ", score());
                printf("%d.", mxscor);
                scorng = FALSE;
                gaveup = yes(143, 54, 54);

                if(gaveup) done(2);

                goto l2012;
            case 25:                    /* foo: 8250            */
                k = vocab(wd1, 3, 0);
                spk = 42;

                if(foobar == 1 - k) goto l8252;

                if(foobar != 0) spk = 151;

                goto l2011;
            l8252:
                foobar = k;

                if(k != 4) goto l2009;

                foobar = 0;

                if(place[eggs] == plac[eggs]
                        || (toting(eggs) && loc == plac[eggs])) goto l2011;

                if(place[eggs] == 0 && place[troll] == 0 && prop[troll] == 0)
                    prop[troll] = 1;

                k = 2;

                if(here(eggs)) k = 1;

                if(loc == plac[eggs]) k = 0;

                move(eggs, plac[eggs]);
                pspeak(eggs, k);
                goto l2012;
            case 26:                    /* brief=8260           */
                spk = 156;
                abbnum = 10000;
                detail = 3;
                goto l2011;
            case 27:                    /* read=8270            */

                if(here(magzin)) obj = magzin;

                if(here(tablet)) obj = obj * 100 + tablet;

                if(here(messag)) obj = obj * 100 + messag;

                if(closed && toting(oyster)) obj = oyster;

                if(obj > 100 || obj == 0 || dark()) goto l8000;

                goto l9270;
            case 30:                    /* suspend=8300         */
                spk = 201;

                if(demo) goto l2011;

                printf("I can suspend your adventure for you so");
                printf(" you can resume later, but\n");
                printf("you will have to wait at least");
                printf(" %d minutes before continuing.", latncy);

                if(!yes(200, 54, 54)) goto l2012;

                datime(&saved, &savet);
                ciao();                 /* Do we quit? */
                continue;               /* Maybe not */
            case 31:                    /* hours=8310           */
                printf("Colossal cave is closed 9am-5pm Mon ");
                printf("through Fri except holidays.\n");
                goto l2012;
            default:
                bug(23);
        }

    l4090:

        switch(verb) {
            case 1:                     /* take = 9010          */
            l9010:

                switch(trtake()) {
                    case 2011:
                        goto l2011;
                    case 9220:
                        goto l9220;
                    case 2009:
                        goto l2009;
                    case 2012:
                        goto l2012;
                    default:
                        bug(102);
                }

            l9020:
            case 2:                     /* drop = 9020          */

                switch(trdrop()) {
                    case 2011:
                        goto l2011;
                    case 19000:
                        done(3);
                    case 2012:
                        goto l2012;
                    default:
                        bug(105);
                }

            case 3:

                switch(trsay()) {
                    case 2012:
                        goto l2012;
                    case 2630:
                        goto l2630;
                    default:
                        bug(107);
                }

            l9040:
            case 4:
            case 6:            /* open, close          */

                switch(tropen()) {
                    case 2011:
                        goto l2011;
                    case 2010:
                        goto l2010;
                    default:
                        bug(106);
                }

            case 5:
                goto l2009;         /* nothing              */
            case 7:                     /* on   9070            */
            l9070:

                if(!here(lamp))  goto l2011;

                spk = 184;

                if(limit < 0) goto l2011;

                prop[lamp] = 1;
                rspeak(39);

                if(wzdark) goto l2000;

                goto l2012;

            case 8:                     /* off                  */
            l9080:

                if(!here(lamp)) goto l2011;

                prop[lamp] = 0;
                rspeak(40);

                if(dark()) rspeak(16);

                goto l2012;

            case 9:                     /* wave                 */

                if((!toting(obj)) && (obj != rod || !toting(rod2)))
                    spk = 29;

                if(obj != rod || !at(fissur) || !toting(obj) || closng)
                    goto l2011;

                prop[fissur] = 1 - prop[fissur];
                pspeak(fissur, 2 - prop[fissur]);
                goto l2012;
            case 10:
            case 11:
            case 18:  /* calm, walk, quit     */
            case 24:
            case 25:
            case 26:  /* score, foo, brief    */
            case 30:
            case 31:           /* suspend, hours       */
                goto l2011;
            l9120:
            case 12:                    /* kill                 */

                switch(trkill()) {
                    case 8000:
                        goto l8000;
                    case 8:
                        goto l8;
                    case 2011:
                        goto l2011;
                    case 2608:
                        goto l2608;
                    case 19000:
                        done(3);
                    default:
                        bug(112);
                }

            l9130:
            case 13:                    /* pour                 */

                if(obj == bottle || obj == 0) obj = liq();

                if(obj == 0) goto l8000;

                if(!toting(obj)) goto l2011;

                spk = 78;

                if(obj != oil && obj != water) goto l2011;

                prop[bottle] = 1;
                place[obj] = 0;
                spk = 77;

                if(!(at(plant) || at(door))) goto l2011;

                if(at(door)) {
                    prop[door] = 0; /* 9132                 */

                    if(obj == oil) prop[door] = 1;

                    spk = 113 + prop[door];
                    goto l2011;
                }

                spk = 112;

                if(obj != water) goto l2011;

                pspeak(plant, prop[plant] + 1);
                prop[plant] = (prop[plant] + 2) % 6;
                prop[plant2] = prop[plant] / 2;
                k = null;
                goto l8;
            case 14:                    /* 9140 - eat           */

                if(obj == food) goto l8142;

                if(obj == bird || obj == snake || obj == clam || obj == oyster
                        || obj == dwarf || obj == dragon || obj == troll
                        || obj == bear) spk = 71;

                goto l2011;
            l9150:
            case 15:                    /* 9150 - drink         */

                if(obj == 0 && liqloc(loc) != water && (liq() != water
                                                        || !here(bottle))) goto l8000;

                if(obj != 0 && obj != water) spk = 110;

                if(spk == 110 || liq() != water || !here(bottle))
                    goto l2011;

                prop[bottle] = 1;
                place[water] = 0;
                spk = 74;
                goto l2011;
            case 16:                    /* 9160: rub            */

                if(obj != lamp) spk = 76;

                goto l2011;
            case 17:                    /* 9170: throw          */

                switch(trtoss()) {
                    case 2011:
                        goto l2011;
                    case 9020:
                        goto l9020;
                    case 9120:
                        goto l9120;
                    case 8:
                        goto l8;
                    case 9210:
                        goto l9210;
                    default:
                        bug(113);
                }

            case 19:
            case 20:           /* 9190: find, invent   */

                if(at(obj) || (liq() == obj && at(bottle))
                        || k == liqloc(loc)) spk = 94;

                for(i = 1; i <= 5; i++)
                    if(dloc[i] == loc && dflag >= 2 && obj == dwarf)
                        spk = 94;

                if(closed) spk = 138;

                if(toting(obj)) spk = 24;

                goto l2011;
            l9210:
            case 21:                    /* feed                 */

                switch(trfeed()) {
                    case 2011:
                        goto l2011;
                    default:
                        bug(114);
                }

            l9220:
            case 22:                    /* fill                 */

                switch(trfill()) {
                    case 2011:
                        goto l2011;
                    case 8000:
                        goto l8000;
                    case 9020:
                        goto l9020;
                    default:
                        bug(115);
                }

            l9230:
            case 23:                    /* blast                */

                if(prop[rod2] < 0 || !closed) goto l2011;

                bonus = 133;

                if(loc == 115) bonus = 134;

                if(here(rod2)) bonus = 135;

                rspeak(bonus);
                done(2);
            l9270:
            case 27:                    /* read                 */

                if(dark()) goto l5190;

                if(obj == magzin) spk = 190;

                if(obj == tablet) spk = 196;

                if(obj == messag) spk = 191;

                if(obj == oyster && hinted[2] && toting(oyster)) spk = 194;

                if(obj != oyster || hinted[2] || !toting(oyster)
                        || !closed) goto l2011;

                hinted[2] = yes(192, 193, 54);
                goto l2012;
            case 28:                    /* break                */

                if(obj == mirror) spk = 148;

                if(obj == vase && prop[vase] == 0) {
                    spk = 198;

                    if(toting(vase)) drop(vase, loc);

                    prop[vase] = 2;
                    fixed[vase] = -1;
                    goto l2011;
                }

                if(obj != mirror || !closed) goto l2011;

                rspeak(197);
                done(3);

            case 29:                    /* wake                 */

                if(obj != dwarf || !closed) goto l2011;

                rspeak(199);
                done(3);

            default:
                bug(24);
        }

    l5000:
        obj = k;

        if(fixed[k] != loc && !here(k)) goto l5100;

    l5010:

        if(*wd2 != 0) goto l2800;

        if(verb != 0) goto l4090;

        printf("What do you want to do with the %s?\n", wd1);
        goto l2600;
    l5100:

        if(k != grate) goto l5110;

        if(loc == 1 || loc == 4 || loc == 7) k = dprssn;

        if(loc > 9 && loc < 15) k = entrnc;

        if(k != grate) goto l8;

    l5110:

        if(k != dwarf) goto l5120;

        for(i = 1; i <= 5; i++)
            if(dloc[i] == loc && dflag >= 2) goto l5010;

    l5120:

        if((liq() == k && here(bottle)) || k == liqloc(loc)) goto l5010;

        if(obj != plant || !at(plant2) || prop[plant2] == 0) goto l5130;

        obj = plant2;
        goto l5010;
    l5130:

        if(obj != knife || knfloc != loc) goto l5140;

        knfloc = -1;
        spk = 116;
        goto l2011;
    l5140:

        if(obj != rod || !here(rod2)) goto l5190;

        obj = rod2;
        goto l5010;
    l5190:

        if((verb == find || verb == invent) && *wd2 == 0) goto l5010;

        printf("I see no %s here\n", wd1);
        goto l2012;
    }
}
