Discord.py转弯系统



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

我的代码应该做的是重用数据库中的数据,并将其排序为最多四个列表(每个文本频道最多允许有四个玩家,在任何时候至少允许两个玩家轮流参与游戏(;因此,我制作了一个格式化程序,它基本上抓取玩家(从2到4(,并将它们放在一个列表中,该列表被传递到Turns类中指定的player参数中,然后(在其他类的帮助下(,吐出一个合适的值,该值当前是谁的回合(由定义的函数控制(。

这是我的Cog文件:

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

然而,当我在文本通道内发送另一条短信时,代码只是重复并重新打印上面的两行。。。

打算在这里输出的是:

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

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

我非常希望on_message事件返回新玩家,并在实例方面进行更改。

如果有人能帮忙,请提供一些信息和代码给我!我很想知道我该怎么解决这个问题!

还请注意,我对Python背后的类和复杂性并不是很有经验;如果可能的话,请把事情解释清楚!

提前谢谢。

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

简单示例:

def foo():
count = 0
print(count)
count += 1   # change variable here
foo()
foo()
# Output
0
0    # no change, because 'count' gets reseted

在您的情况下,fooon_message事件,countturns0Turns对象。

您需要检查游戏是否已启动,并将实例存储在其他位置。假设我们有与上面相同的情况,但现在错误已经解决:

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时完成它。

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

# ...
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编写了这段代码;对于未来偶然发现这一点的人来说,你是幸运的:(

最新更新