1313
1414from 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
1717from minimax import Minimax , MinimaxResult , Player
1818
1919from azul .state import (
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
143146if __name__ == "__main__" :
0 commit comments