zones_set / zones_clear / zones_merge, zones_contains / zones_nearest and the clusters' bounding circles, over fixed arrays of ZONES_MAX (16). WildlifeWorld.active freezes an animal outside (no state change, no dice), NpcWorld.active a walker (and no birth outside), VehicleWorld.active a moored boat, and ThingsWorld.restocks keeps a morning's restock inside; every default is "everywhere", so an unbound game is unchanged. Tests: the merge (near players one cluster, far two, a player leaving splits a chain), contains, nearest, the radius; wildlife, npc, vehicles and things pass as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
40 lines
1.7 KiB
Text
40 lines
1.7 KiB
Text
# state.ludic - the discs by player slot and the clusters the last merge made
|
|
export const ZONES_MAX: int = 16 # player slots a world can hold (at least PLY_MAX)
|
|
export const ZONES_NO_FOG: float = 900.0 # the radius of a player who sees to the horizon
|
|
export const ZONES_PAST_FOG: float = 40.0 # simulated this far past what a player can see
|
|
export const ZONES_LEAST: float = 150.0 # and never less than this
|
|
|
|
export state ZonesState {
|
|
zn_on: words = words(ZONES_MAX)
|
|
zn_x: []float = floats(ZONES_MAX)
|
|
zn_z: []float = floats(ZONES_MAX)
|
|
zn_r: []float = floats(ZONES_MAX)
|
|
zn_cl: words = words(ZONES_MAX) # each disc's cluster, after zones_merge
|
|
zn_up: words = words(ZONES_MAX) # the merge's union-find
|
|
zn_ncl: int = 0
|
|
zn_cx: []float = floats(ZONES_MAX) # each cluster's bounding circle
|
|
zn_cz: []float = floats(ZONES_MAX)
|
|
zn_cr: []float = floats(ZONES_MAX)
|
|
zn_cn: words = words(ZONES_MAX) # how many discs it holds
|
|
}
|
|
|
|
# a player's radius from how far they see: fog_dist <= 0 is no fog
|
|
export function zones_radius(fog_dist: float) -> float {
|
|
if fog_dist <= 0.0 { return ZONES_NO_FOG }
|
|
return Math.max(fog_dist + ZONES_PAST_FOG, ZONES_LEAST)
|
|
}
|
|
|
|
export function zones_set(zones_st: mut ZonesState, pid: int, x: float, z: float, r: float) -> void {
|
|
if pid < 0 or pid >= ZONES_MAX { return }
|
|
zones_st.zn_on[pid] = 1
|
|
zones_st.zn_x[pid] = x
|
|
zones_st.zn_z[pid] = z
|
|
zones_st.zn_r[pid] = r
|
|
}
|
|
|
|
export function zones_clear(zones_st: mut ZonesState, pid: int) -> void { if pid >= 0 and pid < ZONES_MAX { zones_st.zn_on[pid] = 0 } }
|
|
|
|
export function zones_reset(zones_st: mut ZonesState) -> void {
|
|
for i in 0 .. ZONES_MAX { zones_st.zn_on[i] = 0 }
|
|
zones_st.zn_ncl = 0
|
|
}
|