Skip to main content
Glama
events.ts5.99 kB
import type { EventLogEntry, EventType, Equipment, Item } from '../types.js'; import { ITEMS_POOL, cloneItem } from '../data/items.js'; interface EventConfig { type: EventType; probability: number; // 0-1 description: string; goldChange?: [number, number]; // [min, max] damageRange?: [number, number]; // [min, max] floorsSkipped?: number; canDropItem?: boolean; canDropHoldingItem?: boolean; } // イベント定義(自然言語で記述) const EVENT_CONFIGS: EventConfig[] = [ { type: 'trap_fall', probability: 0.05, description: '落とし穴に落ちて次の階に転落した!', floorsSkipped: 1 }, { type: 'poison', probability: 0.08, description: '毒の罠を踏んでしまった!', damageRange: [5, 15] }, { type: 'treasure', probability: 0.1, description: '隠された宝箱を発見した!', goldChange: [20, 50], canDropItem: true }, { type: 'healing_fountain', probability: 0.06, description: '癒しの泉を発見した。体力が回復した。', damageRange: [-20, -10] // マイナスは回復 }, { type: 'trap_damage', probability: 0.12, description: '針の罠が作動した!', damageRange: [3, 8] }, { type: 'shortcut', probability: 0.04, description: '隠し通路を発見!階段を飛ばして進んだ。', floorsSkipped: 2 }, { type: 'ambush', probability: 0.1, description: '敵の奇襲を受けた!', damageRange: [10, 20] }, { type: 'item_drop', probability: 0.08, description: '宝箱の中に持ち物を発見した!', canDropHoldingItem: true } ]; export function rollForEvent( floor: number, luckStat: number, rewardPool: Equipment[], equippedCharm?: Item, itemRewardPool?: Item[] ): EventLogEntry | null { // 運が高いほどポジティブなイベント発生率が上がる const luckModifier = luckStat / 100; for (const config of EVENT_CONFIGS) { let probability = config.probability; // ポジティブなイベントは運で確率上昇 if (config.type === 'treasure' || config.type === 'healing_fountain' || config.type === 'shortcut' || config.type === 'item_drop') { probability *= (1 + luckModifier); } // ネガティブなイベントは運で確率減少 else { probability *= (1 - luckModifier * 0.5); } if (Math.random() < probability) { const event = generateEvent(floor, config, rewardPool, itemRewardPool); // Check if charm should block this negative event if ( equippedCharm?.effect.blockNegativeEvent && isNegativeEvent(config.type) ) { event.charmBlocked = true; event.description = 'おまもりが災難から守ってくれた!'; event.effect = {}; // Clear all negative effects } return event; } } return null; } function isNegativeEvent(eventType: EventType): boolean { const negativeEvents: EventType[] = [ 'trap_fall', 'poison', 'trap_damage', 'ambush' ]; return negativeEvents.includes(eventType); } function generateEvent( floor: number, config: EventConfig, rewardPool: Equipment[], itemRewardPool?: Item[] ): EventLogEntry { const event: EventLogEntry = { floor, type: config.type, description: config.description, effect: {} }; // ゴールド変化 if (config.goldChange) { const [min, max] = config.goldChange; event.effect.goldChange = Math.floor(Math.random() * (max - min + 1)) + min; } // ダメージ/回復 if (config.damageRange) { const [min, max] = config.damageRange; event.effect.damageDealt = Math.floor(Math.random() * (max - min + 1)) + min; } // 階層スキップ if (config.floorsSkipped) { event.effect.floorsSkipped = config.floorsSkipped; } // アイテムドロップ if (config.canDropItem && Math.random() < 0.3 && rewardPool.length > 0) { const randomItem = rewardPool[Math.floor(Math.random() * rewardPool.length)]; event.effect.itemsGained = [randomItem]; } // 持ち物ドロップ(ダンジョン固有のプールから選択、なければ全体プールから) if (config.canDropHoldingItem) { const pool = itemRewardPool && itemRewardPool.length > 0 ? itemRewardPool : ITEMS_POOL; if (pool.length > 0) { const randomHoldingItem = pool[Math.floor(Math.random() * pool.length)]; event.effect.holdingItemsGained = [cloneItem(randomHoldingItem)]; } } return event; } // イベント結果を日本語で説明 export function formatEventDescription(event: EventLogEntry): string { let output = `【${event.floor}階】${event.description}`; if (event.effect.goldChange) { if (event.effect.goldChange > 0) { output += ` (ゴールド +${event.effect.goldChange})`; } else { output += ` (ゴールド ${event.effect.goldChange})`; } } if (event.effect.damageDealt) { if (event.effect.damageDealt > 0) { output += ` (ダメージ ${event.effect.damageDealt})`; } else { output += ` (回復 ${Math.abs(event.effect.damageDealt)})`; } } if (event.effect.floorsSkipped) { output += ` (${event.effect.floorsSkipped}階スキップ)`; } if (event.effect.itemsGained && event.effect.itemsGained.length > 0) { const items = event.effect.itemsGained.map(i => i.name).join(', '); output += ` (装備入手: ${items})`; } if (event.effect.holdingItemsGained && event.effect.holdingItemsGained.length > 0) { const items = event.effect.holdingItemsGained.map(i => i.name).join(', '); output += ` (持ち物入手: ${items})`; } if (event.charmBlocked) { output += ' (おまもりで回避!)'; } return output; } // カスタムイベントを追加する関数(将来的な拡張用) export function addCustomEvent(config: EventConfig): void { EVENT_CONFIGS.push(config); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/bellsanct/mcp-dungeon-game'

If you have feedback or need assistance with the MCP directory API, please join our Discord server