CodePraxis Football
Write a Python agent that plays football. Test it on your laptop, watch it play, record videos, and score it the same way the judges do.
Install
pip install codepraxis-football # Python 3.12 or newer; Mac, Linux, Windows
codepraxis-football doctor # checks the engine, rendering and video
codepraxis-football init my-agent # sample agent + this guide + a practice level
cd my-agent
On a Linux server or a minimal Linux install, the game needs the system OpenGL libraries:
sudo apt install libgl1 libegl1 (desktops already have them). No GPU is needed.
Try it
codepraxis-football play shoot_keeper # play it yourself with the keyboard
codepraxis-football watch agent.py shoot_keeper # watch your agent in a window
codepraxis-football eval agent.py shoot_keeper # official score: 100 seeded episodes
codepraxis-football video agent.py shoot_keeper -o a.mp4 # record without a window
codepraxis-football watch-match agent.py random match_5v5 # two agents live: yellow vs blue
codepraxis-football match agent.py other.py match_5v5 # same, no window, JSON result
codepraxis-football levels # every level
The window and videos hold the picture for a moment after goals, cards and set pieces.
Add --fast to skip that. Training and eval never pause.
The 3D view (window, video --view 3d) runs extra engine code that changes how a match plays out, so the
same seed can end differently there than in eval. video --view topdown shows exactly what eval scored.
Keyboard: arrows move, hold e sprint, hold c dribble, s short pass, a high pass,
w long pass, d shoot, x slide tackle, Esc quit.
Write an agent
An agent is a file with one function. It gets what its player sees and returns one action:
from codepraxis_football import Action
def agent(obs):
me = obs['left_team'][obs['active']]
if me[0] > 0.7:
return Action.SHOT
return Action.RIGHT
Agents that need memory can use a class instead:
class Agent:
def reset(self): # start of every episode
self.steps = 0
def act(self, obs):
self.steps += 1
return Action.RIGHT
Optional settings at the top of the file:
| Setting | Default | Meaning |
|---|---|---|
OBSERVATION |
'raw' |
'raw' (dict), 'vector' (115 numbers), 'minimap' (72x96x4), 'pixels' (72x96x3, slow) |
PLAYERS |
1 |
How many of our players you control. With more than 1, obs is a list and you return a list |
The pitch
x runs from -1 (our goal) to 1 (the goal you attack). y runs from -0.42 (top) to 0.42 (bottom).
You always attack to the right, also when the judges play your agent as the other team.
Raw observation fields
| Field | Meaning |
|---|---|
ball |
[x, y, z] ball position (z = height) |
ball_direction |
[x, y, z] ball movement per step |
ball_owned_team |
-1 nobody, 0 us, 1 them |
ball_owned_player |
index of the player with the ball |
left_team, right_team |
[x, y] of every player (left = us) |
left_team_direction, right_team_direction |
movement per step of every player |
left_team_roles, right_team_roles |
0 GK, 1 CB, 2 LB, 3 RB, 4 DM, 5 CM, 6 LM, 7 RM, 8 AM, 9 CF |
left_team_tired_factor, right_team_tired_factor |
0 fresh to 1 exhausted |
left_team_yellow_card, left_team_active (and right) |
cards; active False = sent off |
active |
index (in left_team) of the player you control |
sticky_actions |
10 flags: 8 directions, sprint, dribble (on until released) |
score |
[ours, theirs] |
steps_left |
steps until the episode ends |
game_mode |
0 normal, 1 kick-off, 2 goal kick, 3 free kick, 4 corner, 5 throw-in, 6 penalty |
Actions
| # | Action | # | Action |
|---|---|---|---|
| 0 | IDLE | 10 | HIGH_PASS |
| 1-8 | LEFT, TOP_LEFT, TOP, TOP_RIGHT, RIGHT, BOTTOM_RIGHT, BOTTOM, BOTTOM_LEFT | 11 | SHORT_PASS |
| 9 | LONG_PASS | 12 | SHOT |
| 13 | SPRINT | 14 | RELEASE_DIRECTION |
| 15 | RELEASE_SPRINT | 16 | SLIDING |
| 17 | DRIBBLE | 18 | RELEASE_DRIBBLE |
Directions, sprint and dribble stay on until released. Passes and shots go the way the player faces.
Use it from Python (training)
import codepraxis_football as cpf
env = cpf.make('shoot_keeper', observation='vector') # Gymnasium API
obs, info = env.reset(seed=0)
obs, reward, terminated, truncated, info = env.step(cpf.Action.SHOT)
reward is +1 for our goal and -1 for theirs. With no window the game runs at several hundred
steps per second per CPU core; run one environment per core to train faster:
import gymnasium as gym
def make_env():
return cpf.make('shoot_keeper', observation='vector')
if __name__ == '__main__':
envs = gym.vector.AsyncVectorEnv([make_env] * 4) # 4 processes
obs, info = envs.reset(seed=[0, 1, 2, 3])
On a 2024 laptop, 4 environments run ~1,500 steps/s: a million training steps in about 11 minutes.
Reinforcement learning
Any library that speaks Gymnasium works. With Stable-Baselines3 (pip install stable-baselines3):
from stable_baselines3 import PPO
from stable_baselines3.common.vec_env import SubprocVecEnv, VecMonitor
import codepraxis_football as cpf
def make_env():
return cpf.make('shoot_keeper', observation='vector', reward='checkpoints')
if __name__ == '__main__':
envs = VecMonitor(SubprocVecEnv([make_env] * 4))
model = PPO('MlpPolicy', envs, n_steps=512, batch_size=512, gamma=0.993)
model.learn(total_timesteps=2_000_000)
model.save('model')
reward='checkpoints' adds small rewards for carrying the ball towards the goal, so learning
starts long before the first goal. Use the saved model as an agent:
import os
from stable_baselines3 import PPO
OBSERVATION = 'vector'
model = PPO.load(os.path.join(os.path.dirname(__file__), 'model.zip')) # next to agent.py
def agent(obs):
return int(model.predict(obs, deterministic=True)[0])
Scoring
eval runs your agent for 100 episodes with fixed seeds and prints JSON: goal_rate
(episodes where you scored), avg_steps_to_goal, wins/draws/losses, timeouts and errors.
A step slower than 50 ms counts as IDLE. If your agent raises an error, that episode scores
nothing and the rest still run. The judges use the same command with seeds you haven't seen.
Make your own practice level
See my_level.py from init. Use a level file anywhere a level name goes:
codepraxis-football watch agent.py my_level.py.
Metadata
Release files for codepraxis-football 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
Total release size: 10.7 MB
Release files / codepraxis_football-0.1.0-cp312-abi3-win_amd64.whl
| Download URL | codepraxis_football-0.1.0-cp312-abi3-win_amd64.whl |
|---|---|
| Size | 1.9 MB |
| Tags | CPython 3.12 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
9e5fcb3015d4694f9bdf02fa0e29d3a8a1ad3331bc04297a636e5498e72c5d28
|
|
BLAKE2b-256 checksum How to use checksums |
1124720e0430408dc732a6869d78a3586be9f1fda1957808ce2488265232c473
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.2
|
Release files / codepraxis_football-0.1.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
| Download URL | codepraxis_football-0.1.0-cp312-abi3-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl |
|---|---|
| Size | 2.6 MB |
| Tags | CPython 3.12 Linux glibc 2.27+ x86-64 Linux glibc 2.28+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
35a8ff8072ff6d70d4a0b3e4584c78890c43e28c3e84c489cd882cced2c3e7c9
|
|
BLAKE2b-256 checksum How to use checksums |
d2808867578661ffa85820b227aff9e8c933f3e6264f41cace492b21cd4a5686
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.2
|
Release files / codepraxis_football-0.1.0-cp312-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl
| Download URL | codepraxis_football-0.1.0-cp312-abi3-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.12 Linux glibc 2.27+ ARM64 Linux glibc 2.28+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
6e0f9a05f27c0c476557d9e0bf224b5c5da5e44740e2a1ae410ebd140612733f
|
|
BLAKE2b-256 checksum How to use checksums |
4c0feb143db3e2cf7cdd2d4924241eff6ff1d64391e586e47ffac20bb25afdb0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.2
|
Release files / codepraxis_football-0.1.0-cp312-abi3-macosx_11_0_arm64.whl
| Download URL | codepraxis_football-0.1.0-cp312-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 1.8 MB |
| Tags | CPython 3.12 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
10d590050226928a384ff9484b3d32cd749dc50a1da58bcea4cf271d3806023f
|
|
BLAKE2b-256 checksum How to use checksums |
921142e6ad4b078b8ce0d534adb1ad8205dae4f52152c0352cd7a80a66133982
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.2
|
Release files / codepraxis_football-0.1.0-cp312-abi3-macosx_10_15_x86_64.whl
| Download URL | codepraxis_football-0.1.0-cp312-abi3-macosx_10_15_x86_64.whl |
|---|---|
| Size | 2.0 MB |
| Tags | CPython 3.12 abi3 macOS 10.15+ x86-64 |
|
SHA-256 checksum How to use checksums |
101785e7bf388c7f82f21bb581f2582fafccb1614b556e556bf2cb507eb3d848
|
|
BLAKE2b-256 checksum How to use checksums |
c703ced7b9abcb9342a4becc35e207320918058f37d1b61f6b9f308743c584e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.15.2
|
Security for codepraxis-football 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.