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: v15i017: bt4 - Broken Throne, multiplayer realtime conquest game (V2.03), Part03/03
- Message-ID: <3828@master.CNA.TEK.COM>
- Date: 29 Oct 92 01:42:45 GMT
- Article-I.D.: master.3828
- Sender: news@master.CNA.TEK.COM
- Lines: 1372
- Approved: billr@saab.CNA.TEK.COM
- Xref: uunet comp.sources.games:1516
-
- Submitted-by: boutell@isis.cshl.org (Tom Boutell)
- Posting-number: Volume 15, Issue 17
- Archive-name: bt4/Part03
- 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 3 (of 3)."
- # Contents: INSTALL Makefile bt.h btinterface.c btinterface.h btpack.c
- # btpack.h map.txt msleep.c msleep.h readme xbt
- # Wrapped by billr@saab on Wed Oct 28 17:38:00 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'INSTALL' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'INSTALL'\"
- else
- echo shar: Extracting \"'INSTALL'\" \(97 characters\)
- sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
- XCopy the 'btserverrc' file to '.btserverrc' in your home directory or in
- Xyour playing directory.
- END_OF_FILE
- if test 97 -ne `wc -c <'INSTALL'`; then
- echo shar: \"'INSTALL'\" unpacked with wrong size!
- fi
- # end of 'INSTALL'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(858 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- Xall: btclient btserver btrobot
- X
- X#don't use -ltermlib for AIX (edit second line for btclient, below, to
- X#remove this).
- X#don't use -O or -lbsd with AIX, either (not used here but something you
- X#might otherwise expect to need to change).
- X
- Xbtclient: btclient.o btpack.o msleep.o
- X cc btclient.o btpack.o msleep.o -o btclient -ltermcap -lcurses -ltermlib
- X
- Xbtserver: btserver.o btpack.o btinterface.o msleep.o
- X cc btserver.o btpack.o btinterface.o msleep.o -o btserver
- X
- Xbtrobot: btrobot.o btpack.o
- X cc btrobot.o btpack.o -o btrobot
- X
- Xbtrobot.o: btrobot.c bt.h
- X cc -c -g btrobot.c
- X
- Xbtclient.o: btclient.c btclient.h bt.h
- X cc -c -g btclient.c
- Xbtpack.o: btpack.c btpack.h
- X cc -c -g btpack.c
- Xbtinterface.o: btinterface.c btinterface.h
- X cc -c -g btinterface.c
- Xbtserver.o: btserver.c btserver.h bt.h
- X cc -c -g btserver.c
- Xmsleep.o: msleep.c msleep.h
- X cc -c -g msleep.c
- X
- END_OF_FILE
- if test 858 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'bt.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'bt.h'\"
- else
- echo shar: Extracting \"'bt.h'\" \(1463 characters\)
- sed "s/^X//" >'bt.h' <<'END_OF_FILE'
- X/*
- X * Main Include File for Broken Throne By Tom Boutell Do As Thou Wilt, But
- X * Give Me The Source!
- X *
- X * If your compiler complains, uncomment the line below (remove the surrounding
- X * characters). Thanks to Marcus Ranum:
- X */
- X
- X/* #define COMPILER_HATES_VOIDSTAR 1 */
- X
- X#ifdef COMPILER_HATES_VOIDSTAR
- Xtypedef char *pointer;
- X#else
- Xtypedef void *pointer;
- X#endif
- X
- Xtypedef struct {
- X char terrain;
- X int population;
- X int lastuse;
- X int troops;
- X int owner;
- X int region;
- X} hex;
- X
- Xtypedef struct {
- X int x;
- X int y;
- X} location;
- X
- Xtypedef struct {
- X int action;
- X int hexes;
- X int troops;
- X int population;
- X int citadels;
- X int live;
- X location start;
- X} player;
- X
- X/* Messages from server to clients: */
- 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#define _LOOK 73
- X#define _BUSY 74
- X
- X/* From clients to server: */
- 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
- X/* Maximum number of players (this # is really outrageously high): */
- X
- X#define _MAXPLAYERS 20
- X
- X/* Maximum size of wait queue (also pretty hefty): */
- X
- X#define _MAXWAITQUEUE 40
- END_OF_FILE
- if test 1463 -ne `wc -c <'bt.h'`; then
- echo shar: \"'bt.h'\" unpacked with wrong size!
- fi
- # end of 'bt.h'
- fi
- if test -f 'btinterface.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'btinterface.c'\"
- else
- echo shar: Extracting \"'btinterface.c'\" \(14454 characters\)
- sed "s/^X//" >'btinterface.c' <<'END_OF_FILE'
- X
- X/*
- X * btinterface.c: Socket communications support& medium- level message
- X * passing functions. Copyright (C) 1990 Tom Boutell on original portions.
- X * All low- level socket code drawn with appreciation from: SOCK.C Copyright
- X * (C)1989 Dr Evil Laboratories This code written by Ray Moody, Roy Riggs,
- X * Mitch Adler, Bill Burdick, and Steven Grady No one makes any guarantees
- X * about anything. This file maybe freely distributed and modified as long
- X * as this header remains intact.
- X */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X
- X#ifdef _AIX
- X#include <sys/select.h>
- X#endif
- X
- X#ifdef sequent
- X#include <strings.h>
- X#else
- X#include <string.h>
- X#endif
- X
- X#include <ctype.h>
- X#include <signal.h>
- X#include <netdb.h>
- X#include <varargs.h>
- X
- X#include "btpack.h"
- X#include "bt.h"
- X#include "btserver.h"
- X#include "btinterface.h"
- X
- X#define DEBUG
- X#undef DEBUG
- X#ifdef DEBUG
- X#define debug printf
- X#else
- X#define debug 0+
- X#define perror 0+
- X#endif
- X
- X#define TRACE 1
- X
- X#define SECONDSLIMIT 0L
- X#define MICROSECONDSLIMIT 1L
- X
- X#define LINE_LEN 1024
- X#define LOST_CARRIER_MSG "F"
- X
- X#define NONE (fd_set *) NULL
- X#define NEVER (struct timeval *) NULL
- X#define IGNORE (struct sockaddr *) NULL
- X
- X/* To assist in signal handling: */
- X
- X#define SENDPLAYER 0
- X#define SENDQUEUE 1
- X#define SENDOTHER 2
- Xint sendtype;
- Xint whodied;
- Xint brokenpipe = 0;
- X
- Xfd_set active;
- Xstruct sockaddr_in sc_in;
- Xint s;
- Xchar cur_input[LINE_LEN];
- Xchar *curhostname = "";
- Xint playerfds[_MAXPLAYERS];
- Xchar outputline[256];
- Xint full;
- X
- Xint waitqueue[_MAXWAITQUEUE];
- Xint waitqueuefront = 0;
- Xint waitqueueback = 0;
- Xint waitqueuetotal = 0;
- X
- Xvoid
- Xsetupinterface(portnumber)
- X int portnumber;
- X{
- X init_socket(portnumber);
- X playertext = (outputline + 1);
- X signal(SIGPIPE, broken);
- X full = 0;
- X}
- X
- Xvoid
- Xfetchplayers()
- X{
- X int current;
- X int gotplayers = 0;
- X for (current = 1; (current <= totalplayers); current++) {
- X players[current].live = 0;
- X }
- X do {
- X int p;
- X unsigned char type;
- X int np;
- X int fd = -1;
- X char specific[81];
- X if ((!waitqueuetotal) || ((fd = waitdequeue()) == -1)) {
- X do {
- X np = new_player(0);
- X if (np != -1) {
- X fd = np;
- X }
- X } while (fd == -1);
- X }
- X for (current = 1; (current <= totalplayers); current++) {
- X if (players[current].live == 0) {
- X gotplayers++;
- X playerfds[current] = fd;
- X players[current].live = 1;
- X#if TRACE
- X printf("Player %d has joined.\n", current);
- X#endif
- X outputline[0] = _YOUARE;
- X outputline[1] = 64 + current;
- X outputline[2] = 0;
- X if (!(w_p(current, outputline, strlen(&outputline[0]) + 1))) {
- X#if TRACE
- X printf("... Connection broken.\n");
- X#endif
- X players[current].live = 0;
- X disconnect_player(current);
- X gotplayers--;
- X }
- X break;
- X }
- X }
- X while (getrequest(&p, &type, specific)) {
- X if (type == _DISCONNECT) {
- X players[p].live = 0;
- X#if TRACE
- X printf("Player %d quit during startup.\n", p);
- X#endif
- X disconnect_player(p);
- X gotplayers--;
- X }
- X }
- X } while (gotplayers < totalplayers);
- X full = 1;
- X}
- X
- Xvoid
- Xtellplayer(theplayer)
- X int theplayer;
- X{
- X outputline[0] = _TEXT;
- X w_p(theplayer, outputline, strlen(outputline) + 1);
- X}
- X
- Xvoid
- Xbroadcast(messagetype, details)
- X char messagetype;
- X pointer details;
- X{
- X location where;
- X location *wherep;
- X int thisplayer;
- X int current;
- X outputline[0] = messagetype;
- X switch (messagetype) {
- X
- X case _HEXSTATUS:
- X wherep = (location *) details;
- X where = (*wherep);
- X outputline[1] = 64 + where.x;
- X outputline[2] = 64 + where.y;
- X outputline[3] = 64 + map[where.x][where.y].terrain;
- X packint(4, map[where.x][where.y].population);
- X packint(7, map[where.x][where.y].lastuse);
- X packint(10, map[where.x][where.y].troops);
- X outputline[13] = map[where.x][where.y].owner + 64;
- X outputline[14] = NULL;
- X break;
- X case _LOOK:
- X where = (*(location *) details);
- X outputline[1] = 64 + where.x;
- X outputline[2] = 64 + where.y;
- X outputline[3] = NULL;
- X break;
- X case _PLAYERSTATUS:
- X thisplayer = (*(int *) details);
- X outputline[1] = thisplayer + 64;
- X packint(2, players[thisplayer].action);
- X packint(5, players[thisplayer].hexes);
- X packint(8, players[thisplayer].troops);
- X packint(11, players[thisplayer].population);
- X packint(14, players[thisplayer].citadels);
- X outputline[17] = players[thisplayer].start.x + 64;
- X outputline[18] = players[thisplayer].start.y + 64;
- X outputline[19] = NULL;
- X break;
- X case _PLAYERDEAD:
- X thisplayer = (*(int *) details);
- X outputline[1] = thisplayer + 64;
- X outputline[2] = NULL;
- X break;
- X case _ACTION:
- X outputline[1] = NULL;
- X break;
- X case _STARTUP:
- X outputline[1] = totalplayers + 64;
- X where = (*(location *) details);
- X outputline[2] = 64 + where.x;
- X outputline[3] = 64 + where.y;
- X outputline[4] = NULL;
- X break;
- X case _TEXT:
- X strcpy(&outputline[1], (char *) details);
- X break;
- X case _END:
- X outputline[1] = NULL;
- X }
- X for (current = 0; (current <= totalplayers); current++) {
- X if (players[current].live) {
- X if (!(w_p(current, outputline, strlen(outputline) + 1))) {
- X players[current].live = 0;
- X killplayer(current);
- X }
- X }
- X }
- X}
- X
- Xvoid
- Xbroadcastwaitqueue(messagetype, details)
- X unsigned char messagetype;
- X pointer details;
- X{
- X int i;
- X switch (messagetype) {
- X case _END:
- X outputline[0] = _END;
- X outputline[1] = NULL;
- X break;
- X case _TEXT:
- X outputline[0] = _TEXT;
- X strcpy(&outputline[1], details);
- X break;
- X case _BUSY:
- X outputline[0] = _BUSY;
- X outputline[1] = NULL;
- X break;
- X }
- X i = waitqueueback;
- X while (i != waitqueuefront) {
- X w_q(i, outputline, strlen(outputline) + 1);
- X i++;
- X if (i >= _MAXWAITQUEUE)
- X i = 0;
- X };
- X}
- X
- Xvoid
- Xtellwaitqueue(q)
- X int q;
- X{
- X outputline[0] = _TEXT;
- X w_q(q, outputline, strlen(outputline) + 1);
- X}
- X
- Xvoid
- Xupdatewaitqueue()
- X{
- X int i;
- X int count = 0;
- X outputline[0] = _TEXT;
- X i = waitqueueback;
- X while (i != waitqueuefront) {
- X if (waitqueue[i] != -1) {
- X sprintf(playertext, "You are now #%d in the queue.", ++count);
- X tellwaitqueue(i);
- X }
- X i++;
- X if (i > _MAXWAITQUEUE) {
- X i = 0;
- X }
- X }
- X}
- X
- Xint
- Xgetrequest(thisplayer, requesttype, specific)
- X int *thisplayer;
- X char *requesttype;
- X char *specific;
- X{
- X char *received;
- X static int sweep;
- X int oldsweep;
- X if (full) {
- X int np;
- X np = new_player(1);
- X if (np != -1) {
- X if (gamecontinuous) {
- X /*
- X * We're running in continuous mode, so
- X * enqueue
- X */
- X waitenqueue(np);
- X } else {
- X /* Tell them we're busy */
- X outputline[0] = _BUSY;
- X outputline[1] = '\0';
- X w_fd(np, outputline, strlen(outputline) + 1);
- X disconnect_fd(np);
- X }
- X }
- X }
- X sweep++;
- X if ((sweep > totalplayers) || (sweep <= 0))
- X sweep = 1;
- X oldsweep = sweep;
- X while (players[sweep].live == 0) {
- X sweep++;
- X if (sweep > totalplayers)
- X sweep = 1;
- X if (sweep == oldsweep)
- X return 0;
- X }
- X received = read_player(sweep);
- X *thisplayer = sweep;
- X if (*received == NULL)
- X return 0;
- X *requesttype = received[0];
- X strcpy(specific, (received += 1));
- X return 1;
- X}
- X
- X
- Xvoid
- Xshutdowninterface()
- X{
- X disconnect_all();
- X}
- X
- X/* Burst pipe handler */
- X
- Xvoid
- Xbroken()
- X{
- X /* Reinstall ourselves */
- X signal(SIGPIPE, broken);
- X brokenpipe = 1;
- X /* Switch on who we were writing to */
- X switch (sendtype) {
- X case SENDPLAYER:
- X players[whodied].live = 0;
- X killplayer(whodied);
- X break;
- X case SENDQUEUE:
- X disconnect_fd(waitqueue[whodied]);
- X /* Set slot available */
- X waitqueue[whodied] = -1;
- X break;
- X case SENDOTHER:
- X /* Just close the fd and hope this doesn't put us in a loop */
- X disconnect_fd(whodied);
- X break;
- X }
- X}
- X
- Xint
- Xwaitdequeue()
- X{
- X int fd;
- X do {
- X if (waitqueuetotal == 0) {
- X return -1;
- X }
- X waitqueuetotal--;
- X fd = waitqueue[waitqueueback++];
- X if (waitqueueback >= _MAXWAITQUEUE)
- X waitqueueback = 0;
- X updatewaitqueue();
- X } while (fd == -1);
- X return fd;
- X}
- X
- Xvoid
- Xwaitenqueue(fd)
- X int fd;
- X{
- X if (waitqueuetotal == _MAXWAITQUEUE) {
- X outputline[0] = _TEXT;
- X sprintf(&outputline[1], "Queue is full, try later.");
- X w_fd(fd, outputline, strlen(outputline) + 1);
- X outputline[0] = _BUSY;
- X outputline[1] = '\0';
- X w_fd(fd, outputline, strlen(outputline) + 1);
- X disconnect_fd(fd);
- X return;
- X }
- X waitqueue[waitqueuefront] = fd;
- X waitqueuetotal++;
- X outputline[0] = _TEXT;
- X sprintf(&outputline[1], "You are #%d in the wait queue.", waitqueuetotal);
- X w_q(waitqueuefront, outputline, strlen(outputline) + 1);
- X outputline[0] = _TEXT;
- X sprintf(&outputline[1], "(There are %d players per game.)", totalplayers);
- X w_q(waitqueuefront, outputline, strlen(outputline) + 1);
- X waitqueuefront++;
- X if (waitqueuefront >= _MAXWAITQUEUE)
- X waitqueuefront = 0;
- X}
- X
- X/*
- X * - PD Socket code begins here. init_socket() - initialize our socket, port
- X * is the port number to use call this once at the beginning of your code
- X */
- X
- Xint
- Xinit_socket(port)
- X int port;
- X{
- X setbuf(stdout, (char *) 0);
- X if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- X perror("socket");
- X return 0;
- X }
- X sc_in.sin_family = AF_INET;
- X sc_in.sin_addr.s_addr = INADDR_ANY;
- X sc_in.sin_port = htons((u_short) port);
- X if (bind(s, (struct sockaddr *) & sc_in, sizeof(sc_in)) < 0) {
- X perror("bind");
- X return 0;
- X }
- X if (listen(s, 5) < 0) {
- X perror("listen");
- X return 0;
- X }
- X FD_ZERO(&active);
- X
- X return 1;
- X}
- X
- X
- X/*
- X * disconnect_all() - throws everyone off
- X */
- X
- Xint
- Xdisconnect_all()
- X{
- X register int i;
- X
- X for (i = 0; i < FD_SETSIZE; i++) {
- X if (FD_ISSET(i, &active))
- X (void) disconnect_fd(i);
- X }
- X return 1;
- X}
- X
- X
- X/*
- X * shut-down -- kills all connections and exits the pgm
- X */
- X
- Xint
- Xshut_down()
- X{
- X (void) disconnect_all();
- X exit(0);
- X}
- X
- X
- X/*
- X * hostfrom() - returns a string containing an ascii name for the host that
- X * the passed socket s is connected to. Note that the string is in static
- X * space. If you want to munge with it, make a copy.
- X */
- X
- Xchar *
- Xhostfrom(i)
- X int i;
- X{
- X struct sockaddr_in from;
- X int fromlen = sizeof(from);
- X struct hostent *host;
- X struct in_addr addr;
- X
- X if (getpeername(i, &from, &fromlen) < 0) {
- X perror("getpeername");
- X return NULL;
- X }
- X addr = from.sin_addr;
- X if ((host = gethostbyaddr(&addr, sizeof(addr), AF_INET)) == NULL) {
- X debug("gethostbyaddr failed");
- X return NULL;
- X }
- X return curhostname = host->h_name;
- X}
- X
- X
- X/*
- X * hostname() - returns curhostname
- X */
- X
- Xchar *
- Xhostname()
- X{
- X return curhostname;
- X}
- X
- X
- X/*
- X * new_player() - call this routine in your main loop to allow new players to
- X * join. returns a playerId or -1 if no one wants to join. if wait == 0,
- X * then put your process to sleep until someone new tries to connect.
- X */
- X
- Xint
- Xnew_player(wait)
- X int wait; /* 0 - wait for activity, else don't wait */
- X{
- X fd_set readfds;
- X int j;
- X struct timeval *pWaitTime, waitTime;
- X
- X pWaitTime = &waitTime;
- X
- X if (0 == wait) {
- X pWaitTime = NEVER;
- X } else {
- X pWaitTime->tv_sec = SECONDSLIMIT;
- X pWaitTime->tv_usec = MICROSECONDSLIMIT;
- X }
- X
- X bcopy((char *) &active, (char *) &readfds, sizeof(active));
- X
- X FD_SET(s, &readfds);
- X
- X if (select(FD_SETSIZE, &readfds, NONE, NONE, pWaitTime) < 0) {
- X perror("select");
- X return -1;
- X }
- X if (FD_ISSET(s, &readfds)) {
- X if ((j = accept(s, IGNORE, (int *) 0)) < 0) {
- X return -1;
- X }
- X FD_SET(j, &active);
- X curhostname = hostfrom(j);
- X debug("Test Host=%s\n", curhostname);
- X return j;
- X } else {
- X return -1;
- X }
- X}
- X
- X/* disconnect_player: disconnects given player */
- X
- Xint
- Xdisconnect_player(p)
- X int p;
- X{
- X disconnect_fd(playerfds[p]);
- X}
- X
- X/*
- X * disconnect_fd() - drop the connection with the given fd
- X */
- X
- Xint
- Xdisconnect_fd(fd)
- X int fd;
- X{
- X if (FD_ISSET(fd, &active)) {
- X debug("** Just dropped %d\n", fd);
- X FD_CLR(fd, &active);
- X if (close(fd) < 0) {
- X perror("close");
- X return 0;
- X }
- X } else {
- X debug("** Just tried to drop someone not connected\n");
- X return 0;
- X }
- X return 1;
- X}
- X
- X/* read_player() - returns next string from given player. */
- X
- Xchar *
- Xread_player(p)
- X int p;
- X{
- X return (read_fd(playerfds[p]));
- X}
- X
- X/*
- X * read_fd() - This routine returns the next string from the given fd. If
- X * there is no input it returns the empty string. If the connection is lost
- X * the string LOST_CARRIER_MSG is returned.
- X */
- X
- Xchar *
- Xread_fd(playerFd)
- X int playerFd;
- X{
- X fd_set readfds;
- X struct timeval waitTime;
- X
- X waitTime.tv_sec = SECONDSLIMIT;
- X waitTime.tv_usec = MICROSECONDSLIMIT;
- X
- X bcopy((char *) &active, (char *) &readfds, sizeof(active));
- X
- X if (select(FD_SETSIZE, &readfds, NONE, NONE, &waitTime) < 0) {
- X perror("select");
- X return ("");
- X }
- X if (FD_ISSET(playerFd, &readfds)) {
- X int nbytes;
- X
- X nbytes = read(playerFd, cur_input, LINE_LEN);
- X if (nbytes < 0) {
- X perror("read");
- X disconnect_fd(playerFd);
- X return (LOST_CARRIER_MSG);
- X } else if (nbytes == 0) {
- X disconnect_fd(playerFd);
- X return (LOST_CARRIER_MSG);
- X } else {
- X if (nbytes != LINE_LEN) {
- X cur_input[nbytes] = '\0';
- X } else {
- X cur_input[LINE_LEN - 1] = '\0';
- X }
- X
- X return ((char *) cur_input);
- X }
- X }
- X return ("");
- X}
- X
- X/* w_p() - write string of given length to player p */
- X
- Xint
- Xw_p(p, str, len)
- X int p;
- X char *str;
- X int len;
- X{
- X /* To assist in sigpipe handling */
- X sendtype = SENDPLAYER;
- X whodied = p;
- X write_fd_proper(playerfds[p], str, len);
- X if (brokenpipe) {
- X brokenpipe = 0;
- X return 0;
- X }
- X return 1;
- X}
- X
- X/* w_q() - write string of given length to queue position q */
- X
- Xint
- Xw_q(q, str, len)
- X int q;
- X char *str;
- X int len;
- X{
- X sendtype = SENDQUEUE;
- X whodied = q;
- X write_fd_proper(waitqueue[q], str, len);
- X if (brokenpipe) {
- X brokenpipe = 0;
- X return 0;
- X }
- X return 1;
- X}
- X
- X/*
- X * w_fd() - write to file descriptor, a string with the given length
- X */
- X
- Xint
- Xw_fd(fd, str, len)
- X int fd;
- X char *str;
- X int len;
- X{
- X sendtype = SENDOTHER;
- X write_fd_proper(fd, str, len);
- X if (brokenpipe) {
- X brokenpipe = 0;
- X return 0;
- X }
- X return 1;
- X}
- X
- Xint
- Xwrite_fd_proper(fd, str, len)
- X int fd;
- X char *str;
- X int len;
- X{
- X if (fd > -1) {
- X if (!FD_ISSET(fd, &active)) {
- X debug("** Tried to write to closed id #%d.\n", fd);
- X return 0;
- X } else if (write(fd, str, len) < 0) {
- X perror("Write");
- X return 0;
- X }
- X }
- X return 1;
- X}
- END_OF_FILE
- if test 14454 -ne `wc -c <'btinterface.c'`; then
- echo shar: \"'btinterface.c'\" unpacked with wrong size!
- fi
- # end of 'btinterface.c'
- fi
- if test -f 'btinterface.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'btinterface.h'\"
- else
- echo shar: Extracting \"'btinterface.h'\" \(897 characters\)
- sed "s/^X//" >'btinterface.h' <<'END_OF_FILE'
- Xvoid setupinterface(); /* int portnumber */
- Xvoid shutdowninterface();
- Xint getrequest();
- X/* int* player,char* requesttype,char* specific */
- Xvoid broadcast(); /* char messagetype,void* details */
- Xvoid tellplayer(); /* int player */
- Xint init_socket(); /* int port */
- Xint disconnect_all();
- Xint shutdown();
- Xchar *hostfrom(); /* int i */
- Xchar *hostname();
- Xint new_player(); /* int wait */
- Xint disconnect(); /* int id */
- Xchar *read_player(); /* int playerFd */
- Xint w_p(); /* int id, char* str, int len */
- Xchar *playertext; /* String to sprinted by tellplayer */
- Xvoid broken(); /* Broken pipe handler */
- Xvoid updatewaitqueue();
- Xchar *read_fd();
- Xint w_fd();
- Xint write_fd_proper();
- END_OF_FILE
- if test 897 -ne `wc -c <'btinterface.h'`; then
- echo shar: \"'btinterface.h'\" unpacked with wrong size!
- fi
- # end of 'btinterface.h'
- fi
- if test -f 'btpack.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'btpack.c'\"
- else
- echo shar: Extracting \"'btpack.c'\" \(875 characters\)
- sed "s/^X//" >'btpack.c' <<'END_OF_FILE'
- X/*
- X * pack.c: Functions for packing of Broken Throne data for transmission via
- X * sockets. Copyright 1990, Tom Boutell.
- X */
- X
- X#include "bt.h"
- X#include "btpack.h"
- X
- Xvoid
- Xpackint(offset, contents)
- X int offset;
- X int contents;
- X{
- X outputline[offset] = (contents % 32) + 32;
- X contents /= 32;
- X outputline[offset + 1] = (contents % 32) + 32;
- X contents /= 32;
- X outputline[offset + 2] = (contents % 32) + 32;
- X}
- X
- Xvoid
- Xstriplocation(at, specific, offset)
- X location *at;
- X char *specific;
- X int *offset;
- X{
- X at->x = specific[*offset] - 64;
- X at->y = specific[*offset + 1] - 64;
- X *offset += 2;
- X}
- X
- Xvoid
- Xstripint(number, specific, offset)
- X int *number;
- X char *specific;
- X int *offset;
- X{
- X *number = specific[*offset] - 32 + (specific[*offset + 1] - 32) * 32 +
- X (specific[*offset + 2] - 32) * 1024;
- X *offset += 3;
- X}
- END_OF_FILE
- if test 875 -ne `wc -c <'btpack.c'`; then
- echo shar: \"'btpack.c'\" unpacked with wrong size!
- fi
- # end of 'btpack.c'
- fi
- if test -f 'btpack.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'btpack.h'\"
- else
- echo shar: Extracting \"'btpack.h'\" \(367 characters\)
- sed "s/^X//" >'btpack.h' <<'END_OF_FILE'
- X/*
- X * pack.h: function declarations for packing data for socket transmission
- X * under Broken Throne. (C) 1990 Tom Boutell.
- X */
- X
- Xextern char outputline[];
- X
- Xvoid packint(); /* int offset,int contents */
- Xvoid striplocation();/* location* at,char* specific,int* offset */
- Xvoid stripint(); /* int* number,char* specific,int* offset */
- END_OF_FILE
- if test 367 -ne `wc -c <'btpack.h'`; then
- echo shar: \"'btpack.h'\" unpacked with wrong size!
- fi
- # end of 'btpack.h'
- fi
- if test -f 'map.txt' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'map.txt'\"
- else
- echo shar: Extracting \"'map.txt'\" \(279 characters\)
- sed "s/^X//" >'map.txt' <<'END_OF_FILE'
- X16x16
- XMMMMFMMFMFMMMMTT
- XMMFF....TMMMFFMM
- XMMMMMMMM.6..MTMM
- XMMMM..T..MMMMMMM
- XMMFFFM..T..TMMMM
- XMMMMMMMTMMMMMMTM
- XMMM..1....5...MM
- XMMMMMMTMMMMMMMMM
- XMMMMMM...MTMMMMM
- XMMMTMMMMT4MMM3TM
- XMM.....MMMMMMMMM
- XMMMMMMTMTMTMMFFM
- XMT..T..MMMMMMMMM
- XMMMMMMMMFFFMTMMM
- XMMMTMMMMTMM.2.MM
- XMMMMMMMMMMMMMMMM
- X
- END_OF_FILE
- if test 279 -ne `wc -c <'map.txt'`; then
- echo shar: \"'map.txt'\" unpacked with wrong size!
- fi
- # end of 'map.txt'
- fi
- if test -f 'msleep.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'msleep.c'\"
- else
- echo shar: Extracting \"'msleep.c'\" \(292 characters\)
- sed "s/^X//" >'msleep.c' <<'END_OF_FILE'
- X
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#ifdef _AIX
- X#include <sys/select.h>
- X#endif
- X#ifndef NULL
- X#define NULL 0
- X#endif /* NULL */
- X
- Xvoid
- Xmsleep(n)
- X long n;
- X{
- X struct timeval sleept;
- X sleept.tv_sec = 0;
- X sleept.tv_usec = n;
- X select(FD_SETSIZE, NULL, NULL, NULL, &sleept);
- X}
- END_OF_FILE
- if test 292 -ne `wc -c <'msleep.c'`; then
- echo shar: \"'msleep.c'\" unpacked with wrong size!
- fi
- # end of 'msleep.c'
- fi
- if test -f 'msleep.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'msleep.h'\"
- else
- echo shar: Extracting \"'msleep.h'\" \(238 characters\)
- sed "s/^X//" >'msleep.h' <<'END_OF_FILE'
- X/*
- X * msleep: A portable routine to sleep for n microseconds. By Tom Boutell
- X * 2/2/91, from various suggestions from netfolk. (One fellow sent me such a
- X * routine earlier, which I have lost.)
- X */
- X
- Xvoid msleep( /* int n */ );
- END_OF_FILE
- if test 238 -ne `wc -c <'msleep.h'`; then
- echo shar: \"'msleep.h'\" unpacked with wrong size!
- fi
- # end of 'msleep.h'
- fi
- if test -f 'readme' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'readme'\"
- else
- echo shar: Extracting \"'readme'\" \(12171 characters\)
- sed "s/^X//" >'readme' <<'END_OF_FILE'
- XTHE BROKEN THRONE, version 2.03
- X
- XBy Tom Boutell, 11/20/90- 10/20/92. As of version 2.01, the game is
- XCopyright 1992, Thomas Boutell. You may do what you wish with it
- Xprovided you do not charge money for the game in any way. All commercial
- Xuse of Broken Throne must be done by agreement with the author (myself).
- X
- XPlease clear changed versions with me first.
- XI'd like to act as a switchboard for new versions of the game.
- X
- XTO INSTALL THE GAME
- X
- XFirst, read the Makefile to see if there are any notes specific to your
- Xsystem (AIX, for instance, requires a small change be made).
- XType "make btserver" to make the server, then type "make btclient" to make
- Xthe client. Third, enter "make btrobot" to make the robot player. Alternatively
- Xyou can simply type "make" particularly if you have built the game before
- Xand know it's fairly compatible with your machine and errors will be few.
- X
- XIF IT WORKS
- X
- XPat yourself on the back and read "bt.doc" next to learn how to start
- Xup and play the game!
- X
- XIF IT DOESN'T WORK (PARTIALLY OR COMPLETELY)
- X
- XThe Server:
- X If you get errors concering the file "bt.h,"
- X or the variable "details" in btinterface.c, then what you need to do
- X is go into bt.h and uncomment a line. There are further instructions
- X in bt.h explaining how to do this.
- X If anything else goes wrong, please mail me the details
- X (boutell@cshl.org). It's worth noting that I wrote
- X a hopefully portable routine, msleep(), to sleep for n microseconds
- X by way of select; if you have trouble with it, but your machine has
- X the routine usleep(), use it instead. (Plain sleep(), unfortunately,
- X only works in 1 - second increments, much too long.)
- X
- XThe Client:
- X "make btclient" can be more problematic, since I have to use Curses, and
- X curses has portability problems here and there. But keyboard I/O is now
- X handled in a way that's just as portable as the socket stuff, so if the
- X server compiles, that shouldn't be a problem either.
- X
- X "But what's wrong with the backspace key?" If you have problems with the
- X backspace or escape keys, look in btclient.h for the definitions (right
- X at the beginning) of these keys. I assumed the regular ASCII definitions,
- X and I'm accepting delete as interchangeable with backspace, so this
- X should cover most folks. If you need to alter these, go ahead; at your
- X own risk of course!
- X
- X If the system complains about "cbreak" and "nocbreak," then insert
- X the line #define BSD_CURSES at the start of btclient.c and recompile.
- X
- XThe Robot:
- X "make btrobot" should have no problems, especially if you have no problem
- X making the client, since it's a hacked client without the ugly user
- X interface stuff that's so difficult to port.
- X
- XAll Three:
- X
- X One easy fix you may have to make: if your compiler complains that errno
- X is undefined, insert "int errno;" at main level in btclient.c. This really
- X shouldn't be necessary, but sometimes it is.
- X
- XIf You Change Things:
- X
- X If you *do* make a fix, please mail it to me so others can have it.
- X Please set it up with an #ifdef specific to your machine, unless of course
- X it's a general bug.
- X
- XHOW TO PLAY:
- X
- XRead bt.doc, which is a manual on how to play the game.
- X
- XCONTACT SERVICE
- X
- XContact me at boutell@cshl.org if you'd like to contact with me with
- Xbug reports and/or suggestions.
- X
- XACKNOWLEDGEMENTS
- X
- XI'd like to thank the net for many, many, *many* useful suggestions and
- Xcorrections. It's due to all of you that I now have such a solid package.
- XA version 2.0 note: I owe an apology to Rudolf Fleischer (sp?), whose
- Xmany fascinating patches for volcanoes and the like were lost over
- Xthe year or two in which I didn't work with the game. Rudolf, if you're
- Xstill out there, feel free to make those patches to version 2.0, and
- XI'll be glad to include them in version 2.1, especially since we
- Xnow have a good mechanism for controlling options.
- X
- XCHANGES IN VERSION 2.03
- X
- X- "-1 troops recruited" fixed more robustly. Also the massive starvation
- Xbug should be fixed.
- X
- XCHANGES IN VERSION 2.02
- X
- X- Failure to refresh info window fixed. (Oops.) Bug introduced by
- Xhelp window fix. Should've tested more thoroughly before releasing this one.
- X
- X- "-1 troops recruited" fixed.
- X
- XCHANGES IN VERSION 2.01
- X
- X- xbt file, inadvertently left out of 2.0, put back in.
- X
- X- Wait queue bug, which caused continuous servers to seem to have huge
- Xqueues despite the fact that no one was playing after being up for
- Xa while, has (hopefully) been fixed.
- X
- X- I've attempted to fix a bug in the support code that would cause
- Xmassive starvation of all troops in the heartland!
- X
- X- The client now redraws the screen properly after looking at the
- Xhelp window.
- X
- XThe version 2.0 client is still compatible with the new server, but the
- Xhelp window fix is enough to justify getting the new one, I think.
- X
- XCHANGES IN VERSION 2.0
- X
- X- SUPPORT RULES. This prevents the "piles of 99 shuffling around" problem
- X of older versions of the game, and adds a new strategic dimension.
- X Some will dislike it at first but it greatly increases the strategic
- X interest of the game.
- X
- X- AUTOMATIC RECRUITMENT. This one has been asked for so many times the
- X exact count is lost to memory.
- X
- X- CONTINUOUS SERVER MODE. This permits the establishment of permanently-
- X open BT servers. (Well, permanent at least until a segmentation
- X fault, that is. (: ) This includes a wait-queue facility.
- X
- X- Variable map size at the server, with clients automatically notified
- X of the map size; clients know if they can't handle a map size and
- X shut themselves down with a message to that effect.
- X
- X- Only territory a player specifically owns now benefits recruitment.
- X
- X- A .btserverrc file to control server options.
- X
- X- Standard option syntax for the command line of each program.
- X
- X- Lots of bug fixes. I even brought the server up under codecenter
- X and beat out bugs and thinkos and misfeatures with it. The code
- X still betrays the fact that it was written in an earlier style
- X I no longer consider elegant, but it's getting downright tolerable.
- X
- XCHANGES IN VERSION 1.12
- X
- X- You can now design your own maps on which to play! This should make games
- X between more than two players substantially more fair than they have
- X been. See the main documentation file.
- X
- X- Armies are now represented by three units each in battle rather than
- X five, since the primary problem with battle odds was somewhere else
- X entirely (see below!).
- X
- X- Another subtle bug: a received text message during the entry of a user's
- X command to move troops or tell a message used to ruin the user's input.
- X This has been fixed.
- X
- X- The redraw key should *finally* work, as long as curscr behaves as it
- X should on your screen. Redraw is capital M ("messy").
- X
- X- The addition of a recruitment warning: the client displays an "R" in the
- X lower right corner for a few seconds each time the necessary period
- X between safe recruitments goes by. The player need not pay attention to this,
- X but it is one way of keeping up.
- X
- X- The client is now guaranteed to correctly display up to 9999 action
- X points per player, without the previous occasional erasing.
- X
- X- A major bug nobody ever reported: The terrain modifiers for combat have
- X been *backwards* since day one! No kidding! I reversed this. All of a
- X sudden it's no longer absurdly easy to take over citadels.
- X
- X- Some users have reported that btclient doesn't accept their backspace key.
- X I've taken my best shot at repairing this, and if you still can't seem
- X to backspace, see the notes above regarding this in the section entitled
- X "The Client:".
- X
- X- A fail- safe escape key has been added; it gets you out of whatever you
- X were doing. I added this to make the default for the move command acceptable
- X to folks used to cancelling it by just pressing RETURN. (Entering 0 will
- X work too of course.)
- X
- X- The infamous void* details; problem has been resolved. In bt.h, the main
- X makefile, you can now uncomment a line to force the program to use
- X char* as a generic pointer type instead. This should satisfy the
- X longings of older compilers.
- X
- X- The move command now defaults to *all* armies in the sector you are
- X moving from. Of course it is possible that these armies may get sacked
- X as you are in the process of giving the order, in which case it won't
- X go through, but the client will try to move the most current number of
- X armies. (This was just as possible before when typing in the number of
- X armies explicitly and losing a few in the process.)
- X
- X- More compatibility fixes. Cleaned up use of "=-" and "=*"; added
- X #ifdefs for BSD curses (see "if it doesn't work"). Please send your patches!
- X
- XCHANGES IN VERSION 1.11
- X
- X- Replaced a forgotten call to usleep() in btclient with a call to my
- X msleep() function.
- X
- XCHANGES IN VERSION 1.10
- X
- X- Many folks have reported arguments between their compiler and my
- X use of a void pointer named "details" in interface.c. I've unrolled
- X this code a little in hopes of placating unfriendly compilers. If you've
- X had this problem and been able to solve it, please let me know! Folks
- X would like the solution.
- X- The server now uses a little routine named msleep() to sleep for n
- X microseconds, instead of usleep() (a wonderful but nonportable SunOS
- X routine). I should thank the net for many suggestions and code examples
- X leading to this.
- X- A viable robot player is now included! See the bt.doc file for details
- X on its use.
- X- The usleep() call has been eliminated. The client program now simply
- X selects until either a keyboard event or server message arrives. Very
- X polite; no nasty demand on the processor. Also much more portable.
- X- The M command (redraw map) now works properly.
- X- Problems due to which the game could crash after folks disconnected
- X have been resolved. This is a major improvement; I haven't been able
- X to get the server to crash since.
- X- There are no more strange delays in which another keypress is needed
- X to make the last one "go through." The same change that eliminated the
- X call to usleep() fixed this.
- X- The quit command now has a confirmation that accepts only 'y' or 'Y'
- X to prevent accidental disconnection.
- X- The code is somewhat cleaned up, though the haste with which I wrote the
- X game still shows!
- X- THE INFAMOUS ACTION POINT BUG IS DEAD! Hurrah! With some help from folks
- X on rec.games.programmer, I discovered that when the client was through
- X handling a "move" message from the server, it would "fall through" and
- X process an "action" message, producing an incorrect AP count. AP counts
- X should now be displayed correctly at all times, and movement costs
- X will no longer appear random. (They never were, but after movement, the
- X correct number of APs was broadcast, understandably confusing the player
- X pretty badly.)
- X- *** A change affecting the rules: army units now fight as sets of
- X five units. This is invisible to the player, but results in a more
- X even distribution of losses, so it's much less common to take out four
- X armies with one by luck, although still possible.
- X
- XCHANGES IN VERSION 1.01
- X
- X- Input is now handled in a way that should be generic BSD.
- X- The 'h' key no longer summons help; this is now done with the ? key,
- X shifted or not ('/').
- X- Certain strange compiler errors in interface.c are resolved. (Some
- X compilers were treating =* as meaning something other than "equal to
- X the dereferenced value of." One even treated =-1 as meaning something
- X other than equal to -1!) Parentheses in judicious places solved these.
- X- You can now move the cursor while "thinking" about what command to enter.
- X The only time you can't move the cursor is while entering a text
- X message or typing a number of troops.
- X- It is now easier to tell whether you are in command mode or entering
- X a location.
- X- You can now specify a different port number. This is given as a second
- X argument to btserver, and also to btclient. This permits multiple games
- X on one machine.
- X- 'M' (capitalized) now redraws a Messy screen after a talk message, etc.
- X- There is now an opening message while the map is being transmitted.
- X- The number of players must be inputted on the command line. An old
- X undocumented feature of the server was the ability to prompt for this,
- X removed to make the new port number question unambiguous.
- END_OF_FILE
- if test 12171 -ne `wc -c <'readme'`; then
- echo shar: \"'readme'\" unpacked with wrong size!
- fi
- # end of 'readme'
- fi
- if test -f 'xbt' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'xbt'\"
- else
- echo shar: Extracting \"'xbt'\" \(83 characters\)
- sed "s/^X//" >'xbt' <<'END_OF_FILE'
- X#!/bin/sh
- X
- Xexec `xterm -fn "-*-fixed-*-*-*-*-*-200-*-*-*-*-*-*" -e btclient $*` &
- END_OF_FILE
- if test 83 -ne `wc -c <'xbt'`; then
- echo shar: \"'xbt'\" unpacked with wrong size!
- fi
- chmod +x 'xbt'
- # end of 'xbt'
- fi
- echo shar: End of archive 3 \(of 3\).
- cp /dev/null ark3isdone
- 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
-