/* -*- Objc -*- */ /* * $Id: MapRandom.m,v 1.1 2003/07/24 13:50:53 gabby Exp $ * * Copyright (C) 2003 Free Software Foundation, Inc. * * This file is part of GNU Hégémonie. * * 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 #include "MapRandom.h" @implementation MapRandom + (int) _hazardWithFar: (int)far withHeigth: (int)height andMaxHeight: (int)maxHeight { NSParameterAssert (height <= 255); NSParameterAssert (height <= maxHeight); NSParameterAssert (height >= 0); int valMax; if (far + height > maxHeight) valMax = maxHeight; else valMax = far + height; int valMin; if (height - far < 0) valMin = 0; else valMin = height - far; int val = valMax - valMin; int r = (int) ((double)val * rand() / (RAND_MAX + 1.0)); return valMin + r; } + (int) _heightBetween: (map_coord_t)pos1 and: (map_coord_t)pos2 withFar: (int)far andMaxHeight: (int)maxHeight withHF: (MapTerrain *)heightField { int height = ([heightField heightAtPosition: pos1] + [heightField heightAtPosition: pos2]) / 2.0; return [self _hazardWithFar: far withHeigth: height andMaxHeight: maxHeight]; } + (void) _generateFractaleGroundWithUpLeft: (map_coord_t)pos1 andDownRight: (map_coord_t)pos2 andMaxHeight: (int)maxHeight withHF: (MapTerrain *)heightField { int xMid = (pos1.x + pos2.x) / 2; int zMid = (pos1.z + pos2.z) / 2; if((xMid != pos1.x) || (zMid != pos1.z)) { map_coord_t pos; int upMid, downMid, leftMid, rightMid; // calculate up middle pos = MakeMapCoord (xMid, pos1.z); if ([heightField heightAtPosition: pos] == 0) { upMid = [self _heightBetween: pos1 and: MakeMapCoord (pos2.x, pos1.z) withFar: xMid - pos1.x andMaxHeight: maxHeight withHF: heightField]; [heightField setHeightAtPosition: pos toHeight: (u_int8_t)upMid]; } else upMid = [heightField heightAtPosition: pos]; // calculate down middle pos = MakeMapCoord (xMid, pos2.z); if ([heightField heightAtPosition: pos] == 0) { downMid = [self _heightBetween: MakeMapCoord (pos1.x, pos2.z) and: pos2 withFar: xMid - pos1.x andMaxHeight: maxHeight withHF: heightField]; [heightField setHeightAtPosition: pos toHeight: (u_int8_t)downMid]; } else downMid = [heightField heightAtPosition: pos]; // calculate left middle pos = MakeMapCoord (pos1.x, zMid); if ([heightField heightAtPosition: pos] == 0) { leftMid = [self _heightBetween: pos1 and: MakeMapCoord (pos1.x, pos2.z) withFar: zMid - pos1.z andMaxHeight: maxHeight withHF: heightField]; [heightField setHeightAtPosition: pos toHeight: (u_int8_t)leftMid]; } else leftMid = [heightField heightAtPosition: pos]; // calculate right middle pos = MakeMapCoord (pos2.x, zMid); if ([heightField heightAtPosition: pos] == 0) { rightMid = [self _heightBetween: MakeMapCoord (pos2.x, pos1.z) and: pos2 withFar: zMid - pos1.z andMaxHeight: maxHeight withHF: heightField]; [heightField setHeightAtPosition: pos toHeight: (u_int8_t)rightMid]; } else rightMid = [heightField heightAtPosition: pos]; // calculate center int height = (upMid + downMid + leftMid + rightMid) / 4; int far = (int)sqrt ((double)(SQUARE (xMid - pos1.x) + SQUARE(zMid - pos1.z))); height = [self _hazardWithFar: far withHeigth: height andMaxHeight: maxHeight]; [heightField setHeightAtPosition: MakeMapCoord (xMid, zMid) toHeight: (u_int8_t)height]; // redo for each sub-rectangle [self _generateFractaleGroundWithUpLeft: pos1 andDownRight: MakeMapCoord (xMid, zMid) andMaxHeight: maxHeight withHF: heightField]; [self _generateFractaleGroundWithUpLeft: MakeMapCoord (xMid, pos1.z) andDownRight: MakeMapCoord (pos2.x, zMid) andMaxHeight: maxHeight withHF: heightField]; [self _generateFractaleGroundWithUpLeft: MakeMapCoord (pos1.x, zMid) andDownRight: MakeMapCoord (xMid, pos2.z) andMaxHeight: maxHeight withHF: heightField]; [self _generateFractaleGroundWithUpLeft: MakeMapCoord (xMid, zMid) andDownRight: pos2 andMaxHeight: maxHeight withHF: heightField]; } } + (void) mapRandom: (MapTerrain *)heightField andMaxHeight: (int)maxHeight { NSParameterAssert (maxHeight > 1); NSParameterAssert (maxHeight <= 255); int xLength = [heightField xLength]; int zLength = [heightField zLength]; srand (time (0)); int height = (int) ((double)maxHeight * rand() / (RAND_MAX + 1.0)); [heightField setHeightAtPosition: MakeMapCoord (0, 0) toHeight: (u_int8_t)height]; [self _generateFractaleGroundWithUpLeft: MakeMapCoord (0, 0) andDownRight: MakeMapCoord (xLength, zLength) andMaxHeight: maxHeight withHF: heightField]; } + (void) mountainRandom: (MapTerrain *)heightField atCenter: (map_coord_t)center withXLength: (int)xLength andZLength: (int)zLength andMaxHeight: (int)maxHeight { NSParameterAssert (maxHeight > 1); NSParameterAssert (maxHeight <= 255); NSParameterAssert (xLength >= 10); NSParameterAssert (zLength >= 10); srand (time (0)); map_coord_t upLeft = MakeMapCoord (center.x - xLength / 2, center.z - zLength / 2); map_coord_t downRight = MakeMapCoord (center.x + xLength / 2, center.z + zLength / 2); [self _generateFractaleGroundWithUpLeft: upLeft andDownRight: downRight andMaxHeight: maxHeight withHF: heightField]; } + (void) resetHeightField: (MapTerrain *)heightField { int xLength = [heightField xLength]; int zLength = [heightField zLength]; int x; for (x = 0; x < xLength; x++) { int z; for (z = 0; z < zLength; z++) { [heightField setHeightAtPosition: MakeMapCoord (x, z) toHeight: 0]; } } } @end