/* save_indexed: * Core save routine for 8 bpp images. * */ static int save_indexed(png_structp png_ptr, BITMAP *bmp) { ASSERT(bitmap_color_depth(bmp) == 8); if (is_memory_bitmap(bmp)) { /* fast path */ int y; for (y=0; y<bmp->h; y++) { png_write_row(png_ptr, bmp->line[y]); } return 1; } else { /* generic case */ unsigned char *rowdata; int x, y; rowdata = (unsigned char *)malloc(bmp->w * 3); if (!rowdata) return 0; for (y=0; y<bmp->h; y++) { unsigned char *p = rowdata; for (x=0; x<bmp->w; x++) { *p++ = getpixel(bmp, x, y); } png_write_row(png_ptr, rowdata); } free(rowdata); return 1; } }
int is_route_possible(int fromx, int fromy, int tox, int toy, block wss) { wallscreen = wss; suggestx = -1; // ensure it's a memory bitmap, so we can use direct access to line[] array if ((wss == NULL) || (!is_memory_bitmap(wss)) || (bitmap_color_depth(wss) != 8)) quit("is_route_possible: invalid walkable areas bitmap supplied"); if (getpixel(wallscreen, fromx, fromy) < 1) return 0; block tempw = create_bitmap_ex(8, wallscreen->w, wallscreen->h); if (tempw == NULL) quit("no memory for route calculation"); if (!is_memory_bitmap(tempw)) quit("tempw is not memory bitmap"); blit(wallscreen, tempw, 0, 0, 0, 0, tempw->w, tempw->h); int dd, ff; // initialize array for finding widths of walkable areas int thisar, inarow = 0, lastarea = 0; int walk_area_times[MAX_WALK_AREAS + 1]; for (dd = 0; dd <= MAX_WALK_AREAS; dd++) { walk_area_times[dd] = 0; walk_area_granularity[dd] = 0; } for (ff = 0; ff < tempw->h; ff++) { for (dd = 0; dd < tempw->w; dd++) { thisar = tempw->line[ff][dd]; // count how high the area is at this point if ((thisar == lastarea) && (thisar > 0)) inarow++; else if (lastarea > MAX_WALK_AREAS) quit("!Calculate_Route: invalid colours in walkable area mask"); else if (lastarea != 0) { walk_area_granularity[lastarea] += inarow; walk_area_times[lastarea]++; inarow = 0; } lastarea = thisar; } } for (dd = 0; dd < tempw->w; dd++) { for (ff = 0; ff < tempw->h; ff++) { thisar = tempw->line[ff][dd]; if (thisar > 0) putpixel(tempw, dd, ff, 1); // count how high the area is at this point if ((thisar == lastarea) && (thisar > 0)) inarow++; else if (lastarea != 0) { walk_area_granularity[lastarea] += inarow; walk_area_times[lastarea]++; inarow = 0; } lastarea = thisar; } } // find the average "width" of a path in this walkable area for (dd = 1; dd <= MAX_WALK_AREAS; dd++) { if (walk_area_times[dd] == 0) { walk_area_granularity[dd] = MAX_GRANULARITY; continue; } walk_area_granularity[dd] /= walk_area_times[dd]; if (walk_area_granularity[dd] <= 4) walk_area_granularity[dd] = 2; else if (walk_area_granularity[dd] <= 15) walk_area_granularity[dd] = 3; else walk_area_granularity[dd] = MAX_GRANULARITY; /*char toprnt[200]; sprintf(toprnt,"area %d: Gran %d", dd, walk_area_granularity[dd]); winalert(toprnt); */ } walk_area_granularity[0] = MAX_GRANULARITY; floodfill(tempw, fromx, fromy, 232); if (getpixel(tempw, tox, toy) != 232) { // Destination pixel is not walkable // Try the 100x100 square around the target first at 3-pixel granularity int tryFirstX = tox - 50, tryToX = tox + 50; int tryFirstY = toy - 50, tryToY = toy + 50; if (!find_nearest_walkable_area(tempw, tryFirstX, tryFirstY, tryToX, tryToY, tox, toy, 3)) { // Nothing found, sweep the whole room at 5 pixel granularity find_nearest_walkable_area(tempw, 0, 0, tempw->w, tempw->h, tox, toy, 5); } wfreeblock(tempw); return 0; } wfreeblock(tempw); return 1; }