Merge branch 'lang/allocs-physics' into lang/foundations
This commit is contained in:
commit
2bed060d13
32 changed files with 175 additions and 70 deletions
21
packages/ludic.character/fact_pool.ludic
Normal file
21
packages/ludic.character/fact_pool.ludic
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# ludic.character/fact_pool.ludic - the facts' records made at the start (CHARACTERFACTS of them) with a free list
|
||||||
|
# of room for all, so a frame holding a new peak of facts makes nothing until that many are held
|
||||||
|
const CHR_FACTS: int = 64
|
||||||
|
|
||||||
|
function chr_fpool_new() -> []CharacterFact {
|
||||||
|
let l = new []CharacterFact
|
||||||
|
for i in 0 .. CHR_FACTS { push(l, new CharacterFact) }
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
function chr_ffree_new() -> []CharacterFact {
|
||||||
|
let l = chr_fpool_new()
|
||||||
|
List.clear(l)
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
# past them: a record for the new peak, kept in the pool for good
|
||||||
|
@alloc_ok("a new peak of facts held at once, past the 64 made at the start; kept and reused")
|
||||||
|
function chr_fact_more(character_st: mut CharacterState) -> CharacterFact {
|
||||||
|
let f = new CharacterFact
|
||||||
|
push(character_st.chr_fpool, f)
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ numbers float
|
||||||
import "ludic.base"
|
import "ludic.base"
|
||||||
import "rules.ludic"
|
import "rules.ludic"
|
||||||
import "ports.ludic"
|
import "ports.ludic"
|
||||||
|
import "fact_pool.ludic"
|
||||||
import "state.ludic"
|
import "state.ludic"
|
||||||
import "queries.ludic"
|
import "queries.ludic"
|
||||||
import "ground.ludic"
|
import "ground.ludic"
|
||||||
|
|
|
||||||
|
|
@ -104,8 +104,8 @@ export state CharacterState {
|
||||||
chr_safe_x: float = 0.0
|
chr_safe_x: float = 0.0
|
||||||
chr_safe_z: float = 0.0
|
chr_safe_z: float = 0.0
|
||||||
chr_fact_q: Queue<CharacterFact> = chr_fact_q__new()
|
chr_fact_q: Queue<CharacterFact> = chr_fact_q__new()
|
||||||
chr_fpool: []CharacterFact = new []CharacterFact # every fact record made, reused once no drain holds it
|
chr_fpool: []CharacterFact = chr_fpool_new() # every fact record made, reused once no drain holds it
|
||||||
chr_ffree: []CharacterFact = new []CharacterFact
|
chr_ffree: []CharacterFact = chr_ffree_new()
|
||||||
chr_fnext: int = 0
|
chr_fnext: int = 0
|
||||||
}
|
}
|
||||||
function chr__top_plain(x: float, z: float, r: float, from_y: float, step: float, base: float) -> float { return base }
|
function chr__top_plain(x: float, z: float, r: float, from_y: float, step: float, base: float) -> float { return base }
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,7 @@ function chr_fact_record(character_st: mut CharacterState) -> CharacterFact {
|
||||||
character_st.chr_fnext += 1
|
character_st.chr_fnext += 1
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
let f = new CharacterFact
|
return chr_fact_more(character_st)
|
||||||
push(character_st.chr_fpool, f)
|
|
||||||
return f
|
|
||||||
}
|
}
|
||||||
function chr_say(character_st: mut CharacterState, what: int, v: float) -> void {
|
function chr_say(character_st: mut CharacterState, what: int, v: float) -> void {
|
||||||
let f = chr_fact_record(character_st)
|
let f = chr_fact_record(character_st)
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ export function npc_spawn(npc_st: mut NpcState, kind: int) -> NpcPerson {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@alloc_ok("a walker for each of np_max at most; one who left is reused")
|
||||||
if p == null {
|
if p == null {
|
||||||
if len(npc_st.np_walkers) >= npc_st.np_max { return null }
|
if len(npc_st.np_walkers) >= npc_st.np_max { return null }
|
||||||
p = new NpcPerson
|
p = new NpcPerson
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ export function npc_mirroring(npc_st: NpcState) -> bool { return npc_st.np_mirro
|
||||||
# the host's slot: somebody new in it (born), or nobody (gone)
|
# the host's slot: somebody new in it (born), or nobody (gone)
|
||||||
export function npc_put(npc_st: mut NpcState, slot: int, id: int, kind: int, look: int, seed: float, name: string, hx: float, hz: float) -> NpcPerson {
|
export function npc_put(npc_st: mut NpcState, slot: int, id: int, kind: int, look: int, seed: float, name: string, hx: float, hz: float) -> NpcPerson {
|
||||||
if slot < 0 or slot >= npc_st.np_max or kind < 0 or kind >= NPCK_COUNT { return null }
|
if slot < 0 or slot >= npc_st.np_max or kind < 0 or kind >= NPCK_COUNT { return null }
|
||||||
|
@alloc_ok("a guest's copy of the host's slots, no more than np_max")
|
||||||
while len(npc_st.np_walkers) <= slot {
|
while len(npc_st.np_walkers) <= slot {
|
||||||
let q = new NpcPerson
|
let q = new NpcPerson
|
||||||
q.slot = len(npc_st.np_walkers)
|
q.slot = len(npc_st.np_walkers)
|
||||||
|
|
|
||||||
|
|
@ -7,30 +7,47 @@ export function npc_name_used(npc_st: NpcState, n: string) -> bool {
|
||||||
for i in 0 .. len(all) { if all[i].active and all[i].name == n { return true } }
|
for i in 0 .. len(all) { if all[i].active and all[i].name == n { return true } }
|
||||||
let posts = npc_posts(npc_st)
|
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(posts) { if posts[i].active and posts[i].name == n { return true } }
|
||||||
if npc_st.np_recent != null { for i in 0 .. len(npc_st.np_recent) { if npc_st.np_recent[i] == 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
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
# a free name from the body's pool, from a place in it the dice choose ("" when the pool is empty)
|
# 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 {
|
export function npc_pick_name(npc_st: NpcState, body: int) -> string {
|
||||||
let pool = new []string
|
var n = 0
|
||||||
for i in 0 .. NPCN_COUNT { if NpcNames[i].body == body { push(pool, NpcNames[i].name) } }
|
for i in 0 .. NPCN_COUNT { if NpcNames[i].body == body { n += 1 } }
|
||||||
let n = len(pool)
|
|
||||||
if n == 0 { return "" }
|
if n == 0 { return "" }
|
||||||
let start = npc_between(npc_st, 0, n - 1)
|
let start = npc_between(npc_st, 0, n - 1)
|
||||||
for k in 0 .. n {
|
for k in 0 .. n {
|
||||||
let name = pool[(start + k) % n]
|
let name = np_name_nth(body, (start + k) % n)
|
||||||
if not npc_name_used(npc_st, name) { return name }
|
if not npc_name_used(npc_st, name) { return name }
|
||||||
}
|
}
|
||||||
return pool[start]
|
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 {
|
function np_left(npc_st: mut NpcState, name: string) -> void {
|
||||||
push(npc_st.np_recent, name)
|
npc_st.np_recent[npc_st.np_rnext] = name
|
||||||
if len(npc_st.np_recent) <= 8 { return }
|
npc_st.np_rnext = (npc_st.np_rnext + 1) % len(npc_st.np_recent)
|
||||||
let keep = new []string
|
}
|
||||||
for i in len(npc_st.np_recent) - 8 .. len(npc_st.np_recent) { push(keep, npc_st.np_recent[i]) }
|
function np_recent_new() -> []string {
|
||||||
npc_st.np_recent = keep
|
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
|
# how many pairs share a name, the place's own names included
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ export state NpcState {
|
||||||
np_wx: float = 0.0
|
np_wx: float = 0.0
|
||||||
np_wz: float = 0.0
|
np_wz: float = 0.0
|
||||||
np_clock: float = 0.0
|
np_clock: float = 0.0
|
||||||
np_recent: []string = new []string # the last few names that left
|
np_recent: []string = np_recent_new() # the last few names that left, a ring
|
||||||
|
np_rnext: int = 0
|
||||||
np_walkers: []NpcPerson = new []NpcPerson
|
np_walkers: []NpcPerson = new []NpcPerson
|
||||||
np_posts: []NpcPerson = new []NpcPerson
|
np_posts: []NpcPerson = new []NpcPerson
|
||||||
np_max: int = 10 # walkers at most
|
np_max: int = 10 # walkers at most
|
||||||
|
|
|
||||||
|
|
@ -24,3 +24,10 @@ function np_queue_sized(q: Queue<NpcFact>) -> Queue<NpcFact> {
|
||||||
List.clear(q.spare)
|
List.clear(q.spare)
|
||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
# past them: a record for the new peak, kept in the pool for good
|
||||||
|
@alloc_ok("a new peak of facts held at once, past the 64 made at the start; kept and reused")
|
||||||
|
function np_fact_more(npc_st: mut NpcState) -> NpcFact {
|
||||||
|
let f = new NpcFact
|
||||||
|
push(npc_st.np_fpool, f)
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ export function npc_reset(npc_st: mut NpcState) -> void {
|
||||||
npc_st.np_n = 0
|
npc_st.np_n = 0
|
||||||
npc_st.np_next_h = 0.0
|
npc_st.np_next_h = 0.0
|
||||||
npc_st.np_hold = false
|
npc_st.np_hold = false
|
||||||
npc_st.np_recent = new []string
|
np_recent_clear(npc_st)
|
||||||
q_clear(npc_facts(npc_st))
|
q_clear(npc_facts(npc_st))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,9 +94,7 @@ function np_fact_record(npc_st: mut NpcState) -> NpcFact {
|
||||||
f.z = 0.0
|
f.z = 0.0
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
let f = new NpcFact
|
return np_fact_more(npc_st)
|
||||||
push(npc_st.np_fpool, f)
|
|
||||||
return f
|
|
||||||
}
|
}
|
||||||
# how many fact records have ever been made: the peak held at once, not the facts pushed
|
# how many fact records have ever been made: the peak held at once, not the facts pushed
|
||||||
export function npc_fact_records(npc_st: NpcState) -> int { return len(npc_st.np_fpool) }
|
export function npc_fact_records(npc_st: NpcState) -> int { return len(npc_st.np_fpool) }
|
||||||
|
|
|
||||||
21
packages/ludic.physics/fact_pool.ludic
Normal file
21
packages/ludic.physics/fact_pool.ludic
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# ludic.physics/fact_pool.ludic - the facts' records made at the start (PHYSFACTS of them) with a free list
|
||||||
|
# of room for all, so a frame holding a new peak of facts makes nothing until that many are held
|
||||||
|
const PH_FACTS: int = 64
|
||||||
|
|
||||||
|
function ph_fpool_new() -> []PhysFact {
|
||||||
|
let l = new []PhysFact
|
||||||
|
for i in 0 .. PH_FACTS { push(l, new PhysFact) }
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
function ph_ffree_new() -> []PhysFact {
|
||||||
|
let l = ph_fpool_new()
|
||||||
|
List.clear(l)
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
# past them: a record for the new peak, kept in the pool for good
|
||||||
|
@alloc_ok("a new peak of facts held at once, past the 64 made at the start; kept and reused")
|
||||||
|
function ph_fact_more(physics_st: mut PhysicsState) -> PhysFact {
|
||||||
|
let f = new PhysFact
|
||||||
|
push(physics_st.ph_fpool, f)
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ numbers float
|
||||||
import "ludic.base"
|
import "ludic.base"
|
||||||
import "native.ludic"
|
import "native.ludic"
|
||||||
import "state.ludic"
|
import "state.ludic"
|
||||||
|
import "fact_pool.ludic"
|
||||||
import "shape_ids.ludic"
|
import "shape_ids.ludic"
|
||||||
import "owned.ludic"
|
import "owned.ludic"
|
||||||
import "shapes.ludic"
|
import "shapes.ludic"
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
const PH_INDEX: int = 8388607 # a body id's low 23 bits are its index (Jolt's BodyID)
|
const PH_INDEX: int = 8388607 # a body id's low 23 bits are its index (Jolt's BodyID)
|
||||||
|
|
||||||
# every body owns nothing: at a world's opening, the table made once at its size and kept after
|
# every body owns nothing: at a world's opening, the table made once at its size and kept after
|
||||||
|
@alloc_ok("the body table made at its size when a world opens, kept after")
|
||||||
function ph_own_reset(physics_st: mut PhysicsState, max_bodies: int) -> void {
|
function ph_own_reset(physics_st: mut PhysicsState, max_bodies: int) -> void {
|
||||||
if len(physics_st.ph_own) < max_bodies {
|
if len(physics_st.ph_own) < max_bodies {
|
||||||
List.clear(physics_st.ph_own)
|
List.clear(physics_st.ph_own)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ function ph_keep(physics_st: mut PhysicsState, s: pointer) -> int {
|
||||||
physics_st.ph_shapes[id] = s
|
physics_st.ph_shapes[id] = s
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
@alloc_ok("the id table grows to the most shapes held at once; a freed id is handed out again")
|
||||||
push(physics_st.ph_shapes, s)
|
push(physics_st.ph_shapes, s)
|
||||||
return len(physics_st.ph_shapes) - 1
|
return len(physics_st.ph_shapes) - 1
|
||||||
}
|
}
|
||||||
|
|
@ -26,6 +27,7 @@ export function phys_shape_free(physics_st: mut PhysicsState, id: int) -> void {
|
||||||
if s == null { return }
|
if s == null { return }
|
||||||
jph_shape_free(s)
|
jph_shape_free(s)
|
||||||
physics_st.ph_shapes[id] = null
|
physics_st.ph_shapes[id] = null
|
||||||
|
@alloc_ok("the spare ids, no more than the most shapes ever held")
|
||||||
push(physics_st.ph_spare, id)
|
push(physics_st.ph_spare, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,7 @@ export function phys_close(physics_st: mut PhysicsState) -> void {
|
||||||
}
|
}
|
||||||
if physics_st.ph_shapes != null { List.clear(physics_st.ph_shapes) }
|
if physics_st.ph_shapes != null { List.clear(physics_st.ph_shapes) }
|
||||||
List.clear(physics_st.ph_spare)
|
List.clear(physics_st.ph_spare)
|
||||||
List.clear(physics_st.ph_floats)
|
physics_st.ph_nf = 0
|
||||||
List.clear(physics_st.ph_float_k)
|
|
||||||
if physics_st.ph_facts != null { q_clear(physics_st.ph_facts) }
|
if physics_st.ph_facts != null { q_clear(physics_st.ph_facts) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,18 +46,17 @@ export state PhysicsState {
|
||||||
ph_steps: int = 0
|
ph_steps: int = 0
|
||||||
ph_gen: int = 0 # how many worlds have been opened: an id from an older one is stale
|
ph_gen: int = 0 # how many worlds have been opened: an id from an older one is stale
|
||||||
ph_hard: float = 2.0 # metres a second: a contact under this is not a fact
|
ph_hard: float = 2.0 # metres a second: a contact under this is not a fact
|
||||||
ph_floats: []int = new []int # buoyant bodies' ids
|
ph_floats: words = words(256) # buoyant bodies' ids, the first ph_nf of them
|
||||||
ph_float_k: []float = new []float # and theirs: buoyancy, linear drag, angular drag, wet
|
ph_float_k: floats = floats(256 * 4) # and theirs: buoyancy, linear drag, angular drag, wet
|
||||||
ph_floats2: []int = new []int # the spare pair phys_sink filters into
|
ph_nf: int = 0
|
||||||
ph_float_k2: []float = new []float
|
|
||||||
ph_rx: float = 0.0 # where the last phys_resolve put a body
|
ph_rx: float = 0.0 # where the last phys_resolve put a body
|
||||||
ph_rz: float = 0.0
|
ph_rz: float = 0.0
|
||||||
ph_walkers: []pointer = new []pointer # a walker id is its place here; null once removed
|
ph_walkers: []pointer = new []pointer # a walker id is its place here; null once removed
|
||||||
ph_ids: []int = words(PH_CAP * 2)
|
ph_ids: []int = words(PH_CAP * 2)
|
||||||
ph_vals: []float = floats(PH_CAP * 4)
|
ph_vals: []float = floats(PH_CAP * 4)
|
||||||
ph_facts: Queue<PhysFact> = ph_facts__new()
|
ph_facts: Queue<PhysFact> = ph_facts__new()
|
||||||
ph_fpool: []PhysFact = new []PhysFact # every fact record made, reused once no drain holds it
|
ph_fpool: []PhysFact = ph_fpool_new() # every fact record made, reused once no drain holds it
|
||||||
ph_ffree: []PhysFact = new []PhysFact
|
ph_ffree: []PhysFact = ph_ffree_new()
|
||||||
ph_fnext: int = 0
|
ph_fnext: int = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,7 @@ function ph_fact_record(physics_st: mut PhysicsState) -> PhysFact {
|
||||||
physics_st.ph_fnext += 1
|
physics_st.ph_fnext += 1
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
let f = new PhysFact
|
return ph_fact_more(physics_st)
|
||||||
push(physics_st.ph_fpool, f)
|
|
||||||
return f
|
|
||||||
}
|
}
|
||||||
function ph_contacts(physics_st: mut PhysicsState) -> void {
|
function ph_contacts(physics_st: mut PhysicsState) -> void {
|
||||||
let n = jph_contacts_drain(physics_st.ph_world, physics_st.ph_ids, physics_st.ph_vals, PH_CAP)
|
let n = jph_contacts_drain(physics_st.ph_world, physics_st.ph_ids, physics_st.ph_vals, PH_CAP)
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ export function phys_walker_add(physics_st: mut PhysicsState, r: float, h: float
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@alloc_ok("a slot for the most walkers at once; a removed one's slot is reused")
|
||||||
push(physics_st.ph_walkers, k)
|
push(physics_st.ph_walkers, k)
|
||||||
return len(physics_st.ph_walkers) - 1
|
return len(physics_st.ph_walkers) - 1
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,46 +2,42 @@
|
||||||
# carried by its current, and slowed by its drags. Reaching the water is a PHYS_SPLASH fact.
|
# carried by its current, and slowed by its drags. Reaching the water is a PHYS_SPLASH fact.
|
||||||
const PH_K: int = 4
|
const PH_K: int = 4
|
||||||
|
|
||||||
# buoyancy 1 floats level with the surface, more rides higher; drags in 1/s
|
# buoyancy 1 floats level with the surface, more rides higher; drags in 1/s. At most 256 float at
|
||||||
|
# once (a table made with the state): past that a body is simply not buoyed
|
||||||
export function phys_float(physics_st: mut PhysicsState, id: int, buoyancy: float, linear_drag: float, angular_drag: float) -> void {
|
export function phys_float(physics_st: mut PhysicsState, id: int, buoyancy: float, linear_drag: float, angular_drag: float) -> void {
|
||||||
ph_buffers()
|
ph_buffers()
|
||||||
phys_sink(physics_st, id)
|
phys_sink(physics_st, id)
|
||||||
push(physics_st.ph_floats, id)
|
if physics_st.ph_nf >= len(physics_st.ph_floats) { return }
|
||||||
push(physics_st.ph_float_k, buoyancy)
|
let i = physics_st.ph_nf
|
||||||
push(physics_st.ph_float_k, linear_drag)
|
physics_st.ph_floats[i] = id
|
||||||
push(physics_st.ph_float_k, angular_drag)
|
physics_st.ph_float_k[i * PH_K] = buoyancy
|
||||||
push(physics_st.ph_float_k, 0.0)
|
physics_st.ph_float_k[i * PH_K + 1] = linear_drag
|
||||||
|
physics_st.ph_float_k[i * PH_K + 2] = angular_drag
|
||||||
|
physics_st.ph_float_k[i * PH_K + 3] = 0.0
|
||||||
|
physics_st.ph_nf += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# no longer floats (it is still a body); every removal asks, so the lists are filtered into a kept
|
# no longer floats (it is still a body): the last one takes its row
|
||||||
# spare pair and swapped, never made anew
|
|
||||||
export function phys_sink(physics_st: mut PhysicsState, id: int) -> void {
|
export function phys_sink(physics_st: mut PhysicsState, id: int) -> void {
|
||||||
if physics_st.ph_floats == null { return }
|
for i in 0 .. physics_st.ph_nf {
|
||||||
let ids = physics_st.ph_floats2
|
if physics_st.ph_floats[i] == id {
|
||||||
let ks = physics_st.ph_float_k2
|
let last = physics_st.ph_nf - 1
|
||||||
List.clear(ids)
|
physics_st.ph_floats[i] = physics_st.ph_floats[last]
|
||||||
List.clear(ks)
|
for k in 0 .. PH_K { physics_st.ph_float_k[i * PH_K + k] = physics_st.ph_float_k[last * PH_K + k] }
|
||||||
for i in 0 .. len(physics_st.ph_floats) {
|
physics_st.ph_nf = last
|
||||||
if physics_st.ph_floats[i] != id {
|
return
|
||||||
push(ids, physics_st.ph_floats[i])
|
|
||||||
for k in 0 .. PH_K { push(ks, physics_st.ph_float_k[i * PH_K + k]) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
physics_st.ph_floats2 = physics_st.ph_floats
|
|
||||||
physics_st.ph_float_k2 = physics_st.ph_float_k
|
|
||||||
physics_st.ph_floats = ids
|
|
||||||
physics_st.ph_float_k = ks
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function phys_floating(physics_st: PhysicsState, id: int) -> bool {
|
export function phys_floating(physics_st: PhysicsState, id: int) -> bool {
|
||||||
if physics_st.ph_floats == null { return false }
|
for i in 0 .. physics_st.ph_nf { if physics_st.ph_floats[i] == id { return true } }
|
||||||
for i in 0 .. len(physics_st.ph_floats) { if physics_st.ph_floats[i] == id { return true } }
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
function ph_buoy_all(physics_st: mut PhysicsState) -> void {
|
function ph_buoy_all(physics_st: mut PhysicsState) -> void {
|
||||||
let dt = physics_st.ph_step
|
let dt = physics_st.ph_step
|
||||||
for i in 0 .. len(physics_st.ph_floats) {
|
for i in 0 .. physics_st.ph_nf {
|
||||||
let id = physics_st.ph_floats[i]
|
let id = physics_st.ph_floats[i]
|
||||||
if jph_body_read(physics_st.ph_world, id, physics_st.ph_vals) == 0 {
|
if jph_body_read(physics_st.ph_world, id, physics_st.ph_vals) == 0 {
|
||||||
ph_buoy_one(physics_st, i, id, physics_st.ph_vals[0], physics_st.ph_vals[2], dt)
|
ph_buoy_one(physics_st, i, id, physics_st.ph_vals[0], physics_st.ph_vals[2], dt)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
# call.ludic - a player's boat or horse brought to a place: made there the first time, fetched there
|
# call.ludic - a player's boat or horse brought to a place: made there the first time, fetched there
|
||||||
# after; gone when its player leaves
|
# after; gone when its player leaves
|
||||||
|
@alloc_ok("a player's own boat or horse, made the first time it is called and fetched after")
|
||||||
function ve_add(vehicles_st: VehiclesState, kind: int, owner: int, x: float, z: float, yaw: float) -> Vehicle {
|
function ve_add(vehicles_st: VehiclesState, kind: int, owner: int, x: float, z: float, yaw: float) -> Vehicle {
|
||||||
if kind != VEHICLE_HORSE and kind != VEHICLE_BOAT { return null }
|
if kind != VEHICLE_HORSE and kind != VEHICLE_BOAT { return null }
|
||||||
let v = new Vehicle
|
let v = new Vehicle
|
||||||
|
|
|
||||||
21
packages/ludic.vehicles/fact_pool.ludic
Normal file
21
packages/ludic.vehicles/fact_pool.ludic
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# ludic.vehicles/fact_pool.ludic - the facts' records made at the start (VEHICLEFACTS of them) with a free list
|
||||||
|
# of room for all, so a frame holding a new peak of facts makes nothing until that many are held
|
||||||
|
const VE_FACTS: int = 64
|
||||||
|
|
||||||
|
function ve_fpool_new() -> []VehicleFact {
|
||||||
|
let l = new []VehicleFact
|
||||||
|
for i in 0 .. VE_FACTS { push(l, new VehicleFact) }
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
function ve_ffree_new() -> []VehicleFact {
|
||||||
|
let l = ve_fpool_new()
|
||||||
|
List.clear(l)
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
# past them: a record for the new peak, kept in the pool for good
|
||||||
|
@alloc_ok("a new peak of facts held at once, past the 64 made at the start; kept and reused")
|
||||||
|
function ve_fact_more(vehicles_st: mut VehiclesState) -> VehicleFact {
|
||||||
|
let f = new VehicleFact
|
||||||
|
push(vehicles_st.ve_fpool, f)
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import "ludic.base"
|
||||||
import "kinds.ludic"
|
import "kinds.ludic"
|
||||||
import "table.ludic"
|
import "table.ludic"
|
||||||
import "ports.ludic"
|
import "ports.ludic"
|
||||||
|
import "fact_pool.ludic"
|
||||||
import "state.ludic"
|
import "state.ludic"
|
||||||
import "places.ludic"
|
import "places.ludic"
|
||||||
import "call.ludic"
|
import "call.ludic"
|
||||||
|
|
|
||||||
|
|
@ -63,8 +63,8 @@ export state VehiclesState {
|
||||||
ve_ly: float = 0.0
|
ve_ly: float = 0.0
|
||||||
ve_lz: float = 0.0
|
ve_lz: float = 0.0
|
||||||
ve_fact_q: Queue<VehicleFact> = ve_fact_q__new()
|
ve_fact_q: Queue<VehicleFact> = ve_fact_q__new()
|
||||||
ve_fpool: []VehicleFact = new []VehicleFact # every fact record made, reused once no drain holds it
|
ve_fpool: []VehicleFact = ve_fpool_new() # every fact record made, reused once no drain holds it
|
||||||
ve_ffree: []VehicleFact = new []VehicleFact
|
ve_ffree: []VehicleFact = ve_ffree_new()
|
||||||
ve_fnext: int = 0
|
ve_fnext: int = 0
|
||||||
}
|
}
|
||||||
function ve__dry(x: float, z: float) -> float { return -10000.0 }
|
function ve__dry(x: float, z: float) -> float { return -10000.0 }
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,7 @@ function ve_fact_record(vehicles_st: mut VehiclesState) -> VehicleFact {
|
||||||
vehicles_st.ve_fnext += 1
|
vehicles_st.ve_fnext += 1
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
let f = new VehicleFact
|
return ve_fact_more(vehicles_st)
|
||||||
push(vehicles_st.ve_fpool, f)
|
|
||||||
return f
|
|
||||||
}
|
}
|
||||||
# how many fact records have ever been made: the peak held at once, not the facts pushed
|
# how many fact records have ever been made: the peak held at once, not the facts pushed
|
||||||
export function vehicle_fact_records(vehicles_st: VehiclesState) -> int { return len(vehicles_st.ve_fpool) }
|
export function vehicle_fact_records(vehicles_st: VehiclesState) -> int { return len(vehicles_st.ve_fpool) }
|
||||||
|
|
|
||||||
|
|
@ -376,7 +376,7 @@ program VehiclesTest {
|
||||||
expect(vehicle_by_nid(vehicles_st, b.nid) == null)
|
expect(vehicle_by_nid(vehicles_st, b.nid) == null)
|
||||||
}
|
}
|
||||||
|
|
||||||
test "a fed fact a turn, drained each turn, makes a few records and then reuses them" (vehicles_st: mut VehiclesState, vehicles_test_st: mut VehiclesTestState) {
|
test "a fed fact a turn, drained each turn, makes no record past the ones made at the start" (vehicles_st: mut VehiclesState, vehicles_test_st: mut VehiclesTestState) {
|
||||||
fresh(vehicles_st, vehicles_test_st)
|
fresh(vehicles_st, vehicles_test_st)
|
||||||
vehicle_call_for(vehicles_st, 0, VEHICLE_HORSE, 0)
|
vehicle_call_for(vehicles_st, 0, VEHICLE_HORSE, 0)
|
||||||
let h = vehicle_find(vehicles_st, VEHICLE_HORSE)
|
let h = vehicle_find(vehicles_st, VEHICLE_HORSE)
|
||||||
|
|
@ -386,6 +386,6 @@ program VehiclesTest {
|
||||||
fed += count(facts(vehicles_st), VEHICLE_FED)
|
fed += count(facts(vehicles_st), VEHICLE_FED)
|
||||||
}
|
}
|
||||||
expect_eq(fed, 1000)
|
expect_eq(fed, 1000)
|
||||||
expect(vehicle_fact_records(vehicles_st) <= 4)
|
expect_eq(vehicle_fact_records(vehicles_st), 64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
packages/ludic.wildlife/fact_pool.ludic
Normal file
21
packages/ludic.wildlife/fact_pool.ludic
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# ludic.wildlife/fact_pool.ludic - the facts' records made at the start (WILDFACTS of them) with a free list
|
||||||
|
# of room for all, so a frame holding a new peak of facts makes nothing until that many are held
|
||||||
|
const WL_FACTS: int = 64
|
||||||
|
|
||||||
|
function wl_fpool_new() -> []WildFact {
|
||||||
|
let l = new []WildFact
|
||||||
|
for i in 0 .. WL_FACTS { push(l, new WildFact) }
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
function wl_ffree_new() -> []WildFact {
|
||||||
|
let l = wl_fpool_new()
|
||||||
|
List.clear(l)
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
# past them: a record for the new peak, kept in the pool for good
|
||||||
|
@alloc_ok("a new peak of facts held at once, past the 64 made at the start; kept and reused")
|
||||||
|
function wl_fact_more(wildlife_st: mut WildlifeState) -> WildFact {
|
||||||
|
let f = new WildFact
|
||||||
|
push(wildlife_st.wl_fpool, f)
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
@ -48,9 +48,7 @@ function wl_fact_record(wildlife_st: mut WildlifeState) -> WildFact {
|
||||||
f.diet = 0
|
f.diet = 0
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
let f = new WildFact
|
return wl_fact_more(wildlife_st)
|
||||||
push(wildlife_st.wl_fpool, f)
|
|
||||||
return f
|
|
||||||
}
|
}
|
||||||
# how many fact records have ever been made: the peak held at once, not the facts pushed
|
# how many fact records have ever been made: the peak held at once, not the facts pushed
|
||||||
export function wildlife_fact_records(wildlife_st: WildlifeState) -> int { return len(wildlife_st.wl_fpool) }
|
export function wildlife_fact_records(wildlife_st: WildlifeState) -> int { return len(wildlife_st.wl_fpool) }
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ module ludic_wildlife uses ludic_base
|
||||||
numbers float
|
numbers float
|
||||||
import "ludic.base"
|
import "ludic.base"
|
||||||
import "species.ludic"
|
import "species.ludic"
|
||||||
|
import "fact_pool.ludic"
|
||||||
import "animal.ludic"
|
import "animal.ludic"
|
||||||
import "places.ludic"
|
import "places.ludic"
|
||||||
import "port.ludic"
|
import "port.ludic"
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ export property WildSpecies {
|
||||||
|
|
||||||
export state WildlifeState {
|
export state WildlifeState {
|
||||||
wl_facts: Queue<WildFact> = wl_facts__new()
|
wl_facts: Queue<WildFact> = wl_facts__new()
|
||||||
wl_fpool: []WildFact = new []WildFact # every fact record made, reused once no drain holds it
|
wl_fpool: []WildFact = wl_fpool_new() # every fact record made, reused once no drain holds it
|
||||||
wl_ffree: []WildFact = new []WildFact # of those, the ones free at the last look
|
wl_ffree: []WildFact = wl_ffree_new() # of those, the ones free at the last look
|
||||||
wl_fnext: []int = words(1) # the next of them to hand out
|
wl_fnext: []int = words(1) # the next of them to hand out
|
||||||
wl_own: WildTable = null # a guest's own animals, put away whole while it draws the host's
|
wl_own: WildTable = null # a guest's own animals, put away whole while it draws the host's
|
||||||
wl_host: WildTable = wl__new() # the table the host's are drawn into: made once, cleared per join
|
wl_host: WildTable = wl__new() # the table the host's are drawn into: made once, cleared per join
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ export property WildTable {
|
||||||
nids: IntMap = null
|
nids: IntMap = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@alloc_ok("a table of animals: a load, or a guest taking the host's")
|
||||||
function wl__new() -> WildTable {
|
function wl__new() -> WildTable {
|
||||||
let w = new WildTable
|
let w = new WildTable
|
||||||
let tb: Table<WildAnimal> = table_new(2, 2)
|
let tb: Table<WildAnimal> = table_new(2, 2)
|
||||||
|
|
|
||||||
|
|
@ -84,13 +84,13 @@ program WildCrowdTest {
|
||||||
expect(not wildlife_listed(wildlife_st, a))
|
expect(not wildlife_listed(wildlife_st, a))
|
||||||
}
|
}
|
||||||
|
|
||||||
test "a fact a frame, drained each frame, makes a few records and then reuses them" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
test "a fact a frame, drained each frame, makes no record past the ones made at the start" (wildlife_st: mut WildlifeState, wildlife_tests_fake_st: mut WildlifeTestsFakeState) {
|
||||||
let a = walker(wildlife_st, wildlife_tests_fake_st)
|
let a = walker(wildlife_st, wildlife_tests_fake_st)
|
||||||
for k in 1 .. 3001 {
|
for k in 1 .. 3001 {
|
||||||
wildlife_moved(wildlife_st, a, 0.0, -3.0 * float(k), 0.0, -1.2)
|
wildlife_moved(wildlife_st, a, 0.0, -3.0 * float(k), 0.0, -1.2)
|
||||||
let fs = q_drain(wildlife_facts(wildlife_st))
|
let fs = q_drain(wildlife_facts(wildlife_st))
|
||||||
for i in 0 .. len(fs) { expect_eq(fs[i].what, WILD_PRINT) }
|
for i in 0 .. len(fs) { expect_eq(fs[i].what, WILD_PRINT) }
|
||||||
}
|
}
|
||||||
expect(wildlife_fact_records(wildlife_st) <= 4)
|
expect_eq(wildlife_fact_records(wildlife_st), 64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue