stuff
This commit is contained in:
132
IDEAS.md
Normal file
132
IDEAS.md
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
yes ai made this, no, i dont care.
|
||||||
|
|
||||||
|
# Ideas & Future Vision
|
||||||
|
|
||||||
|
Parking lot for things I want to build but aren't building yet. Nothing here is a
|
||||||
|
commitment to a timeline — it's here so it's out of my head and safe.
|
||||||
|
|
||||||
|
Rule for this file: an idea only graduates to "actually build it" once the things
|
||||||
|
it depends on already exist. Don't build up the dependency chain. Build down it.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The Big One: Emergent Quest Engine
|
||||||
|
|
||||||
|
The dream. A quest system where quests aren't hand-written — they're generated by
|
||||||
|
chaining several smaller generators together, each feeding the next. The goal is
|
||||||
|
quests that feel *authored* because the pieces reference each other and reference
|
||||||
|
the player's actual cat/state.
|
||||||
|
|
||||||
|
### The chain
|
||||||
|
1. Generate an **item** + what it does (effect).
|
||||||
|
2. Generate a **character** who needs that item *because of what it does*.
|
||||||
|
3. Generate a **location** the character (or the cat?) travels to.
|
||||||
|
4. Generate an **encounter / fight**, scaled to a generated skill level, maybe
|
||||||
|
flavored by a custom name.
|
||||||
|
5. Resolve it → bring the item back → gain **xp, money**, maybe **food/items found
|
||||||
|
on the way**.
|
||||||
|
|
||||||
|
### Why it could feel special (not generic radiant-quest slop)
|
||||||
|
- Quests reference the *specific cat*: its traits ("your chonky cat..."), its name,
|
||||||
|
its current stats. Two players get different quests because their cats differ —
|
||||||
|
not because of raw RNG.
|
||||||
|
- The chain links cause to effect: the character needs the item *because* of what
|
||||||
|
the item does. The reward ties back to the chain. That's the "wait, this feels
|
||||||
|
written" magic.
|
||||||
|
|
||||||
|
### The trap to avoid
|
||||||
|
"Unique" and "meaningful" pull opposite directions. Pure randomization gives you
|
||||||
|
infinite *technically unique* quests that all *feel identical* (Skyrim radiant
|
||||||
|
quests: "go to random place, kill random thing, fetch random item" forever).
|
||||||
|
|
||||||
|
The fix — same lesson as the name generator: **variety lives in the TEMPLATES,
|
||||||
|
uniqueness lives in the SLOTS.** Ten hand-written quest templates with rich,
|
||||||
|
state-aware slots beats one template randomized harder. Constrain to get quality.
|
||||||
|
|
||||||
|
### The hard part most people underestimate
|
||||||
|
- **Completion checking.** A quest is only meaningful if the game can tell when
|
||||||
|
it's *done*. Every template's win condition must be something the game actually
|
||||||
|
tracks. "Feed 3 times" needs a feed counter. "Happiness > 50" needs the happiness
|
||||||
|
stat. So quests are GATED on the systems they reference already existing.
|
||||||
|
- **Procedural MECHANICS are way harder than procedural CONTENT.** A generated
|
||||||
|
*name* is just text — any string works. A generated *item effect* has to actually
|
||||||
|
DO something the game can execute. That means generated items pick from a FIXED
|
||||||
|
vocabulary of effects the game already knows how to run ("restore N hunger",
|
||||||
|
"add N happiness", "worth N money") — generated *parameters*, fixed *effect types*.
|
||||||
|
Do NOT try to generate brand-new mechanics; generate combinations of existing ones.
|
||||||
|
|
||||||
|
### Quests must persist
|
||||||
|
An active/in-progress quest has to survive save/load. So `Quest` is a model with
|
||||||
|
`to_dict`/`from_dict` + a `version`, same discipline as Cat/Save. Active quests
|
||||||
|
live on the Save.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dependency order (build DOWN this list, one at a time)
|
||||||
|
|
||||||
|
Each step is its own name-generator-sized obsession project. Each one is gated on
|
||||||
|
the steps above it. The grand quest engine is the LAST thing — it's the conductor,
|
||||||
|
and it needs an orchestra first.
|
||||||
|
|
||||||
|
0. **Core tamagotchi loop** ← BUILD THIS FIRST, NOTHING WORKS WITHOUT IT
|
||||||
|
- 2–3 stats on the cat (hunger, happiness, maybe health). Start with ONE.
|
||||||
|
- Decay over time (stats drop while away — uses elapsed-time logic).
|
||||||
|
- Actions that restore them (feed → hunger, pet/play → happiness). First real
|
||||||
|
`rules.py` verbs. Pure + testable.
|
||||||
|
- A reason actions aren't free → food item → money → a way to earn money.
|
||||||
|
- **Prove the core loop is fun before building anything on top of it.** If the
|
||||||
|
cat-care loop isn't satisfying, no quest engine saves it.
|
||||||
|
|
||||||
|
1. **Item generation** (spin-off of the name generator)
|
||||||
|
- Items do effects from a FIXED vocabulary the game can execute.
|
||||||
|
- Generate the parameters/flavor, not new mechanics.
|
||||||
|
- Gated on: stats existing (effects need something to affect).
|
||||||
|
|
||||||
|
2. **Character / NPC generation**
|
||||||
|
- Reuse the name generator for NPC names.
|
||||||
|
- Each NPC has a need (tied to an item effect).
|
||||||
|
- Gated on: item generation.
|
||||||
|
|
||||||
|
3. **Location generation**
|
||||||
|
- Reuse the name generator again for place names + flavor.
|
||||||
|
|
||||||
|
4. **Combat system**
|
||||||
|
- Its own whole system. Skill/level scaling, resolution.
|
||||||
|
- Gated on: stats, maybe items (gear?).
|
||||||
|
|
||||||
|
5. **Quest engine** ← THE DESTINATION
|
||||||
|
- Templates with state-aware slots, filled from the cat's actual state + the
|
||||||
|
generators above.
|
||||||
|
- Orchestrates items + characters + locations + combat into a chain.
|
||||||
|
- Completion conditions that check real, existing systems.
|
||||||
|
- Rewards that pay out real money/xp/items.
|
||||||
|
- Gated on: literally everything above.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Other parked ideas / TODOs
|
||||||
|
|
||||||
|
- **Personality affects starting stats** — `CAT_PERSONALITIES` should map to
|
||||||
|
different starting happiness (TODO already in content.py). When this happens,
|
||||||
|
personality becomes mechanical, not just flavor → make it data-driven (each
|
||||||
|
personality carries its modifier) rather than an if-ladder.
|
||||||
|
- **Save overwrite handling** — two cats named the same silently overwrite. Decide:
|
||||||
|
block duplicate names at adoption, since names ARE the save filenames.
|
||||||
|
- **Saves → proper user-data dir** — currently `untitled/saves/` inside the package.
|
||||||
|
Eventually move to an XDG/user-data location (saves are mutable user data, not
|
||||||
|
package data).
|
||||||
|
- **Delete save** flow (main-menu only, with confirm, never the active save).
|
||||||
|
- **Web version** — pty/xterm.js bridge. Dead last, after the game is actually a game.
|
||||||
|
- **Name generator polish** — order-3 vs order-2 experiment; soft length cap is in.
|
||||||
|
- **A studio splash / fake boot sequence** easter egg (CatDOS-style).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Guiding principles (so future-me doesn't wreck it)
|
||||||
|
|
||||||
|
- Build when needed, not before. Park visions here; build the next small thing.
|
||||||
|
- Variety in templates, uniqueness in slots. Constrain generators to get quality.
|
||||||
|
- Generate parameters from a fixed vocabulary, never generate raw mechanics.
|
||||||
|
- Keep the layers: model (data) ← rules/generation (logic) ← screens (I/O).
|
||||||
|
- Pure logic stays testable. If you can't test it without a terminal, it leaked.
|
||||||
|
- Prove each loop is fun before stacking the next system on it.
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
_MIGRATIONS = {}
|
|
||||||
|
_MIGRATIONS = {} # TODO: ADD HUNGER AND LAST PLAYED MIGRATION
|
||||||
|
|
||||||
|
|
||||||
def migrate(data):
|
def migrate(data):
|
||||||
|
|||||||
@@ -1,14 +1,24 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
class Cat:
|
class Cat:
|
||||||
def __init__(self, name, traits):
|
def __init__(self, name, traits, hunger=100, last_updated=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.traits = traits
|
self.traits = traits
|
||||||
|
self.hunger = hunger
|
||||||
|
self.last_updated = last_updated if last_updated is not None else time.time()
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {"name": self.name, "traits": self.traits}
|
return {
|
||||||
|
"name": self.name,
|
||||||
|
"traits": self.traits,
|
||||||
|
"hunger": self.hunger,
|
||||||
|
"last_updated": self.last_updated,
|
||||||
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def from_dict(data):
|
def from_dict(data):
|
||||||
return Cat(data["name"], data["traits"])
|
return Cat(data["name"], data["traits"], data["hunger"], data["last_updated"])
|
||||||
|
|
||||||
|
|
||||||
class Save:
|
class Save:
|
||||||
|
|||||||
Reference in New Issue
Block a user