From 5f603cb193d79e583bb5b8209b763b63d5d6243c Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 19 Aug 2026 18:10:42 +0200 Subject: [PATCH] =?UTF-8?q?Tourismusregion:=20Umwelt=20bei=C3=9Ft=20jetzt?= =?UTF-8?q?=20+=20Sch=C3=BCler-Erkl=C3=A4rung=20(Balance-Pass=201)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Diagnose per headless-Sim-Harness (.dontDeploy/tools/tr-balance-harness.mjs): „alles zubauen" senkte die Umwelt nur 75→50 (über der 45-Schwelle) und der Exit-Umwelt-Malus war TOTER Flag-Code → man konnte der Umwelt kaum schaden. - model.js: (1) Exit-Umwelt-Malus wirklich angewandt — env<60 zieht bei umweltbewussten Gästen Zufriedenheit ab (je tiefer, desto mehr). (2) Über- tourismus-Drift im 10-s-Takt: dichte Bebauung (>6 Bauwerke) + Verkehr zehren die Umwelt aus. (3) Einmalige Lern-Warnkarte, wenn Umwelt < 50 kippt. - data.js: Naturschutzgebiet-Beschreibung klar (rettet die Umwelt +20, Natur- Attraktionen +15 %, sperrt Bauplätze — Naturschutz vs. Ausbau abwägen). - main.js: Willkommenskarte erklärt die Umwelt-Mechanik für Schüler. Messung nachher: „alles zubauen" → Umwelt 75→37 (unter 45), Umweltziel verfehlt, Ø-Sterne fallen. Feintuning Sterne-Kurve/Ansprüche-Eskalation bleibt für Thomas' Playtest (Game-Feeling headless nicht bewertbar). Co-Authored-By: Claude Opus 4.8 --- .dontDeploy/tools/tr-balance-harness.mjs | 73 ++++++++++++++++++++++++ App/sims/tourismusregion/js/data.js | 2 +- App/sims/tourismusregion/js/main.js | 4 ++ App/sims/tourismusregion/js/model.js | 33 ++++++++++- 4 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 .dontDeploy/tools/tr-balance-harness.mjs diff --git a/.dontDeploy/tools/tr-balance-harness.mjs b/.dontDeploy/tools/tr-balance-harness.mjs new file mode 100644 index 0000000..eb9fa0a --- /dev/null +++ b/.dontDeploy/tools/tr-balance-harness.mjs @@ -0,0 +1,73 @@ +// Headless-Balance-Messung (temporär). node sim-harness.mjs +import { createState, place, upgrade, callNextWave, tick, GOALS } from '../../App/sims/tourismusregion/js/model.js'; +import { BUILDINGS, GAME_LEN } from '../../App/sims/tourismusregion/js/data.js'; + +const ALL_TYPES = Object.keys(BUILDINGS); +function upgradeAllMax(s) { + for (const b of s.buildings) { + const def = BUILDINGS[b.type]; + let guard = 0; + while (b.level < def.cost.length && s.budget >= def.cost[b.level] && guard++ < 6) { + const r = upgrade(s, b); + if (!r || !r.ok) break; + } + } +} + +function run(strategy, mapId = 'talschleife') { + const s = createState({ mapId, seed: 12345 }); + const dt = 0.5; + let t = 0; + + function tryBuildAll() { + for (let i = 0; i < s.slots.length; i++) { + const slot = s.slots[i]; + if (slot.building || slot.blocked) continue; + for (const type of ALL_TYPES) { + const def = BUILDINGS[type]; + if (!def || s.budget < def.cost[0]) continue; + const r = place(s, type, i); + if (r && r.ok) break; + } + } + } + function buildOneCafe() { + // Minimal-Strategie: genau EIN Café (Thomas' „5-Sterne-Café macht alles grün") + if (s.buildings.length) return; + for (let i = 0; i < s.slots.length; i++) { + if (s.slots[i].building || s.slots[i].blocked) continue; + const r = place(s, 'cafe', i); + if (r && r.ok) return; + } + } + + let guard = 0; + while (t < GAME_LEN && s.phase < 8 && guard++ < 2000) { + if (strategy === 'buildAll' || strategy === 'maxedAll') tryBuildAll(); + if (strategy === 'maxedAll') upgradeAllMax(s); + if (strategy === 'oneCafe') buildOneCafe(); + try { callNextWave(s); } catch (_) {} + for (let k = 0; k < 40 && t < GAME_LEN; k++) { tick(s, dt); t += dt; } + } + if (strategy === 'maxedAll') upgradeAllMax(s); + // Restzeit auslaufen lassen + while (t < GAME_LEN && guard++ < 6000) { tick(s, dt); t += dt; } + + const stars = s.stats.all.count ? s.stats.all.stars / s.stats.all.count : 0; + return { + strategy, + env: Math.round(s.env), + avgStars: +stars.toFixed(2), + visitorsExited: s.stats.all.count, + budget: Math.round(s.budget), + buildings: s.buildings.length, + traffic: Math.round(s.traffic || 0), + goalsMet: GOALS.filter(g => g.check(s)).length + '/' + GOALS.length, + }; +} + +console.log('=== Tourismusregion Balance-Messung (talschleife) ==='); +for (const strat of ['maxedAll', 'buildAll', 'oneCafe']) { + const r = run(strat); + console.log(`${strat.padEnd(9)} → env ${String(r.env).padStart(3)} · Ø${r.avgStars}★ · ${r.buildings} Geb. · Verkehr ${r.traffic} · Ziele ${r.goalsMet} · Budget ${r.budget}`); +} diff --git a/App/sims/tourismusregion/js/data.js b/App/sims/tourismusregion/js/data.js index 98f77b7..fca86b9 100644 --- a/App/sims/tourismusregion/js/data.js +++ b/App/sims/tourismusregion/js/data.js @@ -283,7 +283,7 @@ export const BUILDINGS = { }, naturschutz: { name: 'Naturschutzgebiet', emoji: '🌿', cat: 'nature', unlockPhase: 4, maxLevel: 1, fx: '🦋', sound: 'pling', - desc: 'Umwelt +20, Naturerlebnis +15 % – sperrt aber Bauplätze im Umkreis.', + desc: 'Hebt die Umwelt sofort um +20 und macht Natur-Attraktionen 15 % attraktiver. So rettest du die Landschaft, wenn zu viel Bauen die Umwelt gedrückt hat – Wanderer und Naturfreunde danken es dir. Preis: sperrt umliegende Bauplätze (Naturschutz vor Ausbau).', cost: [300], sat: [6], slow: [0.05], diff --git a/App/sims/tourismusregion/js/main.js b/App/sims/tourismusregion/js/main.js index b9b5e84..88138eb 100644 --- a/App/sims/tourismusregion/js/main.js +++ b/App/sims/tourismusregion/js/main.js @@ -112,6 +112,10 @@ function startGame() { + 'See, Berg – und drei Wege, auf denen Gäste ankommen.\n\n' + 'Ziel: zufriedene Gäste (Ø 3,5 ★), regionale Wertschöpfung (2500 €), ' + 'intakte Umwelt (≥ 45) und ein solides Budget.\n\n' + + '🌲 Die Umwelt ist deine Landschaft: Wanderer und Naturfreunde lieben sie intakt. ' + + 'Zu viel Bauen und Verkehr lässt die Umwelt sinken – fällt sie zu tief, vergraulst ' + + 'du genau diese Gäste. Ein 🌿 Naturschutzgebiet hebt die Umwelt wieder und zieht ' + + 'Naturgäste an, sperrt aber Bauplätze in der Nähe. Abwägen ist alles!\n\n' + 'Gebaut wird auf den markierten Bauplätzen am Weg – starte mit einem Wirtshaus!', }); if (!localStorage.getItem('tourismusregion_seen')) { diff --git a/App/sims/tourismusregion/js/model.js b/App/sims/tourismusregion/js/model.js index 501c8ac..7a7f6ab 100644 --- a/App/sims/tourismusregion/js/model.js +++ b/App/sims/tourismusregion/js/model.js @@ -119,6 +119,30 @@ export function tick(state, dt) { cost /= 6; // pro Minute → pro 10 s state.budget -= cost; state.opCostTotal += cost; + + // Übertourismus (§10 Raumnutzungskonflikt): dichte Bebauung + viel Verkehr + // zehren die Umwelt langsam aus. Ab ~6 fertigen Bauwerken beginnt der Druck. + // „Alles zubauen" drückt die Umwelt so über die Partie klar unter die + // 45er-Schwelle — vorher blieb sie fast konstant. Naturschutzgebiet (+20) + // und maßvolles Bauen sind die Gegenmittel. + const builtCount = state.buildings.reduce((n, b) => n + (b.construction <= 0 ? 1 : 0), 0); + const overbuild = Math.max(0, builtCount - 6); + const envErode = overbuild * 0.06 + state.traffic * 0.012; // pro 10 s + if (envErode > 0) state.env = clampEnv(state.env - envErode); + + // Einmalige Lern-Warnung, sobald die Umwelt kippt (didaktischer Hinweis). + if (state.env < 50 && !state.envWarned) { + state.envWarned = true; + state.pendingCards.push({ + kind: 'card', icon: '🌲', title: 'Die Umwelt leidet!', sound: 'card', + text: 'Deine Umwelt ist unter 50 gefallen. Umweltbewusste Gäste – ' + + 'Wanderer, Naturfreunde, Radgruppen – werden unzufrieden, wenn sie ' + + 'unter 45 sinkt, und bleiben irgendwann ganz weg.\n\n' + + 'Was hilft: maßvoller bauen, auf sanfte Anreise (Bus, Rad, Bahn) ' + + 'setzen – oder ein 🌿 Naturschutzgebiet bauen, das die Umwelt sofort ' + + 'um +20 hebt. Naturschutz gegen Ausbau abwägen ist der Kern des Spiels.', + }); + } } // Verkehr: Parkplätze + aktive Auto-/Busgruppen @@ -495,7 +519,14 @@ function exitVisitor(state, v) { const tPen = state.traffic * 0.08 * g.trafficSens; if (tPen > 4) malus.traffic = true; sat -= tPen; - if (state.env < 45 && g.envSens >= 0.7) malus.env = true; + // Umwelt-Malus WIRKLICH anwenden (war zuvor nur ein toter Flag ohne Wirkung): + // eine kaputte Landschaft vergrault Gäste — je umweltbewusster, desto stärker, + // und je tiefer die Umwelt fällt, desto heftiger. Ab env<60 spürbar, <40 hart. + // Das ist der Raumnutzungskonflikt: zu viel zubauen → Umwelt kippt → Rating fällt. + if (state.env < 60 && g.envSens >= 0.4) { + sat -= g.envSens * (60 - state.env) * 0.5; // env 40 → ~6, env 20 → ~12 (× envSens) + if (state.env < 45) malus.env = true; + } if (v.timeIn > g.maxTime) { sat *= 0.92; malus.time = true; } const ratio = Math.max(0, sat) / g.satTarget;