def test_legend_from_degrees(self): self.assertEqual("North", Compass.legend(0)) self.assertEqual("South", Compass.legend(180)) self.assertEqual("East", Compass.legend(90)) self.assertEqual("West", Compass.legend(270)) self.assertEqual("NorthWest", Compass.legend(Decimal("292.6"))) self.assertEqual("NorthWest", Compass.legend(315)) self.assertEqual("NorthWest", Compass.legend(Decimal("337.5"))) self.assertEqual("North", Compass.legend(Decimal("337.6"))) self.assertEqual("North", Compass.legend(360))
def route(self, locn, dest, maxlen, visited=None): if (locn, dest) in self._cache: return self._cache[(locn, dest)] visited = set([]) if visited is None else set(visited) if locn == dest: return deque([], maxlen=maxlen) bearing = Compass.bearing( dest.get_state(Spot).value - locn.get_state(Spot).value) moves = self.navigate(locn) options = sorted(((abs(k - bearing), v) for k, v in moves.items() if v not in visited), key=operator.itemgetter(0)) while options: deviation, hop = options.pop(0) visited.add(hop) try: rv = deque(self.route(hop, dest, maxlen, frozenset(visited))) if hop in rv: continue else: self._cache[(hop, dest)] = tuple(rv) rv.appendleft(hop) except TypeError: continue if len(rv) == maxlen: return None return rv else: return None
def test_legend_from_complex(self): self.assertEqual("North", Compass.legend(complex(0, 1))) self.assertEqual("NorthEast", Compass.legend(complex(1, 1))) self.assertEqual("East", Compass.legend(complex(1, 0))) self.assertEqual("SouthEast", Compass.legend(complex(1, -1))) self.assertEqual("South", Compass.legend(complex(0, -1))) self.assertEqual("SouthWest", Compass.legend(complex(-1, -1))) self.assertEqual("West", Compass.legend(complex(-1, 0))) self.assertEqual("NorthWest", Compass.legend(complex(-1, 1)))
def test_bearing_from_complex(self): self.assertEqual(Decimal(360), Compass.bearing(complex(0, 1))) self.assertEqual(Decimal(45), Compass.bearing(complex(1, 1))) self.assertEqual(Decimal(90), Compass.bearing(complex(1, 0))) self.assertEqual(Decimal(135), Compass.bearing(complex(1, -1))) self.assertEqual(Decimal(180), Compass.bearing(complex(0, -1))) self.assertEqual(Decimal(225), Compass.bearing(complex(-1, -1))) self.assertEqual(Decimal(270), Compass.bearing(complex(-1, 0))) self.assertEqual(Decimal(315), Compass.bearing(complex(-1, 1)))
def moves(session, spot=None): """Return the location and available moves from a spot.""" spot = spot or Game.spot(session) locn = next(i for i in session.finder.lookup if isinstance(i, Location) and i.get_state(Spot) == spot) moves = [(Compass.legend(k), v) for k, v in session.finder.navigate(locn).items()] return locn, moves
def navigate(self, locn): spot = locn.get_state(Spot) neighbours = self.match(locn, forward=[Via.bidir, Via.forwd], reverse=[Via.bidir, Via.bckwd], predicate=lambda x: isinstance(x, Location)) return OrderedDict([ (Compass.bearing(i.get_state(Spot).value - spot.value), i) for i in neighbours ])
async def __call__(self, session, loop=None): log = logging.getLogger( "{0!s}.{1}".format(session.uid, self.__class__.__name__) ) if not hasattr(self.actor, "_lock"): self.actor._lock = asyncio.Lock(loop=loop) while True: try: await self.actor._lock.acquire() if self.actions: move = self.actions.popleft() move.entity.set_state(move.hop.get_state(Spot)) log.info("{0} goes {1} to {2.label}".format( "{0.actor.name.firstname} {0.actor.name.surname}".format(self) if move.entity is self.actor else move.entity.label, Compass.legend(move.vector), move.hop )) else: player = session.cache.get("player", self.actor) log.debug( "{0.actor.name.firstname} {0.actor.name.surname} tracks {1.name.firstname}".format( self, player ) ) location = self.visit( session.finder, self.locate(session.finder, player), self.options ) log.info( "{0.actor.name.firstname} {0.actor.name.surname} chooses {1.label}".format( self, location ) ) self.actions.extend(self.moves(session.finder, self.actor, location)) await Clock.next_event() finally: self.actor._lock.release()
async def __call__(self, finder, loop=None): for i in self.claim_resources(finder): self.log.info("{0} claimed by {1._name}".format(i, self.actor)) while True: try: await self.actor._lock.acquire() op = self.operations[0] if isinstance(op, Delivering): actions = self.deliver(finder, op) for act in actions: if isinstance(act, Move): act.entity.set_state(act.hop.get_state(Spot)) self.log.info("{0} goes {1} to {2.label}".format( "{0.actor.name.firstname} {0.actor.name.surname}". format(self) if act.entity is self.actor else act.entity.label, Compass.legend(act.vector), act.hop)) elif isinstance(act, Transfer): if act.quantity: act.source.contents[act.commodity] -= act.quantity act.destination.contents[ act.commodity] += act.quantity self.log.info( "{0.label} takes {1:0.3f} Kg {2.label}".format( act.destination, act.commodity.material.value * act.quantity, act.commodity)) op.memory.append(act.destination.contents.copy()) await asyncio.sleep(0.1, loop=loop) finally: self.actor._lock.release() self.operations.rotate(-1)