Example #1
0
Vector<pointT> successors(pointT position, Grid<char> &board, Vector<pointT> &deltas) { 
	Vector<pointT> next; 
	
	for (int i =0; i < deltas.size(); i++) { 
		int nextRow = position.row + deltas[i].row; 
		int nextCol = position.col + deltas[i].col; 
		pointT pt; pt.row = nextRow; pt.col = nextCol; 
		if ( inGrid(board, pt) ) { 
			next.add(pt); 
		}
	}
	return next; 
}
//checks if a dapp has been applied to (x,y) at step k
int dappdone(Task* taskGrid, int M, int N, int x, int y, int k)
{
	int ret = 0;

	if(!inGrid(M, N, x, y))
		return 1;

	if(genericdone(taskGrid, M, x, y, k))//finished operation
	{
		if(tgrid(x,y).taskType == DAPP)//is dapp task
			ret = 1;
	}

	return ret;
}
//if can apply at (x,y) step k, returns 1. 0 otherwise
int candoSAPP(Task* taskGrid, int M, int N, int x, int y, int k)
{
	int ret = 0;

	if (!inGrid(M, N, x - 1, y))
		return 1;

	//checkqrs(k,k)k done, check vectors are ready
	if(qrsdone(taskGrid, M, k))
	{
		//checkdapp(x,y)k-1 done//check previous step completed
		if(dappdone(taskGrid, M, N, x, y, k - 1))
			ret = 1;
	}

	return ret;
}
int candoQRD(Task* taskGrid, int M, int N, int x, int y, int k)
{
	int ret = 0;
		
	//checkgendone(x-1,k)k done check if row above is done (qrd or qrs)
	if(genericdone(taskGrid, M, x-1, y, k))
	{
		//checkdapp(x,y)k-1 done check if dapp in place has been done
		if(k == 0)//if no previous
			ret = 1;
		else if(dappdone(taskGrid, M, N, x, y, k-1))
			ret = 1;
	}

	if(!inGrid(M, N, x, y))
		ret = 0;

	return ret;
}
Example #5
0
std::set<const Model*> UniformGrid::getModels(const Ray& ray) const {
  std::set<const Model*> models;

  Point3D nextT(0, 0, 0);

  // The point *within* the grid where the ray first intersected it
  Point3D rayStartPoint(0, 0, 0);

  if (!inGrid(ray.start)) {
    const auto& sp = startPoint;
    // Not in the grid: We will use a cube the sz of whole grid to find
    // the point of entry into the grid
    auto gridCubeInverse = (translationMatrix(sp[0], sp[0], sp[0]) *
                           gridSizeScaleMatrix).invert();
    HitRecord hr;
    if (!utilityCube.intersects(ray, &hr, gridCubeInverse)) {
      // Does not intersect the grid even
      return models;
    }
    nextT[0] = hr.t;
    nextT[1] = hr.t;
    nextT[2] = hr.t;
    rayStartPoint = ray.at(hr.t);
  }
  else {
    rayStartPoint = ray.start;
  }

  // Place in the grid we are currently stepping through
  CellCoord gridCoord = coordAt(rayStartPoint);

  Vector3D dir(
      std::abs(ray.dir[0]), std::abs(ray.dir[1]), std::abs(ray.dir[2]));

  // These values are in units of t: how far we must go to travel a whole cell
  Vector3D dt(
    isZero(dir[0]) ? 0 : cellSize / dir[0],
    isZero(dir[1]) ? 0 : cellSize / dir[1],
    isZero(dir[2]) ? 0 : cellSize / dir[2]
  );
  {
    // The bottom left corner of the cell we are starting in
    Point3D gsp = pointAt(gridCoord); // "Grid start point"

    // Determine how far, in units of t, we have to go in any direction
    // to reach the next cell
    // If we are going "forwards" in a coordinate then we need to travel to
    // gsp + cellSize. If we are going "backwards" in a coordinate then we need
    // to travel to only gsp.
    for (int i = 0; i < 3; ++i) {
      if (isZero(dir[i])) {
        nextT[i] = -1;
        continue;
      }
      if (ray.dir[i] < 0) {
        nextT[i] += (rayStartPoint[i] - gsp[i]) / dir[i];
      }
      else {
        nextT[i] += (gsp[i] + cellSize - rayStartPoint[i]) / dir[i];
      }
    }
  }

  // Which direction in the grid to move when we hit a "next" value
  CellCoord incs(
    (ray.dir[0] > 0) ? 1 : -1,
    (ray.dir[1] > 0) ? 1 : -1,
    (ray.dir[2] > 0) ? 1 : -1
  );

  // Check if a coord is still valid
  auto coordOk = [&] (int coord) -> bool {
    return 0 <= coord && coord < sideLength;
  };
  auto smaller = [] (double a, double b) -> bool {
    return (b < 0) || a <= b;
  };

  while (coordOk(gridCoord.x) && coordOk(gridCoord.y) && coordOk(gridCoord.z)) {
    for (const Model* model : cells[indexFor(gridCoord)].models) {
      models.insert(model);
    }

    for (int i = 0; i < 3; ++i) {
      if (nextT[i] < 0) continue;
      const auto a = nextT[(i + 1) % 3];
      const auto b = nextT[(i + 2) % 3];
      if (smaller(nextT[i], a) && smaller(nextT[i], b)) {
        nextT[i] += dt[i];
        gridCoord[i] += incs[i];
        break;
      }
    }
  }

  return models;
}
//can always do qrs if in grid
int candoQRS(Task* taskGrid, int M, int N, int x, int y, int k)
{
	return inGrid(M, N, x, y);
}
// int doffire(unsigned int xmax=128, unsigned int ymax=128, unsigned int fmatch=125 unsigned short burnPropAge=400) {
// use simpler float nRand, nClust probabilities...
int doffire(unsigned tmax=1000000, int doSQL=1, unsigned int fMatch=200, float nRand=1, float nClust=0, int kmax=4, unsigned int sheepSpeed=0) {
    // burn toplolgy: do we nave nnn burning
    //
    // allow for no-fire simulation (aka, sheep only):
    if (fMatch==0) fMatch=tmax;
    //
    std::string simName("ForestFire7e");
    std::string simPramComment("");
    //int fMatch = 250;
    //
    unsigned short rFire = 1;
    unsigned int nBurning = 0;
    unsigned short dnBurning = 0;
    int thisX, thisY, xFire, yFire;
    unsigned int sheepPos;
    //int *fireSquare = new int;
    int *fireSquare = NULL;
    unsigned int nBurnedTotal=0, nFires=0;  // number of elements burning, new Elements burning...
    //
    int burnPropAge=1;
    //
    //int *bigClustMaps = new int[(ymax+2)*(xmax+2)];
    int *grids = new int[(ymax+2)*(xmax+2)];

    int intKey;
    float aveRho, aveVol;
    int gridPos=0;
    //
    int rSeed=int(time(NULL));
    int drSeed = 0;
    srand(time(NULL));
    Rand plantRandx(rSeed + drSeed);
    drSeed ++;
    Rand plantRandy(rSeed + drSeed);
    drSeed ++;
    Rand fireRandx(rSeed + drSeed);
    drSeed ++;
    Rand fireRandy(rSeed + drSeed);
    drSeed ++;
    Rand rfMatch(rSeed + drSeed);
    drSeed ++;
    Rand rcPlant(rSeed + drSeed);
    drSeed ++;
    Rand walkDir(rSeed + drSeed);
    drSeed ++;
    Rand sheepRand(rSeed + drSeed);
    drSeed ++;
    Rand sheepRand2(rSeed + drSeed);
    drSeed ++;

    // initialize the grid/cluster-grid with "rocks" around the border and in otherwise empty cells.
    // "cluster 0" will, for the time being, not participate in the simulation. just for posterity,
    // we will place "rocks" around the borders. initialize the interior of the grid with 0; we will
    // map the excluded areas via the clusters grid.
    for (unsigned int i = (xmax+2); i<(xmax+2)*(ymax+1); i++) {
        // initialize here with tree-seeds and sheep:
        *(grids+i) = 0;
    };
    for (unsigned int i=0; i<(xmax+2); i++) {
        //grids[i] = rockAge;
        //grids[(ymax+1)*(xmax+2) + i] = rockAge;
        *(grids+i) = rockAge;
        *(grids + (ymax+1)*(xmax+2) + i) = rockAge;
        //
    };
    for (unsigned int i=0; i<(ymax+2); i++) {
        //grids[(xmax+2)*i] = rockAge;
        //grids[(xmax+2)*i + xmax+1] = rockAge;
        *(grids + (xmax+2)*i) = rockAge;
        *(grids +(xmax+2)*i + xmax+1) = rockAge;
        //
    };
    //printf("the grid:\n");
    //printGrid(grids, 1, xmax, ymax);
    //
    // cluster map moved to a function:
//	unsigned int biggestFire = getClustMaps1(bigClustMaps);
    unsigned int biggestFire = xmax0*ymax0;
    // now, the cluster map is established. as we plant trees, we will plant against this grid.
    //
    // seed the grid with some trees:
    Rand treeSeedx(rSeed + drSeed);
    drSeed ++;
    Rand treeSeedy(rSeed + drSeed);
    drSeed ++;
    // particularly for dendritic models, how many seeds to we want? in the purest form, we want 1, but that will take a LONG time to get started.
    for (unsigned int i=0; i < xmax; i++) {
        // seed the grid with some trees
        //if (rand()%(xmax)==1 and i%(xmax+2)!=0 and (i+1)%(xmax+2)!=0 and i>(xmax+2) and i<((xmax+2)*(ymax+1)) ) grids[i]++;
        int thisX = treeSeedx.nextInt(xmax);
        int thisY = treeSeedy.nextInt(ymax);
        //thisClust = clustGrids[(xmax+2)*(thisY+1)+thisX+1];
        //grids[(xmax+2)*(thisY+1)+thisX+1] = thisClust;
        //thisClust = *(bigClustMaps + (xmax+2)*(thisY+1)+thisX+1);
        *(grids + (xmax+2)*(thisY+1)+thisX+1) = 1;
        //yodapause();
    };
//	for (unsigned int i=0; i < nSheep; i++) {
//		// seed the grid with some sheep
//		int thisX = treeSeedx.nextInt(xmax);
//		int thisY = treeSeedy.nextInt(ymax);
//		*(grids + (xmax+2)*(thisY+1)+thisX+1) = sheepAge;
//		//yodapause();
//		};

    //printf("random grid established...\n");
    //printGrid(&grids[0], 1, xmax, ymax);
    //
    char DB[]="ForestFire";
    char HOST[]="localhost";
    char USER[]="myoder";
    char PASSWORD[]="yoda";
    mysqlpp::Connection myconn(DB, HOST, USER, PASSWORD);
    mysqlpp::Query myquery=myconn.query();
    mysqlpp::Result res1;
    //int intKey;
    //unsigned int fcounts[xmax*ymax];
    //unsigned int *fcounts = new unsigned int[xmax*ymax];
    unsigned int *fcounts = new unsigned int[biggestFire];
    for (unsigned int i=0; i<biggestFire; i++) {
        //fcounts[i]=0;
        *(fcounts + i) = 0;
    };
    if (doSQL==1 or doSQL==5) {
        //
        // insert a new row for this sim-run:
        myquery.reset();
        printf("insert simprams.\n");
        //myquery << "insert into ForestFire.SimPrams (SimName, SimSW, xmax, ymax, sparkInterval, sparkProb, burnAge, propAge, tmax, wrapX, wrapY, Comment) values (%0q, %1q, %2q, %3q, %4q, %5q, %6q, %7q, %8q, %9q, %10q, %11q )";
        myquery << "insert into ForestFire.SimPrams (SimName, SimSW, xmax, ymax, sparkInterval, tmax, nRand, nClust, kmax, sheepSpeed, Comment) values (%0q, %1q, %2q, %3q, %4q, %5q, %6q, %7q, %8q, %9q, %10q)";
        myquery.parse();
        // note: simIndex(auto-int) and dtTime (default TIMESTAMP) set automatically.
        myquery.execute(simName.c_str(), simName.c_str(), xmax, ymax, fMatch, tmax, nRand, nClust, kmax, sheepSpeed, simPramComment.c_str());
        //
        // now, get the integer key for this simulation:
        // note that this could be accomplished with one call (optimal if MySQL calls have high overhead)
        // by writing a SPROC on the MySQL side.
        // also see the mysql_insert_id() (C API) and LAST_INSERT_ID() (SQL) functions, by which we should be ablt to automatically retrieve the indexID.
        myquery.reset();
        printf("fetch simIndex.\n");
        myquery << "select max(simIndex) from ForestFire.SimPrams where simName=%0q and simSW=%1q";
        myquery.parse();
        res1 = myquery.store(simName.c_str(), simName.c_str());
        intKey = res1.at(0).at(0);
    }; // doSQL

    /*
    	if (doSQL==1 or doSQL==5) {
    		//
    		// insert a new row for this sim-run:
    		myquery.reset();
    		printf("insert simprams.\n");
    		myquery << "insert into ForestFire.SimPrams (SimName, SimSW, xmax, ymax, sparkInterval, sparkProb, burnAge, propAge, tmax, wrapX, wrapY, Comment) values (%0q, %1q, %2q, %3q, %4q, %5q, %6q, %7q, %8q, %9q, %10q, %11q )";
    		myquery.parse();
    		// note: simIndex(auto-int) and dtTime (default TIMESTAMP) set automatically.
    		myquery.execute(simName.c_str(), simName.c_str(), xmax, ymax, fmatch, pMatch, burnAge, burnPropAge, tmax, wrapx1, wrapy1, simPramComment.c_str());
    		//
    		// now, get the integer key for this simulation:
    		// note that this could be accomplished with one call (optimal if MySQL calls have high overhead)
    		// by writing a SPROC on the MySQL side.
    		// also see the mysql_insert_id() (C API) and LAST_INSERT_ID() (SQL) functions, by which we should be ablt to automatically retrieve the indexID.
    		myquery.reset();
    		printf("fetch simIndex.\n");
    		myquery << "select max(simIndex) from ForestFire.SimPrams where simName=%0q and simSW=%1q";
    		myquery.parse();
    		res1 = myquery.store(simName.c_str(), simName.c_str());
    		intKey = res1.at(0).at(0);
    		}; // doSQL
    */
    //
    for (unsigned int i=0; i<=tmax; i++) {
        //
        // first do the sheep:
        // note, we can remove sheep by setting sheepSpeed=0
        // use smarter sheep; sheep move to (and eat) an occupied site or at random.
        // printf("sheepSpeed: %d\n", sheepSpeed);
        // yodapause();

        for (unsigned short isheep = 0; isheep<sheepSpeed; isheep++) {
            switch (*(grids+sheepPos)) {
            case 0:
            case rockAge:
                // move:
                //sheepPos = sheepPos + getRandDir((xmax+2), sheepRand);
                sheepPos = sheepPos + getSheepDir(sheepPos, grids, (xmax+2), sheepRand);
                break;
            case 1:
                // eat:
                *(grids+sheepPos)=0;
                break;
            default:
                // nothing.
                break;
            };

            //
            // are we outside the grid or on an illegal spot?
            //if (sheepPos<=(xmax+2) or sheepPos>((xmax+2)*(ymax+1)) or sheepPos%(xmax+2)==0 or sheepPos%(xmax+1)==0) {
            if (inGrid(sheepPos, (xmax+2), (ymax+2))==0) {
                // we've wandered off the grid; get new sheep.
                sheepPos = (xmax+2) + 1 + sheepRand.nextInt(xmax) + (xmax+2)*sheepRand.nextInt(ymax);
                //*(grids+sheepPos)=0;
                //sheepPos = sheepPos + getSheepDir(sheepPos, grids, (xmax+2), sheepRand);
            };
        }; // sheep-speed


        //
        //if (doSQL==5 or doSQL==6) if(i%1000000 == 0) printf("%d million\n", i/1000000);
        if (doSQL==6) if(i%1000000 == 0) printf("%d million\n", i/1000000);

        if (doSQL==16) {
            if(i%100000 == 0) {
                // printf("%d million\n", i/1000000);
                aveRho=0;
                aveVol=0;
                for (unsigned int k=0; k<(xmax+2)*(ymax+2); k++) {
                    if (*(grids+k)>0 and *(grids+k)<rockAge) {
                        aveRho = aveRho + 1;
                        aveVol = aveVol + *(grids+k);
                    };
                };
                //printf("mils,\t Rho,\t Vol,\t %d, %f, %f\n", i/1000000, float(aveRho)/float(xmax*ymax), float(aveVol)/float(xmax*ymax));
                printf("%d, %f, %f\n", i/1000000, float(aveRho)/float(xmax*ymax), float(aveVol)/float(xmax*ymax));
            };
        };
        //
        // PLANT A TREE:
        // select a grid for tree planting:
        // yoder, v7: introduce dendritic growth. we have two prams, nRand, nClst. define a P(rand)-> Pr, P(clust)->Pc: Pr=nRand/(nRand+nClust), etc.
        //for (unsigned int irp=0; irp<randPlant; irp++) {
        thisX = plantRandx.nextInt(xmax);
        thisY = plantRandy.nextInt(ymax);
        gridPos = (xmax+2)*(thisY+1)+1+thisX;
        //
        *(grids+gridPos) = 1;
        // what is the grid value? if it's empty, plant against P=nRand/(nRand+nClust); if it's a tree, plant each adjacent grid with nR/(nR+nC)
        //
        /*
        		switch (*(grids+gridPos)) {
        			case 0:
        				// planting stats:
        				if (rcPlant.nextDouble() <= nRand) {
        					*(grids+gridPos) = 1;
        					};
        				break;
        			case 1:
        				if (rcPlant.nextDouble() <= float(nClust)/float(nClust+nRand) and *(grids+gridPos + 1)==0) {
        					*(grids+gridPos+1) = 1;
        					};
        				if (rcPlant.nextDouble() <= float(nClust)/float(nClust+nRand) and *(grids+gridPos - 1)==0) {
        					*(grids+gridPos-1) = 1;
        					};
        				if (rcPlant.nextDouble() <= float(nClust)/float(nClust+nRand) and *(grids+gridPos + (xmax+2))==0) {
        					*(grids+gridPos+(xmax+2)) = 1;
        					};
        				if (rcPlant.nextDouble() <= float(nClust)/float(nClust+nRand) and *(grids+gridPos - (xmax+2))==0) {
        					*(grids+gridPos-(xmax+2)) = 1;
        					};
        				break;
        			case sheepAge:
        				//move. if we walk off the grid, replace at random. eat.
        				sheepPos = gridPos + getRandDir((xmax+2), sheepRand);
        				//
        				// are we outside the grid or on an illegal spot?
        				if (sheepPos<=(xmax+2) or sheepPos>((xmax+2)*(ymax+1)) or sheepPos%(xmax+2)==0 or sheepPos%(xmax+1)==0) {
        					// we've wandered off the grid; get new sheep.
        					sheepPos = (xmax+2) + 1 + sheepRand.nextInt(xmax) + (xmax+2)*sheepRand.nextInt(ymax);
        					};
        				*(grids+gridPos)=0;						// move off the old cell
        				*(grids+sheepPos) = sheepAge;			// move to the new cell
        				break;
        			};
        */

        //
// debug:
//		if (i%10000==0) {
//			plotGridSimple (grids, i, xmax, ymax);
//			};

        // we've planted a tree. do we throw a match?
        // a 1 in fMatch chance (use any value between 0 and fMatch)
        if (rfMatch.nextInt(fMatch) == 1) {
            //yodapause();
            // throw a match.
            xFire = fireRandx.nextInt(xmax) + 1;
            yFire = fireRandy.nextInt(ymax) + 1;
            //
            fireSquare = grids + (xmax+2)*yFire + xFire;
            //printf("match: (%d, %d) :: %d\n", xFire, yFire, *fireSquare);
            //yodapause();
            //
            if (*fireSquare > 0 and *fireSquare<rockAge) {
                // initiate a new fire.
                // start from the epicenter and work out in concentric rectangles (squares)
                // until there are no new fires.
                // note: we make two passes over each circle. for now, we assume all squares
                // continue to burn until the fire is over. this is a subtle consideration that
                // will not matter for simpler versions of the model, but if we introduce burn probabilities,
                // we will have to be more careful.

                //burningClust = clustGrids[(xmax+2)*yFire + xFire];
                //burningClust = *(bigClustMaps + (xmax+2)*yFire + xFire);
                *fireSquare=-(*fireSquare);	// the fire-square starts burning
                //
                rFire = 1;
                dnBurning = 1;
                //
                nBurning = dnBurning;
                int yFireMin = int(yodacode::greaterOf((yFire-rFire), 1));	// we always start with a 1 squar boundary. we might, however, encounter the edges.
                int yFireMax = int(yodacode::lesserOf((yFire+rFire), float(ymax)));
                int xFireMin = int(yodacode::greaterOf(float(xFire-rFire), 1));
                int xFireMax = int(yodacode::lesserOf(float(xFire+rFire), float(xmax)));
                //printf("fire range: %d, %d, %d, %d\n", yFireMin, yFireMax, xFireMin, xFireMax);
                //printf("preplot\n.");
                //
                //plotGrid(&grids[0],i, xmax, ymax);
                if (doSQL==0) {
                    printGrid(grids, i, xmax, ymax);
                };
                //while (dnBurning > 0) {
                while (dnBurning > 0) {
                    dnBurning=0;
                    for (char doTwice = 0; doTwice <=1; doTwice++) {	// "char" is a 1 byte integer. we could also use a boolean to count to 2.
                        for (int iy = (yFireMin); iy <= (yFireMax); iy++) {
                            for (int ix = (xFireMin); ix <= (xFireMax); ix++) {
                                // also note: Gelb is right. a recursive approach is faster, though this bredth-first appraoch is more like real fire propagation.
                                // printf("try-burn: %d, %d\n", ix, iy);
                                //plotGrid(&grids[0], xmax, ymax);
                                //yodapause();
                                //
                                int * centerGrid = (grids + ix + (xmax+2)*iy);
                                int cStat, uStat, dStat, lStat, rStat;
                                //int ulStat, urStat, llStat, lrStat;	// diagonal elements.
                                cStat = *centerGrid;
                                //
                                uStat = *(centerGrid + (xmax+2));
                                dStat = *(centerGrid - (xmax+2));
                                lStat = *(centerGrid - 1);
                                rStat = *(centerGrid + 1);
                                //
                                // diagonal elements:
                                //ulStat = getGridStatus(*(centerGrid + (xmax+2) - 1), i);
                                //urStat = getGridStatus(*(centerGrid + (xmax+2) + 1), i);
                                //llStat = getGridStatus(*(centerGrid - (xmax+2) - 1), i);
                                //lrStat = getGridStatus(*(centerGrid - (xmax+2) + 1), i);
                                //yodapause();
                                //if (*centerGrid >= burnAge and (*leftGrid==-1 or *rightGrid==-1 or *upGrid==-1 or *downGrid==-1)) {
                                //if (*centerGrid >= burnAge and (*leftGrid<=-burnPropAge or *rightGrid<=-burnPropAge or *upGrid<=-burnPropAge or *downGrid<=-burnPropAge)) {
                                //if (cStat >= burnAge and cStat < rockAge and (lStat<=-burnPropAge or rStat<=-burnPropAge or uStat<=-burnPropAge or dStat<=-burnPropAge)) {
                                //
                                // no immunity:
                                if (cStat >= 1 and cStat < rockAge
                                        and (lStat<=-1 or rStat<=-1 or uStat<=-1 or dStat<=-1) )
                                {
                                    //
                                    //						// next nearest neighbors:
                                    //						if (cStat >= burnAge and cStat < rockAge
                                    //							and  ( (lStat<=-burnPropAge or rStat<=-burnPropAge or uStat<=-burnPropAge or dStat<=-burnPropAge)
                                    //								 or ( (ulStat<=-nnnAge or urStat<=-nnnAge  or llStat<=-nnnAge  or lrStat<=-nnnAge)
                                    //									 and (ulStat<=-burnPropAge or urStat<=-burnPropAge or llStat<=-burnPropAge  or lrStat<=-burnPropAge)
                                    //									 )
                                    //						 		)
                                    //							) {
                                    *centerGrid = -(*centerGrid);
                                    // age -> number of trees in that grid...
                                    dnBurning ++;
                                    //printf("[%d, %d] catches from [%d, %d]\n", ix, iy, xFire, yFire);
                                };
                            }; // ix
                        }; // iy
                    }; // doTwice
                    // plotGridSimple (grids, i, xmax, ymax);
                    nBurning = nBurning + dnBurning;
                    //yodapause();
                    xFireMin = int(yodacode::greaterOf(1, float(xFireMin-1)));
                    xFireMax = int(yodacode::lesserOf(float(xmax), xFireMax+1));
                    yFireMin = int(yodacode::greaterOf(1, float(yFireMin-1)));
                    yFireMax = int(yodacode::lesserOf(float(ymax), yFireMax+1));
                    // g1.plot_xy(vfireX, vfireY, "");
                };	// end "while" fire still burining
                //
                nFires++;
                nBurnedTotal = nBurnedTotal + nBurning;
                fcounts[nBurning-1]++;
                //	plotGrid(&grids[0], xmax, ymax);
                if (doSQL==0) {
                    printGrid(&grids[0], i, xmax, ymax);
                    printf("fire size, vol, nFires, totalBurned, totalVol: (%d) (%d) (%d)\n", nBurning, nFires, nBurnedTotal);
                };
                // write fire to MySQL:
                if (doSQL==1) {
                    printf("fire size, nFires, totalBurned: (%d) (%d) (%d)\n", nBurning, nFires, nBurnedTotal);
                    //				myquery.reset();
                    //				myquery << "insert into ForestFire.ForestFires (simIndex, t, xSpark, ySpark, AveTreeAge, nBurned) values (%0q, %1q, %2q, %3q, %4q, %5q) ";
                    //				myquery.parse();
                    //				myquery.execute(intKey, i, xFire, yFire, aveTreeAge, nBurning);
                };
                if (doSQL==3) {
                    printf("fire (%d) at time %d\n",nBurning, i);
                    if (nBurning>=10) plotGridSimple (grids, i, xmax, ymax);
                };
                if (doSQL==4) {
                    if (nBurning>=10) plotGridImg (grids, i, xmax, ymax, burnPropAge);
                };
                //
                // fires finished burning; extinguish:
                for (int iy = (yFireMin); iy <= (yFireMax); iy++) {
                    for (int ix = (xFireMin); ix <= (xFireMax); ix++) {
                        // &grids[0] + ix + (xmax+2)*iy
                        //if (grids[ix + (xmax+2)*iy] < 0) grids[ix + (xmax+2)*iy]=0;
                        if (*(grids +ix + (xmax+2)*iy) < 0) *(grids +ix + (xmax+2)*iy)=0;
                    };
                };
            }; //else printf("no tree at match point.\n");	// if match -> tree...
        }; // if match-time
    };	// end sim-steps.
    // end simulation.
    //printf("doSQL: %d\n", doSQL);
    // doSQL's:
    // 0: 'print-grid" fires
    // 1: full SQL: insert each forest fire data-set into ForestFires
    // 2: print summary to screen. use this for direct gnuplot calls, " plot '<./ffire4...'"
    // 3: Print each fire to screen; "plotGrid" each fire nBurning>(25) print summary to screen at end
    // 4: plotGridImg each fire nBurning>(20); print summary to screen,
    // 5: SQL: insert just summary data to SQL; prints progress by million (will screw up plotting)
    // 6: report summary, progress by million.
    // 11: return to standard-output the last grid in full. use to make an image of the final grid.
    //
    // end-o-run summaries (print):
    if (doSQL==2 or doSQL==3 or doSQL==4 or doSQL==6) {
        for (unsigned int i=0; i<(biggestFire); i++) {
            //if (fcounts[i]!=0) printf("%d\t%d\n", i+1, fcounts[i]);
            if (*(fcounts + i) != 0) printf("%d\t%d\n", i+1, *(fcounts + i));
            //printf("%d,\t%d\n", i+1, fcounts[i]);
        };
    } else {
        //printf("finished.\nfire size, nFires, totalBurned: (%d) (%d) (%d)\n", nBurning, nFires, nBurnedTotal);
    };
    if (doSQL==5 ) { // no plots, just a summary -> SQL
        //
        for (unsigned int i=0; i<(biggestFire); i++) {
            // if (fcounts[i]!=0) printf("%d\t%d\n", i+1, fcounts[i]);
            //	printf ("sql bits: %d, %d, %d, %d\n", intKey, tmax, i+1, fcounts[i]);
            myquery.reset();
            myquery << "insert into ffcounts (simIndex, tmax, nBurned, nEvents) values (%0q, %1q, %2q, %3q)";
            myquery.parse();
            myquery.execute(intKey, tmax, i+1, fcounts[i]);
            //printf("%d,\t%d\n", i+1, fcounts[i]);
        };
    };
    // return the final grid in full and give an average density at the end...?
    if (doSQL==11) {
        for (unsigned int i=0; i<(xmax+2)*(ymax+2); i++) {
            printf ("%d,\t%d,\t%d\n", i-int(i/(xmax+2))*(xmax+2), i/(xmax+2), getGridStatus(*(grids+i), tmax));
        };
    };

    //yodacode::yodapause();
    return 0;
    //return &grids[0];
};