| 3.5 評価関数の実装 |
本節では局面を評価する関数Evaluator_Value()について説明します。
Evaluator_Value()について説明する前にパターンインデックスを計算するマクロについて説明します。
これらのマクロは以下のように記述されています。
#define BOARD_INDEX_4(b,s1,s2,s3,s4) \ (((Board_Disk((b),(s1)) * 3 + Board_Disk((b),(s2))) * 3 + Board_Disk((b),(s3))) * 3 + \ Board_Disk((b),(s4))) #define BOARD_INDEX_5(b,s1,s2,s3,s4,s5) \ ((((Board_Disk((b),(s1)) * 3 + Board_Disk((b),(s2))) * 3 + Board_Disk((b),(s3))) * 3 + \ Board_Disk((b),(s4))) * 3 + Board_Disk((b),(s5))) #define BOARD_INDEX_6(b,s1,s2,s3,s4,s5,s6) \ (((((Board_Disk((b),(s1)) * 3 + Board_Disk((b),(s2))) * 3 + Board_Disk((b),(s3))) * 3 + \ Board_Disk((b),(s4))) * 3 + Board_Disk((b),(s5))) * 3 + Board_Disk((b),(s6))) #define BOARD_INDEX_7(b,s1,s2,s3,s4,s5,s6,s7) \ ((((((Board_Disk((b),(s1)) * 3 + Board_Disk((b),(s2))) * 3 + Board_Disk((b),(s3))) * 3 + \ Board_Disk((b),(s4))) * 3 + Board_Disk((b),(s5))) * 3 + Board_Disk((b),(s6))) * 3 + \ Board_Disk((b),(s7))) #define BOARD_INDEX_8(b,s1,s2,s3,s4,s5,s6,s7,s8) \ (((((((Board_Disk((b),(s1)) * 3 + Board_Disk((b),(s2))) * 3 + Board_Disk((b),(s3))) * 3 + \ Board_Disk((b),(s4))) * 3 + Board_Disk((b),(s5))) * 3 + Board_Disk((b),(s6))) * 3 + \ Board_Disk((b),(s7))) * 3 + Board_Disk((b),(s8))) #define BOARD_INDEX_9(b,s1,s2,s3,s4,s5,s6,s7,s8,s9) \ ((((((((Board_Disk((b),(s1)) * 3 + Board_Disk((b),(s2))) * 3 + Board_Disk((b),(s3))) * 3 + \ Board_Disk((b),(s4))) * 3 + Board_Disk((b),(s5))) * 3 + Board_Disk((b),(s6))) * 3 + \ Board_Disk((b),(s7))) * 3 + Board_Disk((b),(s8))) * 3 + Board_Disk((b),(s9))) #define BOARD_INDEX_10(b,s1,s2,s3,s4,s5,s6,s7,s8,s10) \ ((((((((Board_Disk((b),(s1)) * 3 + Board_Disk((b),(s2))) * 3 + Board_Disk((b),(s3))) * 3 + \ Board_Disk((b),(s4))) * 3 + Board_Disk((b),(s5))) * 3 + Board_Disk((b),(s6))) * 3 + \ Board_Disk((b),(s7))) * 3 + Board_Disk((b),(s8))) * 3 + Board_Disk((b),(s9))) * 3 + \ Board_Disk((b),(s10)))
Boardクラスとマスの位置を指定することでパターンインデックスを計算します。
4マスで構成されるパターンから10マスで構成されるパターンまでそれぞれマクロが用意されています。
例えばA4からH8まで1列に並んだマスのパターンの場合には
BOARD_INDEX_8(board, A4, B4, C4, D4, E4, F4, G4, H4)
とすることで計算できます。
ここでboardはBoardクラスへのポインタです。
それでは局面の評価を行う関数Evaluator_Value()の内部を見てみましょう。
ちょっと長いですが、全部記述します。
int Evaluator_Value(const Evaluator *self, const Board *in_board)
{
int result = 0;
/* A4-H4 */
result += self->Value[PATTERN_ID_LINE4][BOARD_INDEX_8(in_board, A4, B4, C4, D4, E4, F4, G4, H4)];
/* A5-H5 */
result += self->Value[PATTERN_ID_LINE4][BOARD_INDEX_8(in_board, A5, B5, C5, D5, E5, F5, G5, H5)];
/* D1-D8 */
result += self->Value[PATTERN_ID_LINE4][BOARD_INDEX_8(in_board, D1, D2, D3, D4, D5, D6, D7, D8)];
/* E1-E8 */
result += self->Value[PATTERN_ID_LINE4][BOARD_INDEX_8(in_board, E1, E2, E3, E4, E5, E6, E7, E8)];
/* A3-H3 */
result += self->Value[PATTERN_ID_LINE3][BOARD_INDEX_8(in_board, A3, B3, C3, D3, E3, F3, G3, H3)];
/* A6-H6 */
result += self->Value[PATTERN_ID_LINE3][BOARD_INDEX_8(in_board, A6, B6, C6, D6, E6, F6, G6, H6)];
/* C1-C8 */
result += self->Value[PATTERN_ID_LINE3][BOARD_INDEX_8(in_board, C1, C2, C3, C4, C5, C6, C7, C8)];
/* F1-F8 */
result += self->Value[PATTERN_ID_LINE3][BOARD_INDEX_8(in_board, F1, F2, F3, F4, F5, F6, F7, F8)];
/* A2-H2 */
result += self->Value[PATTERN_ID_LINE2][BOARD_INDEX_8(in_board, A2, B2, C2, D2, E2, F2, G2, H2)];
/* A7-H7 */
result += self->Value[PATTERN_ID_LINE2][BOARD_INDEX_8(in_board, A7, B7, C7, D7, E7, F7, G7, H7)];
/* B1-B8 */
result += self->Value[PATTERN_ID_LINE2][BOARD_INDEX_8(in_board, B1, B2, B3, B4, B5, B6, B7, B8)];
/* G1-G8 */
result += self->Value[PATTERN_ID_LINE2][BOARD_INDEX_8(in_board, G1, G2, G3, G4, G5, G6, G7, G8)];
/* A1-H8 */
result += self->Value[PATTERN_ID_DIAG8][BOARD_INDEX_8(in_board, A1, B2, C3, D4, E5, F6, G7, H8)];
/* A8-H1 */
result += self->Value[PATTERN_ID_DIAG8][BOARD_INDEX_8(in_board, A8, B7, C6, D5, E4, F3, G2, H1)];
/* A2-G8*/
result += self->Value[PATTERN_ID_DIAG7][BOARD_INDEX_7(in_board, A2, B3, C4, D5, E6, F7, G8)];
/* B1-H7 */
result += self->Value[PATTERN_ID_DIAG7][BOARD_INDEX_7(in_board, B1, C2, D3, E4, F5, G6, H7)];
/* A7-G1 */
result += self->Value[PATTERN_ID_DIAG7][BOARD_INDEX_7(in_board, A7, B6, C5, D4, E3, F2, G1)];
/* B8-H2 */
result += self->Value[PATTERN_ID_DIAG7][BOARD_INDEX_7(in_board, B8, C7, D6, E5, F4, G3, H2)];
/* A3-F8*/
result += self->Value[PATTERN_ID_DIAG6][BOARD_INDEX_6(in_board, A3, B4, C5, D6, E7, F8)];
/* C1-H6 */
result += self->Value[PATTERN_ID_DIAG6][BOARD_INDEX_6(in_board, C1, D2, E3, F4, G5, H6)];
/* A6-F1 */
result += self->Value[PATTERN_ID_DIAG6][BOARD_INDEX_6(in_board, A6, B5, C4, D3, E2, F1)];
/* C8-H3 */
result += self->Value[PATTERN_ID_DIAG6][BOARD_INDEX_6(in_board, C8, D7, E6, F5, G4, H3)];
/* A4-E8*/
result += self->Value[PATTERN_ID_DIAG5][BOARD_INDEX_5(in_board, A4, B5, C6, D7, E8)];
/* D1-H5 */
result += self->Value[PATTERN_ID_DIAG5][BOARD_INDEX_5(in_board, D1, E2, F3, G4, H5)];
/* A5-E1 */
result += self->Value[PATTERN_ID_DIAG5][BOARD_INDEX_5(in_board, A5, B4, C3, D2, E1)];
/* D8-H4 */
result += self->Value[PATTERN_ID_DIAG5][BOARD_INDEX_5(in_board, D8, E7, F6, G5, H4)];
/* A5-D8*/
result += self->Value[PATTERN_ID_DIAG4][BOARD_INDEX_4(in_board, A5, B6, C7, D8)];
/* E1-H4 */
result += self->Value[PATTERN_ID_DIAG4][BOARD_INDEX_4(in_board, E1, F2, G3, H4)];
/* A4-D1 */
result += self->Value[PATTERN_ID_DIAG4][BOARD_INDEX_4(in_board, A4, B3, C2, D1)];
/* E8-H5 */
result += self->Value[PATTERN_ID_DIAG4][BOARD_INDEX_4(in_board, E8, F7, G6, H5)];
/* A1-G1 + B2 */
result += self->Value[PATTERN_ID_EDGE8][BOARD_INDEX_8(in_board, A1, B1, C1, D1, E1, F1, G1, B2)];
/* H1-B1 + G2 */
result += self->Value[PATTERN_ID_EDGE8][BOARD_INDEX_8(in_board, H1, G1, F1, E1, D1, C1, B1, G2)];
/* A8-G8 + B7 */
result += self->Value[PATTERN_ID_EDGE8][BOARD_INDEX_8(in_board, A8, B8, C8, D8, E8, F8, G8, B7)];
/* H8-B8 + G7 */
result += self->Value[PATTERN_ID_EDGE8][BOARD_INDEX_8(in_board, H8, G8, F8, E8, D8, C8, B8, G7)];
/* A1-A7 + B2 */
result += self->Value[PATTERN_ID_EDGE8][BOARD_INDEX_8(in_board, A1, A2, A3, A4, A5, A6, A7, B2)];
/* A8-A2 + B7 */
result += self->Value[PATTERN_ID_EDGE8][BOARD_INDEX_8(in_board, A8, A7, A6, A5, A4, A3, A2, B7)];
/* H1-H7 + G2 */
result += self->Value[PATTERN_ID_EDGE8][BOARD_INDEX_8(in_board, H1, H2, H3, H4, H5, H6, H7, G2)];
/* H8-H2 + G7 */
result += self->Value[PATTERN_ID_EDGE8][BOARD_INDEX_8(in_board, H8, H7, H6, H5, H4, H3, H2, G7)];
/* A1-C1 + A2-C2 + A3-B3 */
result += self->Value[PATTERN_ID_CORNER8][BOARD_INDEX_8(in_board, A1, B1, C1, A2, B2, C2, A3, B3)];
/* H1-F1 + H2-F2 + H3-G3 */
result += self->Value[PATTERN_ID_CORNER8][BOARD_INDEX_8(in_board, H1, G1, F1, H2, G2, F2, H3, G3)];
/* A8-C8 + A7-C7 + A6-B6 */
result += self->Value[PATTERN_ID_CORNER8][BOARD_INDEX_8(in_board, A8, B8, C8, A7, B7, C7, A6, B6)];
/* H8-F8 + H7-F7 + H6-G6 */
result += self->Value[PATTERN_ID_CORNER8][BOARD_INDEX_8(in_board, H8, G8, F8, H7, G7, F7, H6, G6)];
/* parity */
result += self->Value[PATTERN_ID_PARITY][Board_CountDisks(in_board, EMPTY) & 1];
return result;
}
関数自体は長いですが、処理の内容は単純です。
各パターンのインデックスを求め、変数Valueから対応する評価値を取り出して足していっているだけです。