Package horizons :: Package scenario :: Module conditions
[hide private]
[frames] | no frames]

Source Code for Module horizons.scenario.conditions

  1  # ################################################### 
  2  # Copyright (C) 2008-2017 The Unknown Horizons Team 
  3  # team@unknown-horizons.org 
  4  # This file is part of Unknown Horizons. 
  5  # 
  6  # Unknown Horizons is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 2 of the License, or 
  9  # (at your option) any later version. 
 10  # 
 11  # This program is distributed in the hope that it will be useful, 
 12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  # GNU General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the 
 18  # Free Software Foundation, Inc., 
 19  # 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 20  # ################################################### 
 21   
 22  from horizons.constants import BUILDINGS, RES 
 23  from horizons.scheduler import Scheduler 
 24  from horizons.util.pathfinding.pather import StaticPather 
 25  from horizons.util.python.registry import Registry 
26 27 28 -class ConditionsRegistry(Registry):
29 """ 30 Class that holds all available conditions. 31 32 These are functions, that perform a certain check at one point in time. 33 There is no memory, e.g. if you lose progress, conditions just aren't true any more. 34 35 Condition checking is split up in 2 types: 36 37 1. possible condition change is notified somewhere in the game code 38 2. condition is checked periodically 39 """
40 - def __init__(self):
41 super().__init__() 42 self.check_periodically = []
43
44 - def register_function(self, func, periodically=False):
45 """Register condition. 46 47 `periodically` means that this condition function will be called periodically 48 by the ScenarioEventHandler. 49 """ 50 name = func.__name__ 51 self.registry[name] = func 52 # allow instance.example_condition_name to work, used as identifier to notify 53 # about condition change (see 1) 54 setattr(self, name, name) 55 56 if periodically: 57 self.check_periodically.append(name)
58 59 60 CONDITIONS = ConditionsRegistry() 61 register = CONDITIONS.register
62 63 64 @register() 65 -def settlements_num_greater(session, limit):
66 """Returns whether the number of player settlements is greater than *limit*.""" 67 return len(_get_player_settlements(session)) > limit
68
69 70 @register() 71 -def settler_level_greater(session, limit):
72 """Returns whether the highest tier reached in any player settlement is greater than *limit*.""" 73 return (session.world.player.settler_level > limit)
74
75 76 @register(periodically=True) 77 -def player_gold_greater(session, limit):
78 """Returns whether the player has more gold than *limit*.""" 79 # NOTE avoid circular import 80 from horizons.component.storagecomponent import StorageComponent 81 return (session.world.player.get_component(StorageComponent).inventory[RES.GOLD] > limit)
82
83 84 @register(periodically=True) 85 -def player_gold_less(session, limit):
86 """Returns whether the player has less gold than *limit*.""" 87 # NOTE avoid circular import 88 from horizons.component.storagecomponent import StorageComponent 89 return (session.world.player.get_component(StorageComponent).inventory[RES.GOLD] < limit)
90
91 92 @register(periodically=True) 93 -def settlement_balance_greater(session, limit):
94 """Returns whether the balance of at least one player settlement is higher than *limit*.""" 95 return any(settlement for settlement in _get_player_settlements(session) if 96 settlement.balance > limit)
97
98 99 @register(periodically=True) 100 -def player_balance_greater(session, limit):
101 """Returns whether the cumulative balance of all player settlements is higher than *limit*.""" 102 return (sum(settlement.balance for settlement in _get_player_settlements(session)) > limit)
103
104 105 @register(periodically=True) 106 -def settlement_inhabitants_greater(session, limit):
107 """Returns whether at least one player settlement has more than *limit* inhabitants.""" 108 return any(settlement for settlement in _get_player_settlements(session) if 109 settlement.inhabitants > limit)
110
111 112 @register(periodically=True) 113 -def player_inhabitants_greater(session, limit):
114 """Returns whether all player settlements combined have more than *limit* inhabitants.""" 115 return (sum(settlement.inhabitants for settlement in _get_player_settlements(session)) > limit)
116
117 118 @register() 119 -def building_num_of_type_greater(session, building_class, limit):
120 """Returns whether any player settlement has more than *limit* buildings of type *building_class*.""" 121 for settlement in _get_player_settlements(session): 122 if len(settlement.buildings_by_id[building_class]) > limit: 123 return True 124 return False
125
126 127 @register(periodically=True) 128 -def player_res_stored_greater(session, resource, limit):
129 """Returns whether all player settlements combined have more than *limit* 130 of *resource* in their inventories.""" 131 # NOTE avoid circular import 132 from horizons.component.storagecomponent import StorageComponent 133 return (sum(settlement.get_component(StorageComponent).inventory[resource] for settlement in _get_player_settlements(session)) > limit)
134
135 136 @register(periodically=True) 137 -def player_res_stored_less(session, resource, limit):
138 """Returns whether all player settlements combined have less than *limit* 139 of *resource* in their inventories.""" 140 # NOTE avoid circular import 141 from horizons.component.storagecomponent import StorageComponent 142 return (sum(settlement.get_component(StorageComponent).inventory[resource] for settlement in _get_player_settlements(session)) < limit)
143
144 145 @register(periodically=True) 146 -def settlement_res_stored_greater(session, resource, limit):
147 """Returns whether at least one player settlement has more than *limit* 148 of *resource* in its inventory.""" 149 # NOTE avoid circular import 150 from horizons.component.storagecomponent import StorageComponent 151 return any(settlement for settlement in _get_player_settlements(session) if 152 settlement.get_component(StorageComponent).inventory[resource] > limit)
153
154 155 @register(periodically=True) 156 -def player_total_earnings_greater(session, limit):
157 """Returns whether the player has earned more than *limit* money with 158 trading in all settlements combined. Profit = sell_income - buy_expenses.""" 159 total_earning = 0 160 for settlement in _get_player_settlements(session): 161 total_earning += settlement.total_earnings 162 return total_earning > limit
163
164 165 @register(periodically=True) 166 -def settlement_produced_res_greater(session, resource, limit):
167 """Returns whether more than *limit* resource have been produced in any player settlement.""" 168 return any(settlement for settlement in _get_player_settlements(session) if 169 settlement.produced_res.get(resource, 0) > limit)
170
171 172 @register(periodically=True) 173 -def player_produced_res_greater(session, resource, limit):
174 """Returns whether more than *limit* of the resource *resource* 175 have been produced in all player settlements combined.""" 176 return sum(settlement.produced_res.get(resource, 0) for settlement in _get_player_settlements(session)) > limit
177
178 179 @register(periodically=True) 180 -def buildings_connected_to_warehouse_gt(session, building_class, limit):
181 """Checks whether more than *limit* of *building_class* type buildings are 182 connected to a warehouse or storage.""" 183 return (_building_connected_to_any_of(session, building_class, 184 BUILDINGS.WAREHOUSE, BUILDINGS.STORAGE) > limit)
185
186 187 @register(periodically=True) 188 -def buildings_connected_to_warehouse_lt(session, building_class, limit):
189 """Checks whether less than *limit* of *building_class* type buildings are 190 connected to a warehouse or storage.""" 191 return (_building_connected_to_any_of(session, building_class, 192 BUILDINGS.WAREHOUSE, BUILDINGS.STORAGE) < limit)
193
194 195 @register(periodically=True) 196 -def buildings_connected_to_building_gt(session, building_class, class2, limit):
197 """Checks whether more than *limit* of *building_class* type buildings are 198 connected to any building of type *class2*.""" 199 return (_building_connected_to_any_of(session, building_class, class2) > limit)
200
201 202 @register(periodically=True) 203 -def buildings_connected_to_building_lt(session, building_class, class2, limit):
204 """Checks whether less than *limit* of *building_class* type buildings are 205 connected to any building of type *class2*.""" 206 return (_building_connected_to_any_of(session, building_class, class2) < limit)
207
208 209 @register(periodically=True) 210 -def building_in_range(session, building_class1, building_class2):
211 """Checks whether there is a building_class2 in range of a building_class1.""" 212 return _building_in_range_of(session, building_class1, building_class2)
213
214 215 @register(periodically=True) 216 -def time_passed(session, seconds):
217 """Returns whether at least *seconds* seconds have passed since the game started.""" 218 return (Scheduler().cur_tick >= Scheduler().get_ticks(seconds))
219
220 221 @register() 222 -def game_started(session):
223 """Always return True. Used for one-off events""" 224 return True
225
226 227 @register() 228 -def var_eq(session, variable, value):
229 """Returns whether *variable* has a value equal to *value*. 230 Returns False if variable was never set in the current session.""" 231 if variable not in _get_scenario_vars(session): 232 return False 233 return (_get_scenario_vars(session)[variable] == value)
234
235 236 @register() 237 -def var_gt(session, variable, value):
238 """Returns whether *variable* has a value greater than *value*. 239 Returns False if variable was never set in the current session.""" 240 if variable not in _get_scenario_vars(session): 241 return False 242 return (_get_scenario_vars(session)[variable] > value)
243
244 245 @register() 246 -def var_lt(session, variable, value):
247 """Returns whether *variable* has a value less than *value*. 248 Returns False if variable was never set in the current session.""" 249 if variable not in _get_scenario_vars(session): 250 return False 251 return (_get_scenario_vars(session)[variable] < value)
252
253 254 -def _get_player_settlements(session):
255 """Helper generator, returns settlements of local player.""" 256 return session.world.player.settlements
257
258 259 -def _get_scenario_vars(session):
260 return session.scenario_eventhandler._scenario_variables
261
262 263 -def _building_connected_to_any_of(session, building_class, *classes):
264 """Returns the exact amount of buildings of type *building_class* that are 265 connected to any building of a class in the building type list *classes*. 266 Counts all player settlements.""" 267 building_to_check = [] 268 check_connection = [] 269 for settlement in _get_player_settlements(session): 270 building_to_check.extend(settlement.buildings_by_id[building_class]) 271 for b_class in classes: 272 for building in settlement.buildings_by_id[b_class]: 273 check_connection.append(building) 274 found_connected = 0 275 for building in building_to_check: 276 for check in check_connection: 277 if StaticPather.get_path_on_roads(building.island, building, check): 278 found_connected += 1 279 break 280 return found_connected
281
282 283 @register(periodically=True) 284 -def player_number_of_ships_gt(session, player_id, limit):
285 """Returns whether the number of ships owned by the player *player_id* is greater than *limit*.""" 286 number_of_ships = len([s for s in session.world.ships if s.owner.worldid == player_id]) 287 return number_of_ships > limit
288
289 290 @register(periodically=True) 291 -def player_number_of_ships_lt(session, player_id, limit):
292 """Returns whether the number of ships owned by the player *player_id* is less than *limit*.""" 293 number_of_ships = len([s for s in session.world.ships if s.owner.worldid == player_id]) 294 return number_of_ships < limit
295
296 297 -def _building_connected_to_all_of(session, building_class, *classes):
298 """Returns the exact amount of buildings of type *building_class* that are 299 connected to any building of each class in *classes*. Counts all player settlements."""
300 #TODO
301 302 303 -def _building_in_range_of(session, building_class, *classes):
304 """Returns whether there is any building of type *building_class* 305 in range of any building of a class in the building type list *classes*. 306 Counts all player settlements.""" 307 308 for settlement in _get_player_settlements(session): # iterate through settlements 309 for building in settlement.buildings_by_id[building_class]: # iterate through all buildings of building_class 310 for other_class in classes: # iterate through all given other classes 311 for building2 in settlement.buildings_by_id[other_class]: # iterate through all buildings of other_class 312 if building.position.distance(building2.position) <= building.radius: # building in range of building2 313 return True 314 return False # building not found in range
315