[comp.sources.games] v12i066: torus - topologically enhanced version of robots2, Part01/01

billr@saab.CNA.TEK.COM (Bill Randle) (05/02/91)

Submitted-by: Tad White <tadpole@math.ucla.edu>
Posting-number: Volume 12, Issue 66
Archive-name: torus/Part01
Environment: curses

[[This is a topologically enhanced version of Robots2, played
on a torus (or optionally on an annulus or a rectangle).]]

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  Makefile good.c main.c opt.c robot.c robots.h score.c
#   torus.6 user.c
# Wrapped by billr@saab on Wed May  1 13:02:47 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(5805 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# Makefile written by Paul Pomes, University of Illinois,
X# Computing Services Office
X#
X# Copyright (C) 1986 by Paul Pomes and the University of Illinois Board
X# of Trustees
X#
X# This Makefile is distributed in the hope that it will be useful,
X# but without any warranty.  No author or distributor accepts
X# responsibility to anyone for the consequences of using it or for
X# whether it serves any particular purpose or works at all, unless
X# s/he says so in writing.
X#
X# Everyone is granted permission to copy, modify and redistribute
X# this Makefile under the following conditions:
X#
X#    Permission is granted to anyone to make or distribute copies
X#    of Makefile source code, either as received or modified, in any
X#    medium, provided that all copyright notices, permission and
X#    nonwarranty notices are preserved, and that the distributor
X#    grants the recipient permission for further redistribution as
X#    permitted by this document, and gives him and points out to
X#    him an exact copy of this document to inform him of his rights.
X#
X#    Permission is granted to distribute this Makefile in compiled
X#    or executable form under the same conditions applying for
X#    source code, provided that either
X#    A. it is accompanied by the corresponding machine-readable
X#       source code, or
X#    B. it is accompanied by a written offer, with no time limit,
X#       to give anyone a machine-readable copy of the corresponding
X#       source code in return for reimbursement of the cost of
X#       distribution.  This written offer must permit verbatim
X#       duplication by anyone.
X#    C. it is distributed by someone who received only the
X#       executable form, and is accompanied by a copy of the
X#       written offer of source code which he received along with it.
X#
X# In other words, you are welcome to use, share and improve this
X# Makefile.  You are forbidden to forbid anyone else to use, share
X# and improve what you give them.   Help stamp out software-hoarding!
X#
X# UUCP:     {ihnp4,seismo}!uiucuxc!paul
X# Internet: paul@uxc.cso.uiuc.edu   BITNET: paul@uiucuxc
X# MILNET:   paul@uiucuxc.arpa       CSNET:  paul%uxc@uiuc.csnet
X# US Mail:  Univ of Illinois, CSO, 1304 W Springfield Ave, Urbana, IL  61801
X
X# .PREFIXES:	./RCS
X.SUFFIXES:	.c,v .h,v .y,v
X
XCC     = cc
XCO     = co
XRM     = /bin/rm -f
X
XHOF_FILE= ${DESTLIB}/robots2_hof
XTMP_FILE= ${DESTLIB}/robots2_tmp
XT_HOF_FILE= ${DESTLIB}/torus_hof
XT_TMP_FILE= ${DESTLIB}/torus_tmp
X
X# -DBSD42 provides big performance win
X
XDEFS   = -DBSD42 -DHOF_FILE='"${HOF_FILE}"' -DTMP_FILE='"${TMP_FILE}"' -DT_HOF_FILE='"${T_HOF_FILE}"' -DT_TMP_FILE='"${T_TMP_FILE}"'
XCFLAGS = ${DEFS} -O
XFFLAGS = ${DEFS}
XPFLAGS = ${DEFS}
XLFLAGS = 
XYFLAGS = 
XLDFLAGS= 
XLIBS   = -lcurses -ltermcap
X
XDESTBIN= /home/oak/grad/tadpole/topology
XDESTETC= /home/oak/grad/tadpole/topology/etc
XDESTLIB= /home/oak/grad/tadpole/topology/lib
XMS     = l
X
X
XHDRS   = robots.h
XSRCS   = good.c main.c opt.c robot.c score.c user.c
XOBJS   = good.o main.o opt.o robot.o score.o user.o
XVERS   = 
X
X.c,v.o:
X	${CO} -q $*.c
X	${CC} ${CFLAGS} -c $*.c
X	${RM} $*.c
X
X.c,v.c:
X	${CO} -q $*.c
X
X.h,v.h:
X	${CO} -q $*.h
X
X.y,v.y:
X	${CO} -q $*.y
X
Xall:	torus
X
Xtorus:	${OBJS}
X	${CC} -o torus ${LDFLAGS} ${OBJS} ${LIBS}
X
Xinstall:	torus
X	install -s -m 2511 -g games torus ${DESTBIN}
X	touch ${HOF_FILE} ${TMP_FILE}
X	chmod 664 ${HOF_FILE} ${TMP_FILE}
X	chgrp games ${HOF_FILE} ${TMP_FILE}
X	touch ${T_HOF_FILE} ${T_TMP_FILE}
X	chmod 664 ${T_HOF_FILE} ${T_TMP_FILE}
X	chgrp games ${T_HOF_FILE} ${T_TMP_FILE}
X	install -c -m 444 torus.6 ${MANDIR}/torus.${MS}
X
Xuninstall:	/tmp
X	rm -f ${DESTBIN}/torus \
X		${MANDIR}/torus.${MS} ${CATDIR}/torus.${MS} \
X		${HOF_FILE} ${TMP_FILE}
X
Xlint:	${HDRS} ${SRCS}
X	lint -habx ${DEFS} ${SRCS}
X
Xshar:	${HDRS} ${SRCS} ${OTHERS}
X	shar ${HDRS} ${SRCS} ${OTHERS} > torus.shar
X
Xtags:	${HDRS} ${SRCS}
X	ctags ${HDRS} ${SRCS}
X
Xclean:
X	@echo "Removing object and junk files."
X	rm -f robots2 *.o core a.out make.log lint.out Makefile.bak torus.shar
X
Xclobber:
X	@echo "Removing read-only source files that have RCS parents."
X	@echo "Error code 1 indicates last file in SRCS list was not removed."
X	@echo "(Which is OK)"
X	make clean
X	-if [ `whoami` != root ]; then \
X	   for i in ${HDRS} ${SRCS}; do \
X	      if [ ! -w $$i ]; then \
X	         ( if   [ -f $$i,v ];     then rm -f $$i; \
X	           elif [ -f RCS/$$i,v ]; then rm -f $$i; \
X	         fi ); \
X	      else echo $$i "writeable, not removed"; \
X	      fi; \
X	   done; \
X	else echo "Running \"make clobber\" as root will zap ALL SRCS,\
X		RCS'ed or not (not done)."; \
X	fi
X
Xcompress:
X	make clean
X	@echo "Compressing source and RCS files."
X	find . -size +2 \( -name \*.h -o -name \*.c -o -name \*.f \
X		-o -name \*.p -o -name \*.l -o -name \*.y -o -name \*,v \) \
X		-exec compress {} \;
X
Xuncompress:
X	uncompressdir .
X
X# RCS stuff
X
Xci:		${HDRS} ${SRCS}
X		-ci $?
X		@touch ci
X
Xcoall:
X		co -l ${HDRS} ${SRCS}
X
Xupdate:
X		ci -sDist -u -f${VERS} ${HDRS} ${SRCS}
X		@touch ci
X
Xdepend:
X	grep '^#[ 	]*include' /dev/null ${SRCS} \
X		| sed -e '/"/s/:[^"]*"\([^"]*\)".*/: \1/' \
X		      -e '/</s/:[^<]*<\([^>]*\)>.*/: \/usr\/include\/\1/' \
X		| sed -e 's/\.c:/.o:/' -e 's/\.p:/.o:/' \
X			-e 's/\.y:/.o:/' -e 's/\.l:/.o:/' >makedep
X	echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep
X	echo '$$r makedep' >>eddep
X	echo 'w' >>eddep
X	cp Makefile Makefile.bak
X	ed - Makefile < eddep
X	rm eddep makedep
X	echo '# DEPENDENCIES MUST END AT END OF FILE' >> Makefile
X	echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >> Makefile
X	echo '# see make depend above' >> Makefile
X
X# DO NOT DELETE THIS LINE -- make depend uses it
X
Xgood.o: robots.h
Xmain.o: robots.h
Xmain.o: /usr/include/sys/stat.h
Xopt.o: robots.h
Xrobot.o: robots.h
Xscore.o: robots.h
Xuser.o: robots.h
X# DEPENDENCIES MUST END AT END OF FILE
X# IF YOU PUT STUFF HERE IT WILL GO AWAY
X# see make depend above
END_OF_FILE
if test 5805 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'good.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'good.c'\"
else
echo shar: Extracting \"'good.c'\" \(3748 characters\)
sed "s/^X//" >'good.c' <<'END_OF_FILE'
X# include "robots.h"
X
X/*
X * good.c: Figure out all possible good moves.
X * This piece of code use to be trivial - then fast robots came
X * and moveable heaps and its now an AI expert system in its own right!
X */
X
Xgood_moves ()
X{
X  register int test_x, test_y;
X  register char *m, *a;
X  static char moves[] = "hjklyubn.a";
X  static char ans[sizeof (moves)];
X  char savebuf[9], savechar;
X  int i,j, notsilly;
X
X  a = ans;
X  for(m = moves; *m != 'a'; m++) {
X    test_x = hbound(my_y+yinc(*m),my_x+xinc(*m));
X    test_y = vbound(my_y+yinc(*m),my_x+xinc(*m));
X    move(test_y,test_x);
X    switch(inch()) {
X      case ' ':
X      case DOT:
X      case ME:
X        if( isgood(test_y, test_x) )
X          *a++ = *m;
X        break;
X      case SCRAP:
X        if (moveable_heaps) {
X        int nscrap_x,nscrap_y;
X        nscrap_x = hbound(test_y +yinc(*m),test_x +xinc(*m));
X        nscrap_y = vbound(test_y +yinc(*m),test_x +xinc(*m));
X        move(nscrap_y,nscrap_x);
X/*	if (inch()==DOT) {
X          addch(SCRAP);
X          if (isgood(test_y,test_x))
X            *a++ = *m;
X          move(nscrap_y,nscrap_x);
X          addch(DOT);
X          }
X        if (inch()==' ') {
X          addch(SCRAP);
X          if (isgood(test_y,test_x))
X            *a++ = *m;
X          move(nscrap_y,nscrap_x);
X          addch(' ');
X	  } */ /* rfs -- rewritten to eliminate bug in wimpy mode */
X	if ((savechar=inch())==DOT || savechar==' ') {
X	  addch(SCRAP);
X	  if (isgood(test_y,test_x))
X	    *a++ = *m;
X	  move(nscrap_y,nscrap_x);
X	  addch(savechar);
X	  } /* rfs -- end of replacement code */
X        }
X        break;
X    }
X  }
X  /* now lets do the antimatter case */
X  if (free_teleports) {
X  notsilly = 0;  /* silly to do it if not get robots */
X  for(i= -1;i <= 1; i++)
X    for(j= -1; j<= 1; j++) {
X      tmove(my_y+i,my_x+j);
X      savechar = inch();
X      if (savechar == FROBOT || savechar == ROBOT) {
X        savebuf[ (i+1)*3 +j +1] = savechar;
X        addch(' ');
X        notsilly = 1;
X        }
X      else
X        savebuf[ (i+1)*3 +j +1] = ' ';
X      }
X  if( notsilly && isgood(my_y,my_x) )
X    *a++ = *m;
X
X  for(i= -1;i <= 1; i++)
X    for(j= -1; j<= 1; j++) {
X      tmove(my_y+i,my_x+j);
X      savechar = savebuf[ (i+1)*3 +j +1];
X      if (savechar == FROBOT || savechar == ROBOT)
X        addch(savechar);
X      }
X  }
X  *a = 0;
X  if(ans[0]) {
X    a = ans;
X  } else {
X    a = "Forget it!";
X  }
X  mvprintw(LINES-1,MSGPOS,"%-*.*s",RVPOS-MSGPOS,RVPOS-MSGPOS,a);
X}
X
Xisgood(ty,tx)
Xregister int tx, ty;
X{
X  register int x, y;
X
X  for(x = -2; x <= 2; x++) {
X    for(y = -2; y <= 2; y++) {
X      if ( abs(x) > 1 || abs(y) > 1 ) { /* we are 2 steps out */
X        if( blocked(ty, tx, y, x))
X          continue;
X        tmove(ty+y,tx+x);
X        if ( abs(x) == 2 && abs(y) == 2
X              && inch() == FROBOT){
X          return FALSE;  }
X        if ( x == -1 && scan(ty+y, tx+x, 0, 1) )
X          return FALSE;
X        if ( y == -1 && scan(ty+y, tx+x, 1, 0) )
X          return FALSE;
X      } /* outer perimeter checked */
X      else {
X        tmove(ty+y,tx+x);
X        switch(inch()) {
X          case FROBOT:
X          case ROBOT: /* robot next to you */
X            return FALSE;
X        }
X      }
X    }
X  }
X  return TRUE;
X}
X
Xscan(y, x, yi, xi) /* scan along this line looking for collision conditions */
Xint x, y, xi, yi;
X{
X  int rcount = 0;
X  register int ctr;
X
X  for(ctr = 0;ctr<=2;ctr++) {
X    tmove(y + (ctr*yi), x + (ctr*xi));
X    switch(inch()) {
X      case FROBOT:
X        rcount += 4;
X        break;
X      case ROBOT:
X        rcount ++;
X        break;
X    }
X  }
X  return rcount == 4;
X}
X
Xblocked(my, mx, y, x)
Xregister int  my, mx, y, x;
X{
X  if ( x < 0 ) x++;
X  if ( y < 0 ) y++;
X  if ( x > 0 ) x--;
X  if ( y > 0 ) y--;
X  tmove(my+y, mx+x);
X  return inch() == SCRAP;
X}
END_OF_FILE
if test 3748 -ne `wc -c <'good.c'`; then
    echo shar: \"'good.c'\" unpacked with wrong size!
fi
# end of 'good.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(9110 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/*
X *	R O B O T S   ( T O R U S )
X *
X *	The game of robots.
X *	History:
X *	Original Implementation
X *		Allan Black <allan@cs.strath.ac.uk>
X *	Updated for fast robots, moveable heaps, ROBOTOPTS
X *	antimatter, v7/sys5/4.2 portability etc.
X *		Graeme Lunt <gal@cs.nott.ac.uk>
X *		Julian Onions <jpo@cs.nott.ac.uk>
X *	Topological modifications:
X *		Tad White <tadpole@math.ucla.edu>
X *
X * Provided free as long as you don't make money from it!
X */
X
X# include "robots.h"
X
Xchar	whoami[MAXSTR];
Xchar	my_user_name[MAXSTR];
Xchar	cmd_ch;
X
Xbool	dead = FALSE;
Xbool	last_stand;
Xbool	show_highscore = TRUE;
Xbool	adjacent, first_move, bad_move, waiting;
Xbool	moveable_heaps = TRUE;
Xbool    hsew = TRUE;
Xbool    vsew = TRUE;
Xbool    toral = TRUE;
Xbool    hrev = FALSE;
Xbool    vrev = FALSE;
Xbool    wimpy = FALSE;
Xbool    all_moves = FALSE;
Xbool    continuous = FALSE;
X
Xint	my_x, my_y;
Xint	new_x, new_y;
Xint	level = 0;
Xint	free_teleports = 0;
Xint	old_free;
Xint	free_per_level = 1;
Xint	count;
Xint	dots = 0;
Xint	robot_value = MIN_VALUE;
Xint	max_robots = MIN_ROBOTS;
Xint	nrobots_alive;
Xint	scrap_heaps = 1;  /* to allow for first level */
X
Xlong	score = 0;
Xlong	seed;
X
X# ifdef TIOCSLTC
Xstruct ltchars	ltc;
Xchar	dsusp;
X# endif TIOCSLTC
X
X# ifdef TURBOC
Xint
X#endif
Xr_interrupt();
X
X# define	TERM_UNINIT	00
X# define	TERM_CURSES	01
X# define	TERM_LTC	02
X
Xint	term_state = TERM_UNINIT;	/* cuts out some race conditions */
Xchar	*getenv();
X# ifndef TURBOC /* rfs */
Xstruct	passwd	*getpwuid();
Xchar	_obuf[BUFSIZ];
X# endif
X
Xmain(argc,argv)
X     int argc;
X     char *argv[];
X{
X# ifndef TURBOC /* rfs */
X  register struct passwd *pass;
X# endif
X
X  register char *x;
X  int i;
X
X# ifndef TURBOC /* rfs */
X  setbuf(stdout, _obuf);
X# endif
X  if(argc > 1)
X    for(i=1;i<argc;i++) {
X      if(argv[i][0] == '-')
X	switch(argv[i][1]) {
X	case 's':
X	  show_highscore = TRUE;
X	  scoring(FALSE);
X	  exit(0);
X	  break;
X	case 'h':
X	  hsew = FALSE;
X	  /* hrev = TRUE; */
X	  break;
X	case 'v':
X	  vsew = FALSE;
X	  /* vrev = TRUE; */
X	  break;
X	case 'w':
X	  wimpy = FALSE;
X	  break;
X	case 'c':
X	  continuous = FALSE;
X	  break;
X	}
X      if(argv[i][0] == '+') {
X	switch(argv[i][1]) {
X	case 'h':
X	  hsew = TRUE;
X	  hrev = FALSE;
X	  break;
X	case 'v':
X	  vsew = TRUE;
X	  vrev = FALSE;
X	  break;
X	case 'w':
X	  wimpy = TRUE;
X	  break;
X	case 'c':
X	  continuous = TRUE;
X	  break;
X	}
X      }
X      if (argv[i][0] == '0') {
X	switch(argv[i][1]) {
X	case 'h':
X	  hsew = FALSE;
X	  hrev = FALSE;
X	  break;
X	case 'v':
X	  vsew = FALSE;
X	  vrev = FALSE;
X	  break;
X	}
X      }
X    }
X# ifdef TURBOC /* rfs */
X  if (strcmp(x=getenv("USERNAME"),"")==0) x="ANON";
X# else
X  if((pass = getpwuid(getuid())) == 0) {
X    x = "ANON";
X  } else {
X    x = pass->pw_name;
X  }
X# endif
X  (void) strcpy(my_user_name, x);
X  (void) strcpy(whoami,x);
X  if((x = getenv(ROBOTOPTS)) != NULL && *x != '\0')
X    get_robot_opts(x);
X  seed = time((time_t *)0)+getuid();
X# ifndef TURBOC /* rfs */
X  (void) signal(SIGQUIT,r_interrupt);
X  (void) signal(SIGINT,r_interrupt);
X# endif
X  if( initscr() == ERR) {
X    fprintf(stderr, "Curses won't initialize - seek a guru\n");
X    quit();
X  }
X  term_state |= TERM_CURSES;
X  crmode();
X  noecho();
X# ifdef TIOCSLTC
X  (void) ioctl(1,TIOCGLTC,&ltc);
X  dsusp = ltc.t_dsuspc;
X  ltc.t_dsuspc = ltc.t_suspc;
X  (void) ioctl(1,TIOCSLTC,&ltc);
X  term_state |= TERM_LTC;
X# endif TIOCSLTC
Xrestart:  
X  dead = FALSE;
X  free_teleports = 0;
X  level = 0;
X  free_per_level = 1;
X  scrap_heaps = 1;
X  score = 0;
X  robot_value = MIN_VALUE;
X  max_robots = MIN_ROBOTS;
X  for(;;) {
X    count = 0;
X    adjacent = FALSE;
X    waiting = FALSE;
X    last_stand = FALSE;
X    old_free = -1;
X    if(rnd(free_per_level) < free_teleports) {
X      free_per_level++;
X      if(free_per_level > MAX_FREE) free_per_level = MAX_FREE;
X    }
X    free_teleports += free_per_level;
X    leaveok(stdscr,FALSE);
X    draw_screen();
X    put_robots();
X    do {
X      my_x = rndx();
X      my_y = rndy();
X      move(my_y,my_x);
X    } while(inch() != ' ');
X    addch(ME);
X    if (dots) put_dots();
X    for(;;) {
X      scorer();
X      if(nrobots_alive == 0) break;
X      command();
X      for(i=1;i<=FASTEST;i++)
X	robots(i);
X      if(dead) { munch(); goto restart; }
X    }
X    msg("%d robots are now %d scrap heaps",max_robots, scrap_heaps);
X    leaveok(stdscr,FALSE);
X    move(my_y,my_x);
X    refresh();
X    (void) readchar();
X    level++;
X  }
X}
X
Xdraw_screen()
X{
X	register int x, y;
X	clear();
X	for(y = 1; y < LINES-2; y++) {
X		mvaddch(y,0,VERT);
X		mvaddch(y,COLS-1,VERT);
X	}
X	for(x = 0; x < COLS; x++) {
X		mvaddch(0,x,HORIZ);
X		mvaddch(LINES-2,x,HORIZ);
X	}
X}
X
Xreadchar()
X{
X# ifdef TURBOC /* rfs */
X	return getch();
X# else
X	static char buf[1];
X	extern int errno;
X
X	while(read(0,buf,1) != 1)
X		if( errno != EINTR) {
X			scoring(TRUE);
X			quit();
X		}
X	return(buf[0]);
X# endif
X}
X
Xput_dots()
X{
X	register int x, y;
X	for(x = my_x-dots; x <= my_x+dots; x++) {
X		for(y = my_y-dots; y <= my_y+dots; y++) {
X			tmove(y,x);
X			if(inch() == ' ') addch(DOT);
X		}
X	}
X}
X
Xerase_dots()
X{
X	register int x, y;
X	for(x = my_x-dots; x <= my_x+dots; x++) {
X		for(y = my_y-dots; y <= my_y+dots; y++) {
X			tmove(y,x);
X			if(inch() == DOT) addch(' ');
X		}
X	}
X}
X
Xxinc(dir)
X	char dir;
X{
X	switch(dir) {
X	case 'h':
X	case 'y':
X	case 'b':
X		return(-1);
X	case 'l':
X	case 'u':
X	case 'n':
X		return(1);
X	case 'j':
X	case 'k':
X	default:
X		return(0);
X	}
X}
X
Xyinc(dir)
X	char dir;
X{
X	switch(dir) {
X	case 'k':
X	case 'y':
X	case 'u':
X		return(-1);
X	case 'j':
X	case 'b':
X	case 'n':
X		return(1);
X	case 'h':
X	case 'l':
X	default:
X		return(0);
X	}
X}
X
Xint vbound(y,x)  /* for toral robots:  converts y to lie within boundary */
X     int y,x;
X{
X  register int t_y;
X  t_y = y;
X  if ( vsew /* ||vrev */ ) {
X    if (y >= LINES-2) t_y = y - (LINES-3);
X    if (y <= 0) t_y = y + (LINES-3);
X  }
X  /* if ( (hrev) && ((x >= COLS-1) || (x <= 0)) ) t_y = LINES - 2 - t_y; */
X  return(t_y);
X}
X
Xint hbound(y,x)
X     int y,x;
X{
X  register int t_x;
X  t_x = x;
X  if (hsew /*||hrev*/ ) {
X    if (x >= COLS-1) t_x = x - (COLS-2);
X    if (x <= 0) t_x = x + (COLS-2);
X  }
X  /* if ( (vrev) && ((y >= LINES-2) || (y <= 0)) ) t_x = COLS - 1 - t_x; */
X  return(t_x);
X}
X
Xtmove(y,x)  /* move with wrap-around, if edge identifications made. */
Xint y,x;
X{
X  move(vbound(y,x),hbound(y,x));
X}
X
Xmunch()
X{
X	scorer();
X	msg("MUNCH! You're robot food");
X	leaveok(stdscr,FALSE);
X	mvaddch(my_y,my_x,MUNCH);
X	move(my_y,my_x);
X	refresh();
X	(void) readchar();
X	scoring(TRUE);
X	if (!continuous) quit();
X}
X
Xquit()
X{
X	if( term_state & TERM_CURSES ) {
X		move(LINES-1,0);
X		refresh();
X		endwin();
X		term_state &= ~ TERM_CURSES;
X	}
X	putchar('\n');
X# ifdef TIOCSLTC
X	if( term_state & TERM_LTC ) {
X		ltc.t_dsuspc = dsusp;
X		(void) ioctl(1,TIOCSLTC,&ltc);
X		term_state &= ~ TERM_LTC;
X	}
X# endif TIOCSLTC
X	(void) signal(SIGINT, SIG_DFL);
X	exit(0);
X}
X
Xrndx()
X{
X	return(rnd(COLS-2)+1);
X}
X
Xrndy()
X{
X	return(rnd(LINES-3)+1);
X}
X
Xrnd(mod)
X	int mod;
X{
X	if(mod <= 0) return(0);
X	return((((seed = seed*11109L+13849L) >> 16) & 0xffffL) % mod);
X}
X
X/* VARARGS 1 */
Xmsg(message,a1, a2, a3, a4, a5, a6, a7)
X	char *message;
X	unsigned int a1, a2, a3, a4, a5, a6, a7;
X{
X	static char msgbuf[1000];
X
X	(void) sprintf(msgbuf, message, a1, a2, a3, a4, a5, a6, a7);
X	mvaddstr(LINES-1,MSGPOS,msgbuf);
X	clrtoeol();
X	refresh();
X}
X
X# ifdef TURBOC /* rfs */
Xint
X# endif
Xr_interrupt()
X{
X	scoring(FALSE);
X	quit();
X}
X
X/*
X * file locking routines - much nicer under BSD ...
X */
X
X# ifdef TURBOC /* rfs */
Xlk_open(file,mode) /* don't need to lock score files on IBM PCs */
Xchar *file;
Xint mode;
X{
X	int	fd;
X	if ((fd = open(file, mode, S_IREAD|S_IWRITE)) < 0)  return -1;
X	return fd;
X}
X
Xlk_close(fd, fname)
Xint	fd;
Xchar	*fname;
X{
X	return close(fd);
X}
X
X# endif
X# if defined(BSD42)
Xlk_open(file, mode)	/* lock a file using the flock sys call */
Xchar	*file;
Xint	mode;
X{
X	int	fd;
X
X	if( (fd = open(file, mode)) < 0)
X		return -1;
X	if( flock(fd, LOCK_EX) < 0)
X	{
X		(void) close(fd);
X		return -1;
X	}
X	return fd;
X}
X
Xlk_close( fd, file)
Xint	fd;
Xchar	*file;
X{
X# ifdef lint
X	file = file;	/* now will you shut up lint???? */
X# endif
X	return close(fd);
X}
X# else
X
X# define	LOCKTIME	(60)	/* 1 minute */
X# include	<sys/stat.h>
X
Xlk_open(file, mode)	/* lock a file by crude means */
Xchar	*file;
Xint	mode;
X{
X	char	tfile[128], lfile[128];
X	struct	stat stbuf;
X	time_t	now;
X	int	fd;
X
X	(void) sprintf(tfile, "%s.t", file);	/* temp file */
X	(void) sprintf(lfile, "%s.l", file);	/* lock file */
X
X	if( close(creat(tfile, 0)) < 0)	/* make temp file */
X		return -1;
X	while( link(tfile, lfile) == -1)	/* now attempt the lock file */
X	{
X		if( stat(lfile, &stbuf) < 0)
X			continue;	/* uhh? -- try again */
X		time(&now);
X		/* OK - is this file old? */
X		if( stbuf.st_mtime + LOCKTIME < now)
X			unlink(lfile);	/* ok its old enough - junk it */
X		else	sleep(1);	/* snooze ... */
X	}
X	unlink(tfile);	/* tmp files done its job */
X	if((fd = open(file, mode)) < 0) {
X		unlink(lfile);
X		return -1;
X	}
X	return fd;
X}
X
Xlk_close(fd, fname)
Xint	fd;
Xchar	*fname;
X{
X	char	lfile[128];
X
X	(void) sprintf(lfile, "%s.l", fname);	/* recreate the lock file name */
X	if( unlink(lfile) == -1) /* blow it away */
X		perror(lfile);
X	return close(fd);
X}
X# endif
X
X# ifdef TURBOC /* rfs */
Xint getuid () {
X  return 0;
X  }
X# endif
END_OF_FILE
if test 9110 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'opt.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'opt.c'\"
else
echo shar: Extracting \"'opt.c'\" \(2564 characters\)
sed "s/^X//" >'opt.c' <<'END_OF_FILE'
X# include "robots.h"
X
X/*
X * opt.c: do a psuedo ROGUEOPTS sort of thing
X */
X
Xtypedef struct Opt {
X	char	*name;
X	int	type;
X} Opt;
X
XOpt	options[] = {
X# define	OPT_NAME	1
X	"name",		OPT_NAME,	/* Who am i boss ? */
X# define	OPT_MOVE_HEAP	2
X	"moveheaps",	OPT_MOVE_HEAP,	/* can push heaps */
X# define	OPT_NOMOVE_HEAP	3
X	"nomoveheaps",	OPT_NOMOVE_HEAP,/* can't push heaps */
X# define	OPT_SHOW_HSCORE 4
X	"showhscore",	OPT_SHOW_HSCORE,
X# define	OPT_NOSHOW_HSCORE 5
X	"noshowhscore", OPT_NOSHOW_HSCORE,
X# define        OPT_HSEW        6
X	"hsew",        OPT_HSEW,
X# define        OPT_NOHSEW      7
X	"nohsew",      OPT_NOHSEW,
X# define        OPT_VSEW        8
X	"vsew",        OPT_VSEW,
X# define        OPT_NOVSEW      9
X	"novsew",      OPT_NOVSEW,
X# define        OPT_WIMPY       10
X        "wimpy",        OPT_WIMPY,
X# define        OPT_STUDLY      11
X        "studly",       OPT_STUDLY,
X# define        OPT_CONT        12
X        "continuous",   OPT_CONT,
X# define        OPT_NOCONT      13
X	"nocontinuous", OPT_NOCONT,
X	0,		0
X};
X
X/* get_robot_opts: Personalise robots to the users tastes. Model after
X * the rogue/urogue type environment stuff. 
X */
X
Xget_robot_opts(str)
Xchar	*str;
X{
X	register char	 *p;
X	Opt	*op;
X	int	len, len2;
X
X	p = str;
X	while(*p)
X	{
X		while(*p && !isalpha(*p)) p++;  /* skip non-alphas */
X		str = p;
X
X		while(isalpha(*p)) p ++;	/* match longest word */
X		len = p - str;
X
X		for(op = options; op->name; op ++)	/* see if defined */
X			if( strncmp(str, op->name, len) == 0)
X				break;
X		if( op->name == NULL)
X			continue;
X		switch(op->type)	/* OK, now do something */
X		{
X			case OPT_NAME:
X				while(*p == '=') p++;	/* skip ='s */
X				str = p;	/* OK, now look for name */
X				while(*p && *p != ',') p++;
X				len2 = (MAXSTR - 1) -
X					(strlen(my_user_name) + 4);
X				len = p - str;
X				len = len < len2 ? len : len2;
X				(void) sprintf(whoami, "%.*s (%s)", len,
X					str, my_user_name);
X				break;
X			case	OPT_MOVE_HEAP:
X				moveable_heaps = TRUE;
X				break;
X			case	OPT_NOMOVE_HEAP:
X				moveable_heaps = FALSE;
X				break;
X			case	OPT_SHOW_HSCORE:
X				show_highscore = TRUE;
X				break;
X			case	OPT_NOSHOW_HSCORE:
X				show_highscore = FALSE;
X				break;
X			case	OPT_HSEW:
X				hsew = TRUE;
X				break;
X			case	OPT_NOHSEW:
X				hsew = FALSE;
X				break;
X			case	OPT_VSEW:
X				vsew = TRUE;
X				break;
X			case	OPT_NOVSEW:
X				vsew = FALSE;
X				break;
X			case	OPT_WIMPY:
X				wimpy = TRUE;
X				break;
X			case	OPT_STUDLY:
X				wimpy = FALSE;
X				break;
X			case	OPT_CONT:
X				continuous = TRUE;
X				break;
X			case	OPT_NOCONT:
X				continuous = FALSE;
X				break;
X		}
X	}
X}
X
END_OF_FILE
if test 2564 -ne `wc -c <'opt.c'`; then
    echo shar: \"'opt.c'\" unpacked with wrong size!
fi
# end of 'opt.c'
fi
if test -f 'robot.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'robot.c'\"
else
echo shar: Extracting \"'robot.c'\" \(4144 characters\)
sed "s/^X//" >'robot.c' <<'END_OF_FILE'
X# include "robots.h"
X
X/*
X * robot.c: most of the robot oriented stuff
X */
X
Xstruct robot {
X  bool  alive;  /* is this suker still kicking */
X  int  x;
X  int  y;
X  int  speed;  /* speed of robot 1 or 2 for now */
X} rbt_list[MAX_ROBOTS+1];
X
Xput_robots()  /* place some robots */
X{
X  register struct robot *r, *end;
X  register int x, y;
X
X  robot_value += level*(5 + (max_robots/scrap_heaps));
X  max_robots += level*3+rnd(level*5);
X  if(max_robots > MAX_ROBOTS) max_robots = MAX_ROBOTS;
X  nrobots_alive = max_robots;
X  scrap_heaps = 0;  /* number of scrap heaps created */
X  end = &rbt_list[max_robots];
X  for(r = rbt_list; r < end; r++) {
X    for(;;) {
X      x = rndx();
X      y = rndy();
X      move(y,x);
X      if(inch() == ' ') break;
X    }
X    r->x = x;
X    r->y = y;
X    r->alive = TRUE;
X    r->speed = 1 +  ( rnd(10) > 6 );
X    if (r->speed == 2) addch(FROBOT);
X    else  addch(ROBOT);
X  }
X}
X
Xrobots(speed)  /* Troops, Troooooops advance! */
Xint speed;
X{
X  register struct robot *r, *end;
X  register int x_inc, y_inc, h_dist, v_dist;
X
X  end = &rbt_list[max_robots];
X  for(r = rbt_list; r < end; r++) {
X    if(r->alive && r->speed >= speed ) {
X      mvaddch(r->y,r->x,' ');
X    }
X  }
X  for(r = rbt_list; r < end; r++) {
X    if (r->alive && r->speed >= speed )
X    {
X      x_inc = sign(my_x-r->x);
X      y_inc = sign(my_y-r->y);
X      /*
X      h_dist = (hrev) ? abs(my_x-WIDTH+r->x) : abs(my_x-r->x);
X      v_dist = (vrev) ? abs(my_y-HEIGHT+r->y) : abs(my_y-r->y);
X      if ((hsew || hrev) && (h_dist > WIDTH/2)) x_inc *= -1;
X      if ((vsew || vrev) && (v_dist > HEIGHT/2)) y_inc *= -1;
X      if ((hrev) && (v_dist > HEIGHT/2)) y_inc *= -1;
X      if ((vrev) && (h_dist > WIDTH/2)) x_inc *= -1;
X      */
X      if ( hsew && (abs(my_x-r->x) > (COLS-2)/2) )
X        x_inc *= -1;
X      if ( vsew && (abs(my_y-r->y) > (LINES-3)/2) )
X        y_inc *= -1;
X      r->y=vbound(r->y+y_inc,r->x+x_inc);
X      r->x=hbound(r->y+y_inc,r->x+x_inc);
X      move(r->y,r->x);
X      switch(inch()) {
X      case ME:  /* robot eat me */
X        addch(MUNCH);
X        dead = TRUE;
X        break;
X      case SCRAP:  /* robot walks into scrap heap */
X        r->alive = FALSE;
X        if(r->speed == 2)
X          score += (MULT * robot_value);
X        else  score += robot_value;
X        nrobots_alive--;
X        break;
X      case FROBOT:
X      case ROBOT:  /* two robots form scrap heap */
X        collision(r, end);
X        r->alive = FALSE;
X        addch(SCRAP);
X        if (r->speed == 2)
X          score += (MULT * robot_value);
X        else  score += robot_value;
X        nrobots_alive -= 2;
X        scrap_heaps++ ;
X        break;
X      case MUNCH:
X        break;
X      default:
X        if(r->speed == 2) addch(FROBOT);
X        else  addch(ROBOT);
X      }
X    }
X  }
X}
X
X/* do two robots collide - if so - which two */
Xcollision(r, end)
Xregister struct robot *r, *end;
X{
X  register struct robot *find;
X
X  for(find = rbt_list; find < end; find++) {
X    if(find->alive && r != find) {
X      if(r->x == find->x && r->y == find->y) {
X        find->alive = FALSE;
X        if (find->speed == 2)
X          score += (MULT * robot_value);
X        else score += robot_value;
X        return;
X      } /* end of if */
X    }
X  }
X}
X
Xscrewdriver()  /* dismantle those robots ... */
X{
X  register int test_x, test_y;
X  register char *m ;
X  register struct robot *end,*find;
X  static char moves[] = "hjklyubn.";
X
X  end = &rbt_list[max_robots];
X
X  for(m = moves; *m; m++) {  /* let's see if there is a robot */
X    test_x = hbound(my_y+yinc(*m),my_x+xinc(*m));
X    test_y = vbound(my_y+yinc(*m),my_x+xinc(*m));
X    move(test_y,test_x);
X    switch(inch()) {
X    case FROBOT:
X    case ROBOT:  /* OK so there is now let's look for it */
X      for(find = rbt_list; find < end; find++) {
X        if(find->alive) {
X          if(test_x == find->x && test_y  == find->y) {
X            find->alive = FALSE;
X            if (find->speed == 2) score += (MULT * robot_value);
X            else score += robot_value;
X            } /* end of if */
X        } /* end of if */
X      } /* end of for */
X      addch(' ');
X      nrobots_alive--;
X      break;
X    } /* end of case */
X  }
X  free_teleports--;
X}
END_OF_FILE
if test 4144 -ne `wc -c <'robot.c'`; then
    echo shar: \"'robot.c'\" unpacked with wrong size!
