Warmth shared by every pile hot enough
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
b4ecacf96c
commit
f7daa4e44d
3 changed files with 26 additions and 7 deletions
|
|
@ -130,8 +130,9 @@ Alpha. One season, bandit raids plus two friendly events, six buildings.
|
||||||
so every log adds to how long it lasts and a full fire never shuts a
|
so every log adds to how long it lasts and a full fire never shuts a
|
||||||
beginner out. Better logs burn hotter colours (red, gold, white, blue,
|
beginner out. Better logs burn hotter colours (red, gold, white, blue,
|
||||||
green, violet), burn first in their pile, and push your own cheaper fuel out
|
green, violet), burn first in their pile, and push your own cheaper fuel out
|
||||||
when your pile is full; the fire is as hot as its hottest pile. Whoever owns
|
when your pile is full; the fire is as hot as its hottest pile. Warmth: 10%
|
||||||
that pile gets 10% of the XP of every craft the fire pays for. Because the fires are shared, the server runs
|
of the XP of every craft the fire pays for, shared evenly by everyone whose
|
||||||
|
pile is hot enough for that craft on its own. Because the fires are shared, the server runs
|
||||||
everyone's actions as time passes, not only when they next look.
|
everyone's actions as time passes, not only when they next look.
|
||||||
- **Events:** raids are announced a day or two ahead. Reconnaissance from
|
- **Events:** raids are announced a day or two ahead. Reconnaissance from
|
||||||
scouts, informants and the spymaster's guild narrows down when, how strong,
|
scouts, informants and the spymaster's guild narrows down when, how strong,
|
||||||
|
|
|
||||||
13
game.py
13
game.py
|
|
@ -167,7 +167,7 @@ FIRES = {
|
||||||
FLAMES = [("Red", "#ff6a2a"), ("Gold", "#ffcb3d"), ("White", "#eeeaf8"),
|
FLAMES = [("Red", "#ff6a2a"), ("Gold", "#ffcb3d"), ("White", "#eeeaf8"),
|
||||||
("Blue", "#4fa3ff"), ("Green", "#3ed37a"), ("Violet", "#b07cff")]
|
("Blue", "#4fa3ff"), ("Green", "#3ed37a"), ("Violet", "#b07cff")]
|
||||||
TEND_XP = [2, 3, 4.5, 5.5, 6.5, 7.5] # per game minute of fire fed, by the log's tier
|
TEND_XP = [2, 3, 4.5, 5.5, 6.5, 7.5] # per game minute of fire fed, by the log's tier
|
||||||
WARMTH = 0.1 # of a craft's XP, to whoever fed the fuel that paid for it
|
WARMTH = 0.1 # of a craft's XP, shared by everyone whose pile is hot enough for it
|
||||||
FIRE_LOW = 30 * 60 # game seconds left when a fire counts as low
|
FIRE_LOW = 30 * 60 # game seconds left when a fire counts as low
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -2139,12 +2139,15 @@ def fire_inputs(world: dict, action: dict) -> dict:
|
||||||
|
|
||||||
|
|
||||||
def _warm(world: dict, crafter: dict, action: dict, xp: float, now: float) -> None:
|
def _warm(world: dict, crafter: dict, action: dict, xp: float, now: float) -> None:
|
||||||
"""A fire paid for a craft: count it, and give its feeder a share of the XP."""
|
"""A fire paid for a craft: count it, and share the warmth between everyone whose
|
||||||
|
pile alone was hot enough for it (a beginner's logs count for bricks and copper)."""
|
||||||
fire = world["city"]["fires"][action["fire"]]
|
fire = world["city"]["fires"][action["fire"]]
|
||||||
fire["saved"] = fire.get("saved", 0) + 1
|
fire["saved"] = fire.get("saved", 0) + 1
|
||||||
keeper = world["players"].get(burning(fire["fuel"])["by"])
|
keepers = [world["players"].get(by) for by in {chunk["by"] for chunk in fire["fuel"]}
|
||||||
if keeper and keeper is not crafter:
|
if burning(fire["fuel"], by)["tier"] >= action["fuel"]]
|
||||||
gain_xp(world, keeper, "firekeeping", xp * WARMTH, now, keeper.setdefault("away", empty_summary()))
|
keepers = [keeper for keeper in keepers if keeper and keeper is not crafter]
|
||||||
|
for keeper in keepers:
|
||||||
|
gain_xp(world, keeper, "firekeeping", xp * WARMTH / len(keepers), now, keeper.setdefault("away", empty_summary()))
|
||||||
|
|
||||||
|
|
||||||
def fires_view(world: dict, now: float) -> dict:
|
def fires_view(world: dict, now: float) -> dict:
|
||||||
|
|
|
||||||
|
|
@ -1953,6 +1953,21 @@ class FirekeepingTest(unittest.TestCase):
|
||||||
self.assertEqual(self.fires["kitchen"]["saved"], 4)
|
self.assertEqual(self.fires["kitchen"]["saved"], 4)
|
||||||
self.assertEqual(self.sam["xp"]["firekeeping"], 0)
|
self.assertEqual(self.sam["xp"]["firekeeping"], 0)
|
||||||
|
|
||||||
|
def test_warmth_is_shared_by_every_pile_hot_enough_for_the_craft(self):
|
||||||
|
self.world["players"]["ash"] = ash = game.new_player("ash", "Ash", "commoner", T0)
|
||||||
|
ash["xp"]["cooking"] = game.XP_TABLE[15]
|
||||||
|
self.fires["kitchen"].update(at=T0, fuel=[{"tier": 3, "left": 6000, "by": "kai"},
|
||||||
|
{"tier": 0, "left": 6000, "by": "sam"}])
|
||||||
|
ash["bank"] = {"raw_shrimp": 1, "raw_trout": 1}
|
||||||
|
game.start_action(self.world, ash, "cook_shrimp", T0, once=True)
|
||||||
|
game.process_player(self.world, ash, T0 + 25, random.Random(1))
|
||||||
|
self.assertAlmostEqual(self.kai["xp"]["firekeeping"], 6 * game.WARMTH / 2)
|
||||||
|
self.assertAlmostEqual(self.sam["xp"]["firekeeping"], 6 * game.WARMTH / 2)
|
||||||
|
game.start_action(self.world, ash, "cook_trout", T0 + 25, once=True)
|
||||||
|
game.process_player(self.world, ash, T0 + 60, random.Random(1))
|
||||||
|
self.assertAlmostEqual(self.kai["xp"]["firekeeping"], 6 * game.WARMTH / 2 + 15 * game.WARMTH) # trout: kai's alone
|
||||||
|
self.assertAlmostEqual(self.sam["xp"]["firekeeping"], 6 * game.WARMTH / 2)
|
||||||
|
|
||||||
def test_catch_up_runs_everyone_and_keeps_what_they_missed(self):
|
def test_catch_up_runs_everyone_and_keeps_what_they_missed(self):
|
||||||
game.start_action(self.world, self.sam, "mine_stone", T0)
|
game.start_action(self.world, self.sam, "mine_stone", T0)
|
||||||
self.assertTrue(game.catch_up(self.world, T0 + 100, random.Random(1)))
|
self.assertTrue(game.catch_up(self.world, T0 + 100, random.Random(1)))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue