-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplay.py
122 lines (96 loc) · 3.38 KB
/
play.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import time
from datetime import datetime
from functools import partial
import pyautogui as pag
import common
import sigmar_garden
import vision
def click(position: pag.Point):
pag.moveTo(position, duration=0.3)
pag.mouseDown()
pag.mouseUp()
def solve(board: sigmar_garden.Board) -> list[sigmar_garden.Move]:
moves = []
if _solve(board, moves, set()):
return moves
return []
def _solve(
board: sigmar_garden.Board, moves: list[sigmar_garden.Move], seen: set
) -> bool:
if board.is_solved():
return True
# Limit the search space to fail faster
if board in seen or len(seen) > 30_000:
return False
seen.add(board)
next_moves = board.get_moves()
for move in sorted(next_moves, key=partial(get_move_score, board), reverse=True):
moves.append(move)
if _solve(board.do_move(move), moves, seen):
return True
moves.pop()
return False
def get_move_score(board: sigmar_garden.Board, move: sigmar_garden.Move) -> int:
cells = [board[point] for point in move.points]
if cells.count(sigmar_garden.Cell.SALT) == 1:
return 1 # discourage salt + element
return sum(map(get_cell_score, cells))
def get_cell_score(cell: sigmar_garden.Cell) -> int:
if cell in sigmar_garden.ELEMENTS:
return 4
if cell in (sigmar_garden.Cell.VITAE, sigmar_garden.Cell.MORS):
return 3
if cell in (sigmar_garden.Cell.SALT, sigmar_garden.Cell.QUICKSILVER):
return 3
if cell in sigmar_garden.METALS:
return 2
return 0
def play_single_game(cell_recognizer: vision.CellRecognizer):
print(datetime.now(), "- Looking for game board...")
pag.moveTo(1, 1)
board_bbox = pag.locateOnScreen("data/board.png", minSearchTime=10, confidence=0.9)
if board_bbox is None:
print("ERROR: could not find game board")
return
print(datetime.now(), f"- Found (at {board_bbox})")
print(datetime.now(), "- Reading board cells...")
positions = list(common.get_cell_positions(board_bbox))
screen = pag.screenshot()
board = sigmar_garden.Board.new_board()
for index, position in enumerate(positions):
cell = cell_recognizer.recognize(
screen.crop(common.get_cell_region(position, 40, 40))
)
point = sigmar_garden.Point.from_index(index)
board[point] = cell
print(datetime.now(), "- Done. Board:")
print(board)
print(datetime.now(), "- Solving...")
moves = solve(board)
if not moves:
print(datetime.now(), "- Couldn't solve :(")
return
print(datetime.now(), "- Playing...")
for move in moves:
for point in move.points:
click(positions[point.to_index()])
print(datetime.now(), "- Done!")
def main():
print(datetime.now(), "- Starting...")
time.sleep(2)
print(datetime.now(), "- Looking for newgame button...")
pag.moveTo(1, 1)
newgame_pos = pag.locateCenterOnScreen("data/newgame.png", confidence=0.9)
if newgame_pos is None:
print("ERROR: could not find newgame button")
return
print(datetime.now(), f"- Found (at {newgame_pos})")
cell_recognizer = vision.CellRecognizer()
while True:
play_single_game(cell_recognizer)
time.sleep(1)
print(datetime.now(), "- Starting a new game!")
click(newgame_pos)
time.sleep(10)
if __name__ == "__main__":
main()