robocode-dev / tank-royale

Git repository for Robocode Tank Royale
Apache License 2.0
145 stars 29 forks source link

Possibility to identify bot from Process to Tick #43

Closed SirStone closed 2 years ago

SirStone commented 2 years ago

Is your feature request related to a problem? Please describe. As I described in this discussion I'm developing an alternative graphic client for roboocode Tankroyale, focused on my needs. The application runs the bots, the server and the controller. My problem is to match the runned robots from process with the bots competing into the battlefield but with the situation nowday looks like is impossiible with 100% accuracy. Here's why: The bot is identified in 3 different ways not linkable to each other if not with guesses.

  1. The bot process is identified by the PID
  2. the bot (from version 0.17.0 of the libraries) is receiving a unique session id, aka sessionId, from the server and is shared to the controller via the BotListUpdate message
  3. the bots, during a battle, is identified by an Id, given with the TickEventForObserver message Assuming that my web application can correctly come in possession of all PIDs, Session IDs and in-battle IDs, right now it hasn't the possibility to connect the bots in these three lists together.

If not clear enough I've put, at the end of the request, a simulated example of situation where the matching is impossible.

Describe the solution you'd like I think that the simpler and easier solution (and so the best) is to add to the BotListUpdate message, as middlepoint between the new bot and the battle, two fields: the PID of the bot (given by the bot itself during the handshake) and the id of the battle, pre-issued by the server that will later use as ids for the battle. In this way the botlistupdate bot object would contain: name, sid, host, port, pid, battle id. With this combination of data every program will be able to discern what a bot is doing in every level of the software without confusion.

ps: I approve the usage of short ID for the battle, means less data to transfer for every tick and the ticks are spammed like hell during the battle, keeping those smallest as possible is mandatory.

Describe alternatives you've considered Alternatives I like less

  1. the bot process, same way as the booter, is capable of receiving input from stdinput and answer to the command "identify" with "PID, sessionID, battleID"
  2. BotUpdateList adds the PID and TicksUpdateEventForObserver uses the sessionid instead of the "battle id"
  3. possiblity to enable for the bot "route stdout to websocket" that set the bot to route the stdoud and stderr messages to a websocket where any software can connect to and listen what the bot process says and TicksUpdateEventForObserver uses the sessionid instead of the "battle id". This solution should disable the need to use the PID and realy on the booter application to boot the bots.
  4. any combination of the above solution should solve the main issue

Additional context simulated example, where the data has the same content is written in italic:

  1. I want to run 3 times the same bot pippo and i get from this 3 bot processes with possible identification by name and/or pid:
    • (pippo,pid1)
    • (pippo, pid2)
    • (pippo, pid3).
  2. I run the controller that upon connection it receives the BotUpdateList with 3 objects with possible identification by name, sessionId (sid in short), host and connection port:
    • (pippo,sid1,host,port1)
    • (pippo,sid2,host,port2)
    • (pippo,sid3,host,port3)
  3. when the match is running, via TickEventForObserver, I get as bot updates, these 3 objects with possible identification by id only:
    • (id1)
    • (id2)
    • (id3)

In this example, where the 3 bots have the same name and same host, is impossible to match the 3 same bots in the 3 lists among each other. Not even the Controller itself can match the bots in the list given within the TicksEventForObserver with the ones given in the BotListUpdate.

Thanks for reading this far

flemming-n-larsen commented 2 years ago

@SirStone Thank you for creating this feature request and providing all the details. πŸ™‚

flemming-n-larsen commented 2 years ago

I will definitely go for your suggestion 2:

BotUpdateList adds the PID and TicksUpdateEventForObserver uses the sessionid instead of the "battle id"

I want to keep the necessary logic at the bot side to a bare minimum.

flemming-n-larsen commented 2 years ago

I have now made the implementation with release 0.17.1, so the Booter provides the boot-id, and the Server the session-id (and battle id). The booter generates a boot-id that is sent to the bot, which sends the boot-id along with the session-id to the server. The server provides all observers with the session-id and boot-id (if available) on each bot with the tick event for observers.

The bot-list-update provides info about the bots via the bot-info schema, which extends the bot-handshake that now contains the sessionId and bootId. And the tick-event-for-observer contains the bot-state-with-id, which also contains sessionId and bootId.

@SirStone: I hope this is useful for you? πŸ™‚

SirStone commented 2 years ago

Nope, this is not improving anything for me, but only because I'm not using the booter at all! If I do I lose the stdout and stderr messages from the bot. If you tell me that I missed te fact that from the booter I can get the messages written by the bot I will rewrite part of the code to use the booter again but today I have to run the bots myself in order to get the output, and doing so the "BotListUpdate" does not contain any PID becasue the is the booter prividing it.

The bots themselves can read their pids but I've read a bit and looks like would be problematic because is platform dependant, not mentioning that you are providing the libraries in 2 languages already.

What about getting the output of the bots from the booter in some way?

flemming-n-larsen commented 2 years ago

@SirStone The booter was "only" made to make it easier to start up bots for the GUI. In reality, bots can be started anywhere and join the server - perhaps even without any PID if they where not started from a process, but e.g. running as a script in a browser.

Talking about PIDs, there is actually two levels: 1) One PID from the process started up by the booter in order to run the script that starts up the bot (any language) 2) Another PID which is the process running the Bot, which could make use of the Java or .Net Bot API (and future APIs). I am not sure if it makes sense for e.g. TypeScript/JavaScript bots to talk about a PID?

The boot id was created, to let the booter provide an id back to the client, e.g. the GUI. It is not easy to get the PID (instead of providing the boot id). The reason being that the bot can only get the PID of the process it is starting itself (1st level), but not the PID running the bot (2nd level). So when the booter creates a boot id, at least the Bot APIs can send the boot id to the server, which the receive via the BOOT_ID environment variable sent via the started process from the booter. But we are in no control of people making their own bots that does not make use of the Bot API, e.g. creating their own communication with the server (just sending and receiving messages using the protocol over a websocket).

It is possible to get the PID from the Bot API with both Java and .Net (I have tested this out). But it might not be available for other languages and environments. But it is still hard to send this PID back to the booter. Perhaps this PID could be printed out as first line from the bot api, which can be processed somehow. But it is not the intention of the booter to read this information. The booter is only responsible for starting up the bot processes locally for convinience. An, bots not using the Bot API should make sure to print out the PID if it is available.

So perhaps we need to think of another solution for fixing your issue?


One idea I have in mind is... that we use the session id for everything and drop the pid and boot id entirely. Instead, the session id is provided by the server when booting up bots, meaning that the booter will be able to forward the session id to the bots via a SESSION_ID environment variable. This session id is then provided back to the server with the bot-handshake. When a bot is not being booted via the booter, it will get a session id from the server-handshake, which it needs to send back via the bot-handshake to identifiy itself.

Do you think this will be a solution that will fix the issue?

SirStone commented 2 years ago

You are right, the Bots API must keep the freedom to be made in many and many different langages.

I'm thinking to drop this search for a solution from the game, you already solved 50% of the problem introducing the session_id. before was: booting(A), joining(B), and battle(C)

A(pid) --x--> B(nothing) --x--> C(id) now A(pid) --x--> B(sid) -----> C(sid)

I have in mind to solve the from A to B with a custom solution in my software, basically when I boot the bots, instead of launching them right away I put them in a "launching queue", the next bot can be lunched only when the previous one joined the server and receiving the session_id or failed. In this way I can get the PID from the booted bot and the "newest session_id" got from the BotUpdateList will be matched to the PID of the latest launched bot. In this way, when I receive any stdout or stderr message, only identifiable with the PID of the process that produced the message, I should be able to map PID-->SID; later, when I receive messages from the battle I can use the mapping SID-->PID.

I just need to put this in code and test.

flemming-n-larsen commented 2 years ago

@SirStone The solution with only booting one bot at a time is very clever and sounds like a nice way to solve the problem. πŸ‘

If the boot-id is not of any use, I guess I will replace is with the plain old pid, which is typically a smaller int, than the one I use for the boot id now. And the pid makes it possible for users to find those in the OS as well. πŸ˜‰

SirStone commented 2 years ago

@flemming-n-larsen killi it! I never liked it since beginning, It won't be missed 😎

flemming-n-larsen commented 2 years ago

OK. I will kill it. πŸ˜‚

flemming-n-larsen commented 2 years ago

I guess release 0.17.3 wraps up the stuff we agreed on for this issue. Hence, I will close the issue. Please create a new one, if there are still things to fix in this area.