0.1.224: Wegzeiten des Plans auf grobem Raster (viel schneller), Ruckler beim Anmelden behoben

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016onJCSHLwhs9udhC9ZLzk9
This commit is contained in:
Lacustat
2026-11-01 14:40:16 +01:00
co-authored by Claude Sonnet 5.5
parent c045446264
commit ea945b98f8
2 changed files with 51 additions and 14 deletions
+50 -13
View File
@@ -758,6 +758,8 @@ end
local NAV_COST = { [0] = 0, 1.0 / 1.4, 1.0, 1.4, 1.8, 2.2 } -- Kostenfaktor je Klasse (a gesperrt, b Strasse, c normal, d huegelig, e steil, f Wasser)
local NAV_WALKED = 0.8
local NAV_MAX_EXPAND = 30000
local NAV_PLAN_MAX = 8000 -- Luftlinie, bis zu der der Plan (Wegzeiten) auf dem Raster rechnet
local NAV_PLAN_EXPAND = 1500 -- Suchschritte je Wegzeit-Berechnung (mehr gibt es nur fuer die Anzeige des Wegs)
local NAV_SNAP = 6 -- Zellen, so weit darf ein Ort von begehbarem Gelaende entfernt sein
local navs = {} -- [welt] = { w, h, cell, left, top, cls = { [idx] = klasse }, walked = { [idx] = true }, rev, built, cache = {} }
@@ -777,11 +779,38 @@ local function NavLoad(world)
end
end
end
n = { w = src.w, h = src.h, cell = src.cell, left = src.left, top = src.top, cls = cls, walked = {}, rev = -1, built = 0, cache = {} }
n = { w = src.w, h = src.h, cell = src.cell, left = src.left, top = src.top, cls = cls, walked = {}, rev = -1, built = 0, cache = {}, fail = {}, costs = NAV_COST }
navs[world] = n
return n
end
-- grobes Raster (4 x 4 Zellen = 167 Yards) fuer die Wegzeiten des Plans: viel schneller zu durchsuchen
local COARSE = 4
local function NavCoarse(n)
if n.coarse then return n.coarse end
local w, h, cls = n.w, n.h, n.cls
local cw, ch = math.ceil(w / COARSE), math.ceil(h / COARSE)
local c = {}
for cr = 0, ch - 1 do
for cc = 0, cw - 1 do
local sum, open, tot = 0, 0, 0
for r = cr * COARSE, math.min(h, cr * COARSE + COARSE) - 1 do
local base = r * w + 1
for k = cc * COARSE, math.min(w, cc * COARSE + COARSE) - 1 do
tot = tot + 1
local cl = cls[base + k]
if cl ~= 0 then open = open + 1 sum = sum + NAV_COST[cl] end
end
end
local v = 0
if open > 0 then v = (sum / open) * (1 + 0.5 * (1 - open / tot)) end
c[cr * cw + cc + 1] = v
end
end
n.coarse = { w = cw, h = ch, cell = n.cell * COARSE, left = n.left, top = n.top, cls = c, walked = {}, cache = {}, fail = {} }
return n.coarse
end
-- gelaufene Zellen auf das Raster legen (hoechstens alle GRAPH_STALE Sekunden neu, wenn es neue Daten gibt)
local function NavWalked(n, world)
local rev = Path.rev or 0
@@ -797,7 +826,7 @@ local function NavWalked(n, world)
if row >= 0 and row < n.h and col >= 0 and col < n.w then walked[row * n.w + col + 1] = true end
end
end
n.walked, n.rev, n.built, n.cache = walked, rev, now, {}
n.walked, n.rev, n.built, n.cache, n.fail = walked, rev, now, {}, {}
end
local function NavCell(n, x, y)
@@ -833,8 +862,8 @@ end
local NAV_DIRS = { { 1, 0, 1 }, { -1, 0, 1 }, { 0, 1, 1 }, { 0, -1, 1 }, { 1, 1, 1.4142 }, { 1, -1, 1.4142 }, { -1, 1, 1.4142 }, { -1, -1, 1.4142 } }
-- A* von Zelle a nach Zelle b. Rueckgabe: Liste von Zellindizes (a ... b) oder nil
local function NavSearch(n, a, b)
local w, h, cls, walked = n.w, n.h, n.cls, n.walked
local function NavSearch(n, a, b, maxExp)
local w, h, cls, walked, costs = n.w, n.h, n.cls, n.walked, n.costs
local bi = b - 1
local br, bc = math.floor(bi / w), bi % w
local g, prev, closed = { [a] = 0 }, {}, {}
@@ -869,7 +898,7 @@ local function NavSearch(n, a, b)
end
return top
end
local function H(r, c) return 0.7 * math.sqrt((r - br) ^ 2 + (c - bc) ^ 2) * 1.15 end
local function H(r, c) return math.sqrt((r - br) ^ 2 + (c - bc) ^ 2) end
local ai = a - 1
Push(a, H(math.floor(ai / w), ai % w))
local expanded = 0
@@ -884,7 +913,7 @@ local function NavSearch(n, a, b)
if not closed[k] then
closed[k] = true
expanded = expanded + 1
if expanded > NAV_MAX_EXPAND then return nil end
if expanded > (maxExp or NAV_MAX_EXPAND) then return nil end
local ki = k - 1
local r, c = math.floor(ki / w), ki % w
local gk = g[k]
@@ -895,8 +924,13 @@ local function NavSearch(n, a, b)
local nk = rr * w + cc + 1
local cl = cls[nk]
if cl and cl ~= 0 and not closed[nk] then
local f = walked[nk] and NAV_WALKED or NAV_COST[cl]
if walked[nk] and cl == 5 then f = NAV_COST[5] end
local f
if costs then
f = costs[cl]
if walked[nk] and cl ~= 5 then f = NAV_WALKED end
else
f = cl
end
local ng = gk + d[3] * f
if not g[nk] or ng < g[nk] then
g[nk] = ng
@@ -912,10 +946,11 @@ local function NavSearch(n, a, b)
end
-- Weg zwischen zwei Orten (Yards im Zellraum): Zellmitten als { x, y }, Laenge in Yards (ohne Anschluss an die Enden), Entfernung der Enden zum Netz
local function NavPath(world, ax, ay, bx, by)
local function NavPath(world, ax, ay, bx, by, maxExp, coarse)
local n = NavLoad(world)
if not n then return nil end
NavWalked(n, world)
if coarse then n = NavCoarse(n) end
local ar, ac = NavCell(n, ax, ay)
local br, bc = NavCell(n, bx, by)
local a, ar2, ac2 = NavSnap(n, ar, ac)
@@ -924,11 +959,12 @@ local function NavPath(world, ax, ay, bx, by)
local ck = a .. ":" .. b
local hit = n.cache[ck]
local chain
if hit ~= nil then
if hit ~= nil and (hit or (n.fail[ck] or 0) >= (maxExp or NAV_MAX_EXPAND)) then
chain = hit or nil
else
chain = a == b and { a } or NavSearch(n, a, b)
chain = a == b and { a } or NavSearch(n, a, b, maxExp)
n.cache[ck] = chain or false
n.fail[ck] = (not chain) and (maxExp or NAV_MAX_EXPAND) or nil
end
if not chain then return nil end
local pts = {}
@@ -1072,8 +1108,9 @@ function Path.Distance(world, ax, ay, bx, by)
if type(world) ~= "number" then return nil end
local straight = math.sqrt((ax - bx) ^ 2 + (ay - by) ^ 2)
if straight < 2 * BLOCK * CELL then return nil end
local pts, len, na, nb = NavPath(world, ax, ay, bx, by)
if pts then return na + len + nb end
if straight > NAV_PLAN_MAX then return nil end
local pts, len, na, nb = NavPath(world, ax, ay, bx, by, NAV_PLAN_EXPAND, true)
if pts then return na + len * 0.93 + nb end
local g = Graph(world)
if not g then return nil end
local sa, da = Snap(g, ax, ay)