Class: Lich::Common::Map

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
documented/common/map/map_dr.rb,
documented/common/map/map_dr.rb,
documented/common/map/map_gs.rb,
documented/common/map/map_gs.rb

Overview

Represents a map in the Lich game. This class handles the management of rooms, their properties, and navigation.

Examples:

Creating a new map

map = Lich::Common::Map.new(1, "Room Title", "Room Description", ["path1", "path2"])

Direct Known Subclasses

Room

Defined Under Namespace

Classes: MinHeap

Constant Summary collapse

@@loaded =
false
@@load_mutex =
Mutex.new
@@current_room_mutex =
Mutex.new
@@fuzzy_room_mutex =
Mutex.new
@@uids =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id, title, description, paths, uid = [], location = nil, climate = nil, terrain = nil, wayto = {}, timeto = {}, image = nil, image_coords = nil, tags = [], check_location = nil, unique_loot = nil) ⇒ Map

Initializes a new map room.

Parameters:

  • id (Integer)

    The unique identifier for the room.

  • title (String)

    The title of the room.

  • description (String)

    A description of the room.

  • paths (Array<String>)

    The paths leading from this room.

  • uid (Array<Integer>) (defaults to: [])

    The unique identifiers associated with this room.

  • location (String, nil) (defaults to: nil)

    The location of the room.

  • climate (String, nil) (defaults to: nil)

    The climate of the room.

  • terrain (String, nil) (defaults to: nil)

    The terrain type of the room.

  • wayto (Hash<String, String>) (defaults to: {})

    The ways to other rooms.

  • timeto (Hash<String, Float>) (defaults to: {})

    The time to travel to other rooms.

  • image (String, nil) (defaults to: nil)

    The image associated with the room.

  • image_coords (Array<Integer>, nil) (defaults to: nil)

    The coordinates for the image.

  • tags (Array<String>) (defaults to: [])

    Tags associated with the room.

  • check_location (String, nil) (defaults to: nil)

    A check for the location.

  • unique_loot (Array<String>, nil) (defaults to: nil)

    Unique loot available in the room.



45
46
47
48
# File 'documented/common/map/map_dr.rb', line 45

def initialize(id, title, description, paths, uid = [], location = nil, climate = nil, terrain = nil, wayto = {}, timeto = {}, image = nil, image_coords = nil, tags = [], check_location = nil, unique_loot = nil, _room_objects = nil)
  @id, @title, @description, @paths, @uid, @location, @climate, @terrain, @wayto, @timeto, @image, @image_coords, @tags, @check_location, @unique_loot = id, title, description, paths, uid, location, climate, terrain, wayto, timeto, image, image_coords, tags, check_location, unique_loot
  @@list[@id] = self
end

Instance Attribute Details

#check_locationObject

Returns the value of attribute check_location.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def check_location
  @check_location
end

#climateObject

Returns the value of attribute climate.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def climate
  @climate
end

#descriptionObject

Returns the value of attribute description.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def description
  @description
end

#idObject (readonly)

Returns the value of attribute id.



25
26
27
# File 'documented/common/map/map_dr.rb', line 25

def id
  @id
end

#imageObject

Returns the value of attribute image.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def image
  @image
end

#image_coordsObject

Returns the value of attribute image_coords.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def image_coords
  @image_coords
end

#locationObject

Returns the value of attribute location.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def location
  @location
end

#pathsObject

Returns the value of attribute paths.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def paths
  @paths
end

#room_objectsObject

Returns the value of attribute room_objects.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def room_objects
  @room_objects
end

#tagsObject

Returns the value of attribute tags.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def tags
  @tags
end

#terrainObject

Returns the value of attribute terrain.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def terrain
  @terrain
end

#timetoObject

Returns the value of attribute timeto.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def timeto
  @timeto
end

#titleObject

Returns the value of attribute title.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def title
  @title
end

#uidObject

Returns the value of attribute uid.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def uid
  @uid
end

#unique_lootObject

Returns the value of attribute unique_loot.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def unique_loot
  @unique_loot
end

#waytoObject

Returns the value of attribute wayto.



26
27
28
# File 'documented/common/map/map_dr.rb', line 26

def wayto
  @wayto
end

Class Method Details

.[](val) ⇒ Map?

Accesses a room by its ID or UID.

Parameters:

  • val (Integer, String)

    The ID or UID of the room to access.

Returns:

  • (Map, nil)

    The room if found, nil otherwise.



83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'documented/common/map/map_dr.rb', line 83

def Map.[](val)
  Map.load unless @@loaded
  if (val.is_a?(Integer)) or val =~ /^[0-9]+$/
    @@list[val.to_i]
  elsif val =~ /^u(-?\d+)$/i
    uid_request = $1.dup.to_i
    @@list[(Map.ids_from_uid(uid_request)[0]).to_i]
  else
    chkre = /#{val.strip.sub(/\.$/, '').gsub(/\.(?:\.\.)?/, '|')}/i
    chk = /#{Regexp.escape(val.strip)}/i
    @@list.find { |room| room.title.find { |title| title =~ chk } } || @@list.find { |room| room.description.find { |desc| desc =~ chk } } || @@list.find { |room| room.description.find { |desc| desc =~ chkre } }
  end
end

.clearBoolean

Clears the map data, including rooms and their properties.

Returns:

  • (Boolean)

    True if the clear operation was successful.



359
360
361
362
363
364
365
366
367
# File 'documented/common/map/map_dr.rb', line 359

def Map.clear
  @@load_mutex.synchronize {
    @@list.clear
    @@tags.clear
    @@loaded = false
    GC.start
  }
  true
end

.currentMap?

Gets the current room based on the game state.

Returns:

  • (Map, nil)

    The current room if found, nil otherwise.



111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'documented/common/map/map_dr.rb', line 111

def Map.current # returns Map/Room
  Map.load unless @@loaded
  if Script.current
    return @@list[@@current_room_id] if XMLData.room_count == @@current_room_count and !@@current_room_id.nil?;
  else
    return @@list[@@current_room_id] if XMLData.room_count == @@fuzzy_room_count and !@@current_room_id.nil?;
  end
  ids = (XMLData.room_id.zero? ? [] : Map.ids_from_uid(XMLData.room_id))
  return Map.set_current(ids[0]) if (ids.size == 1)
  if ids.size > 1 and !@@current_room_id.nil? and (id = Map.match_multi_ids(ids))
    return Map.set_current(id)
  end
  return Map.match_no_uid()
end

.current_or_newMap?

Gets the current room or creates a new one if it doesn’t exist.

Returns:

  • (Map, nil)

    The current room if found, nil otherwise.



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'documented/common/map/map_dr.rb', line 258

def Map.current_or_new # returns Map/Room
  return nil unless Script.current
  @@current_room_count = -1
  @@fuzzy_room_count = -1

  Map.load unless @@loaded

  room = nil

  id = Map.current ? Map.current.id : nil

  echo("Map: current room id is #{id.inspect}")
  unless id.nil?
    room = Map[id]
    unless XMLData.room_id.zero? || room.uid.include?(XMLData.room_id)
      room.uid << XMLData.room_id
      Map.uids_add(XMLData.room_id, room.id)
      echo "Map: Adding new uid for #{room.id}: #{XMLData.room_id}"
    end
    return Map.set_current(room.id)
  end
  id               = Map.get_free_id
  title            = [XMLData.room_title]
  description      = [XMLData.room_description.strip]
  paths            = [XMLData.room_exits_string.strip]
  uid              = (XMLData.room_id.zero? ? [] : [XMLData.room_id])
  room             = Map.new(id, title, description, paths, uid)
  Map.uids_add(XMLData.room_id, room.id) unless XMLData.room_id.zero?
  echo "mapped new room, set current room to #{room.id}"
  return Map.set_current(id)
end

.current_room_idInteger

Gets the current room ID.

Returns:

  • (Integer)

    The ID of the current room.



52
# File 'documented/common/map/map_gs.rb', line 52

def Map.current_room_id; return @@current_room_id; end

.current_room_id=(id) ⇒ Object

Sets the current room ID.

Parameters:

  • id (Integer)

    The ID to set as the current room.



55
# File 'documented/common/map/map_gs.rb', line 55

def Map.current_room_id=(id); @@current_room_id = id; end

.dijkstra(source, destination = nil) ⇒ Array<Integer>, Array<Float>

Performs Dijkstra’s algorithm to find the shortest path from the source room.

Parameters:

  • destination (Integer, nil) (defaults to: nil)

    The optional destination room ID.

Returns:

  • (Array<Integer>, Array<Float>)

    The previous room IDs and shortest distances.



798
799
800
801
802
803
804
805
806
807
# File 'documented/common/map/map_dr.rb', line 798

def Map.dijkstra(source, destination = nil)
  if source.is_a?(Map)
    source.dijkstra(destination)
  elsif (room = Map[source])
    room.dijkstra(destination)
  else
    echo "Map.dijkstra: error: invalid source room"
    nil
  end
end

.estimate_time(array) ⇒ Float

Estimates the time to travel through a series of rooms.

Parameters:

  • array (Array<Integer>)

    The array of room IDs to estimate time for.

Returns:

  • (Float)

    The estimated time to travel through the rooms.



774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
# File 'documented/common/map/map_dr.rb', line 774

def Map.estimate_time(array)
  Map.load unless @@loaded
  unless array.is_a?(Array)
    raise Exception.exception("MapError"), "Map.estimate_time was given something not an array!"
  end
  time = 0.to_f
  until array.length < 2
    room = array.shift
    if (t = Map[room].timeto[array.first.to_s])
      if t.is_a?(StringProc)
        time += t.call.to_f
      else
        time += t.to_f
      end
    else
      time += "0.2".to_f
    end
  end
  time
end

.findpath(source, destination) ⇒ Array<Integer>?

Finds the path from the source room to the destination room.

Parameters:

  • source (Integer, Map)

    The source room ID or Map object.

  • destination (Integer)

    The destination room ID.

Returns:

  • (Array<Integer>, nil)

    The path as an array of room IDs or nil if not found.



941
942
943
944
945
946
947
948
949
950
# File 'documented/common/map/map_dr.rb', line 941

def Map.findpath(source, destination)
  if source.is_a?(Map)
    source.path_to(destination)
  elsif (room = Map[source])
    room.path_to(destination)
  else
    echo "Map.findpath: error: invalid source room"
    nil
  end
end

.fuzzy_room_idInteger

Gets the fuzzy room ID.

Returns:

  • (Integer)

    The fuzzy room ID.



89
# File 'documented/common/map/map_gs.rb', line 89

def Map.fuzzy_room_id; return @@fuzzy_room_id; end

.get_free_idInteger

Gets a free ID for a new room.

Returns:

  • (Integer)

    A free ID for a new room.



68
69
70
71
# File 'documented/common/map/map_dr.rb', line 68

def Map.get_free_id
  Map.load unless @@loaded
  return @@list.compact.max_by { |r| r.id }.id + 1
end

.get_locationString?

Gets the current location based on the game state.

Returns:

  • (String, nil)

    The current location or nil if not set.



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'documented/common/map/map_gs.rb', line 124

def Map.get_location
  unless XMLData.room_count == @@current_location_count
    if (script = Script.current)
      save_want_downstream = script.want_downstream
      script.want_downstream = true
      waitrt?
      location_result = dothistimeout 'location', 15, /^You carefully survey your surroundings and guess that your current location is .*? or somewhere close to it\.$|^You can't do that while submerged under water\.$|^You can't do that\.$|^It would be rude not to give your full attention to the performance\.$|^You can't do that while hanging around up here!$|^You are too distracted by the difficulty of staying alive in these treacherous waters to do that\.$|^You carefully survey your surroundings but are unable to guess your current location\.$|^Not in pitch darkness you don't\.$|^That is too difficult to consider here\.$/
      script.want_downstream = save_want_downstream
      @@current_location_count = XMLData.room_count
      if location_result =~ /^You can't do that while submerged under water\.$|^You can't do that\.$|^It would be rude not to give your full attention to the performance\.$|^You can't do that while hanging around up here!$|^You are too distracted by the difficulty of staying alive in these treacherous waters to do that\.$|^You carefully survey your surroundings but are unable to guess your current location\.$|^Not in pitch darkness you don't\.$|^That is too difficult to consider here\.$/
        @@current_location = false
      else
        @@current_location = /^You carefully survey your surroundings and guess that your current location is (.*?) or somewhere close to it\.$/.match(location_result).captures.first
      end
    else
      return nil
    end
  end
  return @@current_location
