/*
Some plasma sources ripped from Elias Pschernig, thanks dude :o)
*/

#include <allegro.h>

#define MAP_HEIGHT  512
#define MAP_WIDTH   (MAP_HEIGHT*2)
#define MAX_ZTILES  5
#define TILE_WIDTH  (TILE_HEIGHT*2)
#define TILE_HEIGHT 16
#define MAX_X       (MAP_WIDTH*TILE_WIDTH-1)
#define MAX_Y       (MAP_HEIGHT*TILE_HEIGHT-1)
#define MAX_Z       (TILE_HEIGHT*MAX_ZTILES)
#define PLASMA_ROUGHNESS 30


#define mappos(map_,x_,y_) *((int *)map_->line[(y_)&(MAP_HEIGHT-1)]+((x_)&(MAP_WIDTH-1)))

void plasma__create(BITMAP *bmp,int rough);

BITMAP *load_map(int mn) {
 BITMAP *m;
 int x,y,light;
 int c,h;
 m=create_bitmap_ex(32,MAP_WIDTH,MAP_HEIGHT);
 clear_to_color(m,0);

// create a plasma height map
 plasma__create(m,MAX_Z);

// do the lightning
 for(y=0;y<MAP_HEIGHT;y++) {
  for(x=0;x<MAP_WIDTH;x++) {
   light=
     (mappos(m,x+1,y+1)&255)
    +(mappos(m,x,y+1)&255)
    +(mappos(m,x-1,y)&255)
    -(mappos(m,x-1,y-1)&255)
    -(mappos(m,x,y-1)&255)
    -(mappos(m,x+1,y)&255);
   if(light>TILE_HEIGHT) light=TILE_HEIGHT;
   if(light<-TILE_HEIGHT) light=-TILE_HEIGHT;
   light=(light*127)/TILE_HEIGHT;
   light+=127;

   h=mappos(m,x,y);
   h&=255;
   if(h<TILE_HEIGHT) c=makecol24(light/2,light/2,128+light/2)<<8;
   else if(h<TILE_HEIGHT*3) c=makecol24(64+light/2,128+light/2,64)<<8;
   else if(h<TILE_HEIGHT*4) c=makecol24(64+(light*2)/3,light/2,0)<<8;
   else c=makecol24(64+(light*2)/3,64+(light*2)/3,64+(light*2)/3)<<8;

   mappos(m,x,y)+=c;
  }
 }

 return(m);
}

// all the following is the plasma generator

BITMAP *plasma__bitmap;
int plasma__rough=PLASMA_ROUGHNESS;
int plasma__max=254;

int plasma__midcol(int c0,int c1,int s)
{
 int r;
 int heightlevel;
 r=(rand()%(2*s+1))-s;
 r*=100;
 heightlevel=(c0+c1)/2;

 r/=plasma__rough;
 r+=heightlevel;
 if(r<0) r=0;
 if(r>plasma__max) r=plasma__max;
 return(r);
}

void plasma__newpos(int x,int y,int c)
{
 int o;
 o=mappos(plasma__bitmap,x,y);
 if(o==255||c==255) {
  mappos(plasma__bitmap,x,y)=c;
 }
}

int plasma__getpos(int x,int y)
{
 int o;
 o=mappos(plasma__bitmap,x,y);
 return(o);
}

void plasma__run(int x1,int y1,int x2,int y2)
{
 int c[6];
 int cm;
 int mx,my;

 mx=(x2-x1);
 my=(y2-y1);

 if((mx>1)||(my>1)) {

  mx/=2;
  my/=2;

  c[0]=plasma__getpos(x1,y1);
  c[1]=plasma__getpos(x2,y1);
  c[2]=plasma__getpos(x2,y2);
  c[3]=plasma__getpos(x1,y2);

  cm=plasma__midcol(c[0],c[1],mx);
  plasma__newpos(x1+mx,y1,cm);

  cm=plasma__midcol(c[2],c[3],mx);
  plasma__newpos(x1+mx,y2,cm);

  cm=plasma__midcol(c[0],c[3],my);
  plasma__newpos(x1,y1+my,cm);

  cm=plasma__midcol(c[1],c[2],my);
  plasma__newpos(x2,y1+my,cm);

  if(mx==my) {
   cm=plasma__midcol(c[0],c[2],my);
   plasma__newpos(x1+mx,y1+my,cm);

   plasma__run(x1   ,y1,x1+mx,y1+my);
   plasma__run(x1+mx,y1,x2   ,y1+my);
   plasma__run(x1   ,y1+my,x1+mx,y2);
   plasma__run(x1+mx,y1+my,x2   ,y2);
  } else if(mx>my) {
   plasma__run(x1   ,y1,x1+mx,y2);
   plasma__run(x1+mx,y1,x2   ,y2);
  } else {
   plasma__run(x1   ,y1,x2,y1+my);
   plasma__run(x1,y1+my,x2   ,y2);
  }
 }
}

void plasma__create(BITMAP *bmp,int max)
{
 int x,y;

 plasma__bitmap=bmp;
 plasma__max=max;

 for(y=0;y<bmp->h;y++)
  for(x=0;x<bmp->w;x++)
   plasma__newpos(x,y,255);

 plasma__newpos(0,0,0);

 plasma__run(0,0,bmp->w,bmp->h);
}


void draw_map(BITMAP *buffer, BITMAP *map) {
  int i, j;
  for (i=0; i<buffer->w; i++)
  for (j=0; j<buffer->h; j++) {
    int p = mappos(map,i,j);
    int r = getr32(p);
    int g = getg32(p);
    int b = getb32(p);
    int v = (r + g + b) / 5;
    putpixel(buffer, i, j, makecol(v,v,v));
  }
}


/* END */
