Example #1
0
	def _SimulateInternal (self, ticks: int) -> None:
		if ticks <= 0:
			return

		if self.TimeSinceCycleStart is None:
			return

		cycleReproductiveTimeMultiplier = _GetCycleReproductiveTimeMultiplier()  # type: float

		lastTimeSinceCycleStart = self.TimeSinceCycleStart  # type: float
		lastTickSinceCycleStart = ReproductionShared.ReproductiveMinutesToTicks(lastTimeSinceCycleStart, cycleReproductiveTimeMultiplier)  # type: int

		nextTickSinceCycleStart = lastTickSinceCycleStart + ticks  # type: int
		nextTimeSinceCycleStart = ReproductionShared.TicksToReproductiveMinutes(nextTickSinceCycleStart, cycleReproductiveTimeMultiplier)  # type: float

		if self.ShowFertilityNotifications and self.Enabled:
			currentCycleState = self._GetCycle(lastTimeSinceCycleStart)  # type: DotCycle
			currentTicksUntilOvulationStarts = ReproductionShared.GameMinutesToTicks(currentCycleState.GetTimeUntilPhaseStarts(CycleShared.MenstrualCyclePhases.Ovulation))  # type: int

			ticksBeforeOvulationToNotify = ReproductionShared.GameMinutesToTicks(_GetSpermHalfLifeTime())  # type: int

			if ticksBeforeOvulationToNotify < self.MinimumTicksBeforeOvulationToNotify:
				ticksBeforeOvulationToNotify = self.MinimumTicksBeforeOvulationToNotify

			if currentTicksUntilOvulationStarts > 0 and ticksBeforeOvulationToNotify < currentTicksUntilOvulationStarts:
				nextCycleState = self._GetCycle(nextTimeSinceCycleStart)  # type: DotCycle
				nextTicksUntilOvulationStarts = ReproductionShared.GameMinutesToTicks(nextCycleState.GetTimeUntilPhaseStarts(CycleShared.MenstrualCyclePhases.Ovulation))  # type: int

				if ticksBeforeOvulationToNotify > nextTicksUntilOvulationStarts:
					UIDot.ShowFertilityNotification(self.TargetSimInfo)

		self.TimeSinceCycleStart = nextTimeSinceCycleStart
Example #2
0
	def _SimulateInternal (self, simulation: ReproductionShared.Simulation, ticks: int, reproductiveTimeMultiplier: typing.Union[float, int]) -> None:
		ageTicks = ReproductionShared.ReproductiveMinutesToTicks(self.Age, reproductiveTimeMultiplier)  # type: typing.Union[float, int]
		decayTick = ReproductionShared.ReproductiveMinutesToTicks(self.Lifetime, reproductiveTimeMultiplier)  # type: typing.Union[float, int]

		decaying = False  # type: bool
		decayed = False  # type: bool

		if ageTicks < decayTick <= (ageTicks + ticks):
			decaying = True

		if decayTick <= (ageTicks + ticks):
			decayed = True

		if not decayed:
			decayingAmount = self.DecayingTicks(ticks, reproductiveTimeMultiplier)  # type: int
		else:
			decayingAmount = self.SpermCount  # type: int

		self.Age = ReproductionShared.TicksToReproductiveMinutes(ageTicks + ticks, reproductiveTimeMultiplier)
		self.SpermCount -= decayingAmount

		if decaying:
			if self.DecayedCallback is None:
				Debug.Log("Missing callback to be triggered on sperm decay.", This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()))
			else:
				self.DecayedCallback(self)
Example #3
0
	def DecayingTicks (self, ticks: int, reproductiveTimeMultiplier: typing.Union[float, int]) -> int:
		"""
		Get the amount of sperm cells that will decay within this many ticks.
		"""

		if not isinstance(ticks, (int,)):
			raise Exceptions.IncorrectTypeException(ticks, "ticks", (int,))

		if not isinstance(reproductiveTimeMultiplier, (float, int)):
			raise Exceptions.IncorrectTypeException(reproductiveTimeMultiplier, "reproductiveTimeMultiplier", (float, int))

		if ticks < 0:
			raise ValueError("The parameter 'ticks' cannot be less than 0.")

		if reproductiveTimeMultiplier <= 0:
			raise ValueError("The parameter 'reproductiveTimeMultiplier' cannot be less than or equal to 0.")

		if self.SpermCount == 0:
			return 0

		if ticks == 0:
			return 0

		currentAgeTicks = ReproductionShared.ReproductiveMinutesToTicks(self.Age, reproductiveTimeMultiplier)  # type: int
		currentAge = ReproductionShared.TicksToReproductiveMinutes(currentAgeTicks, reproductiveTimeMultiplier)  # type: typing.Union[float, int]  # This is slightly faster than getting using the GetClosestPreciseReproductiveMinute function.
		nextAgeTicks = currentAgeTicks + ticks  # type: typing.Union[float, int]
		nextAge = ReproductionShared.TicksToReproductiveMinutes(nextAgeTicks, reproductiveTimeMultiplier)  # type: typing.Union[float, int]

		lifeTimeTick = ReproductionShared.ReproductiveMinutesToTicks(self.Lifetime, reproductiveTimeMultiplier)

		if nextAgeTicks >= lifeTimeTick:
			return self.SpermCount

		currentPercentageRemaining = 1.0 - self.LifetimeDistribution.CumulativeDistribution(currentAge)  # type: typing.Union[float, int]
		nextPercentageRemaining = 1.0 - self.LifetimeDistribution.CumulativeDistribution(nextAge)  # type: typing.Union[float, int]
		percentageRemainingChange = currentPercentageRemaining - nextPercentageRemaining  # type: typing.Union[float, int]

		originalSpermCount = int(self.SpermCount / currentPercentageRemaining)  # type: int
		decayingSpermCount = int(originalSpermCount * percentageRemainingChange)  # type: int

		if decayingSpermCount < 0:
			Debug.Log("Calculated a decaying sperm count of less than zero (%s)." % decayingSpermCount, This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()))

		return int(originalSpermCount * percentageRemainingChange)
Example #4
0
	def _CycleSimulationPhase (self, simulation: ReproductionShared.Simulation, ticks: int) -> None:
		reproductiveTimeMultiplier = self.ReproductiveTimeMultiplier  # type: typing.Union[float, int]
		simulatingMinutes = ReproductionShared.TicksToReproductiveMinutes(ticks, reproductiveTimeMultiplier)  # type: typing.Union[float, int]

		simulationMemoryKey = self.SimulationMemoryKey
		simulationMemoryExists = simulationMemoryKey in simulation.Memory  # type: bool
		simulationMemory = simulation.Memory.get(simulationMemoryKey, CycleTrackerSimulationMemory())  # type: CycleTrackerSimulationMemory

		if self.TimeSinceLastCycle is not None:
			self.TimeSinceLastCycle += simulatingMinutes

		if self.CurrentCycle is not None:
			cycleTicksRemaining = ReproductionShared.ReproductiveMinutesToTicks(self.CurrentCycle.TimeRemaining, reproductiveTimeMultiplier)  # type: typing.Union[float, int]

			if cycleTicksRemaining < ticks:
				Debug.Log("Simulation stepped over the end of a cycle by %s ticks, this may cause lost time for the tracking sim.\n%s" % (str(ticks - cycleTicksRemaining), self.DebugInformation),
						  This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()), lockReference = self.TrackingSystem)

			self.CurrentCycle.Simulate(simulation, ticks, reproductiveTimeMultiplier)
		else:
			if simulationMemory.CycleStartTesting is None:
				Debug.Log("Expected the 'CycleStartTesting' to be in the simulation memory, but all we found was None.\n" + self.DebugInformation,
						  This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()), lockReference = self.TrackingSystem)

				simulationMemory.CycleStartTesting = self.DoCycleStartTesting()
			elif not simulationMemoryExists:
				simulationMemory.CycleStartTesting = self.DoCycleStartTesting()

			if simulationMemory.CycleStartTesting.GetCanStart():
				timeUntilCycleStart = simulationMemory.CycleStartTesting.GetTimeUntilStart()  # type: typing.Optional[float]
				cycleStartPlanned = timeUntilCycleStart is not None  # type: bool

				if cycleStartPlanned:
					ticksUntilCycleStart = ReproductionShared.ReproductiveMinutesToTicks(timeUntilCycleStart, reproductiveTimeMultiplier)  # type: int
				else:
					ticksUntilCycleStart = 1  # type: int

				if ticksUntilCycleStart <= ticks:
					if cycleStartPlanned and ticksUntilCycleStart < ticks:
						Debug.Log("Simulation stepped over the start of a cycle by %s ticks, this may cause lost time for the tracking sim.\n%s" % (str(ticks - ticksUntilCycleStart), self.DebugInformation),
								  This.Mod.Namespace, Debug.LogLevels.Warning, group = This.Mod.Namespace, owner = __name__, lockIdentifier = __name__ + ":" + str(Python.GetLineNumber()), lockReference = self.TrackingSystem)

					cycleTypeIdentifier = simulationMemory.CycleStartTesting.GetCycleTypeIdentifier()  # type: str

					cycle = self.GenerateCycle(cycleTypeIdentifier)

					self.CycleStartTestingSeed = None
					simulationMemory.CycleStartTesting = None
					self.CurrentCycle = cycle
			else:
				simulationMemory.CycleStartTesting.IncreaseTimeSinceTest(simulatingMinutes)

		if not simulationMemoryExists:
			simulation.Memory[simulationMemoryKey] = simulationMemory
