Skip to content

Enforce unique, nonempty labels for players - #979

Merged
tturocy merged 10 commits into
gambitproject:masterfrom
d-kad:player-labels
Jul 9, 2026
Merged

Enforce unique, nonempty labels for players#979
tturocy merged 10 commits into
gambitproject:masterfrom
d-kad:player-labels

Conversation

@d-kad

@d-kad d-kad commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Issues closed by this PR

Description of the changes in this PR

Enforces the label rules for players, following #978 (nodes and information sets). Players are a non-empty, unique-within-game scope, enforced in GamePlayerRep::SetLabel:

  • A player label must be non-empty, valid, and unique among the game's players; a violating label raises ValueError.
  • The chance player is labeled "Chance", set through the constructor, and its label is reserved: SetLabel rejects any attempt to relabel it.
  • add_player now requires a label (no default, no auto-generation).

@d-kad d-kad added this to the gambit-16.7.0 milestone Jul 8, 2026
@d-kad d-kad added c++ Items which involve writing in C++ cython Items which involve coding in Cython labels Jul 8, 2026
@tturocy

tturocy commented Jul 8, 2026

Copy link
Copy Markdown
Member

I have pushed some fixes to the GUI. The previous changes were assuming that "Player (n+1)" would necessarily be a unique label, which it might not be. This corrects that (and centralises the unique label generation to a single site).

In the Python tests, we don't have a test to confirm that trying to create a player with a duplicate or empty label fails, and further that doing so leaves the game unchanged.

Comment thread src/pygambit/game.pxi Outdated
if str(label) != "":
p.label = str(label)
return p
label_str = str(label)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not sure what calling str() on what is already guaranteed to be a str() is intended to do?

Comment thread src/pygambit/game.pxi Outdated
label_str = str(label)
if not label_str:
raise ValueError("add_player(): label must not be empty")
existing = [player.label for player in self.players]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All these checks duplicate what is already supposed to be done in NewPlayer. And in fact they mask a bug: C++ NewPlayer allows the creation of a player with the label "Chance".

Comment thread src/pygambit/player.pxi
Comment thread src/games/game.h Outdated
Comment thread src/games/gameagg.cc
Comment thread src/games/gametree.cc Outdated
GamePlayer GameTreeRep::NewPlayer()
GamePlayer GameTreeRep::NewPlayer(const std::string &p_label)
{
auto player = std::make_shared<GamePlayerRep>(this, m_players.size() + 1, "");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This defeats the purpose of having the label as an argument of the ctor if we allow ourselves to create a player with an invalid label.

What should be done is the validity of the label is checked first, and then the object allocated after the validity is confirmed.

This means that the logic in SetLabel for duplicate checking needs to be its own function that gets called from wherever is relevant.

@tturocy
tturocy merged commit 592fa0b into gambitproject:master Jul 9, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++ Items which involve writing in C++ cython Items which involve coding in Cython

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants