def consume(self, consumer): if not consumer.inventory.find("lighter"): if consumer is _G.player: say.insayne(f"You have no way to light the {self.name}.") return consumer.inventory.remove(self) cigarette_butt = CigaretteButt.create() consumer.inventory.add(cigarette_butt) consumer.current_room.items.add(Smoke.create(consumer.current_room)) if consumer is _G.player: say.insayne( f"You take a furtive puff on the {self.name}. It tastes foul " "and acrid. You do not feel like you are wearing a leather " "jacket at all.") consumer.psyche.heal_or_harm(dice.roll("1d2")) # TODO: Make insanity a variable statistic? consumer.insanity.heal_or_harm(-dice.roll("1d2")) # TODO: Interesting problem with how this is implemented: # because text is not queued but printed directly, if this line # precedes anything else in this function and player dies, # weird stuff will ensue. consumer.health.heal_or_harm(-dice.roll("2d2"), cause="smoking half a cig") else: name = say.capitalized(consumer.name) say.insayne(f"{name} puffs furtively on a {self.name}.")
def consume(self, consumer): if not consumer.inventory.find("lighter"): if consumer is _G.player: say.insayne(f"You have no way to light the {self.name}.") return # TODO: Buff strength for a little bit. # TODO: Heal insanity, restore psyche. # TODO: I don't like this solution as it presumes the item is in the # consumer's inventory. Maybe that is a fine assumption. If not, # consider storing the inventory relationship as two-way. consumer.inventory.remove(self) cigarette_stub = CigaretteStub.create() consumer.inventory.add(cigarette_stub) consumer.current_room.items.add(Smoke.create(consumer.current_room)) # TODO: Customize text based on whether consumer is player. # TODO: Add location to actors so that the state of onlookers can # be properly assessed. aliases = random.sample(self.aliases, 2) if consumer is _G.player: say.insayne( f"You take a long, smooth drag on the {aliases[0]}. Time seems " "to mellow; all activity nearby slows. Onlookers watch as you " "draw measured, pensive little puffs from the delicious " f"{aliases[1]}. You look very cool.") consumer.health.heal_or_harm(-dice.roll("1d2"), cause="being cool") consumer.psyche.heal_or_harm(dice.roll("2d2")) # TODO: Make insanity a variable statistic? consumer.insanity.heal_or_harm(-dice.roll("2d2")) else: name = say.capitalized(consumer.name) say.insayne( f"{name} puffs mellowly on a {self.name}, looking extremely fly." )
def _resolve_attack(attacker, attack): # TODO: Add equipment, different damage dice, etc. # TODO: Respect attack.method. defender = attack.target is_player = attacker is G.player if is_player: subj, obj = ["you", defender.name] else: subj, obj = [attacker.name, "you"] subj = say.capitalized(subj) miss = "miss" if is_player else "misses" hit = "hit" if is_player else "hits" strength_mod = int((attacker.strength.value - 10) / 2) to_hit = strength_mod + dice.roll("1d20") if to_hit < (10 + (defender.stamina.value - 10) / 2): say.insayne(f"{subj} {miss}.") else: damage = dice.roll("1d8") + strength_mod # TODO: How to organize messages better? Death also creates text, so # there should be a way to make sure the messages are ordered. say.insayne(f"{subj} {hit} {obj} for {damage} damage!") # TODO: Attack should have associated text which is consulted here. defender.health.heal_or_harm( -1 * damage, cause=f"the fins of {say.a(attacker.name)}") if not (is_player or defender.alive): G.just_died = True
def execute(self): self._timer += 1 if self._timer % 3 != 0: return roll = dice.roll("1d10") if roll <= 4: return cig = items.Cigarette.create() self.owner.inventory.add(cig) cig.consume(self.owner)
def test_roll_range(self): possible_values = set(range(1, 11)) for _ in range(100): self.assertIn(dice.roll("d10"), possible_values)
def test_roll_parses_expression(self): with patch("random.randint", new_callable=_MockRandom): self.assertEqual(4, dice.roll("d3")) self.assertEqual(3, dice.roll("1d2")) self.assertEqual(4, dice.roll("2d1"))
def execute(self): if self._counter % 3 == 0: say.insayne("The heat is too much for you.") G.player.health.heal_or_harm(-1 * dice.roll("1d2"), cause="sweating in the boiler room") self._counter += 1
def execute(self): if dice.roll("1d100") > 90: say.insayne("A drop of acid falls on your head.") G.player.health.heal_or_harm(-1 * dice.roll("1d2"), cause="being scalded with acid")
def generate(cls, theme, number_rooms=None): if theme == "office": return _generate_office() room_dict = {} room_list = rooms.get_rooms(number=number_rooms, theme=theme) start_coordinate = _Coordinate(10, 10) coordinate_queue = collections.deque() coordinate_queue.append(start_coordinate) for room in room_list: if not coordinate_queue: break if len(room_dict) >= number_rooms: break # Finds an unoccupied coordinate. while True: coordinate = coordinate_queue.popleft() if room_dict.get(coordinate) is None: break # Creates a new room in that location. room_dict[coordinate] = room for direction in ["north", "south", "east", "west"]: new_coordinate = getattr(coordinate, direction) next_room = room_dict.get(new_coordinate) if next_room is None: coordinate_queue.append(new_coordinate) else: # Adds some exits. if dice.roll("1d100") > 50: _add_exit(room, next_room, direction) # Traverse room graph. If any rooms are not connected, use a # non-Euclidean entrance to address that. # TODO: pop() isn't really random!! Does that matter? all_rooms = set(room_dict.values()) traversed_rooms = set() last_cohort = set() while all_rooms: next_room = all_rooms.pop() if last_cohort: logging.debug("adding a weird transition") next_room.add_exit(directions.purple, traversed_rooms.pop()) last_cohort.clear() traversed_rooms.add(next_room) last_cohort.add(next_room) traversal_queue = collections.deque() traversal_queue.append(next_room) while traversal_queue: next_room = traversal_queue.popleft() actual_room = next_room for exit in actual_room.exits: destination, _ = actual_room.exit(exit) destination_number = destination if destination_number in all_rooms: all_rooms.remove(destination_number) traversed_rooms.add(destination_number) last_cohort.add(destination_number) traversal_queue.append(destination_number) return Floor(room_dict)