home · contact · privacy
Return cookie chars sorted.
[plomrogue2] / plomrogue / things.py
index 072f2513ce9a11a56e86c92828cbfde3cb1f594b..4cc3512cf82cc952f85e80ae9c35d00cd04538c5 100644 (file)
@@ -1,5 +1,5 @@
 from plomrogue.errors import GameError, PlayError
-from plomrogue.mapping import YX
+from plomrogue.mapping import YX, FovMap
 from plomrogue.misc import quote
 import random
 
@@ -48,7 +48,6 @@ class Thing(ThingBase):
 
         def lower_msg_by_volume(msg, volume, largest_audible_distance,
                                 url_limits = []):
-            import random
             factor = largest_audible_distance / 4
             lowered_msg = ''
             in_url = False
@@ -71,10 +70,11 @@ class Thing(ThingBase):
 
         largest_audible_distance = 20
         obstacles = [t.position for t in self.game.things if t.blocks_sound]
+        targets = [t.position for t in self.game.things if t.type_ == 'Player']
         sound_blockers = self.game.get_sound_blockers()
-        dijkstra_map = DijkstraMap(sound_blockers, obstacles, self.game.maps,
-                                   self.position, largest_audible_distance,
-                                   self.game.get_map)
+        dijkstra_map = DijkstraMap(targets, sound_blockers, obstacles,
+                                   self.game.maps, self.position,
+                                   largest_audible_distance, self.game.get_map)
         url_limits = []
         for m in re.finditer('https?://[^\s]+', msg):
             url_limits += [m.start(), m.end()]
@@ -93,7 +93,17 @@ class Thing(ThingBase):
             lowered_nick = lower_msg_by_volume(name, volume,
                                                largest_audible_distance)
             symbol = ''
-            if listener.fov_test(self.position[0], self.position[1]):
+            # if listener.fov_test(self.position[0], self.position[1]):
+            # TODO: We might want to only show chat faces of players that are
+            # in the listener's FOV.  However, if we do a fov_test here,
+            # this might set up a listener._fov where previously there was None,
+            # with ._fov = None serving to Game.send_gamestate() as an indicator
+            # that map view data for listener might be subject to change and
+            # therefore needs to be re-sent.  If we generate an un-set ._fov
+            # here, this inhibits send_gamestate() from sending new map view
+            # data to listener.  We need to re-structure this whole process
+            # if we want to use a FOV test on listener here.
+            if listener_distance < largest_audible_distance / 2:
                 self.game.io.send('CHATFACE %s' % self.id_, c_id)
                 if self.type_ == 'Player' and hasattr(self, 'thing_char'):
                     symbol = '/@' + self.thing_char
@@ -139,16 +149,26 @@ class Thing_SpawnPoint(Thing):
 
 
 
+class ThingInstallable(Thing):
+    portable = True
+    installable = True
+
+    def install(self):
+        self.portable = False
+
+    def uninstall(self):
+        self.portable = True
+
+
+
 class Thing_DoorSpawner(ThingSpawner):
     child_type = 'Door'
 
 
 
-class Thing_Door(Thing):
+class Thing_Door(ThingInstallable):
     symbol_hint = 'D'
     blocks_movement = False
-    portable = True
-    installable = True
 
     def open(self):
         self.blocks_movement = False
@@ -162,12 +182,6 @@ class Thing_Door(Thing):
         self.blocks_sound = True
         self.thing_char = '#'
 
-    def install(self):
-        self.portable = False
-
-    def uninstall(self):
-        self.portable = True
-
 
 
 class Thing_Psychedelic(Thing):
@@ -194,16 +208,14 @@ class Thing_Bottle(Thing):
         self.full = False
 
     def spin(self):
-        import random
         all_players = [t for t in self.game.things if t.type_ == 'Player']
         # TODO: refactor with ThingPlayer.prepare_multiprocessible_fov_stencil
         # and ThingPlayer.fov_test
-        fov_map_class = self.game.map_geometry.fov_map_class
         fov_radius = 12
         light_blockers = self.game.get_light_blockers()
         obstacles = [t.position for t in self.game.things if t.blocks_light]
-        fov = fov_map_class(light_blockers, obstacles, self.game.maps,
-                            self.position, fov_radius, self.game.get_map)
+        fov = FovMap(light_blockers, obstacles, self.game.maps,
+                     self.position, fov_radius, self.game.get_map)
         fov.init_terrain()
         visible_players = []
         for p in all_players:
@@ -422,8 +434,6 @@ class Thing_CookieSpawner(Thing):
 
 class ThingAnimate(Thing):
     blocks_movement = True
-    drunk = 0
-    tripping = 0
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
@@ -470,12 +480,11 @@ class ThingAnimate(Thing):
             self.task = self.get_next_task()
 
     def prepare_multiprocessible_fov_stencil(self):
-        fov_map_class = self.game.map_geometry.fov_map_class
         fov_radius = 3 if self.drunk > 0 else 12
         light_blockers = self.game.get_light_blockers()
         obstacles = [t.position for t in self.game.things if t.blocks_light]
-        self._fov = fov_map_class(light_blockers, obstacles, self.game.maps,
-                                  self.position, fov_radius, self.game.get_map)
+        self._fov = FovMap(light_blockers, obstacles, self.game.maps,
+                           self.position, fov_radius, self.game.get_map)
 
     def multiprocessible_fov_stencil(self):
         self._fov.init_terrain()
@@ -490,9 +499,6 @@ class ThingAnimate(Thing):
         self.multiprocessible_fov_stencil()
         return self._fov
 
-    def fov_stencil_make(self):
-        self._fov.make()
-
     def fov_test(self, big_yx, little_yx):
         test_position = self.fov_stencil.target_yx(big_yx, little_yx)
         if self.fov_stencil.inside(test_position):
@@ -561,6 +567,10 @@ class ThingAnimate(Thing):
 
 class Thing_Player(ThingAnimate):
     symbol_hint = '@'
+    drunk = 0
+    tripping = 0
+    need_for_toilet = 0
+    standing = True
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
@@ -568,12 +578,27 @@ class Thing_Player(ThingAnimate):
 
     def proceed(self):
         super().proceed()
-        self.drunk -= 1
+        if self.drunk >= 0:
+            self.drunk -= 1
+        if self.tripping >= 0:
+            self.tripping -= 1
+        if self.need_for_toilet > 0:
+            self.need_for_toilet += 1
+            terrain = self.game.maps[self.position[0]][self.position[1]]
+            if terrain in self.game.terrains:
+                terrain_type = self.game.terrains[terrain]
+                if 'toilet' in terrain_type.tags:
+                    self.send_msg('CHAT "You use the toilet. What a relief!"')
+                    self.need_for_toilet = 0
+            if 10000 * random.random() < self.need_for_toilet / 100000:
+                self.send_msg('CHAT "You need to go to a toilet."')
+            if self.need_for_toilet > 1000000:
+                self.send_msg('CHAT "You pee into your pants. Eww!"')
+                self.need_for_toilet = 0
         if self.drunk == 0:
             self.send_msg('CHAT "You sober up."')
             self.invalidate('fov')
             self.game.changed = True
-        self.tripping -= 1
         if self.tripping == 0:
             self.send_msg('DEFAULT_COLORS')
             self.send_msg('CHAT "You sober up."')
@@ -601,6 +626,9 @@ class Thing_Player(ThingAnimate):
             self.game.players_hat_chars[self.name] += c
 
     def get_cookie_chars(self):
+        chars = ' #'  # default
         if self.name in self.game.players_hat_chars:
-            return self.game.players_hat_chars[self.name]
-        return ' #'  # default
+            chars = self.game.players_hat_chars[self.name]
+        chars_split = list(chars)
+        chars_split.sort()
+        return ''.join(chars_split)