def get_order_for_npc_sim(cls, sim): zone_director = get_restaurant_zone_director() if zone_director is None: logger.error( 'Trying to get an order for an NPC sim but there is no restaurant zone director.' ) return menu_items = [] for course in cls.FOOD_COURSES: menu_items.extend(zone_director.get_menu_for_course(course)) possible_orders = list( cls.get_possible_orders(sim, menu_items).items()) food_choice = random.weighted_random_item(possible_orders, flipped=True) business_manager = services.business_service( ).get_business_manager_for_zone() if business_manager is not None: bucks_tracker = services.active_household().bucks_tracker if bucks_tracker.is_perk_unlocked( RestaurantTuning.CUSTOMERS_ORDER_EXPENSIVE_FOOD_PERK_DATA. perk): food_choice_2 = random.weighted_random_item(possible_orders, flipped=True) if food_choice_2 is not food_choice: choice_1_price = business_manager.get_value_with_markup( food_choice.restaurant_base_price) choice_2_price = business_manager.get_value_with_markup( food_choice_2.restaurant_base_price) if choice_2_price > choice_1_price: food_choice = food_choice_2 drink_choice = cls.get_choice_for_npc_sim(sim, cls.DRINK_COURSE) if food_choice is None and drink_choice is None: return (None, cls.WATER_ORDER_FOR_BACKUP) return (food_choice, drink_choice)
def _give_reward_payout(reward_instance, sim_info, reward_destination, disallowed_reward_types=(), force_rewards_to_sim_info_inventory=False): payout = [] for reward in reward_instance.rewards: if issubclass(type(reward), tuple): weighted_rewards = [] for random_reward in reward: if random_reward.reward is None: weighted_rewards.append((random_reward.weight, None)) else: if random_reward.reward.factory.reward_type in disallowed_reward_types: continue weighted_rewards.append( (random_reward.weight, random_reward.reward)) chosen_reward_type = random.weighted_random_item(weighted_rewards) else: chosen_reward_type = reward if reward.factory.reward_type not in disallowed_reward_types else None if chosen_reward_type is not None: reward = chosen_reward_type() reward.open_reward(sim_info, reward_destination=reward_destination, force_rewards_to_sim_info_inventory= force_rewards_to_sim_info_inventory, reward_source=reward_instance) payout.append(reward) if payout: reward_instance.try_show_notification(sim_info) return payout
def _start_bowling_situation(self, bowling_lane_obj): situation_manager = services.get_zone_situation_manager() if not self.bowling_venue.bowling_situations_schedule.entries: return total_bowling_lanes = self.get_total_bowling_lanes() all_weighted_situations = self.bowling_venue.bowling_situations_schedule.get_weighted_situations( ) weighted_situations = [ (weight, situation[0]) for (weight, situation) in all_weighted_situations if situation[0].situation_meets_starting_requirements( total_bowling_lanes) ] if not weighted_situations: return situation_to_create = weighted_random_item(weighted_situations) guest_list = situation_to_create.get_predefined_guest_list() if guest_list is None: guest_list = SituationGuestList(invite_only=True) situation_id = situation_manager.create_situation( situation_to_create, guest_list=guest_list, spawn_sims_during_zone_spin_up=True, user_facing=False) self.set_situation_bowling_lane(situation_id, bowling_lane_obj) return situation_id
def do_route_fail_gen(self, timeline): if self.route_fail is None: yield target = self.get_target() if target is None: resolver = SingleObjectResolver(self._obj) else: resolver = DoubleObjectResolver(self._obj, target) balloons = self.route_fail.get_balloon_icons(resolver) if not balloons: yield balloon = weighted_random_item(balloons) if balloon is None: yield icon_info = balloon.icon(resolver, balloon_target_override=None) if icon_info[0] is None and icon_info[1] is None: yield category_icon = None if balloon.category_icon is not None: category_icon = balloon.category_icon(resolver, balloon_target_override=None) (balloon_type, priority) = BALLOON_TYPE_LOOKUP[balloon.balloon_type] balloon_overlay = balloon.overlay request = BalloonRequest(self._obj, icon_info[0], icon_info[1], balloon_overlay, balloon_type, priority, TunableBalloon.BALLOON_DURATION, 0, 0, category_icon) request.distribute()
def _move_objects(self): objects_to_move = services.object_manager().get_objects_matching_tags(self.object_tags, match_any=True) if not objects_to_move: return resolver = self._get_placement_resolver() choices = [(location.weight.get_multiplier(resolver), location.placement_strategy) for location in self.placement_strategy_locations] chosen_strategy = random.weighted_random_item(choices) do_fade = self.fade is not None out_sequence = [] moves = [] in_sequence = [] for object_to_move in objects_to_move: object_to_move.cancel_interactions_running_on_object(FinishingType.OBJECT_CHANGED, cancel_reason_msg='Object changing location.') if self.vfx_on_move is not None: out_sequence.append(lambda _, object_to_move=object_to_move: self.vfx_on_move(object_to_move).start_one_shot()) if do_fade: out_sequence.append(lambda _, object_to_move=object_to_move: object_to_move.fade_out(self.fade.out_time)) moves.append(lambda _, object_to_move=object_to_move: chosen_strategy.try_place_object(object_to_move, resolver)) if do_fade: in_sequence.append(lambda _, object_to_move=object_to_move: object_to_move.fade_in(self.fade.in_time)) sequence = [] if out_sequence: sequence.append(out_sequence) sequence.append(SoftSleepElement(clock.interval_in_sim_minutes(self.fade.out_time))) sequence.append(moves) if in_sequence: sequence.append(in_sequence) element = build_element(sequence, critical=CleanupType.RunAll) services.time_service().sim_timeline.schedule(element)
def _run_finish_actions(self, finish_action): weight_pairs = [(self._get_action_result_weight(action_result), action_result) for action_result in finish_action.action_results] action_result = weighted_random_item(weight_pairs) if action_result is not None: loot_display_text = None resolver = self._interaction.get_resolver() for actions in action_result.loot_actions: for (loot_op, test_ran) in actions.get_loot_ops_gen(resolver): while loot_op.apply_to_resolver(resolver, skip_test=test_ran): if action_result.notification is not None: current_loot_display_text = loot_op.get_display_text() if current_loot_display_text is not None: if loot_display_text is None: loot_display_text = current_loot_display_text else: loot_display_text = self.LOOT_NOTIFICATION_TEXT(loot_display_text, current_loot_display_text) if action_result.notification is not None: if loot_display_text is not None: notification_text = lambda *tokens: self.NOTIFICATION_TEXT(action_result.notification.text(*tokens), loot_display_text) else: notification_text = action_result.notification.text dialog = action_result.notification(self._sim, self._interaction.get_resolver()) dialog.text = notification_text dialog.show_dialog() if action_result.next_moments: next_moment_key = random.choice(action_result.next_moments) self._parent_adventure.queue_adventure_moment(next_moment_key) if action_result.continuation: self._interaction.push_tunable_continuation(action_result.continuation)
def get_ambient_walkby_situation(cls): desire = cls._get_desired_ambient_walkby_situations() if desire is None: return lot_id = services.active_lot_id() weighted_situations = tuple((item.weight, item.situation) for item in desire.weighted_situations if item.situation.can_start_walkby(lot_id)) sitaution = random.weighted_random_item(weighted_situations) return sitaution
def get_definition(self, resolver): definition = weighted_random_item([ (pair.weight.get_multiplier(resolver), pair.definition) for pair in self.definitions ]) if definition is not None: return definition return self.fallback_definition
def transfer_parent_states(self, child_obj, state_mapping): if state_mapping is None: return for parent_state in state_mapping.keys(): while self.owner.state_value_active(parent_state): weight_pairs = [(data.weight, data.child_state) for data in state_mapping.get(parent_state)] state_result = weighted_random_item(weight_pairs) child_obj.set_state(state_result.state, state_result)
def get_choice_for_npc_sim(cls, sim, course): zone_director = get_restaurant_zone_director() menu_items = zone_director.get_menu_for_course(course) possible_items = cls.get_possible_orders(sim, menu_items) if not possible_items: return choice = random.weighted_random_item(list(possible_items.items()), flipped=True) return choice
def get_creation_params(self, resolver): weighted_recipe_creation_data = list( (weighted_recipe.weight.get_multiplier(resolver), weighted_recipe.recipe) for weighted_recipe in self.weighted_recipes) recipe_factory = weighted_random_item(weighted_recipe_creation_data) return ObjectCreationParams( recipe_factory.get_definition(resolver), {'chosen_creation_data': (recipe_factory, recipe_factory.recipe)})
def get_order_for_npc_sim_with_menu(cls, sim, menu_preset): chef_menu = RestaurantTuning.MENU_PRESETS[menu_preset] menu_items = [] for course in cls.FOOD_COURSES: menu_items.extend(chef_menu.recipe_map.get(course, {})) possible_orders = cls.get_possible_orders(sim, menu_items) food_order = random.weighted_random_item(list(possible_orders.items()), flipped=True) return food_order
def _get_initial_adventure_moment_key(self): initial_adventure_moment_key = _initial_adventure_moment_key_overrides.get(self.interaction.sim) if initial_adventure_moment_key is not None: return initial_adventure_moment_key if self._resumable: initial_adventure_moment_key = self.tracker.get_adventure_moment(self.interaction) if initial_adventure_moment_key is not None: return initial_adventure_moment_key participant_resolver = self.interaction.get_resolver() return weighted_random_item([(moment.weight.get_multiplier(participant_resolver), moment.adventure_moment_key) for moment in self._initial_moments])
def get_creation_params(self, resolver): weighted_recipe_creation_data = list( (weighted_recipe.weight.get_multiplier(resolver), weighted_recipe.recipe_tag) for weighted_recipe in self.weighted_recipe_tags) recipe_factory = weighted_random_item(weighted_recipe_creation_data) recipe = recipe_factory.choose_recipe() return ObjectCreationParams( recipe.final_product.definition, {'chosen_creation_data': (recipe_factory, recipe)})
def _create_object_rewards(self, obj_weight_pair, obj_counter, resolver): obj_result = weighted_random_item(obj_weight_pair) for obj_reward in obj_result: created_obj = create_object( obj_reward, init=None, post_add=lambda *args: self._place_object(resolver=resolver, *args)) while created_obj is not None: obj_counter[obj_reward] += 1
def get_situation_and_params(self, predicate=lambda _: True, additional_situations=None): weighted_situations = self.get_weighted_situations(predicate=predicate) if additional_situations is not None: weighted_situations = tuple(weighted_situations) + tuple( additional_situations) situation_and_params = random.weighted_random_item(weighted_situations) if situation_and_params is not None: return situation_and_params return (None, {})
def _on_customer_situation_request(self): self.remove_stale_customer_situations() desired_situation_count = self.customer_count_curb_appeal_curve.get(self._business_manager.get_curb_appeal()) valid_weighted_situations = self._get_valid_customer_situations(self._business_manager) if not valid_weighted_situations: logger.warn('Tried finding a valid starting situation for customer but no situations matches were found.') return while desired_situation_count > len(self._customer_situation_ids): situation_to_start = weighted_random_item(valid_weighted_situations) if situation_to_start is None: break self.start_customer_situation(situation_to_start)
def _choose_next_state(self, invalid_states=None): available_states = set( self._managed_states.keys()) - self._locked_states if invalid_states is not None: available_states = available_states - set(invalid_states) if not available_states: return VetEmployeeSituationStates.DEFAULT weighted = [(self._managed_states[key].weight, key) for key in available_states] weighted.append( (self._default_state_weight, VetEmployeeSituationStates.DEFAULT)) return random.weighted_random_item(weighted)
def _give_reward_payout(reward_instance, sim_info, is_household_reward): payout = [] chosen_reward = None for reward in reward_instance.rewards: if not isinstance(reward, TunableRewardBase): weighted_rewards = [(random_reward.weight, random_reward.reward) for random_reward in reward] chosen_reward = random.weighted_random_item(weighted_rewards) else: chosen_reward = reward chosen_reward.open_reward(sim_info, is_household_reward) payout.append(chosen_reward) if payout: reward_instance.try_show_notification(sim_info) return payout
def _run_action_from_index(self, action_index): try: finish_action = self._finish_actions[action_index] except IndexError as err: logger.exception('Exception {} while attempting to get finish action.\nFinishActions length: {}, ActionIndex: {},\nCurrent Moment: {},\nResolver: {}.\n', err, len(self._finish_actions), action_index, self._parent_adventure._current_moment_key, self.resolver) return forced_action_result = False weight_pairs = [(self._get_action_result_weight(action_result), action_result) for action_result in finish_action.action_results if self._is_action_result_available(action_result)] if not weight_pairs: if self._parent_adventure.force_action_result: forced_action_result = True weight_pairs = [(self._get_action_result_weight(action_result), action_result) for action_result in finish_action.action_results] action_result = weighted_random_item(weight_pairs) if not (action_result is not None or not finish_action.action_results) and not self._apply_action_cost(finish_action): return if action_result is not None: loot_display_text = None resolver = self.resolver for actions in action_result.loot_actions: for (loot_op, test_ran) in actions.get_loot_ops_gen(resolver): (success, _) = loot_op.apply_to_resolver(resolver, skip_test=test_ran) if success and action_result.notification is not None: current_loot_display_text = loot_op.get_display_text() if current_loot_display_text is not None: if loot_display_text is None: loot_display_text = current_loot_display_text else: loot_display_text = self.LOOT_NOTIFICATION_TEXT(loot_display_text, current_loot_display_text) if action_result.notification is not None: if loot_display_text is not None: notification_text = lambda *tokens: self.NOTIFICATION_TEXT(action_result.notification.text(*tokens), loot_display_text) else: notification_text = action_result.notification.text dialog = action_result.notification(self._sim, self.resolver) dialog.text = notification_text dialog.show_dialog() if action_result.next_moments: if forced_action_result: next_moment_key = random.choice(action_result.next_moments) else: next_moment_key = random.choice(tuple(moment_key for moment_key in action_result.next_moments if self._parent_adventure.is_adventure_moment_available(moment_key))) self._parent_adventure.queue_adventure_moment(next_moment_key) if action_result.results_dialog: dialog = action_result.results_dialog(self._sim, resolver=self.resolver) dialog.show_dialog() event_manager = services.get_event_manager() for event_type in action_result.events_to_send: event_manager.process_event(event_type, sim_info=self._sim.sim_info) if action_result.continuation: self._interaction.push_tunable_continuation(action_result.continuation)
def _create_object_rewards (self, obj_weight_states_tuple, obj_counter, resolver, subject = None, placement_override_func = None, post_object_create_func = None): (obj_result, obj_states, quantity) = weighted_random_item(obj_weight_states_tuple) object_rewards = [] if quantity is None: object_rewards = obj_result else: object_rewards.extend(random.choice(obj_result) for _ in range(quantity)) for obj_reward in object_rewards: created_obj = obj_reward(init = None, post_add = lambda *args: self._place_object(*args, resolver = resolver, subject = subject, placement_override_func = placement_override_func)) if created_obj is not None: if post_object_create_func is not None: post_object_create_func(created_obj) obj_counter[created_obj.definition] += 1 if obj_states: for obj_state in obj_states: created_obj.set_state(obj_state.state, obj_state)
def _spawn_object(self, spawn_type=None): if self._spawn_firemeter is not None and len(self._spawned_objects) >= self._spawn_firemeter: return if spawn_type: weight_pairs = [(data.spawn_weight, data) for data in self._spawner_data if data.spawner_option.spawn_type == spawn_type] force_initialization_spawn = True else: weight_pairs = self._get_non_interaction_spawner_data() force_initialization_spawn = False spawn_result = weighted_random_item(weight_pairs) if spawn_result: spawn_type = spawn_result.spawner_option.spawn_type if spawn_type == SpawnerTuning.GROUND_SPAWNER: radius = spawn_result.spawner_option.radius self.create_object_on_ground(self.owner, spawn_result, radius, force_initialization_spawn) if spawn_type == SpawnerTuning.SLOT_SPAWNER: slot_types = {spawn_result.spawner_option.slot_type} self.create_object_on_slot(self.owner, spawn_result, slot_types)
def _create_required_number_of_situations(self): situation_manager = services.get_zone_situation_manager() running_situations = [ type(situation) for situation in self._owner.get_running_festival_situations() ] for situation_entry in self._situations: number_of_situations_running = 0 for situation_type_entry in situation_entry.situations: number_of_situations_running += running_situations.count( situation_type_entry.situation) if situation_entry.object_tag_requirement is None: required_situations = situation_entry.number_of_situations else: tagged_objects = 0 for obj in self._owner.get_all_layer_created_objects(): if build_buy.get_object_has_tag( obj.definition.id, situation_entry.object_tag_requirement): tagged_objects += 1 required_situations = min(tagged_objects, situation_entry.number_of_situations) if number_of_situations_running < required_situations: possible_situations = [ (situation_type_entry.weight, situation_type_entry.situation) for situation_type_entry in situation_entry.situations if self._test_situation(situation_type_entry.situation) ] if possible_situations: for _ in range(situation_entry.number_of_situations - number_of_situations_running): situation = weighted_random_item(possible_situations) guest_list = situation.get_predefined_guest_list() if guest_list is None: guest_list = SituationGuestList(invite_only=True) situation_id = situation_manager.create_situation( situation, guest_list=guest_list, spawn_sims_during_zone_spin_up=True, user_facing=False) self._owner._add_created_situation(situation_id)
def get_weather_event(cls): weather_schedule = [] for (beginning_hour, event_list) in cls.weather_event_time_blocks.items(): weather_schedule.append((beginning_hour, event_list)) weather_schedule.sort(key=operator.itemgetter(0)) time_of_day = services.time_service().sim_now hour_of_day = time_of_day.hour() entry = weather_schedule[-1] weather_events = entry[1] for entry in weather_schedule: if entry[0] <= hour_of_day: weather_events = entry[1] else: break weighted_events = [(weather_event.weight, weather_event) for weather_event in weather_events] chosen_weather_event = random.weighted_random_item(weighted_events) return (chosen_weather_event.weather_event, chosen_weather_event.duration.random_float())
def _spawn_object(self, spawn_type=None, ignore_firemeter=False, create_slot_obj_count=1): spawn_firemeter_value = self.spawn_firemeter( self.owner ) if not ignore_firemeter and self.spawn_firemeter is not None else None if spawn_firemeter_value is not None and len( self._spawned_objects) >= spawn_firemeter_value: return if spawn_type is not None: weight_pairs = [(data.spawn_weight, data) for data in self._spawner_data if data.spawner_option.spawn_type == spawn_type] force_initialization_spawn = True else: weight_pairs = self._get_non_interaction_spawner_data() force_initialization_spawn = False spawn_result = weighted_random_item(weight_pairs) if spawn_result is None: logger.error( "Spawner {} didn't found an object to spawn for spawntype {}. This can be caused by an empty set ofspawn tunables or an infinite recursion force_spawnwhile trying to have a spawner spawn spawners", self.owner, spawn_type) return if random.random() > spawn_result.spawn_chance: return if spawn_result: spawn_type = spawn_result.spawner_option.spawn_type if spawn_type == SpawnerTuning.GROUND_SPAWNER: radius = spawn_result.spawner_option.radius min_radius = spawn_result.spawner_option.min_radius self._create_object_on_ground(spawn_result, radius, min_radius, force_initialization_spawn) if spawn_type == SpawnerTuning.SLOT_SPAWNER: slot_types = {spawn_result.spawner_option.slot_type} if force_initialization_spawn and spawn_result.spawner_option.force_initialization_spawn is not None: create_object_count = spawn_result.spawner_option.force_initialization_spawn else: create_object_count = create_slot_obj_count for _ in range(create_object_count): self._create_object_on_slot(spawn_result, slot_types)
def _spawn_object(self, spawn_type=None): if self._spawn_firemeter is not None and len( self._spawned_objects) >= self._spawn_firemeter: return if spawn_type: weight_pairs = [(data.spawn_weight, data) for data in self._spawner_data if data.spawner_option.spawn_type == spawn_type] force_initialization_spawn = True else: weight_pairs = self._get_non_interaction_spawner_data() force_initialization_spawn = False spawn_result = weighted_random_item(weight_pairs) if spawn_result: spawn_type = spawn_result.spawner_option.spawn_type if spawn_type == SpawnerTuning.GROUND_SPAWNER: radius = spawn_result.spawner_option.radius self.create_object_on_ground(self.owner, spawn_result, radius, force_initialization_spawn) if spawn_type == SpawnerTuning.SLOT_SPAWNER: slot_types = {spawn_result.spawner_option.slot_type} self.create_object_on_slot(self.owner, spawn_result, slot_types)
def modify_objects(self, object_criteria=None): objects_to_destroy = [] num_modified = 0 modifications = defaultdict(CompoundTestList) for mod in self.modifications: if not random_chance(mod.chance * 100): continue if mod.global_tests and not mod.global_tests.run_tests( GlobalResolver()): continue if mod.tests: modifications[mod.action].extend(mod.tests) if mod.weighted_tests: weighted_tests = [] for test_weight_pair in mod.weighted_tests: weighted_tests.append( (test_weight_pair.weight, test_weight_pair.tests)) modifications[mod.action].extend( weighted_random_item(weighted_tests)) if not modifications: return num_modified all_objects = list(services.object_manager().values()) for obj in all_objects: if obj.is_sim: continue if object_criteria is not None and not object_criteria(obj): continue resolver = SingleObjectResolver(obj) modified = False for (action, tests) in modifications.items(): if not tests.run_tests(resolver): continue modified = True action_type = action.action_type if action_type == ModifyAllLotItems.DESTROY_OBJECT: objects_to_destroy.append(obj) break elif action_type == ModifyAllLotItems.SET_STATE: new_state_value = action.action_value if obj.state_component and obj.has_state( new_state_value.state): obj.set_state(new_state_value.state, new_state_value, immediate=True) if action_type in ( ModifyAllLotItems.INVENTORY_TRANSFER, ModifyAllLotItems.DELIVER_BILLS): element = action.action_value() element._do_behavior() elif action_type == ModifyAllLotItems.SET_ON_FIRE: fire_service = services.get_fire_service() fire_service.spawn_fire_at_object(obj) elif action_type == ModifyAllLotItems.CLEANUP_VEHICLE: if self._should_cleanup_vehicle(obj): objects_to_destroy.append(obj) if action_type == ModifyAllLotItems.LOOT: for loot_action in action.loot_actions: loot_action.apply_to_resolver(resolver) else: raise NotImplementedError else: raise NotImplementedError elif action_type == ModifyAllLotItems.LOOT: for loot_action in action.loot_actions: loot_action.apply_to_resolver(resolver) else: raise NotImplementedError else: raise NotImplementedError elif action_type in (ModifyAllLotItems.INVENTORY_TRANSFER, ModifyAllLotItems.DELIVER_BILLS): element = action.action_value() element._do_behavior() elif action_type == ModifyAllLotItems.SET_ON_FIRE: fire_service = services.get_fire_service() fire_service.spawn_fire_at_object(obj) elif action_type == ModifyAllLotItems.CLEANUP_VEHICLE: if self._should_cleanup_vehicle(obj): objects_to_destroy.append(obj) if action_type == ModifyAllLotItems.LOOT: for loot_action in action.loot_actions: loot_action.apply_to_resolver(resolver) else: raise NotImplementedError else: raise NotImplementedError elif action_type == ModifyAllLotItems.LOOT: for loot_action in action.loot_actions: loot_action.apply_to_resolver(resolver) else: raise NotImplementedError else: raise NotImplementedError if modified: num_modified += 1 for obj in objects_to_destroy: obj.destroy(source=self, cause='Destruction requested by modify lot tuning') objects_to_destroy = None return num_modified