Ruby - 510 karakter
Cukup besar; tapi ini adalah percobaan golf saya yang pertama.
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
Input dengan file ditentukan sebagai argumen; Saya menganggap file input terdiri dari blok karakter persegi panjang (jadi, termasuk spasi tambahan), dan memiliki baris baru tambahan.
Versi ini menggunakan ekstensif catch-throwuntuk keluar dari loop mendalam; Saya mungkin dapat memperbaiki masalah dengan batas-memeriksa loop sebagai gantinya.
Kode tidak terotorisasi:
# 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
Edit
Ilmari Karonen mencatat dalam komentar pertanyaan bahwa algoritma penglihatan yang diberikan tidak melihat semua kotak, bahkan ketika tidak ada kendala. Berikut ini adalah demonstrasi dari itu, ke (40,40) jauh dari pemain.
@.......................................
........................................
........................................
........................................
........................................
............ ...........................
.............. ........................
............ ... ..... ...............
.............. ... ..... ...........
............... ... ..... .......
................. ... ..... ...
.................. ... .....
..... . ............ ... .....
..................... ... ...
...... . .............. ...
...... .. .............. ...
....... . ................ ...
....... .. ............. .. ...
....... . ................. ...
........ .. ............... .. ...
........ . ............... ... .
........ .. ................ ..
......... . ................. ...
......... .. ................. ..
....... . . . ................ ...
.......... .. ................... ..
.......... . ................... ..
........ . .. . ..................
........ .. . .. ..................
........... .. .....................
......... . . . ..................
......... .. .. .. .................
......... .. . .. ................
.......... . .. . ................
.......... .. . .. ...............
.......... .. .. .. ..............
.......... . . . .............
........... .. .. .. .............
........... .. . .. ............
........... . .. . ...........