/// <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); }