A Few Updates
Hello readers! Thank you for tuning back in for the second post on Pokémon Type Rock-Paper-Scissors (Pokémon TRPS). Before stepping into the nit and gritty of new python
code I have two updates to share.
The last bot I planned will unfortunately not be covered due to post
limitations and time constraints. While I wanted it to be a fun surprise, the
final bot was a posture checker. Generally speaking, many people sit for long
periods using their computers whether it be work or hobbies. The bot would
have made use of the online presences feature discord
provides where you, your friends, or others on the mutual discord servers can
see which computer game or specific application you are running. If you are
looking to practice creating bots, I highly recommend you attempt to create a
posture checking bot.
As for the other update, the format of the posts for the discord bots will
slightly change (including this one). In light of omitting the last bot, I
will focus more on the comparison of the language and discord libraries as
there is a lot more to compare with Pokémon TRPS. I will be skipping a lot more technical details, so please feel free to leave any questions or request any clarifications regarding these bots.
Python discord.py Extended Edition
After learning how much larger this project was when writing the TypeScript version, I decided to make use of discord.py extensions to abstract some lower level code. These extensions are all imported from discord.py so no new requirements needed to be added to the python environment. Since I started watching all three extended movie editions of the Lord of the Rings this last weekend, I understand how extensive extensions can really be. There are two extensions included in discord.py: commands and tasks. The commands extension allows us to easily specify commands as their own class, without needing our code to interpret / parse messages. To see more information regarding the extensions visit the documentation linked below:
These are quite powerful tools and I highly recommend them for developing your own bot. To maximize cleanliness I designed the code using cogs which are a class provided by the extensions.
Python Cogs
Cogs are a base class that allows developers to easily organize/group similar commands, event listeners, or states. While I only touch on the surface of what cogs can really do in this post, they end up working quite well. So in the case for Pokémon TRPS, I created three cogs:
Play - Commands for play and playcpu
Type - Commands for type and types
Misc - Command for games
All the commands are functionally the same to the TypeScript version, but the code is quite different. To add the cog to the client, I called the load_extentions method provided by the Bot class from the commands extension.
![]() |
| lines 17-26, Main.py |
Additionally each cog needs to have a setup function specified in its file. Without going to much in depth to explain the code, the each cog class needs to inherit Cog from the command extension. See the example below of my Misc cog. While a bit weird, I do not need to call setup as the client automatically calls it during load_extention.
The @commands decoration specifies the method we wish to execute when the command is entered by the user.
Comparison to TypeScript Commands
In comparison to TypeScript command loading, I found python's extensions quite more useful. It is also much easier to load and import cogs than it was to import various TypeScript classes. The trade-off appears to be the setup function in every cog file and inheritance. I would prefer composition over the inheritance which discord.py extensions seems to insists we use. Overall, loading the cogs is a slightly more simple and effective way to organize commands than the previous TypeScript version. Since cogs can also be used for events and state, I think python is overall better for robust implementation of discord bot commands.
Python Reactions
I believe the reactions are the most important thing to cover, as they seem to be the major feature for the game. Luckily like discord.js, much of the heavy lifting for reaction requests are done by discord.py. When creating the game, the bot pushes the reactions for the Pokémon types using the add_reaction command provided by discord.py's Message object.
For actually handling user inputted reactions we have to use the wait_for function provided by discord.py Bot class. With an asynchronous wait_for, I can supply a callback to any specified event. The event I needed was the "reaction_add" event, so I attached a check function as the callback. The check function checks whether the reaction was for the game instance using discord message Ids. Every message has its own unique id. Any bot generated game unique id value would also suffice. I think using the game ids in combination with a server uid would be the best solution for this issue, as conflicting message ids across server may cause issues. The wait_for check callback also ensures only user reactions from the two users locked within the game instance are considered valid. The other issue with using wait_for is we do not know whether the user is userA or userB, therefore I had to make another test comparing user ids.
The wait_for "reaction_add" returns a reaction and user that we can use to confirm type selections.
Comparison to TypeScript Reactions
Starting with the good news, the reaction requests while a little slow, are about twice as fast as TypeScript. The bad news, the reaction handling is rather messy and clunky. I would prefer to use a reaction collector despite the extra overhead since the code is much neater and readable. I think the collection systems discord.js offers are much better suited for control-flow. Discord.js also provides different types of collectors for code to be more easily organized. Possibly with more tender, love, and care, the code for the python reaction handling can be abstracted and control much better. However, this would involve multiple extra lines and time that I did not have to spend while working with TypeScript. For performance I would surprisingly recommend Python, but for conformity and ease of design TypeScript flows much better. The languages in regards to reaction handling, have their own significant unique trade-offs which make the comparison more opinionated. Personally, I think the benefits from the control-flow provided by TypeScript were better for Pokémon TRPS. That said, a bot used by more people would be better off with python when using reactions.
Results
There is not much to say about the results, other than they are the same as the TypeScript version. Although there are minor formatting inconsistencies and performance differences, the bot functions the same. The bot took a much shorter time to develop than the TypeScript version since there was less code and no overhead with setting up a tsconfig. See the screenshots below to see the bot in action!
![]() |
| player vs. player match |
![]() |
| player vs. cpu match |
Final Thoughts
Since I do not believe anyone noticed this last time, or at least pointed it out, I included a tiny easter egg in this post and last post. Essentially each hero / thumbnail image of the blog is a pokemon which relates in someway to the code discussed. TypeScript was the Pokémon "Rotom" since it was the first Pokémon to have multiple alternative forms of differing types. For this blog, I used "Klinklang" since it looks like a group of cogs.
If I were to decide between TypeScript and Python, I would use python in a heartbeat because of the usefulness of discord.py extensions. Nevertheless, there may have been some node packages that also provide nice support similar to cogs and commands for TypeScript. However, I still believe python would be the better choice out of the two to create Pokémon TRPS.






As I am not well-versed in all things Pokémon, I do not feel bad about not spotting the Easter eggs, but thanks for pointing them out and explaining them so I can appreciate them too.
ReplyDelete