5Y5T3M/Assets/Scripts/Node.cs

166 lines
No EOL
4.6 KiB
C#

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<Node> connected;
public bool hovered;
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()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0) && hovered)
{
var count = CycleFinder.FindLargestCycleAmongNeighbors(this);
Debug.Log($"Largest Nacho: {count.Count}");
}
unitText.enabled = hovered;
unitText.text = Units.ToString();
unitText.transform.forward = Camera.main.transform.forward;
UpdateColor();
UpdateTransform();
}
private void OnValidate()
{
UpdateColor();
UpdateTransform();
}
private void OnDestroy()
{
GameManager gm = FindFirstObjectByType<GameManager>();
if (gm == null || Application.isPlaying)
return;
List<Connection> 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<Renderer>().sharedMaterial = material;
hovered = false;
}
}
public class CycleFinder
{
private HashSet<Node> allowedNodes;
private List<Node> bestCycle;
private Node centerNode;
public CycleFinder(Node center)
{
centerNode = center;
allowedNodes = new HashSet<Node>(center.connected);
bestCycle = new List<Node>();
}
public static List<Node> FindLargestCycleAmongNeighbors(Node center)
{
var finder = new CycleFinder(center);
return finder.FindBestCycle();
}
private List<Node> FindBestCycle()
{
// Versuche von jedem Nachbarknoten aus einen Zyklus zu finden
foreach (var startNode in allowedNodes)
{
var visited = new HashSet<Node>();
var currentPath = new List<Node>();
SearchForCycles(startNode, startNode, visited, currentPath);
}
return bestCycle;
}
private void SearchForCycles(Node startNode, Node currentNode, HashSet<Node> visited, List<Node> 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<Node>(path);
}
}
// Wenn der Knoten noch nicht besucht wurde, setze die Suche fort
else if (!visited.Contains(neighbor))
{
SearchForCycles(startNode, neighbor, new HashSet<Node>(visited), new List<Node>(path));
}
}
}
}