123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- /* $NetBSD: auto.c,v 1.7 2004/08/27 09:06:25 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 adjacent THEN
- * move behind the scrapheap
- * 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)
- static int distance(int, int, int, int);
- static int xinc(int);
- static int yinc(int);
- static const char *find_moves(void);
- static COORD *closest_robot(int *);
- static COORD *closest_heap(int *);
- static char move_towards(int, int);
- static char move_away(COORD *);
- static char move_between(COORD *, COORD *);
- static int between(COORD *, COORD *);
- /* 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 const char *
- find_moves()
- {
- int x, y;
- COORD test;
- const char *m;
- char *a;
- static const 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])
- return ans;
- else
- return "t";
- }
- /* 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 = NULL;
- 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 = NULL;
- 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 != 't') {
- 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;
- {
- int dx, dy;
- 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 automove */
|