class_name DreamDB ## Die Traumwelt: ein Dorf, das mit jedem erfüllten Traum wächst. ## Fest sind nur Hörsaal, Dorfplatz und Tor zur Erde. Jedes Haus und sein ## Bewohner werden erzeugt — der Reihe nach, immer weiter nach außen. const HAEUSER_JE_RING := 6 const RING_ERSTER := 30.0 const RING_ABSTAND := 24.0 ## Häuser sitzen auf Achtelrichtungen. Die Achsen 0 (Hörsaal) und 4 (Tor) ## bleiben frei, damit der Weg vom Dorfplatz zu beiden offen bleibt. const SLOTS := [1, 2, 3, 5, 6, 7] static var FEST: Dictionary = { "hoersaal": { "name": "Hörsaal der Wege", "pos": [0.0, 34.0], "size": [16.0, 12.0], "dir": "forward", "color": Color(0.66, 0.72, 0.94), }, "lichtung": { "name": "Der Dorfplatz", "pos": [0.0, 2.0], "size": [0.0, 0.0], "dir": "none", "color": Color(0.60, 0.50, 0.85), }, "tor": { "name": "Tor zur Erde", "pos": [0.0, -34.0], "size": [0.0, 0.0], "dir": "none", "color": Color(0.50, 0.80, 1.0), }, } ## Wird von erzeuge() gefüllt und wächst mit dem Dorf. static var PLACES: Dictionary = FEST.duplicate(true) static var LIST: Array = [] static var FESTE_NAMEN: Array = ["Ailen", "Morr", "Ivo", "Sela"] static var FESTE_ROLLEN: Array = ["Traumweberin", "Erinnerungssammler", "Bote", "Wächterin des Tors"] static var SILBE_A: Array = ["Nu", "Ta", "Es", "Wre", "O", "Ma", "Si", "Te"] static var SILBE_B: Array = ["un", "lia", "kar", "n", "vin", "lu", "rin", "nne"] static var ROLLEN: Array = ["Lichtgießer", "Kartenzeichnerin", "Schwellenhüter", "Fadensucherin", "Stillenzähler", "Wegbereiterin", "Klangsammler", "Nachtgärtnerin"] ## Vier Tagesabläufe, alle mit reichlich Zeit zwischen den Stationen — ## auch ein Haus am äußeren Ring ist so bequem zu erreichen. static var ABLAEUFE: Array = [ [[0, "haus", "traeumt"], [6, "lichtung", "ruht"], [10, "haus", "webt"], [14, "lichtung", "singt"], [18, "haus", "sortiert"], [21, "haus", "traeumt"]], [[0, "haus", "traeumt"], [6, "lichtung", "sammelt"], [10, "haus", "sortiert"], [15, "tor", "beobachtet"], [19, "haus", "webt"], [21, "haus", "traeumt"]], [[0, "tor", "wacht"], [7, "lichtung", "ruht"], [11, "haus", "sortiert"], [15, "tor", "wacht"], [19, "lichtung", "singt"], [21, "haus", "traeumt"]], [[0, "haus", "traeumt"], [4, "tor", "beobachtet"], [8, "lichtung", "wandert"], [12, "haus", "ruht"], [16, "lichtung", "singt"], [20, "haus", "traeumt"]], ] static func haus_key(i: int) -> String: return "haus_%d" % i ## Baut Orte und Bewohner für ein Dorf mit so vielen Häusern neu auf. static func erzeuge(haeuser: int) -> void: PLACES = FEST.duplicate(true) LIST = [] for i in range(maxi(haeuser, 0)): PLACES[haus_key(i)] = _haus(i) LIST.append(_bewohner(i)) ## Wie weit reicht das Dorf hinaus? static func aeusserster_ring(haeuser: int) -> float: if haeuser <= 0: return 0.0 var ring := (haeuser - 1) / HAEUSER_JE_RING return RING_ERSTER + float(ring) * RING_ABSTAND static func _haus(i: int) -> Dictionary: var ring := i / HAEUSER_JE_RING var winkel := float(SLOTS[i % HAEUSER_JE_RING]) * TAU / 8.0 var r := RING_ERSTER + float(ring) * RING_ABSTAND var x := sin(winkel) * r var z := cos(winkel) * r var breite := 12.0 + float(i % 2) * 2.0 var tiefe := 10.0 + float(i % 3) return { "name": "%s Haus" % _besitz(_name(i)), "pos": [x, z], "size": [breite, tiefe], "dir": _tuer_zur_mitte(x, z), "color": Color.from_hsv(fmod(0.60 + float(i) * 0.137, 1.0), 0.34, 0.86), } ## Die Tür zeigt zur Dorfmitte — auf die Seite, die ihr am nächsten liegt. static func _tuer_zur_mitte(x: float, z: float) -> String: if absf(x) > absf(z): return "left" if x > 0.0 else "right" return "forward" if z > 0.0 else "back" static func _bewohner(i: int) -> Dictionary: var haus := haus_key(i) var ablauf: Array = [] for e in ABLAEUFE[i % ABLAEUFE.size()]: ablauf.append([e[0], haus if e[1] == "haus" else e[1], e[2]]) return { "id": "wesen_%d" % i, "name": _name(i), "rolle": _rolle(i), "haus": haus, "leuchtet": true, "farbe": Color.from_hsv(fmod(0.72 + float(i) * 0.161, 1.0), 0.55, 0.95), "routine": ablauf, } static func _name(i: int) -> String: if i < FESTE_NAMEN.size(): return str(FESTE_NAMEN[i]) var j := i - FESTE_NAMEN.size() return str(SILBE_A[j % SILBE_A.size()]) + str(SILBE_B[(j / SILBE_A.size()) % SILBE_B.size()]) ## Genitiv: "Ailens", aber "Morrs" und "Esas'" — Apostroph nur nach Zischlaut. static func _besitz(n: String) -> String: var letzter := n.substr(n.length() - 1).to_lower() return n + "'" if ["s", "z", "x", "ß"].has(letzter) else n + "s" static func _rolle(i: int) -> String: if i < FESTE_ROLLEN.size(): return str(FESTE_ROLLEN[i]) return str(ROLLEN[(i - FESTE_ROLLEN.size()) % ROLLEN.size()]) static func by_id(id: String) -> Dictionary: for w in LIST: if w["id"] == id: return w return {} # ------------------------------------------------------------------ Lehrorte ## Der Hörsaal lehrt den ersten Weg. Jedes Haus bringt einen weiteren mit. static func techniken_von(place_key: String) -> Array: var nr := -1 if place_key == "hoersaal": nr = 0 elif place_key.begins_with("haus_"): nr = int(place_key.substr(5)) + 1 if nr < 0 or nr >= TechDB.LIST.size(): return [] return [TechDB.LIST[nr]["id"]] ## An welchem Ort wird diese Technik gelehrt? "" wenn nirgends. static func ort_von_technik(tech_id: String) -> String: for i in range(TechDB.LIST.size()): if TechDB.LIST[i]["id"] == tech_id: return "hoersaal" if i == 0 else haus_key(i - 1) return "" ## Alle Orte, an denen im aktuellen Dorf gelehrt wird. static func lehrorte() -> Array: var out: Array = ["hoersaal"] for i in range(LIST.size()): if not techniken_von(haus_key(i)).is_empty(): out.append(haus_key(i)) return out