Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/SimHacker/moollm --skill subjective명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
SOC 직업 분류 기준
| name | subjective |
| description | First-person code — the "I" shifts based on who is speaking |
| allowed-tools | ["read_file","write_file"] |
| tier | 1 |
| protocol | SUBJECTIVE-ORIENTED |
| tags | ["moollm","programming","perspective","first-person","context"] |
| related | ["context","runtime","object","character"] |
| adversary | third-person-coupling |
"i_have('key') reads naturally. 'Does the world have a key?' does not." — The Gezelligheid Grotto Design Principles
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 |
world.// Third-person: "Does the world have a key?"
if (world.has("key")) ...
// But who has the key? The world? The player? Confusing!
i_// First-person: "Do I have a key?"
if (i_have("key")) ...
// Clear! The current subject is asking about themselves.
i_ Functionsi_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
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
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
i_flag("door_unlocked") // Is this flag set?
i_set_flag("door_unlocked") // Set this flag
i_am_in("pub/") // Am I in this room?
i_can_see("treasure") // Can I see this object?
i_go("north") // Move in direction
i_say("Hello!") // Emit dialogue
i_emote("grins widely") // Emit emote
i_think("This is odd...") // Emit internal thought
The meaning of i_ changes based on who is "speaking":
# In player action handlers
effect: |
if i_have("key"):
i_say("I found the key!")
i_drop("key") # Drop in current room
# 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!")
# In NPC dialogue/behavior
behavior: |
if i_have("gold") and i_can_see("beggar"):
i_give("gold")
i_say("For you, friend.")
# 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.")
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);
(.. ??= []).(itemId);
}
}
() {
inv = .. || [];
idx = inv.(itemId);
(idx > -) {
inv.(idx, );
(.. ??= []).({ : itemId });
}
}
() {
inv = .. || [];
( itemId inv) {
item = .(itemId);
(item && (item. || []).(tag)) {
;
}
}
;
}
() {
..?.[stateKey] === ;
}
() {
!.(stateKey);
}
() {
..?.[stateKey];
}
() {
.. ??= {};
..[stateKey] = value;
}
() {
buffs = .. || [];
buffs.( b. === buffId);
}
() {
.. ??= [];
...(buff);
}
() {
buffs = .. || [];
.. = buffs.( b. !== buffId);
}
() {
.. === roomPath ||
.?. === roomPath;
}
() {
objects = .?. || [];
objects.( o. === objectId);
}
() {
. = direction;
}
() {
.();
}
() {
.();
}
() {
.();
}
() {
.(message);
}
}
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):
.emit()
():
.emit(message)
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!");
}
}
}
i_ vs world. SplitUse 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);
}
i_have("key") reads like EnglishSUBJECTIVE-ORIENTED — The "I" shifts based on who is speaking