
/*   AmigaBorders
 *   von Alexander Huber
 *
 *   This was an early C-program and is thus far from perfection!
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <devices/console.h>
#include <stdio.h>

#define rot 3                            /*              */
#define orange 2                         /*  Workbench-  */
#define weiss 1                          /*   farben     */
#define schwarz 0                        /*              */
#define itemflags ITEMTEXT|ITEMENABLED|HIGHCOMP
#define itemcheck itemflags|CHECKIT
#define EOS '\0'
#define MOUSECLICK (!(*mausi & 64))
#define putit(string) ConPutStr(WriteMsg,string)

struct NewWindow newwin =                /* Fenster */
{
    0, 12, 640, 244,
    0, 1,
    MOUSEBUTTONS| CLOSEWINDOW| MENUPICK,
    WINDOWDEPTH| WINDOWCLOSE| WINDOWDRAG|
    ACTIVATE| REPORTMOUSE| NOCAREREFRESH,
    NULL, NULL, NULL, NULL, NULL,
    0, 0, 0, 0,
    WBENCHSCREEN
};

struct NewWindow newone =                /* 2 Fenster */
{
    100, 100, 248, 40, 0, 3, NULL, ACTIVATE| RMBTRAP,
    NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN
};

struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Window *fwind, *Window, *OpenWindow();
struct Library *OpenLibrary();
struct RastPort *rp;
struct Preferences Prefs;
extern struct MsgPort *CreatePort();
extern struct IORequest *CreateExtIO();
extern struct IOStdReq *CreateStdIO();
struct IOStdReq *WriteMsg;
struct MsgPort *consoleWritePort;
struct IOStdReq *ReadMsg;
struct MsgPort *consoleReadPort;
struct IntuiMessage *mess, *GetMsg();

struct IntuiText Texts[]=                /* Alle Menütexte */
{
    {0, 1, JAM2, 5, 5, 0, (UBYTE *)" Wirklich Spielende?", 0},
    {0, 1, JAM2, 7, 3, 0, (UBYTE *)" Ja ", 0},
    {0, 1, JAM2, 7, 3, 0, (UBYTE *)"Nein", 0},
    {3, 1, JAM2, 0, 0, 0, (UBYTE *)"Editor", 0},
    {3, 1, JAM2, 0, 0, 0, (UBYTE *)"Laden", 0},
    {3, 1, JAM2, 0, 0, 0, (UBYTE *)"Speichern", 0},
    {3, 1, JAM2, 0, 0, 0, (UBYTE *)"  1 Sp. gegen Amiga", 0},
    {3, 1, JAM2, 0, 0, 0, (UBYTE *)"  1 Sp. gegen 1 Sp.", 0},
    {3, 1, JAM2, 0, 0, 0, (UBYTE *)"  Amiga gegen Amiga", 0},
    {3, 1, JAM2, 0, 0, 0, (UBYTE *)"Computerzug", 0},
    {3, 1, JAM2, 0, 0, 0, (UBYTE *)"Spielstärke", 0},
    {3, 1, JAM2, 0, 0, 0, (UBYTE *)"  1", 0},
    {3, 1, JAM2, 0, 0, 0, (UBYTE *)"  2", 0},
    {3, 1, JAM2, 0, 0, 0, (UBYTE *)"  3", 0},
    {3, 1, JAM2, 0, 0, 0, (UBYTE *)"  4", 0},
    {3, 1, JAM2, 0, 0, 0, (UBYTE *)"  5", 0}
};

struct MenuItem Menues[]=                /* Alle Menüpunkte */
{
    { &Menues[1], 10, 0, 75, 8, itemflags, 0,
      (APTR)&Texts[3], NULL, 0, NULL, 0 },
    { &Menues[2], 10, 10, 75, 8, itemflags, 0,
      (APTR)&Texts[4], NULL, 0, NULL, 0 },
    { NULL, 10, 20, 75, 8, itemflags, 0,
      (APTR)&Texts[5], NULL, 0, NULL, 0 },
    { &Menues[4], 10, 0, 190, 8, itemcheck|CHECKED, 0xfffe,
      (APTR)&Texts[6], NULL, 0, NULL, 0 },
    { &Menues[5], 10, 10, 190, 8, itemcheck, 0xfffd,
      (APTR)&Texts[7], NULL, 0, NULL, 0 },
    { &Menues[6], 10, 20, 190, 8, itemcheck, 0xfffb,
      (APTR)&Texts[8], NULL, 0, NULL, 0 },
    { &Menues[7], 10, 30, 190, 8, itemflags, 0,
      (APTR)&Texts[9], NULL, 0, NULL, 0 },
    { NULL, 10, 40, 190, 8, itemflags, 0,
      (APTR)&Texts[10], NULL, 0, &Menues[8], 0 },
    { &Menues[9], 155, 8, 35, 8, itemcheck|CHECKED, 0xfffe,
      (APTR)&Texts[11], NULL, 0, NULL, 0 },
    { &Menues[10], 155, 16, 35, 8, itemcheck, 0xfffd,
      (APTR)&Texts[12], NULL, 0, NULL, 0 },
    { &Menues[11], 155, 24, 35, 8, itemcheck, 0xfffb,
      (APTR)&Texts[13], NULL, 0, NULL, 0 },
    { &Menues[12], 155, 32, 35, 8, itemcheck, 0xfff7,
      (APTR)&Texts[14], NULL, 0, NULL, 0 },
    { NULL, 155, 40, 35, 8, itemcheck, 0xffef,
      (APTR)&Texts[15], NULL, 0, NULL, 0 }
};

struct Menu UnserMenue[]=                /* 2 Menüs */
{
    { &UnserMenue[1], 0, 0, 80, 0, MENUENABLED,
      "PROJEKT", &Menues[0] },
    { NULL, 90, 0, 145, 0, MENUENABLED,
      "OPTIONEN", &Menues[3] }
};

BOOL done;
USHORT col0, col1, col2, col3;
char *mausi = 0xbfe001;
char filename[21], rstring[81], wstring[81];
FILE *ausgabe, *eingabe, *fopen();       /* Diskettenverwaltung */
short fliste[33][24][5];                 /* Spielfeldliste */
short cfliste[33][24][5];                /* 1 : 1 Kopie von fliste */
short bliste[2729][4];                   /* Bewertungsliste */
short x=0, y=0, oldx, oldy, ed=0, chosen, finished, keine, zugcomp;
short playmode, spielst, player=3, counter[4], filled=0, p, q;
int oh_no;

float random()
{
    static float zahl = 13.0;

    zahl = (889*((long)(zahl))+23147)%2194647;
    return (zahl/2194647);
}

char *
LEFT (dst, src, n)
char *dst;
char *src;
int n;
{
    register char *dscan;
    register char *sscan;
    register int count;

    dscan = dst;
    sscan = src;
    count = n;
    while (--count >= 0 && (*dscan++ = *sscan++) != EOS) continue;
    *dscan++ = EOS;
    return(dst);
}

afk(a1, a2)                    /* Berechnung der x, y Koordinaten, */
{                              /* jeweils innerhalb der Felder */
    p=a1-1; q=a2-1;
    p*=20; q*=10;
    p+=13; q+=17;
}

afk1(a1, a2)                   /* Berechnung der absoluten Koordinaten */
{
    p=a1-1; q=a2-1;
    p*=20; q*=10;
    p+=10; q+=15;
}

amigamove()                    /* Amiga ist am Zug */
{
    register short l, m, n, j;
    short i=0, k=0, zufall, zufall1, x1, y1, x2, y2, count, step=0;
    float a;

    if (playmode==0 && zugcomp==1) {player=3; goto joho;}
    if ((playmode==2 && player==2) || (zugcomp==1 && playmode==1 && player==2)) {player=3; goto joho;}
    if ((playmode==2 && player==3) || (zugcomp==1 && playmode==1 && player==3)) player=2;
    else player=2;
    joho:
    SetAPen(rp, player);
    SetWindowTitles(Window, "Ich überlege...", -1);
    begin:
    for (l=0; l<33; l++)
    {
        for (m=0; m<24; m++)
        {
            if (fliste[l][m][0]==0) continue;
            k=0; i=0;
            for (n=1; n<5; n++)
            {
                if (fliste[l][m][n]==1) i++;
            }
            if (i==3)                            /* Sorry, but DME has a */
            {                                    /* great copy option! */
                x=l; y=m;
                if (fliste[l][m][1]==0)
                {
                    fliste[l][m][1]=1;
                    fliste[l-1][m][3]=1;
                    fliste[l][m][0]=0;
                    set(1, player);
                    afk(l, m);
                    RectFill(rp, p, q, p+15, q+6);
                    counter[player]++;
                    for (j=1; j<5; j++)
                    {
                        if (fliste[l-1][m][j]==1) k++;
                    }
                    if (k==4)
                    {
                        fliste[l-1][m][0]=0;
                        counter[player]++;
                        afk(l-1, m);
                        RectFill(rp, p, q, p+15, q+6);
                    }
                    goto begin;
                }
                if (fliste[l][m][2]==0)
                {
                    fliste[l][m][2]=1;
                    fliste[l][m-1][4]=1;
                    fliste[l][m][0]=0;
                    set(2, player);
                    afk(l, m);
                    RectFill(rp, p, q, p+15, q+6);
                    counter[player]++;
                    for (j=1; j<5; j++)
                    {
                        if (fliste[l][m-1][j]==1) k++;
                    }
                    if (k==4)
                    {
                        fliste[l][m-1][0]=0;
                        counter[player]++;
                        afk(l, m-1);
                        RectFill(rp, p, q, p+15, q+6);
                    }
                    goto begin;
                }
                if (fliste[l][m][3]==0)
                {
                    fliste[l][m][3]=1;
                    fliste[l+1][m][1]=1;
                    fliste[l][m][0]=0;
                    set(3, player);
                    afk(l, m);
                    RectFill(rp, p, q, p+15, q+6);
                    counter[player]++;
                    for (j=1; j<5; j++)
                    {
                        if (fliste[l+1][m][j]==1) k++;
                    }
                    if (k==4)
                    {
                        fliste[l+1][m][0]=0;
                        counter[player]++;
                        afk(l+1, m);
                        RectFill(rp, p, q, p+15, q+6);
                    }
                    goto begin;
                }
                if (fliste[l][m][4]==0)
                {
                    fliste[l][m][4]=1;
                    fliste[l][m+1][2]=1;
                    fliste[l][m][0]=0;
                    set(4, player);
                    afk(l, m);
                    RectFill(rp, p, q, p+15, q+6);
                    counter[player]++;
                    for (j=1; j<5; j++)
                    {
                        if (fliste[l][m+1][j]==1) k++;
                    }
                    if (k==4)
                    {
                        fliste[l][m+1][0]=0;
                        counter[player]++;
                        afk(l, m+1);
                        RectFill(rp, p, q, p+15, q+6);
                    }
                    goto begin;
                }
            }
            else continue;
        }
    }
    l=checkactiv();
    if (l==0) return;
    i=0;
    for (l=0; l<33; l++)
    {
        for (m=0; m<24; m++)
        {
            if (fliste[l][m][0]==0) continue;
            a=random();
            a=random();
            a=a*4;
            zufall=(int)(a+1);
            for (n=1; n<5; n++)
            {
                if (fliste[l][m][zufall]==0)
                {
                    bliste[i][0]=l;      /* Generiert die Bewertungsliste */
                    bliste[i][1]=m;
                    bliste[i][2]=zufall;
                    bliste[i][3]=800;
                    i++;
                }
            zufall++;
            if (zufall>4) zufall=1;
            }
        }
    }
    a=random();
    a=random();
    a=a*i;
    zufall=(int)(a);
    zufall1=zufall;
    clistencopy();
    if (keine==1) goto here5;
    here:
    l=0; m=0;
    x1=bliste[zufall][0];
    y1=bliste[zufall][1];
    j=1;
    for (k=0; k<2; k++)
    {
    if (bliste[zufall][2]==1)
    {
        x2=x1-1; y2=y1;
        cfliste[x1][y1][1]=j;
        cfliste[x2][y2][3]=j;
    }
    if (bliste[zufall][2]==2)
    {
        x2=x1; y2=y1-1;
        cfliste[x1][y1][2]=j;
        cfliste[x2][y2][4]=j;
    }
    if (bliste[zufall][2]==3)
    {
        x2=x1+1; y2=y1;
        cfliste[x1][y1][3]=j;
        cfliste[x2][y2][1]=j;
    }
    if (bliste[zufall][2]==4)
    {
        x2=x1; y2=y1+1;
        cfliste[x1][y1][4]=j;
        cfliste[x2][y2][2]=j;
    }
    for (n=1; n<5; n++)
    {
        if (cfliste[x1][y1][n]==1) m++;
        if (cfliste[x2][y2][n]==1) l++;
    }
    if (m!=3 && l!=3 && j==1) {zugmachen(zufall); goto here2;}
    j=0;
    }
    zufall++;
    if (zufall==i) zufall=0;
    if (zufall!=zufall1) goto here;
    keine=1;
    here5:
    step=(int)(300/i);
    if (step>5) step=5;         /* Spielstärke */
    step=18-3*spielst-step;
    if (step<1) step=1;
    here1:
    l=0; m=0;
    clistencopy();
    x1=bliste[zufall][0];
    y1=bliste[zufall][1];
    if (bliste[zufall][2]==1)
    {
        x2=x1-1; y2=y1;
        cfliste[x1][y1][1]=1;
        cfliste[x2][y2][3]=1;
    }
    if (bliste[zufall][2]==2)
    {
        x2=x1; y2=y1-1;
        cfliste[x1][y1][2]=1;
        cfliste[x2][y2][4]=1;
    }
    if (bliste[zufall][2]==3)
    {
        x2=x1+1; y2=y1;
        cfliste[x1][y1][3]=1;
        cfliste[x2][y2][1]=1;
    }
    if (bliste[zufall][2]==4)
    {
        x2=x1; y2=y1+1;
        cfliste[x1][y1][4]=1;
        cfliste[x2][y2][2]=1;
    }
    for (n=1; n<5; n++)
    {
        if (cfliste[x1][y1][n]==1) m++;
        if (cfliste[x2][y2][n]==1) l++;
    }
    if (m==3)
    {
        count=routine1(x1, y1);
    }
    else
    {
        count=routine1(x2, y2);
    }
    bliste[zufall][3]=count;
    zufall=zufall+step;
    if (zufall>=i) zufall=0;
    if (zufall<=zufall1-step || zufall>=zufall1+step) goto here1;
    zufall=zufall1;
    count=800;
    for (n=zufall1; n<i; n++)
    {
        if (bliste[n][3]<count)
        {
            count=bliste[n][3];
            k=n;
        }
    }
    for (n=0; n<zufall1; n++)
    {
        if (bliste[n][3]<count)
        {
            count=bliste[n][3];
            k=n;
        }
    }
    zugmachen(k);
    here2:
    SetWindowTitles(Window, "Ich warte...", -1);
    if (playmode==2 && player==3) {player=2; return;}
    if (playmode==2 && player==2) {player=3; return;}
    if (zugcomp==1 && playmode==1 && player==3) {player=2; return;}
    if (zugcomp==1 && playmode==1 && player==2) {player=3; return;}
    player=3;
}

zugmachen(number)             /* Amiga setzt eine Wand */
short number;
{
    short s, t, u, n;

    s=bliste[number][0];
    t=bliste[number][1];
    u=bliste[number][2];
    fliste[s][t][u]=1;
    if (u==1)
    {
        fliste[s-1][t][3]=1;
        x=s; y=t;
        set(1, player);
    }
    if (u==2)
    {
        fliste[s][t-1][4]=1;
        x=s; y=t;
        set(2, player);
    }
    if (u==3)
    {
        fliste[s+1][t][1]=1;
        x=s; y=t;
        set(3, player);
    }
    if (u==4)
    {
        fliste[s][t+1][2]=1;
        x=s; y=t;
        set(4, player);
    }
    for (s=0; s<33; s++)                  /* dummy fliste löschen */
    {
        for (t=0; t<24; t++)
        {
            for (u=0; u<5; u++)
            {
                cfliste[s][t][u]=0;
            }
        }
    }
    for (s=0; s<2729; s++)                /* Bewertungsliste löschen */
    {
        for (t=0; t<4; t++)
        {
            bliste[s][t]=0;
        }
    }
}

routine1(x1, y1)         /* Berechnet die Anzahl der Felder, die der Spieler */
short x1, y1;            /* bei Ausführung dieses Zuges bekommen würde */
{
    register short i;
    short j, k, z1, z2, z3, z4, count1=0;

    z1=x1; z2=y1;
    here:
    if (cfliste[z1][z2][1]==0)
    {
        z3=z1-1; z4=z2;
        cfliste[z1][z2][1]=1;
        cfliste[z3][z4][3]=1;
    }
    if (cfliste[z1][z2][2]==0)
    {
        z3=z1; z4=z2-1;
        cfliste[z1][z2][2]=1;
        cfliste[z3][z4][4]=1;
    }
    if (cfliste[z1][z2][3]==0)
    {
        z3=z1+1; z4=z2;
        cfliste[z1][z2][3]=1;
        cfliste[z3][z4][1]=1;
    }
    if (cfliste[z1][z2][4]==0)
    {
        z3=z1; z4=z2+1;
        cfliste[z1][z2][4]=1;
        cfliste[z3][z4][2]=1;
    }
    cfliste[x1][y1][0]=0;
    j=0;
    count1++;
    for (i=1; i<5; i++)
    {
        if (cfliste[z3][z4][i]==1) j++;
    }
    if (j==3)
    {
        z1=z3; z2=z4;
        goto here;
    }
    if (j==4)
    {
        cfliste[z3][z4][0]=0;
        count1++;
    }
    z1=x1-1; z2=y1;
    j=0;
    for (i=1; i<5; i++)
    {
        if (cfliste[z1][z2][0]==0) break;
        if (cfliste[z1][z2][i]==1) j++;
    }
    if (j==3) goto here;
    z1=x1; z2=y1-1;
    j=0;
    for (i=1; i<5; i++)
    {
        if (cfliste[z1][z2][0]==0) break;
        if (cfliste[z1][z2][i]==1) j++;
    }
    if (j==3) goto here;
    z1=x1+1; z2=y1;
    j=0;
    for (i=1; i<5; i++)
    {
        if (cfliste[z1][z2][0]==0) break;
        if (cfliste[z1][z2][i]==1) j++;
    }
    if (j==3) goto here;
    j=0;
    z1=x1; z2=y1+1;
    for (i=1; i<5; i++)
    {
        if (cfliste[z1][z2][0]==0) break;
        if (cfliste[z1][z2][i]==1) j++;
    }
    if (j==3) goto here;
    return(count1);
}

checkactiv()                    /* Gibt es noch aktive Felder ? */
{
    register short l, m;

    for (l=1; l<32; l++)
    {
        for (m=1; m<23; m++)
        {
            if (fliste[l][m][0]==0) continue;
            return(1);
        }
    }
    return(0);
}

abrechnung()                   /* Wer hat gewonnen ? */
{
    char text[81], what[11], what1[11];

    finished=1;
    keine=0;
    if (playmode==0) {strcpy(what, "Spieler 1"); strcpy(what1, "Amiga");}
    if (playmode==1) {strcpy(what, "Spieler 1"); strcpy(what1, "Spieler 2");}
    if (playmode==2) {strcpy(what, "Amiga 1"); strcpy(what1, "Amiga 2");}
    if (counter[2] < counter[3])
    {
        sprintf(text, "%s gewinnt mit %d Steinen gegenüber %d Steinen von %s!", what, counter[3], counter[2], what1);
        SetWindowTitles(Window, text, -1);
    }
    if (counter[2] > counter[3])
    {
        sprintf(text, "%s gewinnt mit %d Steinen gegenüber %d Steinen von %s!", what1, counter[2], counter[3], what);
        SetWindowTitles(Window, text, -1);
    }
    if (counter[2] == counter[3])
    {
        sprintf(text, "Remis! %s und %s haben jeweils %d Steine!", what, what1, counter[3]);
        SetWindowTitles(Window, text, -1);
    }
    counter[2]=0;
    counter[3]=0;
    player=3;
}

select()                       /* Auswahl des Spielers */
{
    if (chosen==1 && x==oldx && y==oldy)
    {
        chosen=0;
        afk(x, y);
        SetAPen(rp, schwarz);
        RectFill(rp, p, q, p+15, q+6);
        return;
    }
    if (chosen==1)
    {
        if (x==oldx+1 && y==oldy)        /* Zweites Feld rechts daneben */
        {
            if (fliste[x][y][1]==0)
            {
                set(1, player);
                fliste[x][y][1]=1;
                fliste[oldx][y][3]=1;
                done=1;
            }
        }
        if (x==oldx-1 && y==oldy)        /* Zweites Feld links daneben */
        {
            if (fliste[x][y][3]==0)
            {
                set(3, player);
                fliste[x][y][3]=1;
                fliste[oldx][y][1]=1;
                done=1;
            }
        }
        if (x==oldx && y==oldy-1)        /* Zweites Feld darüber */
        {
            if (fliste[x][y][4]==0)
            {
                set(4, player);
                fliste[x][y][4]=1;
                fliste[x][oldy][2]=1;
                done=1;
            }
        }
        if (x==oldx && y==oldy+1)        /* Zweites Feld darunter */
        {
            if (fliste[x][y][2]==0)
            {
                set(2, player);
                fliste[x][y][2]=1;
                fliste[x][oldy][4]=1;
                done=1;
            }
        }
        SetAPen(rp, schwarz);
        afk(oldx, oldy);
        RectFill(rp, p, q, p+15, q+6);
        chosen=0;
        return;
    }
    if (chosen==0)
    {
        chosen=1;
        if (player==3) SetAPen(rp, rot);
        if (player==2) SetAPen(rp, orange);
        afk(x, y);
        RectFill(rp, p+6, q+2, p+9, q+4);
        oldx=x; oldy=y;
    }
}

set(dir, farb)                 /* Malt in Farbe >farb< auf Seite >dir< */
short dir, farb;               /* des Feldes eine Mauer */
{
    int i=0, j=0;

    afk1(x, y);
    SetAPen(rp, farb);
    switch (dir)
    {
        case 1: a:
                Move(rp, p, q);          /* linke Mauer */
                Draw(rp, p, q+10);
                Move(rp, p+1, q);
                Draw(rp, p+1, q+10);
                if ((playmode==0 && player==2 && j<4) || (playmode==2 && j<4) || (zugcomp==1 && j<4))
                {
                    for (i=0; i<13000; i++);         /* Blinken */
                    SetAPen (rp, weiss);             /* Could've been done */
                    j++;                             /* easier. Sorry! */
                    if (j==2 || j==4) SetAPen (rp, farb);
                    goto a;
                }
                break;
        case 2: b:
                Move(rp, p, q);          /* obere Mauer */
                Draw(rp, p+20, q);
                if ((playmode==0 && player==2 && j<4) || (playmode==2 && j<4) || (zugcomp==1 && j<4))
                {
                    for (i=0; i<13000; i++);         /* Blinken */
                    SetAPen (rp, weiss);
                    j++;
                    if (j==2 || j==4) SetAPen (rp, farb);
                    goto b;
                }
                break;
        case 3: c:
                Move(rp, p+20, q);       /* rechte Mauer */
                Draw(rp, p+20, q+10);
                Move(rp, p+21, q);
                Draw(rp, p+21, q+10);
                if ((playmode==0 && player==2 && j<4) || (playmode==2 && j<4) || (zugcomp==1 && j<4))
                {
                    for (i=0; i<13000; i++);         /* Blinken */
                    SetAPen (rp, weiss);
                    j++;
                    if (j==2 || j==4) SetAPen (rp, farb);
                    goto c;
                }
                break;
        case 4: d:
                Move(rp, p, q+10);       /* untere Mauer */
                Draw(rp, p+20, q+10);
                if ((playmode==0 && player==2 && j<4) || (playmode==2 && j<4) || (zugcomp==1 && j<4))
                {
                    for (i=0; i<13000; i++);         /* Blinken */
                    SetAPen (rp, weiss);
                    j++;
                    if (j==2 || j==4) SetAPen (rp, farb);
                    goto d;
                }
                break;
    }
}

bewertung()                      /* Kurs bewerten */
{
    register short i, j, k;
    short v=0;

    ll(1);
    for (i=1; i<32; i++)
    {
        for (j=1; j<23; j++)
        {
            if (fliste[i][j][0]==0) continue;
            if (fliste[i-1][j][0]==1) goto h1;  /* linkes Feld von Gewähltem */
            else
            {
                fliste[i][j][1]=1;
                fliste[i-1][j][3]=1;
            }
            h1:
            if (fliste[i][j-1][0]==1) goto h2;  /* oberes Feld - " - */
            else
            {
                fliste[i][j][2]=1;
                fliste[i][j-1][4]=1;
            }
            h2:
            if (fliste[i+1][j][0]==1) goto h3;  /* rechtes Feld - " - */
            else
            {
                fliste[i][j][3]=1;
                fliste[i+1][j][1]=1;
            }
            h3:
            if (fliste[i][j+1][0]==1) continue; /* unteres Feld - " - */
            else
            {
                fliste[i][j][4]=1;
                fliste[i][j+1][2]=1;
            }
        }
    }
    for (i=1; i<32; i++)
    {
        for (j=1; j<23; j++)
        {
            if (fliste[i][j][0]==0) continue;
            v=0;
            for (k=1; k<5; k++)
            {
                if (fliste[i][j][k]==1) v++;
            }
            if (v>3)
            {             /* Sollen Einzelreihen nicht möglich */
                ll(1);    /* sein, so muß es heißen: if (v>2)  */
                ed=1;
                SetWindowTitles(Window, "Bewertung: Kurs nicht akzeptabel! Keine Einzelfelder!", -1);
                return;
            }
        }
    }
    SetWindowTitles(Window, "Bewertung: Kurs ist in Ordnung!", -1);
    ed=0;
    player=3;
    changegraf();
}

changegraf()                    /* Graphik wie auf Blatt Papier */
{
    register short r, s, i;

    SetAPen(rp, schwarz);
    RectFill(rp, 5, 12, 637, 242);
    SetAPen(rp, weiss);
    for (r=1; r<32; r++)
    {
        for (s=1; s<23; s++)
        {
            if (fliste[r][s][0]==0) continue;
            else
            {
                afk1(r, s);
                Move(rp, p, q);
                for (i=0; i<2; i++)
                {
                    if (fliste[r][s-1][0]==0) SetAPen(rp, rot);
                    Draw(rp, p+20+i, q);
                    SetAPen(rp, weiss);
                    if (fliste[r+1][s][0]==0) SetAPen(rp, rot);
                    Draw(rp, p+20+i, q+10);
                    SetAPen(rp, weiss);
                    if (fliste[r][s+1][0]==0) SetAPen(rp, rot);
                    Draw(rp, p+i, q+10);
                    SetAPen(rp, weiss);
                    if (fliste[r-1][s][0]==0) SetAPen(rp, rot);
                    Draw(rp, p+i, q);
                    SetAPen(rp, weiss);
                }
            }
        }
    }
}

ll(how)                        /* fliste löschen */
int how;
{
    register short l, m, n;

    for (l=0; l<33; l++)
    {
        for (m=0; m<24; m++)
        {
            if (how==1)        /* nur Mauern löschen */
            {
                for (n=1; n<5; n++)
                {
                    fliste[l][m][n]=0;
                }
            }
            if (how==0)        /* komplett löschen */
            {
                for (n=0; n<5; n++)
                {
                    fliste[l][m][n]=0;
                }
            }
        }
    }
}

save()                          /* Kurs sichern */
{
    register short r, s;

    askffilen(0);
    if (strcmp(filename, "x")==0 || strcmp(filename, "X")==0)
    {
        SetWindowTitles(Window, "Abbruch!", -1);
        strcpy(filename, "");
        return;
    }
    strcat(filename, ".kurs");
    if (!(ausgabe=fopen(filename, "w")))
    {
        SetWindowTitles(Window, "Ich kann den Kurs nicht speichern! Achtung: Kurs nicht gespeichert!", -1);
        strcpy(filename, "");
        return;
    }
    SetWindowTitles(Window, "Ich speichere den Kurs... Bitte warten!", -1);
    for (r=0; r<33; r++)
    {
        for (s=0; s<24; s++)
        {
            fprintf(ausgabe, "%d", fliste[r][s][0]);
        }
    }
    fclose(ausgabe);
    strcpy(filename, "");
    SetWindowTitles(Window, "Kurs gespeichert. Alles in Ordnung!", -1);
}

load(ab)                          /* Kurs laden */
short ab;
{
    register short r, s;

    if (ab==1) {strcpy(filename, "welcome"); goto here;} /* This loads WELCOME */
    askffilen(1);
    if (strcmp(filename, "x")==0 || strcmp(filename, "X")==0)
    {
        SetWindowTitles(Window, "Abbruch!", -1);
        strcpy(filename, "");
        return;
    }
    here:
    strcat(filename, ".kurs");
    if (!(eingabe=fopen(filename, "r")))
    {
        SetWindowTitles(Window, "Ich kann den Kurs nicht laden!", -1);
        strcpy(filename, "");
        return;
    }
    SetWindowTitles(Window, "Ich lade den Kurs... Bitte warten!", -1);
    ll(0);
    for (r=0; r<33; r++)
    {
        for (s=0; s<24; s++)
        {
            fscanf(eingabe, "%1h", &fliste[r][s][0]);
        }
    }
    fclose(eingabe);
    strcpy(filename, "");
    bewertung();
}

xytofeld(m, n)                    /* Ermittelt Feld aus Mausposition */
short m, n;
{
    m-=10; n-=15;
    if (m<0 || n<0 || m>619 || n>219) {x=0; y=0; return;}
    m/=20; n/=10;
    x=m+1; y=n+1;
    if (fliste[x][y][0]==0 && ed==0) {x=0; y=0;}
}

start()                           /* Alles öffnen und aufbauen */
{
    if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 0L)))
        finish();
    if (!(GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 0L)))
        finish();
    if (!(Window = (struct Window *) OpenWindow (&newwin)))
        finish();
    rp=Window->RPort;
    GetPrefs(&Prefs, sizeof(struct Preferences));
    col0=Prefs.color0;
    col1=Prefs.color1;
    col2=Prefs.color2;      /* Save original Prefs colours */
    col3=Prefs.color3;
    Prefs.color0=0x000;
    Prefs.color1=0x666;
    Prefs.color2=0xff0;     /* Set new colours */
    Prefs.color3=0xf64;
    SetPrefs(&Prefs, sizeof(struct Preferences), FALSE);
    SetMenuStrip(Window, &UnserMenue);
    spielst=1;
    playmode=0;
}

finish()                          /* Bye, Bye! */
{
    Prefs.color0=col0;
    Prefs.color1=col1;
    Prefs.color2=col2;
    Prefs.color3=col3;
    SetPrefs(&Prefs, sizeof(struct Preferences), FALSE);
    ClearMenuStrip(Window);
    if (Window) CloseWindow(Window);
    if (GfxBase) CloseLibrary(GfxBase);
    if (IntuitionBase) CloseLibrary(IntuitionBase);
    exit(TRUE);
}

setraster()                       /* Gitter malen */
{
    register short i;

    SetAPen(rp, schwarz);
    RectFill(rp, 5, 12, 637, 242);
    SetAPen(rp, weiss);
    for (i=10; i<=630; i+=20)
    {
        Move(rp, i, 15);
        Draw(rp, i, 235);
        Move(rp, i+1, 15);
        Draw(rp, i+1, 235);
    }
    for (i=15; i<=240; i+=10)
    {
        Move(rp, 10, i);
        Draw(rp, 630, i);
    }
}

