Roguelike'yi aydınlatın


14

Bir tahta verildiğinde, oynatıcının hangi karakterleri görebileceğini görüntülemek veya döndürmek için en kısa programı veya işlevi yazın. Bir karakter, vizyonu engelleyen karakterleri geçmeden oyuncu ile oyuncu arasında bir çizgi çizmek mümkünse görünür.

Giriş:

  • @oyuncunun pozisyonunu temsil eder. Girişte bunlardan sadece biri olacaktır.
  • normal ifade ile eşleşen herhangi bir karakter [#A-Z]görüşü engeller.
  • eşleşen herhangi bir karakter [ a-z]görmeyi sağlar.
  • geçersiz karakter olmayacak
  • dikdörtgen giriş garantilidir

Satırlar aşağıdaki gibi tanımlanır:

  • vektörü bir büyüklük ve yön olarak tanımlar
  • bir yön N, NE, E, SE, S, SW, W, NW
  • büyüklük bu yönde kaç karakter sayılacağıdır
  • ilk vektör d olarak adlandırılan izin 1 ; ikinci vektör d 2 olarak adlandırılır
  • d bir 1 ya da d 2 arasında bir büyüklüğe sahip olması gerekir 1; diğeri ne büyüklükte olabilir
  • d 1 'in yönü d 2 ' nin yönüne bitişik olmalıdır (örn: N ve NE)

Bir çizgi d uygulanarak işaretlenmiş yol boyunca tüm karakter olarak tanımlanır 1 , daha sonra d 2 , d 1 , d 2 ....

Örnek çizgi ( .s tarafından verilir ):
d 1 = (büyüklük: 4, yön: E)
d 2 = (büyüklük: 1, NE yönü)

               .....
          .....
     .....
@.... 

Çıktı:

  • her görünür karakter doğru konumda, yer .değiştirir.
  • Görünmeyen her karakter için alan.

Örnek giriş:

@         
    K     
 J        

    L   




         o

Karşılık gelen çıktı:

@.........
....K.....
.J.....   
..........
.. .L.....
..  . ....
... .. ...
...  .. ..
...   .  .
....  ..  

Örnek Giriş:

 B###M#  by 
 #Q   # Zmpq
 # # aaa    
@  m #      
# ##P#      
# ####      
# ####      
#M ###      
######      

Karşılık gelen Çıktı:

.B  #M      
.# ..   Z pq
.#.#.aaa..  
@..m.#      
#.##P#      
 .#         
 .#         
 M.         
  #         

Örnek giriş:

  w                 

     O  l   gg  rT  
   QQL      Ag  #b  
   qqqqq         XqQ
 x     V# f@aa      
   Y        aaa     
   uU  E  l TaKK    
  e  dd  FF d opi   
   e       d        

Karşılık gelen çıktı:

   ..........  .....
    ......... ..... 
     O..l...gg..rT  
...QQL......Ag..#b..
...qqqqq.........XqQ
        #.f@aa......
   Y........aaa.....
...uU..E..l.TaKK....
      d..FF.d.op    
     .... .d. ...   

3
Tamam ... yarasalar, her türlü mantar, küf ve yılan ve hatta hayaletler bakış açısını engeller, ama dev mimikler, tepe orkları, mastodonlar, her türlü diğer canlılar ve hatta ateş girdabı değil mi?
John Dvorak

@JanDvorak Tembeltim ve engelleme için büyük harfler seçtim. Kısa canavarlara karşı TALL canavarları gibi; hangisini görebileceksin. Yani evet.
Justin

1
Kuantum mekaniğini bilmiyorum, ama yarasa ve gnome mumya kolay bir anlaşma olabilir. Ancak mimik işleri daha da karmaşıklaştırabilir. Ayrıca, bu üç karınca eğlenceli olabilir ve kuzeydoğudaki çok çeşitli canavarlar sizi zaten biliyor olabilir. Evet ... kötü olabilir. # 3'e gelince - benim teleporasyon kaydırmam nerede? Hata! Zırh yok edildi.
John Dvorak

3
Sadece meraklı bir gözlem, ama “çizgi” tanımını doğru anlarsam, engel olmadan bile görünmeyecek bazı kareler var gibi görünüyor . Örneğin, oynatıcı (0, 0) konumundaysa, (5, 12) üzerindeki kareye herhangi bir satırdan ulaşılamaz. Diyelim ki, Bresenham'ın herhangi iki nokta arasında bir çizgi çizmek için çizgi algoritmasının bazı kanonik uygulamasını belirtmek ve onunla oyuncu arasındaki çizgi bir engelle kesişiyorsa belirsiz bir kareyi tanımlamak daha mantıklı olabilir.
Ilmari Karonen

1
@IlmariKaronen Kesinlikle haklısın. Ben böyle seviyorum. :-).
Justin

Yanıtlar:


5

GolfScript, 171 karakter

.n?):L)[n*.]*1/:I'@'?{\+[{1$+}*]..{I=26,{65+}%"#
"+\?)}??)<}+{[L~.).)1L)L.(-1L~]>2<`{[.[~\]]{1/~2$*+L*.-1%}%\;~}+L,%~}8,%%{|}*`{1$?)I@=.n=@|\.' '={;'.'}*' 'if}+I,,%''*n%n*

Giriş STDIN'de sağlanmalıdır.

Yukarıda verilen örneklerin çıktıları biraz farklıdır. Yanıtları elle doğruladım ve doğru olduklarını düşünüyorum.

Örnek 1:

@.........
....K.....
.J.....   
..........
.. .L.....
..  . ....
... .. ...
...  .. ..
...   .  .
....  ..  

Örnek 2:

.B  #M      
.# ..   Z pq
.#.#.aaa..  
@..m.#      
#.##P#      
 .#         
 .#         
 M.         
  #         

Örnek 3:

   ..........  .....
    ......... ..... 
     O..l...gg..rT  
...QQL......Ag..#b..
...qqqqq.........XqQ
        #.f@aa......
   Y........aaa.....
...uU..E..l.TaKK....
      d..FF.d.op    
     .... .d. ...   

Bu, tek satır girişleri için geçerli görünmüyor (geçerli dikdörtgenler ...)
Justin

@Quincunx Kod, girişinizi bir satırsonu ile sonlandırdığınızı varsayar. Alternatif n+olarak, kodun başına ekleyin .
Howard

4

Yakut - 510 karakter

Oldukça mamut; ama bu benim ilk golf girişimim.

m=$<.read;w,s,o,p=m.index(?\n)+1,m.size,m.dup.gsub(/[^@\n]/,' '),m.index(?@);d=[-w,1-w,1,w+1,w,w-1,-1,-1-w];0.upto(7){|i|x=d[i];[i-1,i+1].each{|j|y=d[j%8];[1,nil].each{|l|t=0;catch(:a){loop{c,f,r=p,1,nil;catch(:b){loop{(l||r)&&(1.upto(t){|u|c+=x;n=!(0...s).include?(c)||m[c]==?\n;n&&throw(f ?:a: :b);o[c]=m[c]==" "??.: m[c];a=m[c]=~/[#A-Z]/;a&&throw(f ?:a: :b)};f=nil);r=1;c+=y;n=!(0...s).include?(c)||m[c]==?\n;n&&throw(f ?:a: :b);o[c]=m[c]==" "??.: m[c];a=m[c]=~/[#A-Z]/;a&&throw(f ?:a: :b)}};t+=1}}}}};$><<o

Girdi, bağımsız değişken olarak belirtilen dosyaya göre yapılır; Giriş dosyasının dikdörtgen bir karakter bloğundan (yani sondaki boşluklar dahil) oluştuğunu ve sondaki bir satırsonu olduğunu varsayıyorum.

Bu sürüm, catch-throwderin döngülerden çıkmak için kapsamlı bir şekilde kullanılır ; Bunun yerine sınır denetimli döngülerle sorunları iyileştirebilirim.

Kesintisiz kod:

# Read the map in
map = $<.read

# Determine its width and size
width = map.index("\n")+1
size = map.size

# Create a blank copy of the map to fill in with visible stuff
output = map.dup.gsub /[^@\n]/,' '

# Locate the player
player = map.index('@')

dirs = [
  -width,   # N
  1-width,  # NE
  1,        # E
  width+1,  # SE
  width,    # S
  width-1,  # SW
  -1,       # W
  -1-width  # NW
]

0.upto(7) do |i1|
  d1 = dirs[i1]
  [i1-1, i1+1].each do |i2|
    d2 = dirs[i2%8]

    # Stepping by 0,1,2... in d1, work along the line.
    # Write the cell value into the duplicate map, then break if it's
    # a "solid" character.
    #
    # Extensive use of catch-throw lets us exit deep loops.

    # For convenience of notation, instead of having either d1 or d2
    # be magnitude 1, and always doing d1,d2,d1... - I have d2 always
    # being magnitude 1, and doing either d1,d2,d1 or d2,d1,d2...

    # Loop twice - first with d1,d2,d1... second with d2,d1,d2...
    [true,false].each do |long_first|
      step = 0

      catch(:all_done) do
        # This loop increments step each iteration, being the magnitude of d1
        loop do
          cell = player
          first = true  # True until we've done the first d1
          later = false # True once we've done the first d2

          catch(:done) do
            # This loop repeatedly applies d1 and d2
            loop do
              if long_first || later  # Don't apply d1 first if starting with d2
                1.upto(step) do |dd1|
                  cell += d1 # Move one cell in d1
                  invalid = !(0...size).include?(cell) || map[cell]=="\n" # Out of range
                  throw :all_done if first && invalid # No point trying a longer step if the
                                                      # first application of d1 is out of range
                  throw :done if invalid # No point continuing with this step length

                  output[cell]=map[cell] == " " ? '.' : map[cell] # Transfer visble character
                  wall = map[cell]=~/[#A-Z]/  # Hit a wall?
                  throw :all_done if first && wall # Drop out as before
                  throw :done if wall
                end
                first = false
              end
              later=true

              # Now repeat above for the single d2 step
              cell += d2
              invalid = !(0...size).include?(cell) || map[cell]=="\n"
              throw :all_done if first && invalid
              throw :done if invalid
              output[cell]=map[cell] == " " ? '.' : map[cell]
              wall = map[cell]=~/[#A-Z]/
              throw :all_done if first && wall
              throw :done if wall
            end
          end
          step += 1
        end
      end
    end
  end
end

puts output

Düzenle

Ilmari Karonen, soruda verilen görme algoritmasının engel olmasa bile tüm kareleri görmediğini belirtti. İşte bir gösteri, oyuncudan (40,40) uzakta.

@.......................................
........................................
........................................
........................................
........................................
............ ...........................
..............  ........................
............ ...   ..... ...............
.............. ...    .....  ...........
...............  ...     .....   .......
.................  ...      .....    ...
..................   ...       .....
..... . ............   ...        .....
.....................    ...         ...
...... . ..............    ...
...... .. ..............     ...
....... . ................     ...
....... .. ............. ..      ...
.......  .  .................      ...
........ .. ............... ..       ...
........  .  ............... ...       .
........  ..  ................ ..
.........  .  ................. ...
.........  ..  .................  ..
....... .   .   . ................ ...
..........  ..  ...................  ..
..........   .   ...................  ..
........ .   ..   . ..................
........ ..   .   .. ..................
...........   ..   .....................
......... .    .    . ..................
......... ..   ..   .. .................
......... ..    .    .. ................
.......... .    ..    . ................
.......... ..    .    .. ...............
.......... ..    ..    .. ..............
..........  .     .     .  .............
........... ..    ..    .. .............
........... ..     .     .. ............
...........  .     ..     .  ...........

Hmm. Bu test 3'te başarısız olur. Hata ayıklama gerekiyor.
Chowlett

Emin misiniz? Bir hata yapabilirdim ...
Justin

Kesinlikle - Duvarın arkasındaki V'yi görebiliyorum! Sanırım bir önceki satırdan sonra yeni satırı tespit etmiyorum.
Chowlett

Kesinlikle bunu görmemeliyiz ...
Justin

Ah, bu benim girişimle ilgili bir problemdi; Sonra fazladan yerim vardı XqQ. En üstündeki ekstra hattı vardır adresten ve arasında yalnızca bir boşluk - dedi ki, 3 için verilen cevabı hiç TestCase uymuyor Ove l.
Chowlett
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.