Автоматическая идентификация цены свитков в Nethack


21

О Боже, нет! Вы не можете оставить нас здесь с дверной ручкой! Это будет nethack везде! - 1 день назад от Geobits

Ну, не могу разочаровать ...

Введение

(вы можете пропустить этот раздел, если вас не интересует экспозиция и / или у вас синдром взрыва вкладок )

Одной из характерных механик Nethack (и Rogue, и подобных игр в том же жанре roguelike) является его система идентификации . В начале игры только предметы в вашем начальном инвентаре «официально идентифицированы». Подавляющее большинство других объектов начинаются неизвестно; например, «щит отражения» будет первоначально отображаться как «полированный серебряный щит», прежде чем он будет идентифицирован.

«Полированный серебряный щит» может быть только щитом отражения , но это имеет интересные последствия в двух других случаях.

  1. Некоторые предметы отличаются друг от друга, но имеют одинаковый «внешний вид». Например, если вы найдете « серый камень », это может быть одна из четырех вещей: кремневый камень (бесполезный), пробный камень (может быть полезен), грузовой камень (который сильно обременит вас, потому что он весит тонну, а вы не могу бросить это), или камень везения (чрезвычайно полезный, почти необходимый для победы в игре).

  2. Многие предметы (свитки, палочки, кольца, книги заклинаний, некоторые доспехи и т. Д.) Имеют случайный вид. Это означает, что существует список возможных появлений, скажем, зелий; например, [ золотое зелье , водоворотное зелье , шипучее зелье , пурпурно-красное зелье и т. д.]. Эти явления затем случайным образом соотносятся с тем, чем они на самом деле являются ( зелье исцеления , зелье паралича , зрение невидимого , зелье полиморфа и т. Д.).

    Это означает, что шестиугольный амулет может спасти вашу жизнь в одной игре (амулет спасения жизни) , а в следующей - задушить вас (амулет удушения) .

Естественно, это делает идентификацию предметов критической частью игры. Предметы могут быть «формально идентифицированы», что означает, что они однозначно будут отображаться как определенно определенный предмет (например, все найденные драгоценные жезлы будут отображаться как жезлы создания монстра ); это делается главным образом с помощью свитков или книг заклинаний идентификации. Обычно их не хватает, что приводит нас к ...

Неформальная идентификация. Это означает, что вы абсолютно уверены (или уверены), что определенный неопознанный элемент относится к определенному типу (или что это может быть только один из нескольких типов), но вы еще «формально» не определили его. Это можно сделать несколькими способами: тестирование гравировки для палочек, тестирование погружения для колец или самый распространенный метод ...

свиток с ценой

... идентификация цены ! Вот о чем этот вызов.

Короче говоря, есть магазины, расположенные в Dungeons of Doom (да, владельцы магазинов думали, что было бы неплохо открыть магазин в каком-нибудь подземном подземелье; не спрашивайте, почему). В этих магазинах вы можете покупать и продавать различные предметы, с которыми вы сталкиваетесь во время путешествий. При покупке или продаже предмета продавец сначала скажет вам, сколько он продаст вам / за что купит его у вас. Поскольку определенные товары гарантированно имеют определенные цены , вы можете использовать это для неформальной идентификации определенного типа товара.

Некоторые предметы, такие как свиток света , являются единственными предметами, которые стоят определенную сумму, что позволяет однозначно идентифицировать их; тем не менее, большинство предметов делят ценовую группу с другими предметами того же класса, что только позволяет сузить возможности (что все еще полезно). Однако на цены покупки / продажи предмета влияет ряд переменных (например, ваш показатель Харизмы ). Отсюда и таблица выше.

Не могли бы вы сказать, что мне нравится Nethack?

вход

Входные данные будут предоставлены как (vanilla, 3.4.3) игра Nethack, в которую играют в данный момент:

"For you, most gracious sir; only 177 for this scroll labeled VERR YED HORRE."
--More--

        ------------
        |          .                                        ---------
        |          |                         ----------     |    ^  |
        |          .##       ################.        +#   #.       .#
        |          | #                       |       _|#   #---------#
        |          | ###                   ##.<       |#   ####      #
        |          .#########################----------#      #      #
        ------------   ###     #         ############# #      #      #
           #             #  -----------  #             #      #   ####
         ###             ###|         |###             #      #   #----------
         #                 #.         |#             ### #    #   #|.???????|
        ##                  |         |#             #--------#   #|.??@????|
    ----.----###############.         |#             #|      |#   #-@???????|
    |.......+#              |         |#             #.      |#    ----------
    |.......|               |         .#              |      |#
    |......>|               -----------               |      +#
    ---------                                         --------


