def interpolate(known_data_points, x) xmin, xmax = nil, nil keys = known_data_points.keys.sort # find the first known x value at or below the provided x value… keys.reverse_each do |k| if k <= x xmin = k break end end xmin = keys[-1] if xmin == nil # find the first known x value at or above the provided x value… keys.each do |k| if k >= x xmax = k break end end xmax = keys[0] if xmax == nil return known_data_points[x] if known_data_points[x] != nil # finally, interpolate and return the answer! return known_data_points[xmin] + (((x - xmin) * (known_data_points[xmax] - known_data_points[xmin])) / (xmax - xmin)) end class NilClass def each # just to prevent an error. If a container is nil we just treat it empty. end end class Symbol def sect_to_str case self when :void then meh = " " when :sect_self then meh = "#Y@" when :door_ns then meh = "#P-" when :door_we then meh = "#P|" when :track_ns then meh = "#R|" when :track_we then meh = "#R-" when :track_ne then meh = "#R/" when :track_nw then meh = "#R\\" when :track_found then meh = "#RX" else sect = Sector.lookup(self) wall = self == sect.symbolw if wall # we're dealing with a wall sector. meh = ("#" + sect.wall_options[0].rand + sect.wall_options[1].rand) else meh = ("#" + sect.path_options[0].rand + sect.path_options[1].rand) end end return meh end end def convert_mxp(s) state = :not_found # parse the string for any of the character in the regular expression. # Then handle them differently dependant on the current state of the parsing as well as the individual character. # "<> \x03 <> \x04 <>" should become "<> \x03 <> \x04 <>" s.gsub!(/["<>&\x03\x04]/) do |f| if state == :not_found state = :found if(f == "\x03") case f when "<" then "<" when ">" then ">" when "&" then "&" when '"' then """ else f end elsif state == :found state = :not_found if (f == "\x04") f end end return s end $bad_words = /(ass|bitch|cunt|nigger|slut|whore|dick|shit|penis|piss|fuck|cocksucker)/i ### extend center function for strings. class String ### redefine center to o_center alias o_center center alias o_ljust ljust alias o_rjust rjust # remove bad words def lang_filter! self.gsub!($bad_words, "(expletive)") end ### break a string up into an array of arguments. ### valid format can be any words separated by spaces or def multi_args ss = StringScanner.new(self) arr = [] loop do ss.scan(/\s+/) # advance any spaces that may exist. if ss.peek(1) == '"' temp = ss.scan(/".*?"/).match(/"(.*?)"/).captures[0] rescue nil else temp = ss.scan_until(/[A-Za-z0-9._\-\/]+/) end break if !temp arr << temp.strip end return arr end def finalize_mxp! gsub!("\x03", "<") gsub!("\x04", ">") gsub!("\x05", "&") end def convert_mxp! state = :not_found # parse the string for any of the character in the regular expression. # Then handle them differently dependant on the current state of the parsing as well as the individual character. # "<> \x03 <> \x04 <>" should become "<> \x03 <> \x04 <>" gsub!(/["<>&\x03\x04]/) do |f| if state == :not_found state = :found if(f == "\x03") case f when "<" then "<" when ">" then ">" when "&" then "&" when '"' then """ else f end elsif state == :found state = :not_found if (f == "\x04") f end end end def strip_mxp! mode = 0 gsub!(/./) do |e| if mode == 0 # then we copy if e == "\x03" mode += 1 "" else e end else if e == "\x04" mode -= 1 # down a level "" else "" end end end end def sub_color! gsub! /#[^0-9^#^ ]/, "" ### busts color gsub! /##/, "#" self end def plaintext s = self.dup s.sub_color! s.strip_mxp! s end def center count, fill=' ' s = self.plaintext s.o_center(count, fill).sub(s, self) end def ljust count, fill=' ' s = self.dup s.sub_color! s2 = s.dup return s.o_ljust(count, fill).sub(s2, self) end def rjust count, fill=' ' s = self.dup s.sub_color! s2 = s.dup return s.o_rjust(count, fill).sub(s2, self) end def arg_class! p=nil command = "" one_arg! self, command return nil if command.empty? $editable_classes.each_pair do |k, v| if k.start_with? command.downcase return v end end return nil end def arg_dir! p=nil s = "" one_arg!self, s return s.exit_code_to_i end def arg_none p=nil return false if !self.empty? return nil end def arg_tag! p=nil command = self.multi_args[0] return nil if command.empty? return command end def arg_str p=nil return nil if self == '' return self end def arg_str! p=nil return nil if self == '' return self.slice!(0..-1) end # see if arg is an object in the room with p def arg_actor_room! p=nil return nil if !p || self.empty? things_in_room = {"room"=>[]} things_in_room["room"] = p.in_room.people.select { |obj| ((obj.is_a?(NPC) || obj.is_a?(Player)) && (p != obj))} # parse the string, use a specific list, and it is destructive to the string. found = query_parse self, things_in_room, true found.empty? ? nil : found end # see if arg is an object in the room with p def arg_obj_room! p=nil return nil if !p || self.empty? things_in_room = {"room"=>[]} p.in_room.each_stuff { |obj| things_in_room["room"] << obj if obj.is_a? Item } # parse the string, use a specific list, and it is destructive to the string. found = query_parse self, things_in_room, true found.empty? ? nil : found end # obj that is worn. def arg_obj_worn! p=nil return nil if !p || self.empty? lists = {} found = [] p.each_stuff_worn {|thing| found << thing } lists["equipment"] = found lists = query_parse(self, lists, true) # query the objects in inventory of p lists.empty? ? nil : lists end def arg_obj_inv! p=nil return nil if !p || self.empty? lists = {} # items currently worn are not included. worn_items = p.worn_items found = [] p.each_stuff_not_worn { |thing| found << thing } lists["inventory"] = found lists = query_parse(self, lists, true) # query the objects in inventory of p lists.empty? ? nil : lists end def arg_obj_inv_or_room! p=nil return nil if !p || self.empty? list = {"inventory"=>[], "room"=>[]} p.each_stuff { |obj| list["inventory"] << obj if obj.is_a? Item } p.in_room.each_stuff { |obj| list["room"] << obj if obj.is_a? Item } list = query_parse(self, list, true) # query the objects in inventory of p list.empty? ? nil : list end def arg_player_in_game! p=nil # may not want to select them all in the future. Right now it does. list = {"game"=>$dplayer_list.select { |player| true }} found = query_parse(self, list, true, {:name=>:short_desc, :id=>:__id__}) # query the players and match. found.empty? ? nil : found end def arg_int! p=nil command = "" one_arg! self, command return nil if command.empty? return Integer(command) rescue nil end def arg_word! p=nil command = "" one_arg! self, command if command.empty? nil else command end end ### Read up to amt characters into a new string. ### If amt is greater than strlength the entire string is returned. def pop_some amt return slice! 0..(amt-1) end def pop_line if (pos = index("\n")) != nil then return slice!(0..pos).chomp end nil end def exit_code_to_i sel = nil case self when "north" then sel = 0 when "east" then sel = 1 when "south" then sel = 2 when "west" then sel = 3 when "up" then sel = 4 when "down" then sel = 5 when "0" then sel = 0 when "1" then sel = 1 when "2" then sel = 2 when "3" then sel = 3 when "4" then sel = 4 when "5" then sel = 5 end return sel end def get_player $dplayer_list.each do |xplay| #return the player if they match the name. return xplay if xplay.name.start_with? self end return nil end # returns an array ordered pair of [x, y]. This will throw an exception that can be rescued if it is invalid. def get_coords gsub!(/[,.]/, ' ') a = split(' ') if (a[0] != nil && a[1] != nil && a[0].is_number? && a[1].is_number?) a[0], a[1] = Integer(a[0]), Integer(a[1]) return a end raise "Invalid coordinates." return [0,0] end # returns true or false. def is_coords? (get_coords rescue false) ? true : false end #check to see if a number def is_number? if (Integer(self) rescue false) true else false end end end ### Extension for rounding a floating point. class Float def roundf(places) temp = self.to_s.length sprintf("%#{temp}.#{places}f",self).to_f end end ### Extension for various Integers class Integer def exit_code_to_s ea = ["north", "east", "south", "west", "up", "down"] return nil if (self > 5 || self < 0) return ea[self] end def exit_code_rev ea = [2, 3, 0, 1, 5, 4] return nil if (self > 5 || self < 0) return ea[self] end def commify str = "#{self}" str.to_s.reverse.scan(/(?:\d*\.)?\d{1,3}-?/).join(',').reverse end end ### Check to see if a given name is valid def check_name name return false if (name.size < 3 || name.size > 12) if name =~ /^[[:alpha:]]+$/ return true else return false end end ### Check to see if password is valid for new password. def check_pass pass return false if (pass.length < 3 || pass.length > 12) pass.length.times do |i| if pass[i].chr == '~' return false end end return true end def communicate author, txt, range, called=nil filtered = txt.dup filtered.lang_filter! case range when :comm_local called = "say" if !called author.view("#CYou #{called}, '#{author.channel_flags.is_set?(:language_filter)? filtered : txt}'#n" + ENDL) called = called.en.plural in_room.display([:visual, :sound, "other.can_see?(actor) || other.can_hear?(actor)"], self, [self], "#C<%=other.peek(actor)%> #{called}, '<%=other.listen(other.channel_flags.is_set?(:language_filter) ? arg[1] : arg[0], actor)%>#n'", txt, filtered) when :comm_global called = "gossip" if !called called = called.en.plural author.view "#PYou #{called}, '#{author.channel_flags.is_set?(:language_filter)? filtered : txt}'#n" + ENDL $dplayer_list.each do |other| next if other == author other.view "#P#{other.peek(author)} #{called}, '#{other.channel_flags.is_set?(:language_filter)? filtered : txt}'#n" + ENDL end when :comm_private # not implemented end end ### Loading of help files, areas, etc, at boot time. def load_muddata load_helps end ### Check to reconnect a player. ### Called in core nanny coroutine. def check_reconnect name $dplayer_list.each do |dPlayer| if dPlayer.name.capitalize == name.capitalize dPlayer.socket.close_connection true if dPlayer.socket return dPlayer end end nil end ### Checks if aStr is a prefix of bStr. def is_prefix astr, bstr return false if astr.nil? || bstr.nil? || astr.empty? || bstr.empty? astr == bstr.slice(0...astr.size) end def one_arg fstr, bstr, nums_too = true bstr.replace(fstr.slice(if nums_too then /[0-9a-zA-Z@:_\.-]+/ else /[a-zA-Z@:_\.-]+/ end) || '') end ### Breaks a string down into a single argument. def one_arg! fstr, bstr, nums_too = true bstr.replace(fstr.slice!(if nums_too then /[0-9a-zA-Z@:_\.-]+/ else /[a-zA-Z@:_\.-]+/ end) || '') fstr.lstrip! end ### ### Detects the last time the file was edited. def last_modified file return File.stat(file).mtime.to_i rescue return 0 end # distance form def dist_form(a1, a2) Math.sqrt( (a2[0] - a1[0])**2 + (a2[1] - a1[1])**2) end # find the azimuth of the direction towards target def get_azi a, b # find the distance between the two points. hyp = dist_form a, b adj = (b[1] - a[1]) #which hemisphere? if (b[0] - a[0]) >= 0 d = 0 else adj = -adj d = 180 end # cos^-1 (adj/hyp) * 180/PI r = Math::acos(adj/hyp) # answer in radians d = r * 180 / Math::PI + d end def find_player arg $dplayer_list.each do |xPlayer| return xPlayer if is_prefix arg.capitalize, xPlayer.name end return nil end def strip_color txt txt.gsub! end # takes a string and returns a string with color codes added. def render_color(data) data.gsub!($comp_tab) do |s| $color_table[s] end return data end def render_color2(data) return data end def text_to_world txt $dsock_list.each do |d| d.text_to_socket txt end end