1

This question might be complicated and my brain can't really explain it well so please bare with this crappy explanation, My question, When you trigger a command for example .start it will start let's say a text based game, of course you would have the commands to be able to actually play the game however my concern is people can still trigger the ingame commands without needing to start the game for example .

     if message.content.startswith("/play"):       #Here is the play command where you execute the game to start
         await client.send_message(message.channel, "Welcome to the game!")
     if message.content.startswith("/examine):
         await client.send_message(message.channel, "You examined the rock and well, got a rock!") #In-Game commands/movements

What i'm saying is, is there a way of only being able to use the in-game commands only when the game itself is activated? Additional Question: How would you store a user's information like basically saving the game (You don't really need to answer this as i would like to learn this myself but any tips would be great!)

Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96
Cupcake
  • 37
  • 1
  • 4
  • 14
  • Is the game played on a per-player or per channel level? You can see one example of how to persist data in a file [in this question](https://stackoverflow.com/questions/50890310/how-to-get-discord-py-bot-to-show-different-stats-for-every-player/50901369#50901369) – Patrick Haugh Jun 30 '18 at 10:56
  • Its per-player. My concern as said in the question is just you can still trigger the commands outside of the game. – Cupcake Jul 01 '18 at 01:48

1 Answers1

0

First, we want some object that stores the state of a particular session. We can just call this object Game. We'll maintain a mapping of discord.Users to Games. A User existing in this mapping means that they are playing the game. Some basics would look something like:

from discord.ext import commands

class Game:
    def __init__(self):
        self.points = 0
        self.inventory = []

bot = commands.Bot('/')

sessions = {}

@bot.command(pass_context=True)
async def play(ctx):
    if ctx.message.author.id in sessions:
        await bot.say("You're already playing")
        return
    sessions[ctx.message.author.id] = Game()
    await bot.say("Welcome to the game!")

@bot.command(pass_context=True)
async def quit(ctx):
    if ctx.message.author.id not in sessions:
        await bot.say("You're not playing the game")
        return
    del sessions[ctx.message.author.id]
    await bot.say("Game Over")

@bot.command(pass_context=True)
async def examine(ctx):
    session = sessions.get(ctx.message.author.id, None)
    if session is None:
        await bot.say("You're not playing the game")
        return
    session.inventory.append("A rock")
    await bot.say("You examined the rock and well, got a rock!")

bot.run("TOKEN")

Some things you could do to extend this: make use of checks and CommandErrors to avoid having to repeat the code for checking sessions; make sure that Games are pickleable, and write code for saving games using pickle; write a game that's more fun than collecting rocks.

Patrick Haugh
  • 59,226
  • 13
  • 88
  • 96
  • Hi! Thanks for the answer however i tried your code and my bot doesn't reply to me and also doesn't display any type of error, i've tried customizing just a bit by a bit just the text (lol) i can't seem to find the problem either that or i'm just dumb. `class Game: def __init__(self): self.points = 0 self.inventory = [] sessions = {} @bot.command(pass_context=True) async def test(ctx): if ctx.message.author.id in sessions: await bot.say("oof") return sessions[ctx.message.author.id] = Game() await bot.say("oof 2")` – Cupcake Jul 01 '18 at 12:53
  • @Cupcake Do you have an `on_message` event? See: https://stackoverflow.com/questions/49331096/why-does-on-message-stop-commands-from-working – Patrick Haugh Jul 01 '18 at 12:56
  • Sorry for the late reply but i don't think iam? It maybe because i use @client.event instead of @bot.command? – Cupcake Jul 08 '18 at 07:11
  • Here is my code btw `class Game: def __init__(self): self.points = 0 self.inventory = [] sessions = {} @client.event async def club(ctx): if ctx.message.author.id in sessions: await bot.say("Your already in the game!") return sessions[ctx.message.author.id] = Game() await bot.say("Welcome to the game!")` – Cupcake Jul 08 '18 at 07:39
  • This won't work, for a few reasons. You're referencing both `client` and `bot`. You should have one `commands.Bot` object that represents your bot. Everywhere you have `client` replace it with `bot`. `@bot.event` is for registering event handlers. [There is a limited list of events that `discord.py` handles by default.](https://discordpy.readthedocs.io/en/latest/api.html#event-reference) You instead want to use `@bot.command` as I have done above to define commands. You can find some basic instruction on how to do so here https://discordpy.readthedocs.io/en/rewrite/ext/commands/commands.html – Patrick Haugh Jul 08 '18 at 13:19
  • So i just replaced my `client` with `bot` in terms of code, However the code still doesn't work. My other commands work just fine but for some reason the bot won't give me errors about the code and nor it responds to me. – Cupcake Jul 08 '18 at 23:12
  • You should probably ask a new question where you can share your new code and explain more fully how what your bot is doing is not like what you want it to do. – Patrick Haugh Jul 08 '18 at 23:39