#include <functions.h>
#include <stdio.h>
#include <clib/amigaguide_protos.h>
#include <intuition/intuition.h>

extern UWORD *SpielKarten[];
extern BYTE UndoStack[][3],PlayStack[][10],Stack[],EndStack[];

extern long CheatLevel,Punkte,UndoCounter,HiOff;
extern BOOL MBFlag,AGFlag,done;

extern struct Window *Wnd;
extern struct RastPort *RastPort;
extern struct Image Image;
extern struct Image ImRah;
extern struct IntuiText Text1;
extern struct EasyStruct EndeReq;
extern struct NewAmigaGuide nag;

struct EasyStruct Help = {sizeof(struct EasyStruct), 0, "Hilfe",
        "Leider kann die Hilfsfunktion nicht aktiviert werden.\n"
        "(AmigaGuide.library (V34) vorhanden?)", "OK"};

void DrawRow(long n);
void FehlerAnz(long nr);
void KartenMischen();

void PrintPunkte(long pkt)
{
  char str[5];

  sprintf(str,"%d",5 - (Stack[0] / 10));
  Text1.IText = (UBYTE *)&str;
  PrintIText(RastPort, &Text1, 71, 20+HiOff);
  Punkte += pkt;
  if(Punkte < 0) Punkte = 0;
  sprintf(str,"%4d",Punkte);
  Text1.IText = (UBYTE *)&str;
  PrintIText(RastPort, &Text1, 80, 45+HiOff);
}

void SetUndo(long w0,long w1,long w2)
{
  UndoStack[UndoCounter][0] = w0;
  UndoStack[UndoCounter][1] = w1;
  UndoStack[UndoCounter++][2] = w2;
  if(UndoCounter == 1) OnMenu(Wnd, 1);
}

void Undo()
{
  long i,MR1,MR2,ML1,count,Card,pkt=0;
  long off1,off2,invisible=0;
  char str[5];

  if(!UndoCounter) return;
  UndoCounter--;
  MR1 = UndoStack[UndoCounter][0];
  MR2 = UndoStack[UndoCounter][1];
  count = UndoStack[UndoCounter][2];
  if(count == -1)       /* kein normaler Zug */
  {
    if(MR1 == -1)       /* Zug vom Talon */
    {
      invisible = 1;
      pkt = -2;
      if(!Stack[0])
      {
        Image.ImageData = SpielKarten[53];
        DrawImage(RastPort, &Image, 10, HiOff);
      }
      for(i=9;i>=0;i--)
      {
        Stack[++Stack[0]] = PlayStack[PlayStack[0][i]--][i];
        DrawRow(i);
        if(PlayStack[PlayStack[0][i]][i] == Stack[Stack[0]]+1) pkt -= 2;
      }
      sprintf(str,"%d",5 - (Stack[0] / 10));
      Text1.IText = (UBYTE *)&str;
      PrintIText(RastPort, &Text1, 71, 20+HiOff);
      PrintPunkte(pkt);
    }
    else                /* Zug auf EndStack */
    {
      pkt = -26;
      if(MR2 < 0)
      {
        invisible = 1;
        PlayStack[PlayStack[0][MR1]][MR1] *= -1;
        MR2 *= -1;
        pkt -= 10;
        if(PlayStack[0][MR1] == 1) pkt -= 15;
      }
      MR2--;
      Card = EndStack[MR2];
      ML1 = PlayStack[0][MR1]+1;
      for(i=ML1;i<ML1+13;i++)
      {
        PlayStack[i][MR1] = Card--;
        PlayStack[0][MR1]++;
      }
      EndStack[MR2] = 0;
      DrawImage(RastPort, &ImRah, MR2*62+134, HiOff);
      DrawRow(MR1);
      PrintPunkte(pkt);
    }
  }
  else                  /* normaler Spielzug */
  {
    pkt = 0;
    off1 = PlayStack[0][MR1];
    if(MR2 < 0)
    {
      invisible = 1;
      MR2 *= -1;
      PlayStack[off1][MR1] *= -1;
      pkt -= 10;
      if(off1 == 1) pkt -= 15;
    }
    MR2--;
    off2 = PlayStack[0][MR2];
    if(PlayStack[off1][MR1] == PlayStack[off2-count+1][MR2]+1) pkt += 2;
    if(PlayStack[off2-count][MR2] == PlayStack[off2-count+1][MR2]+1) pkt -= 2;
    for(i=1;i<=count;i++) PlayStack[off1+i][MR1] = PlayStack[off2-count+i][MR2];
    PlayStack[0][MR1] += count;
    PlayStack[0][MR2] -= count;
    DrawRow(MR2);
    DrawRow(MR1);
    if(pkt) PrintPunkte(pkt);
  }
  if((CheatLevel+invisible) > 1) PrintPunkte((Punkte+1)/2*-1);
  if(!UndoCounter) OffMenu(Wnd, 1);
}

