#include <stdio.h>
#include <stdlib.h>
//
// probably should have used something like:
//
// https://bitesofcode.wordpress.com/2016/12/23/landscape-generation-using-midpoint-displacement/
//
// but tried my own hack first to see what it would look like. At least mine only uses context of
// immediate neighbour, so very suitable for left & right scrolling on Vectrex (for a Lunar Lander
// game, or a Defender clone or maybe Scramble...)
//
// Note: surface wraps so can be infinite.
//
// Needs a good random with an easily-set seed.
//
#define WRAP 1023
#define BASE 2 /* minimum height */
int surface(int i) {
int flat=0, prev_flat=0, height=0, block=0, prev_major=0, major=0, next_major=0, minor;
int global_seed = 1234;
// everything is in 8-unit blocks
block = ((i-8)&WRAP) & ~7;
srandom((block<<3+global_seed)^block);
prev_major = (random()&15) * 4;
prev_flat = random()&15; // 1 in 15 is a flat zone, where we override the point to the right, and set it the
// same height as this point, providing a flat area to land on, or house fuel depots, etc.
block = ((i+8)&WRAP) & ~7;
srandom((block<<3+global_seed)^block);
next_major = (random()&15) * 4;
block = i & ~7;
srandom((block<<3+global_seed)^block);
major = (random()&15) * 4;
flat = random()&15; // 1 in 15 is a flat zone
// every flat segment is a landing zone - probability = 1 in 16
if (prev_flat == 0) {
minor = 0;
major = prev_major;
} else if (flat == 0) {
minor = 0;
next_major = major;
} else {
srandom(((i<<3)+global_seed)^i);
minor = (random()&3);
}
height = major + ((next_major - major) * (i&7) / 8); // on the vectrex could skip minor, and draw one line between 8 points.
return height+minor;
}
void stars(int i) {
while (i --> 0) fputc('*', stdout);
fputc('\n', stdout);
}
int main(int argc, char **argv) {
int y, x;
for (x = 0; x <= WRAP; x++) {
y = surface(x);
//fprintf(stdout, "y %d\n", y);
stars(BASE+y);
}
}