Class: Lich::Common::Map

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

Overview

Deprecated class for Map with various methods.

Direct Known Subclasses

Room

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 instance of the Map class.

Parameters:

  • id (Integer)

    The unique identifier for the map.

  • title (Array<String>)

    The titles associated with the map.

  • description (Array<String>)

    The descriptions associated with the map.

  • paths (Array<String>)

    The paths available in the map.

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

    The unique identifiers for the user (default: empty array).

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

    The location of the map (default: nil).

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

    The climate of the map (default: nil).

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

    The terrain of the map (default: nil).

  • wayto (Hash) (defaults to: {})

    The ways to navigate the map (default: empty hash).

  • timeto (Hash) (defaults to: {})

    The time taken to navigate the map (default: empty hash).

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

    The image associated with the map (default: nil).

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

    The coordinates of the image (default: nil).

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

    The tags associated with the map (default: empty array).

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

    The location to check (default: nil).

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

    The unique loot associated with the map (default: nil).



43
44
45
46
# File 'lib/common/map/map_dr.rb', line 43

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.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def check_location
  @check_location
end

#climateObject

Returns the value of attribute climate.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def climate
  @climate
end

#descriptionObject

Returns the value of attribute description.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def description
  @description
end

#idObject (readonly)

Returns the value of attribute id.



20
21
22
# File 'lib/common/map/map_dr.rb', line 20

def id
  @id
end

#imageObject

Returns the value of attribute image.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def image
  @image
end

#image_coordsObject

Returns the value of attribute image_coords.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def image_coords
  @image_coords
end

#locationObject

Returns the value of attribute location.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def location
  @location
end

#pathsObject

Returns the value of attribute paths.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def paths
  @paths
end

#room_objectsObject

Returns the value of attribute room_objects.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def room_objects
  @room_objects
end

#tagsObject

Returns the value of attribute tags.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def tags
  @tags
end

#terrainObject

Returns the value of attribute terrain.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def terrain
  @terrain
end

#timetoObject

Returns the value of attribute timeto.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def timeto
  @timeto
end

#titleObject

Returns the value of attribute title.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def title
  @title
end

#uidObject

Returns the value of attribute uid.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def uid
  @uid
end

#unique_lootObject

Returns the value of attribute unique_loot.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def unique_loot
  @unique_loot
end

#waytoObject

Returns the value of attribute wayto.



21
22
23
# File 'lib/common/map/map_dr.rb', line 21

def wayto
  @wayto
end

Class Method Details

.[](val) ⇒ Map?

Retrieves a map by its ID or title.

Parameters:

  • val (Integer, String)

    The ID or title of the map to retrieve.

Returns:

  • (Map, nil)

    The map if found, nil otherwise.



102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/common/map/map_dr.rb', line 102

def Map.[](val)
  Map.load unless @@loaded
  if (val.class == 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 all data from the map, including lists and tags.

Returns:

  • (Boolean)

    Returns true after clearing the data.



403
404
405
406
407
408
409
410
411
# File 'lib/common/map/map_dr.rb', line 403

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

.currentMap?

Retrieves the current map based on the context.

Returns:

  • (Map, nil)

    The current map if found, nil otherwise.



137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/common/map/map_dr.rb', line 137

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, ...

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

Examples:

current_room = Map.current_or_new
puts current_room.id if current_room

Returns:

  • (Map, Room, nil)

    the current room or a new room if created, or nil if no script is current.

Raises:

  • (StandardError)

    raises an error if the room cannot be loaded.



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
# File 'lib/common/map/map_dr.rb', line 295

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

Retrieves the current room ID.

Returns:

  • (Integer)

    The current room ID.



51
# File 'lib/common/map/map_gs.rb', line 51

def Map.current_room_id; return @@current_room_id; end

.current_room_id=(id) ⇒ Integer

Sets the current room ID.

Parameters:

  • id (Integer)

    The new current room ID.

Returns:

  • (Integer)

    The updated current room ID.



57
# File 'lib/common/map/map_gs.rb', line 57

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

.dijkstra(source, destination = nil) ⇒ Array?

Finds the shortest path between rooms using Dijkstra’s algorithm.

Examples:

path, distances = Map.dijkstra("room1", "room2")

Parameters:

  • source (Map, String, Integer)

    the source room or its identifier.

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

    the destination room identifier (optional).

Returns:

  • (Array, nil)

    an array containing the previous rooms and shortest distances, or nil on error.



885
886
887
888
889
890
891
892
893
894
# File 'lib/common/map/map_dr.rb', line 885

def Map.dijkstra(source, destination = nil)
  if source.class == 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 required to traverse a sequence of rooms.

Examples:

time = Map.estimate_time([1, 2, 3])

Parameters:

  • array (Array)

    an array of room identifiers to traverse.

Returns:

  • (Float)

    the estimated time to traverse the rooms.

Raises:

  • (Exception)

    if the input is not an array.



857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
# File 'lib/common/map/map_dr.rb', line 857

def Map.estimate_time(array)
  Map.load unless @@loaded
  unless array.class == 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.class == Proc
        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 to the destination.

Examples:

path = Map.findpath("Room1", 5)

Parameters:

  • source (Map, String)

    The source room or its identifier.

  • destination (Integer)

    The destination room identifier.

Returns:

  • (Array<Integer>, nil)

    The path as an array of room identifiers or nil if no path exists.

Raises:

  • (StandardError)

    If the source is invalid.



1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
# File 'lib/common/map/map_dr.rb', line 1009

def Map.findpath(source, destination)
  if source.class == 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

Retrieves the fuzzy room ID.

Returns:

  • (Integer)

    The fuzzy room ID.



107
# File 'lib/common/map/map_gs.rb', line 107

def Map.fuzzy_room_id; return @@fuzzy_room_id; end

.get_free_idInteger

Gets a free ID for a new map.

Returns:

  • (Integer)

    A new unique ID for the map.



76
77
78
79
# File 'lib/common/map/map_dr.rb', line 76

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 map’s context.

Returns:

  • (String, false, nil)

    The current location as a string, false if unable to determine, or nil if no script is running.



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/common/map/map_gs.rb', line 146

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

Retrieves the identifiers associated with a given unique identifier (UID).

Parameters:

  • n (String)

    The unique identifier for which to retrieve associated IDs.

Returns:

  • (Array)

    An array of IDs associated with the given UID, or an empty array if none exist.



396
397
398
# File 'lib/common/map/map_dr.rb', line 396

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

.imagesArray<String>

Note:

This method loads the map data if it hasn’t been loaded yet.

Retrieves a list of unique images from the map.

Examples:

images = Map.images
puts images.inspect

Returns:

  • (Array<String>)

    an array of unique images.



520
521
522
523
524
# File 'lib/common/map/map_gs.rb', line 520

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>

Retrieves the list of all maps.

Returns:

  • (Array<Map>)

    The list of maps.



88
89
90
91
# File 'lib/common/map/map_dr.rb', line 88

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

.load(filename = nil) ⇒ Boolean

Loads map data from files, either from a specified filename or from the default directory.

Examples:

Map.load("path/to/map.json")

Parameters:

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

    The name of the file to load. If nil, defaults to loading all map files.

Returns:

  • (Boolean)

    Returns true if loading was successful, false otherwise.



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
# File 'lib/common/map/map_dr.rb', line 428

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.

Examples:

Map.load_dat("path/to/map.dat")

Parameters:

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

    The name of the DAT file to load. If nil, defaults to loading all DAT map files.

Returns:

  • (Boolean)

    Returns true if loading was successful, false otherwise.



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
# File 'lib/common/map/map_dr.rb', line 514

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.

Examples:

Map.load_json("path/to/map.json")

Parameters:

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

    The name of the JSON file to load. If nil, defaults to loading all JSON map files.

Returns:

  • (Boolean)

    Returns true if loading was successful, false otherwise.



460
461
462
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
498
499
500
501
502
503
504
505
506
507
508
# File 'lib/common/map/map_dr.rb', line 460

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].class == 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_uidsvoid

Note:

This method will call ‘Map.load` if the map is not already loaded.

This method returns an undefined value.

Loads unique identifiers (UIDs) from the map data.



379
380
381
382
383
384
385
386
387
388
389
390
391
# File 'lib/common/map/map_dr.rb', line 379

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.

Examples:

Map.load_xml("path/to/map.xml")

Parameters:

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

    The name of the XML file to load. Defaults to “#DATA_DIR/#XMLData.game/map.xml”.

Returns:

  • (Boolean)

    Returns true if loading was successful, false otherwise.

Raises:

  • (Exception)

    Raises an exception if the specified file does not exist.



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
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
# File 'lib/common/map/map_dr.rb', line 557

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 has been loaded.

Returns:

  • (Boolean)

    True if the map is loaded, false otherwise.



62
# File 'lib/common/map/map_gs.rb', line 62

def Map.loaded; return @@loaded; end

.locationsArray<String>

Note:

This method loads the map data if it hasn’t been loaded yet.

Retrieves a list of unique locations from the map.

Examples:

locations = Map.locations
puts locations.inspect

Returns:

  • (Array<String>)

    an array of unique locations.



507
508
509
510
511
# File 'lib/common/map/map_gs.rb', line 507

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 map based on the provided script.

Parameters:

  • script (Script)

    The current script context.

Returns:

  • (Integer)

    The ID of the matched map.



180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
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
# File 'lib/common/map/map_dr.rb', line 180

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?

Note:

This method uses a mutex to synchronize access to shared resources.

Matches a room based on fuzzy criteria such as title, description, and exits.

Examples:

room_id = Map.match_fuzzy
puts room_id if room_id

Returns:

  • (Integer, nil)

    the ID of the matched room or nil if no match is found.



236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
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
# File 'lib/common/map/map_dr.rb', line 236

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 IDs to find a valid one.

Parameters:

  • ids (Array<Integer>)

    The list of IDs to match.

Returns:

  • (Integer, nil)

    The matched ID if found, nil otherwise.



355
356
357
358
359
# File 'lib/common/map/map_dr.rb', line 355

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 map without a unique identifier.

Returns:

  • (Map, nil)

    The matched map if found, nil otherwise.



155
156
157
158
159
160
161
# File 'lib/common/map/map_dr.rb', line 155

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?

Retrieves the previous map based on the previous room ID.

Returns:

  • (Map, nil)

    The previous map if it exists, nil otherwise.



119
120
121
# File 'lib/common/map/map_dr.rb', line 119

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

.previous_room_idInteger?

Retrieves the previous room ID.

Returns:

  • (Integer, nil)

    The previous room ID or nil if not set.



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

def Map.previous_room_id; return @@previous_room_id; end

.previous_room_id=(id) ⇒ Integer

Sets the previous room ID.

Parameters:

  • id (Integer)

    The new previous room ID.

Returns:

  • (Integer)

    The updated previous room ID.



73
# File 'lib/common/map/map_gs.rb', line 73

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

.previous_uidInteger?

Retrieves the previous unique identifier.

Returns:

  • (Integer, nil)

    The previous unique identifier or nil if not set.



126
127
128
# File 'lib/common/map/map_dr.rb', line 126

def Map.previous_uid
  return XMLData.previous_nav_rm
end

.reloadvoid

This method returns an undefined value.

Reloads the map by clearing existing data and loading it again.



416
417
418
419
# File 'lib/common/map/map_dr.rb', line 416

def Map.reload
  Map.clear
  Map.load
end

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

This method returns an undefined value.

Saves the current map data to a file.

Examples:

Map.save("my_map.dat")

Parameters:

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

    the name of the file to save the map data to. Defaults to “#DATA_DIR/#XMLData.game/map-#Time.now.to_i.dat”.

Raises:

  • (StandardError)

    if there is an error during file operations.



682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
# File 'lib/common/map/map_dr.rb', line 682

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") ⇒ void

This method returns an undefined value.

Saves the current map data in JSON format to a file.

Examples:

Map.save_json("my_map.json")

Parameters:

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

    the name of the file to save the JSON data to. Defaults to “#DATA_DIR/#XMLData.game/map-#Time.now.to_i.json”.

Raises:

  • (StandardError)

    if there is an error during file operations.



750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
# File 'lib/common/map/map_dr.rb', line 750

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") ⇒ void

This method returns an undefined value.

Saves the current map data in XML format to a file.

Examples:

Map.save_xml("my_map.xml")

Parameters:

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

    the name of the file to save the XML data to. Defaults to “#DATA_DIR/#XMLData.game/map-#Time.now.to_i.xml”.

Raises:

  • (StandardError)

    if there is an error during file operations.



780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
# File 'lib/common/map/map_dr.rb', line 780

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].class == Proc
            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].class == Proc
            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 map based on the provided ID.

Parameters:

  • id (Integer)

    The ID of the map to set as current.

Returns:

  • (Map, nil)

    The newly set current map or nil if the ID is nil.



344
345
346
347
348
349
# File 'lib/common/map/map_dr.rb', line 344

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 a fuzzy current map based on the provided ID.

Parameters:

  • id (Integer)

    The ID of the map to set as fuzzy current.

Returns:

  • (Map, nil)

    The newly set fuzzy current map or nil if the ID is nil.



168
169
170
171
172
173
# File 'lib/common/map/map_dr.rb', line 168

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>

Note:

This method loads the map data if it hasn’t been loaded yet.

Retrieves a list of unique tags from the map.

Examples:

tags = Map.tags
puts tags.inspect

Returns:

  • (Array<String>)

    an array of unique tags.



364
365
366
367
368
369
370
371
372
373
374
# File 'lib/common/map/map_dr.rb', line 364

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.

Examples:

json_data = Map.to_json

Parameters:

  • args (Array)

    optional arguments for JSON generation.

Returns:

  • (String)

    the JSON representation of the map data.



711
712
713
714
# File 'lib/common/map/map_dr.rb', line 711

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

.uidsHash

Retrieves the unique identifiers (UIDs) stored in the map.

Returns:

  • (Hash)

    A hash containing the unique identifiers.



542
# File 'lib/common/map/map_gs.rb', line 542

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

.uids_add(uid, id) ⇒ void

Note:

If the UID already exists, the ID will only be added if it is not already present.

This method returns an undefined value.

Adds a new identifier to the list of identifiers associated with a given unique identifier (UID).

Parameters:

  • uid (String)

    The unique identifier to which the ID will be added.

  • id (String)

    The identifier to be added.



332
333
334
335
336
337
338
# File 'lib/common/map/map_dr.rb', line 332

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_clearvoid

This method returns an undefined value.

Clears all unique identifiers (UIDs) from the map.



547
# File 'lib/common/map/map_gs.rb', line 547

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

Instance Method Details

#descString

Returns the description of the map.

Examples:

description = map.desc

Returns:

  • (String)

    The description of the map.



1108
1109
1110
# File 'lib/common/map/map_dr.rb', line 1108

def desc
  @description
end

#dijkstra(destination = nil) ⇒ Array?

Finds the shortest path from the current room to a destination using Dijkstra’s algorithm.

Examples:

previous, distances = room_instance.dijkstra("room2")

Parameters:

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

    the destination room identifier or identifiers.

Returns:

  • (Array, nil)

    an array containing the previous rooms and shortest distances, or nil on error.



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
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# File 'lib/common/map/map_dr.rb', line 902

def dijkstra(destination = nil)
  begin
    Map.load unless @@loaded
    source = @id
    visited = Array.new
    shortest_distances = Array.new
    previous = Array.new
    pq = [source]
    pq_push = proc { |val|
      for i in 0...pq.size
        if shortest_distances[val] <= shortest_distances[pq[i]]
          pq.insert(i, val)
          break
        end
      end
      pq.push(val) if i.nil? or (i == pq.size - 1)
    }
    visited[source] = true
    shortest_distances[source] = 0
    if destination.nil?
      until pq.size == 0
        v = pq.shift
        visited[v] = true
        @@list[v].wayto.keys.each { |adj_room|
          adj_room_i = adj_room.to_i
          unless visited[adj_room_i]
            if @@list[v].timeto[adj_room].class == Proc
              nd = @@list[v].timeto[adj_room].call
            else
              nd = @@list[v].timeto[adj_room]
            end
            if nd
              nd += shortest_distances[v]
              if shortest_distances[adj_room_i].nil? or (shortest_distances[adj_room_i] > nd)
                shortest_distances[adj_room_i] = nd
                previous[adj_room_i] = v
                pq_push.call(adj_room_i)
              end
            end
          end
        }
      end
    elsif destination.class == Integer
      until pq.size == 0
        v = pq.shift
        break if v == destination
        visited[v] = true
        @@list[v].wayto.keys.each { |adj_room|
          adj_room_i = adj_room.to_i
          unless visited[adj_room_i]
            if @@list[v].timeto[adj_room].class == Proc
              nd = @@list[v].timeto[adj_room].call
            else
              nd = @@list[v].timeto[adj_room]
            end
            if nd
              nd += shortest_distances[v]
              if shortest_distances[adj_room_i].nil? or (shortest_distances[adj_room_i] > nd)
                shortest_distances[adj_room_i] = nd
                previous[adj_room_i] = v
                pq_push.call(adj_room_i)
              end
            end
          end
        }
      end
    elsif destination.class == Array
      dest_list = destination.collect { |dest| dest.to_i }
      until pq.size == 0
        v = pq.shift
        break if dest_list.include?(v) and (shortest_distances[v] < 20)
        visited[v] = true
        @@list[v].wayto.keys.each { |adj_room|
          adj_room_i = adj_room.to_i
          unless visited[adj_room_i]
            if @@list[v].timeto[adj_room].class == Proc
              nd = @@list[v].timeto[adj_room].call
            else
              nd = @@list[v].timeto[adj_room]
            end
            if nd
              nd += shortest_distances[v]
              if shortest_distances[adj_room_i].nil? or (shortest_distances[adj_room_i] > nd)
                shortest_distances[adj_room_i] = nd
                previous[adj_room_i] = v
                pq_push.call(adj_room_i)
              end
            end
          end
        }
      end
    end
    return previous, shortest_distances
  rescue
    echo "Map.dijkstra: error: #{$!}"
    respond $!.backtrace
    nil
  end
end

#find_all_nearest_by_tag(tag_name) ⇒ Array<Integer>

Finds all nearest rooms by the specified tag name.

Examples:

nearest_rooms = room.find_all_nearest_by_tag("bathroom")

Parameters:

  • tag_name (String)

    The tag name to search for.

Returns:

  • (Array<Integer>)

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



1062
1063
1064
1065
1066
1067
1068
# File 'lib/common/map/map_dr.rb', line 1062

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 given list of target rooms.

Examples:

nearest_room_id = room.find_nearest([1, 2, 3])

Parameters:

  • target_list (Array<Integer>)

    An array of room identifiers to search from.

Returns:

  • (Integer, nil)

    The identifier of the nearest room or nil if none found.



1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
# File 'lib/common/map/map_dr.rb', line 1076

def find_nearest(target_list)
  target_list = target_list.collect { |num| num.to_i }
  if target_list.include?(@id)
    @id
  else
    _, shortest_distances = Map.dijkstra(@id, target_list)
    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

#find_nearest_by_tag(tag_name) ⇒ Integer?

Finds the nearest room by the specified tag name.

Examples:

nearest_room_id = room.find_nearest_by_tag("kitchen")

Parameters:

  • tag_name (String)

    The tag name to search for.

Returns:

  • (Integer, nil)

    The identifier of the nearest room with the tag or nil if none found.



1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
# File 'lib/common/map/map_dr.rb', line 1044

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

Retrieves the fuzzy room ID.

Returns:

  • (Integer)

    The fuzzy room ID.



78
# File 'lib/common/map/map_gs.rb', line 78

def fuzzy_room_id; return @@current_room_id; end

#geonil

Returns nil as a placeholder for geographical data.

Examples:

geo_data = map.geo

Returns:

  • (nil)

    Always returns nil.



1165
1166
1167
# File 'lib/common/map/map_dr.rb', line 1165

def geo
  nil
end

#inspectString

Inspects the map instance variables.

Returns:

  • (String)

    A string representation of the instance variables and their values.



65
66
67
# File 'lib/common/map/map_dr.rb', line 65

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

#map_nameString

Returns the name of the map.

Examples:

name = map.map_name

Returns:

  • (String)

    The name of the map.



1117
1118
1119
# File 'lib/common/map/map_dr.rb', line 1117

def map_name
  @image
end

#map_roomsizeInteger?

Returns the size of the room in the map.

Examples:

room_size = map.map_roomsize

Returns:

  • (Integer, nil)

    The size of the room or nil if image_coords is not set.



1152
1153
1154
1155
1156
1157
1158
# File 'lib/common/map/map_dr.rb', line 1152

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

#map_xInteger?

Returns the x-coordinate of the map’s center.

Examples:

x_coord = map.map_x

Returns:

  • (Integer, nil)

    The x-coordinate or nil if image_coords is not set.



1126
1127
1128
1129
1130
1131
1132
# File 'lib/common/map/map_dr.rb', line 1126

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

#map_yInteger?

Returns the y-coordinate of the map’s center.

Examples:

y_coord = map.map_y

Returns:

  • (Integer, nil)

    The y-coordinate or nil if image_coords is not set.



1139
1140
1141
1142
1143
1144
1145
# File 'lib/common/map/map_dr.rb', line 1139

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 current map is outside.

Returns:

  • (Boolean)

    True if the map is outside, false otherwise.



83
# File 'lib/common/map/map_gs.rb', line 83

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

#path_to(destination) ⇒ Array<Integer>?

Note:

This method loads the map data if it hasn’t been loaded yet.

Calculates the path to the specified destination using Dijkstra’s algorithm.

Examples:

path = room.path_to(3)

Parameters:

  • destination (Integer)

    The destination room identifier.

Returns:

  • (Array<Integer>, nil)

    The path as an array of room identifiers or nil if no path exists.



1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
# File 'lib/common/map/map_dr.rb', line 1026

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 map ID to an integer.

Returns:

  • (Integer)

    The map ID as an integer.



51
52
53
# File 'lib/common/map/map_dr.rb', line 51

def to_i
  @id
end

#to_json(*_args) ⇒ String

Converts the current instance of the map to JSON format.

Examples:

map_instance.to_json

Parameters:

  • _args (Array)

    optional arguments for JSON generation.

Returns:

  • (String)

    the JSON representation of the map instance.



722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
# File 'lib/common/map/map_dr.rb', line 722

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.class == Array and b.empty?) };
  JSON.pretty_generate(mapjson);
end

#to_sString

Returns a string representation of the map.

Returns:

  • (String)

    A formatted string containing the map’s details.



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

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