McRogueFace/tests/unit/test_tcod_complete.py
John McCardle 018e73590f feat: Implement FOV enum and layer draw_fov for #114 and #113
Phase 1 - FOV Enum System:
- Create PyFOV.h/cpp with mcrfpy.FOV IntEnum (BASIC, DIAMOND, SHADOW, etc.)
- Add mcrfpy.default_fov module property initialized to FOV.BASIC
- Add grid.fov and grid.fov_radius properties for per-grid defaults
- Remove deprecated module-level FOV_* constants (breaking change)

Phase 2 - Layer Operations:
- Implement ColorLayer.fill_rect(pos, size, color) for rectangle fills
- Implement TileLayer.fill_rect(pos, size, index) for tile rectangle fills
- Implement ColorLayer.draw_fov(source, radius, fov, visible, discovered, unknown)
  to paint FOV-based visibility on color layers using parent grid's TCOD map

The FOV enum uses Python's IntEnum for type safety while maintaining
backward compatibility with integer values. Tests updated to use new API.

Addresses #114 (FOV enum), #113 (layer operations)

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 15:18:10 -05:00

117 lines
No EOL
3.5 KiB
Python

#!/usr/bin/env python3
"""Complete test of TCOD integration features."""
import mcrfpy
import sys
def run_tests():
print("=== TCOD Integration Test Suite ===\n")
# Test 1: Basic Grid Creation
print("Test 1: Grid Creation")
mcrfpy.createScene("tcod_test")
grid = mcrfpy.Grid(grid_x=10, grid_y=10, texture=None, pos=(10, 10), size=(160, 160))
print("✓ Grid created successfully\n")
# Test 2: Grid Point Manipulation
print("Test 2: Grid Point Properties")
# Set all cells as floor
for y in range(10):
for x in range(10):
point = grid.at(x, y)
point.walkable = True
point.transparent = True
# Create walls
walls = [(4, 2), (4, 3), (4, 4), (4, 5), (4, 6), (4, 7)]
for x, y in walls:
point = grid.at(x, y)
point.walkable = False
point.transparent = False
# Verify
assert grid.at(0, 0).walkable == True
assert grid.at(4, 3).walkable == False
print("✓ Grid points configured correctly\n")
# Test 3: Field of View
print("Test 3: Field of View Algorithms")
# Test different algorithms (using new mcrfpy.FOV enum)
algorithms = [
("Basic", mcrfpy.FOV.BASIC),
("Diamond", mcrfpy.FOV.DIAMOND),
("Shadow", mcrfpy.FOV.SHADOW),
("Permissive", mcrfpy.FOV.PERMISSIVE_2),
("Restrictive", mcrfpy.FOV.RESTRICTIVE)
]
for name, algo in algorithms:
grid.compute_fov(2, 5, radius=5, light_walls=True, algorithm=algo)
visible_count = sum(1 for y in range(10) for x in range(10) if grid.is_in_fov(x, y))
print(f" {name}: {visible_count} cells visible")
# Check specific cells
assert grid.is_in_fov(2, 5) == True # Origin always visible
assert grid.is_in_fov(5, 5) == False # Behind wall
print("✓ All FOV algorithms working\n")
# Test 4: Pathfinding
print("Test 4: A* Pathfinding")
# Find path around wall
path = grid.find_path(1, 5, 8, 5)
if path:
print(f" Path found: {len(path)} steps")
print(f" Route: {path[:3]}...{path[-3:]}")
# Verify path goes around wall
assert (4, 5) not in path # Should not go through wall
assert len(path) >= 7 # Should be at least 7 steps (direct would be 7)
else:
print(" ERROR: No path found!")
# Test diagonal movement
path_diag = grid.find_path(0, 0, 9, 9, diagonal_cost=1.41)
path_no_diag = grid.find_path(0, 0, 9, 9, diagonal_cost=0.0)
print(f" With diagonals: {len(path_diag)} steps")
print(f" Without diagonals: {len(path_no_diag)} steps")
assert len(path_diag) < len(path_no_diag) # Diagonal should be shorter
print("✓ Pathfinding working correctly\n")
# Test 5: Edge Cases
print("Test 5: Edge Cases")
# Out of bounds
assert grid.is_in_fov(-1, 0) == False
assert grid.is_in_fov(10, 10) == False
# Invalid path
# Surround a cell completely
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]:
if dx != 0 or dy != 0:
grid.at(5 + dx, 5 + dy).walkable = False
blocked_path = grid.find_path(5, 5, 0, 0)
assert len(blocked_path) == 0 # Should return empty path
print("✓ Edge cases handled properly\n")
print("=== All Tests Passed! ===")
return True
try:
if run_tests():
print("\nPASS")
else:
print("\nFAIL")
except Exception as e:
print(f"\nFAIL: {e}")
import traceback
traceback.print_exc()
sys.exit(0)