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) ; }