OpenCores
URL https://opencores.org/ocsvn/connect-6/connect-6/trunk

Subversion Repositories connect-6

[/] [connect-6/] [trunk/] [CONNECTK/] [connectk-2.0/] [src/] [ai/] [search.c] - Blame information for rev 13

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 sumanta.ch
 
2
/*
3
 
4
connectk -- UMN CSci 5512W project
5
 
6
*/
7
 
8
#include "config.h"
9
#include <string.h>
10
#include <glib.h>
11
#include "../shared.h"
12
#include "../connectk.h"
13
 
14
/* Variables required to check for cache hits */
15
static int cache_id = -1, cache_depth = -1, cache_branch = -1;
16
static SEARCH cache_search = -1;
17
static AIMoves *cache_moves = NULL;
18
static AIWEIGHT cache_best;
19
static Player *cache_player;
20
static AIFunc cache_func;
21
static BCOORD cache_size;
22
 
23
void dfs_cache_dump(void)
24
/* Called from tests.c to print out the DFS cache */
25
{
26
        g_debug("DFS cache: ");
27
        aimoves_print(cache_moves);
28
        g_print("\n");
29
}
30
 
31
static void cache_set(int index, AIMove *move)
32
{
33
        if (move->weight < cache_best || index > place_p)
34
                return;
35
        if (cache_moves->len <= index)
36
                cache_moves->len = index + 1;
37
        cache_moves->data[index] = *move;
38
        cache_best = move->weight;
39
}
40
 
41
static AIWEIGHT df_search(Board *b, AIMoves *moves, Player *player,
42
                          int depth, int cache_index,
43
                          PIECE searched, AIWEIGHT alpha, AIWEIGHT beta)
44
/* Depth is in _moves_ */
45
{
46
        int i, j;
47
 
48
        /* Halt and depth abort */
49
        if (ai_stop || depth < 1)
50
                return moves->utility;
51
 
52
        /* Alpha-beta sanity check */
53
        if (alpha >= beta) {
54
                g_warning("DFS alpha-beta failed sanity check");
55
                return moves->utility;
56
        }
57
 
58
        /* Search only the top moves beyond the minimum */
59
        aimoves_sort(moves);
60
        if (moves->len > player->branch) {
61
                for (i = player->branch; i < moves->len; i++)
62
                        if (moves->data[i].weight != moves->data[0].weight)
63
                                break;
64
                moves->len = i;
65
        }
66
 
67
        /* No moves left -- its a draw */
68
        if (moves->len < 1)
69
                return AIW_DRAW;
70
 
71
        /* Search each move available in depth first order */
72
        for (i = 0; i < moves->len; i++) {
73
                Board *b_next;
74
                AIMove *aim = moves->data + i;
75
                AIMoves *moves_next;
76
 
77
                /* Did we get a bad move? */
78
                if (!piece_empty(piece_at(b, aim->x, aim->y))) {
79
                        g_warning("DFS utility function suggested a bad move "
80
                                  "(%s)", bcoords_to_string(aim->x, aim->y));
81
                        continue;
82
                }
83
 
84
                /* Already searched here? */
85
                if (piece_at(b, aim->x, aim->y) == searched)
86
                        continue;
87
                place_piece_type(b, aim->x, aim->y, searched);
88
 
89
                b_next = board_new();
90
                board_copy(b, b_next);
91
                place_piece(b_next, aim->x, aim->y);
92
 
93
                /* Did we win? */
94
                if (check_win(b_next, aim->x, aim->y))
95
                        aim->weight = AIW_WIN;
96
 
97
                /* Otherwise, search deeper */
98
                else  {
99
                        int next_ci = cache_index + 1;
100
                        AIWEIGHT next_alpha = alpha, next_beta = beta;
101
                        AIFunc func;
102
 
103
                        b_next->moves_left--;
104
 
105
                        /* Player has changed */
106
                        if (b_next->moves_left <= 0) {
107
                                b_next->moves_left = place_p;
108
                                b_next->turn = other_player(b->turn);
109
                                next_ci += place_p;
110
                                searched++;
111
                                next_alpha = -beta;
112
                                next_beta = -alpha;
113
                        }
114
 
115
                        func = ai(player->ai)->func;
116
                        if (!func) {
117
                                g_warning("DFS player has no AI function");
118
                                return moves->utility;
119
                        }
120
                        moves_next = func(b_next);
121
                        aim->weight = df_search(b_next, moves_next, player,
122
                                                depth - 1, next_ci, searched,
123
                                                next_alpha, next_beta);
124
                        aimoves_free(moves_next);
125
                        if (b_next->turn != b->turn)
126
                                aim->weight = -aim->weight;
127
                }
128
 
129
                /* Debug search */
130
                if (opt_debug_dfsc) {
131
                        for(j = MAX_DEPTH - depth; j > 0; j--)
132
                                g_print("-");
133
                        g_print("> d=%d, %s, u=%d, a=%d, b=%d %s\n",
134
                                depth, bcoords_to_string(aim->x, aim->y),
135
                                aim->weight, alpha, beta,
136
                                piece_to_string(b->turn));
137
                }
138
 
139
                board_free(b_next);
140
                if (aim->weight > alpha) {
141
                        alpha = aim->weight;
142
                        cache_set(cache_index, aim);
143
 
144
                        /* Victory abort */
145
                        if (alpha >= AIW_WIN)
146
                                return AIW_WIN;
147
 
148
                        /* Alpha-beta pruning */
149
                        if (alpha >= beta)
150
                                return alpha;
151
                }
152
        }
153
 
154
        return alpha;
155
}
156
 
