Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
4e68ceb
update README.md
Ipsedo Aug 7, 2026
38cae81
* miss distance scale at 10.0
Ipsedo Aug 8, 2026
88d62d9
constant target entropy for sac
Ipsedo Aug 8, 2026
44cbc96
lower initt sigma
Ipsedo Aug 8, 2026
58a2b6c
higher entropy coef for ppo
Ipsedo Aug 8, 2026
b2932ee
* no fire cost -> collapse entropy ptherwise
Ipsedo Aug 9, 2026
d2e884a
fix sac : esperance of min and not min of esperances
Ipsedo Aug 9, 2026
0650105
learned coef for ppo entropies
Ipsedo Aug 10, 2026
369626a
normalize reward with std for SAC
Ipsedo Aug 10, 2026
58fe084
increase continuous target entropy (from sigma 0.1 to 0.3)
Ipsedo Aug 10, 2026
f1e98b3
increase contunous target entropy for sac (sigma 0.1 to 0.3)
Ipsedo Aug 10, 2026
ec841d8
remaining frames as a terminal step =x penalty like death
Ipsedo Aug 10, 2026
8bc0b9a
torch check for uint8 at vision network : no runtime_error -> it is a…
Ipsedo Aug 10, 2026
0e4649e
lower sigma for continuous target entropy (from 0.3 to 0.1)
Ipsedo Aug 11, 2026
4b77642
actor init sigma to 0.1
Ipsedo Aug 11, 2026
2076ec7
actor init sigma to 0.1
Ipsedo Aug 11, 2026
f393fc2
lower sigma for continuous target entropy of SAC (from 0.3 to 0.1)
Ipsedo Aug 11, 2026
c1a18e5
lower sigma for continuous target entropy (from 0.3 to 0.1)
Ipsedo Aug 11, 2026
c6dfa53
* fix discrete head init to be target fire probability
Ipsedo Aug 12, 2026
c8b8057
designation
Ipsedo Aug 12, 2026
1c5b32e
initial alpha temperature initialized to right values (SAC & PPO)
Ipsedo Aug 12, 2026
e65fca2
fix ppo :
Ipsedo Aug 12, 2026
e5b8d5c
centralized constants
Ipsedo Aug 12, 2026
cada611
* try without potential reward shaping
Ipsedo Aug 13, 2026
3d26b81
scientific format for reward metric
Ipsedo Aug 13, 2026
1876274
remove metric (wrong because add dead tank rewards)
Ipsedo Aug 13, 2026
6591e17
refactor
Ipsedo Aug 13, 2026
a67dc31
add clang-tidy to ignore nodiscard
Ipsedo Aug 13, 2026
399f068
fix warnings
Ipsedo Aug 13, 2026
29b636b
fix warnings
Ipsedo Aug 13, 2026
7d78f8a
fix warnings
Ipsedo Aug 13, 2026
24a6bb6
fix last metric
Ipsedo Aug 13, 2026
195193a
* target sigma from 0.1 to 0.2
Ipsedo Aug 13, 2026
24f1708
constant entropy coefficient for PPO + smaller spawn zone
Ipsedo Aug 13, 2026
6d9f818
* shell reserve regeneration (1 shell each 1.5s)
Ipsedo Aug 14, 2026
f4fd34a
one alpha per continuous action (PPO under training, do the same for …
Ipsedo Aug 16, 2026
f38db53
update target sigma and target fire proba + higher lr for alphas in ppo
Ipsedo Aug 16, 2026
42e769f
fix+refactor multi alpha
Ipsedo Aug 16, 2026
4fffd25
fix continuous target entropy depending on mu (compute entropy per ba…
Ipsedo Aug 16, 2026
ba2b61b
rename variable
Ipsedo Aug 16, 2026
4f51da4
refactor
Ipsedo Aug 16, 2026
5e26ce6
refactor
Ipsedo Aug 16, 2026
15ef7ad
rename class (clamped alphas)
Ipsedo Aug 16, 2026
43fc473
fix entropy in PPO and SAC
Ipsedo Aug 16, 2026
c35e453
harmonize PPO entropy shape like SAC
Ipsedo Aug 16, 2026
3ca9ffd
* re-add fire cost
Ipsedo Aug 17, 2026
6dc2faa
update reward : ratio = 1.5 * miss / sqrt(distance)
Ipsedo Aug 17, 2026
8ec924e
no reward norm for SAC
Ipsedo Aug 17, 2026
01badec
PPO : continue training on other minibatch when kl exceed
Ipsedo Aug 17, 2026
38acf00
PPO : continue training on other minibatch when kl exceed
Ipsedo Aug 17, 2026
1d71c95
refactor ambiguity between params (initial/target sigma & fire proba)…
Ipsedo Aug 17, 2026
3cb600c
initialization style
Ipsedo Aug 17, 2026
816ea67
fix kl in ppo
Ipsedo Aug 18, 2026
060c899
fix windows build
Ipsedo Aug 18, 2026
39da94f
lower continuous entropy coef and lower miss distance scale
Ipsedo Aug 18, 2026
1764289
Big fix : damages on shell contact
Ipsedo Aug 18, 2026
c747112
* fix set train to false (LayerNorm & GroupNorm)
Ipsedo Aug 19, 2026
5042981
add critic ev metric
Ipsedo Aug 19, 2026
5f41fc1
re-add alpha parameters for PPO => per continuous action alpha
Ipsedo Aug 19, 2026
12f3fe0
remove comment
Ipsedo Aug 19, 2026
2acc712
update SAC hyperparams
Ipsedo Aug 19, 2026
8fdb9ce
initial sigma for SAC
Ipsedo Aug 19, 2026
8a6e078
add trained model
Ipsedo Aug 20, 2026
f39b3b2
* train ppo actor entropy & action only if kl not exceeded
Ipsedo Aug 20, 2026
934b061
PID Lagrangian for entropy adjustment in PPO
Ipsedo Aug 20, 2026
93c271a
PID Lagrangian for entropy adjustment in PPO : fix discrete
Ipsedo Aug 20, 2026
eaec694
fix pid lagrangian
Ipsedo Aug 20, 2026
6631566
* sample or not for torch agent
Ipsedo Aug 21, 2026
5ed7139
add trained model that works
Ipsedo Aug 21, 2026
5f645da
fix CI glm::mat4 instead of {1.f}
Ipsedo Aug 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
# Checks désactivés pour tout le projet (clang-tidy n'est utilisé que par l'IDE :
# ni le build CMake ni la CI ne le lancent).
#
# modernize-use-nodiscard : réclame [[nodiscard]] sur toute méthode const
# renvoyant une valeur — trop bruyant pour les nombreux getters du projet.
Checks: '-modernize-use-nodiscard'
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ A battle-royal game with trained agent which controls tanks in realistic physic

## Description

Each agent receives the rendered frame of its camera as input, and it is trained to fire and hit enemies.
Each tank receives the rendered frame of its camera as input, and the agent is trained to fire and hit enemies.

When agent is trained (with SAC algorithm) you can fight against other tanks.
When the agent is trained (with the PPO or SAC algorithm), you can fight it through the tanks it handles.

## Installation

Expand Down
3 changes: 0 additions & 3 deletions arenai_agent/src/agents/agent_cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,4 @@ namespace arenai::agent {
return algorithms;
}

AgentCli get_default_agent_cli() {
return make_agent_cli<SacHyperParams, SacTorchAgentFactory>("sac", sac_cli_fields());
}
}// namespace arenai::agent
3 changes: 1 addition & 2 deletions arenai_agent/src/agents/agent_cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ namespace arenai::agent {
create_factory;
};

// the first entry is the algorithm used when no subcommand is given
std::vector<AgentCli> make_agent_clis();

AgentCli get_default_agent_cli();

}// namespace arenai::agent

#endif//ARENAI_ALGORITHMS_H
3 changes: 2 additions & 1 deletion arenai_agent/src/agents/factory_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ namespace arenai::agent {
.channels,
get_value<group_norm_nums>(
"group_norm_nums", parse_cli_group_norms, {{{1, 2, 3, 4, 6, 8}}})
.groups),
.groups,
0.f, 0.f),
get_value<bool>("cuda", false) ? torch::kCUDA : torch::kCPU);
}

Expand Down
9 changes: 5 additions & 4 deletions arenai_agent/src/agents/ppo/ppo_agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ namespace arenai::agent {
std::vector<core::Action> TorchPpoAgent::act(
const std::vector<core::State> &states, const int vision_height, const int vision_width) {
const auto [continuous_action, discrete_action] =
act(states_to_tensor(states, vision_height, vision_width));
act(states_to_tensor(states, vision_height, vision_width), false);
return tensor_to_actions(continuous_action, discrete_action);
}

TorchAction TorchPpoAgent::act(const TorchState &state) {
TorchAction TorchPpoAgent::act(const TorchState &state, const bool sample) {
TorchAction action;
torch::Tensor continuous_log_prob;
torch::Tensor discrete_log_prob;
Expand All @@ -44,8 +44,9 @@ namespace arenai::agent {
const auto &[vision, sensors] = state;
const auto &[mu, sigma, discrete_proba] = actor->act(vision, sensors);

action.continuous_action = truncated_normal_sample(mu, sigma);
action.discrete_action = multinomial_sample(discrete_proba);
action.continuous_action = sample ? truncated_normal_sample(mu, sigma) : mu;
action.discrete_action = sample ? multinomial_sample(discrete_proba)
: multinomial_max_action(discrete_proba);

// old log-probabilities, kept for the PPO importance ratio
continuous_log_prob =
Expand Down
2 changes: 1 addition & 1 deletion arenai_agent/src/agents/ppo/ppo_agent.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace arenai::agent {
const std::shared_ptr<Actor> &actor, torch::Device device,
std::optional<std::shared_ptr<PpoStepCollector>> collector = std::nullopt);

TorchAction act(const TorchState &state) override;
TorchAction act(const TorchState &state, bool sample) override;

std::vector<core::Action>
act(const std::vector<core::State> &states, int vision_height, int vision_width) override;
Expand Down
6 changes: 2 additions & 4 deletions arenai_agent/src/agents/ppo/ppo_collector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@ namespace arenai::agent {
last_discrete_log_prob = discrete_log_prob;
}

void PpoStepCollector::on_transition(
const torch::Tensor &rewards, const torch::Tensor &done, const torch::Tensor &truncated) {
void PpoStepCollector::on_transition(const torch::Tensor &rewards, const torch::Tensor &done) {
rollout_buffer->add(
{.state = last_state,
.action = last_action,
.continuous_log_prob = last_continuous_log_prob,
.discrete_log_prob = last_discrete_log_prob,
.reward = rewards,
.done = done,
.truncated = truncated});
.done = done});
}

void PpoStepCollector::on_episode_end(const TorchState &final_state) {
Expand Down
4 changes: 1 addition & 3 deletions arenai_agent/src/agents/ppo/ppo_collector.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ namespace arenai::agent {
const TorchState &state, const TorchAction &action,
const torch::Tensor &continuous_log_prob, const torch::Tensor &discrete_log_prob);

void on_transition(
const torch::Tensor &rewards, const torch::Tensor &done,
const torch::Tensor &truncated) override;
void on_transition(const torch::Tensor &rewards, const torch::Tensor &done) override;

void on_episode_end(const TorchState &final_state) override;

Expand Down
14 changes: 7 additions & 7 deletions arenai_agent/src/agents/ppo/ppo_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ namespace arenai::agent {
: actor(std::make_shared<Actor>(
vision_height, vision_width, nb_sensors, nb_continuous_actions, nb_discrete_actions,
params.hidden_size_sensors, params.actor_hidden_sizes, params.vision_channels,
params.group_norm_nums)),
params.group_norm_nums, params.initial_sigma, params.initial_fire_proba)),
rollout_buffer(std::make_shared<PpoRolloutBuffer>()),
collector(std::make_shared<PpoStepCollector>(rollout_buffer)),
agent(std::make_shared<TorchPpoAgent>(actor, device, collector)),
trainer(std::make_shared<PpoTrainer>(
actor, rollout_buffer, vision_height, vision_width, nb_sensors,
params.actor_learning_rate, params.critic_learning_rate, params.hidden_size_sensors,
params.critic_hidden_sizes, params.vision_channels, params.group_norm_nums, device,
params.metric_window_size, params.gamma, params.gae_lambda, params.clip_epsilon,
params.target_kl, params.grad_norm_max, params.continuous_entropy_coef,
params.discrete_entropy_coef, params.epochs, params.rollout_size,
actor, rollout_buffer, vision_height, vision_width, nb_sensors, nb_continuous_actions,
params.actor_learning_rate, params.critic_learning_rate, params.alpha_learning_rate,
params.hidden_size_sensors, params.critic_hidden_sizes, params.vision_channels,
params.group_norm_nums, device, params.metric_window_size, params.gamma,
params.gae_lambda, params.clip_epsilon, params.target_kl, params.grad_norm_max,
params.target_sigma, params.target_fire_proba, params.epochs, params.rollout_size,
params.minibatch_size)) {}

std::shared_ptr<AbstractTorchAgent> PpoTorchAgentFactory::get_agent() { return agent; }
Expand Down
39 changes: 21 additions & 18 deletions arenai_agent/src/agents/ppo/ppo_hyperparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,27 @@ namespace arenai::agent {

std::vector<CliField<PpoHyperParams>> ppo_cli_fields() {
return {
{"--actor_learning_rate", &PpoHyperParams::actor_learning_rate},
{"--critic_learning_rate", &PpoHyperParams::critic_learning_rate},
{"--hidden_size_sensors", &PpoHyperParams::hidden_size_sensors},
{"--actor_hidden_sizes", &PpoHyperParams::actor_hidden_sizes},
{"--critic_hidden_sizes", &PpoHyperParams::critic_hidden_sizes},
{"--vision_channels", &PpoHyperParams::vision_channels},
{"--group_norm_nums", &PpoHyperParams::group_norm_nums},
{"--metric_window_size", &PpoHyperParams::metric_window_size},
{"--gamma", &PpoHyperParams::gamma},
{"--gae_lambda", &PpoHyperParams::gae_lambda},
{"--clip_epsilon", &PpoHyperParams::clip_epsilon},
{"--target_kl", &PpoHyperParams::target_kl},
{"--grad_norm_max", &PpoHyperParams::grad_norm_max},
{"--continuous_entropy_coef", &PpoHyperParams::continuous_entropy_coef},
{"--discrete_entropy_coef", &PpoHyperParams::discrete_entropy_coef},
{"--epochs", &PpoHyperParams::epochs},
{"--rollout_size", &PpoHyperParams::rollout_size},
{"--minibatch_size", &PpoHyperParams::minibatch_size},
{.name = "--actor_learning_rate", .member = &PpoHyperParams::actor_learning_rate},
{.name = "--critic_learning_rate", .member = &PpoHyperParams::critic_learning_rate},
{.name = "--alpha_learning_rate", .member = &PpoHyperParams::alpha_learning_rate},
{.name = "--hidden_size_sensors", .member = &PpoHyperParams::hidden_size_sensors},
{.name = "--actor_hidden_sizes", .member = &PpoHyperParams::actor_hidden_sizes},
{.name = "--critic_hidden_sizes", .member = &PpoHyperParams::critic_hidden_sizes},
{.name = "--vision_channels", .member = &PpoHyperParams::vision_channels},
{.name = "--group_norm_nums", .member = &PpoHyperParams::group_norm_nums},
{.name = "--initial_sigma", .member = &PpoHyperParams::initial_sigma},
{.name = "--initial_fire_proba", .member = &PpoHyperParams::initial_fire_proba},
{.name = "--metric_window_size", .member = &PpoHyperParams::metric_window_size},
{.name = "--gamma", .member = &PpoHyperParams::gamma},
{.name = "--gae_lambda", .member = &PpoHyperParams::gae_lambda},
{.name = "--clip_epsilon", .member = &PpoHyperParams::clip_epsilon},
{.name = "--target_kl", .member = &PpoHyperParams::target_kl},
{.name = "--grad_norm_max", .member = &PpoHyperParams::grad_norm_max},
{.name = "--target_sigma", .member = &PpoHyperParams::target_sigma},
{.name = "--target_fire_proba", .member = &PpoHyperParams::target_fire_proba},
{.name = "--epochs", .member = &PpoHyperParams::epochs},
{.name = "--rollout_size", .member = &PpoHyperParams::rollout_size},
{.name = "--minibatch_size", .member = &PpoHyperParams::minibatch_size},
};
}

Expand Down
17 changes: 8 additions & 9 deletions arenai_agent/src/agents/ppo/ppo_hyperparams.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,24 @@ namespace arenai::agent {
struct PpoHyperParams {
float actor_learning_rate = 1e-4f;
float critic_learning_rate = 3e-4f;
float alpha_learning_rate = 1e-3f;
int hidden_size_sensors = 128;
std::vector<int> actor_hidden_sizes = {1024, 512};
std::vector<int> critic_hidden_sizes = {1024, 512};
std::vector<std::tuple<int, int>> vision_channels = {{3, 8}, {8, 16}, {16, 24},
{24, 32}, {32, 48}, {48, 64}};
std::vector<int> group_norm_nums = {1, 2, 3, 4, 6, 8};
float initial_sigma = 0.4f;
float initial_fire_proba = 0.025f;
int metric_window_size = 256;
// 0.997 at 30 Hz -> ~11 s credit horizon (shell flight time + fights stay visible)
float gamma = 0.997f;
// 0.98: a shell resolving 30-60 steps after the fire still reaches the fire
// decision at x0.25-0.5 through GAE, instead of x0.04-0.2 with 0.95
float gamma = 0.99f;
float gae_lambda = 0.98f;
float clip_epsilon = 0.2f;
// early-stop of the epoch loop when approx KL > 1.5 * target_kl; <= 0 disables it
float target_kl = 0.02f;
float target_kl = 0.05f;
float grad_norm_max = 0.5f;
float continuous_entropy_coef = 0.0005f;
float discrete_entropy_coef = 0.005f;
int epochs = 4;
float target_sigma = 0.4f;
float target_fire_proba = 0.025f;
int epochs = 2;
int rollout_size = 30 * 30;
int minibatch_size = 1024;
};
Expand Down
10 changes: 2 additions & 8 deletions arenai_agent/src/agents/ppo/ppo_rollout_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ namespace arenai::agent {
// tanks already terminated before this step have no valid transition to store
const auto valid = already_terminated_.logical_not();
already_terminated_.logical_or_(
step.done.detach()
.cpu()
.to(torch::kBool)
.reshape({nb_tanks})
.logical_or(step.truncated.detach().cpu().to(torch::kBool).reshape({nb_tanks})));
step.done.detach().cpu().to(torch::kBool).reshape({nb_tanks}));

steps_.push_back(
{.step =
Expand All @@ -42,8 +38,7 @@ namespace arenai::agent {
.continuous_log_prob = step.continuous_log_prob.detach().cpu(),
.discrete_log_prob = step.discrete_log_prob.detach().cpu(),
.reward = step.reward.detach().cpu(),
.done = step.done.detach().cpu(),
.truncated = step.truncated.detach().cpu()},
.done = step.done.detach().cpu()},
.valid = valid});

// the freshly added step is pending: its closing observation is not known yet
Expand Down Expand Up @@ -93,7 +88,6 @@ namespace arenai::agent {
stack([](const StoredStep &s) { return s.step.discrete_log_prob; }),
.rewards = stack([](const StoredStep &s) { return s.step.reward; }),
.dones = stack([](const StoredStep &s) { return s.step.done; }),
.truncateds = stack([](const StoredStep &s) { return s.step.truncated; }),
.bootstrap_state = bootstrap_state,
.valids = stack([](const StoredStep &s) { return s.valid; }).unsqueeze(-1)};

Expand Down
4 changes: 1 addition & 3 deletions arenai_agent/src/agents/ppo/ppo_rollout_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ namespace arenai::agent {
torch::Tensor discrete_log_prob;
torch::Tensor reward;
torch::Tensor done;
torch::Tensor truncated;
};

// On-policy rollout stacked on the time dimension: every tensor is [T, nb_tanks, ...]
Expand All @@ -32,7 +31,6 @@ namespace arenai::agent {
torch::Tensor discrete_log_probs;
torch::Tensor rewards;
torch::Tensor dones;
torch::Tensor truncateds;
// [nb_tanks, ...] observation closing the last step, for the value bootstrap
TorchState bootstrap_state;
// [T, nb_tanks, 1] whether the (step, tank) pair is a live transition
Expand Down Expand Up @@ -62,7 +60,7 @@ namespace arenai::agent {
// observation closing the last stored step, set by finish_episode()
std::optional<TorchState> final_state_;

// [nb_tanks] tanks already done/truncated in the current episode
// [nb_tanks] tanks already done in the current episode
torch::Tensor already_terminated_;
};

Expand Down
Loading
Loading