graph-games-proto 0.3.2049__py3-none-any.whl → 0.3.2077__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,
@@ -3288,8 +3437,9 @@ def handle_move_bonus_cards(kernel, action):
3288
3437
 
3289
3438
  # Take a random walk on the player's graph. A node can be visiting more than once, but an edge cannot be visited more than once.
3290
3439
  # Example graph: PlayerGraph(player_idx=0, neighbors=[[], [], [], [], [], [], [], [], [], [], [30]
3291
- def random_player_graph_walk(game, player_idx):
3292
- player_graph = game.player_graphs[player_idx]
3440
+ @dispatch(StateKernel, int)
3441
+ def random_player_graph_walk(kernel, player_idx):
3442
+ player_graph = kernel.player_graphs_3[player_idx]
3293
3443
  nodes_indices_with_neighbors = [i for i, neighbors in enumerate(player_graph.neighbors) if neighbors]
3294
3444
 
3295
3445
  if not nodes_indices_with_neighbors:
@@ -3524,18 +3674,19 @@ def handle_move_pieces_to_path_action(kernel, action):
3524
3674
  return kernel
3525
3675
 
3526
3676
  path_idx = move_pieces_to_path.path_idx
3527
- path = kernel.idx2path[path_idx]
3677
+ path_record = kernel.idx2pathrecord[path_idx]
3528
3678
 
3529
- if path is None or not path.segments:
3679
+ if path_record is None or not path_record.segment_uuids:
3530
3680
  return kernel
3531
3681
 
3532
- 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]
3533
3684
  # Find the piece in the player's pieces
3534
3685
  piece_idx = next((i for i, player_piece_uuid in enumerate(player.pieces) if player_piece_uuid == piece_uuid), None)
3535
3686
  if piece_idx is not None:
3536
3687
  # Remove the piece from player's pieces
3537
3688
  piece = player.pieces.pop(piece_idx)
3538
- segment.pieces.append(piece)
3689
+ segment_record.piece_uuids.append(piece)
3539
3690
 
3540
3691
  for card_uuid in default.card_uuids:
3541
3692
  # Find the card in the player's cards
@@ -3549,7 +3700,7 @@ def handle_move_pieces_to_path_action(kernel, action):
3549
3700
  kernel = recycle_decks_if_needed(kernel)
3550
3701
  kernel = replenish_decks_if_needed(kernel)
3551
3702
  kernel = kernel.set(players=kernel.players)
3552
- kernel = kernel.set(idx2path=kernel.idx2path)
3703
+ kernel = kernel.set(idx2pathrecord=kernel.idx2pathrecord)
3553
3704
 
3554
3705
  return kernel
3555
3706
 
@@ -3835,10 +3986,10 @@ def is_move_pieces_to_path_action_legal(state, action):
3835
3986
  player_idx = action.legal_action.player_idx
3836
3987
  proposed_cards_uuids = action.move_pieces_to_path.card_uuids
3837
3988
  path_idx = action.legal_action.move_pieces_to_path.path_idx
3838
- path = state.kernel.idx2path[path_idx]
3989
+ path_record = state.kernel.idx2pathrecord[path_idx]
3839
3990
  proposed_cards = [card_uuid for card_uuid in state.kernel.players[player_idx].cards if card_uuid in proposed_cards_uuids]
3840
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]
3841
- remaining_segments = path.segments
3992
+ remaining_segment_records = [state.kernel.uuid2segmentrecord[segment_uuid] for segment_uuid in path_record.segment_uuids]
3842
3993
 
3843
3994
  # print("******************************1234 is_move_pieces_to_path_action_legal 1b: ", proposed_cards)
3844
3995
  # print("******************************1234 is_move_pieces_to_path_action_legal 1c: ", proposed_pieces)
@@ -3848,7 +3999,7 @@ def is_move_pieces_to_path_action_legal(state, action):
3848
3999
  state.kernel,
3849
4000
  proposed_cards,
3850
4001
  proposed_pieces,
3851
- remaining_segments,
4002
+ remaining_segment_records,
3852
4003
  )
3853
4004
 
3854
4005
  # print("******************************1234 is_move_pieces_to_path_action_legal 2a", card_fulfillment)
@@ -3869,7 +4020,7 @@ def is_move_pieces_to_path_action_legal(state, action):
3869
4020
 
3870
4021
  @dispatch(StateKernel)
3871
4022
  def get_total_path_count(kernel):
3872
- return len(kernel.idx2path)
4023
+ return len(kernel.idx2pathrecord)
3873
4024
 
3874
4025
 
3875
4026
  @dispatch(StateKernel, int, int)
@@ -3916,16 +4067,18 @@ def get_legal_actions_for_paths(kernel, player_idx):
3916
4067
  return legal_actions
3917
4068
 
3918
4069
 
3919
- @dispatch(StateKernel, BiEdge)
3920
- def get_player_idxs_on_edge(kernel, edge):
4070
+ @dispatch(StateKernel, BiEdgeRecord)
4071
+ def get_player_idxs_on_edge(kernel, edge_record):
3921
4072
  player_idxs = set()
3922
- if not edge or not edge.paths:
4073
+ if not edge_record or not edge_record.path_idxs:
3923
4074
  return list(player_idxs)
3924
4075
 
3925
- for path in edge.paths:
3926
- for segment in path.segments:
3927
- if segment.pieces and segment.pieces[0]:
3928
- 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]]
3929
4082
  if piece:
3930
4083
  player_idxs.add(piece.player_idx)
3931
4084
 
@@ -3937,11 +4090,10 @@ def is_path_open_to_player(state_kernel, path_idx, player_idx):
3937
4090
  if not state_kernel or path_idx < 0 or get_total_path_count(state_kernel) <= path_idx:
3938
4091
  return False
3939
4092
 
3940
- path = state_kernel.idx2path[path_idx]
3941
- edge_idx = state_kernel.edgeuuid2idx[path.edge_uuid]
3942
- edge = state_kernel.edges[edge_idx]
4093
+ path_record = state_kernel.idx2pathrecord[path_idx]
4094
+ edge_record = state_kernel.uuid2edgerecord[path_record.edge_uuid]
3943
4095
 
3944
- 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)
3945
4097
 
3946
4098
  # Check if edge is too crowded for the number of players
3947
4099
  if state_kernel.game_config.num_players <= 3:
@@ -3952,12 +4104,14 @@ def is_path_open_to_player(state_kernel, path_idx, player_idx):
3952
4104
  return False
3953
4105
 
3954
4106
  # Check if any segment of the path has pieces from any player
3955
- if path.segments[0].pieces:
3956
- 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
3957
4111
 
3958
4112
  # Check if the player has enough pieces to claim the path
3959
4113
  player_pieces = state_kernel.players[player_idx].pieces
3960
- if len(player_pieces) < len(path.segments):
4114
+ if len(player_pieces) < len(path_record.segment_uuids):
3961
4115
  return False
3962
4116
 
3963
4117
  return True
@@ -4009,68 +4163,68 @@ def get_wild_unit_uuids(state_kernel):
4009
4163
 
4010
4164
 
4011
4165
  @dispatch(StateKernel, list, list, list)
4012
- def match_strict_wild(state_kernel, fulfillment, cards, segments):
4166
+ def match_strict_wild(state_kernel, fulfillment, cards, segment_records):
4013
4167
  new_fulfillment = fulfillment.copy()
4014
4168
  new_cards = cards.copy()
4015
4169
  wild_unit_uuids = get_wild_unit_uuids(state_kernel)
4016
- new_segments = []
4170
+ new_segment_records = []
4017
4171
 
4018
- for segment in segments:
4019
- if segment.unit_uuid and segment.unit_uuid in wild_unit_uuids:
4020
- 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)
4021
4175
  if first_matching_idx is not None:
4022
4176
  new_fulfillment.append(new_cards.pop(first_matching_idx))
4023
4177
  else:
4024
- new_segments.append(segment)
4178
+ new_segment_records.append(segment_record)
4025
4179
  else:
4026
- new_segments.append(segment)
4180
+ new_segment_records.append(segment_record)
4027
4181
 
4028
- return new_fulfillment, new_cards, new_segments
4182
+ return new_fulfillment, new_cards, new_segment_records
4029
4183
 
4030
4184
  @dispatch(StateKernel, list, list, list)
4031
- def match_non_wild_non_empty(state_kernel, fulfillment, cards, segments):
4185
+ def match_non_wild_non_empty(state_kernel, fulfillment, cards, segment_records):
4032
4186
  new_fulfillment = fulfillment.copy()
4033
4187
  new_cards = cards.copy()
4034
4188
  wild_unit_uuids = get_wild_unit_uuids(state_kernel)
4035
- new_segments = []
4189
+ new_segment_records = []
4036
4190
 
4037
- for segment in segments:
4038
- 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)
4039
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)
4040
4194
  first_matching_idx = first_strict_matching_idx if first_strict_matching_idx is not None else first_wild_matching_idx
4041
4195
  if first_matching_idx is not None:
4042
4196
  new_fulfillment.append(new_cards.pop(first_matching_idx))
4043
4197
  else:
4044
- new_segments.append(segment)
4198
+ new_segment_records.append(segment_record)
4045
4199
 
4046
- return new_fulfillment, new_cards, new_segments
4200
+ return new_fulfillment, new_cards, new_segment_records
4047
4201
 
4048
4202
 
4049
4203
  @dispatch(StateKernel, list, list, list)
4050
- def match_empty(state_kernel, fulfillment, cards, segments):
4051
- num_empty_segments = sum(1 for segment in segments if segment.unit_uuid is None)
4052
- if num_empty_segments == 0:
4053
- 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
4054
4208
 
4055
- tuples = get_uniform_sets(state_kernel, cards, num_empty_segments)
4209
+ tuples = get_uniform_sets(state_kernel, cards, num_empty_segment_records)
4056
4210
  # print(f"****************************************** len(cards): {len(cards)}")
4057
4211
  # print(f"****************************************** num_empty_segments: {num_empty_segments}")
4058
4212
  # print(f"Found {len(tuples)} tuples for empty segments: {tuples}")
4059
4213
  if len(tuples) == 0:
4060
- return fulfillment, cards, segments
4214
+ return fulfillment, cards, segment_records
4061
4215
 
4062
4216
  new_fulfillment = fulfillment.copy()
4063
4217
 
4064
- new_segments = []
4065
- for segment in segments:
4066
- if segment.unit_uuid:
4067
- 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)
4068
4222
 
4069
- first_tuple = tuples[0][:num_empty_segments]
4223
+ first_tuple = tuples[0][:num_empty_segment_records]
4070
4224
  # print(f"Using first tuple for empty segments: {first_tuple}")
4071
4225
  new_cards = list(set(cards) - set(first_tuple))
4072
4226
  new_fulfillment.extend(first_tuple)
4073
- return new_fulfillment, new_cards, new_segments
4227
+ return new_fulfillment, new_cards, new_segment_records
4074
4228
 
4075
4229
 
4076
4230
  @dispatch(StateKernel, list, int)
@@ -4130,48 +4284,48 @@ def get_sample_actionclaimpath(game, player_idx, path_idx):
4130
4284
 
4131
4285
  @dispatch(StateKernel, int, int)
4132
4286
  def get_sample_path_fulfillment(kernel, player_idx, path_idx):
4133
- path = kernel.idx2path[path_idx]
4287
+ path_record = kernel.idx2pathrecord[path_idx]
4134
4288
  remaining_card_uuids = [card_uuid for card_uuid in kernel.players[player_idx].cards if kernel.carduuid2card[card_uuid].deck_idx == 0]
4135
4289
  remaining_pieces = [
4136
4290
  piece_uuid
4137
4291
  for piece_uuid in kernel.players[player_idx].pieces
4138
4292
  if kernel.pieceuuid2piece[piece_uuid].piece_template_idx == 0
4139
4293
  ]
4140
- remaining_segments = path.segments
4294
+ remaining_segment_records = [kernel.uuid2segmentrecord[segment_uuid] for segment_uuid in path_record.segment_uuids]
4141
4295
  return get_path_fulfillment_from_resources(
4142
4296
  kernel,
4143
4297
  remaining_card_uuids,
4144
4298
  remaining_pieces,
4145
- remaining_segments,
4299
+ remaining_segment_records,
4146
4300
  )
4147
4301
 
4148
4302
  @dispatch(StateKernel, list, list, list)
4149
- 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):
4150
4304
 
4151
- if len(remaining_pieces) < len(remaining_segments):
4305
+ if len(remaining_pieces) < len(remaining_segment_records):
4152
4306
  print("Not enough pieces to fulfill the path segments")
4153
4307
  return None, None
4154
4308
 
4155
- piece_fulfillment = remaining_pieces[:len(remaining_segments)]
4309
+ piece_fulfillment = remaining_pieces[:len(remaining_segment_records)]
4156
4310
 
4157
4311
  card_fulfillment = []
4158
- 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)
4159
4313
 
4160
- if len(remaining_segments) == 0:
4314
+ if len(remaining_segment_records) == 0:
4161
4315
  return card_fulfillment, piece_fulfillment
4162
4316
  # Probably don't need this check, but we should unit test
4163
4317
  # elif len(get_wild_segments(remaining_segments)) > 0:
4164
4318
  # return None
4165
4319
 
4166
- card_fulfillment, remaining_card_uuids, remaining_segments = match_non_wild_non_empty(state_kernel, card_fulfillment, remaining_card_uuids, remaining_segments)
4167
- 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:
4168
4322
  return card_fulfillment, piece_fulfillment
4169
4323
  # Probably don't need this check, but we should unit test
4170
4324
  # elif len(get_non_wild_non_empty_segments(remaining_segments)) > 0:
4171
4325
  # return None
4172
4326
 
4173
- card_fulfillment, remaining_card_uuids, remaining_segments = match_empty(state_kernel, card_fulfillment, remaining_card_uuids, remaining_segments)
4174
- 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:
4175
4329
  return card_fulfillment, piece_fulfillment
4176
4330
 
4177
4331
  # print("get_path_fulfillment_from_resources (None, None) because remaining_segments is not empty: ", remaining_segments)
@@ -4548,6 +4702,52 @@ def isterminal(s):
4548
4702
 
4549
4703
  @dispatch(State)
4550
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
+ piece = k.pieceuuid2piece[piece_uuid]
4717
+ pieces.append(piece)
4718
+ segments.append(
4719
+ Segment2(
4720
+ uuid=segment_record.uuid,
4721
+ unit_uuid=segment_record.unit_uuid,
4722
+ pieces=pieces,
4723
+ )
4724
+ )
4725
+ paths.append(
4726
+ Path2(
4727
+ uuid=path_record.uuid,
4728
+ edge_uuid=path_record.edge_uuid,
4729
+ segments=segments,
4730
+ idx=path_record.idx
4731
+ )
4732
+ )
4733
+
4734
+ edge = BiEdge(
4735
+ uuid=edge_record.uuid,
4736
+ start_point_uuid=edge_record.start_point_uuid,
4737
+ end_point_uuid=edge_record.end_point_uuid,
4738
+ node_1_uuid=edge_record.node_1_uuid,
4739
+ node_2_uuid=edge_record.node_2_uuid,
4740
+ node_1_idx=edge_record.node_1_idx,
4741
+ node_2_idx=edge_record.node_2_idx,
4742
+ paths=paths,
4743
+ score=edge_record.score,
4744
+ )
4745
+ edges.append(edge)
4746
+
4747
+ # stopped here
4748
+
4749
+
4750
+
4551
4751
  return PublicState(
4552
4752
  deadlines=get_deadlines(s),
4553
4753
  game_started_at=s.kernel.game_config.started_at,
@@ -4562,7 +4762,7 @@ def getpublicstate(s):
4562
4762
  player_graphs=s.kernel.player_graphs_3,
4563
4763
  goals=s.kernel.goals,
4564
4764
  nodes=s.kernel.nodes,
4565
- edges=s.kernel.edges,
4765
+ edges=edges,
4566
4766
  regions=s.kernel.regions,
4567
4767
  decks=[getpublicdeck(s, deck) for deck in s.kernel.decks],
4568
4768
  piles=s.kernel.piles,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graph_games_proto
3
- Version: 0.3.2049
3
+ Version: 0.3.2077
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=XmmV1LeHVFb124gHfvHwivUnO8B231kEfpFYPZ746zY,193928
3
+ graph_games_proto/fns.py,sha256=vKVTt-EYziaIHajv8gxt5FMGTvQXW1eWh851DyxDyyY,201209
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.2049.dist-info/METADATA,sha256=Hs1pmJOZluWebeiniLQ1oUCQFlU4M43oPIO-oeHiukM,188
7
- graph_games_proto-0.3.2049.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
8
- graph_games_proto-0.3.2049.dist-info/top_level.txt,sha256=-4QSrBMf_MM4BGsr2QXBpqDx8c8k_OPnzGyFjqjakes,18
9
- graph_games_proto-0.3.2049.dist-info/RECORD,,
6
+ graph_games_proto-0.3.2077.dist-info/METADATA,sha256=o6EAHn38ZoToH0VTgQsZhG0xMVK6Zh3tFN7rbL20Y8o,188
7
+ graph_games_proto-0.3.2077.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
8
+ graph_games_proto-0.3.2077.dist-info/top_level.txt,sha256=-4QSrBMf_MM4BGsr2QXBpqDx8c8k_OPnzGyFjqjakes,18
9
+ graph_games_proto-0.3.2077.dist-info/RECORD,,