/*
    bomb - automatic interactive visual stimulation
    Copyright (C) 1994  Scott Draves <spot@cs.cmu.edu>

    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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#define mac_bomb 0
#define vga_bomb 0
#define xws_bomb 0
#define ogl_bomb 0
#define win_bomb 1


#if mac_bomb || win_bomb
#  define DATA_DIR ""
typedef unsigned char u_char;
#  define M_PI 3.141592654
#else
#  include <unistd.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>

#if vga_bomb
#  include <vga.h>
#endif

#include "cmap.h"
#include "libifs.h"


#ifdef __cplusplus
extern "C" {
#endif


#define alen(x) (sizeof(x)/sizeof((x)[0]))

#if mac_bomb || win_bomb
#  define R (rand()|(rand()<<16))
#else
#  define R   (random())
#endif
#define bool int

#define R8b (random_byte())


int iclamp(int p, int n);



/* REZ is not used by some rules */

/* REZ chooses the grid size.  
   0 = 160x100
   1 = 160x200
   2 = 320x200 */
#define REZ 2

#if REZ==0
#  define XSIZE 160
#  define XMUL 2
#  define YSIZE 100
#  define YMUL 2
#elif REZ==1
#  define XSIZE 160
#  define XMUL 2
#  define YSIZE 200
#  define YMUL 1
#elif REZ==2
#  define XSIZE 320
#  define XMUL 1
#  define YSIZE 200
#  define YMUL 1
#endif

#define SMALL_XSIZE (XSIZE/2)
#define SMALL_YSIZE (YSIZE/2)
#define SMALL_XMUL  (XMUL*2)
#define SMALL_YMUL  (YMUL*2)

#define VSMALL_XSIZE (XSIZE/8)
#define VSMALL_YSIZE (YSIZE/8)
#define VSMALL_XMUL  (XMUL*8)
#define VSMALL_YMUL  (YMUL*8)


typedef int board_t[XSIZE+2][YSIZE+2];

typedef struct {
   int fill;
} fill_t;

#define MAXRHYTHM 2

typedef struct {
   int rule;
   int speed;     /* computed from speed_*    */
   int mask;
   bool randomized_underflow;
   bool cycle_bkg;
   bool remap;
   bool floor;           /* computed from frame, hot, cold */
   int driver_slowdown;
   int brain;
   int brain_shift;
   int drift;
   int drift_speed;
   int rhythm[MAXRHYTHM];
   double drift_time;
   ifs_control_point flame_cp;
   int hot;
   int cool;
   int image_window_size;
   int search_time;
   int bsize;
   int speed_base;
   int speed_beat_speed;
   int speed_beat_size;
   int seq[2];
} rule_t;

typedef struct {
   int cmap;
   int index;
   int index2;
} cmap_t;

extern board_t board[2];
extern board_t board2[2];
extern board_t board3[2];
extern int dbuf;
extern int remap[256 * 256];
extern int p1;
#define MAXFLAMES 500
extern ifs_control_point flames[MAXFLAMES];
extern int nflames;

void distrib(int dist, rule_t *rule, cmap_t *cmap, fill_t *fill);
void init_rotate();

#define LIVE_BIT 1
#define HIST_BIT 2

/* a place to write 8-bit pixels.  should have a cmap in here */
typedef struct {
   u_char *p;
   int width;
   int height;
   int stride;
} image8_t;

extern image8_t fb;

#define max_heat (0x10000)

#define N_RAM_IMAGES 10

int seq_next_image(int *seq_p);
void init_shade();
void init_wave();
void seq_start(int *seq);
void init_rotor();
void init_seq();
void pick_liss_coefs();

#define status_string_length 80
extern char status_string[status_string_length];

int random_byte();
int quantize(double d);


/* instead of argv (XXX) */
#define argd(s,d)   ((ai = getenv(s)) ? atof(ai) : (d))
#define argi(s,d)   ((ai = getenv(s)) ? atoi(ai) : (d))
#define args(s,d)   ((ai = getenv(s)) ? ai : (d))
#define arge(s,e)   ((ai = getenv(s)) && (!strcmp(e,ai)))
static char *ai;

extern int high_growth_game(rule_t *p);

#ifdef __cplusplus
}
#endif
