diff options
Diffstat (limited to 'robots/auto.c')
-rw-r--r-- | robots/auto.c | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/robots/auto.c b/robots/auto.c new file mode 100644 index 00000000..f2621fff --- /dev/null +++ b/robots/auto.c @@ -0,0 +1,380 @@ +/* $NetBSD: auto.c,v 1.1 1999/05/15 23:56:35 christos Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Automatic move. + * intelligent ? + * Algo : + * IF scrapheaps don't exist THEN + * IF not in danger THEN + * stay at current position; + * ELSE move away from the closest robot; + * FI + * ELSE + * find closest heap; + * find closest robot; + * IF scrapheap is adjacenHEN + * move behind the scrapheap + * ELSE + * move away from the closest robot + * FI + * ELSE + * take the move that takes you away from the + * robots and closest to the heap + * FI + * FI + */ +#include "robots.h" + +#define ABS(a) (((a)>0)?(a):-(a)) +#define MIN(a,b) (((a)>(b))?(b):(a)) +#define MAX(a,b) (((a)<(b))?(b):(a)) + +#define CONSDEBUG(a) + + +/* distance(): + * return "move" number distance of the two coordinates + */ +static int +distance(x1, y1, x2, y2) + int x1, y1, x2, y2; +{ + return MAX(ABS(ABS(x1) - ABS(x2)), ABS(ABS(y1) - ABS(y2))); +} /* end distance */ + +/* xinc(): + * Return x coordinate moves + */ +static int +xinc(dir) + int dir; +{ + switch(dir) { + case 'b': + case 'h': + case 'y': + return -1; + case 'l': + case 'n': + case 'u': + return 1; + case 'j': + case 'k': + default: + return 0; + } +} + +/* yinc(): + * Return y coordinate moves + */ +static int +yinc(dir) + int dir; +{ + switch(dir) { + case 'k': + case 'u': + case 'y': + return -1; + case 'b': + case 'j': + case 'n': + return 1; + case 'h': + case 'l': + default: + return 0; + } +} + +/* find_moves(): + * Find possible moves + */ +static char * +find_moves() +{ + int x, y; + COORD test; + char *m, *a; + static char moves[] = ".hjklyubn"; + static char ans[sizeof moves]; + a = ans; + + for(m = moves; *m; m++) { + test.x = My_pos.x + xinc(*m); + test.y = My_pos.y + yinc(*m); + move(test.y, test.x); + switch(winch(stdscr)) { + case ' ': + case PLAYER: + for(x = test.x - 1; x <= test.x + 1; x++) { + for(y = test.y - 1; y <= test.y + 1; y++) { + move(y, x); + if(winch(stdscr) == ROBOT) + goto bad; + } + } + *a++ = *m; + } + bad:; + } + *a = 0; + if(ans[0]) + a = ans; + else + a = "t"; + return a; +} + +/* closest_robot(): + * return the robot closest to us + * and put in dist its distance + */ +static COORD * +closest_robot(dist) + int *dist; +{ + COORD *rob, *end, *minrob; + int tdist, mindist; + + mindist = 1000000; + end = &Robots[MAXROBOTS]; + for (rob = Robots; rob < end; rob++) { + tdist = distance(My_pos.x, My_pos.y, rob->x, rob->y); + if (tdist < mindist) { + minrob = rob; + mindist = tdist; + } + } + *dist = mindist; + return minrob; +} /* end closest_robot */ + +/* closest_heap(): + * return the heap closest to us + * and put in dist its distance + */ +static COORD * +closest_heap(dist) + int *dist; +{ + COORD *hp, *end, *minhp; + int mindist, tdist; + + mindist = 1000000; + end = &Scrap[MAXROBOTS]; + for (hp = Scrap; hp < end; hp++) { + if (hp->x == 0 && hp->y == 0) + break; + tdist = distance(My_pos.x, My_pos.y, hp->x, hp->y); + if (tdist < mindist) { + minhp = hp; + mindist = tdist; + } + } + *dist = mindist; + return minhp; +} /* end closest_heap */ + +/* move_towards(): + * move as close to the given direction as possible + */ +static char +move_towards(dx, dy) + int dx, dy; +{ + char ok_moves[10], best_move; + char *ptr; + int move_judge, cur_judge, mvx, mvy; + + (void)strcpy(ok_moves, find_moves()); + best_move = ok_moves[0]; + if (best_move != 'F') { + mvx = xinc(best_move); + mvy = yinc(best_move); + move_judge = ABS(mvx - dx) + ABS(mvy - dy); + for (ptr = &ok_moves[1]; *ptr != '\0'; ptr++) { + mvx = xinc(*ptr); + mvy = yinc(*ptr); + cur_judge = ABS(mvx - dx) + ABS(mvy - dy); + if (cur_judge < move_judge) { + move_judge = cur_judge; + best_move = *ptr; + } + } + } + return best_move; +} /* end move_towards */ + +/* move_away(): + * move away form the robot given + */ +static char +move_away(rob) + COORD *rob; +{ + int dx, dy; + + dx = sign(My_pos.x - rob->x); + dy = sign(My_pos.y - rob->y); + return move_towards(dx, dy); +} /* end move_away */ + + +/* move_between(): + * move the closest heap between us and the closest robot + */ +static char +move_between(rob, hp) + COORD *rob; + COORD *hp; +{ + char ok_moves[10], best_move; + char *ptr; + int move_judge, cur_judge, dx, dy, mvx, mvy; + float slope, cons; + + /* equation of the line between us and the closest robot */ + if (My_pos.x == rob->x) { + /* + * me and the robot are aligned in x + * change my x so I get closer to the heap + * and my y far from the robot + */ + dx = - sign(My_pos.x - hp->x); + dy = sign(My_pos.y - rob->y); + CONSDEBUG(("aligned in x")); + } + else if (My_pos.y == rob->y) { + /* + * me and the robot are aligned in y + * change my y so I get closer to the heap + * and my x far from the robot + */ + dx = sign(My_pos.x - rob->x); + dy = -sign(My_pos.y - hp->y); + CONSDEBUG(("aligned in y")); + } + else { + CONSDEBUG(("no aligned")); + slope = (My_pos.y - rob->y) / (My_pos.x - rob->x); + cons = slope * rob->y; + if (ABS(My_pos.x - rob->x) > ABS(My_pos.y - rob->y)) { + /* + * we are closest to the robot in x + * move away from the robot in x and + * close to the scrap in y + */ + dx = sign(My_pos.x - rob->x); + dy = sign(((slope * ((float) hp->x)) + cons) - + ((float) hp->y)); + } + else { + dx = sign(((slope * ((float) hp->x)) + cons) - + ((float) hp->y)); + dy = sign(My_pos.y - rob->y); + } + } + CONSDEBUG(("me (%d,%d) robot(%d,%d) heap(%d,%d) delta(%d,%d)", + My_pos.x, My_pos.y, rob->x, rob->y, hp->x, hp->y, dx, dy)); + return move_towards(dx, dy); +} /* end move_between */ + +/* between(): + * Return true if the heap is between us and the robot + */ +int +between(rob, hp) + COORD *rob; + COORD *hp; +{ + /* I = @ */ + if (hp->x > rob->x && My_pos.x < rob->x) + return 0; + /* @ = I */ + if (hp->x < rob->x && My_pos.x > rob->x) + return 0; + /* @ */ + /* = */ + /* I */ + if (hp->y < rob->y && My_pos.y > rob->y) + return 0; + /* I */ + /* = */ + /* @ */ + if (hp->y > rob->y && My_pos.y < rob->y) + return 0; + return 1; +} /* end between */ + +/* automove(): + * find and do the best move if flag + * else get the first move; + */ +char +automove() +{ +#if 0 + return find_moves()[0]; +#else + COORD *robot_close; + COORD *heap_close; + int robot_dist, robot_heap, heap_dist; + + robot_close = closest_robot(&robot_dist); + if (robot_dist > 1) + return('.'); + if (!Num_scrap) + /* no scrap heaps just run away */ + return move_away(robot_close); + + heap_close = closest_heap(&heap_dist); + robot_heap = distance(robot_close->x, robot_close->y, + heap_close->x, heap_close->y); + if (robot_heap <= heap_dist && !between(robot_close, heap_close)) { + /* + * robot is closest to us from the heap. Run away! + */ + return move_away(robot_close); + } + + return move_between(robot_close, heap_close); +#endif +} /* end get_move */ |