Hi. Thanks for the tips.
For the demo it sufficed to compute deltas for the X and Y panning
and only evaluate tiles on those two edges and their neighbors for
lighting. This approach turned out to be very low cost in terms of
CPU cycles and additional code.
To do anything more elaborate I'm sure would require new tricks and
optimizations. When processing a high number of objects in Python
and pygame it becomes immediately clear that one can't get away with
a brute force approach. I agree, big gains are to be had with
hashing, caching, culling, dividing and scheduling workloads,
memoization and and blit call reduction.
I tried a quadtree but my implementation was very slow so I ditched
it. Gummworld2 now uses a spatialhash tailored for pygame rects, and
optionally Gummworld2's geometry classes. I find it a pretty
efficient solution for spatial culling and collision detection.