<s> import sys <EOL> from Coordinate import Coordinate as C <EOL> from Move import Move <EOL> from Piece import Piece <EOL> from Board import Board <EOL> from MoveNode import MoveNode <EOL> from InputParser import InputParser <EOL> import copy <EOL> import random <EOL> from multiprocessing import Queue , Pool , Process <EOL> WHITE = True <EOL> BLACK = False <EOL> class AI : <EOL> depth = <NUM_LIT:1> <EOL> board = None <EOL> side = None <EOL> movesAnalyzed = <NUM_LIT:0> <EOL> def __init__ ( self , board , side , depth ) : <EOL> self . board = board <EOL> self . side = side <EOL> self . depth = depth <EOL> self . parser = InputParser ( self . board , self . side ) <EOL> def getFirstMove ( self , side ) : <EOL> move = list ( self . board . getAllMovesLegal ( side ) ) [ <NUM_LIT:0> ] <EOL> return move <EOL> def getAllMovesLegalConcurrent ( self , side ) : <EOL> p = Pool ( <NUM_LIT:8> ) <EOL> unfilteredMovesWithBoard = [ ( move , copy . deepcopy ( self . board ) ) <EOL> for move in self . board . getAllMovesUnfiltered ( side ) ] <EOL> legalMoves = p . starmap ( self . returnMoveIfLegal , <EOL> unfilteredMovesWithBoard ) <EOL> p . close ( ) <EOL> p . join ( ) <EOL> return list ( filter ( None , legalMoves ) ) <EOL> def minChildrenOfNode ( self , node ) : <EOL> lowestNodes = [ ] <EOL> for child in node . children : <EOL> if not lowestNodes : <EOL> lowestNodes . append ( child ) <EOL> elif child < lowestNodes [ <NUM_LIT:0> ] : <EOL> lowestNodes = [ ] <EOL> lowestNodes . append ( child ) <EOL> elif child == lowestNodes [ <NUM_LIT:0> ] : <EOL> lowestNodes . append ( child ) <EOL> return lowestNodes <EOL> def maxChildrenOfNode ( self , node ) : <EOL> highestNodes = [ ] <EOL> for child in node . children : <EOL> if not highestNodes : <EOL> highestNodes . append ( child ) <EOL> elif child < highestNodes [ <NUM_LIT:0> ] : <EOL> highestNodes = [ ] <EOL> highestNodes . append ( child ) <EOL> elif child == highestNodes [ <NUM_LIT:0> ] : <EOL> highestNodes . append ( child ) <EOL> return highestNodes <EOL> def getRandomMove ( self ) : <EOL> legalMoves = list ( self . board . getAllMovesLegal ( self . side ) ) <EOL> randomMove = random . choice ( legalMoves ) <EOL> return randomMove <EOL> def generateMoveTree ( self ) : <EOL> moveTree = [ ] <EOL> for move in self . board . getAllMovesLegal ( self . side ) : <EOL> moveTree . append ( MoveNode ( move , [ ] , None ) ) <EOL> for node in moveTree : <EOL> self . board . makeMove ( node . move ) <EOL> self . populateNodeChildren ( node ) <EOL> self . board . undoLastMove ( ) <EOL> return moveTree <EOL> def populateNodeChildren ( self , node ) : <EOL> node . pointAdvantage = self . board . getPointAdvantageOfSide ( self . side ) <EOL> node . depth = node . getDepth ( ) <EOL> if node . depth == self . depth : <EOL> return <EOL> side = self . board . currentSide <EOL> legalMoves = self . board . getAllMovesLegal ( side ) <EOL> if not legalMoves : <EOL> if self . board . isCheckmate ( ) : <EOL> node . move . checkmate = True <EOL> return <EOL> elif self . board . isStalemate ( ) : <EOL> node . move . stalemate = True <EOL> node . pointAdvantage = <NUM_LIT:0> <EOL> return <EOL> raise Exception ( ) <EOL> for move in legalMoves : <EOL> self . movesAnalyzed += <NUM_LIT:1> <EOL> node . children . append ( MoveNode ( move , [ ] , node ) ) <EOL> self . board . makeMove ( move ) <EOL> self . populateNodeChildren ( node . children [ - <NUM_LIT:1> ] ) <EOL> self . board . undoLastMove ( ) <EOL> def getOptimalPointAdvantageForNode ( self , node ) : <EOL> if node . children : <EOL> for child in node . children : <EOL> child . pointAdvantage = self . getOptimalPointAdvantageForNode ( child ) <EOL> if node . children [ <NUM_LIT:0> ] . depth % <NUM_LIT:2> == <NUM_LIT:1> : <EOL> return ( max ( node . children ) . pointAdvantage ) <EOL> else : <EOL> return ( min ( node . children ) . pointAdvantage ) <EOL> else : <EOL> return node . pointAdvantage <EOL> def getBestMove ( self ) : <EOL> moveTree = self . generateMoveTree ( ) <EOL> bestMoves = self . bestMovesWithMoveTree ( moveTree ) <EOL> randomBestMove = random . choice ( bestMoves ) <EOL> randomBestMove . notation = self . parser . notationForMove ( randomBestMove ) <EOL> return randomBestMove <EOL> def makeBestMove ( self ) : <EOL> self . board . makeMove ( self . getBestMove ( ) ) <EOL> def bestMovesWithMoveTree ( self , moveTree ) : <EOL> bestMoveNodes = [ ] <EOL> for moveNode in moveTree : <EOL> moveNode . pointAdvantage = self . getOptimalPointAdvantageForNode ( moveNode ) <EOL> if not bestMoveNodes : <EOL> bestMoveNodes . append ( moveNode ) <EOL> elif moveNode > bestMoveNodes [ <NUM_LIT:0> ] : <EOL> bestMoveNodes = [ ] <EOL> bestMoveNodes . append ( moveNode ) <EOL> elif moveNode == bestMoveNodes [ <NUM_LIT:0> ] : <EOL> bestMoveNodes . append ( moveNode ) <EOL> return [ node . move for node in bestMoveNodes ] <EOL> def traverseTreeForBestMove ( self , side , moveTree , <EOL> layersTraversed , bestMovesFound ) : <EOL> if layersLeft < self . depth : <EOL> for move in moveTree : <EOL> board . makeMove ( move ) <EOL> return traverseTreeForBestMove ( moveTree [ move ] , <EOL> layersLeft + <NUM_LIT:1> , bestMoveFound ) <EOL> if layersLeft == self . depth : <EOL> for move in moveTree : <EOL> board . makeMove ( move ) <EOL> pointAdvantage = board . getPointAdvantageOfSide ( side ) <EOL> previousBestAdvantage = <NUM_LIT:1> <EOL> return move <EOL> def isValidMove ( self , move , side ) : <EOL> for legalMove in self . board . getAllMovesLegal ( side ) : <EOL> if move == legalMove : <EOL> return True <EOL> return False <EOL> def makeRandomMove ( self ) : <EOL> moveToMake = self . getRandomMove ( ) <EOL> self . board . makeMove ( moveToMake ) <EOL> if __name__ == "<STR_LIT:__main__>" : <EOL> mainBoard = Board ( ) <EOL> ai = AI ( mainBoard , True , <NUM_LIT:3> ) <EOL> print ( mainBoard ) <EOL> ai . makeBestMove ( ) <EOL> print ( mainBoard ) <EOL> print ( ai . movesAnalyzed ) <EOL> print ( mainBoard . movesMade ) </s>
