Nostrmon — Decentralized Monster-Taming World Protocol

Specifies: kind 30597 kind 30259 kind 38267 kind 36011 kind 35253 kind 39951

NIP-XX: Nostrmon — Decentralized Monster-Taming World Protocol

draft optional

Abstract

This NIP defines a decentralized monster-taming game protocol on Nostr. “Nostrmon” (Nostr Monsters) is a framework inspired by games like Pokémon, where regions, maps, Nostrmon creatures, NPCs, and game saves are all Nostr addressable events. Anyone can create and publish content — regions, maps, creatures, or NPCs — and clients can assemble these events into a playable, traversable world.


Event Kinds

Kind Name Description
30597 Region A named region containing references to maps
30259 Map A 2D grid-based map with layered tile data
38267 Nostrmon A Nostr Monster creature definition
36011 NPC A Non-Player Character (simple or AI-driven)
35253 Game Save A player’s game progress snapshot
39951 Item A usable, holdable, or key item definition

Kind 30597 — Region

A Region is a named collection of maps that form a coherent geographical area. Each user may publish as many regions as they wish.

Tags

Tag Req. Description
d Unique identifier for the region (slug)
name Human-readable region name
map One or more references to map events. Value: naddr of map
entry The d tag of the map that serves as the travel entry/exit point for this region
summary Short description of the region
image URL of a banner or splash image for the region
music naddr of a default music event (kind 36787) for the region
t Hashtags for discovery (e.g., nostrmon)
alt NIP-31 human-readable description: "Nostrmon region: <name>"

Example

{
  "kind": 30597,
  "content": "A vast volcanic region with ancient ruins and mysterious tunnels.",
  "tags": [
    ["d", "ashfire-region"],
    ["name", "Ashfire Region"],
    ["map", "naddr1...map1"],
    ["map", "naddr1...map2"],
    ["entry", "ashfire-gateway"],
    ["summary", "A volcanic region full of fire-type Nostrmon."],
    ["image", "https://example.com/ashfire-banner.jpg"],
    ["music", "naddr1...battletheme"],
    ["t", "nostrmon"],
    ["alt", "Nostrmon region: Ashfire Region"]
  ]
}

Kind 30259 — Map

A Map is a 2D, grid-based environment with up to 5 layers. Maps are the atomic playable unit of the world.

Tags

Tag Req. Description
d Unique identifier (slug) for the map
name Human-readable map name
type Map type: route, area, town, city, dungeon, house
width Map width in tiles (integer, as string)
height Map height in tiles (integer, as string)
region naddr of the region this map belongs to. Absent = “Unknown Region”
music naddr of a music event (kind 36787) for this map
multiplayer "true" or "false". Default: "false"
prison "true" or "false". Default: "false". Disables fast travel on map
daynight "true" or "false". Whether day/night cycle is visible. Default: "true"
entry-map "true" or "false". Marks this map as the region’s travel gateway. Entry maps can be linked to entry maps of other regions for cross-region warps.
fasttravel-x X tile coordinate where the player spawns when fast-traveling to this map (integer string). Default: "1"
fasttravel-y Y tile coordinate where the player spawns when fast-traveling to this map (integer string). Default: "1"
image URL of a preview image for the map
t Tags for discovery, always include nostrmon
alt NIP-31 description: "Nostrmon map: <name>"

Content

The content field is a JSON object with the following structure:

interface MapContent {
  // Layer 1 (REQUIRED): Terrain layer
  // 2D array [row][col] of terrain tile IDs (integers)
  terrain: number[][];

  // Layer 2 (REQUIRED): Interactive layer
  // Sparse array of interactive objects keyed by "x,y"
  interactive: Record<string, InteractiveObject>;

  // Layer 3 (OPTIONAL): Height map for 3D rendering
  // 2D array [row][col] of height values (0.0–1.0)
  heightmap?: number[][];

  // Layer 4 (OPTIONAL): Wild encounter zones
  // Array of encounter zone definitions
  encounters?: EncounterZone[];

  // Layer 5 (OPTIONAL): Named zones
  namedZones?: NamedZone[];
}

Terrain Tile IDs

Terrain tile IDs are integers. Clients are responsible for rendering tilesets. Suggested standard tile IDs:

ID Type Category Passable Notes
0 Void/Empty Special No No tile
1 Grass Outdoor Yes May trigger wild encounters
2 Tall Grass Outdoor Yes High encounter rate
3 Water Outdoor Surf Requires Surf ability
4 Deep Water Outdoor Surf Requires Dive ability
5 Sand Outdoor Yes
6 Snow Outdoor Yes May slow movement
7 Ice Outdoor Yes Sliding movement
8 Mountain Outdoor No Solid obstacle
9 Rock Outdoor No Solid obstacle
10 Tree Outdoor No Can be Cut
11 Flower Outdoor Yes
12 Path/Road Outdoor Yes
13 Bridge Outdoor Yes
14 Cliff Outdoor No Can Surf below
15 Cave Floor Indoor Yes
16 Cave Wall Indoor No
17 Cave Water Indoor Surf
18 Floor (Indoor) Indoor Yes Generic indoor floor
19 Wall (Indoor) Indoor No
20 Carpet Indoor Yes
21 Counter Indoor No Shop counter
22 Bookshelf Indoor No
23 Lava Special No Damages player
24 Pit Special Fall Player falls through
25 Warp Pad Special Yes Visual warp indicator
26 Tall Grass (Cave) Indoor Yes Encounters in caves
27 Sand (Indoor) Indoor Yes
28 Swamp Outdoor Yes Slow movement, encounters
29 Roof/Overhang Overhead Renders over player (z-layered)
30 Rail/Track Indoor Yes

House Tiles (Outdoor)

House tiles are used on outdoor maps to represent buildings the player can enter via warps.

ID Type Category Passable Notes
31 House Wall Outdoor/House No Generic exterior house wall
32 House Roof Outdoor/House No Roof tile; renders above player level
33 House Door Outdoor/House Warp Entrance/exit point; triggers warp action
34 House Window Outdoor/House No Decorative; may show light at night
35 House Chimney Outdoor/House No Decorative chimney top
36 House Foundation Outdoor/House No Base/step of a building
37 Shop Awning Outdoor/House No Overhead awning above shop doorways
38 House Roof (Peaked) Outdoor/House No Peaked/angled roof section

Fence & Wall Tiles (Special — Outdoor or Indoor)

Fence and wall tiles are traversal obstacles. They can appear in both outdoor and indoor settings.

ID Type Category Passable Notes
40 Wooden Fence Special/Fence No Common outdoor low fence; can be jumped over
41 Stone Wall (Ext.) Special/Fence No Exterior stone boundary wall
42 Iron Fence Special/Fence No Metal fence; urban/city areas
43 Hedge Special/Fence No Living plant fence; can be Cut
44 Picket Fence Special/Fence No Decorative short fence; used near houses
45 Low Wall Special/Fence No Short interior divider; indoor and outdoor
46 Barricade Special/Fence No Temporary blockade; can be conditional
47 Corner Wall Special/Wall No 90° corner wall piece for interiors
48 Pillar Special/Wall No Decorative or structural column; indoor/outdoor
49 Fence Gate Special/Fence Cond. Passable only when a condition is met
50 Cave Fence Special/Fence No Fence type suited for cave environments
51 Fence Post Special/Fence No Single post; connects fence segments

Clients may extend this list with custom tile IDs above 100.

Interactive Object Types

interface InteractiveObject {
  type: "npc" | "sign" | "warp" | "item" | "trigger";

  // For type "npc"
  npc?: string;         // naddr of the NPC event (kind 36011)
  facing?: "up" | "down" | "left" | "right";

  // For type "sign"
  text?: string;        // Text content shown when examined

  // For type "warp"
  // Target map reference. Resolution order:
  //   1. Full naddr (naddr1…) — unambiguous, preferred for cross-user warps
  //   2. d-tag slug — resolved against the same author's maps first, then globally
  target?: string;
  // Tile coordinates on the target map where the player arrives.
  // If omitted, the target map's fasttravel-x/fasttravel-y tags are used as fallback.
  targetX?: number;
  targetY?: number;
  direction?: "both" | "one-way"; // Default: "both"
  condition?: string;   // Script condition (see Script System)
  visible?: boolean | string; // true/false or script expression

  // For type "item"
  item?: string;        // Item identifier
  condition?: string;   // Script condition (only show/take if met)

  // For type "trigger"
  script?: string;      // Script executed when player steps on tile
  triggerOn?: "step" | "action"; // Default: "step"
}

Encounter Zone

interface EncounterZone {
  // Tiles included in this zone, as array of "x,y" coordinates
  // OR a rect: [x, y, width, height]
  tiles?: string[];
  rect?: [number, number, number, number];

  // Encounter rate: 0.0–1.0
  rate: number;

  // Nostrmon that can appear here
  nostrmon: EncounterEntry[];
}

interface EncounterEntry {
  // naddr of the Nostrmon event (kind 38267), or its d-tag
  ref: string;

  // Level range
  minLevel: number;
  maxLevel: number;

  // Relative rarity weight (default: 1)
  weight?: number;

  // Which form index to use (default: 0)
  formIndex?: number;
}

Named Zone

interface NamedZone {
  name: string;
  // Zone type for minimap: "area", "town", "city", "dungeon"
  type: "area" | "town" | "city" | "dungeon";
  // Rectangle: [x, y, width, height] in tiles
  rect: [number, number, number, number];
  // Optional hex color for minimap rendering
  color?: string;
}

Script System

The interactive layer supports a simple scripting language for conditions and triggers. Scripts are plain strings using a minimal expression syntax:

# Variables (set/check flags)
SET flag_name
UNSET flag_name
HAS flag_name         # Check if flag is set
NOT HAS flag_name

# Item checks
HAS_ITEM item_id
NOT HAS_ITEM item_id
GIVE_ITEM item_id

# Badge/Achievement checks
HAS_BADGE badge_id

# Dialogue
SAY "Line 1" "Line 2" "Line 3"
SAY_CONDITIONAL HAS flag_name "You already did this." "You haven't done this yet."

# Choice boxes
CHOICE "Option A" "Option B"
ON_CHOICE 0 SET chose_a
ON_CHOICE 1 SET chose_b

# Warp
WARP naddr_or_dtag x y

# Battle
BATTLE naddr_npc
BATTLE_WILD naddr_nostrmon level

# Control flow
IF HAS flag_name THEN ... END

Kind 38267 — Nostrmon

A Nostrmon is an addressable event defining a creature species, including its stats, types, moves, and sprites.

Tags

Tag Req. Description
d Unique species identifier (slug, e.g. flamewulf)
name Species name
type One, two, or three types (repeat tag). e.g. ["type", "fire"]
sprite URL of the front sprite image
backsprite URL of the back sprite (for battle screen)
model3d URL of a 3D model file (glTF/glb) for 3D clients
hp Base HP stat (integer string)
atk Base Attack stat
def Base Defense stat
spatk Base Special Attack stat
spdef Base Special Defense stat
spd Base Speed stat
move Learnable move. Format: ["move", "move-id", "learn-method", "level-or-condition"]
t nostrmon and any other tags
alt NIP-31 description: "Nostrmon creature: <name>"

Content

The content field is a JSON object:

interface NostrmonContent {
  // Flavor text / Pokédex-style description
  description?: string;

  // Forms (if more than one form exists)
  forms?: NostrmonForm[];
}

interface NostrmonForm {
  name: string;           // Form name (e.g., "Mega", "Shiny", "Winter")
  sprite: string;         // Front sprite URL for this form
  backsprite?: string;    // Back sprite URL for this form
  model3d?: string;       // 3D model URL for this form
  types?: string[];       // Override types for this form
  // Override stats (omitted = use base stats)
  hp?: number;
  atk?: number;
  def?: number;
  spatk?: number;
  spdef?: number;
  spd?: number;
}

Move Learn Methods

The move tag’s learn method field accepts:

Method Description
level Learned at the given level number
tm Taught via Technical Machine item
egg Learned via breeding (egg move)
tutor Taught by a move tutor NPC
evolution Learned upon evolution

Types

Standard Nostrmon types (clients may define custom types):

normal, fire, water, electric, grass, ice, fighting, poison, ground, flying, psychic, bug, rock, ghost, dragon, dark, steel, fairy, cosmic, digital, sound, nature

Example

{
  "kind": 38267,
  "content": "{\"description\":\"A canine Nostrmon wreathed in spectral flame. It is said to guard the gates of forgotten servers.\",\"forms\":[]}",
  "tags": [
    ["d", "flamewulf"],
    ["name", "Flamewulf"],
    ["type", "fire"],
    ["type", "ghost"],
    ["sprite", "https://example.com/flamewulf-front.png"],
    ["backsprite", "https://example.com/flamewulf-back.png"],
    ["hp", "75"],
    ["atk", "90"],
    ["def", "60"],
    ["spatk", "85"],
    ["spdef", "65"],
    ["spd", "100"],
    ["move", "ember", "level", "5"],
    ["move", "shadow-ball", "level", "30"],
    ["move", "flamethrower", "tm", ""],
    ["t", "nostrmon"],
    ["alt", "Nostrmon creature: Flamewulf"]
  ]
}

Kind 36011 — NPC

An NPC (Non-Player Character) is a character that can be placed on maps. NPCs come in two varieties: Simple (scripted dialogue) and AI (language model driven).

Tags

Tag Req. Description
d Unique NPC identifier (slug)
name NPC display name
npc-type "simple" or "ai"
sprite URL of the NPC’s sprite image
nostrmon naddr of a Nostrmon. Repeat for multiple Nostrmon (used in battles)
nostrmon-level Level for each Nostrmon (paired by index with nostrmon tags)
trainer-class Trainer class string (e.g., "Bug Catcher", "Gym Leader")
battle-music naddr of a music event for the battle against this NPC
t nostrmon and discovery tags
alt NIP-31 description: "Nostrmon NPC: <name>"

Content

The content field is a JSON object:

interface NPCContent {
  // Scripted dialogue (required for simple NPCs, used as fallback for AI NPCs)
  dialogue: string[];

  // Choice-based dialogue branches (optional)
  choices?: NPCChoice[];

  // For AI NPCs only
  ai?: {
    // Describe the NPC's knowledge, backstory, and behavior in natural language
    knowledge: string;
    // NPC personality and behavior description
    behavior: string;
    // Preferred languages (English always required)
    languages?: string[];
    // Additional freeform properties
    notes?: string;
  };
}

interface NPCChoice {
  prompt: string;           // The player's choice text
  response: string[];       // NPC response dialogue
  condition?: string;       // Script condition to show this choice
  effect?: string;          // Script effect when chosen
}

Example (Simple NPC)

{
  "kind": 36011,
  "content": "{\"dialogue\":[\"Greetings, traveler!\",\"The Ashfire Caves to the east are dangerous.\",\"Make sure your Nostrmon are well rested before you go!\"]}",
  "tags": [
    ["d", "old-hermit-ashfire"],
    ["name", "Old Hermit"],
    ["npc-type", "simple"],
    ["sprite", "https://example.com/hermit-sprite.png"],
    ["t", "nostrmon"],
    ["alt", "Nostrmon NPC: Old Hermit"]
  ]
}

Example (AI NPC)

{
  "kind": 36011,
  "content": "{\"dialogue\":[\"Hello! I'm Professor Nakamoto. I study Nostrmon across the decentralized world.\"],\"ai\":{\"knowledge\":\"Expert on Nostrmon biology, types, and habitats. Knows all maps in Ashfire Region.\",\"behavior\":\"Friendly and enthusiastic. Loves giving hints. Never breaks character.\",\"languages\":[\"English\",\"Japanese\"],\"notes\":\"Occasionally quotes Satoshi Nakamoto philosophically.\"}}",
  "tags": [
    ["d", "professor-nakamoto"],
    ["name", "Prof. Nakamoto"],
    ["npc-type", "ai"],
    ["sprite", "https://example.com/professor-sprite.png"],
    ["t", "nostrmon"],
    ["alt", "Nostrmon NPC: Prof. Nakamoto"]
  ]
}

Kind 35253 — Game Save

A Game Save records a player’s progress. It is a replaceable event per d tag, allowing players to maintain named save slots. Players may also export/import saves locally.

Tags

Tag Req. Description
d Save slot identifier (e.g., "save-1")
save-name Human-readable save name
region naddr of the current region
map d tag of the current map
playtime Total playtime in seconds (integer string)
version Protocol version of this save format (e.g., "1")
alt NIP-31 description: "Nostrmon game save"

Content

The content field is NIP-44 encrypted to the player’s own pubkey and contains the full game state as JSON:

interface GameSaveContent {
  // Player info
  playerName: string;
  badges: string[];           // Badge IDs earned

  // Current position
  currentMap: string;         // d-tag of current map
  currentRegion?: string;     // naddr of current region
  positionX: number;
  positionY: number;

  // Active team (up to 6 Nostrmon)
  team: OwnedNostrmon[];

  // PC Storage boxes
  storage: OwnedNostrmon[][];

  // Inventory
  inventory: Record<string, number>; // item_id -> quantity

  // World flags (script system state)
  flags: Record<string, boolean>;

  // Completed NPC battles
  defeatedTrainers: string[]; // NPC d-tags

  // Timestamps
  savedAt: number;
  startedAt: number;
}

interface OwnedNostrmon {
  speciesRef: string;    // naddr or d-tag of species (kind 38267)
  nickname?: string;
  level: number;
  experience: number;
  formIndex: number;     // Current form (default: 0)
  hp: number;            // Current HP
  moves: string[];       // Up to 4 move IDs currently equipped
  learnedMoves: string[];// All moves ever learned
  // Individual Values (genetic variation, 0-31 per stat)
  ivs: { hp: number; atk: number; def: number; spatk: number; spdef: number; spd: number; };
  // Effort Values (training gains)
  evs: { hp: number; atk: number; def: number; spatk: number; spdef: number; spd: number; };
  // Personality traits (affect stat calculations)
  nature: string;
  caughtAt: number;      // Unix timestamp
  caughtMap?: string;    // d-tag of map where caught
}

Kind 39951 — Item

An Item is an addressable event defining a usable, holdable, or key item that can be found in the world, bought in shops, or given by NPCs. Items from any author can be referenced.

Tags

Tag Req. Description
d Unique item identifier (slug, e.g. potion, escape-rope)
name Human-readable item name
item-type Category: consumable, hold, key, tm, ball, badge, misc
sprite URL of the item’s icon/sprite image
price Default shop buy price in gold (integer string). "0" = not for sale
sell-price Default sell price (integer string). Omit = half of price
single-use "true" if consumed on use. Default: "true" for consumables
holdable "true" if a Nostrmon can hold this item in battle
t nostrmon and any additional tags
alt NIP-31 description: "Nostrmon item: <name>"

Content

The content field is a JSON object:

interface ItemContent {
  // Description shown in the bag/item screen
  description: string;

  // What happens when this item is used (plain-text script or freeform description)
  // Clients interpret this to apply effects. Common effect keywords:
  //   HEAL_HP <amount>          — restore HP to one Nostrmon
  //   HEAL_HP_ALL <amount>      — restore HP to all team Nostrmon
  //   HEAL_STATUS               — cure a status condition
  //   REVIVE                    — revive a fainted Nostrmon to half HP
  //   REVIVE_FULL               — revive to full HP
  //   CATCH_RATE <multiplier>   — ball catch-rate multiplier (for ball items)
  //   TEACH_MOVE <move-id>      — teach a move (for TM items)
  //   WARP_ESCAPE               — escape from a dungeon to last town
  //   BADGE <badge-id>          — grants a badge (for badge items)
  effect?: string;
}

Item Categories

Category Description
consumable Used from the bag; disappears after use (e.g. Potion, Antidote)
hold Held by a Nostrmon during battle for passive effects
key Key item; never consumed; triggers world events or opens warps
tm Technical Machine; teaches a move to a compatible Nostrmon
ball Used in battle to catch wild Nostrmon; has a CATCH_RATE multiplier
badge Proof of a gym/trainer victory; unlocks abilities or areas
misc Miscellaneous item with no standard category

Example

{
  "kind": 39951,
  "content": "{\"description\":\"Restores 20 HP to a single Nostrmon.\",\"effect\":\"HEAL_HP 20\"}",
  "tags": [
    ["d", "potion"],
    ["name", "Potion"],
    ["item-type", "consumable"],
    ["sprite", "https://example.com/items/potion.png"],
    ["price", "300"],
    ["sell-price", "150"],
    ["single-use", "true"],
    ["holdable", "false"],
    ["t", "nostrmon"],
    ["alt", "Nostrmon item: Potion"]
  ]
}

Querying Content

Discover all Nostrmon (any author)

[{ "kinds": [38267], "#t": ["nostrmon"], "limit": 50 }]

Discover all regions (any author)

[{ "kinds": [30597], "#t": ["nostrmon"], "limit": 50 }]

Get a specific NPC by author and d-tag

[{ "kinds": [36011], "authors": ["<pubkey>"], "#d": ["old-hermit-ashfire"] }]

Discover all items (any author)

[{ "kinds": [39951], "#t": ["nostrmon"], "limit": 100 }]

Get all maps in a region (by region naddr reference)

Maps reference their region via the region tag. Clients should query maps and filter by region reference client-side, or use a relay that supports tag filtering.


Battle Rules

Wild Battles

  • A wild encounter is triggered when the player steps on a tile inside an encounter zone, according to the zone’s rate (0–1).
  • Auto-catch rule: Wild Nostrmon at level 1–5 are caught automatically at 100% success rate with no battle required. This ensures new players always get their first Nostrmon.
  • If the player has no Nostrmon in their team, wild encounters at any level trigger auto-catch instead of a battle.
  • For wild Nostrmon above level 5, a full battle takes place. The player may fight, use items, switch Nostrmon, or attempt to flee.
  • Catching requires a ball item. Catch rate = 0.3 + (1 − currentHpRatio) × 0.7 modified by the ball’s CATCH_RATE multiplier.
  • The player can flee from any wild battle without penalty.

Trainer Battles

  • NPCs with one or more nostrmon tags initiate trainer battles when the player interacts with them.
  • The player cannot catch the Nostrmon of another trainer.
  • The player cannot flee a trainer battle.
  • Defeating a trainer stores their d-tag in defeatedTrainers in the save. Re-interacting with a defeated trainer shows fallback dialogue instead of battle.
  • Trainer battle music uses the NPC’s battle-music tag if set, otherwise the region’s default battle theme.

Stat & Damage Calculation

  • Stats use the standard formula: floor((2×base + IV + floor(EV/4)) × level / 100) + 5 (or +level+10 for HP)
  • IVs: random 0–31 per stat, generated at catch/receive time
  • EVs: start at 0, gained from defeating Nostrmon
  • Natures: 25 natures, each raises one stat by 10% and lowers another (or neutral)
  • Level-up: cubic XP formula XP_needed = (level+1)³ − level³

XP & Levelling

  • Clients MUST award XP to the active Nostrmon after defeating or catching a wild Nostrmon
  • XP reward: floor((sum_of_base_stats × enemy_level) / 7)
  • When a Nostrmon’s XP exceeds the threshold, it levels up and its stats recalculate
  • Clients SHOULD check for move learning on level-up (from the species move tags with learn-method: level)

Multiplayer Presence

On maps with multiplayer: "true", clients SHOULD broadcast the player’s position using ephemeral kind 20001 events (“Presence Events”).

Kind 20001 — Presence Event (Ephemeral)

Field Value
kind 20001
content JSON: {"x": <tile_x>, "y": <tile_y>, "name": "<display_name>"}
tags ["d", "<map_d_tag>"], ["expiration", "<unix_timestamp+30>"]
  • Clients broadcast their position every ~5 seconds while on a multiplayer map
  • Clients subscribe to kind 20001 events filtered by the current map’s d tag
  • Players not seen for 20+ seconds should be removed from the display
  • Other players are shown as coloured dots or avatars on the map
  • Position data is not saved — it is purely ephemeral

Client Requirements

MUST

  • Clients MUST be able to render and play maps using terrain and interactive layers
  • Clients MUST support Nostrmon battles (wild and trainer)
  • Clients MUST auto-catch wild Nostrmon at level 1–5 at 100% rate without battle
  • Clients MUST prevent catching in trainer battles
  • Clients MUST prevent fleeing in trainer battles
  • Clients MUST support game saves (kind 35253) with NIP-44 encryption
  • Clients MUST persist saves locally (e.g. localStorage) in addition to Nostr
  • Clients MUST treat maps without a region tag as belonging to “Unknown Region”
  • Clients MUST use fasttravel-x / fasttravel-y as the spawn position when fast-traveling to a map
  • Clients MUST NOT allow fast-traveling to a map with prison: "true" unless it belongs to the current user
  • Clients MUST implement an in-game menu with at minimum: team management, bag/inventory, save game

SHOULD

  • Clients SHOULD render a minimap for regions with map type-appropriate icons
  • Clients SHOULD support keyboard navigation and touch controls on mobile
  • Clients SHOULD support gamepad/controller input
  • Clients SHOULD render day/night cycles for maps where daynight is "true"
  • Clients SHOULD handle AI NPCs with configurable AI provider/model
  • Clients SHOULD list entry maps (entry-map: "true") from all authors for cross-region warp selection
  • Clients SHOULD broadcast and receive presence events on multiplayer maps (kind 20001)
  • Clients SHOULD show PC box storage for Nostrmon overflow management

MAY

  • Clients MAY render maps in 2.5D or 3D using the height map layer
  • Clients MAY provide editors for regions, maps, Nostrmon, NPCs, and items
  • Clients MAY support custom tilesets beyond the standard tile IDs
  • Clients MAY support NPC shops (using item price tags for buy/sell)
  • Clients MAY implement Nostrmon trading between players on multiplayer maps

Interoperability Notes

  • All creature references use naddr (kind 38267) or the d tag — clients should support both
  • Map warps referencing other users’ maps are valid and encouraged for cross-region travel
  • Nostrmon from any author may be referenced in encounter zones
  • Music references use kind 36787 (Nostr Music events)
  • The t: nostrmon tag is used for all discovery queries — clients SHOULD include it on all published events

This NIP was authored as part of the Nostrmon World client. Feedback welcome.


Looking for comments…

Searching Nostr relays. This may take a moment the first time this article is opened.