blob: f8ba775a2f6b6e8a3b29f0e3ca6f8cbd047232c4 (
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
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
/// 新档职业状态:按世界 seed 与职业种子生成 nowTick 所属日的 Offered 任务(design §3)。
let occupationStateFor (seed: uint64) (kind: Occupation.Kind) (nowTick: int64) : Occupation.State =
let baseState = Occupation.stateOf kind
{ baseState with
Today = Occupation.dailyTaskOf seed (Occupation.occupationSeedOf kind) (Occupation.dayIndexOf nowTick) kind }
/// 跨日刷新当日任务;同日(含 Done/Failed 终态)原样保留。
let refreshOccupationToday (seed: uint64) (state: Occupation.State) (nowTick: int64) : Occupation.State =
{ state with
Today =
Occupation.refreshToday
seed
(Occupation.occupationSeedOf state.Profile.Kind)
state.Profile.Kind
nowTick
state.Today }
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
|