# Check for invalid room connection directions (diagonal directions)
ifroom['connections']
room['connections'].eachdo|direction,target|
unlessvalid_directions.include?(direction)
issues<<"❌ INVALID: Room '#{room_id}' uses invalid direction '#{direction}' - only north, south, east, west are valid (not northeast, southeast, etc.)"
end
# Check reverse connections if target is a single room
# Check for incorrect VM launcher configuration (type: "pc" with vmAccess)
ifobj['type']=='pc'&&obj['vmAccess']
issues<<"❌ INVALID: '#{path}' uses type: 'pc' with vmAccess - should use type: 'vm-launcher' instead. See scenarios/secgen_vm_lab/scenario.json.erb for example"
issues<<"❌ INVALID: '#{path}' is a container with contents but missing required 'locked' field - must be explicitly true or false for server-side validation"
# Check for key locks without keyPins (REQUIRED, not recommended)
unlessobj['keyPins']
issues<<"❌ INVALID: '#{path}' has lockType: 'key' but missing required 'keyPins' array - key locks must specify keyPins array for lockpicking minigame"
end
end
end
# Check for key items without keyPins (REQUIRED, not recommended)
ifobj['type']=='key'&&!obj['keyPins']
issues<<"❌ INVALID: '#{path}' (key item) missing required 'keyPins' array - key items must specify keyPins array for lockpicking"
end
# Check for items with id field (should use type field for #give_item tags)
ifobj['itemsHeld']
obj['itemsHeld'].each_with_indexdo|item,item_idx|
ifitem['id']
issues<<"❌ INVALID: '#{path}/itemsHeld[#{item_idx}]' has 'id' field - items should NOT have 'id' field. Use 'type' field to match #give_item tag parameter"
end
end
end
end
end
# Track room lock types
ifroom['locked']&&room['lockType']
lock_types_used.add(room['lockType'])
caseroom['lockType']
when'rfid'
has_rfid_lock=true
when'bluetooth'
has_bluetooth_lock=true
when'pin'
has_pin_lock=true
when'password'
has_password_lock=true
when'key'
has_key_lock=true
# Check for key locks without keyPins (REQUIRED, not recommended)
unlessroom['keyPins']
issues<<"❌ INVALID: 'rooms/#{room_id}' has lockType: 'key' but missing required 'keyPins' array - key locks must specify keyPins array for lockpicking minigame"
# Validate phone NPC structure - should have phoneId
unlessnpc['phoneId']
issues<<"❌ INVALID: '#{path}' (phone NPC) missing required 'phoneId' field - phone NPCs must specify which phone they appear on (e.g., 'player_phone')"
# Validate phone NPC structure - should NOT have position (phone NPCs don't have positions)
ifnpc['position']
issues<<"⚠ WARNING: '#{path}' (phone NPC) has 'position' field - phone NPCs should NOT have position (they're not in-world sprites). Remove the position field."
# Validate phone NPC structure - should NOT have spriteSheet (phone NPCs don't have sprites)
ifnpc['spriteSheet']
issues<<"⚠ WARNING: '#{path}' (phone NPC) has 'spriteSheet' field - phone NPCs should NOT have spriteSheet (they're not in-world sprites). Remove the spriteSheet field."
issues<<"❌ INVALID: '#{path}/itemsHeld[#{item_idx}]' has 'id' field - items should NOT have 'id' field. Use 'type' field to match #give_item tag parameter (e.g., type: 'id_badge' matches #give_item:id_badge)"
# Flag incorrect structure - phone NPCs should be in rooms, not phoneNPCs section
issues<<"❌ INVALID: '#{path}' - Phone NPCs should be defined in 'rooms/{room_id}/npcs[]' arrays, NOT in a separate 'phoneNPCs' section. See scenarios/npc-sprite-test3/scenario.json.erb for correct format. Phone NPCs should be in the starting room (or room where phone is accessible) with npcType: 'phone'"
issues<<"💡 SUGGESTION: Consider adding VM launcher terminals (type: 'vm-launcher') - see scenarios/secgen_vm_lab/scenario.json.erb for example"
end
unlesshas_flag_station
issues<<"💡 SUGGESTION: Consider adding flag station terminals (type: 'flag-station') for VM flag submission - see scenarios/secgen_vm_lab/scenario.json.erb for example"
end
unlesshas_pc_with_files
issues<<"💡 SUGGESTION: Consider adding at least one PC container (type: 'pc') with files in 'contents' array and optional post-it notes - see scenarios/ceo_exfil/scenario.json.erb for example"
issues<<"💡 SUGGESTION: Consider adding at least one phone NPC (in rooms or phoneNPCs section) with timedMessages or eventMappings - see scenarios/ceo_exfil/scenario.json.erb for example"
end
unlesshas_opening_cutscene
issues<<"💡 SUGGESTION: Consider adding opening briefing cutscene - NPC with timedConversation (delay: 0) in starting room - see scenarios/m01_first_contact/scenario.json.erb for example"
end
unlesshas_closing_debrief
issues<<"💡 SUGGESTION: Consider adding closing debrief trigger - phone NPC with eventMapping for global_variable_changed - see scenarios/m01_first_contact/scenario.json.erb for example"
end
# Check for NPCs without waypoints
ifhas_person_npcs&&!has_npc_with_waypoints
issues<<"💡 SUGGESTION: Consider adding waypoints to at least one person NPC for more dynamic patrol behavior - see scenarios/test-npc-waypoints/scenario.json.erb for example. Add 'behavior.patrol.waypoints' array with {x, y} coordinates"
issues<<"💡 SUGGESTION: Consider adding timedMessages to phone contacts for more engaging interactions - see scenarios/npc-sprite-test3/scenario.json.erb for example. Phone NPCs without timed messages: #{npc_list}"
issues<<"💡 SUGGESTION: Consider adding variety in lock types - scenarios typically use 2+ different lock mechanisms (key, pin, rfid, password). Currently using: #{lock_types_used.to_a.join(', ')||'none'}. See scenarios/ceo_exfil/scenario.json.erb for examples"
end
# Suggest RFID locks
unlesshas_rfid_lock
issues<<"💡 SUGGESTION: Consider adding RFID locks for modern security scenarios - see scenarios/test-rfid/scenario.json.erb for examples"
end
# Suggest PIN locks
unlesshas_pin_lock
issues<<"💡 SUGGESTION: Consider adding PIN locks for numeric code challenges - see scenarios/ceo_exfil/scenario.json.erb for examples"
end
# Suggest password locks
unlesshas_password_lock
issues<<"💡 SUGGESTION: Consider adding password locks for computer/device access - see scenarios/ceo_exfil/scenario.json.erb for examples"
end
# Suggest security tools
unlesshas_security_tools
issues<<"💡 SUGGESTION: Consider adding security tools (fingerprint_kit, pin-cracker, bluetooth_scanner, rfid_cloner) for more interactive gameplay - see scenarios/ceo_exfil/scenario.json.erb for examples"
end
# Suggest containers with contents
unlesshas_container_with_contents
issues<<"💡 SUGGESTION: Consider adding containers (safes, suitcases) with contents for hidden items and rewards - see scenarios/ceo_exfil/scenario.json.erb for examples"
end
# Suggest readable items
unlesshas_readable_items
issues<<"💡 SUGGESTION: Consider adding readable items (notes, documents) for storytelling and clues - see scenarios/ceo_exfil/scenario.json.erb for examples"