-
Notifications
You must be signed in to change notification settings - Fork 455
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
243055a
commit 3ac7b46
Showing
1 changed file
with
95 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,95 +1,95 @@ | ||
""" | ||
Some example strategies for people who want to create a custom, homemade bot. | ||
With these classes, bot makers will not have to implement the UCI or XBoard interfaces themselves. | ||
""" | ||
|
||
from __future__ import annotations | ||
import chess | ||
from chess.engine import PlayResult, Limit | ||
import random | ||
from lib.engine_wrapper import MinimalEngine, MOVE | ||
from typing import Any | ||
import logging | ||
|
||
|
||
# Use this logger variable to print messages to the console or log files. | ||
# logger.info("message") will always print "message" to the console or log file. | ||
# logger.debug("message") will only print "message" if verbose logging is enabled. | ||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class ExampleEngine(MinimalEngine): | ||
"""An example engine that all homemade engines inherit.""" | ||
|
||
pass | ||
|
||
|
||
# Strategy names and ideas from tom7's excellent eloWorld video | ||
|
||
class RandomMove(ExampleEngine): | ||
"""Get a random move.""" | ||
|
||
def search(self, board: chess.Board, *args: Any) -> PlayResult: | ||
"""Choose a random move.""" | ||
return PlayResult(random.choice(list(board.legal_moves)), None) | ||
|
||
|
||
class Alphabetical(ExampleEngine): | ||
"""Get the first move when sorted by san representation.""" | ||
|
||
def search(self, board: chess.Board, *args: Any) -> PlayResult: | ||
"""Choose the first move alphabetically.""" | ||
moves = list(board.legal_moves) | ||
moves.sort(key=board.san) | ||
return PlayResult(moves[0], None) | ||
|
||
|
||
class FirstMove(ExampleEngine): | ||
"""Get the first move when sorted by uci representation.""" | ||
|
||
def search(self, board: chess.Board, *args: Any) -> PlayResult: | ||
"""Choose the first move alphabetically in uci representation.""" | ||
moves = list(board.legal_moves) | ||
moves.sort(key=str) | ||
return PlayResult(moves[0], None) | ||
|
||
|
||
class ComboEngine(ExampleEngine): | ||
""" | ||
Get a move using multiple different methods. | ||
This engine demonstrates how one can use `time_limit`, `draw_offered`, and `root_moves`. | ||
""" | ||
|
||
def search(self, board: chess.Board, time_limit: Limit, ponder: bool, draw_offered: bool, root_moves: MOVE) -> PlayResult: | ||
""" | ||
Choose a move using multiple different methods. | ||
:param board: The current position. | ||
:param time_limit: Conditions for how long the engine can search (e.g. we have 10 seconds and search up to depth 10). | ||
:param ponder: Whether the engine can ponder after playing a move. | ||
:param draw_offered: Whether the bot was offered a draw. | ||
:param root_moves: If it is a list, the engine should only play a move that is in `root_moves`. | ||
:return: The move to play. | ||
""" | ||
if isinstance(time_limit.time, int): | ||
my_time = time_limit.time | ||
my_inc = 0 | ||
elif board.turn == chess.WHITE: | ||
my_time = time_limit.white_clock if isinstance(time_limit.white_clock, int) else 0 | ||
my_inc = time_limit.white_inc if isinstance(time_limit.white_inc, int) else 0 | ||
else: | ||
my_time = time_limit.black_clock if isinstance(time_limit.black_clock, int) else 0 | ||
my_inc = time_limit.black_inc if isinstance(time_limit.black_inc, int) else 0 | ||
|
||
possible_moves = root_moves if isinstance(root_moves, list) else list(board.legal_moves) | ||
|
||
if my_time / 60 + my_inc > 10: | ||
# Choose a random move. | ||
move = random.choice(possible_moves) | ||
else: | ||
# Choose the first move alphabetically in uci representation. | ||
possible_moves.sort(key=str) | ||
move = possible_moves[0] | ||
return PlayResult(move, None, draw_offered=draw_offered) | ||
""" | ||
Some example strategies for people who want to create a custom, homemade bot. | ||
With these classes, bot makers will not have to implement the UCI or XBoard interfaces themselves. | ||
""" | ||
|
||
from __future__ import annotations | ||
import chess | ||
from chess.engine import PlayResult, Limit | ||
import random | ||
from lib.engine_wrapper import MinimalEngine, MOVE | ||
from typing import Any | ||
import logging | ||
|
||
|
||
# Use this logger variable to print messages to the console or log files. | ||
# logger.info("message") will always print "message" to the console or log file. | ||
# logger.debug("message") will only print "message" if verbose logging is enabled. | ||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class ExampleEngine(MinimalEngine): | ||
"""An example engine that all homemade engines inherit.""" | ||
|
||
pass | ||
|
||
|
||
# Strategy names and ideas from tom7's excellent eloWorld video | ||
|
||
class RandomMove(ExampleEngine): | ||
"""Get a random move.""" | ||
|
||
def search(self, board: chess.Board, *args: Any) -> PlayResult: | ||
"""Choose a random move.""" | ||
return PlayResult(random.choice(list(board.legal_moves)), None) | ||
|
||
|
||
class Alphabetical(ExampleEngine): | ||
"""Get the first move when sorted by san representation.""" | ||
|
||
def search(self, board: chess.Board, *args: Any) -> PlayResult: | ||
"""Choose the first move alphabetically.""" | ||
moves = list(board.legal_moves) | ||
moves.sort(key=board.san) | ||
return PlayResult(moves[0], None) | ||
|
||
|
||
class FirstMove(ExampleEngine): | ||
"""Get the first move when sorted by uci representation.""" | ||
|
||
def search(self, board: chess.Board, *args: Any) -> PlayResult: | ||
"""Choose the first move alphabetically in uci representation.""" | ||
moves = list(board.legal_moves) | ||
moves.sort(key=str) | ||
return PlayResult(moves[0], None) | ||
|
||
|
||
class ComboEngine(ExampleEngine): | ||
""" | ||
Get a move using multiple different methods. | ||
This engine demonstrates how one can use `time_limit`, `draw_offered`, and `root_moves`. | ||
""" | ||
|
||
def search(self, board: chess.Board, time_limit: Limit, ponder: bool, draw_offered: bool, root_moves: MOVE) -> PlayResult: | ||
""" | ||
Choose a move using multiple different methods. | ||
:param board: The current position. | ||
:param time_limit: Conditions for how long the engine can search (e.g. we have 10 seconds and search up to depth 10). | ||
:param ponder: Whether the engine can ponder after playing a move. | ||
:param draw_offered: Whether the bot was offered a draw. | ||
:param root_moves: If it is a list, the engine should only play a move that is in `root_moves`. | ||
:return: The move to play. | ||
""" | ||
if isinstance(time_limit.time, int): | ||
my_time = time_limit.time | ||
my_inc = 0 | ||
elif board.turn == chess.WHITE: | ||
my_time = time_limit.white_clock if isinstance(time_limit.white_clock, int) else 0 | ||
my_inc = time_limit.white_inc if isinstance(time_limit.white_inc, int) else 0 | ||
else: | ||
my_time = time_limit.black_clock if isinstance(time_limit.black_clock, int) else 0 | ||
my_inc = time_limit.black_inc if isinstance(time_limit.black_inc, int) else 0 | ||
|
||
possible_moves = root_moves if isinstance(root_moves, list) else list(board.legal_moves) | ||
|
||
if my_time / 60 + my_inc > 10: | ||
# Choose a random move. | ||
move = random.choice(possible_moves) | ||
else: | ||
# Choose the first move alphabetically in uci representation. | ||
possible_moves.sort(key=str) | ||
move = possible_moves[0] | ||
return PlayResult(move, None, draw_offered=draw_offered) |