• Just a reminder that providing specifics on, sharing links to, or naming websites where ROMs can be accessed is against the rules. If your post has any of this information it will be removed.
  • Ever thought it'd be cool to have your art, writing, or challenge runs featured on PokéCommunity? Click here for info - we'd love to spotlight your work!
  • Dawn, Gloria, Juliana, or Summer - which Pokémon protagonist is your favorite? Let us know by voting in our poll!
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

sort array of map ids based on map name

  • 752
    Posts
    14
    Years
    • UK
    • Seen Dec 29, 2024
    I don't know if its possible but I want to load into an array the ids of maps the have encounters on them, sort them by their map name (so that routes and towns are together) and then display them as a selectable list.

    So far i have it loading the maps into an array, and displaying them selectable on screen. I don't know / cant work out how to sort them maps by their map name

    This is what i have so far

    Code:
    BASECOLOR=Color.new(255,255,255)
    SHADOWCOLOR=Color.new(0,0,0)
    
    class Window_PokemonMapEncounters < Window_DrawableCommand
      def initialize(encounters,total,x,y,width,height,viewport=nil)
        @total = total
        @encounters = encounters
        super(x,y,width,height,viewport)
        @selarrow=AnimatedBitmap.new("Graphics/Pictures/mapSel")
        self.windowskin=nil
      end
      
      def getMapId(i)
        item=@total[i]
      end
    
      def itemCount
        return @stock.length+1
      end
    
      def item
        return self.index>[email protected] ? 0 : @total[self.index]
      end
    
      def drawItem(index,count,rect)
        textpos=[]
        rect=drawCursor(index,rect)
        ypos=rect.y
        item=@total[index]
        if index==count-1
          textpos.push([_INTL("CANCEL"),rect.x,ypos+2,false,
             SHADOWCOLOR,BASECOLOR])
        else
          textpos.push([pbGetMapNameFromId(item),rect.x,ypos+2,false,
          BASECOLOR,SHADOWCOLOR])
        end
        pbDrawTextPositions(self.contents,textpos)
      end
    end
    
    class PokemonMapEncountersScene
      def update
        pbUpdateSpriteHash(@sprites)
      end
    
      def pbStartScene
        @total=0
        @index=0
        @sprites={}
        @viewport=Viewport.new(0,0,Graphics.width,Graphics.height)
        @viewport.z=99999
        addBackgroundPlane(@sprites,"bg","mapencounters-list",@viewport)
        @sprites["overlay"]=BitmapSprite.new(Graphics.width,Graphics.height,@viewport)
        pbSetSystemFont(@sprites["overlay"].bitmap)
        pbDrawText
        pbFadeInAndShow(@sprites) { update }
      end
    
      def pbDrawText
        overlay=@sprites["overlay"].bitmap
        overlay.clear
        
        if $game_switches[151]
          encdata=load_data("Data/encounters_2.dat")
        elsif $game_switches[169]
          encdata=load_data("Data/encounters_ghosts.dat")
        else
          encdata=load_data("Data/encounters.dat")
        end
        encounterMapIds = encdata.keys
        
        @sprites["mapList"]=Window_PokemonMapEncounters.new(encdata,
          encounterMapIds,10,40,Graphics.width,350,@viewport)
        @sprites["mapList"].viewport=@viewport
        
        textPositions=[
           [_INTL("Select a Location"),10,0,0,BASECOLOR,SHADOWCOLOR],
        ]
        
        pbSetSystemFont(@sprites["overlay"].bitmap)
        if !textPositions.empty?
          pbDrawTextPositions(@sprites["overlay"].bitmap,textPositions)
        end
      end
      
      def pbPokemonMapEncounters
        loop do
          Graphics.update
          Input.update
          self.update
          if Input.trigger?(Input::B)
            break
          end
          if Input.trigger?(Input::C)
            index = @sprites["mapList"].index
            mapId = @sprites["mapList"].getMapId(index)
          end
        end 
      end
    
      def pbEndScene
        pbFadeOutAndHide(@sprites) { update }
        pbDisposeSpriteHash(@sprites)
        @viewport.dispose
      end
    end
    
    class PokemonMapEncounters
      def initialize(scene)
        @scene=scene
      end
    
      def pbStartScreen
        @scene.pbStartScene
        @scene.pbPokemonMapEncounters
        @scene.pbEndScene
      end
    end
     
    Lol, that should not really be a question. If you press F1 in RMXP, and search arrays in the help section, you'll find the answer. If you have your map names dumped in an array, and that is the only way you're manipulating/using them, you can simply do array.sort. This sorts the strings in arrays alphabetically, though you can have array.sort {|a,b| ... } to define additional sorting parameters.

    Example:
    Code:
    a [COLOR="DeepSkyBlue"]= [[/COLOR] [COLOR="Purple"]"d"[/COLOR][COLOR="DeepSkyBlue"],[/COLOR] [COLOR="Purple"]"a"[/COLOR][COLOR="DeepSkyBlue"],[/COLOR] [COLOR="Purple"]"e"[/COLOR][COLOR="DeepSkyBlue"],[/COLOR] [COLOR="Purple"]"c"[/COLOR][COLOR="DeepSkyBlue"],[/COLOR] [COLOR="Purple"]"b"[/COLOR] [COLOR="DeepSkyBlue"]][/COLOR]
    a[COLOR="DeepSkyBlue"].[/COLOR]sort                    [COLOR="YellowGreen"]#=> ["a", "b", "c", "d", "e"][/COLOR]
    a[COLOR="DeepSkyBlue"].[/COLOR]sort [COLOR="DeepSkyBlue"]{|[/COLOR]x[COLOR="DeepSkyBlue"],[/COLOR]y[COLOR="DeepSkyBlue"]|[/COLOR] y [COLOR="DeepSkyBlue"]<=>[/COLOR] x [COLOR="DeepSkyBlue"]}[/COLOR]   [COLOR="YellowGreen"]#=> ["e", "d", "c", "b", "a"][/COLOR]
     
    What you're looking for is the sort_by method. Here, I've made a standalone test.

    Code:
    def sortTest
      a = ["Route 1", "Town 1", "Route 2", "Town 2"]
      b = [0, 1, 2, 3]
      
      b = b.sort_by{|elem| a[elem]}
      p(b)
    end

    First array 'a' contains the names of the maps, and the second array 'b' their ids. When I print
    out 'b' after sorting, it says [0, 2, 1, 3], in other words, it sorted the array 'b' by map names from
    'a'. If we rearrange the first array according to the new index order from sorted 'b', we have
    ["Route 1", "Route 2", "Town 1", "Town 2"].

    You should have a separate method that takes only these two arrays and returns sorted ids.
    For more info, check out the documentation for sort_by or take a look at this
    https://stackoverflow.com/questions/4283295/how-to-sort-an-array-in-ruby-to-a-particular-order

    Hope this helps!
     
    ok, i'm getting an error
    Exception: ArgumentError
    Message: comparison of Array with Array failed

    The two arrays are made by
    Code:
    mapNames = [] # Array containing the names of the maps
        for e in encdata.keys
          mapNames.push(pbGetMapNameFromId(e))
        end
        
        encounterMapIds = encdata.keys # Array containing the IDs of the maps
        encounterMapIds = encounterMapIds.sort_by{|elem| mapNames[elem]} # Sort The map ids by name

    Both arrays seem to contain the correct values, by printing them i get
    [27, 126, 159, 170, 181, 22, 55, 66, 143, 154, 187, 39, 160, 12, 23, 34, 56, 67, 78, 133, 144, 155, 177, 188, 18, 62, 73, 128, 2, 24, 68, 112, 167, 178, 189, 52, 63, 129, 184, 3, 14, 58, 69, 80, 168, 179, 9, 20, 31, 130, 163, 174, 4, 26, 70, 169, 180, 21, 32, 142, 153, 175]

    ["Gym", "Route 16", "Power Plant", "Pokemon Mansion B1F", "Seafoam Island B4F", "Mt. Moon B1F", "Diglett's Cave", "Pokemon Tower 3F", "Area 2", "Route 14", "Victory Road 1F", "Route 6", "Cinnabar Island", "Route 2", "Mt. Moon B2F", "Route 5", "Route 9", "Pokemon Tower 4F", "Route 7", "Fuchsia City", "Area 3", "Route 13", "Seafoam Island 1F", "Victory Road 2F", "Route 22", "Rock Tunnel 1F", "Route 8", "Mt. Moon B3F", "Pallet Town", "Route 4", "Pokemon Tower 5F", "Safari Entrance", "Pokemon Mansion 1F", "Seafoam Island B1F", "Victory Road 3F", "Route 11", "Rock Tunnel B1F", "Route 17", "Route 23", "Route 1", "Viridian Forest", "Route 10", "Pokemon Tower 6F", "Celadon City", "Pokemon Mansion 2F", "Seafoam Island B2F", "Viridian City", "Route 3", "Route 24", "Route 18", "Route 21", "Route 20", "Towns", "Cerulean City", "Pokemon Tower 7F", "Pokemon Mansion 3F", "Seafoam Island B3F", "Mt. Moon 1F", "Route 25", "Area 1", "Route 15", "Route 19"]

    I seem to have narrowed it down to the ids in the array not being consecutive, if i change your b array to b = [0, 1, 2, 4] then i get the same error with your example
     
    Last edited:
    Yes, the problem is that I'm taking values from the array with map names according to the index from
    the ids array. In my example, map with id = 0 will have name on 0th position in the names array.

    So, you should either have map with id=x be on position names[x] or have a hash that maps id values
    to names. The second solution seems more elegant as adding id => name pairs to the hash is better
    than having a sparse array in this example.

    So, this part will need changing.

    Code:
    mapNames = [] # Array containing the names of the maps
    for e in encdata.keys
       mapNames.push(pbGetMapNameFromId(e))
    end

    Make mapNames a hash (mapNames = {}), and instead of push, use mapNames[id] = name
     
    Back
    Top