Skip to content

Commit e3591f9

Browse files
tidy notebook
1 parent e049629 commit e3591f9

1 file changed

Lines changed: 141 additions & 45 deletions

File tree

doc/tutorials/interoperability_tutorials/openspiel.ipynb

Lines changed: 141 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
"cell_type": "markdown",
55
"metadata": {},
66
"source": [
7-
"# Using Gambit with OpenSpiel\n",
7+
"# Usinops_one_card_poker ops_one_card_pokerambit with OpenSpiel\n",
88
"\n",
9-
"This tutorial demonstrates the interoperability of the Gambit and OpenSpiel Python packages for game-theoretic analysis.\n",
9+
"This tutorial demonstrates the interoperability of the ops_one_card_pokerambit and OpenSpiel Python packages for game-theoretic analysis.\n",
1010
"\n",
1111
"Where Gambit is used to compute exact equilibria for games, OpenSpiel provides a variety of iterative learning algorithms that can be used to approximate strategies. Another key distinction is that the PyGambit API allows the user a simple way to define custom games (see tutorials 1-3). This is also possible in OpenSpiel for normal form games, and you can load `.efg` files created from Gambit for extensive form, however some of the key functionality for iterated learning of strategies is only available for games from the built-in library (see the [OpenSpiel documentation](https://openspiel.readthedocs.io/en/latest/games.html)).\n",
1212
"\n",
@@ -18,7 +18,7 @@
1818
"4. Comparing the strategies from OpenSpiel against equilibria strategies computed with Gambit\n",
1919
"\n",
2020
"Note:\n",
21-
"- The version of OpenSpiel used in this tutorial is `1.6.1`. If you are running this tutorial locally, this will be the version installed via the included `requirements.txt` file.\n",
21+
"- The version of OpenSpiel used in this tutorial is `1.6.9`. If you are running this tutorial locally, this will be the version installed via the included `requirements.txt` file.\n",
2222
"- The OpenSpiel code was adapted from the introductory tutorial for the OpenSpiel API on colab [here](https://colab.research.google.com/github/deepmind/open_spiel/blob/master/open_spiel/colabs/OpenSpielTutorial.ipynb)."
2323
]
2424
},
@@ -928,13 +928,13 @@
928928
"output_type": "stream",
929929
"text": [
930930
"\n",
931-
"p0:d1 p1:d0\n",
932-
"Agent 0 chooses p0a0\n",
931+
"p0:d0 p1:d1\n",
932+
"Agent 0 chooses p0a2\n",
933933
"\n",
934-
"p0:d1 p1:d0 p0:a0\n",
934+
"p0:d0 p1:d1 p0:a2\n",
935935
"Agent 1 chooses p1a2\n",
936936
"\n",
937-
"p0:d1 p1:d0 p0:a0 p1:a2\n",
937+
"p0:d0 p1:d1 p0:a2 p1:a2\n",
938938
"Rewards: [10.0, 10.0]\n"
939939
]
940940
}
@@ -976,32 +976,86 @@
976976
"source": [
977977
"## Extensive form games created with Gambit\n",
978978
"\n",
979-
"It's also possible to create an extensive form game in Gambit and export it to OpenSpiel. Here we demonstrate this with the one-card poker game introduced in tutorial 3."
979+
"It's also possible to create an extensive form game in Gambit and export it to OpenSpiel. Here we demonstrate this with the one-card poker game introduced in tutorial 3:"
980980
]
981981
},
982982
{
983983
"cell_type": "code",
984-
"execution_count": 28,
984+
"execution_count": 47,
985+
"id": "77dc34c8",
986+
"metadata": {},
987+
"outputs": [],
988+
"source": [
989+
"gbt_one_card_poker = gbt.Game.new_tree(\n",
990+
" players=[\"Alice\", \"Bob\"],\n",
991+
" title=\"Stripped-Down Poker: a simple game of one-card poker from Reiley et al (2008).\"\n",
992+
")\n",
993+
"\n",
994+
"gbt_one_card_poker.append_move(\n",
995+
" gbt_one_card_poker.root,\n",
996+
" player=gbt_one_card_poker.players.chance,\n",
997+
" actions=[\"King\", \"Queen\"] # By default, chance actions have equal probabilities\n",
998+
")\n",
999+
"\n",
1000+
"for node in gbt_one_card_poker.root.children:\n",
1001+
" gbt_one_card_poker.append_move(\n",
1002+
" node,\n",
1003+
" player=\"Alice\",\n",
1004+
" actions=[\"Bet\", \"Fold\"]\n",
1005+
" )\n",
1006+
"\n",
1007+
"gbt_one_card_poker.append_move(\n",
1008+
" [gbt_one_card_poker.root.children[\"King\"].children[\"Bet\"], gbt_one_card_poker.root.children[\"Queen\"].children[\"Bet\"]],\n",
1009+
" player=\"Bob\",\n",
1010+
" actions=[\"Call\", \"Fold\"]\n",
1011+
")\n",
1012+
"\n",
1013+
"win_big = gbt_one_card_poker.add_outcome([2, -2], label=\"Win Big\")\n",
1014+
"win = gbt_one_card_poker.add_outcome([1, -1], label=\"Win\")\n",
1015+
"lose_big = gbt_one_card_poker.add_outcome([-2, 2], label=\"Lose Big\")\n",
1016+
"lose = gbt_one_card_poker.add_outcome([-1, 1], label=\"Lose\")\n",
1017+
"\n",
1018+
"# Alice folds, Bob wins small\n",
1019+
"gbt_one_card_poker.set_outcome(gbt_one_card_poker.root.children[\"King\"].children[\"Fold\"], lose)\n",
1020+
"gbt_one_card_poker.set_outcome(gbt_one_card_poker.root.children[\"Queen\"].children[\"Fold\"], lose)\n",
1021+
"# Bob sees Alice Bet and calls, correctly believing she is bluffing, Bob wins big\n",
1022+
"gbt_one_card_poker.set_outcome(gbt_one_card_poker.root.children[\"Queen\"].children[\"Bet\"].children[\"Call\"], lose_big)\n",
1023+
"\n",
1024+
"# Bob sees Alice Bet and calls, incorrectly believing she is bluffing, Alice wins big\n",
1025+
"gbt_one_card_poker.set_outcome(gbt_one_card_poker.root.children[\"King\"].children[\"Bet\"].children[\"Call\"], win_big)\n",
1026+
"\n",
1027+
"# Bob does not call Alice's Bet, Alice wins small\n",
1028+
"gbt_one_card_poker.set_outcome(gbt_one_card_poker.root.children[\"King\"].children[\"Bet\"].children[\"Fold\"], win)\n",
1029+
"gbt_one_card_poker.set_outcome(gbt_one_card_poker.root.children[\"Queen\"].children[\"Bet\"].children[\"Fold\"], win)"
1030+
]
1031+
},
1032+
{
1033+
"cell_type": "markdown",
1034+
"id": "4f296f44",
1035+
"metadata": {},
1036+
"source": [
1037+
"Create the game in OpenSpiel:"
1038+
]
1039+
},
1040+
{
1041+
"cell_type": "code",
1042+
"execution_count": 48,
9851043
"id": "07340e32",
9861044
"metadata": {},
9871045
"outputs": [
9881046
{
989-
"ename": "FileNotFoundError",
990-
"evalue": "[Errno 2] No such file or directory: '../poker.efg'",
991-
"output_type": "error",
992-
"traceback": [
993-
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
994-
"\u001b[31mFileNotFoundError\u001b[39m Traceback (most recent call last)",
995-
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[28]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28;43mopen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43m../poker.efg\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mr\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m)\u001b[49m \u001b[38;5;28;01mas\u001b[39;00m f:\n\u001b[32m 2\u001b[39m poker_efg_string = f.read()\n\u001b[32m 3\u001b[39m ops_one_card_poker = pyspiel.load_efg_game(poker_efg_string)\n",
996-
"\u001b[36mFile \u001b[39m\u001b[32m~/anaconda3/envs/gambitvenv313/lib/python3.13/site-packages/IPython/core/interactiveshell.py:343\u001b[39m, in \u001b[36m_modified_open\u001b[39m\u001b[34m(file, *args, **kwargs)\u001b[39m\n\u001b[32m 336\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m file \u001b[38;5;129;01min\u001b[39;00m {\u001b[32m0\u001b[39m, \u001b[32m1\u001b[39m, \u001b[32m2\u001b[39m}:\n\u001b[32m 337\u001b[39m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[32m 338\u001b[39m \u001b[33mf\u001b[39m\u001b[33m\"\u001b[39m\u001b[33mIPython won\u001b[39m\u001b[33m'\u001b[39m\u001b[33mt let you open fd=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfile\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m by default \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 339\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mas it is likely to crash IPython. If you know what you are doing, \u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 340\u001b[39m \u001b[33m\"\u001b[39m\u001b[33myou can use builtins\u001b[39m\u001b[33m'\u001b[39m\u001b[33m open.\u001b[39m\u001b[33m\"\u001b[39m\n\u001b[32m 341\u001b[39m )\n\u001b[32m--> \u001b[39m\u001b[32m343\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mio_open\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfile\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
997-
"\u001b[31mFileNotFoundError\u001b[39m: [Errno 2] No such file or directory: '../poker.efg'"
998-
]
1047+
"data": {
1048+
"text/plain": [
1049+
"efg_game()"
1050+
]
1051+
},
1052+
"execution_count": 48,
1053+
"metadata": {},
1054+
"output_type": "execute_result"
9991055
}
10001056
],
10011057
"source": [
1002-
"with open(\"../poker.efg\", \"r\") as f:\n",
1003-
" poker_efg_string = f.read()\n",
1004-
" ops_one_card_poker = pyspiel.load_efg_game(poker_efg_string)\n",
1058+
"ops_one_card_poker = pyspiel.load_efg_game(gbt_one_card_poker.to_efg())\n",
10051059
"ops_one_card_poker"
10061060
]
10071061
},
@@ -1017,17 +1071,17 @@
10171071
},
10181072
{
10191073
"cell_type": "code",
1020-
"execution_count": null,
1074+
"execution_count": 49,
10211075
"id": "c01c4d6f",
10221076
"metadata": {},
10231077
"outputs": [
10241078
{
10251079
"data": {
10261080
"text/plain": [
1027-
"4"
1081+
"3"
10281082
]
10291083
},
1030-
"execution_count": 29,
1084+
"execution_count": 49,
10311085
"metadata": {},
10321086
"output_type": "execute_result"
10331087
}
@@ -1041,14 +1095,14 @@
10411095
"id": "9986860c",
10421096
"metadata": {},
10431097
"source": [
1044-
"The one-card poker game has 4 distinct actions, 2 are for the first player (Alice in the example game): \"Raise\" and \"Fold\", and 2 for the second player (Bob): \"Meet\" and \"Pass\".\n",
1098+
"The one-card poker game has 4 distinct actions, 2 are for the first player (Alice in the example game): \"Bet\" and \"Fold\", and 2 for the second player (Bob): \"Call\" and \"Fold\".\n",
10451099
"\n",
10461100
"Initialising the game state, we can see the current player at the start is the chance player, who deals the cards:"
10471101
]
10481102
},
10491103
{
10501104
"cell_type": "code",
1051-
"execution_count": null,
1105+
"execution_count": 50,
10521106
"id": "3b9cc43b",
10531107
"metadata": {},
10541108
"outputs": [
@@ -1058,7 +1112,7 @@
10581112
"0: Chance: 1 King 0.5 Queen 0.5"
10591113
]
10601114
},
1061-
"execution_count": 30,
1115+
"execution_count": 50,
10621116
"metadata": {},
10631117
"output_type": "execute_result"
10641118
}
@@ -1068,6 +1122,27 @@
10681122
"state"
10691123
]
10701124
},
1125+
{
1126+
"cell_type": "code",
1127+
"execution_count": 51,
1128+
"id": "e23df723",
1129+
"metadata": {},
1130+
"outputs": [
1131+
{
1132+
"data": {
1133+
"text/plain": [
1134+
"[0, 1]"
1135+
]
1136+
},
1137+
"execution_count": 51,
1138+
"metadata": {},
1139+
"output_type": "execute_result"
1140+
}
1141+
],
1142+
"source": [
1143+
"state.legal_actions()"
1144+
]
1145+
},
10711146
{
10721147
"cell_type": "markdown",
10731148
"id": "7b0959f9",
@@ -1078,17 +1153,17 @@
10781153
},
10791154
{
10801155
"cell_type": "code",
1081-
"execution_count": null,
1156+
"execution_count": 52,
10821157
"id": "4dd5d504",
10831158
"metadata": {},
10841159
"outputs": [
10851160
{
10861161
"data": {
10871162
"text/plain": [
1088-
"1: Player: 1 1 Raise Fold"
1163+
"1: Player: 1 1 Bet Fold"
10891164
]
10901165
},
1091-
"execution_count": 31,
1166+
"execution_count": 52,
10921167
"metadata": {},
10931168
"output_type": "execute_result"
10941169
}
@@ -1098,28 +1173,49 @@
10981173
"state"
10991174
]
11001175
},
1176+
{
1177+
"cell_type": "code",
1178+
"execution_count": 53,
1179+
"id": "be557706",
1180+
"metadata": {},
1181+
"outputs": [
1182+
{
1183+
"data": {
1184+
"text/plain": [
1185+
"[0, 1]"
1186+
]
1187+
},
1188+
"execution_count": 53,
1189+
"metadata": {},
1190+
"output_type": "execute_result"
1191+
}
1192+
],
1193+
"source": [
1194+
"state.legal_actions()"
1195+
]
1196+
},
11011197
{
11021198
"cell_type": "markdown",
11031199
"id": "b4291f07",
11041200
"metadata": {},
11051201
"source": [
11061202
"As expected, it's now the first player's (Alice's) turn.\n",
1107-
"Let's have Alice choose to \"Raise\" (action 0):"
1203+
"Let's have Alice choose to \"Bet\" (action 0):"
11081204
]
11091205
},
11101206
{
11111207
"cell_type": "code",
1112-
"execution_count": null,
1208+
"execution_count": 54,
11131209
"id": "bd15369f",
11141210
"metadata": {},
11151211
"outputs": [
11161212
{
11171213
"data": {
11181214
"text/plain": [
1119-
"3: Player: 2 1 Meet Pass"
1215+
"3: Player: 2 1 Call Fold"
11201216
]
11211217
},
1122-
"execution_count": 32,
1218+
"execution_count": 54,
11231219
"metadata": {},
11241220
"output_type": "execute_result"
11251221
}
@@ -1139,17 +1235,17 @@
11391235
},
11401236
{
11411237
"cell_type": "code",
1142-
"execution_count": null,
1238+
"execution_count": 55,
11431239
"id": "8d81ff6b",
11441240
"metadata": {},
11451241
"outputs": [
11461242
{
11471243
"data": {
11481244
"text/plain": [
1149-
"[2, 3]"
1245+
"[1, 2]"
11501246
]
11511247
},
1152-
"execution_count": 33,
1248+
"execution_count": 55,
11531249
"metadata": {},
11541250
"output_type": "execute_result"
11551251
}
@@ -1163,29 +1259,29 @@
11631259
"id": "fdb5194f",
11641260
"metadata": {},
11651261
"source": [
1166-
"Whereas player 1 (Alice) had the option to \"Raise\" (action 0) and \"Fold\" (action 1), player 2 (Bob) now has the option to \"Meet\" (action 2) or \"Pass\" (action 3).\n",
1167-
"Let's have Bob choose to \"Pass\":"
1262+
"Player 2 (Bob) now has the option to \"Call\" (action 1) or \"Fold\" (action 2).\n",
1263+
"Let's have Bob choose to \"Fold\":"
11681264
]
11691265
},
11701266
{
11711267
"cell_type": "code",
1172-
"execution_count": null,
1268+
"execution_count": 56,
11731269
"id": "97913fe5",
11741270
"metadata": {},
11751271
"outputs": [
11761272
{
11771273
"data": {
11781274
"text/plain": [
1179-
"6: Terminal: Alice wins 1 -1"
1275+
"6: Terminal: Win 1 -1"
11801276
]
11811277
},
1182-
"execution_count": 34,
1278+
"execution_count": 56,
11831279
"metadata": {},
11841280
"output_type": "execute_result"
11851281
}
11861282
],
11871283
"source": [
1188-
"state.apply_action(3)\n",
1284+
"state.apply_action(2)\n",
11891285
"state"
11901286
]
11911287
},
@@ -1194,7 +1290,7 @@
11941290
"id": "1bf09576",
11951291
"metadata": {},
11961292
"source": [
1197-
"Since Bob passed, Alice takes the small win and we reach a terminal state."
1293+
"Since Bob Folded, Alice takes the small win and we reach a terminal state."
11981294
]
11991295
}
12001296
],

0 commit comments

Comments
 (0)