Wizard the Evoker         St:12 Dx:14 Co:11 In:16 Wi:12 Ch:10  Chaotic
Dlvl:2  $:0  HP:11(11) Pw:0(8) AC:9  Exp:1 T:11

Это означает, что он гарантированно имеет несколько свойств:

  • Это всегда будет 24 строки.

  • Каждая строка всегда будет длиной не более 80 символов.

  • Вторая до последней строки будет состоять из следующих « жетонов »: имя и заголовок игрока (в форме « foo the bar »), список атрибутов (разделенных одним пробелом) и выравнивание игрока ( Законный, Нейтральный или Хаотический). Каждый токен будет разделен переменным количеством пробелов. 1

  • Список атрибутов всегда будет таким St:* Dx:* Co:* In:* Wi:* Ch:*, где *символ представляет собой целое число от 3 до 25. 2 (Интересным моментом здесь является последний показатель Харизма, который вам нужен для расчета цены.)

  • Первая строка всегда будет состоять из сообщения, связанного с магазином (в частности, сообщения, которое отображается, когда вы покупаете или продаете товар). Кроме того, этот предмет гарантированно будет одним, неопознанным, безымянным свитком. Для покупки предмета это:

    "For you, {TITLE}; only {PRICE} for this scroll labeled {LABEL}."--More--
    

    а для продажи это:

    {SHK} offers {PRICE} gold pieces for your scroll labeled {LABEL}.  Sell it? [ynaq] (y)
    

    где перечисленные ниже «переменные» {curly braces}:

    • {TITLE}всегда один из « хороших », « почитаемых », « самых добрых » или « уважаемых », соединенных с « дамой » или « сэром ».

    • {PRICE} всегда целое число

    • {LABEL}всегда будет одним из следующих ( источник ):

      ZELGO MER       JUYED AWK YACC  NR 9             XIXAXA XOXAXA XUXAXA
      PRATYAVAYAH     DAIYEN FOOELS   LEP GEX VEN ZEA  PRIRUTSENIE
      ELBIB YLOH      VERR YED HORRE  VENZAR BORGAVVE  THARR
      YUM YUM         KERNOD WEL      ELAM EBOW        DUAM XNAHT
      ANDOVA BEGARIN  KIRJE           VE FORBRYDERNE   HACKEM MUCHE
      VELOX NEB       FOOBIE BLETCH   TEMOV            GARVEN DEH
      READ ME
      
    • {SHK}всегда будет одним из следующих ( источник ):

      Skibbereen      Ballingeary     Inishbofin      Annootok        Abitibi
      Kanturk         Kilgarvan       Kesh            Upernavik       Maganasipi
      Rath Luirc      Cahersiveen     Hebiwerie       Angmagssalik    Akureyri
      Ennistymon      Glenbeigh       Possogroenoe    Aklavik         Kopasker
      Lahinch         Kilmihil        Asidonhopo      Inuvik          Budereyri
      Kinnegad        Kiltamagh       Manlobbi        Tuktoyaktuk     Akranes
      Lugnaquillia    Droichead Atha  Adjama          Chicoutimi      Bordeyri
      Enniscorthy     Inniscrone      Pakka Pakka     Ouiatchouane    Holmavik
      Gweebarra       Clonegal        Kabalebo        Chibougamau     Lucrezia
      Kittamagh       Lisnaskea       Wonotobo        Matagami        Dirk
      Nenagh          Culdaff         Akalapi         Kipawa
      Sneem           Dunfanaghy      Sipaliwini      Kinojevis
      

    Это сообщение может быть разбито на другую строку (но оно никогда не займет больше 2 строк). 3

  • За исключением первых нескольких строк, все ставки выключены относительно того, как выглядит остальная часть экрана. Nethack использует большую часть набора символов ASCII . Единственное, что вы можете с уверенностью предположить, это то, что вход будет чисто ASCII (однако это, вероятно, не будет иметь значения, потому что вы все равно можете отбросить строки 3-22).

Если входные данные взяты в качестве аргумента функции, они будут заданы точно так, как показано в примере выше (разделены символом новой строки). Если вы вводите через STDIN, он будет представлен как 24 последовательных строки ввода (опять же, как показано выше). Вы можете выбрать, хотите ли вы, чтобы ввод имел завершающий символ новой строки или нет. На входе гарантированно не должно быть завершающих пробелов.

Выход

Вывод должен быть представлен как то, что я должен #nameпрокрутить, что я просто ценовой ID. Система именования, которую я использую (и которую я видел, используют другие):

  • Если свиток однозначно идентифицирован как определенный свиток (идентификация, свет, зачарование оружия), #nameто это так. Это касается свитков следующих базовых цен (вы узнаете, как рассчитать базовую цену ниже): 20 -> идентификация, 50 -> легкое, 60 -> зачарование оружия.

  • В противном случае возьмите первые три буквы внешнего вида свитка или первое слово, если оно меньше 3 символов. Например, ZELGO MERстановится ZEL, VE FORBRYDERNEстановится VEи т. Д. Сопоставьте с этим (пробел, а затем) базовую цену свитка. Например, ELB 300.

  • Если базовая цена может быть одной из двух возможностей, я обычно продолжаю пытаться купить или продать предмет, пока не получу предложенную цену, которая однозначно помещает его в определенный ценовой интервал. Однако вы не можете сделать это в этой задаче, поэтому просто разделите две возможные базовые цены с помощью косой черты ( /). Например, HAC 60/80.

Вот формула для преобразования базовой цены товара в цену, которую вам предлагается купить:

  • начать с базовой цены товара

  • вероятность возможной 33% «неопознанной доплаты», рассчитанной через price += price / 3

  • еще один шанс 33% «разметки присоски» (на самом деле это не случайный шанс, а для целей этого вызова), рассчитанный таким же образом

  • модификатор харизмы, который применяется следующим образом:

    Ch    3-5     6-7       8-10      11-15  16-17     18        19-25
    Mod   +100%   +50%      +33%      +0%    -25%      -33%      -50%
    Code  p *= 2  p += p/2  p += p/3  ---    p -= p/4  p -= p/3  p /= 2
    

А вот формула для базовой цены -> цена продажи:

  • начать с базовой цены товара

  • разделите это либо на 2, либо на 3 («нормальная» или «разметка присоски» соответственно; опять же, не случайно, но для целей этой задачи)

  • вероятность дальнейшего снижения на 25% 4 , рассчитывается черезprice -= price / 4

Деление является целочисленным делением, что означает, что результат на каждом шаге округляется в меньшую сторону. (Источник: вики , и немного копания исходного кода. Перевернуть эти формулы - ваша работа.)

Наконец, вот удобный график ASCII, который показывает возможные цены покупки (сгруппированные по статистике харизмы) и цены продажи свитка с определенной базовой ценой:

Base  Ch<6          6-7          8-10         11-15        16-17        18           19-25        Sell
20    40/52/68      30/39/51     26/34/45     20/26/34     15/20/26     14/18/23     10/13/17     5/6/8/10
50    100/132/176   75/99/132    66/88/117    50/66/88     38/50/66     34/44/59     25/33/44     12/16/19/25
60    120/160/212   90/120/159   80/106/141   60/80/106    45/60/80     40/54/71     30/40/53     15/20/23/30
80    160/212/282   120/159/211  106/141/188  80/106/141   60/80/106    54/71/94     40/53/70     20/26/30/40
100   200/266/354   150/199/265  133/177/236  100/133/177  75/100/133   67/89/118    50/66/88     25/33/38/50
200   400/532/708   300/399/531  266/354/472  200/266/354  150/200/266  134/178/236  100/133/177  50/66/75/100
300   600/800/1066  450/600/799  400/533/710  300/400/533  225/300/400  200/267/356  150/200/266  75/100/113/150

(Это идентично графику на вики, за исключением того, что в нем перечислены все возможные цены продажи, в то время как на вики-графике не учитываются две из четырех возможных цен продажи. Нет, я не создавал этот график вручную; сгенерирован с помощью этого сценария Ruby .)

Контрольные примеры

Входные данные:

"For you, honored sir; only 80 for this scroll labeled LEP GEX VEN ZEA."
--More--                   #                                          #
                      ----------------                              -----
                      |              |              ------------####+   |
      -----           |              -##############+          .#   |   |
      |   .###########|           >  |#           # |          |  ##.   |
      |   |          #------------.---#           ##.          |  # -----
      -+---          ##################             ----.-------###    #
       ####                     ###                     #       #      #
          #                     #                       #     ###      ###
          ###                 ###                       #     #          #
            #                 #                         #   ###     -----|--
       -----.---            ###                     ----+---#       |...@..|
       |       |            #                       |      |#       |???+??|
       |  <    .#          ##                     ##+      |        |+?????|
       |       |#    ------.-------                 |      |        |??]?@?|
       ---------###  |            |                 |      |        --------
            #     #  |            |                 --------
                  ###|            |                       #
                    #+            |
                     --------------

