empire sources (part 3 of 6)

Charles Simmons chuck at amdahl.uts.amdahl.com
Mon Apr 11 11:00:16 AEST 1988



# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# bugs display.c empire.h

echo x - bugs
sed -e 's/^X//' > "bugs" << '//E*O*F bugs//'
X/* %W% %G% %U% - (c) Copyright 1987, 1988 Chuck Simmons */
X
X/*
X *    Copyright (C) 1987, 1988 Chuck Simmons
X * 
X * See the file COPYING, distributed with empire, for restriction
X * and warranty information.
X */
X
XBugs
X----
X
X1)  The computer is allowed to leave armies in cities.  Fixing this
Xfeature might be difficult.  This feature also gives the computer
Xa small advantage which slightly helps overcome the natural superiority
Xof humans.
X
X2)  Once upon a time, if a fighter landed on a carrier, the user
Xwas never asked if she wanted to move it again.  I don't know if
Xthis bug still exists.
X
X3)  Satellites are not completely implemented.  When the user
Xmoves to a satellite, it should be allowed.  The user should
Xnot be asked if she "really wants to attack her own piece".
XEnemy satelites should not cause the user's pieces to be
Xawoken, since there is nothing the user can do.
X
X4)  If the computer has a damaged ship and is returning it to
Xport, the user can block the ship with another piece.  The computer
Xwill not attempt to move the damaged ship.  The user can then
Xsail up a transport to the city the damaged ship is heading toward,
Xunblock the damaged ship, and as soon as the damaged ship enters
Xport, take the city.  Since ships in port are capturable, the user
Xshould now own one slightly damaged ship.
X
X5)  An assertion failed in 'attack_obj'.  Somehow this routine
Xwas passed a location where there was no defending object.  This
Ximplies that a view map was messed up.  I've no idea why.
X
X6)  Currently, a fighter's range is not decremented if it is not
Xmoved during a turn.  This could be called a feature, but I think
XI would really prefer that a fighter's range was decremented by at
Xleast one each turn.  The computer does not take advantage of this
Xbug.
X
X7)  While playing a game, one of my cities was producing armies.
XAt one point in the game, the city sudddenly decided that never
Xagain would it increment the build count.  Actually, at one point
Xthe build count seemed to be negative.  The count eventually reached
Xzero and stayed there.  My hypothesis is that somewhere I'm trashing
Xmy data structures, and somehow the "owner" of the city got set to
Xsome incorrect value.
X
X(Note that bugs (5) and (7) occured while there was an inconsitency
Xin the 'kill_city' routine.  Hardware had its ownership modified,
Xbut it remained in the object list of the wrong user.  This
Xcould have caused some problems.  So potentially bugs 5 and 7 no
Xlonger exist.)
X
X8)  Movement of armies in "attack" mode seems a little strange.
X
X9)  Maybe in "sentry" mode, an army should wake up and go into "attack"
Xmode if an invader appears on the continent.  In any event, there
Xshould be some mechanism to allow a user to specify that an army
Xshould sit on the shore and wait for either a transport to pass by,
Xor for an invader to appear on the continent.
X
X10)  When setting a city function, the computer should prompt
Xfor the various pieces of input.  Even I have a hard time setting
Xfunctions for cities.
X
X
XCode Cleanup (Enhancements to improve performance or generality)
X----------------------------------------------------------------
X
X1)  How can we use minicurses?  minicurses is smaller and possibly
Xfaster than full blown curses.  The curses routines that I use
Xwhich are not part of minicurses are 'clrtoeol', 'getstr', and 'getch'.
XThese seem pretty fundamental, but I know very little about curses.
X
X2)  'vmap_cont' and 'vmap_mark_up_cont' would almost certainly be
Xfaster if we didn't recurse, but instead used something like the
Xperimeter lists used in all the other map scanning algorithms.
XSince 'vmap_mark_up_cont' takes about 10% of the processing time,
Xthe performance improvements could be significant.
X
X3)  The real speed killer is 'expand_perimeter'.  This routine
Xis very generalized, and not all the generality is always needed.
XIt might be better to write multiple non-general routines.  I believe
Xthis routine accounts for roughly 20% to 30% of the processing time.
XIf we take subroutines like 'strchr' and 'terrain_type' into account
Xas well, this routine accounts for more like 50% of the processing.
XHowever, on a mainframe, the game plays sufficiently fast.
X
X4)  Allow multiple computer players and/or multiple human players.
XAllow the players to come in over a network of workstations.
X
X5)  The width and height of the map should be parameters to the
Xprogram.
X
X6)  Interrupts should be caught.  When an interrupt is received,
Xthe user should be asked if she really wants to quit, and she
Xshould be warned if the game will not be saved.  This is particularly
Xuseful when playing over a noisy phone line that generates spurious
Xinterrupts.  (When will digitial telephone transmissions arrive?)
X
X7)  Storage for the various data structures should be allocated
Xdynamically instead of being stored in static tables.
X
X
XDebugging Aids
X--------------
X
X1)  My current debugging algorithm is to put the program into
Xdebug mode with the "++" command, and then put the program into
Xmovie mode with the "%" command.  When I see something wrong, I
Xhit the interrupt key and restart the program, so that I can
Xuse other debugging commands.  It would be nice if this interface
Xwas better.  (See comments above about catching interrupts.)
X
X2)  It would be nice if there were debugging commands which allowed
Xme to examine the computer map and request information such as
X"What is this city producing?  What objects are in this city? etc."
XThis would be very much like the edit mode "?" command.
X
X
XComputer Algorithm Enhancements
X-------------------------------
X
X1)  What improvements can be made to speed up the acquiring of
Xterritory by the computer?
X
XNote:  As a person, I can acquire about 1/2 the board (and control
X3/4 of the board) in about 150 turns.
XThe current algorithm seems to be a little bit slower, but within
Xthe same order of magnitude.
X
XObservations:
X
XI've implemented an algorithm which keeps the computer from exploring
Xevery little square of the world it comes across.  Building satellites
Xseems to slow down the computer.  The computer has an algorithm
Xfor unloading armies on interesting continents.
X
XA careful balance seems to be needed between the number of army
Xproducing cities and the number of tt producing cities.  Currently,
XI build a tt as soon as poosible.  On large
Xcontinents, this is a drawback, as the tt is built before armies
Xare ready to leave.  To counter this effect, I attempted to build
Xmore armies in other cities.  This causes an overproduction in
Xarmies after the first tt's fill up and head off to find something
Xto dump on.
X
XSuggestions:
X
XVarious minor improvements might be made in causing tt's to load
Xone or two turns faster, and to unload one or two turns faster.
XOther improvements would prevent two tt's from heading to the
Xsame destination.
X
XThis fix would probably go in 'transport_move' in 'compmove.c'.
XIn this routine, for a loading transport, we would count the
Xnumber of adjacent loading armies for the current cell, for each reachable
Xcell that is one away, and for each reachable cell that is two away.
XIf there were reachable loading armies, we would move the transport
Xto that square.  Otherwise we would use the current algorithm to
Xfind a destination for the transport and move the transport to that
Xdestination.
X
XFor unloading transports, things are perhaps slightly more difficult.
XI think what needs to be done here is, if the transport cannot move
Xalong a shortest path towards the destination, then the transport
Xshould attempt to move to an adjacent square which minimizes either
Xthe row distance between the tt and the objective, or the column
Xdistance between the tt and the objective.  For tie-breakers, the
Xtt would move to the cell which touched the most land.
X
XPossibly I should describe the problems that the above to tweaks
Xwould fix.  For loading armies, loading transports prefer moving to
Xstaying in place.  Thus, they will sometimes move from a square
Xthat touches lots of loading armies, to a square that touches very
Xfew loading armies.  This probably increases the load time by one
Xor two turns.
X
XFor unloading tt's, a tt will often be on a diagonal from a city
Xthat is an objective.  Unloading armies will hop off one at a time
Xbecause there is only one land square on a shortest path between the
Xtt and the city.  This particular case wastes about 4 moves.
X
X2)  The computer's algorithm is optimized for 70% water and
Xa smoothness of 5.  (More accurately, I developed the algorithm
Xusing these parameters for all of my testing and debugging.)
XPotentially the computer algorithm will be extremely poor for
Xother parameter values.  For example, the computer currently
Xbuilds transports at the first possible opportunity.  Transports
Xwould not be very useful on a world with only 10% water.  (Still,
Xthere are checks to prevent ships from being built in inappropriate
Xcities, so this may not be too much of a problem.)
X
XPotentially, the computer should use a more dynamic alogorithm
Xwhere it "notices" that certain kinds of pieces are going to be
Xneed in the near future and then builds these things.  I've no ideas
Xin this area for concrete algorithms, however.
X
XA plausible alternative would be for the computer to examine the
Xparameters supplied by the user.  If the user knows the parameters,
Xwhy shouldn't the computer?
X
X3)  The computer should be willing to land a fighter on a
Xcarrier if the carrier can be reached in one turn.
X
X4)  The computer should "track" user ships.  That is, whenever the
Xcomputer sees a user ship, it should keep a list of possible locations
Xwhere that ship could be.  It should then make some attempt to find
Xand destroy the ship.  (See "Search and Destroy" under the user
Xinterface comments.)
X
XThis code may be more trouble then its worth.  Currently, it appears
Xthat the computer does a very good job of destroying user shipping.
XThe reason for this is that there are good reasons for the user's
Xships to reappear where ships were previously seen.  Also, the
Xcomputer tends to amass great amounts of fire power when a ship
Xhas been seen, so the computer tends to bump into any other user
Xship that happens to be in the area.  Also, the user is looking for
Xthe computer's ships, and is moving lots of ships into the sealanes
Xthat the computer tends to use.
X
X
XUser Interface Enhancements
X---------------------------
X
X1)  In edit mode, it would be nice if it was easier to move around
Xthe screen.  (Mouse based approaches where the user points and clicks
Xto say "move this piece to here" would be real nice.)  One idea
Xwould be to allow the user to type in four digits that specify the
Xsquare to move to; or to type in two digits where the first digit
Xis the 10's row, and the second digit is the 10's column.  (Thus,
Xif the user typed "43", the cursor would be moved to location "4030".)
X
X2)  Small screens should not be redrawn so often.  When moving
Xpieces, we should move everything that is on the current screen
X(except for stuff that is real close to the edge of the screen,
Xbut not the edge of the board).  If necessary, we might redraw
Xthe screen as the user moved off the screen.  Or we could allow
Xthe user to explicitly tell us to redraw a new sector.  If the
Xscreen was redrawn, we would then work on moving pieces that were
Xdisplayed on the new screen.  In general, we only want to redraw
Xthe screen if we absolutely have to.  (This approach would also
Xbe real, real useful on terminals that are just a little bit smaller
Xthan the complete map.  Using a terminal with something like 105
Xcolumns will be extremely disconcerting.  The screen will be
Xredrawn for what seems like no reason at all.)
X
X3)  It is extremely difficult to tell when a satellite has gone
Xby, and when an enemy piece displayed on the screen is current,
Xand when the piece is a ghost.
X
XOne possibility would be to highlight enemy pieces that have just
Xbeen seen.  Another possibility would be for the user to type
Xa "?" when the cursor is on top of any enemy piece, and the displayed
Xinformation would be how long ago that piece was seen.  (Also, see
Xsearch and destroy tracking below.)
X
X4)  The user should be allowed to "zoom in" and "zoom out".  Zooming
Xin causes the playing board to be printed at four times the density
Xof the previous display density.  Thus, four squares would be
Xdrawn as a single square on the screen.  Zooming out undoes the
Xaffects of zooming in.  Actually, there should be multiple
Xlevels of zooming; 10 levels would probably more than suffice.
XThis enhancement allows the user to easily get a big picture of what
Xis going on.  Most of the time, the user would be able to play
Xwith the board zoomed in.  The user might sometimes need to zoom
Xout to navigate a ship through a "river" or an army over an isthmus.
X
XCurrently, there is a command to display a "zoomed" version of the
Xmap.  This command prints a compact display of the map that fits on
Xthe screen.  This is not quite the same as the above, because what
XI'm suggesting is that the user be allowed to make moves on a compact
Xdisplay of the map.
X
X5)  Search and Destroy.  Here is an idea for a sizeable modification
Xto the user interface.
X
XBasically, we want the computer to keep track of some information
Xfor the user.  The information is possible locations of enemy ships.
XWhen the user sees a ship on the screen, the computer would start
Xtracking the ship.
X
X(Tracking would be implemented as follows:  The initial location
Xof the ship would be stored in a perimeter list.  On each round,
Xthe perimeter list would be expanded to encompass all cells which
Xthe ship could have reached.  Cells that the user has seen this
Xturn are removed from the perimeter list.  After the user's turn,
Xcells that the user has seen are removed from the list again.
XProblems arise when a tracked ship moves into unexplored territory.)
X
XNow the user should be able to give various commands.  Commands
Xwould be things like:
X
X"Describe to me all ships you are tracking."  This command would
Xprint a list of ships being tracked, the types, the number of
Xpossible locations for the ship, the time the ship was first seen,
Xand any code used to represent that ship in tracking displays.
XPossibly, the likelihood that the ship has been destroyed would
Xbe displayed as well.
X
X"Display possible locations for a ship."  This command would
Xdisplay the possible locations for a ship.  Possible locations
Xmight be printed by highlighting the squares where the ship could
Xbe.
X
X"Stop tracking a ship."  This command would delete information about
Xa ship that the user assumed she had destroyed.  Note that the computer
Xwill sometimes be able to tell that a tracked ship has been destroyed.
XThe user might also give this command if a ship was presumed to have
Xgotten itself lost.  The computer might also stop tracking a ship if
Xthe number of possible locations for the ship gets large.
X
XTo support the above, the user should be able to place fighters
Xand ships in "Search and Destroy" mode.  Here the user would specify
Xa tracked ship that was to be searched for.  The fighters and ships of
Xthe user would move in such a way as to minimize the size of the
Xperimeter list for the tracked ship.
X
X5)  It has been suggested that all pieces at a location be moved
Xat once instead of skipping around the screen in the order the
Xpieces happen to be allocated.  For example, the user is often
Xasked what to do with each of the armies aboard a transport.  If
Xthe user knows there are five armies aboard, she may start hitting
Xthe 's' key to put those armies to sleep.  If the user isn't paying
Xenough attention, she may discover that she has just put to sleep
Xsome piece on a few squares away.
X
X6)  When moving a ship or army toward a destination, or when
Xmoving a ship toward port to be repaired, the user will often
Xwant to avoid land that might contain enemy pieces.  This functionality
Xis partially implemented in that ships prefer to be at sea if there
Xis nothing to explore.  Pieces moving towards a destination also
Xprefer to move so that they are in the middle of all the shortest
Xpaths to the destination.
X
XDespite this, it might be desirable to implement a movement mode
Xwhereby ships went out of there way to avoid the enemy.
X
X7)  It should be possible for the user to obtain information about
Xpieces which are contained within another piece.  For example,
Xit would be nice to know the movement function of every ship
Xcontained in a city, or of every army on a transport.
X
X8)  The big problem...  The user needs to type one hell of a lot
Xof commands to control the movement of her pieces.  I've implemented
Xa lot of stuff to alleviate this problem, but lots more can be
Xdone.  If we assume that everything is implemented as a "movement
Xfunction", the following movement functions would be interesting:
X
X"load army" -- an army moves toward the nearest loading transport
Xor transport producing city.  Note that this is the same algorithm
Xas that used by the computer.
X
X(For armies, there are really only
Xthree functions that are needed:  "attack" (which is implemented)
Xwhere the army explores a continent and attackes the enemy or
Xunowned cities; "load" where armies leave a continent; and "unload"
Xwhere armies leave a boat for some other continent.  Also note that
Xwhen I play the game, most of the commands that I give are commands
Xto move the army to a place where a transport will pick up the army,
Xcommands to have the army wait for the transport and load, commands
Xto put the army to sleep while it is being transported, and command
Xto wake up and unload the armies.)
X
X"load transport" -- the transport is marked as "loading", and the
Xtransport moves toward the nearest loading army.
X
X"unload army" -- I'm not sure what this does, nor what "unload
Xtransport" does.  Basically, I want some pseudo-intelligent mechanism
Xfor telling the computer not to ask me questions about armies on
Xa transport until that transport reaches "something interesting".
X"load army" and "load transport" would be much easier to implement.
XUnloading is where intelligence and strategy can be important.
X
X"patrol" -- This causes a piece to move so as to decrease the
Xlikelihood that an enemy piece can sneak by.  One method of implementing
Xthis would be for the piece to move toward the square two away that
Xhad been least recently seen.  It might be desirable to constrain
Xa patrolling piece to a relatively small area of the board.
X
XNote that the "Grope" command (or "explore" mode) is no longer of
Xmuch use for armies.  Possibly "attack" mode would be useful for
Xships and fighters.
X
X9)  One possibility for all of the above might be to allow the
Xuser to specify some algorithm that describes how pieces should
Xmove.  I've thought along the lines of letting the user specify
Xsome sort of macro, and letting the user specify the arguments
Xto one of the 'vmap_find_*obj' routines.  This might require the
Xability for the user to place arbitrary labels on any square.
X
X
XGame Modifications
X------------------
X
X1)  Mobile repair platforms.  Currently a damaged boat moves very
Xslowly towards the nearest city.  A floating platform that could move
Xtowards damaged boats might be useful.  Also, this little baby would
Xstay out of cities and so not be capturable.  Hits would be 1; strength
Xzero; and speed might be greater than 2.
X
X2)  Setting transports to have a strength of zero might be interesting.
X
X3)  Implementing the world as a torus instead of a rectangle might
Xbe better.  This means having the map wrap at the edges instead of
Xterminating at the edges.
X
X4)  Increase the "logistics" aspects of the game.  What about
Xoil, iron, food, etc?  Oil might be used to determine the range
Xof a boat or ship.  Armies might starve without food.  Iron might
Xbe necessary for building a ship.
X
X5)  One of my goals has been to define lots of highly specialized
Xpieces so that each type of piece must be built and used in order
Xto have an effective strategy.  In the original game of empire,
XI eventually developed a strategy whereby the only pieces I would
Xbuild were armies and transports.  The computer basically couldn't
Xbeat me unless we both started on the same continent and it lucked out.
XThe game also ended within one hundred turns.
X
XNow, eventually, I might decide that the current program also has
Xthe same faults (in which case I'll tweak the computer movement
Xalgorithms so that it plays differently).
X
XHowever, I have been making changes to increase the specialization
Xof all the pieces.
X
XObviously, armies must be built because they are the only pieces that
Xcan capture cities.
X
XObviously, transports must be built (on worlds that have a reasonable
Xamount of water) because that's the only way an army can be carried
Xto another city.  Since transports don't move all that fast, and
Xsince transports are fairly weak, they aren't good for much else
X(in theory).
X
XBeyond this...  Patrol boats and fighters are very similar.  Both
Xare fast, both are quickly produced, both have low hits.
XI suspect that an effective strategy could be developed where one
Xor the other of these pieces, but not necessarily both, were built.
XPatrol boats have an advantage in their unlimited range.  This makes
Xthem useful for extremely long range exploration.  Fighters have
Xan advantage in their great speed.  This makes them extremely useful
Xfor tracking and patrolling.  Fighters also have a sufficient range
Xthat they can easily move across the board from one city to another
Xwithout really needing carriers.  Possibly, the range of fighters
Xis too great.  Possibly, the range of fighters should be 16.
X(For purposes of user friendliness, the range of fighters should be
Xa multiple of the speed.)
X
XNow, carriers, destroyers, subs, and battleships are very similar.
XCarriers and battleships have the advantage that they can take a
Xbeating and then be reparied.  Destroyers and subs have the advantage
Xthat lots of them can be produced which increases the amount of
Xterritory that can be seen at any time.
X
XDecreasing the range of fighters might increase the utility of
Xcarriers, but then the user would probably build more patrol boats
Xinstead.
X
XSo, I guess I'm looking for more specialized pieces.  Mobile
Xrepair platforms are one idea.  Satellites are an attempt at
Xa second idea, but this idea needs more refinement.  Currently,
Xthe computer does just fine without building satellites (as near
Xas I can tell).  Maybe satellites would be more useful if they
Xwere faster or scanned a larger area.
X
X
XUser Comments
X-------------
X> empire is getting very good about asking me about all the troups on a transport,
X> etc. before going on to another piece, but its still not perfect.
X> 
X> the computer still seems to be spending too much effort fighting, and not enough
X> exploring.  i think i've got it beat, although i'm not sure yet.  i was burning
X> transport after transport (of the computers) while he tried to take an island
X> from me.  he finally succeeded, but i must have killed 8 transports in the
X> process (he got two of mine).
X> 
X> early in the game, he had a real superiority with patrol boats, that was giving
X> me fits.  but now i think i've got him, and am making it very hard for him to
X> move around.  also, he still hasn't finished taking islands he's colonized--
X> hopefully i'll be able to take some away from him.  he should have consolidated
X> them long ago, and being harassing me.
X> 
X> The satellite is fun, although i wish it would head into enemy territory
X> instead of back into mine.
X
XThe first paragraph is a request that all pieces of a type in
Xone position be moved before moving pieces of that type at
Xanother position.  This fix should be combined with the needed fix
Xto move all pieces on the screen before redrawing the screen.
X
XThe second paragraph suggests to me that the computer should
Xmove lots of patrol boats and other support craft into an area
Xto clear it out before moving in transports.  The transports are
Xtoo vulnerable, and the computer isn't defending them very well.
XMaybe what I mean here is that the computer should have a concept
Xof "escorts".  When moving a transport, a destroyer, sub, or at
Xleast a patrol boat should try and remain near by.  Then if our
Xtransport gets destroyed by an enemy, at least there is some chance
Xthat we can kill off the attacker.
X
XOther problems probably exist in this area as well.  Early in the
Xgame, the computer will see an unowned city and drop some armies on
Xit.  A little later the computer will notice that there is a user
Xcity on the same continent.  Now, all the computer's transports
Xgo floating around that user city and dump armies on it.  The computer
Xhas used massive amounts of resources to take a continent instead
Xof exploring and sweeping up more easily defended continents.
X
XOn the other hand, the computer is very "contentious".  It's kind of
Xfun to have the computer fighting so hard to keep me from taking its
Xcities.  Also, if I don't use the current strategy, there is a danger
Xthat the computer will not fight hard enough to keep the user from
Xinvading and taking a computer-owned continent.
X
XColonization...  The computer takes new continents very slowly.
XI don't know why.  The computer should be producing armies in
Xthe first city it takes, and the computer will produce armies
Xin new cities as long as it sees an unowned city to attack.
XPotentially, there is a problem in that the computer might not
Xsee an unowned city, even though there is lots of unexplored territory,
Xand thus probably an unowned city, on the continent.
X
XThe bigger problem seems to be that the computer is producing too
Xmany armies and not enough other stuff.  In the particular game that
Xthese comments derived from, the computer had a massive continent
Xthat was smothered in armies.  Instead of producing so many armies,
Xthe computer should have produced more fighters and non-transport
Xships.  Tweaking the "ration?" arrays in compmove.c should make things
Xbetter.
X
XNote that the user's strategy was to seek and destroy transports.
XThe user would ignore other ships for relatively long periods of
Xtime for a chance to destroy one of the computer's transports.  This
Xstrategy was quite effective; the user tended to be able to keep
Xmany more transports on the board than the computer.
X
X> planes aren't that useful even as they are--sure they're good for zooming
X> in and destroying the odd troop transport, but they're not that helpful for
X> exploration.  i still suspect the optimal strategy is armies, transports,
X> and patrol boats, with a few planes.  Later in the game planes become
X> useful because they can be gotten to the scene so quickly.   If you want
X> to reduce them, how about reducing them to 24?   Also, when a plane is
X> about to fly past the point of no return (return to anything) how about
X> a question, a la "troops can't walk on water, Sir?".  as long as i can
X> override the objection, its not a problem.
X
X> oh, i think it would suffice to be able to launch satellites in a particular
X> direction.
X
XThe first paragraph is a response to my suggestion that a fighter's
Xrange should be reduced to 16 so as to make patrol boats and carriers
Xmore useful.
X
XMaybe we should crank up the hits on the various objects.  This
Xwould make attacks a little more deterministic.  For example:
X
Xarmies: 2               armies 10
Xtransports: 2           transports 10
Xfighters: 2             fighters 10
Xpatrol boats: 2         patrol boats 10
Xsubmarines: 4           submarines 20
Xdestoyers: 6            destroyers 30
Xcarriers: 10            carriers 80
Xbattleships: 12         battleships 100
X
XBut then we would have to worry about repairing armies?  Or maybe
Xthe effectiveness of an army simply goes down when it doesn't have
Xfull hit points?  This would also greatly increase the repair time
Xof an object.  Or maybe objects would be repaired two or 10 hits
Xper turn.
X
XOther bugs...
X-------------
X
XPossibly displayed messages should be of two types:  Important messages
Xand non-important messages.  After an important message, the computer
Xwould delay for the full amount of delay time.  After an unimportant
Xmessage, it might not do anything.
X
X
X1)  The "m" and "n" commands should work in movement mode.
XThey should also work when setting the function of a piece
Xfor a city.
X
X2)  Should there be a way to tell the program you are done
Xattempting to move a fighter, and don't ask me about moves
Xseven more times?
X
X3)  The program should use environment variables or command line
Xarguments to supply the filenames for "empsave.dat" and "empmovie.dat".
XA command line argument would also be useful for telling the
Xprogram how often the game should be saved.  Actually, all
Xcommand line arguments should have associated environment variables
Xthat can be used to set defaults.
X
X4)  When the user types "q" to quit, the program should exit
Ximmediately if the game has been saved.  If the game hasn't been
Xsaved, the user should be told, and asked if she really wants to
Xquit.
//E*O*F bugs//

