home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-01-26 | 54.2 KB | 2,076 lines |
- Path: uunet!charon.amdahl.com!pacbell.com!iggy.GW.Vitalink.COM!cs.widener.edu!eff!sol.ctr.columbia.edu!destroyer!gatech!emory!ogicse!zephyr.ens.tek.com!master!saab!billr
- From: billr@saab.CNA.TEK.COM (Bill Randle)
- Newsgroups: comp.sources.games
- Subject: v15i015: bt4 - Broken Throne, multiplayer realtime conquest game (V2.03), Part01/03
- Message-ID: <3826@master.CNA.TEK.COM>
- Date: 29 Oct 92 01:41:54 GMT
- Sender: news@master.CNA.TEK.COM
- Lines: 2064
- Approved: billr@saab.CNA.TEK.COM
- Xref: uunet comp.sources.games:1514
-
- Submitted-by: boutell@isis.cshl.org (Tom Boutell)
- Posting-number: Volume 15, Issue 15
- Archive-name: bt4/Part01
- Supersedes: bt3: Volume 12, Issue 52-53
- Environment: INET sockets, curses
-
- [This is the latest version of Broken Throne. It includes internal
- restructuring, new features and AIX support. -br]
-
- #! /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 1 (of 3)."
- # Contents: MANIFEST btrobot.c btserver.c
- # Wrapped by billr@saab on Wed Oct 28 17:38:00 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'MANIFEST' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MANIFEST'\"
- else
- echo shar: Extracting \"'MANIFEST'\" \(765 characters\)
- sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
- X File Name Archive # Description
- X-----------------------------------------------------------
- X INSTALL 3
- X MANIFEST 1 This shipping list
- X Makefile 3
- X bt.doc 2
- X bt.h 3
- X btclient.c 2
- X btclient.h 2
- X btinterface.c 3
- X btinterface.h 3
- X btpack.c 3
- X btpack.h 3
- X btrobot.c 1
- X btserver.c 1
- X btserver.h 2
- X btserverrc 2
- X changes 2
- X map.txt 3
- X msleep.c 3
- X msleep.h 3
- X readme 3
- X xbt 3
- END_OF_FILE
- if test 765 -ne `wc -c <'MANIFEST'`; then
- echo shar: \"'MANIFEST'\" unpacked with wrong size!
- fi
- # end of 'MANIFEST'
- fi
- if test -f 'btrobot.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'btrobot.c'\"
- else
- echo shar: Extracting \"'btrobot.c'\" \(10429 characters\)
- sed "s/^X//" >'btrobot.c' <<'END_OF_FILE'
- X/*
- X * Robot player for Broken Throne- 12/90 by Tom Boutell This robot is
- X * basically a hacked client. You can use it as a starting point for robots
- X * of your own!
- X */
- X
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/socket.h>
- 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#include <math.h>
- X
- X#include "bt.h"
- X#include "btpack.h"
- X
- X#define SECONDSLIMIT 0L
- X#define MICROSECONDSLIMIT 1L
- Xhex **map;
- Xint gamemapsizex;
- Xint gamemapsizey;
- Xplayer players[20];
- Xint playernumber;
- Xplayer *me;
- Xint totalplayers;
- Xint currenttime;
- Xint living;
- Xint port;
- Xint playerFd;
- Xint promptoffset;
- Xfd_set server;
- Xint inputstate;
- Xchar *host;
- Xint connectstream();
- Xint inputwaiting();
- Xvoid setupmap();
- Xvoid readnullterm();
- Xvoid endprogram();
- Xint inrange();
- Xint legal();
- Xvoid move();
- Xint getmessage();
- Xchar specificspace[256];
- Xchar outputline[256];
- Xchar *specific;
- X
- Xmain(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X char hostname[81];
- X int done;
- X char messagetype;
- X location at;
- X location from, to;
- X int theplayer;
- X int x, y, roll;
- X int xexp, yexp, xnew, ynew;
- X int xbest, ybest, sbest, sthis;
- X int tried;
- X int offset;
- X int count;
- X int i;
- 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, "btrobot: 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, "btrobot: port # missing for -p option.\n");
- X exit(-1);
- X }
- X } else {
- X fprintf(stderr, "Unknown option.\n");
- X fprintf(stderr, "Usage: btrobot -h hostname [-p port#]\n");
- X exit(-1);
- X }
- X }
- X
- X if (connectstream() == 0) {
- X perror("Socket unopenable.\n");
- X exit(1);
- X }
- X signal(SIGPIPE, endprogram);
- X signal(SIGTERM, endprogram);
- X signal(SIGQUIT, endprogram);
- X signal(SIGINT, endprogram);
- X done = 0;
- X currenttime = 0;
- X specific = specificspace;
- X /* Get YOUARE message */
- X do {
- X getmessage(&messagetype, specific);
- X if (messagetype == _END) {
- X endprogram();
- X }
- X } while (messagetype != _YOUARE);
- X playernumber = specific[0] - 64;
- X me = &players[playernumber];
- X /* Get STARTUP message */
- X do {
- X getmessage(&messagetype, specific);
- X if (messagetype == _END) {
- X endprogram();
- X }
- X } while (messagetype != _STARTUP);
- X totalplayers = specific[0] - 64;
- X gamemapsizex = specific[1] - 64;
- X gamemapsizey = specific[2] - 64;
- X setupmap();
- X for (count = 1; (count <= totalplayers); count++)
- X players[count].live = 1;
- X
- X while (done != 2) {
- X while (getmessage(&messagetype, specific)) {
- 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 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 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 }
- X }
- X }
- X if (theplayer == playernumber) {
- X done = 2;
- X }
- X break;
- X case _TEXT:
- 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 }
- X }
- X currenttime++;
- X break;
- X case _END:
- X done = 2;
- X break;
- X }
- X }
- X sleep(1);
- X /* Now it's time to think. */
- X /* Sweep our towns and do useful things: */
- X /* osmose troops around the board. */
- X if ((me->action) > 5) {
- X tried = 0;
- X while (tried == 0) {
- X xexp++;
- X if (xexp == gamemapsizex) {
- X xexp = 0;
- X yexp++;
- X if (yexp == gamemapsizey) {
- X yexp = 0;
- X tried = 1;
- X }
- X }
- X if ((map[xexp][yexp].owner == playernumber) && (map[xexp][yexp].troops > 0)) {
- X xbest = (-1);
- X ybest = (-1);
- X sbest = (-9999);
- X for (y = (-1); (y <= 1); y++) {
- X for (x = (-1); (x <= 1); x++) {
- X sthis = 0;
- X if (legal(xexp + x, yexp + y)) {
- X if (map[xexp + x][yexp + y].terrain == 6)
- X sthis = sthis - 50;
- X if (map[xexp + x][yexp + y].owner != playernumber)
- X sthis = sthis + 30;
- X if (map[xexp + x][yexp + y].terrain == 2)
- X sthis = sthis + 20;
- X if (map[xexp + x][yexp + y].terrain == 5)
- X sthis = sthis + 25;
- X if ((sthis > sbest) ||
- X ((sthis == sbest) && (((rand() * 512) % 2) == 0))) {
- X xbest = xexp + x;
- X ybest = yexp + y;
- X sbest = sthis;
- X }
- X }
- X }
- X }
- X xnew = xbest;
- X ynew = ybest;
- X if ((xnew != xexp) || (ynew != yexp)) {
- X if ((map[xexp][yexp].terrain != 6) || (((rand() * 512) % 10) > 7)) {
- X move(xexp, yexp, xnew, ynew, 1);
- X tried = 1;
- X }
- X }
- X }
- X }
- X }
- X }
- X /* Terminating code - needs to be called on CTRLC also. */
- X endprogram();
- X}
- X
- Xvoid
- Xmove(x1, y1, x2, y2, troops)
- X int x1, y1, x2, y2, troops;
- X{
- X outputline[0] = _MOVE;
- X outputline[1] = x1 + 64;
- X outputline[2] = y1 + 64;
- X outputline[3] = x2 + 64;
- X outputline[4] = y2 + 64;
- X packint(5, troops);
- X outputline[8] = 0;
- X write(playerFd, outputline, strlen(outputline) + 1);
- X}
- X
- Xvoid
- Xendprogram()
- X{
- X outputline[0] = _DISCONNECT;
- X outputline[1] = NULL;
- X write(playerFd, outputline, strlen(outputline) + 1);
- X /*
- X * Give server a chance to send any messages about our death without
- X * a SIGPIPE
- X */
- X sleep(2);
- X /* Now close connection */
- X close(playerFd);
- X exit(-1);
- X}
- X
- Xint
- Xlegal(x, y)
- X int x, y;
- X{
- X if (inrange(x, 0, gamemapsizex - 1) && inrange(y, 0, gamemapsizey - 1))
- X return 1;
- X else
- X return 0;
- 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 char in;
- X int pos;
- X *messagetype = 0;
- X *specific = 0;
- X if (!inputwaiting(&server, playerFd)) {
- X return 0;
- X }
- X read(playerFd, messagetype, 1);
- X pos = 0;
- 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 (!inputwaiting(&server, playerFd));
- X read(playerFd, 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 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 }
- X }
- 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, &server);
- X playerFd = s;
- X return (1);
- X}
- X
- Xint
- Xinputwaiting(sfdset, sfd)
- X fd_set *sfdset;
- X int sfd;
- X{
- X int errrec;
- X fd_set readfds;
- X struct timeval waitTime;
- X waitTime.tv_sec = SECONDSLIMIT;
- X waitTime.tv_usec = MICROSECONDSLIMIT;
- X bcopy((char *) sfdset, (char *) &readfds, sizeof(*sfdset));
- X if (select(FD_SETSIZE, &readfds, NULL, NULL, &waitTime) < 0) {
- X if (errno != EINTR) {
- X perror("select");
- X }
- X return 0;
- X }
- X if (FD_ISSET(sfd, &readfds))
- X return 1;
- X else
- X return 0;
- X}
- 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 10429 -ne `wc -c <'btrobot.c'`; then
- echo shar: \"'btrobot.c'\" unpacked with wrong size!
- fi
- # end of 'btrobot.c'
- fi
- if test -f 'btserver.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'btserver.c'\"
- else
- echo shar: Extracting \"'btserver.c'\" \(39546 characters\)
- sed "s/^X//" >'btserver.c' <<'END_OF_FILE'
- X#include <math.h>
- X#include <stdio.h>
- X#include <varargs.h>
- X#include <string.h>
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#include <signal.h>
- X#include <stdlib.h>
- X#include "bt.h"
- X#include "btserver.h"
- X#include "btinterface.h"
- X#include "btpack.h"
- X#include "msleep.h"
- X
- Xhex **map;
- Xplayer players[_MAXPLAYERS];
- X
- Xint gamemapsizey;
- Xint gamemapsizex;
- Xint gamespeed;
- Xint gamecitycost;
- Xint gamedestroycost;
- Xint gamerecruittime;
- Xint portnumber;
- Xint gamecontinuous;
- X
- Xint currentplayer;
- Xint totalplayers;
- Xint currenttime;
- Xint ismap;
- Xint living;
- Xint memoryalloced;
- Xchar gamemapfile[81];
- X
- Xint terrainfrom[] = {0, 0, 10, 10, 5, 5, -10, 0};
- Xint terrainto[] = {0, 0, -10, -10, -10, -15, 10, 0};
- Xint terrainpopulation[] = {0, 100, 300, 50, 75, 400, 10, 0};
- X
- X#define QUEUESIZE (gamemapsizex*gamemapsizey)
- Xstatic location *recruitqueue;
- Xstatic int queuefront;
- Xstatic int queueback;
- X
- X
- X/* And enough space for half that many regions */
- X
- X/*
- X * Track population and # of troops, and remember one hex that's in the
- X * region from which to seek others when needed
- X */
- X
- Xstatic int *regionspop;
- Xstatic location *regionshex;
- Xstatic int *regionstroops;
- Xstatic int regionnext;
- X
- X#define STREQ(a, b) (strcmp(a,b)==0)
- X#define SAFEARG ((i+1)<argc)
- X
- Xvoid
- Xreadbtserverrc(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X int i;
- X char defaultfile[81];
- X char *path;
- X FILE *f;
- X int found;
- X path = getenv("HOME");
- X sprintf(defaultfile, ".btserverrc");
- X if (!(f = fopen(defaultfile, "r"))) {
- X sprintf(defaultfile, "%s/btserverrc", path);
- X if (!(f = fopen(defaultfile, "r"))) {
- X found = 0;
- X } else {
- X found = 1;
- X }
- X } else {
- X found = 1;
- X }
- X for (i = 1; (i < argc); i++) {
- X if (STREQ(argv[i], "-d")) {
- X if (SAFEARG) {
- X sprintf(defaultfile, "%s", argv[i + 1]);
- X if (!(f = fopen(defaultfile, "r"))) {
- X found = 0;
- X fprintf(stderr, "btserver: default file specified not found.\n");
- X exiterror();
- X } else {
- X found = 1;
- X }
- X } else {
- X fprintf(stderr, "btserver: filename missing for -d option.\n");
- X exiterror();
- X }
- X }
- X }
- X if (!found) {
- X return; /* no .btserverrc */
- X }
- X /* Now process file */
- X while (!feof(f)) {
- X char sbuf[81];
- X char *item;
- X char *valuestr;
- X char *sp;
- X int value;
- X if (!(fgets(sbuf, 81, f)))
- X break;
- X if ((sbuf[0] == ';') || (sbuf[0] == '#'))
- X continue; /* Comment */
- X sp = strchr(sbuf, ' ');
- X if (!sp)
- X continue; /* Blank or comment line */
- X *sp = '\0';
- X item = sbuf;
- X valuestr = sp + 1;
- X /* Stomp CR */
- X valuestr[strlen(valuestr) - 1] = '\0';
- X value = atoi(valuestr);
- X
- X if (STREQ(item, "players")) {
- X totalplayers = value;
- X if (totalplayers > _MAXPLAYERS) {
- X fprintf(stderr, "Error in default file: max of %d players.\n",
- X _MAXPLAYERS);
- X fclose(f);
- X exiterror();
- X }
- X } else if (STREQ(item, "sizex")) {
- X gamemapsizex = value;
- X } else if (STREQ(item, "sizey")) {
- X gamemapsizey = value;
- X } else if (STREQ(item, "size")) {
- X if (sscanf(valuestr, "%dx%d", &gamemapsizex, &gamemapsizey) < 2) {
- X fprintf(stderr,
- X "Error in default file: dimension(s) missing for size option.\n");
- X fprintf(stderr, "(example syntax: size 5x5 - note the x)\n");
- X exiterror();
- X }
- X } else if (STREQ(item, "speed")) {
- X gamespeed = value;
- X } else if (STREQ(item, "citycost")) {
- X gamecitycost = value;
- X } else if (STREQ(item, "destroycost")) {
- X gamedestroycost = value;
- X } else if (STREQ(item, "recruittime")) {
- X gamerecruittime = value;
- X } else if (STREQ(item, "mapfile")) {
- X ismap = 1;
- X strcpy(gamemapfile, valuestr);
- X } else if (STREQ(item, "continuous")) {
- X if (STREQ(valuestr, "on")) {
- X gamecontinuous = 1;
- X } else {
- X gamecontinuous = 0;
- X }
- X } else if (STREQ(item, "port")) {
- X portnumber = value;
- X if (value < 1000 || value > 9999) {
- X fprintf(stderr, "Error in default file: port number must be\n");
- X fprintf(stderr, "between 1000 and 9999.\n");
- X exiterror();
- X }
- X }
- X }
- X fclose(f);
- X}
- X
- Xvoid
- Xusage()
- X{
- X fprintf(stderr,
- X "Usage: btserver -n [# of players] -p [port # (default 2727)]\n");
- X fprintf(stderr,
- X "-m [map filename; -r creates random map] -d [defaults file; default\n");
- X fprintf(stderr, "~/.btserverrc] -s [widthxheight; default %dx%d]\n",
- X _DEFAULTMAPSIZEX, _DEFAULTMAPSIZEY);
- X}
- X
- Xvoid
- Xreadargs(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X int i;
- X for (i = 1; (i < argc); i++) {
- X if (STREQ(argv[i], "-d")) {
- X i++; /* Ignore (and ignore argument) */
- X } else if (STREQ(argv[i], "-n")) {
- X if (SAFEARG) {
- X totalplayers = atoi(argv[++i]);
- X if (totalplayers > _MAXPLAYERS) {
- X fprintf(stderr, "btserver: maximum of %d players.\n",
- X _MAXPLAYERS);
- X exiterror();
- X }
- X } else {
- X fprintf(stderr, "btserver: # of players missing for -n option.\n");
- X exiterror();
- X }
- X } else if (STREQ(argv[i], "-p")) {
- X if (SAFEARG) {
- X portnumber = atoi(argv[++i]);
- X if (portnumber < 1000 || portnumber > 9999) {
- X fprintf(stderr, "btserver: port # must be between 1000 and 9999.\n");
- X exiterror();
- X }
- X } else {
- X fprintf(stderr, "btserver: port # missing for -p option.\n");
- X exiterror();
- X }
- X } else if (STREQ(argv[i], "-m")) {
- X if (SAFEARG) {
- X strcpy(gamemapfile, argv[++i]);
- X ismap = 1;
- X } else {
- X fprintf(stderr, "btserver: filename missing for -m option.\n");
- X exiterror();
- X }
- X } else if (STREQ(argv[i], "-r")) {
- X ismap = 0;
- X } else if (STREQ(argv[i], "-s")) {
- X if (SAFEARG) {
- X if (sscanf(argv[++i], "%dx%d", &gamemapsizex, &gamemapsizey) < 2) {
- X fprintf(stderr, "btserver: dimension(s) missing for -s option.\n");
- X fprintf(stderr, "(example syntax: -s 5x5 - note the x)\n");
- X exiterror();
- X }
- X } else {
- X fprintf(stderr, "btserver: dimension(s) missing for -s option.\n");
- X fprintf(stderr, "(example syntax: -s 5x5 - note the x)\n");
- X exiterror();
- X }
- X } else if (STREQ(argv[i], "-?") || STREQ(argv[i], "-h")) {
- X usage();
- X exiterror();
- X } else {
- X fprintf(stderr, "Unknown option.\n");
- X usage();
- X exiterror();
- X }
- X }
- X}
- X
- Xint
- Xmain(argc, argv)
- X int argc;
- X char *argv[];
- X{
- X char requesttype;
- X location from, to;
- X int number;
- X long lasttime;
- X long newtime;
- X char specificspace[256];
- X char *specific;
- X int offset;
- X location size;
- X printf("Broken Throne server program launching...\n");
- X ismap = 0;
- X totalplayers = 0;
- X portnumber = 2727;
- X memoryalloced = 0;
- X gamemapsizex = _DEFAULTMAPSIZEX;
- X gamemapsizey = _DEFAULTMAPSIZEY;
- X gamespeed = _DEFAULTSPEED;
- X gamecitycost = _DEFAULTCITYCOST;
- X gamedestroycost = _DEFAULTDESTROYCOST;
- X gamerecruittime = _DEFAULTRECRUITTIME;
- X gamecontinuous = 0; /* Not continuous by default */
- X ismap = 0;
- X readbtserverrc(argc, argv);
- X if (argc > 1) {
- X readargs(argc, argv);
- X }
- X if (ismap) {
- X FILE *f;
- X if (!(f = fopen(gamemapfile, "r"))) {
- X fprintf(stderr, "btserver: unable to open map file %s.\n", gamemapfile);
- X exiterror();
- X }
- X if (fscanf(f, "%dx%d", &gamemapsizex, &gamemapsizey) < 2) {
- X fprintf(stderr, "btserver: dimensions missing from map file %s.\n",
- X gamemapfile);
- X fclose(f);
- X exiterror();
- X }
- X fclose(f);
- X }
- X if ((gamemapsizex > _MAXMAPSIZEX) || (gamemapsizey > _MAXMAPSIZEY)) {
- X fprintf(stderr, "Maximum map dimensions: %dx%d.\n",
- X _MAXMAPSIZEX, _MAXMAPSIZEY);
- X exiterror();
- X }
- X if (!totalplayers) {
- X fprintf(stderr, "Error: a number of players must be specified.\n");
- X usage();
- X exiterror();
- X }
- X setupinterface(portnumber);
- X do {
- X fetchplayers();
- X living = totalplayers;
- X specific = specificspace;
- X time(&lasttime);
- X srand(lasttime % 1024); /* Get a new random # seed */
- X signal(SIGTERM, endtrap);
- X signal(SIGQUIT, endtrap);
- X signal(SIGINT, endtrap);
- X size.x = gamemapsizex;
- X size.y = gamemapsizey;
- X currenttime = 100;
- X broadcast(_STARTUP, (pointer) & size);
- X setupmap(ismap, gamemapfile);
- X while (living > 0) {
- X msleep(100000);
- X while (getrequest(¤tplayer, &requesttype, specific)) {
- X offset = 0;
- X switch ((int) requesttype) {
- X case _DISCONNECT:
- X if (players[currentplayer].live != 0) {
- X players[currentplayer].live = 0;
- X killplayer(currentplayer);
- X }
- X disconnect_player(currentplayer);
- X break;
- X case _MOVE:
- X striplocation(&from, specific, &offset);
- X striplocation(&to, specific, &offset);
- X stripint(&number, specific, &offset);
- X move(from, to, number);
- X break;
- X case _RECRUIT:
- X striplocation(&from, specific, &offset);
- X recruitqueueremove(from.x, from.y);
- X recruit(from);
- X recruitenqueue(from.x, from.y);
- X break;
- X case _CONSTRUCT:
- X striplocation(&from, specific, &offset);
- X construct(from);
- X break;
- X case _DESTROY:
- X striplocation(&from, specific, &offset);
- X destroy(from);
- X break;
- X case _QUIT:
- X killplayer(currentplayer);
- X break;
- X case _PRIVATE:
- X sprintf(playertext, "%c: %s", currentplayer + 64, &specific[1]);
- X tellplayer(specific[0] - 64);
- X break;
- X case _TELLALL:
- X sprintf(playertext, "%c to ALL: %s", currentplayer + 64, specific);
- X broadcast(_TEXT, (pointer) playertext);
- X }
- X }
- X time(&newtime);
- X if (newtime - lasttime >= gamespeed) {
- X currenttime++;
- X broadcast(_ACTION, (pointer) NULL);
- X recruitall();
- X support();
- X for (number = 1; (number <= totalplayers); number++)
- X players[number].action += (2 + players[number].citadels);
- X lasttime = newtime;
- X }
- X }
- X freememory();
- X } while (gamecontinuous);
- X fprintf(stderr, "Server Shutdown\n");
- X endprogram();
- X exit(0);
- X}
- X
- Xvoid
- Xendtrap()
- X{
- X broadcast(_TEXT, (pointer) "Server died");
- X broadcastwaitqueue(_TEXT, (pointer) "Server died");
- X endprogram();
- X}
- X
- Xvoid
- Xendprogram()
- X{
- X broadcast(_END, (pointer) NULL);
- X broadcastwaitqueue(_END, (pointer) NULL);
- X shutdowninterface();
- X freememory();
- X exit(0);
- X}
- X
- Xvoid
- Xexiterror()
- X{
- X freememory();
- X exit(-1);
- X}
- X
- Xvoid
- Xfreememory()
- X{
- X int i;
- X if (memoryalloced) {
- X free(regionshex);
- X free(regionspop);
- X free(regionstroops);
- X for (i = 0; (i < gamemapsizex); i++) {
- X free(map[i]);
- X }
- X free(map);
- X memoryalloced = 0;
- X }
- X}
- X
- Xvoid
- Xrecruitdequeue()
- X{
- X if (queuefront == queueback)
- X return;
- X queuefront++;
- X if (queuefront >= QUEUESIZE)
- X queuefront = 0;
- X}
- X
- Xvoid
- Xrecruitenqueue(x, y)
- X int x, y;
- X{
- X recruitqueue[queueback].x = x;
- X recruitqueue[queueback].y = y;
- X queueback++;
- X if (queueback >= QUEUESIZE)
- X queueback = 0;
- X}
- X
- Xvoid
- Xrecruitqueueremove(x, y)
- X int x, y;
- X{
- X int i;
- X i = queuefront;
- X while (i != queueback) {
- X if ((recruitqueue[i].x == x) && (recruitqueue[i].y == y)) {
- X recruitqueue[i].x = -1; /* Mark as invalid */
- X return;
- X }
- X i++;
- X if (i >= QUEUESIZE)
- X i = 0;
- X }
- X}
- X
- Xvoid
- Xsupport()
- X{
- X location *hexes;
- X int total;
- X int i;
- X hexes = (location *) malloc(sizeof(location) * gamemapsizex * gamemapsizey);
- X for (i = 1; (i < regionnext); i++) {
- X int supportable;
- X int deficit;
- X if (regionspop[i] == 0)
- X continue; /* No territory - defunct */
- X supportable = regionspop[i] / 100;
- X if (supportable < regionstroops[i]) {
- X int where;
- X int origwhere;
- X location at;
- X deficit = regionstroops[i] - supportable;
- X /* Have a starvation event somewhere */
- X regionget(regionshex[i], hexes, &total);
- X /* If the survey didn't fix it, it's real */
- X if (supportable < regionstroops[i]) {
- X where = (rand() % total);
- X origwhere = where;
- X do {
- X at = hexes[where];
- X if (map[at.x][at.y].troops) {
- X int owner;
- X owner = map[at.x][at.y].owner;
- X map[at.x][at.y].troops--;
- X players[owner].troops--;
- X regionstroops[i]--;
- X sprintf(playertext, "Starvation at %s.", namelocation(at));
- X tellplayer(owner);
- X broadcast(_HEXSTATUS, (pointer) & at);
- X broadcast(_PLAYERSTATUS, (pointer) & owner);
- X break;
- X }
- X where++;
- X if (where >= total) {
- X where = 0;
- X }
- X } while (where != origwhere);
- X }
- X }
- X }
- X free(hexes);
- X}
- X
- Xvoid
- Xrecruitall()
- X{
- X int x, y;
- X while (queuefront != queueback) {
- X x = recruitqueue[queuefront].x;
- X y = recruitqueue[queuefront].y;
- X if (x < 0) { /* Destroyed */
- X recruitdequeue();
- X continue;
- X }
- X if (map[x][y].lastuse <= (currenttime - gamerecruittime)) {
- X currentplayer = map[x][y].owner;
- X recruit(recruitqueue[queuefront]);
- X recruitdequeue();
- X recruitenqueue(x, y);
- X } else { /* This is at the front and not ready, so
- X * none are ready */
- X return;
- X }
- X }
- X}
- X
- Xvoid
- Xstopgame(message)
- X char *message;
- X{
- X broadcast(_TEXT, (pointer) message);
- X endprogram();
- X}
- X
- Xint
- Xcost(x, y)
- X int x;
- X int y;
- X{
- X if (map[x][y].owner == currentplayer)
- X return 2;
- X else
- X return 4;
- X}
- X
- Xvoid
- Xregionupdate(at, new, newowner)
- X location at;
- X int new;
- X int newowner;
- X{
- X int old;
- X int dpop;
- X int oldtotal = 0;
- X int newtotal = 0;
- X int x, y;
- X int i;
- X location oldnbrs[8];
- X location newnbrs[8];
- X old = map[at.x][at.y].region;
- X map[at.x][at.y].owner = newowner;
- X map[at.x][at.y].region = new;
- X dpop = map[at.x][at.y].population;
- X regionspop[old] -= dpop;
- X regionspop[new] += dpop;
- X /*
- X * If previously unowned, no split is possible; if previously owned,
- X * pay attention
- X */
- X if (old) {
- X for (x = at.x - 1; (x <= at.x + 1); x++) {
- X for (y = at.y - 1; (y <= at.y + 1); y++) {
- X if ((!(legal(x, y))) || ((x == at.x) && (y == at.y)))
- X continue;
- X if (map[x][y].region == old) {
- X location l;
- X l.x = x;
- X l.y = y;
- X oldnbrs[oldtotal++] = l;
- X } else if (map[x][y].owner == newowner) {
- X location l;
- X l.x = x;
- X l.y = y;
- X newnbrs[newtotal++] = l;
- X }
- X }
- X }
- X if (oldtotal) {
- X /*
- X * Check each neighbor; if a path doesn't exist to
- X * the first, then make a new region including that
- X * neighbor. First make sure the region hasn't
- X * already been changed (because it's adjacent to an
- X * already - broken - off neighbor).
- X */
- X
- X /*
- X * First, set the seed hex of the first neighbors'
- X * region to be the first neighbors' location, since
- X * it might otherwise fall in a broken - off region.
- X */
- X
- X regionshex[map[oldnbrs[0].x][oldnbrs[0].y].region] = oldnbrs[0];
- X
- X for (i = 1; (i < oldtotal); i++) {
- X if (map[oldnbrs[i].x][oldnbrs[i].y].region == old) {
- X if (!(regionpath(oldnbrs[0], oldnbrs[i]))) {
- X regionnew(oldnbrs[i]);
- X }
- X }
- X }
- X }
- X }
- X /* Now see if regions belonging to the new owner have been joined */
- X if (newtotal) {
- X for (i = 0; (i < newtotal); i++) {
- X if (map[newnbrs[i].x][newnbrs[i].y].region != new) {
- X regionchange(newnbrs[i], new);
- X }
- X }
- X }
- X /* Dump map */
- X#ifdef DUMPMAP
- X for (x = 0; (x < regionnext); x++) {
- X printf("%d:%d,%d ", x, regionspop[x], regionstroops[x]);
- X }
- X
- X printf("\n");
- X for (y = 0; (y < gamemapsizey); y++) {
- X for (x = 0; (x < gamemapsizex); x++) {
- X printf("%d ", map[x][y].region);
- X }
- X printf("\n");
- X }
- X printf("\n");
- X#endif
- X}
- X
- X/* The x and y components of the 8 directions */
- X
- Xstatic int dirx[] = {-1, 0, 1, -1, 1, -1, 0, 1};
- Xstatic int diry[] = {-1, -1, -1, 0, 0, 1, 1, 1};
- X
- Xint
- Xregionpath(from, to)
- X location from, to;
- X{
- X location *locs;
- X int *dirs;
- X int **been;
- X int hloc = 0;
- X int r;
- X int x, y;
- X int result = 0;
- X locs = (location *) malloc(sizeof(location) * gamemapsizex * gamemapsizey);
- X dirs = (int *) malloc(sizeof(int) * gamemapsizex * gamemapsizey);
- X been = (int **) malloc(sizeof(int *) * gamemapsizex);
- X locs[hloc] = from;
- X dirs[hloc] = 0;
- X for (x = 0; (x < gamemapsizex); x++) {
- X been[x] = (int *) malloc(sizeof(int) * gamemapsizey);
- X }
- X r = map[from.x][from.y].region;
- X for (y = 0; (y < gamemapsizey); y++) {
- X for (x = 0; (x < gamemapsizex); x++) {
- X been[x][y] = 0;
- X }
- X }
- X while (1) {
- X int d;
- X location l;
- X location next;
- X d = dirs[hloc];
- X l = locs[hloc];
- X been[l.x][l.y] = 1;
- X while (1) {
- X if (l.x == to.x && l.y == to.y) {
- X result = 1;
- X goto freemem;
- X }
- X next.x = l.x + dirx[d];
- X next.y = l.y + diry[d];
- X if (legal(next.x, next.y) &&
- X (map[next.x][next.y].region == r) &&
- X ((!been[next.x][next.y]))) {
- X hloc++;
- X locs[hloc] = next;
- X dirs[hloc] = 0;
- X break;
- X } else {
- X d++;
- X if (d > 7) {
- X hloc--;
- X if (hloc < 0) {
- X result = 0;
- X goto freemem;
- X } else {
- X break;
- X }
- X }
- X }
- X }
- X }
- Xfreemem:
- X free(locs);
- X free(dirs);
- X for (x = 0; (x < gamemapsizex); x++) {
- X free(been[x]);
- X }
- X free(been);
- X return result;
- X}
- X
- Xvoid
- Xregionchange(at, new)
- X location at;
- X int new;
- X{
- X location *hexes;
- X int total;
- X int i;
- X int old;
- X hexes = (location *) malloc(sizeof(hex) * gamemapsizex * gamemapsizey);
- X regionget(at, hexes, &total);
- X old = map[at.x][at.y].region;
- X for (i = 0; (i < total); i++) {
- X hex *h;
- X h = &map[hexes[i].x][hexes[i].y];
- X h->region = new;
- X regionspop[old] -= h->population;
- X regionspop[new] += h->population;
- X regionstroops[old] -= h->troops;
- X regionstroops[new] += h->troops;
- X }
- X free(hexes);
- X}
- X
- Xvoid
- Xregionget(at, hexes, total)
- X location at;
- X location *hexes;
- X int *total;
- X{
- X /* My favorite organic floodfill */
- X int r;
- X int **been;
- X int cseed = 0;
- X int hseed = 1;
- X int x, y;
- X been = (int **) malloc(sizeof(int *) * gamemapsizex);
- X for (x = 0; (x < gamemapsizex); x++) {
- X been[x] = (int *) malloc(sizeof(int) * gamemapsizey);
- X }
- X for (y = 0; (y < gamemapsizey); y++) {
- X for (x = 0; (x < gamemapsizex); x++) {
- X been[x][y] = 0;
- X }
- X }
- X hexes[0] = at;
- X been[at.x][at.y] = 1;
- X r = map[at.x][at.y].region;
- X /*
- X * While we're here, may as well fix these values in case I've
- X * managed to break them
- X */
- X regionspop[r] = 0;
- X regionstroops[r] = 0;
- X regionspop[r] += map[at.x][at.y].population;
- X regionstroops[r] += map[at.x][at.y].troops;
- X do {
- X int i;
- X location c;
- X c = hexes[cseed];
- X cseed++;
- X for (i = 0; (i < 8); i++) {
- X location l;
- X l.x = c.x + dirx[i];
- X l.y = c.y + diry[i];
- X if (legal(l.x, l.y) &&
- X (map[l.x][l.y].region == r) && (!been[l.x][l.y])) {
- X hexes[hseed] = l;
- X hseed++;
- X been[l.x][l.y] = 1;
- X regionspop[r] += map[l.x][l.y].population;
- X regionstroops[r] += map[l.x][l.y].troops;
- X }
- X }
- X } while (cseed < hseed);
- X *total = hseed;
- X for (x = 0; (x < gamemapsizex); x++) {
- X free(been[x]);
- X }
- X free(been);
- X}
- X
- Xvoid
- Xregionnew(at)
- X location at;
- X{
- X int i;
- X for (i = 1; (i < regionnext); i++) {
- X if (regionspop[i] == 0) {
- X regionstroops[i] = 0;
- X regionchange(at, i);
- X regionshex[i] = at;
- X return;
- X }
- X }
- X regionshex[regionnext] = at;
- X regionchange(at, regionnext++);
- X}
- X
- Xvoid
- Xmove(from, to, number)
- X location from;
- X location to;
- X int number;
- X{
- X int owner;
- X int enemystrength;
- X int unitsa;
- X int unitsb;
- X int numberold;
- X int enemyold;
- X int stragglers;
- X int marchers;
- X int weight;
- X if (number == 0) {
- X sprintf(playertext, "Ignored (no troops moved).");
- X tellcurrentplayer();
- X return;
- X }
- X if (abs(from.x - to.x) > 1 || abs(from.y - to.y) > 1) {
- X sprintf(playertext, "That destination is out of range.\n");
- X tellcurrentplayer();
- X return;
- X }
- X if (map[from.x][from.y].owner == currentplayer)
- X if (players[currentplayer].action >= number * cost(to.x, to.y))
- X if (map[from.x][from.y].troops >= number)
- X map[from.x][from.y].troops -= number;
- X else {
- X sprintf(playertext, "You do not have enough troops in that hex.\n");
- X tellcurrentplayer();
- X return;
- X }
- X else {
- X sprintf(playertext, "You don't have enough action points.\n");
- X tellcurrentplayer();
- X return;
- X }
- X else {
- X sprintf(playertext, "You don't control that hex!\n");
- X tellcurrentplayer();
- X return;
- X }
- X players[currentplayer].action -= number * cost(to.x, to.y);
- X switch (map[to.x][to.y].terrain) {
- X case 1:
- X break;
- X case 2:
- X break;
- X case 3:
- X stragglers = 0;
- X for (marchers = 1; (marchers <= number); marchers++) {
- X if ((rand() & 512) == 0)
- X stragglers++;
- X }
- X map[from.x][from.y].troops += stragglers;
- X if (stragglers == number) {
- X sprintf(playertext, "No troops made it through the mountains.");
- X tellcurrentplayer();
- X broadcast(_PLAYERSTATUS, (pointer) & currentplayer);
- X return;
- X } else if (stragglers >= 0) {
- X sprintf(playertext, "%d of your armies have not crossed.", stragglers);
- X tellcurrentplayer();
- X number -= stragglers;
- X }
- X break;
- X case 4:
- X break;
- X case 5:
- X break;
- X case 6:
- X if ((rand() & 512) == 0) {
- X players[currentplayer].troops--;
- X regionstroops[map[from.x][from.y].region]--;
- X if (number == 1) {
- X sprintf(playertext, "Your army was sucked into the swamp.");
- X tellcurrentplayer();
- X number = 0;
- X break;
- X } else {
- X sprintf(playertext, "One of your units was lost in the swamp.");
- X tellcurrentplayer();
- X number--;
- X break;
- X }
- X }
- X break;
- X case 7:
- X sprintf(playertext, "Crags are impassable.");
- X tellcurrentplayer();
- X map[from.x][from.y].troops += number;
- X players[currentplayer].action += number * cost(to.x, to.y);
- X return;
- X }
- X owner = map[to.x][to.y].owner;
- X if (owner != currentplayer) {
- X if (owner != 0)
- X broadcast(_LOOK, (pointer) & to);
- X enemystrength = map[to.x][to.y].troops;
- X if (enemystrength == 0) {
- X sprintf(playertext, "%s was overrun.", namelocation(to));
- X tellcurrentplayer();
- X if (map[to.x][to.y].terrain == 5) {
- X players[owner].citadels--;
- X if (players[owner].citadels == 0) {
- X sprintf(playertext, "Your last citadel was seized!");
- X tellplayer(owner);
- X killplayer(owner);
- X }
- X players[currentplayer].citadels++;
- X }
- X regionupdate(to, map[from.x][from.y].region, currentplayer);
- X map[to.x][to.y].troops = number;
- X if (map[to.x][to.y].terrain == 2 || map[to.x][to.y].terrain == 5) {
- X map[to.x][to.y].lastuse = currenttime;
- X recruitqueueremove(to.x, to.y);
- X recruitenqueue(to.x, to.y);
- X }
- X players[currentplayer].population += map[to.x][to.y].population;
- X players[currentplayer].hexes++;
- X if (owner > 0) {
- X players[owner].hexes--;
- X broadcast(_PLAYERSTATUS, (pointer) & owner);
- X }
- X broadcast(_PLAYERSTATUS, (pointer) & currentplayer);
- X broadcast(_HEXSTATUS, (pointer) & to);
- X broadcast(_HEXSTATUS, (pointer) & from);
- X } else {
- X sprintf(playertext, "You have been attacked by %s at %s with %d troops.",
- X nameplayer(currentplayer),
- X namelocation(to), number);
- X tellplayer(owner);
- X weight = 50;
- X weight += terrainfrom[map[from.x][from.y].terrain];
- X weight += terrainto[map[to.x][to.y].terrain];
- X unitsa = number * 3;
- X unitsb = enemystrength * 3;
- X while ((unitsa > 0) && (unitsb > 0)) {
- X if (weight > ((rand() >> 5) % 100)) { /* In search of good
- X * random #s! */
- X unitsb--;
- X } else {
- X unitsa--;
- X }
- X }
- X numberold = number;
- X enemyold = enemystrength;
- X number = ((unitsa + 2) / 3);
- X enemystrength = ((unitsb + 2) / 3);
- X players[currentplayer].troops -= (numberold - number);
- X regionstroops[map[from.x][from.y].region] -= (numberold - number);
- X players[owner].troops -= (enemyold - enemystrength);
- X regionstroops[map[to.x][to.y].region] -= (enemyold - enemystrength);
- X if (unitsa == 0) {
- X sprintf(playertext, "Your forces were destroyed.");
- X tellcurrentplayer();
- X sprintf(playertext,
- X "You destroyed the enemy forces. %d of your armies survived.",
- X enemystrength);
- X tellplayer(owner);
- X map[to.x][to.y].troops = enemystrength;
- X broadcast(_HEXSTATUS, (pointer) & from);
- X broadcast(_HEXSTATUS, (pointer) & to);
- X broadcast(_PLAYERSTATUS, (pointer) & currentplayer);
- X broadcast(_PLAYERSTATUS, (pointer) & owner);
- X } else {
- X sprintf(playertext, "You liberated the territory.");
- X tellcurrentplayer();
- X if (owner != 0) {
- X sprintf(playertext, "The territory was seized. %d armies occupied the territory.", number);
- X tellplayer(owner);
- X players[owner].population -=
- X map[to.x][to.y].population;
- X if (map[to.x][to.y].terrain == 5) {
- X players[owner].citadels--;
- X if (players[owner].citadels == 0) {
- X sprintf(playertext, "Your last citadel has been eliminated!");
- X tellplayer(owner);
- X killplayer(owner);
- X }
- X players[currentplayer].citadels++;
- X }
- X map[to.x][to.y].troops = number;
- X regionupdate(to, map[from.x][from.y].region, currentplayer);
- X if (map[to.x][to.y].terrain == 2 || map[to.x][to.y].terrain == 5) {
- X map[to.x][to.y].lastuse = currenttime;
- X recruitenqueue(to.x, to.y);
- X }
- X players[currentplayer].hexes++;
- X players[owner].hexes--;
- X players[currentplayer].population += map[to.x][to.y].population;
- X broadcast(_PLAYERSTATUS, (pointer) & currentplayer);
- X broadcast(_PLAYERSTATUS, (pointer) & owner);
- X broadcast(_HEXSTATUS, (pointer) & from);
- X broadcast(_HEXSTATUS, (pointer) & to);
- X }
- X }
- X }
- X } else {
- X marchers = number + map[to.x][to.y].troops;
- X if (marchers > 99) {
- X sprintf(playertext, "Up to 99 troops per territory.");
- X tellcurrentplayer();
- X map[to.x][to.y].troops = 99;
- X players[currentplayer].action += (marchers - 99);
- X map[from.x][from.y].troops += (marchers - 99);
- X broadcast(_HEXSTATUS, (pointer) & from);
- X broadcast(_HEXSTATUS, (pointer) & to);
- X broadcast(_PLAYERSTATUS, (pointer) & currentplayer);
- X return;
- X } else {
- X map[to.x][to.y].troops = marchers;
- X broadcast(_HEXSTATUS, (pointer) & from);
- X broadcast(_HEXSTATUS, (pointer) & to);
- X broadcast(_PLAYERSTATUS, (pointer) & currentplayer);
- X return;
- X }
- X }
- X}
- X
- Xint
- Xlegal(x, y)
- X int x;
- X int y;
- X{
- X if (x >= 0 && x < gamemapsizex && y >= 0 && y < gamemapsizey)
- X return 1;
- X else
- X return 0;
- X}
- X
- Xvoid
- Xconstruct(at)
- X location at;
- X{
- X if (map[at.x][at.y].owner != currentplayer) {
- X sprintf(playertext, "You don't own that territory!");
- X tellcurrentplayer();
- X return;
- X }
- X if (map[at.x][at.y].terrain != 2) {
- X sprintf(playertext, "That territory is not a town.");
- X tellcurrentplayer();
- X return;
- X }
- X if (players[currentplayer].action < gamecitycost) {
- X sprintf(playertext, "You don't have enough action points!");
- X tellcurrentplayer();
- X return;
- X }
- X map[at.x][at.y].terrain = 5;
- X players[currentplayer].citadels++;
- X players[currentplayer].action -= gamecitycost;
- X players[currentplayer].population -= terrainpopulation[2];
- X players[currentplayer].population += terrainpopulation[5];
- X broadcast(_HEXSTATUS, (pointer) & at);
- X broadcast(_PLAYERSTATUS, (pointer) & currentplayer);
- X sprintf(playertext, "You have constructed a new city.");
- X tellcurrentplayer();
- X}
- X
- Xvoid
- Xdestroy(at)
- X location at;
- X{
- X if ((players[currentplayer].citadels == 1) && (map[at.x][at.y].terrain == 5)) {
- X sprintf(playertext, "You cannot destroy your last city.");
- X tellcurrentplayer();
- X return;
- X }
- X if (map[at.x][at.y].owner != currentplayer) {
- X sprintf(playertext, "You don't control that territory!");
- X tellcurrentplayer();
- X return;
- X }
- X if ((map[at.x][at.y].terrain != 2) && (map[at.x][at.y].terrain != 5)) {
- X sprintf(playertext, "That territory is not a town or city!");
- X tellcurrentplayer();
- X return;
- X }
- X if (map[at.x][at.y].troops == 0) {
- X sprintf(playertext, "You must have forces in the territory!");
- X tellcurrentplayer();
- X return;
- X }
- X if (players[currentplayer].action < gamedestroycost) {
- X sprintf(playertext, "You need at least %d action points.", gamedestroycost);
- X tellcurrentplayer();
- X return;
- X }
- X players[currentplayer].action -= gamedestroycost;
- X if (map[at.x][at.y].terrain == 5)
- X players[currentplayer].citadels--;
- X players[currentplayer].population -= map[at.x][at.y].population;
- X map[at.x][at.y].terrain = 1;
- X recruitqueueremove(at.x, at.y);
- X players[currentplayer].population += terrainpopulation[1];
- X broadcast(_HEXSTATUS, (pointer) & at);
- X broadcast(_PLAYERSTATUS, (pointer) & currentplayer);
- X sprintf(playertext, "You have destroyed the territory.");
- X tellcurrentplayer();
- X}
- X
- Xvoid
- Xrecruit(at)
- X location at;
- X{
- X int chance;
- X int population;
- X int x, y;
- X int recruits;
- X int supportable;
- X int total;
- X if (map[at.x][at.y].owner != currentplayer) {
- X sprintf(playertext, "You don't own that territory!");
- X tellcurrentplayer();
- X return;
- X }
- X if ((map[at.x][at.y].terrain != 2) && (map[at.x][at.y].terrain != 5)) {
- X sprintf(playertext, "That territory is not a town or citadel.");
- X tellcurrentplayer();
- X return;
- X }
- X chance = currenttime - map[at.x][at.y].lastuse;
- X map[at.x][at.y].lastuse = currenttime;
- X population = 0;
- X if (chance >= ((rand() / 100) % gamerecruittime)) {
- X for (y = (-1); (y <= 1); y++) {
- X for (x = (-1); (x <= 1); x++) {
- X if (legal(at.x + x, at.y + y)) {
- X if ((((map[at.x + x][at.y + y].terrain != 2) &&
- X (map[at.x + x][at.y + y].terrain != 5)) ||
- X ((x == 0) && (y == 0))) &&
- X (map[at.x][at.y].owner == currentplayer))
- X population += map[at.x + x][at.y + y].population;
- X }
- X }
- X }
- X recruits = population / (100 * ((rand() / 100) % 5 + 2)) + 1;
- X total = regionstroops[map[at.x][at.y].region];
- X if (regionspop[map[at.x][at.y].region] < 0) {
- X regionspop[map[at.x][at.y].region] = 1;
- X }
- X supportable = regionspop[map[at.x][at.y].region] / 100;
- X if (total + recruits > supportable) {
- X recruits = supportable - total;
- X if (recruits <= 0) {
- X return;
- X }
- X }
- X if (map[at.x][at.y].troops == 99) {
- X return;
- X }
- X map[at.x][at.y].troops += recruits;
- X if (map[at.x][at.y].troops > 99) {
- X recruits -= (map[at.x][at.y].troops - 99);
- X map[at.x][at.y].troops = 99;
- X }
- X players[currentplayer].troops += recruits;
- X regionstroops[map[at.x][at.y].region] += recruits;
- X sprintf(playertext, "You recruited %d troops at %s.", recruits,
- X namelocation(at));
- X tellcurrentplayer();
- X broadcast(_PLAYERSTATUS, (pointer) & currentplayer);
- X broadcast(_HEXSTATUS, (pointer) & at);
- X return;
- X } else {
- X sprintf(playertext, "Recruitment failed; the territory is under too much stress.");
- X tellcurrentplayer();
- X return;
- X }
- X}
- X
- Xvoid
- Xsetupmap(ismap, mapfile)
- X int ismap;
- X char *mapfile;
- X{
- X FILE *mf;
- X int **altitude;
- X int **newaltitude;
- X int x, y, subx, suby;
- X int seed;
- X int seedcomp;
- X int acceptable;
- X int full;
- X int totalaltitude;
- X location newhex;
- X int placement;
- X int typ;
- X int i;
- X static char dummy[81];
- X char buf[2];
- X full = 0;
- X if (ismap) {
- X broadcast(_TEXT, "Loading the map...");
- X } else {
- X broadcast(_TEXT, "Generating the map...");
- X }
- X /* Allocate space for map, et cetera */
- X map = (hex **) malloc(sizeof(hex *) * gamemapsizex);
- X for (i = 0; (i < gamemapsizex); i++) {
- X map[i] = (hex *) malloc(sizeof(hex) * gamemapsizey);
- X }
- X queuefront = 0;
- X queueback = 0;
- X regionnext = 1;
- X memoryalloced = 1;
- X /* Now the simple vectors */
- X recruitqueue = (location *) malloc(sizeof(location) * gamemapsizex * gamemapsizey);
- X regionspop = (int *) malloc(sizeof(int) * gamemapsizex * gamemapsizey / 2);
- X regionstroops = (int *) malloc(sizeof(int) * gamemapsizex * gamemapsizey / 2);
- X regionshex = (location *) malloc(sizeof(location) * gamemapsizex * gamemapsizey / 2);
- X regionspop[0] = 0;
- X if (ismap) {
- X mf = fopen(mapfile, "r");
- X fgets(dummy, 80, mf); /* Throw away dimensions (already
- X * read) */
- X if (!mf) {
- X stopgame("Btserver: map file specified not found.\n");
- X }
- X for (y = 0; (y < gamemapsizey); y++) {
- X x = 0;
- X while (x < gamemapsizex) {
- X /* Throw away spaces */
- X while ((placement = getc(mf)) == ' ');
- X if (isdigit(placement)) {
- X buf[0] = placement;
- X buf[1] = 0;
- X seed = atoi(buf);
- X if (seed <= totalplayers) {
- X location l;
- X map[x][y].terrain = 5;
- X map[x][y].owner = seed;
- X map[x][y].population = terrainpopulation[5];
- X regionspop[regionnext] = map[x][y].population;
- X regionstroops[regionnext] = 0;
- X l.x = x;
- X l.y = y;
- X regionshex[0] = l;
- X map[x][y].region = regionnext++;
- X players[seed].start.x = x;
- X players[seed].start.y = y;
- X players[seed].population = terrainpopulation[5];
- X players[seed].live = 1;
- X players[seed].hexes = 1;
- X players[seed].citadels = 1;
- X map[x][y].lastuse = 0;
- X recruitenqueue(x, y);
- X broadcast(_HEXSTATUS, (pointer) & players[seed].start);
- X broadcast(_PLAYERSTATUS, (pointer) & seed);
- X } else {
- X map[x][y].terrain = 1;
- X map[x][y].population = terrainpopulation[1];
- X regionspop[0] += map[x][y].population;
- X map[x][y].owner = 0;
- X map[x][y].troops = 0;
- X map[x][y].region = 0;
- X newhex.x = x;
- X newhex.y = y;
- X broadcast(_HEXSTATUS, (pointer) & newhex);
- X }
- X x++;
- X } else {
- X switch (placement) {
- X case '.':
- X typ = 1;
- X break;
- X case 'T':
- X typ = 2;
- X break;
- X case 'M':
- X typ = 3;
- X break;
- X case 'F':
- X typ = 4;
- X break;
- X case 'C':
- X typ = 5;
- X break;
- X case 'S':
- X typ = 6;
- X break;
- X default:
- X typ = 0;
- X break;
- X }
- X if (typ) {
- X map[x][y].terrain = typ;
- X map[x][y].population = terrainpopulation[typ];
- X regionspop[0] += map[x][y].population;
- X map[x][y].owner = 0;
- X map[x][y].troops = 0;
- X map[x][y].lastuse = 0;
- X map[x][y].region = 0;
- X newhex.x = x;
- X newhex.y = y;
- X broadcast(_HEXSTATUS, (pointer) & newhex);
- X x++;
- X }
- X }
- X }
- X }
- X return;
- X }
- X /* Generate random map */
- X altitude = (int **) malloc(sizeof(int *) * gamemapsizex);
- X newaltitude = (int **) malloc(sizeof(int *) * gamemapsizex);
- X for (i = 0; (i < gamemapsizex); i++) {
- X altitude[i] = (int *) malloc(sizeof(int) * gamemapsizey);
- X newaltitude[i] = (int *) malloc(sizeof(int) * gamemapsizey);
- X }
- X /* Now we can finally get started with map generation */
- X for (y = 0; (y < gamemapsizey); y++) {
- X for (x = 0; (x < gamemapsizex); x++) {
- X map[x][y].terrain = 0;
- X altitude[x][y] = 0;
- X }
- X }
- X for (seed = 1; (seed <= totalplayers); seed++) {
- X location l;
- X int initx, inity;
- X x = ((rand() / 32) % (gamemapsizex - 4)) + 2;
- X y = ((rand() / 32) % (gamemapsizey - 4)) + 2;
- X initx = x;
- X inity = y;
- X while (1) {
- X acceptable = 1;
- X x++;
- X if (x > gamemapsizex - 2) {
- X x = 3;
- X y++;
- X if (y > gamemapsizey - 2) {
- X y = 1;
- X }
- X }
- X if ((x == initx) && (y == inity)) {
- X fprintf(stderr, "btserver: unable to fit %d players on the map.\n",
- X totalplayers);
- X fprintf(stderr, "Try fewer players or a larger map.\n");
- X exiterror();
- X }
- X for (seedcomp = 1; (seedcomp < seed); seedcomp++) {
- X if (abs(x - players[seedcomp].start.x) +
- X abs(y - players[seedcomp].start.y) < 5)
- X acceptable = 0;
- X }
- X if (acceptable == 1)
- X break;
- X }
- X map[x][y].terrain = 5;
- X map[x][y].lastuse = 0;
- X altitude[x][y] = 100;
- X map[x][y].population = terrainpopulation[5];
- X map[x][y].owner = seed;
- X map[x][y].troops = 0;
- X players[seed].start.x = x;
- X players[seed].start.y = y;
- X players[seed].population = terrainpopulation[5];
- X players[seed].live = 1;
- X players[seed].hexes++;
- X players[seed].citadels = 1;
- X regionspop[regionnext] = map[x][y].population;
- X regionstroops[regionnext] = 0;
- X l.x = x;
- X l.y = y;
- X regionshex[regionnext] = l;
- X map[x][y].region = regionnext++;
- X recruitenqueue(x, y);
- X broadcast(_HEXSTATUS, (pointer) & players[seed].start);
- X broadcast(_PLAYERSTATUS, (pointer) & seed);
- X full++;
- X }
- X /*
- X * Now sweep, dropping altitudes of new hexes based on adjacents.
- X * Don't let altitude drop to zero; increment full as each hex is
- X * filled. At 90% full or so, call it quits.
- X */
- X
- X acceptable = (gamemapsizey * gamemapsizex) * 9 / 10;
- X while (full < acceptable) {
- X for (y = 0; (y < gamemapsizey); y++) {
- X for (x = 0; (x < gamemapsizex); x++) {
- X newaltitude[x][y] = altitude[x][y];
- X if (altitude[x][y] == 0) {
- X totalaltitude = 0;
- X for (suby = (-1); (suby <= 1); suby++) {
- X for (subx = (-1); (subx <= 1); subx++) {
- X if (legal(x + subx, y + suby))
- X totalaltitude += altitude[x + subx][y + suby];
- X }
- X }
- X if (totalaltitude > 0) {
- X newaltitude[x][y] = totalaltitude / 2 + ((rand() / 100) % 20);
- X map[x][y].lastuse = 0;
- X map[x][y].troops = 0;
- X map[x][y].owner = 0;
- X map[x][y].region = 0;
- X placement = ((rand() / 100) % 100) * (newaltitude[x][y]) / 100;
- X if (placement > 90) {
- X map[x][y].terrain = 7;
- X } else if (placement > 70) {
- X map[x][y].terrain = 3;
- X } else if (placement > 50) {
- X map[x][y].terrain = 4;
- X } else if (placement > 40) {
- X map[x][y].terrain = 2;
- X } else if (placement > 20) {
- X map[x][y].terrain = 1;
- X } else {
- X map[x][y].terrain = 6;
- X }
- X map[x][y].population = terrainpopulation[map[x][y].terrain];
- X regionspop[0] += map[x][y].population;
- X newhex.x = x;
- X newhex.y = y;
- X broadcast(_HEXSTATUS, (pointer) & newhex);
- X full++;
- X }
- X }
- X }
- X }
- X for (y = 0; (y < gamemapsizey); y++) {
- X for (x = 0; (x < gamemapsizex); x++) {
- X altitude[x][y] = newaltitude[x][y];
- X }
- X }
- X }
- X for (y = 0; (y < gamemapsizey); y++) {
- X for (x = 0; (x < gamemapsizex); x++) {
- X if (!map[x][y].terrain) {
- X map[x][y].terrain = 7;
- X map[x][y].population = terrainpopulation[7];
- X regionspop[0] += map[x][y].population;
- X map[x][y].owner = 0;
- X map[x][y].lastuse = 0;
- X map[x][y].troops = 0;
- X map[x][y].region = 0;
- X newhex.x = x;
- X newhex.y = y;
- X broadcast(_HEXSTATUS, (pointer) & newhex);
- X }
- X }
- X }
- X for (i = 0; (i < gamemapsizex); i++) {
- X free(altitude[i]);
- X free(newaltitude[i]);
- X }
- X free(altitude);
- X free(newaltitude);
- X}
- X
- Xvoid
- Xtellcurrentplayer()
- X{
- X tellplayer(currentplayer);
- X}
- X
- Xvoid
- Xkillplayer(owner)
- X int owner;
- X{
- X int x, y;
- X int i;
- X broadcast(_PLAYERDEAD, (pointer) & owner);
- X for (y = 0; (y < gamemapsizey); y++) {
- X for (x = 0; (x < gamemapsizex); x++) {
- X if (map[x][y].owner == owner) {
- X map[x][y].owner = 0;
- X map[x][y].troops = 0;
- X regionspop[map[x][y].region] = 0;
- X regionstroops[map[x][y].troops] = 0;
- X map[x][y].region = 0;
- X if ((map[x][y].terrain == 2) || (map[x][y].terrain == 5)) {
- X recruitqueueremove(x, y);
- X }
- X }
- X }
- X }
- X players[owner].population = 0;
- X players[owner].troops = 0;
- X if (players[owner].live) {
- X players[owner].live = 2;
- X }
- X living = 0;
- X for (i = 1; (i <= totalplayers); i++) {
- X if (players[i].live == 1) {
- X living++;
- X }
- X }
- X sprintf(playertext, "%d players left in current game.", living);
- X broadcastwaitqueue(_TEXT, playertext);
- X}
- X
- Xchar *
- Xnamelocation(at)
- X location at;
- X{
- X static char namespace[20];
- X sprintf(namespace, "[%c%d]", 65 + at.x, at.y);
- X return &namespace[0];
- X}
- X
- Xchar *
- Xnameplayer(thisid)
- X int thisid;
- X{
- X static char namespace[20];
- X namespace[0] = ' ';
- X namespace[1] = 64 + thisid;
- X namespace[2] = ' ';
- X namespace[3] = NULL;
- X return &namespace[0];
- X}
- END_OF_FILE
- if test 39546 -ne `wc -c <'btserver.c'`; then
- echo shar: \"'btserver.c'\" unpacked with wrong size!
- fi
- # end of 'btserver.c'
- fi
- echo shar: End of archive 1 \(of 3\).
- cp /dev/null ark1isdone
- 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
-