Automatyczna identyfikacja ceny zwojów w Nethack

21

O BOGOWIE NIE !! Nie możesz nas tu zostawić z Klamką! Wszędzie będzie nethack! - 1 dzień temu przez Geobits

Cóż, nie mogę zawieść ...

Wprowadzenie

(możesz pominąć tę sekcję, jeśli nie obchodzi Cię ekspozycja i / lub jeśli masz syndrom eksplozji tabulatora )

Jedną z charakterystycznych mechanizmów gry Nethack (i Rogue oraz podobnych gier z tego samego gatunku roguelike) jest jej system identyfikacji . Na początku gry tylko przedmioty w ekwipunku początkowym są „formalnie identyfikowane”. Zdecydowana większość innych obiektów zaczyna się od nieznanych; na przykład „tarcza odbicia” będzie początkowo wyświetlana jako „polerowana srebrna tarcza”, zanim zostanie zidentyfikowana.

„Polerowana srebrna tarcza” może być tylko tarczą odbijającą , ale ma to interesujące konsekwencje w dwóch innych przypadkach.

  1. Niektóre elementy różnią się od siebie, ale mają taki sam „wygląd”. Na przykład, jeśli okaże się „ Grey Stone ”, to może być jedną z czterech rzeczy: kamień krzemień (bezużyteczny), A probierczym (może być przydatna), A loadstone (które poważnie obciążają ty ponieważ waży tonę i nie można go upuścić) lub kamień szczęścia (niezwykle pomocny, prawie niezbędny do wygrania gry).

  2. Wiele przedmiotów (zwoje, różdżki, pierścienie, księgi czarów, niektóre zbroje itp.) Mają losowy wygląd. Oznacza to, że istnieje ustalona lista możliwych wyglądów, powiedzmy, że mikstury mogłyby mieć; na przykład [ złoty eliksir , swirly eliksir , gazowany eliksir , fioletowo-czerwony eliksir , itp]. Te wyglądy są następnie losowo przypisywane do tego, czym faktycznie są ( mikstura leczenia , mikstura paraliżu , mikstura widzenia niewidzialnego , mikstura polimorfii itp.).

    Co oznacza, że sześciokątny amulet może uratować ci życie w jednej grze (amulet ratowania życia) , aw następnej udusi cię na śmierć (amulet uduszenia) .

Oczywiście sprawia to, że identyfikacja przedmiotów jest kluczową częścią gry. Przedmioty mogą być „formalnie zidentyfikowane”, co oznacza, że ​​jednoznacznie okażą się jako zdecydowanie określony przedmiot (np. Wszystkie znalezione klejnoty różdżki pojawią się jako różdżki stworzenia potwora ); odbywa się to przede wszystkim za pomocą zwojów lub ksiąg zaklęć identyfikacyjnych. Zazwyczaj brakuje ich, co prowadzi nas do ...

Nieformalna identyfikacja. Oznacza to, że jesteś całkiem pewien (lub pewien), że określony niezidentyfikowany przedmiot jest określonego typu (lub że może to być tylko jeden z kilku rodzajów), ale jeszcze go „formalnie” nie zidentyfikowałeś. Można to zrobić za pomocą kilku metod: testowanie grawerowania różdżek, testowanie zatapiania pierścieni lub najpopularniejsza metoda ...

przewiń wykres ID ceny

... identyfikacja ceny ! Na tym właśnie polega to wyzwanie.

W skrócie, w Dungeons of Doom znajdują się sklepy (tak, sklepikarze uznali, że dobrym pomysłem byłoby założenie sklepu w podziemnym lochu; nie pytaj dlaczego). W tych sklepach możesz kupować i sprzedawać różne przedmioty, które napotkasz podczas podróży. Kupując lub sprzedając przedmiot, sprzedawca najpierw powie ci, za ile by ci go sprzedał / za który kupiłby od ciebie. Ponieważ pewne produkty mają zagwarantowane określone ceny , możesz użyć tego do nieformalnej identyfikacji określonego rodzaju przedmiotu.

Niektóre przedmioty, takie jak zwój światła , są jedynymi przedmiotami, które kosztują określoną kwotę, co pozwala jednoznacznie je zidentyfikować; jednak większość przedmiotów dzieli grupę cenową z innymi przedmiotami tej samej klasy, co pozwala jedynie zawęzić możliwości (co jest nadal przydatne). Jednak na ceny kupna / sprzedaży przedmiotu wpływa wiele zmiennych (takich jak statystyki charyzmy ). Stąd powyższy wykres.

Czy możesz powiedzieć, że lubię Nethacka?

Wkład

Dane wejściowe zostaną dostarczone jako gra Nethack (waniliowa, 3.4.3):

"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

Oznacza to, że gwarantuje kilka właściwości:

  • Zawsze będzie miał 24 linie.

  • Każda linia zawsze będzie miała 80 znaków lub mniej.

  • Drugi do ostatniej linii będzie składał się z następujących „ żetony «: imię gracza i tytuł (w formie» foo bar ”), wykaz atrybutów (oddzielonych pojedynczym odstępem) i wyrównanie gracza ( Zgodny z prawem, neutralny lub chaotyczny). Każdy token będzie oddzielony zmienną liczbą spacji. 1

  • Lista atrybutów zawsze będzie St:* Dx:* Co:* In:* Wi:* Ch:*, gdzie *postać reprezentuje liczbę całkowitą od 3 do 25. 2 (Punktem zainteresowania jest tutaj ostatnia statystyka, Charyzma, którą musisz obliczyć ceny).

  • Pierwszy wiersz zawsze będzie składał się z komunikatu związanego ze sklepem (w szczególności komunikatu wyświetlanego podczas zakupu lub sprzedaży produktu). Co więcej, ten przedmiot to z pewnością pojedynczy, niezidentyfikowany, nienazwany zwój. W przypadku zakupu przedmiotu jest to:

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

    a do sprzedaży jest to:

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

    gdzie wymienione „zmienne” {curly braces}są następujące:

    • {TITLE}jest zawsze jednym z „ dobrych ”, „ uhonorowanych ”, „ najbardziej łaskawych ” lub „ szanowanych ”, połączonych z „ damą ” lub „ panem ”.

    • {PRICE} jest zawsze liczbą całkowitą.

    • {LABEL}zawsze będzie jednym z następujących ( źródło ):

      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}zawsze będzie jednym z następujących ( źródło ):

      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
      

    Ta wiadomość może być podzielona na inną linię (ale nigdy nie zajmie więcej niż 2 linii). 3)

  • Oprócz kilku pierwszych linii wszystkie zakłady są wyłączone, jak wygląda reszta ekranu. Nethack używa większości zestawu znaków ASCII . Jedyną rzeczą, którą możesz bezpiecznie założyć, jest to, że dane wejściowe będą miały czysto ASCII (jednak prawdopodobnie nie będzie to miało znaczenia, ponieważ i tak możesz odrzucić linie 3-22).

Jeśli dane wejściowe są traktowane jako argument funkcji, zostaną podane dokładnie tak, jak pokazano w powyższym przykładzie (oddzielone znakiem nowej linii). Jeśli wprowadzisz przez STDIN, zostanie podany jako 24 kolejne wiersze wprowadzania (ponownie, jak pokazano powyżej). Możesz wybrać, czy chcesz, aby wejście miało końcowy znak nowej linii, czy nie. Na wejściu gwarantuje się brak spacji końcowych.

Wydajność

Dane wyjściowe powinny być dostarczane jako #nameprzewijany przeze mnie identyfikator ceny. System nazw, z którego korzystam (i który widziałem, że inni używają) to:

  • Jeśli zwój jest jednoznacznie zidentyfikowany jako pewien zwój (identyfikacja, światło, zaklęcie broni), #nameto on. Jest tak w przypadku zwojów następujących cen bazowych (poniżej zobaczysz, jak obliczyć cenę bazową): 20 -> identyfikacja, 50 -> lekka, 60 -> zaczarowana broń.

  • W przeciwnym razie weź pierwsze trzy litery wyglądu zwoju lub pierwsze słowo, jeśli ma mniej niż 3 znaki. Na przykład ZELGO MERstaje się ZEL, VE FORBRYDERNEstaje się VEitp. Połącz z tym (spacją, a następnie) cenę bazową zwoju. Na przykład ELB 300.

  • Jeśli cena podstawowa może być jedną z dwóch możliwości, zwykle próbuję kupić lub sprzedać przedmiot, dopóki nie otrzymam oferowanej ceny, która jednoznacznie umieści go w określonym przedziale cenowym. Jednak nie możesz tego zrobić w tym wyzwaniu, więc po prostu oddziel dwie możliwe ceny bazowe ukośnikiem ( /). Na przykład HAC 60/80.

Oto wzór na przeliczenie ceny bazowej przedmiotu na cenę, jaką oferuje się za jego zakup:

  • zacznij od ceny bazowej produktu

  • prawdopodobieństwo możliwej 33% „niezidentyfikowanej dopłaty”, obliczonej przez price += price / 3

  • kolejna szansa na 33% „znacznika przyssawki” (tak naprawdę nie jest to przypadkowa szansa, ale na potrzeby tego wyzwania jest), obliczona w ten sam sposób

  • modyfikator charyzmy, który stosuje się w następujący sposób:

    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
    

A oto wzór na cenę bazową -> cena sprzedaży:

  • zacznij od ceny bazowej produktu

  • podziel to przez 2 lub 3 (odpowiednio „normalne” lub „znaczniki przyssawki”; ponownie, nie losowe, ale jest to na potrzeby tego wyzwania)

  • szansa na dalsze 25% zmniejszenie 4 , obliczone przezprice -= price / 4

Podział jest podziałem całkowitym, co oznacza, że ​​wynik na każdym kroku jest zaokrąglany w dół. (Źródło: wiki i trochę kopania kodu źródłowego. Odwracanie tych formuł to twoje zadanie.)

Wreszcie, oto poręczny, elegancki wykres ASCII, który pokazuje możliwe ceny zakupu (pogrupowane według statystyki Charisma) i ceny sprzedaży zwoju z określoną ceną bazową:

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

(Jest to identyczne z wykresem na wiki z wyjątkiem tego, że zawiera wszystkie możliwe ceny sprzedaży, podczas gdy wykres wiki nie uwzględnia dwóch z czterech możliwych cen sprzedaży. Nie, nie utworzyłem ręcznie tego wykresu; wygenerowany za pomocą tego skryptu Ruby .)

Przypadki testowe

Wkład:

"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

Wydajność: LEP 60/80


Wkład:

"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

Wydajność: enchant weapon


Wkład:

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

Wydajność: GAR 300


Wkład:

"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

Wydajność: VE 100


Wkład:

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

Wydajność: identify

(Musiałem ręcznie skompilować Nethacka z usuniętymi wszystkimi innymi nazwiskami sprzedawców, ponieważ nie mogłem znaleźć sprzedawcy, który miałby spację w jego imieniu ...)

Zasady


1: nie zawsze jest to prawdą podczas gry Nethack, ale zakładamy to ze względu na prostotę.

2: znowu, nie zawsze prawda. Siła może wynosić od 18/01 do 18 / **, ale nie musisz sobie z tym poradzić.

3: więcej uproszczeń brutto. Na przykład sprzedawca może nazywać cię „szumowiną” lub „najbardziej znanym i świętym stworzeniem”, ale nie musisz sobie z tym poradzić.

4: który inteligentny gracz porusza się, wielokrotnie oferując sprzedaż przedmiotu, dopóki nie otrzyma wyższej ceny.

Klamka
źródło
15
Święta ściana tekstu!
orlp

Odpowiedzi:

10

JavaScript (ES6), 1610 724 601 612 419 405 bajtów

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

Duża ściana tekstu, spotykaj dużą ścianę kodu.

Nie golfił

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

Przykład

usandfriends
źródło
1
To jeden wielki skrypt.
Fatalize
1
Woah, ktoś w końcu na to odpowiedział? Nicea: D
Klamka
@Doorknob Chciałem to zaktualizować przez jakiś czas, w końcu się do tego zabrałem.
usandfriends