def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._possible_situations = []
        for possible_situation in self.possible_situations:
            if possible_situation.situation.NPC_hosted_situation_player_job is None:
                logger.error('Situation: {} tuned in schedule entry without NPC_hosted_situation_player_job tuned.', possible_situation.situation)
            if possible_situation.situation.NPC_hosted_situation_player_job not in possible_situation.situation.get_tuned_jobs():
                logger.error('NPC_hosted_situation_player_job: {} tuned in Situation: {} that is not a possible job for that situation.', possible_situation.situation.NPC_hosted_situation_player_job, possible_situation.situation)
            self._possible_situations.append((possible_situation.weight, possible_situation.situation))
        self.duration = 0

    def select_situation(self):
        return sims4.random.weighted_random_item(self._possible_situations)

TunableNPCHostedSituationEntry = TunableSingletonFactory.create_auto_factory(NPCHostedSituationEntry)

class NPCHostedSituationSchedule(WeeklySchedule):
    __qualname__ = 'NPCHostedSituationSchedule'
    FACTORY_TUNABLES = {'schedule_entries': TunableList(description='\n                A list of event schedules. Each event is a mapping of days of\n                the week to a start_time and duration.\n                ', tunable=TunableNPCHostedSituationEntry()), 'cooldown': TunableSimMinute(description='\n                The cooldown of the scheduler.  If a situation is started\n                through it then another situation will not start for that\n                amount of time.\n                ', default=10, minimum=1), 'creation_chance': TunableRange(description='\n                Chance that a situation will start at each entry point.\n                ', tunable_type=float, default=0.5, minimum=0.0, maximum=1.0)}

    def __init__(self, schedule_entries, cooldown, creation_chance):
        super().__init__(schedule_entries, start_callback=self._try_and_create_NPC_hosted_situation, schedule_immediate=False, min_alarm_time_span=interval_in_sim_minutes(30))
        self._cooldown = interval_in_sim_minutes(cooldown)
        self._creation_chance = creation_chance

    def _try_and_create_NPC_hosted_situation(self, scheduler, alarm_data, callback_data):
        if random.random() > self._creation_chance:
            return
        if services.get_zone_situation_manager().is_user_facing_situation_running():
            return
Example #2
0
    def get_expected_args(self):
        return {'interaction': event_testing.test_events.FROM_EVENT_DATA}

    def __call__(self, interaction=None):
        if interaction.affordance is self.affordance:
            return TestResult.TRUE
        if self.tags & interaction.get_category_tags():
            return TestResult.TRUE
        return TestResult(
            False,
            'Failed affordance check: {} is not {} and does not have any matching tags in {}.',
            interaction.affordance, self.affordance, self.tags)


TunableInteractionOfInterest = TunableSingletonFactory.create_auto_factory(
    InteractionOfInterest)


class SituationGoalInteractionTime(SituationGoal):
    __qualname__ = 'SituationGoalInteractionTime'
    DURATION_RUN = 'duration_run'
    REMOVE_INSTANCE_TUNABLES = ('_post_tests', )
    INSTANCE_TUNABLES = {
        '_goal_test':
        TunableInteractionOfInterest(
            description=
            '\n                Interaction and duration that this situation goal will use.\n                Example: Bartend for 10 sim minutes.\n                ',
            tuning_group=GroupNames.TESTS)
    }

    def __init__(self, *args, reader=None, **kwargs):
        'role_state':
        TunableReference(
            services.get_instance_manager(sims4.resources.Types.ROLE_STATE),
            description='A role state the sim assigned to the job will perform'
        )
    }

    def __init__(self, situation_job, role_state):
        self.job = situation_job
        self.role_state = role_state

    def add_to_situation_jobs(self, situation):
        situation._add_job_type(self.job, self.role_state)


TunableSituationJobAndRoleState = TunableSingletonFactory.create_auto_factory(
    SituationJobAndRoleState)


