MU Soapbox

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Muxify
    • Mustard

    What's So Hard About Ruby?

    Game Development
    18
    54
    3228
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • faraday
      faraday @Arkandel last edited by

      @arkandel Heh, right?

      For comparison, here's the same function (more or less - there's not a 100% mapping) in the Ares ruby framework. It's still complex, but at least it's readable.

      https://github.com/AresMUSH/aresmush/blob/master/plugins/fs3combat/helpers/actions_helper.rb#L392

      And because it's a modern framework, I can have unit tests to make sure each piece works right.

      1 Reply Last reply Reply Quote 0
      • G
        Groth @faraday last edited by

        @faraday said in What's So Hard About Ruby?:

        I'm not saying Lisp (or MUSHCode for that matter) is a bad language. They have their niche uses.

        It's probably fine to call MUSHCode a bad language for modern use. It made sense for the purpose it was designed, when everyone was using telnet and there was no such thing as IDE's and source control and feeding the game code line by line was just the way you did things.

        I don't think it makes any sense in a world where we have so many powerful IDE's and flexible frameworks to work with.

        That said, one thing that's easy to do in MUSH and hard to do without MUSHCode is scripting unique objects. I haven't tried it in Ares but I know in Evennia it's non-trivial to make something like a ball you can throw at people or a magic 8 ball or whatever.

        What is obvious to you may not be obvious to me and vice versa.

        faraday EMDA 2 Replies Last reply Reply Quote 0
        • faraday
          faraday @Groth last edited by faraday

          @groth said in What's So Hard About Ruby?:

          It's probably fine to call MUSHCode a bad language for modern use.

          If your constraints are that you need to be able to edit complex systems live in-game through a MU client, I doubt you could do much better than MUCode. People are still doing that so I consider that a modern use. YMMV though obviously. Bad or not, it's a pain to code in.

          @groth said in What's So Hard About Ruby?:

          That said, one thing that's easy to do in MUSH and hard to do without MUSHCode is scripting unique objects. I haven't tried it in Ares but I know in Evennia it's non-trivial to make something like a ball you can throw at people or a magic 8 ball or whatever.

          I mean, it depends on what you want the thing to do.

          class MagicEightBallCmd
                include CommandHandler
                
                def check_has_ball
                   return "You don't have a magic 8-ball!" if false
                   return nil
                end
                
                def handle
                   message = ""
                   case rand(3)
                   when 0
                     message = "A"
                   when 1
                     message = "B"
                   else
                     message = "D"
                   end
                   client.emit "You shake the magic eight-ball. It says: #{message}"
                end
              end
          

          What's different about Ares is that it's designed for global systems, not local code. Why? Because I personally feel that local code is archaic and rarely-used on the kind of narrative-focused MUs that Ares is made for, and also local code doesn't mesh well with web portal play, which Ares is also made for.

          So if you want your 8ball command to be a global available to anyone on-demand, it's easy. If you want to limit it, you need to put a bit more thought into how exactly that's going to work and update the check_has_ball method accordingly. Is it a full-blown economy and inventory tracking system, a "has_eight_ball" flag that's set by staff, something that only works in Joe's Bar, or what?

          1 Reply Last reply Reply Quote 0
          • Cobalt
            Cobalt Tutorialist last edited by

            Maybe I just don't have the brain for modern coding languages then. Because I found it frustrating to the point of despair.

            G faraday 2 Replies Last reply Reply Quote 1
            • G
              Groth @Cobalt last edited by

              @cobalt said in What's So Hard About Ruby?:

              Maybe I just don't have the brain for modern coding languages then. Because I found it frustrating to the point of despair.

              The frustrating part I find with any modern language is learning the quirks of any given library or framework. They all have subtle differences that can trip you up until you get used to them.

              I would recommend starting with something small and manageable or modding some pre existing project. Tinkering with an ares game or arx gives plenty of opportunity for small projects.

              What is obvious to you may not be obvious to me and vice versa.

              Cobalt 1 Reply Last reply Reply Quote 0
              • Cobalt
                Cobalt Tutorialist @Groth last edited by

                @groth Yeah, I did that. I even went through the tutorials on ares central, both the one for coding the notes stuff and links to getting started with Ruby. Then when it came time to do my own project I could not, for the life of me, wrap my head around how to do it.

                I wanted to code a widget that would flip the area a room was at from "simulated weather" to "space", to simulate turning a viewport off and on. And I couldn't, for the life of me, figure out how to get/set the area.

                Other people have thrived with Ares and Ruby, so obviously the language isn't the problem. The problem is me.

                Possibly because I learnt softcode before real code.

                Derp G faraday 3 Replies Last reply Reply Quote 0
                • Derp
                  Derp Admin @Cobalt last edited by

                  @cobalt

                  If it makes you feel better, I haven't quite figured that out either.

                  The actual coding of Ruby I can do.

                  But I've read the AresCentral tutorials about three dozen times, and right around the time we get into YAML and coding plugins -- something just does not line up.

                  I cannot for the life of me figure out how the YAML files get structured into character sheet data, or how to represent ranges in YAML files, or even, really, how to create a command that appends data onto old data, like a list of aspirations that can be /added and /completed.

                  I feel like all the information is there, or should be there, or there should be some way to figure it out. But the 'putting it all into practice' part, to me, feels like 'Alright, now that you know the times tables, let's talk about polynomial equations'.

                  Like -- it feels there are missing steps in there, somewhere, and that I should be able to piece it together. But for the life of me I have not been able to so far.

                  Racism isn't Tinkerbell. It doesn't need you to believe in it for it to exist.

                  Cobalt 1 Reply Last reply Reply Quote 1
                  • Cobalt
                    Cobalt Tutorialist @Derp last edited by

                    @derp Right, exactly, I feel like I missed some very obvious important step somewhere that everyone else can see and understand but I am just blind to it.

                    I might try again now that I am being treated for ADD (kinda), but like... Waves hands in space. It feels like there's some missing link that my brain just cannot click onto.

                    Derp 1 Reply Last reply Reply Quote 1
                    • G
                      Groth @Cobalt last edited by

                      @cobalt

                      The problem is likely just the different paradigm and your brain thinking the MUSH way. Rooms, objects, characters etc are not set up the same way so whenever you try to approach a problem the same way you did MUSH code it doesn't work.

                      Unfortunately there's probably no easier way then learning the new pattern step by step until you're used to it. With Ares at least Faraday did a great work with the documentation.

                      What is obvious to you may not be obvious to me and vice versa.

                      1 Reply Last reply Reply Quote 0
                      • Derp
                        Derp Admin @Cobalt last edited by

                        @cobalt

                        Yeah, exactly.

                        Like, I know that I'm not completely inept at this, I managed to code a functional polyhedral die roller from scratch complete with pretty output templates and everything.

                        And yet, when we get to updating character objects in the database and how to structure them -- it really feels like there's a missing link, somewhere.

                        Like, it has to be there because a billion other people have made it work, it seems. But for whatever reason, it's like 'here is a YAML file and here is how to create and update a field on the character object and here is how to create Cortex...'

                        And still, I'm left going -- ok so if I wanted to do 'Strength has a range of values from 1 to 5 in integers' -- how do I do that?

                        If I do set Strength = 5 how do I tell the game that the 5 is an integer and not a string?

                        How do I tell it that Strength = Duck is an invalid value in the YAML?

                        There are so many questions.

                        Racism isn't Tinkerbell. It doesn't need you to believe in it for it to exist.

                        faraday 1 Reply Last reply Reply Quote 1
                        • faraday
                          faraday @Cobalt last edited by faraday

                          @Cobalt @Derp I don't think there's anything wrong with you or that you're missing anything in particular.

                          Ares is massive. Thousands of files. Tens of thousands of lines of code. A website. A database. Two different programming languages (more if you count the templating languages and YAML and CSS).

                          It's a lot.

                          The thing is - MUSHcode was a lot too. I remember printing out the function help files back in the '90s and being all: OMG this is overwhelming. I learned it piece by piece, starting out with some dumb little notepad object or something and working up slowly. We've just all had so many years to build up familiarity with it, and probably have forgotten how hard it was to get started.

                          Another confounding factor is that in Ares, most of the stuff you need is already built. So all that remains is the hard stuff - chargen, magic, and other massive systems. Nobody's starting with their own custom +finger because that's already done for you. And even if you did want to customize it, you have to first decipher what's already been made. So you go from getting your feet wet in the tutorials to jumping right into the deep end. It's hard.

                          But none of that has anything to do with the language itself.

                          1 Reply Last reply Reply Quote 2
                          • faraday
                            faraday @Derp last edited by

                            @derp said in What's So Hard About Ruby?:

                            And still, I'm left going -- ok so if I wanted to do 'Strength has a range of values from 1 to 5 in integers' -- how do I do that?
                            If I do set Strength = 5 how do I tell the game that the 5 is an integer and not a string?
                            How do I tell it that Strength = Duck is an invalid value in the YAML?

                            These are great questions for the Ares forums or discord, and there are lots of different ways to do it, but this might help. (I'm winging it, so please don't expect this to actually work right as written)

                             class AttributeSetCmdHandler
                                  include CommandHandler
                            
                                  # Place to store our ability name and rating
                                  attr_accessor :ability, :rating
                            
                                  # This makes sure you gave both an ability and rating
                                  def required_args
                                    [ self.ability, self.rating ]
                                  end
                                  
                                  # This cracks apart our `set Strength=5` into its pieces.
                                  # The ability is trimmed and titlecased.
                                  # The rating is interpreted as a number. If it's not a number string it becomes 0.
                                  def parse_args
                                    args = cmd.parse_args(ArgParser.arg1_equals_arg2)
                                    self.ability = titltecase_arg(args.arg1)
                                    self.rating = integer_arg(args.arg2)
                                  end
                            
                                  def handle
                                    # Read our list of attributes and max rating from the YAML config.
                                    valid_attrs = Global.read_config("yoursystem", "attributes")
                                    max_rating = Global.read_config("yoursystem", "max_attr_rating")
                                    
                                    if (self.rating < 0 || self.rating > max_rating)
                                      client.emit_failure "Invalid rating."
                                      return
                                    end
                                    
                                    if (!valid_attrs.include?(self.ability))
                                      client.emit_failure "Not a valid ability."
                                      return
                                    end
                                    
                                    # update the database. attributes is probably a name:value
                                    # hash, so there's a little extra fussing you have to do.
                                    abilities = enactor.yoursystem_attributes
                                    abilities[self.ability] = self.rating
                                    enactor.update(yoursystem_attributes: abilities)
                            
                                    client.emit_success "You set your #{self.ability} to #{self.rating}."
                                  end
                                end
                                 
                            
                            1 Reply Last reply Reply Quote 2
                            • faraday
                              faraday @Cobalt last edited by faraday

                              @cobalt said in What's So Hard About Ruby?:

                              I wanted to code a widget that would flip the area a room was at from "simulated weather" to "space", to simulate turning a viewport off and on. And I couldn't, for the life of me, figure out how to get/set the area.

                              Sorry for the triple post but wanted to answer the pieces separately.

                              # Set your current room to the space area
                              space_area = Area.named("Space")
                              enactor.room.update(area: space_area)
                              

                              Changing it back gets a bit trickier because you might have to create a temporary storage for "the area it used to be in" or something. Kinda depends how you want it to work.

                              Regardless, this is not something I would have expected to be super intuitive looking at the 2,000 or so lines of code in the 'rooms' module, so you shouldn't feel bad for not being able to just figure it out at a glance. I'm always happy to help point folks in the right direction though.

                              1 Reply Last reply Reply Quote 2
                              • EMDA
                                EMDA @Groth last edited by EMDA

                                @groth said in What's So Hard About Ruby?:

                                I haven't tried it in Ares but I know in Evennia it's non-trivial to make something like a ball you can throw at people or a magic 8 ball or whatever.

                                I don't think doing that would be too difficult in Evennia either. I kinda structured this off some furniture code I wrote a long time ago on a pet project, but I'm really rusty with both Evennia and python at the moment so it's just a broad-strokes sketch and not meant to work out of the box and probably not the best way to do it!

                                from evennia import DefaultObject, CmdSet, default_cmds
                                import random
                                
                                class EightBall(DefaultObject):
                                    "A simple 8-ball"
                                    
                                    def at_init(self):
                                        self.ndb.fortunes = self.ndb.fortunes or ["1","2","3","4","5","6","7","8"]
                                    
                                    def at_object_creation(self):
                                        # add the commands associated with the 8-ball to each instance
                                        self.cmdset.add("typeclasses.eightball.BallCmdSet", permanent=True)
                                
                                    def fortune(self):
                                        # return a random selection from our fortunes. I don't think this return is an
                                        # issue but if it were you might need to change how this is done.
                                        selection = random.choice(self.ndb.fortunes)
                                        return selection
                                
                                class CmdShake(default_cmds.MuxCommand):
                                    """
                                    Usage:
                                        shake <object>
                                    
                                    This command allows a character to read their fortune in an 8-ball.
                                    """
                                    
                                    key = "shake"
                                    arg_regex = r"\s.+" # require a space-separated argument, i.e. 'ball'
                                    locks = "cmd:all()"
                                        
                                    def parse(self):
                                        self.target = self.args.strip()
                                    
                                    def func(self):
                                        caller = self.caller
                                        target = caller.search(self.target)
                                        
                                        if not target:
                                            #yield an error if the target cannot be found
                                            caller.msg(f"Can't find {self.target}.")
                                            return
                                        elif not isinstance(target, EightBall):
                                            # ensure the command is being used on a valid target
                                            caller.msg("Shaking that would be rude!")
                                            return
                                        else:
                                            # provide a fortune to the caller
                                            caller.location.msg_contents(f"{caller.key} shakes {target.key} and studies it closely.")
                                            fortune = target.fortune()
                                            caller.msg(f"Through {target.key}'s murky glass, you can read: {fortune}.")
                                            return
                                
                                class BallCmdSet(CmdSet):
                                    """
                                    Base command set for 8-ball objects.
                                    """
                                    
                                    key = "BallCmdSet"
                                    
                                    def at_cmdset_creation(self):
                                        self.add(CmdShake())
                                

                                You could modify and complicate that in a host of ways, like having the main class have hundreds of fortunes and just pack a selection of 8 into each object (and be saved instead of being nbd), and so on, but it's a scaffold.

                                A huge challenge with an engine like Evennia, and from what faraday has been saying with Ares, is that a lot of its power comes from the fact that it has all kinds of hooks and tools distinct from the language it uses packed in everywhere. So even a simple idea ends up involving a lot of wrestling to learn how to get it to fit into the pattern of the engine, and that's really hard at first.

                                On the head subject of the thread, I think Ruby is pretty straightforward and no more difficult than Python or another alternative. My only experience with it was a mandatory semester of programming-for-non-programmers in college and I had no head for code but I suffered through it kinda well, and that's a point in the language's favor in a big way. The biggest hurdle to making any project a reality, imo, is bridging the gap from understanding the basics of a language (if you're approaching from a new-coder perspective) to understanding how to leverage whatever tools the engine you're using has to offer, and that's going to happen regardless of the language and regardless of the engine.

                                1 Reply Last reply Reply Quote 5
                                • 1
                                • 2
                                • 3
                                • 3 / 3
                                • First post
                                  Last post