Implement SkillTree data structure with SkillNode, prerequisites, tiers, and tree traversal #227
Labels
No labels
Blocked
Duplicate
MoSCoW/Could Have
MoSCoW/Must Have
MoSCoW/Should Have
Points/1
Points/13
Points/2
Points/21
Points/3
Points/5
Points/8
Priority/Backlog
Priority/Critical
Priority/High
Priority/Low
Priority/Medium
State/Completed
State/In progress
State/In review
State/Paused
State/Unverified
State/Verified
State/Wont Do
Type/Bug
Type/Epic
Type/Feature
Type/Legendary
Type/Task
Type/Testing
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Blocks
#223 Epic: Skill Tree Data Model & Storage
aethyr/Aethyr
Reference: aethyr/Aethyr#227
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Metadata
feature/m4-skill-tree-data-structurefeat(skills): implement SkillTree data structure with SkillNode, prerequisites, tiers, and tree traversalBackground and Context
The skill system in Aethyr requires a flexible, graph-based data structure to represent skill trees. Each discipline (Combat, Survival, Crafting, Social, Magic) has its own tree of skill nodes arranged in tiers with prerequisite chains. The
SkillTreeclass serves as the central data model that all other skill-related features depend on.The
SkillTreeholds a directed acyclic graph (DAG) ofSkillNodeobjects. EachSkillNoderepresents a single learnable skill with progression levels. Nodes are connected by prerequisite relationships — a player must reach a certain level in prerequisite nodes before unlocking dependent ones.This is the foundational building block for the entire Character Progression & Skills legendary. Every subsequent issue in this legendary depends on this data structure being correct and performant.
Expected Behavior
SkillNode class with attributes:
name(String) — unique identifier for the node (e.g.,"combat","swordplay").discipline(Symbol) — the root discipline this node belongs to (:combat,:survival, etc.).tier(Integer) — the depth level in the tree (0 = root, 1 = first branch, etc.).prerequisites(Array of Hash) — list of{name: "node_name", level: N}entries required to unlock this node.xp_required(Integer) — XP needed per level, default 10000.current_xp(Integer) — current XP accumulated toward next level (player-specific, not stored here).max_level(Integer) — maximum achievable level for this node, default 10.description(String) — human-readable description of the skill.SkillTree class with methods:
initialize(nodes: [])— build the tree from a list of SkillNode definitions.lookup(name)— find a node by name, returnsSkillNodeornil. O(1) via hash lookup.list_by_discipline(discipline)— return all nodes for a given discipline, sorted by tier.check_unlockable(player)— return all nodes the player meets prerequisites for but hasn't unlocked.children_of(node_name)— return all nodes that havenode_nameas a prerequisite.root_nodes— return all tier-0 nodes.validate!— verify no circular dependencies, all prerequisites reference existing nodes.Graph Integrity:
validate!raisesSkillTree::CyclicDependencyErrorif cycles are detected.validate!raisesSkillTree::MissingPrerequisiteErrorotherwise.Acceptance Criteria
SkillNodeclass exists atlib/aethyr/core/skills/skill_node.rbwith all specified attributes.SkillTreeclass exists atlib/aethyr/core/skills/skill_tree.rbwith all specified methods.lookupis O(1) using an internal@nodes_by_namehash.list_by_disciplinereturns nodes sorted by tier ascending.check_unlockablecorrectly evaluates prerequisite levels against player skill data.validate!detects cyclic dependencies and missing prerequisites.children_ofreturns correct dependents for any node.Aethyr::Core::Skillsmodule namespace.Subtasks
lib/aethyr/core/skills/skill_node.rbwith theSkillNodeclass and all attributes.lib/aethyr/core/skills/skill_tree.rbwith theSkillTreeclass.initializeto build@nodes_by_namehash and@nodes_by_disciplinegrouped hash.lookup(name)with O(1) hash access.list_by_discipline(discipline)with tier sorting.check_unlockable(player)that inspectsplayer.info["skills"]for prerequisite levels.children_of(node_name)by scanning prerequisites.root_nodesreturning tier-0 nodes.validate!with cycle detection (topological sort) and missing-prerequisite checks.CyclicDependencyError,MissingPrerequisiteError.tests/unit/skill_tree.featurecovering node lookup, discipline listing, unlockable checking, cycle detection, missing prerequisite detection, children traversal.tests/integration/for skill tree loading and validation.bundle exec rake unit_profileand verify no performance regressions.bundle exec rake unit. If coverage is <97% then review the current unit test coverage report atbuild/tests/unit/coverage/and use it to write new Cucumber based unit tests to improve code coverage. Specifically, write Cucumber/Gherkin style unit tests that are descriptively named and specifically improve coverage on whichever file has the most uncovered lines by writing tests that will target the uncovered lines in the report. Once that is done rerunbundle exec rake unitto verify all tests pass and coverage is above >=97%. Only mark this as complete once coverage is >=97%, if not repeat this task as many times as is needed until coverage reaches >=97%.bundle exec rake(default task: unit tests with coverage) andbundle exec rake integration, fix any errors if needed ensuring both pass across entire code base, do not ignore any failure even if it seems unrelated to this commit, fix it.Definition of Done
This issue is complete when:
master, reviewed, and merged before this issue is marked done.