1 /****************************************************************************
2 * Copyright (c) 1998-2006,2007 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.49 2007/09/29 17:35:57 tom Exp $
67 #include <test.priv.h>
73 static chtype flavor[] =
75 'O', '*', '#', '$', '%', '0', '@',
77 static const short xinc[] =
79 1, 1, 1, 0, -1, -1, -1, 0
82 -1, 0, 1, 1, 1, 0, -1, -1
99 static const char *field;
100 static int length = 16, number = 3;
101 static chtype trail = ' ';
104 static int generation, trace_start, trace_end;
107 static const struct options {
204 onsig(int sig GCC_UNUSED)
207 ExitProgram(EXIT_FAILURE);
213 long r = (rand() & 077777);
214 return ((float) r / 32768.);
218 draw_worm(WINDOW *win, void *data)
220 WORM *w = (WORM *) data;
221 const struct options *op;
227 int bottom = LINES - 1;
232 if ((x = w->xpos[h = w->head]) < 0) {
233 wmove(win, y = w->ypos[h] = bottom, x = w->xpos[h] = 0);
234 waddch(win, w->attrs);
248 if (w->xpos[w->head = h] >= 0) {
254 && --refs[y1][x1] == 0) {
276 : normal))))[w->orientation];
283 w->orientation = op->opts[0];
286 w->orientation = op->opts[(int) (ranf() * (float) op->nopts)];
291 x += xinc[w->orientation];
292 y += yinc[w->orientation];
297 waddch(win, w->attrs);
307 #if !defined(NCURSES_VERSION_PATCH) || (NCURSES_VERSION_PATCH < 20070915)
309 use_window(WINDOW *win, int (*func) (WINDOW *, void *), void *data)
311 return func(win, data);
317 start_worm(void *arg)
321 use_window(stdscr, draw_worm, arg);
335 static bool first = TRUE;
338 for (n = 0, w = &worm[0]; n < number; n++, w++) {
340 rc = pthread_create(&(w->thread), NULL, start_worm, w);
344 for (n = 0, w = &worm[0]; n < number; n++, w++) {
345 if (use_window(stdscr, draw_worm, w))
353 main(int argc, char *argv[])
362 setlocale(LC_ALL, "");
364 for (x = 1; x < argc; x++) {
376 if ((length = atoi(argv[x])) < 2 || length > 1024) {
377 fprintf(stderr, "%s: Invalid length\n", *argv);
378 ExitProgram(EXIT_FAILURE);
384 if ((number = atoi(argv[x])) < 1 || number > 40) {
385 fprintf(stderr, "%s: Invalid number of worms\n", *argv);
386 ExitProgram(EXIT_FAILURE);
394 trace_start = atoi(argv[++x]);
395 trace_end = atoi(argv[++x]);
398 _nc_optimize_enable ^= OPTIMIZE_ALL; /* declared by ncurses */
404 "usage: %s [-field] [-length #] [-number #] [-trail]\n", *argv);
405 ExitProgram(EXIT_FAILURE);
409 signal(SIGINT, onsig);
422 int bg = COLOR_BLACK;
424 #if HAVE_USE_DEFAULT_COLORS
425 if (use_default_colors() == OK)
429 #define SET_COLOR(num, fg) \
430 init_pair(num+1, fg, bg); \
431 flavor[num] |= COLOR_PAIR(num+1) | A_BOLD
433 SET_COLOR(0, COLOR_GREEN);
434 SET_COLOR(1, COLOR_RED);
435 SET_COLOR(2, COLOR_CYAN);
436 SET_COLOR(3, COLOR_WHITE);
437 SET_COLOR(4, COLOR_MAGENTA);
438 SET_COLOR(5, COLOR_BLUE);
439 SET_COLOR(6, COLOR_YELLOW);
443 refs = typeMalloc(short *, LINES);
444 for (y = 0; y < LINES; y++) {
445 refs[y] = typeMalloc(short, COLS);
446 for (x = 0; x < COLS; x++) {
452 /* if addressing the lower right corner doesn't work in your curses */
453 refs[bottom][last] = 1;
454 #endif /* BADCORNER */
456 for (n = number, w = &worm[0]; --n >= 0; w++) {
457 w->attrs = flavor[n % SIZEOF(flavor)];
461 if (!(ip = typeMalloc(short, (length + 1)))) {
462 fprintf(stderr, "%s: out of memory\n", *argv);
463 ExitProgram(EXIT_FAILURE);
466 for (x = length; --x >= 0;)
468 if (!(ip = typeMalloc(short, (length + 1)))) {
469 fprintf(stderr, "%s: out of memory\n", *argv);
470 ExitProgram(EXIT_FAILURE);
473 for (y = length; --y >= 0;)
479 for (y = bottom; --y >= 0;) {
480 for (x = COLS; --x >= 0;) {
481 addch((chtype) (*p++));
489 nodelay(stdscr, TRUE);
494 if ((ch = getch()) > 0) {
496 if (trace_start || trace_end) {
497 if (generation == trace_start) {
500 } else if (generation == trace_end) {
509 if (ch == KEY_RESIZE) {
510 if (last != COLS - 1) {
511 for (y = 0; y <= bottom; y++) {
512 refs[y] = typeRealloc(short, COLS, refs[y]);
513 for (x = last + 1; x < COLS; x++)
518 if (bottom != LINES - 1) {
519 for (y = LINES; y <= bottom; y++)
521 refs = typeRealloc(short *, LINES, refs);
522 for (y = bottom + 1; y < LINES; y++) {
523 refs[y] = typeMalloc(short, COLS);
524 for (x = 0; x < COLS; x++)
532 * Make it simple to put this into single-step mode, or resume
533 * normal operation -T.Dickey
538 } else if (ch == 's') {
539 nodelay(stdscr, FALSE);
540 } else if (ch == ' ') {
541 nodelay(stdscr, TRUE);
545 done = draw_all_worms();
552 for (y = 0; y < LINES; y++) {
556 for (n = number, w = &worm[0]; --n >= 0; w++) {
561 ExitProgram(EXIT_SUCCESS);