Add height zones, jetpack boost particles, and TigerStyle guidelines
Level generator: add vertical variety with tall levels (46 tiles). Segment generators accept ground_row parameter, SEG_CLIMB connects height zones, transitions inherit predecessor ground row to prevent walkability gaps. Climb segments respect traversal direction. Jetpack boost: add blue flame particles during dash (burst + trail) and continuous idle glow from player back while boost timer is active. Camera: add 30px vertical look-ahead when player velocity exceeds 50 px/s. Fix flame vent pedestal in gen_pit to use ground-relative position instead of map bottom (broken in tall HIGH-zone levels). Add TigerStyle coding guidelines to AGENTS.md adapted for C11. Add tall_test.lvl (40x46) for height zone validation.
This commit is contained in:
94
AGENTS.md
94
AGENTS.md
@@ -129,6 +129,100 @@ Paths are forward-slash, relative to `src/` or `include/`: `"engine/core.h"`, `"
|
||||
- `snprintf` / `strncpy` with explicit size limits for strings
|
||||
- `ASSET_PATH_MAX` (256) for path buffers
|
||||
|
||||
## TigerStyle Guidelines
|
||||
|
||||
Follow the principles from [TigerStyle](https://github.com/tigerbeetle/tigerbeetle/blob/main/docs/TIGER_STYLE.md),
|
||||
adapted for this C11 codebase. The design goals are **safety, performance, and developer
|
||||
experience**, in that order.
|
||||
|
||||
### Safety
|
||||
|
||||
- **Simple, explicit control flow.** No recursion. Minimal abstractions — only where they
|
||||
genuinely model the domain. Every abstraction has a cost; prefer straightforward code.
|
||||
|
||||
- **Put a limit on everything.** All loops and queues must have a fixed upper bound. Use
|
||||
`MAX_ENTITIES`, `MAX_ENTITY_SPAWNS`, `MAX_EXIT_ZONES`, etc. Where a loop cannot terminate
|
||||
(e.g. the game loop), document why.
|
||||
|
||||
- **Assert preconditions, postconditions, and invariants.** Validate function arguments and
|
||||
return values. A function must not operate blindly on unchecked data. In C, use `assert()`
|
||||
or early-return checks with `fprintf(stderr, ...)` for runtime-recoverable cases.
|
||||
Split compound conditions: prefer `assert(a); assert(b);` over `assert(a && b);`.
|
||||
|
||||
- **Assert the positive and negative space.** Check what you expect AND what you do not expect.
|
||||
Bugs live at the boundary between valid and invalid data.
|
||||
|
||||
- **Static allocation after initialization.** Fixed-size arrays for collections (`MAX_ENTITIES`
|
||||
pool, tile defs). Dynamic allocation (`calloc`) only during level loading for tile layers.
|
||||
No allocation or reallocation during gameplay.
|
||||
|
||||
- **Smallest possible scope for variables.** Declare variables close to where they are used.
|
||||
Minimize the number of live variables at any point.
|
||||
|
||||
- **Hard limit of ~70 lines per function.** When splitting, centralize control flow (switch/if)
|
||||
in the parent function and push pure computation into helpers. Keep leaf functions pure.
|
||||
"Push `if`s up and `for`s down."
|
||||
|
||||
- **Zero compiler warnings.** All builds must pass `-Wall -Wextra` with zero warnings.
|
||||
|
||||
- **Handle all errors.** Every `fopen`, `calloc`, `snprintf` return must be checked. Early
|
||||
return on failure.
|
||||
|
||||
### Performance
|
||||
|
||||
- **Think about performance in the design phase.** The biggest wins (1000x) come from
|
||||
structural decisions, not micro-optimization after the fact.
|
||||
|
||||
- **Back-of-the-envelope sketches** for the four resources: network, disk, memory, CPU.
|
||||
For a game: frame budget is ~16ms at 60 Hz. Know where time goes.
|
||||
|
||||
- **Optimize for the slowest resource first** (disk > memory > CPU), weighted by frequency.
|
||||
A cache miss that happens every frame matters more than a disk read that happens once at
|
||||
level load.
|
||||
|
||||
- **Batch and amortize.** Sprite batching via `renderer_submit()`. Particle pools. Tile
|
||||
culling to the viewport. Don't iterate what you don't need to.
|
||||
|
||||
- **Be explicit with the compiler.** Don't rely on the optimizer to fix structural problems.
|
||||
Extract hot inner loops into standalone helpers with primitive arguments when it helps
|
||||
clarity and performance.
|
||||
|
||||
### Developer Experience
|
||||
|
||||
- **Get the nouns and verbs right.** Names should capture what a thing is or does. Take time
|
||||
to find the right name. Module-prefixed functions (`player_update`, `tilemap_load`) already
|
||||
enforce this.
|
||||
|
||||
- **Add units or qualifiers last, sorted by descending significance.** For example,
|
||||
`latency_ms_max` not `max_latency_ms`. Related variables then align: `latency_ms_min`,
|
||||
`latency_ms_avg`.
|
||||
|
||||
- **Always say why.** Comments explain rationale, not just what the code does. If a design
|
||||
decision isn't obvious, explain the tradeoff. Code alone is not documentation.
|
||||
|
||||
- **Comments are sentences.** Capital letter, full stop, space after `/*`. End-of-line
|
||||
comments can be phrases without punctuation.
|
||||
|
||||
- **Order matters for readability.** Put important things near the top of a file. Public API
|
||||
first, then helpers. In structs, fields before methods.
|
||||
|
||||
- **Don't duplicate variables or alias them.** One source of truth per value. Reduces the
|
||||
chance of state getting out of sync.
|
||||
|
||||
- **Calculate or check variables close to where they are used.** Don't introduce variables
|
||||
before they are needed. Minimize the gap between place-of-check and place-of-use.
|
||||
|
||||
- **Descriptive commit messages.** Imperative mood. Inform the reader about the why, not
|
||||
just the what. The commit message is the permanent record — PR descriptions are not
|
||||
stored in git.
|
||||
|
||||
### Zero Technical Debt
|
||||
|
||||
Do it right the first time. Don't allow known issues to slip through — exponential-complexity
|
||||
algorithms, unbounded loops, potential buffer overflows. What we ship is solid. We may lack
|
||||
features, but what we have meets our design goals. This is the only way to make steady
|
||||
incremental progress.
|
||||
|
||||
## Architecture Patterns
|
||||
|
||||
### Entity System
|
||||
|
||||
Reference in New Issue
Block a user