2004-01-27 23:30:28 +03:00
|
|
|
/* $NetBSD: auto.c,v 1.6 2004/01/27 20:30:30 jsm Exp $ */
|
1999-05-16 03:56:35 +04:00
|
|
|
|
|
|
|
/*-
|
|
|
|
* 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)
|
|
|
|
|
2004-01-27 23:30:28 +03:00
|
|
|
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 *);
|
1999-05-16 03:56:35 +04:00
|
|
|
|
|
|
|
/* 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
|
|
|
|
*/
|
Add use of `const' where appropriate to the games.
This merges in all such remaining changes from the Linux port of the
NetBSD games, except in hunt (where substantial changes from OpenBSD
need to be looked at).
Some such changes were previously covered in PRs bin/6041, bin/6146,
bin/6148, bin/6150, bin/6151, bin/6580, bin/6660, bin/7993, bin/7994,
bin/8039, bin/8057 and bin/8093.
1999-09-09 01:17:44 +04:00
|
|
|
static const char *
|
1999-05-16 03:56:35 +04:00
|
|
|
find_moves()
|
|
|
|
{
|
|
|
|
int x, y;
|
|
|
|
COORD test;
|
Add use of `const' where appropriate to the games.
This merges in all such remaining changes from the Linux port of the
NetBSD games, except in hunt (where substantial changes from OpenBSD
need to be looked at).
Some such changes were previously covered in PRs bin/6041, bin/6146,
bin/6148, bin/6150, bin/6151, bin/6580, bin/6660, bin/7993, bin/7994,
bin/8039, bin/8057 and bin/8093.
1999-09-09 01:17:44 +04:00
|
|
|
const char *m;
|
|
|
|
char *a;
|
|
|
|
static const char moves[] = ".hjklyubn";
|
1999-05-16 03:56:35 +04:00
|
|
|
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])
|
Add use of `const' where appropriate to the games.
This merges in all such remaining changes from the Linux port of the
NetBSD games, except in hunt (where substantial changes from OpenBSD
need to be looked at).
Some such changes were previously covered in PRs bin/6041, bin/6146,
bin/6148, bin/6150, bin/6151, bin/6580, bin/6660, bin/7993, bin/7994,
bin/8039, bin/8057 and bin/8093.
1999-09-09 01:17:44 +04:00
|
|
|
return ans;
|
1999-05-16 03:56:35 +04:00
|
|
|
else
|
Add use of `const' where appropriate to the games.
This merges in all such remaining changes from the Linux port of the
NetBSD games, except in hunt (where substantial changes from OpenBSD
need to be looked at).
Some such changes were previously covered in PRs bin/6041, bin/6146,
bin/6148, bin/6150, bin/6151, bin/6580, bin/6660, bin/7993, bin/7994,
bin/8039, bin/8057 and bin/8093.
1999-09-09 01:17:44 +04:00
|
|
|
return "t";
|
1999-05-16 03:56:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* closest_robot():
|
|
|
|
* return the robot closest to us
|
|
|
|
* and put in dist its distance
|
|
|
|
*/
|
|
|
|
static COORD *
|
|
|
|
closest_robot(dist)
|
|
|
|
int *dist;
|
|
|
|
{
|
1999-05-16 04:15:46 +04:00
|
|
|
COORD *rob, *end, *minrob = NULL;
|
1999-05-16 03:56:35 +04:00
|
|
|
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;
|
|
|
|
{
|
1999-05-16 04:15:46 +04:00
|
|
|
COORD *hp, *end, *minhp = NULL;
|
1999-05-16 03:56:35 +04:00
|
|
|
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];
|
2002-01-31 20:35:52 +03:00
|
|
|
if (best_move != 't') {
|
1999-05-16 03:56:35 +04:00
|
|
|
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;
|
|
|
|
{
|
1999-05-16 04:03:35 +04:00
|
|
|
int dx, dy;
|
1999-05-16 03:56:35 +04:00
|
|
|
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
|
1999-05-16 04:03:35 +04:00
|
|
|
} /* end automove */
|