[BACK]Return to Grid.c CVS log [TXT][DIR] Up to [contributed] / brogue-ce / src / brogue

Annotation of brogue-ce/src/brogue/Grid.c, Revision 1.1

1.1     ! rubenllo    1: /*
        !             2:  *  Grid
        !             3:  *  Brogue
        !             4:  *
        !             5:  *  Created by Brian Walker on 12/7/12.
        !             6:  *  Copyright 2012. All rights reserved.
        !             7:  *
        !             8:  *  This file is part of Brogue.
        !             9:  *
        !            10:  *  This program is free software: you can redistribute it and/or modify
        !            11:  *  it under the terms of the GNU Affero General Public License as
        !            12:  *  published by the Free Software Foundation, either version 3 of the
        !            13:  *  License, or (at your option) any later version.
        !            14:  *
        !            15:  *  This program is distributed in the hope that it will be useful,
        !            16:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            17:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            18:  *  GNU Affero General Public License for more details.
        !            19:  *
        !            20:  *  You should have received a copy of the GNU Affero General Public License
        !            21:  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
        !            22:  */
        !            23:
        !            24: #include "Rogue.h"
        !            25: #include "IncludeGlobals.h"
        !            26:
        !            27:
        !            28: // mallocing two-dimensional arrays! dun dun DUN!
        !            29: short **allocGrid() {
        !            30:     short i;
        !            31:     short **array = malloc(DCOLS * sizeof(short *));
        !            32:
        !            33:     array[0] = malloc(DROWS * DCOLS * sizeof(short));
        !            34:     for(i = 1; i < DCOLS; i++) {
        !            35:         array[i] = array[0] + i * DROWS;
        !            36:     }
        !            37:     return array;
        !            38: }
        !            39:
        !            40: void freeGrid(short **array) {
        !            41:     free(array[0]);
        !            42:     free(array);
        !            43: }
        !            44:
        !            45: void copyGrid(short **to, short **from) {
        !            46:     short i, j;
        !            47:
        !            48:     for(i = 0; i < DCOLS; i++) {
        !            49:         for(j = 0; j < DROWS; j++) {
        !            50:             to[i][j] = from[i][j];
        !            51:         }
        !            52:     }
        !            53: }
        !            54:
        !            55: void fillGrid(short **grid, short fillValue) {
        !            56:     short i, j;
        !            57:
        !            58:     for(i = 0; i < DCOLS; i++) {
        !            59:         for(j = 0; j < DROWS; j++) {
        !            60:             grid[i][j] = fillValue;
        !            61:         }
        !            62:     }
        !            63: }
        !            64:
        !            65: // Highlight the portion indicated by hiliteCharGrid with the hiliteColor at the hiliteStrength -- both latter arguments are optional.
        !            66: void hiliteGrid(short **grid, color *hiliteColor, short hiliteStrength) {
        !            67:     short i, j, x, y;
        !            68:     color hCol;
        !            69:
        !            70:     assureCosmeticRNG;
        !            71:
        !            72:     if (hiliteColor) {
        !            73:         hCol = *hiliteColor;
        !            74:     } else {
        !            75:         hCol = yellow;
        !            76:     }
        !            77:
        !            78:     bakeColor(&hCol);
        !            79:
        !            80:     if (!hiliteStrength) {
        !            81:         hiliteStrength = 75;
        !            82:     }
        !            83:
        !            84:     for (i=0; i<DCOLS; i++) {
        !            85:         for (j=0; j<DROWS; j++) {
        !            86:             if (grid[i][j]) {
        !            87:                 x = mapToWindowX(i);
        !            88:                 y = mapToWindowY(j);
        !            89:
        !            90:                 displayBuffer[x][y].needsUpdate = true;
        !            91:                 displayBuffer[x][y].backColorComponents[0] = clamp(displayBuffer[x][y].backColorComponents[0] + hCol.red * hiliteStrength / 100, 0, 100);
        !            92:                 displayBuffer[x][y].backColorComponents[1] = clamp(displayBuffer[x][y].backColorComponents[1] + hCol.green * hiliteStrength / 100, 0, 100);
        !            93:                 displayBuffer[x][y].backColorComponents[2] = clamp(displayBuffer[x][y].backColorComponents[2] + hCol.blue * hiliteStrength / 100, 0, 100);
        !            94:                 displayBuffer[x][y].foreColorComponents[0] = clamp(displayBuffer[x][y].foreColorComponents[0] + hCol.red * hiliteStrength / 100, 0, 100);
        !            95:                 displayBuffer[x][y].foreColorComponents[1] = clamp(displayBuffer[x][y].foreColorComponents[1] + hCol.green * hiliteStrength / 100, 0, 100);
        !            96:                 displayBuffer[x][y].foreColorComponents[2] = clamp(displayBuffer[x][y].foreColorComponents[2] + hCol.blue * hiliteStrength / 100, 0, 100);
        !            97:             }
        !            98:         }
        !            99:     }
        !           100:     restoreRNG;
        !           101: }
        !           102:
        !           103: void findReplaceGrid(short **grid, short findValueMin, short findValueMax, short fillValue) {
        !           104:     short i, j;
        !           105:
        !           106:     for(i = 0; i < DCOLS; i++) {
        !           107:         for(j = 0; j < DROWS; j++) {
        !           108:             if (grid[i][j] >= findValueMin && grid[i][j] <= findValueMax) {
        !           109:                 grid[i][j] = fillValue;
        !           110:             }
        !           111:         }
        !           112:     }
        !           113: }
        !           114:
        !           115: // Flood-fills the grid from (x, y) along cells that are within the eligible range.
        !           116: // Returns the total count of filled cells.
        !           117: short floodFillGrid(short **grid, short x, short y, short eligibleValueMin, short eligibleValueMax, short fillValue) {
        !           118:     enum directions dir;
        !           119:     short newX, newY, fillCount = 1;
        !           120:
        !           121:     brogueAssert(fillValue < eligibleValueMin || fillValue > eligibleValueMax);
        !           122:
        !           123:     grid[x][y] = fillValue;
        !           124:     for (dir = 0; dir < 4; dir++) {
        !           125:         newX = x + nbDirs[dir][0];
        !           126:         newY = y + nbDirs[dir][1];
        !           127:         if (coordinatesAreInMap(newX, newY)
        !           128:             && grid[newX][newY] >= eligibleValueMin
        !           129:             && grid[newX][newY] <= eligibleValueMax) {
        !           130:             fillCount += floodFillGrid(grid, newX, newY, eligibleValueMin, eligibleValueMax, fillValue);
        !           131:         }
        !           132:     }
        !           133:     return fillCount;
        !           134: }
        !           135:
        !           136: void drawRectangleOnGrid(short **grid, short x, short y, short width, short height, short value) {
        !           137:     short i, j;
        !           138:
        !           139:     for (i=x; i < x+width; i++) {
        !           140:         for (j=y; j<y+height; j++) {
        !           141:             grid[i][j] = value;
        !           142:         }
        !           143:     }
        !           144: }
        !           145:
        !           146: void drawCircleOnGrid(short **grid, short x, short y, short radius, short value) {
        !           147:     short i, j;
        !           148:
        !           149:     for (i=max(0, x - radius - 1); i < max(DCOLS, x + radius); i++) {
        !           150:         for (j=max(0, y - radius - 1); j < max(DROWS, y + radius); j++) {
        !           151:             if ((i-x)*(i-x) + (j-y)*(j-y) < radius * radius + radius) {
        !           152:                 grid[i][j] = value;
        !           153:             }
        !           154:         }
        !           155:     }
        !           156: }
        !           157:
        !           158: void intersectGrids(short **onto, short **from) {
        !           159:     short i, j;
        !           160:     for(i = 0; i < DCOLS; i++) {
        !           161:         for(j = 0; j < DROWS; j++) {
        !           162:             if (onto[i][j] && from[i][j]) {
        !           163:                 onto[i][j] = true;
        !           164:             } else {
        !           165:                 onto[i][j] = false;
        !           166:             }
        !           167:         }
        !           168:     }
        !           169: }
        !           170:
        !           171: void uniteGrids(short **onto, short **from) {
        !           172:     short i, j;
        !           173:     for(i = 0; i < DCOLS; i++) {
        !           174:         for(j = 0; j < DROWS; j++) {
        !           175:             if (!onto[i][j] && from[i][j]) {
        !           176:                 onto[i][j] = from[i][j];
        !           177:             }
        !           178:         }
        !           179:     }
        !           180: }
        !           181:
        !           182: void invertGrid(short **grid) {
        !           183:     short i, j;
        !           184:     for(i = 0; i < DCOLS; i++) {
        !           185:         for(j = 0; j < DROWS; j++) {
        !           186:             grid[i][j] = !grid[i][j];
        !           187:         }
        !           188:     }
        !           189: }
        !           190:
        !           191: // Fills grid locations with the given value if they match any terrain flags or map flags.
        !           192: // Otherwise does not change the grid location.
        !           193: void getTerrainGrid(short **grid, short value, unsigned long terrainFlags, unsigned long mapFlags) {
        !           194:     short i, j;
        !           195:     for(i = 0; i < DCOLS; i++) {
        !           196:         for(j = 0; j < DROWS; j++) {
        !           197:             if (grid[i][j] != value && cellHasTerrainFlag(i, j, terrainFlags) || (pmap[i][j].flags & mapFlags)) {
        !           198:                 grid[i][j] = value;
        !           199:             }
        !           200:         }
        !           201:     }
        !           202: }
        !           203:
        !           204: void getTMGrid(short **grid, short value, unsigned long TMflags) {
        !           205:     short i, j;
        !           206:     for(i = 0; i < DCOLS; i++) {
        !           207:         for(j = 0; j < DROWS; j++) {
        !           208:             if (grid[i][j] != value && cellHasTMFlag(i, j, TMflags)) {
        !           209:                 grid[i][j] = value;
        !           210:             }
        !           211:         }
        !           212:     }
        !           213: }
        !           214:
        !           215: void getPassableArcGrid(short **grid, short minPassableArc, short maxPassableArc, short value) {
        !           216:     short i, j, count;
        !           217:     for(i = 0; i < DCOLS; i++) {
        !           218:         for(j = 0; j < DROWS; j++) {
        !           219:             if (grid[i][j] != value) {
        !           220:                 count = passableArcCount(i, j);
        !           221:                 if (count >= minPassableArc && count <= maxPassableArc) {
        !           222:                     grid[i][j] = value;
        !           223:                 }
        !           224:             }
        !           225:         }
        !           226:     }
        !           227: }
        !           228:
        !           229: short validLocationCount(short **grid, short validValue) {
        !           230:     short i, j, count;
        !           231:     count = 0;
        !           232:     for(i = 0; i < DCOLS; i++) {
        !           233:         for(j = 0; j < DROWS; j++) {
        !           234:             if (grid[i][j] == validValue) {
        !           235:                 count++;
        !           236:             }
        !           237:         }
        !           238:     }
        !           239:     return count;
        !           240: }
        !           241:
        !           242: short leastPositiveValueInGrid(short **grid) {
        !           243:     short i, j, leastPositiveValue = 0;
        !           244:     for(i = 0; i < DCOLS; i++) {
        !           245:         for(j = 0; j < DROWS; j++) {
        !           246:             if (grid[i][j] > 0 && (leastPositiveValue == 0 || grid[i][j] < leastPositiveValue)) {
        !           247:                 leastPositiveValue = grid[i][j];
        !           248:             }
        !           249:         }
        !           250:     }
        !           251:     return leastPositiveValue;
        !           252: }
        !           253:
        !           254: // Takes a grid as a mask of valid locations, chooses one randomly and returns it as (x, y).
        !           255: // If there are no valid locations, returns (-1, -1).
        !           256: void randomLocationInGrid(short **grid, short *x, short *y, short validValue) {
        !           257:     const short locationCount = validLocationCount(grid, validValue);
        !           258:     short i, j;
        !           259:
        !           260:     if (locationCount <= 0) {
        !           261:         *x = *y = -1;
        !           262:         return;
        !           263:     }
        !           264:     short index = rand_range(0, locationCount - 1);
        !           265:     for(i = 0; i < DCOLS && index >= 0; i++) {
        !           266:         for(j = 0; j < DROWS && index >= 0; j++) {
        !           267:             if (grid[i][j] == validValue) {
        !           268:                 if (index == 0) {
        !           269:                     *x = i;
        !           270:                     *y = j;
        !           271:                 }
        !           272:                 index--;
        !           273:             }
        !           274:         }
        !           275:     }
        !           276:     return;
        !           277: }
        !           278:
        !           279: // Finds the lowest positive number in a grid, chooses one location with that number randomly and returns it as (x, y).
        !           280: // If there are no valid locations, returns (-1, -1).
        !           281: void randomLeastPositiveLocationInGrid(short **grid, short *x, short *y, boolean deterministic) {
        !           282:     const short targetValue = leastPositiveValueInGrid(grid);
        !           283:     short locationCount;
        !           284:     short i, j, index;
        !           285:
        !           286:     if (targetValue == 0) {
        !           287:         *x = *y = -1;
        !           288:         return;
        !           289:     }
        !           290:
        !           291:     locationCount = 0;
        !           292:     for(i = 0; i < DCOLS; i++) {
        !           293:         for(j = 0; j < DROWS; j++) {
        !           294:             if (grid[i][j] == targetValue) {
        !           295:                 locationCount++;
        !           296:             }
        !           297:         }
        !           298:     }
        !           299:
        !           300:     if (deterministic) {
        !           301:         index = locationCount / 2;
        !           302:     } else {
        !           303:         index = rand_range(0, locationCount - 1);
        !           304:     }
        !           305:
        !           306:     for(i = 0; i < DCOLS && index >= 0; i++) {
        !           307:         for(j = 0; j < DROWS && index >= 0; j++) {
        !           308:             if (grid[i][j] == targetValue) {
        !           309:                 if (index == 0) {
        !           310:                     *x = i;
        !           311:                     *y = j;
        !           312:                 }
        !           313:                 index--;
        !           314:             }
        !           315:         }
        !           316:     }
        !           317:     return;
        !           318: }
        !           319:
        !           320: boolean getQualifyingPathLocNear(short *retValX, short *retValY,
        !           321:                                  short x, short y,
        !           322:                                  boolean hallwaysAllowed,
        !           323:                                  unsigned long blockingTerrainFlags,
        !           324:                                  unsigned long blockingMapFlags,
        !           325:                                  unsigned long forbiddenTerrainFlags,
        !           326:                                  unsigned long forbiddenMapFlags,
        !           327:                                  boolean deterministic) {
        !           328:     short **grid, **costMap;
        !           329:     short loc[2];
        !           330:
        !           331:     // First check the given location to see if it works, as an optimization.
        !           332:     if (!cellHasTerrainFlag(x, y, blockingTerrainFlags | forbiddenTerrainFlags)
        !           333:         && !(pmap[x][y].flags & (blockingMapFlags | forbiddenMapFlags))
        !           334:         && (hallwaysAllowed || passableArcCount(x, y) <= 1)) {
        !           335:
        !           336:         *retValX = x;
        !           337:         *retValY = y;
        !           338:         return true;
        !           339:     }
        !           340:
        !           341:     // Allocate the grids.
        !           342:     grid = allocGrid();
        !           343:     costMap = allocGrid();
        !           344:
        !           345:     // Start with a base of a high number everywhere.
        !           346:     fillGrid(grid, 30000);
        !           347:     fillGrid(costMap, 1);
        !           348:
        !           349:     // Block off the pathing blockers.
        !           350:     getTerrainGrid(costMap, PDS_FORBIDDEN, blockingTerrainFlags, blockingMapFlags);
        !           351:     if (blockingTerrainFlags & (T_OBSTRUCTS_DIAGONAL_MOVEMENT | T_OBSTRUCTS_PASSABILITY)) {
        !           352:         getTerrainGrid(costMap, PDS_OBSTRUCTION, T_OBSTRUCTS_DIAGONAL_MOVEMENT, 0);
        !           353:     }
        !           354:
        !           355:     // Run the distance scan.
        !           356:     grid[x][y] = 1;
        !           357:     costMap[x][y] = 1;
        !           358:     dijkstraScan(grid, costMap, true);
        !           359:     findReplaceGrid(grid, 30000, 30000, 0);
        !           360:
        !           361:     // Block off invalid targets that aren't pathing blockers.
        !           362:     getTerrainGrid(grid, 0, forbiddenTerrainFlags, forbiddenMapFlags);
        !           363:     if (!hallwaysAllowed) {
        !           364:         getPassableArcGrid(grid, 2, 10, 0);
        !           365:     }
        !           366:
        !           367:     // Get the solution.
        !           368:     randomLeastPositiveLocationInGrid(grid, retValX, retValY, deterministic);
        !           369:
        !           370: //    dumpLevelToScreen();
        !           371: //    displayGrid(grid);
        !           372: //    if (coordinatesAreInMap(*retValX, *retValY)) {
        !           373: //        hiliteCell(*retValX, *retValY, &yellow, 100, true);
        !           374: //    }
        !           375: //    temporaryMessage("Qualifying path selected:", true);
        !           376:
        !           377:     freeGrid(grid);
        !           378:     freeGrid(costMap);
        !           379:
        !           380:     // Fall back to a pathing-agnostic alternative if there are no solutions.
        !           381:     if (*retValX == -1 && *retValY == -1) {
        !           382:         if (getQualifyingLocNear(loc, x, y, hallwaysAllowed, NULL,
        !           383:                                  (blockingTerrainFlags | forbiddenTerrainFlags),
        !           384:                                  (blockingMapFlags | forbiddenMapFlags),
        !           385:                                  false, deterministic)) {
        !           386:             *retValX = loc[0];
        !           387:             *retValY = loc[1];
        !           388:             return true; // Found a fallback solution.
        !           389:         } else {
        !           390:             return false; // No solutions.
        !           391:         }
        !           392:     } else {
        !           393:         return true; // Found a primary solution.
        !           394:     }
        !           395: }
        !           396:
        !           397: void cellularAutomataRound(short **grid, char birthParameters[9], char survivalParameters[9]) {
        !           398:     short i, j, nbCount, newX, newY;
        !           399:     enum directions dir;
        !           400:     short **buffer2;
        !           401:
        !           402:     buffer2 = allocGrid();
        !           403:     copyGrid(buffer2, grid); // Make a backup of grid in buffer2, so that each generation is isolated.
        !           404:
        !           405:     for(i=0; i<DCOLS; i++) {
        !           406:         for(j=0; j<DROWS; j++) {
        !           407:             nbCount = 0;
        !           408:             for (dir=0; dir< DIRECTION_COUNT; dir++) {
        !           409:                 newX = i + nbDirs[dir][0];
        !           410:                 newY = j + nbDirs[dir][1];
        !           411:                 if (coordinatesAreInMap(newX, newY)
        !           412:                     && buffer2[newX][newY]) {
        !           413:
        !           414:                     nbCount++;
        !           415:                 }
        !           416:             }
        !           417:             if (!buffer2[i][j] && birthParameters[nbCount] == 't') {
        !           418:                 grid[i][j] = 1; // birth
        !           419:             } else if (buffer2[i][j] && survivalParameters[nbCount] == 't') {
        !           420:                 // survival
        !           421:             } else {
        !           422:                 grid[i][j] = 0; // death
        !           423:             }
        !           424:         }
        !           425:     }
        !           426:
        !           427:     freeGrid(buffer2);
        !           428: }
        !           429:
        !           430: // Marks a cell as being a member of blobNumber, then recursively iterates through the rest of the blob
        !           431: short fillContiguousRegion(short **grid, short x, short y, short fillValue) {
        !           432:     enum directions dir;
        !           433:     short newX, newY, numberOfCells = 1;
        !           434:
        !           435:     grid[x][y] = fillValue;
        !           436:
        !           437:     // Iterate through the four cardinal neighbors.
        !           438:     for (dir=0; dir<4; dir++) {
        !           439:         newX = x + nbDirs[dir][0];
        !           440:         newY = y + nbDirs[dir][1];
        !           441:         if (!coordinatesAreInMap(newX, newY)) {
        !           442:             break;
        !           443:         }
        !           444:         if (grid[newX][newY] == 1) { // If the neighbor is an unmarked region cell,
        !           445:             numberOfCells += fillContiguousRegion(grid, newX, newY, fillValue); // then recurse.
        !           446:         }
        !           447:     }
        !           448:     return numberOfCells;
        !           449: }
        !           450:
        !           451: // Loads up **grid with the results of a cellular automata simulation.
        !           452: void createBlobOnGrid(short **grid,
        !           453:                       short *retMinX, short *retMinY, short *retWidth, short *retHeight,
        !           454:                       short roundCount,
        !           455:                       short minBlobWidth, short minBlobHeight,
        !           456:                       short maxBlobWidth, short maxBlobHeight, short percentSeeded,
        !           457:                       char birthParameters[9], char survivalParameters[9]) {
        !           458:
        !           459:     short i, j, k;
        !           460:     short blobNumber, blobSize, topBlobNumber, topBlobSize;
        !           461:
        !           462:     short topBlobMinX, topBlobMinY, topBlobMaxX, topBlobMaxY, blobWidth, blobHeight;
        !           463:     //short buffer2[maxBlobWidth][maxBlobHeight]; // buffer[][] is already a global short array
        !           464:     boolean foundACellThisLine;
        !           465:
        !           466:     // Generate blobs until they satisfy the minBlobWidth and minBlobHeight restraints
        !           467:     do {
        !           468:         // Clear buffer.
        !           469:         fillGrid(grid, 0);
        !           470:
        !           471:         // Fill relevant portion with noise based on the percentSeeded argument.
        !           472:         for(i=0; i<maxBlobWidth; i++) {
        !           473:             for(j=0; j<maxBlobHeight; j++) {
        !           474:                 grid[i][j] = (rand_percent(percentSeeded) ? 1 : 0);
        !           475:             }
        !           476:         }
        !           477:
        !           478: //        colorOverDungeon(&darkGray);
        !           479: //        hiliteGrid(grid, &white, 100);
        !           480: //        temporaryMessage("Random starting noise:", true);
        !           481:
        !           482:         // Some iterations of cellular automata
        !           483:         for (k=0; k<roundCount; k++) {
        !           484:             cellularAutomataRound(grid, birthParameters, survivalParameters);
        !           485:
        !           486: //            colorOverDungeon(&darkGray);
        !           487: //            hiliteGrid(grid, &white, 100);
        !           488: //            temporaryMessage("Cellular automata progress:", true);
        !           489:         }
        !           490:
        !           491: //        colorOverDungeon(&darkGray);
        !           492: //        hiliteGrid(grid, &white, 100);
        !           493: //        temporaryMessage("Cellular automata result:", true);
        !           494:
        !           495:         // Now to measure the result. These are best-of variables; start them out at worst-case values.
        !           496:         topBlobSize =   0;
        !           497:         topBlobNumber = 0;
        !           498:         topBlobMinX =   maxBlobWidth;
        !           499:         topBlobMaxX =   0;
        !           500:         topBlobMinY =   maxBlobHeight;
        !           501:         topBlobMaxY =   0;
        !           502:
        !           503:         // Fill each blob with its own number, starting with 2 (since 1 means floor), and keeping track of the biggest:
        !           504:         blobNumber = 2;
        !           505:
        !           506:         for(i=0; i<DCOLS; i++) {
        !           507:             for(j=0; j<DROWS; j++) {
        !           508:                 if (grid[i][j] == 1) { // an unmarked blob
        !           509:                     // Mark all the cells and returns the total size:
        !           510:                     blobSize = fillContiguousRegion(grid, i, j, blobNumber);
        !           511:                     if (blobSize > topBlobSize) { // if this blob is a new record
        !           512:                         topBlobSize = blobSize;
        !           513:                         topBlobNumber = blobNumber;
        !           514:                     }
        !           515:                     blobNumber++;
        !           516:                 }
        !           517:             }
        !           518:         }
        !           519:
        !           520:         // Figure out the top blob's height and width:
        !           521:         // First find the max & min x:
        !           522:         for(i=0; i<DCOLS; i++) {
        !           523:             foundACellThisLine = false;
        !           524:             for(j=0; j<DROWS; j++) {
        !           525:                 if (grid[i][j] == topBlobNumber) {
        !           526:                     foundACellThisLine = true;
        !           527:                     break;
        !           528:                 }
        !           529:             }
        !           530:             if (foundACellThisLine) {
        !           531:                 if (i < topBlobMinX) {
        !           532:                     topBlobMinX = i;
        !           533:                 }
        !           534:                 if (i > topBlobMaxX) {
        !           535:                     topBlobMaxX = i;
        !           536:                 }
        !           537:             }
        !           538:         }
        !           539:
        !           540:         // Then the max & min y:
        !           541:         for(j=0; j<DROWS; j++) {
        !           542:             foundACellThisLine = false;
        !           543:             for(i=0; i<DCOLS; i++) {
        !           544:                 if (grid[i][j] == topBlobNumber) {
        !           545:                     foundACellThisLine = true;
        !           546:                     break;
        !           547:                 }
        !           548:             }
        !           549:             if (foundACellThisLine) {
        !           550:                 if (j < topBlobMinY) {
        !           551:                     topBlobMinY = j;
        !           552:                 }
        !           553:                 if (j > topBlobMaxY) {
        !           554:                     topBlobMaxY = j;
        !           555:                 }
        !           556:             }
        !           557:         }
        !           558:
        !           559:         blobWidth =     (topBlobMaxX - topBlobMinX) + 1;
        !           560:         blobHeight =    (topBlobMaxY - topBlobMinY) + 1;
        !           561:
        !           562:     } while (blobWidth < minBlobWidth
        !           563:              || blobHeight < minBlobHeight
        !           564:              || topBlobNumber == 0);
        !           565:
        !           566:     // Replace the winning blob with 1's, and everything else with 0's:
        !           567:     for(i=0; i<DCOLS; i++) {
        !           568:         for(j=0; j<DROWS; j++) {
        !           569:             if (grid[i][j] == topBlobNumber) {
        !           570:                 grid[i][j] = 1;
        !           571:             } else {
        !           572:                 grid[i][j] = 0;
        !           573:             }
        !           574:         }
        !           575:     }
        !           576:
        !           577:     // Populate the returned variables.
        !           578:     *retMinX = topBlobMinX;
        !           579:     *retMinY = topBlobMinY;
        !           580:     *retWidth = blobWidth;
        !           581:     *retHeight = blobHeight;
        !           582: }

CVSweb