Initial commit: Plants turn-based battle game
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
# Plants — Turn-Based Battle Game
|
||||
|
||||
A turn-based battle game in Python. Normal battles are 4v4; the Tower mode
|
||||
starts small and ramps up.
|
||||
|
||||
## Run it
|
||||
|
||||
```
|
||||
pip install -r requirements.txt
|
||||
python main.py
|
||||
```
|
||||
|
||||
You land on the **main menu**:
|
||||
- **Seeds** — seed pack opening; the main way to get/enhance plants.
|
||||
- **Plants** — the plants you own, with their **level/stage**; open a plant to see its
|
||||
stats and **Water** (+1 level) or **Evolve** it
|
||||
(at milestone levels, consuming duplicates).
|
||||
- **Battle** — pick a difficulty stage (1–5, gated by enemy rarity), then the
|
||||
enemy team is rolled so you know the matchup, and you pick your 4 allies and
|
||||
fight. Higher stages grant more packs on a win; any loss grants a lesser pack.
|
||||
- **Tower** — a 20-stage gauntlet. Enemies start with 1 common plant and get
|
||||
stronger (more enemies, higher rarity, higher level) each stage; your team is
|
||||
fresh every fight. After each win you **choose one of three roguelike
|
||||
blessings** (shields, stat boosts, enemy debuffs, heal-over-time…) that last
|
||||
for the rest of the run — the core of the tower's roguelike loop.
|
||||
Stages 1–5 pay 1 water each, stages 6–20 pay scaling
|
||||
**Tower packs** (high-rarity odds), which you can open or redeem for 20 water.
|
||||
- **Collection** — plants you've discovered (they're added when you battle them);
|
||||
undiscovered plants show as blacked-out silhouettes. Saved in `data/collection.json`.
|
||||
- **Soil** — retrieve a **seed** from any owned plant (once per cooldown, from
|
||||
its detail page), plant it, then grow a copy in stages. Each stage fills over
|
||||
time; **fertilizing** (1 fertilizer per stage) advances it. Higher rarities
|
||||
have more stages; harvesting grants a duplicate of that plant. You start with
|
||||
**1 plot**; extra plots unlock for escalating fertilizer (10, then 20, 30…,
|
||||
up to 5 total). Soil unlocks once you own **8 distinct plants**.
|
||||
|
||||
## Rarities
|
||||
|
||||
Every plant has a **rarity** tag (common / rare / epic / legendary) —
|
||||
purely cosmetic, only used to weight seed-pack drops. A **victory** grants
|
||||
seed packs equal to the difficulty stage (1–5) **plus fertilizer equal to the
|
||||
floor** (1–5); a **defeat** grants 1
|
||||
**lesser pack** (worse rarity odds, no type weighting). Type packs roll the
|
||||
rarity first (matching the general pack) and then pick a plant of that rarity
|
||||
from the type when possible; rarer plants are rarer pulls.
|
||||
|
||||
## Watering, fertilizer & Evolution
|
||||
|
||||
Two resources:
|
||||
- **Water** — the scarce, valuable currency. **Watering** gives an instant +1
|
||||
level by spending 1 water, and 5 water can be converted into a seed pack.
|
||||
Water comes mainly from Tower rewards (stage 1–5 wins pay 1 water, Tower packs
|
||||
redeem for 10).
|
||||
- **Fertilizer** — the common currency earned from **battle wins**. It's used to
|
||||
fertilize growing Soil plots (each fertilizer advances a plot one stage).
|
||||
|
||||
- **XP** is earned from battles (participation + win bonus); allies auto-level up.
|
||||
Higher difficulty stages pay more XP (scales with the stage number), and Tower
|
||||
wins pay XP too. The lowest-level plant on your team earns bonus XP based on
|
||||
the level gap (catch-up).
|
||||
- **Evolution** unlocks at milestone levels (5 → stage 2, 10 → stage 3) and
|
||||
consumes duplicates. Stages multiply base stats before the level curve.
|
||||
- Enemies in battle are scaled to roughly your team's level.
|
||||
- Stat growth: attack/defense +6%, health +8%, speed +4% per level (see `engine/growth.py`).
|
||||
|
||||
## Roguelike blessings (Tower)
|
||||
|
||||
After every Tower win you're offered **3 random blessings** and keep one (or
|
||||
skip). Blessings stack for the rest of the run and apply at the **start of each
|
||||
battle**. They come in three rarity tiers:
|
||||
|
||||
- **Common** — small shields/stat boosts and start-of-battle buffs (e.g. "team
|
||||
starts with a shield for 10% of max health").
|
||||
- **Rare** — bigger boosts, heal-over-time, stronger healing, enemy debuffs
|
||||
(Speed/Attack Down).
|
||||
- **Epic** — strong shields, "+15% attack", "+20% max health", enemies start
|
||||
Vulnerable.
|
||||
- **Legendary** — rare picks with big payoff: block the first damage taken,
|
||||
a 40% shield, a one-time revive, or a large HP/attack combo.
|
||||
|
||||
Blessings are offered from a **rarity-weighted** pool, so legendary relics show
|
||||
up rarely.
|
||||
|
||||
Blessings are defined declaratively in `engine/relics.py` (`RELIC_POOL`); each
|
||||
relic is a `Relic` with an `apply(battle)` function that runs once per battle in
|
||||
`Battle.start()`. They're tracked per-run (not saved). An **"All blessings"
|
||||
overview** (`ui/relics_overview.py`) shows the whole pool grouped by rarity with
|
||||
the ones you've collected highlighted in gold; click any card for a closer look.
|
||||
It opens from the blessing-choice screen and by clicking the "Blessings:" line
|
||||
on the Tower battle screen.
|
||||
|
||||
## Plant types & type advantages
|
||||
|
||||
Five types with a rock-paper-scissors cycle:
|
||||
|
||||
**Radiant > Nocturnal > Ice > Garden > Wildflowers > Radiant**
|
||||
|
||||
- Hitting a type you're strong against deals **+30%** damage.
|
||||
- Hitting a type that's strong against you deals **−30%**.
|
||||
- Applies only to damage — heals and shields are unaffected.
|
||||
|
||||
## Stats & damage
|
||||
|
||||
- **Health** — the damage pool.
|
||||
- **Attack / Defense** — damage = skill power + attack − defense (min 1).
|
||||
- **Speed** — an **initiative timeline**: each plant acts based on `100 / speed`
|
||||
interval, so faster plants act *more often* and interleave with slower ones
|
||||
(e.g. a 110-speed enemy goes 110 → 75 → 110 → 50…). The blue bar under each
|
||||
unit's health shows how close it is to its next turn. Speed buffs/debuffs
|
||||
change the interval, and "reduce turn progress" effects literally push a
|
||||
plant's next turn back.
|
||||
- **Crit** — base 10%, doubles damage.
|
||||
|
||||
## Debuffs
|
||||
|
||||
- **Wilt** — damage over 3 turns (total = % of the triggering hit's damage);
|
||||
reapplying resets it to 3 turns.
|
||||
- **Shield** — temporary HP that absorbs damage; cannot be healed.
|
||||
- **Damage-over-time** (Dark Corrosion, Chill) — deals its listed damage **every
|
||||
turn** while active; Dark Corrosion stacks.
|
||||
- **Sleep** — skips turns until the target has taken damage twice.
|
||||
- **Vulnerable X** — +50% damage for the next X hits.
|
||||
- **Intoxicate / Oblivion** — an Intoxicated plant's attacks splash half their
|
||||
damage onto one of its own allies; an Oblivious plant may only use its weakest
|
||||
skill (both last their stated duration, e.g. 1-2 turns).
|
||||
- Plus speed/crit/attack/defense down, Madness, Tether, and more.
|
||||
|
||||
## The plant pool (27)
|
||||
|
||||
All defined declaratively in `engine/plants.py` so new plants are easy to add:
|
||||
|
||||
- **Radiant:** Zinnia, Sunflower, Daisy, Marigold, Daffodil
|
||||
- **Garden:** Rose, Peony, Magnolia, Hydrangea, Sweet Pea, Chrysanthemum
|
||||
- **Wildflower:** Lily, Hibiscus, Poppy, Tulip, Lotus, Dandelion
|
||||
- **Nocturnal:** Nightshade, Moonflower, Orchid, Lavender, Venus Flytrap
|
||||
- **Ice:** Snowdrop, Primrose, Winter Jasmine, Hellebore, Camelia
|
||||
|
||||
Each has a role (Attacker / Support / Tank), a unique passive, three skills
|
||||
with cooldowns, and base stats. Tanks protect their team from single-target
|
||||
attacks (AOE still hits everyone).
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
engine/ Pure-Python battle logic (types, skills, effects, plants, battle).
|
||||
No pygame — reusable for a web UI or Flet later.
|
||||
ui/ pygame frontend: team picker + battle screen.
|
||||
tests/ unittest coverage of the engine.
|
||||
```
|
||||
|
||||
Adding a plant later = add one entry to `POOL` in `engine/plants.py`.
|
||||
|
||||
## Tests
|
||||
|
||||
```
|
||||
python -m unittest discover -s tests
|
||||
```
|
||||
|
||||
## Roadmap ideas
|
||||
|
||||
- Balance pass (sim currently favors the player's chosen teams)
|
||||
- More team strategies, saving team compositions
|
||||
- Web UI via Flask, or a real mobile app via Flet
|
||||
Reference in New Issue
Block a user