예제 #1
0
    def hits(self, x: int, y: int) -> Dict[str, List[Entity]]:
        # Returns a list of indirect and direct hits.
        indirect = []
        direct = []
        for subname in get_subs():
            sub = get_sub(subname)
            pos = sub.movement.get_position()
            distance = diagonal_distance(pos, (x, y))
            if distance == 0:
                direct.append(sub)
            elif distance == 1:
                indirect.append(sub)

        for npcid in get_npcs():
            npc = get_npc(npcid)
            pos = npc.get_position()
            distance = diagonal_distance(pos, (x, y))
            if distance == 0:
                direct.append(npc)
            elif distance == 1:
                indirect.append(npc)

        shuffle(indirect)
        shuffle(direct)
        return {"indirect": indirect, "direct": direct}
예제 #2
0
    async def broadcast(self, content: str):
        if self.last_comms + COMMS_COOLDOWN > now():
            return False

        my_pos = self.sub.movement.get_position()
        for subname in get_subs():
            if subname == self.sub._name:
                continue

            sub = get_sub(subname)

            dist = diagonal_distance(my_pos, sub.movement.get_position())
            garbled = self.garble(content, dist)
            if garbled is not None:
                await sub.send_message(
                    f"**Message received from {self.sub.name()}**:\n`{garbled}`\n**END MESSAGE**",
                    "captain")

        for npcid in get_npcs():
            npc = get_npc(npcid)

            dist = diagonal_distance(my_pos, npc.get_position())
            garbled = self.garble(content, dist)
            if garbled is not None:
                await npc.send_message(
                    f"**Message received from {self.sub.name()}**:\n`{garbled}`\n**END MESSAGE**",
                    "")
        self.last_comms = now()
        return True
예제 #3
0
async def explode(pos: Tuple[int, int],
                  power: int,
                  sub_exclusions: List[str] = [],
                  npc_exclusions: List[int] = []):
    """
    Makes an explosion in pos, dealing power damage to the centre square,
    power-1 to the surrounding ones, power-2 to those that surround and
    so on.
    """
    from ALTANTIS.subs.state import get_sub_objects
    from ALTANTIS.npcs.npc import get_npc_objects
    for sub in get_sub_objects():
        if sub._name in sub_exclusions:
            continue

        sub_pos = sub.movement.get_position()
        sub_dist = diagonal_distance(pos, sub_pos)
        damage = power - sub_dist

        if damage > 0:
            await sub.send_message(f"Explosion in {pos}!", "captain")
            sub.damage(damage)

    for npc in get_npc_objects():
        if npc.id in npc_exclusions:
            continue

        npc_pos = npc.get_position()
        npc_dist = diagonal_distance(pos, npc_pos)
        damage = power - npc_dist

        if damage > 0:
            await npc.send_message(f"Explosion in {pos}!", "captain")
            npc.damage(damage)
예제 #4
0
파일: npc.py 프로젝트: finnbar/ALTANTIS
 def move_towards_sub(self, dist: int) -> bool:
     """
     Looks for the closest sub in range, and moves towards it.
     """
     nearby_entities: List[Entity] = all_in_submap(self.get_position(),
                                                   dist)
     closest: Tuple[Optional[Submarine], int] = (None, 0)
     for entity in nearby_entities:
         if isinstance(entity, Submarine):
             sub: Submarine = entity
             this_dist = diagonal_distance(self.get_position(),
                                           sub.get_position())
             if (closest[0] is None) or this_dist < closest[1]:
                 closest = (entity, this_dist)
     if closest[0] is not None:
         direction = determine_direction(self.get_position(),
                                         closest[0].get_position())
         if direction is not None:
             rotated = rotate_direction(direction)
             directions = [direction]
             if rotated is not None:
                 directions.append(rotated[0])
                 directions.append(rotated[1])
             for possible_direction in directions:
                 if self.move(*go_in_direction(possible_direction)):
                     return True
     return False
예제 #5
0
def all_in_submap(pos: Tuple[int, int],
                  dist: int,
                  sub_exclusions: List[str] = [],
                  npc_exclusions: List[int] = []) -> List[Entity]:
    from ALTANTIS.subs.state import filtered_teams, get_sub
    from ALTANTIS.npcs.npc import filtered_npcs, get_npc
    """
    Gets all entities some distance from the chosen square.
    Ignores any entities in exclusions.
    """
    result: List[Entity] = []
    subs_in_range = filtered_teams(
        lambda sub: diagonal_distance(sub.movement.get_position(
        ), pos) <= dist and sub._name not in sub_exclusions)
    for sub in map(get_sub, subs_in_range):
        if sub: result.append(sub)
    npcs_in_range = filtered_npcs(lambda npc: diagonal_distance(
        npc.get_position(), pos) <= dist and npc.id not in npc_exclusions)
    for npc in map(get_npc, npcs_in_range):
        if npc: result.append(npc)
    return result
예제 #6
0
 def prepare_shot(self, damaging: bool, x: int, y: int) -> str:
     if not in_world(x, y):
         return "Coordinate outside of world."
     if diagonal_distance(self.sub.movement.get_position(),
                          (x, y)) > self.range:
         return "Coordinate outside of range."
     if damaging and self.weapons_charge >= 2:
         self.planned_shots.append((True, x, y))
         self.weapons_charge -= 2
         return f"Damaging shot fired at ({x}, {y})!"
     if (not damaging) and self.weapons_charge >= 1:
         self.planned_shots.append((False, x, y))
         self.weapons_charge -= 1
         return f"Non-damaging shot fired at ({x}, {y})!"
     return "Not enough charge to use that."
예제 #7
0
파일: comms.py 프로젝트: finnbar/ALTANTIS
    async def broadcast(self, content : str) -> str:
        if self.last_comms + COMMS_COOLDOWN > now():
            return f"The comms system is still cooling down! (Requires {int(self.last_comms + COMMS_COOLDOWN - now())}s more.)"

        if self.sub.power.get_power("comms") == 0:
            return "Cannot use comms system that isn't powered!"
        
        my_pos = self.sub.movement.get_position()
        for sub in get_sub_objects():
            if sub._name == self.sub._name:
                continue

            dist = diagonal_distance(my_pos, sub.movement.get_position())
            garbled = self.garble(content, dist)
            if garbled is not None:
                await sub.send_message(f"**Message received from {self.sub.name()}**:\n`{garbled}`\n**END MESSAGE**", "captain")

        for npc in get_npc_objects():
            dist = diagonal_distance(my_pos, npc.get_position())
            garbled = self.garble(content, dist)
            if garbled is not None:
                await npc.send_message(f"**Message received from {self.sub.name()}**:\n`{garbled}`\n**END MESSAGE**", "")
        self.last_comms = now()
        return "Transmitted message."
예제 #8
0
파일: scan.py 프로젝트: the-Bruce/ALTANTIS
def explore_submap(pos: Tuple[int, int],
                   dist: int,
                   sub_exclusions: Collection[str] = (),
                   npc_exclusions: Collection[int] = (),
                   with_distance: bool = False) -> List[str]:
    """
    Explores the area centered around pos = (cx, cy) spanning distance dist.
    Returns all outward_broadcast events (as a list) formatted for output.
    Ignores any NPCs or subs with a name included in exclusions.
    """
    events = []
    (cx, cy) = pos
    # First, map squares.
    for i in range(-dist, dist + 1):
        x = cx + i
        if x < 0 or x >= X_LIMIT:
            continue
        for j in range(-dist, dist + 1):
            y = cy + j
            if y < 0 or y >= Y_LIMIT:
                continue
            this_dist = diagonal_distance((0, 0), (i, j))
            event = get_square(x, y).outward_broadcast(dist - this_dist)
            if event != "":
                direction = determine_direction((cx, cy), (x, y))
                if direction is None:
                    event = f"{event} - in your current square!"
                else:
                    distance_measure = ""
                    if with_distance:
                        distance_measure = f" at a distance of {this_dist} away"
                    event = f"{event} - in direction {direction.upper()}{distance_measure}!"
                events.append(event)

    # Then, submarines.
    for subname in get_subs():
        if subname in sub_exclusions:
            continue

        sub = get_sub(subname)
        sub_pos = sub.movement.get_position()
        sub_dist = diagonal_distance(pos, sub_pos)

        # If out of range, drop it.
        if sub_dist > dist:
            continue

        event = sub.scan.outward_broadcast(dist - sub_dist)
        direction = determine_direction(pos, sub_pos)
        if direction is None:
            event = f"{event} in your current square!"
        else:
            event = f"{event} in direction {direction.upper()}!"
        events.append(event)

    # Finally, NPCs.
    for npcid in get_npcs():
        if npcid in npc_exclusions:
            continue

        npc_obj = get_npc(npcid)
        npc_pos = npc_obj.get_position()
        npc_dist = diagonal_distance(pos, npc_pos)

        if npc_dist > dist:
            continue

        event = npc_obj.outward_broadcast(dist - npc_dist)
        direction = determine_direction(pos, npc_pos)
        if direction is None:
            event = f"{event} in your current square!"
        else:
            event = f"{event} in direction {direction.upper()}!"
        events.append(event)

    return events