using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Verse; namespace Rimworld_Animations { public class GroupAnimationContext { public int priority = 0; public List whitelist; public List blacklist; /* public virtual bool CanAnimationBeUsed(List actors) { if (!whitelist.NullOrEmpty()) { for (int i = 0; i < whitelist.Count; i++) { // check whitelist to make sure pawn can be in this act //for each whitelist item, pawntest must hold true for that pawn if (!whitelist[i].PawnTest(actors[i])) { return false; } } } if (!blacklist.NullOrEmpty()) { for (int i = 0; i < blacklist.Count; i++) { // check blacklist to make sure pawn can be in this act // for each blacklist item, pawntest must hold false for that pawn if (blacklist[i].PawnTest(actors[i])) { return false; } } } return true; } */ /* public List FindWorkingPermutation(List pawns, int index = 0) { //can't play anim for empty list of pawns if (pawns.Count == 0) return null; //pawns list doesn't match number in whitelist if (index == 0 && pawns.Count != whitelist.Count) return null; //if list only has one pawn and it works for that index, return it if (pawns.Count == 1) { return CanAnimationBeUsedFor(pawns[0], index) ? pawns : null; } for (int i = 0; i < pawns.Count; i++) { if (CanAnimationBeUsedFor(pawns[i], index)) { //remove the pawn that we know works for that context List smallerSubset = pawns.Where((item, idx) => idx != i).ToList(); //try to find a working subset for the next indices List newWorkingSubset = FindWorkingPermutation(smallerSubset, index + 1); if (newWorkingSubset != null) { newWorkingSubset.Insert(0, pawns[i]); return newWorkingSubset; } } } return null; } */ public List FindAnyWorkingSet(List actors) { if (actors.Count != whitelist.Count) return null; int numActors = actors.Count; Dictionary> validPawnContexts = new Dictionary>(); for (int i = 0; i < numActors; i++) { validPawnContexts[i] = new List(); for (int j = 0; j < numActors; j++) { if (CanAnimationBeUsedFor(actors[i], j)) { //give a list of all pawn's valid potential spots validPawnContexts[i].Add(j); } } } //set all spots as empty (-1) int[] indexAssignedToPawn = Enumerable.Repeat(-1, numActors).ToArray(); for (int i = 0; i < numActors; i++) { bool[] visited = new bool[numActors]; //try to fill in each space //try to shove spaces out of the way, get them to look elsewhere if (!DfsMatch(i, visited, indexAssignedToPawn, validPawnContexts)) { return null; } } List actorOrder = new List(); foreach (int actorIndex in indexAssignedToPawn) { actorOrder.Add(actors[actorIndex]); } return actorOrder; } public bool DfsMatch(int pawnIndex, bool[] visited, int[] indexAssignedToPawn, Dictionary> validPawnContexts) { foreach (int index in validPawnContexts[pawnIndex]) { //don't infinte loop if (visited[index]) continue; visited[index] = true; //fill in space or shove something else out of the way if (indexAssignedToPawn[index] == -1 || DfsMatch(indexAssignedToPawn[index], visited, indexAssignedToPawn, validPawnContexts)) { indexAssignedToPawn[index] = pawnIndex; return true; } } return false; } public virtual bool CanAnimationBeUsedFor(Pawn actor, int index) { if (whitelist.NullOrEmpty()) return false; if (index < 0 || index >= whitelist.Count) { return false; } if (!whitelist[index].PawnTest(actor)) { return false; } if (!blacklist.NullOrEmpty() && blacklist[index].PawnTest(actor)) { return false; } return true; } public virtual int AnimationPriority() { return priority; } //cool class for designating contexts for animations // configure CanAnimationBeUsed to test whether it can be used } }