Ejemplo n.º 1
0
		for i in xrange(tries):
			# choose x-difference, then y-difference so that the distance is in the range.
			x_diff = randint(1, in_range) # always go at least 1 field
			y_max_diff = int( math.sqrt(range_squared - x_diff*x_diff) )
			y_diff = randint(0, y_max_diff)
			# use randomness of x/y_diff below, randint calls are expensive
			# this results in a higher chance for x > y than y < x, so equalize
			if (x_diff + y_diff) % 2 == 0:
				x_diff, y_diff = y_diff, x_diff
			# direction
			if x_diff % 2 == 0:
				y_diff = -y_diff
			if y_diff % 2 == 0:
				x_diff = -x_diff
			# check this target
			possible_target = Point(self.position.x + x_diff, self.position.y + y_diff)
			path = self.check_move(possible_target)
			if path:
				return (possible_target, path)
		return (None, None)

	@property
	def classname(self):
		return self.session.db.get_unit_type_name(self.id)

	def __str__(self): # debug
		return '%s(id=%s;worldid=%s)' % (self.name, self.id, self.worldid if hasattr(self, 'worldid') else 'none')


decorators.bind_all(Unit)
Ejemplo n.º 2
0
class BuildableSingleOnDeposit(BuildableSingle):
	"""For mines; those buildings are only buildable upon other buildings (clay pit on clay deposit, e.g.)
	For now, mines can only be built on a single type of deposit.
	This is specified in game.sqlite in the table "mine", and saved in cls.buildable_on_deposit in
	the buildingclass.
	"""
	irregular_conditions = True
	@classmethod
	def _check_buildings(cls, session, position, island=None):
		"""Check if there are buildings blocking the build"""
		if island is None:
			island = session.world.get_island(position.center())
		deposit = None
		for tile in island.get_tiles_tuple( position.tuple_iter() ):
			if tile.object is None or \
			   tile.object.id != cls.buildable_on_deposit_type or \
			   (deposit is not None and tile.object != deposit): # only build on 1 deposit
				raise _NotBuildableError(BuildableErrorTypes.NEED_RES_SOURCE)
			deposit = tile.object
		return set([deposit.worldid])



decorators.bind_all(Buildable)
decorators.bind_all(BuildableSingle)
decorators.bind_all(BuildableRect)
decorators.bind_all(BuildableSingleFromShip)
decorators.bind_all(BuildableSingleOnCoast)
decorators.bind_all(BuildableSingleOnDeposit)
Ejemplo n.º 3
0
		"""Create the produced unit now."""
		productions = self._productions.values()
		for production in productions:
			assert isinstance(production, UnitProduction)
			self.on_production_finished(production.get_produced_units())
			for unit, amount in production.get_produced_units().iteritems():
				for i in xrange(0, amount):
					radius = 1
					found_tile = False
					# search for free water tile, and increase search radius if none is found
					while not found_tile:
						for coord in Circle(self.instance.position.center(), radius).tuple_iter():
							point = Point(coord[0], coord[1])
							if self.instance.island.get_tile(point) is None:
								tile = self.session.world.get_tile(point)
								if tile is not None and tile.is_water and coord not in self.session.world.ship_map:
									# execute bypassing the manager, it's simulated on every machine
									u = CreateUnit(self.instance.owner.worldid, unit, point.x, point.y)(issuer=self.instance.owner)
									# Fire a message indicating that the ship has been created
									name = u.get_component(NamedComponent).name
									self.session.ingame_gui.message_widget.add(string_id='NEW_UNIT', point=point, message_dict={'name' : name})
									found_tile = True
									break
						radius += 1


decorators.bind_all(Producer)
decorators.bind_all(MineProducer)
decorators.bind_all(QueueProducer)
decorators.bind_all(UnitProducer)
Ejemplo n.º 4
0
	def toggle_owner_highlight(self):
		renderer = self.session.view.renderer['InstanceRenderer']
		self.owner_highlight_active = not self.owner_highlight_active
		if self.owner_highlight_active: #show
			for player in self.players:
				red = player.color.r
				green = player.color.g
				blue = player.color.b
				for settlement in player.settlements:
					for tile in settlement.ground_map.itervalues():
						renderer.addColored(tile._instance, red, green, blue)
		else: # 'hide' functionality
			renderer.removeAllColored()

	def toggle_translucency(self):
		"""Make certain building types translucent"""
		worldutils.toggle_translucency(self)

	def toggle_health_for_all_health_instances(self):
		worldutils.toggle_health_for_all_health_instances(self)


def load_building(session, db, typeid, worldid):
	"""Loads a saved building. Don't load buildings yourself in the game code."""
	return Entities.buildings[typeid].load(session, db, worldid)


