ローグライクライトアップ


14

ボードが与えられたら、最短のプログラムまたは関数を記述して、プレーヤーの視界に入っているキャラクターを表示または返します。視力を妨げるキャラクターと交差することなく、キャラクターとプレイヤーの間に線を引くことができる場合、キャラクターは見えます。

入力:

  • @プレイヤーの位置を表します。入力にはこれらの1つだけがあります。
  • 正規表現に一致するキャラクターは[#A-Z]視力をブロックします。
  • 一致[ a-z]するすべてのキャラクターが視覚を許可します。
  • 無効な文字はありません
  • 長方形の入力が保証されます

行は次のように定義されます。

  • ベクトルを大きさと方向に定義する
  • 方向は、N、NE、E、SE、S、SW、W、NWのいずれかです。
  • 大きさは、その方向に沿って数える文字数です
  • 初期ベクトルをd 1と呼びます。2番目のベクトルはd 2と呼ばれます
  • d 1またはd 2のいずれかは、次の大きさでなければなりません1。もう一方はどんな大きさでも構いません
  • d 1の方向はd 2の方向に隣接している必要があります(例:NおよびNE)

行は、d 1、次にd 2、d 1、d 2 ...を適用することによってマークされたパスに沿ったすべての文字であると定義されます。

サンプルライン(.sで指定):
d 1 =(大きさ:4、方向:E)
d 2 =(大きさ:1、方向NE)

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

出力:

  • 適切な位置に表示される各文字は、.スペースの代わりになります。
  • 各非表示文字のスペース。

サンプル入力:

@         
    K     
 J        

    L   




         o

対応する出力:

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

サンプル入力:

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

対応する出力:

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

サンプル入力:

  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        

対応する出力:

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

3
OK ...コウモリ、あらゆる種類のファンギ、カビ、ヘビ、レイスでさえも視界を遮りますが、巨大な模倣物、丘のオーク、マストドン、他のあらゆる種類の生物、さらには火の渦はそうではありませんか?
ジョンドヴォルザーク14年

@JanDvorak私は怠け者で、ブロックするために大文字を選びました。トールモンスターとショートモンスターのような並べ替え。どちらを見渡せますか あ、はい。
ジャスティン14年

1
量子力学については知りませんが、コウモリとノームのミイラは簡単な取引かもしれません。ただし、模倣によって事態はさらに複雑になる可能性があります。また、これらの3匹のアリは楽しいかもしれません。北東の大規模な分類されたモンスターのグループは、あなたについて既に知っているかもしれません。うん...それは厄介かもしれません。#3-私のテレポレーションスクロールはどこですか?おっと、それは鎧を破壊しました。
ジョンドヴォルザーク14年

3
興味があるだけの観測が、私は右の「行」のあなたの定義を理解している場合でも、表示されませんいくつかの正方形があるように、それが見えずに障害物が。たとえば、プレーヤーが(0、0)にいる場合、(5、12)の正方形にはどの線でも到達できません。たとえば、任意の2点間の線を引くためにBresenhamの線アルゴリズムの標準的な実装を指定し、正方形とプレーヤーとの間の線が障害物と交差する場合は不明瞭な正方形を定義する方が理にかなっているかもしれません。
イルマリカロネン14年

1
@IlmariKaronenあなたは絶対に正しいです。それは私が好きな方法です。:-)。
ジャスティン14年

回答:


5

GolfScript、171文字

.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*

入力はSTDINで提供する必要があります。

上記の例の出力はわずかに異なります。私は手で応答を確認し、それらが正しいと思います。

例1:

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

例2:

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

例3:

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

これは、単一行の入力(有効な四角形...)では機能していないようです
ジャスティン14年

@Quincunxこのコードは、入力を改行で確定することを前提としています。またはn+、コードの先頭に追加します。
ハワード14年

4

Ruby-510文字

かなりマンモス。しかし、それはゴルフへの私の初めての試みです。

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

入力は、引数として指定されたファイルによるものです。入力ファイルは、長方形の文字ブロック(つまり、末尾のスペースが含まれる)で構成され、末尾に改行があると想定しています。

このバージョンは、catch-throw深いループを終了するために広範囲に使用します。代わりに、境界チェックループを使用して問題を改善できます。

難読化されていないコード:

# 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

編集

Ilmari Karonenは質問のコメントで、障害物がない場合でも、与えられたビジョンアルゴリズムはすべての正方形を見るわけではないと述べています。これは、プレーヤーから(40,40)離れたところのデモです。

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

うーん。これはテスト3に失敗します。デバッグが必要です。
チャウレット14年

本気ですか?私は...ミスを犯したかもしれない
ジャスティン・

確かに-壁の後ろにVが見えます!前の行の後に改行を検出していないと思います。
チャウレット14年

確かにそれを見てすべきではありません...
ジャスティン

ああ、それは私の入力に問題がありました。後に余分なスペースがありましたXqQ。それは、少なくとも上部に余分なラインを持っている、との間に一つだけのスペース-それは3のために、あなたの与えられた答えは、すべてのテストケースと一致していない、と述べたOl
チャウレット14年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.