Factor out common subject parsing logic

This commit is contained in:
Tim Van Baak 2024-08-28 14:39:21 +00:00
parent 14a493d95c
commit f77cc60185
1 changed files with 67 additions and 38 deletions

View File

@ -223,73 +223,77 @@ public class OrderParser(World world)
} else if (re.Move.Match(command) is Match moveMatch && moveMatch.Success) {
return TryParseMoveOrder(world, power, moveMatch, out order);
} else if (re.SupportHold.Match(command) is Match sholdMatch && sholdMatch.Success) {
// DATC 4.B.4: coast specification in support orders
throw new NotImplementedException();
return TryParseSupportHoldOrder(world, power, sholdMatch, out order);
} else if (re.SupportMove.Match(command) is Match smoveMatch && smoveMatch.Success) {
throw new NotImplementedException();
return TryParseSupportMoveOrder(world, power, smoveMatch, out order);
} else {
throw new NotImplementedException();
}
}
public static bool TryParseHoldOrder(World world, string power, Match match, [NotNullWhen(true)] out Order? order)
public static bool TryParseOrderSubject(
World world,
string parsedTimeline,
string parsedTurn,
string parsedProvince,
[NotNullWhen(true)] out Unit? subject)
{
order = null;
var hold = ParseHold(match);
subject = null;
string timeline = hold.timeline.Length > 0
? hold.timeline
string timeline = parsedTimeline.Length > 0
? parsedTimeline
// If timeline is unspecified, use the root timeline
: Season.First.Timeline;
var seasonsInTimeline = world.Timelines.Seasons.Where(season => season.Timeline == timeline);
if (!seasonsInTimeline.Any()) return false;
int turn = hold.turn.Length > 0
? int.Parse(hold.turn)
int turn = parsedTurn.Length > 0
? int.Parse(parsedTurn)
// If turn is unspecified, use the latest turn in the timeline
: seasonsInTimeline.Max(season => season.Turn);
Province province = world.Map.Provinces.Single(province => province.Is(hold.province));
Province province = world.Map.Provinces.Single(province => province.Is(parsedProvince));
Unit? subject = world.Units.FirstOrDefault(unit
// Because only one unit can be in a province at a time, the province is sufficient to identify the subject
// and the location is ignored. This also satisfies DATC 4.B.5, which requires that a wrong coast for the
// subject be ignored.
subject = world.Units.FirstOrDefault(unit
=> world.Map.GetLocation(unit!.Location).ProvinceName == province.Name
&& unit!.Season.Timeline == timeline
&& unit!.Season.Turn == turn,
null);
if (subject is null) return false;
return subject is not null;
}
public static bool TryParseHoldOrder(
World world,
string power,
Match match,
[NotNullWhen(true)] out Order? order)
{
order = null;
var hold = ParseHold(match);
if (!TryParseOrderSubject(world, hold.timeline, hold.turn, hold.province, out Unit? subject)) {
return false;
}
order = new HoldOrder(power, subject);
return true;
}
public static bool TryParseMoveOrder(World world, string power, Match match, [NotNullWhen(true)] out Order? order)
public static bool TryParseMoveOrder(
World world,
string power,
Match match,
[NotNullWhen(true)] out Order? order)
{
order = null;
var move = ParseMove(match);
string timeline = move.timeline.Length > 0
? move.timeline
// If timeline is unspecified, use the root timeline
: Season.First.Timeline;
var seasonsInTimeline = world.Timelines.Seasons.Where(season => season.Timeline == timeline);
if (!seasonsInTimeline.Any()) return false;
int turn = move.turn.Length > 0
? int.Parse(move.turn)
// If turn is unspecified, use the latest turn in the timeline
: seasonsInTimeline.Max(season => season.Turn);
Province province = world.Map.Provinces.Single(province => province.Is(move.province));
// Because only one unit can be in a province at a time, the province is sufficient to identify the subject
// and the location is ignored. This also satisfies DATC 4.B.5, which requires that a wrong coast for the
// subject be ignored.
Unit? subject = world.Units.FirstOrDefault(unit
=> world.Map.GetLocation(unit!.Location).ProvinceName == province.Name
&& unit!.Season.Timeline == timeline
&& unit!.Season.Turn == turn,
null);
if (subject is null) return false;
if (!TryParseOrderSubject(world, move.timeline, move.turn, move.province, out Unit? subject)) {
return false;
}
string destTimeline = move.destTimeline.Length > 0
? move.destTimeline
@ -333,4 +337,29 @@ public class OrderParser(World world)
order = new MoveOrder(power, subject, new(destTimeline, destTurn), destLocationKey);
return true;
}
public static bool TryParseSupportHoldOrder(
World world,
string power,
Match match,
[NotNullWhen(true)] out Order? order)
{
order = null;
var support = ParseSupportHold(match);
throw new NotImplementedException();
}
public static bool TryParseSupportMoveOrder(
World world,
string power,
Match match,
[NotNullWhen(true)] out Order? order)
{
order = null;
var support = ParseSupportMove(match);
throw new NotImplementedException();
// It is possible to support a move to an inaccessible coast if another coast is accessible to the subject.
// DATC 4.B.4 prefers that automatic adjudicators strictly require matching coasts in supports.
}
}