environments

package module
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 23, 2026 License: GPL-3.0 Imports: 14 Imported by: 2

README

Environment Generation Tool - Usage Guide

Overview

The environment generation tool provides a complete system for creating tactical game environments (dungeons, buildings, outdoor areas) using procedural generation. It sits in the Tools layer of the RPG Toolkit architecture and acts as a client-friendly middleware over the spatial module.

Core Philosophy

The environment tool follows the toolkit's philosophy of providing infrastructure, not implementation:

  • Simple wall generation: Just "empty" or "random" patterns
  • Client controls parameters: Density, destructible ratio, materials
  • Fully procedural: No opinionated "maze" or "tactical cover" patterns
  • Maximum flexibility: Games define their own meaning of tactical variety

Quick Start

1. Basic Environment Generation
// Create environment generator
generator := environments.NewGraphBasedGenerator(environments.GraphBasedGeneratorConfig{
    ID:          "dungeon-generator",
    Type:        "procedural",
    EventBus:    eventBus,
    ShapeLoader: environments.NewShapeLoader("assets/shapes"),
})

// Generate environment
config := environments.GenerationConfig{
    RoomCount:  8,
    LayoutType: environments.LayoutTypeOrganic,
    Seed:       12345,
}

environment, err := generator.Generate(config)
2. Simple Room Building
// Create room with random walls
room := environments.NewRoomBuilder(config).
    WithSize(15, 12).
    WithWallPattern("random").
    WithWallDensity(0.4).               // 40% wall density
    WithDestructibleRatio(0.7).         // 70% destructible
    Build()
3. Convenience Functions
// Dense cover room (high wall density 0.6-0.9)
denseCoverRoom := environments.DenseCoverRoom(20, 15)

// Sparse cover room (low wall density 0.1-0.4) 
sparseCoverRoom := environments.SparseCoverRoom(20, 15)

// Balanced cover room (medium wall density 0.4-0.7)
balancedRoom := environments.BalancedCoverRoom(20, 15)


Wall System

Simple Pattern Selection
  • "empty": No internal walls - open areas, social encounters
  • "random": Procedural wall placement with configurable parameters
Client Control Parameters
room := builder.
    WithWallPattern("random").
    WithWallDensity(0.5).           // 0.0 = no walls, 1.0 = maximum walls
    WithDestructibleRatio(0.8).     // 0.0 = all indestructible, 1.0 = all destructible
    WithMaterial("stone").          // Wall material (game-specific)
    WithRandomSeed(42).             // Reproducible generation
    Build()
Wall Properties
// Games can customize wall behavior
type WallProperties struct {
    // Destruction
    HP           int      // Health points
    Resistance   []string // Damage types resisted
    Weakness     []string // Damage types with extra effect
    
    // Physical
    Material     string   // Visual/audio material
    Thickness    float64  // Wall thickness
    Height       float64  // Wall height
    
    // Gameplay
    BlocksLoS      bool   // Line of sight blocking
    BlocksMovement bool   // Movement blocking
    ProvidesCover  bool   // Combat cover bonus
}

Architecture Flow

1. Generation Process
Client Request → Environment Generator → Room Builder → Spatial Integration
      ↓                    ↓                  ↓              ↓
   Parameters        Abstract Graph      Room + Walls    Spatial Entities
2. Wall Integration
// Walls become spatial entities automatically
type WallEntity struct {
    // Implements spatial.Placeable interface
    position   spatial.Position
    properties WallProperties
}

// Automatic spatial integration
func (w *WallEntity) BlocksMovement() bool {
    return !w.destroyed && w.properties.BlocksMovement
}
3. Event Flow
// Environment publishes events
"environment.generated"     // Generation complete
"wall.pattern.applied"      // Walls added to room

// Environment consumes events
"spatial.entity.placed"     // Apply environmental effects
"turn.started"              // Process environmental changes

Client Usage Patterns

1. Density-Based Variety
// Sparse walls for open combat
sparseRoom := builder.WithWallDensity(0.2).Build()

// Dense walls for tactical maneuvering
denseRoom := builder.WithWallDensity(0.8).Build()

// No walls for social encounters
openRoom := builder.WithWallPattern("empty").Build()
2. Destructible Wall Tactics
// Mostly destructible - players can reshape battlefield
flexibleRoom := builder.WithDestructibleRatio(0.9).Build()

// Mostly indestructible - fixed tactical positions
rigidRoom := builder.WithDestructibleRatio(0.1).Build()

// Mixed - some permanent structure, some flexibility
balancedRoom := builder.WithDestructibleRatio(0.6).Build()
3. Material Customization
// Stone walls - high HP, fire resistant
stoneRoom := builder.WithMaterial("stone").Build()

// Wood walls - lower HP, fire weakness
woodRoom := builder.WithMaterial("wood").Build()

// Metal walls - electrical weakness
metalRoom := builder.WithMaterial("metal").Build()

Wall Destruction Mechanics

1. Applying Damage
// Get wall entity at position
entities := room.GetEntitiesAt(position)
for _, entity := range entities {
    if wall, ok := entity.(*environments.WallEntity); ok {
        // Apply damage
        destroyed := wall.TakeDamage(25, "fire")
        
        if destroyed {
            // New tactical options available
            fmt.Println("Wall destroyed! New path available.")
        }
    }
}
2. Automatic Spatial Updates
// Destroyed walls automatically stop blocking
canMove := room.CanPlaceEntity(player, wallPosition)     // Now true
canSee := !room.IsLineOfSightBlocked(from, to)          // Now true
3. Repair and Reconstruction
// Repair damaged walls
wall.Repair(10)

// Destroy walls immediately (scripted events)
wall.Destroy()

Query System

1. Environment-Level Queries
// Find all entities in environment
entities := environment.QueryEntitiesInRange(
    context.Background(),
    centerPos, 
    10.0,     // radius
    "",       // all rooms
    nil,      // no filter
)

// Find entities in specific room
roomEntities := environment.QueryEntitiesInRange(
    context.Background(),
    centerPos,
    10.0,
    "room-1", // specific room
    nil,
)
2. Wall-Specific Queries
// Get all walls in room
walls := environments.GetWallEntitiesInRoom(room)

// Check wall segment health
current, max, destroyed := environments.GetWallSegmentHealth(room, "wall-segment-1")

// Find walls by segment
segmentWalls := environments.FindWallEntitiesBySegment(allEntities, "wall-segment-1")

Extension Points

1. Custom Wall Patterns
// Register custom pattern algorithm
environments.RegisterWallPattern("custom", func(shape RoomShape, size Dimensions, params PatternParams) []WallSegment {
    // Custom wall generation logic
    return generateCustomWalls(shape, size, params)
})

// Use custom pattern
room := builder.WithWallPattern("custom").Build()
2. Custom Materials
// Define game-specific materials
environments.RegisterMaterial("magical_ice", WallProperties{
    HP:         15,
    Resistance: []string{"cold", "water"},
    Weakness:   []string{"fire"},
    Material:   "ice",
    BlocksLoS:  true,
    BlocksMovement: true,
})
3. Environmental Effects
// Subscribe to wall destruction events
eventBus.Subscribe("wall.destroyed", func(event events.GameEvent) {
    // Custom game logic when walls are destroyed
    handleWallDestruction(event.Source.(*environments.WallEntity))
})

Best Practices

1. Choosing Wall Parameters
// Open areas - social encounters, large battles
builder.WithWallPattern("empty")

// Light tactical - some cover, open movement
builder.WithWallPattern("random").WithWallDensity(0.3)

// Heavy tactical - lots of cover, complex movement
builder.WithWallPattern("random").WithWallDensity(0.7)
2. Destructible Ratios by Room Purpose
// Structural rooms - permanent architecture
builder.WithDestructibleRatio(0.2)

// General rooms - some tactical flexibility
builder.WithDestructibleRatio(0.6)

// Interactive rooms - heavy environmental interaction
builder.WithDestructibleRatio(0.9)
3. Performance Optimization
// Use specific room IDs for better performance
entities := environment.QueryEntitiesInRange(ctx, pos, radius, "room-1", filter)

// Batch wall operations
for _, wallID := range wallsToDestroy {
    environments.DestroyWallSegment(room, wallID)
}

Example Game Integration

// Game-specific room factory
func CreateRoomLayout(layoutType string) spatial.Room {
    var density, destructibleRatio float64
    
    switch layoutType {
    case "open":
        density = 0.0
        destructibleRatio = 0.0
    case "sparse":
        density = 0.3
        destructibleRatio = 0.8
    case "dense":
        density = 0.7
        destructibleRatio = 0.4
    default:
        density = 0.5
        destructibleRatio = 0.6
    }
    
    return environments.NewRoomBuilder(config).
        WithSize(20, 15).
        WithWallPattern("random").
        WithWallDensity(density).
        WithDestructibleRatio(destructibleRatio).
        WithMaterial("stone").
        Build()
}

This simplified approach provides maximum flexibility while maintaining the toolkit's philosophy of infrastructure over implementation. Games can create endless variety by adjusting simple parameters rather than choosing from predefined patterns.

Documentation

Overview

Package environments provides procedural generation of rooms and areas using spatial primitives and environmental features without game logic.

Purpose: This package generates physical spaces with rooms, corridors, and features while remaining agnostic to game-specific concepts like encounter design or narrative purpose. It creates the stage, not the play.

Scope:

  • Room shape generation (rectangle, L-shape, cross, etc.)
  • Corridor and connection generation between rooms
  • Environmental feature placement (walls, pillars, etc.)
  • Graph-based and BSP layout algorithms
  • Room sizing based on capacity calculations
  • Wall patterns (empty, random destructible)
  • Integration with selectables for random generation

Non-Goals:

  • Encounter design: What spawns in rooms is game-specific
  • Trap mechanics: Trap effects and saves are game rules
  • Secret doors: Detection DCs are game-specific
  • Narrative generation: Story/quest hooks belong in games
  • Dungeon ecology: Logical creature placement is game logic
  • Treasure placement: Value and rarity are game-specific
  • Environmental hazards: Damage and effects are game rules

Integration: This package integrates with:

  • spatial: Creates rooms compatible with spatial system
  • selectables: For random room shapes and features
  • events: Publishes generation events

The environments package generates interesting spaces that games can populate with their own content and meaning.

Example:

gen := environments.NewGraphGenerator(environments.GeneratorConfig{
    MinRooms: 5,
    MaxRooms: 10,
})

// Generate a dungeon level
env := gen.Generate(environments.Parameters{
    TargetCapacity: 50,  // Space for ~50 entities total
    Connectivity:   0.7, // 70% connected graph
    Shapes: []environments.ShapeWeight{
        {Shape: "rectangle", Weight: 60},
        {Shape: "L", Weight: 30},
        {Shape: "cross", Weight: 10},
    },
})

// Iterate generated rooms
for _, room := range env.GetRooms() {
    // Room is ready for spawn system to populate
    fmt.Printf("Room %s: %dx%d at %v\n",
        room.ID(), room.Width(), room.Height(), room.Position())
}

// Access the spatial orchestrator
orchestrator := env.GetOrchestrator()
// Use for movement, queries, etc.

Package environments provides procedural generation of game environments using graph algorithms. This package creates environments by building abstract graphs of rooms and connections, then placing them spatially while integrating with the spatial module for obstacle detection.

Package environments provides procedural environment and room generation capabilities.

Index

Constants

View Source
const (
	// EventEnvironmentGenerated is published when a new environment is successfully generated.
	EventEnvironmentGenerated = "environment.generated"
	// EventEnvironmentDestroyed is published when an environment is destroyed or cleaned up.
	EventEnvironmentDestroyed = "environment.destroyed"
	// EventEnvironmentExported is published when an environment is exported to a file or byte array.
	EventEnvironmentExported = "environment.exported"
	// EventEnvironmentImported is published when an environment is imported from a file or byte array.
	EventEnvironmentImported = "environment.imported"

	// EventThemeChanged is published when the environment's theme is changed.
	EventThemeChanged = "environment.theme.changed"
	// EventEnvironmentMetadataChanged is published when the environment's metadata is changed.
	EventEnvironmentMetadataChanged = "environment.metadata.changed"
	// EventLayoutChanged is published when the layout of the environment is changed.
	EventLayoutChanged = "environment.layout.changed"

	// EventRoomTemplateApplied is published when a room template is applied to create a new room.
	EventRoomTemplateApplied = "environment.room_template.applied"
	// EventRoomTemplateRemoved is published when a room template is removed.
	EventRoomTemplateRemoved = "environment.room_template.removed"

	// EventConnectionTemplateApplied is published when a connection template is applied to create a new connection.
	EventConnectionTemplateApplied = "environment.connection_template.applied"
	// EventConnectionTemplateRemoved is published when a connection template is removed.
	EventConnectionTemplateRemoved = "environment.connection_template.removed"

	// EventFeatureAdded is published when a feature is added to the environment.
	EventFeatureAdded = "environment.feature.added"
	// EventFeatureRemoved is published when a feature is removed from the environment.
	EventFeatureRemoved = "environment.feature.removed"
	// EventFeatureActivated is published when a feature is activated in the environment.
	EventFeatureActivated = "environment.feature.activated"
	// EventFeatureDeactivated is published when a feature is deactivated in the environment.
	EventFeatureDeactivated = "environment.feature.deactivated"

	// EventEnvironmentEffectApplied is published when an environmental effect is applied.
	EventEnvironmentEffectApplied = "environment.effect.applied"
	// EventEnvironmentEffectRemoved is published when an environmental effect is removed.
	EventEnvironmentEffectRemoved = "environment.effect.removed"
	// EventEnvironmentEffectExpired is published when an environmental effect expires.
	EventEnvironmentEffectExpired = "environment.effect.expired"

	// EventHazardActivated is published when a hazard becomes active in the environment.
	EventHazardActivated = "environment.hazard.activated"
	// EventHazardDeactivated is published when a hazard is deactivated in the environment.
	EventHazardDeactivated = "environment.hazard.deactivated"
	// EventHazardTriggered is published when a hazard is triggered in the environment.
	EventHazardTriggered = "environment.hazard.triggered"

	// EventEnvironmentEntityAdded is published when an entity is added to the environment.
	EventEnvironmentEntityAdded = "environment.entity.added"
	// EventEnvironmentEntityRemoved is published when an entity is removed from the environment.
	EventEnvironmentEntityRemoved = "environment.entity.removed"
	// EventEnvironmentEntityMoved is published when an entity is moved in the environment.
	EventEnvironmentEntityMoved = "environment.entity.moved"

	// EventEnvironmentRoomAdded is published when a room is added to the environment.
	EventEnvironmentRoomAdded = "environment.room.added"
	// EventEnvironmentRoomRemoved is published when a room is removed from the environment.
	EventEnvironmentRoomRemoved = "environment.room.removed"
	// EventEnvironmentRoomModified is published when a room is modified in the environment.
	EventEnvironmentRoomModified = "environment.room.modified"

	// EventEnvironmentQueryExecuted is published when an environment query is executed.
	EventEnvironmentQueryExecuted = "environment.query.executed"
	// EventEnvironmentQueryFailed is published when an environment query fails to execute.
	EventEnvironmentQueryFailed = "environment.query.failed"

	// EventGenerationStarted is published when environment generation begins.
	EventGenerationStarted = "environment.generation.started"
	// EventGenerationCompleted is published when environment generation completes successfully.
	EventGenerationCompleted = "environment.generation.completed"
	// EventGenerationFailed is published when environment generation fails.
	EventGenerationFailed = "environment.generation.failed"
	// EventGenerationProgress is published to indicate the progress of environment generation.
	EventGenerationProgress = "environment.generation.progress"

	// EventEmergencyFallbackTriggered is published when emergency fallback is triggered during generation.
	EventEmergencyFallbackTriggered = "environment.emergency_fallback.triggered"
)
View Source
const (
	RoomTypeEntrance = "entrance"
	RoomTypeBoss     = "boss"
	RoomTypeCorridor = "corridor"
	RoomTypeTreasure = "treasure"
	RoomTypeTrap     = "trap"
	RoomTypeExit     = "exit"
	RoomTypeChamber  = "chamber"
	RoomTypeJunction = "junction"
)

Room type constants

View Source
const (
	PatternEmpty   = "empty"
	PatternRandom  = "random"
	ShapeRectangle = "rectangle"
	ShapeSquare    = "square"
	ThemeDefault   = "default"
)

Pattern constants

Variables

View Source
var (
	// GenerationStartedTopic publishes events when environment generation starts
	GenerationStartedTopic = events.DefineTypedTopic[GenerationStartedEvent]("environment.generation.started")
	// GenerationProgressTopic publishes events during environment generation progress
	GenerationProgressTopic = events.DefineTypedTopic[GenerationProgressEvent]("environment.generation.progress")
	// GenerationCompletedTopic publishes events when environment generation completes
	GenerationCompletedTopic = events.DefineTypedTopic[GenerationCompletedEvent]("environment.generation.completed")
	// GenerationFailedTopic publishes events when environment generation fails
	GenerationFailedTopic = events.DefineTypedTopic[GenerationFailedEvent]("environment.generation.failed")
	// EmergencyFallbackTopic publishes events when emergency fallback procedures are triggered
	EmergencyFallbackTopic = events.DefineTypedTopic[EmergencyFallbackEvent]("environment.emergency_fallback.triggered")

	// EnvironmentGeneratedTopic publishes events when environments are generated
	EnvironmentGeneratedTopic = events.DefineTypedTopic[EnvironmentGeneratedEvent]("environment.generated")
	// EnvironmentDestroyedTopic publishes events when environments are destroyed
	EnvironmentDestroyedTopic = events.DefineTypedTopic[EnvironmentDestroyedEvent]("environment.destroyed")

	// EnvironmentEntityAddedTopic publishes events when entities are added to environments
	EnvironmentEntityAddedTopic = events.DefineTypedTopic[EnvironmentEntityAddedEvent]("environment.entity.added")
	// EnvironmentEntityRemovedTopic publishes events when entities are removed from environments
	EnvironmentEntityRemovedTopic = events.DefineTypedTopic[EnvironmentEntityRemovedEvent]("environment.entity.removed")

	// EnvironmentRoomAddedTopic publishes events when rooms are added to environments
	EnvironmentRoomAddedTopic = events.DefineTypedTopic[EnvironmentRoomAddedEvent]("environment.room.added")
	// EnvironmentRoomRemovedTopic publishes events when rooms are removed from environments
	EnvironmentRoomRemovedTopic = events.DefineTypedTopic[EnvironmentRoomRemovedEvent]("environment.room.removed")

	// FeatureAddedTopic publishes events when features are added to environments
	FeatureAddedTopic = events.DefineTypedTopic[FeatureAddedEvent]("environment.feature.added")
	// FeatureRemovedTopic publishes events when features are removed from environments
	FeatureRemovedTopic = events.DefineTypedTopic[FeatureRemovedEvent]("environment.feature.removed")

	// HazardTriggeredTopic publishes events when environmental hazards are triggered
	HazardTriggeredTopic = events.DefineTypedTopic[HazardTriggeredEvent]("environment.hazard.triggered")

	// ThemeChangedTopic publishes events when environment themes change
	ThemeChangedTopic = events.DefineTypedTopic[ThemeChangedEvent]("environment.theme.changed")
	// EnvironmentMetadataChangedTopic publishes events when environment metadata changes
	EnvironmentMetadataChangedTopic = events.DefineTypedTopic[EnvironmentMetadataChangedEvent]("environment.metadata")

	// EnvironmentEntityMovedTopic publishes events when entities move within environments
	EnvironmentEntityMovedTopic = events.DefineTypedTopic[EnvironmentEntityMovedEvent]("environment.entity.moved")

	// QueryExecutedTopic publishes events when environment queries are executed
	QueryExecutedTopic = events.DefineTypedTopic[QueryExecutedEvent]("environment.query.executed")
	// QueryFailedTopic publishes events when environment queries fail
	QueryFailedTopic = events.DefineTypedTopic[QueryFailedEvent]("environment.query.failed")

	// RoomBuiltTopic publishes events when rooms are built within environments
	RoomBuiltTopic = events.DefineTypedTopic[RoomBuiltEvent]("environment.room.built")
)
View Source
var WallPatterns = map[string]WallPatternFunc{
	"empty":  EmptyPattern,
	"random": RandomPattern,
}

WallPatterns is the registry for available wall patterns.

Functions

func BalancedCoverRoom

func BalancedCoverRoom(width, height int) (spatial.Room, error)

BalancedCoverRoom creates a room with medium wall density using selectables for infinite variety within balanced cover constraints (0.4-0.7 density range)

func CalculateOptimalRoomSize

func CalculateOptimalRoomSize(intentProfile SpatialIntentProfile, entityCount int) spatial.Dimensions

CalculateOptimalRoomSize determines the best room dimensions for the given parameters Purpose: Core feeling-based sizing function that translates intent into concrete dimensions

func CreateWallEntities

func CreateWallEntities(walls []WallSegment) []spatial.Placeable

CreateWallEntities converts wall segments into wall entities Purpose: Discretizes wall segments into individual positioned entities that can be placed in spatial rooms for obstacle detection

func DenseCoverRoom

func DenseCoverRoom(width, height int) (spatial.Room, error)

DenseCoverRoom creates a room with high wall density using selectables for infinite variety within dense cover constraints (0.6-0.9 density range)

func DestroyWallSegment

func DestroyWallSegment(room spatial.Room, segmentID string) error

DestroyWallSegment destroys all wall entities belonging to a segment

func GetDefaultDensityTable

func GetDefaultDensityTable() selectables.SelectionTable[Range]

GetDefaultDensityTable returns a table for wall density range selection Purpose: Provides variety in wall density while maintaining constraint profiles

func GetDefaultDestructibleTable

func GetDefaultDestructibleTable() selectables.SelectionTable[Range]

GetDefaultDestructibleTable returns a table for destructible wall ratio selection Purpose: Provides variety in wall interaction possibilities

func GetDefaultPatternTable

func GetDefaultPatternTable() selectables.SelectionTable[string]

GetDefaultPatternTable returns a table for wall pattern algorithm selection Purpose: Provides variety in wall arrangement styles

func GetDefaultRotationModeTable

func GetDefaultRotationModeTable() selectables.SelectionTable[string]

GetDefaultRotationModeTable returns a table for rotation mode selection Purpose: Provides variety in room orientation

func GetDefaultSafetyProfileTable

func GetDefaultSafetyProfileTable() selectables.SelectionTable[SafetyProfile]

GetDefaultSafetyProfileTable returns a table for safety profile selection Purpose: Provides variety in pathfinding and safety requirements

func GetDefaultShapeTable

func GetDefaultShapeTable() selectables.SelectionTable[string]

GetDefaultShapeTable returns a table for room shape selection Purpose: Provides variety in room geometry while respecting common usage patterns

func GetDefaultShapes

func GetDefaultShapes() map[string]*RoomShape

GetDefaultShapes returns basic shapes for development/testing

func GetWallSegmentHealth

func GetWallSegmentHealth(room spatial.Room, segmentID string) (current, maximum int, destroyed bool)

GetWallSegmentHealth returns the health status of a wall segment

func IsShapeCompatibleWithGrid

func IsShapeCompatibleWithGrid(shape *RoomShape, gridType string) bool

IsShapeCompatibleWithGrid checks if a shape works well with a specific grid type Purpose: Helps select appropriate shapes for different grid systems

func QuickRoom

func QuickRoom(width, height int, pattern string) (spatial.Room, error)

QuickRoom creates a room with sensible defaults

func RepairWallSegment

func RepairWallSegment(room spatial.Room, segmentID string, healAmount int) error

RepairWallSegment repairs all wall entities belonging to a segment

func SparseCoverRoom

func SparseCoverRoom(width, height int) (spatial.Room, error)

SparseCoverRoom creates a room with low wall density using selectables for infinite variety within sparse cover constraints (0.1-0.4 density range)

Types

type BasicEnvironment

type BasicEnvironment struct {
	// contains filtered or unexported fields
}

BasicEnvironment is the core implementation of the Environment interface Purpose: Wraps a spatial orchestrator with environment-specific functionality like metadata, queries, and event integration. Acts as the primary client interface to the spatial infrastructure.

func NewBasicEnvironment

func NewBasicEnvironment(config BasicEnvironmentConfig) *BasicEnvironment

NewBasicEnvironment creates a new BasicEnvironment following toolkit patterns Purpose: Standard constructor with config struct, proper initialization

func (*BasicEnvironment) Cleanup

func (e *BasicEnvironment) Cleanup()

Cleanup method for proper resource management

func (*BasicEnvironment) ConnectToEventBus added in v0.1.1

func (e *BasicEnvironment) ConnectToEventBus(bus events.EventBus)

ConnectToEventBus connects the environment's typed topics to the event bus

func (*BasicEnvironment) Export

func (e *BasicEnvironment) Export() ([]byte, error)

Export serializes the environment to a byte array for storage or transmission.

func (*BasicEnvironment) FindPath

FindPath finds a path between two positions within the environment.

func (*BasicEnvironment) FindPathCube added in v0.2.0

func (e *BasicEnvironment) FindPathCube(input *FindPathCubeInput) (*FindPathCubeOutput, error)

FindPathCube finds a path between cube coordinates using A* algorithm. This is the primary pathfinding method for hex grid environments.

func (*BasicEnvironment) GetBlockedHexes added in v0.3.0

func (e *BasicEnvironment) GetBlockedHexes() map[spatial.CubeCoordinate]bool

GetBlockedHexes returns all blocked hexes in dungeon-absolute coordinates. This returns the pre-calculated blocked hexes from generation.

func (*BasicEnvironment) GetConnection

func (e *BasicEnvironment) GetConnection(connectionID string) (spatial.Connection, bool)

GetConnection returns a specific connection by ID

func (*BasicEnvironment) GetConnections

func (e *BasicEnvironment) GetConnections() []spatial.Connection

GetConnections returns all connections in this environment

func (*BasicEnvironment) GetID

func (e *BasicEnvironment) GetID() string

GetID returns the unique identifier for this environment

func (*BasicEnvironment) GetMetadata

func (e *BasicEnvironment) GetMetadata() EnvironmentMetadata

GetMetadata returns metadata about this environment

func (*BasicEnvironment) GetOrchestrator

func (e *BasicEnvironment) GetOrchestrator() spatial.RoomOrchestrator

GetOrchestrator returns the room orchestrator managing spatial layout

func (*BasicEnvironment) GetRoom

func (e *BasicEnvironment) GetRoom(roomID string) (spatial.Room, bool)

GetRoom returns a specific room by ID

func (*BasicEnvironment) GetRoomAt added in v0.3.0

func (e *BasicEnvironment) GetRoomAt(coord spatial.CubeCoordinate) (string, bool)

GetRoomAt returns which room contains the given dungeon-absolute coordinate.

func (*BasicEnvironment) GetRoomBounds added in v0.3.0

GetRoomBounds returns the min/max coordinates for a room in dungeon-absolute space.

func (*BasicEnvironment) GetRoomPosition added in v0.3.0

func (e *BasicEnvironment) GetRoomPosition(roomID string) (spatial.CubeCoordinate, bool)

GetRoomPosition returns a room's origin in dungeon-absolute coordinates.

func (*BasicEnvironment) GetRooms

func (e *BasicEnvironment) GetRooms() []spatial.Room

GetRooms returns all rooms in this environment

func (*BasicEnvironment) GetTheme

func (e *BasicEnvironment) GetTheme() string

GetTheme returns the theme of this environment

func (*BasicEnvironment) GetType

func (e *BasicEnvironment) GetType() core.EntityType

GetType returns the type of this environment

func (*BasicEnvironment) QueryEntities

func (e *BasicEnvironment) QueryEntities(ctx context.Context, query EntityQuery) ([]core.Entity, error)

QueryEntities searches for entities within the environment based on the provided query criteria.

func (*BasicEnvironment) QueryRooms

func (e *BasicEnvironment) QueryRooms(ctx context.Context, query RoomQuery) ([]spatial.Room, error)

QueryRooms searches for rooms within the environment based on the provided query criteria.

func (*BasicEnvironment) SetTheme

func (e *BasicEnvironment) SetTheme(newTheme string)

SetTheme changes the visual and atmospheric theme of the environment.

func (*BasicEnvironment) ToData added in v0.4.0

func (e *BasicEnvironment) ToData() EnvironmentData

ToData converts a BasicEnvironment to EnvironmentData for persistence. All coordinates are converted to absolute environment space. Output is deterministic - slices are sorted by ID.

Purpose: Serialize the environment for storage. The game server receives this and passes it through without coordinate conversions.

func (*BasicEnvironment) UpdateMetadata

func (e *BasicEnvironment) UpdateMetadata(metadata EnvironmentMetadata)

UpdateMetadata updates the environment's metadata with new information.

type BasicEnvironmentConfig

type BasicEnvironmentConfig struct {
	ID       string              `json:"id"`
	Type     string              `json:"type"`
	Theme    string              `json:"theme"`
	Metadata EnvironmentMetadata `json:"metadata"`
	// EventBus removed - ConnectToEventBus pattern used instead
	Orchestrator spatial.RoomOrchestrator `json:"-"` // Not serializable
	QueryHandler QueryHandler             `json:"-"` // Not serializable
	// RoomPositions maps room IDs to their origin in dungeon-absolute coordinates
	// Enables unified coordinate system across the entire environment
	RoomPositions map[string]spatial.CubeCoordinate `json:"-"` // Not serializable
	// BlockedHexes contains all blocked positions in dungeon-absolute coordinates
	// Calculated during generation from wall placements
	BlockedHexes map[spatial.CubeCoordinate]bool `json:"-"` // Not serializable
}

BasicEnvironmentConfig follows the toolkit's config pattern Purpose: Provides clean dependency injection and configuration

type BasicQueryHandler

type BasicQueryHandler struct {
	// contains filtered or unexported fields
}

BasicQueryHandler implements the QueryHandler interface Purpose: Provides environment-level queries that aggregate across multiple rooms while delegating the actual spatial math to the spatial infrastructure. This is the "query aggregator" pattern from ADR-0011.

func NewBasicQueryHandler

func NewBasicQueryHandler(config BasicQueryHandlerConfig) *BasicQueryHandler

NewBasicQueryHandler creates a new query handler

func (*BasicQueryHandler) ConnectToEventBus added in v0.1.1

func (h *BasicQueryHandler) ConnectToEventBus(bus events.EventBus)

ConnectToEventBus connects the query handler's typed topics to the event bus

func (*BasicQueryHandler) HandleCapacityQuery

func (h *BasicQueryHandler) HandleCapacityQuery(
	ctx context.Context, query CapacityQuery,
) (CapacityQueryResponse, error)

HandleCapacityQuery processes a capacity analysis query Purpose: Provides advisory information about room capacity for intelligent room design

func (*BasicQueryHandler) HandleEntityQuery

func (h *BasicQueryHandler) HandleEntityQuery(ctx context.Context, query EntityQuery) ([]core.Entity, error)

HandleEntityQuery processes an entity query across the environment It handles different query types: specific rooms, range-based, or environment-wide.

func (*BasicQueryHandler) HandlePathQuery

func (h *BasicQueryHandler) HandlePathQuery(ctx context.Context, query PathQuery) ([]spatial.Position, error)

HandlePathQuery processes a pathfinding query between two positions It finds the rooms containing the positions and delegates pathfinding to spatial infrastructure.

func (*BasicQueryHandler) HandleRoomQuery

func (h *BasicQueryHandler) HandleRoomQuery(ctx context.Context, query RoomQuery) ([]spatial.Room, error)

HandleRoomQuery processes a room query across the environment It applies filters for room types, themes, features, spatial proximity, and connections.

func (*BasicQueryHandler) HandleSizingQuery

func (h *BasicQueryHandler) HandleSizingQuery(ctx context.Context, query SizingQuery) (spatial.Dimensions, error)

HandleSizingQuery processes a room sizing query Purpose: Calculates optimal room dimensions for specific requirements

type BasicQueryHandlerConfig

type BasicQueryHandlerConfig struct {
	Orchestrator spatial.RoomOrchestrator `json:"-"`
	SpatialQuery *spatial.QueryUtils      `json:"-"`
}

BasicQueryHandlerConfig follows toolkit config pattern

type BasicRoomBuilder

type BasicRoomBuilder struct {
	// contains filtered or unexported fields
}

BasicRoomBuilder implements the RoomBuilder interface Purpose: Provides a fluent API for building rooms with shapes, patterns, and walls

func NewBasicRoomBuilder

func NewBasicRoomBuilder(config BasicRoomBuilderConfig) *BasicRoomBuilder

NewBasicRoomBuilder creates a new room builder

func (*BasicRoomBuilder) Build

func (b *BasicRoomBuilder) Build() (spatial.Room, error)

Build finalizes the room configuration and generates the room

func (*BasicRoomBuilder) ConnectToEventBus added in v0.1.1

func (b *BasicRoomBuilder) ConnectToEventBus(bus events.EventBus)

ConnectToEventBus connects the room builder's typed topics to the event bus

func (*BasicRoomBuilder) WithDestructibleRatio

func (b *BasicRoomBuilder) WithDestructibleRatio(ratio float64) RoomBuilder

WithDestructibleRatio sets the destructible wall ratio

func (*BasicRoomBuilder) WithFeatures

func (b *BasicRoomBuilder) WithFeatures(features ...Feature) RoomBuilder

WithFeatures adds features to the room Features can be any spatial.Placeable entity like furniture, decorations, etc. It accepts a variadic list of Feature objects

func (*BasicRoomBuilder) WithLayout

func (b *BasicRoomBuilder) WithLayout(layout Layout) RoomBuilder

WithLayout sets the room layout It accepts a Layout object which defines the layout type and parameters The layout type can be linear, branching, grid, or organic

func (*BasicRoomBuilder) WithMaterial

func (b *BasicRoomBuilder) WithMaterial(material string) RoomBuilder

WithMaterial sets the wall material

func (*BasicRoomBuilder) WithPrefab

func (b *BasicRoomBuilder) WithPrefab(prefab RoomPrefab) RoomBuilder

WithPrefab applies a room prefab configuration It accepts a RoomPrefab object which contains predefined settings for size, theme, and features

func (*BasicRoomBuilder) WithRandomRotation

func (b *BasicRoomBuilder) WithRandomRotation() RoomBuilder

WithRandomRotation enables random rotation for the room shape The rotation will be randomly selected from [0, 90, 180, 270] degrees Uses math/rand for reproducible generation when combined with WithRandomSeed

func (*BasicRoomBuilder) WithRandomSeed

func (b *BasicRoomBuilder) WithRandomSeed(seed int64) RoomBuilder

WithRandomSeed sets the random seed for reproducible generation

func (*BasicRoomBuilder) WithRotation

func (b *BasicRoomBuilder) WithRotation(degrees int) RoomBuilder

WithRotation sets a specific rotation angle for the room shape Accepts angles in degrees: 0, 90, 180, 270

func (*BasicRoomBuilder) WithSafety

func (b *BasicRoomBuilder) WithSafety(safety PathSafetyParams) RoomBuilder

WithSafety sets the path safety parameters

func (*BasicRoomBuilder) WithShape

func (b *BasicRoomBuilder) WithShape(shapeName string) RoomBuilder

WithShape sets the room shape by name

func (*BasicRoomBuilder) WithSize

func (b *BasicRoomBuilder) WithSize(width, height int) RoomBuilder

WithSize sets the room size It accepts width and height in pixels

func (*BasicRoomBuilder) WithTheme

func (b *BasicRoomBuilder) WithTheme(theme string) RoomBuilder

WithTheme sets the room theme for styling and generation context. It accepts a RoomShape object or a shape name to load from the shape loader

func (*BasicRoomBuilder) WithWallDensity

func (b *BasicRoomBuilder) WithWallDensity(density float64) RoomBuilder

WithWallDensity sets the wall density

func (*BasicRoomBuilder) WithWallPattern

func (b *BasicRoomBuilder) WithWallPattern(pattern string) RoomBuilder

WithWallPattern sets the wall pattern

type BasicRoomBuilderConfig

type BasicRoomBuilderConfig struct {
	// EventBus removed - ConnectToEventBus pattern used instead
	ShapeLoader *ShapeLoader
}

BasicRoomBuilderConfig configures the room builder

type CapacityAnalysis

type CapacityAnalysis struct {
	TotalArea               float64          `json:"total_area"`                // Total room area
	UsableArea              float64          `json:"usable_area"`               // Area available for entities
	EntityArea              float64          `json:"entity_area"`               // Area occupied by entities
	MovementArea            float64          `json:"movement_area"`             // Area for movement
	InteractionArea         float64          `json:"interaction_area"`          // Area for entity interactions
	EfficiencyRating        float64          `json:"efficiency_rating"`         // How efficiently space is used
	ComfortRating           float64          `json:"comfort_rating"`            // How comfortable the space feels
	RecommendedActions      []string         `json:"recommended_actions"`       // Suggested improvements
	RoomCapacity            CapacityEstimate `json:"room_capacity"`             // Room capacity analysis
	RequestedEntityCount    int              `json:"requested_entity_count"`    // Number of entities requested
	CapacityUtilization     float64          `json:"capacity_utilization"`      // Capacity utilization ratio
	ResultingSpatialFeeling SpatialFeeling   `json:"resulting_spatial_feeling"` // Resulting spatial experience
	SplitOptions            []RoomSplit      `json:"split_options"`             // Room splitting options
}

CapacityAnalysis provides detailed capacity analysis results Purpose: In-depth analysis for games that need detailed capacity information

func AnalyzeRoomCapacityForEntityCount

func AnalyzeRoomCapacityForEntityCount(
	size spatial.Dimensions, entityCount int, constraints CapacityConstraints,
) CapacityAnalysis

AnalyzeRoomCapacityForEntityCount analyzes how well a room handles a specific entity count Purpose: Provides games with capacity analysis to help them make layout decisions

type CapacityConstraints

type CapacityConstraints struct {
	MinDimensions             spatial.Dimensions `json:"min_dimensions"`              // Minimum room size
	MaxDimensions             spatial.Dimensions `json:"max_dimensions"`              // Maximum room size
	AspectRatio               float64            `json:"aspect_ratio"`                // Preferred width/height ratio
	MaxEntitiesPerRoom        int                `json:"max_entities_per_room"`       // Maximum entities allowed per room
	MinMovementSpace          float64            `json:"min_movement_space"`          // Minimum movement space factor
	WallDensityModifier       float64            `json:"wall_density_modifier"`       // Wall density impact
	RequiredPathwayMultiplier float64            `json:"required_pathway_multiplier"` // Pathway space multiplier
	TargetSpatialFeeling      SpatialFeeling     `json:"target_spatial_feeling"`      // Target spatial experience
	MinEntitySpacing          float64            `json:"min_entity_spacing"`          // Minimum space between entities
}

CapacityConstraints define limits and requirements for capacity calculations Purpose: Allows games to specify constraints on room sizing and capacity

func GetDefaultConstraintsForFeeling

func GetDefaultConstraintsForFeeling(feeling SpatialFeeling) CapacityConstraints

GetDefaultConstraintsForFeeling provides sensible default constraints for a spatial feeling Purpose: Helper function for games that want default constraints but want to make their own decisions

type CapacityEstimate

type CapacityEstimate struct {
	RecommendedEntityCount int            `json:"recommended_entity_count"` // Recommended entity count
	MaxEntityCount         int            `json:"max_entity_count"`         // Maximum entities that fit comfortably
	UtilizationPercent     float64        `json:"utilization_percent"`      // How much of room would be used
	CrowdingFactor         float64        `json:"crowding_factor"`          // How crowded it would feel (0.0-1.0)
	MovementSpace          float64        `json:"movement_space"`           // Available movement area
	SpatialFeelingActual   SpatialFeeling `json:"spatial_feeling_actual"`   // Actual spatial feeling achieved
	MovementFreedomActual  float64        `json:"movement_freedom_actual"`  // Actual movement freedom achieved
	QualityScore           float64        `json:"quality_score"`            // Overall quality score (0.0-1.0)
	UsableArea             float64        `json:"usable_area"`              // Total usable area for entities
}

CapacityEstimate provides analysis of room capacity Purpose: Advisory information about how well a room accommodates entities

func EstimateRoomCapacity

func EstimateRoomCapacity(size spatial.Dimensions, constraints CapacityConstraints) CapacityEstimate

EstimateRoomCapacity analyzes a room size and provides detailed capacity information Purpose: Comprehensive capacity analysis for decision making and room optimization

type CapacityQuery

type CapacityQuery struct {
	RoomID              string               `json:"room_id"`                         // Target room for analysis
	Intent              SpatialIntentProfile `json:"intent"`                          // Desired spatial experience
	EntityCount         int                  `json:"entity_count,omitempty"`          // Number of entities to accommodate
	EntitySizes         []spatial.Dimensions `json:"entity_sizes,omitempty"`          // Sizes of entities to place
	RoomSize            spatial.Dimensions   `json:"room_size,omitempty"`             // Room dimensions for analysis
	Constraints         CapacityConstraints  `json:"constraints,omitempty"`           // Capacity constraints
	ExistingEntityCount int                  `json:"existing_entity_count,omitempty"` // Current entity count
	IncludeSplitOptions bool                 `json:"include_split_options,omitempty"` // Include split recommendations
}

CapacityQuery represents a query for room capacity analysis Purpose: Allows games to analyze room capacity for intelligent design decisions

type CapacityQueryResponse

type CapacityQueryResponse struct {
	Estimate     CapacityEstimate `json:"estimate"`      // Capacity analysis results
	SplitOptions []RoomSplit      `json:"split_options"` // Room splitting recommendations
	Analysis     CapacityAnalysis `json:"analysis"`      // Detailed capacity analysis
	Satisfied    bool             `json:"satisfied"`     // Whether requirements can be met
	Alternatives []string         `json:"alternatives"`  // Alternative approaches
}

CapacityQueryResponse contains results from capacity analysis Purpose: Provides advisory information about room capacity and recommendations

type ComponentFactory

type ComponentFactory interface {
	// CreateComponent creates a component from a specification
	CreateComponent(spec interface{}) (interface{}, error)

	// GetComponentType returns the component type this factory creates
	GetComponentType() string

	// Validate validates a component specification
	Validate(spec interface{}) error
}

ComponentFactory defines the interface for custom component creation

type ConnectionEdge

type ConnectionEdge struct {
	ID            string  `json:"id"`
	FromRoomID    string  `json:"from_room_id"`
	ToRoomID      string  `json:"to_room_id"`
	Type          string  `json:"type"`
	Bidirectional bool    `json:"bidirectional"`
	Cost          float64 `json:"cost"`
	Required      bool    `json:"required"`
	// FromPosition is the door position in FromRoom's local coordinates
	FromPosition spatial.CubeCoordinate `json:"from_position"`
	// ToPosition is the door position in ToRoom's local coordinates
	ToPosition spatial.CubeCoordinate `json:"to_position"`
}

ConnectionEdge represents a connection in the abstract graph

type ConnectionPoint

type ConnectionPoint struct {
	Name       string                 `json:"name"`       // Connection identifier
	Position   spatial.Position       `json:"position"`   // Where connection attaches (normalized)
	Direction  string                 `json:"direction"`  // "north", "south", "east", "west", "northeast", etc.
	Type       string                 `json:"type"`       // "door", "passage", "stairs", etc.
	Required   bool                   `json:"required"`   // Must this connection exist?
	Properties map[string]interface{} `json:"properties"` // Connection-specific data
}

ConnectionPoint defines where connections can attach to this room Purpose: Specifies valid connection locations in a grid-agnostic way

type ConstraintType

type ConstraintType int

ConstraintType categorizes different kinds of generation constraints Purpose: Allows the generator to handle different constraint types appropriately. Some constraints affect placement, others affect connections, etc.

const (
	// ConstraintTypePlacement represents where rooms can be placed
	ConstraintTypePlacement ConstraintType = iota
	// ConstraintTypeConnection represents how rooms can connect
	ConstraintTypeConnection
	// ConstraintTypeProximity represents distance relationships
	ConstraintTypeProximity
	// ConstraintTypeSequence represents order requirements
	ConstraintTypeSequence
)

type EmergencyFallbackEvent added in v0.1.1

type EmergencyFallbackEvent struct {
	GenerationID string                 `json:"generation_id"`
	Trigger      string                 `json:"trigger"`
	FallbackType string                 `json:"fallback_type"`
	Parameters   map[string]interface{} `json:"parameters,omitempty"`
	Timestamp    time.Time              `json:"timestamp"`
}

EmergencyFallbackEvent contains data for emergency fallback activation events

type EntityQuery

type EntityQuery struct {
	// Spatial criteria
	Center  *spatial.Position `json:"center,omitempty"`   // Center point for range queries
	Radius  float64           `json:"radius,omitempty"`   // Search radius
	RoomIDs []string          `json:"room_ids,omitempty"` // Specific rooms to search

	// Entity criteria
	EntityTypes []string `json:"entity_types,omitempty"` // Entity types to include
	ExcludeIDs  []string `json:"exclude_ids,omitempty"`  // Entity IDs to exclude

	// Environment-specific criteria
	InTheme    string `json:"in_theme,omitempty"`    // Only in rooms with theme
	HasFeature string `json:"has_feature,omitempty"` // Only in rooms with feature

	// Result limits
	Limit int `json:"limit,omitempty"` // Max results to return
}

EntityQuery represents a query for entities across the environment Purpose: Provides structured way to query entities across multiple rooms. More powerful than spatial queries because it can aggregate across rooms and apply environment-specific filters.

type Environment

type Environment interface {
	core.Entity

	// GetOrchestrator returns the underlying spatial orchestrator
	GetOrchestrator() spatial.RoomOrchestrator

	// GetRooms returns all rooms in the environment
	GetRooms() []spatial.Room

	// GetRoom returns a specific room by ID
	GetRoom(roomID string) (spatial.Room, bool)

	// GetConnections returns all connections in the environment
	GetConnections() []spatial.Connection

	// GetConnection returns a specific connection by ID
	GetConnection(connectionID string) (spatial.Connection, bool)

	// GetTheme returns the environment's theme
	GetTheme() string

	// GetMetadata returns environment metadata
	GetMetadata() EnvironmentMetadata

	// QueryEntities performs multi-room entity queries
	QueryEntities(ctx context.Context, query EntityQuery) ([]core.Entity, error)

	// QueryRooms performs room-based queries
	QueryRooms(ctx context.Context, query RoomQuery) ([]spatial.Room, error)

	// FindPath finds a path between two positions across rooms
	FindPath(from, to spatial.Position) ([]spatial.Position, error)

	// FindPathCube finds a path between cube coordinates using A* algorithm.
	// Uses the spatial.PathFinder for hex grid pathfinding.
	FindPathCube(input *FindPathCubeInput) (*FindPathCubeOutput, error)

	// GetBlockedHexes returns all blocked hexes (walls, obstacles) in dungeon-absolute coordinates.
	// This aggregates blocked hexes from all rooms, offset by their positions.
	GetBlockedHexes() map[spatial.CubeCoordinate]bool

	// GetRoomAt returns which room contains the given dungeon-absolute coordinate.
	// Returns the room ID and true if found, empty string and false otherwise.
	GetRoomAt(coord spatial.CubeCoordinate) (roomID string, found bool)

	// GetRoomBounds returns the min/max coordinates for a room in dungeon-absolute space.
	// Useful for determining room boundaries for event filtering.
	GetRoomBounds(roomID string) (minCoord, maxCoord spatial.CubeCoordinate, err error)

	// GetRoomPosition returns a room's origin in dungeon-absolute coordinates.
	GetRoomPosition(roomID string) (spatial.CubeCoordinate, bool)

	// Export exports the environment to a serializable format
	Export() ([]byte, error)
}

Environment defines the interface for generated environments

type EnvironmentData added in v0.4.0

type EnvironmentData struct {
	// ID is the unique identifier for this environment
	ID string `json:"id"`

	// Type categorizes the environment (game-specific via EnvironmentType constants)
	Type EnvironmentType `json:"type"`

	// Theme is the visual/atmospheric theme of the environment
	Theme string `json:"theme,omitempty"`

	// Metadata contains descriptive information (name, description, tags, etc.)
	Metadata EnvironmentMetadata `json:"metadata"`

	// Zones contains logical zone groupings with their absolute origins
	Zones []ZoneData `json:"zones"`

	// Passages defines how zones connect (for pathfinding)
	Passages []PassageData `json:"passages"`

	// Entities contains all placed entities with absolute coordinates
	Entities []PlacedEntityData `json:"entities"`

	// Walls contains all wall segments in absolute coordinates
	Walls []WallSegmentData `json:"walls"`
}

EnvironmentData contains all information needed to persist and reconstruct a multi-zone environment with absolute coordinates.

This is generic infrastructure - game-specific concepts (dungeons, towns, etc.) should compose this structure and add their own metadata.

All coordinates are absolute - consumers should never perform coordinate conversions.

type EnvironmentDestroyedEvent added in v0.1.1

type EnvironmentDestroyedEvent struct {
	EnvironmentID string    `json:"environment_id"`
	Reason        string    `json:"reason,omitempty"`
	DestroyedAt   time.Time `json:"destroyed_at"`
}

EnvironmentDestroyedEvent contains data for environment destruction events

type EnvironmentEntityAddedEvent added in v0.1.1

type EnvironmentEntityAddedEvent struct {
	EnvironmentID string                 `json:"environment_id"`
	EntityID      string                 `json:"entity_id"`
	EntityType    string                 `json:"entity_type,omitempty"`
	RoomID        string                 `json:"room_id,omitempty"`
	Properties    map[string]interface{} `json:"properties,omitempty"`
	AddedAt       time.Time              `json:"added_at"`
}

EnvironmentEntityAddedEvent contains data for entity addition to environment events

type EnvironmentEntityMovedEvent added in v0.1.1

type EnvironmentEntityMovedEvent struct {
	EnvironmentID string                 `json:"environment_id"`
	EntityID      string                 `json:"entity_id"`
	EntityType    string                 `json:"entity_type,omitempty"`
	RoomID        string                 `json:"room_id,omitempty"`
	FromPosition  map[string]interface{} `json:"from_position,omitempty"`
	ToPosition    map[string]interface{} `json:"to_position,omitempty"`
	Properties    map[string]interface{} `json:"properties,omitempty"`
	MovedAt       time.Time              `json:"moved_at"`
}

EnvironmentEntityMovedEvent contains data for entity movement within environment events

type EnvironmentEntityRemovedEvent added in v0.1.1

type EnvironmentEntityRemovedEvent struct {
	EnvironmentID string    `json:"environment_id"`
	EntityID      string    `json:"entity_id"`
	RoomID        string    `json:"room_id,omitempty"`
	Reason        string    `json:"reason,omitempty"`
	RemovedAt     time.Time `json:"removed_at"`
}

EnvironmentEntityRemovedEvent contains data for entity removal from environment events

type EnvironmentGeneratedEvent added in v0.1.1

type EnvironmentGeneratedEvent struct {
	EnvironmentID string                 `json:"environment_id"`
	Type          string                 `json:"type"`
	Theme         string                 `json:"theme,omitempty"`
	RoomCount     int                    `json:"room_count"`
	Features      []string               `json:"features,omitempty"`
	Metadata      map[string]interface{} `json:"metadata,omitempty"`
	GeneratedAt   time.Time              `json:"generated_at"`
}

EnvironmentGeneratedEvent contains data for environment generation completion events

type EnvironmentGenerator

type EnvironmentGenerator interface {
	core.Entity

	// Generate creates a new environment
	Generate(ctx context.Context, config GenerationConfig) (Environment, error)

	// GetGenerationType returns the generation type
	GetGenerationType() GenerationType

	// Validate validates a generation configuration
	Validate(config GenerationConfig) error

	// GetCapabilities returns generator capabilities
	GetCapabilities() GeneratorCapabilities
}

EnvironmentGenerator defines the interface for environment generation

type EnvironmentMetadata

type EnvironmentMetadata struct {
	Name        string            `json:"name"`         // Human-readable name
	Description string            `json:"description"`  // Narrative description
	Theme       string            `json:"theme"`        // Visual/thematic style
	Tags        []string          `json:"tags"`         // Searchable tags
	Properties  map[string]string `json:"properties"`   // Custom key-value data
	GeneratedAt time.Time         `json:"generated_at"` // When environment was created
	GeneratedBy string            `json:"generated_by"` // Generator that created it
	Version     string            `json:"version"`      // Environment format version
}

EnvironmentMetadata contains descriptive information about an environment Purpose: Allows environments to carry theme, description, and generation info without affecting spatial behavior. Games can use this for UI, saving, etc.

type EnvironmentMetadataChangedEvent added in v0.1.1

type EnvironmentMetadataChangedEvent struct {
	EnvironmentID string              `json:"environment_id"`
	Metadata      EnvironmentMetadata `json:"metadata"`
	ChangedAt     time.Time           `json:"changed_at"`
}

EnvironmentMetadataChangedEvent contains data for environment metadata change events

type EnvironmentRoomAddedEvent added in v0.1.1

type EnvironmentRoomAddedEvent struct {
	EnvironmentID string                 `json:"environment_id"`
	RoomID        string                 `json:"room_id"`
	RoomType      string                 `json:"room_type,omitempty"`
	Properties    map[string]interface{} `json:"properties,omitempty"`
	AddedAt       time.Time              `json:"added_at"`
}

EnvironmentRoomAddedEvent contains data for room addition to environment events

type EnvironmentRoomRemovedEvent added in v0.1.1

type EnvironmentRoomRemovedEvent struct {
	EnvironmentID string    `json:"environment_id"`
	RoomID        string    `json:"room_id"`
	Reason        string    `json:"reason,omitempty"`
	RemovedAt     time.Time `json:"removed_at"`
}

EnvironmentRoomRemovedEvent contains data for room removal from environment events

type EnvironmentSize

type EnvironmentSize int

EnvironmentSize represents predefined environment sizes Purpose: Provides convenient size presets while allowing custom sizes. Games can use standard sizes or define their own through Custom + dimensions.

const (
	// EnvironmentSizeSmall represents small environment sizes ~10-20 rooms
	EnvironmentSizeSmall EnvironmentSize = iota
	// EnvironmentSizeMedium is the default size for most environments ~20-50 rooms
	EnvironmentSizeMedium
	// EnvironmentSizeLarge represents large environments ~50-150 rooms
	EnvironmentSizeLarge
	// EnvironmentSizeCustom allows for custom dimensions
	EnvironmentSizeCustom
)

type EnvironmentType added in v0.4.0

type EnvironmentType string

EnvironmentType is a typed string for environment categorization. Rulebooks define constants using this type (e.g., "dungeon", "cave", "town").

type Feature

type Feature struct {
	Type       string                 `json:"type"`       // Feature type (trap, chest, etc.)
	Name       string                 `json:"name"`       // Display name
	Position   *spatial.Position      `json:"position"`   // Where in the room (if specific)
	Properties map[string]interface{} `json:"properties"` // Feature-specific data
}

Feature represents an environmental feature that can be added to rooms Purpose: Provides extensible way to add game-specific elements to rooms without coupling the environment system to specific game mechanics.

type FeatureAddedEvent added in v0.1.1

type FeatureAddedEvent struct {
	EnvironmentID string                 `json:"environment_id"`
	FeatureID     string                 `json:"feature_id"`
	FeatureType   string                 `json:"feature_type"`
	RoomID        string                 `json:"room_id,omitempty"`
	Properties    map[string]interface{} `json:"properties,omitempty"`
	AddedAt       time.Time              `json:"added_at"`
}

FeatureAddedEvent contains data for feature addition to environment events

type FeatureEntity

type FeatureEntity struct {
	// contains filtered or unexported fields
}

FeatureEntity represents a room feature as a spatial entity

func (*FeatureEntity) BlocksLineOfSight

func (f *FeatureEntity) BlocksLineOfSight() bool

BlocksLineOfSight checks if this feature blocks line of sight

func (*FeatureEntity) BlocksMovement

func (f *FeatureEntity) BlocksMovement() bool

BlocksMovement checks if this feature blocks movement

func (*FeatureEntity) GetID

func (f *FeatureEntity) GetID() string

GetID returns the unique ID of this feature entity

func (*FeatureEntity) GetSize

func (f *FeatureEntity) GetSize() int

GetSize returns the size of this feature entity

func (*FeatureEntity) GetType

func (f *FeatureEntity) GetType() core.EntityType

GetType returns the type of this feature entity

type FeatureRemovedEvent added in v0.1.1

type FeatureRemovedEvent struct {
	EnvironmentID string    `json:"environment_id"`
	FeatureID     string    `json:"feature_id"`
	RoomID        string    `json:"room_id,omitempty"`
	Reason        string    `json:"reason,omitempty"`
	RemovedAt     time.Time `json:"removed_at"`
}

FeatureRemovedEvent contains data for feature removal from environment events

type FindPathCubeInput added in v0.2.0

type FindPathCubeInput struct {
	From    spatial.CubeCoordinate          `json:"from"` // Starting position
	To      spatial.CubeCoordinate          `json:"to"`   // Destination position
	Blocked map[spatial.CubeCoordinate]bool `json:"-"`    // Blocked hexes (walls, obstacles)
}

FindPathCubeInput represents input for cube coordinate pathfinding Purpose: Provides structured input for A* pathfinding across the environment using cube coordinates for hex grids.

type FindPathCubeOutput added in v0.2.0

type FindPathCubeOutput struct {
	Path          []spatial.CubeCoordinate `json:"path"`           // Path excluding start, including goal
	TotalDistance int                      `json:"total_distance"` // Number of hexes in path
	Found         bool                     `json:"found"`          // Whether a path was found
}

FindPathCubeOutput represents the result of cube coordinate pathfinding Purpose: Returns the path and metadata for pathfinding queries.

type GenerationCompletedEvent added in v0.1.1

type GenerationCompletedEvent struct {
	GenerationID    string                 `json:"generation_id"`
	RequestID       string                 `json:"request_id,omitempty"`
	Config          map[string]interface{} `json:"config"`
	RoomCount       int                    `json:"room_count"`
	ConnectionCount int                    `json:"connection_count"`
	Duration        time.Duration          `json:"duration"`
	CompletedAt     time.Time              `json:"completed_at"`
}

GenerationCompletedEvent contains data for environment generation completion events

type GenerationConfig

type GenerationConfig struct {
	// Request identification
	ID        string `json:"id"`         // Unique generation ID
	RequestID string `json:"request_id"` // Optional request correlation ID

	// Basic generation parameters
	Type  GenerationType  `json:"type"`  // Graph, Prefab, or Hybrid
	Seed  int64           `json:"seed"`  // Random seed for reproducible generation
	Theme string          `json:"theme"` // Overall environment theme
	Size  EnvironmentSize `json:"size"`  // Small, Medium, Large, Custom

	// Room configuration
	RoomCount       int                `json:"room_count"`       // Number of rooms to generate
	ConnectionCount int                `json:"connection_count"` // Number of connections between rooms
	RoomTypes       []string           `json:"room_types"`       // Available room types
	MinRoomSize     spatial.Dimensions `json:"min_room_size"`    // Minimum room dimensions
	MaxRoomSize     spatial.Dimensions `json:"max_room_size"`    // Maximum room dimensions

	// Layout configuration
	Layout       LayoutType `json:"layout"`       // Overall layout pattern
	Density      float64    `json:"density"`      // How tightly packed (0.0-1.0)
	Connectivity float64    `json:"connectivity"` // How connected rooms are (0.0-1.0)

	// Component factories for custom room types
	ComponentFactories map[string]ComponentFactory `json:"-"` // Custom component creators

	// Constraints and rules
	Constraints []GenerationConstraint `json:"constraints"` // Generation rules
	Metadata    EnvironmentMetadata    `json:"metadata"`    // Environment metadata
}

GenerationConfig specifies how to generate an environment Purpose: Provides all parameters needed for generation while keeping the generator interface clean. Allows for complex configurations without polluting the Generate() method signature.

type GenerationConstraint

type GenerationConstraint struct {
	Type        ConstraintType `json:"type"`        // What kind of constraint
	Target      string         `json:"target"`      // What it applies to (room type, etc.)
	Requirement string         `json:"requirement"` // The actual requirement
	Priority    int            `json:"priority"`    // Higher priority = more important
}

GenerationConstraint represents a rule that must be satisfied during generation Purpose: Allows games to specify requirements like "boss room must be furthest from entrance" or "treasure rooms must be connected to main path". Keeps generation flexible while ensuring game-specific requirements.

type GenerationFailedEvent added in v0.1.1

type GenerationFailedEvent struct {
	GenerationID string                 `json:"generation_id"`
	RequestID    string                 `json:"request_id,omitempty"`
	Config       map[string]interface{} `json:"config,omitempty"`
	Error        string                 `json:"error"`
	Stage        string                 `json:"stage"`
	FailedAt     time.Time              `json:"failed_at"`
}

GenerationFailedEvent contains data for environment generation failure events

type GenerationProgressEvent added in v0.1.1

type GenerationProgressEvent struct {
	GenerationID string    `json:"generation_id"`
	Stage        string    `json:"stage"`    // "layout", "walls", "features", "validation"
	Progress     float64   `json:"progress"` // 0.0 to 1.0
	Message      string    `json:"message,omitempty"`
	Timestamp    time.Time `json:"timestamp"`
}

GenerationProgressEvent contains data for environment generation progress events

type GenerationStartedEvent added in v0.1.1

type GenerationStartedEvent struct {
	GenerationID string                 `json:"generation_id"`
	RequestID    string                 `json:"request_id,omitempty"`
	Config       map[string]interface{} `json:"config"`
	StartTime    time.Time              `json:"start_time"`
}

GenerationStartedEvent contains data for environment generation start events

type GenerationType

type GenerationType int

GenerationType represents different environment generation approaches

const (
	// GenerationTypeGraph represents graph-based generation
	GenerationTypeGraph GenerationType = iota
	// GenerationTypePrefab represents prefab-based generation
	GenerationTypePrefab
	// GenerationTypeHybrid represents hybrid generation combining graph and prefab
	GenerationTypeHybrid
)

type GeneratorCapabilities

type GeneratorCapabilities struct {
	SupportedTypes      []GenerationType  `json:"supported_types"`       // What generation types
	SupportedLayouts    []LayoutType      `json:"supported_layouts"`     // What layout patterns
	SupportedSizes      []EnvironmentSize `json:"supported_sizes"`       // What size ranges
	MaxRoomCount        int               `json:"max_room_count"`        // Technical limits
	SupportsConstraints bool              `json:"supports_constraints"`  // Can handle constraints
	SupportsCustomRooms bool              `json:"supports_custom_rooms"` // Can use custom room types
}

GeneratorCapabilities describes what a generator can do Purpose: Allows runtime discovery of generator features. Games can query capabilities to show appropriate UI options or validate configurations.

type GraphBasedGenerator

type GraphBasedGenerator struct {
	// contains filtered or unexported fields
}

GraphBasedGenerator implements environment generation using graph algorithms Purpose: Creates environments by first building abstract graphs of rooms and connections, then placing them spatially. This provides the flexibility prioritized in ADR-0011 while leveraging existing spatial infrastructure.

func NewGraphBasedGenerator

func NewGraphBasedGenerator(config GraphBasedGeneratorConfig) *GraphBasedGenerator

NewGraphBasedGenerator creates a new graph-based environment generator

func (*GraphBasedGenerator) ConnectToEventBus added in v0.1.1

func (g *GraphBasedGenerator) ConnectToEventBus(bus events.EventBus)

ConnectToEventBus connects the generator's typed topics to the event bus

func (*GraphBasedGenerator) Generate

Generate creates a new environment based on the provided configuration.

func (*GraphBasedGenerator) GetCapabilities

func (g *GraphBasedGenerator) GetCapabilities() GeneratorCapabilities

GetCapabilities returns the capabilities of this generator.

func (*GraphBasedGenerator) GetGenerationType

func (g *GraphBasedGenerator) GetGenerationType() GenerationType

GetGenerationType returns the type of generation this generator performs.

func (*GraphBasedGenerator) GetID

func (g *GraphBasedGenerator) GetID() string

GetID returns the unique identifier of the generator.

func (*GraphBasedGenerator) GetType

func (g *GraphBasedGenerator) GetType() core.EntityType

GetType returns the type of the generator.

func (*GraphBasedGenerator) RegisterRoomFactory

func (g *GraphBasedGenerator) RegisterRoomFactory(roomType string, factory ComponentFactory)

RegisterRoomFactory registers a custom room factory for a specific room type.

func (*GraphBasedGenerator) UnregisterRoomFactory

func (g *GraphBasedGenerator) UnregisterRoomFactory(roomType string)

UnregisterRoomFactory removes a custom room factory for a specific room type.

func (*GraphBasedGenerator) Validate

func (g *GraphBasedGenerator) Validate(config GenerationConfig) error

Validate checks if the provided configuration is valid for this generator.

type GraphBasedGeneratorConfig

type GraphBasedGeneratorConfig struct {
	ID   string `json:"id"`
	Type string `json:"type"`
	// EventBus removed - ConnectToEventBus pattern used instead
	SpatialQuery  *spatial.QueryUtils         `json:"-"`
	Seed          int64                       `json:"seed"`
	RoomFactories map[string]ComponentFactory `json:"-"`
}

GraphBasedGeneratorConfig follows toolkit config pattern

type GridHints

type GridHints struct {
	PreferredGridTypes []string               `json:"preferred_grid_types"` // "square", "hex", "gridless"
	MinSize            spatial.Dimensions     `json:"min_size"`             // Minimum recommended size
	MaxSize            spatial.Dimensions     `json:"max_size"`             // Maximum recommended size
	AspectRatio        float64                `json:"aspect_ratio"`         // Preferred width/height ratio
	SnapToGrid         bool                   `json:"snap_to_grid"`         // Should boundary snap to grid?
	Properties         map[string]interface{} `json:"properties"`           // Grid-specific hints
}

GridHints provides grid-specific guidance for shape optimization Purpose: Allows shapes to provide hints for better grid compatibility without being tied to specific grid types

type GridShapeValue added in v0.4.0

type GridShapeValue string

GridShapeValue is a typed string for grid shape serialization. Maps to spatial.GridShape during load/save operations.

const (
	// GridShapeHex represents a hexagonal grid (6 neighbors, cube coordinates)
	GridShapeHex GridShapeValue = "hex"
	// GridShapeSquare represents a square grid (8 neighbors, D&D 5e Chebyshev distance)
	GridShapeSquare GridShapeValue = "square"
	// GridShapeGridless represents continuous positioning (Euclidean distance)
	GridShapeGridless GridShapeValue = "gridless"
)

Grid shape constants - these map to spatial.GridShape values

type HazardTriggeredEvent added in v0.1.1

type HazardTriggeredEvent struct {
	EnvironmentID string                 `json:"environment_id"`
	HazardID      string                 `json:"hazard_id"`
	HazardType    string                 `json:"hazard_type"`
	TriggerEntity string                 `json:"trigger_entity,omitempty"`
	RoomID        string                 `json:"room_id,omitempty"`
	Effect        string                 `json:"effect,omitempty"`
	Properties    map[string]interface{} `json:"properties,omitempty"`
	TriggeredAt   time.Time              `json:"triggered_at"`
}

HazardTriggeredEvent contains data for environmental hazard trigger events

type HexOrientationValue added in v0.4.0

type HexOrientationValue string

HexOrientationValue is a typed string for hex grid orientation serialization. Maps to spatial.HexOrientation during load/save operations.

const (
	// HexOrientationPointy represents pointy-top hex orientation
	HexOrientationPointy HexOrientationValue = "pointy"
	// HexOrientationFlat represents flat-top hex orientation
	HexOrientationFlat HexOrientationValue = "flat"
)

Hex orientation constants - these map to spatial.HexOrientation values

type Layout

type Layout struct {
	Type        LayoutType             `json:"type"`        // Layout pattern type
	Parameters  map[string]interface{} `json:"parameters"`  // Layout-specific parameters
	Connections []LayoutConnection     `json:"connections"` // Connection specifications
}

Layout represents a spatial arrangement pattern for rooms Purpose: Defines how rooms should be arranged spatially. Can be used by generators to create different types of environments.

type LayoutConnection

type LayoutConnection struct {
	FromType       string  `json:"from_type"`       // Source room type
	ToType         string  `json:"to_type"`         // Destination room type
	ConnectionType string  `json:"connection_type"` // Type of connection
	Probability    float64 `json:"probability"`     // Chance this connection exists
	Required       bool    `json:"required"`        // Must this connection exist
}

LayoutConnection represents a connection specification in a layout Purpose: Defines how rooms should be connected in a layout pattern. More abstract than spatial connections - gets converted during generation.

type LayoutType

type LayoutType int

LayoutType represents different spatial arrangement patterns Purpose: Defines how rooms are connected spatially. Each pattern creates different gameplay experiences (linear vs open vs hub-based exploration).

const (
	// LayoutTypeLinear represents a linear sequence of rooms
	LayoutTypeLinear LayoutType = iota
	// LayoutTypeBranching represents a branching structure with multiple paths
	LayoutTypeBranching
	// LayoutTypeGrid represents a regular grid pattern
	LayoutTypeGrid
	// LayoutTypeOrganic represents irregular, natural connections
	LayoutTypeOrganic
	// LayoutTypeCustom represents a custom layout algorithm // Use custom layout algorithm
	LayoutTypeCustom
)

type LoadFromDataInput added in v0.4.0

type LoadFromDataInput struct {
	Data     EnvironmentData
	EventBus events.EventBus
}

LoadFromDataInput contains parameters for loading an environment from data

type LoadFromDataOutput added in v0.4.0

type LoadFromDataOutput struct {
	Environment     *BasicEnvironment
	PlacementErrors []error // Non-fatal errors during entity placement
}

LoadFromDataOutput contains the result of loading an environment

func LoadFromData added in v0.4.0

func LoadFromData(input LoadFromDataInput) (*LoadFromDataOutput, error)

LoadFromData creates a BasicEnvironment from EnvironmentData. This reconstructs the environment from persisted data.

Returns the environment and any non-fatal placement errors. Fatal errors (missing ID, invalid grid shape) return an error.

type PassageData added in v0.4.0

type PassageData struct {
	// ID is the unique identifier for this passage
	ID string `json:"id"`

	// FromZoneID is the source zone
	FromZoneID string `json:"from_zone_id"`

	// ToZoneID is the destination zone
	ToZoneID string `json:"to_zone_id"`

	// ControllingEntityID references an entity that controls this passage (optional)
	// If empty, the passage is always open
	// Games use this to reference doors, gates, portals, etc.
	ControllingEntityID string `json:"controlling_entity_id,omitempty"`

	// Bidirectional indicates if movement works both ways (default true)
	Bidirectional bool `json:"bidirectional"`
}

PassageData represents a link between two zones. Passages are abstract relationships - any physical representation (doors, etc.) is stored as an entity.

Purpose: Enables pathfinding between zones and tracks which entities control passage (if any).

type Path

type Path struct {
	From    spatial.Position `json:"from"`    // Path start
	To      spatial.Position `json:"to"`      // Path end
	Width   float64          `json:"width"`   // Required path width
	Purpose string           `json:"purpose"` // "entrance", "exit", "feature_access"
}

Path represents a required path through the room

type PathConstraint

type PathConstraint struct {
	Type      PathConstraintType `json:"type"`      // What kind of constraint
	Parameter string             `json:"parameter"` // Constraint parameter
	Weight    float64            `json:"weight"`    // How much to weight this (0.0-1.0)
}

PathConstraint represents a constraint on pathfinding Purpose: Allows complex pathfinding rules like "avoid locked doors unless entity has key" or "prefer routes through well-lit rooms".

type PathConstraintType

type PathConstraintType int

PathConstraintType categorizes different pathfinding constraints Purpose: Allows the pathfinder to handle different constraint types.

const (
	// PathConstraintTypeAvoid represents constraints to avoid certain connections
	PathConstraintTypeAvoid PathConstraintType = iota
	// PathConstraintTypePrefer represents constraints to prefer certain routes
	PathConstraintTypePrefer
	// PathConstraintTypeRequire represents constraints that must be satisfied
	PathConstraintTypeRequire
	// PathConstraintTypeCost represents constraints that consider movement costs
	PathConstraintTypeCost
)

type PathQuery

type PathQuery struct {
	From        spatial.Position `json:"from"`                  // Starting position
	To          spatial.Position `json:"to"`                    // Destination position
	EntityID    string           `json:"entity_id,omitempty"`   // Entity making the journey
	Constraints []PathConstraint `json:"constraints,omitempty"` // Movement constraints
	MaxCost     float64          `json:"max_cost,omitempty"`    // Maximum total cost
}

PathQuery represents a pathfinding query across the environment Purpose: Enables pathfinding that spans multiple rooms, considering connection types, requirements, and movement costs.

type PathSafetyParams

type PathSafetyParams struct {
	MinPathWidth      float64 `json:"min_path_width"`     // Minimum corridor width
	MinOpenSpace      float64 `json:"min_open_space"`     // % of room that must remain open
	EntitySize        float64 `json:"entity_size"`        // Size of entities that need to move
	RequiredPaths     []Path  `json:"required_paths"`     // Specific paths that must exist
	EmergencyFallback bool    `json:"emergency_fallback"` // Fall back to empty room if validation fails
}

PathSafetyParams ensures generated rooms are navigable

type PatternParams

type PatternParams struct {
	// Generation parameters
	Density           float64 `json:"density"`            // Wall density (0.0-1.0)
	DestructibleRatio float64 `json:"destructible_ratio"` // % of walls that are destructible
	RandomSeed        int64   `json:"random_seed"`        // Seed for reproducible generation

	// Safety parameters
	Safety PathSafetyParams `json:"safety"` // Path validation parameters
	Grid   spatial.Grid     `json:"-"`      // Grid for validation

	// Customization
	Material   string                 `json:"material"`    // Default wall material
	WallHeight float64                `json:"wall_height"` // Default wall height
	Properties map[string]interface{} `json:"properties"`  // Custom properties

}

PatternParams configures wall pattern generation

type PlacedEntityData added in v0.4.0

type PlacedEntityData struct {
	// ID is the unique identifier for this entity
	ID string `json:"id"`

	// Type is a game-specific entity type (e.g., "monster", "door", "character")
	// The environments package does not interpret this value
	Type string `json:"type"`

	// Position is where the entity is located in absolute coordinates
	Position spatial.CubeCoordinate `json:"position"`

	// Size is how many hexes the entity occupies (1 = single hex)
	Size int `json:"size"`

	// BlocksMovement indicates if other entities cannot move through this space
	BlocksMovement bool `json:"blocks_movement"`

	// BlocksLoS indicates if this entity blocks line of sight
	BlocksLoS bool `json:"blocks_los"`

	// ZoneID indicates which zone this entity belongs to
	// Used for visibility filtering and zone-based queries
	ZoneID string `json:"zone_id"`

	// Subtype is a game-specific visual/behavioral subtype
	// Games map this to assets or behaviors
	Subtype string `json:"subtype,omitempty"`

	// Properties contains game-specific data using typed keys
	// The environments package does not interpret this data
	Properties map[PropertyKey]any `json:"properties,omitempty"`
}

PlacedEntityData represents an entity placed in the environment. All positions are in absolute environment coordinates.

This is a generic placement record - the entity type and properties are game-specific strings/data.

type PrefabConnection

type PrefabConnection struct {
	Position spatial.Position `json:"position"` // Where the connection attaches
	Type     string           `json:"type"`     // What type of connection
	Required bool             `json:"required"` // Must this connection exist
	Name     string           `json:"name"`     // Connection identifier
}

PrefabConnection represents a connection point in a room prefab Purpose: Defines where connections can be made to this prefab room. Allows prefabs to specify valid connection points and types.

type PropertyKey added in v0.4.0

type PropertyKey string

PropertyKey is a typed string for entity property keys. Rulebooks define constants using this type (e.g., "open", "locked", "dc"). Using typed keys provides IDE autocomplete for property discovery.

type QueryExecutedEvent added in v0.1.1

type QueryExecutedEvent struct {
	QueryType  string      `json:"query_type"`
	Query      interface{} `json:"query"`
	ExecutedAt time.Time   `json:"executed_at"`
}

QueryExecutedEvent contains data for environment query execution events

type QueryFailedEvent added in v0.1.1

type QueryFailedEvent struct {
	QueryType string      `json:"query_type"`
	Query     interface{} `json:"query"`
	Error     string      `json:"error"`
	FailedAt  time.Time   `json:"failed_at"`
}

QueryFailedEvent contains data for environment query failure events

type QueryHandler

type QueryHandler interface {
	// HandleEntityQuery processes entity queries
	HandleEntityQuery(ctx context.Context, query EntityQuery) ([]core.Entity, error)

	// HandleRoomQuery processes room queries
	HandleRoomQuery(ctx context.Context, query RoomQuery) ([]spatial.Room, error)

	// HandlePathQuery processes pathfinding queries
	HandlePathQuery(ctx context.Context, query PathQuery) ([]spatial.Position, error)
}

QueryHandler defines the interface for environment queries

type Range

type Range struct {
	Min, Max float64
}

Range represents a numeric range for parameter variance multiplication Purpose: Enables selectables to choose constraint profiles while maintaining infinite procedural variety within those constraints

func (Range) Contains

func (r Range) Contains(value float64) bool

Contains checks if a value falls within the range (inclusive)

func (Range) Random

func (r Range) Random() float64

Random returns a random value within the range using math/rand Note: Uses math/rand (not crypto/rand) for deterministic, reproducible room generation when combined with seeded random sources

func (Range) String

func (r Range) String() string

String returns a string representation of the range

type RoomBuilder

type RoomBuilder interface {
	// WithSize sets the room dimensions
	WithSize(width, height int) RoomBuilder

	// WithTheme sets the room theme
	WithTheme(theme string) RoomBuilder

	// WithFeatures adds features to the room
	WithFeatures(features ...Feature) RoomBuilder

	// WithLayout sets the room layout
	WithLayout(layout Layout) RoomBuilder

	// WithPrefab applies a prefab template
	WithPrefab(prefab RoomPrefab) RoomBuilder

	// WithWallPattern sets the wall pattern
	WithWallPattern(pattern string) RoomBuilder

	// WithWallDensity sets the wall density
	WithWallDensity(density float64) RoomBuilder

	// WithDestructibleRatio sets the destructible wall ratio
	WithDestructibleRatio(ratio float64) RoomBuilder

	// WithMaterial sets the wall material
	WithMaterial(material string) RoomBuilder

	// WithShape sets the room shape by name
	WithShape(shapeName string) RoomBuilder

	// WithRandomSeed sets the random seed
	WithRandomSeed(seed int64) RoomBuilder

	// WithSafety sets the path safety parameters
	WithSafety(safety PathSafetyParams) RoomBuilder

	// Build creates the room
	Build() (spatial.Room, error)
}

RoomBuilder defines the interface for component-based room building

type RoomBuiltEvent added in v0.1.1

type RoomBuiltEvent struct {
	RoomID     string                 `json:"room_id"`
	Size       map[string]interface{} `json:"size"`
	Theme      string                 `json:"theme"`
	Pattern    string                 `json:"pattern"`
	Features   []string               `json:"features,omitempty"`
	Properties map[string]interface{} `json:"properties,omitempty"`
	BuiltAt    time.Time              `json:"built_at"`
}

RoomBuiltEvent contains data for room construction completion events

type RoomGenerationRequest

type RoomGenerationRequest struct {
	Purpose             string                                     // "combat", "exploration", "boss"
	Difficulty          int                                        // 1-5 scale influences constraints
	EntityCount         int                                        // Expected entity count for sizing
	SpatialFeeling      SpatialFeeling                             // "tight", "normal", "vast"
	RequiredConnections int                                        // Number of connection points needed
	CustomTables        map[string]selectables.SelectionTable[any] // Optional table overrides
	Context             map[string]interface{}                     // Additional context for selection
}

RoomGenerationRequest contains all criteria for room generation Purpose: Provides context for selectables-driven room generation with optional customization capabilities

type RoomGraph

type RoomGraph struct {
	// contains filtered or unexported fields
}

RoomGraph represents the abstract graph structure

type RoomNode

type RoomNode struct {
	ID         string                 `json:"id"`
	Type       string                 `json:"type"`
	Theme      string                 `json:"theme"`
	Size       spatial.Dimensions     `json:"size"`
	Features   []Feature              `json:"features"`
	Properties map[string]interface{} `json:"properties"`
	// Position is the room's origin in dungeon-absolute coordinates.
	// Set during spatial placement to enable unified coordinate system.
	Position spatial.CubeCoordinate `json:"position"`
}

RoomNode represents a room in the abstract graph

func (*RoomNode) ToAbsolute added in v0.3.0

func (r *RoomNode) ToAbsolute(local spatial.CubeCoordinate) spatial.CubeCoordinate

ToAbsolute converts room-local coordinates to dungeon-absolute coordinates

func (*RoomNode) ToLocal added in v0.3.0

func (r *RoomNode) ToLocal(absolute spatial.CubeCoordinate) spatial.CubeCoordinate

ToLocal converts dungeon-absolute coordinates to room-local coordinates

type RoomPrefab

type RoomPrefab struct {
	Name        string                 `json:"name"`        // Prefab identifier
	Type        string                 `json:"type"`        // Room type this creates
	Theme       string                 `json:"theme"`       // Visual theme
	Size        spatial.Dimensions     `json:"size"`        // Room dimensions
	Features    []Feature              `json:"features"`    // Features to place
	Connections []PrefabConnection     `json:"connections"` // Connection points
	Parameters  map[string]interface{} `json:"parameters"`  // Customization parameters
}

RoomPrefab represents a pre-designed room template Purpose: Allows designers to create reusable room templates that can be instantiated during generation. Supports both exact layouts and parameterized templates.

type RoomProfile

type RoomProfile struct {
	DensityRange      Range         // Wall density constraints (0.0-1.0)
	DestructibleRange Range         // Destructible wall ratio constraints (0.0-1.0)
	PatternAlgorithm  string        // "random", "clustered", "sparse", "empty"
	Shape             string        // "rectangle", "square", "hexagon", "t_shape"
	RotationMode      string        // "random", "fixed", "cardinal_only"
	SafetyProfile     SafetyProfile // Path safety requirements
}

RoomProfile represents a complete room generation profile composed from multiple selectables table selections Purpose: Aggregates all parameters needed for room generation while maintaining procedural variance through range-based selection

type RoomQuery

type RoomQuery struct {
	// Basic criteria
	RoomTypes []string `json:"room_types,omitempty"` // Room types to include
	Themes    []string `json:"themes,omitempty"`     // Themes to include
	Features  []string `json:"features,omitempty"`   // Required features

	// Spatial criteria
	NearPosition *spatial.Position `json:"near_position,omitempty"` // Near this position
	MaxDistance  int               `json:"max_distance,omitempty"`  // Max connections away

	// Connection criteria
	ConnectedTo    string `json:"connected_to,omitempty"`    // Must connect to this room
	MinConnections int    `json:"min_connections,omitempty"` // Minimum number of connections
	MaxConnections int    `json:"max_connections,omitempty"` // Maximum number of connections

	// Result limits
	Limit int `json:"limit,omitempty"` // Max results to return
}

RoomQuery represents a query for rooms in the environment Purpose: Allows complex room searches like "find all treasure rooms within 3 connections of the entrance" or "find rooms with theme X and feature Y".

type RoomShape

type RoomShape struct {
	Name        string `json:"name"`        // Shape identifier
	Description string `json:"description"` // Human-readable description
	Type        string `json:"type"`        // "basic", "junction", "hub"

	// Grid-agnostic boundary definition
	// Uses normalized coordinates (0.0-1.0) that get scaled to actual size
	Boundary []spatial.Position `json:"boundary"` // Outer boundary points

	// Connection points where this room can connect to others
	Connections []ConnectionPoint `json:"connections"` // Where connections attach

	// Metadata for pattern generation
	Properties map[string]interface{} `json:"properties"` // Shape-specific properties

	// Grid compatibility hints
	GridHints GridHints `json:"grid_hints"` // Grid-specific guidance
}

RoomShape represents a room's boundary and connection points Purpose: Defines the outer boundary of a room in a grid-agnostic way. The spatial module handles the specific grid coordinate system.

func RotateShape

func RotateShape(shape *RoomShape, degrees int) *RoomShape

RotateShape rotates a shape by the specified angle (in degrees) Purpose: Applies 2D rotation transformation to shape boundary and connection points

func ScaleShape

func ScaleShape(shape *RoomShape, size spatial.Dimensions) *RoomShape

ScaleShape scales a normalized shape to actual dimensions Purpose: Converts normalized coordinates to actual grid coordinates

type RoomSplit

type RoomSplit struct {
	Reason                        string               `json:"reason"`                          // Why split is recommended
	SplitType                     string               `json:"split_type"`                      // Split type
	Dimensions                    []spatial.Dimensions `json:"dimensions"`                      // Room dimensions
	Benefits                      []string             `json:"benefits"`                        // Split advantages
	Complexity                    float64              `json:"complexity"`                      // Complexity rating
	SuggestedSize                 spatial.Dimensions   `json:"suggested_size"`                  // Split room dimensions
	ConnectionPoints              []spatial.Position   `json:"connection_points"`               // Connection points
	RecommendedEntityDistribution map[string]int       `json:"recommended_entity_distribution"` // Entity distribution
	RecommendedConnectionType     string               `json:"recommended_connection_type"`     // Connection type to use
	SplitReason                   string               `json:"split_reason"`                    // Reason for split
	EstimatedCapacityImprovement  float64              `json:"estimated_capacity_improvement"`  // Expected improvement
}

RoomSplit represents a room splitting recommendation Purpose: Advisory information about how rooms could be divided

func GetSplitOptions

func GetSplitOptions(size spatial.Dimensions, entityCount int, constraints CapacityConstraints) []RoomSplit

GetSplitOptions provides room splitting options without making decisions Purpose: Advisory function that gives games splitting options to consider

type RoomTables

type RoomTables struct {
	DensityTable      selectables.SelectionTable[Range]
	DestructibleTable selectables.SelectionTable[Range]
	PatternTable      selectables.SelectionTable[string]
	ShapeTable        selectables.SelectionTable[string]
	RotationModeTable selectables.SelectionTable[string]
	SafetyTable       selectables.SelectionTable[SafetyProfile]
}

RoomTables aggregates all selectables tables needed for room generation Purpose: Provides a complete set of tables for modular room generation

func GetBalancedCoverTables

func GetBalancedCoverTables() RoomTables

GetBalancedCoverTables returns tables for medium wall density rooms Purpose: Provides balanced wall coverage (0.4-0.7 range) for general use

func GetDefaultRoomTables

func GetDefaultRoomTables() RoomTables

GetDefaultRoomTables returns the standard set of tables for room generation Purpose: Provides default tables with balanced variety for general use

func GetDenseCoverTables

func GetDenseCoverTables() RoomTables

GetDenseCoverTables returns tables for high wall density rooms Purpose: Provides dense wall coverage (0.6-0.9 range) for complex navigation and tactical positioning

func GetSparseCoverTables

func GetSparseCoverTables() RoomTables

GetSparseCoverTables returns tables for low wall density rooms Purpose: Provides sparse wall coverage (0.1-0.4 range) for movement-focused gameplay

type SafetyProfile

type SafetyProfile struct {
	Name              string  // Profile identifier for selectables
	Description       string  // Human-readable description
	MinPathWidth      float64 // Minimum corridor width
	MinOpenSpace      float64 // % of room that must remain open (0.0-1.0)
	EntitySize        float64 // Size of entities that need to move
	EmergencyFallback bool    // Fall back to empty room if validation fails
}

SafetyProfile represents path safety requirements for room generation Purpose: Provides a comparable type for selectables that creates PathSafetyParams

func (SafetyProfile) ToPathSafetyParams

func (s SafetyProfile) ToPathSafetyParams() PathSafetyParams

ToPathSafetyParams converts SafetyProfile to PathSafetyParams for room generation Purpose: Bridges selectables-compatible type to existing room builder requirements

type ShapeLoader

type ShapeLoader struct {
	// contains filtered or unexported fields
}

ShapeLoader handles loading room shapes from various sources Purpose: Provides flexible shape loading while maintaining grid compatibility

func NewShapeLoader

func NewShapeLoader(shapesPath string) *ShapeLoader

NewShapeLoader creates a new shape loader

func (*ShapeLoader) GetAvailableShapes

func (sl *ShapeLoader) GetAvailableShapes() ([]string, error)

GetAvailableShapes returns list of available shape names

func (*ShapeLoader) LoadAllShapes

func (sl *ShapeLoader) LoadAllShapes() (map[string]*RoomShape, error)

LoadAllShapes loads all available shapes

func (*ShapeLoader) LoadShape

func (sl *ShapeLoader) LoadShape(shapeName string) (*RoomShape, error)

LoadShape loads a room shape by name

type SizingQuery

type SizingQuery struct {
	Intent          SpatialIntentProfile `json:"intent"`                     // Desired spatial experience
	IntentProfile   SpatialIntentProfile `json:"intent_profile"`             // Alternative field name for intent
	EntityCount     int                  `json:"entity_count,omitempty"`     // Number of entities
	EntitySizes     []spatial.Dimensions `json:"entity_sizes,omitempty"`     // Entity dimensions
	Constraints     CapacityConstraints  `json:"constraints,omitempty"`      // Additional constraints
	AdditionalSpace float64              `json:"additional_space,omitempty"` // Extra space multiplier
	MinDimensions   spatial.Dimensions   `json:"min_dimensions,omitempty"`   // Minimum allowed dimensions
	MaxDimensions   spatial.Dimensions   `json:"max_dimensions,omitempty"`   // Maximum allowed dimensions
}

SizingQuery represents a query for optimal room sizing Purpose: Helps determine appropriate room dimensions for specific requirements

type SpatialFeeling

type SpatialFeeling string

SpatialFeeling represents the intended spatial experience for room design

const (
	// SpatialFeelingTight creates intimate, claustrophobic spaces
	SpatialFeelingTight SpatialFeeling = "tight"
	// SpatialFeelingNormal creates balanced, tactical spaces
	SpatialFeelingNormal SpatialFeeling = "normal"
	// SpatialFeelingVast creates expansive, epic spaces
	SpatialFeelingVast SpatialFeeling = "vast"
)

type SpatialIntentProfile

type SpatialIntentProfile struct {
	Feeling              SpatialFeeling `json:"feeling"`                // The desired spatial experience
	EntityDensityTarget  float64        `json:"entity_density_target"`  // Target entity density (0.0-1.0)
	MovementFreedomIndex float64        `json:"movement_freedom_index"` // Movement space factor (0.0-1.0)
	VisualScopeIndex     float64        `json:"visual_scope_index"`     // Visual range factor (0.0-1.0)
	TacticalComplexity   float64        `json:"tactical_complexity"`    // Tactical positioning complexity (0.0-1.0)
}

SpatialIntentProfile translates design concepts into technical parameters Purpose: Converts feeling-based design decisions into concrete spatial calculations

func GetDefaultSpatialIntentProfile

func GetDefaultSpatialIntentProfile(feeling SpatialFeeling) SpatialIntentProfile

GetDefaultSpatialIntentProfile returns a profile for the given spatial feeling Purpose: Provides sensible defaults based on the feeling-based design approach

type ThemeChangedEvent added in v0.1.1

type ThemeChangedEvent struct {
	EnvironmentID string    `json:"environment_id"`
	OldTheme      string    `json:"old_theme"`
	NewTheme      string    `json:"new_theme"`
	AffectedRooms []string  `json:"affected_rooms,omitempty"`
	ChangedAt     time.Time `json:"changed_at"`
}

ThemeChangedEvent contains data for environment theme change events

type WallEntity

type WallEntity struct {
	// contains filtered or unexported fields
}

WallEntity represents a wall as a spatial entity Purpose: Integrates generated walls with spatial module's existing obstacle system by implementing the Placeable interface. This allows walls to automatically affect line of sight, movement, and pathfinding without duplicating logic.

func FindWallEntitiesBySegment

func FindWallEntitiesBySegment(entities []spatial.Placeable, segmentID string) []*WallEntity

FindWallEntitiesBySegment finds all wall entities that belong to a specific segment

func GetWallEntitiesInRoom

func GetWallEntitiesInRoom(room spatial.Room) []*WallEntity

GetWallEntitiesInRoom returns all wall entities in a room

func NewWallEntity

func NewWallEntity(config WallEntityConfig) *WallEntity

NewWallEntity creates a new wall entity

func (*WallEntity) BlocksLineOfSight

func (w *WallEntity) BlocksLineOfSight() bool

BlocksLineOfSight checks if this wall blocks line of sight

func (*WallEntity) BlocksMovement

func (w *WallEntity) BlocksMovement() bool

BlocksMovement checks if this wall blocks movement

func (*WallEntity) Destroy

func (w *WallEntity) Destroy()

Destroy immediately destroys the wall (bypasses HP)

func (*WallEntity) GetCurrentHP

func (w *WallEntity) GetCurrentHP() int

GetCurrentHP returns the current health points

func (*WallEntity) GetID

func (w *WallEntity) GetID() string

GetID returns the unique ID of this entity

func (*WallEntity) GetPosition

func (w *WallEntity) GetPosition() spatial.Position

GetPosition returns the position this wall entity occupies

func (*WallEntity) GetProperties

func (w *WallEntity) GetProperties() WallProperties

GetProperties returns the wall properties

func (*WallEntity) GetSegmentID

func (w *WallEntity) GetSegmentID() string

GetSegmentID returns the ID of the original wall segment

func (*WallEntity) GetSize

func (w *WallEntity) GetSize() int

GetSize returns the size of this entity

func (*WallEntity) GetType

func (w *WallEntity) GetType() core.EntityType

GetType returns the type of this entity

func (*WallEntity) GetWallType

func (w *WallEntity) GetWallType() WallType

GetWallType returns the wall type (destructible, indestructible, etc.)

func (*WallEntity) IsDestroyed

func (w *WallEntity) IsDestroyed() bool

IsDestroyed returns whether this wall has been destroyed

func (*WallEntity) Repair

func (w *WallEntity) Repair(healAmount int)

Repair restores health points to the wall

func (*WallEntity) TakeDamage

func (w *WallEntity) TakeDamage(damage int, damageType string) bool

TakeDamage applies damage to the wall

type WallEntityConfig

type WallEntityConfig struct {
	SegmentID  string
	WallType   WallType
	Properties WallProperties
	Position   spatial.Position
}

WallEntityConfig configures wall entity creation

type WallPatternFunc

type WallPatternFunc func(
	ctx context.Context, shape *RoomShape, size spatial.Dimensions, params PatternParams,
) ([]WallSegment, error)

WallPatternFunc generates wall patterns algorithmically

type WallProperties

type WallProperties struct {
	// Destruction properties
	HP           int      `json:"hp,omitempty"`            // Health points
	Resistance   []string `json:"resistance,omitempty"`    // Damage types resisted
	Weakness     []string `json:"weakness,omitempty"`      // Extra damage types
	RequiredTool string   `json:"required_tool,omitempty"` // Specific tool needed

	// Physical properties
	Material  string  `json:"material"`  // Stone, wood, metal, etc.
	Thickness float64 `json:"thickness"` // Wall thickness
	Height    float64 `json:"height"`    // Wall height

	// Gameplay properties
	BlocksLoS      bool `json:"blocks_los"`      // Blocks line of sight
	BlocksMovement bool `json:"blocks_movement"` // Blocks movement
	ProvidesCover  bool `json:"provides_cover"`  // Combat cover bonus

	// Audio/Visual
	DestroySound string `json:"destroy_sound,omitempty"` // Sound when destroyed
	Texture      string `json:"texture,omitempty"`       // Visual texture
}

WallProperties defines wall behavior and appearance

type WallSegment

type WallSegment struct {
	Start      spatial.Position `json:"start"`      // Wall start position
	End        spatial.Position `json:"end"`        // Wall end position
	Type       WallType         `json:"type"`       // Destructible, indestructible, etc.
	Properties WallProperties   `json:"properties"` // Wall behavior properties
}

WallSegment represents a wall within a room Purpose: Defines walls with destruction properties for tactical gameplay

func EmptyPattern

func EmptyPattern(
	_ context.Context, shape *RoomShape, size spatial.Dimensions, params PatternParams,
) ([]WallSegment, error)

EmptyPattern generates no internal walls

func RandomPattern

func RandomPattern(
	ctx context.Context, shape *RoomShape, size spatial.Dimensions, params PatternParams,
) ([]WallSegment, error)

RandomPattern generates random wall segments based on density parameter

type WallSegmentData added in v0.4.0

type WallSegmentData struct {
	// Start is one endpoint of the wall segment
	Start spatial.CubeCoordinate `json:"start"`

	// End is the other endpoint of the wall segment
	End spatial.CubeCoordinate `json:"end"`

	// BlocksMovement indicates if entities cannot pass through
	BlocksMovement bool `json:"blocks_movement"`

	// BlocksLoS indicates if the wall blocks line of sight
	BlocksLoS bool `json:"blocks_los"`
}

WallSegmentData represents a wall segment in the environment. Walls are defined by their endpoints in absolute coordinates.

Purpose: Enables collision detection and line-of-sight calculations.

type WallType

type WallType int

WallType categorizes wall behavior

const (
	// WallTypeIndestructible represents permanent structural walls.
	WallTypeIndestructible WallType = iota // Permanent structural walls
	// WallTypeDestructible represents walls that can be destroyed by players.
	WallTypeDestructible // Can be destroyed by players
	// WallTypeTemporary represents walls that can be bypassed with effort.
	WallTypeTemporary // Can be bypassed with effort
	// WallTypeConditional represents walls that require specific tools/abilities.
	WallTypeConditional // Requires specific tools/abilities
)

type ZoneData added in v0.4.0

type ZoneData struct {
	// ID is the unique identifier for this zone
	ID string `json:"id"`

	// Type categorizes the zone (game-specific, e.g., "room", "corridor", "outdoor")
	Type string `json:"type"`

	// Origin is the zone's position in absolute environment coordinates
	// This is where the zone's local (0,0,0) maps to in environment space
	Origin spatial.CubeCoordinate `json:"origin"`

	// Width is the number of hexes across (X range in cube coordinates)
	Width int `json:"width"`

	// Height is the number of hexes down (Z range in cube coordinates)
	Height int `json:"height"`

	// GridShape specifies the grid type (hex, square, gridless)
	GridShape GridShapeValue `json:"grid_shape"`

	// Orientation specifies hex orientation (pointy or flat), only for hex grids
	Orientation HexOrientationValue `json:"orientation,omitempty"`

	// EntityIDs lists all entities that belong to this zone
	// Useful for zone-based queries and visibility filtering
	EntityIDs []string `json:"entity_ids,omitempty"`
}

ZoneData represents a logical zone within an environment. Zones are boundaries for queries and visibility, not separate coordinate spaces. All coordinates are already absolute.

Purpose: Allows queries like "what zone contains this hex?" and enables zone-based visibility control.

Directories

Path Synopsis
Package mock is a generated GoMock package.
Package mock is a generated GoMock package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL