9
9
from lib .gameplay .bank import Bank
10
10
from lib .gameplay .board import Board
11
11
from functools import reduce
12
+ from lib .gameplay .hex import Hex
12
13
from typing import Union
13
14
from lib .gameplay .hex import ResourceType
14
15
import logging
@@ -57,25 +58,39 @@ def largest_army_size(self) -> int:
57
58
)
58
59
59
60
def points (
60
- self , players : list ["Player" ], playerWithLongestRoad : Union ["Player" , None ]
61
+ self ,
62
+ playerWithLongestRoad : Union ["Player" , None ],
63
+ playerWithLargestArmy : Union ["Player" , None ],
61
64
) -> int :
62
- # TODO: Add support for largest army and longest road
63
65
return (
64
66
reduce (lambda acc , curr : acc + curr .get_points (), self .cities , 0 )
65
67
+ reduce (lambda acc , curr : acc + curr .get_points (), self .settlements , 0 )
66
68
+ reduce (
67
69
lambda acc , curr : acc + curr .get_points (), self .development_cards , 0
68
70
)
69
71
+ (2 if playerWithLongestRoad == self else 0 )
72
+ + (2 if playerWithLargestArmy == self else 0 )
70
73
)
71
74
75
+ def give_development_card (self , card : DevelopmentCard ) -> None :
76
+ self .development_cards .append (card )
77
+
72
78
def get_active_settlements (self ) -> list [Settlement ]:
73
79
return [
74
80
settlement
75
81
for settlement in self .settlements
76
82
if settlement .vertex is not None
77
83
]
78
84
85
+ def num_active_settlements (self ) -> int :
86
+ return len (self .get_active_settlements ())
87
+
88
+ def get_active_cities (self ) -> list [City ]:
89
+ return [city for city in self .cities if city .vertex is not None ]
90
+
91
+ def num_active_cities (self ) -> int :
92
+ return len (self .get_active_cities ())
93
+
79
94
def get_unplaced_settlement (self ) -> Union [Settlement , None ]:
80
95
for settlement in self .settlements :
81
96
if settlement .position is None :
@@ -142,6 +157,9 @@ def take_resources_from_player(
142
157
raise ValueError ("Player does not have required resources" )
143
158
return cards
144
159
160
+ def give_resource_to_player (self , card : ResourceCard ) -> None :
161
+ self .resources .append (card )
162
+
145
163
def resource_counts (self ) -> dict [ResourceType , int ]:
146
164
counts = {resource : 0 for resource in ResourceType }
147
165
for card in self .resources :
@@ -162,14 +180,11 @@ def can_build_city(self) -> bool:
162
180
resource_counts = self .resource_counts ()
163
181
return (
164
182
self .unplaced_city_count () > 0
165
- and len (self .current_settlements ()) > 0
183
+ and len (self .get_active_cities ()) > 0
166
184
and resource_counts [ResourceType .WHEAT ] >= 2
167
185
and resource_counts [ResourceType .ORE ] >= 3
168
186
)
169
187
170
- def current_settlements (self ) -> list [Settlement ]:
171
- return [s for s in self .settlements if s .position is not None ]
172
-
173
188
def can_build_road (self ) -> bool :
174
189
resource_counts = self .resource_counts ()
175
190
return (
@@ -178,11 +193,17 @@ def can_build_road(self) -> bool:
178
193
and resource_counts [ResourceType .WOOD ] >= 1
179
194
)
180
195
181
- def pop_least_valuable_resource (self ) -> ResourceCard :
182
- # TODO: Implement better logic for choosing which cards to return for manual mode
196
+ def pop_least_valuable_resource (self ) -> Union [ResourceCard , None ]:
183
197
if len (self .resources ) == 0 :
184
- raise ValueError ("Player has no resources" )
185
- return self .resources .pop ()
198
+ return None
199
+
200
+ resource_rankings = reversed (self .rank_resource_values ())
201
+ resource_counts = self .resource_counts ()
202
+
203
+ for resource in resource_rankings :
204
+ if resource_counts [resource ] > 0 :
205
+ [card ] = self .take_resources_from_player ([resource ])
206
+ return card
186
207
187
208
def split_cards (self , bank : Bank ):
188
209
if len (self .resources ) > 7 :
@@ -193,16 +214,9 @@ def split_cards(self, bank: Bank):
193
214
def play_development_card (self , card : DevelopmentCard ):
194
215
pass
195
216
196
- def trade (
197
- self , other : "Player" , offer : list [ResourceCard ], request : list [ResourceCard ]
198
- ):
199
- pass
200
-
201
- def trade_bank (self , offer : list [ResourceCard ], request : list [ResourceCard ]):
202
- pass
203
-
204
- def trade_port (self , offer : list [ResourceCard ], request : list [ResourceCard ]):
205
- pass
217
+ def trade_bank (self , offer : list [ResourceType ], request : ResourceType , bank : Bank ):
218
+ bank .return_cards (self .take_resources_from_player (offer ))
219
+ self .resources .append (bank .get_card (request ))
206
220
207
221
def build_settlement (self , board : Board , vertexLoc : int , bank : Bank ):
208
222
bank .purchase_settlement (self )
@@ -219,10 +233,35 @@ def build_road(self, board: Board, edgeLoc: int, bank: Bank):
219
233
def buy_development_card (self , bank : Bank ):
220
234
bank .purchase_dev_card (self )
221
235
222
- def rob (self , board : Board , bank : Bank ):
223
- random_hex = random .choice (board .get_hexes ())
224
- board .move_robber (random_hex .id )
225
- # TODO: Implement logic for what happens when robber moves to a hex with a player's settlement
236
+ def get_hex_to_rob (self , board : Board , bank : Bank ) -> Hex :
237
+ return random .choice (board .get_hexes ())
238
+
239
+ def choose_player_to_rob (
240
+ self , players : list ["Player" ], board : Board , bank : Bank
241
+ ) -> Union ["Player" , None ]:
242
+ return None if len (players ) == 0 else players [0 ]
243
+
244
+ def rank_resource_values (self ) -> list [ResourceType ]:
245
+ """Returns resources valuable to the player from most valuable to least valuable"""
246
+ return [
247
+ ResourceType .ORE ,
248
+ ResourceType .BRICK ,
249
+ ResourceType .SHEEP ,
250
+ ResourceType .WHEAT ,
251
+ ResourceType .WOOD ,
252
+ ]
253
+
254
+ def rob (self ) -> Union [ResourceCard , None ]:
255
+ return self .pop_least_valuable_resource ()
256
+
257
+ def move_robber (self , board : Board , bank : Bank ) -> None :
258
+ hex = self .get_hex_to_rob (board , bank )
259
+ board .move_robber (hex .id )
260
+
261
+ settled_players = hex .get_settled_players ()
262
+ player_to_rob = self .choose_player_to_rob (settled_players , board , bank )
263
+ if player_to_rob is not None :
264
+ player_to_rob .rob ()
226
265
227
266
def take_turn (self , board : Board , bank : Bank , players : list ["Player" ]):
228
267
pass
0 commit comments