No description
Find a file
Midas van Oene a1b0b564fc
All checks were successful
Build and Publish / build (push) Successful in 2m31s
Merge renovate/sveltejs-vite-plugin-svelte-7.x
2026-04-10 12:14:40 +02:00
.forgejo/workflows Update actions/checkout action to v6 2026-04-05 22:03:29 +00:00
.mvn/wrapper Update dependency maven to v3.9.14 2026-04-10 11:29:22 +02:00
frontend chore(deps): update @sveltejs/vite-plugin-svelte to v7 + vite to v8 2026-04-10 12:14:35 +02:00
Harena API basic frontend 2026-03-07 19:55:53 +01:00
screenshots Arenas 2026-03-08 17:45:43 +01:00
src Meerdere gladiators per event 2026-03-09 12:46:05 +01:00
.gitattributes initial commit 2026-03-07 12:58:32 +01:00
.gitattributes:Zone.Identifier initial commit 2026-03-07 12:58:32 +01:00
.gitignore initial commit 2026-03-07 12:58:32 +01:00
.gitignore:Zone.Identifier initial commit 2026-03-07 12:58:32 +01:00
CLAUDE.md Meerdere gladiators per event 2026-03-09 12:46:05 +01:00
docker-compose.yml Phase 1 setup 2026-03-07 17:10:21 +01:00
Dockerfile fix dockerfile 2026-03-08 11:08:09 +01:00
HARENA_ARENAS.md Arenas 2026-03-08 17:45:43 +01:00
HARENA_ARENAS.md:Zone.Identifier Arenas 2026-03-08 17:45:43 +01:00
HELP.md:Zone.Identifier initial commit 2026-03-07 12:58:32 +01:00
mvnw Phase 1 setup 2026-03-07 17:10:21 +01:00
mvnw.cmd initial commit 2026-03-07 12:58:32 +01:00
pom.xml Update dependency org.openapitools:openapi-generator-maven-plugin to v7.21.0 2026-04-10 12:10:54 +02:00
pom.xml:Zone.Identifier initial commit 2026-03-07 12:58:32 +01:00
README.md basic frontend 2026-03-07 19:55:53 +01:00
renovate.json Add renovate.json 2026-04-03 20:42:02 +00:00

Harena

A gladiator management game built API-first. You are a lanista — master of a gladiatorial school in ancient Rome. Train your fighters, send them to the arena, watch them die. The API is the game.

Inspired by Top Eleven (Nordeus). Designed so humans and AI agents play through the same REST API.


Quick start

# Run in dev mode (H2 in-memory database, no setup needed)
./mvnw spring-boot:run -Dspring-boot.run.profiles=dev

Open http://localhost:8080 for the game UI, or http://localhost:8080/swagger-ui.html for the raw API explorer.


Game loop

Every action is an API call. No UI required.

1. Create your ludus

POST /api/v1/ludus
{ "name": "Ludus Magnus" }

Gives you 5000 denarii and 3 random gladiators.

2. Seed the market

POST /api/v1/game/tick

Populates the market with ~8 gladiators for sale and processes any pending training.

3. Inspect your roster

GET /api/v1/gladiators

Check stats, health, state, and readyToFight.

4. Send someone to fight

POST /api/v1/fights
{ "gladiatorId": "<uuid>", "aggression": "BALANCED" }

The system generates a matched opponent. Aggression choices: CAUTIOUS / BALANCED / AGGRESSIVE.

5. Resolve the fight

POST /api/v1/fights/<id>/resolve

The match engine runs turn-by-turn. Read eventLog in the response for the play-by-play. Gladiators can die permanently.

6. Train between fights

POST /api/v1/gladiators/<id>/train
{ "stat": "STRENGTH" }

POST /api/v1/game/tick   ← training applies here (+3 to +5 points)

7. Buy from the market

GET  /api/v1/market
POST /api/v1/market/<listingId>/purchase

Full snapshot (useful for AI agents)

GET /api/v1/game/state

Running with PostgreSQL

# Start the database
docker-compose up -d db

# Run the app
./mvnw spring-boot:run

Or run everything at once:

docker-compose up

Frontend

A Svelte 5 UI is included in frontend/. It embeds into the Spring Boot JAR as static files.

# Dev mode — hot-reload UI against the running backend
cd frontend
npm install
npm run dev          # http://localhost:5173 (proxies /api to :8080)

# Build and embed into the JAR (requires Node on PATH)
./mvnw package -P build-frontend

The production build writes to src/main/resources/static/ so Spring Boot serves the UI at /.


Development

# Run tests
./mvnw test

# After editing openapi.yaml — regenerate interfaces
./mvnw generate-sources

# Build a Docker image
docker build -t harena .

OpenAPI-first workflow

The API contract lives in src/main/resources/static/openapi.yaml. It is the single source of truth.

When you change the spec:

  1. Run ./mvnw generate-sources
  2. Generated interfaces and models are updated in target/generated-sources/
  3. The compiler flags any controller that no longer satisfies the interface
  4. Update the controller

The spec is served at http://localhost:8080/openapi.yaml and can be imported directly into Bruno or Postman.


Tech stack

Language Kotlin 1.9.25 (JVM 21)
Framework Spring Boot 3.5.11
Database PostgreSQL (default), H2 (dev)
Migrations Flyway
API contract OpenAPI 3, code-generated via openapi-generator
API docs Swagger UI (/swagger-ui.html)
Frontend Svelte 5 + Vite 5 (embedded in JAR)
Testing JUnit 5, MockK, Testcontainers

Game mechanics

Fighting styles (rock-paper-scissors matchup)

Style Beats Loses to
MURMILLO RETIARIUS THRAEX
RETIARIUS SECUTOR MURMILLO
THRAEX MURMILLO SECUTOR
SECUTOR THRAEX RETIARIUS

Aggression settings

Setting Attack Defense Death chance on KO
CAUTIOUS 0.75× 1.20× 10%
BALANCED 1.00× 1.00× 25%
AGGRESSIVE 1.35× 0.75× 55%

Tick processing (in order)

  1. Training completes — 35 stat points applied, gladiator returns to RESTING
  2. Injured heal — INJURED (+10 HP/tick → RECOVERING at 30 HP), RECOVERING (+15 HP/tick → RESTING at 80 HP)
  3. Upkeep — 10 denarii per living gladiator
  4. Morale — +5 per gladiator (capped at 100)
  5. Market — topped up to ~8 available listings

Gladiator states

  • RESTING — ready to fight or train
  • TRAINING — gains stat on next tick
  • INJURED — health < 30, heals slowly
  • RECOVERING — health 3079, heals faster
  • DEAD — permanent