namespace MultiversalDiplomacy.Model; /// /// Represents a state of the map produced by a set of move orders on a previous season. /// public class Season { /// /// A shared counter for handing out new timeline numbers. /// private class TimelineFactory { private int nextTimeline = 0; public int NextTimeline() => nextTimeline++; } /// /// The first turn number. /// public const int FIRST_TURN = 0; /// /// The season immediately preceding this season. /// If this season is an alternate timeline root, the past is from the origin timeline. /// The initial season does not have a past. /// public Season? Past { get; } /// /// The current turn, beginning at 0. Each season (spring and fall) is one turn. /// Phases that only occur after the fall phase occur when Turn % 2 == 1. /// The current year is (Turn / 2) + 1901. /// public int Turn { get; } /// /// The timeline to which this season belongs. /// public int Timeline { get; } /// /// The shared timeline number generator. /// private TimelineFactory Timelines { get; } private Season(Season? past, int turn, int timeline, TimelineFactory factory) { this.Past = past; this.Turn = turn; this.Timeline = timeline; this.Timelines = factory; } /// /// Create a root season at the beginning of time. /// public static Season MakeRoot() { TimelineFactory factory = new TimelineFactory(); return new Season( past: null, turn: FIRST_TURN, timeline: factory.NextTimeline(), factory: factory); } /// /// Create a season immediately after this one in the same timeline. /// public Season MakeNext() => new Season(this, this.Turn + 1, this.Timeline, this.Timelines); /// /// Create a season immediately after this one in a new timeline. /// public Season MakeFork() => new Season(this, this.Turn + 1, this.Timelines.NextTimeline(), this.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. /// 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; } }