From 81c9aa48598880dfed4805d8978933594fd7292f Mon Sep 17 00:00:00 2001 From: Tim Van Baak Date: Mon, 12 Aug 2024 14:39:35 -0700 Subject: [PATCH] Move more timeline logic from Season to World --- .../Adjudicate/MovementPhaseAdjudicator.cs | 8 ++--- MultiversalDiplomacy/Model/Season.cs | 33 ----------------- MultiversalDiplomacy/Model/World.cs | 35 +++++++++++++++++++ MultiversalDiplomacyTests/SeasonTests.cs | 18 +++++----- 4 files changed, 48 insertions(+), 46 deletions(-) diff --git a/MultiversalDiplomacy/Adjudicate/MovementPhaseAdjudicator.cs b/MultiversalDiplomacy/Adjudicate/MovementPhaseAdjudicator.cs index bc675c7..bf5d9be 100644 --- a/MultiversalDiplomacy/Adjudicate/MovementPhaseAdjudicator.cs +++ b/MultiversalDiplomacy/Adjudicate/MovementPhaseAdjudicator.cs @@ -94,7 +94,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator // Turn adjacency && Math.Abs(order.Unit.Season.Turn - order.Season.Turn) <= 1 // Timeline adjacency - && order.Unit.Season.InAdjacentTimeline(order.Season)); + && world.InAdjacentTimeline(order.Unit.Season, order.Season)); List adjacentMoveOrders = moveOrdersByAdjacency[true].ToList(); List nonAdjacentMoveOrders = moveOrdersByAdjacency[false].ToList(); @@ -180,7 +180,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator // Turn adjacency && Math.Abs(order.Unit.Season.Turn - order.Target.Season.Turn) <= 1 // Timeline adjacency - && order.Unit.Season.InAdjacentTimeline(order.Target.Season), + && world.InAdjacentTimeline(order.Unit.Season, order.Target.Season), ValidationReason.UnreachableSupport, ref supportHoldOrders, ref validationResults); @@ -212,7 +212,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator // Turn adjacency && Math.Abs(order.Unit.Season.Turn - order.Season.Turn) <= 1 // Timeline adjacency - && order.Unit.Season.InAdjacentTimeline(order.Season), + && world.InAdjacentTimeline(order.Unit.Season, order.Season), ValidationReason.UnreachableSupport, ref supportMoveOrders, ref validationResults); @@ -639,7 +639,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator // Turn adjacency && Math.Abs(decision.Order.Unit.Season.Turn - decision.Order.Season.Turn) <= 1 // Timeline adjacency - && decision.Order.Unit.Season.InAdjacentTimeline(decision.Order.Season)) + && world.InAdjacentTimeline(decision.Order.Unit.Season, decision.Order.Season)) { bool update = LoggedUpdate(decision, true, depth, "Adjacent move"); return progress | update; diff --git a/MultiversalDiplomacy/Model/Season.cs b/MultiversalDiplomacy/Model/Season.cs index 8db781f..d9109b0 100644 --- a/MultiversalDiplomacy/Model/Season.cs +++ b/MultiversalDiplomacy/Model/Season.cs @@ -93,37 +93,4 @@ public class Season /// public Season MakeFork() => new(this, Turn + 1, Timelines.NextTimeline(), Timelines); - - /// - /// Returns the first season in this season's timeline. The first season is the - /// root of the first timeline. The earliest season in each alternate timeline is - /// the root of that timeline. - /// - public Season TimelineRoot() - => this.Past != null && this.Timeline == this.Past.Timeline - ? this.Past.TimelineRoot() - : this; - - /// - /// Returns whether this season is in an adjacent timeline to another season. - /// Seasons are considered to be in adjacent timelines if they are in the same timeline, - /// one is in a timeline that branched from the other's timeline, or both are in timelines - /// that branched from the same point. - /// - public bool InAdjacentTimeline(Season other) - { - // Timelines are adjacent to themselves. Early out in that case. - if (this.Timeline == other.Timeline) return true; - - // If the timelines aren't identical, one of them isn't the initial trunk. - // They can still be adjacent if one of them branched off of the other, or - // if they both branched off of the same point. - Season thisRoot = this.TimelineRoot(); - Season otherRoot = other.TimelineRoot(); - return // One branched off the other - thisRoot.Past?.Timeline == other.Timeline - || otherRoot.Past?.Timeline == this.Timeline - // Both branched off of the same point - || thisRoot.Past == otherRoot.Past; - } } diff --git a/MultiversalDiplomacy/Model/World.cs b/MultiversalDiplomacy/Model/World.cs index 5499e2e..b47c29e 100644 --- a/MultiversalDiplomacy/Model/World.cs +++ b/MultiversalDiplomacy/Model/World.cs @@ -238,6 +238,41 @@ public class World public Season GetSeason(string designation) => SeasonLookup[designation]; + /// + /// Returns the first season in this season's timeline. The first season is the + /// root of the first timeline. The earliest season in each alternate timeline is + /// the root of that timeline. + /// + public Season GetTimelineRoot(Season season) + { + Season? past = season.Past; + return past != null && season.Timeline == past.Timeline + ? GetTimelineRoot(season.Past!) + : season; + } + + /// + /// Returns whether this season is in an adjacent timeline to another season. + /// Seasons are considered to be in adjacent timelines if they are in the same timeline, + /// one is in a timeline that branched from the other's timeline, or both are in timelines + /// that branched from the same point. + /// + public bool InAdjacentTimeline(Season one, Season two) + { + // Timelines are adjacent to themselves. Early out in that case. + if (one == two) return true; + + // If the timelines aren't identical, one of them isn't the initial trunk. + // They can still be adjacent if one of them branched off of the other, or + // if they both branched off of the same point. + Season rootOne = GetTimelineRoot(one); + Season rootTwo = GetTimelineRoot(two); + bool oneForked = rootOne.PastId != null && GetSeason(rootOne.PastId).Timeline == two.Timeline; + bool twoForked = rootTwo.PastId != null && GetSeason(rootTwo.PastId).Timeline == one.Timeline; + bool bothForked = rootOne.PastId == rootTwo.PastId; + return oneForked || twoForked || bothForked; + } + /// /// Returns a unit in a province. Throws if there are duplicate units. /// diff --git a/MultiversalDiplomacyTests/SeasonTests.cs b/MultiversalDiplomacyTests/SeasonTests.cs index 227fa7a..e4e401c 100644 --- a/MultiversalDiplomacyTests/SeasonTests.cs +++ b/MultiversalDiplomacyTests/SeasonTests.cs @@ -51,15 +51,15 @@ public class SeasonTests Assert.That(c2.Turn, Is.EqualTo(Season.FIRST_TURN + 2), "Unexpected fork turn number"); Assert.That(d3.Turn, Is.EqualTo(Season.FIRST_TURN + 3), "Unexpected fork turn number"); - Assert.That(a0.TimelineRoot(), Is.EqualTo(a0), "Expected timeline root to be reflexive"); - Assert.That(a3.TimelineRoot(), Is.EqualTo(a0), "Expected trunk timeline to have root"); - Assert.That(b2.TimelineRoot(), Is.EqualTo(b2), "Expected alt timeline root to be reflexive"); - Assert.That(b3.TimelineRoot(), Is.EqualTo(b2), "Expected alt timeline to root at first fork"); - Assert.That(c2.TimelineRoot(), Is.EqualTo(c2), "Expected alt timeline root to be reflexive"); - Assert.That(d3.TimelineRoot(), Is.EqualTo(d3), "Expected alt timeline root to be reflexive"); + Assert.That(world.GetTimelineRoot(a0), Is.EqualTo(a0), "Expected timeline root to be reflexive"); + Assert.That(world.GetTimelineRoot(a3), Is.EqualTo(a0), "Expected trunk timeline to have root"); + Assert.That(world.GetTimelineRoot(b2), Is.EqualTo(b2), "Expected alt timeline root to be reflexive"); + Assert.That(world.GetTimelineRoot(b3), Is.EqualTo(b2), "Expected alt timeline to root at first fork"); + Assert.That(world.GetTimelineRoot(c2), Is.EqualTo(c2), "Expected alt timeline root to be reflexive"); + Assert.That(world.GetTimelineRoot(d3), Is.EqualTo(d3), "Expected alt timeline root to be reflexive"); - Assert.That(b3.InAdjacentTimeline(a3), Is.True, "Expected alts to be adjacent to origin"); - Assert.That(b3.InAdjacentTimeline(c2), Is.True, "Expected alts with common origin to be adjacent"); - Assert.That(b3.InAdjacentTimeline(d3), Is.False, "Expected alts from different origins not to be adjacent"); + Assert.That(world.InAdjacentTimeline(b3, a3), Is.True, "Expected alts to be adjacent to origin"); + Assert.That(world.InAdjacentTimeline(b3, c2), Is.True, "Expected alts with common origin to be adjacent"); + Assert.That(world.InAdjacentTimeline(b3, d3), Is.False, "Expected alts from different origins not to be adjacent"); } }