[comp.sources.games] v06i081: tt - Tetris for ordinary terminals, Part02/02

billr@saab.CNA.TEK.COM (Bill Randle) (06/21/89)

Submitted-by: Mike Taylor <mirk@cs.warwick.ac.uk>
Posting-number: Volume 6, Issue 81
Archive-name: tt/Part02

#! /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 2 (of 2)."
# Contents:  Logo Makefile game.h pieces.h screen.h tt.h ttscores
#   utils.c utils.h
# Wrapped by billr@saab on Wed Jun 21 07:25:47 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Logo' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Logo'\"
else
echo shar: Extracting \"'Logo'\" \(804 characters\)
sed "s/^X//" >'Logo' <<'END_OF_FILE'
XNew from Mirksoft ... "tt" ... An Implementation for Terminals of ...
X
X       ________	 ________  ________  _______   ________	  _______
X       %%%%%%%%	 %%%%%%%%  %%%%%%%%  %%%%%%%_  %%%%%%%%	 _%%%%%%%
X	  %%	 %%	      %%     %%	   %%	  %%	 %%
X	  %%	 %%___	      %%     %%____%%	  %%	 %%_____ 
X	  %%	 %%%%%	      %%     %%%%%%_	  %%	  %%%%%%_ 
X	  %%	 %%	      %%     %%	  %%_	  %%	       %%
X	  %%	 %%______     %%     %%	   %%  ___%%___	 ______%%
X	  %%	 %%%%%%%%     %%     %%	   %%  %%%%%%%%	 %%%%%%%
X	 //	////////     //	    //	  //  ////////	///////
X	//     //	    //	   //	//	//	     //
X       //     /////	   //	  //////       //      //////
X      //     //		  //	 //    //     //     //
X  ////////  ////////  ////////	///////	  ////////   ///////
X
X	(Thanks to the Chief Slime Monster for the Logo)
END_OF_FILE
if test 804 -ne `wc -c <'Logo'`; then
    echo shar: \"'Logo'\" unpacked with wrong size!
fi
# end of 'Logo'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(1170 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# Makefile for "tt" - Tetris for Terminals (ie. not just workstations)
X# ====================================================================
X
XSOURCES = tt.c utils.c screen.c pieces.c game.c
XHEADERS = tt.h utils.h screen.h pieces.h game.h 
XOBJECTS = tt.o utils.o screen.o pieces.o game.o
X
XLDFLAGS =
XCFLAGS =
XLINTFLAGS =	-abh -DLINT
XLIBRARIES =	-lcurses -ltermcap
XTIDYUP =	| egrep -v 'possible pointer alignment problem' \
X		| egrep -v 'long assignment may lose accuracy'
X
X# ---------------------------------------------------------------------------
X
Xtt		: $(OBJECTS)
X		  $(CC) $(LDFLAGS) $(CFLAGS) $(OBJECTS) -o tt $(LIBRARIES)
X
Xttl		:
X		  lint $(LINTFLAGS) $(SOURCES) $(TIDYUP)
X
Xlint		:
X		  lint $(LINTFLAGS) $(SOURCES)
X
Xtags		:
X		  etags *.[ch]
X
Xclean		:
X		  rm -f *.o tt a.out core
X
X# --------------------------------------------------------------------------
X
Xtt.o		: tt.c tt.h utils.h screen.h game.h
X
Xutils.o		: utils.c utils.h tt.h screen.h
X
Xscreen.o	: screen.c screen.h tt.h pieces.h utils.h
X
Xpieces.o	: pieces.c pieces.h tt.h
X
Xgame.o		: game.c game.h tt.h screen.h pieces.h utils.h
X
X# --------------------------------------------------------------------------
END_OF_FILE
if test 1170 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'game.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'game.h'\"
else
echo shar: Extracting \"'game.h'\" \(2019 characters\)
sed "s/^X//" >'game.h' <<'END_OF_FILE'
X/***************************************************************************\
X|*									   *|
X|*  game.h:	A version of Tetris to run on ordinary terminals,	   *|
X|*		(ie., not needing a workstation, so should available	   *|
X|*		to peasant Newwords+ users.  This is the module that	   *|
X|*		actually plays the game, (ie. moves things down the	   *|
X|*		screen, select(2)s on the keyboard, and so on)		   *|
X|*									   *|
X|*  Author:	Mike Taylor (mirk@uk.ac.warwick.cs)			   *|
X|*  Started:	Fri May 26 12:26:05 BST 1989				   *|
X|*									   *|
X\***************************************************************************/
X
X#define LEFT_KEY	','	/* Move piece left */
X#define RIGHT_KEY	'/'	/* Move piece right */
X#define ROTATE_KEY	'.'	/* Rotate piece anticlockwise */
X#define DROP_KEY	' '	/* Drop piece to bottom of screen */
X#define SUSP_KEY	's'	/* Suspend.  I'm sorry if its confusing */
X#define QUIT_KEY	'q'	/* Quit.  I'm sorry if its confusing */
X#define CHEAT_KEY	'Z'	/* Cheat (a bit) -- Might not help! */
X
X#define REFRESH_KEY	'\014'	/* Control-L; refreshes screen */
X				/* This is hard-coded in.  It can't */
X				/* be changed by setting TTKEYS, since */
X				/* the peasants couldn't handle all that */
X				/* "setenv TTKEYS `echo | tr`" carp(anag) */
X
X#define NO_MOVES 4		/* Number of moves allowed per fall */
X
X/*-------------------------------------------------------------------------*/
X
Xextern char left_key;		/* Move piece left */
Xextern char right_key;		/* Move piece right */
Xextern char rotate_key;		/* Rotate piece anticlockwise */
Xextern char drop_key;		/* Drop piece to bottom of screen */
Xextern char susp_key;		/* Suspend.  I'm sorry if its confusing */
Xextern char quit_key;		/* Quit.  I'm sorry if its confusing */
Xextern char cheat_key;		/* Frogging identical comments :-P */
X
X/*-------------------------------------------------------------------------*/
X
Xextern void clear_board ();
Xextern void play_game ();
X
X/*-------------------------------------------------------------------------*/
END_OF_FILE
if test 2019 -ne `wc -c <'game.h'`; then
    echo shar: \"'game.h'\" unpacked with wrong size!
