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

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

#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	score.h
#	set_missle.c
#	softclock.c
#	table.h
#	take_from.c
#	term2init.c
#	terminal.c
#	trade.c
#	typedefs.h
# This archive created: Sat Jun  8 13:05:52 1985
echo shar: extracting score.h '(436 characters)'
cat << \SHAR_EOF > score.h
/*
 * %W% (mrdch&amnnon) %G%
 */

/*
 * this file defines the score information structure.
 */

struct  score                           /* score log structure */
{
        char    win[20] ;               /* winner name          */
        char    los[20] ;               /* looser name          */
        int     years ;                 /* game years played    */
        time_t  played_at ;             /* date played at       */
} ;
SHAR_EOF
if test 436 -ne "`wc -c score.h`"
then
echo shar: error transmitting score.h '(should have been 436 characters)'
fi
echo shar: extracting set_missle.c '(1874 characters)'
cat << \SHAR_EOF > set_missle.c
/*
 * %W% (mrdch&amnnon) %G%
 */

# include "header"

/*
 * In order to set new missiles, several requirements have to be met.
 * The planet on which it is to be build must have enough soldiers
 * on it.
 * The knowledge level on that planet has to be at least equal to the
 * level of missiles to be build.
 */

set_missile (s)
char   *s;
{
    planet * pp;
    int     j,
            factor,
            nmissiles,
            missile_type,
            money;

    pp = getpl (s);             /* get planet id */
    assert_player (pp);         /* verify existence + owner */
    skipwhite (s);
    nmissiles = atoi (s);       /* see how many missiles to build  */
    assert_negative (nmissiles);
    if (nmissiles) {            /* skip the no. chars */
        skipnum (s);            /* go to the missile type */
        skipwhite (s);
    }
    else
        nmissiles = 1;          /* if none given, assume 1 */
    if (*s < 'a')
        *s += ('a' - 'A');      /* transform type to l.c. */
    if ((*s < 'a') || (*s > 'a' + MAXSHIPS - 1)) {
        say ("The type of missile is not clear, sir!!");
        return;
    }
    missile_type = *s - 'a';
    if (pp -> inventar.know < missile_type) {
        say ("The knowledge there is insufficient, sir.");
        return;
    }
    s++;
    assert_end (s);
    factor = 1;
    j = missile_type;
    while (j-- > 0)
        factor *= 2;    /* calculate money for X  type missile. */
    j = factor * NCREW ;
    if (pp -> inventar.popul[FIGT] < j ) {
        say ("But sir, no fighters there to carry out this work!!");
        return;
    }
    money = factor * nmissiles * MISSILE_COST;
    assert_money (money);       /* see if he owns that much */
    teller[player] -= money;    /* take player's money */
    pp -> missile[missile_type] += nmissiles;
    say ("The missiles are ready. Prepare detection, sir!!");
}
SHAR_EOF
if test 1874 -ne "`wc -c set_missle.c`"
then
echo shar: error transmitting set_missle.c '(should have been 1874 characters)'
fi
echo shar: extracting softclock.c '(17034 characters)'
cat << \SHAR_EOF > softclock.c
/*
 * %W% (mrdch&amnnon) %G%
 */

# include "header"

# define SOULS   pp->inventar.popul     /* shorter */
# define M_SOULS pp->to_take.popul      /* shorter */

int     month = 0;
int     work_p[MAXPL][CLASES];  /* how many EFFECIVE people are */
extern int  no_new_year;

/*
 * This routine is called whenever a command finishes
 * execution. If time past is longer then defined, or
 * if explicitly asked for, a new year arrives.
 */
softclock (force)
int     force;
{
    static  time_t todays_time = 0;
    static  time_t last_year;

    if (no_new_year)
/* wizard asked that TIME will freeze */
        return;

/* This is the first time we call soft clock. */
    if (todays_time == 0) {
        (void) time (&todays_time);
        last_year = todays_time;
        return;
    }

    (void) time (&todays_time);

    if ( force == 2 ) {         /* We took a break! Restore time */
        last_year =  todays_time - (time_t) ((float) month * (float) YEARLENGTH/100.);
        return;
    }
    if (last_year + YEARLENGTH <= todays_time || force) {
        last_year = todays_time;
        newyear ();
    }
    month = (todays_time - last_year) * 100 / YEARLENGTH;
}

/*
 * A NEW YEAR is defined as one of the following situations :
 * 1- The allocated time had passed.
 * 2- When the TWO players have agreed to it.
 */

int     ncitizens[3],
        npopul[3];
static int  plan_own[MAXPL];

newyear () {
    int     i,
            j;
    planet * pp;

    dowrite_enemy ("Happy new year, dear sir.", 0);
    dowrite_enemy ("Happy new year, dear sir.", 1);

/* only in the FIRST year */
    if (year == 0)
        for (i = 0; i < MAXPL; i++) {
            pp = &pl[i];
            plan_own[i] = pl[i].whos;
            for (j = 0; j < CLASES; j++)
                work_p[i][j] = SOULS[j];
        }

    year++;                     /* this is a NEW year */

/* update EFFECTIVE no of people if planet changed hands */
    for (i = 0; i < MAXPL; i++) {
        pp = &pl[i];
        for (j = 0; j < CLASES; j++) {
            if (plan_own[i] != pl[i].whos)
                work_p[i][j] = 0;
/* update EFFECTIVE no of people if less then before. */
        if (SOULS[j] < work_p[i][j])
            work_p[i][j] = SOULS[j];
        }
    }
    for (i = 0; i < MAXPL; i++) {
        pp = &pl[i];
    /* see if any active alm was left */
        if (pl[i].alms)
            check_alm (i, pp);
    /* raise the popul. of citizens */
        if (work_p[i][CITI])
            inc_popul (i, pp);
    /* see if any knwledge gained */
        if (work_p[i][SCIE])
            check_know (i);
    /* see if mining was done */
        if (work_p[i][MINE] || work_p[i][SLAV])
            check_mining (i);
    /* see if building is in progress */
        if (pl[i].to_build[NSHIPS])
            check_build (i);
    /* see to it that detection devices loose effectiveness */
        if (pl[i].detect)
            reduce_detect (pp);
    /* see if it is espionaged. */
        check_esp (pp);
    }
    for (i = 0; i < MAXPL; i++)
        plan_own[i] = pl[i].whos;
    for (j = 0; j < 2; j++) {
        npopul[j] = count_popul (j);
        ncitizens[j] = count_citi (j);
        teller[j] += ncitizens[j];
        if (trade[j])
                do_trade (j);           /* add the money for trade */
        check_food (j);         /* see if enough food was given */
        clr_svqt (j);           /* clear all two players flags */
    }
/* update the population to the new situation */
    for (i = 0; i < MAXPL; i++) {
        pp = &pl[i];
        for (j = 0; j < CLASES; j++)
            work_p[i][j] = SOULS[j];
    }
}

/* count the effective citizenes */
count_citi (j) {
    int     i,
            nciti = 0;

    for (i = 0; i < MAXPL; i++)
        if (pl[i].whos == j)
            nciti += work_p[i][CITI];
    return (nciti);
}

/* clear save and quit flags */
clr_svqt (j) {
    wants_quit[j] = 0;
    wants_save[j] = 0;
    wants_restor[j] = 0;
    wants_newy[j] = 0;
}

/* increment the citizens population */
inc_popul (i, pp)
planet * pp;
{
    double  d;

    d = (double) work_p[i][CITI];
    d *= (PERC_POPUL) / 100.;
    SOULS[CITI] += (int) d;
}

/*
 * Chek for alm presence. If found and the the flag for this
 * planet is 0- raise it to 1 to indicate that it was just
 * now installed. If it is 1- destroy whatever is found there.
 * If there is none- put 0 in the corresponding flag.
 */
check_alm (i, pp)
planet * pp;
{
    static int  alm_flg[MAXPL]; /* flags to indicate alm presence */
    int     j;

    if (year == 1)
        for (j = 0; j < MAXPL; j++)
            alm_flg[j] = 0;
    if (pl[i].alms) {
        if (!alm_flg[i])
            alm_flg[i]++;
        else {
            for (j = 0; j < CLASES; j++) {
                SOULS[j] = 0;
                M_SOULS[j] = 0;
                work_p[i][j] = 0;
            }
        }
    }
    else
        alm_flg[i] = 0;
}

/* reduce the effectiveness of detection devices */
reduce_detect (pp)
planet * pp;
{
    pp -> detect = pp -> detect * (100 - REDUCE_RATE) / 100;
}

/* update the mining materials in the given planet */
check_mining (i)
int     i;
{
    static int  some_metal[MAXPL];/* accumulates metal */
    int     nminers;

    nminers = work_p[i][MINE] + work_p[i][SLAV];
    while (nminers >= MINING_FACTOR) {
        pl[i].inventar.metals++;
        nminers -= MINING_FACTOR;
    }
    if (nminers)
        some_metal[i] += nminers;
    if (some_metal[i] >= MINING_FACTOR) {
        some_metal[i] -= MINING_FACTOR;
        pl[i].inventar.metals++;
    }
}

/* see if building is in progress */
check_build (i)
int     i;
{
    char    s[450],
            s1[450];
    int     factor = 1,
            nbuild = 0,
            j = 0;
    int     shipcost;
    int     level = pl[i].to_build[LEVEL];
    int     nbuilders = work_p[i][BUIL];

    s[0] = s1[0] = '\0' ;
    while (level > j++)
        factor *= 2;
    shipcost = factor * SHIP_COST;

 /* BEFORE starting to build- is there still knowledge ?? */
    if (pl[i].inventar.know < level) {
        (void) sprintf (s, "The knowledge at %s is not enough, sir.", pl[i].pid);
        dowrite_enemy (s, pl[i].whos);
        return;
    }
    while (pl[i].to_build[NSHIPS]) {
        if (!(pl[i].inventar.metals >= factor)) {
            (void) sprintf (s, "The metal in %s was not enough to complete the work, sir.", pl[i].pid);
            break;
        }
        if (!(nbuilders >= shipcost)) {
            (void) sprintf (s, "There were not enough builders in %s to complete the work, sir.", pl[i].pid);
            break;
        }
        if (!(pl[i].to_build[BUILD_MONEY] >= shipcost)) {
            (void) sprintf (s, "We run out of building ships money in %s, sir.", pl[i].pid);
            break;
        }
        pl[i].inventar.metals -= factor;
        nbuilders -= shipcost;
        pl[i].to_build[BUILD_MONEY] -= shipcost;
        pl[i].to_build[NSHIPS]--;
        pl[i].ships[level]++;
        nbuild++;
    }
    if (nbuild) {
        (void) sprintf (s1, "At %s %d %c-type ships were build !!!", pl[i].pid, nbuild, 'A' + level);
        dowrite_enemy (s1, pl[i].whos);
    }
    if (*s)
        dowrite_enemy (s, pl[i].whos);
}

/* see if any knowledge gained */
check_know (i)
int     i;
{
    char    s[100];
    int     factor = 1,
            nscience = 0,
            j = 0;
    int     know_cost;
    int     level = pl[i].inventar.know + 1;
    static int  know_points[MAXPL];


    if (pl[i].inventar.know == MAXSHIPS -1 ) {
        (void) sprintf (s, "Sir!!! Your scintists at %s are unable to advance further." , pl[i].pid) ;
        dowrite_enemy (s, pl[i].whos) ;
        return;
    }
    if (plan_own[i] != pl[i].whos) {
        know_points[i] = 0;
    }
    while (level > ++j)
        factor *= 2;
    know_cost = factor * KNOW_FACTOR;
    nscience = work_p[i][SCIE];
    know_points[i] += nscience;
    if (know_points[i] >= know_cost) {
        pl[i].inventar.know++;
        (void) sprintf (s, "Sir!!! Your scientists at %s have gained %c-level knowledge!!!", pl[i].pid, level + 'A');
        dowrite_enemy (s, pl[i].whos);
        know_points[i] = 0;
    }
}

do_trade (j)                    /* add the results of last year trade */
int     j;
{
    int     i,
            temp;
    char    s[100];
    double      perc ;

    for ( i = 0 , temp = 0 ; i < MAXPL ; i++)
        if (pl[i].whos == j)
            temp++ ;    /* count the planets he controls */
    if ( (perc = (temp - 33) / 2) < 0 )
        perc = 0 ;
    perc += PERC_TRADE;
    perc += rand () % 5;
    temp = (int) ((double) trade[j] * (100.+  perc) / 100.);
    (void) sprintf (s, "We had %d trade profit last year, sir.",
                temp - trade[j]);
    dowrite_enemy (s, j);
    teller[j] += temp;
    trade[j] = 0;
}

/* check if enough food was provided */
check_food (j)
int     j;
{
    char    s[100];
    int     i,
            k,
            kind;
    planet * pp;

    npopul[j] -= ncitizens[j];
    k = food[j] * FEED_RATIO;   /* check how much was given */

    if (k >= npopul[j]) {
        food[j] -= npopul[j] / FEED_RATIO;
        k -= npopul[j];
        if (k < npopul[j]) {    /* next time they might die */
            (void) sprintf (s, "Sir, we are in danger that %d of our people will starve to death!!!", npopul[j] - k);
            dowrite_enemy (s, j);
        }
        return;
    }
    food[j] = 0;
    npopul[j] -= k;             /* that many we'll have to kill */
    (void) sprintf (s, "%d people died from lack of food, sir.", npopul[j]);
    dowrite_enemy (s, j);
    for (kind = SLAV; kind > CITI; kind--) {
        for (i = MAXPL - 1; i >= 0; --i) {
            pp = &pl[i];
            if (pp -> whos == j) {
                if (npopul[j] - SOULS[kind] > 0) {
                    npopul[j] -= SOULS[kind];
                    SOULS[kind] = 0;
                }
                else {
                    SOULS[kind] -= npopul[j];
                    npopul[j] = 0;
                }
                if (npopul[j] - M_SOULS[kind] > 0) {
                    npopul[j] -= M_SOULS[kind];
                    M_SOULS[kind] = 0;
                }
                else {
                    SOULS[kind] -= npopul[j];
                    npopul[j] = 0;
                }
            }
        }
    }
    if (npopul[j]) {            /* still to kill */
        kind = FIGT;
        for (i = MAXPL; i >= 0; --i) {
            pp = &pl[i];
            if (pp -> whos == j) {
                if (npopul[j] - SOULS[kind] > 0) {
                    npopul[j] -= SOULS[kind];
                    SOULS[kind] = 0;
                }
                else {
                    SOULS[kind] -= npopul[j];
                    npopul[j] = 0;
                }
                if (npopul[j] - M_SOULS[kind] > 0) {
                    npopul[j] -= M_SOULS[kind];
                    M_SOULS[kind] = 0;
                }
                else {
                    SOULS[kind] -= npopul[j];
                    npopul[j] = 0;
                }
            }
        }
    }
}

int     last_esp_cost;

check_esp (pp)
planet * pp;
{
    int     etype;

    if (pp -> whos == 2)        /* uninhabited planet! */
        return;

/* check all types of espionage */
    for (etype = 0; etype < ESPTYP; etype++)
        do_check_esp (pp, etype);
}

do_check_esp (pp, etype)
planet * pp;
{
    int     cpl = pp -> whos;
    int     tl1;
    int     elvl;

    tl1 = pp -> espion[!cpl][etype][0];

/* if no money was invested in this kind by the enemy */
    if (tl1 == 0)
        return;

/* if the investment wasn't succesfull, do not check further */
    if (!gave_info (pp, etype, tl1))
        return;

/* for each consecutive level, check if information was obtained */
    for (elvl = 1; elvl < ESPSIZ; elvl++) {
        if (!counter_esp (pp, etype, elvl - 1, cpl))
            return;

        if (!counter_esp (pp, etype, elvl, !cpl))
            return;
    }
}

counter_esp (pp, etype, lvl, ply)
planet * pp;
{
    char    s[100];
/* that's how much was invested in this counter espionage */
    int     tl = pp -> espion[ply][etype][lvl];

/* no money, no information */
    if (tl == 0)
        return (0);

/* reduce the money required by half */
    last_esp_cost /= 2;

/* not enough  money, no information */
    if (tl < last_esp_cost)
        return (0);

/* in counter espionage, only USED money are lost */
    pp -> espion[ply][etype][lvl] -= last_esp_cost;

    (void) sprintf (s,
            "Level %d information at planet's %s obtained by the enemy.\r\n"
            ,lvl, inftypes[etype]);

/* finally give the information */
    spy_msg (s, ply, pp, lvl);
    return (1);
}

/*
 * the main espionage routine, it only check for first
 * level espionage.
 */
gave_info (pp, etype, tlrs)
planet * pp;
{
    int     secur = pp -> secur;

/* the sum invested */
    last_esp_cost = tlrs;
/* the black_out factor, if present */
    last_esp_cost -= pp -> secur;
/* ALL the money is lost */
    pp -> espion[!pp -> whos][etype][0] = 0;
/* reduce black out */
    secur -= tlrs;
/* add the SPECIFIC cost */
    secur += espcost[etype];
/*
 * Each planet has an MIN_ESP initial blackout
 * without investing any money in blackout!
 */

    if (secur < 0) {
/*
 * We have to give him the info since the
 * blackout is less then the money invested in
 * espionage.
 */
        pp -> secur = 0;
        give_info (pp, etype);
        return (1);             /* info given */
    }
    pp -> secur -= tlrs;
    if (pp -> secur < 0)
        pp -> secur = 0;
    pp -> espion[!pp -> whos][etype][0] = 0;
    return (0);
}

/*
 * when deserving it, give the information required.
 */
give_info (pp, esptype)
planet * pp;
{
    char   *ptos ();
    char   *do_esp_pop ();
    char   *do_esp_force ();
    char   *do_esp_missile ();
    char    s[100];

    switch (esptype) {
        case ESPKIND:
            (void) sprintf (s, "Category: %s\r\n", ptos (pp));
            break;
        case ESPPOP:
            (void) sprintf (s, "Popul: %s\r\n", do_esp_pop (pp));
            break;
        case ESPKNOW:
            (void) sprintf (s, "Knowledge level is %c\r\n", pp -> inventar.know + 'A');
            break;
        case ESPMTL:
            (void) sprintf (s, "Metal: %d\r\n", pp -> inventar.metals);
            break;
        case ESPSHIP:
            (void) sprintf (s, "Force: %s\r\n", do_esp_force (pp));
            break;
        case ESPALM:
            (void) sprintf (s, "ALM installed: %d\r\n", pp -> alms);
            break;
        case ESPMSL:
            (void) sprintf (s, "Missile: %s\r\n", do_esp_missile (pp));
            break;
    }
    spy_msg (s, !pp -> whos, pp, 0);
}

/* returns a string with the kind of planet information */
char   *
        ptos (pp)
        planet * pp;
{
    char   *rindex ();
    char   *x;
    static char s[100];

    (void) strcpy (s, "");

    if (SOULS[FIGT])
        (void) strcat (s, "military/");
    if (SOULS[CITI])
        (void) strcat (s, "agricultural/");
    if (SOULS[MINE])
        (void) strcat (s, "mining/");
    if (SOULS[BUIL])
        (void) strcat (s, "industrial/");
    if (SOULS[SCIE])
        (void) strcat (s, "scientific/");

    x = rindex (s, '/');
    if (x != 0)
        *x = '\0';

    if (strcmp (s, "") == 0)
        (void) strcpy (s, "none");

    return (s);
}

char   *people[] = {
    "fight", "citizen", "scien", "build",
    "miner", "slave", 0
};

/* returns a string with the population information */
char   *
        do_esp_pop (pp)
        planet * pp;
{
    char   *rindex ();
    char   *x;
    int     i,
            j;
    static char    s[100];
    static char    s1[100];

    (void) strcpy (s, "");

    for (i = 0; i < CLASES; i++) {
        j = pp -> inventar.popul[i];
        if (j) {
            (void) sprintf (s1, "%d %s/", j, people[i]);
            (void) strcat (s, s1);
        }
    }
    x = rindex (s, '/');
    if (x != 0)
        *x = '\0';

    if (strcmp (s, "") == 0)
        (void) strcpy (s, "no population");
    return (s);
}

/* returns a string with the force information */
char   *
        do_esp_force (pp)
        planet * pp;
{
    int     i,
            j;
    static char    s[100];
    static char    s1[100];

    (void) strcpy (s, "");

    for (i = 0; i < MAXSHIPS; i++) {
        j = pp -> ships[i];
        if (j) {
            (void) sprintf (s1, "%c-%d ", i + 'A', j);
            (void) strcat (s, s1);
        }
    }

    if (strcmp (s, "") == 0)
        (void) strcpy (s, "no forces");
    return (s);
}

/* returns a string with the missile information */
char   *
        do_esp_missile (pp)
        planet * pp;
{
    int     i,
            j;
    static char    s[100];
    static char    s1[100];

    (void) strcpy (s, "");

    for (i = 0; i < MAXSHIPS; i++) {
        j = pp -> missile[i];
        if (j) {
            (void) sprintf (s1, "%c-%d ", i + 'A', j);
            (void) strcat (s, s1);
        }
    }

    if (strcmp (s, "") == 0)
        (void) strcpy (s, "no missiles");
    return (s);
}
SHAR_EOF
if test 17034 -ne "`wc -c softclock.c`"
then
echo shar: error transmitting softclock.c '(should have been 17034 characters)'
fi
echo shar: extracting table.h '(953 characters)'
cat << \SHAR_EOF > table.h
/*
 * %W% (mrdch&amnnon) %G%
 */

/* Table seed : 1858 */

char    crypt_tab[] = {
    83,
    144,
    137,
    142,
    175,
    188,
    69,
    154,
    203,
    168,
    193,
    102,
    167,
    84,
    253,
    242,
    67,
    192,
    249,
    62,
    159,
    236,
    181,
    74,
    187,
    216,
    49,
    22,
    151,
    132,
    109,
    162,
    51,
    240,
    105,
    238,
    143,
    28,
    37,
    250,
    171,
    8,
    161,
    198,
    135,
    180,
    221,
    82,
    35,
    32,
    217,
    158,
    127,
    76,
    149,
    170,
    155,
    56,
    17,
    118,
    119,
    228,
    77,
    2,
    19,
    80,
    73,
    78,
    111,
    124,
    5,
    90,
    139,
    104,
    129,
    38,
    103,
    20,
    189,
    178,
    3,
    128,
    185,
    254,
    95,
    172,
    117,
    10,
    123,
    152,
    241,
    214,
    87,
    68,
    45,
    98,
    243,
    176,
    41,
    174,
    -1
};
SHAR_EOF
if test 953 -ne "`wc -c table.h`"
then
echo shar: error transmitting table.h '(should have been 953 characters)'
fi
echo shar: extracting take_from.c '(1781 characters)'
cat << \SHAR_EOF > take_from.c
/*
 * %W% (mrdch&amnnon) %G%
 */

# include "header"

takefrom (s)
char   *s;
{
    planet * pp;
    int     i = 0,
            spl;
    char    cc;

    pp = getpl (s);
    assert_player (pp);
    skipwhite (s);
    if (*s == 'k') {            /* in case of knowledge, no parameter
                                   needed */
        if (pp -> inventar.know) {/* only if above A type */
            pp -> to_take.know = pp -> inventar.know;
            pp -> inventar.know = 0;
        /* DONT leave the knowledge there */
            say ("%c-type knowledge ready to be moved, sir !!!",
                    'A' + pp -> to_take.know);
            return;
        }
        say ("Planet blessed with little knowledge, sir.");
        return;
    }
    i = atoi (s);               /* in any other case- numeric parameter
                                   needed */
    assert_number (i);
    skipword (s);
    cc = *s++;
    assert_end (s);
 /*
  * for each of the following:
  * first check if enough available to be taken.
  * if not- print error massege and exit ;
  * if so- make the transportation to the wharehouse
  */
    if (cc == 't') {
        if (pp -> inventar.metals < i) {
            say ("But you don't have that much metal there !!");
            return;
        }
        pp -> inventar.metals -= i;
        pp -> to_take.metals += i;
        say ("%d A-type material ready to move, sir !!", i);
        return;
    }
    spl = which_class (cc);
    assert_occup (spl);
    if (pp -> inventar.popul[spl] < i) {
        say ("But sir, you don't have that much %s there !!", ocup_name[spl]);
        return;
    }
    pp -> inventar.popul[spl] -= i;
    pp -> to_take.popul[spl] += i;
    say ("%d %s are ready to move, sir !!", i, ocup_name[spl]);
    return;
}
SHAR_EOF
if test 1781 -ne "`wc -c take_from.c`"
then
echo shar: error transmitting take_from.c '(should have been 1781 characters)'
fi
echo shar: extracting term2init.c '(6335 characters)'
cat << \SHAR_EOF > term2init.c
/*
 * %W% (mrdch&amnnon) %G%
 */

# include "header"
# include <utmp.h>
# include <sys/stat.h>
# include <signal.h>

# define PATHSIZ        150
# define MAXDUPS        100
# define TIMEOUT        120

# define fd1 chand[0]
# define fd2 chand[1]

int     nulluser;
char    ply0[100],
       *ply1;

term2init ()
{
    char   *t1[PATHSIZ],
           *t2;
    char   *getuser ();
    char   *getlogin ();

    ply1 = getlogin ();
    if (ply1 == 0) {
        fprintf (stderr, "Don't know who you are.\n");
        exit (1);
    }

    for (;;) {
        printf ("Who would you like to play with ? ");
        gets (ply0);
        if (*ply0 != '\0')
            break;
    }
    iswiz[0] = iswizard (ply0);
    iswiz[1] = iswizard (ply1);

    if (strcmp (ply0, "-null") == 0)
                /* enter only if change_player command is to be
                  reserved for wizards only. */
    /*
     if(!iswiz[1])
     {
     fprintf(stderr, "You are not a wizard.\n") ;
     exit(1) ;
     } else
     */
        nulluser = 1;
    if (nulluser)
        (void) strcpy (t1, "/dev/null");
    else
        (void) sprintf (t1, "/dev/%s", getuser (ply0));
    t2 = "/dev/tty";

    if (strcmp (t1, t2) == 0) {
        fprintf (stderr, "You can't expect to play with yourself!\n");
        exit (1);
    }

    page (t1, ply0, ply1);
    printf ("Response....\n\r");
    do2term (t1, t2);
    geterm (t1);
}

geterm (t)
char   *t;
{
    char   *s,
            c,
            termbuf[100],
            pscmd[100];
    FILE * psfp, *popen ();

    if (strcmp (t, "/dev/null") == 0) {
        char *getenv () ;
        fillterm (getenv ("TERM"), &ttycs[0]);
        return;
    }
    if (!strcmp (t, "/dev/console"))
        s = "co";
    else                        /* /dev/ttyxx */
        if (strncmp (t, "/dev/tty", 8) || strlen (t) != 10) {
            fprintf (stderr, "unrecognized tty name %s\n", t);
            exit (1);
        }
        else
            s = &t[8];

    (void) sprintf (pscmd, "ps wwet%s", s);
    psfp = popen (pscmd, "r");
    if (psfp == NULL) {
        fprintf (stderr, "can't execute %s\n", pscmd);
        (void) kill (getpid (), 9);
    }
    if (strfind (psfp, "okgalaxy", 0)) {
        fprintf (stderr, "can't find okgalaxy in %s\n", pscmd);
        (void) kill (getpid (), 9);
    }
    if (strfind (psfp, " TERM=", 1)) {
        fprintf (stderr, "can't find TERM type\n");
        (void) kill (getpid (), 9);
    }
    s = termbuf;
    while ((c = getc (psfp)) != ' ' && c != '\n')
        if (c == EOF) {
            fprintf (stderr, "ps output format error\n");
            (void) kill (getpid (), 9);
        }
        else
            *s++ = c;

    *s = '\0';
    while (getc (psfp) != EOF);
    (void) fclose (psfp);
    fillterm (termbuf, &ttycs[0]);
}

strfind (Xfp, s, Xflag)
FILE * Xfp;
char   *s;
{
    char   *p,
           *e,
            c;

    p = s;
    for (;;) {
        if ((c = getc (Xfp)) == EOF || c == '\n' && Xflag)
            return - 1;
        if (c == *p) {
            if (*++p == '\0')
                return 0;
        }
        else
            if (p != s) {

                for (e = s; e < p; e++)
                    if (c == s[p - e] && !strncmp (e, s, p - e))
                        break;
                if (e < p || c == *s)
                    p = &s[p - e + 1];
                else
                    p = s;
            }
    }
}


struct utmp dups[MAXDUPS];
int     lastdup = 0;

char   *
        getuser (s)
char   *s;
{
    static int  utmpf = -1;
    static struct utmp  utmp;
    char    p[100];
    int     i;
    lastdup = 0;

    if (utmpf == -1)
        utmpf = open ("/etc/utmp", 0);
    else
        (void) lseek (utmpf, 0L, 0);
    if (utmpf == -1)
        return (0);

    while (read (utmpf, (char *) & utmp, sizeof utmp) == sizeof utmp)
        if (strncmp (utmp.ut_name, s, 8) == 0)
            dups[lastdup++] = utmp;

    if (lastdup == 1)
        return (dups[0].ut_line);

    if (lastdup == 0) {
        writes (2, "not logged in.\n\r");
        exit (1);
    }

    printf ("%s logged in more then once.\n", s);
    for (i = 0; i < lastdup; i++) {
        printf ("%s on %s ? ", s, dups[i].ut_line);
        gets (p);
        if (p[0] == 'y')
            return (dups[i].ut_line);
        if (p[0] == 'q')
            return (0);
    }

    writes (2, "no more ttys\n\r");
    exit (1);

    /* NOTREACHED */
}

int     xpipe[2];
int     chand[MAXCHAN];


do2term (t1, t2)
char   *t1,
       *t2;
{
    fd1 = open (t1, 2);
    fd2 = open (t2, 2);
    if (fd1 == -1)
        pout (t1);
    if (fd2 == -1)
        pout (t2);

    if (pipe (xpipe) == -1)
        pout ("pipe");

    (void) dochan (fd1);
    (void) dochan (fd2);
}

pout (s)
char   *s;
{
    perror (s);
    exit (1);
}

dochan (fd)
int     fd;
{
    static  lastchan = 0;
    char    s[50];

    (void) sprintf (s, "%d", lastchan++);
    switch (fork ()) {
        case -1:
            pout ("fork");
        default:                /* parent */
            return (lastchan - 1);

        case 0:
            if (dup2 (fd, 0) == -1)
                pout ("dup2 1");

            if (dup2 (xpipe[1], 1) == -1)
                pout ("dup2 2");

            execl (LOCAL, "local", s, 0);
            pout ("local");
    }
 /* NOTREACHED */
}

readc (x)
chan * x;
{
    return (read (xpipe[0], (char *) x, sizeof (*x)));
}

page (s, nm, iam)
char   *nm;
char   *s;
char   *iam;
{
    int     onalrm ();
    if (nulluser)
        return;

    if (!okterm (s)) {
        fprintf (stderr,
                "%s's terminal,%s, mode is bad for galaxy\n",
                nm, s);
        exit (1);
    }
    if (access (s, 2) == -1) {
        fprintf (stderr, "Can't write %s.\n", nm);
        exit (1);
    }

    if (vfork () == 0) {
        execl (PAGER, "pager", s,
                iam, 0);
        exit (1);
    }

    writes (1, "Please wait.....\n");
    (void) alarm (TIMEOUT);

    signal (SIGALRM, onalrm);
    printf ("Sleeping on %s\n", s);
    while (okterm (s));

    signal (SIGALRM, SIG_IGN);
    return;
}

okterm (s)
char   *s;
{
    struct stat stbuf;

    (void) stat (s, &stbuf);
    if (stbuf.st_mode & S_IREAD >> 3 || stbuf.st_mode & S_IREAD >> 6)
        return (0);
    else
        return (1);
}

onalrm () {
    writes (1, "Timeout.\r\n");
    exit (1);
}
SHAR_EOF
if test 6335 -ne "`wc -c term2init.c`"
then
echo shar: error transmitting term2init.c '(should have been 6335 characters)'
fi
echo shar: extracting terminal.c '(5195 characters)'
cat << \SHAR_EOF > terminal.c
/*
 * %W% (mrdch&amnnon) %G%
 */

# include "header"

/*
 * This file contains all termcap-using functions.  The game uses
 * these function in order to move the cursor, enter standout mode,
 * etc.
 */

FILE * tty;

struct terminal ttycs[2];
struct terminal *ttyc;

char    capbuf[1024];
char   *xxxx = capbuf;
char  **cbuf = &xxxx;

/*
 * This function tries to fill the buffer with the termcap
 * entry of the player's terminal.
 */

fillterm (s, t)
char   *s;
struct terminal *t;
{
    char   *SO,
           *SE,
           *CM,
           *CE,
           *CL,
           *FL,
           *FB,
           *IS,
           *KS,
           *TE,
           *KE,
           *TI;
    int     SG;
    char   *buf;
    char   *malloc ();
    char   *tgetstr ();

    buf = malloc (1024);
    if (buf == 0) {
        writes (2, "OUT OF MEMORY IN FILLTERM.\r\n");
        exit (126);
    }
    t -> t_name = s;
    if (tgetent (buf, s) != 1) {
        fprintf (stderr, "Sorry: Cannot get termcap entry for %s\n",
                s);
        exit (-1);
    }

    SO = tgetstr ("so", cbuf);
    SE = tgetstr ("se", cbuf);
    CM = tgetstr ("cm", cbuf);
    CE = tgetstr ("ce", cbuf);
    CL = tgetstr ("cl", cbuf);
    FL = tgetstr ("fl", cbuf);
    FB = tgetstr ("fb", cbuf);
    IS = tgetstr ("is", cbuf);
    KS = tgetstr ("ks", cbuf);
    TE = tgetstr ("te", cbuf);
    KE = tgetstr ("ke", cbuf);
    TI = tgetstr ("ti", cbuf);

    SG = tgetnum ("sg");

    if (SG == -1)
        SG = 0;

    if (!CM || !SO || !SE || !CL) {
        fprintf (stderr, "The %s terminal lacks basic capabilities. Sorry.\n", s) ;
        exit(1) ;
    }

    t -> t_so = SO;
    t -> t_se = SE;
    t -> t_cm = CM;
    t -> t_ce = CE;
    t -> t_cl = CL;
    t -> t_fl = FL;
    t -> t_fb = FB;
    t -> t_sg = SG;
    t -> t_is = IS;
    t -> t_ks = KS;
    t -> t_te = TE;
    t -> t_ke = KE;
    t -> t_ti = TI;

    free(buf);
}

/* put a single char to a given terminal */
int     xputchar (c)
int     c;
{
    putc (c, tty);
}

/* The initialization for the terminal */
cap_set (t)
struct terminal *t;
{
    tputs (t -> t_is, 1, xputchar);
    tputs (t -> t_ks, 1, xputchar);
    tputs (t -> t_ke, 1, xputchar);
}

/* put the cursor in a x,y position on the screen */
pos (x, y)
int     x,
        y;
{
/*
 * We use only CM.   No CM means no galaxy....
 */
    char   *s;
    char   *tgoto ();

    s = tgoto (ttyc -> t_cm, y, x);
    tputs (s, 1, xputchar);
}

/* output a string, encountering it with end of standout */
se (x, y, s)
char   *s;
{
    pos (x, y);
    tputs (ttyc -> t_se, 1, xputchar);
    print (s);
    tputs (ttyc -> t_se, 1, xputchar);
}

/* output a string, in the standout mode */
so (x, y, s)
char   *s;
{
    pos (x, y);
    tputs (ttyc -> t_so, 1, xputchar);
    print (s);
    tputs (ttyc -> t_se, 1, xputchar);
}

/* clear the whole screen */
clear () {
    pos (1, 1);
    tputs (ttyc -> t_cl, 1, xputchar);
}

/*
 * If the termcap entry was suitably modified, and the terminal
 * has more than one display page, this game benefits greatly
 * from such cases.
 * In short, `fl' entry contains the string that will cause the
 * terminal to "flip" forward , and `fb' entry holds the string
 * that will flip it backward.
 * Whenever any of this are missing, the "flip" is simulated
 * simply by clearing the screen, and writing the relevant
 * information on it.
 */

flip () {
    if (ttyc -> t_fl != 0) {
        if (ttyc -> t_curpage == 0) {
            tputs (ttyc -> t_fl, 1, xputchar);
            ttyc -> t_curpage = 1;
        }
        else {
            tputs (ttyc -> t_fb, 1, xputchar);
            ttyc -> t_curpage = 0;
        }
        return;
    }
    else {
        if (ttyc -> t_curpage == 0)
            ttyc -> t_curpage = 1;
        else {
            init_dis ();
            ttyc -> t_curpage = 0;
        }
    }
}

/* clear to end of line from current cursor position */
ceol () {
    tputs (ttyc -> t_ce, 1, xputchar);
}

/* clear to end of line from given cursor position */
cleol (x, y) {
    pos (x, y);
    tputs (ttyc -> t_ce, 1, xputchar);
}

writes (fd, s)
char   *s;
{
    (void) write (fd, s, strlen (s));
}


/*
 * this function brings the cursor to the current planet.
 * It will restor the video attribute to NORMAL .
 * Care must be taken to consider the effect of video attribute
 * that takes a place on the screen (tvi 925...) and also
 * that if not ended properly, it might extend to the end-of-line
 * or to the end-of-page.
 */

curse_map (pp)
planet * pp;
{
    int     x = pp -> coord[0];
    int     y = pp -> coord[1] + 1;
    draw_map (pp);
    pos (x, y);
}

draw_map (pp)
planet * pp;
{
    char    s[10];
    int     x = pp -> coord[0];
    int     y = pp -> coord[1] + 1;
    s[0] = pp -> d_symbol[player];
    s[1] = 0;

    se (x, y - ttyc -> t_sg, s);
}

/*
 * In this case we LEAVE the map, and go with the cursor to the
 * Command line. Thus we leave a mark at the current planet
 * so reference to it will be easy.
 */

curse_com (pp)
planet * pp;
{
    char    s[10];
    int     x = pp -> coord[0];
    int     y = pp -> coord[1] + 1;

    s[0] = pp -> d_symbol[player];
    s[1] = 0;
    so (x, y - ttyc -> t_sg, s);
}
SHAR_EOF
if test 5195 -ne "`wc -c terminal.c`"
then
echo shar: error transmitting terminal.c '(should have been 5195 characters)'
fi
echo shar: extracting trade.c '(503 characters)'
cat << \SHAR_EOF > trade.c
/*
 * %W% (mrdch&amnnon) %G%
 */

# include "header"

trading (s)
char   *s;
{
    int     i;

    i = atoi (s);               /* take the amount specified */
    assert_money (i);           /* see if legal and available */
    skipword (s);               /* skip over it */
    assert_end (s);             /* see if it ends well */
    say ("I pray for a good trading year, my lord.");
    teller[player] -= i;        /* take his money */
    trade[player] += i;         /* and invest it in trade */
}
SHAR_EOF
if test 503 -ne "`wc -c trade.c`"
then
echo shar: error transmitting trade.c '(should have been 503 characters)'
fi
echo shar: extracting typedefs.h '(3194 characters)'
cat << \SHAR_EOF > typedefs.h
/*
 * %W% (mrdch&amnnon) %G%
 */

/*
 * this include file describes the differnet types used
 * by the game.
 */
typedef struct _movable movable;
typedef struct _info    info;
typedef struct _planet  planet;
typedef struct _chan    chan;

struct _info {
    int     owner;              /* who owns that massege */
    int     nmsg;               /* the current massege no. */
    char    msg[MSGSIZ];        /* max chars in one massesge */
            info * next;        /* and here comes another one.. */
};

struct _movable {               /* what can be taken planet */
    int     popul[CLASES];      /* population            */
    int     metals;             /* how much metal was digged */
    int     know;               /* knowledge level on    */
};


struct _planet {                /* describe a planet */
    char    symbol;             /* the planet original symbol */
    char    d_symbol[2];        /* the planet displayed symbol */
    char    pid[4];             /* planet id */
    int     coord[2];           /* planet's cooridinates */
            planet * gate[10];  /* where can we go from it? */
    int     whos;               /* who owns it */
            movable inventar;   /* what is actually there */
            movable to_take;    /* what ordered to be moved */
    int     secur;              /* security - Black-Out */
    int     alms;               /* how many alm's were left */
    int     paint;              /* how much money for paint */
    int     detect;             /* how much money to detect */
    int     to_build[3];        /* money level & no. to build */
            info * reports;     /* reportes gathered */
    int     ships[MAXSHIPS];    /* no. of ships on planet */
    int     missile[MAXSHIPS];  /* how many missiles are there */
    int     espion[2][ESPTYP][ESPSIZ];/* espionage */
};

/*
 * the following structure is used to communicate between terminals.
 * Since galaxy can't read both terminals, it reads a pipe. The pipe
 * is written on by two local processes, one for each terminal.
 * Each write on the pipe, writes this structure.
 */
struct _chan {
    int     ichan;              /* terminal number */
    char    c;                  /* character       */
};

struct terminal {               /* terminal information */
    char   *t_name;             /* terminal name         */
    char   *t_ke;               /* end keypad transmit   */
    char   *t_so;               /* begin standout mode   */
    char   *t_se;               /* end standout mode     */
    char   *t_cm;               /* cursor motion         */
    char   *t_ce;               /* clear to end of line */
    char   *t_ks;               /* keypad transmit mode */
    char   *t_cl;               /* clear screen          */
    char   *t_fl;               /* move to page 0        */
    char   *t_fb;               /* move to page 1        */
    char   *t_is;               /* initialisation string */
    char   *t_te;               /* program begin use cm  */
    char   *t_ti;               /* program end using cm */
    int     t_sg;               /* # spaces left by so   */
    int     t_curpage;          /* current page          */
};
SHAR_EOF
if test 3194 -ne "`wc -c typedefs.h`"
then
echo shar: error transmitting typedefs.h '(should have been 3194 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.

dye@sx7000.UUCP (Ken R. Dye) (05/06/86)

------------------------------

	Our part 9 got truncated, could you re-transmit it, or mail it to me?

--Ken R. Dye

...ihnp4!umn-cs!ncs-med!sx7000!dye