subjective

First-person code — the "I" shifts based on who is speaking

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "subjective" with this command: npx skills add simhacker/moollm/simhacker-moollm-subjective

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:

ContextWho is "I"?
Player actionThe player character
Object simulate()The object
NPC dialogueThe NPC
Room descriptionThe 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 subjectAccessing global state
Checking own inventoryChecking adventure flags
Modifying own stateNavigating rooms
Speaking in first personManaging 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. Readablei_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

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

context

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

code-review

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

sniffable-python

No summary provided by upstream source.

Repository SourceNeeds Review
General

self-repair

No summary provided by upstream source.

Repository SourceNeeds Review