def _recursive_wire_replace(self, old_wire_coords, new_wire): """Recursively flood through a wire and replace it with a new wire. TODO: How does caching fit into this? Returns : set Set of all the SimNodes which will need to have their IO updated. """ # Replace the current wire self.set_basic(old_wire_coords, new_wire) dirty_simnodes = {} # In the list of all wire neighbours which aren't the new wire... for nd in util.neighbour_deltas(): nc = util.add(old_wire_coords, nd) _, nc, n = self.into(nc, nd) if isinstance(n, Wire) and n != new_wire: # Replace them, too! dirty_simnodes.update( self._recursive_wire_replace(nc, new_wire)) elif n is not None: dirty_simnodes[nc] = n return dirty_simnodes
def editor_loop(self): while True: # Just render the first board for now self.render(self.world.boards[0]) # Get input inp = self.t.inkey() logger.debug('Key Input: ' + repr(inp)) ui_event = self.key_to_event(inp) if ui_event is None: continue move_delta = ui_event.get('move') quit = ui_event.get('quit') write_board = ui_event.get('write_board') if move_delta: new_pos = util.add(self.cursor_pos, move_delta) if min(new_pos) >= 0: self.cursor_pos = new_pos elif quit: return elif write_board: index = write_board['index'] self.write_board_to_disk(self.world.boards[index], write_board['filepath']) else: # Pass it along to the world message queue self.world.submit(ui_event) self.world.process_queue()
def get(self, q_board, my_coords, q_coord_delta): new_coords = util.add(my_coords, q_coord_delta) new_node = q_board.get(new_coords) try: return new_node.get(q_board, new_coords, q_coord_delta) except AttributeError: return (q_board, my_coords, None)
def _surround_bridge_with_wires(self): # Place wire around the bridge new_wires = [util.add(self.bridge_coords, nc) for nc in util.neighbour_deltas()] for w in new_wires: self.board.set(w, Wire()) self.board.tick()
def neighbour_objs_into(self, coords): """Returns the neighbouring nodes through portals (No `None`s)""" n_objs = [] for nd in util.neighbour_deltas(): nc = util.add(coords, nd) _, nc, n = self.into(nc, nd) if n is not None: n_objs.append(n) return n_objs
def _grid_local_wire_break(self, coords, broken_wire: Wire): """Break a wire into multiple bits if required Parameters ---------- coords : (x, y) Coordinates of where the wire group was broken. broken_wire : Wire The wire object which was broken. """ current_obj = self.get(coords) assert (not isinstance(current_obj, Wire)) # Note: This can work even if there are no wires... Just marks all the # neighbours as dirty. new_wires = set() dirty_simnodes = {} # coord -> obj for nd in util.neighbour_deltas(): nc = util.add(coords, nd) # Use coords to avoid mutating what we are iterating over _, nc, n = self.into(nc, nd) if n is broken_wire: new_wire = Wire() dirty_simnodes.update( self._recursive_wire_replace(nc, new_wire)) # Update this later - Can't do here because we need to wait for # dirty simnodes to refresh new_wires.add(new_wire) elif n is not None: dirty_simnodes[nc] = n # Update IO for all dirty_simnodes for coord, n in dirty_simnodes.items(): n.recalculate_io(coord, self) # Make sure the new wires immediately show the correct value for wire in new_wires: wire.calculate_next_output() wire.tick()
def recalculate_io(self, my_coord, board): # Reset inputs as empty, then slowly repopulate self.inputs = set() # Need to keep track of outputs so we don't immediately remove # ourselves again if many neighbour tiles are the same input AND # output object (eg, in the case of a simple 1-tick nand clock) outputs = set() deltas = util.neighbour_deltas() for i, delta in enumerate(deltas): nc = util.add(delta, my_coord) _, nc, n = board.into(nc, delta) if n is not None: if i == self.facing: n.input_add(self, util.invert(delta)) outputs.add(n) else: if n not in outputs: n.input_remove(self) if n.outputs_to(util.invert(delta)): self.inputs.add(n)