Factor out common subject parsing logic
This commit is contained in:
parent
14a493d95c
commit
f77cc60185
|
@ -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 = hold.timeline.Length > 0
|
string timeline = parsedTimeline.Length > 0
|
||||||
? hold.timeline
|
? parsedTimeline
|
||||||
// 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.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue