
CGC - an inside look
So, in continuation of the topic about CGC I will reveal the technical details of systems for holding such competitions based on my own experience.
- Composition of the system
To begin with, let's determine what this kind of system consists of.
Well, firstly, the most important thing is the simulation module. Further, of course, this is the client and server, and finally, the most important part for the Code Game Show is the visualizer. Now consider each of these parts separately.- Simulator
The simulation module defines the physics of the world, a set of units, and in general everything related to the game world. In addition, this module is responsible for simulating fights between strategies.
This raises the first question - what to record the results of battles?
The first option is to record a certain story about the course of the battle, which can subsequently be reproduced using the visualizer.
The second approach is to simulate and play simultaneously.
Each approach has its pros and cons. The advantage of the second approach is to reduce the time spent by participants on the analysis of their strategies during their development. However, the first approach allows you to implement the functionality of setting the speed and playback point.
Another important detail of the simulator is that it must be able to collect data from strategies written in different languages.
Here, there are several implementation options.
The first option that begs is to compile member strategies in a DLL, and then connect these libraries from the simulator. However, this option carries several problems:- not all languages can provide DLL output
- when using a DLL, they are loaded into the general process and may intentionally drop it.
More secure is the option of compiling with executables and using interprocess communication to communicate the simulator and the strategies of the participants. You can use whatever you like for communication - in practice I have seen systems that use standard input / output (but I do not recommend you), systems that communicate through sockets.
Well, the logic of the simulator is quite simple:- information about the participating strategies and the game world (for example, the identifier of the card used) is received
- the simulator launches the strategies of the participants and alternately passes them the commands to execute the Init method
- the simulator receives the results of the Init method of each strategy and processes the errors (run-time, time limit, memory limit) of the user code
- the simulator passes commands to execute the Move method one by one and collects the results
- brings values to acceptable intervals and simulates a battle
- updates the values of game variables and calls the Move method again
- at the end of the battle, records the results of the battle
- Client The
main task of the client is to send solutions and start viewing battles.
It may also be useful to make functional for communication between the jury and the participants to solve inaccuracies in the rules. Sometimes situations arise when the client changes during the competition itself and the auto-update function can also be useful.
There are no features in the client. - Server
Server is one of the most serious parts. The first and last minutes of the competition are usually a very good test for the server - then the requests for verification at these minutes are large enough and your server should respond to them in an acceptable time.
What is included in the server? They go to the simulation module.
Actually the main server, which serves the connection of users and the acceptance of decisions from them. These solutions are then compiled. Successfully compiled solutions are passed to the simulation module.
I strongly recommend using the same compilers that the participants will also have installed - this will reduce the number of errors.
To ensure a high speed of processing user decisions, you can use a cluster (as they do at TIT SFU), but in the absence of a cluster, you can implement a distributed server. - Visualizer
This module is used to display fights. Colorful special effects will make their viewing more interesting and exciting, and if it contains playback management functionality, it will simplify the lives of participants. However, do not get carried away with the effects - remember that if the visualizer slows down a lot for you, this will make competitions impossible.
- Simulator
- User API
Well, it all depends on your imagination, the only thing I would like to note is that I recommend making methods for debugging strategies - for example, outputting debugging messages (displayed only when writing a strategy), outputting points and vectors.
I also recommend issuing the API in a day - in two, and before the competition itself, arrange a small gathering of participants to answer questions. An example at the end of this article is an API from one of the CGCs. - Remarks
Some more comments on the game world. First, consider the difficulty - because the participants will have only 4-5 hours to explore the game world and implement the strategy. The harder the game world will be, the less interesting the players will end up with, and the less spectacular the Code Game Show will be.
If your world is very complex, but you do not want to change it, try to include higher-level methods in the user API (for example, methods for finding the path between two points). You have to spend more than one or two days - it usually takes from a week to a month.
Try to make support for the most common languages - this will expand the circle of participants.
Take the time to play the balance - for a good balance you will have to spend more than one or two days - it usually takes from a week to a month. - Example User API IBonus
interface - describes the interface of IBonus bonus objects: public IMoveableObject Get hit point bonus Return value: number of hit points that the bot will receive if he selects a bonus int GetHP () Get machine gun ammunition bonus Return value: number of bullets for machine gun which the bot will receive if it picks up the bonus int GetMashinegunAmmo () Get the ammo bonus for the laser Return value: the number of charges for the machine gun that the bot will receive if it picks up the bonus int GetLaserAmmo () Get the gun ammunition bonus
Return value: the number of shells for the machine gun that the bot will receive if it picks up the bonus
int GetCannonAmmo ()
Get the ammunition bonus for the rocket launcher
Return value: the number of missiles that the bot will receive if it picks up the bonus
int GetRocketAmmo ()
Get the bot's lifespan
Return value: remaining bonus lifetime in moves
int GetElapsedTime () IBot
interface - describes the interface of the game unit IBot: public IMoveableObject Get command name Return value: returns command name string GetTeamName () Get bot name Return value: returns bot name or an empty string if it is not specified
string GetName ()
Get information about the ammunition and the state of the gun
Information contains information about the ammunition (number of shells) and the time after which the gun will be ready to fire
Return value: current state of the gun
SWeaponInfo GetCannon ()
Get information about the ammunition and the state of the machine gun
Information contains information about the ammunition (the number of shells) and the time after which the machine gun will be ready to fire
Return value: current state of the machine gun
SWeaponInfo GetMashineGun ()
Get information about the ammunition and the state of the laser
Inf The formation contains information about the ammunition (the number of charges) and the time after which the laser will be ready to fire
Return value: current state of the laser
SWeaponInfo GetLaser ()
Get information about the ammunition and the state of the rocket launcher
Information contains information on the ammunition (number of shots) and the time after which the rocket launcher will be ready to fire
Return value: current state of the rocket launcher
SWeaponInfo GetRocket ()
Get type bot
Return value: returns the type of the current bot
BotType GetType ()
Get the rotation of the tower The
rotation of the tower is counted relative to the diametral plane of the bot.
Return value: relative tower rotation in radians
float GetTurrelAngle ()
Get bot health level
Return value: current number of hit points
int GetHP ()
Interface IMoveableObject - describes the interface of objects that can be moved.
Get object position
Returns the coordinate of the center of the object.
Return value: coordinate of the upper left corner
Point GetPosition ()
Get the rotation angle of the object
For more information on the coordinate system see the IWorld interface description
Return value: returns the rotation of the object in radians
float GetDirection ()
Get the radius of the object
Bonuses, shells and bots are circles,
Return value: returns the radius of the float GetRadius () object
Get the object’s speed
Return value: returns the module of the velocity vector
float GetSpeed ()
Get the impulse velocity vector
When a bot collides with some object (a shell, another bot, a map object, except for a bonus), it also acquires an impulse speed when fired.
Return value: impulse velocity vector.
Vector GetImpulseVelocity ()
Set a text label for an object.
Setting text labels allows you to identify objects. Once you set a label for an object, you can later get it from that label. Text labels are not displayed anywhere. Participants do not see the text labels of other participants.
It is forbidden to put notes on bots - such marks will be reset every turn.
Parameters:
mark text label for the
void object SetMark (int mark)
Get the current object label
Return value: current object label if no label is set -1
int GetMark () ISelf
interface - describes the interface of the managed unit. ISelf: public IBot Set the bot name Setting the bot name is possible only inside the Init function. Calls inside Move are ignored. The bot name must not exceed 20 characters. If the length of the name exceeds them, then it will be shortened to the required length. Parameters: name bot name void SetName (string name) Set bot type
Different types of bots have different characteristics. Setting the type of bot is possible only inside the Init function. Calls within Move are ignored.
Parameters:
type
Bot type void SetType (BotType type)
Set movement speed
Changes the value of the speed vector. A negative value corresponds to a backward movement. If the speed exceeds the maximum threshold or is less than the minimum threshold, it will be reduced / increased to acceptable values.
Parameters:
speed New speed
void SetSpeed (float speed)
Set bot rotation
Parameters:
angle New rotation angle in radians
void SetDirection (float angle)
Change bot tower rotation
Parameters:
delta Increment of the turret rotation angle in radians
void TurnTurrel (float delta)
Fire a machine gun
fires a machine gun. The machine gun always shoots in the direction of the bot. If the machine gun is not ready for a shot, nothing happens.
void ShotMashinegun ()
to make a shot from a cannon
is fired from a cannon. The gun is mounted on a tower. If the gun is not ready to fire, nothing happens.
void ShotCannon () Fire a
laser
shot. Fires a laser shot. The laser always shoots in the direction of the bot. If the laser is not ready to fire, nothing happens.
Parameters:
angle of rotation of the laser
void ShotLaser (float angle)
Fire a rocket
launcher. Fires a rocket launcher. If the rocket launcher is not ready to fire, nothing happens.
Parameters:
target Target
void ShotRocket (IMoveableObject * target) IShell
interface - describes the interface of the projectile located on the map. IShell: public IMoveableObject Get the owner. Return value: the bot fired by this shell IBot * GetOwner () Get the target. For shells such as laser, gun and machine gun, the target is NULL. If the object was destroyed, then NULL is returned. Returned value: the target object of the projectile. IMoveableObject * GetTarget () Get the type of projectile.
Return value: shell type, for more details see ShellType description ShellType
GetType ()
Return value: get the damage caused by the shell.
Return value: damage caused by the shell
int GetHP ()
Interface IStaticObject - describes the interface of static map objects.
Get the number of object hit points.
Return value: current value of hit points
int GetHP ()
Get the coordinates of the object The
coordinates of the static object correspond to its upper left corner. For more information on the coordinate system, see IWorld.
Returned value: object coordinates.
Point GetPosition ()
Get object size
Return value: object size
Size GetSize () IWorld
interface - describes the interface of the game world. Get the number of the current move. Numbering starts from 1. The zero move corresponds to the Init call. Return value: current move number int GetCurrentStep () Get the total number of moves Return value: total number of moves (excluding the initialization move) int GetTotalStep () Get a list of static objects List based on the std :: vector type and allows accessing by index. Destroyed objects are removed from the game and are not displayed in this list. Returned value: list of static map objects
IStaticObjectList GetStaticObjects ()
Get a list of enemy bots. The
list is based on the std :: vector type and allows you to access by index.
Killed bots are removed from the game and are not displayed in this list.
Return value: list of enemy bots
IEnemyList GetEnemies ()
Get a list of your bots. The
list is based on type std :: vector and allows you to access by index
Killed bots are deleted from the game and are not displayed in this list
Return value: list of your bots
ISelfList GetSelfs ()
Get a list of shells on the map The
list is based on the std :: vector type and allows you to reverse by index
Shells that flew off the map or collided with an object are removed from the game and are not displayed in this list.
Return value: list of shells on the map
IShellList GetShells ()
Get a list of bonuses on the map The
list is based on the std :: vector type and allows you to access index
Bonuses that have expired or which have been picked up are removed from the game and are not displayed in this list
Returned value: list of bots located on the map
IBonusList GetBonuses ()
Get the object by label
Parameters:
mark label get my object
Return value: if an object with such a label is found, a pointer to it is returned, otherwise NULL is returned
IMoveableObject * GetByMark (int mark)
Add a debug message
Adds a debug message displayed during visualization for debugging.
Parameters:
format message format - a string of n characters. Next are n parameters in accordance with the task format.
d - integer (int)
f - fractional number (float)
s - string (string)
all other characters are not interpreted and fall into the message
The total length of one message should not exceed 255 characters. If the string is longer, then it will be reduced to the required size
void AddMessage (string format, ...)
Add a debug point
Adds a debug point displayed during visualization for debugging.
Parameters:
p coordinate of the point
lifetime during the time the vector was displayed in the moves
void AddPoint (Point p, int lifetime)
Add debug vector
Adds a debug vector displayed during visualization for debugging
Parameters:
start start point
end end point
lifetime vector display time in moves
void AddVector (Point start, Point end, int lifetime)
Get map width
Return value: map width
int GetWidth ()
Get map height
Return value: map height
int GetHeight ()