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.31 2000/09/02 18:41:01 tom Exp $
40 #include <test.priv.h>
44 static chtype flavor[] =
46 'O', '*', '#', '$', '%', '0', '@',
48 #define MAXWORMS (sizeof(flavor)/sizeof(chtype))
49 static const short xinc[] =
51 1, 1, 1, 0, -1, -1, -1, 0
54 -1, 0, 1, 1, 1, 0, -1, -1
57 int orientation, head;
61 static const char *field;
62 static int length = 16, number = 3;
63 static chtype trail = ' ';
66 int generation, trace_start, trace_end, singlestep;
69 static const struct options {
166 onsig(int sig GCC_UNUSED)
175 long r = (rand() & 077777);
176 return ((float) r / 32768.);
180 main(int argc, char *argv[])
186 const struct options *op;
191 for (x = 1; x < argc; x++) {
203 if ((length = atoi(argv[x])) < 2 || length > 1024) {
204 fprintf(stderr, "%s: Invalid length\n", *argv);
211 if ((number = atoi(argv[x])) < 1 || number > 40) {
212 fprintf(stderr, "%s: Invalid number of worms\n", *argv);
224 trace_start = atoi(argv[++x]);
225 trace_end = atoi(argv[++x]);
228 _nc_optimize_enable ^= OPTIMIZE_ALL; /* declared by ncurses */
234 "usage: %s [-field] [-length #] [-number #] [-trail]\n", *argv);
239 signal(SIGINT, onsig);
252 int bg = COLOR_BLACK;
254 #if HAVE_USE_DEFAULT_COLORS
255 if (use_default_colors() == OK)
259 #define SET_COLOR(num, fg) \
260 init_pair(num+1, fg, bg); \
261 flavor[num] |= COLOR_PAIR(num+1) | A_BOLD
263 SET_COLOR(0, COLOR_GREEN);
264 SET_COLOR(1, COLOR_RED);
265 SET_COLOR(2, COLOR_CYAN);
266 SET_COLOR(3, COLOR_WHITE);
267 SET_COLOR(4, COLOR_MAGENTA);
268 SET_COLOR(5, COLOR_BLUE);
269 SET_COLOR(6, COLOR_YELLOW);
273 ref = typeMalloc(short *, LINES);
274 for (y = 0; y < LINES; y++) {
275 ref[y] = typeMalloc(short, COLS);
276 for (x = 0; x < COLS; x++) {
282 /* if addressing the lower right corner doesn't work in your curses */
283 ref[bottom][last] = 1;
284 #endif /* BADCORNER */
286 for (n = number, w = &worm[0]; --n >= 0; w++) {
287 w->orientation = w->head = 0;
288 if (!(ip = typeMalloc(short, (length + 1)))) {
289 fprintf(stderr, "%s: out of memory\n", *argv);
293 for (x = length; --x >= 0;)
295 if (!(ip = typeMalloc(short, (length + 1)))) {
296 fprintf(stderr, "%s: out of memory\n", *argv);
300 for (y = length; --y >= 0;)
306 for (y = bottom; --y >= 0;) {
307 for (x = COLS; --x >= 0;) {
308 addch((chtype) (*p++));
317 nodelay(stdscr, TRUE);
322 if (trace_start || trace_end) {
323 if (generation == trace_start) {
326 } else if (generation == trace_end) {
331 if (singlestep && generation > trace_start && generation < trace_end)
339 if ((ch = getch()) > 0) {
341 if (ch == KEY_RESIZE) {
342 if (last != COLS - 1) {
343 for (y = 0; y <= bottom; y++) {
344 ref[y] = typeRealloc(short, COLS, ref[y]);
345 for (x = last + 1; x < COLS; x++)
350 if (bottom != LINES - 1) {
351 for (y = LINES; y <= bottom; y++)
353 ref = typeRealloc(short *, LINES, ref);
354 for (y = bottom + 1; y < LINES; y++) {
355 ref[y] = typeMalloc(short, COLS);
356 for (x = 0; x < COLS; x++)
364 * Make it simple to put this into single-step mode, or resume
365 * normal operation -TD
369 return (EXIT_SUCCESS);
370 } else if (ch == 's') {
371 nodelay(stdscr, FALSE);
372 } else if (ch == ' ') {
373 nodelay(stdscr, TRUE);
378 for (n = 0, w = &worm[0]; n < number; n++, w++) {
379 if ((x = w->xpos[h = w->head]) < 0) {
380 move(y = w->ypos[h] = bottom, x = w->xpos[h] = 0);
381 addch(flavor[n % MAXWORMS]);
392 if (w->xpos[w->head = h] >= 0) {
398 && --ref[y1][x1] == 0) {
403 op = &(x == 0 ? (y == 0 ? upleft : (y == bottom ? lowleft :
405 (x == last ? (y == 0 ? upright : (y == bottom ? lowright :
407 (y == 0 ? upper : (y == bottom ? lower : normal))))[w->orientation];
413 w->orientation = op->opts[0];
416 w->orientation = op->opts[(int) (ranf() * (float) op->nopts)];
418 move(y += yinc[w->orientation], x += xinc[w->orientation]);
422 addch(flavor[n % MAXWORMS]);
423 ref[w->ypos[h] = y][w->xpos[h] = x]++;