refactor: class-based units and abilities#269
Merged
Conversation
Introduce abstract base classes for the class-based ability architecture. Ability provides unit reference, abstract description/meta, and a static .with() factory for deferred config. Action and Sense extend it with void and any return types respectively. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert walk, attack, shoot, bind, rescue, pivot, rest, and detonate from curried factory functions to classes extending Action. Abilities with config params define static .with() methods returning AbilityBindings. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert feel, look, listen, health, maxHealth, think, directionOf, directionOfStairs, and distanceOf from curried factory functions to classes extending Sense. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove old Ability interface and AbilityCreator type. Fix AbilityBinding to use a concrete constructor signature compatible with subclass constructors. Export AbilityMeta instead of removed types. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace ability.action boolean with instanceof Action in getNextTurn and getAbilities. Add @warriorjs/abilities as core dependency. Update loadLevel to handle AbilityBinding, bare classes, and legacy factories. Update tests to use class-based abilities. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Handle AbilityBinding, bare classes, and legacy factories when reading ability metadata for types.ts generation. Use instanceof Action for action/sense classification. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace factory function calls with AbilityBinding (.with()) and bare class references in unit ability declarations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace factory function calls with .with() bindings and bare class references in both tower definitions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Units are now classes extending Unit from core, with MeleeUnit and
RangedUnit abstract intermediaries providing shared playTurn behavior.
Tower configs use { unit: new Sludge(), position: ... } instead of
spreading plain objects. Engine handles both formats via
loadUnitFromInstance/loadUnitFromConfig. Deep clone preserves class
instances.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
be78d3a to
3a7078f
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #269 +/- ##
==========================================
- Coverage 96.80% 96.29% -0.51%
==========================================
Files 98 101 +3
Lines 1595 1647 +52
Branches 368 373 +5
==========================================
+ Hits 1544 1586 +42
- Misses 41 50 +9
- Partials 10 11 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
The Powder Keep tips and clues reference method calls players write (e.g. warrior.feel().isEmpty()), not ability config declarations. The parentheses were incorrectly removed during the class-based refactor. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename ability files from camelCase to PascalCase (e.g., attack.ts → Attack.ts) to match the exported class names. Update all imports across abilities, units, core, cli, and tower packages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move readonly fields (description, meta) before private fields and reorder constructor assignments for consistency. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move the foundational ability base classes and types (Ability, Action, Sense, AbilityBinding, AbilityMeta) from @warriorjs/abilities to @warriorjs/core. Core no longer depends on abilities; abilities re-exports the base classes from core. Tests for base classes move to core; concrete ability tests import from @warriorjs/core. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the local Ability interface in Unit.ts with an import of the Ability class from core, removing the duplicate definition. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Effect base class to core with abstract passTurn/trigger methods. Convert ticking from a curried factory to a Ticking class extending Effect with static .with() for config. Update loadEffects to handle both class bindings and legacy factories. Remove local Effect interface from Unit.ts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add EffectBinding type to core's Effect.ts mirroring AbilityBinding, and export from both core and effects packages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename ticking.ts to Ticking.ts to match the class name, consistent with the abilities package convention. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4a7343b to
37b5bbb
Compare
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove re-exports of Ability, Action, Sense, AbilityBinding, AbilityMeta, Effect, and EffectBinding from @warriorjs/abilities and @warriorjs/effects. Consumers now import these directly from @warriorjs/core. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace TowerFloorUnit with TowerUnitEntry and TowerWarriorEntry. Remove loadUnitFromConfig and the legacy factory paths in loadAbilities and loadEffects — units are always class instances now. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tower configs now declare unit classes (e.g. unit: Sludge) instead of instances (unit: new Sludge()). The engine instantiates them at level load time, consistent with how ability classes are already handled. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consistent with the Powder Keep style. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove Warrior from @warriorjs/units — each tower defines its own sharedWarriorConfig typed as Pick<WarriorConfig, ...> - Replace UnitConfig and TowerWarriorEntry with WarriorConfig - Rename TowerUnitEntry to UnitConfig (the natural name now that the legacy plain-object format is gone) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add WarriorDefinition, WarriorOverrides, and LevelDefinition types for the tower definition format. Update getLevelConfig to accept TowerDefinition and merge tower.warrior with level.warrior at config resolution time. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tower constructor now accepts warrior (WarriorDefinition) and uses LevelDefinition for levels. Update loadTowers to extract warrior from tower modules. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Define warrior identity (character, color, maxHealth) once at the tower level instead of spreading sharedWarriorConfig into every level. Each level now only declares abilities and position. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add optional static declaredAbilities to the Unit base class and a UnitClass interface for the constructor + static shape. The engine reads abilities from the class at load time, removing the any cast. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add AbilityClass, EffectClass interfaces alongside AbilityBinding and EffectBinding. Export AbilityEntry and EffectEntry union types. Move UnitClass interface to Unit.ts. All Record<string, any> in config types are now properly typed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…orts These are implementation details used only within types.ts. External consumers use AbilityBinding/AbilityEntry and EffectBinding/EffectEntry. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Convert playTurn from a constructor-assigned arrow function to a class method on Unit, MeleeUnit, and RangedUnit. Add exported Turn type for the public turn interface and internal TurnState for engine tracking. Initialize turn as null instead of empty object. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove duplicated playTurn behavior tests from Sludge, ThickSludge, Archer, and Wizard — now covered by MeleeUnit and RangedUnit tests. Concrete tests focus on identity and declared abilities only. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Action/Senseclasses extending anAbilitybase class, using.with()for deferred configMeleeUnit/RangedUnitabstract intermediaries that encapsulate sharedplayTurnbehaviorloadLevel,getNextTurn,getAbilities) to useinstanceof Actioninstead ofability.actionboolean, and handle both class instances and legacy config formatsrenderTypesfor the new ability/unit patternsTest plan
runLevel.test.ts) exercise the full pipeline end-to-end🤖 Generated with Claude Code