gpt4 book ai didi

Python如何为游戏中的每个类制定规则集

转载 作者:太空宇宙 更新时间:2023-11-04 00:02:34 25 4
gpt4 key购买 nike

在 C# 中,我们必须获取/设置来制定规则,但我不知道如何在 Python 中执行此操作。

例子:
兽人只能装备斧头,其他武器不符合条件
人类只能装备剑,其他武器都可以。

我怎样才能告诉 Python 一个 Orc 不能做上面例子中的事情?

提前感谢您的回答,希望这对你们有任何意义。

最佳答案

in C# we have to get/set to make rules, but I don't know how to do this in Python.



不,Getter 和 Setter 在这里帮不了你。请注意,Python 也有 getter/setter 和 dunders(类似于 self.__foo ),但我们不要走这条路。

相反,让我们看看你有什么:
  • 一堆东​​西(比如兽人、人类和剑之类的东西)
  • 一堆 Action (好吧,目前只有一个 Action ,挥舞,但也许明天你会决定吸血鬼可以喝血,但人类不能)
  • 和一堆规则(斧头是武器,剑是武器,兽人只能使用斧头,人类可以使用其他武器,......)。

  • 所以,让我们尝试以这种方式对我们的游戏进行建模:使用 Things , Actions , 和 Rules .

    因为我们是很酷的 child ,所以让我们从将我们的规则写成文本开始:
    rules =[
    "Human is Person",
    "Orc is Person",
    "Person may wield Weapon",
    "Human may not wield Axe",
    "Orc may only wield Axe",
    "Sword is Weapon",
    "Bow is Weapon",
    "Axe is Weapon",
    "Cow is Animal",
    "Animal may eat Grass"
    ]

    正如你所看到的,我也谈到了奶牛、动物和草,所以我们可以看到我们将采用一种非常通用的方法。

    我们知道我们的“事物”有不同的类型、名称和调用“ Action ”的方式,所以这里是我们的 Thing类(class):
    class Thing:
    def __init__(self, name, *type):
    self.name = name
    self.type = ['Thing', *type]

    def action(self, action_class, *args):
    action_class(self, *args)()

    一个 Thing'Thing' 类型以及我们传递给 __init__ 的任何其他内容,我们可以调用 action带有 Action 的函数类(我们很快创建它)和我们传递给这个函数的一些参数。

    到目前为止,如此简单。

    现在,这是一个通用的 Action可能看起来像:
    class Action:
    def __init__(self, name, a, b):
    self.name = name
    self.a = a
    self.b = b

    def invoke(self):
    print('You feel a strange sensation...')

    def forbidden(self):
    print(f"{self.a.name} tries to {self.name} {self.b.name}, but that is not possible")

    def __call__(self):
    if Rules.allowed(self):
    self.invoke()
    else:
    self.forbidden()
    print('----------')

    只需一个名称和两件事( ab )。它可以被调用(例如通过 Thing.action ),并且它要么被允许被调用(然后调用 invoke )或不被调用(然后调用 fobidden )。

    让我们忽略 Rules.allowed现在并创建一些执行某些操作的操作:
    class Wield(Action):
    def __init__(self, thing, weapon):
    super().__init__('wield', thing, weapon)

    def invoke(self):
    if hasattr(self.a, 'weapon'):
    print(f'{self.a.name} drops {self.a.weapon.name}')
    self.a.weapon = self.b
    print(f'{self.a.name} now wields {self.a.weapon.name}')

    class Eat(Action):
    def __init__(self, thing, food):
    super().__init__('eat', thing, food)

    def forbidden(self):
    print(f'{self.a.name} tried to eat {self.b.name}, but did not like it very much...')

    def invoke(self):
    print(f'{self.a.name} eats {self.b.name}')
    Wield操作将设置 weapon调用者的,但只有在允许的情况下。 Eat行动,好吧,现在只打印一条消息......

    所以,我们现在唯一要做的就是实际实现 Rules.allowed ,这意味着解析我们最初创建的规则并对其采取行动。

    这是 Rules类(class):
    class Rules:
    alias_list = []
    prohibition_list = []
    permission_list = []
    exclusive_list = []

    def parse_rules(rules):
    for rule in rules:
    if ' is ' in rule:
    type, alias = rule.split(' is ')
    Rules.alias_list.append((type, alias))
    elif ' may only ' in rule:
    obj, rest = rule.split(' may only ')
    action, second = rest.split(' ')
    Rules.exclusive_list.append((obj, action, second))
    elif ' may not ' in rule:
    obj, rest = rule.split(' may not ')
    action, second = rest.split(' ')
    Rules.prohibition_list.append((obj, action, second))
    elif ' may ' in rule:
    obj, rest = rule.split(' may ')
    action, second = rest.split(' ')
    Rules.permission_list.append((obj, action, second))

    def resolve_types_inner(types, aliases):
    for (source_type, alias_type) in aliases[:]:
    if source_type in types:
    types.add(alias_type)
    aliases.remove((source_type, alias_type))
    return Rules.resolve_types_inner(types, aliases)
    return types

    def resolve_types(thing):
    types = set(thing.type)
    return Rules.resolve_types_inner(types, Rules.alias_list[:])

    def allowed(action_to_test):
    a_types = Rules.resolve_types(action_to_test.a)
    b_types = Rules.resolve_types(action_to_test.b)

    for (a, action, b) in Rules.exclusive_list:
    if action == action_to_test.name:
    if a in a_types and b in b_types:
    print ('-- allowed by exclusive_list')
    return True

    for (a, action, b) in Rules.prohibition_list:
    if action == action_to_test.name:
    if a in a_types and b in b_types:
    print ('-- forbidden')
    return False

    for (a, action, b) in Rules.permission_list:
    if action == action_to_test.name:
    if a in a_types and b in b_types:
    if not action in (x for (a2,x,b2) in Rules.exclusive_list if x == action and a2 in a_types):
    print ('-- allowed')
    return True
    else:
    print ('-- forbidden by exclusive_list')
    return False
    print ('-- no rules match')

    当然,这只是非常基本的,不是成熟的规则引擎或逻辑编程语言,但现在可以了。

    我们已经支持 4 个功能:
  • 别名。我们可以说某事 A 就是某事 B,并且 B 的所有规则都适用于 A
  • 允许某事
  • 禁止某事
  • 仅允许特定 B 使用 A
  • parse_rules函数只是拆分字符串并将部分添加到不同的列表中,在 allowed 中函数我们迭代这些列表以确定是否允许某些内容。

    随意改进或添加新功能。

    所以,现在我们准备好了。

    让我们运行以下命令:
    # prepare our simple rule engine
    Rules.parse_rules(rules)

    # Let some things exist in the world
    Carl_the_Human = Thing('Carl', 'Human')
    Grump_the_Orc = Thing('Grump', 'Orc')
    Sandy_the_Cow = Thing('Sandy', 'Cow')
    Carls_sword = Thing("Carl's Sword of Justice", 'Sword')
    Grumps_axe = Thing("Grump's rusty Axe", 'Axe')
    Old_bow = Thing("An old bow", 'Bow')

    # Sandy is hungry
    Sandy_the_Cow.action(Wield, Grumps_axe)
    Sandy_the_Cow.action(Eat, Grumps_axe)
    Sandy_the_Cow.action(Eat, Thing("a bunch of grass", "Grass"))

    # Carl wants to try some weapons
    Carl_the_Human.action(Wield, Carls_sword)
    Carl_the_Human.action(Wield, Grumps_axe)
    Carl_the_Human.action(Wield, Old_bow)

    # Grump wants to try some weapons
    Grump_the_Orc.action(Wield, Grumps_axe)
    Grump_the_Orc.action(Wield, Carls_sword)

    我们得到以下结果:
    -- no rules match  
    Sandy tries to wield Grump's rusty Axe, but that is not possible
    ----------
    -- no rules match
    Sandy tried to eat Grump's rusty Axe, but did not like it very much...
    ----------
    -- allowed
    Sandy eats a bunch of grass
    ----------
    -- allowed
    Carl now wields Carl's Sword of Justice
    ----------
    -- forbidden
    Carl tries to wield Grump's rusty Axe, but that is not possible
    ----------
    -- allowed
    Carl drops Carl's Sword of Justice
    Carl now wields An old bow
    ----------
    -- allowed by exclusive_list
    Grump now wields Grump's rusty Axe
    ----------
    -- forbidden by exclusive_list
    Grump tries to wield Carl's Sword of Justice, but that is not possible
    ----------

    每当我们在游戏世界中需要一个新的“规则”时,我们可以将它作为简单文本添加到我们的规则列表中,并让我们的简单规则引擎决定是否允许某些事情(或者如果我们扩展我们的引擎,甚至应该如何发生某些事情) .

    那么也许我们有远程和近战武器,剑士也可以使用长矛而不是弓,弓箭手可以使用弓和长矛而不是近战武器?

    没问题,直接写在规则里:
    "Ranged is Weapon",
    "Melee is Weapon",
    "Bow is Ranged",
    "Spear is Ranged",
    "Sword is Melee",
    "Human is Person",
    "Archer is Human",
    "Swordman is Human",
    "Person may wield Weapon",
    "Archer may not wield Melee",
    "Swordman may not wield Bow"

    示例:
    Swordman = Thing('the old Guy', 'Swordman')
    Archer = Thing('the Archer', 'Archer')
    Carls_sword = Thing("Carl's Sword of Justice", 'Sword')
    Old_bow = Thing("An old bow", 'Bow')
    Spear = Thing("A golden Spear", 'Spear')

    Archer.action(Wield, Carls_sword)
    Archer.action(Wield, Old_bow)
    Archer.action(Wield, Spear)

    Swordman.action(Wield, Carls_sword)
    Swordman.action(Wield, Old_bow)
    Swordman.action(Wield, Spear)

    结果:
    -- forbidden
    the Archer tries to wield Carl's Sword of Justice, but that is not possible
    ----------
    -- allowed
    the Archer now wields An old bow
    ----------
    -- allowed
    the Archer drops An old bow
    the Archer now wields A golden Spear
    ----------
    -- allowed
    the old Guy now wields Carl's Sword of Justice
    ----------
    -- forbidden
    the old Guy tries to wield An old bow, but that is not possible
    ----------
    -- allowed
    the old Guy drops Carl's Sword of Justice
    the old Guy now wields A golden Spear
    ----------

    这是完整的、可运行的代码,您可以自己尝试:
    rules =[
    "Human is Person",
    "Orc is Person",
    "Person may wield Weapon",
    "Human may not wield Axe",
    "Orc may only wield Axe",
    "Sword is Weapon",
    "Bow is Weapon",
    "Axe is Weapon",
    "Cow is Animal",
    "Animal may eat Grass"
    ]

    class Rules:
    alias_list = []
    prohibition_list = []
    permission_list = []
    exclusive_list = []

    def parse_rules(rules):
    for rule in rules:
    if ' is ' in rule:
    type, alias = rule.split(' is ')
    Rules.alias_list.append((type, alias))
    elif ' may only ' in rule:
    obj, rest = rule.split(' may only ')
    action, second = rest.split(' ')
    Rules.exclusive_list.append((obj, action, second))
    elif ' may not ' in rule:
    obj, rest = rule.split(' may not ')
    action, second = rest.split(' ')
    Rules.prohibition_list.append((obj, action, second))
    elif ' may ' in rule:
    obj, rest = rule.split(' may ')
    action, second = rest.split(' ')
    Rules.permission_list.append((obj, action, second))

    def resolve_types_inner(types, aliases):
    for (source_type, alias_type) in aliases[:]:
    if source_type in types:
    types.add(alias_type)
    aliases.remove((source_type, alias_type))
    return Rules.resolve_types_inner(types, aliases)
    return types

    def resolve_types(thing):
    types = set(thing.type)
    return Rules.resolve_types_inner(types, Rules.alias_list[:])

    def allowed(action_to_test):
    a_types = Rules.resolve_types(action_to_test.a)
    b_types = Rules.resolve_types(action_to_test.b)

    for (a, action, b) in Rules.exclusive_list:
    if action == action_to_test.name:
    if a in a_types and b in b_types:
    print ('-- allowed by exclusive_list')
    return True

    for (a, action, b) in Rules.prohibition_list:
    if action == action_to_test.name:
    if a in a_types and b in b_types:
    print ('-- forbidden')
    return False

    for (a, action, b) in Rules.permission_list:
    if action == action_to_test.name:
    if a in a_types and b in b_types:
    if not action in (x for (a2,x,b2) in Rules.exclusive_list if x == action and a2 in a_types):
    print ('-- allowed')
    return True
    else:
    print ('-- forbidden by exclusive_list')
    return False

    print ('-- no rules match')

    class Action:
    def __init__(self, name, a, b):
    self.name = name
    self.a = a
    self.b = b

    def invoke(self):
    print('You feel a strange sensation...')

    def forbidden(self):
    print(f"{self.a.name} tries to {self.name} {self.b.name}, but that is not possible")

    def __call__(self):
    if Rules.allowed(self):
    self.invoke()
    else:
    self.forbidden()
    print('----------')

    class Wield(Action):
    def __init__(self, thing, weapon):
    super().__init__('wield', thing, weapon)

    def invoke(self):
    if hasattr(self.a, 'weapon'):
    print(f'{self.a.name} drops {self.a.weapon.name}')
    self.a.weapon = self.b
    print(f'{self.a.name} now wields {self.a.weapon.name}')

    class Eat(Action):
    def __init__(self, thing, food):
    super().__init__('eat', thing, food)

    def forbidden(self):
    print(f'{self.a.name} tried to eat {self.b.name}, but did not like it very much...')

    def invoke(self):
    print(f'{self.a.name} eats {self.b.name}')

    class Thing:
    def __init__(self, name, *type):
    self.name = name
    self.type = ['Thing', *type]

    def action(self, action_class, *args):
    action_class(self, *args)()

    if __name__ == '__main__':

    Rules.parse_rules(rules)

    Carl_the_Human = Thing('Carl', 'Human')
    Grump_the_Orc = Thing('Grump', 'Orc')
    Sandy_the_Cow = Thing('Sandy', 'Cow')
    Carls_sword = Thing("Carl's Sword of Justice", 'Sword')
    Grumps_axe = Thing("Grump's rusty Axe", 'Axe')
    Old_bow = Thing("An old bow", 'Bow')

    Sandy_the_Cow.action(Wield, Grumps_axe)
    Sandy_the_Cow.action(Eat, Grumps_axe)
    Sandy_the_Cow.action(Eat, Thing("a bunch of grass", "Grass"))

    Carl_the_Human.action(Wield, Carls_sword)
    Carl_the_Human.action(Wield, Grumps_axe)
    Carl_the_Human.action(Wield, Old_bow)

    Grump_the_Orc.action(Wield, Grumps_axe)
    Grump_the_Orc.action(Wield, Carls_sword)

    请注意,有专门的编程语言,例如 Inform7 .

    如果你想阅读更多,我建议阅读 Wizards and warriors Eric Lippert 的系列,它正是讨论了这个问题(我的回答受到了这个系列的启发),甚至使用了类似的例子(幻想类和武器),但恕我直言,这是 OO 编程语言中的一个常见陷阱,用对象并试图将业务逻辑强制到语言类型系统中。

    关于Python如何为游戏中的每个类制定规则集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55226942/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com