[net.sources.games] Galaxy - part 7 of 10

ejb@think.ARPA (Erik Bailey) (04/24/86)

#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	move_to.c
#	no_detect.c
#	options.h
#	over_stat.c
#	parse.c
# This archive created: Sat Jun  8 13:01:36 1985
echo shar: extracting move_to.c '(21037 characters)'
cat << \SHAR_EOF > move_to.c
/*
 * %W% (mrdch&amnnon) %G%
 */

# include "header"
# define ENEMY_FIGT sp->inventar.popul[FIGT]

int     my_ships[MAXSHIPS];     /* # ships moved to attack */
movable taken;                  /* here we put all that we have taken */
int     fighters;               /* no. of attacking fighters     */
planet * fp, *sp;               /* the First and Second planets pointers */
int     past_plan;              /* how many planets did we pass */
int     attack_fail[] = {
    0, 0, 2, 8, 16, 25, 33, 37, 42, 44, 45, 46, 47, 48
};
int     this_paint;

moveto (s)
char   *s;
{
    planet * tmp;
    char    s1[100];
    int     i,
            j,
            n,
            ngate;
    double  dtct,
            nodtct,
            ftemp,
            addfact;
    char   *spotted_ships ();   /* procedure to transform vars of the * type
                                   int[MAXSHIPS] to string */

    for (j = 0; j < MAXSHIPS; j++)/* clean temp storage */
        my_ships[j] = 0;
    for (j = 0; j < CLASES; j++)
        taken.popul[j] = 0;
    taken.metals = 0;

    fp = getpl (s);             /* see where from */
    assert_player (fp);         /* is the first planet his own */
    skipwhite (s);              /* go to the second planet */

    if (*s != '-') {            /* the '-' needed to signify destination */
        say ("Destination not clear, sir !!");
        return;
    }
    else
        *s = ' ';               /* the function must have a ' ' at the start */
    sp = getpl (s);             /* identify the second planet */
    if (fp == sp) {
        say ("That will not change much, sir !!");
        return;
    }
    skipwhite (s);
    j = -1;
    if (*s == '>') {            /* a SPECIFIC direction was given */
        s++;
        skipwhite (s);
    /* check if the direction is one allowed */
        if ((j = find_direct (*s++)) < 0) {
            say ("The direction specified is unclear, sir!!!");
            return;
        }
/* check if this direction brings us to the destination */
        tmp = fp;
        for (i = 0; i < 17; i++)/* can't be more than that */
            if ((tmp = tmp -> gate[j]) == sp || tmp == NULL)
                break;
        if (tmp != sp) {
            say ("In this direction we can never reach there, sir!!!");
            return;
        }

    }
 /*
  * Search for the destination planet along the specified
  * route. You either fall at the galaxy end, meet yourself
  * again in the circle, or FIND it.
  */
    if (j == -1) {              /* no direction was specified */
        ngate = 0;
        for (i = 0; i < 10; i++) {
            tmp = fp;
            while ((tmp = tmp -> gate[i]))
                if (tmp == sp) {
                    ngate++;
                    j = i;
                    break;      /* see remark below */
                }
                else
                    if (tmp == fp)
                        break;
        }
        if (!ngate) {
            say ("I don't see any direct route to %s, sir.", sp -> pid);
            return;
        }
    /* If forcing the players to specify a route is desired. if (ngate > 1) {
       say ("There is more then one way to get to %s, sir.", sp -> pid);
       return; } */
    }
    ngate = j;
 /* start collecting the aramade that was ordered to fly */
    for (;;) {
        skipwhite (s);
        i = atoi (s);           /* take the no. of ships */
        assert_negative (i);    /* see if not negative */
        if (i) {                /* if any was specified */
            skipnum (s);        /* go over it */
            skipwhite (s);      /* and get the type */
        }
        else
            i = 1;              /* if none given, assume 1 */
        if (*s < 'a')
            *s += ('a' - 'A');  /* transform them to lower */
        if ((*s < 'a') || (*s > 'a' + MAXSHIPS - 1)) {
            say ("The type of ship is not clear, sir!!");
            return;
        }
        j = *s - 'a';
        my_ships[j] += i;
        s++;
        skipwhite (s);
        if (!*s)                /* check if EOL reached */
            break;
    }
    for (j = 0; j < MAXSHIPS; j++)
        if (my_ships[j] > fp -> ships[j]) {
            say ("But you don't have that many %c-type ships there, sir!!", j + 'A');
            return;
        }
    n = 0;                      /* calculate no of fighters to fly them */
    for (j = 0, i = 1; j < MAXSHIPS; j++, i *= 2)
        n += NCREW / i * my_ships[j];
    if (n > fp -> inventar.popul[FIGT]) {/* not enough */
        say ("But sir, there are not enough fighters to fly these ships !!");
        return;
    }

 /*
  * At this point it is clear that movement is possible.
  * Before doing anything else- put in a "movable"
  * structure everything ordered to be moved. Update the
  * source planet NOW, and the destination planet
  * only after it's nature is known.
  * Then check if the movement was discovered. If so-
  * notify the enemy.
  * If going to a friendly planet just do the house keeping.
  * Else -  it's WAR .
  */

 /* update no. of fighters on the source planet */

    fighters = n;
    fp -> inventar.popul[FIGT] -= n;
 /* update no. of ships */
    for (j = 0; j < MAXSHIPS; j++)
        fp -> ships[j] -= my_ships[j];
 /* deal with the knowledge */
    taken.know = fp -> to_take.know;
    fp -> to_take.know = 0;
 /* how much can he carry? */
    n = 0;
    for (j = 0; j < MAXSHIPS; j++)
        n += (j + 1) * my_ships[j];
    if (n >= fp -> to_take.metals) {/* enough room */
        taken.metals += fp -> to_take.metals;
        fp -> to_take.metals = 0;
    }
    else {
        taken.metals += fp -> to_take.metals - n;
        fp -> to_take.metals -= n;
    }
 /* see how many people wait */
    i = 0;
    for (j = 0; j < CLASES; j++)
        i += fp -> to_take.popul[j];
 /* and how many places */
    n = 0;
    for (j = 0; j < MAXSHIPS; j++)
        n += VISITORS * (j + 1) * my_ships[j];
    if (n >= i)                 /* if enough room */
        for (j = 0; j < CLASES; j++) {
            taken.popul[j] = fp -> to_take.popul[j];
            fp -> to_take.popul[j] = 0;
        }
 /* NOT enough room. transfer by importance */
    else
        for (j = 0; n > 0; j++) {
            if ((n - fp -> to_take.popul[j]) >= 0) {
                n -= fp -> to_take.popul[j];
                taken.popul[j] = fp -> to_take.popul[j];
                fp -> to_take.popul[j] = 0;
            }
            else {
                taken.popul[j] = n;
                fp -> to_take.popul[j] -= n;
                n = 0;
            }
        }

 /* here check if the movement was discovered */

    this_paint = fp -> paint;   /* keep the paint. */
    fp -> paint = 0;            /* NONE was left at home */

 /*
  * Calculate effective painting.
  * The rule when calculating the paint:
  *     More ships   - easier to detect ;
  *     Better ships - harder to detect.
  * The calculation is confined to the type of ship. i.e.
  * each ship type has it's own no. indicating how
  * difficult it is to detect it.
  * As the ships start their voyage, the paint fades at
  * the FADE_RATE per each planet past-by.
  * A new factor is then calculated.
  */
    addfact = 0;
    for (i = 0, ftemp = 1; i < MAXSHIPS; i++, ftemp /= 2)
        addfact += ftemp * my_ships[i];
    nodtct = this_paint / addfact;

    tmp = fp;
    past_plan = 0;

    do {
        past_plan++;            /* count the no. of planets we passed */
        tmp = tmp -> gate[ngate];/* continue along the line */
        this_paint = (double) this_paint * (100.- FADE_RATE) / 100.;
        addfact = 0;
        for (i = 0, ftemp = 1; i < MAXSHIPS; i++, ftemp /= 2)
            addfact += ftemp * my_ships[i];
        nodtct = this_paint / addfact;

        if (tmp -> whos != fp -> whos) {
            dtct = tmp -> detect;
            if (dtct > nodtct) {
                if (!any_force (tmp -> missile))
                    (void) sprintf (s1, "Sir!!! At %s we spotted %s enemy ships.", tmp -> pid, spotted_ships (my_ships));
                else {
                    (void) sprintf (s1, "Sir!!! At %s our %s missiles encountered ", tmp -> pid, spotted_ships (tmp -> missile));
                    (void) sprintf (s1, "%s%s enemy ships.", s1, spotted_ships (my_ships));
                }
                dowrite_enemy (s1, !player);
                missile_war (tmp);
                if (!any_force (my_ships)) {
                    (void) sprintf (s1, "Sir!!! Our missiles defeated the enemy at %s!!!", tmp -> pid);
                    dowrite_enemy (s1, !player);
                    assert_loosing ();
                }
            }
        }
    } while (tmp != sp);

    if (sp -> alms)             /* are there any alms ? */
        assert_loosing ();

/* *********************************************  */

    if ((fp -> whos == sp -> whos) || (sp -> whos == 2)) {
    /* forces remain in his domain or neutral captured */
    /* first move the ships */
        for (j = 0; j < MAXSHIPS; j++)
            sp -> ships[j] += my_ships[j];
    /* then the fighters */
        sp -> inventar.popul[FIGT] += fighters;
    /* is there knowledge to take? */
        if (sp -> to_take.know < taken.know)
            sp -> to_take.know = taken.know;
    /* take the materials */
        sp -> to_take.metals += taken.metals;
    /* take the people */
        for (j = 0; j < CLASES; j++)
            sp -> to_take.popul[j] += taken.popul[j];
        sp -> paint += this_paint;
        if (sp -> whos != fp -> whos) {
            say ("Congratulations, sir. We have captured that planet.");
            sp -> whos = fp -> whos;
            prepare_siege ();
            chek_siege (sp);
            return;
        }
    }
    else {
        if (ENEMY_FIGT)         /* any FIGHTERS there? */
            war ();
        if (!any_force (my_ships)) {
            (void) sprintf (s1, "Sir!!! Our forces have encountered and defeated the enemy at %s!!!", sp -> pid);
            dowrite_enemy (s1, !player);
            assert_loosing ();
        }
        capture (1, sp);
        sp -> paint += this_paint;
        prepare_siege ();
        chek_siege (sp);
        say ("Congratulations, sir!!. We have captured that planet.");
    }
    check_end ();
}

/* *********************************************  */

 /*
  * This is the WAR section.
  * The results are determined by the no. and level of the
  * ships involved in the battle, and also the distance
  * that the attacking ships have traveled to their destination.
  * The longer they traveled, the better are the chances for
  * the defending forces to defeat their enemy with little
  * or no lost to themselves.
  */
war () {
    int     i,
            j,
            k,
            n;
    int     his_ships[MAXSHIPS];
    int     perc_fail = attack_fail[past_plan],
            temp_fail;
    char    s1[100];

    for (i = 0; i < MAXSHIPS; i++)
        his_ships[i] = 0;       /* clean temporary storage */

    for (j = MAXSHIPS - 1, i = NCREW; j >= 0; j--, i /= 2)
        while (sp -> ships[j] && ENEMY_FIGT >= NCREW / i) {
            his_ships[j]++;
            sp -> ships[j]--;
            ENEMY_FIGT -= NCREW / i;
        }

    if (!any_force (his_ships))
        return;                 /* he might not have enough soldiers */

    for (j = 0; j < MAXSHIPS; j++)
        while (my_ships[j] && his_ships[j]) {/* any ships */
            my_ships[j]--;      /* I ALWAYS loose one */
            i = 100 - (rand () % 100);
            if (i > perc_fail)  /* if more then criterion */
                his_ships[j]--; /* He looses too */
        }

    if (!any_force (his_ships))
        return;

    for (j = 1, k = 2; j < MAXSHIPS; j++, k *= 2) {
        if (my_ships[j] > 0) {
            i = 0;
            n = k;
            while (i < j) {
                while (his_ships[i] >= n && my_ships[j]) {
                    my_ships[j]--;/* I loose */
                    temp_fail = 100 - (rand () % 100);
                    if (temp_fail > perc_fail)
                        his_ships[i] -= n;/* He too */
                }
                if (my_ships[j])
                    his_ships[i] = 0;
                i++;
                n /= 2;
            }
        }
        else
            if (his_ships[j] > 0) {
                i = 0;
                n = k;
                while (i < j) {
                    while (my_ships[i] >= n && his_ships[j]) {
                        my_ships[i] -= n;
                        temp_fail = 100 - (rand () % 100);
                        if (temp_fail > perc_fail)
                            his_ships[j]--;
                    }
                    if (his_ships[j])
                        my_ships[i] = 0;
                    i++;
                    n /= 2;
                }
            }
    }
    if (!any_force (his_ships))
        return;

 /* none left from My forces.  we're doomed */

    n = 0;              /* calculate no of fighters left to him */
    for (j = 0, i = 1; j < MAXSHIPS; j++, i *= 2) {
        sp -> ships[j] += his_ships[j];
        n += NCREW / i * his_ships[j];
    }

    ENEMY_FIGT += n;
    (void) sprintf (s1, "Sir!!! Our forces have encountered and defeated the enemy at %s!!!", sp -> pid);
    dowrite_enemy (s1, !player);
    assert_loosing ();
}

missile_war (pp)
planet * pp;
{
    int     i,
            j,
            k,
            n;
    char    s1[100];
    int     destroyed[MAXSHIPS];/* # of ships destroyed */

    if (!any_force (pp -> missile))
        return;                 /* the defender has no missiles there */

    for (j = 0; j < MAXSHIPS; j++)
        destroyed[j] = 0;       /* all ships are intact (so far...) */

    for (j = 0; j < MAXSHIPS; j++)
        while (my_ships[j] && pp -> missile[j]) {/* any ships */
            my_ships[j]--;      /* I ALWAYS loose one */
            destroyed[j]++;     /* remember what I lost */
            pp -> missile[j]--; /* He looses too */
        }

    if (!any_force (pp -> missile)) {
    /* The battle has been fought, tell the owner of the missiles */
        (void) sprintf (s1, "Sir!!! Our missiles destroyed the enemy ships: %s.", spotted_ships (destroyed));
        dowrite_enemy (s1, !player);
        return;
    }

    for (j = 1, k = 2; j < MAXSHIPS; j++, k *= 2) {
        if (my_ships[j] > 0) {
            i = 0;
            n = k;
            while (i < j) {
                while (pp -> missile[i] >= n && my_ships[j]) {
                    my_ships[j]--;
                    destroyed[j]++;
                    pp -> missile[i] -= n;
                }
                if (my_ships[j])
                    pp -> missile[i] = 0;
                i++;
                n /= 2;
            }
        }
        else
            if (pp -> missile[j] > 0) {
                i = 0;
                n = k;
                while (i < j) {
                    while (my_ships[i] >= n && pp -> missile[j]) {
                        my_ships[i] -= n;
                        destroyed[j] += n;
                        pp -> missile[j]--;
                    }
                    if (pp -> missile[j]) {
                        destroyed[i] = my_ships[i];
                        my_ships[i] = 0;
                    }
                    i++;
                    n /= 2;
                }
            }
    }
 /* The battle has been fought, tell the owner of the missiles */
    (void) sprintf (s1, "Sir!!! Our missiles destroyed the enemy ships: %s.", spotted_ships (destroyed));
    dowrite_enemy (s1, !player);
}

/*
 * Here when landing on a unarmed enemy's teritory
 * or when winning a battle.
 */

capture (force, sp)
int     force;
planet * sp;
{
    int     i,
            j,
            k,
            m,
            n,
            n1,
            n2;

    sp -> whos = fp -> whos;    /* now it is MINE */
    free_reports (sp -> reports);/* the reports are not actual */
    sp -> secur = 0;            /* no security is valid */
    if (force) {
        sp -> paint = 0;        /* if paint was left-destroy */
        sp -> detect = 0;       /* if detection left-destroy */
        for (j = 0; j < MAXSHIPS; j++)
            sp -> missile[j] = 0;
    }
    for (j = 0; j < ESPSIZ; j++)
        for (m = 0; m < ESPTYP; m++)
            for (k = 0; k < 2; k++)
                sp -> espion[k][m][j] = 0;/* and no espionage yet */

 /* first move the forces */
    for (j = 0; j < MAXSHIPS; j++)
        sp -> ships[j] = my_ships[j];
 /* how much metal can he carry? */
    n = 0;
    for (j = 0; j < MAXSHIPS; j++)
        n += (j + 1) * my_ships[j];
    if (n >= taken.metals)      /* enough room */
        sp -> to_take.metals += taken.metals;
    else
        sp -> to_take.metals += n;
 /* when dealing with knowledge, it is ALWAYS transfered */
    if (force) {
        sp -> to_take.know = taken.know;
        sp -> inventar.know = taken.know;
    }
 /* now deal with the people */
    n2 = sp -> to_take.popul[SLAV];/* keep them. they were yours */
    sp -> to_take.popul[SLAV] = 0;
 /* add all the to_be_transfered people */
    for (j = 0, n1 = 0; j < CLASES; j++) {
        n1 += sp -> to_take.popul[j];
        sp -> to_take.popul[j] = 0;
    }
    sp -> to_take.popul[CITI] = n2;
    sp -> to_take.popul[SLAV] = n1;/* put them correctly now */
 /* see how many people wait */
    i = 0;
    for (j = 0; j < CLASES; j++)
        i += taken.popul[j];
 /* and how many places */
    n = 0;
    for (j = 0; j < MAXSHIPS; j++)
        n += VISITORS * (j + 1) * my_ships[j];
    if (n >= i)                 /* if enough room */
        for (j = 0; j < CLASES; j++) {
            sp -> to_take.popul[j] += taken.popul[j];
        }
 /* NOT enough room. transfer by importance */
    else
        for (j = 0; n > 0; j++) {
            if ((n - taken.popul[j]) >= 0) {
                n -= taken.popul[j];
                sp -> to_take.popul[j] += taken.popul[j];
            }
            else {
                sp -> to_take.popul[j] += n;
                n = 0;
            }
        }
 /* now deal with the people that are stationed on the planet */
    n2 = sp -> inventar.popul[SLAV];/* keep them. they were yours */
    sp -> inventar.popul[SLAV] = 0;
 /* add all the to_be_transfered people */
    for (j = 0, n1 = 0; j < CLASES; j++) {
        n1 += sp -> inventar.popul[j];
        sp -> inventar.popul[j] = 0;
    }
    sp -> to_take.popul[CITI] += n2;
    sp -> inventar.popul[SLAV] = n1;/* put them correectly now */

    n = 0;                      /* calculate no of fighters left to me */
    for (j = 0, i = 1; j < MAXSHIPS; j++, i *= 2)
        n += NCREW / i * my_ships[j];
    ENEMY_FIGT = n;
}

/* this recursive functions frees all the information that
 * was gathered about a captured planet. Naturly, it is not valid
 * anymore. */
free_reports (prvinfo)
info * prvinfo;
{
    if (prvinfo == 0)
        return;                 /* end of list. */
    free_reports (prvinfo -> next);
    ifree (prvinfo);
}

/* check to see if any forces left */
any_force (ship)
int    *ship;
{
    int     n,
            j;

    n = 0;
    for (j = 0; j < MAXSHIPS; j++)
        if (*ship++)
            n++;
    return (n);
}
/* this function prepares for the siege checking */
prepare_siege () {
    int     i;

    fighters = 0;
    taken.know = 0;
    taken.metals = 0;
    for (i = 0; i < CLASES; i++)
        taken.popul[i] = 0;
    for (i = 0; i < MAXSHIPS; i++)
        my_ships[i] = 0;
}

/*
 * This function checks to see if by capturing a planet
 * a siege was completed around one of the enemy's planets.
 * Each surrounding planet is scanned, and if it belongs to
 * the enenmy, it's surroundings is scanned. If all the
 * planets belong to the PLAYER, it is considered captured.
 * In contrast to direct taking by force, all except the ships
 * remain intact.
 */

chek_siege (pp)
planet * pp;
{
    char    s[100];
    int     i,
            j,
            np;
    planet * tmp1, *tmp2;

    for (i = 0; i < 10; i++)
        if ((tmp1 = pp -> gate[i]) && (tmp1 -> whos == !player)) {
            for (j = 0, np = 0; j < 10; j++)
                if ((tmp2 = tmp1 -> gate[j]) && (tmp2 -> whos != player))
                    np++;
            if (!np) {          /* he is totaly surrounded */
                capture (0, tmp1);
                (void) sprintf (s, "Sir!!! we have taken %s planet too!!!", tmp1 -> pid);
                dowrite_enemy (s, player);
            }
        }
}

/* This procedure transforms an integer array with ship counts in */
/* a string listing the amounts of the different ships            */
/* The array [3,2,0,1,0,0,...,0] would be transformed to the      */
/* string " 3A 2B 1D" .                                           */
char   *spotted_ships (ship)
int    *ship;
{
    static char s[100];         /* The list of ships; e.g. " 3A 2B 1D" */
    int     j;

    s[0] = '\0';
    for (j = 0; j < MAXSHIPS; j++) {
        if (*ship)
            (void) sprintf (s, "%s %d%c", s, *ship, 'A' + j);
        ship++;
    }
    return (s);
}
SHAR_EOF
if test 21037 -ne "`wc -c move_to.c`"
then
echo shar: error transmitting move_to.c '(should have been 21037 characters)'
fi
echo shar: extracting no_detect.c '(726 characters)'
cat << \SHAR_EOF > no_detect.c
/*
 * %W% (mrdch&amnnon) %G%
 */

# include "header"

nodetect (s)
char   *s;
{
    planet * pp;
    int     i;

    pp = getpl (s);             /* get planet id                 */
    assert_player (pp);         /* see if legal planet + owner   */
    skipwhite (s);              /* go to the money part          */
    i = atoi (s);               /* take the amount               */
    assert_money (i);           /* see if there is enough of it */
    skipword (s);               /* skip that no.                 */
    assert_end (s);             /* does it end good??            */
    pp -> paint += i;           /* raise the paint               */
    teller[player] -= i;        /* take his money                */
}
SHAR_EOF
if test 726 -ne "`wc -c no_detect.c`"
then
echo shar: error transmitting no_detect.c '(should have been 726 characters)'
fi
echo shar: extracting options.h '(50 characters)'
cat << \SHAR_EOF > options.h
/*
 * %W% (mrdch&amnnon) %G%
 */

# define ENQDBG
SHAR_EOF
if test 50 -ne "`wc -c options.h`"
then
echo shar: error transmitting options.h '(should have been 50 characters)'
fi
echo shar: extracting over_stat.c '(10506 characters)'
cat << \SHAR_EOF > over_stat.c
/*
 * %W% (mrdch&amnnon) %G%
 */

# include "header"

overstat (s)
char   *s;
{
    planet * pp;
    int     i,
            j;
    int     all_popul[CLASES];  /* to count the entire population */
    int     myships[MAXSHIPS];  /* to count the ships inventory */
    int     mymissile[MAXSHIPS];/* to count the missile inventory */
    int     nplanets[PLKINDS + 1];/* to count planet's situation */
    int     nalms = 0;          /* to count the alms */
    int     nmetals = 0;        /* to count the metal digged */
    int     maxknow = -1;       /* the no. of planet with max know */
    char    cc;
    static char owner = 'O';
    static char black = '?';
    static char force = '!';
    static char specl = '+';
    static char alms  = '~';
    static char fight = '^';
    static char build = '&';
    static char dinfo = 'I';
    static char spies = 'S';
    static char detec = 'T';
    static char paint = '%';
    static char missl = 'M';

    skipwhite (s);
    if (*s == '\0') {
        flip ();
        clear ();
        for (i = 0; i < CLASES; i++)
            all_popul[i] = 0;
        for (i = 0; i < MAXSHIPS; i++) {
            myships[i] = 0;
            mymissile[i] = 0;
        }
        for (i = 0; i <= PLKINDS; i++)
            nplanets[i] = 0;
        for (i = 0, pp = &pl[0]; i < MAXPL; i++, pp = &pl[i])
            if (pp -> whos == player) {
                nplanets[PLKINDS]++;
                nalms += pp -> alms;/* add total alms */
                nmetals += pp -> inventar.metals;/* add total metals */
                if (maxknow == -1)
                    maxknow = i;
                if (pl[maxknow].inventar.know < pl[i].inventar.know)
                    maxknow = i;/* update max knowledge */

                if (pp -> inventar.popul[FIGT])
                    nplanets[FIGT]++;
                if (pp -> inventar.popul[CITI])
                    nplanets[CITI]++;
                if (pp -> inventar.popul[MINE])
                    nplanets[MINE]++;
                if (pp -> inventar.popul[BUIL])
                    nplanets[BUIL]++;
                if (pp -> inventar.popul[SCIE])
                    nplanets[SCIE]++;
                for (j = 0; j < CLASES; j++) {
                    all_popul[j] += pp -> inventar.popul[j];
                    all_popul[j] += pp -> to_take.popul[j];
                }
                for (j = 0; j < MAXSHIPS; j++) {
                    myships[j] += pp -> ships[j];
                    mymissile[j] += pp -> missile[j];
                }
            }

        pos (0, 28);
        print ("Overall situation report");
        pos (1, 28);
        print ("========================\r\n");
        print ("Population: %d\r\n", count_popul (player));
        for (j = 0; j < CLASES; j++)
            if (all_popul[j])
                print ("%6d %s\r\n", all_popul[j], ocup_name[j]);
        pos (11, 0);
        print ("Planets situation:\r\n");
        print ("%6d controlled planets\r\n", nplanets[PLKINDS]);
        print ("%6d Military bases.\r\n", nplanets[FIGT]);
        print ("%6d Agricultural planets.\r\n", nplanets[CITI]);
        print ("%6d Mining planets.\r\n", nplanets[MINE]);
        print ("%6d Industrial planets. \r\n", nplanets[BUIL]);
        print ("%6d Scientific planets.\r\n", nplanets[SCIE]);
        j = 3;
        pos (j++, 38);
        print ("No. of ships and missiles:");
        for (i = 0; i < MAXSHIPS; i++)
            if (myships[i] || mymissile[i]) {
                pos (j++, 35);
                print ("%c-type %4d ships %4d missiles.",
                        i + 'A', myships[i], mymissile[i]);
            }
        j++;
        pos (j++, 35);
        print ("Invested in trade %d Tellers.", trade[player]);
        pos (j++, 35);
        print ("Feeding the population with %d Tellers.",
                food[player]);
        pos (j++, 35);
        print ("Total of %d ALMs were laid.", nalms);
        pos (j++, 35);
        print ("Total of %d A-type metal quantities.", nmetals);
        pos (j++, 35);
        print ("The best knowledge is %c in planet %s.",
                'A' + pl[maxknow].inventar.know, pl[maxknow].pid);
        more ();
        return;
    }
/*
 * owner = 'O' ;
 * black = '?' ;
 * force = '!' ;
 * specl = '+' ;
 * alms  = '~' ;
 * fight = '^' ;
 * build = '&' ;
 * dinfo = 'I' ;
 * spies = 'S' ;
 * detec = 'T' ;
 * paint = '%' ;
 * missl = 'M' ;
 *
 * The chars used are: n  o  a  s  b  f  F  c  k  e  i  d  p  m
 * Their attributes:      O  ~  +  ?  !  ^  & A-G S  I  T  %  M
 */
    while ((cc = *s++)) {
        switch (cc) {
            case 'n':   /* clean the screen from all attributes */
                clean_attr ();
                break;
            case 'o':           /* show in reverse planets he owns */
                for (i = 0; i < MAXPL; i++)
                    if (pl[i].whos == player)
                        change_attr (owner, i);
                    else
                        check_attr (owner, i);
                break;
            case 'p':           /* show where detecting devices exist */
                for (i = 0; i < MAXPL; i++)
                    if (pl[i].whos == player)
                        if (pl[i].paint)
                            change_attr (paint, i);
                        else
                            check_attr (paint, i);
                break;
            case 'd':           /* show where detecting devices exist */
                for (i = 0; i < MAXPL; i++)
                    if (pl[i].whos == player)
                        if (pl[i].detect)
                            change_attr (detec, i);
                        else
                            check_attr (detec, i);
                break;

            case 'a':           /* show planets he owns with alm */
                for (i = 0; i < MAXPL; i++)
                    if (pl[i].whos == player)
                        if (pl[i].alms)
                            change_attr (alms, i);
                        else
                            check_attr (alms, i);
                break;
            case 's':           /* show special planets */
                for (i = 0; i < MAXPL; i++)
                    if (pl[i].whos == player) {
                        j = pl[i].inventar.popul[CITI] != 0;
                        j = j || (pl[i].inventar.popul[MINE] != 0);
                        j = j || (pl[i].inventar.popul[BUIL] != 0);
                        j = j || (pl[i].inventar.popul[SCIE] != 0);
                        if (j)
                            change_attr (specl, i);
                        else
                            check_attr (specl, i);
                    }
                break;
            case 'b':           /* show blanked planets */
                for (i = 0; i < MAXPL; i++)
                    if (pl[i].whos == player)
                        if (pl[i].secur)
                            change_attr (black, i);
                        else
                            check_attr (black, i);
                break;
            case 'f':           /* show where his forces are */
                for (i = 0; i < MAXPL; i++)
                    if (pl[i].whos == player) {
                        j = 0;
                        while (!pl[i].ships[j] && j < MAXSHIPS)
                                j++;
                        if (j < MAXSHIPS)
                            change_attr (force, i);
                        else
                            check_attr (force, i);
                    }
                break;
            case 'm':           /* show where his missiles are */
                for (i = 0; i < MAXPL; i++)
                    if (pl[i].whos == player) {
                        j = 0;
                        while (!pl[i].missile[j] && j < MAXSHIPS)
                                j++;
                        if (j < MAXSHIPS)
                            change_attr (missl, i);
                    }
                break;
            case 'F':           /* show where he has fighters */
                for (i = 0; i < MAXPL; i++)
                    if (pl[i].whos == player) {
                        if (pl[i].inventar.popul[FIGT])
                            change_attr (fight, i);
                        else
                            check_attr (fight, i);
                    }
                break;
            case 'c':   /* show where building of ships is done */
                for (i = 0; i < MAXPL; i++)
                    if (pl[i].whos == player) {
                        if (pl[i].to_build[BUILD_MONEY] || pl[i].to_build[NSHIPS])
                            change_attr (build, i);
                        else
                            check_attr (build, i);
                    }
                break;
            case 'k':   /* show other then A level of knowledge */
                for (i = 0; i < MAXPL; i++)
                    if (pl[i].whos == player) {
                        if (pl[i].inventar.know)
                            change_attr ('A' + pl[i].inventar.know, i);
                        else
                            if (pl[i].d_symbol[player] >= 'A' &&
                            pl[i].d_symbol[player] <= 'A' + MAXSHIPS)
                                change_attr (pl[i].symbol, i);
                    }
                break;
            case 'i':           /* show where you have messages */
                for (i = 0; i < MAXPL; i++)
                    if (count_msgs (pl[i].reports, player))
                        change_attr (dinfo, i);
                    else
                        check_attr (dinfo, i);
                break;
            case 'e':           /* show to which planet you have send
                                   spies */
                for (i = 0; i < MAXPL; i++)
                    if (count_spies (&pl[i], player))
                        change_attr (spies, i);
                    else
                        check_attr (spies, i);
                break;
            default:
                return;
        }
    }
}

clean_attr () {
    int     i;
    for (i = 0; i < MAXPL; i++)
        change_attr (pl[i].symbol, i);
}

change_attr (cc, i)
char    cc;
int     i;
{
    if (pl[i].d_symbol[player] != cc) {
        pl[i].d_symbol[player] = cc;
        pos (pl[i].coord[0], pl[i].coord[1] + 1);
        disch (cc);
    }
}

check_attr (cc, i)
char    cc;
{
    if (pl[i].d_symbol[player] == cc)
        change_attr (pl[i].symbol, i);
}
SHAR_EOF
if test 10506 -ne "`wc -c over_stat.c`"
then
echo shar: error transmitting over_stat.c '(should have been 10506 characters)'
fi
echo shar: extracting parse.c '(16496 characters)'
cat << \SHAR_EOF > parse.c
/*
 * %W% (mrdch&amnnon) %G%
 */

# include "header"

/* if a restored game switched players i.d. */
extern  SWITCH_FLAG;
extern  nulluser;
extern int  no_new_year;
char    moreflg[2] = TWOZERO;
/* flag to indicate if player changed during game */
char    didchange[2] = TWOZERO;
int     changestat;
planet * curpln;

int     overstat (), retrieve (), pversion (),
        getoutofhere (), restorgame (), savegame (), takepl (),
        endgame (), quit (), give_up (), planetsit (), planetenq (),
        blackout (), assign (), feedpop (), takefrom (), moveto (),
        detectmv (), nodetect (), leaveat (), trading (), putalm (),
        init_disc (), killalm (), write_enemy (), build (),
        set_missile (), help (), menu (), next_year (), wizwiz (),
        no_new (), toggle_wizard (), changeplay ();

struct commands {
    char   *str;                /* the command name      */
    int     (*cfun) ();         /* the function that executes it   */
    char   *docname;            /* the file name that documents it */
    char   *exp;                /* a short explanation   */
};

struct commands ctab[] = {
    "os", overstat, "overstat",
    "Overall Situation.                  os || os [abcdefFikmnops]",
    "ps", planetsit, "plansit",
    "Planet Situation.                   ps [plid] [i]",
    "as", assign, "assign",
    "Assign people.                      as [plid] N (cfmbs) (cfmbs)",
    "en", planetenq, "planenq",
    "Enquire Planet.                     en [plid] [level] (afkmpst) T",
    "bo", blackout, "blackout",
    "Blackout a Planet.                  bo [plid] T",
    "tk", takefrom, "takefrom",
    "Take from.                          tk [plid] (k) || (N (tcfmbsv) )",
    "lv", leaveat, "leave_at",
    "Leave at.                           lv [plid] (k || K) || (N (tcfmbsv) )",
    "mv", moveto, "move_to",
    "Move to.                            mv [plid] -[plid] [>dr] NH [NH NH ...]",
    "bs", build, "build",
    "Build new ships.                    bs [plid] NH T || bs [plid] t T",
    "sm", set_missile, "set_missl",
    "Set missiles.                       sm [plid] NH",
    "dt", detectmv, "detect",
    "Detect movement / Paint ships.      dt/nd [plid] T",
    "nd", nodetect, "paint", 0,
    "lm", putalm, "putalm",
    "Lay ALM.                            lm [plid] N",
    "dm", killalm, "killalm",
    "Deactivate ALM.                     dm [plid] N",
    "fd", feedpop, "feedpop",
    "Feed population.                    fd T",
    "tr", trading, "trade",
    "Trade.                              tr T",
    "rt", retrieve, "retrieve",
    "Retrieve invested money.            rt T (tfbs) [plid]",
    "wr", write_enemy, "write",
    "Write to the enemy.                 wr [anything....+ return]",
    "mp", init_disc, "init_dis",
    "Refresh the screen.                 mp",
    "ny", next_year, "next_year",
    "Jump a year/Continue stoped game.   ny",
    "nn", no_new, "next_year",
    "Stop game for a while.              nn",
    "sv", savegame, "savegame",
    "Save / Restore Game.                sv/rs (file name)",
    "rs", restorgame, "restor", 0,
    "gu", give_up, "give_up",
    "Give up this game / Ask to quit.    gu/qt",
    "qt", quit, "quit", 0,
    "menu", menu, 0, 0,
    "help", help, "help", 0,
    "man", help, "help", 0,
    "version", pversion, 0, 0,
    "cp", changeplay, "chng_ply", "# Change player",
    "wz", wizwiz, 0, "# Get a lot of everything",
    "capt", takepl, 0, "# Take any planet you wish",
    "toggle", toggle_wizard, 0, "# Give up/regain wizardcy",
    "getout", getoutofhere, 0, "# Exit the game neatly and QUICK!!",
    0, 0, 0, 0
};

/*
 * this funstion sets the active terminal to the required .
 */
termn (n) {
    if (SWITCH_FLAG)            /* in a restored game, player switched */
        n = !n;
    if (n == 0) {
        term0 ();
    }
    else {
        term1 ();
    }
/* check if cp command was given */
    if (didchange[n]) {
        player = !player;
        changestat = 1;
    }
    else
        changestat = 0;
/* set the  current planet to the active player */
    if (!player)
        curpln = spntr;
    else
        curpln = apntr;
}

#define GETSTRMODE      1
#define CURSORMODE      2

/* in these buffers the input from both players is gathered */
char    bufs[2][100];
/* pointers into the buffers */
int     bufsp[2] = TWOZERO;
/* flags to the current position of player */
int     mode[2] = {
    CURSORMODE, CURSORMODE
};
/*
 * The main loop. Reads chars from the two processes, stores
 * them in bufs, and interprets the command. When a legal
 * command is found, the function associated with that command
 * is invoked. The nature of this program requires that ALL
 * the relevant information to a specific command to be known
 * at the time of it's execution. (Any busy wait loop will cause
 * stagnation for the SECOND player).
 */
parse () {
    struct commands *c = ctab;
    char   *ch;
    chan x;

 /* initialize first terminal */
    termn (0);
    if (ctrlinit () == 0);
    crmode ();
    noecho ();
    say ("Sir. If you feel somewhat lost, give the \"help\" command.");
    cleol (22, 11);

 /* initialize second terminal */
    termn (1);
    if (ctrlinit () == 0);
    crmode ();
    noecho ();
    say ("Sir. If you feel somewhat lost, give the \"help\" command.");
    cleol (22, 11);

/* enter main loop */
getcommand:
    for (;;) {
        c = ctab;
        (void) fflush (ttys[0]);
        (void) fflush (ttys[1]);
        if (readc (&x) != sizeof (x))
            bug ("read error on pipe.");
        termn (x.ichan);        /* set terminal to where it came from */
    /*
     *  First check if it's in "more" mode .
     *  In that case, flip back on request.
     */
        if (moreflg[player]) {
            if (x.c != ' ' && x.c != '5')
                goto getcommand;
            endmore ();
            putmsgs ('r');      /* regular printout */
            prteller ();
            goto getcommand;
        }
    /* esc char toggles the two stages */
        if (x.c == '\033') {    /* ascii esc */
            if (mode[player] == GETSTRMODE) {
                mode[player] = CURSORMODE;
                curse_map (curpln);
            }
            else {
                mode[player] = GETSTRMODE;
                curse_com (curpln);
                cleol (22, 11 + bufsp[player]);
            }
            goto getcommand;
        }
    /* in the map mode, movement and message command and given */
        if (mode[player] == CURSORMODE) {
            if (x.c == '-' || x.c == ' ') {/* delete messages stack */
                putmsgs ('-');  /* to advance rapidly */
                curse_map (curpln);
                goto getcommand;
            }
        /* good for ascii only. */
            if ((x.c > '9') || iscntrl (x.c)) {
                curse_com (curpln);
                mode[player] = GETSTRMODE;
                cleol (22, 11 + bufsp[player]);
            }
            else {
                changeloc (x.c);
                goto getcommand;
            }
        }
        if (mode[player] == GETSTRMODE) {
            if (x.c == '\n' || x.c == '\r') {
                mode[player] = CURSORMODE;
                bufs[player][bufsp[player]] = '\0';
                ch = bufs[player];
                bufsp[player] = 0;
                goto parse;
            }
            else                /* collect the chars */
                dogetstr (x.c);
        }
    }
/* find out which command was given */
parse:
    if (*ch) {
        if (Pause) {
        /* were having a pause. Execute harmless commands (no movements) */
            if (strncmp (ch, "mv", 2) == 0) {
                say ("As we take a break, I cannot move a single ship, sir.");
                cleol (22, 11);
                goto getcommand;
            }
        }
        while (c -> str != 0) {
            cleol (23, 0);
            if (strcmpn (ch, c -> str, strlen (c -> str)) == 0) {
            /*  enable quick return in case of error */
                if (setjmp (jparse) == 0)
                    (*c -> cfun) (ch + strlen (c -> str));
            /* update time */
                if (!Pause)
                    softclock (0);
                if (!moreflg[player]) {
                    cleol (22, 11);
                    putmsgs ('r');/* regular */
                    prteller ();
                }
                goto getcommand;
            }
            c++;
        }
        error ();
        c = ctab;
        goto getcommand;
    }
    goto getcommand;
}

extern int  month;              /* the x/100 of the year */

prteller () {
    char    s[10];

    cleol (19, 0);
    pr_at (19, 4, "Planet: %s", curpln -> pid);
    pos (19, 25);
    if (teller[player])
        print ("You have %d Tellers left, sir.", teller[player]);
    else
        print ("No money left, sir. So sorry..");
    if (month < 10)
        (void) sprintf (s, "%c%d", '0', month);
    else
        (void) sprintf (s, "%d", month);
    if (wants_newy[player])
        pr_at (19, 62, "NY");
    pr_at (19, 65, "Year : %d.%s", year, s);
    curse_map (curpln);
}

changeloc (dir)
char    dir;
{
    int     j;

 /* if the terminal has the capability, flip the page over */
    if (dir == '5')
        if (ttyc -> t_fl != 0) {
            flip ();
            more ();
            return;
        }

    if ((j = find_direct (dir)) < 0)
        return;                 /* illegal direction */
    if (curpln -> gate[j] == NULL)
        return;
    curpln = curpln -> gate[j];
    if (!player)
        spntr = curpln;
    else
        apntr = curpln;

    pr_at (19, 12, "%s", curpln -> pid);
 /* update position at screen */
    curse_map (curpln);
}

/*
 * This function prints a message and sleeps until a character
 * is striked at the terminal which executed more.
 *
 * The problem is that we can't wait to a character here becaue
 * we want to get a character from the other terminal.
 *
 * We can use the fact that all the functions
 * using more() call it just before they return to parse.
 * More will simply set a flag to tell parse that we are in
 * more mode.
 */
more () {
    so (23, 56, "Hit SPACE to continue");
    (void) fflush (tty);
    moreflg[player] = 1;
}

endmore () {
    cleol (23, 0);              /* clear the "more" message */
    moreflg[player] = 0;
    flip ();
}

/*
 * Get online help. All the commands that are listed above
 * have help files associated with them. In case that information
 * is required about some general issues, the requested file is
 * searced. Actually, all the manual can be obtained in that
 * fashion.
 */
help (s)
char   *s;
{
    FILE * docfile;
    char    nwcm[200];
    struct commands *c = ctab;

    skipwhite (s);
    if (*s == '\0') {           /* no patrameters were given */
        strcpy (nwcm, "help");
        help (nwcm);            /* call recursivly with arg  */
        return;
    }

    if (*s == '-') {            /* a general information was requested */
        (void) sprintf (nwcm, "%s%s.doc", ONLINE, ++s);
        goto show_doc;
    }

    while (c -> str != 0) {     /* didn't reach the last command */
        if (strncmp (s, c -> str, strlen (c -> str)) == 0) {
            if (c -> docname == 0)
                break;
            (void) sprintf (nwcm, "%s%s.doc", ONLINE, c -> docname);
    show_doc: docfile = fopen (nwcm, "r");
            if (docfile == NULL) {
                say ("I think you have the wrong name, sir. Try \"help\".");
                return;
            }
            flip ();
            clear ();
            while (fgets (nwcm, 200, docfile) != NULL)
                print ("%s\r", nwcm);
            (void) fclose (docfile);
            more ();
            return;
        }
        c++;
    }
    say ("But sir !!! I don't understand that command. Try \"menu\".");
}

/*
 * Extract from the command structure the information concerning
 * the syntax of the commands.
 */
menu (s)
char   *s;
{
    struct commands *c = ctab;
    int     wiz = 0;

    skipwhite (s);
    if (*s == 'w') {
        assert_wizard ();
        wiz = 1;
    }

    flip ();
    clear ();
    if (!wiz)
        print ("<plid = planet id> <N = no.> <T = Tellers> <H = ship type> <dr = direction>");
    else
        print ("This commands are only yours to give, dear lord.\n\n\r\r");
    while (c -> str != 0) {
        if (c -> exp != 0) {
            if (!wiz) {
                if (*c -> exp != '#')
                    print ("\r\n%s", c -> exp);
            }
            else {
                if (*c -> exp == '#')
                    print ("\r\n%s:\t\t%s", c -> str, c -> exp);
            }
        }
        c++;
    }
    more ();
}

error () {
    say ("Sorry sir, but I don't understand you!!");
    curse_map (curpln);
}

/*
 * This function terminates the game. If it is calles with
 * a winner, the principal facts of the game will be recorded
 * on the galaxy score file. If there is no winner, the game
 * will just end gracefully.
 */
# include       "score.h"
endgame (mode)
int     mode;
{
    int     resf;
    char   *ctime ();
    struct score    sc;
    time_t time ();

/* force the printout of games played -null */
    if (nulluser && !iswiz[1])
        mode = 1;

    if (mode == -1)
        goto noscore;

    resf = open (GALSCOR, 1);
    if (resf == -1)
        goto noscore;

    (void) lseek (resf, 0L, 2);

    if (mode) {
        strcpy (sc.win, ply1), strcpy (sc.los, ply0);
    }
    else {
        strcpy (sc.win, ply0), strcpy (sc.los, ply1);
    }

    sc.played_at = time (0);
    sc.years = year;

    (void) write (resf, (char *) & sc, sizeof (sc));
    (void) close (resf);

noscore:
    term0 ();
    doend (mode);
    term1 ();
    doend (mode);
    if (mode != -1)
        sleep (7);
    (void) kill (0, 9);
}

doend (mode) {
    static char *argv[] = {
        "IGNORED",
        "-t"
    };

    clear ();
    if (mode != -1) {
        glxscore (2, argv);
    }
    ctrlreset ();
    (void) fflush (tty);
}

/* check if the capital was invaded */
check_end () {
    int     j = capitals[0] -> whos;

    if (j == capitals[1] -> whos)
        end_game (j);
}

/*
 * A suicidal command. When all is lost.
 */
give_up () {
    end_game (!player);
}

/*
 * This function enables two players to discontinue the game
 * withourt any of them loosing face. Of course, they both
 * must agree.
 */
quit () {
    if (wants_quit[player]) {
        wants_quit[player] = 0;
        say ("Canceling last quit request.");
        return;
    }
    if (!wants_quit[!player]) {
        wants_quit[player] = 1;
        say ("Waiting for him to agree....");
        dowrite_enemy ("I would like to quit. If offer accepted, give the \"qt\" command.", !player);
        return;
    }

    endgame (-1);
}

pversion () {
    extern char version[80];

    say (version);
}

/* STOP the time */
no_new () {
    if (nulluser || iswiz[player] == 1) {
        no_new_year = 1;
        return;
    }
 /* We want to have a break! */

    if (wants_pause[player]) {
        say ("Cancelling last pause request");
        wants_pause[player] = 0;
        return;
    }
    wants_pause[player] = 1;
    if (wants_pause[!player]) {
        Pause = 1;
        no_new_year = 1;
        dowrite_enemy ("Break activated, Sir!!!", player);
        dowrite_enemy ("Break activated, Sir!!!", !player);
        return;
    }
    say ("Waiting for him to agree.....");
    dowrite_enemy ("Hey, let's take a break OK ?", !player);
}

/*
 * If the two players ask for a new year - so it will happen.
 * wizard may force one.
 */
next_year () {
    if (nulluser || iswiz[player] == 1) {
        no_new_year = 0;
        Pause = 0;
        softclock (1);
        return;
    }

    if (wants_newy[player]) {
        wants_newy[player] = 0;
        if (Pause)
            dowrite_enemy ("Sorry. I still need time.", !player);
        say ("Canceling last new_year request.");
        return;
    }

    if (!wants_newy[!player]) {
        wants_newy[player] = 1;
        if (Pause) {
            dowrite_enemy ("Let's continue the game O.K. ?", !player);
            say ("Waiting for him to agree...");
        }
        return;
    }

    wants_newy[player] = 0;
    wants_newy[!player] = 0;
    no_new_year = 0;

    if (Pause) {
        Pause = 0;
        dowrite_enemy ("There we go again!!", player);
        dowrite_enemy ("There we go again!!", !player);
        softclock (2);
        return;
    }
    softclock (1);
}
SHAR_EOF
if test 16496 -ne "`wc -c parse.c`"
then
echo shar: error transmitting parse.c '(should have been 16496 characters)'
fi
#	End of shell archive
exit 0
-- 

Erik Bailey        -- 7 Oak Knoll                 (USENET courtesy of
ihnp4!think!ejb       Arlington, MA  02174        Thinking Machines Corp.
ejb@think.com         (617) 643-0732              Cambridge, MA)

	   It takes thought to make a program that thinks.
	   But it takes work to make a program that works.