fi
# end of 'game.h'
fi
if test -f 'pieces.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pieces.h'\"
else
echo shar: Extracting \"'pieces.h'\" \(843 characters\)
sed "s/^X//" >'pieces.h' <<'END_OF_FILE'
X/***************************************************************************\
X|*									   *|
X|*  pieces.h:	A version of Tetris to run on ordinary terminals,	   *|
X|*		(ie., not needing a workstation, so should available	   *|
X|*		to peasant Newwords+ users.  This module contains the	   *|
X|*		definitions of the pieces.				   *|
X|*									   *|
X|*  Author:	Mike Taylor (mirk@uk.ac.warwick.cs)			   *|
X|*  Started:	Fri May 26 12:26:05 BST 1989				   *|
X|*									   *|
X\***************************************************************************/
X
Xstruct piece {
X  char app[3];
X  int points;
X  int index[NO_ORIENTS][NO_SQUARES][NO_DIMS];
X};
X
X/*-------------------------------------------------------------------------*/
X
Xextern struct piece pieces[NO_PIECES];
X
X/*-------------------------------------------------------------------------*/
END_OF_FILE
if test 843 -ne `wc -c <'pieces.h'`; then
    echo shar: \"'pieces.h'\" unpacked with wrong size!
fi
# end of 'pieces.h'
fi
if test -f 'screen.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'screen.h'\"
else
echo shar: Extracting \"'screen.h'\" \(1347 characters\)
sed "s/^X//" >'screen.h' <<'END_OF_FILE'
X/***************************************************************************\
X|*									   *|
X|*  screen.h:	A version of Tetris to run on ordinary terminals,	   *|
X|*		(ie., not needing a workstation, so should available	   *|
X|*		to peasant Newwords+ users.  This module handles all	   *|
X|*		the icky curses(3x) bits.				   *|
X|*									   *|
X|*  Author:	Mike Taylor (mirk@uk.ac.warwick.cs)			   *|
X|*  Started:	Fri May 26 12:26:05 BST 1989				   *|
X|*									   *|
X\***************************************************************************/
X
X#define WALL_CHAR	'|'	/* Character used for sides of pay-area */
X#define FLOOR_CHAR	'='	/* Character used for base-line */
X#define CORNER_CHAR	'+'	/* Character used bottom left and right */
X#define BLANK_CHAR	' '	/* Character used elsewhere */
X
X#define PD_DRAW		0	/* Code to draw piece */
X#define PD_ERASE	1	/* Code to erase piece */
X
X/*-------------------------------------------------------------------------*/
X
Xextern void myrefresh ();
Xextern void hoopy_refresh ();
Xextern void print_msg ();
Xextern void clear_area ();
Xextern void setup_screen ();
Xextern void setup_curses ();
Xextern void update_scores ();
Xextern void draw_board ();
Xextern void draw_piece ();
Xextern void place_piece ();
Xextern int can_place ();
X
X/*-------------------------------------------------------------------------*/
END_OF_FILE
if test 1347 -ne `wc -c <'screen.h'`; then
    echo shar: \"'screen.h'\" unpacked with wrong size!
fi
# end of 'screen.h'
fi
if test -f 'tt.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tt.h'\"
else
echo shar: Extracting \"'tt.h'\" \(6693 characters\)
sed "s/^X//" >'tt.h' <<'END_OF_FILE'
X/***************************************************************************\
X|*									   *|
X|*  tt.h:	A version of Tetris to run on ordinary terminals,	   *|
X|*		(ie., not needing a workstation, so should available	   *|
X|*		to peasant Newwords+ users.				   *|
X|*									   *|
X|*  Author:	Mike Taylor (mirk@uk.ac.warwick.cs)			   *|
X|*  Started:	Fri May 26 12:26:05 BST 1989				   *|
X|*									   *|
X\***************************************************************************/
X/***************************************************************************\
X|*									   *|
X|*  The following macro, if defined, causes the exclusive high-score	   *|
X|*  file-locking to be done using lockf(3) instead of the O_EXCL flag	   *|
X|*  on open(2).	 This means that no temporary file need be created, and	   *|
X|*  thus, that no write-permission is needed on a lockfile-directory.	   *|
X|*  This should probably be used in preference to open(O_EXCL) when it	   *|
X|*  exists and is bugless.  WARNING: on some machines, buggy versions	   *|
X|*  of lockf(3) can crash the machine, (eg. Sun3/4s running SunOS 4.0.1)   *|
X|*									   *|
X\***************************************************************************/
X
X#define LOCKF			/* Use lockf(3) instead of open(O_EXCL) */
X
X/***************************************************************************\
X|*									   *|
X|*  File in which high-scores will be stored.  I'm not gonna muck	   *|
X|*  about encrypting them or anything, so you can either make tt	   *|
X|*  setuid, or just run the risk of stupid people editing the high-	   *|
X|*  score table by hand.						   *|
X|*									   *|
X\***************************************************************************/
X
X#define LOCK_FILE	"/poppy/ma/ujf/open/lib/junk/ttlock"
X#define SCORE_FILE	"/poppy/ma/ujf/open/lib/ttscores"
X
X/*-------------------------------------------------------------------------*/
X
X#define NO_HISCORES	100	/* Size of high-score table */
X#define NO_SHOWN	10	/* Default number to print */
X#define LINELEN		160	/* Maximum length of a line of text */
X#define NAMELEN		24	/* Multiple of four for struct-padding */
X#define CODELEN		12	/* Multiple of four for struct-padding */
X
X#define GAME_WIDTH	10	/* Number of squares across board */
X#define GAME_DEPTH	20	/* Number of squares down board */
X#define STAT_WIDTH	37	/* Number of characters for messages */
X
X#define NO_PIECES	7	/* Number of different pieces */
X#define NO_ORIENTS	4	/* Number of orientations possible */
X#define NO_SQUARES	4	/* Max. number of squares per piece */
X#define NO_DIMS		2	/* Number of dimensions of screen */
X
X#define PI_EMPTY	-1	/* Position of board is empty */
X#define PI_SQUARE	0	/* Square piece */
X#define PI_LONG		1	/* Long piece */
X#define PI_ELL1		2	/* L-shaped piece */
X#define PI_ELL2		3	/* Backwards L-shaped piece */
X#define PI_TEE		4	/* T-shaped piece */
X#define PI_ESS1		5	/* S-shaped piece */
X#define PI_ESS2		6	/* Backwards S-shaped piece */
X
X/***************************************************************************\
X|*									   *|
X|*  The following #defines, (the LE_* ones) are local errors, in the	   *|
X|*  sense of being local to this program, as distinct from the system	   *|
X|*  errors, (ENOENT, EINTR and friends).  They should be used as exit	   *|
X|*  statuses, as the first argument to die(), defined in utils.c	   *|
X|*									   *|
X\***************************************************************************/
X
X#define LE_OK		0	/* No problems, me ole' fruit-bat */
X#define LE_USAGE	1	/* Command-line syntax was wrong */
X#define LE_ENV		2	/* Couldn't get environment variable */
X#define LE_TERMCAP	3	/* Couldn't get a termcap entry */
X#define LE_SCREEN	4	/* Screen was too small for game */
X#define LE_SIGNAL	5	/* Signal(3) call failed */
X#define LE_SELECT	6	/* Select(2) call failed */
X#define LE_READ		7	/* Read(2) call failed */
X#define LE_MALLOC	8	/* Couldn't allocate memory */
X#define LE_LEVEL	9	/* User wanted to play on a silly level */
X#define LE_OPEN		10	/* Open(2) call failed */
X#define LE_STAT		11	/* {f,l,}stat(2) call failed */
X#define LE_WRITE	12	/* write(2) call failed */
X#define LE_GETUID	13	/* getuid(2) call failed */
X#define LE_GETPW	14	/* getpwuid(3) call failed */
X
X/***************************************************************************\
X|*									   *|
X|*  This is the structure of which the high-score table is composed.	   *|
X|*  I'm gonna make everything a muliple of four bytes in an attempt	   *|
X|*  to maintain file-compatibility between sun3s and 4s (and maybe	   *|
X|*  other things, who knows?)  This is also why all the integers are	   *|
X|*  long -- this helps to ensure that they will be four bytes long on	   *|
X|*  most architectures, (ie. including some that have 2-byte integers)	   *|
X|*  thus making struct-compatibility more likely.			   *|
X|*									   *|
X\***************************************************************************/
X
Xstruct score_ent {
X  char name[NAMELEN];		/* Name of player (from environment) */
X  char code[CODELEN];		/* Code of player (from getpwuid()) */
X  long int score;		/* Total score (5 for an "S" etc.) */
X  long int no_pieces;		/* Number of pieces dropped in */
X  long int no_levels;		/* Number of levels completed */
X  long int game_level;		/* Number of free pieces at start */
X};
X
X/*-------------------------------------------------------------------------*/
X
Xextern int screen_depth;	/* To be calculated by termcap(3) */
Xextern int screen_width;	/* To be calculated by termcap(3) */
Xextern int so_gunk;		/* To be calculated by termcap(3) */
Xextern int in_curses;		/* Set to 1 after initialisation */
Xextern int rotate_backwards;	/* If set non-zero, rotate clockwise */
Xextern int no_hiscores;		/* Number of hi-scores in the table */
Xextern int game_level;		/* Number of free pieces */
Xextern int score;		/* Accumulated game score */
Xextern int no_pieces;		/* Number of pieces dropped so far */
Xextern int no_levels;		/* Number of levels filled & deleted */
Xextern char prog_name[LINELEN]; /* Will be the basename of argv[0] */
Xextern char user_name[NAMELEN]; /* From environment: TTNAME or NAME */
Xextern char user_code[CODELEN]; /* From getpwuid(getuid())->pw_name */
Xextern int board[GAME_DEPTH+4][GAME_WIDTH];
Xextern struct score_ent hi_scores[NO_HISCORES];
X
Xextern char tc_string[LINELEN]; /* Static, filled by termcap(3) */
Xextern char *so_str;		/* Points at things found by termcap(3) */
Xextern char *se_str;		/* Points at things found by termcap(3) */
X
X/*-------------------------------------------------------------------------*/
X
Xextern void signal_die ();	/* When CTRL-C etc. is pressed */
X
X/*-------------------------------------------------------------------------*/
END_OF_FILE
if test 6693 -ne `wc -c <'tt.h'`; then
    echo shar: \"'tt.h'\" unpacked with wrong size!
