games@tekred.CNA.TEK.COM (03/01/89)
Submitted-by: Martin Heidegger <vespa@ssyx.ucsc.edu> Posting-number: Volume 6, Issue 17 Archive-name: tetris/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: FILES Makefile check_block.c check_horiz.c csr.h cursive.c # display_high.c draw_shadow.c drop_block.c erase_horiz.c # get_level.c help.tetris redefine.c save_game.c score.c # score.tetris set_level.c setup_next.c tetris.h tetris.man useful.c # Wrapped by billr@saab on Tue Feb 28 12:49:59 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'FILES' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'FILES'\" else echo shar: Extracting \"'FILES'\" \(1751 characters\) sed "s/^X//" >'FILES' <<'END_OF_FILE' X You should have: X XMakefile: this is the makefile, it needs some modification of directory X names X Xtetris.man: this is the unix style manual page formatted in -man macros X you can modify the filenames in it to reflect where you X end up placing some of tetris' utility files. X Xhelp.tetris: this is the online help file, it will be moved by the makefile Xscore.tetris: this is the file that keeps score, it is not necessary that X it really exist, as tetris will make it if it doesn't exist X Xmonitor.tetris: this is the super snoopy big brother file, it tells the owner X of tetris who played, when they played and how they did. X this filename can be declared as "/dev/null" in the file X tetris.h and this will effectively turn the monitoring process X off. This file is like score.tetris, it doesn't have to exist X for tetris, as tetris will make it itself. I think that the X makefile will complain if these two files aren't around, X but no big deal, just touch the filenames. X Xcsr.h this is the include file for the cursor package I use X I don't use curses because it is too slow. This may X cause portability problems, but then I didn't concern X myself with that when I wrote tetris. X Xtetris.h this is the include file for tetris itself. You will need X to modify pathnames that are defined in this file or tetris X will not like you. I will trap for these nasties in the X future but right now I am too lazy. X XThe rest of the files are the source files, this is a manifest of them: X Xcheck_block.c Xcheck_horiz.c Xcsr.c Xcursive.c Xdefine_shapes.c Xdisplay_high.c Xdraw_shadow.c Xdrop_block.c Xend_game.c Xerase_horiz.c Xget_level.c Xinit_tetris.c Xmain.c Xprint_shape.c Xprocess_input.c Xredefine.c Xsave_game.c Xscore.c Xset_level.c Xsetup_next.c Xuseful.c END_OF_FILE if test 1751 -ne `wc -c <'FILES'`; then echo shar: \"'FILES'\" unpacked with wrong size! fi # end of 'FILES' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(1722 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# X# Makefile for tetris X# X# 2/23/89 X# X# adam margulies vespa@ssyx.ucsc.edu X# {...}!ucbvax!ucscc!ssyx!vespa X# X# makes: tetris debug install clean docs shar all new X# X# if this is a new installation use 'make new' X# X X# where the binary will go XDESTDIR = /usr/games X X# where the lib files go XLIBDIR = /usr/games/lib/tetris X X# where the documentation goes XDOCDIR = /usr/games/Doc X X# what the documentation is called XDOCNAME = tetris.doc X XINC = tetris.h csr.h X XOBJ = check_block.o\ X check_horiz.o\ X csr.o\ X cursive.o\ X define_shapes.o\ X display_high.o\ X draw_shadow.o\ X drop_block.o\ X end_game.o\ X erase_horiz.o\ X get_level.o\ X init_tetris.o\ X main.o\ X print_shape.o\ X process_input.o\ X redefine.o\ X save_game.o\ X score.o\ X set_level.o\ X setup_next.o\ X useful.o X Xtetris: $(OBJ) $(INC) X cc -O -s -o tetris $(OBJ) -ltermcap X chmod 2711 tetris X @echo "binary ready" X Xdebug: $(OBJ) $(INC) X cc -g -o tetris $(OBJ) -ltermcap X chmod 2711 tetris X @echo "debug binary ready" X Xinstall: X install tetris $(DESTDIR) X chmod 2711 $(DESTDIR)/tetris X X @echo "done" X Xclean: X /bin/rm -rf *.o tetris core nroff.out make.out X Xdocs: X @/bin/rm -rf nroff.out X nroff -man tetris.man > nroff.out X X @/bin/rm -rf $(DOCDIR)/$(DOCNAME) X mv nroff.out $(DOCDIR)/$(DOCNAME) X chmod 664 $(DOCDIR)/$(DOCNAME) X X @echo "docs ready" X Xshar: X @/bin/rm -rf ../tetris.shar X shar README FILES Makefile help.tetris score.tetris monitor.tetris\ X *.c *.h tetris.man > ../tetris.shar X X @echo "shar ready" X Xall: clean docs tetris X Xnew: all X @/bin/rm -rf $(LIBDIR)/{help, monitor, score}.tetris X @touch monitor.tetris X @touch score.tetris X mv {help, monitor, score}.tetris $(LIBDIR) X chmod 664 $(LIBDIR)/{help, monitor, score}.tetris X Xinit_tetris.o: tetris.h END_OF_FILE if test 1722 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'check_block.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'check_block.c'\" else echo shar: Extracting \"'check_block.c'\" \(3597 characters\) sed "s/^X//" >'check_block.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* Tetris: check_block() */ X/* */ X/* checks to make sure that the moving shape can proceed to the next */ X/* line on the screen. the function returns 0 if the shape can't move */ X/* on to the line below, 1 otherwise. */ X X#include "tetris.h" X Xint check_block() X{ X int x = curx, y = cury, sh = current->shape, rt = current->rot; X if (y > (21 - current->height)) /* reached bottom of screen */ X return(0); X X /* These lines check to make sure that the next line is clear */ X X if (shape[sh].table[3][rt] & 8 && X window0[y+4][x] != ' ') X return(0); X if (shape[sh].table[3][rt] & 4 && X window0[y+4][x+1] != ' ') X return(0); X if (shape[sh].table[3][rt] & 2 && X window0[y+4][x+2] != ' ') X return(0); X if (shape[sh].table[3][rt] & 1 && X window0[y+4][x+3] != ' ') X return(0); X X /* These lines check to make sure that line 2 of the shape doesn't snag */ X X if ((shape[sh].table[2][rt] & 8) && X (window0[y+3][x] != ' ' && X !(shape[sh].table[3][rt] & 8))) X return(0); X if (shape[sh].table[2][rt] & 4 && X (window0[y+3][x+1] != ' ' && X !(shape[sh].table[3][rt] & 4))) X return(0); X if (shape[sh].table[2][rt] & 2 && X (window0[y+3][x+2] != ' ' && X !(shape[sh].table[3][rt] & 2))) X return(0); X if (shape[sh].table[2][rt] & 1 && X (window0[y+3][x+3] != ' ' && X !(shape[sh].table[3][rt] & 1))) X return(0); X X /* These lines check to make sure that line 1 of the shape doesn't snag */ X X if (y > -1) { X if (shape[sh].table[1][rt] & 8 && X window0[y+2][x] != ' ' && X !(shape[sh].table[2][rt] & 8)) X return(0); X if (shape[sh].table[1][rt] & 4 && X (window0[y+2][x+1] != ' ' && X !(shape[sh].table[2][rt] & 4))) X return(0); X if (shape[sh].table[1][rt] & 2 && X (window0[y+2][x+2] != ' ' && X !(shape[sh].table[2][rt] & 2))) X return(0); X if (shape[sh].table[1][rt] & 1 && X (window0[y+2][x+3] != ' ' && X !(shape[sh].table[2][rt] & 1))) X return(0); X } X X /* These lines check to make sure that line 0 of the shape doesn't snag */ X X if (y > 0) { X if (shape[sh].table[0][rt] & 8 && X (window0[y+1][x] != ' ' && X !(shape[sh].table[1][rt] & 8))) X return(0); X if (shape[sh].table[0][rt] & 4 && X (window0[y+1][x+1] != ' ' && X !(shape[sh].table[1][rt] & 4))) X return(0); X if (shape[sh].table[0][rt] & 2 && X (window0[y+1][x+2] != ' ' && X !(shape[sh].table[1][rt] & 2))) X return(0); X if (shape[sh].table[0][rt] & 1 && X (window0[y+1][x+3] != ' ' && X !(shape[sh].table[1][rt] & 1))) X return(0); X } X X /* successful drop, return */ X return(1); X} END_OF_FILE if test 3597 -ne `wc -c <'check_block.c'`; then echo shar: \"'check_block.c'\" unpacked with wrong size! fi # end of 'check_block.c' fi if test -f 'check_horiz.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'check_horiz.c'\" else echo shar: Extracting \"'check_horiz.c'\" \(1212 characters\) sed "s/^X//" >'check_horiz.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* Tetris: check_horiz() */ X/* */ X/* this function is called after the shape has stopped and before a */ X/* new shape begins dropping. it checks to see if a horizontal line */ X/* is complete and if so calls erase_horiz() to erase it. */ X/* */ X#include "tetris.h" X Xvoid check_horiz() X{ X int i,j,flag; /* i and j are counters, flag is 0 if a row X is complete */ X X for (i = 2; i < 22; i++) { X flag = 0; X for (j=35; j<45; j++) { X if (window0[i][j] == ' ') X flag=1; X } X if (!flag) X erase_horiz(i); X } X} END_OF_FILE if test 1212 -ne `wc -c <'check_horiz.c'`; then echo shar: \"'check_horiz.c'\" unpacked with wrong size! fi # end of 'check_horiz.c' fi if test -f 'csr.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'csr.h'\" else echo shar: Extracting \"'csr.h'\" \(810 characters\) sed "s/^X//" >'csr.h' <<'END_OF_FILE' X#include <sgtty.h> X X#ifdef EXPANSION X#define MAX_X 132 X#define MAX_Y 48 X#else X#define MAX_X 80 X#define MAX_Y 24 X#endif X Xchar window0[MAX_Y][MAX_X]; Xchar window1[MAX_Y][MAX_X]; Xchar window2[MAX_Y][MAX_X]; X Xchar *tc_ce; Xchar *tc_cm; Xchar *tc_cl; Xchar *tc_up; Xchar *tc_do; Xint putch(); Xint _csrx, _csry, _rx, _ry; X X#define move(y,x) (_csry =y, _csrx =x) X#define mvaddch(y,x,ch) ((window1[y][x] = ch)) X#define addch(ch) window1[_csry][_csrx++] = ch X#define erase(y,x,n) tospaces(&window1[y][x], n) X X#define cls() (tputs(tc_cl, 0, putch)) X#define csr(row,col) (tputs(tgoto(tc_cm, col, row), 0, putch),\ X _csry = row, _csrx = col) X X#define stty(a,b) ioctl(a, TIOCSETN, b) X Xstruct sgttyb tty, orig_tty; Xstruct ltchars ltc, orig_ltc; Xstruct tchars tc, orig_tc; Xextern short ospeed; X END_OF_FILE if test 810 -ne `wc -c <'csr.h'`; then echo shar: \"'csr.h'\" unpacked with wrong size! fi # end of 'csr.h' fi if test -f 'cursive.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cursive.c'\" else echo shar: Extracting \"'cursive.c'\" \(1635 characters\) sed "s/^X//" >'cursive.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* Tetris: cursive() */ X/* Draws the word "Tetris" in cursive writing on the screen */ X#include "tetris.h" X Xvoid Xcursive() X{ X mvaddstr(0, 0, "_____ "); X mvaddstr(1, 0, " | _ ___ _ . _ "); X mvaddstr(2, 0, " | (_ | | ) | ( "); X mvaddstr(3, 0, " | (_ | | \\ | _) "); X mvaddstr(4, 0, " the addiction"); X X /* Capital T */ X csr_draw(0, 0, 0, 4); X csr_draw(1, 2, 1, 2); X csr_draw(2, 2, 2, 2); X csr_draw(3, 2, 3, 2); X X /* Little e */ X csr_draw(1, 5, 1, 5); X csr_draw(2, 4, 2, 4); X csr_draw(2, 5, 2, 5); X csr_draw(3, 4, 3, 4); X csr_draw(3, 5, 3, 5); X X /* Little t */ X csr_draw(1, 7, 1, 7); X csr_draw(1, 8, 1, 8); X csr_draw(1, 9, 1, 9); X csr_draw(2, 8, 2, 8); X csr_draw(3, 8, 3, 8); X X /* Little r */ X csr_draw(3, 11, 3, 11); X csr_draw(2, 11, 2, 11); X csr_draw(1, 12, 1, 12); X csr_draw(2, 13, 2, 13); X csr_draw(3, 11, 3, 15); X X /* Little i */ X csr_draw(2, 15, 2, 15); X csr_draw(3, 15, 3, 16); X X /* Little s */ X csr_draw(1, 18, 1, 18); X csr_draw(2, 17, 2, 17); X csr_draw(3, 18, 3, 18); X csr_draw(3, 17, 3, 17); X X csr_draw(1, 15, 1, 15); X X csr_draw(4, 0, 4, 26); X} END_OF_FILE if test 1635 -ne `wc -c <'cursive.c'`; then echo shar: \"'cursive.c'\" unpacked with wrong size! fi # end of 'cursive.c' fi if test -f 'display_high.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'display_high.c'\" else echo shar: Extracting \"'display_high.c'\" \(1556 characters\) sed "s/^X//" >'display_high.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* X** display_high.c X** X** Displays the high score list X** X*/ X#include "tetris.h" X Xdisplay_high() X{ X FILE *fp, *fopen(); X int counter, i; X X cls(); X mvaddstr(0,15," _____ ____ _____ ____ __ ____"); X mvaddstr(1,15,"/\\ \\ /\\ \\/\\ \\ /\\ \\ /\\ \\ /\\ \\"); X mvaddstr(2,15,"\\/_ _// / __/\\/_ _// / // / // / __/"); X mvaddstr(3,15,"/ / / / / __/ / / / / / _// / //\\/_ /"); X mvaddstr(4,15,"\\/_/ \\/___/ \\/_/ \\/___\\ \\/_/ \\/___/"); X X csr_draw(0,14,4,60); X resetty(); X X printf("\n"); X printf("\n"); X X if ((fp = fopen(HIGHSCOREFILE, "r")) == NULL){ X SIGHOLD(14); X cls(); X csr(23,0); X resetty(); X fprintf(stderr, "%s\n", HIGHSCOREFILE); X perror("opening highscore file"); X exit(3); X } X X flock(fileno(fp), LOCK_EX); X for(counter=0;counter<15;counter++){ X fscanf(fp, "%d\n", &high_score[counter]); X fscanf(fp, "%s\n", high_user[counter]); X fgets(high_name[counter], 255, fp); X for (i=0; i<255; i++) X if (high_name[counter][i] == '\n') X high_name[counter][i] = '\0'; X printf(" %2.2d. %7.7d %40.40s (%s) \n", counter+1, X high_score[counter], high_name[counter], high_user[counter]); X } X flock(fileno(fp), LOCK_UN); X fclose(fp); X} END_OF_FILE if test 1556 -ne `wc -c <'display_high.c'`; then echo shar: \"'display_high.c'\" unpacked with wrong size! fi # end of 'display_high.c' fi if test -f 'draw_shadow.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'draw_shadow.c'\" else echo shar: Extracting \"'draw_shadow.c'\" \(655 characters\) sed "s/^X//" >'draw_shadow.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* Tetris: draw_shadow.c X** X** draws the shadow of the block at row 21 X** X*/ X#include "tetris.h" X Xvoid draw_shadow() { X X int i; X X for(i=35; i<45; i++) { X if ( i >= (curx + (xoffset ? 1 : 0)) && X i < (curx + current->width + (xoffset ? 1 : 0)) ) X mvaddch(22,i,'='); X else mvaddch(22,i,'-'); X } X csr_draw(22,35,22,44); X} END_OF_FILE if test 655 -ne `wc -c <'draw_shadow.c'`; then echo shar: \"'draw_shadow.c'\" unpacked with wrong size! fi # end of 'draw_shadow.c' fi if test -f 'drop_block.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'drop_block.c'\" else echo shar: Extracting \"'drop_block.c'\" \(2848 characters\) sed "s/^X//" >'drop_block.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* Tetris: drop_block() */ X/* */ X/* This function calls check_block() to make sure that the block */ X/* can drop down the screen. If so it increments the current y */ X/* position and calls print_shape() with a "color" of ' '. This */ X/* erases the shape. If the player has not requested */ X/* a "fast drop" or the block has reached the bottom then the */ X/* function draws the shape with a call to print_shape() and returns. */ X/* */ X/* If check_block() shows that the shape has been blocked then it gets */ X/* trickier. If the current y position is too high then the game is */ X/* over (i.e. the player has not successfully negotiated the block */ X/* past the top of the screen). A call to score() updates the score */ X/* and a call to end_game() terminates the program. */ X/* */ X/* If the above is false then the program knows that the block has */ X/* successfully come to rest. The call to score() is made to record */ X/* the score and check_horiz() is called to clear any complete horiz */ X/* lines then setup_next() is called to ready the next block. */ X#include "tetris.h" X#include <sys/ioctl.h> X Xvoid drop_block() X{ X void end_game(), check_horiz(); X int num_char_pend; X X ioctl(1, TIOCOUTQ, &num_char_pend); /* this checks the number of characters X pending on the terminal */ X X if (num_char_pend != 0) X return; X X if (check_block()) { X cury++; X print_shape(current->shape, curx, cury-1, current->rot, ' '); X if (!fast_drop || (cury + current->height == 22)) X print_shape(current->shape, curx, cury, current->rot, X current->color); X } X else { X if (cury < 2) { X if (fast_drop) X print_shape(current->shape, curx, cury, current->rot, X current->color); X score(cury + current->height - 1); X end_game(); X } X else { X if (fast_drop) X print_shape(current->shape, curx, cury, current->rot, X current->color); X score(cury + current->height - 1); X check_horiz(); X setup_next(); X } X } X X} END_OF_FILE if test 2848 -ne `wc -c <'drop_block.c'`; then echo shar: \"'drop_block.c'\" unpacked with wrong size! fi # end of 'drop_block.c' fi if test -f 'erase_horiz.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'erase_horiz.c'\" else echo shar: Extracting \"'erase_horiz.c'\" \(1218 characters\) sed "s/^X//" >'erase_horiz.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* Tetris: erase_horiz.c */ X/* */ X/* Upon being called by check_horiz() this function updates the */ X/* window array to erase the completed horizontal row. */ X/* It also increments the level for every tenth row that is eaten. */ X#include "tetris.h" X Xerase_horiz(row) Xint row; X{ X int i,j; X X if (row>2) X for(i=row-1; i>1; i--) X for(j=35; j<45; j++) X window1[i+1][j] = window1[i][j]; X for(j=35; j<45; j++) X window1[2][j] = ' '; X X X csr_draw(2,35,row,44); X X move(1,65); X printc("lines: %3.3d", ++lines); X if(lines && !(lines % 10) && ((lines/10) > level)) { X move(2,65); X printc("level: %2.2d", ++level); X next->color = '0' + (level % 10); X set_level(); X } X csr_draw(1,65,2,79); X} END_OF_FILE if test 1218 -ne `wc -c <'erase_horiz.c'`; then echo shar: \"'erase_horiz.c'\" unpacked with wrong size! fi # end of 'erase_horiz.c' fi if test -f 'get_level.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'get_level.c'\" else echo shar: Extracting \"'get_level.c'\" \(3558 characters\) sed "s/^X//" >'get_level.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* get_level.c X** X** Gets the level the user prefers to start on and also gets the users X** preference on "rubble" and generates the "rubble". Rubble is random X** stuff put on the playing field to spice up the game at the beginning. X*/ X#include "tetris.h" X Xvoid get_level() X{ X int i; X save_screen(5,19,16,62); X clear(5,19,16,62); X X mvaddstr(05,19, "+-----------------------------------------+"); X mvaddstr(06,19, "| Starting level: |"); X mvaddstr(15,19, "| [hjkl] to move, [space] to toggle |"); X for(i=7; i<15; i++) X mvaddstr(i,19,"| |"); X mvaddstr(11,19, "| Rows of obstacles: |"); X mvaddstr(16,19,"+-----------------------------------------+"); X X mvaddstr(07,21,"**** **** **** **** **** **** **** ****"); X mvaddstr(08,21,"*00* *01* *03* *05* *07* *09* *11* *13*"); X mvaddstr(09,21,"**** **** **** **** **** **** **** ****"); X X mvaddstr(12,21,"**** **** **** **** **** **** **** ****"); X mvaddstr(13,21,"*00* *01* *03* *05* *07* *09* *11* *13*"); X mvaddstr(14,21,"**** **** **** **** **** **** **** ****"); X X read_input(); X X restore_screen(5,19,16,62); X X} X Xread_input() X{ X int x = 0; X int y = 8; X char c; X X mvaddstr(7, 21, "++++"); X mvaddch(8, 21, '+'); X mvaddch(8, 24, '+'); X mvaddstr(9, 21, "++++"); X X mvaddstr(12, 21,"++++"); X mvaddch(13,21, '+'); X mvaddch(13,24, '+'); X mvaddstr(14, 21,"++++"); X csr_draw(5,19,16,62); X X csr(y, 23 + (x*5)); X X while(1){ X c = getchar(); X switch(c) { X case 'h': X x -= 1; X x = (x<0 ? 7 : x); X csr(y, 23 + (x*5)); X break; X case 'l': X x += 1; X x = (x>7 ? 0 : x); X csr(y, 23 + (x*5)); X break; X case 'j': X y = (y==8 ? 13 : 8); X csr(y, 23 + (x*5)); X break; X case 'k': X y = (y==8 ? 13 : 8); X csr(y, 23 + (x*5)); X break; X case ' ': X mvaddstr((y == 8 ? 7 : 12), 21 + X ((y == 8 ? (level+1)/2 : (rubble+1)/2)*5),"****"); X mvaddch((y == 8 ? 8 : 13),21 + X ((y == 8 ? (level+1)/2 : (rubble+1)/2)*5), '*'); X mvaddch((y == 8 ? 8 : 13),24 + X ((y == 8 ? (level+1)/2 : (rubble+1)/2)*5), '*'); X mvaddstr((y == 8 ? 9 : 14), 21 + X ((y == 8 ? (level+1)/2 : (rubble+1)/2)*5),"****"); X csr_draw((y == 8 ? 7 : 12),21 + ((y == 8 ? X (level+1)/2 : (rubble+1)/2)*5), X (y == 8 ? 9 : 14), 24 + ((y == 8 ? X (level+1)/2 : (rubble+1)/2)*5)); X if(y == 8) X level = (x == 0 ? 0 : (2*x) - 1); X else X rubble = (x == 0 ? 0 : (2*x) - 1); X mvaddstr((y == 8 ? 7 : 12), 21 + X ((y == 8 ? (level+1)/2 : (rubble+1)/2)*5),"++++"); X mvaddch((y == 8 ? 8 : 13),21 + X ((y == 8 ? (level+1)/2 : (rubble+1)/2)*5), '+'); X mvaddch((y == 8 ? 8 : 13),24 + X ((y == 8 ? (level+1)/2 : (rubble+1)/2)*5), '+'); X mvaddstr((y == 8 ? 9 : 14), 21 + X ((y == 8 ? (level+1)/2 : (rubble+1)/2)*5),"++++"); X csr_draw((y == 8 ? 7 : 12),21 + ((y == 8 ? X (level+1)/2 : (rubble+1)/2)*5), X (y == 8 ? 9 : 14), 24 + ((y == 8 ? X (level+1)/2 : (rubble+1)/2)*5)); X csr(y, 23 + (x*5)); X break; X default: X return; X } X } X} X Xmake_rubble() X{ X int i,j; X char color[8]; X X strcpy(color, "#$%@&*+"); X X for(i=21; i>21-rubble; i--) X for(j=35; j<45; j++) X if((random() % 100) > 60) X mvaddch(i,j,color[(random() % 7)]); X} END_OF_FILE if test 3558 -ne `wc -c <'get_level.c'`; then echo shar: \"'get_level.c'\" unpacked with wrong size! fi # end of 'get_level.c' fi if test -f 'help.tetris' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'help.tetris'\" else echo shar: Extracting \"'help.tetris'\" \(1834 characters\) sed "s/^X//" >'help.tetris' <<'END_OF_FILE' X X TETRIS COMMANDS Xh- move block left This game was supposedly written Xl- move block right by some soviet kid. You try to drop the Xj- rotate block counter-clockwise the blocks into complete horizontal Xk- rotate block clockwise rows; when you do, that row disappears. X Xn- turn on/off next block display For every tenth row that disappears, Xb- turn on/off shadowing the level is increased. Xspace- drop block quickly The game ends when a shape cannot drop X past the top of the screen. XD- redefine keys XP- pause, any key to resume XQ- quit XS- save X adam margulies, vespa@ssyx.ucsc.edu X X X [PRESS ANY KEY FOR NEXT SCREEN] X X X TETRIS SCORING X X There are seven blocks in tetris, each rotation has its own point value. X X $ @@ && * *** + +++ X #### 5 $$$ 5 @@ 6 && 6 *** 6 * 6 +++ 6 + 6 X X # $$$ 6 @ & ** * ++ + X # 8 $ $ $ @@ 7 && 7 * 7 * 6 + 7 + 7 X # $$ 5 5 $$ @ & * ** + ++ X # $ $ X X In addition, a point is scored for each level above the bottom that the Xblock comes to rest. If the space bar is pressed, a point is scored for Xeach row above the bottom that block is at. The level bonus is two times the Xthe current level per block. If the next block display or the block shadowing Xis on then the level bonus is reduced by a number equal to the current level. X [PRESS ANY KEY TO RETURN TO GAME] X END_OF_FILE if test 1834 -ne `wc -c <'help.tetris'`; then echo shar: \"'help.tetris'\" unpacked with wrong size! fi # end of 'help.tetris' fi if test -f 'redefine.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'redefine.c'\" else echo shar: Extracting \"'redefine.c'\" \(1474 characters\) sed "s/^X//" >'redefine.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* redefine.c X** X** allows redefinition of keys X*/ X#include "tetris.h" X X Xvoid redefine() X{ X char c; X int i; X X save_screen(0,0,23,79); X clear(0,0,23,79); X X mvaddstr(10,10,"Redefining keys. . ."); X move(12,15); X printc("move left: %c", key->left); X move(13,15); X printc("move right: %c", key->right); X move(14,15); X printc("rotate ccw: %c", key->rotleft); X move(15,15); X printc("rotate cw: %c", key->rotright); X move(16,15); X printc("drop: %c", key->drop); X move(17,15); X printc("toggle next block: %c", key->togdisp); X move(18,15); X printc("toggle shadowing: %c", key->togshad); X csr_draw(0,0,23,79); X X for(i=12; i<19; i++) { X mvaddch(i,38,'?'); X csr_draw(i,38,i,38); X c = getchar(); X mvaddch(i,38,c); X csr_draw(i,38,i,38); X switch(i) { X case 12: X key->left = c; X break; X case 13: X key->right = c; X break; X case 14: X key->rotleft = c; X break; X case 15: X key->rotright = c; X break; X case 16: X key->drop = c; X break; X case 17: X key->togdisp = c; X break; X case 18: X key->togshad = c; X } X } X restore_screen(0,0,23,79); X csr_draw(0,0,23,79); X} END_OF_FILE if test 1474 -ne `wc -c <'redefine.c'`; then echo shar: \"'redefine.c'\" unpacked with wrong size! fi # end of 'redefine.c' fi if test -f 'save_game.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'save_game.c'\" else echo shar: Extracting \"'save_game.c'\" \(1925 characters\) sed "s/^X//" >'save_game.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* Tetris: save_game.c X** X** Saves the game X** X*/ X#include "tetris.h" X Xvoid save_game() { X X FILE *fp; X int i,j; X struct stat buf; X X if ((fp = fopen(rcd_file, "w")) == NULL){ X SIGHOLD(14); X cls(); X csr(23,0); X resetty(); X fprintf(stderr, "%s\n", rcd_file); X perror("opening save file"); X exit(3); X } X X mvaddstr(23,0,"Got here [1]"); X csr_draw(23,0,23,79); X X stat(rcd_file, &buf); X for(i=0; i<20; i++) { X for(j=0; j<10; j++) X putc(window0[i+2][j+35], fp); X putc('\n', fp); X } X X mvaddstr(23,0,"Got here [0]"); X csr_draw(23,0,23,79); X X fprintf(fp, "%ld\n", buf.st_ctime); X fprintf(fp, "%d\n", VERSION); X fprintf(fp, "%d\n%d\n%d\n", points, level, lines); X fprintf(fp, "%d\n", disp_next); X fprintf(fp, "%d\n", shadow); X fprintf(fp, "%d\n", disp_tomb); X fprintf(fp, "%d\n", disp_high); X fprintf(fp, "%d\n%d\n", cury, curx); X fprintf(fp, "%d\n%d\n", current->shape, current->rot); X fprintf(fp, "%d\n", current->was_shown); X fprintf(fp, "%d\n", current->was_shadowed); X fprintf(fp, "%d\n%d\n", next->shape, next->rot); X fprintf(fp, "%d\n", next->was_shown); X fprintf(fp, "%d\n", next->was_shadowed); X fprintf(fp, "%d\n", addict); X fprintf(fp, "%c\n", key->right); X fprintf(fp, "%c\n", key->left); X fprintf(fp, "%c\n", key->rotright); X fprintf(fp, "%c\n", key->rotleft); X fprintf(fp, "%c\n", key->drop); X fprintf(fp, "%c\n", key->togdisp); X fprintf(fp, "%c\n", key->togshad); X close(fp); X X for (i=2; i<12; i++) { X mvaddstr(i,35,"++++++++++"); X mvaddstr(23-i,35,"++++++++++"); X csr_draw(2,35,21,44); X } X mvaddstr(11,35,"GAME SAVED"); X csr_draw(11,35,11,44); X X csr(23,0); X resetty(); X exit(0); X} END_OF_FILE if test 1925 -ne `wc -c <'save_game.c'`; then echo shar: \"'save_game.c'\" unpacked with wrong size! fi # end of 'save_game.c' 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'\" \(739 characters\) sed "s/^X//" >'score.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* Tetris: score.c */ X/* this is what keeps score */ X#include "tetris.h" X Xvoid score(final_row) Xint final_row; X{ X points += current->pointv + 21 - final_row; X if (current->was_shown == 0) X points += level; X if (current->was_shadowed == 0) X points += level; X if (dropped_from) X points += final_row - dropped_from; X X move(0, 65); X printc("score: %7.7d", points); X X csr_draw(0,65,0,79); X} END_OF_FILE if test 739 -ne `wc -c <'score.c'`; then echo shar: \"'score.c'\" unpacked with wrong size! fi # end of 'score.c' fi if test -f 'score.tetris' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'score.tetris'\" else echo shar: Extracting \"'score.tetris'\" \(393 characters\) sed "s/^X//" >'score.tetris' <<'END_OF_FILE' X40144 Xpuzzled XDo not go gently into that dark night. X39458 Xlupin3 X-=/TetriSuicide/=- X31758 Xjohnnyb X-=[ Bloc - Head ]=- X29403 Xclndria XDon't be afraid...I don't [usually] bite X28322 Xentropy Xdoofus X28305 Xastarte XGoddess of Fertility X28275 Xlestat XThe Vampire Lestat X24746 Xgames XMartin Heidegger X22574 Xmmp Xdoofus X22188 Xbluelbo XI can stop any time I want X20330 Xserling XRich Wilkman...Tetris Addict END_OF_FILE if test 393 -ne `wc -c <'score.tetris'`; then echo shar: \"'score.tetris'\" unpacked with wrong size! fi # end of 'score.tetris' fi if test -f 'set_level.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'set_level.c'\" else echo shar: Extracting \"'set_level.c'\" \(626 characters\) sed "s/^X//" >'set_level.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* Tetris: set_level.c X** this decrements the interval timer everytime a new level is reached X*/ X#include "tetris.h" X Xset_level() X{ X timer.it_interval.tv_usec = 500000 - (level * 1000 * DIFFICULTY); X timer.it_value.tv_usec = 500000 - (level * 1000 * DIFFICULTY); X setitimer(ITIMER_REAL, &timer, 0); X} END_OF_FILE if test 626 -ne `wc -c <'set_level.c'`; then echo shar: \"'set_level.c'\" unpacked with wrong size! fi # end of 'set_level.c' fi if test -f 'setup_next.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'setup_next.c'\" else echo shar: Extracting \"'setup_next.c'\" \(1849 characters\) sed "s/^X//" >'setup_next.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* Tetris: setup_next.c */ X/* */ X/* following a successful drop of a block this function will do all the */ X/* house-keeping necessary to the creation of a new block. */ X/* */ X#include "tetris.h" X Xvoid setup_next() X{ X X int pow(); X X if (disp_next) X print_shape(next->shape, 17, 6, X next->rot, ' '); /* erase the next shape */ X X bcopy(next, current, sizeof(struct shape)); /* move next to current */ X X next->shape = random() % 7; X next->rot = random() % 4; X next->color = shape[next->shape].color; X next->offset = shape[next->shape].offset; X next->pointv = shape[next->shape].pointv[next->rot]; X next->was_shown = (disp_next ? 1 : 0); X X if (next->rot == 0 || next->rot == 2) { X next->width = shape[next->shape].width; X next->height = shape[next->shape].height; X } X if (next->rot == 1 || next->rot == 3) { X next->width = shape[next->shape].height; X next->height = shape[next->shape].width; X } X X curx = 39 - ((current->offset & pow(2, 6 - (current->rot * 2))) ? 1 : 0); X X cury = 2 - ((current->offset & pow(2, 7 - (current->rot * 2))) ? 1 : 0) - X current->height; X X if (disp_next) X print_shape(next->shape, 17, 6, next->rot, X next->color); X print_shape(current->shape, curx, cury, current->rot, X current->color); X if (shadow == 1) { X current->was_shadowed = 1; X draw_shadow(); X } X} END_OF_FILE if test 1849 -ne `wc -c <'setup_next.c'`; then echo shar: \"'setup_next.c'\" unpacked with wrong size! fi # end of 'setup_next.c' fi if test -f 'tetris.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tetris.h'\" else echo shar: Extracting \"'tetris.h'\" \(3167 characters\) sed "s/^X//" >'tetris.h' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* Tetris: tetris.h */ X/* */ X/* this is the header file, it does all the necessary includes, defines */ X/* the necessary macros, and contains a lot of needed runtime data. */ X#include <sys/file.h> X#include <sys/time.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <pwd.h> X#include <signal.h> X#include <stdio.h> X#include <utmp.h> X#include "csr.h" X X#define LASTDATE "2/23/89" X#define VERSION 13 X X#define HIGHSCOREFILE "/usr/games/lib/tetris/score.tetris" X#define MONITORFILE "/dev/null" X#define HELPFILE "/usr/games/lib/tetris/help.tetris" X#define MASTERUID 0 X#define DIFFICULTY 10 X X#define NUMOFCOLORS 9 /* number of 'colors' available */ X#define xoffset (current->offset & pow(2, 6 - (current->rot *2))) X#define yoffset (current->offset & pow(2, 7 - (current->rot *2))) X#define MASK(sig) (1 << ((sig) - 1)) X#define SIGHOLD(signo) (sigblock(MASK(signo))) X#define SIGRELSE(signo) (sigsetmask(sigblock(0) &~ MASK(signo))) X Xchar keystr[10]; Xint addict; Xint rubble; Xint version; Xint disp_next; /* flag for the display next block feature (bug?)*/ Xint disp_tomb; /* flag for the display tombstone feature (bug?)*/ Xint disp_high; /* flag for the display high score feature (bug?)*/ Xint disp_open; /* flag for the display open screen feature (bug?)*/ Xint shadow; /* flag for the shadowing feature (bug?)*/ Xint nowrite; /* flag for nowrite option */ Xstruct stat *ttystat; /* this hold the file perms of the user's tty */ Xint curx, cury; /* current block's x,y coords */ Xint points, level; /* current score and level */ Xint current_high; /* current high score */ Xchar rcd_file[255]; /* path to rc file */ Xint lines; /* number of lines eaten */ Xint dropped_from; /* flag to tell score function where fast drop X came from */ Xint fast_drop; /* flag for dropping blocks fast */ Xchar *user; Xint high_score[15]; Xchar high_user[15][8]; Xchar high_name[15][255]; Xchar username[100]; X Xstruct shape_table { /* this structure holds all the block defins */ X int table[4][4]; X int width; X int height; X int offset; X int pointv[4]; X char color; X } shape[7]; X Xstruct shape { /* these are for quick reference */ X int shape; /* do I know what I am doing? Nah.... */ X int rot; X int width; X int height; X int offset; X int pointv; X char color; X int was_shown; X int was_shadowed; X } *current, *next; X Xstruct keystr { X char left; X char right; X char rotleft; X char rotright; X char drop; X char togdisp; X char togshad; X } *key; X Xstruct itimerval timer, otimer; /* these are for the interrupt timing */ Xstruct passwd *user_info; /* user info (tricky names aren't they?) */ END_OF_FILE if test 3167 -ne `wc -c <'tetris.h'`; then echo shar: \"'tetris.h'\" unpacked with wrong size! fi # end of 'tetris.h' fi if test -f 'tetris.man' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tetris.man'\" else echo shar: Extracting \"'tetris.man'\" \(3191 characters\) sed "s/^X//" >'tetris.man' <<'END_OF_FILE' X.TH TETRIS 1 "23 February 1989" "UNIX Programmer's Manual" X.SH NAME Xtetris - popular game of dropping blocks. X.SH SYNOPSIS X.B /usr/games/tetris X[-] [-whotnbsa] [-L level] [-N name] [-O oblev] [-K keys] X.SH DESCRIPTION X.B Tetris Xis played in real-time on a 10X20 board. Randomly selected shapes of Xfour contiguous blocks are dropped from the top of the board. The player Xtries to rotate and move the blocks so that they form continuous Xhorizontal rows. When a row is completed, it disappears. If the screen Xfills up to the point that a shape cannot drop below the top of the screen, Xthe game ends. X.br X.SH ARGUMENTS X XThe command line arguments are as follows: X X.B X- X- give summary of usage X.br X.B Xw X- makes you unwritable for duration of game X.br X.B Xh X- suppress printing of high score list X.br X.B Xo X- suppress opening screen selection box X.br X.B Xt X- display roguelike tombstone X.br X.B Xn X- turn off next block display X.br X.B Xb X- turn off shadowing X.br X.B Xs X- display high score list and exit X.br X.B Xa X- addict option, logs you out when game is over X.br X.B XN X.I [name] Xuse [name] for high score list (40 chars max), default to NAME environment. X.br X.B XL X.I [level] X- start at [level] of difficulty (max starting level of 20) X.br X.B XO X.I [oblev] X- generate [oblev]s of debris (max 13 levels of debris) X.br X.B XK X.I [keys] X- map control keys to [keys] X.br X XTetris also checks for the environment variable TETRIS. The user can place Xcommand line arguments into this variable to be used for every game. X X.br X.SH COMMANDS X X.B h X- move block left X.br X.B l X- move block right X.br X.B j X- rotate block counter-clockwise X.br X.B k X- rotate block clockwise X.br X.B ? X- online help X.br X.B n X- toggle next block display X.br X.B b X- toggle shadowing X.br X.B space X- drop block quickly X.br X.B D X- redefine keys X.br X.B P X- pause game X.br X.B S X- save game X.br X.B Q X- quit game X.br X.SH DIAGNOSTICS X.I Your terminal must have cursor movement capabilities: X.br XThis is message from the cursor movement package informing you that Xyour terminal is not sophisticated enough for tetris. In some cases, your Xtermcap entry might be to blame. X X.br X.I Panic! X.br XYou have been a naughty tetris player. You have tried to modify your Xsave file and tetris is now going to punish you. X.br X.SH FILES X.I /usr/games/lib/help.tetris X.br X.I /usr/games/lib/monitor.tetris X.br X.I /usr/games/lib/score.tetris X.br X.I ~/tetris.save X.br X.SH BUGS X.br XIn its current version (1.3) \s-2unix\*R\s+2 Tetris is too cpu intensive. X X.br XThere are strange quirks that allow blocks to be rotated into one another. X X.br XThe save game files are minimally secure at best. X X.br XThe key mapping works but you have to give the keys in the proper order. XThe implementation is very unforgiving. X X.br XTetris was conceived by a soviet computer science student and is, therefore, Xmost probably a communist plot. X X.SH AUTHOR Xvespa@ssyx.ucsc.edu X.br X{...}!ucbvax!ucscc!ssyx!vespa X.br X.SH NOTES XTetris is meant for free distribution. It is not to be licensed or sold Xfor profit. X X.br XAnyone who wishes a copy may have one. X X.br XIn general, I would like to see distribution done in the philosophy Xof the Free Software Foundation, a.k.a. the GNU project. END_OF_FILE if test 3191 -ne `wc -c <'tetris.man'`; then echo shar: \"'tetris.man'\" unpacked with wrong size! fi # end of 'tetris.man' fi if test -f 'useful.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'useful.c'\" else echo shar: Extracting \"'useful.c'\" \(813 characters\) sed "s/^X//" >'useful.c' <<'END_OF_FILE' X/* X** written by adam margulies vespa@ssyx.ucsc.edu X** {...}!ucbvax!ucscc!ssyx!vespa X** X** permission is granted to freely distribute this code provided that you: X** X** 1) don't charge for it X** 2) leave my name and header on it X** 3) clearly document your changes and place your name on them X** X*/ X/* Tetris: useful.c */ X/* these are functions that I find useful for all other function writing */ X#include "tetris.h" X Xint pow(base, exponent) Xint base, exponent; X{ X int tmp = 1; X X if (exponent == 0) X return(1); X X if (exponent == 1) X return(base); X X while (exponent--) X tmp *= base; X X return(tmp); X} X Xvoid bfill(buf, len, ch) Xchar *buf, ch; Xint len; X{ X while(len--) X *buf++ = ch; X} X Xvoid cont_hand() { X init_csr(); X bfill(window0, sizeof(window0), ' '); X refresh(); X} END_OF_FILE if test 813 -ne `wc -c <'useful.c'`; then echo shar: \"'useful.c'\" unpacked with wrong size! fi # end of 'useful.c' 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