Room levels 2 and 3, researched in the library: a quarter better each, brighter, with gold trim

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-05 23:44:03 +01:00
1 parent f7b550a6b1
commit 9b49bc2c9d
23 files changed
+171 -10

No files matched your search

+35 -8
View File
@@ -486,6 +486,7 @@ pub struct MasterState {
pub incoming: Vec<(u8, f32, Option<usize>)>,
pub training_bill: f32,
pub counts: [usize; N_ROOMS],
pub room_level: Vec<u8>,
pub springs: usize,
pub known: Vec<bool>,
pub researchable: Vec<bool>,
@@ -522,6 +523,8 @@ pub struct Game {
pub hand: Vec<u32>,
#[serde(skip)]
pub counts: [usize; N_ROOMS], // room tiles per room kind (ROOM_KINDS order, recounted)
#[serde(default)]
pub room_level: Vec<u8>, // level of every room kind (ROOM_KINDS order; 1 when missing), researched
pub gate_hp: f32,
pub gate_hit_t: f32,
pub gate_stage: u32, // defender thresholds triggered (0..3)
@@ -783,6 +786,18 @@ pub fn room_index(k: Kind) -> Option<usize> {
ROOM_KINDS.iter().position(|&r| r == k)
}
impl Game {
// the researched level of a room kind of the master being processed (1, 2 or 3)
pub fn room_level_of(&self, k: Kind) -> u8 {
room_index(k).and_then(|r| self.room_level.get(r).copied()).unwrap_or(1).max(1)
}
// how much better a room works at its level: +25% per level above the first
pub fn room_bonus(&self, k: Kind) -> f32 {
1.0 + 0.25 * (self.room_level_of(k) - 1) as f32
}
}
pub(crate) fn adj4(a: usize, b: usize) -> bool {
let (ax, ay) = xy(a);
let (bx, by) = xy(b);
@@ -866,6 +881,7 @@ impl Game {
paused: false,
hand: Vec::new(),
counts: [0; N_ROOMS],
room_level: Vec::new(),
gate_hp: GATE_HP,
gate_hit_t: -100.0,
gate_stage: 0,
@@ -1126,7 +1142,7 @@ impl Game {
}
pub fn gold_cap(&self) -> f32 {
CORE_STORE + TREASURY_TILE * self.counts[0] as f32
CORE_STORE + TREASURY_TILE * self.counts[0] as f32 * self.room_bonus(Kind::Treasury)
}
pub fn add_gold(&mut self, amount: f32) -> f32 {
@@ -1433,6 +1449,7 @@ impl Game {
incoming: std::mem::take(&mut self.incoming),
training_bill: self.training_bill,
counts: self.counts,
room_level: self.room_level.clone(),
springs: self.springs,
known: std::mem::take(&mut self.known),
researchable: std::mem::take(&mut self.researchable),
@@ -1463,6 +1480,7 @@ impl Game {
self.incoming = m.incoming;
self.training_bill = m.training_bill;
self.counts = m.counts;
self.room_level = m.room_level;
self.springs = m.springs;
self.known = m.known;
self.researchable = m.researchable;
@@ -1606,9 +1624,17 @@ impl Game {
return;
}
self.time += dt;
// mushroom gardens grow faster at a higher level (of the master who owns them)
let farm = Kind::Farm;
let lv: Vec<(Owner, f32)> = self.master_sides().into_iter().map(|s| (Owner::of_side(s), {
let r = room_index(farm).unwrap_or(0);
let l = if s == self.me_side { self.room_level.get(r).copied() } else { self.masters.iter().find(|m| m.side == s).and_then(|m| m.room_level.get(r).copied()) };
1.0 + 0.25 * (l.unwrap_or(1).max(1) - 1) as f32
})).collect();
for t in self.map.t.iter_mut() {
if t.kind == Kind::Farm {
t.food = (t.food + dt / 18.0).min(3.0);
let f = lv.iter().find(|x| x.0 == t.owner).map_or(1.0, |x| x.1);
t.food = (t.food + dt * f / 18.0).min(3.0);
}
}
for side in self.master_sides() {
@@ -3798,8 +3824,9 @@ impl Game {
}
// resting heals: quickly in a bed room, slower next to the core; back to work at 75%
let bed_room = matches!(self.map.t[b].kind, Kind::Lair | Kind::Aerie);
e.hp = (e.hp + e.max_hp * dt / if bed_room { 12.0 } else { 24.0 }).min(e.max_hp);
e.energy = (e.energy + dt / 14.0).min(1.0);
let rest = if bed_room { self.room_bonus(self.map.t[b].kind) } else { 1.0 };
e.hp = (e.hp + e.max_hp * dt * rest / if bed_room { 12.0 } else { 24.0 }).min(e.max_hp);
e.energy = (e.energy + dt * rest / 14.0).min(1.0);
if e.hp >= e.max_hp * 0.75 {
e.job = Job::None;
}
@@ -3857,7 +3884,7 @@ impl Game {
if tl.food >= 1.0 {
tl.food -= 1.0;
e.hunger = 0.0;
e.hp = (e.hp + e.max_hp * 0.2).min(e.max_hp);
e.hp = (e.hp + e.max_hp * 0.2 * self.room_bonus(Kind::Temple)).min(e.max_hp);
}
self.unreserve(me);
e.job = Job::None;
@@ -3887,7 +3914,7 @@ impl Game {
}
e.working = true;
self.training_bill += TRAIN_COST * dt;
e.xp += 7.0 * dt;
e.xp += 7.0 * dt * self.room_bonus(Kind::Training);
e.timer -= dt;
if e.timer <= 0.0 {
self.unreserve(me);
@@ -3916,7 +3943,7 @@ impl Game {
}
e.working = true;
let rate = if e.kind == EK::Cogling { 2.5 } else { 1.0 } * (1.0 + 0.1 * (e.level - 1) as f32);
self.forge_work += rate * dt;
self.forge_work += rate * dt * self.room_bonus(Kind::Forge);
e.xp += 2.5 * dt;
e.timer -= dt;
if e.timer <= 0.0 {
@@ -3939,7 +3966,7 @@ impl Game {
EK::Owl => 1.3,
_ => 0.5,
} * (1.0 + 0.12 * (e.level - 1) as f32);
self.add_research(points * dt);
self.add_research(points * dt * self.room_bonus(Kind::Library));
e.xp += 3.0 * dt;
e.timer -= dt;
if e.timer <= 0.0 {