summaryrefslogtreecommitdiff
path: root/src/LivingVillage.Kernel.Tests/DailyTaskTests.fs
diff options
context:
space:
mode:
Diffstat (limited to 'src/LivingVillage.Kernel.Tests/DailyTaskTests.fs')
-rw-r--r--src/LivingVillage.Kernel.Tests/DailyTaskTests.fs100
1 files changed, 93 insertions, 7 deletions
diff --git a/src/LivingVillage.Kernel.Tests/DailyTaskTests.fs b/src/LivingVillage.Kernel.Tests/DailyTaskTests.fs
index e784d83..0800ff8 100644
--- a/src/LivingVillage.Kernel.Tests/DailyTaskTests.fs
+++ b/src/LivingVillage.Kernel.Tests/DailyTaskTests.fs
@@ -50,20 +50,24 @@ type DailyTaskTests () =
Assert.AreEqual<uint64>(0x02D114B7ABDD7A1FUL, Occupation.taskHash 4242UL 99UL 0L)
[<TestMethod>]
- member _.FarmerAndFisherPoolsAreThreeTemplatesEach () =
+ member _.EveryOccupationPoolIsNonEmptyAndFarmFisherKeepThree () =
Assert.AreEqual(
[ Occupation.DeliverGrain; Occupation.HelpWork; Occupation.TillSoil ],
Occupation.taskPoolOf Occupation.Farmer)
Assert.AreEqual(
[ Occupation.NightCatch; Occupation.SellFish; Occupation.MarketInquiry ],
Occupation.taskPoolOf Occupation.Fisher)
- Assert.AreEqual<int>(0, Occupation.taskPoolOf Occupation.Peddler |> List.length)
- Assert.AreEqual<int>(0, Occupation.taskPoolOf Occupation.Scholar |> List.length)
+ Assert.AreEqual(
+ [ Occupation.BuyGoods; Occupation.Resell ],
+ Occupation.taskPoolOf Occupation.Peddler)
+ Assert.AreEqual(
+ [ Occupation.ObserveNotes; Occupation.ReasonDebate ],
+ Occupation.taskPoolOf Occupation.Scholar)
[<TestMethod>]
member _.GeneratedTasksStayInPoolAndRepeatDeterministically () =
for seed, occ in [ (42UL, 7UL); (7UL, 42UL); (123456789UL, 555UL) ] do
- for kind in [ Occupation.Farmer; Occupation.Fisher ] do
+ for kind in Occupation.all do
let pool = Occupation.taskPoolOf kind
for day in 0L .. 299L do
let task = (Occupation.dailyTaskOf seed occ day kind).Value
@@ -77,9 +81,17 @@ type DailyTaskTests () =
Assert.IsTrue(distinct.Count >= 2, "300 days must not pin a single template")
[<TestMethod>]
- member _.PeddlerAndScholarHaveNoDailyTaskYet () =
- Assert.AreEqual<Occupation.DailyTask option>(None, Occupation.dailyTaskOf 42UL 7UL 0L Occupation.Peddler)
- Assert.AreEqual<Occupation.DailyTask option>(None, Occupation.dailyTaskOf 42UL 7UL 0L Occupation.Scholar)
+ member _.PeddlerAndScholarGenerateTheirOwnDailyTasks () =
+ for kind in [ Occupation.Peddler; Occupation.Scholar ] do
+ for day in 0L .. 59L do
+ let task = (Occupation.dailyTaskOf 42UL 7UL day kind).Value
+ Assert.IsTrue(Occupation.taskPoolOf kind |> List.contains task.TemplateId)
+ Assert.AreEqual<Occupation.TaskTemplateId>(
+ Occupation.BuyGoods,
+ (Occupation.dailyTaskOf 42UL 7UL 0L Occupation.Peddler).Value.TemplateId)
+ Assert.AreEqual<Occupation.TaskTemplateId>(
+ Occupation.ObserveNotes,
+ (Occupation.dailyTaskOf 42UL 7UL 0L Occupation.Scholar).Value.TemplateId)
[<TestMethod>]
member _.TaskWindowCoversExactlyOneDayStartingOffered () =
@@ -98,6 +110,10 @@ type DailyTaskTests () =
Assert.AreEqual<string>("夜捕", Occupation.taskNameOf Occupation.NightCatch)
Assert.AreEqual<string>("卖渔", Occupation.taskNameOf Occupation.SellFish)
Assert.AreEqual<string>("询价", Occupation.taskNameOf Occupation.MarketInquiry)
+ Assert.AreEqual<string>("收货", Occupation.taskNameOf Occupation.BuyGoods)
+ Assert.AreEqual<string>("转卖", Occupation.taskNameOf Occupation.Resell)
+ Assert.AreEqual<string>("观察记事", Occupation.taskNameOf Occupation.ObserveNotes)
+ Assert.AreEqual<string>("论理", Occupation.taskNameOf Occupation.ReasonDebate)
// ---- §3 状态机 Offered|Active|Done|Failed ----
@@ -298,3 +314,73 @@ type DailyTaskTests () =
let state = { (Occupation.stateOf Occupation.Farmer) with Today = Some(DailyTaskHarness.taskForDay 9L) }
WorldSave.saveWith (Some state) world
Assert.AreEqual<string>(build (), build ())
+
+ // ---- P15:货郎/书生模板完成信号、事件通道桥、当日刷新 ----
+
+ [<TestMethod>]
+ member _.PeddlerAndScholarTemplatesCompleteOnTheirSignals () =
+ let buy = DailyTaskHarness.accepted Occupation.BuyGoods
+ Assert.AreEqual<Occupation.TaskState>(Occupation.Done, (Occupation.applySignal (Occupation.Purchased(Food, 2)) buy).State)
+ Assert.AreEqual<Occupation.TaskState>(Occupation.Active, (Occupation.applySignal (Occupation.Purchased(Food, 0)) buy).State)
+ Assert.AreEqual<Occupation.TaskState>(Occupation.Active, (Occupation.applySignal (Occupation.Dialogued(NpcId 0)) buy).State)
+ let resell = DailyTaskHarness.accepted Occupation.Resell
+ Assert.AreEqual<Occupation.TaskState>(Occupation.Done, (Occupation.applySignal (Occupation.Traded(playerId, Spice, 1)) resell).State)
+ Assert.AreEqual<Occupation.TaskState>(Occupation.Active, (Occupation.applySignal (Occupation.Traded(NpcId 2, Spice, 1)) resell).State)
+ let observe = DailyTaskHarness.accepted Occupation.ObserveNotes
+ Assert.AreEqual<Occupation.TaskState>(Occupation.Done, (Occupation.applySignal Occupation.Observed observe).State)
+ Assert.AreEqual<Occupation.TaskState>(Occupation.Active, (Occupation.applySignal (Occupation.Dialogued(NpcId 0)) observe).State)
+ let reason = DailyTaskHarness.accepted Occupation.ReasonDebate
+ Assert.AreEqual<Occupation.TaskState>(Occupation.Done, (Occupation.applySignal (Occupation.Dialogued(NpcId 3)) reason).State)
+ Assert.AreEqual<Occupation.TaskState>(Occupation.Active, (Occupation.applySignal Occupation.Observed reason).State)
+
+ [<TestMethod>]
+ member _.SignalBridgeIgnoresNpcInitiatedEvents () =
+ let npcDialogue =
+ { Tick = 5L
+ Kind = DialogueEvent { Tick = 5L; Actor = NpcId 1; Target = NpcId 2; Intent = SmallTalk; Response = Friendly; Valence = 0.3f } }
+ Assert.AreEqual<Occupation.TaskSignal option>(None, Occupation.signalOfInteraction npcDialogue)
+ let npcTrade = { Tick = 5L; Kind = TradeEvent(NpcId 1, NpcId 2, Food, 1, 1.0f) }
+ Assert.AreEqual<Occupation.TaskSignal option>(None, Occupation.signalOfInteraction npcTrade)
+ let playerBuy = { Tick = 6L; Kind = TradeEvent(playerId, NpcId 2, Spice, 3, 2.0f) }
+ Assert.AreEqual<Occupation.TaskSignal option>(Some(Occupation.Purchased(Spice, 3)), Occupation.signalOfInteraction playerBuy)
+ let playerSell = { Tick = 7L; Kind = TradeEvent(NpcId 2, playerId, Fish, 4, 2.0f) }
+ Assert.AreEqual<Occupation.TaskSignal option>(Some(Occupation.Traded(playerId, Fish, 4)), Occupation.signalOfInteraction playerSell)
+
+ [<TestMethod>]
+ member _.PlayerDialogueEventThroughExistingChannelCompletesTheDaysTask () =
+ let world = Sim.initialWorldN 7UL 4
+ let nearFirst = { world with Avatar = { world.Avatar with Pos = world.Npcs.[0].Pos } }
+ match Sim.chooseDialogue (NpcId 0) SmallTalk nearFirst with
+ | DialogueRejected (failure, _) -> Assert.Fail($"dialogue rejected: {failure}")
+ | DialogueSucceeded (outcome, afterDialogue) ->
+ let event = afterDialogue.Events |> List.last
+ Assert.AreEqual<Sim.NpcId>(playerId, outcome.Actor)
+ Assert.AreEqual<Occupation.TaskSignal option>(Some(Occupation.Dialogued(NpcId 0)), Occupation.signalOfInteraction event)
+ let day =
+ [ 0L .. 60L ]
+ |> List.find (fun day ->
+ (Occupation.dailyTaskOf 42UL 7UL day Occupation.Farmer).Value.TemplateId = Occupation.HelpWork)
+ let offered = (Occupation.dailyTaskOf 42UL 7UL day Occupation.Farmer).Value
+ let notAccepted = Occupation.advanceTask event { (Occupation.stateOf Occupation.Farmer) with Today = Some offered }
+ Assert.AreEqual<Occupation.TaskState>(Occupation.Offered, notAccepted.Today.Value.State)
+ let active = notAccepted.Today |> Option.map Occupation.acceptTask
+ let completed = Occupation.advanceTask event { notAccepted with Today = active }
+ Assert.AreEqual<Occupation.TaskState>(Occupation.Done, completed.Today.Value.State)
+
+ [<TestMethod>]
+ member _.RefreshTodayKeepsSameDayFinalsAndRegeneratesOnDayChange () =
+ let day0 = (Occupation.dailyTaskOf 42UL 7UL 0L Occupation.Farmer).Value
+ Assert.AreEqual<Occupation.DailyTask option>(
+ Some day0,
+ Occupation.refreshToday 42UL 7UL Occupation.Farmer (Sim.ticksPerDay - 1L) (Some day0))
+ let day1 = (Occupation.dailyTaskOf 42UL 7UL 1L Occupation.Farmer).Value
+ Assert.AreEqual<Occupation.DailyTask option>(
+ Some day1,
+ Occupation.refreshToday 42UL 7UL Occupation.Farmer Sim.ticksPerDay (Some day0))
+ let finished = { day0 with State = Occupation.Done }
+ Assert.AreEqual<Occupation.DailyTask option>(
+ Some finished,
+ Occupation.refreshToday 42UL 7UL Occupation.Farmer 10L (Some finished))
+ Assert.AreEqual<Occupation.DailyTask option>(
+ Some day1,
+ Occupation.refreshToday 42UL 7UL Occupation.Farmer Sim.ticksPerDay None)