graph-games-proto 0.3.2050__py3-none-any.whl → 0.3.2078__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/fns.py CHANGED
@@ -1104,7 +1104,7 @@ class PrivateState(PClass):
1104
1104
  player_score = field(type=PrivatePlayerScore)
1105
1105
  player = field(type=Player)
1106
1106
  legal_actions_3 = field(type=list) # List[LegalAction]
1107
- goal_completions = field(type=list, initial=[]) # List[GoalCompletion]
1107
+ goal_completions = field(type=list) # List[GoalCompletion]
1108
1108
  def __todict__(self):
1109
1109
  return {
1110
1110
  "my_history": [x.__todict__() for x in self.my_history],
@@ -1779,6 +1779,33 @@ class Segment2(PClass):
1779
1779
  unit_uuid=d["unit_uuid"],
1780
1780
  pieces=d["pieces"],
1781
1781
  )
1782
+
1783
+
1784
+ class SegmentRecord(PClass):
1785
+ uuid = field(type=str)
1786
+ unit_uuid = field(type=(str, type(None)), initial=None) # Optional[str]
1787
+ piece_uuids = field(type=list) # List[str]
1788
+ def __todict__(self):
1789
+ return {
1790
+ "uuid": self.uuid,
1791
+ "unit_uuid": self.unit_uuid,
1792
+ "piece_uuids": self.piece_uuids,
1793
+ }
1794
+ @staticmethod
1795
+ def __fromdict__(d):
1796
+ return SegmentRecord(
1797
+ uuid=d["uuid"],
1798
+ unit_uuid=d["unit_uuid"],
1799
+ piece_uuids=d["piece_uuids"],
1800
+ )
1801
+
1802
+
1803
+ def init_segment_record(segment: Segment2) -> SegmentRecord:
1804
+ return SegmentRecord(
1805
+ uuid=segment.uuid,
1806
+ unit_uuid=segment.unit_uuid,
1807
+ piece_uuids=[piece.uuid for piece in segment.pieces],
1808
+ )
1782
1809
 
1783
1810
 
1784
1811
  class Path2(PClass):
@@ -1803,6 +1830,38 @@ class Path2(PClass):
1803
1830
  )
1804
1831
 
1805
1832
 
1833
+ class PathRecord(PClass):
1834
+ uuid = field(type=str)
1835
+ idx = field(type=int)
1836
+ edge_uuid = field(type=str)
1837
+ segment_uuids = field(type=list) # List[str]
1838
+ def __todict__(self):
1839
+ return {
1840
+ "uuid": self.uuid,
1841
+ "idx": self.idx,
1842
+ "edge_uuid": self.edge_uuid,
1843
+ "segment_uuids": self.segment_uuids,
1844
+ }
1845
+ @staticmethod
1846
+ def __fromdict__(d):
1847
+ return PathRecord(
1848
+ uuid=d["uuid"],
1849
+ idx=d["idx"],
1850
+ edge_uuid=d["edge_uuid"],
1851
+ segment_uuids=d["segment_uuids"],
1852
+ )
1853
+
1854
+
1855
+ def init_path_record(path: Path2) -> PathRecord:
1856
+ return PathRecord(
1857
+ uuid=path.uuid,
1858
+ idx=path.idx,
1859
+ edge_uuid=path.edge_uuid,
1860
+ segment_uuids=[segment.uuid for segment in path.segments],
1861
+ )
1862
+
1863
+
1864
+
1806
1865
  class BiEdge(PClass):
1807
1866
  uuid = field(type=str)
1808
1867
  start_point_uuid = field(type=str)
@@ -1840,6 +1899,57 @@ class BiEdge(PClass):
1840
1899
  )
1841
1900
 
1842
1901
 
