[英]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
在您的情况下, foo
是on_message
事件, count
是turns
数, 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.