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).