def get_ground_units(self, position=None, radius=None):
		"""@see get_ships"""
		if position is not None and radius is not None:
			circle = Circle(position, radius)
			return [unit for unit in self.ground_units if circle.contains(unit.position)]
		else:
			return self.ground_units
def test_circle():
	c1 = Circle(Point(0, 0), 1)
	c2 = Circle(Point(0, 0), 2)
	c3 = Circle(Point(0, 0), 0)
	assert not (c1 == c2)
	assert c1 != c2
	assert c1.get_coordinates() == [(-1, 0), (0, -1), (0, 0), (0, 1), (1, 0)]
	assert c3.get_coordinates() == [(0, 0)]
Exemple #3
0
	def testCircle(self):
		c1 = Circle(Point(0,0), 1)
		c2 = Circle(Point(0,0), 2)
		c3 = Circle(Point(0,0), 0)
		self.assertFalse(c1 == c2)
		self.assertTrue(c1 != c2)
		self.assertNotEqual(c1, c2)
		self.assertEqual(c1.get_coordinates(), [(-1, 0), (0, -1), (0, 0), (0, 1), (1, 0)])
		self.assertEqual(c3.get_coordinates(), [(0,0)])
	def _add_coloring(self, pos):
		brush = Circle(Point(*pos), self.session.world_editor.brush_size - 1)
		for p in brush.tuple_iter():
			if p not in self.session.world.full_map:
				continue

			tile = self.session.world.full_map[p]
			if hasattr(tile, '_instance'):
				self.renderer.addColored(tile._instance, *self.HIGHLIGHT_COLOR)
Exemple #5
0
	def get_ships(self, position=None, radius=None):
		"""Returns all ships on the map, optionally only those in range
		around the specified position.
		@param position: Point or Rect instance.
		@param radius: int radius to use.
		@return: List of ships.
		"""
		if position is not None and radius is not None:
			circle = Circle(position, radius)
			return [ship for ship in self.ships if circle.contains(ship.position)]
		else:
			return self.ships
 def get_buildings(self, position=None, radius=None):
     """@see get_ships"""
     buildings = []
     if position is not None and radius is not None:
         circle = Circle(position, radius)
         for island in self.islands:
             for building in island.buildings:
                 if circle.contains(building.position.center):
                     buildings.append(building)
         return buildings
     else:
         return [b for b in island.buildings for island in self.islands]
    def act_auto_attack(self):
        """
		Check if target still exists or if unit exited the hold ground area
		"""
        if not Circle(self.return_position, self.move_range).contains(self.instance.position.center) or \
         not self.instance.is_attacking():
            try:
                self.instance.move(self.return_position)
            except MoveNotPossible:
                self.instance.move(
                    Circle(self.return_position, self.stance_radius))
            self.state = 'move_back'
	def get_ships(self, position=None, radius=None):
		"""Returns all ships on the map, optionally only those in range
		around the specified position.
		@param position: Point or Rect instance.
		@param radius: int radius to use.
		@return: List of ships.
		"""
		if position is not None and radius is not None:
			circle = Circle(position, radius)
			return [ship for ship in self.ships if circle.contains(ship.position)]
		else:
			return self.ships
	def get_buildings(self, position=None, radius=None):
		"""@see get_ships"""
		buildings = []
		if position is not None and radius is not None:
			circle = Circle(position, radius)
			for island in self.islands:
				for building in island.buildings:
					if circle.contains(building.position.center):
						buildings.append(building)
			return buildings
		else:
			return [b for b in island.buildings for island in self.islands]
Exemple #10
0
	def move(self, destination, callback=None, ratio=1.0):
		"""
		Move fleet to a destination.
		@param ratio: what percentage of ships has to reach destination in order for the move to be considered done:
			0.0 - None (not really useful, executes the callback right away)
			0.0001 - effectively ANY ship
			1.0 - ALL of the ships
			0.5 - at least half of the ships
			etc.
		"""
		assert self.size() > 0, "ordered to move a fleet consisting of 0 ships"

		# it's ok to specify single point for a destination only when there's only one ship in a fleet
		if isinstance(destination, Point) and self.size() > 1:
			destination = Circle(destination, self._get_circle_size())

		self.destination = destination
		self.state = self.fleetStates.moving
		self.ratio = ratio

		self.callback = callback

		# This is a good place to do something fancier later like preserving ship formation instead sailing to the same point
		for ship in self._ships.keys():
			self._move_ship(ship, destination, Callback(self._ship_reached, ship))
