Add Rolemaster ruleset parsing scaffolding

This commit is contained in:
2026-04-03 00:15:02 +02:00
parent 13c6215c89
commit 90afe3b06b
8 changed files with 149 additions and 16 deletions

View File

@@ -7,28 +7,49 @@ public sealed class DiceRulesTests
{
Assert.Equal(RulesetKind.D6, DiceRules.TryParseRulesetId("d6"));
Assert.Equal(RulesetKind.Dnd5e, DiceRules.TryParseRulesetId("dnd5e"));
Assert.Equal(RulesetKind.Rolemaster, DiceRules.TryParseRulesetId("rolemaster"));
Assert.Null(DiceRules.TryParseRulesetId("unknown"));
var d6 = DiceRules.ParseExpression(RulesetKind.D6, "5D+4");
var dnd = DiceRules.ParseExpression(RulesetKind.Dnd5e, "2d12+2");
var rolemasterInitiative = DiceRules.ParseExpression(RulesetKind.Rolemaster, "2d10-15");
var rolemasterPercentile = DiceRules.ParseExpression(RulesetKind.Rolemaster, "d100+4");
var rolemasterOpenEnded = DiceRules.ParseExpression(RulesetKind.Rolemaster, "1d100!+85");
var emptyExpression = DiceRules.ParseExpression(RulesetKind.Dnd5e, "");
var badFormat = DiceRules.ParseExpression(RulesetKind.Dnd5e, "abc");
var tooManyDice = DiceRules.ParseExpression(RulesetKind.D6, "51D+1");
var tooManySides = DiceRules.ParseExpression(RulesetKind.Dnd5e, "1d1001");
var tooLargeModifier = DiceRules.ParseExpression(RulesetKind.Dnd5e, "1d20+1001");
var negativeDndModifier = DiceRules.ParseExpression(RulesetKind.Dnd5e, "1d20-1");
var invalidRolemasterFormat = DiceRules.ParseExpression(RulesetKind.Rolemaster, "2d12+1");
var tooNegativeRolemasterModifier = DiceRules.ParseExpression(RulesetKind.Rolemaster, "d100-1001");
var unknownRulesetExpression = DiceRules.ParseExpression((RulesetKind)99, "1d20+1");
Assert.True(d6.Succeeded);
Assert.True(dnd.Succeeded);
Assert.True(rolemasterInitiative.Succeeded);
Assert.True(rolemasterPercentile.Succeeded);
Assert.True(rolemasterOpenEnded.Succeeded);
Assert.False(emptyExpression.Succeeded);
Assert.False(badFormat.Succeeded);
Assert.False(tooManyDice.Succeeded);
Assert.False(tooManySides.Succeeded);
Assert.False(tooLargeModifier.Succeeded);
Assert.False(negativeDndModifier.Succeeded);
Assert.False(invalidRolemasterFormat.Succeeded);
Assert.False(tooNegativeRolemasterModifier.Succeeded);
Assert.False(unknownRulesetExpression.Succeeded);
Assert.Equal("2d10-15", rolemasterInitiative.Value!.Canonical);
Assert.Equal(DiceExpressionKind.RolemasterInitiative, rolemasterInitiative.Value.Kind);
Assert.Equal("d100+4", rolemasterPercentile.Value!.Canonical);
Assert.Equal(DiceExpressionKind.RolemasterPercentile, rolemasterPercentile.Value.Kind);
Assert.Equal("d100!+85", rolemasterOpenEnded.Value!.Canonical);
Assert.Equal(DiceExpressionKind.RolemasterOpenEndedPercentile, rolemasterOpenEnded.Value.Kind);
Assert.Equal("d6", DiceRules.ToRulesetId(RulesetKind.D6));
Assert.Equal("dnd5e", DiceRules.ToRulesetId(RulesetKind.Dnd5e));
Assert.Equal("rolemaster", DiceRules.ToRulesetId(RulesetKind.Rolemaster));
Assert.Throws<ArgumentOutOfRangeException>(() => DiceRules.ToRulesetId((RulesetKind)99));
}
}
}

View File

@@ -14,9 +14,11 @@ public sealed class ServiceCampaignTests
service.Register("gm", "Password123", "GM");
var gmSession = ServiceTestSupport.GetValue(service.Login("gm", "Password123")).SessionToken;
var campaign = ServiceTestSupport.GetValue(service.CreateCampaign(gmSession, "Name", "d6"));
var rolemasterCampaign = ServiceTestSupport.GetValue(service.CreateCampaign(gmSession, "Rolemaster Name", "rolemaster"));
var invalidRuleset = service.CreateCampaign(gmSession, "Name 2", "unknown");
Assert.False(invalidRuleset.Succeeded);
Assert.Equal("rolemaster", rolemasterCampaign.RulesetId);
var noCampaignCharacter = service.CreateCharacter(gmSession, "Hero", Guid.NewGuid());
Assert.False(noCampaignCharacter.Succeeded);

View File

@@ -174,4 +174,40 @@ public sealed class ServiceSkillGroupAndOwnershipTests
var campaignAfterDeletes = ServiceTestSupport.GetValue(service.GetCampaign(gmSession, campaign.Id));
Assert.Empty(campaignAfterDeletes.Characters);
}
[Fact]
public void RolemasterSkillDefinitions_CanonicalizeAndKeepLegacyNegativeModifierRules()
{
using var harness = ServiceTestSupport.CreateHarness();
var service = harness.Service;
service.Register("gm-rm", "Password123", "GM");
service.Register("owner-rm", "Password123", "Owner");
var gmSession = ServiceTestSupport.GetValue(service.Login("gm-rm", "Password123")).SessionToken;
var ownerSession = ServiceTestSupport.GetValue(service.Login("owner-rm", "Password123")).SessionToken;
var rolemasterCampaign = ServiceTestSupport.GetValue(service.CreateCampaign(gmSession, "Shadow World", "rolemaster"));
var dndCampaign = ServiceTestSupport.GetValue(service.CreateCampaign(gmSession, "Forgotten Realms", "dnd5e"));
var rolemasterCharacter = ServiceTestSupport.GetValue(service.CreateCharacter(ownerSession, "Harn", rolemasterCampaign.Id));
var dndCharacter = ServiceTestSupport.GetValue(service.CreateCharacter(ownerSession, "Mage", dndCampaign.Id));
var negativeDndSkill = service.CreateSkill(ownerSession, dndCharacter.Id, "Invalid", "1d20-1", 0, false);
Assert.False(negativeDndSkill.Succeeded);
var rolemasterGroup = ServiceTestSupport.GetValue(service.CreateSkillGroup(ownerSession, rolemasterCharacter.Id, "Initiative", "2d10-15", 3, true));
Assert.Equal("2d10-15", rolemasterGroup.DiceRollDefinition);
Assert.Equal(0, rolemasterGroup.WildDice);
Assert.False(rolemasterGroup.AllowFumble);
var percentileSkill = ServiceTestSupport.GetValue(service.CreateSkill(ownerSession, rolemasterCharacter.Id, "Perception", "1d100-20", 4, true));
Assert.Equal("d100-20", percentileSkill.DiceRollDefinition);
Assert.Equal(0, percentileSkill.WildDice);
Assert.False(percentileSkill.AllowFumble);
var openEndedSkill = ServiceTestSupport.GetValue(service.UpdateSkill(ownerSession, percentileSkill.Id, "Perception", "1d100!+85", 5, true));
Assert.Equal("d100!+85", openEndedSkill.DiceRollDefinition);
Assert.Equal(0, openEndedSkill.WildDice);
Assert.False(openEndedSkill.AllowFumble);
}
}