Skip to content

[envpool] fix multiplayer players.env_id inference - #347

Merged
Trinkle23897 merged 4 commits into
mainfrom
jiayi/fix-multiplayer-players-env-id
Mar 23, 2026
Merged

[envpool] fix multiplayer players.env_id inference#347
Trinkle23897 merged 4 commits into
mainfrom
jiayi/fix-multiplayer-players-env-id

Conversation

@Trinkle23897

Copy link
Copy Markdown
Collaborator

Summary

  • Problem: the simplified Python multiplayer action path was filling players.env_id with the batch env_id, so flattened per-player actions were grouped against the wrong environments when an env contributed more than one player action.
  • Scope: infer players.env_id from the incoming Python action payload, reuse the latest observed player-to-env mapping when player counts vary by env, and add Python-side regression coverage for the multiplayer wrapper path.
  • Outcome: multiplayer actions sent through the shorthand Python API now preserve the correct per-player env mapping instead of silently slicing the action buffer incorrectly.

This fixes the Python wrapper bug behind issue #296 without changing the C++ action parser contract.

Technical Details

  • Approach: teach EnvPoolMixin._from() to derive players.env_id from player-shaped action arrays, fall back to the cached info:players.env_id mapping from the last recv(), and raise when the mapping is ambiguous instead of fabricating a wrong one.
  • Code pointers:
    • envpool/python/envpool.py: adds players.env_id inference and caches info:players.env_id on recv() for variable-player batches.
    • envpool/dummy/dummy_py_envpool_test.py: adds regression coverage around the real dummy DM wrapper for uniform multiplayer, cached variable-player, explicit mapping, and ambiguous-input cases.
    • envpool/dummy/BUILD: wires the dummy Python test to the Python API wrapper target.
  • Notes: the regression test now uses the existing dummy env wrapper rather than a standalone fake mixin harness.

Test Plan

Automated

  • python3 -m py_compile envpool/python/envpool.py envpool/dummy/dummy_py_envpool_test.py: passed.

Suggested Manual

  • USE_BAZEL_VERSION=8.6.0 bazelisk test //envpool/dummy:dummy_py_envpool_test --config=test --spawn_strategy=local --test_output=errors: exercise the real dummy wrapper path on Linux.
  • Re-run the issue [BUG] incorrect parsing of actions in multiagent environment #296 repro against this branch on dev-0: confirm the flattened multiplayer action now expands to the expected players.env_id sequence instead of the old one-element-per-env mapping.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2dad8c18e9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread envpool/python/envpool.py
Comment on lines +209 to +211
if "info:players.env_id" in state:
self._last_players_env_id = np.array(
state["info:players.env_id"], copy=True

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep player/env mappings per env instead of last batch

In async usage, send() can target any env_id subset, not just the batch returned by the most recent recv(). This code overwrites a single _last_players_env_id array on every recv(), so if a caller aggregates multiple recv() batches before sending actions, the older envs lose their cached player mapping and _cached_players_env_id() falls back to uniform inference or raises. For variable-player envs that means Env::ParseAction() in envpool/core/env.h slices the flattened player arrays against the wrong environments.

Useful? React with 👍 / 👎.

Comment thread envpool/python/envpool.py
Comment on lines +87 to +90
if env_id.shape[0] == 0 or player_count % env_id.shape[0] != 0:
raise RuntimeError(
"Cannot infer players.env_id for multiplayer action; "
"pass a dict action with explicit players.env_id."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject divisible-but-ambiguous player counts

This only treats non-divisible totals as ambiguous. When the cache is unavailable, a batch like env_id=[0,1] with 4 player actions is still ambiguous for variable-player envs (1+3, 2+2, and 3+1 are all possible; the dummy multiplayer env can produce 1+3 because each env’s player count advances independently). The code then fabricates a uniform players.env_id split, and Env::ParseAction() groups some players’ actions under the wrong env instead of surfacing the ambiguity.

Useful? React with 👍 / 👎.

@Trinkle23897 Trinkle23897 linked an issue Mar 23, 2026 that may be closed by this pull request
@Trinkle23897
Trinkle23897 merged commit c5c56fe into main Mar 23, 2026
2 of 4 checks passed
@Trinkle23897
Trinkle23897 deleted the jiayi/fix-multiplayer-players-env-id branch March 23, 2026 22:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] incorrect parsing of actions in multiagent environment

1 participant