[net.sources] OGRE source

wizard@pur-ee.UUCP (games) (01/20/85)

	New sources to OGRE. New things:

		New ogres 0,1,2,4,6,7,8
		New units mobile howitzer, light tanks, bunkers

------------------------------CUT HERE------------------------------------------

# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#        Makefile         README       attack.c          ext.h
#          init.c    initround.c         main.c          map.c
#          move.c         ogre.6         ogre.h      ogrecom.c
#           ogres     ogrestat.c      resolve.c      termcap.c
# 
#
echo 'x - Makefile'
sed 's/^X//' <<'________This_Is_The_END________' >>Makefile
XOBJ = init.o termcap.o map.o main.o move.o initround.o ogrecom.o ogrestat.o \
X	  attack.o resolve.o
XDOBJ = dinit.o dtermcap.o dmap.o dmain.o dmove.o dinitround.o dogrecom.o dogrestat.o \
X	  dattack.o dresolve.o
X
Xogre: $(OBJ)
X	cc -o ogre $(OBJ) -ltermcap
X
Xdebug: $(DOBJ)
X	cc -g -o ogre $(OBJ) -ltermcap
X
Xinit.o: init.c ogre.h
X	cc -c init.c
X
Xdinit.o: init.c ogre.h
X	cc -g -c init.c
X
Xmain.o: main.c ogre.h
X	cc -c main.c
X
Xdmain.o: main.c ogre.h
X	cc -g -c main.c
X
Xmove.o: move.c ogre.h
X	cc -c move.c
X
Xdmove.o: move.c ogre.h
X	cc -g -c move.c
X
Xdattack.o: attack.c ogre.h
X	cc -g -c attack.c
X
Xattack.o: attack.c ogre.h
X	cc -c attack.c
X
Xdresolve.o: resolve.c ogre.h
X	cc -g -c resolve.c
X
Xresolve.o: resolve.c ogre.h
X	cc -c resolve.c
X
Xdinitround.o: initround.c ogre.h
X	cc -g -c initround.c
X
Xinitround.o: initround.c ogre.h
X	cc -c initround.c
X
Xdtermcap.o: termcap.c
X	cc -g -c termcap.c
X
Xtermcap.o: termcap.c
X	cc -c termcap.c
X
Xdogrecom.o: ogrecom.c ogre.h
X	cc -g -c ogrecom.c
X
Xogrecom.o: ogrecom.c ogre.h
X	cc -c ogrecom.c
X
Xdogrestat.o: ogrestat.c ogre.h
X	cc -g -c ogrestat.c
X
Xogrestat.o: ogrestat.c ogre.h
X	cc -c ogrestat.c
X
Xmap.o: map.c ogre.h
X	cc -c map.c
X
Xdmap.o: map.c ogre.h
X	cc -g -c map.c
X
Xbackup:
X	tar cvf /arch/mike/ogre.tar *
X
Xrcs: init.c termcap.c map.c main.c move.c initround.c ogrecom.c ogrestat.c \
X	  attack.c resolve.c ogre.6
X	ci -l $?
X	touch rcs
________This_Is_The_END________
echo 'x - README'
sed 's/^X//' <<'________This_Is_The_END________' >>README
XAs promised, here is the hacked version of OGRE. I have put in the
Xfollowing enhancements:
X
X1) Stacking for armor is now correct (I closed the "SIT" hole).
X
XYou cannot move an armor unit onto any other unit if that would leave it
Xwith zero movement points. Nor can you issue the 's' or ' ' (SIT) commands
Xwhile the unit is stacked with another unit.
X
X2) Infantry stacking works as per the MetaGaming rules.
X
XAlmost. All infantry units are now 1s. You may have up to three ones on any
Xhex at one time. This stacking limit can be exceeded during movement, but
Xnot at the end of a units movement. Unlike the MetaGaming version of the
Xrules, stacked units are treated as multiple units, so a destroyed result
Xdoesn't destroy everything in the hex.
X
X3) A pass option now exists for movement, as well as for firing.
X
XAny time the game is waiting for you to issue a move command for a unit,
Xyou may type 'p' to pass on that unit. The unit is put back where it
Xstarted from, and given the number of movement points it had before.  With
Xthe corrected stacking rules, this is a necessity.
X
X4) You can pick up pieces after you've put them down during setup.
X
XWhile initially placing units, you can move on top of a unit and issue a
X'u' command. The unit is removed, and you get the armor or infantry
Xpoints back.
X
X5) You can get a mobile CP.
X
XAfter you place the CP, the game asks how many movement points the CP
Xshould have. Each movement point costs you one armor point. You can have at
Xmost 2 movement points - which makes the game far to easy.
X
X6) The ogre strategy has been improved.
X
XThe ogre is now much more relentless about mashing the CP. With the change
Xin the victory conditions from the MetaGaming version, this is reasonable.
X
X7) Case sensitivity has been stripped.
X
XThe system now ignores the case of input characters. With the undo during
Xsetup, this is reasonable.
X
X8) Clear screen added.
X
XUnlike the posted version, this one works any time the system is waiting
Xfor input.
X
X8) All bug fixes that I've seen posted.
X
XThat doesn't mean I got them all, of course.
X
XThe 'ogre 6' variant didn't get done. The screen display defeated me. Maybe
Xlater...
X
X	<mike
X
________This_Is_The_END________
echo 'x - attack.c'
sed 's/^X//' <<'________This_Is_The_END________' >>attack.c
X/*
X    This file contains routines to collect attack orders from the player,
X    and display his odds of success for each target.  It calls the
X    routines in "resolve.c" to determine the outcomes of the attacks.
X
X    Michael Caplinger, Rice University, March 1982.
X*/
X
X#include "ext.h"
X
Xstatic OGRE allocated;
X
X#define NOPASS      '\0'
X#define RESOLVE     'R'
X#define MISSILE     'M'
X#define LAUNCH      'L'
X#define MAIN        'B'
X#define SECONDARY   'S'
X#define AP          'A'
X#define TREAD       'T'
X
Xattack_def()
X{
X    char moreunits;
X    int  i;
X
X    moreunits = TRUE;
X    zero(&allocated, sizeof(allocated));
X    init_def_attack();
X
X    /*
X        The "fired" element of each unit description is here used as a
X        Boolean to keep track of who has fired.
X    */
X
X    while(moreunits) {
X
X        moreunits = FALSE;
X
X        for(i = 0; i < n_units; i++) {
X
X            if(unit[i].status == OK &&
X                !unit[i].fired &&
X                unit[i].attack > 0  &&
X                unit[i].range_to_ogre <= unit[i].range) {
X
X                    describe_action("Fire", i);
X
X                    if(get_target(i) == PASS) moreunits = TRUE;
X                    else unit[i].fired = TRUE;
X
X            }
X        }
X    }
X    ogre_resolve(&allocated);
X}
X
Xget_target(i)
Xint i;
X{
X
X    char    action, invalid;
X
X    movecur_unit(i);
X
X    do {
X
X        invalid = FALSE;
X        action = readchar();
X    
X        switch(action) {
X    
X            case PASS:
X                return(PASS);
X    
X            case MISSILE:
X                if(ogre.missiles > 0) {
X                    allocated.missiles += unit[i].attack;
X                    update_odds(action);
X                }
X                else {
X                    invalid = TRUE;
X                }
X                break;
X
X            case LAUNCH:
X                if(ogre.launchers > 0) {
X                    allocated.launchers += unit[i].attack;
X                    update_odds(action);
X                }
X                else {
X                    invalid = TRUE;
X                }
X                break;
X    
X            case MAIN:
X                if(ogre.main_bats > 0) {
X                    allocated.main_bats += unit[i].attack;
X                    update_odds(action);
X                }
X                else {
X                    invalid = TRUE;
X                }
X                break;
X    
X            case SECONDARY:
X                if(ogre.sec_bats > 0) {
X                    allocated.sec_bats += unit[i].attack;
X                    update_odds(action);
X                }
X                else {
X                    invalid = TRUE;
X                }
X                break;
X    
X            case AP:
X                if(ogre.ap > 0) {
X                    allocated.ap += unit[i].attack;
X                    update_odds(action);
X                }
X                else {
X                    invalid = TRUE;
X                }
X                break;
X    
X            case TREAD:
X                if(ogre.treads > 0) {
X                    allocated.treads += unit[i].attack;
X                    update_odds(action);
X                }
X                else {
X                    invalid = TRUE;
X                }
X                if(invalid) break;
X
X                /* TREAD has to be resolved immediately. */
X                ogre_resolve(&allocated);
X                zero(&allocated, sizeof(allocated));
X                break;
X
X            case RESOLVE:
X                ogre_resolve(&allocated);
X                zero(&allocated, sizeof(allocated));
X                return(PASS);
X                break;
X
X            default:
X                invalid = TRUE;
X                break;
X    
X        }
X
X    } while(invalid);
X
X    return(NOPASS);
X
X}
X
X
Xzero(area, size)
Xchar *area;
Xint  size;
X{
X
X    int i;
X
X    for(i = 0; i < size; i++) area[i] = '\0';
X
X}
X
Xupdate_odds(weapon)
Xchar weapon;
X{
X
X    char *odd_str();
X
X    switch(weapon) {
X
X        case MAIN:
X
X            display_xy(17, 64, "%d/%d (%s)", allocated.main_bats, DEF_MAIN,
X                odd_str(allocated.main_bats, DEF_MAIN));
X            break;
X
X        case SECONDARY:
X
X            display_xy(18, 64, "%d/%d (%s)", allocated.sec_bats, DEF_SECONDARY,
X                odd_str(allocated.sec_bats, DEF_SECONDARY));
X            break;
X
X        case MISSILE:
X
X            display_xy(19, 64, "%s", odd_str(allocated.missiles, DEF_MISSILES));
X            break;
X
X        case LAUNCH:
X
X            display_xy(20, 64, "%s", odd_str(allocated.launchers, DEF_LAUNCH));
X            break;
X
X        case AP:
X
X            display_xy(21, 64, "%s", odd_str(allocated.ap, DEF_AP));
X            break;
X
X        case TREAD:
X            display_xy(22, 64, "1/1 (%d)", allocated.treads);
X            break;
X
X    }
X
X}
X
________This_Is_The_END________
echo 'x - ext.h'
sed 's/^X//' <<'________This_Is_The_END________' >>ext.h
X#include <stdio.h>
X#include "ogre.h"
X#define CRATEROUS 12
X
X#ifdef MAIN
X
XUNIT unit[N_UNITS];
XOGRE ogre;
Xint n_units;
Xint mark;
Xstruct{
X	int l_hex;
X	int r_hex;
X} craters[50];
Xint donecraters;
Xint numcraters;
X
X#else
X
Xextern UNIT unit[N_UNITS];
Xextern OGRE ogre;
Xextern int n_units;
Xextern int mark;
Xstruct{
X	int l_hex;
X	int r_hex;
X} craters[50];
Xint donecraters;
Xint numcraters;
X
X#endif
X
X
________This_Is_The_END________
echo 'x - init.c'
sed 's/^X//' <<'________This_Is_The_END________' >>init.c
X#include "ext.h"
X#define UNDO	'^'
X
Xstatic char a, b;
Xstatic int cp_set;
Xstatic int infantry_points, armor_points, n_free;
X
Xinit_units(mark)
X{
X    int unitcmp();
X
X	init_screen();
X
X    a = 10;
X    b = 10;
X
X    switch(mark) {
X
X        case 0:			/* Raider O.G.R.E. a toughie */
X            armor_points = 48;
X            infantry_points = 12;
X            break;
X
X        case 1:
X            armor_points = 8;	/* O.G.R.E I a creampuff */
X            infantry_points = 12;
X            break;
X
X        case 2:			/* O.G.R.E. II hmm.... */
X            armor_points = 12;
X            infantry_points = 12;
X            break;
X
X        case 3:			/* O.G.R.E. III that's the idea! */
X            armor_points = 40;
X            infantry_points = 18;
X            break;
X
X        case 4:			/* O.G.R.E. IV more of the same */
X            armor_points = 40;
X            infantry_points = 24;
X            break;
X
X        case 5: 		/* O.G.R.E. V mama bear */
X            armor_points = 72;
X            infantry_points = 27;
X            break;
X
X        case 6:			/* O.G.R.E. VI papa bear */
X            armor_points = 80;
X            infantry_points = 33;
X            break;
X
X        case 7:			/* O.G.R.E. VII granddad bear */
X            armor_points = 120;
X            infantry_points = 60;
X            break;
X
X        case 8:			/* O.G.R.E. VII WHAT!!! */
X            armor_points = 200;
X            infantry_points = 72;
X            break;
X
X    }
X
X    n_units = n_free = 0;
X    cp_set = FALSE;
X
X    while(armor_points > 0 || infantry_points > 0 || !cp_set) {
X        display(16, "left to place: %d armor, %d infantry%s",
X            armor_points, infantry_points,
X            (cp_set) ? "." : ", CP");
X        getunit();
X    }
X
X    /* sort the units so lower the i, the more valuable the unit. */
X    qsort( (char *) unit, n_units, sizeof(UNIT), unitcmp);
X
X
X}
X
Xgetunit()
X{
X    char    no_new, bad_char;
X    char    olda, oldb;
X    char    dir, i;
X
X    no_new = TRUE;
X    bad_char = FALSE;
X
X    movecur_hex(a, b);
X
X    while(no_new) {
X
X        olda = a;
X        oldb = b;
X
X        dir = readchar();
X    
X        switch(dir) {
X    
X            case RIGHT:
X                a--;
X                b--;
X                break;
X    
X            case UPRIGHT:
X                a--;
X                break;
X    
X            case DOWNRIGHT:
X                b--;
X                break;
X    
X            case LEFT:
X                a++;
X                b++;
X                break;
X    
X            case UPLEFT:
X                b++;
X                break;
X    
X            case DOWNLEFT:
X                a++;
X                break;
X    
X	    case UNDO:
X		if ((i = occupied(a, b)) == 0 || unit[--i].status != OK) {
X		    bad_char = TRUE ;
X		    break ;
X		    }
X		if (unit[i].type == CP) {
X			cp_set = FALSE ;
X			armor_points += unit[i].movement*4 ;
X			}
X		else if (unit[i].type == INFANTRY) infantry_points += 1 ;
X		else if (unit[i].type == HOWITZER) armor_points += 8 ;
X		else if (unit[i].type == HVYTANK) armor_points += 4 ;
X		else if (unit[i].type == MSLTANK) armor_points += 4 ;
X		else if (unit[i].type == GEV) armor_points += 4 ;
X		else if (unit[i].type == LGTTANK) armor_points += 3 ;
X		else if (unit[i].type == MHOW) armor_points += 8 ;
X		else if (unit[i].type == BUNKER) armor_points += 10 ;
X		else broken("Internal error in init!") ;
X
X		if (i < n_free) n_free = i ;
X		unit[i].status = DESTROYED ;
X		update_hex(a, b) ;
X		no_new = FALSE ;
X		break ;
X			
X            case CP:
X                if(cp_set) {
X                    bad_char = TRUE;
X                }
X                else {
X                    add_unit(a, b, dir);
X                    no_new = FALSE;
X                    cp_set = TRUE;
X                }
X                break;
X
X            case HVYTANK:
X            case MSLTANK:
X            case GEV:
X                if(occupied(a, b) || blocked(a, b) || armor_points < 4) {
X                    bad_char = TRUE;
X                    break;
X                }
X                add_unit(a, b, dir);
X                no_new = FALSE;
X                armor_points = armor_points - 4;
X                break;
X    
X	    case BUNKER:
X                if(occupied(a, b) || blocked(a, b) || armor_points < 10) {
X                    bad_char = TRUE;
X                    break;
X                }
X                add_unit(a, b, dir);
X                no_new = FALSE;
X                armor_points = armor_points - 10;
X                break;
X    
X	    case LGTTANK:
X                if(occupied(a, b) || blocked(a, b) || armor_points < 3) {
X                    bad_char = TRUE;
X                    break;
X                }
X                add_unit(a, b, dir);
X                no_new = FALSE;
X                armor_points = armor_points - 3;
X                break;
X    
X            case INFANTRY:
X		dir = '3' ;
X	    case '3':
X	    case '2':
X	    case '1':
X		dir = dir - '0' ;
X                if(blocked(a, b) || infantry_points < dir) {
X                    bad_char = TRUE;
X                    break;
X                }
X		if ((i = occupied(a, b)) != 0)
X		    if (unit[--i].type != INFANTRY
X		    || infantry_on(a, b) + dir > 3) {
X			bad_char = TRUE ;
X			break ;
X			}
X		while (dir--) {
X                    add_unit(a, b, 'I');
X                    infantry_points -= 1 ;
X		    }
X                no_new = FALSE;
X                break;
X    
X            case HOWITZER:
X                if(occupied(a, b) || blocked(a, b) || armor_points < 8) {
X                    bad_char = TRUE;
X                    break;
X                }
X                add_unit(a, b, dir);
X                no_new = FALSE;
X                armor_points = armor_points - 8;
X                break;
X    
X	    case MHOW:
X                if(occupied(a, b) || blocked(a, b) || armor_points < 8) {
X                    bad_char = TRUE;
X                    break;
X                }
X                add_unit(a, b, dir);
X                no_new = FALSE;
X                armor_points = armor_points - 8;
X                break;
X            default:
X                bad_char = TRUE;
X                break;
X    
X        }
X    
X        if(off_obstructed(a, b)  || 
X            bad_char)
X        {
X
X	    putchar(BEEP) ;
X            a = olda;
X            b = oldb;
X            bad_char = FALSE;
X    
X        }
X
X        else {
X
X            movecur_hex(a, b);
X
X        }
X
X    }
X
X}
X
Xadd_unit(a, b, c)
Xchar a, b, c;
X{
X    int i, j;
X
X    i = n_free;
X    if (n_free == n_units) {
X    	n_free = ++n_units ;
X	unit[i].status = DESTROYED ;
X	}
X    else
X    	while (++n_free < n_units)
X	    if (unit[n_free].status == DESTROYED) break ;
X
X    if (unit[i].status != DESTROYED)
X	broken("Using non-free unit in add_unit!") ;
X    if (n_units > N_UNITS)
X	broken("Out of Units. Recompile with larger N_UNITS!") ;
X
X    switch(c) {
X
X        case CP:
X            unit[i].type = CP;
X            unit[i].attack = 0;
X            unit[i].range = 0;
X            unit[i].defend = 0;
X	    j=10;
X	    while ((j>2)||(j<0)&&(armor_points>j*4)){
X		display(17, "Movement points for CP? ", 0) ;
X		j = getchar() ;
X 		if (j >= '0' && j <= '2') 
X                      {j -= '0' ;}
X                  else 
X                      j = 0;
X		display(17, "                        ", 0) ;
X	    }
X	    movecur(17, 0); eeol() ;
X            unit[i].movement = j;
X	    armor_points -= 4*j;
X            break; 
X
X        case HVYTANK:
X            unit[i].type = HVYTANK;
X            unit[i].attack = 4;
X            unit[i].range = 2;
X            unit[i].defend = 3;
X            unit[i].movement = 3;
X            break; 
X
X        case BUNKER:
X            unit[i].type = BUNKER;
X            unit[i].attack = 0;
X            unit[i].range = 0;
X            unit[i].defend = 6;
X            unit[i].movement = 0;
X            break; 
X
X        case LGTTANK:
X            unit[i].type = LGTTANK;
X            unit[i].attack = 2;
X            unit[i].range = 2;
X            unit[i].defend = 2;
X            unit[i].movement = 3;
X            break; 
X
X        case MSLTANK:
X            unit[i].type = MSLTANK;
X            unit[i].attack = 3;
X            unit[i].range = 4;
X            unit[i].defend = 2;
X            unit[i].movement = 2;
X            break; 
X
X        case GEV:
X            unit[i].type = GEV;
X            unit[i].attack = 2;
X            unit[i].range = 2;
X            unit[i].defend = 2;
X            unit[i].movement = 4;
X            break; 
X
X        case HOWITZER:
X            unit[i].type = HOWITZER;
X            unit[i].attack = 6;
X            unit[i].range = 8;
X            unit[i].defend = 1;
X            unit[i].movement = 0;
X            break; 
X
X        case MHOW:
X            unit[i].type = MHOW;
X            unit[i].attack = 6;
X            unit[i].range = 6;
X            unit[i].defend = 1;
X            unit[i].movement = 1;
X            break; 
X
X	case INFANTRY:
X            unit[i].type = INFANTRY;
X            unit[i].attack = 1;
X            unit[i].range = 1;
X            unit[i].defend = 1;
X            unit[i].movement = 2;
X            break; 
X
X    }
X
X    unit[i].range_to_ogre = 0;
X    unit[i].fired = 0;
X    unit[i].status = OK;
X    unit[i].moves_left = 0;
X    unit[i].l_hex = a;
X    unit[i].r_hex = b;
X
X    disp_unit(i);
X
X}
X
Xoccupied(a, b)
Xchar a,b;
X{
X    int i;
X
X    for(i = 0; i < n_units; i++)
X        if(unit[i].status != DESTROYED &&
X           unit[i].l_hex == a &&
X           unit[i].r_hex == b &&
X	   unit[i].type != BUNKER ) return(++i);
X
X    return(FALSE);
X
X}
X
Xinfantry_on(a, b)
Xchar a,b;
X{
X    int i, c;
X
X    for (c = i = 0; i < n_units; i++)
X	if (unit[i].type == INFANTRY && unit[i].status != DESTROYED
X	&& unit[i].l_hex == a && unit[i].r_hex == b)
X	    c++ ;
X
X    return c ;
X
X}
X	   
Xinit_ogre(mark)
X{
X
X    ogre.l_hex = rand() % 7 + 22; /* 22 - 28 */
X    ogre.r_hex = 50 - ogre.l_hex;
X
X    switch(mark) {
X
X        case 1:
X            ogre.treads = 15;
X            ogre.init_treads = 15;
X            ogre.movement = 3;
X            ogre.missiles = 0;
X	    ogre.launchers = 0;
X            ogre.main_bats = 1;
X            ogre.sec_bats  = 0;
X            ogre.ap = 2;
X            break;
X
X        case 2:
X            ogre.treads = 30;
X            ogre.init_treads = 30;
X            ogre.movement = 3;
X            ogre.missiles = 0;
X	    ogre.launchers = 0;
X            ogre.main_bats = 1;
X            ogre.sec_bats  = 2;
X            ogre.ap = 6;
X            break;
X
X        case 3:
X            ogre.treads = 45;
X            ogre.init_treads = 45;
X            ogre.movement = 3;
X            ogre.missiles = 2;
X	    ogre.launchers = 0;
X            ogre.main_bats = 1;
X            ogre.sec_bats  = 4;
X            ogre.ap = 8;
X            break;
X
X        case 4:
X            ogre.treads = 45;
X            ogre.init_treads = 45;
X            ogre.movement = 3;
X            ogre.missiles = 2;
X	    ogre.launchers = 0;
X            ogre.main_bats = 2;
X            ogre.sec_bats  = 4;
X            ogre.ap = 8;
X            break;
X
X        case 5:
X            ogre.treads = 60;
X            ogre.init_treads = 60;
X            ogre.movement = 3;
X            ogre.missiles = 5;
X	    ogre.launchers = 0;
X            ogre.main_bats = 2;
X            ogre.sec_bats  = 6;
X            ogre.ap = 10;
X            break;
X
X        case 6:
X            ogre.treads = 75;
X            ogre.init_treads = 75;
X            ogre.movement = 3;
X            ogre.missiles = 5;
X	    ogre.launchers = 2;
X            ogre.main_bats = 4;
X            ogre.sec_bats  = 10;
X            ogre.ap = 12;
X            break;
X
X        case 0:
X            ogre.treads = 45;
X            ogre.init_treads = 45;
X            ogre.movement = 4;
X            ogre.missiles = 2;
X	    ogre.launchers = 2;
X            ogre.main_bats = 1;
X            ogre.sec_bats  = 2;
X            ogre.ap = 12;
X            break;
X
X        case 7:
X            ogre.treads = 90;
X            ogre.init_treads = 90;
X            ogre.movement = 4;
X            ogre.missiles = 6;
X	    ogre.launchers = 4;
X            ogre.main_bats = 8;
X            ogre.sec_bats  = 12;
X            ogre.ap = 30;
X            break;
X
X        case 8:
X            ogre.treads = 140;
X            ogre.init_treads = 140;
X            ogre.movement = 5;
X            ogre.missiles = 10;
X	    ogre.launchers = 12;
X            ogre.main_bats = 12;
X            ogre.sec_bats  = 24;
X            ogre.ap = 60;
X            break;
X
X    }
X
X
X    disp_ogre();
X
X}
X
Xunitcmp(u1, u2)
XUNIT *u1, *u2;
X{
X    int cmp;
X
X    switch(u1 -> type) {
X
X        case CP:
X
X            switch(u2 -> type) {
X
X                case CP: 
X                    cmp = 0;
X                    break;
X
X                default:
X                    cmp = -1;
X                    break;
X
X            }
X
X            break;
X
X        case HOWITZER:
X            switch(u2 -> type) {
X
X                case CP: 
X                    cmp = 1;
X                    break;
X
X                case HOWITZER:
X                    cmp = 0;
X                    break;
X
X                default:
X                    cmp = -1;
X                    break;
X
X            }
X
X            break;
X
X        case HVYTANK:
X            switch(u2 -> type) {
X
X                case CP:
X                case HOWITZER:
X                    cmp = 1;
X                    break;
X
X                case HVYTANK:
X                    cmp = 0;
X                    break;
X
X                default:
X                    cmp = -1;
X                    break;
X
X            }
X
X            break;
X
X        case MSLTANK:
X            switch(u2 -> type) {
X
X                case CP:
X                case HOWITZER:
X                case HVYTANK:
X                    cmp = 1;
X                    break;
X
X                case MSLTANK:
X                    cmp = 0;
X                    break;
X
X                default:
X                    cmp = -1;
X                    break;
X
X            }
X
X            break;
X
X        case GEV:
X            switch(u2 -> type) {
X
X                case INFANTRY:
X                    cmp = -1;
X                    break;
X
X                case GEV:
X                    cmp = 0;
X                    break;
X
X                default:
X                    cmp = 1;
X                    break;
X
X            }
X
X            break;
X
X        case INFANTRY:
X            switch(u2 -> type) {
X
X                case INFANTRY: 
X                    cmp = 0;
X                    break;
X
X                default:
X                    cmp = 1;
X                    break;
X
X            }
X
X            break;
X
X        }
X
X    return(cmp);
X
X}
X
Xbroken(thing) char *thing; {
X
X	clear_screen() ;
X	reset_term() ;
X    	printf("Internal error: %s\n", thing) ;
X	exit(1) ;
X	}
X
________This_Is_The_END________
echo 'x - initround.c'
sed 's/^X//' <<'________This_Is_The_END________' >>initround.c
X#include "ext.h"
X
Xinit_round()
X{
X
X    int i;
X
X    for(i = 0; i < n_units; i++) {
X
X        unit[i].moves_left = unit[i].movement;
X        if(unit[i].status == DISABLED) {
X            unit[i].status = OK;
X            update_hex(unit[i].l_hex, unit[i].r_hex);
X        }
X        unit[i].range_to_ogre =
X            range(ogre.l_hex, ogre.r_hex, unit[i].l_hex, unit[i].r_hex);
X
X    }
X
X}
X
Xinit_move_ogre()
X{
X
X    int i;
X
X    for(i = 0; i < n_units; i++) {
X
X        unit[i].range_to_ogre =
X            range(ogre.l_hex, ogre.r_hex, unit[i].l_hex, unit[i].r_hex);
X
X    }
X
X}
X
Xinit_def_attack()
X{
X
X    int i;
X
X    for(i = 0; i < n_units; i++) {
X
X        if(unit[i].status == OK) {
X            unit[i].fired = FALSE;
X            unit[i].range_to_ogre =
X                range(ogre.l_hex, ogre.r_hex, unit[i].l_hex, unit[i].r_hex);
X        }
X
X    }
X
X}
X
Xinit_ogre_attack()
X{
X
X    int i;
X
X    for(i = 0; i < n_units; i++) {
X
X            unit[i].fired = 0;
X            unit[i].range_to_ogre =
X                range(ogre.l_hex, ogre.r_hex, unit[i].l_hex, unit[i].r_hex);
X
X    }
X
X}
X
Xinit_gev2()
X{
X    int i;
X
X    for(i = 0; i < n_units; i++)
X        if(unit[i].status == OK && unit[i].type == GEV)
X            unit[i].moves_left = 3;
X
X}
X
________This_Is_The_END________
echo 'x - main.c'
sed 's/^X//' <<'________This_Is_The_END________' >>main.c
X/*
X    OGRE: a tactical ground combat game set in 2085.
X
X    Adapted from the Metagaming Microgame by Steve Jackson.
X
X    This version was written for a Vax 11/780 under Unix
X    by Michael Caplinger, Rice University, February-March 1982.
X
X    Paper game (c) 1977 by Steve Jackson
X    This implementation (c) 1982, 1984 by Michael Caplinger
X*/
X
X#include <signal.h>
X#include <ctype.h>
X
X#define MAIN
X#include "ext.h"
X
Xmain(argc, argv)
Xchar **argv;
X{
X
X    int handler();
X
X    signal(SIGINT, handler);
X
X    if(argc > 1){
X        if ((argv[1][0]-'0'>=0)&&(argv[1][0]-'0' < 9))
X		mark = argv[1][0] - '0';
X    }
X    else mark = 3;
X
X    set_term();
X    srand(time(0));
X    init_units(mark);
X    init_ogre(mark);
X    disp_ogre_status(TRUE);
X
X    while(1) {
X
X        init_round();
X
X        /* The Ogre fires. */
X        assign_fire_ogre();
X        check_over(); 
X
X        /* Player moves, and fires. */
X        move_def();
X        attack_def();
X
X        /* Let the GEVs move their extra 3 turns. */
X        init_gev2();
X        move_def();
X
X        /* The Ogre moves. */
X        move_ogre();
X        check_over(); 
X
X    }
X
X}
X
Xhandler() {
X
X    clear_screen();
X    reset_term();
X    exit(0);
X
X}
X
X/*
X    Get a character. If it's a ^L, redraw the screen.
X*/
X
Xreadchar() {
X	int	c ;
X
X	while ((c = getchar()) == REDRAW) redraw_screen() ;
X	return (islower(c) ? toupper(c) : c) ;
X	}
X
X/*
X    See if the game is over, and die if it is.
X*/
Xcheck_over()
X{
X    char *message;
X    int over;
X
X    over = FALSE;
X
X    if(unit[0].status == DESTROYED) {
X        message = "The Ogre wins!!";
X        over = TRUE;
X    }
X    if(ogre.movement == 0) {
X        message = "You win!!";
X        over = TRUE;
X    }
X
X    if(over) {
X        clear_screen();
X        reset_term();
X        printf("%s\n", message);
X        exit(0);
X    }
X
X}
________This_Is_The_END________
echo 'x - map.c'
sed 's/^X//' <<'________This_Is_The_END________' >>map.c
X/*
X    These routines implement all functions associated with the map and display
X    thereof.
X
X    (Thanks to Bob Hood of Rice for coming up with 
X     the x-y and range algorithms.)
X
X    Michael Caplinger, Rice University, March 1982.
X*/
X
X#include "ext.h"
X#include <ctype.h>
X
Xint lastunit = 0 ;
Xchar *lastaction = (char *) 0 ;
X
X
X/* Initialize the map display, at the beginning of the game. */
Xinit_screen() {
X
X    int a, b;
X
X    tc_setup();
X    clear_screen();
X
X    for(a = 1; a <= 28; a++) {
X        for(b = 1; b <= 28; b++) {
X            if(!off_map(a, b)) {
X                disp_hex(a, b, '.');
X            }
X        }
X    }
X    disp_craters();
X}
X
Xredraw_screen() {
X
X    int a, b;
X
X    clear_screen();
X
X    for(a = 1; a <= 28; a++) {
X        for(b = 1; b <= 28; b++) {
X            if(!off_map(a, b)) {
X                update_hex(a, b);
X            }
X        }
X    }
X
X    disp_ogre_status(1);
X    describe_action(lastaction, lastunit) ;
X
X}
X
X/* 
X    Convert a left and right hex pair (eg, the hex 2015 has an l_hex of 20 and
X    an r_hex of 15) to x-y screen coordinates.
X*/
Xto_xy(lhex, rhex, row, col)
Xchar lhex, rhex, *row, *col;
X{
X
X    *row = (lhex - rhex) + 7;
X    *col = 50 - (lhex + rhex);
X
X}
X
X/* Check to see if an lr pair is off the map. */
Xoff_map(a, b)
Xchar a, b;
X{
X    char row, col;
X
X    to_xy(a, b, &row, &col);
X    if(col < 0 || col > 38 || row < 0 || row > 14) return(TRUE);
X    else return(FALSE);
X
X}
X
X/* Check to see if an lr pair is off the obstructed area of the map. */
Xoff_obstructed(a, b)
Xchar a, b;
X{
X    char row, col;
X
X    to_xy(a, b, &row, &col);
X    if(col < 10 || col > 38 || row < 0 || row > 14) return(TRUE);
X    else return(FALSE);
X
X}
X
X/* Display a character at a given hex. */
Xdisp_hex(a, b, c)
Xchar a, b, c;
X{
X    char row, col;
X
X    to_xy(a, b, &row, &col);
X
X    movecur(row, col * 2 + 1);
X    putchar(c);
X
X}
X
X/* 
X    Display the contents of a hex.  If more than one item is in a hex,
X    the following precedence applies:
X        1) Ogre
X        2) Defending units (by value)
X        3) Craters (not that anything can be in a crater hex.)
X*/
Xupdate_hex(a, b)
Xchar a, b;
X{
X
X    int i;
X
X    if(ogre.l_hex == a && ogre.r_hex == b) {
X        disp_ogre();
X        return;
X    }
X
X    for(i = 0; i < n_units; i++)
X        if(unit[i].l_hex == a && unit[i].r_hex == b &&
X            unit[i].status != DESTROYED) {
X            disp_unit(i);
X            return;
X        }
X
X    if(blocked(a, b)) {
X        disp_hex(a, b, '*');
X        return;
X    }
X
X    disp_hex(a, b, '.');
X
X}
X
X/* Display the ith unit. */
Xdisp_unit(i)
Xint i;
X{
X    char a, b;
X
X    a = unit[i].l_hex;
X    b = unit[i].r_hex;
X
X    switch(unit[i].status) {
X
X        case OK:
X
X            switch(unit[i].type) {
X
X                case INFANTRY:
X		    disp_hex(a, b, '0' + infantry_on(a, b));
X                    break;
X
X                default:
X		    disp_hex(a, b, unit[i].type);
X                    break;
X
X            }
X            break;
X
X        case DISABLED:
X            disp_hex(a, b, tolower(unit[i].type));
X            break;
X
X        case DESTROYED:
X            disp_hex(a, b, '.');
X            break;
X
X    }
X
X}
X
X/* Display the Ogre. */
Xdisp_ogre()
X{
X    char a, b;
X
X    a = ogre.l_hex;
X    b = ogre.r_hex;
X
X    disp_hex(a, b, 'O');
X
X}
X
X
X/* Move the cursor to the specified hex on the screen. */
Xmovecur_hex(a, b)
Xchar a, b;
X{
X    char row, col;
X
X    to_xy(a, b, &row, &col);
X
X    movecur(row, col * 2 + 1);
X
X}
X
X/* Point at the ith unit with the cursor. */
Xmovecur_unit(i)
Xint i;
X{
X
X    movecur_hex(unit[i].l_hex, unit[i].r_hex);
X
X}
X
X#define ABS(i) (((i) < 0) ? -(i) : (i))
X#define BIGINT 32767
X
X/* Calculate the range between 2 hexes. */
Xrange(a1, b1, a2, b2)
Xchar a1, b1, a2, b2;
X{
X
X    char    diff1, diff2, temp;
X    int     subrange[3];
X    int     min, i;
X    int     rangesum;
X
X    diff1 = a1 - b1;
X    diff2 = a2 - b2;
X
X    subrange[0] = ABS(a1 - a2);
X    subrange[1] = ABS(b1 - b2);
X    subrange[2] = ABS(diff1 - diff2);
X
X    min = 0;
X    for(i = 1; i < 3; i++)
X        if(subrange[i] < subrange[min]) min = i;
X
X    rangesum = subrange[min];
X
X    temp = subrange[min]; subrange[min] = subrange[2]; subrange[2] = temp;
X
X    min = 0;
X    for(i = 1; i < 2; i++)
X        if(subrange[i] < subrange[min]) min = i;
X
X    rangesum += subrange[min];
X
X    return(rangesum);
X
X}
X
X#define MAXCRATERS 50;
Xinit_craters()
X{
X	int x,y,cc = 0;
X	srand(getpid());
X
X	for(x=1;x<50;x++)
X	  	for(y=1;y<50;y++){
X			if (rand() % CRATEROUS == 1){
X				if (!off_map(x,y)){ /* sorry*/
X			 		craters[cc].l_hex = x;
X			 		craters[cc].r_hex = y;
X					cc++;
X				}
X			};
X			if (cc == 50)
X				goto done;
X		}
X	done: return(cc);
X}
X/* Determine if a hex has a crater. */
Xblocked(a, b)
Xchar a, b;
X{
X    int i;
X
X    for(i = 0; i < numcraters; i++) 
X        if(craters[i].l_hex == a && craters[i].r_hex == b) return(TRUE);
X
X    return(FALSE);
X
X}
X
X/* Display the craters. */
Xdisp_craters()
X{
X    int i;
X
X    if (!donecraters)
X	numcraters = init_craters();
X    for(i = 0; i < numcraters; i++) 
X        disp_hex(craters[i].l_hex, craters[i].r_hex, '*');
X
X}
X
X#include <stdio.h>
X
Xdescribe_action(action, i)
Xchar *action;
Xint i;
X{
X
X    lastunit = i;
X    lastaction = action ;
X
X    display(16,"                                                       ");
X    switch(unit[i].type) {
X
X        case HOWITZER:
X            display(16, "%s howitzer (%d/%d D%d M%d)", action,
X                unit[i].attack, unit[i].range, 
X                unit[i].defend, unit[i].moves_left);
X            break;
X
X        case MHOW:
X            display(16, "%s mobile howitzer (%d/%d D%d M%d)", action,
X                unit[i].attack, unit[i].range, 
X                unit[i].defend, unit[i].moves_left);
X            break;
X
X        case MSLTANK:
X            display(16, "%s missile tank (%d/%d D%d M%d)", action,
X                unit[i].attack, unit[i].range, 
X                unit[i].defend, unit[i].moves_left);
X            break;
X
X        case GEV:
X            display(16, "%s GEV (%d/%d D%d M%d)", action,
X                unit[i].attack, unit[i].range, 
X                unit[i].defend, unit[i].moves_left);
X            break;
X
X        case HVYTANK:
X            display(16, "%s heavy tank (%d/%d D%d M%d)", action,
X                unit[i].attack, unit[i].range, 
X                unit[i].defend, unit[i].moves_left);
X            break;
X
X        case LGTTANK:
X            display(16, "%s light tank (%d/%d D%d M%d)", action,
X                unit[i].attack, unit[i].range, 
X                unit[i].defend, unit[i].moves_left);
X            break;
X
X        case INFANTRY:
X            display(16, "%s infantry (%d/%d D%d M%d)", action,
X                unit[i].attack, unit[i].range, 
X                unit[i].defend, unit[i].moves_left);
X            break;
X
X	case CP:
X	    display(16, "%s CP (%d/%d D%d M%d)", action,
X                unit[i].attack, unit[i].range, 
X                unit[i].defend, unit[i].moves_left);
X	    break;
X    }
X
X}
X
X/* VARARGS */
Xdisplay(line, format, args)
Xint line;
Xchar *format;
Xint args;
X{
X
X    movecur(line, 0);
X    eeol();
X    _doprnt(format, &args, stdout);
X
X}
X
X/* VARARGS */
Xdisplay_xy(line, col, format, args)
Xint line, col;
Xchar *format;
Xint args;
X{
X
X    movecur(line, col);
X    eeol();
X    _doprnt(format, &args, stdout);
X
X}
X
X
X
________This_Is_The_END________
echo 'x - move.c'
sed 's/^X//' <<'________This_Is_The_END________' >>move.c
X/*
X    Move the defender's units.
X
X    Michael Caplinger, Rice University, March 1982.
X*/
X
X#include "ext.h"
X
Xmove_def()
X{
X    int i,j;
X    char moreunits, l_old, r_old, m_old ;
X
X    for (moreunits = TRUE; moreunits;) {
X	moreunits = FALSE ;
X	for(i = 0; i < n_units; i++)
X	    if (unit[i].status == OK && unit[i].moves_left > 0) {
X		describe_action("Move", i);
X		m_old = unit[i].moves_left ;
X		l_old = unit[i].l_hex ;
X		r_old = unit[i].r_hex ;
X		while(unit[i].moves_left > 0 && unit[i].status == OK)
X		    if (getmove(i, l_old, r_old, m_old)) {
X		    	moreunits = TRUE ;
X			break ;
X			}
X		}
X	}
X	for(i=0;i<n_units;i++)
X		switch (unit[i].type){
X			case MHOW:
X				unit[i].defend = DEFEND_MHOW;
X				break;
X			case HOWITZER:
X				unit[i].defend = DEFEND_HOWITZER;
X				break;
X			case LGTTANK:
X				unit[i].defend = DEFEND_LGTTANK;
X				break;
X			case MSLTANK:
X				unit[i].defend = DEFEND_MSLTANK;
X				break;
X			case HVYTANK:
X				unit[i].defend = DEFEND_HVYTANK;
X				break;
X			case INFANTRY:
X				unit[i].defend = DEFEND_INFANTRY;
X				break;
X			case CP:
X				unit[i].defend = DEFEND_CP;
X				break;
X			case GEV:
X				unit[i].defend = DEFEND_GEV;
X				break;
X		}
X
X	for(i=0;i<n_units;i++)
X		if (unit[i].type==BUNKER)
X			for(j=0;j<n_units;j++)
X				if ((unit[i].l_hex==unit[j].l_hex)&&(unit[i].r_hex==unit[j].l_hex)&&(i!=j))
X					unit[j].defend=6;
X
X   disp_craters();
X}
X/*
X * getmove - retrieves one move, verifies that the board is correct, and
X *	returns whether or not this unit can move again.
X */
Xgetmove(i, l_old, r_old, m_old)
Xint i;
Xchar l_old, r_old, m_old ;
X{
X
X    char    nomove, bad_char;
X    char    a, b, dir;
X    char    olda, oldb ;
X
X    nomove = TRUE;
X
X    while(nomove) {
X    
X        a = unit[i].l_hex;
X        b = unit[i].r_hex;
X
X        movecur_hex(a, b);
X
X        bad_char = FALSE;
X    
X        dir = readchar();
X    
X        switch(dir) {
X    
X            case RIGHT:
X                a--;
X                b--;
X                break;
X    
X            case UPRIGHT:
X                a--;
X                break;
X    
X            case DOWNRIGHT:
X                b--;
X                break;
X    
X            case LEFT:
X                a++;
X                b++;
X                break;
X    
X            case UPLEFT:
X                b++;
X                break;
X    
X            case DOWNLEFT:
X                a++;
X                break;
X    
X            case SIT:
X            case ' ':
X		for (dir = 0; dir < n_units; dir++)
X		    if (unit[dir].type != BUNKER)
X		    	if (dir != i && unit[dir].status != DESTROYED &&
X				unit[dir].l_hex == a && unit[dir].r_hex == b)
X			    	bad_char = unit[dir].type != INFANTRY
X		               	|| unit[i].type != INFANTRY
X			       	|| infantry_on(a, b) > 3 ;
X			if (bad_char) break ;
X	
X                	unit[i].moves_left = 0;
X			return FALSE ;
X
X	    case PASS:
X		unit[i].l_hex = l_old ;
X		unit[i].r_hex = r_old ;
X		unit[i].moves_left = m_old ;
X		update_hex(a, b) ;	
X		disp_unit(i) ;
X	    	return TRUE ;
X
X            default:
X                bad_char = TRUE;
X                break;
X    
X        }
X
X        /* Rule 5.02 */
X
X        if(bad_char ||
X	    off_map(a, b) || 
X            (blocked(a, b)&&(unit[i].type !=INFANTRY)) ||
X	    ( ((dir = occupied(a, b)) && unit[i].moves_left == 1) &&
X	      (unit[i].type != INFANTRY || unit[--dir].type !=INFANTRY ||
X	       unit[i].attack + infantry_on(a, b) > 3)))
X	
X        {
X	    putchar(BEEP) ;
X            bad_char = FALSE;
X    
X        }
X
X        else {
X            /* move the thing */
X
X	    if (unit[i].type==INFANTRY)
X		unit[i].defend=1;
X	    if (blocked(a,b))
X		unit[i].defend=3;
X	    olda = unit[i].l_hex;
X	    oldb = unit[i].r_hex;
X	    unit[i].l_hex = a;
X            unit[i].r_hex = b;
X	    update_hex(olda, oldb);
X	    disp_unit(i) ;
X
X            nomove = FALSE;
X            unit[i].moves_left -= 1;
X
X            def_ram(i);
X
X        }
X
X    }
X    return FALSE  ;
X}
________This_Is_The_END________
echo 'x - ogre.6'
sed 's/^X//' <<'________This_Is_The_END________' >>ogre.6
X.TH OGRE 6
X.UC 4
X.SH NAME
XOgre - a game of tank warfare in the 21st century.
X.SH SYNOPSIS
X/usr/games/ogre [ogre type (0-6)]
X.SH DESCRIPTION
X.PP
XOgre is a game of tank warfare in the 21st century.  You command a force of
Xinfantry, armor, and howitzers pitted against a giant cybernetic tank, the
XOgre.  Your mission is to destroy the Ogre, or at least render it immobile,
Xbefore it reaches and destroys your command post.
X.PP
XA more complete reference on how to play can be found in the Ogre rule book
Xfor the Metagaming MicroGame, now distributed by Steve Jackson's company.
XHere's some very sketchy and incomplete documentation for Ogre players:
X.PP
XThe game has the following phases:
X.PP
X1) Initialization.  The player's armor units, infantry, and command post
Xare placed on the map.  Nothing can be placed on the leftmost 7
Xcolumns of hexes, or on craters (*'s), or on any unit already placed.
XValid commands are:
X.nf
X
X           y   u
X
X        g         j    (hex movement keys)
X
X           b   n
X
X            place a:
X                        attack   range    defense  movement
XH   howitzer            6        8        1        0
X@   mobile howitzer     6        6        1        1
XT   heavy tank          4        2        3        3
XL   light tank          2        2        2        3
XM   missile tank        3        4        2        2
XV   GEV                 2        2        2        4/2
X1   1 infantry unit     1        1        1        2
X2   2 infantry units    1        1        1        2
X3   3 infantry units    1        1        1        2
XI   3 infantry units    1        1        1        2
XB   bunker              0        0        5        0
XC   command post
X^   undo - pick up the unit
X.fi
X
Xon the space currently pointed at by the cursor.
X.PP
XUnits are displayed as these characters, except infantry, which appear
Xas '1', '2', or '3' depending on the number of units in the hex.
X.PP
XAfter placing the command post, you will be asked what its movement
Xallowance should be. You may give the CP a movement allowance of
X0, 1, or 2 hexes. Each point of movement allowance you give the CP
Xwill cost one armor point. Note that you must have enough armor
Xpoints left to provide the CP the desired movement. In any case, a
Xmovement of 0 is always valid.
X.PP
X2) The Ogre (an O) now appears.
X.nf
X                MAIN    SEC     MISS    LAUN    AP      TREAD
XO.G.R.E I       1       0       0       0       2       15
XO.G.R.E II      1       2       0       0       6       30
XO.G.R.E III     1       4       2       0       8       45
XO.G.R.E IV      2       4       2       0       8       45
XO.G.R.E IV (0)  1       4       0       2       8       45
XO.G.R.E V       2       6       5       0       10      60
XO.G.R.E VI      4      10       5       2       12      75
XO.G.R.E VII     8      12       5       4       30      90
XO.G.R.E VIII    12     20	10      12      60      140
X
X.fi
X.PP
X3) You are given the opportunity to move all your vehicles and infantry
Xthat can move.  The cursor motion keys are used to move the unit indicated
Xby the cursor.  Additionally, the following commands are available:
X.TP
X.B 's',' '
XStop moving the unit where it is.
X.TP
X.B 'p'
XPut this unit back where it started, and move it later.
X.PP
XNo vehicle can move through a crater hex, or end it's movement on a friendly
Xunit, with the exception of infantry (see below).
XMoving through the hex occupied by the Ogre is an attempt to ram the
XOgre.  This reduces the Ogre's treads by some amount, and destroys the
Xunit.
X.PP
X4) You now fire all your vehicles in range at designated targets on the
XOgre.  The following commands are used:
X.TP     
X.B m  
Xfire at missiles
X.TP     
X.B l  
Xfire at missile launchers
X.TP
X.B b   
Xfire at main batteries
X.TP
X.B s   
Xfire at secondary batteries
X.TP        
X.B a   
Xfire at anti-personnel guns
X.TP        
X.B t   
Xfire at treads
X.PP
XThe odds of destroying the target are displayed, but no action
Xis taken until 'r' is used, or until you run out of attack points.
X(except for attacks on treads - see below.)
X(in the odds display, '+' means a sure thing.)
X.TP 
X.B p   
XPass. The unit is passed over, and given the opportunity to fire
Xlater.
X.TP        
X.B r   
XResolve all allocations so far, and display the results.  This
Xis implied by 't', as tread attacks cannot be grouped.  A resolve
Xis done automatically when you run out of attacking units.
X.PP
X5) Second movement phase for GEVs.  Just like step 3, except that only GEVs
Xcan move.
X.PP
X6) The Ogre moves.  If it runs over any of your units, they are damaged
Xor destroyed.
X.PP
X7) The Ogre fires at all units in range.  Destroyed units are removed from
Xthe map.  Disabled units are displayed in lower case, and may not
Xmove or fire until the end of the NEXT Ogre attack.
X.PP
XSteps 3 through 7 are repeated until either
Xa) the Ogre has no movement points left, in which case you win, or
Xb) your command post is destroyed, in which case the Ogre wins.
X.SH MISCELLANEOUS
X.PP
XIn general, you cannot have more than one unit in a hex (no stacking),
Xexcept for infantry. You may have as many as three infantry units in a hex.
XInstead of an 'I' to indicate infantry, the number of units in the hex is
Xdisplayed.  Even when stacked, infantry units still attack, defend, and
Xmove as seperate units.  Currently, the only place where this game differs
Xfrom the board game is that the ogre may use AP on a hex with multiple
Xunits in it once per unit, as opposed to once per hex.
X.PP
XThe display "a/r Dd Mm" means the unit concerned attacks at a, at range r,
Xdefends at d, and moves m hexes per turn.
X.PP
XThe Ogre by default is a Mark III.  An argument of '5' on the command line
Xmakes it a Mark V, and gives you more armor points.
X.PP
XThe game can be interrupted at any point with a control-C.  There's now
Xno way to restart.
X.PP
XThe screen can be redrawn (after say a control-Z) with a control-L.
X.PP
XThe paper game is copyright (c) 1977 by Steve Jackson.  This computer
Ximplementation is copyright (c) 1984 by Michael Caplinger.
XModifications copyright (c) 1984 by Mike Meyer.
X.SH AUTHOR
XMichael Caplinger, Rice University (mike@rice.ARPA), from a Microgame of the
Xsame name published by Metagaming of Austin, Texas, and written by Steve
XJackson.  This implementation is not authorized in any way by Mr. Jackson,
Xand should not be sold for profit.
X.SH SEE ALSO
Xtermcap(5)
X.SH BUGS
X.PP
XThe Ogre sometimes gets confused and doesn't know where to go, so it
Xoscillates from one hex to another, and then back.
X
________This_Is_The_END________
echo 'x - ogre.h'
sed 's/^X//' <<'________This_Is_The_END________' >>ogre.h
Xtypedef struct {
X
X    char    type;
X    char    attack;
X    char    range;
X    char    defend;
X    char    movement;
X    char    range_to_ogre;
X    char    fired;
X    char    moves_left;
X    char    status;
X    char    l_hex;
X    char    r_hex;
X
X} UNIT;
X
Xtypedef struct {
X
X    char    missiles;
X    char    launchers;
X    char    main_bats;
X    char    sec_bats;
X    char    ap;
X    char    treads;
X    char    movement;
X    char    moves_left;
X    char    l_hex;
X    char    r_hex;
X    char    init_treads;
X    char    where;
X
X} OGRE;
X
X/* unit types */
X
X#define CP          'C'
X#define BUNKER      '#'
X#define HVYTANK     'T'
X#define LGTTANK     'L'
X#define MSLTANK     'M'
X#define GEV         'V'
X#define HOWITZER    'H'
X#define INFANTRY    'I'
X#define MHOW	    '@'
X
X#define DEFEND_CP           1
X#define DEFEND_HVYTANK 	    3
X#define DEFEND_LGTTANK 	    2
X#define DEFEND_MSLTANK 	    2
X#define DEFEND_GEV     	    2
X#define DEFEND_HOWITZER	    1
X#define DEFEND_INFANTRY	    1
X#define DEFEND_MHOW	    1
X
X/* unit statuses */
X#define OK          1
X#define DISABLED    2
X#define DESTROYED   3
X
X/* directions */
X#define RIGHT       'J'
X#define UPRIGHT     'U'
X#define DOWNRIGHT   'N'
X#define LEFT        'G'
X#define UPLEFT      'Y'
X#define DOWNLEFT    'B'
X#define SIT         'S'
X#define PASS        'P'
X#define REDRAW      '\014'
X#define BEEP	    '\07'
X
X#define TRUE        1
X#define FALSE       0
X
X#define N_UNITS     200
X
X#define DEF_MISSILES    3
X#define DEF_LAUNCH	3
X#define DEF_MAIN        4
X#define DEF_SECONDARY   3
X#define DEF_AP          1
X
X#define ATK_MISSILES    6
X#define	ATK_LAUNCH	6
X#define ATK_MAIN        4
X#define ATK_SECONDARY   3
X#define ATK_AP          1
X
X#define RANGE_MISSILES      5  
X#define RANGE_LAUNCH	    5
X#define RANGE_MAIN          3
X#define RANGE_SECONDARY     2
X#define RANGE_AP            1
X
________This_Is_The_END________
echo 'x - ogrecom.c'
sed 's/^X//' <<'________This_Is_The_END________' >>ogrecom.c
X/*
X    These routines define the Ogre's stategy (such as it is).
X    There's lots of room for improvement here.
X*/
X
X#include "ext.h"
X
Xmove_ogre()
X{
X
X    init_move_ogre();
X
X    ogre.moves_left = ogre.movement;
X
X    while(ogre.moves_left > 0) {
X        move_ogre1();
X        ogre_ram();
X        cycle();
X    }
X
X}
X
X#define INFINITY 32767
X
X/* Move the Ogre one hex. */
Xmove_ogre1()
X{
X
X    int weight[7];
X    int i, max;
X    char a, b;
X    char olda, oldb;
X/* dyt - prevent oscillation */
X    static int osccnt;
X    static int oscdir;
X    static int mapdir[7] = { 0, 4, 5, 6, 1, 2, 3 };
X
X    a = ogre.l_hex;
X    b = ogre.r_hex;
X
X    /* Collect weights for each possible move. These will be maximized. */
X
X    weight[0] = - INFINITY; /* temp patch: getweight(a, b); */
X    weight[1] = getweight(a - 1, b - 1);
X    weight[2] = getweight(a - 1, b);
X    weight[3] = getweight(a, b + 1);
X    weight[4] = getweight(a + 1, b + 1);
X    weight[5] = getweight(a + 1, b);
X    weight[6] = getweight(a, b - 1);
X
X/* dyt - prevent oscillation - decrease weight if returning to old position */
X    weight[mapdir[oscdir]] -= 10 * osccnt;
X
X    max = 0;
X    for(i = 1; i < 7; i++)
X        if(weight[i] > weight[max]) max = i;
X
X/* dyt - record new direction */
X    if (max == mapdir[oscdir])
X     	  osccnt++;
X    else
X        osccnt = 0;
X    oscdir = max;
X
X/* display(17, "max %d weight %d cnt %d odir %d ndir %d",
X	max, weight[max], osccnt, oscdir, mapdir[oscdir]);
X   cycle(); */
X
X    switch(max) {
X
X        case 0:
X            break;
X
X        case 1:
X            a--;
X            b--;
X            break;
X
X        case 2:
X            a--;
X            break;
X
X        case 3:
X            b++;
X            break;
X
X        case 4:
X            a++;
X            b++;
X            break;
X
X        case 5:
X            a++;
X            break;
X
X        case 6:
X            b--;
X            break;
X
X    }
X
X    olda = ogre.l_hex;
X    oldb =  ogre.r_hex;
X
X    ogre.l_hex = a;
X    ogre.r_hex = b;
X
X    update_hex(olda, oldb);
X
X    disp_ogre();
X    ogre.moves_left -= 1;
X
X}
X
X/*
X    The weight for each hex is a measure of how desirable it is to be in that
X    hex; the weights of the six possible directions are maximized.
X
X    The primary consideration is distance to the CP; in the absence of other
X    factors, the Ogre will take the fastest course to the CP.
X    However, the Ogre will crush any unit it can (units with higher attacks
X    chosen first) and moves towards units that are within range of its missiles
X    or batteries.  It attempts to weight so that a concentration of dangerous,
X    immobile units (like howitzers) is attacked first.
X
X    Testing indicates that this isn't a bad strategy.
X*/
Xgetweight(a, b)
Xchar a, b;
X{
X    int weight = 0;
X    int total_attacks;
X    int to_target;
X    int i;
X
X    total_attacks = ogre.missiles + ogre.main_bats + ogre.sec_bats;
X
X    for(i = 1; i < n_units; i++)
X    if (unit[i].type != '#'){
X
X        if(unit[i].status == DESTROYED) continue;
X
X        to_target = range(a, b, unit[i].l_hex, unit[i].r_hex);
X
X        /*
X             If you can crush somebody, do it.
X             More dangerous units get crushed first.
X        */
X        if(to_target == 0) {
X	    if(unit[i].type == CP) weight = 50;
X            else weight = 10 * unit[i].attack;
X            break;
X        }
X
X        if(total_attacks <= 0) continue;
X
X        if(to_target <= RANGE_MISSILES && ogre.missiles > 0) {
X            weight += unit[i].attack;
X            weight += 4 - unit[i].movement;
X            total_attacks -= 1;
X            continue;
X        }
X
X        if(to_target <= RANGE_LAUNCH && ogre.launchers > 0) {
X            weight += unit[i].attack;
X            weight += 4 - unit[i].movement;
X            total_attacks -= 1;
X            continue;
X        }
X
X
X        if(to_target <= RANGE_MAIN && ogre.main_bats > 0) {
X            weight += unit[i].attack;
X            weight += 4 - unit[i].movement;
X            total_attacks -= 1;
X            continue;
X        }
X
X        if(to_target <= RANGE_SECONDARY && ogre.sec_bats > 0) {
X            weight += unit[i].attack;
X            weight += 4 - unit[i].movement;
X            total_attacks -= 1;
X            continue;
X        }
X
X        if(to_target <= RANGE_AP && ogre.ap > 0 && 
X	    (unit[i].type == INFANTRY || unit[i].type == CP)) {
X            weight += unit[i].attack;
X            weight += 4 - unit[i].movement;
X            total_attacks -= 1;
X            continue;
X        }
X
X    }
X
X/* make moving towards the CP a goal even in the face of crushing things */
X    weight += 40 *
X        (range(ogre.l_hex, ogre.r_hex, unit[0].l_hex, unit[0].r_hex)
X	    - range(a, b, unit[0].l_hex, unit[0].r_hex)) ;
X
X    if(off_map(a, b) || blocked(a, b)) weight = - INFINITY;
X/*
Xdisplay(17, "%d %d weight %d", a, b, weight); cycle();
X*/
X
X    return(weight);
X
X}
X
X#define INCR(i) i = (i == n_units - 1) ? 0 : i + 1
X
X#define MIN(a, b) (((a) > (b)) ? (a) : (b))
X
X/* 
X    Figure out who the Ogre will fire at. In this code, the "fired" element
X    of the unit description is the number of hit points assigned against that
X    unit.
X*/
Xassign_fire_ogre()
X{
X
X    int i, unitno, nmissiles, nlaunchers;
X
X    init_ogre_attack();
X
X    /*
X        The basic strategy here is to fire at the next unit in range. Since
X        the units are sorted by value, this will hopefully (although not 
X        always) result in reasonable choices for targets.
X        Experience indicates that the Ogre often overkills (which is OK)
X        but fails to attack some valuable possibility (not OK).  Some
X        work needs to be done here.
X    */
X
X    unitno = nextunit(RANGE_AP, 0);
X
X/*
X * The difference between this and the board game - the board game only
X * lets the ogre AP a hex once per turn, as opposed to once per unit.
X */
X    for(i = 0; i < ogre.ap; i++) {
X
X        if(unit[unitno].range_to_ogre <= RANGE_AP &&
X          (unit[unitno].type == CP || unit[unitno].type == INFANTRY)) {
X
X            unit[unitno].fired += ATK_AP;
X            display_attack("AP", unitno);
X
X        }
X        unitno = nextunit(RANGE_AP, unitno);
X
X    }
X
X    unitno = nextunit(RANGE_SECONDARY, unitno);
X
X    for(i = 0; i < ogre.sec_bats; i++) {
X
X        if(unit[unitno].range_to_ogre <= RANGE_SECONDARY) {
X
X            unit[unitno].fired += ATK_SECONDARY;
X            display_attack("secondary battery", unitno);
X
X        }
X        unitno = nextunit(RANGE_SECONDARY, unitno);
X
X    }
X
X    unitno = nextunit(RANGE_MAIN, unitno);
X
X    for(i = 0; i < ogre.main_bats; i++) {
X
X        if(unit[unitno].range_to_ogre <= RANGE_MAIN) {
X
X            unit[unitno].fired += ATK_MAIN;
X            display_attack("main battery", unitno);
X
X        }
X        unitno = nextunit(RANGE_MAIN, unitno);
X
X    }
X
X    unitno = nextunit(RANGE_LAUNCH, unitno);
X
X    nlaunchers = ogre.launchers;
X
X    for(i = 0; i < nlaunchers; i++) {
X
X        if(unit[unitno].status != DESTROYED &&
X	    /* don't fire at infantry... 27 Oct 83 */
X	    unit[unitno].type != INFANTRY && 
X            unit[unitno].range_to_ogre <= RANGE_LAUNCH) {
X
X            unit[unitno].fired += ATK_LAUNCH;
X            display_attack("launched missile", unitno);
X            disp_ogre_status(FALSE);
X
X        }
X        unitno = nextunit(RANGE_LAUNCH, unitno);
X
X    }
X
X    unitno = nextunit(RANGE_MISSILES, unitno);
X
X    nmissiles = ogre.missiles;
X
X    for(i = 0; i < nmissiles; i++) {
X
X        if(unit[unitno].status != DESTROYED &&
X	    /* don't fire at infantry... 27 Oct 83 */
X	    unit[unitno].type != INFANTRY && 
X            unit[unitno].range_to_ogre <= RANGE_MISSILES) {
X
X            unit[unitno].fired += ATK_MISSILES;
X            ogre.missiles -= 1;
X            display_attack("missile", unitno);
X            disp_ogre_status(FALSE);
X
X        }
X        unitno = nextunit(RANGE_MISSILES, unitno);
X
X    }
X
X}
X
X#include <stdio.h>
X 
Xcycle()
X{
X
X    fflush(stdout);
X    sleep(1);
X
X}
X
X/*
X    Display and resolve an attack on a single defending unit.
X*/
Xdisplay_attack(weapon, target)
Xchar *weapon;
Xint  target;
X{
X
X    /* No point if the unit is already destroyed. */
X    if(unit[target].status == DESTROYED) return;
X
X    display(16, "Ogre fires %s at unit at hex %d%d", weapon,
X        unit[target].l_hex, unit[target].r_hex);
X
X    movecur_hex(unit[target].l_hex, unit[target].r_hex);
X
X    cycle();
X
X    def_resolve(target);
X    display(16, "                                                    ");
X
X}
X
Xnextunit(range, unitno)
Xint range;
Xint unitno;
X{
X    int start;
X
X    start = unitno;
X    INCR(unitno);
X    while(unitno != start) {
X        if(range == 1) {
X            if(unit[unitno].status != DESTROYED &&
X                (unit[unitno].type == CP || unit[unitno].type == INFANTRY) &&
X                unit[unitno].range_to_ogre <= range)
X                return(unitno);
X        }
X        else {
X            if(unit[unitno].status != DESTROYED &&
X                unit[unitno].range_to_ogre <= range)
X                return(unitno);
X        }
X        INCR(unitno);
X    }
X
X    return(unitno);
X
X}
________This_Is_The_END________
echo 'x - ogres'
sed 's/^X//' <<'________This_Is_The_END________' >>ogres
X		MAIN	SEC	MISS 	LAUN	AP	TREAD
XOGRE I		1	0	0	0	2	15
XOGRE II		1	2	0	0	6	30
XOGRE III	1	4	2	0	8	45
XOGRE IV		2	4	2	0	8	45
XOGRE IV		1	4	0	2	8	45
XOGRE V		2	6	5	0	10	60
XOGRE VI		4	10	5	2	12	75
________This_Is_The_END________
echo 'x - ogrestat.c'
sed 's/^X//' <<'________This_Is_The_END________' >>ogrestat.c
X/*
X    Handle the Ogre status display.
X*/
X
X#include "ext.h"
X
Xdisp_ogre_status(redraw)
X
X/* If redraw is false, the display is not touched if nothing has changed. */
Xint redraw;
X{
X    static OGRE last;
X
X    /*
X        The Ogre status display occupies the bottom 6 lines of the display.
X    */
X
X    /*               0        1         2         3         4
X                     1234567890123456789012345678901234567890       */
X
X    if(redraw || last.main_bats != ogre.main_bats)
X        if(ogre.main_bats > 0)
X        display(17, "                             Main Batteries:      %d (4/3 D4)", ogre.main_bats);
X        else display(17, "                                                        ");
X
X    if(redraw || last.sec_bats != ogre.sec_bats)
X        if(ogre.sec_bats > 0)
X        display(18, "                             Secondary Batteries: %d (3/2 D3)", ogre.sec_bats);
X        else display(18, "                                                        ");
X
X    if(redraw || last.missiles != ogre.missiles)
X        if(ogre.missiles > 0)
X        display(19, "                             Missiles:            %d (6/5 D3)", ogre.missiles);
X        else display(19, "                                                        ");
X
X    if(redraw || last.launchers != ogre.launchers)
X        if(ogre.launchers > 0)
X        display(20, "                             Launchers:           %d (6/5 D3)", ogre.launchers);
X        else display(20, "                                                         ");
X
X    if(redraw || last.ap != ogre.ap)
X        if(ogre.ap > 0)
X        display(21, "                             Anti-personnel:     %2d (1/1 D1)", ogre.ap);
X        else display(21, "                                                        ");
X
X    if(redraw || last.treads != ogre.treads)
X        if(ogre.treads > 0)
X        display(22, "                             Treads:             %2d (1/* D1)", ogre.treads);
X        else display(22, "                                                        ");
X
X    if(redraw || last.movement != ogre.movement)
X        display(23, "                             Movement:            %d", ogre.movement);
X
X    copy(&last, &ogre, sizeof(last));
X
X}
X
Xcopy(to, from, size)
Xchar *to, *from;
Xint size;
X{
X    int i;
X
X    for(i = 0; i < size; i++) to[i] = from[i];
X
X}
X
________This_Is_The_END________
echo 'x - resolve.c'
sed 's/^X//' <<'________This_Is_The_END________' >>resolve.c
X/*
X    Resolve all attacks and rams from both directions.
X
X    Michael Caplinger, Rice University, March 1982.
X*/
X
X#include "ext.h"
X
Xstatic char *odd_names[] = {
X    "0/1",
X    "1/2",
X    "1/1",
X    "2/1",
X    "3/1",
X    "4/1",
X    "+",
X};
X
Xstatic char crt[6][7] = {
X
X    OK, OK,        OK,        OK,        DISABLED,  DISABLED,  DESTROYED,
X    OK, OK,        OK,        DISABLED,  DISABLED,  DESTROYED, DESTROYED,
X    OK, OK,        DISABLED,  DISABLED,  DESTROYED, DESTROYED, DESTROYED,
X    OK, OK,        DISABLED,  DESTROYED, DESTROYED, DESTROYED, DESTROYED,
X    OK, DISABLED,  DESTROYED, DESTROYED, DESTROYED, DESTROYED, DESTROYED,
X    OK, DESTROYED, DESTROYED, DESTROYED, DESTROYED, DESTROYED, DESTROYED,
X
X};
X
Xodds(attack, defend)
Xint attack, defend;
X{
X    int result;
X
X    result = (defend > 0) ? attack / defend + 1 : 6;
X
X    if(result > 6) result = 6;
X
X    if(result == 1)
X        result = (2 * attack < defend) ? 0 : 1;
X
X    return(result);
X
X}
X
Xchar *odd_str(attack, defend)
Xint attack, defend;
X{
X
X    return(odd_names[odds(attack, defend)]);
X
X}
X
X
X/* Resolve all attacks on the Ogre. */
Xogre_resolve(allocations)
XOGRE *allocations;
X{
X
X    display(16, "Resolving..."); cycle();
X
X    if(allocations -> missiles > 0) {
X        if(crt[roll()][odds(allocations -> missiles, DEF_MISSILES)] ==
X            DESTROYED) ogre.missiles -= 1;
X    }
X
X    if(allocations -> launchers > 0) {
X        if(crt[roll()][odds(allocations -> launchers, DEF_LAUNCH)] ==
X            DESTROYED) ogre.launchers -= 1;
X    }
X
X    if(allocations -> main_bats > 0) {
X        if(crt[roll()][odds(allocations -> main_bats, DEF_MAIN)] ==
X            DESTROYED) ogre.main_bats -= 1;
X    }
X
X    if(allocations -> sec_bats > 0) {
X        if(crt[roll()][odds(allocations -> sec_bats, DEF_SECONDARY)] ==
X            DESTROYED) ogre.sec_bats -= 1;
X    }
X
X    if(allocations -> ap > 0) {
X        if(crt[roll()][odds(allocations -> ap, DEF_AP)] ==
X            DESTROYED) ogre.ap -= 1;
X    }
X
X    if(allocations -> treads > 0) {
X        if(crt[roll()][odds(1, 1)] == DESTROYED)
X            decrease_treads(allocations -> treads);
X
X    }
X
X    /* erase the odds. */
X    movecur(17, 64); printf("              ");
X    movecur(18, 64); printf("              ");
X    movecur(19, 64); printf("              ");
X    movecur(20, 64); printf("              ");
X    movecur(21, 64); printf("              ");
X    movecur(22, 64); printf("              ");
X
X    /* update the Ogre status display. */
X    disp_ogre_status(FALSE);
X    check_over();
X}
X
X/* Resolve an Ogre attack on a defending unit. */
Xdef_resolve(i)
X{
X    char result;
X
X    if(unit[i].status != DESTROYED && unit[i].fired > 0) {
X
X        result = crt[roll()][odds(unit[i].fired, unit[i].defend)];
X
X        /* Infantry is a special case. */
X        if(unit[i].type == INFANTRY) {
X            if(result != OK)		/* Infantry is fragile */
X		unit[i].status = DESTROYED;
X            update_hex(unit[i].l_hex, unit[i].r_hex);
X	    return;
X            }
X
X        if(unit[i].type == BUNKER) {
X            if(result != DESTROYED)	/* Bunkers are tough! */
X		unit[i].status = OK;
X            update_hex(unit[i].l_hex, unit[i].r_hex);
X	    return;
X            }
X
X        switch(unit[i].status) {
X
X            case OK:
X                unit[i].status = result;
X                break;
X
X            case DISABLED:
X                if(result != OK) unit[i].status = DESTROYED;
X                break;
X
X        }
X
X        if(unit[i].status != OK) 
X            update_hex(unit[i].l_hex, unit[i].r_hex);
X
X    }
X
X}
X
Xroll()
X{
X
X    return(rand() % 6);
X
X}
X
X/* Routine called for each hex the Ogre moves through, to handle rams. */
Xogre_ram()
X{
X    int i, hit_infantry = FALSE;
X
X    /* Rule 5.03 */
X    for(i = 0; i < n_units; i++)
X        if(unit[i].l_hex == ogre.l_hex &&
X           unit[i].r_hex == ogre.r_hex &&
X           unit[i].status != DESTROYED)
X
X            switch(unit[i].type) {
X
X                case INFANTRY:
X
X                    /* Rule 5.04 */
X                    if(ogre.ap > 0 && !hit_infantry) {
X                        unit[i].status = DESTROYED ;
X			hit_infantry = TRUE ;
X                    }
X                    break;
X
X                default:
X
X                    /* Rule 5.031 */
X                    if(unit[i].movement == 0 || 
X                       unit[i].status == DISABLED) {
X                        unit[i].status = DESTROYED;
X                        decrease_treads( (unit[i].type == HVYTANK) ? 2 : 1);
X                        disp_ogre_status(FALSE);
X                    }
X                    else {
X                        unit[i].status = (roll() > 3) ? DESTROYED : DISABLED;
X                        decrease_treads( (unit[i].type == HVYTANK) ? 2 : 1);
X                        disp_ogre_status(FALSE);
X                    }
X                    break;
X
X            }
X
X
X}
X
X/* See if a defender has rammed the Ogre. */
Xdef_ram(i)
Xint i;
X{
X    if(unit[i].l_hex == ogre.l_hex &&
X       unit[i].r_hex == ogre.r_hex &&
X       unit[i].type != INFANTRY) {
X
X        /* Rule 5.036 */
X
X        decrease_treads(1);
X        unit[i].status = DESTROYED;
X        disp_ogre_status(FALSE);
X	disp_ogre() ;
X
X    }
X
X}
X
Xdecrease_treads(attack)
Xint attack;
X{
X
X    /* Rule 6.05 */
X
X    /* Now, where is the movement factor going? */
X
X    ogre.treads  -= attack;
X    ogre.movement = 0;
X    if(ogre.treads > 0)  ogre.movement = 1;
X    switch(mark){
X	case '0':
X    if(ogre.treads > 30) ogre.movement = 4;
X    if(ogre.treads > 20) ogre.movement = 3;
X    if(ogre.treads > 15) ogre.movement = 2;
X	case '7':
X    if(ogre.treads > 50) ogre.movement = 4;
X    if(ogre.treads > 30) ogre.movement = 3;
X    if(ogre.treads > 10) ogre.movement = 2;
X	case '8':
X    if(ogre.treads > 120) ogre.movement = 5;
X    if(ogre.treads > 100) ogre.movement = 4;
X    if(ogre.treads > 70) ogre.movement = 3;
X    if(ogre.treads > 50) ogre.movement = 2;
X	default:
X    if(ogre.treads > ogre.init_treads / 3) ogre.movement = 2;
X    if(ogre.treads > 2 * ogre.init_treads / 3) ogre.movement = 3;
X    }
X}
X
X
________This_Is_The_END________
echo 'x - termcap.c'
sed 's/^X//' <<'________This_Is_The_END________' >>termcap.c
X#include <sgtty.h>
X
X/*
X    Interface to termcap library.
X*/
X
Xchar    *BC, *UP;
Xchar    *eeolseq, *cmseq;
Xchar    *clearseq;
Xshort   ospeed;
Xint     putchar();
X
Xtc_setup() {
X
X    static  char    bp[1024];
X    static  char    buffer[1024];
X    char    *area = buffer;
X    char    *getenv();
X    char    *tgetstr();
X    char    *name;
X    int     retcode;
X
X    name = getenv("TERM");
X
X    retcode = tgetent(bp, name);
X
X    switch(retcode) {
X
X        case -1:
X            printf("can't open termcap file.\n");
X            exit(1);
X            break;
X
X        case 0:
X            printf("No termcap entry for %s.\n", name);
X            exit(1);
X            break;
X
X    }
X
X    eeolseq = tgetstr("ce", &area);
X    cmseq   = tgetstr("cm", &area);
X    clearseq = tgetstr("cl", &area);
X    BC   = tgetstr("bc", &area);
X    UP   = tgetstr("up", &area);
X
X}
X
Xeeol() {
X
X    tputs(eeolseq, 0, putchar);
X
X}
X
Xclear_screen() {
X
X    tputs(clearseq, 0, putchar);
X
X}
X
Xmovecur(row, col)
Xint row, col;
X{
X    char *tgoto() ;
X
X    tputs(tgoto(cmseq, col, row), 0, putchar);
X
X}
X
Xstruct sgttyb old_term;
Xstruct sgttyb new_term;
X
X/*
X    Set terminal to CBREAK and NOECHO.
X*/
Xset_term() {
X    static int  first = 1;
X
X    if(first) {
X        gtty(0, &old_term);
X        gtty(0, &new_term);
X
X        new_term.sg_flags &= ~(ECHO | XTABS); /* | CRMOD); */
X        new_term.sg_flags |= CBREAK;
X	
X	ospeed = new_term.sg_ospeed;
X
X        first = 0;
X    }
X
X    stty(0, &new_term);
X
X}
X
X/*
X    Reset the terminal to normal mode.
X*/
Xreset_term() {
X
X    stty(0, &old_term);
X
X}
X
________This_Is_The_END________
exit