def gas_helps(constraints, race): for unit, count in constraints: # reactor build time 50s, marine 25s if unit == MARINE and count > 3: return True # cycore time 50 # warp gate time 160 # zealot time 38 -> 28 with warpgate if unit == ZEALOT and count > 5: return True instance = Instance() instance.init_as_race(race) can_reach = set([i for i in xrange(NUM_UNITS) if instance.units[i] > 0]) old_size = 0 new_size = len(can_reach) gasless_events = filter(lambda event: event.cost[1] == 0, events) while old_size < new_size: old_size = new_size for event in gasless_events: for req, kind in event.requirements: if kind is not NOT and req not in can_reach: break else: if event.result in [add, warp, research, warp]: can_reach |= set([product for product in event.args]) new_size = len(can_reach) required = set([i for unit, count in constraints]) return required.issubset(can_reach)
def a_star_optimization(race, constraints): """ Returns the optimal build order for fitting the given constraints, having calculated it via an A* search Optimality is measured according to time required to meet constraints. This function necessarily returns a most optimal build Contraints is an array of units required in the form [(UNIT_INDEX, UNIT_COUNT)] Race denotes the race: "Z", "P", or "T" """ frozen_cons = frozenset(constraints) set_up(frozen_cons,race) frontier = PriorityQueue() # no limit first_instance = Instance() first_instance.init_as_race(race) # The items in the queue should be a tuple, with the first element being a tuple of events, and the second element being the last instance of those events. if has_constraints(first_instance, constraints): # Create the desired order using the events list best_order = Order(race = race, events_list = tuple()) return best_order frontier.push((tuple(), first_instance), 1) while not frontier.isEmpty(): events_so_far, current_instance = frontier.pop() # Check all available event options # TODO move filter into all avaialable options = current_instance.all_available() # somehow we need to handle gas tricks # filter ones that help # TODO chronoboost options = [[option, ""] for option in options if helps(option, frozen_cons) and Order(race = race, events_list = events_so_far + ([option,""],), calc = False).sanity_check(True)] while len(options) > 0: for index in xrange(len(options) -1, -1, -1): # yeah event_info = options[index] if (current_instance.available(now = True, event_index = event_info[0])): del options[index] new_instance = copy.deepcopy(current_instance) new_instance.apply_event(event_info) extension = (events_so_far + (event_info,), new_instance) if events[event_info[0]].get_result() == boost: pass else: frontier.push(extension, cost(extension[1]) + heuristic(extension[1],constraints)) current_instance.increment({},{}) if has_constraints(current_instance, constraints): best_order = Order(race = race, events_list = events_so_far) return best_order raise Exception("a_star optimization shouldn't have exited without a solution.")