import type { AptitudeKey } from "./types"; // 적성 레벨별 초당 작업량 (기획서 4.4) — BASE_RATE로 전체 속도 스케일 조정 export const APTITUDE_RATE = [0, 1.0, 2.2, 4.8, 10.0, 21.0, 45.0]; export const BASE_RATE = 0.2; // 품종별 스프라이트 폴더 (public/assets/cats/{폴더}/). 미등록 품종은 기본(오렌지 태비) 사용 export const CAT_SPRITE_DIR: Record = { korean_shorthair: "korean_shorthair", munchkin: "munchkin", norwegian_forest: "norwegian_forest", bengal: "bengal", russian_blue: "russian_blue", persian: "persian", sphynx: "sphynx", maine_coon: "maine_coon", }; export type CatFrame = "idle" | "walk1" | "walk2" | "work" | "cook" | "sleep"; export function catSprite(breed: string, frame: CatFrame): string { const dir = CAT_SPRITE_DIR[breed]; return dir ? `/assets/cats/${dir}/${frame}.png` : `/assets/cats/${frame}.png`; } // 건물 일러스트 (public/assets/buildings/) export const BUILDING_IMG: Record = { construction: "/assets/buildings/construction.png", hall: "/assets/buildings/hall.png", dock: "/assets/buildings/dock.png", lumberyard: "/assets/buildings/lumberyard.png", quarry: "/assets/buildings/quarry.png", kitchen: "/assets/buildings/kitchen.png", }; // 적성별 도구 일러스트 (public/assets/tools/) export const TOOL_IMG: Record = { fishing: "/assets/tools/fishing.png", logging: "/assets/tools/logging.png", mining: "/assets/tools/mining.png", foraging: "/assets/tools/foraging.png", cooking: "/assets/tools/cooking.png", crafting: "/assets/tools/crafting.png", grooming: "/assets/tools/grooming.png", }; export const APTITUDE_LABEL: Record = { fishing: "낚시", logging: "벌목", mining: "채굴", foraging: "채집", cooking: "요리", crafting: "제작", grooming: "손질", }; export interface BreedDef { key: string; name: string; emoji: string; rarity: number; // 별 개수 weight: number; // 추첨 가중치 bias: AptitudeKey[]; // 적성 편향 aptitudeCap: number; appetiteMod: number; } // 기획서 4.2 품종표 export const BREEDS: BreedDef[] = [ { key: "korean_shorthair", name: "코리안 숏헤어", emoji: "🐱", rarity: 1, weight: 35, bias: [], aptitudeCap: 5, appetiteMod: -1 }, { key: "munchkin", name: "먼치킨", emoji: "😺", rarity: 1, weight: 25, bias: ["foraging", "grooming"], aptitudeCap: 5, appetiteMod: 0 }, { key: "norwegian_forest", name: "노르웨이 숲", emoji: "🐈", rarity: 2, weight: 15, bias: ["logging", "mining"], aptitudeCap: 5, appetiteMod: 1 }, { key: "bengal", name: "뱅갈", emoji: "🐆", rarity: 2, weight: 10, bias: ["fishing", "foraging"], aptitudeCap: 5, appetiteMod: 0 }, { key: "russian_blue", name: "러시안 블루", emoji: "🐈‍⬛", rarity: 2, weight: 8, bias: ["crafting", "cooking"], aptitudeCap: 5, appetiteMod: 0 }, { key: "persian", name: "페르시안", emoji: "😸", rarity: 3, weight: 4, bias: ["cooking", "grooming"], aptitudeCap: 5, appetiteMod: 0 }, { key: "sphynx", name: "스핑크스", emoji: "🐯", rarity: 3, weight: 2, bias: ["crafting", "mining"], aptitudeCap: 5, appetiteMod: 0 }, { key: "maine_coon", name: "메인쿤", emoji: "🦁", rarity: 4, weight: 1, bias: ["logging", "mining"], aptitudeCap: 6, appetiteMod: 2 }, ]; export interface PassiveDef { key: string; name: string; kind: "positive" | "negative" | "tradeoff"; desc: string; speedMul: number; // 1단계에서는 작업 속도 효과만 적용 } // 기획서 5장 중 1단계에서 의미 있는 패시브 위주 export const PASSIVES: PassiveDef[] = [ { key: "diligent", name: "부지런함", kind: "positive", desc: "작업 속도 +25%", speedMul: 1.25 }, { key: "sturdy", name: "튼튼함", kind: "positive", desc: "체력 소모 -30%", speedMul: 1 }, { key: "small_eater", name: "소식가", kind: "positive", desc: "식량 소모 -30%", speedMul: 1 }, { key: "lucky", name: "복덩이", kind: "positive", desc: "확률적으로 냥코인 획득", speedMul: 1 }, { key: "lazy", name: "게으름뱅이", kind: "negative", desc: "작업 속도 -30%", speedMul: 0.7 }, { key: "big_eater", name: "대식가", kind: "negative", desc: "식량 소모 +50%", speedMul: 1 }, { key: "workaholic", name: "일중독", kind: "tradeoff", desc: "작업 속도 +60%, 행복도 감소 +40%", speedMul: 1.6 }, { key: "optimist", name: "낙천적", kind: "positive", desc: "행복도 감소 속도 -40%", speedMul: 1 }, { key: "picky", name: "까다로움", kind: "negative", desc: "행복도 감소 속도 +50%", speedMul: 1 }, { key: "popular", name: "인기쟁이", kind: "positive", desc: "같은 건물 동료의 행복도가 서서히 상승", speedMul: 1 }, ]; // ---------- 마을 보드 ---------- import type { BuildingType } from "./types"; export const BOARD_COLS = 15; export const BOARD_ROWS = 15; export const BOARD_VERSION = 2; // 보드 개편 시 증가 → 세이브 위치 리셋 export const HALL_TILE = { i: 6, j: 3 }; export const TREE_TILES: Array<{ i: number; j: number }> = [ { i: 0, j: 9 }, { i: 1, j: 11 }, { i: 3, j: 12 }, { i: 0, j: 13 }, { i: 1, j: 8 }, { i: 4, j: 13 }, { i: 11, j: 1 }, { i: 2, j: 0 }, ]; // 강은 동쪽 2열 export const isWaterTile = (i: number) => i >= BOARD_COLS - 2; // 건물 풋프린트 (타일 단위, pos는 좌상단 앵커) export const FOOTPRINTS: Record = { hall: { w: 3, h: 3 }, dock: { w: 2, h: 2 }, lumberyard: { w: 2, h: 2 }, quarry: { w: 2, h: 2 }, kitchen: { w: 2, h: 2 }, cat_house: { w: 2, h: 2 }, sun_deck: { w: 2, h: 2 }, }; export const footprintOf = (type: string) => FOOTPRINTS[type] ?? { w: 1, h: 1 }; // 배치 규칙: 부두는 물 위에만 export type PlacementRule = "land" | "onWater"; export const PLACEMENT_RULES: Partial> = { dock: "onWater", }; // 보드 v2 기본 위치 (마이그레이션 시 재배치) export const DEFAULT_BUILDING_POS: Record = { dock_1: { i: 13, j: 6 }, lumberyard_1: { i: 2, j: 9 }, kitchen_1: { i: 8, j: 8 }, quarry_1: { i: 1, j: 2 }, }; // ---------- 성장 ---------- export const EXP_PER_LEVEL = 90; // 레벨업 필요 경험치 = 레벨 × 90 export const APT_POINT_EVERY = 3; // 3레벨마다 적성 포인트 1 // ---------- 건설 가능한 건물 ---------- export interface BuildDef { id: string; // 건물 인스턴스 id (단일 건설) type: "dock" | "lumberyard" | "quarry" | "kitchen" | "cat_house" | "sun_deck"; kind?: "work" | "passive"; // passive: 고양이 배치 없음 (기본 work) name: string; emoji: string; aptitude: AptitudeKey; resource?: "fish" | "wood" | "stone"; maxSlots: number; cost: Partial>; reqHallLv: number; buildTime: number; // 건설 소요 시간 (초) desc: string; } export const BUILD_DEFS: BuildDef[] = [ { id: "dock_1", type: "dock", name: "부두", emoji: "⚓", aptitude: "fishing", resource: "fish", maxSlots: 3, cost: {}, reqHallLv: 1, buildTime: 15, desc: "낚시 적성 고양이가 생선을 잡습니다. 강물 위에 지어요. 첫 건물이라 무료!", }, { id: "lumberyard_1", type: "lumberyard", name: "벌목장", emoji: "🪓", aptitude: "logging", resource: "wood", maxSlots: 3, cost: { fish: 30 }, reqHallLv: 1, buildTime: 30, desc: "벌목 적성 고양이가 목재를 모읍니다. 목재는 모든 건설의 기본!", }, { id: "kitchen_1", type: "kitchen", name: "부엌", emoji: "🍳", aptitude: "cooking", maxSlots: 2, cost: { wood: 60 }, reqHallLv: 1, buildTime: 60, desc: "요리 적성 고양이가 생선으로 요리를 만들고, 배고픈 고양이들이 알아서 먹으러 옵니다.", }, { id: "quarry_1", type: "quarry", name: "채석장", emoji: "⛏️", aptitude: "mining", resource: "stone", maxSlots: 3, cost: { wood: 120 }, reqHallLv: 2, buildTime: 120, desc: "채굴 적성 고양이가 돌을 캡니다. 돌은 회관 증축과 중급 건물에 필요합니다.", }, { id: "cat_house_1", type: "cat_house", name: "고양이 집", emoji: "🛖", kind: "passive", aptitude: "grooming", maxSlots: 0, cost: { wood: 100, stone: 20 }, reqHallLv: 3, buildTime: 90, desc: "지친 고양이가 푹 쉬는 보금자리. 휴식 회복이 빨라지고(분당 +30) 행복도 하락을 막아줍니다.", }, { id: "sun_deck_1", type: "sun_deck", name: "햇볕 데크", emoji: "🌞", kind: "passive", aptitude: "grooming", maxSlots: 0, cost: { wood: 120, stone: 40 }, reqHallLv: 3, buildTime: 90, desc: "따끈한 햇살 아래 뒹굴뒹굴. 마을 전체의 행복도 회복이 1.5배 빨라집니다.", }, ]; // ---------- 꾸미기 (바닥 장식) ---------- export interface DecoDef { key: string; name: string; cost: Partial>; img: string; } export const DECO_DEFS: DecoDef[] = [ { key: "dirt", name: "흙마당", cost: { wood: 10 }, img: "/assets/deco/dirt.png" }, { key: "boulders", name: "바위 터", cost: { stone: 15 }, img: "/assets/deco/boulders.png" }, { key: "pavement", name: "돌바닥", cost: { stone: 25 }, img: "/assets/deco/pavement.png" }, { key: "deck", name: "나무 데크", cost: { wood: 30 }, img: "/assets/deco/deck.png" }, { key: "pebbles", name: "자갈길", cost: { stone: 12 }, img: "/assets/deco/pebbles.png" }, { key: "stump", name: "그루터기 쉼터", cost: { wood: 20 }, img: "/assets/deco/stump.png" }, { key: "flower_grass", name: "꽃잔디", cost: { wood: 15 }, img: "/assets/deco/flower_grass.png" }, { key: "plaza", name: "돌광장", cost: { stone: 30 }, img: "/assets/deco/plaza.png" }, { key: "boardwalk", name: "나무길", cost: { wood: 25 }, img: "/assets/deco/boardwalk.png" }, ]; // ---------- 요리 (부엌) ---------- export interface RecipeDef { key: string; name: string; emoji: string; input: Partial>; // 재료 (추후 획득처 확장) work: number; // 요리 1개당 필요 작업량 fullness: number; // 먹었을 때 포만도 회복량 reqHallLv: number; // 해금 조건: 회관 레벨 reqKitchenLv: number; // 해금 조건: 부엌 레벨 } export const RECIPES: RecipeDef[] = [ { key: "grilled_fish", name: "물고기 구이", emoji: "🍖", input: { fish: 2 }, work: 3, fullness: 40, reqHallLv: 1, reqKitchenLv: 1, }, { key: "smoked_fish", name: "훈제 생선", emoji: "🐟", input: { fish: 3 }, work: 6, fullness: 70, reqHallLv: 3, reqKitchenLv: 2, // 아직 잠김 — 회관·부엌 증축으로 해금 예정 }, ]; export const KITCHEN_MEAL_CAPS = [10, 15]; // 부엌 레벨별 선반 보관 수 export const KITCHEN_UPGRADE_COST = { wood: 150, stone: 60 }; // Lv1→2 export const mealCap = (kitchenLv: number) => KITCHEN_MEAL_CAPS[kitchenLv - 1] ?? KITCHEN_MEAL_CAPS[KITCHEN_MEAL_CAPS.length - 1]; export const EAT_THRESHOLD = 65; // 이 포만도 이하면 먹으러 감 export const FULLNESS_DECAY_PER_SEC = 0.03; // × 식욕 수치 // ---------- 체력·행복도 (Phase B) ---------- export const ENERGY_DRAIN_PER_SEC = 2 / 60; // 작업 중 체력 소모 (분당 2) export const REST_RECOVER_PER_SEC = 20 / 60; // 휴식 회복 (분당 20) export const HOUSE_RECOVER_PER_SEC = 30 / 60; // 고양이 집 휴식 회복 (분당 30) export const IDLE_RECOVER_PER_SEC = 10 / 60; // 배회 중 자연 회복 (분당 10) export const CAT_HOUSE_CAPACITY = 4; // 고양이 집 1채당 휴식 정원 export const STRIKE_THRESHOLD = 20; // 행복도가 이 밑이면 파업 export const STRIKE_RESUME = 40; // 이 이상 회복되면 복귀 // ---------- 마을 회관 증축 ---------- export interface HallLevelDef { capacity: number; cost: Partial>; reqCat?: { level: number; count: number }; reqBuildings?: Array<{ type: "quarry" | "kitchen"; level?: number; label: string }>; locked?: string; // 아직 구현 안 된 선행 요소 안내 } export const HALL_LEVELS: Record = { 2: { capacity: 5, cost: { wood: 100, fish: 80 }, reqCat: { level: 3, count: 1 } }, 3: { capacity: 8, cost: { wood: 250, stone: 150 }, reqCat: { level: 5, count: 2 }, reqBuildings: [ { type: "quarry", label: "채석장 건설" }, { type: "kitchen", level: 2, label: "부엌 Lv2" }, ], }, 4: { capacity: 12, cost: { stone: 400 }, reqCat: { level: 8, count: 3 }, locked: "목공소(목판)가 추가된 뒤 해금됩니다", }, }; export const CAT_NAMES = [ "치즈", "나비", "콩이", "보리", "두부", "마루", "모찌", "호두", "감자", "앙꼬", "밤이", "구름", "초코", "우유", "깨비", "솜이", "달이", "별이", "쿠키", "만두", "생강", "참깨", "누룽지", "조약돌", ];