home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / games / volume15 / bt4 / part03 < prev    next >
Encoding:
Internet Message Format  |  1993-01-26  |  38.2 KB

  1. Path: uunet!charon.amdahl.com!pacbell.com!network.ucsd.edu!ogicse!zephyr.ens.tek.com!master!saab!billr
  2. From: billr@saab.CNA.TEK.COM (Bill Randle)
  3. Newsgroups: comp.sources.games
  4. Subject: v15i017:  bt4 - Broken Throne, multiplayer realtime conquest game (V2.03), Part03/03
  5. Message-ID: <3828@master.CNA.TEK.COM>
  6. Date: 29 Oct 92 01:42:45 GMT
  7. Article-I.D.: master.3828
  8. Sender: news@master.CNA.TEK.COM
  9. Lines: 1372
  10. Approved: billr@saab.CNA.TEK.COM
  11. Xref: uunet comp.sources.games:1516
  12.  
  13. Submitted-by: boutell@isis.cshl.org (Tom Boutell)
  14. Posting-number: Volume 15, Issue 17
  15. Archive-name: bt4/Part03
  16. Supersedes: bt3: Volume 12, Issue 52-53
  17. Environment: INET sockets, curses
  18.  
  19.  
  20.  
  21. #! /bin/sh
  22. # This is a shell archive.  Remove anything before this line, then unpack
  23. # it by saving it into a file and typing "sh file".  To overwrite existing
  24. # files, type "sh file -c".  You can also feed this as standard input via
  25. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  26. # will see the following message at the end:
  27. #        "End of archive 3 (of 3)."
  28. # Contents:  INSTALL Makefile bt.h btinterface.c btinterface.h btpack.c
  29. #   btpack.h map.txt msleep.c msleep.h readme xbt
  30. # Wrapped by billr@saab on Wed Oct 28 17:38:00 1992
  31. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  32. if test -f 'INSTALL' -a "${1}" != "-c" ; then 
  33.   echo shar: Will not clobber existing file \"'INSTALL'\"
  34. else
  35. echo shar: Extracting \"'INSTALL'\" \(97 characters\)
  36. sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
  37. XCopy the 'btserverrc' file to '.btserverrc' in your home directory or in
  38. Xyour playing directory.
  39. END_OF_FILE
  40. if test 97 -ne `wc -c <'INSTALL'`; then
  41.     echo shar: \"'INSTALL'\" unpacked with wrong size!
  42. fi
  43. # end of 'INSTALL'
  44. fi
  45. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  46.   echo shar: Will not clobber existing file \"'Makefile'\"
  47. else
  48. echo shar: Extracting \"'Makefile'\" \(858 characters\)
  49. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  50. Xall: btclient btserver btrobot
  51. X
  52. X#don't use -ltermlib for AIX (edit second line for btclient, below, to
  53. X#remove this).
  54. X#don't use -O or -lbsd with AIX, either (not used here but something you
  55. X#might otherwise expect to need to change).
  56. X
  57. Xbtclient: btclient.o btpack.o msleep.o
  58. X    cc btclient.o btpack.o msleep.o -o btclient -ltermcap -lcurses -ltermlib
  59. X
  60. Xbtserver: btserver.o btpack.o btinterface.o msleep.o
  61. X    cc btserver.o btpack.o btinterface.o msleep.o -o btserver 
  62. X
  63. Xbtrobot: btrobot.o btpack.o
  64. X    cc btrobot.o btpack.o -o btrobot
  65. X
  66. Xbtrobot.o: btrobot.c bt.h
  67. X    cc -c -g btrobot.c
  68. X
  69. Xbtclient.o: btclient.c btclient.h bt.h
  70. X    cc -c -g btclient.c
  71. Xbtpack.o: btpack.c btpack.h
  72. X    cc -c -g btpack.c
  73. Xbtinterface.o: btinterface.c btinterface.h
  74. X    cc -c -g btinterface.c 
  75. Xbtserver.o: btserver.c btserver.h bt.h
  76. X    cc -c -g btserver.c 
  77. Xmsleep.o: msleep.c msleep.h
  78. X    cc -c -g msleep.c
  79. X
  80. END_OF_FILE
  81. if test 858 -ne `wc -c <'Makefile'`; then
  82.     echo shar: \"'Makefile'\" unpacked with wrong size!
  83. fi
  84. # end of 'Makefile'
  85. fi
  86. if test -f 'bt.h' -a "${1}" != "-c" ; then 
  87.   echo shar: Will not clobber existing file \"'bt.h'\"
  88. else
  89. echo shar: Extracting \"'bt.h'\" \(1463 characters\)
  90. sed "s/^X//" >'bt.h' <<'END_OF_FILE'
  91. X/*
  92. X * Main Include File for Broken Throne By Tom Boutell Do As Thou Wilt, But
  93. X * Give Me The Source!
  94. X * 
  95. X * If your compiler complains, uncomment the line below (remove the surrounding
  96. X * characters). Thanks to Marcus Ranum:
  97. X */
  98. X
  99. X/* #define COMPILER_HATES_VOIDSTAR 1 */
  100. X
  101. X#ifdef COMPILER_HATES_VOIDSTAR
  102. Xtypedef char   *pointer;
  103. X#else
  104. Xtypedef void   *pointer;
  105. X#endif
  106. X
  107. Xtypedef struct {
  108. X    char            terrain;
  109. X    int             population;
  110. X    int             lastuse;
  111. X    int             troops;
  112. X    int             owner;
  113. X    int             region;
  114. X}               hex;
  115. X
  116. Xtypedef struct {
  117. X    int             x;
  118. X    int             y;
  119. X}               location;
  120. X
  121. Xtypedef struct {
  122. X    int             action;
  123. X    int             hexes;
  124. X    int             troops;
  125. X    int             population;
  126. X    int             citadels;
  127. X    int             live;
  128. X    location        start;
  129. X}               player;
  130. X
  131. X/* Messages from server to clients: */
  132. X#define _HEXSTATUS 65
  133. X#define _PLAYERSTATUS 66
  134. X#define _PLAYERDEAD 67
  135. X#define _ACTION 68
  136. X#define _TEXT 69
  137. X#define _STARTUP 70
  138. X#define _END 71
  139. X#define _YOUARE 72
  140. X#define _LOOK 73
  141. X#define _BUSY 74
  142. X
  143. X/* From clients to server: */
  144. X#define _MOVE 65
  145. X#define _RECRUIT 66
  146. X#define _QUIT 67
  147. X#define _PRIVATE 68
  148. X#define _TELLALL 69
  149. X#define _DISCONNECT 70
  150. X#define _CONSTRUCT 71
  151. X#define _DESTROY 72
  152. X
  153. X/* Maximum number of players (this # is really outrageously high): */
  154. X
  155. X#define _MAXPLAYERS 20
  156. X
  157. X/* Maximum size of wait queue (also pretty hefty): */
  158. X
  159. X#define _MAXWAITQUEUE 40
  160. END_OF_FILE
  161. if test 1463 -ne `wc -c <'bt.h'`; then
  162.     echo shar: \"'bt.h'\" unpacked with wrong size!
  163. fi
  164. # end of 'bt.h'
  165. fi
  166. if test -f 'btinterface.c' -a "${1}" != "-c" ; then 
  167.   echo shar: Will not clobber existing file \"'btinterface.c'\"
  168. else
  169. echo shar: Extracting \"'btinterface.c'\" \(14454 characters\)
  170. sed "s/^X//" >'btinterface.c' <<'END_OF_FILE'
  171. X
  172. X/*
  173. X * btinterface.c: Socket communications support& medium- level message
  174. X * passing functions. Copyright (C) 1990 Tom Boutell on original portions.
  175. X * All low- level socket code drawn with appreciation from: SOCK.C Copyright
  176. X * (C)1989 Dr Evil Laboratories This code written by Ray Moody, Roy Riggs,
  177. X * Mitch Adler, Bill Burdick, and Steven Grady No one makes any guarantees
  178. X * about anything.  This file maybe freely distributed and modified as long
  179. X * as this header remains intact.
  180. X */
  181. X
  182. X#include <stdio.h>
  183. X#include <sys/types.h>
  184. X#include <sys/time.h>
  185. X#include <sys/socket.h>
  186. X#include <netinet/in.h>
  187. X
  188. X#ifdef _AIX
  189. X#include <sys/select.h>
  190. X#endif
  191. X
  192. X#ifdef sequent
  193. X#include <strings.h>
  194. X#else
  195. X#include <string.h>
  196. X#endif
  197. X
  198. X#include <ctype.h>
  199. X#include <signal.h>
  200. X#include <netdb.h>
  201. X#include <varargs.h>
  202. X
  203. X#include "btpack.h"
  204. X#include "bt.h"
  205. X#include "btserver.h"
  206. X#include "btinterface.h"
  207. X
  208. X#define DEBUG
  209. X#undef DEBUG
  210. X#ifdef DEBUG
  211. X#define debug printf
  212. X#else
  213. X#define debug 0+
  214. X#define perror 0+
  215. X#endif
  216. X
  217. X#define TRACE 1
  218. X
  219. X#define SECONDSLIMIT 0L
  220. X#define MICROSECONDSLIMIT 1L
  221. X
  222. X#define LINE_LEN 1024
  223. X#define LOST_CARRIER_MSG "F"
  224. X
  225. X#define NONE (fd_set *) NULL
  226. X#define NEVER (struct timeval *) NULL
  227. X#define IGNORE (struct sockaddr *) NULL
  228. X
  229. X/* To assist in signal handling: */
  230. X
  231. X#define SENDPLAYER 0
  232. X#define SENDQUEUE 1
  233. X#define SENDOTHER 2
  234. Xint             sendtype;
  235. Xint             whodied;
  236. Xint             brokenpipe = 0;
  237. X
  238. Xfd_set          active;
  239. Xstruct sockaddr_in sc_in;
  240. Xint             s;
  241. Xchar            cur_input[LINE_LEN];
  242. Xchar           *curhostname = "";
  243. Xint             playerfds[_MAXPLAYERS];
  244. Xchar            outputline[256];
  245. Xint             full;
  246. X
  247. Xint             waitqueue[_MAXWAITQUEUE];
  248. Xint             waitqueuefront = 0;
  249. Xint             waitqueueback = 0;
  250. Xint             waitqueuetotal = 0;
  251. X
  252. Xvoid 
  253. Xsetupinterface(portnumber)
  254. X    int             portnumber;
  255. X{
  256. X    init_socket(portnumber);
  257. X    playertext = (outputline + 1);
  258. X    signal(SIGPIPE, broken);
  259. X    full = 0;
  260. X}
  261. X
  262. Xvoid 
  263. Xfetchplayers()
  264. X{
  265. X    int             current;
  266. X    int             gotplayers = 0;
  267. X    for (current = 1; (current <= totalplayers); current++) {
  268. X        players[current].live = 0;
  269. X    }
  270. X    do {
  271. X        int             p;
  272. X        unsigned char   type;
  273. X        int             np;
  274. X        int             fd = -1;
  275. X        char            specific[81];
  276. X        if ((!waitqueuetotal) || ((fd = waitdequeue()) == -1)) {
  277. X            do {
  278. X                np = new_player(0);
  279. X                if (np != -1) {
  280. X                    fd = np;
  281. X                }
  282. X            } while (fd == -1);
  283. X        }
  284. X        for (current = 1; (current <= totalplayers); current++) {
  285. X            if (players[current].live == 0) {
  286. X                gotplayers++;
  287. X                playerfds[current] = fd;
  288. X                players[current].live = 1;
  289. X#if TRACE
  290. X                printf("Player %d has joined.\n", current);
  291. X#endif
  292. X                outputline[0] = _YOUARE;
  293. X                outputline[1] = 64 + current;
  294. X                outputline[2] = 0;
  295. X                if (!(w_p(current, outputline, strlen(&outputline[0]) + 1))) {
  296. X#if TRACE
  297. X                    printf("... Connection broken.\n");
  298. X#endif
  299. X                    players[current].live = 0;
  300. X                    disconnect_player(current);
  301. X                    gotplayers--;
  302. X                }
  303. X                break;
  304. X            }
  305. X        }
  306. X        while (getrequest(&p, &type, specific)) {
  307. X            if (type == _DISCONNECT) {
  308. X                players[p].live = 0;
  309. X#if TRACE
  310. X                printf("Player %d quit during startup.\n", p);
  311. X#endif
  312. X                disconnect_player(p);
  313. X                gotplayers--;
  314. X            }
  315. X        }
  316. X    } while (gotplayers < totalplayers);
  317. X    full = 1;
  318. X}
  319. X
  320. Xvoid 
  321. Xtellplayer(theplayer)
  322. X    int             theplayer;
  323. X{
  324. X    outputline[0] = _TEXT;
  325. X    w_p(theplayer, outputline, strlen(outputline) + 1);
  326. X}
  327. X
  328. Xvoid 
  329. Xbroadcast(messagetype, details)
  330. X    char            messagetype;
  331. X    pointer         details;
  332. X{
  333. X    location        where;
  334. X    location       *wherep;
  335. X    int             thisplayer;
  336. X    int             current;
  337. X    outputline[0] = messagetype;
  338. X    switch (messagetype) {
  339. X
  340. X    case _HEXSTATUS:
  341. X        wherep = (location *) details;
  342. X        where = (*wherep);
  343. X        outputline[1] = 64 + where.x;
  344. X        outputline[2] = 64 + where.y;
  345. X        outputline[3] = 64 + map[where.x][where.y].terrain;
  346. X        packint(4, map[where.x][where.y].population);
  347. X        packint(7, map[where.x][where.y].lastuse);
  348. X        packint(10, map[where.x][where.y].troops);
  349. X        outputline[13] = map[where.x][where.y].owner + 64;
  350. X        outputline[14] = NULL;
  351. X        break;
  352. X    case _LOOK:
  353. X        where = (*(location *) details);
  354. X        outputline[1] = 64 + where.x;
  355. X        outputline[2] = 64 + where.y;
  356. X        outputline[3] = NULL;
  357. X        break;
  358. X    case _PLAYERSTATUS:
  359. X        thisplayer = (*(int *) details);
  360. X        outputline[1] = thisplayer + 64;
  361. X        packint(2, players[thisplayer].action);
  362. X        packint(5, players[thisplayer].hexes);
  363. X        packint(8, players[thisplayer].troops);
  364. X        packint(11, players[thisplayer].population);
  365. X        packint(14, players[thisplayer].citadels);
  366. X        outputline[17] = players[thisplayer].start.x + 64;
  367. X        outputline[18] = players[thisplayer].start.y + 64;
  368. X        outputline[19] = NULL;
  369. X        break;
  370. X    case _PLAYERDEAD:
  371. X        thisplayer = (*(int *) details);
  372. X        outputline[1] = thisplayer + 64;
  373. X        outputline[2] = NULL;
  374. X        break;
  375. X    case _ACTION:
  376. X        outputline[1] = NULL;
  377. X        break;
  378. X    case _STARTUP:
  379. X        outputline[1] = totalplayers + 64;
  380. X        where = (*(location *) details);
  381. X        outputline[2] = 64 + where.x;
  382. X        outputline[3] = 64 + where.y;
  383. X        outputline[4] = NULL;
  384. X        break;
  385. X    case _TEXT:
  386. X        strcpy(&outputline[1], (char *) details);
  387. X        break;
  388. X    case _END:
  389. X        outputline[1] = NULL;
  390. X    }
  391. X    for (current = 0; (current <= totalplayers); current++) {
  392. X        if (players[current].live) {
  393. X            if (!(w_p(current, outputline, strlen(outputline) + 1))) {
  394. X                players[current].live = 0;
  395. X                killplayer(current);
  396. X            }
  397. X        }
  398. X    }
  399. X}
  400. X
  401. Xvoid 
  402. Xbroadcastwaitqueue(messagetype, details)
  403. X    unsigned char   messagetype;
  404. X    pointer         details;
  405. X{
  406. X    int             i;
  407. X    switch (messagetype) {
  408. X    case _END:
  409. X        outputline[0] = _END;
  410. X        outputline[1] = NULL;
  411. X        break;
  412. X    case _TEXT:
  413. X        outputline[0] = _TEXT;
  414. X        strcpy(&outputline[1], details);
  415. X        break;
  416. X    case _BUSY:
  417. X        outputline[0] = _BUSY;
  418. X        outputline[1] = NULL;
  419. X        break;
  420. X    }
  421. X    i = waitqueueback;
  422. X    while (i != waitqueuefront) {
  423. X        w_q(i, outputline, strlen(outputline) + 1);
  424. X        i++;
  425. X        if (i >= _MAXWAITQUEUE)
  426. X            i = 0;
  427. X    };
  428. X}
  429. X
  430. Xvoid 
  431. Xtellwaitqueue(q)
  432. X    int             q;
  433. X{
  434. X    outputline[0] = _TEXT;
  435. X    w_q(q, outputline, strlen(outputline) + 1);
  436. X}
  437. X
  438. Xvoid 
  439. Xupdatewaitqueue()
  440. X{
  441. X    int             i;
  442. X    int             count = 0;
  443. X    outputline[0] = _TEXT;
  444. X    i = waitqueueback;
  445. X    while (i != waitqueuefront) {
  446. X        if (waitqueue[i] != -1) {
  447. X            sprintf(playertext, "You are now #%d in the queue.", ++count);
  448. X            tellwaitqueue(i);
  449. X        }
  450. X        i++;
  451. X        if (i > _MAXWAITQUEUE) {
  452. X            i = 0;
  453. X        }
  454. X    }
  455. X}
  456. X
  457. Xint 
  458. Xgetrequest(thisplayer, requesttype, specific)
  459. X    int            *thisplayer;
  460. X    char           *requesttype;
  461. X    char           *specific;
  462. X{
  463. X    char           *received;
  464. X    static int      sweep;
  465. X    int             oldsweep;
  466. X    if (full) {
  467. X        int             np;
  468. X        np = new_player(1);
  469. X        if (np != -1) {
  470. X            if (gamecontinuous) {
  471. X                /*
  472. X                 * We're running in continuous mode, so
  473. X                 * enqueue
  474. X                 */
  475. X                waitenqueue(np);
  476. X            } else {
  477. X                /* Tell them we're busy */
  478. X                outputline[0] = _BUSY;
  479. X                outputline[1] = '\0';
  480. X                w_fd(np, outputline, strlen(outputline) + 1);
  481. X                disconnect_fd(np);
  482. X            }
  483. X        }
  484. X    }
  485. X    sweep++;
  486. X    if ((sweep > totalplayers) || (sweep <= 0))
  487. X        sweep = 1;
  488. X    oldsweep = sweep;
  489. X    while (players[sweep].live == 0) {
  490. X        sweep++;
  491. X        if (sweep > totalplayers)
  492. X            sweep = 1;
  493. X        if (sweep == oldsweep)
  494. X            return 0;
  495. X    }
  496. X    received = read_player(sweep);
  497. X    *thisplayer = sweep;
  498. X    if (*received == NULL)
  499. X        return 0;
  500. X    *requesttype = received[0];
  501. X    strcpy(specific, (received += 1));
  502. X    return 1;
  503. X}
  504. X
  505. X
  506. Xvoid 
  507. Xshutdowninterface()
  508. X{
  509. X    disconnect_all();
  510. X}
  511. X
  512. X/* Burst pipe handler */
  513. X
  514. Xvoid 
  515. Xbroken()
  516. X{
  517. X    /* Reinstall ourselves */
  518. X    signal(SIGPIPE, broken);
  519. X    brokenpipe = 1;
  520. X    /* Switch on who we were writing to */
  521. X    switch (sendtype) {
  522. X    case SENDPLAYER:
  523. X        players[whodied].live = 0;
  524. X        killplayer(whodied);
  525. X        break;
  526. X    case SENDQUEUE:
  527. X        disconnect_fd(waitqueue[whodied]);
  528. X        /* Set slot available */
  529. X        waitqueue[whodied] = -1;
  530. X        break;
  531. X    case SENDOTHER:
  532. X        /* Just close the fd and hope this doesn't put us in a loop */
  533. X        disconnect_fd(whodied);
  534. X        break;
  535. X    }
  536. X}
  537. X
  538. Xint 
  539. Xwaitdequeue()
  540. X{
  541. X    int             fd;
  542. X    do {
  543. X        if (waitqueuetotal == 0) {
  544. X            return -1;
  545. X        }
  546. X        waitqueuetotal--;
  547. X        fd = waitqueue[waitqueueback++];
  548. X        if (waitqueueback >= _MAXWAITQUEUE)
  549. X            waitqueueback = 0;
  550. X        updatewaitqueue();
  551. X    } while (fd == -1);
  552. X    return fd;
  553. X}
  554. X
  555. Xvoid 
  556. Xwaitenqueue(fd)
  557. X    int             fd;
  558. X{
  559. X    if (waitqueuetotal == _MAXWAITQUEUE) {
  560. X        outputline[0] = _TEXT;
  561. X        sprintf(&outputline[1], "Queue is full, try later.");
  562. X        w_fd(fd, outputline, strlen(outputline) + 1);
  563. X        outputline[0] = _BUSY;
  564. X        outputline[1] = '\0';
  565. X        w_fd(fd, outputline, strlen(outputline) + 1);
  566. X        disconnect_fd(fd);
  567. X        return;
  568. X    }
  569. X    waitqueue[waitqueuefront] = fd;
  570. X    waitqueuetotal++;
  571. X    outputline[0] = _TEXT;
  572. X    sprintf(&outputline[1], "You are #%d in the wait queue.", waitqueuetotal);
  573. X    w_q(waitqueuefront, outputline, strlen(outputline) + 1);
  574. X    outputline[0] = _TEXT;
  575. X    sprintf(&outputline[1], "(There are %d players per game.)", totalplayers);
  576. X    w_q(waitqueuefront, outputline, strlen(outputline) + 1);
  577. X    waitqueuefront++;
  578. X    if (waitqueuefront >= _MAXWAITQUEUE)
  579. X        waitqueuefront = 0;
  580. X}
  581. X
  582. X/*
  583. X * - PD Socket code begins here. init_socket() - initialize our socket, port
  584. X * is the port number to use call this once at the beginning of your code
  585. X */
  586. X
  587. Xint 
  588. Xinit_socket(port)
  589. X    int             port;
  590. X{
  591. X    setbuf(stdout, (char *) 0);
  592. X    if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  593. X        perror("socket");
  594. X        return 0;
  595. X    }
  596. X    sc_in.sin_family = AF_INET;
  597. X    sc_in.sin_addr.s_addr = INADDR_ANY;
  598. X    sc_in.sin_port = htons((u_short) port);
  599. X    if (bind(s, (struct sockaddr *) & sc_in, sizeof(sc_in)) < 0) {
  600. X        perror("bind");
  601. X        return 0;
  602. X    }
  603. X    if (listen(s, 5) < 0) {
  604. X        perror("listen");
  605. X        return 0;
  606. X    }
  607. X    FD_ZERO(&active);
  608. X
  609. X    return 1;
  610. X}
  611. X
  612. X
  613. X/*
  614. X * disconnect_all() - throws everyone off
  615. X */
  616. X
  617. Xint 
  618. Xdisconnect_all()
  619. X{
  620. X    register int    i;
  621. X
  622. X    for (i = 0; i < FD_SETSIZE; i++) {
  623. X        if (FD_ISSET(i, &active))
  624. X            (void) disconnect_fd(i);
  625. X    }
  626. X    return 1;
  627. X}
  628. X
  629. X
  630. X/*
  631. X * shut-down -- kills all connections and exits the pgm
  632. X */
  633. X
  634. Xint 
  635. Xshut_down()
  636. X{
  637. X    (void) disconnect_all();
  638. X    exit(0);
  639. X}
  640. X
  641. X
  642. X/*
  643. X * hostfrom() - returns a string containing an ascii name for the host that
  644. X * the passed socket s is connected to.  Note that the string is in static
  645. X * space.  If you want to munge with it, make a copy.
  646. X */
  647. X
  648. Xchar           *
  649. Xhostfrom(i)
  650. X    int             i;
  651. X{
  652. X    struct sockaddr_in from;
  653. X    int             fromlen = sizeof(from);
  654. X    struct hostent *host;
  655. X    struct in_addr  addr;
  656. X
  657. X    if (getpeername(i, &from, &fromlen) < 0) {
  658. X        perror("getpeername");
  659. X        return NULL;
  660. X    }
  661. X    addr = from.sin_addr;
  662. X    if ((host = gethostbyaddr(&addr, sizeof(addr), AF_INET)) == NULL) {
  663. X        debug("gethostbyaddr failed");
  664. X        return NULL;
  665. X    }
  666. X    return curhostname = host->h_name;
  667. X}
  668. X
  669. X
  670. X/*
  671. X * hostname() - returns curhostname
  672. X */
  673. X
  674. Xchar           *
  675. Xhostname()
  676. X{
  677. X    return curhostname;
  678. X}
  679. X
  680. X
  681. X/*
  682. X * new_player() - call this routine in your main loop to allow new players to
  683. X * join.  returns a playerId or -1 if no one wants to join. if wait == 0,
  684. X * then put your process to sleep until someone new tries to connect.
  685. X */
  686. X
  687. Xint 
  688. Xnew_player(wait)
  689. X    int             wait;    /* 0 - wait for activity, else don't wait */
  690. X{
  691. X    fd_set          readfds;
  692. X    int             j;
  693. X    struct timeval *pWaitTime, waitTime;
  694. X
  695. X    pWaitTime = &waitTime;
  696. X
  697. X    if (0 == wait) {
  698. X        pWaitTime = NEVER;
  699. X    } else {
  700. X        pWaitTime->tv_sec = SECONDSLIMIT;
  701. X        pWaitTime->tv_usec = MICROSECONDSLIMIT;
  702. X    }
  703. X
  704. X    bcopy((char *) &active, (char *) &readfds, sizeof(active));
  705. X
  706. X    FD_SET(s, &readfds);
  707. X
  708. X    if (select(FD_SETSIZE, &readfds, NONE, NONE, pWaitTime) < 0) {
  709. X        perror("select");
  710. X        return -1;
  711. X    }
  712. X    if (FD_ISSET(s, &readfds)) {
  713. X        if ((j = accept(s, IGNORE, (int *) 0)) < 0) {
  714. X            return -1;
  715. X        }
  716. X        FD_SET(j, &active);
  717. X        curhostname = hostfrom(j);
  718. X        debug("Test Host=%s\n", curhostname);
  719. X        return j;
  720. X    } else {
  721. X        return -1;
  722. X    }
  723. X}
  724. X
  725. X/* disconnect_player: disconnects given player */
  726. X
  727. Xint 
  728. Xdisconnect_player(p)
  729. X    int             p;
  730. X{
  731. X    disconnect_fd(playerfds[p]);
  732. X}
  733. X
  734. X/*
  735. X * disconnect_fd() - drop the connection with the given fd
  736. X */
  737. X
  738. Xint 
  739. Xdisconnect_fd(fd)
  740. X    int             fd;
  741. X{
  742. X    if (FD_ISSET(fd, &active)) {
  743. X        debug("** Just dropped %d\n", fd);
  744. X        FD_CLR(fd, &active);
  745. X        if (close(fd) < 0) {
  746. X            perror("close");
  747. X            return 0;
  748. X        }
  749. X    } else {
  750. X        debug("** Just tried to drop someone not connected\n");
  751. X        return 0;
  752. X    }
  753. X    return 1;
  754. X}
  755. X
  756. X/* read_player() - returns next string from given player. */
  757. X
  758. Xchar           *
  759. Xread_player(p)
  760. X    int             p;
  761. X{
  762. X    return (read_fd(playerfds[p]));
  763. X}
  764. X
  765. X/*
  766. X * read_fd() -     This routine returns the next string from the given fd. If
  767. X * there is no input it returns the empty string. If the connection is lost
  768. X * the string LOST_CARRIER_MSG is returned.
  769. X */
  770. X
  771. Xchar           *
  772. Xread_fd(playerFd)
  773. X    int             playerFd;
  774. X{
  775. X    fd_set          readfds;
  776. X    struct timeval  waitTime;
  777. X
  778. X    waitTime.tv_sec = SECONDSLIMIT;
  779. X    waitTime.tv_usec = MICROSECONDSLIMIT;
  780. X
  781. X    bcopy((char *) &active, (char *) &readfds, sizeof(active));
  782. X
  783. X    if (select(FD_SETSIZE, &readfds, NONE, NONE, &waitTime) < 0) {
  784. X        perror("select");
  785. X        return ("");
  786. X    }
  787. X    if (FD_ISSET(playerFd, &readfds)) {
  788. X        int             nbytes;
  789. X
  790. X        nbytes = read(playerFd, cur_input, LINE_LEN);
  791. X        if (nbytes < 0) {
  792. X            perror("read");
  793. X            disconnect_fd(playerFd);
  794. X            return (LOST_CARRIER_MSG);
  795. X        } else if (nbytes == 0) {
  796. X            disconnect_fd(playerFd);
  797. X            return (LOST_CARRIER_MSG);
  798. X        } else {
  799. X            if (nbytes != LINE_LEN) {
  800. X                cur_input[nbytes] = '\0';
  801. X            } else {
  802. X                cur_input[LINE_LEN - 1] = '\0';
  803. X            }
  804. X
  805. X            return ((char *) cur_input);
  806. X        }
  807. X    }
  808. X    return ("");
  809. X}
  810. X
  811. X/* w_p() - write string of given length to player p */
  812. X
  813. Xint 
  814. Xw_p(p, str, len)
  815. X    int             p;
  816. X    char           *str;
  817. X    int             len;
  818. X{
  819. X    /* To assist in sigpipe handling */
  820. X    sendtype = SENDPLAYER;
  821. X    whodied = p;
  822. X    write_fd_proper(playerfds[p], str, len);
  823. X    if (brokenpipe) {
  824. X        brokenpipe = 0;
  825. X        return 0;
  826. X    }
  827. X    return 1;
  828. X}
  829. X
  830. X/* w_q() - write string of given length to queue position q */
  831. X
  832. Xint 
  833. Xw_q(q, str, len)
  834. X    int             q;
  835. X    char           *str;
  836. X    int             len;
  837. X{
  838. X    sendtype = SENDQUEUE;
  839. X    whodied = q;
  840. X    write_fd_proper(waitqueue[q], str, len);
  841. X    if (brokenpipe) {
  842. X        brokenpipe = 0;
  843. X        return 0;
  844. X    }
  845. X    return 1;
  846. X}
  847. X
  848. X/*
  849. X * w_fd() - write to file descriptor, a string with the given length
  850. X */
  851. X
  852. Xint 
  853. Xw_fd(fd, str, len)
  854. X    int             fd;
  855. X    char           *str;
  856. X    int             len;
  857. X{
  858. X    sendtype = SENDOTHER;
  859. X    write_fd_proper(fd, str, len);
  860. X    if (brokenpipe) {
  861. X        brokenpipe = 0;
  862. X        return 0;
  863. X    }
  864. X    return 1;
  865. X}
  866. X
  867. Xint 
  868. Xwrite_fd_proper(fd, str, len)
  869. X    int             fd;
  870. X    char           *str;
  871. X    int             len;
  872. X{
  873. X    if (fd > -1) {
  874. X        if (!FD_ISSET(fd, &active)) {
  875. X            debug("** Tried to write to closed id #%d.\n", fd);
  876. X            return 0;
  877. X        } else if (write(fd, str, len) < 0) {
  878. X            perror("Write");
  879. X            return 0;
  880. X        }
  881. X    }
  882. X    return 1;
  883. X}
  884. END_OF_FILE
  885. if test 14454 -ne `wc -c <'btinterface.c'`; then
  886.     echo shar: \"'btinterface.c'\" unpacked with wrong size!
  887. fi
  888. # end of 'btinterface.c'
  889. fi
  890. if test -f 'btinterface.h' -a "${1}" != "-c" ; then 
  891.   echo shar: Will not clobber existing file \"'btinterface.h'\"
  892. else
  893. echo shar: Extracting \"'btinterface.h'\" \(897 characters\)
  894. sed "s/^X//" >'btinterface.h' <<'END_OF_FILE'
  895. Xvoid            setupinterface();    /* int portnumber */
  896. Xvoid            shutdowninterface();
  897. Xint             getrequest();
  898. X/* int* player,char* requesttype,char* specific */
  899. Xvoid            broadcast();    /* char messagetype,void* details */
  900. Xvoid            tellplayer();    /* int player */
  901. Xint             init_socket();    /* int port */
  902. Xint             disconnect_all();
  903. Xint             shutdown();
  904. Xchar           *hostfrom();    /* int i */
  905. Xchar           *hostname();
  906. Xint             new_player();    /* int wait */
  907. Xint             disconnect();    /* int id */
  908. Xchar           *read_player();    /* int playerFd */
  909. Xint             w_p();        /* int id, char* str, int len */
  910. Xchar           *playertext;    /* String to sprinted by tellplayer */
  911. Xvoid            broken();    /* Broken pipe handler */
  912. Xvoid            updatewaitqueue();
  913. Xchar           *read_fd();
  914. Xint             w_fd();
  915. Xint             write_fd_proper();
  916. END_OF_FILE
  917. if test 897 -ne `wc -c <'btinterface.h'`; then
  918.     echo shar: \"'btinterface.h'\" unpacked with wrong size!
  919. fi
  920. # end of 'btinterface.h'
  921. fi
  922. if test -f 'btpack.c' -a "${1}" != "-c" ; then 
  923.   echo shar: Will not clobber existing file \"'btpack.c'\"
  924. else
  925. echo shar: Extracting \"'btpack.c'\" \(875 characters\)
  926. sed "s/^X//" >'btpack.c' <<'END_OF_FILE'
  927. X/*
  928. X * pack.c: Functions for packing of Broken Throne data for transmission via
  929. X * sockets. Copyright 1990, Tom Boutell.
  930. X */
  931. X
  932. X#include "bt.h"
  933. X#include "btpack.h"
  934. X
  935. Xvoid
  936. Xpackint(offset, contents)
  937. X    int             offset;
  938. X    int             contents;
  939. X{
  940. X    outputline[offset] = (contents % 32) + 32;
  941. X    contents /= 32;
  942. X    outputline[offset + 1] = (contents % 32) + 32;
  943. X    contents /= 32;
  944. X    outputline[offset + 2] = (contents % 32) + 32;
  945. X}
  946. X
  947. Xvoid
  948. Xstriplocation(at, specific, offset)
  949. X    location       *at;
  950. X    char           *specific;
  951. X    int            *offset;
  952. X{
  953. X    at->x = specific[*offset] - 64;
  954. X    at->y = specific[*offset + 1] - 64;
  955. X    *offset += 2;
  956. X}
  957. X
  958. Xvoid
  959. Xstripint(number, specific, offset)
  960. X    int            *number;
  961. X    char           *specific;
  962. X    int            *offset;
  963. X{
  964. X    *number = specific[*offset] - 32 + (specific[*offset + 1] - 32) * 32 +
  965. X        (specific[*offset + 2] - 32) * 1024;
  966. X    *offset += 3;
  967. X}
  968. END_OF_FILE
  969. if test 875 -ne `wc -c <'btpack.c'`; then
  970.     echo shar: \"'btpack.c'\" unpacked with wrong size!
  971. fi
  972. # end of 'btpack.c'
  973. fi
  974. if test -f 'btpack.h' -a "${1}" != "-c" ; then 
  975.   echo shar: Will not clobber existing file \"'btpack.h'\"
  976. else
  977. echo shar: Extracting \"'btpack.h'\" \(367 characters\)
  978. sed "s/^X//" >'btpack.h' <<'END_OF_FILE'
  979. X/*
  980. X * pack.h: function declarations for packing data for socket transmission
  981. X * under Broken Throne. (C) 1990 Tom Boutell.
  982. X */
  983. X
  984. Xextern char     outputline[];
  985. X
  986. Xvoid            packint();    /* int offset,int contents */
  987. Xvoid            striplocation();/* location* at,char* specific,int* offset */
  988. Xvoid            stripint();    /* int* number,char* specific,int* offset */
  989. END_OF_FILE
  990. if test 367 -ne `wc -c <'btpack.h'`; then
  991.     echo shar: \"'btpack.h'\" unpacked with wrong size!
  992. fi
  993. # end of 'btpack.h'
  994. fi
  995. if test -f 'map.txt' -a "${1}" != "-c" ; then 
  996.   echo shar: Will not clobber existing file \"'map.txt'\"
  997. else
  998. echo shar: Extracting \"'map.txt'\" \(279 characters\)
  999. sed "s/^X//" >'map.txt' <<'END_OF_FILE'
  1000. X16x16
  1001. XMMMMFMMFMFMMMMTT
  1002. XMMFF....TMMMFFMM
  1003. XMMMMMMMM.6..MTMM
  1004. XMMMM..T..MMMMMMM
  1005. XMMFFFM..T..TMMMM
  1006. XMMMMMMMTMMMMMMTM
  1007. XMMM..1....5...MM
  1008. XMMMMMMTMMMMMMMMM
  1009. XMMMMMM...MTMMMMM
  1010. XMMMTMMMMT4MMM3TM
  1011. XMM.....MMMMMMMMM
  1012. XMMMMMMTMTMTMMFFM
  1013. XMT..T..MMMMMMMMM
  1014. XMMMMMMMMFFFMTMMM
  1015. XMMMTMMMMTMM.2.MM
  1016. XMMMMMMMMMMMMMMMM
  1017. X
  1018. END_OF_FILE
  1019. if test 279 -ne `wc -c <'map.txt'`; then
  1020.     echo shar: \"'map.txt'\" unpacked with wrong size!
  1021. fi
  1022. # end of 'map.txt'
  1023. fi
  1024. if test -f 'msleep.c' -a "${1}" != "-c" ; then 
  1025.   echo shar: Will not clobber existing file \"'msleep.c'\"
  1026. else
  1027. echo shar: Extracting \"'msleep.c'\" \(292 characters\)
  1028. sed "s/^X//" >'msleep.c' <<'END_OF_FILE'
  1029. X
  1030. X#include <sys/types.h>
  1031. X#include <sys/time.h>
  1032. X#ifdef _AIX
  1033. X#include <sys/select.h>
  1034. X#endif
  1035. X#ifndef NULL
  1036. X#define NULL 0
  1037. X#endif                /* NULL */
  1038. X
  1039. Xvoid
  1040. Xmsleep(n)
  1041. X    long            n;
  1042. X{
  1043. X    struct timeval  sleept;
  1044. X    sleept.tv_sec = 0;
  1045. X    sleept.tv_usec = n;
  1046. X    select(FD_SETSIZE, NULL, NULL, NULL, &sleept);
  1047. X}
  1048. END_OF_FILE
  1049. if test 292 -ne `wc -c <'msleep.c'`; then
  1050.     echo shar: \"'msleep.c'\" unpacked with wrong size!
  1051. fi
  1052. # end of 'msleep.c'
  1053. fi
  1054. if test -f 'msleep.h' -a "${1}" != "-c" ; then 
  1055.   echo shar: Will not clobber existing file \"'msleep.h'\"
  1056. else
  1057. echo shar: Extracting \"'msleep.h'\" \(238 characters\)
  1058. sed "s/^X//" >'msleep.h' <<'END_OF_FILE'
  1059. X/*
  1060. X * msleep: A portable routine to sleep for n microseconds. By Tom Boutell
  1061. X * 2/2/91, from various suggestions from netfolk. (One fellow sent me such a
  1062. X * routine earlier, which I have lost.)
  1063. X */
  1064. X
  1065. Xvoid            msleep( /* int n */ );
  1066. END_OF_FILE
  1067. if test 238 -ne `wc -c <'msleep.h'`; then
  1068.     echo shar: \"'msleep.h'\" unpacked with wrong size!
  1069. fi
  1070. # end of 'msleep.h'
  1071. fi
  1072. if test -f 'readme' -a "${1}" != "-c" ; then 
  1073.   echo shar: Will not clobber existing file \"'readme'\"
  1074. else
  1075. echo shar: Extracting \"'readme'\" \(12171 characters\)
  1076. sed "s/^X//" >'readme' <<'END_OF_FILE'
  1077. XTHE BROKEN THRONE, version 2.03
  1078. X
  1079. XBy Tom Boutell, 11/20/90- 10/20/92. As of version 2.01, the game is
  1080. XCopyright 1992, Thomas Boutell. You may do what you wish with it
  1081. Xprovided you do not charge money for the game in any way. All commercial
  1082. Xuse of Broken Throne must be done by agreement with the author (myself).
  1083. X
  1084. XPlease clear changed versions with me first.
  1085. XI'd like to act as a switchboard for new versions of the game.
  1086. X
  1087. XTO INSTALL THE GAME
  1088. X
  1089. XFirst, read the Makefile to see if there are any notes specific to your
  1090. Xsystem (AIX, for instance, requires a small change be made).
  1091. XType "make btserver" to make the server, then type "make btclient" to make
  1092. Xthe client. Third, enter "make btrobot" to make the robot player. Alternatively
  1093. Xyou can simply type "make" particularly if you have built the game before
  1094. Xand know it's fairly compatible with your machine and errors will be few.
  1095. X
  1096. XIF IT WORKS
  1097. X
  1098. XPat yourself on the back and read "bt.doc" next to learn how to start
  1099. Xup and play the game!
  1100. X
  1101. XIF IT DOESN'T WORK (PARTIALLY OR COMPLETELY)
  1102. X
  1103. XThe Server:
  1104. X  If you get errors concering the file "bt.h,"
  1105. X  or the variable "details" in btinterface.c, then what you need to do
  1106. X  is go into bt.h and uncomment a line. There are further instructions
  1107. X  in bt.h explaining how to do this.
  1108. X  If anything else goes wrong, please mail me the details
  1109. X  (boutell@cshl.org). It's worth noting that I wrote
  1110. X  a hopefully portable routine, msleep(), to sleep for n microseconds
  1111. X  by way of select; if you have trouble with it, but your machine has
  1112. X    the routine usleep(), use it instead. (Plain sleep(), unfortunately,
  1113. X    only works in 1 - second increments, much too long.)
  1114. X
  1115. XThe Client:
  1116. X  "make btclient" can be more problematic, since I have to use Curses, and
  1117. X  curses has portability problems here and there. But keyboard I/O is now
  1118. X  handled in a way that's just as portable as the socket stuff, so if the
  1119. X  server compiles, that shouldn't be a problem either.
  1120. X
  1121. X  "But what's wrong with the backspace key?" If you have problems with the
  1122. X  backspace or escape keys, look in btclient.h for the definitions (right
  1123. X  at the beginning) of these keys. I assumed the regular ASCII definitions,
  1124. X  and I'm accepting delete as interchangeable with backspace, so this
  1125. X  should cover most folks. If you need to alter these, go ahead; at your
  1126. X  own risk of course!
  1127. X
  1128. X  If the system complains about "cbreak" and "nocbreak," then insert
  1129. X  the line #define BSD_CURSES at the start of btclient.c and recompile.
  1130. X
  1131. XThe Robot:   
  1132. X  "make btrobot" should have no problems, especially if you have no problem
  1133. X  making the client, since it's a hacked client without the ugly user
  1134. X  interface stuff that's so difficult to port.
  1135. X
  1136. XAll Three:
  1137. X
  1138. X  One easy fix you may have to make: if your compiler complains that errno
  1139. X  is undefined, insert "int errno;" at main level in btclient.c. This really
  1140. X  shouldn't be necessary, but sometimes it is.
  1141. X
  1142. XIf You Change Things:
  1143. X
  1144. X  If you *do* make a fix, please mail it to me so others can have it.
  1145. X  Please set it up with an #ifdef specific to your machine, unless of course
  1146. X  it's a general bug. 
  1147. X
  1148. XHOW TO PLAY:
  1149. X
  1150. XRead bt.doc, which is a manual on how to play the game.
  1151. X
  1152. XCONTACT SERVICE
  1153. X
  1154. XContact me at boutell@cshl.org if you'd like to contact with me with
  1155. Xbug reports and/or suggestions.
  1156. X
  1157. XACKNOWLEDGEMENTS
  1158. X
  1159. XI'd like to thank the net for many, many, *many* useful suggestions and
  1160. Xcorrections. It's due to all of you that I now have such a solid package.
  1161. XA version 2.0 note: I owe an apology to Rudolf Fleischer (sp?), whose
  1162. Xmany fascinating patches for volcanoes and the like were lost over
  1163. Xthe year or two in which I didn't work with the game. Rudolf, if you're
  1164. Xstill out there, feel free to make those patches to version 2.0, and
  1165. XI'll be glad to include them in version 2.1, especially since we
  1166. Xnow have a good mechanism for controlling options.
  1167. X
  1168. XCHANGES IN VERSION 2.03
  1169. X
  1170. X- "-1 troops recruited" fixed more robustly. Also the massive starvation
  1171. Xbug should be fixed.
  1172. X
  1173. XCHANGES IN VERSION 2.02
  1174. X
  1175. X- Failure to refresh info window fixed. (Oops.) Bug introduced by
  1176. Xhelp window fix. Should've tested more thoroughly before releasing this one.
  1177. X
  1178. X- "-1 troops recruited" fixed.
  1179. X
  1180. XCHANGES IN VERSION 2.01
  1181. X
  1182. X- xbt file, inadvertently left out of 2.0, put back in.
  1183. X
  1184. X- Wait queue bug, which caused continuous servers to seem to have huge
  1185. Xqueues despite the fact that no one was playing after being up for
  1186. Xa while, has (hopefully) been fixed. 
  1187. X
  1188. X- I've attempted to fix a bug in the support code that would cause
  1189. Xmassive starvation of all troops in the heartland!
  1190. X
  1191. X- The client now redraws the screen properly after looking at the
  1192. Xhelp window.
  1193. X
  1194. XThe version 2.0 client is still compatible with the new server, but the
  1195. Xhelp window fix is enough to justify getting the new one, I think.
  1196. X
  1197. XCHANGES IN VERSION 2.0
  1198. X
  1199. X- SUPPORT RULES. This prevents the "piles of 99 shuffling around" problem
  1200. X    of older versions of the game, and adds a new strategic dimension.
  1201. X    Some will dislike it at first but it greatly increases the strategic
  1202. X    interest of the game.
  1203. X
  1204. X- AUTOMATIC RECRUITMENT. This one has been asked for so many times the
  1205. X    exact count is lost to memory.
  1206. X
  1207. X- CONTINUOUS SERVER MODE. This permits the establishment of permanently-
  1208. X    open BT servers. (Well, permanent at least until a segmentation
  1209. X    fault, that is. (: ) This includes a wait-queue facility.
  1210. X
  1211. X- Variable map size at the server, with clients automatically notified
  1212. X    of the map size; clients know if they can't handle a map size and
  1213. X    shut themselves down with a message to that effect.
  1214. X
  1215. X- Only territory a player specifically owns now benefits recruitment.
  1216. X
  1217. X- A .btserverrc file to control server options.
  1218. X
  1219. X- Standard option syntax for the command line of each program.
  1220. X
  1221. X- Lots of bug fixes. I even brought the server up under codecenter
  1222. X    and beat out bugs and thinkos and misfeatures with it. The code
  1223. X    still betrays the fact that it was written in an earlier style
  1224. X    I no longer consider elegant, but it's getting downright tolerable.
  1225. X
  1226. XCHANGES IN VERSION 1.12
  1227. X
  1228. X- You can now design your own maps on which to play! This should make games
  1229. X  between more than two players substantially more fair than they have
  1230. X  been. See the main documentation file.
  1231. X
  1232. X- Armies are now represented by three units each in battle rather than
  1233. X  five, since the primary problem with battle odds was somewhere else
  1234. X  entirely (see below!).
  1235. X
  1236. X- Another subtle bug: a received text message during the entry of a user's
  1237. X  command to move troops or tell a message used to ruin the user's input.
  1238. X  This has been fixed.
  1239. X
  1240. X- The redraw key should *finally* work, as long as curscr behaves as it
  1241. X  should on your screen. Redraw is capital M ("messy").
  1242. X
  1243. X- The addition of a recruitment warning: the client displays an "R" in the
  1244. X  lower right corner for a few seconds each time the necessary period
  1245. X  between safe recruitments goes by. The player need not pay attention to this,
  1246. X  but it is one way of keeping up.
  1247. X
  1248. X- The client is now guaranteed to correctly display up to 9999 action
  1249. X  points per player, without the previous occasional erasing.
  1250. X
  1251. X- A major bug nobody ever reported: The terrain modifiers for combat have
  1252. X  been *backwards* since day one! No kidding! I reversed this. All of a
  1253. X  sudden it's no longer absurdly easy to take over citadels.
  1254. X
  1255. X- Some users have reported that btclient doesn't accept their backspace key.
  1256. X  I've taken my best shot at repairing this, and if you still can't seem
  1257. X  to backspace, see the notes above regarding this in the section entitled
  1258. X  "The Client:".
  1259. X
  1260. X- A fail- safe escape key has been added; it gets you out of whatever you
  1261. X  were doing. I added this to make the default for the move command acceptable
  1262. X  to folks used to cancelling it by just pressing RETURN. (Entering 0 will
  1263. X  work too of course.)
  1264. X
  1265. X- The infamous void* details; problem has been resolved. In bt.h, the main
  1266. X  makefile, you can now uncomment a line to force the program to use
  1267. X  char* as a generic pointer type instead. This should satisfy the
  1268. X  longings of older compilers.
  1269. X
  1270. X- The move command now defaults to *all* armies in the sector you are
  1271. X  moving from. Of course it is possible that these armies may get sacked
  1272. X  as you are in the process of giving the order, in which case it won't
  1273. X  go through, but the client will try to move the most current number of
  1274. X  armies. (This was just as possible before when typing in the number of
  1275. X  armies explicitly and losing a few in the process.)
  1276. X
  1277. X- More compatibility fixes. Cleaned up use of "=-" and "=*"; added
  1278. X  #ifdefs for BSD curses (see "if it doesn't work"). Please send your patches!
  1279. X
  1280. XCHANGES IN VERSION 1.11
  1281. X
  1282. X- Replaced a forgotten call to usleep() in btclient with a call to my
  1283. X  msleep() function.
  1284. X
  1285. XCHANGES IN VERSION 1.10
  1286. X
  1287. X- Many folks have reported arguments between their compiler and my
  1288. X  use of a void pointer named "details" in interface.c. I've unrolled
  1289. X  this code a little in hopes of placating unfriendly compilers. If you've
  1290. X  had this problem and been able to solve it, please let me know! Folks
  1291. X  would like the solution.
  1292. X- The server now uses a little routine named msleep() to sleep for n
  1293. X  microseconds, instead of usleep() (a wonderful but nonportable SunOS
  1294. X  routine). I should thank the net for many suggestions and code examples
  1295. X  leading to this.
  1296. X- A viable robot player is now included! See the bt.doc file for details
  1297. X  on its use. 
  1298. X- The usleep() call has been eliminated. The client program now simply
  1299. X  selects until either a keyboard event or server message arrives. Very
  1300. X  polite; no nasty demand on the processor. Also much more portable.
  1301. X- The M command (redraw map) now works properly.
  1302. X- Problems due to which the game could crash after folks disconnected
  1303. X  have been resolved. This is a major improvement; I haven't been able
  1304. X  to get the server to crash since.
  1305. X- There are no more strange delays in which another keypress is needed
  1306. X  to make the last one "go through." The same change that eliminated the
  1307. X  call to usleep() fixed this.
  1308. X- The quit command now has a confirmation that accepts only 'y' or 'Y'
  1309. X  to prevent accidental disconnection.
  1310. X- The code is somewhat cleaned up, though the haste with which I wrote the
  1311. X  game still shows!
  1312. X- THE INFAMOUS ACTION POINT BUG IS DEAD! Hurrah! With some help from folks
  1313. X  on rec.games.programmer, I discovered that when the client was through
  1314. X  handling a "move" message from the server, it would "fall through" and
  1315. X  process an "action" message, producing an incorrect AP count. AP counts
  1316. X  should now be displayed correctly at all times, and movement costs
  1317. X  will no longer appear random. (They never were, but after movement, the
  1318. X  correct number of APs was broadcast, understandably confusing the player
  1319. X  pretty badly.)
  1320. X- *** A change affecting the rules: army units now fight as sets of
  1321. X  five units. This is invisible to the player, but results in a more
  1322. X  even distribution of losses, so it's much less common to take out four
  1323. X  armies with one by luck, although still possible.
  1324. X
  1325. XCHANGES IN VERSION 1.01
  1326. X
  1327. X- Input is now handled in a way that should be generic BSD.
  1328. X- The 'h' key no longer summons help; this is now done with the ? key,
  1329. X  shifted or not ('/').
  1330. X- Certain strange compiler errors in interface.c are resolved. (Some
  1331. X  compilers were treating =* as meaning something other than "equal to
  1332. X  the dereferenced value of." One even treated =-1 as meaning something
  1333. X  other than equal to -1!) Parentheses in judicious places solved these.
  1334. X- You can now move the cursor while "thinking" about what command to enter.
  1335. X  The only time you can't move the cursor is while entering a text
  1336. X  message or typing a number of troops.
  1337. X- It is now easier to tell whether you are in command mode or entering
  1338. X  a location.
  1339. X- You can now specify a different port number. This is given as a second
  1340. X  argument to btserver, and also to btclient. This permits multiple games
  1341. X  on one machine.
  1342. X- 'M' (capitalized) now redraws a Messy screen after a talk message, etc.
  1343. X- There is now an opening message while the map is being transmitted.
  1344. X- The number of players must be inputted on the command line. An old
  1345. X  undocumented feature of the server was the ability to prompt for this,
  1346. X  removed to make the new port number question unambiguous.
  1347. END_OF_FILE
  1348. if test 12171 -ne `wc -c <'readme'`; then
  1349.     echo shar: \"'readme'\" unpacked with wrong size!
  1350. fi
  1351. # end of 'readme'
  1352. fi
  1353. if test -f 'xbt' -a "${1}" != "-c" ; then 
  1354.   echo shar: Will not clobber existing file \"'xbt'\"
  1355. else
  1356. echo shar: Extracting \"'xbt'\" \(83 characters\)
  1357. sed "s/^X//" >'xbt' <<'END_OF_FILE'
  1358. X#!/bin/sh 
  1359. X
  1360. Xexec `xterm -fn "-*-fixed-*-*-*-*-*-200-*-*-*-*-*-*" -e btclient $*` &
  1361. END_OF_FILE
  1362. if test 83 -ne `wc -c <'xbt'`; then
  1363.     echo shar: \"'xbt'\" unpacked with wrong size!
  1364. fi
  1365. chmod +x 'xbt'
  1366. # end of 'xbt'
  1367. fi
  1368. echo shar: End of archive 3 \(of 3\).
  1369. cp /dev/null ark3isdone
  1370. MISSING=""
  1371. for I in 1 2 3 ; do
  1372.     if test ! -f ark${I}isdone ; then
  1373.     MISSING="${MISSING} ${I}"
  1374.     fi
  1375. done
  1376. if test "${MISSING}" = "" ; then
  1377.     echo You have unpacked all 3 archives.
  1378.     rm -f ark[1-9]isdone
  1379. else
  1380.     echo You still need to unpack the following archives:
  1381.     echo "        " ${MISSING}
  1382. fi
  1383. ##  End of shell archive.
  1384. exit 0
  1385.