graph-games-proto 0.3.1865__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 -1629
- {graph_games_proto-0.3.1865.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.1865.dist-info/RECORD +0 -9
- {graph_games_proto-0.3.1865.dist-info → graph_games_proto-0.3.1877.dist-info}/WHEEL +0 -0
- {graph_games_proto-0.3.1865.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,207 +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
|
-
# num_route_cards::Int
|
1013
|
-
# num_route_discards::Int
|
1014
|
-
# num_unit_cards::Int
|
1015
|
-
# num_unit_discards::Int
|
1016
|
-
# faceup_spots::Vector{Union{Nothing,Int}}
|
1017
|
-
# player_hands::Vector{PublicPlayerInfo}
|
1018
|
-
# captured_segments::Vector{CapturedSegment}
|
1019
|
-
# captured_points::Vector{CapturedPoint}
|
1020
|
-
# last_to_play::Union{Nothing,Int}
|
1021
|
-
# terminal::Bool
|
1022
|
-
# winners::Vector{Int}
|
1023
|
-
# market_refills::Vector{MarketRefill}
|
1024
|
-
|
1025
|
-
|
1026
|
-
class AltAction(PClass):
|
1027
|
-
player_idx = field(type=int)
|
1028
|
-
action_name = field(type=str)
|
1029
|
-
path_idx = field(type=(int, type(None)), initial=None)
|
1030
|
-
return_route_cards = field(type=list, initial=[]) # List[int]
|
1031
|
-
draw_faceup_unit_card_num = field(type=(int, type(None)), initial=None)
|
1032
|
-
draw_faceup_spot_num = field(type=(int, type(None)), initial=None)
|
1033
|
-
point_uuid = field(type=(str, type(None)), initial=None)
|
1034
|
-
unit_combo = field(type=(str, type(None)), initial=None) # TODO: should be list of int
|
1035
|
-
def __todict__(self):
|
1036
|
-
return {
|
1037
|
-
"player_idx": self.player_idx,
|
1038
|
-
"action_name": self.action_name,
|
1039
|
-
"path_idx": self.path_idx,
|
1040
|
-
"return_route_cards": self.return_route_cards,
|
1041
|
-
"draw_faceup_unit_card_num": self.draw_faceup_unit_card_num,
|
1042
|
-
"draw_faceup_spot_num": self.draw_faceup_spot_num,
|
1043
|
-
"point_uuid": self.point_uuid,
|
1044
|
-
"unit_combo": self.unit_combo
|
1045
|
-
}
|
1046
|
-
@staticmethod
|
1047
|
-
def __fromdict__(json_dict):
|
1048
|
-
return AltAction(
|
1049
|
-
player_idx=json_dict["player_idx"],
|
1050
|
-
action_name=json_dict["action_name"],
|
1051
|
-
path_idx=json_dict.get("path_idx", None), # Handle missing key gracefully
|
1052
|
-
return_route_cards=json_dict.get("return_route_cards", []), # Handle missing key gracefully
|
1053
|
-
draw_faceup_unit_card_num=json_dict.get("draw_faceup_unit_card_num", None), # Handle missing key gracefully
|
1054
|
-
draw_faceup_spot_num=json_dict.get("draw_faceup_spot_num", None), # Handle missing key gracefully
|
1055
|
-
point_uuid=json_dict.get("point_uuid", None), # Handle missing key gracefully
|
1056
|
-
unit_combo=json_dict.get("unit_combo", None) # Handle missing key gracefully
|
1057
|
-
)
|
1058
|
-
|
1059
|
-
|
1060
|
-
class ActionSpec(PClass):
|
1061
|
-
# # TODO: should remove "player_idx" as it's always the same as "to_play"
|
1062
|
-
player_idx = field(type=int)
|
1063
|
-
action_name = field(type=str)
|
1064
|
-
return_route_option_sets = field(type=list, initial=[]) # List[OptionSet]
|
1065
|
-
draw_faceup_spots = field(type=dict, initial={}) # Dict{Int, int}
|
1066
|
-
points = field(type=list, initial=[]) # List[PointCombos]
|
1067
|
-
paths = field(type=list, initial=[]) # List[PathCombos]
|
1068
|
-
def __todict__(self):
|
1069
|
-
return {
|
1070
|
-
"player_idx": self.player_idx,
|
1071
|
-
"action_name": self.action_name,
|
1072
|
-
"return_route_option_sets": [x.__todict__() for x in self.return_route_option_sets],
|
1073
|
-
"draw_faceup_spots": self.draw_faceup_spots,
|
1074
|
-
"points": [x.__todict__() for x in self.points],
|
1075
|
-
"paths": [x.__todict__() for x in self.paths],
|
1076
|
-
}
|
1077
|
-
@staticmethod
|
1078
|
-
def __fromdict__(d):
|
1079
|
-
print("""d["return_route_option_sets"]""", d["return_route_option_sets"])
|
1080
|
-
return ActionSpec(
|
1081
|
-
player_idx=d["player_idx"],
|
1082
|
-
action_name=d["action_name"],
|
1083
|
-
return_route_option_sets=[OptionSet.__fromdict__(x) for x in d["return_route_option_sets"]],
|
1084
|
-
draw_faceup_spots=d["draw_faceup_spots"],
|
1085
|
-
points=[PointCombos.__fromdict__(x) for x in d["points"]],
|
1086
|
-
paths=[PathCombos.__fromdict__(x) for x in d["paths"]],
|
1087
|
-
)
|
1088
|
-
|
1089
|
-
|
1090
|
-
# Implementing the following Julia function:
|
1091
|
-
# struct PathCombos
|
1092
|
-
# path_idx::Int
|
1093
|
-
# default_combo::String
|
1094
|
-
# sample_fulfillment::Vector{Int}
|
1095
|
-
# end
|
1096
|
-
class PathCombos(PClass):
|
1097
|
-
path_idx = field(type=int)
|
1098
|
-
default_combo = field(type=str)
|
1099
|
-
sample_fulfillment = field(type=list) # List[int]
|
1100
|
-
def __todict__(self):
|
1101
|
-
return {
|
1102
|
-
"path_idx": self.path_idx,
|
1103
|
-
"default_combo": self.default_combo,
|
1104
|
-
"sample_fulfillment": self.sample_fulfillment,
|
1105
|
-
}
|
1106
|
-
@staticmethod
|
1107
|
-
def __fromdict__(d):
|
1108
|
-
return PathCombos(
|
1109
|
-
path_idx=d["path_idx"],
|
1110
|
-
default_combo=d["default_combo"],
|
1111
|
-
sample_fulfillment=d["sample_fulfillment"]
|
1112
|
-
)
|
1113
|
-
|
1114
|
-
|
1115
|
-
# Implementing the following Julia function:
|
1116
|
-
# struct OptionSet
|
1117
|
-
# option_idxs::Set{Int}
|
1118
|
-
# end
|
1119
|
-
class OptionSet(PClass):
|
1120
|
-
option_idxs = field(type=set) # Set[int]
|
1121
|
-
def __todict__(self):
|
1122
|
-
return {
|
1123
|
-
"option_idxs": list(self.option_idxs),
|
1124
|
-
}
|
1125
|
-
@staticmethod
|
1126
|
-
def __fromdict__(d):
|
1127
|
-
return OptionSet(
|
1128
|
-
option_idxs=set(d["option_idxs"])
|
1129
|
-
)
|
1130
|
-
|
1131
|
-
|
1132
|
-
class PointCombos(PClass):
|
1133
|
-
point_uuid = field(type=str)
|
1134
|
-
default_combo = field(type=str)
|
1135
|
-
sample_fulfillment = field(type=list) # List[int]
|
1136
|
-
def __todict__(self):
|
1137
|
-
return {
|
1138
|
-
"point_uuid": self.point_uuid,
|
1139
|
-
"default_combo": self.default_combo,
|
1140
|
-
"sample_fulfillment": self.sample_fulfillment,
|
1141
|
-
}
|
1142
|
-
@staticmethod
|
1143
|
-
def __fromdict__(d):
|
1144
|
-
return PointCombos(
|
1145
|
-
point_uuid=d["point_uuid"],
|
1146
|
-
default_combo=d["default_combo"],
|
1147
|
-
sample_fulfillment=d["sample_fulfillment"]
|
1148
|
-
)
|
1149
|
-
|
1150
|
-
|
1151
|
-
class PlayerInfo(PClass):
|
1152
|
-
fig = field(type=Fig)
|
1153
|
-
player_idx = field(type=int)
|
1154
|
-
new_route_cards = field(type=PVector) # List[int]
|
1155
|
-
route_cards = field(type=PVector) # List[int]
|
1156
|
-
unit_cards = field(type=PVector) # List[int]
|
1157
|
-
completed_routes = field(type=list) # List[int]
|
1158
|
-
completed_clusters = field(type=list) # List[UUID]
|
1159
|
-
paths = field(type=list) # List[int]
|
1160
|
-
points = field(type=list) # List[UUID]
|
1161
|
-
tokens = field(type=list) # List[UUID]
|
1162
|
-
num_pieces = field(type=int)
|
1163
|
-
num_point_pieces = field(type=int)
|
1164
|
-
longest_trail = field(type=list) # List[int]
|
1165
|
-
longest_trail_len = field(type=int)
|
1166
|
-
final_score = field(type=object) # Union{Nothing, PlayerScore}
|
1167
|
-
def __todict__(self):
|
1168
|
-
return {
|
1169
|
-
"fig": self.fig.__todict__(),
|
1170
|
-
"player_idx": self.player_idx,
|
1171
|
-
"new_route_cards": list(self.new_route_cards),
|
1172
|
-
"route_cards": list(self.route_cards),
|
1173
|
-
"unit_cards": list(self.unit_cards),
|
1174
|
-
"completed_routes": self.completed_routes,
|
1175
|
-
"completed_clusters": self.completed_clusters,
|
1176
|
-
"paths": self.paths,
|
1177
|
-
"points": self.points,
|
1178
|
-
"tokens": self.tokens,
|
1179
|
-
"num_pieces": self.num_pieces,
|
1180
|
-
"num_point_pieces": self.num_point_pieces,
|
1181
|
-
"longest_trail": self.longest_trail,
|
1182
|
-
"longest_trail_len": self.longest_trail_len,
|
1183
|
-
"final_score": self.final_score.__todict__() if self.final_score else None,
|
1184
|
-
}
|
1185
|
-
@staticmethod
|
1186
|
-
def __fromdict__(d):
|
1187
|
-
return PlayerInfo(
|
1188
|
-
fig=Fig.__fromdict__(d["fig"]),
|
1189
|
-
player_idx=d["player_idx"],
|
1190
|
-
new_route_cards=pvector(d["new_route_cards"]),
|
1191
|
-
route_cards=pvector(d["route_cards"]),
|
1192
|
-
unit_cards=pvector(d["unit_cards"]),
|
1193
|
-
completed_routes=d["completed_routes"],
|
1194
|
-
completed_clusters=d["completed_clusters"],
|
1195
|
-
paths=d["paths"],
|
1196
|
-
points=d["points"],
|
1197
|
-
tokens=d["tokens"],
|
1198
|
-
num_pieces=d["num_pieces"],
|
1199
|
-
num_point_pieces=d["num_point_pieces"],
|
1200
|
-
longest_trail=d["longest_trail"],
|
1201
|
-
longest_trail_len=d["longest_trail_len"],
|
1202
|
-
final_score=PlayerScore.__fromdict__(d["final_score"]) if d.get("final_score") else None,
|
1203
|
-
)
|
1204
|
-
@staticmethod
|
1205
|
-
def clone(hand):
|
1206
|
-
return PlayerInfo.__fromdict__(hand.__todict__())
|
1207
|
-
|
1208
|
-
|
1209
992
|
class PublicPlayer(PClass):
|
1210
993
|
idx = field(type=int)
|
1211
994
|
pieces = field(type=list) # List[Piece]
|
@@ -1316,36 +1099,27 @@ class PrivatePlayerScore(PClass):
|
|
1316
1099
|
)
|
1317
1100
|
|
1318
1101
|
|
1319
|
-
# Implementing the following Julia function:
|
1320
|
-
# struct PrivateState
|
1321
|
-
# legal_actions::Vector{ActionSpec}
|
1322
|
-
# segment_statuses::Vector{SegmentStatus}
|
1323
|
-
# hand::PlayerInfo
|
1324
|
-
# end
|
1325
1102
|
class PrivateState(PClass):
|
1103
|
+
my_history = field(type=list) # List[Action2]
|
1326
1104
|
player_score = field(type=PrivatePlayerScore)
|
1327
1105
|
player = field(type=Player)
|
1328
1106
|
legal_actions_2 = field(type=list) # List[LegalAction]
|
1329
|
-
legal_actions = field(type=list) # List[ActionSpec]
|
1330
|
-
hand = field(type=PlayerInfo)
|
1331
1107
|
goal_completions = field(type=list, initial=[]) # List[GoalCompletion]
|
1332
1108
|
def __todict__(self):
|
1333
1109
|
return {
|
1110
|
+
"my_history": [x.__todict__() for x in self.my_history],
|
1334
1111
|
"player_score": self.player_score.__todict__(),
|
1335
1112
|
"player": self.player.__todict__(),
|
1336
1113
|
"legal_actions_2": [x.__todict__() for x in self.legal_actions_2],
|
1337
|
-
"legal_actions": [x.__todict__() for x in self.legal_actions],
|
1338
|
-
"hand": self.hand.__todict__(),
|
1339
1114
|
"goal_completions": [x.__todict__() for x in self.goal_completions],
|
1340
1115
|
}
|
1341
1116
|
@staticmethod
|
1342
1117
|
def __fromdict__(d):
|
1343
1118
|
return PrivateState(
|
1119
|
+
my_history=[Action2.__fromdict__(x) for x in d["my_history"]],
|
1344
1120
|
player_score=PrivatePlayerScore.__fromdict__(d["player_score"]),
|
1345
1121
|
player=Player.__fromdict__(d["player"]),
|
1346
1122
|
legal_actions_2=[LegalAction.__fromdict__(x) for x in d["legal_actions_2"]],
|
1347
|
-
legal_actions=[ActionSpec.__fromdict__(x) for x in d["legal_actions"]],
|
1348
|
-
hand=PlayerInfo.__fromdict__(d["hand"]),
|
1349
1123
|
goal_completions=[GoalCompletion.__fromdict__(x) for x in d["goal_completions"]],
|
1350
1124
|
)
|
1351
1125
|
|
@@ -2164,7 +1938,6 @@ class State(PClass):
|
|
2164
1938
|
uuid2segment = field(type=dict) # Dict[str, Segment]
|
2165
1939
|
pieceuuid2piece = field(type=dict) # Dict[str, Piece]
|
2166
1940
|
carduuid2card = field(type=dict) # Dict[str, Card]
|
2167
|
-
final_scores = field(type=(list, type(None)), initial=None) # Optional[List[int]]
|
2168
1941
|
bonus_statuses = field(type=list) # List[BonusStatus]
|
2169
1942
|
bonusuuid2bonusidx = field(type=dict) # Dict[str, int]
|
2170
1943
|
carduuid2deckidx = field(type=dict) # Dict[str, int]
|
@@ -2188,16 +1961,8 @@ class State(PClass):
|
|
2188
1961
|
game_config = field(type=GameConfig)
|
2189
1962
|
rng = field(type=random.Random)
|
2190
1963
|
terminal = field(type=bool)
|
2191
|
-
initial_to_play = field(type=list) # List[int]
|
2192
|
-
route_cards = field(type=PVector) # List[int]
|
2193
|
-
route_discards = field(type=PVector) # List[int]
|
2194
|
-
player_hands = field(type=PVector) # List[PlayerInfo]
|
2195
|
-
unit_cards = field(type=PVector) # List[int]
|
2196
|
-
faceup_spots = field(type=PVector) # List[Union{Nothing, int}]
|
2197
|
-
unit_discards = field(type=PVector) # List[int]
|
2198
1964
|
last_to_play = field(type=(int, type(None)), initial=None)
|
2199
1965
|
winners = field(type=list) # List[int]
|
2200
|
-
# market_refills::Vector{MarketRefill}
|
2201
1966
|
def __todict__(self):
|
2202
1967
|
return {
|
2203
1968
|
"uuid2edge": {k: v.__todict__() for k, v in self.uuid2edge.items()},
|
@@ -2205,7 +1970,6 @@ class State(PClass):
|
|
2205
1970
|
"uuid2segment": {k: v.__todict__() for k, v in self.uuid2segment.items()},
|
2206
1971
|
"pieceuuid2piece": {k: v.__todict__() for k, v in self.pieceuuid2piece.items()},
|
2207
1972
|
"carduuid2card": {k: v.__todict__() for k, v in self.carduuid2card.items()},
|
2208
|
-
"final_scores": self.final_scores,
|
2209
1973
|
"bonus_statuses": [status.__todict__() for status in self.bonus_statuses],
|
2210
1974
|
"bonusuuid2bonusidx": self.bonusuuid2bonusidx,
|
2211
1975
|
"carduuid2deckidx": self.carduuid2deckidx,
|
@@ -2229,13 +1993,6 @@ class State(PClass):
|
|
2229
1993
|
"game_config": self.game_config.__todict__(),
|
2230
1994
|
"rng": rng2json(self.rng),
|
2231
1995
|
"terminal": self.terminal,
|
2232
|
-
"initial_to_play": self.initial_to_play,
|
2233
|
-
"route_cards": list(self.route_cards),
|
2234
|
-
"route_discards": list(self.route_discards),
|
2235
|
-
"player_hands": [x.__todict__() for x in self.player_hands],
|
2236
|
-
"unit_cards": list(self.unit_cards),
|
2237
|
-
"faceup_spots": list(self.faceup_spots),
|
2238
|
-
"unit_discards": list(self.unit_discards),
|
2239
1996
|
"last_to_play": self.last_to_play,
|
2240
1997
|
"winners": self.winners,
|
2241
1998
|
}
|
@@ -2247,7 +2004,6 @@ class State(PClass):
|
|
2247
2004
|
uuid2segment={k: Segment2.__fromdict__(v) for k, v in d["uuid2segment"].items()},
|
2248
2005
|
pieceuuid2piece={k: Piece.__fromdict__(v) for k, v in d["pieceuuid2piece"].items()},
|
2249
2006
|
carduuid2card={k: Card.__fromdict__(v) for k, v in d["carduuid2card"].items()},
|
2250
|
-
final_scores=d["final_scores"],
|
2251
2007
|
bonus_statuses=[BonusStatus.__fromdict__(x) for x in d["bonus_statuses"]],
|
2252
2008
|
bonusuuid2bonusidx=d["bonusuuid2bonusidx"],
|
2253
2009
|
carduuid2deckidx=d["carduuid2deckidx"],
|
@@ -2271,13 +2027,6 @@ class State(PClass):
|
|
2271
2027
|
game_config=GameConfig.__fromdict__(d["game_config"]),
|
2272
2028
|
rng=json2rng(d["rng"]),
|
2273
2029
|
terminal=d["terminal"],
|
2274
|
-
initial_to_play=d["initial_to_play"],
|
2275
|
-
route_cards=pvector(d["route_cards"]),
|
2276
|
-
route_discards=pvector(d["route_discards"]),
|
2277
|
-
player_hands=pvector([PlayerInfo.__fromdict__(h) for h in d["player_hands"]]),
|
2278
|
-
unit_cards=pvector(d["unit_cards"]),
|
2279
|
-
faceup_spots=pvector(d["faceup_spots"]),
|
2280
|
-
unit_discards=pvector(d["unit_discards"]),
|
2281
2030
|
last_to_play=d.get("last_to_play"),
|
2282
2031
|
winners=d["winners"],
|
2283
2032
|
)
|
@@ -2479,70 +2228,6 @@ class ScoreItem(PClass):
|
|
2479
2228
|
)
|
2480
2229
|
|
2481
2230
|
|
2482
|
-
# Implementing the following GraphQL type:
|
2483
|
-
# type PublicPlayerInfo {
|
2484
|
-
# final_score: PlayerScore
|
2485
|
-
# longest_trail: [Int]!
|
2486
|
-
# longest_trail_len: Int!
|
2487
|
-
# num_pieces: Int!
|
2488
|
-
# num_route_cards: Int!
|
2489
|
-
# num_unit_cards: Int!
|
2490
|
-
# paths: [Int]!
|
2491
|
-
# route_statuses: [RouteStatus]
|
2492
|
-
# score: Int!
|
2493
|
-
# }
|
2494
|
-
class PublicPlayerInfo(PClass):
|
2495
|
-
final_score = field(type=(PlayerScore, type(None)), initial=None) # Union{Nothing, PlayerScore}
|
2496
|
-
longest_trail = field(type=list) # List[int]
|
2497
|
-
longest_trail_len = field(type=int)
|
2498
|
-
num_pieces = field(type=int)
|
2499
|
-
num_route_cards = field(type=int)
|
2500
|
-
num_new_route_cards = field(type=int)
|
2501
|
-
num_unit_cards = field(type=int)
|
2502
|
-
paths = field(type=list) # List[int]
|
2503
|
-
points = field(type=list) # List[UUID]
|
2504
|
-
tokens = field(type=list) # List[UUID]
|
2505
|
-
route_statuses = field(type=list) # List[RouteStatus]
|
2506
|
-
score = field(type=int)
|
2507
|
-
num_point_pieces = field(type=int, initial=0) # Added to match PlayerInfo
|
2508
|
-
completed_clusters = field(type=list, initial=[]) # Added to match PlayerInfo
|
2509
|
-
def __todict__(self):
|
2510
|
-
return {
|
2511
|
-
"final_score": self.final_score.__todict__() if self.final_score else None,
|
2512
|
-
"longest_trail": self.longest_trail,
|
2513
|
-
"longest_trail_len": self.longest_trail_len,
|
2514
|
-
"num_pieces": self.num_pieces,
|
2515
|
-
"num_route_cards": self.num_route_cards,
|
2516
|
-
"num_new_route_cards": self.num_new_route_cards,
|
2517
|
-
"num_unit_cards": self.num_unit_cards,
|
2518
|
-
"paths": self.paths,
|
2519
|
-
"points": self.points,
|
2520
|
-
"tokens": self.tokens,
|
2521
|
-
"route_statuses": [x.__todict__() for x in self.route_statuses],
|
2522
|
-
"score": self.score,
|
2523
|
-
"num_point_pieces": self.num_point_pieces,
|
2524
|
-
"completed_clusters": self.completed_clusters,
|
2525
|
-
}
|
2526
|
-
@staticmethod
|
2527
|
-
def __fromdict__(d):
|
2528
|
-
return PublicPlayerInfo(
|
2529
|
-
final_score=PlayerScore.__fromdict__(d["final_score"]) if d.get("final_score") else None,
|
2530
|
-
longest_trail=d["longest_trail"],
|
2531
|
-
longest_trail_len=d["longest_trail_len"],
|
2532
|
-
num_pieces=d["num_pieces"],
|
2533
|
-
num_route_cards=d["num_route_cards"],
|
2534
|
-
num_new_route_cards=d["num_new_route_cards"],
|
2535
|
-
num_unit_cards=d["num_unit_cards"],
|
2536
|
-
paths=d["paths"],
|
2537
|
-
points=d["points"],
|
2538
|
-
tokens=d["tokens"],
|
2539
|
-
route_statuses=[RouteStatus.__fromdict__(x) for x in d["route_statuses"]],
|
2540
|
-
score=d["score"],
|
2541
|
-
num_point_pieces=d.get("num_point_pieces", 0),
|
2542
|
-
completed_clusters=d.get("completed_clusters", []),
|
2543
|
-
)
|
2544
|
-
|
2545
|
-
|
2546
2231
|
class AllottedTime(PClass):
|
2547
2232
|
seconds = field(type=int)
|
2548
2233
|
since_action_idx = field(type=int)
|
@@ -2597,21 +2282,10 @@ class PublicState(PClass):
|
|
2597
2282
|
decks = field(type=list) # List[PublicDeck]
|
2598
2283
|
piles = field(type=list) # List[Pile]
|
2599
2284
|
player_idxs = field(type=list) # List[int]
|
2600
|
-
initial_to_play = field(type=list) # List[int]
|
2601
|
-
to_play = field(type=list) # List[int]
|
2602
|
-
unit_discards = field(type=list) # List[int]
|
2603
|
-
num_route_cards = field(type=int)
|
2604
|
-
num_route_discards = field(type=int)
|
2605
|
-
num_unit_cards = field(type=int)
|
2606
|
-
num_unit_discards = field(type=int)
|
2607
|
-
faceup_spots = field(type=list) # List[Union{Nothing, int}]
|
2608
2285
|
players = field(type=list) # List[PublicPlayer]
|
2609
|
-
player_hands = field(type=list) # List[PublicPlayerInfo]
|
2610
2286
|
last_to_play = field(type=(int, type(None)), initial=None)
|
2611
2287
|
winners = field(type=list)
|
2612
2288
|
terminal = field(type=bool)
|
2613
|
-
captured_points = field(type=list) # List[CapturedPoint]
|
2614
|
-
captured_segments = field(type=list) # List[CapturedSegment]
|
2615
2289
|
def __todict__(self):
|
2616
2290
|
return {
|
2617
2291
|
"deadlines": [deadline.__todict__() if deadline else None for deadline in self.deadlines],
|
@@ -2632,21 +2306,10 @@ class PublicState(PClass):
|
|
2632
2306
|
"decks": [deck.__todict__() for deck in self.decks],
|
2633
2307
|
"piles": [pile.__todict__() for pile in self.piles],
|
2634
2308
|
"player_idxs": self.player_idxs,
|
2635
|
-
"initial_to_play": self.initial_to_play,
|
2636
|
-
"to_play": self.to_play,
|
2637
|
-
"unit_discards": self.unit_discards,
|
2638
|
-
"num_route_cards": self.num_route_cards,
|
2639
|
-
"num_route_discards": self.num_route_discards,
|
2640
|
-
"num_unit_cards": self.num_unit_cards,
|
2641
|
-
"num_unit_discards": self.num_unit_discards,
|
2642
|
-
"faceup_spots": self.faceup_spots,
|
2643
2309
|
"players": [x.__todict__() for x in self.players],
|
2644
|
-
"player_hands": [x.__todict__() for x in self.player_hands],
|
2645
2310
|
"last_to_play": self.last_to_play,
|
2646
2311
|
"winners": self.winners,
|
2647
2312
|
"terminal": self.terminal,
|
2648
|
-
"captured_points": [x.__todict__() for x in self.captured_points],
|
2649
|
-
"captured_segments": [x.__todict__() for x in self.captured_segments],
|
2650
2313
|
}
|
2651
2314
|
@staticmethod
|
2652
2315
|
def __fromdict__(d):
|
@@ -2669,26 +2332,11 @@ class PublicState(PClass):
|
|
2669
2332
|
decks=[PublicDeck.__fromdict__(deck) for deck in d["decks"]],
|
2670
2333
|
piles=[Pile.__fromdict__(x) for x in d["piles"]],
|
2671
2334
|
player_idxs=d["player_idxs"],
|
2672
|
-
initial_to_play=d["initial_to_play"],
|
2673
|
-
to_play=d["to_play"],
|
2674
|
-
unit_discards=d["unit_discards"],
|
2675
|
-
num_route_cards=d["num_route_cards"],
|
2676
|
-
num_route_discards=d["num_route_discards"],
|
2677
|
-
num_unit_cards=d["num_unit_cards"],
|
2678
|
-
num_unit_discards=d["num_unit_discards"],
|
2679
|
-
faceup_spots=d["faceup_spots"],
|
2680
2335
|
players=[PublicPlayer.__fromdict__(x) for x in d["players"]],
|
2681
|
-
player_hands=[PublicPlayerInfo.__fromdict__(x) for x in d["player_hands"]],
|
2682
2336
|
last_to_play=d.get("last_to_play"),
|
2683
2337
|
winners=d["winners"],
|
2684
2338
|
terminal=d["terminal"],
|
2685
|
-
captured_points=[CapturedPoint.__fromdict__(x) for x in d["captured_points"]],
|
2686
|
-
captured_segments=[CapturedSegment.__fromdict__(x) for x in d["captured_segments"]],
|
2687
2339
|
)
|
2688
|
-
# fig::Fig
|
2689
|
-
# captured_segments::Vector{CapturedSegment}
|
2690
|
-
# captured_points::Vector{CapturedPoint}
|
2691
|
-
# market_refills::Vector{MarketRefill}
|
2692
2340
|
|
2693
2341
|
|
2694
2342
|
class PlayerState(PClass):
|
@@ -2837,50 +2485,9 @@ def getsettingvalue(s, setting_name):
|
|
2837
2485
|
def getinitialstate(game_config):
|
2838
2486
|
fig = game_config.fig
|
2839
2487
|
rng = getrng(game_config.seed)
|
2840
|
-
route_deck = shuffledeck(getnumroutecards(fig), rng)
|
2841
2488
|
unit_deck = shuffledeck(gettotaldeckcards(fig), rng)
|
2842
2489
|
route_deck_idx, unit_deck_idx = 0, 0
|
2843
|
-
player_hands = []
|
2844
|
-
initial_num_route_choices = getsettingvalue(fig, "initial_num_route_choices")
|
2845
|
-
num_initial_unit_cards = getsettingvalue(fig, "num_initial_unit_cards")
|
2846
|
-
num_segment_pieces_per_player = getsettingvalue(fig, "num_segment_pieces_per_player")
|
2847
|
-
num_point_pieces_per_player = getsettingvalue(fig, "num_point_pieces_per_player")
|
2848
|
-
|
2849
|
-
|
2850
|
-
for player_idx in range(game_config.num_players):
|
2851
|
-
player_hand = PlayerInfo(
|
2852
|
-
fig=fig,
|
2853
|
-
player_idx=player_idx,
|
2854
|
-
new_route_cards=pvector(route_deck[route_deck_idx:(route_deck_idx+(initial_num_route_choices))]),
|
2855
|
-
route_cards=pvector([]),
|
2856
|
-
unit_cards=pvector(unit_deck[unit_deck_idx:(unit_deck_idx + num_initial_unit_cards)]),
|
2857
|
-
completed_routes=[],
|
2858
|
-
completed_clusters=[],
|
2859
|
-
paths=[],
|
2860
|
-
points=[],
|
2861
|
-
tokens=[],
|
2862
|
-
num_pieces=num_segment_pieces_per_player,
|
2863
|
-
num_point_pieces=num_point_pieces_per_player,
|
2864
|
-
longest_trail=[],
|
2865
|
-
longest_trail_len=0,
|
2866
|
-
final_score=None,
|
2867
|
-
)
|
2868
|
-
player_hands.append(player_hand)
|
2869
|
-
route_deck_idx += initial_num_route_choices
|
2870
|
-
unit_deck_idx += num_initial_unit_cards
|
2871
|
-
|
2872
|
-
faceup_spots = getfaceupspots(fig, unit_deck, unit_deck_idx)
|
2873
2490
|
unit_deck_idx += 5
|
2874
|
-
# Implementing the following Julia function:
|
2875
|
-
# unit_cards = unit_deck[unit_deck_idx:end]
|
2876
|
-
unit_cards = unit_deck[unit_deck_idx:] if unit_deck_idx < len(unit_deck) else []
|
2877
|
-
route_cards = route_deck[route_deck_idx:]
|
2878
|
-
|
2879
|
-
if getsettingvalue(fig, 'action_route_discard'):
|
2880
|
-
initial_to_play = list(range(game_config.num_players))
|
2881
|
-
else:
|
2882
|
-
initial_to_play = [getfirstplayeridx(rng, game_config.num_players)]
|
2883
|
-
|
2884
2491
|
board_config = fig.board_config
|
2885
2492
|
deck_0_rng = getrng(1234321)
|
2886
2493
|
deck_1_rng = getrng(8738758)
|
@@ -2965,7 +2572,6 @@ def getinitialstate(game_config):
|
|
2965
2572
|
uuid2segment=uuid2segment,
|
2966
2573
|
pieceuuid2piece=pieceuuid2piece,
|
2967
2574
|
carduuid2card=carduuid2card,
|
2968
|
-
final_scores=None,
|
2969
2575
|
bonus_statuses=bonus_statuses,
|
2970
2576
|
bonusuuid2bonusidx=bonusuuid2bonusidx,
|
2971
2577
|
carduuid2deckidx=carduuid2deckidx,
|
@@ -2996,14 +2602,7 @@ def getinitialstate(game_config):
|
|
2996
2602
|
player_idxs=list(range(game_config.num_players)),
|
2997
2603
|
decks=decks,
|
2998
2604
|
game_config=game_config,
|
2999
|
-
initial_to_play=initial_to_play,
|
3000
2605
|
rng=rng,
|
3001
|
-
route_cards=pvector(route_cards),
|
3002
|
-
route_discards=pvector([]),
|
3003
|
-
player_hands=pvector(player_hands),
|
3004
|
-
unit_cards=pvector(unit_cards),
|
3005
|
-
unit_discards=pvector([]),
|
3006
|
-
faceup_spots=pvector(faceup_spots),
|
3007
2606
|
last_to_play=None,
|
3008
2607
|
winners=[],
|
3009
2608
|
terminal=False,
|
@@ -3114,15 +2713,20 @@ def handle_last_to_play(game):
|
|
3114
2713
|
return game
|
3115
2714
|
|
3116
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
|
+
|
3117
2723
|
def handle_calc_winners(game):
|
3118
2724
|
if game.terminal:
|
3119
2725
|
players_with_highest_score = []
|
3120
2726
|
highest_score = -1000
|
3121
|
-
final_scores =
|
2727
|
+
final_scores = getfinalscores(game)
|
3122
2728
|
for player_idx in range(len(game.players)):
|
3123
|
-
|
3124
|
-
final_score = getpublicplayerscore(game, player_score).total
|
3125
|
-
final_scores.append(final_score)
|
2729
|
+
final_score = final_scores[player_idx]
|
3126
2730
|
if final_score > highest_score:
|
3127
2731
|
highest_score = final_score
|
3128
2732
|
players_with_highest_score = [player_idx]
|
@@ -3130,7 +2734,6 @@ def handle_calc_winners(game):
|
|
3130
2734
|
players_with_highest_score.append(player_idx)
|
3131
2735
|
return game.set(
|
3132
2736
|
winners=players_with_highest_score,
|
3133
|
-
final_scores=final_scores,
|
3134
2737
|
)
|
3135
2738
|
|
3136
2739
|
return game
|
@@ -4428,63 +4031,6 @@ def getnextstate2(s, a, log=False):
|
|
4428
4031
|
return s
|
4429
4032
|
|
4430
4033
|
|
4431
|
-
|
4432
|
-
@dispatch(State, QValueLearningPolicy)
|
4433
|
-
def getnextaction(s, policy):
|
4434
|
-
player_idx = gettoplay(s)[0]
|
4435
|
-
legal_action_specs = getlegalactionspecsforplayer(s, player_idx, None, None)
|
4436
|
-
legal_actions = get_all_legal_actions(s, player_idx, legal_action_specs)
|
4437
|
-
|
4438
|
-
if s.rng.random() <= policy.epsilon:
|
4439
|
-
random_action = legal_actions[s.rng.randint(0, len(legal_actions) - 1)]
|
4440
|
-
return random_action
|
4441
|
-
|
4442
|
-
q_values = policy.qvalue_fn(s, legal_actions)
|
4443
|
-
argmax_idx = max(range(len(q_values)), key=lambda i: q_values[i])
|
4444
|
-
|
4445
|
-
return legal_actions[argmax_idx]
|
4446
|
-
|
4447
|
-
|
4448
|
-
@dispatch(State, RandoPolicy)
|
4449
|
-
def getnextaction(s, policy):
|
4450
|
-
player_idx = gettoplay(s)[0]
|
4451
|
-
legal_actions = getlegalactionspecsforplayer(s, player_idx, None, None)
|
4452
|
-
action_spec = legal_actions[s.rng.randint(0, len(legal_actions) - 1)]
|
4453
|
-
|
4454
|
-
if action_spec.action_name == "ROUTE_DISCARD":
|
4455
|
-
return AltAction(
|
4456
|
-
action_name="ROUTE_DISCARD",
|
4457
|
-
player_idx=player_idx,
|
4458
|
-
return_route_cards=[0],
|
4459
|
-
)
|
4460
|
-
|
4461
|
-
if action_spec.action_name == "DRAW_UNIT_FACEUP":
|
4462
|
-
draw_faceup_spot_num = 1
|
4463
|
-
return AltAction(
|
4464
|
-
action_name="DRAW_UNIT_FACEUP",
|
4465
|
-
player_idx=player_idx,
|
4466
|
-
draw_faceup_unit_card_num=s.faceup_spots[draw_faceup_spot_num-1],
|
4467
|
-
draw_faceup_spot_num=draw_faceup_spot_num,
|
4468
|
-
)
|
4469
|
-
|
4470
|
-
if action_spec.action_name == "DRAW_UNIT_DECK":
|
4471
|
-
return AltAction(
|
4472
|
-
action_name="DRAW_UNIT_DECK",
|
4473
|
-
player_idx=player_idx,
|
4474
|
-
)
|
4475
|
-
|
4476
|
-
if action_spec.action_name == "CLAIM_POINT":
|
4477
|
-
point = action_spec.points[s.rng.randint(0, len(action_spec.points) - 1)]
|
4478
|
-
return AltAction(
|
4479
|
-
action_name="CLAIM_POINT",
|
4480
|
-
player_idx=player_idx,
|
4481
|
-
point_uuid=str(point.point_uuid),
|
4482
|
-
unit_combo=point.default_combo,
|
4483
|
-
)
|
4484
|
-
|
4485
|
-
return None
|
4486
|
-
|
4487
|
-
|
4488
4034
|
def getpublicplayerscore(s, player_score):
|
4489
4035
|
if s.terminal:
|
4490
4036
|
# Join the arrays of public and private items
|
@@ -4568,6 +4114,98 @@ def get_deadlines(s):
|
|
4568
4114
|
]
|
4569
4115
|
|
4570
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
|
+
|
4571
4209
|
@dispatch(State)
|
4572
4210
|
def getpublicstate(s):
|
4573
4211
|
return PublicState(
|
@@ -4579,8 +4217,8 @@ def getpublicstate(s):
|
|
4579
4217
|
bonus_statuses=s.bonus_statuses,
|
4580
4218
|
starting_decks=s.starting_decks,
|
4581
4219
|
starting_piles=s.starting_piles,
|
4582
|
-
history=
|
4583
|
-
player_scores=
|
4220
|
+
history=get_public_history(s),
|
4221
|
+
player_scores=get_public_player_scores(s),
|
4584
4222
|
player_graphs=s.player_graphs,
|
4585
4223
|
goals=s.goals,
|
4586
4224
|
nodes=s.nodes,
|
@@ -4589,21 +4227,10 @@ def getpublicstate(s):
|
|
4589
4227
|
decks=[getpublicdeck(s, deck) for deck in s.decks],
|
4590
4228
|
piles=s.piles,
|
4591
4229
|
player_idxs=s.player_idxs,
|
4592
|
-
initial_to_play=s.initial_to_play,
|
4593
|
-
to_play=gettoplay(s),
|
4594
|
-
unit_discards=list(s.unit_discards),
|
4595
|
-
num_route_cards=len(s.route_cards),
|
4596
|
-
num_route_discards=len(s.route_discards),
|
4597
|
-
num_unit_cards=len(s.unit_cards),
|
4598
|
-
num_unit_discards=len(s.unit_discards),
|
4599
|
-
faceup_spots=list(s.faceup_spots),
|
4600
4230
|
players=[getpublicplayer(s, p) for p in s.players],
|
4601
|
-
player_hands=[getpublicplayerinfo(s, p) for p in s.player_hands],
|
4602
4231
|
last_to_play=s.last_to_play,
|
4603
4232
|
winners=s.winners,
|
4604
4233
|
terminal=s.terminal,
|
4605
|
-
captured_points=getcapturedpoints(s),
|
4606
|
-
captured_segments=getcapturedsegments(s),
|
4607
4234
|
)
|
4608
4235
|
|
4609
4236
|
|
@@ -4635,31 +4262,6 @@ def getpublicplayer(s, p):
|
|
4635
4262
|
)
|
4636
4263
|
|
4637
4264
|
|
4638
|
-
@dispatch(State, PlayerInfo)
|
4639
|
-
def getpublicplayerinfo(s, p):
|
4640
|
-
# if s.terminal
|
4641
|
-
# route_statuses = getroutestatuses(p)
|
4642
|
-
# else
|
4643
|
-
# route_statuses = []
|
4644
|
-
# end
|
4645
|
-
return PublicPlayerInfo(
|
4646
|
-
final_score=p.final_score,
|
4647
|
-
longest_trail=p.longest_trail,
|
4648
|
-
longest_trail_len=p.longest_trail_len,
|
4649
|
-
num_pieces=p.num_pieces,
|
4650
|
-
num_route_cards=len(p.route_cards),
|
4651
|
-
num_new_route_cards=len(p.new_route_cards),
|
4652
|
-
num_unit_cards=len(p.unit_cards),
|
4653
|
-
paths=p.paths,
|
4654
|
-
points=p.points,
|
4655
|
-
tokens=p.tokens,
|
4656
|
-
route_statuses=[], # TODO: implement!
|
4657
|
-
score=getpublicscore(s, p.player_idx),
|
4658
|
-
num_point_pieces=p.num_point_pieces,
|
4659
|
-
completed_clusters=p.completed_clusters,
|
4660
|
-
)
|
4661
|
-
|
4662
|
-
|
4663
4265
|
# Implementing the following Julia function:
|
4664
4266
|
# function getpublicscore(s::State, player_idx::Int)
|
4665
4267
|
# addends = Int[]
|
@@ -4774,18 +4376,6 @@ def gettoplay(s, last_action_type):
|
|
4774
4376
|
return [getlastplayeridxplus1(s)]
|
4775
4377
|
|
4776
4378
|
|
4777
|
-
# Implementing the following Julia function:
|
4778
|
-
@dispatch(State, NoAction)
|
4779
|
-
# function gettoplay(s::State, last_action_key::Nothing)
|
4780
|
-
# if getsettingvalue(s, :action_route_discard)
|
4781
|
-
# return collect(1:s.game_config.num_players)
|
4782
|
-
# end
|
4783
|
-
# [getfirstplayeridx(s.game)]
|
4784
|
-
# end
|
4785
|
-
def gettoplay(s, last_action_type):
|
4786
|
-
return s.initial_to_play
|
4787
|
-
|
4788
|
-
|
4789
4379
|
def getrng(seed):
|
4790
4380
|
rng = random.Random()
|
4791
4381
|
rng.seed(seed)
|
@@ -4946,273 +4536,6 @@ def combinations(a, n=None):
|
|
4946
4536
|
# then the state is "terminal".
|
4947
4537
|
###
|
4948
4538
|
|
4949
|
-
# Implementing the following Julia function:
|
4950
|
-
# function getrouteoptionsets(s::State, player_idx, min_required)
|
4951
|
-
# num_choices = length(s.player_hands[player_idx].new_route_cards)
|
4952
|
-
# max_return_size = num_choices - min_required
|
4953
|
-
# set = collect(1:num_choices)
|
4954
|
-
# OptionSet.(
|
4955
|
-
# Set{Int}.(
|
4956
|
-
# reduce(
|
4957
|
-
# vcat,
|
4958
|
-
# [collect(combinations(set, n)) for n in 0:max_return_size],
|
4959
|
-
# )
|
4960
|
-
# )
|
4961
|
-
# )
|
4962
|
-
# end
|
4963
|
-
def getrouteoptionsets(s, player_idx, min_required):
|
4964
|
-
num_choices = len(s.player_hands[player_idx].new_route_cards)
|
4965
|
-
max_return_size = num_choices - min_required
|
4966
|
-
choice_set = list(range(num_choices))
|
4967
|
-
all_combinations = [
|
4968
|
-
set(comb)
|
4969
|
-
for n in range(max_return_size + 1)
|
4970
|
-
for comb in combinations(choice_set, n)
|
4971
|
-
]
|
4972
|
-
return [OptionSet(option_idxs=comb) for comb in all_combinations]
|
4973
|
-
|
4974
|
-
|
4975
|
-
|
4976
|
-
# Implementing the following Julia function:
|
4977
|
-
# function getlegalactionsforplayer(s::State, player_idx, repeat_player, last_action)
|
4978
|
-
# min_initial_routes = getsettingvalue(s.fig, :min_initial_routes)
|
4979
|
-
# min_chosen_routes = getsettingvalue(s.fig, :min_chosen_routes)
|
4980
|
-
|
4981
|
-
# # Initial Route Card Discard
|
4982
|
-
# if getsettingvalue(s, :action_route_discard) && length(s.action_history) < s.game_config.num_players
|
4983
|
-
# return [
|
4984
|
-
# ActionSpec(
|
4985
|
-
# player_idx=player_idx,
|
4986
|
-
# action_name=ROUTE_DISCARD,
|
4987
|
-
# return_route_option_sets=getrouteoptionsets(s, player_idx, min_initial_routes),
|
4988
|
-
# )
|
4989
|
-
# ]
|
4990
|
-
# end
|
4991
|
-
|
4992
|
-
# action_specs = ActionSpec[]
|
4993
|
-
# if getsettingvalue(s, :action_draw_unit_faceup) && !isempty(getvalidspotnums(s))
|
4994
|
-
# push!(
|
4995
|
-
# action_specs,
|
4996
|
-
# ActionSpec(
|
4997
|
-
# player_idx=player_idx,
|
4998
|
-
# action_name=DRAW_UNIT_FACEUP,
|
4999
|
-
# draw_faceup_spots=Dict((spot_num, s.faceup_spots[spot_num]) for spot_num in getvalidspotnums(s)),
|
5000
|
-
# )
|
5001
|
-
# )
|
5002
|
-
# end
|
5003
|
-
|
5004
|
-
# if getsettingvalue(s, :action_draw_route) && (length(s.route_cards) + length(s.route_discards)) >= min_chosen_routes
|
5005
|
-
# push!(action_specs, ActionSpec(s.fig, player_idx, :DRAW_ROUTE))
|
5006
|
-
# end
|
5007
|
-
|
5008
|
-
# if getsettingvalue(s, :action_draw_unit_deck) && (!isempty(s.unit_cards) || !isempty(s.unit_discards))
|
5009
|
-
# push!(action_specs, ActionSpec(s.fig, player_idx, :DRAW_UNIT_DECK))
|
5010
|
-
# end
|
5011
|
-
|
5012
|
-
# if getsettingvalue(s, :action_claim_path)
|
5013
|
-
# append!(action_specs, getclaimpathactionspecs(s, player_idx))
|
5014
|
-
# end
|
5015
|
-
|
5016
|
-
# if getsettingvalue(s.fig, :action_claim_point)
|
5017
|
-
# append!(action_specs, getclaimpointactionspecs(s, player_idx))
|
5018
|
-
# end
|
5019
|
-
|
5020
|
-
# action_specs
|
5021
|
-
# end
|
5022
|
-
@dispatch(State, int, object, object)
|
5023
|
-
def getlegalactionspecsforplayer(s, player_idx, repeat_player, last_action):
|
5024
|
-
min_chosen_routes = getsettingvalue(s, 'min_chosen_routes')
|
5025
|
-
|
5026
|
-
action_specs = []
|
5027
|
-
if getsettingvalue(s, 'action_draw_unit_faceup') and s.faceup_spots:
|
5028
|
-
|
5029
|
-
# Convert this Julia to Python:
|
5030
|
-
# Julia:
|
5031
|
-
# draw_faceup_spots = Dict((spot_num, s.faceup_spots[spot_num]) for spot_num in getvalidspotnums(s))
|
5032
|
-
# Python:
|
5033
|
-
draw_faceup_spots = {spot_num: s.faceup_spots[spot_num-1] for spot_num in getvalidspotnums(s)}
|
5034
|
-
|
5035
|
-
action_specs.append(
|
5036
|
-
ActionSpec(
|
5037
|
-
player_idx=player_idx,
|
5038
|
-
action_name="DRAW_UNIT_FACEUP",
|
5039
|
-
return_route_option_sets = [],
|
5040
|
-
draw_faceup_spots=draw_faceup_spots,
|
5041
|
-
points = [],
|
5042
|
-
paths = [],
|
5043
|
-
)
|
5044
|
-
)
|
5045
|
-
|
5046
|
-
if getsettingvalue(s, 'action_draw_route') and (len(s.route_cards) + len(s.route_discards)) >= min_chosen_routes:
|
5047
|
-
action_specs.append(
|
5048
|
-
AltAction(
|
5049
|
-
player_idx=player_idx,
|
5050
|
-
action_name="DRAW_ROUTE",
|
5051
|
-
return_route_option_sets = [],
|
5052
|
-
draw_faceup_spots={},
|
5053
|
-
points = [],
|
5054
|
-
paths = [],
|
5055
|
-
)
|
5056
|
-
)
|
5057
|
-
|
5058
|
-
if getsettingvalue(s, 'action_draw_unit_deck') and (s.unit_cards or s.unit_discards):
|
5059
|
-
action_specs.append(
|
5060
|
-
ActionSpec(
|
5061
|
-
player_idx=player_idx,
|
5062
|
-
action_name="DRAW_UNIT_DECK",
|
5063
|
-
return_route_option_sets = [],
|
5064
|
-
draw_faceup_spots={},
|
5065
|
-
points = [],
|
5066
|
-
paths = [],
|
5067
|
-
)
|
5068
|
-
)
|
5069
|
-
|
5070
|
-
if getsettingvalue(s, 'action_claim_path'):
|
5071
|
-
action_specs.extend(getclaimpathactionspecs(s, player_idx))
|
5072
|
-
pass
|
5073
|
-
|
5074
|
-
if getsettingvalue(s, 'action_claim_point'):
|
5075
|
-
action_specs.extend(getclaimpointactionspecs(s, player_idx))
|
5076
|
-
|
5077
|
-
return action_specs
|
5078
|
-
|
5079
|
-
|
5080
|
-
# Implementing the following Julia function:
|
5081
|
-
# function getclaimpointactionspecs(s::State, player_idx::Int; log=false)
|
5082
|
-
# action_specs = ActionSpec[]
|
5083
|
-
# available_point_statuses = getavailablepoints(s, player_idx)
|
5084
|
-
# points = map(available_point_statuses) do available_point_status
|
5085
|
-
# (; uuid, sample_fulfillment) = available_point_status
|
5086
|
-
# fulfillment_sorted = sample_fulfillment
|
5087
|
-
# sample_fulfillment = [x.unit_card_num for x in fulfillment_sorted]
|
5088
|
-
# fulfillment_str = join(sample_fulfillment, "-")
|
5089
|
-
# PointCombos(uuid, fulfillment_str, sample_fulfillment)
|
5090
|
-
# end
|
5091
|
-
# if !isempty(points)
|
5092
|
-
# push!(
|
5093
|
-
# action_specs,
|
5094
|
-
# ActionSpec(
|
5095
|
-
# action_name=CLAIM_POINT,
|
5096
|
-
# player_idx=player_idx,
|
5097
|
-
# points=points,
|
5098
|
-
# )
|
5099
|
-
# )
|
5100
|
-
# end
|
5101
|
-
# action_specs
|
5102
|
-
# end
|
5103
|
-
def getclaimpointactionspecs(s, player_idx, log=False):
|
5104
|
-
action_specs = []
|
5105
|
-
available_point_statuses = getavailablepoints(s, player_idx)
|
5106
|
-
|
5107
|
-
# points = map(available_point_statuses) do available_point_status
|
5108
|
-
# (; uuid, sample_fulfillment) = available_point_status
|
5109
|
-
# fulfillment_sorted = sample_fulfillment
|
5110
|
-
# sample_fulfillment = [x.unit_card_num for x in fulfillment_sorted]
|
5111
|
-
# fulfillment_str = join(sample_fulfillment, "-")
|
5112
|
-
# PointCombos(uuid, fulfillment_str, sample_fulfillment)
|
5113
|
-
# end
|
5114
|
-
|
5115
|
-
def process_point_status(available_point_status):
|
5116
|
-
uuid = available_point_status['uuid']
|
5117
|
-
sample_fulfillment = available_point_status['sample_fulfillment']
|
5118
|
-
fulfillment_sorted = sample_fulfillment
|
5119
|
-
sample_fulfillment = [x['unit_card_num'] for x in fulfillment_sorted]
|
5120
|
-
fulfillment_str = '-'.join(map(str, sample_fulfillment))
|
5121
|
-
return PointCombos(
|
5122
|
-
point_uuid=uuid,
|
5123
|
-
default_combo=fulfillment_str,
|
5124
|
-
sample_fulfillment=sample_fulfillment
|
5125
|
-
)
|
5126
|
-
|
5127
|
-
point_combos = list(map(process_point_status, available_point_statuses))
|
5128
|
-
|
5129
|
-
if point_combos:
|
5130
|
-
action_specs.append(
|
5131
|
-
ActionSpec(
|
5132
|
-
player_idx=player_idx,
|
5133
|
-
action_name="CLAIM_POINT",
|
5134
|
-
return_route_option_sets = [],
|
5135
|
-
draw_faceup_spots = {},
|
5136
|
-
points=point_combos,
|
5137
|
-
paths = [],
|
5138
|
-
)
|
5139
|
-
)
|
5140
|
-
|
5141
|
-
return action_specs
|
5142
|
-
|
5143
|
-
|
5144
|
-
# Implementing the following Julia function:
|
5145
|
-
# function getclaimpathactionspecs(s::State, player_idx::Int; log=false)
|
5146
|
-
# action_specs = ActionSpec[]
|
5147
|
-
# available_path_statuses = getavailablepaths(s, player_idx)
|
5148
|
-
# paths = map(available_path_statuses) do available_path_status
|
5149
|
-
# (; num, sample_fulfillment) = available_path_status
|
5150
|
-
# fulfillment_sorted = Base.sort(sample_fulfillment; by=x -> x.segment_num)
|
5151
|
-
# sample_fulfillment = [x.unit_card_num for x in fulfillment_sorted]
|
5152
|
-
# fulfillment_str = join(sample_fulfillment, "-")
|
5153
|
-
# PathCombos(num, fulfillment_str, sample_fulfillment)
|
5154
|
-
# end
|
5155
|
-
# if !isempty(paths)
|
5156
|
-
# push!(
|
5157
|
-
# action_specs,
|
5158
|
-
# ActionSpec(
|
5159
|
-
# action_name=CLAIM_PATH,
|
5160
|
-
# player_idx=player_idx,
|
5161
|
-
# paths=paths,
|
5162
|
-
# )
|
5163
|
-
# )
|
5164
|
-
# end
|
5165
|
-
# action_specs
|
5166
|
-
# end
|
5167
|
-
def getclaimpathactionspecs(s, player_idx, log=False):
|
5168
|
-
action_specs = []
|
5169
|
-
available_path_statuses = getavailablepathstatuses(s, player_idx)
|
5170
|
-
|
5171
|
-
def process_path_status(available_path_status):
|
5172
|
-
num = available_path_status.num
|
5173
|
-
sample_fulfillment = available_path_status.sample_fulfillment
|
5174
|
-
fulfillment_sorted = sorted(sample_fulfillment, key=lambda x: x.segment_num)
|
5175
|
-
sample_fulfillment = [x.unit_card_num for x in fulfillment_sorted]
|
5176
|
-
fulfillment_str = '-'.join(map(str, sample_fulfillment))
|
5177
|
-
return PathCombos(
|
5178
|
-
path_idx=(num-1),
|
5179
|
-
default_combo=fulfillment_str,
|
5180
|
-
sample_fulfillment=sample_fulfillment
|
5181
|
-
)
|
5182
|
-
|
5183
|
-
paths = list(map(process_path_status, available_path_statuses))
|
5184
|
-
|
5185
|
-
if paths:
|
5186
|
-
action_specs.append(
|
5187
|
-
ActionSpec(
|
5188
|
-
player_idx=player_idx,
|
5189
|
-
action_name="CLAIM_PATH",
|
5190
|
-
return_route_option_sets = [],
|
5191
|
-
draw_faceup_spots={},
|
5192
|
-
points=[],
|
5193
|
-
paths=paths,
|
5194
|
-
)
|
5195
|
-
)
|
5196
|
-
|
5197
|
-
return action_specs
|
5198
|
-
|
5199
|
-
|
5200
|
-
# Implementing the following Julia function:
|
5201
|
-
# function getavailablepaths(s::State, player_num::Int)
|
5202
|
-
# balance = s.player_hands[player_num].unit_cards
|
5203
|
-
# path_statuses = map(getpotentialpathnums(s, player_num)) do path_num
|
5204
|
-
# getpathstatus(s, player_num, path_num)
|
5205
|
-
# end
|
5206
|
-
# filter(x -> x.fulfillable, path_statuses)
|
5207
|
-
# end
|
5208
|
-
def getavailablepathstatuses(s, player_num):
|
5209
|
-
balance = s.player_hands[player_num].unit_cards
|
5210
|
-
path_statuses = [
|
5211
|
-
getpathstatus(s, player_num, path_idx)
|
5212
|
-
for path_idx in getpotentialpathidxs(s, player_num)
|
5213
|
-
]
|
5214
|
-
return list(filter(lambda x: x.fulfillable, path_statuses))
|
5215
|
-
|
5216
4539
|
|
5217
4540
|
# Implementing the following Julia function:
|
5218
4541
|
# function getpotentialpathnums(s::State, player_num::Int)
|
@@ -5441,409 +4764,9 @@ def getclaimedpathidxs(s):
|
|
5441
4764
|
return claimed
|
5442
4765
|
|
5443
4766
|
|
5444
|
-
# Implementing the following Julia function:
|
5445
|
-
# function getpathstatus(s::State, player_idx, path_num)
|
5446
|
-
# balance = s.player_hands[player_idx].unit_cards
|
5447
|
-
# (; fig) = s
|
5448
|
-
# (; board_config) = fig
|
5449
|
-
# (; deck_units, board_paths) = board_config
|
5450
|
-
# unituuid2deckunit = Dict(x.unit_uuid => x for x in deck_units)
|
5451
|
-
# path = board_paths[path_num]
|
5452
|
-
# ordered_segments = prioritysort(fig, path.path.segments)
|
5453
|
-
# fulfillment = OrderedFullfillment[]
|
5454
|
-
# wild_unit_uuids = getwildunituuids(fig)
|
5455
|
-
# # @show wild_unit_uuids
|
5456
|
-
# non_wild_unit_uuids = getnonwildunituuids(fig)
|
5457
|
-
# # @show non_wild_unit_uuids
|
5458
|
-
|
5459
|
-
# # @show balance
|
5460
|
-
|
5461
|
-
# balance_unituuid2deckcardnums = Dict()
|
5462
|
-
# for deck_card_num in balance
|
5463
|
-
# unit_uuid = getunituuid(fig, deck_card_num)
|
5464
|
-
# if !haskey(balance_unituuid2deckcardnums, unit_uuid)
|
5465
|
-
# balance_unituuid2deckcardnums[unit_uuid] = []
|
5466
|
-
# end
|
5467
|
-
# push!(balance_unituuid2deckcardnums[unit_uuid], deck_card_num)
|
5468
|
-
# end
|
5469
|
-
|
5470
|
-
# # @show balance_unituuid2deckcardnums
|
5471
|
-
|
5472
|
-
# function hasexactunitmatch(unit_uuid)
|
5473
|
-
# (
|
5474
|
-
# haskey(balance_unituuid2deckcardnums, unit_uuid) &&
|
5475
|
-
# length(balance_unituuid2deckcardnums[unit_uuid]) > 0
|
5476
|
-
# )
|
5477
|
-
# end
|
5478
|
-
|
5479
|
-
# function anywildsleft()
|
5480
|
-
# for wild_unit_uuid in wild_unit_uuids
|
5481
|
-
# if haskey(balance_unituuid2deckcardnums, wild_unit_uuid)
|
5482
|
-
# if !isempty(balance_unituuid2deckcardnums[wild_unit_uuid])
|
5483
|
-
# return true
|
5484
|
-
# end
|
5485
|
-
# end
|
5486
|
-
# end
|
5487
|
-
# false
|
5488
|
-
# end
|
5489
|
-
|
5490
|
-
# function gettotalwildcount()
|
5491
|
-
# count = 0
|
5492
|
-
# for wild_unit_uuid in wild_unit_uuids
|
5493
|
-
# if haskey(balance_unituuid2deckcardnums, wild_unit_uuid)
|
5494
|
-
# count += length(balance_unituuid2deckcardnums[wild_unit_uuid])
|
5495
|
-
# end
|
5496
|
-
# end
|
5497
|
-
# count
|
5498
|
-
# end
|
5499
|
-
|
5500
|
-
# function popawildcard!()
|
5501
|
-
# for wild_unit_uuid in wild_unit_uuids
|
5502
|
-
# if haskey(balance_unituuid2deckcardnums, wild_unit_uuid)
|
5503
|
-
# if !isempty(balance_unituuid2deckcardnums[wild_unit_uuid])
|
5504
|
-
# return pop!(balance_unituuid2deckcardnums[wild_unit_uuid])
|
5505
|
-
# end
|
5506
|
-
# end
|
5507
|
-
# end
|
5508
|
-
# nothing
|
5509
|
-
# end
|
5510
|
-
|
5511
|
-
# function getnonemptywildstack()
|
5512
|
-
# for wild_unit_uuid in wild_unit_uuids
|
5513
|
-
# if haskey(balance_unituuid2deckcardnums, wild_unit_uuid)
|
5514
|
-
# if !isempty(balance_unituuid2deckcardnums[wild_unit_uuid])
|
5515
|
-
# return balance_unituuid2deckcardnums[wild_unit_uuid]
|
5516
|
-
# end
|
5517
|
-
# end
|
5518
|
-
# end
|
5519
|
-
# nothing
|
5520
|
-
# end
|
5521
|
-
|
5522
|
-
# function getlargestnonwildstack()
|
5523
|
-
# largest_non_wild_unit_uuid = nothing
|
5524
|
-
# largest_found = 0
|
5525
|
-
# for non_wild_unit_uuid in non_wild_unit_uuids
|
5526
|
-
# if haskey(balance_unituuid2deckcardnums, non_wild_unit_uuid)
|
5527
|
-
# curr_length = length(balance_unituuid2deckcardnums[non_wild_unit_uuid])
|
5528
|
-
# if curr_length > largest_found
|
5529
|
-
# largest_found = curr_length
|
5530
|
-
# largest_non_wild_unit_uuid = non_wild_unit_uuid
|
5531
|
-
# end
|
5532
|
-
# end
|
5533
|
-
# end
|
5534
|
-
# if !isnothing(largest_non_wild_unit_uuid)
|
5535
|
-
# return balance_unituuid2deckcardnums[largest_non_wild_unit_uuid]
|
5536
|
-
# end
|
5537
|
-
# nothing
|
5538
|
-
# end
|
5539
|
-
|
5540
|
-
# for ordered_segment in ordered_segments
|
5541
|
-
# target_segment = ordered_segment.segment
|
5542
|
-
# segment_num = ordered_segment.path_segment_num
|
5543
|
-
# (; unit_uuid) = target_segment
|
5544
|
-
# # @show unit_uuid
|
5545
|
-
# # @show keys(unituuid2deckunit)
|
5546
|
-
# target_unit = isnothing(unit_uuid) ? nothing : unituuid2deckunit[unit_uuid]
|
5547
|
-
# # @show target_unit
|
5548
|
-
|
5549
|
-
# if isnothing(target_unit)
|
5550
|
-
# # do nothing (this is a blank segment)
|
5551
|
-
# elseif target_unit.is_wild
|
5552
|
-
# if hasexactunitmatch(unit_uuid)
|
5553
|
-
# popped = pop!(balance_unituuid2deckcardnums[unit_uuid])
|
5554
|
-
# push!(fulfillment, OrderedFullfillment(segment_num, popped))
|
5555
|
-
# end
|
5556
|
-
# else
|
5557
|
-
# # @show 3
|
5558
|
-
# if hasexactunitmatch(unit_uuid)
|
5559
|
-
# # @show 4
|
5560
|
-
# popped = pop!(balance_unituuid2deckcardnums[unit_uuid])
|
5561
|
-
# push!(fulfillment, OrderedFullfillment(segment_num, popped))
|
5562
|
-
# elseif anywildsleft()
|
5563
|
-
# # @show 5
|
5564
|
-
# non_empty_wild_stack = getnonemptywildstack()
|
5565
|
-
# popped = pop!(non_empty_wild_stack)
|
5566
|
-
# push!(fulfillment, OrderedFullfillment(segment_num, popped))
|
5567
|
-
# end
|
5568
|
-
# end
|
5569
|
-
# end
|
5570
|
-
|
5571
|
-
# blank_remaining_segments = filter(
|
5572
|
-
# ordered_segment -> isblank(ordered_segment.segment.unit_uuid),
|
5573
|
-
# ordered_segments,
|
5574
|
-
# )
|
5575
|
-
# # @show blank_remaining_segments
|
5576
|
-
# largest_non_wild_stack = getlargestnonwildstack()
|
5577
|
-
# # @show largest_non_wild_stack
|
5578
|
-
# for blank_remaining_segment in blank_remaining_segments
|
5579
|
-
# if !isnothing(largest_non_wild_stack) && !isempty(largest_non_wild_stack)
|
5580
|
-
# popped = pop!(largest_non_wild_stack)
|
5581
|
-
# push!(fulfillment, OrderedFullfillment(blank_remaining_segment.path_segment_num, popped))
|
5582
|
-
# elseif gettotalwildcount() > 0
|
5583
|
-
# popped = popawildcard!()
|
5584
|
-
# push!(fulfillment, OrderedFullfillment(blank_remaining_segment.path_segment_num, popped))
|
5585
|
-
# end
|
5586
|
-
# end
|
5587
|
-
|
5588
|
-
# # @show fulfillment
|
5589
|
-
# deepq_edges = map(ordered_segments) do ordered_segment
|
5590
|
-
# (; path_segment_num) = ordered_segment
|
5591
|
-
# (; segment) = ordered_segment
|
5592
|
-
# fullfillable_by_me = in(path_segment_num, [x.segment_num for x in fulfillment])
|
5593
|
-
# captured_by_me = in(path_num, s.player_hands[player_idx].paths)
|
5594
|
-
# captured_by_other = !captured_by_me && in(path_num, getclaimedpathidxs(s))
|
5595
|
-
# available_to_me = !(captured_by_me || captured_by_other) && fullfillable_by_me
|
5596
|
-
# status = "Other"
|
5597
|
-
# if captured_by_me
|
5598
|
-
# status = "CapturedByMe"
|
5599
|
-
# elseif captured_by_other
|
5600
|
-
# status = "CapturedByOther"
|
5601
|
-
# elseif available_to_me
|
5602
|
-
# status = "AvailableToMe"
|
5603
|
-
# end
|
5604
|
-
# SegmentStatus(
|
5605
|
-
# path_num,
|
5606
|
-
# path_segment_num,
|
5607
|
-
# captured_by_me,
|
5608
|
-
# captured_by_other,
|
5609
|
-
# available_to_me,
|
5610
|
-
# status,
|
5611
|
-
# segment,
|
5612
|
-
# )
|
5613
|
-
# end
|
5614
|
-
|
5615
|
-
# fulfillable = Base.all([x.available_to_me for x in deepq_edges])
|
5616
|
-
# PathStatus(path_num, fulfillable, deepq_edges, fulfillment)
|
5617
|
-
# end
|
5618
|
-
def getpathstatus(s, player_idx, path_idx):
|
5619
|
-
path_num = path_idx + 1
|
5620
|
-
balance = s.player_hands[player_idx].unit_cards
|
5621
|
-
fig = s.game_config.fig
|
5622
|
-
board_config = fig.board_config
|
5623
|
-
deck_units = board_config.deck_units
|
5624
|
-
board_paths = board_config.board_paths
|
5625
|
-
unituuid2deckunit = {x.unit_uuid: x for x in deck_units}
|
5626
|
-
path = board_paths[path_idx]
|
5627
|
-
ordered_segments = prioritysort(fig, path.path.segments)
|
5628
|
-
fulfillment = []
|
5629
|
-
wild_unit_uuids = getwildunituuids(fig)
|
5630
|
-
non_wild_unit_uuids = getnonwildunituuids(fig)
|
5631
|
-
|
5632
|
-
balance_unituuid2deckcardnums = {}
|
5633
|
-
|
5634
|
-
for deck_card_num in balance:
|
5635
|
-
unit_uuid = getunituuid(fig, deck_card_num)
|
5636
|
-
if unit_uuid not in balance_unituuid2deckcardnums:
|
5637
|
-
balance_unituuid2deckcardnums[unit_uuid] = []
|
5638
|
-
balance_unituuid2deckcardnums[unit_uuid].append(deck_card_num)
|
5639
|
-
|
5640
|
-
def hasexactunitmatch(unit_uuid):
|
5641
|
-
# print("unit_uuid: ", unit_uuid)
|
5642
|
-
# print("balance_unituuid2deckcardnums: ", balance_unituuid2deckcardnums)
|
5643
|
-
print("")
|
5644
|
-
return (
|
5645
|
-
unit_uuid in balance_unituuid2deckcardnums and
|
5646
|
-
len(balance_unituuid2deckcardnums[unit_uuid]) > 0
|
5647
|
-
)
|
5648
|
-
|
5649
|
-
def anywildsleft():
|
5650
|
-
for wild_unit_uuid in wild_unit_uuids:
|
5651
|
-
if wild_unit_uuid in balance_unituuid2deckcardnums:
|
5652
|
-
if balance_unituuid2deckcardnums[wild_unit_uuid]:
|
5653
|
-
return True
|
5654
|
-
return False
|
5655
|
-
|
5656
|
-
def gettotalwildcount():
|
5657
|
-
count = 0
|
5658
|
-
for wild_unit_uuid in wild_unit_uuids:
|
5659
|
-
if wild_unit_uuid in balance_unituuid2deckcardnums:
|
5660
|
-
count += len(balance_unituuid2deckcardnums[wild_unit_uuid])
|
5661
|
-
return count
|
5662
|
-
|
5663
|
-
def popawildcard():
|
5664
|
-
for wild_unit_uuid in wild_unit_uuids:
|
5665
|
-
if wild_unit_uuid in balance_unituuid2deckcardnums:
|
5666
|
-
if balance_unituuid2deckcardnums[wild_unit_uuid]:
|
5667
|
-
return balance_unituuid2deckcardnums[wild_unit_uuid].pop()
|
5668
|
-
return None
|
5669
4767
|
|
5670
|
-
def getnonemptywildstack():
|
5671
|
-
for wild_unit_uuid in wild_unit_uuids:
|
5672
|
-
if wild_unit_uuid in balance_unituuid2deckcardnums:
|
5673
|
-
if balance_unituuid2deckcardnums[wild_unit_uuid]:
|
5674
|
-
return balance_unituuid2deckcardnums[wild_unit_uuid]
|
5675
|
-
return None
|
5676
4768
|
|
5677
|
-
def getlargestnonwildstack():
|
5678
|
-
largest_non_wild_unit_uuid = None
|
5679
|
-
largest_found = 0
|
5680
|
-
for non_wild_unit_uuid in non_wild_unit_uuids:
|
5681
|
-
if non_wild_unit_uuid in balance_unituuid2deckcardnums:
|
5682
|
-
curr_length = len(balance_unituuid2deckcardnums[non_wild_unit_uuid])
|
5683
|
-
if curr_length > largest_found:
|
5684
|
-
largest_found = curr_length
|
5685
|
-
largest_non_wild_unit_uuid = non_wild_unit_uuid
|
5686
|
-
if largest_non_wild_unit_uuid is not None:
|
5687
|
-
return balance_unituuid2deckcardnums[largest_non_wild_unit_uuid]
|
5688
|
-
return None
|
5689
|
-
|
5690
|
-
for ordered_segment in ordered_segments:
|
5691
|
-
target_segment = ordered_segment.segment
|
5692
|
-
segment_num = ordered_segment.path_segment_num
|
5693
|
-
unit_uuid = target_segment.unit_uuid
|
5694
|
-
target_unit = None if unit_uuid is None else unituuid2deckunit[unit_uuid]
|
5695
|
-
|
5696
|
-
if target_unit is None:
|
5697
|
-
# do nothing (this is a blank segment)
|
5698
|
-
pass
|
5699
|
-
elif target_unit.is_wild:
|
5700
|
-
if hasexactunitmatch(unit_uuid):
|
5701
|
-
popped = balance_unituuid2deckcardnums[unit_uuid].pop()
|
5702
|
-
fulfillment.append(OrderedFullfillment(segment_num=segment_num, unit_card_num=popped))
|
5703
|
-
else:
|
5704
|
-
# print("anywildsleft(): ", anywildsleft())
|
5705
|
-
if hasexactunitmatch(unit_uuid):
|
5706
|
-
popped = balance_unituuid2deckcardnums[unit_uuid].pop()
|
5707
|
-
fulfillment.append(OrderedFullfillment(segment_num=segment_num, unit_card_num=popped))
|
5708
|
-
elif anywildsleft():
|
5709
|
-
non_empty_wild_stack = getnonemptywildstack()
|
5710
|
-
popped = non_empty_wild_stack.pop()
|
5711
|
-
fulfillment.append(OrderedFullfillment(segment_num=segment_num, unit_card_num=popped))
|
5712
|
-
# @show 5
|
5713
|
-
|
5714
|
-
blank_remaining_segments = list(filter(
|
5715
|
-
lambda ordered_segment: ordered_segment.segment.unit_uuid is None,
|
5716
|
-
ordered_segments,
|
5717
|
-
))
|
5718
|
-
|
5719
|
-
largest_non_wild_stack = getlargestnonwildstack()
|
5720
|
-
|
5721
|
-
for blank_remaining_segment in blank_remaining_segments:
|
5722
|
-
if largest_non_wild_stack is not None and largest_non_wild_stack:
|
5723
|
-
popped = largest_non_wild_stack.pop()
|
5724
|
-
fulfillment.append(OrderedFullfillment(segment_num=blank_remaining_segment.path_segment_num, unit_card_num=popped))
|
5725
|
-
elif gettotalwildcount() > 0:
|
5726
|
-
popped = popawildcard()
|
5727
|
-
fulfillment.append(OrderedFullfillment(segment_num=blank_remaining_segment.path_segment_num, unit_card_num=popped))
|
5728
|
-
|
5729
|
-
# Implementing the following Julia code:
|
5730
|
-
# deepq_edges = map(ordered_segments) do ordered_segment
|
5731
|
-
# (; path_segment_num) = ordered_segment
|
5732
|
-
# (; segment) = ordered_segment
|
5733
|
-
# fullfillable_by_me = in(path_segment_num, [x.segment_num for x in fulfillment])
|
5734
|
-
# captured_by_me = in(path_num, s.player_hands[player_idx].paths)
|
5735
|
-
# captured_by_other = !captured_by_me && in(path_num, getclaimedpathidxs(s))
|
5736
|
-
# available_to_me = !(captured_by_me || captured_by_other) && fullfillable_by_me
|
5737
|
-
# status = "Other"
|
5738
|
-
# if captured_by_me
|
5739
|
-
# status = "CapturedByMe"
|
5740
|
-
# elseif captured_by_other
|
5741
|
-
# status = "CapturedByOther"
|
5742
|
-
# elseif available_to_me
|
5743
|
-
# status = "AvailableToMe"
|
5744
|
-
# end
|
5745
|
-
# SegmentStatus(
|
5746
|
-
# path_num,
|
5747
|
-
# path_segment_num,
|
5748
|
-
# captured_by_me,
|
5749
|
-
# captured_by_other,
|
5750
|
-
# available_to_me,
|
5751
|
-
# status,
|
5752
|
-
# segment,
|
5753
|
-
# )
|
5754
|
-
# end
|
5755
|
-
# fulfillable = Base.all([x.available_to_me for x in deepq_edges])
|
5756
|
-
# PathStatus(path_num, fulfillable, deepq_edges, fulfillment)
|
5757
|
-
deepq_edges = []
|
5758
|
-
for ordered_segment in ordered_segments:
|
5759
|
-
path_segment_num = ordered_segment.path_segment_num
|
5760
|
-
segment = ordered_segment.segment
|
5761
|
-
fullfillable_by_me = path_segment_num in [x.segment_num for x in fulfillment]
|
5762
|
-
captured_by_me = path_idx in s.player_hands[player_idx].paths
|
5763
|
-
captured_by_other = not captured_by_me and path_idx in getclaimedpathidxs(s)
|
5764
|
-
available_to_me = not (captured_by_me or captured_by_other) and fullfillable_by_me
|
5765
|
-
status = "Other"
|
5766
|
-
if captured_by_me:
|
5767
|
-
status = "CapturedByMe"
|
5768
|
-
elif captured_by_other:
|
5769
|
-
status = "CapturedByOther"
|
5770
|
-
elif available_to_me:
|
5771
|
-
status = "AvailableToMe"
|
5772
|
-
|
5773
|
-
deepq_edges.append(
|
5774
|
-
SegmentStatus(
|
5775
|
-
path_idx=path_idx,
|
5776
|
-
path_num=path_num,
|
5777
|
-
path_segment_num=path_segment_num,
|
5778
|
-
captured_by_me=captured_by_me,
|
5779
|
-
captured_by_other=captured_by_other,
|
5780
|
-
available_to_me=available_to_me,
|
5781
|
-
status=status,
|
5782
|
-
segment=segment
|
5783
|
-
)
|
5784
|
-
)
|
5785
|
-
|
5786
|
-
fulfillable = all([x.available_to_me for x in deepq_edges])
|
5787
|
-
return PathStatus(
|
5788
|
-
idx=path_idx,
|
5789
|
-
num=path_num,
|
5790
|
-
fulfillable=fulfillable,
|
5791
|
-
segment_statuses=deepq_edges,
|
5792
|
-
sample_fulfillment=fulfillment
|
5793
|
-
)
|
5794
|
-
|
5795
|
-
|
5796
|
-
# Implementing the following Julia function:
|
5797
|
-
# function getavailablepoints(s::State, player_num::Int)
|
5798
|
-
# point_statuses = map(getpotentialpointuuids(s, player_num)) do point_uuid
|
5799
|
-
# getpointstatus(s, player_num, point_uuid)
|
5800
|
-
# end
|
5801
|
-
# sort(filter(x -> x.fulfillable, point_statuses); by=x -> x.uuid)
|
5802
|
-
# end
|
5803
|
-
def getavailablepoints(s, player_num):
|
5804
|
-
point_statuses = [
|
5805
|
-
getpointstatus(s, player_num, point_uuid)
|
5806
|
-
for point_uuid in getpotentialpointuuids(s, player_num)
|
5807
|
-
]
|
5808
|
-
return sorted(
|
5809
|
-
filter(lambda x: x['fulfillable'], point_statuses),
|
5810
|
-
key=lambda x: x['uuid']
|
5811
|
-
)
|
5812
|
-
|
5813
|
-
# Implementing the following Julia function:
|
5814
|
-
# function getpointstatus(s::State, player_idx::Int, point_uuid::UUID)
|
5815
|
-
# balance = s.player_hands[player_idx].unit_cards
|
5816
|
-
# fulfillment = OrderedPointFullfillment[]
|
5817
|
-
# if !isempty(balance)
|
5818
|
-
# push!(fulfillment, OrderedPointFullfillment(balance[1]))
|
5819
|
-
# end
|
5820
|
-
# PointStatus(point_uuid, true, fulfillment)
|
5821
|
-
# end
|
5822
|
-
def getpointstatus(s, player_idx, point_uuid):
|
5823
|
-
balance = s.player_hands[player_idx].unit_cards
|
5824
|
-
fulfillment = []
|
5825
|
-
if balance:
|
5826
|
-
fulfillment.append({'unit_card_num': balance[0]})
|
5827
|
-
return {
|
5828
|
-
'uuid': point_uuid,
|
5829
|
-
'fulfillable': True,
|
5830
|
-
'sample_fulfillment': fulfillment
|
5831
|
-
}
|
5832
4769
|
|
5833
|
-
# Implementing the following Julia function:
|
5834
|
-
# function getpotentialpointuuids(s::State, player_num::Int)
|
5835
|
-
# (; num_point_pieces) = s.player_hands[player_num]
|
5836
|
-
# setdiff(
|
5837
|
-
# Set(getnodeuuids(s.fig, num_point_pieces)),
|
5838
|
-
# Set(getunavailablepoints(s)),
|
5839
|
-
# ) |> collect
|
5840
|
-
# end
|
5841
|
-
def getpotentialpointuuids(s, player_num):
|
5842
|
-
num_point_pieces = s.player_hands[player_num].num_point_pieces
|
5843
|
-
return list(
|
5844
|
-
set(getnodeuuids(s.game_config.fig, num_point_pieces)) -
|
5845
|
-
set(getunavailablepoints(s))
|
5846
|
-
)
|
5847
4770
|
|
5848
4771
|
# Implementing the following Julia function:
|
5849
4772
|
# function getnodeuuids(f::Fig, remaining_pieces::Int)
|
@@ -5880,33 +4803,6 @@ def getunavailablepoints(s):
|
|
5880
4803
|
return unavailable_points
|
5881
4804
|
|
5882
4805
|
|
5883
|
-
# Implementing the following Julia function:
|
5884
|
-
# function calcfinalscores(s::State)
|
5885
|
-
# if !s.terminal
|
5886
|
-
# return s
|
5887
|
-
# end
|
5888
|
-
# @reset s.player_hands = calcfinalscore.(s, s.player_hands)
|
5889
|
-
# s
|
5890
|
-
# end
|
5891
|
-
@dispatch(State)
|
5892
|
-
def calcfinalscores(s):
|
5893
|
-
if not s.terminal:
|
5894
|
-
return s
|
5895
|
-
return s.set(player_hands=pvector([calcfinalscore(s, h) for h in s.player_hands]))
|
5896
|
-
|
5897
|
-
|
5898
|
-
# Implementing the following Julia function:
|
5899
|
-
# function calcfinalscore(s::State, hand::PlayerInfo)
|
5900
|
-
# (; total, breakdown) = getprivatescore(s, hand)
|
5901
|
-
# @reset hand.final_score = PlayerScore(total, breakdown)
|
5902
|
-
# hand
|
5903
|
-
# end
|
5904
|
-
@dispatch(State, PlayerInfo)
|
5905
|
-
def calcfinalscore(s, hand):
|
5906
|
-
total, breakdown = getprivatescore(s, hand)
|
5907
|
-
return hand.set(final_score=PlayerScore(total=total, breakdown=breakdown))
|
5908
|
-
|
5909
|
-
|
5910
4806
|
# Implementing the following Julia function:
|
5911
4807
|
# function calcwinners(s::State)
|
5912
4808
|
# if !s.terminal
|
@@ -5930,172 +4826,15 @@ def calcwinners(s):
|
|
5930
4826
|
|
5931
4827
|
|
5932
4828
|
def printplayer(s, player_idx):
|
5933
|
-
|
5934
|
-
legal_actions = getlegalactionspecs(s, player_idx)
|
5935
|
-
print(f"~~~~~~~~~~~~ P{player_idx} ~~~~~~~~~~~~")
|
5936
|
-
print(f"private score: {getprivatescore(s, hand)}")
|
5937
|
-
print(f"public score: {getpublicscore(s, player_idx)}")
|
5938
|
-
print(f"completed clusters: {list(str(c) for c in hand.completed_clusters)}")
|
5939
|
-
print(f"units: {list(hand.unit_cards)}")
|
5940
|
-
if getsettingvalue(s, "route_scoring"):
|
5941
|
-
print(f"routes: {list(hand.route_cards)} choices:{list(hand.new_route_cards)}")
|
5942
|
-
print(f"captured points: {list(str(p) for p in hand.points)}")
|
5943
|
-
print(f"legal actions: {list(a.action_name for a in legal_actions)}")
|
4829
|
+
pass
|
5944
4830
|
|
5945
4831
|
|
5946
4832
|
def printstate(s):
|
5947
|
-
|
5948
|
-
print(f"Last to play: {s.last_to_play}")
|
5949
|
-
print(f"Winners: {list(s.winners)}")
|
5950
|
-
print(f"Route Deck: {list(s.route_cards)}")
|
5951
|
-
print(f"Route Disc: {list(s.route_discards)}")
|
5952
|
-
print(f"Unit Deck: ...{list(s.unit_cards[60:])}")
|
5953
|
-
print(f"Unit Disc: {list(s.unit_discards)}")
|
5954
|
-
print(f"FaceUp: {list(s.faceup_spots)}")
|
5955
|
-
print(f"ToPlay: {gettoplay(s)}")
|
5956
|
-
print(f"Terminal: {s.terminal}")
|
5957
|
-
|
5958
|
-
for i in range(s.game_config.num_players):
|
5959
|
-
printplayer(s, i)
|
5960
|
-
print(f"****************************************\n")
|
4833
|
+
pass
|
5961
4834
|
|
5962
4835
|
|
5963
4836
|
def printaction(a, i):
|
5964
|
-
|
5965
|
-
print(f"{a}")
|
5966
|
-
print(f"****************************************\n\n\n")
|
5967
|
-
|
5968
|
-
|
5969
|
-
# Implementing the following Julia function:
|
5970
|
-
# function getprivatescore(s::State, hand::PlayerInfo; bonus=true)
|
5971
|
-
# player_idx = hand.player_idx
|
5972
|
-
# breakdown = []
|
5973
|
-
|
5974
|
-
# # Path scores
|
5975
|
-
# if getsettingvalue(s, :path_scoring)
|
5976
|
-
# (; path_scores) = s.fig
|
5977
|
-
# for len in getplayerpathlens(s, player_idx)
|
5978
|
-
# push!(
|
5979
|
-
# breakdown,
|
5980
|
-
# ScoreItem(
|
5981
|
-
# code_idx=getscorecodeidx(s.fig, :PATH),
|
5982
|
-
# amount=path_scores[len],
|
5983
|
-
# )
|
5984
|
-
# )
|
5985
|
-
# end
|
5986
|
-
# end
|
5987
|
-
|
5988
|
-
# # Bonus: most clusters
|
5989
|
-
# if getsettingvalue(s, :most_clusters_bonus)
|
5990
|
-
# bonus_most_clusters_score = getsettingvalue(s.fig, :bonus_most_clusters_score)
|
5991
|
-
# if in(player_idx, s.most_clusters_player_idxs)
|
5992
|
-
# push!(
|
5993
|
-
# breakdown,
|
5994
|
-
# ScoreItem(
|
5995
|
-
# code_idx=getscorecodeidx(s.fig, :MOST_CLUSTERS),
|
5996
|
-
# amount=bonus_most_clusters_score,
|
5997
|
-
# )
|
5998
|
-
# )
|
5999
|
-
# end
|
6000
|
-
# end
|
6001
|
-
|
6002
|
-
# # Longest trail
|
6003
|
-
# if !getsettingvalue(s, :disable_longest_path_bonus)
|
6004
|
-
# longest_path_score = getsettingvalue(s.fig, :longest_path_score)
|
6005
|
-
# if in(player_idx, s.longest_trail_player_idxs)
|
6006
|
-
# push!(
|
6007
|
-
# breakdown,
|
6008
|
-
# ScoreItem(
|
6009
|
-
# code_idx=getscorecodeidx(s.fig, :LONGEST_ROAD),
|
6010
|
-
# amount=longest_path_score,
|
6011
|
-
# )
|
6012
|
-
# )
|
6013
|
-
# end
|
6014
|
-
# end
|
6015
|
-
|
6016
|
-
# # Completed routes
|
6017
|
-
# if getsettingvalue(s, :route_scoring)
|
6018
|
-
# hand = s.player_hands[player_idx]
|
6019
|
-
# (; board_config) = s.fig
|
6020
|
-
# (; routes) = board_config
|
6021
|
-
# for route_idx in hand.route_cards
|
6022
|
-
# route_score = routes[route_idx].score
|
6023
|
-
# amount = in(route_idx, hand.completed_routes) ? route_score : -1*route_score
|
6024
|
-
# push!(
|
6025
|
-
# breakdown,
|
6026
|
-
# ScoreItem(
|
6027
|
-
# code_idx=getscorecodeidx(s.fig, :ROUTE),
|
6028
|
-
# amount=amount
|
6029
|
-
# )
|
6030
|
-
# )
|
6031
|
-
# end
|
6032
|
-
# end
|
6033
|
-
|
6034
|
-
# # Completed clusters
|
6035
|
-
# if getsettingvalue(s, :cluster_scoring)
|
6036
|
-
# (; clusters) = s.fig.board_config
|
6037
|
-
# uuid2cluster = Dict((x.uuid, x) for x in clusters)
|
6038
|
-
# (; completed_clusters) = s.player_hands[player_idx]
|
6039
|
-
# cluster_scores = map(completed_clusters) do cluster_uuid
|
6040
|
-
# uuid2cluster[cluster_uuid].score
|
6041
|
-
# end
|
6042
|
-
# if !isempty(cluster_scores)
|
6043
|
-
# push!(breakdown,
|
6044
|
-
# ScoreItem(
|
6045
|
-
# code_idx=getscorecodeidx(s.fig, :CLUSTER),
|
6046
|
-
# amount=sum(cluster_scores)
|
6047
|
-
# )
|
6048
|
-
# )
|
6049
|
-
# end
|
6050
|
-
# end
|
6051
|
-
|
6052
|
-
# amounts = [item.amount for item in breakdown]
|
6053
|
-
# total = sum(amounts; init=0)
|
6054
|
-
# (
|
6055
|
-
# total=total,
|
6056
|
-
# breakdown=breakdown,
|
6057
|
-
# )
|
6058
|
-
# end
|
6059
|
-
@dispatch(State, PlayerInfo)
|
6060
|
-
def getprivatescore(s, hand):
|
6061
|
-
player_idx = hand.player_idx
|
6062
|
-
breakdown = []
|
6063
|
-
|
6064
|
-
# Path scores
|
6065
|
-
if getsettingvalue(s, 'path_scoring'):
|
6066
|
-
path_scores = s.game_config.fig.path_scores
|
6067
|
-
for len in getplayerpathlens(s, player_idx):
|
6068
|
-
breakdown.append(ScoreItem(
|
6069
|
-
code_idx=getscorecodeidx(s.game_config.fig, 'PATH'),
|
6070
|
-
amount=path_scores[len],
|
6071
|
-
))
|
6072
|
-
|
6073
|
-
# Completed routes
|
6074
|
-
if False and getsettingvalue(s, 'route_scoring'):
|
6075
|
-
routes = s.game_config.fig.board_config.routes
|
6076
|
-
for route_idx in hand.route_cards:
|
6077
|
-
route_score = routes[route_idx].score
|
6078
|
-
amount = route_score if route_idx in hand.completed_routes else -1 * route_score
|
6079
|
-
breakdown.append(ScoreItem(
|
6080
|
-
code_idx=getscorecodeidx(s.game_config.fig, 'ROUTE'),
|
6081
|
-
amount=amount
|
6082
|
-
))
|
6083
|
-
|
6084
|
-
# Completed clusters
|
6085
|
-
if getsettingvalue(s, 'cluster_scoring'):
|
6086
|
-
clusters = s.game_config.fig.board_config.clusters
|
6087
|
-
uuid2cluster = {x.uuid: x for x in clusters}
|
6088
|
-
completed_clusters = hand.completed_clusters
|
6089
|
-
cluster_scores = [uuid2cluster[cluster_uuid].score for cluster_uuid in completed_clusters]
|
6090
|
-
if cluster_scores:
|
6091
|
-
breakdown.append(ScoreItem(
|
6092
|
-
code_idx=getscorecodeidx(s.game_config.fig, 'CLUSTER'),
|
6093
|
-
amount=sum(cluster_scores)
|
6094
|
-
))
|
6095
|
-
|
6096
|
-
amounts = [item.amount for item in breakdown]
|
6097
|
-
total = sum(amounts)
|
6098
|
-
return total, breakdown
|
4837
|
+
pass
|
6099
4838
|
|
6100
4839
|
|
6101
4840
|
# Implementing the following Julia function:
|
@@ -6134,46 +4873,6 @@ def getscorecodes(f):
|
|
6134
4873
|
return score_codes
|
6135
4874
|
|
6136
4875
|
|
6137
|
-
# Implementing the following Julia function:
|
6138
|
-
# function assertunitcardsaccountedfor(s::State)
|
6139
|
-
# total_num_unit_cards = gettotaldeckcards(s.fig)
|
6140
|
-
# total_found = getunitcardstotalfound(s)
|
6141
|
-
# @assert total_num_unit_cards == total_found "Unit cards not accounted for. $(total_num_unit_cards) != $(total_found)"
|
6142
|
-
# end
|
6143
|
-
def assertunitcardsaccountedfor(s):
|
6144
|
-
total_num_unit_cards = gettotaldeckcards(s.game_config.fig)
|
6145
|
-
total_found = getunitcardstotalfound(s)
|
6146
|
-
assert total_num_unit_cards == total_found, f"Unit cards not accounted for. {total_num_unit_cards} != {total_found}"
|
6147
|
-
|
6148
|
-
|
6149
|
-
# Implementing the following Julia function:
|
6150
|
-
# function getunitcardstotalfound(s::State)
|
6151
|
-
# num_player_unit_cards = sum(gettotalnumunitcards.(s.player_hands))
|
6152
|
-
# total_found = sum([
|
6153
|
-
# num_player_unit_cards,
|
6154
|
-
# length(s.unit_discards),
|
6155
|
-
# length(s.unit_cards),
|
6156
|
-
# length(getvalidspotnums(s)),
|
6157
|
-
# ])
|
6158
|
-
# total_found
|
6159
|
-
# end
|
6160
|
-
def getunitcardstotalfound(s):
|
6161
|
-
num_player_unit_cards = sum(gettotalnumunitcards(p) for p in s.player_hands)
|
6162
|
-
total_found = sum([
|
6163
|
-
num_player_unit_cards,
|
6164
|
-
len(s.unit_discards),
|
6165
|
-
len(s.unit_cards),
|
6166
|
-
len(getvalidspotnums(s)),
|
6167
|
-
])
|
6168
|
-
return total_found
|
6169
|
-
|
6170
|
-
|
6171
|
-
# Implementing the following Julia function:
|
6172
|
-
# gettotalnumunitcards(player_hand::PlayerInfo) = length(player_hand.unit_cards)
|
6173
|
-
def gettotalnumunitcards(player_hand):
|
6174
|
-
return len(player_hand.unit_cards)
|
6175
|
-
|
6176
|
-
|
6177
4876
|
# Implementing the following Julia function:
|
6178
4877
|
# function getvalidspotnums(s::State)
|
6179
4878
|
# filter(n -> !isnothing(s.faceup_spots[n]), 1:length(s.faceup_spots))
|
@@ -6182,44 +4881,6 @@ def getvalidspotnums(s):
|
|
6182
4881
|
return [n for n in range(1, len(s.faceup_spots) + 1) if s.faceup_spots[n-1] is not None]
|
6183
4882
|
|
6184
4883
|
|
6185
|
-
# Implementing the following Julia function:
|
6186
|
-
# function assertroutecardsaccountedfor(s::State)
|
6187
|
-
# total_num_route_cards = getnumroutecards(s.fig)
|
6188
|
-
# num_player_route_cards = sum(gettotalnumroutecards.(s.player_hands))
|
6189
|
-
# total_found = sum([
|
6190
|
-
# num_player_route_cards,
|
6191
|
-
# length(s.route_discards),
|
6192
|
-
# length(s.route_cards),
|
6193
|
-
# ])
|
6194
|
-
# @assert total_num_route_cards == total_found "Route cards not accounted for. $(total_num_route_cards) != $(total_found)"
|
6195
|
-
# end
|
6196
|
-
def assertroutecardsaccountedfor(s):
|
6197
|
-
total_num_route_cards = getnumroutecards(s.game_config.fig)
|
6198
|
-
num_player_route_cards = sum(gettotalnumroutecards(p) for p in s.player_hands)
|
6199
|
-
total_found = sum([
|
6200
|
-
num_player_route_cards,
|
6201
|
-
len(s.route_discards),
|
6202
|
-
len(s.route_cards),
|
6203
|
-
])
|
6204
|
-
assert total_num_route_cards == total_found, f"Route cards not accounted for. {total_num_route_cards} != {total_found}"
|
6205
|
-
|
6206
|
-
|
6207
|
-
# Implementing the following Julia function:
|
6208
|
-
# gettotalnumroutecards(player_hand::PlayerInfo) = length(player_hand.route_cards) + length(player_hand.new_route_cards)
|
6209
|
-
def gettotalnumroutecards(player_hand):
|
6210
|
-
return len(player_hand.route_cards) + len(player_hand.new_route_cards)
|
6211
|
-
|
6212
|
-
|
6213
|
-
# Implementing the following Julia function:
|
6214
|
-
# function assertallcardsaccountedfor(s::State)
|
6215
|
-
# assertroutecardsaccountedfor(s)
|
6216
|
-
# assertunitcardsaccountedfor(s)
|
6217
|
-
# end
|
6218
|
-
def assertallcardsaccountedfor(s):
|
6219
|
-
assertroutecardsaccountedfor(s)
|
6220
|
-
assertunitcardsaccountedfor(s)
|
6221
|
-
|
6222
|
-
|
6223
4884
|
# Implementing the following Julia function:
|
6224
4885
|
# function getlegalactions(s::State)
|
6225
4886
|
# getlegalactions(s, gettoplay(s))
|
@@ -6245,74 +4906,6 @@ def getlegalactionspecs(s, player_idxs):
|
|
6245
4906
|
return legal_actions
|
6246
4907
|
|
6247
4908
|
|
6248
|
-
# Implementing the following Julia function:
|
6249
|
-
# function getcapturedsegments(s::State)
|
6250
|
-
# (; fig) = s
|
6251
|
-
# (; board_config) = fig
|
6252
|
-
# public_player_hands = PublicPlayerInfo.(s, s.player_hands)
|
6253
|
-
# (; board_paths) = board_config
|
6254
|
-
# captured_segments = CapturedSegment[]
|
6255
|
-
# for (player_num, player_hand) in enumerate(public_player_hands)
|
6256
|
-
# for path_num in player_hand.paths
|
6257
|
-
# link_path = board_paths[path_num].path
|
6258
|
-
# for segment in link_path.segments
|
6259
|
-
# captured_segment = CapturedSegment(
|
6260
|
-
# player_num,
|
6261
|
-
# segment.uuid,
|
6262
|
-
# )
|
6263
|
-
# push!(captured_segments, captured_segment)
|
6264
|
-
# end
|
6265
|
-
# end
|
6266
|
-
# end
|
6267
|
-
# captured_segments
|
6268
|
-
# end
|
6269
|
-
@dispatch(State)
|
6270
|
-
def getcapturedsegments(s):
|
6271
|
-
public_player_hands = [getpublicplayerinfo(s, p) for p in s.player_hands]
|
6272
|
-
board_paths = s.game_config.fig.board_config.board_paths
|
6273
|
-
captured_segments = []
|
6274
|
-
for player_idx, player_hand in enumerate(public_player_hands):
|
6275
|
-
for path_idx in player_hand.paths:
|
6276
|
-
link_path = board_paths[path_idx].path
|
6277
|
-
for segment in link_path.segments:
|
6278
|
-
captured_segment = CapturedSegment(
|
6279
|
-
player_num=(player_idx+1),
|
6280
|
-
segment_uuid=segment.uuid,
|
6281
|
-
)
|
6282
|
-
captured_segments.append(captured_segment)
|
6283
|
-
return captured_segments
|
6284
|
-
|
6285
|
-
|
6286
|
-
# Implementing the following Julia function:
|
6287
|
-
# function getcapturedpoints(s::State)
|
6288
|
-
# (; fig) = s
|
6289
|
-
# public_player_hands = PublicPlayerInfo.(s, s.player_hands)
|
6290
|
-
# captured_points = CapturedPoint[]
|
6291
|
-
# for (player_num, player_hand) in enumerate(public_player_hands)
|
6292
|
-
# for point_uuid in player_hand.points
|
6293
|
-
# captured_point = CapturedPoint(
|
6294
|
-
# player_num,
|
6295
|
-
# point_uuid,
|
6296
|
-
# )
|
6297
|
-
# push!(captured_points, captured_point)
|
6298
|
-
# end
|
6299
|
-
# end
|
6300
|
-
# captured_points
|
6301
|
-
# end
|
6302
|
-
@dispatch(State)
|
6303
|
-
def getcapturedpoints(s):
|
6304
|
-
public_player_hands = [getpublicplayerinfo(s, p) for p in s.player_hands]
|
6305
|
-
captured_points = []
|
6306
|
-
for player_idx, player_hand in enumerate(public_player_hands):
|
6307
|
-
for point_uuid in player_hand.points:
|
6308
|
-
captured_point = CapturedPoint(
|
6309
|
-
player_num=player_idx+1,
|
6310
|
-
point_uuid=point_uuid,
|
6311
|
-
)
|
6312
|
-
captured_points.append(captured_point)
|
6313
|
-
return captured_points
|
6314
|
-
|
6315
|
-
|
6316
4909
|
def json_serializer(obj):
|
6317
4910
|
if isinstance(obj, set):
|
6318
4911
|
return list(obj)
|
@@ -6374,7 +4967,6 @@ def getprivatestate(s, player_idx):
|
|
6374
4967
|
player=s.players[player_idx],
|
6375
4968
|
legal_actions_2 = get_legal_actions(s, player_idx),
|
6376
4969
|
legal_actions=legal_actions,
|
6377
|
-
hand=s.player_hands[player_idx],
|
6378
4970
|
goal_completions=goal_completions,
|
6379
4971
|
)
|
6380
4972
|
|
@@ -6522,132 +5114,92 @@ def diff(A, dims=None):
|
|
6522
5114
|
return [[A[i][j] - A[i][j - 1] for j in range(1, len(A[0]))] for i in range(len(A))]
|
6523
5115
|
else:
|
6524
5116
|
raise ValueError("dims must be either 1 or 2")
|
6525
|
-
|
6526
5117
|
|
6527
|
-
@dispatch(StaticBoardConfig, PlayerState)
|
6528
|
-
def get_imagined_state(static_board_config, player_state):
|
6529
|
-
board_config = static_board_config.board_config
|
6530
|
-
public_state = player_state.public
|
6531
|
-
private_state = player_state.private
|
6532
|
-
my_hand = private_state.hand
|
6533
|
-
|
6534
|
-
fig = initfig("af472d67-05ec-4b5d-9eb7-6b0cea9eec5a", board_config)
|
6535
|
-
seed = 4012489341 # TODO: this should be random (or if non-stochastic, loaded from the net.seed)
|
6536
|
-
rng = getrng(seed)
|
6537
|
-
|
6538
|
-
# TODO: this needs to come from x_json['game_config']
|
6539
|
-
game_config = GameConfig(
|
6540
|
-
uuid = str(generate_uuid_with_rng(rng)),
|
6541
|
-
started_at = "2025-01-01 00:00:00",
|
6542
|
-
num_players = 2,
|
6543
|
-
fig = fig,
|
6544
|
-
seed = seed
|
6545
|
-
)
|
6546
5118
|
|
6547
|
-
|
6548
|
-
|
5119
|
+
def get_default_toplay(s):
|
5120
|
+
if s.legal_actions_2:
|
5121
|
+
return s.legal_actions_2[0].player_idx
|
5122
|
+
return None
|
6549
5123
|
|
6550
|
-
def remove_card_idx(to_mutate, card_idx):
|
6551
|
-
if card_idx in to_mutate:
|
6552
|
-
to_mutate.remove(card_idx)
|
6553
5124
|
|
6554
|
-
|
6555
|
-
|
6556
|
-
|
5125
|
+
def get_intuited_best_actions(ps):
|
5126
|
+
if not ps.legal_actions_2:
|
5127
|
+
return None
|
5128
|
+
return ps.legal_actions_2[:8]
|
6557
5129
|
|
6558
|
-
|
6559
|
-
imagined_route_card_idxs = rng.sample(possible_route_card_idxs, public_state.num_route_cards)
|
6560
|
-
remove_card_idxs(possible_route_card_idxs, imagined_route_card_idxs)
|
6561
|
-
imagined_route_discard_idxs = rng.sample(possible_route_card_idxs, public_state.num_route_discards)
|
6562
|
-
remove_card_idxs(possible_route_card_idxs, imagined_route_discard_idxs)
|
6563
5130
|
|
6564
|
-
|
6565
|
-
|
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
|
6566
5136
|
|
6567
|
-
for unit_card in public_state.unit_discards:
|
6568
|
-
remove_card_idx(possible_unit_card_idxs, unit_card-1)
|
6569
5137
|
|
6570
|
-
|
6571
|
-
|
5138
|
+
def getvproxy0(ps):
|
5139
|
+
return 0
|
6572
5140
|
|
6573
|
-
imagined_unit_card_idxs = rng.sample(possible_unit_card_idxs, public_state.num_unit_cards)
|
6574
|
-
imagined_unit_cards = [x+1 for x in imagined_unit_card_idxs]
|
6575
|
-
remove_card_idxs(possible_unit_card_idxs, imagined_unit_card_idxs)
|
6576
5141
|
|
5142
|
+
def imagine_dynamics(ps, a):
|
5143
|
+
return dynamics(imagine_state(ps), a)
|
6577
5144
|
|
6578
|
-
imagined_player_hands = []
|
6579
5145
|
|
6580
|
-
|
6581
|
-
|
6582
|
-
|
6583
|
-
|
6584
|
-
|
6585
|
-
|
6586
|
-
remove_card_idxs(possible_unit_card_idxs, imagined_player_unit_card_idxs)
|
6587
|
-
imagined_player_route_card_idxs = rng.sample(possible_route_card_idxs, public_player_info.num_route_cards)
|
6588
|
-
remove_card_idxs(possible_route_card_idxs, imagined_player_route_card_idxs)
|
6589
|
-
imagined_player_new_route_card_idxs = rng.sample(possible_route_card_idxs, public_player_info.num_new_route_cards)
|
6590
|
-
remove_card_idxs(possible_route_card_idxs, imagined_player_new_route_card_idxs)
|
6591
|
-
imagined_player_route_cards = [x+1 for x in imagined_player_route_card_idxs]
|
6592
|
-
imagined_player_new_route_cards = [x+1 for x in imagined_player_new_route_card_idxs]
|
6593
|
-
imagined_player_hands.append(
|
6594
|
-
PlayerInfo(
|
6595
|
-
fig = fig,
|
6596
|
-
player_idx = player_idx,
|
6597
|
-
new_route_cards = pvector(imagined_player_new_route_cards), # Guess at this.
|
6598
|
-
route_cards = pvector(imagined_player_route_cards), # Guess at this.
|
6599
|
-
unit_cards = pvector(imagined_player_unit_cards), # Guess at this.
|
6600
|
-
completed_routes = [], # Guess at this.
|
6601
|
-
completed_clusters = public_player_info.completed_clusters,
|
6602
|
-
paths = public_player_info.paths,
|
6603
|
-
points = public_player_info.points,
|
6604
|
-
tokens = public_player_info.tokens,
|
6605
|
-
num_pieces = public_player_info.num_pieces,
|
6606
|
-
num_point_pieces = public_player_info.num_point_pieces,
|
6607
|
-
longest_trail = public_player_info.longest_trail,
|
6608
|
-
longest_trail_len = public_player_info.longest_trail_len,
|
6609
|
-
final_score = public_player_info.final_score,
|
6610
|
-
)
|
6611
|
-
)
|
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
|
6612
5152
|
|
6613
5153
|
|
6614
|
-
|
6615
|
-
|
6616
|
-
|
6617
|
-
|
6618
|
-
|
6619
|
-
|
6620
|
-
|
6621
|
-
|
6622
|
-
|
6623
|
-
|
6624
|
-
|
6625
|
-
|
6626
|
-
|
6627
|
-
|
6628
|
-
|
6629
|
-
|
6630
|
-
|
6631
|
-
|
6632
|
-
|
6633
|
-
|
6634
|
-
|
6635
|
-
|
6636
|
-
|
6637
|
-
|
6638
|
-
|
6639
|
-
|
6640
|
-
|
6641
|
-
|
6642
|
-
|
6643
|
-
|
6644
|
-
|
6645
|
-
|
6646
|
-
|
6647
|
-
|
6648
|
-
|
6649
|
-
|
6650
|
-
|
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
|
+
|
6651
5203
|
|
6652
5204
|
INIT_HOOK_1 = """def handler(game):
|
6653
5205
|
return shuffle_all_decks(game)
|