def __init__(self, owner, xy=None, celestial=None, territory=None, busy=False): self.owner = owner # the Player ID who owns this ('Evan') self.xy = xy # LID of region (0,0) (tuple) self.celestial = celestial self.territory = territory # LID of territory ('North') self.id = self.owner.upper() + type(self).__name__.lower() self.busy = busy # If the vehicle is doing something # get all the functions that can be "cast"-- abilities in game terms self.abilities = [f[2:] for f in dir(type(self)) if f.startswith('A_')] # set EID and add to area # note that EID must be reset whenever unit is added to new area self.eid = self.get_eid() if self.xy: # store self into Regions.pickle Regions = get_file('Regions.pickle') Regions[self.xy].content[self.eid] = self save_file(Regions, 'Regions.pickle') if self.territory: # store self into Territories.pickle Territories = get_file('Territories.pickle') TerrKey = self.celestial.upper() + self.territory.lower() Territories[TerrKey].content[self.eid] = self save_file(Territories, 'Territories.pickle')
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)
def get_entity_obj(entity_display, target_xy=None, target_celestial=None, target_territory=None,): """Gets a target entity object given the entity display name and a region entity_display -- The display name of an entity, e.g. "Breq's Halcyon" \n target_xy -- The "(x, y)" coordinates of the region containing the entity OR target_celestial -- The celestial the entity is on target_territory -- The territory that the entity is in """ if target_xy: # if it's in a region # get the region Regions = get_file('Regions.pickle') target_region = Regions[region_string_to_int(target_xy)] # get the entity object target_entity = target_region.content[entity_display] return target_entity if target_territory: # if it's in the territory Territories = get_file('Territories.pickle') TID = target_celestial.upper() + target_territory.lower() target_territory = Territories[TID] # get the entity object target_entity = target_territory.content[entity_display] return target_entity
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)
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)
def __init__(self, name, xy, territories={}): self.name = name self.xy = xy self.territories = territories # add self to the region designated by xy Regions = get_file('Regions.pickle') Regions[xy].content[name] = self save_file(Regions, 'Regions.pickle') # add self to celestial storage Celestials = get_file('Celestials.pickle') Celestials[self.name] = self save_file(Celestials, 'Celestials.pickle')
def payload_manage(pload): # check if the payload makes a task if pload.isTaskMaker: # get the source object sourceLID = pload.sourceLID sourceFile = sourceLID['LocFile'] sourceKey = sourceLID['LocKey'] sourceEID = sourceLID['EID'] storageDict = get_file(sourceFile) source = storageDict[sourceKey].content[sourceEID] if source.busy: # check if the entity is busy # ? set some sort of "activetask" attribute for entities ? # # ? we can use that to say what, exactly, they're busy doing ? # return f'```{source} is busy. Use ~cancel_task "entity_name" "entity_location" to cancel the task.```' # else, set the source to busy source.busy = True save_file(storageDict, sourceFile) # get numbers of minutes since epoch (MSE) right now current_MSE = int(time() // 60) # add the duration to figure out when to trigger trigger_time = current_MSE + (pload.taskDuration * 60) # create a Task, rest is handled in tasks.py Task(sourceLID, trigger_time, pload.onCompleteFunc, pload.onCompleteArgs) # * message management and output # We unpack the messages into a single string: bot_message = '```yaml\n' # send it as a code block for sub_message in pload.messages: bot_message = bot_message + sub_message + '\n' # get rid of the final linebreak and complete codeblock return bot_message[:-1] + '```'
def deluser(): username = request.args.get('username') if username in files.get_file().keys(): files.del_file(username) return redirect('/') else: return redirect('/')
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])
def __init__(self, xy): self.xy = xy self.content = {} # add self to the Regions dict Regions = get_file('Regions.pickle') Regions[self.xy] = self save_file(Regions, 'Regions.pickle')
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)
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)
def __init__(self, uid, name): # set attributes self.uid = uid self.name = name # store self into Players dict Players = get_file('Players.pickle') Players[uid] = self save_file(Players, 'Players.pickle')
def test(): username = request.args.get('username') password = request.args.get('password') if username in files.get_file().keys(): return redirect('/') else: files.write_file(username, password) return redirect('/')
def get_stat(self, stat): needed = 0 Tags = get_file('Tags.pickle') for t in self.tags: try: needed += Tags[t].statistics[stat] except KeyError: # doesn't have the statistic pass return needed
def __init__(self, category, name, attributes=[], statistics={}): self.category = category self.name = name self.attributes = attributes self.statistics = statistics # add self to Tags Tags = get_file('Tags.pickle') Tags[self.name] = self print(Tags) save_file(Tags, 'Tags.pickle')
def transform_image(transform_name, img_name): transform = transforms.get(transform_name) if transform: img_content = get_file(img_name) resp_content = "" if img_content: f = cStringIO.StringIO(img_content) outf, encoding = process_image(f, transform) content_type = mimetypes.guess_type("a.%s" % encoding) return make_response((outf.read(), 200, {'Content-Type': content_type})) return "404", 404
def manual_complete_all_tasks(): """Automatically completes all tasks in queue, regardless of time""" Tasks = get_file('Tasks.pickle') payloads = [] for sublist in Tasks.values(): for item in sublist: task_return = item.complete() payloads.append(task_return) Tasks = {} save_file(Tasks, 'Tasks.pickle') return payloads
def create_slingshot(self, c1, c2): # get the starting and ending region of space Regions = get_file('Regions.pickle') start_region = Regions[c1.xy] end_region = Regions[c2.xy] # create a Slingshot Path Terminus in each spot start_region.content['Slingshot Path Terminus'] = self.SPathTerminus( c1.xy, end_region) end_region.content['Slingshot Path Terminus'] = self.SPathTerminus( c2.xy, start_region) save_file(Regions, 'Regions.pickle')
async def scan(ctx, *args): """Returns the contents of the given region or territory. You must have vision of the target. Vision is typically granted by possessing a unit in that area. EXAMPLE: ~scan (0,0) OR EXAMPLE: ~scan Earth North target_xy -- The (x,y) coordinates of the region to scan OR celestial_name -- The name of the celestial the target is on territory_name -- The label of the territory the target is in""" if len(args) == 1: # if the caster is in a region target_xy = args[0] storage_file = 'Regions.pickle' Regions = get_file(storage_file) # translate coords to actual region object target = Regions[region_string_to_int(target_xy)] elif len(args) == 2: # if the caster is in a territory celestial_name = args[0] territory_name = args[1] territory_label = celestial_name.upper() + territory_name.lower() storage_file = 'Territories.pickle' Territories = get_file(storage_file) target = Territories[territory_label] else: await ctx.send('```Error: Improper number of arguments.\n ~scan "target_xy" OR ~scan "celestial_name" "territory_name"') return # check if the user has vision of the target uid = ctx.message.author.id if not target.check_vision(uid): await ctx.send(f'```You do not have vision of {target}.```') return # if they do, scan it result = target.scan() output = payload_manage(result) await ctx.send(output)
def transform_image(transform_name, img_name): transform = transforms.get(transform_name) if transform: img_content = get_file(img_name) resp_content = "" if img_content: f = cStringIO.StringIO(img_content) outf, encoding = process_image(f, transform) content_type = mimetypes.guess_type("a.%s" % encoding) return make_response((outf.read(), 200, { 'Content-Type': content_type })) return "404", 404
def complete(self): """ Calls the task's associated trigger_func """ # set the task user to not busy anymore sourceLID = self.sourceLID sourceFile = sourceLID['LocFile'] sourceKey = sourceLID['LocKey'] sourceEID = sourceLID['EID'] storageDict = get_file(sourceFile) source = storageDict[sourceKey].content[sourceEID] source.busy = False save_file(storageDict, sourceFile) # trigger the func return self.trigger_func(*self.trigger_args)
async def inspect_territory(ctx, planet, territory): """Inspects a given territory of a planet EXAMPLE: ~inspect_territory "North" "Earth" territory -- The name of the territory planet -- The name of the planet""" Territories = get_file('Territories.pickle') # get the territory ID TID = planet.upper() + territory.lower() territory_obj = Territories[TID] pload = territory_obj.inspect() output = payload_manage(pload) await ctx.send(output)
def __init__(self, sourceLID, trigger_hour, trigger_func, trigger_args): self.sourceLID = sourceLID self.trigger_hour = int(trigger_hour) self.trigger_func = trigger_func self.trigger_args = trigger_args # add self to the task storage dictionary under the trigger hour Tasks = get_file('Tasks.pickle') try: # if there are other tasks for that hour, add self to the list Tasks[self.trigger_hour].append(self) except KeyError: # if not, make a new list with self Tasks[self.trigger_hour] = [self] save_file(Tasks, 'Tasks.pickle')
def check_duplicate(self, EID): # print(f'CHECKING DUPLICATE: {EID}') if self.xy: # check for duplicate in region # get the region object Regions = get_file('Regions.pickle') region = Regions[self.xy] if EID in region.content.keys(): # duplicate found # increment i nonlocal entityIncrement entityIncrement += 1 # set new EID EID = EID[:-2] + f' {entityIncrement}' # check if the new EID is a dupe return check_duplicate(self, EID) else: # if there's no duplicate return EID if self.territory: # check for duplicate in territory Territories = get_file('Territories.pickle') TID = self.celestial.upper() + self.territory.lower() territory = Territories[TID] if EID in territory.content.keys(): # duplicate found # increment i entityIncrement += 1 # set new EID EID = EID[:-2] + f' {entityIncrement}' # check if the new EID is a dupe return check_duplicate(self, EID) else: # if there's no duplicate return EID
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()
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])
def check_vision(self, viewer_uid): '''Checks each entity in region, returns if <viewer_uid> owns any''' Players = get_file('Players.pickle') try: viewer = Players[viewer_uid] except KeyError as e: # generally if that player object hasn't been created print(f'check_vision KeyError {e}') return False for entity in self.content.values(): try: if entity.owner == viewer.name: return True except AttributeError as e: # generally, because there's an entity with no owner pass return False
def check_tasks(): """Runs through all tasks and runs then removes the appropriate ones""" Tasks = get_file('Tasks.pickle') current_MSE = int(time() / 60) print(f'CURRENT TIME: {current_MSE}') print(f'TASKS BEFORE: {Tasks}') payloads = [] # check every minute that currently has tasks on it for key in Tasks: # if that minute is before/equal to the current minute if key <= current_MSE: # complete all tasks under that minute for t in Tasks[key]: task_return = t.complete() payloads.append(task_return) # then, we create a new tasks dictionary with only the minute yet to come Tasks = {key: value for (key, value) in Tasks.items() if key > current_MSE} save_file(Tasks, 'Tasks.pickle') # send the output to the botCommands background loop return payloads
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])
async def register_player(ctx, player_name): """Registers a Discord user under the given player_name. EXAMPLE: ~register_player Evan player_name -- The player name to register the Discord user under. """ uid = ctx.message.author.id # make sure this is a unique player Players = get_file('Players.pickle') if uid in list(Players.keys()): await ctx.send('Error: you\'re already registered!') return # make sure this is a unique username if player_name in [p.name for p in Players.values()]: await ctx.send('Error: a player already has this name!') return # if both of those are math, initialize a Player object Player(uid, player_name) await ctx.send(f'Player {player_name} created with UID {uid}')
def calculate_response(response_type, request_handler, method, request_uri, headers, data, error_code): if response_type == 'html': request = { 'method': method.upper(), 'path': request_uri, 'headers': headers, 'variables': data } handler = getattr(functions, request_handler) response = handler(request).split('\r\n\r\n', 1) if response[0].startswith('HTTP/1.0 302 Moved Temporarily\r\nLocation: '): redirect = response[0].lower()[42:] if redirect in redirects: request['method'] = 'GET' text = redirects[redirect](request).split('\r\n\r\n', 1)[1] else: text = response[1] else: text = response[1] temp_result = re.sub(r'<input.+?>', 'input', text) result = re.sub(r'<ul.+?class=[\'\"].+?menu.+?[\'\"]>.+?</ul>', 'menu', temp_result) return result if response_type == 'static': root, filename = files.get_static_path(request_uri) return files.get_file(root, filename) if response_type == 'error': return http.error(error_code).split('\r\n\r\n', 1)[1] print "Invalid response type" exit(0)
def handle_read(self): bytes = self.recv(self.recv_block_size) if not bytes: return # get http-headers if not self.http_headers: result = self._recv_headers(bytes) if result != 'done': # http headers are not recieved return else: # get http-data self.http_data.write(bytes) self.http_data_size = self.http_data_size + bytes.__len__() request_method = self.request_line[0] parts = self.request_line[1].split('?', 1) request_uri = parts[0] # GET variables are with unique names! variables = dict(parse_qsl(parts[1])) if parts.__len__() > 1 else {} if request_method not in ('GET', 'POST'): self.error = 405 self.buffer_out = http.error(self.error) return headers = [] # check for static (css|js|img) content static_exts = ('.css', '.jpg', '.png', '.gif', '.svg', '.xml', '.txt') if request_uri[-4:] in static_exts or \ request_uri[-3:] == '.js' or request_uri[-5:] == '.jpeg': if request_method == 'POST': self.error = 405 self.buffer_out = http.error(self.error) return root, filename = files.get_static_path(request_uri) if root is None: self.error = 404 self.buffer_out = http.error(self.error) return content = files.get_file(root, filename) if content is None: self.error = 404 self.buffer_out = http.error(self.error) return # add MIME type to headers if request_uri.endswith('.css'): headers.append('Content-Type: text/css',) if request_uri.endswith('.js'): headers.append('Content-Type: application/x-javascript',) if request_uri.endswith('.jpg') or request_uri.endswith('.jpeg'): headers.append('Content-Type: image/jpeg',) if request_uri.endswith('.png'): headers.append('Content-Type: image/png',) if request_uri.endswith('.gif'): headers.append('Content-Type: image/gif',) if request_uri.endswith('.svg'): headers.append('Content-Type: image/svg+xml',) self.buffer_out = http.response(200, "OK", headers, content) return # check request url in router found = False for line in self.router: uri = line[0] functions = line[1] cachable = line[2] response = '' m = re.match(uri, request_uri) if m: if request_method == 'GET' and functions[0]: found = True function = functions[0] break if request_method == 'POST' and functions[1]: found = True function = functions[1] break self.error = 405 self.buffer_out = http.error(self.error) return if not found: self.error = 404 self.buffer_out = http.error(self.error) return # POST request if request_method == 'POST': try: content_length = int(http.get_header(self.http_headers, \ 'Content-Length')) except (ValueError, TypeError): self.error = 411 self.buffer_out = http.error(self.error) return # unauth zone request if not request_uri.startswith(core.MANAGER_URL) or \ request_uri == '%slogin/' % core.MANAGER_URL: # check POST restrictions if content_length > self.max_unauth_data: self.error = 413 self.buffer_out = http.error(self.error) return # recieve POST data if self._recv_data(request_uri, variables, content_length): return post = http.parse_post_data(self.http_headers, self.http_data, \ self.max_memory_data_size) variables.update(post) if not request_uri.startswith(core.MANAGER_URL) or \ request_uri == '%slogin/' % core.MANAGER_URL: # check valid token if 'token' not in variables.iterkeys() or \ not protection.valid_client_token(variables['token']): self.error = 403 self.buffer_out = http.error(self.error) return # check for upload file progress request if request_method == 'GET' and request_uri.endswith('/progress/') and \ request_uri[:-9] in ALLOWED_UPLOAD_URIS: response = self.get_upload_progress(variables) self.buffer_out = http.json_data(response) return need_generate_response = False need_cache = False # check cache for existing item if request_method == 'GET' and cachable: content = self.cache.get(request_uri) if not content: need_generate_response = True need_cache = True if request_method == 'GET' and not cachable: need_generate_response = True need_cache = False # POST requests are not cachable if request_method == 'POST': need_generate_response = True need_cache = False if not need_generate_response: headers = ( 'Content-Type: text/html', 'Content-Length: %s' % content.__len__() ) response = http.response(200, "OK", headers, content) else: # generate response by function parameters = m.groups() request = { 'method': request_method, 'path': request_uri, 'headers': self.http_headers, 'variables': variables, 'files': None } if DEBUG: response = function(request, *parameters) else: try: response = function(request, *parameters) except: self.error = 500 self.buffer_out = http.error(self.error) return if need_cache: # add to cache self.cache.set(request_uri, response) # copy to buffer self.buffer_out = response return