Files
TheriapolisV3/Theriapolis.Core/Rules/Stats/Size.cs
T
Christopher Wiebe b451f83174 Initial commit: Theriapolis baseline at port/godot branch point
Captures the pre-Godot-port state of the codebase. This is the rollback
anchor for the Godot port (M0 of theriapolis-rpg-implementation-plan-godot-port.md).
All Phase 0 through Phase 6.5 work is included; Phase 7 is in flight.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-30 20:40:51 -07:00

67 lines
2.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
namespace Theriapolis.Core.Rules.Stats;
/// <summary>
/// Body-size category from clades.md. Determines tactical-tile footprint,
/// reach, equipment fit, and grappling rules.
/// </summary>
public enum SizeCategory : byte
{
Tiny = 0, // reserved; no Phase 5 species uses this
Small = 1, // rabbit-folk, housecat-folk, ferret-folk
Medium = 2, // fox-folk, deer-folk, ram-folk, leopard-folk, badger-folk, hare-folk
MediumLarge = 3, // wolf-folk, elk-folk, lion-folk, wolverine-folk, coyote-folk
Large = 4, // brown bear-folk, polar bear-folk, moose-folk, bull-folk, bison-folk
Huge = 5, // reserved; no Phase 5 species uses this
}
public static class SizeExtensions
{
/// <summary>Tactical-tile footprint per side (1 = 1×1, 2 = 2×2).</summary>
public static int FootprintTiles(this SizeCategory s) => s switch
{
SizeCategory.Tiny => 1,
SizeCategory.Small => 1,
SizeCategory.Medium => 1,
SizeCategory.MediumLarge => 1, // counts as Large for grappling/carrying only
SizeCategory.Large => 2,
SizeCategory.Huge => 3,
_ => throw new ArgumentOutOfRangeException(nameof(s)),
};
/// <summary>Default melee reach in tactical tiles (weapon-modifiable).</summary>
public static int DefaultReachTiles(this SizeCategory s) => s switch
{
SizeCategory.Tiny => 1,
SizeCategory.Small => 1,
SizeCategory.Medium => 1,
SizeCategory.MediumLarge => 1,
SizeCategory.Large => 2,
SizeCategory.Huge => 3,
_ => throw new ArgumentOutOfRangeException(nameof(s)),
};
/// <summary>Carrying-capacity multiplier per equipment.md (Small ½×, Large 2×).</summary>
public static float CarryCapacityMult(this SizeCategory s) => s switch
{
SizeCategory.Tiny => 0.25f,
SizeCategory.Small => 0.5f,
SizeCategory.Medium => 1.0f,
SizeCategory.MediumLarge => 1.0f, // Medium frame, Large for grappling
SizeCategory.Large => 2.0f,
SizeCategory.Huge => 4.0f,
_ => throw new ArgumentOutOfRangeException(nameof(s)),
};
/// <summary>Parses a snake_case JSON value (e.g. "medium_large") into a SizeCategory.</summary>
public static SizeCategory FromJson(string? raw) => raw switch
{
"tiny" => SizeCategory.Tiny,
"small" => SizeCategory.Small,
"medium" => SizeCategory.Medium,
"medium_large" => SizeCategory.MediumLarge,
"large" => SizeCategory.Large,
"huge" => SizeCategory.Huge,
_ => throw new ArgumentException($"Unknown size category: '{raw}'"),
};
}