Package horizons :: Package ai :: Package aiplayer :: Package building :: Module lumberjack
[hide private]
[frames] | no frames]

Source Code for Module horizons.ai.aiplayer.building.lumberjack

  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 typing import List, Set, Tuple 
 23   
 24  from horizons.ai.aiplayer.basicbuilder import BasicBuilder 
 25  from horizons.ai.aiplayer.building import AbstractBuilding 
 26  from horizons.ai.aiplayer.buildingevaluator import BuildingEvaluator 
 27  from horizons.ai.aiplayer.constants import BUILD_RESULT, BUILDING_PURPOSE 
 28  from horizons.constants import BUILDINGS 
 29  from horizons.entities import Entities 
 30  from horizons.util.shapes import Rect 
31 32 33 -class AbstractLumberjack(AbstractBuilding):
34 @property
35 - def evaluator_class(self):
37 38 @classmethod
39 - def register_buildings(cls):
41
42 43 -class LumberjackEvaluator(BuildingEvaluator):
44 __template_outline = None # type: List[Set[Tuple[int, int]]] 45 __radius_offsets = None # type: List[Tuple[int, int]] 46 47 @classmethod
48 - def __init_outline(cls):
49 """Save a template outline that surrounds a lumberjack.""" 50 position = Rect.init_from_topleft_and_size_tuples((0, 0), Entities.buildings[BUILDINGS.LUMBERJACK].size) 51 moves = [(-1, 0), (0, -1), (0, 1), (1, 0)] 52 coords_list = set(position.get_radius_coordinates(Entities.buildings[BUILDINGS.LUMBERJACK].radius, True)) 53 54 result = set() 55 for x, y in coords_list: 56 for dx, dy in moves: 57 coords = (x + dx, y + dy) 58 if coords not in coords_list: 59 result.add(coords) 60 cls.__template_outline = sorted(list(result)) 61 cls.__radius_offsets = sorted(position.get_radius_coordinates(Entities.buildings[BUILDINGS.LUMBERJACK].radius))
62 63 @classmethod
64 - def _get_outline(cls, x, y):
65 result = [] 66 for dx, dy in cls.__template_outline: 67 result.append((x + dx, y + dy)) 68 return result
69 70 @classmethod
71 - def create(cls, area_builder, x, y, orientation):
72 # TODO: create a late initialization phase for this kind of stuff 73 if cls.__radius_offsets is None: 74 cls.__init_outline() 75 76 area_value = 0 77 coastline = area_builder.land_manager.coastline 78 personality = area_builder.owner.personality_manager.get('LumberjackEvaluator') 79 for dx, dy in cls.__radius_offsets: 80 coords = (x + dx, y + dy) 81 if coords in area_builder.plan and coords not in coastline: 82 purpose = area_builder.plan[coords][0] 83 if purpose == BUILDING_PURPOSE.NONE: 84 area_value += personality.new_tree 85 elif purpose == BUILDING_PURPOSE.TREE: 86 area_value += personality.shared_tree 87 area_value = min(area_value, personality.max_forest_value) # the lumberjack doesn't actually need all the trees 88 if area_value < personality.min_forest_value: 89 return None # the area is too bad for a lumberjack 90 91 personality = area_builder.owner.personality_manager.get('LumberjackEvaluator') 92 alignment = cls._get_alignment_from_outline(area_builder, cls._get_outline(x, y)) 93 value = area_value + alignment * personality.alignment_importance 94 builder = BasicBuilder.create(BUILDINGS.LUMBERJACK, (x, y), orientation) 95 return LumberjackEvaluator(area_builder, builder, value)
96 97 @property
98 - def purpose(self):
100
101 - def execute(self):
102 # TODO Add a check that figures out if all trees that should be planted are in range of the settlement. 103 # If not, return range missing result 104 (result, building) = super().execute() 105 if result != BUILD_RESULT.OK: 106 return (result, None) 107 108 production_builder = self.area_builder 109 coastline = production_builder.land_manager.coastline 110 island_ground_map = production_builder.island.ground_map 111 forest_coords_list = [] 112 for coords in building.position.get_radius_coordinates(Entities.buildings[BUILDINGS.LUMBERJACK].radius): 113 if coords in production_builder.plan and production_builder.plan[coords][0] == BUILDING_PURPOSE.NONE and coords not in coastline: 114 if island_ground_map[coords].object is not None and island_ground_map[coords].object.id == BUILDINGS.TREE: 115 forest_coords_list.append(coords) 116 elif island_ground_map[coords].settlement is not None and island_ground_map[coords].settlement.owner is self.area_builder.owner: 117 builder = BasicBuilder(BUILDINGS.TREE, coords, 0) 118 if not builder.have_resources(production_builder.land_manager): 119 break 120 if builder: 121 assert builder.execute(production_builder.land_manager) 122 forest_coords_list.append(coords) 123 124 production_builder.register_change_list(forest_coords_list, BUILDING_PURPOSE.TREE, None) 125 126 return (BUILD_RESULT.OK, building)
127 128 129 AbstractLumberjack.register_buildings() 130