refactor(runtime,packages,examples): named constants, package enums, idiom sweep

- runtime: HEADLESS_FRAME_PATH, STICK_DEADZONE / STICK_LEFT_X/Y, key and
  byte codes as char literals throughout (`k == 'w'`, `fill(rt_map, ' ', …)`)
- ludic.gameplay/stats: drop the duplicate `stat_field` (it answered "atk"
  for every build stat); Stats.base uses stats_field_name
- ludic.shooter: compare aim modes and fire patterns with AimMode.* and
  WeaponPattern.* instead of raw ints; STICK_RIGHT_X/Y
- ludic.npcai: DecisionMade / brain_set_state use AiState.*
- examples/games/menu.ludic uses Font.load / Ui.* with FONT_PATH and
  BACKDROP named; strings.ludic header says what it prints
- whole tree: `x = x + 1` → `x += 1` (single-term right-hand sides only),
  `0 - x` → `-x`, ASCII codes → char literals; every .ludic and every
  ```ludic fence reformatted with the fixed formatter (whitespace only)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-05 01:12:26 +03:00
parent e3e1bc7784
commit bf36bc8a8f
103 changed files with 1256 additions and 1252 deletions

View file

@ -32,14 +32,14 @@ event CraftCompleted { e: int = 0, recipe: int = 0 }
# Craft.recipe(name, out_item, out_qty) — declare a recipe; returns its id.
@Namespace(Craft) function craft_recipe(name: pointer, out_item: pointer, out_qty: int) -> int {
craft_ensure()
if recipe_n >= CRAFT_MAX { return 0 - 1 }
if recipe_n >= CRAFT_MAX { return -1 }
let id = recipe_n
recipe_out[id] = out_item; recipe_outqty[id] = out_qty
recipe_n = recipe_n + 1
recipe_n += 1
Dict.set(recipe_reg, name, id)
return id
}
@Namespace(Craft) function craft_id(name: pointer) -> int { craft_ensure(); return Dict.get_or(recipe_reg, name, 0 - 1) }
@Namespace(Craft) function craft_id(name: pointer) -> int { craft_ensure(); return Dict.get_or(recipe_reg, name, -1) }
# Craft.ingredient(recipe_name, item, qty) — add an ingredient requirement.
@Namespace(Craft) function craft_ingredient(recipe_name: pointer, item: pointer, qty: int) -> void {
craft_ensure()
@ -47,7 +47,7 @@ event CraftCompleted { e: int = 0, recipe: int = 0 }
if rid < 0 { return }
if ing_n >= CRAFT_ING_MAX { return }
ing_rid[ing_n] = rid; ing_name[ing_n] = item; ing_qty[ing_n] = qty
ing_n = ing_n + 1
ing_n += 1
}
# Craft.can(e, recipe_name) — does the owner hold every ingredient?
@ -60,7 +60,7 @@ event CraftCompleted { e: int = 0, recipe: int = 0 }
if ing_rid[i] == rid {
if Inventory.count(e, ing_name[i]) < ing_qty[i] { return 0 }
}
i = i + 1
i += 1
}
return 1
}
@ -75,7 +75,7 @@ event CraftCompleted { e: int = 0, recipe: int = 0 }
var i = 0
while i < ing_n {
if ing_rid[i] == rid { Inventory.remove(e, ing_name[i], ing_qty[i]) }
i = i + 1
i += 1
}
Inventory.add(e, recipe_out[rid], recipe_outqty[rid])
emit CraftCompleted(e: e, recipe: rid)

View file

@ -38,12 +38,12 @@ event DialogEnded { e: int = 0 }
# Dialog.tree(name) — register (or fetch) a tree id.
@Namespace(Dialog) function dialog_tree(name: pointer) -> int {
dlg_ensure()
let ex = Dict.get_or(dlg_reg, name, 0 - 1)
let ex = Dict.get_or(dlg_reg, name, -1)
if ex >= 0 { return ex }
if dlg_tree_n >= DLG_TREE_MAX { return 0 - 1 }
if dlg_tree_n >= DLG_TREE_MAX { return -1 }
let id = dlg_tree_n
dlg_tree_start[id] = 0 - 1
dlg_tree_n = dlg_tree_n + 1
dlg_tree_start[id] = -1
dlg_tree_n += 1
Dict.set(dlg_reg, name, id)
return id
}
@ -52,21 +52,21 @@ event DialogEnded { e: int = 0 }
@Namespace(Dialog) function dialog_node(tree_name: pointer, text: pointer) -> int {
dlg_ensure()
let tid = dialog_tree(tree_name)
if tid < 0 { return 0 - 1 }
if dlg_node_n >= DLG_NODE_MAX { return 0 - 1 }
if tid < 0 { return -1 }
if dlg_node_n >= DLG_NODE_MAX { return -1 }
let id = dlg_node_n
dlg_node_tree[id] = tid; dlg_node_text[id] = text
dlg_node_n = dlg_node_n + 1
dlg_node_n += 1
if dlg_tree_start[tid] < 0 { dlg_tree_start[tid] = id }
return id
}
# Dialog.choice(node, label, next_node) — add a branch (next_node -1 ends).
@Namespace(Dialog) function dialog_choice(node: int, label: pointer, next_node: int) -> int {
dlg_ensure()
if dlg_choice_n >= DLG_CHOICE_MAX { return 0 - 1 }
if dlg_choice_n >= DLG_CHOICE_MAX { return -1 }
let id = dlg_choice_n
dlg_choice_node[id] = node; dlg_choice_label[id] = label; dlg_choice_next[id] = next_node
dlg_choice_n = dlg_choice_n + 1
dlg_choice_n += 1
return id
}
@ -101,7 +101,7 @@ function dlg_set(e: int, name: pointer, v: int) -> void {
if dlg_get(e, "active") == 0 { return 0 }
let node = dlg_get(e, "node")
var n = 0; var i = 0
while i < dlg_choice_n { if dlg_choice_node[i] == node { n = n + 1 }; i = i + 1 }
while i < dlg_choice_n { if dlg_choice_node[i] == node { n += 1 }; i += 1 }
return n
}
# Dialog.choose(e, i) — take the i-th choice (veto-able); advance or end.
@ -109,12 +109,12 @@ function dlg_set(e: int, name: pointer, v: int) -> void {
dlg_ensure()
if dlg_get(e, "active") == 0 { return 0 }
let node = dlg_get(e, "node")
var seen = 0; var i = 0; var pick = 0 - 1
var seen = 0; var i = 0; var pick = -1
while i < dlg_choice_n {
if dlg_choice_node[i] == node {
if seen == idx { pick = i; i = dlg_choice_n } else { seen = seen + 1 }
if seen == idx { pick = i; i = dlg_choice_n } else { seen += 1 }
}
i = i + 1
i += 1
}
if pick < 0 { return 0 }
if emit DialogChoice(e: e, node: node, choice: idx) != 0 { return 0 }

View file

@ -26,14 +26,14 @@ function item_ensure() -> void {
# Item.def(name, stack_max, weight, value) — register an item template. Returns id.
@Namespace(Item) function item_def(name: pointer, stack_max: int, weight: int, value: int) -> int {
item_ensure()
if item_n >= INV_MAX { return 0 - 1 }
if item_n >= INV_MAX { return -1 }
let id = item_n
item_stackmax[id] = stack_max; item_weight[id] = weight; item_value[id] = value
item_n = item_n + 1
item_n += 1
Dict.set(item_reg, name, id)
return id
}
@Namespace(Item) function item_id(name: pointer) -> int { item_ensure(); return Dict.get_or(item_reg, name, 0 - 1) }
@Namespace(Item) function item_id(name: pointer) -> int { item_ensure(); return Dict.get_or(item_reg, name, -1) }
@Namespace(Item) function item_value_of(name: pointer) -> int {
let id = item_id(name); if id < 0 { return 0 }
return item_value[id]
@ -97,7 +97,7 @@ event cancellable ItemUse { e: int = 0, item: int = 0 } # veto a use (
@Namespace(Inventory) function inventory_spend_gold(e: int, n: int) -> int {
let g = inventory_gold(e)
if g < n { return 0 }
inventory_add_gold(e, 0 - n)
inventory_add_gold(e, -n)
return 1
}

View file

@ -48,7 +48,7 @@ function mv_body_set(e: int, name: pointer, v: int) -> void {
let P = World.prop_id("Body"); if P < 0 { return }
let f = World.field_id(P, name); if f >= 0 { World.set(e, P, f, v) }
}
function mv_sign(a: int) -> int { if a > 0 { return 1 }; if a < 0 { return 0 - 1 }; return 0 }
function mv_sign(a: int) -> int { if a > 0 { return 1 }; if a < 0 { return -1 }; return 0 }
# is the destination cell walkable? Uses the Solids tilemap when configured,
# otherwise the whole field is open.
@ -159,19 +159,19 @@ function mover_free(e: int) -> void {
let ax = mv_pos(e, "x") + mv_get(e, "facing_x") * step
let ay = mv_pos(e, "y") + mv_get(e, "facing_y") * step
let PP = World.prop_id("Position")
if PP < 0 { return 0 - 1 }
if PP < 0 { return -1 }
var o = World.query_next(PP, 0)
while o >= 0 {
if o != e {
let ox = World.get(o, PP, World.field_id(PP, "x"))
let oy = World.get(o, PP, World.field_id(PP, "y"))
let dx = ox - ax; let dy = oy - ay
var adx = dx; if adx < 0 { adx = 0 - adx }
var ady = dy; if ady < 0 { ady = 0 - ady }
var adx = dx; if adx < 0 { adx = -adx }
var ady = dy; if ady < 0 { ady = -ady }
if (adx < step) and (ady < step) { emit Interacted(e: e, target: o); return o }
}
o = World.query_next(PP, o + 1)
}
emit Interacted(e: e, target: 0 - 1)
return 0 - 1
emit Interacted(e: e, target: -1)
return -1
}

View file

@ -9,7 +9,7 @@ const PZ_Q: int = 65536
property Pushable { }
property Switch { on: int = 0 }
property Pressure { on: int = 0, step: int = 16 }
property Gate { open: int = 0, src: int = 0 - 1 }
property Gate { open: int = 0, src: int = -1 }
event BlockPushed { block: int = 0, dx: int = 0, dy: int = 0 }
event cancellable PushBlocked { block: int = 0 }
@ -27,13 +27,13 @@ function pz_pos_set(e: int, name: pointer, v: int) -> void {
# the pushable whose cell is exactly (x, y), or -1.
function pz_block_at(x: int, y: int) -> int {
let P = World.prop_id("Pushable")
if P < 0 { return 0 - 1 }
if P < 0 { return -1 }
var e = World.query_next(P, 0)
while e >= 0 {
if (pz_pos(e, "x") == x) and (pz_pos(e, "y") == y) { return e }
e = World.query_next(P, e + 1)
}
return 0 - 1
return -1
}
# reuse the Mover module's tilemap walkability check when present.
@ -120,9 +120,9 @@ function pz_source_on(src: int) -> int {
if (o != e) and (World.has(o, P) == 0) {
let ox = World.get(o, PP, World.field_id(PP, "x"))
let oy = World.get(o, PP, World.field_id(PP, "y"))
var adx = ox - px; if adx < 0 { adx = 0 - adx }
var ady = oy - py; if ady < 0 { ady = 0 - ady }
if (adx < step) and (ady < step) { on = 1; o = 0 - 1 }
var adx = ox - px; if adx < 0 { adx = -adx }
var ady = oy - py; if ady < 0 { ady = -ady }
if (adx < step) and (ady < step) { on = 1; o = -1 }
}
if o >= 0 { o = World.query_next(PP, o + 1) }
}

View file

@ -41,24 +41,24 @@ event ObjectiveProgressed { quest: int = 0, objective: int = 0, have: int = 0, n
# Quest.define(name) — register a quest (state hidden). Returns id.
@Namespace(Quest) function quest_define(name: pointer) -> int {
quest_ensure()
if quest_n >= QUEST_MAX { return 0 - 1 }
if quest_n >= QUEST_MAX { return -1 }
let id = quest_n
quest_state[id] = 0
quest_n = quest_n + 1
quest_n += 1
Dict.set(quest_reg, name, id)
return id
}
@Namespace(Quest) function quest_id(name: pointer) -> int { quest_ensure(); return Dict.get_or(quest_reg, name, 0 - 1) }
@Namespace(Quest) function quest_id(name: pointer) -> int { quest_ensure(); return Dict.get_or(quest_reg, name, -1) }
# Quest.objective(quest_name, kind, target, need) — add an objective.
@Namespace(Quest) function quest_objective(quest_name: pointer, kind: int, target: int, need: int) -> int {
quest_ensure()
let qid = quest_id(quest_name)
if qid < 0 { return 0 - 1 }
if obj_n >= OBJ_MAX { return 0 - 1 }
if qid < 0 { return -1 }
if obj_n >= OBJ_MAX { return -1 }
let id = obj_n
obj_qid[id] = qid; obj_kind[id] = kind; obj_target[id] = target
obj_need[id] = need; obj_have[id] = 0
obj_n = obj_n + 1
obj_n += 1
return id
}
# Quest.start(name) — activate a quest (emits QuestStarted).
@ -72,7 +72,7 @@ event ObjectiveProgressed { quest: int = 0, objective: int = 0, have: int = 0, n
@Namespace(Quest) function quest_state_of(name: pointer) -> int {
quest_ensure()
let qid = quest_id(name)
if qid < 0 { return 0 - 1 }
if qid < 0 { return -1 }
return quest_state[qid]
}
@ -81,7 +81,7 @@ function quest_all_done(qid: int) -> int {
var i = 0
while i < obj_n {
if obj_qid[i] == qid { if obj_have[i] < obj_need[i] { return 0 } }
i = i + 1
i += 1
}
return 1
}
@ -98,7 +98,7 @@ function quest_all_done(qid: int) -> int {
if obj_kind[i] == kind {
if (obj_target[i] == 0) or (obj_target[i] == target) {
if obj_have[i] < obj_need[i] {
obj_have[i] = obj_have[i] + amount
obj_have[i] += amount
if obj_have[i] > obj_need[i] { obj_have[i] = obj_need[i] }
emit ObjectiveProgressed(quest: qid, objective: i, have: obj_have[i], need: obj_need[i])
if quest_all_done(qid) == 1 {
@ -109,7 +109,7 @@ function quest_all_done(qid: int) -> int {
}
}
}
i = i + 1
i += 1
}
}

View file

@ -22,7 +22,7 @@ event StatusExpired { target: int = 0, kind: int = 0 }
# Status.apply(target, kind, amount, interval, ttl) — attach a timed effect.
@Namespace(Status) function status_apply(target: int, kind: int, amount: int, interval: int, ttl: int) -> int {
let m = World.model_id("StatusFx")
if m < 0 { return 0 - 1 }
if m < 0 { return -1 }
let e = World.spawn(m)
let P = World.prop_id("Status")
World.set(e, P, World.field_id(P, "target"), target)