Welcome to Echoes in the Dark — a modern, modular roguelike engine and game demo built in OCaml. This project is all about learning, experimentation, and pushing the boundaries of functional game development.
- Turn-based, entity-driven roguelike with a focus on extensibility and clarity.
- Entity-Component System (ECS): All game objects are entities with flexible, composable components.
- Infinite/Procedural World: Powered by a dynamic chunking system for seamless exploration.
- Modern OCaml: Uses the Base library, functional patterns, and Raylib bindings for graphics/input/audio.
- Modular Architecture: Clean separation of UI, core logic, resources, and utilities.
- System Architecture: High-level overview, major modules, and how everything fits together.
- Project Structure: Directory/module breakdown, dependency diagrams, and data flow.
- Chunking System: How the world is split into 32x32 chunks for infinite/procedural generation.
- Workflow & Coding Policies: How we work, code, and contribute (OCaml functional style, memory files, reviews, etc.).
- Story & Lore: The narrative, world, and monster/item lists.
opam install . --deps-onlydune build
dune exec echoes_darksrc/— Main source code (ECS, systems, chunking, UI, etc.)test/— Testsmedia/— Screenshots and assetsresources/— Game resources (fonts, images, prefabs, tiles)docs/— All project documentation (see above)
See project_structure.md for full details and diagrams.
- Entity-Component System: Flexible, extensible, and easy to hack on.
- Dynamic Chunking: Infinite/procedural world, loaded in 32x32 tile chunks around the player.
- Functional OCaml: Modern, idiomatic code using Base and best practices.
- Raylib Integration: Fast graphics, input, and audio.
- Clear Docs: Everything you need to understand, extend, or contribute.
We welcome all contributors — whether you're new to OCaml, games, or just want to help!
- Read the Workflow & Coding Policies before starting.
- Fork the repo, create a feature branch, and open a pull request.
- All code is reviewed for clarity, style, and function.
- Update docs and memory files as you go.
- Be functional, be idiomatic, be kind.
MIT — see LICENSE for details.
- For technical details, see architecture.md and chunking_design.md.
- For project goals and roadmap, see the memory files in
docs/andtasks/. - For help or questions, open an issue or discussion!
To help optimize performance in this roguelike game, the following features have been implemented:
The traditional ECS implementation using hashtables has been enhanced with a packed array alternative that can be used for performance-critical operations:
- The
Components.Packed_componentsmodule provides efficient array-based storage for hot components - Components implemented with packed arrays include: Position, Stats, Blocking, and Renderable
- This provides better data locality and cache efficiency compared to hashtables
- The packed representation supports batch operations for processing multiple entities efficiently
The game includes a built-in performance profiling system that can be enabled with the --profile command-line flag:
./echoes_dark --profile
When enabled, this will:
- Track component access patterns and timing
- Generate periodic performance reports showing hotspots
- Enable the use of optimized data structures for performance-critical operations
To add profiling to a new component:
- Update the
performance_profiler.mlmodule to track the new component type - Create wrapper functions that time component access
- Update systems to use packed components for batch operations where appropriate
For future development, consider these optimization guidelines:
- Use packed arrays for components that are frequently accessed
- Implement batch operations for processing multiple entities at once
- Keep hot data together for better cache locality
- Use the profiler to identify bottlenecks before optimizing
- Consider spatial partitioning for collision and visibility tests
- Minimize dynamic memory allocation during the game loop
The performance tools make it easy to measure the impact of optimizations and ensure the game runs smoothly even with many entities.