fi
# end of 'robot.c'
fi
if test -f 'robots.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'robots.h'\"
else
echo shar: Extracting \"'robots.h'\" \(2662 characters\)
sed "s/^X//" >'robots.h' <<'END_OF_FILE'
X/*
X * robots.h: include file for the robots game
X */
X
X# include <curses.h>
X# include <signal.h>
X# include <pwd.h>
X# include <ctype.h>
X# include <sys/types.h>
X# include <errno.h>
X# ifdef	BSD42
X# include <sys/file.h>
X# endif BSD42
X
X# define MIN_ROBOTS	10	/* no. of robots you start with */
X# define MAX_ROBOTS	500	/* maximum robots on a screen	*/
X# define MIN_VALUE	10	/* what each robot is worth to begin */
X# define MAX_FREE	3	/* max free teleports per level	*/
X# define FASTEST	2	/* the fastest robot (dont fiddle) */
X
X# define VERT	'|'		/* vertical wall	*/
X# define HORIZ	'-'		/* horizontal wall	*/
X# define ROBOT	'+'		/* normal robot		*/
X# define FROBOT '#'		/* fast robot		*/
X# define SCRAP  '*'
X# define ME	'@'
X# define MUNCH	'!'
X# define DOT	'.'
X
X# define LEVEL		(level+1)
X
X# define MSGPOS		35	/* where messages appear on bottom line */
X# define RVPOS		47
X
X# define WIDTH          (COLS-2)
X# define HEIGHT         (LINES-3)
X
X/* These you may want to fiddle with. Position of the two high score files */
X#ifndef	HOF_FILE
X# define HOF_FILE	"/usr/sheriff/jpo/games/lib/robots_hof"
X#endif
X#ifndef	TMP_FILE
X# define TMP_FILE	"/usr/sheriff/jpo/games/lib/robots_tmp"
X#endif
X
X# define NUMSCORES	20		/* number of people to record */
X# define NUMNAME	"Twenty"	/* above spelt out */
X
X# define TEMP_DAYS	7		/* how long temp scores last */
X# define TEMP_NAME	"Week"
X
X# define ROBOTOPTS	"ROBOTOPTS"	/* environment tailoring */
X
X# define MAXSTR		100
X
X# define MULT		1.5		/* multiplier for fast robots */
X
X/* if ALLSCORES Undefined - record top n players */
X# define ALLSCORES			/* record top n scores */
X
X# define SECSPERDAY	86400
X
X# define ctrl(x)	((x)&037)
X# define BEL	ctrl('G')
X
X# define	abs(X)  ((X) < 0 ? -(X) : (X))
X# define	sign(X) ((X) < 0 ? -1 : (X) > 0)
X
Xextern	char	whoami[];
Xextern	char	my_user_name[];
Xextern	char	cmd_ch;
X
Xextern	bool	moveable_heaps;
Xextern	bool	show_highscore;
Xextern  bool    hsew;
Xextern  bool    vsew;
Xextern  bool    toral;
Xextern  bool    hrev;
Xextern  bool    vrev;
Xextern  bool    wimpy;
Xextern  bool    continuous;
Xextern  bool    all_moves;
Xextern	bool	last_stand;
Xextern	bool	bad_move;
Xextern	bool	running;
Xextern	bool	waiting;
Xextern	bool	first_move;
Xextern	bool	adjacent;
Xextern	bool	dead;
X
Xextern	int	my_x, my_y;
Xextern	int	new_x, new_y;
Xextern	int	count;
Xextern	int	free_teleports;
Xextern	int 	dots;
Xextern	int	robot_value;
Xextern	int	level;
Xextern	int	max_robots;
Xextern	int	scrap_heaps;
Xextern	int	nrobots_alive;
Xextern	int	free_per_level;
Xextern	int	old_free;
X
Xextern	long	score;
Xextern	long	lseek();
X
Xextern	char	*strcpy ();
Xextern	char	*strncpy ();
Xextern	char	*malloc ();
Xextern	char	*gets ();
Xextern	char	*sprintf ();
END_OF_FILE
if test 2662 -ne `wc -c <'robots.h'`; then
    echo shar: \"'robots.h'\" unpacked with wrong size!
fi
# end of 'robots.h'
fi
if test -f 'score.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'score.c'\"
else
echo shar: Extracting \"'score.c'\" \(5431 characters\)
sed "s/^X//" >'score.c' <<'END_OF_FILE'
X# include "robots.h"
X
X/*
X * score.c: All the scoring code is in here.
X */
X
Xstruct scorefile {
X	int	s_uid;
X	long	s_score;
X	char	s_name[MAXSTR];
X	bool	s_eaten;
X	int	s_level;
X	bool    s_hsew;
X	bool    s_vsew;
X	bool    s_wimpy;
X	int	s_days;
X};
X
X# define FILE_SIZE	(NUMSCORES*sizeof(struct scorefile))
X
Xscoring(eaten)
X	bool eaten;
X{
X	static char buf[MAXSTR];
X        toral = hsew && vsew;
X	(void) sprintf(buf,"for this %s",TEMP_NAME);
X	if( record_score(eaten,toral?T_TMP_FILE:TMP_FILE,TEMP_DAYS,buf)
X            || show_highscore) {
X		printf("[Press return to continue]");
X		fflush(stdout);
X		gets(buf);
X	}
X	record_score(eaten,toral?T_HOF_FILE:HOF_FILE,0,"of All Time");
X}
X
X# define	sigbit(x)	(1 << ((x) - 1))
X
Xrecord_score(eaten,fname,max_days,type_str)
X	bool eaten;
X	char *fname;
X	int max_days;
X	char *type_str;
X{
X	int value;
X	int fd;
X	int omask;
X
X	/* block signals while recording the score
X	 * hope this routine doesn't get stuck!
X	 */
X# ifndef BSD42
X# ifdef TURBOC /* rfs */
X	void
X# else
X	int
X# endif
X	     (*oint)(), (*oterm)(), (*ohup)();
X
X	oint = signal(SIGINT, SIG_IGN);
X	oterm = signal(SIGTERM, SIG_IGN);
X# ifndef TURBOC /* rfs */
X	ohup = signal(SIGHUP, SIG_IGN);
X# endif
X# else
X	omask = sigblock( sigbit(SIGINT) | sigbit(SIGTERM) | sigbit(SIGHUP)
X			| sigbit(SIGTSTP));
X# endif
X
X	if((fd = lk_open(fname,
X# ifdef TURBOC /* rfs */
X				O_RDWR | O_CREAT | O_BINARY
X# else
X				2
X# endif
X					)) < 0) {
X		perror(fname);
X	} else {
X		value = do_score(eaten,fd,max_days,type_str);
X		lk_close(fd, fname);
X	}
X# ifdef BSD42
X	(void) sigsetmask(omask);
X# else
X	(void) signal(SIGINT, oint);
X	(void) signal(SIGTERM, oterm);
X# ifndef TURBOC /* rfs */
X	(void) signal(SIGHUP, ohup);
X# endif
X# endif
X	return value;
X}
X
Xdo_score(eaten,fd,max_days,type_str)
X	bool eaten;
X	int fd, max_days;
X	char *type_str;
X{
X	register struct scorefile *position;
X	register int x;
X/*	register struct scorefile *remove, *sfile, *eof; */ /* rfs */
X	register struct scorefile *remove, *eof; /* rfs */
X	static struct scorefile *sfile=NULL; /* rfs */
X	struct scorefile *oldest, *this;
X	int uid, this_day, limit;
X
X	this_day = max_days ? time((time_t *)0)/SECSPERDAY : 0;
X	limit = this_day-max_days;
X	if (sfile==NULL) /* rfs */
X	sfile = (struct scorefile *)(malloc(FILE_SIZE));
X	if( sfile == NULL)
X	{
X		fprintf( stderr, "Out of memory so no scoring");
X		return FALSE;
X	}
X	eof = &sfile[NUMSCORES];
X	this = 0;
X	for(position = sfile; position < eof; position++) {
X		position->s_score = 0;
X		position->s_days = 0;
X	}
X	read(fd, (char *)sfile,FILE_SIZE);
X	remove = 0;
X	if(score > 0) {
X		uid = getuid();
X		oldest = 0;
X		x = limit;
X		for(position = eof-1; position >= sfile; position--) {
X			if(position->s_days < x) {
X				x = position->s_days;
X				oldest = position;
X			}
X		}
X		position = 0;
X		for(remove = sfile; remove < eof; remove++) {
X			if(position == 0 && score > remove->s_score) position = remove;
X# ifndef ALLSCORES
X			if(remove->s_uid == uid) break;
X# endif ALLSCORES
X		}
X		if(remove < eof) {
X			if(position == 0 && remove->s_days < limit) position = remove;
X		} else if(oldest) {
X			remove = oldest;
X			if(position == 0) {
X				position = eof-1;
X			} else if(remove < position) {
X				position--;
X			}
X		} else if(position) {
X			remove = eof-1;
X		}
X		if(position) {
X			if(remove < position) {
X				while(remove < position) {
X					*remove = *(remove+1);
X					remove++;
X				}
X			} else {
X				while(remove > position) {
X					*remove = *(remove-1);
X					remove--;
X				}
X			}
X			position->s_score = score;
X			(void) strncpy(position->s_name,whoami,MAXSTR);
X			position->s_eaten = eaten;
X			position->s_level = LEVEL;
X			position->s_uid = uid;
X			position->s_hsew = hsew;
X			position->s_vsew = vsew;
X			position->s_wimpy = wimpy;
X			position->s_days = this_day;
X			this = position;
X			if(lseek(fd,0L,0) == -1L ||
X				write(fd,(char *)sfile,FILE_SIZE) != FILE_SIZE)
X				perror("scorefile");
X			close(fd);
X		}
X	}
X	if( show_highscore || this )
X	{
X		printf(
X# ifdef ALLSCORES
X			"\nTop %s %s Scores %s:\n",
X# else ALLSCORES
X			"\nTop %s %s Robotists %s:\n",
X# endif ALLSCORES
X			NUMNAME,
X                        toral?"Toral":"Non-Toral",
X			type_str
X		);
X		printf("Rank     Score    Name\n");
X		for(position = sfile; position < eof; position++) {
X			if(position->s_score == 0) break;
X			if(position == this)
X				putchar('>');
X			else  putchar(' ');
X			printf(
X			       "%c%2d %10ld  %8s: %s on %6s",
X			       position->s_days < limit ? '*' : ' ',
X			       position-sfile+1,
X			       position->s_score,
X			       position->s_name,
X			       position->s_eaten ?
X			         "robot chow" : "ducked out",
X			       position->s_wimpy ? "wimpy" : "studly");
X			if(position->s_hsew)
X			  printf( " %7s",
X				 (position->s_vsew) ? "toral" : "annular");
X			else
X			  printf( " %7s",
X				 (position->s_vsew) ? "annular" : "planar");
X			printf(" level %d.", position->s_level);
X
X			if(position == this)
X				putchar('<');
X			putchar('\n');
X		}
X	}
X	return (this != 0);
X}
X
Xscorer()
X{
X	static char tels[6];
X	if(free_teleports != old_free) {
X		if(free_teleports > free_per_level) {
X			(void) sprintf(tels,"%d+%d",
X				       free_per_level,
X				       free_teleports-free_per_level);
X		} else {
X			(void) sprintf(tels,"%d",free_teleports);
X		}
X		old_free = free_teleports;
X	}
X	move(LINES-1,0);
X	clrtoeol();
X	printw("<%s> level: %d    score: %ld",tels,LEVEL,score);
X        mvprintw(LINES-1,RVPOS,"heaps:%3d robots:%3d value: %d",
X					scrap_heaps,nrobots_alive,robot_value);
X	clrtoeol();
X}
X
END_OF_FILE
if test 5431 -ne `wc -c <'score.c'`; then
    echo shar: \"'score.c'\" unpacked with wrong size!
fi
# end of 'score.c'
fi
if test -f 'torus.6' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'torus.6'\"
else
echo shar: Extracting \"'torus.6'\" \(4302 characters\)
sed "s/^X//" >'torus.6' <<'END_OF_FILE'
X.TH TORUS 6 "30 January 1990"
X.SH NAME
Xtorus \- a game of logic
X.SH SYNOPSIS
X.B /usr/games/torus
X.RB [-c] [-s] [+-h] [+-v] [+-w]
X.SH DESCRIPTION
X.B Torus
Xis a display-based game which must be played on a CRT terminal
Xfrom among those supported by vi(1).  This is a topologically
Xenhanced version of the game Robots.
XThe object of the game is to avoid the robots:
Xcausing them to collide with each other, creating a
X.IR scrap\ heap .
XRobots are also destroyed if they run into a
X.IR scrap\ heap .
X.PP
XThe current version supports non-planar games.  Orientation-
Xpreserving identifications of the sides may be made independently
Xin both directions.  The default playing field is a flat torus.
X.PP
XYou are represented on the screen by a '@' sign.
XThe robots are represented by `+' and `#' signs.
XScrap heaps are represented by `*' signs.
XAfter each move, all robots move one step towards you except for
Xthe `#' robots which move at twice the speed of normal robots.
X.PP
XThe following commands are recognized:
X.IP h
XMove left.
X.IP l
XMove right.
X.IP j
XMove down.
X.IP k
XMove up.
X.IP y
XMove up and left.
X.IP u
XMove up and right.
X.IP b
XMove down and left.
X.IP n
XMove down and right.
X.IP .
X.IP w
XDo nothing.
X.IP t
XTeleport to a safe square if possible (limited in number).
X.IP r
XTeleport to a random position.
X.IP a
XAntimatter, all robots one square away from you vanish.
X.IP s
X.IP W
XSit and watch.
X.IP d
XDisplay dots.
X.IP m
XPrint list of `safe' moves (if using the 'wimpy' option). 
X.IP M
XTurn on or off the continuous display of `safe' moves.
X.IP ?
XSame as above.
X.IP q
XQuit game.
X.IP ^R
XRedraw the screen.
X.IP ^Z
XSuspend the game, on systems which support it.
X.IP ^W
XSit and watch while safe to do so.
X.PP
XA command may be preceeded by a count where relevant.
X.I Shift\-direction
Xmoves as far as possible in that direction.
X.I Control\-direction
Xmoves until adjacent to something.
X.PP
XA record is kept of the personal best scores of each player:
Xone for the current week and one for all time.
XScores are printed out at the end of the game.
XThe scores can be printed out with the '\-s' parameter.
X.SH OPTIONS
XThe following command line options can be used to override
Xthe environment settings:
X.TP
X.B \-s
XDisplay the high scores.
X.TP
X.B \-c
XPlay continuously -- no pauses between games.
X.TP
X.B \+h
XIdentify the left and right edges of the screen.
X.TP
X.B \-h
XDo not identify the left and right edges of the screen.
X.TP
X.B \+\/\-v
XSame as above, but controls the top and bottom edges.
X.TP
X.B \+\/\-w
XTurn on or off the Wimp setting (view legal moves).
X.SH CONFIGURATION
XIf you have in your environment the variable
X.I ROBOTOPTS
Xthen this is examined for a comma separated list of options to be set.
XBinary options can be preceeded with `no' to reverse the meaning.
XValid options are
X.IP name=string
XSet your name to the given string, this is recorded in the high
Xscore table. Your name appears as `string (username)'.
X.IP moveheaps
XMake the scrap heaps movable. If heaps are movable, then
Xa scrap heap can be pushed in any direction provided there is nothing
Xbehind the heap. This may or may not be the default.
X.IP showhscores
XThis option shows the highscore table after every game. The
Xnegated version will only print out the highscore only if you appear
Xon it.
X.IP continuous
XPlay continuously without pauses between games.
X.IP hsew
XThis option identifies the left and right horizontal borders of the playing
Xfield.  'vsew' is also available.
X.IP wimpy/studly
XThese options control the ability to display legal moves.
X.SH NOTE
XThe first time the `t' command is used on a new level
Xyou are guaranteed not to land next to a robot, a count of
Xthese `safe' teleports is maintained in the bottom left hand corner.
X`Antimatters' use up a `safe' teleport.
X.br
XAn asterisk in the first set of scores indicates an out-of-date entry.
X.br
XThe value of each robot in the next round is inversely
Xproportional to the
Xnumber of scrap heaps created in the previous round.
XDouble speed robots count 1.5 times the value of normal robots.
X.SH FILES
X.nf
X/usr/games/lib/robots_tmp	this week's best scores
X/usr/games/lib/robots_hof	all time best scores
X.fi
X.SH AUTHOR
XAllan Black, Strathclyde University, Glasgow.
X.br
XEnhancements by Graeme Lunt & Julian Onions, Nottingham University.
X.br
XTopological enhancements by Tad White.
X
END_OF_FILE
if test 4302 -ne `wc -c <'torus.6'`; then
    echo shar: \"'torus.6'\" unpacked with wrong size!
fi
# end of 'torus.6'
fi
if test -f 'user.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'user.c'\"
else
echo shar: Extracting \"'user.c'\" \(4626 characters\)
sed "s/^X//" >'user.c' <<'END_OF_FILE'
X# include "robots.h"
X
X/*
X * user.c: user oriented things
X */
X
Xcommand()  /* whats the user trying to tell us */
X{
Xretry:
X  if (all_moves && wimpy) good_moves();
X  move(my_y,my_x);
X  refresh();
X  if(last_stand) return;
X  bad_move = FALSE;
X  switch(cmd_ch=read_com()) {
X  case '.':
X  case 'h':
X  case 'j':
X  case 'k':
X  case 'l':
X  case 'y':
X  case 'u':
X  case 'b':
X  case 'n':
X  case 'w':
X    do_move(cmd_ch);
X    break;
X  case 't':
X  case 'r':
X  case 'T':
X  case 'R':
X  teleport:
X    new_x = rndx();
X    new_y = rndy();
X    move(new_y,new_x);
X    switch(inch()) {
X    case FROBOT:
X    case ROBOT:
X    case SCRAP:
X    case ME:
X      goto teleport;
X    }
X    if( (free_teleports > 0)
X       && ((cmd_ch == 't')||(cmd_ch =='T')) ) {
X      if( !isgood(new_y, new_x))
X        goto teleport;
X      free_teleports--;
X    }
X    break;
X  case 's':
X  case 'S':
X  case 'W':
X    last_stand = TRUE;
X    leaveok(stdscr,TRUE);
X    return;
X  case 'M':
X    all_moves = !all_moves;
X    goto retry;
X  case 'm':
X  case '?':
X    if (wimpy) good_moves();
X    else mvprintw(LINES-1,MSGPOS,"Be a stud!");
X    goto retry;
X  case 'd':
X  case 'D':
X    if(dots < 2) {
X      dots++;
X      put_dots();
X    } else {
X      erase_dots();
X      dots = 0;
X    }
X    goto retry;
X  case 'q':
X  case 'Q':
X    quit(FALSE);
X  case 'a':
X  case 'A':  /* Antimatter - sonic screwdriver */
X    if (free_teleports) { new_x = my_x;
X          new_y = my_y;
X          screwdriver();
X        }
X    else goto retry;
X    break;
X  case ctrl('R'):
X    clearok(curscr,TRUE);
X    wrefresh(curscr);
X    goto retry;
X  default:
X    bad_move = TRUE;
X  }
X  if(bad_move) {
X    putchar(BEL);
X    refresh();
X    count = 0;
X    adjacent=FALSE;
X    waiting=FALSE;
X    first_move=FALSE;
X    goto retry;
X  }
X  first_move = FALSE;
X  if(dots) erase_dots();
X  mvaddch(my_y,my_x,' ');
X  my_x = new_x;
X  my_y = new_y;
X  move(my_y,my_x);
X  if((inch() == ROBOT)||(inch() == FROBOT)) dead=TRUE;
X  else {
X    if(dots) put_dots();
X    mvaddch(my_y,my_x,ME);
X    refresh();
X  }
X}
X
Xread_com()
X{
X  static int     com;
X
X  if(count == 0) {
X    if(isdigit(com = readchar())) {
X      count = com-'0';
X      while(isdigit(com = readchar()))
X        count = count*10+com-'0';
X    }
X    else { /* rfs -- eliminate possible infinite loop when running */
X      switch (com) {
X	case ctrl('W'):
X	  /* com |= 0040; */
X	  waiting=TRUE;
X	case ctrl('H'):
X	case ctrl('J'):
X	case ctrl('K'):
X	case ctrl('L'):
X	case ctrl('Y'):
X	case ctrl('U'):
X	case ctrl('B'):
X	case ctrl('N'):
X	  com |= 0100;
X	  adjacent = TRUE;
X	  first_move=TRUE;
X      }
X      switch (com) {
X	case 'H':
X	case 'L':
X	  count = WIDTH;
X	  com |= 0040;
X	  first_move=TRUE;
X	  break;
X	case 'J':
X	case 'K':
X	  count = HEIGHT;
X	  com |= 0040;
X	  first_move=TRUE;
X	  break;
X	case 'Y':
X	case 'U':
X	case 'N':
X	case 'B':
X        case 'W':
X	  { /* set count to the least common multiple of WIDTH and HEIGHT */
X	    int w=WIDTH, h=HEIGHT,t;
X	    while (w>h) {
X	      t=w-h;
X	      if (t<h) { w=h; h=t; }
X	      else w=t;
X	      }
X	    count=(WIDTH/w)*HEIGHT;
X	  }
X	  com |= 0040;
X	  first_move=TRUE;
X	  break;
X	default:
X	  count=0;
X	  break;
X	}
X    }
X  }
X  if(count > 0) count--;
X  return(com);
X}
X
Xdo_move(dir)  /* implement the users move */
X  char dir;
X{
X  register int x, y;
X  new_x = hbound(my_y+yinc(dir),my_x+xinc(dir));
X  new_y = vbound(my_y+yinc(dir),my_x+xinc(dir));
X  if(adjacent && !first_move) {
X    for(x = -2; x <= 2; x++) {
X      for(y = -2; y <= 2; y++) {
X        tmove(new_y+y ,new_x+x);
X        switch(inch()) {
X        case SCRAP:
X          if( waiting )
X            break;
X        case ROBOT:
X          if(abs(x) < 2 && abs(y) < 2) {
X            bad_move = TRUE;
X            return;
X          }
X          else break;
X        case FROBOT:
X          if (waiting &&
X            blocked(new_y, new_x, y, x) )
X            break;
X          bad_move = TRUE;
X          return;
X        }
X      }
X    }
X  }
X  move(new_y,new_x); /* already bounded */
X  switch(inch()) {
X  case SCRAP:
X    if(moveable_heaps && move_heap(dir)) break;
X    else {
X      bad_move = TRUE;
X      return;
X    }
X  case VERT:
X    if (hsew||hrev) break; 
X    else {
X      bad_move = TRUE;
X      return;
X    }
X  case HORIZ:
X    if (vsew||vrev) break;
X    else {
X      bad_move = TRUE;
X      return;
X    }
X  }
X}
X
Xmove_heap(dir)  /* push a scrap heap */
Xchar  dir;
X{
X  register int  x, y;
X
X  x = hbound(new_y + yinc(dir),new_x + xinc(dir));
X  y = vbound(new_y + yinc(dir),new_x + xinc(dir));
X  move(y, x);
X  switch(inch()) {
X    case VERT:
X    case HORIZ:
X    case SCRAP:
X    case ROBOT:
X    case FROBOT:
X      return FALSE;
X  }
X  addch(SCRAP);
X  mvaddch(new_y,new_x,' ');
X  return TRUE;
X}
END_OF_FILE
if test 4626 -ne `wc -c <'user.c'`; then
    echo shar: \"'user.c'\" unpacked with wrong size!
fi
# end of 'user.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    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