diff --git a/src/RealTime/CustomAI/IRealTimeBuildingAI.cs b/src/RealTime/CustomAI/IRealTimeBuildingAI.cs new file mode 100644 index 0000000000000000000000000000000000000000..335a7f43a55e4e6d32f02ab9119b236dfb19600b --- /dev/null +++ b/src/RealTime/CustomAI/IRealTimeBuildingAI.cs @@ -0,0 +1,25 @@ +// +// Copyright (c) dymanoid. All rights reserved. +// + +namespace RealTime.CustomAI +{ + /// + /// An interface for the custom logic for the private buildings. + /// + internal interface IRealTimeBuildingAI + { + /// + /// Determines whether the building with the specified is noise restricted + /// (has NIMBY policy that is active on current time). + /// + /// The building ID to check. + /// The ID of a building where the citizen starts their journey. + /// Specify 0 if there is no journey in schedule. + /// + /// true if the building with the specified has NIMBY policy + /// that is active on current time; otherwise, false. + /// + bool IsNoiseRestricted(ushort buildingId, ushort currentBuildingId = 0); + } +} \ No newline at end of file diff --git a/src/RealTime/CustomAI/ISpareTimeBehavior.cs b/src/RealTime/CustomAI/ISpareTimeBehavior.cs new file mode 100644 index 0000000000000000000000000000000000000000..eea4872cc4acd0bd05dd26a447d9b17d9430d1a5 --- /dev/null +++ b/src/RealTime/CustomAI/ISpareTimeBehavior.cs @@ -0,0 +1,33 @@ +// +// Copyright (c) dymanoid. All rights reserved. +// + +namespace RealTime.CustomAI +{ + /// + /// An interface for custom logic for the spare time simulation. + /// + internal interface ISpareTimeBehavior + { + /// + /// Gets the probability whether a citizen with specified age would go relaxing on current time. + /// + /// + /// The age of the citizen to check. + /// The citizen's assigned work shift (default is ). + /// + /// A percentage value in range of 0..100 that describes the probability whether + /// a citizen with specified age would go relaxing on current time. + uint GetRelaxingChance(Citizen.AgeGroup citizenAge, WorkShift workShift = WorkShift.Unemployed); + + /// + /// Gets the probability whether a citizen with specified age would go shopping on current time. + /// + /// + /// The age of the citizen to check. + /// + /// A percentage value in range of 0..100 that describes the probability whether + /// a citizen with specified age would go shopping on current time. + uint GetShoppingChance(Citizen.AgeGroup citizenAge); + } +} \ No newline at end of file diff --git a/src/RealTime/CustomAI/ITravelBehavior.cs b/src/RealTime/CustomAI/ITravelBehavior.cs new file mode 100644 index 0000000000000000000000000000000000000000..74f64e8c2350b79112bf85c63ae905a37315dd32 --- /dev/null +++ b/src/RealTime/CustomAI/ITravelBehavior.cs @@ -0,0 +1,18 @@ +// +// Copyright (c) dymanoid. All rights reserved. +// + +namespace RealTime.CustomAI +{ + /// + /// An interface for citizens traveling behavior. + /// + internal interface ITravelBehavior + { + /// Gets an estimated travel time (in hours) between two specified buildings. + /// The ID of the first building. + /// The ID of the second building. + /// An estimated travel time in hours. + float GetEstimatedTravelTime(ushort building1, ushort building2); + } +} \ No newline at end of file diff --git a/src/RealTime/CustomAI/IWorkBehavior.cs b/src/RealTime/CustomAI/IWorkBehavior.cs new file mode 100644 index 0000000000000000000000000000000000000000..6150e5a4cf31b87004fd5d1275a4b88c0a1c8b8d --- /dev/null +++ b/src/RealTime/CustomAI/IWorkBehavior.cs @@ -0,0 +1,54 @@ +// +// Copyright (c) dymanoid. All rights reserved. +// + +namespace RealTime.CustomAI +{ + /// + /// An interface for the citizens work behavior. + /// + internal interface IWorkBehavior + { + /// Notifies this object that a new game day starts. + void BeginNewDay(); + + /// + /// Determines whether a building of specified and + /// currently has working hours. Note that this method always returns true for residential buildings. + /// + /// The building service. + /// The building sub-service. + /// + /// true if a building of specified and + /// currently has working hours; otherwise, false. + /// + bool IsBuildingWorking(ItemClass.Service service, ItemClass.SubService subService); + + /// Updates the citizen's work schedule by determining the time for going to work. + /// The citizen's schedule to update. + /// The ID of the building where the citizen is currently located. + /// The duration (in hours) of a full citizens simulation cycle. + /// true if work was scheduled; otherwise, false. + bool ScheduleGoToWork(ref CitizenSchedule schedule, ushort currentBuilding, float simulationCycle); + + /// Updates the citizen's work schedule by determining the lunch time. + /// The citizen's schedule to update. + /// The citizen's age. + /// true if a lunch time was scheduled; otherwise, false. + bool ScheduleLunch(ref CitizenSchedule schedule, Citizen.AgeGroup citizenAge); + + /// Updates the citizen's work schedule by determining the returning from lunch time. + /// The citizen's schedule to update. + void ScheduleReturnFromLunch(ref CitizenSchedule schedule); + + /// Updates the citizen's work schedule by determining the time for returning from work. + /// The citizen's schedule to update. + /// The age of the citizen. + void ScheduleReturnFromWork(ref CitizenSchedule schedule, Citizen.AgeGroup citizenAge); + + /// Updates the citizen's work shift parameters in the specified citizen's . + /// The citizen's schedule to update the work shift in. + /// The age of the citizen. + void UpdateWorkShift(ref CitizenSchedule schedule, Citizen.AgeGroup citizenAge); + } +} \ No newline at end of file diff --git a/src/RealTime/CustomAI/RealTimeBuildingAI.cs b/src/RealTime/CustomAI/RealTimeBuildingAI.cs index 295127ccf21c7e950671aa2e8572b06e0b9300e8..490f3fbacbaf2435cdfe7f4f787aef43d11c1592 100644 --- a/src/RealTime/CustomAI/RealTimeBuildingAI.cs +++ b/src/RealTime/CustomAI/RealTimeBuildingAI.cs @@ -13,7 +13,7 @@ namespace RealTime.CustomAI /// /// A class that incorporates the custom logic for the private buildings. /// - internal sealed class RealTimeBuildingAI + internal sealed class RealTimeBuildingAI : IRealTimeBuildingAI { private const int ConstructionSpeedPaused = 10880; private const int ConstructionSpeedMinimum = 1088; @@ -27,8 +27,8 @@ namespace RealTime.CustomAI private readonly ITimeInfo timeInfo; private readonly IBuildingManagerConnection buildingManager; private readonly IToolManagerConnection toolManager; - private readonly WorkBehavior workBehavior; - private readonly TravelBehavior travelBehavior; + private readonly IWorkBehavior workBehavior; + private readonly ITravelBehavior travelBehavior; private readonly bool[] lightStates; @@ -58,8 +58,8 @@ namespace RealTime.CustomAI ITimeInfo timeInfo, IBuildingManagerConnection buildingManager, IToolManagerConnection toolManager, - WorkBehavior workBehavior, - TravelBehavior travelBehavior) + IWorkBehavior workBehavior, + ITravelBehavior travelBehavior) { this.config = config ?? throw new ArgumentNullException(nameof(config)); this.timeInfo = timeInfo ?? throw new ArgumentNullException(nameof(timeInfo)); diff --git a/src/RealTime/CustomAI/RealTimeHumanAIBase.cs b/src/RealTime/CustomAI/RealTimeHumanAIBase.cs index d7e4d872f5f50d79cf12c5133f1f9ede2d0b04ae..563e8eaccec473e2cb31425eb2aa7a1e5b22c3c6 100644 --- a/src/RealTime/CustomAI/RealTimeHumanAIBase.cs +++ b/src/RealTime/CustomAI/RealTimeHumanAIBase.cs @@ -28,8 +28,8 @@ namespace RealTime.CustomAI /// /// A configuration to use with this custom logic. /// An object providing the proxies that connect the method calls to the game methods. - /// A reference an instance. - protected RealTimeHumanAIBase(RealTimeConfig config, GameConnections connections, RealTimeEventManager eventManager) + /// A reference to an instance. + protected RealTimeHumanAIBase(RealTimeConfig config, GameConnections connections, IRealTimeEventManager eventManager) { Config = config ?? throw new ArgumentNullException(nameof(config)); EventMgr = eventManager ?? throw new ArgumentNullException(nameof(eventManager)); @@ -68,7 +68,7 @@ namespace RealTime.CustomAI /// /// Gets a reference to the event manager. /// - protected RealTimeEventManager EventMgr { get; } + protected IRealTimeEventManager EventMgr { get; } /// /// Gets a reference to the proxy class that provides access to citizen's methods and fields. diff --git a/src/RealTime/CustomAI/RealTimeResidentAI.cs b/src/RealTime/CustomAI/RealTimeResidentAI.cs index 3f0ff0395b9c7ec8ab70895d85e6217ebf6cbb5a..f83167e8db760d06cdaa12c3af127ee42ab0f469 100644 --- a/src/RealTime/CustomAI/RealTimeResidentAI.cs +++ b/src/RealTime/CustomAI/RealTimeResidentAI.cs @@ -18,11 +18,13 @@ namespace RealTime.CustomAI where TCitizen : struct { private readonly ResidentAIConnection residentAI; - private readonly RealTimeBuildingAI buildingAI; - private readonly WorkBehavior workBehavior; - private readonly SpareTimeBehavior spareTimeBehavior; - private readonly TravelBehavior travelBehavior; + private readonly IRealTimeBuildingAI buildingAI; + private readonly IWorkBehavior workBehavior; + private readonly ISpareTimeBehavior spareTimeBehavior; + private readonly ITravelBehavior travelBehavior; + private readonly CitizenSchedule[] residentSchedules; + private float simulationCycle; /// Initializes a new instance of the class. @@ -30,7 +32,7 @@ namespace RealTime.CustomAI /// A instance containing the mod's configuration. /// A instance that provides the game connection implementation. /// A connection to the game's resident AI. - /// A instance. + /// An instance. /// The custom building AI. /// A behavior that provides simulation info for the citizens work time. /// A behavior that provides simulation info for the citizens spare time. @@ -39,11 +41,11 @@ namespace RealTime.CustomAI RealTimeConfig config, GameConnections connections, ResidentAIConnection residentAI, - RealTimeEventManager eventManager, - RealTimeBuildingAI buildingAI, - WorkBehavior workBehavior, - SpareTimeBehavior spareTimeBehavior, - TravelBehavior travelBehavior) + IRealTimeEventManager eventManager, + IRealTimeBuildingAI buildingAI, + IWorkBehavior workBehavior, + ISpareTimeBehavior spareTimeBehavior, + ITravelBehavior travelBehavior) : base(config, connections, eventManager) { this.residentAI = residentAI ?? throw new ArgumentNullException(nameof(residentAI)); @@ -135,7 +137,7 @@ namespace RealTime.CustomAI /// Performs simulation for starting a new day for all citizens. public void BeginNewDay() { - workBehavior.UpdateLunchTime(); + workBehavior.BeginNewDay(); todayWakeup = TimeInfo.Now.Date.AddHours(Config.WakeUpHour); } diff --git a/src/RealTime/CustomAI/RealTimeTouristAI.cs b/src/RealTime/CustomAI/RealTimeTouristAI.cs index a6e55af18ecb8fe9293925fceb315259201ec25c..fe3bfbc1c7978990cdaeabc4ac15e152ba6b2ac1 100644 --- a/src/RealTime/CustomAI/RealTimeTouristAI.cs +++ b/src/RealTime/CustomAI/RealTimeTouristAI.cs @@ -22,7 +22,7 @@ namespace RealTime.CustomAI where TCitizen : struct { private readonly TouristAIConnection touristAI; - private readonly SpareTimeBehavior spareTimeBehavior; + private readonly ISpareTimeBehavior spareTimeBehavior; /// /// Initializes a new instance of the class. @@ -39,8 +39,8 @@ namespace RealTime.CustomAI RealTimeConfig config, GameConnections connections, TouristAIConnection touristAI, - RealTimeEventManager eventManager, - SpareTimeBehavior spareTimeBehavior) + IRealTimeEventManager eventManager, + ISpareTimeBehavior spareTimeBehavior) : base(config, connections, eventManager) { this.touristAI = touristAI ?? throw new ArgumentNullException(nameof(touristAI)); diff --git a/src/RealTime/CustomAI/SpareTimeBehavior.cs b/src/RealTime/CustomAI/SpareTimeBehavior.cs index 5367f12629ea3856d32f351fcc7db1412d917e12..af9b3eb9dd4dc3bc2b902262b6f835eb39bbcea3 100644 --- a/src/RealTime/CustomAI/SpareTimeBehavior.cs +++ b/src/RealTime/CustomAI/SpareTimeBehavior.cs @@ -13,7 +13,7 @@ namespace RealTime.CustomAI /// /// A class that provides custom logic for the spare time simulation. /// - internal sealed class SpareTimeBehavior + internal sealed class SpareTimeBehavior : ISpareTimeBehavior { private readonly RealTimeConfig config; private readonly ITimeInfo timeInfo; diff --git a/src/RealTime/CustomAI/TravelBehavior.cs b/src/RealTime/CustomAI/TravelBehavior.cs index 4ca776ced564b0cb9221bde5847628262650069e..779f6e247055a1561969dde9a71556a5f13c074a 100644 --- a/src/RealTime/CustomAI/TravelBehavior.cs +++ b/src/RealTime/CustomAI/TravelBehavior.cs @@ -8,7 +8,10 @@ namespace RealTime.CustomAI using RealTime.Tools; using static Constants; - internal sealed class TravelBehavior + /// + /// A behavior for citizens traveling. + /// + internal sealed class TravelBehavior : ITravelBehavior { private readonly IBuildingManagerConnection buildingManager; diff --git a/src/RealTime/CustomAI/WorkBehavior.cs b/src/RealTime/CustomAI/WorkBehavior.cs index 5779607bfb0b0aea3c65f7bbf15a660fd1f5f12a..ee28e3b18523b752ef2128b6d8805f393608c647 100644 --- a/src/RealTime/CustomAI/WorkBehavior.cs +++ b/src/RealTime/CustomAI/WorkBehavior.cs @@ -14,13 +14,13 @@ namespace RealTime.CustomAI /// /// A class containing methods for managing the citizens' work behavior. /// - internal sealed class WorkBehavior + internal sealed class WorkBehavior : IWorkBehavior { private readonly RealTimeConfig config; private readonly IRandomizer randomizer; private readonly IBuildingManagerConnection buildingManager; private readonly ITimeInfo timeInfo; - private readonly TravelBehavior travelBehavior; + private readonly ITravelBehavior travelBehavior; private DateTime lunchBegin; private DateTime lunchEnd; @@ -37,7 +37,7 @@ namespace RealTime.CustomAI IRandomizer randomizer, IBuildingManagerConnection buildingManager, ITimeInfo timeInfo, - TravelBehavior travelBehavior) + ITravelBehavior travelBehavior) { this.config = config ?? throw new ArgumentNullException(nameof(config)); this.randomizer = randomizer ?? throw new ArgumentNullException(nameof(randomizer)); @@ -90,8 +90,8 @@ namespace RealTime.CustomAI HasExtendedFirstWorkShift(service, subService)); } - /// Updates the lunch time according to current date and configuration. - public void UpdateLunchTime() + /// Notifies this object that a new game day starts. + public void BeginNewDay() { DateTime today = timeInfo.Now.Date; lunchBegin = today.AddHours(config.LunchBegin); diff --git a/src/RealTime/Events/IRealTimeEventManager.cs b/src/RealTime/Events/IRealTimeEventManager.cs new file mode 100644 index 0000000000000000000000000000000000000000..21506a8c61ee90ed8ade1670f4e17896950d915b --- /dev/null +++ b/src/RealTime/Events/IRealTimeEventManager.cs @@ -0,0 +1,36 @@ +// +// Copyright (c) dymanoid. All rights reserved. +// + +namespace RealTime.Events +{ + using System; + + /// An interface for the customized city events manager. + internal interface IRealTimeEventManager + { + /// + /// Gets the instance of an ongoing or upcoming city event that takes place in a building + /// with specified ID. + /// + /// The ID of a building to search events for. + /// An instance of the first matching city event, or null if none found. + ICityEvent GetCityEvent(ushort buildingId); + + /// + /// Gets the instance of an upcoming city event whose start time is between the specified values. + /// + /// The earliest city event start time to consider. + /// The latest city event start time to consider. + /// An instance of the first matching city event, or null if none found. + ICityEvent GetUpcomingCityEvent(DateTime earliestStartTime, DateTime latestStartTime); + + /// Gets the state of a city event in the specified building. + /// The building ID to check events in. + /// The latest start time of events to consider. + /// + /// The state of an event that meets the specified criteria, or if none found. + /// + CityEventState GetEventState(ushort buildingId, DateTime latestStart); + } +} \ No newline at end of file diff --git a/src/RealTime/Events/RealTimeEventManager.cs b/src/RealTime/Events/RealTimeEventManager.cs index 525c8286a44da9995dfd378433f6ab5563b8e3ff..ea8008518b92bbe96b0443e4ffe92838773a9b6e 100644 --- a/src/RealTime/Events/RealTimeEventManager.cs +++ b/src/RealTime/Events/RealTimeEventManager.cs @@ -16,7 +16,7 @@ namespace RealTime.Events /// The central class for the custom city events logic. /// - internal sealed class RealTimeEventManager : IStorageData + internal sealed class RealTimeEventManager : IStorageData, IRealTimeEventManager { private const int MaximumEventsCount = 5; private const string StorageDataId = "RealTimeEvents"; diff --git a/src/RealTime/RealTime.csproj b/src/RealTime/RealTime.csproj index 27346c64f9ff082e9b844f0d608a6246ea9dfaf4..cb96a925bcf54b26fe2e23792ebedc3a0e43940d 100644 --- a/src/RealTime/RealTime.csproj +++ b/src/RealTime/RealTime.csproj @@ -60,6 +60,10 @@ + + + + @@ -77,6 +81,7 @@ +