class InteractionOfInterest(AutoFactoryInit):
    __qualname__ = 'InteractionOfInterest'
    FACTORY_TUNABLES = {
        'affordances':
        TunableList(
            TunableReference(services.affordance_manager()),
            description=
            "The Sim must have started either any affordance in this list or an interaction matching one of the tags in this tunable's Tags field."
        ),
        'tags':
        TunableSet(
            TunableEnumEntry(Tag, Tag.INVALID),
            description=
    def get_expected_args(self):
        return {'objects': ParticipantType.Object}

    def __call__(self, objects=None):
        obj = next(iter(objects))
        match = self.item(obj, None)
        if not match:
            return event_testing.results.TestResult(
                False,
                'ObjectMatchesDefinitionOrTagTest: Object did not match specified checks.'
            )
        return event_testing.results.TestResult.TRUE


TunableObjectMatchesDefinitionOrTagTest = TunableSingletonFactory.create_auto_factory(
    ObjectMatchesDefinitionOrTagTest)


class ModifyAllLotItems(HasTunableFactory, AutoFactoryInit):
    DESTROY_OBJECT = 0
    SET_STATE = 1
    INVENTORY_TRANSFER = 2
    DELIVER_BILLS = 3
    SET_ON_FIRE = 4
    CLEANUP_VEHICLE = 5
    LOOT = 6
    FACTORY_TUNABLES = {
        'description':
        '\n        Tune modifications to apply to all objects on a lot.\n        Can do state changes, destroy certain items, etc.\n        \n        EX: for auto cleaning, tune to have objects with Dirtiness state that\n        equals dirty to be set to the clean state and tune to have dirty dishes\n        and spoiled food to be deleted\n        ',
        'modifications':
        TunableList(
    def get_score_for_type(self, affordance, resolver):
        if self.is_type(affordance, resolver):
            return self._score_bonus
        return 0

    def get_success_for_type(self, affordance, resolver):
        if self.is_type(affordance, resolver):
            return self._success_modifier
        return 0

    def get_new_pie_menu_icon_and_parent_name_for_type(self, affordance,
                                                       resolver):
        if self.is_type(affordance, resolver):
            return (self._new_pie_menu_icon, self._pie_menu_parent_name,
                    self._interaction_category_blacklist_tags)
        return (None, None, None)

    def get_basic_extras_for_type(self, affordance, resolver):
        if self.is_type(affordance, resolver):
            return self._basic_extras
        return []

    def debug_affordances_gen(self):
        for affordance in self._affordances:
            yield affordance.__name__
        for affordnace_snippet in self._affordance_lists:
            yield affordnace_snippet.__name__


TunableAffordanceScoringModifier = TunableSingletonFactory.create_auto_factory(
    AffordanceReferenceScoringModifier)
    __qualname__ = 'EarningsOfInterest'
    FACTORY_TUNABLES = {'tags': TunableSet(description='\n                A set of tags that will match an affordance instead of looking\n                for a specific one. If you leave this empty, all Simoleons earned will be counted.\n                ', tunable=TunableEnumEntry(Tag, Tag.INVALID)), 'amount_to_earn': TunableRange(description='\n                The amount of time in Simoleons earned from all relevant activities for this\n                goal to pass.\n                ', tunable_type=int, default=10, minimum=1)}

    def get_expected_args(self):
        return {'amount': event_testing.test_events.FROM_EVENT_DATA, 'tags': event_testing.test_events.FROM_EVENT_DATA}

    def __call__(self, amount=None, tags=None):
        if amount is None:
            return TestResult(False, 'Amount is None')
        if len(self.tags) == 0 or tags is not None and self.tags & tags:
            if amount > 0:
                return TestResult.TRUE
            return TestResult(False, 'No money earned')
        return TestResult(False, 'Failed relevant tags check: Earnings do not have any matching tags in {}.', self.tags)

TunableEarningsOfInterest = TunableSingletonFactory.create_auto_factory(EarningsOfInterest)

class SituationGoalSimoleonsEarned(SituationGoal):
    __qualname__ = 'SituationGoalSimoleonsEarned'
    SIMOLEONS_EARNED = 'simoleons_earned'
    REMOVE_INSTANCE_TUNABLES = ('_post_tests',)
    INSTANCE_TUNABLES = {'_goal_test': TunableEarningsOfInterest(description='\n                Interaction and Simoleon amount that this situation goal will use.\n                Example: Earn 1000 Simoleons from Bartending activities.\n                ', tuning_group=GroupNames.TESTS)}

    def __init__(self, *args, reader=None, **kwargs):
        super().__init__(reader=reader, *args, **kwargs)
        self._total_simoleons_earned = 0
        self._test_events = set()
        self._test_events.add(event_testing.test_events.TestEvent.SimoleonsEarned)
        services.get_event_manager().register(self, self._test_events)
        if reader is not None:
            simoleons_earned = reader.read_uint64(self.SIMOLEONS_EARNED, 0)
        return TestResult.TRUE

    def _all_related_sims_and_id_gen(self, source_sim, target_sims):
        for sim_b_id in source_sim.relationship_tracker.target_sim_gen():
            sim_b = services.sim_info_manager().get(sim_b_id)
            yield (sim_b, sim_b_id)

    def _all_specified_sims_and_id_gen(self, source_sims, target_sims):
        for sim in target_sims:
            if sim is None:
                yield (None, None)
            else:
                yield (sim, sim.sim_id)


TunableRelationshipTest = TunableSingletonFactory.create_auto_factory(
    RelationshipTest)


class ObjectTypeRelationshipTest(HasTunableSingletonFactory,
                                 BaseRelationshipTest):
    FACTORY_TUNABLES = {
        'description':
        'Gate availability by a relationship status.\n        \n            Note: \n            This is different than the instance-based Object Relationship Component\n            and applies only to the relationships of Object Based Tracks tuned under\n            relationship tracker module tuning.\n            \n            If object rel does not exist, the test will treat the rel_track value \n            with an assumed value of 0 with no rel-bits.\n            ',
        'target_type':
        TunableVariant(
            description=
            '\n            The type of target we want to test the relationship on.  This will\n            either be a tag set (in the case where we want to test rel on \n            uninstantiated objects) or an object.\n            ',
            tag_set=TunableReference(
                description=
                '\n                Tag set that defines the target objects of the relationship.\n                ',
                manager=services.get_instance_manager(
Example #8
0
    def skill_tag_modifiers(self):
        return self._skill_tag_modifiers

    @property
    def commodities_to_add(self):
        return self._commodities_to_add

    @property
    def override_convergence(self):
        return self._override_convergence_value

    def is_locked(self, stat_type):
        if self._locked_stats and stat_type in self._locked_stats:
            return True
        return False

    def is_scored(self, stat_type):
        if self._only_scored_stat_types is None or stat_type in self._only_scored_stat_types:
            return True
        return False

    @property
    def off_lot_autonomy_rule(self):
        return self._off_lot_autonomy_rule

    @property
    def super_affordance_suppress_on_add(self):
        return self._super_affordance_suppress_on_add

TunableAutonomyModifier = TunableSingletonFactory.create_auto_factory(AutonomyModifier)
Example #9
0
        return dict(self.expected_kwargs)

    def __call__(self, interaction=None):
        if interaction.get_interaction_type() is self.affordance:
            return TestResult.TRUE
        if self.tags & interaction.get_category_tags():
            return TestResult.TRUE
        return TestResult(False, 'Failed affordance check: {} is not {} and does not have any matching tags in {}.', interaction.affordance, self.affordance, self.tags)

    def custom_keys_gen(self):
        if self.affordance:
            yield self.affordance
        for tag in self.tags:
            yield tag

TunableMultipleSimInteractionOfInterest = TunableSingletonFactory.create_auto_factory(MultipleSimInteractionOfInterest)

class SituationGoalMultipleSimsInInteraction(SituationGoal):
    INSTANCE_TUNABLES = {'_goal_test': TunableMultipleSimInteractionOfInterest(tuning_group=GroupNames.TESTS), '_select_sims_outside_of_situation': sims4.tuning.tunable.Tunable(bool, False, description='\n                If true, the goal system selects all instantiated sims in the zone.\n                ')}

    def __init__(self, *args, reader=None, **kwargs):
        super().__init__(*args, reader=reader, **kwargs)
        self._sims_running_interaction = set()
        self._test_events = set()

    def setup(self):
        super().setup()

        def test_affordance(sim):
            return sim.si_state.is_running_affordance(self._goal_test.affordance) or sim.get_running_interactions_by_tags(self._goal_test.tags)
Example #10
0
                subject_clubs = get_clubs_for_subject(subject)
                clubs_to_test = subject_clubs if clubs_to_test is None else clubs_to_test & subject_clubs
        if not clubs_to_test:
            return self.test_gathering(None, test_subjects, test_targets)
        if not any(
                self.test_gathering(club, test_subjects, test_targets)
                for club in clubs_to_test):
            return TestResult(
                False,
                'Subjects {} or Targets {} failed the club gatherings test for {}.',
                test_subjects, test_targets, clubs_to_test)
        else:
            return TestResult.TRUE


TunableClubGatheringTest = TunableSingletonFactory.create_auto_factory(
    ClubGatheringTest)


class ClubTest(HasTunableSingletonFactory, AutoFactoryInit,
               event_testing.test_base.BaseTest):
    _AffordanceData = namedtuple('_AffordanceData', ('affordance', 'target'))
    CLUB_USE_ASSOCIATED = 1
    CLUB_USE_ANY = 2
    CLUB_FROM_EVENT_DATA = 3
    AFFORDANCE_RULE_ENCOURAGED = 1
    AFFORDANCE_RULE_DISCOURAGED = 2
    AFFORDANCE_RULE_NOT_ENCOURAGED = 3
    AFFORDANCE_RULE_NOT_DISCOURAGED = 4
    FACTORY_TUNABLES = {
        'subject':
        TunableEnumEntry(
class InteractionOfInterest(AutoFactoryInit):
    __qualname__ = 'InteractionOfInterest'
    FACTORY_TUNABLES = {'affordance': TunableReference(description='\n                The affordance that we are are timing for length of runtime.\n                ', manager=services.affordance_manager(), class_restrictions='SuperInteraction'), 'tags': TunableSet(description='\n                A set of tags that will match an affordance instead of looking\n                for a specific one.\n                ', tunable=TunableEnumEntry(Tag, Tag.INVALID)), 'duration': TunableRange(description='\n                The amount of time in sim hours that this interaction has to\n                run for this test to be considered passed.\n                ', tunable_type=int, default=10, minimum=1)}

    def get_expected_args(self):
        return {'interaction': event_testing.test_events.FROM_EVENT_DATA}

    def __call__(self, interaction=None):
        if interaction.affordance is self.affordance:
            return TestResult.TRUE
        if self.tags & interaction.get_category_tags():
            return TestResult.TRUE
        return TestResult(False, 'Failed affordance check: {} is not {} and does not have any matching tags in {}.', interaction.affordance, self.affordance, self.tags)

TunableInteractionOfInterest = TunableSingletonFactory.create_auto_factory(InteractionOfInterest)

class SituationGoalInteractionTime(SituationGoal):
    __qualname__ = 'SituationGoalInteractionTime'
    DURATION_RUN = 'duration_run'
    REMOVE_INSTANCE_TUNABLES = ('_post_tests',)
    INSTANCE_TUNABLES = {'_goal_test': TunableInteractionOfInterest(description='\n                Interaction and duration that this situation goal will use.\n                Example: Bartend for 10 sim minutes.\n                ', tuning_group=GroupNames.TESTS)}

    def __init__(self, *args, reader=None, **kwargs):
        super().__init__(reader=reader, *args, **kwargs)
        self._total_time_ran = TimeSpan.ZERO
        self._last_started_time = None
        self._alarm_handle = None
        self._total_duration = interval_in_sim_hours(self._goal_test.duration)
        self._test_events = set()
        self._test_events.add(event_testing.test_events.TestEvent.InteractionStart)
from sims4.tuning.tunable import TunableSingletonFactory, TunableThreshold, TunableEnumEntry, TunableReference
import event_testing.test_base
import services
import sims4.log
logger = sims4.log.Logger('Tests')

class TestBasedScoreThresholdTest(event_testing.test_base.BaseTest):
    __qualname__ = 'TestBasedScoreThresholdTest'
    FACTORY_TUNABLES = {'description': 'Gate availability by a statistic on the actor or target.', 'who': TunableEnumEntry(ParticipantType, ParticipantType.Actor, description='Who or what to apply this test to.'), 'test_based_score': TunableReference(services.test_based_score_manager(), description='The specific cumulative test.'), 'threshold': TunableThreshold(description="The threshold to control availability based on the statistic's value")}

    def __init__(self, who, test_based_score, threshold, **kwargs):
        super().__init__(safe_to_skip=True, **kwargs)
        self.who = who
        self.test_based_score = test_based_score
        self.threshold = threshold

    def get_expected_args(self):
        return {'resolver': RESOLVER_PARTICIPANT}

    def __call__(self, resolver=None):
        score = self.test_based_score.get_score(resolver)
        if not self.threshold.compare(score):
            operator_symbol = Operator.from_function(self.threshold.comparison).symbol
            return TestResult(False, 'Failed {}. Current Score: {}. Operator: {}. Threshold: {}', self.test_based_score.__name__, score, operator_symbol, self.threshold, tooltip=self.tooltip)
        return TestResult.TRUE

    def tuning_is_valid(self):
        return self.test_based_score is not None

TunableTestBasedScoreThresholdTest = TunableSingletonFactory.create_auto_factory(TestBasedScoreThresholdTest)
Example #13
0
                            if not runtime_slot.empty and valid_count >= self.slot_count_required:
                                return TestResult.TRUE
                else:
                    for runtime_slot in target.get_runtime_slots_gen(slot_types={self.child_slot}, bone_name_hash=None):
                        if self.slot_test_type.object_type is not None:
                            for child in runtime_slot.children:
                                if self.slot_test_type.object_type(child):
                                    break
                            else:
                                return TestResult(False, 'None of the children objects were of the specified type. {} children={}', self.slot_test_type.object_type, runtime_slot.children)
                        valid_count += 1
                        if not runtime_slot.empty and valid_count >= self.slot_count_required:
                            return TestResult.TRUE
        return TestResult(False, "SlotTest: participant doesn't meet slot availability requirements", tooltip=self.tooltip)

TunableSlotTest = TunableSingletonFactory.create_auto_factory(SlotTest)

class RelatedSlotsTest(HasTunableSingletonFactory, AutoFactoryInit, event_testing.test_base.BaseTest):
    FACTORY_TUNABLES = {'participant': TunableEnumEntry(description='\n            The subject of this slot test.', tunable_type=ParticipantType, default=ParticipantType.Object), 'slot_tests': TunableList(description='\n            A list of slot tests that must all pass on a single part in order\n            for that part to count.\n            ', tunable=TunableTuple(description='\n                A tuple containing all the information for the slot tests.\n                ', slot=SlotType.TunableReference(description=' \n                    A particular slot type to be tested.\n                    '), requires_child=OptionalTunable(description='\n                    If set to has children then there must be a child in the \n                    slot to pass the test.\n                    \n                    If not checked then the slot must be a empty in order to\n                    pass the test.\n                    ', disabled_name='No_Children', enabled_name='Has_Children', tunable=TunableTuple(description='\n                        A tuple holding all of the different tuning for what\n                        matters about the child of a specified slot. For\n                        instance the test for what kind of object you are \n                        looking for in this specific slot type.\n                        ', object_type=OptionalTunable(description='\n                            A test for what type of object at least one of the\n                            children of this slot must be.\n                            ', tunable=TunableVariant(description='\n                                If set to definition id then at least one of the child\n                                objects must pass the definition test specified.\n                                \n                                If set to object tags then at least one of the child\n                                objects must pass the object tag test specified. \n                                ', definition_id=ObjectTypeFactory.TunableFactory(), object_tags=ObjectTagFactory.TunableFactory())))), count_required=Tunable(description='\n                    Minimum number of slots that must pass the test (to either be\n                    empty or have children) before the requirement is met.\n                    ', tunable_type=int, default=1))), 'parts_required': Tunable(description='\n            The number of parts that must pass all of the slot tests in order\n            for this test to return True.\n            ', tunable_type=int, default=1)}

    def get_expected_args(self):
        return {'test_targets': self.participant}

    def test_part(self, part):
        for entry in self.slot_tests:
            valid_count = 0
            for runtime_slot in part.get_runtime_slots_gen(slot_types={entry.slot}, bone_name_hash=None):
                if (entry.requires_child is None) == runtime_slot.empty:
                    if entry.requires_child is not None and entry.requires_child.object_type is not None:
                        for obj in runtime_slot.children:
                            if entry.requires_child.object_type(obj):
Example #14
0
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._start_and_end_times = set()
        for (day, day_enabled) in self.days_available.items():
            while day_enabled:
                days_as_time_span = date_and_time.create_time_span(days=day)
                start_time = self.start_time + days_as_time_span
                end_time = start_time + date_and_time.create_time_span(
                    hours=self.duration)
                self._start_and_end_times.add((start_time, end_time))

    def get_start_and_end_times(self):
        return self._start_and_end_times


TunableScheduleEntry = TunableSingletonFactory.create_auto_factory(
    ScheduleEntry)


class WeeklySchedule:
    __qualname__ = 'WeeklySchedule'
    FACTORY_TUNABLES = {
        'description':
        '\n        A tunable to specify a weekly schedule.\n        ',
        'schedule_entries': TunableList(
            description=
            '\n            A list of event schedules. Each event is a mapping of days of\n            the week to a start_time and duration.\n            ',
            tunable=TunableScheduleEntry())
    }

    def __init__(self,
                 schedule_entries,
    def __init__(self, who, test_based_score, threshold, **kwargs):
        super().__init__(safe_to_skip=True, **kwargs)
        self.who = who
        self.test_based_score = test_based_score
        self.threshold = threshold

    def get_expected_args(self):
        return {'resolver': RESOLVER_PARTICIPANT}

    def __call__(self, resolver=None):
        score = self.test_based_score.get_score(resolver)
        if not self.threshold.compare(score):
            operator_symbol = Operator.from_function(
                self.threshold.comparison).symbol
            return TestResult(
                False,
                'Failed {}. Current Score: {}. Operator: {}. Threshold: {}',
                self.test_based_score.__name__,
                score,
                operator_symbol,
                self.threshold,
                tooltip=self.tooltip)
        return TestResult.TRUE

    def tuning_is_valid(self):
        return self.test_based_score is not None


TunableTestBasedScoreThresholdTest = TunableSingletonFactory.create_auto_factory(
    TestBasedScoreThresholdTest)
        'situation':
        TunableReference(
            description='\n            The situation to start.\n            ',
            manager=services.get_instance_manager(
                sims4.resources.Types.SITUATION))
    }

    def perform(self, resolver):
        guest_list = self.situation.get_predefined_guest_list()
        if guest_list is None:
            guest_list = SituationGuestList(invite_only=True)
        services.get_zone_situation_manager().create_situation(
            self.situation, guest_list=guest_list, user_facing=False)


StartSituation = TunableSingletonFactory.create_auto_factory(
    _StartSituation, 'StartSituation')


class _ModifyAllItems(AutoFactoryInit):
    FACTORY_TUNABLES = {
        'item_modifications':
        ModifyAllLotItems.TunableFactory(
            description=
            '\n            Modify objects on the active lot.\n            ')
    }

    def perform(self, resolver):
        self.item_modifications().modify_objects()


ModifyAllItems = TunableSingletonFactory.create_auto_factory(
Example #17
0
                 priority=DEFAULT,
                 insert_strategy=QueueInsertStrategy.NEXT,
                 must_run_next=False,
                 **kwargs):
        (target, context) = self._get_target_and_context(
            sim,
            resolver,
            source=source,
            priority=priority,
            insert_strategy=insert_strategy,
            must_run_next=must_run_next)
        return sim.push_super_affordance(self.affordance, target, context,
                                         **kwargs)


TunableReactionSi = TunableSingletonFactory.create_auto_factory(ReactionSi)


class ReactionMixer(AutoFactoryInit):
    FACTORY_TUNABLES = {
        'affordance_target':
        OptionalTunable(
            description=
            '\n            If enabled, the pushed interaction will target a specified\n            participant.\n            ',
            tunable=TunableEnumEntry(
                description=
                '\n                The participant to be targeted by the pushed interaction.\n                ',
                tunable_type=ParticipantTypeReaction,
                default=ParticipantTypeReaction.TargetSim)),
        'super_affordance_override':
        OptionalTunable(
Example #18
0
    def target_matches_object_tags(self, interaction=None):
        if interaction is None or interaction.target is None or interaction.target.is_sim:
            return False
        object_id = interaction.target.definition.id
        target_object_tags = set(build_buy.get_object_all_tags(object_id))
        if self.object_tags.test_type == TagTestType.CONTAINS_ANY_TAG_IN_SET:
            return target_object_tags & self.object_tags.tag_set
        if self.object_tags.test_type == TagTestType.CONTAINS_ALL_TAGS_IN_SET:
            return target_object_tags & self.object_tags.tag_set == self.object_tags.tag_set
        if self.object_tags.test_type == TagTestType.CONTAINS_NO_TAGS_IN_SET:
            return not target_object_tags & self.object_tags.tag_set
        return False


TunableParticipantRanInteractionTest = TunableSingletonFactory.create_auto_factory(
    ParticipantRanInteractionTest)


class ParticipantStartedInteractionTest(event_testing.test_base.BaseTest):
    __qualname__ = 'ParticipantStartedInteractionTest'
    test_events = (event_testing.test_events.TestEvent.InteractionStart, )
    USES_EVENT_DATA = True
    FACTORY_TUNABLES = {
        'description':
        'Check to see if the Sim started an affordance as a particular actor',
        'participant':
        TunableEnumEntry(
            ParticipantType,
            ParticipantType.Actor,
            description=
            'This is the role the sim in question should be to pass.'),
    FACTORY_TUNABLES = {'tags': TunableSet(description='\n                A set of tags that will match an affordance instead of looking\n                for a specific one. If you leave this empty, all Simoleons earned will be counted.\n                ', tunable=TunableEnumEntry(Tag, Tag.INVALID)), 'amount_to_earn': TunableRange(description='\n                The amount of time in Simoleons earned from all relevant activities for this\n                goal to pass.\n                ', tunable_type=int, default=10, minimum=1)}
    expected_kwargs = (('amount', event_testing.test_constants.FROM_EVENT_DATA), ('tags', event_testing.test_constants.FROM_EVENT_DATA))

    def get_expected_args(self):
        return dict(self.expected_kwargs)

    def __call__(self, amount=None, tags=None):
        if amount is None:
            return TestResult(False, 'Amount is None')
        if len(self.tags) == 0 or tags is not None and self.tags & tags:
            if amount > 0:
                return TestResult.TRUE
            return TestResult(False, 'No money earned')
        return TestResult(False, 'Failed relevant tags check: Earnings do not have any matching tags in {}.', self.tags)

TunableEarningsOfInterest = TunableSingletonFactory.create_auto_factory(EarningsOfInterest)

class SituationGoalSimoleonsEarned(SituationGoal):
    SIMOLEONS_EARNED = 'simoleons_earned'
    REMOVE_INSTANCE_TUNABLES = ('_post_tests',)
    INSTANCE_TUNABLES = {'_goal_test': TunableEarningsOfInterest(description='\n                Interaction and Simoleon amount that this situation goal will use.\n                Example: Earn 1000 Simoleons from Bartending activities.\n                ', tuning_group=GroupNames.TESTS)}

    def __init__(self, *args, reader=None, **kwargs):
        super().__init__(*args, reader=reader, **kwargs)
        self._total_simoleons_earned = 0
        self._test_events = set()
        if reader is not None:
            simoleons_earned = reader.read_uint64(self.SIMOLEONS_EARNED, 0)
            self._total_simoleons_earned = simoleons_earned

    def setup(self):
        return len(self.tags) != 0 or len(self.affordances) != 0

    def target_matches_object_tags(self, interaction=None):
        if interaction is None or interaction.target is None or interaction.target.is_sim:
            return False
        object_id = interaction.target.definition.id
        target_object_tags = set(build_buy.get_object_all_tags(object_id))
        if self.object_tags.test_type == TagTestType.CONTAINS_ANY_TAG_IN_SET:
            return target_object_tags & self.object_tags.tag_set
        if self.object_tags.test_type == TagTestType.CONTAINS_ALL_TAGS_IN_SET:
            return target_object_tags & self.object_tags.tag_set == self.object_tags.tag_set
        if self.object_tags.test_type == TagTestType.CONTAINS_NO_TAGS_IN_SET:
            return not target_object_tags & self.object_tags.tag_set
        return False

TunableParticipantRanInteractionTest = TunableSingletonFactory.create_auto_factory(ParticipantRanInteractionTest)

class ParticipantStartedInteractionTest(event_testing.test_base.BaseTest):
    __qualname__ = 'ParticipantStartedInteractionTest'
    test_events = (event_testing.test_events.TestEvent.InteractionStart,)
    USES_EVENT_DATA = True
    FACTORY_TUNABLES = {'description': 'Check to see if the Sim started an affordance as a particular actor', 'participant': TunableEnumEntry(ParticipantType, ParticipantType.Actor, description='This is the role the sim in question should be to pass.'), 'affordances': TunableList(TunableReference(services.affordance_manager()), description="The Sim must have started either any affordance in this list or an interaction matching one of the tags in this tunable's Tags field."), 'tags': TunableSet(TunableEnumEntry(Tag, Tag.INVALID), description='The Sim must have run either an interaction matching one of these Tags or an affordance from the list of Affordances in this tunable.')}

    def __init__(self, participant, affordances, tags, **kwargs):
        super().__init__(**kwargs)
        self.participant_type = participant
        self.affordances = affordances
        self.tags = tags

    def get_test_events_to_register(self):
        return ()
Example #21
0
                    tooltip=self.tooltip)
        return TestResult.TRUE

    def _get_make_true_value(self):
        if self.value is not None:
            for value in algos.binary_walk_gen(self.value.state.values):
                if self.operator(value.value, self.value.value):
                    return (TestResult.TRUE, value)
            operator_symbol = Operator.from_function(self.operator).symbol
        return (TestResult(
            False, 'Could not find value to satisfy operation: {} {} {}',
            self.value.state if self.value is not None else '<Unavailable>',
            operator_symbol, self.value), None)


TunableStateTest = TunableSingletonFactory.create_auto_factory(StateTest)


class WhiteBlackStateTest(HasTunableSingletonFactory, AutoFactoryInit,
                          event_testing.test_base.BaseTest):
    test_events = ()
    FACTORY_TUNABLES = {
        'participant':
        TunableEnumEntry(
            description=
            '\n            Who or what to apply this test to.\n            ',
            tunable_type=ParticipantType,
            default=ParticipantType.Object),
        'states':
        TunableWhiteBlackList(
            description=