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.37 2002/06/29 23:32:18 tom Exp $
40 #include <test.priv.h>
42 static chtype flavor
[] =
44 'O', '*', '#', '$', '%', '0', '@',
46 static const short xinc
[] =
48 1, 1, 1, 0, -1, -1, -1, 0
51 -1, 0, 1, 1, 1, 0, -1, -1
54 int orientation
, head
;
58 static const char *field
;
59 static int length
= 16, number
= 3;
60 static chtype trail
= ' ';
63 int generation
, trace_start
, trace_end
, singlestep
;
66 static const struct options
{
163 onsig(int sig GCC_UNUSED
)
166 ExitProgram(EXIT_FAILURE
);
172 long r
= (rand() & 077777);
173 return ((float) r
/ 32768.);
177 main(int argc
, char *argv
[])
183 const struct options
*op
;
188 setlocale(LC_ALL
, "");
190 for (x
= 1; x
< argc
; x
++) {
202 if ((length
= atoi(argv
[x
])) < 2 || length
> 1024) {
203 fprintf(stderr
, "%s: Invalid length\n", *argv
);
204 ExitProgram(EXIT_FAILURE
);
210 if ((number
= atoi(argv
[x
])) < 1 || number
> 40) {
211 fprintf(stderr
, "%s: Invalid number of worms\n", *argv
);
212 ExitProgram(EXIT_FAILURE
);
223 trace_start
= atoi(argv
[++x
]);
224 trace_end
= atoi(argv
[++x
]);
227 _nc_optimize_enable
^= OPTIMIZE_ALL
; /* declared by ncurses */
233 "usage: %s [-field] [-length #] [-number #] [-trail]\n", *argv
);
234 ExitProgram(EXIT_FAILURE
);
238 signal(SIGINT
, onsig
);
251 int bg
= COLOR_BLACK
;
253 #if HAVE_USE_DEFAULT_COLORS
254 if (use_default_colors() == OK
)
258 #define SET_COLOR(num, fg) \
259 init_pair(num+1, fg, bg); \
260 flavor[num] |= COLOR_PAIR(num+1) | A_BOLD
262 SET_COLOR(0, COLOR_GREEN
);
263 SET_COLOR(1, COLOR_RED
);
264 SET_COLOR(2, COLOR_CYAN
);
265 SET_COLOR(3, COLOR_WHITE
);
266 SET_COLOR(4, COLOR_MAGENTA
);
267 SET_COLOR(5, COLOR_BLUE
);
268 SET_COLOR(6, COLOR_YELLOW
);
272 ref
= typeMalloc(short *, LINES
);
273 for (y
= 0; y
< LINES
; y
++) {
274 ref
[y
] = typeMalloc(short, COLS
);
275 for (x
= 0; x
< COLS
; x
++) {
281 /* if addressing the lower right corner doesn't work in your curses */
282 ref
[bottom
][last
] = 1;
283 #endif /* BADCORNER */
285 for (n
= number
, w
= &worm
[0]; --n
>= 0; w
++) {
286 w
->orientation
= w
->head
= 0;
287 if (!(ip
= typeMalloc(short, (length
+ 1)))) {
288 fprintf(stderr
, "%s: out of memory\n", *argv
);
289 ExitProgram(EXIT_FAILURE
);
292 for (x
= length
; --x
>= 0;)
294 if (!(ip
= typeMalloc(short, (length
+ 1)))) {
295 fprintf(stderr
, "%s: out of memory\n", *argv
);
296 ExitProgram(EXIT_FAILURE
);
299 for (y
= length
; --y
>= 0;)
305 for (y
= bottom
; --y
>= 0;) {
306 for (x
= COLS
; --x
>= 0;) {
307 addch((chtype
) (*p
++));
316 nodelay(stdscr
, TRUE
);
321 if (trace_start
|| trace_end
) {
322 if (generation
== trace_start
) {
325 } else if (generation
== trace_end
) {
330 if (singlestep
&& generation
> trace_start
&& generation
< trace_end
)
338 if ((ch
= getch()) > 0) {
340 if (ch
== KEY_RESIZE
) {
341 if (last
!= COLS
- 1) {
342 for (y
= 0; y
<= bottom
; y
++) {
343 ref
[y
] = typeRealloc(short, COLS
, ref
[y
]);
344 for (x
= last
+ 1; x
< COLS
; x
++)
349 if (bottom
!= LINES
- 1) {
350 for (y
= LINES
; y
<= bottom
; y
++)
352 ref
= typeRealloc(short *, LINES
, ref
);
353 for (y
= bottom
+ 1; y
< LINES
; y
++) {
354 ref
[y
] = typeMalloc(short, COLS
);
355 for (x
= 0; x
< COLS
; x
++)
363 * Make it simple to put this into single-step mode, or resume
364 * normal operation -TD
368 ExitProgram(EXIT_SUCCESS
);
369 } else if (ch
== 's') {
370 nodelay(stdscr
, FALSE
);
371 } else if (ch
== ' ') {
372 nodelay(stdscr
, TRUE
);
377 for (n
= 0, w
= &worm
[0]; n
< number
; n
++, w
++) {
378 if ((x
= w
->xpos
[h
= w
->head
]) < 0) {
379 move(y
= w
->ypos
[h
] = bottom
, x
= w
->xpos
[h
] = 0);
380 addch(flavor
[n
% SIZEOF(flavor
)]);
391 if (w
->xpos
[w
->head
= h
] >= 0) {
397 && --ref
[y1
][x1
] == 0) {
402 op
= &(x
== 0 ? (y
== 0 ? upleft
: (y
== bottom
? lowleft
:
404 (x
== last
? (y
== 0 ? upright
: (y
== bottom
? lowright
:
406 (y
== 0 ? upper
: (y
== bottom
? lower
: normal
))))[w
->orientation
];
410 ExitProgram(EXIT_SUCCESS
);
412 w
->orientation
= op
->opts
[0];
415 w
->orientation
= op
->opts
[(int) (ranf() * (float) op
->nopts
)];
417 move(y
+= yinc
[w
->orientation
], x
+= xinc
[w
->orientation
]);
421 addch(flavor
[n
% SIZEOF(flavor
)]);
422 ref
[w
->ypos
[h
] = y
][w
->xpos
[h
] = x
]++;