Exemple #1
0
 template <class XPR> vtab_t eval(const XPR & xxi){
   vtab_t xi =  rowvect(xxi);
   itab_t index = nt2::bsearch (breaks, xi);
   vtab_t val   = coefs(index, 1);
   for(size_t i=2; i <= order; ++i){
     val = mul(colvect(xi-breaks(index)), val) + coefs(index,i);
   }
   val = nt2::reshape(val, size(xxi));
   return val; 
 }
Exemple #2
0
/* Be sure this corresponds with what happens to player-thrown objects in
 * dothrow.c (for consistency). --KAA
 * Returns 0 if object still exists (not destroyed).
 */
static int
drop_throw(struct obj *obj, boolean ohit, int x, int y)
{
    int retvalu = 1;
    int create;
    struct monst *mtmp;
    struct trap *t;

    if (breaks(obj, x, y))
        return 1;

    if (ohit && (is_multigen(obj) || obj->otyp == ROCK))
        create = !rn2(3);
    else
        create = 1;

    if (create &&
        !((mtmp = m_at(level, x, y)) && (mtmp->mtrapped) &&
          (t = t_at(level, x, y)) && (is_pit_trap(t->ttyp)))) {
        int objgone = 0;

        if (down_gate(x, y) != -1)
            objgone = ship_object(obj, x, y, FALSE);
        if (!objgone) {
            if (!flooreffects(obj, x, y, "fall")) {
                /* don't double-dip on damage */
                place_object(obj, level, x, y);
                if (!mtmp && x == u.ux && y == u.uy)
                    mtmp = &youmonst;
                if (mtmp && ohit)
                    passive_obj(mtmp, obj, NULL);
                stackobj(obj);
                retvalu = 0;
            }
        }
    } else
        obfree(obj, NULL);
    return retvalu;
}
static QList<double> _calcJenksBreaks( QList<double> values, int classes,
                                       double minimum, double maximum,
                                       int maximumSize = 1000 )
{
  // Jenks Optimal (Natural Breaks) algorithm
  // Based on the Jenks algorithm from the 'classInt' package available for
  // the R statistical prgramming language, and from Python code from here:
  // http://danieljlewis.org/2010/06/07/jenks-natural-breaks-algorithm-in-python/
  // and is based on a JAVA and Fortran code available here:
  // https://stat.ethz.ch/pipermail/r-sig-geo/2006-March/000811.html

  // Returns class breaks such that classes are internally homogeneous while
  // assuring heterogeneity among classes.

  if ( !values.count() )
    return QList<double>();

  if ( classes <= 1 )
  {
    return QList<double>() << maximum;
  }

  if ( classes >= values.size() )
  {
    return values;
  }

  QVector<double> sample;

  // if we have lots of values, we need to take a random sample
  if ( values.size() > maximumSize )
  {
    // for now, sample at least maximumSize values or a 10% sample, whichever
    // is larger. This will produce a more representative sample for very large
    // layers, but could end up being computationally intensive...

    qsrand( time( 0 ) );

    sample.resize( qMax( maximumSize, values.size() / 10 ) );

    QgsDebugMsg( QString( "natural breaks (jenks) sample size: %1" ).arg( sample.size() ) );
    QgsDebugMsg( QString( "values:%1" ).arg( values.size() ) );

    sample[ 0 ] = minimum;
    sample[ 1 ] = maximum;;
    for ( int i = 2; i < sample.size(); i++ )
    {
      // pick a random integer from 0 to n
      double r = qrand();
      int j = floor( r / RAND_MAX * ( values.size() - 1 ) );
      sample[ i ] = values[ j ];
    }
  }
  else
  {
    sample = values.toVector();
  }

  int n = sample.size();

  // sort the sample values
  qSort( sample );

  QVector< QVector<int> > matrixOne( n + 1 );
  QVector< QVector<double> > matrixTwo( n + 1 );

  for ( int i = 0; i <= n; i++ )
  {
    matrixOne[i].resize( classes + 1 );
    matrixTwo[i].resize( classes + 1 );
  }

  for ( int i = 1; i <= classes; i++ )
  {
    matrixOne[0][i] = 1;
    matrixOne[1][i] = 1;
    matrixTwo[0][i] = 0.0;
    for ( int j = 2; j <= n; j++ )
    {
      matrixTwo[j][i] = std::numeric_limits<double>::max();
    }
  }

  for ( int l = 2; l <= n; l++ )
  {
    double s1 = 0.0;
    double s2 = 0.0;
    int w = 0;

    double v = 0.0;

    for ( int m = 1; m <= l; m++ )
    {
      int i3 = l - m + 1;

      double val = sample[ i3 - 1 ];

      s2 += val * val;
      s1 += val;
      w++;

      v = s2 - ( s1 * s1 ) / ( double ) w;
      int i4 = i3 - 1;
      if ( i4 != 0 )
      {
        for ( int j = 2; j <= classes; j++ )
        {
          if ( matrixTwo[l][j] >= v + matrixTwo[i4][j - 1] )
          {
            matrixOne[l][j] = i4;
            matrixTwo[l][j] = v + matrixTwo[i4][j - 1];
          }
        }
      }
    }
    matrixOne[l][1] = 1;
    matrixTwo[l][1] = v;
  }

  QVector<double> breaks( classes );
  breaks[classes-1] = sample[n-1];

  for ( int j = classes, k = n; j >= 2; j-- )
  {
    int id = matrixOne[k][j] - 1;
    breaks[j - 2] = sample[id];
    k = matrixOne[k][j] - 1;
  }

  return breaks.toList();
} //_calcJenksBreaks
Exemple #4
0
//-------------------------------------------------------------------------------
//
//  checkDictionary       This function handles all processing of characters in
//                        the "dictionary" set. It will determine the appropriate
//                        course of action, and possibly set up a cache in the
//                        process.
//
//-------------------------------------------------------------------------------
int32_t BreakIterator::checkDictionary(int32_t startPos,
                            int32_t endPos,
                            UBool reverse) {
#if 1
	return reverse ? startPos : endPos;
#else
    // Reset the old break cache first.
    uint32_t dictionaryCount = fDictionaryCharCount;
    reset();

    if (dictionaryCount <= 1 || (endPos - startPos) <= 1) {
        return (reverse ? startPos : endPos);
    }
    
    // Starting from the starting point, scan towards the proposed result,
    // looking for the first dictionary character (which may be the one
    // we're on, if we're starting in the middle of a range).
    utext_setNativeIndex(fText, reverse ? endPos : startPos);
    if (reverse) {
        UTEXT_PREVIOUS32(fText);
    }
    
    int32_t rangeStart = startPos;
    int32_t rangeEnd = endPos;

    uint16_t    category;
    int32_t     current;
    UErrorCode  status = U_ZERO_ERROR;
    UStack      breaks(status);
    int32_t     foundBreakCount = 0;
    UChar32     c = utext_current32(fText);

    UTRIE_GET16(&fData->fTrie, c, category);
    
    // Is the character we're starting on a dictionary character? If so, we
    // need to back up to include the entire run; otherwise the results of
    // the break algorithm will differ depending on where we start. Since
    // the result is cached and there is typically a non-dictionary break
    // within a small number of words, there should be little performance impact.
    if (category & 0x4000) {
        if (reverse) {
            do {
                utext_next32(fText);          // TODO:  recast to work directly with postincrement.
                c = utext_current32(fText);
                UTRIE_GET16(&fData->fTrie, c, category);
            } while (c != U_SENTINEL && (category & 0x4000));
            // Back up to the last dictionary character
            rangeEnd = (int32_t)UTEXT_GETNATIVEINDEX(fText);
            if (c == U_SENTINEL) {
                // c = fText->last32();
                //   TODO:  why was this if needed?
                c = UTEXT_PREVIOUS32(fText);
            }
            else {
                c = UTEXT_PREVIOUS32(fText);
            }
        }
        else {
            do {
                c = UTEXT_PREVIOUS32(fText);
                UTRIE_GET16(&fData->fTrie, c, category);
            }
            while (c != U_SENTINEL && (category & 0x4000));
            // Back up to the last dictionary character
            if (c == U_SENTINEL) {
                // c = fText->first32();
                c = utext_current32(fText);
            }
            else {
                utext_next32(fText);
                c = utext_current32(fText);
            }
            rangeStart = (int32_t)UTEXT_GETNATIVEINDEX(fText);;
        }
        UTRIE_GET16(&fData->fTrie, c, category);
    }
    
    // Loop through the text, looking for ranges of dictionary characters.
    // For each span, find the appropriate break engine, and ask it to find
    // any breaks within the span.
    // Note: we always do this in the forward direction, so that the break
    // cache is built in the right order.
    if (reverse) {
        utext_setNativeIndex(fText, rangeStart);
        c = utext_current32(fText);
        UTRIE_GET16(&fData->fTrie, c, category);
    }
    while(U_SUCCESS(status)) {
        while((current = (int32_t)UTEXT_GETNATIVEINDEX(fText)) < rangeEnd && (category & 0x4000) == 0) {
            utext_next32(fText);           // TODO:  tweak for post-increment operation
            c = utext_current32(fText);
            UTRIE_GET16(&fData->fTrie, c, category);
        }
        if (current >= rangeEnd) {
            break;
        }
        
        // We now have a dictionary character. Get the appropriate language object
        // to deal with it.
        const LanguageBreakEngine *lbe = getLanguageBreakEngine(c);
        
        // Ask the language object if there are any breaks. It will leave the text
        // pointer on the other side of its range, ready to search for the next one.
        if (lbe != NULL) {
            foundBreakCount += lbe->findBreaks(fText, rangeStart, rangeEnd, FALSE, fBreakType, breaks);
        }
        
        // Reload the loop variables for the next go-round
        c = utext_current32(fText);
        UTRIE_GET16(&fData->fTrie, c, category);
    }
    
    // If we found breaks, build a new break cache. The first and last entries must
    // be the original starting and ending position.
    if (foundBreakCount > 0) {
        int32_t totalBreaks = foundBreakCount;
        if (startPos < breaks.elementAti(0)) {
            totalBreaks += 1;
        }
        if (endPos > breaks.peeki()) {
            totalBreaks += 1;
        }
        fCachedBreakPositions = (int32_t *)uprv_malloc(totalBreaks * sizeof(int32_t));
        if (fCachedBreakPositions != NULL) {
            int32_t out = 0;
            fNumCachedBreakPositions = totalBreaks;
            if (startPos < breaks.elementAti(0)) {
                fCachedBreakPositions[out++] = startPos;
            }
            for (int32_t i = 0; i < foundBreakCount; ++i) {
                fCachedBreakPositions[out++] = breaks.elementAti(i);
            }
            if (endPos > fCachedBreakPositions[out-1]) {
                fCachedBreakPositions[out] = endPos;
            }
            // If there are breaks, then by definition, we are replacing the original
            // proposed break by one of the breaks we found. Use following() and
            // preceding() to do the work. They should never recurse in this case.
            if (reverse) {
                return preceding(endPos - 1);
            }
            else {
                return following(startPos);
            }
        }
        // If the allocation failed, just fall through to the "no breaks found" case.
    }

    // If we get here, there were no language-based breaks. Set the text pointer
    // to the original proposed break.
    utext_setNativeIndex(fText, reverse ? startPos : endPos);
    return (reverse ? startPos : endPos);
#endif
}
// *****************************************************************
//			GenerateCategories()
// *****************************************************************
vector<CategoriesData>* FieldClassification::GenerateCategories(CString fieldName, FieldType fieldType, 
		vector<VARIANT*>& srcValues, tkClassificationType ClassificationType, 
		long numClasses, long& errorCode)
{
	CComVariant minValue, maxValue;
	minValue.vt = VT_EMPTY;
	maxValue.vt = VT_EMPTY;

	long numShapes = srcValues.size();

	/* we won't define intervals for string values */
	if (ClassificationType != ctUniqueValues && fieldType == STRING_FIELD)
	{
		errorCode = tkNOT_UNIQUE_CLASSIFICATION_FOR_STRINGS;
		return NULL;
	}

	if ((numClasses <= 0 || numClasses > 1000) && (ClassificationType != ctUniqueValues))
	{
		errorCode = tkTOO_MANY_CATEGORIES;
		return NULL;
	}

	if (ClassificationType == ctStandardDeviation)
	{
		errorCode = tkINVALID_PARAMETER_VALUE;
		return NULL;
	}

	// natural breaks aren't designed to work otherwise
	if (numShapes < numClasses && ClassificationType == ctNaturalBreaks)
	{
		numClasses = numShapes;
	}

	// values in specified range should be classified
	bool useRange = minValue.vt != VT_EMPTY && maxValue.vt != VT_EMPTY && fieldType == DOUBLE_FIELD;

	if (useRange) //fieldType == DOUBLE_FIELD)
	{
		double max, min;
		dVal(minValue, min);
		dVal(maxValue, max);
		minValue.vt = VT_R8;
		maxValue.vt = VT_R8;
		minValue.dblVal = min;
		maxValue.dblVal = max;
	}

	//bool useRange = minValue.vt == VT_R8 && maxValue.vt == VT_R8 && fieldType != STRING_FIELD;

	std::vector<CategoriesData>* result = new std::vector<CategoriesData>;
	if (ClassificationType == ctUniqueValues)
	{
		std::set<CComVariant> dict;
		CComVariant val;

		for (long i = 0; i < numShapes; i++)
		{
			VariantCopy(&val, srcValues[i]);
			if (useRange && (val.dblVal < minValue.dblVal || val.dblVal > maxValue.dblVal))
				continue;

			if (dict.find(val) == dict.end())
				dict.insert(val);
		}
		/* creating categories */
		std::vector<CComVariant> values;
		copy(dict.begin(), dict.end(), inserter(values, values.end()));

		for (int i = 0; i < (int)values.size(); i++)
		{
			CategoriesData data;
			data.minValue = values[i];
			data.maxValue = values[i];
			result->push_back(data);
		}
		dict.clear();
		values.clear();
	}
	else if (ClassificationType == ctEqualSumOfValues)
	{
		CComVariant val;

		// sorting the values
		std::vector<double> values;
		double totalSum = 0, dValue;
		for (int i = 0; i < numShapes; i++)
		{
			VariantCopy(&val, srcValues[i]);
			if (useRange && (val.dblVal < minValue.dblVal || val.dblVal > maxValue.dblVal))
				continue;

			dVal(val, dValue); val.Clear();
			values.push_back(dValue);
			totalSum += dValue;
		}
		sort(values.begin(), values.end());

		double step = totalSum / (double)numClasses;
		int index = 1;
		double sum = 0;

		for (int i = 0; i < (int)values.size(); i++)
		{
			sum += values[i];
			if (sum >= step * (double)index || i == numShapes - 1)
			{
				CategoriesData data;

				if (index == numClasses)
					data.maxValue = values[values.size() - 1];
				else if (i != 0)
					data.maxValue = (values[i] + values[i - 1]) / 2;
				else
					data.maxValue = values[0];

				if (index == 1)
					data.minValue = values[0];
				else
					data.minValue = (*result)[result->size() - 1].maxValue;

				result->push_back(data);
				index++;
			}
		}
	}
	else if (ClassificationType == ctEqualIntervals)
	{
		CComVariant vMin, vMax;

		if (useRange)
		{
			vMin = minValue;
			vMax = maxValue;
		}
		else
		{
			GetMinValue(srcValues, vMin, true);
			GetMinValue(srcValues, vMax, false);
		}

		double dMin, dMax;
		dVal(vMin, dMin); dVal(vMax, dMax);
		vMin.Clear(); vMax.Clear();

		/*	creating classes */
		double dStep = (dMax - dMin) / (double)numClasses;
		while (dMin < dMax)
		{
			CategoriesData data;
			data.minValue = dMin;
			data.maxValue = dMin + dStep;
			result->push_back(data);

			dMin += dStep;
		}
	}
	else if (ClassificationType == ctEqualCount)
	{
		CComVariant vMin, vMax;
		if (useRange)
		{
			vMin = minValue;
			vMax = maxValue;
		}
		else
		{
			GetMinValue(srcValues, vMin, true);
			GetMinValue(srcValues, vMax, false);
		}

		double dMin, dMax;
		dVal(vMin, dMin); dVal(vMax, dMax);
		vMin.Clear(); vMax.Clear();

		// sorting the values
		std::vector<double> values;
		for (int i = 0; i < numShapes; i++)
		{
			VariantCopy(&vMin, srcValues[i]);
			dVal(vMin, dMin); vMin.Clear();
			values.push_back(dMin);
		}
		sort(values.begin(), values.end());

		/*	creating classes */
		int i = 0;
		int count = numShapes / numClasses;

		for (int i = 0; i < numShapes; i += count)
		{
			dMin = values[i];
			if (i + count < numShapes)
				dMax = values[i + count];
			else
				dMax = values[numShapes - 1];

			CategoriesData data;
			data.minValue = dMin;
			data.maxValue = dMax;
			result->push_back(data);
		}
		values.clear();
	}
	else if (ClassificationType == ctNaturalBreaks)
	{
		CComVariant vMin; double dMin;
		// sorting the values
		std::vector<double> values;
		for (int i = 0; i < numShapes; i++)
		{
			VariantCopy(&vMin, srcValues[i]);

			if (useRange && (vMin.dblVal < minValue.dblVal || vMin.dblVal > maxValue.dblVal))
				continue;

			dVal(vMin, dMin); vMin.Clear();
			values.push_back(dMin);
		}
		sort(values.begin(), values.end());

		CJenksBreaks breaks(&values, numClasses);
		if (breaks.Initialized())
		{
			breaks.Optimize();
			std::vector<long>* startIndices = breaks.get_Results();
			//std::vector<int>* startIndices = breaks.TestIt(&values, numClasses);

			if (startIndices)
			{
				for (unsigned int i = 0; i < startIndices->size(); i++)
				{
					CategoriesData data;
					data.minValue = values[(*startIndices)[i]];
					if (i == startIndices->size() - 1)
						data.maxValue = values[values.size() - 1];
					else
						data.maxValue = values[(*startIndices)[i + 1]];

					result->push_back(data);
				}
				delete startIndices;
			}
		}
	}
	
	// TODO: implement this as well; then it can be used in table class
	//else if (ClassificationType == ctStandardDeviation)

	// ------------------------------------------------------
	//		generating text expressions
	// ------------------------------------------------------
	if (ClassificationType == ctUniqueValues)
	{
		USES_CONVERSION;
		for (int i = 0; i < (int)result->size(); i++)
		{
			//CString strExpression;
			CString strValue;
			CComVariant* val = &(*result)[i].minValue;
			switch (val->vt)
			{
				case VT_BSTR:
					strValue = OLE2CA(val->bstrVal);
					(*result)[i].name = strValue;
					(*result)[i].expression = "[" + fieldName + "] = \"" + strValue + "\"";
					break;
				case VT_R8:
					strValue.Format("%g", val->dblVal);
					(*result)[i].name = strValue;
					(*result)[i].expression = "[" + fieldName + "] = " + strValue;
					break;
				case VT_I4:
					strValue.Format("%i", val->lVal);
					(*result)[i].name = strValue;
					(*result)[i].expression = "[" + fieldName + "] = " + strValue;
					break;
			}
		}
	}
	else //if (ClassificationType == ctEqualIntervals || ClassificationType == ctEqualCount)
	{
		// in case % is present, we need to put to double it for proper formatting
		fieldName.Replace("%", "%%");

		for (int i = 0; i < (int)result->size(); i++)
		{
			CategoriesData* data = &((*result)[i]);

			CString strExpression, strName, sFormat;

			if (i == 0)
			{
				data->minValue.dblVal = floor(data->minValue.dblVal);
			}
			else if (i == result->size() - 1)
			{
				data->maxValue.dblVal = ceil(data->maxValue.dblVal);
			}

			CString upperBound = (i == result->size() - 1) ? "<=" : "<";

			switch (data->minValue.vt)
			{
				case VT_R8:
					sFormat = "%g";
					data->name = Utility::FormatNumber(data->minValue.dblVal, sFormat) + " - " + Utility::FormatNumber(data->maxValue.dblVal, sFormat);
					data->expression.Format("[" + fieldName + "] >= %f AND [" + fieldName + "] " + upperBound + " %f", data->minValue.dblVal, data->maxValue.dblVal);
					break;
				case VT_I4:
					sFormat = "%i";
					data->name = Utility::FormatNumber(data->minValue.dblVal, sFormat) + " - " + Utility::FormatNumber(data->maxValue.dblVal, sFormat);
					data->expression.Format("[" + fieldName + "] >= %i AND [" + fieldName + "] " + upperBound + " %i", data->minValue.lVal, data->maxValue.lVal);
					break;
			}
		}
	}

	if (result->size() > 0)
	{
		return result;
	}
	else
	{
		delete result;
		return NULL;
	}
}
Exemple #6
0
static void colSums(SWMat<TNumMat> mat, Vec<TNumVec> vec, int nthreads){
	if (mat.ncol != vec.len) throw std::invalid_argument("provided vector has invalid length");

	nthreads = std::max(nthreads, 1);
	
	TNumVec*  cs = vec.ptr;
	const int nrow = mat.nrow;
	const int step = mat.step;
	//in this case the normal colSums is probably faster:
	if (step*4 > nrow){
		colSums<TNumMat, TNumVec, SWMat>(mat, vec, nthreads); return;
	}
	
	const int ncol = mat.ncol;
	const int iold = -step;
	const int inew = nrow - step;
	
	
	//splitting the computation manually for multithreading.
	//Even though it is really hard to think of a case where multithreading here would
	//make any difference...
	std::vector<int> breaks(nthreads + 1);
	double facc = 0, f = ncol/((double)nthreads);
	for (int i = 1; i < nthreads; ++i){ breaks[i] = round(facc); facc += f; }
	breaks[nthreads] = ncol;
	
	
	#pragma omp parallel for schedule(static) num_threads(nthreads)
	for (int chunk = 0; chunk < nthreads; ++chunk){
		int firstcol = breaks[chunk];
		int lastcol = breaks[chunk+1];
		if (lastcol > firstcol){
			//first iteration without recursion
			TNumMat* colValues = mat.colptr(firstcol);
			TNumMat tmp = 0;
			for (int row = 0; row < nrow; ++row){
				tmp += colValues[row];
			}
			cs[firstcol] = tmp;
			//other iterations with recursion
			
			//it would be much more readable to place this if inside the loop,
			//but there is no guarantee that the compiler puts it here
			// (or, even more efficient, before)
			// (or, even more efficient, before)
			if (step == 1){
				for (int col = firstcol + 1; col < lastcol; ++col){ 
					colValues += 1;
					tmp += colValues[inew] - colValues[-1];
					
					cs[col] = tmp;
				}
			} else if (step == 2){
				for (int col = firstcol + 1; col < lastcol; ++col){ 
					colValues += 2; 
					tmp += colValues[inew] + colValues[inew + 1] - colValues[-2] - colValues[-1];
					
					cs[col] = tmp;
				}
			} else {
				for (int col = firstcol + 1; col < lastcol; ++col){
					colValues += step;
					//subtracting old values
					for (int i = iold; i < 0; ++i){ tmp -= colValues[i]; }
					//adding new ones
					for (int i = inew; i < nrow; ++i){ tmp += colValues[i]; }
					
					cs[col] = tmp;
				}
			}
		}
	}
}
Exemple #7
0
/* TRUE iff thrown/kicked/rolled object doesn't pass through iron bars */
boolean
hits_bars(struct obj ** obj_p, /* *obj_p will be set to NULL if object breaks */
          int x, int y, int always_hit, /* caller can force a hit for items
                                           which would fit through */
          int whodidit)
{       /* 1==hero, 0=other, -1==just check whether it'll pass thru */
    struct obj *otmp = *obj_p;
    int obj_type = otmp->otyp;
    boolean hits = always_hit;

    if (!hits)
        switch (otmp->oclass) {
        case WEAPON_CLASS:
            {
                int oskill = objects[obj_type].oc_skill;

                hits = (oskill != -P_BOW && oskill != -P_CROSSBOW &&
                        oskill != -P_DART && oskill != -P_SHURIKEN &&
                        oskill != P_SPEAR && oskill != P_JAVELIN &&
                        oskill != P_KNIFE); /* but not dagger */
                break;
            }
        case ARMOR_CLASS:
            hits = (objects[obj_type].oc_armcat != ARM_GLOVES);
            break;
        case TOOL_CLASS:
            hits = (obj_type != SKELETON_KEY && obj_type != LOCK_PICK &&
                    obj_type != CREDIT_CARD && obj_type != TALLOW_CANDLE &&
                    obj_type != WAX_CANDLE && obj_type != LENSES &&
                    obj_type != TIN_WHISTLE && obj_type != MAGIC_WHISTLE);
            break;
        case ROCK_CLASS:       /* includes boulder */
            if (obj_type != STATUE || mons[otmp->corpsenm].msize > MZ_TINY)
                hits = TRUE;
            break;
        case FOOD_CLASS:
            if (obj_type == CORPSE && mons[otmp->corpsenm].msize > MZ_TINY)
                hits = TRUE;
            else
                hits = (obj_type == MEAT_STICK ||
                        obj_type == HUGE_CHUNK_OF_MEAT);
            break;
        case SPBOOK_CLASS:
        case WAND_CLASS:
        case BALL_CLASS:
        case CHAIN_CLASS:
            hits = TRUE;
            break;
        default:
            break;
        }

    if (hits && whodidit != -1) {
        if (whodidit ? hero_breaks(otmp, x, y, FALSE) : breaks(otmp, x, y))
            *obj_p = otmp = 0;  /* object is now gone */
        /* breakage makes its own noises */
        else if (obj_type == BOULDER || obj_type == HEAVY_IRON_BALL)
            pline("Whang!");
        else if (otmp->oclass == COIN_CLASS ||
                 objects[obj_type].oc_material == GOLD ||
                 objects[obj_type].oc_material == SILVER)
            pline("Clink!");
        else
            pline("Clonk!");
    }

    return hits;
}
Exemple #8
0
/* returns number of scattered objects */
long
scatter(int sx, int sy, /* location of objects to scatter */
        int blastforce, /* force behind the scattering */
        unsigned int scflags, struct obj *obj)
{   /* only scatter this obj */
    struct obj *otmp;
    struct level *lev = obj ? obj->olev : level;
    int tmp;
    int farthest = 0;
    uchar typ;
    long qtmp;
    boolean used_up;
    boolean individual_object = obj ? TRUE : FALSE;
    struct monst *mtmp;
    struct scatter_chain *stmp, *stmp2 = 0;
    struct scatter_chain *schain = NULL;
    long total = 0L;
    boolean visible = (lev == level && cansee(sx, sy));

    while ((otmp = individual_object ? obj : lev->objects[sx][sy]) != 0) {
        if (otmp->quan > 1L) {
            qtmp = otmp->quan - 1;
            if (qtmp > LARGEST_INT)
                qtmp = LARGEST_INT;
            qtmp = (long)rnd((int)qtmp);
            otmp = splitobj(otmp, qtmp);
        } else {
            obj = NULL; /* all used */
        }
        obj_extract_self(otmp);
        used_up = FALSE;

        /* 9 in 10 chance of fracturing boulders or statues */
        if ((scflags & MAY_FRACTURE)
                && ((otmp->otyp == BOULDER) || (otmp->otyp == STATUE))
                && rn2(10)) {
            if (otmp->otyp == BOULDER) {
                if (visible)
                    pline("%s apart.", Tobjnam(otmp, "break"));
                fracture_rock(otmp);
                place_object(otmp, lev, sx, sy);
                if ((otmp = sobj_at(BOULDER, lev, sx, sy)) != 0) {
                    /* another boulder here, restack it to the top */
                    obj_extract_self(otmp);
                    place_object(otmp, lev, sx, sy);
                }
            } else {
                struct trap *trap;

                if ((trap = t_at(lev, sx, sy)) && trap->ttyp == STATUE_TRAP)
                    deltrap(lev, trap);
                if (visible)
                    pline("%s.", Tobjnam(otmp, "crumble"));
                break_statue(otmp);
                place_object(otmp, lev, sx, sy); /* put fragments on floor */
            }
            used_up = TRUE;

            /* 1 in 10 chance of destruction of obj; glass, egg destruction */
        } else if ((scflags & MAY_DESTROY) &&
                   (!rn2(10) || (objects[otmp->otyp].oc_material == GLASS ||
                                 otmp->otyp == EGG))) {
            if (breaks(otmp, (xchar) sx, (xchar) sy))
                used_up = TRUE;
        }

        if (!used_up) {
            stmp = malloc(sizeof (struct scatter_chain));
            stmp->next = NULL;
            stmp->obj = otmp;
            stmp->ox = sx;
            stmp->oy = sy;
            tmp = rn2(8);       /* get the direction */
            stmp->dx = xdir[tmp];
            stmp->dy = ydir[tmp];
            tmp = blastforce - (otmp->owt / 40);
            if (tmp < 1)
                tmp = 1;
            stmp->range = rnd(tmp);     /* anywhere up to that determ. by wt */
            if (farthest < stmp->range)
                farthest = stmp->range;
            stmp->stopped = FALSE;
            if (!schain)
                schain = stmp;
            else
                stmp2->next = stmp;
            stmp2 = stmp;
        }
    }

    while (farthest-- > 0) {
        for (stmp = schain; stmp; stmp = stmp->next) {
            if ((stmp->range-- > 0) && (!stmp->stopped)) {
                bhitpos.x = stmp->ox + stmp->dx;
                bhitpos.y = stmp->oy + stmp->dy;
                typ = lev->locations[bhitpos.x][bhitpos.y].typ;
                if (!isok(bhitpos.x, bhitpos.y)) {
                    bhitpos.x -= stmp->dx;
                    bhitpos.y -= stmp->dy;
                    stmp->stopped = TRUE;
                } else if (!ZAP_POS(typ) ||
                           closed_door(lev, bhitpos.x, bhitpos.y)) {
                    bhitpos.x -= stmp->dx;
                    bhitpos.y -= stmp->dy;
                    stmp->stopped = TRUE;
                } else if ((mtmp = m_at(lev, bhitpos.x, bhitpos.y)) != 0) {
                    if (scflags & MAY_HITMON) {
                        stmp->range--;
                        if (ohitmon(mtmp, stmp->obj, 1, FALSE)) {
                            stmp->obj = NULL;
                            stmp->stopped = TRUE;
                        }
                    }
                } else if (bhitpos.x == u.ux && bhitpos.y == u.uy) {
                    if (scflags & MAY_HITYOU) {
                        int hitvalu, hitu;

                        action_interrupted();

                        hitvalu = 8 + stmp->obj->spe;
                        if (bigmonst(youmonst.data))
                            hitvalu++;
                        hitu =
                            thitu(hitvalu, dmgval(stmp->obj, &youmonst),
                                  stmp->obj, NULL);
                        if (hitu)
                            stmp->range -= 3;
                    }
                } else {
                    if (scflags & VIS_EFFECTS) {
                        /* tmpsym_at(bhitpos.x, bhitpos.y); */
                        /* delay_output(); */
                    }
                }
                stmp->ox = bhitpos.x;
                stmp->oy = bhitpos.y;
            }
        }
    }
    for (stmp = schain; stmp; stmp = stmp2) {
        int x, y;

        stmp2 = stmp->next;
        x = stmp->ox;
        y = stmp->oy;
        if (stmp->obj) {
            if (x != sx || y != sy)
                total += stmp->obj->quan;
            place_object(stmp->obj, lev, x, y);
            stackobj(stmp->obj);
        }
        free(stmp);
        if (lev == level)
            newsym(x, y);
    }

    return total;
}
int main(int argc, char *argv[])
{
	int format = UNKNOWN;
	int gaps = APPEND;
	int ret = 0;		/* return value of breaks() */

	/* option variables */
	int c;
	/* getopt_long() variables */
	extern char *optarg;
	extern int optind;

	static struct option longopts[] = {
		{"help", no_argument, NULL, 'h'},
		{"input-format", required_argument, NULL, 'i'},
		{"append-gaps", no_argument, NULL, 'a'},
		{"prepend-gaps", no_argument, NULL, 'p'},
		{"split-gaps", no_argument, NULL, 's'},
		{"version", no_argument, NULL, 'V'},
		{NULL, 0, NULL, 0}
	};

	progname = argv[0];

	while (-1 != (c = getopt_long(argc, argv, "hi:V", longopts, NULL))) {
		switch (c) {
		case 'h':
			usage(0);
			break;
		case 'i':
			if (0 == strcmp("cue", optarg)) {
				format = CUE;
			} else if (0 == strcmp("toc", optarg)) {
				format = TOC;
			} else {
				fprintf(stderr, "%s: error: unknown input file"
				        " format `%s'\n", progname, optarg);
				usage(1);
			}
			break;
		case 'a':
			gaps = APPEND;
			break;
		case 'p':
			gaps = PREPEND;
			break;
		case 's':
			gaps = SPLIT;
			break;
		case 'V':
			version();
			break;
		default:
			usage(1);
			break;
		}
	}

	/* What we do depends on the number of operands. */
	if (optind == argc) {
		/* No operands: report breakpoints of stdin. */
		ret = breaks("-", format, gaps);
	} else {
		/* Report track breakpoints for each operand. */
		for (; optind < argc; optind++) {
			ret = breaks(argv[optind], format, gaps);
			/* Exit if breaks() returns nonzero. */
			if (!ret) {
				break;
			}
		}
	}

	return ret;
}
void print_non_overlapping_pairs(std::vector<int>& v)
{
    std::vector<bool> breaks(v.size() - 1, false); // breaks used for segmenting
    print_vec(v, breaks, 0);
}