[comp.sources.games] v11i077: bt - Broken Throne, multiplayer realtime conquest game, Patch1

billr@daemon.CNA.TEK.COM (Bill Randle) (12/01/90)

Submitted-by: Tom Boutell <boutell@freezer.it.udel.edu>
Posting-number: Volume 11, Issue 77
Archive-name: bt/Patch1
Patch-To: bt: Volume 11, Issue 75-76
Environment: INET sockets, curses

	[This patch brings bt to version 1.01. Unpack this file
	 and feed to patch(1), or feed directly to patch in your
	 bt source directory.  -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 shell archive."
# Contents:  patches01
# Wrapped by billr@saab on Fri Nov 30 17:18:08 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'patches01' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'patches01'\"
else
echo shar: Extracting \"'patches01'\" \(32580 characters\)
sed "s/^X//" >'patches01' <<'END_OF_FILE'
X*** ../../bt/Makefile	Mon Nov 12 13:10:55 1990
X--- Makefile	Sat Nov 24 15:38:43 1990
X***************
X*** 4,9 ****
X--- 4,14 ----
X  btserver: bt.o pack.o interface.o
X  	cc bt.o pack.o interface.o -o btserver
X  
X+ btrobot: robot.o pack.o
X+ 	cc robot.o pack.o -o btrobot
X+ 
X+ robot.o: robot.c
X+ 	cc -c -g robot.c
X  client.o: client.c
X  	cc -c -g client.c
X  pack.o: pack.c
X*** ../../bt/README	Tue Nov 20 12:48:35 1990
X--- README	Sat Nov 24 11:05:38 1990
X***************
X*** 19,30 ****
X  If "make btserver" fails, I will be very, very surprised. Please mail me
X  the details (boutell@freezer.it.udel.edu).
X  
X  If "make btclient" fails, I won't be so surprised. This is because the game
X  plays games with stdin to find out if there are characters waiting or not.
X! This shouldn't vary from one Unix to another but it probably will anyway.
X  If you can fix it for your machine, great; mail me what you did so I can
X  create a compile- time option for that machine. One possible replacement
X  approach for System V folks is to use the nodelay() routine of Curses.
X  (This routine is missing in SunOS curses. Ahrgh.) Of course, if the code
X  runs as- is, you're golden!
X  
X--- 19,67 ----
X  If "make btserver" fails, I will be very, very surprised. Please mail me
X  the details (boutell@freezer.it.udel.edu).
X  
X+ One exception: your libraries may not support the usleep call. In that
X+ case, replace it with a call to sleep(1), or remove it altogether. The
X+ prior method is greatly preferred. Even better would be to sleep for
X+ 1/10th of a second in a way that is appropriate for your system. Please
X+ do NOT simply insert a counting loop since the only purpose of this line
X+ is to give time back to the system.
X+ 
X  If "make btclient" fails, I won't be so surprised. This is because the game
X  plays games with stdin to find out if there are characters waiting or not.
X! If you are running a BSD unix, you should not have problems under this
X! release. If you are running under System V, you almost certainly will.
X  If you can fix it for your machine, great; mail me what you did so I can
X  create a compile- time option for that machine. One possible replacement
X  approach for System V folks is to use the nodelay() routine of Curses.
X  (This routine is missing in SunOS curses. Ahrgh.) Of course, if the code
X  runs as- is, you're golden!
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 client.c. This really
X+ shouldn't be necessary, but sometimes it is.
X+ 
X+ CHANGES 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.
X+ 
X+ 
X  
X*** ../../bt/bt.c	Fri Nov 16 12:34:12 1990
X--- bt.c	Sat Nov 24 15:44:15 1990
X***************
X*** 24,29 ****
X--- 24,30 ----
X    int number;
X    int x,y;
X    int flag;
X+   int portnumber;
X    long lasttime;
X    long newtime;
X    char specificspace[256];
X***************
X*** 30,40 ****
X    char *specific;
X    int offset;
X    printf("Broken Throne server program launching...\n");
X!   if (argc>1) 
X      totalplayers=atoi(argv[1]);
X    else {
X!     printf("Number of players? ");
X!     scanf("%d",&totalplayers); 
X    }
X    if (totalplayers<1 || totalplayers>_MAXPLAYERS) {
X       printf("Number of players should be between 1 and %d.\n",_MAXPLAYERS);
X--- 31,50 ----
X    char *specific;
X    int offset;
X    printf("Broken Throne server program launching...\n");
X!   portnumber=2727;
X!   if (argc>1) {
X      totalplayers=atoi(argv[1]);
X+     if (argc>2) {
X+       portnumber=atoi(argv[2]);
X+       if (portnumber<1000 || portnumber>9999) {
X+         printf("Port number must be between 1000 and 9999.\n");
X+         exit(1);
X+       }
X+     }
X+   }
X    else {
X!     printf("Usage: btserver #ofplayers <port# (optional)>\n");
X!     exit(1);
X    }
X    if (totalplayers<1 || totalplayers>_MAXPLAYERS) {
X       printf("Number of players should be between 1 and %d.\n",_MAXPLAYERS);
X***************
X*** 45,51 ****
X    specific=specificspace;
X    time(&lasttime);
X    srand(lasttime % 1024); /* Get a new random # seed */
X!   setupinterface();
X    signal(SIGTERM,endprogram);
X    broadcast(_STARTUP,(void*)NULL);
X    setupmap();
X--- 55,61 ----
X    specific=specificspace;
X    time(&lasttime);
X    srand(lasttime % 1024); /* Get a new random # seed */
X!   setupinterface(portnumber);
X    signal(SIGTERM,endprogram);
X    broadcast(_STARTUP,(void*)NULL);
X    setupmap();
X***************
X*** 415,422 ****
X    map[at.x][at.y].lastuse=currenttime;
X    population=0;
X    if (chance>((rand() / 100) % 20)) {
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][at.y].terrain!=2) && (map[at.x][at.y].terrain!=5)) ||
X                ((x==0) && (y==0))) && ((map[at.x][at.y].owner==currentplayer) ||
X--- 425,432 ----
X    map[at.x][at.y].lastuse=currenttime;
X    population=0;
X    if (chance>((rand() / 100) % 20)) {
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][at.y].terrain!=2) && (map[at.x][at.y].terrain!=5)) ||
X                ((x==0) && (y==0))) && ((map[at.x][at.y].owner==currentplayer) ||
X***************
X*** 447,457 ****
X  }
X  
X  void setupmap() {
X! /* Not yet safe; will keep trying by means of rand to position a
X!    player indefinitely if it runs out of space or hits a numeric
X!    ugly. Can be remedied by sweeping the map starting from one
X!    random point. Map generator is not optimized well. */
X! 
X    int altitude[_MAPX][_MAPY];
X    int newaltitude[_MAPX][_MAPY];
X    int x,y,subx,suby;
X--- 457,464 ----
X  }
X  
X  void setupmap() {
X! /* Relatively safe, but if there isn't room for the number of players
X!    the game may lock up. */
X    int altitude[_MAPX][_MAPY];
X    int newaltitude[_MAPX][_MAPY];
X    int x,y,subx,suby;
X***************
X*** 463,468 ****
X--- 470,477 ----
X    location newhex;
X    int placement;
X    full=0;
X+   sprintf(playertext,"Generating the map...");
X+   broadcast(_TEXT,(void*)playertext);
X    for (y=0; (y<_MAPY); y++) {
X      for (x=0; (x<_MAPX); x++) {
X        altitude[x][y]=0;
X***************
X*** 522,529 ****
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--- 531,538 ----
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*** ../../bt/bt.doc	Tue Nov 20 12:44:45 1990
X--- bt.doc	Sat Nov 24 11:12:30 1990
X***************
X*** 82,93 ****
X  order to keep his screen from being "munged" as the server announces
X  players.
X  
X  Once the client is launched, a blank map will be displayed. Within a moment
X  or two it should be replaced by the full map; be patient if there are
X  several players.
X  
X  When the game first begins, the player is told which lowercase letter
X! belongs to them. Initially the player controls one city and no troops.
X  In order to acquire troops, the r (recruit) command should be used
X  immediately. A cursor will appear at the city's location. This cursor
X  can be moved with the standard vi/ moria/ hack movement keys:
X--- 82,103 ----
X  order to keep his screen from being "munged" as the server announces
X  players.
X  
X+ OTHER PORT NUMBERS
X+ 
X+ If you do not want to use the default port (2727), or if there is another
X+ BT game in progress on the same machine, you will need to specify a port
X+ number. Port numbers should be between 1000 and 9999, the same on both
X+ client and server. Enter the port number after the number of players
X+ or machine address, and before the & in the case of the server.
X+ 
X+ ONCE THE GAME STARTS:
X+ 
X  Once the client is launched, a blank map will be displayed. Within a moment
X  or two it should be replaced by the full map; be patient if there are
X  several players.
X  
X  When the game first begins, the player is told which lowercase letter
X! represents them. Initially the player controls one city and no troops.
X  In order to acquire troops, the r (recruit) command should be used
X  immediately. A cursor will appear at the city's location. This cursor
X  can be moved with the standard vi/ moria/ hack movement keys:
X***************
X*** 112,120 ****
X  Once a new town is reached, the player can use the r command here to recruit
X  more troops.
X  
X! Recruitment can only take place every twenty ticks in any given town or
X! city. The exact length of time is found in the file bt.h, in terms of seconds.
X! Also found in bt.h is the constant _SPEED, which determines how often a "tick"
X  takes place, awarding action points and bringing the next recruitment closer.
X  The player can attempt to recruit early, but runs the risk of failure, and
X  will be forced to wait the full time again if recruitment does not succeed.
X--- 122,129 ----
X  Once a new town is reached, the player can use the r command here to recruit
X  more troops.
X  
X! Recruitment can only take place every twenty ticks in any given town or city.
X! Found in bt.h is the constant _SPEED, which determines how often a "tick"
X  takes place, awarding action points and bringing the next recruitment closer.
X  The player can attempt to recruit early, but runs the risk of failure, and
X  will be forced to wait the full time again if recruitment does not succeed.
X***************
X*** 127,132 ****
X--- 136,152 ----
X  army moved. When each tick takes place, the player will receive 2 action
X  points, plus 1 action point for each city under the player's control.
X  
X+ Action points are displayed for each player at the bottom of the screen:
X+ 
X+ A: 6,13
X+ 
X+ This denotes that player A has six hexes (territories) and thirteen
X+ action points.
X+ 
X+ The cursor can be moved freely while considering what command to enter
X+ next. The only time you cannot move the cursor is during the entry of a
X+ number of troops, or a text message to another player.
X+ 
X  COMBAT
X  
X  Combat in the Broken Throne is simple; the player simply moves troops into
X***************
X*** 197,202 ****
X--- 217,224 ----
X    for the locations from which and to which troops are to be moved, then
X    for the number of troops.
X  r (location): recruit troops. See notes above on the rules of recruitment.
X+ M (capitalized): redraw a Messy screen. This is useful after a talk
X+   request messes up your display.
X  
X  WINNING& LOSING
X  
X***************
X*** 233,241 ****
X  
X  SUNVIEW
X  
X! Broken Throne does not run properly under Sunview. This is because curses
X! support for Sunview seems to be broken. If someone is willing to investigate
X! the cause I'll be glad to accommodate a fix.
X  
X  ... Enjoy! Someday I'll make this into a proper man page.
X   
X--- 255,263 ----
X  
X  SUNVIEW
X  
X! Performance under Sunview is a mixed thing, apparently. On our somewhat
X! older Sunview, there are problems with Curses that prevent it from running
X! properly, but under Sunview 3.0 I'm told it works fine.
X  
X  ... Enjoy! Someday I'll make this into a proper man page.
X   
X*** ../../bt/client.c	Fri Nov 16 12:39:46 1990
X--- client.c	Sat Nov 24 10:50:03 1990
X***************
X*** 7,17 ****
X  #include <signal.h>
X  #include <sys/time.h>
X  #include <fcntl.h>
X- #include <stropts.h>
X  #include <errno.h>
X- 
X  #include "types.h"
X  #include "pack.h"
X  #define _MAPX 16
X  #define _MAPY 16
X  
X--- 7,16 ----
X  #include <signal.h>
X  #include <sys/time.h>
X  #include <fcntl.h>
X  #include <errno.h>
X  #include "types.h"
X  #include "pack.h"
X+ #include <ctype.h>
X  #define _MAPX 16
X  #define _MAPY 16
X  
X***************
X*** 52,58 ****
X  int port;
X  int playerFd;
X  int promptoffset;
X! fd_set active;
X  int inputstate;
X  char* host;
X  int connectstream();
X--- 51,58 ----
X  int port;
X  int playerFd;
X  int promptoffset;
X! fd_set server;
X! fd_set term;
X  int inputstate;
X  char* host;
X  int connectstream();
X***************
X*** 87,93 ****
X   char* argv[];
X   {
X   WINDOW* help;
X-  struct strpeek checkio;
X   int inputchar;
X   int inputpos;
X   char inputline[200];
X--- 87,92 ----
X***************
X*** 120,125 ****
X--- 119,125 ----
X   cbreak();
X   noecho();
X   inputstate=_CURSORCOMMAND;
X+  promptplayer("Command:");
X   xsize=COLS/(_MAPX+1);
X   promptoffset=0;
X   if (xsize<4) {
X***************
X*** 133,140 ****
X   signal(SIGTERM,endprogram);
X   signal(SIGCONT,restorescreen);
X   inputfd=fileno(stdin);
X!  /* ioctl(fileno(stdin),I_SETSIG,S_INPUT);
X!  signal(SIGPOLL,inputfork); */
X   fflush(stdin);
X   done=0;
X   inputpos=0;
X--- 133,139 ----
X   signal(SIGTERM,endprogram);
X   signal(SIGCONT,restorescreen);
X   inputfd=fileno(stdin);
X!  FD_SET(inputfd,&term);
X   fflush(stdin);
X   done=0;
X   inputpos=0;
X***************
X*** 145,150 ****
X--- 144,151 ----
X   playernumber=specific[0]-64;
X   sprintf(inputline,"We are player %c.\n",playernumber+64);
X   tellplayer(inputline);
X+  sprintf(inputline,"? summons help.\n");
X+  tellplayer(inputline);
X   while (!getmessage(&messagetype,specific));
X   totalplayers=specific[0]-64;
X   for (count=1; (count<=totalplayers); count++) 
X***************
X*** 224,230 ****
X       }
X     }
X    if (done!=0) {
X!    if (ioctl(inputfd,I_PEEK,&checkio)) {
X       inputchar=getch();
X       if (inputchar=='q')
X         done=2;
X--- 225,231 ----
X       }
X     }
X    if (done!=0) {
X!    if (inputwaiting(&term,inputfd)) {
X       inputchar=getch();
X       if (inputchar=='q')
X         done=2;
X***************
X*** 231,238 ****
X     }
X    }
X    else {
X!    checkio.flags=0;
X!    while (ioctl(inputfd,I_PEEK,&checkio)) {
X      inputchar=getch();
X      switch (inputstate) {
X      case _CURSORM1:
X--- 232,238 ----
X     }
X    }
X    else {
X!    while (inputwaiting(&term,inputfd)) {
X      inputchar=getch();
X      switch (inputstate) {
X      case _CURSORM1:
X***************
X*** 240,245 ****
X--- 240,246 ----
X      case _CURSORRECRUIT:
X      case _CURSORCONSTRUCT:
X      case _CURSORDESTROY:
X+     case _CURSORCOMMAND:
X       switch(inputchar) {
X        case 'h':
X        if (cursorx>0) {
X***************
X*** 305,321 ****
X         }
X         write(playerFd,outputline,strlen(outputline)+1);
X         inputstate=_CURSORCOMMAND;
X         break;
X        }
X        break;
X       }
X!     break;
X!     case _CURSORCOMMAND:
X       switch(inputchar) {
X-       case 'h':
X        case '/':
X        case '?':
X!       help=newwin(16,65,1,5);
X        werase(help);
X        box(help,'|','-');
X        wmove(help,0,0);
X--- 306,323 ----
X         }
X         write(playerFd,outputline,strlen(outputline)+1);
X         inputstate=_CURSORCOMMAND;
X+        promptplayer("Command:");
X         break;
X+        case _CURSORCOMMAND:
X+        tellplayer("Huh?\n");
X        }
X        break;
X       }
X!     if (inputstate==_CURSORCOMMAND) {
X       switch(inputchar) {
X        case '/':
X        case '?':
X!       help=newwin(17,65,1,5);
X        werase(help);
X        box(help,'|','-');
X        wmove(help,0,0);
X***************
X*** 332,338 ****
X        mvwprintw(help,11,1,"Select the location by pressing the space bar or RETURN.");
X        mvwprintw(help,12,1,"t: tell player (player letter): followed by message.");
X        mvwprintw(help,13,1,"Enter a '#' sign instead of a letter to tell all.");
X!       mvwprintw(help,14,1,"Press any key now to continue play.");
X        wrefresh(help);
X        inputchar=getch();
X        delwin(help);
X--- 334,341 ----
X        mvwprintw(help,11,1,"Select the location by pressing the space bar or RETURN.");
X        mvwprintw(help,12,1,"t: tell player (player letter): followed by message.");
X        mvwprintw(help,13,1,"Enter a '#' sign instead of a letter to tell all.");
X!       mvwprintw(help,14,1,"M: (capitalized): redraw Messy screen.");
X!       mvwprintw(help,15,1,"Press any key now to continue play.");
X        wrefresh(help);
X        inputchar=getch();
X        delwin(help);
X***************
X*** 339,344 ****
X--- 342,349 ----
X        touchwin(mapw);
X        wrefresh(mapw);
X        break; 
X+       case 'M':
X+       restorescreen();
X        case 'm':
X        promptplayer("Move: From? ");
X        inputstate=_CURSORM1;
X***************
X*** 370,375 ****
X--- 375,381 ----
X        promptplayer("Tell: whom and what? ");
X        inputstate=_CURSORTELL;
X       }
X+     }
X      break;
X      case _CURSORM3:
X      case _CURSORTELL:
X***************
X*** 414,419 ****
X--- 420,426 ----
X               tellplayer("Huh?\n"); 
X           }
X           inputstate=_CURSORCOMMAND;
X+          promptplayer("Command:");
X           break;
X           case _CURSORM3:
X           outputline[0]=_MOVE;
X***************
X*** 425,430 ****
X--- 432,438 ----
X           outputline[8]=NULL;
X           write(playerFd,outputline,strlen(outputline)+1);
X           inputstate=_CURSORCOMMAND;
X+          promptplayer("Command:");
X           break;
X          }  
X        default:
X***************
X*** 496,502 ****
X    int pos;
X    *messagetype=0;
X    *specific=0;
X!   if (!inputwaiting()) {
X      return 0;
X    }
X    read(playerFd,messagetype,1);
X--- 504,510 ----
X    int pos;
X    *messagetype=0;
X    *specific=0;
X!   if (!inputwaiting(&server,playerFd)) {
X      return 0;
X    }
X    read(playerFd,messagetype,1);
X***************
X*** 517,523 ****
X    current=specific;
X    done=0;
X    while (done==0) {
X!     while (!inputwaiting());
X      read(playerFd,current,1);
X      if (*current==0)
X        done=1;
X--- 525,531 ----
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***************
X*** 613,630 ****
X      perror("connect");
X      return(0);
X    }
X!   FD_SET(s,&active);
X    playerFd=s;
X    return(1);
X  }
X  
X! int inputwaiting() {
X    int errrec;
X    fd_set readfds;
X    struct timeval waitTime;
X    waitTime.tv_sec=SECONDSLIMIT;
X    waitTime.tv_usec=MICROSECONDSLIMIT;
X!   bcopy((char *) &active, (char *) &readfds,sizeof(active));
X    if (select(FD_SETSIZE,&readfds,NULL,NULL,&waitTime)<0) {
X      if (errno!=EINTR) { 
X      perror("select");
X--- 621,641 ----
X      perror("connect");
X      return(0);
X    }
X!   FD_SET(s,&server);
X    playerFd=s;
X    return(1);
X  }
X  
X! int inputwaiting(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*** 631,637 ****
X      }
X      return 0;
X    }
X!   if (FD_ISSET(playerFd,&readfds))
X      return 1;
X    else
X      return 0;
X--- 642,648 ----
X      }
X      return 0;
X    }
X!   if (FD_ISSET(sfd,&readfds))
X      return 1;
X    else
X      return 0;
X***************
X*** 650,658 ****
X    static char outputline[100];
X    move(18,theplayer*10-9);
X    if (players[theplayer].live==1) 
X!     addstr(sprintf(outputline,"%c:%d ,%d ",theplayer+64,
X                     players[theplayer].hexes,players[theplayer].action));
X!   else addstr(sprintf(outputline,"%c: Dead",theplayer+64));
X  }
X  
X  /* get_host_address: borrowed with appreciation from Tinytalk. Does a nice
X--- 661,669 ----
X    static char outputline[100];
X    move(18,theplayer*10-9);
X    if (players[theplayer].live==1) 
X!     addstr(sprintf(outputline,"%c:%d ,%d   ",theplayer+64,
X                     players[theplayer].hexes,players[theplayer].action));
X!   else addstr(sprintf(outputline,"%c: Dead  ",theplayer+64));
X  }
X  
X  /* get_host_address: borrowed with appreciation from Tinytalk. Does a nice
X*** ../../bt/interface.c	Thu Nov 15 00:51:02 1990
X--- interface.c	Sat Nov 24 10:54:25 1990
X***************
X*** 52,60 ****
X  char *curhostname = "";
X  int playerids[20];
X  char outputline[256];
X! void setupinterface() {
X    int current;
X!   init_socket(2727);
X    playertext=(outputline+1);
X    for (current=1; (current<=totalplayers); current++) {
X      playerids[current]=new_player(0);
X--- 52,62 ----
X  char *curhostname = "";
X  int playerids[20];
X  char outputline[256];
X! void setupinterface(portnumber)
X!   int portnumber;
X! {
X    int current;
X!   init_socket(portnumber);
X    playertext=(outputline+1);
X    for (current=1; (current<=totalplayers); current++) {
X      playerids[current]=new_player(0);
X***************
X*** 85,91 ****
X    switch (messagetype) {
X     
X      case _HEXSTATUS:
X!       where=*(location*)details;
X        outputline[1]=64+where.x;
X        outputline[2]=64+where.y;
X        outputline[3]=64+map[where.x][where.y].terrain;
X--- 87,93 ----
X    switch (messagetype) {
X     
X      case _HEXSTATUS:
X!       where=(*(location*)details);
X        outputline[1]=64+where.x;
X        outputline[2]=64+where.y;
X        outputline[3]=64+map[where.x][where.y].terrain;
X***************
X*** 96,102 ****
X        outputline[14]=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--- 98,104 ----
X        outputline[14]=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***************
X*** 108,114 ****
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--- 110,116 ----
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*** ../../bt/interface.h	Thu Nov  8 05:57:35 1990
X--- interface.h	Sat Nov 24 10:54:48 1990
X***************
X*** 1,4 ****
X! void setupinterface();
X  void shutdowninterface();
X  int getrequest();
X       /* int* player,char* requesttype,char* specific */
X--- 1,4 ----
X! void setupinterface(); /* int portnumber */
X  void shutdowninterface();
X  int getrequest();
X       /* int* player,char* requesttype,char* specific */
XNo differences encountered
XNo differences encountered
XNo differences encountered
X*** /dev/null	Fri Nov 30 17:15:02 1990
X--- changes	Sat Nov 24 11:05:56 1990
X***************
X*** 0 ****
X--- 1,2 ----
X+ See the readme file for a description of changes in version 1.01.
X+ 
X*** /dev/null	Fri Nov 30 17:15:02 1990
X--- robot.c	Sat Nov 24 15:40:32 1990
X***************
X*** 0 ****
X--- 1,348 ----
X+ /* Robot player for Broken Throne- 11/24/90 by Tom Boutell */
X+ 
X+ 
X+ #include <stdio.h>
X+ #include <curses.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 "types.h"
X+ #include "pack.h"
X+ #include <ctype.h>
X+ #define _MAPX 16
X+ #define _MAPY 16
X+ 
X+ #define _HEXSTATUS 65
X+ #define _PLAYERSTATUS 66
X+ #define _PLAYERDEAD 67
X+ #define _ACTION 68
X+ #define _TEXT 69
X+ #define _STARTUP 70
X+ #define _END 71
X+ #define _YOUARE 72
X+ #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+ #define SECONDSLIMIT 0L
X+ #define MICROSECONDSLIMIT 1L
X+ hex map[_MAPX][_MAPY];
X+ int lastrecruit[_MAPX][_MAPY];
X+ player players[20];
X+ int playernumber;
X+ player* me;
X+ int totalplayers;
X+ int currenttime;
X+ int living;
X+ int port;
X+ int playerFd;
X+ int promptoffset;
X+ fd_set server;
X+ int inputstate;
X+ char* host;
X+ int connectstream();
X+ int inputwaiting();
X+ void setupmap();
X+ void readnullterm();
X+ void endprogram();
X+ int inrange();
X+ void recruit();
X+ int getmessage();
X+ char specificspace[256];
X+ char outputline[256];
X+ char* specific;
X+ 
X+ main(argc,argv)
X+  int argc;
X+  char* argv[];
X+  {
X+  int done;
X+  char messagetype;
X+  location at;
X+  location from,to;
X+  int theplayer;
X+  int x,y,roll;
X+  int offset;
X+  int count;
X+  if (argc>1) {
X+    host=argv[1];
X+    if (argc>2) 
X+      port=atoi(argv[2]);
X+    else
X+      port=2727;
X+  }
X+  else {
X+    printf("Usage: btclient hostaddress portnumber\n");
X+    exit(1);
X+  }
X+ 
X+  if (connectstream()==0) {
X+    perror("Socket unopenable.\n");
X+    exit(1);
X+  }
X+  setupmap();
X+  done=0;
X+  currenttime=0;
X+  specific=specificspace;
X+  while (!getmessage(&messagetype,specific));
X+  playernumber=specific[0]-64;
X+  me=&players[playernumber];
X+  while (!getmessage(&messagetype,specific));
X+  totalplayers=specific[0]-64;
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<_MAPY); y++) {
X+            for (x=0; (x<_MAPX); 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+        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+   usleep(100000);
X+   /* Now it's time to think. */
X+   /* Sweep our towns and do useful things: */
X+   for (y=0; (y<_MAPY); y++) {
X+     for (x=0; (x<_MAPX); x++) {
X+       if (map[x][y].owner==playernumber) {
X+         if ((map[x][y].terrain==2) || (map[x][y].terrain==5)) {
X+           if ((currenttime-lastrecruit[x][y])>20) {
X+             recruit(x,y);
X+           }
X+         }
X+       }  
X+     }
X+   }         
X+  } 
X+  /* Terminating code - needs to be called on CTRLC also. */
X+  endprogram();
X+ }
X+ 
X+ void recruit(x,y)
X+ int x,y;
X+ {
X+   outputline[0]=_RECRUIT;
X+   outputline[1]=x+64;
X+   outputline[2]=y+64;
X+   outputline[3]=NULL;
X+   write(playerFd,outputline,strlen(outputline)+1);
X+ }
X+ 
X+ void endprogram() {
X+   outputline[0]=_DISCONNECT;
X+   outputline[1]=NULL;
X+   write(playerFd,outputline,strlen(outputline)+1); 
X+ }
X+ 
X+ int inrange(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+        
X+ int getmessage(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+ 
X+ void readnullterm(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+ 
X+ void setupmap(x,y) 
X+   int x;
X+   int y;
X+ {
X+   for (y=0; (y<_MAPY); y++) {
X+     for (x=0; (x<_MAPX); x++) {
X+       lastrecruit[x][y]=-100;
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+ 
X+ int connectstream()
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+ 
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+ 
X+ int inputwaiting(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+ /* get_host_address: borrowed with appreciation from Tinytalk. Does a nice
X+    job of getting around the various stupidities of the inetaddr routine,
X+    et cetera. */
X+ 
X+ int get_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+ 
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+   }
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+ 
X+     bcopy(blob->h_addr, addr, sizeof(struct in_addr));
X+   }
X+ 
X+   return (1);                           /* Success. */
X+ }
X+ 
X+ 
X*** /dev/null	Fri Nov 30 17:15:02 1990
X--- patchlevel.h	Fri Nov 30 17:17:41 1990
X***************
X*** 0 ****
X--- 1 ----
X+ #define PATCHLEVEL	1
END_OF_FILE
if test 32580 -ne `wc -c <'patches01'`; then
    echo shar: \"'patches01'\" unpacked with wrong size!
fi
# end of 'patches01'
fi
echo shar: End of shell archive.
exit 0