feat: Thread-safe FOV system with improved API

Major improvements to the Field of View (FOV) system:

1. Added thread safety with mutex protection
   - Added mutable std::mutex fov_mutex to UIGrid class
   - Protected computeFOV() and isInFOV() with lock_guard
   - Minimal overhead for current single-threaded operation
   - Ready for future multi-threading requirements

2. Enhanced compute_fov() API to return visible cells
   - Changed return type from void to List[Tuple[int, int, bool, bool]]
   - Returns (x, y, visible, discovered) for all visible cells
   - Maintains backward compatibility by still updating internal FOV state
   - Allows FOV queries without affecting entity states

3. Fixed Part 4 tutorial visibility rendering
   - Added required entity.update_visibility() calls after compute_fov()
   - Fixed black grid issue in perspective rendering
   - Updated hallway generation to use L-shaped corridors

The architecture now properly separates concerns while maintaining
performance and preparing for future enhancements. Each entity can
have independent FOV calculations without race conditions.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
John McCardle 2025-07-22 23:00:34 -04:00
commit 7aef412343
4 changed files with 86 additions and 14 deletions

View file

@ -88,7 +88,21 @@ def carve_hallway(x1, y1, x2, y2):
Referenced from cos_level.py lines 184-217, improved with libtcod.line()
"""
# Get all points along the line
points = mcrfpy.libtcod.line(x1, y1, x2, y2)
# Simple solution: works if your characters have diagonal movement
#points = mcrfpy.libtcod.line(x1, y1, x2, y2)
# We don't, so we're going to carve a path with an elbow in it
points = []
if random.choice([True, False]):
# x1,y1 -> x2,y1 -> x2,y2
points.extend(mcrfpy.libtcod.line(x1, y1, x2, y1))
points.extend(mcrfpy.libtcod.line(x2, y1, x2, y2))
else:
# x1,y1 -> x1,y2 -> x2,y2
points.extend(mcrfpy.libtcod.line(x1, y1, x1, y2))
points.extend(mcrfpy.libtcod.line(x1, y2, x2, y2))
# Carve out each point
for x, y in points:
@ -296,4 +310,4 @@ print("Tutorial Part 3 loaded!")
print(f"Generated dungeon with {len(rooms)} rooms")
print(f"Player spawned at ({spawn_x}, {spawn_y})")
print("Walls now block movement!")
print("Use WASD or Arrow keys to explore the dungeon!")
print("Use WASD or Arrow keys to explore the dungeon!")