evaluate: Do not attack too early when first 5 moves

If first 4 moves is placing at star point, move 5 temporarily use depth 1 search
in order to make sure white player do not attack and try to block black.
(For 9ms, star point is b4/d6/f4/d2)

This changed the white's moves.

For nine men's morris:

If first 4 moves is:
1. b4 d6
2. f4 d2
Next move, white will place at a4/c4/e4/g4,
now changed to place at d7/d5/d3/d1

If first 4 moves is:
1. b4 f4
2. d6 d2
Next move, white will place at b6, it is not wrong,
now changed to place at d4/g4/d3/d1, it is not wrong too.

Test result:

Play against Perfect Database:
400 games.
There is no significant change in the Draw rate.

Play 90 games against the pre-improved version:
White (New) Vs Black (Old)
White's win rate increased to 20%,  equivalent to Black's winning rate
Originally less than 10%.
This commit is contained in:
Calcitem 2021-06-14 11:42:37 +08:00
parent 97247acb80
commit e67dfc5645
4 changed files with 39 additions and 4 deletions

View File

@ -25,7 +25,7 @@
#pragma execution_character_set("utf-8") #pragma execution_character_set("utf-8")
#endif #endif
//#define EVALUATE_MOBILITY #define EVALUATE_MOBILITY
//#undef QT_GUI_LIB //#undef QT_GUI_LIB

View File

@ -56,6 +56,13 @@ Value Evaluation::value()
break; break;
case Phase::placing: case Phase::placing:
#ifdef EVALUATE_MOBILITY
if (pos.piece_on_board_count(WHITE) + pos.piece_on_board_count(BLACK) <= 5) {
value += (Value)pos.get_mobility_diff();
}
//break;
#endif /* EVALUATE_MOBILITY */
pieceInHandDiffCount = pos.piece_in_hand_count(WHITE) - pos.piece_in_hand_count(BLACK); pieceInHandDiffCount = pos.piece_in_hand_count(WHITE) - pos.piece_in_hand_count(BLACK);
value += VALUE_EACH_PIECE_INHAND * pieceInHandDiffCount; value += VALUE_EACH_PIECE_INHAND * pieceInHandDiffCount;
@ -77,12 +84,13 @@ Value Evaluation::value()
break; break;
case Phase::moving: case Phase::moving:
value = (pos.piece_on_board_count(WHITE) - pos.piece_on_board_count(BLACK)) * VALUE_EACH_PIECE_ONBOARD;
#ifdef EVALUATE_MOBILITY #ifdef EVALUATE_MOBILITY
value += pos.get_mobility_diff() / 5; //value += (Value)pos.get_mobility_diff();
//break;
#endif /* EVALUATE_MOBILITY */ #endif /* EVALUATE_MOBILITY */
value = (pos.piece_on_board_count(WHITE) - pos.piece_on_board_count(BLACK)) * VALUE_EACH_PIECE_ONBOARD;
switch (pos.get_action()) { switch (pos.get_action()) {
case Action::select: case Action::select:
case Action::place: case Action::place:

View File

@ -423,6 +423,25 @@ void move_priority_list_shuffle()
#endif #endif
} }
bool is_star_squares_full(Position *pos)
{
bool ret = false;
if (rule.hasDiagonalLines) {
ret = (pos->get_board()[SQ_17] &&
pos->get_board()[SQ_19] &&
pos->get_board()[SQ_21] &&
pos->get_board()[SQ_23]);
} else {
ret = (pos->get_board()[SQ_16] &&
pos->get_board()[SQ_18] &&
pos->get_board()[SQ_20] &&
pos->get_board()[SQ_22]);
}
return ret;
}
Depth get_search_depth(const Position *pos) Depth get_search_depth(const Position *pos)
{ {
Depth d = 0; Depth d = 0;
@ -447,6 +466,12 @@ Depth get_search_depth(const Position *pos)
const int index = rule.piecesCount * 2 - pos->count<IN_HAND>(WHITE) - pos->count<IN_HAND>(BLACK); const int index = rule.piecesCount * 2 - pos->count<IN_HAND>(WHITE) - pos->count<IN_HAND>(BLACK);
d = placingDepthTable[index]; d = placingDepthTable[index];
if (index == 4 &&
is_star_squares_full((Position *)pos)) {
d = 1; // In order to use Mobility
}
if (d == 0) { if (d == 0) {
return (Depth)gameOptions.getSkillLevel(); return (Depth)gameOptions.getSkillLevel();
} else { } else {

View File

@ -382,6 +382,8 @@ Value search(Position *pos, Sanmill::Stack<Position> &ss, Depth depth, Depth ori
epsilon = 0; epsilon = 0;
} }
//epsilon += pos->piece_to_remove_count();
#ifdef PVS_AI #ifdef PVS_AI
if (i == 0) { if (i == 0) {
if (after != before) { if (after != before) {