@Xecutor - It may well be similar, I'll detail the steps below for the 'final' version I'm using.
@Kyzrati - Thanks for the links, been following along with your blog posts on other subjects as well. I must say you are a very good technical writer in addition to your programming talents. I'm not sure with sound and smell just how detailed a treatment I need as I am only using them for 'alert checks' - waking up a mob AI on successful smell or sound detection or providing a notice to the player.
The steps I'm using to create a low artifact ray cache are:
1) Calculate one octant's worth of floating point rays from offset origin (0.5, 0.5) in steps of A radians, beginning with an axis aligned ray. (I've been using A = pi/720 which yields 180 rays per
quadrant octant, likely an excessive number for small values of R and perhaps a low value for extremely large values of R).
2) For each ray create eight line paths (one per octant) of the desired radius R with the lines having integer point values as offsets from the origin (0,0). Maintain the order (octal axis aligned -> diagonal).
3) Translate the lines into a tree having one node per cell in the field of view. Begin with the root (origin) cell and iterate through the lines created in step 2. For each point in each line, if the point is not already included in the tree, add it as a child of the preceding point's cell.
4) (Optional) Remap the tree into an array format with index offsets as a cpu cache optimization. The cache can be stored externally if desired since for any given values of A and R you will get the same results.
Usage:
Using the cache is simply a matter of walking the tree, skipping children of any blocked nodes. Since you are walking the tree in ray path order, you can easily apply any calculations which require values from both previous and current cells along the path.
Characteristics:
Memory: Each cache contains one node per cell in the fully open (no blocks) field of view. Each node consists of an integer pair representing the relative coordinate value and a reference to each child node. The maximum number of child nodes per node is 8, however it is worth noting that only the root node has that many children. Except for the root node, the maximum number of children is three.
Speed: Each possible cell in the field of view is touched at most once and only once. Except for cells on the circumference, blocked cells will reduce the number of cells checked. I do not believe any faster algorithms exist.
Shape: Low artifact variant of the basic raycasting algorithm (see BASIC in
http://www.roguebasin.com/index.php?title=Comparative_study_of_field_of_view_algorithms_for_2D_grid_based_worlds#Symmetry). Due to the use of floating point rays and axis alignment ordering, many of the artifacts normally associated with ray casting in a roguelike are eliminated. Note that there are some oddities with diagonals especially near a pillar - still working on correcting.
Sometime in the next couple days I'll create a command line Python script to generate the ray caches for given values of A and R which I'll publish along with example tree source for anyone who wants to test this in more detail.