/* * Copyright (C) 2003 Tim Martin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include #include #include #include "heightmap.h" #define MAXHEIGHTDIFFERENCE 1 #define MAPPOS(mapstruct, x, y) mapstruct->map[ ((y) * (mapstruct->sizex+1)) + (x)] struct heightmap_s { int sizex; int sizey; char *map; }; int heightmap_init(int sizex, int sizey, heightmap_t **map) { heightmap_t *ret; ret = malloc(sizeof(heightmap_t)); if (!ret) return -1; memset(ret, 0, sizeof(heightmap_t)); ret->sizex = sizex; ret->sizey = sizey; ret->map = malloc(sizeof(char)*(sizex+1)*(sizey+1)); if (!ret->map) return -1; memset(ret->map, DEFAULT_HEIGHT, sizeof(char)*(sizex+1)*(sizey+1)); *map = ret; return 0; } int heightmap_getsize_x(heightmap_t *map) { return map->sizex; } int heightmap_getsize_y(heightmap_t *map) { return map->sizey; } int heightmap_getheight(heightmap_t *map, int x, int y, int dirview, heightsquare_t *square) { if ((x < 0) || (x > map->sizex - 1) || (y < 0) || (y > map->sizey - 1)) { return -1; } square->index[(0+dirview+4)%4] = MAPPOS(map,x ,y ); square->index[(1+dirview+4)%4] = MAPPOS(map,x+1,y ); square->index[(2+dirview+4)%4] = MAPPOS(map,x+1,y+1); square->index[(3+dirview+4)%4] = MAPPOS(map,x ,y+1); return 0; } int heightmap_get(heightmap_t *map, int x, int y) { return MAPPOS(map, x, y); } int heightmap_can_changeheight(heightmap_t *map, int x, int y, int change) { int newheight; newheight = MAPPOS(map,x,y) + change; if (x > 0) if (abs(newheight - MAPPOS(map,x-1,y)) > MAXHEIGHTDIFFERENCE) { /*printf("diff btwn %d,%d and %d,%d too big\n",x,y,x-1,y);*/ return 0; } if (x < map->sizex-1) if (abs(newheight - MAPPOS(map,x+1,y)) > MAXHEIGHTDIFFERENCE) { /*printf("diff btwn %d,%d and %d,%d too big\n",x,y,x+1,y);*/ return 0; } if (y > 0) if (abs(newheight - MAPPOS(map,x,y-1)) > MAXHEIGHTDIFFERENCE) { /*printf("diff btwn %d,%d and %d,%d too big\n",x,y,x,y-1);*/ return 0; } if (y < map->sizey-1) if (abs(newheight - MAPPOS(map,x,y+1)) > MAXHEIGHTDIFFERENCE) { /*printf("diff btwn %d,%d and %d,%d too big\n",x,y,x,y+1);*/ return 0; } if ((x > 0) && (y > 0)) if (abs(newheight - MAPPOS(map,x-1,y-1)) > MAXHEIGHTDIFFERENCE) { /*printf("diff btwn %d,%d and %d,%d too big\n",x,y,x-1,y);*/ return 0; } if ((x < map->sizex-1) && (y > 0)) if (abs(newheight - MAPPOS(map,x+1,y-1)) > MAXHEIGHTDIFFERENCE) { /*printf("diff btwn %d,%d and %d,%d too big\n",x,y,x-1,y);*/ return 0; } if ((x < map->sizex-1) && (y < map->sizey-1)) if (abs(newheight - MAPPOS(map,x+1,y+1)) > MAXHEIGHTDIFFERENCE) { /*printf("diff btwn %d,%d and %d,%d too big\n",x,y,x-1,y);*/ return 0; } if ((x > 0) && (y < map->sizey-1)) if (abs(newheight - MAPPOS(map,x-1,y+1)) > MAXHEIGHTDIFFERENCE) { /*printf("diff btwn %d,%d and %d,%d too big\n",x,y,x-1,y);*/ return 0; } return 1; } static int heightmap_changeheight(heightmap_t *map, int x, int y, int change, int checkdiffs) { /* sanity check */ if ((x < 0) || (x >= map->sizex)) return -1; if ((y < 0) || (y >= map->sizey)) return -1; /* can't be more than MAXHEIGHTDIFFERENCE away from any of it's neighbors */ if (checkdiffs) { if (!heightmap_can_changeheight(map, x, y, change)) { return -1; } } MAPPOS(map,x,y) += change; if (x == map->sizex-1) { MAPPOS(map,x+1,y) = MAPPOS(map,x,y); } if (y == map->sizey-1) { MAPPOS(map,x,y+1) = MAPPOS(map,x,y); } if ((x == map->sizex-1) && (y == map->sizey-1)) { MAPPOS(map,x+1,y+1) = MAPPOS(map,x,y); } return 0; } int heightmap_raise(heightmap_t *map, int x, int y) { return heightmap_changeheight(map, x, y, 1, 1); } int heightmap_lower(heightmap_t *map, int x, int y) { return heightmap_changeheight(map, x, y, -1, 1); } int heightmap_setheight(heightmap_t *map, int x, int y, int isinit, int height) { return heightmap_changeheight(map, x, y, height - MAPPOS(map,x,y), !isinit); } int heightmap_islevel(heightsquare_t *square) { if (square->dir.topleft != square->dir.topright) return 0; if (square->dir.topleft != square->dir.botleft) return 0; if (square->dir.topleft != square->dir.botright) return 0; return 1; } int heightmap_islevel_spot(heightmap_t *map, int x, int y) { heightsquare_t square; int r; r = heightmap_getheight(map, x, y, 0, &square); if (r) return 0; return heightmap_islevel(&square); }