- Restructure docs/ into hierarchical organization (00-overview → 04-reference) - Eliminate duplicate global/ directory (-16 files) - Integrate toCheck/ content into main structure - Update CLAUDE.md with new documentation architecture - Remove legacy engine references - Consolidate 53 → 32 documentation files (-40% reduction) - Add proper navigation README.md with clear entry points New structure: 📁 00-overview/ - Vision & context 📁 01-architecture/ - Technical architecture 📁 02-systems/ - Game systems 📁 03-implementation/ - Testing & configuration 📁 04-reference/ - Technical reference 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
305 lines
8.8 KiB
Markdown
305 lines
8.8 KiB
Markdown
# Behavior Composition Patterns - Warfactory
|
|
|
|
**Philosophy** : Modules comportements combinables via configuration JSON pour AI flexibility
|
|
|
|
## Point 46 : Behavior Composition Pattern
|
|
|
|
### Concept Core
|
|
|
|
**Modular Behaviors** : Chaque comportement AI = module autonome combinable
|
|
|
|
```cpp
|
|
// Base behavior interface
|
|
class IBehaviorModule : public IModule {
|
|
public:
|
|
virtual json process(const json& context) = 0;
|
|
virtual float getWeight() const = 0;
|
|
virtual bool shouldActivate(const json& triggers) const = 0;
|
|
};
|
|
```
|
|
|
|
### Behavior Module Examples
|
|
|
|
#### AggressiveBehavior Module
|
|
```cpp
|
|
class AggressiveBehavior : public IBehaviorModule {
|
|
json process(const json& context) override {
|
|
auto enemy_detected = context["enemy_detected"].get<bool>();
|
|
auto health = context["health"].get<float>();
|
|
|
|
if (enemy_detected && health > 50.0f) {
|
|
return {
|
|
{"action", "attack"},
|
|
{"priority", "high"},
|
|
{"target_selection", "closest_enemy"}
|
|
};
|
|
}
|
|
|
|
return {{"action", "patrol"}};
|
|
}
|
|
|
|
float getWeight() const override { return 0.8f; } // High aggression
|
|
|
|
bool shouldActivate(const json& triggers) override {
|
|
return triggers.contains("enemy_nearby") || triggers.contains("under_attack");
|
|
}
|
|
};
|
|
```
|
|
|
|
#### CautiousBehavior Module
|
|
```cpp
|
|
class CautiousBehavior : public IBehaviorModule {
|
|
json process(const json& context) override {
|
|
auto health = context["health"].get<float>();
|
|
auto enemy_count = context["enemy_count"].get<int>();
|
|
|
|
if (health < 30.0f || enemy_count > 2) {
|
|
return {
|
|
{"action", "retreat"},
|
|
{"priority", "critical"},
|
|
{"retreat_direction", "base"}
|
|
};
|
|
}
|
|
|
|
return {{"action", "defensive_position"}};
|
|
}
|
|
|
|
float getWeight() const override { return 0.6f; } // Moderate caution
|
|
|
|
bool shouldActivate(const json& triggers) override {
|
|
return triggers.contains("low_health") || triggers.contains("outnumbered");
|
|
}
|
|
};
|
|
```
|
|
|
|
#### EconomicBehavior Module
|
|
```cpp
|
|
class EconomicBehavior : public IBehaviorModule {
|
|
json process(const json& context) override {
|
|
auto resources = context["resources"].get<int>();
|
|
auto factory_status = context["factory_active"].get<bool>();
|
|
|
|
if (resources < 100 && factory_status) {
|
|
return {
|
|
{"action", "gather_resources"},
|
|
{"priority", "medium"},
|
|
{"resource_type", "preferred"}
|
|
};
|
|
}
|
|
|
|
return {{"action", "optimize_production"}};
|
|
}
|
|
|
|
float getWeight() const override { return 0.4f; } // Economic focus
|
|
|
|
bool shouldActivate(const json& triggers) override {
|
|
return triggers.contains("low_resources") || triggers.contains("economic_opportunity");
|
|
}
|
|
};
|
|
```
|
|
|
|
### Composition Engine
|
|
|
|
#### BehaviorCompositionEngine
|
|
```cpp
|
|
class BehaviorCompositionEngine : public IModule {
|
|
private:
|
|
std::map<std::string, std::unique_ptr<IBehaviorModule>> behaviors;
|
|
json composition_config;
|
|
|
|
public:
|
|
void initialize(const json& config) override {
|
|
composition_config = config["behavior_composition"];
|
|
|
|
// Load configured behavior modules
|
|
for (const auto& behavior_name : composition_config["modules"]) {
|
|
loadBehaviorModule(behavior_name);
|
|
}
|
|
}
|
|
|
|
json process(const json& context) override {
|
|
std::vector<json> behavior_outputs;
|
|
std::vector<float> weights;
|
|
|
|
// Process all active behaviors
|
|
for (const auto& [name, behavior] : behaviors) {
|
|
if (shouldActivateBehavior(name, context)) {
|
|
auto output = behavior->process(context);
|
|
behavior_outputs.push_back(output);
|
|
weights.push_back(getBehaviorWeight(name));
|
|
}
|
|
}
|
|
|
|
// Compose final decision
|
|
return composeBehaviors(behavior_outputs, weights);
|
|
}
|
|
|
|
private:
|
|
bool shouldActivateBehavior(const std::string& name, const json& context) {
|
|
auto triggers = extractTriggers(context);
|
|
return behaviors[name]->shouldActivate(triggers);
|
|
}
|
|
|
|
float getBehaviorWeight(const std::string& name) {
|
|
auto weights = composition_config["weights"];
|
|
if (weights.contains(name)) {
|
|
return weights[name].get<float>();
|
|
}
|
|
return behaviors[name]->getWeight();
|
|
}
|
|
|
|
json composeBehaviors(const std::vector<json>& outputs, const std::vector<float>& weights) {
|
|
// Weighted decision composition
|
|
json final_decision;
|
|
float total_weight = 0.0f;
|
|
|
|
// Calculate weighted priorities
|
|
for (size_t i = 0; i < outputs.size(); ++i) {
|
|
auto priority = getPriorityValue(outputs[i]["priority"]);
|
|
auto weighted_priority = priority * weights[i];
|
|
|
|
if (weighted_priority > total_weight) {
|
|
final_decision = outputs[i];
|
|
total_weight = weighted_priority;
|
|
}
|
|
}
|
|
|
|
return final_decision;
|
|
}
|
|
};
|
|
```
|
|
|
|
### Configuration-Driven Composition
|
|
|
|
#### Example Configuration
|
|
```json
|
|
{
|
|
"behavior_composition": {
|
|
"modules": ["aggressive", "cautious", "economic"],
|
|
"weights": {
|
|
"aggressive": 0.7,
|
|
"cautious": 0.8,
|
|
"economic": 0.3
|
|
},
|
|
"triggers": {
|
|
"low_health": "switch_to_cautious",
|
|
"enemy_nearby": "activate_aggressive",
|
|
"low_resources": "activate_economic"
|
|
},
|
|
"priority_matrix": {
|
|
"critical": 1.0,
|
|
"high": 0.8,
|
|
"medium": 0.5,
|
|
"low": 0.2
|
|
},
|
|
"dynamic_weights": {
|
|
"health_modifier": {
|
|
"high_health": {"aggressive": 1.2, "cautious": 0.8},
|
|
"low_health": {"aggressive": 0.3, "cautious": 1.5}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Advanced Composition Features
|
|
```json
|
|
{
|
|
"behavior_composition": {
|
|
"modules": ["aggressive", "cautious", "economic", "tactical"],
|
|
"composition_strategy": "weighted_priority",
|
|
"context_modifiers": {
|
|
"time_of_day": {
|
|
"night": {"cautious": 1.3, "aggressive": 0.7},
|
|
"day": {"aggressive": 1.1, "tactical": 1.2}
|
|
},
|
|
"resource_level": {
|
|
"abundant": {"economic": 0.5, "aggressive": 1.3},
|
|
"scarce": {"economic": 1.5, "cautious": 1.2}
|
|
}
|
|
},
|
|
"behavior_transitions": {
|
|
"aggressive_to_cautious": {
|
|
"trigger": "health < 25%",
|
|
"transition_time": 2.0
|
|
},
|
|
"economic_to_aggressive": {
|
|
"trigger": "resources > 500",
|
|
"transition_time": 1.0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Usage Examples
|
|
|
|
#### Tank AI Composition
|
|
```json
|
|
{
|
|
"tank_ai": {
|
|
"modules": ["aggressive", "tactical", "survival"],
|
|
"weights": {"aggressive": 0.8, "tactical": 0.9, "survival": 1.0},
|
|
"context": "combat_heavy"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Economic AI Composition
|
|
```json
|
|
{
|
|
"company_ai": {
|
|
"modules": ["economic", "cautious", "opportunistic"],
|
|
"weights": {"economic": 1.0, "cautious": 0.6, "opportunistic": 0.4},
|
|
"context": "market_trading"
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Diplomatic AI Composition
|
|
```json
|
|
{
|
|
"diplomatic_ai": {
|
|
"modules": ["cooperative", "strategic", "economic"],
|
|
"weights": {"cooperative": 0.7, "strategic": 0.9, "economic": 0.5},
|
|
"context": "international_relations"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Architecture Benefits
|
|
|
|
### Development Advantages
|
|
- **Module Reusability** : Behaviors réutilisables entre différents AI agents
|
|
- **Easy Testing** : Chaque behavior testable indépendamment
|
|
- **Claude-Friendly** : Modules 200 lignes max, comprehensibles par IA
|
|
- **Hot-Reload** : Modification behaviors sans restart système
|
|
|
|
### Gameplay Advantages
|
|
- **AI Diversity** : Combinations créent personnalités AI distinctes
|
|
- **Dynamic Adaptation** : Behaviors s'adaptent selon context/triggers
|
|
- **Emergent Complexity** : Interactions behaviors créent sophistication émergente
|
|
- **Player Customization** : Players peuvent configurer AI allies
|
|
|
|
### Performance Benefits
|
|
- **Selective Activation** : Seuls behaviors pertinents s'activent
|
|
- **Lightweight Composition** : JSON processing minimal overhead
|
|
- **Parallel Processing** : Behaviors processables en parallèle
|
|
- **Efficient Caching** : Composition results cachables
|
|
|
|
## Implementation Strategy
|
|
|
|
### Phase 1 : Core Behaviors
|
|
- Implement basic behavior modules (Aggressive, Cautious, Economic)
|
|
- Simple weighted composition
|
|
- JSON configuration loading
|
|
|
|
### Phase 2 : Advanced Composition
|
|
- Context modifiers et dynamic weights
|
|
- Behavior transitions
|
|
- Priority matrices sophistiquées
|
|
|
|
### Phase 3 : AI Personalities
|
|
- Predefined personality templates
|
|
- Player customization interface
|
|
- Emergent behavior analysis |