summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Desktop/WorldBootstrap.fs
blob: 0e8ea30ebc0fd07904be1411160199df88a492b6 (plain)
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
namespace LivingVillage.Desktop

open LivingVillage.Kernel
open LivingVillage.Kernel.Sim

module WorldBootstrap =

    let private tileCenter (x: int) (y: int) : Vec2 =
        { X = float32 (x * Sim.tilePixels + Sim.tilePixels / 2)
          Y = float32 (y * Sim.tilePixels + Sim.tilePixels / 2) }

    let private npcSpawnTiles : (int * int) array =
        [| for y in [ 14; 18; 28; 32; 36; 40 ] do
               for x in [ 24; 28; 32; 36; 40 ] do
                   yield x, y |]

    let private avatarSpawnPosition = tileCenter 31 25

    let private daylightStartTick = 6L * Sim.ticksPerDay / 24L

    let initialWorldWithOccupation (startAtDaylight: bool) (seed: uint64) (count: int) (occupation: Occupation.State option) : World =
        if count < 0 || count > npcSpawnTiles.Length then
            invalidArg (nameof count) "Desktop bootstrap supports at most 30 NPCs."

        let startTick = if startAtDaylight then daylightStartTick else 0L
        let baseWorld = Sim.initialWorldN seed count
        let avatar =
            let baseAvatar =
                { baseWorld.Avatar with
                    Pos = avatarSpawnPosition
                    Mind = { baseWorld.Avatar.Mind with Target = avatarSpawnPosition } }
            match occupation with
            | None -> baseAvatar
            | Some state ->
                let needs = baseAvatar.Mind.Needs
                { baseAvatar with
                    Mind =
                        { baseAvatar.Mind with
                            Needs =
                                { needs with
                                    Money = float32 state.Profile.InitialMoney
                                    Energy = state.Profile.InitialEnergy } } }
        let npcs =
            baseWorld.Npcs
            |> Array.mapi (fun index npc ->
                let x, y = npcSpawnTiles.[index]
                { npc with Pos = tileCenter x y })

        { baseWorld with
            Tick = startTick
            Time = float startTick * Sim.dtSeconds
            Avatar = avatar
            Npcs = npcs }

    let initialWorldForDaylight (startAtDaylight: bool) (seed: uint64) (count: int) : World =
        initialWorldWithOccupation startAtDaylight seed count None

    let initialWorld (seed: uint64) (count: int) : World =
        initialWorldWithOccupation false seed count None