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) { } else if (re.Move.Match(command) is Match moveMatch && moveMatch.Success) {
return TryParseMoveOrder(world, power, moveMatch, out order); return TryParseMoveOrder(world, power, moveMatch, out order);
} else if (re.SupportHold.Match(command) is Match sholdMatch && sholdMatch.Success) { } else if (re.SupportHold.Match(command) is Match sholdMatch && sholdMatch.Success) {
// DATC 4.B.4: coast specification in support orders return TryParseSupportHoldOrder(world, power, sholdMatch, out order);
throw new NotImplementedException();
} else if (re.SupportMove.Match(command) is Match smoveMatch && smoveMatch.Success) { } else if (re.SupportMove.Match(command) is Match smoveMatch && smoveMatch.Success) {
throw new NotImplementedException(); return TryParseSupportMoveOrder(world, power, smoveMatch, out order);
} else { } else {
throw new NotImplementedException(); 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; subject = null;
var hold = ParseHold(match);
string timeline = parsedTimeline.Length > 0
string timeline = hold.timeline.Length > 0 ? parsedTimeline
? hold.timeline
// If timeline is unspecified, use the root timeline // If timeline is unspecified, use the root timeline
: Season.First.Timeline; : Season.First.Timeline;
var seasonsInTimeline = world.Timelines.Seasons.Where(season => season.Timeline == timeline); var seasonsInTimeline = world.Timelines.Seasons.Where(season => season.Timeline == timeline);
if (!seasonsInTimeline.Any()) return false; if (!seasonsInTimeline.Any()) return false;
int turn = hold.turn.Length > 0 int turn = parsedTurn.Length > 0
? int.Parse(hold.turn) ? int.Parse(parsedTurn)
// If turn is unspecified, use the latest turn in the timeline // If turn is unspecified, use the latest turn in the timeline
: seasonsInTimeline.Max(season => season.Turn); : 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 => world.Map.GetLocation(unit!.Location).ProvinceName == province.Name
&& unit!.Season.Timeline == timeline && unit!.Season.Timeline == timeline
&& unit!.Season.Turn == turn, && unit!.Season.Turn == turn,
null); 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); order = new HoldOrder(power, subject);
return true; 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; order = null;
var move = ParseMove(match); var move = ParseMove(match);
string timeline = move.timeline.Length > 0 if (!TryParseOrderSubject(world, move.timeline, move.turn, move.province, out Unit? subject)) {
? move.timeline return false;
// 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;
string destTimeline = move.destTimeline.Length > 0 string destTimeline = move.destTimeline.Length > 0
? move.destTimeline ? move.destTimeline
@ -333,4 +337,29 @@ public class OrderParser(World world)
order = new MoveOrder(power, subject, new(destTimeline, destTurn), destLocationKey); order = new MoveOrder(power, subject, new(destTimeline, destTurn), destLocationKey);
return true; 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.
}
} }