Thắp sáng một Roguelike


14

Đưa ra một bảng, viết chương trình hoặc chức năng ngắn nhất để hiển thị hoặc trả về những nhân vật nào trong tầm nhìn của người chơi. Một nhân vật nằm trong tầm ngắm nếu có thể vẽ một đường thẳng giữa nó và người chơi, mà không vượt qua bất kỳ nhân vật nào cản tầm nhìn.

Đầu vào:

  • @đại diện cho vị trí của người chơi. Sẽ chỉ có một trong số này trong đầu vào.
  • bất kỳ nhân vật phù hợp với [#A-Z]tầm nhìn khối regex .
  • bất kỳ nhân vật phù hợp [ a-z]cho phép tầm nhìn.
  • sẽ không có ký tự không hợp lệ
  • bạn được đảm bảo một đầu vào hình chữ nhật

Các dòng được định nghĩa như sau:

  • định nghĩa vectơ là độ lớn và hướng
  • một hướng là một trong N, NE, E, SE, S, SW, W, NW
  • độ lớn là bao nhiêu ký tự dọc theo hướng đó để đếm
  • để vectơ ban đầu được gọi là d 1 ; vectơ thứ hai được gọi là d 2
  • một trong d 1 hoặc d 2 phải có độ lớn 1; người kia có thể có bất kỳ cường độ nào
  • hướng của d 1 phải liền kề với hướng của d 2 (ví dụ: N và NE)

Một dòng được định nghĩa là tất cả các ký tự dọc theo đường dẫn được đánh dấu bằng cách áp dụng d 1 , sau đó d 2 , d 1 , d 2 ....

Dòng mẫu (được cho bởi .s):
d 1 = (độ lớn: 4, hướng: E)
d 2 = (độ lớn: 1, hướng NE)

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

Đầu ra:

  • mỗi nhân vật nhìn thấy ở đúng vị trí, .thay thế cho không gian.
  • Không gian cho mỗi nhân vật không nhìn thấy.

Đầu vào mẫu:

@         
    K     
 J        

    L   




         o

Đầu ra tương ứng:

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

Đầu vào mẫu:

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

Đầu ra tương ứng:

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

Đầu vào mẫu:

  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        

Đầu ra tương ứng:

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

3
OK ... dơi, tất cả các loại nấm, nấm mốc và rắn và thậm chí cả bầy đàn đều chặn tầm nhìn, nhưng bắt chước khổng lồ, Orc đồi, mastodon, tất cả các loại sinh vật khác hoặc thậm chí là xoáy lửa không?
John Dvorak

@JanDvorak Tôi lười biếng và chọn chữ in hoa để chặn. Sắp xếp giống như quái vật TALL vs quái vật ngắn; mà bạn sẽ có thể nhìn thấy hơn. Vì vậy, có.
Justin

1
Tôi không biết về cơ học lượng tử, nhưng xác ướp và xác ướp có thể là một thỏa thuận dễ dàng. Việc bắt chước có thể làm phức tạp mọi thứ hơn nữa, mặc dù. Ngoài ra, ba con kiến ​​đó có thể rất vui, và nhóm lớn các loại quái vật ở phía đông bắc có thể đã biết về bạn. Vâng ... nó có thể khó chịu. Đối với # 3 - cuộn từ xa của tôi ở đâu? Rất tiếc, đó là phá hủy áo giáp.
John Dvorak

3
Chỉ là một quan sát tò mò, nhưng nếu tôi hiểu định nghĩa của bạn về "đường thẳng", có vẻ như có một số hình vuông sẽ không thể nhìn thấy ngay cả khi không có bất kỳ trở ngại nào. Ví dụ: nếu người chơi ở (0, 0), thì hình vuông tại (5, 12) không thể đạt được bằng bất kỳ dòng nào. Có thể có ý nghĩa hơn khi nói, chỉ định một số triển khai chính tắc của thuật toán đường thẳng của Bresenham để vẽ một đường thẳng giữa hai điểm bất kỳ và xác định một hình vuông là bị che khuất nếu đường giữa nó và người chơi giao nhau với một chướng ngại vật.
Ilmari Karonen

1
@IlmariKaronen Bạn hoàn toàn chính xác. Đó chỉ là cách tôi thích nó. :-).
Justin

Câu trả lời:


5

GolfScript, 171 ký tự

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

Đầu vào phải được cung cấp trên STDIN.

Đầu ra cho các ví dụ đưa ra ở trên là hơi khác nhau. Tôi đã xác minh các câu trả lời bằng tay và nghĩ rằng chúng là chính xác.

Ví dụ 1:

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

Ví dụ 2:

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

Ví dụ 3:

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

Điều này dường như không hoạt động đối với các đầu vào dòng đơn (là hình chữ nhật hợp lệ ...)
Justin

@Quincunx Mã giả định rằng bạn hoàn thành đầu vào của mình bằng một dòng mới. Hoặc thêm vào n+mã.
Howard

4

Ruby - 510 ký tự

Khá là một con voi ma mút; nhưng đó là lần đầu tiên tôi thử chơi gôn.

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

Đầu vào là bởi tệp được chỉ định làm đối số; Tôi giả sử tệp đầu vào bao gồm một khối ký tự hình chữ nhật (vì vậy, bao gồm các khoảng trắng ở cuối) và để có một dòng mới.

Phiên bản này sử dụng rộng rãi catch-throwđể thoát khỏi các vòng lặp sâu; Thay vào đó, tôi có thể cải thiện các vấn đề với các vòng kiểm tra giới hạn.

Mã không được kiểm tra:

# 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

Biên tập

Ilmari Karonen lưu ý trong các câu hỏi nhận xét rằng thuật toán thị giác đã cho không nhìn thấy tất cả các hình vuông, ngay cả khi không có chướng ngại vật. Đây là một minh chứng cho điều đó, cách xa người chơi (40,40).

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

Hừm. Điều này không kiểm tra 3. Cần gỡ lỗi.
Chowlett

bạn có chắc không? Tôi có thể đã phạm sai lầm ...
Justin

Khá chắc chắn - tôi có thể nhìn thấy chữ V phía sau bức tường! Tôi nghĩ rằng tôi không phát hiện ra dòng mới sau dòng trước.
Chowlett

Chắc chắn không nên thấy điều đó ...
Justin

Ah, đó là một vấn đề với đầu vào của tôi; Tôi đã có thêm một không gian sau XqQ. Điều đó nói rằng, câu trả lời cho 3 của bạn hoàn toàn không khớp với testcase - ít nhất nó có một dòng phụ ở trên cùng và chỉ có một khoảng trắng giữa Ol.
Chowlett
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.