ludic.fire: a camp fire's fuel, lit and out, the rain on it, and its reach
Minutes of fuel that burn down in game time, twice as fast in the rain with nothing over the ring, and the hours it held under cover. Lighting and feeding are decided (fire_decide), costed in wood (fire_cost) and applied (fire_apply) apart, so a machine that does not own the world can ask the one that does. Warmth and cooking by distance are queries. FIRE_LIT, FIRE_WENT_OUT and FIRE_LOW_FUEL are facts; the rain, the tarp, the ban and who owns the world come through the FireWorld port. Its own save section. Uses ludic_base only; 8 tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
cf42214974
commit
0af0ef681f
9 changed files with 402 additions and 0 deletions
145
packages/ludic.fire/tests/fire_test.ludic
Normal file
145
packages/ludic.fire/tests/fire_test.ludic
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
# fire_test.ludic - lighting and feeding decided, paid for and applied; burning down in game time,
|
||||
# faster in the rain; low fuel and going out as facts; warmth and cooking by distance; the save
|
||||
import "ludic.fire"
|
||||
import "ludic.base"
|
||||
program FireTest {
|
||||
numbers float
|
||||
var owns: bool = true
|
||||
var wet: bool = false
|
||||
var tarp: bool = false
|
||||
var ban: bool = false
|
||||
|
||||
function fake_owns() -> bool { return owns }
|
||||
function fake_wet() -> bool { return wet }
|
||||
function fake_tarp() -> bool { return tarp }
|
||||
function fake_allowed() -> bool { return not ban }
|
||||
|
||||
bind FireWorld {
|
||||
owns_world: fn fake_owns
|
||||
is_wet: fn fake_wet
|
||||
sheltered: fn fake_tarp
|
||||
allowed: fn fake_allowed
|
||||
}
|
||||
|
||||
function fresh() -> void {
|
||||
fire_config(3, 120.0, 60.0, 15.0)
|
||||
fire_config_reach(3.6, 3.5)
|
||||
fire_reset()
|
||||
}
|
||||
|
||||
function facts() -> []FireFact { return q_drain(fire_facts()) }
|
||||
function count(fs: []FireFact, what: int) -> int {
|
||||
var n = 0
|
||||
for i in 0 .. len(fs) { if fs[i].what == what { n += 1 } }
|
||||
return n
|
||||
}
|
||||
|
||||
function light() -> void { fire_apply(fire_decide(3)) }
|
||||
|
||||
test "three logs light it, and that is a fact" {
|
||||
fresh()
|
||||
expect_eq(fire_decide(2), FIRE_NO_WOOD)
|
||||
expect_eq(fire_decide(3), FIRE_LIGHT)
|
||||
expect_eq(fire_cost(FIRE_LIGHT), 3)
|
||||
light()
|
||||
expect(fire_lit())
|
||||
expect(fire_fuel() == 120.0)
|
||||
expect_eq(count(facts(), FIRE_LIT), 1)
|
||||
}
|
||||
|
||||
test "a lit fire takes a log for an hour" {
|
||||
fresh()
|
||||
light()
|
||||
expect_eq(fire_decide(0), FIRE_NO_LOG)
|
||||
expect_eq(fire_decide(1), FIRE_FEED)
|
||||
expect_eq(fire_cost(FIRE_FEED), 1)
|
||||
fire_apply(FIRE_FEED)
|
||||
expect(fire_fuel() == 180.0)
|
||||
}
|
||||
|
||||
test "a ban and a soaked ring refuse, a tarp keeps it dry" {
|
||||
fresh()
|
||||
ban = true
|
||||
expect_eq(fire_decide(5), FIRE_BANNED)
|
||||
ban = false
|
||||
wet = true
|
||||
expect_eq(fire_decide(5), FIRE_SOAKED)
|
||||
expect_eq(fire_cost(FIRE_SOAKED), 0)
|
||||
tarp = true
|
||||
expect_eq(fire_decide(5), FIRE_LIGHT)
|
||||
}
|
||||
|
||||
test "it burns a minute a minute, runs low, and goes out as facts" {
|
||||
fresh()
|
||||
light()
|
||||
facts()
|
||||
fire_run(1.5)
|
||||
expect(fire_fuel() == 30.0)
|
||||
expect(not fire_low())
|
||||
fire_run(0.3)
|
||||
expect(fire_low())
|
||||
expect_eq(count(facts(), FIRE_LOW_FUEL), 1)
|
||||
fire_run(0.5)
|
||||
expect(not fire_lit())
|
||||
expect(fire_fuel() == 0.0)
|
||||
expect_eq(count(facts(), FIRE_WENT_OUT), 1)
|
||||
}
|
||||
|
||||
test "the rain burns it twice as fast, and under a tarp it counts the hours" {
|
||||
fresh()
|
||||
light()
|
||||
wet = true
|
||||
fire_run(0.5)
|
||||
expect(fire_fuel() == 60.0)
|
||||
tarp = true
|
||||
fire_run(0.5)
|
||||
expect(fire_fuel() == 30.0)
|
||||
expect(fire_rain_hours() == 0.5)
|
||||
fire_morning()
|
||||
expect(fire_rain_hours() == 0.0)
|
||||
}
|
||||
|
||||
test "a machine that does not own the world burns nothing, but is told" {
|
||||
fresh()
|
||||
light()
|
||||
owns = false
|
||||
fire_run(5.0)
|
||||
expect(fire_fuel() == 120.0)
|
||||
facts()
|
||||
fire_told(false, 0.0, true)
|
||||
expect(not fire_lit())
|
||||
expect_eq(count(facts(), FIRE_WENT_OUT), 1)
|
||||
fire_told(true, 50.0, true)
|
||||
fire_told(false, 0.0, false)
|
||||
expect_eq(q_len(fire_facts()), 0)
|
||||
}
|
||||
|
||||
test "it warms and cooks close, and only while lit" {
|
||||
fresh()
|
||||
expect(not fire_warms(1.0))
|
||||
light()
|
||||
expect(fire_warms(3.5))
|
||||
expect(not fire_warms(3.7))
|
||||
expect(fire_cooks(3.4))
|
||||
expect(not fire_cooks(3.55))
|
||||
fire_out()
|
||||
expect(not fire_cooks(0.0))
|
||||
}
|
||||
|
||||
test "a save section reads back the same fire" {
|
||||
fresh()
|
||||
light()
|
||||
wet = true
|
||||
tarp = true
|
||||
fire_run(0.25)
|
||||
let root = save_tree()
|
||||
save_section(root, "fire", 1, fire_save())
|
||||
let text = save_encode(root)
|
||||
fire_reset()
|
||||
let n = load_section(save_decode(text), "fire")
|
||||
fire_load(n.data, n.version)
|
||||
expect(fire_lit())
|
||||
expect(fire_fuel() == 105.0)
|
||||
expect(fire_rain_hours() == 0.25)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue