def move(self, game_state): self.start_timer() self.res_action, self.res_state = self.choose_default_answer(game_state) print "w=",CenterMassEvaluator().evaluate(game_state,WHITE) print "b=",CenterMassEvaluator().evaluate(game_state,BLACK) try: EndTimer.check("m10") # calculate info set for this game_state if self.init_state is self.prev_state: state_info_set = self.info_set #first turn is us: we already has infoset else: state_info_set = self._update_info_set_no_action(self.prev_state, game_state, self.info_set) EndTimer.check("m20") # calculate info set for result game_state self.res_info_set = self._update_info_set_no_action(game_state, self.res_state, state_info_set) #choose our move # results saved in self.res_action, self.res_state self.search(game_state, state_info_set, self.init_max_depth) #save our turn and its info set: to be able calculate next one except TimeOutException: #TODO for release handle all exceptios pass # save data about our move self.prev_state = self.res_state self.info_set = self.res_info_set return self.res_action
def evaluate2(self, state, player, action =None, quad_table_ext=None): ''' @type state: loa_game.LinesOfActionState ''' cmt = initialize(state.board) cmt.coord_repr EndTimer.check(name="cm_f") my_coord_list = cmt.coord_repr[player] cm = cmt.cm_dict[player] EndTimer.check(name="cm_g") GTimeStatistics.start_measure("sum_of_min_distances_ext2") rsmd = self.sum_of_min_distances_ext2(cm,my_coord_list) GTimeStatistics.stop_measure("sum_of_min_distances_ext2") smart_sum, smart_sum_count, dsum, dmin_sum, dmin, dmin_count = rsmd r1 = self.min_sum_res(smart_sum_count, smart_sum) r2 = self.min_sum_fix(dmin, dmin_count, len(my_coord_list)) return r1, r2
def search(self, current_state, info_set, init_max_depth): ''' @param info_set: info set of current_state ''' # start iterative search curr_max_depth = init_max_depth # print "time left", end_time - time.clock(), "d=", curr_max_depth while True: EndTimer.check("start search") print "time left", EndTimer.time_left(), "d=", curr_max_depth alg = SmartAlphaBetaSearch(self.player, self.utility, self.turn_cache, self.winner_check,self.use_quads) self.res_action, self.res_state, self.res_info_set = alg.search(current_state, curr_max_depth, info_set) curr_max_depth += self.depth_delta #TODO: TODO
def sum_of_min_distances_ext2(self,cm,coord_list): dists = map(lambda p: self.distance(cm,p), coord_list) EndTimer.check(name="cm_d") dsum = sum(dists) dmin = min(dists) EndTimer.check(name="cm_e") dmin_count = dists.count(dmin) dmin_sum = dmin * dmin_count smart_sum = dsum - dmin_sum smart_sum_count = len(coord_list) - dmin_count return smart_sum, smart_sum_count, dsum, dmin_sum, dmin, dmin_count
def move(self, game_state): self.start_timer() self.res_action, self.res_state = self.choose_default_answer(game_state) self.turn_cache.clean_up_if_need(game_state, self.last_game_state) #gc stuff gc.enable() collected = self.time_statistics.measure_function(gc.collect) self.collected += collected gc.disable() try: EndTimer.check("m10") # calculate info set for this game_state if self.init_state is self.prev_state: state_info_set = self.info_set #first turn is us: we already has infoset else: state_info_set = self._update_info_set_no_action(self.prev_state, game_state, self.info_set) EndTimer.check("m20") # calculate info set for result game_state self.res_info_set = self._update_info_set_no_action(game_state, self.res_state, state_info_set) #choose our move # results saved in self.res_action, self.res_state self.search(game_state, state_info_set, self.init_max_depth) #save our turn and its info set: to be able calculate next one except TimeOutException: #TODO for release handle all exceptios self.node_statistics.clear_monitor() pass #save data about last gamestate self.last_game_state = game_state # save data about our move self.prev_state = self.res_state self.info_set = self.res_info_set self.stop_timer() # print "cm", CenterMassEvaluator().evaluate(self.res_state, self.player, self.res_info_set) # print "e", QuadEvaluator().evaluate(self.res_state, self.player, self.res_info_set) return self.res_action
def search(self, current_state, info_set, init_max_depth): ''' @param info_set: info set of current_state ''' # start iterative search curr_max_depth = init_max_depth #print init_max_depth # print "time left", end_time - time.clock(), "d=", curr_max_depth alg = SmartAlphaBetaSearch(self.player, self.utility, self.turn_cache, self.time_statistics, self.node_statistics, self.winner_check, ) while True: EndTimer.check("start search") self.node_statistics.start_monitor(curr_max_depth) r = alg.search(current_state, curr_max_depth, info_set) self.node_statistics.stop_monitor(curr_max_depth) self.res_action, self.res_state, self.res_info_set = r #print "Solution at depth:", curr_max_depth, " time left:", EndTimer.time_left() curr_max_depth += self.depth_delta
def search(self, current_state, max_depth, info_set): ''' Search game to determine best action; use alpha-beta pruning. @param current_state: The current game state to start the search from. @return: best_action, best_state ''' # on each search this is renewed! # best_value = -INFINITY EndTimer.check(name="a") #successors = current_state.getSuccessors() successors = self.turn_cache.get(current_state, LinesOfActionState.getSuccessors) successors_items = successors.items() EndTimer.check(name="a1") for action, newstate in successors_items: new_info_set = self._update_info_set(current_state, newstate, action, info_set) EndTimer.check(name="b") #state_info = {} # todo initiate newstate info value = self._minValue(newstate, best_value, INFINITY, 1,max_depth, new_info_set) if value > best_value: best_value = value best = (action,newstate,new_info_set) return best
def _minValue(self, state, alpha, beta, depth,max_depth,info_set): need_return, v = self._need_return(state, depth, max_depth,info_set) if need_return: return v value = INFINITY EndTimer.check(name="f") #successors = state.getSuccessors() successors = self.turn_cache.get(state, LinesOfActionState.getSuccessors) # -- reordering -- #ordered_successors = self.f_oreder(successors,depth,max_depth) #str_key = "_minValue.successors.items() d:{%s} tag{%s}" % (depth,random_tag()) #self.time_statistics.start_measure(str_key) successors_items = successors.items() #self.time_statistics.stop_measure(str_key) for action, successor_state in successors_items: EndTimer.check(name="g") # update iterative info for son node new_info_set = self._update_info_set(state, successor_state, action, info_set) EndTimer.check(name="h") max_value = self._maxValue(successor_state, alpha, beta, depth + 1,max_depth,new_info_set) value = min(value,max_value) if value <= alpha: # cut return value beta = min(beta, value) return value
def _need_return(self,state, depth, max_depth,info_set): ''' checks if node terminal or reached depth limit =X @return: True, value if X if node terminal or reached depth limit, value - node value False,0 - continue searching ''' EndTimer.check("_need_return10") #every (min/max Value) starts with this self.node_statistics.visit_node() # check if node is terminate w = self.f_checkWinner(state,info_set) # if it is : return its value (-1 for enemy, +1 for us) if w != 0: return True,w EndTimer.check("_need_return20") # if reached depth limit: evaluate node using heuristics if depth >= max_depth: u_res = self.turn_cache.get(state, self.utility, info_set) return True, u_res# self.utility(state) # new_info_set return False,0
def initialize(board): # {WHITE : [(x,y),(x1,y1),...], BLACK : [(x,y),(x1,y1),...]} EndTimer.check(name="cm_a") coord_repr = state_to_coord_repr(board) # central of mass dict {WHITE : (x,y) , BLACK : [(x,y),(x1,y1),...]} cm_dict ={} EndTimer.check(name="cm_b") cm_dict[WHITE] = center_of_mass_from_coord_list(coord_repr[WHITE]) EndTimer.check(name="cm_c") cm_dict[BLACK] = center_of_mass_from_coord_list(coord_repr[BLACK]) res = CenterMassTable(coord_repr,cm_dict) return res
def _maxValue(self, state, alpha, beta, depth,max_depth, info_set): need_return, v = self._need_return(state, depth, max_depth,info_set) if need_return: return v # -- on regular node : use improved alpha beta -- value = -INFINITY EndTimer.check(name="d1") #successors = state.getSuccessors() successors = self.turn_cache.get(state, LinesOfActionState.getSuccessors) # -- reordering -- #ordered_successors = self.f_oreder(successors,depth,max_depth) EndTimer.check(name="d2") #str_key = "_maxValue.successors.items() d:{%s} tag{1%s}" % (depth,random_tag()) #self.time_statistics.start_measure(str_key) successors_items = successors.items() #self.time_statistics.stop_measure(str_key) for action, successor_state in successors_items: EndTimer.check(name="d3") # update iterative info for son node new_info_set = self._update_info_set(state, successor_state, action, info_set) # calculate minimum for son EndTimer.check(name="e") min_value = self._minValue(successor_state, alpha, beta, depth + 1,max_depth, new_info_set ) value = max(value,min_value) if value >= beta: # cut return value alpha = max(alpha, value) # save partial results return value
def stop_timer(self): EndTimer.stop()
def start_timer(self): EndTimer.set_limit_and_start(self.corrected_turn_time_limit)