Beispiel #1
0
    def A_move_region(self, adjacent_region):
        """Move to an adjacent region of space

        adjacent_region -- (x,y) coordinates of an adjacent region"""
        # check to make sure not on celestial
        if self.celestial:
            message = [
                f'{self} is currently on the celestial {self.celestial}. Use the take_off ability before trying to move regions.'
            ]
            return Payload(self.get_LID(), message)
        # get the two region objects
        Regions = get_file('Regions.pickle')
        r1 = Regions[self.xy]
        # this is a user-facing ability, so adjacent_region is a string
        adjacent_region_tup = region_string_to_int(adjacent_region)
        r2 = Regions[adjacent_region_tup]
        # calculate the distance between the two regions
        distance = distance_between(r1.xy[0], r2.xy[0], r1.xy[1], r2.xy[1])
        # calculate the time it would take in hours
        duration = distance / self.speed_space
        messages = [
            f'{self} is now moving towards {r2}.',
            f'It will arrive in {duration} hours'
        ]
        return Payload(self.get_LID(),
                       messages,
                       isTaskMaker=True,
                       taskDuration=duration,
                       onCompleteFunc=self.set_new_region,
                       onCompleteArgs=[adjacent_region_tup])
Beispiel #2
0
 def resource_harvested(self, resource_name, harvester_ID):
     # need to do this so we can save
     Territories = get_file('Territories.pickle')
     self_territory = Territories[self.id]
     harvester = self_territory.content[harvester_ID]
     try:
         # decrease resource by 1
         self_territory.resources[resource_name] -= 1
     except KeyError as e:
         # double-check that the resource is actually here
         print(
             f'{e} not found in {self} when harvest was attempted by {self.content[harvester_ID]}.'
         )
         messages = [
             f'{resource_name} in {self} was depleted before {self.content[harvester_ID]} could complete harvest.'
         ]
         return Payload(None, messages)
     # add the resource to the harvester's inventory
     if resource_name in self.content[harvester_ID].inventory:
         # increment if already exists
         self_territory.content[harvester_ID].inventory[resource_name] += 1
     else:
         # set if it doesn't exist
         self_territory.content[harvester_ID].inventory[resource_name] = 1
     # save inventory and resource changes
     save_file(Territories, 'Territories.pickle')
     messages = [f'{harvester} has harvested 1 {resource_name}.']
     return Payload(None, messages)
Beispiel #3
0
    def A_harvest_resource(self, resource_name):
        """Harvest a resource in the same territory as this Harvester

        resource_name -- The name of the resource to harvest
        You can see the resources in a territory with ~scan.
        """
        # get the territory of self
        TID = self.celestial.upper() + self.territory.lower()
        Territories = get_file('Territories.pickle')
        terr_obj = Territories[TID]
        try:
            if terr_obj.resources[resource_name] != 0:
                # harvest the resource
                duration = self.harvest_time
                messages = [f'{self} is now harvesting 1 {resource_name} from {self.territory} {self.celestial}.',
                            f'It will be completed in {duration} hours.']
                return Payload(self.get_LID(), messages, isTaskMaker=True,
                               taskDuration=duration,
                               onCompleteFunc=terr_obj.resource_harvested,
                               onCompleteArgs=[resource_name, self.eid])
            elif terr_obj.resource[resource_name] == 0:
                messages = [f'The {resource_name} in {self.territory} is depleted.',
                            f'Wait for Evan to implement the regeneration mechanic.']
                return Payload(self.get_LID(), messages)
        except KeyError:
            # if the resource doesn't exist at all in the territory
            messages = [f'There is no {resource_name} in {self.territory}']
            return Payload(self.get_LID(), messages)
Beispiel #4
0
    def set_new_region(self, new_region_xy):
        """Trigger function used to move the entity into a new region

        First, deletes the entity from its old region or territory
        Then places the entity in the new region

        new_region_xy -- The tuple (x,y) of the new region
        """
        # get the region storage file
        Regions = get_file('Regions.pickle')
        if self.eid in Regions[self.xy].content:
            # remove self from old region
            del Regions[self.xy].content[self.eid]
        else:
            # triggered if the entity is on a celestial
            # therefore:
            Territories = get_file('Territories.pickle')
            # get the Territory ID from the celestial + territory name
            TID = self.celestial.upper() + self.territory.lower()
            # remove self from the territory and celestial
            self.territory = None
            self.celestial = None
            del Territories[TID].content[self.eid]
            save_file(Territories, 'Territories.pickle')
        # add self to new region
        self.xy = new_region_xy
        new_region = Regions[new_region_xy]
        new_region.content[self.get_eid()] = self
        save_file(Regions, 'Regions.pickle')
        # managing output (what the bot should send)
        messages = [f'{self} has arrived in {new_region_xy}']
        return Payload(self.get_LID(), messages)
Beispiel #5
0
    def set_new_territory(self, new_territory_ID):
        """Trigger function used to place the entity in a new territory

        First, deletes from the old region or territory
        Then, places in the new territory

        new_territory_ID -- The territory ID string, e.g. EARTHnorth
        """
        if self.xy:
            # delete self, if in a region
            Regions = get_file('Regions.pickle')
            old_region = Regions[self.xy]
            del old_region.content[self.eid]
            save_file(Regions, 'Regions.pickle')
        if self.territory:
            # delete self, if in a territory
            Territories = get_file('Territories.pickle')
            TID = self.celestial.upper() + self.territory.lower()
            old_territory = Territories[TID]
            del old_territory.content[self.eid]
            save_file(Territories, 'Territories.pickle')
        # now we add to new territory
        Territories = get_file('Territories.pickle')
        new_territory = Territories[new_territory_ID]
        self.celestial = new_territory.parent
        self.territory = new_territory.label
        new_territory.content[self.get_eid()] = self
        # change self.territory
        save_file(Territories, 'Territories.pickle')
        # bot output
        messages = [f'{self} has arrived in {new_territory}']
        return Payload(self.get_LID(), messages)
Beispiel #6
0
    def landed_on(self, entity_id, target_territory):
        '''Function that is called when this celestial is landed on

        entity_id -- The ID of the entity that is lending on this celestial
        target_territory -- The territory this entity will land'''
        # * Note that this "sucks in" the landing_entity * #
        # * Vs. the entity actually landing * #
        # * The celestial is doing all the work * #
        Regions = get_file('Regions.pickle')
        # get the region object
        Region = Regions[self.xy]
        # get the entity object from the region dict
        entity_obj = Region.content[entity_id]
        # get the territory object from Territories.pickle
        Territories = get_file('Territories.pickle')
        territory_obj = Territories[self.name.upper() +
                                    target_territory.lower()]
        # add the entity to the territory
        territory_obj.content[entity_id] = entity_obj
        # set the attributes of the vehicle
        entity_obj.celestial = self.name
        entity_obj.territory = target_territory
        save_file(Territories, 'Territories.pickle')
        # delete the entity from the region
        del Region.content[entity_id]
        save_file(Regions, 'Regions.pickle')
        # return the payload for the landing
        messages = [
            f'{entity_obj} has landed on the {target_territory} region of {self}.'
        ]
        return Payload(self, messages)
async def on_command_error(ctx, error):
    '''Manages error messages'''
    # This prevents any commands with local handlers being handled here in on_command_error.
    if hasattr(ctx.command, 'on_error'):
        return
    if isinstance(error, commands.errors.CommandInvokeError):
        err_string = str(error)
        if 'KeyError' in err_string:
            missing_ID = err_string.split()[-1]
            messages = [f'A lookup failed when looking under the ID {missing_ID}.',
                        'You may have mistyped the entity name, or are searching in the wrong region/territory.',
                        'Try ~scanning the region or territory to make sure the entity is in it.']
            output = payload_manage(Payload(None, messages))
            await ctx.send(output)
        traceback.print_exception(type(error), error, error.__traceback__)
        return
    if isinstance(error, commands.errors.MissingRequiredArgument):
        command = ctx.command
        signature = command.signature.replace('<', '"').replace('>', '"')
        messages = [f'Improper usage or missing arguments for {command}.',
                    f'{command.name} {signature}']
        output = payload_manage(Payload(None, messages))
        await ctx.send(output)
        return
    if isinstance(error, commands.errors.CommandNotFound):
        attempt = ctx.message.content[1:]
        all_commands = bot.all_commands
        possible_commands = [c for c in all_commands if attempt in c]
        messages = [f'The command "{attempt}" does not exist']
        if possible_commands:
            messages.append(f'Did you mean: {possible_commands}?')
        else:
            messages.append(f'No commands contain "{attempt}".')
        output = payload_manage(Payload(None, messages))
        await ctx.send(output)
        return
    if isinstance(error, KeyError):
        messages = f'No result was found when looking up {error}'
        output = payload_manage(Payload(None, messages))
        await ctx.send(output)
        return
    print('Ignoring exception in command {}:'.format(ctx.command))
    traceback.print_exception(type(error), error, error.__traceback__)
