// ============================================================ // All gameplay tunables in one place - tweak freely // ============================================================ // --- world --- export const TILE = 16; // px per tile (Tiny Town tiles are 16x16) export const MAP_W = 64; export const MAP_H = 48; export const START_POP = 20; // --- time --- export const TPS = 10; // sim ticks per second (real-time) export const DAY_SECONDS = 240; // one in-game day = 4 real minutes export const DAY_TICKS = DAY_SECONDS * TPS; export const NIGHT_START = 0.75; // fraction of day when night falls export const DAWN = 0.02; // fraction when dawn begins // --- needs (per tick rates, 10 ticks = 1 second) --- export const HUNGER_RATE = 0.055; export const ENERGY_RATE = 0.03; export const SOCIAL_RATE = 0.02; export const SLEEP_RECOVER = 0.4; export const HUNGER_EAT_THRESHOLD = 60; export const SOCIAL_TALK_THRESHOLD = 50; export const EAT_TICKS = 12; export const STARVE_HEALTH_DRAIN = 0.08; export const HEALTH_REGEN = 0.015; // --- movement --- export const WALK_SPEED = 0.22; // tiles per tick // --- food --- export const BUSH_REGEN_TICKS = DAY_TICKS; // one berry regrows per in-game day export const BUSH_MAX = 4; // --- seasons & weather --- export const WEATHER_DURATION_TICKS = Math.floor(DAY_TICKS / 3); export const CROP_TICKS_TO_GROW = Math.floor(DAY_TICKS * 1.5); // ~1.5 days base growth export const BERRY_REGEN_WINTER = 0.35; // berry regrowth speed in winter export const ENERGY_WINTER_MULT = 1.35; // cold drains energy faster // --- jobs & economy --- export const WORK_START_FRAC = 0.06; // work hours: ~sunrise to early afternoon export const WORK_END_FRAC = 0.62; export const TREE_REGEN_TICKS = DAY_TICKS * 2; export const WOOD_PER_TREE = 3; export const STONE_PER_SESSION = 2; export const FISH_PER_SESSION = 2; export const CROP_HARVEST = 6; export const FARM_WOOD_COST = 2; export const WORK_SESSION_TICKS = 70; export const MAX_WORK_SESSIONS = 6; // sessions per villager per day - rest is life export const EGG_EVERY_TICKS = Math.floor(DAY_TICKS * 0.75); // --- life cycle --- export const ELDER_AT_MIN = 13; export const ELDER_AT_MAX = 15; export const LIFESPAN_MIN = 15; export const LIFESPAN_MAX = 19; export const BABY_DAYS = 0.75; export const CHILD_DAYS = 2; export const AGE_PER_TICK = 1 / DAY_TICKS; // in days // --- love & family --- export const RELATION_FRIEND = 35; export const RELATION_CRUSH = 55; export const RELATION_COUPLE = 65; export const MARRY_VALUE = 80; export const PREGNANCY_DAYS = 1; export const PREGNANCY_CHANCE = 0.4; // nightly, married fertile couple, food ok export const MAX_POP = 36; export const HUT_WOOD = 5; export const HUT_STONE = 2; export const SHRINE_WOOD = 2; export const SHRINE_STONE = 3; // --- shrine & festival --- export const SHRINE_FAITH_AVG = 55; export const SHRINE_MIN_BELIEVERS = 6; export const FESTIVAL_FAITH_AVG = 65; export const FESTIVAL_TICKS = 260; // --- funerals & mourning --- export const MOURNING_TICKS = 320; // --- mind (M3) --- export const MOOD_BASELINE = 55; // content mood export const STRESS_DECAY = 0.006; // per tick natural drain export const STRESS_DECAY_SLEEP = 0.012; export const MOOD_HARD_LIMIT_DECAY = 0.01; export const RESILIENCE_MIN = 30; export const RESILIENCE_MAX = 90; export const RESILIENCE_GROW = 0.6; // per survived hardship while coping export const RESILIENCE_SOFTEN = 0.15; // per soft day without any hardship export const DISORDER_BASE_CHANCE = 0.045; // per trauma event, scaled by weight/resilience export const DISORDER_REPEAT_MULT = 2.5; // if traumatized again within 2 days export const STRESS_TRAUMA_WEIGHT = 22; // typical trauma stress export const DISORDER_RECOVER_TICK = 0.02; // natural recovery per tick export const PANIC_TICKS = 90; // --- crimes (M3) --- export const FIGHT_TICKS = 30; export const FIGHT_HEALTH_DRAIN = 0.5; // per tick per fighter export const FIGHT_START_STRESS = 78; // stress needed to consider violence export const MURDER_ESCALATION = 0.04; // chance a fight turns lethal (temper-scaled) export const GRUDGE_LEVEL = 25; // relations value below this = grudge export const THEFT_HUNGER = 88; // starving people steal export const THEFT_CHANCE = 0.004; // per tick when starving & low honesty export const SABOTAGE_STRESS = 75; export const SABOTAGE_CHANCE = 0.0015; // per tick when envious + stressed + dishonest export const ADULTERY_MOOD = 40; // unhappy marriages can stray export const CRIME_EXILE_STRIKES = 3; // witnessed crimes before the village exiles export const EXILE_CAMP_RADIUS = 10; // tiles from spawn exiles may not enter export const EXILE_REDEEM_DAYS = 5; export const VENGEANCE_CHANCE = 0.002; // per tick per grudge-carrier with vengeance want export const WITNESS_RANGE_CRIME = 6; // --- wants (M3) --- export const WANT_MAX = 3; export const WANT_SATISFY_MOOD = 10; export const WANT_IGNORED_STRESS = 12; // per day ignored export const WANT_PURSUE_CHANCE = 0.15; // per idle period // --- institutions (M3) --- export const SCHOOL_MIN_CHILDREN = 3; export const SCHOOL_SKILL_PER_TICK = 0.03; export const HOSPITAL_HEAL_PER_SESSION = 25; export const HOSPITAL_MIND_PER_SESSION = 10; export const KITCHEN_MEAL_HOUR = 0.62; // shared meal starts at this day fraction export const KITCHEN_MOOD_BOOST = 12; export const TAVERN_START_HOUR = 0.7; export const TAVERN_MOOD_BOOST = 8; export const TAVERN_FIGHT_CHANCE = 0.03; // per drunk temper-high evening export const TEMPLE_SERMON_STRESS_RELIEF = 3; export const GRANARY_SPOILAGE = 0.25; // share of perishables lost per winter week without granary // --- god mind tools (M3) --- export const PEACE_STRESS_RELIEF = 40; export const PEACE_DISORDER_PROGRESS = 15; export const PEACE_MOOD_BOOST = 15; // --- plague --- export const PLAGUE_DURATION_TICKS = DAY_TICKS * 2; export const PLAGUE_HEALTH_DRAIN = 0.035; export const PLAGUE_RADIUS = 5; export const FAMINE_RADIUS = 6; // --- god command acts --- export const ACTS = [ "none", "pray", "tell_others", "goto_person", "goto_place", "gather_food", "sleep", "stop", ] as const; // --- persistence --- export const AUTOSAVE_EVERY_TICKS = 300; export const SAVE_VERSION = 2; // --- faith & prayer --- export const PRAY_FAITH_MIN = 55; export const PRAY_CHANCE = 0.0015; // per tick when idle export const PRAY_DURATION = 24; // ticks // --- conversations --- export const MAX_CONCURRENT_CONVOS = 2; export const CONVO_GLOBAL_COOLDOWN = 60; // ticks between convo starts export const CONVO_PERSONAL_COOLDOWN = 220; // ticks per human export const CONVO_LINE_DELAY = 12; // ticks between lines export const CONVO_MAX_EXCHANGES = 4; export const CONVO_TIMEOUT = 150; // ticks to wait for an LLM line export const CONVO_RANGE_TILES = 2; // --- LLM --- export const LLM_DEFAULT_MODEL = "qwen2.5:7b"; export const LLM_TIMEOUT_MS = 90_000; export const LLM_MAX_CONCURRENT = 1; // Ollama works best serially export const LLM_QUEUE_CAP = 24; export const LLM_TEMPERATURE = 0.85; export const LLM_CTX = 2048; export const LLM_MAX_TOKENS_DIALOGUE = 100; export const LLM_MAX_TOKENS_GOD = 220; export const LLM_MAX_TOKENS_REFLECT = 280; // --- memory --- export const MEMORY_CAP = 160; export const RECALL_LIMIT = 5; // --- god powers --- export const OBSERVER_RANGE = 8; // tiles - who "sees" a miracle export const OVERHEAR_RANGE = 4; // tiles - who overhears the Voice