DownloadNetRealm: Inter-Node RPG Game Proposal
Status: Draft Proposal
Generated: 2026-02-05
Note: This is an AI-generated draft proposal and has not been reviewed for technical accuracy or feasibility.
Overview
NetRealm is a turn-based RPG WebDoor game that uses echomail to enable cross-node gameplay across LovlyNet. Players fight monsters, level up their characters, collect loot, and compete with players on other BBS nodes through asynchronous PvP combat and global leaderboards.
Architecture: NetRealm is a self-contained WebDoor that requires zero modifications to core BinktermPHP. All game logic, API endpoints, and routing are handled within the WebDoor's own index.php. The echomail processor is registered via configuration, not code changes.
Core Concept
-
Daily Turns: Each player gets a set number of turns per day (e.g., 25 turns)
-
Local PvE: Fight monsters, explore dungeons, gather resources
-
Cross-Node PvP: Challenge players on other nodes via echomail
-
Global Leaderboards: Rankings visible across all participating nodes
-
Persistent Character: Character stats, inventory, and progress saved between sessions
Unified Local and Network Gameplay
Local Gameplay (No Echomail)
Direct database operations for single-player activities:
- PvE Combat: Fight monsters, gain XP/gold/items
- Inventory Management: Equip/unequip items
- Shopping: Buy/sell items
- Character Management: View stats, level up
- Healing/Resting: Recover HP
Flow: User action ? API call ? Database update ? Instant result
PvP (Unified via Echomail)
All PvP challenges (local or remote) use the same echomail-based flow:
Local PvP (both players on same node):
1. Alice challenges Bob (both local)
2. Game posts PvP message to NETREALM_SYNC via MessageHandler::postEchomail()
3. Message saved to echomail table
4. Game immediately queries and processes the message
5. Updates both players' stats
6. Players see result immediately
Remote PvP (players on different nodes):
1. Alice challenges Dave (on remote node)
2. Game posts PvP message to NETREALM_SYNC via MessageHandler::postEchomail()
3. Message saved to echomail table AND transmitted via binkp
4. When Dave opens NetRealm, game queries NETREALM_SYNC messages
5. Processes PvP result, updates Dave's stats
6. Dave sees he was challenged and the result
Incoming Remote Challenge:
1. Remote node posts PvP challenge
2. Arrives via binkp ? saved to local echomail table
3. Batch processor runs ? processes combat
4. Local player sees they were challenged and the result
Benefits of Unified Approach
-
Single code path: PvP logic is identical for local and remote
-
No special cases: Processor doesn't care about message origin
-
Consistent UX: All PvP has same ~1-5 min delay (acceptable for turn-based game)
-
Simple: Echomail table is single source of truth
Game Mechanics
Character System
Stats:
- Level: 1-50, determines power and unlocks
- HP (Hit Points): Current/Max health
- Attack: Damage dealt in combat
- Defense: Damage reduction
- Experience: Progress toward next level
- Gold: Currency for purchases
Classes (Optional Phase 2):
- Warrior (high HP, defense)
- Rogue (high attack, critical hits)
- Mage (magic attacks, buffs)
Turn Economy
-
Players receive 25 turns per day at reset (configurable)
-
Turns regenerate at midnight (system timezone)
-
Premium: Extra turns available for credits
-
Actions that consume turns:
- Combat encounter: 1 turn
- Dungeon exploration: 2 turns
- Rest/healing: 0 turns (but limited uses)
- PvP challenge: 3 turns
Combat System
PvE Combat (vs Monsters):
- Random encounters based on player level
- Simple combat formula: damage = attack * (1 + random(0.8, 1.2)) - defense
- Victory: Gain XP, gold, chance of loot
- Defeat: Lose gold, return to town
PvP Combat (vs Other Players):
- Unified system: Works the same for local and remote opponents
- Asynchronous: Attacker initiates, defender auto-defends (uses stored stats)
- Echomail-based: All PvP flows through NETREALM_SYNC echomail ? batch processor
- Processing delay: 1-5 minutes (acceptable for turn-based game)
- Results: Winner gets XP, gold bounty, ranking points
- Penalties: Loser loses gold, ranking points (but not items/levels)
- Visibility: Results visible to both players and broadcast to network
Monster Tiers
Level-appropriate monsters with scaling rewards:
| Level Range | Monster Examples | XP | Gold |
|-------------|-----------------|-----|------|
| 1-5 | Rat, Goblin, Slime | 10-25 | 5-15 |
| 6-10 | Wolf, Bandit, Skeleton | 30-60 | 20-40 |
| 11-20 | Orc, Dark Mage, Troll | 70-150 | 50-100 |
| 21-30 | Vampire, Demon, Drake | 200-400 | 150-300 |
| 31-40 | Dragon, Lich, Giant | 500-900 | 400-700 |
| 41-50 | Elder Dragon, Demon Lord | 1000-2000 | 1000-2000 |
Items & Equipment
Equipment Slots:
- Weapon (+Attack)
- Armor (+Defense)
- Accessory (+HP or special bonus)
Item Rarity:
- Common (white): Basic stats
- Uncommon (green): +10% stats
- Rare (blue): +25% stats, 1 bonus
- Epic (purple): +50% stats, 2 bonuses
- Legendary (orange): +100% stats, 3 bonuses
Shop System:
- Town shop with basic items
- Prices scale with item power
- Sell items for 50% of purchase price
Progression
Leveling:
- XP required: level * 100 (e.g., Level 5?6 = 500 XP)
- Each level grants: +10 HP, +2 Attack, +1 Defense
- Heal to full HP on level up
Daily Reset:
- Turns regenerate
- Daily quest available
- Random event chance (market discount, bonus XP day, etc.)
Inter-Node Features (Echomail Integration)
Echomail Area
NETREALM_SYNC - Game synchronization echo area (sysop-only) for:
- PvP combat results
- Leaderboard updates (daily/weekly)
- Rare item discoveries (legendary drops)
- World events
- Tournament announcements
Auto-Creation: On first run, NetRealm automatically creates the NETREALM_SYNC echo area if it doesn't exist:
- Domain: lovlynet
- Access: Sysop only (read/write restricted)
- Description: "NetRealm RPG game synchronization area"
Message Ordering and Reliability
Important: Echomail messages may arrive out of order due to network delays and store-and-forward routing. The game handles this by:
-
UTC Timestamps: All messages include a UTC timestamp (ISO 8601 format) for proper ordering across timezones
-
Message IDs: Each message has a unique ID for duplicate detection
-
Idempotent processing: Processing the same message twice is safe
-
Last-write-wins: For leaderboards, newer timestamps override older data
Message Types
1. PvP Challenge Result
Subject: [NetRealm] PvP: Alice(1:1/1) defeated Bob(1:2/3)
From: BBS Node 1:1/1
{
"type": "pvp_result",
"attacker": {
"name": "Alice",
"node": "1:1/1",
"level": 15
},
"defender": {
"name": "Bob",
"node": "1:2/3",
"level": 14
},
"result": "victory",
"xp_gained": 150,
"gold_won": 75,
"timestamp": "2026-02-05T14:23:00Z" // UTC timestamp (ISO 8601)
}
2. Leaderboard Update
Subject: [NetRealm] Daily Leaderboard - 2026-02-05
From: Master Node (configurable)
{
"type": "leaderboard",
"period": "daily",
"date": "2026-02-05",
"top_players": [
{"rank": 1, "name": "Alice", "node": "1:1/1", "level": 25, "score": 15000},
{"rank": 2, "name": "Charlie", "node": "1:3/5", "level": 23, "score": 12500},
{"rank": 3, "name": "Bob", "node": "1:2/3", "level": 22, "score": 11000}
]
}
3. Legendary Item Drop
Subject: [NetRealm] LEGENDARY DROP: Dragon Slayer Sword found!
From: BBS Node 1:1/1
{
"type": "legendary_drop",
"player": "Alice",
"node": "1:1/1",
"item": {
"name": "Dragon Slayer Sword",
"rarity": "legendary",
"stats": {
"attack": 150
}
},
"source": "Elder Dragon",
"timestamp": "2026-02-05T16:45:00Z"
}
4. World Event
Subject: [NetRealm] EVENT: Double XP Weekend!
From: Game System
{
"type": "event",
"name": "Double XP Weekend",
"description": "All XP gains doubled for 48 hours!",
"start": "2026-02-07T00:00:00Z",
"end": "2026-02-09T00:00:00Z",
"multiplier": 2.0
}
Cross-Node Player Discovery
-
Players can search for opponents on other nodes
-
View basic stats: Name, Node, Level, Win/Loss record
-
Challenge via echomail (async combat resolution)
-
Combat results posted back to both nodes
Global Leaderboards
Rankings:
1. Overall: Total experience/level
2. PvP: Win/loss ratio, ranking points
3. Wealth: Total gold + item value
4. Monster Slayer: Total monsters defeated
Update Frequency:
- Real-time on local node
- Synced via echomail daily at reset
- Nodes can query other nodes for current standings
Technical Architecture
IMPORTANT: NetRealm is a self-contained WebDoor that requires no changes to core BinktermPHP. All game logic, API endpoints, and routing are handled within the WebDoor directory using its own index.php entry point.
File Structure
public_html/webdoors/netrealm/
??? webdoor.json # Manifest
??? game.html # Game interface (loaded by webdoor launcher)
??? api.php # API endpoint handler
??? src/
? ??? NetRealmGame.php # Main game class
? ??? Character.php # Character management
? ??? Combat.php # Combat system
? ??? Inventory.php # Inventory/equipment
? ??? Shop.php # Shop system
? ??? Network.php # Cross-node player registry
? ??? Leaderboard.php # Leaderboard management
??? game.html # Game interface (loaded by main BBS webdoor launcher)
??? css/
? ??? netrealm.css # Game styles
? ??? rpg-theme.css # RPG-themed UI
??? js/
? ??? game.js # Main game logic
? ??? combat.js # Combat system
? ??? inventory.js # Item management
? ??? network.js # API communication
??? assets/
? ??? sprites/ # Character/monster sprites
? ??? sounds/ # Combat sounds (optional)
??? migrations/
??? v1.0.0_netrealm_schema.sql # Database schema
Database Schema
-- Player characters
CREATE TABLE netrealm_characters (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(50) NOT NULL,
level INTEGER DEFAULT 1,
experience INTEGER DEFAULT 0,
hp_current INTEGER DEFAULT 100,
hp_max INTEGER DEFAULT 100,
attack INTEGER DEFAULT 10,
defense INTEGER DEFAULT 5,
gold INTEGER DEFAULT 100,
turns_remaining INTEGER DEFAULT 25,
turns_last_reset TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_played TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(user_id)
);
-- Equipment inventory
CREATE TABLE netrealm_inventory (
id SERIAL PRIMARY KEY,
character_id INTEGER NOT NULL REFERENCES netrealm_characters(id) ON DELETE CASCADE,
item_id INTEGER NOT NULL,
item_name VARCHAR(100) NOT NULL,
item_type VARCHAR(20) NOT NULL, -- weapon, armor, accessory
rarity VARCHAR(20) NOT NULL, -- common, uncommon, rare, epic, legendary
attack_bonus INTEGER DEFAULT 0,
defense_bonus INTEGER DEFAULT 0,
hp_bonus INTEGER DEFAULT 0,
is_equipped BOOLEAN DEFAULT FALSE,
acquired_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Combat log (local fights)
CREATE TABLE netrealm_combat_log (
id SERIAL PRIMARY KEY,
character_id INTEGER NOT NULL REFERENCES netrealm_characters(id) ON DELETE CASCADE,
opponent_type VARCHAR(20) NOT NULL, -- monster, player
opponent_name VARCHAR(100) NOT NULL,
opponent_node VARCHAR(50), -- NULL for monsters, node address for players
result VARCHAR(10) NOT NULL, -- victory, defeat
xp_gained INTEGER DEFAULT 0,
gold_gained INTEGER DEFAULT 0,
items_looted TEXT, -- JSON array
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Cross-node player registry (cached from echomail)
CREATE TABLE netrealm_network_players (
id SERIAL PRIMARY KEY,
player_name VARCHAR(50) NOT NULL,
node_address VARCHAR(50) NOT NULL,
level INTEGER NOT NULL,
attack INTEGER NOT NULL,
defense INTEGER NOT NULL,
hp_max INTEGER NOT NULL,
wins INTEGER DEFAULT 0,
losses INTEGER DEFAULT 0,
last_seen TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(player_name, node_address)
);
-- Global leaderboard cache
CREATE TABLE netrealm_leaderboard (
id SERIAL PRIMARY KEY,
player_name VARCHAR(50) NOT NULL,
node_address VARCHAR(50) NOT NULL,
rank_type VARCHAR(20) NOT NULL, -- overall, pvp, wealth, monster_slayer
rank_value INTEGER NOT NULL,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(player_name, node_address, rank_type)
);
-- Echomail message tracking (prevent duplicate processing)
CREATE TABLE netrealm_processed_messages (
id SERIAL PRIMARY KEY,
echomail_id INTEGER NOT NULL UNIQUE REFERENCES echomail(id) ON DELETE CASCADE,
processed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_netrealm_processed ON netrealm_processed_messages(echomail_id);
API Endpoint Handler
Request Flow:
1. User loads WebDoor: Browser requests /webdoors/netrealm/game.html
2. JavaScript makes API call: fetch('/webdoors/netrealm/api.php?endpoint=character')
3. api.php handles request, executes game logic, returns JSON
4. JavaScript updates UI with response
No .htaccess or URL rewriting needed - just simple GET parameters.
api.php Structure
The WebDoor's api.php handles ALL API endpoints using GET parameters:
<?php
// public_html/webdoors/netrealm/api.php
require_once __DIR__ . '/../../../vendor/autoload.php';
use BinktermPHP\Database;
use BinktermPHP\Auth;
// Get database connection
$db = Database::getInstance()->getPdo();
// Check authentication
$auth = new Auth();
if (!$auth->isLoggedIn()) {
http_response_code(401);
echo json_encode(['error' => 'Authentication required']);
exit;
}
$userId = $auth->getUserId();
// Load game classes
require_once __DIR__ . '/src/NetRealmGame.php';
require_once __DIR__ . '/src/Character.php';
require_once __DIR__ . '/src/Combat.php';
require_once __DIR__ . '/src/Inventory.php';
require_once __DIR__ . '/src/Shop.php';
require_once __DIR__ . '/src/Network.php';
require_once __DIR__ . '/src/Leaderboard.php';
$game = new NetRealmGame($db, $userId);
// Get endpoint from query string
$endpoint = $_GET['endpoint'] ?? '';
$method = $_SERVER['REQUEST_METHOD'];
// API routing
header('Content-Type: application/json');
try {
switch ($endpoint) {
// Character endpoints
case 'character':
if ($method === 'GET') {
echo json_encode($game->getCharacter());
} elseif ($method === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
echo json_encode($game->createCharacter($data['name']));
}
break;
// Combat endpoints
case 'combat':
if ($method === 'GET') {
echo json_encode($game->getAvailableMonsters());
} elseif ($method === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
echo json_encode($game->fightMonster($data['monster_id']));
}
break;
// Inventory
case 'inventory':
echo json_encode($game->getInventory());
break;
case 'equip':
if ($method === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
echo json_encode($game->equipItem($data['item_id']));
}
break;
// Shop
case 'shop':
echo json_encode($game->getShopItems());
break;
case 'shop-buy':
if ($method === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
echo json_encode($game->buyItem($data['item_id']));
}
break;
case 'shop-sell':
if ($method === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
echo json_encode($game->sellItem($data['inventory_id']));
}
break;
// Rest/heal
case 'rest':
echo json_encode($game->rest());
break;
// Network/PvP
case 'network':
echo json_encode($game->getNetworkPlayers());
break;
case 'pvp':
if ($method === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
echo json_encode($game->challengePlayer($data['player_id']));
}
break;
// Leaderboard
case 'leaderboard':
$type = $_GET['type'] ?? 'overall';
echo json_encode($game->getLeaderboard($type));
break;
// Credits integration
case 'buy-turns':
if ($method === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
echo json_encode($game->buyTurns($data['amount']));
}
break;
default:
http_response_code(404);
echo json_encode(['error' => 'Endpoint not found']);
}
} catch (Exception $e) {
http_response_code(500);
echo json_encode(['error' => $e->getMessage()]);
}
WebDoor Manifest
webdoor.json: {
"name": "NetRealm",
"version": "1.0.0",
"description": "Inter-node RPG adventure using echomail for cross-node gameplay",
"author": "BinktermPHP",
"category": "rpg",
"display_name": "NetRealm RPG",
"icon": "??",
"requires_auth": true,
"api_version": "1.0",
"entry_point": "game.html",
"echomail_integration": {
"echoarea": "NETREALM_SYNC",
"message_types": ["pvp_result", "leaderboard", "legendary_drop", "event"]
},
"config": {
"daily_turns": 25,
"turn_reset_hour": 0,
"starting_gold": 100,
"starting_level": 1,
"pvp_enabled": true,
"credits_per_extra_turn": 5,
"max_extra_turns_per_day": 10
}
}
How It Works:
1. User clicks "NetRealm RPG" in the WebDoors menu
2. BinktermPHP loads game.html (the entry_point) in an iframe/modal
3. JavaScript in game.html makes API calls to /webdoors/netrealm/api/*
4. All API calls are routed through index.php which handles game logic
5. Game queries NETREALM_SYNC messages via MessageHandler when players access it
6. Game posts to NETREALM_SYNC via MessageHandler::postEchomail() for cross-node events
Zero Core Modifications: The entire game is self-contained within the WebDoor directory.
API Endpoints
All API endpoints are handled internally by the WebDoor's index.php. No core BinktermPHP routing changes required.
Base URL: /webdoors/netrealm/
GET /webdoors/netrealm/api/character - Get player's character
POST /webdoors/netrealm/api/character - Create new character
GET /webdoors/netrealm/api/combat - Get available monsters
POST /webdoors/netrealm/api/combat - Fight a monster
GET /webdoors/netrealm/api/inventory - Get inventory
POST /webdoors/netrealm/api/equip - Equip/unequip item
GET /webdoors/netrealm/api/shop - Get shop items
POST /webdoors/netrealm/api/shop/buy - Buy item
POST /webdoors/netrealm/api/shop/sell - Sell item
GET /webdoors/netrealm/api/rest - Heal at inn (free, limited)
GET /webdoors/netrealm/api/network - List players on other nodes
POST /webdoors/netrealm/api/pvp - Challenge another player
GET /webdoors/netrealm/api/leaderboard - Get global leaderboard
POST /webdoors/netrealm/api/buy-turns - Purchase extra turns with credits
Note: JavaScript code in the game calls these endpoints relative to the WebDoor's base path.
Echomail Processing
NetRealm uses BinktermPHP's MessageHandler class to post and query echomail messages. No custom processor needed - the game queries messages on-demand when players access it.
Posting Messages (e.g., PvP results): use BinktermPHP\MessageHandler;
$messageHandler = new MessageHandler();
// Post PvP result to NETREALM_SYNC
$pvpData = [
'type' => 'pvp_result',
'attacker' => ['name' => 'Alice', 'node' => '1:1/1', 'level' => 15],
'defender' => ['name' => 'Bob', 'node' => '1:2/3', 'level' => 14],
'result' => 'victory',
'xp_gained' => 150,
'gold_won' => 75,
'timestamp' => gmdate('c') // UTC timestamp
];
$messageHandler->postEchomail(
$gameSystemUserId, // System user ID for game messages
'NETREALM_SYNC', // Echo area tag
'lovlynet', // Domain
'All', // To name
'[NetRealm] PvP Result', // Subject
json_encode($pvpData), // Message text as JSON
null, // Reply to ID
'NetRealm RPG' // Tagline
);
Querying Messages (check for new game events): // When player opens game, fetch recent NETREALM_SYNC messages
$messages = $messageHandler->getEchomail(
'NETREALM_SYNC', // Echo area tag
'lovlynet', // Domain
1, // Page
100, // Limit (last 100 messages)
null, // User ID (null = all messages)
'all' // Filter
);
// Process each message
foreach ($messages['messages'] as $msg) {
$data = json_decode($msg['message_text'], true);
switch ($data['type'] ?? '') {
case 'pvp_result':
$this->processPvPResult($data);
break;
case 'leaderboard':
$this->processLeaderboard($data);
break;
case 'legendary_drop':
$this->processLegendaryDrop($data);
break;
}
}
Echo Area Auto-Creation:
On first run (when no NETREALM_SYNC echo area exists), the game automatically creates it:
// In NetRealmGame or initialization code
$stmt = $db->prepare("SELECT id FROM echoareas WHERE tag = ? AND domain = ?");
$stmt->execute(['NETREALM_SYNC', 'lovlynet']);
if (!$stmt->fetch()) {
// Create the echo area
$stmt = $db->prepare("
INSERT INTO echoareas (tag, domain, description, sysop_only, created_at)
VALUES (?, ?, ?, TRUE, NOW())
");
$stmt->execute([
'NETREALM_SYNC',
'lovlynet',
'NetRealm RPG game synchronization area (auto-created)'
]);
}
This ensures NETREALM_SYNC exists before any game messages are posted. Since it's sysop-only, regular users can't see it. The game posts/reads messages directly via SQL.
Processing Flow:
1. Incoming echomail: Packets arrive ? messages saved to echomail table by BinktermPHP
2. Local PvP: Player initiates challenge ? game posts via MessageHandler::postEchomail() ? saved to echomail table
3. On-demand processing: When player opens game ? query NETREALM_SYNC messages via MessageHandler::getEchomail() ? process new messages ? update game state
4. Unified: All PvP (local + remote) flows through echomail table, processed when needed
Benefits of On-Demand Processing:
- No batch processor or daemon needed
- No queue table needed
- Simpler architecture
- Game state updates when players actually play
- Uses existing BinktermPHP MessageHandler methods
Message Processing (in game code):
When a player opens NetRealm, the game queries for new NETREALM_SYNC messages and processes them:
// In NetRealmGame class or similar
public function syncFromNetwork()
{
$messageHandler = new \BinktermPHP\MessageHandler();
// Get recent messages from NETREALM_SYNC
$result = $messageHandler->getEchomail(
'NETREALM_SYNC',
'lovlynet',
1,
100, // Last 100 messages
null,
'all'
);
foreach ($result['messages'] as $msg) {
// Skip if already processed
if ($this->isMessageProcessed($msg['id'])) {
continue;
}
$data = json_decode($msg['message_text'], true);
switch ($data['type'] ?? '') {
case 'pvp_result':
$this->processPvPResult($data);
break;
case 'leaderboard':
$this->processLeaderboard($data);
break;
case 'legendary_drop':
$this->processLegendaryDrop($data);
break;
case 'event':
$this->processEvent($data);
break;
}
// Mark message as processed
$this->markMessageProcessed($msg['id']);
}
}
private function isMessageProcessed(int $messageId): bool
{
$stmt = $this->db->prepare(
"SELECT 1 FROM netrealm_processed_messages WHERE echomail_id = ?"
);
$stmt->execute([$messageId]);
return $stmt->fetch() !== false;
}
private function markMessageProcessed(int $messageId): void
{
$stmt = $this->db->prepare(
"INSERT INTO netrealm_processed_messages (echomail_id, processed_at)
VALUES (?, NOW())
ON CONFLICT (echomail_id) DO NOTHING"
);
$stmt->execute([$messageId]);
}
When Processing Runs:
- When player opens NetRealm
- After player completes an action (combat, challenge, etc.)
- Game always checks for new network messages before displaying state
No daemon or processor registration needed - just direct queries using MessageHandler.
Game Balance
Turn Economy
-
25 turns = ~15-20 minutes of gameplay
-
Encourages daily engagement
-
Extra turns via credits (5 credits per turn, max 10/day)
Combat Difficulty
-
Monsters scale with player level
-
80% win rate against level-appropriate monsters
-
20% chance of finding items on victory
-
Rare drops (5% for rare+, 1% for epic+, 0.1% for legendary)
PvP Balance
-
Can only challenge players within ±5 levels
-
Defender gets 20% defense bonus (home advantage)
-
Win/loss ratios visible to discourage griefing
-
Cooldown: Can only challenge same player once per day
Progression Curve
-
Level 1?20: Fast (1-2 days per level with active play)
-
Level 20?35: Medium (3-5 days per level)
-
Level 35?50: Slow (7-14 days per level)
-
Endgame: PvP competition, legendary hunting, rankings
Implementation Phases
Key Principle: All implementation happens within /webdoors/netrealm/ - no core BinktermPHP modifications.
Phase 1: Core Gameplay (MVP)
Week 1-2:
- Create WebDoor directory structure
- Database migration for NetRealm tables
- Build index.php routing system
- Implement game classes (Character, Combat, Inventory, Shop)
- Create basic game UI (game.html + CSS/JS)
- Character creation/management
- Basic PvE combat
- Turn system and daily reset
- Simple inventory and equipment
- Shop system
Deliverables:
- Playable single-node game
- Characters persist between sessions
- Daily turn regeneration works
- No core changes made
Phase 2: Enhanced Gameplay
Week 3-4:
- Monster variety and balancing
- Item rarity system
- Combat animations/polish
- Rest/healing system
- Combat log and statistics
- Local leaderboard
Deliverables:
- Polished game experience
- Balanced progression
- Player engagement metrics
- Still no core changes
Phase 3: Echomail Integration
Week 5-6:
- Create NETREALM_SYNC echoarea (auto-created on first run)
- Implement message posting via MessageHandler::postEchomail()
- Implement message querying via MessageHandler::getEchomail()
- Cross-node player registry
- PvP challenge system (posts to NETREALM_SYNC)
- Global leaderboard sync
- Network player discovery
- Message processing on game load
Deliverables:
- Cross-node PvP functional
- Leaderboards sync between nodes
- Battle results broadcast via echomail
- Uses existing MessageHandler - no core code changes
Phase 4: Advanced Features
Week 7-8:
- Daily quests
- World events
- Tournaments
- Credits integration (buy turns) - uses existing BinktermPHP credits API
- Admin interface within WebDoor
- Achievement system
Deliverables:
- Rich endgame content
- Monetization options
- Long-term engagement features
- All features self-contained in WebDoor
Success Metrics
-
Engagement: Daily active users, average turns used
-
Retention: Return rate after 7 days, 30 days
-
Network Effect: Number of cross-node PvP battles
-
Viral: New player signups from echomail exposure
-
Monetization: Credits spent on extra turns
Future Enhancements
-
Guilds: Cross-node player organizations
-
Raids: Cooperative boss fights requiring multiple players
-
Crafting: Combine items to create better equipment
-
Pet System: Companions that assist in combat
-
Seasonal Events: Limited-time content and rewards
-
Player Trading: Item/gold exchange system
-
Tournaments: Scheduled PvP competitions with prizes
Technical Considerations
Security
-
Validate all echomail messages (check node signatures)
-
Rate limiting on PvP challenges
-
Server-side combat resolution (prevent cheating)
-
Sanitize all user input
Performance
-
Batch processing: Processor runs every 1-5 minutes (configurable)
-
Non-blocking: Packet processing not delayed by game logic
-
Cache network player data (refresh daily)
-
Index combat_log and inventory tables
-
Lazy load leaderboards (don't fetch on every page load)
-
Paginate combat history
-
Consider faster batch interval (30-60 seconds) for more responsive PvP
Scalability
-
Echomail queuing for high-traffic nodes
-
Database connection pooling
-
Consider Redis for session/turn tracking
-
Horizontal scaling for API endpoints
Conclusion
NetRealm combines nostalgic BBS door game mechanics with modern web technology and FidoNet's unique distributed architecture. By using echomail for inter-node communication, it demonstrates the collaborative potential of LovlyNet while providing engaging daily gameplay.
The phased approach allows for rapid MVP development while leaving room for rich feature expansion based on player feedback and network adoption.
Next Steps:
1. Review and approve proposal
2. Create NETREALM_SYNC echoarea on LovlyNet
3. Create WebDoor directory: public_html/webdoors/netrealm/
4. Run database migration for NetRealm tables
5. Build index.php routing and API endpoint handler
6. Implement game classes and UI (Phase 1)
7. Implement echomail integration using MessageHandler
8. Beta test with small group of nodes
9. Launch network-wide
Installation for Sysops:
1. Copy /webdoors/netrealm/ directory to their BBS
2. Run NetRealm database migration
3. NETREALM_SYNC echo area auto-creates on first game access
4. Game appears automatically in WebDoors menu
5. Start playing!
No daemon or processor needed - game processes messages on-demand when players access it.
|