#include "ktkMap.h" #include // malloc #include // printf, remove #include // round /* ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, const declarations, etc. ```````````````````````````````` */ const struct ktkMap ktk_MAP_DEFAULT = { 0, 0, 0, 0, 0, NULL }; const struct ktkCell ktk_CELL_DEFAULT = { 0, 0, // id_1, id_2 NULL, 0, ktk_CELL_EMPTY|ktk_CELL_CELL_DELETE, // data, size, flags NULL, 0 // contained cell(s), count of contained }; /* ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, Functions ```````````````````````````````` */ /*int ktk_resizeMap(struct ktkMap *map, int w, int h) { int x, y; int delta_w = w - map->w; int delta_h = h - map->h; if (w < 0 || h < 0) return 1; // delete out of bound cells. if (delta_w < 0) { for (x = map->w-1; x > w; x--) { for (y = map->h-1; y > h; y--) { ktk_deleteCell(&map->cell[x][y]); } } } if (delta_h < 0) { for (y = map->h-1; y > h; y--) { for (x = map->w-1; x > w; x--) { ktk_deleteCell(&map->cell[x][y]); } } } // free out of bound cells for (x = w; x < map->w; x++) { free(map->cell[x]); } // resize :) if ((map->cell = realloc(map->cell, w * sizeof(struct ktkCell*))) != NULL) { if (delta_w > 0) { for (x = map->w; x < w; x++) { if ((map->cell[x] = malloc(h * sizeof(struct ktkCell))) == NULL) { // uhoh, ran out of memory. Report error, but set width to as far as we got w = x; int xf = x; for (xf = x; xf > 0; xf--) { free(map->cell[xf]); } break; } } } } else { // major problem, couldn't realloc at all. Cancel operation. :S // TODO: set error code? return 2; } // realloc old x pointers if height has grown if (delta_h > 0) { for (x = 0; x < w; x++) { // laziness if ((map->cell[x] = realloc(map->cell[x], h * sizeof(struct ktkCell))) == NULL) { // MORE REPORTING ERRORS } } } // initialize new cells if (delta_w > 0) { for (x = map->w; x < w; x++) { for (y = map->h; y < h; y++) { map->cell[x][y] = ktk_CELL_DEFAULT; } } } if (delta_h > 0) { for (y = map->h; y < h; y++) { for (x = 0; x < w; x++) { map->cell[x][y] = ktk_CELL_DEFAULT; } } } map->w = w; map->h = h; // okay! return 0; }*/ int ktk_resizeMap(struct ktkMap *map, int w, int h) { if (w < map->w) { int i; for (i = w; i < map->w; i++) { int j; for (j = 0; j < map->h; j++) { ktk_deleteCell(&(map->cell[i][j])); } } } if (h < map->h) { int i; for (i = 0; i < map->w; i++) { int j; for (j = h; j < map->h; j++) { ktk_deleteCell(&(map->cell[i][j])); } } } map->cell = realloc(map->cell, w * sizeof(struct ktkCell*)); int i; for (i = map->w; i < w; i++) { map->cell[i] = NULL; } for (i = 0; i < w; i++) { map->cell[i] = realloc(map->cell[i], h * sizeof(struct ktkCell)); int j; for (j = 0; j < h; j++) { //ktk_copyCell(&ktk_CELL_DEFAULT, &(map->cell[i][j])); if (i >= map->w) { map->cell[i][j] = ktk_CELL_DEFAULT; } else { if (j >= map->h) { map->cell[i][j] = ktk_CELL_DEFAULT; } } } } map->w = w; map->h = h; return 0; } int ktk_copyMap(struct ktkMap *map_1, struct ktkMap *map_2) { int x, y; ktk_deleteMap(map_2); map_2->flags = map_1->flags; map_2->x = map_1->x; map_2->y = map_1->y; ktk_resizeMap(map_2, map_1->w, map_1->h); for (x = 0; x < map_1->w; x++) { for (y = 0; y< map_1->h; y++) { ktk_copyCell(&map_1->cell[x][y], &map_2->cell[x][y]); } } return 0; } int ktk_mergeMaps(struct ktkMap *map_1, struct ktkMap *map_2) { int max_x = map_2->x + map_2->w; int max_y = map_2->y + map_2->h; if (map_1->flags & ktk_MAP_RESIZE) { if (max_x >= map_1->w) { ktk_resizeMap(map_1, max_x, map_1->h); } if (max_y >= map_1->h) { ktk_resizeMap(map_1, map_1->w, max_y); } } int x, y; for (x = 0; x < map_2->w; x++) { if (map_2->x+x >= map_1->w || map_2->x+x < 0) continue; for (y = 0; y < map_2->h; y++) { if (map_2->y+y >= map_1->h || map_2->y+y < 0) continue; if (map_2->cell[x][y].flags & ktk_CELL_EMPTY) continue; // TODO: don't delete, but append ktk_deleteCell(&(map_1->cell[map_2->x+x][map_2->y+y])); ktk_copyCell(&(map_2->cell[x][y]), &(map_1->cell[map_2->x+x][map_2->y+y])); } } return 0; } int ktk_deleteMap(struct ktkMap *map) { int x, y; for (x = 0; x < map->w; x++) { for (y = 0; y < map->h; y++) { ktk_deleteCell(&map->cell[x][y]); } free(map->cell[x]); } free(map->cell); map->w = 0; map->h = 0; map->cell = NULL; return 0; } int ktk_checkMapOverlap(struct ktkMap *map_1, struct ktkMap *map_2) { int x, y; for (x = 0; x < map_2->w; x++) { if (map_2->x+x >= map_1->w || map_2->x+x < 0) continue; for (y = 0; y < map_2->h; y++) { if (map_2->y+y >= map_1->h || map_2->y+y < 0) continue; //printf("%dx%d(%d|%d) vs %dx%d(%d|%d)\n", x, y, map_2->cell[x][y].id_1, map_2->cell[x][y].flags, map_2->x+x, map_2->y+y, map_1->cell[map_2->x+x][map_2->y+y].id_1, map_1->cell[map_2->x+x][map_2->y+y].flags); //printf("%d (%d)\n", map_2->cell[x][y].flags & ktk_CELL_EMPTY, ktk_CELL_EMPTY); //printf("%d (%d)\n", map_1->cell[map_2->x+x][map_2->y+y].flags & ktk_CELL_EMPTY, ktk_CELL_EMPTY); if (map_2->cell[x][y].flags & ktk_CELL_EMPTY) continue; if (map_1->cell[map_2->x+x][map_2->y+y].flags & ktk_CELL_EMPTY) continue; return 1; } } return 0; } int ktk_unsetMapCell(struct ktkMap *map, int x, int y) { if (x < 0 || x > map->w) return 1; if (y < 0 || y > map->h) return 1; map->cell[x][y].flags |= ktk_CELL_EMPTY; return 0; } int ktk_setMapCell(struct ktkMap *map, int x, int y) { if (x < 0 || x >= map->w) return 1; if (y < 0 || y >= map->h) return 1; map->cell[x][y].flags &= ~ktk_CELL_EMPTY; return 0; } struct ktkMap *ktk_borderCells(struct ktkMap *map, struct ktkMap *new_map) { ktk_resizeMap(new_map, map->w, map->h); int x = map->x, y = map->y; for (x = 0; x < map->w; x++) { for (y = 0; y < map->h; y++) { if (map->cell[x][y].flags & ktk_CELL_EMPTY) continue; // l if (x-1 >= 0 && x < map->w) { if (map->cell[x-1][y].flags & ktk_CELL_EMPTY) { // new_map->cell[x-1][y].flags &= !ktk_CELL_EMPTY; new_map->cell[x][y].flags &= !ktk_CELL_EMPTY; } } else { new_map->cell[x][y].flags &= !ktk_CELL_EMPTY; } // r if (x+1 < map->w) { if (map->cell[x+1][y].flags & ktk_CELL_EMPTY) { //new_map->cell[x+1][y].flags &= !ktk_CELL_EMPTY; new_map->cell[x][y].flags &= !ktk_CELL_EMPTY; } } else { new_map->cell[x][y].flags &= !ktk_CELL_EMPTY; } // u if (y-1 >= 0) { if (map->cell[x][y-1].flags & ktk_CELL_EMPTY) { new_map->cell[x][y].flags &= !ktk_CELL_EMPTY; //new_map->cell[x][y-1].flags &= !ktk_CELL_EMPTY; } // ul if (x-1 >= 0) { if (map->cell[x-1][y-1].flags & ktk_CELL_EMPTY) { //new_map->cell[x+1][y].flags &= !ktk_CELL_EMPTY; new_map->cell[x][y].flags &= !ktk_CELL_EMPTY; } } // ur if (x+1 < map->w) { if (map->cell[x+1][y-1].flags & ktk_CELL_EMPTY) { //new_map->cell[x+1][y].flags &= !ktk_CELL_EMPTY; new_map->cell[x][y].flags &= !ktk_CELL_EMPTY; } } } else { new_map->cell[x][y].flags &= !ktk_CELL_EMPTY; } // d if (y+1 < map->h) { if (map->cell[x][y+1].flags & ktk_CELL_EMPTY) { new_map->cell[x][y].flags &= !ktk_CELL_EMPTY; //new_map->cell[x][y+1].flags &= !ktk_CELL_EMPTY; } // dl if (x-1 >= 0) { if (map->cell[x-1][y+1].flags & ktk_CELL_EMPTY) { //new_map->cell[x+1][y].flags &= !ktk_CELL_EMPTY; new_map->cell[x][y].flags &= !ktk_CELL_EMPTY; } } // dr if (x+1 < map->w) { if (map->cell[x+1][y+1].flags & ktk_CELL_EMPTY) { //new_map->cell[x+1][y].flags &= !ktk_CELL_EMPTY; new_map->cell[x][y].flags &= !ktk_CELL_EMPTY; } } } else { new_map->cell[x][y].flags &= !ktk_CELL_EMPTY; } // ul // ur } } return new_map; } int ktk_fillRect(struct ktkMap *map, int o_x, int o_y, int s_x, int s_y) { int x, y; for (x = 0; x < s_x; x++) { for (y = 0; y < s_y; y++) { ktk_setMapCell(map, o_x+x, o_y+y); } } return 0; } int ktk_fillEllipseBorder(struct ktkMap *map, int r_x, int r_y) { int y = 0; int x = 0; float a, b; r_x /= 2; r_y /= 2; int hw = r_x; int hh = r_y; int o_x = 0; int o_y = 0; a = (r_y*r_y) - (r_x * r_x * r_y) + (r_x * r_x) / 4; while ((2.0 * r_y * r_y * x) <= (2.0 * r_x * r_x * y)) { x++; if (a <= 0) { a = a + (2.0f * r_y * r_y * x) + (r_y * r_y); } else { y--; a = a + (2.0f * r_y * r_y * x) - (2.0f * r_x * r_x * y) + (r_y * r_y); } ktk_setMapCell(map, o_x+x, o_y+y); ktk_setMapCell(map, o_x-x, o_y+y); ktk_setMapCell(map, o_x+x, o_y-y); ktk_setMapCell(map, o_x-x, o_y-y); x = -x; ktk_setMapCell(map, o_x+x, o_y+y); ktk_setMapCell(map, o_x-x, o_y+y); ktk_setMapCell(map, o_x+x, o_y-y); ktk_setMapCell(map, o_x-x, o_y-y); x = -x; } x = r_x; y = 0; ktk_setMapCell(map, o_x+x, o_y+y); ktk_setMapCell(map, o_x-x, o_y+y); ktk_setMapCell(map, o_x+x, o_y-y); ktk_setMapCell(map, o_x-x, o_y-y); b = (r_x * r_x) + 2.0f * (r_y * r_y * r_x) + (r_y * r_y)/4; while ((2.0f * r_y * r_y * x) > (2.0f * r_x * r_x * y)) { y++; if (b > 0) { b = b + (r_x * r_x) - (2.0 * r_x * r_x * y); } else { x--; b = b + (2.0f * r_y * r_y * x) - (2.0f * r_x * r_x * y) + (r_x * r_x); } ktk_setMapCell(map, o_x+x, o_y+y); ktk_setMapCell(map, o_x-x, o_y+y); ktk_setMapCell(map, o_x+x, o_y-y); ktk_setMapCell(map, o_x-x, o_y-y); y = -y; ktk_setMapCell(map, o_x+x, o_y+y); ktk_setMapCell(map, o_x-x, o_y+y); ktk_setMapCell(map, o_x+x, o_y-y); ktk_setMapCell(map, o_x-x, o_y-y); y = -y; } return 0; } int ktk_fillEllipse(struct ktkMap *map, int o_x, int o_y, int r_x, int r_y) { int y; int x; int hw = r_x/2; int hh = r_y/2; for (y = -hh; y <= hh; y++) { for (x = -hw; x <= hw; x++) { double dx = (double)x / (double)hw; double dy = (double)y / (double)hh; if (dx*dx+dy*dy <= 1) { //if(x < 0 || x > r_x || y < 0 || y > r_y) continue; //printf("%dx%d\n", hw+x, hh+y); ktk_setMapCell(map, hw+o_x+x, hh+o_y+y); } } } return 0; } int ktk_fillCircle(struct ktkMap *map, int radius) { int h = radius/2; int x, y; for (x = h-radius; x <= h+radius; x++) { for(y = h-radius; y <= h+radius; y++) { if ((x*x)+(y*y) < (radius*radius)) { if(x < 0 || x > map->x || y < 0 || y > map->y) continue; ktk_setMapCell(map, x, y); } } } return 0; } int ktk_drawLine(struct ktkMap *map, int x1, int y1, int x2, int y2) { int x, y; if (y2-y1 < x2-x1) { for (x = x1; x <= x2; x++) { y = y1 + ((y2-y1)/(x2-x1)) * (x-x1); ktk_setMapCell(map, x, y); } } else { for (y = y1; y <= y2; y++) { x = x1 + ((x2-x1)/(y2-y1)) * (y-y1); ktk_setMapCell(map, x, y); } } return 0; } void ktk_printMap(struct ktkMap *map) { int x, y; for (y = 0; y < map->h; y++) { printf("---\n"); for (x = 0; x < map->w; x++) { printf("%d:%d ", map->cell[x][y].id_1, map->cell[x][y].id_2); } printf("\n"); } } int ktk_deleteCell(struct ktkCell *cell) { if (cell->flags & ktk_CELL_DATA_FREE && cell->data != NULL) { free(cell->data); cell->data_size = 0; cell->data = NULL; } if (cell->flags & ktk_CELL_CELL_DELETE && cell->cell != NULL) { int z; for (z = 0; z < cell->cell_count; z++) { ktk_deleteCell(&(cell->cell[z])); } free(cell->cell); cell->cell = NULL; cell->cell_count = 0; } cell->flags = cell->flags & ~ktk_CELL_EMPTY; return 0; } int ktk_copyCell(struct ktkCell *cell_1, struct ktkCell *cell_2) { *cell_2 = *cell_1; if (cell_1->data != NULL) { cell_2->data = malloc(cell_1->data_size); memcpy(cell_2->data, cell_1->data, cell_1->data_size); } if (cell_1->cell != NULL) { int i; cell_2->cell = malloc(sizeof(struct ktkCell)*cell_1->cell_count); for (i = 0; i < cell_1->cell_count; i++) { ktk_copyCell(&cell_1->cell[i], &cell_2->cell[i]); } } return 0; }