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:
parent
e3e1bc7784
commit
bf36bc8a8f
103 changed files with 1256 additions and 1252 deletions
|
|
@ -32,7 +32,7 @@ property Brain {
|
|||
home_x: int = 0, home_y: int = 0, seed: int = 1,
|
||||
hunt_blind: int = 0 # 1 = with no target in sight, seek the nearest hostile anyway (no idle patrol)
|
||||
}
|
||||
property Follower { leader: int = 0 - 1, distance: int = 40, mode: int = 0 } # mode 0 follow,1 guard,2 aggressive
|
||||
property Follower { leader: int = -1, distance: int = 40, mode: int = 0 } # mode 0 follow,1 guard,2 aggressive
|
||||
property Steering { separate: int = 0, cohere: int = 0, align: int = 0, radius: int = 48 }
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
@ -59,7 +59,7 @@ function ai_has(prop: pointer, e: int) -> int {
|
|||
let P = World.prop_id(prop); if P < 0 { return 0 }
|
||||
return World.has(e, P)
|
||||
}
|
||||
function sign_i(a: int) -> int { if a > 0 { return 1 }; if a < 0 { return 0 - 1 }; return 0 }
|
||||
function sign_i(a: int) -> int { if a > 0 { return 1 }; if a < 0 { return -1 }; return 0 }
|
||||
|
||||
# optional line-of-sight over the tilemap (only when a Solids config exists);
|
||||
# without a tilemap the field is open, so LOS is always clear.
|
||||
|
|
@ -104,7 +104,7 @@ function ai_los(px: int, py: int, tx: int, ty: int) -> int {
|
|||
let fac = Faction.id_of(e)
|
||||
# nearest hostile in range + LOS
|
||||
let PF = World.prop_id("Faction")
|
||||
var best = 0 - 1
|
||||
var best = -1
|
||||
var bestd = 0
|
||||
var o = World.query_next(PF, 0)
|
||||
while o >= 0 {
|
||||
|
|
@ -196,8 +196,8 @@ function brain_seek(e: int, tx: int, ty: int) -> void {
|
|||
function brain_flee(e: int, tx: int, ty: int) -> void {
|
||||
let px = ai_get("Position", e, "x")
|
||||
let py = ai_get("Position", e, "y")
|
||||
ai_set("Brain", e, "intent_x", 0 - sign_i(tx - px))
|
||||
ai_set("Brain", e, "intent_y", 0 - sign_i(ty - py))
|
||||
ai_set("Brain", e, "intent_x", -sign_i(tx - px))
|
||||
ai_set("Brain", e, "intent_y", -sign_i(ty - py))
|
||||
}
|
||||
function brain_stop(e: int) -> void { ai_set("Brain", e, "intent_x", 0); ai_set("Brain", e, "intent_y", 0) }
|
||||
|
||||
|
|
@ -257,20 +257,20 @@ function ai_decide_fsm(e: int) -> void {
|
|||
let tx = ai_get("Memory", e, "last_x")
|
||||
let ty = ai_get("Memory", e, "last_y")
|
||||
if brain_low_hp(e, ai_get("Brain", e, "flee_pct")) == 1 {
|
||||
if emit DecisionMade(e: e, action: 3) == 0 { brain_set_state(e, 3); brain_flee(e, tx, ty) }
|
||||
if emit DecisionMade(e: e, action: AiState.Flee) == 0 { brain_set_state(e, AiState.Flee); brain_flee(e, tx, ty) }
|
||||
} else {
|
||||
if d2 <= ar * ar {
|
||||
if emit DecisionMade(e: e, action: 2) == 0 { brain_set_state(e, 2); brain_stop(e); ai_set("Brain", e, "want_fire", 1) }
|
||||
if emit DecisionMade(e: e, action: AiState.Attack) == 0 { brain_set_state(e, AiState.Attack); brain_stop(e); ai_set("Brain", e, "want_fire", 1) }
|
||||
} else {
|
||||
if emit DecisionMade(e: e, action: 1) == 0 { brain_set_state(e, 1); brain_seek(e, tx, ty) }
|
||||
if emit DecisionMade(e: e, action: AiState.Chase) == 0 { brain_set_state(e, AiState.Chase); brain_seek(e, tx, ty) }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let prey = brain_nearest_hostile(e)
|
||||
if (ai_get("Brain", e, "hunt_blind") == 1) and (prey >= 0) {
|
||||
if emit DecisionMade(e: e, action: 1) == 0 { brain_set_state(e, 1); brain_seek(e, ai_get("Position", prey, "x"), ai_get("Position", prey, "y")) }
|
||||
if emit DecisionMade(e: e, action: AiState.Chase) == 0 { brain_set_state(e, AiState.Chase); brain_seek(e, ai_get("Position", prey, "x"), ai_get("Position", prey, "y")) }
|
||||
} else {
|
||||
if emit DecisionMade(e: e, action: 0) == 0 { brain_set_state(e, 0); brain_wander(e) }
|
||||
if emit DecisionMade(e: e, action: AiState.Patrol) == 0 { brain_set_state(e, AiState.Patrol); brain_wander(e) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -278,11 +278,11 @@ function ai_decide_fsm(e: int) -> void {
|
|||
function brain_nearest_hostile(e: int) -> int {
|
||||
let PF = World.prop_id("Faction")
|
||||
let PP = World.prop_id("Position")
|
||||
if (PF < 0) or (PP < 0) { return 0 - 1 }
|
||||
if (PF < 0) or (PP < 0) { return -1 }
|
||||
let fac = Faction.id_of(e)
|
||||
let px = ai_get("Position", e, "x")
|
||||
let py = ai_get("Position", e, "y")
|
||||
var best = 0 - 1
|
||||
var best = -1
|
||||
var bestd = 0
|
||||
var o = World.query_next(PF, 0)
|
||||
while o >= 0 {
|
||||
|
|
@ -338,11 +338,11 @@ function ai_decide_bt(e: int) -> void {
|
|||
let ar = ai_get("Brain", e, "attack_range")
|
||||
if ai_get("Memory", e, "has_target") == 1 { # leaf: see_target
|
||||
if brain_target_d2(e) <= ar * ar { # leaf: in_range
|
||||
if emit DecisionMade(e: e, action: 2) == 0 { brain_set_state(e, 2); brain_stop(e); ai_set("Brain", e, "want_fire", 1); return }
|
||||
if emit DecisionMade(e: e, action: AiState.Attack) == 0 { brain_set_state(e, AiState.Attack); brain_stop(e); ai_set("Brain", e, "want_fire", 1); return }
|
||||
}
|
||||
if emit DecisionMade(e: e, action: 1) == 0 { brain_set_state(e, 1); brain_seek(e, tx, ty); return }
|
||||
if emit DecisionMade(e: e, action: AiState.Chase) == 0 { brain_set_state(e, AiState.Chase); brain_seek(e, tx, ty); return }
|
||||
}
|
||||
if emit DecisionMade(e: e, action: 0) == 0 { brain_set_state(e, 0); brain_wander(e) }
|
||||
if emit DecisionMade(e: e, action: AiState.Patrol) == 0 { brain_set_state(e, AiState.Patrol); brain_wander(e) }
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
|
|
@ -404,8 +404,8 @@ function ai_decide_bt(e: int) -> void {
|
|||
let dx = ox - px; let dy = oy - py
|
||||
let d2 = dx * dx + dy * dy
|
||||
if d2 <= radius * radius {
|
||||
sepx = sepx - sign_i(dx); sepy = sepy - sign_i(dy)
|
||||
cx = cx + ox; cy = cy + oy; n = n + 1
|
||||
sepx -= sign_i(dx); sepy -= sign_i(dy)
|
||||
cx += ox; cy += oy; n += 1
|
||||
}
|
||||
}
|
||||
o = World.query_next(PS, o + 1)
|
||||
|
|
@ -413,8 +413,8 @@ function ai_decide_bt(e: int) -> void {
|
|||
if n > 0 {
|
||||
var ix = ai_get("Brain", e, "intent_x")
|
||||
var iy = ai_get("Brain", e, "intent_y")
|
||||
if wsep > 0 { ix = ix + sign_i(sepx); iy = iy + sign_i(sepy) }
|
||||
if wcoh > 0 { ix = ix + sign_i(cx / n - px); iy = iy + sign_i(cy / n - py) }
|
||||
if wsep > 0 { ix += sign_i(sepx); iy += sign_i(sepy) }
|
||||
if wcoh > 0 { ix += sign_i(cx / n - px); iy += sign_i(cy / n - py) }
|
||||
ai_set("Brain", e, "intent_x", sign_i(ix))
|
||||
ai_set("Brain", e, "intent_y", sign_i(iy))
|
||||
}
|
||||
|
|
@ -457,7 +457,7 @@ function ai_decide_bt(e: int) -> void {
|
|||
@Namespace(Ai) function ai_state(e: int) -> int { return ai_get("Brain", e, "state") }
|
||||
@Namespace(Ai) function ai_target(e: int) -> int {
|
||||
if ai_get("Memory", e, "has_target") == 1 { return ai_get("Memory", e, "target") }
|
||||
return 0 - 1
|
||||
return -1
|
||||
}
|
||||
@Namespace(Follower) function follower_set(e: int, leader: int, distance: int, mode: int) -> void {
|
||||
ai_set("Follower", e, "leader", leader)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue