diff --git a/app/app-retro.vue b/app/app-retro.vue index 98db4a0..88c5c81 100644 --- a/app/app-retro.vue +++ b/app/app-retro.vue @@ -216,7 +216,7 @@ async function handlePlay(type = 'normal') { } async function handleClean() { - const result = await petSystem.clean() + const result = await petSystem.cleanPoop() log(result.success ? `CLEANED ${result.poopCount} POOP` : result.message) updateState() } @@ -228,7 +228,7 @@ async function handleHeal() { } async function handleSleep() { - const result = await petSystem.sleep() + const result = await petSystem.toggleSleep() log(result.success ? result.message : result.message) updateState() } diff --git a/app/app.vue b/app/app.vue index 702e501..9a5aff5 100644 --- a/app/app.vue +++ b/app/app.vue @@ -159,6 +159,258 @@ [SICK] 生病 [POOP] 便便 x{{ petState.poopCount }} + + +
+

═ 成就系統 ═

+
+
+ 已解鎖: {{ unlockedAchievementsCount }}/{{ totalAchievementsCount }} + 進度: {{ achievementProgress }}% +
+
+
+ 查看成就列表 ({{ unlockedAchievementsCount }}/{{ totalAchievementsCount }}) +
+
+
{{ achievement.icon || '🏆' }}
+
+
{{ achievement.name }}
+
{{ achievement.description }}
+
+
+
+
+ {{ getAchievementProgressText(achievement) }} +
+
+ 獎勵: + + {{ getBonusName(key) }}{{ formatBonusValue(value) }} + +
+
+
+
+
+
+ + +
+

═ 背包系統 ═

+ + +
+

裝備槽位

+
+
稀有度說明:
+
+ + {{ rarityData.name }} (掉落: {{ (rarityData.dropRate * 100).toFixed(0) }}%) + +
+
邊框顏色代表稀有度,數字為基礎掉落機率
+
+
+
+
{{ slotName.name }} {{ slotName.icon }}
+ + +
+
實際裝備
+
+ {{ getEquippedItemIcon(slotKey, 'equipment') }} + {{ getEquippedItemName(slotKey, 'equipment') }} + +
+
+
+ + +
+
外觀套件
+
+ {{ getEquippedItemIcon(slotKey, 'appearance') }} + {{ getEquippedItemName(slotKey, 'appearance') }} + +
+
+
+
+
+
+ + +
+ 查看背包 ({{ inventoryItemCount }} 種道具) +
+
+
+ {{ itemData.item.icon || '📦' }} + + {{ itemData.item.name }} + + x{{ itemData.count }} +
+
+
+ {{ getRarityName(itemData.item.rarity) }} + + (掉落: {{ (itemData.item.dropRate * 100).toFixed(0) }}%) + +
+
{{ itemTypeNames[itemData.item.type] || itemData.item.type }}
+
{{ itemData.item.description }}
+ + +
+
效果:
+
+ + {{ getStatName(key) }}{{ formatStatValue(value) }} + +
+
+ + {{ getStatName(key) }}{{ formatPercentValue(value) }} + +
+
+ +
+ 耐久度: {{ itemData.instance.durability }}/{{ itemData.item.maxDurability }} +
+
+
+ + + + +
+ + +
+
+ + + / {{ itemData.count }} +
+ +
+
+
+ 背包是空的 +
+
+
+
+ + + +
+
+ {{ tooltipContent.icon }} + + {{ tooltipContent.name }} + +
+
+ {{ tooltipContent.rarity }} (掉落: {{ tooltipContent.dropRate }}%) +
+
{{ tooltipContent.type }}
+
{{ tooltipContent.description }}
+ +
+
效果:
+
+ {{ effect.stat }}{{ effect.value }} +
+
+ +
+ 耐久度: {{ tooltipContent.durability.current }}/{{ tooltipContent.durability.max }} +
@@ -242,6 +494,13 @@

[PRAY] 神明系統

+ +
+ + +
@@ -290,6 +549,45 @@
+ +
+

成就系統

+ + + + + +
+ +
+

背包系統

+ +
+
按類型:
+
+ + + + + +
+
+
+
按類別:
+
+ + + + +
+
+
@@ -317,13 +615,36 @@ position: fixed; bottom: 60px; right: 10px; - background: rgba(0, 0, 0, 0.9); + background: rgba(0, 0, 0, 0.95); color: white; padding: 15px; border-radius: 10px; z-index: 9999; - width: 200px; - border: 1px solid #444; + width: 280px; + max-height: calc(100vh - 80px); + overflow-y: auto; + overflow-x: hidden; + border: 2px solid #ff00ff; + box-shadow: 0 0 20px rgba(255, 0, 255, 0.5); +} + +/* Debug 面板滾動條樣式 */ +.debug-panel::-webkit-scrollbar { + width: 8px; +} + +.debug-panel::-webkit-scrollbar-track { + background: rgba(255, 0, 255, 0.1); + border-radius: 4px; +} + +.debug-panel::-webkit-scrollbar-thumb { + background: rgba(255, 0, 255, 0.5); + border-radius: 4px; +} + +.debug-panel::-webkit-scrollbar-thumb:hover { + background: rgba(255, 0, 255, 0.8); } .debug-panel h3 { @@ -366,6 +687,8 @@ import { onMounted, onUnmounted, ref } from 'vue' import { PetSystem } from '../core/pet-system.js' import { EventSystem } from '../core/event-system.js' import { TempleSystem } from '../core/temple-system.js' +import { AchievementSystem } from '../core/achievement-system.js' +import { InventorySystem } from '../core/inventory-system.js' import { ApiService } from '../core/api-service.js' // 創建 API 服務 @@ -382,9 +705,11 @@ const isReady = ref(false) const isRunning = ref(false) const showNameInput = ref(false) const inputPetName = ref('') +const deityLotTypes = ref([]) +const selectedLotType = ref('') // 系統實例 -let petSystem, eventSystem, templeSystem +let petSystem, eventSystem, templeSystem, achievementSystem, inventorySystem // 更新狀態顯示 function updatePetState() { @@ -518,6 +843,13 @@ function getAllBonuses(state) { } } + // 6. 成就加成 + if (state.achievementBuffs) { + for (const [key, value] of Object.entries(state.achievementBuffs)) { + bonuses[key] = (bonuses[key] || 0) + value + } + } + return bonuses } @@ -986,6 +1318,13 @@ function listDeities() { console.log('='.repeat(50) + '\n') } +// 抽籤(簡化版,兼容舊 API) +async function drawFortune() { + // 使用 drawLot 作為實現 + const result = await handleDrawLot() + return result +} + // 應用 Buff async function applyBuffs() { await eventSystem.applyBuffs() @@ -1008,9 +1347,25 @@ async function confirmName() { // 初始化系統 async function init(petName = null) { - petSystem = new PetSystem(apiService) - eventSystem = new EventSystem(petSystem, apiService) - templeSystem = new TempleSystem(petSystem, apiService) + // 先創建成就系統 + achievementSystem = new AchievementSystem(null, null, null, apiService) + + // 先創建背包系統(因為其他系統可能需要它) + inventorySystem = new InventorySystem(null, null, apiService) + + // 創建其他系統,並傳入成就系統和背包系統 + petSystem = new PetSystem(apiService, achievementSystem, inventorySystem) + eventSystem = new EventSystem(petSystem, apiService, achievementSystem, inventorySystem) + templeSystem = new TempleSystem(petSystem, apiService, achievementSystem) + + // 更新成就系統的引用 + achievementSystem.petSystem = petSystem + achievementSystem.eventSystem = eventSystem + achievementSystem.templeSystem = templeSystem + + // 更新背包系統的引用 + inventorySystem.petSystem = petSystem + inventorySystem.eventSystem = eventSystem try { await petSystem.initialize('tinyTigerCat') @@ -1020,6 +1375,40 @@ async function init(petName = null) { } await eventSystem.initialize() await templeSystem.initialize() + await achievementSystem.initialize() // 這會重新應用已解鎖成就的加成 + await inventorySystem.initialize() // 初始化背包系統,會重新應用裝備效果 + + // 設置神明籤詩類型 + if (templeSystem) { + const currentDeity = templeSystem.getCurrentDeity() + deityLotTypes.value = currentDeity?.lotTypes || ['guanyin_100'] + selectedLotType.value = deityLotTypes.value[0] + } + + // 重新計算戰鬥數值(確保成就加成已應用) + petSystem.calculateCombatStats() + + // 初始化道具類型名稱和稀有度映射(提前載入) + try { + const { ITEM_TYPES, ITEM_RARITY } = await import('../data/items.js') + for (const [type, typeData] of Object.entries(ITEM_TYPES)) { + itemTypeNames.value[type] = typeData.name + } + for (const [rarity, rarityData] of Object.entries(ITEM_RARITY)) { + itemRarity.value[rarity] = rarityData + } + } catch (error) { + console.warn('[App] 載入道具類型失敗:', error) + } + + // 初始檢查成就 + await achievementSystem.checkAndUnlockAchievements() + + // 更新成就列表 + await updateAchievementList() + + // 更新背包列表 + await updateInventoryList() updatePetState() isReady.value = true @@ -1031,6 +1420,18 @@ async function init(petName = null) { // 自動啟動遊戲循環 start() + // 定期更新成就列表(每 5 秒) + setInterval(async () => { + if (achievementSystem) { + await achievementSystem.checkAndUnlockAchievements() + await updateAchievementList() + } + // 更新背包列表 + if (inventorySystem) { + await updateInventoryList() + } + }, 5000) + showStatus() } catch (error) { // 如果沒有名字,顯示輸入對話框 @@ -1275,6 +1676,28 @@ function testBonuses() { // 掛載到 window // Debug UI 狀態 const showDebug = ref(false) +const debugAchievementId = ref('') + +// 成就相關響應式數據 +const allAchievements = ref([]) +const unlockedAchievementsCount = ref(0) +const totalAchievementsCount = ref(0) +const achievementProgress = ref(0) + +// 背包相關響應式數據 +const inventoryItems = ref({}) +const inventoryItemCount = ref(0) +const equipmentSlots = ref({ + weapon: { name: '武器', icon: '⚔️' }, + armor: { name: '防具', icon: '🛡️' }, + hat: { name: '帽子', icon: '🎩' }, + accessory: { name: '飾品', icon: '💍' }, + talisman: { name: '護身符', icon: '🔮' }, + special: { name: '特殊', icon: '⭐' } +}) +const itemTypeNames = ref({}) +const itemRarity = ref({}) +const deleteCounts = ref({}) // 每個道具的刪除數量 // Debug 方法 const debugResetPrayer = async () => { @@ -1310,6 +1733,718 @@ const debugAddPoop = async () => { await window.debug.setStat('poopCount', 4) } +// 成就相關函數 +function isAchievementUnlocked(achievementId) { + if (!achievementSystem) return false + return achievementSystem.unlockedAchievements.includes(achievementId) +} + +function getAchievementProgressPercent(achievement) { + if (!achievementSystem) return 0 + const progress = achievementSystem.getAchievementProgress(achievement) + return progress.progress || 0 +} + +function getAchievementProgressText(achievement) { + if (!achievementSystem) return '0%' + const progress = achievementSystem.getAchievementProgress(achievement) + if (progress.current !== undefined && progress.target !== undefined) { + return `${progress.current}/${progress.target} (${Math.round(progress.progress)}%)` + } + return `${Math.round(progress.progress)}%` +} + +function formatBonusValue(value) { + if (typeof value === 'number' && value < 1 && value > 0) { + return ` +${(value * 100).toFixed(0)}%` + } + return value > 0 ? ` +${value}` : ` ${value}` +} + +async function updateAchievementList() { + if (!achievementSystem) return + + const { ACHIEVEMENTS } = await import('../data/achievements.js') + allAchievements.value = ACHIEVEMENTS + totalAchievementsCount.value = ACHIEVEMENTS.length + unlockedAchievementsCount.value = achievementSystem.unlockedAchievements.length + achievementProgress.value = totalAchievementsCount.value > 0 + ? Math.round((unlockedAchievementsCount.value / totalAchievementsCount.value) * 100) + : 0 +} + +// 更新背包列表(過濾掉已裝備的道具) +async function updateInventoryList() { + if (!inventorySystem) return + + const inventory = inventorySystem.getInventory() + const equipped = inventorySystem.getEquipped() + const items = {} + + const { ITEMS, ITEM_TYPES, ITEM_RARITY } = await import('../data/items.js') + + // 更新道具類型名稱映射(只在第一次或需要時更新) + if (Object.keys(itemTypeNames.value).length === 0) { + for (const [type, typeData] of Object.entries(ITEM_TYPES)) { + itemTypeNames.value[type] = typeData.name + } + } + + // 更新稀有度映射(只在第一次或需要時更新) + if (Object.keys(itemRarity.value).length === 0) { + for (const [rarity, rarityData] of Object.entries(ITEM_RARITY)) { + itemRarity.value[rarity] = rarityData + } + } + + // 收集所有已裝備的道具 ID(用於過濾) + const equippedItemIds = new Set() + for (const [slot, slotData] of Object.entries(equipped)) { + if (slotData && typeof slotData === 'object') { + if (slotData.equipment) { + const eqItemId = typeof slotData.equipment === 'string' ? slotData.equipment : slotData.equipment.itemId + if (eqItemId) { + // 計算已裝備的實例數量 + const instanceId = typeof slotData.equipment === 'object' ? slotData.equipment.instanceId : null + if (instanceId) { + equippedItemIds.add(`${eqItemId}_${instanceId}`) + } else { + equippedItemIds.add(eqItemId) + } + } + } + if (slotData.appearance) { + const apItemId = typeof slotData.appearance === 'string' ? slotData.appearance : slotData.appearance.itemId + if (apItemId) { + const instanceId = typeof slotData.appearance === 'object' ? slotData.appearance.instanceId : null + if (instanceId) { + equippedItemIds.add(`${apItemId}_${instanceId}`) + } else { + equippedItemIds.add(apItemId) + } + } + } + } + } + + // 從 inventorySystem 獲取道具數據(已從 API 載入) + const itemsData = inventorySystem.items || {} + + for (const [itemId, data] of Object.entries(inventory)) { + // 優先使用 API 載入的道具數據 + let item = itemsData[itemId] || ITEMS[itemId] + + if (item) { + // 如果道具沒有 dropRate,使用稀有度的默認掉落率 + if (item.dropRate === undefined && item.rarity) { + const rarityData = ITEM_RARITY[item.rarity] + if (rarityData) { + item = { ...item, dropRate: rarityData.dropRate } + } + } + + // 只有消耗品可以堆疊,裝備類每件分開顯示 + if (item.type === 'consumable') { + // 消耗品:顯示堆疊數量 + items[itemId] = { + item, + count: data.count, + totalCount: data.count, + equippedCount: 0, + isStackable: true + } + } else { + // 裝備類:每件分開顯示 + if (data.items && data.items.length > 0) { + // 為每個未裝備的實例創建一個條目 + for (const instance of data.items) { + const instanceKey = `${itemId}_${instance.id}` + if (!equippedItemIds.has(instanceKey)) { + // 使用實例 ID 作為 key,這樣每件裝備都會單獨顯示 + const instanceItemId = `${itemId}_${instance.id}` + items[instanceItemId] = { + item, + count: 1, + totalCount: 1, + equippedCount: 0, + isStackable: false, + instanceId: instance.id, + instance: instance, // 保存實例數據用於顯示耐久度等 + originalItemId: itemId // 保存原始 itemId 用於操作 + } + } + } + } + } + } + } + + inventoryItems.value = items + inventoryItemCount.value = Object.keys(items).length + + // 初始化刪除數量(如果還沒有設置) + for (const itemId of Object.keys(items)) { + if (deleteCounts.value[itemId] === undefined) { + deleteCounts.value[itemId] = 1 + } + } + + // 清理已不存在的道具的刪除數量 + for (const itemId of Object.keys(deleteCounts.value)) { + if (!items[itemId]) { + delete deleteCounts.value[itemId] + } + } +} + +// 獲取道具類型名稱(備用函數) +function getItemTypeName(type) { + return itemTypeNames.value[type] || type +} + +// 獲取稀有度名稱 +function getRarityName(rarity) { + return itemRarity.value[rarity]?.name || rarity || '普通' +} + +// 獲取稀有度顏色 +function getRarityColor(rarity) { + return itemRarity.value[rarity]?.color || '#9d9d9d' +} + +// 獲取稀有度 CSS 類 +function getRarityClass(rarity) { + return `rarity-${rarity || 'common'}` +} + +// 獲取道具掉落率(如果道具沒有指定,使用稀有度的默認值) +function getItemDropRate(item) { + if (item.dropRate !== undefined) { + return (item.dropRate * 100).toFixed(0) + } + // 如果沒有指定掉落率,使用稀有度的默認值 + if (item.rarity && itemRarity.value[item.rarity]) { + return (itemRarity.value[item.rarity].dropRate * 100).toFixed(0) + } + return '0' +} + +// Tooltip 相關 +const itemTooltip = ref(false) +const tooltipContent = ref(null) +const tooltipPosition = ref({ x: 0, y: 0 }) + +function showItemTooltip(event, item, itemId, instance = null) { + if (!item) return + + const tooltip = { + name: item.name, + icon: item.icon || '📦', + type: itemTypeNames.value[item.type] || item.type, + rarity: getRarityName(item.rarity), + rarityColor: getRarityColor(item.rarity), + description: item.description, + effects: [], + durability: null, + dropRate: getItemDropRate(item) + } + + // 收集效果 + if (item.effects) { + if (item.effects.flat) { + for (const [key, value] of Object.entries(item.effects.flat)) { + tooltip.effects.push({ + type: 'flat', + stat: getStatName(key), + value: formatStatValue(value) + }) + } + } + if (item.effects.percent) { + for (const [key, value] of Object.entries(item.effects.percent)) { + tooltip.effects.push({ + type: 'percent', + stat: getStatName(key), + value: formatPercentValue(value) + }) + } + } + } + + // 耐久度(如果有實例數據) + if (instance && instance.durability !== undefined && instance.durability !== Infinity) { + tooltip.durability = { + current: instance.durability, + max: instance.maxDurability || item.maxDurability + } + } else if (item.durability !== Infinity && item.maxDurability) { + tooltip.durability = { + current: item.durability, + max: item.maxDurability + } + } + + tooltipContent.value = tooltip + tooltipPosition.value = { + x: event.clientX + 15, + y: event.clientY + 15 + } + itemTooltip.value = true +} + +function hideItemTooltip() { + itemTooltip.value = false + tooltipContent.value = null +} + +// 獲取屬性名稱(用於顯示效果) +function getStatName(key) { + const names = { + // 基礎屬性 + str: '力量', + int: '智力', + dex: '敏捷', + luck: '運勢', + health: '最大健康', + attack: '攻擊', + defense: '防禦', + speed: '速度', + hp: 'HP', + // 狀態 + hunger: '飢餓', + happiness: '快樂', + // 成長 + strGain: '力量成長', + intGain: '智力成長', + dexGain: '敏捷成長', + // 恢復 + happinessRecovery: '快樂恢復', + healthRecovery: '健康恢復', + // 其他 + dropRate: '掉落率', + sicknessReduction: '生病抗性' + } + return names[key] || key +} + +// 格式化數值(固定值) +function formatStatValue(value) { + if (value > 0) { + return ` +${value}` + } else if (value < 0) { + return ` ${value}` + } + return '' +} + +// 格式化百分比值 +function formatPercentValue(value) { + if (typeof value === 'number') { + const percent = (value * 100).toFixed(0) + if (value > 0) { + return ` +${percent}%` + } else if (value < 0) { + return ` ${percent}%` + } + } + return '' +} + +// 獲取裝備的道具 ID(支持新雙槽位結構) +function getEquippedItemId(slot, type = 'equipment') { + if (!inventorySystem) return null + const equipped = inventorySystem.getEquipped() + const slotData = equipped[slot] + if (!slotData) return null + + // 兼容舊格式 + if (typeof slotData === 'string' || (typeof slotData === 'object' && slotData.itemId)) { + return typeof slotData === 'string' ? slotData : slotData.itemId + } + + // 新格式:雙槽位 + const equippedData = slotData[type] + if (!equippedData) return null + return typeof equippedData === 'string' ? equippedData : equippedData.itemId +} + +// 獲取裝備的道具圖標 +function getEquippedItemIcon(slot, type = 'equipment') { + if (!inventorySystem) return '📦' + const itemId = getEquippedItemId(slot, type) + if (!itemId) return '📦' + + // 從 inventoryItems 中查找 + const itemData = inventoryItems.value[itemId] + return itemData?.item?.icon || '📦' +} + +// 獲取裝備的道具名稱 +function getEquippedItemName(slot, type = 'equipment') { + if (!inventorySystem) return '' + const itemId = getEquippedItemId(slot, type) + if (!itemId) return '' + + // 從 inventoryItems 中查找 + const itemData = inventoryItems.value[itemId] + return itemData?.item?.name || '' +} + +// 檢查槽位是否有裝備(支持新結構) +function hasEquipped(slot, type = null) { + if (!inventorySystem) return false + const equipped = inventorySystem.getEquipped() + const slotData = equipped[slot] + if (!slotData) return false + + // 兼容舊格式 + if (typeof slotData === 'string' || (typeof slotData === 'object' && slotData.itemId)) { + return type === null || type === 'equipment' + } + + // 新格式:雙槽位 + if (type === null) { + return !!(slotData.equipment || slotData.appearance) + } + return !!slotData[type] +} + +// 檢查是否可以裝備 +function canEquip(item) { + return item.type === 'equipment' || + item.type === 'appearance' || + item.type === 'talisman' || + item.type === 'special' +} + +// 獲取道具耐久度 +function getItemDurability(itemId, instanceId = null) { + if (!inventorySystem) return 0 + const inventory = inventorySystem.getInventory() + + // 如果是實例 ID(包含下劃線和實例 ID) + if (itemId.includes('_') && itemId.split('_').length > 2) { + const parts = itemId.split('_') + const originalItemId = parts[0] + const instanceId = parts.slice(1).join('_') + const itemData = inventory[originalItemId] + if (itemData && itemData.items) { + const instance = itemData.items.find(i => i.id === instanceId) + return instance ? (instance.durability || 0) : 0 + } + } else { + // 舊格式或消耗品 + const itemData = inventory[itemId] + if (!itemData) return 0 + + // 如果有實例數據 + if (itemData.items && itemData.items.length > 0) { + if (instanceId) { + const instance = itemData.items.find(i => i.id === instanceId) + return instance ? (instance.durability || 0) : 0 + } + return itemData.items[0].durability || 0 + } + } + + return 0 +} + +// 處理使用道具 +async function handleUseItem(itemId) { + if (!inventorySystem) return + + try { + const result = await inventorySystem.useItem(itemId, 1) + if (result.success) { + await updateInventoryList() + updatePetState() + console.log(`[UI] 使用了道具: ${itemId}`) + } else { + console.error(`[UI] 使用道具失敗: ${result.message}`) + } + } catch (error) { + console.error('[UI] 使用道具錯誤:', error) + } +} + +// 處理裝備道具 +// equipType: 'equipment' | 'appearance' | 'auto' +async function handleEquip(itemId, slot, equipType = 'auto') { + if (!inventorySystem) return + + try { + // 如果是實例 ID(裝備類分開顯示),需要提取原始 itemId 和 instanceId + let actualItemId = itemId + let instanceId = null + + const itemData = inventoryItems.value[itemId] + if (itemData) { + if (itemData.originalItemId) { + // 這是分開顯示的裝備實例 + actualItemId = itemData.originalItemId + instanceId = itemData.instanceId + } else if (itemId.includes('_') && itemId.split('_').length > 2) { + // 實例 ID 格式:itemId_instanceId + const parts = itemId.split('_') + actualItemId = parts[0] + instanceId = parts.slice(1).join('_') + } + } + + const result = await inventorySystem.equipItem(actualItemId, slot, equipType, instanceId) + if (result.success) { + await updateInventoryList() + updatePetState() + const typeName = result.type === 'appearance' ? '外觀' : '實際' + console.log(`[UI] 裝備了道具: ${actualItemId} (${typeName})`) + } else { + console.error(`[UI] 裝備失敗: ${result.message}`) + } + } catch (error) { + console.error('[UI] 裝備錯誤:', error) + } +} + +// 處理卸下裝備 +// type: 'equipment' | 'appearance' | null (卸下全部) +async function handleUnequip(slot, type = null) { + if (!inventorySystem) return + + try { + const result = await inventorySystem.unequipItem(slot, type) + if (result.success) { + await updateInventoryList() + updatePetState() + const typeName = type === 'appearance' ? '外觀' : (type === 'equipment' ? '實際' : '全部') + console.log(`[UI] 卸下了裝備: ${slot} (${typeName})`) + } else { + console.error(`[UI] 卸下失敗: ${result.message}`) + } + } catch (error) { + console.error('[UI] 卸下錯誤:', error) + } +} + +// 處理修復裝備 +async function handleRepair(itemId) { + if (!inventorySystem) return + + try { + const result = await inventorySystem.repairItem(itemId) + if (result.success) { + await updateInventoryList() + updatePetState() + console.log(`[UI] 修復了裝備: ${itemId}`) + } else { + console.error(`[UI] 修復失敗: ${result.message}`) + } + } catch (error) { + console.error('[UI] 修復錯誤:', error) + } +} + +// Debug 成就功能 +async function debugUnlockAchievement() { + if (!achievementSystem || !debugAchievementId.value) { + console.log('[ERR] 請輸入成就 ID') + return + } + + const achievement = allAchievements.value.find(a => a.id === debugAchievementId.value) + if (!achievement) { + console.log(`[ERR] 找不到成就: ${debugAchievementId.value}`) + return + } + + await achievementSystem.unlockAchievement(achievement) + await updateAchievementList() + updatePetState() + console.log(`[OK] 成就已解鎖: ${achievement.name}`) +} + +async function debugListAchievements() { + if (!achievementSystem) { + console.log('[ERR] 成就系統未初始化') + return + } + + const unlocked = achievementSystem.getUnlockedAchievements() + const locked = achievementSystem.getLockedAchievements() + + console.log('\n' + '='.repeat(60)) + console.log('🏆 成就列表') + console.log('='.repeat(60)) + console.log(`\n✅ 已解鎖 (${unlocked.length}/${allAchievements.value.length}):`) + unlocked.forEach(a => { + console.log(` ${a.icon} ${a.name} - ${a.description}`) + }) + + console.log(`\n🔒 未解鎖 (${locked.length}):`) + locked.forEach(a => { + const progress = achievementSystem.getAchievementProgress(a) + if (progress.current !== undefined && progress.target !== undefined) { + console.log(` ${a.icon} ${a.name} - ${a.description}`) + console.log(` 進度: ${progress.current}/${progress.target} (${Math.round(progress.progress)}%)`) + } else { + console.log(` ${a.icon} ${a.name} - ${a.description}`) + } + }) + console.log('='.repeat(60) + '\n') +} + +async function debugUnlockAllAchievements() { + if (!achievementSystem) { + console.log('[ERR] 成就系統未初始化') + return + } + + const { ACHIEVEMENTS } = await import('../data/achievements.js') + let count = 0 + + for (const achievement of ACHIEVEMENTS) { + if (!achievementSystem.unlockedAchievements.includes(achievement.id)) { + await achievementSystem.unlockAchievement(achievement) + count++ + } + } + + await updateAchievementList() + updatePetState() + console.log(`[OK] 已解鎖 ${count} 個成就`) +} + +async function debugResetAchievements() { + if (!achievementSystem) { + console.log('[ERR] 成就系統未初始化') + return + } + + if (!confirm('確定要重置所有成就嗎?此操作無法復原!')) { + return + } + + achievementSystem.unlockedAchievements = [] + achievementSystem.achievementStats = { + actionCounts: { + feed: 0, + play: 0, + clean: 0, + heal: 0, + sleep: 0, + pray: 0, + drawFortune: 0 + }, + eventCount: 0, + eventTypeCounts: { + good: 0, + bad: 0, + weird: 0, + rare: 0 + }, + recoveredFromDying: false, + perfectStateReached: false + } + + // 清除成就加成 + await petSystem.updateState({ achievementBuffs: {} }) + petSystem.calculateCombatStats() + + // 同步到 API + try { + await achievementSystem.api.saveAchievements({ + unlocked: [], + stats: achievementSystem.achievementStats + }) + } catch (error) { + localStorage.setItem('achievements', JSON.stringify({ + unlocked: [], + stats: achievementSystem.achievementStats + })) + } + + await updateAchievementList() + updatePetState() + console.log('[OK] 成就已重置') +} + +// Debug 背包功能 +async function debugAddRandomItem() { + if (!inventorySystem) { + console.log('[ERR] 背包系統未初始化') + return + } + + const { ITEMS } = await import('../data/items.js') + const itemIds = Object.keys(ITEMS) + const randomItemId = itemIds[Math.floor(Math.random() * itemIds.length)] + + const result = await inventorySystem.addItem(randomItemId, 1) + if (result.success) { + await updateInventoryList() + updatePetState() + console.log(`[OK] 隨機產生道具: ${result.item.name}`) + } else { + console.error(`[ERR] 產生道具失敗: ${result.message}`) + } +} + +async function debugAddItemByType(type) { + if (!inventorySystem) { + console.log('[ERR] 背包系統未初始化') + return + } + + const { ITEMS } = await import('../data/items.js') + const itemsOfType = Object.entries(ITEMS) + .filter(([id, item]) => item.type === type) + .map(([id]) => id) + + if (itemsOfType.length === 0) { + console.log(`[ERR] 沒有找到類型為 ${type} 的道具`) + return + } + + const randomItemId = itemsOfType[Math.floor(Math.random() * itemsOfType.length)] + const result = await inventorySystem.addItem(randomItemId, 1) + + if (result.success) { + await updateInventoryList() + updatePetState() + console.log(`[OK] 產生 ${type} 道具: ${result.item.name}`) + } else { + console.error(`[ERR] 產生道具失敗: ${result.message}`) + } +} + +async function debugAddItemByCategory(category) { + if (!inventorySystem) { + console.log('[ERR] 背包系統未初始化') + return + } + + const { ITEMS } = await import('../data/items.js') + const itemsOfCategory = Object.entries(ITEMS) + .filter(([id, item]) => item.category === category) + .map(([id]) => id) + + if (itemsOfCategory.length === 0) { + console.log(`[ERR] 沒有找到類別為 ${category} 的道具`) + return + } + + const randomItemId = itemsOfCategory[Math.floor(Math.random() * itemsOfCategory.length)] + const result = await inventorySystem.addItem(randomItemId, 1) + + if (result.success) { + await updateInventoryList() + updatePetState() + console.log(`[OK] 產生 ${category} 道具: ${result.item.name}`) + } else { + console.error(`[ERR] 產生道具失敗: ${result.message}`) + } +} + // 處理鍵盤輸入(可選) const handleKeydown = (e) => { // Ctrl + Shift + D 開關 Debug 面板 @@ -1337,6 +2472,7 @@ onMounted(async () => { window.petSystem = petSystem window.eventSystem = eventSystem window.templeSystem = templeSystem + window.inventorySystem = inventorySystem window.showStatus = showStatus window.start = start window.stop = stop @@ -2077,4 +3213,703 @@ button.active { button.active:hover { background: #6ee2c4 !important; } + +/* 成就系統樣式 */ +.achievement-summary { + margin-bottom: 10px; +} + +.achievement-stats { + display: flex; + justify-content: space-around; + padding: 10px; + background: #001100; + border: 1px solid #00ff00; + border-radius: 4px; + font-size: 12px; +} + +.achievement-stats span { + color: #00ff00; + font-weight: bold; +} + +.achievement-list { + margin-top: 10px; + border: 1px solid #3c3c3c; + border-radius: 4px; + padding: 10px; +} + +.achievement-list summary { + cursor: pointer; + user-select: none; + color: #4ec9b0; + font-weight: bold; + padding: 5px; + list-style-position: inside; +} + +.achievement-list summary:hover { + background: rgba(78, 201, 176, 0.1); + border-radius: 4px; +} + +.achievement-list[open] summary { + margin-bottom: 10px; + border-bottom: 1px solid #3c3c3c; + padding-bottom: 10px; +} + +.achievement-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 10px; + max-height: 400px; + overflow-y: auto; + padding: 10px 0; +} + +.achievement-item { + display: flex; + gap: 10px; + padding: 10px; + background: #001100; + border: 2px solid #003300; + border-radius: 4px; + transition: all 0.2s; +} + +.achievement-item.unlocked { + border-color: #00ff00; + background: #002200; + box-shadow: 0 0 10px rgba(0, 255, 0, 0.3); +} + +.achievement-item.locked { + opacity: 0.6; + border-color: #333; +} + +.achievement-icon { + font-size: 24px; + min-width: 30px; + text-align: center; +} + +.achievement-info { + flex: 1; +} + +.achievement-name { + color: #00ffff; + font-weight: bold; + font-size: 14px; + margin-bottom: 4px; +} + +.achievement-item.locked .achievement-name { + color: #888; +} + +.achievement-desc { + color: #aaa; + font-size: 11px; + margin-bottom: 6px; +} + +.achievement-progress { + margin-top: 6px; +} + +.progress-bar { + width: 100%; + height: 6px; + background: #000; + border: 1px solid #333; + border-radius: 3px; + overflow: hidden; + margin-bottom: 4px; +} + +.progress-fill { + height: 100%; + background: #00ff00; + transition: width 0.3s; +} + +.progress-text { + color: #888; + font-size: 10px; +} + +.achievement-reward { + margin-top: 6px; + padding-top: 6px; + border-top: 1px solid #333; + font-size: 10px; +} + +.reward-label { + color: #00aa00; + margin-right: 4px; +} + +.reward-item { + color: #00ff00; + margin-right: 8px; +} + +/* 背包系統樣式 */ +.equipment-slots { + margin-bottom: 15px; +} + +.equipment-slots h4 { + color: #4ec9b0; + margin-bottom: 10px; + font-size: 14px; +} + +/* 稀有度圖例 */ +.rarity-legend { + background: #001100; + border: 2px solid #3c3c3c; + border-radius: 4px; + padding: 10px; + margin-bottom: 15px; +} + +.legend-title { + color: #4ec9b0; + font-size: 12px; + font-weight: bold; + margin-bottom: 8px; +} + +.legend-items { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 6px; +} + +.legend-item { + padding: 4px 8px; + border-radius: 3px; + font-size: 10px; + border: 2px solid; +} + +.legend-item.rarity-common { + border-color: #9d9d9d; + color: #9d9d9d; +} + +.legend-item.rarity-uncommon { + border-color: #1eff00; + color: #1eff00; + box-shadow: 0 0 5px rgba(30, 255, 0, 0.3); +} + +.legend-item.rarity-rare { + border-color: #0070dd; + color: #0070dd; + box-shadow: 0 0 8px rgba(0, 112, 221, 0.4); +} + +.legend-item.rarity-epic { + border-color: #a335ee; + color: #a335ee; + box-shadow: 0 0 10px rgba(163, 53, 238, 0.5); +} + +.legend-item.rarity-legendary { + border-color: #ff8000; + color: #ff8000; + box-shadow: 0 0 15px rgba(255, 128, 0, 0.6); +} + +.legend-note { + color: #888; + font-size: 9px; + font-style: italic; +} + +.slots-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 12px; + margin-bottom: 10px; +} + +.equipment-slot-container { + border: 2px solid #3c3c3c; + border-radius: 4px; + padding: 8px; + background: #000511; + display: flex; + flex-direction: column; + gap: 6px; +} + +.slot-header { + font-size: 11px; + color: #4ec9b0; + font-weight: bold; + text-align: center; + padding-bottom: 4px; + border-bottom: 1px solid #3c3c3c; +} + +.equipment-slot { + border: 2px solid #3c3c3c; + border-radius: 4px; + padding: 6px; + background: #001100; + min-height: 50px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + position: relative; +} + +.equipment-slot-main.equipped { + border-color: #00ff00; + background: #002200; + box-shadow: 0 0 5px rgba(0, 255, 0, 0.3); +} + +.equipment-slot-appearance.equipped { + border-color: #00ffff; + background: #002222; + box-shadow: 0 0 5px rgba(0, 255, 255, 0.3); +} + +.slot-label { + font-size: 10px; + color: #888; + margin-bottom: 4px; +} + +.slot-item { + display: flex; + flex-direction: column; + align-items: center; + gap: 4px; + position: relative; + width: 100%; +} + +.slot-item .item-icon { + font-size: 20px; +} + +.slot-item .item-name { + font-size: 10px; + color: #00ff00; + text-align: center; +} + +.unequip-btn, .delete-btn { + width: 20px; + height: 20px; + padding: 0; + background: #ff0000; + border: 1px solid #ff0000; + border-radius: 3px; + color: white; + font-size: 10px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s; +} + +.unequip-btn:hover, .delete-btn:hover { + background: #cc0000; + transform: scale(1.1); +} + +.delete-btn { + background: #aa0000; + border-color: #aa0000; +} + +.delete-btn:hover { + background: #880000; +} + +.slot-empty { + color: #666; + font-size: 11px; +} + +.inventory-list { + margin-top: 10px; + border: 1px solid #3c3c3c; + border-radius: 4px; + padding: 10px; +} + +.inventory-list summary { + cursor: pointer; + user-select: none; + color: #4ec9b0; + font-weight: bold; + padding: 5px; + list-style-position: inside; +} + +.inventory-list summary:hover { + background: rgba(78, 201, 176, 0.1); + border-radius: 4px; +} + +.inventory-list[open] summary { + margin-bottom: 10px; + border-bottom: 1px solid #3c3c3c; + padding-bottom: 10px; +} + +.inventory-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + gap: 10px; + max-height: 400px; + overflow-y: auto; + padding: 10px 0; +} + +.inventory-item { + border: 2px solid #3c3c3c; + border-radius: 4px; + padding: 10px; + background: #001100; + display: flex; + flex-direction: column; + gap: 8px; + transition: all 0.2s; +} + +/* 稀有度邊框顏色 */ +.inventory-item.rarity-common { + border-color: #9d9d9d; +} + +.inventory-item.rarity-uncommon { + border-color: #1eff00; + box-shadow: 0 0 5px rgba(30, 255, 0, 0.3); +} + +.inventory-item.rarity-rare { + border-color: #0070dd; + box-shadow: 0 0 8px rgba(0, 112, 221, 0.4); +} + +.inventory-item.rarity-epic { + border-color: #a335ee; + box-shadow: 0 0 10px rgba(163, 53, 238, 0.5); +} + +.inventory-item.rarity-legendary { + border-color: #ff8000; + box-shadow: 0 0 15px rgba(255, 128, 0, 0.6); + background: linear-gradient(135deg, #001100 0%, #331100 100%); +} + +.inventory-item .item-header { + display: flex; + align-items: center; + gap: 8px; +} + +.inventory-item .item-icon { + font-size: 20px; +} + +.inventory-item .item-name { + flex: 1; + color: #00ffff; + font-weight: bold; + font-size: 13px; +} + +.inventory-item .item-count { + color: #888; + font-size: 11px; +} + +.inventory-item .item-info { + font-size: 11px; + color: #aaa; +} + +.inventory-item .item-type { + color: #4ec9b0; + margin-bottom: 4px; +} + +.inventory-item .item-rarity { + font-weight: bold; + margin-bottom: 4px; +} + +.inventory-item .drop-rate { + color: #888; + font-size: 10px; + font-weight: normal; + margin-left: 4px; +} + +.inventory-item .item-description { + margin-bottom: 4px; +} + +.inventory-item .item-durability { + color: #ffaa00; +} + +.inventory-item .item-actions { + display: flex; + gap: 5px; + flex-wrap: wrap; +} + +.action-btn { + padding: 4px 8px; + font-size: 10px; + background: #333; + border: 1px solid #555; + color: #fff; + border-radius: 3px; + cursor: pointer; + transition: all 0.2s; +} + +.action-btn:hover:not(:disabled) { + background: #555; + border-color: #777; +} + +.action-btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.use-btn:hover:not(:disabled) { + background: #00aa00; + border-color: #00ff00; +} + +.equip-btn:hover:not(:disabled) { + background: #0066aa; + border-color: #0099ff; +} + +.appearance-btn { + background: #333366 !important; + border-color: #6666aa !important; +} + +.appearance-btn:hover:not(:disabled) { + background: #444477 !important; + border-color: #7777bb !important; +} + +.repair-btn:hover:not(:disabled) { + background: #aa6600; + border-color: #ff9900; +} + +/* 刪除區域樣式 */ +.item-delete-section { + margin-top: 8px; + padding-top: 8px; + border-top: 1px solid #333; + display: flex; + flex-direction: column; + gap: 6px; +} + +.delete-controls { + display: flex; + align-items: center; + gap: 6px; +} + +.delete-label { + color: #888; + font-size: 10px; + white-space: nowrap; +} + +.delete-input { + width: 50px; + padding: 4px; + background: #1e1e1e; + border: 1px solid #3c3c3c; + border-radius: 3px; + color: #fff; + font-size: 11px; + text-align: center; +} + +.delete-input:focus { + outline: none; + border-color: #ff0000; + box-shadow: 0 0 5px rgba(255, 0, 0, 0.3); +} + +.delete-max { + color: #666; + font-size: 10px; +} + +.action-btn.delete-btn { + background: #aa0000 !important; + border-color: #aa0000 !important; + color: white !important; + width: 100%; +} + +.action-btn.delete-btn:hover:not(:disabled) { + background: #cc0000 !important; + border-color: #cc0000 !important; +} + +.inventory-empty { + grid-column: 1 / -1; + text-align: center; + color: #666; + padding: 20px; +} + +.debug-input { + width: 100%; + padding: 5px; + margin-bottom: 5px; + background: #1e1e1e; + border: 1px solid #ff00ff; + color: #ff00ff; + font-size: 10px; + border-radius: 3px; +} + +.debug-input:focus { + outline: none; + border-color: #ff00ff; + box-shadow: 0 0 5px rgba(255, 0, 255, 0.5); +} + +/* 道具效果說明 */ +.item-effects { + margin-top: 6px; + padding-top: 6px; + border-top: 1px solid #333; + font-size: 10px; +} + +.effects-title { + color: #4ec9b0; + font-weight: bold; + margin-bottom: 4px; +} + +.effects-flat, .effects-percent { + display: flex; + flex-wrap: wrap; + gap: 6px; + margin-top: 4px; +} + +.effect-item { + padding: 2px 6px; + background: #001122; + border: 1px solid #3c3c3c; + border-radius: 3px; + color: #00ff00; + white-space: nowrap; +} + +/* 道具 Tooltip 樣式 */ +.item-tooltip { + position: fixed; + background: #000; + border: 2px solid #00ff00; + border-radius: 4px; + padding: 10px; + min-width: 200px; + max-width: 300px; + z-index: 10000; + box-shadow: 0 0 20px rgba(0, 255, 0, 0.5); + pointer-events: none; + font-size: 11px; +} + +.tooltip-header { + display: flex; + align-items: center; + gap: 6px; + margin-bottom: 6px; +} + +.tooltip-icon { + font-size: 20px; +} + +.tooltip-name { + font-weight: bold; + font-size: 13px; + color: #00ffff; +} + +.tooltip-rarity { + font-size: 10px; + margin-bottom: 4px; + font-weight: bold; +} + +.tooltip-type { + color: #4ec9b0; + font-size: 10px; + margin-bottom: 6px; +} + +.tooltip-description { + color: #aaa; + font-size: 10px; + margin-bottom: 8px; + line-height: 1.4; +} + +.tooltip-effects { + margin-top: 8px; + padding-top: 8px; + border-top: 1px solid #333; +} + +.tooltip-effects-title { + color: #4ec9b0; + font-weight: bold; + font-size: 10px; + margin-bottom: 4px; +} + +.tooltip-effect-item { + color: #00ff00; + font-size: 10px; + padding: 2px 0; +} + +.tooltip-durability { + margin-top: 8px; + padding-top: 8px; + border-top: 1px solid #333; + color: #ffaa00; + font-size: 10px; + font-weight: bold; +} diff --git a/console-demo.js b/console-demo.js index 3494617..7a12153 100644 --- a/console-demo.js +++ b/console-demo.js @@ -229,16 +229,20 @@ async function pray() { // 抽籤 async function drawFortune() { - const result = await templeSystem.drawFortune() + // 使用 drawLot 方法 + const result = await templeSystem.drawLot() if (result.success) { console.log('\n🎴 抽籤結果:') console.log('='.repeat(50)) console.log(`等級: ${result.lot.grade}`) console.log(`籤詩: ${result.lot.poem1}`) - console.log(` ${result.lot.poem2}`) + if (result.lot.poem2) { + console.log(` ${result.lot.poem2}`) + } console.log(`解釋: ${result.lot.meaning}`) - if (result.buff) { - console.log(`\n✨ 獲得 Buff: ${result.buff.name}`) + if (result.needVerification) { + console.log(`\n⚠️ 需要三聖筊驗證才能解籤`) + console.log(`目前: ${result.verificationCount}/${result.requiredHoly} 聖筊`) } console.log('='.repeat(50) + '\n') } else { diff --git a/core/achievement-system.js b/core/achievement-system.js new file mode 100644 index 0000000..e2b3900 --- /dev/null +++ b/core/achievement-system.js @@ -0,0 +1,335 @@ +// 成就系統核心 +import { apiService } from './api-service.js' +import { ACHIEVEMENTS } from '../data/achievements.js' + +export class AchievementSystem { + constructor(petSystem, eventSystem, templeSystem, api = apiService) { + this.petSystem = petSystem + this.eventSystem = eventSystem + this.templeSystem = templeSystem + this.api = api + this.achievements = ACHIEVEMENTS + this.unlockedAchievements = [] // 已解鎖的成就 ID 列表 + this.achievementStats = { + // 動作計數 + actionCounts: { + feed: 0, + play: 0, + clean: 0, + heal: 0, + sleep: 0, + pray: 0, + drawFortune: 0 + }, + // 事件計數 + eventCount: 0, + eventTypeCounts: { + good: 0, + bad: 0, + weird: 0, + rare: 0 + }, + // 特殊狀態 + recoveredFromDying: false, + perfectStateReached: false + } + } + + // 初始化(從 API 載入已解鎖成就) + async initialize() { + try { + const saved = await this.api.getAchievements() + if (saved) { + this.unlockedAchievements = saved.unlocked || [] + this.achievementStats = { ...this.achievementStats, ...saved.stats } + } + console.log(`[AchievementSystem] 載入 ${this.unlockedAchievements.length} 個已解鎖成就`) + + // 重新應用已解鎖成就的加成 + await this.reapplyAchievementBuffs() + } catch (error) { + console.error('[AchievementSystem] 載入成就失敗:', error) + // 降級到本地載入 + const saved = localStorage.getItem('achievements') + if (saved) { + const data = JSON.parse(saved) + this.unlockedAchievements = data.unlocked || [] + this.achievementStats = { ...this.achievementStats, ...data.stats } + + // 重新應用已解鎖成就的加成 + await this.reapplyAchievementBuffs() + } + } + } + + // 重新應用已解鎖成就的加成(初始化時使用) + async reapplyAchievementBuffs() { + if (!this.petSystem) return + + const unlocked = this.achievements.filter(a => this.unlockedAchievements.includes(a.id)) + const achievementBuffs = {} + + // 累積所有已解鎖成就的加成 + for (const achievement of unlocked) { + if (achievement.reward && achievement.reward.buffs) { + for (const [key, value] of Object.entries(achievement.reward.buffs)) { + achievementBuffs[key] = (achievementBuffs[key] || 0) + value + } + } + } + + // 更新寵物狀態 + if (Object.keys(achievementBuffs).length > 0) { + await this.petSystem.updateState({ achievementBuffs }) + // 重新計算戰鬥數值 + this.petSystem.calculateCombatStats() + console.log(`[AchievementSystem] 已重新應用 ${unlocked.length} 個成就的加成`) + } + } + + // 檢查成就條件 + checkCondition(achievement) { + const condition = achievement.condition + const state = this.petSystem.getState() + + switch (condition.type) { + case 'age': + return state.ageSeconds >= condition.value + + case 'stage': + return state.stage === condition.value + + case 'stats': + // 檢查所有指定屬性是否達到要求 + for (const [stat, value] of Object.entries(condition.stats)) { + if ((state[stat] || 0) < value) { + return false + } + } + return true + + case 'action_count': + return this.achievementStats.actionCounts[condition.action] >= condition.value + + case 'deity_favor': + // 檢查任一神明好感度 + const favors = state.deityFavors || {} + return Object.values(favors).some(favor => favor >= condition.value) + + case 'event_count': + return this.achievementStats.eventCount >= condition.value + + case 'event_type_count': + return this.achievementStats.eventTypeCounts[condition.eventType] >= condition.value + + case 'recovered_from_dying': + return this.achievementStats.recoveredFromDying === condition.value + + case 'perfect_state': + if (condition.value) { + return state.hunger >= 100 && + state.happiness >= 100 && + state.health >= 100 + } + return false + + default: + return false + } + } + + // 檢查並解鎖成就 + async checkAndUnlockAchievements() { + const newlyUnlocked = [] + + for (const achievement of this.achievements) { + // 如果已經解鎖,跳過 + if (this.unlockedAchievements.includes(achievement.id)) { + continue + } + + // 檢查條件 + if (this.checkCondition(achievement)) { + await this.unlockAchievement(achievement) + newlyUnlocked.push(achievement) + } + } + + return newlyUnlocked + } + + // 解鎖成就 + async unlockAchievement(achievement) { + if (this.unlockedAchievements.includes(achievement.id)) { + return // 已經解鎖 + } + + this.unlockedAchievements.push(achievement.id) + + // 應用成就獎勵(永久 Buff) + if (achievement.reward && achievement.reward.buffs) { + // 將成就加成添加到寵物狀態 + const currentState = this.petSystem.getState() + const achievementBuffs = currentState.achievementBuffs || {} + + // 合併加成 + for (const [key, value] of Object.entries(achievement.reward.buffs)) { + achievementBuffs[key] = (achievementBuffs[key] || 0) + value + } + + await this.petSystem.updateState({ achievementBuffs }) + + // 重新計算戰鬥數值 + this.petSystem.calculateCombatStats() + } + + // 同步到 API + try { + await this.api.saveAchievements({ + unlocked: this.unlockedAchievements, + stats: this.achievementStats + }) + } catch (error) { + console.warn('[AchievementSystem] API 同步失敗:', error) + // 降級到 localStorage + localStorage.setItem('achievements', JSON.stringify({ + unlocked: this.unlockedAchievements, + stats: this.achievementStats + })) + } + + // 顯示成就通知 + console.log(`\n${'='.repeat(50)}`) + console.log(`🏆 成就解鎖:${achievement.icon} ${achievement.name}`) + console.log(`📝 ${achievement.description}`) + if (achievement.reward && achievement.reward.buffs) { + console.log(`✨ 獎勵:`) + for (const [key, value] of Object.entries(achievement.reward.buffs)) { + const sign = value > 0 ? '+' : '' + if (typeof value === 'number' && value < 1 && value > 0) { + console.log(` ${key}: ${sign}${(value * 100).toFixed(0)}%`) + } else { + console.log(` ${key}: ${sign}${value}`) + } + } + } + console.log('='.repeat(50) + '\n') + + return achievement + } + + // 記錄動作 + async recordAction(action) { + if (this.achievementStats.actionCounts[action] !== undefined) { + this.achievementStats.actionCounts[action]++ + await this.checkAndUnlockAchievements() + } + } + + // 記錄事件 + async recordEvent(event) { + this.achievementStats.eventCount++ + if (event.type && this.achievementStats.eventTypeCounts[event.type] !== undefined) { + this.achievementStats.eventTypeCounts[event.type]++ + } + await this.checkAndUnlockAchievements() + } + + // 記錄從瀕死恢復 + recordRecoveryFromDying() { + if (!this.achievementStats.recoveredFromDying) { + this.achievementStats.recoveredFromDying = true + this.checkAndUnlockAchievements() + } + } + + // 檢查完美狀態 + checkPerfectState() { + const state = this.petSystem.getState() + if (state.hunger >= 100 && + state.happiness >= 100 && + state.health >= 100 && + !this.achievementStats.perfectStateReached) { + this.achievementStats.perfectStateReached = true + this.checkAndUnlockAchievements() + } + } + + // 獲取已解鎖成就 + getUnlockedAchievements() { + return this.achievements.filter(a => this.unlockedAchievements.includes(a.id)) + } + + // 獲取未解鎖成就 + getLockedAchievements() { + return this.achievements.filter(a => !this.unlockedAchievements.includes(a.id)) + } + + // 獲取成就進度 + getAchievementProgress(achievement) { + const condition = achievement.condition + const state = this.petSystem.getState() + + switch (condition.type) { + case 'age': + return { + current: state.ageSeconds, + target: condition.value, + progress: Math.min(100, (state.ageSeconds / condition.value) * 100) + } + + case 'action_count': + return { + current: this.achievementStats.actionCounts[condition.action] || 0, + target: condition.value, + progress: Math.min(100, ((this.achievementStats.actionCounts[condition.action] || 0) / condition.value) * 100) + } + + case 'stats': + // 返回最低進度 + let minProgress = 100 + for (const [stat, value] of Object.entries(condition.stats)) { + const current = state[stat] || 0 + const progress = Math.min(100, (current / value) * 100) + minProgress = Math.min(minProgress, progress) + } + return { progress: minProgress } + + case 'deity_favor': + const favors = state.deityFavors || {} + const maxFavor = Math.max(...Object.values(favors), 0) + return { + current: maxFavor, + target: condition.value, + progress: Math.min(100, (maxFavor / condition.value) * 100) + } + + case 'event_count': + return { + current: this.achievementStats.eventCount, + target: condition.value, + progress: Math.min(100, (this.achievementStats.eventCount / condition.value) * 100) + } + + default: + return { progress: 0 } + } + } + + // 獲取所有成就加成(用於顯示) + getAllAchievementBonuses() { + const bonuses = {} + const unlocked = this.getUnlockedAchievements() + + for (const achievement of unlocked) { + if (achievement.reward && achievement.reward.buffs) { + for (const [key, value] of Object.entries(achievement.reward.buffs)) { + bonuses[key] = (bonuses[key] || 0) + value + } + } + } + + return bonuses + } +} + diff --git a/core/api-service.js b/core/api-service.js index 38717be..d13eb24 100644 --- a/core/api-service.js +++ b/core/api-service.js @@ -47,6 +47,14 @@ export class ApiService { return this.saveMockPetState(options.body) case 'pet/delete': return this.deleteMockPetState() + case 'achievements/get': + return this.getMockAchievements() + case 'achievements/save': + return this.saveMockAchievements(options.body) + case 'inventory/get': + return this.getMockInventory() + case 'inventory/save': + return this.saveMockInventory(options.body) default: throw new Error(`Unknown endpoint: ${endpoint}`) } @@ -262,6 +270,81 @@ export class ApiService { localStorage.removeItem('petState') return { success: true, message: '寵物已刪除' } } + + // 成就相關 + async getAchievements() { + return this.request('achievements/get') + } + + async saveAchievements(data) { + return this.request('achievements/save', { + method: 'POST', + body: data + }) + } + + getMockAchievements() { + const stored = localStorage.getItem('achievements') + if (stored) { + return JSON.parse(stored) + } + return null + } + + saveMockAchievements(data) { + localStorage.setItem('achievements', JSON.stringify(data)) + return { success: true, message: '成就已儲存' } + } + + // 背包相關 + async getInventory() { + return this.request('inventory/get') + } + + async saveInventory(data) { + return this.request('inventory/save', { + method: 'POST', + body: data + }) + } + + getMockInventory() { + const stored = localStorage.getItem('inventory') + if (stored) { + return JSON.parse(stored) + } + return { + inventory: {}, + equipped: { + weapon: null, + armor: null, + hat: null, + accessory: null, + talisman: null, + special: null + }, + appearance: {} + } + } + + saveMockInventory(data) { + try { + const dataToSave = { + inventory: data.inventory || {}, + equipped: data.equipped || {}, + appearance: data.appearance || {} + } + localStorage.setItem('inventory', JSON.stringify(dataToSave)) + console.log('[ApiService] 背包已儲存到 localStorage:', { + inventoryCount: Object.keys(dataToSave.inventory).length, + equipped: dataToSave.equipped + }) + return { success: true, message: '背包已儲存' } + } catch (error) { + console.error('[ApiService] 儲存背包失敗:', error) + return { success: false, message: '儲存失敗: ' + error.message } + } + } } // 預設實例 diff --git a/core/event-system.js b/core/event-system.js index 6d6019b..5bbaef8 100644 --- a/core/event-system.js +++ b/core/event-system.js @@ -2,9 +2,11 @@ import { apiService } from './api-service.js' export class EventSystem { - constructor(petSystem, api = apiService) { + constructor(petSystem, api = apiService, achievementSystem = null, inventorySystem = null) { this.petSystem = petSystem this.api = api + this.achievementSystem = achievementSystem + this.inventorySystem = inventorySystem this.events = [] this.buffManager = new BuffManager() this.eventHistory = [] @@ -123,6 +125,11 @@ export class EventSystem { effects: results }) + // 通知成就系統(如果存在) + if (this.achievementSystem) { + await this.achievementSystem.recordEvent(event) + } + // 同步到 API try { await this.api.triggerEvent(eventId, currentState) @@ -142,6 +149,9 @@ export class EventSystem { case 'addBuff': return await this.addBuff(effect.payload) + case 'addItem': + return await this.addItem(effect.payload) + case 'spawnPoop': return await this.spawnPoop(effect.payload) @@ -235,6 +245,25 @@ export class EventSystem { return { type: 'templeFavor', deityId, favor: newFavor } } + // 添加道具效果 + async addItem(payload) { + if (!this.inventorySystem) { + console.warn('[EventSystem] 背包系統未初始化,無法添加道具') + return { type: 'addItem', success: false, message: '背包系統未初始化' } + } + + const { itemId, count = 1 } = payload + const result = await this.inventorySystem.addItem(itemId, count) + + if (result.success) { + console.log(`[事件] 獲得道具: ${result.item.name} x${count}`) + return { type: 'addItem', success: true, itemId, count, item: result.item } + } else { + console.warn(`[事件] 添加道具失敗: ${result.message}`) + return { type: 'addItem', success: false, message: result.message } + } + } + // 應用 Buff 到狀態(每 tick 呼叫) async applyBuffs() { const petState = this.petSystem.getState() diff --git a/core/inventory-system.js b/core/inventory-system.js new file mode 100644 index 0000000..7385666 --- /dev/null +++ b/core/inventory-system.js @@ -0,0 +1,720 @@ +// 背包系統核心 +import { apiService } from './api-service.js' +import { ITEM_TYPES, ITEM_RARITY, EQUIPMENT_SLOTS } from '../data/items.js' + +export class InventorySystem { + constructor(petSystem, eventSystem, api = apiService) { + this.petSystem = petSystem + this.eventSystem = eventSystem + this.api = api + this.items = {} // 從 API 載入的道具數據 + this.itemTypes = ITEM_TYPES + this.itemRarity = ITEM_RARITY + this.equipmentSlots = EQUIPMENT_SLOTS + + // 背包結構:{ itemId: { count: number, item: ItemData } } + this.inventory = {} + + // 裝備槽位:每個槽位可以同時裝備實際套件和外觀套件 + // { slot: { equipment: itemId/object, appearance: itemId/object } } + this.equipped = { + weapon: { equipment: null, appearance: null }, + armor: { equipment: null, appearance: null }, + hat: { equipment: null, appearance: null }, + accessory: { equipment: null, appearance: null }, + talisman: { equipment: null, appearance: null }, + special: { equipment: null, appearance: null } + } + + // 外觀設定(從外觀套件或實際裝備中提取,外觀套件優先) + this.appearance = {} + } + + // 初始化(從 API 載入道具數據、背包和裝備) + async initialize() { + try { + // 從 API 載入道具列表 + const itemsList = await this.api.getItems() + if (itemsList && Array.isArray(itemsList)) { + // 將數組轉換為對象,以 itemId 為 key + this.items = {} + for (const item of itemsList) { + if (item.id) { + this.items[item.id] = item + } + } + console.log(`[InventorySystem] 從 API 載入 ${Object.keys(this.items).length} 種道具`) + } else { + // 降級到本地數據 + const { ITEMS } = await import('../data/items.js') + this.items = ITEMS + console.log(`[InventorySystem] 使用本地道具數據,共 ${Object.keys(this.items).length} 種道具`) + } + } catch (error) { + console.warn('[InventorySystem] 載入道具列表失敗,使用本地數據:', error) + // 降級到本地數據 + const { ITEMS } = await import('../data/items.js') + this.items = ITEMS + } + + try { + // 載入背包和裝備 + const saved = await this.api.getInventory() + if (saved) { + this.inventory = saved.inventory || {} + // 兼容舊格式:如果是舊格式(單一值),轉換為新格式 + if (saved.equipped) { + for (const [slot, equipped] of Object.entries(saved.equipped)) { + if (this.equipped[slot]) { + // 新格式:已有 equipment 和 appearance 結構 + if (equipped && typeof equipped === 'object' && (equipped.equipment !== undefined || equipped.appearance !== undefined)) { + this.equipped[slot] = { + equipment: equipped.equipment || null, + appearance: equipped.appearance || null + } + } else if (equipped) { + // 舊格式:單一值,判斷是裝備還是外觀 + const itemId = typeof equipped === 'string' ? equipped : equipped.itemId + const item = this.items[itemId] + if (item) { + if (item.type === 'appearance') { + this.equipped[slot] = { equipment: null, appearance: equipped } + } else { + this.equipped[slot] = { equipment: equipped, appearance: null } + } + } + } + } + } + } + this.appearance = saved.appearance || {} + } + + // 重新應用裝備效果 + await this.reapplyEquipmentEffects() + + console.log(`[InventorySystem] 載入背包,共 ${Object.keys(this.inventory).length} 種道具`) + } catch (error) { + console.error('[InventorySystem] 載入背包失敗:', error) + // 降級到本地載入 + const saved = localStorage.getItem('inventory') + if (saved) { + const data = JSON.parse(saved) + this.inventory = data.inventory || {} + this.equipped = { ...this.equipped, ...data.equipped } + this.appearance = data.appearance || {} + await this.reapplyEquipmentEffects() + } + } + } + + // 添加道具到背包 + async addItem(itemId, count = 1) { + const item = this.items[itemId] + if (!item) { + console.warn(`[InventorySystem] 找不到道具: ${itemId}`) + return { success: false, message: '道具不存在' } + } + + // 只有消耗品可以堆疊,其他道具(裝備、外觀、護身符、特殊)每件都要分開 + if (item.type === 'consumable') { + // 消耗品可以堆疊 + if (!this.inventory[itemId]) { + this.inventory[itemId] = { + count: 0, + item: { ...item } + } + } + this.inventory[itemId].count += count + } else { + // 裝備類道具(equipment, appearance, talisman, special)每件分開 + if (!this.inventory[itemId]) { + this.inventory[itemId] = { + count: 0, + items: [] // 多個相同裝備,每個有獨立耐久度 + } + } + + // 添加新裝備實例(每件都是獨立的) + for (let i = 0; i < count; i++) { + this.inventory[itemId].items = this.inventory[itemId].items || [] + this.inventory[itemId].items.push({ + id: `${itemId}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, + itemId, + durability: item.durability !== undefined ? item.durability : Infinity, + maxDurability: item.maxDurability !== undefined ? item.maxDurability : Infinity + }) + this.inventory[itemId].count++ + } + } + + // 同步到 API + await this.saveInventory() + + console.log(`[InventorySystem] 獲得 ${count} 個 ${item.name}`) + return { success: true, item, count } + } + + // 移除道具(會自動卸下如果正在裝備中) + async removeItem(itemId, count = 1) { + // 檢查是否正在裝備中,如果是則先卸下 + for (const [slot, slotData] of Object.entries(this.equipped)) { + if (typeof slotData === 'object' && slotData !== null) { + if (slotData.equipment) { + const eqItemId = typeof slotData.equipment === 'string' ? slotData.equipment : slotData.equipment.itemId + if (eqItemId === itemId) { + await this.unequipItem(slot, 'equipment') + } + } + if (slotData.appearance) { + const apItemId = typeof slotData.appearance === 'string' ? slotData.appearance : slotData.appearance.itemId + if (apItemId === itemId) { + await this.unequipItem(slot, 'appearance') + } + } + } + } + if (!this.inventory[itemId]) { + return { success: false, message: '道具不存在' } + } + + const item = this.items[itemId] + + // 只有消耗品可以堆疊 + if (item.type === 'consumable') { + if (this.inventory[itemId].count < count) { + return { success: false, message: '道具數量不足' } + } + this.inventory[itemId].count -= count + if (this.inventory[itemId].count <= 0) { + delete this.inventory[itemId] + } + } else { + // 裝備類道具,每件分開 + if (this.inventory[itemId].count < count) { + return { success: false, message: '道具數量不足' } + } + + // 移除指定數量的裝備實例(從未裝備的開始移除) + this.inventory[itemId].items = this.inventory[itemId].items || [] + + // 找出未裝備的實例 + const equippedInstances = new Set() + for (const [slot, slotData] of Object.entries(this.equipped)) { + if (slotData && typeof slotData === 'object') { + if (slotData.equipment && typeof slotData.equipment === 'object' && slotData.equipment.itemId === itemId) { + equippedInstances.add(slotData.equipment.instanceId) + } + if (slotData.appearance && typeof slotData.appearance === 'object' && slotData.appearance.itemId === itemId) { + equippedInstances.add(slotData.appearance.instanceId) + } + } + } + + // 先移除未裝備的實例 + let removed = 0 + for (let i = this.inventory[itemId].items.length - 1; i >= 0 && removed < count; i--) { + if (!equippedInstances.has(this.inventory[itemId].items[i].id)) { + this.inventory[itemId].items.splice(i, 1) + removed++ + } + } + + this.inventory[itemId].count -= removed + + if (this.inventory[itemId].count <= 0) { + delete this.inventory[itemId] + } + } + + await this.saveInventory() + console.log(`[InventorySystem] 移除道具: ${itemId} x${count}`) + return { success: true } + } + + // 重置背包(清除所有道具和裝備) + async resetInventory() { + this.inventory = {} + this.equipped = { + weapon: { equipment: null, appearance: null }, + armor: { equipment: null, appearance: null }, + hat: { equipment: null, appearance: null }, + accessory: { equipment: null, appearance: null }, + talisman: { equipment: null, appearance: null }, + special: { equipment: null, appearance: null } + } + this.appearance = {} + + // 清除裝備效果 + await this.petSystem.updateState({ equipmentBuffs: { flat: {}, percent: {} } }) + this.petSystem.calculateCombatStats() + + // 清除 localStorage + localStorage.removeItem('inventory') + + // 同步到 API + await this.saveInventory() + + console.log('[InventorySystem] 背包已重置') + return { success: true } + } + + // 使用消耗品 + async useItem(itemId, count = 1) { + const item = this.items[itemId] + if (!item) { + return { success: false, message: '道具不存在' } + } + + if (item.type !== 'consumable') { + return { success: false, message: '此道具不是消耗品' } + } + + // 檢查數量 + if (!this.inventory[itemId] || this.inventory[itemId].count < count) { + return { success: false, message: '道具數量不足' } + } + + const results = [] + + // 執行效果 + for (let i = 0; i < count; i++) { + const result = await this.executeItemEffects(item) + results.push(result) + } + + // 移除道具 + await this.removeItem(itemId, count) + + // 同步到 API + try { + await this.api.useItem(itemId, count) + } catch (error) { + console.warn('[InventorySystem] API 同步失敗:', error) + } + + return { success: true, results } + } + + // 執行道具效果 + async executeItemEffects(item) { + const results = [] + const state = this.petSystem.getState() + + if (item.effects) { + // 修改屬性 + if (item.effects.modifyStats) { + const updates = {} + for (const [key, value] of Object.entries(item.effects.modifyStats)) { + if (key === 'health') { + const maxHealth = this.petSystem.getMaxHealth() + updates[key] = Math.min(maxHealth, (state[key] || 0) + value) + } else if (key === 'hunger' || key === 'happiness') { + updates[key] = Math.min(100, Math.max(0, (state[key] || 0) + value)) + } else { + updates[key] = (state[key] || 0) + value + } + } + await this.petSystem.updateState(updates) + results.push({ type: 'modifyStats', updates }) + } + + // 治癒疾病 + if (item.effects.cureSickness && state.isSick) { + await this.petSystem.updateState({ isSick: false }) + results.push({ type: 'cureSickness' }) + } + + // 添加 Buff + if (item.effects.addBuff) { + await this.eventSystem.addBuff(item.effects.addBuff) + results.push({ type: 'addBuff', buff: item.effects.addBuff }) + } + } + + return results + } + + // 裝備道具 + // equipType: 'equipment' | 'appearance' | 'auto' (自動判斷) + async equipItem(itemId, slot = null, equipType = 'auto') { + const item = this.items[itemId] + if (!item) { + return { success: false, message: '道具不存在' } + } + + // 檢查是否可裝備 + if (item.type !== 'equipment' && item.type !== 'appearance' && item.type !== 'talisman' && item.type !== 'special') { + return { success: false, message: '此道具無法裝備' } + } + + // 確定槽位 + const targetSlot = slot || item.slot + if (!targetSlot) { + return { success: false, message: '道具沒有指定槽位' } + } + + // 檢查是否有該道具 + if (!this.inventory[itemId] || this.inventory[itemId].count < 1) { + return { success: false, message: '背包中沒有此道具' } + } + + // 確定裝備類型 + let targetType = equipType + if (targetType === 'auto') { + // 自動判斷:appearance 類型裝備到 appearance 槽位,其他裝備到 equipment 槽位 + if (item.type === 'appearance') { + targetType = 'appearance' + } else { + targetType = 'equipment' + } + } + + // 檢查槽位結構 + if (!this.equipped[targetSlot] || typeof this.equipped[targetSlot] !== 'object') { + this.equipped[targetSlot] = { equipment: null, appearance: null } + } + + // 如果該子槽位已有裝備,先卸下 + if (this.equipped[targetSlot][targetType]) { + await this.unequipItem(targetSlot, targetType) + } + + // 裝備道具 + let equippedData = null + if (item.type === 'consumable') { + // 消耗品不應該裝備 + return { success: false, message: '消耗品無法裝備' } + } else { + // 裝備類道具,使用指定的實例或選擇第一個未裝備的 + if (!instanceId) { + // 選擇第一個未裝備的實例 + const instances = this.inventory[itemId].items || [] + if (instances.length === 0) { + return { success: false, message: '裝備實例不存在' } + } + + // 找出已裝備的實例 + const equippedInstances = new Set() + for (const [s, slotData] of Object.entries(this.equipped)) { + if (slotData && typeof slotData === 'object') { + if (slotData.equipment && typeof slotData.equipment === 'object' && slotData.equipment.itemId === itemId) { + equippedInstances.add(slotData.equipment.instanceId) + } + if (slotData.appearance && typeof slotData.appearance === 'object' && slotData.appearance.itemId === itemId) { + equippedInstances.add(slotData.appearance.instanceId) + } + } + } + + // 選擇第一個未裝備的實例 + const availableInstance = instances.find(i => !equippedInstances.has(i.id)) + if (!availableInstance) { + return { success: false, message: '所有裝備實例都已裝備' } + } + instanceId = availableInstance.id + } + + equippedData = { + itemId, + instanceId: instanceId + } + } + + // 裝備到對應槽位 + this.equipped[targetSlot][targetType] = equippedData + + // 更新外觀(優先使用外觀套件,如果沒有則使用實際裝備的外觀) + await this.updateAppearance() + + // 應用裝備效果(只有實際裝備才有效果) + await this.applyEquipmentEffects() + + // 同步到 API + await this.saveInventory() + + const slotName = EQUIPMENT_SLOTS[targetSlot]?.name || targetSlot + const typeName = targetType === 'appearance' ? '外觀' : '實際' + console.log(`[InventorySystem] 裝備 ${item.name} 到 ${slotName} (${typeName})`) + return { success: true, item, slot: targetSlot, type: targetType } + } + + // 卸下裝備 + // type: 'equipment' | 'appearance' | null (卸下全部) + async unequipItem(slot, type = null) { + if (!this.equipped[slot]) { + return { success: false, message: '該槽位沒有裝備' } + } + + // 如果沒有指定類型,卸下全部(兼容舊代碼) + if (type === null) { + const results = [] + if (this.equipped[slot].equipment) { + const result = await this.unequipItem(slot, 'equipment') + if (result.success) results.push(result) + } + if (this.equipped[slot].appearance) { + const result = await this.unequipItem(slot, 'appearance') + if (result.success) results.push(result) + } + return { success: results.length > 0, results } + } + + // 卸下指定類型的裝備 + const equipped = this.equipped[slot][type] + if (!equipped) { + return { success: false, message: `該槽位的${type === 'appearance' ? '外觀' : '實際'}裝備為空` } + } + + const itemId = typeof equipped === 'string' ? equipped : equipped.itemId + const item = this.items[itemId] + + // 清除裝備 + this.equipped[slot][type] = null + + // 更新外觀 + await this.updateAppearance() + + // 重新計算屬性(只有卸下實際裝備才需要) + if (type === 'equipment') { + await this.applyEquipmentEffects() + } + + // 同步到 API + await this.saveInventory() + + console.log(`[InventorySystem] 卸下 ${item?.name || itemId} (${type === 'appearance' ? '外觀' : '實際'})`) + return { success: true, item, type } + } + + // 更新外觀(優先使用外觀套件,如果沒有則使用實際裝備的外觀) + async updateAppearance() { + this.appearance = {} + + // 遍歷所有槽位 + for (const [slot, equipped] of Object.entries(this.equipped)) { + if (!equipped) continue + + // 優先使用外觀套件 + if (equipped.appearance) { + const itemId = typeof equipped.appearance === 'string' ? equipped.appearance : equipped.appearance.itemId + const item = this.items[itemId] + if (item && item.appearance) { + this.appearance = { ...this.appearance, ...item.appearance } + } + } else if (equipped.equipment) { + // 如果沒有外觀套件,使用實際裝備的外觀 + const itemId = typeof equipped.equipment === 'string' ? equipped.equipment : equipped.equipment.itemId + const item = this.items[itemId] + if (item && item.appearance) { + this.appearance = { ...this.appearance, ...item.appearance } + } + } + } + } + + // 應用裝備效果(只應用實際裝備的效果,外觀套件不影響數值) + async applyEquipmentEffects() { + const state = this.petSystem.getState() + const equipmentBuffs = {} + + // 收集所有實際裝備的加成(不包括外觀套件) + for (const [slot, equipped] of Object.entries(this.equipped)) { + if (!equipped || !equipped.equipment) continue + + const itemId = typeof equipped.equipment === 'string' ? equipped.equipment : equipped.equipment.itemId + const item = this.items[itemId] + if (!item) continue + + // 檢查耐久度(如果是裝備類且有耐久度) + if (item.type === 'equipment' && item.durability !== Infinity) { + const instanceId = typeof equipped.equipment === 'object' ? equipped.equipment.instanceId : null + if (instanceId) { + const instance = this.inventory[itemId]?.items?.find(i => i.id === instanceId) + if (instance && instance.durability <= 0) { + // 裝備已損壞,自動卸下 + console.log(`[InventorySystem] ${item.name} 已損壞,自動卸下`) + this.equipped[slot].equipment = null + continue + } + } + } + + // 應用裝備效果(只有實際裝備才有效果) + if (item.effects) { + if (item.effects.flat) { + for (const [key, value] of Object.entries(item.effects.flat)) { + if (!equipmentBuffs.flat) equipmentBuffs.flat = {} + equipmentBuffs.flat[key] = (equipmentBuffs.flat[key] || 0) + value + } + } + if (item.effects.percent) { + for (const [key, value] of Object.entries(item.effects.percent)) { + if (!equipmentBuffs.percent) equipmentBuffs.percent = {} + equipmentBuffs.percent[key] = (equipmentBuffs.percent[key] || 0) + value + } + } + } + } + + // 更新寵物狀態(確保結構正確) + const finalBuffs = { + flat: equipmentBuffs.flat || {}, + percent: equipmentBuffs.percent || {} + } + + await this.petSystem.updateState({ equipmentBuffs: finalBuffs }) + + // 重新計算戰鬥數值 + this.petSystem.calculateCombatStats() + + return finalBuffs + } + + // 重新應用裝備效果(初始化時使用) + async reapplyEquipmentEffects() { + await this.applyEquipmentEffects() + } + + // 減少裝備耐久度(只減少實際裝備的耐久度) + async reduceDurability(slot, amount = 1) { + const equipped = this.equipped[slot] + if (!equipped || !equipped.equipment) return + + const itemId = typeof equipped.equipment === 'string' ? equipped.equipment : equipped.equipment.itemId + const item = this.items[itemId] + + // 只有裝備類且有耐久度的才會減少 + if (item.type !== 'equipment' || item.durability === Infinity) return + + const instanceId = typeof equipped.equipment === 'object' ? equipped.equipment.instanceId : null + if (!instanceId) return + + // 找到裝備實例 + const instance = this.inventory[itemId]?.items?.find(i => i.id === instanceId) + if (!instance) return + + // 減少耐久度 + instance.durability = Math.max(0, instance.durability - amount) + + // 如果耐久度歸零,自動卸下 + if (instance.durability <= 0) { + console.log(`[InventorySystem] ${item.name} 耐久度歸零,已損壞`) + await this.unequipItem(slot, 'equipment') + } + + await this.saveInventory() + } + + // 修復裝備 + async repairItem(itemId, instanceId = null) { + if (!this.inventory[itemId]) { + return { success: false, message: '道具不存在' } + } + + const item = this.items[itemId] + if (item.durability === Infinity) { + return { success: false, message: '此道具無法修復(永久裝備)' } + } + + if (item.stackable) { + return { success: false, message: '此道具無法修復' } + } + + const instances = this.inventory[itemId].items || [] + let repaired = false + + if (instanceId) { + // 修復指定實例 + const instance = instances.find(i => i.id === instanceId) + if (instance) { + instance.durability = instance.maxDurability || item.maxDurability + repaired = true + } + } else { + // 修復所有實例 + instances.forEach(instance => { + instance.durability = instance.maxDurability || item.maxDurability + }) + repaired = instances.length > 0 + } + + if (repaired) { + await this.saveInventory() + await this.applyEquipmentEffects() // 重新應用效果 + return { success: true, message: '裝備已修復' } + } + + return { success: false, message: '修復失敗' } + } + + // 獲取背包 + getInventory() { + return { ...this.inventory } + } + + // 獲取裝備 + getEquipped() { + return { ...this.equipped } + } + + // 獲取外觀 + getAppearance() { + return { ...this.appearance } + } + + // 檢查是否有道具 + hasItem(itemId, count = 1) { + if (!this.inventory[itemId]) return false + return this.inventory[itemId].count >= count + } + + // 獲取道具數量 + getItemCount(itemId) { + return this.inventory[itemId]?.count || 0 + } + + // 獲取裝備的道具 + // type: 'equipment' | 'appearance' | null (返回兩個) + getEquippedItem(slot, type = null) { + const equipped = this.equipped[slot] + if (!equipped) return null + + if (type) { + const equippedData = equipped[type] + if (!equippedData) return null + const itemId = typeof equippedData === 'string' ? equippedData : equippedData.itemId + return this.items[itemId] || null + } else { + // 返回兩個 + return { + equipment: equipped.equipment ? (() => { + const itemId = typeof equipped.equipment === 'string' ? equipped.equipment : equipped.equipment.itemId + return this.items[itemId] || null + })() : null, + appearance: equipped.appearance ? (() => { + const itemId = typeof equipped.appearance === 'string' ? equipped.appearance : equipped.appearance.itemId + return this.items[itemId] || null + })() : null + } + } + } + + // 保存背包(同步到 API) + async saveInventory() { + const data = { + inventory: this.inventory, + equipped: this.equipped, + appearance: this.appearance + } + + try { + await this.api.saveInventory(data) + } catch (error) { + console.warn('[InventorySystem] API 同步失敗:', error) + // 降級到 localStorage + localStorage.setItem('inventory', JSON.stringify(data)) + } + } +} + diff --git a/core/pet-system.js b/core/pet-system.js index 1fc61fb..ce082c4 100644 --- a/core/pet-system.js +++ b/core/pet-system.js @@ -5,8 +5,10 @@ import { FATES } from '../data/fates.js' import { DEITIES } from '../data/deities.js' export class PetSystem { - constructor(api = apiService) { + constructor(api = apiService, achievementSystem = null, inventorySystem = null) { this.api = api + this.achievementSystem = achievementSystem + this.inventorySystem = inventorySystem this.state = null this.speciesConfig = null this.tickInterval = null @@ -23,6 +25,11 @@ export class PetSystem { // 創建新寵物 this.state = this.createInitialState(speciesId) await this.api.savePetState(this.state) + } else { + // 確保 achievementBuffs 存在(向後兼容) + if (!this.state.achievementBuffs) { + this.state.achievementBuffs = {} + } } // 載入種族配置 @@ -76,7 +83,10 @@ export class PetSystem { buffs: [], inventory: [], generation: 1, - lastTickTime: Date.now() + lastTickTime: Date.now(), + achievementBuffs: {}, // 成就加成 + equipmentBuffs: {}, // 裝備加成 + appearance: {} // 外觀設定 } // 分配命格 @@ -104,7 +114,7 @@ export class PetSystem { } } - // 獲取所有加成(命格 + 神明基礎 + 神明好感度等級 + 神明滿級 + Buff) + // 獲取所有加成(命格 + 神明基礎 + 神明好感度等級 + 神明滿級 + 成就 + Buff) getAllBonuses() { const bonuses = {} @@ -147,6 +157,29 @@ export class PetSystem { } } + // 5. 成就加成 + if (this.state.achievementBuffs) { + for (const [key, value] of Object.entries(this.state.achievementBuffs)) { + bonuses[key] = (bonuses[key] || 0) + value + } + } + + // 6. 裝備加成 + if (this.state.equipmentBuffs) { + // 處理 flat 加成(直接數值加成) + if (this.state.equipmentBuffs.flat) { + for (const [key, value] of Object.entries(this.state.equipmentBuffs.flat)) { + bonuses[key] = (bonuses[key] || 0) + value + } + } + // 處理 percent 加成(百分比加成) + if (this.state.equipmentBuffs.percent) { + for (const [key, value] of Object.entries(this.state.equipmentBuffs.percent)) { + bonuses[key] = (bonuses[key] || 0) + value + } + } + } + return bonuses } @@ -457,14 +490,46 @@ export class PetSystem { } else { // 健康恢復,重置瀕死計時 if (this.state.dyingSeconds > 0) { + const wasDying = this.state.dyingSeconds > 0 this.state.dyingSeconds = 0 console.log('✨ 寵物脫離瀕死狀態') + + // 通知成就系統(如果存在) + if (this.achievementSystem && wasDying) { + this.achievementSystem.recordRecoveryFromDying() + } + } + } + + // 檢查成就(年齡、階段、完美狀態等) + if (this.achievementSystem) { + await this.achievementSystem.checkAndUnlockAchievements() + this.achievementSystem.checkPerfectState() + } + + // 減少裝備耐久度(每 tick 減少少量,戰鬥或特殊情況會減少更多) + if (this.inventorySystem) { + // 只有裝備中的道具才會減少耐久度 + const equipped = this.inventorySystem.getEquipped() + for (const [slot, equippedItem] of Object.entries(equipped)) { + if (equippedItem) { + // 每 10 個 tick 減少 1 點耐久度(約每 30 秒) + if (this.state._tickCount && this.state._tickCount % 10 === 0) { + await this.inventorySystem.reduceDurability(slot, 1) + } + } } } // 重新计算属性(含加成) this.calculateCombatStats() + // 初始化 tick 計數器 + if (!this.state._tickCount) { + this.state._tickCount = 0 + } + this.state._tickCount++ + // 同步到 API await this.updateState({ // 基礎屬性 @@ -599,6 +664,12 @@ export class PetSystem { str: newStr }) + // 記錄到成就系統 + if (this.achievementSystem) { + await this.achievementSystem.recordAction('feed') + this.achievementSystem.checkPerfectState() + } + this.calculateCombatStats() return { success: true, hunger: newHunger, weight: newWeight, strGain, weightChange } @@ -684,6 +755,12 @@ export class PetSystem { weight: newWeight }) + // 記錄到成就系統 + if (this.achievementSystem) { + await this.achievementSystem.recordAction('play') + this.achievementSystem.checkPerfectState() + } + this.calculateCombatStats() return { @@ -712,6 +789,12 @@ export class PetSystem { happiness: newHappiness }) + // 記錄到成就系統 + if (this.achievementSystem) { + await this.achievementSystem.recordAction('clean') + this.achievementSystem.checkPerfectState() + } + return { success: true, poopCount: newPoopCount, happiness: newHappiness } } @@ -736,6 +819,12 @@ export class PetSystem { isSick: false }) + // 記錄到成就系統 + if (this.achievementSystem) { + await this.achievementSystem.recordAction('heal') + this.achievementSystem.checkPerfectState() + } + return { success: true, health: newHealth, @@ -799,6 +888,11 @@ export class PetSystem { _autoSlept: willRandomSleep ? true : (newIsSleeping ? false : undefined) }) + // 記錄到成就系統 + if (this.achievementSystem && newIsSleeping) { + await this.achievementSystem.recordAction('sleep') + } + return { success: true, isSleeping: willRandomSleep ? true : newIsSleeping, diff --git a/core/temple-system.js b/core/temple-system.js index ed83260..7b2772d 100644 --- a/core/temple-system.js +++ b/core/temple-system.js @@ -3,9 +3,10 @@ import { apiService } from './api-service.js' import { JIAOBEI_CONFIG } from '../data/jiaobei-config.js' export class TempleSystem { - constructor(petSystem, api = apiService) { + constructor(petSystem, api = apiService, achievementSystem = null) { this.petSystem = petSystem this.api = api + this.achievementSystem = achievementSystem this.deities = [] } @@ -103,6 +104,13 @@ export class TempleSystem { // 獲取神明對話 const dialogue = deity.dialogues[Math.floor(Math.random() * deity.dialogues.length)] + // 記錄到成就系統 + if (this.achievementSystem) { + await this.achievementSystem.recordAction('pray') + // 檢查神明好感度成就 + await this.achievementSystem.checkAndUnlockAchievements() + } + return { success: true, favorIncrease: result.favorIncrease, @@ -152,6 +160,12 @@ export class TempleSystem { const randomIndex = Math.floor(Math.random() * lots.length) const lot = lots[randomIndex] + // 記錄到成就系統 + if (this.achievementSystem) { + await this.achievementSystem.recordAction('drawFortune') + await this.achievementSystem.checkAndUnlockAchievements() + } + // 返回需要擲筊驗證的狀態 return { success: true, @@ -249,27 +263,27 @@ export class TempleSystem { const probabilities = this.calculateJiaobeiProbabilities() const result = this.rollJiaobei(probabilities) - // 選擇訊息 - const messages = JIAOBEI_CONFIG.messages[result] - const message = messages[Math.floor(Math.random() * messages.length)] - return { success: true, result, - message, deity: deity.name, - probabilities, - question + message: result === 'holy' ? '聖筊' : result === 'laughing' ? '笑筊' : '陰筊', + probabilities } } + // 取得當前神明可用的 lotTypes(可能有多個) + getCurrentDeityLotTypes() { + const deity = this.getCurrentDeity() + // 若未設定則回傳空陣列,避免錯誤 + return deity?.lotTypes ?? [] + } + // 計算擲筊概率(考慮運勢和好感度) calculateJiaobeiProbabilities() { const state = this.petSystem.getState() const deity = this.getCurrentDeity() - // 動態載入配置(同步) - // 基礎概率 let { holy, laughing, negative } = JIAOBEI_CONFIG.baseProbability diff --git a/data/achievements.js b/data/achievements.js new file mode 100644 index 0000000..da30edc --- /dev/null +++ b/data/achievements.js @@ -0,0 +1,433 @@ +// 成就系統配置 +// 每個成就包含:id, name, description, condition, reward + +export const ACHIEVEMENTS = [ + // ========== 成長類成就 ========== + { + id: 'first_step', + name: '第一步', + description: '寵物年齡達到 1 小時', + category: 'growth', + condition: { + type: 'age', + value: 3600 // 1 小時(秒) + }, + reward: { + buffs: { + strGain: 0.05, // 力量成長 +5% + intGain: 0.05 // 智力成長 +5% + } + }, + icon: '👶' + }, + { + id: 'one_day_old', + name: '一日之計', + description: '寵物年齡達到 1 天', + category: 'growth', + condition: { + type: 'age', + value: 86400 // 1 天(秒) + }, + reward: { + buffs: { + strGain: 0.10, + intGain: 0.10, + dexGain: 0.10, + luck: 2 // 運勢 +2 + } + }, + icon: '📅' + }, + { + id: 'evolved_baby', + name: '破殼而出', + description: '從蛋階段進化到幼體', + category: 'growth', + condition: { + type: 'stage', + value: 'baby' + }, + reward: { + buffs: { + health: 5, // 最大健康 +5 + strGain: 0.05 + } + }, + icon: '🥚' + }, + { + id: 'evolved_child', + name: '茁壯成長', + description: '進化到幼年階段', + category: 'growth', + condition: { + type: 'stage', + value: 'child' + }, + reward: { + buffs: { + health: 10, + strGain: 0.10, + intGain: 0.10 + } + }, + icon: '🌱' + }, + { + id: 'evolved_adult', + name: '成年禮', + description: '進化到成年階段', + category: 'growth', + condition: { + type: 'stage', + value: 'adult' + }, + reward: { + buffs: { + health: 20, + strGain: 0.15, + intGain: 0.15, + dexGain: 0.15, + luck: 5 + } + }, + icon: '🎂' + }, + { + id: 'perfect_stats', + name: '完美屬性', + description: '力量、智力、敏捷都達到 50', + category: 'growth', + condition: { + type: 'stats', + stats: { + str: 50, + int: 50, + dex: 50 + } + }, + reward: { + buffs: { + str: 3, + int: 3, + dex: 3, + attack: 0.10, // 攻擊力 +10% + defense: 0.10 // 防禦力 +10% + } + }, + icon: '⭐' + }, + { + id: 'max_stats', + name: '屬性巔峰', + description: '力量、智力、敏捷都達到 100', + category: 'growth', + condition: { + type: 'stats', + stats: { + str: 100, + int: 100, + dex: 100 + } + }, + reward: { + buffs: { + str: 10, + int: 10, + dex: 10, + luck: 10, + attack: 0.20, + defense: 0.20, + speed: 0.20 + } + }, + icon: '💎' + }, + + // ========== 互動類成就 ========== + { + id: 'first_feed', + name: '初次餵食', + description: '第一次餵食寵物', + category: 'interaction', + condition: { + type: 'action_count', + action: 'feed', + value: 1 + }, + reward: { + buffs: { + strGain: 0.03 + } + }, + icon: '🍼' + }, + { + id: 'caretaker', + name: '照顧者', + description: '累計餵食 50 次', + category: 'interaction', + condition: { + type: 'action_count', + action: 'feed', + value: 50 + }, + reward: { + buffs: { + strGain: 0.10, + healthRecovery: 0.05 + } + }, + icon: '🍽️' + }, + { + id: 'playful_master', + name: '玩耍大師', + description: '累計玩耍 100 次', + category: 'interaction', + condition: { + type: 'action_count', + action: 'play', + value: 100 + }, + reward: { + buffs: { + dexGain: 0.15, + intGain: 0.10, + happinessRecovery: 0.10 + } + }, + icon: '🎮' + }, + { + id: 'clean_freak', + name: '清潔達人', + description: '累計清理便便 30 次', + category: 'interaction', + condition: { + type: 'action_count', + action: 'clean', + value: 30 + }, + reward: { + buffs: { + health: 5, + sicknessReduction: 0.10 // 生病抗性 +10% + } + }, + icon: '🧹' + }, + { + id: 'healer', + name: '治療師', + description: '累計治療 20 次', + category: 'interaction', + condition: { + type: 'action_count', + action: 'heal', + value: 20 + }, + reward: { + buffs: { + healthRecovery: 0.15, + health: 10 + } + }, + icon: '💊' + }, + + // ========== 神明類成就 ========== + { + id: 'first_prayer', + name: '初次祈福', + description: '第一次向神明祈福', + category: 'temple', + condition: { + type: 'action_count', + action: 'pray', + value: 1 + }, + reward: { + buffs: { + luck: 1 + } + }, + icon: '🙏' + }, + { + id: 'devout', + name: '虔誠信徒', + description: '累計祈福 50 次', + category: 'temple', + condition: { + type: 'action_count', + action: 'pray', + value: 50 + }, + reward: { + buffs: { + luck: 5, + happinessRecovery: 0.05 + } + }, + icon: '🕯️' + }, + { + id: 'deity_friend', + name: '神明之友', + description: '任一神明好感度達到 50', + category: 'temple', + condition: { + type: 'deity_favor', + value: 50 + }, + reward: { + buffs: { + luck: 3, + healthRecovery: 0.05 + } + }, + icon: '👼' + }, + { + id: 'deity_best_friend', + name: '神明摯友', + description: '任一神明好感度達到 100', + category: 'temple', + condition: { + type: 'deity_favor', + value: 100 + }, + reward: { + buffs: { + luck: 10, + healthRecovery: 0.10, + happinessRecovery: 0.05 + } + }, + icon: '🌟' + }, + { + id: 'fortune_teller', + name: '求籤達人', + description: '累計抽籤 10 次', + category: 'temple', + condition: { + type: 'action_count', + action: 'drawFortune', + value: 10 + }, + reward: { + buffs: { + luck: 3, + dropRate: 0.05 // 掉落率 +5% + } + }, + icon: '🎴' + }, + + // ========== 事件類成就 ========== + { + id: 'event_explorer', + name: '事件探索者', + description: '觸發 20 個事件', + category: 'event', + condition: { + type: 'event_count', + value: 20 + }, + reward: { + buffs: { + luck: 2, + dropRate: 0.03 + } + }, + icon: '🔍' + }, + { + id: 'lucky_one', + name: '幸運兒', + description: '觸發 5 個好事件', + category: 'event', + condition: { + type: 'event_type_count', + eventType: 'good', + value: 5 + }, + reward: { + buffs: { + luck: 5, + happinessRecovery: 0.05 + } + }, + icon: '🍀' + }, + + // ========== 特殊類成就 ========== + { + id: 'survivor', + name: '倖存者', + description: '從瀕死狀態恢復健康', + category: 'special', + condition: { + type: 'recovered_from_dying', + value: true + }, + reward: { + buffs: { + health: 15, + healthRecovery: 0.20, + sicknessReduction: 0.15 + } + }, + icon: '💪' + }, + { + id: 'perfect_day', + name: '完美的一天', + description: '飢餓、快樂、健康同時達到 100', + category: 'special', + condition: { + type: 'perfect_state', + value: true + }, + reward: { + buffs: { + strGain: 0.05, + intGain: 0.05, + dexGain: 0.05, + happinessRecovery: 0.05 + } + }, + icon: '✨' + }, + { + id: 'night_owl', + name: '夜貓子', + description: '累計睡眠 50 次', + category: 'special', + condition: { + type: 'action_count', + action: 'sleep', + value: 50 + }, + reward: { + buffs: { + health: 10, + healthRecovery: 0.10 + } + }, + icon: '🌙' + } +] + +// 成就分類 +export const ACHIEVEMENT_CATEGORIES = { + growth: { name: '成長', icon: '📈' }, + interaction: { name: '互動', icon: '🤝' }, + temple: { name: '神明', icon: '🙏' }, + event: { name: '事件', icon: '🎲' }, + special: { name: '特殊', icon: '⭐' } +} + diff --git a/data/events.js b/data/events.js index d93fff3..fe30949 100644 --- a/data/events.js +++ b/data/events.js @@ -50,6 +50,23 @@ export const EVENT_CONFIG = [ { type: 'logMessage', payload: '感受到神明的祝福,寵物精神煥發!' } ] }, + { + id: 'find_item', + type: 'good', + weight: 0.2, + condition: (state) => state.luck > 15, + conditionDescription: '需要:運勢 > 15', + effects: [ + { + type: 'addItem', + payload: { + itemId: 'cookie', // 預設掉落餅乾,可以改為隨機 + count: 1 + } + }, + { type: 'logMessage', payload: '寵物發現了一個道具!' } + ] + }, { id: 'rare_treasure', type: 'rare', diff --git a/data/items.js b/data/items.js index d25903d..49749a6 100644 --- a/data/items.js +++ b/data/items.js @@ -1,39 +1,399 @@ -// 道具配置 +// 道具配置系統 +// 道具類型:equipment(裝備)、appearance(外觀)、consumable(消耗品)、talisman(護身符)、special(特殊) + export const ITEMS = { + // ========== 裝備類(有耐久度)========== + + // 武器類 + wooden_sword: { + id: 'wooden_sword', + name: '木劍', + type: 'equipment', + category: 'weapon', + slot: 'weapon', + rarity: 'common', + dropRate: 0.50, // 掉落機率 50% + durability: 100, // 最大耐久度 + maxDurability: 100, + effects: { + flat: { attack: 5 }, + percent: { attack: 0.05 } // 攻擊力 +5% + }, + description: '基礎木製武器,增加攻擊力', + icon: '⚔️', + appearance: null // 武器不改變外觀 + }, + + iron_sword: { + id: 'iron_sword', + name: '鐵劍', + type: 'equipment', + category: 'weapon', + slot: 'weapon', + rarity: 'uncommon', + dropRate: 0.30, // 掉落機率 30% + durability: 200, + maxDurability: 200, + effects: { + flat: { attack: 15, str: 3 }, + percent: { attack: 0.10 } + }, + description: '堅固的鐵製武器,大幅增加攻擊力', + icon: '🗡️', + appearance: null + }, + + magic_staff: { + id: 'magic_staff', + name: '魔法杖', + type: 'equipment', + category: 'weapon', + slot: 'weapon', + rarity: 'rare', + dropRate: 0.15, // 掉落機率 15% + durability: 150, + maxDurability: 150, + effects: { + flat: { attack: 10, int: 5 }, + percent: { attack: 0.08, intGain: 0.10 } + }, + description: '蘊含魔力的法杖,增加智力和智力成長', + icon: '🪄', + appearance: null + }, + + // 防具類 + leather_armor: { + id: 'leather_armor', + name: '皮甲', + type: 'equipment', + category: 'armor', + slot: 'armor', + rarity: 'common', + dropRate: 0.50, // 掉落機率 50% + durability: 120, + maxDurability: 120, + effects: { + flat: { defense: 8, health: 10 }, + percent: { defense: 0.05 } + }, + description: '輕便的皮製護甲,增加防禦力和最大健康', + icon: '🛡️', + appearance: null + }, + + iron_armor: { + id: 'iron_armor', + name: '鐵甲', + type: 'equipment', + category: 'armor', + slot: 'armor', + rarity: 'uncommon', + dropRate: 0.30, // 掉落機率 30% + durability: 250, + maxDurability: 250, + effects: { + flat: { defense: 20, health: 20 }, + percent: { defense: 0.15 } + }, + description: '厚重的鐵製護甲,大幅增加防禦力', + icon: '⚔️', + appearance: null + }, + + // ========== 外觀類(無耐久,不壞)========== + + cute_hat: { + id: 'cute_hat', + name: '可愛帽子', + type: 'appearance', + category: 'hat', + slot: 'hat', + rarity: 'common', + durability: Infinity, // 外觀類永不損壞 + maxDurability: Infinity, + effects: { + flat: { happiness: 5 } // 外觀類可以有小加成 + }, + description: '可愛的帽子,讓寵物看起來更萌', + icon: '🎩', + appearance: { + hat: 'cute_hat' + } + }, + + cool_sunglasses: { + id: 'cool_sunglasses', + name: '酷炫墨鏡', + type: 'appearance', + category: 'accessory', + slot: 'accessory', + rarity: 'uncommon', + durability: Infinity, + maxDurability: Infinity, + effects: { + percent: { happinessRecovery: 0.10, dex: 2 } + }, + description: '超酷的墨鏡,增加快樂恢復和敏捷', + icon: '🕶️', + appearance: { + accessory: 'cool_sunglasses' + } + }, + + red_scarf: { + id: 'red_scarf', + name: '紅色圍巾', + type: 'appearance', + category: 'accessory', + slot: 'accessory', + rarity: 'common', + durability: Infinity, + maxDurability: Infinity, + effects: {}, + description: '溫暖的紅色圍巾,純外觀道具', + icon: '🧣', + appearance: { + accessory: 'red_scarf' + } + }, + + // ========== 消耗品類 ========== + cookie: { id: 'cookie', name: '幸運餅乾', type: 'consumable', - effects: { modifyStats: { hunger: +20, happiness: +10 } }, - description: '增加飢餓和快樂' + category: 'food', + rarity: 'common', + stackable: true, + effects: { + modifyStats: { hunger: 20, happiness: 10 } + }, + description: '美味的餅乾,增加飢餓和快樂', + icon: '🍪' }, - water: { - id: 'water', - name: '神水', + + health_potion: { + id: 'health_potion', + name: '治療藥水', type: 'consumable', - effects: { modifyStats: { health: +15, happiness: +5 } }, - description: '恢復健康' + category: 'potion', + rarity: 'common', + stackable: true, + effects: { + modifyStats: { health: 30 }, + cureSickness: true + }, + description: '恢復健康並治癒疾病', + icon: '🧪' }, - amulet: { - id: 'amulet', + + energy_drink: { + id: 'energy_drink', + name: '能量飲料', + type: 'consumable', + category: 'potion', + rarity: 'uncommon', + stackable: true, + effects: { + modifyStats: { happiness: 20 }, + addBuff: { + id: 'energized', + name: '精力充沛', + durationTicks: 10, // 持續 10 ticks + flat: { dex: 5 }, + percent: { speed: 0.10 } + } + }, + description: '提供臨時速度和敏捷加成', + icon: '🥤' + }, + + growth_pill: { + id: 'growth_pill', + name: '成長藥丸', + type: 'consumable', + category: 'potion', + rarity: 'rare', + stackable: true, + effects: { + modifyStats: { str: 1, int: 1, dex: 1 } + }, + description: '永久增加力量、智力、敏捷各 1 點', + icon: '💊' + }, + + // ========== 護身符類(永久加成)========== + + lucky_amulet: { + id: 'lucky_amulet', + name: '幸運護身符', + type: 'talisman', + category: 'talisman', + slot: 'talisman', + rarity: 'uncommon', + durability: Infinity, + maxDurability: Infinity, + effects: { + flat: { luck: 5 }, + percent: { dropRate: 0.10 } + }, + description: '帶來好運的護身符,增加運勢和掉落率', + icon: '🔮' + }, + + protection_amulet: { + id: 'protection_amulet', name: '平安符', - type: 'equipment', - effects: { addBuff: { id: 'amulet_protection', name: '平安符保護', durationTicks: Infinity, flat: { health: 20 } } }, - description: '永久增加健康上限' + type: 'talisman', + category: 'talisman', + slot: 'talisman', + rarity: 'rare', + durability: Infinity, + maxDurability: Infinity, + effects: { + flat: { health: 20 }, + percent: { sicknessReduction: 0.20, healthRecovery: 0.15 } + }, + description: '保佑平安的護身符,增加健康上限和恢復效率', + icon: '🛡️' }, - sunglasses: { - id: 'sunglasses', - name: '酷酷墨鏡', - type: 'equipment', - effects: { addBuff: { id: 'cool', name: '酷炫', durationTicks: Infinity, percent: { happiness: 0.1 } } }, - description: '配戴時增加快樂 10%' + + wisdom_amulet: { + id: 'wisdom_amulet', + name: '智慧護身符', + type: 'talisman', + category: 'talisman', + slot: 'talisman', + rarity: 'rare', + durability: Infinity, + maxDurability: Infinity, + effects: { + flat: { int: 5 }, + percent: { intGain: 0.15, happinessRecovery: 0.10 } + }, + description: '提升智慧的護身符,增加智力和智力成長', + icon: '📿' }, + + // ========== 特殊道具類 ========== + training_manual: { id: 'training_manual', name: '訓練手冊', + type: 'special', + category: 'book', + slot: 'special', + rarity: 'uncommon', + durability: Infinity, + maxDurability: Infinity, + effects: { + percent: { strGain: 0.15, dexGain: 0.15 } + }, + description: '訓練指南,增加力量和敏捷成長效率', + icon: '📖' + }, + + time_crystal: { + id: 'time_crystal', + name: '時間水晶', + type: 'special', + category: 'crystal', + slot: 'special', + rarity: 'legendary', + durability: Infinity, + maxDurability: Infinity, + effects: { + percent: { + strGain: 0.10, + intGain: 0.10, + dexGain: 0.10, + happinessRecovery: 0.10, + healthRecovery: 0.10 + } + }, + description: '神秘的水晶,全面提升成長和恢復效率', + icon: '💎' + }, + + // ========== 永久裝備(不會壞)========== + + golden_crown: { + id: 'golden_crown', + name: '黃金王冠', type: 'equipment', - effects: { addBuff: { id: 'training', name: '訓練加成', durationTicks: Infinity, percent: { str: 0.15, dex: 0.15 } } }, - description: '配戴時增加力量和敏捷成長' + category: 'crown', + slot: 'hat', + rarity: 'legendary', + durability: Infinity, // 永久裝備 + maxDurability: Infinity, + effects: { + flat: { str: 10, int: 10, dex: 10, luck: 10 }, + percent: { attack: 0.20, defense: 0.20, speed: 0.20 } + }, + description: '傳說中的黃金王冠,全面提升所有屬性', + icon: '👑', + appearance: { + hat: 'golden_crown' + } } } +// 道具類型定義 +export const ITEM_TYPES = { + equipment: { name: '裝備', icon: '⚔️' }, + appearance: { name: '外觀', icon: '👕' }, + consumable: { name: '消耗品', icon: '🍪' }, + talisman: { name: '護身符', icon: '🔮' }, + special: { name: '特殊', icon: '⭐' } +} + +// 稀有度定義(資料檔保持英文 key,但 name 為中文顯示用) +export const ITEM_RARITY = { + common: { + name: '普通', + color: '#9d9d9d', + multiplier: 1.0, + dropRate: 0.50, // 50% 基礎掉落機率 + description: '最常見的道具,容易獲得' + }, + uncommon: { + name: '優秀', + color: '#1eff00', + multiplier: 1.2, + dropRate: 0.30, // 30% 基礎掉落機率 + description: '較為少見的道具,有一定價值' + }, + rare: { + name: '稀有', + color: '#0070dd', + multiplier: 1.5, + dropRate: 0.15, // 15% 基礎掉落機率 + description: '稀有的道具,效果顯著' + }, + epic: { + name: '史詩', + color: '#a335ee', + multiplier: 2.0, + dropRate: 0.05, // 5% 基礎掉落機率 + description: '史詩級道具,非常珍貴' + }, + legendary: { + name: '傳說', + color: '#ff8000', + multiplier: 3.0, + dropRate: 0.01, // 1% 基礎掉落機率 + description: '傳說級道具,極其稀有且強大' + } +} + +// 裝備槽位定義 +export const EQUIPMENT_SLOTS = { + weapon: { name: '武器', icon: '⚔️' }, + armor: { name: '防具', icon: '🛡️' }, + hat: { name: '帽子', icon: '🎩' }, + accessory: { name: '飾品', icon: '💍' }, + talisman: { name: '護身符', icon: '🔮' }, + special: { name: '特殊', icon: '⭐' } +} diff --git a/liushijiazi_60_lot.json b/liushijiazi_60_lot.json new file mode 100644 index 0000000..9077226 --- /dev/null +++ b/liushijiazi_60_lot.json @@ -0,0 +1,722 @@ +[ + { + "id": 1, + "no": "第一籤【甲子】", + "grade": "", + "palace": "", + "poem1": "日出便見風雲散\n光明清淨照世間\n一向前途通大道\n萬事清吉保平安", + "poem2": "", + "meaning": "", + "explanation": "凡事 大吉昌。\n作事 難成。成者大吉。\n家事 無憂。\n家運 平安大吉。\n婚姻 允成。\n求兒 大吉。\n六甲 頭胎男。二胎女。\n求財 先大進。後小利。\n功名 望後有成。\n歲君 清吉。\n治病 未日(半月)痊安。\n出外 平安。\n經商 如意。\n來人 月光在。\n行舟 有大財。\n移居 得安。\n失物 在東急尋能還。\n求雨 尚未。\n官事 理斷分明。\n六畜 好。\n耕作 甚得利。\n築室 清吉光明。\n墳墓 地穴大吉。\n討海 漸漸得利。\n作塭 大吉利。\n魚苗 不畏。\n月令 遂意。\n尋人 得回。\n遠信 速至。", + "oracle": "", + "story": "1.包公請雷驚仁宗\n2.包文極審張世真" + }, + { + "id": 2, + "no": "第二籤【甲寅】", + "grade": "", + "palace": "", + "poem1": "於今此景正當時\n看看欲吐百花魁\n若能遇得春色到\n一洒清吉脫塵埃\n於今此景正當時\n看看欲吐百花魁\n若能遇得春色到\n一酒清吉脫塵埃", + "poem2": "", + "meaning": "", + "explanation": "凡事 春天到。\n作事 春成美。冬不佳。\n家事 必得進益。\n家運 福祉茂盛。\n婚姻 永偕伉儷。\n求兒 適宜。\n六甲 生男。\n求財 如泉湧。(先有後無)\n功名 二次成。秋進連中。\n歲君 中和。\n治病 老不好。少平安。\n出外 春夏好。秋冬呆。\n經商 大吉利市。\n來人 南方。\n行舟 有大財。\n移居 平平。(不可)\n失物 謹尋在。遲者無。\n求雨 甲子日得有。\n官事 完局。\n六畜 興旺大利。\n耕作 春季如意。\n築室 大吉。\n墳墓 光前裕後。\n討海 春有冬無。\n作塭 可慶獲利。\n魚苗 大利。\n月令 不畏。\n尋人 南方。\n遠信 春天到。", + "oracle": "", + "story": "1.趙子龍救阿斗\n三國。趙雲。字子龍。常山人。初依袁紹。後從劉先主。\n時曹操欲下江南。先攻先主於莘野。先主走樊城。\n復敗於當陽。家眷失散。雲於土暀U遇縻夫人。\n夫人將子阿斗托雲。雲將馬授夫人。夫人不肯授。\n投井而死。雲哭埋畢。懷抱阿斗。殺出重圍。\n2.陳東初祭梅得救\n3.薛交薛癸旁州遇採樓得繡球" + }, + { + "id": 3, + "no": "第三籤【甲辰】", + "grade": "", + "palace": "", + "poem1": "勸君把定心莫虛\n天註衣祿自有餘\n和合重重常吉慶\n時來終遇得明珠\n衣祿二字,另有改作姻緣一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 吉。\n作事 二次成。\n家事 餘興且喜。\n家運 和氣。後得祥瑞。\n婚姻 大吉。\n求兒 吉。\n六甲 先男後女。\n求財 後遇貴人大興。\n功名 後科連登。尾有。\n歲君 安和。\n治病 命不畏。平安。\n出外 向南方遇貴人。\n經商 先利平。後大財。\n來人 立即到。\n行舟 漸得大財。\n移居 得安\n失物 月光必在。\n求雨 過日自有。\n官事 不畏。破財。完局。\n六畜 可納。\n耕作 下冬好。\n築室 大吉。\n墳墓 永裕後崑。\n討海 晚有大利。\n作塭 和者必獲厚利。\n魚苗 後得大利。\n月令 漸得春風。\n尋人 得回。\n遠信 守候佳音。", + "oracle": "", + "story": "1.朱德武入寺相分明\n2.摧文德胡鳳嬌到家空成婚" + }, + { + "id": 4, + "no": "第四籤【甲午】", + "grade": "", + "palace": "", + "poem1": "風恬浪靜可行舟\n恰是中秋月一輪\n凡事不須多憂慮\n福祿自有慶家門", + "poem2": "", + "meaning": "", + "explanation": "凡事 成者大吉。\n作事 有成。\n家事 綿綿齊輝。\n家運 大獲吉昌。\n婚姻 和諧。月半成。\n求兒 好。\n六甲 先男後女。\n求財 在家好。出外凶。\n功名 顯祖榮宗。\n歲君 平安。\n治病 近日痊癒。\n出外 求財求事如意。\n經商 大吉利。\n來人 即到。\n行舟 風平。大吉。\n移居 可慶。\n失物 月光在。\n求雨 月末即到。\n官事 破財。求貴人解。\n六畜 興盛。\n耕作 有收。\n築室 門庭興旺。\n墳墓 可得瑞氣。\n討海 有大財。\n作塭 有望。\n魚苗 月光好。\n月令 好。\n尋人 快遇。\n遠信 遲到。", + "oracle": "", + "story": "1.趙子龍救阿斗\n三國。趙雲。字子龍。常山人。初依袁紹。後從劉先主。\n時曹操欲下江南。先攻先主於莘野。先主走樊城。\n復敗於當陽。家眷失散。雲於土暀U遇縻夫人。\n夫人將子阿斗托雲。雲將馬授夫人。夫人不肯授。\n投井而死。雲哭埋畢。懷抱阿斗。殺出重圍。\n2.盧龍王次子招親\n盧字,另有作廬字一說。" + }, + { + "id": 5, + "no": "第五籤", + "grade": "", + "palace": "甲申", + "poem1": "兒恐前途命有變\n勸君作急可宜先\n且守長江無大事\n命逢太白守身邊\n只恐前途命有變\n勸君作急可宜先\n且守長江無大事\n命逢太白守身邊\n命字,另有作明字一說。\n太白,指太白金星神。", + "poem2": "", + "meaning": "", + "explanation": "凡事 待時機。\n作事 顛倒。前凶後吉。\n家事 有貴人。團圓。\n家運 先被邪。後吉祥。\n婚姻 多口舌。不吉。\n求兒 不佳。\n六甲 頭胎生女次生男。(先女后女)\n求財 以待時來。(不吉)\n功名 必遇。防徼。\n歲君 平安。\n治病 月光癒。暗不吉。\n出外 下半年好。\n經商 先利。後遇貴人。\n來人 遲後到。\n行舟 出外有風波災。\n移居 不好。\n失物 謹尋在。遲即無。\n求雨 朝夕即有。\n官事 宜和拖尾。(被官欺。后完明)\n六畜 不祥。\n耕作 內有不足。\n築室 不吉。\n墳墓 先平後得佳氣。\n討海 邪病先輕後好。\n作塭 先難後得。\n魚苗 先無後有。\n月令 淡淡。\n尋人 待慢。\n遠信 必阻遲至。", + "oracle": "", + "story": "1.韓文公過秦嶺遇霜雪凍\n韓愈。字退之。昌黎人。唐德宗貞元八年進士。諡文公。\n因諫迎佛骨。獨怒天子。貶至潮州刺史。\n途經藍關。大雪封山。韓嘆皇上不殺我。皇天亡我矣。\n有曰\n雲橫秦嶺家何在。雪擁藍關馬不前。\n2.王剪戰袁達" + }, + { + "id": 6, + "no": "第六籤【甲戌】", + "grade": "", + "palace": "", + "poem1": "風雲致雨落洋洋\n天災時氣必有傷\n命內此事難和合\n更逢一足出外鄉", + "poem2": "", + "meaning": "", + "explanation": "凡事 待望。\n作事 不成局。\n家事 家庭相爭。\n家運 有怪必防。\n婚姻 不宜。\n求兒 不可。\n六甲 男高貴。晚投枝。\n求財 空有。\n功名 難望。\n歲君 破財。27月令不吉。\n治病 邪作病。險不吉。\n出外 無貴人。\n經商 財本耗散。\n來人 月光即到。\n行舟 不好。\n移居 且慢。\n失物 運如此。路難逢。\n求雨 不到則久。\n官事 了錢。拖尾。\n六畜 不佳。\n耕作 無收。\n築室 犯凶星。\n墳墓 地運不佳。\n討海 邪祟不利。\n作塭 失利。\n魚苗 失利了錢。\n月令 不遂。\n尋人 遲遇。\n遠信 無望。", + "oracle": "", + "story": "1.烏精亂宋朝\n烏字,另有改作鳥字一說。\n烏精或指烏靈聖母。她是東晉時沙賈使君之女。\n秀才慎郎(蛟精所變)入贅賈府。賈女亦變蛟。\n生三子(兩子被許真君斬)。餘子修成虯龍(轉世秦檜)。\n烏靈聖母欲報殺子之仇。和兀朮合作滅宋。\n(見岳飛傳。清。錢彩著。01/73/79)\n「鳥精亂宋朝」在台灣傳統歌仔戲中的戲名為《觀音收大鵬》,是廟會中常演出的戲碼。劇情描述宋朝仁宗時期,觀世音菩薩身邊的大鵬鳥,幻化成人形,到人間作亂,天災人禍頻傳,民不聊生,最後觀世音菩薩下凡,收服大鵬鳥,為人民解患。\n故事內容有一切都會化險為夷的寓意。\n資料來源\n2.劉志遠戰瓜精。(劉志遠投軍)\n劉志遠與妻李三娘居舅家。舅嫌其貧。\n哄志遠往瓜園。欲給二瓜精吃掉。\n志遠夜持鎗。戰瓜精走入地。掘開見劍。\n拾之辭妻投軍。後得天下。" + }, + { + "id": 7, + "no": "第七籤【乙丑】", + "grade": "", + "palace": "", + "poem1": "雲開月出正分明\n不須進退問前程\n婚姻皆由天註定\n和合清吉萬事成\n正字,另有改作見字一說。\n問字,另有改作向字一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 後成。\n作事 月光成。\n家事 冒險。平安。\n家運 漸漸平安。\n婚姻 月光成。暗不成。\n求兒 好。\n六甲 定必生女。\n求財 有成。\n功名 少有成。老無。\n歲君 好。\n治病 女平。男晚好。少險。老不畏。\n出外 滿路異香。\n經商 成者大吉。\n來人 月中到。\n行舟 須當先防。\n移居 不吉。\n失物 月光在。月暗無\n求雨 初無。月尾有。\n官事 破財。完局。\n六畜 興旺。\n耕作 有收。\n築室 月中好。\n墳墓 地勢甚美。\n討海 合和吉。不合凶。\n作塭 須防風水。\n魚苗 月中吉。\n月令 淡淡。\n尋人 月中遇。\n遠信 可喜。", + "oracle": "", + "story": "1.國公暗察白袍將\n國公暗察,另有改作包公暗訪一說。\n2.尉遲恭掛帥" + }, + { + "id": 8, + "no": "第八籤【乙卯】", + "grade": "", + "palace": "", + "poem1": "禾稻看看結成完\n此事必定兩相全\n回到家中寬心坐\n妻兒鼓舞樂團圓\n鼓舞,另有改作皷腹一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 和者得。不和失。\n作事 先難後興。\n家事 進益團美。\n家運 平安。\n婚姻 成。大吉。兩全其美。\n求兒 吉。\n六甲 先男後女。\n求財 下半年好。家利。\n功名 二次得進。\n歲君 和氣。\n治病 少不畏。老不好。\n出外 不可。\n經商 有利必得。\n來人 速到。\n行舟 得財。\n移居 大吉。\n失物 速尋必在。\n求雨 月尾即有。\n官事 二次完明。了財。\n六畜 大吉。\n耕作 下半年有收成。\n築室 居中。(鼓員固美)\n墳墓 地運有合。\n討海 好。\n作塭 允收。\n魚苗 大利。\n月令 破財。下年不畏。(和氣)\n尋人 速至。\n遠信 速至。", + "oracle": "", + "story": "1.薛仁貴回家\n唐朝時代。薛仁貴征東。得勝回朝。封王而歸家。\n當時秋將冷。雁南飛。紅葉凋謝。人洗寒衣。此秋天冷落之景象。\n2.朱并(幷)回家" + }, + { + "id": 9, + "no": "第九籤【乙巳】", + "grade": "", + "palace": "", + "poem1": "龍虎相隨在深山\n君爾何須背後看\n不知此去相愛愉\n他日與我卻無干\n愉字,另有改作娛字一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 謹慎。\n作事 守己安分。\n家事 無有際會。\n家運 有邪。難安。\n婚姻 不可。\n求兒 切要不可。\n六甲 子媳虛。\n求財 無益。\n功名 不取。\n歲君 不吉。\n治病 運深危險。寅辰日過不畏。\n出外 不可。\n經商 了錢。\n來人 未日(半月)到。\n行舟 不美。\n移居 不佳。\n失物 難尋。\n求雨 尚未。自有。\n官事 不可。破財。\n六畜 不可納。\n耕作 無收。了工。\n築室 且慢也可。\n墳墓 地勢適當。\n討海 有犯邪祟。\n作塭 了工蝕本。\n魚苗 了錢。\n月令 破財有口舌。\n尋人 漸回。\n遠信 無望。", + "oracle": "", + "story": "龍虎爭鬥(龍虎相會)" + }, + { + "id": 10, + "no": "第十籤【乙未】", + "grade": "", + "palace": "", + "poem1": "花開結子一半枯\n可惜今年汝虛度\n漸漸日落西山去\n勸君不用向前途", + "poem2": "", + "meaning": "", + "explanation": "凡事 拖尾。難解難脫。\n作事 難成。\n家事 恐防短壽。\n家運 難安。\n婚姻 不可。難成。\n求兒 不可。\n六甲 子媳難得\n求財 上半年空破財。九月過不畏。\n功名 枉費。難得。\n歲君 不順。\n治病 月半安。月尾死。\n出外 不可。\n經商 不好。了錢。\n來人 月底間。\n行舟 謹慎無害。\n移居 不允。\n失物 難尋。\n求雨 朝夕即到。\n官事 大了錢。不好。\n六畜 不吉。\n耕作 五分平平。\n築室 有災星。\n墳墓 地犯退敗。必遷。\n討海 全無。不好。\n作塭 無望。蝕本。\n魚苗 得失。\n月令 難通。\n尋人 月尾回。\n遠信 難至。", + "oracle": "", + "story": "1.岳飛掠秦檜\n岳飛本為大鵬轉世。秦檜本為鐵背虯龍轉世。\n昔大鵬認出虯龍仍妖精。故啄虯龍左眼。\n血流披面(眼瞎)。逃入黃河。\n後虯龍轉世為秦檜。報此前仇。\n(見岳飛傳。清。錢彩著。01/73/79)\n2.奉吟受災。" + }, + { + "id": 11, + "no": "第十一籤【乙酉】", + "grade": "", + "palace": "", + "poem1": "靈雞漸漸見分明\n凡事且看子丑寅\n雲開月出照天下\n郎君即便見太平", + "poem2": "", + "meaning": "", + "explanation": "凡事 作不和。子錢安。\n作事 子丑寅日必成。\n家事 平好。\n家運 漸漸得居春風。\n婚姻 終成。\n求兒 不可。(可也)\n六甲 先男。貴氣。(子媳缺)\n求財 漸漸有收。\n功名 費了工。八月好。\n歲君 順吉。\n治病 大命不好。子丑寅日過不畏。\n出外 子丑寅日可行。\n經商 不利。\n來人 近日到。\n行舟 不可。\n移居 平安。(子丑寅日抽好)\n失物 子丑寅日尋在。\n求雨 近有。\n官事 有人和吉。三月完局。\n六畜 可納。\n耕作 半收。\n築室 好。\n墳墓 平平。\n討海 前呆后微。\n作塭 小收微利。\n魚苗 小利。\n月令 不畏。\n尋人 牛虎日。\n遠信 牛虎日。", + "oracle": "", + "story": "1.韓文公過秦嶺湘子掃霜雪\n韓愈。字退之。昌黎人。唐德宗貞元八年進士。諡文公。\n因諫迎佛骨。獨怒天子。貶至潮州刺史。\n途經藍關。大雪封山。韓嘆皇上不殺我。皇天亡我矣。\n有曰雲橫秦嶺家何在。雪擁藍關馬不前。\n韓湘子(八仙之一)曰。叔父休驚。解下佩劍一指。路上大雪溶化。給韓愈開路。\n2.高求楊戩?權" + }, + { + "id": 12, + "no": "第十二籤【乙亥】", + "grade": "", + "palace": "", + "poem1": "長江風浪漸漸靜\n于今得進可安寧\n必有貴人相扶助\n凶事脫出見太平", + "poem2": "", + "meaning": "", + "explanation": "凡事 月光好。\n作事 進行有利。\n家事 光耀門閭。\n家運 漸安。\n婚姻 可合成者吉。\n求兒 吉。\n六甲 先男高貴。\n求財 好運。得意。\n功名 難得。\n歲君 順吉。\n治病 月光好。老不痊。\n出外 有貴人扶。\n經商 大吉。\n來人 近日到。\n行舟 大吉。\n移居 平正。\n失物 急尋在。遲難尋。\n求雨 遠。\n官事 了錢。求貴人脫。\n六畜 可納。\n耕作 平平。\n築室 慢即可。\n墳墓 地勢有合。\n討海 微利后有。\n作塭 漸得如意。\n魚苗 中有利。\n月令 破財不遂。\n尋人 近日。\n遠信 速至。", + "oracle": "", + "story": "1.智遠戰瓜精\n(劉志遠戰瓜精、劉志遠投軍)\n劉志遠與妻李三娘居舅家。舅嫌其貧。\n哄志遠往瓜園。欲給二瓜精吃掉。\n志遠夜持鎗。戰瓜精走入地。掘開見劍。\n拾之辭妻投軍。後得天下。\n2.桃花女流勿太歲" + }, + { + "id": 13, + "no": "第十三籤【丙子】", + "grade": "", + "palace": "", + "poem1": "命中正逢羅孛關\n用盡心機總未休\n作福問神難得過\n恰是行舟上高灘\n羅孛為凶星(彗星)\n高灘為擱淺之意", + "poem2": "", + "meaning": "", + "explanation": "凡事 不吉\n作事 先難後興。\n家事 門庭起風波。\n家運 人不安。邪作祟。\n婚姻 難合。\n求兒 不可。\n六甲 臨產危險。\n求財 犯活鬼。下年無。\n功名 費工。望後得進。\n歲君 淡淡。(凶事不美)\n治病 犯(太歲)必死。未不畏。\n出外 不可。\n經商 失運。\n來人 難望。\n行舟 不順。失利。\n移居 不可\n失物 錢難尋。未日(半月)在。\n求雨 近日無。\n官事 大呆。\n六畜 不吉。\n耕作 小收。不利。\n築室 犯災星。\n墳墓 地勢不吉。\n討海 不好。無財。失利。\n作塭 防風水。失。虧本。\n魚苗 待機可以。\n月令 正月至六月止。\n尋人 難。免望。\n遠信 音息魚沉。", + "oracle": "", + "story": "1.三藏被紅孩兒燒\n唐三藏及豬八戒被紅孩兒捉去。要蒸吃唐僧肉。壽延千紀。\n孫悟空救師不果。唐三藏九死一生。最後才得觀音解圍。\n2.撐渡伯行舟遇太歲" + }, + { + "id": 14, + "no": "第十四籤【丙寅】", + "grade": "", + "palace": "", + "poem1": "財中漸漸見分明\n花開花謝結子成\n寬心且看月中桂\n郎君即便見太平", + "poem2": "", + "meaning": "", + "explanation": "凡事 大吉。\n作事 決意成功。\n家事 光前裕后。可喜。\n家運 平安。\n婚姻 成好。\n求兒 平正。\n六甲 先男後女。富貴。\n求財 月光進。漸暗少。\n功名 可喜。\n歲君 中和。\n治病 險。月光過不畏。\n出外 不可(必得貴人)。\n經商 漸得。\n來人 月尾到。\n行舟 月圓過大吉。\n移居 吉。(不可)\n失物 西方尋。(月光在。月暗無)\n求雨 月半無。月尾有。\n官事 破財後。完明。\n六畜 大吉。\n耕作 早晚有收成。\n築室 子孫永發其昌。\n墳墓 得其地。後大吉。\n討海 月光過。大吉。\n作塭 先微。後有大利。\n魚苗 大利。\n月令 頭破錢。後如意。\n尋人 月中至。\n遠信 速至。", + "oracle": "", + "story": "1.桃園三結義\n大丈夫(關公)以四海為家。何患乎吾無兄弟。\n入桃園。睹兩人奇異。請問英雄何處。\n雄紏紏。朗曰張飛。\n貌堂堂。溫言劉備。\n出生投地今逢主。須待挽天河水來蕩滌。誠哉龍虎風雲會。\n宰牛馬昭告天地。結義匡扶漢室。\n2.曹操賜雲祥馬袍贈金銀。" + }, + { + "id": 15, + "no": "第十五籤【丙辰】", + "grade": "", + "palace": "", + "poem1": "八十原來是太公\n看看晚景遇文王\n目下緊事休相問\n勸君且守待運通\n目字,另有改作月字一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 大破財。求解和。\n作事 難成。\n家事 平平。\n家運 平平。\n婚姻 配偶慢成。\n求兒 不可。\n六甲 先女後男。(先男後女)\n求財 晚即發。\n功名 難就。\n歲君 先平後吉。\n治病 求平安。十日險。\n出外 慢日可行。\n經商 漸且候時。\n來人 月尾有。\n行舟 不如意。有事。\n移居 待時。\n失物 緊尋得。遲者無。\n求雨 不日到。\n官事 不吉。求貴人和。\n六畜 漸且退步。\n耕作 無收。\n築室 漸且退步。\n墳墓 遲必發。\n討海 無財和者吉\n作塭 無望\n魚苗 且守慢至。\n月令 不遂。\n尋人 不可急。\n遠信 遲延。", + "oracle": "", + "story": "1.渭水河太公釣魚\n周。姜尚。字子牙。汲人。先世封於呂。亦曰呂望。\n避紂亂居東海之濱。釣於磻溪(渭水)。\n文王聞其賢。聘為師(丞相)。(其時年八十)\n後周伐紂。滅商興周。武王稱曰尚父。封其子丁公於齊。\n2.武吉挑柴打死人。(武吉遇師)\n武吉本是樵夫。姜子牙釣于磻溪。二人相遇。\n見子牙用直鉤釣魚大笑。子牙看武吉氣息斷曰。\n今日入城打死人。武吉怒別。擔柴入城。\n誤觸王相致死。文王畫地為牢。\n武吉後被暫釋。照顧老母至秋後正法。老母令其找姜子牙求救。\n太公收其為徒。授兵法。又令其挖坑施咒破解先天數。\n秋後不見武吉伏刑。文王演先天數。以為武吉已畏罪自殺。\n後文王碰見武吉。武吉引文王見姜太公。受封武德將軍。\n師徒二人為文王效力。\n(故事見于封神榜)\n故 事\n籤解一" + }, + { + "id": 16, + "no": "第十六籤【丙午】", + "grade": "", + "palace": "", + "poem1": "不須作福不須求\n用盡心機總未休\n陽世不知陰世事\n法官如爐不自由", + "poem2": "", + "meaning": "", + "explanation": "凡事 恐防風波災。\n作事 退步。\n家事 恐防有變。\n家運 陰邪。求神解決。\n婚姻 不合。有鬼作怪。\n求兒 不可。\n六甲 先男後女。(子媳虛)\n求財 春夏好秋冬呆。\n功名 難得。\n歲君 浮沉。\n治病 必危。有陰公作祟。未日(半月)過不畏。\n出外 防險。\n經商 難就。了錢。\n來人 遲慢。\n行舟 不如意。惹失。\n移居 不可。\n失物 難尋。(未日(半月)在)\n求雨 不日到。\n官事 緊防刑事。\n六畜 不可納。\n耕作 無收。\n築室 不可。\n墳墓 地勢不佳。\n討海 有陰鬼。難得。\n作塭 難如意。要忍耐。\n魚苗 失利難如意。\n月令 了錢。\n尋人 遲慢。\n遠信 必有失音。", + "oracle": "", + "story": "李世民遊地府\n唐太宗。李世民。因涇河鬼龍投訴世民曾許諾救他而沒救。\n閻王召世民下幽冥對案。由于鬼門關有入無出。須經過十殿至輪轉。\n超生貴道門而回陽。時歷三晝夜。王宮已把世民入棺。後破棺救出世民。\n太宗有感惡報之慘。于是大赦天下。四百死囚離獄。三千怨女出宮。\n(故事見于西遊記11回)" + }, + { + "id": 17, + "no": "第十七籤【丙申】", + "grade": "", + "palace": "", + "poem1": "舊恨重重未改為\n家中禍患不臨身\n須當謹防宜作福\n龍蛇交會得和合\n不▼或誤。連上句當作已。\n得■相", + "poem2": "", + "meaning": "", + "explanation": "凡事 人害緊。和無事。\n作事 先難後易。\n家事 和為貴。\n家運 居之則安。\n婚姻 大吉。\n求兒 不可。\n六甲 先男後女。\n求財 勤儉必得。\n功名 修陰德必中。\n歲君 淡淡。\n治病 求神庇祐。辰未日(半月)過漸癒。\n出外 辰巳日則可。\n經商 平平。\n來人 辰未日(半月)到。\n行舟 平平。財輕。\n移居 隨意。(不可)\n失物 辰巳日在。(難尋)\n求雨 初初到尾。(不明其意)\n官事 和為貴。不和凶。\n六畜 納者不可。\n耕作 平平。少利。\n築室 有犯陰邪。\n墳墓 平平。小吉。\n討海 微利運不辰\n作塭 運不合。求小利。\n魚苗 微利。\n月令 不畏。漸漸平安。\n尋人 待時。\n遠信 慢。", + "oracle": "", + "story": "1.莊子破棺。(莊子試妻)\n周朝。姓莊名周。字子休。宋國蒙邑人。仕周為漆園吏。\n莊子假死試妻。其妻田氏守孝。七天後有一楚國王孫公子到訪。\n自稱莊子之徒。願執百日之喪。田氏愛公子俊美。不足廿日成婚。\n公子叫心疼。曰腦髓(人心)可治。田氏往劈莊子棺以取腦髓(人心)。\n莊子破棺而出。後田氏羞愧自殺。\n2.薛公大鬧花燈跌死太子驚死聖駕\n3.姜尚未卜吉凶事" + }, + { + "id": 18, + "no": "第十八籤【丙戌】", + "grade": "", + "palace": "", + "poem1": "君問中間此言因\n看看祿馬拱前程\n若得貴人多得利\n和合自有兩分明", + "poem2": "", + "meaning": "", + "explanation": "凡事 忍耐求和。\n作事 貴人利。和氣成。\n家事 圓滿進財。\n家運 瑞氣盈庭。\n婚姻 大吉。\n求兒 月光好。月暗平。\n六甲 先男。\n求財 不多。(萬金萬貫連得)\n功名 有望。\n歲君 得利。\n治病 痊癒。\n出外 有貴人提攜。\n經商 大進利市。\n來人 月光到。\n行舟 得財。\n移居 大吉。\n失物 月光在。\n求雨 不日即到。\n官事 速和公判。\n六畜 可好。\n耕作 有收。\n築室 祥氣盈庭。\n墳墓 福人必得福地。\n討海 和者得大財。\n作塭 獲利三倍。\n魚苗 大利。\n月令 平安吉慶。\n尋人 在。\n遠信 佳音速報。", + "oracle": "", + "story": "1.楊管醉玉仝坐馬。\n2.秦叔寶救李淵般家。" + }, + { + "id": 19, + "no": "第十九籤【丁丑】", + "grade": "", + "palace": "", + "poem1": "富貴由命天註定\n心高必然誤君期\n不然且回依舊路\n雲開月出自分明", + "poem2": "", + "meaning": "", + "explanation": "凡事 被人害。理完(終)明。\n作事 月光好。\n家事 和而貴。(犯相剋。望神佛)\n家運 不佳。可住平安。\n婚姻 不成。由天註定。\n求兒 慢一步。\n六甲 先女後男。得貴。(作福出麟兒)\n求財 守機而作。\n功名 難得。\n歲君 照舊。\n治病 險。月光好。若(暗)不癒。\n出外 不可。\n經商 難如意。守待時。\n來人 月頭到。\n行舟 平平。\n移居 可。\n失物 月光在。暗難尋。\n求雨 未有。\n官事 命運犯刑相剋。拖尾。\n六畜 不可。\n耕作 不可依舊。\n築室 不可。\n墳墓 舊墳重興。\n討海 運微不逢時。\n作塭 守運心亦虧本。\n魚苗 應月明。\n月令 桂候。\n尋人 暫待。\n遠信 將近就至。", + "oracle": "", + "story": "1.紅孩兒捷住路頭\n2.范丹妻未出身殺九夫" + }, + { + "id": 20, + "no": "第二十籤【丁卯】", + "grade": "", + "palace": "", + "poem1": "前途功名未得意\n只恐命內有交加\n兩家必定防損失\n勸君且退莫咨嗟", + "poem2": "", + "meaning": "", + "explanation": "凡事 了錢。拖尾。不合。\n作事 無成。\n家事 恐生孽物。\n家運 防邪怪作之災。\n婚姻 難合。\n求兒 不可。\n六甲 臨產危險。\n求財 不得。\n功名 科運無。難進中。\n歲君 坎坷。\n治病 大命險。未日(半月)好。\n出外 無運。不可。\n經商 不就。\n來人 未日(半月)到。\n行舟 失利。\n移居 不可。\n失物 不得了工。\n求雨 無。\n官事 拖尾破財。\n六畜 不合。\n耕作 難收。\n築室 不得完美。\n墳墓 不可葬。地不合。\n討海 有陰公作祟。\n作塭 命運蹉跎。無望。\n魚苗 失了資本。\n月令 陰邪作病。難遂。\n尋人 延緩。\n遠信 音信沉沒。", + "oracle": "", + "story": "1.孫悟空大難火災\n火字,另有改作水字一說。\n孫悟空大鬧天宮。火刑不畏。八卦爐不困。\n後給佛祖壓于五指山下。惡貫滿刑身受困。\n五百年後才遇唐僧解救。\n2.薛丁山著飛刀" + }, + { + "id": 21, + "no": "第二一籤【丁巳】", + "grade": "", + "palace": "", + "poem1": "十方佛法有靈通\n大難禍患不相同\n紅日當空常照耀\n還有貴人到家堂", + "poem2": "", + "meaning": "", + "explanation": "凡事 貴人扶持。\n作事 和大吉。散得失。\n家事 門庭可恭可賀。\n家運 必得吉昌。\n婚姻 難成。\n求兒 好。\n六甲 先男後女。\n求財 先無後有。\n功名 望後科。\n歲君 中和。\n治病 大命險。貴人扶。\n出外 緩有貴人。\n經商 先難後吉。\n來人 立即到。\n行舟 無大利。\n移居 適宜大吉。\n失物 可在。\n求雨 緩到。\n官事 微殃。有貴人。脫。\n六畜 納之可喜。\n耕作 平平晚收。\n築室 必有餘慶。\n墳墓 顯裕後昆。\n討海 先微。后有大利。\n作塭 有利可得。\n魚苗 慢則有財。\n月令 平后。有貴人。吉。\n尋人 在。\n遠信 速至有喜。", + "oracle": "", + "story": "朱壽昌尋母在長亭(朱壽昌辭官尋母)\n朱壽昌字康叔。宋朝天長人。母劉氏(妾)被遂後改嫁。\n朱于熙寧(1068~1077)初。棄官尋母曰。不見母面誓不復還。\n至同州竟無意中見母。劉氏已七十多歲(分離五十年)。" + }, + { + "id": 22, + "no": "第二二籤【丁未】", + "grade": "", + "palace": "", + "poem1": "太公家業八十成\n月出光輝四海明\n命內自然逢大吉\n茅屋中間百事亨", + "poem2": "", + "meaning": "", + "explanation": "凡事 先呆。得貴人吉。\n作事 先呆後吉。\n家事 門庭吉慶。\n家運 安居春風。\n婚姻 和合。\n求兒 平正。\n六甲 生男。(子媳虛)\n求財 先微後進。\n功名 晚可有進。\n歲君 順利。\n治病 老不畏。少不好。\n出外 平平。(有貴人提攜。得利)\n經商 有利益。\n來人 月光到。\n行舟 晚運可通。\n移居 好。\n失物 月光在。月暗無。\n求雨 上下弦。\n官事 和合好。(貴人了錢。完局)\n六畜 納有利。\n耕作 允好。\n築室 百事吉慶。\n墳墓 有餘裕哉。\n討海 先無後利。\n作塭 晚者大利\n魚苗 有利可得。\n月令 不遂。\n尋人 慢至。\n遠信 音信慢至。", + "oracle": "", + "story": "周文王為姜太公拖車\n周文王夜夢飛熊(長翼之虎)。出賢士之兆。\n文王求賢出溪頭。不見賢人只見鉤。\n文王回宮傳旨令百官留殿齋戒三日。第四日沐浴更衣。\n出往磻溪迎姜子牙(道號飛熊)。數里前文王下馬步行。\n拜子牙為丞相。後文王乘輿。子牙乘馬回朝。\n(故事見封神榜。拖車一事未見)" + }, + { + "id": 23, + "no": "第二三籤【丁酉】", + "grade": "", + "palace": "", + "poem1": "欲去長江水闊茫\n前途未遂運未通\n如今絲綸常在手\n只恐魚水不相逢", + "poem2": "", + "meaning": "", + "explanation": "凡事 不可作。和者吉。\n作事 遲緩。\n家事 門庭失運。了錢。\n家運 崎嶇不順。\n婚姻 大吉。\n求兒 不可。\n六甲 生男。(子虛。先女後男)\n求財 先失運。後有利。\n功名 無望。\n歲君 順利。\n治病 了錢。尾過漸好。\n出外 不可。\n經商 顛倒。\n來人 未日(半月)到。\n行舟 運途不佳。\n移居 不佳。等待。\n失物 尋不見。\n求雨 上下弦。\n官事 尾勝吉。(了錢完局)\n六畜 不可納。\n耕作 不合時運。微利。\n築室 不可。且慢。\n墳墓 地氣不佳。\n討海 運途不佳。\n作塭 防魚失。求微利。\n魚苗 後日可得小利。\n月令 不遂。\n尋人 緩。\n遠信 音信無到。", + "oracle": "", + "story": "1.周玉姊可遇陳春生\n2.姜子牙送飯為武吉掩卦" + }, + { + "id": 24, + "no": "第二四籤【丁亥】", + "grade": "", + "palace": "", + "poem1": "月出光輝四海明\n前途祿位見太平\n浮雲掃退終無事\n可保禍患不臨身", + "poem2": "", + "meaning": "", + "explanation": "凡事 緊和平。了錢工。\n作事 月光即成\n家事 大進圓滿。\n家運 平安\n婚姻 和合\n求兒 好。\n六甲 先男。(先女後男)\n求財 少有。\n功名 顯榮祖宗。恐有變。\n歲君 中和\n治病 陰邪祟。求神安\n出外 先少利。後可得\n經商 無利。\n來人 月光到。\n行舟 財輕。平平。\n移居 后即可以\n失物 月光在。月暗無。\n求雨 未有。\n官事 冒險。有貴人。好。\n六畜 可納。\n耕作 平正。\n築室 漸且候。待日期\n墳墓 后大吉\n討海 無大財。陰作祟。\n作塭 途中防水微利。\n魚苗 先微后有。\n月令 不遂。\n尋人 可回。\n遠信 佳音速至。", + "oracle": "", + "story": "1.秦叔寶救李淵\n2.孟良焦讚救宗寶" + }, + { + "id": 25, + "no": "第二五籤【戊子】", + "grade": "", + "palace": "", + "poem1": "總是前途莫心勞\n求神問聖枉是多\n但看雞犬日過後\n不須作福事如何", + "poem2": "", + "meaning": "", + "explanation": "凡事 作可作。和者吉。\n作事 慢成。\n家事 平平。\n家運 宅舍難居\n婚姻 不好難成。\n求兒 不可。\n六甲 謝良愿。求神佛。\n求財 微利不吉。\n功名 未就。\n歲君 中和\n治病 運深。酉戌不畏。\n出外 不可。\n經商 新業差。舊業平\n來人 戌日到。\n行舟 財輕微利。\n移居 且慢。\n失物 己丑卯戌日在。\n求雨 甲子乙丑日。不久。\n官事 宜和。(必受災殃)\n六畜 不可。\n耕作 只收半。\n築室 不美。成者安。\n墳墓 地勢不合。\n討海 和者好。不和呆。\n作塭 只求微利。\n魚苗 小利。\n月令 下半年平安。\n尋人 慢至。\n遠信 音信遲延。", + "oracle": "", + "story": "1.鳳嬌觀音庵問籤中奸臣計\n2.胡鳳嬌觀音寺行香求懺" + }, + { + "id": 26, + "no": "第二六籤【戊寅】", + "grade": "", + "palace": "", + "poem1": "選出牡丹第一枝\n勸君折取莫遲疑\n世間若問相知處\n萬事逢春正及時", + "poem2": "", + "meaning": "", + "explanation": "凡事 春吉冬呆。\n作事 春天可成\n家事 綿綿齊美\n家運 安居春風。\n婚姻 成者好。\n求兒 平平。\n六甲 先男後女。\n求財 財源廣進。\n功名 朱衣點頭。(及第)\n歲君 順吉。\n治病 平安。(婦忌十一月男能十二月。老危少安)\n出外 平安有。春滿載\n經商 逢春發無窮\n來人 月光到。\n行舟 財利平平\n移居 平安\n失物 在東方。緊尋在。\n求雨 必到。\n官事 必和。(必勝)\n六畜 可納\n耕作 早冬好。下冬呆。\n築室 逢春大吉。\n墳墓 真龍正穴\n討海 春有冬無。\n作塭 逢春利。外微利。\n魚苗 三月吉四月小吉。\n月令 不遂。逢春如意。\n尋人 月前得回。\n遠信 源源而來。", + "oracle": "", + "story": "1.范丹洗浴遇賢妻\n2.薛丁山破收飛刀" + }, + { + "id": 27, + "no": "第二七籤【戊辰】", + "grade": "", + "palace": "", + "poem1": "君爾寬心且自由\n門庭清吉家無憂\n財寶自然終吉利\n凡事無傷不用求", + "poem2": "", + "meaning": "", + "explanation": "凡事 有財允成。不畏。\n作事 成功。\n家事 團圓且喜。\n家運 可得興旺。\n婚姻 大吉。\n求兒 不可。\n六甲 添得弄璋之喜。\n求財 先輕後得。\n功名 晚到。\n歲君 淡淡。(未安)\n治病 得安。\n出外 先呆後好。\n經商 獲如意。後大利。\n來人 難在。\n行舟 先平安後大進。\n移居 慢即吉。\n失物 自回。\n求雨 尚未有。\n官事 有貴人。平安。\n六畜 興旺\n耕作 早冬微。晚冬好。\n築室 喜得瑞氣盈門。\n墳墓 地運大進益。\n討海 先無後有。\n作塭 免介意。有利得。\n魚苗 先微后有。\n月令 平安。\n尋人 不見。難尋。\n遠信 佳音速至。", + "oracle": "", + "story": "1.胡完救文氏母女\n2.摧文德清胡鳳嬌" + }, + { + "id": 28, + "no": "第二八籤【戊午】", + "grade": "", + "palace": "", + "poem1": "於今莫作此當時\n虎落平陽被犬欺\n世間凡事何難定\n千山萬水也遲疑", + "poem2": "", + "meaning": "", + "explanation": "凡事 後成吉。\n作事 難成。\n家事 恐防大害。\n家運 人作怪。恐風波。\n婚姻 不吉。(女帶殺氣)\n求兒 不可。\n六甲 須防難產。\n求財 不得。\n功名 無。\n歲君 平平。\n治病 運犯劫。被邪欺。寅戌日過不畏。\n出外 被人欺。\n經商 呆人欺。難如意。\n來人 難在。\n行舟 無利可得。(了財帛)\n移居 大不好。\n失物 難尋。\n求雨 不日到。\n官事 被官欺。大了錢。\n六畜 不安。\n耕作 半收。\n築室 不可。(犯殺)\n墳墓 犯六十年。緊移。\n討海 無利可得。\n作塭 剋口舌。忍耐好。\n魚苗 不利。\n月令 九不畏。防人欺。\n尋人 難得。\n遠信 魚沉消息。", + "oracle": "", + "story": "1.李存孝打虎\n2.石存孝遇李克用收為誼子" + }, + { + "id": 29, + "no": "第二九籤【戊申】", + "grade": "", + "palace": "", + "poem1": "枯木可惜未逢春\n如今反在暗中藏\n寬心且守風霜退\n還君依舊作乾坤\n未逢春二字,另有改作逢春時一說。\n反且二字,另有改作返還一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 待時。\n作事 難成。\n家事 平安。\n家運 合家興旺。(運滯)\n婚姻 平平。\n求兒 不吉。\n六甲 先男後女。\n求財 新業差。舊業平。\n功名 不就。\n歲君 平正。\n治病 運暗。逢春出運。(老凶)\n出外 不可。\n經商 須守安命不可。\n來人 未日(半月)到。\n行舟 無利可得。\n移居 不吉。\n失物 援尋。(必在)\n求雨 久不至。\n官事 拖尾。\n六畜 不可。\n耕作 無利半收。\n築室 漸待開春。\n墳墓 地運後必發。\n討海 依舊吉。新不利。\n作塭 返原運。暗無利。\n魚苗 春有利。夏失時。\n月令 不遂。\n尋人 行人待。\n遠信 音信速至。", + "oracle": "", + "story": "古城會關公斬蔡陽" + }, + { + "id": 30, + "no": "第三十籤【戊戌】", + "grade": "", + "palace": "", + "poem1": "漸漸看此月中和\n過後須防未得高\n改變顏色前途去\n凡事必定見重勞", + "poem2": "", + "meaning": "", + "explanation": "凡事 了錢。甚不好。\n作事 難成。\n家事 門有險。了錢災。\n家運 了錢難安。\n婚姻 不成。\n求兒 不可。且慢。\n六甲 空孕。勿躁。\n求財 無利。\n功名 不成難進。\n歲君 不遂。\n治病 險。半月不癒。重。\n出外 不可出。\n經商 經營不就。\n來人 月光到。\n行舟 了工了本。\n移居 不可。\n失物 難尋。\n求雨 久不至。\n官事 枉費了錢。\n六畜 不佳。\n耕作 了工後。半年好。\n築室 不安。\n墳墓 地氣不佳。\n討海 了工。無利。\n作塭 枉費徒勞。失利。\n魚苗 無望。\n月令 不遂。\n尋人 行人漸回。\n遠信 音信有變。", + "oracle": "", + "story": "1.豬哥過柿山\n2.薛丁山三請樊梨花" + }, + { + "id": 31, + "no": "第三一籤【己丑】", + "grade": "", + "palace": "", + "poem1": "綠柳蒼蒼正當時\n任君此去作乾坤\n花果結實無殘謝\n福祿自有慶家門", + "poem2": "", + "meaning": "", + "explanation": "凡事 得利。\n作事 成功。\n家事 瓜瓞綿綿。\n家運 世世興旺。\n婚姻 好結尾。\n求兒 好。\n六甲 先女後男。(生男)\n求財 用心即有。(春敗好。在家好)\n功名 差人來報喜。\n歲君 大吉。\n治病 喜遇良醫。\n出外 大吉可進。\n經商 大發資財。\n來人 立即到。\n行舟 財發萬金。\n移居 適其所哉。\n失物 急尋可有。\n求雨 及時。\n官事 緊完局。了錢。\n六畜 可納。\n耕作 好。\n築室 好。\n墳墓 幸喜得遇其穴。\n討海 財發萬金\n作塭 黃金萬貫可喜。\n魚苗 見春可喜。\n月令 不遂。\n尋人 必在。\n遠信 音信有回。", + "oracle": "", + "story": "1.孟姜女招親\n2.董永皇都市仙女送孩兒。(董永遇仙)\n漢。董永。千乘人。少失母。獨養父。流寓孝感。\n父亡無以葬。乃從人貸錢一萬。日後無錢還。\n當以身作奴。葬畢。其主要董永日取柴一擔。\n汲水四擔。鋤田六七畝。辛苦難當。\n一日上山砍柴倦睡。皇天見其孝行。即差仙女下凡為婚。\n董永醒來見女恐是妖精。女攔曰吾無父母又無依。欲結為夫婦。\n董永見其淒涼。帶女回歸。主人責董永拐帶婦人禍及其主。\n後暫留該女。遍訪四方家庭並無失婦人。才允成親。\n董婦百日織得錦五十丈。剪一半往市賣出得銀。贖脫董永身。\n後將錦進。敕封進寶狀元。\n仙姬曰。天賜兒子三歲送還。(仙女回天)。\n後其子十六歲中狀元。衣錦還鄉。\n3.董永遇仙\n漢。董永。千乘人。少失母。獨養父。流寓孝感。\n父亡無以葬。乃從人貸錢一萬。日後無錢還。當以身作奴。\n葬畢。道遇一婦人。求為永妻。永與俱詰。\n錢主令織縑(錦)三百疋以償。一月而畢。辭永去。\n乃曰。我(係)天上織女。緣君至孝。\n玉帝令我助君償債。言訖。凌空而去。" + }, + { + "id": 32, + "no": "第三二籤【己卯】", + "grade": "", + "palace": "", + "poem1": "詩 曰\n龍虎相交前門前\n此事必定兩相連\n黃金忽然變成鐵\n何用作福問神仙", + "poem2": "", + "meaning": "", + "explanation": "凡事 退卻。\n作事 難得成功。\n家事 恐遇風波之災。\n家運 多口舌之災。\n婚姻 不吉。\n求兒 不可。\n六甲 防小產。子息虛。\n求財 失利虧本。\n功名 無望。\n歲君 中和。(不遂)\n治病 有邪凶險。拖尾。少者好。寅辰日不畏\n出外 不可。犯災難。\n經商 了錢。\n來人 寅辰日到。\n行舟 無利。了工。\n移居 大不好。\n失物 難尋。\n求雨 不日到。\n官事 了錢拖尾。\n六畜 損失。\n耕作 不可。\n築室 必退敗。\n墳墓 地氣漸失。\n討海 徒勞。\n作塭 失運虧本。\n魚苗 不可。\n月令 不遂。\n尋人 寅辰日在。\n遠信 音信遲至。", + "oracle": "", + "story": "1.劉備入東吳進贅\n劉玄德。即西蜀先主也。為荊州牧時。甘夫人新喪。\n東吳孫權聞知。詐以妹招贅欲賺其人。吳素討荊州。\n孔明料知。乃授趙雲錦囊計。保先主入吳。\n意弄假成真。娶孫夫人以歸焉。\n2.龍處交會" + }, + { + "id": 33, + "no": "第三三籤【己巳】", + "grade": "", + "palace": "", + "poem1": "欲去長江水闊茫\n行舟把定未遭風\n戶內用心再作福\n看看魚水得相逢", + "poem2": "", + "meaning": "", + "explanation": "凡事 不可急進。\n作事 二次成功。\n家事 門庭缺。後團圓。\n家運 門庭興旺。\n婚姻 大吉。\n求兒 且慢。待後日。\n六甲 先男後女。\n求財 漸有。\n功名 望後科。\n歲君 平和。\n治病 拖尾。破財。不畏\n出外 平安。\n經商 安分待時。\n來人 辰未日(半月)到。\n行舟 恐防未日(半月)風波。\n移居 二次成吉。\n失物 用心再尋。\n求雨 緩有。\n官事 先呆後好。\n六畜 小吉。\n耕作 有收成。\n築室 要把定。待後日。\n墳墓 地運小吉\n討海 得財。\n作塭 漸漸得財。\n魚苗 好。\n月令 不安。\n尋人 未日(半月)在。\n遠信 音信遲延。", + "oracle": "", + "story": "1.銅銀買紙靴\n銅銀指私混銅之偽銀幣。\n紙靴指用紙代革所造之假鞋。\n意即使用偽幣卻買了假貨。\n想騙人自己也被騙。有害人終害己之意。\n故事出處未明。\n籤文新解\n欲去長江水闊茫。 有大水阻隔欲望。\n行舟把定未遭風。 欠佳運(風)而未能前進。\n戶內用心再作福。 內心須去惡從善。並求神明保佑。\n看看魚水得相逢。 如此才有風把帆吹。(魚水喻風帆)\n本籤之 解曰▼ 29項多不合此意。\n因此讀者只能以 解曰(人意)▼ 作參考。\n主看簽詩(神示)內容。反覆推敲及請教賢明(貴人)。\n2.劉備入東吳回荊州\n劉玄德。即西蜀先主也。為荊州牧時。甘夫人(劉備妻)新喪。\n東吳孫權聞知。詐以妹招贅欲賺(軟禁)其人。吳素討荊州。\n孔明料知。乃授趙雲錦囊計。保先主入吳。(東江招親)\n意弄假成真。娶孫夫人以歸焉。\n有曰\n周郎妙計高天下。賠了夫人又折兵。" + }, + { + "id": 34, + "no": "第三四籤【己未】", + "grade": "", + "palace": "", + "poem1": "危險高山行過盡\n莫嫌此路有重重\n若見蘭桂漸漸發\n長蛇反轉變成龍\n過字,另有改作通字一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 勤勞徐進。\n作事 先呆漸漸成圓\n家事 門戶進益。\n家運 險後漸得吉慶。\n婚姻 晚成好。\n求兒 不可。\n六甲 生女。(先男后女)\n求財 先呆後好。\n功名 有望。\n歲君 未年得宜。\n治病 少平安。老不好\n出外 平順。\n經商 後有大財。\n來人 辰未日(半月)到。\n行舟 漸漸有利可得。\n移居 不可。\n失物 七八月尋必在。\n求雨 不日到。\n官事 難完局。求貴人\n六畜 小吉。\n耕作 平平有收\n築室 宅運漸發。\n墳墓 得其所哉。\n討海 春平平冬有財。\n作塭 有利。\n魚苗 慢即有。\n月令 漸漸出運。\n尋人 遠行待時回。\n遠信 音信立至。", + "oracle": "", + "story": "曹操潼關遇馬超" + }, + { + "id": 35, + "no": "第三五籤【己酉】", + "grade": "", + "palace": "", + "poem1": "此事何須用心機\n前途變怪自然知\n看看此去得和合\n漸漸脫出見太平", + "poem2": "", + "meaning": "", + "explanation": "凡事 臨機應變。\n作事 辰未日(半月)成好。(半吉。拖尾。了錢)\n家事 寬守即好。\n家運 風波漸消。\n婚姻 難成。成大吉。\n求兒 不可。\n六甲 生產難。子媳虛。\n求財 遇呆人。漸很利。\n功名 有活鬼。難進。\n歲君 未年得宜。\n治病 鬼作祟。後拖尾。\n出外 平正。\n經商 難得如意。\n來人 辰未日(半月)到。\n行舟 先失後得。\n移居 南面得宜。\n失物 難尋。\n求雨 不日到。\n官事 命運蹉跎。破財。\n六畜 顛倒。\n耕作 早平。晚好。\n築室 犯凶星。不可。\n墳墓 運不佳。後能發。\n討海 鬼作祟後微利。\n作塭 鬼作怪後得利。\n魚苗 先失時後得宜。\n月令 不遂祈神。\n尋人 久回。\n遠信 守待可至。", + "oracle": "", + "story": "吳漢殺妻為母救主" + }, + { + "id": 36, + "no": "第三六籤【己亥】", + "grade": "", + "palace": "", + "poem1": "福如東海壽如山\n君爾何須嘆苦難\n命內自然逢大吉\n祈保分明自平安\n自平安三字,另有改作得平安或得自安三字。", + "poem2": "", + "meaning": "", + "explanation": "凡事 亨通得自安。\n作事 成者甚好。\n家事 光輝門庭。\n家運 吉星拱照。\n婚姻 美滿大吉\n求兒 好。\n六甲 得添弄璋。(生男)\n求財 黃金萬貫。\n功名 祝神求佛可進。\n歲君 平安。\n治病 少者不畏。老險。\n出外 不可。(滿載榮歸)\n經商 萬商雲集。\n來人 月光即到。\n行舟 大好居中。\n移居 兄弟和合者吉。\n失物 尋在。\n求雨 及時。\n官事 了錢過後完局。\n六畜 興旺。\n耕作 早晚有收。\n築室 福雙全。子孫旺\n墳墓 地勢套當。\n討海 有大財。\n作塭 神指示得大財。\n魚苗 大利。\n月令 不遂。\n尋人 得至。\n遠信 速報佳音。", + "oracle": "", + "story": "1.薛仁貴救駕\n2.李世民落海灘" + }, + { + "id": 37, + "no": "第三七籤【庚子】", + "grade": "", + "palace": "", + "poem1": "運逢得意身顯變\n君爾身中皆有益\n一向前途無難事\n決意之中保清吉", + "poem2": "", + "meaning": "", + "explanation": "凡事 有錢。拖尾。平安。\n作事 可成。有口舌。\n家事 克振家聲。。\n家運 居之平安。\n婚姻 好。\n求兒 好吉。\n六甲 先男後女。\n求財 漸有。\n功名 望後科。(身顯)\n歲君 平安\n治病 險不畏。祈平安。\n出外 平正。\n經商 峻發日新。\n來人 立即到。\n行舟 有利可得。\n移居 好吉。\n失物 難尋。\n求雨 不日到。\n官事 破財。結局。\n六畜 適宜吉昌。\n耕作 平平。有收。\n築室 清吉。\n墳墓 得其所哉。\n討海 和大利。漸得進。\n作塭 漸得利。\n魚苗 漸好。\n月令 漸好。\n尋人 盡心得回。\n遠信 佳音速至。", + "oracle": "", + "story": "1.正德君看呼綠牡丹開\n2.正德君戲李鳳姐" + }, + { + "id": 38, + "no": "第三八籤【庚寅】", + "grade": "", + "palace": "", + "poem1": "三、六、九、十二月\n名顯有意在中央\n不須祈禱心自安\n看看早晚日過後\n即時得意在其間\n央字,另有改作間字一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 守己安分。\n作事 晚成好。早無利。\n家事 門庭光輝進益。\n家運 恭順。\n婚姻 成好。\n求兒 好。\n六甲 生男。(先女後男)\n求財 晚來好。\n功名 真可喜。\n歲君 順利。\n治病 平安痊癒。\n出外 必得利。\n經商 後有大財。\n來人 三日後到。\n行舟 平平得利。\n移居 可有喜慶。\n失物 尋必在。\n求雨 尚未。\n官事 祈神完明。了錢。\n六畜 有利可得。\n耕作 有收可以。\n築室 得意平安。\n墳墓 地勢可佳。速發。\n討海 下半年有利。\n作塭 可喜有利。\n魚苗 五日內買得利。\n月令 平平。\n尋人 漸回。\n遠信 急至。", + "oracle": "", + "story": "1.劉備三顧孔明茅蘆(廬)\n三國時。諸葛亮隱居于隆中之茅屋。劉備求賢。\n往訪三次才得見孔明。\n諭有寶心安。得意遲早。靜待時機。不請自來。\n2.三顧草廬\n漢。諸葛亮。字孔明。瑯琊人。漢末避居南陽。\n志學清修。養生之道。研究奇明(門)遁法。天文術數。\n卦算韜略。無所不精。初不求聞達於諸侯。\n後徐庶薦於劉先生。先主凡三往問計。延為軍師。\n先主即位。拜丞相。受以託孤。後主封為武卿侯。卒諡忠武。" + }, + { + "id": 39, + "no": "第三九籤【庚辰】", + "grade": "", + "palace": "", + "poem1": "意中若問神仙路\n勸爾且退望高樓\n寬心且守寬心坐\n必然遇得貴人扶", + "poem2": "", + "meaning": "", + "explanation": "凡事 漸應。\n作事 有貴人。好到尾\n家事 永獲吉慶。\n家運 漸漸平安。\n婚姻 成好。(二次者成好)\n求兒 不可。有事。\n六甲 男女貴氣。(子媳晚。得弄璋)\n求財 漸有。\n功名 望後科。\n歲君 淡安。\n治病 少貴人。老拖運\n出外 遇貴人\n經商 先平後利。\n來人 難在。\n行舟 先不利。後小利\n移居 平平\n失物 尋在。\n求雨 未有。\n官事 後有貴人。\n六畜 不可。\n耕作 照舊種。可收成。\n築室 後好\n墳墓 地勢允好\n討海 先不利後小利。\n作塭 先失利後有利。\n魚苗 失在前利在後。\n月令 不遂了財。\n尋人 難在。\n遠信 緩緩就至。", + "oracle": "", + "story": "1.楊文廣被困柳州城\n宋朝元帥狄青征南蠻。困于蒙雲關。楊文廣往救。\n南蠻女將段紅玉施邪術圍困楊文廣。\n柳州城是否指蒙雲關不明。\n2.孔夫子小兒答\n孔子于魯西設教。御車出遊。遇一童子阻路。\n小兒與孔子互相問答。孔子窮詞。曰後生可畏。登車而去。\n三字經有。昔仲尼。師項橐(項托)。即此兒也。" + }, + { + "id": 40, + "no": "第四十籤【庚午】", + "grade": "", + "palace": "", + "poem1": "平生富貴成祿位\n君家門戶定光輝\n此中必定無損失\n夫妻百歲喜相隨", + "poem2": "", + "meaning": "", + "explanation": "凡事 拖尾。了錢。漸吉。\n作事 難得成功。\n家事 大吉進益。\n家運 五世其昌。\n婚姻 美滿。\n求兒 好。\n六甲 先男後女。\n求財 有大進。\n功名 指日高陞。\n歲君 平順。\n治病 少漸癒。老不安。\n出外 平安。\n經商 有成。\n來人 月光到。\n行舟 有利。\n移居 暫緩。\n失物 必在。\n求雨 下旬到。\n官事 了錢可安。\n六畜 可喜有利。\n耕作 平平。下半年好。\n築室 壽命長。富貴至。\n墳墓 綿綿齊美。\n討海 後必大利。\n作塭 有大利。\n魚苗 大利。\n月令 不遂。\n尋人 得回。\n遠信 將近就至。", + "oracle": "", + "story": "1.三元會葛其量夫妻相會\n2.三元會葛奇蔡坤買書" + }, + { + "id": 41, + "no": "第四一籤【庚申】", + "grade": "", + "palace": "", + "poem1": "今行到此實難推\n歌歌暢飲自徘徊\n雞犬相聞消息近\n婚姻夙世結成雙\n此字,另有作手字一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 和者吉。\n作事 難成。\n家事 克振家聲。\n家運 漸得平安。\n婚姻 偕老。\n求兒 不可。\n六甲 得添弄璋。(生男)\n求財 難。酉戌日即成。\n功名 無。\n歲君 平和。\n治病 拖尾。戌日不畏。\n出外 東北方好。\n經商 遲有利。\n來人 戌日到。\n行舟 無財可得。\n移居 不可。\n失物 東北方酉戌尋在。\n求雨 有。\n官事 勝局。\n六畜 不好。\n耕作 平平有利。\n築室 九月以後好。\n墳墓 平平。\n討海 無利時待。\n作塭 微利平平。\n魚苗 不好。\n月令 不遂。\n尋人 慢至。\n遠信 酉戌日至。", + "oracle": "", + "story": "1.王小姐為色事到禍審英月\n2.掩雞拖木屐三伯探英台" + }, + { + "id": 42, + "no": "第四二籤【庚戌】", + "grade": "", + "palace": "", + "poem1": "一重江水一重山\n誰知此去路又難\n任他改求終不過\n是非終久未得安", + "poem2": "", + "meaning": "", + "explanation": "凡事 了錢。過運\n作事 難成。\n家事 門庭難合。\n家運 不安。\n婚姻 無望。\n求兒 不雅。\n六甲 臨產險。先後男。(生女)\n求財 無有益。\n功名 不就。\n歲君 浮沉。\n治病 病險。未日(半月)不畏。\n出外 不可。\n經商 難有成就。\n來人 未日(半月)到不到無。\n行舟 防險。\n移居 午年尾。抽此吉。\n失物 難尋。\n求雨 有小無大。\n官事 不好。拖尾。\n六畜 不佳。\n耕作 無收成。\n築室 不吉。\n墳墓 地運不佳。遷移。\n討海 無利可得。\n作塭 犯風水了錢。\n魚苗 蝕本。\n月令 多逢口舌。\n尋人 難在。\n遠信 雁杳魚沉。", + "oracle": "", + "story": "姜女送寒衣哭倒萬里長城\n孟姜女。秦始皇時人。夫范杞郎。派作長城。久役不歸。\n姜女尋夫。范杞郎已死。屍骨不存。\n姜女大哭。長城崩塌。露出夫骨。" + }, + { + "id": 43, + "no": "第四三籤【辛丑】", + "grade": "", + "palace": "", + "poem1": "一年作事急如飛\n君爾寬心莫遲疑\n貴人還在千里外\n音信月中漸漸知", + "poem2": "", + "meaning": "", + "explanation": "凡事 候時過(月半)。貴人成。\n作事 月半好。\n家事 喜遇貴人。\n家運 光輝門庭。\n婚姻 平平。\n求兒 平正。(且候寬緩)\n六甲 先女後男。(先男後女)\n求財 未遇時。月半合。\n功名 不就。(得意允進)\n歲君 起倒。\n治病 月半過。有貴人。\n出外 不利。\n經商 先無後有。\n來人 月光到。\n行舟 小有利益。\n移居 不可。\n失物 月光在。\n求雨 小許。\n官事 不畏。\n六畜 緩日即好。\n耕作 小有收獲。\n築室 好。\n墳墓 可得吉地吉穴。\n討海 月半過大進。\n作塭 後有大利。\n魚苗 月半過有利。\n月令 了錢。\n尋人 月半過有人報。\n遠信 中旬可至。", + "oracle": "", + "story": "1.偶才母井邊相會\n2.三嬸報喜。蘇秦回家假不第" + }, + { + "id": 44, + "no": "第四四籤【辛卯】", + "grade": "", + "palace": "", + "poem1": "客到前途多得利\n君爾何故兩相疑\n雖是中間逢進退\n月出光輝得運時\n逢字,另有改作防字一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 月光好。\n作事 運至事成。\n家事 志氣遠大。\n家運 左右平安。\n婚姻 中和。\n求兒 不可。\n六甲 先女後男。(弄瓦之慶)\n求財 淡淡。(漸利益。亨可喜)\n功名 必能得進。\n歲君 起倒。\n治病 月光安。運光彩。\n出外 一路順風。\n經商 大吉利市。\n來人 月半到。\n行舟 大吉有利。\n移居 大吉。\n失物 月光在。寅辰在。\n求雨 未有。\n官事 了錢。月光完局。\n六畜 可納。\n耕作 平平。(有利可得)\n築室 可居安樂。\n墳墓 地氣漸發財。\n討海 可能得利。\n作塭 有獲大利。\n魚苗 有利可得。\n月令 待時可安。\n尋人 月光在。\n遠信 速報好音。", + "oracle": "", + "story": "洪益春留傘愛陣三" + }, + { + "id": 45, + "no": "第四五籤【辛巳】", + "grade": "", + "palace": "", + "poem1": "花開今已結成果\n富貴榮華終到老\n君子小人相會合\n萬事清吉莫煩惱\n小人 :指小孩,參考 『孔夫子過番逢小兒\n』故事\n(這點單憑詩文論斷容易被誤解)", + "poem2": "", + "meaning": "", + "explanation": "凡事 以禮待人。\n作事 月光好。(難成)\n家事 瓜瓞綿綿。\n家運 福祉合亨。\n婚姻 中和。(合姻緣。百年老)\n求兒 好。\n六甲 先男後女。(先女後男)\n求財 可得萬貫。\n功名 晚成大器。\n歲君 平和。\n治病 老惡運。少不畏。\n出外 平正。(不利)\n經商 舊業俊發。後呆。\n來人 未日(半月)到。\n行舟 先無後有財。\n移居 平平。\n失物 歸。(拖過。未日(半月)在)\n求雨 未有。\n官事 難完局。拖尾。\n六畜 興旺。\n耕作 允順。\n築室 居之即安。\n墳墓 代代簪纓。\n討海 先無後有。\n作塭 後可得利。\n魚苗 有利可求。\n月令 平安。\n尋人 慢回。\n遠信 慢慢即至。", + "oracle": "", + "story": "1.孔夫子過番逢小兒\n可在網路上以『路逢數兒嬉戲』檢索到故事內容,在此不贅述\n2.薛仁貴固白虎關父子不相逢" + }, + { + "id": 46, + "no": "第四六籤【辛未】", + "grade": "", + "palace": "", + "poem1": "功名得意與君顯\n前途富貴喜安然\n若遇一輪明月照\n十五團圓光滿天\n意光二字,另有改作位照一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 大吉利。\n作事 成好。\n家事 福祉其昌。\n家運 安居樂業。\n婚姻 偕老。\n求兒 好。\n六甲 先男後女。\n求財 平平。\n功名 有。\n歲君 吉。\n治病 老拖尾。少立癒。\n出外 有貴人好。\n經商 利市三倍。\n來人 月半有。\n行舟 可喜吉利。\n移居 好。\n失物 月光有。\n求雨 月半到。\n官事 破財。完局。\n六畜 平平。\n耕作 平正。\n築室 得其所居。\n墳墓 得其吉地。\n討海 月半過漸得利。\n作塭 可得財利。\n魚苗 利路亨通。\n月令 漸平安。\n尋人 月光在。\n遠信 月半就至。", + "oracle": "", + "story": "1,江中立欽賜狀元\n2.江中立遇永祿君" + }, + { + "id": 47, + "no": "第四七籤【辛酉】", + "grade": "", + "palace": "", + "poem1": "君爾何須問聖跡\n自己心中皆有益\n於今且看月中旬\n凶事脫出化成吉\n心字,另有改作身字一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 先凶後好。\n作事 二次即成。\n家事 門閭得宜。\n家運 門庭小吉。\n婚姻 正好。\n求兒 好。\n六甲 年頭生女年尾生男。(月頭女月尾男)(先男後女)\n求財 輕。\n功名 有。(後科得進)\n歲君 淡安。\n治病 逢未月平安。十二月不吉。\n出外 先凶後吉。\n經商 利市。\n來人 月光到。\n行舟 春夏好。秋冬平。\n移居 正好。\n失物 尋有。(未日/半月在)\n求雨 未久。\n官事 先凶後吉。(未日/半月完局)\n六畜 平安。\n耕作 中中。\n築室 有合不畏。\n墳墓 地勢套當。\n討海 春夏大吉。\n作塭 得利。\n魚苗 先凶後吉。\n月令 不遂。\n尋人 慢回。\n遠信 近日就至。", + "oracle": "", + "story": "1.劉永作官蔭妻兒。\n2.李三娘井邊會" + }, + { + "id": 48, + "no": "第四八籤【辛亥】", + "grade": "", + "palace": "", + "poem1": "陽世作事未和同\n雲遮月色正朦朧\n心中意欲前途去\n只恐命內運未通\n命內運未通五字,另有改作前途未運通一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 被人害。和者吉。\n作事 難成。未日抽成。\n家事 不合。\n家運 有邪氣。不安。\n婚姻 不好。\n求兒 不可。\n六甲 生男。(子媳虛。晚來得)\n求財 輕。無利。\n功名 無。\n歲君 浮沉。\n治病 鬼作祟。未日(半月)好。寅辰卯不畏。\n出外 不可向前。\n經商 無財。\n來人 未日(半月)到。\n行舟 了無利。\n移居 不好。\n失物 尋無望。\n求雨 暴到。\n官事 未可。\n六畜 不可養。\n耕作 不吉。(只半收)\n築室 不可決定。\n墳墓 地氣不佳。\n討海 有鬼作祟。\n作塭 難得利。\n魚苗 多端失利。\n月令 失暗難通。\n尋人 難至。\n遠信 音息茫杳。", + "oracle": "", + "story": "蜻蜓誤入蜘蛛網\n誤入陷阱。有翅難飛。掙扎或求神者。有一線生機。\n否則等死。\n凶象。運滯。烏雲蓋頂。凡事不吉。" + }, + { + "id": 49, + "no": "第四九籤【壬子】", + "grade": "", + "palace": "", + "poem1": "言語雖多不可從\n風雲靜處未行龍\n暗中終得明消息\n君爾何須問重重", + "poem2": "", + "meaning": "", + "explanation": "凡事 不和。有鬼作祟。\n作事 未日辰日成好。\n家事 門第大益。\n家運 平常。\n婚姻 口舌多難成。(成者允吉)\n求兒 不好。有呆人。\n六甲 生男。(後女)\n求財 輕淡有利益。\n功名 未遂。不可。\n歲君 浮沉。\n治病 老不好。少不畏。\n出外 不可。\n經商 夥不和者。無利。\n來人 未日(半月)到。\n行舟 先凶後吉。\n移居 不可望。\n失物 無。\n求雨 尚未。\n官事 平後。拖尾。了錢。\n六畜 不好。\n耕作 早好。\n築室 好。\n墳墓 地氣漸發吉。\n討海 春夏不佳。冬平。\n作塭 先無利。後有望。\n魚苗 有利入手。\n月令 有口舌。\n尋人 慢回。\n遠信 音信慢至。", + "oracle": "", + "story": "1.佛印稍婆答歌詩\n2.蘇小妹答佛印(禪師)" + }, + { + "id": 50, + "no": "第五十籤【壬寅】", + "grade": "", + "palace": "", + "poem1": "佛前發誓無異心\n且看前途得好音\n此物原來本是鐵\n也能變化得成金", + "poem2": "", + "meaning": "", + "explanation": "凡事 有公人求完。吉。\n作事 難成。\n家事 家庭進益。\n家運 瑞氣滿門。\n婚姻 難成。成者大吉。\n求兒 好。大吉。\n六甲 男女貴氣。(先男後女)(男難養。生女好)\n求財 大吉。寶樹開花。\n功名 無。\n歲君 吉。\n治病 祝天地者平安。老拖尾。\n出外 不可。(慢即有大財)\n經商 先平平。後大吉。\n來人 月光到。\n行舟 早晚平平。\n移居 好。\n失物 急尋在。(西尋)\n求雨 及時。\n官事 拖尾。(去倒得失了錢)\n六畜 平安大進。\n耕作 早好晚平。\n築室 慢吉。\n墳墓 吉地吉穴。\n討海 和者大吉。\n作塭 先呆後有大利。\n魚苗 後有大利。\n月令 漸春風好。\n尋人 速回。\n遠信 音信速至。", + "oracle": "", + "story": "1.小兒遇三煞\n煞即殺。小兒煞有廿六關。于鬼有五鬼關和鬼門關。\n本屬凶象。有符可解。難關可過。\n諭人只要肯信。逢凶化吉。鐵可成金。信乎。\n(三煞指啥不明)。\n2.小兒路遇惡鬼" + }, + { + "id": 51, + "no": "第五一籤【壬辰】", + "grade": "", + "palace": "", + "poem1": "東西南北不堪行\n前途此事正可當\n勸君把定莫煩惱\n家門自有保安康", + "poem2": "", + "meaning": "", + "explanation": "凡事 自守待運。\n作事 勤成。\n家事 門庭大益。\n家運 門庭永昌。\n婚姻 成好。\n求兒 平平。\n六甲 先男後女。貴氣。\n求財 冬天大吉。(依舊好)\n功名 後科。\n歲君 吉。\n治病 命拖尾。老少安。\n出外 不可。\n經商 小利。(在家好)\n來人 月光到。\n行舟 了本。\n移居 不可。\n失物 尋有。\n求雨 不日到。\n官事 萬和。\n六畜 有利。\n耕作 早平晚好。\n築室 平平。\n墳墓 地勢適宜。\n討海 無大財。\n作塭 自守可得。\n魚苗 小利益。\n月令 不遂。\n尋人 時到則回。\n遠信 音信緩至。", + "oracle": "", + "story": "1.趙玄郎河東大戰龍虎關\n2.宋朝趙匡胤困河東" + }, + { + "id": 52, + "no": "第五二籤【壬午】", + "grade": "", + "palace": "", + "poem1": "功名事業本由天\n不須掛念意懸懸\n若問中間遲與速\n風雲際會在眼前\n掛字,另有改作介字一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 慢成。大險。\n作事 難成。(急成。遲者了錢)\n家事 家庭大吉。\n家運 到處有貴人。\n婚姻 成好。\n求兒 好。(不好。有事)\n六甲 添之弄璋。(生男)\n求財 浮沉。(有大利)\n功名 揚名在即。\n歲君 起倒。\n治病 三日過貴人好。\n出外 行遇主公。\n經商 萬商雲集。\n來人 立即到。\n行舟 有利可得。\n移居 平正。\n失物 難尋。(速尋在)\n求雨 多風雨少。\n官事 有虛。(破財完局)\n六畜 有利。\n耕作 平平有收。\n築室 可以平安。\n墳墓 穴場允吉。\n討海 得財在三日過。\n作塭 有大利。\n魚苗 此近日得大財。\n月令 平平。漸漸平安。\n尋人 漸回。\n遠信 音信立至。", + "oracle": "", + "story": "1.上帝公收龜蛇\n上帝公即北極玄天上帝(北帝)。又稱真武君。\n龜蛇于江中興波作浪。被北帝收服。\n其神像每見足踏龜蛇。如何收服未明。\n2.薛仁貴回家遇丁山" + }, + { + "id": 53, + "no": "第五三籤【壬申 】", + "grade": "", + "palace": "", + "poem1": "看君來問心中事\n積善之家慶有餘\n運亨財子雙雙至\n指日喜氣溢門閭", + "poem2": "", + "meaning": "", + "explanation": "凡事 大吉。有貴人。\n作事 成好。\n家事 進益無窮。\n家運 禎祥福祉。\n婚姻 成好。(益夫旺子)\n求兒 大富貴。\n六甲 先男後女。(雙生貴子)\n求財 積善大利。\n功名 無。(可得進)\n歲君 中平。\n治病 拖尾不畏。平安。\n出外 好。(利路亨通)\n經商 萬利可得。\n來人 月光到。\n行舟 大吉利。\n移居 平安。\n失物 援尋。\n求雨 月尾到。\n官事 緊審和好。(完者大吉)\n六畜 可納平安。\n耕作 中平。(大利)\n築室 可好。(瑞氣呈祥)\n墳墓 大吉。(世代流芳)\n討海 可得大進。\n作塭 滿載而歸。\n魚苗 有大利。\n月令 平安。\n尋人 得回。\n遠信 速報佳音。", + "oracle": "", + "story": "1.蘇秦夫妻相會\n2.蘇秦不第\n戰國。蘇秦。洛陽人。師鬼谷子。\n游說秦王。書十二上其說。不行。\n裘敝金盡。憔悴而歸。至家妻不下(織)機。(不理睬其夫)\n嫂不為炊。(不煮飯給其叔)\n秦慚怒。得太公陰符。發憤苦讀。\n困怠時用錐刺股。痛而再讀。\n後以合從(合縱)之說。聯六國抗秦。\n說趙竟佩六國相印。\n後回家喜氣洋洋。\n3.蘇秦回家假不第" + }, + { + "id": 54, + "no": "第五四籤【壬戌】", + "grade": "", + "palace": "", + "poem1": "孤燈寂寂夜沉沉\n萬事清吉萬事成\n若逢陰中有善果\n燒得好香達神明", + "poem2": "", + "meaning": "", + "explanation": "凡事 清吉。不用財。\n作事 難成。(必成)\n家事 望神保佑。\n家運 門庭興旺。\n婚姻 大吉。\n求兒 成好。\n六甲 弄璋之慶。(生男)\n求財 先無後有。\n功名 善心有。\n歲君 淡淡。\n治病 不畏。拖尾。祈神。\n出外 須靠自己。\n經商 勿與人合夥。\n來人 月尾到。\n行舟 小利。\n移居 好。(不可)\n失物 緊尋在。\n求雨 必來。\n官事 和好。(拖尾。得勝)\n六畜 小利。\n耕作 允好。\n築室 大吉。\n墳墓 地運(氣)亨通。\n討海 小利。\n作塭 小得微利。\n魚苗 自己有小利。\n月令 平平。求神庇佑。\n尋人 祈求。自回。\n遠信 音信急至。", + "oracle": "", + "story": "1.念月英相國寺\n2.念月英求佛嫁良緣" + }, + { + "id": 55, + "no": "第五五籤【癸丑】", + "grade": "", + "palace": "", + "poem1": "須知進退總虛言\n看看發暗未必全\n珠玉深藏還未變\n心中但得枉徒然", + "poem2": "", + "meaning": "", + "explanation": "凡事 了工。無利益。\n作事 難成。\n家事 家庭多逢口舌。\n家運 先凶後吉。\n婚姻 不成。\n求兒 不可。\n六甲 先男後女。(生男)(子媳晚得)\n求財 輕。\n功名 等後科。\n歲君 安。\n治病 不好。拖尾。\n出外 無貴人。\n經商 了錢。\n來人 未日(半月)到。\n行舟 無利。\n移居 不宜。\n失物 難尋。\n求雨 未有。\n官事 拖尾。了錢。\n六畜 了工無利。\n耕作 平平。\n築室 難得平安。\n墳墓 地勢不吉。\n討海 費了工。\n作塭 了資本。\n魚苗 蝕本。\n月令 不遂有口舌。\n尋人 難。\n遠信 漸且待望。", + "oracle": "", + "story": "1.郭華醉酒誤佳期\n胭脂記。宋郭華。治陽人。往汴京。赴試。\n因戀胭脂舖女。王月英之美。落第不歸。羈留汴京。\n與之約期私會。屆期。王月英至。值郭華酒飲過醉。推擠不醒。\n乃解日鞋。藏華懷中而回。華醒時。見鞋悔恨。仰吞而死。\n是何為。出門不知過。欲者戒焉。\n2.玉堂春求佛嫁良緣\n明朝正德年間(1506~1521)。名妓玉堂春與王三官(王景隆)相戀。\n三官耗盡金錢被逐。玉姐贈銀回家讀書求功名。一年後中秋。\n玉堂春向神明祝願三官中榜。以結良緣。\n對月燒香禱告天。何時得洩腹中冤。\n王郎有日登金榜。不枉今生結好緣。\n三官高中第四名。但玉姐被老鴇賣給山西商人沈洪。\n沈洪又被妻毒死。其妻誣告玉堂春殺夫。\n知縣受賂。玉堂春被苦打成招。\n王三官有幸被派山西巡按。最後冤情大白。終成眷屬。\n(故事出自警世通言)" + }, + { + "id": 56, + "no": "第五六籤【癸卯】", + "grade": "", + "palace": "", + "poem1": "病中若得苦心勞\n到底完全總未遭\n去後不須回頭問\n心中事務盡消磨", + "poem2": "", + "meaning": "", + "explanation": "凡事 小心為要。(成者不好)\n作事 難成。\n家事 門庭小吉。\n家運 平常罔居。\n婚姻 不可。\n求兒 不吉。(無根基)\n六甲 先女後男。(生男)(無求必得)\n求財 空無。\n功名 難望。(可望)\n歲君 頗安。\n治病 先凶後吉。\n出外 在家待時。\n經商 多勞辛苦。\n來人 未日(半月)到\n行舟 無利益。\n移居 不好。\n失物 未日(半月)在。(無處可尋)\n求雨 尚未。\n官事 拖尾。(了錢)\n六畜 不可。\n耕作 平平。(無。半收)\n築室 多逢疾病。不佳。\n墳墓 淡淡平平。\n討海 無利益。\n作塭 失利無望。\n魚苗 無利了錢。\n月令 不遂。\n尋人 信尚遠。\n遠信 音信耐候。", + "oracle": "", + "story": "楊戩得病在西軒" + }, + { + "id": 57, + "no": "第五七籤【癸巳】", + "grade": "", + "palace": "", + "poem1": "勸君把定心莫虛\n前途清吉得運時\n到底中間無大事\n又遇神仙守安居", + "poem2": "", + "meaning": "", + "explanation": "凡事 心意把定。\n作事 成好。\n家事 且喜進益。\n家運 神仙扶持。平安。\n婚姻 大吉。\n求兒 大吉。\n六甲 先女後男。(月頭女。月尾男)(弄璋喜慶)\n求財 輕得。(應手而得)\n功名 必中。\n歲君 淡淡。\n治病 漸平安。貴人扶。\n出外 遇貴人提攜。(在家好)\n經商 小有成就。(永發其財)\n來人 未日(半月)到。\n行舟 平平有財。\n移居 平安。(不宜)\n失物 難尋。(謹尋有)\n求雨 不日到。\n官事 宜求和解。\n六畜 平平。\n耕作 平平有收。\n築室 平安。\n墳墓 地運如意。\n討海 有利入手。\n作塭 有利可得。\n魚苗 有大利。\n月令 破財。平安。\n尋人 只近回。\n遠信 且候佳音。", + "oracle": "", + "story": "1.白蛇精遇許漢文。(許宣)\n宋朝高宗年間。杭州賣藥郎許宣。父母早逝。\n清明往廟燒香祭祖。事後乘船。遇一白衣婦人求搭。\n同舟共慕。白衣婦實白蛇精所化。\n白蛇把心不定。千年道行一朝喪。\n許宣把心不定。屢遭官司。\n2.龐涓孫臏學法\n戰國。孫臏齊人。龐涓魏人。同師事鬼谷子。\n孫臏之學優於龐涓。涓為魏將。與臏鬥智。輸而忌之。\n乃以計刖其足。後孫臏假作顛狂。得脫歸。" + }, + { + "id": 58, + "no": "第五八籤【癸未】", + "grade": "", + "palace": "", + "poem1": "蛇身意欲變成龍\n只恐命內運未通\n久病且作寬心坐\n言語雖多不可從", + "poem2": "", + "meaning": "", + "explanation": "凡事 不好。難成。\n作事 未日抽。成好。\n家事 漸待。莫得。\n家運 不順。\n婚姻 不吉。\n求兒 不可。\n六甲 弄璋之喜。\n求財 淡淡。\n功名 未該得。不能進。\n歲君 平平。\n治病 拖尾。不痊癒。\n出外 未日抽成。\n經商 無利可求。\n來人 己未日(半月)到。\n行舟 可得小利。(無利)\n移居 不可。\n失物 尋在。\n求雨 遠。\n官事 反覆。(恐生尚端)\n六畜 了錢不利。\n耕作 中平。\n築室 等待。\n墳墓 穴地平安。\n討海 可得小利。\n作塭 無財利。\n魚苗 不可採買。\n月令 破財。多逢口舌。\n尋人 辰日在。\n遠信 音信且待。", + "oracle": "", + "story": "1.白蛇精詐言往南海遇漢文\n2.袁達入昭國關" + }, + { + "id": 59, + "no": "第五九籤【癸酉】", + "grade": "", + "palace": "", + "poem1": "有心作福莫遲疑\n求名清吉正當時\n此事必能成會合\n財寶自然喜相隨", + "poem2": "", + "meaning": "", + "explanation": "凡事 後吉得利。\n作事 難成。成者好。\n家事 百福百祿。\n家運 門庭增輝。\n婚姻 成好。\n求兒 亦可得。\n六甲 得添弄璋。(男女貴氣)\n求財 慢好。有利益。\n功名 有可得。\n歲君 平和。\n治病 子丑寅過不畏。\n出外 平安。(後得財星拱照)\n經商 先呆。後有利。\n來人 未日(半月)到。\n行舟 後吉。\n移居 好。\n失物 未日(半月)在。\n求雨 不日到。\n官事 中和。了錢。完局。\n六畜 平平。\n耕作 有收成。\n築室 吉。\n墳墓 地運參差。\n討海 先失後得。\n作塭 有利可得。\n魚苗 且慢可得利。\n月令 漸安。\n尋人 有著。\n遠信 佳音速報。", + "oracle": "", + "story": "1.皇都市上有神仙\n2.老鼠精鬧宋朝\n這是一部神怪小說。敍述五個老鼠精變成人形,猖獗為害擾亂社會。最後包公上奏玉帝,向西天雷音寺如來處借來玉面金貓,降伏了五鼠的故事。\n這一故事出自《包龍圖判百家公案》(包公案)第五十八回決戮五鼠鬧東京(簡稱『五鼠鬧東京』)。\n雖然『五鼠鬧東京』故事很長,建議還是看清全部故事再行解籤,故事全文詳見:\nhttp://www.open-lit.com/listbook.php?cid=3&gbid=188&start=0" + }, + { + "id": 60, + "no": "第六十籤【癸亥】", + "grade": "", + "palace": "", + "poem1": "月出光輝本清吉\n浮雲總是蔽陰色\n戶內用心再作福\n當官分理便有益\n陰字,另有改作蔭字一說。", + "poem2": "", + "meaning": "", + "explanation": "凡事 拖尾。了錢。\n作事 成無益。犯官事。\n家事 門庭平安。\n家運 小吉。\n婚姻 難得。\n求兒 慢即好。\n六甲 臨產空孕。(生女)(先男後女)\n求財 淡有。\n功名 望後科。\n歲君 把方殺。\n治病 拖尾。後痊癒。(男女犯魂必死)\n出外 不可。\n經商 後來有得。\n來人 月光到。\n行舟 有小利。(把定)\n移居 不可。\n失物 月光在。\n求雨 不日到。\n官事 不畏。\n六畜 不得利。了錢。\n耕作 平平。\n築室 不合。按住。\n墳墓 地運呆。後得吉。\n討海 平平小利。\n作塭 有小利。\n魚苗 無利可得。\n月令 不遂。\n尋人 遠回。\n遠信 音信慢至。", + "oracle": "", + "story": "1.薛剛踢死太子驚崩聖駕\n2.楊六婿斬子" + } +] \ No newline at end of file