Version: 1.0.0
A single-player online strategy game with army movement, territory control, and AI opponent
Barony is a browser-based turn-based strategy game where you command armies to capture villages and castles against an AI opponent. Build your forces, control territory, and use strategic policies to defeat your enemy.
- PLAYER_GUIDE.md - Complete guide to playing Barony (start here!)
- DOCS.md - Documentation index (find what you need)
- CHANGELOG.md - Version history and features
- MVP.md - MVP specification and implementation details
- ROADMAP.md - Future feature roadmap (v1.1+)
- TICKETS.md - Development tickets and tasks
Barony authenticates players through the standalone UserAuth
service, which docker-compose builds from a sibling checkout. Clone it next to this repo first:
# from the directory that contains barony/
git clone https://github.com/Preponderous-Software/UserAuth.git
cd barony
# JWT_SECRET must be at least 32 bytes; override the dev default in production
export JWT_SECRET="please-change-this-to-a-32-byte-minimum-secret"
docker-compose up --buildThis brings up four services together: userauth-db (Postgres), userauth (port 9998),
backend (8080), and web-client (3000). Then open http://localhost:3000 in your browser,
create an account, and log in.
If UserAuth lives elsewhere, point
USERAUTH_PATHat it (e.g.USERAUTH_PATH=../sibling/UserAuth).
# Backend
cd backend && ./mvnw spring-boot:run
# Web Client (separate terminal)
cd web-client && ./mvnw spring-boot:runThen open http://localhost:3000 in your browser.
backend/- Spring Boot REST API (game logic)web-client/- Browser-based client (HTML5 Canvas)
Single-Game Endpoints:
GET /state- Get current game statePOST /tick- Advance game by one turnPOST /command- Send MOVE or SPLIT commandPOST /api/reset- Reset gamePOST /api/decision- Change ruler policyGET /api/ruler-stats- Get realm statistics
Authenticated, Per-Player Endpoints (require the barony_token auth cookie, or an Authorization: Bearer <token> header):
GET /api/session/state- Get the authenticated player's game statePOST /api/session/tick- Advance the player's game by one turnPOST /api/session/command- Send a command for the playerPOST /api/session/reset- Reset the player's gamePOST /api/session/decision- Change ruler policy for the playerGET /api/session/ruler-stats- Get realm statistics for the player
These endpoints validate the token against UserAuth on every request, so missing,
invalid, expired, or revoked (logged-out) tokens are rejected with 401. Game state is keyed
by the authenticated username.
Authentication (proxied to the UserAuth service):
POST /api/auth/register- Create an account ({username, password})POST /api/auth/login- Log in; sets the JWT in an HttpOnlybarony_tokencookie (returns{username, expiresAt}, never the token)POST /api/auth/logout- Revoke the token and clear the cookie
Barony never stores credentials itself — it delegates to UserAuth. On login the UserAuth-issued
JWT is placed in an HttpOnly, Secure, SameSite=Lax cookie rather than handed to JavaScript, so
an XSS can't read it; the browser then sends it automatically and the backend validates it on each
authenticated game request. (A Bearer header is still accepted as a fallback for CLI / API
clients that already hold a token.)
browser → web-client (proxy) → backend → UserAuth (/register, /login, /session/validate, /logout)
# Register
curl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{"username":"alice","password":"a-strong-password"}'
# Log in — the JWT is set as an HttpOnly cookie (saved to the jar), not returned in the body
curl -c cookies.txt -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"alice","password":"a-strong-password"}'
# Use the cookie on per-player endpoints
curl -b cookies.txt http://localhost:8080/api/session/state
# Log out (revokes the token and clears the cookie; it is refused afterward)
curl -b cookies.txt -X POST http://localhost:8080/api/auth/logoutMove Army:
curl -X POST http://localhost:8080/command \
-H "Content-Type: application/json" \
-d '{"type":"MOVE","armyId":1,"targetX":5,"targetY":5}'Split Army:
curl -X POST http://localhost:8080/command \
-H "Content-Type: application/json" \
-d '{"type":"SPLIT","armyId":1,"splitAmount":5}'Change Policy:
curl -X POST http://localhost:8080/api/decision \
-H "Content-Type: application/json" \
-d '{"category":"ECONOMIC","choice":"HEAVY_TAXATION"}'For detailed API documentation, see technical sections below.
Browser-based interface with HTML5 Canvas rendering.
Start:
docker-compose upThen open http://localhost:3000
- Toast notifications replace all in-game blocking alerts
- Canvas hover tooltips (tile info, army stats, castle capture progress)
- Army selection highlight ring on canvas
- Right-click to deselect armies
- Auto Play toggle button (single button, active-state indication)
- Color-coded stats (green ≥ 90, amber 70–89, red < 70)
- Policy cooldown progress bar
- Game-over banner overlay on canvas
- Inline split validation (no alerts)
- Colorblind modes: Deuteranopia, Protanopia, Tritanopia
- Themes: Dark (default), Classic, High Contrast
- Adjustable font size: Small, Medium, Large
- Settings panel with live preview
- Settings persisted to
localStorageunderbarony_settings
- Goal: Capture all enemy castles to win
- Players: You (blue) vs AI (red)
- Movement: Armies move 1 tile per turn
- Villages: Generate +1 soldier/turn for stationed armies
- Combat: Simultaneous damage (10 vs 7 → 3 vs 0)
- Castle Capture: Occupy for 3 consecutive turns
See PLAYER_GUIDE.md for complete gameplay instructions.
Requirements: Java 17, Maven (wrapper included)
# Backend
cd backend && ./mvnw clean package test
# Web Client
cd web-client && ./mvnw clean package testGitHub Actions runs on all PRs:
- Builds backend and web client
- Runs all unit and integration tests
- Uses JDK 17 with Maven caching
- Spring Boot REST API
- Per-player game state, kept in memory and persisted per account so games survive restarts
- Storage: embedded H2 saved to
./databy default (mount it as a volume in production); setDB_URL(+DB_USERNAME/DB_PASSWORD) to use Postgres instead - Unique army IDs (not list indices)
- CORS: localhost only
- Spring Boot + Thymeleaf
- HTML5 Canvas rendering
- RESTful backend communication
Backend won't start:
- Check Java 17:
java -version - Port 8080 in use:
lsof -i :8080(Unix) ornetstat -ano | findstr :8080(Windows)
Web client won't load:
- Ensure backend is running first
- Check that port 3000 isn't already in use
- Try clearing browser cache
Policy changes not working:
- Wait for 15-turn cooldown
- Check Ruler Stats panel for timer
- Effects are gradual (several turns)
For detailed troubleshooting, see PLAYER_GUIDE.md.
- Playing the game? See PLAYER_GUIDE.md
- Technical issues? Check the Troubleshooting section above
- Can't find what you need? See DOCS.md for documentation index
- Found a bug? Open an issue on GitHub
This project is licensed under the Stephenson Software Non-Commercial License (Stephenson-NC).
© 2025 Daniel McCoy Stephenson. All rights reserved.
You may use, modify, and share this software for non-commercial purposes only.
Commercial use is prohibited without explicit written permission from the copyright holder.
Full license text: LICENSE.md (canonical: Stephenson-Software/stephenson-nc-license)
SPDX Identifier (custom): LicenseRef-Stephenson-NC