makemove.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /* $NetBSD: makemove.c,v 1.7 2003/08/07 09:37:17 agc Exp $ */
  2. /*
  3. * Copyright (c) 1994
  4. * The Regents of the University of California. All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Ralph Campbell.
  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. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #include <sys/cdefs.h>
  34. #ifndef lint
  35. #if 0
  36. static char sccsid[] = "@(#)makemove.c 8.2 (Berkeley) 5/3/95";
  37. #else
  38. __RCSID("$NetBSD: makemove.c,v 1.7 2003/08/07 09:37:17 agc Exp $");
  39. #endif
  40. #endif /* not lint */
  41. #include "gomoku.h"
  42. /* direction deltas */
  43. const int dd[4] = {
  44. MRIGHT, MRIGHT+MDOWN, MDOWN, MDOWN+MLEFT
  45. };
  46. const int weight[5] = { 0, 1, 7, 22, 100 };
  47. /*
  48. * Return values:
  49. * MOVEOK everything is OK.
  50. * RESIGN Player resigned.
  51. * ILLEGAL Illegal move.
  52. * WIN The winning move was just played.
  53. * TIE The game is a tie.
  54. */
  55. int
  56. makemove(us, mv)
  57. int us, mv;
  58. {
  59. struct spotstr *sp, *fsp;
  60. union comboval *cp;
  61. struct spotstr *osp;
  62. struct combostr *cbp, *cbp1;
  63. union comboval *cp1;
  64. int i, f, r, d, n;
  65. int space, val, bmask;
  66. /* check for end of game */
  67. if (mv == RESIGN)
  68. return(RESIGN);
  69. /* check for illegal move */
  70. sp = &board[mv];
  71. if (sp->s_occ != EMPTY)
  72. return(ILLEGAL);
  73. /* make move */
  74. sp->s_occ = us;
  75. movelog[movenum - 1] = mv;
  76. if (++movenum == BSZ * BSZ)
  77. return(TIE);
  78. /* compute new frame values */
  79. sp->s_wval = 0;
  80. osp = sp;
  81. for (r = 4; --r >= 0; ) { /* for each direction */
  82. d = dd[r];
  83. fsp = osp;
  84. bmask = BFLAG << r;
  85. for (f = 5; --f >= 0; fsp -= d) { /* for each frame */
  86. if (fsp->s_occ == BORDER)
  87. goto nextr;
  88. if (fsp->s_flg & bmask)
  89. continue;
  90. /* remove this frame from the sorted list of frames */
  91. cbp = fsp->s_frame[r];
  92. if (cbp->c_next) {
  93. if (sortframes[BLACK] == cbp)
  94. sortframes[BLACK] = cbp->c_next;
  95. if (sortframes[WHITE] == cbp)
  96. sortframes[WHITE] = cbp->c_next;
  97. cbp->c_next->c_prev = cbp->c_prev;
  98. cbp->c_prev->c_next = cbp->c_next;
  99. }
  100. /* compute old weight value for this frame */
  101. cp = &fsp->s_fval[BLACK][r];
  102. if (cp->s <= 0x500)
  103. val = weight[5 - cp->c.a - cp->c.b];
  104. else
  105. val = 0;
  106. cp = &fsp->s_fval[WHITE][r];
  107. if (cp->s <= 0x500)
  108. val += weight[5 - cp->c.a - cp->c.b];
  109. /* compute new combo value for this frame */
  110. sp = fsp;
  111. space = sp->s_occ == EMPTY;
  112. n = 0;
  113. for (i = 5; --i >= 0; sp += d) { /* for each spot */
  114. if (sp->s_occ == us)
  115. n++;
  116. else if (sp->s_occ == EMPTY)
  117. sp->s_wval -= val;
  118. else {
  119. /* this frame is now blocked, adjust values */
  120. fsp->s_flg |= bmask;
  121. fsp->s_fval[BLACK][r].s = MAXCOMBO;
  122. fsp->s_fval[WHITE][r].s = MAXCOMBO;
  123. while (--i >= 0) {
  124. sp += d;
  125. if (sp->s_occ == EMPTY)
  126. sp->s_wval -= val;
  127. }
  128. goto nextf;
  129. }
  130. }
  131. /* check for game over */
  132. if (n == 5)
  133. return(WIN);
  134. /* compute new value & combo number for this frame & color */
  135. fsp->s_fval[!us][r].s = MAXCOMBO;
  136. cp = &fsp->s_fval[us][r];
  137. /* both ends open? */
  138. if (space && sp->s_occ == EMPTY) {
  139. cp->c.a = 4 - n;
  140. cp->c.b = 1;
  141. } else {
  142. cp->c.a = 5 - n;
  143. cp->c.b = 0;
  144. }
  145. val = weight[n];
  146. sp = fsp;
  147. for (i = 5; --i >= 0; sp += d) /* for each spot */
  148. if (sp->s_occ == EMPTY)
  149. sp->s_wval += val;
  150. /* add this frame to the sorted list of frames by combo value */
  151. cbp1 = sortframes[us];
  152. if (!cbp1)
  153. sortframes[us] = cbp->c_next = cbp->c_prev = cbp;
  154. else {
  155. cp1 = &board[cbp1->c_vertex].s_fval[us][cbp1->c_dir];
  156. if (cp->s <= cp1->s) {
  157. /* insert at the head of the list */
  158. sortframes[us] = cbp;
  159. } else {
  160. do {
  161. cbp1 = cbp1->c_next;
  162. cp1 = &board[cbp1->c_vertex].s_fval[us][cbp1->c_dir];
  163. if (cp->s <= cp1->s)
  164. break;
  165. } while (cbp1 != sortframes[us]);
  166. }
  167. cbp->c_next = cbp1;
  168. cbp->c_prev = cbp1->c_prev;
  169. cbp1->c_prev->c_next = cbp;
  170. cbp1->c_prev = cbp;
  171. }
  172. nextf:
  173. ;
  174. }
  175. /* both ends open? */
  176. if (fsp->s_occ == EMPTY) {
  177. cp = &fsp->s_fval[BLACK][r];
  178. if (cp->c.b) {
  179. cp->c.a += 1;
  180. cp->c.b = 0;
  181. }
  182. cp = &fsp->s_fval[WHITE][r];
  183. if (cp->c.b) {
  184. cp->c.a += 1;
  185. cp->c.b = 0;
  186. }
  187. }
  188. nextr:
  189. ;
  190. }
  191. update_overlap(osp);
  192. return(MOVEOK);
  193. }
  194. /*
  195. * fix up the overlap array due to updating spot osp.
  196. */
  197. void
  198. update_overlap(osp)
  199. struct spotstr *osp;
  200. {
  201. struct spotstr *sp, *sp1, *sp2;
  202. int i, f, r, r1, d, d1, n;
  203. int a, b, bmask, bmask1;
  204. struct spotstr *esp;
  205. char *str;
  206. esp = NULL;
  207. for (r = 4; --r >= 0; ) { /* for each direction */
  208. d = dd[r];
  209. sp1 = osp;
  210. bmask = BFLAG << r;
  211. for (f = 0; f < 6; f++, sp1 -= d) { /* for each frame */
  212. if (sp1->s_occ == BORDER)
  213. break;
  214. if (sp1->s_flg & bmask)
  215. continue;
  216. /*
  217. * Update all other frames that intersect the current one
  218. * to indicate whether they still overlap or not.
  219. * Since F1 overlap F2 == F2 overlap F1, we only need to
  220. * do the rows 0 <= r1 <= r. The r1 == r case is special
  221. * since the two frames can overlap at more than one point.
  222. */
  223. str = &overlap[(a = sp1->s_frame[r] - frames) * FAREA];
  224. sp2 = sp1 - d;
  225. for (i = f + 1; i < 6; i++, sp2 -= d) {
  226. if (sp2->s_occ == BORDER)
  227. break;
  228. if (sp2->s_flg & bmask)
  229. continue;
  230. /*
  231. * count the number of empty spots to see if there is
  232. * still an overlap.
  233. */
  234. n = 0;
  235. sp = sp1;
  236. for (b = i - f; b < 5; b++, sp += d) {
  237. if (sp->s_occ == EMPTY) {
  238. esp = sp; /* save the intersection point */
  239. n++;
  240. }
  241. }
  242. b = sp2->s_frame[r] - frames;
  243. if (n == 0) {
  244. if (sp->s_occ == EMPTY) {
  245. str[b] &= 0xA;
  246. overlap[b * FAREA + a] &= 0xC;
  247. intersect[a * FAREA + b] = n = sp - board;
  248. intersect[b * FAREA + a] = n;
  249. } else {
  250. str[b] = 0;
  251. overlap[b * FAREA + a] = 0;
  252. }
  253. } else if (n == 1) {
  254. if (sp->s_occ == EMPTY) {
  255. str[b] &= 0xAF;
  256. overlap[b * FAREA + a] &= 0xCF;
  257. } else {
  258. str[b] &= 0xF;
  259. overlap[b * FAREA + a] &= 0xF;
  260. }
  261. intersect[a * FAREA + b] = n = esp - board;
  262. intersect[b * FAREA + a] = n;
  263. }
  264. /* else no change, still multiple overlap */
  265. }
  266. /* the other directions can only intersect at spot osp */
  267. for (r1 = r; --r1 >= 0; ) {
  268. d1 = dd[r1];
  269. bmask1 = BFLAG << r1;
  270. sp = osp;
  271. for (i = 6; --i >= 0; sp -= d1) { /* for each spot */
  272. if (sp->s_occ == BORDER)
  273. break;
  274. if (sp->s_flg & bmask1)
  275. continue;
  276. b = sp->s_frame[r1] - frames;
  277. str[b] = 0;
  278. overlap[b * FAREA + a] = 0;
  279. }
  280. }
  281. }
  282. }
  283. }