]>
git.cameronkatri.com Git - bsdgames-darwin.git/blob - hunt/hunt/otto.c
1 /* $NetBSD: otto.c,v 1.7 2004/02/08 22:23:50 jsm Exp $ */
4 * Copyright (c) 1983-2003, Regents of the University of California.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
11 * + Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * + Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * + Neither the name of the University of California, San Francisco nor
17 * the names of its contributors may be used to endorse or promote
18 * products derived from this software without specific prior written
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 * otto - a hunt otto-matic player
37 * This guy is buggy, unfair, stupid, and not extensible.
38 * Future versions of hunt will have a subroutine library for
39 * automatic players to link to. If you write your own "otto"
40 * please let us know what subroutines you would expect in the
43 * Id: otto.c,v 1.14 2003/04/16 06:11:54 gregc Exp
46 #include <sys/cdefs.h>
48 __RCSID("$NetBSD: otto.c,v 1.7 2004/02/08 22:23:50 jsm Exp $");
51 # include <sys/time.h>
74 extern char screen
[SCREEN_HEIGHT
][SCREEN_WIDTH2
];
75 # define SCREEN(y, x) screen[y][x]
77 # define SCREEN(y, x) mvinch(y, x)
81 # define STATIC static
86 # define OPPONENT "{}i!"
87 # define PROPONENT "^v<>"
88 # define WALL "+\\/#*-|"
89 # define PUSHOVER " bg;*#&"
90 # define SHOTS "$@Oo:"
92 /* number of "directions" */
93 # define NUMDIRECTIONS 4
95 /* absolute directions (facings) - counterclockwise */
102 /* relative directions - counterclockwise */
108 # define ABSCHARS "NWSE"
109 # define RELCHARS "FLBR"
110 # define DIRKEYS "khjl"
112 STATIC
char command
[BUFSIZ
];
116 STATIC
FILE *debug
= NULL
;
121 # define ON_RIGHT 0x4
122 # define ON_SIDE (ON_LEFT|ON_RIGHT)
124 # define BEEN_SAME 0x10
132 STATIC
struct item flbr
[NUMDIRECTIONS
];
134 # define fitem flbr[FRONT]
135 # define litem flbr[LEFT]
136 # define bitem flbr[BACK]
137 # define ritem flbr[RIGHT]
141 STATIC
int num_turns
; /* for wandering */
142 STATIC
char been_there
[HEIGHT
][WIDTH2
];
143 STATIC
struct itimerval pause_time
= { { 0, 0 }, { 0, 55000 }};
145 STATIC
void attack(int, struct item
*);
146 STATIC
void duck(int);
147 STATIC
void face_and_move_direction(int, int);
148 STATIC
int go_for_ammo(char);
149 STATIC
void ottolook(int, struct item
*);
150 STATIC
void look_around(void);
151 STATIC SIGNAL_TYPE
nothing(int);
152 STATIC
int stop_look(struct item
*, char, int, int);
153 STATIC
void wander(void);
155 extern int Otto_count
;
159 int dummy
__attribute__((__unused__
));
173 debug
= fopen("bug", "w");
176 fprintf(debug
, "\n%c(%d,%d)", face
, y
, x
);
178 (void) signal(SIGALRM
, nothing
);
179 old_mask
= sigblock(sigmask(SIGALRM
));
180 setitimer(ITIMER_REAL
, &pause_time
, NULL
);
182 sigsetmask(old_mask
);
184 /* save away parameters so other functions may use/update info */
186 case '^': facing
= NORTH
; break;
187 case '<': facing
= WEST
; break;
188 case 'v': facing
= SOUTH
; break;
189 case '>': facing
= EAST
; break;
193 been_there
[row
][col
] |= 1 << facing
;
195 /* initially no commands to be sent */
198 /* find something to do */
200 for (i
= 0; i
< NUMDIRECTIONS
; i
++) {
201 if (strchr(OPPONENT
, flbr
[i
].what
) != NULL
) {
203 memset(been_there
, 0, sizeof been_there
);
208 if (strchr(SHOTS
, bitem
.what
) != NULL
&& !(bitem
.what
& ON_SIDE
)) {
210 memset(been_there
, 0, sizeof been_there
);
212 } else if (go_for_ammo(BOOT_PAIR
)) {
213 memset(been_there
, 0, sizeof been_there
);
214 } else if (go_for_ammo(BOOT
)) {
215 memset(been_there
, 0, sizeof been_there
);
217 } else if (go_for_ammo(GMINE
))
218 memset(been_there
, 0, sizeof been_there
);
219 else if (go_for_ammo(MINE
))
220 memset(been_there
, 0, sizeof been_there
);
225 (void) write(Socket
, command
, comlen
);
226 Otto_count
+= comlen
;
228 (void) fwrite(command
, 1, comlen
, debug
);
232 # define direction(abs,rel) (((abs) + (rel)) % NUMDIRECTIONS)
235 stop_look(itemp
, c
, dist
, side
)
245 itemp
->flags
&= ~DEADEND
;
254 if (itemp
->distance
== -1) {
255 itemp
->distance
= dist
;
258 itemp
->flags
|= ON_LEFT
;
260 itemp
->flags
|= ON_RIGHT
;
271 if (itemp
->distance
== -1 || (!side
272 && (itemp
->flags
& ON_SIDE
273 || itemp
->what
== GMINE
|| itemp
->what
== MINE
))) {
274 itemp
->distance
= dist
;
276 itemp
->flags
&= ~ON_SIDE
;
278 itemp
->flags
|= ON_LEFT
;
280 itemp
->flags
|= ON_RIGHT
;
288 itemp
->distance
= dist
;
290 itemp
->flags
&= ~(ON_SIDE
|DEADEND
);
292 itemp
->flags
|= ON_LEFT
;
294 itemp
->flags
|= ON_RIGHT
;
298 /* a wall or unknown object */
301 if (itemp
->distance
== -1) {
302 itemp
->distance
= dist
;
310 ottolook(rel_dir
, itemp
)
319 itemp
->distance
= -1;
320 itemp
->flags
= DEADEND
|BEEN
; /* true until proven false */
322 switch (direction(facing
, rel_dir
)) {
325 if (been_there
[row
- 1][col
] & NORTH
)
326 itemp
->flags
|= BEEN_SAME
;
327 for (r
= row
- 1; r
>= 0; r
--)
328 for (c
= col
- 1; c
< col
+ 2; c
++) {
330 if (stop_look(itemp
, ch
, row
- r
, c
- col
))
332 if (c
== col
&& !been_there
[r
][c
])
333 itemp
->flags
&= ~BEEN
;
336 if (itemp
->flags
& DEADEND
) {
337 itemp
->flags
|= BEEN
;
338 been_there
[r
][col
] |= NORTH
;
339 for (r
= row
- 1; r
> row
- itemp
->distance
; r
--)
340 been_there
[r
][col
] = ALLDIRS
;
345 if (been_there
[row
+ 1][col
] & SOUTH
)
346 itemp
->flags
|= BEEN_SAME
;
347 for (r
= row
+ 1; r
< HEIGHT
; r
++)
348 for (c
= col
- 1; c
< col
+ 2; c
++) {
350 if (stop_look(itemp
, ch
, r
- row
, col
- c
))
352 if (c
== col
&& !been_there
[r
][c
])
353 itemp
->flags
&= ~BEEN
;
356 if (itemp
->flags
& DEADEND
) {
357 itemp
->flags
|= BEEN
;
358 been_there
[r
][col
] |= SOUTH
;
359 for (r
= row
+ 1; r
< row
+ itemp
->distance
; r
++)
360 been_there
[r
][col
] = ALLDIRS
;
365 if (been_there
[row
][col
- 1] & WEST
)
366 itemp
->flags
|= BEEN_SAME
;
367 for (c
= col
- 1; c
>= 0; c
--)
368 for (r
= row
- 1; r
< row
+ 2; r
++) {
370 if (stop_look(itemp
, ch
, col
- c
, row
- r
))
372 if (r
== row
&& !been_there
[r
][c
])
373 itemp
->flags
&= ~BEEN
;
376 if (itemp
->flags
& DEADEND
) {
377 itemp
->flags
|= BEEN
;
378 been_there
[r
][col
] |= WEST
;
379 for (c
= col
- 1; c
> col
- itemp
->distance
; c
--)
380 been_there
[row
][c
] = ALLDIRS
;
385 if (been_there
[row
][col
+ 1] & EAST
)
386 itemp
->flags
|= BEEN_SAME
;
387 for (c
= col
+ 1; c
< WIDTH
; c
++)
388 for (r
= row
- 1; r
< row
+ 2; r
++) {
390 if (stop_look(itemp
, ch
, c
- col
, r
- row
))
392 if (r
== row
&& !been_there
[r
][c
])
393 itemp
->flags
&= ~BEEN
;
396 if (itemp
->flags
& DEADEND
) {
397 itemp
->flags
|= BEEN
;
398 been_there
[r
][col
] |= EAST
;
399 for (c
= col
+ 1; c
< col
+ itemp
->distance
; c
++)
400 been_there
[row
][c
] = ALLDIRS
;
414 for (i
= 0; i
< NUMDIRECTIONS
; i
++) {
415 ottolook(i
, &flbr
[i
]);
417 fprintf(debug
, " ottolook(%c)=%c(%d)(0x%x)",
418 RELCHARS
[i
], flbr
[i
].what
, flbr
[i
].distance
, flbr
[i
].flags
);
424 * as a side effect modifies facing and location (row, col)
428 face_and_move_direction(rel_dir
, distance
)
429 int rel_dir
, distance
;
435 cmd
= DIRKEYS
[facing
= direction(facing
, rel_dir
)];
437 if (rel_dir
!= FRONT
) {
439 struct item items
[NUMDIRECTIONS
];
441 command
[comlen
++] = toupper(cmd
);
443 /* rotate ottolook's to be in right position */
444 for (i
= 0; i
< NUMDIRECTIONS
; i
++)
446 flbr
[(i
+ old_facing
) % NUMDIRECTIONS
];
447 memcpy(flbr
, items
, sizeof flbr
);
451 command
[comlen
++] = cmd
;
454 case NORTH
: row
--; break;
455 case WEST
: col
--; break;
456 case SOUTH
: row
++; break;
457 case EAST
: col
++; break;
465 attack(rel_dir
, itemp
)
469 if (!(itemp
->flags
& ON_SIDE
)) {
470 face_and_move_direction(rel_dir
, 0);
471 command
[comlen
++] = 'o';
472 command
[comlen
++] = 'o';
474 command
[comlen
++] = ' ';
475 } else if (itemp
->distance
> 1) {
476 face_and_move_direction(rel_dir
, 2);
479 face_and_move_direction(rel_dir
, 1);
480 if (itemp
->flags
& ON_LEFT
)
484 (void) face_and_move_direction(rel_dir
, 0);
485 command
[comlen
++] = 'f';
486 command
[comlen
++] = 'f';
488 command
[comlen
++] = ' ';
498 switch (dir
= direction(facing
, rel_dir
)) {
502 if (strchr(PUSHOVER
, SCREEN(row
, col
- 1)) != NULL
)
503 command
[comlen
++] = 'h';
504 else if (strchr(PUSHOVER
, SCREEN(row
, col
+ 1)) != NULL
)
505 command
[comlen
++] = 'l';
506 else if (dir
== NORTH
507 && strchr(PUSHOVER
, SCREEN(row
+ 1, col
)) != NULL
)
508 command
[comlen
++] = 'j';
509 else if (dir
== SOUTH
510 && strchr(PUSHOVER
, SCREEN(row
- 1, col
)) != NULL
)
511 command
[comlen
++] = 'k';
512 else if (dir
== NORTH
)
513 command
[comlen
++] = 'k';
515 command
[comlen
++] = 'j';
520 if (strchr(PUSHOVER
, SCREEN(row
- 1, col
)) != NULL
)
521 command
[comlen
++] = 'k';
522 else if (strchr(PUSHOVER
, SCREEN(row
+ 1, col
)) != NULL
)
523 command
[comlen
++] = 'j';
525 && strchr(PUSHOVER
, SCREEN(row
, col
+ 1)) != NULL
)
526 command
[comlen
++] = 'l';
528 && strchr(PUSHOVER
, SCREEN(row
, col
- 1)) != NULL
)
529 command
[comlen
++] = 'h';
530 else if (dir
== WEST
)
531 command
[comlen
++] = 'h';
533 command
[comlen
++] = 'l';
539 * go for the closest mine if possible
546 int i
, rel_dir
, dist
;
550 for (i
= 0; i
< NUMDIRECTIONS
; i
++) {
551 if (flbr
[i
].what
== mine
&& flbr
[i
].distance
< dist
) {
553 dist
= flbr
[i
].distance
;
559 if (!(flbr
[rel_dir
].flags
& ON_SIDE
)
560 || flbr
[rel_dir
].distance
> 1) {
563 face_and_move_direction(rel_dir
, dist
);
565 return FALSE
; /* until it's done right */
572 int i
, j
, rel_dir
, dir_mask
, dir_count
;
574 for (i
= 0; i
< NUMDIRECTIONS
; i
++)
575 if (!(flbr
[i
].flags
& BEEN
) || flbr
[i
].distance
<= 1)
577 if (i
== NUMDIRECTIONS
)
578 memset(been_there
, 0, sizeof been_there
);
579 dir_mask
= dir_count
= 0;
580 for (i
= 0; i
< NUMDIRECTIONS
; i
++) {
581 j
= (RIGHT
+ i
) % NUMDIRECTIONS
;
582 if (flbr
[j
].distance
<= 1 || flbr
[j
].flags
& DEADEND
)
584 if (!(flbr
[j
].flags
& BEEN_SAME
)) {
590 && num_turns
> 4 + (random() %
591 ((flbr
[FRONT
].flags
& BEEN
) ? 7 : HEIGHT
)))
601 if (dir_count
== 0) {
602 duck(random() % NUMDIRECTIONS
);
605 } else if (dir_count
== 1)
606 rel_dir
= ffs(dir_mask
) - 1;
608 rel_dir
= ffs(dir_mask
) - 1;
609 dir_mask
&= ~(1 << rel_dir
);
610 while (dir_mask
!= 0) {
611 i
= ffs(dir_mask
) - 1;
612 if (random() % 5 == 0)
614 dir_mask
&= ~(1 << i
);
617 if (rel_dir
== FRONT
)
623 fprintf(debug
, " w(%c)", RELCHARS
[rel_dir
]);
625 face_and_move_direction(rel_dir
, 1);