From 729e72408fa1c3180275ad3c0e6689143a0f2f38 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Sat, 9 Mar 2019 01:08:35 +0100 Subject: [PATCH] Allow item-in-vicinity selection for item pickup. --- new/example_client.py | 72 +++++++++++++++++++++++++++------------ new/plomrogue/commands.py | 8 +++++ new/plomrogue/game.py | 3 +- new/plomrogue/tasks.py | 5 ++- new/plomrogue/things.py | 10 ++++++ 5 files changed, 72 insertions(+), 26 deletions(-) diff --git a/new/example_client.py b/new/example_client.py index b561d9d..1e91070 100755 --- a/new/example_client.py +++ b/new/example_client.py @@ -71,6 +71,7 @@ class World(WorldBase): self.map_ = Map() self.player_inventory = [] self.player_id = 0 + self.pickable_items = [] def new_map(self, yx): self.map_ = Map(yx) @@ -94,6 +95,7 @@ def cmd_TURN(game, n): """Set game.turn to n, empty game.things.""" game.world.turn = n game.world.things = [] + game.world.pickable_items = [] game.to_update['turn'] = False game.to_update['map'] = False cmd_TURN.argtypes = 'int:nonneg' @@ -115,6 +117,11 @@ def cmd_PLAYER_INVENTORY(game, ids): game.world.player_inventory = ids # TODO: test whether valid IDs cmd_PLAYER_INVENTORY.argtypes = 'seq:int:nonneg' +def cmd_PICKABLE_ITEMS(game, ids): + game.world.pickable_items = ids + game.to_update['map'] = True +cmd_PICKABLE_ITEMS.argtypes = 'seq:int:nonneg' + class Game: @@ -130,6 +137,7 @@ class Game: 'PLAYER_INVENTORY': cmd_PLAYER_INVENTORY, 'GAME_STATE_COMPLETE': cmd_GAME_STATE_COMPLETE, 'MAP': cmd_MAP, + 'PICKABLE_ITEMS': cmd_PICKABLE_ITEMS, 'THING_TYPE': cmd_THING_TYPE, 'THING_POS': cmd_THING_POS} self.log_text = '' @@ -139,6 +147,7 @@ class Game: 'turn': True, } self.do_quit = False + self.to_update_lock = False def get_command(self, command_name): from functools import partial @@ -153,6 +162,7 @@ class Game: return None def handle_input(self, msg): + self.log(msg) if msg == 'BYE': self.do_quit = True return @@ -319,13 +329,17 @@ class MapWidget(Widget): if self.tui.view == 'map': self.draw_map() elif self.tui.view == 'inventory': - self.draw_inventory() - - def draw_inventory(self): - lines = ['INVENTORY:'] + self.draw_item_selector('INVENTORY:', + self.tui.game.world.player_inventory) + elif self.tui.view == 'pickable_items': + self.draw_item_selector('PICKABLE:', + self.tui.game.world.pickable_items) + + def draw_item_selector(self, title, selection): + lines = [title] counter = 0 - for id_ in self.tui.game.world.player_inventory: - pointer = '*' if counter == self.tui.inventory_pointer else ' ' + for id_ in selection: + pointer = '*' if counter == self.tui.item_pointer else ' ' t = self.tui.game.world.get_thing(id_) lines += ['%s %s' % (pointer, t.type_)] counter += 1 @@ -408,7 +422,7 @@ class TUI: self.game = game self.parser = Parser(self.game) self.to_update = {'edit': False} - self.inventory_pointer = 0 + self.item_pointer = 0 curses.wrapper(self.loop) def draw_screen(self): @@ -494,31 +508,45 @@ class TUI: for w in widgets: w.ensure_freshness(True) elif key == 'p': - for t in self.game.world.things: - if t == self.game.world.player or \ - t.id_ in self.game.world.player_inventory: - continue - if t.position == self.game.world.player.position: - self.socket.send('TASK:PICKUP %s' % t.id_) - break + self.socket.send('GET_PICKABLE_ITEMS') + self.item_pointer = 0 + self.view = 'pickable_items' elif key == 'i': + self.item_pointer = 0 self.view = 'inventory' self.game.to_update['map'] = True + elif self.view == 'pickable_items': + if key == 'c': + self.view = 'map' + elif key == 'j' and \ + len(self.game.world.pickable_items) > \ + self.item_pointer + 1: + self.item_pointer += 1 + elif key == 'k' and self.item_pointer > 0: + self.item_pointer -= 1 + elif key == 'p' and \ + len(self.game.world.pickable_items) > 0: + id_ = self.game.world.pickable_items[self.item_pointer] + self.socket.send('TASK:PICKUP %s' % id_) + self.view = 'map' + else: + continue + self.game.to_update['map'] = True elif self.view == 'inventory': - if key == 'i': + if key == 'c': self.view = 'map' elif key == 'j' and \ len(self.game.world.player_inventory) > \ - self.inventory_pointer + 1: - self.inventory_pointer += 1 - elif key == 'k' and self.inventory_pointer > 0: - self.inventory_pointer -= 1 + self.item_pointer + 1: + self.item_pointer += 1 + elif key == 'k' and self.item_pointer > 0: + self.item_pointer -= 1 elif key == 'd' and \ len(self.game.world.player_inventory) > 0: - id_ = self.game.world.player_inventory[self.inventory_pointer] + id_ = self.game.world.player_inventory[self.item_pointer] self.socket.send('TASK:DROP %s' % id_) - if self.inventory_pointer > 0: - self.inventory_pointer -= 1 + if self.item_pointer > 0: + self.item_pointer -= 1 else: continue self.game.to_update['map'] = True diff --git a/new/plomrogue/commands.py b/new/plomrogue/commands.py index 3ae5958..92f583d 100644 --- a/new/plomrogue/commands.py +++ b/new/plomrogue/commands.py @@ -46,6 +46,14 @@ def cmd_THING_INVENTORY(game, id_, ids): t.inventory = ids # TODO: test whether valid IDs cmd_THING_INVENTORY.argtypes = 'int:nonneg seq:int:nonneg' +def cmd_GET_PICKABLE_ITEMS(game, connection_id): + pickable_ids = game.world.player.get_pickable_items() + if len(pickable_ids) > 0: + game.io.send('PICKABLE_ITEMS %s' % + ','.join([str(id_) for id_ in pickable_ids])) + else: + game.io.send('PICKABLE_ITEMS ,') + def cmd_TERRAIN_LINE(game, y, terrain_line): game.world.map_.set_line(y, terrain_line) cmd_TERRAIN_LINE.argtypes = 'int:nonneg string' diff --git a/new/plomrogue/game.py b/new/plomrogue/game.py index e24edbb..e8e80c0 100755 --- a/new/plomrogue/game.py +++ b/new/plomrogue/game.py @@ -2,7 +2,7 @@ from plomrogue.tasks import Task_WAIT, Task_MOVE, Task_PICKUP, Task_DROP from plomrogue.errors import ArgError from plomrogue.commands import (cmd_GEN_WORLD, cmd_GET_GAMESTATE, cmd_MAP, cmd_MAP, cmd_THING_TYPE, cmd_THING_POS, - cmd_THING_INVENTORY, + cmd_THING_INVENTORY, cmd_GET_PICKABLE_ITEMS, cmd_TERRAIN_LINE, cmd_PLAYER_ID, cmd_TURN, cmd_SWITCH_PLAYER, cmd_SAVE) from plomrogue.mapping import MapHex @@ -119,6 +119,7 @@ class Game: 'THING_POS': cmd_THING_POS, 'THING_INVENTORY': cmd_THING_INVENTORY, 'TERRAIN_LINE': cmd_TERRAIN_LINE, + 'GET_PICKABLE_ITEMS': cmd_GET_PICKABLE_ITEMS, 'PLAYER_ID': cmd_PLAYER_ID, 'TURN': cmd_TURN, 'SWITCH_PLAYER': cmd_SWITCH_PLAYER, diff --git a/new/plomrogue/tasks.py b/new/plomrogue/tasks.py index 1be5b6d..6f2f1be 100644 --- a/new/plomrogue/tasks.py +++ b/new/plomrogue/tasks.py @@ -59,9 +59,7 @@ class Task_PICKUP(Task): to_pick_up = self.thing.world.get_thing(self.args[0], create_unfound=False) if to_pick_up is None or \ - to_pick_up.in_inventory or \ - to_pick_up == self.thing or \ - self.thing.position != to_pick_up.position: + to_pick_up.id_ not in self.thing.get_pickable_items(): raise GameError('thing of ID %s not in reach to pick up' % self.args[0]) @@ -69,6 +67,7 @@ class Task_PICKUP(Task): to_pick_up = self.thing.world.get_thing(self.args[0]) self.thing.inventory += [self.args[0]] to_pick_up.in_inventory = True + to_pick_up.position = self.thing.position diff --git a/new/plomrogue/things.py b/new/plomrogue/things.py index a631b17..20ce486 100644 --- a/new/plomrogue/things.py +++ b/new/plomrogue/things.py @@ -149,6 +149,16 @@ class ThingAnimate(Thing): visible_things += [thing] return visible_things + def get_pickable_items(self): + pickable_ids = [] + for t in [t for t in self.get_visible_things() if + isinstance(t, ThingItem) and + (t.position == self.position or + t.position in + self.world.map_.get_neighbors(self.position).values())]: + pickable_ids += [t.id_] + return pickable_ids + class ThingHuman(ThingAnimate): -- 2.30.2