Switch repo to English, add i18n with EN/DE language files and first-start language selection

- in-game texts moved to lang/en.lang and lang/de.lang (key = text, placeholders)
- game logic emits message keys + args, translated at display time
- localStorage access via own miniquad JS plugin (www/dc_plugin.js)
- code comments, DESIGN.md, CREDITS.md translated; README.md added

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-02 22:53:03 +01:00
1 parent a101f6ddc4
commit fbf6f223fc
18 files changed
+1072 -362

No files matched your search

+22 -22
View File
@@ -1,4 +1,4 @@
// Karte, Kacheln, Generierung und Wegfindung.
// Map, tiles, generation and path finding.
use std::cmp::Reverse;
use std::collections::BinaryHeap;
@@ -34,13 +34,13 @@ pub enum Owner {
pub struct Tile {
pub kind: Kind,
pub owner: Owner,
pub hp: f32, // Grab-Widerstand
pub gold: i32, // Goldvorrat (Goldader)
pub marked: bool, // zum Graben markiert
pub reserved: u32, // Entity-ID + 1, die diese Kachel bearbeitet
pub food: f32, // Pilze im Pilzgarten
pub bed: u32, // Entity-ID + 1, die hier schläft
pub var: u8, // Texturvariante
pub hp: f32, // dig resistance
pub gold: i32, // gold left (gold vein)
pub marked: bool, // marked for digging
pub reserved: u32, // entity id + 1 working on this tile
pub food: f32, // mushrooms in the mushroom garden
pub bed: u32, // entity id + 1 sleeping here
pub var: u8, // texture variant
}
impl Tile {
@@ -97,7 +97,7 @@ impl Rng {
pub struct Map {
pub t: Vec<Tile>,
pub core: (i32, i32), // linke obere Ecke des Kerns (3x3)
pub core: (i32, i32), // top-left corner of the core (3x3)
pub portal: (i32, i32),
pub gate: (i32, i32),
}
@@ -119,7 +119,7 @@ impl Map {
let mut s = seed;
loop {
let m = Map::try_generate(s);
// Sicherstellen, dass Helden den Kern erreichen können
// make sure heroes can reach the core
if m.hero_path_to_core(idx(m.gate.0 + 1, m.gate.1 + 1)).is_some() {
return m;
}
@@ -163,21 +163,21 @@ impl Map {
}
};
// Felsbrocken
// rock clusters
for _ in 0..22 {
let cx = rng.range(4, MW as i32 - 5);
let cy = rng.range(4, MH as i32 - 5);
let r = rng.range(1, 3);
blob(&mut t, &mut rng, cx, cy, r, Kind::Rock);
}
// Goldadern
// gold veins
for _ in 0..16 {
let cx = rng.range(4, MW as i32 - 5);
let cy = rng.range(4, MH as i32 - 5);
let r = rng.range(1, 2);
blob(&mut t, &mut rng, cx, cy, r, Kind::Gold);
}
// Garantiertes Gold in Startnähe
// guaranteed gold near the start
for k in 0..3 {
let cx = core.0 + rng.range(-3, 9);
let cy = core.1 + if k % 2 == 0 { rng.range(-9, -6) } else { rng.range(7, 9) };
@@ -197,7 +197,7 @@ impl Map {
}
};
// Kleine natürliche Höhlen
// small natural caves
for _ in 0..4 {
let cx = rng.range(20, 48);
let cy = rng.range(6, 58);
@@ -206,9 +206,9 @@ impl Map {
room(&mut t, cx - w, cy - h, cx + w, cy + h, Owner::None);
}
// Startbereich
// starting area
room(&mut t, core.0 - 3, core.1 - 3, core.0 + 5, core.1 + 5, Owner::Player);
// Kern 3x3
// core 3x3
for y in 0..3 {
for x in 0..3 {
let tl = &mut t[idx(core.0 + x, core.1 + y)];
@@ -216,14 +216,14 @@ impl Map {
tl.owner = Owner::Player;
}
}
// Portalhöhle
// portal cave
room(&mut t, portal.0 - 2, portal.1 - 2, portal.0 + 4, portal.1 + 4, Owner::None);
for y in 0..3 {
for x in 0..3 {
t[idx(portal.0 + x, portal.1 + y)].kind = Kind::Portal;
}
}
// Heldentor
// hero gate
room(&mut t, gate.0 - 2, gate.1 - 2, gate.0 + 4, gate.1 + 4, Owner::Hero);
for y in 0..3 {
for x in 0..3 {
@@ -240,9 +240,9 @@ impl Map {
Map { t, core, portal, gate }
}
// Allgemeine Dijkstra-Suche.
// cost(i) -> None = unpassierbar, Some(c) = Kosten zum Betreten.
// goal(i) -> true = Ziel erreicht.
// Generic Dijkstra search.
// cost(i) -> None = impassable, Some(c) = cost of entering.
// goal(i) -> true = goal reached.
pub fn search<C, G>(&self, start: usize, cost: C, goal: G, diag: bool) -> Option<Vec<usize>>
where
C: Fn(usize) -> Option<u32>,
@@ -279,7 +279,7 @@ impl Map {
let Some(c) = cost(ni) else { continue };
let mut step = c * 10;
if k >= 4 {
// Diagonal nur, wenn beide Nachbarn begehbar sind (keine Ecken schneiden)
// diagonal only if both neighbours are walkable (no corner cutting)
if c > 1 || !self.walk(x + dx, y) || !self.walk(x, y + dy) {
continue;
}