private Dictionary <uint, uint> mAdjacencyMasks; //for memoizing adjacency masks so that the don't need to be recomputed. Key is an inclusion mask, item is its adjacency mask. public KamiPuzzle(ColorArea[] startingAreas, int numberOfColors) { //Here, the areaMasks of base area data correspond to their adjacency. mNumberOfColors = numberOfColors; mOriginalAreaCount = startingAreas.Length; mAdjacencyMasks = new Dictionary <uint, uint>(); //Seed the adjacency dictionary with the info of the starting areas. ColorArea[] initialAreas = new ColorArea[startingAreas.Length]; for (int i = 0; i < startingAreas.Length; i++) { initialAreas[i] = new ColorArea((uint)(1 << i), startingAreas[i].color); mAdjacencyMasks.Add((uint)(1 << i), startingAreas[i].areaMask); } //Generate the initial state. mInitialState = new KamiState(mOriginalAreaCount, mNumberOfColors, initialAreas); Debug.Log($"Puzzle constructed. Number of colors = {mNumberOfColors}, Adjacency Mask count = {mAdjacencyMasks.Count}, Initial State Areas Count = {mInitialState.areas.Length}"); }
/// <summary> /// This method applies the "paintbucket" mechanic of Kami to move the puzzle from one state to another. /// </summary> /// <param name="fromState"></param> /// <param name="paintedArea"></param> /// <param name="paintedColor"></param> /// <returns></returns> private KamiState TransitionState(KamiState fromState, ColorArea paintedArea, int paintedColor) { List <ColorArea> areasToBeMerged = new List <ColorArea>(); List <ColorArea> remainingAreas = new List <ColorArea>(); foreach (ColorArea area in fromState.areas) { if ((TestAdjacency(paintedArea, area) && (area.color == paintedColor)) || (area.areaMask == paintedArea.areaMask)) { //Add the painted area and adjacent areas of the paintedColor; areasToBeMerged.Add(area); } else { remainingAreas.Add(area); } } remainingAreas.Add(MergeAreas(areasToBeMerged, paintedColor)); //Merge the painted area and append it to the list of unpainted areas. return(new KamiState(mOriginalAreaCount, mNumberOfColors, remainingAreas.ToArray())); }
private bool TestAdjacency(ColorArea fromArea, ColorArea toArea) { return((mAdjacencyMasks[fromArea.areaMask] & toArea.areaMask) > 0); //areas are adjacent if A's adjacency mask has overlap with B's area mask. }