Something went wrong. Try again.
Your trusty automation assistant in TLE Community misadventures!
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105import _ from 'lodash'
import { lacuna, call } from '@tlecommunity/super-core'
// `get_star_map` rejects a rectangle whose area exceeds 3001, so each window is a// 54x54 square (2916). Rings step outward by a full window width.const HALF = 27const WINDOW = HALF * 2
/** * Euclidean distance between two `{ x, y }` points. */export function distance(a, b) { let dx = a.x - b.x let dy = a.y - b.y
return Math.sqrt(dx * dx + dy * dy)}
// Window centres for the square Chebyshev ring `k` around the origin.function ringCentres(origin, k) { if (k === 0) { return [{ x: origin.x, y: origin.y }] }
let centres = []
for (let dx = -k; dx <= k; dx++) { for (let dy = -k; dy <= k; dy++) { if (Math.max(Math.abs(dx), Math.abs(dy)) === k) { centres.push({ x: origin.x + dx * WINDOW, y: origin.y + dy * WINDOW }) } } }
return centres}
/** * Scan the star map outward from `origin`, one 54-wide ring at a time (closest * ring first), calling `collect(star)` for every distinct star returned. `collect` * should return truthy when the star yielded a usable candidate; scanning stops * once `enough(candidateCount)` is truthy or `maxRing` rings have been scanned. * * @param {{x: number, y: number}} origin * @param {Object} opts * @param {Function} opts.collect * @param {?Function} opts.enough * @param {?number} opts.maxRing */export async function scanOutward(origin, { collect, enough, maxRing = 2 }) { let seen = new Set() let count = 0
for (let k = 0; k <= maxRing; k++) { for (const centre of ringCentres(origin, k)) { let res = await call(() => lacuna.map.getStarMap({ left: Math.round(centre.x - HALF), right: Math.round(centre.x + HALF), bottom: Math.round(centre.y - HALF), top: Math.round(centre.y + HALF), }) )
for (const star of res.stars || []) { if (seen.has(star.id)) { continue }
seen.add(star.id)
if (collect(star)) { count++ } } }
if (typeof enough === 'function' && enough(count)) { return } }}
/** * Clamp a desired ship-build quantity to the room actually available in a * planet's Shipyard queue and Space Port docks. * * @param {object} shipyard - a Shipyard building (needs `.id`) * @param {number} desired - how many ships the caller wants to build * @returns {Promise<number>} the number that will actually fit (>= 0) */export async function buildRoom(shipyard, desired) { if (desired <= 0) { return 0 }
let buildable = await call(() => lacuna.shipyard.getBuildable({ building_id: shipyard.id })) let dockSpace = parseInt(buildable.docks_available, 10) || 0 let queueSpace = (parseInt(buildable.build_queue_max, 10) || 0) - (parseInt(buildable.build_queue_used, 10) || 0)
return _.max([0, _.min([desired, dockSpace, queueSpace])])}