* Gradually iterate over all tiles on the map, calling their TileLoopProcs once every TILE_UPDATE_FREQUENCY ticks. */
| 796 | * Gradually iterate over all tiles on the map, calling their TileLoopProcs once every TILE_UPDATE_FREQUENCY ticks. |
| 797 | */ |
| 798 | void RunTileLoop() |
| 799 | { |
| 800 | PerformanceAccumulator framerate(PFE_GL_LANDSCAPE); |
| 801 | |
| 802 | /* The pseudorandom sequence of tiles is generated using a Galois linear feedback |
| 803 | * shift register (LFSR). This allows a deterministic pseudorandom ordering, but |
| 804 | * still with minimal state and fast iteration. */ |
| 805 | |
| 806 | /* Maximal length LFSR feedback terms, from 12-bit (for 64x64 maps) to 24-bit (for 4096x4096 maps). |
| 807 | * Extracted from http://www.ece.cmu.edu/~koopman/lfsr/ */ |
| 808 | static const uint32_t feedbacks[] = { |
| 809 | 0xD8F, 0x1296, 0x2496, 0x4357, 0x8679, 0x1030E, 0x206CD, 0x403FE, 0x807B8, 0x1004B2, 0x2006A8, 0x4004B2, 0x800B87 |
| 810 | }; |
| 811 | static_assert(lengthof(feedbacks) == 2 * MAX_MAP_SIZE_BITS - 2 * MIN_MAP_SIZE_BITS + 1); |
| 812 | const uint32_t feedback = feedbacks[Map::LogX() + Map::LogY() - 2 * MIN_MAP_SIZE_BITS]; |
| 813 | |
| 814 | /* We update every tile every TILE_UPDATE_FREQUENCY ticks, so divide the map size by 2^TILE_UPDATE_FREQUENCY_LOG = TILE_UPDATE_FREQUENCY */ |
| 815 | static_assert(2 * MIN_MAP_SIZE_BITS >= TILE_UPDATE_FREQUENCY_LOG); |
| 816 | uint count = 1 << (Map::LogX() + Map::LogY() - TILE_UPDATE_FREQUENCY_LOG); |
| 817 | |
| 818 | TileIndex tile = _cur_tileloop_tile; |
| 819 | /* The LFSR cannot have a zeroed state. */ |
| 820 | assert(tile != 0); |
| 821 | |
| 822 | /* Manually update tile 0 every TILE_UPDATE_FREQUENCY ticks - the LFSR never iterates over it itself. */ |
| 823 | if (TimerGameTick::counter % TILE_UPDATE_FREQUENCY == 0) { |
| 824 | _tile_type_procs[GetTileType(0)]->tile_loop_proc(TileIndex{}); |
| 825 | count--; |
| 826 | } |
| 827 | |
| 828 | while (count--) { |
| 829 | _tile_type_procs[GetTileType(tile)]->tile_loop_proc(tile); |
| 830 | |
| 831 | /* Get the next tile in sequence using a Galois LFSR. */ |
| 832 | tile = TileIndex{(tile.base() >> 1) ^ (-(int32_t)(tile.base() & 1) & feedback)}; |
| 833 | } |
| 834 | |
| 835 | _cur_tileloop_tile = tile; |
| 836 | } |
| 837 | |
| 838 | void InitializeLandscape() |
| 839 | { |
no test coverage detected