decorators.bind_all(World)
decorators.bind_all(load_building)
Ejemplo n.º 5
0
		return smallest_fisher

	def get_buildings_in_range(self, reslist=None):
		"""Returns all buildings in range .
		Overwrite in subclasses that need ranges around the pickup.
		@param res: optional, only search for buildings that provide res"""
		reach = RadiusRect(self.home_building.position, self.home_building.radius)
		return self.session.world.get_providers_in_range(reach, reslist=reslist)

class DisasterRecoveryCollector(StorageCollector):
	"""Collects disasters such as fire or pestilence."""
	def finish_working(self, collector_already_home=False):
		super(DisasterRecoveryCollector, self).finish_working(collector_already_home=collector_already_home)
		building = self.job.object
		if hasattr(building, "disaster"): # make sure that building hasn't recovered any other way
			building.disaster.recover(building)

	def get_job(self):
		if self.home_building is not None and \
		   not self.session.world.disaster_manager.is_affected( self.home_building.settlement ):
			return None # not one disaster active, bail out

		return super(DisasterRecoveryCollector, self).get_job()

decorators.bind_all(BuildingCollector)
decorators.bind_all(FieldCollector)
decorators.bind_all(FisherShipCollector)
decorators.bind_all(SettlerCollector)
decorators.bind_all(StorageCollector)
decorators.bind_all(DisasterRecoveryCollector)
Ejemplo n.º 6
0
		if shuffle_first:
			self.collector.session.random.shuffle(self)
		inventory = self.collector.get_home_inventory()
		self.sort(key=lambda job: min(inventory[res] for res in job.resources) , reverse=False)

	def _sort_jobs_fewest_available_and_distance(self):
		"""Sort jobs by fewest available, but secondaryly also consider distance"""
		# python sort is stable, so two sequenced sorts work.
		self._sort_jobs_distance()
		self._sort_jobs_fewest_available(shuffle_first=False)

	def _sort_jobs_for_storage_collector(self):
		"""Special sophisticated sorting routing for storage collectors.
		Same as fewest_available_and_distance_, but also considers whether target inv is full."""
		self._sort_jobs_fewest_available_and_distance()
		self._sort_target_inventory_full()

	def _sort_jobs_distance(self):
		"""Prefer targets that are nearer"""
		self.sort(key=lambda job: self.collector.position.distance(job.object.loading_area))

	def _sort_target_inventory_full(self):
		"""Prefer targets with full inventory"""
		self.sort(key=operator.attrgetter('target_inventory_full_num'), reverse=True)

	def __str__(self):
		return str([ str(i) for i in self ])


decorators.bind_all(Collector)
		path_length = 0 # length in ticks to travel the distance
		speed = self.get_unit_velocity()
		for i in xrange(1, len(path)):
			dx = abs(path[i - 1][0] - path[i][0])
			dy = abs(path[i - 1][1] - path[i][1])
			if dx and dy:
				path_length += speed[1]
			else:
				path_length += speed[0]
		return path_length

	def get_move_target(self):
		return self.path.get_move_target()

	def save(self, db):
		super(MovingObject, self).save(db)
		# NOTE: _move_action is currently not yet saved and neither is blocked_callback.
		self.path.save(db, self.worldid)

	def load(self, db, worldid):
		super(MovingObject, self).load(db, worldid)
		x, y = db("SELECT x, y FROM unit WHERE rowid = ?", worldid)[0]
		self.__init(x, y)
		path_loaded = self.path.load(db, worldid)
		if path_loaded:
			self.__is_moving = True
			self._setup_move()
			Scheduler().add_new_object(self._move_tick, self, run_in=0)

decorators.bind_all(MovingObject)
		"""Runs necessary steps to deselect the ship."""
		if self._selected:
			super(SelectableShipComponent, self).deselect()
			self.instance._update_buoy(remove_only=True)

class SelectableFisherComponent(SelectableBuildingComponent):
	"""Class used to highlight the radius of a fisher. Highlights only the fishing
	grounds."""

	@classmethod
	def _do_select(cls, renderer, position, world, settlement, radius,
	               range_applies_only_on_island):
		# No super, we don't want to color the ground
		cls._init_fake_tile()
		layer = world.session.view.layers[LAYERS.FIELDS]
		for fish_deposit in world.get_providers_in_range(RadiusRect(position, radius), res=RES.FISH):
			#renderer.addColored(fish_deposit._instance, *cls.selection_color)
			#cls._selected_tiles.l.append(fish_deposit)
			for pos in fish_deposit.position:
				cls._add_fake_tile(pos.x, pos.y, layer, renderer)

	"""@classmethod
	def get_instance(cls, arguments):
		arguments = copy.copy(arguments)
		return SelectableFisherComponent( **arguments )"""

decorators.bind_all(SelectableFisherComponent)
decorators.bind_all(SelectableBuildingComponent)
decorators.bind_all(SelectableShipComponent)
decorators.bind_all(SelectableUnitComponent)
Ejemplo n.º 9
0
        super(BuildRelatedBuildingToolLogic, self).__init__(building_tool)
        # instance must be weakref
        self.instance = instance

    def _reshow_tab(self):
        from horizons.gui.tabs import BuildRelatedTab

        self.instance().get_component(SelectableComponent).show_menu(jump_to_tabclass=BuildRelatedTab)

    def on_escape(self, session):
        super(BuildRelatedBuildingToolLogic, self).on_escape(session)
        self._reshow_tab()

    def continue_build(self):
        self._reshow_tab()

    def add_change_listener(self, instance, building_tool):
        pass  # using messages now

    def remove_change_listener(self, instance, building_tool):
        pass

    def remove(self, session):
        super(BuildRelatedBuildingToolLogic, self).remove(session)


decorators.bind_all(BuildingTool)
decorators.bind_all(SettlementBuildingToolLogic)
decorators.bind_all(ShipBuildingToolLogic)
decorators.bind_all(BuildRelatedBuildingToolLogic)
Ejemplo n.º 10
0
		if not self.kill_animal:
			self.log.debug("%s releasing animal %s",self, self.job.object)
			Scheduler().add_new_object(self.job.object.search_job, self.job.object, \
			                           GAME_SPEED.TICKS_PER_SECOND)


class FarmAnimalCollector(AnimalCollector):
	def get_animals_in_range(self, reslist=None):
		"""Returns animals from buildings in range"""
		reach = RadiusRect(self.home_building.position, self.home_building.radius)
		# don't consider res when searching for buildings, since only their animals are
		# the acctual providers
		buildings = self.home_building.island.get_providers_in_range(reach)
		animal_lists = (building.animals for building in buildings if hasattr(building, 'animals'))
		# use overloaded + for lists here in sum
		return sum(animal_lists, [])


class HunterCollector(AnimalCollector):
	kill_animal = True

	def get_animals_in_range(self, res=None):
		dist = self.home_building.position.distance_to_point
		radius = self.home_building.radius
		return [ animal for animal in self.home_building.island.wild_animals if \
		         dist(animal.position) <= radius ]


decorators.bind_all(AnimalCollector)
decorators.bind_all(FarmAnimalCollector)
decorators.bind_all(HunterCollector)
Ejemplo n.º 11
0
				# set first action
				action = action_sets[action_set_id].keys()[0]

		instance.act(action+"_"+str(action_set_id), facing_loc, True)
		return (instance, action_set_id)

	@classmethod
	def have_resources(cls, inventory_holders, owner):
		return Build.check_resources({}, cls.costs, owner, inventory_holders)[0]

	def init(self):
		"""init the building, called after the constructor is run and the building is positioned (the settlement variable is assigned etc)
		"""
		pass

	def start(self):
		"""This function is called when the building is built, to start production for example."""
		pass

	#@decorators.relese_mode(ret="Building")
	def __str__(self): # debug
		return '%s(id=%s;worldid=%s)' % (self.name, self.id, self.worldid if hasattr(self, 'worldid') else 'none')


class DefaultBuilding(BasicBuilding, BuildableSingle):
	"""Building with default properties, that does nothing."""
	pass


decorators.bind_all(BasicBuilding)
Ejemplo n.º 12
0
		return self.session.world.ground_unit_map

	def _check_for_obstacles(self, point):
		# retrieve island, island of soldier may change at any time
		island = self.session.world.get_island(self.unit.position)
		path_blocked = not island.path_nodes.is_walkable(self.path[self.cur])
		if path_blocked:
			# update list in island, so that new path calculations consider this obstacle
			island.path_nodes.reset_tile_walkability(point)
			self.log.debug("tile %s %s blocked for %s %s on island", point[0], point[1], \
										 self.unit, self.unit.worldid);
			return path_blocked
		else:
			# also check in super class
			return super(SoldierPather, self)._check_for_obstacles(point)


class StaticPather(object):
	"""Misc pathing routines not depending on units.
	Does not use AbstractPather Interface"""
	@classmethod
	def get_path_on_roads(cls, island, source, destination):
		"""Returns a path that runs only on roads.
		@param island: island to search path on
		@param source, destination: Point or anything supported by FindPath
		@return: list of tuples or None in case no path is found"""
		return FindPath()(source, destination, island.path_nodes.road_nodes)


decorators.bind_all(AbstractPather)