Move more timeline logic from Season to World

This commit is contained in:
Tim Van Baak 2024-08-12 14:39:35 -07:00
parent 7d4f7760be
commit f5afb4105b
4 changed files with 48 additions and 46 deletions

View File

@ -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<MoveOrder> adjacentMoveOrders = moveOrdersByAdjacency[true].ToList();
List<MoveOrder> 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;

View File

@ -93,37 +93,4 @@ public class Season
/// </summary>
public Season MakeFork()
=> new(this, Turn + 1, Timelines.NextTimeline(), Timelines);
/// <summary>
/// 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.
/// </summary>
public Season TimelineRoot()
=> this.Past != null && this.Timeline == this.Past.Timeline
? this.Past.TimelineRoot()
: this;
/// <summary>
/// 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.
/// </summary>
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;
}
}

View File

@ -238,6 +238,41 @@ public class World
public Season GetSeason(string designation)
=> SeasonLookup[designation];
/// <summary>
/// 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.
/// </summary>
public Season GetTimelineRoot(Season season)
{
Season? past = season.Past;
return past != null && season.Timeline == past.Timeline
? GetTimelineRoot(season.Past!)
: season;
}
/// <summary>
/// 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.
/// </summary>
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;
}
/// <summary>
/// Returns a unit in a province. Throws if there are duplicate units.
/// </summary>

View File

@ -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");
}
}