subjective

📁 simhacker/moollm 📅 Jan 26, 2026
10
总安装量
2
周安装量
#30800
全站排名
安装命令
npx skills add https://github.com/simhacker/moollm --skill subjective

Agent 安装分布

opencode 2
command-code 2
claude-code 2
github-copilot 2
codex 2
gemini-cli 2

Skill 文档

Subjective-Oriented Programming

“i_have(‘key’) reads naturally. ‘Does the world have a key?’ does not.” — The Gezelligheid Grotto Design Principles


What Is It?

Subjective-oriented programming uses i_ prefixed functions that speak from the current subject’s perspective. The “I” shifts based on context:

Context Who is “I”?
Player action The player character
Object simulate() The object
NPC dialogue The NPC
Room description The room

The Problem with world.

// Third-person: "Does the world have a key?"
if (world.has("key")) ...

// But who has the key? The world? The player? Confusing!

The Solution: i_

// First-person: "Do I have a key?"
if (i_have("key")) ...

// Clear! The current subject is asking about themselves.

Core i_ Functions

Inventory

i_have("key")           // Do I have this item?
i_give("key")           // Give item to current target
i_take("key")           // Take item from current target
i_drop("key")           // Drop item in current room
i_has_tag("weapon")     // Do I have any item with this tag?
i_find_by_tag("food")   // Find all my items with this tag

State

i_am("lit")             // Am I in this state? (object.state.lit)
i_am_not("broken")      // Am I NOT in this state?
i_set("lit", true)      // Set my state
i_get("fuel")           // Get my state value

Buffs

i_have_buff("strength")     // Do I have this buff?
i_add_buff(buff)            // Apply buff to myself
i_remove_buff("strength")   // Remove buff from myself

Flags

i_flag("door_unlocked")     // Is this flag set?
i_set_flag("door_unlocked") // Set this flag

Location

i_am_in("pub/")             // Am I in this room?
i_can_see("treasure")       // Can I see this object?
i_go("north")               // Move in direction

Communication

i_say("Hello!")             // Emit dialogue
i_emote("grins widely")     // Emit emote
i_think("This is odd...")   // Emit internal thought

Context Shifting

The meaning of i_ changes based on who is “speaking”:

Player Context

# In player action handlers
effect: |
  if i_have("key"):
    i_say("I found the key!")
    i_drop("key")  # Drop in current room

Object Context (simulate)

# In object's simulate field
simulate: |
  if i_am("lit"):
    i_set("fuel", i_get("fuel") - 1)
    if i_get("fuel") <= 0:
      i_set("lit", false)
      i_emit("The lamp dies!")

NPC Context

# In NPC dialogue/behavior
behavior: |
  if i_have("gold") and i_can_see("beggar"):
    i_give("gold")
    i_say("For you, friend.")

Room Context

# In room description/behavior
describe: |
  if i_am("dark"):
    i_emit("You can't see anything.")
  else:
    i_emit("A cozy room with a fireplace.")

Implementation

The i_ functions are bound to the current subject:

class World {
  // The current subject ("I")
  get subject() {
    return this.object || this.npc || this.player;
  }
  
  // === INVENTORY (subjective) ===
  
  i_have(itemId) {
    const inv = this.subject.inventory || [];
    return inv.includes(itemId);
  }
  
  i_give(itemId) {
    const inv = this.subject.inventory || [];
    const idx = inv.indexOf(itemId);
    if (idx > -1) {
      inv.splice(idx, 1);
      (this.target.inventory ??= []).push(itemId);
    }
  }
  
  i_take(itemId) {
    const targetInv = this.target.inventory || [];
    const idx = targetInv.indexOf(itemId);
    if (idx > -1) {
      targetInv.splice(idx, 1);
      (this.subject.inventory ??= []).push(itemId);
    }
  }
  
  i_drop(itemId) {
    const inv = this.subject.inventory || [];
    const idx = inv.indexOf(itemId);
    if (idx > -1) {
      inv.splice(idx, 1);
      (this.room.objects ??= []).push({ id: itemId });
    }
  }
  
  i_has_tag(tag) {
    const inv = this.subject.inventory || [];
    for (const itemId of inv) {
      const item = this.getObject(itemId);
      if (item && (item.tags || []).includes(tag)) {
        return true;
      }
    }
    return false;
  }
  
  // === STATE (subjective) ===
  
  i_am(stateKey) {
    return this.subject.state?.[stateKey] === true;
  }
  
  i_am_not(stateKey) {
    return !this.i_am(stateKey);
  }
  
  i_get(stateKey) {
    return this.subject.state?.[stateKey];
  }
  
  i_set(stateKey, value) {
    this.subject.state ??= {};
    this.subject.state[stateKey] = value;
  }
  
  // === BUFFS (subjective) ===
  
  i_have_buff(buffId) {
    const buffs = this.subject.buffs || [];
    return buffs.some(b => b.id === buffId);
  }
  
  i_add_buff(buff) {
    this.subject.buffs ??= [];
    this.subject.buffs.push(buff);
  }
  
  i_remove_buff(buffId) {
    const buffs = this.subject.buffs || [];
    this.subject.buffs = buffs.filter(b => b.id !== buffId);
  }
  
  // === LOCATION (subjective) ===
  
  i_am_in(roomPath) {
    return this.subject.location === roomPath ||
           this.room?.path === roomPath;
  }
  
  i_can_see(objectId) {
    const objects = this.room?.objects || [];
    return objects.some(o => o.id === objectId);
  }
  
  i_go(direction) {
    this._pendingNavigation = direction;
  }
  
  // === COMMUNICATION (subjective) ===
  
  i_say(message) {
    this.emit(`${this.subject.name}: "${message}"`);
  }
  
  i_emote(action) {
    this.emit(`${this.subject.name} ${action}`);
  }
  
  i_think(thought) {
    this.emit(`(${this.subject.name} thinks: "${thought}")`);
  }
  
  i_emit(message) {
    this.emit(message);
  }
}

Python Equivalent

class World:
    @property
    def subject(self):
        """The current 'I' — object, NPC, or player."""
        return self.object or self.npc or self.player
    
    def i_have(self, item_id: str) -> bool:
        inv = self.subject.get('inventory', [])
        return item_id in inv
    
    def i_am(self, state_key: str) -> bool:
        return self.subject.get('state', {}).get(state_key) == True
    
    def i_get(self, state_key: str):
        return self.subject.get('state', {}).get(state_key)
    
    def i_set(self, state_key: str, value):
        state = self.subject.setdefault('state', {})
        state[state_key] = value
    
    def i_say(self, message: str):
        self.emit(f"{self.subject.get('name')}: \"{message}\"")
    
    def i_emit(self, message: str):
        self.emit(message)
    
    # ... etc

Natural Language Compilation

The LLM compiles natural language to i_ calls:

# Natural language
guard: "I have the key and I am not cursed"

# Compiled
guard_js: (world) => world.i_have("key") && !world.i_have_buff("cursed")
guard_py: lambda world: world.i_have("key") and not world.i_have_buff("cursed")
# Natural language (object context)
simulate: |
  if I am lit and fuel > 0:
    consume 1 fuel
    if fuel reaches 0:
      I am no longer lit
      say "The lamp dies!"

# Compiled
simulate_js: (world) => {
  if (world.i_am("lit") && world.i_get("fuel") > 0) {
    world.i_set("fuel", world.i_get("fuel") - 1);
    if (world.i_get("fuel") <= 0) {
      world.i_set("lit", false);
      world.i_emit("The lamp dies!");
    }
  }
}

The i_ vs world. Split

Use i_ when… Use world. when…
Acting as current subject Accessing global state
Checking own inventory Checking adventure flags
Modifying own state Navigating rooms
Speaking in first person Managing party
// Mixed example
if (i_have("key") && world.flag("door_visible")) {
  i_say("I can unlock this door!");
  world.set_flag("door_unlocked", true);
}

Benefits

  1. Readable — i_have("key") reads like English
  2. Context-aware — “I” shifts naturally
  3. Object-oriented — Objects think for themselves
  4. Compilable — LLM can translate natural language easily
  5. Debuggable — Clear who is speaking in logs

Protocol Symbol

SUBJECTIVE-ORIENTED — The "I" shifts based on who is speaking