Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2a462cf
test_node.py: replace integer indexing with labels
d-kad Jun 9, 2026
1312032
test_outcomes.py: replace integer indexing with labels
d-kad Jun 9, 2026
23e402a
test_strategic.py: replace integer indexing with labels
d-kad Jun 9, 2026
01bf5cb
test_players.py: replace integer indexing with labels
d-kad Jun 9, 2026
3da2101
test_extensive.py: replace integer indexing with labels
d-kad Jun 9, 2026
a4d9922
test_game.py: replace integer indexing with labels
d-kad Jun 9, 2026
20c575a
games.py: replace integer indexing with labels
d-kad Jun 9, 2026
b87b711
nash.py: replace integer indexing with labels
d-kad Jun 9, 2026
655328b
test_mixed.py: replace integer indexing with iteration
d-kad Jun 9, 2026
09624e1
test_node.py: replace integer indexing with labels
d-kad Jun 9, 2026
1cc650d
test_infosets.py: replace integer indexing with labels
d-kad Jun 9, 2026
b1a2a8a
test_behav.py: replace integer indexing with labels
d-kad Jun 9, 2026
43e3982
test_actions.py: replace integer indexing with labels
d-kad Jun 9, 2026
62c57d5
Update tests for KeyError on missing action label in NodeChildren
d-kad Jun 11, 2026
50f93e0
docstring polishes
d-kad Jun 11, 2026
5dade61
Replace integer indexing of players, strategies, and infosets with
d-kad Jun 11, 2026
d7f8c01
Consolidate and extend tests for label-only collection indexing
d-kad Jun 11, 2026
b802aa3
Remove integer indexing from game collections
d-kad Jun 11, 2026
d38a8b5
add Changelog and api.rst
d-kad Jun 11, 2026
50a14d7
Strip surrounding whitespace from label lookup strings
d-kad Jun 12, 2026
9cc29b8
`Game.__getitem__` was deliberately omitted from index for now becaus…
tturocy Jun 16, 2026
e142b4b
Add str type hints to collection indexers and remove label normalization
d-kad Jun 16, 2026
203c37c
Merge branch 'master' into indexing
tturocy Jun 18, 2026
a1f2acb
Update ChangeLog
tturocy Jun 18, 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
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
unsaved work. (#12)
- Created and documented right-click context menu in the normal form pivot table, which makes the
mechanism for deleting a strategy more clear. (#855)
- In `pygambit`, indexing game object collections by integer position has been removed. (#942)

### Removed
- Built-in plotting of logit QRE for strategic games has been removed in the GUI (#809)
Expand Down
13 changes: 7 additions & 6 deletions doc/tutorials/01_quickstart.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,14 @@
"metadata": {},
"outputs": [],
"source": [
"g.players[0].label = \"Tom\"\n",
"g.players[0].strategies[0].label = \"Cooperate\"\n",
"g.players[0].strategies[1].label = \"Defect\"\n",
"tom, jerry = g.players\n",
"tom.label = \"Tom\"\n",
"jerry.label = \"Jerry\"\n",
"\n",
"g.players[1].label = \"Jerry\"\n",
"g.players[1].strategies[0].label = \"Cooperate\"\n",
"g.players[1].strategies[1].label = \"Defect\""
"for player in g.players:\n",
" cooperate, defect = player.strategies\n",
" cooperate.label = \"Cooperate\"\n",
" defect.label = \"Defect\""
]
},
{
Expand Down
9 changes: 5 additions & 4 deletions doc/tutorials/03_stripped_down_poker.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,8 @@
"outputs": [],
"source": [
"# Remember that Bob has a single information set\n",
"for action in g.players[\"Bob\"].infosets[0].actions:\n",
"(bob_infoset,) = g.players[\"Bob\"].infosets\n",
"for action in bob_infoset.actions:\n",
" print(\n",
" f\"When Bob plays {action.label} his expected payoff is {eqm.action_value(action)}\"\n",
" )"
Expand All @@ -520,7 +521,7 @@
"metadata": {},
"outputs": [],
"source": [
"for node in g.players[\"Bob\"].infosets[0].members:\n",
"for node in bob_infoset.members:\n",
" print(\n",
" f\"Bob's belief in reaching the {node.parent.prior_action.label} -> \"\n",
" f\"{node.prior_action.label} node is: {eqm.belief(node)}\"\n",
Expand All @@ -544,7 +545,7 @@
"metadata": {},
"outputs": [],
"source": [
"eqm.infoset_prob(g.players[\"Bob\"].infosets[0])"
"eqm.infoset_prob(bob_infoset)"
]
},
{
Expand All @@ -562,7 +563,7 @@
"metadata": {},
"outputs": [],
"source": [
"for node in g.players[\"Bob\"].infosets[0].members:\n",
"for node in bob_infoset.members:\n",
" print(\n",
" f\"The probability that the node {node.parent.prior_action.label} -> \"\n",
" f\"{node.prior_action.label} is reached is: {eqm.realiz_prob(node)}. \",\n",
Expand Down
10 changes: 5 additions & 5 deletions doc/tutorials/interoperability_tutorials/openspiel.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,8 @@
"gbt_matrix_rps_game.title = \"Rock-Paper-Scissors\"\n",
"\n",
"for player in gbt_matrix_rps_game.players:\n",
" player.strategies[0].label = \"Rock\"\n",
" player.strategies[1].label = \"Paper\"\n",
" player.strategies[2].label = \"Scissors\"\n",
" for strategy, label in zip(player.strategies, [\"Rock\", \"Paper\", \"Scissors\"], strict=True):\n",
" strategy.label = label\n",
"\n",
"gbt_matrix_rps_game"
]
Expand Down Expand Up @@ -356,11 +355,12 @@
"outputs": [],
"source": [
"p1_payoffs, p2_payoffs = gbt_prisoners_dilemma_game.to_arrays(dtype=float)\n",
"p1, p2 = gbt_prisoners_dilemma_game.players\n",
"ops_prisoners_dilemma_game = pyspiel.create_matrix_game(\n",
" gbt_prisoners_dilemma_game.title,\n",
" \"Classic Prisoner's Dilemma\", # description\n",
" [strategy.label for strategy in gbt_prisoners_dilemma_game.players[0].strategies],\n",
" [strategy.label for strategy in gbt_prisoners_dilemma_game.players[1].strategies],\n",
" [strategy.label for strategy in p1.strategies],\n",
" [strategy.label for strategy in p2.strategies],\n",
" p1_payoffs,\n",
" p2_payoffs\n",
")"
Expand Down
22 changes: 21 additions & 1 deletion src/pygambit/gambit.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import warnings
import typing

import cython
import typing

from .error import *

Expand Down Expand Up @@ -74,6 +73,27 @@ def _to_number(value: typing.Any) -> c_Number:
return c_Number(value.encode("ascii"))


@cython.cfunc
Comment thread
d-kad marked this conversation as resolved.
def _resolve_by_label(collection, label: str, scope: str, kind: str, kind_plural: str):
"""Resolve a member of a game collection by its text label.

Game collections are accessed by label, not by position. Lookup is by exact label match.

Failure modes:
* an empty label raises ``ValueError``;
* a label matching no member raises ``KeyError``;
* a label matching more than one member raises ``ValueError``.
"""
if not label:
raise ValueError(f"{kind} label cannot be empty")
matches = [x for x in collection if x.label == label]
if not matches:
raise KeyError(f"{scope} has no {kind} with label '{label}'")
if len(matches) > 1:
raise ValueError(f"{scope} has multiple {kind_plural} with label '{label}'")
return matches[0]


PlayerReference = Player | str
StrategyReference = Strategy | str
InfosetReference = Infoset | str
Expand Down
Loading
Loading