Identificação automática de preço de pergaminhos no Nethack


21

OH DEUSES NÃO !! Você não pode nos deixar aqui com maçaneta! Haverá nethack em todos os lugares! - 1d atrás por Geobits

Bem, não poderia decepcionar ...

Introdução

(você pode pular esta seção se não se importar com a exposição e / ou se tiver Síndrome de explosão por tabulação )

Uma das mecânicas características de Nethack (e Rogue, e jogos similares no mesmo gênero roguelike) é o seu sistema de identificação . No início do jogo, apenas os itens do seu inventário inicial são "formalmente identificados". A grande maioria dos outros objetos começa desconhecida; por exemplo, um "escudo de reflexão" será exibido inicialmente como um "escudo de prata polida" antes de ser identificado.

Um "escudo de prata polida" pode ser apenas um escudo de reflexão , mas isso tem conseqüências interessantes em outros dois casos.

  1. Alguns itens são diferentes um do outro, mas têm a mesma "aparência". Por exemplo, se você encontrar uma " pedra cinza ", pode ser uma das quatro coisas: uma pedra de pederneira (inútil), uma pedra de toque (pode ser útil), uma pedra de carga (que o sobrecarregará severamente porque pesa uma tonelada e você não pode descartá- lo) ou uma pedra da sorte (extremamente útil, quase necessária para ganhar o jogo).

  2. Muitos itens (pergaminhos, varinhas, anéis, livros de feitiços, algumas armaduras etc.) têm uma aparência aleatória. O que isso significa é que existe uma lista definida de possíveis aparências, digamos, que poções poderiam ter; por exemplo, [ dourado poção , poção swirly , poção efervescente , poção roxo-vermelho , etc.]. Essas aparências são então designadas aleatoriamente para o que realmente são ( poção de cura , poção de paralisia , poção de ver invisível , poção de polimorfo , etc.).

    O que significa que um amuleto hexagonal pode salvar sua vida em um jogo (amuleto de salvar vidas) e sufocá-lo até a morte no próximo (amuleto de estrangulamento) .

Naturalmente, isso torna a identificação de itens uma parte crítica do jogo. Os itens podem ser "formalmente identificados", o que significa que eles aparecerão inequivocamente como sendo definitivamente um determinado item (por exemplo, todas as varinhas de jóias que você encontrar aparecerão como varinhas de criar monstro ); isso é feito principalmente por meio de pergaminhos ou livros de feitiços de identificação. Normalmente, esses são escassos, o que nos leva a ...

Identificação informal. Isso significa que você tem certeza (ou certeza) de que um determinado item não identificado é de um determinado tipo (ou que pode ser apenas um de vários tipos), mas você ainda não o identificou "formalmente". Isso pode ser feito através de vários métodos: teste de gravação de varinhas, teste de colisão de anéis ou o método mais comum ...

gráfico de identificação de preço de rolagem

... identificação de preço ! Qual é o objetivo deste desafio.

Em poucas palavras, existem lojas localizadas nas Dungeons of Doom (sim, os lojistas pensaram que seria uma boa ideia montar uma loja em alguma masmorra subterrânea; não pergunte o porquê). Nessas lojas, você pode comprar e vender os vários itens que você encontra durante suas viagens. Ao comprar ou vender um item, o lojista primeiro diz a você o quanto ele o venderia / o compraria de você. Como é garantido que determinados itens têm preços específicos , você pode usá-lo para identificar informalmente um determinado tipo de item.

Alguns itens, como o rolo de luz , são os únicos a custar uma certa quantia, o que permite identificá-los sem ambiguidade; no entanto, a maioria dos itens compartilha um grupo de preços com outros itens da mesma classe, o que apenas permite diminuir as possibilidades (o que ainda é útil). No entanto, os preços de compra / venda de um item são afetados por várias variáveis ​​(como o seu status do Carisma ). Daí o gráfico acima.

Você poderia dizer que eu gosto de Nethack?

Entrada

A entrada será fornecida como um jogo Nethack (baunilha, 3.4.3) atualmente sendo jogado:

"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

Isso significa que é garantido que você tenha várias propriedades:

  • Ele vai sempre ser de 24 longas filas.

  • Cada linha sempre terá 80 caracteres ou menos.

  • A penúltima linha consistirá nos seguintes " tokens ": nome e título do jogador (na forma de " foo the bar "), a lista de atributos (separados por um único espaço) e o alinhamento do jogador ( Legal, Neutro ou Caótico). Cada token será separado por um número variável de espaços. 1 1

  • A lista de atributos sempre será St:* Dx:* Co:* In:* Wi:* Ch:*, onde um *caractere representa um número inteiro de 3 a 25. 2 (O ponto de interesse aqui é a última estatística, Carisma, que você precisa calcular os preços.)

  • A primeira linha sempre consistirá em uma mensagem relacionada à loja (especificamente, a mensagem exibida quando você estiver comprando ou vendendo um item). Além disso, é garantido que este item seja um único pergaminho não identificado e sem nome. Para comprar um item, é o seguinte:

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

    e para venda, é:

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

    onde as "variáveis" listadas {curly braces}são as seguintes:

    • {TITLE}é sempre um dos " bons ", " honrados ", " mais gentis " ou " estimados ", concatenados com " senhora " ou " senhor ".

    • {PRICE} é sempre um número inteiro.

    • {LABEL}sempre será um dos seguintes ( fonte ):

      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}sempre será um dos seguintes ( fonte ):

      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
      

    Essa mensagem pode ser dividida em outra linha (mas nunca ocupará mais de 2 linhas). 3

  • Além das primeiras linhas, todas as apostas estão fora da aparência do resto da tela. O Nethack usa a maioria do conjunto de caracteres ASCII . A única coisa que você pode assumir com segurança é que a entrada será puramente ASCII (no entanto, isso provavelmente não importará porque você pode descartar as linhas 3-22 de qualquer maneira).

Se a entrada for tomada como argumento de função, ela será fornecida exatamente como mostrado no exemplo acima (nova linha separada). Se você inserir via STDIN, ele será fornecido como 24 linhas consecutivas de entrada (novamente, como mostrado acima). Você pode escolher se deseja que a entrada tenha uma nova linha à direita ou não. A entrada é garantida para não ter espaços à direita.

Saída

A saída deve ser fornecida como o que deveria ser #nameo pergaminho que acabei de identificar. O sistema de nomes que eu uso (e que eu já vi outros usarem) é:

  • Se o pergaminho for inequivocamente identificado como um certo pergaminho (identificar, iluminar, encantar arma), #nameé isso. É o caso dos pergaminhos dos seguintes preços base (você verá como calcular o preço base abaixo): 20 -> identificar, 50 -> leve, 60 -> encantar a arma.

  • Caso contrário, pegue as três primeiras letras da aparência do pergaminho ou a primeira palavra se tiver menos de 3 caracteres. Por exemplo, ZELGO MERtorna-se ZEL, VE FORBRYDERNEtorna-se VEetc. Concatene com este (um espaço e, em seguida) o preço base do pergaminho. Por exemplo ELB 300,.

  • Se o preço base pode ser uma das duas possibilidades, normalmente continuo tentando comprar ou vender o item até obter um preço oferecido que o coloca inequivocamente em um determinado intervalo de preços. No entanto, você não pode fazer isso neste desafio; basta separar os dois preços base possíveis com uma barra ( /). Por exemplo HAC 60/80,.

Aqui está a fórmula para converter o preço base de um item no preço que lhe é oferecido para comprá-lo:

  • comece com o preço base do item

  • chance de uma possível "sobretaxa não identificada" de 33%, calculada via price += price / 3

  • outra chance de uma "marcação otária" de 33% (na verdade, não é uma chance aleatória, mas para os fins desse desafio), calculada da mesma maneira

  • um modificador de carisma, que é aplicado da seguinte maneira:

    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
    

E aqui está a fórmula para o preço base -> preço de venda:

  • comece com o preço base do item

  • divida isso por 2 ou 3 ("normal" ou "otário marcação", respectivamente; novamente, não aleatório, mas é para os propósitos deste desafio)

  • possibilidade de uma redução adicional de 25% 4 , calculada viaprice -= price / 4

A divisão é divisão inteira, o que significa que o resultado em cada etapa é arredondado para baixo. (Fonte: wiki , e um pouco de digitação do código-fonte. Inverter essas fórmulas é o seu trabalho.)

Finalmente, aqui está um gráfico ASCII prático que mostra os possíveis preços de compra (agrupados por estatísticas Charisma) e os preços de venda de um pergaminho com um determinado preço base:

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

(Isso é idêntico ao gráfico no wiki, exceto que lista todos os preços de venda possíveis, enquanto o gráfico do wiki negligencia a inclusão de dois dos quatro possíveis preços de venda. Não, eu não fiz esse gráfico manualmente; gerado com esse script Ruby .)

Casos de teste

Entrada:

"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

Saída: LEP 60/80


Entrada:

"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

Saída: enchant weapon


Entrada:

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

Saída: GAR 300


Entrada:

"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

Saída: VE 100


Entrada:

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

Saída: identify

(Eu tive que compilar manualmente o Nethack com todos os outros nomes de lojistas removidos porque não consegui encontrar um lojista que tivesse um espaço em seu nome ...)

Regras


1: isso nem sempre é verdade durante um jogo Nethack, mas assumimos isso por uma questão de simplicidade.

2: novamente, nem sempre é verdade. A força pode variar de 18/01 a 18 / **, mas você não precisa lidar com isso.

3: simplificações mais brutas. Por exemplo, é possível para um lojista chamá-lo de "escória" ou "criatura mais renomada e sagrada", mas você não precisa lidar com nada disso.

4: que um jogador inteligente se desloca oferecendo repetidamente a venda do item até receber o preço mais alto.


15
Santo muro de texto!
orlp

Respostas:


10

Javascript (ES6), 1610 724 601 612 419 405 bytes

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])

Grande muralha de texto, conheça grande muralha de código.

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]
)

Exemplo


1
Essa é uma grande pilha de scripts.
Fatalize

1
Woah, alguém finalmente respondeu isso? Nice: D
Maçaneta da porta

@Doorknob Estava querendo atualizar isso por um tempo, finalmente cheguei a ele.
usandfriends 13/03
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.