echo x - display.c
sed -e 's/^X//' > "display.c" << '//E*O*F display.c//'
X/* %W% %G% %U% - (c) Copyright 1987, 1988 Chuck Simmons */
X
X/*
X *    Copyright (C) 1987, 1988 Chuck Simmons
X * 
X * See the file COPYING, distributed with empire, for restriction
X * and warranty information.
X */
X
X/*
Xdisplay.c -- This file contains routines for displaying sectors and
Xmoving the cursor about in a sector.  We need to remember the following
Xinformation:
X
X	the current map portion displayed on the screen;
X
X	whether the displayed portion is from the user's or the computer's
X	point of view;
X*/
X
X#ifdef SYSV
X#include <string.h>
X#else
X#include <strings.h>
X#endif
X
X#include <curses.h>
X#include "empire.h"
X#include "extern.h"
X
Xstatic int whose_map = UNOWNED; /* user's or computer's point of view */
Xstatic int ref_row; /* map loc displayed in upper-left corner */
Xstatic int ref_col;
Xstatic int save_sector; /* the currently displayed sector */
Xstatic int save_cursor; /* currently displayed cursor position */
Xstatic int change_ok = TRUE; /* true if new sector may be displayed */
X
X/*
XThis routine is called when the current display has been
Xtrashed and no sector is shown on the screen.
X*/
X
Xvoid kill_display () {
X	whose_map = UNOWNED;
X}
X
X/*
XThis routine is called when a new sector may be displayed on the
Xscreen even if the location to be displayed is already on the screen.
X*/
X
Xvoid sector_change () {
X	change_ok = TRUE;
X}
X
X/*
XReturn the currently displayed user sector, if any.  If a user
Xsector is not displayed, return -1.
X*/
X
Xint cur_sector () {
X	if (whose_map != USER) return (-1);
X	return (save_sector);
X}
X
X/*
XReturn the current position of the cursor.  If the user's map
Xis not on the screen, we return -1.
X*/
X
Xlong cur_cursor () {
X	if (whose_map != USER) return (-1);
X	return (save_cursor);
X}
X
X/*
XDisplay a location on the screen. We figure out the sector the
Xlocation is in and display that sector.  The cursor is left at
Xthe requested location.
X
XWe redisplay the sector only if we either have been requested to
Xredisplay the sector, or if the location is not on the screen.
X*/
X
Xvoid
Xdisplay_loc (whose, vmap, loc)
Xint whose; /* whose map to display */
Xview_map_t vmap[];
Xlong loc; /* location to display */
X{
X	void print_sector(), show_loc();
X	
X	if (change_ok || whose != whose_map || !on_screen (loc))
X		print_sector (whose, vmap, loc_sector (loc));
X		
X	show_loc (vmap, loc);
X}
X
X/*
XDisplay a location iff the location is on the screen.
X*/
X
Xvoid
Xdisplay_locx (whose, vmap, loc)
Xint whose; /* whose map to display */
Xview_map_t vmap[];
Xlong loc; /* location to display */
X{
X	if (whose == whose_map && on_screen (loc))
X		show_loc (vmap, loc);
X}
X
X/*
XDisplay a location which exists on the screen.
X*/
X
Xvoid
Xshow_loc (vmap, loc)
Xview_map_t vmap[];
Xlong loc;
X{
X	int r, c;
X	
X	r = loc_row (loc);
X	c = loc_col (loc);
X	(void) move (r-ref_row+NUMTOPS, c-ref_col);
X	(void) addch ((chtype)vmap[loc].contents);;
X	save_cursor = loc; /* remember cursor location */
X	(void) move (r-ref_row+NUMTOPS, c-ref_col);
X}
X
X/*
XPrint a sector of the user's on the screen.  If it is already displayed,
Xwe do nothing.  Otherwise we redraw the screen.  Someday, some intelligence
Xin doing this might be interesting.  We heavily depend on curses to update
Xthe screen in a reasonable fashion.
X
XIf the desired sector
Xis not displayed, we clear the screen.  We then update the screen
Xto reflect the current map.  We heavily depend on curses to correctly
Xoptimize the redrawing of the screen.
X
XWhen redrawing the screen, we figure out where the
Xcenter of the sector is in relation to the map.  We then compute
Xthe screen coordinates where we want to display the center of the
Xsector.  We will remember the sector displayed, the map displayed,
Xand the map location that appears in the upper-left corner of the
Xscreen.
X*/
X 
Xvoid
Xprint_sector (whose, vmap, sector)
Xchar whose; /* USER or COMP */
Xview_map_t vmap[]; /* map to display */
Xint sector; /* sector to display */
X{
X	void display_screen();
X
X	int first_row, first_col, last_row, last_col;
X	int display_rows, display_cols;
X	int r, c;
X
X	save_sector = sector; /* remember last sector displayed */
X	change_ok = FALSE; /* we are displaying a new sector */
X
X	display_rows = lines - NUMTOPS - 1; /* num lines to display */
X	display_cols = cols - NUMSIDES;
X
X	/* compute row and column edges of sector */
X	first_row = sector_row (sector) * ROWS_PER_SECTOR;
X	first_col = sector_col (sector) * COLS_PER_SECTOR;
X	last_row = first_row + ROWS_PER_SECTOR - 1;
X	last_col = first_col + COLS_PER_SECTOR - 1;
X
X	if (!(whose == whose_map /* correct map is on screen? */
X	   && ref_row <= first_row /* top row on screen? */
X	   && ref_col <= first_col /* first col on screen? */
X	   && ref_row + display_rows - 1 >= last_row /* bot row on screen? */
X	   && ref_col + display_cols - 1 >= last_col)) /* last col on screen? */
X	(void) clear (); /* erase current screen */
X
X	/* figure out first row and col to print; subtract half
X	   the extra lines from the first line */
X
X	ref_row = first_row - (display_rows - ROWS_PER_SECTOR) / 2;
X	ref_col = first_col - (display_cols - COLS_PER_SECTOR) / 2;
X
X	/* try not to go past bottom of map */
X	if (ref_row + display_rows - 1 > MAP_HEIGHT - 1)
X		ref_row = MAP_HEIGHT - 1 - (display_rows - 1);
X
X	/* never go past top of map */
X        if (ref_row < 0) ref_row = 0;
X
X	/* same with columns */
X	if (ref_col + display_cols - 1 > MAP_WIDTH - 1)
X		ref_col = MAP_WIDTH - 1 - (display_cols - 1);
X
X	if (ref_col < 0) ref_col = 0;
X
X        whose_map = whose; /* remember whose map is displayed */
X	display_screen (vmap);
X
X	/* print x-coordinates along bottom of screen */
X	for (c = ref_col; c < ref_col + display_cols && c < MAP_WIDTH; c++)
X	if (c % 10 == 0) {
X		pos_str (lines-1, c-ref_col, "%d", c);
X	}
X	/* print y-coordinates along right of screen */
X	for (r = ref_row; r < ref_row + display_rows && r < MAP_HEIGHT; r++) {
X		if (r % 2 == 0)
X			pos_str (r-ref_row+NUMTOPS, cols-NUMSIDES+1, "%2d", r);
X		else pos_str (r-ref_row+NUMTOPS, cols-NUMSIDES+1, "  ");
X	}
X	/* print round number */
X	(void) sprintf (jnkbuf, "Sector %d Round %d", sector, date);
X	for (r = 0; jnkbuf[r] != '\0'; r++) {
X		if (r+NUMTOPS >= MAP_HEIGHT) break;
X		(void) move (r+NUMTOPS, cols-NUMSIDES+4);
X		(void) addch ((chtype)jnkbuf[r]);
X	}
X}
X
X/*
XDisplay the portion of the map that appears on the screen.
X*/
X
Xvoid display_screen (vmap)
Xview_map_t vmap[];
X{
X	int display_rows, display_cols;
X	int r, c;
X	long t;
X
X	display_rows = lines - NUMTOPS - 1; /* num lines to display */
X	display_cols = cols - NUMSIDES;
X
X	for (r = ref_row; r < ref_row + display_rows && r < MAP_HEIGHT; r++)
X	for (c = ref_col; c < ref_col + display_cols && c < MAP_WIDTH; c++) {
X		t = row_col_loc (r, c);
X		(void) move (r-ref_row+NUMTOPS, c-ref_col);
X		(void) addch ((chtype)vmap[t].contents);;
X	}
X}
X
X/*
XMove the cursor in a specified direction.  We return TRUE if the
Xcursor remains in the currently displayed screen, otherwise FALSE.
XWe display the cursor on the screen, if possible.
X*/
X
Xint
Xmove_cursor (cursor, offset)
Xlong *cursor; /* current cursor position */
Xint offset; /* offset to add to cursor */
X{
X	long t;
X	int r, c;
X 
X	t = *cursor + offset; /* proposed location */
X	if (!map[t].on_board) return (FALSE); /* trying to move off map */
X	if (!on_screen (t)) return (FALSE); /* loc is off screen */
X	
X	*cursor = t; /* update cursor position */
X	save_cursor = *cursor;
X	       
X	r = loc_row (save_cursor);
X	c = loc_col (save_cursor);
X	(void) move (r-ref_row+NUMTOPS, c-ref_col);
X       
X	return (TRUE);
X}
X
X/*
XSee if a location is displayed on the screen.
X*/
X
Xint on_screen (loc)
Xlong loc;
X{
X	int new_r, new_c;
X	
X	new_r = loc_row (loc);
X	new_c = loc_col (loc);
X
X	if (new_r < ref_row /* past top of screen */
X	 || new_r - ref_row > lines - NUMTOPS - 1 /* past bot of screen? */
X	 || new_c < ref_col /* past left edge of screen? */
X	 || new_c - ref_col > cols - NUMSIDES) /* past right edge of screen? */
X	return (FALSE);
X
X	return (TRUE);
X}
X
X/* Print a view map for debugging. */
X
Xvoid
Xprint_xzoom (vmap)
Xview_map_t *vmap;
X{
X	print_zoom (vmap);
X#if 0
X	prompt ("Hit a key: ");
X	(void) get_chx (); /* wait for user */
X#endif
X}
X
X/*
XPrint a condensed version of the map.
X*/
X
Xchar zoom_list[] = "XO*tcbsdpfaTCBSDPFAzZ+. ";
X
Xvoid
Xprint_zoom (vmap)
Xview_map_t *vmap;
X{
X	void print_zoom_cell();
X
X	int row_inc, col_inc;
X	int r, c;
X
X	kill_display ();
X
X	row_inc = (MAP_HEIGHT + lines - NUMTOPS - 1) / (lines - NUMTOPS);
X	col_inc = (MAP_WIDTH + cols - 1) / (cols - 1);
X
X	for (r = 0; r < MAP_HEIGHT; r += row_inc)
X	for (c = 0; c < MAP_WIDTH; c += col_inc)
X	print_zoom_cell (vmap, r, c, row_inc, col_inc);
X
X	pos_str (0, 0, "Round #%d", date);
X	
X	(void) refresh ();
X}
X
X/*
XPrint a single cell in condensed format.
X*/
X
Xvoid
Xprint_zoom_cell (vmap, row, col, row_inc, col_inc)
Xview_map_t *vmap;
Xint row, col;
Xint row_inc, col_inc;
X{
X	int r, c;
X	char cell;
X
X	cell = ' ';
X	for (r = row; r < row + row_inc; r++)
X	for (c = col; c < col + col_inc; c++)
X	if (strchr (zoom_list, vmap[row_col_loc(r,c)].contents)
X		< strchr (zoom_list, cell))
X	cell = vmap[row_col_loc(r,c)].contents;
X	
X	(void) move (row/row_inc + NUMTOPS, col/col_inc);
X	(void) addch ((chtype)cell);
X}
X
X/*
XPrint a condensed version of a pathmap.
X*/
X
Xvoid
Xprint_pzoom (s, pmap, vmap)
Xchar *s;
Xpath_map_t *pmap;
Xview_map_t *vmap;
X{
X	void print_pzoom_cell();
X
X	int row_inc, col_inc;
X	int r, c;
X
X	kill_display ();
X
X	row_inc = (MAP_HEIGHT + lines - NUMTOPS - 1) / (lines - NUMTOPS);
X	col_inc = (MAP_WIDTH + cols - 1) / (cols - 1);
X
X	for (r = 0; r < MAP_HEIGHT; r += row_inc)
X	for (c = 0; c < MAP_WIDTH; c += col_inc)
X	print_pzoom_cell (pmap, vmap, r, c, row_inc, col_inc);
X
X	prompt (s);
X	(void) get_chx (); /* wait for user */
X	
X	(void) refresh ();
X}
X
X/*
XPrint a single cell of a pathmap in condensed format.
XWe average all squares in the cell and take the mod 10 value.
XSquares with a value of -1 are printed with '-', squares with
Xa value of INFINITY/2 are printed with 'P', and squares with
Xa value of INFINITY are printed with 'Z'.  Squares with a value
Xbetween P and Z are printed as U.
X*/
X
Xvoid
Xprint_pzoom_cell (pmap, vmap, row, col, row_inc, col_inc)
Xpath_map_t *pmap;
Xview_map_t *vmap;
Xint row, col;
Xint row_inc, col_inc;
X{
X	int r, c;
X	int sum, d;
X	char cell;
X
X	sum = 0;
X	d = 0; /* number of squares in cell */
X	
X	for (r = row; r < row + row_inc; r++)
X	for (c = col; c < col + col_inc; c++) {
X		sum += pmap[row_col_loc(r,c)].cost;
X		d += 1;
X	}
X	sum /= d;
X	
X	if (pmap[row_col_loc(row,col)].terrain == T_PATH) cell = '-';
X	else if (sum < 0) cell = '!';
X	else if (sum == INFINITY/2) cell = 'P';
X	else if (sum == INFINITY) cell = ' ';
X	else if (sum > INFINITY/2) cell = 'U';
X	else {
X		sum %= 36;
X		if (sum < 10) cell = sum + '0';
X		else cell = sum - 10 + 'a';
X	}
X	
X	if (cell == ' ')
X		print_zoom_cell (vmap, row, col, row_inc, col_inc);
X	else {
X		(void) move (row/row_inc + NUMTOPS, col/col_inc);
X		(void) addch ((chtype)cell);
X	}
X}
X
X/*
XDisplay the score off in the corner of the screen.
X*/
X
Xvoid
Xdisplay_score ()
X{
X	pos_str (0, cols-12, " User  Comp");
X	pos_str (1, cols-12, "%5d %5d", user_score, comp_score);
X}
//E*O*F display.c//

