// converge: from two points of differing sign, converge to zero crossing
// Assume sign(v1) = -sign(v2)
Point3D IsoSurfacePolygonizer::converge(const Point3DWithValue &p1, const Point3DWithValue &p2, int itCount) {
#ifdef _DEBUG
  if(p1.m_positive == p2.m_positive) {
    throwInvalidArgumentException(__TFUNCTION__,_T("%s has same sign as %s")
                                 ,p1.toString().cstr(), p2.toString().cstr());
  }
#endif // _DEBUG
  Point3DWithValue x1, x2;
  if(p1.m_positive) {
    x1 = p1;
    x2 = p2;
  } else {
    x1 = p2;
    x2 = p1;
  }
  for(int i = itCount = max(itCount, RES);;) {
    const Point3D x = x2 - (x2-x1) * (x2.m_value/(x2.m_value-x1.m_value));
    if(i-- == 0) {
      return x;
    }
    const double y = evaluate(x);
    if(y > 0) {
      (x1 = x).setValue(y);
    } else if(y < 0) {
      (x2 = x).setValue(y);
    } else {
      m_statistics.m_zeroHits++;
      return x;
    }
  }
}
void BitSet::throwIndexOutOfRange(const TCHAR *method, size_t index, _In_z_ _Printf_format_string_ TCHAR const * const format, ...) const {
  va_list argptr;
  va_start(argptr, format);
  const String msg = vformat(format, argptr);
  va_end(argptr);
  throwInvalidArgumentException(method, _T("%s:%s"), msg.cstr(), indexOutOfRangeString(index).cstr());
}
BitSet::BitSet(size_t capacity) {
  if(capacity == 0) {
    throwInvalidArgumentException(__TFUNCTION__, _T("Capacity=0"));
  }
  m_capacity = capacity;
  const size_t atomCount = _BS_ATOMCOUNT(m_capacity);
  m_p = new Atom[atomCount]; TRACE_NEW(m_p)
  memset(m_p,0,atomCount * sizeof(Atom));
}
ByteOutputFile::ByteOutputFile(FILE *f) {
  if(f == NULL) {
    throwInvalidArgumentException(__TFUNCTION__, _T("Illegal argument(NULL)"));
  }
  m_file    = f;
  m_oldMode = setFileMode(f, _O_BINARY);

  init(EMPTYSTRING);
}
void Game::setNonCapturingQueen(const Move &m) {
  const FieldInfo &toInfo = s_fieldInfo[m.m_to];

  switch(m.m_direction) {
  case MD_LEFT     :
    LDAwalkLeft(            toInfo, m.m_from);
    LDAenterColumn(         toInfo);
    LDAenterDiag12(         toInfo);
    break;

  case MD_RIGHT    :
    LDAwalkRight(           toInfo, m.m_from);
    LDAenterColumn(         toInfo);
    LDAenterDiag12(         toInfo);
    break;

  case MD_DOWN     :
    LDAwalkDown(            toInfo, m.m_from);
    LDAenterRow(            toInfo);
    LDAenterDiag12(         toInfo);
    break;

  case MD_UP       :
    LDAwalkUp(              toInfo, m.m_from);
    LDAenterRow(            toInfo);
    LDAenterDiag12(         toInfo);
    break;

  case MD_DOWNDIAG1:
    LDAwalkDownDiag1(       toInfo, m.m_from);
    LDAenterRC(             toInfo);
    LDAenterDiag2(          toInfo);
    break;

  case MD_UPDIAG1  :
    LDAwalkUpDiag1(         toInfo, m.m_from);
    LDAenterRC(             toInfo);
    LDAenterDiag2(          toInfo);
    break;

  case MD_DOWNDIAG2:
    LDAwalkDownDiag2(       toInfo, m.m_from);
    LDAenterRC(             toInfo);
    LDAenterDiag1(          toInfo);
    break;

  case MD_UPDIAG2  :
    LDAwalkUpDiag2(         toInfo, m.m_from);
    LDAenterRC(             toInfo);
    LDAenterDiag1(          toInfo);
    break;

  default:
    throwInvalidArgumentException(__TFUNCTION__, _T("m.direction=%d"), m.m_direction);
  }
}
DoubleInterval CSliderCtrlWithTransformation::stepsToToInterval(UINT steps) {
  DEFINEMETHODNAME;
  if (steps < 2 || steps > 10000) {
    throwInvalidArgumentException(method, _T("steps=%u, must be in range [2..10000]"), steps);
  }
  const int minRange = 0;
  const int maxRange = steps-1;
  SetRange(minRange, maxRange);
  return DoubleInterval(minRange, maxRange);
}
Exemple #7
0
PSLQ::PSLQ(const BigRealVector &x, int digits, int verbose, double gamma) {
  if(gamma <= m_minGamma) {
    throwInvalidArgumentException(__TFUNCTION__,_T("gamma=%.16lf. Must be > %.16lf"),gamma,m_minGamma);
  }

  m_verbose = verbose;
  m_x       = x;
  m_gamma   = gamma;
  m_n       = (int)x.getDimension();
  m_digits  = digits ? digits : findPrecision(x);
  m_x.setPrecision(m_digits);
}
AbstractAxisPainter *SystemPainter::createAxisPainter(bool xAxis, AxisType type) {
  AbstractAxisPainter *result;
  switch(type) {
  case AXIS_LINEAR             : result = new LinearAxisPainter(            *this, xAxis); break;
  case AXIS_LOGARITHMIC        : result = new LogarithmicAxisPainter(       *this, xAxis); break;
  case AXIS_NORMAL_DISTRIBUTION: result = new NormalDistributionAxisPainter(*this, xAxis); break;
  case AXIS_DATE               : result = new DateAxisPainter(              *this, xAxis); break;
  default                      : throwInvalidArgumentException(__TFUNCTION__,_T("type (=%d)"),type);
                                 return NULL;
  }
  TRACE_NEW(result);
  return result;
}
BOOL CEditListNumericEditor::Create(CWnd *parent, int id, UINT flags, DoubleInterval *legalInterval) {
  DEFINEMETHODNAME;
  const CRect r(10,10,20,20);
  const BOOL ok = CEdit::Create(WS_CHILD | ES_AUTOHSCROLL | ES_RIGHT, r, parent, id);
  if(ok) {
    SetFont(parent->GetFont());
  }
  m_flags        = flags;
  if(LF_NUM_HASINTERVAL(m_flags) && (legalInterval == NULL)) {
    throwInvalidArgumentException(method, _T("Has Lower- or Upper-limit specified, but no legal interval"));
  }
  const ListFieldType type = LF_GETTYPE(flags);
  m_decimalCount           = LF_NUM_GETDECIMALCOUNT(flags);
  if(m_decimalCount > 0) {
    if(isIntegerType()) {
      throwInvalidArgumentException(method, _T("Field with type %s cannot have decimals"), CTableModel::getListFieldTypeName(type).cstr());
    }
  }

  const DoubleInterval maxInterval = CTableModel::getMaxInterval(type);

  if(legalInterval) {
    m_legalInterval = *legalInterval;
    if(!maxInterval.contains(m_legalInterval)) {
      throwException(_T("Illegal interval for type %s"), CTableModel::getListFieldTypeName(type).cstr());
    }
    if(!(m_flags & LF_NUM_HAS_LOWERLIMIT)) {
      m_legalInterval.setFrom(maxInterval.getFrom());
    }
    if(!(m_flags & LF_NUM_HAS_UPPERLIMIT)) {
      m_legalInterval.setTo(maxInterval.getTo());
    }
  } else {
    m_legalInterval = maxInterval;
  }
  return ok;
}
void CSliderCtrlWithTransformation::setTransformation(DoubleInterval &interval, UINT steps, IntervalScale type) {
  DEFINEMETHODNAME;
  const DoubleInterval toInterval = stepsToToInterval(steps);
  cleanup();
  switch (type) {
  case LINEAR             :
    m_tr = new LinearTransformation(interval, toInterval); TRACE_NEW(m_tr);
    break;
  case LOGARITHMIC        :
    m_tr = new LogarithmicTransformation(interval, toInterval); TRACE_NEW(m_tr);
    break;
  case NORMAL_DISTRIBUTION:
    m_tr = new NormalDistributionTransformation(interval, toInterval); TRACE_NEW(m_tr);
    break;
  default:
    throwInvalidArgumentException(method, _T("type=%d"), type);
  }
}
void BigRational::init(const BigInt &numerator, const BigInt &denominator) {
  DEFINEMETHODNAME;
  if(denominator.isZero()) {
    throwInvalidArgumentException(method, _T("Denominator is zero"));
  }

  DigitPool *pool = getDigitPool();
  if(numerator.isZero()) { // zero always 0/1
    m_numerator   = pool->get0();
    m_denominator = pool->get1();
  } else {
    const BigInt gcd = findGCD(BigInt(fabs(numerator)),BigInt(fabs(denominator)));
    m_numerator   = numerator / gcd;
    m_denominator = denominator / gcd;
    if(denominator.isNegative()) { // Negative numbers are represented with negative numerator and positive denominator
      m_numerator   = -m_numerator;
      m_denominator = -m_denominator;
    }
  }
}
void Game::queenLeaveField(const Move &m) {
  const FieldInfo &fromInfo = s_fieldInfo[m.m_from];

  updateKingDir(m);

  switch(m.m_direction) {
  case MD_LEFT    :   // Leave column and both diagonals
  case MD_RIGHT   :
    LDAleaveColumn(         fromInfo);
    LDAleaveDiag12(         fromInfo);
    break;

  case MD_DOWN    :   // Leave row and both diagonals
  case MD_UP      :
    LDAleaveRow(            fromInfo);
    LDAleaveDiag12(         fromInfo);
    break;

  case MD_UPDIAG1  :  // Leave row, column and diag2
  case MD_DOWNDIAG1:
    LDAleaveRC(             fromInfo);
    LDAleaveDiag2(          fromInfo);
    break;

  case MD_UPDIAG2  :  // Leave row, column and diag1
  case MD_DOWNDIAG2:
    LDAleaveRC(             fromInfo);
    LDAleaveDiag1(          fromInfo);
    break;

  default          :
    throwInvalidArgumentException(__TFUNCTION__, _T("m.direction=%d"), m.m_direction);
  }

  SET_EMPTYFIELD(m.m_from);
}
Exemple #13
0
 void throwArgumentAndBufferExceptions()
 {
     throwInvalidArgumentException();
     throwBufferOverrunException();
 }