fi
# end of 'tt.h'
fi
if test -f 'ttscores' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ttscores'\"
else
echo shar: Extracting \"'ttscores'\" \(7172 characters\)
sed "s/^X//" >'ttscores' <<'END_OF_FILE'
XRuth 'Vashti' GlassboroXPaul CapperXXS ShipwayXHector the SpectreXMirk the ProgrammerXPaul 'Freddy' CapperXWarwick University EvanEND_OF_FILE
Xecho shar: 1 control character may be missing from \"'ttscores'\"
Xif test 3796 -ne `wc -c <'ttscores'`; then
X    echo shar: \"'ttscores'\" unpacked with wrong size!
Xfi
X# end of 'ttscores'
Xfi
Xif test -f 'utils.c' -a "${1}" != "-c" ; then 
X  echo shar: Will not clobber existing file \"'utils.c'\"
Xelse
Xecho shar: Extracting \"'utils.c'\" \(6633 characters\)
Xsed "s/^X//" >'utils.c' <<'END_OF_FILE'
X/***************************************************************************\
X|*									   *|
X|*  utils.c:	A version of Tetris to run on ordinary terminals,	   *|
X|*		(ie., not needing a workstation, so should available	   *|
X|*		to peasant Newwords+ users.  This module supplies all	   *|
X|*		the function that I will need, but which are not	   *|
X|*		intrinsically a part of Tetris itself.			   *|
X|*									   *|
X|*  Author:	Mike Taylor (mirk@uk.ac.warwick.cs)			   *|
X|*  Started:	Fri May 26 12:26:05 BST 1989				   *|
X|*									   *|
X\***************************************************************************/
X
X#include <varargs.h>
X#include <curses.h>
X#include <strings.h>
X#include <sys/types.h>
X#include <sys/time.h>
X#include <errno.h>
X
X#include "tt.h"
X#include "utils.h"
X#include "screen.h"
X
X/*-------------------------------------------------------------------------*/
X
Xextern char *rindex ();
Xextern char *getenv ();
X
X/***************************************************************************\
X|*									   *|
X|*  The function basename() acts like the UNIX(tm) command of the same	   *|
X|*  name.  It takes as its argument a string, and returns the last path-   *|
X|*  component of that string, (ie, the section after the last '/'), or	   *|
X|*  the whole string if it has no '/'.					   *|
X|*									   *|
X\***************************************************************************/
X
Xchar *basename (name)
X  char *name;
X{
X  char *slash;
X  if (slash = rindex (name, '/'))
X    return (slash+1);
X  else
X    return (name);
X}
X
X/***************************************************************************\
X|*									   *|
X|*  This is my home-made varargs-based version of C++'s neat function of   *|
X|*  the same name.  It saves all that tedious mucking about with static	   *|
X|*  buffers which you sprintf into, then forget all about, by basically	   *|
X|*  being a sprintf with its own statis storage.  It takes as arguments	   *|
X|*  exactly the same things as printf(3), and returns a pointer to the	   *|
X|*  resultant string.							   *|
X|*									   *|
X\***************************************************************************/
X
X/*VARARGS*/
Xchar *form (va_alist)
X  va_dcl
X{
X  va_list pvar;
X  char *fmt_string;
X  static char result[LINELEN];
X  
X  va_start (pvar);
X  fmt_string = va_arg (pvar, char*);
X  (void) vsprintf (result, fmt_string, pvar);
X  va_end (pvar);
X  return (result);
X}
X
X/***************************************************************************\
X|*									   *|
X|*  This is yer bog-standard "print a message and quit" function, except   *|
X|*  that it checks to see if we are in curses(3x), and if so, takes us	   *|
X|*  out before doing its stuff.	 The arguments are an integer, the exit	   *|
X|*  status, and a string containing an error report, to which will be	   *|
X|*  prepended the program name when it is printed.  If the status code	   *|
X|*  is LE_OK, (ie. nothing went wrong), no message is printed.		   *|
X|*									   *|
X\***************************************************************************/
X
Xvoid die (status, line)
X  int status;
X  char *line;
X{
X  if (in_curses) {
X    myrefresh ();
X#ifndef LINT
X    nocbreak ();
X    echo ();
X#endif /* LINT */
X    endwin ();
X  }
X
X  if (status != LE_OK)
X    (void) printf ("%s: %s\n", prog_name, line);
X
X#ifndef LOCKF
X  (void) unlink (LOCK_FILE);	/* Just in case :-) */
X#endif /* LOCKF */
X  exit (status);
X}
X
X/***************************************************************************\
X|*									   *|
X|*  The function get_termcap extracts the information we need from the	   *|
X|*  UNIX terminal capability database.	It has been (correctly) pointed	   *|
X|*  out that most of what I do in this function is already done for me	   *|
X|*  by curses(3x), but (A) curses behaves stupidly on terminals with	   *|
X|*  termcap's "sg" non-zero, (ie. refuses to enter standout mode, so	   *|
X|*  you *have* to do it manually), and (B) I wanted to prove a point to	   *|
X|*  Sunny and others, who said it was impossible.  Tgets() sucks :-P	   *|
X|*									   *|
X\***************************************************************************/
X
Xvoid get_termcap ()
X{
X  static char bp[1024];		/* Seems odd to hardwire the 1024, but ... */
X  char *term_name;		/* ... the manual entry told me to do it! */
X  int status;			/* Success/failure of tgetent here */
X  char *tmp_ptr = tc_string;	/* Pointer to be advanced by tgetstr() */
X
X  if ((term_name = getenv ("TERM")) == NULL)
X    die (LE_ENV, "couldn't get TERM from environment");
X
X  if ((status = tgetent (bp, term_name)) == -1)
X    die (LE_TERMCAP, "couldn't open TERMCAP file");
X
X  if (status == 0)
X    die (LE_TERMCAP, "couldn't find your terminal in TERMCAP file");
X
X  if ((screen_depth = tgetnum ("li")) == -1)
X    die (LE_TERMCAP, "couldn't get screen-depth from termcap");
X
X  if ((screen_width = tgetnum ("co")) == -1)
X    die (LE_TERMCAP, "couldn't get screen-width from termcap");
X
X  if ((so_gunk = tgetnum ("sg")) == -1)
X    so_gunk = 0;		/* Default value */
X
X  so_str = tmp_ptr;
X  if (tgetstr ("so", &tmp_ptr) == NULL)
X    die (LE_TERMCAP, "couldn't get standout code from termcap");
X
X  se_str = tmp_ptr;
X  if (tgetstr ("se", &tmp_ptr) == NULL)
X    die (LE_TERMCAP, "couldn't get standend code from termcap");
X}
X
X/***************************************************************************\
X|*									   *|
X|*  The function flush_keybord() checks to see whether there are any	   *|
X|*  keystrokes waiting to be read, and if so reads them and throws	   *|
X|*  them away.	Surprising how complex this needs to be, but the only	   *|
X|*  alternative I can think of is to ioctl() stdin to be non-blocking,	   *|
X|*  read() until it returns 0, then ioctl() it back, which is scarcely	   *|
X|*  an improvement.							   *|
X|*									   *|
X\***************************************************************************/
X
Xvoid flush_keyboard ()
X{
X  fd_set fds;			/* Will contain only stdin */
X  struct timeval timeout;	/* Will contain a zero timeout (poll) */
X  static char buffer[LINELEN];	/* Will be used as the buffer to read(2) */
X  int status;			/* Contains select(2)'s return value */
X
X  while (1) {
X    FD_ZERO (&fds);
X    FD_SET (0, &fds);
X    timeout.tv_sec = 0L;
X    timeout.tv_usec = 0L;
X    if (((status = select (1, &fds, (fd_set*) NULL, (fd_set*) NULL,
X			   &timeout)) == -1) && (errno != EINTR))
X      die (LE_SELECT, "select(2) failed in flush_keybord()");
X    if ((status == 0) || (status == -1))
X      break;			/* Can only be -1 if errno == EINTR */
X    (void) read (0, buffer, LINELEN);
X  }
X}
X
X/*-------------------------------------------------------------------------*/
END_OF_FILE
if test 7172 -ne `wc -c <'ttscores'`; then
    echo shar: \"'ttscores'\" unpacked with wrong size!
