繁体   English   中英

Discord.py转向系统

[英]Discord.py turn system

我目前正在开发一个基于消息的 discord.py 回合系统,它将玩家数据存储在 aiosqlite 数据库中(此处未显示),然后利用该数据来确定当前轮到谁; 虽然,事情并没有真正按计划 go ......

我的代码应该做的是重用数据库中的数据并将其分类为最多四个的列表(每个文本通道最多允许有四个玩家,并且在任何情况下至少有两个玩家轮流玩游戏及时); 所以我做了一个格式化程序,它基本上抓取玩家(范围从 2 到 4)并将它们放在一个列表中,该列表被传递到转弯 class 内的指定player Turns - 然后(在其他类的帮助下),吐出当前轮到谁的适当值(由定义的函数控制)。

这是我的齿轮文件:

(Do note that this is a snippet of my full code - if you see any unused variables or missing imports, know that this wasn't a mistake on my side).

前面的长代码*

from discord.ext import commands

class Turns:
    def __init__(self, player1: int = None, player2: int = None, player3: int = None, player4: int = None):
        self.player_1 = player1
        self.player_2 = player2
        self.player_3 = player3
        self.player_4 = player4
        self.turn = 1
        self.turn_member = self.player_1

    def switch_turns(self, player: int):

        if self.player_4 is not None:
            if player == self.player_1:
                self.turn = 2
                self.turn_member = self.player_2
                return self.player_2, self.turn, self.turn_member
            if player == self.player_2:
                self.turn = 3
                self.turn_member = self.player_3
                return self.player_3, self.turn, self.turn_member
            if player == self.player_3:
                self.turn = 4
                self.turn_member = self.player_4
                return self.player_4, self.turn, self.turn_member
            if player == self.player_4:
                self.turn = 1
                self.turn_member = self.player_1
                return self.player_1, self.turn, self.turn_member

        if self.player_3 is not None and self.player_4 is None:
            if player == self.player_1:
                self.turn = 2
                self.turn_member = self.player_2
                return self.player_2, self.turn, self.turn_member
            if player == self.player_2:
                self.turn = 3
                self.turn_member = self.player_3
                return self.player_3, self.turn, self.turn_member
            if player == self.player_3:
                self.turn = 1
                self.turn_member = self.player_2
                return self.player_1, self.turn, self.turn_member

        if self.player_4 is None and self.player_3 is None:
            if player == self.player_1:
                self.turn = 2
                self.turn_member = self.player_2
                return self.player_2, self.turn, self.turn_member
            if player == self.player_2:
                self.turn = 1
                self.turn_member = self.player_1
                return self.player_1, self.turn, self.turn_member

    def player_current_turn(self):

        if self.player_4 is not None:
            if self.turn == 1:
                return self.player_1
            if self.turn == 2:
                return self.player_2
            if self.turn == 3:
                return self.player_3
            if self.turn == 4:
                return self.player_4

        if self.player_3 is not None and self.player_4 is None:
            if self.turn == 1:
                return self.player_1
            if self.turn == 2:
                return self.player_2
            if self.turn == 3:
                return self.player_3

        if self.player_4 is None and self.player_3 is None:
            if self.turn == 1:
                return self.player_1
            if self.turn == 2:
                return self.player_2


class Format_Lists:

    @staticmethod
    def format_list(list: list = None):
        if len(list) == 4:
            pass
        if len(list) == 3:
            formatted_triple_list = [list[0], list[1], list[2], None]
            return formatted_triple_list
        if len(list) == 2:
            formatted_double_list = [list[0], list[1], None, None]
            return formatted_double_list


class RoleplayModerationCoVents(commands.Cog):

    def turn_set(self, player1: int = None, player2: int = None, player3: int = None, player4: int = None):
        if player3 is None and player4 is None:
            turns = Turns(player1=player1, player2=player2)
            return turns
        if player4 is None and player3 is not None:
            turns = Turns(player1=player1, player2=player2, player3=player3)
            return turns
        if player4 is not None:
            turns = Turns(player1=player1, player2=player2, player3=player3, player4=player4)
            return turns

    @commands.Cog.listener()
    async def on_message(self, ctx):

        FormattedList = Format_Lists().format_list({list acquired from database}) # A list of length 4 containing the players' IDs, with None in each empty entry.

        turns = self.turn_set(player1=FormattedList[0], player2=FormattedList[1], player3=FormattedList[2], player4=FormattedList[3])
        print(f'It\'s currently {await ctx.guild.fetch_member(turns.player_current_turn())}\'s turn!')

        if ctx.author.id == turns.player_current_turn():
            turns.switch_turns(player=ctx.author.id)
            new_turn = int(turns.player_current_turn())
            print(f'It\'s now {await ctx.guild.fetch_member(new_turn)}\'s turn!')
            return int(turns.player_current_turn())

async def setup(bot):
    await bot.add_cog(RoleplayModerationCoVents(bot))

为简单起见,我将在此示例中使用两人动态。

现在,问题是我的代码有错误; 起初它似乎工作正常 - 显示预期:

It's currently {insert player1}'s turn!

It's now {insert player2}'s turn!

但是,当我在文本通道中发送另一条文本消息时 - 代码只是重复并重新打印上面的两行......

打算在这里作为 output 拥有的是:

'It's currently {insert player2}'s turn!'

'It's now {insert player1}'s turn!'

我非常希望on_message事件返回新玩家并根据实例进行更改。

如果有人可以提供帮助,请向我提供一些信息和代码! 我很想知道如何解决这个问题!

另请注意,我对课程和 Python 背后的复杂性不是超级有经验; 如果可能的话,请彻底解释清楚!

先感谢您。

问题是,您正在调用self.turn_set()并将Turns的实例存储在on_message function 中。 function 完成后数据丢失。

简单的例子:

def foo():
    count = 0
    print(count)
    count += 1   # change variable here

foo()
foo()

# Output
0
0    # no change, because 'count' gets reseted

在您的情况下, fooon_message事件, countturns数, 0您的Turns object。

您需要检查游戏是否已启动并将实例存储在其他位置。 假设我们遇到了和上面一样的情况,但是现在这个 bug 已经解决了:

class FooClass:

    def __init__(self):
        self.is_started = False
        self.count = None

    def foo(self):
        if not self.is_started:   # + the conditions you want that the game starts
            self.is_started = True
            self.count = 0   # store 0 only on first call
        else:
            self.count += 1

        # when game is finished, reset flag
        if self.count == 2:
            self.is_started = False

        print(self.count)

foo_object = FooClass()
foo_object.foo()
foo_object.foo()
foo_object.foo()
foo_object.foo()

# Output
0
1
2
0   # reset

在这种情况下,我说,我想在count达到值2时完成它。

在您的情况下,您可以将这两个变量存储在RoleplayModerationCoVents class 中,如下所示:

# ...

class RoleplayModerationCoVents(commands.Cog):
    
    def __init__(self, bot):
        self.bot = bot
        self.is_started = False
        self.turns = None
        
    def turn_set(self, player1: int = None, player2: int = None, player3: int = None, player4: int = None):
        # ...

    @commands.Cog.listener()
    async def on_message(self, ctx):
        # ...
        if not self.is_started:   # + the conditions you want that the game starts
            # start game by setting bool to True
            self.is_started = True
            self.turns = self.turn_set(player1=FormattedList[0], player2=FormattedList[1], player3=FormattedList[2], player4=FormattedList[3])
            print(f'It\'s currently {await ctx.guild.fetch_member(turns.player_current_turn())}\'s turn!')

        if ctx.author.id == turns.player_current_turn():
            self.turns.switch_turns(player=ctx.author.id)
            new_turn = int(self.turns.player_current_turn())
            print(f'It\'s now {await ctx.guild.fetch_member(new_turn)}\'s turn!')
            # ...
        
        if ... : # conditions which end the game
            self.is_started = False
async def setup(bot):
    await bot.add_cog(RoleplayModerationCoVents(bot))

要添加@puncher 的帖子,这是一个最终的、完全可操作的代码:

from discord.ext import commands


class Turns:
    def __init__(self, player1: int = None, player2: int = None, player3: int = None, player4: int = None):
        self.player_1 = player1
        self.player_2 = player2
        self.player_3 = player3
        self.player_4 = player4
        self.turn = 1
        self.turn_member = self.player_1

    def switch_turns(self, player: int):

        if self.player_4 is not None:
            if player == self.player_1:
                self.turn = 2
                self.turn_member = self.player_2
                return self.player_2, self.turn, self.turn_member
            if player == self.player_2:
                self.turn = 3
                self.turn_member = self.player_3
                return self.player_3, self.turn, self.turn_member
            if player == self.player_3:
                self.turn = 4
                self.turn_member = self.player_4
                return self.player_4, self.turn, self.turn_member
            if player == self.player_4:
                self.turn = 1
                self.turn_member = self.player_1
                return self.player_1, self.turn, self.turn_member

        if self.player_3 is not None and self.player_4 is None:
            if player == self.player_1:
                self.turn = 2
                self.turn_member = self.player_2
                return self.player_2, self.turn, self.turn_member
            if player == self.player_2:
                self.turn = 3
                self.turn_member = self.player_3
                return self.player_3, self.turn, self.turn_member
            if player == self.player_3:
                self.turn = 1
                self.turn_member = self.player_2
                return self.player_1, self.turn, self.turn_member

        if self.player_4 is None and self.player_3 is None:
            if player == self.player_1:
                self.turn = 2
                self.turn_member = self.player_2
                return self.player_2, self.turn, self.turn_member
            if player == self.player_2:
                self.turn = 1
                self.turn_member = self.player_1
                return self.player_1, self.turn, self.turn_member

    def player_current_turn(self):

        if self.player_4 is not None:
            if self.turn == 1:
                return self.player_1
            if self.turn == 2:
                return self.player_2
            if self.turn == 3:
                return self.player_3
            if self.turn == 4:
                return self.player_4

        if self.player_3 is not None and self.player_4 is None:
            if self.turn == 1:
                return self.player_1
            if self.turn == 2:
                return self.player_2
            if self.turn == 3:
                return self.player_3

        if self.player_4 is None and self.player_3 is None:
            if self.turn == 1:
                return self.player_1
            if self.turn == 2:
                return self.player_2

    def rp(self):
        if not self.is_started:
            self.is_started = True
            self.count = 0
        else:
            self.count += 1


class Format_Lists:

    @staticmethod
    def format_list(list: list = None):
        if len(list) == 4:
            pass
        if len(list) == 3:
            formatted_triple_list = [list[0], list[1], list[2], None]
            return formatted_triple_list
        if len(list) == 2:
            formatted_double_list = [list[0], list[1], None, None]
            return formatted_double_list


class RoleplayModerationCoVents(commands.Cog):

    def __init__(self, bot):
        self.bot = bot
        self.is_started = False
        self.turns = None

    def turn_set(self, player1: int = None, player2: int = None, player3: int = None, player4: int = None):
        if player3 is None and player4 is None:
            turn = Turns(player1=player1, player2=player2)
            return turn
        if player4 is None and player3 is not None:
            turn = Turns(player1=player1, player2=player2, player3=player3)
            return turn
        if player4 is not None:
            turn = Turns(player1=player1, player2=player2, player3=player3, player4=player4)
            return turn

    @commands.Cog.listener()
    async def on_message(self, ctx):

        if not self.is_started:   # + the conditions you want that the game starts
            # start game by setting bool to True
            self.is_started = True
            self.turns = self.turn_set(player1=FormattedList[0], player2=FormattedList[1], player3=FormattedList[2], player4=FormattedList[3])
            print(f'It\'s currently {await ctx.guild.fetch_member(self.turns.player_current_turn())}\'s turn!')

        if ctx.author.id == self.turns.player_current_turn():
            self.turns.switch_turns(player=ctx.author.id)
            new_turn = int(self.turns.player_current_turn())
            print(f'It\'s now {await ctx.guild.fetch_member(new_turn)}\'s turn!')
            return
            # ...

        if ... : # conditions which end the game
            self.is_started = False


async def setup(bot):
    await bot.add_cog(RoleplayModerationCoVents(bot))

我在包含print(f'It\'s now {await ctx.guild.fetch_member(new_turn)}\'s turn!')的行之后添加了一个简单的return语句,因为代码实际上并没有返回新的播放器,而是卡在第一个播放器上。

非常感谢@puncher 编写此代码; 对于将来偶然发现这一点的人-您是幸运的:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM