๐Ÿ“ฆ sleepyfran / duets

๐Ÿ“„ MainMenu.fs ยท 94 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94module Duets.Cli.Scenes.MainMenu

open Duets.Agents
open Duets.Agents.Savegame
open Duets.Cli.Components
open Duets.Cli.SceneIndex
open Duets.Cli.Text
open Duets.Data.Savegame.Types
open System.Reflection

let gameVersion =
    let assembly = Assembly.GetEntryAssembly()

    let infoVersion =
        assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()

    match infoVersion with
    | null -> assembly.GetName().Version.ToString()
    | attr ->
        let version = attr.InformationalVersion
        let isNonFinalVersion = version.Contains("-")
        if isNonFinalVersion then version else version.Split("+")[0]


type private MainMenuOption =
    | NewGame
    | LoadGame
    | Settings

let private textFromOption opt =
    match opt with
    | NewGame -> MainMenu.newGame
    | LoadGame -> MainMenu.loadGame
    | Settings -> MainMenu.settings

let private textFromMigrationError err =
    match err with
    | MigrationError.InvalidStructure message -> message
    | MigrationError.InvalidVersion version ->
        $"Unknown savegame version {version}"

/// Main menu of the game where the user can choose to either start a new game
/// or load a previous one.
let rec mainMenu skipSaving =
    clearScreen ()

    Generic.gameName |> showFiglet
    showGameInfo gameVersion

    let savegameState = Savegame.load ()

    if skipSaving then
        Styles.danger
            "--no-saving arg detected, all changes during gameplay won't be persisted!"
        |> showMessage

    let hasSavegameAvailable =
        match savegameState with
        | Available _ -> true
        | NotAvailable -> false
        | Incompatible reason ->
            textFromMigrationError reason
            |> MainMenu.incompatibleSavegame
            |> showMessage

            false

    let selectedChoice =
        showOptionalChoicePrompt
            MainMenu.prompt
            MainMenu.exit
            textFromOption
            [ NewGame
              if hasSavegameAvailable then
                  LoadGame
              Settings ]

    match selectedChoice with
    | Some NewGame -> createNewGame skipSaving hasSavegameAvailable
    | Some LoadGame -> Scene.WorldAfterMovement
    | Some Settings -> Scene.Settings
    | None -> Scene.Exit ExitMode.SkipSave

and private createNewGame skipSaving hasSavegameAvailable =
    if hasSavegameAvailable then
        let confirmed = showConfirmationPrompt MainMenu.newGameReplacePrompt

        if confirmed then
            Scene.CharacterCreator
        else
            mainMenu skipSaving
    else
        Scene.CharacterCreator