OO and game design questions

J

Jonathan Hartley

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

Mr. Roy Smith already proposed using closures. I already did a similar
thing in my code, but instead of decrease_hp() I have AttributeEffect
class which is able to modify any attribute (in old RPGs some monsters
could drain your intelligence, in my game laser gun hit will decrease
HP as well as armor integrity). The first version looks like this
(missing few checks):

class AttributeEffect(object):
    '''Effect changes object's attribute by delta'''
    def __init__(self, obj, attrib, delta):
        self.obj = obj               # reference to object the effect
applies to
        self.attrib = attrib         # name of attribute that effect
applies to
        self.delta = delta           # change of value for
object.attribute
    def apply(self):
        value = getattr(self.obj, self.attrib) # todo: try, except
        value += self.delta
        setattr(self.obj(), self.attrib, value)

Yesterday I learned that Python 3.0 introduces nonlocal keyword which
would simplify defining effect functions and passing them along. Nice
improvement.


Very cool, that looks like it would work. The thing I like about the
lambda idea though, is that you don't have to write any classes like
AttributeEffect, (and presumably other such classes, like
LoseItemEffect, etc.) Instead of *modelling* the different kind of
effects that could happen, you just write code that *performs* the
desired effect. (e.g. monster.hp -= damage) To my eyes, lambda's are
therefore more flexible and require less code. But I could be wrong,
and obviously you should do what you think is best for your
circumstances. Very best of luck with it.

Out of interest, is there anywhere you blog about the game
development, or are likely to make announcements?

Jonathan Hartley
 
J

Jonathan Hartley

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

Mr. Roy Smith already proposed using closures. I already did a similar
thing in my code, but instead of decrease_hp() I have AttributeEffect
class which is able to modify any attribute (in old RPGs some monsters
could drain your intelligence, in my game laser gun hit will decrease
HP as well as armor integrity). The first version looks like this
(missing few checks):

class AttributeEffect(object):
    '''Effect changes object's attribute by delta'''
    def __init__(self, obj, attrib, delta):
        self.obj = obj               # reference to object the effect
applies to
        self.attrib = attrib         # name of attribute that effect
applies to
        self.delta = delta           # change of value for
object.attribute
    def apply(self):
        value = getattr(self.obj, self.attrib) # todo: try, except
        value += self.delta
        setattr(self.obj(), self.attrib, value)

Yesterday I learned that Python 3.0 introduces nonlocal keyword which
would simplify defining effect functions and passing them along. Nice
improvement.


Very cool, that looks like it would work. The thing I like about the
lambda idea though, is that you don't have to write any classes like
AttributeEffect, (and presumably other such classes, like
LoseItemEffect, etc.) Instead of *modelling* the different kind of
effects that could happen, you just write code that *performs* the
desired effect. (e.g. monster.hp -= damage) To my eyes, lambda's are
therefore more flexible and require less code. But I could be wrong,
and obviously you should do what you think is best for your
circumstances. Very best of luck with it.

Out of interest, is there anywhere you blog about the game
development, or are likely to make announcements?

Jonathan Hartley
 
J

Jonathan Hartley

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

Mr. Roy Smith already proposed using closures. I already did a similar
thing in my code, but instead of decrease_hp() I have AttributeEffect
class which is able to modify any attribute (in old RPGs some monsters
could drain your intelligence, in my game laser gun hit will decrease
HP as well as armor integrity). The first version looks like this
(missing few checks):

class AttributeEffect(object):
    '''Effect changes object's attribute by delta'''
    def __init__(self, obj, attrib, delta):
        self.obj = obj               # reference to object the effect
applies to
        self.attrib = attrib         # name of attribute that effect
applies to
        self.delta = delta           # change of value for
object.attribute
    def apply(self):
        value = getattr(self.obj, self.attrib) # todo: try, except
        value += self.delta
        setattr(self.obj(), self.attrib, value)

Yesterday I learned that Python 3.0 introduces nonlocal keyword which
would simplify defining effect functions and passing them along. Nice
improvement.


Very cool, that looks like it would work. The thing I like about the
lambda idea though, is that you don't have to write any classes like
AttributeEffect, (and presumably other such classes, like
LoseItemEffect, etc.) Instead of *modelling* the different kind of
effects that could happen, you just write code that *performs* the
desired effect. (e.g. monster.hp -= damage) To my eyes, lambda's are
therefore more flexible and require less code. But I could be wrong,
and obviously you should do what you think is best for your
circumstances. Very best of luck with it.

Out of interest, is there anywhere you blog about the game
development, or are likely to make announcements?

Jonathan Hartley
 
G

Gregory Ewing

Jonathan said:
One common way to store delayed actions is as a lambda (an anonymous
function.)

Although note that you don't have to use 'lambda' in
particular -- functions defined with 'def' can be used
the same way.
 
A

Aahz

I think a 'place' (to generalise it) is quite a small object in any case.
All it needs to contain is a few lists:
- a list of exits, which in some implementations might be simply
references to other places, but might usefully be objects with
two sides, each having an appearance and a link to the place
where that side appears.
- a list of fixed objects which only serve to describe the place.
- a list of mobile objects that actors can pick up and move
- a list of actors who happen to be there.

plus a describePlace() method and add(), remove() and getItem() methods
for each list. It may be possible to use a single list for all types of
object, in which case the object itself would be very small indeed.

Maybe you want a rule-based approach:

http://eblong.com/zarf/essays/rule-based-if/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top