# AutoHero

Isometric idle/incremental RPG for Telegram Mini Apps.

- **Backend**: Go — server-authoritative combat, REST + WebSocket APIs
- **Frontend**: React + TypeScript + PixiJS — isometric rendering, procedural endless map
- **Database**: PostgreSQL (primary) + Redis (caching/sessions)
- **Platform**: Telegram Mini Apps (`window.Telegram.WebApp` SDK)

## Game Features

- **Endless procedural world** — terrain, road, trees, bushes, and rocks generated on the fly
- **Semi-random hero movement** — wanders with heading drift, steering noise, and rest pauses
- **Server-authoritative encounters** — enemies spawn only from backend commands
- **Phase-based XP progression** — early levels fast, mid balanced, late slow
- **Band-based enemy scaling** — enemies scale within their level band with gentle overcap
- **Auto-equip loot** — drops auto-equip if 3%+ better, otherwise auto-sell
- **Buff system** — 8 buffs with cooldowns, persisted to database
- **Inventory HUD** — shows equipped weapon, armor (with rarity colors), and gold
- **Offline progression** — uses the same enemy/reward pipeline as online play

## Prerequisites

- Docker + Docker Compose
- Node.js 20+ and npm (for local frontend development)
- Go 1.23+ (for running backend outside Docker)

## Environment setup

1. Copy env template:
```bash
cp .env.example .env
```
2. Set at least:
   - `ADMIN_BASIC_AUTH_USERNAME`
   - `ADMIN_BASIC_AUTH_PASSWORD`
3. Optional:
   - `ADMIN_BASIC_AUTH_REALM` (default: `AutoHero Admin`)
   - `BOT_TOKEN` (needed when you enable Telegram auth middleware)

## Run with Docker (recommended)

Start everything:
```bash
docker compose up -d --build
```

Stop:
```bash
docker compose down
```

View logs:
```bash
docker compose logs -f
```

### Database migrations (existing volumes)

`docker-entrypoint-initdb.d` only runs SQL on **first** Postgres data directory init. After pulling new code, apply incremental migrations:

```bash
make migrate
```

Or: `sh scripts/migrate.sh` (Git Bash / macOS / Linux), or `powershell -File scripts/migrate.ps1` on Windows.

By default this **skips** `000001_*` (bootstrap + seed `INSERT`s; re-running breaks duplicates). Fresh Compose volumes still get `000001` from initdb. For an **empty** DB without that hook: `make migrate-bootstrap`, or `MIGRATE_INCLUDE_BOOTSTRAP=1 sh scripts/migrate.sh`, or `powershell -File scripts/migrate.ps1 -Bootstrap`.

Default URLs:
- Backend: `http://localhost:8080`
- Frontend: `http://localhost:3001` (HTTP), `https://localhost:3000` (HTTPS)

## Run locally (split mode)

1. Start dependencies only:
```bash
docker compose up -d postgres redis
```

2. Run backend:
```bash
cd backend
go run ./cmd/server
```

3. Run frontend in another terminal:
```bash
cd frontend
npm install
npm run dev
```

Frontend dev server runs at `http://localhost:5173` and proxies `/api` + `/ws` to backend `:8080`.

## Backend admin endpoints: Basic Auth

All backend endpoints under `/admin` require HTTP Basic Auth.

If username or password is missing, admin requests are rejected with `401 Unauthorized`.

### Admin auth quick check

Request without credentials (expected `401 Unauthorized`):
```bash
curl -i http://localhost:8080/admin/info
```

Authenticated request:
```bash
curl -i -u "$ADMIN_BASIC_AUTH_USERNAME:$ADMIN_BASIC_AUTH_PASSWORD" \
  http://localhost:8080/admin/info
```

## Smoke tests

Backend health:
```bash
curl -i http://localhost:8080/health
```

Frontend dev server:
```bash
curl -i http://localhost:3000
```

Run backend tests:
```bash
cd backend
go test -race ./...
```

Run frontend lint/build:
```bash
cd frontend
npm run lint
npm run build
```

## Balance Overview

**XP curve (phase-based, v3 — bases ×10 vs v2):**
- L1–9: `180 × 1.28^(L-1)`
- L10–29: `1450 × 1.15^(L-10)`
- L30+: `23000 × 1.10^(L-30)`

**Stat growth (v3):** MaxHP +1+Con/6 every 10th level; Attack/Defense +1 every 30th; Str +1 every 40th; Con +1 every 50th; Agi +1 every 60th; Luck +1 every 100th.

| Level | XP to Next | MaxHP | Attack | Defense | Str | Con | Agi | Luck | AttackPower | DefensePower | AttackSpeed |
|------:|-----------:|------:|-------:|--------:|----:|----:|----:|-----:|------------:|-------------:|------------:|
| 1     | 180        | 100   | 10     | 5       | 1   | 1   | 1   | 1    | 12          | 6            | 1.03        |
| 5     | 483        | 100   | 10     | 5       | 1   | 1   | 1   | 1    | 12          | 6            | 1.03        |
| 10    | 1,450      | 101   | 10     | 5       | 1   | 1   | 1   | 1    | 12          | 6            | 1.03        |
| 20    | 5,866      | 102   | 10     | 5       | 1   | 1   | 1   | 1    | 12          | 6            | 1.03        |
| 30    | 23,000     | 103   | 11     | 6       | 1   | 1   | 1   | 1    | 13          | 7            | 1.03        |

See `docs/specification.md` for full design details.
