[Tutor] TypeError: unhashable type: 'pygame.math.Vector2'

dn PyTutor at danceswithmice.info
Fri Jun 26 20:12:54 EDT 2020


On 27/06/20 2:25 AM, Cravan wrote:
> Sadly, an error pops up when I change the code.
> Here's my edited code for the class file:
> ````
> class Zomb(pg.sprite.Sprite):
>      def __init__(self, game, x, y):
>          self.groups = game.all_sprites, game.zombs
>          pg.sprite.Sprite.__init__(self, self.groups)
>          self.game = game
>          self.image = game.zomb_img
>          self.rect = self.image.get_rect()
>          #image = image provided in game
>          self.x = x
>          self.y = y
>          self.pos = (x, y)
>          #this is each state
>          #possible states
>          for a in range(int(GRIDWIDTH)):
>              for b in range(int(GRIDHEIGHT)):
>                  self.stateSpace = [(a,b)]
>          self.actionSpace = {'U': - 1, 'D': 1,
>                              'L': - 1, 'R': 1}
>          #corresponding adjustments
>          self.possibleActions = ['U', 'D', 'L', 'R']
>          #list of possible actions
>          self.vel = 0
>          self.acc = 0
>          self.rect.center = vec(self.x, self.y)
>          self.rotate = 0
> 
>      def setState(self, state):
>          self.pos = state
> 
>      def TerminalState(self, state):
>          if self.game.health == 0:
>              return True
>          else:
>              return False
> 
>      def step(self, action):
>          x, y = self.x, self.y
>          if self.actionSpace[action] == 'U':
>              self.y = self.y + 1
>          elif self.actionSpace[action] == 'D':
>              self.y = self.y - 1
>          elif self.actionSpace[action] == 'R':
>              self.x = self.x + 1
>          elif self.actionSpace[action] == 'L':
>              self.x = self.x - 1
>          resultingState = (self.x, self.y)
>          self.game.reward = -1 if not self.TerminalState(resultingState) else 0
>          self.setState(resultingState)
> 
> 
>          return resultingState, self.game.reward,\
>              self.TerminalState(resultingState), None
> 
>      def actionSpaceSample(self):
>          return np.random.choice(self.possibleActions)
> 
>      def update(self):
>          self.rotate = (self.game.player.pos - self.rect.center).angle_to(vec(1, 0))
>          self.image = self.game.zomb_img
>          self.rect = self.image.get_rect()
>          self.acc = vec(ZOMB_SPEED, 0).rotate(-self.rotate)
> ````
> And here's my edited main implementation now in the update() function:
> ```
> ALPHA = 0.1
>          GAMMA = 1.0
>          EPS = 1.0
>          Q = {}
> 
>          for zomb in self.zombs:
>              print(zomb.stateSpace)
>              for state in zomb.stateSpace:
>                  for action in zomb.possibleActions:
>                      Q[state, action] = 0
>          numGames = 10
>          totalRewards = np.zeros(numGames)
>          for i in range(numGames):
> 
>              print('starting game ', i + 1)
>              epRewards = 0
> 
>          rand = np.random.random()
>          for zomb in self.zombs:
>              observation = zomb.pos
>              #state
>              action = maxAction(Q, observation, zomb.possibleActions) if rand < (1-EPS) \
>                                                          else zomb.actionSpaceSample()
>              #choosing the best action possible
> 
>              observationnew, reward, done, info = zomb.step(action)
>          epRewards += reward
> 
>          for zomb in self.zombs:
>              possible_actions = zomb.possibleActions
>              action_ = maxAction(Q, observationnew, possible_actions)
> 
>          Q[observation,action] = Q[observation,action] + ALPHA*(reward + \
>                      GAMMA*Q[observationnew,action_] - Q[observation,action])
>          observation = observationnew
>          if EPS - 2 / numGames > 0:
>              EPS -= 2 / numGames
>          else:
>              EPS = 0
>          totalRewards[i] = epRewards
> ```
> However, this error pops up:
> #######
> Traceback (most recent call last):
>    File "maze.py", line 181, in <module>
>      g.run()
>    File "maze.py", line 53, in run
>      self.update()
>    File "maze.py", line 109, in update
>      action_ = maxAction(Q, observationnew, possible_actions)
>    File "maze.py", line 177, in maxAction
>      values = np.array([Q[state,a] for a in actions])
>    File "maze.py", line 177, in <listcomp>
>      values = np.array([Q[state,a] for a in actions])
> KeyError: ((6, 26), 'U')
> ######


It may be worth taking a step-back - both in terms of the design you are 
implementing and the questions you are asking of us:-

Have looked and looked, and then used 'find', but failed to find the 
code-line at-error. Why? [help us to help you!]

Aside from learning Python's idioms, are you using a competent IDE? 
Could you then use full-names instead of abbreviations, without adding 
major effort? I think we could guess what a "zomb" is, but would it be 
better (and kinder) to remove all doubt?

Have comments and "docstrings" (a pythonic idiom) been used to describe 
what the code/each function is supposed to do, and why?

If the game's environment is described as a "grid", why is its width and 
height described using anything other than int[eger]s?

What is the purpose of "state"? Is there a difference between "state" 
and "position" (or next-/previous-position)?

Have you understood the (animation) concept of collision? (assuming that 
is part of the intent here) Have you noted various algorithms and 
approximations which are commonly-used?
-- 
Regards =dn


More information about the Tutor mailing list