end

.ids_from_uid(n) ⇒ Array<Integer>

Gets the room IDs associated with a given UID.

Parameters:

  • n (Integer)

    The UID to look up.

Returns:

  • (Array<Integer>)

    An array of room IDs associated with the UID.



353
354
355
# File 'documented/common/map/map_dr.rb', line 353

def Map.ids_from_uid(n)
  return (@@uids[n].nil? || n == 0 ? [] : @@uids[n])
end

.imagesArray<String>

Gets the unique images from all rooms.

Returns:

  • (Array<String>)

    An array of unique images.



470
471
472
473
474
# File 'documented/common/map/map_gs.rb', line 470

def Map.images
  Map.load unless @@loaded
  @@images = @@list.each_with_object({}) { |r, h| h[r.image] = nil if !h.key?(r.image) }.keys if @@images.empty?;
  return @@images.dup
end

.listArray<Map>

Gets the list of all rooms.

Returns:

  • (Array<Map>)

    An array of all rooms.



75
76
77
78
# File 'documented/common/map/map_dr.rb', line 75

def Map.list
  Map.load unless @@loaded
  @@list
end

.load(filename = nil) ⇒ Boolean

Loads the map data from files.

Parameters:

  • filename (String, nil) (defaults to: nil)

    The optional filename to load from.

Returns:

  • (Boolean)

    True if the load operation was successful.



379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
# File 'documented/common/map/map_dr.rb', line 379

def Map.load(filename = nil)
  if filename.nil?
    file_list = Dir.entries("#{DATA_DIR}/#{XMLData.game}").find_all { |filename| filename =~ /^map\-[0-9]+\.(?:dat|xml|json)$/i }.collect { |filename| "#{DATA_DIR}/#{XMLData.game}/#{filename}" }.sort.reverse
  else
    file_list = [filename]
  end
  if file_list.empty?
    respond "--- Lich: error: no map database found"
    return false
  end
  while (filename = file_list.shift)
    if filename =~ /\.json$/i
      if Map.load_json(filename)
        return true
      end
    elsif filename =~ /\.xml$/
      if Map.load_xml(filename)
        return true
      end
    else
      if Map.load_dat(filename)
        return true
      end
    end
  end
  return false
end

.load_dat(filename = nil) ⇒ Boolean

Loads map data from a DAT file.

Parameters:

  • filename (String, nil) (defaults to: nil)

    The optional filename to load from.

Returns:

  • (Boolean)

    True if the load operation was successful.



463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
# File 'documented/common/map/map_dr.rb', line 463

def Map.load_dat(filename = nil)
  @@load_mutex.synchronize {
    if @@loaded
      return true
    else
      if filename.nil?
        file_list = Dir.entries("#{DATA_DIR}/#{XMLData.game}").find_all { |filename| filename =~ /^map\-[0-9]+\.dat$/ }.collect { |filename| "#{DATA_DIR}/#{XMLData.game}/#{filename}" }.sort.reverse
      else
        file_list = [filename]
        respond "--- file_list = #{filename.inspect}"
      end
      if file_list.empty?
        respond "--- Lich: error: no map database found"
        return false
      end
      while (filename = file_list.shift)
        begin
          @@list = File.open(filename, 'rb') { |f| Marshal.load(f.read) }
          respond "--- Map loaded #{filename}" # if error

          @@loaded = true
          Map.load_uids
          return true
        rescue
          if file_list.empty?
            respond "--- Lich: error: failed to load #{filename}: #{$!}"
          else
            respond "--- warning: failed to load #{filename}: #{$!}"
          end
        end
      end
      return false
    end
  }
end

.load_json(filename = nil) ⇒ Boolean

Loads map data from a JSON file.

Parameters:

  • filename (String, nil) (defaults to: nil)

    The optional filename to load from.

Returns:

  • (Boolean)

    True if the load operation was successful.



410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
# File 'documented/common/map/map_dr.rb', line 410

def Map.load_json(filename = nil)
  @@load_mutex.synchronize {
    if @@loaded
      return true
    else
      if filename
        file_list = [filename]
        # respond "--- loading #{filename}" #if error
      else
        file_list = Dir.entries("#{DATA_DIR}/#{XMLData.game}").find_all { |filename|
          filename =~ /^map\-[0-9]+\.json$/i
        }.collect { |filename|
          "#{DATA_DIR}/#{XMLData.game}/#{filename}"
        }.sort.reverse
        # respond "--- loading #{filename}" #if error
      end
      if file_list.empty?
        respond "--- Lich: error: no map database found"
        return false
      end
      while (filename = file_list.shift)
        if File.exist?(filename)
          File.open(filename) { |f|
            JSON.parse(f.read).each { |room|
              room['wayto'].keys.each { |k|
                if room['wayto'][k][0..2] == ';e '
                  room['wayto'][k] = StringProc.new(room['wayto'][k][3..-1])
                end
              }
              room['timeto'].keys.each { |k|
                if (room['timeto'][k].is_a?(String)) and (room['timeto'][k][0..2] == ';e ')
                  room['timeto'][k] = StringProc.new(room['timeto'][k][3..-1])
                end
              }
              room['tags'] ||= []
              room['uid'] ||= []
              Map.new(room['id'], room['title'], room['description'], room['paths'], room['uid'], room['location'], room['climate'], room['terrain'], room['wayto'], room['timeto'], room['image'], room['image_coords'], room['tags'], room['check_location'], room['unique_loot'])
            }
          }
          @@tags.clear
          respond "--- Map loaded #{filename}" # if error
          @@loaded = true
          Map.load_uids
          return true
        end
      end
    end
  }
end

.load_uidsObject

Loads the UID mappings from the current list of rooms.



336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'documented/common/map/map_dr.rb', line 336

def Map.load_uids()
  Map.load unless @@loaded
  @@uids.clear
  @@list.each { |r|
    r.uid.each { |u|
      if @@uids[u].nil?
        @@uids[u] = [r.id]
      else
        @@uids[u] << r.id if !@@uids[u].include?(r.id)
      end
    }
  }
end

.load_xml(filename = "#{DATA_DIR}/#{XMLData.game}/map.xml") ⇒ Boolean

Loads map data from an XML file.

Parameters:

  • filename (String) (defaults to: "#{DATA_DIR}/#{XMLData.game}/map.xml")

    The filename to load from.

Returns:

  • (Boolean)

    True if the load operation was successful.



502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
# File 'documented/common/map/map_dr.rb', line 502

def Map.load_xml(filename = "#{DATA_DIR}/#{XMLData.game}/map.xml")
  @@load_mutex.synchronize {
    if @@loaded
      return true
    else
      unless File.exist?(filename)
        raise Exception.exception("MapDatabaseError"), "Fatal error: file `#{filename}' does not exist!"
      end
      missing_end = false
      current_tag = nil
      current_attributes = nil
      room = nil
      buffer = String.new
      unescape = { 'lt' => '<', 'gt' => '>', 'quot' => '"', 'apos' => "'", 'amp' => '&' }
      tag_start = proc { |element, attributes|
        current_tag = element
        current_attributes = attributes
        if element == 'room'
          room = Hash.new
          room['id'] = attributes['id'].to_i
          room['location'] = attributes['location']
          room['climate'] = attributes['climate']
          room['terrain'] = attributes['terrain']
          room['wayto'] = Hash.new
          room['timeto'] = Hash.new
          room['title'] = Array.new
          room['description'] = Array.new
          room['paths'] = Array.new
          room['tags'] = Array.new
          room['unique_loot'] = Array.new
          room['uid'] = Array.new
          room['room_objects'] = Array.new
        elsif element =~ /^(?:image|tsoran)$/ and attributes['name'] and attributes['x'] and attributes['y'] and attributes['size']
          room['image'] = attributes['name']
          room['image_coords'] = [(attributes['x'].to_i - (attributes['size'] / 2.0).round), (attributes['y'].to_i - (attributes['size'] / 2.0).round), (attributes['x'].to_i + (attributes['size'] / 2.0).round), (attributes['y'].to_i + (attributes['size'] / 2.0).round)]
        elsif (element == 'image') and attributes['name'] and attributes['coords'] and (attributes['coords'] =~ /[0-9]+,[0-9]+,[0-9]+,[0-9]+/)
          room['image'] = attributes['name']
          room['image_coords'] = attributes['coords'].split(',').collect { |num| num.to_i }
        elsif element == 'map'
          missing_end = true
        end
      }
      text = proc { |text_string|
        if current_tag == 'tag'
          room['tags'].push(text_string)
        elsif current_tag =~ /^(?:title|description|paths|unique_loot|tag|room_objects)$/
          room[current_tag].push(text_string)
        elsif current_tag =~ /^(?:uid)$/
          room[current_tag].push(text_string.to_i)
        elsif current_tag == 'exit' and current_attributes['target']
          if current_attributes['type'].downcase == 'string'
            room['wayto'][current_attributes['target']] = text_string
          end
          if current_attributes['cost'] =~ /^[0-9\.]+$/
            room['timeto'][current_attributes['target']] = current_attributes['cost'].to_f
          elsif current_attributes['cost'].length > 0
            room['timeto'][current_attributes['target']] = StringProc.new(current_attributes['cost'])
          else
            room['timeto'][current_attributes['target']] = 0.2
          end
        end
      }
      tag_end = proc { |element|
        if element == 'room'
          room['unique_loot'] = nil if room['unique_loot'].empty?
          room['room_objects'] = nil if room['room_objects'].empty?
          Map.new(room['id'], room['title'], room['description'], room['paths'], room['uid'], room['location'], room['climate'], room['terrain'], room['wayto'], room['timeto'], room['image'], room['image_coords'], room['tags'], room['check_location'], room['unique_loot'], room['room_objects'])
        elsif element == 'map'
          missing_end = false
        end
        current_tag = nil
      }
      begin
        File.open(filename) { |file|
          while (line = file.gets)
            buffer.concat(line)
            # fixme: remove   (?=<)   ?
            while (str = buffer.slice!(/^<([^>]+)><\/\1>|^[^<]+(?=<)|^<[^<]+>/))
              if str[0, 1] == '<'
                if str[1, 1] == '/'
                  element = /^<\/([^\s>\/]+)/.match(str).captures.first
                  tag_end.call(element)
                else
                  if str =~ /^<([^>]+)><\/\1>/
                    element = $1
                    tag_start.call(element)
                    text.call('')
                    tag_end.call(element)
                  else
                    element = /^<([^\s>\/]+)/.match(str).captures.first
                    attributes = Hash.new
                    str.scan(/([A-z][A-z0-9_\-]*)=(["'])(.*?)\2/).each { |attr| attributes[attr[0]] = attr[2].gsub(/&(#{unescape.keys.join('|')});/) { unescape[$1] } }
                    tag_start.call(element, attributes)
                    tag_end.call(element) if str[-2, 1] == '/'
                  end
                end
              else
                text.call(str.gsub(/&(#{unescape.keys.join('|')});/) { unescape[$1] })
              end
            end
          end
        }
        if missing_end
          respond "--- Lich: error: failed to load #{filename}: unexpected end of file"
          return false
        end
        @@tags.clear
        Map.load_uids
        @@loaded = true
        return true
      rescue
        respond "--- Lich: error: failed to load #{filename}: #{$!}"
        return false
      end
    end
  }
end

.loadedBoolean

Checks if the map is loaded.

Returns:

  • (Boolean)

    True if the map is loaded, false otherwise.



58
# File 'documented/common/map/map_gs.rb', line 58

def Map.loaded; return @@loaded; end

.locationsArray<String>

Gets the unique locations from all rooms.

Returns:

  • (Array<String>)

    An array of unique locations.



462
463
464
465
466
# File 'documented/common/map/map_gs.rb', line 462

def Map.locations
  Map.load unless @@loaded
  @@locations = @@list.each_with_object({}) { |r, h| h[r.location] = nil if !h.key?(r.location) }.keys if @@locations.empty?;
  return @@locations.dup
end

.match_current(script) ⇒ Integer

Matches the current room based on the script’s state.

Parameters:

  • script (Script)

    The current script context.

Returns:

  • (Integer)

    The ID of the matched room.



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'documented/common/map/map_dr.rb', line 148

def Map.match_current(_script) # returns id
  @@current_room_mutex.synchronize {
    Hash.new
    need_set_desc_off = false
    begin
      begin
        @@current_room_count = XMLData.room_count
        foggy_exits = (XMLData.room_exits_string =~ /^Obvious (?:exits|paths): obscured by a thick fog$/)
        if (room = @@list.find { |r|
              r.title.include?(XMLData.room_title) and
                r.description.include?(XMLData.room_description.strip) and
                (foggy_exits or r.paths.include?(XMLData.room_exits_string.strip))
            })
          redo unless @@current_room_count == XMLData.room_count
          if room.uid.any?
            unless room.uid.include?(XMLData.room_id)
              return nil
            else
              return room.id
            end
          else
            return room.id
          end
        else
          redo unless @@current_room_count == XMLData.room_count
          desc_regex = /#{Regexp.escape(XMLData.room_description.strip.sub(/\.+$/, '')).gsub(/\\\.(?:\\\.\\\.)?/, '|')}/
          if (room = @@list.find { |r|
                r.title.include?(XMLData.room_title) and
                  (foggy_exits or r.paths.include?(XMLData.room_exits_string.strip)) and
                  (XMLData.room_window_disabled or r.description.any? { |desc| desc =~ desc_regex })
              })
            redo unless @@current_room_count == XMLData.room_count
            if room.uid.any?
              unless room.uid.include?(XMLData.room_id)
                return nil
              else
                return room.id
              end
            else
              return room.id
            end
          else
            redo unless @@current_room_count == XMLData.room_count
            return nil
          end
        end
      end
    ensure
      put 'set description off' if need_set_desc_off
    end
  }
end

.match_fuzzyInteger?

Matches a room based on fuzzy logic.

Returns:

  • (Integer, nil)

    The matched room ID if found, nil otherwise.



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'documented/common/map/map_dr.rb', line 203

def Map.match_fuzzy() # returns id
  @@fuzzy_room_mutex.synchronize {
    @@fuzzy_room_count = XMLData.room_count
    begin
      foggy_exits = (XMLData.room_exits_string =~ /^Obvious (?:exits|paths): obscured by a thick fog$/)
      if (room = @@list.find { |r|
            r.title.include?(XMLData.room_title) and
              r.description.include?(XMLData.room_description.strip) and
              (foggy_exits or r.paths.include?(XMLData.room_exits_string.strip))
          })
        redo unless @@fuzzy_room_count == XMLData.room_count

        if room.uid.any?
          unless room.uid.include?(XMLData.room_id)
            return nil
          else
            return room.id
          end
        elsif room.tags.any? { |tag| tag =~ /^(set desc on; )?peer [a-z]+ =~ \/.+\/$/ }
          return nil
        else
          return room.id
        end
      else
        redo unless @@fuzzy_room_count == XMLData.room_count
        desc_regex = /#{Regexp.escape(XMLData.room_description.strip.sub(/\.+$/, '')).gsub(/\\\.(?:\\\.\\\.)?/, '|')}/
        if (room = @@list.find { |r|
              r.title.include?(XMLData.room_title) and
              (foggy_exits or r.paths.include?(XMLData.room_exits_string.strip)) and
              (XMLData.room_window_disabled or r.description.any? { |desc| desc =~ desc_regex })
            })
          redo unless @@fuzzy_room_count == XMLData.room_count

          if room.uid.any?
            unless room.uid.include?(XMLData.room_id)
              return nil
            else
              return room.id
            end
          elsif room.tags.any? { |tag| tag =~ /^(set desc on; )?peer [a-z]+ =~ \/.+\/$/ }
            return nil
          else
            return room.id
          end
        else
          redo unless @@fuzzy_room_count == XMLData.room_count
          return nil
        end
      end
    end
  }
end

.match_multi_ids(ids) ⇒ Integer?

Matches multiple room IDs based on the current room’s wayto.

Parameters:

  • ids (Array<Integer>)

    The array of IDs to match.

Returns:

  • (Integer, nil)

    The matched ID if found, nil otherwise.



314
315
316
317
318
# File 'documented/common/map/map_dr.rb', line 314

def Map.match_multi_ids(ids) # returns id
  matches = ids.find_all { |s| @@list[@@current_room_id].wayto.keys.include?(s.to_s) }
  return matches[0] if matches.size == 1;
  return nil;
end

.match_no_uidMap?

Matches the current room based on the game state without a UID.

Returns:

  • (Map, nil)

    The matched room if found, nil otherwise.



128
129
130
131
132
133
134
# File 'documented/common/map/map_dr.rb', line 128

def Map.match_no_uid() # returns Map/Room
  if (script = Script.current)
    return Map.set_current(Map.match_current(script))
  else
    return Map.set_fuzzy(Map.match_fuzzy())
  end
end

.previousMap?

Gets the previous room based on the previous room ID.

Returns:

  • (Map, nil)

    The previous room if found, nil otherwise.



99
100
101
# File 'documented/common/map/map_dr.rb', line 99

def Map.previous
  return @@list[@@previous_room_id]
end

.previous_room_idInteger?

Gets the previous room ID.

Returns:

  • (Integer, nil)

    The ID of the previous room or nil if not set.



61
# File 'documented/common/map/map_gs.rb', line 61

def Map.previous_room_id; return @@previous_room_id; end

.previous_room_id=(id) ⇒ Object

Sets the previous room ID.

Parameters:

  • id (Integer)

    The ID to set as the previous room.



64
# File 'documented/common/map/map_gs.rb', line 64

def Map.previous_room_id=(id); @@previous_room_id = id; end

.previous_uidInteger

Gets the previous room UID.

Returns:

  • (Integer)

    The previous room UID.



105
106
107
# File 'documented/common/map/map_dr.rb', line 105

def Map.previous_uid
  return XMLData.previous_nav_rm
end

.reloadBoolean

Reloads the map data from the source.

Returns:

  • (Boolean)

    True if the reload operation was successful.



371
372
373
374
# File 'documented/common/map/map_dr.rb', line 371

def Map.reload
  Map.clear
  Map.load
end

.save(filename = "#{DATA_DIR}/#{XMLData.game}/map-#{Time.now.to_i}.dat") ⇒ Boolean

Saves the current map data to a DAT file.

Parameters:

  • filename (String) (defaults to: "#{DATA_DIR}/#{XMLData.game}/map-#{Time.now.to_i}.dat")

    The filename to save to.

Returns:

  • (Boolean)

    True if the save operation was successful.



623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
# File 'documented/common/map/map_dr.rb', line 623

def Map.save(filename = "#{DATA_DIR}/#{XMLData.game}/map-#{Time.now.to_i}.dat")
  if File.exist?(filename)
    respond "--- Backing up map database"
    begin
      # fixme: does this work on all platforms? File.rename(filename, "#{filename}.bak")
      File.open(filename, 'rb') { |infile|
        File.open("#{filename}.bak", 'wb') { |outfile|
          outfile.write(infile.read)
        }
      }
    rescue
      respond "--- Lich: error: #{$!}"
    end
  end
  begin
    File.open(filename, 'wb') { |f| f.write(Marshal.dump(@@list)) }
    @@tags.clear
    respond "--- Map database saved"
  rescue
    respond "--- Lich: error: #{$!}"
  end
end

.save_json(filename = "#{DATA_DIR}/#{XMLData.game}/map-#{Time.now.to_i}.json") ⇒ Boolean

Saves the current map data to a JSON file.

Parameters:

  • filename (String) (defaults to: "#{DATA_DIR}/#{XMLData.game}/map-#{Time.now.to_i}.json")

    The filename to save to.

Returns:

  • (Boolean)

    True if the save operation was successful.



678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
# File 'documented/common/map/map_dr.rb', line 678

def Map.save_json(filename = "#{DATA_DIR}/#{XMLData.game}/map-#{Time.now.to_i}.json")
  if File.exist?(filename)
    respond "File exists!  Backing it up before proceeding..."
    begin
      File.open(filename, 'rb') { |infile|
        File.open("#{filename}.bak", "wb:UTF-8") { |outfile|
          outfile.write(infile.read)
        }
      }
    rescue
      respond "--- Lich: error: #{$!}\n\t#{$!.backtrace[0..1].join("\n\t")}"
      Lich.log "error: #{$!}\n\t#{$!.backtrace.join("\n\t")}"
    end
  end
  File.open(filename, 'wb:UTF-8') { |file|
    file.write(Map.to_json)
  }
  respond "#{filename} saved"
end

.save_xml(filename = "#{DATA_DIR}/#{XMLData.game}/map-#{Time.now.to_i}.xml") ⇒ Boolean

Saves the current map data to an XML file.

Parameters:

  • filename (String) (defaults to: "#{DATA_DIR}/#{XMLData.game}/map-#{Time.now.to_i}.xml")

    The filename to save to.

Returns:

  • (Boolean)

    True if the save operation was successful.



701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
# File 'documented/common/map/map_dr.rb', line 701

def Map.save_xml(filename = "#{DATA_DIR}/#{XMLData.game}/map-#{Time.now.to_i}.xml")
  if File.exist?(filename)
    respond "File exists!  Backing it up before proceeding..."
    begin
      File.open(filename, 'rb') { |infile|
        File.open("#{filename}.bak", "wb") { |outfile|
          outfile.write(infile.read)
        }
      }
    rescue
      respond "--- Lich: error: #{$!}\n\t#{$!.backtrace[0..1].join("\n\t")}"
      Lich.log "error: #{$!}\n\t#{$!.backtrace.join("\n\t")}"
    end
  end
  begin
    escape = { '<' => '&lt;', '>' => '&gt;', '"' => '&quot;', "'" => "&apos;", '&' => '&amp;' }
    File.open(filename, 'w') { |file|
      file.write "<map>\n"
      @@list.each { |room|
        next if room == nil
        if room.location
          location = " location=#{(room.location.gsub(/(<|>|"|'|&)/) { escape[$1] }).inspect}"
        else
          location = ''
        end
        if room.climate
          climate = " climate=#{(room.climate.gsub(/(<|>|"|'|&)/) { escape[$1] }).inspect}"
        else
          climate = ''
        end
        if room.terrain
          terrain = " terrain=#{(room.terrain.gsub(/(<|>|"|'|&)/) { escape[$1] }).inspect}"
        else
          terrain = ''
        end
        file.write "   <room id=\"#{room.id}\"#{location}#{climate}#{terrain}>\n"
        room.title.each { |title| file.write "      <title>#{title.gsub(/(<|>|"|'|&)/) { escape[$1] }}</title>\n" }
        room.description.each { |desc| file.write "      <description>#{desc.gsub(/(<|>|"|'|&)/) { escape[$1] }}</description>\n" }
        room.paths.each { |paths| file.write "      <paths>#{paths.gsub(/(<|>|"|'|&)/) { escape[$1] }}</paths>\n" }
        room.tags.each { |tag| file.write "      <tag>#{tag.gsub(/(<|>|"|'|&)/) { escape[$1] }}</tag>\n" }
        room.uid.each { |u| file.write "      <uid>#{u}</uid>\n" }
        room.unique_loot.to_a.each { |loot| file.write "      <unique_loot>#{loot.gsub(/(<|>|"|'|&)/) { escape[$1] }}</unique_loot>\n" }
        room.room_objects.to_a.each { |loot| file.write "      <room_objects>#{loot.gsub(/(<|>|"|'|&)/) { escape[$1] }}</room_objects>\n" }
        file.write "      <image name=\"#{room.image.gsub(/(<|>|"|'|&)/) { escape[$1] }}\" coords=\"#{room.image_coords.join(',')}\" />\n" if room.image and room.image_coords
        room.wayto.keys.each { |target|
          if room.timeto[target].is_a?(StringProc)
            cost = " cost=\"#{room.timeto[target]._dump.gsub(/(<|>|"|'|&)/) { escape[$1] }}\""
          elsif room.timeto[target]
            cost = " cost=\"#{room.timeto[target]}\""
          else
            cost = ''
          end
          if room.wayto[target].is_a?(StringProc)
            file.write "      <exit target=\"#{target}\" type=\"Proc\"#{cost}>#{room.wayto[target]._dump.gsub(/(<|>|"|'|&)/) { escape[$1] }}</exit>\n"
          else
            file.write "      <exit target=\"#{target}\" type=\"#{room.wayto[target].class}\"#{cost}>#{room.wayto[target].gsub(/(<|>|"|'|&)/) { escape[$1] }}</exit>\n"
          end
        }
        file.write "   </room>\n"
      }
      file.write "</map>\n"
    }
    @@tags.clear
    respond "--- map database saved to: #{filename}"
  rescue
    respond $!
  end
  GC.start
end

.set_current(id) ⇒ Map?

Sets the current room based on the given ID.

Parameters:

  • id (Integer)

    The ID of the room to set as current.

Returns:

  • (Map, nil)

    The room if found, nil otherwise.



304
305
306
307
308
309
# File 'documented/common/map/map_dr.rb', line 304

def Map.set_current(id) # returns Map/Room
  @@previous_room_id = @@current_room_id if id != @@current_room_id;
  @@current_room_id  = id
  return nil if id.nil?
  return @@list[id]
end

.set_fuzzy(id) ⇒ Map?

Sets the fuzzy room based on the given ID.

Parameters:

  • id (Integer)

    The ID of the room to set as fuzzy.

Returns:

  • (Map, nil)

    The room if found, nil otherwise.



139
140
141
142
143
144
# File 'documented/common/map/map_dr.rb', line 139

def Map.set_fuzzy(id) # returns Map/Room
  @@previous_room_id = @@current_room_id if !id.nil? and id != @@current_room_id;
  @@current_room_id  = id
  return nil if id.nil?
  return @@list[id]
end

.tagsArray<String>

Gets the unique tags from all rooms.

Returns:

  • (Array<String>)

    An array of unique tags.



322
323
324
325
326
327
328
329
330
331
332
# File 'documented/common/map/map_dr.rb', line 322

def Map.tags
  Map.load unless @@loaded
  if @@tags.empty?
    @@list.each { |r|
      r.tags.each { |t|
        @@tags.push(t) unless @@tags.include?(t)
      }
    }
  end
  @@tags.dup
end

.to_json(*args) ⇒ String

Converts the map data to JSON format.

Parameters:

  • args (Array)

    Additional arguments for JSON generation.

Returns:

  • (String)

    The JSON representation of the map.



649
650
651
652
# File 'documented/common/map/map_dr.rb', line 649

def Map.to_json(*args)
  @@list.delete_if { |r| r.nil? }
  @@list.to_json(args)
end

.uidsHash<Integer, Array<Integer>>

Gets the unique IDs mapping.

Returns:

  • (Hash<Integer, Array<Integer>>)

    A hash mapping UIDs to room IDs.



486
# File 'documented/common/map/map_gs.rb', line 486

def Map.uids(); return @@uids; end

.uids_add(uid, id) ⇒ Object

Adds a room ID to the UID mapping.

Parameters:

  • uid (Integer)

    The UID to associate with a room ID.

  • id (Integer)

    The room ID to associate with the UID.



293
294
295
296
297
298
299
# File 'documented/common/map/map_dr.rb', line 293

def Map.uids_add(uid, id)
  if !@@uids.key?(uid)
    @@uids[uid] = [id]
  else
    @@uids[uid] << id if !@@uids[uid].include?(id)
  end
end

.uids_clearObject



487
# File 'documented/common/map/map_gs.rb', line 487

def Map.uids_clear(); @@uids.clear; end

Instance Method Details

#descObject



1015
1016
1017
# File 'documented/common/map/map_dr.rb', line 1015

def desc
  @description
end

#dijkstra(destination = nil) ⇒ Object



867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
# File 'documented/common/map/map_dr.rb', line 867

def dijkstra(destination = nil)
  begin
    Map.load unless @@loaded
    source = @id
    visited = {}
    shortest_distances_hash = {}
    previous_hash = {}

    pq = MinHeap.new
    pq.push(0, source)
    shortest_distances_hash[source] = 0

    # Early termination check
    check_destination = proc { |v, dist|
      case destination
      when Integer
        v == destination
      when Array
        destination.include?(v) && dist < 20
      else
        false
      end
    }

    until pq.empty?
      current_dist, v = pq.pop

      next if visited[v]
      break if check_destination.call(v, current_dist)

      visited[v] = true

      @@list[v].wayto.keys.each do |adj_room|
        adj_room_i = adj_room.to_i
        next if visited[adj_room_i]

        edge_weight = if @@list[v].timeto[adj_room].is_a?(StringProc)
                        @@list[v].timeto[adj_room].call
                      else
                        @@list[v].timeto[adj_room]
                      end

        next unless edge_weight

        new_distance = current_dist + edge_weight

        if !shortest_distances_hash[adj_room_i] || shortest_distances_hash[adj_room_i] > new_distance
          shortest_distances_hash[adj_room_i] = new_distance
          previous_hash[adj_room_i] = v
          pq.push(new_distance, adj_room_i)
        end
      end
    end

    # Convert hashes back to arrays for backward compatibility
    max_room_id = [previous_hash.keys.max, shortest_distances_hash.keys.max].compact.max || 0
    previous = Array.new(max_room_id + 1)
    shortest_distances = Array.new(max_room_id + 1)

    previous_hash.each { |key, value| previous[key] = value }
    shortest_distances_hash.each { |key, value| shortest_distances[key] = value }

    return previous, shortest_distances
  rescue => e
    echo "Map.dijkstra: error: #{e}"
    respond e.backtrace
    nil
  end
end

#find_all_nearest_by_tag(tag_name) ⇒ Array<Integer>

Finds all nearest rooms with a specific tag.

Parameters:

  • tag_name (String)

    The tag to search for.

Returns:

  • (Array<Integer>)

    An array of IDs of the nearest rooms with the tag.



985
986
987
988
989
990
991
# File 'documented/common/map/map_dr.rb', line 985

def find_all_nearest_by_tag(tag_name)
  target_list = Array.new
  @@list.each { |room| target_list.push(room.id) if room.tags.include?(tag_name) }
  _, shortest_distances = Map.dijkstra(@id)
  target_list.delete_if { |room_num| shortest_distances[room_num].nil? }
  target_list.sort { |a, b| shortest_distances[a] <=> shortest_distances[b] }
end

#find_nearest(target_list) ⇒ Integer

Finds the nearest room from a list of target rooms.

Parameters:

  • target_list (Array<Integer>)

    The list of target room IDs.

Returns:

  • (Integer)

    The ID of the nearest room.



996
997
998
999
1000
1001
1002
1003
1004
1005
# File 'documented/common/map/map_dr.rb', line 996

def find_nearest(target_list)
  target_list = target_list.collect { |num| num.to_i }
  if target_list.include?(@id)
    @id
  else
    _previous, shortest_distances = Map.dijkstra(@id, target_list)
    valid_rooms = target_list.select { |room_num| shortest_distances[room_num].is_a?(Numeric) }
    return valid_rooms.min_by { |room_num| shortest_distances[room_num] }
  end
end

#find_nearest_by_tag(tag_name) ⇒ Integer

Finds the nearest room with a specific tag.

Parameters:

  • tag_name (String)

    The tag to search for.

Returns:

  • (Integer)

    The ID of the nearest room with the tag.



970
971
972
973
974
975
976
977
978
979
980
# File 'documented/common/map/map_dr.rb', line 970

def find_nearest_by_tag(tag_name)
  target_list = Array.new
  @@list.each { |room| target_list.push(room.id) if room.tags.include?(tag_name) }
  _, shortest_distances = Map.dijkstra(@id, target_list)
  if target_list.include?(@id)
    @id
  else
    target_list.delete_if { |room_num| shortest_distances[room_num].nil? }
    target_list.sort { |a, b| shortest_distances[a] <=> shortest_distances[b] }.first
  end
end

#fuzzy_room_idInteger

Gets the fuzzy room ID.

Returns:

  • (Integer)

    The fuzzy room ID.



67
# File 'documented/common/map/map_gs.rb', line 67

def fuzzy_room_id; return @@current_room_id; end

#geoObject



1047
1048
1049
# File 'documented/common/map/map_dr.rb', line 1047

def geo
  nil
end

#inspectString

Inspects the room object.

Returns:

  • (String)

    A string containing the instance variables and their values.



83
84
85
# File 'documented/common/map/map_gs.rb', line 83

def inspect
  self.instance_variables.collect { |var| var.to_s + "=" + self.instance_variable_get(var).inspect }.join("\n")
end

#map_nameObject



1019
1020
1021
# File 'documented/common/map/map_dr.rb', line 1019

def map_name
  @image
end

#map_roomsizeObject



1039
1040
1041
1042
1043
1044
1045
# File 'documented/common/map/map_dr.rb', line 1039

def map_roomsize
  if @image_coords.nil?
    nil
  else
    image_coords[2] - image_coords[0]
  end
end

#map_xObject



1023
1024
1025
1026
1027
1028
1029
# File 'documented/common/map/map_dr.rb', line 1023

def map_x
  if @image_coords.nil?
    nil
  else
    ((image_coords[0] + image_coords[2]) / 2.0).round
  end
end

#map_yObject



1031
1032
1033
1034
1035
1036
1037
# File 'documented/common/map/map_dr.rb', line 1031

def map_y
  if @image_coords.nil?
    nil
  else
    ((image_coords[1] + image_coords[3]) / 2.0).round
  end
end

#outside?Boolean

Checks if the room is outside.

Returns:

  • (Boolean)

    True if the room is outside, false otherwise.



70
# File 'documented/common/map/map_gs.rb', line 70

def outside?; return @paths.last =~ /^Obvious paths:/ ? true : false; end

#path_to(destination) ⇒ Array<Integer>?

Finds the path to a destination room.

Parameters:

  • destination (Integer)

    The destination room ID.

Returns:

  • (Array<Integer>, nil)

    The path as an array of room IDs or nil if not found.



955
956
957
958
959
960
961
962
963
964
965
# File 'documented/common/map/map_dr.rb', line 955

def path_to(destination)
  Map.load unless @@loaded
  destination = destination.to_i
  previous, _ = dijkstra(destination)
  return nil unless previous[destination]
  path = [destination]
  path.push(previous[path[-1]]) until previous[path[-1]] == @id
  path.reverse!
  path.pop
  return path
end

#to_iInteger

Converts the room to an integer ID.

Returns:

  • (Integer)

    The ID of the room.



52
53
54
# File 'documented/common/map/map_dr.rb', line 52

def to_i
  @id
end

#to_json(*_args) ⇒ String

Converts the room data to JSON format.

Parameters:

  • args (Array)

    Additional arguments for JSON generation.

Returns:

  • (String)

    The JSON representation of the room.



816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
# File 'documented/common/map/map_gs.rb', line 816

def to_json(*_args)
  mapjson = ({
    :id             => @id,
    :title          => @title,
    :description    => @description,
    :paths          => @paths,
    :location       => @location,
    :climate        => @climate,
    :terrain        => @terrain,
    :wayto          => @wayto,
    :timeto         => @timeto,
    :image          => @image,
    :image_coords   => @image_coords,
    :tags           => @tags,
    :check_location => @check_location,
    :unique_loot    => @unique_loot,
    :uid            => @uid,
  }).delete_if { |_a, b| b.nil? or (b.is_a?(Array) and b.empty?) };
  JSON.pretty_generate(mapjson);
end

#to_sString

Converts the room to a string representation.

Returns:

  • (String)

    A string representation of the room.



58
59
60
# File 'documented/common/map/map_dr.rb', line 58

def to_s
  "##{@id} (#{@uid[-1]}):\n#{@title[-1]}\n#{@description[-1]}\n#{@paths[-1]}"
end