Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Timed turns #30

Merged
merged 19 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/Duets.Cli/Components/Commands/Clock.Command.fs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
namespace Duets.Cli.Components.Commands

open Duets.Agents
open Duets.Cli.Components
open Duets.Cli.SceneIndex
open Duets.Cli.Text
open Duets.Common
open Duets.Entities
open Duets.Simulation

[<RequireQualifiedAccess>]
module ClockCommand =
Expand All @@ -19,6 +22,9 @@ module ClockCommand =
"Shows the current day moment and the number of day moments until the end of the day"
Handler =
(fun _ ->
let turnInfo =
Queries.Calendar.currentTurnInformation (State.get ())

dayMomentsWithEvents
|> List.indexed
|> List.fold
Expand Down Expand Up @@ -58,4 +64,11 @@ module ClockCommand =
|> Styles.highlight
|> showMessage

let formatDayMoment =
Generic.dayMomentName >> String.lowercase >> Styles.time

$"Spent {turnInfo.TimeSpent} minutes on {turnInfo.CurrentDayMoment |> formatDayMoment}. {turnInfo.TimeLeft} minutes until {turnInfo.NextDayMoment |> formatDayMoment}"
|> Styles.faded
|> showMessage

Scene.World) }
13 changes: 4 additions & 9 deletions src/Duets.Cli/Components/Commands/Help.Command.fs
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,20 @@ open Duets.Entities
module HelpCommand =
/// Creates a command that shows the name and description of all given
/// commands as a list.
let create (commands: (int<dayMoments> * Command) list) =
let create (commands: Command list) =
{ Name = "help"
Description = Command.helpDescription
Handler =
fun _ ->
showMessage Command.helpDescription

let columns =
[ Styles.header "Command"
Styles.header "Description"
Styles.header Emoji.clock ]
[ Styles.header "Command"; Styles.header "Description" ]

let rows =
commands
|> List.map (fun (timeConsumption, command) ->
[ Styles.highlight command.Name
command.Description
if timeConsumption > 0<dayMoments> then
$"{timeConsumption}" ])
|> List.map (fun command ->
[ Styles.highlight command.Name; command.Description ])

showTable columns rows

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module LeaveCommand =
$"Allows you to leave the {Generic.miniGameName miniGameId} game"
Handler =
(fun _ ->
let result = Blackjack.leave (State.get ()) miniGameState
let result = Blackjack.leave miniGameState

match result with
| Ok effect -> effect |> Effect.applyMultiple
Expand Down
4 changes: 2 additions & 2 deletions src/Duets.Cli/Components/Effect.fs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ let private displayEffect effect =
let place = job.Location ||> Queries.World.placeInCityById

Career.careerPromoted job place.Name salary |> showMessage
| CareerShiftPerformed(_, payment) ->
| CareerShiftPerformed(_, _, payment) ->
Career.workShiftFinished payment |> showMessage
| CharacterAttributeChanged(_, attr, Diff(previous, current)) ->
match attr with
Expand Down Expand Up @@ -199,7 +199,7 @@ let private displayEffect effect =
"Choose where you want to go next" |> showMessage

showMapUntilChoice () |> applyMultiple
| PlayResult result ->
| GamePlayed result ->
lineBreak ()

let gameResultMessage simpleResult =
Expand Down
12 changes: 5 additions & 7 deletions src/Duets.Cli/Scenes/World.fs
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,7 @@ let private commandsFromInteractions interactions =
match interactionWithMetadata.State with
| InteractionState.Enabled -> command
| InteractionState.Disabled disabledReason ->
Command.disable disabledReason command
|> Tuple.two interactionWithMetadata.TimeAdvance)
Command.disable disabledReason command)

let private filterAttributesForInfoBar =
List.choose (fun (attr, amount) ->
Expand Down Expand Up @@ -275,11 +274,10 @@ let worldScene mode =
relationshipLevel
| _ -> Command.commonPrompt today currentDayMoment characterAttributes

let commandsWithMetadata =
let commands =
commandsFromInteractions interactionsWithState
@ [ (0<dayMoments>, ExitCommand.get); (0<dayMoments>, MeCommand.get) ]
@ [ ExitCommand.get; MeCommand.get ]

commandsWithMetadata
|> List.map snd
|> (@) [ HelpCommand.create commandsWithMetadata ]
commands
|> (@) [ HelpCommand.create commands ]
|> showCommandPrompt promptText
3 changes: 3 additions & 0 deletions src/Duets.Common/Func.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ module Duets.Common.Func

/// Transforms an F# function into a System.Func.
let toFunc<'a, 'b> f = System.Func<'a, 'b>(f)

/// Wraps a value in a function that ignores its input and returns the value.
let toConst<'a> (value: 'a) _ = value
14 changes: 13 additions & 1 deletion src/Duets.Entities/Calendar.fs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
module rec Duets.Entities.Calendar

open Duets.Common
open FSharp.Data.UnitSystems.SI.UnitNames
open Fugit.Shorthand
open Duets.Common
open System
open System.Globalization

Expand All @@ -27,8 +28,13 @@ let everyDay =
DayOfWeek.Sunday ]

module DayMoments =
/// Contains all the possible day moments in a week.
let oneWeek = Calendar.allDayMoments |> List.length |> (*) 7<dayMoments>

/// Transforms the given number of day moments into minutes.
let toMinutes dayMoments =
dayMoments / 1<dayMoments> * 180<minute>

[<RequireQualifiedAccess>]
module Ops =
/// Adds the given number of days to the date.
Expand Down Expand Up @@ -214,5 +220,11 @@ module Parse =
| "Midnight" -> Midnight
| _ -> EarlyMorning


[<RequireQualifiedAccess>]
module Seconds =
/// Transforms the given number of seconds into minutes.
let toMinutes seconds = (seconds / 60<second>) * 1<minute>

/// Returns the date in which the game starts.
let gameBeginning = Date.Now |> Transform.changeDayMoment EarlyMorning
4 changes: 4 additions & 0 deletions src/Duets.Entities/Lenses.fs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ module State =
let today_ =
(fun (s: State) -> s.Today), (fun v (s: State) -> { s with Today = v })

let turnMinutes_ =
(fun (s: State) -> s.TurnMinutes),
(fun v (s: State) -> { s with TurnMinutes = v })

let worldItems_ =
(fun (s: State) -> s.WorldItems),
(fun v (s: State) -> { s with WorldItems = v })
Expand Down
1 change: 1 addition & 0 deletions src/Duets.Entities/State.fs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ let empty =
SocialNetworkCurrentAccountStatus.NoAccountCreated
Accounts = Map.empty } }
Today = Calendar.gameBeginning
TurnMinutes = 0<minute>
WorldItems = Map.empty }
19 changes: 17 additions & 2 deletions src/Duets.Entities/Types/Effect.Types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,20 @@ module EffectTypes =
| AlbumReleased of Band * ReleasedAlbum
| AlbumReleasedUpdate of Band * ReleasedAlbum
| AlbumReviewsReceived of Band * ReleasedAlbum
| AlbumSongAdded of Band * UnreleasedAlbum * Recorded<Song>
| AlbumUpdated of Band * UnreleasedAlbum
| Ate of item: Item * food: EdibleItem
| BalanceUpdated of BankAccountHolder * Diff<Amount>
| BandFansChanged of Band * Diff<Fans>
| BandSwitchedGenre of Band * Diff<Genre>
| BookRead of Item * Book
| CareerAccept of CharacterId * Job
| CareerLeave of CharacterId * Job
| CareerPromoted of Job * salary: Amount
| CareerShiftPerformed of Job * payment: Amount
| CareerShiftPerformed of
Job *
shiftDuration: int<dayMoments> *
payment: Amount
| CharacterAttributeChanged of
character: CharacterId *
attribute: CharacterAttribute *
Expand All @@ -32,9 +38,14 @@ module EffectTypes =
| ConcertFinished of band: Band * concert: PastConcert * income: Amount
| ConcertUpdated of Band * ScheduledConcert
| ConcertCancelled of Band * PastConcert
| ConcertSoundcheckPerformed
| Drank of item: Item * drink: DrinkableItem
| Exercised of Item
| FlightBooked of Flight
| FlightUpdated of Flight
| FlightLanded of Flight
| GameCreated of State
| GamePlayed of PlayResult
| GenreMarketsUpdated of GenreMarketByGenre
| ItemAddedToCharacterInventory of Item
| ItemChangedInCharacterInventory of Diff<Item>
Expand All @@ -45,8 +56,10 @@ module EffectTypes =
| ItemRemovedFromWorld of RoomCoordinates * Item
| MerchPriceSet of band: Band * merchItem: Item * price: Amount
| MerchSold of band: Band * (Item * int<quantity>) list * income: Amount
| MerchStandSetup
| MemberHired of Band * Character * CurrentMember * SkillWithLevel list
| MemberFired of Band * CurrentMember * PastMember
| MiniGamePlayed of MiniGameId
| MoneyEarned of BankAccountHolder * BankTransaction
| MoneyTransferred of BankAccountHolder * BankTransaction
| NotificationScheduled of Date * DayMoment * Notification
Expand All @@ -61,6 +74,7 @@ module EffectTypes =
| RentalUpdated of Rental
| SituationChanged of Situation
| SkillImproved of Character * Diff<SkillWithLevel>
| SocialActionPerformed of SocializingState * SocialActionKind
| SocialNetworkAccountCreated of SocialNetworkKey * SocialNetworkAccount
| SocialNetworkAccountFollowersChanged of
SocialNetworkKey *
Expand All @@ -80,8 +94,9 @@ module EffectTypes =
| SongDiscarded of Band * Unfinished<Song>
| SongPracticed of Band * Finished<Song>
| PlaceClosed of Place
| PlayResult of PlayResult
| TimeAdvanced of Date
| TurnTimeUpdated of int<minute>
| WatchedTv of Item
/// Moves the player to a new room inside the current place.
| WorldEnterRoom of Diff<RoomCoordinates>
/// Moves the player to a different place in the current city or a
Expand Down
3 changes: 1 addition & 2 deletions src/Duets.Entities/Types/Interaction.Types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,7 @@ module InteractionTypes =
/// of time that it'll take to perform it.
type InteractionWithMetadata =
{ Interaction: Interaction
State: InteractionState
TimeAdvance: int<dayMoments> }
State: InteractionState }

/// Defines a simple win/lose result for a non-interactive game.
[<RequireQualifiedAccess>]
Expand Down
2 changes: 2 additions & 0 deletions src/Duets.Entities/Types/State.Types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,7 @@ module StateTypes =
Rentals: CharacterRentals
Situation: Situation
SocialNetworks: SocialNetworks
// TODO: Merge today and turn minutes into one property.
Today: Date
TurnMinutes: int<minute>
WorldItems: WorldItems }
5 changes: 1 addition & 4 deletions src/Duets.Simulation/Careers/Work.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ open Duets.Entities
open Duets.Simulation
open Duets.Simulation.Bank.Operations
open Duets.Simulation.Character
open Duets.Simulation.Time

let private workAttributeChange state (job: Job) =
let character = Queries.Characters.playableCharacter state
Expand Down Expand Up @@ -44,7 +43,6 @@ let workShift state job =
let characterAccount = Queries.Bank.playableCharacterAccount state

let shiftDayMoments = timeAdvancement state job
let timeEffects = AdvanceTime.advanceDayMoment' state shiftDayMoments

let shiftSalary =
job.CurrentStage.BaseSalaryPerDayMoment * decimal shiftDayMoments
Expand All @@ -53,7 +51,6 @@ let workShift state job =

let attributeEffects = workAttributeChange state job

[ yield CareerShiftPerformed(job, shiftSalary)
yield! timeEffects
[ yield CareerShiftPerformed(job, shiftDayMoments, shiftSalary)
yield shiftPay
yield! attributeEffects ]
8 changes: 6 additions & 2 deletions src/Duets.Simulation/Concerts/Live/Live.Actions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ let soundcheck state checklist =
Config.MusicSimulation.Merch.soundcheckTime
|> advanceDayMoment' state

[ Situations.preparingConcert' updatedChecklist; yield! timeEffects ]
[ ConcertSoundcheckPerformed
Situations.preparingConcert' updatedChecklist
yield! timeEffects ]


/// Sets up the merch stand, which improves the ticket sales of the concert.
Expand All @@ -35,7 +37,9 @@ let setupMerchStand state checklist =
Config.MusicSimulation.Merch.standSetupTime
|> advanceDayMoment' state

[ Situations.preparingConcert' updatedChecklist; yield! timeEffects ]
[ MerchStandSetup
Situations.preparingConcert' updatedChecklist
yield! timeEffects ]

/// Starts the given concert if the band is ready to play.
let startConcert state concert =
Expand Down
5 changes: 5 additions & 0 deletions src/Duets.Simulation/Config.fs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,11 @@ module Revenue =
/// Indicates how many dd a band makes per stream.
let revenuePerStream = 0.0055

module Time =
/// Number of minutes that a day moment has, which is effectively the
/// number of minutes we allow the player to perform per turn.
let minutesPerDayMoment = 180<minute>

module Travel =
/// Price per kilometers for buying plane tickets.
let pricePerKm = 0.067m
Loading
Loading