wip(0.S3): the packages migrated by ludic migrate state packages - every package test green
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
1e8b5b0523
commit
07505e7ef2
294 changed files with 14996 additions and 14675 deletions
|
|
@ -6,53 +6,56 @@ export property Queue<T> {
|
|||
}
|
||||
|
||||
# every named queue's pending count, so a frame's end can say which facts nobody read
|
||||
var qb_names: []string = null
|
||||
var qb_pending: []int = null
|
||||
export state BaseState {
|
||||
qb_names: []string = null
|
||||
qb_pending: []int = null
|
||||
cs_list: []System = null
|
||||
}
|
||||
|
||||
function qb_init() -> void {
|
||||
if qb_names != null { return }
|
||||
qb_names = new []string
|
||||
qb_pending = new []int
|
||||
function qb_init(base_st: mut BaseState) -> void {
|
||||
if base_st.qb_names != null { return }
|
||||
base_st.qb_names = new []string
|
||||
base_st.qb_pending = new []int
|
||||
}
|
||||
|
||||
# a queue; the name is only for core_undrained
|
||||
export function queue_new<T>(name: string) -> Queue<T> {
|
||||
qb_init()
|
||||
export function queue_new<T>(base_st: mut BaseState, name: string) -> Queue<T> {
|
||||
qb_init(base_st)
|
||||
let q = new Queue<T>
|
||||
q.items = new []T
|
||||
q.id = len(qb_names)
|
||||
push(qb_names, name)
|
||||
push(qb_pending, 0)
|
||||
q.id = len(base_st.qb_names)
|
||||
push(base_st.qb_names, name)
|
||||
push(base_st.qb_pending, 0)
|
||||
return q
|
||||
}
|
||||
|
||||
export function q_push<T>(q: Queue<T>, v: T) -> void {
|
||||
export function q_push<T>(base_st: mut BaseState, q: Queue<T>, v: T) -> void {
|
||||
push(q.items, v)
|
||||
qb_pending[q.id] = len(q.items)
|
||||
base_st.qb_pending[q.id] = len(q.items)
|
||||
}
|
||||
|
||||
# the facts in the order they were pushed; the queue is empty afterwards
|
||||
export function q_drain<T>(q: Queue<T>) -> []T {
|
||||
export function q_drain<T>(base_st: mut BaseState, q: Queue<T>) -> []T {
|
||||
let out = q.items
|
||||
q.items = new []T
|
||||
qb_pending[q.id] = 0
|
||||
base_st.qb_pending[q.id] = 0
|
||||
return out
|
||||
}
|
||||
|
||||
export function q_len<T>(q: Queue<T>) -> int { return len(q.items) }
|
||||
|
||||
export function q_clear<T>(q: Queue<T>) -> void {
|
||||
export function q_clear<T>(base_st: mut BaseState, q: Queue<T>) -> void {
|
||||
q.items = new []T
|
||||
qb_pending[q.id] = 0
|
||||
base_st.qb_pending[q.id] = 0
|
||||
}
|
||||
|
||||
# the names of the queues still holding facts; call it at the end of a frame, where a fact
|
||||
# left behind is a route nobody wrote
|
||||
export function core_undrained() -> []string {
|
||||
qb_init()
|
||||
export function core_undrained(base_st: mut BaseState) -> []string {
|
||||
qb_init(base_st)
|
||||
let out = new []string
|
||||
for i in 0 .. len(qb_names) {
|
||||
if qb_pending[i] > 0 { push(out, qb_names[i]) }
|
||||
for i in 0 .. len(base_st.qb_names) {
|
||||
if base_st.qb_pending[i] > 0 { push(out, base_st.qb_names[i]) }
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,14 +16,13 @@ export property System {
|
|||
# fishing_tick }` from its own module; the runner starts from these, then core_add appends
|
||||
export open registry Systems of System as SYS
|
||||
|
||||
var cs_list: []System = null
|
||||
|
||||
function cs_all() -> []System {
|
||||
if cs_list == null {
|
||||
cs_list = new []System
|
||||
for i in 0 .. SYS_COUNT { push(cs_list, Systems[i]) }
|
||||
function cs_all(base_st: mut BaseState) -> []System {
|
||||
if base_st.cs_list == null {
|
||||
base_st.cs_list = new []System
|
||||
for i in 0 .. SYS_COUNT { push(base_st.cs_list, Systems[i]) }
|
||||
}
|
||||
return cs_list
|
||||
return base_st.cs_list
|
||||
}
|
||||
|
||||
export function system_new(key: string, phase: int) -> System {
|
||||
|
|
@ -34,8 +33,8 @@ export function system_new(key: string, phase: int) -> System {
|
|||
}
|
||||
|
||||
# a key is a save section's name, so two systems may not share one
|
||||
export function core_add(s: System) -> void {
|
||||
let all = cs_all()
|
||||
export function core_add(base_st: mut BaseState, s: System) -> void {
|
||||
let all = cs_all(base_st)
|
||||
for i in 0 .. len(all) {
|
||||
if all[i].key == s.key {
|
||||
print(`ludic.base: two systems are keyed "{s.key}"`)
|
||||
|
|
@ -45,21 +44,21 @@ export function core_add(s: System) -> void {
|
|||
push(all, s)
|
||||
}
|
||||
|
||||
export function core_clear() -> void { cs_list = new []System }
|
||||
export function core_count() -> int { return len(cs_all()) }
|
||||
export function core_clear(base_st: mut BaseState) -> void { base_st.cs_list = new []System }
|
||||
export function core_count(base_st: mut BaseState) -> int { return len(cs_all(base_st)) }
|
||||
|
||||
export function core_init_all() -> void {
|
||||
let all = cs_all()
|
||||
export function core_init_all(base_st: mut BaseState) -> void {
|
||||
let all = cs_all(base_st)
|
||||
for i in 0 .. len(all) { if all[i].init != null { all[i].init() } }
|
||||
}
|
||||
|
||||
export function core_reset_all() -> void {
|
||||
let all = cs_all()
|
||||
export function core_reset_all(base_st: mut BaseState) -> void {
|
||||
let all = cs_all(base_st)
|
||||
for i in 0 .. len(all) { if all[i].reset != null { all[i].reset() } }
|
||||
}
|
||||
|
||||
export function core_tick_all(t: Tick) -> void {
|
||||
let all = cs_all()
|
||||
export function core_tick_all(base_st: mut BaseState, t: Tick) -> void {
|
||||
let all = cs_all(base_st)
|
||||
for ph in 0 .. PH_COUNT {
|
||||
for i in 0 .. len(all) {
|
||||
if all[i].phase == ph and all[i].tick != null { all[i].tick(t) }
|
||||
|
|
@ -68,9 +67,9 @@ export function core_tick_all(t: Tick) -> void {
|
|||
}
|
||||
|
||||
# every system that saves, under its key with its version
|
||||
export function core_save_all() -> Val {
|
||||
export function core_save_all(base_st: mut BaseState) -> Val {
|
||||
let root = save_tree()
|
||||
let all = cs_all()
|
||||
let all = cs_all(base_st)
|
||||
for i in 0 .. len(all) {
|
||||
if all[i].save != null { save_section(root, all[i].key, all[i].version, all[i].save()) }
|
||||
}
|
||||
|
|
@ -78,8 +77,8 @@ export function core_save_all() -> Val {
|
|||
}
|
||||
|
||||
# each system its own section; one with no section (or no load) is reset instead
|
||||
export function core_load_all(root: Val) -> void {
|
||||
let all = cs_all()
|
||||
export function core_load_all(base_st: mut BaseState, root: Val) -> void {
|
||||
let all = cs_all(base_st)
|
||||
for i in 0 .. len(all) {
|
||||
let n = load_section(root, all[i].key)
|
||||
if n.found and all[i].load != null { all[i].load(n.data, n.version) } else if all[i].reset != null { all[i].reset() }
|
||||
|
|
|
|||
|
|
@ -12,52 +12,52 @@ program QueueTest {
|
|||
return c
|
||||
}
|
||||
|
||||
function fifo_case() -> void {
|
||||
let q: Queue<int> = queue_new("ints")
|
||||
q_push(q, 3)
|
||||
q_push(q, 1)
|
||||
q_push(q, 2)
|
||||
function fifo_case(base_st: mut BaseState) -> void {
|
||||
let q: Queue<int> = queue_new(base_st, "ints")
|
||||
q_push(base_st, q, 3)
|
||||
q_push(base_st, q, 1)
|
||||
q_push(base_st, q, 2)
|
||||
expect_eq(q_len(q), 3)
|
||||
let xs = q_drain(q)
|
||||
let xs = q_drain(base_st, q)
|
||||
expect_eq(len(xs), 3)
|
||||
expect_eq(xs[0], 3)
|
||||
expect_eq(xs[1], 1)
|
||||
expect_eq(xs[2], 2)
|
||||
expect_eq(q_len(q), 0)
|
||||
expect_eq(len(q_drain(q)), 0)
|
||||
expect_eq(len(q_drain(base_st, q)), 0)
|
||||
}
|
||||
|
||||
function record_case() -> void {
|
||||
let q: Queue<Caught> = queue_new("caught")
|
||||
q_push(q, caught(2, 1.5))
|
||||
q_push(q, caught(4, 0.25))
|
||||
let cs = q_drain(q)
|
||||
function record_case(base_st: mut BaseState) -> void {
|
||||
let q: Queue<Caught> = queue_new(base_st, "caught")
|
||||
q_push(base_st, q, caught(2, 1.5))
|
||||
q_push(base_st, q, caught(4, 0.25))
|
||||
let cs = q_drain(base_st, q)
|
||||
expect_eq(cs[1].species, 4)
|
||||
expect(cs[0].weight == 1.5)
|
||||
}
|
||||
|
||||
function clear_case() -> void {
|
||||
let q: Queue<string> = queue_new("words")
|
||||
q_push(q, "a")
|
||||
q_clear(q)
|
||||
function clear_case(base_st: mut BaseState) -> void {
|
||||
let q: Queue<string> = queue_new(base_st, "words")
|
||||
q_push(base_st, q, "a")
|
||||
q_clear(base_st, q)
|
||||
expect_eq(q_len(q), 0)
|
||||
}
|
||||
|
||||
function undrained_case() -> void {
|
||||
let a: Queue<int> = queue_new("left_behind")
|
||||
let b: Queue<int> = queue_new("read")
|
||||
q_push(a, 1)
|
||||
q_push(b, 2)
|
||||
q_drain(b)
|
||||
let names = core_undrained()
|
||||
function undrained_case(base_st: mut BaseState) -> void {
|
||||
let a: Queue<int> = queue_new(base_st, "left_behind")
|
||||
let b: Queue<int> = queue_new(base_st, "read")
|
||||
q_push(base_st, a, 1)
|
||||
q_push(base_st, b, 2)
|
||||
q_drain(base_st, b)
|
||||
let names = core_undrained(base_st)
|
||||
expect_eq(len(names), 1)
|
||||
expect(names[0] == "left_behind")
|
||||
q_drain(a)
|
||||
expect_eq(len(core_undrained()), 0)
|
||||
q_drain(base_st, a)
|
||||
expect_eq(len(core_undrained(base_st)), 0)
|
||||
}
|
||||
|
||||
test "a queue drains in the order it was pushed" { fifo_case() }
|
||||
test "a queue holds records" { record_case() }
|
||||
test "clear drops what is waiting" { clear_case() }
|
||||
test "the undrained queues are named, and a drain clears the report" { undrained_case() }
|
||||
test "a queue drains in the order it was pushed" (base_st: mut BaseState) { fifo_case(base_st) }
|
||||
test "a queue holds records" (base_st: mut BaseState) { record_case(base_st) }
|
||||
test "clear drops what is waiting" (base_st: mut BaseState) { clear_case(base_st) }
|
||||
test "the undrained queues are named, and a drain clears the report" (base_st: mut BaseState) { undrained_case(base_st) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,19 +3,21 @@
|
|||
import "ludic.base"
|
||||
program RegistryTest {
|
||||
numbers float
|
||||
var trail: string = ""
|
||||
function late_tick(t: Tick) -> void { trail = trail + "l" }
|
||||
function early_tick(t: Tick) -> void { trail = trail + "e" }
|
||||
function added_tick(t: Tick) -> void { trail = trail + "a" }
|
||||
state RegistrytestState {
|
||||
trail: string = ""
|
||||
}
|
||||
function late_tick(registrytest_st: mut RegistrytestState, t: Tick) -> void { registrytest_st.trail = registrytest_st.trail + "l" }
|
||||
function early_tick(registrytest_st: mut RegistrytestState, t: Tick) -> void { registrytest_st.trail = registrytest_st.trail + "e" }
|
||||
function added_tick(registrytest_st: mut RegistrytestState, t: Tick) -> void { registrytest_st.trail = registrytest_st.trail + "a" }
|
||||
def Systems late { phase: PH_RESOLVE, tick: fn late_tick }
|
||||
def Systems early { phase: PH_INPUT, tick: fn early_tick }
|
||||
test "the declared systems run, phase by phase" {
|
||||
expect_eq(core_count(), 2)
|
||||
test "the declared systems run, phase by phase" (base_st: mut BaseState, registrytest_st: RegistrytestState) {
|
||||
expect_eq(core_count(base_st), 2)
|
||||
expect(Systems[SYS_LATE].key == "late")
|
||||
let s = system_new("added", PH_INPUT)
|
||||
s.tick = fn added_tick
|
||||
core_add(s)
|
||||
core_tick_all(tick_new(0.016, 1, 0.0))
|
||||
expect(trail == "eal")
|
||||
core_add(base_st, s)
|
||||
core_tick_all(base_st, tick_new(0.016, 1, 0.0))
|
||||
expect(registrytest_st.trail == "eal")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,57 +10,57 @@ program RouteTest {
|
|||
bind FishingWorld { is_water: fn water_everywhere_but_land }
|
||||
|
||||
# the route: a landed fish goes into the pack
|
||||
function route_fishing_pack(t: Tick) -> void {
|
||||
let fish = q_drain(caught)
|
||||
for i in 0 .. len(fish) { pack_add(fish[i].species, 1) }
|
||||
function route_fishing_pack(base_st: mut BaseState, toy_fishing_st: ToyFishingState, toy_pack_st: mut ToyPackState, t: Tick) -> void {
|
||||
let fish = q_drain(base_st, toy_fishing_st.caught)
|
||||
for i in 0 .. len(fish) { pack_add(toy_pack_st, fish[i].species, 1) }
|
||||
}
|
||||
|
||||
function game_start() -> void {
|
||||
core_clear()
|
||||
core_add(fishing_system())
|
||||
function game_start(base_st: mut BaseState) -> void {
|
||||
core_clear(base_st)
|
||||
core_add(base_st, fishing_system())
|
||||
let r = system_new("route.fishing_pack", PH_RESOLVE)
|
||||
r.tick = fn route_fishing_pack
|
||||
core_add(r)
|
||||
core_add(pack_system())
|
||||
core_reset_all()
|
||||
core_add(base_st, r)
|
||||
core_add(base_st, pack_system())
|
||||
core_reset_all(base_st)
|
||||
}
|
||||
|
||||
function pack_total() -> int { return pack_count(0) + pack_count(1) + pack_count(2) }
|
||||
function pack_total(toy_pack_st: ToyPackState) -> int { return pack_count(toy_pack_st, 0) + pack_count(toy_pack_st, 1) + pack_count(toy_pack_st, 2) }
|
||||
|
||||
test "three casts on water land three fish in the pack, one on land lands nothing" {
|
||||
game_start()
|
||||
expect(fishing_cast(1.0, 2.0))
|
||||
expect(fishing_cast(3.0, 2.0))
|
||||
expect(fishing_cast(5.0, 2.0))
|
||||
expect(not fishing_cast(500.0, 2.0))
|
||||
core_tick_all(tick_new(1.0 / 60.0, 0, 0.0))
|
||||
expect_eq(pack_total(), 3)
|
||||
expect_eq(len(core_undrained()), 0)
|
||||
test "three casts on water land three fish in the pack, one on land lands nothing" (base_st: mut BaseState, toy_fishing_st: mut ToyFishingState, toy_pack_st: ToyPackState) {
|
||||
game_start(base_st)
|
||||
expect(fishing_cast(toy_fishing_st, 1.0, 2.0))
|
||||
expect(fishing_cast(toy_fishing_st, 3.0, 2.0))
|
||||
expect(fishing_cast(toy_fishing_st, 5.0, 2.0))
|
||||
expect(not fishing_cast(toy_fishing_st, 500.0, 2.0))
|
||||
core_tick_all(base_st, tick_new(1.0 / 60.0, 0, 0.0))
|
||||
expect_eq(pack_total(toy_pack_st), 3)
|
||||
expect_eq(len(core_undrained(base_st)), 0)
|
||||
}
|
||||
|
||||
test "the pack saves its own section and the fishing, which saves nothing, is reset" {
|
||||
game_start()
|
||||
fishing_cast(1.0, 1.0)
|
||||
core_tick_all(tick_new(1.0 / 60.0, 0, 0.0))
|
||||
let text = save_encode(core_save_all())
|
||||
test "the pack saves its own section and the fishing, which saves nothing, is reset" (base_st: mut BaseState, toy_fishing_st: mut ToyFishingState, toy_pack_st: ToyPackState) {
|
||||
game_start(base_st)
|
||||
fishing_cast(toy_fishing_st, 1.0, 1.0)
|
||||
core_tick_all(base_st, tick_new(1.0 / 60.0, 0, 0.0))
|
||||
let text = save_encode(core_save_all(base_st))
|
||||
let tree = save_decode(text)
|
||||
expect_eq(Value.count(tree), 1)
|
||||
expect_eq(load_section(tree, "pack").version, 1)
|
||||
expect(not load_section(tree, "fishing").found)
|
||||
core_reset_all()
|
||||
expect_eq(pack_total(), 0)
|
||||
core_load_all(save_decode(text))
|
||||
expect_eq(pack_total(), 1)
|
||||
core_reset_all(base_st)
|
||||
expect_eq(pack_total(toy_pack_st), 0)
|
||||
core_load_all(base_st, save_decode(text))
|
||||
expect_eq(pack_total(toy_pack_st), 1)
|
||||
}
|
||||
|
||||
test "the same seed lands the same fish" {
|
||||
game_start()
|
||||
fishing_cast(1.0, 1.0)
|
||||
core_tick_all(tick_new(1.0 / 60.0, 0, 0.0))
|
||||
let first = save_encode(core_save_all())
|
||||
game_start()
|
||||
fishing_cast(1.0, 1.0)
|
||||
core_tick_all(tick_new(1.0 / 60.0, 0, 0.0))
|
||||
expect(save_encode(core_save_all()) == first)
|
||||
test "the same seed lands the same fish" (base_st: mut BaseState, toy_fishing_st: mut ToyFishingState) {
|
||||
game_start(base_st)
|
||||
fishing_cast(toy_fishing_st, 1.0, 1.0)
|
||||
core_tick_all(base_st, tick_new(1.0 / 60.0, 0, 0.0))
|
||||
let first = save_encode(core_save_all(base_st))
|
||||
game_start(base_st)
|
||||
fishing_cast(toy_fishing_st, 1.0, 1.0)
|
||||
core_tick_all(base_st, tick_new(1.0 / 60.0, 0, 0.0))
|
||||
expect(save_encode(core_save_all(base_st)) == first)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,31 +3,33 @@
|
|||
import "ludic.base"
|
||||
program SystemTest {
|
||||
numbers float
|
||||
var trail: string = ""
|
||||
var apples: int = 0
|
||||
var hours: float = 0.0
|
||||
state SystemtestState {
|
||||
trail: string = ""
|
||||
apples: int = 0
|
||||
hours: float = 0.0
|
||||
}
|
||||
|
||||
function draw_tick(t: Tick) -> void { trail = trail + "d" }
|
||||
function think_tick(t: Tick) -> void { trail = trail + "t" }
|
||||
function input_tick(t: Tick) -> void { trail = trail + "i" }
|
||||
function commit_tick(t: Tick) -> void { trail = trail + "c" }
|
||||
function apples_init() -> void { trail = trail + "A" }
|
||||
function apples_reset() -> void { apples = 0 }
|
||||
function apples_tick(t: Tick) -> void { apples += 1 }
|
||||
function apples_save() -> Val {
|
||||
function draw_tick(systemtest_st: mut SystemtestState, t: Tick) -> void { systemtest_st.trail = systemtest_st.trail + "d" }
|
||||
function think_tick(systemtest_st: mut SystemtestState, t: Tick) -> void { systemtest_st.trail = systemtest_st.trail + "t" }
|
||||
function input_tick(systemtest_st: mut SystemtestState, t: Tick) -> void { systemtest_st.trail = systemtest_st.trail + "i" }
|
||||
function commit_tick(systemtest_st: mut SystemtestState, t: Tick) -> void { systemtest_st.trail = systemtest_st.trail + "c" }
|
||||
function apples_init(systemtest_st: mut SystemtestState) -> void { systemtest_st.trail = systemtest_st.trail + "A" }
|
||||
function apples_reset(systemtest_st: mut SystemtestState) -> void { systemtest_st.apples = 0 }
|
||||
function apples_tick(systemtest_st: mut SystemtestState, t: Tick) -> void { systemtest_st.apples += 1 }
|
||||
function apples_save(systemtest_st: SystemtestState) -> Val {
|
||||
let v = Value.object()
|
||||
sv_put_int(v, "n", apples)
|
||||
sv_put_int(v, "n", systemtest_st.apples)
|
||||
return v
|
||||
}
|
||||
function apples_load(v: Val, version: int) -> void { apples = sv_int(v, "n", 0) * version }
|
||||
function clock_reset() -> void { hours = 6.0 }
|
||||
function clock_tick(t: Tick) -> void { hours = hours + t.hours }
|
||||
function clock_save() -> Val {
|
||||
function apples_load(systemtest_st: mut SystemtestState, v: Val, version: int) -> void { systemtest_st.apples = sv_int(v, "n", 0) * version }
|
||||
function clock_reset(systemtest_st: mut SystemtestState) -> void { systemtest_st.hours = 6.0 }
|
||||
function clock_tick(systemtest_st: mut SystemtestState, t: Tick) -> void { systemtest_st.hours = systemtest_st.hours + t.hours }
|
||||
function clock_save(systemtest_st: SystemtestState) -> Val {
|
||||
let v = Value.object()
|
||||
sv_put_float(v, "h", hours)
|
||||
sv_put_float(v, "h", systemtest_st.hours)
|
||||
return v
|
||||
}
|
||||
function clock_load(v: Val, version: int) -> void { hours = sv_float(v, "h", 6.0) }
|
||||
function clock_load(systemtest_st: mut SystemtestState, v: Val, version: int) -> void { systemtest_st.hours = sv_float(v, "h", 6.0) }
|
||||
|
||||
function sys(key: string, phase: int, tick: fn(Tick) -> void) -> System {
|
||||
let s = system_new(key, phase)
|
||||
|
|
@ -35,71 +37,71 @@ program SystemTest {
|
|||
return s
|
||||
}
|
||||
|
||||
function setup() -> void {
|
||||
core_clear()
|
||||
trail = ""
|
||||
core_add(sys("draw", PH_PRESENT, fn draw_tick))
|
||||
core_add(sys("think", PH_SIMULATE, fn think_tick))
|
||||
function setup(base_st: mut BaseState, systemtest_st: mut SystemtestState) -> void {
|
||||
core_clear(base_st)
|
||||
systemtest_st.trail = ""
|
||||
core_add(base_st, sys("draw", PH_PRESENT, fn draw_tick))
|
||||
core_add(base_st, sys("think", PH_SIMULATE, fn think_tick))
|
||||
let a = sys("apples", PH_SIMULATE, fn apples_tick)
|
||||
a.init = fn apples_init
|
||||
a.reset = fn apples_reset
|
||||
a.save = fn apples_save
|
||||
a.load = fn apples_load
|
||||
a.version = 2
|
||||
core_add(a)
|
||||
core_add(sys("input", PH_INPUT, fn input_tick))
|
||||
core_add(sys("commit", PH_COMMIT, fn commit_tick))
|
||||
core_add(base_st, a)
|
||||
core_add(base_st, sys("input", PH_INPUT, fn input_tick))
|
||||
core_add(base_st, sys("commit", PH_COMMIT, fn commit_tick))
|
||||
let c = sys("clock", PH_SIMULATE, fn clock_tick)
|
||||
c.reset = fn clock_reset
|
||||
c.save = fn clock_save
|
||||
c.load = fn clock_load
|
||||
core_add(c)
|
||||
core_add(base_st, c)
|
||||
}
|
||||
|
||||
test "tick runs phase by phase, in the order added within a phase" {
|
||||
setup()
|
||||
core_tick_all(tick_new(1.0 / 60.0, 0, 0.0))
|
||||
expect(trail == "itcd")
|
||||
expect_eq(apples, 1)
|
||||
test "tick runs phase by phase, in the order added within a phase" (base_st: mut BaseState, systemtest_st: mut SystemtestState) {
|
||||
setup(base_st, systemtest_st)
|
||||
core_tick_all(base_st, tick_new(1.0 / 60.0, 0, 0.0))
|
||||
expect(systemtest_st.trail == "itcd")
|
||||
expect_eq(systemtest_st.apples, 1)
|
||||
}
|
||||
|
||||
test "init and reset run in the order added and skip a null verb" {
|
||||
setup()
|
||||
core_init_all()
|
||||
expect(trail == "A")
|
||||
apples = 9
|
||||
core_reset_all()
|
||||
expect_eq(apples, 0)
|
||||
expect(hours == 6.0)
|
||||
expect_eq(core_count(), 6)
|
||||
test "init and reset run in the order added and skip a null verb" (base_st: mut BaseState, systemtest_st: mut SystemtestState) {
|
||||
setup(base_st, systemtest_st)
|
||||
core_init_all(base_st)
|
||||
expect(systemtest_st.trail == "A")
|
||||
systemtest_st.apples = 9
|
||||
core_reset_all(base_st)
|
||||
expect_eq(systemtest_st.apples, 0)
|
||||
expect(systemtest_st.hours == 6.0)
|
||||
expect_eq(core_count(base_st), 6)
|
||||
}
|
||||
|
||||
test "save writes each system under its key with its version, and load reads it back" {
|
||||
setup()
|
||||
core_reset_all()
|
||||
apples = 4
|
||||
core_tick_all(tick_new(0.016, 1, 0.5))
|
||||
let root = core_save_all()
|
||||
test "save writes each system under its key with its version, and load reads it back" (base_st: mut BaseState, systemtest_st: mut SystemtestState) {
|
||||
setup(base_st, systemtest_st)
|
||||
core_reset_all(base_st)
|
||||
systemtest_st.apples = 4
|
||||
core_tick_all(base_st, tick_new(0.016, 1, 0.5))
|
||||
let root = core_save_all(base_st)
|
||||
expect_eq(Value.count(root), 2)
|
||||
expect_eq(load_section(root, "apples").version, 2)
|
||||
expect_eq(load_section(root, "clock").version, 1)
|
||||
let text = save_encode(root)
|
||||
core_reset_all()
|
||||
core_load_all(save_decode(text))
|
||||
expect_eq(apples, 10)
|
||||
expect(hours == 6.5)
|
||||
core_reset_all(base_st)
|
||||
core_load_all(base_st, save_decode(text))
|
||||
expect_eq(systemtest_st.apples, 10)
|
||||
expect(systemtest_st.hours == 6.5)
|
||||
}
|
||||
|
||||
test "a system with no section in the save is reset" {
|
||||
setup()
|
||||
apples = 3
|
||||
hours = 11.0
|
||||
test "a system with no section in the save is reset" (base_st: mut BaseState, systemtest_st: mut SystemtestState) {
|
||||
setup(base_st, systemtest_st)
|
||||
systemtest_st.apples = 3
|
||||
systemtest_st.hours = 11.0
|
||||
let root = save_tree()
|
||||
let v = Value.object()
|
||||
sv_put_float(v, "h", 20.25)
|
||||
save_section(root, "clock", 1, v)
|
||||
core_load_all(root)
|
||||
expect_eq(apples, 0)
|
||||
expect(hours == 20.25)
|
||||
core_load_all(base_st, root)
|
||||
expect_eq(systemtest_st.apples, 0)
|
||||
expect(systemtest_st.hours == 20.25)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,26 +4,28 @@ numbers float
|
|||
import "ludic.base"
|
||||
export property Caught { species: int = 0, weight: float = 0.0 }
|
||||
export port FishingWorld { is_water: fn(float, float) -> bool } # its port
|
||||
var dice: Rng = null
|
||||
var casts: int = 0
|
||||
export var caught: Queue<Caught> = null # its facts
|
||||
export function fishing_cast(x: float, z: float) -> bool { # its verb
|
||||
export state ToyFishingState {
|
||||
dice: Rng = null
|
||||
casts: int = 0
|
||||
caught: Queue<Caught> = null # its facts
|
||||
}
|
||||
export function fishing_cast(toy_fishing_st: mut ToyFishingState, x: float, z: float) -> bool { # its verb
|
||||
if not FishingWorld.is_water(x, z) { return false }
|
||||
casts += 1
|
||||
toy_fishing_st.casts += 1
|
||||
return true
|
||||
}
|
||||
function fishing_reset() -> void {
|
||||
casts = 0
|
||||
dice = rng_new(7)
|
||||
caught = queue_new("fishing.caught")
|
||||
function fishing_reset(base_st: mut BaseState, toy_fishing_st: mut ToyFishingState) -> void {
|
||||
toy_fishing_st.casts = 0
|
||||
toy_fishing_st.dice = rng_new(7)
|
||||
toy_fishing_st.caught = queue_new(base_st, "fishing.caught")
|
||||
}
|
||||
function fishing_tick(t: Tick) -> void {
|
||||
while casts > 0 {
|
||||
function fishing_tick(base_st: mut BaseState, toy_fishing_st: mut ToyFishingState, t: Tick) -> void {
|
||||
while toy_fishing_st.casts > 0 {
|
||||
let c = new Caught
|
||||
c.species = rng_between(dice, 0, 2)
|
||||
c.weight = 0.5 + rng_float(dice)
|
||||
q_push(caught, c)
|
||||
casts -= 1
|
||||
c.species = rng_between(toy_fishing_st.dice, 0, 2)
|
||||
c.weight = 0.5 + rng_float(toy_fishing_st.dice)
|
||||
q_push(base_st, toy_fishing_st.caught, c)
|
||||
toy_fishing_st.casts -= 1
|
||||
}
|
||||
}
|
||||
export function fishing_system() -> System {
|
||||
|
|
|
|||
|
|
@ -2,22 +2,24 @@
|
|||
module toy_pack uses ludic_base
|
||||
numbers float
|
||||
import "ludic.base"
|
||||
var counts: []int = null
|
||||
export function pack_add(kind: int, n: int) -> void { counts[kind] = counts[kind] + n }
|
||||
export function pack_count(kind: int) -> int { return counts[kind] }
|
||||
function pack_reset() -> void {
|
||||
counts = new []int
|
||||
for i in 0 .. 3 { push(counts, 0) }
|
||||
export state ToyPackState {
|
||||
counts: []int = null
|
||||
}
|
||||
function pack_save() -> Val {
|
||||
export function pack_add(toy_pack_st: mut ToyPackState, kind: int, n: int) -> void { toy_pack_st.counts[kind] = toy_pack_st.counts[kind] + n }
|
||||
export function pack_count(toy_pack_st: ToyPackState, kind: int) -> int { return toy_pack_st.counts[kind] }
|
||||
function pack_reset(toy_pack_st: mut ToyPackState) -> void {
|
||||
toy_pack_st.counts = new []int
|
||||
for i in 0 .. 3 { push(toy_pack_st.counts, 0) }
|
||||
}
|
||||
function pack_save(toy_pack_st: ToyPackState) -> Val {
|
||||
let v = Value.object()
|
||||
sv_put_ints(v, "counts", counts)
|
||||
sv_put_ints(v, "counts", toy_pack_st.counts)
|
||||
return v
|
||||
}
|
||||
function pack_load(v: Val, version: int) -> void {
|
||||
pack_reset()
|
||||
function pack_load(toy_pack_st: mut ToyPackState, v: Val, version: int) -> void {
|
||||
pack_reset(toy_pack_st)
|
||||
let xs = sv_ints(v, "counts")
|
||||
for i in 0 .. len(xs) { if i < len(counts) { counts[i] = xs[i] } }
|
||||
for i in 0 .. len(xs) { if i < len(toy_pack_st.counts) { toy_pack_st.counts[i] = xs[i] } }
|
||||
}
|
||||
export function pack_system() -> System {
|
||||
let s = system_new("pack", PH_COMMIT)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue