[net.sources.games] Well, at least it's a source.... but that's all it is.

remote@tjalk.UUCP (02/23/87)

I've not only had enough of all the requests and other non-sources in
this newsgroup, but also of the complaints about the absence of sources.
Fact is, I haven't seen a source around here in ages.
So I am going to do something about it. I must admit, the next program
is not much. It isn't even a real game.
But it's a _s_o_u_r_c_e. This mini-program plays for you "worms".
It makes all kind of worms crawl over your screen, that is actually
all there is to it. But there are 4 things good about it:
- It looks good.
- The worms don't cross or overlay eachother.
- I wrote the program myself (some time ago already)
- You don't have a right to critizice it unless you send in a source yourself.
However, it is terminal dependant, but if you know the cursor-movement-codes
of your terminal, it should be really a very minor problem to modify it.

Well, let's hope many people will have a right to criticize it in the
future ( :-) ? ). Good luck to you all - write and sweat!
Or like we say here in Holland: Schrijf ze!

						   ||
						BISSCHOP
						   ||
						   ||
						   ||
							(That's also Dutch)


----8<------8<----------cut here-----------8<------------8<------------8<---



#define MaxNrOfWorms 32 /* You can't alter this without altering the zoo! */
			/* (Zoo: see somewhere else in this program)      */
#define MaxLength   256 /* This really is long enough! */
#define ScreenWidth  80   /* adapt to your terminal!  */
#define ScreenHeigth 23	  

#include <stdio.h>


int wormlength = 20 ;	/* 20 by default, can be redefined by -l<nr> */
int nrofworms = 3 ;	/* 3 by default, can be redefined by -n<nr> */
char *message = "				W O R M S ! ! !" ;
			/* message can be redifined by -m<string> */

int x_direction[8] = { 1, 1, 0, -1, -1, -1, 0, 1} ;
int y_direction[8] = { 0, 1, 1, 1, 0, -1, -1, -1} ;

int screen[ScreenWidth][ScreenHeigth] ;



main(argc, argv)

char	**argv ;

{	int wormx[MaxNrOfWorms][MaxLength] , wormy[MaxNrOfWorms][MaxLength] ;
	int dir[MaxNrOfWorms], i, j;
	int ptr1, ptr2 , x , y, *direction ;
	long dummy ;
	char *pos() ;


	/* First test for any flags... */

	for ( i = 1 ; i < argc ; i++ )
		if ( argv[i][0] == '-' )
		{	switch( argv[i][1] )
			{ case 'l' : if (
				sscanf ( argv[i] , "-l%d", &wormlength)==0 ||
			        wormlength < 2 || wormlength > MaxLength )
				{	puts("Bad length.") ;
					exit( 1 ) ;
				} break ;
			  case 'n' : if (
				sscanf ( argv[i] , "-n%d", &nrofworms)==0 ||
			        nrofworms < 1 || nrofworms > MaxNrOfWorms )
				{	puts("Bad number of worms.") ;
					exit( 1 ) ;
				} break ;
			  case 'm' : message = argv[i]+2 ; break ;
			default : printf(" -%c: bad option.\n", argv[i][1]) ;
				  exit(1) ;
			}
		}
		else
		{	printf("Syntax: %s [ -l<nr> ] [ -n<nr> ] \
[ -m<message> ]\n", argv[0]);
			exit(1) ;
		}

	/* Now let's initialize !! */

	clear_screen() ;
	printf("%s%s", pos(0, 22) , message ) ;

	for ( j=0 ; j < nrofworms ; j++ )
	{	for ( i=0 ; i < wormlength ; i++ )
			wormx[j][i]=wormy[j][i]=0 ;
		dir[ j ] = 1 ;  /* direction of worm j */
	}

	screen[0][0]= nrofworms * wormlength ;
	ptr1 = ptr2 = 0 ;
	     /* They point to the front and the back of a worm, respectively.*/


	/* init randomizer... I hope this will work, it works on UNIX */
	srand( (int) time ( &dummy) ) ;




	while ( 1 )
	{   ptr2 = (ptr1 + 1) % wormlength ;
			/* Take the next part of each worm. */

	    for ( i = 0 ; i < nrofworms ; i++ )
	    {	int enough = 0 ;

		x=wormx[i][ptr2] ; y=wormy[i][ptr2] ;
			/* x and y are the coordinates of the tail of worm i,
			/* which has to be removed.			*/
	    	if ( (--screen[x][y])==0) printf("%s ", pos(x, y) ) ; 
			/* It will only be removed when there are no other
			/* "parts" of worms on that spot on the screen.  */

		/* Now put a head somewhere. */
		/* We'll modify the direction just until we've got a
		/* correct direction (so that the worm will not cross or
		/* overlap another worm or itself, nor will run of the screen),
		/* or that we've had enough,
		/* since than there probably is no such direction. */

		direction = &dir[i] ;

		do	*direction = ( *direction + (rand()) % 3 +7 ) % 8 ;
		while ( ( x = wormx[i][ptr1] + x_direction[*direction] ) < 0 ||
			x > ScreenWidth-1 ||
		        ( y = wormy[i][ptr1] + y_direction[*direction] ) < 0 ||
			y > ScreenHeigth-2 ||
		        ( ( screen[x][y]!=0 || cross( x, y, *direction ) )
							    && enough++ < 19)) ;

		if ( enough >= 19 ) /* We can't move this poor worm */
		{	x = wormx[i][ptr1] ;  /*  old coordinates  */
			y = wormy[i][ptr1] ;
		}

		/*	x and y now contain the new coordinates of the worms
		/*	head. Let's just place it on the screen (and in memory)
		 */
		wormx[i][ptr2] = x ;
		wormy[i][ptr2] = y ;
		printf("%s%c", pos( x , y ) ,
				      "*#Ox@~.+!&%$'`=-oXwW()^~*#x0@+./"[i] ) ;
				/*  Welcome to the zoo!! ^^^^ */
		screen[x][y]++ ;
	    }
	    ptr1 = ptr2 ;
	}
}





cross(x, y, d)  /* Checks whether two worms "cross". Worms cross when they
		/* both move diogonally and cross, like:
		/*
		/*		O	XX
		/*		 O   XXX
		/*		  OXX
		/*		  XO
		/*		  X OOOO
		/*		 X
		/*
		/*	This is not allowed. */
{
	if ( d&1 == 0 ) return 0 ; /* worm moving diogonally? */

	return  ( screen[x][y-y_direction[d]] && screen[x-x_direction[d]][y] ) ;
}



/* Warning!!!!!! The next two routines are terminal-dependant!!!
/* They adress the cursor/clear the screen respectively.
/* They should work on plenty of terminals but they won't work on even more.
/* One could use curses(3) (UNIX only?), but I have to know more about it first.
/* Adapt them to your own terminal(s) if necessary.
/* They wil work on a210's, a230's, iq120's, d80's, d150's, tvi912/950's,
/* atr8000, adm 3a/31/2/42, qume5, zentec 30, mime2as, carlock and others.
 */

char *pos( x , y )  /* watch it: I always use x,y instead of y,x! */
{
	static char uit[5] = { 27, '=' , ' ', ' ' } ;
				/*   That is: "\E=%+ %+ :" in termcap */

	uit[3] = ' '+x ; uit[2] = ' '+y ;
	return uit ;
}



clear_screen()
{
	putchar(26) ;
}