The problem I needed to solve
If the shared core starts knowing Hokm and Pasur, every additional game becomes more costly. I wanted validation, winner evaluation and scoring to be separately definable.
Implementation in this snapshot
IGameRuleSet declares ValidateCardPlay, EvaluateRoundWinner and CalculateScore. Each receives its own context and returns its own result; CoreRuleSystem invokes these contracts.
The design decision and its cost
A small contract keeps generic logic from assuming a particular rule. However, not every complex game flow fits into those three functions, and specialized services can still be necessary.
Current boundaries
The documentation includes a Hokm RuleSet as an extension example. I do not treat that example as proof of a final scene-wired class; Hokm also runs through its specialized services.
Calculating a score before applying it
In a card game, asking whether a move is legal differs from asking who receives points. IGameRuleSet expresses these decisions through separate contexts and results, and CoreRuleSystem delegates to the chosen implementation. The wrapper adds no suit or rank rules. For Dalo, this makes each decision’s inputs explicit. The limitation is equally clear: if a context lacks information required by a game, the generic contract alone cannot model every stage.
CoreRuleSystem.ApplyScore illustrates separation between calculation and mutation. It ignores null or unchanged results, iterates ScoreChanges and adds each amount to the corresponding player’s Score. Changes without a Player are skipped rather than rejected. Readers should understand that applying a calculated report does not necessarily fail loudly. A consumer requiring every change to apply must validate the result before entering that loop.
The loop has no operation ID or record of previously applied results. Reapplying a result containing changes can add those points again; RuleSystem does not automatically provide duplicate protection. This is why I distinguish the generic contract from Hokm’s specialized services. The core documentation’s RuleSet example explains an extension path, but does not prove that the example class runs in the current scene. Claims about active wiring need scene references and construction paths, rather than an instructional excerpt alone.
What this stage taught me
For me, this was an exercise in boundaries. The core provides capabilities and the game makes decisions. Adding a game should not mean filling the core with conditions on game names.




