Skip to content

Commit 30aa342

Browse files
committed
Work on getting machine client working
1 parent bc8cdca commit 30aa342

File tree

4 files changed

+278
-94
lines changed

4 files changed

+278
-94
lines changed

computer_players/MiniMax_AI.py

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from typing import TYPE_CHECKING, TypeAlias, TypeVar
1515

16-
##from machine_client import RemoteState, run_clients_in_local_servers_sync
16+
from machine_client import RemoteState, run_clients_in_local_servers_sync
1717
from minimax import Minimax, MinimaxResult, Player
1818

1919
from azul.state import (
@@ -37,13 +37,13 @@
3737
# 1 = True = AI (Us) = MAX = 1, 3
3838

3939

40-
class AzulMinimax(Minimax[State, Action]):
40+
class AzulMinimax(Minimax[tuple[State, int], Action]):
4141
"""Minimax Algorithm for Checkers."""
4242

4343
__slots__ = ()
4444

4545
@staticmethod
46-
def value(state: State) -> int | float:
46+
def value(state: tuple[State, int]) -> int | float:
4747
"""Return value of given game state."""
4848
# Real
4949
real_state, max_player = state
@@ -68,76 +68,79 @@ def value(state: State) -> int | float:
6868
return (max_ - min_) / (abs(max_) + abs(min_) + 1)
6969

7070
@staticmethod
71-
def terminal(state: State) -> bool:
71+
def terminal(state: tuple[State, int]) -> bool:
7272
"""Return if game state is terminal."""
7373
real_state, _max_player = state
7474
return real_state.current_phase == Phase.end
7575

7676
@staticmethod
77-
def player(state: State) -> Player:
77+
def player(state: tuple[State, int]) -> Player:
7878
"""Return Player enum from current state's turn."""
7979
real_state, max_player = state
8080
return (
8181
Player.MAX if real_state.current_turn == max_player else Player.MIN
8282
)
8383

8484
@staticmethod
85-
def actions(state: State) -> Iterable[Action]:
85+
def actions(state: tuple[State, int]) -> Iterable[Action]:
8686
"""Return all actions that are able to be performed for the current player in the given state."""
8787
real_state, _max_player = state
8888
return tuple(real_state.yield_actions())
8989
## print(f'{len(actions) = }')
9090

9191
@staticmethod
92-
def result(state: State, action: Action) -> State:
92+
def result(state: tuple[State, int], action: Action) -> tuple[State, int]:
9393
"""Return new state after performing given action on given current state."""
9494
real_state, max_player = state
9595
return (real_state.preform_action(action), max_player)
9696

9797
@classmethod
98-
def adaptive_depth_minimax(cls, state: State) -> MinimaxResult[Action]:
98+
def adaptive_depth_minimax(
99+
cls,
100+
state: tuple[State, int],
101+
) -> MinimaxResult[Action]:
99102
"""Adaptive depth minimax."""
100103
# TODO
101104
depth = 1
102105
return cls.alphabeta(state, depth)
103106

104107

105-
##class MinimaxPlayer(RemoteState):
106-
## """Minimax Player."""
107-
##
108-
## __slots__ = ()
109-
##
110-
## async def preform_turn(self) -> Action:
111-
## """Perform turn."""
112-
## print("preform_turn")
113-
## ##value, action = CheckersMinimax.adaptive_depth_minimax(
114-
## ## self.state, 4, 5
115-
## ##)
116-
## ##value, action = CheckersMinimax.minimax(self.state, 4)
117-
## value, action = CheckersMinimax.alphabeta(self.state, 4)
118-
## if action is None:
119-
## raise ValueError("action is None")
120-
## print(f"{value = }")
121-
## return action
108+
class MinimaxPlayer(RemoteState):
109+
"""Minimax Player."""
122110

111+
__slots__ = ()
123112

124-
def run() -> None:
125-
"""Run MinimaxPlayer clients in local server."""
126-
import random
127-
128-
random.seed(0)
129-
130-
state = (State.new_game(2), 0)
131-
132-
while not AzulMinimax.terminal(state):
133-
action = AzulMinimax.adaptive_depth_minimax(state)
134-
print(f"{action = }")
135-
state = AzulMinimax.result(state, action.action)
136-
print(f"{state = }")
137-
print(state)
113+
async def preform_turn(self) -> Action:
114+
"""Perform turn."""
115+
print("preform_turn")
116+
##value, action = CheckersMinimax.adaptive_depth_minimax(
117+
## self.state, 4, 5
118+
##)
119+
##value, action = CheckersMinimax.minimax(self.state, 4)
120+
value, action = AzulMinimax.alphabeta((self.state, self.playing_as), 1)
121+
## value, action = AzulMinimax.alphabeta((self.state, self.playing_as), 4)
122+
if action is None:
123+
raise ValueError("action is None")
124+
print(f"{value = }")
125+
return action
138126

139127

140-
## run_clients_in_local_servers_sync(MinimaxPlayer)
128+
def run() -> None:
129+
"""Run MinimaxPlayer clients in local server."""
130+
## import random
131+
##
132+
## random.seed(0)
133+
##
134+
## state = (State.new_game(2), 0)
135+
##
136+
## while not AzulMinimax.terminal(state):
137+
## action = AzulMinimax.adaptive_depth_minimax(state)
138+
## print(f"{action = }")
139+
## state = AzulMinimax.result(state, action.action)
140+
## print(f"{state = }")
141+
## print(state)
142+
143+
run_clients_in_local_servers_sync(MinimaxPlayer)
141144

142145

143146
if __name__ == "__main__":

0 commit comments

Comments
 (0)