Add rules-aware lookup dice rolling

This commit is contained in:
2026-03-15 02:47:10 +01:00
parent 74613724bc
commit cada74c7ac
14 changed files with 540 additions and 8 deletions

View File

@@ -4,6 +4,13 @@ namespace RolemasterDb.App.Features;
public sealed record LookupOption(string Key, string Label);
public sealed record AttackTableReference(
string Key,
string Label,
string AttackKind,
int? FumbleMinRoll,
int? FumbleMaxRoll);
public sealed record CriticalColumnReference(
string Key,
string Label,
@@ -32,7 +39,7 @@ public sealed record CriticalTableReference(
IReadOnlyList<CriticalRollBandReference> RollBands);
public sealed record LookupReferenceData(
IReadOnlyList<LookupOption> AttackTables,
IReadOnlyList<AttackTableReference> AttackTables,
IReadOnlyList<LookupOption> ArmorTypes,
IReadOnlyList<CriticalTableReference> CriticalTables);

View File

@@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace RolemasterDb.App.Features;
public sealed record LookupRollResult(
int Total,
IReadOnlyList<int> Rolls)
{
public bool IsOpenEnded => Rolls.Count > 1;
}

View File

@@ -18,7 +18,12 @@ public sealed class LookupService(IDbContextFactory<RolemasterDbContext> dbConte
var attackTables = await dbContext.AttackTables
.AsNoTracking()
.OrderBy(item => item.DisplayName)
.Select(item => new LookupOption(item.Slug, item.DisplayName))
.Select(item => new AttackTableReference(
item.Slug,
item.DisplayName,
item.AttackKind,
item.FumbleMinRoll,
item.FumbleMaxRoll))
.ToListAsync(cancellationToken);
var armorTypes = await dbContext.ArmorTypes

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace RolemasterDb.App.Features;
public static class RolemasterRoller
{
public static LookupRollResult RollAttack(Random random) =>
RollOpenEndedHigh(random);
public static LookupRollResult RollCritical(Random random, CriticalTableReference? table) =>
AllowsOpenEndedCritical(table)
? RollOpenEndedHigh(random)
: RollStandard(random);
public static bool AllowsOpenEndedCritical(CriticalTableReference? table) =>
table is not null &&
table.RollBands.Any(item => item.MinRoll > 100 || item.MaxRoll is null || item.MaxRoll > 100);
public static LookupRollResult RollStandard(Random random)
{
var roll = random.Next(1, 101);
return new LookupRollResult(roll, [roll]);
}
public static LookupRollResult RollOpenEndedHigh(Random random)
{
var rolls = new List<int>();
var total = 0;
while (true)
{
var roll = random.Next(1, 101);
rolls.Add(roll);
total += roll;
if (roll < 96)
{
break;
}
}
return new LookupRollResult(total, rolls);
}
}