Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
### Added
- Added `Game.has_perfect_recall(player)`, and `GameRep::HasPerfectRecall(const GamePlayer &)`
in C++, reporting whether an individual player has perfect recall. (#1107)
- Added `MixedBehaviorProfile.event_probs`, returning the probability with which each of
the chance player's events is reached, as an `EventProbVector`. (#1109)
- Added `Game.get_outcomes()`, returning a materialized list of outcome labels, replacing
`Game.outcomes`.
- Added `Game.get_outcome_payoffs(label)`, returning the payoff to each player at the outcome
Expand All @@ -15,6 +17,8 @@
`Game.relabel_strategies`. Added `GameRep::RelabelOutcomes` in C++.

### Changed
- `MixedBehaviorProfile.infoset_probs` now covers only the personal players' information sets,
as `infoset_values` and `infoset_regrets`; the chance player's events moved to `event_probs`. (#1109)
- `Game.make_outcome` now returns `None` instead of the `Outcome` created; use the `label`
already passed in, together with `Game.get_outcome_payoffs`/`Game.relabel_outcomes`, to refer
to it afterward.
Expand Down
17 changes: 10 additions & 7 deletions doc/formats.efg.rst
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,21 @@ generates these numbers as 1, 2, etc. as they appear first in the
file, but there are no requirements other than uniqueness. The same
integer may be used to specify information sets for different players;
this is not ambiguous since the player number appears as well.
The chance player's events are numbered in the same way, uniquely among
the events; since chance nodes carry no player number, an event number
cannot be confused with an information set number.
Finally, outcomes are also arbitrarily numbered in the file format in
the same way in which information sets are, except for the special
number 0 which is reserved to indicate the null outcome.
Outcome 0 must not have a name or payoffs specified.

Information sets and outcomes may (and frequently will) appear
Information sets, events, and outcomes may (and frequently will) appear
multiple times within a game. By convention, the second and subsequent
times an information set or outcome appears, the file may omit the
descriptive information for that information set or outcome.
times an information set, event, or outcome appears, the file may omit the
descriptive information for it.
Alternatively, the file may specify the descriptive information again;
however, it must precisely match the original declaration of the
information set or outcome. Any mismatch in repeated declarations
however, it must precisely match the original declaration.
Any mismatch in repeated declarations
is an error, and the file is not valid.
If any part of the description is omitted, the whole description must be omitted.

Expand All @@ -138,8 +141,8 @@ with the character c . Following this, in order, are


+ a text string, giving the name of the node
+ a positive integer specifying the information set number
+ (optional) the name of the information set and a list of actions at the information set with their
+ a positive integer specifying the event number
+ (optional) the name of the event and a list of actions at the event with their
corresponding probabilities
+ a nonnegative integer specifying the outcome
+ (optional) the name of the outcome and the payoffs to each player for the outcome
Expand Down
16 changes: 10 additions & 6 deletions doc/gui.efg.building.rst
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,13 @@ Editing moves
-------------

The properties of an existing move -- the label of its information
set, the player to which it belongs, and the actions available at it
-- can be changed by right-clicking on any node belonging to the move
set or event, the player to which it belongs, and the actions available
at it -- can be changed by right-clicking on any node belonging to the move
and choosing :guilabel:`Move properties`. This displays the
:guilabel:`Move properties` dialog, which shows a dropdown for the player
to which the move belongs (each player again shown with its colour), a text
field for the information set's label, and a row for each action, showing
its label and, for moves belonging to the chance player, its probability.
field for the information set's or event's label, and a row for each action,
showing its label and, for moves belonging to the chance player, its probability.

Adding, removing, and reordering actions
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -205,7 +205,9 @@ A node can be placed in the same information set as another using the
drag-and-drop idiom described in :ref:`copying-trees`: dragging one
node onto another and choosing :guilabel:`Put node in same information
set` (or, when dropping on a terminal node, :guilabel:`Insert move
using same information set`) from the popup menu. This is currently the
using same information set`) from the popup menu. When the node being
dragged belongs to the chance player, these read :guilabel:`Put node in
same event` and :guilabel:`Insert move using same event`. This is currently the
only way to have a newly created move share an information set with an
existing one; the :ref:`per-player submenu <adding-moves>` for adding a
move always creates a fresh information set.
Expand All @@ -225,7 +227,9 @@ a list of all other information sets in the game which are compatible
with the node, that is, which have the same number of
actions. Additionally, the node can be moved to a new, singleton
information set by setting this dropdown to the :guilabel:`New
information set` entry.
information set` entry. For a node belonging to the chance player the
dropdown is labeled :guilabel:`Event`, lists the game's events, and
offers :guilabel:`New event` instead.



Expand Down
3 changes: 2 additions & 1 deletion doc/gui.nash.rst
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ also names the player who moves there and shows the probability of
reaching the node, the probability of reaching its information set, that
player's belief about being at this particular node conditional on having
reached the information set, and the information set's value to the
player who moves there.
player who moves there. For a node belonging to the chance player, the
popup refers to its event instead of an information set throughout.

The computed profiles can also be viewed in the reduced strategic
game. Clicking on the strategic game icon changes the view to the
Expand Down
2 changes: 2 additions & 0 deletions doc/pygambit.api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ Probability distributions over behavior
MixedBehaviorProfile.node_values
MixedBehaviorProfile.realiz_probs
MixedBehaviorProfile.infoset_probs
MixedBehaviorProfile.event_probs
MixedBehaviorProfile.beliefs
MixedBehaviorProfile.agent_max_regret
MixedBehaviorProfile.agent_liap_value
Expand All @@ -255,6 +256,7 @@ Probability distributions over behavior
InfosetValueVector
InfosetRegretVector
InfosetProbVector
EventProbVector
ActionValueVector
ActionRegretVector
ActionValuesVector
Expand Down
4 changes: 2 additions & 2 deletions src/games/file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -762,15 +762,15 @@ void CheckChanceProbs(const GameFileLexer &p_state, const int p_infosetId,
const GameInfoset &p_infoset, const Array<Number> &p_probs)
{
if (p_infoset->GetActions().size() != p_probs.size()) {
p_state.OnParseError("Chance infoset probability count mismatch "
p_state.OnParseError("Event probability count mismatch "
"(infoset " +
std::to_string(p_infosetId) + ")");
}
auto action_it = p_infoset->GetActions().begin();
for (size_t i = 1; i <= p_probs.size(); ++i) {
if (static_cast<const std::string &>(p_infoset->GetActionProb(*action_it)) !=
static_cast<const std::string &>(p_probs[i])) {
p_state.OnParseError("Chance infoset probabilities do not match previous definition "
p_state.OnParseError("Event probabilities do not match previous definition "
"(infoset " +
std::to_string(p_infosetId) + ")");
}
Expand Down
15 changes: 10 additions & 5 deletions src/gui/dleditmove.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const wxColour kNewLabelColour(0, 102, 0); // new action: bold, dark green
const wxColour kRenamedLabelColour(0, 51, 204); // renamed action: italic, strong blue
} // namespace

// An editable, variable-length list of the actions at an information set, colour-coded like
// An editable, variable-length list of the actions at an infoset, colour-coded like
// a source-control diff (added/renamed/deleted).
//
// Each row's *stable label* (its label before this dialog touched it, or a placeholder for a
Expand Down Expand Up @@ -459,7 +459,8 @@ wxString ActionPanel::ValidateLabels()

if (invalid && message.empty()) {
message = value.empty() ? _("Action labels cannot be empty.")
: _("Action labels must be unique within the information set.");
: m_isChance ? _("Action labels must be unique within the event.")
: _("Action labels must be unique within the infoset.");
}
}
return message;
Expand Down Expand Up @@ -528,8 +529,10 @@ EditMoveDialog::EditMoveDialog(wxWindow *p_parent, const std::shared_ptr<GameDoc
}

auto *labelSizer = new wxBoxSizer(wxHORIZONTAL);
labelSizer->Add(new wxStaticText(m_headerPanel, wxID_STATIC, _("Information set label")), 0,
wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(7));
labelSizer->Add(new wxStaticText(m_headerPanel, wxID_STATIC,
p_infoset->IsChanceInfoset() ? _("Event label")
: _("Information set label")),
0, wxALIGN_CENTER_VERTICAL | wxRIGHT, FromDIP(7));
m_infosetLabel =
new LabelTextCtrl(m_headerPanel, wxID_ANY, wxString::FromUTF8(p_infoset->GetLabel()));
m_infosetLabelDefaultBg = m_infosetLabel->GetBackgroundColour();
Expand Down Expand Up @@ -606,7 +609,9 @@ void EditMoveDialog::UpdateValidation()
m_infosetLabel->SetBackgroundColour(infosetValid ? m_infosetLabelDefaultBg : kInvalidLabelBg);
m_infosetLabel->Refresh();
if (!infosetValid) {
message = _("Information set label must be unique for the player.");
message = m_infoset->IsChanceInfoset()
? _("Event label must be unique.")
: _("Information set label must be unique for the player.");
}

const wxString actionMessage = m_actionPanel->ValidateLabels();
Expand Down
2 changes: 1 addition & 1 deletion src/gui/dleditmove.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class EditMoveDialog final : public wxDialog {
std::string GetStableLabel(int p_index) const;
// The label as currently typed into the row at position `p_index`.
wxString GetActionLabel(int p_index) const;
// The probability currently typed into the row at position `p_index` (chance infosets only).
// The probability currently typed into the row at position `p_index` (events only).
Number GetActionProb(int p_index) const;
};
} // namespace Gambit::GUI
Expand Down
11 changes: 6 additions & 5 deletions src/gui/dleditnode.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,20 @@ EditNodeDialog::EditNodeDialog(wxWindow *p_parent, const GameNode &p_node)
labelSizer->Add(m_nodeLabel, 1, wxALL | wxCENTER | wxEXPAND, S);
topSizer->Add(labelSizer, 0, wxALL | wxEXPAND, S);

const bool isChance = !p_node->IsTerminal() && p_node->GetInfoset()->IsChanceInfoset();
auto *infosetSizer = new wxBoxSizer(wxHORIZONTAL);
infosetSizer->Add(new wxStaticText(this, wxID_STATIC, _("Information set")), 0, wxALL | wxCENTER,
S);
infosetSizer->Add(new wxStaticText(this, wxID_STATIC, isChance ? _("Event") : _("Infoset")), 0,
wxALL | wxCENTER, S);
m_infoset = new wxChoice(this, wxID_ANY);
if (!p_node->IsTerminal()) {
m_infoset->Append(_("New information set"));
if (p_node->GetInfoset()->IsChanceInfoset()) {
m_infoset->Append(isChance ? _("New event") : _("New infoset"));
if (isChance) {
int selection = 0;
for (const auto &infoset : p_node->GetGame()->GetChance()->GetInfosets()) {
if (infoset->GetActions().size() == p_node->GetChildren().size()) {
m_infosetList.push_back(infoset);
wxString label;
label << _("Chance infoset ") << infoset->GetNumber();
label << _("Event ") << infoset->GetNumber();
m_infoset->Append(label);
if (infoset == p_node->GetInfoset()) {
selection = m_infosetList.size();
Expand Down
7 changes: 5 additions & 2 deletions src/gui/efgdragdrop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -258,11 +258,14 @@ bool EfgDisplay::ShowTreeDropMenu(const GameNode &p_targetNode, const GameNode &
menu.AppendSeparator();
}

const bool isChance = p_sourceNode->GetPlayer()->IsChance();
if (p_targetNode->IsTerminal()) {
menu.Append(infosetId, _("Insert move using same information set"));
menu.Append(infosetId, isChance ? _("Insert move using same event")
: _("Insert move using same information set"));
}
else {
menu.Append(infosetId, _("Put node in same information set"));
menu.Append(infosetId,
isChance ? _("Put node in same event") : _("Put node in same information set"));
}
}

Expand Down
11 changes: 7 additions & 4 deletions src/gui/efgtooltip.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,7 @@ wxString AppendMovePopup::ValidateLabels()

if (invalid && message.empty()) {
message = value.empty() ? _("Action labels cannot be empty.")
: m_isChance ? _("Action labels must be unique within the event.")
: _("Action labels must be unique within the information set.");
}
}
Expand Down Expand Up @@ -1509,11 +1510,13 @@ void NodeInfoPopup::ShowForNode(const GameNode &p_node)
m_moveHeading->SetLabel(wxString::FromUTF8(mover->GetLabel()) + _(" to move"));
m_nodeProbText->SetLabel(_("Pr(Node reached): ") +
wxString::FromUTF8(profiles.GetRealizProb(p_node)));
m_infosetProbText->SetLabel(_("Pr(Infoset reached): ") +
wxString::FromUTF8(profiles.GetInfosetProb(p_node)));
m_infosetProbText->SetLabel(
(mover->IsChance() ? _("Pr(Event reached): ") : _("Pr(Information set reached): ")) +
wxString::FromUTF8(profiles.GetInfosetProb(p_node)));
m_beliefText->SetLabel(_("Belief: ") + wxString::FromUTF8(profiles.GetBeliefProb(p_node)));
m_infosetValueText->SetLabel(_("Payoff | Infoset: ") +
wxString::FromUTF8(profiles.GetInfosetValue(p_node)));
m_infosetValueText->SetLabel(
(mover->IsChance() ? _("Payoff | Event: ") : _("Payoff | Information set: ")) +
wxString::FromUTF8(profiles.GetInfosetValue(p_node)));
}
m_contentPanel->GetSizer()->Show(m_moveSizer, showMove, true);

Expand Down
Loading
Loading