def getAvailableMovesScore(board, position, unit): ''' compute a score that defines how desirable each position is given how many units you can eat for certain and when (time - dist) ''' eatableOpponents = [k for k in board.humansPos if unit >= board.humansPos[k]] + [k for k in board.getOpponentDict() if unit >= 1.5*board.getOpponentDict()[k]] number = [u for u in board.humansPos.values() if unit >= u] + [u for u in board.getOpponentUnitsNumber() if unit >= 1.5 * u] distance = [np.max(np.abs(np.subtract(list(enemy), position))) for enemy in eatableOpponents] score = np.sum([n/(d+1) for n, d in zip(number, distance)]) return score
def getHeuristic(board, heuristicHistory, Smart_score): hash = board.hash() if (hash in heuristicHistory): heuristic = heuristicHistory[hash] else: #print('Board :', board.getBoard()) our_position, our_unit_nb = board.getBiggestPosition() opponents_unit_nb = board.getOpponentUnitsNumberSum() humans_pos = np.array(list(board.humansPos.keys()), dtype=(int, int)) humans_nb = np.array(list(board.humansPos.values()), dtype=int) enemy_pos = np.array(board.getOpponentCurrentPositions(), dtype=(int, int)) enemy_nb = np.array(board.getOpponentUnitsNumber(), dtype=int) #filter human positions where we are not at least equal to them in number humans_pos = humans_pos[humans_nb <= our_unit_nb] humans_nb = humans_nb[humans_nb <= our_unit_nb] #filter enemy positions where we are 1.5x more so we are sure to win enemy_pos = enemy_pos[enemy_nb * 1.5 <= our_unit_nb] enemy_nb = enemy_nb[enemy_nb * 1.5 <= our_unit_nb] if len(humans_pos) > 0: positions_tile = np.tile( our_position, (len(humans_pos), 1) ) # create an array of our_position, reapeated human_pos times #compute the distance with humans (and our position) max_dist = np.max(np.abs(positions_tile - humans_pos), axis=1) max_heuristic_humans = humans_nb / (max_dist + 1) else: max_heuristic_humans = [0] if len(enemy_pos) > 0: positions_tile = np.tile(our_position, (len(enemy_pos), 1)) #compute the distance with ennemy max_dist = np.max(np.abs(positions_tile - enemy_pos), axis=1) max_heuristic_enemy = enemy_nb / (max_dist + 1) else: max_heuristic_enemy = [0] #our heuristic is human heuristic + enemy heuristic + our current unit_nb - enemy unit number #print(board.getBiggestPosition()) #print("max(max_heuristic_humans)", max(max_heuristic_humans), # "max_heuristic_enemy", max_heuristic_enemy, # "max(max_heuristic_enemy)" , max(max_heuristic_enemy)) heuristic = max(max_heuristic_humans) + max( max_heuristic_enemy) + our_unit_nb - opponents_unit_nb #print(heuristic) heuristicHistory[hash] = heuristic return heuristic
def getOrderedScore(position, board): ''' position refers to one of the potential new positions we could occupy in the next round give bonuses to each position wrt to our ability to eat humans/ennemies in a close future ''' bonus = 0 my_unit = board.getBiggestPosition()[1] # first type of bonus - if we eat enemies if (tuple(position) in board.getOpponentCurrentPositions()): if board.getOpponentDict()[tuple( position)] <= board.getBiggestPosition()[1]: bonus += 1000 * board.getOpponentDict()[tuple(position)] # second type - if we eat humans if (tuple(position) in board.humansPos): if board.humansPos[tuple(position)] <= board.getBiggestPosition()[1]: bonus += 100 * board.humansPos[tuple(position)] # third type of bonus : we get closer to possibly eatable humans or enemies eatable = [k for k, v in board.humansPos.items() if my_unit >= v] + [ k for k, v in board.getOpponentDict().items() if my_unit >= 1.5 * v ] if len(eatable) > 0: maxDistance = max(board.board_w, board.board_h) maxNumber = board.getOpponentUnitsNumberSum() + sum( list(board.humansPos.values())) distance = [ 10 - 9 * np.max(np.abs(np.subtract(list(enemy), position))) / maxDistance for enemy in eatable ] number = [ 9 * unit / maxNumber for unit in board.humansPos.values() if my_unit >= unit ] + [ 9 * unit / maxNumber for unit in board.getOpponentUnitsNumber() if my_unit >= 1.5 * unit ] combined = [10 * dist + num for dist, num in zip(distance, number)] bonus += (maxDistance - np.min(combined)) return bonus
def getSmarterHeuristic(board, heuristicHistory, Smart_score): """ Heuristic function """ hash = board.hash() if (hash in heuristicHistory): heuristic = heuristicHistory[hash] else: score = 0 # Store essential information our_position, our_unit_nb = board.getBiggestPosition() units_nb = board.getCurrentUnitsNumber() total_units_nb = board.getCurrentUnitsNumberSum() our_pos = board.getCurrentPositions() humans_pos = np.array(list(board.humansPos.keys()), dtype=(int, int)) humans_nb = np.array(list(board.humansPos.values()), dtype=int) total_humans_nb = np.sum(humans_nb) enemy_pos = np.array(board.getOpponentCurrentPositions(), dtype=(int, int)) enemy_nb = np.array(board.getOpponentUnitsNumber(), dtype=int) opponents_unit_nb = board.getOpponentUnitsNumberSum() distanceEnemies = [ np.max(np.abs(np.subtract(list(enemy), our_position))) for enemy in enemy_pos ] # distanceHumans = [np.max(np.abs(np.subtract(list(human_loc), our_position))) """ # Consider the case where there is no human left if total_humans_nb == 0: for dist, enemy_unit in zip(distanceEnemies, enemy_nb): if (enemy_unit < 1.5 * total_units_nb): score += 10000 / ((dist+1)*(enemy_unit)) else: score -= 10 /(dist+1) heuristic = score heuristicHistory[hash] = heuristic # consider distance of ennemy with our units --> if = 1, bad. else: """ # Consider eatable humans and proximity - does not deal with split yet potential_units = total_units_nb for humans_loc, human_unit in zip(humans_pos, humans_nb): dist = np.max(np.abs(np.subtract(humans_loc, our_position))) if (human_unit > potential_units): p = 0 elif (total_units_nb >= human_unit): p = 1 else: p = 2 / 3 distEH = min([ np.max(np.abs(np.subtract(list(enemy), humans_loc))) for enemy in enemy_pos ]) if ((distEH) / (dist + 1) <= 1 / 4): q = 0.5 elif (0.9 < (distEH + 1) / (dist + 1) and (distEH + 1) / (dist + 1) < 1.2): q = 1.2 else: q = 1 score += p * q * human_unit / (dist + 1) potential_units += human_unit # Consider ennemies for dist, enemy_unit in zip(distanceEnemies, enemy_nb): if (enemy_unit >= 1.5 * total_units_nb): score -= (enemy_unit - total_units_nb) / (dist + 1) # avoid elif (total_units_nb > 1.5 * enemy_unit): score += (total_units_nb - enemy_unit) / (dist + 1 ) # go towards else: score += 1 / (dist + 1) # if no humans left, go attack # consider distance of ennemy with our units --> if = 1, bad. # Compute heuristic greedy = 4 # how greedy we want our bot to be, meaning how much does it values the units gained within tree search # score is weighted by 1, Smart_score by 3.5. heuristic = score + Smart_score - greedy * opponents_unit_nb + greedy * total_units_nb heuristicHistory[hash] = heuristic return heuristic