0

I don't like how ugly long if/elif statements look. And switch/case statements aren't much better. I find dictionaries easier to read. Now I know how to handle it if each key binding goes to a different function, that's easy. But that would require 8 different move functions (moveNE, moveN, moveNW, etc, etc, etc). So I want to have a simple move_object function that takes a direction as an argument. But, I'm having problems getting this code to work and I'm not sure what I'm doing wrong. Here's the code in question.

First, the dictionary:

self.keybindings = {ord("h"): {"function":self.move_object, 
                               "args":{"thing":self.things[0], "direction":"North"}},
                    ord('j'): {"function":self.move_object,
                               "args":{"thing":self.things[0], "direction":"South"}},
                    ord('g'): {"function":self.move_object,
                               "args":{"thing":self.things[0], "direction":"East"}},
                    ord('k'): {"function":self.move_object,
                               "args":{"thing":self.things[0], "direction":"West"}},
                    ord('y'): {"function":self.move_object,
                               "args":{"thing":self.things[0], "direction":"NorthWest"}},
                    ord('u'): {"function":self.move_object,
                               "args":{"thing":self.things[0], "direction":"NorthEast"}},
                    ord('b'): {"function":self.move_object,
                               "args":{"thing":self.things[0], "direction":"SouthWest"}},
                    ord('n'): {"function":self.move_object,
                               "args":{"thing":self.things[0], "direction":"SouthEast"}},
                    ord('l'): {"function":self.look, "args":{"thing":self.things[0],}},
                    ord('q'): {"function":self.save_game,
                              "args":{"placeholder":0}}}

Now, the move_object function:

def move_object(self, thing, direction): 
"""I chose to let the Game class handle redraws instead of objects.
I did this because it will make it easier should I ever attempt to rewrite
this with libtcod, pygcurses, or even some sort of browser-based thing.
Display is cleanly separated from obects and map data.
Objects use the variable name "thing" to avoid namespace collision."""
curx = keywords[thing].x
cury = keywords[thing].y
newy = keywords[thing].y + directions[keywords[direction]][0]
newx = thing.x + directions[keywords[direction]][1]
if not self.is_blocked(newx, newy):
  logging.info("Not blocked")
  keywords[thing].x = newx
  keywords[thing].y = newy

And finally, the code that should call the move_object function:

 c = self.main.getch()
  try:
    self.keybindings[c]["function"](self.keybindings[c]["args"])
  except KeyError:
    pass

The keybindings are defined in the Game Class init function and the final block of code occurs within Game.main_loop()

I've read the tutorials several times and I can't figure out what I'm doing wrong. I thought that what I have here would pass the args dictionary as **keywords into the move_object() function, but its giving me an argument error (expected 2 arguments, received 1).

Jonathanb
  • 1,224
  • 1
  • 11
  • 16
  • You could just use [`functools.partial`](https://docs.python.org/3/library/functools.html#functools.partial). As it stands, you're simply missing `**` and passing a dictionary as a single positional argument, rather than unpacking it to multiple keyword arguments. – jonrsharpe Jun 22 '16 at 13:06
  • Where would I put the **? Like this self.keybindings[c]["function"](**self.keybindings[c]["args"]) – Jonathanb Jun 22 '16 at 13:10

0 Answers0