forked from TheYoBots/Lishogi-Bot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
strategies.py
91 lines (71 loc) · 2.71 KB
/
strategies.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
"""
Some example strategies for people who want to create a custom, homemade bot.
And some handy classes to extend
"""
import random
from engine_wrapper import EngineWrapper
class FillerEngine:
"""
Not meant to be an actual engine.
This is only used to provide the property "self.engine"
in "MinimalEngine" which extends "EngineWrapper"
"""
def __init__(self, main_engine, name=None):
self.id = {
"name": name
}
self.name = name
self.main_engine = main_engine
def __getattr__(self, method_name):
main_engine = self.main_engine
def method(*args, **kwargs):
nonlocal main_engine
nonlocal method_name
return main_engine.notify(method_name, *args, **kwargs)
return method
class MinimalEngine(EngineWrapper):
"""
Subclass this to prevent a few random errors
Even though MinimalEngine extends EngineWrapper,
you don't have to actually wrap an engine.
At minimum, just implement `search`,
however you can also change other methods like
`notify`, `first_search`, `get_time_control`, etc.
"""
def __init__(self, commands, options, stderr, name=None):
super().__init__(options)
self.go_commands = options.pop("go_commands", {}) or {}
self.engine_name = self.__class__.__name__ if name is None else name
self.last_move_info = []
self.engine = FillerEngine(self, name=self.name)
self.engine.id = {
"name": self.engine_name
}
def search_for(self, board, game, movetime):
return self.search(board, movetime, False)
def search(self, board, ponder):
raise NotImplementedError("The search method is not implemented")
def notify(self, method_name, *args, **kwargs):
"""
The EngineWrapper class sometimes calls methods on "self.engine".
"self.engine" is a filler property that notifies <self>
whenever an attribute is called.
Nothing happens unless the main engine does something.
Simply put, the following code is equivalent
self.engine.<method_name>(<*args>, <**kwargs>)
self.notify(<method_name>, <*args>, <**kwargs>)
"""
pass
class ExampleEngine(MinimalEngine):
pass
# Strategy names and ideas from tom7's excellent eloWorld video
class RandomMove(ExampleEngine):
def search(self, board, *args):
move = random.choice(list(board.legal_moves))
return move.usi(), None
class FirstMove(ExampleEngine):
"""Gets the first move when sorted by usi representation"""
def search(self, board, *args):
moves = list(board.legal_moves)
moves.sort(key=str)
return moves[0].usi(), None