/*

        zug.c    -   Ein Teil von Gambler

        (c) by Guido Appenzeller - Landessternwarte - 6900 Heidelberg

*/

#include "gambler.h"

int    ZX[] = { 0,1,1,1,0,-1,-1,-1 };
int    ZY[] = { -1,-1,0,1,1,1,0,-1 };

extern struct Spielregeln SR;
extern char               Compressed[350];
extern char               BestMove[350];
extern int                CLength;
extern int                Slt[2];
extern int                Spielfeld[50][50];
extern int                Hilfsfeld[50][50];
extern int                EndFlag,WinNr;
extern int                ZaehleReihen();
extern int                ZugNr;

/* --- Der Zuggenerator mit Hilfsroutinen --------------------------- */

MacheZug(St1,SpielerNr)
int St1[50][50];
int SpielerNr;
{
    int x,y,wertung,nw,moves,f,qx,qy,qqx,qqy,z,xx,yy,zz,fl,k,km,k2;
    int Typ;

    ShowText("Mein Zug:");

    moves = 0; qqx=99; qqy=99;
    wertung = -32001;

    km = (SR.Brettbreite>SR.Bretthoehe) ? SR.Brettbreite : SR.Bretthoehe ;

    if( Slt[SpielerNr] > 0 )
     {
      if( ( SR.SteineFlags[SpielerNr] & FALLSETZEN ) > 0 )
       {
        for( x=0; x<SR.Brettbreite; x++)
            {
                y = SR.Bretthoehe - 1;
                while( (St1[x][y] != NULL) && (y>=0) ) y--;
                if( y>=0 )
                    {
                        moves++;
                        f = 0;

                        if( y>0 )
                            {
                                CopyStellung(St1,Hilfsfeld);
                                Hilfsfeld[x][y-1] = 2-SpielerNr;
                                if( Sieg(Hilfsfeld,1-SpielerNr) != NULL )
                                    {
                                        f = 1; nw = -30000;
                                    }
                            }

                        CopyStellung(St1,Hilfsfeld);
                        Hilfsfeld[x][y] = SpielerNr+1;
                        CompressStellung(Hilfsfeld);

                        if( f == NULL ) nw = Bewerte(SpielerNr);

                        if( nw > wertung )
                            {
                                wertung = nw;
                                SaveBest();
                                qx = x; qy = y;
                            }
                    }
            }
       }
      else
       {
        for( x=0; x<SR.Brettbreite; x++)
            for( y=0; y<SR.Bretthoehe; y++)
                if( St1[x][y] == 0 )
                    {
                        moves++;
                        CopyStellung(St1,Hilfsfeld);
                        Hilfsfeld[x][y] = SpielerNr+1;
                        CompressStellung(Hilfsfeld);
                        nw = Bewerte(SpielerNr);
                        if( nw > wertung )
                            {
                                wertung = nw;
                                SaveBest();
                                qx = x; qy = y;
                            }
                    }
       }
     }
   else
     {
       for( x=0; x<SR.Brettbreite; x++)
         for( y=0; y<SR.Bretthoehe; y++)
           if( (St1[x][y] == (SpielerNr+1)) || (St1[x][y] == (SpielerNr+3)) )
             {
               Typ = St1[x][y]-1;
               for(z=0; z<8; z++)
                 if( ( SR.Zugrichtungen[Typ] & (1 << z ) ) > 0 )
                   {

                     if( ( SR.SteineFlags[Typ] & ZIEHEN ) > 0 )
                      if( ( (x+ZX[z])>-1 ) && ( (x+ZX[z])<SR.Brettbreite ) )
                       if( ( (y+ZY[z])>-1 ) && ( (y+ZY[z])<SR.Bretthoehe ) )
                        if( St1[ x+ZX[z] ][ y+ZY[z] ] == NULL )
                         {
                          moves++;
                          CopyStellung(St1,Hilfsfeld);
                          Hilfsfeld[x][y] = NULL;
                          Hilfsfeld[ x+ZX[z] ][ y+ZY[z] ] = Typ+1;
                          CompressStellung(Hilfsfeld);
                          nw = Bewerte(SpielerNr);
                          if( nw > wertung )
                            {
                                wertung = nw;
                                SaveBest();
                                qx = x; qy = y;
                                qqx = x+ZX[z]; qqy = y+ZY[z];
                            }
                         }

                     if( ( SR.SteineFlags[Typ] & SCHLAGEN ) > 0 )
                      if( ( (x+ZX[z])>-1 ) && ( (x+ZX[z])<SR.Brettbreite ) )
                       if( ( (y+ZY[z])>-1 ) && ( (y+ZY[z])<SR.Bretthoehe ) )
                        if( St1[ x+ZX[z] ][ y+ZY[z] ] == (2-SpielerNr) ||
                         St1[ x+ZX[z] ][ y+ZY[z] ] == (4-SpielerNr) )
                         {
                          moves++;
                          CopyStellung(St1,Hilfsfeld);
                          Hilfsfeld[x][y] = NULL;
                          Hilfsfeld[ x+ZX[z] ][ y+ZY[z] ] = Typ+1;
                          CompressStellung(Hilfsfeld);
                          nw = Bewerte(SpielerNr);
                          if( SR.SteineFlags[Typ] & SCHLAGZWANG )
                           nw = (nw>16384) ? (nw) : (nw+16000) ;
                          if( nw > wertung )
                            {
                                wertung = nw;
                                SaveBest();
                                qx = x; qy = y;
                                qqx = x+ZX[z]; qqy = y+ZY[z];
                            }
                         }

                     if( ( SR.SteineFlags[Typ] & SPRINGEN ) > 0 )
                       {
                          if( GenerateJump(St1,SpielerNr,x,y,z) == 1 )
                            {
                                moves++;

                                CompressStellung(Hilfsfeld);

                                nw = Bewerte(SpielerNr);
                                if( SR.SteineFlags[Typ] & SCHLAGZWANG )
                                 if( SR.SteineFlags[Typ] & SPRUNGSCHLAG )
                                  nw = (nw>16384) ? (nw) : (nw+16000) ;

                                if( nw > wertung )
                                    {
                                         wertung = nw;
                                         SaveBest();
                                         qqx = x+2*ZX[z]; qqy = y+2*ZY[z];
                                         qx = x; qy = y;
                                    }
                            }
                       }

                     if( ( SR.SteineFlags[Typ] & WEITSPRUNG) > 0 )
                       {
                         for( k=2; k<km; k++ )
                          if( GenerateFarJump(St1,SpielerNr,x,y,z,k) == 1 )
                            {
                                moves++;

                                CompressStellung(Hilfsfeld);

                                nw = Bewerte(SpielerNr);
                                if( SR.SteineFlags[Typ] & SCHLAGZWANG )
                                 if( SR.SteineFlags[Typ] & SPRUNGSCHLAG )
                                  nw = (nw>16384) ? (nw) : (nw+16000) ;

                                if( nw > wertung )
                                    {
                                         wertung = nw;
                                         SaveBest();
                                         qqx = x+k*ZX[z]; qqy = y+k*ZY[z];
                                         qx = x; qy = y;
                                    }
                            }
                       }

                     if( ( SR.SteineFlags[Typ] & WEITZUG) > 0 )
                       {
                         for( k=2; k<km; k++ )
                          if( GenerateFarStep(St1,SpielerNr,x,y,z,k) == 1 )
                            {
                                moves++;

                                CompressStellung(Hilfsfeld);

                                nw = Bewerte(SpielerNr);

                                if( nw > wertung )
                                    {
                                         wertung = nw;
                                         SaveBest();
                                         qqx = x+k*ZX[z]; qqy = y+k*ZY[z];
                                         qx = x; qy = y;
                                    }
                            }
                       }

                     if( ( SR.SteineFlags[Typ] & MULTISPRUNG ) > 0 )
                      {
                       if( GenerateJump(St1,SpielerNr,x,y,z) == 1 )
                       {
                        xx = x+2*ZX[z]; yy = y+2*ZY[z];

                     do {

                        fl = 0;

                        for( zz=0; zz<8; zz++ )
                         if( ( SR.Zugrichtungen[Typ] & (1 << zz )) > 0)
                          if( GenerateJump(Hilfsfeld,SpielerNr,xx,yy,zz)==1 )
                            {
                                xx = xx+2*ZX[zz]; yy = yy+2*ZY[zz]; fl = 1;
                            }

                        } while ( fl == 1 );

                        CompressStellung(Hilfsfeld);

                        nw = Bewerte(SpielerNr);
                        if( SR.SteineFlags[Typ] & SCHLAGZWANG )
                            if( SR.SteineFlags[Typ] & SPRUNGSCHLAG )
                                nw = (nw>16384) ? (nw) : (nw+16000) ;

                        if( nw > wertung )
                                {
                                         wertung = nw;
                                         SaveBest();
                                         qqx = x+2*ZX[z]; qqy = y+2*ZY[z];
                                         qx = x; qy = y;
                                }
                        }
                       if( ( SR.SteineFlags[Typ] & WEITSPRUNG ) > 0 )
                        {
                         for( k=2; k<km; k++ )
                          if( GenerateFarJump(St1,SpielerNr,x,y,z,k) == 1 )
                           {
                            xx = x+k*ZX[z]; yy = y+k*ZY[z];

                         do {

                              fl = 0;

                              for( zz=0; zz<8; zz++ )
                               for( k2=2; k2<km; k2++ )
                                if( ( SR.Zugrichtungen[Typ] & (1 << zz )) > 0)
                                 if( GenerateFarJump(Hilfsfeld,SpielerNr,xx,yy,zz,k2)==1 )
                                  {
                                    xx = xx+k2*ZX[zz]; yy = yy+k2*ZY[zz]; fl = 1;
                                  }

                            } while ( fl == 1 );

                            CompressStellung(Hilfsfeld);

                            nw = Bewerte(SpielerNr);
                            if( SR.SteineFlags[Typ] & SCHLAGZWANG )
                               if( SR.SteineFlags[Typ] & SPRUNGSCHLAG )
                                   nw = (nw>16384) ? (nw) : (nw+16000) ;

                            if( nw > wertung )
                                    {
                                         wertung = nw;
                                         SaveBest();
                                         qqx = x+2*ZX[z]; qqy = y+2*ZY[z];
                                         qx = x; qy = y;
                                    }
                           }
                        }
                      }

                   }
             }
     }


    if( moves == 0 )
        {
            EndFlag = 1;
            if( ( SR.Siegflags[1-SpielerNr] & S_ANDERERFEST ) > 0 )
                 WinNr = 1-SpielerNr;
            else WinNr = 2;
        }
    else
        {
            if( Slt[SpielerNr] > 0 ) Slt[SpielerNr]--;
            ShowMove(qx,qy);
            if( qqy != 99 ) { AText("-"); ShowMove(qqx,qqy); }
            LoadBest();
            ExpandStellung(St1);
        }

}

int GenerateJump(St1,SpielerNr,x,y,z)
int St1[50][50];
int SpielerNr;
int x,y,z;
{
    int fl,Typ;

    fl = 0;

    if( ( (x+2*ZX[z])>-1 ) && ( (x+2*ZX[z])<SR.Brettbreite ) )
        if( ( (y+2*ZY[z])>-1 ) && ( (y+2*ZY[z])<SR.Bretthoehe ) )
            if( St1[ x+2*ZX[z] ][ y+2*ZY[z] ] == NULL )
                if( St1[ x+ZX[z] ][ y+ZY[z] ] == (2-SpielerNr) ||
                    St1[ x+ZX[z] ][ y+ZY[z] ] == (4-SpielerNr) )
                       {
                          fl = 1;
                          if( St1 != Hilfsfeld ) CopyStellung(St1,Hilfsfeld);
                          Typ = Hilfsfeld[x][y]-1;
                          Hilfsfeld[x][y] = NULL;
                          if( SR.SteineFlags[Typ] & SPRUNGSCHLAG )
                            Hilfsfeld[ x+ZX[z] ][ y+ZY[z] ] = NULL;
                          Hilfsfeld[ x+2*ZX[z] ][ y+2*ZY[z] ] = Typ+1;
                       }

    if( fl == 1 ) return(1);
    else          return(0);

}

int GenerateFarJump(St1,SpielerNr,x,y,z,k)
int St1[50][50];
int SpielerNr;
int x,y,z,k;
{
    int fl,Typ,t,f2,c,q;

    fl = 0;

    if( ( (x+k*ZX[z])>-1 ) && ( (x+k*ZX[z])<SR.Brettbreite ) )
        if( ( (y+k*ZY[z])>-1 ) && ( (y+k*ZY[z])<SR.Bretthoehe ) )
            if( St1[ x+k*ZX[z] ][ y+k*ZY[z] ] == NULL )
              {
                f2 = 0; c = 0;
                for( t=1; t<k; t++ )
                  {
                    q = St1[ x+t*ZX[z] ][ y+t*ZY[z] ]-1;
                    if(  (q == SpielerNr)  || (q == (SpielerNr+2) ) ) f2 = 1;
                    if( (q == 1-SpielerNr) || (q == (3-SpielerNr) ) ) c++;
                  }
                if( c != 1 ) f2 = 1;
                if( f2 == 0 )
                       {
                          fl = 1;
                          if( St1 != Hilfsfeld ) CopyStellung(St1,Hilfsfeld);
                          Typ = Hilfsfeld[x][y]-1;
                          Hilfsfeld[x][y] = NULL;
                          if( SR.SteineFlags[Typ] & SPRUNGSCHLAG )
                              for( t=1; t<k; t++ )
                                  Hilfsfeld[ x+t*ZX[z] ][ y+t*ZY[z] ] = NULL;
                          Hilfsfeld[ x+k*ZX[z] ][ y+k*ZY[z] ] = Typ+1;
                       }
              }

    if( fl == 1 ) return(1);
    else          return(0);

}

int GenerateFarStep(St1,SpielerNr,x,y,z,k)
int St1[50][50];
int SpielerNr;
int x,y,z,k;
{
    int fl,Typ,t,f2;

    fl = 0;

    if( ( (x+k*ZX[z])>-1 ) && ( (x+k*ZX[z])<SR.Brettbreite ) )
        if( ( (y+k*ZY[z])>-1 ) && ( (y+k*ZY[z])<SR.Bretthoehe ) )
            if( St1[ x+k*ZX[z] ][ y+k*ZY[z] ] == NULL )
              {
                f2 = 0;
                for( t=1; t<k; t++ )
                    if( St1[ x+t*ZX[z] ][ y+t*ZY[z] ] != NULL ) f2 = 1;
                if( f2 == 0 )
                       {
                          fl = 1;
                          if( St1 != Hilfsfeld ) CopyStellung(St1,Hilfsfeld);
                          Typ = Hilfsfeld[x][y]-1;
                          Hilfsfeld[x][y] = NULL;
                          Hilfsfeld[ x+k*ZX[z] ][ y+k*ZY[z] ] = Typ+1;
                       }
              }
    if( fl == 1 ) return(1);
    else          return(0);

}



