Представление снаряжения

Материал из Клуб любителей рогаликов
Перейти к: навигация, поиск

Данная статья была написана для RLNews Darren'а Hebden'а

Снаряжение отслеживает Предметы в Хранилище. Предметы это всё, что вы считаете отслеживаемым: перчатки, дубины, пища, монеты, цветы. Хранение - всё, что определяется как способное содержать предметы: ящики (клады), мешки, руки, здания.

Основное Снаряжение не заботится о внешнем лоске, таком, например, как ограничения по вместимости. Сохранение реализации основного снаряжения допускает многократное использование кода, будет обсуждено позже.

В этой статье для моделирования примеров использован псевдокод. Примеры используют следующий образец определения предмета:

  define Item:
     variable Name

Отслеживание предметов

Есть два основных пути отслеживания предметов. Первый - с помощью простого списка, довольно похожему по написанию на список продуктов (list of groceries). Списки обычно - FIFO (Первым Положил - Первым Забрал) или LIFO (Последним Положил - Первым Забрал). Могут существовать и другие пути. На самом деле, в некоторых языках, есть очень экзотические формы списков. Проблема со списками - поиск информации из середины списка. Список изучается до конца или пока информация не будет найдена.

В нашем примере - простой список:

  list define Inventory

Второй - через более сложную схему в которой отслеживается больше, чем предмет. Также отслеживается информация о предмете. Это то, как предметы могут быть сгруппированы. Группирование имеет свои за и против, как и всё остальное. Использование группирования, например, допускает более легкое отображение предметов (разумеется, по моему собственному мнению). В некоторых отношениях, группирование - более сложная форма списка, используемая для таких вещей как словари, карты и другие.

В этом примере, предметы отслеживаются по их именам. Пример:

  list define Inventory:
     list define itemNames
     keyedList define qtys

Добавление предметов

Что толку использовать Снаряжение, если вы не можете добавлять в него предметы? Таким образом, первая функция, которую мы определим, функция добавления - add().

В основной форме, add(), хочет только разместить передаваемый предмет в список:

  List define Inventory:
     define add(item):
        insert item

Со сложной формой, add(), более подробна. Возникают вопросы: есть ли уже такой предмет в снаряжении - это может повлиять на характеристики отслеживания? Сделаем ли я/вы, если необходимо, настройку характеристик отслеживания? Отметьте, как это сделано в примере:

list define Inventory:

  list define itemNames
     keyedList define qtys
     define add(item):
        if item is in me.itemNames       #do I exist?
           then me.qtys.key(item.name) = +1
        if item is not in me.itemNames   #I don't exist
           then me.qtys.key.add(item.name)
           me.itemNames.add(item.name)
           me.qtys.key(item.name) = +1 

Удаление предметов

Функция Удаление, remove(), противоположна add(). Найдите помещённый предмет и удалите его из списка. Давайте проверим это с нашими двумя псевдокодами.

Конечно, этот пример не принимает во внимание поведение, зависящее от языка (language dependent behavior) (Cи - вы устанавили свои указатели?). Таким образом абстракция та же, что и для add():

  List define Inventory:
     define remove(item):
        delete item

Здесь, как и в сложной функции add(), нужно выполнить больше работы. Мы не только находим предмет, но и убеждаемся, что наше отслеживание характеристик корректируется соответствующим образом.

  list define Inventory:
     list define itemNames
     keyedList define qtys
     define remove(item):
     if item is in me.itemNames
        then me.qtys.key(item.name) = -1
        if me.qtys.key(item.name) == 0
           then me.qtys.delete(item.name)
     if item is not in me.itemNames
        then error

В завершение, наш пример должен показывать соответствующее количество предметов. Плюс, если у нас в снаряжении нет предметов, не должно быть никакого количества или списка.

Отображение предметов (опционально)

Это указано как опция, поскольку вы можете не кодировать показ Снаряжения как часть вашего Снаряжения. Это может быть в вашем UI-коде. Тем не менее, в ходе тестирования, иметь возможность простого отображения Снаряжения очень полезно.

Как всегда, самый простой путь - метод списка. Просто пройдите список, печатая каждый предмет:

  List define Inventory:
     define display():
        For each item in Inventory:
           print item.name

Из-за особенности нашей трассировки, нам нужно печатать предмет и количество. В противном случае будет неопределенность. Единственная дополнительная особенность сложного [примера] по сравнению с простым - печать заголовка "Предмет Кол.".

  List define Inventory:
     define display():
        print "Item     Qty"
        for each item in me.itemNames:
           print item, me.qtys.key(item.name)

Возможные преимущества

Для разработчиков, использующих языки стиля OO (C++, SmallTalk, Java, и т.п.), наличие простого Объекта Снаряжения позволяет вам легко включать его в другие области игры. Можно сделать Контейнеры (сочетание Предметов и Снаряжения), Здания (Структура и Снаряжение), и многое другое. Конечно языки не OO-стиля (C, Pascal, Basic), могут использовать Снаряжение как функции в других частях игры. Указание (The point is): как только вы определите, какое основное снаряжение будет в вашей игре, найдите как использовать его во многих областях.

Пример

Вот примера снаряжения, использующее язык Python. Я нахожу, что Python - великий язык для макетирования. Он легко определяет ошибки, устанавливает их, и т.п. Потом вы можете легко перекодировать на любой другой язык.

The Item Object - class Item:

  def __init__(self, name):#object constructor
     self.name = name

The Inventory Object - class Inventory:

  def __init__(self):
     self. NameList = []#a list of item names
     self.qtys = {}#a dictionary of item quantities
     self.contents = []#a list of actual items
  def add(self, itemList = []):
     for item in itemList:
        #Check item is self
        if item is self:
           print 'Cannot store', item,' in itself!'
        if item in self.contents:
           print 'You already have this item!'
        else:
           #Check if item is in nameList
           if item.name in self.NameList:
              #merely insert
              self.qtys[item.name] = self.qtys[item.name] + 1
           #otherwise add to nameList
           else:
              self.qtys[item.name] = 1
              self.nameList.append(item.name)
           self.contents.append(item)
  def remove(self, item):
     #does item exist?
     If item not in self.contents:
        print item.name, 'is not in your inventory'
     else:
        self.qtys[item.name] = self.qtys[item.name] - 1
        if self.qtys[item.name] == 0:
           del self.qtys[item.name]
           self.NameList.remove(item.name)
        self.contents.remove(item)
  def display(self):
     #let's show everything!
     Print "Item\tQty"
     for item in self.NameList:
        print item,"\t", self.qtys[item]

Дополнительная информация

Для информации о Python, посетите: http://www.python.org Пожалуйста высылайте автору все комментарии, запросы, и уведомления об ошибках.

email: uncle_wiggly@bigfoot.com Версия: 1.0 Дата: 25 Октября 1999



Автор: Kenneth Power.
Источник: Inventory Abstraction.
Перевел: Дмитрий О. Бужинский [Bu], 24.05.2005.