using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace Babushka.scripts.CSharp.Common.Fight; public class FighterTurn : IEnumerable { private class Node { public required Node next; public required FightWorld.Fighter fighter; } private Node? _currentNode; public FightWorld.Fighter Current => _currentNode?.fighter ?? throw new InvalidOperationException("No current fighter"); public void Next() { Debug.Assert(_currentNode != null, "currentNode!=null"); _currentNode = _currentNode.next; } public FightWorld.Fighter PeekNext() { Debug.Assert(_currentNode != null, "currentNode!=null"); return _currentNode.next.fighter; } public void AddAsLast(FightWorld.Fighter value) { // if first node if (_currentNode == null) { _currentNode = new Node { fighter = value, next = null! }; _currentNode.next = _currentNode; return; } var newNode = new Node { fighter = value, next = _currentNode }; var node = _currentNode; while (node.next != _currentNode) { node = node.next; } node.next = newNode; } public void AddAsNext(FightWorld.Fighter value) { // if first node if (_currentNode == null) { AddAsLast(value); return; } var newNode = new Node { fighter = value, next = _currentNode.next }; _currentNode.next = newNode; } public bool Remove(FightWorld.Fighter value) { if (_currentNode == null) return false; // if only one node if (_currentNode.next == _currentNode) { if (_currentNode.fighter == value) { _currentNode = null; return true; } return false; } var node = _currentNode; do { // next is the fighter to remove if (node.next.fighter == value) { // if removing current, keep current // it will be implicitly deleted by loss of reference on the next Next() call node.next = node.next.next; return true; } node = node.next; } while (node != _currentNode); return false; } /// /// Sets the current one back /// This is an expensive operation, because the entire data structure needs to be circled /// public void SpinBack() { if (_currentNode == null) return; var node = _currentNode; while (node.next != _currentNode) { node = node.next; } _currentNode = node; } public IEnumerator GetEnumerator() { if (_currentNode == null) return Enumerable.Empty().GetEnumerator(); var list = new List(); var n = _currentNode; while (true) { list.Add(n.fighter); if (n.next == _currentNode) break; n = n.next; } return list.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }