home · contact · privacy
Add thing protection.
authorChristian Heller <c.heller@plomlompom.de>
Fri, 27 Nov 2020 00:21:03 +0000 (01:21 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Fri, 27 Nov 2020 00:21:03 +0000 (01:21 +0100)
config.json
plomrogue/commands.py
plomrogue/game.py
plomrogue/things.py
rogue_chat.html
rogue_chat.py
rogue_chat_curses.py

index 406f461881ce77767a55852d876c5ec8612df8da..15022fea7abc533d98c1e98add2e43b675cc13ad 100644 (file)
@@ -11,6 +11,7 @@
     "switch_to_admin": "A",
     "switch_to_control_pw_pw": "C",
     "switch_to_control_tile_type": "Q",
+    "switch_to_admin_thing_protect": "T",
     "flatten": "F",
     "take_thing": "z",
     "drop_thing": "u",
index a2f98ed1bf989d3195096cf84456815e7da8fc0d..3a10a4c24e182aa6b72dd6a41ac575bcb2664d0e 100644 (file)
@@ -118,6 +118,19 @@ def cmd_SET_TILE_CONTROL(game, yx, control_char, connection_id):
     game.changed = True
 cmd_SET_TILE_CONTROL.argtypes = 'yx_tuple:nonneg char'
 
+def cmd_THING_PROTECTION(game, thing_id, protection_char, connection_id):
+    player = game.get_player(connection_id)
+    if not player:
+        raise GameError('need to be logged in for this')
+    if not game.sessions[connection_id]['status'] == 'admin':
+        raise GameError('need to be admin for this')
+    t = game.get_thing(thing_id)
+    if not t:
+        raise GameError('thing of ID %s not found' % thing_id)
+    t.protection = protection_char
+    game.changed = True
+cmd_THING_PROTECTION.argtypes = 'int:pos char'
+
 def cmd_SET_MAP_CONTROL_PASSWORD(game, tile_class, password, connection_id):
     player = game.get_player(connection_id)
     if not player:
@@ -269,13 +282,16 @@ def cmd_THING(game, big_yx, little_yx, thing_type, thing_id):
     game.changed = True
 cmd_THING.argtypes = 'yx_tuple yx_tuple:nonneg string:thing_type int:nonneg'
 
-def cmd_THING_NAME(game, thing_id, name, connection_id):
+def cmd_THING_NAME(game, thing_id, name, pw, connection_id):
+    # TODO check if thing in FOV
     t = game.get_thing(thing_id)
     if not t:
         raise GameError('thing of ID %s not found' % thing_id)
+    if not game.can_do_thing_with_pw(t, pw):
+        raise GameError('wrong password for tile')
     t.name = name
     game.changed = True
-cmd_THING_NAME.argtypes = 'int:pos string'
+cmd_THING_NAME.argtypes = 'int:pos string string'
 
 def cmd_GOD_THING_NAME(game, thing_id, name):
     t = game.get_thing(thing_id)
@@ -283,3 +299,10 @@ def cmd_GOD_THING_NAME(game, thing_id, name):
         raise GameError('thing of ID %s not found' % thing_id)
     t.name = name
 cmd_GOD_THING_NAME.argtypes = 'int:pos string'
+
+def cmd_GOD_THING_PROTECTION(game, thing_id, protection_char):
+    t = game.get_thing(thing_id)
+    if not t:
+        raise GameError('thing of ID %s not found' % thing_id)
+    t.protection = protection_char
+cmd_GOD_THING_PROTECTION.argtypes = 'int:pos char'
index 49fdeeb007e73364baa41af166a7c7bf39f35464..f504599f59e4146adcc96a2645c9b48583f8e672 100755 (executable)
@@ -159,6 +159,12 @@ class Game(GameBase):
                 print("FILE INPUT LINE %5s: %s" % (i, line), end='')
                 self.io.handle_input(line, god_mode=True)
 
+    def can_do_thing_with_pw(self, thing, pw):
+        if thing.protection in self.map_control_passwords.keys():
+            if pw != self.map_control_passwords[thing.protection]:
+                return False
+        return True
+
     def can_do_tile_with_pw(self, big_yx, little_yx, pw):
         map_control = self.get_map(big_yx, 'control')
         tile_class = map_control[little_yx]
@@ -204,7 +210,8 @@ class Game(GameBase):
             self.io.send('MAP_CONTROL %s' % quote(visible_control), c_id)
             for t in [t for t in self.things if player.fov_test(*t.position)]:
                 target_yx = player.fov_stencil.target_yx(*t.position)
-                self.io.send('THING %s %s %s' % (target_yx, t.type_, t.id_), c_id)
+                self.io.send('THING %s %s %s %s' % (target_yx, t.type_,
+                                                    quote(t.protection), t.id_), c_id)
                 if hasattr(t, 'name'):
                     self.io.send('THING_NAME %s %s' % (t.id_, quote(t.name)), c_id)
                 if hasattr(t, 'player_char'):
@@ -333,6 +340,7 @@ class Game(GameBase):
             for t in [t for t in self.things if not t.type_ == 'Player']:
                 write(f, 'THING %s %s %s %s' % (t.position[0],
                                                 t.position[1], t.type_, t.id_))
+                write(f, 'GOD_THING_PROTECTION %s %s' % (t.id_, quote(t.protection)))
                 if hasattr(t, 'name'):
                     write(f, 'GOD_THING_NAME %s %s' % (t.id_, quote(t.name)))
             write(f, 'SPAWN_POINT %s %s' % (self.spawn_point[0],
index 0edf8fbed42a83363ad43d0012a4a1f74cd37685..1618ee65e49c07493fc2cc67f87a22045f4b998c 100644 (file)
@@ -18,6 +18,7 @@ class ThingBase:
 
 class Thing(ThingBase):
     blocking = False
+    protection = '.'
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
index d2136df8a6dd3517eff99e0b7fb210be99bc0c30..15b715a4f0e686108bfdf0923ee8b4b19b558162 100644 (file)
@@ -72,6 +72,7 @@ keyboard input/control: <span id="keyboard_control"></span>
     <td>
       <button id="switch_to_control_pw_type">change protection character password</button>
       <button id="switch_to_control_tile_type">change protection areas</button>
+      <button id="switch_to_admin_thing_protect">change thing protection</button>
       <button id="toggle_tile_draw">toggle protection character drawing</button>
     </td>
   <tr>
@@ -104,6 +105,7 @@ keyboard input/control: <span id="keyboard_control"></span>
 <li><input id="key_switch_to_admin_enter" type="text" value="A" />
 <li><input id="key_switch_to_control_pw_type" type="text" value="C" />
 <li><input id="key_switch_to_control_tile_type" type="text" value="Q" />
+<li><input id="key_switch_to_admin_thing_protect" type="text" value="T" />
 <li><input id="key_switch_to_annotate" type="text" value="M" />
 <li><input id="key_switch_to_portal" type="text" value="T" />
 <li>toggle map view: <input id="key_toggle_map_mode" type="text" value="L" />
@@ -131,6 +133,10 @@ let mode_helps = {
         'short': 'name thing',
         'long': 'Give name to/change name of thing here.'
     },
+    'admin_thing_protect': {
+        'short': 'change thing protection',
+        'long': 'Change protection character for thing here.'
+    },
     'write': {
         'short': 'change terrain',
         'long': 'This mode allows you to change the map tile you currently stand on (if your map editing password authorizes you so).  Just enter any printable ASCII character to imprint it on the ground below you.'
@@ -386,9 +392,10 @@ let server = {
             game.portals = {};
             game.turn = parseInt(tokens[1]);
         } else if (tokens[0] === 'THING') {
-            let t = game.get_thing(tokens[3], true);
+            let t = game.get_thing(tokens[4], true);
             t.position = parser.parse_yx(tokens[1]);
             t.type_ = tokens[2];
+            t.protection = tokens[3];
         } else if (tokens[0] === 'THING_NAME') {
             let t = game.get_thing(tokens[1], false);
             if (t) {
@@ -554,6 +561,7 @@ let tui = {
   mode_write: new Mode('write', false, false, false, true),
   mode_edit: new Mode('edit'),
   mode_control_pw_type: new Mode('control_pw_type', true),
+  mode_admin_thing_protect: new Mode('admin_thing_protect', true),
   mode_portal: new Mode('portal', true, true),
   mode_password: new Mode('password', true),
   mode_name_thing: new Mode('name_thing', true, true),
@@ -565,7 +573,7 @@ let tui = {
   init: function() {
       this.mode_play.available_modes = ["chat", "study", "edit", "admin_enter"]
       this.mode_study.available_modes = ["chat", "play", "admin_enter", "edit"]
-      this.mode_admin.available_modes = ["control_pw_type",
+      this.mode_admin.available_modes = ["admin_thing_protect", "control_pw_type",
                                          "control_tile_type", "chat",
                                          "study", "play", "edit"]
       this.mode_control_tile_draw.available_modes = ["admin_enter"]
@@ -622,7 +630,7 @@ let tui = {
     this.tile_draw = false;
     if (mode_name == 'admin_enter' && this.is_admin) {
         mode_name = 'admin';
-    } else if (mode_name == 'name_thing') {
+    } else if (['name_thing', 'admin_thing_protect'].includes(mode_name)) {
         let player_position = game.things[game.player_id].position;
         let thing_id = null;
         for (let t_id in game.things) {
@@ -713,6 +721,7 @@ let tui = {
     } else if (this.mode.name == 'admin') {
         document.getElementById("switch_to_control_pw_type").disabled = false;
         document.getElementById("switch_to_control_tile_type").disabled = false;
+        document.getElementById("switch_to_admin_thing_protect").disabled = false;
     } else if (this.mode.name == 'study') {
         document.getElementById("toggle_map_mode").disabled = false;
     } else if (this.mode.is_single_char_entry) {
@@ -723,6 +732,8 @@ let tui = {
         this.log_msg('@ enter tile protection character for which you want to change the password:')
     } else if (this.mode.name == 'control_tile_type') {
         this.log_msg('@ enter tile protection character which you want to draw:')
+    } else if (this.mode.name == 'admin_thing_protect') {
+        this.log_msg('@ enter thing protection character:')
     } else if (this.mode.name == 'control_pw_pw') {
         this.log_msg('@ enter tile protection password for "' + this.tile_control_char + '":');
     } else if (this.mode.name == 'control_tile_draw') {
@@ -759,6 +770,11 @@ let tui = {
           if (t && t.name_) {
               this.inputEl.value = t.name_;
           }
+      } else if (this.mode.name == 'admin_thing_protect') {
+          let t = game.get_thing(this.selected_thing_id);
+          if (t && t.protection) {
+              this.inputEl.value = t.protection;
+          }
       }
   },
   recalc_input_lines: function() {
@@ -1206,7 +1222,11 @@ let explorer = {
              let t = game.things[t_id];
              if (t.position[0] == this.position[0] && t.position[1] == this.position[1]) {
                  let symbol = game.thing_types[t.type_];
-                 info += "THING: " + t.type_ + " / " + symbol;
+                 let protection = t.protection;
+                 if (protection == '.') {
+                     protection = 'unprotected';
+                 }
+                 info += "THING: " + t.type_ + " / protection: " + protection + " / " + symbol;
                  if (t.player_char) {
                      info += t.player_char;
                  };
@@ -1290,7 +1310,8 @@ tui.inputEl.addEventListener('keydown', (event) => {
         if (tui.inputEl.value.length == 0) {
             tui.inputEl.value = " ";
         }
-        server.send(["THING_NAME", tui.selected_thing_id, tui.inputEl.value]);
+        server.send(["THING_NAME", tui.selected_thing_id, tui.inputEl.value,
+                     tui.password]);
         tui.switch_mode('edit');
     } else if (tui.mode.name == 'annotate' && event.key == 'Enter') {
         explorer.annotate(tui.inputEl.value);
@@ -1320,6 +1341,14 @@ tui.inputEl.addEventListener('keydown', (event) => {
             tui.tile_control_char = tui.inputEl.value[0];
             tui.switch_mode('control_tile_draw');
         }
+    } else if (tui.mode.name == 'admin_thing_protect' && event.key == 'Enter') {
+        if (tui.inputEl.value.length != 1) {
+            tui.log_msg('@ entered non-single-char, therefore aborted');
+        } else {
+            server.send(['THING_PROTECTION', tui.selected_thing_id, tui.inputEl.value])
+            tui.log_msg('@ sent new protection character for thing');
+        }
+        tui.switch_mode('admin');
     } else if (tui.mode.name == 'chat' && event.key == 'Enter') {
         let tokens = parser.tokenize(tui.inputEl.value);
         if (tokens.length > 0 && tokens[0].length > 0) {
index abdd02726a3bfe66aa9229c47f15e33ee3fb4870..5c5e657d149faae4625bce198e8a6cc1f12527db 100755 (executable)
@@ -8,6 +8,7 @@ from plomrogue.commands import (cmd_ALL, cmd_LOGIN, cmd_NICK, cmd_PING, cmd_THIN
                                 cmd_THING_NAME, cmd_TERRAINS, cmd_ADMIN_PASSWORD,
                                 cmd_BECOME_ADMIN, cmd_SET_TILE_CONTROL,
                                 cmd_GOD_THING_NAME,
+                                cmd_GOD_THING_PROTECTION, cmd_THING_PROTECTION,
                                 cmd_SET_MAP_CONTROL_PASSWORD, cmd_SPAWN_POINT)
 from plomrogue.tasks import (Task_WAIT, Task_MOVE, Task_WRITE, Task_PICK_UP,
                              Task_DROP, Task_FLATTEN_SURROUNDINGS)
@@ -34,6 +35,8 @@ game.register_command(cmd_TASKS)
 game.register_command(cmd_THING_TYPES)
 game.register_command(cmd_TERRAINS)
 game.register_command(cmd_THING)
+game.register_command(cmd_THING_PROTECTION)
+game.register_command(cmd_GOD_THING_PROTECTION)
 game.register_command(cmd_THING_NAME)
 game.register_command(cmd_GOD_THING_NAME)
 game.register_command(cmd_ADMIN_PASSWORD)
index 7ffee570842b6bb234e1bd143889c331006d7188..5ad366a78815e6fd6d3526d256f62e8232b1c7ed 100755 (executable)
@@ -27,6 +27,10 @@ mode_helps = {
         'short': 'name thing',
         'long': 'Give name to/change name of thing here.'
     },
+    'admin_thing_protect': {
+        'short': 'change thing protection',
+        'long': 'Change protection character for thing here.'
+    },
     'write': {
         'short': 'change terrain',
         'long': 'This mode allows you to change the map tile you currently stand on (if your map editing password authorizes you so).  Just enter any printable ASCII character to imprint it on the ground below you.'
@@ -156,14 +160,15 @@ def cmd_PLAYER_ID(game, player_id):
     game.player_id = player_id
 cmd_PLAYER_ID.argtypes = 'int:nonneg'
 
-def cmd_THING(game, yx, thing_type, thing_id):
+def cmd_THING(game, yx, thing_type, protection, thing_id):
     t = game.get_thing(thing_id)
     if not t:
         t = ThingBase(game, thing_id)
         game.things += [t]
     t.position = yx
     t.type_ = thing_type
-cmd_THING.argtypes = 'yx_tuple:nonneg string:thing_type int:nonneg'
+    t.protection = protection
+cmd_THING.argtypes = 'yx_tuple:nonneg string:thing_type char int:nonneg'
 
 def cmd_THING_NAME(game, thing_id, name):
     t = game.get_thing(thing_id)
@@ -360,6 +365,7 @@ class TUI:
     mode_control_pw_pw = Mode('control_pw_pw', has_input_prompt=True)
     mode_control_tile_type = Mode('control_tile_type', has_input_prompt=True)
     mode_control_tile_draw = Mode('control_tile_draw')
+    mode_admin_thing_protect = Mode('admin_thing_protect', has_input_prompt=True)
     mode_annotate = Mode('annotate', has_input_prompt=True, shows_info=True)
     mode_portal = Mode('portal', has_input_prompt=True, shows_info=True)
     mode_chat = Mode('chat', has_input_prompt=True)
@@ -376,7 +382,7 @@ class TUI:
         import json
         self.mode_play.available_modes = ["chat", "study", "edit", "admin_enter"]
         self.mode_study.available_modes = ["chat", "play", "admin_enter", "edit"]
-        self.mode_admin.available_modes = ["control_pw_type",
+        self.mode_admin.available_modes = ["admin_thing_protect", "control_pw_type",
                                            "control_tile_type", "chat",
                                            "study", "play", "edit"]
         self.mode_control_tile_draw.available_modes = ["admin_enter"]
@@ -408,6 +414,7 @@ class TUI:
             'switch_to_admin_enter': 'A',
             'switch_to_control_pw_type': 'C',
             'switch_to_control_tile_type': 'Q',
+            'switch_to_admin_thing_protect': 'T',
             'flatten': 'F',
             'take_thing': 'z',
             'drop_thing': 'u',
@@ -508,6 +515,9 @@ class TUI:
         elif self.mode.name == 'name_thing':
             if hasattr(self.thing_selected, 'name'):
                 self.input_ = self.thing_selected.name
+        elif self.mode.name == 'admin_thing_protect':
+            if hasattr(self.thing_selected, 'protection'):
+                self.input_ = self.thing_selected.protection
 
     def send_tile_control_command(self):
         self.send('SET_TILE_CONTROL %s %s' %
@@ -527,7 +537,7 @@ class TUI:
         self.tile_draw = False
         if mode_name == 'admin_enter' and self.is_admin:
             mode_name = 'admin'
-        elif mode_name == 'name_thing':
+        elif mode_name in {'name_thing', 'admin_thing_protect'}:
             player = self.game.get_thing(self.game.player_id)
             thing = None
             for t in [t for t in self.game.things if t.position == player.position
@@ -568,6 +578,8 @@ class TUI:
             self.log_msg('@ enter tile protection character for which you want to change the password:')
         elif self.mode.name == 'control_tile_type':
             self.log_msg('@ enter tile protection character which you want to draw:')
+        elif self.mode.name == 'admin_thing_protect':
+            self.log_msg('@ enter thing protection character:')
         elif self.mode.name == 'control_pw_pw':
             self.log_msg('@ enter tile protection password for "%s":' % self.tile_control_char)
         elif self.mode.name == 'control_tile_draw':
@@ -665,8 +677,11 @@ class TUI:
                 info += 'PROTECTION: %s\n' % protection
                 for t in self.game.things:
                     if t.position == self.explorer:
-                        info += 'THING: %s / %s' % (t.type_,
-                                                    self.game.thing_types[t.type_])
+                        protection = t.protection
+                        if protection == '.':
+                            protection = 'unprotected'
+                        info += 'THING: %s / protection: %s / %s' %\
+                            (t.type_, protection, self.game.thing_types[t.type_])
                         if hasattr(t, 'player_char'):
                             info += t.player_char
                         if hasattr(t, 'name'):
@@ -915,6 +930,14 @@ class TUI:
                 else:
                     self.tile_control_char = self.input_
                     self.switch_mode('control_pw_pw')
+            elif self.mode.name == 'admin_thing_protect' and key == '\n':
+                if len(self.input_) != 1:
+                    self.log_msg('@ entered non-single-char, therefore aborted')
+                else:
+                    self.send('THING_PROTECTION %s %s' % (self.thing_selected.id_,
+                                                          quote(self.input_)))
+                    self.log_msg('@ sent new protection character for thing')
+                self.switch_mode('admin')
             elif self.mode.name == 'control_tile_type' and key == '\n':
                 if len(self.input_) != 1:
                     self.log_msg('@ entered non-single-char, therefore aborted')
@@ -948,8 +971,9 @@ class TUI:
             elif self.mode.name == 'name_thing' and key == '\n':
                 if self.input_ == '':
                     self.input_ = ' '
-                self.send('THING_NAME %s %s' % (self.thing_selected.id_,
-                                                quote(self.input_)))
+                self.send('THING_NAME %s %s %s' % (self.thing_selected.id_,
+                                                   quote(self.input_),
+                                                   quote(self.password)))
                 self.switch_mode('edit')
             elif self.mode.name == 'annotate' and key == '\n':
                 if self.input_ == '':