echo x - empire.h
sed -e 's/^X//' > "empire.h" << '//E*O*F empire.h//'
X/* %W% %G% %U% - (c) Copyright 1987, 1988 Chuck Simmons */
X
X/*
X *    Copyright (C) 1987, 1988 Chuck Simmons
X * 
X * See the file COPYING, distributed with empire, for restriction
X * and warranty information.
X */
X
X/*
Xempire.h -- type and constant declarations
X*/
X
X#ifndef TRUE
X#define TRUE 1
X#define FALSE 0
X#endif
X
X#ifndef NULL
X#define NULL 0
X#endif
X
X/* Redefine some functions for portability. */
X
X#ifndef SYSV
X#define memcpy(dst,src,len) bcopy((src),(dst),(len))
X#define strchr(s,c) index(s,c)
Xtypedef char chtype;
X#define beep() (putchar('\7'))
X#define napms(d) (usleep((d)*1000))
X#else
Xchar *memset();
Xchar *memcpy();
X#define bzero(dst,len) memset(dst,0,len)
X#endif
X
Xtypedef unsigned char uchar;
X
X#define ASSERT(x) if (!(x)) assert ("x", __FILE__, __LINE__);
X#define ABORT assert ("aborting", __FILE__, __LINE__)
X
X/* directions one can move */
X#define NORTH 0
X#define NORTHEAST 1
X#define EAST 2
X#define SOUTHEAST 3
X#define SOUTH 4
X#define SOUTHWEST 5
X#define WEST 6
X#define NORTHWEST 7
X
X#define NUMTOPS 3 /* number of lines at top of screen for messages */
X#define NUMSIDES 6 /* number of lines at side of screen */
X#define STRSIZE 80 /* number of characters in a string */
X
X/* Information we maintain about cities. */
X
X#define NUM_CITY 70
X#define UNOWNED 0
X#define USER 1
X#define COMP 2
X
X/* Piece types. */
X#define ARMY 0
X#define FIGHTER 1
X#define PATROL 2
X#define DESTROYER 3
X#define SUBMARINE 4
X#define TRANSPORT 5
X#define CARRIER 6
X#define BATTLESHIP 7
X#define SATELLITE 8
X#define NUM_OBJECTS 9 /* number of defined objects */
X#define NOPIECE ((char)255) /* a 'null' piece */
X
X#define LIST_SIZE 5000 /* max number of pieces on board */
X
Xtypedef struct city_info {
X	long loc; /* location of city */
X	uchar owner; /* UNOWNED, USER, COMP */
X	long func[NUM_OBJECTS]; /* function for each object */
X	long work; /* units of work performed */
X	char prod; /* item being produced */
X} city_info_t;
X
X/*
XTypes of programmed movement.  Use negative numbers for special
Xfunctions, use positive numbers to move toward a specific location.
X*/
X
X#define NOFUNC -1	/* no programmed function */
X#define RANDOM -2	/* move randomly */
X#define SENTRY -3	/* sleep */
X#define FILL -4         /* fill transport */
X#define LAND -5         /* land fighter at city */
X#define EXPLORE -6      /* piece explores nearby */
X#define ARMYLOAD -7     /* army moves toward and boards a transport */
X#define ARMYATTACK -8   /* army looks for city to attack */
X#define TTLOAD -9       /* transport moves toward loading armies */
X#define REPAIR -10      /* ship moves toward port */
X#define WFTRANSPORT -11 /* army boards a transport */
X#define MOVE_N -12      /* move north */
X#define MOVE_NE -13     /* move northeast */
X#define MOVE_E -14      /* move east */
X#define MOVE_SE -15     /* move southeast */
X#define MOVE_S -16      /* move south */
X#define MOVE_SW -17     /* move southwest */
X#define MOVE_W -18      /* move west */
X#define MOVE_NW -19     /* move northwest */
X
X/* Index to list of function names. */
X#define FUNCI(x) (-(x)-1)
X
X/*
XMacro to convert a movement function into a direction.
X*/
X
X#define MOVE_DIR(a) (-(a)+MOVE_N)
X
X/*
XInformation we maintain about each piece.
X*/
X
Xtypedef struct { /* ptrs for doubly linked list */
X	struct piece_info *next; /* pointer to next in list */
X	struct piece_info *prev; /* pointer to prev in list */
X} link_t;
X
Xtypedef struct piece_info {
X	link_t piece_link; /* linked list of pieces of this type */
X	link_t loc_link; /* linked list of pieces at a location */
X	link_t cargo_link; /* linked list of cargo pieces */
X	int owner; /* owner of piece */
X	int type; /* type of piece */
X	long loc; /* location of piece */
X	long func; /* programmed type of movement */
X	short hits; /* hits left */
X	int moved; /* moves made */
X	struct piece_info *ship; /* pointer to containing ship */
X	struct piece_info *cargo; /* pointer to cargo list */
X	short count; /* count of items on board */
X	short range; /* current range (if applicable) */
X} piece_info_t;
X
X/*
XMacros to link and unlink an object from a doubly linked list.
X*/
X
X#define LINK(head,obj,list) { \
X	obj->list.prev = NULL; \
X	obj->list.next = head; \
X	if (head) head->list.prev = obj; \
X	head = obj; \
X}
X
X#define UNLINK(head,obj,list) { \
X	if (obj->list.next) \
X		obj->list.next->list.prev = obj->list.prev; \
X        if (obj->list.prev) \
X		obj->list.prev->list.next = obj->list.next; \
X        else head = obj->list.next; \
X	obj->list.next = NULL; /* encourage mem faults in buggy code */ \
X	obj->list.prev = NULL; \
X}
X
X/* macros to set map and list of an object */
X#define MAP(owner) ((owner) == USER ? user_map : comp_map)
X#define LIST(owner) ((owner) == USER ? user_obj : comp_obj)
X
X/* macro to step through adjacent cells */
X#define FOR_ADJ(loc,new_loc,i) for (i=0; (i<8 ? new_loc=loc+dir_offset[i],1 : 0); i++)
X#define FOR_ADJ_ON(loc,new_loc,i) FOR_ADJ(loc,new_loc,i) if (map[new_loc].on_board)
X
X/*
XWe maintain attributes for each piece.  Attributes are currently constant,
Xbut the way has been paved to allow user's to change attributes at the
Xbeginning of a game.
X*/
X
X#define INFINITY 1000000 /* a large number */
X
Xtypedef struct piece_attr {
X	char sname; /* eg 'C' */
X	char name[20]; /* eg "aircraft carrier" */
X	char nickname[20]; /* eg "carrier" */
X	char article[20]; /* eg "an aircraft carrier" */
X	char plural[20]; /* eg "aircraft carriers" */
X	char terrain[4]; /* terrain piece can pass over eg "." */
X	uchar build_time; /* time needed to build unit */
X	uchar strength; /* attack strength */
X	uchar max_hits; /* number of hits when completely repaired */
X	uchar speed; /* number of squares moved per turn */
X	uchar capacity; /* max objects that can be held */
X	long range; /* range of piece */
X} piece_attr_t;
X
X/*
XThere are 3 maps.  'map' describes the world as it actually
Xexists; it tells whether each map cell is land, water or a city;
Xit tells whether or not a square is on the board.
X
X'user_map' describes the user's view of the world.  'comp_map' describes
Xthe computer's view of the world.
X*/
X
X#define MAP_WIDTH 100
X#define MAP_HEIGHT 60
X#define MAP_SIZE (MAP_WIDTH * MAP_HEIGHT)
X
Xtypedef struct real_map { /* a cell of the actual map */
X	char contents; /* '+', '.', or '*' */
X	uchar on_board; /* TRUE iff on the board */
X	city_info_t *cityp; /* ptr to city at this location */
X	piece_info_t *objp; /* list of objects at this location */
X} real_map_t;
X
Xtypedef struct view_map { /* a cell of one player's world view */
X	char contents; /* '+', '.', '*', 'A', 'a', etc */
X	long seen; /* date when last updated */
X} view_map_t;
X
X/* Define information we maintain for a pathmap. */
X
Xtypedef struct {
X	int cost; /* total cost to get here */
X	int inc_cost; /* incremental cost to get here */
X	char terrain; /* T_LAND, T_WATER, T_UNKNOWN, T_PATH */
X} path_map_t;
X
X#define T_UNKNOWN 0
X#define T_PATH 1
X#define T_LAND 2
X#define T_WATER 4
X#define T_AIR (T_LAND | T_WATER)
X
X/* A record for counts we obtain when scanning a continent. */
X
Xtypedef struct {
X	int user_cities; /* number of user cities on continent */
X	int user_objects[NUM_OBJECTS];
X	int comp_cities;
X	int comp_objects[NUM_OBJECTS];
X	int size; /* size of continent in cells */
X	int unowned_cities; /* number of unowned cities */
X	int unexplored; /* unexplored territory */
X} scan_counts_t;
X
X/* Define useful constants for accessing sectors. */
X
X#define SECTOR_ROWS 5 /* number of vertical sectors */
X#define SECTOR_COLS 2 /* number of horizontal sectors */
X#define NUM_SECTORS (SECTOR_ROWS * SECTOR_COLS) /* total sectors */
X#define ROWS_PER_SECTOR ((MAP_HEIGHT+SECTOR_ROWS-1)/SECTOR_ROWS)
X#define COLS_PER_SECTOR ((MAP_WIDTH+SECTOR_COLS-1)/SECTOR_COLS)
X
X/* Information we need for finding a path for moving a piece. */
X
Xtypedef struct {
X	char city_owner; /* char that represents home city */
X	char *objectives; /* list of objectives */
X	int weights[11]; /* weight of each objective */
X} move_info_t;
X
X/* special weights */
X#define W_TT_BUILD -1 /* special cost for city building a tt */
X
X/* List of cells in the perimeter of our searching for a path. */
X
Xtypedef struct {
X	long len; /* number of items in list */
X	long list[MAP_SIZE]; /* list of locations */
X} perimeter_t;
//E*O*F empire.h//

echo shar: End of archive 3 \(of 6\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 ; do
    if test ! -f ark${I}isdone ; then
        MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 6 archives.
    rm -f ark[1-9]*isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0



More information about the Alt.sources mailing list