I have a question about advancing to the next level. The engine code basically goes:
For the first 3 commands in the queue
{
if this bot has enough score to progress
{
progress this bot
return;
}
else
{
if there is no bot
return
else
do everything else
}
}
There are a magnitude of issues that I’m seeing:
1: the engine checks whether there is a player connected to the command after dequeueing it and after the player object is already used. And if it does find a command without a player, it can crash the game loop, and if it doesn’t, it completely stops processing commands for that tick instead of skipping that command and doing an extra command. Meaning if there is a command without a player, every command after that gets skipped for this tick. This is also related to an additional error I’ll discuss below.
2: If a player has enough points to progress to the next level, it only happens on the next tick and only when that player sends a command. Shouldn’t this check happen after the collectibles for this tick has been collected?
3: If a player advances to the next level, all commands after that players command gets skipped for this tick, and stays queued for the next tick, meaning those players loses essentially 1-3 ticks depending on how their bots respond to missed ticks. (IE I progress and my command is second in the queue, 1 command works fine, second command gets ignored and I progress instead, third command gets skipped, 4th command isn’t processed to begin with.). This also means that if multiple players have enough points to progress on the same tick, only 1 player can progress per tick.
4: if there is an invalid action, invalid player, or a player progresses, the physics are not updated and the game state is not sent to the bots. Meaning the next tick, that states are going to be a mess for any command that was processed the previous tick, since the physics never updated for that tick. (this might explain some other issues people were having where a state transitions from a jump into a fall immediately etc)
as a result of the above, it looks like between when a player collected enough points to progress and when it gets the gamestate that it has progressed is no less than 2 ticks and can be infinitely long.
Additionally, on the runner hub, where a command gets queued:
if (!engine.CommandQueue.Any(c => c.BotId == command.BotId))
{
engine.CommandQueue.Enqueue(command);
}
This performs only a check to see whether a command for that bot it is queued already, it does not check whether a bot with that id is registered. This means a bot can spam commands with random IDs and they will be queued. In conjunction with the above mentioned issue about checking the player, this means that a bot can essentially cause the engine to skip ticks. While it might not necessarily benefit from it directly since its own commands would also be skipped, it could have an extremely detrimental effect on other bots. Alternatively, if a bot progresses to the next level first, it can essentially spam commands to prevent anyone else from progressing, ensuring a first place for that match.
I will do a pr that should address these issues shortly