home *** CD-ROM | disk | FTP | other *** search
- #include "types.h"
- #include "fixed.h"
- #include "utils.h"
- #include "screen.h"
- #include "palobj.h"
- #include <stdlib>
- #include <conio.h>
- #include <stddef.h>
- #include <fcntl.h>
- #include <fstream.h>
- #include <io.h>
- #include <stdio.h>
-
- #define VOX_WIDTH 256
- #define VOX_HEIGHT 256
- #define VOX_LEVEL 8
-
- #define MAX_SAFETY (1000000)
-
- #define COLOR_INCR 16
- #define GREEN_COL_OFFSET (0*COLOR_INCR)
- #define BROWN_COL_OFFSET (0*COLOR_INCR)
- #define WHITE_COL_OFFSET (0*COLOR_INCR)
- #define BLUE_COL_OFFSET (12*COLOR_INCR)
-
- #define MID_LIGHT 16
- #define MAX_LIGHT 31
- long LIGHT_SCALER;
- #define LIGHT_INCR 1
-
- #define MAX_RIVERS 20
-
- #define WATER_LINE 72
- #define TREE_LINE 160
- #define SNOW_LINE 208
-
- MYFIXED BASE_NOISE;
- MYFIXED NOISE_SCALE;
- #define MAX_HEIGHT (convtoMYFIXED(256))
- #define MAX_REAL_HEIGHT 255
-
- #define MAX_RAND 32767
-
- #define MAX_DIRS 4
- #define DIR_RIGHT 0
- #define DIR_UP 1
- #define DIR_LEFT 2
- #define DIR_DOWN 3
-
- #define X_COL TRUE
- #define Y_COL FALSE
-
- #define ALT_PAL_F_NAME "whites.pal"
- #define COL_PAL_F_NAME "standard.pal"
-
- #define real_alts image[0]
- #define colors image[1]
- #define alt_palette palette[0]
- #define col_palette palette[1]
-
- long smooth_scaler;
-
- typedef MYFIXED T_ALT;
- typedef MYFIXED * PT_ALT;
-
- void Make_Vox_Line(
- T_ALT base_top,
- T_ALT base_bottom,
- T_ALT noise,
- short lev_count,
- PT_ALT elev_buff);
-
- inline long random(long range)
- {
- return (fixedmd((LONG)rand(), range, MAX_RAND));
- }
-
- class Vox_Gobject : public palobj {
- protected:
- short dimensions;
- PT_ALT * altitudes;
- long Loc(short x, short y)
- {
- return ((y&(height-1))*width+(x&(width-1)));
- };
- void Make_Vox_Middle(
- T_ALT noise,
- short lev_count);
- void Convert_Altitudes();
- void Generate_Color_Map();
- void Smooth_Map();
- void Clear_Alts() {
- for (short cur_row=0; cur_row<width; cur_row++)
- delete altitudes[cur_row];
- delete altitudes;
- };
- BOOL Progress_River(short cur_x, short cur_y, short dir_start);
- void Make_Water(short cur_x, short cur_y);
- void Make_Rivers();
- short Next_Direction(short cur_direction);
- public:
- Vox_Gobject() : palobj(2)
- {
- };
- void Reset() {
- Clear_Alts();
- delete real_alts;
- delete colors;
- delete alt_palette;
- delete col_palette;
- };
- void Make_Vox_Map(short level_count, BOOL external_option);
- ~Vox_Gobject()
- {
- Clear_Alts();
- palobj::~palobj();
- };
- };
-
- void main(LONG argc, PCHAR argv[])
- {
- if (argc<2)
- return;
-
- cout << "Enter Base Noise (ex. 512)\n";
- cin >> BASE_NOISE;
- BASE_NOISE=convtoMYFIXED(BASE_NOISE);
- cout << "Enter Noise Scaler (ex. 8192)\n";
- cin >> NOISE_SCALE;
- cout << "Enter Shadow Scaler (ex. 4096)\n";
- cin >> LIGHT_SCALER;
- cout << "Enter Smoothing effect (ex. 2)\n";
- cin >> smooth_scaler;
- char ch;
- srand(strtoint(argv[1]));
- Vox_Gobject bob;
- if (!strnicmp(argv[argc-1], "EXTALT", 8)) {
- bob.Make_Vox_Map(VOX_LEVEL, TRUE);
- } else bob.Make_Vox_Map(VOX_LEVEL, FALSE);
- setgmode(0x13);
- bob.drawpalette(setpalette);
- bob.show(screen,SCREEN_WIDTH,0,0);
- ch=getch();
- bob.drawpalette(setpalette,1);
- bob.show(screen,SCREEN_WIDTH,0,0,1);
- ch=getch();
- if (argc>2) {
- bob.assignoutfile(argv[2]);
- bob.Write(0);
- } /* endif */
- if (argc>3) {
- bob.assignoutfile(argv[3]);
- bob.Write(1);
- } /* endif */
- setgmode(0x3);
- }
-
- void Make_Vox_Line(
- T_ALT base_top,
- T_ALT base_bottom,
- T_ALT noise,
- short level_count,
- PT_ALT elev_buff)
- {
-
- // is line already small enough to fill w/ endpoints
- if (level_count==0) {
- elev_buff[0] = base_top;
- elev_buff[1] = base_bottom;
- return;
- } /* endif */
-
- // Nope, so get a middle altitude
- MYFIXED y_mid=(base_top+base_bottom)/2;
- y_mid+=(random(noise)-(noise/2));
-
- // Are there few enough points to fill w/ endpoints and middle?
- if (level_count==1) {
- elev_buff[0]=base_top;
- elev_buff[1]=y_mid;
- elev_buff[2]=base_bottom;
- return;
- } /* endif */
-
- // Nope, so we'll just have to divide the line into and process each half
-
- // Get new values for next level of recursion
- short point_count=(1<<level_count)+1;
- short point_middle=point_count/2;
- T_ALT new_noise=fixedmult(noise, NOISE_SCALE);
- short new_level_count=level_count-1;
-
- // Process top half
- Make_Vox_Line(
- base_top,
- y_mid,
- new_noise,
- new_level_count,
- elev_buff);
-
- // Process bottom half
- Make_Vox_Line(
- y_mid,
- base_bottom,
- new_noise,
- new_level_count,
- elev_buff+point_middle);
-
- return;
- }
-
- void Vox_Gobject::Make_Vox_Map(short lev_count, BOOL external_option)
- {
- // dimensions must be the 2^lev_count +1
- // don't ask why
-
- dimensions=(1<<lev_count)+1;
- width=dimensions-1;
- height=dimensions-1;
- image_size=width*height;
-
- //Allocate Initial Altitude Tables
-
- if ((altitudes=new PT_ALT [dimensions])==NULL) {
- return;
- } /* endif */
-
- for (short cur_column=0; cur_column<dimensions; cur_column++) {
- if ((altitudes[cur_column]=new T_ALT [dimensions])==NULL) {
- return;
- } /* endif */
- } /* endfor */
-
- if (!external_option)
- {
-
- // Init random values on four corners of map
-
- T_ALT tl_corner, tr_corner, bl_corner, br_corner;
-
- tl_corner=(MAX_HEIGHT/2) /* + (random(BASE_NOISE) - (BASE_NOISE/2)) */ ;
- tr_corner=(MAX_HEIGHT/2) /* + (random(BASE_NOISE) - (BASE_NOISE/2)) */ ;
- bl_corner=(MAX_HEIGHT/2) /* + (random(BASE_NOISE) - (BASE_NOISE/2)) */ ;
- br_corner=(MAX_HEIGHT/2) /* + (random(BASE_NOISE) - (BASE_NOISE/2)) */ ;
-
- // Generate edges
-
- // top
- Make_Vox_Line(
- tl_corner,
- bl_corner,
- fixedmult(BASE_NOISE,NOISE_SCALE),
- lev_count,
- &(altitudes[0][0])
- );
-
- // right
- /*
- Make_Vox_Line(
- tr_corner,
- br_corner,
- fixedmult(BASE_NOISE,NOISE_SCALE),
- lev_count,
- &(altitudes[dimensions-1][0])
- );
- */
- memcpy(&(altitudes[dimensions-1][0]), &(altitudes[0][0]), sizeof(T_ALT)*dimensions);
-
- PT_ALT temp_alt_buf=new T_ALT [dimensions];
- short cur_element;
-
- // top
- Make_Vox_Line(
- tl_corner,
- tr_corner,
- fixedmult(BASE_NOISE,NOISE_SCALE),
- lev_count,
- temp_alt_buf);
-
- for (cur_element=0; cur_element<dimensions; cur_element++) {
- altitudes[cur_element][0]=temp_alt_buf[cur_element];
- } /* endfor */
-
- // bottom
- /*
- Make_Vox_Line(
- bl_corner,
- br_corner,
- fixedmult(BASE_NOISE,NOISE_SCALE),
- lev_count,
- temp_alt_buf);
- */
-
- for (cur_element=0; cur_element<dimensions; cur_element++) {
- altitudes[cur_element][dimensions-1]=temp_alt_buf[cur_element];
- } /* endfor */
-
- delete temp_alt_buf;
-
- // Now Generate 2D map
-
- Make_Vox_Middle(
- fixedmult(BASE_NOISE,NOISE_SCALE),
- lev_count);
-
- } else {
- FILE * fp;
- fp=fopen("terr.dat", "r+b");
- for (short cur_x=0; cur_x<width; cur_x++) {
- fread(altitudes[cur_x], height, sizeof(T_ALT), fp);
- } /* endfor */
- }
-
- // convert to bitmapable level altitudes
-
- Convert_Altitudes();
-
- // get rid of jaggedy look!
-
- if (!external_option)
- Smooth_Map();
-
- // Generate colors based on altitudes
-
- Generate_Color_Map();
-
- // Draw some rivers, for viewing enjoyment
-
- //Make_Rivers();
- }
-
- void Vox_Gobject::Smooth_Map() {
- PUCHAR temp_altitudes;
- temp_altitudes=new UCHAR [width * height];
- for (short cur_x=0; cur_x<width; cur_x++) {
- for (short cur_y=0; cur_y<height; cur_y++) {
- long sum=0;
- for (short u=-smooth_scaler; u<=smooth_scaler; u++) {
- for (short v=-smooth_scaler; v<=smooth_scaler; v++) {
- sum+=real_alts[Loc((cur_x+u+width)&(width-1),(cur_y+v+height)&(height-1))];
- }
- }
- temp_altitudes[Loc(cur_x, cur_y)]=(UCHAR)(sum/ ((2*smooth_scaler+1) *(2*smooth_scaler+1)));
- } /* endfor */
- } /* endfor */
-
- for (cur_x=0; cur_x<width; cur_x++) {
- for (short cur_y=0; cur_y<height; cur_y++) {
- real_alts[Loc(cur_x, cur_y)]=temp_altitudes[Loc(cur_x, cur_y)];
- altitudes[cur_x][cur_y]=convtoMYFIXED(temp_altitudes[Loc(cur_x, cur_y)]);
- }
- }
- delete temp_altitudes;
- }
-
- void Vox_Gobject::Make_Vox_Middle(
- T_ALT noise,
- short lev_count)
- {
- short base_stepper, half_stepper;
- T_ALT cur_noise;
- short cur_x, cur_y;
- short cur_level;
- short point_count;
-
- cur_noise=noise;
- point_count=dimensions-1;
- half_stepper=point_count;
-
- // Generate middle points for each level
- for (cur_level=0; cur_level<lev_count; cur_level++) {
- base_stepper=half_stepper;
- half_stepper/=2;
-
- // Get mid points between levels corners
- for (cur_x=half_stepper; cur_x < point_count; cur_x += base_stepper) {
- for (cur_y=half_stepper; cur_y < point_count; cur_y += base_stepper) {
- altitudes[cur_x][cur_y] = (altitudes[cur_x - half_stepper][cur_y - half_stepper] +
- altitudes[cur_x - half_stepper][cur_y + half_stepper] +
- altitudes[cur_x + half_stepper][cur_y - half_stepper] +
- altitudes[cur_x + half_stepper][cur_y + half_stepper]) / 4;
- altitudes[cur_x][cur_y] += (random(cur_noise) - (cur_noise/2));
- } /* endfor */
- } /* endfor */
-
- // Get mid points on edges between corners
- if (cur_level > 0) {
-
- // do mid points on x edges then the ones on y edges
-
- for (cur_x = half_stepper; cur_x < point_count; cur_x += base_stepper) {
- for (cur_y = base_stepper; cur_y < point_count; cur_y += base_stepper) {
- altitudes[cur_x][cur_y] = (altitudes[cur_x][cur_y - half_stepper] +
- altitudes[cur_x][cur_y + half_stepper] +
- altitudes[cur_x - half_stepper][cur_y] +
- altitudes[cur_x + half_stepper][cur_y]) / 4;
- altitudes[cur_x][cur_y] += (random(cur_noise) - (cur_noise/2));
- } /* endfor */
- } /* endfor */
-
- for (cur_x = base_stepper; cur_x < point_count; cur_x += base_stepper) {
- for (cur_y = half_stepper; cur_y < point_count; cur_y += base_stepper) {
- altitudes[cur_x][cur_y] = (altitudes[cur_x][cur_y - half_stepper] +
- altitudes[cur_x][cur_y + half_stepper] +
- altitudes[cur_x - half_stepper][cur_y] +
- altitudes[cur_x + half_stepper][cur_y]) / 4;
- altitudes[cur_x][cur_y] += (random(cur_noise) - (cur_noise/2));
- } /* endfor */
- } /* endfor */
-
- } /* endif */
-
- // Now change noise for next round through
- cur_noise=fixedmult(cur_noise, NOISE_SCALE);
- } /* endfor */
-
- }
-
- void Vox_Gobject::Convert_Altitudes()
- {
- if ((real_alts= new UCHAR [image_size])==NULL) {
- return;
- } /* endif */
-
- // load up palette
- if ((alt_palette= new UCHAR [PALETTE_SIZE])==NULL) {
- return;
- } /* endif */
- fstream fp(ALT_PAL_F_NAME, ios::in | ios::out | ios::binary);
- fp.read(alt_palette, PALETTE_SIZE);
- fp.close();
-
- for (short cur_x=0; cur_x<width; cur_x++)
- for (short cur_y=0; cur_y<height; cur_y++) {
- if (altitudes[cur_x][cur_y]<0)
- real_alts[Loc(cur_x, cur_y)]=0;
- else if (altitudes[cur_x][cur_y]>=MAX_HEIGHT)
- real_alts[Loc(cur_x, cur_y)]=MAX_REAL_HEIGHT;
- else real_alts[Loc(cur_x, cur_y)]=(UCHAR)(convtoLONG(altitudes[cur_x][cur_y]));
- }
-
- }
-
- void Vox_Gobject::Generate_Color_Map()
- {
- if ((colors= new UCHAR [image_size])==NULL) {
- return;
- } /* endif */
-
- // load up palette
- if ((col_palette= new UCHAR [PALETTE_SIZE])==NULL) {
- return;
- } /* endif */
- fstream fp(COL_PAL_F_NAME, ios::in | ios::out | ios::binary);
- fp.read(col_palette, PALETTE_SIZE);
- fp.close();
-
- T_ALT alt_difference;
- SHORT light;
- UCHAR cur_alt;
- for (short cur_x=0; cur_x<width; cur_x++) {
- for (short cur_y=0; cur_y<height; cur_y++) {
-
- // find shadow on light
- alt_difference=0;
- alt_difference+=(altitudes[(cur_x+1) % width][cur_y]-altitudes[cur_x][cur_y]);
- alt_difference+=(altitudes[cur_x][cur_y]-altitudes[(cur_x-1+width)%width][cur_y]);
-
- light=(alt_difference / LIGHT_SCALER)+MID_LIGHT;
- if (light<0)
- light=0;
- if (light>MAX_LIGHT)
- light=MAX_LIGHT;
-
- light*=LIGHT_INCR;
-
- cur_alt=real_alts[Loc(cur_x, cur_y)];
-
- // Decide upon terrain color
- if (cur_alt < WATER_LINE) {
- colors[Loc(cur_x, cur_y)]=light+GREEN_COL_OFFSET;
- } else if (cur_alt < TREE_LINE)
- colors[Loc(cur_x, cur_y)]=light+GREEN_COL_OFFSET;
- else if (cur_alt < SNOW_LINE)
- colors[Loc(cur_x, cur_y)]=light+BROWN_COL_OFFSET;
- else colors[Loc(cur_x, cur_y)]=light+WHITE_COL_OFFSET;
- } /* endfor */
- } /* endfor */
- }
-
- BOOL marked_spots[VOX_WIDTH * VOX_HEIGHT];
-
- void Vox_Gobject::Make_Rivers() {
- short num_rivers;
- short w,h,cur_river;
- for (w=0; w<width; w++) {
- for (h=0; h<height; h++) {
- marked_spots[Loc(w,h)]=FALSE;
- } /* endfor */
- } /* endfor */
- num_rivers=random(MAX_RIVERS);
- for (cur_river=0; cur_river<num_rivers; cur_river++) {
- Progress_River(random(VOX_WIDTH), random(VOX_HEIGHT), random(MAX_DIRS));
- }
- }
-
- void Vox_Gobject::Make_Water(short cur_x, short cur_y) {
- colors[Loc(cur_x, cur_y)]=(UCHAR)((short)(colors[Loc(cur_x, cur_y)]-GREEN_COL_OFFSET)/2
- +BLUE_COL_OFFSET);
- }
-
- short Vox_Gobject::Next_Direction(short cur_direction) {
- return ((cur_direction+1)%MAX_DIRS);
- }
-
- BOOL Vox_Gobject::Progress_River(short cur_x, short cur_y, short start_dir) {
- short this_alt;
- short direction, dir_count;
- BOOL found;
-
- direction=Next_Direction(start_dir);
- if (!marked_spots[Loc(cur_x, cur_y)]) {
- marked_spots[Loc(cur_x, cur_y)]=TRUE;
- Make_Water(cur_x, cur_y);
- this_alt=real_alts[Loc(cur_x, cur_y)]+2;
- dir_count=0;
- found=FALSE;
- while ((!found)&&(dir_count<MAX_DIRS)) {
- switch (direction) {
- case DIR_RIGHT:
- if (this_alt>=real_alts[Loc(cur_x+1, cur_y)]) {
- found=Progress_River(cur_x+1, cur_y, direction);
- }
- break;
- case DIR_UP:
- if (this_alt>=real_alts[Loc(cur_x, cur_y+1)]) {
- found=Progress_River(cur_x, cur_y+1, direction);
- }
- break;
- case DIR_LEFT:
- if (this_alt>=real_alts[Loc(cur_x-1, cur_y)]) {
- found=Progress_River(cur_x-1, cur_y, direction);
- }
- break;
- case DIR_DOWN:
- if (this_alt>=real_alts[Loc(cur_x, cur_y-1)]) {
- found=Progress_River(cur_x, cur_y-1, direction);
- } /* endif */
- break;
- default:
- break;
- } /* endswitch */
- dir_count++;
- direction=Next_Direction(direction);
- } /* endwhile */
- return TRUE;
- } else {
- return FALSE;
- } /* endif */
- }
-
-
-
-