Refactor timelines and season creation logic into World
This commit is contained in:
parent
58f877425a
commit
345d54f960
|
@ -312,9 +312,9 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
|
|||
|
||||
// All moves to a particular season in a single phase result in the same future. Keep a
|
||||
// record of when a future season has been created.
|
||||
Dictionary<Season, Season> createdFutures = new();
|
||||
List<Unit> createdUnits = new();
|
||||
List<RetreatingUnit> retreats = new();
|
||||
Dictionary<Season, Season> createdFutures = [];
|
||||
List<Unit> createdUnits = [];
|
||||
List<RetreatingUnit> retreats = [];
|
||||
|
||||
// Populate createdFutures with the timeline fork decisions
|
||||
logger.Log(1, "Processing AdvanceTimeline decisions");
|
||||
|
@ -324,9 +324,7 @@ public class MovementPhaseAdjudicator : IPhaseAdjudicator
|
|||
if (advanceTimeline.Outcome == true)
|
||||
{
|
||||
// A timeline that doesn't have a future yet simply continues. Otherwise, it forks.
|
||||
createdFutures[advanceTimeline.Season] = !world.GetFutures(advanceTimeline.Season).Any()
|
||||
? advanceTimeline.Season.MakeNext()
|
||||
: advanceTimeline.Season.MakeFork();
|
||||
createdFutures[advanceTimeline.Season] = world.ContinueOrFork(advanceTimeline.Season);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,4 +20,10 @@ public static class ModelExtensions
|
|||
{
|
||||
return $"{coord.season.Timeline}-{coord.province.Abbreviations[0]}@{coord.season.Turn}";
|
||||
}
|
||||
|
||||
public static World ContinueOrFork(this World world, Season season, out Season future)
|
||||
{
|
||||
future = world.ContinueOrFork(season);
|
||||
return world.Update(seasons: world.Seasons.Append(future));
|
||||
}
|
||||
}
|
|
@ -43,44 +43,12 @@ public class Season
|
|||
[JsonIgnore]
|
||||
public (string Timeline, int Turn) Coord => (this.Timeline, this.Turn);
|
||||
|
||||
/// <summary>
|
||||
/// The shared timeline number generator.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
private TimelineFactory Timelines { get; }
|
||||
|
||||
private Season(string? past, int turn, string timeline, TimelineFactory factory)
|
||||
public Season(string? past, int turn, string timeline)
|
||||
{
|
||||
this.Past = past;
|
||||
this.Turn = turn;
|
||||
this.Timeline = timeline;
|
||||
this.Timelines = factory;
|
||||
}
|
||||
|
||||
public override string ToString() => Designation;
|
||||
|
||||
/// <summary>
|
||||
/// Create a root season at the beginning of time.
|
||||
/// </summary>
|
||||
public static Season MakeRoot()
|
||||
{
|
||||
TimelineFactory factory = new();
|
||||
return new Season(
|
||||
past: null,
|
||||
turn: FIRST_TURN,
|
||||
timeline: factory.NextTimeline(),
|
||||
factory: factory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a season immediately after this one in the same timeline.
|
||||
/// </summary>
|
||||
public Season MakeNext()
|
||||
=> new(this.Designation, Turn + 1, Timeline, Timelines);
|
||||
|
||||
/// <summary>
|
||||
/// Create a season immediately after this one in a new timeline.
|
||||
/// </summary>
|
||||
public Season MakeFork()
|
||||
=> new(this.Designation, Turn + 1, Timelines.NextTimeline(), Timelines);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ namespace MultiversalDiplomacy.Model;
|
|||
/// <summary>
|
||||
/// A shared counter for handing out new timeline designations.
|
||||
/// </summary>
|
||||
internal class TimelineFactory
|
||||
public class TimelineFactory
|
||||
{
|
||||
private static readonly char[] Letters = [
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
|
||||
|
|
|
@ -63,6 +63,11 @@ public class World
|
|||
/// </summary>
|
||||
public ReadOnlyDictionary<string, OrderHistory> OrderHistory { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The shared timeline number generator.
|
||||
/// </summary>
|
||||
public TimelineFactory Timelines { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Immutable game options.
|
||||
/// </summary>
|
||||
|
@ -77,6 +82,7 @@ public class World
|
|||
ReadOnlyCollection<Unit> units,
|
||||
ReadOnlyCollection<RetreatingUnit> retreatingUnits,
|
||||
ReadOnlyDictionary<string, OrderHistory> orderHistory,
|
||||
TimelineFactory timelines,
|
||||
Options options)
|
||||
{
|
||||
this.Map = map;
|
||||
|
@ -84,6 +90,7 @@ public class World
|
|||
this.Units = units;
|
||||
this.RetreatingUnits = retreatingUnits;
|
||||
this.OrderHistory = orderHistory;
|
||||
this.Timelines = timelines;
|
||||
this.Options = options;
|
||||
|
||||
this.SeasonLookup = new(Seasons.ToDictionary(season => $"{season.Timeline}{season.Turn}"));
|
||||
|
@ -105,6 +112,7 @@ public class World
|
|||
units ?? previous.Units,
|
||||
retreatingUnits ?? previous.RetreatingUnits,
|
||||
orderHistory ?? previous.OrderHistory,
|
||||
previous.Timelines,
|
||||
options ?? previous.Options)
|
||||
{
|
||||
}
|
||||
|
@ -114,12 +122,14 @@ public class World
|
|||
/// </summary>
|
||||
public static World WithMap(Map map)
|
||||
{
|
||||
TimelineFactory timelines = new();
|
||||
return new World(
|
||||
map,
|
||||
new([Season.MakeRoot()]),
|
||||
new([new(past: null, Season.FIRST_TURN, timelines.NextTimeline())]),
|
||||
new([]),
|
||||
new([]),
|
||||
new(new Dictionary<string, OrderHistory>()),
|
||||
timelines,
|
||||
new Options());
|
||||
}
|
||||
|
||||
|
@ -209,21 +219,12 @@ public class World
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a season immediately after this one in the same timeline.
|
||||
/// Create a continuation of this season if it has no futures, otherwise ceate a fork.
|
||||
/// </summary>
|
||||
public World ContinueSeason(string season)
|
||||
=> Update(seasons: Seasons.Append(SeasonLookup[season].MakeNext()));
|
||||
|
||||
/// <summary>
|
||||
/// Create a season immediately after this one in the same timeline.
|
||||
/// </summary>
|
||||
public World ContinueSeason(Season season) => ContinueSeason(season.ToString());
|
||||
|
||||
/// <summary>
|
||||
/// Create a season immediately after this one in a new timeline.
|
||||
/// </summary>
|
||||
public World ForkSeason(string season)
|
||||
=> Update(seasons: Seasons.Append(SeasonLookup[season].MakeFork()));
|
||||
public Season ContinueOrFork(Season season)
|
||||
=> GetFutures(season).Any()
|
||||
? new(season.Designation, season.Turn + 1, Timelines.NextTimeline())
|
||||
: new(season.Designation, season.Turn + 1, season.Timeline);
|
||||
|
||||
/// <summary>
|
||||
/// A standard Diplomacy game setup.
|
||||
|
|
|
@ -9,30 +9,22 @@ public class SeasonTests
|
|||
[Test]
|
||||
public void TimelineForking()
|
||||
{
|
||||
World world = World
|
||||
.WithMap(Map.Test)
|
||||
.ContinueSeason("a0")
|
||||
.ContinueSeason("a1")
|
||||
.ContinueSeason("a2")
|
||||
.ForkSeason("a1")
|
||||
.ContinueSeason("b2")
|
||||
.ForkSeason("a1")
|
||||
.ForkSeason("a2");
|
||||
World world = World.WithMap(Map.Test);
|
||||
Season a0 = world.GetSeason("a0");
|
||||
world = world
|
||||
.ContinueOrFork(a0, out Season a1)
|
||||
.ContinueOrFork(a1, out Season a2)
|
||||
.ContinueOrFork(a2, out Season a3)
|
||||
.ContinueOrFork(a1, out Season b2)
|
||||
.ContinueOrFork(b2, out Season b3)
|
||||
.ContinueOrFork(a1, out Season c2)
|
||||
.ContinueOrFork(a2, out Season d3);
|
||||
|
||||
Assert.That(
|
||||
world.Seasons.Select(season => season.ToString()),
|
||||
Is.EquivalentTo(new List<string> { "a0", "a1", "a2", "a3", "b2", "b3", "c2", "d3" }),
|
||||
"Unexpected seasons");
|
||||
|
||||
Season a0 = world.GetSeason("a0");
|
||||
Season a1 = world.GetSeason("a1");
|
||||
Season a2 = world.GetSeason("a2");
|
||||
Season a3 = world.GetSeason("a3");
|
||||
Season b2 = world.GetSeason("b2");
|
||||
Season b3 = world.GetSeason("b3");
|
||||
Season c2 = world.GetSeason("c2");
|
||||
Season d3 = world.GetSeason("d3");
|
||||
|
||||
Assert.That(a0.Timeline, Is.EqualTo("a"), "Unexpected trunk timeline");
|
||||
Assert.That(a1.Timeline, Is.EqualTo("a"), "Unexpected trunk timeline");
|
||||
Assert.That(a2.Timeline, Is.EqualTo("a"), "Unexpected trunk timeline");
|
||||
|
|
|
@ -17,12 +17,10 @@ public class UnitTests
|
|||
Season a0 = world.RootSeason;
|
||||
Unit u1 = Unit.Build(Mun, a0, pw1, UnitType.Army);
|
||||
|
||||
world = world.ContinueSeason(a0);
|
||||
Season a1 = world.GetSeason("a1");
|
||||
world = world.ContinueOrFork(a0, out Season a1);
|
||||
Unit u2 = u1.Next(Boh, a1);
|
||||
|
||||
world = world.ContinueSeason(a1);
|
||||
Season a2 = world.GetSeason("a2");
|
||||
_ = world.ContinueOrFork(a1, out Season a2);
|
||||
Unit u3 = u2.Next(Tyr, a2);
|
||||
|
||||
Assert.That(u3.Past, Is.EqualTo(u2), "Missing unit past");
|
||||
|
|
Loading…
Reference in New Issue