Click here for part I.
- The darkness stencil array mirrors the grid of tiles which make up the view screen graphics.
- The graphics engine determines which tiles are visible vs. hidden/dark based on whether, for each grid coordinate, the darkness stencil array contains $00 (visible) or $01 (dark/hidden).
- The game set the values in the darkness stencil array based on the time of day, by copying preset values in memory into to the darkness stencil array, which in turn tells the graphics engine which tiles not to draw.
Mountains, Walls, Etc.
The preset values used by the game to determine which tiles should be dark/hidden, with regard to the time of day, were calculated by humans in advance. In contrast, terrain/objects like mountains and walls that block line of sight are impractical to anticipate in advance and preset into memory. The computer would run out of memory and my brain would turn to jelly long before the task was complete, and not necessarily in that order.
The reason is because line of sight calculations depend on the position of the object(s) relative to the player. The number of possible screen layouts that exist are exponential. As a result, I found no alternative but to program some extremely rudimentary artificial intelligence into the 'ol Apple II.
First, it should be said that the line of site (LOS) calculation that is done is a very rough one. There are certainly some positions that look a little strange, which we'll try to avoid through map design.
The logical core of the LOS algorithm is centered on the screen being divided into 8 sections, with a specific darkness pattern associate with each section. For each obscuring tile on the screen (mountains, walls, etc) the algorithm determines which of the 8 screen sections the obscuring tile resides in. Conceptually the sections can be labeled, relative to the direction of the obscuring tile to player, Northwest, North, Northeast, East, Southeast, South, Southwest and West.
After the LOS algorithm determines the screen section a given obscuring tile is in, it applies the darkness pattern for that screen section to the tile grid coordinates around the obscuring tile's grid location and copies the results to the darkness stencil array. This process is repeated until each obscuring tile has been evaluated.
Conveniently, the time of day darkness calculation is done before LOS so the results of the LOS calculation override the time of day calculations. Said another way, even if it's day time, the player still can't see over mountains.
Ok, that pretty much wraps this up then, have a nice -
Wait! You said that after the first screen after game launch is drawn, the game scrolls the existing tiles on the screen rather than drawing them all from scratch, except for the screen edges. If that is the case, how do the $00 (visible), and $01 (hidden/dark) flags effect which tiles are visible in the area of the screen that was scrolled?
Great question. There is another array that tracks whether each tile on the grid was $00 (visible) or $01 (hidden) as of the end of the last player move. There are a bunch of calculations going on that consider whether tiles were hidden before but are visible now vs. visible before but hidden now, and therefore whether a few tiles need to be drawn or erased which were scrolled. This gets fairly ugly from a code structure point of view as it's done as the darkness algorithm is running in order to be speed efficient.
If anyone is interesting in taking a deeper dive on any of this let me know. I'm happy to share the charts and diagrams that map out how the LOS does it's calculations in each of the 8 screen sections too.