Wizard the Evoker         St:11 Dx:15 Co:9 In:20 Wi:9 Ch:11  Chaotic
Dlvl:7  $:0  HP:11(11) Pw:1(8) AC:9  Exp:1

Выход: LEP 60/80


Входные данные:

"For you, most gracious sir; only 80 for this scroll labeled DAIYEN FOOELS."
--More--                                                             #
                ------------                         -----      -------
 -----          |          |                         |   |      |     |
 |!)%|          |          |     ---------------     |   |     #-     |
 |*[@|          |          .#####|   <         |#####.   |   ###|     |
 |?(?|          ---------.--    #+             |#    |   |   #  |     |
 |[!(|                  ##       |             |#    |   +#### #.     .#
 |.@.|         ##################.             +#    ---.-     #|     |#
 ---|-                ###        ---------------#       ##     #-------#
    ##                #                    ######        #     #       #
     #              ###                         #        #     #       #
     ##             #                           #        #     #       #
  ------        #####                           #        #     #       #
  |    |       -.----                           #        #     #       #
  |    .#####  |^   |                        ####        #     #       #
  |    |    #  |    |          ----          #-----------.---- #       #------
  |    |    ###|    |          |  |          #.      >       | #       #|    |
  ------      #.    |          |  |           |              .##       #|    |
               |    |          ----           |              |         #.    |
               ------                         ----------------          ------

Wizard the Evoker         St:11 Dx:14 Co:16 In:15 Wi:10 Ch:9  Chaotic
Dlvl:6  $:0  HP:11(11) Pw:9(9) AC:9  Exp:1

Выход: enchant weapon


Входные данные:

Aklavik offers 113 gold pieces for your scroll labeled GARVEN DEH.  Sell it?
[ynaq] (y)

     -----      ------                                 ---------      -------
     |   |      |    |                         #     ##.       |      |.?)%/|
     |   |    ##.    |                       -----   # |       |      |.@!=*|
     |<  |    # |    |            #        ##.   .#####+    >  |#    #-.*?@[|
     |   .##### |    |      ------------   # | { |#    |^      |#    #|.=%)+|
     ---.-      |    |      |          .#### |   |#    ---------##   #-------
       ##       -.----     #.          |     |   |#          # ###   #
       #         ########  #|          .##   |   |#            ##    #
     ###                #  #------------ #   -----#          ####    #
     #                  #######          ##########################  #
     #                    #   #                            ###----.--#
     #                    ### #                            # #|     |#
   --.----       ########################################### #.     |#
   |     |       #----------.-#                               |     |#
   |     |       #|          |#                               -------
   |     |       #|          .#
   |     |########|          |
   -------        ------------
                   #    #
Wizard the Evoker         St:9 Dx:14 Co:11 In:19 Wi:10 Ch:12  Chaotic
Dlvl:4  $:0  HP:11(11) Pw:5(9) AC:9  Exp:1 Satiated

Выход: GAR 300


Входные данные:

"For you, good lady; only 67 for this scroll labeled VE FORBRYDERNE."--More--

                                                 -------
                                               ##|     |
  ------------                                 # |     |
  |+[!/!?%[?)|                               ### |     |          --------
  |[)(!/+]?!@|               #               #   |     |        ##+      |
  |.......@..|            --------------   ###   | <   | ##       |      |
  --------+---           #|            |   #     |     |  #       |    > |
          #            ###|            .####     --.----  ###    #-      |
          #            ###.            |           #        #  ###|      |
          #          #### ---.----------           #        ######.      |
          #          ####    ##                    #         ###  --------
          #        ####       #                    #         #
          #        ####       ########################     ###
        ###      ####                            ----+---- #
        #   #    ####                            |       .##
    ----.------####                              |  ^    |
    |         +####                              |    >  |
    |         |                                  | ^     |
    -----------                                  ---------

Wizard the Evoker         St:18 Dx:18 Co:16 In:20 Wi:20 Ch:18  Chaotic
Dlvl:4  $:150 HP:11(11) Pw:5(7) AC:9  Exp:1

Выход: VE 100


Входные данные:

Droichead Atha offers 5 gold pieces for your scroll labeled XIXAXA XOXAXA
XUXAXA.  Sell it? [ynaq] (y)
                                                ------------
                   -----                        |          .#
                   |   .### -----------        #.       {  |#
       -----       |   |  # |         |      ###|          |#
       |   .#     #.   |  # |         |      #  ---------+--#
       |   |    ###-|---    |         .##  ###          ##  #
       |   |    #   # #     |         | #  #            #   #
       |   -#####   #       |         | #### ############   #
       |>  | ##     #       ---------+-  ## -.----------    # ----------
       |   .####    ###             ## #####|          |    # |.*??/?)*|
       -----   #      #             #  #    |          |    # |@*)%!)]%|
               ###    ###         ######    |          |    # |.=)!%*!!|
                 #      #         #  #      |          |    ##+@*[%)(%?|
                 #####################      |          |      |.]?*?)%%|
                    -----+---.----##########.          |      |.%)%!!!%|
                    |            +##        ------------      ----------
                    |    <       |                  #
                    |            |
                    --------------

Wizard the Digger          St:11 Dx:9 Co:14 In:6 Wi:6 Ch:9  Lawful
Dlvl:3  $:0  HP:15(15) Pw:0(1) AC:9  Exp:1

Выход: identify

(Мне пришлось вручную скомпилировать Nethack со всеми другими именами лавочников, потому что я не мог найти лавочника, у которого было пробел в его имени ...)

правила


1: это не всегда верно во время игры Nethack, но мы предполагаем это ради простоты.

2: опять не всегда правда. Сила может быть от 18/01 до 18 / **, но вам не нужно с этим справляться.

3: более грубые упрощения. Например, владелец магазина может называть вас «мразь» или «самым известным и священным существом», но вам не нужно с этим справляться.

4: который умный игрок обходит, неоднократно предлагая продать предмет, пока ему не дадут более высокую цену.


15
Святая стена текста!
orlp

Ответы:


10

Javascript (ES6), 1610 724 601 612 419 405 байт

a=>(b=a.match(/(\d+) (g|f).+d (\w{0,3})[\s\S]+h:(\d+)/m),c=+b[4],d=[20,50,60,80,100,200,300].map(e=>(f=e>>1,g=~~(e/3),[e,b[2]=='g'?[g-(g>>2),g,f-(f>>2),f]:[e,e+g,e+g+~~((e+g)/3)].map(h=>c<6?h*2:c<8?h+h>>1:c<11?h+~~(h/3):c<16?h:c<18?h-(h>>2):c<19?h-~~(h/3):h>>1)])).filter(i=>i[1].includes(+b[1])),j={20:'identify',50:'light',60:'enchant weapon'}[d[0][0]],k=b[3]+' '+d[0][0],d.length==1?j||k:k+'/'+d[1][0])

Большая стена текста, встречайте большую стену кода.

Ungolfed

inp => (
    extraction = inp.match(/(\d+) (g|f).+d (\w{0,3})[\s\S]+h:(\d+)/m),

    charisma = +extraction[4],

    allowed = [20, 50, 60, 80, 100, 200, 300].map(base => (
        tmp1 = base >> 1,
        tmp2 = ~~(base / 3),
        [
            base,
            extraction[2] == 'g' ?
                [tmp2 - (tmp2 >> 2), tmp2, tmp1 - (tmp1 >> 2), tmp1]
            :
                [base, base + tmp2, base + tmp2 + ~~((base + tmp2) / 3)].map(val =>
                    charisma < 6 ?
                        val * 2
                    : charisma < 8 ?
                        val + val >> 1
                    : charisma < 11 ?
                        val + ~~(val / 3)
                    : charisma < 16 ?
                        val
                    : charisma < 18 ?
                        val - (val >> 2)
                    : charisma < 19 ?
                        val - ~~(val / 3)
                    : val >> 1
            )
        ]
    )).filter(key => key[1].includes(+extraction[1])),

    name_ = {
        20: 'identify',
        50: 'light',
        60: 'enchant weapon'
    }[allowed[0][0]],

    tmp3 = extraction[3] + ' ' + allowed[0][0],

    allowed.length == 1 ?
        name_ || tmp3
    :
        tmp3 + '/' + allowed[1][0]
)

пример


1
Это одна большая куча сценариев.
Роковая

1
Вау, кто-то наконец-то ответил на это? Ницца: D
дверная ручка

@ Doorknob Давно хотел обновить это, наконец-то дошел до этого.
usandfriends
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.