Chessistics/chessistics-engine/Rules/CollisionResolver.cs
Samuel Bouchet a7280b1a5a Overhaul turn mechanics, collision destruction, and visual animations
- New turn order: produce -> transfer -> move -> collision resolution
- Collisions now destroy weaker pieces (status > level > mutual destruction)
  instead of halting the simulation. SimPhase.Collision removed.
- Add piece Level property (all level 1 in proto, prepared for future)
- Production fires every turn (interval concept removed), buffer = Amount
  (default 1, future 2-4), leftovers overwritten each turn
- Transfer tiebreaker: status > level > clockwise direction (alternating
  even/odd turns in y-up coords), replaces distance-to-production
- Demands always accept matching cargo even when already satisfied
- TurnNumber added to all turn events for animation grouping
- Simultaneous animations: produce flash, cargo slide, parallel piece moves
- Camera centering fix + middle-click pan
- GDD updated with new rules + lore section added

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 21:44:12 +02:00

55 lines
1.8 KiB
C#

using Chessistics.Engine.Model;
namespace Chessistics.Engine.Rules;
public static class CollisionResolver
{
/// <summary>
/// Resolves collisions after movement. For each cell with 2+ pieces,
/// the strongest piece survives and destroys the others.
/// Priority: SocialStatus desc → Level desc → mutual destruction on exact tie.
/// </summary>
public static List<(PieceState? Survivor, List<PieceState> Destroyed, Coords Cell)> ResolveCollisions(
IReadOnlyList<PieceState> pieces)
{
var results = new List<(PieceState? Survivor, List<PieceState> Destroyed, Coords Cell)>();
var byCell = new Dictionary<Coords, List<PieceState>>();
foreach (var piece in pieces)
{
if (!byCell.TryGetValue(piece.CurrentCell, out var list))
{
list = [];
byCell[piece.CurrentCell] = list;
}
list.Add(piece);
}
foreach (var (cell, occupants) in byCell)
{
if (occupants.Count < 2) continue;
// Sort by priority: highest status first, then highest level
var sorted = occupants
.OrderByDescending(p => p.SocialStatus)
.ThenByDescending(p => p.Level)
.ToList();
var top = sorted[0];
var second = sorted[1];
// If top two have same status AND same level → mutual destruction
if (top.SocialStatus == second.SocialStatus && top.Level == second.Level)
{
results.Add((null, sorted, cell));
}
else
{
var destroyed = sorted.Skip(1).ToList();
results.Add((top, destroyed, cell));
}
}
return results;
}
}