another attempt at solving the riddle
This commit is contained in:
parent
2d7b714c20
commit
1bd2e27746
|
@ -0,0 +1,203 @@
|
|||
/**
|
||||
* crystal-ng.c
|
||||
*
|
||||
* Ⓒ 2023 konomo
|
||||
* EUPL-1.2
|
||||
**/
|
||||
|
||||
#include<stdio.h> /* printf; fprintf */
|
||||
#include<stdlib.h> /* atoi; rand; srand */
|
||||
#include<time.h> /* time */
|
||||
#include<math.h> /* lround */
|
||||
|
||||
#include "crystal-ng.h"
|
||||
#include "bmp.h"
|
||||
|
||||
/* how many colours, max at 256 */
|
||||
int colors = 256;
|
||||
|
||||
/* generate_bitmap() from bmp.c */
|
||||
/* extern void line(int x0, int y0, int x1, int y1, unsigned char clr); /\* bres.c *\/ */
|
||||
|
||||
char new_sprout(int id);
|
||||
void process(int x, int y);
|
||||
int check_pixel(int x, int y);
|
||||
int paint_pixel(int x, int y, unsigned char clr);
|
||||
|
||||
unsigned char image[HEIGHT][WIDTH][BPP];
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if(colors<3) colors = 3;
|
||||
if(colors>256) colors = 256;
|
||||
|
||||
char *file_name = (char*) "output.bmp";
|
||||
srand(time(NULL));
|
||||
|
||||
for(int i=0; i<SPROUTS; ++i)
|
||||
{
|
||||
char err = new_sprout(i);
|
||||
if(err==1) fprintf(stderr, "sprouting failed for id %d\n", i);
|
||||
}
|
||||
|
||||
/* iterate through image grid. if on colored spot, check for empty spots and
|
||||
expand as far as possible by velocity */
|
||||
for(int x=0; x<WIDTH; ++x)
|
||||
{
|
||||
printf("%d\n", x);
|
||||
for(int y=0; y<HEIGHT; ++y)
|
||||
{
|
||||
process(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
generate_bitmap((unsigned char*)image, HEIGHT, WIDTH, file_name);
|
||||
printf("image generation done.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* color limiting code */
|
||||
unsigned char generate_color()
|
||||
{
|
||||
unsigned char clr = rand() % colors /* + colors */;
|
||||
|
||||
clr*=(unsigned char)lround( (256/colors) );
|
||||
|
||||
return clr;
|
||||
}
|
||||
|
||||
char new_sprout(int id)
|
||||
{
|
||||
if(id >= SPROUTS) return 1;
|
||||
|
||||
int x = rand() % WIDTH + 1;
|
||||
int y = rand() % HEIGHT + 1;
|
||||
unsigned char clr = generate_color();
|
||||
|
||||
printf("sprout %d at (%d|%d)\n", id, x, y);
|
||||
paint_pixel(x, y, clr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int order_check(int var, int c, int order)
|
||||
{
|
||||
if(order==-1)
|
||||
return check_pixel(c, var);
|
||||
return check_pixel(var, c);
|
||||
}
|
||||
|
||||
/* this function will first check the variables plus the total calculated
|
||||
velocity (velocity in this function simply means a value that is added to (var).
|
||||
if this does not work, (v) is reduced until it is 0, attempting to find the
|
||||
closest uncoloured/empty pixel. once it is found (or is 0), a line is drawn.
|
||||
this is how a crystal grows.
|
||||
var is a variable value, c is constant value, v is velocity, order is the
|
||||
order in which these values are to be checked ( [order_check] ). clr is
|
||||
the color. */
|
||||
void id_and_proceed(int var, int c, int v, int order, unsigned char clr)
|
||||
{
|
||||
if(var + v < 0)
|
||||
return;
|
||||
/* guard */
|
||||
/* if(order==-1) /\* y-axis *\/ */
|
||||
/* { */
|
||||
/* if(var + v < 0) */
|
||||
/* return; */
|
||||
/* } */
|
||||
/* else /\* x-axis *\/ */
|
||||
/* { */
|
||||
/* } */
|
||||
|
||||
int r = 2;
|
||||
r = order_check(var+v, c, order);
|
||||
/* if(order==-1) */
|
||||
/* r = check_pixel(c, var); */
|
||||
/* else */
|
||||
/* r = check_pixel(var, c); */
|
||||
|
||||
/* if(r==2) return; */
|
||||
|
||||
/* find most far away empty pixel */
|
||||
while(r!=0 && v > 0)
|
||||
{
|
||||
--v;
|
||||
v-=1;
|
||||
if(v<0) v=0; /* just in case */
|
||||
r=order_check(var+v, c, order);
|
||||
/* r=check_pixel(x, y); */
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if(order==-1)
|
||||
paint_pixel(c, var+v, clr);
|
||||
else
|
||||
paint_pixel(var+v, c, clr);
|
||||
--v;
|
||||
}
|
||||
while(v>=0);
|
||||
}
|
||||
|
||||
void process(int x, int y)
|
||||
{
|
||||
unsigned char clr = 0;
|
||||
|
||||
switch(check_pixel(x, y))
|
||||
{
|
||||
case 0: /* empty/black/background pixel */
|
||||
case 2: /* invalid coordinates */
|
||||
return;
|
||||
case 1: /* colored pixel */
|
||||
clr = image[y][x][0];
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "process(): this case should never be met.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
id_and_proceed(y, x, velocity[0] * (-1), -1, clr); /* north */
|
||||
id_and_proceed(x, y, velocity[1], 1, clr); /* east */
|
||||
id_and_proceed(y, x, velocity[2], -1, clr); /* south */
|
||||
id_and_proceed(x, y, velocity[3] * (-1), 1, clr); /* west */
|
||||
|
||||
/* int y_north = y - velocity[0]; */
|
||||
/* int x_east = x + velocity[1]; */
|
||||
/* int y_south = y + velocity[2]; */
|
||||
/* int x_west = x - velocity[3]; */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* returns 0 if the given pixel is black (0)
|
||||
returns 1 if it is coloured
|
||||
returns 2 if the coordinates are invalid */
|
||||
int check_pixel(int x, int y)
|
||||
{
|
||||
/* printf("Checking (%u|%u)\n", x, y); */
|
||||
if(x>=WIDTH || y>=HEIGHT)
|
||||
{
|
||||
fprintf(stderr, "coords (%d|%d) exceed image size %d×%d.\n", x, y, WIDTH, HEIGHT);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* as the image will be grayscaled, it works to check only one layer */
|
||||
/* this implies the background colour is 0 */
|
||||
if(image[y][x][0]!=0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int paint_pixel(int x, int y, unsigned char clr)
|
||||
{
|
||||
/* printf("paint_pixel called\n"); */
|
||||
if(check_pixel(x, y)) return 1;
|
||||
|
||||
image[y][x][0]=clr;
|
||||
image[y][x][1]=clr;
|
||||
image[y][x][2]=clr;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* crystal .h
|
||||
* Ⓒ 2023 konomo
|
||||
* EUPL-1.2
|
||||
**/
|
||||
|
||||
#ifndef __CRYSTAL_NG_H__
|
||||
#define __CRYSTAL_NG_H__
|
||||
|
||||
/* for 4k */
|
||||
/* #define WIDTH 3840 */
|
||||
/* #define HEIGHT 2160 */
|
||||
|
||||
/* for fullhd */
|
||||
/* #define WIDTH 1920 */
|
||||
/* #define HEIGHT 1080 */
|
||||
|
||||
/* for 360p*/
|
||||
#define WIDTH 480
|
||||
#define HEIGHT 360
|
||||
|
||||
/* #define SPROUTS 50000 */
|
||||
/* #define SPROUTS 5000 */
|
||||
#define SPROUTS 500
|
||||
/* #define SPROUTS 50 */
|
||||
/* #define SPROUTS 20 */
|
||||
/* #define SPROUTS 1 */
|
||||
|
||||
/* length of simulation */
|
||||
/* #define SIMLENGTH 10000 */
|
||||
/* #define SIMLENGTH 500 */
|
||||
/* #define SIMLENGTH 1 */
|
||||
/* #define SIMLENGTH 5 */
|
||||
/* #define SIMLENGTH 20 */
|
||||
|
||||
/* default velocity */
|
||||
const int velocity[] = {1, 1, 1, 1};
|
||||
/* const int velocity[] = {20, 20, 20, 20}; */
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue