Example #1
0
void cellularAutomataRound(short **grid, char birthParameters[9], char survivalParameters[9]) {
    short i, j, nbCount, newX, newY;
    enum directions dir;
    short **buffer2;
    
    buffer2 = allocGrid();
    copyGrid(buffer2, grid); // Make a backup of grid in buffer2, so that each generation is isolated.
    
    for(i=0; i<DCOLS; i++) {
        for(j=0; j<DROWS; j++) {
            nbCount = 0;
            for (dir=0; dir< DIRECTION_COUNT; dir++) {
                newX = i + nbDirs[dir][0];
                newY = j + nbDirs[dir][1];
                if (coordinatesAreInMap(newX, newY)
                    && buffer2[newX][newY]) {
                    
                    nbCount++;
                }
            }
            if (!buffer2[i][j] && birthParameters[nbCount] == 't') {
                grid[i][j] = 1;	// birth
            } else if (buffer2[i][j] && survivalParameters[nbCount] == 't') {
                // survival
            } else {
                grid[i][j] = 0;	// death
            }
        }
    }
    
    freeGrid(buffer2);
}
Example #2
0
// Flood-fills the grid from (x, y) along cells that are within the eligible range.
// Returns the total count of filled cells.
short floodFillGrid(short **grid, short x, short y, short eligibleValueMin, short eligibleValueMax, short fillValue) {
    enum directions dir;
	short newX, newY, fillCount = 1;
    
    brogueAssert(fillValue < eligibleValueMin || fillValue > eligibleValueMax);
    
    grid[x][y] = fillValue;
    for (dir = 0; dir < 4; dir++) {
        newX = x + nbDirs[dir][0];
        newY = y + nbDirs[dir][1];
        if (coordinatesAreInMap(newX, newY)
            && grid[newX][newY] >= eligibleValueMin
            && grid[newX][newY] <= eligibleValueMax) {
            fillCount += floodFillGrid(grid, newX, newY, eligibleValueMin, eligibleValueMax, fillValue);
        }
    }
    return fillCount;
}
Example #3
0
// Marks a cell as being a member of blobNumber, then recursively iterates through the rest of the blob
short fillContiguousRegion(short **grid, short x, short y, short fillValue) {
    enum directions dir;
	short newX, newY, numberOfCells = 1;
	
	grid[x][y] = fillValue;
	
	// Iterate through the four cardinal neighbors.
	for (dir=0; dir<4; dir++) {
		newX = x + nbDirs[dir][0];
		newY = y + nbDirs[dir][1];
		if (!coordinatesAreInMap(newX, newY)) {
			break;
		}
		if (grid[newX][newY] == 1) { // If the neighbor is an unmarked region cell,
			numberOfCells += fillContiguousRegion(grid, newX, newY, fillValue); // then recurse.
		}
	}
	return numberOfCells;
}
Example #4
0
File: map.c Project: sbuggay/Solace
// This is a custom implementation of recursive shadowcasting.
void scanOctantFOV(char grid[VIEWWIDTH][VIEWHEIGHT], short xLoc, short yLoc, short octant, float maxRadius,
				   short columnsRightFromOrigin, long startSlope, long endSlope, unsigned long forbiddenTerrain,
				   unsigned long forbiddenFlags, boolean cautiousOnWalls) {
	
	if (columnsRightFromOrigin >= maxRadius) return;
	
	short i, a, b, iStart, iEnd, x, y, x2, y2; // x and y are temporary variables on which we do the octant transform
	long newStartSlope, newEndSlope;
	boolean cellObstructed;
	
	newStartSlope = startSlope;
	
	a = ((LOS_SLOPE_GRANULARITY / -2 + 1) + startSlope * columnsRightFromOrigin) / LOS_SLOPE_GRANULARITY;
	b = ((LOS_SLOPE_GRANULARITY / -2 + 1) + endSlope * columnsRightFromOrigin) / LOS_SLOPE_GRANULARITY;
	
	iStart = min(a, b);
	iEnd = max(a, b);
	
	// restrict vision to a circle of radius maxRadius
	if ((columnsRightFromOrigin*columnsRightFromOrigin + iEnd*iEnd) >= maxRadius*maxRadius) {
		return;
	}
	if ((columnsRightFromOrigin*columnsRightFromOrigin + iStart*iStart) >= maxRadius*maxRadius) {
		iStart = (int) (-1 * sqrt(maxRadius*maxRadius - columnsRightFromOrigin*columnsRightFromOrigin) + FLOAT_FUDGE);
	}
	
	x = xLoc + columnsRightFromOrigin;
	y = yLoc + iStart;
	betweenOctant1andN(&x, &y, xLoc, yLoc, octant);
	boolean currentlyLit = coordinatesAreInMap(x, y) && !(cellHasTerrainFlag(x, y, forbiddenTerrain) ||
														  (pmap[x][y].flags & forbiddenFlags));
	for (i = iStart; i <= iEnd; i++) {
		x = xLoc + columnsRightFromOrigin;
		y = yLoc + i;
		betweenOctant1andN(&x, &y, xLoc, yLoc, octant);
		if (!coordinatesAreInMap(x, y)) {
			// We're off the map -- here there be memory corruption.
			continue;
		}
		cellObstructed = (cellHasTerrainFlag(x, y, forbiddenTerrain) || (pmap[x][y].flags & forbiddenFlags));
		// if we're cautious on walls and this is a wall:
		if (cautiousOnWalls && cellObstructed) {
			// (x2, y2) is the tile one space closer to the origin from the tile we're on:
			x2 = xLoc + columnsRightFromOrigin - 1;
			y2 = yLoc + i;
			if (i < 0) {
				y2++;
			} else if (i > 0) {
				y2--;
			}
			betweenOctant1andN(&x2, &y2, xLoc, yLoc, octant);
			
			if (pmap[x2][y2].flags & IN_FIELD_OF_VIEW) {
				// previous tile is visible, so illuminate
				grid[x][y] = 1;
			}
		} else {
			// illuminate
			grid[x][y] = 1;
		}
		if (!cellObstructed && !currentlyLit) { // next column slope starts here
			newStartSlope = (long int) ((LOS_SLOPE_GRANULARITY * (i) - LOS_SLOPE_GRANULARITY / 2) / (columnsRightFromOrigin + 0.5));
			currentlyLit = true;
		} else if (cellObstructed && currentlyLit) { // next column slope ends here
			newEndSlope = (long int) ((LOS_SLOPE_GRANULARITY * (i) - LOS_SLOPE_GRANULARITY / 2)
							/ (columnsRightFromOrigin - 0.5));
			if (newStartSlope <= newEndSlope) {
				// run next column
				scanOctantFOV(grid, xLoc, yLoc, octant, maxRadius, columnsRightFromOrigin + 1, newStartSlope, newEndSlope,
							  forbiddenTerrain, forbiddenFlags, cautiousOnWalls);
			}
			currentlyLit = false;
		}
	}
	if (currentlyLit) { // got to the bottom of the scan while lit
		newEndSlope = endSlope;
		if (newStartSlope <= newEndSlope) {
			// run next column
			scanOctantFOV(grid, xLoc, yLoc, octant, maxRadius, columnsRightFromOrigin + 1, newStartSlope, newEndSlope,
						  forbiddenTerrain, forbiddenFlags, cautiousOnWalls);
		}
	}
}
Example #5
0
/*
 * Given the x and y coordinate, checks the permanent map and returns
 * true if cell at the coordinates is considered to be in a terrain
 * loop.
 *
 * TDOD: Figure out what this does.
 * TODO: What is a terrain loop?
 * TODO: Remove magic numbers in parameters.
 */
bool checkLoopiness(struct pcell pmap[DCOLS][DROWS],
                    const short x, const short y,
                    const short cDirs[8][2])
{
  bool inString;
  short newX, newY, dir, sdir;
  short numStrings, maxStringLength, currentStringLength;

  if (!(pmap[x][y].flags & IN_LOOP)) {
    return false;
  }

  // find an unloopy neighbor to start on
  for (sdir = 0; sdir < 8; sdir++) {
    newX = x + cDirs[sdir][0];
    newY = y + cDirs[sdir][1];
    if (!coordinatesAreInMap(newX, newY)
        || !(pmap[newX][newY].flags & IN_LOOP)) {
      break;
    }
  }
  if (sdir == 8) { // no unloopy neighbors
    return false; // leave cell loopy
  }

  // starting on this unloopy neighbor, work clockwise and count up (a) the number of strings
  // of loopy neighbors, and (b) the length of the longest such string.
  numStrings = maxStringLength = currentStringLength = 0;
  inString = false;
  for (dir = sdir; dir < sdir + 8; dir++) {
    newX = x + cDirs[dir % 8][0];
    newY = y + cDirs[dir % 8][1];
    if (coordinatesAreInMap(newX, newY) && (pmap[newX][newY].flags & IN_LOOP)) {
      currentStringLength++;
      if (!inString) {
        if (numStrings > 0) {
          return false; // more than one string here; leave loopy
        }
        numStrings++;
        inString = true;
      }
    } else if (inString) {
      if (currentStringLength > maxStringLength) {
        maxStringLength = currentStringLength;
      }
      currentStringLength = 0;
      inString = false;
    }
  }
  if (inString && currentStringLength > maxStringLength) {
    maxStringLength = currentStringLength;
  }
  if (numStrings == 1 && maxStringLength <= 4) {
    pmap[x][y].flags &= ~IN_LOOP;

    for (dir = 0; dir < 8; dir++) {
      newX = x + cDirs[dir][0];
      newY = y + cDirs[dir][1];
      if (coordinatesAreInMap(newX, newY)) {
        checkLoopiness(pmap, newX, newY, cDirs);
      }
    }
    return true;
  } else {
    return false;
  }
}