handlemenue(menu, item, subitem)      /* Menüverwaltung */
int menu, item, subitem;
{
    short i=0;
    register short r, s;

    switch(menu)
        {
        case 0: switch(item)          /* Projekt Menü */
                {
                case 0: if (ed==0)                 /* Editor */
                        {
                            ed=1;
                            setraster();
                            playmode=0;
                            ll(0);
                            counter[2]=0;
                            counter[3]=0;
                            player=3;
                        }
                        else bewertung();
                        break;
                case 1: ed=0;                      /* Laden */
                        playmode=0;
                        counter[2]=0;
                        counter[3]=0;
                        load(0);
                        break;
                case 2: if (ed==1) bewertung();    /* Speichern */
                        if (ed==1) break;
                        save();
                        break;
                }
                break;
        case 1: switch(item)          /* Options Menü */
                {
                case 0: if (ed==1) bewertung();    /* 1 Sp. gegen Amiga */
                        if (ed==1) break;
                        playmode=0;
                        player=3;
                        break;
                case 1: if (ed==1) bewertung();    /* 1 Sp. gegen 1 Sp. */
                        if (ed==1) break;
                        playmode=1;
                        filled=0;
                        break;
                case 2: if (ed==1) bewertung();    /* Amiga gegen Amiga */
                        if (ed==1) break;
                        playmode=2;
                        if ((i=checkactiv())==0) {playmode=0; break;}
                        break;
                case 3: if (ed==1) bewertung();    /* Computerzug */
                        if (ed==1 || (i=checkactiv())==0) break;
                        zugcomp=1;
                        if (playmode==1 && player==3) {player=2; goto ja;}
                        if (playmode==1 && player==2) player=3;
                        ja:
                        amigamove();
                        i=checkactiv();
                        if (i==0) {zugcomp=0; abrechnung(); break;}
                        if (playmode==1) {zugcomp=0; break;}
                        zugcomp=0;
                        amigamove();
                        i=checkactiv();
                        if (i==0) abrechnung();
                        break;
                case 4: switch(subitem)            /* Spielstärke */
                        {
                        case 0: spielst=1;      /* 1 */
                                break;
                        case 1: spielst=2;      /* 2 */
                                break;
                        case 2: spielst=3;      /* 3 */
                                break;
                        case 3: spielst=4;      /* 4 */
                                break;
                        case 4: spielst=5;      /* 5 */
                                break;
                        }
                        break;
                }
                break;
        default:
                break;
        }
}

clistencopy()                   /* Erstellt eine 1 : 1 Kopie von fliste */
{
    register short  l, m, n;

    for (l=0; l<33; l++)
    {
        for (m=0; m<24; m++)
        {
            for (n=0; n<5; n++)
            {
                cfliste[l][m][n]=fliste[l][m][n];
            }
        }
    }
}

main()                           /* Hauptprogramm */
{
    int i;
    long j=0;
    short a=0, b=0, g=0;

    start();
    load(1);                     /* This loads WELCOME */
    SetWindowTitles(Window, "Ich warte...", "AmigaBorders von Alexander Huber");
    while (TRUE)
    {
        zack:
        if (playmode==2 && finished==0)  /* if (Amiga gegen Amiga) */
        {
            if (player==3) {player=2; goto ja1;}
            if (player==2) player=3;
            ja1:
            amigamove();
            if (player==2) {SetWindowTitles(Window, "Ich überlege...", -1); goto ja;}
            for (i=0; i<70000; i++)
            {                            /* CPU, please forgive me!  */
                                         /* No time for a task here! */
                if (MOUSECLICK) {playmode=0; player=3; goto zack;}
            }
            ja:
            g=checkactiv();
            if (g==0) abrechnung();
            if (finished==1) {finished=0; playmode=0; ll(0);}
        }
        else WaitPort (Window->UserPort);
        while (mess = (struct IntuiMessage *) GetMsg (Window->UserPort))
        {
            switch(mess->Class)
            {
                case CLOSEWINDOW:    /* You're just kidding, aren't you? */
                    ReplyMsg (mess); /* You really wanna quit this game?!? */
                    SetWindowTitles(Window, "Ich warte...", -1);
                    if (AutoRequest(Window, &Texts[0], &Texts[1], &Texts[2], NULL, NULL, 195, 60)) finish();
                    break;
                case MOUSEBUTTONS:
                    switch(mess->Code)
                    {
                        case SELECTDOWN:   /* Linker Mausknopf gedrückt */
                        b=mess->MouseY;
                        a=mess->MouseX;
                        ReplyMsg (mess);
                        xytofeld(a, b);
                        if (x==0 && y==0 && chosen==1) select();
                        if (x==0 && y==0) break;
                        if (ed==1)         /* if (Editor) */
                        {
                            afk(x, y);
                            if (fliste[x][y][0]==0)
                            {
                                fliste[x][y][0]=1;
                                SetAPen(rp, weiss);
                                RectFill(rp, p, q, p+15, q+6);
                            }
                            else if (fliste[x][y][0]==1)
                            {
                                fliste[x][y][0]=0;
                                SetAPen(rp, schwarz);
                                RectFill(rp, p, q, p+15, q+6);
                            }
                        }                  /* else */
                        if (ed==1) break;
                        if (fliste[x][y][0]==0) {chosen=0; break; break;}
                        if (done == 0) select();
                        if (done == 0) break;
                        done=0;
                        SetAPen(rp, player);
                        if (fliste[oldx][oldy][1]==1 && fliste[oldx][oldy][2]==1 && fliste[oldx][oldy][3]==1 && fliste[oldx][oldy][4]==1)
                        {
                            afk(oldx, oldy);
                            RectFill(rp, p, q, p+15, q+6);
                            fliste[oldx][oldy][0]=0;
                            counter[player]++;
                            g=checkactiv();
                            if (g==0) abrechnung();
                            filled=1;
                        }
                        if (fliste[x][y][1]==1 && fliste[x][y][2]==1 && fliste[x][y][3]==1 && fliste[x][y][4]==1)
                        {
                            afk(x, y);
                            RectFill(rp, p, q, p+15, q+6);
                            fliste[x][y][0]=0;
                            counter[player]++;
                            g=checkactiv();
                            if (g==0) abrechnung();
                            filled=1;
                        }
                        if (finished==1) {finished=0; filled=0; ll(0); break; break;}
                        if (filled==1) goto here;
                        if (player==2) player=3;
                        else player=2;
                        here:
                        if (playmode==1 && finished==0) {filled=0; break;}
                        if (playmode==0 && finished==0 && filled==1) {filled=0; break;}
                        if (playmode==0 && finished==0 && filled==0) amigamove();
                        g=checkactiv();
                        if (g==0) abrechnung();
                        if (finished==1) {finished=0; ll(0);}
                        break;
                    }
                    break;
                case MENUPICK:        /* Menüaufruf */
                    if (MENUNUM(mess->Code) != MENUNULL)
                        handlemenue(MENUNUM(mess->Code), ITEMNUM(mess->Code), SUBNUM(mess->Code));
                    ReplyMsg (mess);
                    break;
                default:
                    ReplyMsg (mess);
                    break;
            }
        }
    }
}

askffilen(num)            /* Hole den Filenamen */
short num;                /* Diese Eingaberoutine ist zwar ziemlich lang */
{                         /* dafür jedoch universell einsetzbar und */
    int name=0;           /* außerdem idiotensicher! Ich habe sie schon */
                          /* für viele Dinge benutzt, und deshalb einfach */
                          /* auch für dieses Spiel übernommen */

    if (!(fwind = (struct Window *) OpenWindow (&newone))) finish();
    consoleWritePort = CreatePort ("own.conwrite",0L);
    if (consoleWritePort == 0) finish();
    WriteMsg = CreateStdIO (consoleWritePort);
    if (WriteMsg == 0) finish();
    consoleReadPort = CreatePort ("own.conread",0L);
    if (consoleReadPort == 0) finish();
    ReadMsg = CreateStdIO (consoleReadPort);
    if (ReadMsg == 0) finish();
    oh_no = OpenConsole (WriteMsg, ReadMsg, fwind);
    if (oh_no != 0) finish();
    QueueRead (ReadMsg, &rstring);
    putit("\x9b\x30\x20\x70");              /* Switch Cursor off! */
    if (num==0) SetWindowTitles(fwind, "Funktion: Speichern!          ", -1);
    else SetWindowTitles(fwind, "Funktion: Laden!              ", -1);
    putit("\nFilename (x für Ausstieg!): \n");
    putit("\x9b\x20\x70");                  /* Switch Cursor on! */
    do
    {
        again:
        name = askkey();
        if (name!=13 && name!=8 && (name<33 || name>125)) goto again;
        if (name==13 && strlen(filename)==0) goto again;
        else if (name==13) break;
        if (strlen(filename)>=19 && name!=8) goto again;
        if (name==8 && strlen(filename)==0) goto again;
        else if (name==8) {putit("\b \b"); LEFT(filename, filename, strlen(filename)-1); goto again;}
        sprintf(wstring, "%c", name);
        putit(wstring);
        strcat(filename, wstring);
    } while (TRUE);
    CloseDevice(WriteMsg);               /* Alles wieder zumachen */
    CloseWindow(fwind);
    DeleteStdIO(ReadMsg);
    DeletePort(consoleReadPort);
    DeleteStdIO(WriteMsg);
    DeletePort(consoleWritePort);
}

askkey()                  /* Hole Buchstaben von der Tastatur */
{
    int so;
    so=ConGetChar(consoleReadPort, ReadMsg, &rstring);     /* Wait... */
    return(so);
}

OpenConsole(wrequest,rrequest,windi)     /* Need all this for console! */
struct IOStdReq *wrequest;               /* Though quite superfluous */
struct IOStdReq *rrequest;               /* here, I know! */
struct Window *windi;
{
    int no;
    wrequest->io_Data = (APTR) windi;
    wrequest->io_Length = sizeof (*windi);
    no = OpenDevice ("console.device", 0L, wrequest, 0L);
    rrequest->io_Device = wrequest->io_Device;
    rrequest->io_Unit = wrequest->io_Unit;
    return(no);
}

ConPutStr(request,string)
struct IOStdReq *request;
char *string;
{
    request->io_Command = CMD_WRITE;
    request->io_Data = (APTR) string;
    request->io_Length = -1L;
    DoIO (request);
    return(0);
}

ConGetChar(consolePort,request,whereto)
struct MsgPort *consolePort;
struct IOStdReq *request;
char *whereto;
{
    register UBYTE temp;
    while ((GetMsg(consolePort)==NULL)) WaitPort(consolePort);
    temp = *whereto;
    QueueRead(request,whereto);
    return(temp);
}

QueueRead(request,whereto)
struct IOStdReq *request;
char *whereto;
{
    request->io_Command = CMD_READ;
    request->io_Data = (APTR) whereto;
    request->io_Length = 1L;
    SendIO(request);
    return(0);
}


