Skip to main content
Code Review

Return to Question

Commonmark migration
Source Link
  1. As the size of the dictionary grows I intend to keep use a bzipped and pickled version of it, created once and updated in case of changes to the JSON/dictionary.

    As the size of the dictionary grows I intend to keep use a bzipped and pickled version of it, created once and updated in case of changes to the JSON/dictionary.

  2. This code does not reflect the actual main structure of the game but tries to illustrate, through a working example, an approach specifically on how could weapons (and other items) be created based on dictionaries in a way that this data could provide conditional verifications and actions to interact dynamically with a huge combinations of race x attributes x features x classes behavior.

    This code does not reflect the actual main structure of the game but tries to illustrate, through a working example, an approach specifically on how could weapons (and other items) be created based on dictionaries in a way that this data could provide conditional verifications and actions to interact dynamically with a huge combinations of race x attributes x features x classes behavior.

    What is a weapon here is actually a component of a game object in the main code, and so is the player and other creatures. With that said, any specific comment on the main structure is still appreciated, but the main focus should be in the interaction between the Weapon class and the dictionary.

  3. The action "unholy area" of the weapon, in this specific example, would affect every neighbor square of the "owner" (I don't update the item position after someone picks it up, only when the item is dropped); other passive effects would do the same (heal the owner every turn, etc.). I could pass the owner to its equipment at every on_turn call but it sounded like such a waste;

  4. The _class variable holds a character class (such as Cleric, Rogue, etc.), not a Python class.

What is a weapon here is actually a component of a game object in the main code, and so is the player and other creatures. With that said, any specific comment on the main structure is still appreciated, but the main focus should be in the interaction between the Weapon class and the dictionary. 3. The action "unholy area" of the weapon, in this specific example, would affect every neighbor square of the "owner" (I don't update the item position after someone picks it up, only when the item is dropped); other passive effects would do the same (heal the owner every turn, etc.). I could pass the owner to its equipment at every on_turn call but it sounded like such a waste; 4. The _class variable holds a character class (such as Cleric, Rogue, etc.), not a Python class.

  1. As the size of the dictionary grows I intend to keep use a bzipped and pickled version of it, created once and updated in case of changes to the JSON/dictionary.
  2. This code does not reflect the actual main structure of the game but tries to illustrate, through a working example, an approach specifically on how could weapons (and other items) be created based on dictionaries in a way that this data could provide conditional verifications and actions to interact dynamically with a huge combinations of race x attributes x features x classes behavior.

What is a weapon here is actually a component of a game object in the main code, and so is the player and other creatures. With that said, any specific comment on the main structure is still appreciated, but the main focus should be in the interaction between the Weapon class and the dictionary. 3. The action "unholy area" of the weapon, in this specific example, would affect every neighbor square of the "owner" (I don't update the item position after someone picks it up, only when the item is dropped); other passive effects would do the same (heal the owner every turn, etc.). I could pass the owner to its equipment at every on_turn call but it sounded like such a waste; 4. The _class variable holds a character class (such as Cleric, Rogue, etc.), not a Python class.

  1. As the size of the dictionary grows I intend to keep use a bzipped and pickled version of it, created once and updated in case of changes to the JSON/dictionary.

  2. This code does not reflect the actual main structure of the game but tries to illustrate, through a working example, an approach specifically on how could weapons (and other items) be created based on dictionaries in a way that this data could provide conditional verifications and actions to interact dynamically with a huge combinations of race x attributes x features x classes behavior.

    What is a weapon here is actually a component of a game object in the main code, and so is the player and other creatures. With that said, any specific comment on the main structure is still appreciated, but the main focus should be in the interaction between the Weapon class and the dictionary.

  3. The action "unholy area" of the weapon, in this specific example, would affect every neighbor square of the "owner" (I don't update the item position after someone picks it up, only when the item is dropped); other passive effects would do the same (heal the owner every turn, etc.). I could pass the owner to its equipment at every on_turn call but it sounded like such a waste;

  4. The _class variable holds a character class (such as Cleric, Rogue, etc.), not a Python class.

deleted 384 characters in body
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

In aan RPG game I'm developing, after building a base Weapon class, instead of having many subclasses of Weapon, I want the weapons to be built upon dictionary parameters. Many of them will be simple static information (weight, value, etc.), but others will have conditionally definedconditionally defined parameters, with not only numeric/textual values: they may have to call external methodsexternal methods, such as spell-like effect, feat, skill, combat maneuvers, etc.).

The number of items (that will share most of this Weapon example's design, once I'm done with it), eventually, should reach the hundredshundreds (the PRD rules I'm adapting to this game already provide a few hundred "basic items"), and allow the player to build new ones, both at runtime based on existing models (crafting) and pre-runtime (modding).

One weapon, for example, should change its stats and associated functions (spell-like effects) when equipped according to the wielder's class.

One weapon, for example, should change its stats and associated functions (spell-like effects) when equipped according to the wielder's class. But many more different conditions should be needed/used as I add fancy magic weapons, armors and items.

Below is a piece of code showing kind of how it works so far (a simplified, working version of my logic). Currently itThis currently relies on a few setattr and eval calls to handle strings from the dictionary.

I would like to hear suggestions on preferable approachespreferable approaches, concerning performance, security, etc.. Can it be significantly improvedsignificantly improved somehow? Readability (always) matters, any pythonist's approach, perhaps?.

  1. As the size of the dictionary grows I intend to keep use a bzipped and pickled version of it, created once and updated in case of changes to the JSON/dictionary.
  2. This code does not reflect the actual main structure of the game but tries to illustrate, through a working example, an approach specifically on how could weapons (and other items) be created based on dictionaries in a way that this data could provide conditional verifications and actions to interact dynamically with a huge combinations of race x attributes x features x classes behavior. What is a weapon here is actually a component of a game object in the main code, and so is the player and other creatures. With that said, any specific comment on the main structure is still appreciated, but the main focus should be in the interaction between the Weapon class and the dictionary.
  3. The item.owner = self doen't look too good, as cat said , but there are (many) cases where a component (item, ai, etc.) interact 'backwards' with its owner. The action "unholy area"This code does not reflect the actual main structure of the weapongame but tries to illustrate, in this specificthrough a working example, would affect every neighbor square of the "owner"an approach specifically on how could weapons (I don't update the item position after someone picks it up, only when the item is dropped);and other passive effects would do the same (heal the owner every turn, etc.items). I be created based on dictionaries in a way that this data could pass the ownerprovide conditional verifications and actions to its equipments at every on_turn call but it sounded like such a waste;
  4. The _class variable holds a character class (such as cleric, rogue, etc.), notinteract dynamically with a python classhuge combinations of race x attributes x features x classes behavior.

What is a weapon here is actually a component of a game object in the main code, and so is the player and other creatures. With that said, any specific comment on the main structure is still appreciated, but the main focus should be in the interaction between the Weapon class and the dictionary. 3. The action "unholy area" of the weapon, in this specific example, would affect every neighbor square of the "owner" (I don't update the item position after someone picks it up, only when the item is dropped); other passive effects would do the same (heal the owner every turn, etc.). I could pass the owner to its equipment at every on_turn call but it sounded like such a waste; 4. The _class variable holds a character class (such as Cleric, Rogue, etc.), not a Python class.

In a RPG game I'm developing, after building a base Weapon class, instead of having many subclasses of Weapon, I want the weapons to be built upon dictionary parameters. Many of them will be simple static information (weight, value, etc.), but others will have conditionally defined parameters, with not only numeric/textual values: they may have to call external methods, such as spell-like effect, feat, skill, combat maneuvers, etc.).

The number of items (that will share most of this Weapon example's design, once I'm done with it), eventually, should reach the hundreds (the PRD rules I'm adapting to this game already provide a few hundred "basic items"), and allow the player to build new ones, both at runtime based on existing models (crafting) and pre-runtime (modding).

One weapon, for example, should change its stats and associated functions (spell-like effects) when equipped according to the wielder's class.

But many more different conditions should be needed/used as I add fancy magic weapons, armors and items.

Below is a piece of code showing kind of how it works so far (a simplified, working version of my logic). Currently it relies on a few setattr and eval calls to handle strings from the dictionary.

I would like to hear suggestions on preferable approaches, concerning performance, security, etc.. Can it be significantly improved somehow? Readability (always) matters, any pythonist's approach, perhaps?

  1. As the size of the dictionary grows I intend to keep use a bzipped and pickled version of it, created once and updated in case of changes to the JSON/dictionary.
  2. This code does not reflect the actual main structure of the game but tries to illustrate, through a working example, an approach specifically on how could weapons (and other items) be created based on dictionaries in a way that this data could provide conditional verifications and actions to interact dynamically with a huge combinations of race x attributes x features x classes behavior. What is a weapon here is actually a component of a game object in the main code, and so is the player and other creatures. With that said, any specific comment on the main structure is still appreciated, but the main focus should be in the interaction between the Weapon class and the dictionary.
  3. The item.owner = self doen't look too good, as cat said , but there are (many) cases where a component (item, ai, etc.) interact 'backwards' with its owner. The action "unholy area" of the weapon, in this specific example, would affect every neighbor square of the "owner" (I don't update the item position after someone picks it up, only when the item is dropped); other passive effects would do the same (heal the owner every turn, etc.). I could pass the owner to its equipments at every on_turn call but it sounded like such a waste;
  4. The _class variable holds a character class (such as cleric, rogue, etc.), not a python class.

In an RPG game I'm developing, after building a base Weapon class, instead of having many subclasses of Weapon, I want the weapons to be built upon dictionary parameters. Many of them will be simple static information (weight, value, etc.), but others will have conditionally defined parameters, with not only numeric/textual values: they may have to call external methods, such as spell-like effect, feat, skill, combat maneuvers, etc.).

The number of items (that will share most of this Weapon example's design, once I'm done with it), eventually, should reach the hundreds (the PRD rules I'm adapting to this game already provide a few hundred "basic items"), and allow the player to build new ones, both at runtime based on existing models (crafting) and pre-runtime (modding).

One weapon, for example, should change its stats and associated functions (spell-like effects) when equipped according to the wielder's class. But many more different conditions should be needed/used as I add fancy magic weapons, armors and items.

This currently relies on a few setattr and eval calls to handle strings from the dictionary. I would like to hear suggestions on preferable approaches, concerning performance, security, etc.. Can it be significantly improved somehow? Readability (always) matters.

  1. As the size of the dictionary grows I intend to keep use a bzipped and pickled version of it, created once and updated in case of changes to the JSON/dictionary.
  2. This code does not reflect the actual main structure of the game but tries to illustrate, through a working example, an approach specifically on how could weapons (and other items) be created based on dictionaries in a way that this data could provide conditional verifications and actions to interact dynamically with a huge combinations of race x attributes x features x classes behavior.

What is a weapon here is actually a component of a game object in the main code, and so is the player and other creatures. With that said, any specific comment on the main structure is still appreciated, but the main focus should be in the interaction between the Weapon class and the dictionary. 3. The action "unholy area" of the weapon, in this specific example, would affect every neighbor square of the "owner" (I don't update the item position after someone picks it up, only when the item is dropped); other passive effects would do the same (heal the owner every turn, etc.). I could pass the owner to its equipment at every on_turn call but it sounded like such a waste; 4. The _class variable holds a character class (such as Cleric, Rogue, etc.), not a Python class.

Tweeted twitter.com/StackCodeReview/status/694824126737944576
Rollback to Revision 5
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

The code belowBelow is the result of some editing based on the suggestions/answers received, a piece of code showing kind of how it works so far (a simplified, working version of my logic). Currently it relies on a specific part offew setattr and eval calls to handle strings from the game logicdictionary.

I would like to hear suggestions on Suggestions concerning the dictionary handling and the conditional setting of the Weapon class parameters could still be usedpreferable approaches, concerning performance, security, etc.. Can it be significantly improved somehow? Readability (always) matters, any pythonist's approach, perhaps?

"""A# A design test for dynamic class building."""
# > attributes and conditional logic are readed from a dictionary.
# This dictionary will actually reside in another file, maybe a json or
# gzipped pickled json...
# Attributes and conditional logic relative to the items are readed from it.
WEAPONS = {
 "bastard's sting": {
 "equipped": False,
 "magic": 2,
 "on_turn_actions": [],
 "on_hit_actions": [],
 "on_equip": [
 {
 "type": "check",
 "condition": {
 'object': 'owner',(
 'attribute': 'char_class'"self.owner.is_of_class",
 'value': "antipaladin"["antipaladin"]
 }),
 True: [
 {
 "type": "action",
 "action": "add_to""self.add_on_hit",
 "args": {
 "category": "on_hit",
  "actions": ["unholy"]
 }
 },
 {
 "type": "action",
 "action": "add_to""self.add_on_turn",
 "args": {
 "category": "on_turn",
  "actions": ["unholy aurea"]
 }
 },
 {
 "type": "action",
 "action": "set_attribute""self.set_attribute",
 "args": {
  "field": "magic"["magic", "value": 5
 }5]
 }
 ],
 False: [
 {
 "type": "action",
 "action": "set_attribute""self.set_attribute",
 "args": {
  "field": "magic"["magic", "value": 2
 }2]
 }
 ]
 }
 ],
 "on_unequip": [
 {
 "type": "action",
 "action": "remove_from""self.rem_on_hit",
 "args": {
 "category": "on_hit",
 "actions": ["unholy"]
 },
 },
 {
 "type": "action",
 "action": "remove_from""self.rem_on_turn",
 "args": {
 "category": "on_turn",
 "actions": ["unholy aurea"]
 },["unholy_aurea"]
 },
 {
 "type": "action",
 "action": "set_attribute""self.set_attribute",
 "args": ["magic"["self.magic", 2]
 }
 ]
 }
}
class Player:
 """Represents the player character."""

 inventory = []
 def __init__(self, char_class_class):
 """For this example, we just store the class on the instance."""
 self.char_class_class = char_class_class
 def pick_up(self, item):
 """Pick an object, put in inventory, set its owner."""
 self.inventory.append(item)
 item.owner = self

 def is_of_class(self, _class):
 """Checks for the Character _class, not a python `class`"""
 return self._class == _class

class Weapon:
 """An type of item that can be equipped/used to attack."""
 equipped = False
 action_lists = {
 "on_hit": "on_hit_actions",
 "on_turn": "on_turn_actions",
 }
 def __init__(self, template):
 """Set the parameters based on a template."""
 self.__dict__.update(WEAPONS[template])
 def toggle_equipequip(self):
 """Set item status and call its on equip/unequip functions."""
 if self.equipped:
 = True
 for action in self.equipped = Falseon_equip:
 actionsif =action['type'] self.on_unequip== "check":
 else: self.check(action)
 self.equippedelif =action['type'] True== "action":
 actions = self.on_equipaction(action)
 def unequip(self):
  """Unset item dynamic status, call its on unequip functions."""
 self.equipped = False
 for action in actionsself.on_unequip:
 if action['type'] == "check":
 self.check(action)
 elif action['type'] == "action":
 self.action(action)
 def check(self, dic):
 """Check a condition and call an action according to it."""
 obj = getattr(self, dic['condition']['object'])
 compared_attcheck_act = getattreval(obj, dic['condition']['attribute']dic['condition'][0])
 valueargs = dic['condition']['value']dic['condition'][1]
 result = compared_att == valuecheck_act(*args)
 self.action(*dic[result])
 def action(self, *dicts):
 """Perform action with args, both specified on dicts."""
 for dic in dicts:
 act = getattreval(self, dic['action'])
 args = dic['args']
 if isinstance(args, list):
 act(*args)
 elif isinstance(args, dict):
 act(**args)
 def set_attribute(self, field, value):
 """Set the specified field with the given value."""
 setattr(self, field, valuedic['args'])
 def add_toset_attribute(self, category, actionsargs):
 """Add one or more actions toname, thevalue category's= list."""args
 action_list = getattrsetattr(self, self.action_lists[category]name, value)
 def add_on_hit(self, actions):
 for action in actions:
 if action not in action_listself.on_hit_actions:
 action_listself.on_hit_actions.append(action)
 def remove_fromadd_on_turn(self, category, actions):
 """Remove onefor oraction morein actions:
 from the category's list if action not in self."""on_turn_actions:
 action_list = self.action_lists[category]on_turn_actions.append(action)
 def rem_on_hit(self, actions):
 for action in actions:
 if action in action_listtry:
 action_listself.on_hit_actions.remove(action)
 except ValueError:
 # We never had that but unequip tries to clean it anyway.
 pass
 def rem_on_turn(self, actions):
 for action in actions:
 try:
 self.on_turn_actions.remove(action)
 except ValueError:
 pass

defif test()__name__ == '__main__':
 """A simple"""Let's test. it!"""
 Item features should be printed differently for each player.
 """
 weapon = Weapon("bastard's sting")
 player1 = Player("paladin")
 player1.pick_up(weapon)
 weapon.toggle_equipequip()
 print("Enhancement: {}, Hit effects: {}, Other effects: {}".format(
 weapon.magic, weapon.on_hit_actions, weapon.on_turn_actions))
 weapon.toggle_equipunequip()
 player2 = Player("antipaladin")
 player2.pick_up(weapon)
 weapon.toggle_equipequip()
 print("Enhancement: {}, Hit effects: {}, Other effects: {}".format(
 weapon.magic, weapon.on_hit_actions, weapon.on_turn_actions))

if __name__ == '__main__':
 test()
  1. As the size of the dictionary grows I intend to keep use a bzipped and pickled version of it, created once and updated in case of changes to the JSON/dictionary.
  2. This code does not reflect the actual main structure of the game but tries to illustrate, through a working example, an approach specifically on how could weapons (and other items) could be created based on dictionaries in a way that this data could provide conditional verifications and actions to interact dynamically with a huge combinations of race x attributes x features x classes behavior. What is a weapon here is actually a component of a game object in the main code, and so areis the player and other creatures. With that said, any specific comment on the main structure is still appreciated, but the main focus should be in the interaction between the Weapon class and the dictionary.
  3. The item.owner = self doen't look too good, as cat said, but there are (many) cases where a component (item, ai, etc.) interact 'backwards' with its owner. The action "unholy area" of the weapon, in this specific example, would affect every neighbor square of the "owner" (I don't update the item position after someone picks it up, only when the item is dropped); other passive effects would do the same (heal the owner every turn, etc.). I could pass the owner to its equipments at every on_turn call but it sounded like such a wastewaste;
  4. The _class variable holds a character class (such as cleric, rogue, etc.), not a python class.

Edited to reflect most of cat's suggestions / accepted answer.

The code below is the result of some editing based on the suggestions/answers received, a simplified, working version of a specific part of the game logic.

Suggestions concerning the dictionary handling and the conditional setting of the Weapon class parameters could still be used.

"""A design test for dynamic class building."""
# This dictionary will actually reside in another file, maybe a json or
# gzipped pickled json...
# Attributes and conditional logic relative to the items are readed from it.
WEAPONS = {
 "bastard's sting": {
 "magic": 2,
 "on_turn_actions": [],
 "on_hit_actions": [],
 "on_equip": [
 {
 "type": "check",
 "condition": {
 'object': 'owner',
 'attribute': 'char_class',
 'value': "antipaladin"
 },
 True: [
 {
 "type": "action",
 "action": "add_to",
 "args": {
 "category": "on_hit",
  "actions": ["unholy"]
 }
 },
 {
 "type": "action",
 "action": "add_to",
 "args": {
 "category": "on_turn",
  "actions": ["unholy aurea"]
 }
 },
 {
 "type": "action",
 "action": "set_attribute",
 "args": {
  "field": "magic", "value": 5
 }
 }
 ],
 False: [
 {
 "type": "action",
 "action": "set_attribute",
 "args": {
  "field": "magic", "value": 2
 }
 }
 ]
 }
 ],
 "on_unequip": [
 {
 "type": "action",
 "action": "remove_from",
 "args": {
 "category": "on_hit",
 "actions": ["unholy"]
 },
 },
 {
 "type": "action",
 "action": "remove_from",
 "args": {
 "category": "on_turn",
 "actions": ["unholy aurea"]
 },
 },
 {
 "type": "action",
 "action": "set_attribute",
 "args": ["magic", 2]
 }
 ]
 }
}
class Player:
 """Represents the player character."""

 inventory = []
 def __init__(self, char_class):
 """For this example, we just store the class on the instance."""
 self.char_class = char_class
 def pick_up(self, item):
 """Pick an object, put in inventory, set its owner."""
 self.inventory.append(item)
 item.owner = self
class Weapon:
 """An type of item that can be equipped/used to attack."""
 equipped = False
 action_lists = {
 "on_hit": "on_hit_actions",
 "on_turn": "on_turn_actions",
 }
 def __init__(self, template):
 """Set the parameters based on a template."""
 self.__dict__.update(WEAPONS[template])
 def toggle_equip(self):
 """Set item status and call its equip/unequip functions."""
 if self.equipped:
 self.equipped = False
 actions = self.on_unequip
 else:
 self.equipped = True
 actions = self.on_equip
 for action in actions:
 if action['type'] == "check":
 self.check(action)
 elif action['type'] == "action":
 self.action(action)
 def check(self, dic):
 """Check a condition and call an action according to it."""
 obj = getattr(self, dic['condition']['object'])
 compared_att = getattr(obj, dic['condition']['attribute'])
 value = dic['condition']['value']
 result = compared_att == value
 self.action(*dic[result])
 def action(self, *dicts):
 """Perform action with args, both specified on dicts."""
 for dic in dicts:
 act = getattr(self, dic['action'])
 args = dic['args']
 if isinstance(args, list):
 act(*args)
 elif isinstance(args, dict):
 act(**args)
 def set_attribute(self, field, value):
 """Set the specified field with the given value."""
 setattr(self, field, value)
 def add_to(self, category, actions):
 """Add one or more actions to the category's list."""
 action_list = getattr(self, self.action_lists[category])
 for action in actions:
 if action not in action_list:
 action_list.append(action)
 def remove_from(self, category, actions):
 """Remove one or more actions from the category's list."""
 action_list = self.action_lists[category]
 for action in actions:
 if action in action_list:
 action_list.remove(action)
def test():
 """A simple test.
 Item features should be printed differently for each player.
 """
 weapon = Weapon("bastard's sting")
 player1 = Player("paladin")
 player1.pick_up(weapon)
 weapon.toggle_equip()
 print("Enhancement: {}, Hit effects: {}, Other effects: {}".format(
 weapon.magic, weapon.on_hit_actions, weapon.on_turn_actions))
 weapon.toggle_equip()
 player2 = Player("antipaladin")
 player2.pick_up(weapon)
 weapon.toggle_equip()
 print("Enhancement: {}, Hit effects: {}, Other effects: {}".format(
 weapon.magic, weapon.on_hit_actions, weapon.on_turn_actions))

if __name__ == '__main__':
 test()
  1. As the size of the dictionary grows I intend to keep use a bzipped and pickled version of it, created once and updated in case of changes to the JSON/dictionary.
  2. This code does not reflect the actual main structure of the game but tries to illustrate, through a working example, an approach specifically on how weapons (and other items) could be created based on dictionaries in a way that this data could provide conditional verifications and actions to interact dynamically with a huge combinations of race x attributes x features x classes behavior. What is a weapon here is actually a component of a game object in the main code, and so are the player and other creatures.
  3. The item.owner = self doen't look too good, as cat said, but there are (many) cases where a component (item, ai, etc.) interact 'backwards' with its owner. The action "unholy area" of the weapon, in this specific example, would affect every neighbor square of the "owner" (I don't update the item position after someone picks it up, only when the item is dropped); other passive effects would do the same (heal the owner every turn, etc.). I could pass the owner to its equipments at every on_turn call but it sounded like such a waste.

Edited to reflect most of cat's suggestions / accepted answer.

Below is a piece of code showing kind of how it works so far (a simplified, working version of my logic). Currently it relies on a few setattr and eval calls to handle strings from the dictionary.

I would like to hear suggestions on preferable approaches, concerning performance, security, etc.. Can it be significantly improved somehow? Readability (always) matters, any pythonist's approach, perhaps?

# A design test for dynamic class building.
# > attributes and conditional logic are readed from a dictionary.
# This dictionary will actually reside in another file, maybe a json or
# gzipped pickled json...
WEAPONS = {
 "bastard's sting": {
 "equipped": False,
 "magic": 2,
 "on_turn_actions": [],
 "on_hit_actions": [],
 "on_equip": [
 {
 "type": "check",
 "condition": (
 "self.owner.is_of_class",
 ["antipaladin"]
 ),
 True: [
 {
 "type": "action",
 "action": "self.add_on_hit",
 "args": ["unholy"]
 },
 {
 "type": "action",
 "action": "self.add_on_turn",
 "args": ["unholy aurea"]
 },
 {
 "type": "action",
 "action": "self.set_attribute",
 "args": ["magic", 5]
 }
 ],
 False: [
 {
 "type": "action",
 "action": "self.set_attribute",
 "args": ["magic", 2]
 }
 ]
 }
 ],
 "on_unequip": [
 {
 "type": "action",
 "action": "self.rem_on_hit",
 "args": ["unholy"]
 },
 {
 "type": "action",
 "action": "self.rem_on_turn",
 "args": ["unholy_aurea"]
 },
 {
 "type": "action",
 "action": "self.set_attribute",
 "args": ["self.magic", 2]
 }
 ]
 }
}
class Player:
 inventory = []
 def __init__(self, _class):
 self._class = _class
 def pick_up(self, item):
 """Pick an object, put in inventory, set its owner."""
 self.inventory.append(item)
 item.owner = self

 def is_of_class(self, _class):
 """Checks for the Character _class, not a python `class`"""
 return self._class == _class

class Weapon:
 """An type of item that can be equipped/used to attack."""
 def __init__(self, template):
 """Set the parameters based on a template."""
 self.__dict__.update(WEAPONS[template])
 def equip(self):
 """Set item status and call its on equip functions."""
 self.equipped = True
 for action in self.on_equip:
 if action['type'] == "check":
  self.check(action)
 elif action['type'] == "action":
 self.action(action)
 def unequip(self):
  """Unset item dynamic status, call its on unequip functions."""
 self.equipped = False
 for action in self.on_unequip:
 if action['type'] == "check":
 self.check(action)
 elif action['type'] == "action":
 self.action(action)
 def check(self, dic):
 """Check a condition and call an action according to it."""
 check_act = eval(dic['condition'][0])
 args = dic['condition'][1]
 result = check_act(*args)
 self.action(*dic[result])
 def action(self, *dicts):
 """Perform action with args, both specified on dicts."""
 for dic in dicts:
 act = eval(dic['action'])
 act(dic['args'])
 def set_attribute(self, args):
 name, value = args
 setattr(self, name, value)
 def add_on_hit(self, actions):
 for action in actions:
 if action not in self.on_hit_actions:
 self.on_hit_actions.append(action)
 def add_on_turn(self, actions):
 for action in actions:
  if action not in self.on_turn_actions:
 self.on_turn_actions.append(action)
 def rem_on_hit(self, actions):
 for action in actions:
 try:
 self.on_hit_actions.remove(action)
 except ValueError:
 # We never had that but unequip tries to clean it anyway.
 pass
 def rem_on_turn(self, actions):
 for action in actions:
 try:
 self.on_turn_actions.remove(action)
 except ValueError:
 pass

if __name__ == '__main__':
 """Let's test it!"""
 weapon = Weapon("bastard's sting")
 player1 = Player("paladin")
 player1.pick_up(weapon)
 weapon.equip()
 print("Enhancement: {}, Hit effects: {}, Other effects: {}".format(
 weapon.magic, weapon.on_hit_actions, weapon.on_turn_actions))
 weapon.unequip()
 player2 = Player("antipaladin")
 player2.pick_up(weapon)
 weapon.equip()
 print("Enhancement: {}, Hit effects: {}, Other effects: {}".format(
 weapon.magic, weapon.on_hit_actions, weapon.on_turn_actions))
  1. As the size of the dictionary grows I intend to keep use a bzipped and pickled version of it, created once and updated in case of changes to the JSON/dictionary.
  2. This code does not reflect the actual main structure of the game but tries to illustrate, through a working example, an approach specifically on how could weapons (and other items) be created based on dictionaries in a way that this data could provide conditional verifications and actions to interact dynamically with a huge combinations of race x attributes x features x classes behavior. What is a weapon here is actually a component of a game object in the main code, and so is the player and other creatures. With that said, any specific comment on the main structure is still appreciated, but the main focus should be in the interaction between the Weapon class and the dictionary.
  3. The item.owner = self doen't look too good, as cat said, but there are (many) cases where a component (item, ai, etc.) interact 'backwards' with its owner. The action "unholy area" of the weapon, in this specific example, would affect every neighbor square of the "owner" (I don't update the item position after someone picks it up, only when the item is dropped); other passive effects would do the same (heal the owner every turn, etc.). I could pass the owner to its equipments at every on_turn call but it sounded like such a waste;
  4. The _class variable holds a character class (such as cleric, rogue, etc.), not a python class.
improved the code after some suggestions received
Source Link
Loading
Notes 3 and 4, is_of_class docstring, all for clarification.
Source Link
Loading
edited tags
Link
200_success
  • 145.5k
  • 22
  • 190
  • 479
Loading
clarification about the code structure
Source Link
Loading
deleted 31 characters in body
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238
Loading
Source Link
Loading
lang-py

AltStyle によって変換されたページ (->オリジナル) /