too
This commit is contained in:
parent
4fdc567e08
commit
e00bfd8879
51 changed files with 1203 additions and 833 deletions
|
|
@ -101,6 +101,7 @@ function hasBetterFoodThanZunchiNearby(tarinai, world, maxDist = 180) {
|
|||
for (const it of world.nearbyItems?.(tarinai.x, tarinai.y, maxDist) || world.items || []) {
|
||||
if (!it || it.dead || it.type === "zunchi") continue;
|
||||
if (tarinai.shouldAvoidTarget?.(it)) continue;
|
||||
if (tarinaiTargetBlockedByObstacle(world, tarinai, it, "food")) continue;
|
||||
const type = effectiveFoodTypeForItem(it);
|
||||
if (!type) continue;
|
||||
if (["sweet", "food", "grass", "water", "zunda_juice", "ant_corpse"].includes(type) || (isServingFoodType(type))) {
|
||||
|
|
@ -130,25 +131,48 @@ function zunchiEatingBlocked(tarinai, item, world) {
|
|||
return false;
|
||||
}
|
||||
|
||||
function tarinaiTargetBlockedByObstacle(world, tarinai, item, role = "") {
|
||||
if (!world || !tarinai || !item) return false;
|
||||
// ずんだ餅だけは障害物越しでも食べに行く。
|
||||
if ((role === "food" || role === "medicine") && effectiveFoodTypeForItem(item) === "sweet") return false;
|
||||
return Boolean(world.targetBlockedByObstacle?.(tarinai, item, Math.max(18, (tarinai.radius || 20) * 0.65)));
|
||||
}
|
||||
|
||||
function foodRoleSearchTypes(role = "") {
|
||||
const set = new Set();
|
||||
if (role === "food") {
|
||||
for (const type of ["food", "sweet", "love_mochi", "fight_mochi", "sleep_drug", "laxative", "protein", "niteropu", "ammo", "mystery_drug", "mercury", "giant_drug", "dwarf_drug", "grass", "zunchi", "ant_corpse", "zunda_juice", "duplicator"]) set.add(type);
|
||||
if (typeof FOOD_SERVING_TYPES !== "undefined") for (const type of FOOD_SERVING_TYPES) set.add(type);
|
||||
} else if (role === "drink") {
|
||||
for (const type of ["water", "zunda_juice", "duplicator"]) set.add(type);
|
||||
} else if (role === "medicine") {
|
||||
for (const type of ["sweet", "water", "zunda_juice", "sleep_drug", "love_mochi", "fight_mochi", "laxative", "protein", "niteropu", "ammo", "mystery_drug", "mercury", "giant_drug", "dwarf_drug", "duplicator"]) set.add(type);
|
||||
if (typeof PARAM_EFFECT_ITEM_TYPES !== "undefined") for (const type of PARAM_EFFECT_ITEM_TYPES) set.add(type);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
function findNearestItemWithRole(world, tarinai, role, maxDist = 520) {
|
||||
let best = null, bestScore = Infinity;
|
||||
const hunger = Number(tarinai?.hunger || 0) || 0;
|
||||
const foodNeed = Number(tarinai?.needRaw?.food ?? tarinai?.needs?.food ?? 0) || 0;
|
||||
const foodEmergency = role === "food" && (hunger >= 96 || foodNeed >= 84);
|
||||
const searchDist = foodEmergency ? Math.max(maxDist, 1180) : maxDist;
|
||||
const primary = ((role === "food" || role === "drink" || role === "medicine") && world?.nearbyFood)
|
||||
const searchDist = Math.max(1, Number(maxDist) || 520);
|
||||
const foodLikeRole = role === "food" || role === "drink" || role === "medicine";
|
||||
const primary = (foodLikeRole && world?.nearbyFood)
|
||||
? world.nearbyFood(tarinai.x, tarinai.y, searchDist, true)
|
||||
: (world?.nearbyItems?.(tarinai.x, tarinai.y, searchDist, true) || world?.items || []);
|
||||
const candidates = Array.isArray(primary) ? primary.slice() : [];
|
||||
if (foodEmergency && world?.itemsOfType) {
|
||||
const emergencyTypes = new Set(["food", "sweet", "love_mochi", "fight_mochi", "sleep_drug", "laxative", "protein", "niteropu", "ammo", "mystery_drug", "mercury", "giant_drug", "dwarf_drug", "grass", "zunchi", "ant_corpse", "zunda_juice", "duplicator"]);
|
||||
if (typeof FOOD_SERVING_TYPES !== "undefined") for (const type of FOOD_SERVING_TYPES) emergencyTypes.add(type);
|
||||
for (const type of emergencyTypes) {
|
||||
for (const it of world.itemsOfType(type) || []) {
|
||||
if (it && !it.dead && !candidates.includes(it)) candidates.push(it);
|
||||
}
|
||||
const addCandidate = (it) => {
|
||||
if (it && !it.dead && !candidates.includes(it)) candidates.push(it);
|
||||
};
|
||||
|
||||
// 食料・水・薬は、通常時から空間インデックスだけに依存しない。
|
||||
// 生成直後/移動直後のアイテムが nearbyFood のキャッシュから漏れても、距離と roleMatches で最終判定する。
|
||||
if (foodLikeRole) {
|
||||
if (Array.isArray(world?.items)) for (const it of world.items) addCandidate(it);
|
||||
if (world?.itemsOfType) {
|
||||
for (const type of foodRoleSearchTypes(role)) for (const it of world.itemsOfType(type) || []) addCandidate(it);
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of candidates) {
|
||||
if (!roleMatches(item, role)) continue;
|
||||
if (role === "food" && typeof tarinai?.foodItemHasServingLeft === "function") {
|
||||
|
|
@ -160,11 +184,16 @@ function findNearestItemWithRole(world, tarinai, role, maxDist = 520) {
|
|||
if (tarinai?.shouldAvoidTarget?.(item)) continue;
|
||||
const d = item.type === "duplicator" ? foodInteractionDistance(tarinai, item) : dist(tarinai, item);
|
||||
if (d > searchDist) continue;
|
||||
const blocked = tarinaiTargetBlockedByObstacle(world, tarinai, item, role);
|
||||
let score = d;
|
||||
if (role === "food" || role === "medicine") {
|
||||
const priority = foodPriorityScore(tarinai, item, d);
|
||||
if (!Number.isFinite(priority)) continue;
|
||||
score = -priority;
|
||||
score = -priority + (blocked ? 260 : 0);
|
||||
} else if (blocked && !foodLikeRole) {
|
||||
continue;
|
||||
} else if (blocked) {
|
||||
score += 180;
|
||||
}
|
||||
if (score < bestScore) { best = item; bestScore = score; }
|
||||
}
|
||||
|
|
@ -295,6 +324,7 @@ function findOwnedStructure(world, tarinai, type = "", maxDist = Infinity) {
|
|||
for (const item of world?.items || []) {
|
||||
if (!item?.isStructure || item.dead || item.ownerId !== tarinai.id) continue;
|
||||
if (type && item.type !== type) continue;
|
||||
if (tarinaiTargetBlockedByObstacle(world, tarinai, item, "structure")) continue;
|
||||
const d = dist(tarinai, item);
|
||||
if (d < bestD) { best = item; bestD = d; }
|
||||
}
|
||||
|
|
@ -307,6 +337,7 @@ function findUnownedStructure(world, tarinai, type = "", maxDist = Infinity) {
|
|||
if (!item?.isStructure || item.dead || item.ownerId) continue;
|
||||
if (type && item.type !== type) continue;
|
||||
if (tarinai?.shouldAvoidTarget?.(item)) continue;
|
||||
if (tarinaiTargetBlockedByObstacle(world, tarinai, item, "structure")) continue;
|
||||
const d = dist(tarinai, item);
|
||||
if (d < bestD) { best = item; bestD = d; }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue