/*
 *  Copyright (c) 1995  Andreas Schmitz
 *  All rights reserved.
 *
 *  This is a blanker-module for Garshne-Blanker 3.6
 */

#include <exec/memory.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <float.h>
#include <stdlib.h>
#include "/includes.h"

#define SQSIZE    0
#define BLACKWIN  2
#define RESTART   4
#define TOPSCR    8

#define farb(i) ((i)*(0x01000000)) /* for setting RGB32-Colors */

#include "Rival_rev.h"
STATIC const UBYTE VersTag[] = VERSTAG;

/* Routines */

/* alle Pixel im Rechteck in der gleichen Farbe ? */
char Recheckt(struct RastPort *rp,int xmin,int ymin,int xmax,int ymax,int farbe)
{
   int breit,hoch;
   int xmitt,ymitt;
   int i,start,x,y;
   int r[4][4];
   char back=1;

   breit=xmax-xmin;
   hoch=ymax-ymin;

   if ((breit<40)||(hoch<30)) {
      for (y=ymin;y<=ymax;y++) {
         for (x=xmin;x<=xmax;x++) {
            if (ReadPixel(rp,x,y)!=farbe) {
               return(0);
            }
         }
      }
      return(back);
   }

   xmitt=xmin+1+(rand()%(breit-1));
   ymitt=ymin+1+(rand()%(hoch-1));

   r[0][0]=xmin;
   r[0][1]=ymin;
   r[0][2]=xmitt;
   r[0][3]=ymitt;

   r[1][0]=xmitt+1;
   r[1][1]=ymitt+1;
   r[1][2]=xmax;
   r[1][3]=ymax;

   r[2][0]=xmitt+1;
   r[2][1]=ymin;
   r[2][2]=xmax;
   r[2][3]=ymitt;

   r[3][0]=xmin;
   r[3][1]=ymitt+1;
   r[3][2]=xmitt;
   r[3][3]=ymax;

   start=rand()%4;

   for (i=start+1;i<=3;i++) {
      back=Recheckt(rp,r[i][0],r[i][1],r[i][2],r[i][3],farbe);
      if (back==0) return(back);
   }

   for (i=0;i<=start;i++) {
      back=Recheckt(rp,r[i][0],r[i][1],r[i][2],r[i][3],farbe);
      if (back==0) return(back);
   }

   return(back);
}

/* suche Pixel im Rechteck mit der Farbe und uebergebe Koordinaten */
char ReSearch(struct RastPort *rp,int xmin,int ymin,int xmax,int ymax,int farbe,int *koord)
{
   int breit,hoch;
   int xmitt,ymitt;
   int i,start,x,y;
   int xstart,dx,ystart,dy;
   int r[4][4];
   char back=0;

   breit=xmax-xmin;
   hoch=ymax-ymin;

   if ((breit<80)||(hoch<60)) {
      /* random search */
      if (rand()%2==0) {
         dx=4;
         xstart=xmin;
      }
      else {
         dx=-4;
         xstart=xmax;
      }
      if (rand()%2==0) {
         dy=3;
         ystart=ymin;
      }
      else {
         dy=-3;
         ystart=ymax;
      }
      for (y=ystart;(y>=ymin)&&(y<=ymax);y=y+dy) {
         for (x=xstart;(x>=xmin)&&(x<=xmax);x=x+dx) {
            if (ReadPixel(rp,x,y)==farbe) {
               koord[0]=x;
               koord[1]=y;
               return(1);
            }
         }
      }
      return(back);
   }

   xmitt=xmin+1+(rand()%(breit-1));
   ymitt=ymin+1+(rand()%(hoch-1));

   r[0][0]=xmin;
   r[0][1]=ymin;
   r[0][2]=xmitt;
   r[0][3]=ymitt;

   r[1][0]=xmitt+1;
   r[1][1]=ymitt+1;
   r[1][2]=xmax;
   r[1][3]=ymax;

   r[2][0]=xmitt+1;
   r[2][1]=ymin;
   r[2][2]=xmax;
   r[2][3]=ymitt;

   r[3][0]=xmin;
   r[3][1]=ymitt+1;
   r[3][2]=xmitt;
   r[3][3]=ymax;

   start=rand()%4;

   for (i=start+1;i<=3;i++) {
      back=ReSearch(rp,r[i][0],r[i][1],r[i][2],r[i][3],farbe,koord);
      if (back==1) return(back);
   }

   for (i=0;i<=start;i++) {
      back=ReSearch(rp,r[i][0],r[i][1],r[i][2],r[i][3],farbe,koord);
      if (back==1) return(back);
   }

   return(back);
}

VOID Defaults( PrefObject *Prefs )
{
	Prefs[SQSIZE].po_Level = 12;
	Prefs[BLACKWIN].po_Level = 0;
	Prefs[RESTART].po_Active = 2;
	Prefs[TOPSCR].po_Active = 0;
}

LONG Blank( PrefObject *Prefs )
{
	struct Screen *Scr;
   struct RastPort *RP;
   struct ViewPort *VP;
	struct Window *Wnd;

	LONG RetVal = OK;
   LONG zeit,duration,Colors,black;
	SHORT Width,Height,x,y,color;
   SHORT xmin,xmax,ymin,ymax;
   unsigned int Pixels,count=0;
   int koord[2];
   SHORT sqsize,blackwin;

	sqsize=Prefs[SQSIZE].po_Level;

   duration=999999999;
   if (Prefs[RESTART].po_Active>0) duration=(4-Prefs[RESTART].po_Active)*30*CLK_TCK;

	blackwin=101-Prefs[BLACKWIN].po_Level;
   if (blackwin==101) blackwin=0;
   if (blackwin>90) blackwin=blackwin*2;
   if (blackwin>80) blackwin=blackwin*2;
   if (blackwin>60) blackwin=blackwin*2;

   srand((unsigned)clock());

   /* restart-loop */

   while(1) {

      Scr = cloneTopScreen( FALSE, Prefs[TOPSCR].po_Active );

      if (Scr) {
         Wnd = BlankMousePointer( Scr );

         /* Get all Screen-Information */
         VP=&((*Scr).ViewPort);
         RP=&((*Scr).RastPort);
  	  		Colors = 1L << Scr->RastPort.BitMap->Depth;
         Width=Scr->Width;
         Height=Scr->Height;
         Pixels=Width*Height;

         /* Find the color that fits best to black
            and change this color to real black (>=39)
            Choose color no.1 for OS <39 */
         if (blackwin>0) {
            black=1;
            if (GfxBase->lib_Version>38) {
               black=FindColor(VP->ColorMap,farb(0),farb(0),farb(0),Colors-1);
               if (black<0) black=1;
               if (black>=Colors) black=1;
            }
            SetRGB32(VP,black,farb(0),farb(0),farb(0));
         }

         zeit=clock();
 
         /* main-loop */
         while(1) {

            count++;
            x=rand()%Width;
            y=rand()%Height;

            if ((blackwin>0)&&(count%blackwin==0)) {

               /* Try to find black systematicly */
               /* (recursive ReSearch will do this for us) */

               color=black;
               if (ReSearch(RP,0,0,Width-1,Height-1,color,koord)==1) {
                  x=koord[0];
                  y=koord[1];
               }
            }
            else {
               color=ReadPixel(RP,x,y);
            }
            SetAPen(RP,color);
            xmin=x-sqsize;
            ymin=y-sqsize;
            if (xmin<0) xmin=0;
            if (ymin<0) ymin=0;
            xmax=x+sqsize;
            ymax=y+sqsize;
            if (xmax>=Width) xmax=Width-1;
            if (ymax>=Height) ymax=Height-1;

            /* Draw the square */
            RectFill(RP,xmin,ymin,xmax,ymax);

				if (count%5==0) {

               RetVal = ContinueBlanking();
               if (RetVal!=OK) break;

      			if (count%50==0) {
                  ScreenToFront( Scr );
                  if (clock()>zeit+duration) {

                     zeit=clock();
                     /* whole screen in same color ? */

                     if (blackwin>0) color=black;
                        else color=ReadPixel(RP,0,0);

                     /* four quadrants */

                     RetVal=OK;

                     if (Recheckt(RP,0,0,Width/2,Height/2,color)==1) {
                        RetVal = ContinueBlanking();
                        if (RetVal!=OK) break;
                        if (Recheckt(RP,Width/2+1,0,Width-1,Height/2,color)==1) {
                           RetVal = ContinueBlanking();
                           if (RetVal!=OK) break;
                           if (Recheckt(RP,0,Height/2+1,Width/2,Height-1,color)==1) {
                              RetVal = ContinueBlanking();
                              if (RetVal!=OK) break;
                              if (Recheckt(RP,Width/2+1,Height/2+1,Width-1,Height-1,color)==1) {
                                 RetVal = ContinueBlanking();
                                 if (RetVal!=OK) break;
                                 RetVal = -42;
                                 break;
                              }
                           }
                        }
                     }
                  }
               }
            }
         }

         UnblankMousePointer( Wnd );
         CloseScreen( Scr );
      }
      else RetVal=FAILED;

      if (RetVal!=-42) break;

   }

   return RetVal;
}
