Example #1
0
        /// <summary>
        /// sx, sy - rozmiar stolu (sx zawsze parzyste)
        /// px, py - polozenie kuli
        /// wx, wy - wektor ruchu/uderzenia
        /// </summary>
        /// <param name="sx"></param>
        /// <param name="sy"></param>
        /// <param name="px"></param>
        /// <param name="py"></param>
        /// <param name="wx"></param>
        /// <param name="wy"></param>
        /// <returns></returns>
        public Pocket CheckPocket(int sx, int sy, int px, int py, int wx, int wy)
        {
            //od razu w luzie
            if (IsMeshPoint(sx, sy, px, py))
            {
                return(SpecifyPocket(sx, sy, px, py));
            }

            //bez ruchu
            if ((wx == 0) && (wy == 0))
            {
                return(Pocket.NIE);
            }

            //przypadki poziome
            if (wy == 0)
            {
                return(GetHorizontalPocket(sx, sy, px, py, wx));
            }

            //przypadki pionowe
            if (wx == 0)
            {
                return(GetVerticalPocket(sx, px, wy));
            }

            //i pozostale, liczone dla rucho w prawo do gory, inne warianty trzeba przeksztalcic

            //jezeli ruch w lewo to odbijamy stol wzgledem srodka
            bool tablefilppedvertical   = (wx < 0);
            bool tableflippedhorizontal = (wy < 0);

            if (tablefilppedvertical)
            {
                FlipVertical(sx, ref px, ref wx);
            }
            if (tableflippedhorizontal)
            {
                FlipHorizontal(sy, ref py, ref wy);
            }

            //przeskalowanie wektora do najmniejszego mozliwego
            int wgcd = (int)NumbersTheory.GCDBinary(wx, wy);

            wx /= wgcd;
            wy /= wgcd;

            long a, b, c;

            a = (sx / 2) * wy;
            b = wx * py - wy * px;
            c = sy * wx;
            long n, m, p, q;

            n = a / c;
            m = NumbersTheory.Mod(a, c);
            p = b / c;
            q = NumbersTheory.Mod(b, c);

            //analizowane 4 przypadki A/C i B/C
            bool found = true;
            long coefa = 0;

            if ((m == 0) && (q == 0))
            {
                //t > 0 -> a > px/w
                coefa = px / (sx / 2) + 1;
            }
            else if ((m == 0) && (q != 0))
            {
                found = false;
            }
            else if ((m != 0) && (q == 0))
            {
                coefa = c / NumbersTheory.GCDBinary(m, c);
            }
            else if ((m != 0) && (q != 0))
            {
                long l, k;
                long d = NumbersTheory.GCDExt(m, c, out l, out k);
                if (-q % d == 0)
                {
                    long x0 = NumbersTheory.Mod(l * (-q / d), c);
                    coefa = x0;
                    for (long i = 1; i < d; i++) //zgodnie z alg z Cormena powinno byc od 0, ale element 0 jest obliczony wczesniej
                    {
                        long xx = NumbersTheory.Mod(x0 + i * (c / d), c);
                        if (xx < coefa)
                        {
                            coefa = xx;
                        }
                    }
                }
                else
                {
                    found = false;
                }
            }
            //ustalenie punktu kratowego i luzy
            Pocket res = Pocket.NIE;

            if (found)
            {
                long t  = (coefa * (sx / 2) - px) / wx;
                long rx = px + t * wx;
                long ry = py + t * wy;
                if (IsMeshPoint(sx, sy, rx, ry))
                {
                    res = SpecifyPocket(sx, sy, rx, ry);
                }
            }


            //korekta wyniku jezeli stol byl odbijany
            if (tablefilppedvertical)   //ruch byl w lewo - stol byl odbity pionowo -> zamieniamy luzy lewe z prawymi
            {
                res = BackflipVertical(res);
            }
            if (tableflippedhorizontal) //ruch byl w dol - stol odbity poziomo -> zmieniamy luzy gorne i dolne
            {
                res = BackflipHorizontal(res);
            }

            return(res);
        }