void EndGameKeyDefinition5Men2Equal::scanPositions(EndGameKeyWithOccupiedPositions &key, int pIndex, bool allPreviousOnDiag) const {
  switch(pIndex) {
  case 2:
    sym8PositionScanner(key, 2, allPreviousOnDiag, (PositionScanner)&EndGameKeyDefinition5Men2Equal::scanPositions);
    break;
  case 3:
    if(allPreviousOnDiag) {
      for(int i = 0; i < ARRAYSIZE(s_subDiagIndexToPos); i++) {
        const int pos3 = s_subDiagIndexToPos[i];
        if(key.isOccupied(pos3)) continue;
        key.setPosition(3,pos3);
        scanPositions(key, 4, IS_ONMAINDIAG1(pos3));
        key.clearField(pos3);
      }
    } else {
      for(int pos3 = 0; pos3 < 64; pos3++) {
        if(key.isOccupied(pos3)) continue;
        key.setPosition(3,pos3);
        scanPositions(key, 4, false);
        key.clearField(pos3);
      }
    }
    break;
  case 4:
    { const int pos3 = key.getPosition(3);
      if(allPreviousOnDiag) {
        for(int i = 0; i < ARRAYSIZE(s_subDiagIndexToPos); i++) {
          const int pos4 = s_subDiagIndexToPos[i];
          if(key.isOccupied(pos4)) continue;
          if(IS_ONMAINDIAG1(pos4) && (pos4 <= pos3)) continue;
          key.setPosition(4,pos4);
          checkForBothPlayers(key);
          key.clearField(pos4);
        }
      } else if(!key.kingsOnMainDiag1() || !key.p2OnMainDiag1()) {
        for(int pos4 = pos3+1; pos4 < 64; pos4++) {
          if(key.isOccupied(pos4)) continue;
          key.setPosition(4,pos4);
          checkForBothPlayers(key);
          key.clearField(pos4);
        }
      } else { // kings, p2 on maindiag and p3 off maindiag
        const int pi3 = s_offDiagPosToIndex[pos3];
        for(int pi4 = pi3+1; pi4 < ARRAYSIZE(s_offDiagIndexToPos); pi4++) {
          const int pos4 = s_offDiagIndexToPos[pi4];
          if(key.isOccupied(pos4)) continue;

          if(!IS_SAMESIDEMAINDIAG1(pos3, pos4)) {
            if(pi3 > pi4) {
              if(pi3 - 28 > pi4) continue;
            } else {
              if(pi3 > pi4 - 28) continue;
            }
          }
          key.setPosition(4,pos4);
          checkForBothPlayers(key);
          key.clearField(pos4);
        }
      }
    }
    break;

  default:
    throwInvalidArgumentException(__TFUNCTION__, _T("pIndex=%d"), pIndex);
  }
}
void ArrayImpl::indexError(const TCHAR *method, size_t index) const {
  throwInvalidArgumentException(method, _T("Index %s out of range. size=%s")
                               ,format1000(index).cstr()
                               ,format1000(m_size).cstr());
}
void EndGameKeyDefinition6Men3Equal::scanPositions(EndGameKeyWithOccupiedPositions &key, int pIndex, bool allPreviousOnDiag) const {
  switch(pIndex) {
  case 2:
    sym8PositionScanner(key, 2, allPreviousOnDiag, (PositionScanner)&EndGameKeyDefinition6Men3Equal::scanPositions);
    break;
  case 3:
    { for(int pos3 = 0; pos3 < 64; pos3++) { // pos3 = [0..63]
        if(key.isOccupied(pos3)) continue;
        key.setPosition(3,pos3);
        scanPositions(key, 4, allPreviousOnDiag && IS_ONMAINDIAG1(pos3));
        key.clearField(pos3);
      }
    }
    break;
  case 4:
    { const int pos3 = key.getPosition(3);
      if(allPreviousOnDiag) {                // kings, p2,p3 on maindiag, p4 must not be above maindiag
        assert(key.kingsOnMainDiag1() && key.p2OnMainDiag1() && key.p3OnMainDiag1());
        for(int pi4 = 0; pi4 < ARRAYSIZE(s_subDiagIndexToPos); pi4++) {
          const int pos4 = s_subDiagIndexToPos[pi4];
          if(key.isOccupied(pos4)) continue;
          if(IS_ONMAINDIAG1(pos4) && (pos4 <= pos3)) continue;
          key.setPosition(4,pos4);
          scanPositions(key, 5, IS_ONMAINDIAG1(pos4));
          key.clearField(pos4);
        }
      } else if(!key.kingsOnMainDiag1() || !key.p2OnMainDiag1()) {   // kings or p2 off maindiag, p4 = [pos3+1..63]
        for(int pos4 = pos3+1; pos4 < 64; pos4++) {
          if(key.isOccupied(pos4)) continue;
          key.setPosition(4,pos4);
          scanPositions(key, 5, false);
          key.clearField(pos4);
        }
      } else {                               // kings,p2 on maindiag, p3 off maindiag => p4 must be off maindiag and "above" p3
        assert(key.kingsOnMainDiag1() && key.p2OnMainDiag1() && !IS_ONMAINDIAG1(pos3));
        const int pi3 = s_offDiagPosToIndex[pos3];
        for(int pi4 = pi3+1; pi4 < ARRAYSIZE(s_offDiagIndexToPos); pi4++) {
          const int pos4 = s_offDiagIndexToPos[pi4];
          if(key.isOccupied(pos4)) continue;
          if((pi4 >= 28) && (pi4 - 28 >= pi3)) continue;
          key.setPosition(4,pos4);
          scanPositions(key, 5, false);
          key.clearField(pos4);
        }
      }
    }
    break;
  case 5:
    { const int pos4 = key.getPosition(4);
      if(allPreviousOnDiag) {              // kings, p2, p3, p4 on maindag => p5 must not be above maindiag
        assert(key.kingsOnMainDiag1() && key.p2OnMainDiag1() && key.p3OnMainDiag1() && key.p4OnMainDiag1());
        for(int pi5 = 0; pi5 < ARRAYSIZE(s_subDiagIndexToPos); pi5++) {
          const int pos5 = s_subDiagIndexToPos[pi5];
          if(key.isOccupied(pos5)) continue;
          if(IS_ONMAINDIAG1(pos5) && (pos5 <= pos4)) continue;
          key.setPosition(5,pos5);
          checkForBothPlayers(key);
          key.clearField(pos5);
        }
      } else if(!key.kingsOnMainDiag1() || !key.p2OnMainDiag1() ) { // kings or p2 off maindiag => pos5 = [pos4+1..63]
        for(int pos5 = pos4+1; pos5 < 64; pos5++) {
          if(key.isOccupied(pos5)) continue;
          key.setPosition(5,pos5);
          checkForBothPlayers(key);
          key.clearField(pos5);
        }
      } else if(key.p3OnMainDiag1()) {     // kings,p2,p3 on maindiag, p4 below maindiag => p5 must be off maindiag and "above" p4
        assert(IS_BELOWMAINDIAG1(pos4));
        const int pi4 = s_offDiagPosToIndex[pos4];
        for(int pi5 = pi4+1; pi5 < ARRAYSIZE(s_offDiagIndexToPos); pi5++) {
          const int pos5 = s_offDiagIndexToPos[pi5];
          if(key.isOccupied(pos5)) continue;
          if((pi5 >= 28) && (pi5 - 28 < pi4)) continue;
          key.setPosition(5,pos5);
          checkForBothPlayers(key);
          key.clearField(pos5);
        }
      } else {                             // kings,p2 on maindiag, p3 off diag => p5 must be off maindiag and "above" p3 and p4
        assert(key.kingsOnMainDiag1() && key.p2OnMainDiag1() && !key.p3OnMainDiag1());
        const int pos3 = key.getPosition(3);
        const int pi3  = s_offDiagPosToIndex[pos3];
        const int pi4  = s_offDiagPosToIndex[pos4];
        for(int pi5 = 0; pi5 < ARRAYSIZE(s_offDiagIndexToPos); pi5++) {
          const int pos5 = s_offDiagIndexToPos[pi5];
          if(key.isOccupied(pos5)) continue;
          switch(FBOOL3MASK(IS_BELOWMAINDIAG1, pos3, pos4, pos5)) {
          case 0: continue; // none  below  3,4,5 above. skip
          case 1:           // 3     below    4,5 above. => pi3 > max(mirrorDiag1(pi4), mirrorDiag1(pi4)) and
            if(pos5 < pos4) { // Must have pos5 > pos4
              continue;
            }
            if(pi3 <= max(pi4, pi5) - 28) continue;
            break;
          case 2: continue; //   4   below, 3,  5 above. skip
          case 3:           // 3,4   below,     5 above. => pi4 > pi3. must have mirrorDiag1(pi5) <= pi4 (=max(pi3, pi4))
            assert(pi4 > pi3);
            if(pi5 - 28 > pi4) continue;
            break;

          case 4: continue; //     5 below, 3,4   above. skip
          case 5: continue; // 3  ,5 below,   4   above. skip
          case 6: continue; //   4,5 below, 3     above. skip
          case 7:           // 3,4,5 below. Must have pos3 < pos4 < pos5
            if((pos4 <= pos3) || (pos5 <= pos4)) continue;
            break;
          }
          key.setPosition(5,pos5);
          checkForBothPlayers(key);
          key.clearField(pos5);
        }
      }
    }
    break;

  default:
    throwInvalidArgumentException(__TFUNCTION__, _T("pIndex=%d"), pIndex);
  }
}
void EndGameKeyDefinition5Men3Equal::scanPositions(EndGameKeyWithOccupiedPositions &key, int pIndex, bool allPreviousOnDiag) const {
  switch(pIndex) {
  case 2:
    { for(int pos2 = 0; pos2 < 64; pos2++) { // pos2 = [0..63]
        if(key.isOccupied(pos2)) continue;
        key.setPosition(2,pos2);
        scanPositions(key, 3, allPreviousOnDiag && IS_ONMAINDIAG1(pos2));
        key.clearField(pos2);
      }
    }
    break;
  case 3:
    { const int pos2 = key.getPosition(2);
      if(allPreviousOnDiag) {                // kings, p2 on maindiag, p3 must not be above maindiag
        assert(key.kingsOnMainDiag1() && key.p2OnMainDiag1());
        for(int pi3 = 0; pi3 < ARRAYSIZE(s_subDiagIndexToPos); pi3++) {
          const int pos3 = s_subDiagIndexToPos[pi3];
          if(key.isOccupied(pos3)) continue;
          if(IS_ONMAINDIAG1(pos3) && (pos3 <= pos2)) continue;
          key.setPosition(3,pos3);
          scanPositions(key, 4, IS_ONMAINDIAG1(pos3));
          key.clearField(pos3);
        }
      } else if(!key.kingsOnMainDiag1()) {   // kings off maindiag, p3 = [pos2+1..63]
        for(int pos3 = pos2+1; pos3 < 64; pos3++) {
          if(key.isOccupied(pos3)) continue;
          key.setPosition(3,pos3);
          scanPositions(key, 4, false);
          key.clearField(pos3);
        }
      } else {                               // kings on maindiag, p2 off maindiag => p3 must be off maindiag and "above" p2
        assert(key.kingsOnMainDiag1() && !IS_ONMAINDIAG1(pos2));
        const int pi2 = s_offDiagPosToIndex[pos2];
        for(int pi3 = pi2+1; pi3 < ARRAYSIZE(s_offDiagIndexToPos); pi3++) {
          const int pos3 = s_offDiagIndexToPos[pi3];
          if(key.isOccupied(pos3)) continue;
          if((pi3 >= 28) && (pi3 - 28 >= pi2)) continue;
          key.setPosition(3,pos3);
          scanPositions(key, 4, false);
          key.clearField(pos3);
        }
      }
    }
    break;
  case 4:
    { const int pos3 = key.getPosition(3);
      if(allPreviousOnDiag) {              // kings, p2, p3 on maindag => p4 must not be above maindiag
        assert(key.kingsOnMainDiag1() && key.p2OnMainDiag1() && key.p3OnMainDiag1());
        for(int pi4 = 0; pi4 < ARRAYSIZE(s_subDiagIndexToPos); pi4++) {
          const int pos4 = s_subDiagIndexToPos[pi4];
          if(key.isOccupied(pos4)) continue;
          if(IS_ONMAINDIAG1(pos4) && (pos4 <= pos3)) continue;
          key.setPosition(4,pos4);
          checkForBothPlayers(key);
          key.clearField(pos4);
        }
      } else if(!key.kingsOnMainDiag1()) { // kings off maindiag => pos4 = [pos3+1..63]
        for(int pos4 = pos3+1; pos4 < 64; pos4++) {
          if(key.isOccupied(pos4)) continue;
          key.setPosition(4,pos4);
          checkForBothPlayers(key);
          key.clearField(pos4);
        }
      } else if(key.p2OnMainDiag1()) {     // kings,p2 on maindiag, p3 below maindiag => p4 must be off maindiag and "above" p3
        assert(IS_BELOWMAINDIAG1(pos3));
        const int pi3 = s_offDiagPosToIndex[pos3];
        for(int pi4 = pi3+1; pi4 < ARRAYSIZE(s_offDiagIndexToPos); pi4++) {
          const int pos4 = s_offDiagIndexToPos[pi4];
          if(key.isOccupied(pos4)) continue;
          if((pi4 >= 28) && (pi4 - 28 < pi3)) continue;
          key.setPosition(4,pos4);
          checkForBothPlayers(key);
          key.clearField(pos4);
        }
      } else {                             // kings on maindiag, p2,p3 off diag => p4 must be off maindiag and "above" p2 and p3
        assert(key.kingsOnMainDiag1() && !key.p2OnMainDiag1() && !key.p3OnMainDiag1());
        const int pos2 = key.getPosition(2);
        const int pi2  = s_offDiagPosToIndex[pos2];
        const int pi3  = s_offDiagPosToIndex[pos3];
        for(int pi4 = 0; pi4 < ARRAYSIZE(s_offDiagIndexToPos); pi4++) {
          const int pos4 = s_offDiagIndexToPos[pi4];
          if(key.isOccupied(pos4)) continue;
          switch(FBOOL3MASK(IS_BELOWMAINDIAG1, pos2, pos3, pos4)) {
          case 0: continue; // none  below  2,3,4 above. skip
          case 1:           // 2     below    3,4 above. => pi2 > max(mirrorDiag1(pi3), mirrorDiag1(pi4)) and
            if(pos4 < pos3) { // Must have pos4 > pos3
              continue;
            }
            if(pi2 <= max(pi3, pi4) - 28) continue;
            break;
          case 2: continue; //   3   below, 2,  4 above. skip
          case 3:           // 2,3   below,     4 above. => pi3 > pi2. must have mirrorDiag1(pi4) <= pi3 (=max(pi2, pi3))
            assert(pi3 > pi2);
            if(pi4 - 28 > pi3) continue;
            break;

          case 4: continue; //     4 below, 2,3   above. skip
          case 5: continue; // 2  ,4 below,   3   above. skip
          case 6: continue; //   3,4 below, 2     above. skip
          case 7:           // 2,3,4 below. Must have pos2 < pos3 < pos4
            if((pos3 <= pos2) || (pos4 <= pos3)) continue;
            break;
          }
          key.setPosition(4,pos4);
          checkForBothPlayers(key);
          key.clearField(pos4);
        }
      }
    }
    break;

  default:
    throwInvalidArgumentException(__TFUNCTION__, _T("pIndex=%d"), pIndex);
  }
}