157
void search(const Board *b, AIMoves *moves, Player *player)
158
{
159
        Board *copy;
160
        AIFunc move_func = ai(player->ai)->func;
161
 
162
        /* Player is not configured to search */
163
        if (player->search == SEARCH_NONE)
164
                return;
165
 
166
        /* Moves list does not need to be searched */
167
        if (moves->len <= b->moves_left) {
168
                if (opt_debug_dfsc)
169
                        g_debug("DFS no choice abort");
170
                return;
171
        }
172
 
173
        /* Board size changed, cache is invalidated */
174
        if (board_size != cache_size)
175
                cache_moves = NULL;
176
        cache_size = board_size;
177
 
178
        /* Cache hit, last or same board */
179
        if (player->cache && cache_moves && cache_moves->len &&
180
            cache_search == player->search &&
181
            cache_depth == player->depth &&
182
            cache_player == player &&
183
            cache_func == move_func &&
184
            cache_branch == player->branch) {
185
                if (b->parent && cache_id == b->parent->ac.id) {
186
                        aimoves_remove(cache_moves, b->parent->move_x,
187
                                       b->parent->move_y);
188
                        cache_id = b->ac.id;
189
                }
190
                if (cache_id == b->ac.id && cache_moves->len) {
191
                        if (cache_moves->len) {
192
                                aimoves_copy(cache_moves, moves);
193
                                if (opt_debug_dfsc)
194
                                        g_debug("DFS cache HIT");
195
                                return;
196
                        }
197
                        aimoves_free(cache_moves);
198
                        cache_moves = NULL;
199
                }
200
        }
201
 
202
        /* Cache miss */
203
        if (opt_debug_dfsc)
204
                g_debug("DFS cache MISS");
205
        cache_id = b->ac.id;
206
        if (!cache_moves)
207
                cache_moves = aimoves_new();
208
        cache_moves->len = 0;
209
        cache_best = AIW_MIN;
210
        copy = board_new();
211
        board_copy(b, copy);
212
        if (player->search == SEARCH_DFS) {
213
                df_search(copy, moves, player, player->depth, 0,
214
                          PIECE_SEARCHED, AIW_LOSE, AIW_WIN);
215
                if (cache_moves->len)
216
                        aimoves_copy(cache_moves, moves);
217
        } else {
218
                board_free(copy);
219
                g_warning("Unsupported search type %d", player->search);
220
                return;
221
        }
222
        board_free(copy);
223
 
224
        /* Debug DFS search */
225
        if (opt_debug_dfsc)
226
                dfs_cache_dump();
227
 
228
        /* Save params so we can check if we have a hit later */
229
        cache_player = player;
230
        cache_search = player->search;
231
        cache_depth = player->depth;
232
        cache_branch = player->branch;
233
        cache_func = move_func;
234
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.