Skip to content

Commit

Permalink
✨ Add computers to the game
Browse files Browse the repository at this point in the history
  • Loading branch information
sleepyfran committed Jul 14, 2024
1 parent 69c9c03 commit 670aea3
Show file tree
Hide file tree
Showing 32 changed files with 317 additions and 3 deletions.
38 changes: 38 additions & 0 deletions src/Duets.Cli/Components/Commands/Computer/OpenApp.Command.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace Duets.Cli.Components.Commands

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

[<RequireQualifiedAccess>]
module OpenAppCommand =
let private appName =
function
| WordProcessor -> "Word"

/// Command to open an app on the currently used computer.
let create item computer apps =
{ Name = "open app"
Description = "Shows a picker to open an app on the computer"
Handler =
fun _ ->
let selectedApp =
showOptionalChoicePrompt
"Select an app"
Generic.cancel
appName
apps

match selectedApp with
| Some app ->
$"Opening {app |> appName}..." |> showMessage

wait 500<millisecond>

Computer.openApp item computer app |> Effect.applyMultiple
| None -> ()

Scene.World }
13 changes: 13 additions & 0 deletions src/Duets.Cli/Components/Commands/Items/Interactive.Command.fs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,19 @@ module InteractiveCommand =
Items.itemNotReadable |> showMessage
Scene.World)

let ``use`` =
Command.itemInteraction
(Command.VerbOnly "use")
Command.useDescription
ItemInteraction.Use
(function
| Ok effects ->
effects |> Duets.Cli.Effect.applyMultiple
Scene.World
| Error _ ->
Items.itemNotUsable |> showMessage
Scene.World)

let watch =
Command.itemInteraction
(Command.VerbOnly "watch")
Expand Down
21 changes: 21 additions & 0 deletions src/Duets.Cli/Components/Effect.fs
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,27 @@ let private displayEffect effect =
$"""It's time to prepare for the concert! If you have any merchandise, you can set up a stand to sell it by the {"bar" |> Styles.place}. Otherwise, head to the {"stage" |> Styles.place} to do a soundcheck"""
|> Styles.information
|> showMessage
| SituationChanged(Focused(UsingComputer(_, computer))) when
computer.ComputerState = Booting
->
clearScreen ()

"DuOS" |> showFiglet
"Booting up version 1.21..." |> Styles.faded |> showMessage
wait 1000<millisecond>

let createBootMessage message =
$"""[[ {"OK" |> Styles.success} ]] {message}"""

[ createBootMessage "Started network manager"
createBootMessage "Started display manager"
createBootMessage "Started system services"
createBootMessage "Started shell" ]
|> List.iter (fun message ->
message |> showMessage
wait 550<millisecond>)

"Finished booting, took 4.2 seconds" |> Styles.success |> showMessage
| SongImproved(_, Diff(before, after)) ->
let (Unfinished(_, _, previousQuality)) = before
let (Unfinished(_, _, currentQuality)) = after
Expand Down
2 changes: 2 additions & 0 deletions src/Duets.Cli/Duets.Cli.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
<Compile Include="Text\World\RehearsalSpace.fs"/>
<Compile Include="Text\World\Studio.fs"/>
<Compile Include="Text\World\World.fs"/>
<Compile Include="Text\Focused.fs" />
<Compile Include="Components\VisualEffects.fs"/>
<Compile Include="Components\Separator.fs"/>
<Compile Include="Components\Layout.fs"/>
Expand Down Expand Up @@ -96,6 +97,7 @@
<Compile Include="Components\Commands\RehearsalRoom\ListSongs.Command.fs"/>
<Compile Include="Components\Commands\RehearsalRoom\SwitchGenre.Command.fs"/>
<Compile Include="Components\Commands\Career\Work.Command.fs"/>
<Compile Include="Components\Commands\Computer\OpenApp.Command.fs" />
<Compile Include="Components\Commands\Concert\ConcertCommon.fs"/>
<Compile Include="Components\Commands\Concert\StartConcert.Command.fs"/>
<Compile Include="Components\Commands\Concert\DoEncore.Command.fs"/>
Expand Down
11 changes: 11 additions & 0 deletions src/Duets.Cli/Scenes/World.fs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ let private commandsFromInteractions interactions =
| ItemInteraction.Play -> [ InteractiveCommand.play ]
| ItemInteraction.Read -> [ InteractiveCommand.read ]
| ItemInteraction.Sleep -> [ SleepCommand.get ]
| ItemInteraction.Use -> [ InteractiveCommand.``use`` ]
| ItemInteraction.Watch -> [ InteractiveCommand.watch ]
| Interaction.FreeRoam freeRoamInteraction ->
match freeRoamInteraction with
Expand Down Expand Up @@ -164,6 +165,10 @@ let private commandsFromInteractions interactions =
| ShopInteraction.Buy shop -> [ BuyCommand.create shop ]
| ShopInteraction.Order shop -> [ OrderCommand.create shop ]
| ShopInteraction.SeeMenu shop -> [ SeeMenuCommand.create shop ]
| Interaction.Situational computerInteraction ->
match computerInteraction with
| ComputerInteraction.OpenApp(item, computer, apps) ->
[ OpenAppCommand.create item computer apps ]
| Interaction.Social socialInteraction ->
match socialInteraction with
| SocialInteraction.StartConversation(knownNpcs, unknownNpcs) ->
Expand Down Expand Up @@ -259,6 +264,12 @@ let worldScene mode =
currentDayMoment
characterAttributes
ongoingConcert.Points
| Focused focus ->
Focused.actionPrompt
today
currentDayMoment
characterAttributes
focus
| PlayingMiniGame miniGameState ->
MiniGame.actionPrompt today currentDayMoment miniGameState
| Socializing socializingState ->
Expand Down
3 changes: 3 additions & 0 deletions src/Duets.Cli/Text/Command.fs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ let eatDescription =
let readDescription =
$"""Allows you to read a book. Use as {Styles.information "read {book name}"}"""

let useDescription =
$"""Allows you to use an item. Use as {Styles.information "use {item name}"}"""

let putUsage = $"""{Styles.information "put {item name} in {storage name}"}"""

let putDescription =
Expand Down
6 changes: 6 additions & 0 deletions src/Duets.Cli/Text/Emoji.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ let flying = ":airplane_departure:"
/// the space in the end since the emoji does not seem to render well without it.
let concert = ":admission_tickets: "

/// Emoji for representing actions related to computers.
let computer = ":desktop_computer:"

/// Emoji for representing actions related to writing.
let writing = ":pencil:"

/// Emoji for representing actions related to socializing.
let socializing = ":mouth:"

Expand Down
26 changes: 26 additions & 0 deletions src/Duets.Cli/Text/Focused.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module rec Duets.Cli.Text.Focused

open Duets.Entities
open Duets.Entities.SituationTypes

let actionPrompt date dayMoment attributes activity =
$"""{Generic.infoBar date dayMoment attributes}
{activityEmoji activity} {activityName activity}"""
|> Styles.prompt

let activityName activity =
match activity with
| FocusSituation.UsingComputer(item, computer) ->
match computer.ComputerState with
| Booting -> "" (* Won't be shown, it'll be switched right after. *)
| AppSwitcher -> $"Using {item.Name}"
| AppRunning(WordProcessor) -> "Using Word"
|> Styles.faded

let activityEmoji activity =
match activity with
| FocusSituation.UsingComputer(_, computer) ->
match computer.ComputerState with
| Booting -> ""
| AppSwitcher -> $"{Emoji.computer} "
| AppRunning(WordProcessor) -> Emoji.writing
1 change: 1 addition & 0 deletions src/Duets.Cli/Text/Generic.fs
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ let itemDetailedName (item: Item) =
| Key(Chip(cityId, placeId)) ->
let place = Queries.World.placeInCityById cityId placeId
$"Chip for {place.Name} in {cityName cityId}"
| Usable(Computer _) -> $"{item.Brand} {item.Name}" |> Styles.item
| _ -> itemName item

let moreDates = Styles.faded "More dates"
Expand Down
2 changes: 2 additions & 0 deletions src/Duets.Cli/Text/Items.fs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ let itemNotEdible = Styles.error "You can't eat that!"

let itemNotReadable = Styles.error "How are you planning to read that?"

let itemNotUsable = Styles.error "You can't use that!"

let itemCannotBeExercisedWith =
Styles.error "You can't exercise with that! Try a treadmill"

Expand Down
5 changes: 5 additions & 0 deletions src/Duets.Data/Items/Book.Items.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,29 @@ let private specialBooks =
(* Music Theory volumes. *)
{ Title = "Music Theory Vol. I"
Author = "Duets Academy"
Genre = Technical
BookEffects = [ SkillGain(SkillId.Composition, 5) ]
ReadProgress = 0<percent> },
30m<dd>

{ Title = "Music Theory Vol. II"
Author = "Duets Academy"
Genre = Technical
BookEffects = [ SkillGain(SkillId.Composition, 10) ]
ReadProgress = 0<percent> },
60m<dd>

(* Music production volumes. *)
{ Title = "Music Production Vol. I"
Author = "Duets Academy"
Genre = Technical
BookEffects = [ SkillGain(SkillId.MusicProduction, 3) ]
ReadProgress = 0<percent> },
30m<dd>

{ Title = "Music Production Vol. II"
Author = "Duets Academy"
Genre = Technical
BookEffects = [ SkillGain(SkillId.MusicProduction, 8) ]
ReadProgress = 0<percent> },
30m<dd> ]
Expand All @@ -42,6 +46,7 @@ let all: PurchasableItem list =
|> List.map (fun dataBook ->
{ Title = dataBook.Title
Author = dataBook.Author
Genre = Fiction (* TODO: Extract from the data-set. *)
BookEffects = []
ReadProgress = 0<percent> },
15m<dd>)
Expand Down
8 changes: 8 additions & 0 deletions src/Duets.Data/Items/Electronics.Items.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ module Duets.Data.Items.Electronics

open Duets.Entities

module Computer =
let surface: PurchasableItem =
{ Brand = "Microsoft"
Name = "Surface Pro"
Properties =
[ Computer.forPerformance 100m<percent> |> Computer |> Usable ] },
1100m<dd>

module Dartboard =
let dartboard: PurchasableItem =
{ Brand = "Bull's"
Expand Down
10 changes: 10 additions & 0 deletions src/Duets.Entities/Computer.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module Duets.Entities.Computer

/// Default state of a computer's storage.
let defaultStorage = { WordProcessor = { BookProjects = [] } }

/// Creates a computer with the default state and storage and the given performance.
let forPerformance perf =
{ Performance = perf
ComputerState = Booting
Storage = defaultStorage }
2 changes: 2 additions & 0 deletions src/Duets.Entities/Duets.Entities.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<Compile Include="Types\Places\Studio.Types.fs"/>
<Compile Include="Types\Places\Shop.Types.fs"/>
<Compile Include="Types\World.Coordinates.Types.fs"/>
<Compile Include="Types\Computer.Types.fs" />
<Compile Include="Types\Item.Types.fs"/>
<Compile Include="Types\Merch.Types.fs"/>
<Compile Include="Types\World.Types.fs"/>
Expand Down Expand Up @@ -58,6 +59,7 @@
<Compile Include="Song.fs"/>
<Compile Include="Flight.fs"/>
<Compile Include="Instrument.fs"/>
<Compile Include="Computer.fs" />
<Compile Include="Item.fs"/>
<Compile Include="Skill.fs"/>
<Compile Include="Relationships.fs"/>
Expand Down
23 changes: 23 additions & 0 deletions src/Duets.Entities/Types/Book.Types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,28 @@ namespace Duets.Entities

[<AutoOpen>]
module BookTypes =
/// Defines all genres a book can belong to.
type BookGenre =
| Fiction
| NonFiction
| ScienceFiction
| Fantasy
| Mystery
| Romance
| Horror
| Thriller
| Biography
| Autobiography
| SelfHelp
| History
| Poetry
| Drama
| Comedy
| Satire
| Tragedy
| Epic
| Technical

/// Defines the effect that reading a specific book has on a character.
type BookEffect =
| SkillGain of skill: SkillId * amount: int
Expand All @@ -13,5 +35,6 @@ module BookTypes =
type Book =
{ Title: string
Author: string
Genre: BookGenre
BookEffects: BookEffect list
ReadProgress: int<percent> }
43 changes: 43 additions & 0 deletions src/Duets.Entities/Types/Computer.Types.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
namespace Duets.Entities

[<AutoOpen>]
module ComputerTypes =
/// Represents the kind of applications that can be used in the computer.
type App = | WordProcessor

/// Represents the different states that the computer can be in.
type ComputerState =
| Booting
| AppSwitcher
| AppRunning of App

/// Types related to the word processor application.
module WordProcessor =
/// Represents a book that the character is currently working on.
type BookProject =
{ Title: string
Genre: BookGenre
Progress: int<percent> }

/// Represents a collection of books that the character is currently
/// working on.
type WordProcessorStorage = { BookProjects: BookProject list }

/// Represents what's stored in a computer.
type ComputerStorage =
{ WordProcessor: WordProcessor.WordProcessorStorage }

/// Resembles a computer that the character can use.
type Computer =
{
/// Represents the kind of performance that can be extracted from the
/// computer. The performance depends on the computer's hardware
/// and depletes over time.
Performance: decimal<percent>

/// Represents the current state of the computer.
ComputerState: ComputerState

/// Represents the storage available in the computer.
Storage: ComputerStorage
}
7 changes: 7 additions & 0 deletions src/Duets.Entities/Types/Interaction.Types.fs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ module InteractionTypes =
/// Starts a work shift in the given job.
| Work of job: Job

[<RequireQualifiedAccess>]
type ComputerInteraction =
/// Allows the character to open an application on the computer.
| OpenApp of Item * Computer * App list

/// Interactions that can be done while on a concert.
[<RequireQualifiedAccess>]
type ConcertInteraction =
Expand Down Expand Up @@ -90,6 +95,7 @@ module InteractionTypes =
| Play
| Read
| Sleep
| Use
| Watch

/// Interactions related to moving around the world.
Expand Down Expand Up @@ -231,6 +237,7 @@ module InteractionTypes =
| MiniGame of MiniGameInteraction
| MerchandiseWorkshop of MerchandiseWorkshopInteraction
| Rehearsal of RehearsalInteraction
| Situational of ComputerInteraction
| Shop of ShopInteraction
| Social of SocialInteraction
| Studio of StudioInteraction
Expand Down
Loading

0 comments on commit 670aea3

Please sign in to comment.