def execute(self): (result, building) = super(LumberjackEvaluator, self).execute() if result != BUILD_RESULT.OK: return (result, None) for coords in building.position.get_radius_coordinates(Entities.buildings[BUILDINGS.LUMBERJACK_CLASS].radius): if coords in self.area_builder.plan and self.area_builder.plan[coords][0] == BUILDING_PURPOSE.NONE: self.area_builder.register_change(coords[0], coords[1], BUILDING_PURPOSE.TREE, None) # TODO: don't ignore the return value Builder.create(BUILDINGS.TREE_CLASS, self.area_builder.land_manager, Point(coords[0], coords[1])).execute() return (BUILD_RESULT.OK, building)
def execute(self): (result, building) = super(LumberjackEvaluator, self).execute() if result != BUILD_RESULT.OK: return (result, None) for coords in building.position.get_radius_coordinates( Entities.buildings[BUILDINGS.LUMBERJACK].radius): if coords in self.area_builder.plan and self.area_builder.plan[ coords][0] == BUILDING_PURPOSE.NONE: self.area_builder.register_change(coords[0], coords[1], BUILDING_PURPOSE.TREE, None) # TODO: don't ignore the return value Builder.create(BUILDINGS.TREE, self.area_builder.land_manager, Point(coords[0], coords[1])).execute() return (BUILD_RESULT.OK, building)
def create(cls, area_builder, x, y, new_field_purpose): building_id = None if new_field_purpose == BUILDING_PURPOSE.POTATO_FIELD: building_id = BUILDINGS.POTATO_FIELD elif new_field_purpose == BUILDING_PURPOSE.PASTURE: building_id = BUILDINGS.PASTURE elif new_field_purpose == BUILDING_PURPOSE.SUGARCANE_FIELD: building_id = BUILDINGS.SUGARCANE_FIELD elif new_field_purpose == BUILDING_PURPOSE.TOBACCO_FIELD: building_id = BUILDINGS.TOBACCO_FIELD builder = Builder.create(building_id, area_builder.land_manager, Point(x, y)) if not builder: return None value = 0 personality = area_builder.owner.personality_manager.get('ModifiedFieldEvaluator') if new_field_purpose == BUILDING_PURPOSE.POTATO_FIELD: value += personality.add_potato_field_value elif new_field_purpose == BUILDING_PURPOSE.PASTURE: value += personality.add_pasture_value elif new_field_purpose == BUILDING_PURPOSE.SUGARCANE_FIELD: value += personality.add_sugarcane_field_value elif new_field_purpose == BUILDING_PURPOSE.TOBACCO_FIELD: value += personality.add_tobacco_field_value old_field_purpose = area_builder.plan[(x, y)][0] if old_field_purpose == BUILDING_PURPOSE.POTATO_FIELD: value -= personality.remove_unused_potato_field_penalty elif old_field_purpose == BUILDING_PURPOSE.PASTURE: value -= personality.remove_unused_pasture_penalty elif old_field_purpose == BUILDING_PURPOSE.SUGARCANE_FIELD: value -= personality.remove_unused_sugarcane_field_penalty elif old_field_purpose == BUILDING_PURPOSE.TOBACCO_FIELD: value -= personality.remove_unused_tobacco_field_penalty return ModifiedFieldEvaluator(area_builder, builder, value, old_field_purpose)
def make_builder(self, building_id, x, y, needs_collector, orientation = 0): """ Return a Builder object containing the info. If it is impossible to build it then the return value could either be None or a Builder object that evaluates to False. """ return Builder.create(building_id, self.land_manager, Point(x, y), orientation = orientation)
def build_road(self, path): """Build the road given a valid path or None. Return True if it worked, False if the path was None.""" if path is not None: for x, y in path: self.register_change(x, y, BUILDING_PURPOSE.ROAD, None) building = self.island.ground_map[(x, y)].object if building is not None and building.id == BUILDINGS.TRAIL: continue assert Builder.create(BUILDINGS.TRAIL, self.land_manager, Point(x, y)).execute() return path is not None
def make_builder(self, building_id, x, y, needs_collector, orientation=0): """ Return a Builder object containing the info. If it is impossible to build it then the return value could either be None or a Builder object that evaluates to False. """ return Builder.create(building_id, self.land_manager, Point(x, y), orientation=orientation)
def build_roads(self): """Try to build all roads in the village area, record the result in the field roads_built.""" all_built = True for coords, (purpose, (section, _)) in self.plan.iteritems(): if section > self.current_section: all_built = False continue if purpose != BUILDING_PURPOSE.ROAD: continue object = self.island.ground_map[coords].object if object is not None and object.id == BUILDINGS.TRAIL_CLASS: continue if Builder.create(BUILDINGS.TRAIL_CLASS, self.land_manager, Point(coords[0], coords[1])).execute() is None: all_built = False self.roads_built = all_built
def build_roads(self): """Try to build all roads in the village area, record the result in the field roads_built.""" all_built = True for coords, (purpose, (section, _)) in self.plan.iteritems(): if section > self.current_section: all_built = False continue if purpose != BUILDING_PURPOSE.ROAD: continue object = self.island.ground_map[coords].object if object is not None and object.id == BUILDINGS.TRAIL: continue if Builder.create(BUILDINGS.TRAIL, self.land_manager, Point(coords[0], coords[1])).execute() is None: all_built = False self.roads_built = all_built
def build(self, settlement_manager, resource_id): production_builder = settlement_manager.production_builder purpose = self.get_purpose(resource_id) if not production_builder.unused_fields[purpose]: return (BUILD_RESULT.NEED_PARENT_FIRST, None) if not self.have_resources(settlement_manager): return (BUILD_RESULT.NEED_RESOURCES, None) assert len(production_builder.unused_fields[purpose]) > 0, "expected field spot to be available" coords = production_builder.unused_fields[purpose][0] builder = Builder.create(self.id, settlement_manager.land_manager, Point(coords[0], coords[1])) building = builder.execute() if not building: return (BUILD_RESULT.UNKNOWN_ERROR, None) production_builder.unused_fields[purpose].popleft() production_builder.register_change(coords[0], coords[1], purpose, None) return (BUILD_RESULT.OK, building)
def build(self, settlement_manager, resource_id): production_builder = settlement_manager.production_builder purpose = self.get_purpose(resource_id) if not production_builder.unused_fields[purpose]: return (BUILD_RESULT.NEED_PARENT_FIRST, None) if not self.have_resources(settlement_manager): return (BUILD_RESULT.NEED_RESOURCES, None) assert production_builder.unused_fields[purpose], 'expected field spot to be available' coords = production_builder.unused_fields[purpose][0] builder = Builder.create(self.id, settlement_manager.land_manager, Point(coords[0], coords[1])) building = builder.execute() if not building: return (BUILD_RESULT.UNKNOWN_ERROR, None) production_builder.unused_fields[purpose].popleft() production_builder.register_change(coords[0], coords[1], purpose, None) return (BUILD_RESULT.OK, building)
def create(cls, area_builder, x, y, new_field_purpose): building_id = None if new_field_purpose == BUILDING_PURPOSE.POTATO_FIELD: building_id = BUILDINGS.POTATO_FIELD elif new_field_purpose == BUILDING_PURPOSE.PASTURE: building_id = BUILDINGS.PASTURE elif new_field_purpose == BUILDING_PURPOSE.SUGARCANE_FIELD: building_id = BUILDINGS.SUGARCANE_FIELD elif new_field_purpose == BUILDING_PURPOSE.TOBACCO_FIELD: building_id = BUILDINGS.TOBACCO_FIELD builder = Builder.create(building_id, area_builder.land_manager, Point(x, y)) if not builder: return None value = 0 personality = area_builder.owner.personality_manager.get( 'ModifiedFieldEvaluator') if new_field_purpose == BUILDING_PURPOSE.POTATO_FIELD: value += personality.add_potato_field_value elif new_field_purpose == BUILDING_PURPOSE.PASTURE: value += personality.add_pasture_value elif new_field_purpose == BUILDING_PURPOSE.SUGARCANE_FIELD: value += personality.add_sugarcane_field_value elif new_field_purpose == BUILDING_PURPOSE.TOBACCO_FIELD: value += personality.add_tobacco_field_value old_field_purpose = area_builder.plan[(x, y)][0] if old_field_purpose == BUILDING_PURPOSE.POTATO_FIELD: value -= personality.remove_unused_potato_field_penalty elif old_field_purpose == BUILDING_PURPOSE.PASTURE: value -= personality.remove_unused_pasture_penalty elif old_field_purpose == BUILDING_PURPOSE.SUGARCANE_FIELD: value -= personality.remove_unused_sugarcane_field_penalty elif old_field_purpose == BUILDING_PURPOSE.TOBACCO_FIELD: value -= personality.remove_unused_tobacco_field_penalty return ModifiedFieldEvaluator(area_builder, builder, value, old_field_purpose)
def _create(cls, area_builder, farm_x, farm_y, road_dx, road_dy, min_fields, field_purpose): builder = area_builder.make_builder(BUILDINGS.FARM, farm_x, farm_y, True) if not builder: return None farm_plan = {} # place the farm area road existing_roads = 0 for other_offset in xrange(-3, 6): coords = None if road_dx == 0: coords = (farm_x + other_offset, farm_y + road_dy) else: coords = (farm_x + road_dx, farm_y + other_offset) if not cls._suitable_for_road(area_builder, coords): return None if coords in area_builder.plan and area_builder.plan[coords][0] == BUILDING_PURPOSE.NONE: road = Builder.create(BUILDINGS.TRAIL, area_builder.land_manager, Point(coords[0], coords[1])) if road: farm_plan[coords] = (BUILDING_PURPOSE.ROAD, road) else: farm_plan = None break else: existing_roads += 1 if farm_plan is None: return None # impossible to build some part of the road # place the fields fields = 0 for (dx, dy) in cls.__field_offsets: if fields >= 8: break # unable to place more anyway coords = (farm_x + dx, farm_y + dy) field = area_builder.make_builder(BUILDINGS.POTATO_FIELD, coords[0], coords[1], False) if not field: continue for coords2 in field.position.tuple_iter(): if coords2 in farm_plan: field = None break if field is None: continue # some part of the area is reserved for something else fields += 1 for coords2 in field.position.tuple_iter(): farm_plan[coords2] = (BUILDING_PURPOSE.RESERVED, None) farm_plan[coords] = (field_purpose, None) if fields < min_fields: return None # go for the most fields possible # add the farm itself to the plan for coords in builder.position.tuple_iter(): farm_plan[coords] = (BUILDING_PURPOSE.RESERVED, None) farm_plan[(farm_x, farm_y)] = (BUILDING_PURPOSE.FARM, builder) # calculate the alignment value and the rectangle that contains the whole farm alignment = 0 min_x, max_x, min_y, max_y = None, None, None, None for x, y in farm_plan: min_x = x if min_x is None or min_x > x else min_x max_x = x if max_x is None or max_x < x else max_x min_y = y if min_y is None or min_y > y else min_y max_y = y if max_y is None or max_y < y else max_y for dx, dy in cls.__moves: coords = (x + dx, y + dy) if coords in farm_plan: continue if coords not in area_builder.plan or area_builder.plan[coords][0] != BUILDING_PURPOSE.NONE: alignment += 1 # calculate the value of the farm road end points (larger is better) personality = area_builder.owner.personality_manager.get('FarmEvaluator') immediate_connections = 0 for other_offset in [-4, 6]: if road_dx == 0: coords = (farm_x + other_offset, farm_y + road_dy) else: coords = (farm_x + road_dx, farm_y + other_offset) if coords in area_builder.land_manager.roads: immediate_connections += personality.immediate_connection_road elif coords in area_builder.plan: if area_builder.plan[coords][0] == BUILDING_PURPOSE.NONE: immediate_connections += personality.immediate_connection_free extra_space = (max_x - min_x + 1) * (max_y - min_y + 1) - 9 * (fields + 2) value = fields + existing_roads * personality.existing_road_importance + \ alignment * personality.alignment_importance - extra_space * personality.wasted_space_penalty + \ immediate_connections * personality.immediate_connection_importance return FarmEvaluator(area_builder, builder, value, farm_plan, fields, field_purpose)
def _create(cls, area_builder, farm_x, farm_y, road_dx, road_dy, min_fields, field_purpose): builder = area_builder.make_builder(BUILDINGS.FARM, farm_x, farm_y, True) if not builder: return None farm_plan = {} # place the farm area road existing_roads = 0 for other_offset in xrange(-3, 6): coords = None if road_dx == 0: coords = (farm_x + other_offset, farm_y + road_dy) else: coords = (farm_x + road_dx, farm_y + other_offset) if not cls._suitable_for_road(area_builder, coords): return None if coords in area_builder.plan and area_builder.plan[coords][ 0] == BUILDING_PURPOSE.NONE: road = Builder.create(BUILDINGS.TRAIL, area_builder.land_manager, Point(coords[0], coords[1])) if road: farm_plan[coords] = (BUILDING_PURPOSE.ROAD, road) else: farm_plan = None break else: existing_roads += 1 if farm_plan is None: return None # impossible to build some part of the road # place the fields fields = 0 for (dx, dy) in cls.__field_offsets: if fields >= 8: break # unable to place more anyway coords = (farm_x + dx, farm_y + dy) field = area_builder.make_builder(BUILDINGS.POTATO_FIELD, coords[0], coords[1], False) if not field: continue for coords2 in field.position.tuple_iter(): if coords2 in farm_plan: field = None break if field is None: continue # some part of the area is reserved for something else fields += 1 for coords2 in field.position.tuple_iter(): farm_plan[coords2] = (BUILDING_PURPOSE.RESERVED, None) farm_plan[coords] = (field_purpose, None) if fields < min_fields: return None # go for the most fields possible # add the farm itself to the plan for coords in builder.position.tuple_iter(): farm_plan[coords] = (BUILDING_PURPOSE.RESERVED, None) farm_plan[(farm_x, farm_y)] = (BUILDING_PURPOSE.FARM, builder) # calculate the alignment value and the rectangle that contains the whole farm alignment = 0 min_x, max_x, min_y, max_y = None, None, None, None for x, y in farm_plan: min_x = x if min_x is None or min_x > x else min_x max_x = x if max_x is None or max_x < x else max_x min_y = y if min_y is None or min_y > y else min_y max_y = y if max_y is None or max_y < y else max_y for dx, dy in cls.__moves: coords = (x + dx, y + dy) if coords in farm_plan: continue if coords not in area_builder.plan or area_builder.plan[ coords][0] != BUILDING_PURPOSE.NONE: alignment += 1 # calculate the value of the farm road end points (larger is better) personality = area_builder.owner.personality_manager.get( 'FarmEvaluator') immediate_connections = 0 for other_offset in [-4, 6]: if road_dx == 0: coords = (farm_x + other_offset, farm_y + road_dy) else: coords = (farm_x + road_dx, farm_y + other_offset) if coords in area_builder.land_manager.roads: immediate_connections += personality.immediate_connection_road elif coords in area_builder.plan: if area_builder.plan[coords][0] == BUILDING_PURPOSE.NONE: immediate_connections += personality.immediate_connection_free extra_space = (max_x - min_x + 1) * (max_y - min_y + 1) - 9 * (fields + 2) value = fields + existing_roads * personality.existing_road_importance + \ alignment * personality.alignment_importance - extra_space * personality.wasted_space_penalty + \ immediate_connections * personality.immediate_connection_importance return FarmEvaluator(area_builder, builder, value, farm_plan, fields, field_purpose)