Welcome to GoBigger’s documentation!
Overview
GoBigger is a multi-agent environment for reinforce learning. It is similar to Agar, which is a massively multiplayer online action game created by Brazilian developer Matheus Valadares. In GoBigger, players control one or more circular balls in a map. The goal is to gain as much size as possible by eating food balls and other balls smaller than the player’s balls while avoiding larger ones which can eat the player’s balls. Each player starts with one ball, but players can split a ball into two once it reaches a sufficient size, allowing them to control multiple balls.
GoBigger allows users to interact with the multi-agent environment easily. Through the given interface, users can get observations by actions created by their policy. Users can also customize their game environments by changing the args in the config.
Indices and tables
Installation
Prerequisites
System version:
Centos 7
Windows 10
MacOS
Python version: 3.6.8
Get and install GoBigger
You can simply install GoBigger from PyPI with the following command:
pip install gobigger
If you use Anaconda or Miniconda, you can install GoBigger through the following command:
conda install -c opendilab gobigger
You can also install with newest version through GitHub. First get and download the official repository with the following command line.
git clone https://github.com/opendilab/GoBigger.git
Then you can install from source:
# install for use
# Note: use `--user` option to install the related packages in the user own directory(e.g.: ~/.local)
pip install . --user
# install for development(if you want to modify GoBigger)
pip install -e . --user
Quick Start
Launch a game environment
After installation, you can launch your game environment easily according the following code:
import random
from gobigger.envs import create_env
env = create_env('st_t2p2')
obs = env.reset()
for i in range(1000):
actions = {0: [random.uniform(-1, 1), random.uniform(-1, 1), 0],
1: [random.uniform(-1, 1), random.uniform(-1, 1), 0],
2: [random.uniform(-1, 1), random.uniform(-1, 1), 0],
3: [random.uniform(-1, 1), random.uniform(-1, 1), 0]}
obs, rew, done, info = env.step(actions)
print('[{}] leaderboard={}'.format(i, obs[0]['leaderboard']))
if done:
print('finish game!')
break
env.close()
You will see output as following. It shows the frame number and the leaderboard per frame.
[0] leaderboard={0: 3000, 1: 3100.0}
[1] leaderboard={0: 3000, 1: 3100.0}
[2] leaderboard={0: 3000, 1: 3100.0}
[3] leaderboard={0: 3000, 1: 3100.0}
[4] leaderboard={0: 3000, 1: 3100.0}
[5] leaderboard={0: 3000, 1: 3100.0}
[6] leaderboard={0: 3000, 1: 3100.0}
[7] leaderboard={0: 3000, 1: 3100.0}
[8] leaderboard={0: 3000, 1: 3100.0}
[9] leaderboard={0: 3000, 1: 3100.0}
[10] leaderboard={0: 3000, 1: 3100.0}
...
Customize your config
Users can also choose to customize the game environment by modifying the configuration cfg and through the gobigger.envs.create_env_custom
method we provide. The gobigger.envs.create_env_custom
method accepts two parameters, the first parameter is type
, the optional value is st
or sp
, which represent the standard game mode, and the independent action game mode. See the introduction of the two modes for details. Below we give a few simple examples based on the standard game mode.
Add more players in a game
For example, you may want to allow 6 teams and 2 players per team in your game, and then please modify team_num
and player_num_per_team
in config.
from gobigger.envs import create_env_custom
env = create_env_custom(type='st', cfg=dict(
team_num=6,
player_num_per_team=2
))
Extend the game time
If you want to extend the game time to 20 minutes (24000 frames), you can use the following codes.
from gobigger.envs import create_env_custom
env = create_env_custom(type='st', cfg=dict(
frame_limit=24000
))
Change the size of the map
If you want to have a larger map, you can change map_width
and map_height
in config.
from gobigger.envs import create_env_custom
env = create_env_custom(type='st', cfg=dict(
map_width=1000,
map_height=1000,
))
What is GoBigger?
Overview
GoBigger is an Agar like game, which is one of the most popular game all over the world. In GoBigger, users control their owned balls to collect weight in a 2-d map with border. There are many other balls in the map, such as food balls, thorns balls, spore balls and other players’ balls. With the limited time, user are ranked by the weight they collect. In order to improve the antagonism of the game, users are allowed to eat other others’ balls to get more weight. So in a game, users need to grow by eating food-balls and thorns-balls, and escape from the larger balls, and eat smaller balls to gather more weight quickly.

Players are controling clone balls in a game.
For a more detailed exposition rules of the game, we will firstly introduce the balls in GoBigger.
Balls
Food balls
Food balls are the neutral resources in the game. They will stay on where they are borned util someone comes and eats them. If a clone ball eat a food ball, the food ball’s size will be parsed to the clone ball. There is a maximum number of food balls in the map. Once the number of available food balls is not enough, the game will generate new food balls in random positions every certain time.
A clone ball eat a food ball.
Thorn balls
Thorns balls are also the neutral resources in the game. Different with food balls, they have larger size and less quantity. If a clone ball eat a thorn ball, the thorn ball’s size will be parsed to the clone ball. But at the same time, the clone ball will explode and will be splited into several pieces. In GoBigger, the pieces always have the same size, and they will appear evenly around the original clone ball. So be careful! If there are other clone balls larger than yours, you should pay more attention to decide whether to eat the thorns-balls.
Another feature of the thorns-balls is that they can be moved by clone balls through ejecting spore balls. If a clone ball eject spore balls to a thorn ball, the thorn ball will eat the spore balls and grow larger. Besides, it will move on the moving direction of the spore balls. That means if a clone ball wants to force a larger clone ball to explode, it can eject spore balls to the thorn ball and move it to the larger clone ball.
A clone ball eat a thorn ball and explode.
Spore balls
Spore balls are ejected by the clone balls. They will stay on the map and can be eaten by any other clone balls. Spore balls can not move or eat others.
Clone balls eject some spore balls.
Clone balls
Clone balls are the balls you can control in the game. You can change its moving direction at any time if you want. In addition, it can eat other balls smaller than itself by covering others’ center. Once a clone ball eat other balls, its size will raise and it radius will increase accordingly. A clone ball has there skills:
Clone balls eat other clone balls.
Eject
Ejecting a spore ball can help a clone ball decrease its size and make it move faster. When a clone ball ejects, the new spore ball must appear on the clone ball’s moving direction with a high speed and quickly slow down.
A clone ball eject to a thorn ball and move it.
Split
Spliting helps a clone ball to split itself in two pieces. The two pieces has the same size. Remember that all pieces will be merged in certain time. If you want to move faster, you can split and turn your balls into smaller size in order to get higher speed limit.
A clone ball splits into several clone balls.
Rules of Game
There are a few rules to be aware of as following.
Player-balls have a decay on size to ensure that they will not grow too large. For example, we set
size_decay=0.00001
in our default setting, which means that a player-ball’s size will drop 0.001% in a state frame. Normaly we will have 20 state frames in a second, that means a player-ball’s size will drop 0.02% in a second. If your player-ball’s size is too large, you must eat more others to remain your size.If a player’s all balls are eat, it will respawn in somewhere randomly and immediately.
The player’s vision will depends on its balls’ positions. We calculate the centroid of a player, and get the smallest external square of all balls. After that, we expand this square as the final vision. To guarantee each player’s vision, we also provide them with the basic vision even if all their balls gather together. For example, if the balls of a player are dispersed enough, a larger vision will be applied for this player.
Each ball has its own speed limit based on its size. In order to ensure the balance of the game, we let larger balls move slow and smaller balls move fast.
High-level Operations

Eject towards the center.

Surround others by splitting.

Eat food balls quickly.

