def breadthFirstSearch(gui: Gui, start: Node, end: Node) -> bool: """Runs A* algorithm This algorithm explores all of the neighbor nodes at the present depth prior to moving on to the nodes at the next depth level. Reference = [https://en.wikipedia.org/wiki/Breadth-first_search] Parameters ---------- nodes : list A list of nodes present in the grid start : Node The starting point end : Node The ending point Returns ------- bool True if the ending node was reached, else False """ def buildReversePath(came_from: dict, current: Node): while current in came_from: current = came_from[current] current.setState("path") gui.updateContents() came_from = {} open_set = [ start ] # The FIFO data structure for exploring all of the neighbor nodes as soon as they shows up visited = [] while open_set: for event in pygame.event.get(): if event.type == pygame.QUIT: gui.close() current = open_set.pop(0) visited.append(current) if current == end: buildReversePath(came_from, end) end.setState("end point") start.setState("start point") return True for neighbor in current.neighbors: if neighbor not in visited and neighbor.state != "watch": open_set.append(neighbor) came_from[neighbor] = current neighbor.setState("watch") gui.updateContents() if current != start: current.setState("visited") gui.updateContents() return False
def depthFirst(gui: Gui, start: Node, end: Node) -> bool: """Runs Depth-First Search Algorithm This algorithm explores as far as possible along each branch of a tree (or graph) before backtracking. Reference = [https://en.wikipedia.org/wiki/Depth-first_search] Parameters ---------- nodes : list A list of nodes present in the grid start : Node The starting point end : Node The ending point Returns ------- bool True if the ending node was reached, else False """ def buildReversePath(came_from: dict, current: Node): while current in came_from: current = came_from[current] current.setState("path") gui.updateContents() came_from = {} open_set = [ start ] # The LIFO data structure for exploring as far as possible along each branch visited = [] while open_set: for event in pygame.event.get(): if event.type == pygame.QUIT: gui.close() current = open_set.pop(-1) visited.append(current) if current == end: buildReversePath(came_from, end) end.setState("end point") start.setState("start point") return True for neighbor in current.neighbors: if neighbor not in visited: came_from[neighbor] = current open_set.append(neighbor) neighbor.setState("watch") gui.updateContents() if current != start: current.setState("visited") gui.updateContents() return False
def main(): gui_fps = 120 path_finding_fps = 30 gui = Gui(fps=gui_fps) # Mapping the keys that triggers an algorithm initialization search_mapping = { pygame.K_a: aStar, pygame.K_d: depthFirst, pygame.K_b: breadthFirstSearch, } start_node = None end_node = None while True: for event in pygame.event.get(): if event.type == pygame.QUIT: gui.close() if pygame.mouse.get_pressed()[0]: # LEFT MOUSE BUTTON mouse_xy = pygame.mouse.get_pos() start_node, end_node = gui.setNodeColor( mouse_xy, start_node, end_node) if pygame.mouse.get_pressed()[2]: # RIGHT MOUSE BUTTON mouse_xy = pygame.mouse.get_pos() start_node, end_node = gui.resetNodeColor( mouse_xy, start_node, end_node) if event.type == pygame.KEYDOWN: # Look for the keys that triggers an algorithm initialization if event.key in search_mapping.keys(): if start_node and end_node: gui.updateNodeNeighbors() gui.reset( exeptions=["wall", "start point", "end point"]) search = search_mapping[event.key] gui.fps = path_finding_fps search(gui, start_node, end_node) gui.fps = gui_fps # Look for the keys that resets all blocks if event.key == pygame.K_SPACE: start_node, end_node = None, None gui.reset() # Look for the keys that resets all blocks except the maze configuration if event.key == pygame.K_c: gui.reset(exeptions=["wall", "start point", "end point"]) gui.updateContents()
class App(QApplication): def __init__(self): QApplication.__init__(self, sys.argv) # Establish loop as Quamash Event Loop loop = QEventLoop(self) self.loop = loop asyncio.set_event_loop(loop) self.idle = False self.trayIcon = None self.themes = themes self.options = Options try: self.theme = themes[self.options["theme"]["theme"]] except KeyError: self.theme = themes["Pesterchum 2.5"] self.theme_name = self.theme["name"] self.moods = Moods self.emojis = Emojis self.mentions = Mentions self.setStyleSheet(self.theme["styles"]) self.nick = None self.client = DiscordClient(app=self, loop=self.loop) self.user, self.passwd, self.token, self.botAccount = UserAuth if not UserAuth[0] and not UserAuth[1] and not UserAuth[2]: self.openAuth(i=True) save_auth(( self.user, self.passwd, self.token, self.botAccount, )) asyncio.ensure_future(self.connecting()) asyncio.ensure_future(self.runbot()) self.gui = Gui(self.loop, self) loop.run_forever() def cli(self): """ Runs a REPL style loop, if eval(input) is awaitable (`inspect.isawaitable`) will await, runs in an executor """ asyncio.ensure_future(self.run_exe()) async def run_exe(self): while True: try: with QThreadExecutor(1) as exec: line = await self.loop.run_in_executor(exec, input, ">>> ") evl = eval(line) if isawaitable(evl): r = await evl print(r) else: print(evl) except Exception as e: print(e) async def connecting(self): self.connectingDialog = ConnectingDialog(self, self) self.connectingDialog.exec_() async def on_message(self, message): """Called on `Client.on_message`, Message handling happens here""" if message.content.startswith("_") and message.content.endswith("_"): message.content = "/me " + message.content[1:-1] if isinstance(message.channel, discord.PrivateChannel): if not message.channel.name: message.channel.name = ",".join( map(lambda m: m.display_name, message.channel.recipients)) if message.channel.type is discord.ChannelType.group: tab = self.gui.start_privmsg(message.channel) else: tab = self.gui.start_privmsg(message.channel) fmt = fmt_disp_msg(self, message.content, message, user=message.author) if fmt: tab.display_text(fmt) else: if self.gui.memosWindow: if message.server in self.gui.memosWindow.open.keys(): fmt = fmt_disp_msg(self, message.content, message, user=message.author) if fmt: try: self.gui.memosWindow.display_message( message.channel, fmt) except AttributeError as e: print(e) async def on_ready(self): """Called on `Client.on_ready`, generally once the client is logged in and ready""" self.connectingDialog.close() self.nick = self.client.user.name self.quirks = Quirks(self) if "debug" in sys.argv: self.cli() playsound(os.path.join(self.theme["path"], "alarm.wav"), block=False) self.gui.initialize() def change_mood(self, mood): if mood == "offline" or mood == "abscond": asyncio.ensure_future( self.client.change_presence(status=discord.Status.invisible)) else: asyncio.ensure_future( self.client.change_presence( game=discord.Game(name="Feeling {}".format(mood.upper())), status=discord.Status.online)) if self.idle: self.gui.toggleIdle() def change_theme(self, theme, f=False): if f: self.refresh_themes() if theme != self.theme_name or f: self.theme = themes[theme] self.theme_name = self.theme["name"] self.setStyleSheet(self.theme["styles"]) if hasattr(self, "gui"): self.gui.close() self.gui = Gui(self.loop, self) self.gui.initialize() def refresh_themes(self): self.themes = getThemes(dict()) @staticmethod def getColor(member, type=str): """Get the given primary role color for a `Member`, returns a `Discord.Color` instance""" try: clr = member.color except AttributeError: clr = discord.Color.default() if type is str: return "rgb({clr.r},{clr.g},{clr.b})".format(clr=clr) elif type is QColor: return QColor(clr.r, clr.g, clr.b) def send_msg(self, message, channel): """Send message `message` to the User, Private Channel, or Channel `channel`""" message = message.strip() tts = False if message.startswith("/me"): message = "_" + message[3:] + "_" if message.startswith("/tts "): message = message[4:] tts = True if message.startswith("/ooc"): message = "((" + message[4:] + "))" message = self.quirks.process_quirks(message) asyncio.ensure_future( self.client.send_message(channel, message, tts=tts)) def openAuth(self, f=False, i=True): auth = AuthDialog(self, self, f=f, i=i).auth self.user, self.passwd, self.token, self.botAccount = auth if hasattr(self, "gui") and auth and not f: self.exit() async def runbot(self): try: if (self.user and self.passwd) and not self.token: await self.client.start(self.user, self.passwd, bot=False) elif self.token and not (self.user or self.passwd): await self.client.start(self.token, bot=self.botAccount) except discord.LoginFailure: self.openAuth(f=True) save_auth(( self.user, self.passwd, self.token, self.botAccount, )) finally: await self.runbot() def exit(self, code=0): """ Called when exiting the client Save configurations and sys.exit """ try: save_auth(( self.user, self.passwd, self.token, self.botAccount, )) save_options(self.options) self.quirks.save_quirks() except: pass finally: sys.exit(code) def lastWindowClosed(self): self.exit()
def aStar(gui: Gui, start: Node, end: Node) -> bool: """Runs A* algorithm One important aspect of A* is f = g + h Where: f is the total cost of the node. g is the distance between the current node and the start node. h is the heuristic - estimated distance from the current node to the end node. This algorithm expoits the node with the lowest f and its neighbors. Reference = [https://medium.com/@nicholas.w.swift/easy-a-star-pathfinding-7e6689c7f7b2] Code adapted from = [https://morioh.com/p/cf0c6b11c848?f=5c21fb01c16e2556b555ab32] Parameters ---------- nodes : list A list of nodes present in the grid start : Node The starting point end : Node The ending point Returns ------- bool True if the ending node was reached, else False """ def h(node1: Node, node2: Node): return abs(node1.row - node2.row) + abs(node1.col - node2.col) def buildReversePath(came_from: dict, current: Node): while current in came_from: current = came_from[current] current.setState("path") gui.updateContents() g = 0 open_set = PriorityQueue( ) # tip: A structure that it's always sorted (first f then h...). Method get() gets the first element (lowest f). open_set.put((0, g, start)) came_from = {} g_score = {node: float("inf") for node in gui.grid} g_score[start] = 0 f_score = {node: float("inf") for node in gui.grid} f_score[start] = h(start, end) open_set_hash = {start} while not open_set.empty(): for event in pygame.event.get(): if event.type == pygame.QUIT: gui.close() *_, current = open_set.get() open_set_hash.remove(current) if current == end: buildReversePath(came_from, end) end.setState("end point") start.setState("start point") return True for neighbor in current.neighbors: temp_g_score = g_score[current] + 1 if temp_g_score < g_score[neighbor]: came_from[neighbor] = current g_score[neighbor] = temp_g_score f_score[neighbor] = temp_g_score + h(neighbor, end) if neighbor not in open_set_hash: g += 1 open_set.put((f_score[neighbor], g, neighbor)) open_set_hash.add(neighbor) neighbor.setState("watch") gui.updateContents() if current != start: current.setState("visited") gui.updateContents() return False