home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!charon.amdahl.com!pacbell.com!network.ucsd.edu!ogicse!zephyr.ens.tek.com!master!saab!billr
- From: billr@saab.CNA.TEK.COM (Bill Randle)
- Newsgroups: comp.sources.games
- Subject: v15i016: bt4 - Broken Throne, multiplayer realtime conquest game (V2.03), Part02/03
- Message-ID: <3827@master.CNA.TEK.COM>
- Date: 29 Oct 92 01:42:25 GMT
- Article-I.D.: master.3827
- Sender: news@master.CNA.TEK.COM
- Lines: 1711
- Approved: billr@saab.CNA.TEK.COM
- Xref: uunet comp.sources.games:1515
-
- Submitted-by: boutell@isis.cshl.org (Tom Boutell)
- Posting-number: Volume 15, Issue 16
- Archive-name: bt4/Part02
- Supersedes: bt3: Volume 12, Issue 52-53
- Environment: INET sockets, curses
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 3)."
- # Contents: bt.doc btclient.c btclient.h btserver.h btserverrc changes
- # Wrapped by billr@saab on Wed Oct 28 17:38:00 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'bt.doc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'bt.doc'\"
- else
- echo shar: Extracting \"'bt.doc'\" \(22442 characters\)
- sed "s/^X//" >'bt.doc' <<'END_OF_FILE'
- XThe Broken Throne
- X
- XA multiplayer, realtime game of conquest for the Unix operating system
- X
- XBy Tom Boutell (boutell@cshl.org), 11/14/90
- XLatest Revision (2.03) 10/20/92
- X
- XPermission granted to freely copy and alter the code, provided that new
- Xversions are cleared through me before release. I will be acting as a
- Xsource of information, and would appreciate copies of all changes.
- X
- XFIRST
- X
- XSee the readme file for instructions on building the game! This file (bt.doc)
- Xcovers the rules of the game, not installation. The readme file also
- Xcovers new features of each version and tips on getting it to compile
- Xif you don't seem to be having any luck.
- X
- XIf you have played older versions of the game, READ THIS AGAIN ANYWAY,
- Xbecause some major new rules have been added, most importantly
- Xautomatic recruitment and support. Also, the syntax for starting up the
- Xprograms has changed.
- X
- XTHE STORY
- X
- XEmperor Lettuce Prei of Squaria has died, leaving no heir. The nobles
- Xof the land scramble to reunite the pieces of the Broken Throne; do it
- Xfirst and become the next Emperor!
- X
- XABOUT THE GAME
- X
- XBroken Throne is a strategic wargame which runs in "real time." Every
- Xfew seconds, "action points" are transmitted to the players, which allow
- Xthem to do things- recruiting troops, moving troops, attacking, and
- Xconstructing and destroying cities. The object is to seize control of
- Xall of your opponents' cities; when a player controls no cities, that
- Xplayer is out of the game. Gameplay is quite rapid, and the map is
- Xcontinuously updated on the screen. All that is required to play is
- Xan ordinary terminal with curses screen control; any terminal that can
- Xrun a visual editor (like vi or emacs) will do fine. If the terminal
- Xis especially large, the game will take advantage of this, displaying
- Xmore space between locations and adding extra lines to the output window.
- XThis is handy if you are running Xwindows.
- X
- XThe map of Broken Throne is, by default, 16x16, consisting of square
- X"hexes." Each hex may contain one of several types of terrain:
- X
- X. Plains
- XT Town
- XM Mountains (passable)
- XF Forest
- XC City
- XS Swamp
- X^ Crags (impassable mountains)
- X
- XOn the screen, a hex is displayed like this:
- X
- XaC05
- X
- XWhere the lowercase letter is the letter of the player who controls the
- Xhex, the capital letter (or . or ^ ) is the terrain type, and the number
- Xfollowing is the number of troops. Unowned territories have no lowercase
- Xletter, and territories without troops have no following number.
- X
- XSTARTING OUT
- X
- XTo launch the game, a server program must be started. This is
- Xdone by entering:
- X
- Xbtserver -n (# of players) -p &
- X# of players should be replaced by the actual number of combatants
- Xand the & sign puts the server in the background.
- X
- X(Note that the use of standard - style options is a change from the
- Xprevious version of the game.)
- X
- XPutting the server in the background is important because it allows the
- Xplayer who runs the server to play in the game as well, even from
- Xan ASCII terminal.
- X
- XThere are other options for the server, and even more can be
- Xcontrolled in the .btserverrc file; more on that subject later.
- X
- XThen, the individual players each need to launch the client program.
- XThis is done by entering:
- X
- Xbtclient
- X
- XBy itself if the server is running on the SAME MACHINE, or:
- X
- Xbtclient -h machinename
- X
- XIf the server is running on another computer (a different workstation,
- Xfor instance, as opposed to just another text terminal).
- X
- XFor instance, in our local network, bt resides in a subdirectory of my
- Xown directory, so a player types:
- X
- Xcd ~boutell/bt <-- Of course this should be replaced by the path of your
- X *own* Broken Throne directory.
- Xbtserver -n 2 & ... To launch the game for two players, then each
- X player moves to the bt directory and types:
- Xbtclient -h toffee <-- Where "toffee" is the name of the machine the game
- X is running on. If the players and the server are on the
- X same machine, specifying the host is optional.
- X ONLY SERVER SHOULD BE STARTED!
- X
- XThe player who is running the server should start up his client last, in
- Xorder to keep his screen from being "munged" as the server announces
- Xplayers. This will generally keep the screen clean.
- X
- XALTERNATIVELY: if you know of a Broken Throne server that is already
- Xrunning and runs in "continuous mode", such as my own server, you
- Xcan contact it by just running the client:
- X
- Xbtclient -h hostname -p portnumber
- X
- XWhere hostname is the address of the server machine and port number is
- Xthe port advertised as correct to connect to it, anywhere on the Internet.
- XA server running in "continuous mode" will put you into a wait queue if there
- Xis currently a game in progress, and tell you how many players are needed
- Xper game, to give you a rough idea of the wait. When a player is eliminated,
- Xor the current game ends, you'll be updated. When you reach the front of the
- Xqueue at the start of a new game, you'll be one of the players.
- XYou can press CONTROL-C to quit waiting while in the queue; keep an eye
- Xpeeled for messages from the server recommending other machines or port
- Xnumbers for other, less crowded games.
- X
- XFor instance, to connect to my server:
- X
- Xbtclient -h athena.cshl.org -p 2727
- X
- XOTHER PORT NUMBERS
- X
- XIf you do not want to use the default port (2727), or if there is another
- XBT game in progress on the same machine (in which case you will notice
- Xproblems getting your game together), you will need to specify new port
- Xnumber. Port numbers should be between 1000 and 9999, the same on both
- Xclient and server. Enter the port number using the -p option on the
- Xcommand line for both client and server.
- X
- XROBOT PLAYERS
- X
- XIf you can't find opponents or want an added challenge, use the robot
- Xplayer! It's launched just like the client, but plays by itself, so
- Xput it in background so you can launch your own client and take it on.
- XFor example:
- X
- Xbtrobot -h toffee &
- X
- XIt also accepts port numbers if needed. You can launch as many robots
- Xas you wish; INCLUDE THEM IN THE PLAYER COUNT when launching the
- Xserver. The server can't tell them from human players.
- X
- XIMPORTANT NOTE ON USING ROBOTS: If all human players leave a game in which
- Xrobots are still playing, they'll keep going, and they never quit, even
- Xif one of them wins! So the person who launched them should type "jobs" to
- Xlist the programs running, and kill each robot: "kill %n" where n was the
- Xlisted job number of the robot. When all the robots are dead, the server will
- Xsay "Ending," letting you know that the game is completely over (unless
- Xit is running in continuous mode, in which case it will start a new game
- Xor wait for player connections).
- X
- XThe source is in the file btrobot.c. Have fun modifying it; it plays well
- Xearly on but has a rotten endgame, or rather, *no* real endgame. It's
- Xintended to be a jumping-off point for other programmers.
- X
- XONCE THE GAME STARTS:
- X
- XOnce the client is launched, a blank map will be displayed. Within a moment
- Xor two it should be replaced by the full map; be patient if there are
- Xseveral players.
- X
- XWhen the game first begins, the player is told which lowercase letter
- Xrepresents them on the map. Initially the player controls one city and
- Xwill immediately see a number of troops recruited. A cursor will appear
- Xat the city's location. This cursor can be moved with the standard vi/
- Xmoria/ hack movement keys:
- X
- X k
- X |
- X h-*-l
- X |
- X j
- X
- XIt is now possible to fan out and claim control of towns. The m (move)
- Xcommand is used to do this. The player should press m, then move the cursor
- Xto the source of the troops, initially the first city, and press the space
- Xbar. Then the cursor should be moved to the destination of the troops,
- Xwhich can be no more than one hex away; diagonal moves are acceptable.
- XAfter the space bar is pressed again, you will be asked how many troops
- Xto move; typically you'll want to move 1 army at a time at the beginning,
- Xsince you have a limited number of action points (see below). Type
- Xin 1 and press RETURN. The troops will be moved. Continue to move in this
- Xmanner to occupy territory, giving particular emphasis to taking
- Xtowns. (Other territories, particularly forests (F), mountains (M)
- Xand plains (.), are valuable to hold also.)
- X
- XRecruitment of new armies takes place AUTOMATICALLY, every so often in
- Xany given town or city. (This is a major change from the previous
- Xversion of the game.) Note that when a city or town is first taken over,
- Xneutral whether from another player, it is now necessary to wait the
- Xfull recruitment period before new troops can be recruited there.
- X
- XThe amount of time required for recruitment can be changed in the
- X.btserverrc file, to be described in detail later.
- X
- XYou can also recruit more aggressively by using the 'R' key and then
- Xselecting a city or town; keep in mind that the odds of success depend
- Xon how long it's been since the last recruitment.
- X
- XThe number of troops recruited is a function of population, not including
- Xother towns' population, so towns and cities surrounded by farmland will
- Xtend to recruit the most troops, towns surrounded by swamp very few.
- XNote that you must *OWN* surrounding territories to gain the benefit
- Xof their population. (This is also a change from the previous version.)
- XYou own a territory if your lowercase identifying letter appears at
- Xits left. Having an army continuously present is not necessary.
- XNeutral territories belong to and benefit no one, so take
- Xvaluable surrounding territory early.
- X
- XAction points are required to move troops! The player will soon find
- Xthemselves running low on them while exploring the area. This is because
- Xmovement in neutral or enemy territory costs 4 action points per army moved.
- XMovement in the player's own territory costs only 2 action points per
- Xarmy moved. When each tick takes place, the player will receive 2 action
- Xpoints, PLUS 1 action point for each city under the player's control.
- XThis becomes important later in the game.
- X
- XAction points are displayed for each player at the bottom of the screen:
- X
- XA: 6,13
- X
- XThis denotes that player A has six hexes (territories) and thirteen
- Xaction points.
- X
- XThe cursor can be moved freely while considering what command to enter
- Xnext. The only time you cannot move the cursor is during the entry of a
- Xnumber of troops, or a text message to another player.
- X
- XCOMBAT
- X
- XCombat in the Broken Throne is simple; the player simply moves troops into
- Xenemy territory, and the server resolves the conflict. Each round of battle,
- Xthere is a 50% chance the attacker will lose an army, and a 50% chance
- Xthe defender will; this continues until one side has no more troops.
- XUsually, however, the odds of combat are modified by the terrain of the
- Xtwo hexes, as detailed below. If the attacker seizes an opponent's last
- Xcity, that opponent is out of the game!
- X
- XArmies are broken down into units in battle, three units representing
- Xeach army. This makes the odds of battle somewhat more realistic while
- Xstill allowing for occasional freak outcomes.
- X
- XSUPPORT
- X
- XAfter automatic recruitment, support is the second most major change
- Xin version 2.0 of the game. To avoid starvation, ALL ARMIES MUST
- XHAVE SUPPORT. Support is determined by the rule: a CONTIGUOUS
- Xgroup of territories under a player's control can support ONE ARMY
- XFOR EVERY 100 POPULATION. (Plains have a population of 100, towns
- Xmore, other territories typically less. See TERRAIN, below.) For
- Xthis reason it is important to maintain a continuous empire!
- XDiagonal connections DO count, however, and you can restore support
- Xif it is cut by reestablishing a continuous region of territory
- X(retaking what was cut out of the middle). If a region can't
- Xsupport the forces within it, it will lose an army to starvation
- Xeach tick until the number of troops left can be supported or
- Xsupport is reestablished. Note that an army by itself in a
- Xforest, mountain or swamp will starve if it is not connected to
- Xa larger region! Remember, you DON'T have to have an army in
- Xeach territory to own it and maintain support; you just have to
- Xhave your identifying letter in each territory. In other words,
- Xthe last player to have marched through a territory owns that
- Xterritory.
- X
- XTERRAIN
- X
- XThe different terrain types have different roles in the game. Plains
- Xhexes (' . ') have no effect on combat, but provide substantial population.
- XThe number of troops a town or city can recruit depends on the surrounding
- Xpopulation controlled by the town or city's owner. Plains hexes have
- Xa population of 100.
- X
- XTown hexes (' T ') are the basic source of troops in the game, since
- Xrecruitment can only take place here and in cities. They have a strong
- Xdefensive advantage, 10%, and also a 10% offensive advantage.
- XTown hexes have a population of 300.
- X
- XMountain hexes (' M ') are difficult to move through. When moving troops
- Xinto them, some troops will usually be balked by conditions in the passes,
- Xand the action points will still be spent. However, a player in the mountains
- Xenjoys a 10% advantage, both defending against attack and when striking
- Xdown out of the mountains. Mountain hexes have a population of 50.
- X
- XForest hexes (' F ') hide enemy troops from view. Another player can only tell
- Xwho the forest is controlled by; the exact numbers of troops are hidden.
- XForces in a forest enjoy a 5% advantage when attacking out of the forest.
- XForces in the forest have a 10% defensive advantage as well. Forest hexes
- Xhave a population of 75.
- X
- XCity hexes (' C ') are the strongest hexes in the game, with a 15% defensive
- Xadvantage, though only a 5% offensive advantage. The player can recruit
- Xtroops at cities, and cities also provide an extra action point per tick;
- Xthe more cities the player controls, the more resources they have, and
- Xthe more quickly they can move armies. Only towns can be built into
- Xcities, at a cost of typically 90 action points! This value can be set
- Xin the .btserverrc file. If a player loses control of all cities, that player
- Xis out of the game, and their existing troops disband, leaving their territory
- Xfree for the taking! Although building cities is expensive, the action points
- Xthey provide can quickly make up for the cost. It is very inexpensive to
- Xdestroy a city, however, so they should be built in safe areas. City
- Xhexes have a population of 400.
- X
- XSwamp hexes (' S ') are the armpit of Broken Throne! Troops are very
- Xunhappy here; the swamp will often gobble one army of the advancing
- Xforce. Swamps have no population, and unless in the player's way (or
- Xneeded to maintain support) aren't worth slogging through. Troops in a
- Xswamp are at a 10% DISadvantage, both attacking and defending! Swamps
- Xhave a population of only 10.
- X
- XCrag hexes (' ^ ') are impassable mountains. It is not possible to
- Xenter these hexes, and so they do not affect combat. They have
- Xno population.
- X
- XCOMMAND REFERENCE (INCLUDING SOME COMMANDS NOT DESCRIBED ABOVE!)
- X
- Xc (location): construct a city. This requires, usually, 90 action points,
- X unless the value has been changed in the .btserverrc file.
- X Can only be used in towns.
- Xd (location): destroy a city OR TOWN. Usually costs 10 action points.
- Xq: quit the game. You must confirm this.
- Xt (player letter) (message): Tell a player something. Type their player
- X letter (case is not important) after striking t, then your message to
- X them (one line). The message will appear in their output window.
- Xt # (message): If you type a '#' sign instead of a letter, the message
- X will go to all players, including yourself.
- Xm (location) (location) (# of troops): move troops. The game will prompt
- X for the locations from which and to which troops are to be moved, then
- X for the number of troops.
- Xr (location): recruit troops. See notes above on the rules of recruitment.
- X Remember, recruitment is automatically done as often as it is safe,
- X but the r key can be used to force the pace.
- XM (capitalized): redraw a Messy screen. This is useful after a talk
- X request (or line noise) messes up your display.
- XESC (Escape key): Cancels *whatever* you are in the process of doing.
- X Very useful for retaining your sanity.
- X
- XWINNING & LOSING
- X
- XYou win the game when no other players remain. You lose the game if you
- Xcontrol no cities. If your last city is taken (towns don't count), it
- Xdoesn't matter how many troops you still have, so be careful to defend
- Xthem! When a player is eliminated, any remaining troops are dissolved
- Xand territories are free for the taking.
- X
- XIf you have lost the game, you can continue to watch the game for as long
- Xas you like, before striking 'q' to actually leave the program.
- X
- XIf you win, the game will not automatically halt itself. You need to type
- X'q' to quit the game as the last player. This allows the game to be launched
- Xby one person on one terminal to test it out or learn the rules.
- X(Continuous-mode servers may throw all players off the server when
- Xone player is left alive.)
- X
- XThe player who launched the server should see the message "Ending" after
- Xthe last player quits. If not, that player should do a ps -aux command
- Xand look for a lingering copy of the server, then kill that copy of the
- Xserver. (I have not seen such problems recently, but it's possible.
- XA good command to find a lost server: ps -aux | grep btserver will
- Xusually locate the process number.)
- X
- XIF YOU ABORT THE PROGRAM
- X
- XIf you control-c a client, the other players will continue, but you will be
- Xout of the game. This no longer confuses your terminal as in previous
- Xversions; wait a second or two, hit return a few times and you'll
- Xhave a normal Unix prompt back.
- X
- XMORE SERVER OPTIONS:
- XMAP SIZE
- X
- XYou can start up a game with a different map size, as long as your
- Xclient terminals are large enough to support it, using the -s
- X(size) option to the server. For instance:
- X
- Xbtserver -n 2 -s 12x12 &
- X
- XStarts a two - player, 12x12 - map game and puts it into the
- Xbackground.
- X
- XCUSTOMIZED MAPS
- X
- XIf you get tired of playing on random maps, try designing your own map!
- XAll you have to do is create a file arranged like this:
- X
- X(w should be replaced by the width of the map, here 16, and h by the
- Xheight of the map, also 16 in this example. You do NOT need to
- Xspecify the -s option to use a map file with a nonstandard size, because
- Xthe size is in the map file. This is a change from the previous version,
- Xso old map files will need to have a size inserted at the beginning.
- XNote the x between the width and height.)
- X
- Xwxh
- XMMMMFMMFMFMMMMTT
- XMMFF....TMMMFFMM
- XMMMMMMMM.6..MTMM ^
- XMMMM..T..MMMMMMM ^
- XMMFFFM..T..TMMMM
- XMMMMMMMTMMMMMMTM h
- XMMM..1....5...MM
- XMMMMMMTMMMMMMMMM d
- XMMMMMM...MTMMMMM o
- XMMMTMMMMT4MMM3TM w
- XMM.....MMMMMMMMM n
- XMMMMMMTMTMTMMFFM
- XMT..T..MMMMMMMMM v
- XMMMMMMMMFFFMTMMM v
- XMMMTMMMMTMM.2.MM
- XMMMMMMMMMMMMMMMM
- X << w across>>
- X
- X(Don't put in the text "w across" and "h down," of course.)
- X
- XThe same terrain letters you see during the game should be used here in
- Xthe map file. (You may use spaces between symbols if you wish for
- Xmore readability.) In addition, in the locations at which players should
- Xenter the game, place the numbers one through the highest number of
- Xplayers you think should play on the map. You should designate a
- Xlocation for all possible players. If you play with fewer players, the
- Xunused starting locations will become farmland ('.'); otherwise, they become
- Xcities, and the designated players enter the game there.
- X
- XTo load the map, give its filename last on the command line when starting
- Xthe server:
- X
- Xbtserver -n 4 -m map.txt &
- X
- XStarts a four- player game, using the file map.txt.
- X
- Xbtserver -n 4 -p 2000 -m map.txt &
- X
- XStarts a four- player game on port 2000, using the file map.txt.
- X
- XA sample map, map.txt, is provided to help you get the hang of the map
- Xfile system; you can edit it to produce a new map if you wish.
- X
- XIF YOU'VE DESIGNED GOOD MAPS...
- X
- XMail them to me at boutell@cshl.org! I may include a selection
- Xof good ones in a future release, and/or run them on my server.
- X
- XABOUT THE .BTSERVERRC FILE
- X
- XTo customize your server, or to set up a continuously - running
- Xserver that maintains a wait queue and doesn't need to be restarted
- Xto begin a new game, you'll need a .btserverrc file. One is provided
- Xin the standard release. btserver, when run, looks first in the
- Xcurrent directory, then in your home directory, for a .btserverrc
- Xfile; if it doesn't find one, it uses a reasonable set of
- Xbuilt-in defaults. You can specify an alternate filename
- Xusing the -d option.
- X
- XLook at the provided .btserverrc file for complete comments on
- Xwhat settings are available and what each does. The "continuous" setting
- Xis of particular interest. One can also control the default number
- Xof players, the default size of the map, the number of ticks between
- Xrecruitments, the number of seconds per tick, and so on.
- X
- XRUNNING ON LARGE TERMINALS& UNDER X-WINDOWS
- X
- XUnder X- Windows and on other systems providing large terminals the game
- Xwill take advantage of the terminal's size to provide more spacing and
- Xmore room for output messages. The wider and deeper, the better. The game
- Xwill *not* take notice if you resize the window while it is running, however.
- XYou probably don't want a window wider than about 120 characters, though,
- Xsince it becomes difficult to see which locations are next to each other,
- Xunless you're using an expanded map via the -s option.
- X
- XA file titled xbt is provided in the distribution. If you chmod this
- Xfile to make it executable, you can use it in place of btclient when
- Xrunning Xwindows, in order to automatically launch btclient in a
- Xnew window using a larger font. (it's just a shell script that
- Xstarts up btclient. You don't need to use it to play under X, btclient
- Xalone works fine.) I find this file convenient, but it doesn't make BT a true
- XX program by any stretch of the imagination.
- XAn example of its use:
- X
- Xxbt -h maplenut
- X
- X... To connect to a game on the machine "maplenut," exactly as one would
- Xby entering "btclient -h maplenut."
- X
- XSUNVIEW
- X
- XPerformance under Sunview is a mixed thing, apparently. On our somewhat
- Xolder Sunview, there are problems with Curses that prevent it from running
- Xproperly, but under Sunview 3.0 I'm told it works fine.
- X
- XFINDING OPPONENTS
- X
- XThe easiest way to find a game is to connect to my server:
- X
- Xbtclient -h athena.cshl.org
- X
- XYou can also send me email at boutell@cshl.org, which is also the
- Xcorrect address for bug reports. I'm not the best player, incidentally;
- Xthat honor belongs to a friend of mine at the University of Delaware.
- XHE'S the one you should worry about.
- X
- END_OF_FILE
- if test 22442 -ne `wc -c <'bt.doc'`; then
- echo shar: \"'bt.doc'\" unpacked with wrong size!
- fi
- # end of 'bt.doc'
- fi
- if test -f 'btclient.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'btclient.c'\"
- else
- echo shar: Extracting \"'btclient.c'\" \(20630 characters\)
- sed "s/^X//" >'btclient.c' <<'END_OF_FILE'
- X/*
- X * Broken Throne client program, by Tom Boutell 10/90- 12/90 Thanks to Marc
- X * Cygnus for my socket education
- X */
- X
- X#include <stdio.h>
- X#include <curses.h>
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#ifdef _AIX
- X#include <sys/select.h>
- X#endif
- X#include <netinet/in.h>
- X#include <netdb.h>
- X#include <signal.h>
- X#include <sys/time.h>
- X#include <fcntl.h>
- X#include <errno.h>
- X#include <ctype.h>
- X
- X#ifdef BSD_CURSES
- X#define cbreak crmode
- X#define nocbreak nocrmode
- X#endif
- X
- X#ifdef mips
- Xextern int errno;
- X#endif
- X
- X#include "bt.h"
- X#include "btpack.h"
- X#include "btclient.h"
- X#include "msleep.h"
- X
- Xstatic int gamemapsizex;
- Xstatic int gamemapsizey;
- Xstatic int videosetup = 0;
- Xstatic int connected = 0;
- X
- Xmain(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X WINDOW *help;
- X int inputchar;
- X int inputpos;
- X char inputline[200];
- X char recvdline[200];
- X static char hostname[81];
- X int done;
- X char messagetype;
- X location at;
- X location from, to;
- X int theplayer;
- X int x, y;
- X int offset;
- X int count;
- X int i;
- X int gotmessage;
- X port = 2727;
- X gethostname(hostname, 80);
- X host = hostname;
- X for (i = 1; (i < argc); i++) {
- X if (strcmp(argv[i], "-h") == 0) {
- X if ((i + 1) < argc) {
- X host = argv[++i];
- X } else {
- X fprintf(stderr, "btclient: hostname missing for -h option.\n");
- X exit(-1);
- X }
- X } else if (strcmp(argv[i], "-p") == 0) {
- X if ((i + 1) < argc) {
- X port = atoi(argv[++i]);
- X } else {
- X fprintf(stderr, "btclient: port # missing for -p option.\n");
- X exit(-1);
- X }
- X } else {
- X fprintf(stderr, "Unknown option.\n");
- X fprintf(stderr, "Usage: btclient -h hostname [-p port#]\n");
- X exit(-1);
- X }
- X }
- X if (connectstream() == 0) {
- X perror("Server unreachable.\n");
- X exit(1);
- X }
- X printf("Waiting for players to join...\n");
- X promptoffset = 0;
- X signal(SIGTERM, endtrap);
- X signal(SIGQUIT, endtrap);
- X signal(SIGINT, endtrap);
- X signal(SIGPIPE, endtrap);
- X done = 0;
- X inputpos = 0;
- X specific = specificspace;
- X cursorx = (-1);
- X cursory = (-1);
- X /* Get YOUARE message & any other pregame messages */
- X do {
- X waitevent();
- X getmessage(&messagetype, specific);
- X if (messagetype == _END) {
- X endprogram();
- X exit(-1);
- X } else if (messagetype == _BUSY) {
- X printf("Game is full.\n");
- X endprogram();
- X exit(-1);
- X } else if (messagetype == _TEXT) {
- X printf("%s\n", (char *) specific);
- X }
- X } while (messagetype != _YOUARE);
- X playernumber = specific[0] - 64;
- X /* Get STARTUP message */
- X connected = 1;
- X do {
- X waitevent();
- X getmessage(&messagetype, specific);
- X if (messagetype == _END) {
- X printf("Server died.\n");
- X endprogram();
- X exit(-1);
- X }
- X } while (messagetype != _STARTUP);
- X totalplayers = specific[0] - 64;
- X gamemapsizex = specific[1] - 64;
- X gamemapsizey = specific[2] - 64;
- X initscr();
- X cbreak();
- X noecho();
- X inputfd = fileno(stdin);
- X FD_SET(inputfd, &events);
- X fflush(stdin);
- X videosetup = 1;
- X inputstate = _CURSORCOMMAND;
- X /* Now we know enough to setup the display */
- X clear();
- X refresh();
- X xsize = COLS / (gamemapsizex + 1);
- X if (xsize < 4) {
- X fprintf(stderr,
- X "The window is too narrow. Run the server with a narrower map.");
- X endprogram();
- X exit(-1);
- X }
- X if ((LINES - gamemapsizey) < 4) {
- X fprintf(stderr,
- X "The window is too short. Run the server with a shorter map.\n");
- X endprogram();
- X exit(-1);
- X }
- X output = newwin(LINES - gamemapsizey - 4, COLS - 1, gamemapsizey + 4, 0);
- X info = newwin(2, COLS -1, gamemapsizey + 2, 0);
- X scrollok(output, 1);
- X setupmap();
- X signal(SIGCONT, restorescreen);
- X for (count = 1; (count <= totalplayers); count++)
- X players[count].live = 1;
- X sprintf(inputline, "We are player %c.\n", playernumber + 64);
- X tellplayer(inputline);
- X sprintf(inputline, "? summons help.\n");
- X tellplayer(inputline);
- X promptplayer("Command:");
- X while (done != 2) {
- X gotmessage = 0;
- X while (1) {
- X if (!waitshort(playerFd))
- X break;
- X if (!getmessage(&messagetype, specific))
- X break;
- X gotmessage = 1;
- X offset = 0;
- X switch ((int) messagetype) {
- X case _HEXSTATUS:
- X striplocation(&at, specific, &offset);
- X map[at.x][at.y].terrain = specific[offset] - 64;
- X offset++;
- X stripint(&map[at.x][at.y].population, specific, &offset);
- X stripint(&map[at.x][at.y].lastuse, specific, &offset);
- X stripint(&map[at.x][at.y].troops, specific, &offset);
- X map[at.x][at.y].owner = specific[offset] - 64;
- X offset++;
- X displayhex(at.x, at.y);
- X break;
- X case _PLAYERSTATUS:
- X theplayer = specific[offset] - 64;
- X offset++;
- X stripint(&players[theplayer].action, specific, &offset);
- X stripint(&players[theplayer].hexes, specific, &offset);
- X stripint(&players[theplayer].troops, specific, &offset);
- X stripint(&players[theplayer].population, specific, &offset);
- X stripint(&players[theplayer].citadels, specific, &offset);
- X striplocation(&players[theplayer].start, specific, &offset);
- X displayplayer(theplayer);
- X if ((theplayer == playernumber) && (cursorx == (-1))) {
- X cursorx = players[theplayer].start.x;
- X cursory = players[theplayer].start.y;
- X }
- X break;
- X case _PLAYERDEAD:
- X theplayer = specific[0] - 64;
- X players[theplayer].live = 0;
- X for (y = 0; (y < gamemapsizey); y++) {
- X for (x = 0; (x < gamemapsizex); x++) {
- X if (map[x][y].owner == theplayer) {
- X map[x][y].troops = 0;
- X map[x][y].owner = 0;
- X displayhex(x, y);
- X }
- X }
- X }
- X displayplayer(theplayer);
- X refresh();
- X if (theplayer == playernumber) {
- X tellplayer("We are out of the game.\n");
- X if (done == 3)
- X done = 2;
- X else {
- X done = 1;
- X tellplayer("Press q to exit.\n");
- X }
- X }
- X break;
- X case _TEXT:
- X sprintf(recvdline, "%s\n", specific);
- X tellplayer(recvdline);
- X break;
- X case _ACTION:
- X for (theplayer = 1; (theplayer <= totalplayers); theplayer++) {
- X if (players[theplayer].live == 1) {
- X players[theplayer].action += (2 + players[theplayer].citadels);
- X displayplayer(theplayer);
- X }
- X }
- X break;
- X case _END:
- X tellplayer("The game is over.\n");
- X tellplayer("Press q to exit.\n");
- X done = 1;
- X break;
- X case _LOOK:
- X striplocation(&at, specific, &offset);
- X flashhex(at.x, at.y);
- X }
- X }
- X if (done != 0) {
- X if (inputwaiting(inputfd)) {
- X inputchar = getch();
- X if (inputchar == 'q')
- X done = 2;
- X }
- X } else {
- X if (inputwaiting(inputfd)) {
- X inputchar = getch();
- X switch (inputstate) {
- X case _CURSORM1:
- X case _CURSORM2:
- X case _CURSORRECRUIT:
- X case _CURSORCONSTRUCT:
- X case _CURSORDESTROY:
- X case _CURSORCOMMAND:
- X switch (inputchar) {
- X case mescape:
- X if (inputstate != _CURSORCOMMAND) {
- X tellplayer("Cancelled.\n");
- X promptplayer("Command:");
- X inputstate = _CURSORCOMMAND;
- X }
- X break;
- X case 'h':
- X if (cursorx > 0) {
- X cursorx--;
- X displayhex(cursorx + 1, cursory);
- X displayhex(cursorx, cursory);
- X }
- X break;
- X case 'l':
- X if (cursorx < gamemapsizex - 1) {
- X cursorx++;
- X displayhex(cursorx - 1, cursory);
- X displayhex(cursorx, cursory);
- X }
- X break;
- X case 'k':
- X if (cursory > 0) {
- X cursory--;
- X displayhex(cursorx, cursory + 1);
- X displayhex(cursorx, cursory);
- X }
- X break;
- X case 'j':
- X if (cursory < gamemapsizey - 1) {
- X cursory++;
- X displayhex(cursorx, cursory - 1);
- X displayhex(cursorx, cursory);
- X }
- X break;
- X case ' ':
- X case '\n':
- X switch (inputstate) {
- X case _CURSORM1:
- X from.x = cursorx;
- X from.y = cursory;
- X promptplayer("To? ");
- X inputstate = _CURSORM2;
- X break;
- X case _CURSORM2:
- X to.x = cursorx;
- X to.y = cursory;
- X promptplayer("Troops?");
- X inputstate = _CURSORM3;
- X break;
- X case _CURSORRECRUIT:
- X case _CURSORCONSTRUCT:
- X case _CURSORDESTROY:
- X from.x = cursorx;
- X from.y = cursory;
- X outputline[1] = from.x + 64;
- X outputline[2] = from.y + 64;
- X outputline[3] = NULL;
- X switch (inputstate) {
- X case _CURSORRECRUIT:
- X outputline[0] = _RECRUIT;
- X break;
- X case _CURSORCONSTRUCT:
- X outputline[0] = _CONSTRUCT;
- X break;
- X case _CURSORDESTROY:
- X outputline[0] = _DESTROY;
- X break;
- X }
- X write(playerFd, outputline, strlen(outputline) + 1);
- X inputstate = _CURSORCOMMAND;
- X promptplayer("Command:");
- X break;
- X case _CURSORCOMMAND:
- X tellplayer("Huh?\n");
- X }
- X break;
- X }
- X if (inputstate == _CURSORCOMMAND) {
- X switch (inputchar) {
- X case '/':
- X case '?':
- X help = newwin(17, 65, 1, 5);
- X werase(help);
- X box(help, '|', '-');
- X wmove(help, 0, 0);
- X mvwprintw(help, 1, 1, "Broken Throne Help");
- X mvwprintw(help, 2, 1, "m: move troops (from) (to).");
- X mvwprintw(help, 3, 1, " Attacking is accomplished by moving into enemy territory.");
- X mvwprintw(help, 4, 1, "r: recruit troops (location): location must be town or city");
- X mvwprintw(help, 5, 1, "c: construct city (location): location must be town");
- X mvwprintw(help, 6, 1, "d: destroy (location): location must be city or town");
- X mvwprintw(help, 7, 1, "q: quit game.");
- X mvwprintw(help, 8, 1, "Where parentheses appear above, you are expected to move");
- X mvwprintw(help, 9, 1, "the cursor with the standard hack/ vi/ moria movement keys:");
- X mvwprintw(help, 10, 1, "h left, l right, j down, k up.");
- X mvwprintw(help, 11, 1, "Select the location by pressing the space bar or RETURN.");
- X mvwprintw(help, 12, 1, "t: tell player (player letter) followed by message.");
- X mvwprintw(help, 13, 1, "Enter a '#' sign instead of a letter to tell all.");
- X mvwprintw(help, 14, 1, "M: (capitalized): redraw Messy screen.");
- X mvwprintw(help, 15, 1, "Press any key now to continue play.");
- X wrefresh(help);
- X inputchar = getch();
- X werase(help);
- X delwin(help);
- X touchwin(mapw);
- X touchwin(output);
- X touchwin(info);
- X wrefresh(mapw);
- X wrefresh(output);
- X wrefresh(info);
- X break;
- X case 'M':
- X restorescreen();
- X break;
- X case 'm':
- X promptplayer("Move: From? ");
- X inputstate = _CURSORM1;
- X displayhex(cursorx, cursory);
- X break;
- X case 'r':
- X promptplayer("Recruit: at what location? ");
- X inputstate = _CURSORRECRUIT;
- X displayhex(cursorx, cursory);
- X break;
- X case 'c':
- X promptplayer("Construct city: at what location? ");
- X inputstate = _CURSORCONSTRUCT;
- X displayhex(cursorx, cursory);
- X break;
- X case 'd':
- X promptplayer("Destroy city or town: at what location? ");
- X inputstate = _CURSORDESTROY;
- X displayhex(cursorx, cursory);
- X break;
- X case 'q':
- X outputline[0] = _QUIT;
- X outputline[1] = NULL;
- X if (players[playernumber].live) {
- X promptplayer("Quit: confirm (y/n)? ");
- X inputchar = getch();
- X if ((inputchar != 'y') && (inputchar != 'Y')) {
- X tellplayer("Cancelled.\n");
- X break;
- X }
- X }
- X done = 3;
- X write(playerFd, outputline, strlen(outputline) + 1);
- X break;
- X case 't':
- X promptplayer("Tell: whom and what? ");
- X inputstate = _CURSORTELL;
- X }
- X }
- X break;
- X case _CURSORM3:
- X case _CURSORTELL:
- X switch (inputchar) {
- X case mbackspace:
- X case mdelete:
- X if (inputpos > 0) {
- X inputpos--;
- X wmove(info, 1, promptoffset + inputpos);
- X waddch(info, ' ');
- X wmove(info, 1, promptoffset + inputpos);
- X wrefresh(info);
- X }
- X break;
- X case mescape:
- X tellplayer("");
- X tellplayer("Cancelled.\n");
- X promptplayer("Command:");
- X inputstate = _CURSORCOMMAND;
- X break;
- X case '\n':
- X inputline[inputpos] = NULL;
- X wmove(info, 1, 0);
- X wrefresh(info);
- X switch (inputstate) {
- X case _CURSORTELL:
- X inputpos = 0;
- X if (inputline[0] == '#') {
- X outputline[0] = _TELLALL;
- X strcpy(&outputline[1], &inputline[1]);
- X write(playerFd, outputline, strlen(outputline) + 1);
- X } else {
- X outputline[0] = _PRIVATE;
- X if (inputline[0] > 96)
- X inputline[0] -= 32;
- X if (isalpha(inputline[0])) {
- X outputline[1] = inputline[0];
- X if (!inrange(outputline[1] - 64, 1, totalplayers)) {
- X tellplayer("Huh?\n");
- X } else {
- X strcpy(&outputline[2], &inputline[1]);
- X write(playerFd, outputline, strlen(outputline) + 1);
- X }
- X } else
- X tellplayer("Huh?\n");
- X }
- X inputstate = _CURSORCOMMAND;
- X promptplayer("Command:");
- X break;
- X case _CURSORM3:
- X outputline[0] = _MOVE;
- X outputline[1] = from.x + 64;
- X outputline[2] = from.y + 64;
- X outputline[3] = to.x + 64;
- X outputline[4] = to.y + 64;
- X if (inputpos == 0)
- X packint(5, map[from.x][from.y].troops);
- X else
- X packint(5, atoi(inputline));
- X inputpos = 0;
- X outputline[8] = NULL;
- X write(playerFd, outputline, strlen(outputline) + 1);
- X inputstate = _CURSORCOMMAND;
- X promptplayer("Command:");
- X break;
- X }
- X default:
- X if ((inputpos + promptoffset < (COLS - 1)) && (!iscntrl(inputchar))) {
- X inputline[inputpos] = inputchar;
- X wmove(info, 1, promptoffset + inputpos);
- X if (inputpos == 0)
- X wclrtoeol(info);
- X waddch(info, inputchar);
- X wrefresh(info);
- X inputpos++;
- X }
- X }
- X }
- X }
- X }
- X if (gotmessage == 1) {
- X wrefresh(mapw);
- X refresh();
- X }
- X }
- X /* Terminating code - needs to be called on CTRLC also. */
- X endprogram();
- X return 0;
- X}
- X
- Xvoid
- Xwaitevent()
- X{
- X bcopy((char *) &events, (char *) &realevents, sizeof(events));
- X if (select(FD_SETSIZE, &realevents, NULL, NULL, NULL) < 0) {
- X if (errno != EINTR) {
- X perror("select");
- X exit(1);
- X }
- X }
- X}
- X
- Xint
- Xwaitshort(thisfd)
- X int thisfd;
- X{
- X struct timeval waitTime;
- X waitTime.tv_sec = SECONDSLIMIT;
- X waitTime.tv_usec = MICROSECONDSLIMIT;
- X bcopy((char *) &events, (char *) &realevents, sizeof(events));
- X if (select(FD_SETSIZE, &realevents, NULL, NULL, &waitTime) < 0) {
- X if (errno != EINTR) {
- X perror("select");
- X exit(1);
- X }
- X }
- X if (FD_ISSET(thisfd, &realevents))
- X return 1;
- X return 0;
- X}
- X
- X
- Xvoid
- Xpromptplayer(prompt)
- X char *prompt;
- X{
- X wmove(info, 1, 0);
- X wclrtoeol(info);
- X waddstr(info, prompt);
- X promptoffset = strlen(prompt) + 1;
- X wrefresh(info);
- X}
- X
- Xvoid
- Xrestorescreen()
- X{
- X wrefresh(curscr);
- X}
- X
- Xvoid
- Xendtrap()
- X{
- X endprogram();
- X exit(-1);
- X}
- X
- Xvoid
- Xendprogram()
- X{
- X int x;
- X if (connected) {
- X outputline[0] = _DISCONNECT;
- X outputline[1] = NULL;
- X write(playerFd, outputline, strlen(outputline) + 1);
- X /*
- X * Let any messages about our death go through without a
- X * SIGPIPE
- X */
- X sleep(2);
- X close(playerFd);
- X }
- X if (videosetup) {
- X if (output) {
- X wclear(output);
- X delwin(output);
- X }
- X clear();
- X refresh();
- X endwin();
- X echo();
- X nocbreak();
- X }
- X printf("Client shut down.\n");
- X for (x = 0; (x < gamemapsizex); x++) {
- X free(map[x]);
- X }
- X free(map);
- X}
- X
- Xint
- Xinrange(x, low, high)
- X int x;
- X int low;
- X int high;
- X{
- X if (x < low || x > high)
- X return 0;
- X return 1;
- X}
- X
- Xint
- Xgetmessage(messagetype, specific)
- X char *messagetype;
- X char *specific;
- X{
- X *messagetype = 0;
- X *specific = 0;
- X if (!inputwaiting(playerFd)) {
- X return 0;
- X }
- X read(playerFd, messagetype, 1);
- X readnullterm(playerFd, specific);
- X if (*messagetype == 0)
- X return 0;
- X else
- X return 1;
- X}
- X
- Xvoid
- Xreadnullterm(fd, specific)
- X int fd;
- X char *specific;
- X{
- X int done;
- X char *current;
- X current = specific;
- X done = 0;
- X while (done == 0) {
- X while (1) {
- X waitevent();
- X if (inputwaiting(fd))
- X break;
- X }
- X read(fd, current, 1);
- X if (*current == 0)
- X done = 1;
- X current++;
- X }
- X}
- X
- Xvoid
- Xsetupmap(x, y)
- X int x;
- X int y;
- X{
- X for (y = 0; (y < gamemapsizey); y++) {
- X move(y + 1, 0);
- X addch(48 + ((y / 10) % 10));
- X move(y + 1, 1);
- X addch(48 + (y % 10));
- X }
- X for (x = 0; (x < gamemapsizex); x++) {
- X move(0, x * xsize + 5);
- X addch(65 + x);
- X }
- X mapw = newwin(gamemapsizey + 1, 0, 1, 4);
- X map = (hex **) malloc(sizeof(hex *) * gamemapsizex);
- X for (x = 0; (x < gamemapsizex); x++) {
- X map[x] = (hex *) malloc(sizeof(hex) * gamemapsizey);
- X }
- X for (y = 0; (y < gamemapsizey); y++) {
- X for (x = 0; (x < gamemapsizex); x++) {
- X map[x][y].terrain = 7;
- X map[x][y].troops = 0;
- X map[x][y].population = 0;
- X map[x][y].owner = 0;
- X map[x][y].lastuse = 0;
- X displayhex(x, y);
- X }
- X }
- X refresh();
- X wrefresh(mapw);
- X}
- X
- Xvoid
- Xflashhex(x, y)
- X int x;
- X int y;
- X{
- X wmove(mapw, y, x * xsize + 1);
- X waddch(mapw, "*");
- X wrefresh(mapw);
- X msleep(1000);
- X wmove(mapw, y, x * xsize + 1);
- X waddch(mapw, terrainimage[map[x][y].terrain]);
- X}
- X
- Xvoid
- Xdisplayhex(x, y)
- X int x;
- X int y;
- X{
- X int redraw;
- X redraw = 0;
- X if ((x == cursorx) && (y == cursory)) {
- X wstandout(mapw);
- X redraw = 1;
- X } else
- X wstandend(mapw);
- X wmove(mapw, y, x * xsize);
- X if (map[x][y].owner > 0)
- X waddch(mapw, 96 + map[x][y].owner);
- X else
- X waddch(mapw, ' ');
- X wmove(mapw, y, x * xsize + 1);
- X waddch(mapw, terrainimage[map[x][y].terrain]);
- X if (((map[x][y].terrain != 4) || map[x][y].owner == playernumber)
- X && (map[x][y].troops > 0)) {
- X wmove(mapw, y, x * xsize + 2);
- X waddch(mapw, 48 + ((map[x][y].troops / 10) % 10));
- X wmove(mapw, y, x * xsize + 3);
- X waddch(mapw, 48 + (map[x][y].troops % 10));
- X } else {
- X wmove(mapw, y, x * xsize + 2);
- X waddstr(mapw, " ");
- X }
- X wstandend(mapw);
- X if (redraw == 1)
- X wrefresh(mapw);
- X wmove(mapw, y, x * xsize + 1);
- X}
- X
- Xint
- Xconnectstream()
- X{
- X int s;
- X struct sockaddr_in saddr;
- X struct in_addr host_address;
- X if ((s = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
- X perror("socket create");
- X return (0);
- X }
- X saddr.sin_family = AF_INET;
- X if (!get_host_address(host, &host_address)) {
- X printf("Bad or missing server address.\n");
- X exit(1);
- X }
- X bcopy(&host_address, &saddr.sin_addr, sizeof(struct in_addr));
- X /* saddr.sin_addr.s_addr = htonl(inet_addr(host)); Old method */
- X saddr.sin_port = htons(port);
- X
- X if (connect(s, (struct sockaddr *) & saddr, sizeof(struct sockaddr_in)) < 0) {
- X perror("connect");
- X return (0);
- X }
- X FD_SET(s, &events);
- X playerFd = s;
- X return (1);
- X}
- X
- X
- X
- Xint
- Xinputwaiting(sfd)
- X int sfd;
- X{
- X if (FD_ISSET(sfd, &realevents))
- X return 1;
- X else
- X return 0;
- X}
- X
- X/*
- X * int errrec; fd_set readfds; struct timeval waitTime;
- X * waitTime.tv_sec=SECONDSLIMIT; waitTime.tv_usec=MICROSECONDSLIMIT;
- X * bcopy((char *) sfdset, (char *) &readfds,sizeof(*sfdset)); if
- X * (select(FD_SETSIZE,&readfds,NULL,NULL,&waitTime)<0) { if (errno!=EINTR) {
- X * perror("select"); } return 0; } if (FD_ISSET(sfd,&readfds)) return 1; else
- X * return 0; }
- X *
- X */
- X
- Xvoid
- Xtellplayer(this)
- X char *this;
- X{
- X wprintw(output, this);
- X wrefresh(output);
- X}
- X
- Xvoid
- Xdisplayplayer(theplayer)
- X int theplayer;
- X{
- X static char outputline[100];
- X wmove(info, 0, theplayer * 12 - 11);
- X if (players[theplayer].live == 1)
- X waddstr(info, sprintf(outputline, "%c:%4d,%3d", theplayer + 64,
- X players[theplayer].hexes, players[theplayer].action));
- X else
- X waddstr(info, sprintf(outputline, "%c: Dead ", theplayer + 64));
- X wrefresh(info);
- X}
- X
- Xvoid
- Xdisplaysignal(smessage)
- X char *smessage;
- X{
- X wmove(info, 0, COLS - 4);
- X waddstr(info, smessage);
- X}
- X
- X/*
- X * get_host_address: borrowed with appreciation from Tinytalk. Does a nice
- X * job of getting around the various stupidities of the inetaddr routine, et
- X * cetera.
- X */
- X
- Xint
- Xget_host_address(name, addr) /* Get a host address. */
- X register char *name;
- X register struct in_addr *addr;
- X{
- X struct hostent *blob;
- X union { /* %#@!%!@%#!@ idiot who designed */
- X long signed_thingy; /* the inetaddr routine.... */
- X unsigned long unsigned_thingy;
- X } thingy;
- X
- X if (*name == '\0') {
- X fprintf(stderr, "%% No host address specified.\n");
- X return (0);
- X }
- X if ((*name >= '0') && (*name <= '9')) { /* IP address. */
- X addr->s_addr = inet_addr(name);
- X thingy.unsigned_thingy = addr->s_addr;
- X if (thingy.signed_thingy == -1) {
- X fprintf(stderr, "%% Couldn't find host %s .\n", name);
- X return (0);
- X }
- X } else { /* Host name. */
- X blob = gethostbyname(name);
- X
- X if (blob == NULL) {
- X fprintf(stderr, "%% Couldn't find host %s .\n", name);
- X return (0);
- X }
- X bcopy(blob->h_addr, addr, sizeof(struct in_addr));
- X }
- X
- X return (1); /* Success. */
- X}
- END_OF_FILE
- if test 20630 -ne `wc -c <'btclient.c'`; then
- echo shar: \"'btclient.c'\" unpacked with wrong size!
- fi
- # end of 'btclient.c'
- fi
- if test -f 'btclient.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'btclient.h'\"
- else
- echo shar: Extracting \"'btclient.h'\" \(1965 characters\)
- sed "s/^X//" >'btclient.h' <<'END_OF_FILE'
- X/*
- X * btclient.h: function declarations for the Broken Throne Client By Tom
- X * Boutell, 11/90- 2/91. Do As Thou Wilt, Only Please Send Me Copies!
- X *
- X * The three constants below can be changed if necessary to support unusal codes
- X * or non- ASCII machines. Both mdelete and mbackspace are accepted as a
- X * backspace key in an effort to improve compatibility with brain- dead
- X * Cursi. (Well, what ELSE is the plural of Curses? Cursesi?)
- X */
- X
- X#define mbackspace 8
- X#define mdelete 127
- X#define mescape 27
- X
- X#define _CURSORM1 1
- X#define _CURSORM2 2
- X#define _CURSORM3 3
- X#define _CURSORRECRUIT 4
- X#define _CURSORTELL 5
- X#define _CURSORCOMMAND 6
- X#define _CURSORCONSTRUCT 7
- X#define _CURSORDESTROY 8
- X
- X#define SECONDSLIMIT 0L
- X#define MICROSECONDSLIMIT 100000L
- X
- Xhex **map = 0;
- Xplayer players[_MAXPLAYERS];
- Xint playernumber;
- Xint totalplayers;
- Xint currenttime;
- Xint living;
- Xint port;
- Xint playerFd;
- Xint promptoffset;
- Xfd_set events;
- Xfd_set realevents;
- Xint inputstate;
- Xchar *host;
- X
- Xint connectstream();
- Xint inputwaiting();
- Xvoid waitevent();
- Xint waitshort();
- Xvoid setupmap();
- Xvoid displayhex();
- Xvoid flashhex();
- Xvoid tellplayer();
- Xvoid displayplayer();
- Xvoid readnullterm();
- Xvoid endprogram();
- Xvoid restorescreen();
- Xvoid displaysignal();
- Xvoid endtrap();
- Xint inrange();
- Xvoid promptplayer();
- Xint cursorx;
- Xint cursory;
- XWINDOW *info = 0;
- XWINDOW *output = 0;
- XWINDOW *mapw;
- Xint getmessage();
- Xint terrainimage[] = {' ', '.', 'T', 'M', 'F', 'C', 'S', '^'};
- Xchar specificspace[256];
- Xchar outputline[256];
- Xchar *specific;
- Xint inputfd;
- Xint xsize;
- END_OF_FILE
- if test 1965 -ne `wc -c <'btclient.h'`; then
- echo shar: \"'btclient.h'\" unpacked with wrong size!
- fi
- # end of 'btclient.h'
- fi
- if test -f 'btserver.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'btserver.h'\"
- else
- echo shar: Extracting \"'btserver.h'\" \(3048 characters\)
- sed "s/^X//" >'btserver.h' <<'END_OF_FILE'
- X/*
- X * btserver.h- declarations and controlling constants for Broken Throne.
- X * Copyright 1990 by Tom Boutell.
- X */
- X
- X#define _DEFAULTMAPSIZEX 16
- X#define _DEFAULTMAPSIZEY 16
- X#define _DEFAULTCITYCOST 90
- X#define _DEFAULTDESTROYCOST 10
- X#define _DEFAULTRECRUITTIME 60
- X#define _DEFAULTSPEED 5
- X
- X/* Upper limits (due to use of char in transfer) */
- X#define _MAXMAPSIZEX 128
- X#define _MAXMAPSIZEY 128
- X
- X#define _HEXSTATUS 65
- X#define _PLAYERSTATUS 66
- X#define _PLAYERDEAD 67
- X#define _ACTION 68
- X#define _TEXT 69
- X#define _STARTUP 70
- X#define _END 71
- X#define _YOUARE 72
- X
- X#define _MOVE 65
- X#define _RECRUIT 66
- X#define _QUIT 67
- X#define _PRIVATE 68
- X#define _TELLALL 69
- X#define _DISCONNECT 70
- X#define _CONSTRUCT 71
- X#define _DESTROY 72
- X
- Xextern hex **map;
- Xextern player players[_MAXPLAYERS];
- Xextern int currentplayer;
- Xextern int totalplayers;
- Xextern int currenttime;
- Xextern int living;
- Xextern int gamecontinuous;
- X
- X/* Beware terrain type zero... existing to keep C happy. */
- X
- Xvoid move(); /* location from,location to,int number */
- Xvoid tellcurrentplayer(); /* char* fmt, variable args */
- Xvoid setupmap();
- Xvoid recruit(); /* location at */
- Xint legal(); /* int x,int y */
- Xvoid killplayer(); /* int player */
- Xchar *namelocation(); /* location at */
- Xchar *nameplayer(); /* int player */
- Xint cost(); /* int x,y */
- Xvoid destroy(); /* location at */
- Xvoid construct(); /* location at */
- Xvoid endprogram();
- Xvoid stopgame(); /* char* message */
- Xvoid recruitenqueue(); /* enqueue an x,y location for
- X * recruitment */
- Xvoid recruitdequeue(); /* Remove the first item from the
- X * queue */
- Xvoid recruitall(); /* Recruit at any ready, enqueued towns and
- X * cities */
- Xvoid recruitqueueremove(); /* Remove location x,y if in recruit
- X * queue */
- Xvoid regionupdate(); /* Takes location, region taking, player
- X * taking */
- Xvoid regionchange(); /* Takes location, new region number to paint
- X * with */
- Xvoid regionnew(); /* Takes location, paints with new / recycled
- X * region # */
- Xvoid regionget(); /* Takes location, array of locations,
- X * pointer to int; fills in array with set of
- X * locations in the same region as first
- X * location (only if truly contiguous), and
- X * sets *int to total number of locations. */
- Xvoid support(); /* Takes no arguments, checks for support of
- X * forces, starves troops if not supported */
- Xvoid exiterror(); /* Exits with error code; frees memory if
- X * allocated */
- Xvoid freememory(); /* Frees allocated space */
- Xvoid endtrap(); /* Signal handler for server death */
- Xvoid waitenqueue(); /* Enqueues given fd for future game */
- Xvoid broadcastwaitqueue(); /* Sends message to all wait queue
- X * members */
- Xvoid fetchplayers(); /* Get players for new round of game */
- END_OF_FILE
- if test 3048 -ne `wc -c <'btserver.h'`; then
- echo shar: \"'btserver.h'\" unpacked with wrong size!
- fi
- # end of 'btserver.h'
- fi
- if test -f 'btserverrc' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'btserverrc'\"
- else
- echo shar: Extracting \"'btserverrc'\" \(2623 characters\)
- sed "s/^X//" >'btserverrc' <<'END_OF_FILE'
- X; A sample .btserverrc file.
- X; Lines beginning with ; or # are comments. Blank lines are
- X; permitted.
- X
- X; Command - line arguments always override .btserverrc settings.
- X; A .btserverrc in the current directory is looked for first;
- X; if none is found there, the user's home directory is checked.
- X; (Alternatively any default file can be specified with the
- X; -d option.)
- X
- X; There are reasonable hard - coded defaults for all the options below
- X; except for size and players. Players is usually set on the command
- X; line; a good size to set here if players will be using typical
- X; 80x25 ascii terminals is 16x16.
- X
- X; players sets a default number of players. Not commonly used
- X; since the number of players varies a lot with who's available.
- X; set to zero here so the server will give an error if the
- X; number of players isn't given on the command line (-n option).
- X
- Xplayers 0
- X
- X; sizex and sizey set the x and y dimensions of the map
- X; respectively. (Commented out here.)
- X; sizes specified here *or* on the command line are overridden if
- X; a map file is used by the size given on the first line of the
- X; map file.
- X
- Xsizex 16
- Xsizey 16
- X
- X; alternatively, size takes the same widthxheight format as
- X; the -s command - line argument.
- X
- Xsize 12x12
- X
- X; speed sets the number of seconds between game ticks.
- X
- Xspeed 4
- X
- X; citycost sets the number of action points required to
- X; turn a city into a town.
- X
- Xcitycost 80
- X
- X; destroycost sets the number of action points required to
- X; destroy a city or town.
- X
- Xdestroycost 10
- X
- X; recruittime sets the number of ticks (not seconds) between
- X; safe recruitments at a given city or town.
- X
- Xrecruittime 40
- X
- X; mapfile sets the name of a map file to be read by default.
- X; The -r option can be used on the command line to specify that
- X; the map be randomly generated anyway. Commented out in this
- X; example.
- X
- X;mapfile map.txt
- X
- X; specifies the default port on which the game takes place.
- X; Separate groups of players will want to set separate ports
- X; (between 1000 and 9999) since only one server can run on
- X; a given port number. 2727 is the default if no .btserverrc
- X; file is present and the -p option is not used.
- X
- Xport 2727
- X
- X; continuous is a switch. If turned "on", then the game will recycle
- X; and restart after all players have quit, and players who were
- X; unable to get into the first game will be brought in from a
- X; wait queue. If turned "off", "late" players will be told the
- X; game is busy, and the server will shut down after one game.
- X; off is the default.
- X
- Xcontinuous on
- X
- X; THINGS THAT PROBABLY SHOULD BE CONFIGURABLE, BUT AREN'T:
- X
- X; Distribution of terrain types on random maps.
- X; What else?
- X
- END_OF_FILE
- if test 2623 -ne `wc -c <'btserverrc'`; then
- echo shar: \"'btserverrc'\" unpacked with wrong size!
- fi
- # end of 'btserverrc'
- fi
- if test -f 'changes' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'changes'\"
- else
- echo shar: Extracting \"'changes'\" \(502 characters\)
- sed "s/^X//" >'changes' <<'END_OF_FILE'
- XSee the readme file for a description of changes in version 2.0.
- XThere have been several fundamental changes.
- X
- XNOTE: an apology to folks who sent me diff's way back shortly after
- Xversion 1.12; in the intervening year and a half since I ceased
- Xwork on the game to complete my undergraduate career sanely, I have
- Xlost your many nifty patches. ): I will quickly incorporate patches
- Xmade to version 2.0.
- X
- X(Sure enough, version 2.03, which you are looking at,
- Xincorporates several fixes. See the readme.)
- X
- X
- END_OF_FILE
- if test 502 -ne `wc -c <'changes'`; then
- echo shar: \"'changes'\" unpacked with wrong size!
- fi
- # end of 'changes'
- fi
- echo shar: End of archive 2 \(of 3\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 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
-