def getMove(self, board): output.log("Selecting move...", module = "Player") tree = self.getGameTree(board, 1) energy = len(tree.children) moves = [x.board.move for x in tree.children] if len(moves) == 0: return None if energy < self.energythreshold: output.log("Energy %s is lower than %s, so I'll play near the bottom" % (energy, self.energythreshold), module = "Player") move1 = min(moves, key = lambda x : x[0][0]) #choose nearest to the top move2 = min(moves, key = lambda x : x[1][0]) move = min(move1, move2) else: output.log("Energy %s is higher or equal to %s, so I'll play near the top" % (energy, self.energythreshold), module = "Player") move1 = max(moves, key = lambda x : x[0][0]) #choose nearest to the top move2 = max(moves, key = lambda x : x[1][0]) move = max(move1, move2) output.log(move, module = "Player") output.log("Move is ", move, module = "Player") return move
def getMove(self, board): output.log("Selecting move...", module = "Player") moveInput = self.inputStream.readline().strip() try: matches = re.findall(r'^(\d+) (\d+) (\d+) (\d+)$', moveInput)[0] matches = [int(match) for match in matches] move = ((matches[0], matches[1]), (matches[2], matches[3])) except IndexError: output.log("Error parsing input!", module = "Error") move = None return move
def sanitize(self, verbose=True): if verbose: output.log("Sanitizing board...", module = 'Board') def testrefillBoard(refill): for i in range(0, self.columns): for j in range(0, self.rows): if (refill[0].getItem(i, j) > 0): return False return True #WARNING: the snippet below does not correctly simmulate the game's logic donesanitizing = False while not donesanitizing: donegravity = False while not donegravity: self.explodePatterns() donegravity = self.simulateGravity() donesanitizing = testrefillBoard(self.refillBoard()) if verbose: output.log("Done sanitizing.", module = 'Board')
def getMove(self, board): output.log("Calculating tree up to %s levels..." % self.depth, module = "Player") tree = self.getGameTree(board, self.depth) output.log("Calculating path...", module = "Player") (score, path) = self.getPath(tree) output.log("Path is %s (Score: %s). Will take first step and recalculate." % (path, score), module = "Player") if len(path) > 0: return path[0] else: return None
def __init__(self, *args, **kwargs): def getPlayer(name): playeroptions = { 'Human': player.Human(self.moves, self.name, self.inputStream), 'BestScore': player.BestScore(self.moves, self.depth), 'BestEnergy': player.BestEnergy(self.moves, self.depth), 'BestScoreBetterEnergy': player.BestScoreBetterEnergy(self.moves, self.depth, self.minenergy), 'EnergyVSEntropy': player.EnergyVSEntropy(self.moves, self.depth, self.energythreshold), 'EnergyVSEntropyReversed': player.EnergyVSEntropyReversed(self.moves, self.depth, self.energythreshold), 'GreedyEnergyVSEntropy': player.GreedyEnergyVSEntropy(self.moves, self.energythreshold) } return playeroptions[name] def getListOfPossibleMoves(rows, columns): moves = [] #horizontals for i_a in range(0, rows): for j_a in range(0, columns-1): moves.append(((i_a, j_a), (i_a, j_a+1))) #verticals for i_a in range(0, rows-1): for j_a in range(0, columns): moves.append(((i_a, j_a), (i_a+1, j_a))) #output.log("For this %sx%s board, there are a total of %s possible moves " % (rows, columns, len(moves)), module = 'Logic') return moves self.pauses = kwargs.get('pause', False) self.shorten = kwargs.get('shorten', False) self.limit = kwargs.get('limit') self.depth = kwargs.get('depth') self.minenergy = kwargs.get('minenergy', 2) self.energythreshold = kwargs.get('energythreshold') self.boardfile = kwargs.get('boardfile', None) self.refillfile = kwargs.get('refillfile', None) # Human Player self.name = None self.inputStream = sys.stdin # Main loop terminates when this is set True self.forceEnd = False # generate a new game if self.boardfile is None: columns = kwargs.get('columns') rows = kwargs.get('rows') colours = kwargs.get('colours') self.moves = getListOfPossibleMoves(columns, rows) self.board = board.Board(columns, rows, colours) self.board.sanitize() # load a saved board else: try: self.board = board.Board.LoadBoard(self.boardfile) self.board.refillboard = board.Board.LoadRefill(self.refillfile) except Exception as e: output.log("Error: ", e, module = 'Logic') sys.exit(0) self.moves = getListOfPossibleMoves(self.board.rows, self.board.columns) self.player = getPlayer(kwargs.get('player'))
def playGame(self): STATE_BEGIN, STATE_MOVE, STATE_EXPLODE, STATE_GRAVITY, STATE_REFILL, STATE_TERMINATE = range(6) def stateBegin(): output.event('logic_stateBegin', { 'iteration' : self.iteration, 'board_state' : self.board.state }) return STATE_MOVE def stateMove(): move = self.player.getMove(self.board) if (move == None): return True else: result = self.board.makeMove(move) output.event('logic_stateMove', { 'move' : str(move), 'marked_board' : self.board.state.reprConsoleMarkMoves(list(move)), 'move_result' : result }) return False def stateExplode(): (patterns, exploded) = self.board.explodePatterns() output.event('logic_stateExplode', { 'patterns' : patterns, 'exploded' : exploded, 'board_state' : self.board.state, 'shorten' : self.shorten }) return exploded def stateGravity(): fallCount = 0 while not self.board.simulateGravity(): fallCount += 1 output.event('logic_stateGravity', { 'board_state' : self.board.state, 'fall_count' : fallCount, 'shorten' : self.shorten }) def stateRefill(): (refill,_) = self.board.refillBoard() output.event('logic_stateRefill', { 'board_state' : self.board.state, 'refill' : refill, 'shorten' : self.shorten }) count = 0 chain = 0 totalcount = 0 totalchain = 0 score = 0 self.iteration = 1 while not self.forceEnd and (self.iteration <= self.limit or self.limit == 0): self.state = stateBegin() while self.state != STATE_BEGIN: if (self.state == STATE_MOVE): #chain starts at -1 because the first time pieces explode, points should be multiplied by 2^0. chain = -1 score = 0 jewels = [] result = stateMove() if result: output.log("Terminal state achieved in iteration %s. Score: %s." % (self.iteration, self.player.score), module = 'Logic') output.log(self.board.state, module = 'Logic', printModule = False) self.state = STATE_TERMINATE break self.state = STATE_EXPLODE elif (self.state == STATE_EXPLODE): exploded = stateExplode() count += exploded jewels.append(exploded) totalcount += exploded chain += 1 totalchain += chain self.lastscore = self.player.updateScore(exploded, chain) score += self.lastscore self.state = STATE_GRAVITY elif (self.state == STATE_GRAVITY): stateGravity() patterns = self.board.getPatterns() if self.board.hasOnes(patterns): self.state = STATE_EXPLODE else: self.state = STATE_REFILL elif (self.state == STATE_REFILL): stateRefill() patterns = self.board.getPatterns() if self.board.hasOnes(patterns): self.state = STATE_EXPLODE else: output.log("Local Chain: %s\tJewels: %s: %s\tScore: %s" % (chain, jewels, sum(jewels), score), module = 'Logic') output.log("Total Chain: %s\tJewels: %s\tScore: %s" % (totalchain, totalcount, self.player.score), module = 'Logic') self.state = STATE_BEGIN if (self.state == STATE_TERMINATE): break self.iteration += 1 if (self.pauses): raw_input("Press enter to continue.") return { 'iterations' : self.iteration - 1, 'totalChains' : totalchain, 'totalJewels' : totalcount, 'score' : self.player.score }
def getMove(self, board): output.log("Calculating tree up to %s levels..." % self.depth, module = "Player") tree = self.getGameTree(board, self.depth) output.log("Calculating best path...", module = "Player") (totalenergy, path) = self.getPath(tree) energyperdepthlevel = (totalenergy / self.depth) if len(path) > 0: if energyperdepthlevel < self.energythreshold: output.log("Energy per depth level is %s, below the threshold of %s" % (energyperdepthlevel, self.energythreshold), module = "Player") output.log("Will attempt to get lucky and play near the bottom", module = "Player") moves = [x.board.move for x in tree.children] move1 = min(moves, key = lambda x : x[0][0]) #choose nearest to the bottom move2 = min(moves, key = lambda x : x[1][0]) move = min(move1, move2) return move else: output.log("Energy per depth level is %s, above the threshold of %s" % (energyperdepthlevel, self.energythreshold), module = "Player") output.log("Path is %s (Energy: %s). Will take first step and recalculate." % (path, totalenergy), module = "Player") move = path[0] return move else: return None
depth = b_depth, minenergy = b_minenergy, pause = b_pause, energythreshold = b_energythreshold, shorten = b_shorten ) # handle ^C def handle_SIGINT(signal, frame): print('You pressed Ctrl+C!') game.endGame() signal.signal(signal.SIGINT, handle_SIGINT) output.log("**************************************", module = 'Main') output.log("* Welcome to AI Bejeweled", module = 'Main') output.log("* Rules:", module = 'Logic') if game.boardfile is not None: output.log("* Using board from %s and refill from %s " % (game.boardfile, game.refillfile), module = 'Main') output.log("* %sx%sx%s (%s possible moves)" % (game.board.columns, game.board.rows, game.board.colors, len(game.moves)), module = 'Main') output.log("* Using IA Agent %s " % game.player, module = 'Main') if game.limit > 0: output.log("* Will terminate after %s moves" % (game.limit), module = 'Main') output.log("**************************************", module = 'Main') results = game.playGame() output.log("****************************************************************", module = 'Main') output.log("* Simulation terminated after %s moves" % results['iterations'], module = 'Main') output.log("****************************************************************", module = 'Main')