The UCI protocol does not handle draw offers or resignations, so a valid move still needs to be returned. The CECP_Mediator::handle_move() method needs to look at the board to report on draw offers and resignations.
When to offer/accept draw:
Define "dead band" of width D. If position scores have remained within +/- D for more than N moves, then offer draw.
If a draw is on offer, accept if a draw would have been offered or if the current best position score is less than -D.
When to resign:
Keep a modified running sum of all position evaluations of the moves made in the actual game. Scores within the dead band count for zero. Any score above dead band resets the sum to zero. Scores below the dead band are summed normally. If the score reaches beneath a threshold T, resign.
Tuning (initial plan)
Draws:
If two AIs agree to a draw, both are replaced by mutated clones of themselves.
If two AIs play to a draw by a rule (50-move or threefold repetition), then an offspring is created through mating and it replaces one of the parents with a 50% probability.
If an AI rejects a draw offer and goes on to lose, it is killed off and replaced by a clone of the winner.
If an AI rejects a draw offer and goes on to win, the other AI is killed off and replaced by a clone of the winner.
If an AI rejects a draw offer and the game ends in a draw, it is replaced by an offspring created through mating (same ending as resigning).
Resignations:
If an AI resigns, it is replaced by an offspring created through mating.
If an AI loses by checkmate or by time, it is replaced by a clone of the winner.
An important idea is that both offering and not offering a draw need to be risky to avoid populations that (1) agree to a draw before the first move and (2) never consider draws. Accepting a draw offer is safer than continuing the game to a rule-based draw, but the risks and rewards of rejecting a draw offer are magnified.
Similarly, for resigning, it is a loss, but at least some of the resigning AIs genes make it to the next generation. Never resigning leads to dominance or annihilation.
Overall, accurately reading a game for the outcome must be rewarded and inaccurate readings punished.
Questions:
Should multiple draw offers be allowed?
For now, no, as this will annoy human players on lichess (should draw offers ever be offered).
If so, should all scores/move counters be reset upon rejection?
For now, just have a flag std::array<bool, 2> Board::draw_already_offered and reject succeeding draw offers from the same player.
Implementation Sketch
Model signalling for draw offers on
board.pick_move_now()
.Inside
Minimax_AI::choose_move()
, after a move is chosen and just before returning the move,The UCI protocol does not handle draw offers or resignations, so a valid move still needs to be returned. The
CECP_Mediator::handle_move()
method needs to look at the board to report on draw offers and resignations.When to offer/accept draw:
Define "dead band" of width D. If position scores have remained within +/- D for more than N moves, then offer draw.
If a draw is on offer, accept if a draw would have been offered or if the current best position score is less than -D.
When to resign:
Keep a modified running sum of all position evaluations of the moves made in the actual game. Scores within the dead band count for zero. Any score above dead band resets the sum to zero. Scores below the dead band are summed normally. If the score reaches beneath a threshold T, resign.
Tuning (initial plan)
Draws:
Resignations:
An important idea is that both offering and not offering a draw need to be risky to avoid populations that (1) agree to a draw before the first move and (2) never consider draws. Accepting a draw offer is safer than continuing the game to a rule-based draw, but the risks and rewards of rejecting a draw offer are magnified.
Similarly, for resigning, it is a loss, but at least some of the resigning AIs genes make it to the next generation. Never resigning leads to dominance or annihilation.
Overall, accurately reading a game for the outcome must be rewarded and inaccurate readings punished.
Questions:
Should multiple draw offers be allowed?
For now, no, as this will annoy human players on lichess (should draw offers ever be offered).
If so, should all scores/move counters be reset upon rejection?
For now, just have a flag
std::array<bool, 2> Board::draw_already_offered
and reject succeeding draw offers from the same player.