KeeyanGhoreshi / PlatinumSimulator

simulates randomness in pokemon platinum
GNU General Public License v3.0
125 stars 1 forks source link

General questions on the project #1

Closed saechaol closed 1 month ago

saechaol commented 1 month ago

Hi šŸ‘‹

Very cool project, I watched some of the video that you posted on YouTube. I just had a few questions I was curious about, I hope you don't mind answering. FWIW I'm personally not as familiar with C++ (I use at work Swift, Python, Java, in increasingly less significance to my day job) and I haven't used C++ since college, so forgive me if any of my questions can be answered with "I went with this approach because of a limitation of C++". Some questions may be simple, but its more because I'm really interested in your methodology here. I will also apologize in advance if any of my questions are answered in the video (I only watched the first 15 minutes or so).

  1. Any reason why its named yerp? It doesn't sound like any word or interpolation function I am familiar with. I understand mersenne, after the mersenne twister pseudorandom generator algorithm.
  2. Some code seems rather redundant. I understand that for personal projects most people don't really scrutinize code clarity/complexity or prefer the path of least resistance. For example, also in yerp, there are many instances of nested if/else blocks where its mainly checking a simple boolean expression like direction == 1, such as in the while loop in getWanderTime(r). Could these be improved with a switch statement to increase readability?
  3. In pokemon.cpp you created a map of what seems to be encountered / battled pokemon, is that the correct interpretation? I'm making this observation since it seems you also define a PokeClient for each preexisting encounter, but not necessarily all possible encounters
  4. How much did it cost you to run your project? In the readme, you mentioned you spun up a virtual machine like an ec2 instance for the simulation. Did you use GCP/AWS/Azure/other cloud computing service? If so, how much did it cost, or did you just happen to have extra credits?

I had a few more questions but I wanted to dig into this code myself and see how it works lol. Feel free to close this issue if you don't wish to answer at this time. Thanks again if you provide any insight to your approach.

KeeyanGhoreshi commented 1 month ago

I'd be happy to answer your questions

  1. Nope, its just what I called the file 2 years ago, expecting it to just be a test file, but it remained throughout the whole project.
  2. Yep, especially in yerp, there is a lot of repetition or some code smell, but yerp runs simple enough and fast enough functions that it doesn't generally affect the runtime, and there isn't a ton to maintain so it never caused an issue during development.
  3. The map of pokemon is all the pokemon that are available to the simulator, so you're interpreting it correctly. A couple of the pokeclients left in the code are some of the battles I simulated, but they're not all there. Over time different clients came and went, mostly in the form of editing an existing client to make a new one since it was easier.
  4. I don't remember off the top of my head, but large sims were done using EC2 instances and cost something like $5-8 to run depending on the complexity of the sim. Functions in yerp/mersenne run fast enough that running them on my personal computer was sufficient.
saechaol commented 1 month ago

Thanks for the discussion! I have a few more questions (last ones, I promise haha) now that I've had some more time to look at some of the code.

  1. What is the purpose of resources.cpp ? It seems to contain the seemingly unused and identical bingo() and bongo() for loops and the main function seems to perform some bitwise operations on some magic unsigned long
  2. Any specific technical challenges involving your implementation that you would be interested in discussing?
  3. Which function would you say seems to have the largest performance impact on the simulator's runtime; alternatively, did you feel like you had to make any interesting optimizations or tradeoffs for performance?
  4. About parseCommand() - is it correct to interpret your approach here as an implementation of a decision tree?
  5. More on commands: in simulator's main function, we have cList defined as a mutable 2d array. Is there any benefit to this compared to declaring it as a constant? Or are the elements of cList changing whenever its passed to simulate() (arguably I may be reading too much into this one because Occam's razor: it is just easier to declare it as a mutable array)
KeeyanGhoreshi commented 1 month ago
  1. resources.cpp is just a file where I wrote some test code, I think the numbers there are the mersenne twister algorithm bit shift operations.
  2. Lots, mainly involving looking through the decompiled source code, piecing together information, trying to find where and why the game uses certain RNG values that are hidden away in files I didn't have access to, learning a couple of Japanese words so I could read the AI scripts more effectively.
  3. The damage calculation function is run the most, and the AI code takes the longest. Prior to an optimization I made, the AI was calling the damage calculation function 160 times every time it was deciding what move to use, since in the source code it doesn't cache the values it produces and just redoes the calculation each time. Adding caching for that was the single largest performance increase I made. Other than that, keeping the code lean and clear of any superfluous functions I didn't need kept complexity and runtime lower. Lots of checks the game makes (for different abilities/moves/situations) I could just leave out of my code since I knew in advance whether those things would come up in the battle I was about to simulate.
  4. Sort of, the simulator will follow commands down a specific branch, and in that sense it is shaped like a decision tree, but each node represents an action the simulator will take in the battle. The simulator also isn't deciding what command to do, it is just attempting to do every single one, and instead of throwing an error when you ask it to do a command it can't complete (like heal a full health pokemon) it just moves up a branch to see if you've defined a command for that specific scenario. It's a lot less flexible than a decision tree. If you don't have the turn number and branch number set in advance, the simulator will happily move to an empty branch and just start taking the default action.
  5. It's just mutable to make my life easier when changing the commands in between tests
saechaol commented 1 month ago

Thanks! I appreciate your discussion