A robocode like client-server based framework.
I have always enjoyed playing with robocode on the earlier 2000s. And I found a bit odd that I could never really find a natural successor to it designed to run on a client/server mode.
This project is my take on what could be such sucessor.
A lot of the ideas here in this project came from either my memory of robocode or this great article that presents the project.
Not everything was translated as it is in terms of functionality.
I chose gRPC as the protocol to implement the server, this would allow robots to be implemented on any language that supports gRPC.
The common
project has the Robot.proto
file with all the messages and services, but the bot really need to use one method
service GameService {
rpc connect(stream Action) returns (stream FrameUpdate);
}
We use a bi-directional stream. Robots stream actions
based on frameUpdates
they receive from the server.
The server handles all the updates to the internal state of each Robot. It reacts on ACTION
events sent by the clients, and emits it’s own events via a FRAME_UPDATE
message.
Basically the server does:
while match is active:
for each active bot:
update bot state
detect collisions
detect hits
broadcast queued events
enum EventType {
STARTED = 0;
DESTROYED = 1;
HIT_BY = 2;
HIT_ENEMY = 3;
COLISION_DETECTED = 4;
ENEMY_DETECTED = 5;
STATUS_UPDATED = 10;
}
message Robot {
string id = 1;
string name = 2;
Coordinates coordinates = 3;
double speed = 4;
double bearing = 5;
int32 health = 6;
int32 score = 7;
int32 projectiles = 8;
}
message FrameUpdate{
int64 timestamp = 1;
int32 deltaTiming = 2; (1)
Robot robotState = 3;
EventType eventType = 4;
oneof event { (1)
StartedEvent startedEvent = 100;
DestroyedEvent destroyedEvent = 101;
HitByEvent hitByEvent = 102;
HitEnemyEvent hitEnemyEvent = 103;
EnemyDetectedEvent enemyDetectedEvent = 104;
CollisionDetectedEvent collisionDetectedEvent = 105;
}
}
-
Time elapsed between two frame updates
-
OneOf is the closest to a Polymorphic model of events I could use, this could change in the future
The bots are responsible to implement code that reacts on events sent by the server. Your bot should send ACTION
messages to the server.
A typical bot implementation would look like:
while alive:
for each received event:
compute internal state
send action message
The definition of an Action is:
message Action {
int64 timestamp = 1;
string id = 2;
ActionType actionType = 3;
double value = 4;
}
enum ActionType {
JOIN = 0;
ROTATE = 1;
THROTTLE = 2;
FIRE = 3;
LEAVE = 4;
}
Actions are supposed to change the state of the bot on the server side.
-
You control the bearing by modifying the
ROTATE
action. You can set to 1 (clockwise), -1 (counter clockwise), 0 (stop). The rotation speed is dictated by the server -
You control thrust by sending
THROTTLE
events: 1 towards bearing, -1 against, 0 stop -
You fire the cannon by sending
FIRE
, value can only be 1. The server then handles the bullet trajectory and hit. Each bot can only have one bullet flying at a time. It will ignore anyFIRE
events if the bot has any bullets still traversing the world.
There are 3 main projects
-
common: Hosts the proto files, you will need to make sure you
generateProto
task before trying to build the other projects as they depend on generated code from this one -
core: Core server. Starts the game engine inside a ktor/kodein web server. The goal is to allow a web admin interface to start/stop the GameService
-
common-bots: A few sample bots for people to play with
The desired state is described above, but there’s a ton of moving things to take care of. I’ll try to keep the following table up-to-date
Feature |
Status |
Proto API |
Unstable |
Main Game Loop |
Working |
Enemy detection |
Working |
Collision Detection |
Implemented via jbox2d |
Match detection and state |
Not implemented |
Websockets canvas viewer |
Basic implementation |
Configurable GRPC server with lifecycle |
Not implemented |