Concentrate size.
GoBigger Engine Design
Overview
This section mainly explains the engine design of GoBigger, including detailed motion logic for various balls. If readers want to develop a new environment based on GoBigger, or want to learn more about the development details of GoBigger, they can read this section carefully. For the convenience of explanation, we will introduce the logic of each ball, and the interaction with other balls. If you are not familiar with the basic ball units in GoBigger, it is recommended to check the previous section (What is GoBigger) first. Note that the following descriptions are based on the settings of st_t4p3
.
What all balls have in common
In GoBigger, you can see that different balls have different sizes. We define that each ball has a certain
score
, and the correspondingradius
can be calculated from the score.
import math
def score_to_radius(score):
return math. sqrt(score / 100 * 0.042 + 0.15)
Food balls are immovable, but thorn balls, spore balls, and clone balls all contain speed attributes, which means they can all move.
If there is a relationship between two balls that can be eaten and eaten (such as between clone balls, between clone balls and all other balls, between thorn balls and spore balls), then when the centers of the two balls overlap, it will be determined whether phagocytosis can occur by the scores of the balls. We stipulate that phagocytosis can only occur when the score of the large ball exceeds
1.3
times that of the small ball.The center of all balls will not exceed the map boundary during the movement.
Our default in-game
FPS
is20
. That is, the game state is updated20
times in a second. Also, by default each call toenv.step
will advance the environment two frames, the user-provided action will be done in the first frame, and then the second frame will be given an empty action.
Food Ball
Food balls are neutral resources in the game. In the
st_t4p3
configuration, the number of food balls on the map at the start of the game will be800
, and the maximum number is900
. Every8
frames,(maximum quantity - current quantity) * 0.01
food balls will be replenished, and the number of food balls will not exceed the upper limit.The initial score for the food ball is
100
. That is, if a clone eats a food ball, the clone’s score will increase by100
.
Thorn Ball
Thorn balls are also neutral resource in the game. In the
st_t4p3
configuration, the number of thorn balls on the map at the beginning of the game will be9
, and the maximum number is12
. Every120
frames, round up(maximum quantity - current quantity) * 0.2
thorn balls will be added in the map, and the number of thorn balls will not exceed the upper limit.The initial score of the ball of thorns will be randomly selected from the range of
10000
to15000
.When the player ejects the spore ball to the thorn ball, if the spore ball is covered by the center of the thorn ball, the thorn ball will eat the spore ball, and at the same time generate an initial velocity of
10
in the direction of the spore ball’s movement, and the velocity decays uniformly to0
over20
frames.
Spore Ball
The size of the spore ball is fixed and the score is fixed at
1400
.When the spore ball is spit out, the speed is fixed at
30
, and the speed is uniformly attenuated to0
in the20
frame.
Clone Ball
The size of the clone ball increases as it continues to eat the ball. The initial score for the clone ball is 1000
. A single player can have a maximum of 16
clone balls. The eject
skill can only be used when the score of each clone ball exceeds 3200
, and the split
skill can only be used when the score exceeds 3600
.
Speed
The speed of the clone ball is a combination of three parts of the vector: the player’s action, the centripetal force caused by the presence of multiple balls, and the gradually decaying speed caused by splitting or eating the thorn ball. The acceleration caused by player actions and centripetal force is multiplied by the length of each frame as the speed change amount at each frame.
Player Action: As defined by the action space, the player can provide any point
(x,y)
within a unit circle to change the speed of the clone ball. Specifically, GoBigger will first normalize this point to the inside of the unit circle (or to the circle if it is outside, otherwise leave it alone), and then multiply it by the weight30
to give the acceleration.Centripetal force: When the player has multiple clone balls, a centripetal force will be generated inside the multiple balls, which points to the center of mass. In fact, the centripetal force will not be used directly, it will be divided by the radius as the true centripetal force, and multiplied by the weight
10
to be the acceleration.Gradually attenuated speed after splitting or eating the thorn ball: The new clone ball split by eating the thorn ball will have a new initial speed after the split. The modulo length of this velocity is related to the radius after splitting, specifically
(260 - 20 * radius) / 7
, and the direction is away from the center of the circle. The velocity decays evenly to0
over14
frames. If the Clone Ball is obtained through the split skill, the formula for calculating the modulo length of this initial velocity is(95 + 19 * radius) / 7
.The speed brought by player operation and centripetal force will be limited by the upper speed limit. The upper speed limit is related to the radius of the ball, and adjusts the upper speed limit by using the larger of the player action and centripetal force as the
ratio
. The specific formula is(2.35 + 5.66 / radius) * ratio
.
Eating a thorn ball
Each time the Clone Ball eats the Thorns Ball, it will split up to a maximum of
10
new Clone Balls. For example, if a player currently has only two clone balls, and one of the clone balls eats a thorn ball, he will split new10
clone balls, so the player has a total of `` 12`` Clone Balls; if a player currently has10
Clone Balls, and one of them eats a Thorny Ball, he will split a new6
Clone Ball, so this At that time the player has a total of16
clone balls.The maximum score of the new ball split by the Clone Ball is
5000
. For example, the current score of the clone ball is23000
, he eats a thorn ball with a score of10000
, then his score will become33000
. At the same time, this avatar will split into new10
avatars. According to the even distribution, the score of each avatar is3000
.After eating the ball of thorns and splitting, the positions of the new balls are evenly distributed around, and there will always be new ball clones in the horizontal position to the right of the original ball.
Split
The new split ball will be in the direction specified by the player. If there is no specified direction, it will appear in the direction of movement of the original ball.
The split skill will divide the score of the original ball equally between the two split balls.
The split ball will also have the speed of the original one.
Whether after splitting or eating the thorn ball, the player’s clone ball (including triggering the split and eating the thorn ball, as well as the newly added clone ball after these two operations) will enter a cooldown period with a length of
20
. Clone balls in the cooldown period cannot trigger the operation of merging with their own clone balls. Additionally, after the Clone Ball completes a merge, it will re-enter the cooldown phase.
Eject
The spore balls generated after the sporulation operation is performed by the clone ball will appear in the direction specified by the player. If there is no specified direction, it will appear in the movement direction of the clone ball.
Each time the clone ball spit out a spore ball, it is equivalent to dividing
1400
from its own score and assigning it to a new spore ball.
Real-time Interaction with game
GoBigger allow users to play game on their personal computer in real-time. Serveral modes are supported for users to explore this game.
Note
If your version of GoBigger is v0.1.x, please upgrade for a better experience. You can use pip install --upgrade gobigger
to access the latest version of GoBigger.
Standard setting with partial view
If you want to play real-time game on your PC on your own, you can launch a game with the following code:
python -m gobigger.bin.play --mode st --vision-type partial
In this mode, using mouse to control the your balls to move, Q
means eject spore on your moving direction, W
means split your balls, and E
means stop all your balls and gather them together.
Standard setting with full view
If you want to play real-time game on your PC with your friends, you can launch a game with the following code:
python -m gobigger.bin.play --mode st --vision-type full
Independent action setting with partial view
In the independent action game mode, each ball of the player receives an action individually. But because it is more difficult to control, we still only receive an action based on the mouse and keyboard in this mode, and assign this action to all the player’s balls. The game can be started with the following code:
python -m gobigger.bin.play --mode sp --vision-type partial
Space
Standard game mode
Standard game mode refers to the same game as agar, where the player can only provide one action per frame, and then all player balls will perform that one action.
Action Space
Since each ball controlled by the player can only move, sporulate, split, and stop, the action space of GoBigger is relatively simple:
action = [x, y, action_type]
x, y
: is a point in the unit circle.(x, y)
represents the player’s manipulation of the ball’s acceleration.GoBigger will normalize
(x, y)
to ensure that its modulus does not exceed1
.If the user does not provide acceleration changes,
(None, None)
can be provided to indicate no changes to the movement.
action_type
: Int0
: means only move, actually every timeenv.step
is called.1
: Represents ejecting in the given direction. If the direction is not specified (ie(None, None)
), it is executed in the direction of movement.2
: represents splitting in the given direction. If the direction is not specified (ie(None, None)
), it is executed in the direction of movement.
We hope that players can use the various skills of the clone ball more flexibly, and hope that the movement direction will not limit the choice of skills. Therefore, we allow the player to specify different directions and directions of movement when using the skill. For example, when the player’s clone ball is moving to the right, if you want to spore down, you only need to specify action_type=1
and specify (x, y)
at the same time, and the clone ball can go to the side. Continue to move right, while spitting down spores. A simple example is given below.

In addition, some useful actions can be achieved by the clever combination of x
, y
and action_type
. For example, setting x
and y
to both None
when sporulating spores can achieve cross sporulation. E.g:

Submit actions to the environment
In the case of multiple players, it is necessary to specify the correspondence between each action and the player. The submitted actions should be a dictionary, and each key-value-pair
should be a player’s id
and the action he needs to do in this frame. Therefore, the action can be submitted as follows:
team_infos = env.get_team_infos()
actions = {}
for team_id, player_ids in team_infos.items():
actions.update({player_id: [random.uniform(-1, 1), random.uniform(-1, 1), -1] for player_id in player_ids)})
obs = env.step(actions)
Observation Space
After each step of the game, the user can get the game state under the vision of the clone ball.
obs, reward, done, info = env.step()
global_state, player_states = obs
global_state
contains some global information, as follows:
{
'border': [map_width, map_height], # map size
'total_frame': total_frame, # The total number of frames in the whole game
'last_frame_count': last_frame_count, # The current number of frames that have passed
'leaderboard': { team_name: team_size } # Current leaderboard information, including the score of each team. The team's score is the sum of the players' scores in the team
}
player_states
contains the information that each player can get, according to player_id
, as follows:
{
player_id: {
'rectangle': [left_top_x, left_top_y, right_bottom_x, right_bottom_y], # The position of the view box in the global view
'overlap': {
'food': [[position.x, position.y, radius, score], ...], # Food ball information in the field of view, which are position xy, radius, score
'thorns': [[position.x, position.y, radius, score, vel.x, vel.y], ...], # The information of the thorns ball in the field of view, namely position xy, radius, score, current speed xy
'spore': [[position.x, position.y, radius, score, vel.x, vel.y, owner], ...], # The spore ball information in the field of view, which are the position xy, radius, score, Current speed xy, from player's id
'clone': [[[position.x, position.y, radius, score, vel.x, vel.y, direction.x, direction.y,
player_id, team_id], ...], # Player ball information in the field of view, namely position xy, radius, score, current speed xy, current direction xy, belonging player id, belonging team id
},
'team_name': team_name, # The current player's team id
'score': player_score, # current player's score
'can_eject': bool, # Whether the current player can perform the spore action
'can_split': bool, # Whether the current player can perform the split action
},
...
}
The overlap
in player_states
represents the structured information about the ball currently in the player’s field of view. overlap
is a simple dictionary, each key-value pair represents information about a ball in view. overlap
contains structured information about food balls, thorn balls, spore balls, and clone balls. Specifically, for example, we found that the content of the food
field is [[3.0, 4.0, 2, 2], ...]
(only the first element in the list is shown here for simplicity) , then the meaning is that in the player’s field of vision, there is a food ball with a radius of 2
at the coordinates (3.0, 4.0)
, and the score of this food ball is 2
.
Note that the length of the information list for each type of ball is indeterminate. For example, if there are 20
food balls in the current frame view, the length of the list corresponding to the current food
is 20
. In the next frame, if the food ball in the field of view becomes 25
, the corresponding list length will become 25
. Additionally, if only a portion of a ball is in the player’s field of view, GoBigger will also give information about the center and radius of the ball in overlap
.
Reward
After each step
of the game, the user can get the game’s default reward.
_, reward, _, _ = env.step()
The default reward in the game is very simple, it is the difference between the total score of the player’s current frame and the total score of the previous frame. Users can design more complex rewards based on the player’s obseravtion.
Other Information
GoBigger provides statistics and puts this information in info
. After each step
of the game, the user can get it.
_, _, _, info = env.step()
Specifically, info
is a dictionary, and in the context of st_t2p2
, the following information can be obtained:
Independent Action Game Mode
The independent action game mode means that the player needs to provide action to all of his player balls every frame. Each player ball of the player can perform actions independently.
Action Space
The minimum action unit is the same as the standard game mode, except that when doing env.step(actions)
, the format of actions
should be as follows:
actions = {
player_id: {
ball_id: [x, y, action_type],
...
},
...
}
The ball_id
here can be determined from the obs
obtained in each frame. Each ball_id
will uniquely correspond to one of the player’s clone balls.
Observation Space
Most of it is the same as the standard game mode, the only difference is that the clone ball part will add ball_id
information. This information can be used to tell the player where the ball_id
can be taken from when providing actions
.
player_states
is as follows:
{
player_id: {
...
'overlap': {
...
'clone': [[[position.x, position.y, radius, score, vel.x, vel.y, direction.x, direction.y,
player_id, team_id, ball_id], ...], # The player's ball information in the field of view, namely position xy, radius, current speed xy, current direction xy, player id, team id, ball id
},
...
}
}
GoBigger environment
Overview
This section mainly explains the environment design of GoBigger, including the definition of a given environment, and how to customize the corresponding environment.
Defined environment
GoBigger defines some basic environments, which can be generated by the following code
from gobigger.envs import create_env
env = create_env('st_t4p3')
Among them, the first parameter received by create_env()
is a string, which is the name of the environment we have defined. Similarly, in addition to st_t4p3
, we also have st_t2p2
, st_t3p2
to choose from. The differences between each environment are described in detail below.
st_t4p3
: Created a game scene with four teams of three players each. This is the standard game scene we define, and parameters including the refresh speed of various balls in it have been adjusted to a relatively robust level. Users can use this environment to solve some cooperative and confrontational problems in complex spatial scenarios.st_t2p2
: Considering thatst_t4p3
may be too large, we provide a smaller game scene. In this scenario, there are only two teams, and each team has two players. Also, the map size, the number of food orbs and thorn balls have been reduced accordingly. In addition, in order to reduce the player’s early development time, we set the player’s first birth score to 13000 inst_t2p2
to allow players to fight quickly, while this value is 1000 inst_t4p3
.st_t3p2
: This is a medium environment betweenst_t2p2
andst_t4p3
, with three teams of two players each. Likest_t2p2
, a higher birth score is also set to reduce development time.
In addition, the above environment defaults to an action every two frames (20 frames per second). If you want a longer action interval, you can set it with the following code:
from gobigger.envs import create_env
env = create_env('st_t4p3', step_mul=10)
In addition, we have more environments already defined, as follows:
Name |
Agents Size |
Map Size |
Food |
Thorn |
Init Size |
Limited Frame |
---|---|---|---|---|---|---|
st_t1p1 st_t1p2 st_t2p1 st_t2p2 st_t3p2 st_t4p3 st_t5p3 st_t5p4 st_t6p4 |
1x1 1x2 2x1 2x2 3x2 4x3 5x3 5x4 6x4 |
32x32 48x48 48x48 64x64 88x88 128x128 128x128 144x144 144x144 |
[65,75] [130,150] [130,150] [260,300] [500,560] [800,900] [900,1000] [900,1000] [1000,1100] |
[1,2] [2,3] [2,3] [3,4] [5,6] [9,12] [10,12] [10,12] [11,13] |
1000 1000 1000 13000 13000 1000 1000 1000 1000 |
3600(3min) 3600(3min) 3600(3min) 3600(3min) 3600(3min) 14400(12min) 14400(12min) 14400(12min) 14400(12min) |
Customize the corresponding environment
GoBigger’s rich configuration file design allows users to easily set up every detail in the game.
If you want to make a simple modification on the basis of an environment we have defined, for example, modify the duration of a round in st_t2p2
, you can do the following:
from gobigger.envs import create_env
env = create_env('st_t2p2', dict(
frame_limit=10*60*20,
))
In this way, the new environment opened will become a 10-minute round based on st_t2p2
.
Playback System
GoBigger’s playback system supports three options, which can be selected through the environment’s configuration file. The configuration items involved are as follows:
config = dict(
...
playback_settings=dict(
playback_type='none', # ['none', 'by_video', 'by_frame']
by_video=dict(
save_video=False,
save_fps=10,
save_resolution=552,
save_all=True,
save_partial=False,
save_dir='.',
save_name_prefix='test',
),
by_frame=dict(
save_frame=False,
save_all=True,
save_partial=False,
save_dir='.',
save_name_prefix='test',
),
by_action=dict(
save_action=False,
save_dir='.',
save_name_prefix='test',
),
),
...
)
playback_type
can be one of ['none', 'by_video', 'by_frame']
.
none
: means no need to save playbackby_video
: means to save the video directly, and the suffix of the saved file is.mp4
. Generally speaking, the video saved in thest_t4p3
environment is about 80M.by_frame
: Represents the change amount of each frame saved, and the suffix of the saved file is.pb
. Generally speaking, thest_t4p3
environment saves files around 25M.
Save video
If playback_type='by_video'
is selected, the specific configuration items can be as follows:
env = create_env('st_t4p3', dict(
playback_settings=dict(
playback_type='by_video',
by_video=dict(
save_video=True,
save_dir='.', # The directory location where the video needs to be saved
save_name_prefix='test', # Save the prefix of the video name
),
),
))
Save the pb file
If playback_type='by_frame'
is selected, the specific configuration items can be as follows:
env = create_env('st_t4p3', dict(
playback_settings=dict(
playback_type='by_frame',
by_frame=dict(
save_frame=True,
save_dir='.', # The directory location where the video needs to be saved
save_name_prefix='test', # The prefix of the name of the saving video
)
),
))
After getting the saved .pb
file, you need to view it through our given player. Execute the following command in the command line to open the player.
python -m gobigger.bin.replayer
After opening the player, you need to select the .pb
file you want to view. Then you can start watching. The player supports double-speed playback, including 2x, 4x, and 8x (by clicking the button in the lower left corner). Also supports dragging the progress bar.
Configuration
Overview
In order to allow players to further understand the realization of the game mechanism, we have opened some parameters for players to adjust. We hope that players can modify the corresponding parameters to achieve a variety of different environments. At the same time, you can also design your own agent environment to quickly verify the algorithm.
GoBigger puts configurable parameters in gobigger/server/server_default_config.py
Collision Detection Algorithm
Overview
Algorithm efficiency analysis
The theoretical time complexity of the above four algorithms is as follows:
ExhaustiveCollisionDetection:
\(O(n*m)\)
where n denotes the total number of balls and m denotes the number of balls to be asked.
PrecisionCollisionDetection:
\(O(n*log(n)+\Sigma{r}*logn+p)\)
where n denotes the total number of balls, m denotes the number of balls to be asked, k denotes the presicion we set and p denotes number of spheres that actually collided.
RebuildQuadTreeCollisionDetection:
\(O(n*log(n) + m*log(n)+p)\)
where n denotes the total number of balls, m denotes the number of balls to be asked and p denotes number of spheres that actually collided.
RemoveQuadTreeCollisionDetection:
\(O(r*log(n)+m*log(n)+p)\)
where n denotes the total number of balls, m denotes the number of balls to be asked, r denotes the number of spheres whose position status has changed and p denotes number of spheres that actually collided.
In order to test the efficiency of these algorithms, we modify the parameters including the total number of balls, the number of queries, the number of changed balls, and the iteration rounds to set the test scenario. The data in the following table comes from the most representative scenarios
T: the number of all balls in the map
Q: the number of query balls, which usually means the moving balls in the map
C: the number of changing balls, which means the number of collisions
Exhaustive |
Precision |
Rebuild QuadTree |
Remove QuadTree |
|
---|---|---|---|---|
T=3000 Q=300 C=600 |
688ms |
14ms |
47ms |
48ms |
T=3000 Q=300 C=1500 |
1067ms |
16ms |
50ms |
178ms |
T=10000 Q=1000 C=2000 |
8384ms |
61ms |
339ms |
497ms |
T=10000 Q=2000 C=5000 |
12426ms |
86ms |
586ms |
2460ms |
T=30000 Q=6000 C=3000 |
127000ms |
403ms |
5691ms |
8419ms |
In order to see the pros and cons of each algorithm more intuitively, we integrated test data and drew diagrams of four algorithms and various parameters as follows:



According to the results, we can think that the PrecisionCollisionDetection algorithm is far better than the other algorithms in terms of efficiency and stability.
FAQ
Q1: How to save video in a game?
- A1
Set playback_settings
when you create the environment. After finishing a game, test.pb
will be saved at save_dir
, which can be shown by the GoBigger replayer.
env = create_env('st_t3p2', dict(
playback_settings=dict(
playback_type='by_frame',
by_frame=dict(
save_frame=True,
save_dir='.',
save_name_prefix='test',
),
),
))
Q2: What are the winning conditions at the end of the game?
- A2
Sort by calculating the sum of the scores of all players under each team at the end of the game.
Q3: Is there a limit to the size of the partial field of view?
- A3
The size of the player’s partial field of view is determined by the relative position of the player’s doppelganger. We set the player’s minimum field of view to be a matrix of 36*36. With the dispersion of the doppelganger, the player’s maximum field of vision can reach the global level.
agents
BaseAgent
BotAgent
balls
BaseBall
- class gobigger.balls.base_ball.BaseBall(ball_id, position, score, border, **kwargs)[source]
- Overview:
Base class of all balls
- check_border()[source]
- Overview:
Check to see if the position of the ball exceeds the bounds of the map. If it exceeds, the speed and acceleration in the corresponding direction will be zeroed, and the position will be edged
- eat(ball)[source]
- Overview:
Describe the rules of eating and being eaten
- Parameters:
ball <BaseBall>: Eaten ball
- get_dis(ball)[source]
- Overview:
Get the distance between the centers of the two balls
- Parameters:
ball <BaseBall>: another ball
- judge_cover(ball)[source]
- Overview:
Determine whether the center of the two balls is covered
- Parameters:
ball <BaseBall>: another ball
- Returns:
is_covered <bool>: covered or not
- judge_in_rectangle(rectangle)[source]
- Overview:
Determine if the ball and rectangle intersect
- Parameters:
rectangle <List>: left_top_x, left_top_y, right_bottom_x, right_bottom_y
- Returns:
<bool> : intersect or not
FoodBall
ThornsBall
- class gobigger.balls.thorns_ball.ThornsBall(ball_id, position, score, border, **kwargs)[source]
- Overview:
characteristic:
Can’t move actively
Can eat spores. When eating spores, it will inherit the momentum of the spores and move a certain distance.
Can only be eaten by balls heavier than him. After eating, it will split the host into multiple smaller units.
Nothing happens when a ball lighter than him passes by
- eat(ball)[source]
- Overview:
Describe the rules of eating and being eaten
- Parameters:
ball <BaseBall>: Eaten ball
- move(direction=None, duration=0.05, **kwargs)[source]
- Overview:
Realize the movement of the ball, pass in the direction and time parameters, and return the new position
- Parameters:
direction <Vector2>: A point in the unit circle duration <float>: time
- Returns:
position <Vector2>: position after moving
CloneBall
- class gobigger.balls.clone_ball.CloneBall(ball_id, position, score, border, team_id, player_id, vel_given=<Vector2(0, 0)>, acc_given=<Vector2(0, 0)>, from_split=False, from_thorns=False, split_direction=<Vector2(0, 0)>, spore_settings={'score_init': 1.5, 'vel_init': 50, 'vel_zero_frame': 10}, sequence_generator=None, **kwargs)[source]
- Overview:
One of the balls that a single player can control - characteristic: * Can move * Can eat any other ball smaller than itself * Under the control of the player, the movement can be stopped immediately and contracted towards the center of mass of the player * Skill 1: Split each unit into two equally * Skill 2: Spit spores forward * There is a percentage of weight attenuation, and the radius will shrink as the weight attenuates
- eat(ball, clone_num=None)[source]
- Parameters:
clone_num <int>: The total number of balls for the current player
- eject(direction=None) list [source]
- Overview:
When spit out spores, the spores spit out must be in the moving direction of the ball, and the position is tangent to the original ball after spitting out
- Returns:
Return a list containing the spores spit out
- judge_rigid(ball)[source]
- Overview:
Determine whether two balls will collide with a rigid body
- Parameters:
ball <CloneBall>: another ball
- Returns:
<bool>: collide or not
- move(given_acc=None, given_acc_center=None, duration=0.05)[source]
- Overview:
Realize the movement of the ball, pass in the direction and time parameters
- on_thorns(split_num) list [source]
- Overview:
Split after encountering thorns, calculate the score, position, speed, acceleration of each ball after splitting
- Parameters:
split_num <int>: Number of splits added
- Returns:
Return a list that contains the newly added balls after the split, the distribution of the split balls is a circle and the center of the circle has a ball
- rigid_collision(ball)[source]
- Overview:
When two balls collide, We need to determine whether the two balls belong to the same player A. If not, do nothing until one party is eaten at the end B. If the two balls are the same owner, judge whether the age of the two is full or not meet the fusion condition, if they are satisfied, do nothing. C. If the two balls are the same owner, judge whether the age of the two is full or not meet the fusion condition, Then the two balls will collide with rigid bodies This function completes the C part: the rigid body collision part, the logic is as follows:
To determine the degree of fusion of the two balls, use [the radius of both] and subtract [the distance between the two] as the magnitude of the force
Calculate the coefficient according to the weight, the larger the weight, the smaller the coefficient will be
Correct the position of the two according to the coefficient and force
- Parameters:
ball <CloneBall>: another ball
- Returns:
state <bool>: the operation is successful or not
- split(clone_num, direction=None) list [source]
- Overview:
Active splitting, the two balls produced by splitting have the same volume, and their positions are tangent to the forward direction
- Parameters:
clone_num <int>: The total number of balls for the current player
- Returns:
The return value is the new ball after the split
SporeBall
- class gobigger.balls.spore_ball.SporeBall(ball_id, position, border, score, direction=<Vector2(0, 0)>, owner=-1, **kwargs)[source]
- Overview:
Spores spit out by the player ball - characteristic: * Can’t move actively * can not eat * Can be eaten by CloneBall and ThornsBall * There is an initial velocity at birth, and it decays to 0 within a period of time
managers
BaseManager
FoodManager
ThornsManager
PlayerManager
SporeManager
players
BasePlayer
HumanPlayer
- class gobigger.players.human_player.HumanPlayer(cfg, team_id, player_id, border, spore_settings, sequence_generator=None)[source]
- add_balls(balls)[source]
- Overview:
Add new avatars
- Parameters:
balls <List[CloneBall] or CloneBall>: It can be a list or a single doppelganger
- adjust()[source]
- Overview:
Adjust all the balls controlled by the player, including two parts 1. Possible Rigid Body Collision 2. Possible ball-ball fusion
- eject(direction=None)[source]
- Overview:
All clones controlled by the player perform the spore-spitting action
- Return:
<list>: list of new spores
- get_keys_sort_by_balls()[source]
- Overview:
Sort by ball score from largest to smallest
- Return:
<list>: list of names
- move(direction=None, duration=0.05)[source]
- Overview:
Move all balls controlled by the player The main logic is
Processing stopped state
If it is stopping, control all balls to move closer to the center of mass
- Parameters:
direction <Vector2>: A point in the unit circle duration <float>: time
- Returns:
position <Vector2>: position after moving
render
BaseRender
EnvRender
RealtimeRender
RealtimePartialRender
- class gobigger.render.realtime_render.RealtimePartialRender(game_screen_width=512, game_screen_height=512, info_width=0, info_height=0, with_show=True)[source]
- Overview:
Used in real-time games to give the player a visible field of view. The corresponding player can be obtained by specifying the player name. The default is the first player
server
Server
utils
Border
- class gobigger.utils.structures.Border(minx, miny, maxx, maxy, random_generator=None)[source]
- Overview:
used to specify a rectangular range
BaseCollisionDetection
ExhaustiveCollisionDetection
- class gobigger.utils.collision_detection.ExhaustiveCollisionDetection(border: Border)[source]
- Overview:
Exhaustive Algorithm
- solve(query_list: list, gallery_list: list)[source]
- Overview:
For the balls in the query, enumerate each ball in the gallery to determine whether there is a collision
- Parameters:
query_list <List[BaseBall]>: List of balls that need to be queried for collision gallery_list <List[BaseBall]>: List of all balls
- Returns:
- results <Dict[int: List[BaseBall]> return value
- int value denotes:
the subscript in query_list
- string value denotes:
List of balls that collided with the query corresponding to the subscript
PrecisionCollisionDetection
- class gobigger.utils.collision_detection.PrecisionCollisionDetection(border: Border, precision: int = 50)[source]
- Overview:
Precision Approximation Algorithm Divide the map into several rows according to the accuracy that has been set, dynamically maintain the row information in each frame, and search by row
- get_row(x) int [source]
- Overview:
Get the row coordinates of the ball
- Parameter:
node <BaseBall>: The ball need to get its row coordinates
- solve(query_list: list, gallery_list: list)[source]
- Overview:
First, you need to sort the balls in each row according to the ordinate. For the balls in query_list, first abstract the boundary of the ball into a rectangle, then traverse each row in the rectangle, and find the first ball covered by the query through dichotomy in each row, and then Enumerate the balls in sequence until the ordinate exceeds the boundary of the query rectangle.
- Parameters:
query_list <List[BaseBall]>: List of balls that need to be queried for collision gallery_list <List[BaseBall]>: List of all balls
- Returns:
- results <Dict[int: List[BaseBall]> return value
- int value denotes:
the subscript in query_list
- string value denotes:
List of balls that collided with the query corresponding to the subscript
RebuildQuadTreeCollisionDetection
- class gobigger.utils.collision_detection.RebuildQuadTreeCollisionDetection(border: Border, node_capacity=64, tree_depth=32)[source]
- Overview:
Build a quadtree on a two-dimensional plane in every frame, and query collisions in the quadtree
- solve(query_list: list, gallery_list: list)[source]
- Overview:
Construct a quadtree from scratch based on gallery_list and complete the query
- Parameters:
query_list <List[BaseBall]>: List of balls that need to be queried for collision gallery_list <List[BaseBall]>: List of all balls
- Returns:
- results <Dict[int: List[BaseBall]> return value
- int value denotes:
the subscript in query_list
- string value denotes:
List of balls that collided with the query corresponding to the subscript
RemoveQuadTreeCollisionDetection
- class gobigger.utils.collision_detection.RemoveQuadTreeCollisionDetection(border: Border, node_capacity=64, tree_depth=32)[source]
- Overview:
Add delete operations for the quadtree, and dynamically maintain a quadtree
- solve(query_list: list, changed_node_list: list)[source]
- Overview:
Update the points in the quadtree according to the changed_node_list and complete the query
- Parameters:
query_list <List[BaseBall]>: List of balls that need to be queried for collision gallery_list <List[BaseBall]>: List of all balls
- Returns:
- results <Dict[int: List[BaseBall]> return value
- int value denotes:
the subscript in query_list
- string value denotes:
List of balls that collided with the query corresponding to the subscript