RPG Maker VX Ace
TriNameGenRMVXA
Back when I was still a Minecraft modder I wanted to create something that would be very useful to content creators, both Minecraft modders and regular Java programmers. I originally created a name generator which was pretty complicated.
A year or two later I decided to simplify the script a little, and decided to just start from scratch. When creating the first name generator, I had already heard something about Markov Chains, so I decided to just do whatever the hell I wanted (I don't need no stinkin' Markov Chains). Well, turns out that this name generator might be more Markov Chain-y than I thought.
So yeah, here's my very simple name generator. Mind you, it's simple in its design. It doesn't mean the process of creating your own name set is.
Download (16.44 kB, 1703 times downloaded)
Demo (1.33 MB, 417 times downloaded)
You basically need one thing, and that is a list of names. This list can be anything from human names to even cities and animals. You can even use five letter words if you wanted to. You can create this list in two ways, either as an array or as a text file, where each name is separated by a new line.
Now, you'll need to first create a dictionary object.
dictionary = TNG_Dictionary.new
Alternatively you could use optional parameters.
dictionary = TNG_Dictionary.new(min_length, max_length, start_min, dict...)
min_length and max_length define the minimum and maximum search length. What it basically does is stitch two name parts that originally followed eah other together. What the name generator does is splice each name in groups of any amount of characters between min_length and max_length, and for each name part stores what other name parts have followed.
start_min determines the minimum length of the first name part. When set to -1, this value would be min_length - 1.
If you have previously created dictionaries and want to easily merge the two name lists, you can also supply other dictionaries at the end. Do note that name parts are not being merged with the dictionary.
Next, add the names, using either method or both.
dictionary.add_names(array) dictionary.add_file(filename)
After the names are added, the names need to be processed.
dictionary.process_names
Even after you've processed the names, though, you can still add names to be processed. You do still need to process the names again though, although it will skip over those that already have been processed.
Finally, to generate names, you could call the next method. All parameters are optional.
dictionary.generate_name(max_namelength, min_namelength, rng, names_list)
max_namelength and min_namelength define the minimum and maximum length of the name. They default to 10 and 3 respectively. rng is a Random object. If set to nil, it will create a new instance of Random. names_list is an array where the generated name will be stored. When left empty, it will use the generated names list inside the dictionary. This list can be retrieved and cleared.
dictionary.generated_names dictionary.clear_generated
#============================================================================== # # GaryCXJk - TriNameGenVXA v1.00 # * Last Updated: 2013.06.30 # * Level: Medium # * Requires: N/A # #============================================================================== $imported = {} if $imported.nil? $imported["CXJ-TriNameGenVXA"] = true #============================================================================== # # Changelog: # #------------------------------------------------------------------------------ # 2013.06.30 - v1.00 # # * Initial release # #============================================================================== # # Back when I was still a Minecraft modder I wanted to create something that # would be very useful to content creators, both Minecraft modders and regular # Java programmers. I originally created a name generator which was pretty # complicated. # # A year or two later I decided to simplify the script a little, and decided # to just start from scratch. When creating the first name generator, I had # already heard something about Markov Chains, so I decided to just do whatever # the hell I wanted (I don't need no stinkin' Markov Chains). Well, turns out # that this name generator might be more Markov Chain-y than I thought. # # So yeah, here's my very simple name generator. Mind you, it's simple in its # design. It doesn't mean the process of creating your own name set is. # #============================================================================== # # Installation: # # Make sure to put this below Materials, but above Main Process. # #============================================================================== # # Usage: # # You basically need one thing, and that is a list of names. This list can be # anything from human names to even cities and animals. You can even use # five letter words if you wanted to. You can create this list in two ways, # either as an array or as a text file, where each name is separated by a new # line. # # Now, you'll need to first create a dictionary object. # # dictionary = TNG_Dictionary.new # # Alternatively you could use optional parameters. # # dictionary = TNG_Dictionary.new(min_length, max_length, start_min, dict...) # # min_length and max_length define the minimum and maximum search length. # What it basically does is stitch two name parts that originally followed # eah other together. What the name generator does is splice each name in # groups of any amount of characters between min_length and max_length, and # for each name part stores what other name parts have followed. # # start_min determines the minimum length of the first name part. When set to # -1, this value would be min_length - 1. # # If you have previously created dictionaries and want to easily merge the two # name lists, you can also supply other dictionaries at the end. Do note that # name parts are not being merged with the dictionary. # # Next, add the names, using either method or both. # # dictionary.add_names(array) # dictionary.add_file(filename) # # After the names are added, the names need to be processed. # # dictionary.process_names # # Even after you've processed the names, though, you can still add names to be # processed. You do still need to process the names again though, although it # will skip over those that already have been processed. # # Finally, to generate names, you could call the next method. All parameters # are optional. # # dictionary.generate_name(max_namelength, min_namelength, rng, names_list) # # max_namelength and min_namelength define the minimum and maximum length of # the name. They default to 10 and 3 respectively. rng is a Random object. # If set to nil, it will create a new instance of Random. names_list is an # array where the generated name will be stored. When left empty, it will # use the generated names list inside the dictionary. This list can be # retrieved and cleared. # # dictionary.generated_names # dictionary.clear_generated # #============================================================================== # # License: # # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE # Version 2, December 2004 # # Copyright (C) 2013 Sam Hocevar <sam@hocevar.net> # # Everyone is permitted to copy and distribute verbatim or modified # copies of this license document, and changing it is allowed as long # as the name is changed. # # DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE # TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION # # 0. You just DO WHAT THE FUCK YOU WANT TO. # # See http://www.wtfpl.net/ for more details. # #------------------------------------------------------------------------------ # Extra notes: # # This license was picked due to the fact that in my opinion this script # shouldn't be restricted by the creative commons license, which mostly still # requires you to attribute the content to the original creator. I also feel # like this script could help others understand certain mechanics and can # learn from it without the fear of violating a license due to similar coding. # # You can still give credits if you want though, and are free to pick the # following names when you give credit: # # * GaryCXJk # * Gary A.M. Kertopermono # * G.A.M. Kertopermono # * GARYCXJK # # To make it clear, this license allows you to DO WHAT THE FUCK YOU WANT TO, # which means you can use it in commercial as well as non-commercial products, # you can modify it, redistribute it, make toilet paper out of it, sell it on # eBay and win a presidential election with it. But it's mostly for making # games. There are no restrictions, no need to attribute regardless of the # aount of modifications made, you are allowed to remove all references to me, # you are allowed to change the license, although that's pretty much a dick # move (actually, I'm not sure if you can change the license or not, but let's # just not be dicks here, mmm'kay?), you are allowed to directly sell this # script or monetize on it on your own site. # # This script was originally hosted on: # http://area91.multiverseworks.com # #============================================================================== # # The code below should not be altered unless you know what you're doing. # #============================================================================== #============================================================================== # ** TNG_Part #------------------------------------------------------------------------------ # This defines a name part for TriNameGen. #============================================================================== class TNG_Part #-------------------------------------------------------------------------- # * Object Initialization #-------------------------------------------------------------------------- def initialize(part_string) @part_string = part_string end #-------------------------------------------------------------------------- # * Define if this name part can end the name #-------------------------------------------------------------------------- def set_can_end(can_end) @can_end = can_end end #-------------------------------------------------------------------------- # * Determine if this name part can end the name #-------------------------------------------------------------------------- def can_end? @can_end = false if @can_end.nil? return @can_end end #-------------------------------------------------------------------------- # * Add a name part as a possible follow-up #-------------------------------------------------------------------------- def add_part(part) @next_parts||= [] @next_parts.push(part) unless @next_parts.include?(part) end #-------------------------------------------------------------------------- # * Gets the amount of name parts that can follow #-------------------------------------------------------------------------- def length return @next_parts.size end #-------------------------------------------------------------------------- # * Returns a copy of the list of follow-up parts #-------------------------------------------------------------------------- def get_parts @next_parts||= [] return Array.new(@next_parts) end #-------------------------------------------------------------------------- # * Gets a copy of the part string #-------------------------------------------------------------------------- def part_string return String.new(@part_string) end end #============================================================================== # ** TNG_Dictionary #------------------------------------------------------------------------------ # This defines a dictionary for TriNameGen. This is basically the main class # you'll be working with. #============================================================================== class TNG_Dictionary #-------------------------------------------------------------------------- # * Object Initialization #-------------------------------------------------------------------------- def initialize(min_length = 2, max_length = 3, start_min = 1, *dictionary) @unprocessed_names = [] @processed_names = [] @generated_names = [] @start_parts = [] @part_dictionary = {} @min_length = (min_length <= 0 ? 2 : min_length) @max_length = (max_length < @min_length ? (@min_length == 2 ? 3 : @min_length) : max_length) @start_min = (start_min > 0 ? [start_min, @min_length].min : @min_length - 1) add_dictionary(dictionary) unless dictionary.nil? || dictionary.empty? end #-------------------------------------------------------------------------- # * Add the names of other dictionaries into this dictionary #-------------------------------------------------------------------------- def add_dictionary(*dictionaries) dictionaries.each do |dictionary| add_names(dictionary.base_names) end end #-------------------------------------------------------------------------- # * Add names to the unprocessed names list in this dictionary #-------------------------------------------------------------------------- def add_names(names) names.each do |name| next if names.empty? @unprocessed_names.push(name) unless base_names.include?(name) end end #-------------------------------------------------------------------------- # * Add names to the unprocessed names list in this dictionary from a # plaintext file #-------------------------------------------------------------------------- def add_file(filename) File.open(filename, "rb") do |f| data = f.read.split(/[\r\n]+/) end add_names(data) end #-------------------------------------------------------------------------- # * Get all names used to generate this library (both used and unused) #-------------------------------------------------------------------------- def base_names return @unprocessed_names + @processed_names end #-------------------------------------------------------------------------- # * Process the names list #-------------------------------------------------------------------------- def process_names while @unprocessed_names.size > 0 name = @unprocessed_names.shift process_name(name) @processed_names.push(name) end end #-------------------------------------------------------------------------- # * Process the current name #-------------------------------------------------------------------------- def process_name(name) proc = [[[@start_min, name.size].min, name, nil]] while proc.size > 0 while proc.size > 0 && proc[-1][0] > [proc[-1][1].size, @max_length].min proc.pop end next unless proc.size > 0 part_string = proc[-1][1][0, proc[-1][0]] if @part_dictionary.include?(part_string) part = @part_dictionary[part_string] else part = TNG_Part.new(part_string) @part_dictionary[part_string] = part end if !proc[-1][2].nil? proc[-1][2].add_part(part) else @start_parts.push(part) unless @start_parts.include?(part) end if proc[-1][1].size == proc[-1][0] part.set_can_end(true) proc[-1][0]+= 1 else name = proc[-1][1][part_string.size, proc[-1][1].size - part_string.size] proc.push([[@min_length, name.size].min, name, part]) proc[-2][0]+= 1 end end end #-------------------------------------------------------------------------- # * Get all parts #-------------------------------------------------------------------------- def get_parts return Array.new(@part_dictionary.values) end #-------------------------------------------------------------------------- # * Get all start parts #-------------------------------------------------------------------------- def start_parts return Array.new(@start_parts) end #-------------------------------------------------------------------------- # * Generate all possible names # Only advisable during development or to pre-generate a complete # names list #-------------------------------------------------------------------------- def generate_all_names(max_namelength = 10, min_namelength = 3, names_list = @generated_names) min_namelength = 3 if min_namelength < 2 max_namelength = min_namelength if max_namelength < min_namelength proc = [[start_parts, ""]] while !proc.empty? if proc[-1][0].empty? proc.pop next end part = proc[-1][0].shift name = proc[-1][1] + part.part_string if ((min_namelength)..max_namelength).include?(name.size) && part.can_end? && !names_list.include?(name) names_list.push(name) end next if name.size >= max_namelength index = [@min_length, name.size].min next_parts = [] while index <= [@max_length, name.size].min unless @part_dictionary.include?(name[-index, index]) index+= 1 next end parts = @part_dictionary[name[-index, index]].get_parts index+= 1 next if parts.empty? parts.each do |cpart| next if (name + cpart.part_string).size > max_namelength || next_parts.include?(cpart) next_parts.push(cpart) end end proc.push([next_parts, name]) end end #-------------------------------------------------------------------------- # * Generate name #-------------------------------------------------------------------------- def generate_name(max_namelength = 10, min_namelength = 3, rng = nil, names_list = @generated_names) min_namelength = 3 if min_namelength < 2 max_namelength = min_namelength if max_namelength < min_namelength rng = Random.new if rng.nil? proc = [[start_parts, ""]] while !proc.empty? if proc[-1][0].empty? proc.pop next end index = rng.rand(proc[-1][0].size) part = proc[-1][0].delete_at(index) name = proc[-1][1] + part.part_string rndn = rng.rand(2) if ((min_namelength)..max_namelength).include?(name.size) && part.can_end? && !names_list.include?(name) if rndn == 0 names_list.push(name) return name end proc[-1][0].push(part) end next if name.size >= max_namelength index = [@min_length, name.size].min next_parts = [] while index <= [@max_length, name.size].min next unless @part_dictionary.include?(name[-index, index]) parts = @part_dictionary[name[-index, index]].get_parts index+= 1 next if parts.empty? parts.each do |cpart| next if (name + cpart.part_string).size > max_namelength || next_parts.include?(cpart) next_parts.push(cpart) end end proc.push([next_parts, name]) end return "" end #-------------------------------------------------------------------------- # * Clear the default list of generated names #-------------------------------------------------------------------------- def clear_generated @generated_names.clear end def generated_names return Array.new(@generated_names) end end