1902
+ class BiEdgeRecord(PClass):
1903
+ uuid = field(type=str)
1904
+ start_point_uuid = field(type=str)
1905
+ end_point_uuid = field(type=str)
1906
+ node_1_uuid = field(type=str)
1907
+ node_2_uuid = field(type=str)
1908
+ node_1_idx = field(type=int)
1909
+ node_2_idx = field(type=int)
1910
+ path_idxs = field(type=list) # List[str]
1911
+ score = field(type=int)
1912
+ def __todict__(self):
1913
+ return {
1914
+ "uuid": self.uuid,
1915
+ "start_point_uuid": self.start_point_uuid,
1916
+ "end_point_uuid": self.end_point_uuid,
1917
+ "node_1_uuid": self.node_1_uuid,
1918
+ "node_2_uuid": self.node_2_uuid,
1919
+ "node_1_idx": self.node_1_idx,
1920
+ "node_2_idx": self.node_2_idx,
1921
+ "path_idxs": self.path_idxs,
1922
+ "score": self.score,
1923
+ }
1924
+ @staticmethod
1925
+ def __fromdict__(d):
1926
+ return BiEdgeRecord(
1927
+ uuid=d["uuid"],
1928
+ start_point_uuid=d["start_point_uuid"],
1929
+ end_point_uuid=d["end_point_uuid"],
1930
+ node_1_uuid=d["node_1_uuid"],
1931
+ node_2_uuid=d["node_2_uuid"],
1932
+ node_1_idx=d["node_1_idx"],
1933
+ node_2_idx=d["node_2_idx"],
1934
+ path_idxs=d["path_idxs"],
1935
+ score=d["score"],
1936
+ )
1937
+
1938
+
1939
+ def init_biedge_record(biedge: BiEdge) -> BiEdgeRecord:
1940
+ return BiEdgeRecord(
1941
+ uuid=biedge.uuid,
1942
+ start_point_uuid=biedge.start_point_uuid,
1943
+ end_point_uuid=biedge.end_point_uuid,
1944
+ node_1_uuid=biedge.node_1_uuid,
1945
+ node_2_uuid=biedge.node_2_uuid,
1946
+ node_1_idx=biedge.node_1_idx,
1947
+ node_2_idx=biedge.node_2_idx,
1948
+ path_idxs=[path.idx for path in biedge.paths],
1949
+ score=biedge.score,
1950
+ )
1951
+
1952
+
1843
1953
  class Node(PClass):
1844
1954
  idx = field(type=int)
1845
1955
  uuid = field(type=str)
@@ -1932,9 +2042,23 @@ class BonusStatus(PClass):
1932
2042
  )
1933
2043
 
1934
2044
 
2045
+ #==
2046
+ # uuid2edgerecord
2047
+ # uuid2segmentrecord
2048
+ # idx2pathrecord
2049
+ # uuid2piece
2050
+ #==#
2051
+
2052
+
2053
+
1935
2054
  class StateKernel(PClass):
1936
2055
  rng = field(type=random.Random)
1937
2056
  game_config = field(type=GameConfig)
2057
+
2058
+ uuid2edgerecord = field(type=dict) # Dict[str, BiEdgeRecord]
2059
+ uuid2segmentrecord = field(type=dict) # Dict[str, SegmentRecord]
2060
+ idx2pathrecord = field(type=list) # List[PathRecord]
2061
+
1938
2062
  edges = field(type=list) # List[BiEdge]
1939
2063
  nodes = field(type=list) # List[Node]
1940
2064
  regions = field(type=list) # List[Region]
@@ -1943,7 +2067,6 @@ class StateKernel(PClass):
1943
2067
  players = field(type=list) # List[Player]
1944
2068
  player_idxs = field(type=list) # List[int]
1945
2069
  history = field(type=list) # List[PublicAction]
1946
- idx2path = field(type=list) # List[Path2]
1947
2070
  pieceuuid2piece = field(type=dict) # Dict[str, Piece]
1948
2071
  edgeuuid2idx = field(type=dict) # Dict[str, int]
1949
2072
  carduuid2card = field(type=dict) # Dict[str, Card]
@@ -1968,7 +2091,9 @@ class StateKernel(PClass):
1968
2091
  "players": [player.__todict__() for player in self.players],
1969
2092
  "player_idxs": self.player_idxs,
1970
2093
  "history": [action.__todict__() for action in self.history],
1971
- "idx2path": [v.__todict__() for v in self.idx2path],
2094
+ "uuid2edgerecord": {k: v.__todict__() for k, v in self.uuid2edgerecord.items()},
2095
+ "uuid2segmentrecord": {k: v.__todict__() for k, v in self.uuid2segmentrecord.items()},
2096
+ "idx2pathrecord": [v.__todict__() for v in self.idx2pathrecord],
1972
2097
  "pieceuuid2piece": {k: v.__todict__() for k, v in self.pieceuuid2piece.items()},
1973
2098
  "edgeuuid2idx": self.edgeuuid2idx,
1974
2099
  "carduuid2card": {k: v.__todict__() for k, v in self.carduuid2card.items()},
@@ -1995,7 +2120,9 @@ class StateKernel(PClass):
1995
2120
  players=[Player.__fromdict__(player) for player in d["players"]],
1996
2121
  player_idxs=d["player_idxs"],
