Files
BreakEscape/scenarios/RFID_SCENARIO_PATTERNS.md
Z. Cliffe Schreuders bff4a6a31a docs(rfid): Add corrected scenario patterns and multi-protocol test
Created proper RFID scenario examples following project patterns
(hub structure, #exit_conversation tags, card_id format).

## Issues Found in Existing Files:

### test-rfid.json (Not modified - reference only):
 Uses legacy format (rfid_hex, rfid_facility, key_id)
 All EM4100 - no protocol variety
 Door requires not array format
 No protocol testing variety

### rfid-security-guard.ink (Not modified - reference only):
 Uses -> END instead of #exit_conversation
 Doesn't return to hub after exits
 No proper hub pattern
 Clone tag uses hex instead of card_id

## New Corrected Files:

### 1. scenarios/RFID_SCENARIO_PATTERNS.md (NEW)
Comprehensive guide showing:
-  Correct hub pattern with #exit_conversation
-  Proper card_id JSON format
-  Protocol-specific examples
-  Common mistakes to avoid
- Complete working examples

### 2. scenarios/test-rfid-multiprotocol.json (NEW)
Test scenario with ALL 4 protocols:
- EM4100 (instant clone)
- MIFARE_Classic_Weak_Defaults (dictionary)
- MIFARE_Classic_Custom_Keys (Darkside attack)
- MIFARE_DESFire (UID only)

Features:
- 4 NPCs, each with different protocol
- 4 test rooms demonstrating each security level
- Proper card_id format throughout
- Array-based door requirements
- acceptsUIDOnly flag demonstrated

### 3. scenarios/ink/rfid-security-guard-fixed.ink (NEW)
Fixed version showing:
- Proper hub structure
- #exit_conversation on choice lines
- All paths return to hub
- Card protocol variables declared
- Uses {card_card_id} in clone tags

### 4. scenarios/ink/rfid-guard-low.ink (NEW)
Simple EM4100 example:
- Instant clone pattern
- Proper exit handling
- Minimal complexity for learning

### 5. scenarios/ink/rfid-guard-custom.ink (NEW)
MIFARE Custom Keys example:
- Shows attack requirement
- Player feedback for encrypted cards
- Proper state management

## Key Patterns Documented:

### Correct Ink Pattern:
```ink
+ [Leave] #exit_conversation
  # speaker:npc
  Goodbye!
  -> hub  // Return to hub, NOT END
```

### Correct JSON Pattern:
```json
{
  "type": "keycard",
  "card_id": "employee_badge",
  "rfid_protocol": "EM4100",
  "name": "Employee Badge"
}
```

### Door Configuration:
```json
{
  "lockType": "rfid",
  "requires": ["card1", "card2"],
  "acceptsUIDOnly": false
}
```

## Testing Checklist Added:
- [ ] Uses #exit_conversation tag
- [ ] All knots return to hub
- [ ] Card variables declared
- [ ] Uses card_id format
- [ ] Door requires is array
- [ ] No manual hex entry

## Files Added:
- scenarios/RFID_SCENARIO_PATTERNS.md
- scenarios/test-rfid-multiprotocol.json
- scenarios/ink/rfid-security-guard-fixed.ink
- scenarios/ink/rfid-guard-low.ink
- scenarios/ink/rfid-guard-custom.ink

These serve as reference implementations for scenario designers.
Original files (test-rfid.json, rfid-security-guard.ink) left
unmodified as they may be in use.
2025-11-15 23:48:15 +00:00

5.3 KiB

RFID Scenario Patterns - Correct Usage

This document shows the correct patterns for creating RFID scenarios and Ink scripts in this project.

Correct Ink Pattern

Hub Structure with #exit_conversation

VAR has_keycard = false
VAR has_rfid_cloner = false

// Card protocol variables (auto-synced from NPC itemsHeld)
VAR card_protocol = ""
VAR card_instant_clone = false
VAR card_card_id = ""

=== start ===
# speaker:npc
Hello! I'm a guard.
-> hub

=== hub ===
// Main conversation hub

+ [Option 1]
  -> some_knot

+ [Leave] #exit_conversation
  # speaker:npc
  Goodbye!
  -> hub  // Return to hub, not END

=== some_knot ===
# speaker:npc
Some dialogue here.
-> hub  // Always return to hub

Key Rules:

  1. Use #exit_conversation tag - NOT -> END
  2. Tag goes on the choice line - + [Leave] #exit_conversation
  3. After exit, return to hub - -> hub (not -> END)
  4. Always have a hub knot - Central return point for all conversations
  5. All paths return to hub - Enables conversation to resume

Correct Scenario JSON Pattern

Use card_id Format (New)

{
  "npcId": "security_guard",
  "itemsHeld": [
    {
      "type": "keycard",
      "card_id": "employee_badge",
      "rfid_protocol": "EM4100",
      "name": "Employee Badge"
    }
  ]
}

Benefits:

  • No manual hex/UID entry needed
  • Deterministic generation from card_id
  • Simpler for scenario designers
  • Supports all 4 protocols

Door Configuration

{
  "lockType": "rfid",
  "requires": ["employee_badge", "master_card"],
  "acceptsUIDOnly": false
}

Key Points:

  • requires is an array of card_ids
  • acceptsUIDOnly for DESFire UID emulation
  • Use card_id, not key_id

Incorrect Patterns (DO NOT USE)

Wrong Ink Pattern

=== hub ===
+ [Leave]
  # speaker:npc
  Goodbye!
  -> END  // ❌ WRONG - breaks conversation state

Problems:

  • Uses -> END - conversation can't be resumed
  • Doesn't return to hub
  • State isn't saved properly

Wrong Scenario Pattern (Legacy)

{
  "type": "keycard",
  "rfid_hex": "FF4A7B9C21",
  "rfid_facility": 255,
  "rfid_card_number": 18811,
  "key_id": "master_keycard"
}

Problems:

  • Manual hex entry required
  • Uses old key_id instead of card_id
  • Doesn't work with new protocol system
  • More complex for scenario designers

Protocol-Specific Examples

EM4100 (Instant Clone)

{has_keycard and card_instant_clone and card_protocol == "EM4100":
  + [Scan badge] #clone_keycard:{card_card_id}
    # speaker:player
    Quick scan - card cloned!
    -> success
}

MIFARE Classic - Weak Defaults (Dictionary Attack)

{card_instant_clone and card_protocol == "MIFARE_Classic_Weak_Defaults":
  + [Scan badge] #clone_keycard:{card_card_id}
    # speaker:player
    Dictionary attack succeeded instantly!
    -> success
}

MIFARE Classic - Custom Keys (Needs Attack)

{card_needs_attack:
  + [Try to scan]
    # speaker:player
    Encrypted - need Darkside attack (~30 sec)
    -> needs_time
}

MIFARE DESFire (UID Only)

{card_uid_only:
  + [Save UID only]
    # speaker:player
    Saved UID - only works on weak readers
    -> uid_saved
}

Complete Working Example

See these files for complete examples:

  • scenarios/test-rfid-multiprotocol.json - All 4 protocols
  • scenarios/ink/rfid-guard-low.ink - EM4100 example
  • scenarios/ink/rfid-guard-custom.ink - Custom keys example
  • scenarios/ink/rfid-security-guard-fixed.ink - Full featured example

Common Mistakes

Mistake 1: Using -> END for exits

+ [Leave]
  Goodbye!
  -> END  // ❌ WRONG

Correct:

+ [Leave] #exit_conversation
  # speaker:npc
  Goodbye!
  -> hub  // ✅ RIGHT

Mistake 2: Not returning to hub

=== some_knot ===
Dialog here.
// ❌ Falls off end of knot

Correct:

=== some_knot ===
Dialog here.
-> hub  // ✅ Always return to hub

Mistake 3: Using legacy card format

{
  "rfid_hex": "01AB34CD56",
  "key_id": "employee_badge"
}

Correct:

{
  "card_id": "employee_badge",
  "rfid_protocol": "EM4100"
}

Mistake 4: Single card_id instead of array

{
  "requires": "employee_badge"  // ❌ Works but not preferred
}

Correct:

{
  "requires": ["employee_badge", "master_card"]  // ✅ Array format
}

Protocol Names (Use These Exact Strings)

"EM4100"                         // Low security, instant
"MIFARE_Classic_Weak_Defaults"   // Low security, instant dictionary
"MIFARE_Classic_Custom_Keys"     // Medium security, 30sec Darkside
"MIFARE_DESFire"                 // High security, UID only

Testing Checklist

When creating RFID scenarios, verify:

  • Ink file uses #exit_conversation tag
  • All knots return to hub
  • Card variables declared at top
  • Uses card_id format in JSON
  • Uses rfid_protocol with correct protocol name
  • Door requires is an array
  • No manual hex/UID entry
  • Hub pattern implemented correctly
  • #clone_keycard tag uses {card_card_id} variable

Reference Documentation

For more details see:

  • scenarios/ink/README_RFID_VARIABLES.md - Complete Ink variable reference
  • planning_notes/rfid_keycard/protocols_and_interactions/00_IMPLEMENTATION_SUMMARY.md - Technical implementation details