Entities¶
The entities module provides the base classes for all game characters, NPCs, and enemies, along with the stats and AI systems.
Entity Base Classes¶
Base entity system for characters, NPCs, and enemies.
This module provides the base Entity class that all game entities inherit from.
- class barebones_rpg.entities.entity.Entity(*, id=<factory>, name, description='', stats=<factory>, inventory_slots=20, inventory=None, equipment=None, equipped_items=<factory>, faction='neutral', can_act=True, position=(0, 0), ai=None, metadata=<factory>)[source]¶
Bases:
BaseModelBase class for all entities in the game (characters, NPCs, enemies).
Entities have stats, can participate in combat, and can be extended with custom behavior.
Example
>>> hero = Entity(name="Hero", stats=Stats(hp=100, atk=15)) >>> goblin = Entity(name="Goblin", stats=Stats(hp=30, atk=5)) >>> hero.stats.hp -= 10 # Take damage >>> print(hero.is_alive()) True
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- __init__(**data)[source]¶
Create a new model by parsing and validating input data from keyword arguments.
Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.
self is explicitly positional-only to allow self as a field name.
- property stats_manager: StatsManager¶
Get the stats manager for this entity.
- take_damage(amount, source=None, damage_type='physical')[source]¶
Take damage from an attack.
- Parameters:
- Return type:
- Returns:
Actual damage taken after defense and resistance calculations
Note
Damage calculation: final = max(0, starting - defense - (resistance * starting)) - Defense provides flat reduction - Resistance provides percentage reduction (-1.0 to 1.0) - Positive resistance reduces damage (0.5 = 50% reduction) - Negative resistance increases damage (-0.5 = 50% extra damage, i.e., weakness) - Both defense and resistance can be applied simultaneously
- can_perform_action()[source]¶
Check if entity can perform an action.
- Return type:
- Returns:
True if entity can act
- init_equipment()[source]¶
Initialize equipment for this entity.
- Return type:
- Returns:
The created Equipment instance
- register_action(action_name, callback)[source]¶
Register a custom action for this entity.
This allows extending entities with custom behavior.
- class barebones_rpg.entities.entity.Character(*, id=<factory>, name, description='', stats=<factory>, inventory_slots=20, inventory=None, equipment=None, equipped_items=<factory>, faction='player', can_act=True, position=(0, 0), ai=None, metadata=<factory>, character_class='warrior', title='')[source]¶
Bases:
EntityPlayer character class.
Extends Entity with character-specific features like experience and leveling.
- gain_exp(amount, events=None)[source]¶
Gain experience points.
- Parameters:
amount (
int) – Experience to gainevents (
Optional[EventManager]) – Event manager to publish level up events
- Return type:
- Returns:
True if leveled up
- level_up(stat_points_per_level=3)[source]¶
Level up the character.
- Parameters:
stat_points_per_level (
int) – Number of stat points to award (default: 3)- Return type:
This can be overridden to customize stat growth. The default implementation gives unallocated stat points that can be spent on any stat. Games can override this to auto-allocate, use different point values, or restrict what stats can be increased.
- allocate_stat_point(stat_name, amount=1)[source]¶
Allocate stat points to increase a stat.
This method is fully generic - it can increase any stat (primary attributes or derived substats). Games can override this to add restrictions.
- Parameters:
- Return type:
- Returns:
True if allocation was successful, False if not enough points
Example
>>> character.allocate_stat_point("strength", 2) # Increase STR by 2 >>> character.allocate_stat_point("training_speed", 1) # Train speed substat
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class barebones_rpg.entities.entity.NPC(*, id=<factory>, name, description='', stats=<factory>, inventory_slots=20, inventory=None, equipment=None, equipped_items=<factory>, faction='neutral', can_act=True, position=(0, 0), ai=None, metadata=<factory>, dialog_tree_id=None, quest_ids=<factory>, is_merchant=False, merchant_inventory=<factory>)[source]¶
Bases:
EntityNon-player character class.
NPCs can have dialog, quests, and custom behavior.
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class barebones_rpg.entities.entity.Enemy(*, id=<factory>, name, description='', stats=<factory>, inventory_slots=20, inventory=None, equipment=None, equipped_items=<factory>, faction='enemy', can_act=True, position=(0, 0), ai=None, metadata=<factory>, ai_type='aggressive', exp_reward=10, gold_reward=5, loot_table=<factory>, aggro_range=5)[source]¶
Bases:
EntityEnemy character class.
Enemies have AI behavior and drop items/exp when defeated.
The loot_table supports both string references (looked up in LootRegistry) and direct Item objects for procedural generation:
Example
>>> from barebones_rpg.items import create_material >>> >>> # Using string references (requires LootRegistry setup) >>> goblin = Enemy( ... name="Goblin", ... loot_table=[ ... {"item": "Goblin Bone", "chance": 0.3}, ... {"item": "Health Potion", "chance": 0.1} ... ] ... ) >>> >>> # Using direct Item objects (code-first) >>> goblin = Enemy( ... name="Goblin", ... loot_table=[ ... {"item": create_material("Bone", value=5), "chance": 0.3} ... ] ... )
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
Stats System¶
Stats system for entities.
This module provides the stats system used by all entities (characters, NPCs, enemies). Stats are flexible and can be extended for different game types.
- class barebones_rpg.entities.stats.Stats(**data)[source]¶
Bases:
BaseModelBase stats for an entity using attribute-based system.
Primary Attributes (core stats that determine derived values): - STR (Strength): Physical damage, melee power - CON (Constitution): HP, physical defense - INT (Intelligence): Magic damage, MP, magic defense - DEX (Dexterity): Speed, accuracy, evasion, critical chance - CHA (Charisma): Dialog, persuasion, prices
Derived Substats are calculated from attributes + training bonuses.
Example
>>> stats = Stats(strength=15, constitution=12, intelligence=10) >>> stats.hp -= 20 >>> print(stats.hp) 100 >>> stats.allocate_stat_points("strength", 2) # Direct allocation >>> print(stats.strength) 17
- model_config: ClassVar[ConfigDict] = {'extra': 'allow'}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_post_init(_Stats__context)[source]¶
Initialize max HP/MP after creation if not explicitly set.
- get_resistance(damage_type)[source]¶
Get resistance value for a damage type.
- Parameters:
damage_type (
str) – Name of the damage type- Returns:
Positive values = resistance (0.5 = 50% damage reduction)
Negative values = weakness (-0.5 = 50% extra damage)
0.0 = no resistance or weakness
- Return type:
Resistance value (-1.0 to 1.0)
- class barebones_rpg.entities.stats.StatusEffect(**data)[source]¶
Bases:
BaseModelA status effect that can be applied to an entity.
Examples: poisoned, stunned, buffed, etc.
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class barebones_rpg.entities.stats.StatsManager(base_stats)[source]¶
Bases:
objectManages stats and status effects for an entity.
This provides a layer on top of Stats that handles temporary modifiers, status effects, and stat change events.
- __init__(base_stats)[source]¶
Initialize the stats manager.
- Parameters:
base_stats (
Stats) – The base stats for the entity
- get_effective_stat(stat_name, default=0)[source]¶
Get the effective value of a stat including all modifiers.
- add_status_effect(effect)[source]¶
Add a status effect.
- Parameters:
effect (
StatusEffect) – The status effect to add- Return type:
- Returns:
True if status effect was added successfully
AI Interface¶
AI interface system for entity behavior.
This module provides a flexible interface for implementing custom AI behavior for NPCs and enemies. Users can implement their own AI using any approach: state machines, behavior trees, LLM-based decision making, etc.
- class barebones_rpg.entities.ai_interface.AIContext(**data)[source]¶
Bases:
BaseModelContext information for AI decision making.
Provides common fields and a metadata dict for custom context.
Example
>>> context = AIContext( ... entity=goblin, ... nearby_entities=[player, other_goblin], ... metadata={"location": current_location, "combat": combat_instance} ... )
- model_config: ClassVar[ConfigDict] = {'arbitrary_types_allowed': True}¶
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class barebones_rpg.entities.ai_interface.AIInterface[source]¶
Bases:
ABCBase interface for AI implementations.
Implement decide_action() to create custom AI behavior. Users can implement this for any AI approach: - Simple state machines - Behavior trees - Utility-based AI - LLM-based decision making - Rule-based systems
Example
>>> class AggressiveMeleeAI(AIInterface): ... def decide_action(self, context: AIContext) -> dict: ... if context.nearby_entities: ... target = context.nearby_entities[0] ... return {"action": "attack", "target": target} ... return {"action": "wait"} >>> >>> goblin = Enemy(name="Goblin", ai=AggressiveMeleeAI())
- abstractmethod decide_action(context)[source]¶
Decide what action to take based on the current context.
- Parameters:
context (
AIContext) – AIContext with entity state and custom metadata- Return type:
- Returns:
Dict with “action” key and action-specific data. Common actions: “attack”, “move”, “use_skill”, “use_item”, “wait”, “flee”
Examples
{“action”: “attack”, “target”: enemy} {“action”: “move”, “position”: (10, 5)} {“action”: “use_skill”, “skill”: “fireball”, “target”: enemy} {“action”: “wait”}
Example
>>> def decide_action(self, context: AIContext) -> dict: ... entity = context.entity ... if entity.stats.hp < entity.stats.max_hp * 0.3: ... return {"action": "flee"} ... elif context.nearby_entities: ... target = context.nearby_entities[0] ... return {"action": "attack", "target": target} ... return {"action": "wait"}
AI Implementations¶
AI systems for entities.
This module provides AI behavior for NPCs and enemies, including pathfinding-based movement and decision making using the AIInterface.
- class barebones_rpg.entities.ai.SimplePathfindingAI(pathfinder, attack_range=1, max_moves=3)[source]¶
Bases:
AIInterfaceSimple pathfinding-based AI for enemies.
This AI will: - Move toward a target using pathfinding - Attack if adjacent to target - Spend available action points efficiently
- Parameters:
pathfinder (
TilemapPathfinder) – The pathfinder to use for navigationattack_range (
int) – Range at which entity can attack (default: 1)max_moves (
int) – Maximum moves per turn (default: 3)
- __init__(pathfinder, attack_range=1, max_moves=3)[source]¶
Initialize the AI.
- Parameters:
pathfinder (
TilemapPathfinder) – The pathfinder to use for navigationattack_range (
int) – Range at which entity can attackmax_moves (
int) – Maximum moves per turn
- class barebones_rpg.entities.ai.TacticalAI(pathfinder, flee_hp_threshold=0.3, attack_range=1, max_moves=3)[source]¶
Bases:
AIInterfaceMore advanced tactical AI with behavior modes.
This AI can: - Chase and attack - Flee when low health - Patrol between points - Guard a specific location
- Parameters:
pathfinder (
TilemapPathfinder) – The pathfinder to use for navigationflee_hp_threshold (
float) – HP percentage threshold for fleeing (default: 0.3)attack_range (
int) – Attack range (default: 1)max_moves (
int) – Maximum moves per turn (default: 3)
- __init__(pathfinder, flee_hp_threshold=0.3, attack_range=1, max_moves=3)[source]¶
Initialize the tactical AI.
- Parameters:
pathfinder (
TilemapPathfinder) – The pathfinder to use for navigationflee_hp_threshold (
float) – HP percentage threshold for fleeingattack_range (
int) – Attack rangemax_moves (
int) – Maximum moves per turn
- decide_action(context)[source]¶
Decide what action to take based on context.
This implementation considers health status: - If HP below threshold, flees from nearest enemy - Otherwise, behaves like SimplePathfindingAI