Example #5
0
    def _SimulateInternal(self, simulation: ReproductionShared.Simulation,
                          ticks: int,
                          reproductiveTimeMultiplier: float) -> None:
        simulatingMinutes = ReproductionShared.TicksToReproductiveMinutes(
            ticks, reproductiveTimeMultiplier)  # type: float
        gameMinutes = ReproductionShared.TicksToGameMinutes(
            ticks)  # type: float

        effectGuide = self.BirthControlPillsEffectGuide  # type: CycleGuides.BirthControlPillsEffectGuide

        currentNeed = self.Need  # type: float
        nextNeed = self.Need  # type: float

        if effectGuide.NeedPerGameMinute != 0:
            if effectGuide.NeedPerGameMinute > 0:
                if currentNeed != 1:
                    nextNeed += gameMinutes * effectGuide.NeedPerGameMinute

            else:
                if currentNeed != 0:
                    nextNeed += gameMinutes * effectGuide.NeedPerGameMinute

        nextNeed = min(max(nextNeed, 0), 1)

        currentEntrenchmentRate = effectGuide.EntrenchmentPerReproductiveMinute.Evaluate(
            currentNeed)  # type: float
        nextEntrenchmentRate = effectGuide.EntrenchmentPerReproductiveMinute.Evaluate(
            nextNeed)  # type: float

        averageEntrenchmentRate = (
            currentEntrenchmentRate + nextEntrenchmentRate
        ) / 2  # type: float  # This is probably only right if the curve is linear.

        currentEntrenchment = self.Entrenchment
        nextEntrenchment = self.Entrenchment

        if averageEntrenchmentRate != 0:
            if averageEntrenchmentRate > 0:
                if currentEntrenchment != 1:
                    nextEntrenchment += simulatingMinutes * averageEntrenchmentRate
            else:
                if currentEntrenchment != 0:
                    nextEntrenchment += simulatingMinutes * averageEntrenchmentRate

        nextEntrenchment = min(max(nextEntrenchment, 0), 1)

        gameMinutesSinceLastPill = self.GameMinutesSinceLastPill  # type: float

        self.Need = nextNeed
        self.Entrenchment = nextEntrenchment

        if gameMinutesSinceLastPill is not None:
            self.GameMinutesSinceLastPill = gameMinutesSinceLastPill + gameMinutes
Example #6
0
    def _SimulateInternal(self, simulation: ReproductionShared.Simulation,
                          ticks: int,
                          reproductiveTimeMultiplier: float) -> None:
        simulatingMinutes = ReproductionShared.TicksToReproductiveMinutes(
            ticks, reproductiveTimeMultiplier)  # type: float
        quickMode = Settings.QuickMode.Get()  # type: bool

        if not self.Fertilized:
            decaying = False  # type: bool

            if self.Age < self.TimeRemaining <= (self.Age + simulatingMinutes):
                decaying = True

            if decaying:  #TODO set age first?
                if self.DecayedCallback is None:
                    Debug.Log(
                        "Missing callback to be triggered on ovum decay.",
                        This.Mod.Namespace,
                        Debug.LogLevels.Warning,
                        group=This.Mod.Namespace,
                        owner=__name__,
                        lockIdentifier=__name__ + ":" +
                        str(Python.GetLineNumber()))
                else:
                    self.DecayedCallback(self)
        else:
            if quickMode:
                implanting = True  # type: bool
                self.Age = self.ImplantationTime
            else:
                implanting = False  # type: bool

                if self.Age < self.TimeUntilImplantation <= (
                        self.Age + simulatingMinutes):
                    implanting = True

            if implanting:
                if self.AttemptImplantationCallback is None:
                    Debug.Log(
                        "Missing callback to be triggered on ovum implantation attempt.",
                        This.Mod.Namespace,
                        Debug.LogLevels.Warning,
                        group=This.Mod.Namespace,
                        owner=__name__,
                        lockIdentifier=__name__ + ":" +
                        str(Python.GetLineNumber()))
                else:
                    self.AttemptImplantationCallback(self)

        self.Age += simulatingMinutes
    def _SimulateInternal(self, simulation: ReproductionShared.Simulation,
                          ticks: int,
                          reproductiveTimeMultiplier: float) -> None:
        simulatingMinutes = ReproductionShared.TicksToReproductiveMinutes(
            ticks, reproductiveTimeMultiplier)  # type: float

        effectGuide = self.EmergencyContraceptivePillEffectGuide  # type: CycleGuides.EmergencyContraceptivePillEffectGuide

        currentStrength = self.Strength  # type: float
        nextStrength = self.Strength  # type: float

        if effectGuide.StrengthPerReproductiveMinute != 0:
            if effectGuide.StrengthPerReproductiveMinute > 0:
                if currentStrength != 1:
                    nextStrength += simulatingMinutes * effectGuide.StrengthPerReproductiveMinute

            else:
                if currentStrength != 0:
                    nextStrength += simulatingMinutes * effectGuide.StrengthPerReproductiveMinute

        nextStrength = min(max(nextStrength, 0), 1)

        self.Strength = nextStrength