Download agent.py from end000/Checkers-WSPForge-Russian-v2: direct link, hf CLI and curl.
- Browser
- Download file 3.37 kB
-
https://huggingface.co/end000/Checkers-WSPForge-Russian-v2/resolve/main/agent.py
- Command line
-
hf download hf://end000/Checkers-WSPForge-Russian-v2/agent.py
-
curl -L -o agent.py https://huggingface.co/end000/Checkers-WSPForge-Russian-v2/resolve/main/agent.py
3.37 kB
| import argparse | |
| import random | |
| from pathlib import Path | |
| import numpy as np | |
| from draughts import RussianBoard | |
| from draughts.models import Color | |
| from network import FixedNetwork | |
| from rules import Adjudicator | |
| def encode(board,perspective): | |
| masks=(board.white_men,board.white_kings,board.black_men,board.black_kings) | |
| if perspective==Color.BLACK: | |
| masks=masks[2:]+masks[:2] | |
| x=np.zeros(128,np.float32) | |
| for p,mask in enumerate(masks): | |
| while mask: | |
| bit=mask&-mask | |
| square=bit.bit_length()-1 | |
| x[p*32+(square if perspective==Color.WHITE else 31-square)]=1 | |
| mask^=bit | |
| return x | |
| class Agent: | |
| def __init__(self,model_dir='.',seed=1): | |
| self.network=FixedNetwork.load(model_dir) | |
| self.rng=random.Random(seed) | |
| def choose(self,board): | |
| legal=board.legal_moves | |
| if not legal: | |
| raise ValueError('No legal moves') | |
| who=board.turn | |
| batch=[] | |
| for move in legal: | |
| board.push(move) | |
| batch.append(encode(board,who)) | |
| board.pop() | |
| scores=self.network.forward(np.stack(batch)) | |
| best=np.flatnonzero(np.isclose(scores,scores.max(),atol=1e-5,rtol=0)) | |
| return legal[self.rng.choice(best.tolist())] | |
| def notation(move): | |
| return (':' if move.captured_list else '-').join(RussianBoard.SQUARE_NAMES[s] for s in move.square_list) | |
| def main(): | |
| ap=argparse.ArgumentParser(description='Fixed-weight neural Russian draughts') | |
| ap.add_argument('--model-dir',default=str(Path(__file__).resolve().parent)) | |
| ap.add_argument('--fen') | |
| ap.add_argument('--seed',type=int,default=1) | |
| ap.add_argument('--human',choices=['white','black']) | |
| ap.add_argument('--one-move',action='store_true') | |
| args=ap.parse_args() | |
| board=RussianBoard.from_fen(args.fen) if args.fen else RussianBoard() | |
| agent=Agent(args.model_dir,args.seed) | |
| if args.one_move: | |
| print(notation(agent.choose(board))) | |
| return | |
| human=Color.WHITE if args.human=='white' else Color.BLACK if args.human=='black' else None | |
| ai_side=Color.BLACK if human==Color.WHITE else Color.WHITE | |
| random_opponent=random.Random(args.seed+1) | |
| referee=Adjudicator(board,max_plies=300) | |
| while True: | |
| print(board) | |
| legal=board.legal_moves | |
| outcome=referee.outcome(board,legal) | |
| if outcome is not None: | |
| winner,reason=outcome | |
| print('Draw' if winner==0 else 'White wins' if winner==-1 else 'Black wins',reason) | |
| return | |
| side=board.turn | |
| if side==human: | |
| for i,move in enumerate(legal): | |
| print(i+1,notation(move)) | |
| raw=input('Move number (q to quit): ').strip() | |
| if raw.lower()=='q': | |
| return | |
| try: | |
| index=int(raw)-1 | |
| if index<0: | |
| raise ValueError() | |
| move=legal[index] | |
| except (ValueError,IndexError): | |
| print('Choose a move number from the list') | |
| continue | |
| else: | |
| move=agent.choose(board) if side==ai_side else random_opponent.choice(legal) | |
| print('Move:',notation(move)) | |
| piece=board._get(move.square_list[0]) | |
| board.push(move) | |
| referee.update(board,move,piece,side) | |
| if __name__=='__main__': | |
| main() | |