Merge branch 'lang/ecs' into lang/foundations

This commit is contained in:
Orkun ÇAKILKAYA 2026-09-28 17:10:20 +03:00
commit 0a078c7822
6 changed files with 13 additions and 11 deletions

View file

@ -40,7 +40,7 @@ import "ludic.base"
| `Tick { dt, frame, hours }`, `tick_new(dt, frame, hours)` | what a system's tick receives |
| `PH_INPUT`, `PH_SENSE`, `PH_SIMULATE`, `PH_RESOLVE`, `PH_COMMIT`, `PH_PRESENT`, `PH_COUNT` | the phases, in the order they run |
| `Queue<T>`, `queue_new<T>(name)`, `q_push(q, v)`, `q_drain(q) -> []T`, `q_len(q)`, `q_clear(q)` | facts, first in first out (`queue_new`, not `q_new`: that name is render3d's quaternion). A queue keeps its own count, so its verbs take only the queue: a mechanic's verbs take only the mechanic's own state |
| `q_tag(q) -> QueueTag`, `core_undrained(tags) -> []string` | the names of the given queues still holding facts; ask it at the end of a frame |
| `q_tag(q) -> QueueTag`, `core_undrained(tags, out) -> int` | the names of the given queues still holding facts, into a list the caller keeps; ask it at the end of a frame |
| `Rng`, `rng_new(seed)`, `rng_seed(r, seed)`, `rng_next(r)`, `rng_float(r)`, `rng_between(r, lo, hi)`, `rng_span(r, lo, hi)` | a xorshift32 stream of its own (`rng_between` is inclusive; `rng_range` is taken by `Random.range`) |
| `SaveNode { found, version, data }`, `save_tree()`, `save_section(root, key, version, v)`, `load_section(root, key) -> SaveNode`, `save_encode`, `save_decode` | the save tree: `{"fishing": {"v": 3, ...}}`; `v` is reserved in a section, and a non-object value rides under `data` |
| `sv_int`, `sv_float`, `sv_bool`, `sv_str` (key, fallback), `sv_ints` | typed reads with a fallback; a float is kept as thousandths |

View file

@ -34,6 +34,7 @@ export function hd_new(p: HandlePool) -> int {
return s | (p.gen[s] << 22)
}
@alloc_ok("only when a pool is full: the words of its panic")
function hd_refuse(p: HandlePool) -> int {
p.refused += 1
if p.strict { panic(`handle pool {p.name} is full at {len(p.gen)}`) }

View file

@ -73,12 +73,12 @@ export function q_unheld<T>(q: Queue<T>, pool: []T, out: []T) -> int {
# a queue's tag, for core_undrained: queues of different facts in one list
export function q_tag<T>(q: Queue<T>) -> QueueTag { return q.tag }
# the names of the given queues still holding facts; ask it at the end of a frame, where a fact
# left behind is a route nobody wrote
export function core_undrained(tags: []QueueTag) -> []string {
let out = new []string
# the names of the given queues still holding facts, into `out` (cleared first) and counted; ask it
# at the end of a frame, where a fact left behind is a route nobody wrote
export function core_undrained(tags: []QueueTag, out: []string) -> int {
List.clear(out)
for i in 0 .. len(tags) {
if tags[i] != null and tags[i].pending > 0 { push(out, tags[i].name) }
if tags[i] != null and tags[i].pending > 0 { kept_push(out, tags[i].name) }
}
return out
return len(out)
}

View file

@ -86,11 +86,11 @@ program QueueTest {
q_push(b, 2)
q_drain(b)
let tags = [q_tag(a), q_tag(b)]
let names = core_undrained(tags)
expect_eq(len(names), 1)
let names = new []string
expect_eq(core_undrained(tags, names), 1)
expect(names[0] == "left_behind")
q_drain(a)
expect_eq(len(core_undrained(tags)), 0)
expect_eq(core_undrained(tags, names), 0)
}
# an empty drain allocates nothing and hands back the same empty list; a drained list is the

View file

@ -35,7 +35,7 @@ program RouteTest {
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([q_tag(toy_fishing_st.caught)])), 0)
expect_eq(core_undrained([q_tag(toy_fishing_st.caught)], new []string), 0)
}
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) {

View file

@ -2,6 +2,7 @@
# at most 24 characters, so a folder of photographs browses well
const PHT_ALPHA: string = "0123456789abcdefghijklmnopqrstuvwxyz"
@alloc_ok("on a photograph taken: its file name")
export function photo_slug(tags: string) -> string {
var out = ""
var n = 0