using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using TMPro; [ExecuteAlways] public class Node : MonoBehaviour { [Range(-1, 1)] [SerializeField] public int Owner = -1; public int Units; public int id; public TMP_Text unitText; public Material materialOwnerSelf, materialOwnerOther, materialOwnerNone, materialHover; public List connected; public bool hovered; private int Nachos = 0; public static Node pressedNode = null; void Awake() { UpdateColor(); } // Start is called once before the first execution of Update after the MonoBehaviour is created void Start() { } private void FixedUpdate() { CalculateNachos(); } void CalculateNachos() { Nachos = CycleFinder.FindLargestCycleAmongNeighbors(this).Count; } // Update is called once per frame void Update() { if (Input.GetMouseButtonDown(0) && hovered) { Debug.Log($"Largest Nacho: {Nachos}"); } unitText.enabled = hovered; unitText.text = Nachos.ToString(); unitText.transform.forward = Camera.main.transform.forward; UpdateColor(); UpdateTransform(); } private void OnValidate() { UpdateColor(); UpdateTransform(); } private void OnDestroy() { GameManager gm = FindFirstObjectByType(); if (gm == null || Application.isPlaying) return; List looseConnections = gm.GetConnections().FindAll(c => c.nodeA == this || c.nodeB == this) ?? new(); foreach (Connection c in looseConnections) { if (c.lineRenderer != null) DestroyImmediate(c.lineRenderer.gameObject); } } public void UpdateTransform() { transform.localPosition = transform.localPosition.normalized * 20f; if (transform.position != Vector3.zero) transform.forward = transform.position; } public void UpdateColor() { Material material = null; int currentPlayer = GameManager.Instance ? GameManager.Instance.currentPlayer : -1; if (hovered) material = materialHover; else if (Owner == -1 || currentPlayer == -1) material = materialOwnerNone; else if (Owner == currentPlayer) material = materialOwnerSelf; else material = materialOwnerOther; transform.GetChild(0).GetComponent().sharedMaterial = material; hovered = false; } } public class CycleFinder { private HashSet allowedNodes; private List bestCycle; private Node centerNode; private int Owner; public CycleFinder(Node center, int owner) { centerNode = center; allowedNodes = new HashSet(center.connected.Where(obj => obj.Owner == owner)); bestCycle = new List(); Owner = owner; } public static List FindLargestCycleAmongNeighbors(Node center) { var finder = new CycleFinder(center, center.Owner); return finder.FindBestCycle(); } private List FindBestCycle() { // Versuche von jedem Nachbarknoten aus einen Zyklus zu finden foreach (var startNode in allowedNodes) { var visited = new HashSet(); var currentPath = new List(); SearchForCycles(startNode, startNode, visited, currentPath); } return bestCycle; } private void SearchForCycles(Node startNode, Node currentNode, HashSet visited, List path) { // Aktuellen Knoten zum Pfad hinzufugen path.Add(currentNode); visited.Add(currentNode); // Durchsuche alle Verbindungen des aktuellen Knotens foreach (var neighbor in currentNode.connected) { // Nur Nachbarn des Zentralknotens sind erlaubt if (!allowedNodes.Contains(neighbor)) continue; // Wenn wir zum Startknoten zuruckgekehrt sind und mindestens 3 Knoten im Pfad haben if (neighbor == startNode && path.Count >= 3) { // Geschlossenen Zyklus gefunden - prufe ob er besser ist if (path.Count > bestCycle.Count) { bestCycle = new List(path); } } // Wenn der Knoten noch nicht besucht wurde, setze die Suche fort else if (!visited.Contains(neighbor)) { SearchForCycles(startNode, neighbor, new HashSet(visited), new List(path)); } } } }