ludic/packages/ludic.npc/names.ludic
Orkuncakilkaya 58f0dbbc84 fix(ludic.npc): a name picked and a name let go build nothing - the body's names counted in place, the last eight who left in a ring made with the state
ludic deps --allocs (25.2) found npc_pick_name making a list of the body's names at every spawn and
np_left making a new list of the recent names at every retire.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:02:42 +03:00

64 lines
2.3 KiB
Text

# names.ludic - a name nobody else in the place is using: not another person, not one the place
# keeps for itself (NpcWorld.taken: a vendor), and not somebody who left a little while ago
export function npc_name_used(npc_st: NpcState, n: string) -> bool {
if NpcWorld.taken(n) { return true }
let all = npc_walkers(npc_st)
for i in 0 .. len(all) { if all[i].active and all[i].name == n { return true } }
let posts = npc_posts(npc_st)
for i in 0 .. len(posts) { if posts[i].active and posts[i].name == n { return true } }
for i in 0 .. len(npc_st.np_recent) { if npc_st.np_recent[i] != "" and npc_st.np_recent[i] == n { return true } }
return false
}
# a free name from the body's pool, from a place in it the dice choose ("" when the pool is empty)
export function npc_pick_name(npc_st: NpcState, body: int) -> string {
var n = 0
for i in 0 .. NPCN_COUNT { if NpcNames[i].body == body { n += 1 } }
if n == 0 { return "" }
let start = npc_between(npc_st, 0, n - 1)
for k in 0 .. n {
let name = np_name_nth(body, (start + k) % n)
if not npc_name_used(npc_st, name) { return name }
}
return np_name_nth(body, start)
}
# the body's j-th name in the table, counted in place rather than gathered into a list
function np_name_nth(body: int, j: int) -> string {
var seen = 0
for i in 0 .. NPCN_COUNT {
if NpcNames[i].body == body {
if seen == j { return NpcNames[i].name }
seen += 1
}
}
return ""
}
# the last eight who left, in a ring of slots made with the state
function np_left(npc_st: mut NpcState, name: string) -> void {
npc_st.np_recent[npc_st.np_rnext] = name
npc_st.np_rnext = (npc_st.np_rnext + 1) % len(npc_st.np_recent)
}
function np_recent_new() -> []string {
let l = new []string
for i in 0 .. 8 { push(l, "") }
return l
}
function np_recent_clear(npc_st: mut NpcState) -> void {
for i in 0 .. len(npc_st.np_recent) { npc_st.np_recent[i] = "" }
npc_st.np_rnext = 0
}
# how many pairs share a name, the place's own names included
export function npc_name_clashes(npc_st: NpcState) -> int {
var dup = 0
let all = npc_walkers(npc_st)
for i in 0 .. len(all) {
let p = all[i]
if not p.active { continue }
if NpcWorld.taken(p.name) { dup += 1 }
for k in i + 1 .. len(all) { if all[k].active and all[k].name == p.name { dup += 1 } }
}
return dup
}