Skip to main content

runtime

Dual Python/JavaScript adventure runtimes — always in sync

来源信息

仓库
SimHacker/moollm
最近来源活动
2026年2月9日 21:17
检测到的 SKILL.md 语言
英语
星标
60
Forks
5

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
5 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
runtime
description
Dual Python/JavaScript adventure runtimes — always in sync
allowed-tools
["read_file","write_file"]
tier
1
protocol
DUAL-RUNTIME
tags
["moollm","runtime","python","javascript","compilation","sync"]
related
["context","adventure","object","expression"]
adversary
single-target
# Runtime > *"Test in Python, deploy to browser. Same semantics, both targets."* > — Vanessa Freudenberg (memorial voice) --- ## What Is It? The **Runtime** skill defines the dual Python/JavaScript adventure engines. Both runtimes: - Execute compiled expressions - Manage world state - Process simulation ticks - Handle events **CRITICAL:** We ALWAYS generate BOTH `_js` AND `_py` code. Never one without the other. --- ## Why Dual Runtimes? | Runtime | Purpose | |---------|---------| | **Python** | Server-side, testing, LLM tethering, CLI | | **JavaScript** | Browser, standalone play, offline | ```yaml # Dual Runtime Architecture dual_runtime: source: "YAML" compiler: "LLM" outputs: guard_js: "(world) => ..." guard_py: "lambda world: ..." runtimes: python: file: "adventure.py" targets: ["CLI", "Server"] javascript: file: "engine.js" targets: ["Browser", "SPA"] ``` --- ## The World Object Both runtimes implement identical `World` classes: ### Python ```python class World: """Adventure runtime context for Python.""" def __init__(self, adventure_data: dict): # Standard keys self.turn = 0 self.timestamp = None self.adventure = adventure_data self.player = adventure_data.get('player', {}) self.room = None self.party = adventure_data.get('party', {}) # Extended keys (set contextually) self.object = None # During object simulation self.target = None # During targeted action self.npc = None # During NPC simulation # Skill state namespaces self.skills = DotDict() # world.skills.economy.gold # INVENTORY def has(self, item_id: str) -> bool: return item_id in self.player.get('inventory', []) def has_tag(self, tag: str) -> bool: """Check if player has any item with the given tag.""" for item_id in self.player.get('inventory', []): item = self.get_object(item_id) if item and tag in item.get('tags', []): return True return False def find_by_tag(self, tag: str, in_room: bool = True) -> list: """Find all objects with the given tag.""" results = [] # Check inventory for item_id in self.player.get('inventory', []): item = self.get_object(item_id) if item and tag in item.get('tags', []): results.append(item) # Check current room if in_room and self.room: for obj in self.room.get('objects', []): if tag in obj.get('tags', []): results.append(obj) return results def give(self, item_id: str): inv = self.player.setdefault('inventory', []) inv.append(item_id) def take(self, item_id: str): inv = self.player.get('inventory', []) if item_id in inv: inv.remove(item_id) # FLAGS def flag(self, name: str) -> bool: return self.adventure.get('flags', {}).get(name, False) def set_flag(self, name: str, value: bool): flags = self.adventure.setdefault('flags', {}) flags[name] = value # NARRATIVE def emit(self, message: str): self._output_queue.append(message) def narrate(self, message: str, style: str = "normal"): self._output_queue.append({'text': message, 'style': style}) # EVENTS def trigger_event(self, name: str, data: dict = None): self._event_queue.append({'name': name, 'data': data or {}}) # NAVIGATION def go(self, destination: str): self._pending_navigation = destination def can_go(self, direction: str) -> bool: exits = self.room.get('exits', {}) return direction in exits # BUFFS def has_buff(self, buff_id: str) -> bool: buffs = self.player.get('buffs', []) return any(b.get('id') == buff_id for b in buffs) def add_buff(self, buff: dict): buffs = self.player.setdefault('buffs', []) buffs.append(buff) def remove_buff(self, buff_id: str): buffs = self.player.get('buffs', []) self.player['buffs'] = [b for b in buffs if b.get('id') != buff_id] # EFFECTIVE VALUES (Buff Modification Protocol) # # Base value = persistent truth # Effective value = recalculated each tick # # "The base value is truth. The effective value is reality." # def reset_effective(self, obj: dict = None): """ Reset all effective values to their base values. Called at the start of each tick. """ obj = obj or self.object if not obj or 'state' not in obj: return state = obj['state'] for key in list(state.keys()): if not key.endswith('_effective'): effective_key = f"{key}_effective" state[effective_key] = state[key] def get_effective(self, obj: dict, prop: str): """Get effective value, falling back to base if not set.""" state = obj.get('state', {}) effective_key = f"{prop}_effective" if effective_key in state: return state[effective_key] return state.get(prop) def modify_effective(self, obj: dict, prop: str, delta): """Add delta to effective value.""" state = obj.get('state', {}) effective_key = f"{prop}_effective" state[effective_key] = state.get(effective_key, state.get(prop, 0)) + delta def multiply_effective(self, obj: dict, prop: str, factor: float): """Multiply effective value by factor.""" state = obj.get('state', {}) effective_key = f"{prop}_effective" state[effective_key] = state.get(effective_key, state.get(prop, 0)) * factor # RESILIENCE (SimCity Zone Pattern) # # WILL WRIGHT: "If one tile burns but the center survives, # the zone will eventually rebuild." # def ensure_defaults(self, obj: dict = None) -> dict: """ Ensure object has its default state values. Self-initializing: creates state if missing. Self-healing: clamps invalid values. """ obj = obj or self.object if not obj: return {} # Create state if missing if 'state' not in obj: obj['state'] = {} # Merge defaults defaults = obj.get('defaults', {}) for key, default_val in defaults.items(): if key not in obj['state']: obj['state'][key] = default_val return obj['state'] def heal_state(self, obj: dict = None): """ Fix inconsistent state values. - Clamp negative numbers to 0 - Fix logical inconsistencies """ state = self.ensure_defaults(obj) # Clamp numeric values to non-negative for key, val in list(state.items()): if isinstance(val, (int, float)) and val < 0: state[key] = 0 return state # STATE ACCESS def get(self, path: str): """Get value by dot path: world.get('object.state.fuel')""" parts = path.split('.') obj = self for part in parts: if isinstance(obj, dict): obj = obj.get(part) else: obj = getattr(obj, part, None) if obj is None: return None return obj def set(self, path: str, value): """Set value by dot path: world.set('object.state.lit', True)""" parts = path.split('.') obj = self for part in parts[:-1]: if isinstance(obj, dict): obj = obj.setdefault(part, {}) else: obj = getattr(obj, part) if isinstance(obj, dict): obj[parts[-1]] = value else: setattr(obj, parts[-1], value) ``` ### JavaScript ```javascript class World { /** Adventure runtime context for JavaScript. */ constructor(adventureData) { // Standard keys this.turn = 0; this.timestamp = null; this.adventure = adventureData; this.player = adventureData.player || {}; this.room = null; this.party = adventureData.party || {}; // Extended keys (set contextually) this.object = null; // During object simulation this.target = null; // During targeted action this.npc = null; // During NPC simulation // Skill state namespaces this.skills = {}; // world.skills.economy.gold // Internal queues this._outputQueue = []; this._eventQueue = []; this._pendingNavigation = null; } // === INVENTORY === has(itemId) { return (this.player.inventory || []).includes(itemId); } hasTag(tag) { /** Check if player has any item with the given tag. */ for (const itemId of this.player.inventory || []) { const item = this.getObject(itemId); if (item && (item.tags || []).includes(tag)) { return true; } } return false; } findByTag(tag, inRoom = true) { /** Find all objects with the given tag. */ const results = []; // Check inventory for (const itemId of this.player.inventory || []) { const item = this.getObject(itemId); if (item && (item.tags || []).includes(tag)) { results.push(item); } } // Check current room if (inRoom && this.room) { for (const obj of this.room.objects || []) { if ((obj.tags || []).includes(tag)) { results.push(obj); } } } return results; } give(itemId) { this.player.inventory = this.player.inventory || []; this.player.inventory.push(itemId); } take(itemId) { const inv = this.player.inventory || []; const idx = inv.indexOf(itemId); if (idx > -1) inv.splice(idx, 1); } // === FLAGS === flag(name) { return (this.adventure.flags || {})[name] || false; } setFlag(name, value) { this.adventure.flags = this.adventure.flags || {}; this.adventure.flags[name] = value; } // === NARRATIVE === emit(message) { this._outputQueue.push(message); } narrate(message, style = "normal") { this._outputQueue.push({ text: message, style }); } // === EVENTS === triggerEvent(name, data = {}) { this._eventQueue.push({ name, data }); } // === NAVIGATION === go(destination) { this._pendingNavigation = destination; } canGo(direction) { const exits = this.room?.exits || {}; return direction in exits; } // === BUFFS === hasBuff(buffId) { const buffs = this.player.buffs || []; return buffs.some(b => b.id === buffId); } addBuff(buff) { this.player.buffs = this.player.buffs || []; this.player.buffs.push(buff); } removeBuff(buffId) { const buffs = this.player.buffs || []; this.player.buffs = buffs.filter(b => b.id !== buffId); }
在 GitHub 查看
这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看