Pyrel dev log, part 2

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • LostTemplar
    Knight
    • Aug 2009
    • 670

    #61
    browse command to select, 'm ' to cast. Also identify can e.g. identify first unknown object in inventory (or floor, if all inventory is known) if object was not selected, it is what I do 99% of the time anyway.

    Comment

    • Derakon
      Prophet
      • Dec 2009
      • 9022

      #62
      You guys do know that the 'n' command in Angband is "repeat last command", right? So if you want to keep using your rare Bolts of Slay Evil instead of the junky ones while you fight this hell wyrm, just shoot it once, then keep hitting n. Of course this only works so long as you don't do anything else...

      In any event, there's definitely room for defaults to automatically kick in. I'll need some mechanism for prompts to silently be resolved, anyway, if I'm to use this same system for creature AI. The real question is, when should prompts be used, vs. when should the last action taken be assumed to be the one you want to take this time? For example, it'd be completely stupid to assume that when you hit 'm' you want to cast the same spell you did last time. And in fact most item-selecting commands shouldn't assume you want the same thing as last time -- I'd wager that ammo selection is the only situation where this question is remotely contentious.

      Comment

      • LostTemplar
        Knight
        • Aug 2009
        • 670

        #63
        You guys do know that the 'n' command in Angband is "repeat last command", right?
        I know about all angband commands. If I want move & shoot 'n' will not work.

        it'd be completely stupid to assume that when you hit 'm' you want to cast the same spell you did last time.
        Well, it is your opinion, you have right to think so.

        Just one example, if you ever played DOOM, or some other first person shooter, it allways assume, that when you press mouse button, you want fire the same weapon, you did last time, unless you press the special key to change the weapon, and this is not stupid, it is just how UI works. It is quite a legitimate way for UI to function and many people just like it, yes it needs one extra key press if you need to switch weapons (e.g Diablo II do same thing with spells, you bind spell to mouse button and it will stay here until you change it wilingly, do you think Diablo II UI is stupid ?).
        Last edited by LostTemplar; August 17, 2012, 17:36.

        Comment

        • Derakon
          Prophet
          • Dec 2009
          • 9022

          #64
          You're comparing realtime games with highly repetitive combat to a turn-based game with, admittedly, still relatively repetitive combat, but the scale is significantly different. Doom and Diablo don't have complex verbs; every usable verb is "aim and click". And you typically only have 3-5 readied verbs to switch between.

          Now, it does seem to me that it'd be a good idea to have an easy system to "ready" a verb in Pyrel so that you can refer to it as needed. And it wouldn't be a bad idea to have an automatic "repeat last non-movement verb" or something similar. But that's exactly why the macro system needs to be cleanly implemented, because those user interface enhancements will be handled through the macro system! All you need to do is "bake" most of the context into a verb, so when you perform it, the amount of extra prompting required is minimal.

          So basically, the way I envision this working is that you perform an action, and then say "Hey game, remember that action I just did, and bind it to this key." Or, for multi-turn macros, you explicitly start macro recording, perform your sequence, and then stop the recording. Either way it should be easy to remap your bindings on the fly if you so desire, and you should never need to dip down into a menu system or put special inscriptions on your equipment.

          Comment

          • LostTemplar
            Knight
            • Aug 2009
            • 670

            #65
            Yes, "remember my last move and bind it to that key" will work. However it still may be good to make "do an action" and "collect information for an action" as different elementary calls to the game engine from UI.

            Comment

            • buzzkill
              Prophet
              • May 2008
              • 2939

              #66
              I like where LostTemplar is going with this.

              One keypress to select a "default" ammo, independent of the fire command. there could possibly be 2 defaults, one of firing and one for throwing.

              One keypress to select a "default" target, also independent of the fire command. Could be a particular direction, or grid, or enemy, or something more exotic offered by the game such as the oft used nearest enemy, or most/least healthy enemy, maybe even the enemy most venerable to the ammo/launcher combo.

              Then one could press 'f' to fire using the defaults, or 'F' to be re-prompted. Prompts would always be given if the previous default selection is invalid (out of ammo, no target in range, etc.)

              "Hey game, remember that action I just did, and bind it to this key."
              This is a no brainer.
              www.mediafire.com/buzzkill - Get your 32x32 tiles here. UT32 now compatible Ironband and Quickband 9/6/2012.
              My banding life on Buzzkill's ladder.

              Comment

              • ekolis
                Knight
                • Apr 2007
                • 921

                #67
                Derakon, I created a pull request with a (hopefully) more robust solution to the symbols-being-cut-off problem. For some reason it says it can't be merged into your repo, though, because of multiple heads... I don't see multiple heads on your repo, but maybe you'd know what to do about that!
                You read the scroll labeled NOBIMUS UPSCOTI...
                You are surrounded by a stasis field!
                The tengu tries to teleport, but fails!

                Comment

                • Derakon
                  Prophet
                  • Dec 2009
                  • 9022

                  #68
                  Awesome, thank you! I'll figure out how to get that pulled in later this afternoon. The multiple heads thing was a surprise to me; looks like waaaaay back in revision 12 I did something I decided was a bad idea, and when I backed out the revision I accidentally created an anonymous branch. So that's been lopped off and the pull request is happier now.

                  ...I got my first pull request for Pyrel!

                  Comment

                  • ekolis
                    Knight
                    • Apr 2007
                    • 921

                    #69
                    Hmm, did I merge wrong or is your latest code crashing with "ValueError: Too many values to unpack" in the creature factory?

                    edit: according to this article you can use .items() on a dict if it's too big to iterate, but that just gives me an error about the str type... are you passing in raw JSON strings to the creature factory without actually creating a dict out of them?
                    You read the scroll labeled NOBIMUS UPSCOTI...
                    You are surrounded by a stasis field!
                    The tengu tries to teleport, but fails!

                    Comment

                    • ekolis
                      Knight
                      • Apr 2007
                      • 921

                      #70
                      Man, I wish it was easier to sync the two repos... Bitbucket just tells me what commands to run, but even with that, I have to chop off the stupid $ prompt at the beginning of each line, and then also push back to my own repo on Bitbucket from my local repo! Surely they could have something that automated all that entirely on their servers...

                      ...hmm, I wonder, maybe I can run hg commands against the Bitbucket repos somehow, instead of against my own? Then I could automate it...
                      You read the scroll labeled NOBIMUS UPSCOTI...
                      You are surrounded by a stasis field!
                      The tengu tries to teleport, but fails!

                      Comment

                      • Derakon
                        Prophet
                        • Dec 2009
                        • 9022

                        #71
                        Can you get me a traceback on that error? I'm not able to reproduce it. It's probably caused by trying to iterate directly over a dict instead of iterating over dict.items() or dict.iteritems().

                        dict.items() generates a list of (key, value) tuples. That's fine and all, but for iterating, you actually want to get into the habit of using dict.iteritems(). The difference is that the first one generates the entire list all at once, while the second one only generates tuples as you need them, so it saves a bit on memory. Similarly, it's better to use xrange() for iterating over numbers than using range(). Honestly it's a subtle thing and unlikely to ever make a serious difference in your code performance, but it's a good habit.

                        Comment

                        • Magnate
                          Angband Devteam member
                          • May 2007
                          • 5110

                          #72
                          Originally posted by Derakon
                          ...I got my first pull request for Pyrel!
                          ... applause ...!
                          "Been away so long I hardly knew the place, gee it's good to be back home" - The Beatles

                          Comment

                          • ekolis
                            Knight
                            • Apr 2007
                            • 921

                            #73
                            Sure

                            Traceback (most recent call last):
                            File "C:\Users\Ed\Documents\pyrel\pyrel.py", line 18, in <module>
                            gui.init()
                            File "C:\Users\Ed\Documents\pyrel\gui\__init__.py", line 50, in init
                            guiPackage.init()
                            File "C:\Users\Ed\Documents\pyrel\gui\wxPyrel\__init__. py", line 3, in init
                            import mainApp
                            File "C:\Users\Ed\Documents\pyrel\gui\wxPyrel\mainApp.p y", line 6, in <module>
                            import mapgen.gameMap
                            File "C:\Users\Ed\Documents\pyrel\mapgen\__init__.p y", line 2, in <module>
                            import gameMap
                            File "C:\Users\Ed\Documents\pyrel\mapgen\gameMap.py ", line 6, in <module>
                            import mapgen.generator
                            File "C:\Users\Ed\Documents\pyrel\mapgen\generator. py", line 12, in <module>
                            import things.creatures.creatureLoader
                            File "C:\Users\Ed\Documents\pyrel\things\creatures\crea tureLoader.py", line 45, in <module>
                            loadFile(os.path.join('data', 'creature_template.txt'), TEMPLATE_NAME_MAP, True)
                            File "C:\Users\Ed\Documents\pyrel\things\creatures\crea tureLoader.py", line 38, in loadFile
                            factory = creatureFactory.CreatureFactory(record, isTemplate = isTemplate)
                            File "C:\Users\Ed\Documents\pyrel\things\creatures\crea tureFactory.py", line 76, in __init__
                            for key, value in record:
                            ValueError: too many values to unpack
                            I did notice that for some reason there's a jsonCreature.txt and a jsonTemplate.txt in the pyrel root folder, both of which are unversioned. I don't know if this is some sort of debugging mechanism you put in (dump the file that caused the error) or if it's actually *causing* the error (maybe these files override other files in the data folder?) or if you just left in some extra logging somewhere that dumps stuff to text files in the current directory!

                            It's funny, though, it took me a bit to get used to reading Python error dumps, since they seem to list the call stack in the reverse order of the way that C# does!
                            You read the scroll labeled NOBIMUS UPSCOTI...
                            You are surrounded by a stasis field!
                            The tengu tries to teleport, but fails!

                            Comment

                            • Derakon
                              Prophet
                              • Dec 2009
                              • 9022

                              #74
                              Hm, that's odd. Seems like there must be something wrong with creature_template.txt; it's valid JSON (or else json.load() wouldn't work), but at least one of the records isn't a key/value sequence (probably just a list or a single item instead), so when CreatureFactory tries to iterate over the keys and values, it gets an exception. And yes, CreatureFactory operates on "raw" JSON constructs; among other things, it makes re-serializing the records later easier if I have the original copy lying around. I also have visions of an in-game creature editor that would operate on those records.

                              jsonCreature.txt and jsonTemplate.txt are just redumps of some files from the data directory. I generate them when I need to programmatically fix some aspect of the files. For example, somehow all of the mushrooms ended up being black instead of having the "flavor" color (meaning they should take their coloration from their flavor), so I loaded object.txt, tweaked the records for mushrooms, then serialized every ItemFactory back to JSON to make jsonItems.txt, which I manually copy over data/object.txt.

                              Because the loader operates on a hardcoded path, these redump files should never be loaded accidentally. That said, I generally leave the "generate redump" code commented out (it's the last line or two of each fooLoader.py file), so I'm surprised you're getting those files. What revision are you on? Try modifying util/record.py like so:
                              Code:
                              def loadRecords(filePath, classType, *args, **kwargs):
                                  filehandle = open(filePath, 'r')
                                  records = json.load(filehandle)
                                  result = []
                                  for i, record in enumerate(records):
                                      try:
                                          result.append(classType(record, *args, **kwargs))
                                      except Exception, e:
                                          print "Failed to load record %d: %s" % (i, e)
                                          raise e
                                  filehandle.close()
                                  return result

                              Comment

                              • AnonymousHero
                                Veteran
                                • Jun 2007
                                • 1393

                                #75
                                Originally posted by Derakon
                                Can you get me a traceback on that error? I'm not able to reproduce it. It's probably caused by trying to iterate directly over a dict instead of iterating over dict.items() or dict.iteritems().

                                dict.items() generates a list of (key, value) tuples. That's fine and all, but for iterating, you actually want to get into the habit of using dict.iteritems(). The difference is that the first one generates the entire list all at once, while the second one only generates tuples as you need them, so it saves a bit on memory. Similarly, it's better to use xrange() for iterating over numbers than using range(). Honestly it's a subtle thing and unlikely to ever make a serious difference in your code performance, but it's a good habit.
                                This used to be the case, but isn't any longer. Range() is exactly equivalent to xrange() these days.

                                Comment

                                Working...
                                😀
                                😂
                                🥰
                                😘
                                🤢
                                😎
                                😞
                                😡
                                👍
                                👎