void CheckEnd(long MR1,long ML,long MR2,BOOL dk)
{
  long i;

  MR2 -= 2;

  if(dk)                               /* only for a good Look */
  {
    i=(PlayStack[ML-12][MR1]/13-1)*2;
    MR2 = (EndStack[i]) ? i+1 : i;
  }

  if(EndStack[MR2]) for(i=7;i>=0;i--) if(!EndStack[i]) MR2=i;
  EndStack[MR2] = PlayStack[ML-12][MR1];
  PlayStack[0][MR1] -= 13;
  i=1;
  if(PlayStack[PlayStack[0][MR1]][MR1] < 0)
  {
    PlayStack[PlayStack[0][MR1]][MR1] *= -1;
    i = -1;
    if(PlayStack[0][MR1] == 1) PrintPunkte(51);
    else PrintPunkte(36);
  }
  else PrintPunkte(26);
  DrawRow(MR1);
  Image.ImageData = SpielKarten[EndStack[MR2]];
  DrawImage(RastPort, &Image, MR2*62+134, HiOff);
  SetUndo(MR1,(MR2+1)*i,-1);
  for(i=0;i<8;i++) if(!EndStack[i]) break;
  if(i==8)
    if(EasyRequestArgs(Wnd, &EndeReq, NULL, NULL)) KartenMischen();
    else done = TRUE;
}

long Deal_Row()
{
  long i,pkt=2;

  if(!Stack[0])
  {
    if(HiOff) return(8);
    else return(0);
  }
  for(i=0;i<10;i++) if(!PlayStack[0][i]) return(1);
  for(i=0;i<10;i++)
  {
    if(PlayStack[PlayStack[0][i]][i] == Stack[Stack[0]]+1) pkt += 2;
    PlayStack[++PlayStack[0][i]][i] = Stack[Stack[0]--];
    DrawRow(i);
  }
  if(!Stack[0]) DrawImage(RastPort, &ImRah, 10, HiOff);
  SetUndo(-1,-1,-1);

  PrintPunkte(pkt);
  return(0);
}

long SucheZug(long wert,long farbe)
{
  long i,Card;

  if(wert != 13)
  {
    Card = wert+1+farbe*13;
    for(i=0;i<10;i++) if(PlayStack[PlayStack[0][i]][i] == Card) break;
    if(i != 10) return(i);
    for(i=0;i<10;i++) if(((PlayStack[PlayStack[0][i]][i]-1)%13) == wert) break;
    if(i != 10) return(i);
  }
  for(i=0;i<10;i++) if(!PlayStack[0][i]) break;
  return(i);
}

long Deal_Line(long MR1,long ML1,long MR2,long ML2,BOOL dk)
{
  long i,lastcard,wert,farbe,MLtemp,pkt=0;
  BOOL isRow = FALSE;

  if(ML1<0) return(2);
  if(!PlayStack[0][MR1]) return(3);
  MLtemp   = ML1+1;
  ML1      = PlayStack[0][MR1];
  lastcard = ML1-1;
  wert     = (PlayStack[ML1][MR1]-1)%13;
  farbe    = (PlayStack[ML1][MR1]-1)/13;
  while(lastcard)
  {
    if((wert == (PlayStack[lastcard][MR1]-1)%13 - 1)&&
                    (farbe == (PlayStack[lastcard][MR1]-1)/13))
    {
      wert++;
      lastcard--;
    }
    else break;
  }
  lastcard++;
  if((ML1 - lastcard) == 12) isRow = TRUE;

  if((ML2 == -1)||(isRow && dk))
  {
    if(!isRow) return(4);
    CheckEnd(MR1,ML1,MR2,dk);
    return(0);
  }

  if(!MBFlag)
  {
    if(MLtemp > ML1) MLtemp = ML1;
    if(MLtemp < lastcard) return(6);
    lastcard = MLtemp;
    wert  = (PlayStack[MLtemp][MR1]-1)%13;
    farbe = (PlayStack[MLtemp][MR1]-1)/13;
  }

  if(dk)
  {
    MR2 = SucheZug(wert+1,farbe);
    if(MR2 == 10) return(7);
  }

  ML2=PlayStack[0][MR2];
  if(((PlayStack[ML2][MR2]-1)%13) == 0) return(5);
  if(ML2)
  {
    if((PlayStack[ML2][MR2]-1)%13 != wert+1) return(6);
    if(PlayStack[lastcard][MR1] == (PlayStack[ML2][MR2]-1)) pkt += 2;
  }

  if((PlayStack[lastcard][MR1] == PlayStack[lastcard-1][MR1]-1)&&lastcard>1)
    pkt -= 2;

  i = lastcard;
  while(ML1>=i)
  {
    PlayStack[++ML2][MR2] = PlayStack[i++][MR1];
    PlayStack[0][MR2]++;
    PlayStack[0][MR1]--;
  }

  MLtemp = 1;
  if((PlayStack[lastcard-1][MR1] < 0)&&(lastcard > 1))
  {
    PlayStack[lastcard-1][MR1] *= -1;
    MLtemp = -1;
    pkt += 10;
    if(lastcard == 2) pkt += 15;
  }
  DrawRow(MR1);
  DrawRow(MR2);
  if(pkt) PrintPunkte(pkt);

  SetUndo(MR1,(MR2+1)*MLtemp,ML1-lastcard+1);

  return(0);
}

void MoveCard(long MR1,long ML1,long MR2,long ML2,BOOL dk)
{
  if((MR1 == MR2)&&(!dk)&&(ML2 != -1)) return;
  if((MR1 == 0)&&(ML1 == -1))
  {
    FehlerAnz(Deal_Row());
    return;
  }
  FehlerAnz(Deal_Line(MR1,ML1,MR2,ML2,dk));
}

void Hilfe()
{
  if(AGFlag) CloseAmigaGuide(OpenAmigaGuide(&nag, 0));
  else EasyRequest(Wnd, &Help, NULL, NULL);
} 