Ejemplo n.º 1
0
	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)
Ejemplo n.º 2
0
	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)
Ejemplo n.º 3
0
	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)
Ejemplo n.º 4
0
	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
Ejemplo n.º 5
0
 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 _load(self, db, worldid, success_callback, failure_callback):
		db_result = db("SELECT land_manager, ship, warehouse_builder, state FROM ai_mission_found_settlement WHERE rowid = ?", worldid)[0]
		self.land_manager = WorldObject.get_object_by_id(db_result[0])
		self.warehouse_location = Builder.load(db, db_result[2], self.land_manager)
		self.warehouse = None
		self.state = self.missionStates[db_result[3]]
		super(FoundSettlement, self).load(db, worldid, success_callback, failure_callback, WorldObject.get_object_by_id(db_result[1]))

		if self.state == self.missionStates.moving:
			self.ship.add_move_callback(Callback(self._reached_destination_area))
			self.ship.add_blocked_callback(Callback(self._move_to_destination_area))
		else:
			assert False, 'invalid state'
Ejemplo n.º 7
0
	def _load(self, db, worldid, success_callback, failure_callback):
		db_result = db("SELECT land_manager, ship, warehouse_builder, state FROM ai_mission_found_settlement WHERE rowid = ?", worldid)[0]
		self.land_manager = WorldObject.get_object_by_id(db_result[0])
		self.warehouse_location = Builder.load(db, db_result[2], self.land_manager)
		self.warehouse = None
		self.state = self.missionStates[db_result[3]]
		super(FoundSettlement, self).load(db, worldid, success_callback, failure_callback, WorldObject.get_object_by_id(db_result[1]))

		if self.state == self.missionStates.moving:
			self.ship.add_move_callback(Callback(self._reached_destination_area))
			self.ship.add_blocked_callback(Callback(self._move_to_destination_area))
		else:
			assert False, 'invalid state'
Ejemplo n.º 8
0
	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
Ejemplo n.º 9
0
 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
Ejemplo n.º 10
0
	def find_warehouse_location(cls, ship, land_manager):
		"""
		Finds a location for the warehouse on the given island
		@param LandManager: the LandManager of the island
		@return _BuildPosition: a possible build location
		"""
		moves = [(-1, 0), (0, -1), (0, 1), (1, 0)]
		island = land_manager.island
		world = island.session.world
		personality = land_manager.owner.personality_manager.get('FoundSettlement')
		options = []

		for (x, y), tile in sorted(island.ground_map.iteritems()):
			ok = False
			for x_offset, y_offset in moves:
				for d in xrange(2, 6):
					coords = (x + d * x_offset, y + d * y_offset)
					if coords in world.water_body and world.water_body[coords] == world.water_body[ship.position.to_tuple()]:
						# the planned warehouse should be reachable from the ship's water body
						ok = True
			if not ok:
				continue

			build_info = None
			point = Point(x, y)
			warehouse = Builder(BUILDINGS.WAREHOUSE, land_manager, point, ship = ship)
			if not warehouse:
				continue

			cost = 0
			for coords in land_manager.village:
				distance = point.distance(coords)
				if distance < personality.too_close_penalty_threshold:
					cost += personality.too_close_constant_penalty + personality.too_close_linear_penalty / (distance + 1.0)
				else:
					cost += distance

			for settlement_manager in land_manager.owner.settlement_managers:
				cost += warehouse.position.distance(settlement_manager.settlement.warehouse.position) * personality.linear_warehouse_penalty

			options.append((cost, warehouse))

		for _, build_info in sorted(options):
			(x, y) = build_info.position.get_coordinates()[4]
			if ship.check_move(Circle(Point(x, y), BUILDINGS.BUILD.MAX_BUILDING_SHIP_DISTANCE)):
				return build_info
		return None
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
	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)
Ejemplo n.º 13
0
    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)
Ejemplo n.º 14
0
	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)
Ejemplo n.º 15
0
    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)