1 /****************************************************************************
2 * Copyright (c) 1998-2005,2006 Free Software Foundation, Inc. *
4 * Permission is hereby granted, free of charge, to any person obtaining a *
5 * copy of this software and associated documentation files (the *
6 * "Software"), to deal in the Software without restriction, including *
7 * without limitation the rights to use, copy, modify, merge, publish, *
8 * distribute, distribute with modifications, sublicense, and/or sell *
9 * copies of the Software, and to permit persons to whom the Software is *
10 * furnished to do so, subject to the following conditions: *
12 * The above copyright notice and this permission notice shall be included *
13 * in all copies or substantial portions of the Software. *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
23 * Except as contained in this notice, the name(s) of the above copyright *
24 * holders shall not be used in advertising or otherwise to promote the *
25 * sale, use or other dealings in this Software without prior written *
27 ****************************************************************************/
30 @@@ @@@ @@@@@@@@@@ @@@@@@@@@@@ @@@@@@@@@@@@
31 @@@ @@@ @@@@@@@@@@@@ @@@@@@@@@@@@ @@@@@@@@@@@@@
32 @@@ @@@ @@@@ @@@@ @@@@ @@@@ @@@ @@@@
33 @@@ @@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
34 @@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@
35 @@@@ @@@@ @@@@ @@@ @@@ @@@ @@@ @@@ @@@
36 @@@@@@@@@@@@ @@@@ @@@@ @@@ @@@ @@@ @@@
37 @@@@ @@@@ @@@@@@@@@@@@ @@@ @@@ @@@ @@@
38 @@ @@ @@@@@@@@@@ @@@ @@@ @@@ @@@
41 Caltech High Energy Physics
44 Hacks to turn this into a test frame for cursor movement:
45 Eric S. Raymond <esr@snark.thyrsus.com>
48 July 1995 (esr): worms is now in living color! :-)
51 -f fill screen with copies of 'WORM' at start.
52 -l <n> set worm length
53 -n <n> set number of worms
54 -t make worms leave droppings
55 -T <start> <end> set trace interval
56 -S set single-stepping during trace interval
57 -N suppress cursor-movement optimization
59 This program makes a good torture-test for the ncurses cursor-optimization
60 code. You can use -T to set the worm move interval over which movement
61 traces will be dumped. The program stops and waits for one character of
62 input at the beginning and end of the interval.
64 $Id: worm.c,v 1.41 2006/07/01 22:57:24 tom Exp $
67 #include <test.priv.h>
69 static chtype flavor[] =
71 'O', '*', '#', '$', '%', '0', '@',
73 static const short xinc[] =
75 1, 1, 1, 0, -1, -1, -1, 0
78 -1, 0, 1, 1, 1, 0, -1, -1
81 int orientation, head;
85 static const char *field;
86 static int length = 16, number = 3;
87 static chtype trail = ' ';
90 static int generation, trace_start, trace_end, singlestep;
93 static const struct options {
190 onsig(int sig GCC_UNUSED)
193 ExitProgram(EXIT_FAILURE);
199 long r = (rand() & 077777);
200 return ((float) r / 32768.);
204 main(int argc, char *argv[])
210 const struct options *op;
216 setlocale(LC_ALL, "");
218 for (x = 1; x < argc; x++) {
230 if ((length = atoi(argv[x])) < 2 || length > 1024) {
231 fprintf(stderr, "%s: Invalid length\n", *argv);
232 ExitProgram(EXIT_FAILURE);
238 if ((number = atoi(argv[x])) < 1 || number > 40) {
239 fprintf(stderr, "%s: Invalid number of worms\n", *argv);
240 ExitProgram(EXIT_FAILURE);
251 trace_start = atoi(argv[++x]);
252 trace_end = atoi(argv[++x]);
255 _nc_optimize_enable ^= OPTIMIZE_ALL; /* declared by ncurses */
261 "usage: %s [-field] [-length #] [-number #] [-trail]\n", *argv);
262 ExitProgram(EXIT_FAILURE);
266 signal(SIGINT, onsig);
279 int bg = COLOR_BLACK;
281 #if HAVE_USE_DEFAULT_COLORS
282 if (use_default_colors() == OK)
286 #define SET_COLOR(num, fg) \
287 init_pair(num+1, fg, bg); \
288 flavor[num] |= COLOR_PAIR(num+1) | A_BOLD
290 SET_COLOR(0, COLOR_GREEN);
291 SET_COLOR(1, COLOR_RED);
292 SET_COLOR(2, COLOR_CYAN);
293 SET_COLOR(3, COLOR_WHITE);
294 SET_COLOR(4, COLOR_MAGENTA);
295 SET_COLOR(5, COLOR_BLUE);
296 SET_COLOR(6, COLOR_YELLOW);
300 ref = typeMalloc(short *, LINES);
301 for (y = 0; y < LINES; y++) {
302 ref[y] = typeMalloc(short, COLS);
303 for (x = 0; x < COLS; x++) {
309 /* if addressing the lower right corner doesn't work in your curses */
310 ref[bottom][last] = 1;
311 #endif /* BADCORNER */
313 for (n = number, w = &worm[0]; --n >= 0; w++) {
314 w->orientation = w->head = 0;
315 if (!(ip = typeMalloc(short, (length + 1)))) {
316 fprintf(stderr, "%s: out of memory\n", *argv);
317 ExitProgram(EXIT_FAILURE);
320 for (x = length; --x >= 0;)
322 if (!(ip = typeMalloc(short, (length + 1)))) {
323 fprintf(stderr, "%s: out of memory\n", *argv);
324 ExitProgram(EXIT_FAILURE);
327 for (y = length; --y >= 0;)
333 for (y = bottom; --y >= 0;) {
334 for (x = COLS; --x >= 0;) {
335 addch((chtype) (*p++));
344 nodelay(stdscr, TRUE);
349 if (trace_start || trace_end) {
350 if (generation == trace_start) {
353 } else if (generation == trace_end) {
358 if (singlestep && generation > trace_start && generation < trace_end)
366 if ((ch = getch()) > 0) {
368 if (ch == KEY_RESIZE) {
369 if (last != COLS - 1) {
370 for (y = 0; y <= bottom; y++) {
371 ref[y] = typeRealloc(short, COLS, ref[y]);
372 for (x = last + 1; x < COLS; x++)
377 if (bottom != LINES - 1) {
378 for (y = LINES; y <= bottom; y++)
380 ref = typeRealloc(short *, LINES, ref);
381 for (y = bottom + 1; y < LINES; y++) {
382 ref[y] = typeMalloc(short, COLS);
383 for (x = 0; x < COLS; x++)
391 * Make it simple to put this into single-step mode, or resume
392 * normal operation -T.Dickey
397 } else if (ch == 's') {
398 nodelay(stdscr, FALSE);
399 } else if (ch == ' ') {
400 nodelay(stdscr, TRUE);
405 for (n = 0, w = &worm[0]; n < number; n++, w++) {
406 if ((x = w->xpos[h = w->head]) < 0) {
407 move(y = w->ypos[h] = bottom, x = w->xpos[h] = 0);
408 addch(flavor[n % SIZEOF(flavor)]);
419 if (w->xpos[w->head = h] >= 0) {
425 && --ref[y1][x1] == 0) {
430 op = &(x == 0 ? (y == 0 ? upleft : (y == bottom ? lowleft :
432 (x == last ? (y == 0 ? upright : (y == bottom ? lowright :
434 (y == 0 ? upper : (y == bottom ? lower : normal))))[w->orientation];
440 w->orientation = op->opts[0];
443 w->orientation = op->opts[(int) (ranf() * (float) op->nopts)];
445 move(y += yinc[w->orientation], x += xinc[w->orientation]);
449 addch(flavor[n % SIZEOF(flavor)]);
450 ref[w->ypos[h] = y][w->xpos[h] = x]++;
458 for (y = 0; y < LINES; y++) {
462 for (n = number, w = &worm[0]; --n >= 0; w++) {
467 ExitProgram(EXIT_SUCCESS);