Files
core2026/docs/architecture/legacy-engine-constraints.md
T

2.3 KiB
Raw Blame History

Legacy Constraint System

This document describes the constraint framework used to validate command preconditions. References include legacy/hwe/sammo/Constraint/Constraint.php and legacy/hwe/sammo/Constraint/ConstraintHelper.php.

Core Concepts

Constraints are reusable predicate classes that validate a commands inputs and state. They are built per-command and executed in order:

  • Each constraint extends Constraint and implements test().
  • Constraint::testAll() iterates a list of constraints and returns the first failure [constraintName, reason] or null for success.
  • BaseCommand::hasFullConditionMet() uses these to decide command validity.

Required Input Flags

Constraints declare required inputs using bit flags:

  • REQ_GENERAL, REQ_CITY, REQ_NATION
  • REQ_DEST_GENERAL, REQ_DEST_CITY, REQ_DEST_NATION
  • REQ_ARG with typed sub-flags:
    • REQ_STRING_ARG, REQ_INT_ARG, REQ_NUMERIC_ARG, REQ_BOOLEAN_ARG, REQ_ARRAY_ARG, REQ_BACKED_ENUM_ARG

Constraint::checkInputValues() enforces these expectations and throws if inputs are missing or malformed.

Some constraints expect general.aux to be preloaded as auxVar. Command evaluation calls General::unpackAux() before constraint checks to satisfy these requirements.

Constraint Helper DSL

ConstraintHelper provides factory-style helpers used in command definitions:

  • Examples: AllowWar(), NearCity($distance), ReqGeneralGold($amount), NotOccupiedDestCity(), AllowDiplomacyStatus(...), etc.
  • These helpers return [ConstraintName, arg] tuples consumed by Constraint::testAll().

Common Constraint Classes

Constraints are organized by domain:

  • Diplomacy: AllowDiplomacyStatus, AllowDiplomacyBetweenStatus.
  • Nation/City: OccupiedCity, NotCapital, RemainCityCapacity.
  • General: ReqGeneralCrew, ReqGeneralGold, MustBeTroopLeader.
  • Routing: HasRoute, HasRouteWithEnemy.

Each constraint sets a failure reason string used by UI and logs.

Rewrite References

Rewrite constraint contracts and runtime split details live in docs/architecture/rewrite-constraints.md.

Open Questions / Follow-ups

  • Some constraints rely on env values (turnterm, year, etc.); document each commands exact env payload when porting.