Exemple #11
0
	def _load(self, worldid, owner, db, destroy_callback):
		super(Fleet, self).load(db, worldid)
		self.owner = owner
		state_id, dest_x, dest_y, radius, ratio = db("SELECT state_id, dest_x, dest_y, radius, ratio FROM fleet WHERE fleet_id = ?", worldid)[0]

		if radius:  # Circle
			self.destination = Circle(Point(dest_x, dest_y), radius)
		elif dest_x and dest_y:  # Point
			self.destination = Point(dest_x, dest_y)
		else:  # No destination
			pass

		if ratio:
			self.ratio = ratio

		ships_states = [(WorldObject.get_object_by_id(ship_id), self.shipStates[ship_state_id])
		                for ship_id, ship_state_id
		                in db("SELECT ship_id, state_id FROM fleet_ship WHERE fleet_id = ?", worldid)]
		ships = [item[0] for item in ships_states]

		self.__init(ships, destroy_callback)
		self.state = self.fleetStates[state_id]

		for ship, state in ships_states:
			self._ships[ship] = state

		if self.state == self.fleetStates.moving:
			for ship in self.get_ships():
				if self._ships[ship] == self.shipStates.moving:
					ship.add_move_callback(Callback(self._ship_reached, ship))

		if destroy_callback:
			self.destroy_callback = destroy_callback
        def high(i=0):
            i += 1
            render_name = self._get_render_name("highlight") + str(tup)
            self.minimap_image.set_drawing_enabled()
            self.minimap_image.rendertarget.removeAll(render_name)
            if i > STEPS:
                if finish_callback:
                    finish_callback()
                return
            part = i  # grow bigger
            if i > STEPS // 2:  # after the first half
                part = STEPS - i  # become smaller

            radius = MIN_RAD + int(
                (float(part) / (STEPS // 2)) * (MAX_RAD - MIN_RAD))

            draw_point = self.minimap_image.rendertarget.addPoint
            for x, y in Circle(Point(*tup),
                               radius=radius).get_border_coordinates():
                draw_point(render_name, fife.Point(x, y), *color)

            ExtScheduler().add_new_object(lambda: high(i),
                                          self,
                                          INTERVAL,
                                          loops=1)
Exemple #13
0
    def send_ship_random_warehouse(self, ship, warehouse=None):
        """Sends a ship to a random warehouse on the map
		@param ship: Ship instance that is to be used
		@param warehouse: warehouse instance to move to. Random one is selected on None."""
        self.log.debug("Trader %s ship %s moving to warehouse (random=%s)",
                       self.worldid, ship.worldid, (warehouse is None))
        #TODO maybe this kind of list should be saved somewhere, as this is pretty performance intense
        warehouses = self.session.world.get_warehouses()
        # Remove all warehouses that are not safe to visit
        warehouses = list(filter(self.is_warehouse_safe, warehouses))
        if not warehouses:  # there aren't any warehouses, move randomly
            self.send_ship_random(ship)
        else:  # select a warehouse
            if warehouse is None:
                self.warehouse[ship.worldid] = self.session.random.choice(
                    warehouses)
            else:
                self.warehouse[ship.worldid] = warehouse
            try:  # try to find a possible position near the warehouse
                ship.move(
                    Circle(self.warehouse[ship.worldid].position.center,
                           ship.radius), Callback(self.reached_warehouse,
                                                  ship))
                self.ships[ship] = self.shipStates.moving_to_warehouse
            except MoveNotPossible:
                self.send_ship_random(ship)
    def _chase_closest_ship(self, pirate_ship):
        owner = pirate_ship.owner
        ship = owner.get_nearest_player_ship(pirate_ship)
        if ship:
            owner.ships[pirate_ship] = owner.shipStates.chasing_ship

            # if ship was caught
            if ship.position.distance(
                    pirate_ship.position) <= self.pirate_caught_ship_radius:
                self.log.debug('Pirate %s: Ship %s(%s) caught %s' %
                               (owner.worldid,
                                pirate_ship.get_component(NamedComponent).name,
                                owner.ships[pirate_ship], ship))
                self._sail_home(pirate_ship)
            else:
                try:
                    pirate_ship.move(
                        Circle(ship.position,
                               self.pirate_caught_ship_radius - 1),
                        Callback(self._sail_home, pirate_ship))
                    owner.ships[pirate_ship] = owner.shipStates.chasing_ship
                    self.log.debug(
                        'Pirate %s: Ship %s(%s) chasing %s' %
                        (owner.worldid,
                         pirate_ship.get_component(NamedComponent).name,
                         owner.ships[pirate_ship],
                         ship.get_component(NamedComponent).name))
                except MoveNotPossible:
                    self.log.debug(
                        'Pirate %s: Ship %s(%s) unable to chase the closest ship %s'
                        % (owner.worldid,
                           pirate_ship.get_component(NamedComponent).name,
                           owner.ships[pirate_ship],
                           ship.get_component(NamedComponent).name))
                    owner.ships[pirate_ship] = owner.shipStates.idle
Exemple #15
0
	def sail_to_target(self):
		self.log.debug("Player %s, Mission %s, 1/2 set off to ship %s at %s", self.owner.name, self.__class__.__name__,
			self.target_ship.get_component(NamedComponent).name, self.target_ship.position)
		try:
			self.fleet.move(Circle(self.target_ship.position, self.target_range), self._state_fleet_callbacks[self.missionStates.sailing_to_target])
			self.state = self.missionStates.sailing_to_target
		except MoveNotPossible:
			self.report_failure("Move was not possible when moving to target")
def test_circle():
    c1 = Circle(Point(0, 0), 1)
    c2 = Circle(Point(0, 0), 2)
    c3 = Circle(Point(0, 0), 0)
    assert not (c1 == c2)
    assert c1 != c2
    assert c1.get_coordinates() == [(-1, 0), (0, -1), (0, 0), (0, 1), (1, 0)]
    assert c3.get_coordinates() == [(0, 0)]
 def _move_to_warehouse_area(self, warehouse_position, success_callback,
                             blocked_callback, failure_msg):
     (x, y) = warehouse_position.get_coordinates()[4]
     area = Circle(Point(x, y), BUILDINGS.BUILD.MAX_BUILDING_SHIP_DISTANCE)
     try:
         self.ship.move(area,
                        success_callback,
                        blocked_callback=blocked_callback)
     except MoveNotPossible:
         self.report_failure(failure_msg)
	def _load(self, worldid, owner, db, success_callback, failure_callback):
		super(SurpriseAttack, self)._load(db, worldid, success_callback, failure_callback, owner)
		db_result = db("SELECT enemy_player_id, target_point_x, target_point_y, target_point_radius, return_point_x, return_point_y "
						"FROM ai_mission_surprise_attack WHERE rowid = ?", worldid)[0]
		enemy_player_id, target_point_x, target_point_y, target_point_radius, return_point_x, return_point_y = db_result

		target_point = Circle(Point(target_point_x, target_point_y), target_point_radius)
		return_point = Point(return_point_x, return_point_y)
		enemy_player = WorldObject.get_object_by_id(enemy_player_id)
		self.__init(target_point, return_point, enemy_player)
 def _move_to_warehouse_area(self, position, success_callback,
                             blocked_callback, failure_msg):
     area = Circle(position.center,
                   BUILDINGS.BUILD.MAX_BUILDING_SHIP_DISTANCE)
     try:
         self.ship.move(area,
                        success_callback,
                        blocked_callback=blocked_callback)
     except MoveNotPossible:
         self.report_failure(failure_msg)
Exemple #20
0
	def _sail_home(self, pirate_ship):
		owner = pirate_ship.owner
		try:
			pirate_ship.move(Circle(owner.home_point, self.pirate_home_radius), Callback(self._arrived, pirate_ship))
			owner.ships[pirate_ship] = owner.shipStates.going_home
			self.log.debug('Pirate %s: Ship %s(%s): sailing home at %s' % (owner.worldid, pirate_ship.get_component(NamedComponent).name,
				owner.ships[pirate_ship], owner.home_point))
		except MoveNotPossible:
			owner.ships[pirate_ship] = owner.shipStates.idle
			self.log.debug('Pirate %s: Ship %s: unable to move home at %s' % (owner.worldid, pirate_ship.get_component(NamedComponent).name, owner.home_point))
	def testCircle(self):
		c1 = Circle(Point(0,0), 1)
		c2 = Circle(Point(0,0), 2)
		c3 = Circle(Point(0,0), 0)
		self.assertFalse(c1 == c2)
		self.assertTrue(c1 != c2)
		self.assertNotEqual(c1, c2)
		self.assertEqual(c1.get_coordinates(), [(-1, 0), (0, -1), (0, 0), (0, 1), (1, 0)])
		self.assertEqual(c3.get_coordinates(), [(0,0)])
Exemple #22
0
    def get_surrounding_tiles(self, where, radius=1, include_corners=True):
        """Returns tiles around point with specified radius.
		@param point: instance of Point, or object with get_surrounding()"""
        if hasattr(where, "get_surrounding"):
            coords = where.get_surrounding(include_corners=include_corners)
        else:  # assume Point
            coords = Circle(where, radius).tuple_iter()
        for position in coords:
            tile = self.get_tile_tuple(position)
            if tile is not None:
                yield tile
    def find_warehouse_location(cls, ship, land_manager):
        """Return the coordinates of a location for the warehouse on the given island."""
        warehouse_class = Entities.buildings[BUILDINGS.WAREHOUSE]
        pos_offsets = []
        for dx in range(warehouse_class.width):
            for dy in range(warehouse_class.height):
                pos_offsets.append((dx, dy))

        island = land_manager.island
        personality = land_manager.owner.personality_manager.get(
            'FoundSettlement')

        available_spots_list = list(
            sorted(island.terrain_cache.cache[warehouse_class.terrain_type][
                warehouse_class.size].intersection(
                    island.available_land_cache.cache[warehouse_class.size])))
        available_spots_list = [
            x for x in available_spots_list if warehouse_class.check_build(
                land_manager.session, Point(*x), check_settlement=False)
        ]
        if not available_spots_list:
            return None

        options = []
        limited_spots = island.session.random.sample(
            available_spots_list,
            min(len(available_spots_list), personality.max_options))
        for (x, y) in limited_spots:
            cost = 0
            for (x2, y2) in land_manager.village:
                dx = x2 - x
                dy = y2 - y
                distance = (dx * dx + dy * dy)**0.5
                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 += settlement_manager.settlement.warehouse.position.distance(
                    (x, y)) * personality.linear_warehouse_penalty
            options.append((cost, x, y))

        for _, x, y in sorted(options):
            if ship.check_move(
                    Circle(
                        Point(x + warehouse_class.width // 2,
                              y + warehouse_class.height // 2),
                        BUILDINGS.BUILD.MAX_BUILDING_SHIP_DISTANCE)):
                return (x, y)
        return None
Exemple #24
0
	def _check_island(cls, session, position, island=None):
		# this might raise, just let it through
		super(BuildableSingleOnOcean, cls)._check_island(session, position, island)
		if island is None:
			island = session.world.get_island(position.center)
			if island is None:
				raise _NotBuildableError(BuildableErrorTypes.NO_ISLAND)
		posis = position.get_coordinates()
		for tile in posis:
			for rad in Circle(Point(*tile), 3):
				if rad in session.world.water_body and session.world.water_body[rad] == session.world.sea_number:
					# Found legit see tile
					return island
		raise _NotBuildableError(BuildableErrorTypes.NO_OCEAN_NEARBY)
Exemple #25
0
	def _check_island(cls, session, position, island=None):
		# this might raise, just let it through
		super(BuildableSingleOnOcean, cls)._check_island(session, position, island)
		if island is None:
			island = session.world.get_island(position.center)
			if island is None:
				raise _NotBuildableError(BuildableErrorTypes.NO_ISLAND)
		posis = position.get_coordinates()
		for tile in posis:
			for rad in Circle(Point(*tile), 3):
				if island.get_tile(rad) is None:
					# Tile not on island -> deep water
					return island
		raise _NotBuildableError(BuildableErrorTypes.NO_OCEAN_NEARBY)
    def get_points_in_radius(self, position, radius, shuffle=False):
        """Returns all points in the radius around the point.
		This is a generator; make sure you use it appropriately.
		@param position: Point instance
		@return List of points in radius.
		"""
        assert isinstance(position, Point)
        points = Circle(position, radius)
        if shuffle:
            points = list(points)
            self.session.random.shuffle(points)
        for point in points:
            if self.map_dimensions.contains_without_border(point):
                # don't yield if point is not in map, those points don't exist
                yield point
	def move_to_next_route_warehouse(self, advance_waypoint=True):
		next_destination = self.get_next_destination(advance_waypoint)
		if next_destination is None:
			return

		warehouse = next_destination['warehouse']
		if self.ship.position.distance(warehouse.position.center) <= self.ship.radius:
			self.on_route_warehouse_reached()
			return

		try:
			self.ship.move(Circle(warehouse.position.center, self.ship.radius), self.on_route_warehouse_reached,
			               blocked_callback = self.on_ship_blocked)
		except MoveNotPossible:
			# retry in 5 seconds
			Scheduler().add_new_object(self.on_ship_blocked, self, GAME_SPEED.TICKS_PER_SECOND * 5)
Exemple #28
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
Exemple #29
0
	def __place_unit(self, unit):
		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 not None:
					continue
				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
def spawn_ships(session, owner_id, ship_id, number, *position):
    """
	Creates a number of ships controlled by a certain player around a position on the map.
	@param owner_id: the owner worldid
	@param ship_id: the ship id
	@param number: number of ships to be spawned
	@param position: position around the ships to be spawned
	"""
    center = Point(*position)
    player = WorldObject.get_object_by_id(owner_id)
    # calculate a radius that should fit all the ships
    # if it doesn't fit them all increase the radius
    radius = int(math.sqrt(number))
    while number != 0:
        for point in Circle(center, radius):
            if (point.x, point.y) in session.world.ship_map \
             or session.world.get_island(point) is not None:
                continue
            CreateUnit(owner_id, ship_id, point.x, point.y)(issuer=player)
            number -= 1
            if number == 0:
                break
        radius += 1
    def go(self, x, y):
        from horizons.world.units.movingobject import MoveNotPossible
        """Moves the unit.
		This is called when a unit is selected and the right mouse button is pressed outside the unit"""
        x = int(round(x))
        y = int(round(y))
        move_target = Point(x, y)

        try:
            self.instance.move(move_target)
        except MoveNotPossible:
            # find a near tile to move to
            surrounding = Circle(move_target, radius=1)
            move_target = None
            # try with smaller circles, increase radius if smaller circle isn't reachable
            while surrounding.radius < 5:
                try:
                    self.instance.move(surrounding)
                except MoveNotPossible:
                    surrounding.radius += 1
                    continue
                # update actual target coord
                move_target = self.instance.get_move_target()
                break
        if self.instance.owner.is_local_player:
            self.instance.session.ingame_gui.minimap.show_unit_path(
                self.instance)
        if move_target is None:  # can't move
            if not self.instance.owner.is_local_player:
                return
            if self.session.world.get_tile(Point(
                    x, y)) is None:  # not even in world
                string_id = "MOVE_OUTSIDE_OF_WORLD"
            else:  # in world, but still unreachable
                string_id = "MOVE_INVALID_LOCATION"
            self.session.ingame_gui.message_widget.add(point=Point(x, y),
                                                       string_id=string_id)
def create_random_island(map_db, island_id, id_string):
    """Creates a random island as sqlite db.
	It is rather primitive; it places shapes on the dict.
	The coordinates of tiles will be 0 <= x < width and 0 <= y < height
	@param id_string: random island id string
	"""
    match_obj = re.match(_random_island_id_regexp, id_string)
    assert match_obj
    creation_method, width, height, seed, island_x, island_y = [
        long(i) for i in match_obj.groups()
    ]
    assert creation_method == 2, 'The only supported island creation method is 2.'

    rand = random.Random(seed)
    map_set = set()

    # place this number of shapes
    for i in xrange(15 + width * height // 45):
        # place shape determined by shape_id on (x, y)
        add = True
        shape_id = rand.randint(2, 8)
        rect_chance = 29
        if rand.randint(0, 4) == 0:
            rect_chance = 13
            add = False

        shape = None
        if rand.randint(1, rect_chance) == 1:
            # use a rect
            if add:
                x = rand.randint(8, width - 7)
                y = rand.randint(8, height - 7)
            else:
                x = rand.randint(0, width)
                y = rand.randint(0, height)
            shape = Rect.init_from_topleft_and_size(x - 5, y - 5,
                                                    rand.randint(2, 8),
                                                    rand.randint(2, 8))
        else:
            # use a circle such that the radius is determined by shape_id
            radius = shape_id
            if not add and rand.randint(0, 6) < 5:
                x = rand.randint(-radius * 3 // 2, width + radius * 3 // 2)
                y = rand.randint(-radius * 3 // 2, height + radius * 3 // 2)
                shape = Circle(Point(x, y), shape_id)
            elif width - radius - 4 >= radius + 3 and height - radius - 4 >= radius + 3:
                x = rand.randint(radius + 3, width - radius - 4)
                y = rand.randint(radius + 3, height - radius - 4)
                shape = Circle(Point(x, y), shape_id)

        if shape:
            for shape_coord in shape.tuple_iter():
                if add:
                    map_set.add(shape_coord)
                elif shape_coord in map_set:
                    map_set.discard(shape_coord)

    # write values to db
    map_db("BEGIN TRANSACTION")

    # add grass tiles
    for x, y in map_set:
        map_db("INSERT INTO ground VALUES(?, ?, ?, ?, ?, ?)", island_id,
               island_x + x, island_y + y, *GROUND.DEFAULT_LAND)

    def fill_tiny_spaces(tile):
        """Fills 1 tile gulfs and straits with the specified tile
		@param tile: ground tile to fill with
		"""

        all_neighbours = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1),
                          (1, 0), (1, 1)]
        neighbours = [(-1, 0), (0, -1), (0, 1), (1, 0)]
        corners = [(-1, -1), (-1, 1)]
        knight_moves = [(-2, -1), (-2, 1), (-1, -2), (-1, 2), (1, -2), (1, 2),
                        (2, -1), (2, 1)]
        bad_configs = set([
            0, 1 << 0, 1 << 1, 1 << 2, 1 << 3, (1 << 0) | (1 << 3),
            (1 << 1) | (1 << 2)
        ])

        edge_set = copy.copy(map_set)
        reduce_edge_set = True

        while True:
            to_fill = set()
            to_ignore = set()
            for x, y in edge_set:
                # ignore the tiles with no empty neighbours
                if reduce_edge_set:
                    is_edge = False
                    for x_offset, y_offset in all_neighbours:
                        if (x + x_offset, y + y_offset) not in map_set:
                            is_edge = True
                            break
                    if not is_edge:
                        to_ignore.add((x, y))
                        continue

                for x_offset, y_offset in neighbours:
                    x2 = x + x_offset
                    y2 = y + y_offset
                    if (x2, y2) in map_set:
                        continue
                    # (x2, y2) is now a point just off the island

                    neighbours_dirs = 0
                    for i in xrange(len(neighbours)):
                        x3 = x2 + neighbours[i][0]
                        y3 = y2 + neighbours[i][1]
                        if (x3, y3) not in map_set:
                            neighbours_dirs |= (1 << i)
                    if neighbours_dirs in bad_configs:
                        # part of a straight 1 tile gulf
                        to_fill.add((x2, y2))
                    else:
                        for x_offset, y_offset in corners:
                            x3 = x2 + x_offset
                            y3 = y2 + y_offset
                            x4 = x2 - x_offset
                            y4 = y2 - y_offset
                            if (x3, y3) in map_set and (x4, y4) in map_set:
                                # part of a diagonal 1 tile gulf
                                to_fill.add((x2, y2))
                                break

                # block 1 tile straits
                for x_offset, y_offset in knight_moves:
                    x2 = x + x_offset
                    y2 = y + y_offset
                    if (x2, y2) not in map_set:
                        continue
                    if abs(x_offset) == 1:
                        y2 = y + y_offset // 2
                        if (x2, y2) in map_set or (x, y2) in map_set:
                            continue
                    else:
                        x2 = x + x_offset // 2
                        if (x2, y2) in map_set or (x2, y) in map_set:
                            continue
                    to_fill.add((x2, y2))

                # block diagonal 1 tile straits
                for x_offset, y_offset in corners:
                    x2 = x + x_offset
                    y2 = y + y_offset
                    x3 = x + 2 * x_offset
                    y3 = y + 2 * y_offset
                    if (x2, y2) not in map_set and (x3, y3) in map_set:
                        to_fill.add((x2, y2))
                    elif (x2, y2) in map_set and (x2, y) not in map_set and (
                            x, y2) not in map_set:
                        to_fill.add((x2, y))

            if to_fill:
                for x, y in to_fill:
                    map_set.add((x, y))
                    map_db("INSERT INTO ground VALUES(?, ?, ?, ?, ?, ?)",
                           island_id, island_x + x, island_y + y, *tile)

                old_size = len(edge_set)
                edge_set = edge_set.difference(to_ignore).union(to_fill)
                reduce_edge_set = old_size - len(edge_set) > 50
            else:
                break

    # possible movement directions
    all_moves = {
        'sw': (-1, -1),
        'w': (-1, 0),
        'nw': (-1, 1),
        's': (0, -1),
        'n': (0, 1),
        'se': (1, -1),
        'e': (1, 0),
        'ne': (1, 1)
    }

    def get_island_outline():
        """
		@return: the points just off the island as a dict
		"""
        result = set()
        for x, y in map_set:
            for offset_x, offset_y in all_moves.itervalues():
                coords = (x + offset_x, y + offset_y)
                if coords not in map_set:
                    result.add(coords)
        return result

    # add grass to sand tiles
    fill_tiny_spaces(GROUND.DEFAULT_LAND)
    outline = get_island_outline()
    for x, y in outline:
        filled = []
        for dir in sorted(all_moves):
            coords = (x + all_moves[dir][1], y + all_moves[dir][0])
            if coords in map_set:
                filled.append(dir)

        tile = None
        # straight coast or 1 tile U-shaped gulfs
        if filled == ['s', 'se', 'sw'] or filled == ['s']:
            tile = GROUND.SAND_NORTH
        elif filled == ['e', 'ne', 'se'] or filled == ['e']:
            tile = GROUND.SAND_WEST
        elif filled == ['n', 'ne', 'nw'] or filled == ['n']:
            tile = GROUND.SAND_SOUTH
        elif filled == ['nw', 'sw', 'w'] or filled == ['w']:
            tile = GROUND.SAND_EAST
        # slight turn (looks best with straight coast)
        elif filled == ['e', 'se'] or filled == ['e', 'ne']:
            tile = GROUND.SAND_WEST
        elif filled == ['n', 'ne'] or filled == ['n', 'nw']:
            tile = GROUND.SAND_SOUTH
        elif filled == ['nw', 'w'] or filled == ['sw', 'w']:
            tile = GROUND.SAND_EAST
        elif filled == ['s', 'sw'] or filled == ['s', 'se']:
            tile = GROUND.SAND_NORTH
        # sandy corner
        elif filled == ['se']:
            tile = GROUND.SAND_NORTHWEST1
        elif filled == ['ne']:
            tile = GROUND.SAND_SOUTHWEST1
        elif filled == ['nw']:
            tile = GROUND.SAND_SOUTHEAST1
        elif filled == ['sw']:
            tile = GROUND.SAND_NORTHEAST1
        # grassy corner
        elif 3 <= len(filled) <= 5:
            coast_set = set(filled)
            if 'e' in coast_set and 'se' in coast_set and 's' in coast_set:
                tile = GROUND.SAND_NORTHEAST3
            elif 's' in coast_set and 'sw' in coast_set and 'w' in coast_set:
                tile = GROUND.SAND_NORTHWEST3
            elif 'w' in coast_set and 'nw' in coast_set and 'n' in coast_set:
                tile = GROUND.SAND_SOUTHWEST3
            elif 'n' in coast_set and 'ne' in coast_set and 'e' in coast_set:
                tile = GROUND.SAND_SOUTHEAST3

        assert tile
        map_db("INSERT INTO ground VALUES(?, ?, ?, ?, ?, ?)", island_id,
               island_x + x, island_y + y, *tile)
    map_set = map_set.union(outline)

    # add sand to shallow water tiles
    fill_tiny_spaces(GROUND.SAND)
    outline = get_island_outline()
    for x, y in outline:
        filled = []
        for dir in sorted(all_moves):
            coords = (x + all_moves[dir][1], y + all_moves[dir][0])
            if coords in map_set:
                filled.append(dir)

        tile = None
        # straight coast or 1 tile U-shaped gulfs
        if filled == ['s', 'se', 'sw'] or filled == ['s']:
            tile = GROUND.COAST_NORTH
        elif filled == ['e', 'ne', 'se'] or filled == ['e']:
            tile = GROUND.COAST_WEST
        elif filled == ['n', 'ne', 'nw'] or filled == ['n']:
            tile = GROUND.COAST_SOUTH
        elif filled == ['nw', 'sw', 'w'] or filled == ['w']:
            tile = GROUND.COAST_EAST
        # slight turn (looks best with straight coast)
        elif filled == ['e', 'se'] or filled == ['e', 'ne']:
            tile = GROUND.COAST_WEST
        elif filled == ['n', 'ne'] or filled == ['n', 'nw']:
            tile = GROUND.COAST_SOUTH
        elif filled == ['nw', 'w'] or filled == ['sw', 'w']:
            tile = GROUND.COAST_EAST
        elif filled == ['s', 'sw'] or filled == ['s', 'se']:
            tile = GROUND.COAST_NORTH
        # mostly wet corner
        elif filled == ['se']:
            tile = GROUND.COAST_NORTHWEST1
        elif filled == ['ne']:
            tile = GROUND.COAST_SOUTHWEST1
        elif filled == ['nw']:
            tile = GROUND.COAST_SOUTHEAST1
        elif filled == ['sw']:
            tile = GROUND.COAST_NORTHEAST1
        # mostly dry corner
        elif 3 <= len(filled) <= 5:
            coast_set = set(filled)
            if 'e' in coast_set and 'se' in coast_set and 's' in coast_set:
                tile = GROUND.COAST_NORTHEAST3
            elif 's' in coast_set and 'sw' in coast_set and 'w' in coast_set:
                tile = GROUND.COAST_NORTHWEST3
            elif 'w' in coast_set and 'nw' in coast_set and 'n' in coast_set:
                tile = GROUND.COAST_SOUTHWEST3
            elif 'n' in coast_set and 'ne' in coast_set and 'e' in coast_set:
                tile = GROUND.COAST_SOUTHEAST3

        assert tile
        map_db("INSERT INTO ground VALUES(?, ?, ?, ?, ?, ?)", island_id,
               island_x + x, island_y + y, *tile)
    map_set = map_set.union(outline)

    # add shallow water to deep water tiles
    fill_tiny_spaces(GROUND.SHALLOW_WATER)
    outline = get_island_outline()
    for x, y in outline:
        filled = []
        for dir in sorted(all_moves):
            coords = (x + all_moves[dir][1], y + all_moves[dir][0])
            if coords in map_set:
                filled.append(dir)

        tile = None
        # straight coast or 1 tile U-shaped gulfs
        if filled == ['s', 'se', 'sw'] or filled == ['s']:
            tile = GROUND.DEEP_WATER_NORTH
        elif filled == ['e', 'ne', 'se'] or filled == ['e']:
            tile = GROUND.DEEP_WATER_WEST
        elif filled == ['n', 'ne', 'nw'] or filled == ['n']:
            tile = GROUND.DEEP_WATER_SOUTH
        elif filled == ['nw', 'sw', 'w'] or filled == ['w']:
            tile = GROUND.DEEP_WATER_EAST
        # slight turn (looks best with straight coast)
        elif filled == ['e', 'se'] or filled == ['e', 'ne']:
            tile = GROUND.DEEP_WATER_WEST
        elif filled == ['n', 'ne'] or filled == ['n', 'nw']:
            tile = GROUND.DEEP_WATER_SOUTH
        elif filled == ['nw', 'w'] or filled == ['sw', 'w']:
            tile = GROUND.DEEP_WATER_EAST
        elif filled == ['s', 'sw'] or filled == ['s', 'se']:
            tile = GROUND.DEEP_WATER_NORTH
        # mostly deep corner
        elif filled == ['se']:
            tile = GROUND.DEEP_WATER_NORTHWEST1
        elif filled == ['ne']:
            tile = GROUND.DEEP_WATER_SOUTHWEST1
        elif filled == ['nw']:
            tile = GROUND.DEEP_WATER_SOUTHEAST1
        elif filled == ['sw']:
            tile = GROUND.DEEP_WATER_NORTHEAST1
        # mostly shallow corner
        elif 3 <= len(filled) <= 5:
            coast_set = set(filled)
            if 'e' in coast_set and 'se' in coast_set and 's' in coast_set:
                tile = GROUND.DEEP_WATER_NORTHEAST3
            elif 's' in coast_set and 'sw' in coast_set and 'w' in coast_set:
                tile = GROUND.DEEP_WATER_NORTHWEST3
            elif 'w' in coast_set and 'nw' in coast_set and 'n' in coast_set:
                tile = GROUND.DEEP_WATER_SOUTHWEST3
            elif 'n' in coast_set and 'ne' in coast_set and 'e' in coast_set:
                tile = GROUND.DEEP_WATER_SOUTHEAST3

        assert tile
        map_db("INSERT INTO ground VALUES(?, ?, ?, ?, ?, ?)", island_id,
               island_x + x, island_y + y, *tile)

    map_db("COMMIT")
	def _place_tile(self, coords):
		brush = Circle(Point(*coords), self.session.world_editor.brush_size - 1)
		self.session.world_editor.intermediate_map.set_south_east_corner(brush.tuple_iter(), self._tile_details)
def create_random_island(map_db, island_id, id_string):
	"""Creates a random island as sqlite db.
	It is rather primitive; it places shapes on the dict.
	The coordinates of tiles will be 0 <= x < width and 0 <= y < height
	@param id_string: random island id string
	"""
	match_obj = re.match(_random_island_id_regexp, id_string)
	assert match_obj
	creation_method, width, height, seed, island_x, island_y = [long(i) for i in match_obj.groups()]
	assert creation_method == 2, 'The only supported island creation method is 2.'

	rand = random.Random(seed)
	map_set = set()

	# place this number of shapes
	for i in xrange(15 + width * height // 45):
		# place shape determined by shape_id on (x, y)
		add = True
		shape_id = rand.randint(2, 8)
		rect_chance = 29
		if rand.randint(0, 4) == 0:
			rect_chance = 13
			add = False

		shape = None
		if rand.randint(1, rect_chance) == 1:
			# use a rect
			if add:
				x = rand.randint(8, width - 7)
				y = rand.randint(8, height - 7)
			else:
				x = rand.randint(0, width)
				y = rand.randint(0, height)
			shape = Rect.init_from_topleft_and_size(x - 5, y - 5, rand.randint(2, 8), rand.randint(2, 8))
		else:
			# use a circle such that the radius is determined by shape_id
			radius = shape_id
			if not add and rand.randint(0, 6) < 5:
				x = rand.randint(-radius * 3 // 2, width + radius * 3 // 2)
				y = rand.randint(-radius * 3 // 2, height + radius * 3 // 2)
				shape = Circle(Point(x, y), shape_id)
			elif width - radius - 4 >= radius + 3 and height - radius - 4 >= radius + 3:
				x = rand.randint(radius + 3, width - radius - 4)
				y = rand.randint(radius + 3, height - radius - 4)
				shape = Circle(Point(x, y), shape_id)

		if shape:
			for shape_coord in shape.tuple_iter():
				if add:
					map_set.add(shape_coord)
				elif shape_coord in map_set:
					map_set.discard(shape_coord)

	# write values to db
	map_db("BEGIN TRANSACTION")

	# add grass tiles
	for x, y in map_set:
		map_db("INSERT INTO ground VALUES(?, ?, ?, ?, ?, ?)", island_id, island_x + x, island_y + y, *GROUND.DEFAULT_LAND)

	def fill_tiny_spaces(tile):
		"""Fills 1 tile gulfs and straits with the specified tile
		@param tile: ground tile to fill with
		"""

		all_neighbours = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
		neighbours = [(-1, 0), (0, -1), (0, 1), (1, 0)]
		corners = [(-1, -1), (-1, 1)]
		knight_moves = [(-2, -1), (-2, 1), (-1, -2), (-1, 2), (1, -2), (1, 2), (2, -1), (2, 1)]
		bad_configs = set([0, 1 << 0, 1 << 1, 1 << 2, 1 << 3, (1 << 0) | (1 << 3), (1 << 1) | (1 << 2)])

		edge_set = copy.copy(map_set)
		reduce_edge_set = True

		while True:
			to_fill = set()
			to_ignore = set()
			for x, y in edge_set:
				# ignore the tiles with no empty neighbours
				if reduce_edge_set:
					is_edge = False
					for x_offset, y_offset in all_neighbours:
						if (x + x_offset, y + y_offset) not in map_set:
							is_edge = True
							break
					if not is_edge:
						to_ignore.add((x, y))
						continue

				for x_offset, y_offset in neighbours:
					x2 = x + x_offset
					y2 = y + y_offset
					if (x2, y2) in map_set:
						continue
					# (x2, y2) is now a point just off the island

					neighbours_dirs = 0
					for i in xrange(len(neighbours)):
						x3 = x2 + neighbours[i][0]
						y3 = y2 + neighbours[i][1]
						if (x3, y3) not in map_set:
							neighbours_dirs |= (1 << i)
					if neighbours_dirs in bad_configs:
						# part of a straight 1 tile gulf
						to_fill.add((x2, y2))
					else:
						for x_offset, y_offset in corners:
							x3 = x2 + x_offset
							y3 = y2 + y_offset
							x4 = x2 - x_offset
							y4 = y2 - y_offset
							if (x3, y3) in map_set and (x4, y4) in map_set:
								# part of a diagonal 1 tile gulf
								to_fill.add((x2, y2))
								break

				# block 1 tile straits
				for x_offset, y_offset in knight_moves:
					x2 = x + x_offset
					y2 = y + y_offset
					if (x2, y2) not in map_set:
						continue
					if abs(x_offset) == 1:
						y2 = y + y_offset // 2
						if (x2, y2) in map_set or (x, y2) in map_set:
							continue
					else:
						x2 = x + x_offset // 2
						if (x2, y2) in map_set or (x2, y) in map_set:
							continue
					to_fill.add((x2, y2))

				# block diagonal 1 tile straits
				for x_offset, y_offset in corners:
					x2 = x + x_offset
					y2 = y + y_offset
					x3 = x + 2 * x_offset
					y3 = y + 2 * y_offset
					if (x2, y2) not in map_set and (x3, y3) in map_set:
						to_fill.add((x2, y2))
					elif (x2, y2) in map_set and (x2, y) not in map_set and (x, y2) not in map_set:
						to_fill.add((x2, y))

			if to_fill:
				for x, y in to_fill:
					map_set.add((x, y))
					map_db("INSERT INTO ground VALUES(?, ?, ?, ?, ?, ?)", island_id, island_x + x, island_y + y, *tile)

				old_size = len(edge_set)
				edge_set = edge_set.difference(to_ignore).union(to_fill)
				reduce_edge_set = old_size - len(edge_set) > 50
			else:
				break

	# possible movement directions
	all_moves = {
		'sw' : (-1, -1),
		'w'  : (-1, 0),
		'nw' : (-1, 1),
		's'  : (0, -1),
		'n'  : (0, 1),
		'se' : (1, -1),
		'e'  : (1, 0),
		'ne' : (1, 1)
		}

	def get_island_outline():
		"""
		@return: the points just off the island as a dict
		"""
		result = set()
		for x, y in map_set:
			for offset_x, offset_y in all_moves.itervalues():
				coords = (x + offset_x, y + offset_y)
				if coords not in map_set:
					result.add(coords)
		return result

	# add grass to sand tiles
	fill_tiny_spaces(GROUND.DEFAULT_LAND)
	outline = get_island_outline()
	for x, y in outline:
		filled = []
		for dir in sorted(all_moves):
			coords = (x + all_moves[dir][1], y + all_moves[dir][0])
			if coords in map_set:
				filled.append(dir)

		tile = None
		# straight coast or 1 tile U-shaped gulfs
		if filled == ['s', 'se', 'sw'] or filled == ['s']:
			tile = GROUND.SAND_NORTH
		elif filled == ['e', 'ne', 'se'] or filled == ['e']:
			tile = GROUND.SAND_WEST
		elif filled == ['n', 'ne', 'nw'] or filled == ['n']:
			tile = GROUND.SAND_SOUTH
		elif filled == ['nw', 'sw', 'w'] or filled == ['w']:
			tile = GROUND.SAND_EAST
		# slight turn (looks best with straight coast)
		elif filled == ['e', 'se'] or filled == ['e', 'ne']:
			tile = GROUND.SAND_WEST
		elif filled == ['n', 'ne'] or filled == ['n', 'nw']:
			tile = GROUND.SAND_SOUTH
		elif filled == ['nw', 'w'] or filled == ['sw', 'w']:
			tile = GROUND.SAND_EAST
		elif filled == ['s', 'sw'] or filled == ['s', 'se']:
			tile = GROUND.SAND_NORTH
		# sandy corner
		elif filled == ['se']:
			tile = GROUND.SAND_NORTHWEST1
		elif filled == ['ne']:
			tile = GROUND.SAND_SOUTHWEST1
		elif filled == ['nw']:
			tile = GROUND.SAND_SOUTHEAST1
		elif filled == ['sw']:
			tile = GROUND.SAND_NORTHEAST1
		# grassy corner
		elif 3 <= len(filled) <= 5:
			coast_set = set(filled)
			if 'e' in coast_set and 'se' in coast_set and 's' in coast_set:
				tile = GROUND.SAND_NORTHEAST3
			elif 's' in coast_set and 'sw' in coast_set and 'w' in coast_set:
				tile = GROUND.SAND_NORTHWEST3
			elif 'w' in coast_set and 'nw' in coast_set and 'n' in coast_set:
				tile = GROUND.SAND_SOUTHWEST3
			elif 'n' in coast_set and 'ne' in coast_set and 'e' in coast_set:
				tile = GROUND.SAND_SOUTHEAST3

		assert tile
		map_db("INSERT INTO ground VALUES(?, ?, ?, ?, ?, ?)", island_id, island_x + x, island_y + y, *tile)
	map_set = map_set.union(outline)

	# add sand to shallow water tiles
	fill_tiny_spaces(GROUND.SAND)
	outline = get_island_outline()
	for x, y in outline:
		filled = []
		for dir in sorted(all_moves):
			coords = (x + all_moves[dir][1], y + all_moves[dir][0])
			if coords in map_set:
				filled.append(dir)

		tile = None
		# straight coast or 1 tile U-shaped gulfs
		if filled == ['s', 'se', 'sw'] or filled == ['s']:
			tile = GROUND.COAST_NORTH
		elif filled == ['e', 'ne', 'se'] or filled == ['e']:
			tile = GROUND.COAST_WEST
		elif filled == ['n', 'ne', 'nw'] or filled == ['n']:
			tile = GROUND.COAST_SOUTH
		elif filled == ['nw', 'sw', 'w'] or filled == ['w']:
			tile = GROUND.COAST_EAST
		# slight turn (looks best with straight coast)
		elif filled == ['e', 'se'] or filled == ['e', 'ne']:
			tile = GROUND.COAST_WEST
		elif filled == ['n', 'ne'] or filled == ['n', 'nw']:
			tile = GROUND.COAST_SOUTH
		elif filled == ['nw', 'w'] or filled == ['sw', 'w']:
			tile = GROUND.COAST_EAST
		elif filled == ['s', 'sw'] or filled == ['s', 'se']:
			tile = GROUND.COAST_NORTH
		# mostly wet corner
		elif filled == ['se']:
			tile = GROUND.COAST_NORTHWEST1
		elif filled == ['ne']:
			tile = GROUND.COAST_SOUTHWEST1
		elif filled == ['nw']:
			tile = GROUND.COAST_SOUTHEAST1
		elif filled == ['sw']:
			tile = GROUND.COAST_NORTHEAST1
		# mostly dry corner
		elif 3 <= len(filled) <= 5:
			coast_set = set(filled)
			if 'e' in coast_set and 'se' in coast_set and 's' in coast_set:
				tile = GROUND.COAST_NORTHEAST3
			elif 's' in coast_set and 'sw' in coast_set and 'w' in coast_set:
				tile = GROUND.COAST_NORTHWEST3
			elif 'w' in coast_set and 'nw' in coast_set and 'n' in coast_set:
				tile = GROUND.COAST_SOUTHWEST3
			elif 'n' in coast_set and 'ne' in coast_set and 'e' in coast_set:
				tile = GROUND.COAST_SOUTHEAST3

		assert tile
		map_db("INSERT INTO ground VALUES(?, ?, ?, ?, ?, ?)", island_id, island_x + x, island_y + y, *tile)
	map_set = map_set.union(outline)

	# add shallow water to deep water tiles
	fill_tiny_spaces(GROUND.SHALLOW_WATER)
	outline = get_island_outline()
	for x, y in outline:
		filled = []
		for dir in sorted(all_moves):
			coords = (x + all_moves[dir][1], y + all_moves[dir][0])
			if coords in map_set:
				filled.append(dir)

		tile = None
		# straight coast or 1 tile U-shaped gulfs
		if filled == ['s', 'se', 'sw'] or filled == ['s']:
			tile = GROUND.DEEP_WATER_NORTH
		elif filled == ['e', 'ne', 'se'] or filled == ['e']:
			tile = GROUND.DEEP_WATER_WEST
		elif filled == ['n', 'ne', 'nw'] or filled == ['n']:
			tile = GROUND.DEEP_WATER_SOUTH
		elif filled == ['nw', 'sw', 'w'] or filled == ['w']:
			tile = GROUND.DEEP_WATER_EAST
		# slight turn (looks best with straight coast)
		elif filled == ['e', 'se'] or filled == ['e', 'ne']:
			tile = GROUND.DEEP_WATER_WEST
		elif filled == ['n', 'ne'] or filled == ['n', 'nw']:
			tile = GROUND.DEEP_WATER_SOUTH
		elif filled == ['nw', 'w'] or filled == ['sw', 'w']:
			tile = GROUND.DEEP_WATER_EAST
		elif filled == ['s', 'sw'] or filled == ['s', 'se']:
			tile = GROUND.DEEP_WATER_NORTH
		# mostly deep corner
		elif filled == ['se']:
			tile = GROUND.DEEP_WATER_NORTHWEST1
		elif filled == ['ne']:
			tile = GROUND.DEEP_WATER_SOUTHWEST1
		elif filled == ['nw']:
			tile = GROUND.DEEP_WATER_SOUTHEAST1
		elif filled == ['sw']:
			tile = GROUND.DEEP_WATER_NORTHEAST1
		# mostly shallow corner
		elif 3 <= len(filled) <= 5:
			coast_set = set(filled)
			if 'e' in coast_set and 'se' in coast_set and 's' in coast_set:
				tile = GROUND.DEEP_WATER_NORTHEAST3
			elif 's' in coast_set and 'sw' in coast_set and 'w' in coast_set:
				tile = GROUND.DEEP_WATER_NORTHWEST3
			elif 'w' in coast_set and 'nw' in coast_set and 'n' in coast_set:
				tile = GROUND.DEEP_WATER_SOUTHWEST3
			elif 'n' in coast_set and 'ne' in coast_set and 'e' in coast_set:
				tile = GROUND.DEEP_WATER_SOUTHEAST3

		assert tile
		map_db("INSERT INTO ground VALUES(?, ?, ?, ?, ?, ?)", island_id, island_x + x, island_y + y, *tile)

	map_db("COMMIT")
 def get_warehouse_area(self, settlement, range=10):
     return Circle(self.get_warehouse_point(settlement), range)
 def get_positions():
     iters = (iter(Circle(point, radius)) for radius in xrange(
         cls.CHECK_NEARBY_LOCATIONS_UP_TO_DISTANCE))
     return itertools.chain.from_iterable(iters)
Exemple #37
0
 def _place_tile(self, coords):
     brush = Circle(Point(*coords),
                    self.session.world_editor.brush_size - 1)
     self.session.world_editor.intermediate_map.set_south_east_corner(
         brush.tuple_iter(), self._tile_details)