Beispiel #8
0
 def scan(self):
     messages = [
         f'This is the region of space denoted by the coordinates {self.xy}',
         'This region contains the following entities:'
     ]
     for obj in self.content.values():
         try:
             messages.append(f'  {str(obj)} | {obj.owner}')
         except AttributeError:
             messages.append(f'  {str(obj)} | {type(obj).__name__}')
     return Payload(None, messages)
Beispiel #9
0
 def on_landing(self, landing_obj):
     # get the distance between each celestial (in millions of miles)
     distance = distance_between(self.xy[0], self.linkRegion.xy[0],
                                 self.xy[1], self.linkRegion.xy[1])
     # divide that distance by the slingshot travel rate
     travel_time = distance / 25
     return Payload(self.get_LID(), ['Hello'],
                    isTaskMaker=True,
                    taskDuration=travel_time,
                    onCompleteFunc=landing_obj.change_region,
                    onCompleteArgs=self.linkRegion)
Beispiel #10
0
 def inspect(self):
     """Returns details describing the current state of this entity"""
     messages = [f'A {type(self).__name__} belonging to {self.owner}.']
     if self.xy:
         messages.append(f'It is currently in the region {self.xy}')
     if self.celestial:
         messages.append(
             f'It is currently on the celestial {self.celestial}, in the {self.territory} territory.'
         )
     messages.append(f'It has the following abilities: {self.abilities}')
     return Payload(self.get_LID(), messages)
Beispiel #11
0
 def A_take_off(self):
     """Takes off from the current celestial into the surrounding region"""
     duration = self.speed_landing
     messages = [
         f'{self} is now preparing to take off from the {self.territory} territory of {self.celestial}',
         f'It will arrive in the {self.xy} region in {duration} hours.'
     ]
     return Payload(self.get_LID(),
                    messages,
                    isTaskMaker=True,
                    taskDuration=duration,
                    onCompleteFunc=self.change_region,
                    onCompleteArgs=[self.xy])
Beispiel #12
0
    def A_move_territory(self, new_territory):
        """Move to another territory on the same celestial

        EXAMPLE move_territory South

        new_territory -- The territory on the same celestial to move to
        Territories can be found by ~scanning the celestial
        """
        # check to make sure in territory, not region
        if self.xy:
            message = [f'{self} is currently in the space region {self.xy}, not a territory.']
            return Payload(self.get_LID(), message)
        # this is a user-facing ability, so convert to TID
        new_TID = self.celestial.upper() + new_territory.lower()
        # calculate the time it would take in hours
        duration = self.speed_land
        messages = [f'{self} is now moving towards the {new_territory} territory of {self.celestial}.',
                    f'They will arrive in {duration} hours']
        return Payload(self.get_LID(), messages, isTaskMaker=True,
                       taskDuration=duration,
                       onCompleteFunc=self.set_new_territory,
                       onCompleteArgs=[new_TID])
Beispiel #13
0
    def A_construct_building(self, plan_name):
        """Help construct a building plan in the same territory as this Builder

        plan_name -- The name of the building plan to construct
        You can see plans in the territory with ~scan
        """
        # get the territory of self
        TID = self.celestial.upper() + self.territory.lower()
        Territories = get_file('Territories.pickle')
        terr_obj = Territories[TID]
        try:
            # get the building plan obj
            bpan = terr_obj.content[plan_name]
            messages = [f'{bpan} is now being worked on by {self}.',
                        f"The {bpan}'s progress will be advanced in {self.build_time} hours."]
            return Payload(self.get_LID(), messages,
                           isTaskMaker=True, taskDuration=self.build_time,
                           onCompleteFunc=bpan.worked_on,
                           onCompleteArgs=[1])
        except KeyError:
            # if the name doesn't exist in the territory
            messages = [f'There is no plan named "{plan_name}" in {self.territory}.']
            return Payload(self.get_LID(), messages)