fi
# end of 'ttscores'
fi
if test -f 'utils.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'utils.c'\"
else
echo shar: Extracting \"'utils.c'\" \(6633 characters\)
sed "s/^X//" >'utils.c' <<'END_OF_FILE'
X/***************************************************************************\
X|*									   *|
X|*  utils.c:	A version of Tetris to run on ordinary terminals,	   *|
X|*		(ie., not needing a workstation, so should available	   *|
X|*		to peasant Newwords+ users.  This module supplies all	   *|
X|*		the function that I will need, but which are not	   *|
X|*		intrinsically a part of Tetris itself.			   *|
X|*									   *|
X|*  Author:	Mike Taylor (mirk@uk.ac.warwick.cs)			   *|
X|*  Started:	Fri May 26 12:26:05 BST 1989				   *|
X|*									   *|
X\***************************************************************************/
X
X#include <varargs.h>
X#include <curses.h>
X#include <strings.h>
X#include <sys/types.h>
X#include <sys/time.h>
X#include <errno.h>
X
X#include "tt.h"
X#include "utils.h"
X#include "screen.h"
X
X/*-------------------------------------------------------------------------*/
X
Xextern char *rindex ();
Xextern char *getenv ();
X
X/***************************************************************************\
X|*									   *|
X|*  The function basename() acts like the UNIX(tm) command of the same	   *|
X|*  name.  It takes as its argument a string, and returns the last path-   *|
X|*  component of that string, (ie, the section after the last '/'), or	   *|
X|*  the whole string if it has no '/'.					   *|
X|*									   *|
X\***************************************************************************/
X
Xchar *basename (name)
X  char *name;
X{
X  char *slash;
X  if (slash = rindex (name, '/'))
X    return (slash+1);
X  else
X    return (name);
X}
X
X/***************************************************************************\
X|*									   *|
X|*  This is my home-made varargs-based version of C++'s neat function of   *|
X|*  the same name.  It saves all that tedious mucking about with static	   *|
X|*  buffers which you sprintf into, then forget all about, by basically	   *|
X|*  being a sprintf with its own statis storage.  It takes as arguments	   *|
X|*  exactly the same things as printf(3), and returns a pointer to the	   *|
X|*  resultant string.							   *|
X|*									   *|
X\***************************************************************************/
X
X/*VARARGS*/
Xchar *form (va_alist)
X  va_dcl
X{
X  va_list pvar;
X  char *fmt_string;
X  static char result[LINELEN];
X  
X  va_start (pvar);
X  fmt_string = va_arg (pvar, char*);
X  (void) vsprintf (result, fmt_string, pvar);
X  va_end (pvar);
X  return (result);
X}
X
X/***************************************************************************\
X|*									   *|
X|*  This is yer bog-standard "print a message and quit" function, except   *|
X|*  that it checks to see if we are in curses(3x), and if so, takes us	   *|
X|*  out before doing its stuff.	 The arguments are an integer, the exit	   *|
X|*  status, and a string containing an error report, to which will be	   *|
X|*  prepended the program name when it is printed.  If the status code	   *|
X|*  is LE_OK, (ie. nothing went wrong), no message is printed.		   *|
X|*									   *|
X\***************************************************************************/
X
Xvoid die (status, line)
X  int status;
X  char *line;
X{
X  if (in_curses) {
X    myrefresh ();
X#ifndef LINT
X    nocbreak ();
X    echo ();
X#endif /* LINT */
X    endwin ();
X  }
X
X  if (status != LE_OK)
X    (void) printf ("%s: %s\n", prog_name, line);
X
X#ifndef LOCKF
X  (void) unlink (LOCK_FILE);	/* Just in case :-) */
X#endif /* LOCKF */
X  exit (status);
X}
X
X/***************************************************************************\
X|*									   *|
X|*  The function get_termcap extracts the information we need from the	   *|
X|*  UNIX terminal capability database.	It has been (correctly) pointed	   *|
X|*  out that most of what I do in this function is already done for me	   *|
X|*  by curses(3x), but (A) curses behaves stupidly on terminals with	   *|
X|*  termcap's "sg" non-zero, (ie. refuses to enter standout mode, so	   *|
X|*  you *have* to do it manually), and (B) I wanted to prove a point to	   *|
X|*  Sunny and others, who said it was impossible.  Tgets() sucks :-P	   *|
X|*									   *|
X\***************************************************************************/
X
Xvoid get_termcap ()
X{
X  static char bp[1024];		/* Seems odd to hardwire the 1024, but ... */
X  char *term_name;		/* ... the manual entry told me to do it! */
X  int status;			/* Success/failure of tgetent here */
X  char *tmp_ptr = tc_string;	/* Pointer to be advanced by tgetstr() */
X
X  if ((term_name = getenv ("TERM")) == NULL)
X    die (LE_ENV, "couldn't get TERM from environment");
X
X  if ((status = tgetent (bp, term_name)) == -1)
X    die (LE_TERMCAP, "couldn't open TERMCAP file");
X
X  if (status == 0)
X    die (LE_TERMCAP, "couldn't find your terminal in TERMCAP file");
X
X  if ((screen_depth = tgetnum ("li")) == -1)
X    die (LE_TERMCAP, "couldn't get screen-depth from termcap");
X
X  if ((screen_width = tgetnum ("co")) == -1)
X    die (LE_TERMCAP, "couldn't get screen-width from termcap");
X
X  if ((so_gunk = tgetnum ("sg")) == -1)
X    so_gunk = 0;		/* Default value */
X
X  so_str = tmp_ptr;
X  if (tgetstr ("so", &tmp_ptr) == NULL)
X    die (LE_TERMCAP, "couldn't get standout code from termcap");
X
X  se_str = tmp_ptr;
X  if (tgetstr ("se", &tmp_ptr) == NULL)
X    die (LE_TERMCAP, "couldn't get standend code from termcap");
X}
X
X/***************************************************************************\
X|*									   *|
X|*  The function flush_keybord() checks to see whether there are any	   *|
X|*  keystrokes waiting to be read, and if so reads them and throws	   *|
X|*  them away.	Surprising how complex this needs to be, but the only	   *|
X|*  alternative I can think of is to ioctl() stdin to be non-blocking,	   *|
X|*  read() until it returns 0, then ioctl() it back, which is scarcely	   *|
X|*  an improvement.							   *|
X|*									   *|
X\***************************************************************************/
X
Xvoid flush_keyboard ()
X{
X  fd_set fds;			/* Will contain only stdin */
X  struct timeval timeout;	/* Will contain a zero timeout (poll) */
X  static char buffer[LINELEN];	/* Will be used as the buffer to read(2) */
X  int status;			/* Contains select(2)'s return value */
X
X  while (1) {
X    FD_ZERO (&fds);
X    FD_SET (0, &fds);
X    timeout.tv_sec = 0L;
X    timeout.tv_usec = 0L;
X    if (((status = select (1, &fds, (fd_set*) NULL, (fd_set*) NULL,
X			   &timeout)) == -1) && (errno != EINTR))
X      die (LE_SELECT, "select(2) failed in flush_keybord()");
X    if ((status == 0) || (status == -1))
X      break;			/* Can only be -1 if errno == EINTR */
X    (void) read (0, buffer, LINELEN);
X  }
X}
X
X/*-------------------------------------------------------------------------*/
END_OF_FILE
if test 6633 -ne `wc -c <'utils.c'`; then
    echo shar: \"'utils.c'\" unpacked with wrong size!
