1 /* $NetBSD: auto.c,v 1.10 2009/07/20 06:00:56 dholland Exp $ */
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
36 * IF scrapheaps don't exist THEN
37 * IF not in danger THEN
38 * stay at current position
40 * move away from the closest robot
45 * IF scrapheap is adjacent THEN
46 * move behind the scrapheap
48 * take the move that takes you away from the
49 * robots and closest to the heap
57 #define ABS(a) (((a)>0)?(a):-(a))
58 #define MIN(a,b) (((a)>(b))?(b):(a))
59 #define MAX(a,b) (((a)<(b))?(b):(a))
63 static int distance(int, int, int, int);
66 static const char *find_moves(void);
67 static COORD
*closest_robot(int *);
68 static COORD
*closest_heap(int *);
69 static char move_towards(int, int);
70 static char move_away(COORD
*);
71 static char move_between(COORD
*, COORD
*);
72 static int between(COORD
*, COORD
*);
75 * return "move" number distance of the two coordinates
78 distance(int x1
, int y1
, int x2
, int y2
)
80 return MAX(ABS(ABS(x1
) - ABS(x2
)), ABS(ABS(y1
) - ABS(y2
)));
84 * Return x coordinate moves
106 * Return y coordinate moves
128 * Find possible moves
137 static const char moves
[] = ".hjklyubn";
138 static char ans
[sizeof moves
];
141 for (m
= moves
; *m
; m
++) {
142 test
.x
= My_pos
.x
+ xinc(*m
);
143 test
.y
= My_pos
.y
+ yinc(*m
);
144 move(test
.y
, test
.x
);
145 switch(winch(stdscr
)) {
148 for (x
= test
.x
- 1; x
<= test
.x
+ 1; x
++) {
149 for (y
= test
.y
- 1; y
<= test
.y
+ 1; y
++) {
151 if (winch(stdscr
) == ROBOT
)
167 * return the robot closest to us
168 * and put in dist its distance
171 closest_robot(int *dist
)
173 COORD
*rob
, *end
, *minrob
= NULL
;
177 end
= &Robots
[MAXROBOTS
];
178 for (rob
= Robots
; rob
< end
; rob
++) {
179 tdist
= distance(My_pos
.x
, My_pos
.y
, rob
->x
, rob
->y
);
180 if (tdist
< mindist
) {
190 * return the heap closest to us
191 * and put in dist its distance
194 closest_heap(int *dist
)
196 COORD
*hp
, *end
, *minhp
= NULL
;
200 end
= &Scrap
[MAXROBOTS
];
201 for (hp
= Scrap
; hp
< end
; hp
++) {
202 if (hp
->x
== 0 && hp
->y
== 0)
204 tdist
= distance(My_pos
.x
, My_pos
.y
, hp
->x
, hp
->y
);
205 if (tdist
< mindist
) {
215 * move as close to the given direction as possible
218 move_towards(int dx
, int dy
)
220 char ok_moves
[10], best_move
;
222 int move_judge
, cur_judge
, mvx
, mvy
;
224 (void)strcpy(ok_moves
, find_moves());
225 best_move
= ok_moves
[0];
226 if (best_move
!= 't') {
227 mvx
= xinc(best_move
);
228 mvy
= yinc(best_move
);
229 move_judge
= ABS(mvx
- dx
) + ABS(mvy
- dy
);
230 for (ptr
= &ok_moves
[1]; *ptr
!= '\0'; ptr
++) {
233 cur_judge
= ABS(mvx
- dx
) + ABS(mvy
- dy
);
234 if (cur_judge
< move_judge
) {
235 move_judge
= cur_judge
;
244 * move away form the robot given
247 move_away(COORD
*rob
)
251 dx
= sign(My_pos
.x
- rob
->x
);
252 dy
= sign(My_pos
.y
- rob
->y
);
253 return move_towards(dx
, dy
);
258 * move the closest heap between us and the closest robot
261 move_between(COORD
*rob
, COORD
*hp
)
266 /* equation of the line between us and the closest robot */
267 if (My_pos
.x
== rob
->x
) {
269 * me and the robot are aligned in x
270 * change my x so I get closer to the heap
271 * and my y far from the robot
273 dx
= - sign(My_pos
.x
- hp
->x
);
274 dy
= sign(My_pos
.y
- rob
->y
);
275 CONSDEBUG(("aligned in x"));
277 else if (My_pos
.y
== rob
->y
) {
279 * me and the robot are aligned in y
280 * change my y so I get closer to the heap
281 * and my x far from the robot
283 dx
= sign(My_pos
.x
- rob
->x
);
284 dy
= -sign(My_pos
.y
- hp
->y
);
285 CONSDEBUG(("aligned in y"));
288 CONSDEBUG(("no aligned"));
289 slope
= (My_pos
.y
- rob
->y
) / (My_pos
.x
- rob
->x
);
290 cons
= slope
* rob
->y
;
291 if (ABS(My_pos
.x
- rob
->x
) > ABS(My_pos
.y
- rob
->y
)) {
293 * we are closest to the robot in x
294 * move away from the robot in x and
295 * close to the scrap in y
297 dx
= sign(My_pos
.x
- rob
->x
);
298 dy
= sign(((slope
* ((float) hp
->x
)) + cons
) -
302 dx
= sign(((slope
* ((float) hp
->x
)) + cons
) -
304 dy
= sign(My_pos
.y
- rob
->y
);
307 CONSDEBUG(("me (%d,%d) robot(%d,%d) heap(%d,%d) delta(%d,%d)",
308 My_pos
.x
, My_pos
.y
, rob
->x
, rob
->y
, hp
->x
, hp
->y
, dx
, dy
));
309 return move_towards(dx
, dy
);
313 * Return true if the heap is between us and the robot
316 between(COORD
*rob
, COORD
*hp
)
319 if (hp
->x
> rob
->x
&& My_pos
.x
< rob
->x
)
322 if (hp
->x
< rob
->x
&& My_pos
.x
> rob
->x
)
327 if (hp
->y
< rob
->y
&& My_pos
.y
> rob
->y
)
332 if (hp
->y
> rob
->y
&& My_pos
.y
< rob
->y
)
338 * find and do the best move if flag
339 * else get the first move;
345 return find_moves()[0];
349 int robot_dist
, robot_heap
, heap_dist
;
351 robot_close
= closest_robot(&robot_dist
);
355 /* no scrap heaps just run away */
356 return move_away(robot_close
);
358 heap_close
= closest_heap(&heap_dist
);
359 robot_heap
= distance(robot_close
->x
, robot_close
->y
,
360 heap_close
->x
, heap_close
->y
);
361 if (robot_heap
<= heap_dist
&& !between(robot_close
, heap_close
)) {
363 * robot is closest to us from the heap. Run away!
365 return move_away(robot_close
);
368 return move_between(robot_close
, heap_close
);