Beispiel #14
0
 def scan(self):
     messages = [
         f'The {self.label} territory of the celestial {self.parent}.',
         f'It is a {self.description} biome.',
         f'It currently hosts the following resources: {self.resources}'
     ]
     if self.content:
         messages.append(f'It currently contains the following entities:')
     for obj in self.content.values():
         try:
             messages.append(f'  {str(obj)} | {obj.owner}')
         except AttributeError:
             messages.append(f'  {str(obj)} | {type(obj).__name__}')
     return Payload(self, messages)
Beispiel #15
0
 def worked_on(self, UoC):
     "Trigger func when this building plan is Built by an Actor"
     # need to save self
     LID = self.get_LID()
     Storage = get_file(LID['LocFile'])
     self.construction_remaining -= UoC
     Storage[LID['LocKey']].content[self.eid] = self
     save_file(Storage, LID['LocFile'])
     if self.construction_remaining > 0:
         # if there is still construction to be done
         messages = [f'The construction progress of {self.name} has advanced.',
                     f'It now requires {self.construction_remaining} units of Construction to be completed.']
         return Payload(self.get_LID(), messages)
     elif self.construction_remaining <= 0:
         # if construction_remaining is 0 or less
         return self.complete()
Beispiel #16
0
 def A_calculate_slingshot(self, celest_1, celest_2):
     # * bot-facing function * #
     # calculates a fast path between two celestials
     # first, we have to check that both celestials exist
     Celestials = get_file('Celestials.pickle')
     try:
         c1 = Celestials[celest_1]
         c2 = Celestials[celest_2]
     except KeyError as e:
         return f"The indicated celestial {e} does not exist"
     # now we send out a Payload object to the bot
     return Payload(self.get_LID(), ['Hello'],
                    isTaskMaker=True,
                    taskDuration=1,
                    onCompleteFunc=self.create_slingshot,
                    onCompleteArgs=[c1, c2])
async def ability_help(ctx, entity_display, target_xy, ability):
    """Sends a help display for an ability of a given entity

    EXAMPLE: ~ability_help "Evan's Halcyon" (0,0) move_region

    entity_display -- The display name of the target, e.g. "Breq's Halcyon" \n
    target_xy -- The (x,y) coordinates of the target \n
    ability -- The ability name to display help for (shown by ~inspect)
    """
    target = get_entity_obj(entity_display, target_xy=target_xy)
    ability_method = getattr(target, 'A_' + ability)
    arg_count = ability_method.__code__.co_argcount
    arguments = str(ability_method.__code__.co_varnames[1:arg_count])
    messages = [str(ability_method.__name__)[2:] + '- Arguments: ' + arguments,
                str(ability_method.__doc__)]
    output = payload_manage(Payload(None, messages))
    await ctx.send(output)
Beispiel #18
0
    def A_land_on(self, target_celestial, target_territory):
        """Land on any celestial body capable of hosting a ship

        target_celestial -- The celestial to land on, must be in same region
        target_territory -- The territory the ship should land in
        (Territories can be viewed by ~inspect_entity <landing_target>"""
        duration = self.speed_landing
        # Get the landing_target object
        Regions = get_file('Regions.pickle')
        landing_target = Regions[self.xy].content[target_celestial]
        messages = [
            f'{self} is now preparing to land on {landing_target}.',
            f'It will arrive in {duration} hours.'
        ]
        return Payload(self.get_LID(),
                       messages,
                       isTaskMaker=True,
                       taskDuration=duration,
                       onCompleteFunc=landing_target.landed_on,
                       onCompleteArgs=[self.eid, target_territory])
Beispiel #19
0
 def inspect(self):
     messages = [
         f'The planet {self.name}, located in {self.xy}.',
         f'Contains the territories {list(self.territories.keys())}.'
     ]
     return Payload(self, messages)