3 @@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@
4 @@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@
5 @@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@
6 @@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
7 @@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
8 @@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@
9 @@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@
10 @@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@
11 @@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@
14 Caltech High Energy Physics
17 Hacks to turn this into a test frame for cursor movement:
18 Eric S. Raymond <esr@snark.thyrsus.com>
21 July 1995 (esr): worms is now in living color! :-)
24 -f fill screen with copies of 'WORM' at start.
25 -l <n> set worm length
26 -n <n> set number of worms
27 -t make worms leave droppings
28 -T <start> <end> set trace interval
29 -S set single-stepping during trace interval
30 -N suppress cursor-movement optimization
32 This program makes a good torture-test for the ncurses cursor-optimization
33 code. You can use -T to set the worm move interval over which movement
34 traces will be dumped. The program stops and waits for one character of
35 input at the beginning and end of the interval.
37 $Id: worm.c,v 1.26 1999/10/23 01:31:40 tom Exp $
40 #include <test.priv.h>
44 #define typeAlloc(type,n) (type *) malloc(n * sizeof(type))
45 #define typeRealloc(type,n,p) (type *) realloc(p, n * sizeof(type))
47 static chtype flavor[] =
49 'O', '*', '#', '$', '%', '0', '@',
51 #define MAXWORMS (sizeof(flavor)/sizeof(chtype))
52 static const short xinc[] =
54 1, 1, 1, 0, -1, -1, -1, 0
57 -1, 0, 1, 1, 1, 0, -1, -1
60 int orientation, head;
64 static const char *field;
65 static int length = 16, number = 3;
66 static chtype trail = ' ';
69 int generation, trace_start, trace_end, singlestep;
72 static const struct options {
169 onsig(int sig GCC_UNUSED)
178 long r = (rand() & 077777);
179 return ((float) r / 32768.);
183 main(int argc, char *argv[])
190 const struct options *op;
195 for (x = 1; x < argc; x++) {
207 if ((length = atoi(argv[x])) < 2 || length > 1024) {
208 fprintf(stderr, "%s: Invalid length\n", *argv);
215 if ((number = atoi(argv[x])) < 1 || number > 40) {
216 fprintf(stderr, "%s: Invalid number of worms\n", *argv);
228 trace_start = atoi(argv[++x]);
229 trace_end = atoi(argv[++x]);
232 _nc_optimize_enable ^= OPTIMIZE_ALL; /* declared by ncurses */
238 "usage: %s [-field] [-length #] [-number #] [-trail]\n", *argv);
243 signal(SIGINT, onsig);
256 int bg = COLOR_BLACK;
258 #ifdef NCURSES_VERSION
259 if (use_default_colors() == OK)
263 #define SET_COLOR(num, fg) \
264 init_pair(num+1, fg, bg); \
265 flavor[num] |= COLOR_PAIR(num+1) | A_BOLD
267 SET_COLOR(0, COLOR_GREEN);
268 SET_COLOR(1, COLOR_RED);
269 SET_COLOR(2, COLOR_CYAN);
270 SET_COLOR(3, COLOR_WHITE);
271 SET_COLOR(4, COLOR_MAGENTA);
272 SET_COLOR(5, COLOR_BLUE);
273 SET_COLOR(6, COLOR_YELLOW);
277 ref = typeAlloc(short *, LINES);
278 for (y = 0; y < LINES; y++) {
279 ref[y] = typeAlloc(short, COLS);
280 for (x = 0; x < COLS; x++) {
286 /* if addressing the lower right corner doesn't work in your curses */
287 ref[bottom][last] = 1;
288 #endif /* BADCORNER */
290 for (n = number, w = &worm[0]; --n >= 0; w++) {
291 w->orientation = w->head = 0;
292 if (!(ip = typeAlloc(short, (length + 1)))) {
293 fprintf(stderr, "%s: out of memory\n", *argv);
297 for (x = length; --x >= 0;)
299 if (!(ip = typeAlloc(short, (length + 1)))) {
300 fprintf(stderr, "%s: out of memory\n", *argv);
304 for (y = length; --y >= 0;)
310 for (y = bottom; --y >= 0;) {
311 for (x = COLS; --x >= 0;) {
312 addch((chtype) (*p++));
321 nodelay(stdscr, TRUE);
326 if (trace_start || trace_end) {
327 if (generation == trace_start) {
330 } else if (generation == trace_end) {
335 if (singlestep && generation > trace_start && generation < trace_end)
341 if ((ch = getch()) > 0) {
343 if (ch == KEY_RESIZE) {
344 if (last != COLS - 1) {
345 for (y = 0; y <= bottom; y++) {
346 ref[y] = typeRealloc(short, COLS, ref[y]);
347 for (x = last + 1; x < COLS; x++)
352 if (bottom != LINES - 1) {
353 ref = typeRealloc(short *, LINES, ref);
354 for (y = COLS; y <= bottom; y++)
356 for (y = bottom + 1; y < LINES; y++) {
357 ref[y] = typeAlloc(short, COLS);
358 for (x = 0; x < COLS; x++)
366 * Make it simple to put this into single-step mode, or resume
367 * normal operation -TD
371 return (EXIT_SUCCESS);
372 } else if (ch == 's') {
373 nodelay(stdscr, FALSE);
374 } else if (ch == ' ') {
375 nodelay(stdscr, TRUE);
380 for (n = 0, w = &worm[0]; n < number; n++, w++) {
381 if ((x = w->xpos[h = w->head]) < 0) {
382 move(y = w->ypos[h] = bottom, x = w->xpos[h] = 0);
383 addch(flavor[n % MAXWORMS]);
394 if (w->xpos[w->head = h] >= 0) {
400 && --ref[y1][x1] == 0) {
405 op = &(x == 0 ? (y == 0 ? upleft : (y == bottom ? lowleft :
407 (x == last ? (y == 0 ? upright : (y == bottom ? lowright :
409 (y == 0 ? upper : (y == bottom ? lower : normal))))[w->orientation];
415 w->orientation = op->opts[0];
418 w->orientation = op->opts[(int) (ranf() * (float) op->nopts)];
420 move(y += yinc[w->orientation], x += xinc[w->orientation]);
424 addch(flavor[n % MAXWORMS]);
425 ref[w->ypos[h] = y][w->xpos[h] = x]++;