/*
    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.
*/

#include "defs.h"

/* should simplify use of lp? */

void step_rule_acidlife1(int frame, rule_t *p, image8_t *fb)
{
   int x, y, bx, by;
   board_t *s_heat_board, *d_heat_board;
   board_t *s_game_board, *d_game_board;
   u_char *lp0, *lp1;

   s_heat_board=&board[dbuf];
   d_heat_board=&board[1-dbuf];
   s_game_board=&board2[dbuf];
   d_game_board=&board2[1-dbuf];
   dbuf = 1-dbuf;

   for (y=0;y<=SMALL_YSIZE;y++) {
      (*d_game_board)[0][y] = R;
      x = R;
      x = (x & 1) && (x & 2);
      (*d_game_board)[SMALL_XSIZE+1][y] = x;
   }
   for (x=0;x<=SMALL_XSIZE;x++) {
      (*d_game_board)[x][0] = R;
      (*d_game_board)[x][SMALL_YSIZE+1] = R;
   }

   for (y=1;y<=SMALL_YSIZE;y++) {
      lp0 = fb->p + (fb->stride * 2 * (y - 1));
      lp1 = lp0 + XSIZE - 1;
      for (x=1;x<=SMALL_XSIZE;x++) {
	 int heat, t;
	 heat = ((((*s_heat_board)[x  ][y-1])+
		  ((*s_heat_board)[x-1][y  ])+
		  ((*s_heat_board)[x  ][y  ])+
		  ((*s_heat_board)[x+1][y  ])+
		  ((*s_heat_board)[x  ][y+1])
		  + p->speed)
		 / 5) & p->mask;
	 t = (((*s_game_board)[x+1][y+1]&LIVE_BIT)+
	      ((*s_game_board)[x+1][y-1]&LIVE_BIT)+
	      ((*s_game_board)[x-1][y+1]&LIVE_BIT)+
	      ((*s_game_board)[x-1][y-1]&LIVE_BIT)+
	      ((*s_game_board)[x  ][y-1]&LIVE_BIT)+
	      ((*s_game_board)[x-1][y  ]&LIVE_BIT)+
	      ((*s_game_board)[x+1][y  ]&LIVE_BIT)+
	      ((*s_game_board)[x  ][y+1]&LIVE_BIT));
	 if ((*s_game_board)[x][y]&LIVE_BIT /* || (heat > 200) */) {
	    t = (t == 2 || t == 3);
	 } else {
	    t = (t == 3);
	 }
	 if (t) heat = p->mask;
	 t = ((*s_game_board)[x][y] << 1) | t;
	 (*d_game_board)[x][y]= t;
	 (*d_heat_board)[x][y]= heat;
	 t = (heat > 100) ? (t|128) : (heat&127);
#if 0
	 t = heat;
#endif
	 /* use stride+-1 for effect, nix idea */
	 lp0[fb->stride] = t;
	 *lp0++ = t;
	 lp1[fb->stride] = t;
	 *lp1-- = t;
      }
   }
}

#define feedback 0
#define flevel 20

void step_rule_acidlife2(int frame, rule_t *p, image8_t *fb)
{
   int x, y, bx, by;
   board_t *s_heat_board, *d_heat_board;
   board_t *s_game_board, *d_game_board;
   u_char *lp0, *lp1, *lp2, *lp3;
   int q0, q1;

   s_heat_board=&board[dbuf];
   d_heat_board=&board[1-dbuf];
   s_game_board=&board2[dbuf];
   d_game_board=&board2[1-dbuf];
   dbuf = 1-dbuf;

#if !feedback
   for (y=0;y<=SMALL_YSIZE;y++) {
      int t;
      (*d_game_board)[0][y] = R;
      t = R;
      /* t = (t & 1) && (t & 2); */
      (*d_game_board)[SMALL_XSIZE+1][y] = t;
   }
   for (x=0;x<=SMALL_XSIZE;x++) {
      int t;
      (*d_game_board)[x][0] = R;
      t = R;
      /* t = (t & 1) && (t & 2); */
      (*d_game_board)[x][SMALL_YSIZE+1] = t;
   }
#endif

   for(y=1;y<=SMALL_YSIZE;y++) {
      lp0 = fb->p + (fb->stride * (y - 1));
      lp1 = fb->p + (fb->stride * (YSIZE - y - 1));
      lp2 = fb->p + (fb->stride * (y - 1)) + XSIZE - 1;
      lp3 = fb->p + (fb->stride * (YSIZE - y - 1)) + XSIZE - 1;
      for(x=1;x<=SMALL_XSIZE;x++) {
	 int heat, t;
	 heat = ((((*s_heat_board)[x  ][y-1])+
		  ((*s_heat_board)[x-1][y  ])+
		  ((*s_heat_board)[x  ][y  ])+
		  ((*s_heat_board)[x+1][y  ])+
		  ((*s_heat_board)[x  ][y+1])
		  + p->speed)/5)&p->mask;
	 t = (((*s_game_board)[x+1][y+1]&LIVE_BIT)+
	      ((*s_game_board)[x+1][y-1]&LIVE_BIT)+
	      ((*s_game_board)[x-1][y+1]&LIVE_BIT)+
	      ((*s_game_board)[x-1][y-1]&LIVE_BIT)+
	      ((*s_game_board)[x  ][y-1]&LIVE_BIT)+
	      ((*s_game_board)[x-1][y  ]&LIVE_BIT)+
	      ((*s_game_board)[x+1][y  ]&LIVE_BIT)+
	      ((*s_game_board)[x  ][y+1]&LIVE_BIT));
	 q1 = (*s_game_board)[x][y]&LIVE_BIT;
	 if (q1
#if feedback
	     || (heat < flevel)
#endif
	     ) {
	    t = (t == 2 || t == 3);
	 } else {
	    t = (t == 3);
	 }
#if feedback
	 if (q1^t) heat += 10;
#else
	 if (t) heat = 100;
#endif
	 q0 = t;
	 t = ((*s_game_board)[x][y] << 1) | t;
	 (*d_game_board)[x][y]= t;
	 (*d_heat_board)[x][y]= heat;
#if 0
	 if (p1%3==1)
	    heat = q0 ? 0 : 100;
	 else if (p1%3==2)
	    heat = (heat < flevel) ? 0 : 100;
#endif
	 *lp0++ = heat;
	 *lp1++ = heat;
	 *lp2-- = heat;
	 *lp3-- = heat;
      }
   }
}