fi
# end of 'utils.c'
fi
if test -f 'utils.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'utils.h'\"
else
echo shar: Extracting \"'utils.h'\" \(827 characters\)
sed "s/^X//" >'utils.h' <<'END_OF_FILE'
X/***************************************************************************\
X|*									   *|
X|*  utils.h:	A version of Tetris to run on ordinary terminals,	   *|
X|*		(ie., not needing a workstation, so should available	   *|
X|*		to peasant Newwords+ users.  This module supplies all	   *|
X|*		the function that I will need, but which are not	   *|
X|*		intrinsically a part of Tetris itself.			   *|
X|*									   *|
X|*  Author:	Mike Taylor (mirk@uk.ac.warwick.cs)			   *|
X|*  Started:	Fri May 26 12:26:05 BST 1989				   *|
X|*									   *|
X\***************************************************************************/
X
Xextern char *basename ();
Xextern char *form ();
Xextern void die ();
Xextern void get_termcap ();
Xextern void flush_keyboard ();
X
X/*-------------------------------------------------------------------------*/
END_OF_FILE
if test 827 -ne `wc -c <'utils.h'`; then
    echo shar: \"'utils.h'\" unpacked with wrong size!
fi
# end of 'utils.h'
fi
echo shar: End of archive 2 \(of 2\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0