1997
2122
  history=[PublicAction.__fromdict__(action) for action in d["history"]],
1998
- idx2path=[Path2.__fromdict(v) for v in d["idx2path"]],
2123
+ uuid2edgerecord={k: BiEdgeRecord.__fromdict__(v) for k, v in d["uuid2edgerecord"].items()},
2124
+ uuid2segmentrecord={k: Segment2.__fromdict__(v) for k, v in d["uuid2segmentrecord"].items()},
2125
+ idx2pathrecord=[Path2.__fromdict(v) for v in d["idx2pathrecord"]],
1999
2126
  pieceuuid2piece={k: Piece.__fromdict(v) for k, v in d["pieceuuid2piece"].items()},
2000
2127
  edgeuuid2idx=d["edgeuuid2idx"],
2001
2128
  carduuid2card={k: Card.__fromdict(v) for k, v in d["carduuid2card"].items()},
@@ -2018,11 +2145,11 @@ def init_state_kernel(**kwargs):
2018
2145
  board_config = fig.board_config
2019
2146
  nodes = kwargs.get('nodes', [])
2020
2147
  edges = kwargs.get('edges', [])
2021
- idx2path = []
2148
+ idx2pathrecord = []
2022
2149
  edgeuuid2idx = {edge.uuid: idx for idx, edge in enumerate(edges)}
2023
2150
  for edge in edges:
2024
2151
  for path in edge.paths:
2025
- idx2path.append(path)
2152
+ idx2pathrecord.append(init_path_record(path))
2026
2153
  pieceuuid2piece = {}
2027
2154
  for piece_template in board_config.piece_templates:
2028
2155
  if piece_template.has_player:
@@ -2053,6 +2180,11 @@ def init_state_kernel(**kwargs):
2053
2180
 
2054
2181
  player_graphs_3 = calc_player_graphs3(nodes, edges, pieceuuid2piece, game_config)
2055
2182
 
2183
+ segments = kwargs.get('segments', [])
2184
+
2185
+ uuid2segmentrecord = {segment.uuid: init_segment_record(segment) for segment in segments}
2186
+ uuid2edgerecord = {edge.uuid: init_biedge_record(edge) for edge in edges}
2187
+
2056
2188
  return StateKernel(
2057
2189
  rng=rng,
2058
2190
  game_config=game_config,
@@ -2064,7 +2196,9 @@ def init_state_kernel(**kwargs):
2064
2196
  players=kwargs.get('players'),
2065
2197
  player_idxs=kwargs.get('player_idxs'),
2066
2198
  history=kwargs.get('history', []),
2067
- idx2path=idx2path,
2199
+ uuid2edgerecord=uuid2edgerecord,
2200
+ uuid2segmentrecord=uuid2segmentrecord,
2201
+ idx2pathrecord=idx2pathrecord,
2068
2202
  edgeuuid2idx=edgeuuid2idx,
2069
2203
  carduuid2card=carduuid2card,
2070
2204
  pieceuuid2piece=pieceuuid2piece,
@@ -2083,7 +2217,7 @@ class State(PClass):
2083
2217
  kernel = field(type=StateKernel)
2084
2218
 
2085
2219
  # Identity - these fields should be in the kernel (can only be changed in "get_initial_state" and "get_next_state")
2086
- # The struture should be this: uuid2segment, uuid2edge, uuid2path, uuid2region, uuid2node
2220
+ # The struture should be this: uuid2segmentrecord, uuid2edge, uuid2path, uuid2region, uuid2node
2087
2221
 
2088
2222
  # Memoized
2089
2223
  legal_actions_3 = field(type=list) # List[LegalAction]
@@ -2466,6 +2600,20 @@ def get_nodes(board_config):
2466
2600
  return []
2467
2601
 
2468
2602
 
2603
+ def get_segments(board_config):
2604
+ segments = []
2605
+ for board_path in board_config.board_paths:
2606
+ for segment in board_path.path.segments:
2607
+ segments.append(
2608
+ Segment2(
2609
+ uuid=segment.uuid,
2610
+ unit_uuid=segment.unit_uuid,
2611
+ pieces=[]
2612
+ )
2613
+ )
2614
+ return segments
2615
+
2616
+
2469
2617
  def get_edges(rng, board_config, nodeuuid2idx):
2470
2618
  edges = []
2471
2619
 
@@ -2634,6 +2782,7 @@ def getinitialstate(game_config):
2634
2782
  kernel = init_state_kernel(
2635
2783
  rng=rng,
2636
2784
  game_config=game_config,
2785
+ segments=get_segments(board_config),
2637
2786
  edges=edges,
2638
2787
  nodes=nodes,
2639
2788
  decks=decks,
@@ -3525,18 +3674,19 @@ def handle_move_pieces_to_path_action(kernel, action):
3525
3674
  return kernel
3526
3675
 
3527
3676
  path_idx = move_pieces_to_path.path_idx
3528
- path = kernel.idx2path[path_idx]
3677
+ path_record = kernel.idx2pathrecord[path_idx]
3529
3678
 
3530
- if path is None or not path.segments:
3679
+ if path_record is None or not path_record.segment_uuids:
3531
3680
  return kernel
3532
3681
 
3533
- for piece_uuid, segment in zip(default.piece_uuids, path.segments):
3682
+ for piece_uuid, segment_uuid in zip(default.piece_uuids, path_record.segment_uuids):
3683
+ segment_record = kernel.uuid2segmentrecord[segment_uuid]
3534
3684
  # Find the piece in the player's pieces
3535
3685
  piece_idx = next((i for i, player_piece_uuid in enumerate(player.pieces) if player_piece_uuid == piece_uuid), None)
3536
3686
  if piece_idx is not None:
3537
3687
  # Remove the piece from player's pieces
3538
3688
  piece = player.pieces.pop(piece_idx)
3539
- segment.pieces.append(piece)
3689
+ segment_record.piece_uuids.append(piece)
3540
3690
 
3541
3691
  for card_uuid in default.card_uuids:
3542
3692
  # Find the card in the player's cards
@@ -3550,7 +3700,7 @@ def handle_move_pieces_to_path_action(kernel, action):
3550
3700
  kernel = recycle_decks_if_needed(kernel)
3551
3701
  kernel = replenish_decks_if_needed(kernel)
3552
3702
  kernel = kernel.set(players=kernel.players)
3553
- kernel = kernel.set(idx2path=kernel.idx2path)
3703
+ kernel = kernel.set(idx2pathrecord=kernel.idx2pathrecord)
3554
3704
 
3555
3705
  return kernel
3556
3706
 
@@ -3836,10 +3986,10 @@ def is_move_pieces_to_path_action_legal(state, action):
3836
3986
  player_idx = action.legal_action.player_idx
3837
3987
  proposed_cards_uuids = action.move_pieces_to_path.card_uuids
3838
3988
  path_idx = action.legal_action.move_pieces_to_path.path_idx
3839
- path = state.kernel.idx2path[path_idx]
3989
+ path_record = state.kernel.idx2pathrecord[path_idx]
3840
3990
  proposed_cards = [card_uuid for card_uuid in state.kernel.players[player_idx].cards if card_uuid in proposed_cards_uuids]
3841
3991
  proposed_pieces = [piece_uuid for piece_uuid in state.kernel.players[player_idx].pieces if piece_uuid in action.move_pieces_to_path.piece_uuids]
3842
- remaining_segments = path.segments
3992
+ remaining_segment_records = [state.kernel.uuid2segmentrecord[segment_uuid] for segment_uuid in path_record.segment_uuids]
3843
3993
 
3844
3994
  # print("******************************1234 is_move_pieces_to_path_action_legal 1b: ", proposed_cards)
3845
3995
  # print("******************************1234 is_move_pieces_to_path_action_legal 1c: ", proposed_pieces)
@@ -3849,7 +3999,7 @@ def is_move_pieces_to_path_action_legal(state, action):
3849
3999
  state.kernel,
3850
4000
  proposed_cards,
3851
4001
  proposed_pieces,
3852
- remaining_segments,
4002
+ remaining_segment_records,
3853
4003
  )
3854
4004
 
3855
4005
  # print("******************************1234 is_move_pieces_to_path_action_legal 2a", card_fulfillment)
@@ -3870,7 +4020,7 @@ def is_move_pieces_to_path_action_legal(state, action):
3870
4020
 
3871
4021
  @dispatch(StateKernel)
3872
4022
  def get_total_path_count(kernel):
3873
- return len(kernel.idx2path)
4023
+ return len(kernel.idx2pathrecord)
3874
4024
 
3875
4025
 
3876
4026
  @dispatch(StateKernel, int, int)
@@ -3917,16 +4067,18 @@ def get_legal_actions_for_paths(kernel, player_idx):
3917
4067
  return legal_actions
3918
4068
 
3919
4069
 
3920
- @dispatch(StateKernel, BiEdge)
3921
- def get_player_idxs_on_edge(kernel, edge):
4070
+ @dispatch(StateKernel, BiEdgeRecord)
4071
+ def get_player_idxs_on_edge(kernel, edge_record):
3922
4072
  player_idxs = set()
3923
- if not edge or not edge.paths:
4073
+ if not edge_record or not edge_record.path_idxs:
3924
4074
  return list(player_idxs)
3925
4075
 
3926
- for path in edge.paths:
3927
- for segment in path.segments:
3928
- if segment.pieces and segment.pieces[0]:
3929
- piece = kernel.pieceuuid2piece.get(segment.pieces[0])
4076
+ for path_idx in edge_record.path_idxs:
4077
+ path_record = kernel.idx2pathrecord[path_idx]
4078
+ for segment_uuid in path_record.segment_uuids:
4079
+ segment = kernel.uuid2segmentrecord[segment_uuid]
4080
+ if segment.piece_uuids and segment.piece_uuids[0]:
4081
+ piece = kernel.pieceuuid2piece[segment.piece_uuids[0]]
3930
4082
  if piece:
3931
4083
  player_idxs.add(piece.player_idx)
3932
4084
 
@@ -3938,11 +4090,10 @@ def is_path_open_to_player(state_kernel, path_idx, player_idx):
3938
4090
  if not state_kernel or path_idx < 0 or get_total_path_count(state_kernel) <= path_idx:
3939
4091
  return False
3940
4092
 
3941
- path = state_kernel.idx2path[path_idx]
3942
- edge_idx = state_kernel.edgeuuid2idx[path.edge_uuid]
3943
- edge = state_kernel.edges[edge_idx]
4093
+ path_record = state_kernel.idx2pathrecord[path_idx]
4094
+ edge_record = state_kernel.uuid2edgerecord[path_record.edge_uuid]
3944
4095
 
3945
- player_idxs_on_edge = get_player_idxs_on_edge(state_kernel, edge)
4096
+ player_idxs_on_edge = get_player_idxs_on_edge(state_kernel, edge_record)
3946
4097
 
3947
4098
  # Check if edge is too crowded for the number of players
3948
4099
  if state_kernel.game_config.num_players <= 3:
@@ -3953,12 +4104,14 @@ def is_path_open_to_player(state_kernel, path_idx, player_idx):
3953
4104
  return False
3954
4105
 
3955
4106
  # Check if any segment of the path has pieces from any player
3956
- if path.segments[0].pieces:
3957
- return False
4107
+ for segment_uuid in path_record.segment_uuids:
4108
+ segment_record = state_kernel.uuid2segmentrecord[segment_uuid]
4109
+ if segment_record.piece_uuids:
4110
+ return False
3958
4111
 
3959
4112
  # Check if the player has enough pieces to claim the path
3960
4113
  player_pieces = state_kernel.players[player_idx].pieces
3961
- if len(player_pieces) < len(path.segments):
4114
+ if len(player_pieces) < len(path_record.segment_uuids):
3962
4115
  return False
3963
4116
 
3964
4117
  return True
@@ -4010,68 +4163,68 @@ def get_wild_unit_uuids(state_kernel):
4010
4163
 
4011
4164
 
4012
4165
  @dispatch(StateKernel, list, list, list)
4013
- def match_strict_wild(state_kernel, fulfillment, cards, segments):
4166
+ def match_strict_wild(state_kernel, fulfillment, cards, segment_records):
4014
4167
  new_fulfillment = fulfillment.copy()
4015
4168
  new_cards = cards.copy()
4016
4169
  wild_unit_uuids = get_wild_unit_uuids(state_kernel)
4017
- new_segments = []
4170
+ new_segment_records = []
4018
4171
 
4019
- for segment in segments:
4020
- if segment.unit_uuid and segment.unit_uuid in wild_unit_uuids:
4021
- first_matching_idx = next((i for i, card_uuid in enumerate(new_cards) if state_kernel.carduuid2card[card_uuid].resource_uuid == segment.unit_uuid), None)
4172
+ for segment_record in segment_records:
4173
+ if segment_record.unit_uuid and segment_record.unit_uuid in wild_unit_uuids:
4174
+ first_matching_idx = next((i for i, card_uuid in enumerate(new_cards) if state_kernel.carduuid2card[card_uuid].resource_uuid == segment_record.unit_uuid), None)
4022
4175
  if first_matching_idx is not None:
4023
4176
  new_fulfillment.append(new_cards.pop(first_matching_idx))
4024
4177
  else:
4025
- new_segments.append(segment)
4178
+ new_segment_records.append(segment_record)
4026
4179
  else:
4027
- new_segments.append(segment)
4180
+ new_segment_records.append(segment_record)
4028
4181
 
4029
- return new_fulfillment, new_cards, new_segments
4182
+ return new_fulfillment, new_cards, new_segment_records
4030
4183
 
4031
4184
  @dispatch(StateKernel, list, list, list)
4032
- def match_non_wild_non_empty(state_kernel, fulfillment, cards, segments):
4185
+ def match_non_wild_non_empty(state_kernel, fulfillment, cards, segment_records):
4033
4186
  new_fulfillment = fulfillment.copy()
4034
4187
  new_cards = cards.copy()
4035
4188
  wild_unit_uuids = get_wild_unit_uuids(state_kernel)
4036
- new_segments = []
4189
+ new_segment_records = []
4037
4190
 
4038
- for segment in segments:
4039
- first_strict_matching_idx = next((i for i, card_uuid in enumerate(new_cards) if state_kernel.carduuid2card[card_uuid].resource_uuid == segment.unit_uuid), None)
4191
+ for segment_record in segment_records:
4192
+ first_strict_matching_idx = next((i for i, card_uuid in enumerate(new_cards) if state_kernel.carduuid2card[card_uuid].resource_uuid == segment_record.unit_uuid), None)
4040
4193
  first_wild_matching_idx = next((i for i, card_uuid in enumerate(new_cards) if state_kernel.carduuid2card[card_uuid].resource_uuid in wild_unit_uuids), None)
4041
4194
  first_matching_idx = first_strict_matching_idx if first_strict_matching_idx is not None else first_wild_matching_idx
4042
4195
  if first_matching_idx is not None:
4043
4196
  new_fulfillment.append(new_cards.pop(first_matching_idx))
4044
4197
  else:
4045
- new_segments.append(segment)
4198
+ new_segment_records.append(segment_record)
4046
4199
 
4047
- return new_fulfillment, new_cards, new_segments
4200
+ return new_fulfillment, new_cards, new_segment_records
4048
4201
 
4049
4202
 
4050
4203
  @dispatch(StateKernel, list, list, list)
4051
- def match_empty(state_kernel, fulfillment, cards, segments):
4052
- num_empty_segments = sum(1 for segment in segments if segment.unit_uuid is None)
4053
- if num_empty_segments == 0:
4054
- return fulfillment, cards, segments
4204
+ def match_empty(state_kernel, fulfillment, cards, segment_records):
4205
+ num_empty_segment_records = sum(1 for segment_record in segment_records if segment_record.unit_uuid is None)
4206
+ if num_empty_segment_records == 0:
4207
+ return fulfillment, cards, segment_records
4055
4208
 
4056
- tuples = get_uniform_sets(state_kernel, cards, num_empty_segments)
4209
+ tuples = get_uniform_sets(state_kernel, cards, num_empty_segment_records)
4057
4210
  # print(f"****************************************** len(cards): {len(cards)}")
4058
4211
  # print(f"****************************************** num_empty_segments: {num_empty_segments}")
4059
4212
  # print(f"Found {len(tuples)} tuples for empty segments: {tuples}")
4060
4213
  if len(tuples) == 0:
4061
- return fulfillment, cards, segments
4214
+ return fulfillment, cards, segment_records
4062
4215
 
4063
4216
  new_fulfillment = fulfillment.copy()
4064
4217
 
4065
- new_segments = []
4066
- for segment in segments:
4067
- if segment.unit_uuid:
4068
- new_segments.append(segment)
4218
+ new_segment_records = []
4219
+ for segment_record in segment_records:
4220
+ if segment_record.unit_uuid:
4221
+ new_segment_records.append(segment_record)
4069
4222
 
4070
- first_tuple = tuples[0][:num_empty_segments]
4223
+ first_tuple = tuples[0][:num_empty_segment_records]
4071
4224
  # print(f"Using first tuple for empty segments: {first_tuple}")
4072
4225
  new_cards = list(set(cards) - set(first_tuple))
4073
4226
  new_fulfillment.extend(first_tuple)
4074
- return new_fulfillment, new_cards, new_segments
4227
+ return new_fulfillment, new_cards, new_segment_records
4075
4228
 
4076
4229
 
4077
4230
  @dispatch(StateKernel, list, int)
@@ -4131,48 +4284,48 @@ def get_sample_actionclaimpath(game, player_idx, path_idx):
4131
4284
 
4132
4285
  @dispatch(StateKernel, int, int)
4133
4286
  def get_sample_path_fulfillment(kernel, player_idx, path_idx):
4134
- path = kernel.idx2path[path_idx]
4287
+ path_record = kernel.idx2pathrecord[path_idx]
4135
4288
  remaining_card_uuids = [card_uuid for card_uuid in kernel.players[player_idx].cards if kernel.carduuid2card[card_uuid].deck_idx == 0]
4136
4289
  remaining_pieces = [
4137
4290
  piece_uuid
4138
4291
  for piece_uuid in kernel.players[player_idx].pieces
4139
4292
  if kernel.pieceuuid2piece[piece_uuid].piece_template_idx == 0
4140
4293
  ]
4141
- remaining_segments = path.segments
4294
+ remaining_segment_records = [kernel.uuid2segmentrecord[segment_uuid] for segment_uuid in path_record.segment_uuids]
4142
4295
  return get_path_fulfillment_from_resources(
4143
4296
  kernel,
4144
4297
  remaining_card_uuids,
4145
4298
  remaining_pieces,
4146
- remaining_segments,
4299
+ remaining_segment_records,
4147
4300
  )
4148
4301
 
4149
4302
  @dispatch(StateKernel, list, list, list)
4150
- def get_path_fulfillment_from_resources(state_kernel, remaining_card_uuids, remaining_pieces, remaining_segments, log=False):
4303
+ def get_path_fulfillment_from_resources(state_kernel, remaining_card_uuids, remaining_pieces, remaining_segment_records, log=False):
4151
4304
 
4152
- if len(remaining_pieces) < len(remaining_segments):
4305
+ if len(remaining_pieces) < len(remaining_segment_records):
4153
4306
  print("Not enough pieces to fulfill the path segments")
4154
4307
  return None, None
4155
4308
 
4156
- piece_fulfillment = remaining_pieces[:len(remaining_segments)]
4309
+ piece_fulfillment = remaining_pieces[:len(remaining_segment_records)]
4157
4310
 
4158
4311
  card_fulfillment = []
4159
- card_fulfillment, remaining_card_uuids, remaining_segments = match_strict_wild(state_kernel, card_fulfillment, remaining_card_uuids, remaining_segments)
4312
+ card_fulfillment, remaining_card_uuids, remaining_segment_records = match_strict_wild(state_kernel, card_fulfillment, remaining_card_uuids, remaining_segment_records)
4160
4313
 
4161
- if len(remaining_segments) == 0:
4314
+ if len(remaining_segment_records) == 0:
4162
4315
  return card_fulfillment, piece_fulfillment
4163
4316
  # Probably don't need this check, but we should unit test
4164
4317
  # elif len(get_wild_segments(remaining_segments)) > 0:
4165
4318
  # return None
4166
4319
 
4167
- card_fulfillment, remaining_card_uuids, remaining_segments = match_non_wild_non_empty(state_kernel, card_fulfillment, remaining_card_uuids, remaining_segments)
4168
- if len(remaining_segments) == 0:
4320
+ card_fulfillment, remaining_card_uuids, remaining_segment_records = match_non_wild_non_empty(state_kernel, card_fulfillment, remaining_card_uuids, remaining_segment_records)
4321
+ if len(remaining_segment_records) == 0:
4169
4322
  return card_fulfillment, piece_fulfillment
4170
4323
  # Probably don't need this check, but we should unit test
4171
4324
  # elif len(get_non_wild_non_empty_segments(remaining_segments)) > 0:
4172
4325
  # return None
4173
4326
 
4174
- card_fulfillment, remaining_card_uuids, remaining_segments = match_empty(state_kernel, card_fulfillment, remaining_card_uuids, remaining_segments)
4175
- if len(remaining_segments) == 0:
4327
+ card_fulfillment, remaining_card_uuids, remaining_segment_records = match_empty(state_kernel, card_fulfillment, remaining_card_uuids, remaining_segment_records)
4328
+ if len(remaining_segment_records) == 0:
4176
4329
  return card_fulfillment, piece_fulfillment
4177
4330
 
4178
4331
  # print("get_path_fulfillment_from_resources (None, None) because remaining_segments is not empty: ", remaining_segments)
@@ -4549,6 +4702,51 @@ def isterminal(s):
4549
4702
 
4550
4703
  @dispatch(State)
4551
4704
  def getpublicstate(s):
4705
+ k = s.kernel
4706
+ edges = []
4707
+ for edge_record in s.kernel.uuid2edgerecord.values():
4708
+ paths = []
4709
+ for path_idx in edge_record.path_idxs:
4710
+ path_record = k.idx2pathrecord[path_idx]
4711
+ segments = []
4712
+ for segment_uuid in path_record.segment_uuids:
4713
+ segment_record = k.uuid2segmentrecord[segment_uuid]
4714
+ pieces = []
4715
+ for piece_uuid in segment_record.piece_uuids:
4716
+ pieces.append(piece_uuid)
4717
+ segments.append(
4718
+ Segment2(
4719
+ uuid=segment_record.uuid,
4720
+ unit_uuid=segment_record.unit_uuid,
4721
+ pieces=pieces,
4722
+ )
4723
+ )
4724
+ paths.append(
4725
+ Path2(
4726
+ uuid=path_record.uuid,
4727
+ edge_uuid=path_record.edge_uuid,
4728
+ segments=segments,
4729
+ idx=path_record.idx
4730
+ )
4731
+ )
4732
+
4733
+ edge = BiEdge(
4734
+ uuid=edge_record.uuid,
4735
+ start_point_uuid=edge_record.start_point_uuid,
4736
+ end_point_uuid=edge_record.end_point_uuid,
4737
+ node_1_uuid=edge_record.node_1_uuid,
4738
+ node_2_uuid=edge_record.node_2_uuid,
4739
+ node_1_idx=edge_record.node_1_idx,
4740
+ node_2_idx=edge_record.node_2_idx,
4741
+ paths=paths,
4742
+ score=edge_record.score,
4743
+ )
4744
+ edges.append(edge)
4745
+
4746
+ # stopped here
4747
+
4748
+
4749
+
4552
4750
  return PublicState(
4553
4751
  deadlines=get_deadlines(s),
4554
4752
  game_started_at=s.kernel.game_config.started_at,
@@ -4563,7 +4761,7 @@ def getpublicstate(s):
4563
4761
  player_graphs=s.kernel.player_graphs_3,
4564
4762
  goals=s.kernel.goals,
4565
4763
  nodes=s.kernel.nodes,
4566
- edges=s.kernel.edges,
4764
+ edges=edges,
4567
4765
  regions=s.kernel.regions,
4568
4766
  decks=[getpublicdeck(s, deck) for deck in s.kernel.decks],
4569
4767
  piles=s.kernel.piles,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graph_games_proto
3
- Version: 0.3.2050
3
+ Version: 0.3.2078
4
4
  Requires-Dist: multipledispatch==1.0.0
5
5
  Requires-Dist: pyrsistent==0.20.0
6
6
  Requires-Dist: numpy==2.2.4
@@ -1,9 +1,9 @@
1
1
  graph_games_proto/__init__.py,sha256=_EVQR-51XehfH45XZlba1WPdx3omS3Gm1nTwrgGyn2Q,667
2
2
  graph_games_proto/all_types.py,sha256=IpbwftEcHS5Ewz-saFNk0lO9FvcbuHG36odRTayCXUk,54911
3
- graph_games_proto/fns.py,sha256=4NumIZC9NJ50Du5H9pZrwMUh4kR1wETerB6-jdzcCsI,193962
3
+ graph_games_proto/fns.py,sha256=_1ih4jhg9LtO2OTx5Bo3Xa5G7o43XWEa1jFty_f1lF0,201156
4
4
  graph_games_proto/main.py,sha256=fj2U7KcwrpZtuUhjOX5yVxY18LZvvsxDFYZ_S5mxe04,145
5
5
  graph_games_proto/state.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- graph_games_proto-0.3.2050.dist-info/METADATA,sha256=MKHNdbTExHzQIe9VIZA4Q_ONiS--ccywR06QtE6MGkA,188
7
- graph_games_proto-0.3.2050.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
8
- graph_games_proto-0.3.2050.dist-info/top_level.txt,sha256=-4QSrBMf_MM4BGsr2QXBpqDx8c8k_OPnzGyFjqjakes,18
9
- graph_games_proto-0.3.2050.dist-info/RECORD,,
6
+ graph_games_proto-0.3.2078.dist-info/METADATA,sha256=45PxNh56O2ygcfAq64cbl5dlm4if0pHZURIMCkBCPfU,188
7
+ graph_games_proto-0.3.2078.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
8
+ graph_games_proto-0.3.2078.dist-info/top_level.txt,sha256=-4QSrBMf_MM4BGsr2QXBpqDx8c8k_OPnzGyFjqjakes,18
9
+ graph_games_proto-0.3.2078.dist-info/RECORD,,