Compare commits
No commits in common. "24e80af7efe00808e14b092dc6d6fc7fd4bdfa12" and "b4f8f621ca4bb33df6aacaf9130a0ff280cc1fc8" have entirely different histories.
24e80af7ef
...
b4f8f621ca
|
@ -5,11 +5,6 @@ using MultiversalDiplomacy.Orders;
|
||||||
|
|
||||||
namespace MultiversalDiplomacy.Model;
|
namespace MultiversalDiplomacy.Model;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This class defines the regular expressions that are used to build up larger expressions for matching orders
|
|
||||||
/// and other script inputs. It also provides helper functions to extract the captured order elements as tuples,
|
|
||||||
/// which function as the structured intermediate representation between raw user input and full Order objects.
|
|
||||||
/// </summary>
|
|
||||||
public class OrderRegex(World world)
|
public class OrderRegex(World world)
|
||||||
{
|
{
|
||||||
public const string Type = "(A|F|Army|Fleet)";
|
public const string Type = "(A|F|Army|Fleet)";
|
||||||
|
@ -30,8 +25,6 @@ public class OrderRegex(World world)
|
||||||
|
|
||||||
public const string MoveVerb = "(-|(?:->)|(?:=>)|(?:attack(?:s)?)|(?:move(?:s)?(?: to)?))";
|
public const string MoveVerb = "(-|(?:->)|(?:=>)|(?:attack(?:s)?)|(?:move(?:s)?(?: to)?))";
|
||||||
|
|
||||||
public const string SupportVerb = "(s|support|supports)";
|
|
||||||
|
|
||||||
public const string ViaConvoy = "(convoy|via convoy|by convoy)";
|
public const string ViaConvoy = "(convoy|via convoy|by convoy)";
|
||||||
|
|
||||||
public Regex Hold => new(
|
public Regex Hold => new(
|
||||||
|
@ -88,84 +81,6 @@ public class OrderRegex(World world)
|
||||||
match.Groups[12].Value,
|
match.Groups[12].Value,
|
||||||
match.Groups[13].Value);
|
match.Groups[13].Value);
|
||||||
|
|
||||||
public Regex SupportHold => new(
|
|
||||||
$"^{UnitSpec} {SupportVerb} {UnitSpec}$",
|
|
||||||
RegexOptions.IgnoreCase);
|
|
||||||
|
|
||||||
public static (
|
|
||||||
string type,
|
|
||||||
string timeline,
|
|
||||||
string province,
|
|
||||||
string location,
|
|
||||||
string turn,
|
|
||||||
string supportVerb,
|
|
||||||
string targetType,
|
|
||||||
string targetTimeline,
|
|
||||||
string targetProvince,
|
|
||||||
string targetLocation,
|
|
||||||
string targetTurn)
|
|
||||||
ParseSupportHold(Match match) => (
|
|
||||||
match.Groups[1].Value,
|
|
||||||
match.Groups[2].Value,
|
|
||||||
match.Groups[3].Value,
|
|
||||||
match.Groups[4].Length > 0
|
|
||||||
? match.Groups[4].Value
|
|
||||||
: match.Groups[5].Value,
|
|
||||||
match.Groups[6].Value,
|
|
||||||
match.Groups[7].Value,
|
|
||||||
match.Groups[8].Value,
|
|
||||||
match.Groups[9].Value,
|
|
||||||
match.Groups[10].Value,
|
|
||||||
match.Groups[11].Length > 0
|
|
||||||
? match.Groups[11].Value
|
|
||||||
: match.Groups[12].Value,
|
|
||||||
match.Groups[13].Value);
|
|
||||||
|
|
||||||
public Regex SupportMove => new(
|
|
||||||
$"{UnitSpec} {SupportVerb} {UnitSpec} {MoveVerb} {FullLocation}$",
|
|
||||||
RegexOptions.IgnoreCase);
|
|
||||||
|
|
||||||
public static (
|
|
||||||
string type,
|
|
||||||
string timeline,
|
|
||||||
string province,
|
|
||||||
string location,
|
|
||||||
string turn,
|
|
||||||
string supportVerb,
|
|
||||||
string targetType,
|
|
||||||
string targetTimeline,
|
|
||||||
string targetProvince,
|
|
||||||
string targetLocation,
|
|
||||||
string targetTurn,
|
|
||||||
string moveVerb,
|
|
||||||
string destTimeline,
|
|
||||||
string destProvince,
|
|
||||||
string destLocation,
|
|
||||||
string destTurn)
|
|
||||||
ParseSupportMove(Match match) => (
|
|
||||||
match.Groups[1].Value,
|
|
||||||
match.Groups[2].Value,
|
|
||||||
match.Groups[3].Value,
|
|
||||||
match.Groups[4].Length > 0
|
|
||||||
? match.Groups[4].Value
|
|
||||||
: match.Groups[5].Value,
|
|
||||||
match.Groups[6].Value,
|
|
||||||
match.Groups[7].Value,
|
|
||||||
match.Groups[8].Value,
|
|
||||||
match.Groups[9].Value,
|
|
||||||
match.Groups[10].Value,
|
|
||||||
match.Groups[11].Length > 0
|
|
||||||
? match.Groups[11].Value
|
|
||||||
: match.Groups[12].Value,
|
|
||||||
match.Groups[13].Value,
|
|
||||||
match.Groups[14].Value,
|
|
||||||
match.Groups[15].Value,
|
|
||||||
match.Groups[16].Value,
|
|
||||||
match.Groups[17].Length > 0
|
|
||||||
? match.Groups[17].Value
|
|
||||||
: match.Groups[18].Value,
|
|
||||||
match.Groups[19].Value);
|
|
||||||
|
|
||||||
public static bool TryParseUnit(World world, string unitSpec, [NotNullWhen(true)] out Unit? newUnit)
|
public static bool TryParseUnit(World world, string unitSpec, [NotNullWhen(true)] out Unit? newUnit)
|
||||||
{
|
{
|
||||||
newUnit = null;
|
newUnit = null;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>0.0.2</VersionPrefix>
|
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
|
|
@ -52,6 +52,8 @@ public class RegexTest
|
||||||
|
|
||||||
static IEnumerable<TestCaseData> MoveRegexMatchesTestCases()
|
static IEnumerable<TestCaseData> MoveRegexMatchesTestCases()
|
||||||
{
|
{
|
||||||
|
static TestCaseData Test(string order, params string[] expected)
|
||||||
|
=> new TestCaseData(order, expected).SetName($"{{m}}(\"{order}\")");
|
||||||
// Full specification
|
// Full specification
|
||||||
yield return Test(
|
yield return Test(
|
||||||
"Army a-Munich/l@0 - a-Tyrolia/l@0",
|
"Army a-Munich/l@0 - a-Tyrolia/l@0",
|
||||||
|
@ -68,18 +70,10 @@ public class RegexTest
|
||||||
yield return Test(
|
yield return Test(
|
||||||
"A F-STP - MOS",
|
"A F-STP - MOS",
|
||||||
"A", "F", "STP", "", "", "-", "", "MOS", "", "", "");
|
"A", "F", "STP", "", "", "-", "", "MOS", "", "", "");
|
||||||
// No confusion of timeline and hold verb
|
|
||||||
yield return Test(
|
|
||||||
"A Mun - h-Tyr",
|
|
||||||
"A", "", "Mun", "", "", "-", "h", "Tyr", "", "", "");
|
|
||||||
// No confusion of timeline and support verb
|
|
||||||
yield return Test(
|
|
||||||
"A Mun - s-Tyr",
|
|
||||||
"A", "", "Mun", "", "", "-", "s", "Tyr", "", "", "");
|
|
||||||
// Elements with spaces
|
// Elements with spaces
|
||||||
yield return Test(
|
yield return Test(
|
||||||
"Western Mediterranean Sea moves to Gulf of Lyons via convoy",
|
"Fleet Western Mediterranean Sea moves to Gulf of Lyons via convoy",
|
||||||
"", "", "Western Mediterranean Sea", "", "", "moves to", "", "Gulf of Lyons", "", "", "via convoy");
|
"Fleet", "", "Western Mediterranean Sea", "", "", "moves to", "", "Gulf of Lyons", "", "", "via convoy");
|
||||||
// Parenthesis location
|
// Parenthesis location
|
||||||
yield return Test(
|
yield return Test(
|
||||||
"F Spain(nc) - Spain(sc)",
|
"F Spain(nc) - Spain(sc)",
|
||||||
|
@ -104,96 +98,4 @@ public class RegexTest
|
||||||
Assert.That(actual, Is.EquivalentTo(expected), "Unexpected parse results");
|
Assert.That(actual, Is.EquivalentTo(expected), "Unexpected parse results");
|
||||||
Assert.That(actual, Is.EqualTo(expected), "Unexpected parse results");
|
Assert.That(actual, Is.EqualTo(expected), "Unexpected parse results");
|
||||||
}
|
}
|
||||||
|
|
||||||
static IEnumerable<TestCaseData> SupportHoldRegexMatchesTestCases()
|
|
||||||
{
|
|
||||||
// Full specification
|
|
||||||
yield return Test(
|
|
||||||
"Army a-Munich/l@0 s A a-Tyrolia/l@0",
|
|
||||||
"Army", "a", "Munich", "l", "0", "s", "A", "a", "Tyrolia", "l", "0");
|
|
||||||
// Case insensitivity
|
|
||||||
yield return Test(
|
|
||||||
"fleet B-lon/C@0 SUPPORTS B-enc/W@0",
|
|
||||||
"fleet", "B", "lon", "C", "0", "SUPPORTS", "", "B", "enc", "W", "0");
|
|
||||||
// All optionals missing
|
|
||||||
yield return Test(
|
|
||||||
"ROM s VIE",
|
|
||||||
"", "", "ROM", "", "", "s", "", "", "VIE", "", "");
|
|
||||||
// No confusion of unit type and timeline
|
|
||||||
yield return Test(
|
|
||||||
"A F-STP s MOS",
|
|
||||||
"A", "F", "STP", "", "", "s", "", "", "MOS", "", "");
|
|
||||||
// No confusion of timeline and support verb
|
|
||||||
yield return Test(
|
|
||||||
"A Mun s Tyr",
|
|
||||||
"A", "", "Mun", "", "", "s", "", "", "Tyr", "", "");
|
|
||||||
// Elements with spaces
|
|
||||||
yield return Test(
|
|
||||||
"Western Mediterranean Sea supports Gulf of Lyons",
|
|
||||||
"", "", "Western Mediterranean Sea", "", "", "supports", "", "", "Gulf of Lyons", "", "");
|
|
||||||
// Parenthesis location
|
|
||||||
yield return Test(
|
|
||||||
"F Spain(nc) s Spain(sc)",
|
|
||||||
"F", "", "Spain", "nc", "", "s", "", "", "Spain", "sc", "");
|
|
||||||
// Timeline designation spells out a province
|
|
||||||
yield return Test(
|
|
||||||
"A tyr-MUN(vie) s mun-TYR/vie",
|
|
||||||
"A", "tyr", "MUN", "vie", "", "s", "", "mun", "TYR", "vie", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCaseSource(nameof(SupportHoldRegexMatchesTestCases))]
|
|
||||||
public void SupportHoldRegexMatches(string order, string[] expected)
|
|
||||||
{
|
|
||||||
OrderRegex re = new(World.WithStandardMap());
|
|
||||||
var match = re.SupportHold.Match(order);
|
|
||||||
Assert.True(match.Success, "Match failed");
|
|
||||||
var (type, timeline, province, location, turn, supportVerb,
|
|
||||||
targetType, targetTimeline, targetProvince, targetLocation, targetTurn) = OrderRegex.ParseSupportHold(match);
|
|
||||||
string[] actual = [type, timeline, province, location, turn, supportVerb,
|
|
||||||
targetType, targetTimeline, targetProvince, targetLocation, targetTurn];
|
|
||||||
// Use EquivalentTo for more detailed error message
|
|
||||||
Assert.That(actual, Is.EquivalentTo(expected), "Unexpected parse results");
|
|
||||||
Assert.That(actual, Is.EqualTo(expected), "Unexpected parse results");
|
|
||||||
}
|
|
||||||
|
|
||||||
static IEnumerable<TestCaseData> SupportMoveRegexMatchesTestCases()
|
|
||||||
{
|
|
||||||
// Full specification
|
|
||||||
yield return Test(
|
|
||||||
"Army a-Munich/l@0 s A a-Tyrolia/l@0 - a-Vienna/l@0",
|
|
||||||
"Army", "a", "Munich", "l", "0", "s", "A", "a", "Tyrolia", "l", "0", "-", "a", "Vienna", "l", "0");
|
|
||||||
// Case insensitivity
|
|
||||||
yield return Test(
|
|
||||||
"fleet B-lon/C@0 SUPPORTS B-enc/W@0 MOVE TO B-nts/W@0",
|
|
||||||
"fleet", "B", "lon", "C", "0", "SUPPORTS", "", "B", "enc", "W", "0", "MOVE TO", "B", "nts", "W", "0");
|
|
||||||
// All optionals missing
|
|
||||||
yield return Test(
|
|
||||||
"ROM s VIE - TYR",
|
|
||||||
"", "", "ROM", "", "", "s", "", "", "VIE", "", "", "-", "", "TYR", "", "");
|
|
||||||
// No confusion of unit type and timeline
|
|
||||||
yield return Test(
|
|
||||||
"A F-STP S MOS - A-UKR",
|
|
||||||
"A", "F", "STP", "", "", "S", "", "", "MOS", "", "", "-", "A", "UKR", "", "");
|
|
||||||
// Elements with spaces
|
|
||||||
yield return Test(
|
|
||||||
"Western Mediterranean Sea supports Gulf of Lyons move to North Sea",
|
|
||||||
"", "", "Western Mediterranean Sea", "", "", "supports", "", "", "Gulf of Lyons", "", "", "move to", "", "North Sea", "", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
[TestCaseSource(nameof(SupportMoveRegexMatchesTestCases))]
|
|
||||||
public void SupportMoveRegexMatches(string order, string[] expected)
|
|
||||||
{
|
|
||||||
OrderRegex re = new(World.WithStandardMap());
|
|
||||||
var match = re.SupportMove.Match(order);
|
|
||||||
Assert.True(match.Success, "Match failed");
|
|
||||||
var (type, timeline, province, location, turn, supportVerb,
|
|
||||||
targetType, targetTimeline, targetProvince, targetLocation, targetTurn, moveVerb,
|
|
||||||
destTimeline, destProvince, destLocation, destTurn) = OrderRegex.ParseSupportMove(match);
|
|
||||||
string[] actual = [type, timeline, province, location, turn, supportVerb,
|
|
||||||
targetType, targetTimeline, targetProvince, targetLocation, targetTurn, moveVerb,
|
|
||||||
destTimeline, destProvince, destLocation, destTurn];
|
|
||||||
// Use EquivalentTo for more detailed error message
|
|
||||||
Assert.That(actual, Is.EquivalentTo(expected), "Unexpected parse results");
|
|
||||||
Assert.That(actual, Is.EqualTo(expected), "Unexpected parse results");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,4 +8,4 @@ This project was inspired by [Oliver Lugg's proof-of-concept version](https://gi
|
||||||
|
|
||||||
This project is not ready for end users yet!
|
This project is not ready for end users yet!
|
||||||
|
|
||||||
I am working in VS Code on NixOS so currently the developer setup is optimized for that. VS Code is launched from inside a `nix develop` shell so it gets the environment. The C# debugger fails to launch on NixOS so I run Code through an Ubuntu 22.04 distrobox when I need that.
|
I am working in VS Code on NixOS so currently the developer setup is optimized for that. Code is launch from inside a `nix develop` shell so it gets the environment.
|
||||||
|
|
|
@ -10,8 +10,6 @@ When the adjudicator is in a more complete state, this section will declare the
|
||||||
|
|
||||||
The MDATC (Multiversal Diplomacy Adjudicator Test Cases) document defines test cases that involve multiversal time travel.
|
The MDATC (Multiversal Diplomacy Adjudicator Test Cases) document defines test cases that involve multiversal time travel.
|
||||||
|
|
||||||
- 4.C.5 (missing nationality in support order), 4.C.6 (wrong nationalist in support order): 5dplomacy does not support specifying the nationalirt of the supported unit.
|
|
||||||
|
|
||||||
## Variant rules
|
## Variant rules
|
||||||
|
|
||||||
### Multiversal time travel and timeline forks
|
### Multiversal time travel and timeline forks
|
||||||
|
|
Loading…
Reference in New Issue