Esempio n. 1
0
        /// <summary>
        /// Transforms us into a new macro based on a different click location.
        /// </summary>
        public Macro Transform(Cell clickedCell, Vector3D clickedPoint, Puzzle puzzle, bool mouseMotionReflected)
        {
            Macro m = this.CloneAllButTwists();

            m.SetupMobius(clickedCell, clickedPoint, puzzle, mouseMotionReflected);

            // Did we have an odd number of view reflections?
            bool viewReflected = this.ViewReflected ^ m.ViewReflected;

            Isometry iso1 = new Isometry(m.Mobius, null);
            Isometry iso2 = new Isometry(this.Mobius, null);

            if (viewReflected)
            {
                iso1 = Isometry.ReflectX() * iso1;
            }
            Isometry combined = iso1.Inverse() * iso2;

            foreach (SingleTwist t in this.m_twists)
            {
                // Find the transformed twist data.
                // NOTE: We choose the one which will be closest to the origin after transformation,
                //		 which hopefully won't lead to performance problems.
                //		 I initially just used the first TwistDataForStateCalcs list item,
                //		 but that led to issues because sometimes it would get transformed
                //		 to very near the disk boundary. We'd have run out of cells to
                //		 find the correct closest, and the transformed macros got all messed up.
                TwistData tdOriginal = t.IdentifiedTwistData.TwistDataForStateCalcs
                                       .OrderBy(td => combined.Apply(td.Center).MagSquared())
                                       .First();
                Vector3D  newCenter = combined.Apply(tdOriginal.Center);
                TwistData tdNew     = puzzle.ClosestTwistingCircles(newCenter);

                SingleTwist tClone = t.Clone();
                tClone.IdentifiedTwistData = tdNew.IdentifiedTwistData;

                // If the reverse state of our transformed twist
                // has changed, we may need to reverse the new twist.
                bool reverse = tdOriginal.Reverse ^ tdNew.Reverse;
                if (reverse ^ viewReflected)                    // NOTE: Very similar to code in Renderer.
                {
                    tClone.ReverseTwist();
                }

                m.m_twists.Add(tClone);
            }

            return(m);
        }
Esempio n. 2
0
 public PickInfo(Polygon poly, TwistData twistData)
 {
     Poly      = poly;
     TwistData = twistData;
 }
Esempio n. 3
0
        /// <summary>
        /// Scramble.
        /// </summary>
        /// <param name="numTwists"></param>
        public void Scramble(int numTwists)
        {
            System.Random rand = new System.Random();
            List <IdentifiedTwistData> allTwistData = m_puzzle.AllTwistData;

            if (allTwistData.Count == 0)
            {
                return;
            }

            bool earthquake = m_puzzle.Config.Earthquake;

            for (int i = 0; i < numTwists; i++)
            {
                m_currentTwist = new SingleTwist();
                m_currentTwist.IdentifiedTwistData = allTwistData[rand.Next(allTwistData.Count)];
                m_currentTwist.LeftClick           = rand.Next(2) == 1;

                // Try to avoid repeats of last (suggested by Melinda).
                IdentifiedTwistData last = m_twistHistory.AllTwists.Count == 0 ? null : m_twistHistory.AllTwists.Last().IdentifiedTwistData;
                if (last != null && allTwistData.Count > 2)
                {
                    while (last == m_currentTwist.IdentifiedTwistData)
                    {
                        m_currentTwist.IdentifiedTwistData = allTwistData[rand.Next(allTwistData.Count)];
                    }
                }
                else
                {
                    m_currentTwist.IdentifiedTwistData = allTwistData[rand.Next(allTwistData.Count)];
                }

                TwistData td          = m_currentTwist.IdentifiedTwistData.TwistDataForStateCalcs.First();
                int       numSlices   = td.NumSlices;
                int       randomSlice = rand.Next(numSlices);
                if (!earthquake)
                {
                    randomSlice += 1;
                }
                m_currentTwist.SliceMask = SliceMask.SliceToMask(randomSlice);

                if (earthquake)
                {
                    int       choppedSeg   = m_currentTwist.SliceMask * 2;
                    Vector3D  lookup       = td.Pants.TinyOffset(choppedSeg);
                    Vector3D  reflected    = td.Pants.Hexagon.Segments[choppedSeg].ReflectPoint(lookup);
                    TwistData tdEarthQuake = m_puzzle.ClosestTwistingCircles(reflected);

                    m_currentTwist.IdentifiedTwistDataEarthquake = tdEarthQuake.IdentifiedTwistData;

                    // Fix scrambing here.
                    m_currentTwist.SliceMaskEarthquake = tdEarthQuake.Pants.Closest(reflected) / 2;
                }

                // Apply the twist.
                FinishRotate(updateStatus: false);
            }

            m_twistHistory.Scrambles += numTwists;

            InvalidateAllAndUpdateStatus();
        }