1 /* $NetBSD: makemove.c,v 1.10 2009/06/04 05:43:29 dholland Exp $ */
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
38 static char sccsid
[] = "@(#)makemove.c 8.2 (Berkeley) 5/3/95";
40 __RCSID("$NetBSD: makemove.c,v 1.10 2009/06/04 05:43:29 dholland Exp $");
46 /* direction deltas */
48 MRIGHT
, MRIGHT
+MDOWN
, MDOWN
, MDOWN
+MLEFT
51 static const int weight
[5] = { 0, 1, 7, 22, 100 };
53 static void update_overlap(struct spotstr
*);
57 * MOVEOK everything is OK.
58 * RESIGN Player resigned.
59 * ILLEGAL Illegal move.
60 * WIN The winning move was just played.
61 * TIE The game is a tie.
64 makemove(int us
, int mv
)
66 struct spotstr
*sp
, *fsp
;
69 struct combostr
*cbp
, *cbp1
;
72 int space
, val
, bmask
;
74 /* check for end of game */
78 /* check for illegal move */
80 if (sp
->s_occ
!= EMPTY
)
85 movelog
[movenum
- 1] = mv
;
86 if (++movenum
== BSZ
* BSZ
)
89 /* compute new frame values */
92 for (r
= 4; --r
>= 0; ) { /* for each direction */
96 for (f
= 5; --f
>= 0; fsp
-= d
) { /* for each frame */
97 if (fsp
->s_occ
== BORDER
)
99 if (fsp
->s_flags
& bmask
)
102 /* remove this frame from the sorted list of frames */
103 cbp
= fsp
->s_frame
[r
];
105 if (sortframes
[BLACK
] == cbp
)
106 sortframes
[BLACK
] = cbp
->c_next
;
107 if (sortframes
[WHITE
] == cbp
)
108 sortframes
[WHITE
] = cbp
->c_next
;
109 cbp
->c_next
->c_prev
= cbp
->c_prev
;
110 cbp
->c_prev
->c_next
= cbp
->c_next
;
113 /* compute old weight value for this frame */
114 cp
= &fsp
->s_fval
[BLACK
][r
];
116 val
= weight
[5 - cp
->c
.a
- cp
->c
.b
];
119 cp
= &fsp
->s_fval
[WHITE
][r
];
121 val
+= weight
[5 - cp
->c
.a
- cp
->c
.b
];
123 /* compute new combo value for this frame */
125 space
= sp
->s_occ
== EMPTY
;
127 for (i
= 5; --i
>= 0; sp
+= d
) { /* for each spot */
130 else if (sp
->s_occ
== EMPTY
)
133 /* this frame is now blocked, adjust values */
134 fsp
->s_flags
|= bmask
;
135 fsp
->s_fval
[BLACK
][r
].s
= MAXCOMBO
;
136 fsp
->s_fval
[WHITE
][r
].s
= MAXCOMBO
;
139 if (sp
->s_occ
== EMPTY
)
146 /* check for game over */
150 /* compute new value & combo number for this frame & color */
151 fsp
->s_fval
[!us
][r
].s
= MAXCOMBO
;
152 cp
= &fsp
->s_fval
[us
][r
];
153 /* both ends open? */
154 if (space
&& sp
->s_occ
== EMPTY
) {
163 for (i
= 5; --i
>= 0; sp
+= d
) /* for each spot */
164 if (sp
->s_occ
== EMPTY
)
167 /* add this frame to the sorted list of frames by combo value */
168 cbp1
= sortframes
[us
];
170 sortframes
[us
] = cbp
->c_next
= cbp
->c_prev
= cbp
;
172 cp1
= &board
[cbp1
->c_vertex
].s_fval
[us
][cbp1
->c_dir
];
173 if (cp
->s
<= cp1
->s
) {
174 /* insert at the head of the list */
175 sortframes
[us
] = cbp
;
179 cp1
= &board
[cbp1
->c_vertex
].s_fval
[us
][cbp1
->c_dir
];
182 } while (cbp1
!= sortframes
[us
]);
185 cbp
->c_prev
= cbp1
->c_prev
;
186 cbp1
->c_prev
->c_next
= cbp
;
194 /* both ends open? */
195 if (fsp
->s_occ
== EMPTY
) {
196 cp
= &fsp
->s_fval
[BLACK
][r
];
201 cp
= &fsp
->s_fval
[WHITE
][r
];
218 * fix up the overlap array due to updating spot osp.
221 update_overlap(struct spotstr
*osp
)
223 struct spotstr
*sp
, *sp1
, *sp2
;
224 int i
, f
, r
, r1
, d
, d1
, n
;
225 int a
, b
, bmask
, bmask1
;
230 for (r
= 4; --r
>= 0; ) { /* for each direction */
234 for (f
= 0; f
< 6; f
++, sp1
-= d
) { /* for each frame */
235 if (sp1
->s_occ
== BORDER
)
237 if (sp1
->s_flags
& bmask
)
240 * Update all other frames that intersect the current one
241 * to indicate whether they still overlap or not.
242 * Since F1 overlap F2 == F2 overlap F1, we only need to
243 * do the rows 0 <= r1 <= r. The r1 == r case is special
244 * since the two frames can overlap at more than one point.
246 str
= &overlap
[(a
= sp1
->s_frame
[r
] - frames
) * FAREA
];
248 for (i
= f
+ 1; i
< 6; i
++, sp2
-= d
) {
249 if (sp2
->s_occ
== BORDER
)
251 if (sp2
->s_flags
& bmask
)
254 * count the number of empty spots to see if there is
259 for (b
= i
- f
; b
< 5; b
++, sp
+= d
) {
260 if (sp
->s_occ
== EMPTY
) {
261 esp
= sp
; /* save the intersection point */
265 b
= sp2
->s_frame
[r
] - frames
;
267 if (sp
->s_occ
== EMPTY
) {
269 overlap
[b
* FAREA
+ a
] &= 0xC;
270 intersect
[a
* FAREA
+ b
] = n
= sp
- board
;
271 intersect
[b
* FAREA
+ a
] = n
;
274 overlap
[b
* FAREA
+ a
] = 0;
277 if (sp
->s_occ
== EMPTY
) {
279 overlap
[b
* FAREA
+ a
] &= 0xCF;
282 overlap
[b
* FAREA
+ a
] &= 0xF;
284 intersect
[a
* FAREA
+ b
] = n
= esp
- board
;
285 intersect
[b
* FAREA
+ a
] = n
;
287 /* else no change, still multiple overlap */
290 /* the other directions can only intersect at spot osp */
291 for (r1
= r
; --r1
>= 0; ) {
293 bmask1
= BFLAG
<< r1
;
295 for (i
= 6; --i
>= 0; sp
-= d1
) { /* for each spot */
296 if (sp
->s_occ
== BORDER
)
298 if (sp
->s_flags
& bmask1
)
300 b
= sp
->s_frame
[r1
] - frames
;
302 overlap
[b
* FAREA
+ a
] = 0;