"use strict"; // Layer: world/grass-placement // Grass placement clearance, crowding, and retry sampling helpers. (function (global) { const World = global.World; if (!World) return; Object.defineProperties(World.prototype, Object.getOwnPropertyDescriptors({ grassBlockedAt(x, y, self = null, opts = {}) { const ignoreSoft = Boolean(opts?.ignoreSoftPlacement); for (const it of this.nearbyItems(x, y, 96)) { if (it === self || it.dead) continue; if (ignoreSoft && global.TarinaiPhysicsSoftClear.isSoftPlacementType(it.type)) continue; for (const r of this.solidObstacleRects(it)) { if (this.pointInRect(x, y, r, 10)) return true; } if (it.type !== "zunchi") continue; const dx = (x - it.x) / Math.max(22, it.r * 1.35); const dy = (y - it.y) / Math.max(12, it.r * 0.82); if (dx * dx + dy * dy < 1) return true; } return false; }, grassCrowdedAt(x, y, minGap = 30, self = null) { for (const it of this.nearbyItems(x, y, Math.max(42, minGap + 16))) { if (it === self || it.dead || it.type !== "grass") continue; if (distXY(x, y, it.x, it.y) < minGap) return true; } return false; }, grassOnTarinaiAt(x, y, minGap = 24) { for (const t of this.nearbyTarinai(x, y, minGap + 36)) { if (t.dead || this.isTarinaiHiddenInNestBox(t)) continue; if (distXY(x, y, t.x, t.y) < Math.max(minGap, t.radius * 1.15)) return true; } return false; }, grassSpotOpen(x, y, { minGrassGap = 30, avoidTarinai = true, self = null } = {}) { if (x < 44 || y < 44 || x > this.w - 44 || y > this.h - 44) return false; if (this.grassBlockedAt(x, y, self)) return false; if (this.grassCrowdedAt(x, y, minGrassGap, self)) return false; if (avoidTarinai && this.grassOnTarinaiAt(x, y)) return false; return true; }, findGrassPlantingSpot(x, y, { allowOriginal = true, minRadius = 18, maxRadius = 160, attempts = 36, avoidTarinai = true } = {}) { const cx = clamp(x, 44, this.w - 44); const cy = clamp(y, 44, this.h - 44); if (allowOriginal && this.grassSpotOpen(cx, cy, { avoidTarinai })) return { x: cx, y: cy }; const blockedAtCenter = this.grassBlockedAt(cx, cy); const inner = blockedAtCenter ? Math.max(minRadius, 34) : minRadius; const outer = Math.max(maxRadius, inner + 42); const golden = Math.PI * (3 - Math.sqrt(5)); for (let i = 0; i < attempts; i++) { const t = attempts <= 1 ? 1 : i / (attempts - 1); const radius = lerp(inner, outer, Math.sqrt(t)); const angle = i * golden + stableUnit(`${cx},${cy}`, "grass-plant") * Math.PI * 2; const px = clamp(cx + Math.cos(angle) * radius, 44, this.w - 44); const py = clamp(cy + Math.sin(angle) * radius * 0.72, 44, this.h - 44); if (this.grassSpotOpen(px, py, { avoidTarinai })) return { x: px, y: py }; } return null; }, })); })(typeof window !== "undefined" ? window : globalThis);