| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: makemove.c,v 1.30 2022/05/28 07:58:35 rillig Exp $ */ | | 1 | /* $NetBSD: makemove.c,v 1.31 2022/05/28 08:09:22 rillig Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1994 | | 4 | * Copyright (c) 1994 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to Berkeley by | | 7 | * This code is derived from software contributed to Berkeley by |
8 | * Ralph Campbell. | | 8 | * Ralph Campbell. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -24,53 +24,80 @@ | | | @@ -24,53 +24,80 @@ |
24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 26 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 27 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
28 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 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 | | 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 | | 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 | | 31 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
32 | * SUCH DAMAGE. | | 32 | * SUCH DAMAGE. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | #include <sys/cdefs.h> | | 35 | #include <sys/cdefs.h> |
36 | /* @(#)makemove.c 8.2 (Berkeley) 5/3/95 */ | | 36 | /* @(#)makemove.c 8.2 (Berkeley) 5/3/95 */ |
37 | __RCSID("$NetBSD: makemove.c,v 1.30 2022/05/28 07:58:35 rillig Exp $"); | | 37 | __RCSID("$NetBSD: makemove.c,v 1.31 2022/05/28 08:09:22 rillig Exp $"); |
38 | | | 38 | |
39 | #include "gomoku.h" | | 39 | #include "gomoku.h" |
40 | | | 40 | |
41 | /* direction deltas */ | | 41 | /* direction deltas */ |
42 | const int dd[4] = { | | 42 | const int dd[4] = { |
43 | 1, /* right */ | | 43 | 1, /* right */ |
44 | -(BSZ + 1) + 1, /* down + right */ | | 44 | -(BSZ + 1) + 1, /* down + right */ |
45 | -(BSZ + 1), /* down */ | | 45 | -(BSZ + 1), /* down */ |
46 | -(BSZ + 1) - 1 /* down + left */ | | 46 | -(BSZ + 1) - 1 /* down + left */ |
47 | }; | | 47 | }; |
48 | | | 48 | |
49 | static const int weight[5] = { 0, 1, 7, 22, 100 }; | | 49 | static const int weight[5] = { 0, 1, 7, 22, 100 }; |
50 | | | 50 | |
51 | static void update_overlap(struct spotstr *); | | 51 | static void update_overlap(struct spotstr *); |
52 | | | 52 | |
53 | static bool | | 53 | static bool |
54 | is_tie(void) | | 54 | is_tie(void) |
55 | { | | 55 | { |
56 | | | 56 | |
57 | for (int y = 1; y <= BSZ; y++) | | 57 | for (int y = 1; y <= BSZ; y++) |
58 | for (int x = 1; x <= BSZ; x++) | | 58 | for (int x = 1; x <= BSZ; x++) |
59 | if (board[PT(x, y)].s_wval != 0) | | 59 | if (board[PT(x, y)].s_wval != 0) |
60 | return false; | | 60 | return false; |
61 | return true; | | 61 | return true; |
62 | } | | 62 | } |
63 | | | 63 | |
| | | 64 | static void |
| | | 65 | sortframes_remove(struct combostr *cbp) |
| | | 66 | { |
| | | 67 | |
| | | 68 | if (cbp->c_next == NULL) |
| | | 69 | return; |
| | | 70 | |
| | | 71 | if (sortframes[BLACK] == cbp) |
| | | 72 | sortframes[BLACK] = cbp->c_next; |
| | | 73 | if (sortframes[WHITE] == cbp) |
| | | 74 | sortframes[WHITE] = cbp->c_next; |
| | | 75 | cbp->c_next->c_prev = cbp->c_prev; |
| | | 76 | cbp->c_prev->c_next = cbp->c_next; |
| | | 77 | } |
| | | 78 | |
| | | 79 | static int |
| | | 80 | old_weight_value(const struct spotstr *sp, int r) |
| | | 81 | { |
| | | 82 | union comboval cb; |
| | | 83 | int val = 0; |
| | | 84 | if ((cb = sp->s_fval[BLACK][r]).s <= 0x500) |
| | | 85 | val += weight[5 - cb.cv_force - cb.cv_win]; |
| | | 86 | if ((cb = sp->s_fval[WHITE][r]).s <= 0x500) |
| | | 87 | val += weight[5 - cb.cv_force - cb.cv_win]; |
| | | 88 | return val; |
| | | 89 | } |
| | | 90 | |
64 | /* | | 91 | /* |
65 | * Return values: | | 92 | * Return values: |
66 | * MOVEOK everything is OK. | | 93 | * MOVEOK everything is OK. |
67 | * RESIGN Player resigned. | | 94 | * RESIGN Player resigned. |
68 | * ILLEGAL Illegal move. | | 95 | * ILLEGAL Illegal move. |
69 | * WIN The winning move was just played. | | 96 | * WIN The winning move was just played. |
70 | * TIE The game is a tie. | | 97 | * TIE The game is a tie. |
71 | */ | | 98 | */ |
72 | int | | 99 | int |
73 | makemove(int us, int mv) | | 100 | makemove(int us, int mv) |
74 | { | | 101 | { |
75 | | | 102 | |
76 | /* check for end of game */ | | 103 | /* check for end of game */ |
| @@ -81,65 +108,50 @@ makemove(int us, int mv) | | | @@ -81,65 +108,50 @@ makemove(int us, int mv) |
81 | struct spotstr *sp = &board[mv]; | | 108 | struct spotstr *sp = &board[mv]; |
82 | if (sp->s_occ != EMPTY) | | 109 | if (sp->s_occ != EMPTY) |
83 | return ILLEGAL; | | 110 | return ILLEGAL; |
84 | | | 111 | |
85 | /* make move */ | | 112 | /* make move */ |
86 | sp->s_occ = us; | | 113 | sp->s_occ = us; |
87 | movelog[nmoves++] = mv; | | 114 | movelog[nmoves++] = mv; |
88 | | | 115 | |
89 | /* compute new frame values */ | | 116 | /* compute new frame values */ |
90 | sp->s_wval = 0; | | 117 | sp->s_wval = 0; |
91 | for (int r = 4; --r >= 0; ) { /* for each direction */ | | 118 | for (int r = 4; --r >= 0; ) { /* for each direction */ |
92 | int d = dd[r]; | | 119 | int d = dd[r]; |
93 | struct spotstr *fsp = &board[mv]; | | 120 | struct spotstr *fsp = &board[mv]; |
94 | int bmask = BFLAG << r; | | | |
95 | | | 121 | |
96 | for (int f = 5; --f >= 0; fsp -= d) { /* for each frame */ | | 122 | for (int f = 5; --f >= 0; fsp -= d) { /* for each frame */ |
97 | if (fsp->s_occ == BORDER) | | 123 | if (fsp->s_occ == BORDER) |
98 | goto nextr; | | 124 | goto nextr; |
99 | if ((fsp->s_flags & bmask) != 0) | | 125 | if ((fsp->s_flags & BFLAG << r) != 0) |
100 | continue; | | 126 | continue; |
101 | | | 127 | |
102 | /* remove this frame from the sorted list of frames */ | | | |
103 | struct combostr *cbp = fsp->s_frame[r]; | | 128 | struct combostr *cbp = fsp->s_frame[r]; |
104 | if (cbp->c_next != NULL) { | | 129 | sortframes_remove(cbp); |
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; | | | |
111 | } | | | |
112 | | | 130 | |
113 | /* compute old weight value for this frame */ | | 131 | int val = old_weight_value(fsp, r); |
114 | union comboval cb; | | | |
115 | int val = 0; | | | |
116 | if ((cb = fsp->s_fval[BLACK][r]).s <= 0x500) | | | |
117 | val += weight[5 - cb.cv_force - cb.cv_win]; | | | |
118 | if ((cb = fsp->s_fval[WHITE][r]).s <= 0x500) | | | |
119 | val += weight[5 - cb.cv_force - cb.cv_win]; | | | |
120 | | | 132 | |
121 | /* compute new combo value for this frame */ | | 133 | /* compute new combo value for this frame */ |
122 | bool space = fsp->s_occ == EMPTY; | | 134 | bool space = fsp->s_occ == EMPTY; |
123 | int n = 0; | | 135 | int n = 0; |
124 | sp = fsp; | | 136 | sp = fsp; |
125 | for (int i = 5; --i >= 0; sp += d) { /* for each spot */ | | 137 | for (int i = 5; --i >= 0; sp += d) { /* for each spot */ |
126 | if (sp->s_occ == us) | | 138 | if (sp->s_occ == us) |
127 | n++; | | 139 | n++; |
128 | else if (sp->s_occ == EMPTY) | | 140 | else if (sp->s_occ == EMPTY) |
129 | sp->s_wval -= val; | | 141 | sp->s_wval -= val; |
130 | else { | | 142 | else { |
131 | /* this frame is now blocked, adjust values */ | | 143 | /* this frame is now blocked, adjust values */ |
132 | fsp->s_flags |= bmask; | | 144 | fsp->s_flags |= BFLAG << r; |
133 | fsp->s_fval[BLACK][r].s = 0x600; | | 145 | fsp->s_fval[BLACK][r].s = 0x600; |
134 | fsp->s_fval[WHITE][r].s = 0x600; | | 146 | fsp->s_fval[WHITE][r].s = 0x600; |
135 | while (--i >= 0) { | | 147 | while (--i >= 0) { |
136 | sp += d; | | 148 | sp += d; |
137 | if (sp->s_occ == EMPTY) | | 149 | if (sp->s_occ == EMPTY) |
138 | sp->s_wval -= val; | | 150 | sp->s_wval -= val; |
139 | } | | 151 | } |
140 | goto nextf; | | 152 | goto nextf; |
141 | } | | 153 | } |
142 | } | | 154 | } |
143 | | | 155 | |
144 | /* check for game over */ | | 156 | /* check for game over */ |
145 | if (n == 5) | | 157 | if (n == 5) |