auto.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /* $NetBSD: auto.c,v 1.7 2004/08/27 09:06:25 christos Exp $ */
  2. /*-
  3. * Copyright (c) 1999 The NetBSD Foundation, Inc.
  4. * All rights reserved.
  5. *
  6. * This code is derived from software contributed to The NetBSD Foundation
  7. * by Christos Zoulas.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * 3. All advertising materials mentioning features or use of this software
  18. * must display the following acknowledgement:
  19. * This product includes software developed by the NetBSD
  20. * Foundation, Inc. and its contributors.
  21. * 4. Neither the name of The NetBSD Foundation nor the names of its
  22. * contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  26. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  27. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  28. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  29. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  30. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  35. * POSSIBILITY OF SUCH DAMAGE.
  36. */
  37. /*
  38. * Automatic move.
  39. * intelligent ?
  40. * Algo :
  41. * IF scrapheaps don't exist THEN
  42. * IF not in danger THEN
  43. * stay at current position
  44. * ELSE
  45. * move away from the closest robot
  46. * FI
  47. * ELSE
  48. * find closest heap
  49. * find closest robot
  50. * IF scrapheap is adjacent THEN
  51. * move behind the scrapheap
  52. * ELSE
  53. * take the move that takes you away from the
  54. * robots and closest to the heap
  55. * FI
  56. * FI
  57. */
  58. #include "robots.h"
  59. #define ABS(a) (((a)>0)?(a):-(a))
  60. #define MIN(a,b) (((a)>(b))?(b):(a))
  61. #define MAX(a,b) (((a)<(b))?(b):(a))
  62. #define CONSDEBUG(a)
  63. static int distance(int, int, int, int);
  64. static int xinc(int);
  65. static int yinc(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 *);
  73. /* distance():
  74. * return "move" number distance of the two coordinates
  75. */
  76. static int
  77. distance(x1, y1, x2, y2)
  78. int x1, y1, x2, y2;
  79. {
  80. return MAX(ABS(ABS(x1) - ABS(x2)), ABS(ABS(y1) - ABS(y2)));
  81. } /* end distance */
  82. /* xinc():
  83. * Return x coordinate moves
  84. */
  85. static int
  86. xinc(dir)
  87. int dir;
  88. {
  89. switch(dir) {
  90. case 'b':
  91. case 'h':
  92. case 'y':
  93. return -1;
  94. case 'l':
  95. case 'n':
  96. case 'u':
  97. return 1;
  98. case 'j':
  99. case 'k':
  100. default:
  101. return 0;
  102. }
  103. }
  104. /* yinc():
  105. * Return y coordinate moves
  106. */
  107. static int
  108. yinc(dir)
  109. int dir;
  110. {
  111. switch(dir) {
  112. case 'k':
  113. case 'u':
  114. case 'y':
  115. return -1;
  116. case 'b':
  117. case 'j':
  118. case 'n':
  119. return 1;
  120. case 'h':
  121. case 'l':
  122. default:
  123. return 0;
  124. }
  125. }
  126. /* find_moves():
  127. * Find possible moves
  128. */
  129. static const char *
  130. find_moves()
  131. {
  132. int x, y;
  133. COORD test;
  134. const char *m;
  135. char *a;
  136. static const char moves[] = ".hjklyubn";
  137. static char ans[sizeof moves];
  138. a = ans;
  139. for(m = moves; *m; m++) {
  140. test.x = My_pos.x + xinc(*m);
  141. test.y = My_pos.y + yinc(*m);
  142. move(test.y, test.x);
  143. switch(winch(stdscr)) {
  144. case ' ':
  145. case PLAYER:
  146. for(x = test.x - 1; x <= test.x + 1; x++) {
  147. for(y = test.y - 1; y <= test.y + 1; y++) {
  148. move(y, x);
  149. if(winch(stdscr) == ROBOT)
  150. goto bad;
  151. }
  152. }
  153. *a++ = *m;
  154. }
  155. bad:;
  156. }
  157. *a = 0;
  158. if(ans[0])
  159. return ans;
  160. else
  161. return "t";
  162. }
  163. /* closest_robot():
  164. * return the robot closest to us
  165. * and put in dist its distance
  166. */
  167. static COORD *
  168. closest_robot(dist)
  169. int *dist;
  170. {
  171. COORD *rob, *end, *minrob = NULL;
  172. int tdist, mindist;
  173. mindist = 1000000;
  174. end = &Robots[MAXROBOTS];
  175. for (rob = Robots; rob < end; rob++) {
  176. tdist = distance(My_pos.x, My_pos.y, rob->x, rob->y);
  177. if (tdist < mindist) {
  178. minrob = rob;
  179. mindist = tdist;
  180. }
  181. }
  182. *dist = mindist;
  183. return minrob;
  184. } /* end closest_robot */
  185. /* closest_heap():
  186. * return the heap closest to us
  187. * and put in dist its distance
  188. */
  189. static COORD *
  190. closest_heap(dist)
  191. int *dist;
  192. {
  193. COORD *hp, *end, *minhp = NULL;
  194. int mindist, tdist;
  195. mindist = 1000000;
  196. end = &Scrap[MAXROBOTS];
  197. for (hp = Scrap; hp < end; hp++) {
  198. if (hp->x == 0 && hp->y == 0)
  199. break;
  200. tdist = distance(My_pos.x, My_pos.y, hp->x, hp->y);
  201. if (tdist < mindist) {
  202. minhp = hp;
  203. mindist = tdist;
  204. }
  205. }
  206. *dist = mindist;
  207. return minhp;
  208. } /* end closest_heap */
  209. /* move_towards():
  210. * move as close to the given direction as possible
  211. */
  212. static char
  213. move_towards(dx, dy)
  214. int dx, dy;
  215. {
  216. char ok_moves[10], best_move;
  217. char *ptr;
  218. int move_judge, cur_judge, mvx, mvy;
  219. (void)strcpy(ok_moves, find_moves());
  220. best_move = ok_moves[0];
  221. if (best_move != 't') {
  222. mvx = xinc(best_move);
  223. mvy = yinc(best_move);
  224. move_judge = ABS(mvx - dx) + ABS(mvy - dy);
  225. for (ptr = &ok_moves[1]; *ptr != '\0'; ptr++) {
  226. mvx = xinc(*ptr);
  227. mvy = yinc(*ptr);
  228. cur_judge = ABS(mvx - dx) + ABS(mvy - dy);
  229. if (cur_judge < move_judge) {
  230. move_judge = cur_judge;
  231. best_move = *ptr;
  232. }
  233. }
  234. }
  235. return best_move;
  236. } /* end move_towards */
  237. /* move_away():
  238. * move away form the robot given
  239. */
  240. static char
  241. move_away(rob)
  242. COORD *rob;
  243. {
  244. int dx, dy;
  245. dx = sign(My_pos.x - rob->x);
  246. dy = sign(My_pos.y - rob->y);
  247. return move_towards(dx, dy);
  248. } /* end move_away */
  249. /* move_between():
  250. * move the closest heap between us and the closest robot
  251. */
  252. static char
  253. move_between(rob, hp)
  254. COORD *rob;
  255. COORD *hp;
  256. {
  257. int dx, dy;
  258. float slope, cons;
  259. /* equation of the line between us and the closest robot */
  260. if (My_pos.x == rob->x) {
  261. /*
  262. * me and the robot are aligned in x
  263. * change my x so I get closer to the heap
  264. * and my y far from the robot
  265. */
  266. dx = - sign(My_pos.x - hp->x);
  267. dy = sign(My_pos.y - rob->y);
  268. CONSDEBUG(("aligned in x"));
  269. }
  270. else if (My_pos.y == rob->y) {
  271. /*
  272. * me and the robot are aligned in y
  273. * change my y so I get closer to the heap
  274. * and my x far from the robot
  275. */
  276. dx = sign(My_pos.x - rob->x);
  277. dy = -sign(My_pos.y - hp->y);
  278. CONSDEBUG(("aligned in y"));
  279. }
  280. else {
  281. CONSDEBUG(("no aligned"));
  282. slope = (My_pos.y - rob->y) / (My_pos.x - rob->x);
  283. cons = slope * rob->y;
  284. if (ABS(My_pos.x - rob->x) > ABS(My_pos.y - rob->y)) {
  285. /*
  286. * we are closest to the robot in x
  287. * move away from the robot in x and
  288. * close to the scrap in y
  289. */
  290. dx = sign(My_pos.x - rob->x);
  291. dy = sign(((slope * ((float) hp->x)) + cons) -
  292. ((float) hp->y));
  293. }
  294. else {
  295. dx = sign(((slope * ((float) hp->x)) + cons) -
  296. ((float) hp->y));
  297. dy = sign(My_pos.y - rob->y);
  298. }
  299. }
  300. CONSDEBUG(("me (%d,%d) robot(%d,%d) heap(%d,%d) delta(%d,%d)",
  301. My_pos.x, My_pos.y, rob->x, rob->y, hp->x, hp->y, dx, dy));
  302. return move_towards(dx, dy);
  303. } /* end move_between */
  304. /* between():
  305. * Return true if the heap is between us and the robot
  306. */
  307. int
  308. between(rob, hp)
  309. COORD *rob;
  310. COORD *hp;
  311. {
  312. /* I = @ */
  313. if (hp->x > rob->x && My_pos.x < rob->x)
  314. return 0;
  315. /* @ = I */
  316. if (hp->x < rob->x && My_pos.x > rob->x)
  317. return 0;
  318. /* @ */
  319. /* = */
  320. /* I */
  321. if (hp->y < rob->y && My_pos.y > rob->y)
  322. return 0;
  323. /* I */
  324. /* = */
  325. /* @ */
  326. if (hp->y > rob->y && My_pos.y < rob->y)
  327. return 0;
  328. return 1;
  329. } /* end between */
  330. /* automove():
  331. * find and do the best move if flag
  332. * else get the first move;
  333. */
  334. char
  335. automove()
  336. {
  337. #if 0
  338. return find_moves()[0];
  339. #else
  340. COORD *robot_close;
  341. COORD *heap_close;
  342. int robot_dist, robot_heap, heap_dist;
  343. robot_close = closest_robot(&robot_dist);
  344. if (robot_dist > 1)
  345. return('.');
  346. if (!Num_scrap)
  347. /* no scrap heaps just run away */
  348. return move_away(robot_close);
  349. heap_close = closest_heap(&heap_dist);
  350. robot_heap = distance(robot_close->x, robot_close->y,
  351. heap_close->x, heap_close->y);
  352. if (robot_heap <= heap_dist && !between(robot_close, heap_close)) {
  353. /*
  354. * robot is closest to us from the heap. Run away!
  355. */
  356. return move_away(robot_close);
  357. }
  358. return move_between(robot_close, heap_close);
  359. #endif
  360. } /* end automove */