1 /****************************************************************************
2 * Copyright (c) 1998-2007,2008 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.60 2010/11/13 20:21:21 tom Exp $
67 #include <test.priv.h>
76 #define MAX_LENGTH 1024
78 static chtype flavor
[] =
80 'O', '*', '#', '$', '%', '0', '@',
82 static const int xinc
[] =
84 1, 1, 1, 0, -1, -1, -1, 0
87 -1, 0, 1, 1, 1, 0, -1, -1
101 static unsigned long sequence
= 0;
102 static bool quitting
= FALSE
;
104 static WORM worm
[MAX_WORMS
];
106 static int last_x
, last_y
;
108 static const char *field
;
109 static int length
= 16, number
= 3;
110 static chtype trail
= ' ';
112 static unsigned pending
;
114 static int generation
, trace_start
, trace_end
;
117 static const struct options
{
207 USING_WINDOW(stdscr
, wrefresh
);
213 onsig(int sig GCC_UNUSED
)
216 ExitProgram(EXIT_FAILURE
);
222 long r
= (rand() & 077777);
223 return ((double) r
/ 32768.);
227 draw_worm(WINDOW
*win
, void *data
)
229 WORM
*w
= (WORM
*) data
;
230 const struct options
*op
;
231 unsigned mask
= (unsigned) (~(1 << (w
- worm
)));
232 chtype attrs
= w
->attrs
| ((mask
& pending
) ? A_REVERSE
: 0);
240 if ((x
= w
->xpos
[h
= w
->head
]) < 0) {
241 wmove(win
, y
= w
->ypos
[h
] = last_y
, x
= w
->xpos
[h
] = 0);
256 if (w
->xpos
[w
->head
= h
] >= 0) {
262 && --refs
[y1
][x1
] == 0) {
284 : normal
))))[w
->orientation
];
291 w
->orientation
= op
->opts
[0];
294 w
->orientation
= op
->opts
[(int) (ranf() * (double) op
->nopts
)];
299 x
+= xinc
[w
->orientation
];
300 y
+= yinc
[w
->orientation
];
317 quit_worm(int bitnum
)
319 pending
|= (1 << bitnum
);
320 napms(10); /* let the other thread(s) have a chance */
321 pending
&= ~(1 << bitnum
);
326 start_worm(void *arg
)
328 unsigned long compare
= 0;
329 Trace(("start_worm"));
330 while (!quit_worm(((struct worm
*) arg
) - worm
)) {
331 while (compare
< sequence
) {
334 use_window(stdscr
, draw_worm
, arg
);
336 draw_worm(stdscr
, arg
);
340 Trace(("...start_worm (done)"));
353 static bool first
= TRUE
;
356 for (n
= 0, w
= &worm
[0]; n
< number
; n
++, w
++) {
358 rc
= pthread_create(&(w
->thread
), NULL
, start_worm
, w
);
362 for (n
= 0, w
= &worm
[0]; n
< number
; n
++, w
++) {
365 USING_WINDOW2(stdscr
, draw_worm
, w
)
380 ch
= USING_WINDOW(stdscr
, wgetch
);
386 update_refs(WINDOW
*win
)
391 if (last_x
!= COLS
- 1) {
392 for (y
= 0; y
<= last_y
; y
++) {
393 refs
[y
] = typeRealloc(int, (size_t) COLS
, refs
[y
]);
394 for (x
= last_x
+ 1; x
< COLS
; x
++)
399 if (last_y
!= LINES
- 1) {
400 for (y
= LINES
; y
<= last_y
; y
++)
402 refs
= typeRealloc(int *, (size_t) LINES
, refs
);
403 for (y
= last_y
+ 1; y
< LINES
; y
++) {
404 refs
[y
] = typeMalloc(int, (size_t) COLS
);
405 for (x
= 0; x
< COLS
; x
++)
415 main(int argc
, char *argv
[])
423 setlocale(LC_ALL
, "");
425 for (x
= 1; x
< argc
; x
++) {
437 if ((length
= atoi(argv
[x
])) < 2 || length
> MAX_LENGTH
) {
438 fprintf(stderr
, "%s: Invalid length\n", *argv
);
439 ExitProgram(EXIT_FAILURE
);
445 if ((number
= atoi(argv
[x
])) < 1 || number
> MAX_WORMS
) {
446 fprintf(stderr
, "%s: Invalid number of worms\n", *argv
);
447 ExitProgram(EXIT_FAILURE
);
455 trace_start
= atoi(argv
[++x
]);
456 trace_end
= atoi(argv
[++x
]);
459 _nc_optimize_enable
^= OPTIMIZE_ALL
; /* declared by ncurses */
465 "usage: %s [-field] [-length #] [-number #] [-trail]\n", *argv
);
466 ExitProgram(EXIT_FAILURE
);
470 signal(SIGINT
, onsig
);
483 int bg
= COLOR_BLACK
;
485 #if HAVE_USE_DEFAULT_COLORS
486 if (use_default_colors() == OK
)
490 #define SET_COLOR(num, fg) \
491 init_pair(num+1, (short) fg, (short) bg); \
492 flavor[num] |= COLOR_PAIR(num+1) | A_BOLD
494 SET_COLOR(0, COLOR_GREEN
);
495 SET_COLOR(1, COLOR_RED
);
496 SET_COLOR(2, COLOR_CYAN
);
497 SET_COLOR(3, COLOR_WHITE
);
498 SET_COLOR(4, COLOR_MAGENTA
);
499 SET_COLOR(5, COLOR_BLUE
);
500 SET_COLOR(6, COLOR_YELLOW
);
504 refs
= typeMalloc(int *, (size_t) LINES
);
505 for (y
= 0; y
< LINES
; y
++) {
506 refs
[y
] = typeMalloc(int, (size_t) COLS
);
507 for (x
= 0; x
< COLS
; x
++) {
513 /* if addressing the lower right corner doesn't work in your curses */
514 refs
[last_y
][last_x
] = 1;
515 #endif /* BADCORNER */
517 for (n
= number
, w
= &worm
[0]; --n
>= 0; w
++) {
518 w
->attrs
= flavor
[(unsigned) n
% SIZEOF(flavor
)];
522 if (!(ip
= typeMalloc(int, (size_t) (length
+ 1)))) {
523 fprintf(stderr
, "%s: out of memory\n", *argv
);
524 ExitProgram(EXIT_FAILURE
);
527 for (x
= length
; --x
>= 0;)
529 if (!(ip
= typeMalloc(int, (size_t) (length
+ 1)))) {
530 fprintf(stderr
, "%s: out of memory\n", *argv
);
531 ExitProgram(EXIT_FAILURE
);
534 for (y
= length
; --y
>= 0;)
540 for (y
= last_y
; --y
>= 0;) {
541 for (x
= COLS
; --x
>= 0;) {
542 addch((chtype
) (*p
++));
548 USING_WINDOW(stdscr
, wrefresh
);
549 nodelay(stdscr
, TRUE
);
555 if ((ch
= get_input()) > 0) {
557 if (trace_start
|| trace_end
) {
558 if (generation
== trace_start
) {
561 } else if (generation
== trace_end
) {
571 if (ch
== KEY_RESIZE
) {
572 USING_WINDOW(stdscr
, update_refs
);
577 * Make it simple to put this into single-step mode, or resume
578 * normal operation -T.Dickey
584 } else if (ch
== 's') {
585 nodelay(stdscr
, FALSE
);
586 } else if (ch
== ' ') {
587 nodelay(stdscr
, TRUE
);
591 done
= draw_all_worms();
593 USING_WINDOW(stdscr
, wrefresh
);
599 for (y
= 0; y
< LINES
; y
++) {
603 for (n
= number
, w
= &worm
[0]; --n
>= 0; w
++) {
610 * Do this just in case one of the threads did not really exit.
612 Trace(("join all threads"));
613 for (n
= 0; n
< number
; n
++) {
614 pthread_join(worm
[n
].thread
, NULL
);
617 ExitProgram(EXIT_SUCCESS
);