OO and game design questions

Jonathan Hartley tartley at tartley.com
Wed Oct 20 06:25:55 EDT 2010


On Oct 18, 8:28 am, dex <josipmisko... at gmail.com> wrote:
> I'm building a turn based RPG game as a hobby. The design is becoming
> increasingly complicated and confusing, and I think I may have
> tendency to over-engineer simple things. Can anybody please check my
> problems-solutions and point me to more elegant solution?
>
> Every item/character/room is a separate object. Items/characters need
> to have references to room they are in, and room needs to have a list
> of references to items/characters that are contained within. I decided
> to use weak references. That way I can destroy object by deleting it,
> I don't have to destroy all references as well. In each object's
> __init__() that object is added to game_object list, and in each
> __del__() they are removed from game_object list. This mechanism keeps
> them safe from garbage collector. How pythonic is this design?
>
> In turn-based games, the order of action execution in battle can give
> unfair advantage to players. For example, if player's arm is crippled
> before his action is executed, he would do less damage. To offset
> this, I first execute all players' actions and calculate effects in
> first pass, then apply the effects in second pass. The effect can be
> health decrease by 15HP, item pick-up, 30p experience gain, etc. This
> means the player deals the same amount of damage no matter what
> happens to him in that turn. The difficult part is keeping track of
> various effects. I had to make separate class for various types of
> effects (ChangeAttributeEffect, GetItemEffect, LooseItemEffect). Each
> class stores weak reference to target object and has apply() method
> that applies the effect to object. I'm not satisfied with this as it's
> limiting, error-prone and uses metaprogramming. Is there a design
> pattern that would remember changes to an object, and apply them
> later?
>
> Sorry for the wall of text.


One common way to store delayed actions is as a lambda (an anonymous
function.) A lambda defines a new function:


, and you can call this function later. The created function has no
name, (but you can assign it to a variable to give it a name if you
like) and can be called later:



So in the game, you could have a collection 'effects', each one will
be a lambda:

  effects = []

At the start of the round, as each entity makes its moves, they add
lambdas to this collection.

  effects.append(
      lambda: decrease_hp(monster_a, 4)
  )
  effects.append(
      lambda: lose_item(monster_a, item_b)
  )

Instead of appending it directly like this, I imagine the lambdas
could be returned by the monster's 'act' or 'update' method:

  class Monster():
    def act(self):
      # blah and finally
      return lambda: decrease_hp(monster_a, 4)

Then for the start of a round, first you ask each monster what action
it is going to perform:

  for monster in room.monsters:
      effects.append(
          monster.act()
      )

Then for the end of the round, call all the lambdas

  for effect in effects:
      effect()



More information about the Python-list mailing list