graph-games-proto 0.3.1866__py3-none-any.whl → 0.3.1877__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- graph_games_proto/__init__.py +1 -1
- graph_games_proto/fns.py +181 -1381
- {graph_games_proto-0.3.1866.dist-info → graph_games_proto-0.3.1877.dist-info}/METADATA +1 -1
- graph_games_proto-0.3.1877.dist-info/RECORD +9 -0
- graph_games_proto-0.3.1866.dist-info/RECORD +0 -9
- {graph_games_proto-0.3.1866.dist-info → graph_games_proto-0.3.1877.dist-info}/WHEEL +0 -0
- {graph_games_proto-0.3.1866.dist-info → graph_games_proto-0.3.1877.dist-info}/top_level.txt +0 -0
graph_games_proto/fns.py
CHANGED
@@ -559,22 +559,6 @@ class FrozenBoardConfigDataclass:
|
|
559
559
|
settings: List[FrozenSetting]
|
560
560
|
|
561
561
|
|
562
|
-
@dataclass(frozen=True)
|
563
|
-
class Action:
|
564
|
-
player_idx: int
|
565
|
-
action_name: str
|
566
|
-
return_route_cards: Set[int]
|
567
|
-
point_uuid: Optional[UUID]
|
568
|
-
path_idx: Optional[int]
|
569
|
-
unit_combo: Optional[str]
|
570
|
-
draw_faceup_unit_card_num: Optional[int]
|
571
|
-
draw_faceup_spot_num: Optional[int]
|
572
|
-
def __str__(self):
|
573
|
-
return f"Action({self.action_name})"
|
574
|
-
def __repr__(self):
|
575
|
-
return self.__str__()
|
576
|
-
|
577
|
-
|
578
562
|
class FrozenRoute(PClass):
|
579
563
|
num = field(type=int)
|
580
564
|
uuid = field(type=str)
|
@@ -1005,198 +989,6 @@ class ActionDrawUnit:
|
|
1005
989
|
pass
|
1006
990
|
|
1007
991
|
|
1008
|
-
# struct PublicState
|
1009
|
-
# fig::Fig
|
1010
|
-
# logged_game_uuid::UUID
|
1011
|
-
# to_play::Vector{Int}
|
1012
|
-
# last_to_play::Union{Nothing,Int}
|
1013
|
-
# terminal::Bool
|
1014
|
-
# winners::Vector{Int}
|
1015
|
-
|
1016
|
-
|
1017
|
-
class AltAction(PClass):
|
1018
|
-
player_idx = field(type=int)
|
1019
|
-
action_name = field(type=str)
|
1020
|
-
path_idx = field(type=(int, type(None)), initial=None)
|
1021
|
-
return_route_cards = field(type=list, initial=[]) # List[int]
|
1022
|
-
draw_faceup_unit_card_num = field(type=(int, type(None)), initial=None)
|
1023
|
-
draw_faceup_spot_num = field(type=(int, type(None)), initial=None)
|
1024
|
-
point_uuid = field(type=(str, type(None)), initial=None)
|
1025
|
-
unit_combo = field(type=(str, type(None)), initial=None) # TODO: should be list of int
|
1026
|
-
def __todict__(self):
|
1027
|
-
return {
|
1028
|
-
"player_idx": self.player_idx,
|
1029
|
-
"action_name": self.action_name,
|
1030
|
-
"path_idx": self.path_idx,
|
1031
|
-
"return_route_cards": self.return_route_cards,
|
1032
|
-
"draw_faceup_unit_card_num": self.draw_faceup_unit_card_num,
|
1033
|
-
"draw_faceup_spot_num": self.draw_faceup_spot_num,
|
1034
|
-
"point_uuid": self.point_uuid,
|
1035
|
-
"unit_combo": self.unit_combo
|
1036
|
-
}
|
1037
|
-
@staticmethod
|
1038
|
-
def __fromdict__(json_dict):
|
1039
|
-
return AltAction(
|
1040
|
-
player_idx=json_dict["player_idx"],
|
1041
|
-
action_name=json_dict["action_name"],
|
1042
|
-
path_idx=json_dict.get("path_idx", None), # Handle missing key gracefully
|
1043
|
-
return_route_cards=json_dict.get("return_route_cards", []), # Handle missing key gracefully
|
1044
|
-
draw_faceup_unit_card_num=json_dict.get("draw_faceup_unit_card_num", None), # Handle missing key gracefully
|
1045
|
-
draw_faceup_spot_num=json_dict.get("draw_faceup_spot_num", None), # Handle missing key gracefully
|
1046
|
-
point_uuid=json_dict.get("point_uuid", None), # Handle missing key gracefully
|
1047
|
-
unit_combo=json_dict.get("unit_combo", None) # Handle missing key gracefully
|
1048
|
-
)
|
1049
|
-
|
1050
|
-
|
1051
|
-
class ActionSpec(PClass):
|
1052
|
-
# # TODO: should remove "player_idx" as it's always the same as "to_play"
|
1053
|
-
player_idx = field(type=int)
|
1054
|
-
action_name = field(type=str)
|
1055
|
-
return_route_option_sets = field(type=list, initial=[]) # List[OptionSet]
|
1056
|
-
draw_faceup_spots = field(type=dict, initial={}) # Dict{Int, int}
|
1057
|
-
points = field(type=list, initial=[]) # List[PointCombos]
|
1058
|
-
paths = field(type=list, initial=[]) # List[PathCombos]
|
1059
|
-
def __todict__(self):
|
1060
|
-
return {
|
1061
|
-
"player_idx": self.player_idx,
|
1062
|
-
"action_name": self.action_name,
|
1063
|
-
"return_route_option_sets": [x.__todict__() for x in self.return_route_option_sets],
|
1064
|
-
"draw_faceup_spots": self.draw_faceup_spots,
|
1065
|
-
"points": [x.__todict__() for x in self.points],
|
1066
|
-
"paths": [x.__todict__() for x in self.paths],
|
1067
|
-
}
|
1068
|
-
@staticmethod
|
1069
|
-
def __fromdict__(d):
|
1070
|
-
print("""d["return_route_option_sets"]""", d["return_route_option_sets"])
|
1071
|
-
return ActionSpec(
|
1072
|
-
player_idx=d["player_idx"],
|
1073
|
-
action_name=d["action_name"],
|
1074
|
-
return_route_option_sets=[OptionSet.__fromdict__(x) for x in d["return_route_option_sets"]],
|
1075
|
-
draw_faceup_spots=d["draw_faceup_spots"],
|
1076
|
-
points=[PointCombos.__fromdict__(x) for x in d["points"]],
|
1077
|
-
paths=[PathCombos.__fromdict__(x) for x in d["paths"]],
|
1078
|
-
)
|
1079
|
-
|
1080
|
-
|
1081
|
-
# Implementing the following Julia function:
|
1082
|
-
# struct PathCombos
|
1083
|
-
# path_idx::Int
|
1084
|
-
# default_combo::String
|
1085
|
-
# sample_fulfillment::Vector{Int}
|
1086
|
-
# end
|
1087
|
-
class PathCombos(PClass):
|
1088
|
-
path_idx = field(type=int)
|
1089
|
-
default_combo = field(type=str)
|
1090
|
-
sample_fulfillment = field(type=list) # List[int]
|
1091
|
-
def __todict__(self):
|
1092
|
-
return {
|
1093
|
-
"path_idx": self.path_idx,
|
1094
|
-
"default_combo": self.default_combo,
|
1095
|
-
"sample_fulfillment": self.sample_fulfillment,
|
1096
|
-
}
|
1097
|
-
@staticmethod
|
1098
|
-
def __fromdict__(d):
|
1099
|
-
return PathCombos(
|
1100
|
-
path_idx=d["path_idx"],
|
1101
|
-
default_combo=d["default_combo"],
|
1102
|
-
sample_fulfillment=d["sample_fulfillment"]
|
1103
|
-
)
|
1104
|
-
|
1105
|
-
|
1106
|
-
# Implementing the following Julia function:
|
1107
|
-
# struct OptionSet
|
1108
|
-
# option_idxs::Set{Int}
|
1109
|
-
# end
|
1110
|
-
class OptionSet(PClass):
|
1111
|
-
option_idxs = field(type=set) # Set[int]
|
1112
|
-
def __todict__(self):
|
1113
|
-
return {
|
1114
|
-
"option_idxs": list(self.option_idxs),
|
1115
|
-
}
|
1116
|
-
@staticmethod
|
1117
|
-
def __fromdict__(d):
|
1118
|
-
return OptionSet(
|
1119
|
-
option_idxs=set(d["option_idxs"])
|
1120
|
-
)
|
1121
|
-
|
1122
|
-
|
1123
|
-
class PointCombos(PClass):
|
1124
|
-
point_uuid = field(type=str)
|
1125
|
-
default_combo = field(type=str)
|
1126
|
-
sample_fulfillment = field(type=list) # List[int]
|
1127
|
-
def __todict__(self):
|
1128
|
-
return {
|
1129
|
-
"point_uuid": self.point_uuid,
|
1130
|
-
"default_combo": self.default_combo,
|
1131
|
-
"sample_fulfillment": self.sample_fulfillment,
|
1132
|
-
}
|
1133
|
-
@staticmethod
|
1134
|
-
def __fromdict__(d):
|
1135
|
-
return PointCombos(
|
1136
|
-
point_uuid=d["point_uuid"],
|
1137
|
-
default_combo=d["default_combo"],
|
1138
|
-
sample_fulfillment=d["sample_fulfillment"]
|
1139
|
-
)
|
1140
|
-
|
1141
|
-
|
1142
|
-
class PlayerInfo(PClass):
|
1143
|
-
fig = field(type=Fig)
|
1144
|
-
player_idx = field(type=int)
|
1145
|
-
new_route_cards = field(type=PVector) # List[int]
|
1146
|
-
route_cards = field(type=PVector) # List[int]
|
1147
|
-
unit_cards = field(type=PVector) # List[int]
|
1148
|
-
completed_routes = field(type=list) # List[int]
|
1149
|
-
completed_clusters = field(type=list) # List[UUID]
|
1150
|
-
paths = field(type=list) # List[int]
|
1151
|
-
points = field(type=list) # List[UUID]
|
1152
|
-
tokens = field(type=list) # List[UUID]
|
1153
|
-
num_pieces = field(type=int)
|
1154
|
-
num_point_pieces = field(type=int)
|
1155
|
-
longest_trail = field(type=list) # List[int]
|
1156
|
-
longest_trail_len = field(type=int)
|
1157
|
-
final_score = field(type=object) # Union{Nothing, PlayerScore}
|
1158
|
-
def __todict__(self):
|
1159
|
-
return {
|
1160
|
-
"fig": self.fig.__todict__(),
|
1161
|
-
"player_idx": self.player_idx,
|
1162
|
-
"new_route_cards": list(self.new_route_cards),
|
1163
|
-
"route_cards": list(self.route_cards),
|
1164
|
-
"unit_cards": list(self.unit_cards),
|
1165
|
-
"completed_routes": self.completed_routes,
|
1166
|
-
"completed_clusters": self.completed_clusters,
|
1167
|
-
"paths": self.paths,
|
1168
|
-
"points": self.points,
|
1169
|
-
"tokens": self.tokens,
|
1170
|
-
"num_pieces": self.num_pieces,
|
1171
|
-
"num_point_pieces": self.num_point_pieces,
|
1172
|
-
"longest_trail": self.longest_trail,
|
1173
|
-
"longest_trail_len": self.longest_trail_len,
|
1174
|
-
"final_score": self.final_score.__todict__() if self.final_score else None,
|
1175
|
-
}
|
1176
|
-
@staticmethod
|
1177
|
-
def __fromdict__(d):
|
1178
|
-
return PlayerInfo(
|
1179
|
-
fig=Fig.__fromdict__(d["fig"]),
|
1180
|
-
player_idx=d["player_idx"],
|
1181
|
-
new_route_cards=pvector(d["new_route_cards"]),
|
1182
|
-
route_cards=pvector(d["route_cards"]),
|
1183
|
-
unit_cards=pvector(d["unit_cards"]),
|
1184
|
-
completed_routes=d["completed_routes"],
|
1185
|
-
completed_clusters=d["completed_clusters"],
|
1186
|
-
paths=d["paths"],
|
1187
|
-
points=d["points"],
|
1188
|
-
tokens=d["tokens"],
|
1189
|
-
num_pieces=d["num_pieces"],
|
1190
|
-
num_point_pieces=d["num_point_pieces"],
|
1191
|
-
longest_trail=d["longest_trail"],
|
1192
|
-
longest_trail_len=d["longest_trail_len"],
|
1193
|
-
final_score=PlayerScore.__fromdict__(d["final_score"]) if d.get("final_score") else None,
|
1194
|
-
)
|
1195
|
-
@staticmethod
|
1196
|
-
def clone(hand):
|
1197
|
-
return PlayerInfo.__fromdict__(hand.__todict__())
|
1198
|
-
|
1199
|
-
|
1200
992
|
class PublicPlayer(PClass):
|
1201
993
|
idx = field(type=int)
|
1202
994
|
pieces = field(type=list) # List[Piece]
|
@@ -1307,36 +1099,27 @@ class PrivatePlayerScore(PClass):
|
|
1307
1099
|
)
|
1308
1100
|
|
1309
1101
|
|
1310
|
-
# Implementing the following Julia function:
|
1311
|
-
# struct PrivateState
|
1312
|
-
# legal_actions::Vector{ActionSpec}
|
1313
|
-
# segment_statuses::Vector{SegmentStatus}
|
1314
|
-
# hand::PlayerInfo
|
1315
|
-
# end
|
1316
1102
|
class PrivateState(PClass):
|
1103
|
+
my_history = field(type=list) # List[Action2]
|
1317
1104
|
player_score = field(type=PrivatePlayerScore)
|
1318
1105
|
player = field(type=Player)
|
1319
1106
|
legal_actions_2 = field(type=list) # List[LegalAction]
|
1320
|
-
legal_actions = field(type=list) # List[ActionSpec]
|
1321
|
-
hand = field(type=PlayerInfo)
|
1322
1107
|
goal_completions = field(type=list, initial=[]) # List[GoalCompletion]
|
1323
1108
|
def __todict__(self):
|
1324
1109
|
return {
|
1110
|
+
"my_history": [x.__todict__() for x in self.my_history],
|
1325
1111
|
"player_score": self.player_score.__todict__(),
|
1326
1112
|
"player": self.player.__todict__(),
|
1327
1113
|
"legal_actions_2": [x.__todict__() for x in self.legal_actions_2],
|
1328
|
-
"legal_actions": [x.__todict__() for x in self.legal_actions],
|
1329
|
-
"hand": self.hand.__todict__(),
|
1330
1114
|
"goal_completions": [x.__todict__() for x in self.goal_completions],
|
1331
1115
|
}
|
1332
1116
|
@staticmethod
|
1333
1117
|
def __fromdict__(d):
|
1334
1118
|
return PrivateState(
|
1119
|
+
my_history=[Action2.__fromdict__(x) for x in d["my_history"]],
|
1335
1120
|
player_score=PrivatePlayerScore.__fromdict__(d["player_score"]),
|
1336
1121
|
player=Player.__fromdict__(d["player"]),
|
1337
1122
|
legal_actions_2=[LegalAction.__fromdict__(x) for x in d["legal_actions_2"]],
|
1338
|
-
legal_actions=[ActionSpec.__fromdict__(x) for x in d["legal_actions"]],
|
1339
|
-
hand=PlayerInfo.__fromdict__(d["hand"]),
|
1340
1123
|
goal_completions=[GoalCompletion.__fromdict__(x) for x in d["goal_completions"]],
|
1341
1124
|
)
|
1342
1125
|
|
@@ -2155,7 +1938,6 @@ class State(PClass):
|
|
2155
1938
|
uuid2segment = field(type=dict) # Dict[str, Segment]
|
2156
1939
|
pieceuuid2piece = field(type=dict) # Dict[str, Piece]
|
2157
1940
|
carduuid2card = field(type=dict) # Dict[str, Card]
|
2158
|
-
final_scores = field(type=(list, type(None)), initial=None) # Optional[List[int]]
|
2159
1941
|
bonus_statuses = field(type=list) # List[BonusStatus]
|
2160
1942
|
bonusuuid2bonusidx = field(type=dict) # Dict[str, int]
|
2161
1943
|
carduuid2deckidx = field(type=dict) # Dict[str, int]
|
@@ -2179,10 +1961,6 @@ class State(PClass):
|
|
2179
1961
|
game_config = field(type=GameConfig)
|
2180
1962
|
rng = field(type=random.Random)
|
2181
1963
|
terminal = field(type=bool)
|
2182
|
-
initial_to_play = field(type=list) # List[int]
|
2183
|
-
route_cards = field(type=PVector) # List[int]
|
2184
|
-
route_discards = field(type=PVector) # List[int]
|
2185
|
-
player_hands = field(type=PVector) # List[PlayerInfo]
|
2186
1964
|
last_to_play = field(type=(int, type(None)), initial=None)
|
2187
1965
|
winners = field(type=list) # List[int]
|
2188
1966
|
def __todict__(self):
|
@@ -2192,7 +1970,6 @@ class State(PClass):
|
|
2192
1970
|
"uuid2segment": {k: v.__todict__() for k, v in self.uuid2segment.items()},
|
2193
1971
|
"pieceuuid2piece": {k: v.__todict__() for k, v in self.pieceuuid2piece.items()},
|
2194
1972
|
"carduuid2card": {k: v.__todict__() for k, v in self.carduuid2card.items()},
|
2195
|
-
"final_scores": self.final_scores,
|
2196
1973
|
"bonus_statuses": [status.__todict__() for status in self.bonus_statuses],
|
2197
1974
|
"bonusuuid2bonusidx": self.bonusuuid2bonusidx,
|
2198
1975
|
"carduuid2deckidx": self.carduuid2deckidx,
|
@@ -2216,10 +1993,6 @@ class State(PClass):
|
|
2216
1993
|
"game_config": self.game_config.__todict__(),
|
2217
1994
|
"rng": rng2json(self.rng),
|
2218
1995
|
"terminal": self.terminal,
|
2219
|
-
"initial_to_play": self.initial_to_play,
|
2220
|
-
"route_cards": list(self.route_cards),
|
2221
|
-
"route_discards": list(self.route_discards),
|
2222
|
-
"player_hands": [x.__todict__() for x in self.player_hands],
|
2223
1996
|
"last_to_play": self.last_to_play,
|
2224
1997
|
"winners": self.winners,
|
2225
1998
|
}
|
@@ -2231,7 +2004,6 @@ class State(PClass):
|
|
2231
2004
|
uuid2segment={k: Segment2.__fromdict__(v) for k, v in d["uuid2segment"].items()},
|
2232
2005
|
pieceuuid2piece={k: Piece.__fromdict__(v) for k, v in d["pieceuuid2piece"].items()},
|
2233
2006
|
carduuid2card={k: Card.__fromdict__(v) for k, v in d["carduuid2card"].items()},
|
2234
|
-
final_scores=d["final_scores"],
|
2235
2007
|
bonus_statuses=[BonusStatus.__fromdict__(x) for x in d["bonus_statuses"]],
|
2236
2008
|
bonusuuid2bonusidx=d["bonusuuid2bonusidx"],
|
2237
2009
|
carduuid2deckidx=d["carduuid2deckidx"],
|
@@ -2255,10 +2027,6 @@ class State(PClass):
|
|
2255
2027
|
game_config=GameConfig.__fromdict__(d["game_config"]),
|
2256
2028
|
rng=json2rng(d["rng"]),
|
2257
2029
|
terminal=d["terminal"],
|
2258
|
-
initial_to_play=d["initial_to_play"],
|
2259
|
-
route_cards=pvector(d["route_cards"]),
|
2260
|
-
route_discards=pvector(d["route_discards"]),
|
2261
|
-
player_hands=pvector([PlayerInfo.__fromdict__(h) for h in d["player_hands"]]),
|
2262
2030
|
last_to_play=d.get("last_to_play"),
|
2263
2031
|
winners=d["winners"],
|
2264
2032
|
)
|
@@ -2514,7 +2282,6 @@ class PublicState(PClass):
|
|
2514
2282
|
decks = field(type=list) # List[PublicDeck]
|
2515
2283
|
piles = field(type=list) # List[Pile]
|
2516
2284
|
player_idxs = field(type=list) # List[int]
|
2517
|
-
initial_to_play = field(type=list) # List[int]
|
2518
2285
|
players = field(type=list) # List[PublicPlayer]
|
2519
2286
|
last_to_play = field(type=(int, type(None)), initial=None)
|
2520
2287
|
winners = field(type=list)
|
@@ -2539,7 +2306,6 @@ class PublicState(PClass):
|
|
2539
2306
|
"decks": [deck.__todict__() for deck in self.decks],
|
2540
2307
|
"piles": [pile.__todict__() for pile in self.piles],
|
2541
2308
|
"player_idxs": self.player_idxs,
|
2542
|
-
"initial_to_play": self.initial_to_play,
|
2543
2309
|
"players": [x.__todict__() for x in self.players],
|
2544
2310
|
"last_to_play": self.last_to_play,
|
2545
2311
|
"winners": self.winners,
|
@@ -2566,7 +2332,6 @@ class PublicState(PClass):
|
|
2566
2332
|
decks=[PublicDeck.__fromdict__(deck) for deck in d["decks"]],
|
2567
2333
|
piles=[Pile.__fromdict__(x) for x in d["piles"]],
|
2568
2334
|
player_idxs=d["player_idxs"],
|
2569
|
-
initial_to_play=d["initial_to_play"],
|
2570
2335
|
players=[PublicPlayer.__fromdict__(x) for x in d["players"]],
|
2571
2336
|
last_to_play=d.get("last_to_play"),
|
2572
2337
|
winners=d["winners"],
|
@@ -2720,50 +2485,9 @@ def getsettingvalue(s, setting_name):
|
|
2720
2485
|
def getinitialstate(game_config):
|
2721
2486
|
fig = game_config.fig
|
2722
2487
|
rng = getrng(game_config.seed)
|
2723
|
-
route_deck = shuffledeck(getnumroutecards(fig), rng)
|
2724
2488
|
unit_deck = shuffledeck(gettotaldeckcards(fig), rng)
|
2725
2489
|
route_deck_idx, unit_deck_idx = 0, 0
|
2726
|
-
player_hands = []
|
2727
|
-
initial_num_route_choices = getsettingvalue(fig, "initial_num_route_choices")
|
2728
|
-
num_initial_unit_cards = getsettingvalue(fig, "num_initial_unit_cards")
|
2729
|
-
num_segment_pieces_per_player = getsettingvalue(fig, "num_segment_pieces_per_player")
|
2730
|
-
num_point_pieces_per_player = getsettingvalue(fig, "num_point_pieces_per_player")
|
2731
|
-
|
2732
|
-
|
2733
|
-
for player_idx in range(game_config.num_players):
|
2734
|
-
player_hand = PlayerInfo(
|
2735
|
-
fig=fig,
|
2736
|
-
player_idx=player_idx,
|
2737
|
-
new_route_cards=pvector(route_deck[route_deck_idx:(route_deck_idx+(initial_num_route_choices))]),
|
2738
|
-
route_cards=pvector([]),
|
2739
|
-
unit_cards=pvector(unit_deck[unit_deck_idx:(unit_deck_idx + num_initial_unit_cards)]),
|
2740
|
-
completed_routes=[],
|
2741
|
-
completed_clusters=[],
|
2742
|
-
paths=[],
|
2743
|
-
points=[],
|
2744
|
-
tokens=[],
|
2745
|
-
num_pieces=num_segment_pieces_per_player,
|
2746
|
-
num_point_pieces=num_point_pieces_per_player,
|
2747
|
-
longest_trail=[],
|
2748
|
-
longest_trail_len=0,
|
2749
|
-
final_score=None,
|
2750
|
-
)
|
2751
|
-
player_hands.append(player_hand)
|
2752
|
-
route_deck_idx += initial_num_route_choices
|
2753
|
-
unit_deck_idx += num_initial_unit_cards
|
2754
|
-
|
2755
|
-
faceup_spots = getfaceupspots(fig, unit_deck, unit_deck_idx)
|
2756
2490
|
unit_deck_idx += 5
|
2757
|
-
# Implementing the following Julia function:
|
2758
|
-
# unit_cards = unit_deck[unit_deck_idx:end]
|
2759
|
-
unit_cards = unit_deck[unit_deck_idx:] if unit_deck_idx < len(unit_deck) else []
|
2760
|
-
route_cards = route_deck[route_deck_idx:]
|
2761
|
-
|
2762
|
-
if getsettingvalue(fig, 'action_route_discard'):
|
2763
|
-
initial_to_play = list(range(game_config.num_players))
|
2764
|
-
else:
|
2765
|
-
initial_to_play = [getfirstplayeridx(rng, game_config.num_players)]
|
2766
|
-
|
2767
2491
|
board_config = fig.board_config
|
2768
2492
|
deck_0_rng = getrng(1234321)
|
2769
2493
|
deck_1_rng = getrng(8738758)
|
@@ -2848,7 +2572,6 @@ def getinitialstate(game_config):
|
|
2848
2572
|
uuid2segment=uuid2segment,
|
2849
2573
|
pieceuuid2piece=pieceuuid2piece,
|
2850
2574
|
carduuid2card=carduuid2card,
|
2851
|
-
final_scores=None,
|
2852
2575
|
bonus_statuses=bonus_statuses,
|
2853
2576
|
bonusuuid2bonusidx=bonusuuid2bonusidx,
|
2854
2577
|
carduuid2deckidx=carduuid2deckidx,
|
@@ -2879,11 +2602,7 @@ def getinitialstate(game_config):
|
|
2879
2602
|
player_idxs=list(range(game_config.num_players)),
|
2880
2603
|
decks=decks,
|
2881
2604
|
game_config=game_config,
|
2882
|
-
initial_to_play=initial_to_play,
|
2883
2605
|
rng=rng,
|
2884
|
-
route_cards=pvector(route_cards),
|
2885
|
-
route_discards=pvector([]),
|
2886
|
-
player_hands=pvector(player_hands),
|
2887
2606
|
last_to_play=None,
|
2888
2607
|
winners=[],
|
2889
2608
|
terminal=False,
|
@@ -2994,15 +2713,20 @@ def handle_last_to_play(game):
|
|
2994
2713
|
return game
|
2995
2714
|
|
2996
2715
|
|
2716
|
+
def getfinalscores(game):
|
2717
|
+
return [
|
2718
|
+
getpublicplayerscore(game, game.player_scores[player_idx]).total
|
2719
|
+
for player_idx in range(len(game.players))
|
2720
|
+
]
|
2721
|
+
|
2722
|
+
|
2997
2723
|
def handle_calc_winners(game):
|
2998
2724
|
if game.terminal:
|
2999
2725
|
players_with_highest_score = []
|
3000
2726
|
highest_score = -1000
|
3001
|
-
final_scores =
|
2727
|
+
final_scores = getfinalscores(game)
|
3002
2728
|
for player_idx in range(len(game.players)):
|
3003
|
-
|
3004
|
-
final_score = getpublicplayerscore(game, player_score).total
|
3005
|
-
final_scores.append(final_score)
|
2729
|
+
final_score = final_scores[player_idx]
|
3006
2730
|
if final_score > highest_score:
|
3007
2731
|
highest_score = final_score
|
3008
2732
|
players_with_highest_score = [player_idx]
|
@@ -3010,7 +2734,6 @@ def handle_calc_winners(game):
|
|
3010
2734
|
players_with_highest_score.append(player_idx)
|
3011
2735
|
return game.set(
|
3012
2736
|
winners=players_with_highest_score,
|
3013
|
-
final_scores=final_scores,
|
3014
2737
|
)
|
3015
2738
|
|
3016
2739
|
return game
|
@@ -4308,63 +4031,6 @@ def getnextstate2(s, a, log=False):
|
|
4308
4031
|
return s
|
4309
4032
|
|
4310
4033
|
|
4311
|
-
|
4312
|
-
@dispatch(State, QValueLearningPolicy)
|
4313
|
-
def getnextaction(s, policy):
|
4314
|
-
player_idx = gettoplay(s)[0]
|
4315
|
-
legal_action_specs = getlegalactionspecsforplayer(s, player_idx, None, None)
|
4316
|
-
legal_actions = get_all_legal_actions(s, player_idx, legal_action_specs)
|
4317
|
-
|
4318
|
-
if s.rng.random() <= policy.epsilon:
|
4319
|
-
random_action = legal_actions[s.rng.randint(0, len(legal_actions) - 1)]
|
4320
|
-
return random_action
|
4321
|
-
|
4322
|
-
q_values = policy.qvalue_fn(s, legal_actions)
|
4323
|
-
argmax_idx = max(range(len(q_values)), key=lambda i: q_values[i])
|
4324
|
-
|
4325
|
-
return legal_actions[argmax_idx]
|
4326
|
-
|
4327
|
-
|
4328
|
-
@dispatch(State, RandoPolicy)
|
4329
|
-
def getnextaction(s, policy):
|
4330
|
-
player_idx = gettoplay(s)[0]
|
4331
|
-
legal_actions = getlegalactionspecsforplayer(s, player_idx, None, None)
|
4332
|
-
action_spec = legal_actions[s.rng.randint(0, len(legal_actions) - 1)]
|
4333
|
-
|
4334
|
-
if action_spec.action_name == "ROUTE_DISCARD":
|
4335
|
-
return AltAction(
|
4336
|
-
action_name="ROUTE_DISCARD",
|
4337
|
-
player_idx=player_idx,
|
4338
|
-
return_route_cards=[0],
|
4339
|
-
)
|
4340
|
-
|
4341
|
-
if action_spec.action_name == "DRAW_UNIT_FACEUP":
|
4342
|
-
draw_faceup_spot_num = 1
|
4343
|
-
return AltAction(
|
4344
|
-
action_name="DRAW_UNIT_FACEUP",
|
4345
|
-
player_idx=player_idx,
|
4346
|
-
draw_faceup_unit_card_num=s.faceup_spots[draw_faceup_spot_num-1],
|
4347
|
-
draw_faceup_spot_num=draw_faceup_spot_num,
|
4348
|
-
)
|
4349
|
-
|
4350
|
-
if action_spec.action_name == "DRAW_UNIT_DECK":
|
4351
|
-
return AltAction(
|
4352
|
-
action_name="DRAW_UNIT_DECK",
|
4353
|
-
player_idx=player_idx,
|
4354
|
-
)
|
4355
|
-
|
4356
|
-
if action_spec.action_name == "CLAIM_POINT":
|
4357
|
-
point = action_spec.points[s.rng.randint(0, len(action_spec.points) - 1)]
|
4358
|
-
return AltAction(
|
4359
|
-
action_name="CLAIM_POINT",
|
4360
|
-
player_idx=player_idx,
|
4361
|
-
point_uuid=str(point.point_uuid),
|
4362
|
-
unit_combo=point.default_combo,
|
4363
|
-
)
|
4364
|
-
|
4365
|
-
return None
|
4366
|
-
|
4367
|
-
|
4368
4034
|
def getpublicplayerscore(s, player_score):
|
4369
4035
|
if s.terminal:
|
4370
4036
|
# Join the arrays of public and private items
|
@@ -4448,6 +4114,98 @@ def get_deadlines(s):
|
|
4448
4114
|
]
|
4449
4115
|
|
4450
4116
|
|
4117
|
+
def get_public_player_scores(s):
|
4118
|
+
return [getpublicplayerscore(s, player_score) for player_score in s.player_scores]
|
4119
|
+
|
4120
|
+
|
4121
|
+
# deadlines = field(type=list) # List[RemainingAllottedTime|None]
|
4122
|
+
# game_started_at = field(type=str)
|
4123
|
+
# allotted_times = field(type=list)
|
4124
|
+
# all_pieces = field(type=list) # List[Piece]
|
4125
|
+
# to_play_2 = field(type=list) # List[int]
|
4126
|
+
# bonus_statuses = field(type=list) # List[BonusStatus]
|
4127
|
+
# starting_decks = field(type=list) # List[Deck]
|
4128
|
+
# starting_piles = field(type=list) # List[Pile]
|
4129
|
+
# history = field(type=list) # List[PublicAction]
|
4130
|
+
# player_scores = field(type=list) # List[PublicPlayerScore]
|
4131
|
+
# player_graphs = field(type=list) # List[PlayerGraph]
|
4132
|
+
# goals = field(type=list) # List[Goal]
|
4133
|
+
# nodes = field(type=list) # List[Node]
|
4134
|
+
# edges = field(type=list) # List[BiEdge]
|
4135
|
+
# regions = field(type=list)
|
4136
|
+
# decks = field(type=list) # List[PublicDeck]
|
4137
|
+
# piles = field(type=list) # List[Pile]
|
4138
|
+
# player_idxs = field(type=list) # List[int]
|
4139
|
+
# players = field(type=list) # List[PublicPlayer]
|
4140
|
+
# last_to_play = field(type=(int, type(None)), initial=None)
|
4141
|
+
# winners = field(type=list)
|
4142
|
+
# = field(type=bool)
|
4143
|
+
|
4144
|
+
|
4145
|
+
# player_score = field(type=PrivatePlayerScore)
|
4146
|
+
# player = field(type=Player)
|
4147
|
+
# legal_actions_2 = field(type=list) # List[LegalAction]
|
4148
|
+
# goal_completions = field(type=list, initial=[]) # List[GoalCompletion]
|
4149
|
+
|
4150
|
+
|
4151
|
+
|
4152
|
+
def get_public_history(s):
|
4153
|
+
return [action.get_public(s) for action in s.history]
|
4154
|
+
|
4155
|
+
def imagine_history(public_state, private_state):
|
4156
|
+
pass
|
4157
|
+
|
4158
|
+
def imagine_player_scores(public_state, private_state):
|
4159
|
+
pass
|
4160
|
+
|
4161
|
+
def imagine_legal_actions(public_state, private_state):
|
4162
|
+
pass
|
4163
|
+
|
4164
|
+
def imagine_players(public_state, private_state):
|
4165
|
+
pass
|
4166
|
+
|
4167
|
+
def imagine_decks(public_state, private_state):
|
4168
|
+
pass
|
4169
|
+
|
4170
|
+
def imagine_rng(public_state, private_state):
|
4171
|
+
pass
|
4172
|
+
|
4173
|
+
|
4174
|
+
def imagine_state(public_state, private_state):
|
4175
|
+
return State(
|
4176
|
+
uuid2edge = public_state.uuid2edge,
|
4177
|
+
idx2path = public_state.idx2path,
|
4178
|
+
uuid2segment = public_state.uuid2segment,
|
4179
|
+
pieceuuid2piece = public_state.pieceuuid2piece,
|
4180
|
+
carduuid2card = public_state.carduuid2card,
|
4181
|
+
bonus_statuses = public_state.bonus_statuses,
|
4182
|
+
bonusuuid2bonusidx = public_state.bonusuuid2bonusidx,
|
4183
|
+
carduuid2deckidx = public_state.carduuid2deckidx,
|
4184
|
+
starting_decks = public_state.starting_decks,
|
4185
|
+
starting_piles = public_state.starting_piles,
|
4186
|
+
player_graphs = public_state.player_graphs,
|
4187
|
+
goals = public_state.goals,
|
4188
|
+
nodes = public_state.nodes,
|
4189
|
+
nodeuuid2idx = public_state.nodeuuid2idx,
|
4190
|
+
edges = public_state.edges,
|
4191
|
+
edgeuuid2idx = public_state.edgeuuid2idx,
|
4192
|
+
edgetuple2uuid = public_state.edgetuple2uuid,
|
4193
|
+
regions = public_state.regions,
|
4194
|
+
terminal = public_state.terminal,
|
4195
|
+
last_to_play = public_state.last_to_play,
|
4196
|
+
winners = public_state.winners,
|
4197
|
+
piles = public_state.piles,
|
4198
|
+
player_idxs = public_state.player_idxs,
|
4199
|
+
game_config = public_state.game_config,
|
4200
|
+
legal_actions_2 = imagine_legal_actions(public_state, private_state),
|
4201
|
+
players = imagine_players(public_state, private_state),
|
4202
|
+
decks = imagine_decks(public_state, private_state),
|
4203
|
+
rng = imagine_rng(public_state, private_state),
|
4204
|
+
history = imagine_history(public_state, private_state),
|
4205
|
+
player_scores = imagine_player_scores(public_state, private_state),
|
4206
|
+
)
|
4207
|
+
|
4208
|
+
|
4451
4209
|
@dispatch(State)
|
4452
4210
|
def getpublicstate(s):
|
4453
4211
|
return PublicState(
|
@@ -4459,8 +4217,8 @@ def getpublicstate(s):
|
|
4459
4217
|
bonus_statuses=s.bonus_statuses,
|
4460
4218
|
starting_decks=s.starting_decks,
|
4461
4219
|
starting_piles=s.starting_piles,
|
4462
|
-
history=
|
4463
|
-
player_scores=
|
4220
|
+
history=get_public_history(s),
|
4221
|
+
player_scores=get_public_player_scores(s),
|
4464
4222
|
player_graphs=s.player_graphs,
|
4465
4223
|
goals=s.goals,
|
4466
4224
|
nodes=s.nodes,
|
@@ -4469,7 +4227,6 @@ def getpublicstate(s):
|
|
4469
4227
|
decks=[getpublicdeck(s, deck) for deck in s.decks],
|
4470
4228
|
piles=s.piles,
|
4471
4229
|
player_idxs=s.player_idxs,
|
4472
|
-
initial_to_play=s.initial_to_play,
|
4473
4230
|
players=[getpublicplayer(s, p) for p in s.players],
|
4474
4231
|
last_to_play=s.last_to_play,
|
4475
4232
|
winners=s.winners,
|
@@ -4619,18 +4376,6 @@ def gettoplay(s, last_action_type):
|
|
4619
4376
|
return [getlastplayeridxplus1(s)]
|
4620
4377
|
|
4621
4378
|
|
4622
|
-
# Implementing the following Julia function:
|
4623
|
-
@dispatch(State, NoAction)
|
4624
|
-
# function gettoplay(s::State, last_action_key::Nothing)
|
4625
|
-
# if getsettingvalue(s, :action_route_discard)
|
4626
|
-
# return collect(1:s.game_config.num_players)
|
4627
|
-
# end
|
4628
|
-
# [getfirstplayeridx(s.game)]
|
4629
|
-
# end
|
4630
|
-
def gettoplay(s, last_action_type):
|
4631
|
-
return s.initial_to_play
|
4632
|
-
|
4633
|
-
|
4634
4379
|
def getrng(seed):
|
4635
4380
|
rng = random.Random()
|
4636
4381
|
rng.seed(seed)
|
@@ -4791,262 +4536,6 @@ def combinations(a, n=None):
|
|
4791
4536
|
# then the state is "terminal".
|
4792
4537
|
###
|
4793
4538
|
|
4794
|
-
# Implementing the following Julia function:
|
4795
|
-
# function getrouteoptionsets(s::State, player_idx, min_required)
|
4796
|
-
# num_choices = length(s.player_hands[player_idx].new_route_cards)
|
4797
|
-
# max_return_size = num_choices - min_required
|
4798
|
-
# set = collect(1:num_choices)
|
4799
|
-
# OptionSet.(
|
4800
|
-
# Set{Int}.(
|
4801
|
-
# reduce(
|
4802
|
-
# vcat,
|
4803
|
-
# [collect(combinations(set, n)) for n in 0:max_return_size],
|
4804
|
-
# )
|
4805
|
-
# )
|
4806
|
-
# )
|
4807
|
-
# end
|
4808
|
-
def getrouteoptionsets(s, player_idx, min_required):
|
4809
|
-
num_choices = len(s.player_hands[player_idx].new_route_cards)
|
4810
|
-
max_return_size = num_choices - min_required
|
4811
|
-
choice_set = list(range(num_choices))
|
4812
|
-
all_combinations = [
|
4813
|
-
set(comb)
|
4814
|
-
for n in range(max_return_size + 1)
|
4815
|
-
for comb in combinations(choice_set, n)
|
4816
|
-
]
|
4817
|
-
return [OptionSet(option_idxs=comb) for comb in all_combinations]
|
4818
|
-
|
4819
|
-
|
4820
|
-
|
4821
|
-
# Implementing the following Julia function:
|
4822
|
-
# function getlegalactionsforplayer(s::State, player_idx, repeat_player, last_action)
|
4823
|
-
# min_initial_routes = getsettingvalue(s.fig, :min_initial_routes)
|
4824
|
-
# min_chosen_routes = getsettingvalue(s.fig, :min_chosen_routes)
|
4825
|
-
|
4826
|
-
# action_specs = ActionSpec[]
|
4827
|
-
# if getsettingvalue(s, :action_draw_unit_faceup) && !isempty(getvalidspotnums(s))
|
4828
|
-
# push!(
|
4829
|
-
# action_specs,
|
4830
|
-
# ActionSpec(
|
4831
|
-
# player_idx=player_idx,
|
4832
|
-
# action_name=DRAW_UNIT_FACEUP,
|
4833
|
-
# draw_faceup_spots=Dict((spot_num, s.faceup_spots[spot_num]) for spot_num in getvalidspotnums(s)),
|
4834
|
-
# )
|
4835
|
-
# )
|
4836
|
-
# end
|
4837
|
-
|
4838
|
-
# if getsettingvalue(s, :action_draw_route) && (length(s.route_cards) + length(s.route_discards)) >= min_chosen_routes
|
4839
|
-
# push!(action_specs, ActionSpec(s.fig, player_idx, :DRAW_ROUTE))
|
4840
|
-
# end
|
4841
|
-
|
4842
|
-
# if getsettingvalue(s, :action_draw_unit_deck) && (!isempty(s.unit_cards) || !isempty(s.unit_discards))
|
4843
|
-
# push!(action_specs, ActionSpec(s.fig, player_idx, :DRAW_UNIT_DECK))
|
4844
|
-
# end
|
4845
|
-
|
4846
|
-
# if getsettingvalue(s, :action_claim_path)
|
4847
|
-
# append!(action_specs, getclaimpathactionspecs(s, player_idx))
|
4848
|
-
# end
|
4849
|
-
|
4850
|
-
# if getsettingvalue(s.fig, :action_claim_point)
|
4851
|
-
# append!(action_specs, getclaimpointactionspecs(s, player_idx))
|
4852
|
-
# end
|
4853
|
-
|
4854
|
-
# action_specs
|
4855
|
-
# end
|
4856
|
-
@dispatch(State, int, object, object)
|
4857
|
-
def getlegalactionspecsforplayer(s, player_idx, repeat_player, last_action):
|
4858
|
-
min_chosen_routes = getsettingvalue(s, 'min_chosen_routes')
|
4859
|
-
|
4860
|
-
action_specs = []
|
4861
|
-
if getsettingvalue(s, 'action_draw_unit_faceup') and s.faceup_spots:
|
4862
|
-
|
4863
|
-
# Convert this Julia to Python:
|
4864
|
-
# Julia:
|
4865
|
-
# draw_faceup_spots = Dict((spot_num, s.faceup_spots[spot_num]) for spot_num in getvalidspotnums(s))
|
4866
|
-
# Python:
|
4867
|
-
draw_faceup_spots = {spot_num: s.faceup_spots[spot_num-1] for spot_num in getvalidspotnums(s)}
|
4868
|
-
|
4869
|
-
action_specs.append(
|
4870
|
-
ActionSpec(
|
4871
|
-
player_idx=player_idx,
|
4872
|
-
action_name="DRAW_UNIT_FACEUP",
|
4873
|
-
return_route_option_sets = [],
|
4874
|
-
draw_faceup_spots=draw_faceup_spots,
|
4875
|
-
points = [],
|
4876
|
-
paths = [],
|
4877
|
-
)
|
4878
|
-
)
|
4879
|
-
|
4880
|
-
if getsettingvalue(s, 'action_draw_route') and (len(s.route_cards) + len(s.route_discards)) >= min_chosen_routes:
|
4881
|
-
action_specs.append(
|
4882
|
-
AltAction(
|
4883
|
-
player_idx=player_idx,
|
4884
|
-
action_name="DRAW_ROUTE",
|
4885
|
-
return_route_option_sets = [],
|
4886
|
-
draw_faceup_spots={},
|
4887
|
-
points = [],
|
4888
|
-
paths = [],
|
4889
|
-
)
|
4890
|
-
)
|
4891
|
-
|
4892
|
-
if getsettingvalue(s, 'action_draw_unit_deck') and (s.unit_cards or s.unit_discards):
|
4893
|
-
action_specs.append(
|
4894
|
-
ActionSpec(
|
4895
|
-
player_idx=player_idx,
|
4896
|
-
action_name="DRAW_UNIT_DECK",
|
4897
|
-
return_route_option_sets = [],
|
4898
|
-
draw_faceup_spots={},
|
4899
|
-
points = [],
|
4900
|
-
paths = [],
|
4901
|
-
)
|
4902
|
-
)
|
4903
|
-
|
4904
|
-
if getsettingvalue(s, 'action_claim_path'):
|
4905
|
-
action_specs.extend(getclaimpathactionspecs(s, player_idx))
|
4906
|
-
pass
|
4907
|
-
|
4908
|
-
if getsettingvalue(s, 'action_claim_point'):
|
4909
|
-
action_specs.extend(getclaimpointactionspecs(s, player_idx))
|
4910
|
-
|
4911
|
-
return action_specs
|
4912
|
-
|
4913
|
-
|
4914
|
-
# Implementing the following Julia function:
|
4915
|
-
# function getclaimpointactionspecs(s::State, player_idx::Int; log=false)
|
4916
|
-
# action_specs = ActionSpec[]
|
4917
|
-
# available_point_statuses = getavailablepoints(s, player_idx)
|
4918
|
-
# points = map(available_point_statuses) do available_point_status
|
4919
|
-
# (; uuid, sample_fulfillment) = available_point_status
|
4920
|
-
# fulfillment_sorted = sample_fulfillment
|
4921
|
-
# sample_fulfillment = [x.unit_card_num for x in fulfillment_sorted]
|
4922
|
-
# fulfillment_str = join(sample_fulfillment, "-")
|
4923
|
-
# PointCombos(uuid, fulfillment_str, sample_fulfillment)
|
4924
|
-
# end
|
4925
|
-
# if !isempty(points)
|
4926
|
-
# push!(
|
4927
|
-
# action_specs,
|
4928
|
-
# ActionSpec(
|
4929
|
-
# action_name=CLAIM_POINT,
|
4930
|
-
# player_idx=player_idx,
|
4931
|
-
# points=points,
|
4932
|
-
# )
|
4933
|
-
# )
|
4934
|
-
# end
|
4935
|
-
# action_specs
|
4936
|
-
# end
|
4937
|
-
def getclaimpointactionspecs(s, player_idx, log=False):
|
4938
|
-
action_specs = []
|
4939
|
-
available_point_statuses = getavailablepoints(s, player_idx)
|
4940
|
-
|
4941
|
-
# points = map(available_point_statuses) do available_point_status
|
4942
|
-
# (; uuid, sample_fulfillment) = available_point_status
|
4943
|
-
# fulfillment_sorted = sample_fulfillment
|
4944
|
-
# sample_fulfillment = [x.unit_card_num for x in fulfillment_sorted]
|
4945
|
-
# fulfillment_str = join(sample_fulfillment, "-")
|
4946
|
-
# PointCombos(uuid, fulfillment_str, sample_fulfillment)
|
4947
|
-
# end
|
4948
|
-
|
4949
|
-
def process_point_status(available_point_status):
|
4950
|
-
uuid = available_point_status['uuid']
|
4951
|
-
sample_fulfillment = available_point_status['sample_fulfillment']
|
4952
|
-
fulfillment_sorted = sample_fulfillment
|
4953
|
-
sample_fulfillment = [x['unit_card_num'] for x in fulfillment_sorted]
|
4954
|
-
fulfillment_str = '-'.join(map(str, sample_fulfillment))
|
4955
|
-
return PointCombos(
|
4956
|
-
point_uuid=uuid,
|
4957
|
-
default_combo=fulfillment_str,
|
4958
|
-
sample_fulfillment=sample_fulfillment
|
4959
|
-
)
|
4960
|
-
|
4961
|
-
point_combos = list(map(process_point_status, available_point_statuses))
|
4962
|
-
|
4963
|
-
if point_combos:
|
4964
|
-
action_specs.append(
|
4965
|
-
ActionSpec(
|
4966
|
-
player_idx=player_idx,
|
4967
|
-
action_name="CLAIM_POINT",
|
4968
|
-
return_route_option_sets = [],
|
4969
|
-
draw_faceup_spots = {},
|
4970
|
-
points=point_combos,
|
4971
|
-
paths = [],
|
4972
|
-
)
|
4973
|
-
)
|
4974
|
-
|
4975
|
-
return action_specs
|
4976
|
-
|
4977
|
-
|
4978
|
-
# Implementing the following Julia function:
|
4979
|
-
# function getclaimpathactionspecs(s::State, player_idx::Int; log=false)
|
4980
|
-
# action_specs = ActionSpec[]
|
4981
|
-
# available_path_statuses = getavailablepaths(s, player_idx)
|
4982
|
-
# paths = map(available_path_statuses) do available_path_status
|
4983
|
-
# (; num, sample_fulfillment) = available_path_status
|
4984
|
-
# fulfillment_sorted = Base.sort(sample_fulfillment; by=x -> x.segment_num)
|
4985
|
-
# sample_fulfillment = [x.unit_card_num for x in fulfillment_sorted]
|
4986
|
-
# fulfillment_str = join(sample_fulfillment, "-")
|
4987
|
-
# PathCombos(num, fulfillment_str, sample_fulfillment)
|
4988
|
-
# end
|
4989
|
-
# if !isempty(paths)
|
4990
|
-
# push!(
|
4991
|
-
# action_specs,
|
4992
|
-
# ActionSpec(
|
4993
|
-
# action_name=CLAIM_PATH,
|
4994
|
-
# player_idx=player_idx,
|
4995
|
-
# paths=paths,
|
4996
|
-
# )
|
4997
|
-
# )
|
4998
|
-
# end
|
4999
|
-
# action_specs
|
5000
|
-
# end
|
5001
|
-
def getclaimpathactionspecs(s, player_idx, log=False):
|
5002
|
-
action_specs = []
|
5003
|
-
available_path_statuses = getavailablepathstatuses(s, player_idx)
|
5004
|
-
|
5005
|
-
def process_path_status(available_path_status):
|
5006
|
-
num = available_path_status.num
|
5007
|
-
sample_fulfillment = available_path_status.sample_fulfillment
|
5008
|
-
fulfillment_sorted = sorted(sample_fulfillment, key=lambda x: x.segment_num)
|
5009
|
-
sample_fulfillment = [x.unit_card_num for x in fulfillment_sorted]
|
5010
|
-
fulfillment_str = '-'.join(map(str, sample_fulfillment))
|
5011
|
-
return PathCombos(
|
5012
|
-
path_idx=(num-1),
|
5013
|
-
default_combo=fulfillment_str,
|
5014
|
-
sample_fulfillment=sample_fulfillment
|
5015
|
-
)
|
5016
|
-
|
5017
|
-
paths = list(map(process_path_status, available_path_statuses))
|
5018
|
-
|
5019
|
-
if paths:
|
5020
|
-
action_specs.append(
|
5021
|
-
ActionSpec(
|
5022
|
-
player_idx=player_idx,
|
5023
|
-
action_name="CLAIM_PATH",
|
5024
|
-
return_route_option_sets = [],
|
5025
|
-
draw_faceup_spots={},
|
5026
|
-
points=[],
|
5027
|
-
paths=paths,
|
5028
|
-
)
|
5029
|
-
)
|
5030
|
-
|
5031
|
-
return action_specs
|
5032
|
-
|
5033
|
-
|
5034
|
-
# Implementing the following Julia function:
|
5035
|
-
# function getavailablepaths(s::State, player_num::Int)
|
5036
|
-
# balance = s.player_hands[player_num].unit_cards
|
5037
|
-
# path_statuses = map(getpotentialpathnums(s, player_num)) do path_num
|
5038
|
-
# getpathstatus(s, player_num, path_num)
|
5039
|
-
# end
|
5040
|
-
# filter(x -> x.fulfillable, path_statuses)
|
5041
|
-
# end
|
5042
|
-
def getavailablepathstatuses(s, player_num):
|
5043
|
-
balance = s.player_hands[player_num].unit_cards
|
5044
|
-
path_statuses = [
|
5045
|
-
getpathstatus(s, player_num, path_idx)
|
5046
|
-
for path_idx in getpotentialpathidxs(s, player_num)
|
5047
|
-
]
|
5048
|
-
return list(filter(lambda x: x.fulfillable, path_statuses))
|
5049
|
-
|
5050
4539
|
|
5051
4540
|
# Implementing the following Julia function:
|
5052
4541
|
# function getpotentialpathnums(s::State, player_num::Int)
|
@@ -5275,409 +4764,9 @@ def getclaimedpathidxs(s):
|
|
5275
4764
|
return claimed
|
5276
4765
|
|
5277
4766
|
|
5278
|
-
# Implementing the following Julia function:
|
5279
|
-
# function getpathstatus(s::State, player_idx, path_num)
|
5280
|
-
# balance = s.player_hands[player_idx].unit_cards
|
5281
|
-
# (; fig) = s
|
5282
|
-
# (; board_config) = fig
|
5283
|
-
# (; deck_units, board_paths) = board_config
|
5284
|
-
# unituuid2deckunit = Dict(x.unit_uuid => x for x in deck_units)
|
5285
|
-
# path = board_paths[path_num]
|
5286
|
-
# ordered_segments = prioritysort(fig, path.path.segments)
|
5287
|
-
# fulfillment = OrderedFullfillment[]
|
5288
|
-
# wild_unit_uuids = getwildunituuids(fig)
|
5289
|
-
# # @show wild_unit_uuids
|
5290
|
-
# non_wild_unit_uuids = getnonwildunituuids(fig)
|
5291
|
-
# # @show non_wild_unit_uuids
|
5292
|
-
|
5293
|
-
# # @show balance
|
5294
|
-
|
5295
|
-
# balance_unituuid2deckcardnums = Dict()
|
5296
|
-
# for deck_card_num in balance
|
5297
|
-
# unit_uuid = getunituuid(fig, deck_card_num)
|
5298
|
-
# if !haskey(balance_unituuid2deckcardnums, unit_uuid)
|
5299
|
-
# balance_unituuid2deckcardnums[unit_uuid] = []
|
5300
|
-
# end
|
5301
|
-
# push!(balance_unituuid2deckcardnums[unit_uuid], deck_card_num)
|
5302
|
-
# end
|
5303
4767
|
|
5304
|
-
# # @show balance_unituuid2deckcardnums
|
5305
4768
|
|
5306
|
-
# function hasexactunitmatch(unit_uuid)
|
5307
|
-
# (
|
5308
|
-
# haskey(balance_unituuid2deckcardnums, unit_uuid) &&
|
5309
|
-
# length(balance_unituuid2deckcardnums[unit_uuid]) > 0
|
5310
|
-
# )
|
5311
|
-
# end
|
5312
4769
|
|
5313
|
-
# function anywildsleft()
|
5314
|
-
# for wild_unit_uuid in wild_unit_uuids
|
5315
|
-
# if haskey(balance_unituuid2deckcardnums, wild_unit_uuid)
|
5316
|
-
# if !isempty(balance_unituuid2deckcardnums[wild_unit_uuid])
|
5317
|
-
# return true
|
5318
|
-
# end
|
5319
|
-
# end
|
5320
|
-
# end
|
5321
|
-
# false
|
5322
|
-
# end
|
5323
|
-
|
5324
|
-
# function gettotalwildcount()
|
5325
|
-
# count = 0
|
5326
|
-
# for wild_unit_uuid in wild_unit_uuids
|
5327
|
-
# if haskey(balance_unituuid2deckcardnums, wild_unit_uuid)
|
5328
|
-
# count += length(balance_unituuid2deckcardnums[wild_unit_uuid])
|
5329
|
-
# end
|
5330
|
-
# end
|
5331
|
-
# count
|
5332
|
-
# end
|
5333
|
-
|
5334
|
-
# function popawildcard!()
|
5335
|
-
# for wild_unit_uuid in wild_unit_uuids
|
5336
|
-
# if haskey(balance_unituuid2deckcardnums, wild_unit_uuid)
|
5337
|
-
# if !isempty(balance_unituuid2deckcardnums[wild_unit_uuid])
|
5338
|
-
# return pop!(balance_unituuid2deckcardnums[wild_unit_uuid])
|
5339
|
-
# end
|
5340
|
-
# end
|
5341
|
-
# end
|
5342
|
-
# nothing
|
5343
|
-
# end
|
5344
|
-
|
5345
|
-
# function getnonemptywildstack()
|
5346
|
-
# for wild_unit_uuid in wild_unit_uuids
|
5347
|
-
# if haskey(balance_unituuid2deckcardnums, wild_unit_uuid)
|
5348
|
-
# if !isempty(balance_unituuid2deckcardnums[wild_unit_uuid])
|
5349
|
-
# return balance_unituuid2deckcardnums[wild_unit_uuid]
|
5350
|
-
# end
|
5351
|
-
# end
|
5352
|
-
# end
|
5353
|
-
# nothing
|
5354
|
-
# end
|
5355
|
-
|
5356
|
-
# function getlargestnonwildstack()
|
5357
|
-
# largest_non_wild_unit_uuid = nothing
|
5358
|
-
# largest_found = 0
|
5359
|
-
# for non_wild_unit_uuid in non_wild_unit_uuids
|
5360
|
-
# if haskey(balance_unituuid2deckcardnums, non_wild_unit_uuid)
|
5361
|
-
# curr_length = length(balance_unituuid2deckcardnums[non_wild_unit_uuid])
|
5362
|
-
# if curr_length > largest_found
|
5363
|
-
# largest_found = curr_length
|
5364
|
-
# largest_non_wild_unit_uuid = non_wild_unit_uuid
|
5365
|
-
# end
|
5366
|
-
# end
|
5367
|
-
# end
|
5368
|
-
# if !isnothing(largest_non_wild_unit_uuid)
|
5369
|
-
# return balance_unituuid2deckcardnums[largest_non_wild_unit_uuid]
|
5370
|
-
# end
|
5371
|
-
# nothing
|
5372
|
-
# end
|
5373
|
-
|
5374
|
-
# for ordered_segment in ordered_segments
|
5375
|
-
# target_segment = ordered_segment.segment
|
5376
|
-
# segment_num = ordered_segment.path_segment_num
|
5377
|
-
# (; unit_uuid) = target_segment
|
5378
|
-
# # @show unit_uuid
|
5379
|
-
# # @show keys(unituuid2deckunit)
|
5380
|
-
# target_unit = isnothing(unit_uuid) ? nothing : unituuid2deckunit[unit_uuid]
|
5381
|
-
# # @show target_unit
|
5382
|
-
|
5383
|
-
# if isnothing(target_unit)
|
5384
|
-
# # do nothing (this is a blank segment)
|
5385
|
-
# elseif target_unit.is_wild
|
5386
|
-
# if hasexactunitmatch(unit_uuid)
|
5387
|
-
# popped = pop!(balance_unituuid2deckcardnums[unit_uuid])
|
5388
|
-
# push!(fulfillment, OrderedFullfillment(segment_num, popped))
|
5389
|
-
# end
|
5390
|
-
# else
|
5391
|
-
# # @show 3
|
5392
|
-
# if hasexactunitmatch(unit_uuid)
|
5393
|
-
# # @show 4
|
5394
|
-
# popped = pop!(balance_unituuid2deckcardnums[unit_uuid])
|
5395
|
-
# push!(fulfillment, OrderedFullfillment(segment_num, popped))
|
5396
|
-
# elseif anywildsleft()
|
5397
|
-
# # @show 5
|
5398
|
-
# non_empty_wild_stack = getnonemptywildstack()
|
5399
|
-
# popped = pop!(non_empty_wild_stack)
|
5400
|
-
# push!(fulfillment, OrderedFullfillment(segment_num, popped))
|
5401
|
-
# end
|
5402
|
-
# end
|
5403
|
-
# end
|
5404
|
-
|
5405
|
-
# blank_remaining_segments = filter(
|
5406
|
-
# ordered_segment -> isblank(ordered_segment.segment.unit_uuid),
|
5407
|
-
# ordered_segments,
|
5408
|
-
# )
|
5409
|
-
# # @show blank_remaining_segments
|
5410
|
-
# largest_non_wild_stack = getlargestnonwildstack()
|
5411
|
-
# # @show largest_non_wild_stack
|
5412
|
-
# for blank_remaining_segment in blank_remaining_segments
|
5413
|
-
# if !isnothing(largest_non_wild_stack) && !isempty(largest_non_wild_stack)
|
5414
|
-
# popped = pop!(largest_non_wild_stack)
|
5415
|
-
# push!(fulfillment, OrderedFullfillment(blank_remaining_segment.path_segment_num, popped))
|
5416
|
-
# elseif gettotalwildcount() > 0
|
5417
|
-
# popped = popawildcard!()
|
5418
|
-
# push!(fulfillment, OrderedFullfillment(blank_remaining_segment.path_segment_num, popped))
|
5419
|
-
# end
|
5420
|
-
# end
|
5421
|
-
|
5422
|
-
# # @show fulfillment
|
5423
|
-
# deepq_edges = map(ordered_segments) do ordered_segment
|
5424
|
-
# (; path_segment_num) = ordered_segment
|
5425
|
-
# (; segment) = ordered_segment
|
5426
|
-
# fullfillable_by_me = in(path_segment_num, [x.segment_num for x in fulfillment])
|
5427
|
-
# captured_by_me = in(path_num, s.player_hands[player_idx].paths)
|
5428
|
-
# captured_by_other = !captured_by_me && in(path_num, getclaimedpathidxs(s))
|
5429
|
-
# available_to_me = !(captured_by_me || captured_by_other) && fullfillable_by_me
|
5430
|
-
# status = "Other"
|
5431
|
-
# if captured_by_me
|
5432
|
-
# status = "CapturedByMe"
|
5433
|
-
# elseif captured_by_other
|
5434
|
-
# status = "CapturedByOther"
|
5435
|
-
# elseif available_to_me
|
5436
|
-
# status = "AvailableToMe"
|
5437
|
-
# end
|
5438
|
-
# SegmentStatus(
|
5439
|
-
# path_num,
|
5440
|
-
# path_segment_num,
|
5441
|
-
# captured_by_me,
|
5442
|
-
# captured_by_other,
|
5443
|
-
# available_to_me,
|
5444
|
-
# status,
|
5445
|
-
# segment,
|
5446
|
-
# )
|
5447
|
-
# end
|
5448
|
-
|
5449
|
-
# fulfillable = Base.all([x.available_to_me for x in deepq_edges])
|
5450
|
-
# PathStatus(path_num, fulfillable, deepq_edges, fulfillment)
|
5451
|
-
# end
|
5452
|
-
def getpathstatus(s, player_idx, path_idx):
|
5453
|
-
path_num = path_idx + 1
|
5454
|
-
balance = s.player_hands[player_idx].unit_cards
|
5455
|
-
fig = s.game_config.fig
|
5456
|
-
board_config = fig.board_config
|
5457
|
-
deck_units = board_config.deck_units
|
5458
|
-
board_paths = board_config.board_paths
|
5459
|
-
unituuid2deckunit = {x.unit_uuid: x for x in deck_units}
|
5460
|
-
path = board_paths[path_idx]
|
5461
|
-
ordered_segments = prioritysort(fig, path.path.segments)
|
5462
|
-
fulfillment = []
|
5463
|
-
wild_unit_uuids = getwildunituuids(fig)
|
5464
|
-
non_wild_unit_uuids = getnonwildunituuids(fig)
|
5465
|
-
|
5466
|
-
balance_unituuid2deckcardnums = {}
|
5467
|
-
|
5468
|
-
for deck_card_num in balance:
|
5469
|
-
unit_uuid = getunituuid(fig, deck_card_num)
|
5470
|
-
if unit_uuid not in balance_unituuid2deckcardnums:
|
5471
|
-
balance_unituuid2deckcardnums[unit_uuid] = []
|
5472
|
-
balance_unituuid2deckcardnums[unit_uuid].append(deck_card_num)
|
5473
|
-
|
5474
|
-
def hasexactunitmatch(unit_uuid):
|
5475
|
-
# print("unit_uuid: ", unit_uuid)
|
5476
|
-
# print("balance_unituuid2deckcardnums: ", balance_unituuid2deckcardnums)
|
5477
|
-
print("")
|
5478
|
-
return (
|
5479
|
-
unit_uuid in balance_unituuid2deckcardnums and
|
5480
|
-
len(balance_unituuid2deckcardnums[unit_uuid]) > 0
|
5481
|
-
)
|
5482
|
-
|
5483
|
-
def anywildsleft():
|
5484
|
-
for wild_unit_uuid in wild_unit_uuids:
|
5485
|
-
if wild_unit_uuid in balance_unituuid2deckcardnums:
|
5486
|
-
if balance_unituuid2deckcardnums[wild_unit_uuid]:
|
5487
|
-
return True
|
5488
|
-
return False
|
5489
|
-
|
5490
|
-
def gettotalwildcount():
|
5491
|
-
count = 0
|
5492
|
-
for wild_unit_uuid in wild_unit_uuids:
|
5493
|
-
if wild_unit_uuid in balance_unituuid2deckcardnums:
|
5494
|
-
count += len(balance_unituuid2deckcardnums[wild_unit_uuid])
|
5495
|
-
return count
|
5496
|
-
|
5497
|
-
def popawildcard():
|
5498
|
-
for wild_unit_uuid in wild_unit_uuids:
|
5499
|
-
if wild_unit_uuid in balance_unituuid2deckcardnums:
|
5500
|
-
if balance_unituuid2deckcardnums[wild_unit_uuid]:
|
5501
|
-
return balance_unituuid2deckcardnums[wild_unit_uuid].pop()
|
5502
|
-
return None
|
5503
|
-
|
5504
|
-
def getnonemptywildstack():
|
5505
|
-
for wild_unit_uuid in wild_unit_uuids:
|
5506
|
-
if wild_unit_uuid in balance_unituuid2deckcardnums:
|
5507
|
-
if balance_unituuid2deckcardnums[wild_unit_uuid]:
|
5508
|
-
return balance_unituuid2deckcardnums[wild_unit_uuid]
|
5509
|
-
return None
|
5510
|
-
|
5511
|
-
def getlargestnonwildstack():
|
5512
|
-
largest_non_wild_unit_uuid = None
|
5513
|
-
largest_found = 0
|
5514
|
-
for non_wild_unit_uuid in non_wild_unit_uuids:
|
5515
|
-
if non_wild_unit_uuid in balance_unituuid2deckcardnums:
|
5516
|
-
curr_length = len(balance_unituuid2deckcardnums[non_wild_unit_uuid])
|
5517
|
-
if curr_length > largest_found:
|
5518
|
-
largest_found = curr_length
|
5519
|
-
largest_non_wild_unit_uuid = non_wild_unit_uuid
|
5520
|
-
if largest_non_wild_unit_uuid is not None:
|
5521
|
-
return balance_unituuid2deckcardnums[largest_non_wild_unit_uuid]
|
5522
|
-
return None
|
5523
|
-
|
5524
|
-
for ordered_segment in ordered_segments:
|
5525
|
-
target_segment = ordered_segment.segment
|
5526
|
-
segment_num = ordered_segment.path_segment_num
|
5527
|
-
unit_uuid = target_segment.unit_uuid
|
5528
|
-
target_unit = None if unit_uuid is None else unituuid2deckunit[unit_uuid]
|
5529
|
-
|
5530
|
-
if target_unit is None:
|
5531
|
-
# do nothing (this is a blank segment)
|
5532
|
-
pass
|
5533
|
-
elif target_unit.is_wild:
|
5534
|
-
if hasexactunitmatch(unit_uuid):
|
5535
|
-
popped = balance_unituuid2deckcardnums[unit_uuid].pop()
|
5536
|
-
fulfillment.append(OrderedFullfillment(segment_num=segment_num, unit_card_num=popped))
|
5537
|
-
else:
|
5538
|
-
# print("anywildsleft(): ", anywildsleft())
|
5539
|
-
if hasexactunitmatch(unit_uuid):
|
5540
|
-
popped = balance_unituuid2deckcardnums[unit_uuid].pop()
|
5541
|
-
fulfillment.append(OrderedFullfillment(segment_num=segment_num, unit_card_num=popped))
|
5542
|
-
elif anywildsleft():
|
5543
|
-
non_empty_wild_stack = getnonemptywildstack()
|
5544
|
-
popped = non_empty_wild_stack.pop()
|
5545
|
-
fulfillment.append(OrderedFullfillment(segment_num=segment_num, unit_card_num=popped))
|
5546
|
-
# @show 5
|
5547
|
-
|
5548
|
-
blank_remaining_segments = list(filter(
|
5549
|
-
lambda ordered_segment: ordered_segment.segment.unit_uuid is None,
|
5550
|
-
ordered_segments,
|
5551
|
-
))
|
5552
|
-
|
5553
|
-
largest_non_wild_stack = getlargestnonwildstack()
|
5554
|
-
|
5555
|
-
for blank_remaining_segment in blank_remaining_segments:
|
5556
|
-
if largest_non_wild_stack is not None and largest_non_wild_stack:
|
5557
|
-
popped = largest_non_wild_stack.pop()
|
5558
|
-
fulfillment.append(OrderedFullfillment(segment_num=blank_remaining_segment.path_segment_num, unit_card_num=popped))
|
5559
|
-
elif gettotalwildcount() > 0:
|
5560
|
-
popped = popawildcard()
|
5561
|
-
fulfillment.append(OrderedFullfillment(segment_num=blank_remaining_segment.path_segment_num, unit_card_num=popped))
|
5562
|
-
|
5563
|
-
# Implementing the following Julia code:
|
5564
|
-
# deepq_edges = map(ordered_segments) do ordered_segment
|
5565
|
-
# (; path_segment_num) = ordered_segment
|
5566
|
-
# (; segment) = ordered_segment
|
5567
|
-
# fullfillable_by_me = in(path_segment_num, [x.segment_num for x in fulfillment])
|
5568
|
-
# captured_by_me = in(path_num, s.player_hands[player_idx].paths)
|
5569
|
-
# captured_by_other = !captured_by_me && in(path_num, getclaimedpathidxs(s))
|
5570
|
-
# available_to_me = !(captured_by_me || captured_by_other) && fullfillable_by_me
|
5571
|
-
# status = "Other"
|
5572
|
-
# if captured_by_me
|
5573
|
-
# status = "CapturedByMe"
|
5574
|
-
# elseif captured_by_other
|
5575
|
-
# status = "CapturedByOther"
|
5576
|
-
# elseif available_to_me
|
5577
|
-
# status = "AvailableToMe"
|
5578
|
-
# end
|
5579
|
-
# SegmentStatus(
|
5580
|
-
# path_num,
|
5581
|
-
# path_segment_num,
|
5582
|
-
# captured_by_me,
|
5583
|
-
# captured_by_other,
|
5584
|
-
# available_to_me,
|
5585
|
-
# status,
|
5586
|
-
# segment,
|
5587
|
-
# )
|
5588
|
-
# end
|
5589
|
-
# fulfillable = Base.all([x.available_to_me for x in deepq_edges])
|
5590
|
-
# PathStatus(path_num, fulfillable, deepq_edges, fulfillment)
|
5591
|
-
deepq_edges = []
|
5592
|
-
for ordered_segment in ordered_segments:
|
5593
|
-
path_segment_num = ordered_segment.path_segment_num
|
5594
|
-
segment = ordered_segment.segment
|
5595
|
-
fullfillable_by_me = path_segment_num in [x.segment_num for x in fulfillment]
|
5596
|
-
captured_by_me = path_idx in s.player_hands[player_idx].paths
|
5597
|
-
captured_by_other = not captured_by_me and path_idx in getclaimedpathidxs(s)
|
5598
|
-
available_to_me = not (captured_by_me or captured_by_other) and fullfillable_by_me
|
5599
|
-
status = "Other"
|
5600
|
-
if captured_by_me:
|
5601
|
-
status = "CapturedByMe"
|
5602
|
-
elif captured_by_other:
|
5603
|
-
status = "CapturedByOther"
|
5604
|
-
elif available_to_me:
|
5605
|
-
status = "AvailableToMe"
|
5606
|
-
|
5607
|
-
deepq_edges.append(
|
5608
|
-
SegmentStatus(
|
5609
|
-
path_idx=path_idx,
|
5610
|
-
path_num=path_num,
|
5611
|
-
path_segment_num=path_segment_num,
|
5612
|
-
captured_by_me=captured_by_me,
|
5613
|
-
captured_by_other=captured_by_other,
|
5614
|
-
available_to_me=available_to_me,
|
5615
|
-
status=status,
|
5616
|
-
segment=segment
|
5617
|
-
)
|
5618
|
-
)
|
5619
|
-
|
5620
|
-
fulfillable = all([x.available_to_me for x in deepq_edges])
|
5621
|
-
return PathStatus(
|
5622
|
-
idx=path_idx,
|
5623
|
-
num=path_num,
|
5624
|
-
fulfillable=fulfillable,
|
5625
|
-
segment_statuses=deepq_edges,
|
5626
|
-
sample_fulfillment=fulfillment
|
5627
|
-
)
|
5628
|
-
|
5629
|
-
|
5630
|
-
# Implementing the following Julia function:
|
5631
|
-
# function getavailablepoints(s::State, player_num::Int)
|
5632
|
-
# point_statuses = map(getpotentialpointuuids(s, player_num)) do point_uuid
|
5633
|
-
# getpointstatus(s, player_num, point_uuid)
|
5634
|
-
# end
|
5635
|
-
# sort(filter(x -> x.fulfillable, point_statuses); by=x -> x.uuid)
|
5636
|
-
# end
|
5637
|
-
def getavailablepoints(s, player_num):
|
5638
|
-
point_statuses = [
|
5639
|
-
getpointstatus(s, player_num, point_uuid)
|
5640
|
-
for point_uuid in getpotentialpointuuids(s, player_num)
|
5641
|
-
]
|
5642
|
-
return sorted(
|
5643
|
-
filter(lambda x: x['fulfillable'], point_statuses),
|
5644
|
-
key=lambda x: x['uuid']
|
5645
|
-
)
|
5646
|
-
|
5647
|
-
# Implementing the following Julia function:
|
5648
|
-
# function getpointstatus(s::State, player_idx::Int, point_uuid::UUID)
|
5649
|
-
# balance = s.player_hands[player_idx].unit_cards
|
5650
|
-
# fulfillment = OrderedPointFullfillment[]
|
5651
|
-
# if !isempty(balance)
|
5652
|
-
# push!(fulfillment, OrderedPointFullfillment(balance[1]))
|
5653
|
-
# end
|
5654
|
-
# PointStatus(point_uuid, true, fulfillment)
|
5655
|
-
# end
|
5656
|
-
def getpointstatus(s, player_idx, point_uuid):
|
5657
|
-
balance = s.player_hands[player_idx].unit_cards
|
5658
|
-
fulfillment = []
|
5659
|
-
if balance:
|
5660
|
-
fulfillment.append({'unit_card_num': balance[0]})
|
5661
|
-
return {
|
5662
|
-
'uuid': point_uuid,
|
5663
|
-
'fulfillable': True,
|
5664
|
-
'sample_fulfillment': fulfillment
|
5665
|
-
}
|
5666
|
-
|
5667
|
-
# Implementing the following Julia function:
|
5668
|
-
# function getpotentialpointuuids(s::State, player_num::Int)
|
5669
|
-
# (; num_point_pieces) = s.player_hands[player_num]
|
5670
|
-
# setdiff(
|
5671
|
-
# Set(getnodeuuids(s.fig, num_point_pieces)),
|
5672
|
-
# Set(getunavailablepoints(s)),
|
5673
|
-
# ) |> collect
|
5674
|
-
# end
|
5675
|
-
def getpotentialpointuuids(s, player_num):
|
5676
|
-
num_point_pieces = s.player_hands[player_num].num_point_pieces
|
5677
|
-
return list(
|
5678
|
-
set(getnodeuuids(s.game_config.fig, num_point_pieces)) -
|
5679
|
-
set(getunavailablepoints(s))
|
5680
|
-
)
|
5681
4770
|
|
5682
4771
|
# Implementing the following Julia function:
|
5683
4772
|
# function getnodeuuids(f::Fig, remaining_pieces::Int)
|
@@ -5714,33 +4803,6 @@ def getunavailablepoints(s):
|
|
5714
4803
|
return unavailable_points
|
5715
4804
|
|
5716
4805
|
|
5717
|
-
# Implementing the following Julia function:
|
5718
|
-
# function calcfinalscores(s::State)
|
5719
|
-
# if !s.terminal
|
5720
|
-
# return s
|
5721
|
-
# end
|
5722
|
-
# @reset s.player_hands = calcfinalscore.(s, s.player_hands)
|
5723
|
-
# s
|
5724
|
-
# end
|
5725
|
-
@dispatch(State)
|
5726
|
-
def calcfinalscores(s):
|
5727
|
-
if not s.terminal:
|
5728
|
-
return s
|
5729
|
-
return s.set(player_hands=pvector([calcfinalscore(s, h) for h in s.player_hands]))
|
5730
|
-
|
5731
|
-
|
5732
|
-
# Implementing the following Julia function:
|
5733
|
-
# function calcfinalscore(s::State, hand::PlayerInfo)
|
5734
|
-
# (; total, breakdown) = getprivatescore(s, hand)
|
5735
|
-
# @reset hand.final_score = PlayerScore(total, breakdown)
|
5736
|
-
# hand
|
5737
|
-
# end
|
5738
|
-
@dispatch(State, PlayerInfo)
|
5739
|
-
def calcfinalscore(s, hand):
|
5740
|
-
total, breakdown = getprivatescore(s, hand)
|
5741
|
-
return hand.set(final_score=PlayerScore(total=total, breakdown=breakdown))
|
5742
|
-
|
5743
|
-
|
5744
4806
|
# Implementing the following Julia function:
|
5745
4807
|
# function calcwinners(s::State)
|
5746
4808
|
# if !s.terminal
|
@@ -5764,158 +4826,15 @@ def calcwinners(s):
|
|
5764
4826
|
|
5765
4827
|
|
5766
4828
|
def printplayer(s, player_idx):
|
5767
|
-
|
5768
|
-
legal_actions = getlegalactionspecs(s, player_idx)
|
5769
|
-
print(f"~~~~~~~~~~~~ P{player_idx} ~~~~~~~~~~~~")
|
5770
|
-
print(f"private score: {getprivatescore(s, hand)}")
|
5771
|
-
print(f"public score: {getpublicscore(s, player_idx)}")
|
5772
|
-
print(f"completed clusters: {list(str(c) for c in hand.completed_clusters)}")
|
5773
|
-
print(f"units: {list(hand.unit_cards)}")
|
5774
|
-
if getsettingvalue(s, "route_scoring"):
|
5775
|
-
print(f"routes: {list(hand.route_cards)} choices:{list(hand.new_route_cards)}")
|
5776
|
-
print(f"captured points: {list(str(p) for p in hand.points)}")
|
5777
|
-
print(f"legal actions: {list(a.action_name for a in legal_actions)}")
|
4829
|
+
pass
|
5778
4830
|
|
5779
4831
|
|
5780
4832
|
def printstate(s):
|
5781
|
-
|
5782
|
-
print(f"Last to play: {s.last_to_play}")
|
5783
|
-
print(f"Winners: {list(s.winners)}")
|
5784
|
-
print(f"Route Deck: {list(s.route_cards)}")
|
5785
|
-
print(f"Route Disc: {list(s.route_discards)}")
|
5786
|
-
print(f"Unit Deck: ...{list(s.unit_cards[60:])}")
|
5787
|
-
print(f"Unit Disc: {list(s.unit_discards)}")
|
5788
|
-
print(f"FaceUp: {list(s.faceup_spots)}")
|
5789
|
-
print(f"ToPlay: {gettoplay(s)}")
|
5790
|
-
print(f"Terminal: {s.terminal}")
|
5791
|
-
|
5792
|
-
for i in range(s.game_config.num_players):
|
5793
|
-
printplayer(s, i)
|
5794
|
-
print(f"****************************************\n")
|
4833
|
+
pass
|
5795
4834
|
|
5796
4835
|
|
5797
4836
|
def printaction(a, i):
|
5798
|
-
|
5799
|
-
print(f"{a}")
|
5800
|
-
print(f"****************************************\n\n\n")
|
5801
|
-
|
5802
|
-
|
5803
|
-
# Implementing the following Julia function:
|
5804
|
-
# function getprivatescore(s::State, hand::PlayerInfo; bonus=true)
|
5805
|
-
# player_idx = hand.player_idx
|
5806
|
-
# breakdown = []
|
5807
|
-
|
5808
|
-
# # Path scores
|
5809
|
-
# if getsettingvalue(s, :path_scoring)
|
5810
|
-
# (; path_scores) = s.fig
|
5811
|
-
# for len in getplayerpathlens(s, player_idx)
|
5812
|
-
# push!(
|
5813
|
-
# breakdown,
|
5814
|
-
# ScoreItem(
|
5815
|
-
# code_idx=getscorecodeidx(s.fig, :PATH),
|
5816
|
-
# amount=path_scores[len],
|
5817
|
-
# )
|
5818
|
-
# )
|
5819
|
-
# end
|
5820
|
-
# end
|
5821
|
-
|
5822
|
-
# # Bonus: most clusters
|
5823
|
-
# if getsettingvalue(s, :most_clusters_bonus)
|
5824
|
-
# bonus_most_clusters_score = getsettingvalue(s.fig, :bonus_most_clusters_score)
|
5825
|
-
# if in(player_idx, s.most_clusters_player_idxs)
|
5826
|
-
# push!(
|
5827
|
-
# breakdown,
|
5828
|
-
# ScoreItem(
|
5829
|
-
# code_idx=getscorecodeidx(s.fig, :MOST_CLUSTERS),
|
5830
|
-
# amount=bonus_most_clusters_score,
|
5831
|
-
# )
|
5832
|
-
# )
|
5833
|
-
# end
|
5834
|
-
# end
|
5835
|
-
#
|
5836
|
-
# # Completed routes
|
5837
|
-
# if getsettingvalue(s, :route_scoring)
|
5838
|
-
# hand = s.player_hands[player_idx]
|
5839
|
-
# (; board_config) = s.fig
|
5840
|
-
# (; routes) = board_config
|
5841
|
-
# for route_idx in hand.route_cards
|
5842
|
-
# route_score = routes[route_idx].score
|
5843
|
-
# amount = in(route_idx, hand.completed_routes) ? route_score : -1*route_score
|
5844
|
-
# push!(
|
5845
|
-
# breakdown,
|
5846
|
-
# ScoreItem(
|
5847
|
-
# code_idx=getscorecodeidx(s.fig, :ROUTE),
|
5848
|
-
# amount=amount
|
5849
|
-
# )
|
5850
|
-
# )
|
5851
|
-
# end
|
5852
|
-
# end
|
5853
|
-
|
5854
|
-
# # Completed clusters
|
5855
|
-
# if getsettingvalue(s, :cluster_scoring)
|
5856
|
-
# (; clusters) = s.fig.board_config
|
5857
|
-
# uuid2cluster = Dict((x.uuid, x) for x in clusters)
|
5858
|
-
# (; completed_clusters) = s.player_hands[player_idx]
|
5859
|
-
# cluster_scores = map(completed_clusters) do cluster_uuid
|
5860
|
-
# uuid2cluster[cluster_uuid].score
|
5861
|
-
# end
|
5862
|
-
# if !isempty(cluster_scores)
|
5863
|
-
# push!(breakdown,
|
5864
|
-
# ScoreItem(
|
5865
|
-
# code_idx=getscorecodeidx(s.fig, :CLUSTER),
|
5866
|
-
# amount=sum(cluster_scores)
|
5867
|
-
# )
|
5868
|
-
# )
|
5869
|
-
# end
|
5870
|
-
# end
|
5871
|
-
|
5872
|
-
# amounts = [item.amount for item in breakdown]
|
5873
|
-
# total = sum(amounts; init=0)
|
5874
|
-
# (
|
5875
|
-
# total=total,
|
5876
|
-
# breakdown=breakdown,
|
5877
|
-
# )
|
5878
|
-
# end
|
5879
|
-
@dispatch(State, PlayerInfo)
|
5880
|
-
def getprivatescore(s, hand):
|
5881
|
-
player_idx = hand.player_idx
|
5882
|
-
breakdown = []
|
5883
|
-
|
5884
|
-
# Path scores
|
5885
|
-
if getsettingvalue(s, 'path_scoring'):
|
5886
|
-
path_scores = s.game_config.fig.path_scores
|
5887
|
-
for len in getplayerpathlens(s, player_idx):
|
5888
|
-
breakdown.append(ScoreItem(
|
5889
|
-
code_idx=getscorecodeidx(s.game_config.fig, 'PATH'),
|
5890
|
-
amount=path_scores[len],
|
5891
|
-
))
|
5892
|
-
|
5893
|
-
# Completed routes
|
5894
|
-
if False and getsettingvalue(s, 'route_scoring'):
|
5895
|
-
routes = s.game_config.fig.board_config.routes
|
5896
|
-
for route_idx in hand.route_cards:
|
5897
|
-
route_score = routes[route_idx].score
|
5898
|
-
amount = route_score if route_idx in hand.completed_routes else -1 * route_score
|
5899
|
-
breakdown.append(ScoreItem(
|
5900
|
-
code_idx=getscorecodeidx(s.game_config.fig, 'ROUTE'),
|
5901
|
-
amount=amount
|
5902
|
-
))
|
5903
|
-
|
5904
|
-
# Completed clusters
|
5905
|
-
if getsettingvalue(s, 'cluster_scoring'):
|
5906
|
-
clusters = s.game_config.fig.board_config.clusters
|
5907
|
-
uuid2cluster = {x.uuid: x for x in clusters}
|
5908
|
-
completed_clusters = hand.completed_clusters
|
5909
|
-
cluster_scores = [uuid2cluster[cluster_uuid].score for cluster_uuid in completed_clusters]
|
5910
|
-
if cluster_scores:
|
5911
|
-
breakdown.append(ScoreItem(
|
5912
|
-
code_idx=getscorecodeidx(s.game_config.fig, 'CLUSTER'),
|
5913
|
-
amount=sum(cluster_scores)
|
5914
|
-
))
|
5915
|
-
|
5916
|
-
amounts = [item.amount for item in breakdown]
|
5917
|
-
total = sum(amounts)
|
5918
|
-
return total, breakdown
|
4837
|
+
pass
|
5919
4838
|
|
5920
4839
|
|
5921
4840
|
# Implementing the following Julia function:
|
@@ -5954,46 +4873,6 @@ def getscorecodes(f):
|
|
5954
4873
|
return score_codes
|
5955
4874
|
|
5956
4875
|
|
5957
|
-
# Implementing the following Julia function:
|
5958
|
-
# function assertunitcardsaccountedfor(s::State)
|
5959
|
-
# total_num_unit_cards = gettotaldeckcards(s.fig)
|
5960
|
-
# total_found = getunitcardstotalfound(s)
|
5961
|
-
# @assert total_num_unit_cards == total_found "Unit cards not accounted for. $(total_num_unit_cards) != $(total_found)"
|
5962
|
-
# end
|
5963
|
-
def assertunitcardsaccountedfor(s):
|
5964
|
-
total_num_unit_cards = gettotaldeckcards(s.game_config.fig)
|
5965
|
-
total_found = getunitcardstotalfound(s)
|
5966
|
-
assert total_num_unit_cards == total_found, f"Unit cards not accounted for. {total_num_unit_cards} != {total_found}"
|
5967
|
-
|
5968
|
-
|
5969
|
-
# Implementing the following Julia function:
|
5970
|
-
# function getunitcardstotalfound(s::State)
|
5971
|
-
# num_player_unit_cards = sum(gettotalnumunitcards.(s.player_hands))
|
5972
|
-
# total_found = sum([
|
5973
|
-
# num_player_unit_cards,
|
5974
|
-
# length(s.unit_discards),
|
5975
|
-
# length(s.unit_cards),
|
5976
|
-
# length(getvalidspotnums(s)),
|
5977
|
-
# ])
|
5978
|
-
# total_found
|
5979
|
-
# end
|
5980
|
-
def getunitcardstotalfound(s):
|
5981
|
-
num_player_unit_cards = sum(gettotalnumunitcards(p) for p in s.player_hands)
|
5982
|
-
total_found = sum([
|
5983
|
-
num_player_unit_cards,
|
5984
|
-
len(s.unit_discards),
|
5985
|
-
len(s.unit_cards),
|
5986
|
-
len(getvalidspotnums(s)),
|
5987
|
-
])
|
5988
|
-
return total_found
|
5989
|
-
|
5990
|
-
|
5991
|
-
# Implementing the following Julia function:
|
5992
|
-
# gettotalnumunitcards(player_hand::PlayerInfo) = length(player_hand.unit_cards)
|
5993
|
-
def gettotalnumunitcards(player_hand):
|
5994
|
-
return len(player_hand.unit_cards)
|
5995
|
-
|
5996
|
-
|
5997
4876
|
# Implementing the following Julia function:
|
5998
4877
|
# function getvalidspotnums(s::State)
|
5999
4878
|
# filter(n -> !isnothing(s.faceup_spots[n]), 1:length(s.faceup_spots))
|
@@ -6002,44 +4881,6 @@ def getvalidspotnums(s):
|
|
6002
4881
|
return [n for n in range(1, len(s.faceup_spots) + 1) if s.faceup_spots[n-1] is not None]
|
6003
4882
|
|
6004
4883
|
|
6005
|
-
# Implementing the following Julia function:
|
6006
|
-
# function assertroutecardsaccountedfor(s::State)
|
6007
|
-
# total_num_route_cards = getnumroutecards(s.fig)
|
6008
|
-
# num_player_route_cards = sum(gettotalnumroutecards.(s.player_hands))
|
6009
|
-
# total_found = sum([
|
6010
|
-
# num_player_route_cards,
|
6011
|
-
# length(s.route_discards),
|
6012
|
-
# length(s.route_cards),
|
6013
|
-
# ])
|
6014
|
-
# @assert total_num_route_cards == total_found "Route cards not accounted for. $(total_num_route_cards) != $(total_found)"
|
6015
|
-
# end
|
6016
|
-
def assertroutecardsaccountedfor(s):
|
6017
|
-
total_num_route_cards = getnumroutecards(s.game_config.fig)
|
6018
|
-
num_player_route_cards = sum(gettotalnumroutecards(p) for p in s.player_hands)
|
6019
|
-
total_found = sum([
|
6020
|
-
num_player_route_cards,
|
6021
|
-
len(s.route_discards),
|
6022
|
-
len(s.route_cards),
|
6023
|
-
])
|
6024
|
-
assert total_num_route_cards == total_found, f"Route cards not accounted for. {total_num_route_cards} != {total_found}"
|
6025
|
-
|
6026
|
-
|
6027
|
-
# Implementing the following Julia function:
|
6028
|
-
# gettotalnumroutecards(player_hand::PlayerInfo) = length(player_hand.route_cards) + length(player_hand.new_route_cards)
|
6029
|
-
def gettotalnumroutecards(player_hand):
|
6030
|
-
return len(player_hand.route_cards) + len(player_hand.new_route_cards)
|
6031
|
-
|
6032
|
-
|
6033
|
-
# Implementing the following Julia function:
|
6034
|
-
# function assertallcardsaccountedfor(s::State)
|
6035
|
-
# assertroutecardsaccountedfor(s)
|
6036
|
-
# assertunitcardsaccountedfor(s)
|
6037
|
-
# end
|
6038
|
-
def assertallcardsaccountedfor(s):
|
6039
|
-
assertroutecardsaccountedfor(s)
|
6040
|
-
assertunitcardsaccountedfor(s)
|
6041
|
-
|
6042
|
-
|
6043
4884
|
# Implementing the following Julia function:
|
6044
4885
|
# function getlegalactions(s::State)
|
6045
4886
|
# getlegalactions(s, gettoplay(s))
|
@@ -6126,7 +4967,6 @@ def getprivatestate(s, player_idx):
|
|
6126
4967
|
player=s.players[player_idx],
|
6127
4968
|
legal_actions_2 = get_legal_actions(s, player_idx),
|
6128
4969
|
legal_actions=legal_actions,
|
6129
|
-
hand=s.player_hands[player_idx],
|
6130
4970
|
goal_completions=goal_completions,
|
6131
4971
|
)
|
6132
4972
|
|
@@ -6274,132 +5114,92 @@ def diff(A, dims=None):
|
|
6274
5114
|
return [[A[i][j] - A[i][j - 1] for j in range(1, len(A[0]))] for i in range(len(A))]
|
6275
5115
|
else:
|
6276
5116
|
raise ValueError("dims must be either 1 or 2")
|
6277
|
-
|
6278
5117
|
|
6279
|
-
@dispatch(StaticBoardConfig, PlayerState)
|
6280
|
-
def get_imagined_state(static_board_config, player_state):
|
6281
|
-
board_config = static_board_config.board_config
|
6282
|
-
public_state = player_state.public
|
6283
|
-
private_state = player_state.private
|
6284
|
-
my_hand = private_state.hand
|
6285
|
-
|
6286
|
-
fig = initfig("af472d67-05ec-4b5d-9eb7-6b0cea9eec5a", board_config)
|
6287
|
-
seed = 4012489341 # TODO: this should be random (or if non-stochastic, loaded from the net.seed)
|
6288
|
-
rng = getrng(seed)
|
6289
|
-
|
6290
|
-
# TODO: this needs to come from x_json['game_config']
|
6291
|
-
game_config = GameConfig(
|
6292
|
-
uuid = str(generate_uuid_with_rng(rng)),
|
6293
|
-
started_at = "2025-01-01 00:00:00",
|
6294
|
-
num_players = 2,
|
6295
|
-
fig = fig,
|
6296
|
-
seed = seed
|
6297
|
-
)
|
6298
5118
|
|
6299
|
-
|
6300
|
-
|
5119
|
+
def get_default_toplay(s):
|
5120
|
+
if s.legal_actions_2:
|
5121
|
+
return s.legal_actions_2[0].player_idx
|
5122
|
+
return None
|
6301
5123
|
|
6302
|
-
def remove_card_idx(to_mutate, card_idx):
|
6303
|
-
if card_idx in to_mutate:
|
6304
|
-
to_mutate.remove(card_idx)
|
6305
5124
|
|
6306
|
-
|
6307
|
-
|
6308
|
-
|
5125
|
+
def get_intuited_best_actions(ps):
|
5126
|
+
if not ps.legal_actions_2:
|
5127
|
+
return None
|
5128
|
+
return ps.legal_actions_2[:8]
|
6309
5129
|
|
6310
|
-
|
6311
|
-
# imagined_route_card_idxs = rng.sample(possible_route_card_idxs, public_state.num_route_cards)
|
6312
|
-
remove_card_idxs(possible_route_card_idxs, imagined_route_card_idxs)
|
6313
|
-
# imagined_route_discard_idxs = rng.sample(possible_route_card_idxs, public_state.num_route_discards)
|
6314
|
-
remove_card_idxs(possible_route_card_idxs, imagined_route_discard_idxs)
|
6315
5130
|
|
6316
|
-
|
6317
|
-
|
5131
|
+
def get_spread(q_values, p_idx):
|
5132
|
+
my_q = q_values[p_idx]
|
5133
|
+
other_qs = [q for i, q in enumerate(q_values) if i != p_idx]
|
5134
|
+
spread = my_q - max(other_qs)
|
5135
|
+
return spread
|
6318
5136
|
|
6319
|
-
for unit_card in public_state.unit_discards:
|
6320
|
-
remove_card_idx(possible_unit_card_idxs, unit_card-1)
|
6321
5137
|
|
6322
|
-
|
6323
|
-
|
5138
|
+
def getvproxy0(ps):
|
5139
|
+
return 0
|
6324
5140
|
|
6325
|
-
# imagined_unit_card_idxs = rng.sample(possible_unit_card_idxs, public_state.num_unit_cards)
|
6326
|
-
# imagined_unit_cards = [x+1 for x in imagined_unit_card_idxs]
|
6327
|
-
# remove_card_idxs(possible_unit_card_idxs, imagined_unit_card_idxs)
|
6328
5141
|
|
5142
|
+
def imagine_dynamics(ps, a):
|
5143
|
+
return dynamics(imagine_state(ps), a)
|
6329
5144
|
|
6330
|
-
imagined_player_hands = []
|
6331
5145
|
|
6332
|
-
|
6333
|
-
|
6334
|
-
|
6335
|
-
|
6336
|
-
|
6337
|
-
|
6338
|
-
remove_card_idxs(possible_unit_card_idxs, imagined_player_unit_card_idxs)
|
6339
|
-
# imagined_player_route_card_idxs = rng.sample(possible_route_card_idxs, public_player_info.num_route_cards)
|
6340
|
-
remove_card_idxs(possible_route_card_idxs, imagined_player_route_card_idxs)
|
6341
|
-
imagined_player_new_route_card_idxs = rng.sample(possible_route_card_idxs, public_player_info.num_new_route_cards)
|
6342
|
-
remove_card_idxs(possible_route_card_idxs, imagined_player_new_route_card_idxs)
|
6343
|
-
imagined_player_route_cards = [x+1 for x in imagined_player_route_card_idxs]
|
6344
|
-
imagined_player_new_route_cards = [x+1 for x in imagined_player_new_route_card_idxs]
|
6345
|
-
imagined_player_hands.append(
|
6346
|
-
PlayerInfo(
|
6347
|
-
fig = fig,
|
6348
|
-
player_idx = player_idx,
|
6349
|
-
new_route_cards = pvector(imagined_player_new_route_cards), # Guess at this.
|
6350
|
-
route_cards = pvector(imagined_player_route_cards), # Guess at this.
|
6351
|
-
unit_cards = pvector(imagined_player_unit_cards), # Guess at this.
|
6352
|
-
completed_routes = [], # Guess at this.
|
6353
|
-
completed_clusters = public_player_info.completed_clusters,
|
6354
|
-
paths = public_player_info.paths,
|
6355
|
-
points = public_player_info.points,
|
6356
|
-
tokens = public_player_info.tokens,
|
6357
|
-
num_pieces = public_player_info.num_pieces,
|
6358
|
-
num_point_pieces = public_player_info.num_point_pieces,
|
6359
|
-
longest_trail = public_player_info.longest_trail,
|
6360
|
-
longest_trail_len = public_player_info.longest_trail_len,
|
6361
|
-
final_score = public_player_info.final_score,
|
6362
|
-
)
|
6363
|
-
)
|
5146
|
+
def dynamics(s, a):
|
5147
|
+
scores = get_public_player_scores(s)
|
5148
|
+
next_s = getnextstate2(s, a)
|
5149
|
+
next_scores = get_public_player_scores(next_s)
|
5150
|
+
rewards = [next_scores[i] - scores[i] for i in range(len(scores))]
|
5151
|
+
return next_s, rewards
|
6364
5152
|
|
6365
5153
|
|
6366
|
-
|
6367
|
-
|
6368
|
-
|
6369
|
-
|
6370
|
-
|
6371
|
-
|
6372
|
-
|
6373
|
-
|
6374
|
-
|
6375
|
-
|
6376
|
-
|
6377
|
-
|
6378
|
-
|
6379
|
-
|
6380
|
-
|
6381
|
-
|
6382
|
-
|
6383
|
-
|
6384
|
-
|
6385
|
-
|
6386
|
-
|
6387
|
-
|
6388
|
-
|
6389
|
-
|
6390
|
-
|
6391
|
-
|
6392
|
-
|
6393
|
-
|
6394
|
-
|
6395
|
-
|
6396
|
-
|
6397
|
-
|
6398
|
-
|
6399
|
-
|
6400
|
-
|
6401
|
-
|
6402
|
-
|
5154
|
+
def alpha0(ps):
|
5155
|
+
td = 3
|
5156
|
+
legal_actions = ps.legal_actions_2
|
5157
|
+
if not legal_actions:
|
5158
|
+
return None
|
5159
|
+
intuited = get_intuited_best_actions(ps)
|
5160
|
+
q_proxies = [getqproxy0(ps, a, td) for a in intuited]
|
5161
|
+
max_spread_idx = get_max_spread_idx(q_proxies, ps.player.player_idx)
|
5162
|
+
return intuited[max_spread_idx]
|
5163
|
+
|
5164
|
+
|
5165
|
+
def get_max_spread_idx(q_proxies, p_idx):
|
5166
|
+
spreads = [get_spread(q_proxy, p_idx) for q_proxy in q_proxies]
|
5167
|
+
max_spread_idx = np.argmax(spreads)
|
5168
|
+
return max_spread_idx
|
5169
|
+
|
5170
|
+
|
5171
|
+
def getqproxy0(ps, a, td):
|
5172
|
+
|
5173
|
+
def qproxybase():
|
5174
|
+
next_s, rewards = imagine_dynamics(ps, a)
|
5175
|
+
if next_s.terminal:
|
5176
|
+
return rewards
|
5177
|
+
v_proxies = [
|
5178
|
+
getvproxy0(getprivatestate(next_s, i))
|
5179
|
+
for i in range(next_s.game_config.num_players)
|
5180
|
+
]
|
5181
|
+
q_proxies = [
|
5182
|
+
r + v_proxies[i]
|
5183
|
+
for i, r in enumerate(rewards)
|
5184
|
+
]
|
5185
|
+
return q_proxies
|
5186
|
+
|
5187
|
+
def qproxyrecurse():
|
5188
|
+
next_s, rewards = imagine_dynamics(ps, a)
|
5189
|
+
if next_s.terminal:
|
5190
|
+
return rewards
|
5191
|
+
next_p_idx = get_default_toplay(next_s)
|
5192
|
+
next_ps = getprivatestate(next_s, next_p_idx)
|
5193
|
+
next_p_idx = next_ps.player.player_idx
|
5194
|
+
next_intuited = get_intuited_best_actions(next_ps)
|
5195
|
+
competing_next_q_values = [getqproxy0(next_ps, a, td-1) for a in next_intuited]
|
5196
|
+
max_next_spread_idx = get_max_spread_idx(competing_next_q_values, next_p_idx)
|
5197
|
+
next_q_values = competing_next_q_values[max_next_spread_idx]
|
5198
|
+
q_values = [r + next_q_values[i] for i, r in enumerate(rewards)]
|
5199
|
+
return q_values
|
5200
|
+
|
5201
|
+
return qproxyrecurse() if td > 0 else qproxybase()
|
5202
|
+
|
6403
5203
|
|
6404
5204
|
INIT_HOOK_1 = """def handler(game):
|
6405
5205
|
return shuffle_all_decks(game)
|